summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.browserslistrc16
-rw-r--r--.eslintrc.yml57
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--.gitlab/CODEOWNERS263
-rw-r--r--.gitlab/ci/cng.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml9
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml34
-rw-r--r--.gitlab/ci/notify.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml33
-rw-r--r--.gitlab/ci/releases.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml12
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/verify-lockfile.gitlab-ci.yml11
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml38
-rw-r--r--.gitlab/issue_templates/Actionable Insight.md28
-rw-r--r--.gitlab/issue_templates/Adoption Engineering.md14
-rw-r--r--.gitlab/issue_templates/Basic Proposal.md2
-rw-r--r--.gitlab/issue_templates/Dogfooding.md17
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md3
-rw-r--r--.gitlab/issue_templates/Feature proposal.md6
-rw-r--r--.gitlab/issue_templates/Lean Feature Proposal.md6
-rw-r--r--.gitlab/issue_templates/Query Performance Investigation.md39
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md2
-rw-r--r--.gitlab/issue_templates/actionable_insight.md34
-rw-r--r--.gitlab/merge_request_templates/Change Documentation Location.md4
-rw-r--r--.gitlab/merge_request_templates/Documentation.md8
-rw-r--r--.gitlab/merge_request_templates/New Static Analysis Check.md5
-rw-r--r--.gitpod.yml12
-rw-r--r--.haml-lint_todo.yml2
-rw-r--r--.nvmrc2
-rw-r--r--.rubocop.yml18
-rw-r--r--.rubocop_manual_todo.yml1531
-rw-r--r--.rubocop_todo.yml26
-rw-r--r--.stylelintrc21
-rw-r--r--CHANGELOG.md58
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--Dangerfile9
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_ELASTICSEARCH_INDEXER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile36
-rw-r--r--Gemfile.lock103
-rwxr-xr-xRakefile2
-rw-r--r--app/assets/images/auth_buttons/openid_64.pngbin0 -> 1918 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/create-0.pngbin0 -> 10275 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/create-1.pngbin0 -> 39565 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/create-2.pngbin0 -> 15793 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/gitlab-logo-gray-rgb.pngbin0 -> 42439 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/team-0.pngbin0 -> 42448 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/team-1.pngbin0 -> 62019 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/team-2.pngbin0 -> 54468 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/trial-0.pngbin0 -> 50665 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/trial-1.pngbin0 -> 8676 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/trial-2.pngbin0 -> 47411 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/verify-0.pngbin0 -> 15366 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/verify-1.pngbin0 -> 60722 bytes
-rw-r--r--app/assets/images/mailers/in_product_marketing/verify-2.pngbin0 -> 57506 bytes
-rw-r--r--app/assets/javascripts/actioncable_connection_monitor.js142
-rw-r--r--app/assets/javascripts/actioncable_consumer.js9
-rw-r--r--app/assets/javascripts/activities.js2
-rw-r--r--app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue7
-rw-r--r--app/assets/javascripts/add_context_commits_modal/index.js2
-rw-r--r--app/assets/javascripts/add_context_commits_modal/store/actions.js4
-rw-r--r--app/assets/javascripts/admin/statistics_panel/components/app.vue6
-rw-r--r--app/assets/javascripts/admin/statistics_panel/index.js2
-rw-r--r--app/assets/javascripts/admin/statistics_panel/store/actions.js2
-rw-r--r--app/assets/javascripts/admin/users/components/actions/activate.vue44
-rw-r--r--app/assets/javascripts/admin/users/components/actions/approve.vue21
-rw-r--r--app/assets/javascripts/admin/users/components/actions/block.vue53
-rw-r--r--app/assets/javascripts/admin/users/components/actions/deactivate.vue60
-rw-r--r--app/assets/javascripts/admin/users/components/actions/delete.vue25
-rw-r--r--app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue25
-rw-r--r--app/assets/javascripts/admin/users/components/actions/index.js21
-rw-r--r--app/assets/javascripts/admin/users/components/actions/reject.vue21
-rw-r--r--app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue43
-rw-r--r--app/assets/javascripts/admin/users/components/actions/unblock.vue44
-rw-r--r--app/assets/javascripts/admin/users/components/actions/unlock.vue42
-rw-r--r--app/assets/javascripts/admin/users/components/usage_ping_disabled.vue (renamed from app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue)0
-rw-r--r--app/assets/javascripts/admin/users/components/user_actions.vue119
-rw-r--r--app/assets/javascripts/admin/users/components/user_avatar.vue30
-rw-r--r--app/assets/javascripts/admin/users/components/user_date.vue29
-rw-r--r--app/assets/javascripts/admin/users/components/users_table.vue18
-rw-r--r--app/assets/javascripts/admin/users/constants.js21
-rw-r--r--app/assets/javascripts/admin/users/index.js25
-rw-r--r--app/assets/javascripts/admin/users/tabs.js23
-rw-r--r--app/assets/javascripts/admin/users/utils.js7
-rw-r--r--app/assets/javascripts/alert_management/components/alert_details.vue380
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue18
-rw-r--r--app/assets/javascripts/alert_management/components/alert_sidebar.vue82
-rw-r--r--app/assets/javascripts/alert_management/components/alert_status.vue119
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue41
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue149
-rw-r--r--app/assets/javascripts/alert_management/constants.js31
-rw-r--r--app/assets/javascripts/alert_management/details.js69
-rw-r--r--app/assets/javascripts/alert_management/graphql/mutations/alert_todo_create.mutation.graphql10
-rw-r--r--app/assets/javascripts/alert_management/graphql/queries/details.query.graphql11
-rw-r--r--app/assets/javascripts/alert_management/list.js4
-rw-r--r--app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue187
-rw-r--r--app/assets/javascripts/alerts_service_settings/index.js39
-rw-r--r--app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue77
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue47
-rw-r--r--app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue26
-rw-r--r--app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json112
-rw-r--r--app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json78
-rw-r--r--app/assets/javascripts/alerts_settings/graphql.js2
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql18
-rw-r--r--app/assets/javascripts/alerts_settings/index.js12
-rw-r--r--app/assets/javascripts/alerts_settings/utils/mapping_transformations.js61
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/app.vue6
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/instance_counts.vue6
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue8
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue4
-rw-r--r--app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue4
-rw-r--r--app/assets/javascripts/api.js60
-rw-r--r--app/assets/javascripts/api/user_api.js4
-rw-r--r--app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_application_setting.query.graphql5
-rw-r--r--app/assets/javascripts/artifacts_settings/index.js2
-rw-r--r--app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue57
-rw-r--r--app/assets/javascripts/authentication/mount_2fa.js2
-rw-r--r--app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue6
-rw-r--r--app/assets/javascripts/authentication/u2f/authenticate.js2
-rw-r--r--app/assets/javascripts/authentication/u2f/register.js2
-rw-r--r--app/assets/javascripts/awards_handler.js14
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue6
-rw-r--r--app/assets/javascripts/badges/components/badge_list.vue4
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue2
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue2
-rw-r--r--app/assets/javascripts/badges/store/actions.js2
-rw-r--r--app/assets/javascripts/badges/store/index.js2
-rw-r--r--app/assets/javascripts/badges/store/mutations.js2
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue11
-rw-r--r--app/assets/javascripts/batch_comments/components/drafts_count.vue2
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_dropdown.vue2
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue19
-rw-r--r--app/assets/javascripts/batch_comments/components/publish_button.vue2
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js28
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js4
-rw-r--r--app/assets/javascripts/behaviors/autosize.js12
-rw-r--r--app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js2
-rw-r--r--app/assets/javascripts/behaviors/copy_to_clipboard.js2
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js12
-rw-r--r--app/assets/javascripts/behaviors/index.js38
-rw-r--r--app/assets/javascripts/behaviors/markdown/editor_extensions.js63
-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/inline_html.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/table_header_row.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/text.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_math.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js2
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js2
-rw-r--r--app/assets/javascripts/behaviors/quick_submit.js2
-rw-r--r--app/assets/javascripts/behaviors/secret_values.js2
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/keybindings.js9
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js88
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue525
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js8
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js2
-rw-r--r--app/assets/javascripts/blob/3d_viewer/index.js4
-rw-r--r--app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js2
-rw-r--r--app/assets/javascripts/blob/balsamiq_viewer.js2
-rw-r--r--app/assets/javascripts/blob/blob_file_dropzone.js6
-rw-r--r--app/assets/javascripts/blob/components/blob_header.vue4
-rw-r--r--app/assets/javascripts/blob/components/blob_header_filepath.vue4
-rw-r--r--app/assets/javascripts/blob/components/constants.js2
-rw-r--r--app/assets/javascripts/blob/file_template_mediator.js8
-rw-r--r--app/assets/javascripts/blob/file_template_selector.js2
-rw-r--r--app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js2
-rw-r--r--app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js2
-rw-r--r--app/assets/javascripts/blob/template_selectors/dockerfile_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/gitignore_selector.js2
-rw-r--r--app/assets/javascripts/blob/template_selectors/license_selector.js3
-rw-r--r--app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js2
-rw-r--r--app/assets/javascripts/blob/template_selectors/type_selector.js2
-rw-r--r--app/assets/javascripts/blob/viewer/index.js6
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js6
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js10
-rw-r--r--app/assets/javascripts/boards/boards_util.js14
-rw-r--r--app/assets/javascripts/boards/components/board_add_new_column_trigger.vue21
-rw-r--r--app/assets/javascripts/boards/components/board_assignee_dropdown.vue196
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue7
-rw-r--r--app/assets/javascripts/boards/components/board_card_layout.vue26
-rw-r--r--app/assets/javascripts/boards/components/board_card_layout_deprecated.vue102
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue18
-rw-r--r--app/assets/javascripts/boards/components/board_column_deprecated.vue16
-rw-r--r--app/assets/javascripts/boards/components/board_configuration_options.vue6
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue12
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue26
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue10
-rw-r--r--app/assets/javascripts/boards/components/board_list_deprecated.vue20
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue43
-rw-r--r--app/assets/javascripts/boards/components/board_list_header_deprecated.vue41
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue6
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue_deprecated.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue19
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js67
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue38
-rw-r--r--app/assets/javascripts/boards/components/boards_selector_deprecated.vue357
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue10
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue6
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue4
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/filters.js2
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.vue4
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue4
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue8
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.vue2
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js41
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue2
-rw-r--r--app/assets/javascripts/boards/components/project_select_deprecated.vue4
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue20
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue62
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue8
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue86
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue2
-rw-r--r--app/assets/javascripts/boards/components/toggle_focus.vue52
-rw-r--r--app/assets/javascripts/boards/constants.js20
-rw-r--r--app/assets/javascripts/boards/filtered_search_boards.js8
-rw-r--r--app/assets/javascripts/boards/filters/due_date_filters.js2
-rw-r--r--app/assets/javascripts/boards/graphql/group_milestones.query.graphql17
-rw-r--r--app/assets/javascripts/boards/graphql/project_milestones.query.graphql17
-rw-r--r--app/assets/javascripts/boards/index.js50
-rw-r--r--app/assets/javascripts/boards/models/issue.js6
-rw-r--r--app/assets/javascripts/boards/models/iteration.js9
-rw-r--r--app/assets/javascripts/boards/models/list.js11
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js20
-rw-r--r--app/assets/javascripts/boards/stores/actions.js105
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js22
-rw-r--r--app/assets/javascripts/boards/stores/getters.js10
-rw-r--r--app/assets/javascripts/boards/stores/index.js4
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js7
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js34
-rw-r--r--app/assets/javascripts/boards/stores/state.js4
-rw-r--r--app/assets/javascripts/boards/toggle_focus.js48
-rw-r--r--app/assets/javascripts/branches/components/divergence_graph.vue2
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js2
-rw-r--r--app/assets/javascripts/build_artifacts.js4
-rw-r--r--app/assets/javascripts/captcha/captcha_modal.vue110
-rw-r--r--app/assets/javascripts/captcha/init_recaptcha_script.js48
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint.vue2
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue2
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/index.js2
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js4
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue4
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue4
-rw-r--r--app/assets/javascripts/ci_variable_list/index.js2
-rw-r--r--app/assets/javascripts/ci_variable_list/store/actions.js4
-rw-r--r--app/assets/javascripts/ci_variable_list/store/mutations.js2
-rw-r--r--app/assets/javascripts/clone_panel.js5
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js16
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue5
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue22
-rw-r--r--app/assets/javascripts/clusters/components/fluentd_output_settings.vue2
-rw-r--r--app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue6
-rw-r--r--app/assets/javascripts/clusters/components/knative_domain_editor.vue4
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue88
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js2
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue6
-rw-r--r--app/assets/javascripts/clusters_list/store/actions.js8
-rw-r--r--app/assets/javascripts/clusters_list/store/index.js4
-rw-r--r--app/assets/javascripts/code_navigation/components/app.vue2
-rw-r--r--app/assets/javascripts/code_navigation/index.js2
-rw-r--r--app/assets/javascripts/code_navigation/store/actions.js2
-rw-r--r--app/assets/javascripts/code_navigation/store/index.js2
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js28
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue19
-rw-r--r--app/assets/javascripts/commits.js2
-rw-r--r--app/assets/javascripts/compare_autocomplete.js8
-rw-r--r--app/assets/javascripts/confidential_merge_request/components/project_form_group.vue4
-rw-r--r--app/assets/javascripts/contextual_sidebar.js4
-rw-r--r--app/assets/javascripts/contributors/components/contributors.vue10
-rw-r--r--app/assets/javascripts/contributors/stores/index.js6
-rw-r--r--app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue8
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue2
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue4
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue14
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js2
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/actions.js8
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/index.js10
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js4
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue2
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/index.js7
-rw-r--r--app/assets/javascripts/create_cluster/gke_cluster/store/actions.js2
-rw-r--r--app/assets/javascripts/create_cluster/init_create_cluster.js2
-rw-r--r--app/assets/javascripts/create_cluster/store/cluster_dropdown/index.js2
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js10
-rw-r--r--app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue4
-rw-r--r--app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue6
-rw-r--r--app/assets/javascripts/cycle_analytics/components/banner.vue2
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js12
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_store.js2
-rw-r--r--app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue4
-rw-r--r--app/assets/javascripts/deploy_freeze/components/deploy_freeze_settings.vue2
-rw-r--r--app/assets/javascripts/deploy_freeze/store/actions.js2
-rw-r--r--app/assets/javascripts/deploy_keys/components/app.vue2
-rw-r--r--app/assets/javascripts/deploy_keys/components/key.vue4
-rw-r--r--app/assets/javascripts/deploy_keys/components/keys_panel.vue2
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js11
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js2
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue12
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue10
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_presentation.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue10
-rw-r--r--app/assets/javascripts/design_management/components/design_todo_button.vue4
-rw-r--r--app/assets/javascripts/design_management/components/image.vue2
-rw-r--r--app/assets/javascripts/design_management/components/list/item.vue23
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/index.vue4
-rw-r--r--app/assets/javascripts/design_management/graphql.js10
-rw-r--r--app/assets/javascripts/design_management/index.js2
-rw-r--r--app/assets/javascripts/design_management/mixins/all_designs.js2
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue24
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue47
-rw-r--r--app/assets/javascripts/design_management/router/routes.js2
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js2
-rw-r--r--app/assets/javascripts/design_management/utils/error_messages.js8
-rw-r--r--app/assets/javascripts/design_management/utils/tracking.js2
-rw-r--r--app/assets/javascripts/diff.js6
-rw-r--r--app/assets/javascripts/diffs/components/app.vue50
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue12
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue12
-rw-r--r--app/assets/javascripts/diffs/components/diff_comment_cell.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue24
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussion_reply.vue11
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue65
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue77
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_row.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue20
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue23
-rw-r--r--app/assets/javascripts/diffs/components/diff_row_utils.js4
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue28
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue4
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue2
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue8
-rw-r--r--app/assets/javascripts/diffs/components/no_changes.vue2
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue4
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue6
-rw-r--r--app/assets/javascripts/diffs/components/settings_dropdown.vue4
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue2
-rw-r--r--app/assets/javascripts/diffs/i18n.js7
-rw-r--r--app/assets/javascripts/diffs/index.js7
-rw-r--r--app/assets/javascripts/diffs/store/actions.js46
-rw-r--r--app/assets/javascripts/diffs/store/getters.js19
-rw-r--r--app/assets/javascripts/diffs/store/getters_versions_dropdowns.js2
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js19
-rw-r--r--app/assets/javascripts/diffs/store/utils.js2
-rw-r--r--app/assets/javascripts/diffs/utils/diff_file.js6
-rw-r--r--app/assets/javascripts/diffs/utils/file_reviews.js25
-rw-r--r--app/assets/javascripts/diffs/utils/performance.js2
-rw-r--r--app/assets/javascripts/diffs/utils/suggestions.js28
-rw-r--r--app/assets/javascripts/diffs/utils/uuids.js2
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_form.js2
-rw-r--r--app/assets/javascripts/droplab/drop_down.js2
-rw-r--r--app/assets/javascripts/droplab/drop_lab.js4
-rw-r--r--app/assets/javascripts/dropzone_input.js10
-rw-r--r--app/assets/javascripts/due_date_select.js6
-rw-r--r--app/assets/javascripts/editor/constants.js5
-rw-r--r--app/assets/javascripts/editor/editor_lite.js221
-rw-r--r--app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js2
-rw-r--r--app/assets/javascripts/emoji/index.js256
-rw-r--r--app/assets/javascripts/environments/components/canary_ingress.vue2
-rw-r--r--app/assets/javascripts/environments/components/canary_update_modal.vue2
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue2
-rw-r--r--app/assets/javascripts/environments/components/container.vue29
-rw-r--r--app/assets/javascripts/environments/components/deploy_board.vue11
-rw-r--r--app/assets/javascripts/environments/components/enable_review_app_modal.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_delete.vue5
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue16
-rw-r--r--app/assets/javascripts/environments/components/environment_monitoring.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.vue3
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue38
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue25
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue2
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js4
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue26
-rw-r--r--app/assets/javascripts/environments/index.js6
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js14
-rw-r--r--app/assets/javascripts/environments/mixins/environments_pagination_api_mixin.js66
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js2
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue12
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue12
-rw-r--r--app/assets/javascripts/error_tracking/details.js4
-rw-r--r--app/assets/javascripts/error_tracking/list.js2
-rw-r--r--app/assets/javascripts/error_tracking/store/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking/store/details/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking/store/index.js10
-rw-r--r--app/assets/javascripts/error_tracking/store/list/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking/store/list/mutations.js4
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/app.vue4
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue2
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/actions.js4
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/index.js2
-rw-r--r--app/assets/javascripts/error_tracking_settings/store/mutations.js2
-rw-r--r--app/assets/javascripts/feature_flags/components/edit_feature_flag.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/environments_dropdown.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags.vue19
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags_tab.vue64
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags_table.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue35
-rw-r--r--app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/new_feature_flag.vue13
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy.vue4
-rw-r--r--app/assets/javascripts/feature_flags/components/strategy_parameters.vue2
-rw-r--r--app/assets/javascripts/feature_flags/edit.js2
-rw-r--r--app/assets/javascripts/feature_flags/new.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/actions.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/index.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/edit/mutations.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js4
-rw-r--r--app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/index/actions.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/index/index.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/index/mutations.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/new/actions.js2
-rw-r--r--app/assets/javascripts/feature_flags/store/new/index.js2
-rw-r--r--app/assets/javascripts/feature_highlight/constants.js1
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight.js59
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_helper.js28
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_options.js12
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_popover.vue101
-rw-r--r--app/assets/javascripts/feature_highlight/index.js28
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js10
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_ajax_filter.js6
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js6
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js4
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js6
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_operator.js2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_utils.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js4
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js26
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js2
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js2
-rw-r--r--app/assets/javascripts/filtered_search/recent_searches_root.js19
-rw-r--r--app/assets/javascripts/filtered_search/recent_searches_storage_keys.js2
-rw-r--r--app/assets/javascripts/filtered_search/services/recent_searches_service.js2
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js6
-rw-r--r--app/assets/javascripts/frequent_items/components/app.vue6
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list.vue2
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue2
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue22
-rw-r--r--app/assets/javascripts/frequent_items/index.js2
-rw-r--r--app/assets/javascripts/frequent_items/store/actions.js4
-rw-r--r--app/assets/javascripts/frequent_items/utils.js2
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js145
-rw-r--r--app/assets/javascripts/gl_form.js4
-rw-r--r--app/assets/javascripts/gpg_badges.js4
-rw-r--r--app/assets/javascripts/grafana_integration/components/grafana_integration.vue4
-rw-r--r--app/assets/javascripts/grafana_integration/index.js2
-rw-r--r--app/assets/javascripts/grafana_integration/store/actions.js4
-rw-r--r--app/assets/javascripts/grafana_integration/store/index.js2
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql2
-rw-r--r--app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql17
-rw-r--r--app/assets/javascripts/graphql_shared/mutations/update_alert_status.mutation.graphql17
-rw-r--r--app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql2
-rw-r--r--app/assets/javascripts/group.js4
-rw-r--r--app/assets/javascripts/group_label_subscription.js4
-rw-r--r--app/assets/javascripts/group_settings/components/shared_runners_form.vue2
-rw-r--r--app/assets/javascripts/groups/components/app.vue6
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue20
-rw-r--r--app/assets/javascripts/groups/components/groups.vue2
-rw-r--r--app/assets/javascripts/groups/components/invite_members_banner.vue2
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue2
-rw-r--r--app/assets/javascripts/groups/groups_filterable_list.js2
-rw-r--r--app/assets/javascripts/groups/index.js14
-rw-r--r--app/assets/javascripts/groups/members/components/app.vue40
-rw-r--r--app/assets/javascripts/groups/members/constants.js4
-rw-r--r--app/assets/javascripts/groups/members/index.js43
-rw-r--r--app/assets/javascripts/groups/members/utils.js47
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js2
-rw-r--r--app/assets/javascripts/groups_select.js4
-rw-r--r--app/assets/javascripts/header.js8
-rw-r--r--app/assets/javascripts/helpers/avatar_helper.js2
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue10
-rw-r--r--app/assets/javascripts/ide/components/branches/search_list.vue4
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue17
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue4
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue93
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue10
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue2
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue2
-rw-r--r--app/assets/javascripts/ide/components/file_row_extra.vue4
-rw-r--r--app/assets/javascripts/ide/components/file_templates/dropdown.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue20
-rw-r--r--app/assets/javascripts/ide/components/ide_review.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue8
-rw-r--r--app/assets/javascripts/ide/components/ide_sidebar_nav.vue5
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue6
-rw-r--r--app/assets/javascripts/ide/components/ide_status_list.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue6
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue4
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue6
-rw-r--r--app/assets/javascripts/ide/components/jobs/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue6
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown.vue2
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown_button.vue2
-rw-r--r--app/assets/javascripts/ide/components/nav_form.vue2
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue7
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue2
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue2
-rw-r--r--app/assets/javascripts/ide/components/panes/right.vue6
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue9
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue12
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue3
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue18
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue4
-rw-r--r--app/assets/javascripts/ide/components/terminal/session.vue4
-rw-r--r--app/assets/javascripts/ide/components/terminal/terminal.vue4
-rw-r--r--app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue2
-rw-r--r--app/assets/javascripts/ide/constants.js11
-rw-r--r--app/assets/javascripts/ide/ide_router.js4
-rw-r--r--app/assets/javascripts/ide/index.js10
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js4
-rw-r--r--app/assets/javascripts/ide/lib/create_diff.js2
-rw-r--r--app/assets/javascripts/ide/lib/diff/controller.js4
-rw-r--r--app/assets/javascripts/ide/lib/editor.js12
-rw-r--r--app/assets/javascripts/ide/lib/errors.js4
-rw-r--r--app/assets/javascripts/ide/lib/languages/index.js2
-rw-r--r--app/assets/javascripts/ide/lib/mirror.js2
-rw-r--r--app/assets/javascripts/ide/lib/themes/index.js6
-rw-r--r--app/assets/javascripts/ide/services/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/actions.js14
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js8
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js150
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js2
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js4
-rw-r--r--app/assets/javascripts/ide/stores/getters.js9
-rw-r--r--app/assets/javascripts/ide/stores/index.js16
-rw-r--r--app/assets/javascripts/ide/stores/modules/branches/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/branches/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js18
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/constants.js9
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/getters.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/index.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/editor/setup.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/index.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/router/index.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/messages.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal_sync/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js6
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js4
-rw-r--r--app/assets/javascripts/ide/stores/plugins/terminal_sync.js4
-rw-r--r--app/assets/javascripts/ide/stores/utils.js2
-rw-r--r--app/assets/javascripts/ide/utils.js4
-rw-r--r--app/assets/javascripts/image_diff/helpers/init_image_diff.js2
-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/import_entities/import_groups/components/import_table.vue212
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js61
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql14
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js10
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js85
-rw-r--r--app/assets/javascripts/import_entities/import_groups/index.js17
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue36
-rw-r--r--app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue61
-rw-r--r--app/assets/javascripts/import_entities/import_projects/index.js2
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/actions.js12
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/index.js2
-rw-r--r--app/assets/javascripts/import_entities/import_projects/store/mutations.js2
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue20
-rw-r--r--app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue4
-rw-r--r--app/assets/javascripts/incidents_settings/incidents_settings_service.js2
-rw-r--r--app/assets/javascripts/init_changes_dropdown.js2
-rw-r--r--app/assets/javascripts/init_issuable_sidebar.js8
-rw-r--r--app/assets/javascripts/init_labels.js2
-rw-r--r--app/assets/javascripts/integrations/edit/components/active_checkbox.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/components/confirmation_modal.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue6
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue183
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue41
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/components/override_dropdown.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue2
-rw-r--r--app/assets/javascripts/integrations/edit/components/trigger_fields.vue4
-rw-r--r--app/assets/javascripts/integrations/edit/index.js22
-rw-r--r--app/assets/javascripts/integrations/edit/store/actions.js15
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutation_types.js4
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutations.js9
-rw-r--r--app/assets/javascripts/integrations/edit/store/state.js3
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js55
-rw-r--r--app/assets/javascripts/invite_member/components/invite_member_modal.vue5
-rw-r--r--app/assets/javascripts/invite_member/components/invite_member_trigger.vue2
-rw-r--r--app/assets/javascripts/invite_member/init_invite_member_modal.js2
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue9
-rw-r--r--app/assets/javascripts/invite_members/components/members_token_select.vue4
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js4
-rw-r--r--app/assets/javascripts/issuable/components/issuable_by_email.vue169
-rw-r--r--app/assets/javascripts/issuable/init_issuable_by_email.js35
-rw-r--r--app/assets/javascripts/issuable_bulk_update_actions.js3
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar.js16
-rw-r--r--app/assets/javascripts/issuable_context.js4
-rw-r--r--app/assets/javascripts/issuable_create/components/issuable_form.vue3
-rw-r--r--app/assets/javascripts/issuable_form.js6
-rw-r--r--app/assets/javascripts/issuable_index.js28
-rw-r--r--app/assets/javascripts/issuable_init_bulk_update_sidebar.js2
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue34
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue9
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_tabs.vue7
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_body.vue2
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_description.vue2
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_edit_form.vue2
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_header.vue12
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_show_root.vue2
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_title.vue2
-rw-r--r--app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue2
-rw-r--r--app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql1
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/app.vue2
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/item.vue4
-rw-r--r--app/assets/javascripts/issuable_suggestions/index.js2
-rw-r--r--app/assets/javascripts/issue.js6
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue15
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue8
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue4
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue10
-rw-r--r--app/assets/javascripts/issue_show/components/fields/title.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/form.vue15
-rw-r--r--app/assets/javascripts/issue_show/components/header_actions.vue6
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue8
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue2
-rw-r--r--app/assets/javascripts/issue_show/incident.js2
-rw-r--r--app/assets/javascripts/issue_show/issue.js1
-rw-r--r--app/assets/javascripts/issue_show/utils/parse_data.js2
-rw-r--r--app/assets/javascripts/issue_status_select.js2
-rw-r--r--app/assets/javascripts/issues_list/components/issuable.vue13
-rw-r--r--app/assets/javascripts/issues_list/components/issuables_list_app.vue18
-rw-r--r--app/assets/javascripts/issues_list/components/jira_issues_list_root.vue4
-rw-r--r--app/assets/javascripts/issues_list/index.js2
-rw-r--r--app/assets/javascripts/jira_connect/api.js20
-rw-r--r--app/assets/javascripts/jira_connect/components/app.vue66
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list.vue74
-rw-r--r--app/assets/javascripts/jira_connect/components/groups_list_item.vue47
-rw-r--r--app/assets/javascripts/jira_connect/index.js97
-rw-r--r--app/assets/javascripts/jira_connect/store/index.js5
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_form.vue27
-rw-r--r--app/assets/javascripts/jira_import/queries/search_project_members.query.graphql13
-rw-r--r--app/assets/javascripts/jobs/components/artifacts_block.vue29
-rw-r--r--app/assets/javascripts/jobs/components/empty_state.vue2
-rw-r--r--app/assets/javascripts/jobs/components/environments_block.vue6
-rw-r--r--app/assets/javascripts/jobs/components/erased_block.vue20
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue29
-rw-r--r--app/assets/javascripts/jobs/components/job_container_item.vue4
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue4
-rw-r--r--app/assets/javascripts/jobs/components/log/duration_badge.vue9
-rw-r--r--app/assets/javascripts/jobs/components/log/line_header.vue2
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue2
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue29
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_detail_row.vue14
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_job_details_container.vue24
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue2
-rw-r--r--app/assets/javascripts/jobs/components/stuck_block.vue2
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue55
-rw-r--r--app/assets/javascripts/jobs/index.js2
-rw-r--r--app/assets/javascripts/jobs/store/actions.js10
-rw-r--r--app/assets/javascripts/jobs/store/getters.js10
-rw-r--r--app/assets/javascripts/jobs/store/index.js2
-rw-r--r--app/assets/javascripts/label_manager.js9
-rw-r--r--app/assets/javascripts/labels_select.js14
-rw-r--r--app/assets/javascripts/lib/graphql.js23
-rw-r--r--app/assets/javascripts/lib/utils/array_utility.js20
-rw-r--r--app/assets/javascripts/lib/utils/axios_utils.js2
-rw-r--r--app/assets/javascripts/lib/utils/color_utils.js20
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js16
-rw-r--r--app/assets/javascripts/lib/utils/constants.js6
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js157
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js2
-rw-r--r--app/assets/javascripts/lib/utils/poll.js2
-rw-r--r--app/assets/javascripts/lib/utils/poll_until_complete.js2
-rw-r--r--app/assets/javascripts/lib/utils/sticky.js12
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js2
-rw-r--r--app/assets/javascripts/lib/utils/unit_format/formatter_factory.js3
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js58
-rw-r--r--app/assets/javascripts/lib/utils/webpack.js5
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue15
-rw-r--r--app/assets/javascripts/logs/components/log_advanced_filters.vue2
-rw-r--r--app/assets/javascripts/logs/components/log_simple_filters.vue4
-rw-r--r--app/assets/javascripts/logs/stores/actions.js4
-rw-r--r--app/assets/javascripts/logs/stores/mutations.js2
-rw-r--r--app/assets/javascripts/logs/stores/state.js2
-rw-r--r--app/assets/javascripts/main.js25
-rw-r--r--app/assets/javascripts/manual_ordering.js4
-rw-r--r--app/assets/javascripts/members.js4
-rw-r--r--app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue4
-rw-r--r--app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/leave_button.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue3
-rw-r--r--app/assets/javascripts/members/components/action_buttons/remove_member_button.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue4
-rw-r--r--app/assets/javascripts/members/components/app.vue40
-rw-r--r--app/assets/javascripts/members/components/avatars/user_avatar.vue7
-rw-r--r--app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue2
-rw-r--r--app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue6
-rw-r--r--app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue4
-rw-r--r--app/assets/javascripts/members/components/modals/leave_modal.vue2
-rw-r--r--app/assets/javascripts/members/components/modals/remove_group_link_modal.vue3
-rw-r--r--app/assets/javascripts/members/components/table/member_action_buttons.vue6
-rw-r--r--app/assets/javascripts/members/components/table/member_avatar.vue4
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue20
-rw-r--r--app/assets/javascripts/members/components/table/members_table_cell.vue8
-rw-r--r--app/assets/javascripts/members/constants.js5
-rw-r--r--app/assets/javascripts/members/index.js43
-rw-r--r--app/assets/javascripts/members/store/actions.js6
-rw-r--r--app/assets/javascripts/members/store/index.js4
-rw-r--r--app/assets/javascripts/members/store/mutations.js18
-rw-r--r--app/assets/javascripts/members/utils.js62
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.js11
-rw-r--r--app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js5
-rw-r--r--app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js3
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_store.js2
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js8
-rw-r--r--app/assets/javascripts/merge_request.js8
-rw-r--r--app/assets/javascripts/merge_request/components/status_box.vue6
-rw-r--r--app/assets/javascripts/merge_request_tabs.js76
-rw-r--r--app/assets/javascripts/milestone.js4
-rw-r--r--app/assets/javascripts/milestone_select.js29
-rw-r--r--app/assets/javascripts/milestones/components/milestone_results_section.vue7
-rw-r--r--app/assets/javascripts/mirrors/mirror_repos.js4
-rw-r--r--app/assets/javascripts/mirrors/ssh_mirror.js4
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget.vue11
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget_form.vue8
-rw-r--r--app/assets/javascripts/monitoring/components/charts/anomaly.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/column.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/gauge.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/heatmap.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/options.js2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/single_stat.vue16
-rw-r--r--app/assets/javascripts/monitoring/components/charts/stacked_column.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue12
-rw-r--r--app/assets/javascripts/monitoring/components/create_dashboard_modal.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue31
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue10
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_header.vue15
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue28
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboards_dropdown.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/embed_group.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/metric_embed.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/links_section.vue6
-rw-r--r--app/assets/javascripts/monitoring/components/refresh_button.vue4
-rw-r--r--app/assets/javascripts/monitoring/components/variables_section.vue4
-rw-r--r--app/assets/javascripts/monitoring/constants.js2
-rw-r--r--app/assets/javascripts/monitoring/monitoring_app.js23
-rw-r--r--app/assets/javascripts/monitoring/pages/panel_new_page.vue4
-rw-r--r--app/assets/javascripts/monitoring/requests/index.js2
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js24
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js8
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js4
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js8
-rw-r--r--app/assets/javascripts/monitoring/stores/variable_mapping.js2
-rw-r--r--app/assets/javascripts/monitoring/utils.js12
-rw-r--r--app/assets/javascripts/mr_notes/index.js13
-rw-r--r--app/assets/javascripts/mr_notes/init_notes.js4
-rw-r--r--app/assets/javascripts/mr_notes/stores/index.js2
-rw-r--r--app/assets/javascripts/mr_popover/components/mr_popover.vue2
-rw-r--r--app/assets/javascripts/mr_popover/index.js2
-rw-r--r--app/assets/javascripts/namespace_select.js4
-rw-r--r--app/assets/javascripts/namespaces/leave_by_url.js4
-rw-r--r--app/assets/javascripts/network/branch_graph.js2
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue2
-rw-r--r--app/assets/javascripts/notes.js33
-rw-r--r--app/assets/javascripts/notes/components/comment_field_layout.vue2
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue90
-rw-r--r--app/assets/javascripts/notes/components/diff_discussion_header.vue6
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue4
-rw-r--r--app/assets/javascripts/notes/components/discussion_actions.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_navigator.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue14
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue11
-rw-r--r--app/assets/javascripts/notes/components/email_participants_warning.vue2
-rw-r--r--app/assets/javascripts/notes/components/multiline_comment_form.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue117
-rw-r--r--app/assets/javascripts/notes/components/note_actions/reply_button.vue29
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue38
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue91
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue30
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue63
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue24
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue47
-rw-r--r--app/assets/javascripts/notes/components/sort_discussion.vue2
-rw-r--r--app/assets/javascripts/notes/components/timeline_toggle.vue2
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue25
-rw-r--r--app/assets/javascripts/notes/index.js2
-rw-r--r--app/assets/javascripts/notes/mixins/autosave.js2
-rw-r--r--app/assets/javascripts/notes/mixins/diff_line_note_form.js2
-rw-r--r--app/assets/javascripts/notes/stores/actions.js50
-rw-r--r--app/assets/javascripts/notes/stores/getters.js2
-rw-r--r--app/assets/javascripts/notes/stores/modules/index.js3
-rw-r--r--app/assets/javascripts/notes/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js38
-rw-r--r--app/assets/javascripts/notes/stores/utils.js4
-rw-r--r--app/assets/javascripts/notifications/components/custom_notifications_modal.vue128
-rw-r--r--app/assets/javascripts/notifications/components/notifications_dropdown.vue196
-rw-r--r--app/assets/javascripts/notifications/components/notifications_dropdown_item.vue42
-rw-r--r--app/assets/javascripts/notifications/constants.js58
-rw-r--r--app/assets/javascripts/notifications/index.js44
-rw-r--r--app/assets/javascripts/notifications_dropdown.js2
-rw-r--r--app/assets/javascripts/notifications_form.js4
-rw-r--r--app/assets/javascripts/onboarding_issues/index.js128
-rw-r--r--app/assets/javascripts/operation_settings/components/form_group/dashboard_timezone.vue2
-rw-r--r--app/assets/javascripts/operation_settings/components/form_group/external_dashboard.vue2
-rw-r--r--app/assets/javascripts/operation_settings/components/metrics_settings.vue8
-rw-r--r--app/assets/javascripts/operation_settings/index.js2
-rw-r--r--app/assets/javascripts/operation_settings/store/actions.js4
-rw-r--r--app/assets/javascripts/operation_settings/store/index.js2
-rw-r--r--app/assets/javascripts/packages/details/components/app.vue14
-rw-r--r--app/assets/javascripts/packages/details/components/installation_commands.vue4
-rw-r--r--app/assets/javascripts/packages/details/components/package_files.vue4
-rw-r--r--app/assets/javascripts/packages/details/components/package_history.vue6
-rw-r--r--app/assets/javascripts/packages/details/components/package_title.vue10
-rw-r--r--app/assets/javascripts/packages/details/index.js2
-rw-r--r--app/assets/javascripts/packages/details/store/actions.js2
-rw-r--r--app/assets/javascripts/packages/list/components/package_search.vue50
-rw-r--r--app/assets/javascripts/packages/list/components/package_title.vue2
-rw-r--r--app/assets/javascripts/packages/list/components/packages_filter.vue21
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list.vue8
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue89
-rw-r--r--app/assets/javascripts/packages/list/components/packages_sort.vue60
-rw-r--r--app/assets/javascripts/packages/list/components/tokens/package_type_token.vue26
-rw-r--r--app/assets/javascripts/packages/list/constants.js9
-rw-r--r--app/assets/javascripts/packages/list/packages_list_app_bundle.js4
-rw-r--r--app/assets/javascripts/packages/list/stores/actions.js11
-rw-r--r--app/assets/javascripts/packages/list/stores/getters.js2
-rw-r--r--app/assets/javascripts/packages/list/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/packages/list/stores/mutations.js10
-rw-r--r--app/assets/javascripts/packages/list/stores/state.js5
-rw-r--r--app/assets/javascripts/packages/shared/components/package_list_row.vue10
-rw-r--r--app/assets/javascripts/packages/shared/components/package_tags.vue4
-rw-r--r--app/assets/javascripts/packages/shared/components/packages_list_loader.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/bundle.js8
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue131
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue113
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/constants.js31
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql9
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql8
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js22
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js11
-rw-r--r--app/assets/javascripts/pager.js2
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js2
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/payload_previewer.js2
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js4
-rw-r--r--app/assets/javascripts/pages/admin/clusters/index/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/clusters/show/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/cohorts/index.js22
-rw-r--r--app/assets/javascripts/pages/admin/groups/new/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/integrations/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue2
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/index.js5
-rw-r--r--app/assets/javascripts/pages/admin/runners/index.js5
-rw-r--r--app/assets/javascripts/pages/admin/services/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue58
-rw-r--r--app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue30
-rw-r--r--app/assets/javascripts/pages/admin/users/index.js14
-rw-r--r--app/assets/javascripts/pages/dashboard/issues/index.js6
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js4
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue2
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js8
-rw-r--r--app/assets/javascripts/pages/groups/boards/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/clusters/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/clusters/index/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js12
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js26
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js8
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/milestones/show/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/new/group_path_validator.js4
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/settings/badges/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js9
-rw-r--r--app/assets/javascripts/pages/groups/settings/integrations/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/settings/repository/show/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/shared/group_details.js19
-rw-r--r--app/assets/javascripts/pages/groups/shared/group_tabs.js4
-rw-r--r--app/assets/javascripts/pages/help/index/index.js2
-rw-r--r--app/assets/javascripts/pages/import/bulk_imports/status/index.js (renamed from app/assets/javascripts/pages/import/bulk_imports/index.js)0
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue4
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue4
-rw-r--r--app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js3
-rw-r--r--app/assets/javascripts/pages/oauth/index.js3
-rw-r--r--app/assets/javascripts/pages/profiles/accounts/show/index.js2
-rw-r--r--app/assets/javascripts/pages/profiles/index.js3
-rw-r--r--app/assets/javascripts/pages/profiles/index/index.js2
-rw-r--r--app/assets/javascripts/pages/profiles/notifications/show/index.js4
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js6
-rw-r--r--app/assets/javascripts/pages/profiles/two_factor_auths/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/activity/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/alert_management/details/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/artifacts/browse/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/artifacts/file/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/blame/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/boards/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/clusters/index/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/clusters/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/clusters/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/commit/pipelines/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js23
-rw-r--r--app/assets/javascripts/pages/projects/commits/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/compare/index/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/compare/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/edit/index.js48
-rw-r--r--app/assets/javascripts/pages/projects/edit/mount_search_settings.js12
-rw-r--r--app/assets/javascripts/pages/projects/environments/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/environments/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/find_file/show/index.js16
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue7
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue27
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/incidents/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/init_blob.js6
-rw-r--r--app/assets/javascripts/pages/projects/init_form.js4
-rw-r--r--app/assets/javascripts/pages/projects/issues/form.js4
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js14
-rw-r--r--app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/service_desk/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js23
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/jobs/index/index.js19
-rw-r--r--app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue4
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue27
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue27
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js12
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/index/index.js25
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/conflicts/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js4
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js26
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/edit/check_form_state.js24
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/edit/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/index/index.js9
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js14
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/show/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/milestones/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue6
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js6
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/product_analytics/graphs/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/project.js15
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js92
-rw-r--r--app/assets/javascripts/pages/projects/releases/edit/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/releases/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/releases/new/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/releases/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/security/configuration/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/serverless/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/services/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js11
-rw-r--r--app/assets/javascripts/pages/projects/settings/operations/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/form.js10
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue11
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue97
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js1
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js27
-rw-r--r--app/assets/javascripts/pages/projects/tags/index/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/tags/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/tags/releases/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/tags/remove_tag.js2
-rw-r--r--app/assets/javascripts/pages/projects/tags/show/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/wikis/index.js2
-rw-r--r--app/assets/javascripts/pages/registrations/new/index.js2
-rw-r--r--app/assets/javascripts/pages/search/show/index.js4
-rw-r--r--app/assets/javascripts/pages/search/show/search.js54
-rw-r--r--app/assets/javascripts/pages/sessions/new/index.js6
-rw-r--r--app/assets/javascripts/pages/sessions/new/username_validator.js4
-rw-r--r--app/assets/javascripts/pages/shared/mount_runner_instructions.js32
-rw-r--r--app/assets/javascripts/pages/shared/wikis/index.js8
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js8
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js16
-rw-r--r--app/assets/javascripts/performance_bar/components/add_request.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue21
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue17
-rw-r--r--app/assets/javascripts/performance_bar/index.js5
-rw-r--r--app/assets/javascripts/performance_bar/performance_bar_log.js2
-rw-r--r--app/assets/javascripts/performance_bar/services/performance_bar_service.js2
-rw-r--r--app/assets/javascripts/persistent_user_callout.js4
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue114
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue100
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue52
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue30
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue84
-rw-r--r--app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue84
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue6
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue121
-rw-r--r--app/assets/javascripts/pipeline_editor/components/text_editor.vue46
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/confirm_unsaved_changes_dialog.vue26
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js14
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql2
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql1
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/commit_sha.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js36
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue269
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue60
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue45
-rw-r--r--app/assets/javascripts/pipelines/components/dag/dag.vue10
-rw-r--r--app/assets/javascripts/pipelines/components/dag/dag_graph.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue5
-rw-r--r--app/assets/javascripts/pipelines/components/graph/constants.js6
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue21
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_name_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue5
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue32
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue26
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js4
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue22
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/legacy_header_component.vue132
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue28
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue45
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue44
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue68
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue123
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/stage.vue139
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue40
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_reports.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue2
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js188
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js217
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js110
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_dag.js2
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_graph.js2
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_mediator.js2
-rw-r--r--app/assets/javascripts/pipelines/pipelines_index.js6
-rw-r--r--app/assets/javascripts/pipelines/services/pipelines_service.js2
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/actions.js12
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/getters.js12
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/index.js2
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/state.js3
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/utils.js19
-rw-r--r--app/assets/javascripts/pipelines/utils.js6
-rw-r--r--app/assets/javascripts/popovers/index.js2
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue2
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue4
-rw-r--r--app/assets/javascripts/profile/account/index.js5
-rw-r--r--app/assets/javascripts/profile/preferences/components/profile_preferences.vue105
-rw-r--r--app/assets/javascripts/profile/preferences/constants.js22
-rw-r--r--app/assets/javascripts/profile/preferences/profile_preferences_bundle.js20
-rw-r--r--app/assets/javascripts/profile/profile.js5
-rw-r--r--app/assets/javascripts/project_find_file.js6
-rw-r--r--app/assets/javascripts/project_label_subscription.js6
-rw-r--r--app/assets/javascripts/project_select.js4
-rw-r--r--app/assets/javascripts/projects/commit/components/branches_dropdown.vue2
-rw-r--r--app/assets/javascripts/projects/commit/components/form_modal.vue5
-rw-r--r--app/assets/javascripts/projects/commit/components/form_trigger.vue5
-rw-r--r--app/assets/javascripts/projects/commit/constants.js9
-rw-r--r--app/assets/javascripts/projects/commit/index.js11
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js51
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js20
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_modal.js4
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_trigger.js8
-rw-r--r--app/assets/javascripts/projects/commit/store/actions.js4
-rw-r--r--app/assets/javascripts/projects/commit_box/info/index.js4
-rw-r--r--app/assets/javascripts/projects/commits/components/author_select.vue6
-rw-r--r--app/assets/javascripts/projects/commits/store/actions.js8
-rw-r--r--app/assets/javascripts/projects/compare/components/app.vue89
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown.vue145
-rw-r--r--app/assets/javascripts/projects/compare/index.js33
-rw-r--r--app/assets/javascripts/projects/components/project_delete_button.vue4
-rw-r--r--app/assets/javascripts/projects/components/shared/delete_button.vue4
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue6
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/index.js2
-rw-r--r--app/assets/javascripts/projects/members/constants.js1
-rw-r--r--app/assets/javascripts/projects/members/utils.js8
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue203
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue50
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue233
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/constants.js2
-rw-r--r--app/assets/javascripts/projects/settings/access_dropdown.js87
-rw-r--r--app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue2
-rw-r--r--app/assets/javascripts/projects/settings/mount_shared_runners_toggle.js2
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue67
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue20
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/event_hub.js3
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/index.js70
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js23
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue6
-rw-r--r--app/assets/javascripts/prometheus_alerts/components/reset_key.vue4
-rw-r--r--app/assets/javascripts/prometheus_metrics/custom_metrics.js6
-rw-r--r--app/assets/javascripts/prometheus_metrics/prometheus_metrics.js2
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_create.js10
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js6
-rw-r--r--app/assets/javascripts/protected_tags/constants.js3
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js2
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_create.js4
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_edit.js9
-rw-r--r--app/assets/javascripts/ref/components/ref_selector.vue4
-rw-r--r--app/assets/javascripts/ref/stores/mutations.js4
-rw-r--r--app/assets/javascripts/registry/explorer/components/delete_image.vue76
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue37
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/details_header.vue36
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue44
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/empty_tags_state.vue33
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue50
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue13
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue10
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue5
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue6
-rw-r--r--app/assets/javascripts/registry/explorer/constants/details.js64
-rw-r--r--app/assets/javascripts/registry/explorer/constants/list.js10
-rw-r--r--app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql19
-rw-r--r--app/assets/javascripts/registry/explorer/index.js18
-rw-r--r--app/assets/javascripts/registry/explorer/pages/details.vue157
-rw-r--r--app/assets/javascripts/registry/explorer/pages/list.vue129
-rw-r--r--app/assets/javascripts/registry/explorer/router.js4
-rw-r--r--app/assets/javascripts/registry/settings/components/registry_settings_app.vue2
-rw-r--r--app/assets/javascripts/registry/settings/components/settings_form.vue6
-rw-r--r--app/assets/javascripts/registry/settings/registry_settings_bundle.js4
-rw-r--r--app/assets/javascripts/related_issues/components/add_issuable_form.vue4
-rw-r--r--app/assets/javascripts/related_issues/components/related_issuable_input.vue2
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue6
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_list.vue4
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_root.vue6
-rw-r--r--app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue2
-rw-r--r--app/assets/javascripts/related_merge_requests/store/actions.js4
-rw-r--r--app/assets/javascripts/related_merge_requests/store/index.js2
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue8
-rw-r--r--app/assets/javascripts/releases/components/app_index.vue4
-rw-r--r--app/assets/javascripts/releases/components/asset_links_form.vue4
-rw-r--r--app/assets/javascripts/releases/components/evidence_block.vue6
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block_assets.vue2
-rw-r--r--app/assets/javascripts/releases/components/release_block_footer.vue2
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue19
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_graphql.vue2
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_rest.vue2
-rw-r--r--app/assets/javascripts/releases/components/tag_field_existing.vue4
-rw-r--r--app/assets/javascripts/releases/components/tag_field_new.vue2
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/actions.js6
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/mutations.js2
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/actions.js8
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/index.js2
-rw-r--r--app/assets/javascripts/releases/util.js2
-rw-r--r--app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue2
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/actions.js4
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/getters.js2
-rw-r--r--app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue2
-rw-r--r--app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue18
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/actions.js19
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/getters.js4
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/mutations.js5
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/state.js2
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js4
-rw-r--r--app/assets/javascripts/reports/components/grouped_issues_list.vue2
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue16
-rw-r--r--app/assets/javascripts/reports/components/issue_body.js2
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue2
-rw-r--r--app/assets/javascripts/reports/components/test_issue_body.vue2
-rw-r--r--app/assets/javascripts/reports/store/actions.js2
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue2
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue4
-rw-r--r--app/assets/javascripts/repository/components/preview/index.vue2
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue2
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue4
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue4
-rw-r--r--app/assets/javascripts/repository/graphql.js4
-rw-r--r--app/assets/javascripts/repository/index.js12
-rw-r--r--app/assets/javascripts/repository/mixins/preload.js2
-rw-r--r--app/assets/javascripts/repository/pages/index.vue2
-rw-r--r--app/assets/javascripts/repository/pages/tree.vue2
-rw-r--r--app/assets/javascripts/repository/router.js2
-rw-r--r--app/assets/javascripts/right_sidebar.js4
-rw-r--r--app/assets/javascripts/search/highlight_blob_search_result.js4
-rw-r--r--app/assets/javascripts/search/index.js15
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue4
-rw-r--r--app/assets/javascripts/search/sidebar/components/radio_filter.vue2
-rw-r--r--app/assets/javascripts/search/sort/components/app.vue103
-rw-r--r--app/assets/javascripts/search/sort/constants.js19
-rw-r--r--app/assets/javascripts/search/sort/index.js27
-rw-r--r--app/assets/javascripts/search/store/actions.js2
-rw-r--r--app/assets/javascripts/search/topbar/components/app.vue73
-rw-r--r--app/assets/javascripts/search/topbar/components/group_filter.vue5
-rw-r--r--app/assets/javascripts/search/topbar/components/project_filter.vue5
-rw-r--r--app/assets/javascripts/search/topbar/components/searchable_dropdown.vue2
-rw-r--r--app/assets/javascripts/search/topbar/index.js31
-rw-r--r--app/assets/javascripts/search_autocomplete.js6
-rw-r--r--app/assets/javascripts/search_settings/components/search_settings.vue52
-rw-r--r--app/assets/javascripts/search_settings/index.js27
-rw-r--r--app/assets/javascripts/search_settings/mount.js23
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue23
-rw-r--r--app/assets/javascripts/security_configuration/components/configuration_table.vue97
-rw-r--r--app/assets/javascripts/security_configuration/components/features_constants.js112
-rw-r--r--app/assets/javascripts/security_configuration/components/manage_sast.vue57
-rw-r--r--app/assets/javascripts/security_configuration/components/upgrade.vue26
-rw-r--r--app/assets/javascripts/security_configuration/graphql/configure_sast.mutation.graphql6
-rw-r--r--app/assets/javascripts/security_configuration/index.js29
-rw-r--r--app/assets/javascripts/self_monitor/components/self_monitor_form.vue9
-rw-r--r--app/assets/javascripts/self_monitor/index.js2
-rw-r--r--app/assets/javascripts/self_monitor/store/actions.js4
-rw-r--r--app/assets/javascripts/self_monitor/store/index.js2
-rw-r--r--app/assets/javascripts/sentry/sentry_config.js2
-rw-r--r--app/assets/javascripts/sentry_error_stack_trace/index.js2
-rw-r--r--app/assets/javascripts/serverless/components/area.vue2
-rw-r--r--app/assets/javascripts/serverless/components/environment_row.vue2
-rw-r--r--app/assets/javascripts/serverless/components/function_details.vue4
-rw-r--r--app/assets/javascripts/serverless/components/function_row.vue2
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue28
-rw-r--r--app/assets/javascripts/serverless/serverless_bundle.js2
-rw-r--r--app/assets/javascripts/serverless/store/actions.js6
-rw-r--r--app/assets/javascripts/serverless/survey_banner.vue2
-rw-r--r--app/assets/javascripts/set_status_modal/components/user_availability_status.vue26
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue12
-rw-r--r--app/assets/javascripts/set_status_modal/utils.js6
-rw-r--r--app/assets/javascripts/settings_panels.js25
-rw-r--r--app/assets/javascripts/shared/milestones/form.js2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue54
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue16
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue14
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue37
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue18
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue403
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/user_name_with_status.vue40
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewers.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue128
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_editable_item.vue95
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue15
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue13
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/todo.vue4
-rw-r--r--app/assets/javascripts/sidebar/constants.js16
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js2
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js2
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js56
-rw-r--r--app/assets/javascripts/sidebar/queries/reviewer_rereview.mutation.graphql5
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js15
-rw-r--r--app/assets/javascripts/sidebar/sidebar_bundle.js2
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js16
-rw-r--r--app/assets/javascripts/sidebar/stores/sidebar_store.js8
-rw-r--r--app/assets/javascripts/single_file_diff.js8
-rw-r--r--app/assets/javascripts/snippet/snippet_edit.js4
-rw-r--r--app/assets/javascripts/snippet/snippet_show.js4
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue81
-rw-r--r--app/assets/javascripts/snippets/components/embed_dropdown.vue2
-rw-r--r--app/assets/javascripts/snippets/components/show.vue14
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue2
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_edit.vue8
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_view.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_description_edit.vue2
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue6
-rw-r--r--app/assets/javascripts/snippets/components/snippet_visibility_edit.vue2
-rw-r--r--app/assets/javascripts/snippets/index.js2
-rw-r--r--app/assets/javascripts/snippets/mixins/snippets.js8
-rw-r--r--app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql2
-rw-r--r--app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql3
-rw-r--r--app/assets/javascripts/snippets/utils/blob.js4
-rw-r--r--app/assets/javascripts/snippets/utils/error.js15
-rw-r--r--app/assets/javascripts/star.js4
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_area.vue12
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_drawer.vue7
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue5
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/index.js4
-rw-r--r--app/assets/javascripts/static_site_editor/image_repository.js2
-rw-r--r--app/assets/javascripts/static_site_editor/index.js2
-rw-r--r--app/assets/javascripts/static_site_editor/pages/home.vue8
-rw-r--r--app/assets/javascripts/static_site_editor/pages/success.vue2
-rw-r--r--app/assets/javascripts/static_site_editor/services/submit_content_changes.js2
-rw-r--r--app/assets/javascripts/subscription_select.js2
-rw-r--r--app/assets/javascripts/task_list.js2
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js27
-rw-r--r--app/assets/javascripts/terminal/terminal.js2
-rw-r--r--app/assets/javascripts/terraform/components/states_table.vue62
-rw-r--r--app/assets/javascripts/terraform/components/states_table_actions.vue80
-rw-r--r--app/assets/javascripts/terraform/components/terraform_list.vue2
-rw-r--r--app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql5
-rw-r--r--app/assets/javascripts/terraform/graphql/mutations/add_data_to_state.mutation.graphql3
-rw-r--r--app/assets/javascripts/terraform/graphql/resolvers.js45
-rw-r--r--app/assets/javascripts/terraform/index.js14
-rw-r--r--app/assets/javascripts/toggle_buttons.js2
-rw-r--r--app/assets/javascripts/tooltips/index.js94
-rw-r--r--app/assets/javascripts/ui_development_kit.js2
-rw-r--r--app/assets/javascripts/usage_ping_consent.js2
-rw-r--r--app/assets/javascripts/user_lists/components/edit_user_list.vue2
-rw-r--r--app/assets/javascripts/user_lists/components/new_user_list.vue2
-rw-r--r--app/assets/javascripts/user_lists/components/user_list.vue2
-rw-r--r--app/assets/javascripts/user_lists/store/edit/index.js2
-rw-r--r--app/assets/javascripts/user_lists/store/new/index.js2
-rw-r--r--app/assets/javascripts/user_lists/store/show/index.js2
-rw-r--r--app/assets/javascripts/user_lists/store/show/mutations.js2
-rw-r--r--app/assets/javascripts/users_select/index.js19
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/artifacts_list_app.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue37
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue3
-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/mr_widget_auto_merge_enabled.vue28
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue21
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue25
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue27
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue26
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue45
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue38
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue63
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.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.fragment.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/actions.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/index.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js24
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue392
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_metrics.vue (renamed from app/assets/javascripts/alert_management/components/alert_metrics.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue86
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue125
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/alert_summary_row.vue (renamed from app/assets/javascripts/alert_management/components/alert_summary_row.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignee.vue (renamed from app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue (renamed from app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_header.vue41
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue (renamed from app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue149
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue (renamed from app/assets/javascripts/alert_management/components/system_notes/system_note.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/constants.js31
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/fragments/alert_detail_item.fragment.graphql (renamed from app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql (renamed from app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.mutation.graphql)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql (renamed from app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_sidebar_status.mutation.graphql (renamed from app/assets/javascripts/alert_management/graphql/mutations/toggle_sidebar_status.mutation.graphql)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql10
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql11
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_status.query.graphql (renamed from app/assets/javascripts/alert_management/graphql/queries/sidebar_status.query.graphql)0
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/index.js83
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/router.js (renamed from app/assets/javascripts/alert_management/router.js)0
-rw-r--r--app/assets/javascripts/vue_shared/components/actions_button.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/clone_dropdown.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue61
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/renamed.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/editor_lite.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/index.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/item.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/index.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/help_popover.vue40
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/navigation_tabs.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/code_instruction.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/registry_search.vue90
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/constants.js18
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql20
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql16
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue261
-rw-r--r--app/assets/javascripts/vue_shared/components/settings/settings_block.vue45
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue19
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql13
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql19
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql19
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql17
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql21
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql21
-rw-r--r--app/assets/javascripts/vue_shared/components/split_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/timezone_dropdown.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/todo_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/toggle_button.vue88
-rw-r--r--app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue14
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue2
-rw-r--r--app/assets/javascripts/vue_shared/directives/validation.js2
-rw-r--r--app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js67
-rw-r--r--app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js2
-rw-r--r--app/assets/javascripts/vue_shared/plugins/global_toast.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/constants.js6
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue108
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/getters.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/index.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js4
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/store/utils.js2
-rw-r--r--app/assets/javascripts/vuex_shared/modules/modal/index.js4
-rw-r--r--app/assets/javascripts/webpack_non_compiled_placeholder.js24
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue6
-rw-r--r--app/assets/javascripts/whats_new/store/actions.js2
-rw-r--r--app/assets/javascripts/zen_mode.js2
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss1
-rw-r--r--app/assets/stylesheets/components/batch_comments/review_bar.scss2
-rw-r--r--app/assets/stylesheets/components/design_management/design_list_item.scss5
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/awards.scss2
-rw-r--r--app/assets/stylesheets/framework/buttons.scss23
-rw-r--r--app/assets/stylesheets/framework/carousel.scss202
-rw-r--r--app/assets/stylesheets/framework/ci_variable_list.scss10
-rw-r--r--app/assets/stylesheets/framework/common.scss2
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss2
-rw-r--r--app/assets/stylesheets/framework/diffs.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss24
-rw-r--r--app/assets/stylesheets/framework/feature_highlight.scss51
-rw-r--r--app/assets/stylesheets/framework/files.scss38
-rw-r--r--app/assets/stylesheets/framework/filters.scss9
-rw-r--r--app/assets/stylesheets/framework/header.scss24
-rw-r--r--app/assets/stylesheets/framework/icons.scss48
-rw-r--r--app/assets/stylesheets/framework/mixins.scss7
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss2
-rw-r--r--app/assets/stylesheets/framework/tables.scss3
-rw-r--r--app/assets/stylesheets/framework/typography.scss7
-rw-r--r--app/assets/stylesheets/framework/variables.scss23
-rw-r--r--app/assets/stylesheets/mailer.scss23
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss22
-rw-r--r--app/assets/stylesheets/page_bundles/_pipeline_mixins.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss3
-rw-r--r--app/assets/stylesheets/page_bundles/admin/jobs_index.scss5
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss41
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss65
-rw-r--r--app/assets/stylesheets/page_bundles/import.scss29
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/oncall_schedules.scss12
-rw-r--r--app/assets/stylesheets/page_bundles/pipelines.scss11
-rw-r--r--app/assets/stylesheets/page_bundles/signup.scss4
-rw-r--r--app/assets/stylesheets/pages/admin.scss18
-rw-r--r--app/assets/stylesheets/pages/commits.scss5
-rw-r--r--app/assets/stylesheets/pages/editor.scss13
-rw-r--r--app/assets/stylesheets/pages/groups.scss1
-rw-r--r--app/assets/stylesheets/pages/issuable.scss13
-rw-r--r--app/assets/stylesheets/pages/issues.scss28
-rw-r--r--app/assets/stylesheets/pages/labels.scss2
-rw-r--r--app/assets/stylesheets/pages/login.scss3
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss20
-rw-r--r--app/assets/stylesheets/pages/note_form.scss6
-rw-r--r--app/assets/stylesheets/pages/notes.scss58
-rw-r--r--app/assets/stylesheets/pages/profile.scss20
-rw-r--r--app/assets/stylesheets/pages/projects.scss18
-rw-r--r--app/assets/stylesheets/pages/tree.scss4
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss2
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss3
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss5
-rw-r--r--app/assets/stylesheets/utilities.scss16
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/admin/cohorts_controller.rb14
-rw-r--r--app/controllers/admin/users_controller.rb21
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/autocomplete_controller.rb2
-rw-r--r--app/controllers/chaos_controller.rb9
-rw-r--r--app/controllers/concerns/boards_actions.rb14
-rw-r--r--app/controllers/concerns/boards_responses.rb6
-rw-r--r--app/controllers/concerns/comment_and_close_flag.rb11
-rw-r--r--app/controllers/concerns/integrations_actions.rb4
-rw-r--r--app/controllers/concerns/membership_actions.rb24
-rw-r--r--app/controllers/concerns/multiple_boards_actions.rb1
-rw-r--r--app/controllers/concerns/notes_actions.rb9
-rw-r--r--app/controllers/concerns/redis_tracking.rb16
-rw-r--r--app/controllers/concerns/service_params.rb1
-rw-r--r--app/controllers/concerns/snippets_actions.rb2
-rw-r--r--app/controllers/concerns/spammable_actions.rb57
-rw-r--r--app/controllers/concerns/wiki_actions.rb3
-rw-r--r--app/controllers/dashboard_controller.rb19
-rw-r--r--app/controllers/graphql_controller.rb5
-rw-r--r--app/controllers/groups/boards_controller.rb27
-rw-r--r--app/controllers/groups/email_campaigns_controller.rb61
-rw-r--r--app/controllers/groups/settings/packages_and_registries_controller.rb7
-rw-r--r--app/controllers/groups_controller.rb5
-rw-r--r--app/controllers/help_controller.rb11
-rw-r--r--app/controllers/import/bulk_imports_controller.rb27
-rw-r--r--app/controllers/invites_controller.rb16
-rw-r--r--app/controllers/jira_connect/users_controller.rb2
-rw-r--r--app/controllers/profiles/notifications_controller.rb2
-rw-r--r--app/controllers/profiles/preferences_controller.rb25
-rw-r--r--app/controllers/projects/badges_controller.rb4
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/boards_controller.rb22
-rw-r--r--app/controllers/projects/branches_controller.rb6
-rw-r--r--app/controllers/projects/ci/daily_build_group_report_results_controller.rb20
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb1
-rw-r--r--app/controllers/projects/ci/prometheus_metrics/histograms_controller.rb25
-rw-r--r--app/controllers/projects/commit_controller.rb4
-rw-r--r--app/controllers/projects/discussions_controller.rb2
-rw-r--r--app/controllers/projects/forks_controller.rb8
-rw-r--r--app/controllers/projects/issues_controller.rb15
-rw-r--r--app/controllers/projects/jobs_controller.rb3
-rw-r--r--app/controllers/projects/learn_gitlab_controller.rb19
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb5
-rw-r--r--app/controllers/projects/merge_requests_controller.rb35
-rw-r--r--app/controllers/projects/notes_controller.rb17
-rw-r--r--app/controllers/projects/pipelines/tests_controller.rb6
-rw-r--r--app/controllers/projects/pipelines_controller.rb29
-rw-r--r--app/controllers/projects/project_members_controller.rb4
-rw-r--r--app/controllers/projects/security/configuration_controller.rb23
-rw-r--r--app/controllers/projects/services_controller.rb2
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb4
-rw-r--r--app/controllers/projects/settings/repository_controller.rb1
-rw-r--r--app/controllers/projects/templates_controller.rb4
-rw-r--r--app/controllers/projects_controller.rb38
-rw-r--r--app/controllers/registrations/experience_levels_controller.rb10
-rw-r--r--app/controllers/registrations/welcome_controller.rb19
-rw-r--r--app/controllers/registrations_controller.rb6
-rw-r--r--app/controllers/repositories/git_http_controller.rb2
-rw-r--r--app/controllers/search_controller.rb7
-rw-r--r--app/controllers/snippets/notes_controller.rb2
-rw-r--r--app/controllers/users_controller.rb53
-rw-r--r--app/controllers/whats_new_controller.rb11
-rw-r--r--app/experiments/application_experiment.rb45
-rw-r--r--app/experiments/members/invite_email_experiment.rb18
-rw-r--r--app/experiments/new_project_readme_experiment.rb45
-rw-r--r--app/experiments/strategy/round_robin.rb78
-rw-r--r--app/finders/autocomplete/users_finder.rb10
-rw-r--r--app/finders/ci/jobs_finder.rb7
-rw-r--r--app/finders/ci/testing/daily_build_group_report_results_finder.rb88
-rw-r--r--app/finders/concerns/packages/finder_helper.rb33
-rw-r--r--app/finders/container_repositories_finder.rb9
-rw-r--r--app/finders/deployments_finder.rb85
-rw-r--r--app/finders/labels_finder.rb6
-rw-r--r--app/finders/license_template_finder.rb5
-rw-r--r--app/finders/merge_request/metrics_finder.rb65
-rw-r--r--app/finders/merge_requests/oldest_per_commit_finder.rb33
-rw-r--r--app/finders/packages/group_packages_finder.rb30
-rw-r--r--app/finders/packages/nuget/package_finder.rb2
-rw-r--r--app/finders/packages/packages_finder.rb21
-rw-r--r--app/finders/repositories/commits_with_trailer_finder.rb82
-rw-r--r--app/finders/repositories/previous_tag_finder.rb51
-rw-r--r--app/finders/template_finder.rb16
-rw-r--r--app/finders/terraform/states_finder.rb28
-rw-r--r--app/finders/user_recent_events_finder.rb43
-rw-r--r--app/graphql/mutations/alert_management/base.rb2
-rw-r--r--app/graphql/mutations/alert_management/http_integration/create.rb19
-rw-r--r--app/graphql/mutations/alert_management/http_integration/http_integration_base.rb7
-rw-r--r--app/graphql/mutations/alert_management/http_integration/update.rb4
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb8
-rw-r--r--app/graphql/mutations/boards/lists/base.rb28
-rw-r--r--app/graphql/mutations/boards/lists/base_create.rb55
-rw-r--r--app/graphql/mutations/boards/lists/create.rb51
-rw-r--r--app/graphql/mutations/branches/create.rb10
-rw-r--r--app/graphql/mutations/commits/create.rb10
-rw-r--r--app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb83
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb4
-rw-r--r--app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb24
-rw-r--r--app/graphql/mutations/container_expiration_policies/update.rb10
-rw-r--r--app/graphql/mutations/discussions/toggle_resolve.rb2
-rw-r--r--app/graphql/mutations/issues/create.rb8
-rw-r--r--app/graphql/mutations/jira_import/import_users.rb16
-rw-r--r--app/graphql/mutations/jira_import/start.rb16
-rw-r--r--app/graphql/mutations/merge_requests/create.rb10
-rw-r--r--app/graphql/mutations/merge_requests/reviewer_rereview.rb27
-rw-r--r--app/graphql/mutations/merge_requests/update.rb11
-rw-r--r--app/graphql/mutations/notes/create/base.rb15
-rw-r--r--app/graphql/mutations/releases/base.rb8
-rw-r--r--app/graphql/mutations/releases/create.rb2
-rw-r--r--app/graphql/mutations/releases/delete.rb2
-rw-r--r--app/graphql/mutations/releases/update.rb2
-rw-r--r--app/graphql/mutations/security/ci_configuration/configure_sast.rb46
-rw-r--r--app/graphql/mutations/snippets/create.rb41
-rw-r--r--app/graphql/mutations/snippets/service_compatibility.rb23
-rw-r--r--app/graphql/mutations/snippets/update.rb48
-rw-r--r--app/graphql/mutations/todos/create.rb2
-rw-r--r--app/graphql/mutations/todos/mark_all_done.rb6
-rw-r--r--app/graphql/mutations/todos/mark_done.rb4
-rw-r--r--app/graphql/mutations/todos/restore.rb4
-rw-r--r--app/graphql/mutations/todos/restore_many.rb10
-rw-r--r--app/graphql/queries/container_registry/get_container_repositories.query.graphql19
-rw-r--r--app/graphql/resolvers/base_resolver.rb2
-rw-r--r--app/graphql/resolvers/board_lists_resolver.rb7
-rw-r--r--app/graphql/resolvers/board_resolver.rb2
-rw-r--r--app/graphql/resolvers/boards_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/config_resolver.rb8
-rw-r--r--app/graphql/resolvers/container_repositories_resolver.rb9
-rw-r--r--app/graphql/resolvers/group_labels_resolver.rb17
-rw-r--r--app/graphql/resolvers/labels_resolver.rb46
-rw-r--r--app/graphql/resolvers/package_details_resolver.rb4
-rw-r--r--app/graphql/resolvers/packages_resolver.rb2
-rw-r--r--app/graphql/resolvers/project_merge_requests_resolver.rb33
-rw-r--r--app/graphql/resolvers/snippets/blobs_resolver.rb5
-rw-r--r--app/graphql/resolvers/terraform/states_resolver.rb18
-rw-r--r--app/graphql/types/access_level_type.rb4
-rw-r--r--app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb6
-rw-r--r--app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb6
-rw-r--r--app/graphql/types/alert_management/alert_status_counts_type.rb4
-rw-r--r--app/graphql/types/alert_management/alert_type.rb44
-rw-r--r--app/graphql/types/alert_management/integration_type.rb14
-rw-r--r--app/graphql/types/award_emojis/award_emoji_type.rb12
-rw-r--r--app/graphql/types/base_enum.rb2
-rw-r--r--app/graphql/types/base_field.rb2
-rw-r--r--app/graphql/types/board_list_type.rb16
-rw-r--r--app/graphql/types/board_type.rb10
-rw-r--r--app/graphql/types/boards/board_issue_input_base_type.rb12
-rw-r--r--app/graphql/types/boards/board_issue_input_type.rb4
-rw-r--r--app/graphql/types/branch_type.rb4
-rw-r--r--app/graphql/types/ci/analytics_type.rb22
-rw-r--r--app/graphql/types/ci/application_setting_type.rb14
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb3
-rw-r--r--app/graphql/types/ci/config/config_type.rb8
-rw-r--r--app/graphql/types/ci/config/group_type.rb6
-rw-r--r--app/graphql/types/ci/config/need_type.rb2
-rw-r--r--app/graphql/types/ci/config/stage_type.rb4
-rw-r--r--app/graphql/types/ci/detailed_status_type.rb21
-rw-r--r--app/graphql/types/ci/group_type.rb8
-rw-r--r--app/graphql/types/ci/job_artifact_type.rb4
-rw-r--r--app/graphql/types/ci/job_type.rb12
-rw-r--r--app/graphql/types/ci/pipeline_type.rb52
-rw-r--r--app/graphql/types/ci/runner_architecture_type.rb4
-rw-r--r--app/graphql/types/ci/runner_platform_type.rb6
-rw-r--r--app/graphql/types/ci/runner_setup_type.rb4
-rw-r--r--app/graphql/types/ci/stage_type.rb6
-rw-r--r--app/graphql/types/ci/status_action_type.rb10
-rw-r--r--app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb23
-rw-r--r--app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb28
-rw-r--r--app/graphql/types/ci_configuration/sast/entity_input_type.rb22
-rw-r--r--app/graphql/types/ci_configuration/sast/entity_type.rb37
-rw-r--r--app/graphql/types/ci_configuration/sast/input_type.rb24
-rw-r--r--app/graphql/types/ci_configuration/sast/options_entity_type.rb19
-rw-r--r--app/graphql/types/ci_configuration/sast/type.rb22
-rw-r--r--app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb16
-rw-r--r--app/graphql/types/commit_action_type.rb14
-rw-r--r--app/graphql/types/commit_type.rb28
-rw-r--r--app/graphql/types/container_expiration_policy_type.rb18
-rw-r--r--app/graphql/types/container_repository_details_type.rb2
-rw-r--r--app/graphql/types/container_repository_sort_enum.rb11
-rw-r--r--app/graphql/types/container_repository_type.rb2
-rw-r--r--app/graphql/types/countable_connection_type.rb2
-rw-r--r--app/graphql/types/current_user_todos.rb4
-rw-r--r--app/graphql/types/custom_emoji_type.rb8
-rw-r--r--app/graphql/types/design_management/design_at_version_type.rb4
-rw-r--r--app/graphql/types/design_management/design_collection_type.rb16
-rw-r--r--app/graphql/types/design_management/design_fields.rb18
-rw-r--r--app/graphql/types/design_management/design_type.rb2
-rw-r--r--app/graphql/types/design_management/version_type.rb10
-rw-r--r--app/graphql/types/design_management_type.rb4
-rw-r--r--app/graphql/types/diff_paths_input_type.rb4
-rw-r--r--app/graphql/types/diff_refs_type.rb6
-rw-r--r--app/graphql/types/diff_stats_summary_type.rb8
-rw-r--r--app/graphql/types/diff_stats_type.rb6
-rw-r--r--app/graphql/types/environment_type.rb10
-rw-r--r--app/graphql/types/error_tracking/sentry_detailed_error_type.rb56
-rw-r--r--app/graphql/types/error_tracking/sentry_error_collection_type.rb8
-rw-r--r--app/graphql/types/error_tracking/sentry_error_frequency_type.rb4
-rw-r--r--app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb4
-rw-r--r--app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb10
-rw-r--r--app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb6
-rw-r--r--app/graphql/types/error_tracking/sentry_error_tags_type.rb4
-rw-r--r--app/graphql/types/error_tracking/sentry_error_type.rb34
-rw-r--r--app/graphql/types/event_action_enum.rb12
-rw-r--r--app/graphql/types/event_type.rb36
-rw-r--r--app/graphql/types/eventable_type.rb9
-rw-r--r--app/graphql/types/evidence_type.rb8
-rw-r--r--app/graphql/types/global_id_type.rb2
-rw-r--r--app/graphql/types/grafana_integration_type.rb10
-rw-r--r--app/graphql/types/group_invitation_type.rb2
-rw-r--r--app/graphql/types/group_member_type.rb2
-rw-r--r--app/graphql/types/group_type.rb57
-rw-r--r--app/graphql/types/invitation_interface.rb14
-rw-r--r--app/graphql/types/issue_type.rb80
-rw-r--r--app/graphql/types/jira_import_type.rb14
-rw-r--r--app/graphql/types/jira_user_type.rb12
-rw-r--r--app/graphql/types/jira_users_mapping_input_type.rb4
-rw-r--r--app/graphql/types/label_type.rb10
-rw-r--r--app/graphql/types/member_interface.rb14
-rw-r--r--app/graphql/types/merge_request_connection_type.rb2
-rw-r--r--app/graphql/types/merge_request_state_enum.rb2
-rw-r--r--app/graphql/types/merge_request_state_event_enum.rb16
-rw-r--r--app/graphql/types/merge_request_type.rb146
-rw-r--r--app/graphql/types/metadata_type.rb4
-rw-r--r--app/graphql/types/metrics/dashboard_type.rb6
-rw-r--r--app/graphql/types/metrics/dashboards/annotation_type.rb10
-rw-r--r--app/graphql/types/milestone_state_enum.rb7
-rw-r--r--app/graphql/types/milestone_stats_type.rb4
-rw-r--r--app/graphql/types/milestone_type.rb26
-rw-r--r--app/graphql/types/mutation_type.rb3
-rw-r--r--app/graphql/types/namespace_type.rb24
-rw-r--r--app/graphql/types/notes/diff_position_type.rb22
-rw-r--r--app/graphql/types/notes/discussion_type.rb20
-rw-r--r--app/graphql/types/notes/note_type.rb26
-rw-r--r--app/graphql/types/notes/noteable_type.rb4
-rw-r--r--app/graphql/types/packages/composer/details_type.rb16
-rw-r--r--app/graphql/types/packages/composer/metadatum_type.rb4
-rw-r--r--app/graphql/types/packages/metadata_type.rb23
-rw-r--r--app/graphql/types/packages/package_type.rb19
-rw-r--r--app/graphql/types/packages/package_type_enum.rb2
-rw-r--r--app/graphql/types/packages/package_without_versions_type.rb44
-rw-r--r--app/graphql/types/project_invitation_type.rb2
-rw-r--r--app/graphql/types/project_member_type.rb2
-rw-r--r--app/graphql/types/project_statistics_type.rb18
-rw-r--r--app/graphql/types/project_type.rb175
-rw-r--r--app/graphql/types/projects/service_type.rb4
-rw-r--r--app/graphql/types/projects/service_type_enum.rb2
-rw-r--r--app/graphql/types/projects/services/jira_project_type.rb6
-rw-r--r--app/graphql/types/projects/services/jira_service_type.rb2
-rw-r--r--app/graphql/types/prometheus_alert_type.rb4
-rw-r--r--app/graphql/types/query_type.rb57
-rw-r--r--app/graphql/types/range_input_type.rb4
-rw-r--r--app/graphql/types/release_asset_link_input_type.rb8
-rw-r--r--app/graphql/types/release_asset_link_type.rb12
-rw-r--r--app/graphql/types/release_assets_input_type.rb2
-rw-r--r--app/graphql/types/release_assets_type.rb6
-rw-r--r--app/graphql/types/release_links_type.rb14
-rw-r--r--app/graphql/types/release_source_type.rb4
-rw-r--r--app/graphql/types/release_type.rb26
-rw-r--r--app/graphql/types/repository_type.rb8
-rw-r--r--app/graphql/types/resolvable_interface.rb8
-rw-r--r--app/graphql/types/root_storage_statistics_type.rb18
-rw-r--r--app/graphql/types/snippet_type.rb30
-rw-r--r--app/graphql/types/snippets/blob_action_input_type.rb8
-rw-r--r--app/graphql/types/snippets/blob_type.rb24
-rw-r--r--app/graphql/types/snippets/blob_viewer_type.rb14
-rw-r--r--app/graphql/types/task_completion_status.rb4
-rw-r--r--app/graphql/types/terraform/state_type.rb14
-rw-r--r--app/graphql/types/terraform/state_version_type.rb14
-rw-r--r--app/graphql/types/todo_type.rb20
-rw-r--r--app/graphql/types/tree/blob_type.rb8
-rw-r--r--app/graphql/types/tree/entry_type.rb12
-rw-r--r--app/graphql/types/tree/submodule_type.rb4
-rw-r--r--app/graphql/types/tree/tree_entry_type.rb4
-rw-r--r--app/graphql/types/tree/tree_type.rb8
-rw-r--r--app/graphql/types/user_status_type.rb6
-rw-r--r--app/graphql/types/user_type.rb41
-rw-r--r--app/helpers/analytics/cycle_analytics_helper.rb11
-rw-r--r--app/helpers/analytics/unique_visits_helper.rb1
-rw-r--r--app/helpers/application_helper.rb2
-rw-r--r--app/helpers/application_settings_helper.rb24
-rw-r--r--app/helpers/auth_helper.rb2
-rw-r--r--app/helpers/blob_helper.rb40
-rw-r--r--app/helpers/boards_helper.rb20
-rw-r--r--app/helpers/ci/jobs_helper.rb1
-rw-r--r--app/helpers/commits_helper.rb54
-rw-r--r--app/helpers/container_registry_helper.rb2
-rw-r--r--app/helpers/diff_helper.rb28
-rw-r--r--app/helpers/enable_search_settings_helper.rb9
-rw-r--r--app/helpers/events_helper.rb4
-rw-r--r--app/helpers/external_link_helper.rb2
-rw-r--r--app/helpers/groups/group_members_helper.rb14
-rw-r--r--app/helpers/groups_helper.rb23
-rw-r--r--app/helpers/in_product_marketing_helper.rb350
-rw-r--r--app/helpers/invite_members_helper.rb10
-rw-r--r--app/helpers/issuables_description_templates_helper.rb47
-rw-r--r--app/helpers/issuables_helper.rb73
-rw-r--r--app/helpers/jira_connect_helper.rb10
-rw-r--r--app/helpers/labels_helper.rb42
-rw-r--r--app/helpers/learn_gitlab_helper.rb60
-rw-r--r--app/helpers/merge_requests_helper.rb6
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/helpers/notes_helper.rb6
-rw-r--r--app/helpers/notifications_helper.rb9
-rw-r--r--app/helpers/notify_helper.rb26
-rw-r--r--app/helpers/operations_helper.rb2
-rw-r--r--app/helpers/projects/alert_management_helper.rb7
-rw-r--r--app/helpers/projects/project_members_helper.rb26
-rw-r--r--app/helpers/projects_helper.rb37
-rw-r--r--app/helpers/search_helper.rb21
-rw-r--r--app/helpers/services_helper.rb7
-rw-r--r--app/helpers/sorting_helper.rb21
-rw-r--r--app/helpers/sorting_titles_values_helper.rb8
-rw-r--r--app/helpers/stat_anchors_helper.rb4
-rw-r--r--app/helpers/tree_helper.rb45
-rw-r--r--app/helpers/user_callouts_helper.rb5
-rw-r--r--app/helpers/users_helper.rb23
-rw-r--r--app/mailers/emails/in_product_marketing.rb34
-rw-r--r--app/mailers/emails/members.rb2
-rw-r--r--app/mailers/emails/merge_requests.rb7
-rw-r--r--app/mailers/notify.rb2
-rw-r--r--app/models/active_session.rb25
-rw-r--r--app/models/application_setting.rb50
-rw-r--r--app/models/application_setting_implementation.rb17
-rw-r--r--app/models/audit_event.rb9
-rw-r--r--app/models/board.rb8
-rw-r--r--app/models/bulk_imports/entity.rb15
-rw-r--r--app/models/ci/bridge.rb6
-rw-r--r--app/models/ci/build.rb65
-rw-r--r--app/models/ci/build_dependencies.rb2
-rw-r--r--app/models/ci/build_trace_chunk.rb20
-rw-r--r--app/models/ci/build_trace_chunks/fog.rb10
-rw-r--r--app/models/ci/build_trace_section.rb1
-rw-r--r--app/models/ci/daily_build_group_report_result.rb5
-rw-r--r--app/models/ci/job_artifact.rb10
-rw-r--r--app/models/ci/pipeline.rb36
-rw-r--r--app/models/ci/pipeline_artifact.rb25
-rw-r--r--app/models/ci/pipeline_schedule.rb2
-rw-r--r--app/models/ci/processable.rb56
-rw-r--r--app/models/ci/resource.rb6
-rw-r--r--app/models/ci/resource_group.rb10
-rw-r--r--app/models/ci/stage.rb2
-rw-r--r--app/models/clusters/agent.rb1
-rw-r--r--app/models/clusters/agent_token.rb1
-rw-r--r--app/models/clusters/applications/cert_manager.rb2
-rw-r--r--app/models/clusters/applications/crossplane.rb2
-rw-r--r--app/models/clusters/applications/ingress.rb2
-rw-r--r--app/models/clusters/applications/jupyter.rb2
-rw-r--r--app/models/clusters/applications/knative.rb2
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/platforms/kubernetes.rb8
-rw-r--r--app/models/commit.rb2
-rw-r--r--app/models/commit_status.rb34
-rw-r--r--app/models/concerns/analytics/cycle_analytics/stage.rb19
-rw-r--r--app/models/concerns/atomic_internal_id.rb44
-rw-r--r--app/models/concerns/cacheable_attributes.rb2
-rw-r--r--app/models/concerns/can_move_repository_storage.rb21
-rw-r--r--app/models/concerns/enums/ci/pipeline.rb8
-rw-r--r--app/models/concerns/featurable.rb3
-rw-r--r--app/models/concerns/has_repository.rb9
-rw-r--r--app/models/concerns/nullify_if_blank.rb48
-rw-r--r--app/models/concerns/optimized_issuable_label_filter.rb4
-rw-r--r--app/models/concerns/packages/debian/architecture.rb6
-rw-r--r--app/models/concerns/packages/debian/component.rb31
-rw-r--r--app/models/concerns/packages/debian/component_file.rb101
-rw-r--r--app/models/concerns/packages/debian/distribution.rb10
-rw-r--r--app/models/concerns/protected_ref.rb16
-rw-r--r--app/models/concerns/repositories/can_housekeep_repository.rb4
-rw-r--r--app/models/concerns/repository_storage_movable.rb24
-rw-r--r--app/models/concerns/spammable.rb11
-rw-r--r--app/models/concerns/suppress_composite_primary_key_warning.rb19
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encrypted.rb10
-rw-r--r--app/models/concerns/triggerable_hooks.rb3
-rw-r--r--app/models/container_repository.rb1
-rw-r--r--app/models/custom_emoji.rb9
-rw-r--r--app/models/deployment.rb18
-rw-r--r--app/models/deployment_merge_request.rb2
-rw-r--r--app/models/design_management/design.rb11
-rw-r--r--app/models/event.rb6
-rw-r--r--app/models/experiment.rb8
-rw-r--r--app/models/group.rb14
-rw-r--r--app/models/issue.rb2
-rw-r--r--app/models/issue_assignee.rb2
-rw-r--r--app/models/issue_link.rb4
-rw-r--r--app/models/label.rb2
-rw-r--r--app/models/license_template.rb9
-rw-r--r--app/models/merge_request.rb87
-rw-r--r--app/models/merge_request/metrics.rb8
-rw-r--r--app/models/merge_request_context_commit.rb3
-rw-r--r--app/models/merge_request_context_commit_diff_file.rb2
-rw-r--r--app/models/merge_request_diff.rb25
-rw-r--r--app/models/merge_request_diff_commit.rb27
-rw-r--r--app/models/merge_request_diff_file.rb2
-rw-r--r--app/models/merge_request_reviewer.rb9
-rw-r--r--app/models/milestone_release.rb2
-rw-r--r--app/models/namespace.rb57
-rw-r--r--app/models/namespaces/traversal/recursive.rb61
-rw-r--r--app/models/note.rb6
-rw-r--r--app/models/onboarding_progress.rb26
-rw-r--r--app/models/operations/feature_flag.rb26
-rw-r--r--app/models/packages/composer/cache_file.rb23
-rw-r--r--app/models/packages/composer/metadatum.rb3
-rw-r--r--app/models/packages/debian/group_component.rb9
-rw-r--r--app/models/packages/debian/group_component_file.rb9
-rw-r--r--app/models/packages/debian/project_component.rb9
-rw-r--r--app/models/packages/debian/project_component_file.rb9
-rw-r--r--app/models/packages/debian/project_distribution.rb3
-rw-r--r--app/models/packages/debian/publication.rb24
-rw-r--r--app/models/packages/package.rb28
-rw-r--r--app/models/packages/package_file.rb4
-rw-r--r--app/models/packages/rubygems/metadatum.rb24
-rw-r--r--app/models/pages/lookup_path.rb14
-rw-r--r--app/models/pages/virtual_domain.rb11
-rw-r--r--app/models/pages_deployment.rb8
-rw-r--r--app/models/project.rb56
-rw-r--r--app/models/project_authorization.rb1
-rw-r--r--app/models/project_ci_cd_setting.rb5
-rw-r--r--app/models/project_pages_metadatum.rb3
-rw-r--r--app/models/project_services/alerts_service.rb28
-rw-r--r--app/models/project_services/chat_notification_service.rb26
-rw-r--r--app/models/project_services/confluence_service.rb4
-rw-r--r--app/models/project_services/datadog_service.rb40
-rw-r--r--app/models/project_services/jira_service.rb22
-rw-r--r--app/models/project_services/jira_tracker_data.rb9
-rw-r--r--app/models/project_services/mock_deployment_service.rb38
-rw-r--r--app/models/project_setting.rb2
-rw-r--r--app/models/project_statistics.rb1
-rw-r--r--app/models/protected_branch/push_access_level.rb2
-rw-r--r--app/models/push_event_payload.rb2
-rw-r--r--app/models/readme_blob.rb17
-rw-r--r--app/models/release.rb1
-rw-r--r--app/models/repository.rb64
-rw-r--r--app/models/repository_language.rb2
-rw-r--r--app/models/service.rb19
-rw-r--r--app/models/snippet.rb2
-rw-r--r--app/models/terraform/state.rb2
-rw-r--r--app/models/terraform/state_version.rb6
-rw-r--r--app/models/token_with_iv.rb23
-rw-r--r--app/models/u2f_registration.rb16
-rw-r--r--app/models/user.rb34
-rw-r--r--app/models/user_callout.rb20
-rw-r--r--app/models/user_interacted_project.rb2
-rw-r--r--app/models/user_status.rb16
-rw-r--r--app/models/users/user_follow_user.rb7
-rw-r--r--app/models/vulnerability.rb10
-rw-r--r--app/models/wiki.rb11
-rw-r--r--app/policies/application_setting_policy.rb5
-rw-r--r--app/policies/event_policy.rb9
-rw-r--r--app/policies/project_policy.rb17
-rw-r--r--app/presenters/ci/build_presenter.rb2
-rw-r--r--app/presenters/ci/build_runner_presenter.rb18
-rw-r--r--app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb2
-rw-r--r--app/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter.rb25
-rw-r--r--app/presenters/ci/pipeline_presenter.rb3
-rw-r--r--app/presenters/dev_ops_report/metric_presenter.rb (renamed from app/presenters/dev_ops_score/metric_presenter.rb)0
-rw-r--r--app/presenters/gitlab/whats_new/item_presenter.rb22
-rw-r--r--app/presenters/project_presenter.rb4
-rw-r--r--app/serializers/README.md2
-rw-r--r--app/serializers/admin/user_entity.rb1
-rw-r--r--app/serializers/admin/user_serializer.rb2
-rw-r--r--app/serializers/base_discussion_entity.rb1
-rw-r--r--app/serializers/build_details_entity.rb2
-rw-r--r--app/serializers/ci/codequality_mr_diff_entity.rb7
-rw-r--r--app/serializers/ci/codequality_mr_diff_report_serializer.rb7
-rw-r--r--app/serializers/ci/pipeline_entity.rb124
-rw-r--r--app/serializers/concerns/user_status_tooltip.rb4
-rw-r--r--app/serializers/diff_file_metadata_entity.rb1
-rw-r--r--app/serializers/diffs_entity.rb4
-rw-r--r--app/serializers/group_child_entity.rb2
-rw-r--r--app/serializers/group_group_link_entity.rb50
-rw-r--r--app/serializers/group_group_link_serializer.rb5
-rw-r--r--app/serializers/group_link/group_group_link_entity.rb25
-rw-r--r--app/serializers/group_link/group_group_link_serializer.rb7
-rw-r--r--app/serializers/group_link/group_link_entity.rb34
-rw-r--r--app/serializers/group_link/project_group_link_entity.rb22
-rw-r--r--app/serializers/group_link/project_group_link_serializer.rb7
-rw-r--r--app/serializers/member_entity.rb4
-rw-r--r--app/serializers/merge_request_basic_entity.rb2
-rw-r--r--app/serializers/merge_request_sidebar_extras_entity.rb8
-rw-r--r--app/serializers/merge_request_user_entity.rb13
-rw-r--r--app/serializers/merge_request_widget_entity.rb4
-rw-r--r--app/serializers/pipeline_details_entity.rb2
-rw-r--r--app/serializers/pipeline_entity.rb122
-rw-r--r--app/services/alert_management/http_integrations/update_service.rb15
-rw-r--r--app/services/alert_management/process_prometheus_alert_service.rb121
-rw-r--r--app/services/application_settings/update_service.rb2
-rw-r--r--app/services/authorized_project_update/recalculate_for_user_range_service.rb2
-rw-r--r--app/services/boards/create_service.rb8
-rw-r--r--app/services/boards/list_service.rb8
-rw-r--r--app/services/boards/lists/base_create_service.rb71
-rw-r--r--app/services/boards/lists/create_service.rb63
-rw-r--r--app/services/boards/visits/create_service.rb1
-rw-r--r--app/services/bulk_create_integration_service.rb10
-rw-r--r--app/services/bulk_import_service.rb2
-rw-r--r--app/services/captcha/captcha_verification_service.rb43
-rw-r--r--app/services/ci/create_job_artifacts_service.rb9
-rw-r--r--app/services/ci/create_pipeline_service.rb1
-rw-r--r--app/services/ci/daily_build_group_report_result_service.rb3
-rw-r--r--app/services/ci/generate_codequality_mr_diff_report_service.rb30
-rw-r--r--app/services/ci/generate_coverage_reports_service.rb2
-rw-r--r--app/services/ci/pipeline_artifacts/coverage_report_service.rb2
-rw-r--r--app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb38
-rw-r--r--app/services/ci/pipeline_trigger_service.rb17
-rw-r--r--app/services/ci/process_build_service.rb2
-rw-r--r--app/services/ci/process_pipeline_service.rb13
-rw-r--r--app/services/ci/prometheus_metrics/observe_histograms_service.rb57
-rw-r--r--app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb4
-rw-r--r--app/services/clusters/kubernetes/configure_istio_ingress_service.rb2
-rw-r--r--app/services/concerns/alert_management/alert_processing.rb133
-rw-r--r--app/services/concerns/integrations/project_test_data.rb22
-rw-r--r--app/services/concerns/spam_check_methods.rb39
-rw-r--r--app/services/concerns/update_repository_storage_methods.rb19
-rw-r--r--app/services/container_expiration_policies/cleanup_service.rb15
-rw-r--r--app/services/deployments/create_service.rb8
-rw-r--r--app/services/design_management/move_designs_service.rb7
-rw-r--r--app/services/discussions/resolve_service.rb8
-rw-r--r--app/services/discussions/unresolve_service.rb21
-rw-r--r--app/services/draft_notes/publish_service.rb6
-rw-r--r--app/services/feature_flags/base_service.rb1
-rw-r--r--app/services/git/branch_hooks_service.rb44
-rw-r--r--app/services/git/wiki_push_service.rb9
-rw-r--r--app/services/groups/import_export/export_service.rb56
-rw-r--r--app/services/groups/import_export/import_service.rb52
-rw-r--r--app/services/groups/open_issues_count_service.rb64
-rw-r--r--app/services/issuable_base_service.rb29
-rw-r--r--app/services/issue_rebalancing_service.rb37
-rw-r--r--app/services/issues/close_service.rb2
-rw-r--r--app/services/issues/create_service.rb16
-rw-r--r--app/services/issues/update_service.rb17
-rw-r--r--app/services/jira/requests/base.rb8
-rw-r--r--app/services/members/update_service.rb6
-rw-r--r--app/services/merge_requests/add_context_service.rb3
-rw-r--r--app/services/merge_requests/approval_service.rb1
-rw-r--r--app/services/merge_requests/base_service.rb2
-rw-r--r--app/services/merge_requests/build_service.rb48
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb1
-rw-r--r--app/services/merge_requests/mark_reviewer_reviewed_service.rb19
-rw-r--r--app/services/merge_requests/merge_service.rb6
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb6
-rw-r--r--app/services/merge_requests/post_merge_service.rb31
-rw-r--r--app/services/merge_requests/reload_merge_head_diff_service.rb50
-rw-r--r--app/services/merge_requests/remove_approval_service.rb1
-rw-r--r--app/services/merge_requests/request_review_service.rb28
-rw-r--r--app/services/merge_requests/update_service.rb59
-rw-r--r--app/services/namespaces/in_product_marketing_emails_service.rb112
-rw-r--r--app/services/notes/create_service.rb13
-rw-r--r--app/services/notification_recipients/build_service.rb4
-rw-r--r--app/services/notification_recipients/builder/request_review.rb21
-rw-r--r--app/services/notification_service.rb12
-rw-r--r--app/services/packages/create_package_service.rb7
-rw-r--r--app/services/packages/debian/create_distribution_service.rb75
-rw-r--r--app/services/packages/debian/destroy_distribution_service.rb33
-rw-r--r--app/services/packages/debian/update_distribution_service.rb80
-rw-r--r--app/services/packages/generic/create_package_file_service.rb5
-rw-r--r--app/services/packages/maven/find_or_create_package_service.rb19
-rw-r--r--app/services/pages/delete_service.rb8
-rw-r--r--app/services/pages/migrate_from_legacy_storage_service.rb79
-rw-r--r--app/services/pages/migrate_legacy_storage_to_deployment_service.rb5
-rw-r--r--app/services/pages/zip_directory_service.rb53
-rw-r--r--app/services/projects/alerting/notify_service.rb94
-rw-r--r--app/services/projects/branches_by_mode_service.rb88
-rw-r--r--app/services/projects/cleanup_service.rb2
-rw-r--r--app/services/projects/container_repository/cleanup_tags_service.rb1
-rw-r--r--app/services/projects/create_service.rb20
-rw-r--r--app/services/projects/fork_service.rb11
-rw-r--r--app/services/projects/import_export/export_service.rb6
-rw-r--r--app/services/projects/update_pages_service.rb4
-rw-r--r--app/services/projects/update_service.rb18
-rw-r--r--app/services/quick_actions/interpret_service.rb9
-rw-r--r--app/services/repositories/changelog_service.rb115
-rw-r--r--app/services/repositories/housekeeping_service.rb2
-rw-r--r--app/services/resource_access_tokens/create_service.rb9
-rw-r--r--app/services/resource_access_tokens/revoke_service.rb8
-rw-r--r--app/services/resource_events/base_change_timebox_service.rb7
-rw-r--r--app/services/resource_events/change_milestone_service.rb4
-rw-r--r--app/services/security/ci_configuration/sast_create_service.rb66
-rw-r--r--app/services/security/ci_configuration/sast_parser_service.rb127
-rw-r--r--app/services/snippets/base_service.rb4
-rw-r--r--app/services/snippets/create_service.rb22
-rw-r--r--app/services/snippets/update_service.rb19
-rw-r--r--app/services/spam/spam_action_service.rb93
-rw-r--r--app/services/spam/spam_params.rb32
-rw-r--r--app/services/suggestions/apply_service.rb8
-rw-r--r--app/services/suggestions/create_service.rb2
-rw-r--r--app/services/system_hooks_service.rb36
-rw-r--r--app/services/system_note_service.rb11
-rw-r--r--app/services/system_notes/merge_requests_service.rb20
-rw-r--r--app/services/terraform/remote_state_handler.rb22
-rw-r--r--app/services/test_hooks/system_service.rb3
-rw-r--r--app/services/todo_service.rb8
-rw-r--r--app/services/users/approve_service.rb8
-rw-r--r--app/services/users/batch_status_cleaner_service.rb22
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb14
-rw-r--r--app/services/users/reject_service.rb14
-rw-r--r--app/uploaders/packages/composer/cache_uploader.rb26
-rw-r--r--app/uploaders/packages/debian/component_file_uploader.rb27
-rw-r--r--app/uploaders/terraform/state_uploader.rb4
-rw-r--r--app/validators/json_schemas/application_setting_kroki_formats.json10
-rw-r--r--app/validators/json_schemas/git_trailers.json9
-rw-r--r--app/validators/nested_attributes_duplicates_validator.rb40
-rw-r--r--app/validators/variable_duplicates_validator.rb34
-rw-r--r--app/views/abuse_reports/new.html.haml2
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml2
-rw-r--r--app/views/admin/appearances/_form.html.haml8
-rw-r--r--app/views/admin/appearances/_system_header_footer_form.html.haml8
-rw-r--r--app/views/admin/appearances/preview_sign_in.html.haml4
-rw-r--r--app/views/admin/application_settings/_abuse.html.haml2
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml16
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml26
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_eks.html.haml6
-rw-r--r--app/views/admin/application_settings/_email.html.haml2
-rw-r--r--app/views/admin/application_settings/_external_authorization_service_form.html.haml14
-rw-r--r--app/views/admin/application_settings/_gitaly.html.haml6
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml2
-rw-r--r--app/views/admin/application_settings/_grafana.html.haml2
-rw-r--r--app/views/admin/application_settings/_help_page.html.haml6
-rw-r--r--app/views/admin/application_settings/_import_export_limits.html.haml12
-rw-r--r--app/views/admin/application_settings/_initial_branch_name.html.haml2
-rw-r--r--app/views/admin/application_settings/_ip_limits.html.haml14
-rw-r--r--app/views/admin/application_settings/_issue_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_kroki.html.haml10
-rw-r--r--app/views/admin/application_settings/_note_limits.html.haml12
-rw-r--r--app/views/admin/application_settings/_outbound.html.haml2
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml12
-rw-r--r--app/views/admin/application_settings/_pages.html.haml4
-rw-r--r--app/views/admin/application_settings/_performance.html.haml6
-rw-r--r--app/views/admin/application_settings/_performance_bar.html.haml2
-rw-r--r--app/views/admin/application_settings/_plantuml.html.haml2
-rw-r--r--app/views/admin/application_settings/_prometheus.html.haml2
-rw-r--r--app/views/admin/application_settings/_protected_paths.html.haml6
-rw-r--r--app/views/admin/application_settings/_realtime.html.haml2
-rw-r--r--app/views/admin/application_settings/_registry.html.haml16
-rw-r--r--app/views/admin/application_settings/_repository_check.html.haml6
-rw-r--r--app/views/admin/application_settings/_repository_static_objects.html.haml4
-rw-r--r--app/views/admin/application_settings/_signin.html.haml8
-rw-r--r--app/views/admin/application_settings/_signup.html.haml12
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml6
-rw-r--r--app/views/admin/application_settings/_sourcegraph.html.haml2
-rw-r--r--app/views/admin/application_settings/_spam.html.haml12
-rw-r--r--app/views/admin/application_settings/_terminal.html.haml2
-rw-r--r--app/views/admin/application_settings/_terms.html.haml2
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml8
-rw-r--r--app/views/admin/application_settings/ci/_header.html.haml15
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml2
-rw-r--r--app/views/admin/application_settings/general.html.haml1
-rw-r--r--app/views/admin/application_settings/integrations.html.haml4
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml2
-rw-r--r--app/views/admin/application_settings/network.html.haml11
-rw-r--r--app/views/admin/application_settings/preferences.html.haml12
-rw-r--r--app/views/admin/application_settings/reporting.html.haml4
-rw-r--r--app/views/admin/application_settings/repository.html.haml10
-rw-r--r--app/views/admin/applications/_form.html.haml6
-rw-r--r--app/views/admin/applications/index.html.haml53
-rw-r--r--app/views/admin/applications/show.html.haml4
-rw-r--r--app/views/admin/broadcast_messages/_form.html.haml8
-rw-r--r--app/views/admin/cohorts/index.html.haml7
-rw-r--r--app/views/admin/dashboard/index.html.haml118
-rw-r--r--app/views/admin/groups/_form.html.haml2
-rw-r--r--app/views/admin/groups/_group.html.haml4
-rw-r--r--app/views/admin/hooks/_form.html.haml19
-rw-r--r--app/views/admin/jobs/index.html.haml1
-rw-r--r--app/views/admin/labels/_form.html.haml6
-rw-r--r--app/views/admin/projects/_projects.html.haml4
-rw-r--r--app/views/admin/projects/index.html.haml2
-rw-r--r--app/views/admin/projects/show.html.haml4
-rw-r--r--app/views/admin/runners/index.html.haml6
-rw-r--r--app/views/admin/users/_access_levels.html.haml2
-rw-r--r--app/views/admin/users/_admin_notes.html.haml2
-rw-r--r--app/views/admin/users/_cohorts.html.haml4
-rw-r--r--app/views/admin/users/_cohorts_table.html.haml (renamed from app/views/admin/cohorts/_cohorts_table.html.haml)0
-rw-r--r--app/views/admin/users/_form.html.haml18
-rw-r--r--app/views/admin/users/_head.html.haml3
-rw-r--r--app/views/admin/users/_user.html.haml4
-rw-r--r--app/views/admin/users/_user_detail.html.haml7
-rw-r--r--app/views/admin/users/_users.html.haml88
-rw-r--r--app/views/admin/users/index.html.haml99
-rw-r--r--app/views/admin/users/show.html.haml42
-rw-r--r--app/views/authentication/_authenticate.html.haml2
-rw-r--r--app/views/authentication/_register.html.haml6
-rw-r--r--app/views/ci/group_variables/_content.html.haml2
-rw-r--r--app/views/ci/group_variables/_index.html.haml21
-rw-r--r--app/views/ci/group_variables/_variable_header.html.haml8
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml2
-rw-r--r--app/views/ci/variables/_content.html.haml12
-rw-r--r--app/views/ci/variables/_header.html.haml3
-rw-r--r--app/views/ci/variables/_index.html.haml2
-rw-r--r--app/views/dashboard/_activity_head.html.haml7
-rw-r--r--app/views/dashboard/issues.atom.builder2
-rw-r--r--app/views/dashboard/milestones/index.html.haml13
-rw-r--r--app/views/dashboard/projects/_starred_empty_state.html.haml4
-rw-r--r--app/views/dashboard/projects/index.atom.builder2
-rw-r--r--app/views/dashboard/projects/index.html.haml2
-rw-r--r--app/views/dashboard/todos/_todo.html.haml6
-rw-r--r--app/views/dashboard/todos/index.html.haml4
-rw-r--r--app/views/devise/confirmations/new.html.haml2
-rw-r--r--app/views/devise/passwords/edit.html.haml6
-rw-r--r--app/views/devise/passwords/new.html.haml5
-rw-r--r--app/views/devise/sessions/_new_base.html.haml4
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml6
-rw-r--r--app/views/devise/sessions/two_factor.html.haml2
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml2
-rw-r--r--app/views/devise/shared/_signup_box.html.haml10
-rw-r--r--app/views/devise/shared/_signup_omniauth_provider_list.haml2
-rw-r--r--app/views/discussions/_notes.html.haml2
-rw-r--r--app/views/doorkeeper/applications/_delete_form.html.haml2
-rw-r--r--app/views/doorkeeper/applications/_form.html.haml4
-rw-r--r--app/views/doorkeeper/applications/index.html.haml4
-rw-r--r--app/views/doorkeeper/applications/show.html.haml4
-rw-r--r--app/views/events/_event.atom.builder2
-rw-r--r--app/views/groups/_home_panel.html.haml6
-rw-r--r--app/views/groups/_import_group_from_another_instance_panel.html.haml13
-rw-r--r--app/views/groups/_invite_members_modal.html.haml2
-rw-r--r--app/views/groups/_invite_members_side_nav_link.html.haml3
-rw-r--r--app/views/groups/_new_group_fields.html.haml4
-rw-r--r--app/views/groups/edit.html.haml1
-rw-r--r--app/views/groups/group_members/index.html.haml8
-rw-r--r--app/views/groups/issues.atom.builder2
-rw-r--r--app/views/groups/milestones/index.html.haml15
-rw-r--r--app/views/groups/projects.html.haml8
-rw-r--r--app/views/groups/registry/repositories/index.html.haml7
-rw-r--r--app/views/groups/runners/_group_runners.html.haml4
-rw-r--r--app/views/groups/runners/_runner.html.haml5
-rw-r--r--app/views/groups/settings/_advanced.html.haml4
-rw-r--r--app/views/groups/settings/_export.html.haml6
-rw-r--r--app/views/groups/settings/_general.html.haml2
-rw-r--r--app/views/groups/settings/_pages_settings.html.haml2
-rw-r--r--app/views/groups/settings/_permanent_deletion.html.haml2
-rw-r--r--app/views/groups/settings/_permissions.html.haml2
-rw-r--r--app/views/groups/settings/ci_cd/_auto_devops_form.html.haml2
-rw-r--r--app/views/groups/settings/ci_cd/_form.html.haml6
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/groups/settings/packages_and_registries/index.html.haml2
-rw-r--r--app/views/groups/settings/repository/_initial_branch_name.html.haml2
-rw-r--r--app/views/groups/show.atom.builder2
-rw-r--r--app/views/groups/show.html.haml7
-rw-r--r--app/views/groups/sidebar/_packages_settings.html.haml5
-rw-r--r--app/views/help/_shortcuts.html.haml347
-rw-r--r--app/views/help/shortcuts.js.haml3
-rw-r--r--app/views/import/bulk_imports/status.html.haml8
-rw-r--r--app/views/issues/_issue.atom.builder2
-rw-r--r--app/views/issues/_issues_calendar.ics.ruby2
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml24
-rw-r--r--app/views/layouts/_head.html.haml3
-rw-r--r--app/views/layouts/_matomo.html.haml1
-rw-r--r--app/views/layouts/_page.html.haml3
-rw-r--r--app/views/layouts/_startup_css.haml2
-rw-r--r--app/views/layouts/admin.html.haml5
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml27
-rw-r--r--app/views/layouts/header/_current_user_dropdown_item.html.haml12
-rw-r--r--app/views/layouts/header/_default.html.haml42
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_whats_new_dropdown_item.html.haml5
-rw-r--r--app/views/layouts/jira_connect.html.haml1
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml10
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml30
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml37
-rw-r--r--app/views/layouts/nav/sidebar/_project_security_link.html.haml21
-rw-r--r--app/views/layouts/profile.html.haml1
-rw-r--r--app/views/layouts/signup_onboarding.html.haml (renamed from app/views/layouts/devise_experimental_onboarding_issues.html.haml)0
-rw-r--r--app/views/layouts/welcome.html.haml4
-rw-r--r--app/views/layouts/xml.atom.builder2
-rw-r--r--app/views/notify/in_product_marketing_email.html.haml204
-rw-r--r--app/views/notify/in_product_marketing_email.text.erb23
-rw-r--r--app/views/notify/member_invited_email.html.haml50
-rw-r--r--app/views/notify/provisioned_member_access_granted_email.erb14
-rw-r--r--app/views/notify/provisioned_member_access_granted_email.haml24
-rw-r--r--app/views/notify/provisioned_member_access_granted_email.html.haml25
-rw-r--r--app/views/notify/provisioned_member_access_granted_email.text.erb15
-rw-r--r--app/views/notify/request_review_merge_request_email.html.haml2
-rw-r--r--app/views/notify/request_review_merge_request_email.text.erb1
-rw-r--r--app/views/profiles/_email_settings.html.haml2
-rw-r--r--app/views/profiles/_name.html.haml4
-rw-r--r--app/views/profiles/accounts/_providers.html.haml24
-rw-r--r--app/views/profiles/accounts/show.html.haml25
-rw-r--r--app/views/profiles/emails/index.html.haml16
-rw-r--r--app/views/profiles/keys/_key.html.haml61
-rw-r--r--app/views/profiles/keys/_key_details.html.haml2
-rw-r--r--app/views/profiles/keys/index.html.haml4
-rw-r--r--app/views/profiles/notifications/_email_settings.html.haml4
-rw-r--r--app/views/profiles/notifications/_group_settings.html.haml6
-rw-r--r--app/views/profiles/notifications/_project_settings.html.haml6
-rw-r--r--app/views/profiles/notifications/show.html.haml6
-rw-r--r--app/views/profiles/passwords/edit.html.haml6
-rw-r--r--app/views/profiles/passwords/new.html.haml6
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml23
-rw-r--r--app/views/profiles/preferences/show.html.haml21
-rw-r--r--app/views/profiles/preferences/update.js.erb20
-rw-r--r--app/views/profiles/show.html.haml76
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml5
-rw-r--r--app/views/projects/_activity.html.haml23
-rw-r--r--app/views/projects/_export.html.haml36
-rw-r--r--app/views/projects/_files.html.haml2
-rw-r--r--app/views/projects/_find_file_link.html.haml2
-rw-r--r--app/views/projects/_fork_suggestion.html.haml21
-rw-r--r--app/views/projects/_home_panel.html.haml10
-rw-r--r--app/views/projects/_import_project_pane.html.haml2
-rw-r--r--app/views/projects/_invite_members_link.html.haml4
-rw-r--r--app/views/projects/_invite_members_modal.html.haml2
-rw-r--r--app/views/projects/_invite_members_side_nav_link.html.haml3
-rw-r--r--app/views/projects/_issuable_by_email.html.haml49
-rw-r--r--app/views/projects/_last_push.html.haml2
-rw-r--r--app/views/projects/_merge_request_merge_checks_settings.html.haml1
-rw-r--r--app/views/projects/_merge_request_merge_options_settings.html.haml2
-rw-r--r--app/views/projects/_merge_request_merge_suggestions_settings.html.haml2
-rw-r--r--app/views/projects/_merge_request_settings.html.haml3
-rw-r--r--app/views/projects/_new_project_fields.html.haml7
-rw-r--r--app/views/projects/_new_project_push_tip.html.haml2
-rw-r--r--app/views/projects/_project_templates.html.haml6
-rw-r--r--app/views/projects/_remove.html.haml3
-rw-r--r--app/views/projects/_remove_fork.html.haml1
-rw-r--r--app/views/projects/_service_desk_settings.html.haml2
-rw-r--r--app/views/projects/_stat_anchor_list.html.haml2
-rw-r--r--app/views/projects/_transfer.html.haml9
-rw-r--r--app/views/projects/_visibility_modal.html.haml4
-rw-r--r--app/views/projects/_wiki.html.haml2
-rw-r--r--app/views/projects/artifacts/_artifact.html.haml12
-rw-r--r--app/views/projects/blob/_breadcrumb.html.haml8
-rw-r--r--app/views/projects/blob/_editor.html.haml6
-rw-r--r--app/views/projects/blob/_header.html.haml8
-rw-r--r--app/views/projects/blob/_viewer_switcher.html.haml6
-rw-r--r--app/views/projects/branches/_branch.html.haml22
-rw-r--r--app/views/projects/branches/index.html.haml5
-rw-r--r--app/views/projects/buttons/_clone.html.haml17
-rw-r--r--app/views/projects/buttons/_download.html.haml2
-rw-r--r--app/views/projects/buttons/_download_links.html.haml2
-rw-r--r--app/views/projects/buttons/_fork.html.haml10
-rw-r--r--app/views/projects/buttons/_remove_tag.html.haml2
-rw-r--r--app/views/projects/buttons/_xcode_link.html.haml2
-rw-r--r--app/views/projects/ci/builds/_build.html.haml44
-rw-r--r--app/views/projects/cleanup/_show.html.haml7
-rw-r--r--app/views/projects/commit/_change.html.haml31
-rw-r--r--app/views/projects/commit/_commit_box.html.haml14
-rw-r--r--app/views/projects/commit/_commit_modal.html.haml26
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml2
-rw-r--r--app/views/projects/commit/pipelines.html.haml4
-rw-r--r--app/views/projects/commit/show.html.haml6
-rw-r--r--app/views/projects/commits/_commit.atom.builder2
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/commits/show.atom.builder2
-rw-r--r--app/views/projects/commits/show.html.haml4
-rw-r--r--app/views/projects/compare/_form.html.haml3
-rw-r--r--app/views/projects/compare/index.html.haml6
-rw-r--r--app/views/projects/default_branch/_show.html.haml8
-rw-r--r--app/views/projects/deployments/_rollback.haml6
-rw-r--r--app/views/projects/diffs/_diffs.html.haml7
-rw-r--r--app/views/projects/diffs/_file.html.haml4
-rw-r--r--app/views/projects/diffs/viewers/_collapsed.html.haml4
-rw-r--r--app/views/projects/edit.html.haml39
-rw-r--r--app/views/projects/empty.html.haml3
-rw-r--r--app/views/projects/environments/index.html.haml1
-rw-r--r--app/views/projects/forks/new.html.haml2
-rw-r--r--app/views/projects/graphs/charts.html.haml4
-rw-r--r--app/views/projects/graphs/show.html.haml2
-rw-r--r--app/views/projects/issues/_new_branch.html.haml6
-rw-r--r--app/views/projects/issues/import_csv/_button.html.haml2
-rw-r--r--app/views/projects/issues/index.atom.builder2
-rw-r--r--app/views/projects/issues/index.html.haml4
-rw-r--r--app/views/projects/jobs/_table.html.haml4
-rw-r--r--app/views/projects/jobs/index.html.haml3
-rw-r--r--app/views/projects/learn_gitlab/index.html.haml4
-rw-r--r--app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml2
-rw-r--r--app/views/projects/merge_requests/_commits.html.haml2
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml10
-rw-r--r--app/views/projects/merge_requests/conflicts/_submit_form.html.haml2
-rw-r--r--app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml4
-rw-r--r--app/views/projects/merge_requests/index.html.haml4
-rw-r--r--app/views/projects/merge_requests/show.html.haml13
-rw-r--r--app/views/projects/merge_requests/widget/_commit_change_content.html.haml4
-rw-r--r--app/views/projects/milestones/_form.html.haml4
-rw-r--r--app/views/projects/milestones/index.html.haml19
-rw-r--r--app/views/projects/mirrors/_authentication_method.html.haml4
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos_form.html.haml2
-rw-r--r--app/views/projects/network/show.html.haml6
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/no_repo.html.haml8
-rw-r--r--app/views/projects/notes/_actions.html.haml14
-rw-r--r--app/views/projects/notes/_more_actions_dropdown.html.haml7
-rw-r--r--app/views/projects/pages/_use.html.haml7
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml4
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml8
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml2
-rw-r--r--app/views/projects/pipelines/_info.html.haml3
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml18
-rw-r--r--app/views/projects/pipelines/show.html.haml2
-rw-r--r--app/views/projects/project_members/index.html.haml55
-rw-r--r--app/views/projects/protected_branches/_create_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_branches/shared/_index.html.haml2
-rw-r--r--app/views/projects/protected_branches/shared/_protected_branch.html.haml4
-rw-r--r--app/views/projects/protected_tags/shared/_index.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_tags_list.html.haml1
-rw-r--r--app/views/projects/registry/repositories/index.html.haml7
-rw-r--r--app/views/projects/runners/_group_runners.html.haml4
-rw-r--r--app/views/projects/runners/_runner.html.haml14
-rw-r--r--app/views/projects/runners/_shared_runners.html.haml4
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml8
-rw-r--r--app/views/projects/security/configuration/show.html.haml4
-rw-r--r--app/views/projects/services/_form.html.haml19
-rw-r--r--app/views/projects/services/prometheus/_top.html.haml2
-rw-r--r--app/views/projects/settings/_archive.html.haml10
-rw-r--r--app/views/projects/settings/_general.html.haml12
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml151
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml27
-rw-r--r--app/views/projects/settings/integrations/show.html.haml2
-rw-r--r--app/views/projects/settings/operations/_alert_management.html.haml2
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml2
-rw-r--r--app/views/projects/settings/operations/_tracing.html.haml4
-rw-r--r--app/views/projects/show.atom.builder2
-rw-r--r--app/views/projects/show.html.haml3
-rw-r--r--app/views/projects/tags/_tag.atom.builder2
-rw-r--r--app/views/projects/tags/_tag.html.haml2
-rw-r--r--app/views/projects/tags/index.atom.builder2
-rw-r--r--app/views/projects/tags/index.html.haml4
-rw-r--r--app/views/projects/tags/releases/edit.html.haml4
-rw-r--r--app/views/projects/tags/show.html.haml8
-rw-r--r--app/views/projects/tree/_readme.html.haml10
-rw-r--r--app/views/projects/tree/_tree_content.html.haml24
-rw-r--r--app/views/projects/tree/_tree_header.html.haml5
-rw-r--r--app/views/projects/tree/_tree_row.html.haml27
-rw-r--r--app/views/projects/tree/_truncated_notice_tree_row.html.haml7
-rw-r--r--app/views/projects/triggers/_form.html.haml2
-rw-r--r--app/views/projects/triggers/_index.html.haml71
-rw-r--r--app/views/registrations/welcome/show.html.haml11
-rw-r--r--app/views/search/_filter.html.haml14
-rw-r--r--app/views/search/_form.html.haml20
-rw-r--r--app/views/search/_results.html.haml4
-rw-r--r--app/views/search/_results_status.html.haml6
-rw-r--r--app/views/search/_sort_dropdown.html.haml14
-rw-r--r--app/views/search/opensearch.xml.erb9
-rw-r--r--app/views/search/results/_issuable.html.haml2
-rw-r--r--app/views/search/show.html.haml7
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml2
-rw-r--r--app/views/shared/_auto_devops_callout.html.haml2
-rw-r--r--app/views/shared/_commit_message_container.html.haml2
-rw-r--r--app/views/shared/_email_with_badge.html.haml4
-rw-r--r--app/views/shared/_file_picker_button.html.haml2
-rw-r--r--app/views/shared/_issuable_meta_data.html.haml8
-rw-r--r--app/views/shared/_label.html.haml8
-rw-r--r--app/views/shared/_milestone_expired.html.haml6
-rw-r--r--app/views/shared/_new_commit_form.html.haml2
-rw-r--r--app/views/shared/_no_ssh.html.haml2
-rw-r--r--app/views/shared/_project_limit.html.haml2
-rw-r--r--app/views/shared/_search_settings.html.haml6
-rw-r--r--app/views/shared/_service_settings.html.haml15
-rw-r--r--app/views/shared/access_tokens/_form.html.haml2
-rw-r--r--app/views/shared/access_tokens/_table.html.haml2
-rw-r--r--app/views/shared/boards/_show.html.haml5
-rw-r--r--app/views/shared/boards/components/_sidebar.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_assignee.html.haml36
-rw-r--r--app/views/shared/deploy_keys/_form.html.haml12
-rw-r--r--app/views/shared/deploy_keys/_index.html.haml6
-rw-r--r--app/views/shared/deploy_keys/_project_group_form.html.haml12
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml25
-rw-r--r--app/views/shared/deploy_tokens/_index.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_new_deploy_token.html.haml12
-rw-r--r--app/views/shared/deploy_tokens/_table.html.haml2
-rw-r--r--app/views/shared/empty_states/_deploy_keys.html.haml4
-rw-r--r--app/views/shared/empty_states/_issues.html.haml2
-rw-r--r--app/views/shared/empty_states/_milestones.html.haml7
-rw-r--r--app/views/shared/empty_states/_profile_tabs.html.haml5
-rw-r--r--app/views/shared/empty_states/_snippets.html.haml4
-rw-r--r--app/views/shared/integrations/_form.html.haml11
-rw-r--r--app/views/shared/issuable/_board_create_list_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/_bulk_update_sidebar.html.haml29
-rw-r--r--app/views/shared/issuable/_feed_buttons.html.haml4
-rw-r--r--app/views/shared/issuable/_form.html.haml8
-rw-r--r--app/views/shared/issuable/_label_page_create.html.haml4
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml11
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml6
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar_todo.html.haml4
-rw-r--r--app/views/shared/issuable/csv_export/_button.html.haml2
-rw-r--r--app/views/shared/issuable/form/_template_selector.html.haml4
-rw-r--r--app/views/shared/issuable/form/_title.html.haml2
-rw-r--r--app/views/shared/issue_type/_details_header.html.haml8
-rw-r--r--app/views/shared/milestones/_labels_tab.html.haml4
-rw-r--r--app/views/shared/milestones/_milestone.html.haml4
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml2
-rw-r--r--app/views/shared/notes/_comment_button.html.haml8
-rw-r--r--app/views/shared/notes/_edit_form.html.haml6
-rw-r--r--app/views/shared/notes/_form.html.haml2
-rw-r--r--app/views/shared/notes/_notes_with_form.html.haml3
-rw-r--r--app/views/shared/notifications/_new_button.html.haml6
-rw-r--r--app/views/shared/projects/protected_branches/_update_protected_branch.html.haml4
-rw-r--r--app/views/shared/ssh_keys/_key_delete.html.haml6
-rw-r--r--app/views/shared/users/_user.html.haml13
-rw-r--r--app/views/shared/users/index.html.haml20
-rw-r--r--app/views/shared/web_hooks/_form.html.haml49
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml4
-rw-r--r--app/views/shared/web_hooks/_test_button.html.haml2
-rw-r--r--app/views/shared/wikis/_sidebar.html.haml2
-rw-r--r--app/views/users/show.atom.builder2
-rw-r--r--app/views/users/show.html.haml49
-rw-r--r--app/workers/all_queues.yml71
-rw-r--r--app/workers/authorized_projects_worker.rb2
-rw-r--r--app/workers/build_coverage_worker.rb14
-rw-r--r--app/workers/build_finished_worker.rb6
-rw-r--r--app/workers/build_hooks_worker.rb3
-rw-r--r--app/workers/build_trace_sections_worker.rb14
-rw-r--r--app/workers/bulk_import_worker.rb4
-rw-r--r--app/workers/bulk_imports/entity_worker.rb10
-rw-r--r--app/workers/ci/build_report_result_worker.rb18
-rw-r--r--app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb20
-rw-r--r--app/workers/concerns/git_garbage_collect_methods.rb135
-rw-r--r--app/workers/container_expiration_policies/cleanup_container_repository_worker.rb5
-rw-r--r--app/workers/git_garbage_collect_worker.rb118
-rw-r--r--app/workers/issuable_export_csv_worker.rb25
-rw-r--r--app/workers/jira_connect/sync_builds_worker.rb1
-rw-r--r--app/workers/jira_connect/sync_deployments_worker.rb1
-rw-r--r--app/workers/jira_connect/sync_feature_flags_worker.rb1
-rw-r--r--app/workers/merge_request_cleanup_refs_worker.rb2
-rw-r--r--app/workers/namespaces/in_product_marketing_emails_worker.rb17
-rw-r--r--app/workers/packages/composer/cache_cleanup_worker.rb30
-rw-r--r--app/workers/pages_remove_worker.rb4
-rw-r--r--app/workers/pages_transfer_worker.rb2
-rw-r--r--app/workers/pipeline_hooks_worker.rb3
-rw-r--r--app/workers/post_receive.rb2
-rw-r--r--app/workers/projects/git_garbage_collect_worker.rb37
-rw-r--r--app/workers/schedule_merge_request_cleanup_refs_worker.rb1
-rw-r--r--app/workers/user_status_cleanup/batch_worker.rb33
-rw-r--r--app/workers/wikis/git_garbage_collect_worker.rb20
-rw-r--r--babel.config.js18
-rwxr-xr-xbin/secpick16
-rw-r--r--changelogs/archive-12.md2
-rw-r--r--changelogs/unreleased/14615-remove-compare-swap-revision.yml5
-rw-r--r--changelogs/unreleased/15013-fork-to-different-name.yml5
-rw-r--r--changelogs/unreleased/16827-escape-markdown-avoid-namespace-pollution.yml5
-rw-r--r--changelogs/unreleased/18292-project-name-to-path-conversion-in-api-mangles-dots.yml5
-rw-r--r--changelogs/unreleased/196628-move-number-of-changed-files-into-web-ide-sidebar-badge.yml5
-rw-r--r--changelogs/unreleased/196835-fix-epic-feed.yml5
-rw-r--r--changelogs/unreleased/207385-services-unique-constraint-on-type.yml5
-rw-r--r--changelogs/unreleased/207385-simplify-service-uniqueness-validations.yml5
-rw-r--r--changelogs/unreleased/207473-allow-set-confidential-note-attribute.yml5
-rw-r--r--changelogs/unreleased/212322-remove-duplicate-vulnerabilities.yml5
-rw-r--r--changelogs/unreleased/213581-ide-alert-when-cannot-push-code.yml5
-rw-r--r--changelogs/unreleased/214631-remove-duplicated-vsa-stage-event.yml5
-rw-r--r--changelogs/unreleased/216761-add-image-repository-level-delete-functionality-to-the-image-repos.yml5
-rw-r--r--changelogs/unreleased/216761-proper-404-page-registry-details.yml5
-rw-r--r--changelogs/unreleased/21686_filter_duplicates.yml5
-rw-r--r--changelogs/unreleased/216912-jira-proxy-settings.yml5
-rw-r--r--changelogs/unreleased/220957-Open-with-IDE.yml5
-rw-r--r--changelogs/unreleased/223101-replace-angle-double-left-icon-with-svg.yml5
-rw-r--r--changelogs/unreleased/223618-project-labels-api-return-404-label-not-found-if-label-name-contai.yml5
-rw-r--r--changelogs/unreleased/227349-package-registry-expand-the-filter-and-sort-functionality-on-the-p.yml5
-rw-r--r--changelogs/unreleased/229174_use_unix_time_for_jira_update_sequence_id.yml5
-rw-r--r--changelogs/unreleased/229293-migrate-to-GlButton-note-form.yml5
-rw-r--r--changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-cherry-picking-com.yml5
-rw-r--r--changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert-cherry-picking-com.yml5
-rw-r--r--changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert.yml5
-rw-r--r--changelogs/unreleased/231044-convert-runner-buttons-to-pajamas.yml5
-rw-r--r--changelogs/unreleased/231083-yo-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/231153-deploy-token-button-pajamas.yml5
-rw-r--r--changelogs/unreleased/231173-gl-button.yml5
-rw-r--r--changelogs/unreleased/231179-app-projects-buttons.yml5
-rw-r--r--changelogs/unreleased/231199-yo-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/231204-projects-notes.yml5
-rw-r--r--changelogs/unreleased/231219-yo-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/233708-fix-resource-event-timestamps.yml6
-rw-r--r--changelogs/unreleased/235525-test-report-recent-failures.yml5
-rw-r--r--changelogs/unreleased/239172-add-entity-columns-to-vulnerability-occurrences.yml5
-rw-r--r--changelogs/unreleased/241376-max-nuget-packages-returned.yml5
-rw-r--r--changelogs/unreleased/241744-additional-formats-kroki.yml5
-rw-r--r--changelogs/unreleased/24488-expose-tag-list.yml5
-rw-r--r--changelogs/unreleased/245260-fix-git-url-project-disclosure.yml5
-rw-r--r--changelogs/unreleased/250480-enforce-ssh-key-expiry.yml5
-rw-r--r--changelogs/unreleased/25381-add-a-custom-commit-message-when-applying-a-suggested-change.yml5
-rw-r--r--changelogs/unreleased/25381-add-request-review-alias.yml5
-rw-r--r--changelogs/unreleased/25381-suggestion-custom-commit-ff-default-true.yml5
-rw-r--r--changelogs/unreleased/254256-replace-bootstrap-modal-in-app-views-projects-_issuable_by_email-h.yml5
-rw-r--r--changelogs/unreleased/254643-fix-broken-testsuite-link-when-containing-dot.yml5
-rw-r--r--changelogs/unreleased/255394-runner-tags-in-webhook.yml5
-rw-r--r--changelogs/unreleased/258-collecting-mau-for-gitlab-workflow-vs-code-extension.yml5
-rw-r--r--changelogs/unreleased/258550-fix-long-ci-variable-name-overflows-on-origin.yml5
-rw-r--r--changelogs/unreleased/259719-rollout-optimized-labels-ff.yml5
-rw-r--r--changelogs/unreleased/260419-add-subgroup-events-column-to-webhooks-table.yml5
-rw-r--r--changelogs/unreleased/262047-order-milestones-by-due-date.yml5
-rw-r--r--changelogs/unreleased/262063-global-search-topbar-vue.yml5
-rw-r--r--changelogs/unreleased/262086-schedule-user-unset-status.yml5
-rw-r--r--changelogs/unreleased/262102-fix-stay-on-page-alert-showing-in-empty-snippet.yml5
-rw-r--r--changelogs/unreleased/262860-persist-shift-job.yml5
-rw-r--r--changelogs/unreleased/262863-delete-oncall-rotation-graphql.yml5
-rw-r--r--changelogs/unreleased/263452-display-busy-status-in-issue-sidebar.yml5
-rw-r--r--changelogs/unreleased/263452-sidebar-display-busy-status.yml5
-rw-r--r--changelogs/unreleased/264262-users-who-have-reached-their-personal-project-limit-cannot-fork-to.yml5
-rw-r--r--changelogs/unreleased/267140-add-user-bot-gql.yml5
-rw-r--r--changelogs/unreleased/267140-check-if-user-is-bot.yml5
-rw-r--r--changelogs/unreleased/267344-test-report-file-name-link.yml5
-rw-r--r--changelogs/unreleased/267522-sshkey-delete-parital.yml5
-rw-r--r--changelogs/unreleased/270130-policy-preview-for-egress-deny-all-reports-egress-allow-all.yml5
-rw-r--r--changelogs/unreleased/271263-piwik-support-the-disabling-of-cookies.yml5
-rw-r--r--changelogs/unreleased/271530-improve-user-menu.yml5
-rw-r--r--changelogs/unreleased/273067-fix-ide-open-mr-highligh-first-file.yml5
-rw-r--r--changelogs/unreleased/273288-update-blob-page-buttons.yml5
-rw-r--r--changelogs/unreleased/273328-global-search-sort-ux.yml5
-rw-r--r--changelogs/unreleased/273574-fix-bad-data-in-projects-has_external_issue_tracker.yml5
-rw-r--r--changelogs/unreleased/276583-make-keep-latest-artifact-an-instance-level-configuration.yml5
-rw-r--r--changelogs/unreleased/276882-Allow-metadata-duplicates.yml6
-rw-r--r--changelogs/unreleased/276917-remove-default_merge_ref_for_diffs-feature-flag.yml5
-rw-r--r--changelogs/unreleased/277327_populate_uuid_values_for_security_findings.yml6
-rw-r--r--changelogs/unreleased/277436-2fa-ux-text-changes.yml5
-rw-r--r--changelogs/unreleased/281677_space_in_filename.yml5
-rw-r--r--changelogs/unreleased/281963-move-cohorts-to-users.yml5
-rw-r--r--changelogs/unreleased/283897-fix-inaccessible-pipeline-status-icon-colors-in-mr-widget.yml5
-rw-r--r--changelogs/unreleased/283911-tf-alignment.yml5
-rw-r--r--changelogs/unreleased/283912-remove-redundant-text.yml5
-rw-r--r--changelogs/unreleased/284283-change-error-message-for-user-approval-error.yml5
-rw-r--r--changelogs/unreleased/285287-include-submodule-information-for-files-in-diff-metadata.yml5
-rw-r--r--changelogs/unreleased/285464_improve_highlighting_for_diffs.yml5
-rw-r--r--changelogs/unreleased/285507-fix-reply-box-border.yml5
-rw-r--r--changelogs/unreleased/287690-issue-comment-option-icons-are-not-aligned-consistently.yml5
-rw-r--r--changelogs/unreleased/288715-populate-and-migration-issue_email_participants.yml5
-rw-r--r--changelogs/unreleased/288822-audit-event-removed-user-bug.yml5
-rw-r--r--changelogs/unreleased/289836_monkey_patch_net_http_proxy_crendetial_encoding.yml5
-rw-r--r--changelogs/unreleased/290112_add_security_dashboard_access_level_into_project_features.yml6
-rw-r--r--changelogs/unreleased/290116-enable-webhook-test-reorder-feature.yml5
-rw-r--r--changelogs/unreleased/290231-warning-message-for-group-migration.yml5
-rw-r--r--changelogs/unreleased/290288-composer-cache-pages.yml5
-rw-r--r--changelogs/unreleased/290302-sort-container-repositories.yml5
-rw-r--r--changelogs/unreleased/290302-update-the-default-sort-order-of-the-image-repository-list.yml5
-rw-r--r--changelogs/unreleased/290622-display-warning-mr-edit.yml5
-rw-r--r--changelogs/unreleased/290715-has_external_issue_tracker_trigger.yml5
-rw-r--r--changelogs/unreleased/290741-packages-hidden-status.yml5
-rw-r--r--changelogs/unreleased/290944-pull-by-digest.yml5
-rw-r--r--changelogs/unreleased/291048-allow-unfinished-tag-cleanup-alert-to-be-permanently-dismissible-f.yml5
-rw-r--r--changelogs/unreleased/291140-query-single-state.yml5
-rw-r--r--changelogs/unreleased/291170-issue-mr-list-tabs-icons-sometimes-display-as.yml5
-rw-r--r--changelogs/unreleased/292035-convert-the-assignees-feature-into-a-widget.yml5
-rw-r--r--changelogs/unreleased/292391-quickactions-usage-ping.yml5
-rw-r--r--changelogs/unreleased/292498-editor-lite-diff-editor.yml5
-rw-r--r--changelogs/unreleased/292507-batch-merge-ref-diff.yml5
-rw-r--r--changelogs/unreleased/292713-remove-loading-tf.yml5
-rw-r--r--changelogs/unreleased/292713-tf-lock-loading.yml5
-rw-r--r--changelogs/unreleased/292714-allow-reviewers-to-be-updated-via-api.yml5
-rw-r--r--changelogs/unreleased/292820-update-user-api-docs-and-enable-ff.yml5
-rw-r--r--changelogs/unreleased/292825-track-approver-metrics-for-a-merge-request.yml5
-rw-r--r--changelogs/unreleased/292828-track-suggestion-metrics.yml5
-rw-r--r--changelogs/unreleased/293477-update-pages-help-text.yml5
-rw-r--r--changelogs/unreleased/293720-agent-created-by.yml5
-rw-r--r--changelogs/unreleased/293720-token-created-by.yml5
-rw-r--r--changelogs/unreleased/293819-enable-sort-diffs-default.yml5
-rw-r--r--changelogs/unreleased/294004-enable-jira-sync-builds.yml5
-rw-r--r--changelogs/unreleased/294007-bump-workhorse.yml5
-rw-r--r--changelogs/unreleased/294156-fix-merge-request-changes-comment-fullscreen-mode.yml5
-rw-r--r--changelogs/unreleased/295211-create-BV_x_MODEL-constants.yml5
-rw-r--r--changelogs/unreleased/295311-add-updated-at-to-search-results.yml5
-rw-r--r--changelogs/unreleased/295311-sort-mr-issues-last-updated.yml5
-rw-r--r--changelogs/unreleased/295621-rename-asset-proxy-whitelist-setting.yml5
-rw-r--r--changelogs/unreleased/295626-when-epic-swimlanes-are-enabled-milestones-are-incorrectly-scoped-.yml5
-rw-r--r--changelogs/unreleased/296133-engineering-in-product-email-campaigns-in-saas.yml5
-rw-r--r--changelogs/unreleased/296521-leave-this-group-button-not-working.yml5
-rw-r--r--changelogs/unreleased/296645-removed-unused-dropdown.yml5
-rw-r--r--changelogs/unreleased/296667-fix-branch-change-with-line-selected.yml5
-rw-r--r--changelogs/unreleased/296669-migration-support-customizable-timeouts-for-git-cli-2fa.yml5
-rw-r--r--changelogs/unreleased/296754-followup-from-refactor-namespaceonboardingaction-model-to-onboardi.yml5
-rw-r--r--changelogs/unreleased/296756-cablett-remove-index.yml5
-rw-r--r--changelogs/unreleased/296856-prevent-creating-duplicate-pipelines-manually.yml5
-rw-r--r--changelogs/unreleased/296895-group-setting-to-allow-or-prevent-duplicate-maven-uploads.yml5
-rw-r--r--changelogs/unreleased/296943-expose-user-availability.yml5
-rw-r--r--changelogs/unreleased/296948-container-and-package-list-ui-polish-condense-spacing-to-match-iss.yml5
-rw-r--r--changelogs/unreleased/296990-enable-jira-ff-sync.yml5
-rw-r--r--changelogs/unreleased/297346-flaky-spec-in-ee-spec-features-burnup_charts_spec-rb-burnup-charts.yml5
-rw-r--r--changelogs/unreleased/297644-jira-association-requirements-be.yml5
-rw-r--r--changelogs/unreleased/297664-maintain-data-parity-between-experimentuser-experimentsubject.yml6
-rw-r--r--changelogs/unreleased/298703-terraform-name-validation.yml5
-rw-r--r--changelogs/unreleased/298783-log-user-instance-request-in-audit-events.yml5
-rw-r--r--changelogs/unreleased/298790-the-options-to-show-hide-the-open-and-closed-lists-in-boards-shoul.yml5
-rw-r--r--changelogs/unreleased/298801-group-migration-show-import-status-frontend.yml5
-rw-r--r--changelogs/unreleased/298822-ci-cd-general-pipelines-settings-ui-text.yml5
-rw-r--r--changelogs/unreleased/298975-search-autodiscovery.yml5
-rw-r--r--changelogs/unreleased/299052-fj-add-repository-read-only-column-to-namespace-settings.yml5
-rw-r--r--changelogs/unreleased/299087-track-assignees-and-reviewers-for-merge-requests.yml5
-rw-r--r--changelogs/unreleased/299102-fix-spelling.yml5
-rw-r--r--changelogs/unreleased/299213-project-filter-regression.yml5
-rw-r--r--changelogs/unreleased/299263-rubygems-metadata-migration.yml5
-rw-r--r--changelogs/unreleased/299264-track-create-merge-request-from-issues.yml5
-rw-r--r--changelogs/unreleased/299343-fj-enable-housekeeping-for-wikis.yml5
-rw-r--r--changelogs/unreleased/299403-usage_data_unique_users_committing_ciconfigfile.yml5
-rw-r--r--changelogs/unreleased/299457-user-cannot-merge-an-issue.yml5
-rw-r--r--changelogs/unreleased/299494-add-tooltips-to-requirement-import-and-export.yml5
-rw-r--r--changelogs/unreleased/299559-remove-add-border-borderless-prop-from-ci-icon-when-used-together.yml6
-rw-r--r--changelogs/unreleased/299719-fj-fix-bug-personal-snippet-thread-discussion.yml5
-rw-r--r--changelogs/unreleased/299828-okr-ci-cd-variables-review-and-revise-settings-related-ui-text.yml5
-rw-r--r--changelogs/unreleased/299925-fix-i18n-syntax-in-app-views-projects-cleanup-_show-html-haml.yml5
-rw-r--r--changelogs/unreleased/299954-feature-flag-rollout-of-vue_project_members_list.yml5
-rw-r--r--changelogs/unreleased/299982-Remove-v-html-from-mr_widget_pipeline-vue.yml5
-rw-r--r--changelogs/unreleased/2fa-gl-button.yml5
-rw-r--r--changelogs/unreleased/300048-leipert-allow-head-requests.yml5
-rw-r--r--changelogs/unreleased/300067-mermaid-markdown-er-diagram-does-not-render-attributes.yml5
-rw-r--r--changelogs/unreleased/300105-remove-integrations_test_webhook_optimizations-feature-flag.yml5
-rw-r--r--changelogs/unreleased/300156-external-request-tracking-errors-on-ipv6-host.yml5
-rw-r--r--changelogs/unreleased/300209-fix-suggestions-bad-request.yml5
-rw-r--r--changelogs/unreleased/300220-add-security-orchestration-policy-configuration-model.yml5
-rw-r--r--changelogs/unreleased/300263-remove-btn-build-class.yml6
-rw-r--r--changelogs/unreleased/300367-breadcrumb-links-to-404-page.yml5
-rw-r--r--changelogs/unreleased/300524-create-worker-to-clean-up-composer-cache-pages.yml5
-rw-r--r--changelogs/unreleased/300546-add-new-plans.yml5
-rw-r--r--changelogs/unreleased/300652-fix-prom-metrics-in-puma-single.yml5
-rw-r--r--changelogs/unreleased/300661-fix-readiness-for-puma-single-2.yml5
-rw-r--r--changelogs/unreleased/300847-fix-link.yml5
-rw-r--r--changelogs/unreleased/300860-jobs-empty-state-successful-cleanup.yml5
-rw-r--r--changelogs/unreleased/300910-drop-puma-clustered-validation.yml5
-rw-r--r--changelogs/unreleased/301100-gma-badge.yml5
-rw-r--r--changelogs/unreleased/301140-conditionally-render-test-case-file.yml5
-rw-r--r--changelogs/unreleased/301236-fix-test-report-not-rendering.yml5
-rw-r--r--changelogs/unreleased/30141-improve-merge-failed-error-fe.yml5
-rw-r--r--changelogs/unreleased/30141-merge-error-msg-update.yml5
-rw-r--r--changelogs/unreleased/302-improve-visibility-of-time-spent-with-external-io.yml5
-rw-r--r--changelogs/unreleased/31064-ensure-diff-patch-size-limit-is-monitorable.yml5
-rw-r--r--changelogs/unreleased/320792-add-an-api-rate-limit-for-new-notes-using-application-rate-limits.yml5
-rw-r--r--changelogs/unreleased/320836-display-compare-button.yml5
-rw-r--r--changelogs/unreleased/320965-confidential-issue.yml5
-rw-r--r--changelogs/unreleased/321040-jira-list-search-not-working.yml5
-rw-r--r--changelogs/unreleased/321447-fix-foss.yml5
-rw-r--r--changelogs/unreleased/36705-search-across-full-name-for-assignee-autocomplete.yml5
-rw-r--r--changelogs/unreleased/52756-pipeline_schedule_worker_cron.yml5
-rw-r--r--changelogs/unreleased/5788-geo-automatic-recover-from-leader-change-in-primary-site-docs.yml6
-rw-r--r--changelogs/unreleased/64320-refactor-mr-services.yml5
-rw-r--r--changelogs/unreleased/84402-remove-avatar-from-comment-forms.yml5
-rw-r--r--changelogs/unreleased/ApplyGItLabUIstylesto_edit_form-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_hook-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_test_button-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_table-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIstylesin_notifications_directory.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIstylesto_comment_button-html-haml.yml5
-rw-r--r--changelogs/unreleased/ApplyGitLabUIstylestobuttonin_form-html-haml.yml5
-rw-r--r--changelogs/unreleased/Lint-DeprecatedOpenSSLConstant.yml5
-rw-r--r--changelogs/unreleased/Replace-bootstrap-event-strings-with-constants.yml5
-rw-r--r--changelogs/unreleased/Set-min-width-of-breadcrumb-dropdown-to-200px.yml5
-rw-r--r--changelogs/unreleased/ab-ci-builds-metadata-index.yml5
-rw-r--r--changelogs/unreleased/add-labels-resolver.yml6
-rw-r--r--changelogs/unreleased/add-missing-known-event-ecs-deploy-template.yml5
-rw-r--r--changelogs/unreleased/add-recaptcha-fields-to-snippet-mutations.yml5
-rw-r--r--changelogs/unreleased/add-user-setting-for-opting-into-marketing-emails.yml5
-rw-r--r--changelogs/unreleased/add-webp-to-file-type-detection.yml5
-rw-r--r--changelogs/unreleased/ajk-294034-enable-jira-deployments.yml5
-rw-r--r--changelogs/unreleased/ajk-add-state-events-to-mr-update-mutation.yml5
-rw-r--r--changelogs/unreleased/ajk-graphql-packages.yml5
-rw-r--r--changelogs/unreleased/ajk-jira-connect-fix-ff-url.yml5
-rw-r--r--changelogs/unreleased/ajk-remove-adjacency-check.yml5
-rw-r--r--changelogs/unreleased/align-graph-page.yml5
-rw-r--r--changelogs/unreleased/alipniagov-disable-nakayoshi-by-default.yml5
-rw-r--r--changelogs/unreleased/allow-environment-scopes-to-wrap-feature-flags.yml5
-rw-r--r--changelogs/unreleased/apply-gl-button-schedules.yml5
-rw-r--r--changelogs/unreleased/ar-color-name-changes.yml5
-rw-r--r--changelogs/unreleased/ar-fix-border-color.yml5
-rw-r--r--changelogs/unreleased/ar-update-project-avatar-border-radius.yml5
-rw-r--r--changelogs/unreleased/arty-fix-auditor-badge.yml5
-rw-r--r--changelogs/unreleased/arty-spt-selfserve-del.yml5
-rw-r--r--changelogs/unreleased/asciidoctor-2-0-12.yml5
-rw-r--r--changelogs/unreleased/auto-delete-at.yml5
-rw-r--r--changelogs/unreleased/automatically-authenticate-with-the-dependency-proxy.yml5
-rw-r--r--changelogs/unreleased/bjk-splay_puma_restarts.yml5
-rw-r--r--changelogs/unreleased/btn-confirm-2fa.yml5
-rw-r--r--changelogs/unreleased/btn-default-cicd_for_external_repov.yml5
-rw-r--r--changelogs/unreleased/btn-default-history.yml5
-rw-r--r--changelogs/unreleased/btn-default-lock-unlock.yml5
-rw-r--r--changelogs/unreleased/btn-default-push-rules.yml5
-rw-r--r--changelogs/unreleased/btn-default-rss.yml5
-rw-r--r--changelogs/unreleased/btn-icon-gpg.yml5
-rw-r--r--changelogs/unreleased/btn-icon-issues.yml5
-rw-r--r--changelogs/unreleased/btn-icon-user-profile.yml5
-rw-r--r--changelogs/unreleased/changelog-api.yml5
-rw-r--r--changelogs/unreleased/chat_notification_label_support.yml5
-rw-r--r--changelogs/unreleased/ci-allow-deep-nesting-for-scripts.yml5
-rw-r--r--changelogs/unreleased/cngo-add-landmarks-and-provide-names.yml5
-rw-r--r--changelogs/unreleased/cngo-migrate-feature-flag-toggles-to-gl-toggle.yml5
-rw-r--r--changelogs/unreleased/cngo-migrate-project-settings-to-use-gl-toggle.yml5
-rw-r--r--changelogs/unreleased/cngo-migrate-subscription-toggle-to-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/compliance_pipeline_configuration.yml5
-rw-r--r--changelogs/unreleased/consistent-question-mark-mr.yml5
-rw-r--r--changelogs/unreleased/consistent-tooltip-user-profile.yml5
-rw-r--r--changelogs/unreleased/count-implicit-auto-devops-inclusions-separately.yml5
-rw-r--r--changelogs/unreleased/custom-emoji-banzai-filter.yml5
-rw-r--r--changelogs/unreleased/darneas-296853.yml5
-rw-r--r--changelogs/unreleased/dblessing_fix_ssh_key_regression.yml5
-rw-r--r--changelogs/unreleased/debian_component_files.yml5
-rw-r--r--changelogs/unreleased/debian_distribution_components.yml5
-rw-r--r--changelogs/unreleased/debian_publications.yml5
-rw-r--r--changelogs/unreleased/deprecate_gma_apps.yml5
-rw-r--r--changelogs/unreleased/devops-adoption-pivot.yml5
-rw-r--r--changelogs/unreleased/diff-view-speed.yml5
-rw-r--r--changelogs/unreleased/docs-ci-starter.yml5
-rw-r--r--changelogs/unreleased/docs-redirects-removal-6.yml5
-rw-r--r--changelogs/unreleased/docs-ui-text-settings-deploy-freezes.yml5
-rw-r--r--changelogs/unreleased/docs-ui-text-settings-deploy-keys.yml5
-rw-r--r--changelogs/unreleased/download-patch-diff-new-tab.yml5
-rw-r--r--changelogs/unreleased/eb-code-quality-version-0-85-22.yml5
-rw-r--r--changelogs/unreleased/eb-prometheus-monitoring-report-parsers.yml5
-rw-r--r--changelogs/unreleased/eb-remove-smart-cobertura-parser-flag.yml5
-rw-r--r--changelogs/unreleased/ek-display-full-design-name-in-tooltip.yml5
-rw-r--r--changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml5
-rw-r--r--changelogs/unreleased/enable-query_deployments_via_finished_at_in_vsa-ff.yml5
-rw-r--r--changelogs/unreleased/enable_specialized_project_create_ff.yml5
-rw-r--r--changelogs/unreleased/eread-add-URL-help-text.yml5
-rw-r--r--changelogs/unreleased/feat-bypass-admin-mode-on-git.yml5
-rw-r--r--changelogs/unreleased/feat-follow-eachother.yml5
-rw-r--r--changelogs/unreleased/feat-release-tooltip-for-guest-users.yml5
-rw-r--r--changelogs/unreleased/feature-file-review-docs.yml6
-rw-r--r--changelogs/unreleased/feature-file-review.yml5
-rw-r--r--changelogs/unreleased/feature-flag-contextual-issue-links.yml5
-rw-r--r--changelogs/unreleased/feature-flag-enable-ci-config-merged-tab.yml5
-rw-r--r--changelogs/unreleased/fix-avatar-alignment-edit-board.yml5
-rw-r--r--changelogs/unreleased/fix-back-button-ci-cd-analytics.yml5
-rw-r--r--changelogs/unreleased/fix-button-alignment-applications.yml5
-rw-r--r--changelogs/unreleased/fix-ci-variable-popover-copy-button.yml5
-rw-r--r--changelogs/unreleased/fix-crypto-helper-issue.yml5
-rw-r--r--changelogs/unreleased/fix-email-icon.yml5
-rw-r--r--changelogs/unreleased/fix-merge-trains-cannot-be-retried.yml5
-rw-r--r--changelogs/unreleased/fix-opensearch.yml5
-rw-r--r--changelogs/unreleased/fix-overflowing-design-buttons.yml5
-rw-r--r--changelogs/unreleased/fix-pipeline-and-stage-status.yml5
-rw-r--r--changelogs/unreleased/fix-social-connect-icons-margin.yml5
-rw-r--r--changelogs/unreleased/fix-spacing-labels.yml5
-rw-r--r--changelogs/unreleased/fix-svg-flex.yml5
-rw-r--r--changelogs/unreleased/fix-table-header-space.yml5
-rw-r--r--changelogs/unreleased/fix-unneeded-left-margin-discussion-filter-container.yml5
-rw-r--r--changelogs/unreleased/fj-backfill-project-updated_at-after-repository-move.yml5
-rw-r--r--changelogs/unreleased/fj-create-group-repository-storage-move-table.yml5
-rw-r--r--changelogs/unreleased/fj-fix-api-when-snippet-does-not-exist.yml5
-rw-r--r--changelogs/unreleased/fj-fix-bug-rendering-snippet-activity.yml5
-rw-r--r--changelogs/unreleased/fj-update-update-at-column-after-repository-storage-move.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-group-migration-epic-award-emoji.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-track-bulk-import-exceptions.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-update-project-export-temp-folder-cleanup.yml5
-rw-r--r--changelogs/unreleased/gfm-emoji-refactor.yml5
-rw-r--r--changelogs/unreleased/gitaly-trailer-parsing.yml5
-rw-r--r--changelogs/unreleased/gl-badge-branch-list.yml5
-rw-r--r--changelogs/unreleased/gl-badge-job.yml5
-rw-r--r--changelogs/unreleased/gl-button-ci-cd.yml5
-rw-r--r--changelogs/unreleased/gl-button-commit-page.yml5
-rw-r--r--changelogs/unreleased/gl-button-create-mr.yml5
-rw-r--r--changelogs/unreleased/gl-button-done.yml5
-rw-r--r--changelogs/unreleased/gl-button-download.yml5
-rw-r--r--changelogs/unreleased/gl-button-empty-issue-placeholder.yml5
-rw-r--r--changelogs/unreleased/gl-button-file.yml5
-rw-r--r--changelogs/unreleased/gl-button-fix-tag.yml5
-rw-r--r--changelogs/unreleased/gl-button-issues.yml5
-rw-r--r--changelogs/unreleased/gl-button-job.yml5
-rw-r--r--changelogs/unreleased/gl-button-new-group.yml5
-rw-r--r--changelogs/unreleased/gl-button-new-project.yml5
-rw-r--r--changelogs/unreleased/gl-button-no-repo-actions.yml5
-rw-r--r--changelogs/unreleased/gl-button-resolve-conflict.yml5
-rw-r--r--changelogs/unreleased/gl-button-single-tag.yml5
-rw-r--r--changelogs/unreleased/gl-button-snippets.yml5
-rw-r--r--changelogs/unreleased/gl-button-social.yml5
-rw-r--r--changelogs/unreleased/gl-button-tags.yml5
-rw-r--r--changelogs/unreleased/gl-button-utf-try-again.yml5
-rw-r--r--changelogs/unreleased/gl-card-advanced-search.yml5
-rw-r--r--changelogs/unreleased/gl-form-input-user-applications.yml5
-rw-r--r--changelogs/unreleased/gl-form-input-user-email.yml5
-rw-r--r--changelogs/unreleased/gl-form-input-user-pat.yml5
-rw-r--r--changelogs/unreleased/gl-form-input-user-profile.yml5
-rw-r--r--changelogs/unreleased/gl-new-trials.yml5
-rw-r--r--changelogs/unreleased/gl-ui-graph-page.yml5
-rw-r--r--changelogs/unreleased/gy-artifact-download-multiple-types.yml5
-rw-r--r--changelogs/unreleased/gy-clarify-sample-data.yml5
-rw-r--r--changelogs/unreleased/gy-fix-sample-template.yml5
-rw-r--r--changelogs/unreleased/id-bump-bullet.yml5
-rw-r--r--changelogs/unreleased/id-bump-doorkeeper-to-5-4-0.yml5
-rw-r--r--changelogs/unreleased/id-bump-grape.yml5
-rw-r--r--changelogs/unreleased/id-fix-no-route-error.yml5
-rw-r--r--changelogs/unreleased/id-optimize-branches-index.yml5
-rw-r--r--changelogs/unreleased/id-restrict-protected-rules.yml5
-rw-r--r--changelogs/unreleased/id-update-bundler-audit.yml5
-rw-r--r--changelogs/unreleased/id-update-default-value-for.yml5
-rw-r--r--changelogs/unreleased/id-update-doorkeeper-gem.yml5
-rw-r--r--changelogs/unreleased/id-update-rspec-mocks.yml5
-rw-r--r--changelogs/unreleased/improve-system-oauth-app-layout.yml5
-rw-r--r--changelogs/unreleased/improve-uniquness-validator-on-release.yml5
-rw-r--r--changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml5
-rw-r--r--changelogs/unreleased/instrument-and-log-memory-usage.yml5
-rw-r--r--changelogs/unreleased/jdb-fix-drag-comment-tooltip.yml5
-rw-r--r--changelogs/unreleased/jdb-fix-project-index-file-no-longer-fluid.yml5
-rw-r--r--changelogs/unreleased/jimcser-openapi-readme.yml5
-rw-r--r--changelogs/unreleased/jivanvl-convert-gl-badge-duration-component.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-graphql-pipeline-header-ff.yml5
-rw-r--r--changelogs/unreleased/jivanvl-remove-runner-instructions-ff.yml5
-rw-r--r--changelogs/unreleased/jj-remove-caching-experiments.yml5
-rw-r--r--changelogs/unreleased/jl-improve-profile-status-emoji-alignment.yml5
-rw-r--r--changelogs/unreleased/jswain_whats_new_remove_feature_flag.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-avoid-recursive-group-migration.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-group-labels-pipeline.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-import-group-membership.yml5
-rw-r--r--changelogs/unreleased/kassio-bulkimports-log-pipeline-step-on-failures.yml5
-rw-r--r--changelogs/unreleased/kassio-manage-import-gmau-metrics.yml5
-rw-r--r--changelogs/unreleased/kcomoli-copy-fixes-welcome-page.yml6
-rw-r--r--changelogs/unreleased/leipert-remove-sticky-polyfill.yml5
-rw-r--r--changelogs/unreleased/link-new-line-gpg.yml5
-rw-r--r--changelogs/unreleased/lm-add-merged-yaml.yml5
-rw-r--r--changelogs/unreleased/lm-adds-gitaly-call-label.yml6
-rw-r--r--changelogs/unreleased/loading-space-todo.yml5
-rw-r--r--changelogs/unreleased/make-lifecycle-hooks-to-be-fatal.yml5
-rw-r--r--changelogs/unreleased/map-prometheus-payload-severity.yml5
-rw-r--r--changelogs/unreleased/mc-api-pipeline-webhook-remove-retried-jobs.yml5
-rw-r--r--changelogs/unreleased/mc-backstage-reduce-db-updates-ci-minute-reset.yml5
-rw-r--r--changelogs/unreleased/mc-backstage-schedule-artifact-expiration-backfill-properly.yml5
-rw-r--r--changelogs/unreleased/memoize-fork-button.yml5
-rw-r--r--changelogs/unreleased/mjang-deploy-tokens-okr-update.yml5
-rw-r--r--changelogs/unreleased/mk-fix-cleanup-rake-task-limit.yml5
-rw-r--r--changelogs/unreleased/mo-add-group-id-to-coverage-data.yml5
-rw-r--r--changelogs/unreleased/move-vulnerability-report-to-card.yml5
-rw-r--r--changelogs/unreleased/move_mutations_to_ce_for_sast_config.yml5
-rw-r--r--changelogs/unreleased/msj-todo-alerts.yml5
-rw-r--r--changelogs/unreleased/msj-todo-design-errors.yml5
-rw-r--r--changelogs/unreleased/mwaw-add_index_to_security_scans_on_created_at_and_build_id.yml5
-rw-r--r--changelogs/unreleased/nadia_sotnikova-master-patch-51286.yml5
-rw-r--r--changelogs/unreleased/new-gitlab-ui-blob-editor.yml5
-rw-r--r--changelogs/unreleased/new-tab-links.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-mininterval-to-pipeline-charts.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-cleanup-pipelines-empty-state-experiment.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-fix-welcome-page.yml5
-rw-r--r--changelogs/unreleased/paginate-commit.yml5
-rw-r--r--changelogs/unreleased/pb-bold-font.yml5
-rw-r--r--changelogs/unreleased/pb-change-mr-pipeline-failed-message.yml5
-rw-r--r--changelogs/unreleased/pb-dm-modal-text-color.yml6
-rw-r--r--changelogs/unreleased/pb-move-pipeline-new-input-to-textarea.yml6
-rw-r--r--changelogs/unreleased/pb-use-gl-alert-erased-block.yml5
-rw-r--r--changelogs/unreleased/peterhegman-fix-assignee-dropdown-checkmark.yml5
-rw-r--r--changelogs/unreleased/peterhegman-fix-members-status-emoji-size.yml5
-rw-r--r--changelogs/unreleased/ph-227161-fixDiscussonsOnCommits.yml5
-rw-r--r--changelogs/unreleased/ph-235741-fixSuggestionsUpdatingIncorrectly.yml5
-rw-r--r--changelogs/unreleased/ph-255626-allowMultipleCommentsInInlineView.yml5
-rw-r--r--changelogs/unreleased/ph-293891-fixSuggestionsToReplies.yml5
-rw-r--r--changelogs/unreleased/ph-300006-fixDiffsDiscussionWrongSide.yml5
-rw-r--r--changelogs/unreleased/ph-fixMRGraphQlCommitsCount.yml5
-rw-r--r--changelogs/unreleased/ph-mergeRequestLockedStatus.yml5
-rw-r--r--changelogs/unreleased/ph-ph-fixWidgetGraphqlPipelineWarnings.yml5
-rw-r--r--changelogs/unreleased/ph-reRequestReview.yml5
-rw-r--r--changelogs/unreleased/ph-requestReviewBackend.yml5
-rw-r--r--changelogs/unreleased/philipcunningham-create-dast-scan-model-295243.yml5
-rw-r--r--changelogs/unreleased/pipeline-editor-confirm-dialog.yml5
-rw-r--r--changelogs/unreleased/pkce-cors.yml5
-rw-r--r--changelogs/unreleased/pks-gitaly-fix-force-routing.yml5
-rw-r--r--changelogs/unreleased/pks-gitaly-force-primary-routing-with-hookenv.yml5
-rw-r--r--changelogs/unreleased/pl-generic-payload-severity.yml5
-rw-r--r--changelogs/unreleased/preset_ancestor.yml5
-rw-r--r--changelogs/unreleased/prevent-notifications-from-ghost-user.yml5
-rw-r--r--changelogs/unreleased/prevent_blocked_user_notification.yml5
-rw-r--r--changelogs/unreleased/ps-clean-new-gl-button-refs.yml6
-rw-r--r--changelogs/unreleased/ps-refactor-snippets-edit-spec-no-vm.yml5
-rw-r--r--changelogs/unreleased/ps-remove-gl-dropdown-item-deprecated-adapter.yml5
-rw-r--r--changelogs/unreleased/psi-board-list-highlight.yml5
-rw-r--r--changelogs/unreleased/psi-board-search-align.yml5
-rw-r--r--changelogs/unreleased/psi-pipeline-icon-align.yml5
-rw-r--r--changelogs/unreleased/qmnguyen0711-640-sidekiq-jobretry-skip-should-not-mask-the-underlying-sid.yml5
-rw-r--r--changelogs/unreleased/qmnguyen0711-751-rack-attack-redis-calls-showing-up-in-the-slowlog.yml5
-rw-r--r--changelogs/unreleased/redesign-download-button.yml5
-rw-r--r--changelogs/unreleased/redo-changelog-index.yml5
-rw-r--r--changelogs/unreleased/remove-banzai-commit-full-title.yml5
-rw-r--r--changelogs/unreleased/remove-ci-custom-tags-ff-300155.yml5
-rw-r--r--changelogs/unreleased/remove-extra-margin-project-template.yml5
-rw-r--r--changelogs/unreleased/remove-feature-flag-deploy_keys_on_protected_branches.yml5
-rw-r--r--changelogs/unreleased/remove-feature_flag_contextual_issue.yml5
-rw-r--r--changelogs/unreleased/remove-implicit-feature-flag-check-on-featurable.yml5
-rw-r--r--changelogs/unreleased/remove-merge-request-reviewer-ff.yml5
-rw-r--r--changelogs/unreleased/remove-owner-data-from-group-webhooks.yml5
-rw-r--r--changelogs/unreleased/remove-tmp-index-oauth-applications.yml5
-rw-r--r--changelogs/unreleased/reposition-integration-form-elements.yml5
-rw-r--r--changelogs/unreleased/reset-admin-password-rake-task.yml5
-rw-r--r--changelogs/unreleased/retarget-branch.yml5
-rw-r--r--changelogs/unreleased/return-all-jobs.yml5
-rw-r--r--changelogs/unreleased/revert-3c18ef0b.yml5
-rw-r--r--changelogs/unreleased/revert-project-has_external_wiki.yml5
-rw-r--r--changelogs/unreleased/revert-pull-by-digest.yml6
-rw-r--r--changelogs/unreleased/rf-update-brakeman-rules.yml5
-rw-r--r--changelogs/unreleased/russell-update-project-visibility-settings-ui-text.yml5
-rw-r--r--changelogs/unreleased/selhorn-okr-triggers.yml5
-rw-r--r--changelogs/unreleased/semgrep-docs-n-template.yml5
-rw-r--r--changelogs/unreleased/sfang-project-access-token-api.yml5
-rw-r--r--changelogs/unreleased/sh-add-openid-sso-icon.yml5
-rw-r--r--changelogs/unreleased/sh-disable-ci-live-trace-ff.yml5
-rw-r--r--changelogs/unreleased/sh-fix-discussion-note-promotion-failure-handling.yml5
-rw-r--r--changelogs/unreleased/sh-handle-fog-host-params.yml5
-rw-r--r--changelogs/unreleased/sh-prepend-marginalia-comments.yml5
-rw-r--r--changelogs/unreleased/sh-update-hamlit-for-gc.yml5
-rw-r--r--changelogs/unreleased/sh-update-rugged-v1-0-1.yml5
-rw-r--r--changelogs/unreleased/skr-ide.yml5
-rw-r--r--changelogs/unreleased/skr-refactor-users.yml5
-rw-r--r--changelogs/unreleased/sselhorn-sentence-case-ui.yml5
-rw-r--r--changelogs/unreleased/support-ci-resource-group-in-cross-project-pipeline.yml5
-rw-r--r--changelogs/unreleased/sy-add-shift-timeframe-index.yml5
-rw-r--r--changelogs/unreleased/sy-remove-alert-retriggering.yml6
-rw-r--r--changelogs/unreleased/sy-remove-final-alerts-service-pieces.yml5
-rw-r--r--changelogs/unreleased/sy-update-alerts-docs-urls.yml5
-rw-r--r--changelogs/unreleased/terraform-state-errors-graphql.yml5
-rw-r--r--changelogs/unreleased/terraform-states-migrate-task.yml5
-rw-r--r--changelogs/unreleased/test_update_merge_request_worker_performance.yml5
-rw-r--r--changelogs/unreleased/tor-defect-commit-message-placeholders.yml6
-rw-r--r--changelogs/unreleased/tor-defect-untranslated-strings.yml5
-rw-r--r--changelogs/unreleased/tor-defect-urlencode-image-diff-octothorpe.yml5
-rw-r--r--changelogs/unreleased/tor-feature-highlight-too-large-diffs.yml5
-rw-r--r--changelogs/unreleased/track-5-mins-prod-app-usage.yml5
-rw-r--r--changelogs/unreleased/track-ci-minutes-monthly.yml5
-rw-r--r--changelogs/unreleased/track-project-ci-minutes-monthly.yml5
-rw-r--r--changelogs/unreleased/ui-text-default-branch.yml5
-rw-r--r--changelogs/unreleased/ui-text-protected-environments.yml5
-rw-r--r--changelogs/unreleased/update-feature-flag-error-banner.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-25-0.yml5
-rw-r--r--changelogs/unreleased/update-input.yml5
-rw-r--r--changelogs/unreleased/update-starred-empty-state.yml5
-rw-r--r--changelogs/unreleased/update-table-pb.yml5
-rw-r--r--changelogs/unreleased/update-workhorse-8-61-0.yml5
-rw-r--r--changelogs/unreleased/update-workhorse-8-63.yml5
-rw-r--r--changelogs/unreleased/update_db_on_move_when_identical.yml5
-rw-r--r--changelogs/unreleased/upgrade-cluster-applications-v0-40-0.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-1-35.yml5
-rw-r--r--changelogs/unreleased/use-segmented-controls-ci-cd-analytics.yml5
-rw-r--r--changelogs/unreleased/variables-in-include-enable.yml5
-rw-r--r--changelogs/unreleased/vs-fix-alignment-rebase-in-progress.yml5
-rw-r--r--changelogs/unreleased/vs-fix-margin-for-rebase-based-workflows.yml5
-rw-r--r--changelogs/unreleased/wc-rsync-exclude-path.yml5
-rw-r--r--changelogs/unreleased/workhorse-8-62-0.yml5
-rw-r--r--changelogs/unreleased/xanf-add-filtering-and-pagination-to-bulk-import.yml5
-rw-r--r--changelogs/unreleased/yo-add-btn-default-ci.yml5
-rw-r--r--changelogs/unreleased/yo-btn-default-repo.yml5
-rw-r--r--changelogs/unreleased/yo-btn-info-fix.yml5
-rw-r--r--changelogs/unreleased/yo-canary-shortcut.yml5
-rw-r--r--changelogs/unreleased/yo-empty-labels-container.yml5
-rw-r--r--changelogs/unreleased/yo-empty-milestone.yml5
-rw-r--r--changelogs/unreleased/yo-fix-alertpage-alignment.yml5
-rw-r--r--changelogs/unreleased/yo-fix-border-radius.yml5
-rw-r--r--changelogs/unreleased/yo-fix-mr-edit-button.yml5
-rw-r--r--changelogs/unreleased/yo-fix-notes-bb.yml5
-rw-r--r--changelogs/unreleased/yo-fix-social-buttons.yml5
-rw-r--r--changelogs/unreleased/yo-fix-toggle-collapse-replies.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge-milestone.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge-protected-branch.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge-user-emails.yml5
-rw-r--r--changelogs/unreleased/yo-gl-badge-users-admin.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-admin.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-create-file-mr.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-issuable-create-button.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-issues.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-mirror-update.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-project-page.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-promotion.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-ra.yml5
-rw-r--r--changelogs/unreleased/yo-gl-button-revoke-button.yml5
-rw-r--r--changelogs/unreleased/yo-gl-card-admin.yml5
-rw-r--r--changelogs/unreleased/yo-gl-input-admin-application_settings.yml5
-rw-r--r--changelogs/unreleased/yo-gl-input-admin-users.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-input.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-ui-admin-appearance.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-ui-admin-applications.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-ui-admin-broadcast-messages.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-ui-admin-hooks.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-ui-admin-labels.yml5
-rw-r--r--changelogs/unreleased/yo-gl-new-ui-admin-license.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-87785.yml5
-rw-r--r--changelogs/unreleased/yo-move-to-gl-button.yml5
-rw-r--r--changelogs/unreleased/yo-new-admin-header.yml5
-rw-r--r--changelogs/unreleased/yo-new-input-auth.yml5
-rw-r--r--changelogs/unreleased/yo-pb-improve.yml5
-rw-r--r--changelogs/unreleased/yo-question-icon.yml5
-rw-r--r--changelogs/unreleased/yo-remove-activity-container.yml5
-rw-r--r--changelogs/unreleased/yo-remove-space.yml5
-rw-r--r--changelogs/unreleased/yo-remove-top-border-usage-quotos.yml5
-rw-r--r--changelogs/unreleased/yo-update-gl-button.yml5
-rw-r--r--changelogs/unreleased/yo-verified-gl-badge.yml5
-rw-r--r--changelogs/unreleased/zj-no-duplicate-deployments.yml5
-rw-r--r--config.ru8
-rw-r--r--config/application.rb36
-rw-r--r--config/boot.rb2
-rw-r--r--config/dependency_decisions.yml8
-rw-r--r--config/environment.rb2
-rw-r--r--config/environments/development.rb10
-rw-r--r--config/environments/production.rb2
-rw-r--r--config/environments/test.rb2
-rw-r--r--config/feature_categories.yml3
-rw-r--r--config/feature_flags/development/add_issues_button.yml2
-rw-r--r--config/feature_flags/development/ajax_new_deploy_token.yml2
-rw-r--r--config/feature_flags/development/allow_group_deploy_token.yml2
-rw-r--r--config/feature_flags/development/api_always_use_application_json.yml8
-rw-r--r--config/feature_flags/development/api_json_content_type.yml8
-rw-r--r--config/feature_flags/development/approval_suggestions.yml8
-rw-r--r--config/feature_flags/development/archive_rate_limit.yml6
-rw-r--r--config/feature_flags/development/batch_suggestions.yml8
-rw-r--r--config/feature_flags/development/board_new_list.yml8
-rw-r--r--config/feature_flags/development/branches_pagination_without_count.yml8
-rw-r--r--config/feature_flags/development/builds.yml8
-rw-r--r--config/feature_flags/development/cached_sidebar_open_issues_count.yml8
-rw-r--r--config/feature_flags/development/caching_experiments.yml8
-rw-r--r--config/feature_flags/development/canary_ingress_weight_control.yml2
-rw-r--r--config/feature_flags/development/ci_accept_frontend_prometheus_metrics.yml8
-rw-r--r--config/feature_flags/development/ci_allow_failure_with_exit_codes.yml8
-rw-r--r--config/feature_flags/development/ci_auto_cancel_all_pipelines.yml8
-rw-r--r--config/feature_flags/development/ci_config_merged_tab.yml8
-rw-r--r--config/feature_flags/development/ci_disable_validates_dependencies.yml8
-rw-r--r--config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml2
-rw-r--r--config/feature_flags/development/ci_instance_variables_ui.yml2
-rw-r--r--config/feature_flags/development/ci_job_jwt.yml2
-rw-r--r--config/feature_flags/development/ci_jwt_include_environment.yml8
-rw-r--r--config/feature_flags/development/ci_jwt_signing_key.yml2
-rw-r--r--config/feature_flags/development/ci_live_trace_use_fog_attributes.yml8
-rw-r--r--config/feature_flags/development/ci_mini_pipeline_gl_dropdown.yml8
-rw-r--r--config/feature_flags/development/ci_pipeline_open_merge_requests.yml8
-rw-r--r--config/feature_flags/development/ci_store_pipeline_messages.yml2
-rw-r--r--config/feature_flags/development/ci_synchronous_artifact_parsing.yml2
-rw-r--r--config/feature_flags/development/ci_trigger_payload_into_pipeline.yml8
-rw-r--r--config/feature_flags/development/ci_validate_build_dependencies.yml8
-rw-r--r--config/feature_flags/development/ci_validate_build_dependencies_override.yml8
-rw-r--r--config/feature_flags/development/clear_status_with_quick_options.yml8
-rw-r--r--config/feature_flags/development/codequality_backend_comparison.yml8
-rw-r--r--config/feature_flags/development/confidential_notes.yml8
-rw-r--r--config/feature_flags/development/context_commits.yml8
-rw-r--r--config/feature_flags/development/core_security_mr_widget.yml8
-rw-r--r--config/feature_flags/development/core_security_mr_widget_downloads.yml8
-rw-r--r--config/feature_flags/development/coverage_data_new_finder.yml8
-rw-r--r--config/feature_flags/development/dag_pipeline_tab.yml8
-rw-r--r--config/feature_flags/development/database_sourced_aggregated_metrics.yml8
-rw-r--r--config/feature_flags/development/default_merge_ref_for_diffs.yml2
-rw-r--r--config/feature_flags/development/deploy_keys_on_protected_branches.yml8
-rw-r--r--config/feature_flags/development/deploy_tokens_api.yml8
-rw-r--r--config/feature_flags/development/disable_git_http_fetch_writes.yml8
-rw-r--r--config/feature_flags/development/disable_ssh_key_used_tracking.yml8
-rw-r--r--config/feature_flags/development/drop_license_management_artifact.yml6
-rw-r--r--config/feature_flags/development/dynamic_nonce_creation.yml8
-rw-r--r--config/feature_flags/development/export_reduce_relation_batch_size.yml6
-rw-r--r--config/feature_flags/development/feature_flag_api.yml2
-rw-r--r--config/feature_flags/development/feature_flag_permissions.yml2
-rw-r--r--config/feature_flags/development/file_identifier_hash.yml6
-rw-r--r--config/feature_flags/development/forking.yml8
-rw-r--r--config/feature_flags/development/forward_deployment_enabled.yml2
-rw-r--r--config/feature_flags/development/generic_packages.yml2
-rw-r--r--config/feature_flags/development/gitaly_catfile-cache.yml8
-rw-r--r--config/feature_flags/development/gitaly_deny_disk_access.yml8
-rw-r--r--config/feature_flags/development/gitaly_upload_pack_gitaly_hooks.yml8
-rw-r--r--config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml8
-rw-r--r--config/feature_flags/development/gitlab_ci_trace_read_consistency.yml8
-rw-r--r--config/feature_flags/development/gitlab_experiments.yml8
-rw-r--r--config/feature_flags/development/gl_tooltips.yml8
-rw-r--r--config/feature_flags/development/graphql_individual_release_page.yml2
-rw-r--r--config/feature_flags/development/graphql_milestone_stats.yml2
-rw-r--r--config/feature_flags/development/graphql_pipeline_details_users.yml8
-rw-r--r--config/feature_flags/development/graphql_pipeline_header.yml8
-rw-r--r--config/feature_flags/development/graphql_release_data.yml2
-rw-r--r--config/feature_flags/development/graphql_releases_page.yml2
-rw-r--r--config/feature_flags/development/group_ci_cd_analytics_page.yml2
-rw-r--r--config/feature_flags/development/group_import_export.yml6
-rw-r--r--config/feature_flags/development/honor_escaped_markdown.yml8
-rw-r--r--config/feature_flags/development/import_requirements_csv.yml8
-rw-r--r--config/feature_flags/development/improved_merge_diff_highlighting.yml8
-rw-r--r--config/feature_flags/development/instance_statistics.yml2
-rw-r--r--config/feature_flags/development/issue_rebalancing_optimization.yml8
-rw-r--r--config/feature_flags/development/issues.yml8
-rw-r--r--config/feature_flags/development/jira_for_vulnerabilities.yml2
-rw-r--r--config/feature_flags/development/jira_issues_show_integration.yml8
-rw-r--r--config/feature_flags/development/jira_sync_builds.yml8
-rw-r--r--config/feature_flags/development/jira_sync_deployments.yml8
-rw-r--r--config/feature_flags/development/jira_sync_feature_flags.yml8
-rw-r--r--config/feature_flags/development/kubernetes_agent_on_gitlab_com.yml8
-rw-r--r--config/feature_flags/development/lfs_check.yml4
-rw-r--r--config/feature_flags/development/local_file_reviews.yml8
-rw-r--r--config/feature_flags/development/log_import_export_relation_creation.yml6
-rw-r--r--config/feature_flags/development/maintenance_mode.yml8
-rw-r--r--config/feature_flags/development/merge_request_draft_filter.yml2
-rw-r--r--config/feature_flags/development/merge_request_rebase_nowait_lock.yml8
-rw-r--r--config/feature_flags/development/merge_request_refs_cleanup.yml8
-rw-r--r--config/feature_flags/development/merge_request_reviewers.yml8
-rw-r--r--config/feature_flags/development/merge_requests.yml8
-rw-r--r--config/feature_flags/development/metrics_dashboard.yml8
-rw-r--r--config/feature_flags/development/migrate_user_mentions.yml2
-rw-r--r--config/feature_flags/development/multiline_comments.yml8
-rw-r--r--config/feature_flags/development/new_jira_connect_ui.yml2
-rw-r--r--config/feature_flags/development/new_pipeline_form_prefilled_vars.yml8
-rw-r--r--config/feature_flags/development/new_release_page.yml2
-rw-r--r--config/feature_flags/development/not_issuable_queries.yml2
-rw-r--r--config/feature_flags/development/operations.yml8
-rw-r--r--config/feature_flags/development/optimized_issuable_label_filter.yml4
-rw-r--r--config/feature_flags/development/optimized_merge_request_count_with_merged_at_filter.yml8
-rw-r--r--config/feature_flags/development/optimized_timebox_queries.yml8
-rw-r--r--config/feature_flags/development/optional_code_owners_sections.yml8
-rw-r--r--config/feature_flags/development/packages_and_registries_group_settings.yml8
-rw-r--r--config/feature_flags/development/pages.yml8
-rw-r--r--config/feature_flags/development/pages_serve_from_deployments.yml2
-rw-r--r--config/feature_flags/development/pages_serve_from_legacy_storage.yml8
-rw-r--r--config/feature_flags/development/pages_serve_from_migrated_zip.yml8
-rw-r--r--config/feature_flags/development/pages_serve_with_zip_file_protocol.yml4
-rw-r--r--config/feature_flags/development/pages_update_legacy_storage.yml8
-rw-r--r--config/feature_flags/development/paginate_commit_view.yml8
-rw-r--r--config/feature_flags/development/prohibit_hexadecimal_branch_names.yml6
-rw-r--r--config/feature_flags/development/project_list_filter_bar.yml8
-rw-r--r--config/feature_flags/development/query_deploymenys_via_finished_at_in_vsa.yml8
-rw-r--r--config/feature_flags/development/release_evidence.yml2
-rw-r--r--config/feature_flags/development/release_mr_issue_urls.yml2
-rw-r--r--config/feature_flags/development/remove_comment_close_reopen.yml8
-rw-r--r--config/feature_flags/development/remove_resolve_note.yml2
-rw-r--r--config/feature_flags/development/repository.yml8
-rw-r--r--config/feature_flags/development/repository_archive_hotlinking_interception.yml6
-rw-r--r--config/feature_flags/development/retarget_merge_requests.yml8
-rw-r--r--config/feature_flags/development/reviewer_approval_rules.yml8
-rw-r--r--config/feature_flags/development/rubygem_packages.yml8
-rw-r--r--config/feature_flags/development/secure_security_and_compliance_configuration_page_on_ce.yml8
-rw-r--r--config/feature_flags/development/similarity_search.yml2
-rw-r--r--config/feature_flags/development/simplified_commit_status_group_name.yml8
-rw-r--r--config/feature_flags/development/smart_cobertura_parser.yml8
-rw-r--r--config/feature_flags/development/snippets.yml8
-rw-r--r--config/feature_flags/development/sort_diffs.yml4
-rw-r--r--config/feature_flags/development/specialized_project_authorization_workers.yml4
-rw-r--r--config/feature_flags/development/squash_options.yml8
-rw-r--r--config/feature_flags/development/suggestions_custom_commit.yml2
-rw-r--r--config/feature_flags/development/trace_memory_allocations.yml8
-rw-r--r--config/feature_flags/development/track_issue_activity_actions.yml8
-rw-r--r--config/feature_flags/development/track_unique_visits.yml2
-rw-r--r--config/feature_flags/development/track_unique_wiki_page_views.yml8
-rw-r--r--config/feature_flags/development/tribute_autocomplete.yml2
-rw-r--r--config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml6
-rw-r--r--config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml2
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_edit_mr_desc.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_edit_mr_title.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_add_suggestion.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_apply_suggestion.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_approval_rule_added.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_approval_rule_deleted.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_approval_rule_edited.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_approve_mr.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_assigned.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_create_mr_from_issue.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_marked_as_draft.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_resolve_thread.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_review_requested.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_toggled_task_item_status.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_unapprove_mr.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_unmarked_as_draft.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_unresolve_thread.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_code_review_user_vs_code_api_request.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_load_performance_widget_total.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml8
-rw-r--r--config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml8
-rw-r--r--config/feature_flags/development/usage_data_track_quickactions.yml8
-rw-r--r--config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml8
-rw-r--r--config/feature_flags/development/use_workhorse_s3_client.yml2
-rw-r--r--config/feature_flags/development/user_mode_in_session.yml8
-rw-r--r--config/feature_flags/development/user_time_settings.yml8
-rw-r--r--config/feature_flags/development/validate_import_decompressed_archive_size.yml6
-rw-r--r--config/feature_flags/development/variables_in_include_section_ci.yml8
-rw-r--r--config/feature_flags/development/vue_epics_list.yml8
-rw-r--r--config/feature_flags/development/vue_issuable_sidebar.yml8
-rw-r--r--config/feature_flags/development/vue_notification_dropdown.yml8
-rw-r--r--config/feature_flags/development/vue_project_members_list.yml8
-rw-r--r--config/feature_flags/development/webperf_experiment.yml8
-rw-r--r--config/feature_flags/development/whats_new_drawer.yml8
-rw-r--r--config/feature_flags/development/wiki.yml8
-rw-r--r--config/feature_flags/development/workhorse_archive_cache_disabled.yml6
-rw-r--r--config/feature_flags/experiment/default_to_issues_board_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/in_product_marketing_emails_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml2
-rw-r--r--config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/learn_gitlab_a_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/learn_gitlab_b_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/members_invite_email.yml8
-rw-r--r--config/feature_flags/experiment/onboarding_issues_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/pipelines_empty_state_experiment_percentage.yml8
-rw-r--r--config/feature_flags/ops/scalability_ci_fetch_sha.yml8
-rw-r--r--config/gitlab.yml.example10
-rw-r--r--config/helpers/incremental_webpack_compiler.js128
-rw-r--r--config/initializers/01_secret_token.rb2
-rw-r--r--config/initializers/0_acts_as_taggable.rb2
-rw-r--r--config/initializers/0_inject_enterprise_edition_module.rb35
-rw-r--r--config/initializers/0_inject_feature_flags.rb2
-rw-r--r--config/initializers/0_marginalia.rb5
-rw-r--r--config/initializers/0_post_deployment_migrations.rb2
-rw-r--r--config/initializers/1_settings.rb27
-rw-r--r--config/initializers/2_gitlab.rb2
-rw-r--r--config/initializers/5_backend.rb2
-rw-r--r--config/initializers/6_validations.rb2
-rw-r--r--config/initializers/7_prometheus_metrics.rb47
-rw-r--r--config/initializers/7_redis.rb2
-rw-r--r--config/initializers/8_devise.rb2
-rw-r--r--config/initializers/8_gitaly.rb2
-rw-r--r--config/initializers/9_fast_gettext.rb2
-rw-r--r--config/initializers/action_dispatch_http_mime_negotiation.rb2
-rw-r--r--config/initializers/action_mailer_hooks.rb2
-rw-r--r--config/initializers/active_record_data_types.rb2
-rw-r--r--config/initializers/active_record_ping.rb2
-rw-r--r--config/initializers/active_record_preloader.rb2
-rw-r--r--config/initializers/active_record_schema_ignore_tables.rb2
-rw-r--r--config/initializers/active_record_table_definition.rb2
-rw-r--r--config/initializers/ar_speed_up_migration_checking.rb2
-rw-r--r--config/initializers/asset_proxy_settings.rb2
-rw-r--r--config/initializers/attr_encrypted_no_db_connection.rb2
-rw-r--r--config/initializers/backtrace_silencers.rb2
-rw-r--r--config/initializers/batch_loader.rb2
-rw-r--r--config/initializers/bootstrap_form.rb2
-rw-r--r--config/initializers/bullet.rb2
-rw-r--r--config/initializers/cluster_events_before_phased_restart.rb2
-rw-r--r--config/initializers/console_message.rb2
-rw-r--r--config/initializers/cookies_serializer.rb2
-rw-r--r--config/initializers/date_time_formats.rb2
-rw-r--r--config/initializers/default_url_options.rb2
-rw-r--r--config/initializers/deprecations.rb2
-rw-r--r--config/initializers/direct_upload_support.rb2
-rw-r--r--config/initializers/doorkeeper.rb2
-rw-r--r--config/initializers/doorkeeper_openid_connect.rb2
-rw-r--r--config/initializers/etag_caching.rb2
-rw-r--r--config/initializers/faraday.rb3
-rw-r--r--config/initializers/fill_shards.rb2
-rw-r--r--config/initializers/fix_local_cache_middleware.rb2
-rw-r--r--config/initializers/fog_google_https_private_urls.rb2
-rw-r--r--config/initializers/forbid_sidekiq_in_transactions.rb2
-rw-r--r--config/initializers/gettext_rails_i18n_patch.rb2
-rw-r--r--config/initializers/gitlab_kas_secret.rb2
-rw-r--r--config/initializers/gitlab_shell_secret_token.rb2
-rw-r--r--config/initializers/gitlab_workhorse_secret.rb2
-rw-r--r--config/initializers/go_get.rb2
-rw-r--r--config/initializers/grpc.rb2
-rw-r--r--config/initializers/hamlit.rb2
-rw-r--r--config/initializers/health_check.rb2
-rw-r--r--config/initializers/http_hostname_override.rb2
-rw-r--r--config/initializers/kaminari_active_record_relation_methods_with_limit.rb2
-rw-r--r--config/initializers/kaminari_config.rb2
-rw-r--r--config/initializers/lograge.rb2
-rw-r--r--config/initializers/mail_encoding_patch.rb2
-rw-r--r--config/initializers/mime_types.rb2
-rw-r--r--config/initializers/mini_magick.rb2
-rw-r--r--config/initializers/net_http_patch.rb33
-rw-r--r--config/initializers/new_framework_defaults.rb2
-rw-r--r--config/initializers/octokit.rb2
-rw-r--r--config/initializers/omniauth.rb2
-rw-r--r--config/initializers/peek.rb3
-rw-r--r--config/initializers/postgresql_cte.rb2
-rw-r--r--config/initializers/premailer.rb2
-rw-r--r--config/initializers/query_limiting.rb2
-rw-r--r--config/initializers/rack_attack_logging.rb38
-rw-r--r--config/initializers/rack_lineprof.rb2
-rw-r--r--config/initializers/relative_naming_ci_namespace.rb2
-rw-r--r--config/initializers/request_context.rb2
-rw-r--r--config/initializers/request_profiler.rb2
-rw-r--r--config/initializers/routing_draw.rb2
-rw-r--r--config/initializers/sentry.rb2
-rw-r--r--config/initializers/server_uptime.rb2
-rw-r--r--config/initializers/session_store.rb2
-rw-r--r--config/initializers/sherlock.rb2
-rw-r--r--config/initializers/sidekiq.rb4
-rw-r--r--config/initializers/sprockets.rb2
-rw-r--r--config/initializers/static_files.rb2
-rw-r--r--config/initializers/time_zone.rb2
-rw-r--r--config/initializers/tracing.rb1
-rw-r--r--config/initializers/trusted_proxies.rb2
-rw-r--r--config/initializers/validate_puma.rb10
-rw-r--r--config/initializers/warden.rb2
-rw-r--r--config/initializers/workhorse_multipart.rb2
-rw-r--r--config/initializers/wrap_parameters.rb2
-rw-r--r--config/initializers/zz_metrics.rb17
-rw-r--r--config/initializers_before_autoloader/000_inflections.rb2
-rw-r--r--config/known_invalid_graphql_queries.yml4
-rw-r--r--config/metrics/counts_28d/20210201124930_deployments.yml20
-rw-r--r--config/metrics/counts_28d/deployments.yml15
-rw-r--r--config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml20
-rw-r--r--config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml16
-rw-r--r--config/metrics/counts_all/20210201124934_deployments.yml19
-rw-r--r--config/metrics/counts_all/20210204124930_servers.yml14
-rw-r--r--config/metrics/counts_all/20210204124932_clusters.yml14
-rw-r--r--config/metrics/counts_all/deployments.yml15
-rw-r--r--config/metrics/license/20210201124932_recorded_at.yml20
-rw-r--r--config/metrics/license/20210201124933_uuid.yml20
-rw-r--r--config/metrics/license/20210204124827_hostname.yml19
-rw-r--r--config/metrics/license/20210204124829_active_user_count.yml19
-rw-r--r--config/metrics/license/20210204124854_license_management_jobs.yml16
-rw-r--r--config/metrics/license/20210204124926_license_trial_ends_on.yml14
-rw-r--r--config/metrics/license/20210204124928_version.yml14
-rw-r--r--config/metrics/license/20210204124936_version.yml14
-rw-r--r--config/metrics/license/20210204124938_recording_ce_finished_at.yml16
-rw-r--r--config/metrics/license/recorded_at.yml16
-rw-r--r--config/metrics/license/uuid.yml17
-rw-r--r--config/metrics/schema.json34
-rw-r--r--config/metrics/settings/20210201124935_database_adapter.yml18
-rw-r--r--config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124858_container_registry_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124900_dependency_proxy_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124904_gravatar_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124906_ldap_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124908_mattermost_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124910_omniauth_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124912_prometheus_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124916_reply_by_email_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124918_signup_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124922_grafana_link_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124924_elasticsearch_enabled.yml14
-rw-r--r--config/metrics/settings/20210204124934_enabled.yml14
-rw-r--r--config/metrics/settings/database_adapter.yml14
-rw-r--r--config/object_store_settings.rb16
-rw-r--r--config/puma.example.development.rb2
-rw-r--r--config/puma.rb.example2
-rw-r--r--config/puma_actioncable.example.development.rb2
-rw-r--r--config/routes.rb27
-rw-r--r--config/routes/admin.rb2
-rw-r--r--config/routes/api.rb2
-rw-r--r--config/routes/dashboard.rb2
-rw-r--r--config/routes/development.rb2
-rw-r--r--config/routes/explore.rb2
-rw-r--r--config/routes/git_http.rb6
-rw-r--r--config/routes/google_api.rb2
-rw-r--r--config/routes/group.rb1
-rw-r--r--config/routes/help.rb2
-rw-r--r--config/routes/import.rb2
-rw-r--r--config/routes/legacy_builds.rb2
-rw-r--r--config/routes/merge_requests.rb1
-rw-r--r--config/routes/project.rb13
-rw-r--r--config/routes/repository.rb2
-rw-r--r--config/routes/sherlock.rb2
-rw-r--r--config/routes/sidekiq.rb2
-rw-r--r--config/routes/snippets.rb2
-rw-r--r--config/routes/uploads.rb2
-rw-r--r--config/routes/user.rb4
-rw-r--r--config/routes/wiki.rb2
-rw-r--r--config/sidekiq_queues.yml12
-rw-r--r--config/smime_signature_settings.rb2
-rw-r--r--config/spring.rb2
-rw-r--r--config/webpack.config.js26
-rw-r--r--danger/changelog/Dangerfile2
-rw-r--r--danger/changes_size/Dangerfile2
-rw-r--r--danger/commit_messages/Dangerfile8
-rw-r--r--danger/feature_flag/Dangerfile78
-rw-r--r--danger/frozen_string/Dangerfile47
-rw-r--r--danger/metadata/Dangerfile6
-rw-r--r--danger/pipeline/Dangerfile7
-rw-r--r--danger/plugins/changelog.rb4
-rw-r--r--danger/plugins/feature_flag.rb10
-rw-r--r--danger/plugins/helper.rb6
-rw-r--r--danger/plugins/roulette.rb4
-rw-r--r--danger/plugins/sidekiq_queues.rb4
-rw-r--r--danger/product_intelligence/Dangerfile39
-rw-r--r--danger/roulette/Dangerfile6
-rw-r--r--data/whats_new/202008180001_12_10.yml6
-rw-r--r--data/whats_new/202008180002_13_0.yml8
-rw-r--r--data/whats_new/202008180003_13_01.yml12
-rw-r--r--data/whats_new/202008210001_13_02.yml12
-rw-r--r--data/whats_new/202009150001_13_03.yml4
-rw-r--r--data/whats_new/202009300001_13_04.yml15
-rw-r--r--data/whats_new/202010230001_13_05.yml8
-rw-r--r--data/whats_new/202011230001_13_06.yml8
-rw-r--r--data/whats_new/202012160001_13_07.yml6
-rw-r--r--data/whats_new/202101140001_13_08.yml12
-rw-r--r--data/whats_new/templates/YYYYMMDD0001_XX_YY.yml32
-rw-r--r--db/fixtures/development/25_api_personal_access_token.rb2
-rw-r--r--db/fixtures/development/30_composer_packages.rb121
-rw-r--r--db/migrate/20190225152525_add_auto_dev_ops_enabled_to_namespaces.rb2
-rw-r--r--db/migrate/20190325080727_truncate_user_fullname.rb2
-rw-r--r--db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb2
-rw-r--r--db/migrate/20190621022810_add_last_ci_minutes_usage_notification_level_to_namespaces.rb2
-rw-r--r--db/migrate/20190626175626_add_group_creation_level_to_namespaces.rb2
-rw-r--r--db/migrate/20190715215549_add_group_emails_disabled.rb2
-rw-r--r--db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb2
-rw-r--r--db/migrate/20190828172831_create_package_tag.rb2
-rw-r--r--db/migrate/20190911115109_add_namespaces_max_pages_size.rb2
-rw-r--r--db/migrate/20190911115222_add_namespaces_max_artifacts_size.rb2
-rw-r--r--db/migrate/20191003195218_add_pendo_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20191003195620_add_pendo_url_to_application_settings.rb2
-rw-r--r--db/migrate/20191114132259_add_mentions_disabled_to_namespaces.rb2
-rw-r--r--db/migrate/20191120200015_add_index_to_grafana_integrations.rb2
-rw-r--r--db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb2
-rw-r--r--db/migrate/20200229171700_create_custom_emojis.rb2
-rw-r--r--db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb2
-rw-r--r--db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb2
-rw-r--r--db/migrate/20200407120000_add_push_rule_id_to_groups.rb2
-rw-r--r--db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb4
-rw-r--r--db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb2
-rw-r--r--db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb2
-rw-r--r--db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb2
-rw-r--r--db/migrate/20201027101010_create_user_follow_users.rb24
-rw-r--r--db/migrate/20201108134919_add_finding_fingerprint_table.rb40
-rw-r--r--db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb2
-rw-r--r--db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb11
-rw-r--r--db/migrate/20201120144823_create_tokens_with_iv.rb18
-rw-r--r--db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb18
-rw-r--r--db/migrate/20201204111200_create_packages_debian_project_components.rb35
-rw-r--r--db/migrate/20201204111300_create_packages_debian_group_components.rb35
-rw-r--r--db/migrate/20201204111400_create_packages_debian_project_component_files.rb41
-rw-r--r--db/migrate/20201204111500_create_packages_debian_group_component_files.rb41
-rw-r--r--db/migrate/20201204111600_create_packages_debian_publications.rb19
-rw-r--r--db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb2
-rw-r--r--db/migrate/20201221225303_add_service_desk_reply_to_is_not_null_index_on_issues.rb18
-rw-r--r--db/migrate/20210105052034_rename_asset_proxy_whitelist_on_application_settings.rb21
-rw-r--r--db/migrate/20210105153342_add_entity_columns_to_vulnerability_occurrences.rb16
-rw-r--r--db/migrate/20210105154321_add_text_limit_to_vulnerability_occurrences_entity_columns.rb23
-rw-r--r--db/migrate/20210106155209_add_merge_request_diff_commit_trailers.rb22
-rw-r--r--db/migrate/20210106225424_add_keep_latest_artifacts_to_application_settings.rb11
-rw-r--r--db/migrate/20210107105306_add_diff_type_to_merge_request_diffs.rb31
-rw-r--r--db/migrate/20210107154615_add_merge_request_context_commit_trailers.rb12
-rw-r--r--db/migrate/20210111051045_create_dast_profiles.rb35
-rw-r--r--db/migrate/20210111053308_add_project_fk_for_dast_profile.rb19
-rw-r--r--db/migrate/20210111075104_add_temporary_index_on_security_findings_scan_id.rb18
-rw-r--r--db/migrate/20210112202949_create_composer_cache_file.rb34
-rw-r--r--db/migrate/20210113224909_add_pipeline_configuration_full_path_to_compliance_pipeline.rb16
-rw-r--r--db/migrate/20210113231532_add_converted_at_to_experiment_subjects.rb9
-rw-r--r--db/migrate/20210113231546_add_context_to_experiment_subjects.rb9
-rw-r--r--db/migrate/20210114142443_add_indexes_to_onboarding_progresses.rb27
-rw-r--r--db/migrate/20210115090452_create_group_repository_storage_move.rb34
-rw-r--r--db/migrate/20210117210226_add_has_external_issue_tracker_trigger.rb61
-rw-r--r--db/migrate/20210118111307_add_enforce_ssh_key_expiration_to_application_settings.rb9
-rw-r--r--db/migrate/20210119153801_add_proxy_settings_to_jira_tracker_data.rb16
-rw-r--r--db/migrate/20210119162812_add_text_limit_to_compliance_pipeline_configuration_full_path.rb17
-rw-r--r--db/migrate/20210120180956_extend_index_on_ci_builds_metadata.rb40
-rw-r--r--db/migrate/20210120221743_delete_oauth_applications_tmp_index.rb18
-rw-r--r--db/migrate/20210121093618_remove_repository_read_only_to_groups.rb23
-rw-r--r--db/migrate/20210121100038_add_devops_adoption_group_segment.rb18
-rw-r--r--db/migrate/20210121121102_optional_devops_adoption_segment_name.rb24
-rw-r--r--db/migrate/20210122073805_add_repository_read_only_to_namespace_settings.rb19
-rw-r--r--db/migrate/20210122153259_add_state_to_merge_request_reviewers.rb11
-rw-r--r--db/migrate/20210122155158_add_pipeline_step_to_bulk_imports_failures.rb25
-rw-r--r--db/migrate/20210125105410_add_devops_adoption_segment_namespace_fk.rb17
-rw-r--r--db/migrate/20210126030249_add_security_dashboard_access_level_into_project_features.rb20
-rw-r--r--db/migrate/20210126091713_add_unique_index_services_project_id_and_type.rb19
-rw-r--r--db/migrate/20210126092102_remove_index_services_project_id_and_type.rb20
-rw-r--r--db/migrate/20210126233608_add_rubygems_max_file_size_to_plan_limits.rb9
-rw-r--r--db/migrate/20210127052226_add_subgroup_events_to_web_hooks.rb9
-rw-r--r--db/migrate/20210127143025_add_oldest_merge_requests_index.rb13
-rw-r--r--db/migrate/20210128044930_add_git_two_factor_session_expiry_to_application_settings.rb9
-rw-r--r--db/migrate/20210128101707_add_prevent_merge_without_jira_issue_to_project_settings.rb18
-rw-r--r--db/migrate/20210128114526_add_auto_delete_at_to_environments.rb19
-rw-r--r--db/migrate/20210128140157_add_content_type_to_dependency_proxy_manifests.rb12
-rw-r--r--db/migrate/20210128140232_add_text_limit_to_dependency_proxy_manifests_content_type.rb16
-rw-r--r--db/migrate/20210128152830_create_ci_namespace_monthly_usage.rb30
-rw-r--r--db/migrate/20210129225244_add_index_to_oncall_shfts_on_starts_at_and_ends_at.rb24
-rw-r--r--db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb59
-rw-r--r--db/migrate/20210203002331_drop_backup_label_index.rb19
-rw-r--r--db/migrate/20210203092540_remove_has_external_wiki_constraint.rb20
-rw-r--r--db/migrate/20210203092549_restore_has_external_wiki_default_value.rb31
-rw-r--r--db/migrate/20210203221631_create_packages_rubygems_metadata.rb69
-rw-r--r--db/migrate/20210203222620_add_expired_index_to_composer_cache_files.rb19
-rw-r--r--db/migrate/20210203223551_add_orphan_index_to_composer_cache_files.rb19
-rw-r--r--db/migrate/20210204152257_add_status_to_packages_packages.rb9
-rw-r--r--db/migrate/20210204212850_add_group_id_to_ci_daily_build_group_report_results.rb9
-rw-r--r--db/migrate/20210205084357_create_ci_project_monthly_usage.rb29
-rw-r--r--db/migrate/20210205143926_remove_namespace_id_foreign_key_on_namespace_onboarding_actions.rb19
-rw-r--r--db/migrate/20210205213915_remove_foreign_keys_from_alerts_service_data.rb19
-rw-r--r--db/migrate/20210208125050_add_status_expires_at_to_user_statuses.rb19
-rw-r--r--db/migrate/20210208125248_add_index_on_user_statuses_status_expires_at.rb18
-rw-r--r--db/migrate/20210208144134_add_index_group_id_to_ci_daily_build_group_report_results.rb20
-rw-r--r--db/migrate/20210208161207_add_notes_create_limit_to_application_settings.rb9
-rw-r--r--db/migrate/20210209160510_create_security_orchestration_policy_configurations.rb25
-rw-r--r--db/migrate/20210209171525_add_status_index_to_packages_packages.rb19
-rw-r--r--db/migrate/20210210210232_add_notes_create_limit_allowlist_to_application_settings.rb9
-rw-r--r--db/migrate/20210211195543_add_created_by_user_for_cluster_agent_token.rb28
-rw-r--r--db/migrate/20210216135504_add_created_by_to_cluster_agent.rb27
-rw-r--r--db/optional_migrations/composite_primary_keys.rb2
-rw-r--r--db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb2
-rw-r--r--db/post_migrate/20190606175050_encrypt_feature_flags_clients_tokens.rb2
-rw-r--r--db/post_migrate/20190711201818_encrypt_deploy_tokens_tokens.rb2
-rw-r--r--db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb2
-rw-r--r--db/post_migrate/20200424043515_drop_namespaces_plan_id.rb2
-rw-r--r--db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb2
-rw-r--r--db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb38
-rw-r--r--db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb31
-rw-r--r--db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb88
-rw-r--r--db/post_migrate/20210105052229_clean_up_asset_proxy_whitelist_rename_on_application_settings.rb21
-rw-r--r--db/post_migrate/20210111075105_schedule_uuid_population_for_security_findings.rb26
-rw-r--r--db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb48
-rw-r--r--db/post_migrate/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value.rb34
-rw-r--r--db/post_migrate/20210203143131_migrate_existing_devops_segments_to_groups.rb15
-rw-r--r--db/post_migrate/20210205104425_add_new_post_eoa_plans.rb14
-rw-r--r--db/post_migrate/20210205144537_remove_namespace_onboarding_actions_table.rb23
-rw-r--r--db/post_migrate/20210205174154_remove_bad_dependency_proxy_manifests.rb15
-rw-r--r--db/post_migrate/20210205213933_drop_alerts_service_data.rb26
-rw-r--r--db/post_migrate/20210205214003_remove_alerts_service_records_again.rb19
-rw-r--r--db/post_migrate/20210210093901_backfill_updated_at_after_repository_storage_move.rb34
-rw-r--r--db/schema_migrations/202010271010101
-rw-r--r--db/schema_migrations/202011081349191
-rw-r--r--db/schema_migrations/202011121307101
-rw-r--r--db/schema_migrations/202011200920001
-rw-r--r--db/schema_migrations/202011201448231
-rw-r--r--db/schema_migrations/202011271042281
-rw-r--r--db/schema_migrations/202011282102341
-rw-r--r--db/schema_migrations/202012041112001
-rw-r--r--db/schema_migrations/202012041113001
-rw-r--r--db/schema_migrations/202012041114001
-rw-r--r--db/schema_migrations/202012041115001
-rw-r--r--db/schema_migrations/202012041116001
-rw-r--r--db/schema_migrations/202012212253031
-rw-r--r--db/schema_migrations/202101050301251
-rw-r--r--db/schema_migrations/202101050520341
-rw-r--r--db/schema_migrations/202101050522291
-rw-r--r--db/schema_migrations/202101051533421
-rw-r--r--db/schema_migrations/202101051543211
-rw-r--r--db/schema_migrations/202101061552091
-rw-r--r--db/schema_migrations/202101062254241
-rw-r--r--db/schema_migrations/202101071053061
-rw-r--r--db/schema_migrations/202101071546151
-rw-r--r--db/schema_migrations/202101110510451
-rw-r--r--db/schema_migrations/202101110533081
-rw-r--r--db/schema_migrations/202101110751041
-rw-r--r--db/schema_migrations/202101110751051
-rw-r--r--db/schema_migrations/202101122029491
-rw-r--r--db/schema_migrations/202101132249091
-rw-r--r--db/schema_migrations/202101132315321
-rw-r--r--db/schema_migrations/202101132315461
-rw-r--r--db/schema_migrations/202101141424431
-rw-r--r--db/schema_migrations/202101150904521
-rw-r--r--db/schema_migrations/202101152206101
-rw-r--r--db/schema_migrations/202101172102261
-rw-r--r--db/schema_migrations/202101181113071
-rw-r--r--db/schema_migrations/202101191223541
-rw-r--r--db/schema_migrations/202101191538011
-rw-r--r--db/schema_migrations/202101191628121
-rw-r--r--db/schema_migrations/202101201809561
-rw-r--r--db/schema_migrations/202101202217431
-rw-r--r--db/schema_migrations/202101210936181
-rw-r--r--db/schema_migrations/202101211000381
-rw-r--r--db/schema_migrations/202101211211021
-rw-r--r--db/schema_migrations/202101220738051
-rw-r--r--db/schema_migrations/202101221532591
-rw-r--r--db/schema_migrations/202101221551581
-rw-r--r--db/schema_migrations/202101251054101
-rw-r--r--db/schema_migrations/202101260302491
-rw-r--r--db/schema_migrations/202101260917131
-rw-r--r--db/schema_migrations/202101260921021
-rw-r--r--db/schema_migrations/202101262336081
-rw-r--r--db/schema_migrations/202101270522261
-rw-r--r--db/schema_migrations/202101271430251
-rw-r--r--db/schema_migrations/202101280449301
-rw-r--r--db/schema_migrations/202101281017071
-rw-r--r--db/schema_migrations/202101281145261
-rw-r--r--db/schema_migrations/202101281401571
-rw-r--r--db/schema_migrations/202101281402321
-rw-r--r--db/schema_migrations/202101281528301
-rw-r--r--db/schema_migrations/202101292252441
-rw-r--r--db/schema_migrations/202102011404341
-rw-r--r--db/schema_migrations/202102030023311
-rw-r--r--db/schema_migrations/202102030925401
-rw-r--r--db/schema_migrations/202102030925491
-rw-r--r--db/schema_migrations/202102031431311
-rw-r--r--db/schema_migrations/202102032216311
-rw-r--r--db/schema_migrations/202102032226201
-rw-r--r--db/schema_migrations/202102032235511
-rw-r--r--db/schema_migrations/202102041522571
-rw-r--r--db/schema_migrations/202102042128501
-rw-r--r--db/schema_migrations/202102050843571
-rw-r--r--db/schema_migrations/202102051044251
-rw-r--r--db/schema_migrations/202102051439261
-rw-r--r--db/schema_migrations/202102051445371
-rw-r--r--db/schema_migrations/202102051741541
-rw-r--r--db/schema_migrations/202102052139151
-rw-r--r--db/schema_migrations/202102052139331
-rw-r--r--db/schema_migrations/202102052140031
-rw-r--r--db/schema_migrations/202102081250501
-rw-r--r--db/schema_migrations/202102081252481
-rw-r--r--db/schema_migrations/202102081441341
-rw-r--r--db/schema_migrations/202102081612071
-rw-r--r--db/schema_migrations/202102091605101
-rw-r--r--db/schema_migrations/202102091715251
-rw-r--r--db/schema_migrations/202102100939011
-rw-r--r--db/schema_migrations/202102102102321
-rw-r--r--db/schema_migrations/202102111955431
-rw-r--r--db/schema_migrations/202102161355041
-rw-r--r--db/structure.sql706
-rw-r--r--doc/.vale/gitlab/Acronyms.yml13
-rw-r--r--doc/.vale/gitlab/Admin.yml6
-rw-r--r--doc/.vale/gitlab/SubstitutionSuggestions.yml2
-rw-r--r--doc/.vale/gitlab/Substitutions.yml3
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt155
-rw-r--r--doc/README.md94
-rw-r--r--doc/administration/application_settings_cache.md47
-rw-r--r--doc/administration/audit_events.md28
-rw-r--r--doc/administration/auditor_users.md12
-rw-r--r--doc/administration/auth/README.md7
-rw-r--r--doc/administration/auth/google_secure_ldap.md8
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md8
-rw-r--r--doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md8
-rw-r--r--doc/administration/auth/img/okta_admin_panel_v13_9.pngbin0 -> 49319 bytes
-rw-r--r--doc/administration/auth/ldap-ee.md8
-rw-r--r--doc/administration/auth/ldap-troubleshooting.md8
-rw-r--r--doc/administration/auth/ldap.md8
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/ldap/index.md71
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md34
-rw-r--r--doc/administration/auth/oidc.md43
-rw-r--r--doc/administration/auth/okta.md8
-rw-r--r--doc/administration/auth/smartcard.md2
-rw-r--r--doc/administration/availability/index.md8
-rw-r--r--doc/administration/build_artifacts.md8
-rw-r--r--doc/administration/compliance.md20
-rw-r--r--doc/administration/consul.md2
-rw-r--r--doc/administration/container_registry.md8
-rw-r--r--doc/administration/custom_hooks.md8
-rw-r--r--doc/administration/database_load_balancing.md2
-rw-r--r--doc/administration/dependency_proxy.md8
-rw-r--r--doc/administration/encrypted_configuration.md4
-rw-r--r--doc/administration/external_database.md7
-rw-r--r--doc/administration/feature_flags.md2
-rw-r--r--doc/administration/file_hooks.md31
-rw-r--r--doc/administration/geo/disaster_recovery/background_verification.md6
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md2
-rw-r--r--doc/administration/geo/disaster_recovery/index.md21
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md45
-rw-r--r--doc/administration/geo/disaster_recovery/promotion_runbook.md8
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md2
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md15
-rw-r--r--doc/administration/geo/index.md2
-rw-r--r--doc/administration/geo/replication/configuration.md6
-rw-r--r--doc/administration/geo/replication/database.md8
-rw-r--r--doc/administration/geo/replication/datatypes.md50
-rw-r--r--doc/administration/geo/replication/disable_geo.md2
-rw-r--r--doc/administration/geo/replication/docker_registry.md2
-rw-r--r--doc/administration/geo/replication/external_database.md8
-rw-r--r--doc/administration/geo/replication/faq.md2
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md6
-rw-r--r--doc/administration/geo/replication/high_availability.md8
-rw-r--r--doc/administration/geo/replication/index.md8
-rw-r--r--doc/administration/geo/replication/location_aware_git_url.md2
-rw-r--r--doc/administration/geo/replication/multiple_servers.md2
-rw-r--r--doc/administration/geo/replication/object_storage.md4
-rw-r--r--doc/administration/geo/replication/remove_geo_node.md6
-rw-r--r--doc/administration/geo/replication/security_review.md12
-rw-r--r--doc/administration/geo/replication/troubleshooting.md91
-rw-r--r--doc/administration/geo/replication/tuning.md4
-rw-r--r--doc/administration/geo/replication/updating_the_geo_nodes.md2
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md2
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md544
-rw-r--r--doc/administration/geo/setup/database.md83
-rw-r--r--doc/administration/geo/setup/external_database.md2
-rw-r--r--doc/administration/git_annex.md18
-rw-r--r--doc/administration/git_protocol.md10
-rw-r--r--doc/administration/gitaly/index.md119
-rw-r--r--doc/administration/gitaly/praefect.md241
-rw-r--r--doc/administration/gitaly/reference.md14
-rw-r--r--doc/administration/housekeeping.md2
-rw-r--r--doc/administration/img/impersonated_audit_events_v13_8.pngbin0 -> 11908 bytes
-rw-r--r--doc/administration/img/time_zone_settings.pngbin0 -> 15330 bytes
-rw-r--r--doc/administration/index.md26
-rw-r--r--doc/administration/instance_limits.md52
-rw-r--r--doc/administration/instance_review.md2
-rw-r--r--doc/administration/integration/kroki.md18
-rw-r--r--doc/administration/integration/plantuml.md78
-rw-r--r--doc/administration/integration/terminal.md38
-rw-r--r--doc/administration/invalidate_markdown_cache.md10
-rw-r--r--doc/administration/issue_closing_pattern.md2
-rw-r--r--doc/administration/job_artifacts.md16
-rw-r--r--doc/administration/job_logs.md2
-rw-r--r--doc/administration/job_traces.md8
-rw-r--r--doc/administration/lfs/index.md88
-rw-r--r--doc/administration/lfs/lfs_administration.md8
-rw-r--r--doc/administration/lfs/manage_large_binaries_with_git_lfs.md8
-rw-r--r--doc/administration/lfs/migrate_from_git_annex_to_git_lfs.md8
-rw-r--r--doc/administration/logs.md37
-rw-r--r--doc/administration/maintenance_mode/index.md206
-rw-r--r--doc/administration/maintenance_mode/maintenance_mode_error_message.pngbin0 -> 14666 bytes
-rw-r--r--doc/administration/maven_packages.md8
-rw-r--r--doc/administration/maven_repository.md8
-rw-r--r--doc/administration/merge_request_diffs.md26
-rw-r--r--doc/administration/monitoring/github_imports.md2
-rw-r--r--doc/administration/monitoring/gitlab_instance_administration_project/index.md8
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md14
-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.md16
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md48
-rw-r--r--doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.pngbin7761 -> 0 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_dashboard_import.pngbin11835 -> 0 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_data_source_configuration.pngbin14695 -> 0 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_data_source_empty.pngbin11960 -> 0 bytes
-rw-r--r--doc/administration/monitoring/performance/img/grafana_save_icon.pngbin4598 -> 0 bytes
-rw-r--r--doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.pngbin26169 -> 0 bytes
-rw-r--r--doc/administration/monitoring/performance/img/performance_bar_external_http_calls.pngbin0 -> 56569 bytes
-rw-r--r--doc/administration/monitoring/performance/index.md2
-rw-r--r--doc/administration/monitoring/performance/influxdb_configuration.md5
-rw-r--r--doc/administration/monitoring/performance/influxdb_schema.md5
-rw-r--r--doc/administration/monitoring/performance/introduction.md8
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md8
-rw-r--r--doc/administration/monitoring/performance/prometheus.md8
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md176
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md8
-rw-r--r--doc/administration/monitoring/prometheus/index.md12
-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/redis_exporter.md2
-rw-r--r--doc/administration/monitoring/prometheus/registry_exporter.md2
-rw-r--r--doc/administration/nfs.md8
-rw-r--r--doc/administration/npm_registry.md8
-rw-r--r--doc/administration/object_storage.md44
-rw-r--r--doc/administration/operations.md8
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md8
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md2
-rw-r--r--doc/administration/operations/filesystem_benchmarking.md14
-rw-r--r--doc/administration/operations/index.md8
-rw-r--r--doc/administration/operations/moving_repositories.md49
-rw-r--r--doc/administration/operations/puma.md2
-rw-r--r--doc/administration/operations/speed_up_ssh.md8
-rw-r--r--doc/administration/packages.md8
-rw-r--r--doc/administration/packages/container_registry.md16
-rw-r--r--doc/administration/packages/dependency_proxy.md2
-rw-r--r--doc/administration/packages/index.md6
-rw-r--r--doc/administration/pages/index.md125
-rw-r--r--doc/administration/pages/source.md2
-rw-r--r--doc/administration/plugins.md8
-rw-r--r--doc/administration/postgresql/index.md6
-rw-r--r--doc/administration/postgresql/pgbouncer.md2
-rw-r--r--doc/administration/postgresql/replication_and_failover.md4
-rw-r--r--doc/administration/postgresql/standalone.md2
-rw-r--r--doc/administration/raketasks/check.md2
-rw-r--r--doc/administration/raketasks/doctor.md2
-rw-r--r--doc/administration/raketasks/geo.md2
-rw-r--r--doc/administration/raketasks/github_import.md2
-rw-r--r--doc/administration/raketasks/ldap.md8
-rw-r--r--doc/administration/raketasks/maintenance.md42
-rw-r--r--doc/administration/raketasks/praefect.md2
-rw-r--r--doc/administration/raketasks/project_import_export.md2
-rw-r--r--doc/administration/raketasks/storage.md2
-rw-r--r--doc/administration/raketasks/uploads/migrate.md2
-rw-r--r--doc/administration/raketasks/uploads/sanitize.md2
-rw-r--r--doc/administration/read_only_gitlab.md4
-rw-r--r--doc/administration/redis/replication_and_failover.md2
-rw-r--r--doc/administration/redis/replication_and_failover_external.md2
-rw-r--r--doc/administration/redis/standalone.md2
-rw-r--r--doc/administration/reference_architectures/10k_users.md898
-rw-r--r--doc/administration/reference_architectures/1k_users.md13
-rw-r--r--doc/administration/reference_architectures/25k_users.md82
-rw-r--r--doc/administration/reference_architectures/2k_users.md111
-rw-r--r--doc/administration/reference_architectures/3k_users.md76
-rw-r--r--doc/administration/reference_architectures/50k_users.md82
-rw-r--r--doc/administration/reference_architectures/5k_users.md76
-rw-r--r--doc/administration/reference_architectures/index.md15
-rw-r--r--doc/administration/reference_architectures/troubleshooting.md2
-rw-r--r--doc/administration/repository_checks.md22
-rw-r--r--doc/administration/repository_storage_paths.md186
-rw-r--r--doc/administration/repository_storage_types.md23
-rw-r--r--doc/administration/repository_storages.md8
-rw-r--r--doc/administration/restart_gitlab.md2
-rw-r--r--doc/administration/scaling/index.md8
-rw-r--r--doc/administration/server_hooks.md2
-rw-r--r--doc/administration/snippets/index.md8
-rw-r--r--doc/administration/static_objects_external_storage.md27
-rw-r--r--doc/administration/terraform_state.md16
-rw-r--r--doc/administration/timezone.md15
-rw-r--r--doc/administration/troubleshooting/debug.md18
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md14
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md9
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md2
-rw-r--r--doc/administration/troubleshooting/index.md2
-rw-r--r--doc/administration/troubleshooting/kubernetes_cheat_sheet.md6
-rw-r--r--doc/administration/troubleshooting/linux_cheat_sheet.md26
-rw-r--r--doc/administration/troubleshooting/log_parsing.md8
-rw-r--r--doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md8
-rw-r--r--doc/administration/troubleshooting/sidekiq.md2
-rw-r--r--doc/administration/uploads.md74
-rw-r--r--doc/administration/user_settings.md10
-rw-r--r--doc/administration/wikis/index.md24
-rw-r--r--doc/analytics/README.md8
-rw-r--r--doc/analytics/contribution_analytics.md8
-rw-r--r--doc/api/README.md30
-rw-r--r--doc/api/admin_sidekiq_queues.md2
-rw-r--r--doc/api/api_resources.md22
-rw-r--r--doc/api/appearance.md2
-rw-r--r--doc/api/applications.md2
-rw-r--r--doc/api/audit_events.md6
-rw-r--r--doc/api/avatar.md2
-rw-r--r--doc/api/boards.md6
-rw-r--r--doc/api/branches.md2
-rw-r--r--doc/api/build_triggers.md8
-rw-r--r--doc/api/builds.md8
-rw-r--r--doc/api/commits.md4
-rw-r--r--doc/api/dependency_proxy.md4
-rw-r--r--doc/api/deploy_key_multiple_projects.md8
-rw-r--r--doc/api/deploy_keys.md4
-rw-r--r--doc/api/deploy_tokens.md2
-rw-r--r--doc/api/discussions.md22
-rw-r--r--doc/api/dora4_group_analytics.md84
-rw-r--r--doc/api/dora4_project_analytics.md54
-rw-r--r--doc/api/epic_links.md5
-rw-r--r--doc/api/error_tracking.md2
-rw-r--r--doc/api/events.md4
-rw-r--r--doc/api/feature_flag_user_lists.md4
-rw-r--r--doc/api/feature_flags.md4
-rw-r--r--doc/api/feature_flags_legacy.md4
-rw-r--r--doc/api/features.md2
-rw-r--r--doc/api/geo_nodes.md64
-rw-r--r--doc/api/graphql/getting_started.md3
-rw-r--r--doc/api/graphql/img/users_query_example_v13_8.pngbin200017 -> 53659 bytes
-rw-r--r--doc/api/graphql/index.md39
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql5369
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json9352
-rw-r--r--doc/api/graphql/reference/index.md3071
-rw-r--r--doc/api/graphql/removed_items.md6
-rw-r--r--doc/api/group_badges.md4
-rw-r--r--doc/api/group_boards.md6
-rw-r--r--doc/api/group_clusters.md2
-rw-r--r--doc/api/group_import_export.md5
-rw-r--r--doc/api/group_iterations.md8
-rw-r--r--doc/api/group_milestones.md5
-rw-r--r--doc/api/group_repository_storage_moves.md254
-rw-r--r--doc/api/group_wikis.md6
-rw-r--r--doc/api/groups.md72
-rw-r--r--doc/api/instance_clusters.md4
-rw-r--r--doc/api/issue_links.md4
-rw-r--r--doc/api/issues.md40
-rw-r--r--doc/api/iterations.md8
-rw-r--r--doc/api/jobs.md33
-rw-r--r--doc/api/keys.md2
-rw-r--r--doc/api/license.md2
-rw-r--r--doc/api/license_templates.md8
-rw-r--r--doc/api/lint.md4
-rw-r--r--doc/api/markdown.md2
-rw-r--r--doc/api/members.md11
-rw-r--r--doc/api/merge_request_approvals.md55
-rw-r--r--doc/api/merge_request_context_commits.md2
-rw-r--r--doc/api/merge_requests.md105
-rw-r--r--doc/api/metrics_dashboard_annotations.md2
-rw-r--r--doc/api/metrics_user_starred_dashboards.md2
-rw-r--r--doc/api/milestones.md5
-rw-r--r--doc/api/namespaces.md2
-rw-r--r--doc/api/notes.md5
-rw-r--r--doc/api/notification_settings.md2
-rw-r--r--doc/api/oauth2.md32
-rw-r--r--doc/api/openapi/img/apiviewer01-fs8.pngbin0 -> 79594 bytes
-rw-r--r--doc/api/openapi/img/apiviewer03-fs8.pngbin0 -> 72812 bytes
-rw-r--r--doc/api/openapi/img/apiviewer04-fs8.pngbin0 -> 77404 bytes
-rw-r--r--doc/api/openapi/openapi_interactive.md42
-rw-r--r--doc/api/packages.md12
-rw-r--r--doc/api/personal_access_tokens.md4
-rw-r--r--doc/api/project_aliases.md2
-rw-r--r--doc/api/project_analytics.md52
-rw-r--r--doc/api/project_badges.md11
-rw-r--r--doc/api/project_clusters.md2
-rw-r--r--doc/api/project_import_export.md6
-rw-r--r--doc/api/project_level_variables.md10
-rw-r--r--doc/api/project_repository_storage_moves.md9
-rw-r--r--doc/api/project_snippets.md6
-rw-r--r--doc/api/project_statistics.md2
-rw-r--r--doc/api/project_templates.md9
-rw-r--r--doc/api/projects.md61
-rw-r--r--doc/api/protected_branches.md22
-rw-r--r--doc/api/protected_tags.md2
-rw-r--r--doc/api/releases/index.md4
-rw-r--r--doc/api/remote_mirrors.md2
-rw-r--r--doc/api/repositories.md362
-rw-r--r--doc/api/repository_files.md2
-rw-r--r--doc/api/repository_submodules.md2
-rw-r--r--doc/api/resource_access_tokens.md107
-rw-r--r--doc/api/resource_iteration_events.md7
-rw-r--r--doc/api/runners.md2
-rw-r--r--doc/api/scim.md4
-rw-r--r--doc/api/search.md54
-rw-r--r--doc/api/services.md4
-rw-r--r--doc/api/settings.md31
-rw-r--r--doc/api/sidekiq_metrics.md2
-rw-r--r--doc/api/snippet_repository_storage_moves.md9
-rw-r--r--doc/api/suggestions.md3
-rw-r--r--doc/api/tags.md14
-rw-r--r--doc/api/todos.md5
-rw-r--r--doc/api/users.md133
-rw-r--r--doc/api/v3_to_v4.md2
-rw-r--r--doc/api/visual_review_discussions.md5
-rw-r--r--doc/api/vulnerability_exports.md6
-rw-r--r--doc/api/wikis.md6
-rw-r--r--doc/architecture/blueprints/database_testing/index.md145
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md4
-rw-r--r--doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md6
-rw-r--r--doc/architecture/blueprints/graphql_api/index.md183
-rw-r--r--doc/architecture/blueprints/image_resizing/index.md8
-rw-r--r--doc/ci/README.md30
-rw-r--r--doc/ci/autodeploy/index.md8
-rw-r--r--doc/ci/autodeploy/quick_start_guide.md8
-rw-r--r--doc/ci/build_artifacts/README.md8
-rw-r--r--doc/ci/caching/index.md2
-rw-r--r--doc/ci/chatops/README.md116
-rw-r--r--doc/ci/chatops/index.md116
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md7
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md4
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md4
-rw-r--r--doc/ci/cloud_deployment/index.md36
-rw-r--r--doc/ci/directed_acyclic_graph/index.md18
-rw-r--r--doc/ci/docker/README.md18
-rw-r--r--doc/ci/docker/index.md18
-rw-r--r--doc/ci/docker/using_docker_build.md6
-rw-r--r--doc/ci/docker/using_docker_images.md20
-rw-r--r--doc/ci/docker/using_kaniko.md4
-rw-r--r--doc/ci/enable_or_disable_ci.md2
-rw-r--r--doc/ci/environments.md8
-rw-r--r--doc/ci/environments/deployment_safety.md4
-rw-r--r--doc/ci/environments/environments_dashboard.md4
-rw-r--r--doc/ci/environments/incremental_rollouts.md4
-rw-r--r--doc/ci/environments/index.md28
-rw-r--r--doc/ci/environments/protected_environments.md4
-rw-r--r--doc/ci/examples/README.md38
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md289
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md16
-rw-r--r--doc/ci/examples/browser_performance.md8
-rw-r--r--doc/ci/examples/code_climate.md8
-rw-r--r--doc/ci/examples/code_quality.md8
-rw-r--r--doc/ci/examples/container_scanning.md8
-rw-r--r--doc/ci/examples/dast.md8
-rw-r--r--doc/ci/examples/dependency_scanning.md8
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.pngbin11852 -> 0 bytes
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/create_from_template.pngbin82121 -> 0 bytes
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md145
-rw-r--r--doc/ci/examples/deployment/README.md12
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md4
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/aws_config_window.pngbin9300 -> 0 bytes
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/gitlab_config.pngbin15160 -> 0 bytes
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/test_pipeline_pass.pngbin9985 -> 0 bytes
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md534
-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.md16
-rw-r--r--doc/ci/examples/license_management.md8
-rw-r--r--doc/ci/examples/php.md15
-rw-r--r--doc/ci/examples/sast.md8
-rw-r--r--doc/ci/examples/sast_docker.md8
-rw-r--r--doc/ci/examples/semantic-release.md14
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md2
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md2
-rw-r--r--doc/ci/examples/test-phoenix-application.md5
-rw-r--r--doc/ci/examples/test-scala-application.md81
-rw-r--r--doc/ci/git_submodules.md2
-rw-r--r--doc/ci/introduction/index.md170
-rw-r--r--doc/ci/jenkins/index.md8
-rw-r--r--doc/ci/jobs/index.md41
-rw-r--r--doc/ci/junit_test_reports.md8
-rw-r--r--doc/ci/large_repositories/index.md5
-rw-r--r--doc/ci/lint.md6
-rw-r--r--doc/ci/merge_request_pipelines/index.md5
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md9
-rw-r--r--doc/ci/migration/circleci.md8
-rw-r--r--doc/ci/migration/jenkins.md10
-rw-r--r--doc/ci/multi_project_pipeline_graphs.md8
-rw-r--r--doc/ci/multi_project_pipelines.md14
-rw-r--r--doc/ci/parent_child_pipelines.md13
-rw-r--r--doc/ci/permissions/README.md8
-rw-r--r--doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.pngbin18744 -> 8657 bytes
-rw-r--r--doc/ci/pipeline_editor/index.md66
-rw-r--r--doc/ci/pipelines.md8
-rw-r--r--doc/ci/pipelines/img/job_artifacts_merge_request.pngbin40817 -> 13206 bytes
-rw-r--r--doc/ci/pipelines/index.md29
-rw-r--r--doc/ci/pipelines/job_artifacts.md14
-rw-r--r--doc/ci/pipelines/pipeline_efficiency.md6
-rw-r--r--doc/ci/pipelines/schedules.md4
-rw-r--r--doc/ci/pipelines/settings.md35
-rw-r--r--doc/ci/quick_start/README.md157
-rw-r--r--doc/ci/quick_start/index.md157
-rw-r--r--doc/ci/review_apps/index.md17
-rw-r--r--doc/ci/runners/README.md53
-rw-r--r--doc/ci/secrets/index.md8
-rw-r--r--doc/ci/services/README.md21
-rw-r--r--doc/ci/services/docker-services.md8
-rw-r--r--doc/ci/services/index.md21
-rw-r--r--doc/ci/services/mysql.md2
-rw-r--r--doc/ci/services/postgres.md2
-rw-r--r--doc/ci/ssh_keys/README.md212
-rw-r--r--doc/ci/ssh_keys/index.md212
-rw-r--r--doc/ci/triggers/README.md69
-rw-r--r--doc/ci/triggers/img/builds_page.pngbin20366 -> 0 bytes
-rw-r--r--doc/ci/triggers/img/trigger_single_job.png (renamed from doc/ci/triggers/img/trigger_single_build.png)bin6584 -> 6584 bytes
-rw-r--r--doc/ci/troubleshooting.md40
-rw-r--r--doc/ci/unit_test_reports.md30
-rw-r--r--doc/ci/variables/README.md125
-rw-r--r--doc/ci/variables/predefined_variables.md13
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md2
-rw-r--r--doc/ci/yaml/README.md740
-rw-r--r--doc/ci/yaml/gitlab_ci_yaml.md2
-rw-r--r--doc/ci/yaml/script.md2
-rw-r--r--doc/customization/branded_login_page.md8
-rw-r--r--doc/customization/branded_page_and_email_header.md8
-rw-r--r--doc/customization/favicon.md8
-rw-r--r--doc/customization/help_message.md8
-rw-r--r--doc/customization/index.md8
-rw-r--r--doc/customization/issue_and_merge_request_template.md8
-rw-r--r--doc/customization/issue_closing.md8
-rw-r--r--doc/customization/libravatar.md8
-rw-r--r--doc/customization/new_project_page.md8
-rw-r--r--doc/customization/system_header_and_footer_messages.md8
-rw-r--r--doc/customization/welcome_message.md8
-rw-r--r--doc/development/README.md5
-rw-r--r--doc/development/adding_service_component.md2
-rw-r--r--doc/development/agent/gitops.md2
-rw-r--r--doc/development/agent/identity.md2
-rw-r--r--doc/development/agent/index.md2
-rw-r--r--doc/development/agent/local.md2
-rw-r--r--doc/development/agent/repository_overview.md98
-rw-r--r--doc/development/agent/routing.md179
-rw-r--r--doc/development/agent/user_stories.md2
-rw-r--r--doc/development/api_graphql_styleguide.md91
-rw-r--r--doc/development/api_styleguide.md2
-rw-r--r--doc/development/application_limits.md4
-rw-r--r--doc/development/approval_rules.md12
-rw-r--r--doc/development/architecture.md86
-rw-r--r--doc/development/auto_devops.md2
-rw-r--r--doc/development/changelog.md17
-rw-r--r--doc/development/chaos_endpoints.md59
-rw-r--r--doc/development/chatops_on_gitlabcom.md16
-rw-r--r--doc/development/cicd/img/ci_minutes.pngbin0 -> 20223 bytes
-rw-r--r--doc/development/cicd/index.md39
-rw-r--r--doc/development/code_intelligence/index.md4
-rw-r--r--doc/development/code_review.md35
-rw-r--r--doc/development/contributing/index.md12
-rw-r--r--doc/development/contributing/merge_request_workflow.md10
-rw-r--r--doc/development/contributing/style_guides.md99
-rw-r--r--doc/development/cycle_analytics.md8
-rw-r--r--doc/development/dangerbot.md4
-rw-r--r--doc/development/database/database_reviewer_guidelines.md6
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md6
-rw-r--r--doc/development/database/table_partitioning.md2
-rw-r--r--doc/development/database_debugging.md6
-rw-r--r--doc/development/database_review.md11
-rw-r--r--doc/development/diffs.md22
-rw-r--r--doc/development/directory_structure.md36
-rw-r--r--doc/development/distributed_tracing.md2
-rw-r--r--doc/development/doc_styleguide.md8
-rw-r--r--doc/development/documentation/feature-change-workflow.md8
-rw-r--r--doc/development/documentation/feature_flags.md28
-rw-r--r--doc/development/documentation/improvement-workflow.md8
-rw-r--r--doc/development/documentation/index.md201
-rw-r--r--doc/development/documentation/restful_api_styleguide.md2
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md6
-rw-r--r--doc/development/documentation/site_architecture/index.md2
-rw-r--r--doc/development/documentation/structure.md230
-rw-r--r--doc/development/documentation/styleguide.md3
-rw-r--r--doc/development/documentation/styleguide/img/tier_badge.pngbin9592 -> 9320 bytes
-rw-r--r--doc/development/documentation/styleguide/index.md205
-rw-r--r--doc/development/documentation/testing.md58
-rw-r--r--doc/development/documentation/workflow.md6
-rw-r--r--doc/development/ee_features.md38
-rw-r--r--doc/development/elasticsearch.md14
-rw-r--r--doc/development/experiment_guide/index.md18
-rw-r--r--doc/development/export_csv.md2
-rw-r--r--doc/development/fe_guide/accessibility.md8
-rw-r--r--doc/development/fe_guide/architecture.md4
-rw-r--r--doc/development/fe_guide/axios.md2
-rw-r--r--doc/development/fe_guide/components.md3
-rw-r--r--doc/development/fe_guide/dark_mode.md77
-rw-r--r--doc/development/fe_guide/dependencies.md67
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md219
-rw-r--r--doc/development/fe_guide/design_patterns.md78
-rw-r--r--doc/development/fe_guide/development_process.md6
-rw-r--r--doc/development/fe_guide/dropdowns.md3
-rw-r--r--doc/development/fe_guide/editor_lite.md20
-rw-r--r--doc/development/fe_guide/emojis.md2
-rw-r--r--doc/development/fe_guide/frontend_faq.md39
-rw-r--r--doc/development/fe_guide/graphql.md167
-rw-r--r--doc/development/fe_guide/icons.md12
-rw-r--r--doc/development/fe_guide/index.md19
-rw-r--r--doc/development/fe_guide/performance.md48
-rw-r--r--doc/development/fe_guide/security.md4
-rw-r--r--doc/development/fe_guide/style/html.md32
-rw-r--r--doc/development/fe_guide/style/javascript.md2
-rw-r--r--doc/development/fe_guide/style/scss.md20
-rw-r--r--doc/development/fe_guide/style_guide_js.md8
-rw-r--r--doc/development/fe_guide/style_guide_scss.md8
-rw-r--r--doc/development/fe_guide/testing.md8
-rw-r--r--doc/development/fe_guide/tooling.md6
-rw-r--r--doc/development/fe_guide/troubleshooting.md41
-rw-r--r--doc/development/fe_guide/vue.md40
-rw-r--r--doc/development/fe_guide/vue3_migration.md10
-rw-r--r--doc/development/fe_guide/vuex.md6
-rw-r--r--doc/development/feature_flags.md8
-rw-r--r--doc/development/feature_flags/controls.md36
-rw-r--r--doc/development/feature_flags/development.md46
-rw-r--r--doc/development/feature_flags/index.md3
-rw-r--r--doc/development/feature_flags/process.md6
-rw-r--r--doc/development/filtering_by_label.md4
-rw-r--r--doc/development/foreign_keys.md2
-rw-r--r--doc/development/frontend.md8
-rw-r--r--doc/development/gemfile.md13
-rw-r--r--doc/development/geo.md4
-rw-r--r--doc/development/geo/framework.md33
-rw-r--r--doc/development/gitaly.md43
-rw-r--r--doc/development/go_guide/dependencies.md2
-rw-r--r--doc/development/go_guide/index.md29
-rw-r--r--doc/development/graphql_guide/batchloader.md2
-rw-r--r--doc/development/graphql_guide/graphql_pro.md21
-rw-r--r--doc/development/graphql_guide/index.md7
-rw-r--r--doc/development/graphql_guide/pagination.md4
-rw-r--r--doc/development/i18n/merging_translations.md20
-rw-r--r--doc/development/i18n_guide.md8
-rw-r--r--doc/development/import_project.md2
-rw-r--r--doc/development/instrumentation.md2
-rw-r--r--doc/development/integrations/codesandbox.md34
-rw-r--r--doc/development/integrations/jenkins.md4
-rw-r--r--doc/development/integrations/jira_connect.md6
-rw-r--r--doc/development/integrations/secure.md2
-rw-r--r--doc/development/integrations/secure_partner_integration.md6
-rw-r--r--doc/development/interacting_components.md2
-rw-r--r--doc/development/internal_api.md172
-rw-r--r--doc/development/iterating_tables_in_batches.md2
-rw-r--r--doc/development/kubernetes.md2
-rw-r--r--doc/development/lfs.md18
-rw-r--r--doc/development/licensed_feature_availability.md4
-rw-r--r--doc/development/licensing.md2
-rw-r--r--doc/development/logging.md26
-rw-r--r--doc/development/maintenance_mode.md19
-rw-r--r--doc/development/module_with_instance_variables.md66
-rw-r--r--doc/development/new_fe_guide/dependencies.md38
-rw-r--r--doc/development/new_fe_guide/development/testing.md8
-rw-r--r--doc/development/new_fe_guide/index.md4
-rw-r--r--doc/development/new_fe_guide/modules/widget_extensions.md14
-rw-r--r--doc/development/new_fe_guide/style/html.md8
-rw-r--r--doc/development/new_fe_guide/style/index.md8
-rw-r--r--doc/development/new_fe_guide/style/javascript.md8
-rw-r--r--doc/development/new_fe_guide/style/prettier.md8
-rw-r--r--doc/development/ordering_table_columns.md22
-rw-r--r--doc/development/packages.md18
-rw-r--r--doc/development/performance.md101
-rw-r--r--doc/development/pipelines.md66
-rw-r--r--doc/development/polling.md2
-rw-r--r--doc/development/product_analytics/index.md5
-rw-r--r--doc/development/product_analytics/snowplow.md2
-rw-r--r--doc/development/product_analytics/usage_ping.md2
-rw-r--r--doc/development/profiling.md4
-rw-r--r--doc/development/projections.md4
-rw-r--r--doc/development/prometheus_metrics.md7
-rw-r--r--doc/development/pry_debugging.md7
-rw-r--r--doc/development/python_guide/index.md8
-rw-r--r--doc/development/rake_tasks.md46
-rw-r--r--doc/development/reactive_caching.md4
-rw-r--r--doc/development/redis.md11
-rw-r--r--doc/development/refactoring_guide/index.md2
-rw-r--r--doc/development/repository_mirroring.md6
-rw-r--r--doc/development/rolling_out_changes_using_feature_flags.md8
-rw-r--r--doc/development/secure_coding_guidelines.md70
-rw-r--r--doc/development/shared_files.md2
-rw-r--r--doc/development/shell_commands.md2
-rw-r--r--doc/development/sidekiq_debugging.md8
-rw-r--r--doc/development/sidekiq_style_guide.md2
-rw-r--r--doc/development/snowplow.md312
-rw-r--r--doc/development/stage_group_dashboards.md8
-rw-r--r--doc/development/telemetry/event_dictionary.md8
-rw-r--r--doc/development/telemetry/index.md8
-rw-r--r--doc/development/telemetry/snowplow.md8
-rw-r--r--doc/development/telemetry/usage_ping.md8
-rw-r--r--doc/development/testing.md8
-rw-r--r--doc/development/testing_guide/best_practices.md151
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md4
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md13
-rw-r--r--doc/development/testing_guide/end_to_end/page_objects.md2
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md33
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md32
-rw-r--r--doc/development/testing_guide/frontend_testing.md70
-rw-r--r--doc/development/testing_guide/index.md4
-rw-r--r--doc/development/testing_guide/review_apps.md8
-rw-r--r--doc/development/testing_guide/testing_migrations_guide.md2
-rw-r--r--doc/development/transient/prevention-patterns.md141
-rw-r--r--doc/development/ui_guide.md5
-rw-r--r--doc/development/usage_ping.md129
-rw-r--r--doc/development/usage_ping/dictionary.md887
-rw-r--r--doc/development/usage_ping/metrics_dictionary.md60
-rw-r--r--doc/development/utilities.md45
-rw-r--r--doc/development/ux_guide/animation.md5
-rw-r--r--doc/development/ux_guide/basics.md5
-rw-r--r--doc/development/ux_guide/components.md5
-rw-r--r--doc/development/ux_guide/copy.md5
-rw-r--r--doc/development/ux_guide/features.md5
-rw-r--r--doc/development/ux_guide/illustrations.md5
-rw-r--r--doc/development/ux_guide/index.md5
-rw-r--r--doc/development/ux_guide/principles.md5
-rw-r--r--doc/development/ux_guide/resources.md5
-rw-r--r--doc/development/ux_guide/surfaces.md5
-rw-r--r--doc/development/ux_guide/tips.md5
-rw-r--r--doc/development/ux_guide/users.md8
-rw-r--r--doc/development/wikis.md8
-rw-r--r--doc/development/windows.md4
-rw-r--r--doc/development/writing_documentation.md3
-rw-r--r--doc/downgrade_ee_to_ce/README.md97
-rw-r--r--doc/downgrade_ee_to_ce/index.md97
-rw-r--r--doc/gitlab-basics/README.md49
-rw-r--r--doc/gitlab-basics/add-file.md2
-rw-r--r--doc/gitlab-basics/add-image.md8
-rw-r--r--doc/gitlab-basics/add-merge-request.md8
-rw-r--r--doc/gitlab-basics/basic-git-commands.md8
-rw-r--r--doc/gitlab-basics/command-line-commands.md6
-rw-r--r--doc/gitlab-basics/create-branch.md2
-rw-r--r--doc/gitlab-basics/create-group.md8
-rw-r--r--doc/gitlab-basics/create-issue.md8
-rw-r--r--doc/gitlab-basics/create-project.md175
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md30
-rw-r--r--doc/gitlab-basics/feature_branch_workflow.md2
-rw-r--r--doc/gitlab-basics/fork-project.md14
-rw-r--r--doc/gitlab-basics/index.md49
-rw-r--r--doc/gitlab-basics/start-using-git.md12
-rw-r--r--doc/install/README.md143
-rw-r--r--doc/install/aws/index.md6
-rw-r--r--doc/install/google-protobuf.md8
-rw-r--r--doc/install/google_cloud_platform/index.md2
-rw-r--r--doc/install/index.md143
-rw-r--r--doc/install/installation.md26
-rw-r--r--doc/install/ldap.md8
-rw-r--r--doc/install/openshift_and_gitlab/index.md18
-rw-r--r--doc/install/pivotal/index.md2
-rw-r--r--doc/install/redis.md8
-rw-r--r--doc/install/requirements.md6
-rw-r--r--doc/install/structure.md5
-rw-r--r--doc/integration/README.md11
-rw-r--r--doc/integration/azure.md4
-rw-r--r--doc/integration/bitbucket.md4
-rw-r--r--doc/integration/cas.md4
-rw-r--r--doc/integration/chat_commands.md8
-rw-r--r--doc/integration/crowd.md8
-rw-r--r--doc/integration/elasticsearch.md247
-rw-r--r--doc/integration/github.md14
-rw-r--r--doc/integration/gitlab.md22
-rw-r--r--doc/integration/gitpod.md70
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md15
-rw-r--r--doc/integration/google_workspace_saml.md163
-rw-r--r--doc/integration/img/jira_dev_panel_setup_com_3.pngbin7639 -> 0 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_setup_com_3_v13_9.pngbin0 -> 28042 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_setup_com_4_v13_9.pngbin0 -> 23360 bytes
-rw-r--r--doc/integration/img/oauth_provider_application_form.pngbin12553 -> 0 bytes
-rw-r--r--doc/integration/img/oauth_provider_application_id_secret.pngbin15280 -> 0 bytes
-rw-r--r--doc/integration/img/oauth_provider_authorized_application.pngbin14657 -> 0 bytes
-rw-r--r--doc/integration/img/oauth_provider_user_wide_applications.pngbin17526 -> 0 bytes
-rw-r--r--doc/integration/jenkins.md19
-rw-r--r--doc/integration/jenkins_deprecated.md2
-rw-r--r--doc/integration/jira.md8
-rw-r--r--doc/integration/jira_development_panel.md124
-rw-r--r--doc/integration/kerberos.md15
-rw-r--r--doc/integration/ldap.md8
-rw-r--r--doc/integration/oauth2_generic.md2
-rw-r--r--doc/integration/oauth_provider.md105
-rw-r--r--doc/integration/omniauth.md48
-rw-r--r--doc/integration/openid_connect_provider.md13
-rw-r--r--doc/integration/recaptcha.md4
-rw-r--r--doc/integration/salesforce.md4
-rw-r--r--doc/integration/saml.md38
-rw-r--r--doc/integration/security_partners/index.md23
-rw-r--r--doc/integration/shibboleth.md10
-rw-r--r--doc/integration/slack.md8
-rw-r--r--doc/integration/slash_commands.md18
-rw-r--r--doc/integration/sourcegraph.md31
-rw-r--r--doc/integration/trello_power_up.md7
-rw-r--r--doc/integration/vault.md21
-rw-r--r--doc/intro/README.md49
-rw-r--r--doc/intro/index.md49
-rw-r--r--doc/legal/README.md10
-rw-r--r--doc/legal/index.md10
-rw-r--r--doc/license/README.md8
-rw-r--r--doc/markdown/markdown.md8
-rw-r--r--doc/monitoring/health_check.md8
-rw-r--r--doc/monitoring/performance/gitlab_configuration.md8
-rw-r--r--doc/monitoring/performance/grafana_configuration.md8
-rw-r--r--doc/monitoring/performance/influxdb_configuration.md5
-rw-r--r--doc/monitoring/performance/influxdb_schema.md5
-rw-r--r--doc/monitoring/performance/introduction.md8
-rw-r--r--doc/operations/cleaning_up_redis_sessions.md8
-rw-r--r--doc/operations/error_tracking.md2
-rw-r--r--doc/operations/feature_flags.md24
-rw-r--r--doc/operations/incident_management/alert_details.md8
-rw-r--r--doc/operations/incident_management/alert_integrations.md199
-rw-r--r--doc/operations/incident_management/alert_notifications.md36
-rw-r--r--doc/operations/incident_management/alerts.md11
-rw-r--r--doc/operations/incident_management/generic_alerts.md8
-rw-r--r--doc/operations/incident_management/img/alert_detail_add_todo_v13_1.pngbin16822 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/alert_detail_add_todo_v13_9.pngbin0 -> 26763 bytes
-rw-r--r--doc/operations/incident_management/incidents.md24
-rw-r--r--doc/operations/incident_management/index.md6
-rw-r--r--doc/operations/incident_management/integrations.md187
-rw-r--r--doc/operations/incident_management/paging.md36
-rw-r--r--doc/operations/incident_management/status_page.md2
-rw-r--r--doc/operations/index.md2
-rw-r--r--doc/operations/metrics/alerts.md22
-rw-r--r--doc/operations/metrics/dashboards/default.md2
-rw-r--r--doc/operations/metrics/dashboards/develop.md4
-rw-r--r--doc/operations/metrics/dashboards/index.md8
-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.md4
-rw-r--r--doc/operations/metrics/dashboards/yaml_number_format.md2
-rw-r--r--doc/operations/metrics/embed.md2
-rw-r--r--doc/operations/metrics/embed_grafana.md2
-rw-r--r--doc/operations/metrics/index.md5
-rw-r--r--doc/operations/moving_repositories.md8
-rw-r--r--doc/operations/product_analytics.md4
-rw-r--r--doc/operations/sidekiq_memory_killer.md8
-rw-r--r--doc/operations/tracing.md6
-rw-r--r--doc/operations/unicorn.md8
-rw-r--r--doc/permissions/permissions.md10
-rw-r--r--doc/policy/maintenance.md2
-rw-r--r--doc/push_rules/push_rules.md76
-rw-r--r--doc/raketasks/README.md48
-rw-r--r--doc/raketasks/backup_restore.md29
-rw-r--r--doc/raketasks/check.md8
-rw-r--r--doc/raketasks/cleanup.md10
-rw-r--r--doc/raketasks/features.md14
-rw-r--r--doc/raketasks/generate_sample_prometheus_data.md2
-rw-r--r--doc/raketasks/import.md6
-rw-r--r--doc/raketasks/index.md48
-rw-r--r--doc/raketasks/list_repos.md6
-rw-r--r--doc/raketasks/maintenance.md8
-rw-r--r--doc/raketasks/migrate_snippets.md23
-rw-r--r--doc/raketasks/spdx.md6
-rw-r--r--doc/raketasks/user_management.md6
-rw-r--r--doc/raketasks/web_hooks.md6
-rw-r--r--doc/raketasks/x509_signatures.md2
-rw-r--r--doc/security/README.md2
-rw-r--r--doc/security/asset_proxy.md3
-rw-r--r--doc/security/cicd_environment_variables.md13
-rw-r--r--doc/security/cicd_variables.md13
-rw-r--r--doc/security/crime_vulnerability.md2
-rw-r--r--doc/security/password_storage.md2
-rw-r--r--doc/security/rate_limits.md13
-rw-r--r--doc/security/reset_user_password.md93
-rw-r--r--doc/security/two_factor_authentication.md8
-rw-r--r--doc/security/unlock_user.md2
-rw-r--r--doc/ssh/README.md219
-rw-r--r--doc/subscriptions/bronze_starter.md139
-rw-r--r--doc/subscriptions/gitlab_com/index.md178
-rw-r--r--doc/subscriptions/index.md44
-rw-r--r--doc/subscriptions/self_managed/index.md23
-rw-r--r--doc/system_hooks/system_hooks.md23
-rw-r--r--doc/telemetry/index.md8
-rw-r--r--doc/telemetry/snowplow.md8
-rw-r--r--doc/topics/airgap/index.md3
-rw-r--r--doc/topics/authentication/index.md10
-rw-r--r--doc/topics/autodevops/customize.md12
-rw-r--r--doc/topics/autodevops/img/alexj_autodevops_min_v13_8.pngbin0 -> 20836 bytes
-rw-r--r--doc/topics/autodevops/img/kai_autodevops_min_v13_8.pngbin0 -> 39770 bytes
-rw-r--r--doc/topics/autodevops/index.md29
-rw-r--r--doc/topics/autodevops/quick_start_guide.md6
-rw-r--r--doc/topics/autodevops/requirements.md11
-rw-r--r--doc/topics/autodevops/stages.md10
-rw-r--r--doc/topics/autodevops/upgrading_auto_deploy_dependencies.md4
-rw-r--r--doc/topics/autodevops/upgrading_chart.md8
-rw-r--r--doc/topics/autodevops/upgrading_postgresql.md2
-rw-r--r--doc/topics/cron/index.md2
-rw-r--r--doc/topics/git/feature_branch_development.md2
-rw-r--r--doc/topics/git/git_rebase.md29
-rw-r--r--doc/topics/git/how_to_install_git/index.md2
-rw-r--r--doc/topics/git/index.md2
-rw-r--r--doc/topics/git/lfs/index.md63
-rw-r--r--doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md30
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md4
-rw-r--r--doc/topics/git/migrate_to_git_lfs/index.md8
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md156
-rw-r--r--doc/topics/git/partial_clone.md2
-rw-r--r--doc/topics/git/troubleshooting_git.md23
-rw-r--r--doc/topics/git/useful_git_commands.md8
-rw-r--r--doc/topics/gitlab_flow.md98
-rw-r--r--doc/topics/index.md2
-rw-r--r--doc/university/README.md212
-rw-r--r--doc/university/bookclub/booklist.md5
-rw-r--r--doc/university/bookclub/index.md5
-rw-r--r--doc/university/glossary/README.md5
-rw-r--r--doc/university/high-availability/aws/README.md8
-rw-r--r--doc/university/index.md223
-rw-r--r--doc/university/process/README.md5
-rw-r--r--doc/university/training/end-user/README.md5
-rw-r--r--doc/university/training/gitlab_flow.md57
-rw-r--r--doc/university/training/index.md8
-rw-r--r--doc/university/training/topics/explore_gitlab.md8
-rw-r--r--doc/university/training/topics/getting_started.md4
-rw-r--r--doc/university/training/topics/gitlab_flow.md3
-rw-r--r--doc/university/training/user_training.md6
-rw-r--r--doc/update/README.md423
-rw-r--r--doc/update/index.md423
-rw-r--r--doc/update/mysql_to_postgresql.md10
-rw-r--r--doc/update/patch_versions.md4
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md2
-rw-r--r--doc/update/upgrading_from_source.md2
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md6
-rw-r--r--doc/user/account/security.md8
-rw-r--r--doc/user/account/two_factor_authentication.md8
-rw-r--r--doc/user/admin_area/abuse_reports.md2
-rw-r--r--doc/user/admin_area/analytics/convdev.md8
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md12
-rw-r--r--doc/user/admin_area/analytics/img/cohorts_v13_4.pngbin31518 -> 0 bytes
-rw-r--r--doc/user/admin_area/analytics/img/cohorts_v13_9.pngbin0 -> 62434 bytes
-rw-r--r--doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.pngbin49152 -> 0 bytes
-rw-r--r--doc/user/admin_area/analytics/img/dev_ops_adoption_v13_9.pngbin0 -> 43719 bytes
-rw-r--r--doc/user/admin_area/analytics/index.md6
-rw-r--r--doc/user/admin_area/analytics/instance_statistics.md3
-rw-r--r--doc/user/admin_area/analytics/usage_trends.md2
-rw-r--r--doc/user/admin_area/analytics/user_cohorts.md6
-rw-r--r--doc/user/admin_area/appearance.md7
-rw-r--r--doc/user/admin_area/broadcast_messages.md2
-rw-r--r--doc/user/admin_area/credentials_inventory.md2
-rw-r--r--doc/user/admin_area/custom_project_templates.md2
-rw-r--r--doc/user/admin_area/diff_limits.md22
-rw-r--r--doc/user/admin_area/geo_nodes.md2
-rw-r--r--doc/user/admin_area/img/impersonate_user_button_v13_8.pngbin0 -> 23707 bytes
-rw-r--r--doc/user/admin_area/img/license_details.pngbin65130 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/license_details_v13_8.pngbin0 -> 69506 bytes
-rw-r--r--doc/user/admin_area/index.md39
-rw-r--r--doc/user/admin_area/labels.md2
-rw-r--r--doc/user/admin_area/license.md12
-rw-r--r--doc/user/admin_area/merge_requests_approvals.md2
-rw-r--r--doc/user/admin_area/monitoring/convdev.md5
-rw-r--r--doc/user/admin_area/monitoring/dev_ops_report.md8
-rw-r--r--doc/user/admin_area/monitoring/health_check.md4
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md111
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md68
-rw-r--r--doc/user/admin_area/settings/email.md6
-rw-r--r--doc/user/admin_area/settings/external_authorization.md5
-rw-r--r--doc/user/admin_area/settings/gitaly_timeouts.md2
-rw-r--r--doc/user/admin_area/settings/index.md11
-rw-r--r--doc/user/admin_area/settings/instance_template_repository.md13
-rw-r--r--doc/user/admin_area/settings/project_integration_management.md2
-rw-r--r--doc/user/admin_area/settings/protected_paths.md2
-rw-r--r--doc/user/admin_area/settings/push_event_activities_limit.md12
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_notes_creation.md32
-rw-r--r--doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md2
-rw-r--r--doc/user/admin_area/settings/sign_in_restrictions.md4
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md31
-rw-r--r--doc/user/admin_area/settings/terms.md4
-rw-r--r--doc/user/admin_area/settings/third_party_offers.md4
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md6
-rw-r--r--doc/user/admin_area/settings/user_and_ip_rate_limits.md2
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md61
-rw-r--r--doc/user/admin_area/user_cohorts.md8
-rw-r--r--doc/user/analytics/ci_cd_analytics.md25
-rw-r--r--doc/user/analytics/code_review_analytics.md20
-rw-r--r--doc/user/analytics/cycle_analytics.md8
-rw-r--r--doc/user/analytics/index.md39
-rw-r--r--doc/user/analytics/issue_analytics.md2
-rw-r--r--doc/user/analytics/merge_request_analytics.md7
-rw-r--r--doc/user/analytics/productivity_analytics.md4
-rw-r--r--doc/user/analytics/value_stream_analytics.md2
-rw-r--r--doc/user/application_security/api_fuzzing/index.md165
-rw-r--r--doc/user/application_security/compliance_dashboard/index.md8
-rw-r--r--doc/user/application_security/container_scanning/index.md54
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md45
-rw-r--r--doc/user/application_security/dast/index.md270
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md4
-rw-r--r--doc/user/application_security/dependency_scanning/index.md107
-rw-r--r--doc/user/application_security/img/create_issue_from_vulnerability_v13_3.pngbin5079 -> 0 bytes
-rw-r--r--doc/user/application_security/img/issue.pngbin4780 -> 0 bytes
-rw-r--r--doc/user/application_security/index.md114
-rw-r--r--doc/user/application_security/license_compliance/index.md8
-rw-r--r--doc/user/application_security/license_management/index.md8
-rw-r--r--doc/user/application_security/offline_deployments/index.md16
-rw-r--r--doc/user/application_security/sast/analyzers.md60
-rw-r--r--doc/user/application_security/sast/index.md164
-rw-r--r--doc/user/application_security/secret_detection/index.md71
-rw-r--r--doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_7.pngbin75819 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.pngbin10596 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_dismissal_v13_4.pngbin53541 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_5.pngbin69166 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/security_center_dashboard_empty_v13_4.png (renamed from doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.png)bin13264 -> 13264 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/security_center_dashboard_link_v12_4.png (renamed from doc/user/application_security/security_dashboard/img/instance_security_dashboard_link_v12_4.png)bin7921 -> 7921 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/security_center_dashboard_v13_4.png (renamed from doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.png)bin29797 -> 29797 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png (renamed from doc/user/application_security/security_dashboard/img/instance_security_center_settings_v13_4.png)bin30034 -> 30034 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.pngbin61329 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md130
-rw-r--r--doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.pngbin0 -> 10558 bytes
-rw-r--r--doc/user/application_security/threat_monitoring/index.md77
-rw-r--r--doc/user/application_security/vulnerabilities/index.md105
-rw-r--r--doc/user/application_security/vulnerabilities/severities.md34
-rw-r--r--doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v13_9.pngbin0 -> 54478 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/img/project_security_dashboard_dismissal_v13_9.pngbin0 -> 37066 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/img/project_security_dashboard_v13_9.pngbin0 -> 56375 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/img/vulnerability_details_create_issue_v13_7.png (renamed from doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png)bin31816 -> 31816 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/img/vulnerability_list_table_v13_9.pngbin0 -> 2659 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/index.md95
-rw-r--r--doc/user/asciidoc.md8
-rw-r--r--doc/user/award_emojis.md2
-rw-r--r--doc/user/clusters/agent/index.md50
-rw-r--r--doc/user/clusters/agent/repository.md2
-rw-r--r--doc/user/clusters/agent/runner.md452
-rw-r--r--doc/user/clusters/applications.md58
-rw-r--r--doc/user/clusters/crossplane.md2
-rw-r--r--doc/user/clusters/environments.md6
-rw-r--r--doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.pngbin0 -> 17270 bytes
-rw-r--r--doc/user/clusters/management_project.md2
-rw-r--r--doc/user/compliance/license_compliance/index.md99
-rw-r--r--doc/user/discussions/img/apply_suggestion_v12_7.pngbin44697 -> 0 bytes
-rw-r--r--doc/user/discussions/img/apply_suggestion_v13_9.pngbin0 -> 37127 bytes
-rw-r--r--doc/user/discussions/img/confidential_comments_v13_9.pngbin0 -> 8311 bytes
-rw-r--r--doc/user/discussions/img/custom_commit_v13_9.pngbin0 -> 41069 bytes
-rw-r--r--doc/user/discussions/img/make_suggestion_v12_7.pngbin32548 -> 0 bytes
-rw-r--r--doc/user/discussions/img/make_suggestion_v13_9.pngbin0 -> 30463 bytes
-rw-r--r--doc/user/discussions/img/resolve_thread_open_issue.pngbin21576 -> 0 bytes
-rw-r--r--doc/user/discussions/img/resolve_thread_open_issue_v13_9.pngbin0 -> 13410 bytes
-rw-r--r--doc/user/discussions/img/suggestion_button_v12_7.pngbin28826 -> 0 bytes
-rw-r--r--doc/user/discussions/img/suggestion_button_v13_9.pngbin0 -> 27319 bytes
-rw-r--r--doc/user/discussions/index.md139
-rw-r--r--doc/user/feature_flags.md4
-rw-r--r--doc/user/gitlab_com/index.md35
-rw-r--r--doc/user/group/bulk_editing/index.md26
-rw-r--r--doc/user/group/clusters/index.md8
-rw-r--r--doc/user/group/contribution_analytics/index.md2
-rw-r--r--doc/user/group/dependency_proxy/index.md8
-rw-r--r--doc/user/group/epics/manage_epics.md15
-rw-r--r--doc/user/group/img/group_code_coverage_analytics_v13_7.pngbin21846 -> 0 bytes
-rw-r--r--doc/user/group/img/group_code_coverage_analytics_v13_9.pngbin0 -> 29915 bytes
-rw-r--r--doc/user/group/import/img/bulk_imports_v13_8.pngbin61983 -> 22574 bytes
-rw-r--r--doc/user/group/import/img/import_panel_v13_8.pngbin107428 -> 39125 bytes
-rw-r--r--doc/user/group/import/index.md4
-rw-r--r--doc/user/group/index.md89
-rw-r--r--doc/user/group/issues_analytics/index.md2
-rw-r--r--doc/user/group/iterations/index.md19
-rw-r--r--doc/user/group/repositories_analytics/index.md23
-rw-r--r--doc/user/group/roadmap/index.md9
-rw-r--r--doc/user/group/saml_sso/group_managed_accounts.md7
-rw-r--r--doc/user/group/saml_sso/index.md74
-rw-r--r--doc/user/group/saml_sso/scim_setup.md6
-rw-r--r--doc/user/group/security_dashboard/index.md8
-rw-r--r--doc/user/group/settings/import_export.md5
-rw-r--r--doc/user/group/value_stream_analytics/index.md4
-rw-r--r--doc/user/img/activity_followed_users_v13_9.pngbin0 -> 113807 bytes
-rw-r--r--doc/user/incident_management/index.md8
-rw-r--r--doc/user/index.md10
-rw-r--r--doc/user/infrastructure/index.md13
-rw-r--r--doc/user/infrastructure/mr_integration.md2
-rw-r--r--doc/user/infrastructure/terraform_state.md6
-rw-r--r--doc/user/markdown.md205
-rw-r--r--doc/user/operations_dashboard/index.md12
-rw-r--r--doc/user/packages/composer_repository/index.md8
-rw-r--r--doc/user/packages/conan_repository/index.md34
-rw-r--r--doc/user/packages/container_registry/index.md66
-rw-r--r--doc/user/packages/dependency_proxy/index.md115
-rw-r--r--doc/user/packages/generic_packages/index.md7
-rw-r--r--doc/user/packages/go_proxy/index.md6
-rw-r--r--doc/user/packages/index.md5
-rw-r--r--doc/user/packages/maven_repository/index.md66
-rw-r--r--doc/user/packages/npm_registry/index.md136
-rw-r--r--doc/user/packages/nuget_repository/index.md38
-rw-r--r--doc/user/packages/package_registry/index.md14
-rw-r--r--doc/user/packages/pypi_repository/index.md6
-rw-r--r--doc/user/packages/workflows/project_registry.md12
-rw-r--r--doc/user/permissions.md30
-rw-r--r--doc/user/profile/account/create_accounts.md4
-rw-r--r--doc/user/profile/account/delete_account.md19
-rw-r--r--doc/user/profile/account/index.md8
-rw-r--r--doc/user/profile/account/two_factor_authentication.md22
-rw-r--r--doc/user/profile/active_sessions.md16
-rw-r--r--doc/user/profile/img/profil-preferences-navigation-theme.pngbin16397 -> 0 bytes
-rw-r--r--doc/user/profile/img/profile_following_v13_9.pngbin0 -> 162916 bytes
-rw-r--r--doc/user/profile/img/profile_settings_dropdown.pngbin6972 -> 0 bytes
-rw-r--r--doc/user/profile/index.md149
-rw-r--r--doc/user/profile/notifications.md82
-rw-r--r--doc/user/profile/personal_access_tokens.md9
-rw-r--r--doc/user/profile/preferences.md22
-rw-r--r--doc/user/project/autocomplete_characters.md11
-rw-r--r--doc/user/project/badges.md2
-rw-r--r--doc/user/project/builds/artifacts.md8
-rw-r--r--doc/user/project/bulk_editing.md24
-rw-r--r--doc/user/project/canary_deployments.md6
-rw-r--r--doc/user/project/ci_cd_for_external_repo.md8
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md4
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md2
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md14
-rw-r--r--doc/user/project/clusters/eks_and_gitlab/index.md8
-rw-r--r--doc/user/project/clusters/index.md100
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md4
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md5
-rw-r--r--doc/user/project/clusters/protect/container_network_security/quick_start_guide.md4
-rw-r--r--doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md4
-rw-r--r--doc/user/project/clusters/runbooks/index.md2
-rw-r--r--doc/user/project/clusters/serverless/aws.md8
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/code_intelligence.md2
-rw-r--r--doc/user/project/code_owners.md95
-rw-r--r--doc/user/project/container_registry.md8
-rw-r--r--doc/user/project/cycle_analytics.md8
-rw-r--r--doc/user/project/deploy_boards.md8
-rw-r--r--doc/user/project/deploy_keys/index.md26
-rw-r--r--doc/user/project/deploy_tokens/index.md2
-rw-r--r--doc/user/project/description_templates.md85
-rw-r--r--doc/user/project/file_lock.md9
-rw-r--r--doc/user/project/git_attributes.md2
-rw-r--r--doc/user/project/gpg_signed_commits/index.md8
-rw-r--r--doc/user/project/highlighting.md19
-rw-r--r--doc/user/project/img/optional_code_owners_sections_v13_8.pngbin104264 -> 27377 bytes
-rw-r--r--doc/user/project/img/service_desk_nav_item.pngbin5158 -> 0 bytes
-rw-r--r--doc/user/project/import/cvs.md4
-rw-r--r--doc/user/project/import/gemnasium.md12
-rw-r--r--doc/user/project/import/index.md22
-rw-r--r--doc/user/project/import/repo_by_url.md18
-rw-r--r--doc/user/project/import/svn.md2
-rw-r--r--doc/user/project/import/tfs.md8
-rw-r--r--doc/user/project/index.md398
-rw-r--r--doc/user/project/integrations/bamboo.md10
-rw-r--r--doc/user/project/integrations/ewm.md2
-rw-r--r--doc/user/project/integrations/generic_alerts.md8
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md2
-rw-r--r--doc/user/project/integrations/img/mattermost_configuration.pngbin44878 -> 0 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_configuration_v2.pngbin0 -> 75931 bytes
-rw-r--r--doc/user/project/integrations/irker.md2
-rw-r--r--doc/user/project/integrations/jira.md141
-rw-r--r--doc/user/project/integrations/jira_cloud_configuration.md15
-rw-r--r--doc/user/project/integrations/jira_integrations.md45
-rw-r--r--doc/user/project/integrations/jira_server_configuration.md68
-rw-r--r--doc/user/project/integrations/kubernetes.md8
-rw-r--r--doc/user/project/integrations/mattermost.md4
-rw-r--r--doc/user/project/integrations/overview.md8
-rw-r--r--doc/user/project/integrations/project_services.md8
-rw-r--r--doc/user/project/integrations/prometheus.md53
-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.md4
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md4
-rw-r--r--doc/user/project/integrations/prometheus_library/metrics.md8
-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/prometheus_units.md8
-rw-r--r--doc/user/project/integrations/services_templates.md4
-rw-r--r--doc/user/project/integrations/slack.md1
-rw-r--r--doc/user/project/integrations/slack_slash_commands.md2
-rw-r--r--doc/user/project/integrations/webhooks.md110
-rw-r--r--doc/user/project/issue_board.md53
-rw-r--r--doc/user/project/issues/automatic_issue_closing.md8
-rw-r--r--doc/user/project/issues/closing_issues.md8
-rw-r--r--doc/user/project/issues/confidential_issues.md4
-rw-r--r--doc/user/project/issues/create_new_issue.md8
-rw-r--r--doc/user/project/issues/csv_export.md9
-rw-r--r--doc/user/project/issues/csv_import.md7
-rw-r--r--doc/user/project/issues/deleting_issues.md8
-rw-r--r--doc/user/project/issues/design_management.md12
-rw-r--r--doc/user/project/issues/due_dates.md2
-rw-r--r--doc/user/project/issues/index.md186
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md32
-rw-r--r--doc/user/project/issues/issue_weight.md6
-rw-r--r--doc/user/project/issues/managing_issues.md13
-rw-r--r--doc/user/project/issues/moving_issues.md8
-rw-r--r--doc/user/project/issues/multiple_assignees_for_issues.md6
-rw-r--r--doc/user/project/issues/related_issues.md4
-rw-r--r--doc/user/project/issues/similar_issues.md8
-rw-r--r--doc/user/project/issues/sorting_issue_lists.md2
-rw-r--r--doc/user/project/labels.md28
-rw-r--r--doc/user/project/maven_packages.md8
-rw-r--r--doc/user/project/members/img/access_requests_management_13_8.pngbin21685 -> 0 bytes
-rw-r--r--doc/user/project/members/img/access_requests_management_v13_9.pngbin0 -> 24246 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_accept_13_8.pngbin18139 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_accept_v13_9.pngbin0 -> 21877 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_ready_v13_8.png (renamed from doc/user/project/members/img/add_user_email_ready_13_8.png)bin28850 -> 28850 bytes
-rw-r--r--doc/user/project/members/img/add_user_email_search_v13_8.png (renamed from doc/user/project/members/img/add_user_email_search_13_8.png)bin29293 -> 29293 bytes
-rw-r--r--doc/user/project/members/img/add_user_give_permissions_v13_8.png (renamed from doc/user/project/members/img/add_user_give_permissions_13_8.png)bin69132 -> 69132 bytes
-rw-r--r--doc/user/project/members/img/add_user_import_members_from_another_project_v13_8.png (renamed from doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png)bin35191 -> 35191 bytes
-rw-r--r--doc/user/project/members/img/add_user_imported_members_13_8.pngbin47167 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_imported_members_v13_9.pngbin0 -> 58569 bytes
-rw-r--r--doc/user/project/members/img/add_user_list_members_13_8.pngbin39827 -> 0 bytes
-rw-r--r--doc/user/project/members/img/add_user_list_members_v13_9.pngbin0 -> 48350 bytes
-rw-r--r--doc/user/project/members/img/add_user_search_people_v13_8.png (renamed from doc/user/project/members/img/add_user_search_people_13_8.png)bin28335 -> 28335 bytes
-rw-r--r--doc/user/project/members/img/project_groups_tab_13_8.pngbin65200 -> 0 bytes
-rw-r--r--doc/user/project/members/img/project_groups_tab_v13_9.pngbin0 -> 65788 bytes
-rw-r--r--doc/user/project/members/img/project_members_13_8.pngbin34744 -> 0 bytes
-rw-r--r--doc/user/project/members/img/project_members_filter_direct_v13_9.pngbin0 -> 25485 bytes
-rw-r--r--doc/user/project/members/img/project_members_filter_inherited_v13_9.pngbin0 -> 36770 bytes
-rw-r--r--doc/user/project/members/img/project_members_search_v13_9.pngbin0 -> 24940 bytes
-rw-r--r--doc/user/project/members/img/project_members_sort_v13_9.pngbin0 -> 48520 bytes
-rw-r--r--doc/user/project/members/img/project_members_v13_9.pngbin0 -> 45071 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups_tab_v13_8.pngbin62368 -> 0 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups_tab_v13_9.pngbin0 -> 65630 bytes
-rw-r--r--doc/user/project/members/index.md88
-rw-r--r--doc/user/project/members/share_project_with_groups.md4
-rw-r--r--doc/user/project/merge_requests.md8
-rw-r--r--doc/user/project/merge_requests/allow_collaboration.md21
-rw-r--r--doc/user/project/merge_requests/authorization_for_merge_requests.md2
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md21
-rw-r--r--doc/user/project/merge_requests/code_quality.md128
-rw-r--r--doc/user/project/merge_requests/code_quality_diff.md8
-rw-r--r--doc/user/project/merge_requests/container_scanning.md8
-rw-r--r--doc/user/project/merge_requests/creating_merge_requests.md4
-rw-r--r--doc/user/project/merge_requests/csv_export.md2
-rw-r--r--doc/user/project/merge_requests/dast.md8
-rw-r--r--doc/user/project/merge_requests/dependency_scanning.md8
-rw-r--r--doc/user/project/merge_requests/fast_forward_merge.md2
-rw-r--r--doc/user/project/merge_requests/getting_started.md165
-rw-r--r--doc/user/project/merge_requests/index.md2
-rw-r--r--doc/user/project/merge_requests/license_management.md8
-rw-r--r--doc/user/project/merge_requests/maintainer_access.md8
-rw-r--r--doc/user/project/merge_requests/merge_request_approvals.md118
-rw-r--r--doc/user/project/merge_requests/merge_request_dependencies.md2
-rw-r--r--doc/user/project/merge_requests/merge_request_discussion_resolution.md8
-rw-r--r--doc/user/project/merge_requests/merge_when_build_succeeds.md10
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md11
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md48
-rw-r--r--doc/user/project/merge_requests/revert_changes.md2
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md189
-rw-r--r--doc/user/project/merge_requests/sast.md8
-rw-r--r--doc/user/project/merge_requests/sast_docker.md8
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md30
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md47
-rw-r--r--doc/user/project/merge_requests/versions.md7
-rw-r--r--doc/user/project/merge_requests/work_in_progress_merge_requests.md24
-rw-r--r--doc/user/project/milestones/burndown_and_burnup_charts.md18
-rw-r--r--doc/user/project/milestones/index.md26
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md2
-rw-r--r--doc/user/project/operations/alert_management.md8
-rw-r--r--doc/user/project/operations/dashboard_settings.md8
-rw-r--r--doc/user/project/operations/error_tracking.md8
-rw-r--r--doc/user/project/operations/feature_flags.md8
-rw-r--r--doc/user/project/operations/index.md8
-rw-r--r--doc/user/project/operations/linking_to_an_external_dashboard.md8
-rw-r--r--doc/user/project/operations/tracing.md8
-rw-r--r--doc/user/project/packages/maven.md8
-rw-r--r--doc/user/project/packages/maven_packages.md8
-rw-r--r--doc/user/project/packages/maven_repository.md8
-rw-r--r--doc/user/project/packages/npm_registry.md8
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md5
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md2
-rw-r--r--doc/user/project/pages/getting_started/fork_sample_project.md8
-rw-r--r--doc/user/project/pages/getting_started/new_or_existing_website.md8
-rw-r--r--doc/user/project/pages/getting_started/pages_bundled_template.md8
-rw-r--r--doc/user/project/pages/getting_started/pages_forked_sample_project.md4
-rw-r--r--doc/user/project/pages/getting_started_part_four.md8
-rw-r--r--doc/user/project/pages/getting_started_part_one.md4
-rw-r--r--doc/user/project/pages/getting_started_part_three.md8
-rw-r--r--doc/user/project/pages/getting_started_part_two.md8
-rw-r--r--doc/user/project/pages/index.md2
-rw-r--r--doc/user/project/pages/introduction.md2
-rw-r--r--doc/user/project/pages/pages_access_control.md4
-rw-r--r--doc/user/project/pipelines/job_artifacts.md8
-rw-r--r--doc/user/project/pipelines/schedules.md8
-rw-r--r--doc/user/project/pipelines/settings.md8
-rw-r--r--doc/user/project/protected_branches.md135
-rw-r--r--doc/user/project/protected_tags.md19
-rw-r--r--doc/user/project/push_options.md2
-rw-r--r--doc/user/project/quick_actions.md14
-rw-r--r--doc/user/project/releases.md8
-rw-r--r--doc/user/project/releases/index.md12
-rw-r--r--doc/user/project/repository/branches/index.md8
-rw-r--r--doc/user/project/repository/file_finder.md4
-rw-r--r--doc/user/project/repository/forking_workflow.md2
-rw-r--r--doc/user/project/repository/git_blame.md2
-rw-r--r--doc/user/project/repository/git_history.md2
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md42
-rw-r--r--doc/user/project/repository/index.md53
-rw-r--r--doc/user/project/repository/jupyter_notebooks/index.md2
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md101
-rw-r--r--doc/user/project/repository/repository_mirroring.md62
-rw-r--r--doc/user/project/repository/web_editor.md145
-rw-r--r--doc/user/project/repository/x509_signed_commits/index.md2
-rw-r--r--doc/user/project/requirements/index.md46
-rw-r--r--doc/user/project/security_dashboard.md8
-rw-r--r--doc/user/project/service_desk.md110
-rw-r--r--doc/user/project/settings/import_export.md6
-rw-r--r--doc/user/project/settings/index.md55
-rw-r--r--doc/user/project/settings/project_access_tokens.md8
-rw-r--r--doc/user/project/slash_commands.md8
-rw-r--r--doc/user/project/static_site_editor/index.md51
-rw-r--r--doc/user/project/status_page/index.md8
-rw-r--r--doc/user/project/time_tracking.md2
-rw-r--r--doc/user/project/web_ide/index.md34
-rw-r--r--doc/user/project/wiki/index.md6
-rw-r--r--doc/user/project/working_with_projects.md341
-rw-r--r--doc/user/search/advanced_global_search.md5
-rw-r--r--doc/user/search/advanced_search_syntax.md8
-rw-r--r--doc/user/search/img/search_history.gifbin265970 -> 0 bytes
-rw-r--r--doc/user/search/index.md67
-rw-r--r--doc/user/shortcuts.md17
-rw-r--r--doc/user/snippets.md60
-rw-r--r--doc/user/todos.md2
-rw-r--r--doc/user/upgrade_email_bypass.md4
-rw-r--r--doc/user/usage_quotas.md8
-rw-r--r--generator_templates/usage_metric_definition/metric_definition.yml21
-rw-r--r--lefthook.yml4
-rw-r--r--lib/api/api.rb37
-rw-r--r--lib/api/applications.rb16
-rw-r--r--lib/api/ci/pipelines.rb1
-rw-r--r--lib/api/concerns/packages/conan_endpoints.rb1
-rw-r--r--lib/api/debian_group_packages.rb4
-rw-r--r--lib/api/debian_package_endpoints.rb21
-rw-r--r--lib/api/debian_project_packages.rb14
-rw-r--r--lib/api/deploy_tokens.rb10
-rw-r--r--lib/api/deployments.rb2
-rw-r--r--lib/api/entities/application_setting.rb1
-rw-r--r--lib/api/entities/ci/job.rb3
-rw-r--r--lib/api/entities/merge_request_basic.rb2
-rw-r--r--lib/api/entities/user.rb7
-rw-r--r--lib/api/entities/user_status.rb1
-rw-r--r--lib/api/events.rb2
-rw-r--r--lib/api/generic_packages.rb4
-rwxr-xr-xlib/api/go_proxy.rb16
-rw-r--r--lib/api/group_labels.rb2
-rw-r--r--lib/api/group_packages.rb4
-rw-r--r--lib/api/helpers.rb22
-rw-r--r--lib/api/helpers/internal_helpers.rb2
-rw-r--r--lib/api/helpers/members_helpers.rb2
-rw-r--r--lib/api/helpers/notes_helpers.rb2
-rw-r--r--lib/api/helpers/rate_limiter.rb4
-rw-r--r--lib/api/internal/base.rb36
-rw-r--r--lib/api/internal/kubernetes.rb2
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/api/jobs.rb5
-rw-r--r--lib/api/labels.rb6
-rw-r--r--lib/api/members.rb12
-rw-r--r--lib/api/merge_requests.rb6
-rw-r--r--lib/api/notes.rb4
-rw-r--r--lib/api/nuget_group_packages.rb2
-rw-r--r--lib/api/nuget_project_packages.rb2
-rw-r--r--lib/api/project_packages.rb4
-rw-r--r--lib/api/project_templates.rb18
-rw-r--r--lib/api/projects.rb2
-rw-r--r--lib/api/repositories.rb59
-rw-r--r--lib/api/resource_access_tokens.rb94
-rw-r--r--lib/api/rubygem_packages.rb102
-rw-r--r--lib/api/settings.rb11
-rw-r--r--lib/api/snippet_repository_storage_moves.rb7
-rw-r--r--lib/api/subscriptions.rb5
-rw-r--r--lib/api/suggestions.rb10
-rw-r--r--lib/api/support/git_access_actor.rb2
-rw-r--r--lib/api/users.rb70
-rw-r--r--lib/api/version.rb2
-rw-r--r--lib/atlassian/jira_connect/client.rb8
-rw-r--r--lib/atlassian/jira_connect/serializers/feature_flag_entity.rb2
-rw-r--r--lib/backup/files.rb2
-rw-r--r--lib/banzai/filter/asset_proxy_filter.rb4
-rw-r--r--lib/banzai/filter/custom_emoji_filter.rb62
-rw-r--r--lib/banzai/filter/feature_flag_reference_filter.rb33
-rw-r--r--lib/banzai/filter/markdown_post_escape_filter.rb40
-rw-r--r--lib/banzai/filter/markdown_pre_escape_filter.rb43
-rw-r--r--lib/banzai/filter/plantuml_filter.rb2
-rw-r--r--lib/banzai/filter/truncate_source_filter.rb4
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb4
-rw-r--r--lib/banzai/pipeline/plain_markdown_pipeline.rb4
-rw-r--r--lib/banzai/pipeline/single_line_pipeline.rb3
-rw-r--r--lib/banzai/reference_parser/feature_flag_parser.rb19
-rw-r--r--lib/bulk_imports/common/extractors/graphql_extractor.rb17
-rw-r--r--lib/bulk_imports/common/loaders/entity_loader.rb2
-rw-r--r--lib/bulk_imports/common/transformers/award_emoji_transformer.rb27
-rw-r--r--lib/bulk_imports/common/transformers/hash_key_digger.rb23
-rw-r--r--lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb19
-rw-r--r--lib/bulk_imports/groups/extractors/subgroups_extractor.rb4
-rw-r--r--lib/bulk_imports/groups/graphql/get_group_query.rb36
-rw-r--r--lib/bulk_imports/groups/graphql/get_labels_query.rb50
-rw-r--r--lib/bulk_imports/groups/graphql/get_members_query.rb55
-rw-r--r--lib/bulk_imports/groups/loaders/labels_loader.rb15
-rw-r--r--lib/bulk_imports/groups/loaders/members_loader.rb17
-rw-r--r--lib/bulk_imports/groups/pipelines/group_pipeline.rb2
-rw-r--r--lib/bulk_imports/groups/pipelines/labels_pipeline.rb30
-rw-r--r--lib/bulk_imports/groups/pipelines/members_pipeline.rb31
-rw-r--r--lib/bulk_imports/groups/transformers/member_attributes_transformer.rb56
-rw-r--r--lib/bulk_imports/importers/group_importer.rb15
-rw-r--r--lib/bulk_imports/pipeline.rb21
-rw-r--r--lib/bulk_imports/pipeline/context.rb31
-rw-r--r--lib/bulk_imports/pipeline/extracted_data.rb26
-rw-r--r--lib/bulk_imports/pipeline/runner.rb72
-rw-r--r--lib/feature.rb2
-rw-r--r--lib/feature/gitaly.rb12
-rw-r--r--lib/generators/gitlab/usage_metric_definition_generator.rb89
-rw-r--r--lib/gitlab.rb6
-rw-r--r--lib/gitlab/alert_management/payload.rb7
-rw-r--r--lib/gitlab/alert_management/payload/base.rb31
-rw-r--r--lib/gitlab/alert_management/payload/generic.rb5
-rw-r--r--lib/gitlab/alert_management/payload/prometheus.rb38
-rw-r--r--lib/gitlab/api_authentication/token_locator.rb11
-rw-r--r--lib/gitlab/api_authentication/token_resolver.rb100
-rw-r--r--lib/gitlab/application_rate_limiter.rb18
-rw-r--r--lib/gitlab/auth/otp/session_enforcer.rb36
-rw-r--r--lib/gitlab/auth/u2f_webauthn_converter.rb38
-rw-r--r--lib/gitlab/background_migration.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb22
-rw-r--r--lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_u2f_webauthn.rb21
-rw-r--r--lib/gitlab/background_migration/populate_issue_email_participants.rb28
-rw-r--r--lib/gitlab/background_migration/populate_uuids_for_security_findings.rb18
-rw-r--r--lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb50
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/namespace.rb1
-rw-r--r--lib/gitlab/badge/base.rb23
-rw-r--r--lib/gitlab/badge/coverage/metadata.rb30
-rw-r--r--lib/gitlab/badge/coverage/report.rb75
-rw-r--r--lib/gitlab/badge/coverage/template.rb64
-rw-r--r--lib/gitlab/badge/metadata.rb42
-rw-r--r--lib/gitlab/badge/pipeline/metadata.rb29
-rw-r--r--lib/gitlab/badge/pipeline/status.rb48
-rw-r--r--lib/gitlab/badge/pipeline/template.rb61
-rw-r--r--lib/gitlab/badge/template.rb54
-rw-r--r--lib/gitlab/changelog/ast.rb157
-rw-r--r--lib/gitlab/changelog/committer.rb69
-rw-r--r--lib/gitlab/changelog/config.rb72
-rw-r--r--lib/gitlab/changelog/error.rb8
-rw-r--r--lib/gitlab/changelog/eval_state.rb26
-rw-r--r--lib/gitlab/changelog/generator.rb59
-rw-r--r--lib/gitlab/changelog/parser.rb176
-rw-r--r--lib/gitlab/changelog/release.rb102
-rw-r--r--lib/gitlab/changelog/template.tpl15
-rw-r--r--lib/gitlab/chaos.rb8
-rw-r--r--lib/gitlab/ci/badge/base.rb23
-rw-r--r--lib/gitlab/ci/badge/coverage/metadata.rb30
-rw-r--r--lib/gitlab/ci/badge/coverage/report.rb75
-rw-r--r--lib/gitlab/ci/badge/coverage/template.rb64
-rw-r--r--lib/gitlab/ci/badge/metadata.rb42
-rw-r--r--lib/gitlab/ci/badge/pipeline/metadata.rb29
-rw-r--r--lib/gitlab/ci/badge/pipeline/status.rb48
-rw-r--r--lib/gitlab/ci/badge/pipeline/template.rb61
-rw-r--r--lib/gitlab/ci/badge/template.rb54
-rw-r--r--lib/gitlab/ci/build/credentials/base.rb2
-rw-r--r--lib/gitlab/ci/build/credentials/factory.rb2
-rw-r--r--lib/gitlab/ci/build/credentials/registry.rb26
-rw-r--r--lib/gitlab/ci/build/credentials/registry/dependency_proxy.rb21
-rw-r--r--lib/gitlab/ci/build/credentials/registry/gitlab_registry.rb32
-rw-r--r--lib/gitlab/ci/build/rules.rb17
-rw-r--r--lib/gitlab/ci/charts.rb8
-rw-r--r--lib/gitlab/ci/config.rb6
-rw-r--r--lib/gitlab/ci/config/entry/commands.rb6
-rw-r--r--lib/gitlab/ci/config/entry/job.rb8
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb8
-rw-r--r--lib/gitlab/ci/config/external/file/base.rb2
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb2
-rw-r--r--lib/gitlab/ci/config/yaml.rb29
-rw-r--r--lib/gitlab/ci/config/yaml/tags.rb13
-rw-r--r--lib/gitlab/ci/config/yaml/tags/base.rb72
-rw-r--r--lib/gitlab/ci/config/yaml/tags/reference.rb46
-rw-r--r--lib/gitlab/ci/config/yaml/tags/resolver.rb46
-rw-r--r--lib/gitlab/ci/features.rb25
-rw-r--r--lib/gitlab/ci/jwt.rb25
-rw-r--r--lib/gitlab/ci/parsers.rb4
-rw-r--r--lib/gitlab/ci/parsers/instrumentation.rb32
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb10
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content.rb8
-rw-r--r--lib/gitlab/ci/pipeline/chain/template_usage.rb2
-rw-r--r--lib/gitlab/ci/pipeline/metrics.rb9
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb32
-rw-r--r--lib/gitlab/ci/pipeline/seed/build/resource_group.rb39
-rw-r--r--lib/gitlab/ci/pipeline/seed/processable/resource_group.rb39
-rw-r--r--lib/gitlab/ci/reports/codequality_mr_diff.rb39
-rw-r--r--lib/gitlab/ci/status/bridge/factory.rb1
-rw-r--r--lib/gitlab/ci/status/bridge/waiting_for_resource.rb12
-rw-r--r--lib/gitlab/ci/status/build/waiting_for_resource.rb17
-rw-r--r--lib/gitlab/ci/status/processable/waiting_for_resource.rb27
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Maven.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml22
-rw-r--r--lib/gitlab/ci/trace.rb20
-rw-r--r--lib/gitlab/ci/trace/checksum.rb12
-rw-r--r--lib/gitlab/ci/trace/chunked_io.rb14
-rw-r--r--lib/gitlab/ci/variables/collection/sorted.rb7
-rw-r--r--lib/gitlab/ci/variables/helpers.rb32
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb4
-rw-r--r--lib/gitlab/cleanup/orphan_job_artifact_files.rb15
-rw-r--r--lib/gitlab/cleanup/orphan_lfs_file_references.rb9
-rw-r--r--lib/gitlab/cluster/lifecycle_events.rb30
-rw-r--r--lib/gitlab/cluster/puma_worker_killer_initializer.rb4
-rw-r--r--lib/gitlab/composer/cache.rb71
-rw-r--r--lib/gitlab/composer/version_index.rb2
-rw-r--r--lib/gitlab/conan_token.rb2
-rw-r--r--lib/gitlab/config/entry/validators.rb17
-rw-r--r--lib/gitlab/config/entry/validators/nested_array_helpers.rb46
-rw-r--r--lib/gitlab/config/loader/yaml.rb8
-rw-r--r--lib/gitlab/crypto_helper.rb31
-rw-r--r--lib/gitlab/current_settings.rb4
-rw-r--r--lib/gitlab/cycle_analytics/summary/deploy.rb13
-rw-r--r--lib/gitlab/danger/base_linter.rb96
-rw-r--r--lib/gitlab/danger/changelog.rb92
-rw-r--r--lib/gitlab/danger/commit_linter.rb158
-rw-r--r--lib/gitlab/danger/emoji_checker.rb45
-rw-r--r--lib/gitlab/danger/helper.rb273
-rw-r--r--lib/gitlab/danger/merge_request_linter.rb36
-rw-r--r--lib/gitlab/danger/request_helper.rb23
-rw-r--r--lib/gitlab/danger/roulette.rb169
-rw-r--r--lib/gitlab/danger/sidekiq_queues.rb37
-rw-r--r--lib/gitlab/danger/teammate.rb117
-rw-r--r--lib/gitlab/danger/title_linting.rb23
-rw-r--r--lib/gitlab/danger/weightage.rb10
-rw-r--r--lib/gitlab/danger/weightage/maintainers.rb33
-rw-r--r--lib/gitlab/danger/weightage/reviewers.rb65
-rw-r--r--lib/gitlab/data_builder/build.rb3
-rw-r--r--lib/gitlab/data_builder/pipeline.rb5
-rw-r--r--lib/gitlab/database/consistency.rb31
-rw-r--r--lib/gitlab/database/migration_helpers/v2.rb219
-rw-r--r--lib/gitlab/database/migrations/instrumentation.rb57
-rw-r--r--lib/gitlab/database/migrations/observation.rb14
-rw-r--r--lib/gitlab/database/migrations/observers.rb15
-rw-r--r--lib/gitlab/database/migrations/observers/migration_observer.rb29
-rw-r--r--lib/gitlab/database/migrations/observers/total_database_size_change.rb31
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb4
-rw-r--r--lib/gitlab/diff/char_diff.rb74
-rw-r--r--lib/gitlab/diff/file_collection/base.rb2
-rw-r--r--lib/gitlab/diff/file_collection_sorter.rb14
-rw-r--r--lib/gitlab/diff/highlight.rb5
-rw-r--r--lib/gitlab/diff/highlight_cache.rb11
-rw-r--r--lib/gitlab/diff/inline_diff.rb43
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb10
-rw-r--r--lib/gitlab/emoji.rb10
-rw-r--r--lib/gitlab/experimentation.rb62
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb8
-rw-r--r--lib/gitlab/experimentation/experiment.rb3
-rw-r--r--lib/gitlab/experimentation_logger.rb9
-rw-r--r--lib/gitlab/faraday.rb7
-rw-r--r--lib/gitlab/file_type_detection.rb2
-rw-r--r--lib/gitlab/git/commit.rb3
-rw-r--r--lib/gitlab/git/diff.rb2
-rw-r--r--lib/gitlab/git/push.rb4
-rw-r--r--lib/gitlab/git/rugged_impl/commit.rb1
-rw-r--r--lib/gitlab/git/wiki.rb2
-rw-r--r--lib/gitlab/git_access.rb36
-rw-r--r--lib/gitlab/gitaly_client.rb23
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb3
-rw-r--r--lib/gitlab/gitaly_client/conflicts_service.rb3
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb26
-rw-r--r--lib/gitlab/gitaly_client/storage_settings.rb5
-rw-r--r--lib/gitlab/global_id.rb4
-rw-r--r--lib/gitlab/gon_helper.rb4
-rw-r--r--lib/gitlab/graphql/docs/templates/default.md.haml2
-rw-r--r--lib/gitlab/graphql/pagination/connections.rb4
-rw-r--r--lib/gitlab/graphql/pagination/offset_paginated_relation.rb12
-rw-r--r--lib/gitlab/graphql/queries.rb14
-rw-r--r--lib/gitlab/health_checks/base_abstract_check.rb4
-rw-r--r--lib/gitlab/health_checks/master_check.rb13
-rw-r--r--lib/gitlab/health_checks/probes/collection.rb1
-rw-r--r--lib/gitlab/hook_data/base_builder.rb6
-rw-r--r--lib/gitlab/hook_data/group_builder.rb51
-rw-r--r--lib/gitlab/hook_data/subgroup_builder.rb50
-rw-r--r--lib/gitlab/import_export.rb4
-rw-r--r--lib/gitlab/import_export/decompressed_archive_size_validator.rb83
-rw-r--r--lib/gitlab/import_export/design_repo_restorer.rb7
-rw-r--r--lib/gitlab/import_export/design_repo_saver.rb12
-rw-r--r--lib/gitlab/import_export/file_importer.rb2
-rw-r--r--lib/gitlab/import_export/group/tree_restorer.rb2
-rw-r--r--lib/gitlab/import_export/importer.rb6
-rw-r--r--lib/gitlab/import_export/repo_restorer.rb21
-rw-r--r--lib/gitlab/import_export/repo_saver.rb20
-rw-r--r--lib/gitlab/import_export/saver.rb6
-rw-r--r--lib/gitlab/import_export/wiki_repo_saver.rb15
-rw-r--r--lib/gitlab/instrumentation/elasticsearch_transport.rb17
-rw-r--r--lib/gitlab/instrumentation/redis_cluster_validator.rb2
-rw-r--r--lib/gitlab/instrumentation_helper.rb70
-rw-r--r--lib/gitlab/kas.rb6
-rw-r--r--lib/gitlab/kroki.rb23
-rw-r--r--lib/gitlab/kubernetes/helm/v2/certificate.rb2
-rw-r--r--lib/gitlab/lograge/custom_options.rb4
-rw-r--r--lib/gitlab/memory/instrumentation.rb71
-rw-r--r--lib/gitlab/metrics/exporter/web_exporter.rb4
-rw-r--r--lib/gitlab/metrics/methods.rb2
-rw-r--r--lib/gitlab/metrics/rack_middleware.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/external_http.rb99
-rw-r--r--lib/gitlab/metrics/subscribers/rack_attack.rb91
-rw-r--r--lib/gitlab/middleware/request_context.rb4
-rw-r--r--lib/gitlab/pages_transfer.rb14
-rw-r--r--lib/gitlab/patch/prependable.rb7
-rw-r--r--lib/gitlab/performance_bar/stats.rb29
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb6
-rw-r--r--lib/gitlab/rack_attack.rb4
-rw-r--r--lib/gitlab/rack_attack/instrumented_cache_store.rb32
-rw-r--r--lib/gitlab/recaptcha.rb4
-rw-r--r--lib/gitlab/relative_positioning.rb13
-rw-r--r--lib/gitlab/relative_positioning/range.rb14
-rw-r--r--lib/gitlab/request_context.rb2
-rw-r--r--lib/gitlab/request_forgery_protection.rb4
-rw-r--r--lib/gitlab/runtime.rb4
-rw-r--r--lib/gitlab/sample_data_template.rb2
-rw-r--r--lib/gitlab/search/query.rb18
-rw-r--r--lib/gitlab/search/sort_options.rb4
-rw-r--r--lib/gitlab/search_results.rb4
-rw-r--r--lib/gitlab/sidekiq_death_handler.rb2
-rw-r--r--lib/gitlab/sidekiq_logging/exception_handler.rb27
-rw-r--r--lib/gitlab/sidekiq_logging/logs_jobs.rb1
-rw-r--r--lib/gitlab/sidekiq_logging/structured_logger.rb48
-rw-r--r--lib/gitlab/sidekiq_middleware/client_metrics.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware/instrumentation_logger.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/metrics_helper.rb6
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb2
-rw-r--r--lib/gitlab/suggestions/commit_message.rb5
-rw-r--r--lib/gitlab/task_helpers.rb12
-rw-r--r--lib/gitlab/template/base_template.rb41
-rw-r--r--lib/gitlab/template/finders/global_template_finder.rb7
-rw-r--r--lib/gitlab/template/finders/repo_template_finder.rb6
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb12
-rw-r--r--lib/gitlab/template/issue_template.rb10
-rw-r--r--lib/gitlab/template/merge_request_template.rb10
-rw-r--r--lib/gitlab/terraform/state_migration_helper.rb31
-rw-r--r--lib/gitlab/tracking.rb4
-rw-r--r--lib/gitlab/tracking/standard_context.rb36
-rw-r--r--lib/gitlab/usage/docs/helper.rb63
-rw-r--r--lib/gitlab/usage/docs/renderer.rb32
-rw-r--r--lib/gitlab/usage/docs/templates/default.md.haml28
-rw-r--r--lib/gitlab/usage/docs/value_formatter.rb26
-rw-r--r--lib/gitlab/usage/metric.rb10
-rw-r--r--lib/gitlab/usage/metric_definition.rb13
-rw-r--r--lib/gitlab/usage/metrics/aggregates/aggregate.rb157
-rw-r--r--lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb75
-rw-r--r--lib/gitlab/usage/metrics/aggregates/sources/redis_hll.rb24
-rw-r--r--lib/gitlab/usage_data.rb99
-rw-r--r--lib/gitlab/usage_data_counters/aggregated_metrics/common.yml18
-rw-r--r--lib/gitlab/usage_data_counters/ci_template_unique_counter.rb12
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb133
-rw-r--r--lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb1
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml91
-rw-r--r--lib/gitlab/usage_data_counters/known_events/code_review_events.yml166
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml171
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ecosystem.yml22
-rw-r--r--lib/gitlab/usage_data_counters/known_events/quickactions.yml326
-rw-r--r--lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb91
-rw-r--r--lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb88
-rw-r--r--lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb28
-rw-r--r--lib/gitlab/utils/markdown.rb2
-rw-r--r--lib/gitlab/utils/measuring.rb10
-rw-r--r--lib/gitlab/utils/override.rb10
-rw-r--r--lib/gitlab/utils/usage_data.rb10
-rw-r--r--lib/gitlab/workhorse.rb4
-rw-r--r--lib/gitlab_danger.rb58
-rw-r--r--lib/object_storage/config.rb36
-rw-r--r--lib/object_storage/direct_upload.rb4
-rw-r--r--lib/peek/views/external_http.rb101
-rw-r--r--lib/release_highlights/validator/entry.rb2
-rw-r--r--lib/rouge/formatters/html_gitlab.rb4
-rw-r--r--lib/security/ci_configuration/sast_build_actions.rb170
-rw-r--r--lib/tasks/benchmark.rake11
-rw-r--r--lib/tasks/brakeman.rake2
-rw-r--r--lib/tasks/cache.rake2
-rw-r--r--lib/tasks/ci/cleanup.rake2
-rw-r--r--lib/tasks/cleanup.rake2
-rw-r--r--lib/tasks/config_lint.rake2
-rw-r--r--lib/tasks/db_obsolete_ignored_columns.rake2
-rw-r--r--lib/tasks/dev.rake2
-rw-r--r--lib/tasks/downtime_check.rake2
-rw-r--r--lib/tasks/eslint.rake2
-rw-r--r--lib/tasks/file_hooks.rake2
-rw-r--r--lib/tasks/frontend.rake4
-rw-r--r--lib/tasks/gemojione.rake2
-rw-r--r--lib/tasks/gitlab/artifacts/check.rake2
-rw-r--r--lib/tasks/gitlab/artifacts/migrate.rake2
-rw-r--r--lib/tasks/gitlab/backup.rake2
-rw-r--r--lib/tasks/gitlab/bulk_add_permission.rake2
-rw-r--r--lib/tasks/gitlab/check.rake2
-rw-r--r--lib/tasks/gitlab/cleanup.rake9
-rw-r--r--lib/tasks/gitlab/container_registry.rake2
-rw-r--r--lib/tasks/gitlab/db.rake34
-rw-r--r--lib/tasks/gitlab/doctor/secrets.rake2
-rw-r--r--lib/tasks/gitlab/exclusive_lease.rake2
-rw-r--r--lib/tasks/gitlab/external_diffs.rake2
-rw-r--r--lib/tasks/gitlab/features.rake2
-rw-r--r--lib/tasks/gitlab/generate_sample_prometheus_data.rake2
-rw-r--r--lib/tasks/gitlab/git.rake2
-rw-r--r--lib/tasks/gitlab/gitaly.rake2
-rw-r--r--lib/tasks/gitlab/graphql.rake42
-rw-r--r--lib/tasks/gitlab/helpers.rake2
-rw-r--r--lib/tasks/gitlab/import.rake2
-rw-r--r--lib/tasks/gitlab/import_export.rake2
-rw-r--r--lib/tasks/gitlab/info.rake2
-rw-r--r--lib/tasks/gitlab/ldap.rake2
-rw-r--r--lib/tasks/gitlab/lfs/check.rake2
-rw-r--r--lib/tasks/gitlab/lfs/migrate.rake2
-rw-r--r--lib/tasks/gitlab/list_repos.rake2
-rw-r--r--lib/tasks/gitlab/packages/events.rake2
-rw-r--r--lib/tasks/gitlab/packages/migrate.rake2
-rw-r--r--lib/tasks/gitlab/pages.rake68
-rw-r--r--lib/tasks/gitlab/password.rake31
-rw-r--r--lib/tasks/gitlab/praefect.rake2
-rw-r--r--lib/tasks/gitlab/seed.rake2
-rw-r--r--lib/tasks/gitlab/setup.rake2
-rw-r--r--lib/tasks/gitlab/shell.rake2
-rw-r--r--lib/tasks/gitlab/snippets.rake12
-rw-r--r--lib/tasks/gitlab/storage.rake2
-rw-r--r--lib/tasks/gitlab/tcp_check.rake2
-rw-r--r--lib/tasks/gitlab/terraform/migrate.rake23
-rw-r--r--lib/tasks/gitlab/test.rake2
-rw-r--r--lib/tasks/gitlab/two_factor.rake2
-rw-r--r--lib/tasks/gitlab/update_templates.rake2
-rw-r--r--lib/tasks/gitlab/uploads/check.rake2
-rw-r--r--lib/tasks/gitlab/uploads/migrate.rake2
-rw-r--r--lib/tasks/gitlab/uploads/sanitize.rake2
-rw-r--r--lib/tasks/gitlab/usage_data.rake8
-rw-r--r--lib/tasks/gitlab/user_management.rake2
-rw-r--r--lib/tasks/gitlab/web_hook.rake2
-rw-r--r--lib/tasks/gitlab/workhorse.rake2
-rw-r--r--lib/tasks/gitlab/x509/update.rake2
-rw-r--r--lib/tasks/gitlab_danger.rake4
-rw-r--r--lib/tasks/grape.rake2
-rw-r--r--lib/tasks/haml-lint.rake2
-rw-r--r--lib/tasks/import.rake2
-rw-r--r--lib/tasks/karma.rake2
-rw-r--r--lib/tasks/lint.rake2
-rw-r--r--lib/tasks/migrate/composite_primary_keys.rake2
-rw-r--r--lib/tasks/migrate/migrate_iids.rake2
-rw-r--r--lib/tasks/migrate/setup_postgresql.rake2
-rw-r--r--lib/tasks/pngquant.rake2
-rw-r--r--lib/tasks/rubocop.rake2
-rw-r--r--lib/tasks/scss-lint.rake2
-rw-r--r--lib/tasks/setup.rake2
-rw-r--r--lib/tasks/test.rake2
-rw-r--r--lib/tasks/tokens.rake2
-rw-r--r--locale/am_ET/gitlab.po1788
-rw-r--r--locale/ar_SA/gitlab.po1800
-rw-r--r--locale/as_IN/gitlab.po1788
-rw-r--r--locale/az_AZ/gitlab.po1788
-rw-r--r--locale/ba_RU/gitlab.po1785
-rw-r--r--locale/bg/gitlab.po1788
-rw-r--r--locale/bn_BD/gitlab.po1788
-rw-r--r--locale/bn_IN/gitlab.po1788
-rw-r--r--locale/bs_BA/gitlab.po1791
-rw-r--r--locale/ca_ES/gitlab.po1788
-rw-r--r--locale/cs_CZ/gitlab.po1794
-rw-r--r--locale/cy_GB/gitlab.po1800
-rw-r--r--locale/da_DK/gitlab.po1788
-rw-r--r--locale/de/gitlab.po1856
-rw-r--r--locale/el_GR/gitlab.po1788
-rw-r--r--locale/eo/gitlab.po1788
-rw-r--r--locale/es/gitlab.po1898
-rw-r--r--locale/et_EE/gitlab.po1788
-rw-r--r--locale/fa_IR/gitlab.po1788
-rw-r--r--locale/fi_FI/gitlab.po1788
-rw-r--r--locale/fil_PH/gitlab.po1788
-rw-r--r--locale/fr/gitlab.po1848
-rw-r--r--locale/gitlab.pot2354
-rw-r--r--locale/gl_ES/gitlab.po1788
-rw-r--r--locale/he_IL/gitlab.po1794
-rw-r--r--locale/hi_IN/gitlab.po1788
-rw-r--r--locale/hr_HR/gitlab.po1791
-rw-r--r--locale/hu_HU/gitlab.po1788
-rw-r--r--locale/hy_AM/gitlab.po35264
-rw-r--r--locale/id_ID/gitlab.po1785
-rw-r--r--locale/ig_NG/gitlab.po1785
-rw-r--r--locale/is_IS/gitlab.po1788
-rw-r--r--locale/it/gitlab.po1792
-rw-r--r--locale/ja/gitlab.po2347
-rw-r--r--locale/ka_GE/gitlab.po1788
-rw-r--r--locale/kab/gitlab.po1788
-rw-r--r--locale/ko/gitlab.po1841
-rw-r--r--locale/ku_TR/gitlab.po1788
-rw-r--r--locale/ky_KG/gitlab.po1788
-rw-r--r--locale/lt_LT/gitlab.po1794
-rw-r--r--locale/mk_MK/gitlab.po1788
-rw-r--r--locale/mn_MN/gitlab.po1788
-rw-r--r--locale/nb_NO/gitlab.po1844
-rw-r--r--locale/nl_NL/gitlab.po1790
-rw-r--r--locale/pa_IN/gitlab.po1788
-rw-r--r--locale/pl_PL/gitlab.po1796
-rw-r--r--locale/pt_BR/gitlab.po1856
-rw-r--r--locale/pt_PT/gitlab.po1804
-rw-r--r--locale/ro_RO/gitlab.po1791
-rw-r--r--locale/ru/gitlab.po1922
-rw-r--r--locale/si_LK/gitlab.po1788
-rw-r--r--locale/sk_SK/gitlab.po1794
-rw-r--r--locale/sl_SI/gitlab.po1794
-rw-r--r--locale/sq_AL/gitlab.po1788
-rw-r--r--locale/sr_CS/gitlab.po1791
-rw-r--r--locale/sr_SP/gitlab.po1791
-rw-r--r--locale/sv_SE/gitlab.po1788
-rw-r--r--locale/sw_KE/gitlab.po1788
-rw-r--r--locale/tr_TR/gitlab.po1816
-rw-r--r--locale/uk/gitlab.po1934
-rw-r--r--locale/ur_PK/gitlab.po1788
-rw-r--r--locale/uz_UZ/gitlab.po1788
-rw-r--r--locale/vi_VN/gitlab.po1785
-rw-r--r--locale/zh_CN/gitlab.po1991
-rw-r--r--locale/zh_HK/gitlab.po1791
-rw-r--r--locale/zh_TW/gitlab.po1793
-rw-r--r--package.json55
-rw-r--r--qa/Dockerfile4
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/README.md11
-rw-r--r--qa/Rakefile2
-rwxr-xr-xqa/bin/qa1
-rwxr-xr-xqa/bin/rubymine1
-rw-r--r--qa/qa.rb1
-rw-r--r--qa/qa/fixtures/auto_devops_rack/Gemfile2
-rw-r--r--qa/qa/fixtures/auto_devops_rack/Rakefile2
-rw-r--r--qa/qa/fixtures/auto_devops_rack/config.ru2
-rw-r--r--qa/qa/flow/project.rb10
-rw-r--r--qa/qa/flow/sign_up.rb9
-rw-r--r--qa/qa/page/admin/overview/users/index.rb2
-rw-r--r--qa/qa/page/component/issue_board/show.rb2
-rw-r--r--qa/qa/page/component/note.rb6
-rw-r--r--qa/qa/page/issuable/new.rb11
-rw-r--r--qa/qa/page/main/menu.rb6
-rw-r--r--qa/qa/page/merge_request/show.rb44
-rw-r--r--qa/qa/page/page_concern.rb2
-rw-r--r--qa/qa/page/project/commit/show.rb4
-rw-r--r--qa/qa/page/project/members.rb24
-rw-r--r--qa/qa/page/project/web_ide/edit.rb54
-rw-r--r--qa/qa/resource/ci_variable.rb10
-rw-r--r--qa/qa/resource/issue.rb5
-rw-r--r--qa/qa/resource/members.rb13
-rw-r--r--qa/qa/resource/merge_request.rb8
-rw-r--r--qa/qa/resource/personal_access_token.rb2
-rw-r--r--qa/qa/resource/project.rb8
-rw-r--r--qa/qa/resource/repository/wiki_push.rb5
-rw-r--r--qa/qa/resource/ssh_key.rb2
-rw-r--r--qa/qa/runtime/env.rb4
-rw-r--r--qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb84
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb12
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb65
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb43
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb2
-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/jira/jira_basic_integration_spec.rb25
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb47
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb61
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb70
-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/web_ide/open_web_ide_from_diff_tab_spec.rb80
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb148
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb119
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb2
-rw-r--r--qa/qa/specs/runner.rb2
-rw-r--r--qa/qa/tools/revoke_all_personal_access_tokens.rb2
-rw-r--r--qa/spec/specs/runner_spec.rb28
-rw-r--r--qa/spec/support/matchers/have_assignee.rb15
-rw-r--r--qa/spec/support/matchers/have_child_pipeline.rb15
-rw-r--r--qa/spec/support/matchers/have_content.rb15
-rw-r--r--qa/spec/support/matchers/have_design.rb15
-rw-r--r--qa/spec/support/matchers/have_element.rb15
-rw-r--r--qa/spec/support/matchers/have_file.rb15
-rw-r--r--qa/spec/support/matchers/have_file_content.rb15
-rw-r--r--qa/spec/support/matchers/have_issue.rb15
-rw-r--r--qa/spec/support/matchers/have_job.rb15
-rw-r--r--qa/spec/support/matchers/have_matcher.rb29
-rw-r--r--qa/spec/support/matchers/have_package.rb15
-rw-r--r--qa/spec/support/matchers/have_pipeline.rb15
-rw-r--r--qa/spec/support/matchers/have_related_issue_item.rb15
-rw-r--r--qa/spec/support/matchers/have_snippet_description.rb15
-rw-r--r--rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb2
-rw-r--r--rubocop/cop/gitlab/finder_with_find_by.rb2
-rw-r--r--rubocop/cop/gitlab/httparty.rb4
-rw-r--r--rubocop/cop/gitlab/json.rb4
-rw-r--r--rubocop/cop/gitlab/keys-first-and-values-first.rb2
-rw-r--r--rubocop/cop/gitlab/module_with_instance_variables.rb4
-rw-r--r--rubocop/cop/gitlab/namespaced_class.rb39
-rw-r--r--rubocop/cop/gitlab/predicate_memoization.rb6
-rw-r--r--rubocop/cop/migration/add_concurrent_foreign_key.rb2
-rw-r--r--rubocop/cop/migration/add_concurrent_index.rb2
-rw-r--r--rubocop/cop/migration/add_index.rb2
-rw-r--r--rubocop/cop/migration/add_limit_to_text_columns.rb31
-rw-r--r--rubocop/cop/migration/add_timestamps.rb2
-rw-r--r--rubocop/cop/migration/datetime.rb2
-rw-r--r--rubocop/cop/migration/hash_index.rb2
-rw-r--r--rubocop/cop/migration/remove_column.rb2
-rw-r--r--rubocop/cop/migration/remove_concurrent_index.rb2
-rw-r--r--rubocop/cop/migration/remove_index.rb2
-rw-r--r--rubocop/cop/migration/safer_boolean_column.rb2
-rw-r--r--rubocop/cop/migration/timestamps.rb2
-rw-r--r--rubocop/cop/migration/update_column_in_batches.rb2
-rw-r--r--rubocop/cop/project_path_helper.rb2
-rw-r--r--rubocop/cop/rspec/factories_in_migration_specs.rb2
-rw-r--r--rubocop/migration_helpers.rb11
-rw-r--r--rubocop/qa_helpers.rb2
-rw-r--r--rubocop/rubocop-migrations.yml1
-rw-r--r--rubocop/rubocop-usage-data.yml2
-rwxr-xr-xscripts/api/get_job_id.rb4
-rwxr-xr-xscripts/flaky_examples/detect-new-flaky-examples1
-rwxr-xr-xscripts/flaky_examples/prune-old-flaky-examples1
-rw-r--r--scripts/frontend/extract_gettext_all.js4
-rwxr-xr-xscripts/gather-test-memory-data1
-rwxr-xr-xscripts/generate-gems-memory-metrics-static1
-rwxr-xr-xscripts/generate-gems-size-metrics-static1
-rwxr-xr-xscripts/generate-memory-metrics-on-boot1
-rwxr-xr-xscripts/generate-test-mapping1
-rwxr-xr-xscripts/gitaly-test-build1
-rwxr-xr-xscripts/gitaly-test-spawn1
-rw-r--r--scripts/gitaly_test.rb4
-rwxr-xr-xscripts/insert-rspec-profiling-data1
-rwxr-xr-xscripts/lint-doc.sh18
-rwxr-xr-xscripts/lint-rugged1
-rwxr-xr-xscripts/merge-html-reports1
-rwxr-xr-xscripts/merge-reports1
-rwxr-xr-xscripts/merge-simplecov1
-rwxr-xr-xscripts/no-ee-check2
-rwxr-xr-xscripts/pack-test-mapping1
-rw-r--r--scripts/prepare_build.sh3
-rwxr-xr-xscripts/review_apps/automated_cleanup.rb3
-rwxr-xr-xscripts/security-harness104
-rwxr-xr-xscripts/static-analysis1
-rwxr-xr-xscripts/sync-reports1
-rwxr-xr-xscripts/trigger-build103
-rwxr-xr-xscripts/unpack-test-mapping1
-rwxr-xr-xscripts/update-feature-categories1
-rwxr-xr-xscripts/used-feature-flags1
-rwxr-xr-xscripts/verify-tff-mapping1
-rw-r--r--spec/benchmarks/banzai_benchmark.rb124
-rw-r--r--spec/config/object_store_settings_spec.rb69
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb7
-rw-r--r--spec/controllers/admin/cohorts_controller_spec.rb34
-rw-r--r--spec/controllers/admin/runners_controller_spec.rb3
-rw-r--r--spec/controllers/admin/users_controller_spec.rb7
-rw-r--r--spec/controllers/chaos_controller_spec.rb19
-rw-r--r--spec/controllers/concerns/redis_tracking_spec.rb115
-rw-r--r--spec/controllers/concerns/spammable_actions_spec.rb99
-rw-r--r--spec/controllers/graphql_controller_spec.rb20
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb12
-rw-r--r--spec/controllers/groups_controller_spec.rb60
-rw-r--r--spec/controllers/help_controller_spec.rb110
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb24
-rw-r--r--spec/controllers/invites_controller_spec.rb43
-rw-r--r--spec/controllers/profiles/notifications_controller_spec.rb3
-rw-r--r--spec/controllers/profiles/preferences_controller_spec.rb35
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb4
-rw-r--r--spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb43
-rw-r--r--spec/controllers/projects/discussions_controller_spec.rb7
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb22
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb57
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb48
-rw-r--r--spec/controllers/projects/learn_gitlab_controller_spec.rb44
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb8
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb105
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb87
-rw-r--r--spec/controllers/projects/pipelines/tests_controller_spec.rb24
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb66
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb12
-rw-r--r--spec/controllers/projects/security/configuration_controller_spec.rb55
-rw-r--r--spec/controllers/projects/templates_controller_spec.rb3
-rw-r--r--spec/controllers/projects_controller_spec.rb61
-rw-r--r--spec/controllers/registrations/experience_levels_controller_spec.rb127
-rw-r--r--spec/controllers/registrations_controller_spec.rb12
-rw-r--r--spec/controllers/repositories/git_http_controller_spec.rb33
-rw-r--r--spec/controllers/search_controller_spec.rb392
-rw-r--r--spec/controllers/snippets_controller_spec.rb2
-rw-r--r--spec/db/schema_spec.rb2
-rw-r--r--spec/deprecation_toolkit_env.rb94
-rw-r--r--spec/experiments/application_experiment/cache_spec.rb12
-rw-r--r--spec/experiments/application_experiment_spec.rb147
-rw-r--r--spec/experiments/members/invite_email_experiment_spec.rb37
-rw-r--r--spec/experiments/new_project_readme_experiment_spec.rb93
-rw-r--r--spec/experiments/strategy/round_robin_spec.rb68
-rw-r--r--spec/factories/audit_events.rb15
-rw-r--r--spec/factories/ci/bridge.rb18
-rw-r--r--spec/factories/ci/builds.rb32
-rw-r--r--spec/factories/ci/daily_build_group_report_results.rb1
-rw-r--r--spec/factories/ci/job_artifacts.rb20
-rw-r--r--spec/factories/ci/pipeline_artifacts.rb33
-rw-r--r--spec/factories/ci/pipelines.rb24
-rw-r--r--spec/factories/ci/processable.rb26
-rw-r--r--spec/factories/ci/reports/codequality_degradations.rb98
-rw-r--r--spec/factories/ci/resource.rb2
-rw-r--r--spec/factories/design_management/design_at_version.rb2
-rw-r--r--spec/factories/diff_position.rb2
-rw-r--r--spec/factories/merge_request_diffs.rb6
-rw-r--r--spec/factories/merge_requests.rb45
-rw-r--r--spec/factories/notes.rb16
-rw-r--r--spec/factories/packages.rb54
-rw-r--r--spec/factories/packages/debian/component_file.rb39
-rw-r--r--spec/factories/packages/debian/distribution.rb2
-rw-r--r--spec/factories/packages/debian/group_component.rb9
-rw-r--r--spec/factories/packages/debian/project_component.rb9
-rw-r--r--spec/factories/packages/debian/publication.rb9
-rw-r--r--spec/factories/packages/package_file.rb16
-rw-r--r--spec/factories/packages/rubygems/metadata.rb9
-rw-r--r--spec/factories/pages_deployments.rb18
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/factories/sequences.rb2
-rw-r--r--spec/factories/services_data.rb3
-rw-r--r--spec/factories/token_with_ivs.rb9
-rw-r--r--spec/factories/u2f_registrations.rb2
-rw-r--r--spec/factories/usage_data.rb4
-rw-r--r--spec/features/admin/admin_cohorts_spec.rb33
-rw-r--r--spec/features/admin/admin_disables_git_access_protocol_spec.rb15
-rw-r--r--spec/features/admin/admin_groups_spec.rb2
-rw-r--r--spec/features/admin/admin_projects_spec.rb99
-rw-r--r--spec/features/admin/admin_search_settings_spec.rb27
-rw-r--r--spec/features/admin/admin_settings_spec.rb75
-rw-r--r--spec/features/admin/admin_users_spec.rb70
-rw-r--r--spec/features/admin/users/user_spec.rb4
-rw-r--r--spec/features/alert_management/alert_details_spec.rb2
-rw-r--r--spec/features/alerts_settings/user_views_alerts_settings_spec.rb3
-rw-r--r--spec/features/boards/boards_spec.rb8
-rw-r--r--spec/features/boards/sidebar_spec.rb44
-rw-r--r--spec/features/calendar_spec.rb2
-rw-r--r--spec/features/commit_spec.rb78
-rw-r--r--spec/features/commits_spec.rb3
-rw-r--r--spec/features/dashboard/activity_spec.rb20
-rw-r--r--spec/features/discussion_comments/issue_spec.rb2
-rw-r--r--spec/features/discussion_comments/merge_request_spec.rb1
-rw-r--r--spec/features/discussion_comments/snippets_spec.rb29
-rw-r--r--spec/features/groups/import_export/connect_instance_spec.rb16
-rw-r--r--spec/features/groups/navbar_spec.rb8
-rw-r--r--spec/features/groups/settings/packages_and_registries_spec.rb68
-rw-r--r--spec/features/groups/show_spec.rb1
-rw-r--r--spec/features/help_pages_spec.rb2
-rw-r--r--spec/features/ide/user_opens_merge_request_spec.rb2
-rw-r--r--spec/features/import/manifest_import_spec.rb2
-rw-r--r--spec/features/issuables/issuable_list_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb10
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb35
-rw-r--r--spec/features/issues/issue_state_spec.rb26
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb4
-rw-r--r--spec/features/issues/user_creates_issue_by_email_spec.rb4
-rw-r--r--spec/features/issues/user_resets_their_incoming_email_token_spec.rb24
-rw-r--r--spec/features/issues/user_toggles_subscription_spec.rb6
-rw-r--r--spec/features/labels_hierarchy_spec.rb5
-rw-r--r--spec/features/markdown/markdown_spec.rb27
-rw-r--r--spec/features/markdown/mermaid_spec.rb2
-rw-r--r--spec/features/merge_request/user_accepts_merge_request_spec.rb2
-rw-r--r--spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb37
-rw-r--r--spec/features/merge_request/user_edits_mr_spec.rb10
-rw-r--r--spec/features/merge_request/user_manages_subscription_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_merges_when_pipeline_succeeds_spec.rb8
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_reverts_merge_request_spec.rb43
-rw-r--r--spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb14
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb25
-rw-r--r--spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb234
-rw-r--r--spec/features/merge_request/user_suggests_changes_on_diff_spec.rb17
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb29
-rw-r--r--spec/features/merge_requests/user_filters_by_milestones_spec.rb2
-rw-r--r--spec/features/merge_requests/user_lists_merge_requests_spec.rb12
-rw-r--r--spec/features/profiles/user_edit_preferences_spec.rb11
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb32
-rw-r--r--spec/features/profiles/user_search_settings_spec.rb25
-rw-r--r--spec/features/profiles/user_visits_notifications_tab_spec.rb1
-rw-r--r--spec/features/profiles/user_visits_profile_preferences_page_spec.rb12
-rw-r--r--spec/features/profiles/user_visits_profile_spec.rb2
-rw-r--r--spec/features/projects/branches_spec.rb10
-rw-r--r--spec/features/projects/commit/cherry_pick_spec.rb160
-rw-r--r--spec/features/projects/commit/user_reverts_commit_spec.rb91
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb9
-rw-r--r--spec/features/projects/compare_spec.rb23
-rw-r--r--spec/features/projects/features_visibility_spec.rb6
-rw-r--r--spec/features/projects/files/dockerfile_dropdown_spec.rb8
-rw-r--r--spec/features/projects/files/gitignore_dropdown_spec.rb10
-rw-r--r--spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb7
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb10
-rw-r--r--spec/features/projects/fork_spec.rb39
-rw-r--r--spec/features/projects/graph_spec.rb6
-rw-r--r--spec/features/projects/issuable_templates_spec.rb4
-rw-r--r--spec/features/projects/jobs_spec.rb52
-rw-r--r--spec/features/projects/members/anonymous_user_sees_members_spec.rb26
-rw-r--r--spec/features/projects/members/group_members_spec.rb243
-rw-r--r--spec/features/projects/members/groups_with_access_list_spec.rb180
-rw-r--r--spec/features/projects/members/invite_group_spec.rb86
-rw-r--r--spec/features/projects/members/list_spec.rb222
-rw-r--r--spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb111
-rw-r--r--spec/features/projects/members/sorting_spec.rb204
-rw-r--r--spec/features/projects/members/tabs_spec.rb99
-rw-r--r--spec/features/projects/navbar_spec.rb19
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb185
-rw-r--r--spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb167
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb201
-rw-r--r--spec/features/projects/pages_lets_encrypt_spec.rb167
-rw-r--r--spec/features/projects/pages_spec.rb411
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb221
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb113
-rw-r--r--spec/features/projects/services/user_activates_slack_slash_command_spec.rb4
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/project_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb6
-rw-r--r--spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb6
-rw-r--r--spec/features/projects/settings/user_manages_project_members_spec.rb134
-rw-r--r--spec/features/projects/settings/visibility_settings_spec.rb4
-rw-r--r--spec/features/projects/show/user_manages_notifications_spec.rb1
-rw-r--r--spec/features/projects/show/user_sees_git_instructions_spec.rb7
-rw-r--r--spec/features/projects/terraform_spec.rb2
-rw-r--r--spec/features/projects/user_creates_project_spec.rb6
-rw-r--r--spec/features/projects/user_sees_user_popover_spec.rb2
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb7
-rw-r--r--spec/features/protected_branches_spec.rb6
-rw-r--r--spec/features/registrations/experience_level_spec.rb1
-rw-r--r--spec/features/search/user_searches_for_commits_spec.rb4
-rw-r--r--spec/features/search/user_searches_for_issues_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_merge_requests_spec.rb34
-rw-r--r--spec/features/search/user_searches_for_projects_spec.rb2
-rw-r--r--spec/features/task_lists_spec.rb8
-rw-r--r--spec/features/u2f_spec.rb10
-rw-r--r--spec/features/user_sees_revert_modal_spec.rb27
-rw-r--r--spec/features/users/login_spec.rb2
-rw-r--r--spec/features/users/overview_spec.rb126
-rw-r--r--spec/features/users/show_spec.rb52
-rw-r--r--spec/features/webauthn_spec.rb4
-rw-r--r--spec/features/whats_new_spec.rb35
-rw-r--r--spec/finders/autocomplete/users_finder_spec.rb5
-rw-r--r--spec/finders/ci/jobs_finder_spec.rb33
-rw-r--r--spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb99
-rw-r--r--spec/finders/container_repositories_finder_spec.rb30
-rw-r--r--spec/finders/deployments_finder_spec.rb207
-rw-r--r--spec/finders/license_template_finder_spec.rb43
-rw-r--r--spec/finders/merge_request/metrics_finder_spec.rb76
-rw-r--r--spec/finders/merge_requests/oldest_per_commit_finder_spec.rb46
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb1
-rw-r--r--spec/finders/packages/packages_finder_spec.rb1
-rw-r--r--spec/finders/repositories/commits_with_trailer_finder_spec.rb38
-rw-r--r--spec/finders/repositories/previous_tag_finder_spec.rb41
-rw-r--r--spec/finders/template_finder_spec.rb192
-rw-r--r--spec/finders/terraform/states_finder_spec.rb45
-rw-r--r--spec/finders/user_recent_events_finder_spec.rb120
-rw-r--r--spec/fixtures/api/schemas/entities/codequality_mr_diff_report.json21
-rw-r--r--spec/fixtures/api/schemas/entities/group_group_link.json40
-rw-r--r--spec/fixtures/api/schemas/entities/member.json4
-rw-r--r--spec/fixtures/api/schemas/entities/member_user.json1
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_composer_details.json12
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_composer_metadata.json21
-rw-r--r--spec/fixtures/api/schemas/graphql/packages/package_details.json38
-rw-r--r--spec/fixtures/api/schemas/group_group_links.json6
-rw-r--r--spec/fixtures/api/schemas/group_link/group_group_link.json16
-rw-r--r--spec/fixtures/api/schemas/group_link/group_group_links.json6
-rw-r--r--spec/fixtures/api/schemas/group_link/group_link.json38
-rw-r--r--spec/fixtures/api/schemas/group_link/project_group_link.json16
-rw-r--r--spec/fixtures/api/schemas/group_link/project_group_links.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/job.json4
-rw-r--r--spec/fixtures/markdown.md.erb22
-rw-r--r--spec/fixtures/packages/composer/package.json1
-rw-r--r--spec/fixtures/packages/debian/distribution/Packages2
-rw-r--r--spec/fixtures/packages/debian/distribution/Release1
-rw-r--r--spec/fixtures/packages/rubygems/package-0.0.1.gembin0 -> 4096 bytes
-rw-r--r--spec/fixtures/packages/rubygems/package.gemspec15
-rw-r--r--spec/fixtures/pipeline_artifacts/code_quality_mr_diff.json23
-rw-r--r--spec/fixtures/security_reports/master/gl-sast-report.json983
-rw-r--r--spec/fixtures/security_reports/master/gl-secret-detection-report.json33
-rw-r--r--spec/fixtures/whats_new/invalid.yml2
-rw-r--r--spec/fixtures/whats_new/valid.yml2
-rw-r--r--spec/frontend/__helpers__/emoji.js36
-rw-r--r--spec/frontend/__helpers__/fake_date.js49
-rw-r--r--spec/frontend/__helpers__/fake_date/fake_date.js60
-rw-r--r--spec/frontend/__helpers__/fake_date/fake_date_spec.js33
-rw-r--r--spec/frontend/__helpers__/fake_date/index.js2
-rw-r--r--spec/frontend/__helpers__/fake_date/jest.js41
-rw-r--r--spec/frontend/__helpers__/fake_date_spec.js37
-rw-r--r--spec/frontend/__helpers__/graphql_helpers.js14
-rw-r--r--spec/frontend/__helpers__/graphql_helpers_spec.js23
-rw-r--r--spec/frontend/__helpers__/init_vue_mr_page_helper.js4
-rw-r--r--spec/frontend/__helpers__/jest_execution_watcher.js12
-rw-r--r--spec/frontend/__helpers__/stub_component.js25
-rw-r--r--spec/frontend/__mocks__/@gitlab/ui.js4
-rw-r--r--spec/frontend/access_tokens/components/expires_at_field_spec.js3
-rw-r--r--spec/frontend/actioncable_connection_monitor_spec.js79
-rw-r--r--spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js8
-rw-r--r--spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js2
-rw-r--r--spec/frontend/add_context_commits_modal/store/actions_spec.js2
-rw-r--r--spec/frontend/add_context_commits_modal/store/mutations_spec.js2
-rw-r--r--spec/frontend/admin/statistics_panel/components/app_spec.js8
-rw-r--r--spec/frontend/admin/statistics_panel/store/actions_spec.js2
-rw-r--r--spec/frontend/admin/statistics_panel/store/getters_spec.js2
-rw-r--r--spec/frontend/admin/statistics_panel/store/mutations_spec.js2
-rw-r--r--spec/frontend/admin/users/components/actions/actions_spec.js98
-rw-r--r--spec/frontend/admin/users/components/user_actions_spec.js158
-rw-r--r--spec/frontend/admin/users/components/user_avatar_spec.js85
-rw-r--r--spec/frontend/admin/users/components/user_date_spec.js34
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js28
-rw-r--r--spec/frontend/admin/users/constants.js19
-rw-r--r--spec/frontend/admin/users/index_spec.js4
-rw-r--r--spec/frontend/admin/users/mock_data.js1
-rw-r--r--spec/frontend/alert_management/components/alert_details_spec.js338
-rw-r--r--spec/frontend/alert_management/components/alert_management_empty_state_spec.js2
-rw-r--r--spec/frontend/alert_management/components/alert_management_list_wrapper_spec.js2
-rw-r--r--spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js112
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js8
-rw-r--r--spec/frontend/alert_management/components/alert_metrics_spec.js62
-rw-r--r--spec/frontend/alert_management/components/alert_status_spec.js151
-rw-r--r--spec/frontend/alert_management/components/alert_summary_row_spec.js40
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js173
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_sidebar_spec.js64
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js130
-rw-r--r--spec/frontend/alert_management/components/system_notes/alert_management_system_note_spec.js40
-rw-r--r--spec/frontend/alerts_service_settings/components/__snapshots__/alerts_service_form_spec.js.snap9
-rw-r--r--spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js152
-rw-r--r--spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap98
-rw-r--r--spec/frontend/alerts_settings/alert_mapping_builder_spec.js93
-rw-r--r--spec/frontend/alerts_settings/alerts_integrations_list_spec.js118
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_spec.js351
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js379
-rw-r--r--spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap406
-rw-r--r--spec/frontend/alerts_settings/components/alert_mapping_builder_spec.js102
-rw-r--r--spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js118
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_form_spec.js385
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js379
-rw-r--r--spec/frontend/alerts_settings/components/mocks/apollo_mock.js (renamed from spec/frontend/alerts_settings/mocks/apollo_mock.js)0
-rw-r--r--spec/frontend/alerts_settings/components/mocks/integrations.json (renamed from spec/frontend/alerts_settings/mocks/integrations.json)0
-rw-r--r--spec/frontend/alerts_settings/components/util.js (renamed from spec/frontend/alerts_settings/util.js)0
-rw-r--r--spec/frontend/alerts_settings/mocks/alertFields.json123
-rw-r--r--spec/frontend/alerts_settings/utils/mapping_transformations_spec.js81
-rw-r--r--spec/frontend/analytics/components/activity_chart_spec.js2
-rw-r--r--spec/frontend/analytics/instance_statistics/components/app_spec.js4
-rw-r--r--spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js6
-rw-r--r--spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js15
-rw-r--r--spec/frontend/analytics/instance_statistics/components/users_chart_spec.js13
-rw-r--r--spec/frontend/analytics/shared/components/metric_card_spec.js2
-rw-r--r--spec/frontend/api/api_utils_spec.js4
-rw-r--r--spec/frontend/api_spec.js24
-rw-r--r--spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap55
-rw-r--r--spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js96
-rw-r--r--spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js8
-rw-r--r--spec/frontend/authentication/two_factor_auth/index_spec.js4
-rw-r--r--spec/frontend/avatar_helper_spec.js2
-rw-r--r--spec/frontend/awards_handler_spec.js20
-rw-r--r--spec/frontend/badges/components/badge_form_spec.js10
-rw-r--r--spec/frontend/badges/components/badge_list_row_spec.js2
-rw-r--r--spec/frontend/badges/components/badge_list_spec.js2
-rw-r--r--spec/frontend/badges/components/badge_settings_spec.js8
-rw-r--r--spec/frontend/badges/store/actions_spec.js4
-rw-r--r--spec/frontend/batch_comments/components/draft_note_spec.js23
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js19
-rw-r--r--spec/frontend/batch_comments/components/publish_dropdown_spec.js4
-rw-r--r--spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js2
-rw-r--r--spec/frontend/batch_comments/stores/modules/batch_comments/mutations_spec.js4
-rw-r--r--spec/frontend/behaviors/autosize_spec.js32
-rw-r--r--spec/frontend/behaviors/copy_as_gfm_spec.js2
-rw-r--r--spec/frontend/behaviors/gl_emoji_spec.js4
-rw-r--r--spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js2
-rw-r--r--spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap2
-rw-r--r--spec/frontend/blob/components/blob_content_error_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_content_spec.js4
-rw-r--r--spec/frontend/blob/components/blob_edit_header_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_header_default_actions_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_header_filepath_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_header_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_header_viewer_switcher_spec.js2
-rw-r--r--spec/frontend/blob/notebook/notebook_viever_spec.js4
-rw-r--r--spec/frontend/blob/pdf/pdf_viewer_spec.js2
-rw-r--r--spec/frontend/blob/pipeline_tour_success_modal_spec.js4
-rw-r--r--spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js2
-rw-r--r--spec/frontend/blob/utils_spec.js2
-rw-r--r--spec/frontend/blob/viewer/index_spec.js2
-rw-r--r--spec/frontend/blob_edit/edit_blob_spec.js2
-rw-r--r--spec/frontend/boards/board_list_deprecated_spec.js11
-rw-r--r--spec/frontend/boards/board_list_helper.js8
-rw-r--r--spec/frontend/boards/board_list_spec.js8
-rw-r--r--spec/frontend/boards/board_new_issue_deprecated_spec.js4
-rw-r--r--spec/frontend/boards/boards_store_spec.js6
-rw-r--r--spec/frontend/boards/boards_util_spec.js17
-rw-r--r--spec/frontend/boards/components/board_assignee_dropdown_spec.js380
-rw-r--r--spec/frontend/boards/components/board_card_layout_deprecated_spec.js158
-rw-r--r--spec/frontend/boards/components/board_card_layout_spec.js67
-rw-r--r--spec/frontend/boards/components/board_card_spec.js10
-rw-r--r--spec/frontend/boards/components/board_column_deprecated_spec.js16
-rw-r--r--spec/frontend/boards/components/board_column_spec.js13
-rw-r--r--spec/frontend/boards/components/board_configuration_options_spec.js15
-rw-r--r--spec/frontend/boards/components/board_content_spec.js6
-rw-r--r--spec/frontend/boards/components/board_form_spec.js55
-rw-r--r--spec/frontend/boards/components/board_list_header_deprecated_spec.js12
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js12
-rw-r--r--spec/frontend/boards/components/board_new_issue_spec.js2
-rw-r--r--spec/frontend/boards/components/board_settings_sidebar_spec.js10
-rw-r--r--spec/frontend/boards/components/boards_selector_deprecated_spec.js214
-rw-r--r--spec/frontend/boards/components/boards_selector_spec.js30
-rw-r--r--spec/frontend/boards/components/issue_time_estimate_spec.js2
-rw-r--r--spec/frontend/boards/components/sidebar/board_editable_item_spec.js2
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js4
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js6
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js6
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js50
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js8
-rw-r--r--spec/frontend/boards/components/sidebar/remove_issue_spec.js2
-rw-r--r--spec/frontend/boards/issue_card_deprecated_spec.js4
-rw-r--r--spec/frontend/boards/issue_card_inner_spec.js6
-rw-r--r--spec/frontend/boards/issue_spec.js2
-rw-r--r--spec/frontend/boards/list_spec.js3
-rw-r--r--spec/frontend/boards/mock_data.js6
-rw-r--r--spec/frontend/boards/project_select_deprecated_spec.js9
-rw-r--r--spec/frontend/boards/project_select_spec.js7
-rw-r--r--spec/frontend/boards/stores/actions_spec.js219
-rw-r--r--spec/frontend/boards/stores/getters_spec.js20
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js44
-rw-r--r--spec/frontend/branches/divergence_graph_spec.js2
-rw-r--r--spec/frontend/captcha/captcha_modal_spec.js171
-rw-r--r--spec/frontend/captcha/init_recaptcha_script_spec.js59
-rw-r--r--spec/frontend/ci_lint/components/ci_lint_spec.js2
-rw-r--r--spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js4
-rw-r--r--spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js4
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js6
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_table_spec.js4
-rw-r--r--spec/frontend/ci_variable_list/store/actions_spec.js8
-rw-r--r--spec/frontend/ci_variable_list/store/mutations_spec.js4
-rw-r--r--spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap8
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js6
-rw-r--r--spec/frontend/clusters/components/applications_spec.js68
-rw-r--r--spec/frontend/clusters/components/fluentd_output_settings_spec.js2
-rw-r--r--spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js2
-rw-r--r--spec/frontend/clusters/components/knative_domain_editor_spec.js2
-rw-r--r--spec/frontend/clusters/components/new_cluster_spec.js2
-rw-r--r--spec/frontend/clusters/components/remove_cluster_confirmation_spec.js4
-rw-r--r--spec/frontend/clusters/components/uninstall_application_button_spec.js2
-rw-r--r--spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js2
-rw-r--r--spec/frontend/clusters/components/update_application_confirmation_modal_spec.js2
-rw-r--r--spec/frontend/clusters/forms/components/integration_form_spec.js4
-rw-r--r--spec/frontend/clusters/services/application_state_machine_spec.js2
-rw-r--r--spec/frontend/clusters/services/crossplane_provider_stack_spec.js2
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js2
-rw-r--r--spec/frontend/clusters_list/components/ancestor_notice_spec.js2
-rw-r--r--spec/frontend/clusters_list/components/clusters_spec.js8
-rw-r--r--spec/frontend/clusters_list/components/node_error_help_text_spec.js2
-rw-r--r--spec/frontend/clusters_list/store/actions_spec.js10
-rw-r--r--spec/frontend/clusters_list/store/mutations_spec.js4
-rw-r--r--spec/frontend/code_navigation/components/app_spec.js4
-rw-r--r--spec/frontend/code_navigation/components/popover_spec.js2
-rw-r--r--spec/frontend/code_navigation/store/actions_spec.js2
-rw-r--r--spec/frontend/collapsed_sidebar_todo_spec.js16
-rw-r--r--spec/frontend/commit/commit_pipeline_status_component_spec.js10
-rw-r--r--spec/frontend/commit/pipelines/pipelines_spec.js4
-rw-r--r--spec/frontend/commits_spec.js4
-rw-r--r--spec/frontend/commons/nav/user_merge_requests_spec.js2
-rw-r--r--spec/frontend/confidential_merge_request/components/dropdown_spec.js2
-rw-r--r--spec/frontend/confidential_merge_request/components/project_form_group_spec.js2
-rw-r--r--spec/frontend/contributors/component/contributors_spec.js4
-rw-r--r--spec/frontend/contributors/store/actions_spec.js4
-rw-r--r--spec/frontend/contributors/store/mutations_spec.js4
-rw-r--r--spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js4
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js4
-rw-r--r--spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js10
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js2
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js4
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js4
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js4
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_submit_button_spec.js2
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js4
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js4
-rw-r--r--spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js4
-rw-r--r--spec/frontend/create_cluster/gke_cluster/stores/mutations_spec.js2
-rw-r--r--spec/frontend/create_cluster/init_create_cluster_spec.js2
-rw-r--r--spec/frontend/create_cluster/store/cluster_dropdown/actions_spec.js4
-rw-r--r--spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js2
-rw-r--r--spec/frontend/create_merge_request_dropdown_spec.js4
-rw-r--r--spec/frontend/cycle_analytics/limit_warning_component_spec.js4
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js6
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js4
-rw-r--r--spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js2
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js6
-rw-r--r--spec/frontend/deploy_freeze/store/actions_spec.js6
-rw-r--r--spec/frontend/deploy_freeze/store/mutations_spec.js4
-rw-r--r--spec/frontend/deploy_keys/components/action_btn_spec.js4
-rw-r--r--spec/frontend/deploy_keys/components/app_spec.js6
-rw-r--r--spec/frontend/deploy_keys/components/key_spec.js4
-rw-r--r--spec/frontend/deploy_keys/components/keys_panel_spec.js2
-rw-r--r--spec/frontend/design_management/components/delete_button_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js6
-rw-r--r--spec/frontend/design_management/components/design_notes/design_note_spec.js4
-rw-r--r--spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js4
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_presentation_spec.js4
-rw-r--r--spec/frontend/design_management/components/design_scaler_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_sidebar_spec.js8
-rw-r--r--spec/frontend/design_management/components/design_todo_button_spec.js4
-rw-r--r--spec/frontend/design_management/components/image_spec.js2
-rw-r--r--spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap10
-rw-r--r--spec/frontend/design_management/components/list/item_spec.js52
-rw-r--r--spec/frontend/design_management/components/toolbar/index_spec.js4
-rw-r--r--spec/frontend/design_management/components/upload/button_spec.js2
-rw-r--r--spec/frontend/design_management/components/upload/design_version_dropdown_spec.js2
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js26
-rw-r--r--spec/frontend/design_management/pages/index_spec.js30
-rw-r--r--spec/frontend/design_management/router_spec.js2
-rw-r--r--spec/frontend/design_management/utils/cache_update_spec.js2
-rw-r--r--spec/frontend/design_management/utils/design_management_utils_spec.js4
-rw-r--r--spec/frontend/diffs/components/app_spec.js24
-rw-r--r--spec/frontend/diffs/components/collapsed_files_warning_spec.js4
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js2
-rw-r--r--spec/frontend/diffs/components/commit_widget_spec.js2
-rw-r--r--spec/frontend/diffs/components/compare_dropdown_layout_spec.js4
-rw-r--r--spec/frontend/diffs/components/compare_versions_spec.js4
-rw-r--r--spec/frontend/diffs/components/diff_comment_cell_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js14
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js8
-rw-r--r--spec/frontend/diffs/components/diff_expansion_cell_spec.js8
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js304
-rw-r--r--spec/frontend/diffs/components/diff_file_row_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_file_spec.js78
-rw-r--r--spec/frontend/diffs/components/diff_line_note_form_spec.js5
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js6
-rw-r--r--spec/frontend/diffs/components/diff_row_utils_spec.js11
-rw-r--r--spec/frontend/diffs/components/diff_stats_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_view_spec.js14
-rw-r--r--spec/frontend/diffs/components/image_diff_overlay_spec.js2
-rw-r--r--spec/frontend/diffs/components/inline_diff_table_row_spec.js8
-rw-r--r--spec/frontend/diffs/components/inline_diff_view_spec.js8
-rw-r--r--spec/frontend/diffs/components/no_changes_spec.js4
-rw-r--r--spec/frontend/diffs/components/parallel_diff_table_row_spec.js10
-rw-r--r--spec/frontend/diffs/components/parallel_diff_view_spec.js6
-rw-r--r--spec/frontend/diffs/components/settings_dropdown_spec.js2
-rw-r--r--spec/frontend/diffs/components/tree_list_spec.js2
-rw-r--r--spec/frontend/diffs/store/actions_spec.js8
-rw-r--r--spec/frontend/diffs/store/getters_spec.js68
-rw-r--r--spec/frontend/diffs/store/getters_versions_dropdowns_spec.js4
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js6
-rw-r--r--spec/frontend/diffs/store/utils_spec.js4
-rw-r--r--spec/frontend/diffs/utils/diff_file_spec.js13
-rw-r--r--spec/frontend/diffs/utils/file_reviews_spec.js48
-rw-r--r--spec/frontend/diffs/utils/preferences_spec.js5
-rw-r--r--spec/frontend/diffs/utils/suggestions_spec.js15
-rw-r--r--spec/frontend/dirty_submit/dirty_submit_factory_spec.js2
-rw-r--r--spec/frontend/droplab/drop_down_spec.js2
-rw-r--r--spec/frontend/droplab/hook_spec.js2
-rw-r--r--spec/frontend/droplab/plugins/ajax_filter_spec.js2
-rw-r--r--spec/frontend/droplab/plugins/ajax_spec.js2
-rw-r--r--spec/frontend/dropzone_input_spec.js4
-rw-r--r--spec/frontend/editor/editor_ci_schema_ext_spec.js2
-rw-r--r--spec/frontend/editor/editor_lite_spec.js298
-rw-r--r--spec/frontend/emoji/emoji_spec.js476
-rw-r--r--spec/frontend/emoji/index_spec.js623
-rw-r--r--spec/frontend/environment.js13
-rw-r--r--spec/frontend/environments/canary_ingress_spec.js4
-rw-r--r--spec/frontend/environments/canary_update_modal_spec.js2
-rw-r--r--spec/frontend/environments/confirm_rollback_modal_spec.js2
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js2
-rw-r--r--spec/frontend/environments/enable_review_app_modal_spec.js2
-rw-r--r--spec/frontend/environments/environment_actions_spec.js4
-rw-r--r--spec/frontend/environments/environment_item_spec.js4
-rw-r--r--spec/frontend/environments/environment_monitoring_spec.js2
-rw-r--r--spec/frontend/environments/environment_pin_spec.js4
-rw-r--r--spec/frontend/environments/environment_rollback_spec.js4
-rw-r--r--spec/frontend/environments/environment_stop_spec.js4
-rw-r--r--spec/frontend/environments/environment_table_spec.js4
-rw-r--r--spec/frontend/environments/environments_app_spec.js4
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js14
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_actions_spec.js2
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js10
-rw-r--r--spec/frontend/error_tracking/components/stacktrace_entry_spec.js2
-rw-r--r--spec/frontend/error_tracking/store/actions_spec.js4
-rw-r--r--spec/frontend/error_tracking/store/details/actions_spec.js4
-rw-r--r--spec/frontend/error_tracking/store/list/actions_spec.js6
-rw-r--r--spec/frontend/error_tracking/store/list/mutation_spec.js2
-rw-r--r--spec/frontend/error_tracking_settings/components/app_spec.js2
-rw-r--r--spec/frontend/error_tracking_settings/components/error_tracking_form_spec.js4
-rw-r--r--spec/frontend/error_tracking_settings/components/project_dropdown_spec.js4
-rw-r--r--spec/frontend/error_tracking_settings/store/actions_spec.js8
-rw-r--r--spec/frontend/error_tracking_settings/store/mutation_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/edit_feature_flag_spec.js19
-rw-r--r--spec/frontend/feature_flags/components/environments_dropdown_spec.js6
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_spec.js12
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_tab_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_table_spec.js4
-rw-r--r--spec/frontend/feature_flags/components/form_spec.js47
-rw-r--r--spec/frontend/feature_flags/components/new_environments_dropdown_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/new_feature_flag_spec.js16
-rw-r--r--spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js4
-rw-r--r--spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js4
-rw-r--r--spec/frontend/feature_flags/components/strategies/users_with_id_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategy_parameters_spec.js10
-rw-r--r--spec/frontend/feature_flags/components/strategy_spec.js12
-rw-r--r--spec/frontend/feature_flags/components/user_lists_table_spec.js2
-rw-r--r--spec/frontend/feature_flags/store/edit/actions_spec.js12
-rw-r--r--spec/frontend/feature_flags/store/edit/mutations_spec.js4
-rw-r--r--spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js2
-rw-r--r--spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js2
-rw-r--r--spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js4
-rw-r--r--spec/frontend/feature_flags/store/helpers_spec.js14
-rw-r--r--spec/frontend/feature_flags/store/index/actions_spec.js4
-rw-r--r--spec/frontend/feature_flags/store/index/mutations_spec.js6
-rw-r--r--spec/frontend/feature_flags/store/new/actions_spec.js16
-rw-r--r--spec/frontend/feature_flags/store/new/mutations_spec.js4
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_helper_spec.js70
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_options_spec.js22
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_popover_spec.js80
-rw-r--r--spec/frontend/feature_highlight/feature_highlight_spec.js120
-rw-r--r--spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js2
-rw-r--r--spec/frontend/filtered_search/dropdown_user_spec.js3
-rw-r--r--spec/frontend/filtered_search/filtered_search_manager_spec.js12
-rw-r--r--spec/frontend/filtered_search/filtered_search_tokenizer_spec.js2
-rw-r--r--spec/frontend/filtered_search/recent_searches_root_spec.js49
-rw-r--r--spec/frontend/filtered_search/visual_token_value_spec.js4
-rw-r--r--spec/frontend/fixtures/api_merge_requests.rb19
-rw-r--r--spec/frontend/fixtures/merge_requests.rb1
-rw-r--r--spec/frontend/fixtures/merge_requests_diffs.rb2
-rw-r--r--spec/frontend/fixtures/pipelines.rb2
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js39
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_item_spec.js2
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_spec.js2
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_search_input_spec.js62
-rw-r--r--spec/frontend/frequent_items/store/actions_spec.js6
-rw-r--r--spec/frontend/frequent_items/store/getters_spec.js2
-rw-r--r--spec/frontend/frequent_items/store/mutations_spec.js4
-rw-r--r--spec/frontend/frequent_items/utils_spec.js2
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js128
-rw-r--r--spec/frontend/gl_form_spec.js2
-rw-r--r--spec/frontend/gpg_badges_spec.js2
-rw-r--r--spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap6
-rw-r--r--spec/frontend/grafana_integration/components/grafana_integration_spec.js4
-rw-r--r--spec/frontend/group_settings/components/shared_runners_form_spec.js2
-rw-r--r--spec/frontend/groups/components/app_spec.js12
-rw-r--r--spec/frontend/groups/components/group_folder_spec.js2
-rw-r--r--spec/frontend/groups/components/group_item_spec.js6
-rw-r--r--spec/frontend/groups/components/groups_spec.js6
-rw-r--r--spec/frontend/groups/components/invite_members_banner_spec.js4
-rw-r--r--spec/frontend/groups/components/item_actions_spec.js16
-rw-r--r--spec/frontend/groups/components/item_caret_spec.js2
-rw-r--r--spec/frontend/groups/components/item_stats_value_spec.js2
-rw-r--r--spec/frontend/groups/components/item_type_icon_spec.js2
-rw-r--r--spec/frontend/groups/members/components/app_spec.js95
-rw-r--r--spec/frontend/groups/members/index_spec.js113
-rw-r--r--spec/frontend/groups/members/mock_data.js33
-rw-r--r--spec/frontend/groups/members/utils_spec.js45
-rw-r--r--spec/frontend/groups/service/groups_service_spec.js2
-rw-r--r--spec/frontend/ide/commit_icon_spec.js2
-rw-r--r--spec/frontend/ide/components/activity_bar_spec.js21
-rw-r--r--spec/frontend/ide/components/branches/item_spec.js6
-rw-r--r--spec/frontend/ide/components/branches/search_list_spec.js6
-rw-r--r--spec/frontend/ide/components/commit_sidebar/actions_spec.js27
-rw-r--r--spec/frontend/ide/components/commit_sidebar/editor_header_spec.js4
-rw-r--r--spec/frontend/ide/components/commit_sidebar/empty_state_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js395
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_item_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/list_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/new_merge_request_option_spec.js11
-rw-r--r--spec/frontend/ide/components/commit_sidebar/radio_group_spec.js2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/success_message_spec.js2
-rw-r--r--spec/frontend/ide/components/error_message_spec.js2
-rw-r--r--spec/frontend/ide/components/file_row_extra_spec.js2
-rw-r--r--spec/frontend/ide/components/file_templates/bar_spec.js2
-rw-r--r--spec/frontend/ide/components/file_templates/dropdown_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_file_row_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_review_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_side_bar_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_sidebar_nav_spec.js5
-rw-r--r--spec/frontend/ide/components/ide_spec.js60
-rw-r--r--spec/frontend/ide/components/ide_status_bar_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_status_mr_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_tree_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/detail/scroll_button_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/list_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/stage_spec.js4
-rw-r--r--spec/frontend/ide/components/merge_requests/item_spec.js6
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js4
-rw-r--r--spec/frontend/ide/components/nav_dropdown_spec.js4
-rw-r--r--spec/frontend/ide/components/new_dropdown/index_spec.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/modal_spec.js4
-rw-r--r--spec/frontend/ide/components/panes/collapsible_sidebar_spec.js4
-rw-r--r--spec/frontend/ide/components/panes/right_spec.js6
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js6
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js2
-rw-r--r--spec/frontend/ide/components/preview/navigator_spec.js4
-rw-r--r--spec/frontend/ide/components/repo_commit_section_spec.js6
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js16
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js2
-rw-r--r--spec/frontend/ide/components/repo_tabs_spec.js4
-rw-r--r--spec/frontend/ide/components/resizable_panel_spec.js4
-rw-r--r--spec/frontend/ide/components/terminal/empty_state_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/session_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/terminal_controls_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/terminal_spec.js4
-rw-r--r--spec/frontend/ide/components/terminal/view_spec.js4
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js4
-rw-r--r--spec/frontend/ide/helpers.js2
-rw-r--r--spec/frontend/ide/lib/create_diff_spec.js2
-rw-r--r--spec/frontend/ide/lib/create_file_diff_spec.js2
-rw-r--r--spec/frontend/ide/lib/decorations/controller_spec.js6
-rw-r--r--spec/frontend/ide/lib/diff/controller_spec.js2
-rw-r--r--spec/frontend/ide/lib/editor_spec.js5
-rw-r--r--spec/frontend/ide/lib/languages/hcl_spec.js2
-rw-r--r--spec/frontend/ide/lib/languages/vue_spec.js2
-rw-r--r--spec/frontend/ide/services/index_spec.js4
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js10
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js111
-rw-r--r--spec/frontend/ide/stores/actions/project_spec.js8
-rw-r--r--spec/frontend/ide/stores/actions/tree_spec.js8
-rw-r--r--spec/frontend/ide/stores/actions_spec.js8
-rw-r--r--spec/frontend/ide/stores/getters_spec.js7
-rw-r--r--spec/frontend/ide/stores/modules/branches/actions_spec.js6
-rw-r--r--spec/frontend/ide/stores/modules/branches/mutations_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/clientside/actions_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/commit/actions_spec.js31
-rw-r--r--spec/frontend/ide/stores/modules/commit/getters_spec.js11
-rw-r--r--spec/frontend/ide/stores/modules/commit/mutations_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/editor/actions_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/editor/getters_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/editor/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/file_templates/actions_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/file_templates/getters_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/file_templates/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/merge_requests/actions_spec.js6
-rw-r--r--spec/frontend/ide/stores/modules/merge_requests/mutations_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/pane/mutations_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/actions_spec.js8
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/router/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js6
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js4
-rw-r--r--spec/frontend/ide/stores/modules/terminal/actions/setup_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/messages_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/terminal_sync/mutations_spec.js2
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js2
-rw-r--r--spec/frontend/ide/stores/plugins/terminal_spec.js2
-rw-r--r--spec/frontend/ide/stores/plugins/terminal_sync_spec.js8
-rw-r--r--spec/frontend/ide/stores/utils_spec.js2
-rw-r--r--spec/frontend/image_diff/image_badge_spec.js2
-rw-r--r--spec/frontend/image_diff/image_diff_spec.js2
-rw-r--r--spec/frontend/image_diff/init_discussion_tab_spec.js2
-rw-r--r--spec/frontend/image_diff/replaced_image_diff_spec.js4
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_row_spec.js6
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js167
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js137
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js4
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js276
-rw-r--r--spec/frontend/import_entities/import_projects/components/bitbucket_status_table_spec.js4
-rw-r--r--spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js14
-rw-r--r--spec/frontend/import_entities/import_projects/components/provider_repo_table_row_spec.js12
-rw-r--r--spec/frontend/import_entities/import_projects/store/actions_spec.js12
-rw-r--r--spec/frontend/import_entities/import_projects/store/getters_spec.js2
-rw-r--r--spec/frontend/import_entities/import_projects/store/mutations_spec.js2
-rw-r--r--spec/frontend/import_entities/import_projects/utils_spec.js2
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js10
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/incidents_settings_tabs_spec.js.snap4
-rw-r--r--spec/frontend/incidents_settings/components/incidents_settings_service_spec.js6
-rw-r--r--spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js2
-rw-r--r--spec/frontend/incidents_settings/components/pagerduty_form_spec.js2
-rw-r--r--spec/frontend/integrations/edit/components/active_checkbox_spec.js5
-rw-r--r--spec/frontend/integrations/edit/components/confirmation_modal_spec.js5
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js2
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js169
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js86
-rw-r--r--spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js2
-rw-r--r--spec/frontend/integrations/edit/components/override_dropdown_spec.js7
-rw-r--r--spec/frontend/integrations/edit/components/trigger_fields_spec.js2
-rw-r--r--spec/frontend/integrations/edit/store/actions_spec.js37
-rw-r--r--spec/frontend/integrations/edit/store/getters_spec.js4
-rw-r--r--spec/frontend/integrations/edit/store/mutations_spec.js28
-rw-r--r--spec/frontend/integrations/edit/store/state_spec.js3
-rw-r--r--spec/frontend/integrations/integration_settings_form_spec.js81
-rw-r--r--spec/frontend/invite_member/components/invite_member_modal_spec.js4
-rw-r--r--spec/frontend/invite_member/components/invite_member_trigger_spec.js2
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js2
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js2
-rw-r--r--spec/frontend/invite_members/components/members_token_select_spec.js4
-rw-r--r--spec/frontend/issuable/components/issuable_by_email_spec.js164
-rw-r--r--spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/components/issue_token_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js6
-rw-r--r--spec/frontend/issuable_create/components/issuable_form_spec.js5
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js70
-rw-r--r--spec/frontend/issuable_list/components/issuable_list_root_spec.js4
-rw-r--r--spec/frontend/issuable_list/components/issuable_tabs_spec.js2
-rw-r--r--spec/frontend/issuable_show/components/issuable_body_spec.js11
-rw-r--r--spec/frontend/issuable_show/components/issuable_description_spec.js2
-rw-r--r--spec/frontend/issuable_show/components/issuable_edit_form_spec.js4
-rw-r--r--spec/frontend/issuable_show/components/issuable_header_spec.js61
-rw-r--r--spec/frontend/issuable_show/components/issuable_show_root_spec.js4
-rw-r--r--spec/frontend/issuable_show/components/issuable_title_spec.js2
-rw-r--r--spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js2
-rw-r--r--spec/frontend/issuable_spec.js42
-rw-r--r--spec/frontend/issuable_suggestions/components/item_spec.js4
-rw-r--r--spec/frontend/issue_show/components/app_spec.js14
-rw-r--r--spec/frontend/issue_show/components/description_spec.js2
-rw-r--r--spec/frontend/issue_show/components/fields/description_spec.js78
-rw-r--r--spec/frontend/issue_show/components/fields/description_template_spec.js6
-rw-r--r--spec/frontend/issue_show/components/fields/title_spec.js48
-rw-r--r--spec/frontend/issue_show/components/form_spec.js9
-rw-r--r--spec/frontend/issue_show/components/incidents/highlight_bar_spec.js2
-rw-r--r--spec/frontend/issue_show/components/incidents/incident_tabs_spec.js12
-rw-r--r--spec/frontend/issue_show/components/pinned_links_spec.js2
-rw-r--r--spec/frontend/issue_show/components/title_spec.js2
-rw-r--r--spec/frontend/issue_show/helpers.js9
-rw-r--r--spec/frontend/issue_show/issue_spec.js4
-rw-r--r--spec/frontend/issue_show/mock_data.js1
-rw-r--r--spec/frontend/issue_spec.js4
-rw-r--r--spec/frontend/issues_list/components/issuable_spec.js37
-rw-r--r--spec/frontend/issues_list/components/issuables_list_app_spec.js84
-rw-r--r--spec/frontend/jira_connect/api_spec.js5
-rw-r--r--spec/frontend/jira_connect/components/app_spec.js36
-rw-r--r--spec/frontend/jira_connect/components/groups_list_item_spec.js109
-rw-r--r--spec/frontend/jira_connect/components/groups_list_spec.js30
-rw-r--r--spec/frontend/jira_connect/index_spec.js56
-rw-r--r--spec/frontend/jira_connect/mock_data.js2
-rw-r--r--spec/frontend/jira_import/components/jira_import_form_spec.js81
-rw-r--r--spec/frontend/jira_import/mock_data.js2
-rw-r--r--spec/frontend/jira_import/utils/jira_import_utils_spec.js2
-rw-r--r--spec/frontend/jobs/components/artifacts_block_spec.js2
-rw-r--r--spec/frontend/jobs/components/erased_block_spec.js8
-rw-r--r--spec/frontend/jobs/components/job_app_spec.js13
-rw-r--r--spec/frontend/jobs/components/job_container_item_spec.js102
-rw-r--r--spec/frontend/jobs/components/job_sidebar_details_container_spec.js11
-rw-r--r--spec/frontend/jobs/components/job_sidebar_retry_button_spec.js2
-rw-r--r--spec/frontend/jobs/components/log/line_header_spec.js2
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js2
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js2
-rw-r--r--spec/frontend/jobs/components/sidebar_detail_row_spec.js72
-rw-r--r--spec/frontend/jobs/components/sidebar_spec.js6
-rw-r--r--spec/frontend/jobs/components/trigger_block_spec.js116
-rw-r--r--spec/frontend/jobs/components/unmet_prerequisites_block_spec.js2
-rw-r--r--spec/frontend/jobs/mixins/delayed_job_mixin_spec.js98
-rw-r--r--spec/frontend/jobs/store/actions_spec.js6
-rw-r--r--spec/frontend/jobs/store/mutations_spec.js4
-rw-r--r--spec/frontend/lazy_loader_spec.js2
-rw-r--r--spec/frontend/lib/utils/ajax_cache_spec.js2
-rw-r--r--spec/frontend/lib/utils/array_utility_spec.js32
-rw-r--r--spec/frontend/lib/utils/color_utils_spec.js17
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js8
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js345
-rw-r--r--spec/frontend/lib/utils/poll_spec.js2
-rw-r--r--spec/frontend/lib/utils/poll_until_complete_spec.js2
-rw-r--r--spec/frontend/lib/utils/unit_format/formatter_factory_spec.js21
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js55
-rw-r--r--spec/frontend/line_highlighter_spec.js2
-rw-r--r--spec/frontend/logs/components/environment_logs_spec.js2
-rw-r--r--spec/frontend/logs/components/log_advanced_filters_spec.js9
-rw-r--r--spec/frontend/logs/components/log_control_buttons_spec.js2
-rw-r--r--spec/frontend/logs/components/log_simple_filters_spec.js3
-rw-r--r--spec/frontend/logs/stores/actions_spec.js13
-rw-r--r--spec/frontend/logs/stores/mutations_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/leave_button_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/resend_invite_button_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/user_action_buttons_spec.js4
-rw-r--r--spec/frontend/members/components/app_spec.js95
-rw-r--r--spec/frontend/members/components/avatars/group_avatar_spec.js6
-rw-r--r--spec/frontend/members/components/avatars/invite_avatar_spec.js4
-rw-r--r--spec/frontend/members/components/avatars/user_avatar_spec.js6
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js2
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js4
-rw-r--r--spec/frontend/members/components/modals/leave_modal_spec.js4
-rw-r--r--spec/frontend/members/components/modals/remove_group_link_modal_spec.js4
-rw-r--r--spec/frontend/members/components/table/created_at_spec.js2
-rw-r--r--spec/frontend/members/components/table/expiration_datepicker_spec.js4
-rw-r--r--spec/frontend/members/components/table/expires_at_spec.js2
-rw-r--r--spec/frontend/members/components/table/member_action_buttons_spec.js10
-rw-r--r--spec/frontend/members/components/table/member_avatar_spec.js8
-rw-r--r--spec/frontend/members/components/table/member_source_spec.js2
-rw-r--r--spec/frontend/members/components/table/members_table_cell_spec.js24
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js25
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js11
-rw-r--r--spec/frontend/members/index_spec.js113
-rw-r--r--spec/frontend/members/mock_data.js6
-rw-r--r--spec/frontend/members/store/actions_spec.js20
-rw-r--r--spec/frontend/members/store/mutations_spec.js66
-rw-r--r--spec/frontend/members/utils_spec.js100
-rw-r--r--spec/frontend/merge_request/components/status_box_spec.js10
-rw-r--r--spec/frontend/merge_request_spec.js2
-rw-r--r--spec/frontend/merge_request_tabs_spec.js3
-rw-r--r--spec/frontend/milestones/milestone_combobox_spec.js8
-rw-r--r--spec/frontend/milestones/stores/actions_spec.js2
-rw-r--r--spec/frontend/milestones/stores/mutations_spec.js4
-rw-r--r--spec/frontend/mini_pipeline_graph_dropdown_spec.js2
-rw-r--r--spec/frontend/monitoring/alert_widget_spec.js4
-rw-r--r--spec/frontend/monitoring/components/alert_widget_form_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/anomaly_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/bar_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/column_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/gauge_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/heatmap_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/single_stat_spec.js13
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js13
-rw-r--r--spec/frontend/monitoring/components/create_dashboard_modal_spec.js2
-rw-r--r--spec/frontend/monitoring/components/dashboard_actions_menu_spec.js14
-rw-r--r--spec/frontend/monitoring/components/dashboard_header_spec.js14
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_builder_spec.js9
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js46
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js24
-rw-r--r--spec/frontend/monitoring/components/dashboard_template_spec.js2
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js6
-rw-r--r--spec/frontend/monitoring/components/dashboards_dropdown_spec.js4
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js2
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js8
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js2
-rw-r--r--spec/frontend/monitoring/components/embeds/metric_embed_spec.js2
-rw-r--r--spec/frontend/monitoring/components/empty_state_spec.js4
-rw-r--r--spec/frontend/monitoring/components/graph_group_spec.js2
-rw-r--r--spec/frontend/monitoring/components/links_section_spec.js4
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js4
-rw-r--r--spec/frontend/monitoring/components/variables/dropdown_field_spec.js2
-rw-r--r--spec/frontend/monitoring/components/variables/text_field_spec.js2
-rw-r--r--spec/frontend/monitoring/components/variables_section_spec.js4
-rw-r--r--spec/frontend/monitoring/csv_export_spec.js2
-rw-r--r--spec/frontend/monitoring/fixture_data.js6
-rw-r--r--spec/frontend/monitoring/graph_data.js2
-rw-r--r--spec/frontend/monitoring/mock_data.js2
-rw-r--r--spec/frontend/monitoring/pages/dashboard_page_spec.js4
-rw-r--r--spec/frontend/monitoring/pages/panel_new_page_spec.js7
-rw-r--r--spec/frontend/monitoring/requests/index_spec.js4
-rw-r--r--spec/frontend/monitoring/router_spec.js4
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js32
-rw-r--r--spec/frontend/monitoring/store/embed_group/mutations_spec.js4
-rw-r--r--spec/frontend/monitoring/store/getters_spec.js6
-rw-r--r--spec/frontend/monitoring/store/mutations_spec.js8
-rw-r--r--spec/frontend/monitoring/store/utils_spec.js4
-rw-r--r--spec/frontend/monitoring/store/variable_mapping_spec.js2
-rw-r--r--spec/frontend/monitoring/store_utils.js2
-rw-r--r--spec/frontend/monitoring/utils_spec.js6
-rw-r--r--spec/frontend/namespace_select_spec.js2
-rw-r--r--spec/frontend/notebook/cells/markdown_spec.js2
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js143
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js4
-rw-r--r--spec/frontend/notes/components/diff_with_note_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js8
-rw-r--r--spec/frontend/notes/components/discussion_filter_note_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_filter_spec.js4
-rw-r--r--spec/frontend/notes/components/discussion_navigator_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js27
-rw-r--r--spec/frontend/notes/components/discussion_resolve_button_spec.js2
-rw-r--r--spec/frontend/notes/components/multiline_comment_form_spec.js4
-rw-r--r--spec/frontend/notes/components/note_actions/reply_button_spec.js19
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js11
-rw-r--r--spec/frontend/notes/components/note_awards_list_spec.js4
-rw-r--r--spec/frontend/notes/components/note_body_spec.js56
-rw-r--r--spec/frontend/notes/components/note_form_spec.js32
-rw-r--r--spec/frontend/notes/components/note_header_spec.js11
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js8
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js19
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js12
-rw-r--r--spec/frontend/notes/components/sort_discussion_spec.js4
-rw-r--r--spec/frontend/notes/components/timeline_toggle_spec.js4
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js6
-rw-r--r--spec/frontend/notes/old_notes_spec.js6
-rw-r--r--spec/frontend/notes/stores/actions_spec.js84
-rw-r--r--spec/frontend/notes/stores/getters_spec.js2
-rw-r--r--spec/frontend/notes/stores/mutation_spec.js15
-rw-r--r--spec/frontend/notifications/components/custom_notifications_modal_spec.js267
-rw-r--r--spec/frontend/notifications/components/notifications_dropdown_spec.js274
-rw-r--r--spec/frontend/onboarding_issues/index_spec.js137
-rw-r--r--spec/frontend/operation_settings/components/metrics_settings_spec.js14
-rw-r--r--spec/frontend/operation_settings/store/mutations_spec.js2
-rw-r--r--spec/frontend/packages/details/components/additional_metadata_spec.js4
-rw-r--r--spec/frontend/packages/details/components/app_spec.js25
-rw-r--r--spec/frontend/packages/details/components/composer_installation_spec.js4
-rw-r--r--spec/frontend/packages/details/components/conan_installation_spec.js2
-rw-r--r--spec/frontend/packages/details/components/installations_commands_spec.js6
-rw-r--r--spec/frontend/packages/details/components/maven_installation_spec.js4
-rw-r--r--spec/frontend/packages/details/components/npm_installation_spec.js6
-rw-r--r--spec/frontend/packages/details/components/nuget_installation_spec.js6
-rw-r--r--spec/frontend/packages/details/components/package_files_spec.js4
-rw-r--r--spec/frontend/packages/details/components/package_history_spec.js8
-rw-r--r--spec/frontend/packages/details/components/package_title_spec.js4
-rw-r--r--spec/frontend/packages/details/components/pypi_installation_spec.js2
-rw-r--r--spec/frontend/packages/details/store/actions_spec.js2
-rw-r--r--spec/frontend/packages/details/store/getters_spec.js2
-rw-r--r--spec/frontend/packages/details/store/mutations_spec.js2
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap14
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap555
-rw-r--r--spec/frontend/packages/list/components/packages_filter_spec.js50
-rw-r--r--spec/frontend/packages/list/components/packages_list_app_spec.js65
-rw-r--r--spec/frontend/packages/list/components/packages_list_spec.js10
-rw-r--r--spec/frontend/packages/list/components/packages_search_spec.js107
-rw-r--r--spec/frontend/packages/list/components/packages_sort_spec.js90
-rw-r--r--spec/frontend/packages/list/components/packages_title_spec.js4
-rw-r--r--spec/frontend/packages/list/components/tokens/package_type_token_spec.js48
-rw-r--r--spec/frontend/packages/list/stores/actions_spec.js14
-rw-r--r--spec/frontend/packages/list/stores/mutations_spec.js13
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap10
-rw-r--r--spec/frontend/packages/shared/components/package_list_row_spec.js2
-rw-r--r--spec/frontend/packages/shared/components/packages_list_loader_spec.js4
-rw-r--r--spec/frontend/packages/shared/utils_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js309
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js153
-rw-r--r--spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js56
-rw-r--r--spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js20
-rw-r--r--spec/frontend/packages_and_registries/settings/group/mock_data.js48
-rw-r--r--spec/frontend/pager_spec.js4
-rw-r--r--spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js4
-rw-r--r--spec/frontend/pages/admin/users/components/delete_user_modal_spec.js2
-rw-r--r--spec/frontend/pages/admin/users/components/user_modal_manager_spec.js97
-rw-r--r--spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js4
-rw-r--r--spec/frontend/pages/dashboard/todos/index/todos_spec.js4
-rw-r--r--spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js4
-rw-r--r--spec/frontend/pages/labels/components/promote_label_modal_spec.js4
-rw-r--r--spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js4
-rw-r--r--spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js6
-rw-r--r--spec/frontend/pages/projects/edit/mount_search_settings_spec.js25
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_groups_list_item_spec.js7
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js11
-rw-r--r--spec/frontend/pages/projects/graphs/code_coverage_spec.js6
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap66
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap66
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js63
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js63
-rw-r--r--spec/frontend/pages/projects/merge_requests/edit/check_form_state_spec.js41
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js2
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js103
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js389
-rw-r--r--spec/frontend/performance_bar/components/detailed_metric_spec.js2
-rw-r--r--spec/frontend/persistent_user_callout_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_form_spec.js8
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js223
-rw-r--r--spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js88
-rw-r--r--spec/frontend/pipeline_editor/components/editor/text_editor_spec.js120
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js34
-rw-r--r--spec/frontend/pipeline_editor/components/header/validation_segment_spec.js120
-rw-r--r--spec/frontend/pipeline_editor/components/info/validation_segment_spec.js113
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js4
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_warnings_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js183
-rw-r--r--spec/frontend/pipeline_editor/components/text_editor_spec.js93
-rw-r--r--spec/frontend/pipeline_editor/components/ui/confirm_unsaved_changes_dialog_spec.js42
-rw-r--r--spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js4
-rw-r--r--spec/frontend/pipeline_editor/graphql/resolvers_spec.js6
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js3
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js425
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_home_spec.js78
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js129
-rw-r--r--spec/frontend/pipeline_new/utils/format_refs_spec.js2
-rw-r--r--spec/frontend/pipelines/blank_state_spec.js21
-rw-r--r--spec/frontend/pipelines/components/dag/dag_annotations_spec.js2
-rw-r--r--spec/frontend/pipelines/components/dag/dag_graph_spec.js4
-rw-r--r--spec/frontend/pipelines/components/dag/dag_spec.js6
-rw-r--r--spec/frontend/pipelines/components/dag/parsing_utils_spec.js2
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js2
-rw-r--r--spec/frontend/pipelines/empty_state_spec.js105
-rw-r--r--spec/frontend/pipelines/graph/action_component_spec.js2
-rw-r--r--spec/frontend/pipelines/graph/graph_component_legacy_spec.js12
-rw-r--r--spec/frontend/pipelines/graph/graph_component_spec.js16
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js6
-rw-r--r--spec/frontend/pipelines/graph/job_name_component_spec.js3
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js9
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_legacy_spec.js4
-rw-r--r--spec/frontend/pipelines/graph/linked_pipelines_column_spec.js113
-rw-r--r--spec/frontend/pipelines/graph/stage_column_component_spec.js4
-rw-r--r--spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap23
-rw-r--r--spec/frontend/pipelines/graph_shared/links_inner_spec.js197
-rw-r--r--spec/frontend/pipelines/graph_shared/links_layer_spec.js99
-rw-r--r--spec/frontend/pipelines/header_component_spec.js10
-rw-r--r--spec/frontend/pipelines/legacy_header_component_spec.js116
-rw-r--r--spec/frontend/pipelines/pipeline_graph/mock_data.js135
-rw-r--r--spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js8
-rw-r--r--spec/frontend/pipelines/pipeline_triggerer_spec.js2
-rw-r--r--spec/frontend/pipelines/pipeline_url_spec.js28
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js66
-rw-r--r--spec/frontend/pipelines/pipelines_artifacts_spec.js2
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js990
-rw-r--r--spec/frontend/pipelines/pipelines_table_row_spec.js4
-rw-r--r--spec/frontend/pipelines/shared/links_layer_spec.js99
-rw-r--r--spec/frontend/pipelines/stage_spec.js278
-rw-r--r--spec/frontend/pipelines/test_reports/stores/actions_spec.js7
-rw-r--r--spec/frontend/pipelines/test_reports/stores/getters_spec.js73
-rw-r--r--spec/frontend/pipelines/test_reports/stores/utils_spec.js16
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js37
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js2
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js44
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_table_spec.js2
-rw-r--r--spec/frontend/pipelines/time_ago_spec.js2
-rw-r--r--spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js2
-rw-r--r--spec/frontend/popovers/components/popovers_spec.js2
-rw-r--r--spec/frontend/profile/account/components/delete_account_modal_spec.js4
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js2
-rw-r--r--spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap67
-rw-r--r--spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap51
-rw-r--r--spec/frontend/profile/preferences/components/integration_view_spec.js10
-rw-r--r--spec/frontend/profile/preferences/components/profile_preferences_spec.js142
-rw-r--r--spec/frontend/profile/preferences/mock_data.js2
-rw-r--r--spec/frontend/project_find_file_spec.js2
-rw-r--r--spec/frontend/projects/commit/components/branches_dropdown_spec.js4
-rw-r--r--spec/frontend/projects/commit/components/form_modal_spec.js13
-rw-r--r--spec/frontend/projects/commit/components/form_trigger_spec.js2
-rw-r--r--spec/frontend/projects/commit/store/actions_spec.js6
-rw-r--r--spec/frontend/projects/commit/store/mutations_spec.js2
-rw-r--r--spec/frontend/projects/commit_box/info/load_branches_spec.js2
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js2
-rw-r--r--spec/frontend/projects/commits/store/actions_spec.js4
-rw-r--r--spec/frontend/projects/compare/components/app_spec.js116
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_spec.js92
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap4
-rw-r--r--spec/frontend/projects/components/shared/delete_button_spec.js2
-rw-r--r--spec/frontend/projects/experiment_new_project_creation/components/app_spec.js4
-rw-r--r--spec/frontend/projects/members/utils_spec.js14
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js168
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js94
-rw-r--r--spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js72
-rw-r--r--spec/frontend/projects/pipelines/charts/mock_data.js10
-rw-r--r--spec/frontend/projects/settings/access_dropdown_spec.js1
-rw-r--r--spec/frontend/projects/settings/components/shared_runners_toggle_spec.js2
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js236
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js190
-rw-r--r--spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js111
-rw-r--r--spec/frontend/prometheus_alerts/components/reset_key_spec.js4
-rw-r--r--spec/frontend/prometheus_metrics/custom_metrics_spec.js2
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js2
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js6
-rw-r--r--spec/frontend/ref/stores/actions_spec.js2
-rw-r--r--spec/frontend/ref/stores/mutations_spec.js6
-rw-r--r--spec/frontend/registry/explorer/components/delete_button_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/delete_image_spec.js152
-rw-r--r--spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js68
-rw-r--r--spec/frontend/registry/explorer/components/details_page/details_header_spec.js85
-rw-r--r--spec/frontend/registry/explorer/components/details_page/empty_state_spec.js54
-rw-r--r--spec/frontend/registry/explorer/components/details_page/empty_tags_state_spec.js43
-rw-r--r--spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/details_page/status_alert_spec.js57
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js10
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js32
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js8
-rw-r--r--spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js6
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js10
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js6
-rw-r--r--spec/frontend/registry/explorer/components/list_page/registry_header_spec.js4
-rw-r--r--spec/frontend/registry/explorer/mock_data.js6
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js160
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js122
-rw-r--r--spec/frontend/registry/settings/components/expiration_input_spec.js2
-rw-r--r--spec/frontend/registry/settings/components/expiration_run_text_spec.js2
-rw-r--r--spec/frontend/registry/settings/components/expiration_toggle_spec.js2
-rw-r--r--spec/frontend/registry/settings/components/registry_settings_app_spec.js4
-rw-r--r--spec/frontend/registry/settings/components/settings_form_spec.js6
-rw-r--r--spec/frontend/registry/settings/graphql/cache_updated_spec.js2
-rw-r--r--spec/frontend/related_merge_requests/components/related_merge_requests_spec.js2
-rw-r--r--spec/frontend/related_merge_requests/store/actions_spec.js2
-rw-r--r--spec/frontend/related_merge_requests/store/mutations_spec.js2
-rw-r--r--spec/frontend/releases/components/app_edit_new_spec.js8
-rw-r--r--spec/frontend/releases/components/app_index_spec.js10
-rw-r--r--spec/frontend/releases/components/app_show_spec.js6
-rw-r--r--spec/frontend/releases/components/asset_links_form_spec.js4
-rw-r--r--spec/frontend/releases/components/evidence_block_spec.js4
-rw-r--r--spec/frontend/releases/components/release_block_assets_spec.js4
-rw-r--r--spec/frontend/releases/components/release_block_footer_spec.js32
-rw-r--r--spec/frontend/releases/components/release_block_header_spec.js4
-rw-r--r--spec/frontend/releases/components/release_block_milestone_info_spec.js6
-rw-r--r--spec/frontend/releases/components/release_block_spec.js8
-rw-r--r--spec/frontend/releases/components/release_skeleton_loader_spec.js2
-rw-r--r--spec/frontend/releases/components/releases_pagination_graphql_spec.js6
-rw-r--r--spec/frontend/releases/components/releases_pagination_rest_spec.js6
-rw-r--r--spec/frontend/releases/components/releases_sort_spec.js2
-rw-r--r--spec/frontend/releases/components/tag_field_exsting_spec.js2
-rw-r--r--spec/frontend/releases/components/tag_field_new_spec.js4
-rw-r--r--spec/frontend/releases/components/tag_field_spec.js2
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js14
-rw-r--r--spec/frontend/releases/stores/modules/detail/mutations_spec.js6
-rw-r--r--spec/frontend/releases/stores/modules/list/actions_spec.js20
-rw-r--r--spec/frontend/releases/stores/modules/list/mutations_spec.js8
-rw-r--r--spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js2
-rw-r--r--spec/frontend/reports/accessibility_report/store/actions_spec.js4
-rw-r--r--spec/frontend/reports/accessibility_report/store/getters_spec.js2
-rw-r--r--spec/frontend/reports/accessibility_report/store/mutations_spec.js2
-rw-r--r--spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js7
-rw-r--r--spec/frontend/reports/codequality_report/mock_data.js50
-rw-r--r--spec/frontend/reports/codequality_report/store/actions_spec.js173
-rw-r--r--spec/frontend/reports/codequality_report/store/getters_spec.js2
-rw-r--r--spec/frontend/reports/codequality_report/store/mutations_spec.js16
-rw-r--r--spec/frontend/reports/codequality_report/store/utils/codequality_comparison_spec.js18
-rw-r--r--spec/frontend/reports/components/grouped_test_reports_app_spec.js9
-rw-r--r--spec/frontend/reports/components/modal_spec.js2
-rw-r--r--spec/frontend/reports/components/report_item_spec.js6
-rw-r--r--spec/frontend/reports/components/report_section_spec.js2
-rw-r--r--spec/frontend/reports/components/summary_row_spec.js4
-rw-r--r--spec/frontend/reports/components/test_issue_body_spec.js2
-rw-r--r--spec/frontend/reports/store/actions_spec.js4
-rw-r--r--spec/frontend/reports/store/mutations_spec.js4
-rw-r--r--spec/frontend/reports/store/utils_spec.js2
-rw-r--r--spec/frontend/repository/components/breadcrumbs_spec.js2
-rw-r--r--spec/frontend/repository/components/last_commit_spec.js98
-rw-r--r--spec/frontend/repository/components/preview/index_spec.js2
-rw-r--r--spec/frontend/repository/components/table/index_spec.js2
-rw-r--r--spec/frontend/repository/components/table/parent_row_spec.js2
-rw-r--r--spec/frontend/repository/components/table/row_spec.js2
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js2
-rw-r--r--spec/frontend/repository/utils/dom_spec.js2
-rw-r--r--spec/frontend/right_sidebar_spec.js2
-rw-r--r--spec/frontend/search/highlight_blob_search_result_spec.js3
-rw-r--r--spec/frontend/search/index_spec.js3
-rw-r--r--spec/frontend/search/mock_data.js22
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js4
-rw-r--r--spec/frontend/search/sidebar/components/confidentiality_filter_spec.js2
-rw-r--r--spec/frontend/search/sidebar/components/radio_filter_spec.js6
-rw-r--r--spec/frontend/search/sidebar/components/status_filter_spec.js4
-rw-r--r--spec/frontend/search/sort/components/app_spec.js168
-rw-r--r--spec/frontend/search/store/actions_spec.js6
-rw-r--r--spec/frontend/search/store/mutations_spec.js2
-rw-r--r--spec/frontend/search/topbar/components/app_spec.js113
-rw-r--r--spec/frontend/search/topbar/components/group_filter_spec.js2
-rw-r--r--spec/frontend/search/topbar/components/project_filter_spec.js4
-rw-r--r--spec/frontend/search/topbar/components/searchable_dropdown_spec.js4
-rw-r--r--spec/frontend/search_autocomplete_spec.js5
-rw-r--r--spec/frontend/search_settings/components/search_settings_spec.js100
-rw-r--r--spec/frontend/search_settings/index_spec.js37
-rw-r--r--spec/frontend/search_settings/mount_spec.js35
-rw-r--r--spec/frontend/search_spec.js23
-rw-r--r--spec/frontend/security_configuration/app_spec.js27
-rw-r--r--spec/frontend/security_configuration/configuration_table_spec.js48
-rw-r--r--spec/frontend/security_configuration/manage_sast_spec.js136
-rw-r--r--spec/frontend/security_configuration/upgrade_spec.js29
-rw-r--r--spec/frontend/self_monitor/components/self_monitor_form_spec.js2
-rw-r--r--spec/frontend/sentry/index_spec.js2
-rw-r--r--spec/frontend/sentry/sentry_config_spec.js2
-rw-r--r--spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js2
-rw-r--r--spec/frontend/serverless/components/empty_state_spec.js2
-rw-r--r--spec/frontend/serverless/components/environment_row_spec.js2
-rw-r--r--spec/frontend/serverless/components/function_details_spec.js2
-rw-r--r--spec/frontend/serverless/components/functions_spec.js8
-rw-r--r--spec/frontend/serverless/components/missing_prometheus_spec.js2
-rw-r--r--spec/frontend/serverless/components/url_spec.js2
-rw-r--r--spec/frontend/serverless/store/actions_spec.js2
-rw-r--r--spec/frontend/serverless/store/getters_spec.js2
-rw-r--r--spec/frontend/serverless/store/mutations_spec.js2
-rw-r--r--spec/frontend/serverless/survey_banner_spec.js2
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js2
-rw-r--r--spec/frontend/set_status_modal/user_availability_status_spec.js31
-rw-r--r--spec/frontend/set_status_modal/utils_spec.js15
-rw-r--r--spec/frontend/settings_panels_spec.js10
-rw-r--r--spec/frontend/sidebar/__snapshots__/todo_spec.js.snap2
-rw-r--r--spec/frontend/sidebar/assignee_title_spec.js2
-rw-r--r--spec/frontend/sidebar/assignees_realtime_spec.js4
-rw-r--r--spec/frontend/sidebar/assignees_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js32
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js26
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js6
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js120
-rw-r--r--spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js51
-rw-r--r--spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js4
-rw-r--r--spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js91
-rw-r--r--spec/frontend/sidebar/components/severity/severity_spec.js4
-rw-r--r--spec/frontend/sidebar/components/severity/sidebar_severity_spec.js8
-rw-r--r--spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js2
-rw-r--r--spec/frontend/sidebar/confidential/edit_form_buttons_spec.js4
-rw-r--r--spec/frontend/sidebar/confidential_issue_sidebar_spec.js6
-rw-r--r--spec/frontend/sidebar/lock/edit_form_buttons_spec.js6
-rw-r--r--spec/frontend/sidebar/lock/issuable_lock_form_spec.js6
-rw-r--r--spec/frontend/sidebar/reviewer_title_spec.js2
-rw-r--r--spec/frontend/sidebar/reviewers_spec.js9
-rw-r--r--spec/frontend/sidebar/sidebar_assignees_spec.js6
-rw-r--r--spec/frontend/sidebar/sidebar_move_issue_spec.js6
-rw-r--r--spec/frontend/sidebar/sidebar_subscriptions_spec.js2
-rw-r--r--spec/frontend/sidebar/subscriptions_spec.js25
-rw-r--r--spec/frontend/sidebar/todo_spec.js6
-rw-r--r--spec/frontend/sidebar/user_data_mock.js2
-rw-r--r--spec/frontend/snippets/components/edit_spec.js585
-rw-r--r--spec/frontend/snippets/components/embed_dropdown_spec.js4
-rw-r--r--spec/frontend/snippets/components/show_spec.js9
-rw-r--r--spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js2
-rw-r--r--spec/frontend/snippets/components/snippet_blob_edit_spec.js8
-rw-r--r--spec/frontend/snippets/components/snippet_blob_view_spec.js8
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js8
-rw-r--r--spec/frontend/snippets/components/snippet_title_spec.js2
-rw-r--r--spec/frontend/snippets/test_utils.js55
-rw-r--r--spec/frontend/snippets/utils/error_spec.js16
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js11
-rw-r--r--spec/frontend/static_site_editor/components/edit_drawer_spec.js3
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_controls_spec.js3
-rw-r--r--spec/frontend/static_site_editor/components/edit_meta_modal_spec.js8
-rw-r--r--spec/frontend/static_site_editor/components/front_matter_controls_spec.js2
-rw-r--r--spec/frontend/static_site_editor/components/submit_changes_error_spec.js2
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js2
-rw-r--r--spec/frontend/static_site_editor/pages/home_spec.js8
-rw-r--r--spec/frontend/static_site_editor/pages/success_spec.js4
-rw-r--r--spec/frontend/static_site_editor/services/front_matterify_spec.js3
-rw-r--r--spec/frontend/static_site_editor/services/parse_source_file_spec.js3
-rw-r--r--spec/frontend/task_list_spec.js2
-rw-r--r--spec/frontend/terraform/components/states_table_actions_spec.js181
-rw-r--r--spec/frontend/terraform/components/states_table_spec.js56
-rw-r--r--spec/frontend/terraform/components/terraform_list_spec.js41
-rw-r--r--spec/frontend/test_setup.js14
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js2
-rw-r--r--spec/frontend/tooltips/index_spec.js26
-rw-r--r--spec/frontend/user_lists/components/edit_user_list_spec.js8
-rw-r--r--spec/frontend/user_lists/components/new_user_list_spec.js6
-rw-r--r--spec/frontend/user_lists/components/user_list_spec.js10
-rw-r--r--spec/frontend/user_lists/store/edit/actions_spec.js6
-rw-r--r--spec/frontend/user_lists/store/edit/mutations_spec.js2
-rw-r--r--spec/frontend/user_lists/store/new/actions_spec.js6
-rw-r--r--spec/frontend/user_lists/store/new/mutations_spec.js2
-rw-r--r--spec/frontend/user_lists/store/show/actions_spec.js6
-rw-r--r--spec/frontend/user_lists/store/show/mutations_spec.js4
-rw-r--r--spec/frontend/user_popovers_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/artifacts_list_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js46
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap24
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js24
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js26
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js39
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js14
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js8
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js83
-rw-r--r--spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js4
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_details_spec.js361
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js112
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_metrics_spec.js62
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_status_spec.js166
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_summary_row_spec.js40
-rw-r--r--spec/frontend/vue_shared/alert_details/mocks/alerts.json (renamed from spec/frontend/alert_management/mocks/alerts.json)0
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_managment_sidebar_assignees_spec.js173
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js95
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js103
-rw-r--r--spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js40
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap28
-rw-r--r--spec/frontend/vue_shared/components/actions_button_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/changed_file_icon_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/ci_badge_link_spec.js40
-rw-r--r--spec/frontend/vue_shared/components/ci_icon_spec.js151
-rw-r--r--spec/frontend/vue_shared/components/clipboard_button_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/clone_dropdown_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/color_picker/color_picker_spec.js39
-rw-r--r--spec/frontend/vue_shared/components/commit_spec.js28
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/dismissible_alert_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/dismissible_container_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/dismissible_feedback_alert_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/editor_lite_spec.js11
-rw-r--r--spec/frontend/vue_shared/components/expand_button_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/file_finder/index_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/file_finder/item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/file_icon_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/file_tree_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/mutations_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap16
-rw-r--r--spec/frontend/vue_shared/components/gl_countdown_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/gl_modal_vuex_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/header_ci_component_spec.js118
-rw-r--r--spec/frontend/vue_shared/components/help_popover_spec.js65
-rw-r--r--spec/frontend/vue_shared/components/integration_help_text_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_assignees_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_milestone_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/markdown/field_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/markdown/field_view_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/memory_graph_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/modal_copy_button_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/multiselect_dropdown_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/navigation_tabs_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/notes/noteable_warning_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/notes/system_note_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/pagination_links_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/pikaday_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/registry/code_instruction_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/details_row_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/history_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/metadata_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/registry_search_spec.js105
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/resizable_chart_container_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/mock_data.js107
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js113
-rw-r--r--spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap43
-rw-r--r--spec/frontend/vue_shared/components/settings/settings_block_spec.js86
-rw-r--r--spec/frontend/vue_shared/components/sidebar/date_picker_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js42
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js42
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/smart_virtual_list_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/table_pagination_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/tabs/tabs_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/todo_button_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/toggle_button_spec.js96
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js2
-rw-r--r--spec/frontend/vue_shared/directives/tooltip_spec.js2
-rw-r--r--spec/frontend/vue_shared/directives/track_event_spec.js4
-rw-r--r--spec/frontend/vue_shared/security_reports/mock_data.js17
-rw-r--r--spec/frontend/vue_shared/security_reports/security_reports_app_spec.js374
-rw-r--r--spec/frontend/vue_shared/security_reports/store/getters_spec.js8
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js6
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js2
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js6
-rw-r--r--spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js2
-rw-r--r--spec/frontend/vue_shared/security_reports/utils_spec.js2
-rw-r--r--spec/frontend/vuex_shared/modules/modal/actions_spec.js2
-rw-r--r--spec/frontend/vuex_shared/modules/modal/mutations_spec.js2
-rw-r--r--spec/frontend/whats_new/components/app_spec.js2
-rw-r--r--spec/frontend/whats_new/store/actions_spec.js6
-rw-r--r--spec/frontend/whats_new/store/mutations_spec.js2
-rw-r--r--spec/frontend/whats_new/utils/get_drawer_body_height_spec.js2
-rw-r--r--spec/frontend/zen_mode_spec.js4
-rw-r--r--spec/frontend_integration/ide/helpers/ide_helper.js8
-rw-r--r--spec/frontend_integration/ide/helpers/start.js13
-rw-r--r--spec/frontend_integration/ide/ide_integration_spec.js6
-rw-r--r--spec/frontend_integration/ide/user_opens_file_spec.js2
-rw-r--r--spec/frontend_integration/ide/user_opens_ide_spec.js2
-rw-r--r--spec/frontend_integration/ide/user_opens_mr_spec.js60
-rw-r--r--spec/frontend_integration/test_helpers/factories/commit.js2
-rw-r--r--spec/frontend_integration/test_helpers/fixtures.js14
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/index.js6
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/404.js2
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/routes/projects.js18
-rw-r--r--spec/graphql/mutations/boards/lists/create_spec.rb78
-rw-r--r--spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb46
-rw-r--r--spec/graphql/mutations/merge_requests/update_spec.rb21
-rw-r--r--spec/graphql/mutations/security/ci_configuration/configure_sast_spec.rb120
-rw-r--r--spec/graphql/resolvers/base_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/board_list_issues_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/board_lists_resolver_spec.rb12
-rw-r--r--spec/graphql/resolvers/ci/config_resolver_spec.rb3
-rw-r--r--spec/graphql/resolvers/container_repositories_resolver_spec.rb28
-rw-r--r--spec/graphql/resolvers/group_labels_resolver_spec.rb96
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb12
-rw-r--r--spec/graphql/resolvers/labels_resolver_spec.rb96
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb62
-rw-r--r--spec/graphql/resolvers/package_details_resolver_spec.rb5
-rw-r--r--spec/graphql/resolvers/packages_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/release_milestones_resolver_spec.rb9
-rw-r--r--spec/graphql/resolvers/release_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/terraform/states_resolver_spec.rb20
-rw-r--r--spec/graphql/types/ci/pipeline_type_spec.rb2
-rw-r--r--spec/graphql/types/ci_configuration/sast/analyzers_entity_input_type_spec.rb9
-rw-r--r--spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb11
-rw-r--r--spec/graphql/types/ci_configuration/sast/entity_input_type_spec.rb9
-rw-r--r--spec/graphql/types/ci_configuration/sast/entity_type_spec.rb11
-rw-r--r--spec/graphql/types/ci_configuration/sast/input_type_spec.rb9
-rw-r--r--spec/graphql/types/ci_configuration/sast/options_entity_spec.rb11
-rw-r--r--spec/graphql/types/ci_configuration/sast/type_spec.rb11
-rw-r--r--spec/graphql/types/ci_configuration/sast/ui_component_size_enum_spec.rb11
-rw-r--r--spec/graphql/types/container_repository_sort_enum_spec.rb15
-rw-r--r--spec/graphql/types/event_type_spec.rb11
-rw-r--r--spec/graphql/types/eventable_type_spec.rb9
-rw-r--r--spec/graphql/types/group_type_spec.rb4
-rw-r--r--spec/graphql/types/merge_request_state_event_enum_spec.rb12
-rw-r--r--spec/graphql/types/packages/composer/details_type_spec.rb23
-rw-r--r--spec/graphql/types/packages/composer/metadatum_type_spec.rb4
-rw-r--r--spec/graphql/types/packages/package_type_enum_spec.rb2
-rw-r--r--spec/graphql/types/packages/package_type_spec.rb7
-rw-r--r--spec/graphql/types/packages/package_without_versions_type_spec.rb13
-rw-r--r--spec/graphql/types/project_type_spec.rb172
-rw-r--r--spec/graphql/types/query_type_spec.rb6
-rw-r--r--spec/graphql/types/user_type_spec.rb1
-rw-r--r--spec/helpers/analytics/unique_visits_helper_spec.rb13
-rw-r--r--spec/helpers/application_settings_helper_spec.rb29
-rw-r--r--spec/helpers/auth_helper_spec.rb4
-rw-r--r--spec/helpers/commits_helper_spec.rb104
-rw-r--r--spec/helpers/container_registry_helper_spec.rb4
-rw-r--r--spec/helpers/diff_helper_spec.rb48
-rw-r--r--spec/helpers/enable_search_settings_helper_spec.rb21
-rw-r--r--spec/helpers/events_helper_spec.rb8
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb16
-rw-r--r--spec/helpers/groups_helper_spec.rb78
-rw-r--r--spec/helpers/invite_members_helper_spec.rb87
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb93
-rw-r--r--spec/helpers/issuables_helper_spec.rb47
-rw-r--r--spec/helpers/issues_helper_spec.rb27
-rw-r--r--spec/helpers/jira_connect_helper_spec.rb41
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb91
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb10
-rw-r--r--spec/helpers/notes_helper_spec.rb11
-rw-r--r--spec/helpers/notify_helper_spec.rb31
-rw-r--r--spec/helpers/operations_helper_spec.rb2
-rw-r--r--spec/helpers/projects/alert_management_helper_spec.rb7
-rw-r--r--spec/helpers/projects/project_members_helper_spec.rb56
-rw-r--r--spec/helpers/projects_helper_spec.rb113
-rw-r--r--spec/helpers/search_helper_spec.rb31
-rw-r--r--spec/helpers/sorting_helper_spec.rb18
-rw-r--r--spec/helpers/stat_anchors_helper_spec.rb4
-rw-r--r--spec/helpers/tree_helper_spec.rb88
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb20
-rw-r--r--spec/initializers/lograge_spec.rb24
-rw-r--r--spec/initializers/net_http_patch_spec.rb86
-rw-r--r--spec/initializers/validate_puma_spec.rb67
-rw-r--r--spec/javascripts/fly_out_nav_browser_spec.js2
-rw-r--r--spec/javascripts/matchers.js42
-rw-r--r--spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js6
-rw-r--r--spec/javascripts/test_bundle.js17
-rw-r--r--spec/lib/api/entities/merge_request_basic_spec.rb27
-rw-r--r--spec/lib/api/entities/user_spec.rb12
-rw-r--r--spec/lib/api/support/git_access_actor_spec.rb12
-rw-r--r--spec/lib/atlassian/jira_connect/client_spec.rb66
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb5
-rw-r--r--spec/lib/backup/files_spec.rb14
-rw-r--r--spec/lib/banzai/filter/asset_proxy_filter_spec.rb16
-rw-r--r--spec/lib/banzai/filter/custom_emoji_filter_spec.rb80
-rw-r--r--spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb223
-rw-r--r--spec/lib/banzai/filter/merge_request_reference_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/truncate_source_filter_spec.rb2
-rw-r--r--spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb5
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb12
-rw-r--r--spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb118
-rw-r--r--spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb2
-rw-r--r--spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb53
-rw-r--r--spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb66
-rw-r--r--spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb2
-rw-r--r--spec/lib/bulk_imports/common/transformers/award_emoji_transformer_spec.rb48
-rw-r--r--spec/lib/bulk_imports/common/transformers/hash_key_digger_spec.rb28
-rw-r--r--spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb27
-rw-r--r--spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb24
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb32
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb32
-rw-r--r--spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb35
-rw-r--r--spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb17
-rw-r--r--spec/lib/bulk_imports/groups/loaders/labels_loader_spec.rb30
-rw-r--r--spec/lib/bulk_imports/groups/loaders/members_loader_spec.rb42
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb51
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb118
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb87
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb12
-rw-r--r--spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb24
-rw-r--r--spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb101
-rw-r--r--spec/lib/bulk_imports/importers/group_importer_spec.rb29
-rw-r--r--spec/lib/bulk_imports/pipeline/context_spec.rb38
-rw-r--r--spec/lib/bulk_imports/pipeline/extracted_data_spec.rb53
-rw-r--r--spec/lib/bulk_imports/pipeline/runner_spec.rb97
-rw-r--r--spec/lib/feature/gitaly_spec.rb67
-rw-r--r--spec/lib/gitlab/access/branch_protection_spec.rb10
-rw-r--r--spec/lib/gitlab/alert_management/payload/generic_spec.rb29
-rw-r--r--spec/lib/gitlab/alert_management/payload/prometheus_spec.rb63
-rw-r--r--spec/lib/gitlab/alert_management/payload_spec.rb15
-rw-r--r--spec/lib/gitlab/api_authentication/token_locator_spec.rb21
-rw-r--r--spec/lib/gitlab/api_authentication/token_resolver_spec.rb63
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb67
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb329
-rw-r--r--spec/lib/gitlab/auth/ip_rate_limiter_spec.rb3
-rw-r--r--spec/lib/gitlab/auth/otp/session_enforcer_spec.rb41
-rw-r--r--spec/lib/gitlab/auth/u2f_webauthn_converter_spec.rb29
-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/populate_issue_email_participants_spec.rb20
-rw-r--r--spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb135
-rw-r--r--spec/lib/gitlab/background_migration_spec.rb2
-rw-r--r--spec/lib/gitlab/badge/coverage/metadata_spec.rb32
-rw-r--r--spec/lib/gitlab/badge/coverage/report_spec.rb99
-rw-r--r--spec/lib/gitlab/badge/coverage/template_spec.rb182
-rw-r--r--spec/lib/gitlab/badge/pipeline/metadata_spec.rb29
-rw-r--r--spec/lib/gitlab/badge/pipeline/status_spec.rb127
-rw-r--r--spec/lib/gitlab/badge/pipeline/template_spec.rb140
-rw-r--r--spec/lib/gitlab/changelog/ast_spec.rb246
-rw-r--r--spec/lib/gitlab/changelog/committer_spec.rb128
-rw-r--r--spec/lib/gitlab/changelog/config_spec.rb98
-rw-r--r--spec/lib/gitlab/changelog/generator_spec.rb164
-rw-r--r--spec/lib/gitlab/changelog/parser_spec.rb78
-rw-r--r--spec/lib/gitlab/changelog/release_spec.rb129
-rw-r--r--spec/lib/gitlab/ci/badge/coverage/metadata_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/badge/coverage/report_spec.rb99
-rw-r--r--spec/lib/gitlab/ci/badge/coverage/template_spec.rb182
-rw-r--r--spec/lib/gitlab/ci/badge/pipeline/metadata_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/badge/pipeline/status_spec.rb127
-rw-r--r--spec/lib/gitlab/ci/badge/pipeline/template_spec.rb140
-rw-r--r--spec/lib/gitlab/ci/badge/shared/metadata.rb (renamed from spec/lib/gitlab/badge/shared/metadata.rb)0
-rw-r--r--spec/lib/gitlab/ci/build/credentials/registry/dependency_proxy_spec.rb43
-rw-r--r--spec/lib/gitlab/ci/build/credentials/registry/gitlab_registry_spec.rb43
-rw-r--r--spec/lib/gitlab/ci/build/credentials/registry_spec.rb43
-rw-r--r--spec/lib/gitlab/ci/build/rules_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/charts_spec.rb82
-rw-r--r--spec/lib/gitlab/ci/config/entry/cache_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/config/entry/commands_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/config/yaml/tags/reference_spec.rb121
-rw-r--r--spec/lib/gitlab/ci/config/yaml/tags/resolver_spec.rb123
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/cron_parser_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/jwt_spec.rb36
-rw-r--r--spec/lib/gitlab/ci/parsers/instrumentation_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/parsers_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/build_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build/resource_group_spec.rb46
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/processable/resource_group_spec.rb46
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_mr_diff_spec.rb58
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb58
-rw-r--r--spec/lib/gitlab/ci/reports/codequality_reports_spec.rb58
-rw-r--r--spec/lib/gitlab/ci/status/bridge/factory_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/status/bridge/waiting_for_resource_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/status/build/waiting_for_resource_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb36
-rw-r--r--spec/lib/gitlab/ci/trace/chunked_io_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/variables/collection/sorted_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/variables/helpers_spec.rb103
-rw-r--r--spec/lib/gitlab/cleanup/orphan_job_artifact_files_spec.rb3
-rw-r--r--spec/lib/gitlab/cluster/lifecycle_events_spec.rb85
-rw-r--r--spec/lib/gitlab/composer/cache_spec.rb133
-rw-r--r--spec/lib/gitlab/composer/version_index_spec.rb16
-rw-r--r--spec/lib/gitlab/conan_token_spec.rb2
-rw-r--r--spec/lib/gitlab/config/entry/validators/nested_array_helpers_spec.rb70
-rw-r--r--spec/lib/gitlab/crypto_helper_spec.rb78
-rw-r--r--spec/lib/gitlab/current_settings_spec.rb28
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb34
-rw-r--r--spec/lib/gitlab/danger/base_linter_spec.rb193
-rw-r--r--spec/lib/gitlab/danger/changelog_spec.rb229
-rw-r--r--spec/lib/gitlab/danger/commit_linter_spec.rb242
-rw-r--r--spec/lib/gitlab/danger/emoji_checker_spec.rb38
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb602
-rw-r--r--spec/lib/gitlab/danger/merge_request_linter_spec.rb55
-rw-r--r--spec/lib/gitlab/danger/roulette_spec.rb413
-rw-r--r--spec/lib/gitlab/danger/sidekiq_queues_spec.rb82
-rw-r--r--spec/lib/gitlab/danger/teammate_spec.rb220
-rw-r--r--spec/lib/gitlab/danger/title_linting_spec.rb56
-rw-r--r--spec/lib/gitlab/danger/weightage/maintainers_spec.rb34
-rw-r--r--spec/lib/gitlab/danger/weightage/reviewers_spec.rb63
-rw-r--r--spec/lib/gitlab/data_builder/build_spec.rb4
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb15
-rw-r--r--spec/lib/gitlab/database/migration_helpers/v2_spec.rb221
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb253
-rw-r--r--spec/lib/gitlab/database/migrations/instrumentation_spec.rb111
-rw-r--r--spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb39
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb3
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_spec.rb4
-rw-r--r--spec/lib/gitlab/diff/char_diff_spec.rb77
-rw-r--r--spec/lib/gitlab/diff/file_collection_sorter_spec.rb10
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb18
-rw-r--r--spec/lib/gitlab/diff/inline_diff_spec.rb27
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb7
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb27
-rw-r--r--spec/lib/gitlab/experimentation/experiment_spec.rb3
-rw-r--r--spec/lib/gitlab/experimentation_spec.rb66
-rw-r--r--spec/lib/gitlab/file_finder_spec.rb8
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb3
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb7
-rw-r--r--spec/lib/gitlab/git/push_spec.rb10
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb5
-rw-r--r--spec/lib/gitlab/git_access_spec.rb102
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb10
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb64
-rw-r--r--spec/lib/gitlab/graphql/pagination/connections_spec.rb97
-rw-r--r--spec/lib/gitlab/graphql/queries_spec.rb4
-rw-r--r--spec/lib/gitlab/health_checks/master_check_spec.rb68
-rw-r--r--spec/lib/gitlab/health_checks/probes/collection_spec.rb29
-rw-r--r--spec/lib/gitlab/hook_data/group_builder_spec.rb68
-rw-r--r--spec/lib/gitlab/hook_data/subgroup_builder_spec.rb52
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml7
-rw-r--r--spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb50
-rw-r--r--spec/lib/gitlab/import_export/design_repo_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/design_repo_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/fork_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/group/tree_restorer_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/importer_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/repo_restorer_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/repo_saver_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml4
-rw-r--r--spec/lib/gitlab/import_export/saver_spec.rb12
-rw-r--r--spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb2
-rw-r--r--spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb1
-rw-r--r--spec/lib/gitlab/instrumentation_helper_spec.rb60
-rw-r--r--spec/lib/gitlab/kas_spec.rb44
-rw-r--r--spec/lib/gitlab/memory/instrumentation_spec.rb100
-rw-r--r--spec/lib/gitlab/metrics/subscribers/external_http_spec.rb172
-rw-r--r--spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb203
-rw-r--r--spec/lib/gitlab/middleware/request_context_spec.rb43
-rw-r--r--spec/lib/gitlab/pages_transfer_spec.rb22
-rw-r--r--spec/lib/gitlab/patch/prependable_spec.rb18
-rw-r--r--spec/lib/gitlab/performance_bar/stats_spec.rb8
-rw-r--r--spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb89
-rw-r--r--spec/lib/gitlab/rack_attack_spec.rb3
-rw-r--r--spec/lib/gitlab/repository_cache_adapter_spec.rb7
-rw-r--r--spec/lib/gitlab/request_forgery_protection_spec.rb5
-rw-r--r--spec/lib/gitlab/runtime_spec.rb17
-rw-r--r--spec/lib/gitlab/search/query_spec.rb18
-rw-r--r--spec/lib/gitlab/search_results_spec.rb27
-rw-r--r--spec/lib/gitlab/sidekiq_logging/exception_handler_spec.rb44
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb178
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb21
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb22
-rw-r--r--spec/lib/gitlab/suggestions/commit_message_spec.rb11
-rw-r--r--spec/lib/gitlab/template/finders/global_template_finder_spec.rb23
-rw-r--r--spec/lib/gitlab/terraform/state_migration_helper_spec.rb21
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb55
-rw-r--r--spec/lib/gitlab/tracking_spec.rb47
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb46
-rw-r--r--spec/lib/gitlab/url_blockers/url_allowlist_spec.rb28
-rw-r--r--spec/lib/gitlab/usage/docs/renderer_spec.rb22
-rw-r--r--spec/lib/gitlab/usage/docs/value_formatter_spec.rb26
-rw-r--r--spec/lib/gitlab/usage/metric_definition_spec.rb29
-rw-r--r--spec/lib/gitlab/usage/metric_spec.rb8
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb281
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb146
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb29
-rw-r--r--spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb20
-rw-r--r--spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb86
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb228
-rw-r--r--spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb136
-rw-r--r--spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb163
-rw-r--r--spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb63
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb144
-rw-r--r--spec/lib/gitlab/utils/markdown_spec.rb44
-rw-r--r--spec/lib/gitlab/utils/override_spec.rb67
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb10
-rw-r--r--spec/lib/gitlab/utils_spec.rb8
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb47
-rw-r--r--spec/lib/gitlab_danger_spec.rb76
-rw-r--r--spec/lib/gitlab_spec.rb24
-rw-r--r--spec/lib/object_storage/config_spec.rb63
-rw-r--r--spec/lib/peek/views/external_http_spec.rb215
-rw-r--r--spec/lib/release_highlights/validator/entry_spec.rb2
-rw-r--r--spec/lib/release_highlights/validator_spec.rb2
-rw-r--r--spec/lib/security/ci_configuration/sast_build_actions_spec.rb539
-rw-r--r--spec/mailers/notify_spec.rb22
-rw-r--r--spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb140
-rw-r--r--spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb30
-rw-r--r--spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb28
-rw-r--r--spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb47
-rw-r--r--spec/migrations/add_has_external_issue_tracker_trigger_spec.rb164
-rw-r--r--spec/migrations/add_new_post_eoa_plans_spec.rb32
-rw-r--r--spec/migrations/cleanup_projects_with_bad_has_external_wiki_data_spec.rb89
-rw-r--r--spec/migrations/drop_alerts_service_data_spec.rb21
-rw-r--r--spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb2
-rw-r--r--spec/migrations/remove_alerts_service_records_again_spec.rb23
-rw-r--r--spec/migrations/schedule_migrate_security_scans_spec.rb11
-rw-r--r--spec/migrations/schedule_populate_issue_email_participants_spec.rb33
-rw-r--r--spec/models/active_session_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb77
-rw-r--r--spec/models/bulk_imports/entity_spec.rb31
-rw-r--r--spec/models/ci/bridge_spec.rb8
-rw-r--r--spec/models/ci/build_dependencies_spec.rb28
-rw-r--r--spec/models/ci/build_spec.rb80
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb2
-rw-r--r--spec/models/ci/build_trace_chunks/fog_spec.rb21
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb43
-rw-r--r--spec/models/ci/pipeline_artifact_spec.rb114
-rw-r--r--spec/models/ci/pipeline_spec.rb107
-rw-r--r--spec/models/ci/processable_spec.rb54
-rw-r--r--spec/models/ci/resource_group_spec.rb12
-rw-r--r--spec/models/ci/resource_spec.rb2
-rw-r--r--spec/models/ci/stage_spec.rb3
-rw-r--r--spec/models/clusters/agent_spec.rb1
-rw-r--r--spec/models/clusters/agent_token_spec.rb1
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb10
-rw-r--r--spec/models/commit_spec.rb13
-rw-r--r--spec/models/commit_status_spec.rb73
-rw-r--r--spec/models/concerns/atomic_internal_id_spec.rb152
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb7
-rw-r--r--spec/models/concerns/featurable_spec.rb16
-rw-r--r--spec/models/concerns/issuable_spec.rb19
-rw-r--r--spec/models/concerns/nullify_if_blank_spec.rb51
-rw-r--r--spec/models/concerns/protected_ref_spec.rb77
-rw-r--r--spec/models/concerns/spammable_spec.rb55
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb4
-rw-r--r--spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb8
-rw-r--r--spec/models/deployment_spec.rb56
-rw-r--r--spec/models/design_management/design_spec.rb21
-rw-r--r--spec/models/event_spec.rb64
-rw-r--r--spec/models/experiment_spec.rb57
-rw-r--r--spec/models/group_spec.rb40
-rw-r--r--spec/models/issue_link_spec.rb2
-rw-r--r--spec/models/issue_spec.rb4
-rw-r--r--spec/models/license_template_spec.rb2
-rw-r--r--spec/models/merge_request/metrics_spec.rb11
-rw-r--r--spec/models/merge_request_diff_commit_spec.rb9
-rw-r--r--spec/models/merge_request_diff_spec.rb51
-rw-r--r--spec/models/merge_request_spec.rb239
-rw-r--r--spec/models/namespace_spec.rb76
-rw-r--r--spec/models/note_spec.rb38
-rw-r--r--spec/models/onboarding_progress_spec.rb83
-rw-r--r--spec/models/operations/feature_flag_spec.rb29
-rw-r--r--spec/models/packages/composer/cache_file_spec.rb32
-rw-r--r--spec/models/packages/composer/metadatum_spec.rb16
-rw-r--r--spec/models/packages/debian/group_component_file_spec.rb7
-rw-r--r--spec/models/packages/debian/group_component_spec.rb7
-rw-r--r--spec/models/packages/debian/project_component_file_spec.rb7
-rw-r--r--spec/models/packages/debian/project_component_spec.rb7
-rw-r--r--spec/models/packages/debian/publication_spec.rb47
-rw-r--r--spec/models/packages/package_spec.rb50
-rw-r--r--spec/models/packages/rubygems/metadatum_spec.rb22
-rw-r--r--spec/models/pages/lookup_path_spec.rb38
-rw-r--r--spec/models/pages/virtual_domain_spec.rb21
-rw-r--r--spec/models/pages_deployment_spec.rb40
-rw-r--r--spec/models/project_ci_cd_setting_spec.rb37
-rw-r--r--spec/models/project_services/alerts_service_spec.rb39
-rw-r--r--spec/models/project_services/chat_notification_service_spec.rb33
-rw-r--r--spec/models/project_services/confluence_service_spec.rb6
-rw-r--r--spec/models/project_services/datadog_service_spec.rb36
-rw-r--r--spec/models/project_services/jira_service_spec.rb61
-rw-r--r--spec/models/project_services/jira_tracker_data_spec.rb21
-rw-r--r--spec/models/project_spec.rb242
-rw-r--r--spec/models/project_wiki_spec.rb1
-rw-r--r--spec/models/prometheus_metric_spec.rb10
-rw-r--r--spec/models/protected_branch/push_access_level_spec.rb10
-rw-r--r--spec/models/readme_blob_spec.rb17
-rw-r--r--spec/models/release_highlight_spec.rb2
-rw-r--r--spec/models/release_spec.rb57
-rw-r--r--spec/models/repository_spec.rb78
-rw-r--r--spec/models/service_spec.rb78
-rw-r--r--spec/models/snippet_spec.rb6
-rw-r--r--spec/models/terraform/state_spec.rb12
-rw-r--r--spec/models/terraform/state_version_spec.rb18
-rw-r--r--spec/models/token_with_iv_spec.rb29
-rw-r--r--spec/models/u2f_registration_spec.rb37
-rw-r--r--spec/models/user_spec.rb75
-rw-r--r--spec/models/user_status_spec.rb30
-rw-r--r--spec/policies/project_policy_spec.rb65
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb14
-rw-r--r--spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb66
-rw-r--r--spec/presenters/gitlab/whats_new/item_presenter_spec.rb29
-rw-r--r--spec/presenters/project_presenter_spec.rb2
-rw-r--r--spec/requests/api/api_spec.rb36
-rw-r--r--spec/requests/api/applications_spec.rb2
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb34
-rw-r--r--spec/requests/api/debian_group_packages_spec.rb20
-rw-r--r--spec/requests/api/debian_project_packages_spec.rb28
-rw-r--r--spec/requests/api/deploy_tokens_spec.rb16
-rw-r--r--spec/requests/api/events_spec.rb6
-rw-r--r--spec/requests/api/generic_packages_spec.rb75
-rw-r--r--spec/requests/api/graphql/ci/application_setting_spec.rb49
-rw-r--r--spec/requests/api/graphql/ci/ci_cd_setting_spec.rb2
-rw-r--r--spec/requests/api/graphql/issue/issue_spec.rb14
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb16
-rw-r--r--spec/requests/api/graphql/mutations/boards/lists/create_spec.rb46
-rw-r--r--spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb65
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb8
-rw-r--r--spec/requests/api/graphql/mutations/snippets/create_spec.rb36
-rw-r--r--spec/requests/api/graphql/mutations/snippets/update_spec.rb34
-rw-r--r--spec/requests/api/graphql/packages/package_composer_details_spec.rb39
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb80
-rw-r--r--spec/requests/api/graphql/project/container_repositories_spec.rb47
-rw-r--r--spec/requests/api/graphql/project/issue/designs/notes_spec.rb19
-rw-r--r--spec/requests/api/graphql/project/merge_request/pipelines_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb108
-rw-r--r--spec/requests/api/graphql/project/packages_spec.rb31
-rw-r--r--spec/requests/api/graphql/project/release_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/terraform/state_spec.rb83
-rw-r--r--spec/requests/api/group_import_spec.rb4
-rw-r--r--spec/requests/api/group_labels_spec.rb54
-rw-r--r--spec/requests/api/group_packages_spec.rb1
-rw-r--r--spec/requests/api/groups_spec.rb7
-rw-r--r--spec/requests/api/internal/base_spec.rb267
-rw-r--r--spec/requests/api/internal/kubernetes_spec.rb68
-rw-r--r--spec/requests/api/jobs_spec.rb3
-rw-r--r--spec/requests/api/labels_spec.rb59
-rw-r--r--spec/requests/api/maven_packages_spec.rb22
-rw-r--r--spec/requests/api/merge_requests_spec.rb73
-rw-r--r--spec/requests/api/npm_instance_packages_spec.rb2
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb34
-rw-r--r--spec/requests/api/nuget_project_packages_spec.rb14
-rw-r--r--spec/requests/api/oauth_tokens_spec.rb15
-rw-r--r--spec/requests/api/project_attributes.yml149
-rw-r--r--spec/requests/api/project_import_spec.rb5
-rw-r--r--spec/requests/api/project_packages_spec.rb1
-rw-r--r--spec/requests/api/project_templates_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb77
-rw-r--r--spec/requests/api/pypi_packages_spec.rb27
-rw-r--r--spec/requests/api/repositories_spec.rb81
-rw-r--r--spec/requests/api/resource_access_tokens_spec.rb293
-rw-r--r--spec/requests/api/rubygem_packages_spec.rb139
-rw-r--r--spec/requests/api/settings_spec.rb18
-rw-r--r--spec/requests/api/suggestions_spec.rb27
-rw-r--r--spec/requests/api/templates_spec.rb6
-rw-r--r--spec/requests/api/terraform/state_spec.rb2
-rw-r--r--spec/requests/api/triggers_spec.rb11
-rw-r--r--spec/requests/api/users_spec.rb199
-rw-r--r--spec/requests/api/version_spec.rb12
-rw-r--r--spec/requests/git_http_spec.rb16
-rw-r--r--spec/requests/groups/email_campaigns_controller_spec.rb86
-rw-r--r--spec/requests/health_controller_spec.rb152
-rw-r--r--spec/requests/import/gitlab_groups_controller_spec.rb6
-rw-r--r--spec/requests/import/gitlab_projects_controller_spec.rb3
-rw-r--r--spec/requests/oauth/tokens_controller_spec.rb14
-rw-r--r--spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb46
-rw-r--r--spec/requests/projects/noteable_notes_spec.rb11
-rw-r--r--spec/requests/rack_attack_global_spec.rb6
-rw-r--r--spec/requests/users_controller_spec.rb8
-rw-r--r--spec/requests/whats_new_controller_spec.rb66
-rw-r--r--spec/routing/admin_routing_spec.rb7
-rw-r--r--spec/routing/projects/security/configuration_controller_routing_spec.rb15
-rw-r--r--spec/rubocop/code_reuse_helpers_spec.rb56
-rw-r--r--spec/rubocop/cop/active_record_association_reload_spec.rb2
-rw-r--r--spec/rubocop/cop/api/base_spec.rb5
-rw-r--r--spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb28
-rw-r--r--spec/rubocop/cop/avoid_becomes_spec.rb30
-rw-r--r--spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb6
-rw-r--r--spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb7
-rw-r--r--spec/rubocop/cop/ban_catch_throw_spec.rb26
-rw-r--r--spec/rubocop/cop/code_reuse/finder_spec.rb5
-rw-r--r--spec/rubocop/cop/code_reuse/presenter_spec.rb3
-rw-r--r--spec/rubocop/cop/code_reuse/serializer_spec.rb3
-rw-r--r--spec/rubocop/cop/code_reuse/service_class_spec.rb3
-rw-r--r--spec/rubocop/cop/code_reuse/worker_spec.rb3
-rw-r--r--spec/rubocop/cop/default_scope_spec.rb39
-rw-r--r--spec/rubocop/cop/destroy_all_spec.rb39
-rw-r--r--spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb9
-rw-r--r--spec/rubocop/cop/gitlab/bulk_insert_spec.rb11
-rw-r--r--spec/rubocop/cop/gitlab/change_timezone_spec.rb5
-rw-r--r--spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb47
-rw-r--r--spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/except_spec.rb3
-rw-r--r--spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb49
-rw-r--r--spec/rubocop/cop/gitlab/httparty_spec.rb34
-rw-r--r--spec/rubocop/cop/gitlab/intersect_spec.rb3
-rw-r--r--spec/rubocop/cop/gitlab/json_spec.rb33
-rw-r--r--spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb35
-rw-r--r--spec/rubocop/cop/gitlab/namespaced_class_spec.rb73
-rw-r--r--spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb3
-rw-r--r--spec/rubocop/cop/gitlab/predicate_memoization_spec.rb74
-rw-r--r--spec/rubocop/cop/gitlab/rails_logger_spec.rb22
-rw-r--r--spec/rubocop/cop/gitlab/union_spec.rb3
-rw-r--r--spec/rubocop/cop/graphql/authorize_types_spec.rb7
-rw-r--r--spec/rubocop/cop/graphql/descriptions_spec.rb22
-rw-r--r--spec/rubocop/cop/graphql/gid_expected_type_spec.rb7
-rw-r--r--spec/rubocop/cop/graphql/id_type_spec.rb7
-rw-r--r--spec/rubocop/cop/graphql/json_type_spec.rb24
-rw-r--r--spec/rubocop/cop/graphql/resolver_type_spec.rb18
-rw-r--r--spec/rubocop/cop/group_public_or_visible_to_user_spec.rb23
-rw-r--r--spec/rubocop/cop/include_sidekiq_worker_spec.rb30
-rw-r--r--spec/rubocop/cop/inject_enterprise_edition_module_spec.rb24
-rw-r--r--spec/rubocop/cop/lint/last_keyword_argument_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb18
-rw-r--r--spec/rubocop/cop/performance/ar_count_each_spec.rb4
-rw-r--r--spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb8
-rw-r--r--spec/rubocop/cop/performance/readlines_each_spec.rb23
-rw-r--r--spec/rubocop/cop/project_path_helper_spec.rb29
-rw-r--r--spec/rubocop/cop/put_project_routes_under_scope_spec.rb2
-rw-r--r--spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb4
-rw-r--r--spec/rubocop/cop/qa/element_with_pattern_spec.rb4
-rw-r--r--spec/rubocop/cop/rspec/any_instance_of_spec.rb40
-rw-r--r--spec/rubocop/cop/rspec/be_success_matcher_spec.rb27
-rw-r--r--spec/rubocop/cop/rspec/env_assignment_spec.rb33
-rw-r--r--spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb27
-rw-r--r--spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb6
-rw-r--r--spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb30
-rw-r--r--spec/rubocop/cop/rspec/have_gitlab_http_status_spec.rb51
-rw-r--r--spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb18
-rw-r--r--spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb39
-rw-r--r--spec/rubocop/cop/rspec/timecop_freeze_spec.rb47
-rw-r--r--spec/rubocop/cop/rspec/timecop_travel_spec.rb47
-rw-r--r--spec/rubocop/cop/rspec/top_level_describe_path_spec.rb2
-rw-r--r--spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb67
-rw-r--r--spec/rubocop/cop/safe_params_spec.rb3
-rw-r--r--spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb24
-rw-r--r--spec/rubocop/cop/scalability/cron_worker_context_spec.rb7
-rw-r--r--spec/rubocop/cop/scalability/file_uploads_spec.rb2
-rw-r--r--spec/rubocop/cop/scalability/idempotent_worker_spec.rb11
-rw-r--r--spec/rubocop/cop/static_translation_definition_spec.rb98
-rw-r--r--spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb42
-rw-r--r--spec/rubocop/cop/usage_data/large_table_spec.rb56
-rw-r--r--spec/rubocop/qa_helpers_spec.rb6
-rw-r--r--spec/serializers/admin/user_entity_spec.rb1
-rw-r--r--spec/serializers/admin/user_serializer_spec.rb1
-rw-r--r--spec/serializers/ci/codequality_mr_diff_entity_spec.rb27
-rw-r--r--spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb32
-rw-r--r--spec/serializers/ci/dag_pipeline_entity_spec.rb6
-rw-r--r--spec/serializers/ci/pipeline_entity_spec.rb261
-rw-r--r--spec/serializers/codequality_degradation_entity_spec.rb63
-rw-r--r--spec/serializers/codequality_reports_comparer_entity_spec.rb58
-rw-r--r--spec/serializers/codequality_reports_comparer_serializer_spec.rb58
-rw-r--r--spec/serializers/diff_file_metadata_entity_spec.rb27
-rw-r--r--spec/serializers/diffs_entity_spec.rb15
-rw-r--r--spec/serializers/group_group_link_entity_spec.rb31
-rw-r--r--spec/serializers/group_group_link_serializer_spec.rb13
-rw-r--r--spec/serializers/group_link/group_group_link_entity_spec.rb31
-rw-r--r--spec/serializers/group_link/group_group_link_serializer_spec.rb13
-rw-r--r--spec/serializers/group_link/group_link_entity_spec.rb25
-rw-r--r--spec/serializers/group_link/project_group_link_entity_spec.rb30
-rw-r--r--spec/serializers/group_link/project_group_link_serializer_spec.rb13
-rw-r--r--spec/serializers/member_entity_spec.rb36
-rw-r--r--spec/serializers/member_serializer_spec.rb4
-rw-r--r--spec/serializers/merge_request_basic_entity_spec.rb22
-rw-r--r--spec/serializers/merge_request_sidebar_extras_entity_spec.rb22
-rw-r--r--spec/serializers/merge_request_user_entity_spec.rb18
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb6
-rw-r--r--spec/serializers/paginated_diff_entity_spec.rb2
-rw-r--r--spec/serializers/pipeline_details_entity_spec.rb4
-rw-r--r--spec/serializers/pipeline_entity_spec.rb264
-rw-r--r--spec/serializers/user_serializer_spec.rb2
-rw-r--r--spec/services/alert_management/process_prometheus_alert_service_spec.rb47
-rw-r--r--spec/services/application_settings/update_service_spec.rb2
-rw-r--r--spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb2
-rw-r--r--spec/services/boards/lists/create_service_spec.rb104
-rw-r--r--spec/services/bulk_create_integration_service_spec.rb51
-rw-r--r--spec/services/captcha/captcha_verification_service_spec.rb39
-rw-r--r--spec/services/ci/create_job_artifacts_service_spec.rb28
-rw-r--r--spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb86
-rw-r--r--spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb79
-rw-r--r--spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb50
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb14
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb7
-rw-r--r--spec/services/ci/daily_build_group_report_result_service_spec.rb28
-rw-r--r--spec/services/ci/generate_codequality_mr_diff_report_service_spec.rb51
-rw-r--r--spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb62
-rw-r--r--spec/services/ci/pipeline_trigger_service_spec.rb29
-rw-r--r--spec/services/ci/process_build_service_spec.rb6
-rw-r--r--spec/services/ci/process_pipeline_service_spec.rb29
-rw-r--r--spec/services/ci/prometheus_metrics/observe_histograms_service_spec.rb86
-rw-r--r--spec/services/ci/register_job_service_spec.rb22
-rw-r--r--spec/services/container_expiration_policies/cleanup_service_spec.rb22
-rw-r--r--spec/services/deployments/create_service_spec.rb21
-rw-r--r--spec/services/design_management/move_designs_service_spec.rb12
-rw-r--r--spec/services/discussions/resolve_service_spec.rb14
-rw-r--r--spec/services/discussions/unresolve_service_spec.rb32
-rw-r--r--spec/services/feature_flags/create_service_spec.rb12
-rw-r--r--spec/services/feature_flags/update_service_spec.rb12
-rw-r--r--spec/services/git/branch_hooks_service_spec.rb182
-rw-r--r--spec/services/git/wiki_push_service_spec.rb40
-rw-r--r--spec/services/groups/import_export/export_service_spec.rb14
-rw-r--r--spec/services/groups/open_issues_count_service_spec.rb106
-rw-r--r--spec/services/integrations/test/project_service_spec.rb50
-rw-r--r--spec/services/issue_rebalancing_service_spec.rb108
-rw-r--r--spec/services/issues/close_service_spec.rb3
-rw-r--r--spec/services/issues/create_service_spec.rb176
-rw-r--r--spec/services/issues/update_service_spec.rb2
-rw-r--r--spec/services/members/update_service_spec.rb24
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb13
-rw-r--r--spec/services/merge_requests/approval_service_spec.rb14
-rw-r--r--spec/services/merge_requests/build_service_spec.rb2
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb19
-rw-r--r--spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb2
-rw-r--r--spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb45
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb14
-rw-r--r--spec/services/merge_requests/mergeability_check_service_spec.rb28
-rw-r--r--spec/services/merge_requests/post_merge_service_spec.rb142
-rw-r--r--spec/services/merge_requests/push_options_handler_service_spec.rb45
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb41
-rw-r--r--spec/services/merge_requests/reload_merge_head_diff_service_spec.rb61
-rw-r--r--spec/services/merge_requests/remove_approval_service_spec.rb14
-rw-r--r--spec/services/merge_requests/request_review_service_spec.rb69
-rw-r--r--spec/services/merge_requests/update_service_spec.rb95
-rw-r--r--spec/services/namespaces/in_product_marketing_emails_service_spec.rb159
-rw-r--r--spec/services/notes/create_service_spec.rb20
-rw-r--r--spec/services/notification_recipients/build_service_spec.rb24
-rw-r--r--spec/services/notification_service_spec.rb40
-rw-r--r--spec/services/packages/composer/create_package_service_spec.rb2
-rw-r--r--spec/services/packages/conan/create_package_service_spec.rb1
-rw-r--r--spec/services/packages/debian/create_distribution_service_spec.rb122
-rw-r--r--spec/services/packages/debian/destroy_distribution_service_spec.rb78
-rw-r--r--spec/services/packages/debian/update_distribution_service_spec.rb159
-rw-r--r--spec/services/packages/generic/create_package_file_service_spec.rb40
-rw-r--r--spec/services/packages/maven/find_or_create_package_service_spec.rb10
-rw-r--r--spec/services/packages/npm/create_package_service_spec.rb1
-rw-r--r--spec/services/packages/nuget/create_package_service_spec.rb1
-rw-r--r--spec/services/packages/pypi/create_package_service_spec.rb1
-rw-r--r--spec/services/pages/delete_services_spec.rb81
-rw-r--r--spec/services/pages/migrate_from_legacy_storage_service_spec.rb92
-rw-r--r--spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb8
-rw-r--r--spec/services/pages/zip_directory_service_spec.rb83
-rw-r--r--spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb2
-rw-r--r--spec/services/post_receive_service_spec.rb14
-rw-r--r--spec/services/projects/alerting/notify_service_spec.rb13
-rw-r--r--spec/services/projects/branches_by_mode_service_spec.rb136
-rw-r--r--spec/services/projects/cleanup_service_spec.rb2
-rw-r--r--spec/services/projects/container_repository/cleanup_tags_service_spec.rb4
-rw-r--r--spec/services/projects/create_service_spec.rb44
-rw-r--r--spec/services/projects/fork_service_spec.rb44
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb7
-rw-r--r--spec/services/projects/update_pages_service_spec.rb11
-rw-r--r--spec/services/projects/update_repository_storage_service_spec.rb13
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb194
-rw-r--r--spec/services/repositories/changelog_service_spec.rb130
-rw-r--r--spec/services/resource_access_tokens/create_service_spec.rb10
-rw-r--r--spec/services/resource_access_tokens/revoke_service_spec.rb8
-rw-r--r--spec/services/resource_events/change_milestone_service_spec.rb4
-rw-r--r--spec/services/search/global_service_spec.rb22
-rw-r--r--spec/services/search/group_service_spec.rb24
-rw-r--r--spec/services/security/ci_configuration/sast_create_service_spec.rb69
-rw-r--r--spec/services/security/ci_configuration/sast_parser_service_spec.rb76
-rw-r--r--spec/services/snippets/create_service_spec.rb5
-rw-r--r--spec/services/snippets/update_repository_storage_service_spec.rb13
-rw-r--r--spec/services/snippets/update_service_spec.rb13
-rw-r--r--spec/services/spam/spam_action_service_spec.rb182
-rw-r--r--spec/services/suggestions/apply_service_spec.rb104
-rw-r--r--spec/services/suggestions/create_service_spec.rb33
-rw-r--r--spec/services/system_hooks_service_spec.rb9
-rw-r--r--spec/services/system_note_service_spec.rb11
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb2
-rw-r--r--spec/services/system_notes/merge_requests_service_spec.rb28
-rw-r--r--spec/services/test_hooks/project_service_spec.rb55
-rw-r--r--spec/services/test_hooks/system_service_spec.rb17
-rw-r--r--spec/services/todo_service_spec.rb11
-rw-r--r--spec/services/users/approve_service_spec.rb24
-rw-r--r--spec/services/users/batch_status_cleaner_service_spec.rb43
-rw-r--r--spec/services/users/build_service_spec.rb6
-rw-r--r--spec/services/users/refresh_authorized_projects_service_spec.rb15
-rw-r--r--spec/services/users/reject_service_spec.rb20
-rw-r--r--spec/spec_helper.rb14
-rw-r--r--spec/support/factory_bot.rb13
-rw-r--r--spec/support/gitlab_experiment.rb12
-rw-r--r--spec/support/graphql/field_selection.rb2
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb26
-rw-r--r--spec/support/helpers/features/members_table_helpers.rb26
-rw-r--r--spec/support/helpers/features/notes_helpers.rb4
-rw-r--r--spec/support/helpers/graphql_helpers.rb47
-rw-r--r--spec/support/helpers/next_found_instance_of.rb16
-rw-r--r--spec/support/helpers/search_settings_helpers.rb5
-rw-r--r--spec/support/helpers/seed_helper.rb2
-rw-r--r--spec/support/helpers/smime_helper.rb2
-rw-r--r--spec/support/helpers/sorting_helper.rb31
-rw-r--r--spec/support/helpers/stub_configuration.rb6
-rw-r--r--spec/support/helpers/stub_object_storage.rb7
-rw-r--r--spec/support/helpers/test_env.rb4
-rw-r--r--spec/support/helpers/wait_for_requests.rb2
-rw-r--r--spec/support/matchers/markdown_matchers.rb27
-rw-r--r--spec/support/matchers/nullify_if_blank_matcher.rb11
-rw-r--r--spec/support/matchers/pushed_frontend_feature_flags_matcher.rb23
-rw-r--r--spec/support/matchers/track_self_describing_event_matcher.rb12
-rw-r--r--spec/support/memory_instrumentation_helper.rb17
-rw-r--r--spec/support/migrations_helpers/vulnerabilities_findings_helper.rb118
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb7
-rw-r--r--spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb8
-rw-r--r--spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb15
-rw-r--r--spec/support/shared_contexts/requests/api/workhorse_shared_context.rb6
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb1
-rw-r--r--spec/support/shared_examples/alert_notification_service_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/controllers/unique_hll_events_examples.rb18
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/comment_and_close_button_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/features/discussion_comments_shared_example.rb3
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/navbar_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb3
-rw-r--r--spec/support/shared_examples/features/search_settings_shared_examples.rb42
-rw-r--r--spec/support/shared_examples/finders/packages_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/graphql/label_fields.rb4
-rw-r--r--spec/support/shared_examples/graphql/mutations/boards_list_create_shared_examples.rb83
-rw-r--r--spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb36
-rw-r--r--spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb75
-rw-r--r--spec/support/shared_examples/graphql/mutations/spammable_mutation_fields_examples.rb50
-rw-r--r--spec/support/shared_examples/graphql/notes_creation_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/helpers/issuable_description_templates_shared_examples.rb49
-rw-r--r--spec/support/shared_examples/lib/api/internal_base_shared_examples.rb36
-rw-r--r--spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb95
-rw-r--r--spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb45
-rw-r--r--spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb245
-rw-r--r--spec/support/shared_examples/models/packages/debian/component_shared_examples.rb51
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/models/wiki_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/namespaces/recursive_traversal_examples.rb78
-rw-r--r--spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/quick_actions/issue/clone_quick_action_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/quick_actions/issue/zoom_quick_actions_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb43
-rw-r--r--spec/support/shared_examples/requests/api/graphql/mutations/create_list_shared_examples.rb51
-rw-r--r--spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb62
-rw-r--r--spec/support/shared_examples/requests/api/notes_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb490
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb190
-rw-r--r--spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/packages_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb185
-rw-r--r--spec/support/shared_examples/requests/api/read_user_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb3
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/services/boards/lists_create_service_shared_examples.rb81
-rw-r--r--spec/support/shared_examples/services/issuable_shared_examples.rb21
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb52
-rw-r--r--spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/services/snippets_shared_examples.rb68
-rw-r--r--spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb320
-rw-r--r--spec/tasks/gitlab/cleanup_rake_spec.rb22
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb51
-rw-r--r--spec/tasks/gitlab/git_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/pages_rake_spec.rb94
-rw-r--r--spec/tasks/gitlab/password_rake_spec.rb76
-rw-r--r--spec/tasks/gitlab/terraform/migrate_rake_spec.rb45
-rw-r--r--spec/tooling/danger/base_linter_spec.rb192
-rw-r--r--spec/tooling/danger/changelog_spec.rb228
-rw-r--r--spec/tooling/danger/commit_linter_spec.rb241
-rw-r--r--spec/tooling/danger/danger_spec_helper.rb (renamed from spec/lib/gitlab/danger/danger_spec_helper.rb)0
-rw-r--r--spec/tooling/danger/emoji_checker_spec.rb37
-rw-r--r--spec/tooling/danger/feature_flag_spec.rb157
-rw-r--r--spec/tooling/danger/helper_spec.rb682
-rw-r--r--spec/tooling/danger/merge_request_linter_spec.rb54
-rw-r--r--spec/tooling/danger/roulette_spec.rb429
-rw-r--r--spec/tooling/danger/sidekiq_queues_spec.rb81
-rw-r--r--spec/tooling/danger/teammate_spec.rb225
-rw-r--r--spec/tooling/danger/title_linting_spec.rb91
-rw-r--r--spec/tooling/danger/weightage/maintainers_spec.rb34
-rw-r--r--spec/tooling/danger/weightage/reviewers_spec.rb63
-rw-r--r--spec/tooling/gitlab_danger_spec.rb76
-rw-r--r--spec/tooling/lib/tooling/kubernetes_client_spec.rb8
-rw-r--r--spec/uploaders/packages/composer/cache_uploader_spec.rb45
-rw-r--r--spec/uploaders/packages/debian/component_file_uploader_spec.rb52
-rw-r--r--spec/validators/nested_attributes_duplicates_validator_spec.rb113
-rw-r--r--spec/validators/variable_duplicates_validator_spec.rb69
-rw-r--r--spec/views/groups/show.html.haml_spec.rb52
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb16
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb6
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/nav/sidebar/_project_security_link.html.haml_spec.rb29
-rw-r--r--spec/views/layouts/profile.html.haml_spec.rb39
-rw-r--r--spec/views/projects/_home_panel.html.haml_spec.rb1
-rw-r--r--spec/views/projects/empty.html.haml_spec.rb37
-rw-r--r--spec/views/projects/show.html.haml_spec.rb51
-rw-r--r--spec/views/projects/tree/_tree_row.html.haml_spec.rb43
-rw-r--r--spec/views/registrations/welcome/show.html.haml_spec.rb1
-rw-r--r--spec/views/search/_filter.html.haml_spec.rb17
-rw-r--r--spec/views/search/_form.html.haml_spec.rb14
-rw-r--r--spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb20
-rw-r--r--spec/workers/build_coverage_worker_spec.rb25
-rw-r--r--spec/workers/build_finished_worker_spec.rb20
-rw-r--r--spec/workers/build_trace_sections_worker_spec.rb25
-rw-r--r--spec/workers/bulk_import_worker_spec.rb15
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb14
-rw-r--r--spec/workers/ci/build_report_result_worker_spec.rb30
-rw-r--r--spec/workers/ci/pipeline_artifacts/create_quality_report_worker_spec.rb40
-rw-r--r--spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb2
-rw-r--r--spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb10
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb346
-rw-r--r--spec/workers/jira_connect/sync_builds_worker_spec.rb24
-rw-r--r--spec/workers/jira_connect/sync_deployments_worker_spec.rb24
-rw-r--r--spec/workers/jira_connect/sync_feature_flags_worker_spec.rb24
-rw-r--r--spec/workers/merge_request_cleanup_refs_worker_spec.rb12
-rw-r--r--spec/workers/namespaceless_project_destroy_worker_spec.rb2
-rw-r--r--spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb29
-rw-r--r--spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb25
-rw-r--r--spec/workers/namespaces/onboarding_user_added_worker_spec.rb17
-rw-r--r--spec/workers/new_note_worker_spec.rb20
-rw-r--r--spec/workers/packages/composer/cache_cleanup_worker_spec.rb29
-rw-r--r--spec/workers/pages_remove_worker_spec.rb21
-rw-r--r--spec/workers/pages_transfer_worker_spec.rb2
-rw-r--r--spec/workers/post_receive_spec.rb8
-rw-r--r--spec/workers/projects/git_garbage_collect_worker_spec.rb78
-rw-r--r--spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb12
-rw-r--r--spec/workers/user_status_cleanup/batch_worker_spec.rb33
-rw-r--r--spec/workers/wikis/git_garbage_collect_worker_spec.rb14
-rw-r--r--tooling/danger/base_linter.rb96
-rw-r--r--tooling/danger/changelog.rb92
-rw-r--r--tooling/danger/commit_linter.rb150
-rw-r--r--tooling/danger/emoji_checker.rb45
-rw-r--r--tooling/danger/feature_flag.rb44
-rw-r--r--tooling/danger/helper.rb294
-rw-r--r--tooling/danger/merge_request_linter.rb30
-rw-r--r--tooling/danger/request_helper.rb23
-rw-r--r--tooling/danger/roulette.rb169
-rw-r--r--tooling/danger/sidekiq_queues.rb37
-rw-r--r--tooling/danger/teammate.rb121
-rw-r--r--tooling/danger/title_linting.rb38
-rw-r--r--tooling/danger/weightage.rb10
-rw-r--r--tooling/danger/weightage/maintainers.rb33
-rw-r--r--tooling/danger/weightage/reviewers.rb65
-rw-r--r--tooling/gitlab_danger.rb59
-rw-r--r--tooling/lib/tooling/kubernetes_client.rb2
-rwxr-xr-x[-rw-r--r--]vendor/gitignore/C++.gitignore0
-rwxr-xr-x[-rw-r--r--]vendor/gitignore/Java.gitignore0
-rw-r--r--vendor/sample_data_templates/sample.tar.gzbin340647 -> 367276 bytes
-rw-r--r--workhorse/CHANGELOG38
-rw-r--r--workhorse/VERSION2
-rw-r--r--workhorse/gitaly_test.go175
-rw-r--r--workhorse/go.mod20
-rw-r--r--workhorse/go.sum299
-rw-r--r--workhorse/internal/api/api.go19
-rw-r--r--workhorse/internal/errortracker/sentry.go60
-rw-r--r--workhorse/internal/filestore/save_file_opts.go2
-rw-r--r--workhorse/internal/filestore/save_file_opts_test.go10
-rw-r--r--workhorse/internal/helper/helpers.go43
-rw-r--r--workhorse/internal/helper/raven.go58
-rw-r--r--workhorse/internal/imageresizer/image_resizer.go10
-rw-r--r--workhorse/internal/log/logging.go6
-rw-r--r--workhorse/internal/upstream/routes.go7
-rw-r--r--workhorse/internal/upstream/upstream.go3
-rw-r--r--workhorse/main.go5
-rw-r--r--workhorse/main_test.go6
-rw-r--r--workhorse/raven.go40
-rw-r--r--workhorse/upload_test.go96
-rw-r--r--yarn.lock2061
7915 files changed, 260125 insertions, 95521 deletions
diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 00000000000..3ae7766c325
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,16 @@
+#
+# This list of browsers is a conservative first definition, based on
+# https://docs.gitlab.com/ee/install/requirements.html#supported-web-browsers
+# with the following reasoning:
+#
+# - Edge: Pick the last two major version before the Chrome switch
+# - Rest: We should support the latest ESR of Firefox: 68, because it used quite a lot.
+# For the rest, pick browser versions that have a similar age to Firefox 68.
+#
+# See also this follow-up epic:
+# https://gitlab.com/groups/gitlab-org/-/epics/3957
+#
+chrome >= 73
+edge >= 17
+firefox >= 68
+safari >= 12
diff --git a/.eslintrc.yml b/.eslintrc.yml
index a764f749785..75c52ac1319 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -42,21 +42,50 @@ rules:
no-jquery/no-serialize: error
promise/always-return: off
promise/no-callback-in-promise: off
- "@gitlab/no-global-event-off": error
-
- # BEGIN eslint-plugin-vue@7 overrides
- # TODO: Remove these rules as part of
- # https://gitlab.com/groups/gitlab-org/-/epics/5142. These are setting
- # various vue lint rules as they were in eslint-plugin-vue@6, or disabling
- # new ones, to ease migration to v7, so violations of each can be fixed
- # separately.
- vue/no-mutating-props: off
- vue/one-component-per-file: off
- vue/no-lone-template: off
- vue/component-definition-name-casing: off
- # END eslint-plugin-vue@7 overrides
+ '@gitlab/no-global-event-off': error
+ import/order:
+ - error
+ - groups:
+ - builtin
+ - external
+ - internal
+ - parent
+ - sibling
+ - index
+ pathGroups:
+ - pattern: ~/**
+ group: internal
+ - pattern: emojis/**
+ group: internal
+ - pattern: '{ee_,}empty_states/**'
+ group: internal
+ - pattern: '{ee_,}icons/**'
+ group: internal
+ - pattern: '{ee_,}images/**'
+ group: internal
+ - pattern: vendor/**
+ group: internal
+ - pattern: shared_queries/**
+ group: internal
+ - pattern: '{ee_,}spec/**'
+ group: internal
+ - pattern: '{ee_,}jest/**'
+ group: internal
+ - pattern: ee_else_ce/**
+ group: internal
+ - pattern: ee/**
+ group: internal
+ - pattern: ee_component/**
+ group: internal
+ - pattern: '{test_,}helpers/**'
+ group: internal
+ - pattern: test_fixtures/**
+ group: internal
+ alphabetize:
+ order: asc
overrides:
- files:
- '**/spec/**/*'
rules:
- "@gitlab/require-i18n-strings": off
+ '@gitlab/require-i18n-strings': off
+ '@gitlab/no-runtime-template-compiler': off
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b41d7bcd34f..e38e2f765bd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,7 +17,7 @@ stages:
# in cases where jobs require Docker-in-Docker, the job
# definition must be extended with `.use-docker-in-docker`
default:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
tags:
- gitlab-org
# All jobs are interruptible by default
@@ -111,3 +111,4 @@ include:
- local: .gitlab/ci/dast.gitlab-ci.yml
- local: .gitlab/ci/workhorse.gitlab-ci.yml
- local: .gitlab/ci/graphql.gitlab-ci.yml
+ - local: .gitlab/ci/verify-lockfile.gitlab-ci.yml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index df81d05eec1..0d34eeccf8c 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -6,137 +6,128 @@
*.rb @gitlab-org/maintainers/rails-backend
*.rake @gitlab-org/maintainers/rails-backend
-[Documentation]
+[Documentation Directories]
/doc/ @gl-docsteam
-/doc/administration/monitoring/ @aqualls
+/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
+/doc/administration/geo/ @axil
+/doc/administration/gitaly/ @eread
+/doc/administration/integration/ @aqualls
+/doc/administration/lfs/ @aqualls
+/doc/administration/monitoring/ @ngaskill
+/doc/administration/operations/ @axil @eread @marcia
+/doc/administration/packages/ @ngaskill
+/doc/administration/postgresql/ @marcia
+/doc/administration/raketasks/ @axil @eread @mjang1
+/doc/administration/redis/ @axil
+/doc/administration/reference_architectures/ @axil
+/doc/administration/snippets/ @aqualls
+/doc/administration/troubleshooting @axil @marcia @mjang1
+/doc/ci/ @marcel.amirault @sselhorn
+/doc/ci/environments/ @axil
+/doc/ci/release/ @axil
+/doc/ci/services/ @sselhorn
+/doc/ci/test_cases/ @msedlakjakubowski
/doc/development/ @marcia @mjang1
/doc/development/documentation/ @cnorris
-/doc/ci @marcel.amirault @sselhorn
-/doc/operations @aqualls @eread
-/doc/user/clusters @aqualls
-/doc/user/infrastructure @aqualls
-/doc/user/project/clusters @aqualls
-/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
+/doc/gitlab-basics/ @marcia
+/doc/install/ @axil
+/doc/integration/ @aqualls @mjang1
+/doc/operations/ @ngaskill @axil
+/doc/push_rules/ @aqualls
+/doc/ssh/ @mjang1
+/doc/subscriptions/ @sselhorn
+/doc/topics/autodevops/ @ngaskill @marcia
+/doc/topics/git/ @aqualls
+/doc/update/ @axil @marcia
+/doc/user/analytics/ @mjang1 @ngaskill
+/doc/user/application_security @rdickenson
+/doc/user/clusters/ @marcia
+/doc/user/compliance/ @mjang1 @rdickenson
+/doc/user/group/ @mjang1 @msedlakjakubowski
+/doc/user/group/bulk_editing/ @msedlakjakubowski
+/doc/user/group/epics/ @msedlakjakubowski
+/doc/user/group/iterations/ @msedlakjakubowski
+/doc/user/group/roadmap/ @msedlakjakubowski
+/doc/user/infrastructure/ @marcia
+/doc/user/packages/ @ngaskill
+/doc/user/profile/ @mjang1 @msedlakjakubowski
+/doc/user/project/ @aqualls @axil @eread @mjang1 @msedlakjakubowski @ngaskill
+/doc/user/project/clusters/ @ngaskill
+/doc/user/project/import/ @mjang1 @msedlakjakubowski
+/doc/user/project/integrations/ @aqualls
+/doc/user/project/integrations/prometheus_library/ @ngaskill
+/doc/user/project/issues/ @msedlakjakubowski
+/doc/user/project/merge_requests/ @aqualls @eread
+/doc/user/project/milestones/ @msedlakjakubowski
+/doc/user/project/pages/ @axil
+/doc/user/project/repository/ @aqualls
+/doc/user/project/settings/ @mjang1 @aqualls
+/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
[Docs Create]
-/doc/user/project/merge_requests/allow_collaboration.md @marcia
-/doc/user/project/merge_requests/authorization_for_merge_requests.md @marcia
-/doc/user/project/merge_requests/cherry_pick_changes.md @marcia
-/doc/user/project/merge_requests/creating_merge_requests.md @marcia
-/doc/user/project/merge_requests/fast_forward_merge.md @marcia
-/doc/user/project/merge_requests/getting_started.md @marcia
-/doc/user/project/merge_requests/index.md @marcia
-/doc/user/project/merge_requests/merge_request_approvals.md @marcia
-/doc/user/project/merge_requests/merge_request_dependencies.md @marcia
-/doc/user/project/merge_requests/resolve_conflicts.md @marcia
-/doc/user/project/merge_requests/revert_changes.md @marcia
-/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md @marcia
-/doc/user/project/merge_requests/squash_and_merge.md @marcia
-/doc/user/project/merge_requests/work_in_progress_merge_requests.md @marcia
-/doc/user/project/repository/file_finder.md @marcia
-/doc/user/project/repository/forking_workflow.md @marcia
-/doc/user/project/repository/git_blame.md @marcia
-/doc/user/project/repository/git_history.md @marcia
-/doc/user/project/repository/index.md @marcia
-/doc/user/project/repository/repository_mirroring.md @marcia
-/doc/user/project/repository/web_editor.md @marcia
-/doc/user/project/autocomplete_characters.md @marcia
-/doc/user/project/badges.md @marcia
-/doc/user/project/code_intelligence.md @marcia
-/doc/user/project/code_owners.md @marcia
-/doc/user/project/file_lock.md @marcia
-/doc/user/project/git_attributes.md @marcia
-/doc/user/project/highlighting.md @marcia
-/doc/user/project/index.md @marcia
-/doc/user/project/protected_branches.md @marcia
-/doc/user/project/protected_tags.md @marcia
-/doc/user/project/push_options.md @marcia
-/doc/user/project/repository/branches/index.md @marcia
-/doc/user/project/repository/gpg_signed_commits/index.md @marcia
-/doc/user/project/repository/jupyter_notebooks/index.md @marcia
-/doc/user/project/repository/x509_signed_commits/index.md @marcia
-/doc/user/project/settings/import_export.md @marcia
-/doc/user/project/settings/index.md @marcia
-/doc/user/project/settings/project_access_tokens.md @marcia
-/doc/user/project/static_site_editor/index.md @marcia
-/doc/user/project/web_ide/index.md @marcia
-/doc/user/project/wiki/index.md @marcia
-/doc/gitlab-basics/README.md @marcia
-/doc/gitlab-basics/add-file.md @marcia
-/doc/gitlab-basics/command-line-commands.md @marcia
-/doc/gitlab-basics/create-branch.md @marcia
-/doc/gitlab-basics/create-project.md @marcia
-/doc/gitlab-basics/create-your-ssh-keys.md @marcia
-/doc/gitlab-basics/feature_branch_workflow.md @marcia
-/doc/gitlab-basics/fork-project.md @marcia
-/doc/gitlab-basics/start-using-git.md @marcia
-/doc/integration/sourcegraph.md @marcia
-/doc/intro/README.md @marcia
-/doc/push_rules/push_rules.md @marcia
-/doc/ssh/README.md @marcia
-/doc/topics/git/feature_branch_development.md @marcia
-/doc/topics/git/how_to_install_git/index.md @marcia
-/doc/topics/git/index.md @marcia
-/doc/topics/git/lfs/index.md @marcia
-/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md @marcia
-/doc/topics/git/numerous_undo_possibilities_in_git/index.md @marcia
-/doc/topics/git/partial_clone.md @marcia
-/doc/topics/git/troubleshooting_git.md @marcia
-/doc/topics/git/useful_git_commands.md @marcia
-/doc/topics/gitlab_flow.md @marcia
-/doc/user/index.md @marcia
-/doc/user/snippets.md @marcia
-/doc/administration/issue_closing_pattern.md @marcia
-/doc/user/asciidoc.md @marcia
-/doc/user/markdown.md @marcia
-/doc/user/search/advanced_global_search.md @marcia
-/doc/user/search/advanced_search_syntax.md @marcia
-/doc/user/search/index.md @marcia
-/doc/administration/file_hooks.md @marcia
-/doc/administration/git_annex.md @marcia
-/doc/administration/git_protocol.md @marcia
-/doc/administration/integration/plantuml.md @marcia
-/doc/administration/invalidate_markdown_cache.md @marcia
-/doc/administration/issue_closing_pattern.md @marcia
-/doc/administration/lfs/index.md @marcia
-/doc/administration/merge_request_diffs.md @marcia
-/doc/administration/repository_checks.md @marcia
-/doc/administration/snippets/index.md @marcia
-/doc/administration/static_objects_external_storage.md @marcia
-/doc/api/access_requests.md @marcia
-/doc/api/branches.md @marcia
-/doc/api/commits.md @marcia
-/doc/api/discussions.md @marcia
-/doc/api/group_wikis.md @marcia
-/doc/api/keys.md @marcia
-/doc/api/markdown.md @marcia
-/doc/api/merge_request_approvals.md @marcia
-/doc/api/merge_request_context_commits.md @marcia
-/doc/api/merge_requests.md @marcia
-/doc/api/project_aliases.md @marcia
-/doc/api/project_badges.md @marcia
-/doc/api/project_import_export.md @marcia
-/doc/api/project_level_variables.md @marcia
-/doc/api/project_snippets.md @marcia
-/doc/api/project_statistics.md @marcia
-/doc/api/project_templates.md @marcia
-/doc/api/project_vulnerabilities.md @marcia
-/doc/api/protected_branches.md @marcia
-/doc/api/protected_tags.md @marcia
-/doc/api/remote_mirrors.md @marcia
-/doc/api/repositories.md @marcia
-/doc/api/repository_files.md @marcia
-/doc/api/repository_submodules.md @marcia
-/doc/api/search.md @marcia
-/doc/api/snippets.md @marcia
-/doc/api/suggestions.md @marcia
-/doc/api/tags.md @marcia
-/doc/api/visual_review_discussions.md @marcia
-/doc/api/wikis.md @marcia
-/doc/user/admin_area/settings/account_and_limit_settings.md @marcia
-/doc/user/admin_area/settings/instance_template_repository.md @marcia
-/doc/user/admin_area/settings/push_event_activities_limit.md @marcia
-/doc/user/admin_area/settings/visibility_and_access_controls.md @marcia
+/doc/administration/file_hooks.md @aqualls
+/doc/administration/git_annex.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/static_objects_external_storage.md @aqualls
+/doc/api/access_requests.md @aqualls
+/doc/api/branches.md @aqualls
+/doc/api/commits.md @aqualls
+/doc/api/discussions.md @aqualls
+/doc/api/group_wikis.md @aqualls
+/doc/api/keys.md @aqualls
+/doc/api/markdown.md @aqualls
+/doc/api/merge_request_approvals.md @aqualls
+/doc/api/merge_request_context_commits.md @aqualls
+/doc/api/merge_requests.md @aqualls
+/doc/api/project_aliases.md @aqualls
+/doc/api/project_badges.md @aqualls
+/doc/api/project_import_export.md @aqualls
+/doc/api/project_level_variables.md @aqualls
+/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/protected_branches.md @aqualls
+/doc/api/protected_tags.md @aqualls
+/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/search.md @aqualls
+/doc/api/snippets.md @aqualls
+/doc/api/suggestions.md @aqualls
+/doc/api/tags.md @aqualls
+/doc/api/visual_review_discussions.md @aqualls
+/doc/api/wikis.md @aqualls
+/doc/intro/README.md @aqualls
+/doc/topics/gitlab_flow.md @aqualls
+/doc/user/admin_area/settings/account_and_limit_settings.md @aqualls
+/doc/user/admin_area/settings/instance_template_repository.md @aqualls
+/doc/user/admin_area/settings/push_event_activities_limit.md @aqualls
+/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
+/doc/user/asciidoc.md @aqualls
+/doc/user/index.md @aqualls
+/doc/user/markdown.md @aqualls
+/doc/user/project/autocomplete_characters.md @aqualls
+/doc/user/project/badges.md @aqualls
+/doc/user/project/code_intelligence.md @aqualls
+/doc/user/project/code_owners.md @aqualls
+/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/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/snippets.md @aqualls
[Frontend]
*.scss @annabeldunstone @gitlab-org/maintainers/frontend
@@ -173,7 +164,7 @@
/.gitlab/CODEOWNERS @gl-quality/eng-prod
Dangerfile @gl-quality/eng-prod
/danger/ @gl-quality/eng-prod
-/lib/gitlab/danger/ @gl-quality/eng-prod
+/tooling/danger/ @gl-quality/eng-prod
/scripts/ @gl-quality/eng-prod
/scripts/frontend/ @gl-quality/eng-prod @gitlab-org/maintainers/frontend
/scripts/review_apps/seed-dast-test-data.sh @dappelt @ngeorge1 @gl-quality/eng-prod
@@ -257,3 +248,21 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/usage_data.rb @gitlab-org/growth/product_intelligence/engineers
/lib/gitlab/cycle_analytics/usage_data.rb @gitlab-org/growth/product-intelligence/engineers
/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product-intelligence/engineers
+
+[Growth Experiments]
+/app/assets/javascripts/lib/utils/experimentation.js @gitlab-org/growth/experiment-devs
+/app/experiments/ @gitlab-org/growth/experiment-devs
+/app/models/experiment.rb @gitlab-org/growth/experiment-devs
+/app/models/experiment_subject.rb @gitlab-org/growth/experiment-devs
+/app/models/experiment_user.rb @gitlab-org/growth/experiment-devs
+/app/workers/experiments/ @gitlab-org/growth/experiment-devs
+/config/feature_flags/experiment/ @gitlab-org/growth/experiment-devs
+/ee/config/feature_flags/experiment/ @gitlab-org/growth/experiment-devs
+/ee/lib/api/experiments.rb @gitlab-org/growth/experiment-devs
+/ee/lib/ee/api/entities/experiment.rb @gitlab-org/growth/experiment-devs
+/lib/gitlab/experimentation/ @gitlab-org/growth/experiment-devs
+/lib/gitlab/experimentation.rb @gitlab-org/growth/experiment-devs
+/lib/gitlab/experimentation_logger.rb @gitlab-org/growth/experiment-devs
+
+[Legal]
+/config/dependency_decisions.yml @gitlab-org/legal-reviewers
diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml
index 269996dfd09..af735d3212a 100644
--- a/.gitlab/ci/cng.gitlab-ci.yml
+++ b/.gitlab/ci/cng.gitlab-ci.yml
@@ -1,6 +1,6 @@
cloud-native-image:
extends: .cng:rules
- image: ruby:2.7-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
dependencies: []
stage: post-test
variables:
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 955f44c6216..b42b32ea44d 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -2,7 +2,7 @@
extends:
- .default-retry
- .docs:rules:review-docs
- image: ruby:2.7-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: review
needs: []
variables:
@@ -66,13 +66,6 @@ docs-lint links:
- bundle exec nanoc
# Check the internal links
- bundle exec nanoc check internal_links
- # Delete the redirect files, rebuild, and check internal links again, to see if we are linking to redirects.
- # Don't delete the documentation/index.md, which is a false positive for the simple grep.
- - grep -rl "redirect_to:" /tmp/gitlab-docs/content/ee/ | grep -v "development/documentation/index.md" | xargs rm -f
- - bundle exec nanoc
- - echo -e "\e[1;96mThe following test fails when a doc links to a redirect file."
- - echo -e "\e[1;96mMake sure all links point to the correct page."
- - bundle exec nanoc check internal_links
# Check the internal anchor links
- bundle exec nanoc check internal_anchors
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index c87305cab18..1b4b8a12772 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -15,7 +15,7 @@
extends:
- .frontend-base
- .assets-compile-cache
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-git-2.29-lfs-2.9-node-12.18-yarn-1.22-graphicsmagick-1.3.34
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-git-2.29-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.34
variables:
WEBPACK_VENDOR_DLL: "true"
stage: prepare
@@ -259,13 +259,13 @@ coverage-frontend:
qa-frontend-node:10:
extends: .qa-frontend-node
- image: node:dubnium
+ image: ${GITLAB_DEPENDENCY_PROXY}node:dubnium
qa-frontend-node:latest:
extends:
- .qa-frontend-node
- .frontend:rules:qa-frontend-node-latest
- image: node:latest
+ image: ${GITLAB_DEPENDENCY_PROXY}node:latest
webpack-dev-server:
extends:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 355607c17ac..5de8a6bc250 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -16,15 +16,23 @@
- source scripts/utils.sh
- source scripts/prepare_build.sh
-.rails-cache:
+.setup-test-env-cache:
cache:
- key: "rails-v3"
+ key: "setup-test-env-v1"
paths:
- vendor/ruby/
- vendor/gitaly-ruby/
- .go/pkg/mod/
policy: pull
+.rails-cache:
+ cache:
+ key: "rails-v4"
+ paths:
+ - vendor/ruby/
+ - vendor/gitaly-ruby/
+ policy: pull
+
.static-analysis-cache:
cache:
key: "static-analysis-v2"
@@ -71,41 +79,41 @@
policy: pull
.use-pg11:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- - name: redis:4.0-alpine
+ - name: redis:5.0-alpine
variables:
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- - name: redis:4.0-alpine
+ - name: redis:5.0-alpine
variables:
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.34"
services:
- name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- - name: redis:4.0-alpine
- - name: elasticsearch:7.9.2
+ - name: redis:5.0-alpine
+ - name: elasticsearch:7.10.1
command: ["elasticsearch", "-E", "discovery.type=single-node"]
variables:
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-golang-1.14-git-2.29-lfs-2.9-chrome-85-node-12.18-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.14-git-2.29-lfs-2.9-chrome-87-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.34"
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- - name: redis:4.0-alpine
- - name: elasticsearch:7.9.2
+ - name: redis:5.0-alpine
+ - name: elasticsearch:7.10.1
command: ["elasticsearch", "-E", "discovery.type=single-node"]
variables:
POSTGRES_HOST_AUTH_METHOD: trust
@@ -124,7 +132,7 @@
FOSS_ONLY: '1'
.use-docker-in-docker:
- image: docker:${DOCKER_VERSION}
+ image: ${GITLAB_DEPENDENCY_PROXY}docker:${DOCKER_VERSION}
services:
- docker:${DOCKER_VERSION}-dind
variables:
diff --git a/.gitlab/ci/notify.gitlab-ci.yml b/.gitlab/ci/notify.gitlab-ci.yml
index e18a092bb8f..a8c156c7dba 100644
--- a/.gitlab/ci/notify.gitlab-ci.yml
+++ b/.gitlab/ci/notify.gitlab-ci.yml
@@ -1,5 +1,5 @@
.notify-slack:
- image: alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}alpine
stage: notify
dependencies: []
cache: {}
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 1dc403c9d06..788b482f0a6 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -47,7 +47,7 @@ update-qa-cache:
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.package-and-qa-base:
- image: ruby:2.7-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: qa
retry: 0
script:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index a2a16424f4a..22aa92779ea 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -141,6 +141,7 @@
setup-test-env:
extends:
- .rails-job-base
+ - .setup-test-env-cache
- .rails:rules:default-refs-code-backstage-qa
- .use-pg11
stage: prepare
@@ -180,11 +181,19 @@ setup-test-env:
- tmp/tests/second_storage/
when: always
-update-rails-cache:
+update-setup-test-env-cache:
extends:
- setup-test-env
- .shared:rules:update-cache
- artifacts: {} # This job's purpose is only to update the cache.
+ artifacts:
+ paths: [] # This job's purpose is only to update the cache.
+ cache:
+ policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
+
+update-rails-cache:
+ extends:
+ - update-setup-test-env-cache
+ - .rails-cache
cache:
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
@@ -376,6 +385,17 @@ db:rollback:
- bundle exec rake db:migrate VERSION=20181228175414
- bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
+db:gitlabcom-database-testing:
+ extends: .rails:rules:db:gitlabcom-database-testing
+ stage: test
+ image: ruby:2.7-alpine
+ needs: []
+ allow_failure: true
+ script:
+ - source scripts/utils.sh
+ - install_gitlab_gem
+ - ./scripts/trigger-build gitlab-com-database-testing
+
gitlab:setup:
extends: .db-job-base
variables:
@@ -433,6 +453,8 @@ rspec:deprecations:
variables:
SETUP_DB: "false"
script:
+ - grep -h -R "keyword" deprecations/ | awk '{$1=$1};1' | sort | uniq -c | sort
+ - grep -R "keyword" deprecations/ | wc
- run_timed_command "bundle exec rubocop --only Lint/LastKeywordArgument --parallel"
artifacts:
expire_in: 31d
@@ -482,7 +504,6 @@ rspec:feature-flags:
- .coverage-base
- .rails:rules:rspec-feature-flags
stage: post-test
- allow_failure: true
# We cannot use needs since it would mean needing 84 jobs (since most are parallelized)
# so we use `dependencies` here.
dependencies:
@@ -502,7 +523,11 @@ rspec:feature-flags:
- memory-on-boot
script:
- run_timed_command "bundle install --jobs=$(nproc) --path=vendor --retry=3 --quiet --without default development test production puma unicorn kerberos metrics omnibus ed25519"
- - 'run_timed_command "bundle exec scripts/used-feature-flags" || (scripts/slack master-broken "â˜ ï¸ \`${CI_JOB_NAME}\` failed! â˜ ï¸ See ${CI_JOB_URL}" ci_failing "GitLab Bot" && exit 1)'
+ - if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
+ run_timed_command "bundle exec scripts/used-feature-flags" || (scripts/slack master-broken "â˜ ï¸ \`${CI_JOB_NAME}\` failed! â˜ ï¸ See ${CI_JOB_URL}" ci_failing "GitLab Bot" && exit 1);
+ else
+ run_timed_command "bundle exec scripts/used-feature-flags";
+ fi
# EE/FOSS: default refs (MRs, master, schedules) jobs #
#######################################################
diff --git a/.gitlab/ci/releases.gitlab-ci.yml b/.gitlab/ci/releases.gitlab-ci.yml
index b3f961afe62..77f23814f3c 100644
--- a/.gitlab/ci/releases.gitlab-ci.yml
+++ b/.gitlab/ci/releases.gitlab-ci.yml
@@ -4,7 +4,7 @@
.merge-train-sync:
# We don't need/want any global before/after commands, so we overwrite these
# settings.
- image: alpine:edge
+ image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
stage: sync
before_script:
- apk add --no-cache --update curl bash jq
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index b7d9f18dcb4..c18e898dc12 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -25,7 +25,7 @@ review-build-cng:
extends:
- .default-retry
- .review:rules:review-build-cng
- image: ruby:2.7-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: review-prepare
before_script:
- source ./scripts/utils.sh
@@ -199,7 +199,7 @@ review-performance:
parallel-spec-reports:
extends:
- .review:rules:mr-only-manual
- image: ruby:2.7-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: post-qa
dependencies: ["review-qa-all"]
variables:
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 5e8cdf0daaf..1eafd024f5e 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -112,6 +112,7 @@
.workhorse-patterns: &workhorse-patterns
- "GITLAB_WORKHORSE_VERSION"
- "workhorse/**/*"
+ - ".gitlab/ci/workhorse.gitlab-ci.yml"
.yaml-lint-patterns: &yaml-lint-patterns
- ".gitlab-ci.yml"
@@ -123,9 +124,12 @@
- ".gitlab/route-map.yml"
- "doc/**/*"
- ".markdownlint.json"
+ - "scripts/lint-doc.sh"
.frontend-dependency-patterns: &frontend-dependency-patterns
- "{package.json,yarn.lock}"
+ - "config/webpack.config.js"
+ - "config/helpers/*.js"
.frontend-patterns: &frontend-patterns
- "{package.json,yarn.lock}"
@@ -523,6 +527,13 @@
changes: *db-patterns
- <<: *if-merge-request-title-run-all-rspec
+.rails:rules:db:gitlabcom-database-testing:
+ rules:
+ - if: '$GITLABCOM_DATABASE_TESTING_TRIGGER_TOKEN == null'
+ when: never
+ - <<: *if-merge-request
+ changes: *db-patterns
+
.rails:rules:ee-and-foss-unit:
rules:
- changes: *backend-patterns
@@ -869,6 +880,7 @@
- <<: *if-not-ee
when: never
- <<: *if-master-schedule-2-hourly
+ allow_failure: true
- <<: *if-merge-request-title-run-all-rspec
.rails:rules:master-schedule-nightly--code-backstage:
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index 74510a0a03a..27b68115edc 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -26,7 +26,7 @@ cache gems:
dont-interrupt-me:
extends: .setup:rules:dont-interrupt-me
stage: sync
- image: alpine:edge
+ image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
interruptible: false
variables:
GIT_STRATEGY: none
@@ -52,7 +52,7 @@ no_ee_check:
verify-tests-yml:
extends:
- .setup:rules:verify-tests-yml
- image: ruby:2.7-alpine
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
stage: test
needs: []
script:
@@ -61,7 +61,7 @@ verify-tests-yml:
- scripts/verify-tff-mapping
.detect-test-base:
- image: ruby:2.7
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7
needs: []
stage: prepare
script:
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index aec0a1640f1..b90c02c08ef 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -1,5 +1,5 @@
.tests-metadata-state:
- image: ruby:2.7
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7
before_script:
- source scripts/utils.sh
artifacts:
diff --git a/.gitlab/ci/verify-lockfile.gitlab-ci.yml b/.gitlab/ci/verify-lockfile.gitlab-ci.yml
new file mode 100644
index 00000000000..6336a428b4b
--- /dev/null
+++ b/.gitlab/ci/verify-lockfile.gitlab-ci.yml
@@ -0,0 +1,11 @@
+verify_lockfile:
+ stage: test
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2-git-2.29-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.34
+ needs: []
+ rules:
+ - changes:
+ - yarn.lock
+ script:
+ - npm config set @dappelt:registry https://gitlab.com/api/v4/projects/22564149/packages/npm/
+ - npx lockfile-lint@4.3.7 --path yarn.lock --allowed-hosts yarn --validate-https
+ - npx @dappelt/untamper-my-lockfile --lockfile yarn.lock
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index 29131159876..a40eebd131b 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -1,6 +1,6 @@
workhorse:
extends: .workhorse:rules:workhorse
- image: golang:1.14
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.14
stage: test
needs: []
script:
@@ -8,3 +8,39 @@ workhorse:
- git checkout .
- scripts/update-workhorse check
- make -C workhorse
+
+workhorse:verify:
+ extends: .workhorse:rules:workhorse
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.15
+ stage: test
+ needs: []
+ script:
+ - make -C workhorse verify
+
+.workhorse:test:
+ extends: .workhorse:rules:workhorse
+ services:
+ - name: registry.gitlab.com/gitlab-org/build/cng/gitaly:latest
+ # Disable the hooks so we don't have to stub the GitLab API
+ command: ["/usr/bin/env", "GITALY_TESTING_NO_GIT_HOOKS=1", "/scripts/process-wrapper"]
+ alias: gitaly
+ variables:
+ GITALY_ADDRESS: "tcp://gitaly:8075"
+ stage: test
+ needs: []
+ script:
+ - go version
+ - apt-get update && apt-get -y install libimage-exiftool-perl
+ - make -C workhorse test
+
+workhorse:test using go 1.13:
+ extends: .workhorse:test
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.13
+
+workhorse:test using go 1.14:
+ extends: .workhorse:test
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.14
+
+workhorse:test using go 1.15:
+ extends: .workhorse:test
+ image: ${GITLAB_DEPENDENCY_PROXY}golang:1.15
diff --git a/.gitlab/issue_templates/Actionable Insight.md b/.gitlab/issue_templates/Actionable Insight.md
new file mode 100644
index 00000000000..df519f81799
--- /dev/null
+++ b/.gitlab/issue_templates/Actionable Insight.md
@@ -0,0 +1,28 @@
+<!-- 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. Learn more in the handbook here: https://about.gitlab.com/handbook/engineering/ux/ux-research-training/research-insights/#actionable-insights -->
+
+### 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
+<!--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. -->
+
+- :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
+- [ ] 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.
+
+
+
+
+/label ~"Actionable Insight"
+
diff --git a/.gitlab/issue_templates/Adoption Engineering.md b/.gitlab/issue_templates/Adoption Engineering.md
new file mode 100644
index 00000000000..01e9d0ea033
--- /dev/null
+++ b/.gitlab/issue_templates/Adoption Engineering.md
@@ -0,0 +1,14 @@
+#Design
+<!-- This should include the contexts that determine the reproducibility (stickiness) of an experiment. This means that if you want the same behavior for a user, the context would be user, or if you want all users when viewing a specific project, the context would be the project being viewed, etc. -->
+
+
+#Rollout strategy
+<!-- This is currently called A/B test, which isn't accurate for multi-variants. Let's call this rollout strategy. It should outline the percentages for variants and if there's more than one step to this, each of those steps and the timing for those steps (e.g. 30 days after initial rollout). -->
+
+#Inclusions and exclusions
+<!-- These would be the rules for which given context (and are limited to context or resolvable at experiment time details) is included or excluded from the test. An example of this would be to only run an experiment on groups less than N number of days old. -->
+
+#Segmentation
+<!-- Rules for always saying context with these criteria always get this variant. For instance, if you want to always give groups less than N number of days old the experiment experience, they are specified here. This is different from the exclusion rules above. -->
+
+#Tracking
diff --git a/.gitlab/issue_templates/Basic Proposal.md b/.gitlab/issue_templates/Basic Proposal.md
index 4232561354c..8d47e87f8a3 100644
--- a/.gitlab/issue_templates/Basic Proposal.md
+++ b/.gitlab/issue_templates/Basic Proposal.md
@@ -6,6 +6,6 @@
<!-- Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.
-/label ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Starter"/~"GitLab Premium"/~"GitLab Ultimate"
+/label ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
-->
diff --git a/.gitlab/issue_templates/Dogfooding.md b/.gitlab/issue_templates/Dogfooding.md
new file mode 100644
index 00000000000..d780fbd3f1f
--- /dev/null
+++ b/.gitlab/issue_templates/Dogfooding.md
@@ -0,0 +1,17 @@
+<!--Lightweight issue template to encourage Dogfooding and educate team members about the importance of Dogfooding -->
+
+/label ~"dogfooding" ~"group::" ~"section::" ~"Category::"
+
+## Feature to Dogfood
+<!--Link to Description of feature (Documentation, Epic, Opportunity Canvas, etc.) -->
+
+## Goals
+<!--Level of Dogfooding you are looking for: problem validation, testing, production usage, etc -->
+
+## Progress Tracker
+<!--List of tasks (e.g. a table with columns, project, status, issue links similar to what is [done here](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/8499))-->
+
+## Why Dogfooding is Important
+- https://about.gitlab.com/handbook/values/#dogfooding
+- https://about.gitlab.com/handbook/product/product-processes/#dogfood-everything
+- https://about.gitlab.com/handbook/engineering/#dogfooding
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index 67686b654bd..615fb644967 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -31,7 +31,6 @@ If applicable, any groups/projects that are happy to have this feature turned on
## Roll Out Steps
-- [ ] Confirm that QA tests pass with the feature flag enabled (if you're unsure how, contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors))
- [ ] Enable on staging (`/chatops run feature set feature_name true --staging`)
- [ ] Test on staging
- [ ] Ensure that documentation has been updated
@@ -42,7 +41,7 @@ If applicable, any groups/projects that are happy to have this feature turned on
- [ ] Enable on GitLab.com by running chatops command in `#production` (`/chatops run feature set feature_name true`)
- [ ] Cross post chatops Slack command to `#support_gitlab-com` ([more guidance when this is necessary in the dev docs](https://docs.gitlab.com/ee/development/feature_flags/controls.html#where-to-run-commands)) and in your team channel
- [ ] Announce on the issue that the flag has been enabled
-- [ ] Remove feature flag and add changelog entry
+- [ ] Remove feature flag and add changelog entry. Ensure that the feature flag definition YAML file has been removed in the **same MR** that is removing the feature flag from the code
- [ ] After the flag removal is deployed, [clean up the feature flag](https://docs.gitlab.com/ee/development/feature_flags/controls.html#cleaning-up) by running chatops command in `#production` channel
## Rollback Steps
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 66450c37a22..2cdf2341c88 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -61,7 +61,7 @@ Consider adding checkboxes and expectations of users with certain levels of memb
<!-- See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/workflow.html#for-a-product-change
-* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
+* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/workflow.html
* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html -->
### Availability & Testing
@@ -97,7 +97,7 @@ Create tracking issue using the the Snowplow event tracking template. See https:
### What is the type of buyer?
<!-- What is the buyer persona for this feature? See https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/buyer-persona/
-In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#four-tiers -->
+In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#three-tiers -->
### Is this a cross-stage feature?
@@ -111,5 +111,5 @@ Use the following resources to find the appropriate labels:
- https://about.gitlab.com/handbook/product/categories/features/
-->
/label ~devops:: ~group: ~Category:
-
+/label ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
/label ~feature
diff --git a/.gitlab/issue_templates/Lean Feature Proposal.md b/.gitlab/issue_templates/Lean Feature Proposal.md
index 44210a89023..fb9ac306f31 100644
--- a/.gitlab/issue_templates/Lean Feature Proposal.md
+++ b/.gitlab/issue_templates/Lean Feature Proposal.md
@@ -14,7 +14,7 @@
-/label ~"feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Starter"/~"GitLab Premium"/~"GitLab Ultimate"
+/label ~"feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
<!--- Use the following resources to find the appropriate labels:
@@ -73,7 +73,7 @@ Consider adding checkboxes and expectations of users with certain levels of memb
See the Feature Change Documentation Workflow https://docs.gitlab.com/ee/development/documentation/workflow.html#for-a-product-change
-* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/feature-change-workflow.html#documentation-requirements
+* Add all known Documentation Requirements in this section. See https://docs.gitlab.com/ee/development/documentation/workflow.html
* If this feature requires changing permissions, update the permissions document. See https://docs.gitlab.com/ee/user/permissions.html
### Availability & Testing
@@ -96,7 +96,7 @@ Define both the success metrics and acceptance criteria. Note that success metri
### What is the type of buyer?
What is the buyer persona for this feature? See https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/buyer-persona/
-In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#four-tiers
+In which enterprise tier should this feature go? See https://about.gitlab.com/handbook/product/pricing/#three-tiers
### Is this a cross-stage feature?
diff --git a/.gitlab/issue_templates/Query Performance Investigation.md b/.gitlab/issue_templates/Query Performance Investigation.md
new file mode 100644
index 00000000000..3f2a6361d64
--- /dev/null
+++ b/.gitlab/issue_templates/Query Performance Investigation.md
@@ -0,0 +1,39 @@
+## Description
+
+As the name implies, the purpose of the template is to detail underperforming queries for futher investigation.
+
+### Steps
+
+- [ ] Rename the issue to - `Query Performance Investigation - [Query Snippet | Table info]`
+ - For example - `Query Performance Investigation - SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."id" = $1 LIMIT $2`
+- [ ] Provide information in the Requested Data Points table
+- [ ] Provide [priority and severity labels](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#availability)
+- [ ] If this requires immediate attention cc `@gitlab-org/database-team` and reach out in the #g_database slack channel
+
+### Requested Data points
+
+Please provide as many of these fields as possible when submitting a query performance report.
+
+- TPS
+- Duration
+- Source of calls (Sidekiq, WebAPI, etc)
+- Query ID
+- SQL Statement
+- Query Plan
+- Query Example
+- Total number of calls (relative)
+- % of Total time
+
+<!--
+
+- Example of a postgres checkup report - https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/snippets/2056787
+- Epic - Improving the Database resource usage (&365) - https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/365#short-term-query-improvements
+- Past examples of query performance investigations that have led to this template creation.
+ - Possible Index suggestion or query rewriting (#292454) - https://gitlab.com/gitlab-org/gitlab/-/issues/292454)
+ - High number of Sessions to the database with the value SET parameter (#292022) - https://gitlab.com/gitlab-org/gitlab/-/issues/292022)
+ - Query performance "Select 1" (#220055) - https://gitlab.com/gitlab-org/gitlab/-/issues/220055
+ - Select statements that are in execution during database CPU utilization peak times - licenses table (#292900) - https://gitlab.com/gitlab-org/gitlab/-/issues/292900
+
+-->
+
+/label ~"group::database" ~"database::triage"
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index 3de004b0319..beb066cdfc4 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -1,7 +1,7 @@
<!--
# Read me first!
-Create this issue under https://gitlab.com/gitlab-org/security
+Create this issue under https://gitlab.com/gitlab-org/security/gitlab
Set the title to: `Description of the original issue`
-->
diff --git a/.gitlab/issue_templates/actionable_insight.md b/.gitlab/issue_templates/actionable_insight.md
deleted file mode 100644
index ff6a4f12918..00000000000
--- a/.gitlab/issue_templates/actionable_insight.md
+++ /dev/null
@@ -1,34 +0,0 @@
-## Actionable Insights
-Actionable insights always have a follow-up action that needs to take place as a result of the research observation or data, and a clear recommendation or action associated with it. An actionable insight both defines the insight and clearly calls out the next step. These insights are tracked over time and at the group level.
-
-#### Link
-
-- [ ] Provide the link to the Dovetail actionable insight you created earlier (this should contain all the essential details)
-- [ ] If applicable, link this actionable insight issue back to the original Research Issue in the GitLab UX Research project
-
-#### Assign
-
-- [ ] Assign this issue to the appropriate Product Manager, Product Designer, or UX Researcher
-
-#### Group label
-
-- [ ] Add the appropriate `Group` (such as `~"group::source code"`) label to the issue. This is done to identify and track actionable insights at the group level.
-
-#### Description
-
-- [ ] Provide some brief details on the actionable insight and the action to take
-
--------------------------------------------------------------------------------
-
-| | PLEASE COMPLETE THE BELOW |
-| ------ | ------ |
-| Dovetail link: | (URL goes here) |
-| Details: | (details go here) |
-| Action to take: | (action goes here) |
-
-
-
-
-
-
-/label ~"Actionable Insight"
diff --git a/.gitlab/merge_request_templates/Change Documentation Location.md b/.gitlab/merge_request_templates/Change Documentation Location.md
index 1197c6adc40..0c675d8d0c6 100644
--- a/.gitlab/merge_request_templates/Change Documentation Location.md
+++ b/.gitlab/merge_request_templates/Change Documentation Location.md
@@ -8,9 +8,7 @@
## Related issues
-<!-- Mention the issue(s) this MR closes or is related to -->
-
-Closes
+<!-- Link related issues below. -->
## Moving docs to a new location?
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 9113bf7d028..0c507277ede 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -11,7 +11,7 @@
## Related issues
-<!-- Link related issues below. Insert the issue link or reference after the word "Closes" if merging this should automatically close it. -->
+<!-- Link related issues below. -->
## Author's checklist (required)
@@ -31,13 +31,13 @@ When applicable:
- [ ] Update the [permissions table](https://docs.gitlab.com/ee/user/permissions.html).
- [ ] Link docs to and from the higher-level index page, plus other related docs where helpful.
-- [ ] Add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) accordingly.
-- [ ] Add [GitLab's version history note(s)](https://docs.gitlab.com/ee/development/documentation/styleguide.html#text-for-documentation-requiring-version-text).
+- [ ] Add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#product-tier-badges) accordingly.
+- [ ] Add [GitLab's version history note(s)](https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#gitlab-versions).
- [ ] Add/update the [feature flag section](https://docs.gitlab.com/ee/development/documentation/feature_flags.html).
## Review checklist
-All reviewers can help ensure accuracy, clarity, completeness, and adherence to the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
+All reviewers can help ensure accuracy, clarity, completeness, and adherence to the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide/).
**1. Primary Reviewer**
diff --git a/.gitlab/merge_request_templates/New Static Analysis Check.md b/.gitlab/merge_request_templates/New Static Analysis Check.md
index 5fd2d31767a..66041a784e8 100644
--- a/.gitlab/merge_request_templates/New Static Analysis Check.md
+++ b/.gitlab/merge_request_templates/New Static Analysis Check.md
@@ -1,3 +1,8 @@
+<!--
+When creating a new cop that could be applied to multiple applications,
+we encourage you to add it to https://gitlab.com/gitlab-org/gitlab-styles gem.
+-->
+
## Description of the proposal
<!--
diff --git a/.gitpod.yml b/.gitpod.yml
index dc1dbc1472d..950b06b40e7 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -13,7 +13,10 @@ tasks:
(
set -e
cd /workspace/gitlab-development-kit
- [[ ! -L /workspace/gitlab-development-kit/gitlab ]] && ln -fs /workspace/gitlab /workspace/gitlab-development-kit/gitlab
+ # GitLab FOSS
+ [[ -d /workspace/gitlab-foss ]] && ln -fs /workspace/gitlab-foss /workspace/gitlab-development-kit/gitlab
+ # GitLab
+ [[ -d /workspace/gitlab ]] && ln -fs /workspace/gitlab /workspace/gitlab-development-kit/gitlab
mv /workspace/gitlab-development-kit/secrets.yml /workspace/gitlab-development-kit/gitlab/config
# reconfigure GDK
echo "$(date) – Reconfiguring GDK" | tee -a /workspace/startup.log
@@ -21,7 +24,6 @@ tasks:
# run DB migrations
echo "$(date) – Running DB migrations" | tee -a /workspace/startup.log
make gitlab-db-migrate
- cd -
# stop GDK
echo "$(date) – Stopping GDK" | tee -a /workspace/startup.log
gdk stop
@@ -47,9 +49,11 @@ tasks:
if [ "$GITLAB_RUN_DB_MIGRATIONS" == true ]; then
make gitlab-db-migrate
fi
- cd ../gitlab
+ cd /workspace/gitlab-development-kit/gitlab
+ # Install Lefthook
+ bundle exec lefthook install
git checkout db/structure.sql
- cd ../gitlab-development-kit
+ cd /workspace/gitlab-development-kit
# Waiting for GitLab ...
gp await-port 3000
printf "Waiting for GitLab at $(gp url 3000) ..."
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index bb546632335..5b92863b91e 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -109,7 +109,6 @@ linters:
- 'app/views/groups/runners/edit.html.haml'
- 'app/views/groups/settings/_advanced.html.haml'
- 'app/views/groups/settings/_lfs.html.haml'
- - 'app/views/help/_shortcuts.html.haml'
- 'app/views/help/index.html.haml'
- 'app/views/help/instance_configuration.html.haml'
- 'app/views/help/instance_configuration/_gitlab_ci.html.haml'
@@ -161,7 +160,6 @@ linters:
- 'app/views/projects/_gitlab_import_modal.html.haml'
- 'app/views/projects/_home_panel.html.haml'
- 'app/views/projects/_import_project_pane.html.haml'
- - 'app/views/projects/_issuable_by_email.html.haml'
- 'app/views/projects/_readme.html.haml'
- 'app/views/projects/artifacts/_artifact.html.haml'
- 'app/views/projects/artifacts/_tree_file.html.haml'
diff --git a/.nvmrc b/.nvmrc
index ce122aaa988..c91434ab584 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-12.18.4
+14.15.4
diff --git a/.rubocop.yml b/.rubocop.yml
index 4a0cd9579e6..7a4b53b5aa5 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -78,21 +78,7 @@ Style/AccessModifierDeclarations:
# Frozen String Literal
Style/FrozenStringLiteralComment:
Enabled: true
- Exclude:
- - 'config.ru'
- - 'Dangerfile'
- - 'Gemfile'
- - 'Rakefile'
- - 'app/views/**/*'
- - 'config/**/*'
- - 'danger/**/*'
- - 'db/**/*'
- - 'ee/db/**/*'
- - 'ee/lib/tasks/**/*'
- - 'lib/tasks/**/*'
- - 'qa/**/*'
- - 'rubocop/**/*'
- - 'scripts/**/*'
+ EnforcedStyle: always_true
RSpec/FilePath:
Exclude:
@@ -256,7 +242,7 @@ Gitlab/Json:
- 'scripts/**/*'
- 'lib/rspec_flaky/**/*'
- 'lib/quality/**/*'
- - 'lib/gitlab/danger/**/*'
+ - 'tooling/danger/**/*'
Gitlab/AvoidUploadedFileFromParams:
Enabled: true
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index cdf7f79412b..477d9adec40 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -25,83 +25,11 @@ FactoryBot/InlineAssociation:
- 'spec/factories/go_modules.rb'
- 'spec/factories/group_group_links.rb'
- 'spec/factories/import_export_uploads.rb'
- - 'spec/factories/notes.rb'
- 'spec/factories/uploads.rb'
- 'spec/factories/wiki_pages.rb'
-InternalAffairs/DeprecateCopHelper:
+InternalAffairs/DeprecateCopHelper: # issue to resolve: https://gitlab.com/gitlab-org/gitlab/-/issues/276734
Exclude:
- - 'spec/rubocop/code_reuse_helpers_spec.rb'
- - 'spec/rubocop/qa_helpers_spec.rb'
- - 'spec/rubocop/migration_helpers_spec.rb'
- - 'spec/rubocop/cop/group_public_or_visible_to_user_spec.rb'
- - 'spec/rubocop/cop/static_translation_definition_spec.rb'
- - 'spec/rubocop/cop/lint/last_keyword_argument_spec.rb'
- - 'spec/rubocop/cop/usage_data/large_table_spec.rb'
- - 'spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb'
- - 'spec/rubocop/cop/filename_length_spec.rb'
- - 'spec/rubocop/cop/put_project_routes_under_scope_spec.rb'
- - 'spec/rubocop/cop/gitlab/rails_logger_spec.rb'
- - 'spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb'
- - 'spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb'
- - 'spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb'
- - 'spec/rubocop/cop/gitlab/bulk_insert_spec.rb'
- - 'spec/rubocop/cop/gitlab/intersect_spec.rb'
- - 'spec/rubocop/cop/gitlab/json_spec.rb'
- - 'spec/rubocop/cop/gitlab/httparty_spec.rb'
- - 'spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb'
- - 'spec/rubocop/cop/gitlab/except_spec.rb'
- - 'spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb'
- - 'spec/rubocop/cop/gitlab/change_timezone_spec.rb'
- - 'spec/rubocop/cop/gitlab/predicate_memoization_spec.rb'
- - 'spec/rubocop/cop/gitlab/union_spec.rb'
- - 'spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb'
- - 'spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb'
- - 'spec/rubocop/cop/active_record_association_reload_spec.rb'
- - 'spec/rubocop/cop/ban_catch_throw_spec.rb'
- - 'spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb'
- - 'spec/rubocop/cop/avoid_becomes_spec.rb'
- - 'spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb'
- - 'spec/rubocop/cop/qa/element_with_pattern_spec.rb'
- - 'spec/rubocop/cop/inject_enterprise_edition_module_spec.rb'
- - 'spec/rubocop/cop/code_reuse/finder_spec.rb'
- - 'spec/rubocop/cop/code_reuse/worker_spec.rb'
- - 'spec/rubocop/cop/code_reuse/service_class_spec.rb'
- - 'spec/rubocop/cop/code_reuse/presenter_spec.rb'
- - 'spec/rubocop/cop/code_reuse/serializer_spec.rb'
- - 'spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb'
- - 'spec/rubocop/cop/default_scope_spec.rb'
- - 'spec/rubocop/cop/graphql/resolver_type_spec.rb'
- - 'spec/rubocop/cop/graphql/descriptions_spec.rb'
- - 'spec/rubocop/cop/graphql/json_type_spec.rb'
- - 'spec/rubocop/cop/graphql/gid_expected_type_spec.rb'
- - 'spec/rubocop/cop/graphql/authorize_types_spec.rb'
- - 'spec/rubocop/cop/graphql/id_type_spec.rb'
- - 'spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb'
- - 'spec/rubocop/cop/scalability/idempotent_worker_spec.rb'
- - 'spec/rubocop/cop/scalability/cron_worker_context_spec.rb'
- - 'spec/rubocop/cop/scalability/file_uploads_spec.rb'
- - 'spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb'
- - 'spec/rubocop/cop/api/base_spec.rb'
- - 'spec/rubocop/cop/destroy_all_spec.rb'
- - 'spec/rubocop/cop/safe_params_spec.rb'
- - 'spec/rubocop/cop/include_sidekiq_worker_spec.rb'
- - 'spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb'
- - 'spec/rubocop/cop/rspec/timecop_freeze_spec.rb'
- - 'spec/rubocop/cop/rspec/any_instance_of_spec.rb'
- - 'spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb'
- - 'spec/rubocop/cop/rspec/top_level_describe_path_spec.rb'
- - 'spec/rubocop/cop/rspec/be_success_matcher_spec.rb'
- - 'spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb'
- - 'spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb'
- - 'spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb'
- - 'spec/rubocop/cop/rspec/have_gitlab_http_status_spec.rb'
- - 'spec/rubocop/cop/rspec/timecop_travel_spec.rb'
- - 'spec/rubocop/cop/rspec/env_assignment_spec.rb'
- - 'spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb'
- - 'spec/rubocop/cop/performance/ar_count_each_spec.rb'
- - 'spec/rubocop/cop/performance/readlines_each_spec.rb'
- - 'spec/rubocop/cop/project_path_helper_spec.rb'
- 'spec/rubocop/cop/migration/safer_boolean_column_spec.rb'
- 'spec/rubocop/cop/migration/remove_index_spec.rb'
- 'spec/rubocop/cop/migration/add_index_spec.rb'
@@ -246,7 +174,6 @@ Rails/SaveBang:
- 'ee/spec/services/start_pull_mirroring_service_spec.rb'
- 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
- 'ee/spec/services/todo_service_spec.rb'
- - 'ee/spec/services/update_build_minutes_service_spec.rb'
- 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
- 'ee/spec/support/protected_tags/access_control_shared_examples.rb'
- 'ee/spec/support/shared_examples/features/protected_branches_access_control_shared_examples.rb'
@@ -764,194 +691,6 @@ RSpec/TimecopTravel:
- 'spec/workers/concerns/reenqueuer_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
-Graphql/Descriptions:
- Exclude:
- - 'app/graphql/types/access_level_type.rb'
- - 'app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb'
- - 'app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb'
- - 'app/graphql/types/alert_management/alert_status_counts_type.rb'
- - 'app/graphql/types/alert_management/alert_type.rb'
- - 'app/graphql/types/alert_management/integration_type.rb'
- - 'app/graphql/types/award_emojis/award_emoji_type.rb'
- - 'app/graphql/types/board_list_type.rb'
- - 'app/graphql/types/board_type.rb'
- - 'app/graphql/types/boards/board_issue_input_base_type.rb'
- - 'app/graphql/types/boards/board_issue_input_type.rb'
- - 'app/graphql/types/branch_type.rb'
- - 'app/graphql/types/ci/analytics_type.rb'
- - 'app/graphql/types/ci/config/config_type.rb'
- - 'app/graphql/types/ci/config/group_type.rb'
- - 'app/graphql/types/ci/config/job_type.rb'
- - 'app/graphql/types/ci/config/need_type.rb'
- - 'app/graphql/types/ci/config/stage_type.rb'
- - 'app/graphql/types/ci/detailed_status_type.rb'
- - 'app/graphql/types/ci/group_type.rb'
- - 'app/graphql/types/ci/job_artifact_type.rb'
- - 'app/graphql/types/ci/job_type.rb'
- - 'app/graphql/types/ci/pipeline_type.rb'
- - 'app/graphql/types/ci/runner_architecture_type.rb'
- - 'app/graphql/types/ci/runner_platform_type.rb'
- - 'app/graphql/types/ci/runner_setup_type.rb'
- - 'app/graphql/types/ci/stage_type.rb'
- - 'app/graphql/types/ci/status_action_type.rb'
- - 'app/graphql/types/commit_action_type.rb'
- - 'app/graphql/types/commit_type.rb'
- - 'app/graphql/types/container_expiration_policy_type.rb'
- - 'app/graphql/types/container_repository_details_type.rb'
- - 'app/graphql/types/container_repository_type.rb'
- - 'app/graphql/types/countable_connection_type.rb'
- - 'app/graphql/types/current_user_todos.rb'
- - 'app/graphql/types/custom_emoji_type.rb'
- - 'app/graphql/types/design_management/design_at_version_type.rb'
- - 'app/graphql/types/design_management/design_collection_type.rb'
- - 'app/graphql/types/design_management/design_fields.rb'
- - 'app/graphql/types/design_management/design_type.rb'
- - 'app/graphql/types/design_management/version_type.rb'
- - 'app/graphql/types/design_management_type.rb'
- - 'app/graphql/types/diff_paths_input_type.rb'
- - 'app/graphql/types/diff_refs_type.rb'
- - 'app/graphql/types/diff_stats_summary_type.rb'
- - 'app/graphql/types/diff_stats_type.rb'
- - 'app/graphql/types/environment_type.rb'
- - 'app/graphql/types/error_tracking/sentry_detailed_error_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_collection_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_frequency_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_tags_type.rb'
- - 'app/graphql/types/error_tracking/sentry_error_type.rb'
- - 'app/graphql/types/evidence_type.rb'
- - 'app/graphql/types/grafana_integration_type.rb'
- - 'app/graphql/types/group_invitation_type.rb'
- - 'app/graphql/types/group_member_type.rb'
- - 'app/graphql/types/group_type.rb'
- - 'app/graphql/types/invitation_interface.rb'
- - 'app/graphql/types/issue_type.rb'
- - 'app/graphql/types/jira_import_type.rb'
- - 'app/graphql/types/jira_user_type.rb'
- - 'app/graphql/types/jira_users_mapping_input_type.rb'
- - 'app/graphql/types/label_type.rb'
- - 'app/graphql/types/member_interface.rb'
- - 'app/graphql/types/merge_request_connection_type.rb'
- - 'app/graphql/types/merge_request_type.rb'
- - 'app/graphql/types/metadata_type.rb'
- - 'app/graphql/types/metrics/dashboard_type.rb'
- - 'app/graphql/types/metrics/dashboards/annotation_type.rb'
- - 'app/graphql/types/milestone_stats_type.rb'
- - 'app/graphql/types/milestone_type.rb'
- - 'app/graphql/types/namespace_type.rb'
- - 'app/graphql/types/notes/diff_position_type.rb'
- - 'app/graphql/types/notes/discussion_type.rb'
- - 'app/graphql/types/notes/note_type.rb'
- - 'app/graphql/types/notes/noteable_type.rb'
- - 'app/graphql/types/package_type.rb'
- - 'app/graphql/types/project_invitation_type.rb'
- - 'app/graphql/types/project_member_type.rb'
- - 'app/graphql/types/project_statistics_type.rb'
- - 'app/graphql/types/project_type.rb'
- - 'app/graphql/types/projects/service_type.rb'
- - 'app/graphql/types/projects/services/jira_project_type.rb'
- - 'app/graphql/types/projects/services/jira_service_type.rb'
- - 'app/graphql/types/prometheus_alert_type.rb'
- - 'app/graphql/types/query_type.rb'
- - 'app/graphql/types/range_input_type.rb'
- - 'app/graphql/types/release_asset_link_input_type.rb'
- - 'app/graphql/types/release_asset_link_type.rb'
- - 'app/graphql/types/release_assets_input_type.rb'
- - 'app/graphql/types/release_assets_type.rb'
- - 'app/graphql/types/release_links_type.rb'
- - 'app/graphql/types/release_source_type.rb'
- - 'app/graphql/types/release_type.rb'
- - 'app/graphql/types/repository_type.rb'
- - 'app/graphql/types/resolvable_interface.rb'
- - 'app/graphql/types/root_storage_statistics_type.rb'
- - 'app/graphql/types/snippet_type.rb'
- - 'app/graphql/types/snippets/blob_action_input_type.rb'
- - 'app/graphql/types/snippets/blob_type.rb'
- - 'app/graphql/types/snippets/blob_viewer_type.rb'
- - 'app/graphql/types/task_completion_status.rb'
- - 'app/graphql/types/terraform/state_type.rb'
- - 'app/graphql/types/terraform/state_version_type.rb'
- - 'app/graphql/types/todo_type.rb'
- - 'app/graphql/types/tree/blob_type.rb'
- - 'app/graphql/types/tree/entry_type.rb'
- - 'app/graphql/types/tree/submodule_type.rb'
- - 'app/graphql/types/tree/tree_entry_type.rb'
- - 'app/graphql/types/tree/tree_type.rb'
- - 'app/graphql/types/user_status_type.rb'
- - 'app/graphql/types/user_type.rb'
- - 'ee/app/graphql/ee/types/board_list_type.rb'
- - 'ee/app/graphql/ee/types/board_type.rb'
- - 'ee/app/graphql/ee/types/boards/board_issue_input_base_type.rb'
- - 'ee/app/graphql/ee/types/boards/board_issue_input_type.rb'
- - 'ee/app/graphql/ee/types/ci/pipeline_type.rb'
- - 'ee/app/graphql/ee/types/group_type.rb'
- - 'ee/app/graphql/ee/types/issue_connection_type.rb'
- - 'ee/app/graphql/ee/types/merge_request_type.rb'
- - 'ee/app/graphql/ee/types/namespace_type.rb'
- - 'ee/app/graphql/ee/types/project_type.rb'
- - 'ee/app/graphql/ee/types/query_type.rb'
- - 'ee/app/graphql/types/admin/analytics/devops_adoption/segment_type.rb'
- - 'ee/app/graphql/types/admin/analytics/devops_adoption/snapshot_type.rb'
- - 'ee/app/graphql/types/boards/board_epic_type.rb'
- - 'ee/app/graphql/types/boards/epic_board_type.rb'
- - 'ee/app/graphql/types/boards/epic_user_preferences_type.rb'
- - 'ee/app/graphql/types/burnup_chart_daily_totals_type.rb'
- - 'ee/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb'
- - 'ee/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb'
- - 'ee/app/graphql/types/ci_configuration/sast/entity_input_type.rb'
- - 'ee/app/graphql/types/ci_configuration/sast/input_type.rb'
- - 'ee/app/graphql/types/clusters/agent_token_type.rb'
- - 'ee/app/graphql/types/clusters/agent_type.rb'
- - 'ee/app/graphql/types/compliance_management/compliance_framework_type.rb'
- - 'ee/app/graphql/types/dast_scanner_profile_type.rb'
- - 'ee/app/graphql/types/dast_site_profile_type.rb'
- - 'ee/app/graphql/types/dast_site_validation_type.rb'
- - 'ee/app/graphql/types/epic_descendant_count_type.rb'
- - 'ee/app/graphql/types/epic_descendant_weight_sum_type.rb'
- - 'ee/app/graphql/types/epic_health_status_type.rb'
- - 'ee/app/graphql/types/epic_issue_type.rb'
- - 'ee/app/graphql/types/epic_tree/epic_tree_node_input_type.rb'
- - 'ee/app/graphql/types/epic_type.rb'
- - 'ee/app/graphql/types/external_issue_type.rb'
- - 'ee/app/graphql/types/geo/geo_node_type.rb'
- - 'ee/app/graphql/types/geo/merge_request_diff_registry_type.rb'
- - 'ee/app/graphql/types/geo/package_file_registry_type.rb'
- - 'ee/app/graphql/types/geo/snippet_repository_registry_type.rb'
- - 'ee/app/graphql/types/geo/terraform_state_version_registry_type.rb'
- - 'ee/app/graphql/types/group_stats_type.rb'
- - 'ee/app/graphql/types/incident_management/oncall_schedule_type.rb'
- - 'ee/app/graphql/types/instance_security_dashboard_type.rb'
- - 'ee/app/graphql/types/iteration_type.rb'
- - 'ee/app/graphql/types/metric_image_type.rb'
- - 'ee/app/graphql/types/requirements_management/requirement_states_count_type.rb'
- - 'ee/app/graphql/types/requirements_management/requirement_type.rb'
- - 'ee/app/graphql/types/requirements_management/test_report_type.rb'
- - 'ee/app/graphql/types/scanned_resource_type.rb'
- - 'ee/app/graphql/types/security_report_summary_section_type.rb'
- - 'ee/app/graphql/types/time_report_stats_type.rb'
- - 'ee/app/graphql/types/timebox_metrics_type.rb'
- - 'ee/app/graphql/types/timebox_report_interface.rb'
- - 'ee/app/graphql/types/timebox_report_type.rb'
- - 'ee/app/graphql/types/timelog_type.rb'
- - 'ee/app/graphql/types/vulnerabilities_count_by_day_and_severity_type.rb'
- - 'ee/app/graphql/types/vulnerabilities_count_by_day_type.rb'
- - 'ee/app/graphql/types/vulnerability/external_issue_link_type.rb'
- - 'ee/app/graphql/types/vulnerability/issue_link_type.rb'
- - 'ee/app/graphql/types/vulnerability_identifier_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/container_scanning_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/coverage_fuzzing_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/dast_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/dependency_scanning_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/sast_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/secret_detection_type.rb'
- - 'ee/app/graphql/types/vulnerability_scanner_type.rb'
- - 'ee/app/graphql/types/vulnerability_type.rb'
- - 'ee/app/graphql/types/vulnerable_dependency_type.rb'
- - 'ee/app/graphql/types/vulnerable_package_type.rb'
- - 'ee/app/graphql/types/vulnerable_projects_by_grade_type.rb'
-
# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/34997
RSpec/AnyInstanceOf:
Exclude:
@@ -1451,7 +1190,6 @@ RSpec/AnyInstanceOf:
- 'spec/workers/emails_on_push_worker_spec.rb'
- 'spec/workers/error_tracking_issue_link_worker_spec.rb'
- 'spec/workers/expire_pipeline_cache_worker_spec.rb'
- - 'spec/workers/git_garbage_collect_worker_spec.rb'
- 'spec/workers/group_export_worker_spec.rb'
- 'spec/workers/group_import_worker_spec.rb'
- 'spec/workers/namespaceless_project_destroy_worker_spec.rb'
@@ -1468,3 +1206,1270 @@ RSpec/AnyInstanceOf:
- 'spec/workers/stuck_ci_jobs_worker_spec.rb'
- 'spec/workers/wait_for_cluster_creation_worker_spec.rb'
- 'ee/spec/workers/security/auto_fix_worker_spec.rb'
+
+Gitlab/NamespacedClass:
+ Exclude:
+ - 'config/**/*.rb'
+ - 'db/**/*.rb'
+ - 'ee/bin/**/*'
+ - 'ee/db/**/*.rb'
+ - 'ee/elastic/**/*.rb'
+ - 'scripts/**/*'
+ - 'spec/migrations/**/*.rb'
+ # The list above represents the permanent exclusions for this rule
+ # due to the fact these files are related to infrastructure code.
+ # This list should eventually be moved to .rubocop.yml after all TODOs
+ # are addressed.
+ #
+ # The list below represents the classes that require
+ # a namespace as they make the domain related code.
+ - 'app/channels/issues_channel.rb'
+ - 'app/controllers/abuse_reports_controller.rb'
+ - 'app/controllers/acme_challenges_controller.rb'
+ - 'app/controllers/application_controller.rb'
+ - 'app/controllers/autocomplete_controller.rb'
+ - 'app/controllers/chaos_controller.rb'
+ - 'app/controllers/confirmations_controller.rb'
+ - 'app/controllers/dashboard_controller.rb'
+ - 'app/controllers/graphql_controller.rb'
+ - 'app/controllers/groups_controller.rb'
+ - 'app/controllers/health_check_controller.rb'
+ - 'app/controllers/health_controller.rb'
+ - 'app/controllers/help_controller.rb'
+ - 'app/controllers/ide_controller.rb'
+ - 'app/controllers/invites_controller.rb'
+ - 'app/controllers/jwks_controller.rb'
+ - 'app/controllers/jwt_controller.rb'
+ - 'app/controllers/metrics_controller.rb'
+ - 'app/controllers/notification_settings_controller.rb'
+ - 'app/controllers/omniauth_callbacks_controller.rb'
+ - 'app/controllers/passwords_controller.rb'
+ - 'app/controllers/profiles_controller.rb'
+ - 'app/controllers/projects_controller.rb'
+ - 'app/controllers/registrations_controller.rb'
+ - 'app/controllers/root_controller.rb'
+ - 'app/controllers/runner_setup_controller.rb'
+ - 'app/controllers/search_controller.rb'
+ - 'app/controllers/sent_notifications_controller.rb'
+ - 'app/controllers/sessions_controller.rb'
+ - 'app/controllers/snippets_controller.rb'
+ - 'app/controllers/uploads_controller.rb'
+ - 'app/controllers/user_callouts_controller.rb'
+ - 'app/controllers/users_controller.rb'
+ - 'app/controllers/whats_new_controller.rb'
+ - 'app/finders/abuse_reports_finder.rb'
+ - 'app/finders/access_requests_finder.rb'
+ - 'app/finders/admin/projects_finder.rb'
+ - 'app/finders/applications_finder.rb'
+ - 'app/finders/award_emojis_finder.rb'
+ - 'app/finders/branches_finder.rb'
+ - 'app/finders/cluster_ancestors_finder.rb'
+ - 'app/finders/clusters_finder.rb'
+ - 'app/finders/container_repositories_finder.rb'
+ - 'app/finders/context_commits_finder.rb'
+ - 'app/finders/contributed_projects_finder.rb'
+ - 'app/finders/deployments_finder.rb'
+ - 'app/finders/environment_names_finder.rb'
+ - 'app/finders/environments_finder.rb'
+ - 'app/finders/events_finder.rb'
+ - 'app/finders/feature_flags_finder.rb'
+ - 'app/finders/feature_flags_user_lists_finder.rb'
+ - 'app/finders/fork_projects_finder.rb'
+ - 'app/finders/fork_targets_finder.rb'
+ - 'app/finders/freeze_periods_finder.rb'
+ - 'app/finders/git_refs_finder.rb'
+ - 'app/finders/group_descendants_finder.rb'
+ - 'app/finders/group_finder.rb'
+ - 'app/finders/group_members_finder.rb'
+ - 'app/finders/group_projects_finder.rb'
+ - 'app/finders/groups_finder.rb'
+ - 'app/finders/issuable_finder.rb'
+ - 'app/finders/issuable_finder/params.rb'
+ - 'app/finders/issues_finder.rb'
+ - 'app/finders/issues_finder/params.rb'
+ - 'app/finders/joined_groups_finder.rb'
+ - 'app/finders/keys_finder.rb'
+ - 'app/finders/labels_finder.rb'
+ - 'app/finders/license_template_finder.rb'
+ - 'app/finders/members_finder.rb'
+ - 'app/finders/merge_request_target_project_finder.rb'
+ - 'app/finders/merge_requests_finder.rb'
+ - 'app/finders/merge_requests_finder/params.rb'
+ - 'app/finders/milestones_finder.rb'
+ - 'app/finders/notes_finder.rb'
+ - 'app/finders/pending_todos_finder.rb'
+ - 'app/finders/personal_access_tokens_finder.rb'
+ - 'app/finders/personal_projects_finder.rb'
+ - 'app/finders/projects_finder.rb'
+ - 'app/finders/prometheus_metrics_finder.rb'
+ - 'app/finders/protected_branches_finder.rb'
+ - 'app/finders/releases_finder.rb'
+ - 'app/finders/resource_milestone_event_finder.rb'
+ - 'app/finders/resource_state_event_finder.rb'
+ - 'app/finders/sentry_issue_finder.rb'
+ - 'app/finders/serverless_domain_finder.rb'
+ - 'app/finders/snippets_finder.rb'
+ - 'app/finders/starred_projects_finder.rb'
+ - 'app/finders/tags_finder.rb'
+ - 'app/finders/template_finder.rb'
+ - 'app/finders/todos_finder.rb'
+ - 'app/finders/union_finder.rb'
+ - 'app/finders/uploader_finder.rb'
+ - 'app/finders/user_finder.rb'
+ - 'app/finders/user_group_notification_settings_finder.rb'
+ - 'app/finders/user_groups_counter.rb'
+ - 'app/finders/user_recent_events_finder.rb'
+ - 'app/finders/users_finder.rb'
+ - 'app/finders/users_star_projects_finder.rb'
+ - 'app/finders/users_with_pending_todos_finder.rb'
+ - 'app/graphql/gitlab_schema.rb'
+ - 'app/mailers/abuse_report_mailer.rb'
+ - 'app/mailers/application_mailer.rb'
+ - 'app/mailers/devise_mailer.rb'
+ - 'app/mailers/email_rejection_mailer.rb'
+ - 'app/mailers/notify.rb'
+ - 'app/mailers/previews/devise_mailer_preview.rb'
+ - 'app/mailers/previews/email_rejection_mailer_preview.rb'
+ - 'app/mailers/previews/notify_preview.rb'
+ - 'app/mailers/previews/repository_check_mailer_preview.rb'
+ - 'app/mailers/repository_check_mailer.rb'
+ - 'app/models/ability.rb'
+ - 'app/models/abuse_report.rb'
+ - 'app/models/active_session.rb'
+ - 'app/models/appearance.rb'
+ - 'app/models/application_record.rb'
+ - 'app/models/application_setting.rb'
+ - 'app/models/application_setting/term.rb'
+ - 'app/models/approval.rb'
+ - 'app/models/audit_event.rb'
+ - 'app/models/audit_event_archived.rb'
+ - 'app/models/authentication_event.rb'
+ - 'app/models/award_emoji.rb'
+ - 'app/models/badge.rb'
+ - 'app/models/badges/group_badge.rb'
+ - 'app/models/badges/project_badge.rb'
+ - 'app/models/blob.rb'
+ - 'app/models/board.rb'
+ - 'app/models/board_group_recent_visit.rb'
+ - 'app/models/board_project_recent_visit.rb'
+ - 'app/models/broadcast_message.rb'
+ - 'app/models/bulk_import.rb'
+ - 'app/models/chat_name.rb'
+ - 'app/models/chat_team.rb'
+ - 'app/models/ci_platform_metric.rb'
+ - 'app/models/commit.rb'
+ - 'app/models/commit_collection.rb'
+ - 'app/models/commit_range.rb'
+ - 'app/models/commit_status.rb'
+ - 'app/models/commit_user_mention.rb'
+ - 'app/models/commit_with_pipeline.rb'
+ - 'app/models/compare.rb'
+ - 'app/models/concerns/uniquify.rb'
+ - 'app/models/container_expiration_policy.rb'
+ - 'app/models/container_repository.rb'
+ - 'app/models/custom_emoji.rb'
+ - 'app/models/data_list.rb'
+ - 'app/models/deploy_key.rb'
+ - 'app/models/deploy_keys_project.rb'
+ - 'app/models/deploy_token.rb'
+ - 'app/models/deployment.rb'
+ - 'app/models/deployment_cluster.rb'
+ - 'app/models/deployment_merge_request.rb'
+ - 'app/models/deployment_metrics.rb'
+ - 'app/models/description_version.rb'
+ - 'app/models/design_user_mention.rb'
+ - 'app/models/diff_discussion.rb'
+ - 'app/models/diff_note.rb'
+ - 'app/models/diff_note_position.rb'
+ - 'app/models/directly_addressed_user.rb'
+ - 'app/models/discussion.rb'
+ - 'app/models/discussion_note.rb'
+ - 'app/models/draft_note.rb'
+ - 'app/models/email.rb'
+ - 'app/models/environment.rb'
+ - 'app/models/environment_status.rb'
+ - 'app/models/epic.rb'
+ - 'app/models/event.rb'
+ - 'app/models/event_collection.rb'
+ - 'app/models/experiment.rb'
+ - 'app/models/experiment_subject.rb'
+ - 'app/models/experiment_user.rb'
+ - 'app/models/exported_protected_branch.rb'
+ - 'app/models/external_issue.rb'
+ - 'app/models/external_pull_request.rb'
+ - 'app/models/fork_network.rb'
+ - 'app/models/fork_network_member.rb'
+ - 'app/models/generic_commit_status.rb'
+ - 'app/models/gpg_key.rb'
+ - 'app/models/gpg_key_subkey.rb'
+ - 'app/models/gpg_signature.rb'
+ - 'app/models/grafana_integration.rb'
+ - 'app/models/group.rb'
+ - 'app/models/group_custom_attribute.rb'
+ - 'app/models/group_deploy_key.rb'
+ - 'app/models/group_deploy_keys_group.rb'
+ - 'app/models/group_deploy_token.rb'
+ - 'app/models/group_group_link.rb'
+ - 'app/models/group_import_state.rb'
+ - 'app/models/group_label.rb'
+ - 'app/models/guest.rb'
+ - 'app/models/hooks/active_hook_filter.rb'
+ - 'app/models/hooks/project_hook.rb'
+ - 'app/models/hooks/service_hook.rb'
+ - 'app/models/hooks/system_hook.rb'
+ - 'app/models/hooks/web_hook.rb'
+ - 'app/models/hooks/web_hook_log.rb'
+ - 'app/models/identity.rb'
+ - 'app/models/identity/uniqueness_scopes.rb'
+ - 'app/models/import_export_upload.rb'
+ - 'app/models/import_failure.rb'
+ - 'app/models/individual_note_discussion.rb'
+ - 'app/models/instance_configuration.rb'
+ - 'app/models/instance_metadata.rb'
+ - 'app/models/internal_id.rb'
+ - 'app/models/issuable_severity.rb'
+ - 'app/models/issue.rb'
+ - 'app/models/issue/metrics.rb'
+ - 'app/models/issue_assignee.rb'
+ - 'app/models/issue_collection.rb'
+ - 'app/models/issue_email_participant.rb'
+ - 'app/models/issue_link.rb'
+ - 'app/models/issue_user_mention.rb'
+ - 'app/models/iteration.rb'
+ - 'app/models/jira_connect_installation.rb'
+ - 'app/models/jira_connect_subscription.rb'
+ - 'app/models/jira_import_state.rb'
+ - 'app/models/key.rb'
+ - 'app/models/label.rb'
+ - 'app/models/label_link.rb'
+ - 'app/models/label_note.rb'
+ - 'app/models/label_priority.rb'
+ - 'app/models/legacy_diff_discussion.rb'
+ - 'app/models/legacy_diff_note.rb'
+ - 'app/models/lfs_download_object.rb'
+ - 'app/models/lfs_file_lock.rb'
+ - 'app/models/lfs_object.rb'
+ - 'app/models/lfs_objects_project.rb'
+ - 'app/models/license_template.rb'
+ - 'app/models/list.rb'
+ - 'app/models/list_user_preference.rb'
+ - 'app/models/member.rb'
+ - 'app/models/members/group_member.rb'
+ - 'app/models/members/project_member.rb'
+ - 'app/models/members_preloader.rb'
+ - 'app/models/merge_request.rb'
+ - 'app/models/merge_request_assignee.rb'
+ - 'app/models/merge_request_context_commit.rb'
+ - 'app/models/merge_request_context_commit_diff_file.rb'
+ - 'app/models/merge_request_diff.rb'
+ - 'app/models/merge_request_diff_commit.rb'
+ - 'app/models/merge_request_diff_file.rb'
+ - 'app/models/merge_request_reviewer.rb'
+ - 'app/models/merge_request_user_mention.rb'
+ - 'app/models/merge_requests_closing_issues.rb'
+ - 'app/models/milestone.rb'
+ - 'app/models/milestone_note.rb'
+ - 'app/models/milestone_release.rb'
+ - 'app/models/namespace.rb'
+ - 'app/models/namespace/traversal_hierarchy.rb'
+ - 'app/models/namespace_onboarding_action.rb'
+ - 'app/models/namespace_setting.rb'
+ - 'app/models/note.rb'
+ - 'app/models/note_diff_file.rb'
+ - 'app/models/notification_reason.rb'
+ - 'app/models/notification_recipient.rb'
+ - 'app/models/notification_setting.rb'
+ - 'app/models/oauth_access_grant.rb'
+ - 'app/models/oauth_access_token.rb'
+ - 'app/models/out_of_context_discussion.rb'
+ - 'app/models/onboarding_progress.rb'
+ - 'app/models/pages_deployment.rb'
+ - 'app/models/pages_domain.rb'
+ - 'app/models/pages_domain_acme_order.rb'
+ - 'app/models/personal_access_token.rb'
+ - 'app/models/personal_snippet.rb'
+ - 'app/models/plan.rb'
+ - 'app/models/plan_limits.rb'
+ - 'app/models/pool_repository.rb'
+ - 'app/models/product_analytics_event.rb'
+ - 'app/models/programming_language.rb'
+ - 'app/models/project.rb'
+ - 'app/models/project_authorization.rb'
+ - 'app/models/project_auto_devops.rb'
+ - 'app/models/project_ci_cd_setting.rb'
+ - 'app/models/project_custom_attribute.rb'
+ - 'app/models/project_daily_statistic.rb'
+ - 'app/models/project_deploy_token.rb'
+ - 'app/models/project_export_job.rb'
+ - 'app/models/project_feature.rb'
+ - 'app/models/project_feature_usage.rb'
+ - 'app/models/project_group_link.rb'
+ - 'app/models/project_import_data.rb'
+ - 'app/models/project_import_state.rb'
+ - 'app/models/project_label.rb'
+ - 'app/models/project_metrics_setting.rb'
+ - 'app/models/project_pages_metadatum.rb'
+ - 'app/models/project_repository.rb'
+ - 'app/models/project_repository_storage_move.rb'
+ - 'app/models/project_services/alerts_service.rb'
+ - 'app/models/project_services/alerts_service_data.rb'
+ - 'app/models/project_services/asana_service.rb'
+ - 'app/models/project_services/assembla_service.rb'
+ - 'app/models/project_services/bamboo_service.rb'
+ - 'app/models/project_services/bugzilla_service.rb'
+ - 'app/models/project_services/buildkite_service.rb'
+ - 'app/models/project_services/builds_email_service.rb'
+ - 'app/models/project_services/campfire_service.rb'
+ - 'app/models/project_services/chat_notification_service.rb'
+ - 'app/models/project_services/ci_service.rb'
+ - 'app/models/project_services/confluence_service.rb'
+ - 'app/models/project_services/custom_issue_tracker_service.rb'
+ - 'app/models/project_services/datadog_service.rb'
+ - 'app/models/project_services/discord_service.rb'
+ - 'app/models/project_services/drone_ci_service.rb'
+ - 'app/models/project_services/emails_on_push_service.rb'
+ - 'app/models/project_services/ewm_service.rb'
+ - 'app/models/project_services/external_wiki_service.rb'
+ - 'app/models/project_services/flowdock_service.rb'
+ - 'app/models/project_services/hangouts_chat_service.rb'
+ - 'app/models/project_services/hipchat_service.rb'
+ - 'app/models/project_services/irker_service.rb'
+ - 'app/models/project_services/issue_tracker_data.rb'
+ - 'app/models/project_services/issue_tracker_service.rb'
+ - 'app/models/project_services/jenkins_service.rb'
+ - 'app/models/project_services/jira_service.rb'
+ - 'app/models/project_services/jira_tracker_data.rb'
+ - 'app/models/project_services/mattermost_service.rb'
+ - 'app/models/project_services/mattermost_slash_commands_service.rb'
+ - 'app/models/project_services/microsoft_teams_service.rb'
+ - 'app/models/project_services/mock_ci_service.rb'
+ - 'app/models/project_services/mock_deployment_service.rb'
+ - 'app/models/project_services/mock_monitoring_service.rb'
+ - 'app/models/project_services/monitoring_service.rb'
+ - 'app/models/project_services/open_project_service.rb'
+ - 'app/models/project_services/open_project_tracker_data.rb'
+ - 'app/models/project_services/packagist_service.rb'
+ - 'app/models/project_services/pipelines_email_service.rb'
+ - 'app/models/project_services/pivotaltracker_service.rb'
+ - 'app/models/project_services/prometheus_service.rb'
+ - 'app/models/project_services/pushover_service.rb'
+ - 'app/models/project_services/redmine_service.rb'
+ - 'app/models/project_services/slack_service.rb'
+ - 'app/models/project_services/slack_slash_commands_service.rb'
+ - 'app/models/project_services/slash_commands_service.rb'
+ - 'app/models/project_services/teamcity_service.rb'
+ - 'app/models/project_services/unify_circuit_service.rb'
+ - 'app/models/project_services/webex_teams_service.rb'
+ - 'app/models/project_services/youtrack_service.rb'
+ - 'app/models/project_setting.rb'
+ - 'app/models/project_snippet.rb'
+ - 'app/models/project_statistics.rb'
+ - 'app/models/project_team.rb'
+ - 'app/models/project_tracing_setting.rb'
+ - 'app/models/project_wiki.rb'
+ - 'app/models/prometheus_alert.rb'
+ - 'app/models/prometheus_alert_event.rb'
+ - 'app/models/prometheus_metric.rb'
+ - 'app/models/protectable_dropdown.rb'
+ - 'app/models/protected_branch.rb'
+ - 'app/models/protected_tag.rb'
+ - 'app/models/push_event.rb'
+ - 'app/models/push_event_payload.rb'
+ - 'app/models/raw_usage_data.rb'
+ - 'app/models/readme_blob.rb'
+ - 'app/models/redirect_route.rb'
+ - 'app/models/ref_matcher.rb'
+ - 'app/models/release.rb'
+ - 'app/models/release_highlight.rb'
+ - 'app/models/remote_mirror.rb'
+ - 'app/models/repository.rb'
+ - 'app/models/repository_language.rb'
+ - 'app/models/resource_event.rb'
+ - 'app/models/resource_label_event.rb'
+ - 'app/models/resource_milestone_event.rb'
+ - 'app/models/resource_state_event.rb'
+ - 'app/models/resource_timebox_event.rb'
+ - 'app/models/review.rb'
+ - 'app/models/route.rb'
+ - 'app/models/self_managed_prometheus_alert_event.rb'
+ - 'app/models/sent_notification.rb'
+ - 'app/models/sentry_issue.rb'
+ - 'app/models/service.rb'
+ - 'app/models/service_desk_setting.rb'
+ - 'app/models/service_list.rb'
+ - 'app/models/shard.rb'
+ - 'app/models/snippet.rb'
+ - 'app/models/snippet_blob.rb'
+ - 'app/models/snippet_input_action.rb'
+ - 'app/models/snippet_input_action_collection.rb'
+ - 'app/models/snippet_repository.rb'
+ - 'app/models/snippet_repository_storage_move.rb'
+ - 'app/models/snippet_statistics.rb'
+ - 'app/models/snippet_user_mention.rb'
+ - 'app/models/spam_log.rb'
+ - 'app/models/ssh_host_key.rb'
+ - 'app/models/state_note.rb'
+ - 'app/models/subscription.rb'
+ - 'app/models/suggestion.rb'
+ - 'app/models/synthetic_note.rb'
+ - 'app/models/system_note_metadata.rb'
+ - 'app/models/term_agreement.rb'
+ - 'app/models/timelog.rb'
+ - 'app/models/todo.rb'
+ - 'app/models/tree.rb'
+ - 'app/models/trending_project.rb'
+ - 'app/models/u2f_registration.rb'
+ - 'app/models/upload.rb'
+ - 'app/models/user.rb'
+ - 'app/models/user_agent_detail.rb'
+ - 'app/models/user_callout.rb'
+ - 'app/models/user_canonical_email.rb'
+ - 'app/models/user_custom_attribute.rb'
+ - 'app/models/user_detail.rb'
+ - 'app/models/user_highest_role.rb'
+ - 'app/models/user_interacted_project.rb'
+ - 'app/models/user_mention.rb'
+ - 'app/models/user_preference.rb'
+ - 'app/models/user_status.rb'
+ - 'app/models/user_synced_attributes_metadata.rb'
+ - 'app/models/users_star_project.rb'
+ - 'app/models/users_statistics.rb'
+ - 'app/models/vulnerability.rb'
+ - 'app/models/web_ide_terminal.rb'
+ - 'app/models/webauthn_registration.rb'
+ - 'app/models/wiki.rb'
+ - 'app/models/wiki_directory.rb'
+ - 'app/models/wiki_page.rb'
+ - 'app/models/wiki_page/meta.rb'
+ - 'app/models/wiki_page/slug.rb'
+ - 'app/models/x509_certificate.rb'
+ - 'app/models/x509_commit_signature.rb'
+ - 'app/models/x509_issuer.rb'
+ - 'app/models/zoom_meeting.rb'
+ - 'app/policies/application_setting/term_policy.rb'
+ - 'app/policies/award_emoji_policy.rb'
+ - 'app/policies/base_policy.rb'
+ - 'app/policies/blob_policy.rb'
+ - 'app/policies/board_policy.rb'
+ - 'app/policies/commit_policy.rb'
+ - 'app/policies/commit_status_policy.rb'
+ - 'app/policies/container_expiration_policy_policy.rb'
+ - 'app/policies/container_repository_policy.rb'
+ - 'app/policies/custom_emoji_policy.rb'
+ - 'app/policies/deploy_key_policy.rb'
+ - 'app/policies/deploy_keys_project_policy.rb'
+ - 'app/policies/deploy_token_policy.rb'
+ - 'app/policies/deployment_policy.rb'
+ - 'app/policies/draft_note_policy.rb'
+ - 'app/policies/environment_policy.rb'
+ - 'app/policies/external_issue_policy.rb'
+ - 'app/policies/global_policy.rb'
+ - 'app/policies/grafana_integration_policy.rb'
+ - 'app/policies/group_deploy_key_policy.rb'
+ - 'app/policies/group_deploy_keys_group_policy.rb'
+ - 'app/policies/group_label_policy.rb'
+ - 'app/policies/group_member_policy.rb'
+ - 'app/policies/group_policy.rb'
+ - 'app/policies/identity_provider_policy.rb'
+ - 'app/policies/instance_metadata_policy.rb'
+ - 'app/policies/issuable_policy.rb'
+ - 'app/policies/issue_policy.rb'
+ - 'app/policies/merge_request_policy.rb'
+ - 'app/policies/milestone_policy.rb'
+ - 'app/policies/namespace_policy.rb'
+ - 'app/policies/nil_policy.rb'
+ - 'app/policies/note_policy.rb'
+ - 'app/policies/personal_access_token_policy.rb'
+ - 'app/policies/personal_snippet_policy.rb'
+ - 'app/policies/project_ci_cd_setting_policy.rb'
+ - 'app/policies/project_label_policy.rb'
+ - 'app/policies/project_member_policy.rb'
+ - 'app/policies/project_policy.rb'
+ - 'app/policies/project_snippet_policy.rb'
+ - 'app/policies/project_statistics_policy.rb'
+ - 'app/policies/prometheus_alert_policy.rb'
+ - 'app/policies/protected_branch_policy.rb'
+ - 'app/policies/release_policy.rb'
+ - 'app/policies/repository_policy.rb'
+ - 'app/policies/resource_label_event_policy.rb'
+ - 'app/policies/service_policy.rb'
+ - 'app/policies/suggestion_policy.rb'
+ - 'app/policies/timebox_policy.rb'
+ - 'app/policies/todo_policy.rb'
+ - 'app/policies/user_policy.rb'
+ - 'app/policies/wiki_page_policy.rb'
+ - 'app/policies/wiki_policy.rb'
+ - 'app/presenters/award_emoji_presenter.rb'
+ - 'app/presenters/blob_presenter.rb'
+ - 'app/presenters/board_presenter.rb'
+ - 'app/presenters/clusterable_presenter.rb'
+ - 'app/presenters/commit_presenter.rb'
+ - 'app/presenters/commit_status_presenter.rb'
+ - 'app/presenters/environment_presenter.rb'
+ - 'app/presenters/event_presenter.rb'
+ - 'app/presenters/generic_commit_status_presenter.rb'
+ - 'app/presenters/group_clusterable_presenter.rb'
+ - 'app/presenters/group_member_presenter.rb'
+ - 'app/presenters/instance_clusterable_presenter.rb'
+ - 'app/presenters/invitation_presenter.rb'
+ - 'app/presenters/issue_presenter.rb'
+ - 'app/presenters/label_presenter.rb'
+ - 'app/presenters/member_presenter.rb'
+ - 'app/presenters/members_presenter.rb'
+ - 'app/presenters/merge_request_presenter.rb'
+ - 'app/presenters/milestone_presenter.rb'
+ - 'app/presenters/pages_domain_presenter.rb'
+ - 'app/presenters/project_clusterable_presenter.rb'
+ - 'app/presenters/project_hook_presenter.rb'
+ - 'app/presenters/project_member_presenter.rb'
+ - 'app/presenters/project_presenter.rb'
+ - 'app/presenters/prometheus_alert_presenter.rb'
+ - 'app/presenters/release_presenter.rb'
+ - 'app/presenters/search_service_presenter.rb'
+ - 'app/presenters/sentry_error_presenter.rb'
+ - 'app/presenters/service_hook_presenter.rb'
+ - 'app/presenters/snippet_blob_presenter.rb'
+ - 'app/presenters/snippet_presenter.rb'
+ - 'app/presenters/todo_presenter.rb'
+ - 'app/presenters/tree_entry_presenter.rb'
+ - 'app/presenters/user_presenter.rb'
+ - 'app/presenters/web_hook_log_presenter.rb'
+ - 'app/serializers/accessibility_error_entity.rb'
+ - 'app/serializers/accessibility_reports_comparer_entity.rb'
+ - 'app/serializers/accessibility_reports_comparer_serializer.rb'
+ - 'app/serializers/analytics_build_entity.rb'
+ - 'app/serializers/analytics_build_serializer.rb'
+ - 'app/serializers/analytics_commit_entity.rb'
+ - 'app/serializers/analytics_commit_serializer.rb'
+ - 'app/serializers/analytics_generic_serializer.rb'
+ - 'app/serializers/analytics_issue_entity.rb'
+ - 'app/serializers/analytics_issue_serializer.rb'
+ - 'app/serializers/analytics_merge_request_entity.rb'
+ - 'app/serializers/analytics_merge_request_serializer.rb'
+ - 'app/serializers/analytics_stage_entity.rb'
+ - 'app/serializers/analytics_stage_serializer.rb'
+ - 'app/serializers/analytics_summary_entity.rb'
+ - 'app/serializers/analytics_summary_serializer.rb'
+ - 'app/serializers/award_emoji_entity.rb'
+ - 'app/serializers/base_discussion_entity.rb'
+ - 'app/serializers/base_serializer.rb'
+ - 'app/serializers/blob_entity.rb'
+ - 'app/serializers/board_serializer.rb'
+ - 'app/serializers/board_simple_entity.rb'
+ - 'app/serializers/build_action_entity.rb'
+ - 'app/serializers/build_artifact_entity.rb'
+ - 'app/serializers/build_coverage_entity.rb'
+ - 'app/serializers/build_details_entity.rb'
+ - 'app/serializers/build_metadata_entity.rb'
+ - 'app/serializers/build_serializer.rb'
+ - 'app/serializers/build_trace_entity.rb'
+ - 'app/serializers/build_trace_serializer.rb'
+ - 'app/serializers/cluster_application_entity.rb'
+ - 'app/serializers/cluster_entity.rb'
+ - 'app/serializers/cluster_error_entity.rb'
+ - 'app/serializers/cluster_serializer.rb'
+ - 'app/serializers/codequality_degradation_entity.rb'
+ - 'app/serializers/codequality_reports_comparer_entity.rb'
+ - 'app/serializers/codequality_reports_comparer_serializer.rb'
+ - 'app/serializers/cohort_activity_month_entity.rb'
+ - 'app/serializers/cohort_entity.rb'
+ - 'app/serializers/cohorts_entity.rb'
+ - 'app/serializers/cohorts_serializer.rb'
+ - 'app/serializers/commit_entity.rb'
+ - 'app/serializers/container_repositories_serializer.rb'
+ - 'app/serializers/container_repository_entity.rb'
+ - 'app/serializers/container_tag_entity.rb'
+ - 'app/serializers/container_tags_serializer.rb'
+ - 'app/serializers/current_board_entity.rb'
+ - 'app/serializers/current_board_serializer.rb'
+ - 'app/serializers/current_user_entity.rb'
+ - 'app/serializers/deploy_key_entity.rb'
+ - 'app/serializers/deploy_key_serializer.rb'
+ - 'app/serializers/deploy_keys_project_entity.rb'
+ - 'app/serializers/deployment_cluster_entity.rb'
+ - 'app/serializers/deployment_entity.rb'
+ - 'app/serializers/deployment_serializer.rb'
+ - 'app/serializers/detailed_status_entity.rb'
+ - 'app/serializers/diff_file_base_entity.rb'
+ - 'app/serializers/diff_file_entity.rb'
+ - 'app/serializers/diff_file_metadata_entity.rb'
+ - 'app/serializers/diff_line_entity.rb'
+ - 'app/serializers/diff_line_parallel_entity.rb'
+ - 'app/serializers/diff_line_serializer.rb'
+ - 'app/serializers/diff_viewer_entity.rb'
+ - 'app/serializers/diffs_entity.rb'
+ - 'app/serializers/diffs_metadata_entity.rb'
+ - 'app/serializers/diffs_metadata_serializer.rb'
+ - 'app/serializers/diffs_serializer.rb'
+ - 'app/serializers/discussion_diff_file_entity.rb'
+ - 'app/serializers/discussion_entity.rb'
+ - 'app/serializers/discussion_serializer.rb'
+ - 'app/serializers/draft_note_entity.rb'
+ - 'app/serializers/draft_note_serializer.rb'
+ - 'app/serializers/entity_request.rb'
+ - 'app/serializers/environment_entity.rb'
+ - 'app/serializers/environment_serializer.rb'
+ - 'app/serializers/environment_status_entity.rb'
+ - 'app/serializers/environment_status_serializer.rb'
+ - 'app/serializers/feature_flag_entity.rb'
+ - 'app/serializers/feature_flag_scope_entity.rb'
+ - 'app/serializers/feature_flag_serializer.rb'
+ - 'app/serializers/feature_flag_summary_entity.rb'
+ - 'app/serializers/feature_flag_summary_serializer.rb'
+ - 'app/serializers/feature_flags_client_entity.rb'
+ - 'app/serializers/feature_flags_client_serializer.rb'
+ - 'app/serializers/fork_namespace_entity.rb'
+ - 'app/serializers/fork_namespace_serializer.rb'
+ - 'app/serializers/group_analytics_stage_entity.rb'
+ - 'app/serializers/group_analytics_stage_serializer.rb'
+ - 'app/serializers/group_basic_entity.rb'
+ - 'app/serializers/group_child_entity.rb'
+ - 'app/serializers/group_child_serializer.rb'
+ - 'app/serializers/group_deploy_key_entity.rb'
+ - 'app/serializers/group_deploy_key_serializer.rb'
+ - 'app/serializers/group_deploy_keys_group_entity.rb'
+ - 'app/serializers/group_entity.rb'
+ - 'app/serializers/group_group_link_entity.rb'
+ - 'app/serializers/group_group_link_serializer.rb'
+ - 'app/serializers/group_serializer.rb'
+ - 'app/serializers/issuable_entity.rb'
+ - 'app/serializers/issuable_sidebar_basic_entity.rb'
+ - 'app/serializers/issuable_sidebar_extras_entity.rb'
+ - 'app/serializers/issuable_sidebar_todo_entity.rb'
+ - 'app/serializers/issue_board_entity.rb'
+ - 'app/serializers/issue_entity.rb'
+ - 'app/serializers/issue_serializer.rb'
+ - 'app/serializers/issue_sidebar_basic_entity.rb'
+ - 'app/serializers/issue_sidebar_extras_entity.rb'
+ - 'app/serializers/job_artifact_report_entity.rb'
+ - 'app/serializers/job_entity.rb'
+ - 'app/serializers/job_group_entity.rb'
+ - 'app/serializers/label_entity.rb'
+ - 'app/serializers/label_serializer.rb'
+ - 'app/serializers/lfs_file_lock_entity.rb'
+ - 'app/serializers/lfs_file_lock_serializer.rb'
+ - 'app/serializers/linked_issue_entity.rb'
+ - 'app/serializers/linked_project_issue_entity.rb'
+ - 'app/serializers/linked_project_issue_serializer.rb'
+ - 'app/serializers/member_entity.rb'
+ - 'app/serializers/member_serializer.rb'
+ - 'app/serializers/member_user_entity.rb'
+ - 'app/serializers/merge_request_basic_entity.rb'
+ - 'app/serializers/merge_request_create_entity.rb'
+ - 'app/serializers/merge_request_create_serializer.rb'
+ - 'app/serializers/merge_request_current_user_entity.rb'
+ - 'app/serializers/merge_request_diff_entity.rb'
+ - 'app/serializers/merge_request_for_pipeline_entity.rb'
+ - 'app/serializers/merge_request_metrics_entity.rb'
+ - 'app/serializers/merge_request_noteable_entity.rb'
+ - 'app/serializers/merge_request_poll_cached_widget_entity.rb'
+ - 'app/serializers/merge_request_poll_widget_entity.rb'
+ - 'app/serializers/merge_request_serializer.rb'
+ - 'app/serializers/merge_request_sidebar_basic_entity.rb'
+ - 'app/serializers/merge_request_sidebar_extras_entity.rb'
+ - 'app/serializers/merge_request_user_entity.rb'
+ - 'app/serializers/merge_request_widget_commit_entity.rb'
+ - 'app/serializers/merge_request_widget_entity.rb'
+ - 'app/serializers/move_to_project_entity.rb'
+ - 'app/serializers/move_to_project_serializer.rb'
+ - 'app/serializers/namespace_basic_entity.rb'
+ - 'app/serializers/namespace_serializer.rb'
+ - 'app/serializers/note_attachment_entity.rb'
+ - 'app/serializers/note_entity.rb'
+ - 'app/serializers/note_user_entity.rb'
+ - 'app/serializers/paginated_diff_entity.rb'
+ - 'app/serializers/paginated_diff_serializer.rb'
+ - 'app/serializers/pipeline_details_entity.rb'
+ - 'app/serializers/pipeline_entity.rb'
+ - 'app/serializers/pipeline_serializer.rb'
+ - 'app/serializers/project_entity.rb'
+ - 'app/serializers/project_import_entity.rb'
+ - 'app/serializers/project_mirror_entity.rb'
+ - 'app/serializers/project_mirror_serializer.rb'
+ - 'app/serializers/project_note_entity.rb'
+ - 'app/serializers/project_note_serializer.rb'
+ - 'app/serializers/project_serializer.rb'
+ - 'app/serializers/prometheus_alert_entity.rb'
+ - 'app/serializers/prometheus_alert_serializer.rb'
+ - 'app/serializers/prometheus_metric_entity.rb'
+ - 'app/serializers/prometheus_metric_serializer.rb'
+ - 'app/serializers/release_entity.rb'
+ - 'app/serializers/release_serializer.rb'
+ - 'app/serializers/remote_mirror_entity.rb'
+ - 'app/serializers/review_app_setup_entity.rb'
+ - 'app/serializers/review_app_setup_serializer.rb'
+ - 'app/serializers/rollout_status_entity.rb'
+ - 'app/serializers/route_entity.rb'
+ - 'app/serializers/route_serializer.rb'
+ - 'app/serializers/runner_entity.rb'
+ - 'app/serializers/service_event_entity.rb'
+ - 'app/serializers/service_event_serializer.rb'
+ - 'app/serializers/service_field_entity.rb'
+ - 'app/serializers/service_field_serializer.rb'
+ - 'app/serializers/stage_entity.rb'
+ - 'app/serializers/stage_serializer.rb'
+ - 'app/serializers/suggestion_entity.rb'
+ - 'app/serializers/suggestion_serializer.rb'
+ - 'app/serializers/test_case_entity.rb'
+ - 'app/serializers/test_report_entity.rb'
+ - 'app/serializers/test_report_serializer.rb'
+ - 'app/serializers/test_report_summary_entity.rb'
+ - 'app/serializers/test_report_summary_serializer.rb'
+ - 'app/serializers/test_reports_comparer_entity.rb'
+ - 'app/serializers/test_reports_comparer_serializer.rb'
+ - 'app/serializers/test_suite_comparer_entity.rb'
+ - 'app/serializers/test_suite_entity.rb'
+ - 'app/serializers/test_suite_serializer.rb'
+ - 'app/serializers/test_suite_summary_entity.rb'
+ - 'app/serializers/trigger_variable_entity.rb'
+ - 'app/serializers/triggered_pipeline_entity.rb'
+ - 'app/serializers/user_entity.rb'
+ - 'app/serializers/user_preference_entity.rb'
+ - 'app/serializers/user_serializer.rb'
+ - 'app/serializers/web_ide_terminal_entity.rb'
+ - 'app/serializers/web_ide_terminal_serializer.rb'
+ - 'app/services/access_token_validation_service.rb'
+ - 'app/services/audit_event_service.rb'
+ - 'app/services/auto_merge_service.rb'
+ - 'app/services/base_container_service.rb'
+ - 'app/services/base_count_service.rb'
+ - 'app/services/base_renderer.rb'
+ - 'app/services/base_service.rb'
+ - 'app/services/bulk_create_integration_service.rb'
+ - 'app/services/bulk_import_service.rb'
+ - 'app/services/bulk_push_event_payload_service.rb'
+ - 'app/services/bulk_update_integration_service.rb'
+ - 'app/services/cohorts_service.rb'
+ - 'app/services/compare_service.rb'
+ - 'app/services/container_expiration_policy_service.rb'
+ - 'app/services/event_create_service.rb'
+ - 'app/services/gravatar_service.rb'
+ - 'app/services/import_export_clean_up_service.rb'
+ - 'app/services/issuable_base_service.rb'
+ - 'app/services/issue_rebalancing_service.rb'
+ - 'app/services/markdown_content_rewriter_service.rb'
+ - 'app/services/merge_request_metrics_service.rb'
+ - 'app/services/metrics_service.rb'
+ - 'app/services/note_summary.rb'
+ - 'app/services/notification_service.rb'
+ - 'app/services/onboarding_progress_service.rb'
+ - 'app/services/post_receive_service.rb'
+ - 'app/services/preview_markdown_service.rb'
+ - 'app/services/push_event_payload_service.rb'
+ - 'app/services/repository_archive_clean_up_service.rb'
+ - 'app/services/reset_project_cache_service.rb'
+ - 'app/services/search_service.rb'
+ - 'app/services/service_response.rb'
+ - 'app/services/submit_usage_ping_service.rb'
+ - 'app/services/system_hooks_service.rb'
+ - 'app/services/task_list_toggle_service.rb'
+ - 'app/services/todo_service.rb'
+ - 'app/services/update_container_registry_info_service.rb'
+ - 'app/services/upload_service.rb'
+ - 'app/services/user_agent_detail_service.rb'
+ - 'app/services/user_project_access_changed_service.rb'
+ - 'app/services/verify_pages_domain_service.rb'
+ - 'app/services/web_hook_service.rb'
+ - 'app/services/x509_certificate_revoke_service.rb'
+ - 'app/uploaders/attachment_uploader.rb'
+ - 'app/uploaders/avatar_uploader.rb'
+ - 'app/uploaders/deleted_object_uploader.rb'
+ - 'app/uploaders/dependency_proxy/file_uploader.rb'
+ - 'app/uploaders/external_diff_uploader.rb'
+ - 'app/uploaders/favicon_uploader.rb'
+ - 'app/uploaders/file_mover.rb'
+ - 'app/uploaders/file_uploader.rb'
+ - 'app/uploaders/gitlab_uploader.rb'
+ - 'app/uploaders/import_export_uploader.rb'
+ - 'app/uploaders/job_artifact_uploader.rb'
+ - 'app/uploaders/lfs_object_uploader.rb'
+ - 'app/uploaders/namespace_file_uploader.rb'
+ - 'app/uploaders/personal_file_uploader.rb'
+ - 'app/validators/abstract_path_validator.rb'
+ - 'app/validators/addressable_url_validator.rb'
+ - 'app/validators/array_members_validator.rb'
+ - 'app/validators/branch_filter_validator.rb'
+ - 'app/validators/certificate_fingerprint_validator.rb'
+ - 'app/validators/certificate_key_validator.rb'
+ - 'app/validators/certificate_validator.rb'
+ - 'app/validators/cluster_name_validator.rb'
+ - 'app/validators/color_validator.rb'
+ - 'app/validators/cron_freeze_period_timezone_validator.rb'
+ - 'app/validators/cron_timezone_validator.rb'
+ - 'app/validators/cron_validator.rb'
+ - 'app/validators/devise_email_validator.rb'
+ - 'app/validators/duration_validator.rb'
+ - 'app/validators/feature_flag_strategies_validator.rb'
+ - 'app/validators/feature_flag_user_xids_validator.rb'
+ - 'app/validators/future_date_validator.rb'
+ - 'app/validators/html_safety_validator.rb'
+ - 'app/validators/ip_address_validator.rb'
+ - 'app/validators/js_regex_validator.rb'
+ - 'app/validators/json_schema_validator.rb'
+ - 'app/validators/key_restriction_validator.rb'
+ - 'app/validators/line_code_validator.rb'
+ - 'app/validators/named_ecdsa_key_validator.rb'
+ - 'app/validators/namespace_path_validator.rb'
+ - 'app/validators/project_path_validator.rb'
+ - 'app/validators/public_url_validator.rb'
+ - 'app/validators/qualified_domain_array_validator.rb'
+ - 'app/validators/rsa_key_validator.rb'
+ - 'app/validators/same_project_association_validator.rb'
+ - 'app/validators/sha_validator.rb'
+ - 'app/validators/system_hook_url_validator.rb'
+ - 'app/validators/top_level_group_validator.rb'
+ - 'app/validators/untrusted_regexp_validator.rb'
+ - 'app/validators/nested_attributes_duplicates_validator.rb'
+ - 'app/validators/x509_certificate_credentials_validator.rb'
+ - 'app/validators/zoom_url_validator.rb'
+ - 'app/workers/admin_email_worker.rb'
+ - 'app/workers/approve_blocked_pending_approval_users_worker.rb'
+ - 'app/workers/archive_trace_worker.rb'
+ - 'app/workers/authorized_keys_worker.rb'
+ - 'app/workers/authorized_projects_worker.rb'
+ - 'app/workers/auto_merge_process_worker.rb'
+ - 'app/workers/background_migration_worker.rb'
+ - 'app/workers/build_coverage_worker.rb'
+ - 'app/workers/build_finished_worker.rb'
+ - 'app/workers/build_hooks_worker.rb'
+ - 'app/workers/build_queue_worker.rb'
+ - 'app/workers/build_success_worker.rb'
+ - 'app/workers/build_trace_sections_worker.rb'
+ - 'app/workers/bulk_import_worker.rb'
+ - 'app/workers/chat_notification_worker.rb'
+ - 'app/workers/ci_platform_metrics_update_cron_worker.rb'
+ - 'app/workers/cleanup_container_repository_worker.rb'
+ - 'app/workers/cluster_configure_istio_worker.rb'
+ - 'app/workers/cluster_install_app_worker.rb'
+ - 'app/workers/cluster_patch_app_worker.rb'
+ - 'app/workers/cluster_provision_worker.rb'
+ - 'app/workers/cluster_update_app_worker.rb'
+ - 'app/workers/cluster_upgrade_app_worker.rb'
+ - 'app/workers/cluster_wait_for_app_installation_worker.rb'
+ - 'app/workers/cluster_wait_for_app_update_worker.rb'
+ - 'app/workers/cluster_wait_for_ingress_ip_address_worker.rb'
+ - 'app/workers/container_expiration_policy_worker.rb'
+ - 'app/workers/create_commit_signature_worker.rb'
+ - 'app/workers/create_note_diff_file_worker.rb'
+ - 'app/workers/create_pipeline_worker.rb'
+ - 'app/workers/delete_container_repository_worker.rb'
+ - 'app/workers/delete_diff_files_worker.rb'
+ - 'app/workers/delete_merged_branches_worker.rb'
+ - 'app/workers/delete_stored_files_worker.rb'
+ - 'app/workers/delete_user_worker.rb'
+ - 'app/workers/destroy_pages_deployments_worker.rb'
+ - 'app/workers/detect_repository_languages_worker.rb'
+ - 'app/workers/disallow_two_factor_for_group_worker.rb'
+ - 'app/workers/disallow_two_factor_for_subgroups_worker.rb'
+ - 'app/workers/email_receiver_worker.rb'
+ - 'app/workers/emails_on_push_worker.rb'
+ - 'app/workers/error_tracking_issue_link_worker.rb'
+ - 'app/workers/expire_build_artifacts_worker.rb'
+ - 'app/workers/expire_build_instance_artifacts_worker.rb'
+ - 'app/workers/expire_job_cache_worker.rb'
+ - 'app/workers/expire_pipeline_cache_worker.rb'
+ - 'app/workers/export_csv_worker.rb'
+ - 'app/workers/external_service_reactive_caching_worker.rb'
+ - 'app/workers/file_hook_worker.rb'
+ - 'app/workers/flush_counter_increments_worker.rb'
+ - 'app/workers/git_garbage_collect_worker.rb'
+ - 'app/workers/gitlab_performance_bar_stats_worker.rb'
+ - 'app/workers/gitlab_shell_worker.rb'
+ - 'app/workers/gitlab_usage_ping_worker.rb'
+ - 'app/workers/group_destroy_worker.rb'
+ - 'app/workers/group_export_worker.rb'
+ - 'app/workers/group_import_worker.rb'
+ - 'app/workers/import_export_project_cleanup_worker.rb'
+ - 'app/workers/import_issues_csv_worker.rb'
+ - 'app/workers/invalid_gpg_signature_update_worker.rb'
+ - 'app/workers/irker_worker.rb'
+ - 'app/workers/issuable_export_csv_worker.rb'
+ - 'app/workers/issue_due_scheduler_worker.rb'
+ - 'app/workers/issue_placement_worker.rb'
+ - 'app/workers/issue_rebalancing_worker.rb'
+ - 'app/workers/member_invitation_reminder_emails_worker.rb'
+ - 'app/workers/merge_request_cleanup_refs_worker.rb'
+ - 'app/workers/merge_request_mergeability_check_worker.rb'
+ - 'app/workers/merge_worker.rb'
+ - 'app/workers/migrate_external_diffs_worker.rb'
+ - 'app/workers/namespaceless_project_destroy_worker.rb'
+ - 'app/workers/new_issue_worker.rb'
+ - 'app/workers/new_merge_request_worker.rb'
+ - 'app/workers/new_note_worker.rb'
+ - 'app/workers/pages_domain_removal_cron_worker.rb'
+ - 'app/workers/pages_domain_ssl_renewal_cron_worker.rb'
+ - 'app/workers/pages_domain_ssl_renewal_worker.rb'
+ - 'app/workers/pages_domain_verification_cron_worker.rb'
+ - 'app/workers/pages_domain_verification_worker.rb'
+ - 'app/workers/pages_remove_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'
+ - 'app/workers/pipeline_metrics_worker.rb'
+ - 'app/workers/pipeline_notification_worker.rb'
+ - 'app/workers/pipeline_process_worker.rb'
+ - 'app/workers/pipeline_schedule_worker.rb'
+ - 'app/workers/pipeline_update_worker.rb'
+ - 'app/workers/post_receive.rb'
+ - 'app/workers/process_commit_worker.rb'
+ - 'app/workers/project_cache_worker.rb'
+ - 'app/workers/project_daily_statistics_worker.rb'
+ - 'app/workers/project_destroy_worker.rb'
+ - 'app/workers/project_export_worker.rb'
+ - 'app/workers/project_schedule_bulk_repository_shard_moves_worker.rb'
+ - 'app/workers/project_service_worker.rb'
+ - 'app/workers/project_update_repository_storage_worker.rb'
+ - 'app/workers/propagate_integration_group_worker.rb'
+ - 'app/workers/propagate_integration_inherit_descendant_worker.rb'
+ - 'app/workers/propagate_integration_inherit_worker.rb'
+ - 'app/workers/propagate_integration_project_worker.rb'
+ - 'app/workers/propagate_integration_worker.rb'
+ - 'app/workers/propagate_service_template_worker.rb'
+ - 'app/workers/prune_old_events_worker.rb'
+ - 'app/workers/prune_web_hook_logs_worker.rb'
+ - 'app/workers/purge_dependency_proxy_cache_worker.rb'
+ - 'app/workers/reactive_caching_worker.rb'
+ - 'app/workers/rebase_worker.rb'
+ - 'app/workers/remote_mirror_notification_worker.rb'
+ - 'app/workers/remove_expired_group_links_worker.rb'
+ - 'app/workers/remove_expired_members_worker.rb'
+ - 'app/workers/remove_unaccepted_member_invites_worker.rb'
+ - 'app/workers/remove_unreferenced_lfs_objects_worker.rb'
+ - 'app/workers/repository_archive_cache_worker.rb'
+ - 'app/workers/repository_cleanup_worker.rb'
+ - 'app/workers/repository_fork_worker.rb'
+ - 'app/workers/repository_import_worker.rb'
+ - 'app/workers/repository_remove_remote_worker.rb'
+ - 'app/workers/repository_update_remote_mirror_worker.rb'
+ - 'app/workers/requests_profiles_worker.rb'
+ - 'app/workers/run_pipeline_schedule_worker.rb'
+ - 'app/workers/schedule_merge_request_cleanup_refs_worker.rb'
+ - 'app/workers/schedule_migrate_external_diffs_worker.rb'
+ - 'app/workers/self_monitoring_project_create_worker.rb'
+ - 'app/workers/self_monitoring_project_delete_worker.rb'
+ - 'app/workers/service_desk_email_receiver_worker.rb'
+ - 'app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb'
+ - 'app/workers/snippet_update_repository_storage_worker.rb'
+ - 'app/workers/stage_update_worker.rb'
+ - 'app/workers/stuck_ci_jobs_worker.rb'
+ - 'app/workers/stuck_export_jobs_worker.rb'
+ - 'app/workers/stuck_merge_jobs_worker.rb'
+ - 'app/workers/system_hook_push_worker.rb'
+ - 'app/workers/trending_projects_worker.rb'
+ - 'app/workers/update_container_registry_info_worker.rb'
+ - 'app/workers/update_external_pull_requests_worker.rb'
+ - 'app/workers/update_head_pipeline_for_merge_request_worker.rb'
+ - 'app/workers/update_highest_role_worker.rb'
+ - 'app/workers/update_merge_requests_worker.rb'
+ - 'app/workers/update_project_statistics_worker.rb'
+ - 'app/workers/upload_checksum_worker.rb'
+ - 'app/workers/wait_for_cluster_creation_worker.rb'
+ - 'app/workers/web_hook_worker.rb'
+ - 'app/workers/x509_certificate_revoke_worker.rb'
+ - 'app/workers/x509_issuer_crl_check_worker.rb'
+ - 'ee/app/controllers/countries_controller.rb'
+ - 'ee/app/controllers/country_states_controller.rb'
+ - 'ee/app/controllers/omniauth_kerberos_spnego_controller.rb'
+ - 'ee/app/controllers/operations_controller.rb'
+ - 'ee/app/controllers/sitemap_controller.rb'
+ - 'ee/app/controllers/smartcard_controller.rb'
+ - 'ee/app/controllers/subscriptions_controller.rb'
+ - 'ee/app/controllers/survey_responses_controller.rb'
+ - 'ee/app/controllers/trial_registrations_controller.rb'
+ - 'ee/app/controllers/trials_controller.rb'
+ - 'ee/app/controllers/unsubscribes_controller.rb'
+ - 'ee/app/controllers/usernames_controller.rb'
+ - 'ee/app/finders/audit_log_finder.rb'
+ - 'ee/app/finders/billed_users_finder.rb'
+ - 'ee/app/finders/custom_project_templates_finder.rb'
+ - 'ee/app/finders/dast_scanner_profiles_finder.rb'
+ - 'ee/app/finders/dast_site_profiles_finder.rb'
+ - 'ee/app/finders/dast_site_validations_finder.rb'
+ - 'ee/app/finders/epics_finder.rb'
+ - 'ee/app/finders/geo_node_finder.rb'
+ - 'ee/app/finders/gpg_keys_finder.rb'
+ - 'ee/app/finders/group_saml_identity_finder.rb'
+ - 'ee/app/finders/groups_with_templates_finder.rb'
+ - 'ee/app/finders/iterations_finder.rb'
+ - 'ee/app/finders/licenses_finder.rb'
+ - 'ee/app/finders/merge_requests_compliance_finder.rb'
+ - 'ee/app/finders/merge_trains_finder.rb'
+ - 'ee/app/finders/productivity_analytics_finder.rb'
+ - 'ee/app/finders/scim_finder.rb'
+ - 'ee/app/finders/software_license_policies_finder.rb'
+ - 'ee/app/mailers/ci_minutes_usage_mailer.rb'
+ - 'ee/app/mailers/credentials_inventory_mailer.rb'
+ - 'ee/app/mailers/license_mailer.rb'
+ - 'ee/app/mailers/previews/ci_minutes_usage_mailer_preview.rb'
+ - 'ee/app/mailers/previews/license_mailer_preview.rb'
+ - 'ee/app/models/allowed_email_domain.rb'
+ - 'ee/app/models/approval_merge_request_rule.rb'
+ - 'ee/app/models/approval_merge_request_rule_source.rb'
+ - 'ee/app/models/approval_project_rule.rb'
+ - 'ee/app/models/approval_project_rules_protected_branch.rb'
+ - 'ee/app/models/approval_state.rb'
+ - 'ee/app/models/approval_wrapped_any_approver_rule.rb'
+ - 'ee/app/models/approval_wrapped_code_owner_rule.rb'
+ - 'ee/app/models/approval_wrapped_rule.rb'
+ - 'ee/app/models/approver.rb'
+ - 'ee/app/models/approver_group.rb'
+ - 'ee/app/models/board_assignee.rb'
+ - 'ee/app/models/board_label.rb'
+ - 'ee/app/models/board_user_preference.rb'
+ - 'ee/app/models/burndown.rb'
+ - 'ee/app/models/dast_scanner_profile.rb'
+ - 'ee/app/models/dast_site.rb'
+ - 'ee/app/models/dast_site_profile.rb'
+ - 'ee/app/models/dast_site_token.rb'
+ - 'ee/app/models/dast_site_validation.rb'
+ - 'ee/app/models/elasticsearch_indexed_namespace.rb'
+ - 'ee/app/models/elasticsearch_indexed_project.rb'
+ - 'ee/app/models/epic_issue.rb'
+ - 'ee/app/models/epic_user_mention.rb'
+ - 'ee/app/models/feature_flag_issue.rb'
+ - 'ee/app/models/geo_node.rb'
+ - 'ee/app/models/geo_node_namespace_link.rb'
+ - 'ee/app/models/geo_node_status.rb'
+ - 'ee/app/models/gitlab_subscription.rb'
+ - 'ee/app/models/gitlab_subscription_history.rb'
+ - 'ee/app/models/group_deletion_schedule.rb'
+ - 'ee/app/models/group_merge_request_approval_setting.rb'
+ - 'ee/app/models/group_wiki.rb'
+ - 'ee/app/models/group_wiki_repository.rb'
+ - 'ee/app/models/historical_data.rb'
+ - 'ee/app/models/hooks/group_hook.rb'
+ - 'ee/app/models/index_status.rb'
+ - 'ee/app/models/insight.rb'
+ - 'ee/app/models/instance_security_dashboard.rb'
+ - 'ee/app/models/ip_restriction.rb'
+ - 'ee/app/models/issuable_metric_image.rb'
+ - 'ee/app/models/issuable_sla.rb'
+ - 'ee/app/models/issuables_analytics.rb'
+ - 'ee/app/models/iteration_note.rb'
+ - 'ee/app/models/ldap_group_link.rb'
+ - 'ee/app/models/ldap_key.rb'
+ - 'ee/app/models/license.rb'
+ - 'ee/app/models/merge_request_block.rb'
+ - 'ee/app/models/merge_request_diff_detail.rb'
+ - 'ee/app/models/merge_train.rb'
+ - 'ee/app/models/namespace_limit.rb'
+ - 'ee/app/models/namespace_statistics.rb'
+ - 'ee/app/models/path_lock.rb'
+ - 'ee/app/models/pg_replication_slot.rb'
+ - 'ee/app/models/productivity_analytics.rb'
+ - 'ee/app/models/project_alias.rb'
+ - 'ee/app/models/project_repository_state.rb'
+ - 'ee/app/models/project_security_setting.rb'
+ - 'ee/app/models/project_services/github_service.rb'
+ - 'ee/app/models/project_services/github_service/remote_project.rb'
+ - 'ee/app/models/project_services/github_service/status_message.rb'
+ - 'ee/app/models/project_services/github_service/status_notifier.rb'
+ - 'ee/app/models/project_services/gitlab_slack_application_service.rb'
+ - 'ee/app/models/protected_environment.rb'
+ - 'ee/app/models/push_rule.rb'
+ - 'ee/app/models/resource_iteration_event.rb'
+ - 'ee/app/models/resource_weight_event.rb'
+ - 'ee/app/models/saml_group_link.rb'
+ - 'ee/app/models/saml_provider.rb'
+ - 'ee/app/models/scim_identity.rb'
+ - 'ee/app/models/scim_oauth_access_token.rb'
+ - 'ee/app/models/scoped_label_set.rb'
+ - 'ee/app/models/slack_integration.rb'
+ - 'ee/app/models/smartcard_identity.rb'
+ - 'ee/app/models/software_license.rb'
+ - 'ee/app/models/software_license_policy.rb'
+ - 'ee/app/models/storage_shard.rb'
+ - 'ee/app/models/user_permission_export_upload.rb'
+ - 'ee/app/models/users_ops_dashboard_project.rb'
+ - 'ee/app/models/users_security_dashboard_project.rb'
+ - 'ee/app/models/vulnerability_user_mention.rb'
+ - 'ee/app/models/weight_note.rb'
+ - 'ee/app/policies/approval_merge_request_rule_policy.rb'
+ - 'ee/app/policies/approval_project_rule_policy.rb'
+ - 'ee/app/policies/dast_scanner_profile_policy.rb'
+ - 'ee/app/policies/dast_site_profile_policy.rb'
+ - 'ee/app/policies/dast_site_validation_policy.rb'
+ - 'ee/app/policies/epic_policy.rb'
+ - 'ee/app/policies/geo_node_policy.rb'
+ - 'ee/app/policies/instance_security_dashboard_policy.rb'
+ - 'ee/app/policies/issuable_metric_image_policy.rb'
+ - 'ee/app/policies/iteration_policy.rb'
+ - 'ee/app/policies/saml_provider_policy.rb'
+ - 'ee/app/policies/timelog_policy.rb'
+ - 'ee/app/policies/vulnerability_policy.rb'
+ - 'ee/app/presenters/approval_rule_presenter.rb'
+ - 'ee/app/presenters/audit_event_presenter.rb'
+ - 'ee/app/presenters/epic_issue_presenter.rb'
+ - 'ee/app/presenters/epic_presenter.rb'
+ - 'ee/app/presenters/iteration_presenter.rb'
+ - 'ee/app/presenters/merge_request_approver_presenter.rb'
+ - 'ee/app/presenters/subscription_presenter.rb'
+ - 'ee/app/presenters/vulnerability_presenter.rb'
+ - 'ee/app/serializers/audit_event_entity.rb'
+ - 'ee/app/serializers/audit_event_serializer.rb'
+ - 'ee/app/serializers/blocking_merge_request_entity.rb'
+ - 'ee/app/serializers/board_assignee_entity.rb'
+ - 'ee/app/serializers/board_label_entity.rb'
+ - 'ee/app/serializers/board_milestone_entity.rb'
+ - 'ee/app/serializers/dashboard_environment_entity.rb'
+ - 'ee/app/serializers/dashboard_environments_project_entity.rb'
+ - 'ee/app/serializers/dashboard_environments_serializer.rb'
+ - 'ee/app/serializers/dashboard_operations_project_entity.rb'
+ - 'ee/app/serializers/dashboard_operations_serializer.rb'
+ - 'ee/app/serializers/dependency_entity.rb'
+ - 'ee/app/serializers/dependency_list_entity.rb'
+ - 'ee/app/serializers/dependency_list_serializer.rb'
+ - 'ee/app/serializers/epic_base_entity.rb'
+ - 'ee/app/serializers/epic_entity.rb'
+ - 'ee/app/serializers/epic_note_entity.rb'
+ - 'ee/app/serializers/epic_note_serializer.rb'
+ - 'ee/app/serializers/epic_serializer.rb'
+ - 'ee/app/serializers/file_lock_entity.rb'
+ - 'ee/app/serializers/geo_design_registry_entity.rb'
+ - 'ee/app/serializers/geo_design_registry_serializer.rb'
+ - 'ee/app/serializers/geo_node_serializer.rb'
+ - 'ee/app/serializers/geo_node_status_serializer.rb'
+ - 'ee/app/serializers/geo_project_registry_entity.rb'
+ - 'ee/app/serializers/geo_project_registry_serializer.rb'
+ - 'ee/app/serializers/group_analytics_serializer.rb'
+ - 'ee/app/serializers/group_issuable_autocomplete_entity.rb'
+ - 'ee/app/serializers/group_issuable_autocomplete_serializer.rb'
+ - 'ee/app/serializers/group_vulnerability_autocomplete_entity.rb'
+ - 'ee/app/serializers/group_vulnerability_autocomplete_serializer.rb'
+ - 'ee/app/serializers/invited_group_entity.rb'
+ - 'ee/app/serializers/invited_group_serializer.rb'
+ - 'ee/app/serializers/iteration_serializer.rb'
+ - 'ee/app/serializers/license_entity.rb'
+ - 'ee/app/serializers/license_scanning_reports_comparer_entity.rb'
+ - 'ee/app/serializers/license_scanning_reports_comparer_serializer.rb'
+ - 'ee/app/serializers/license_scanning_reports_serializer.rb'
+ - 'ee/app/serializers/licenses_list_entity.rb'
+ - 'ee/app/serializers/licenses_list_serializer.rb'
+ - 'ee/app/serializers/linked_epic_entity.rb'
+ - 'ee/app/serializers/linked_epic_issue_entity.rb'
+ - 'ee/app/serializers/linked_epic_issue_serializer.rb'
+ - 'ee/app/serializers/linked_epic_serializer.rb'
+ - 'ee/app/serializers/linked_feature_flag_issue_entity.rb'
+ - 'ee/app/serializers/linked_feature_flag_issue_serializer.rb'
+ - 'ee/app/serializers/managed_license_entity.rb'
+ - 'ee/app/serializers/managed_license_serializer.rb'
+ - 'ee/app/serializers/merge_request_compliance_entity.rb'
+ - 'ee/app/serializers/metrics_report_metric_entity.rb'
+ - 'ee/app/serializers/metrics_reports_comparer_entity.rb'
+ - 'ee/app/serializers/metrics_reports_comparer_serializer.rb'
+ - 'ee/app/serializers/milestone_serializer.rb'
+ - 'ee/app/serializers/namespace_entity.rb'
+ - 'ee/app/serializers/productivity_analytics_merge_request_entity.rb'
+ - 'ee/app/serializers/report_list_entity.rb'
+ - 'ee/app/serializers/scim_oauth_access_token_entity.rb'
+ - 'ee/app/serializers/storage_shard_entity.rb'
+ - 'ee/app/serializers/storage_shard_serializer.rb'
+ - 'ee/app/serializers/user_analytics_entity.rb'
+ - 'ee/app/serializers/vulnerability_entity.rb'
+ - 'ee/app/serializers/vulnerability_note_entity.rb'
+ - 'ee/app/serializers/vulnerability_note_serializer.rb'
+ - 'ee/app/serializers/vulnerability_serializer.rb'
+ - 'ee/app/services/clear_namespace_shared_runners_minutes_service.rb'
+ - 'ee/app/services/fetch_subscription_plans_service.rb'
+ - 'ee/app/services/ldap_group_reset_service.rb'
+ - 'ee/app/services/start_pull_mirroring_service.rb'
+ - 'ee/app/services/timebox_report_service.rb'
+ - 'ee/app/uploaders/issuable_metric_image_uploader.rb'
+ - 'ee/app/validators/host_validator.rb'
+ - 'ee/app/validators/ldap_filter_validator.rb'
+ - 'ee/app/workers/active_user_count_threshold_worker.rb'
+ - 'ee/app/workers/adjourned_group_deletion_worker.rb'
+ - 'ee/app/workers/adjourned_project_deletion_worker.rb'
+ - 'ee/app/workers/adjourned_projects_deletion_cron_worker.rb'
+ - 'ee/app/workers/admin_emails_worker.rb'
+ - 'ee/app/workers/clear_shared_runners_minutes_worker.rb'
+ - 'ee/app/workers/create_github_webhook_worker.rb'
+ - 'ee/app/workers/dast_site_validation_worker.rb'
+ - 'ee/app/workers/elastic_association_indexer_worker.rb'
+ - 'ee/app/workers/elastic_cluster_reindexing_cron_worker.rb'
+ - 'ee/app/workers/elastic_commit_indexer_worker.rb'
+ - 'ee/app/workers/elastic_delete_project_worker.rb'
+ - 'ee/app/workers/elastic_full_index_worker.rb'
+ - 'ee/app/workers/elastic_index_bulk_cron_worker.rb'
+ - 'ee/app/workers/elastic_index_initial_bulk_cron_worker.rb'
+ - 'ee/app/workers/elastic_indexer_worker.rb'
+ - 'ee/app/workers/elastic_indexing_control_worker.rb'
+ - 'ee/app/workers/elastic_namespace_indexer_worker.rb'
+ - 'ee/app/workers/elastic_namespace_rollout_worker.rb'
+ - 'ee/app/workers/elastic_remove_expired_namespace_subscriptions_from_index_cron_worker.rb'
+ - 'ee/app/workers/geo_repository_destroy_worker.rb'
+ - 'ee/app/workers/group_saml_group_sync_worker.rb'
+ - 'ee/app/workers/historical_data_worker.rb'
+ - 'ee/app/workers/import_software_licenses_worker.rb'
+ - 'ee/app/workers/ingress_modsecurity_counter_metrics_worker.rb'
+ - 'ee/app/workers/iterations_update_status_worker.rb'
+ - 'ee/app/workers/ldap_all_groups_sync_worker.rb'
+ - 'ee/app/workers/ldap_group_sync_worker.rb'
+ - 'ee/app/workers/ldap_sync_worker.rb'
+ - 'ee/app/workers/merge_request_reset_approvals_worker.rb'
+ - 'ee/app/workers/network_policy_metrics_worker.rb'
+ - 'ee/app/workers/new_epic_worker.rb'
+ - 'ee/app/workers/project_import_schedule_worker.rb'
+ - 'ee/app/workers/project_template_export_worker.rb'
+ - 'ee/app/workers/pseudonymizer_worker.rb'
+ - 'ee/app/workers/refresh_license_compliance_checks_worker.rb'
+ - 'ee/app/workers/repository_push_audit_event_worker.rb'
+ - 'ee/app/workers/repository_update_mirror_worker.rb'
+ - 'ee/app/workers/scan_security_report_secrets_worker.rb'
+ - 'ee/app/workers/set_user_status_based_on_user_cap_setting_worker.rb'
+ - 'ee/app/workers/store_security_reports_worker.rb'
+ - 'ee/app/workers/store_security_scans_worker.rb'
+ - 'ee/app/workers/sync_seat_link_request_worker.rb'
+ - 'ee/app/workers/sync_seat_link_worker.rb'
+ - 'ee/app/workers/sync_security_reports_to_report_approval_rules_worker.rb'
+ - 'ee/app/workers/update_all_mirrors_worker.rb'
+ - 'ee/app/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker.rb'
+ - 'ee/lib/generators/rails/geo_migration_generator.rb'
+ - 'ee/lib/gitlab/path_locks_finder.rb'
+ - 'ee/spec/support/elastic_query_name_inspector.rb'
+ - 'ee/spec/support/ssh_keygen.rb'
+ - 'ee/spec/support/test_license.rb'
+ - 'lib/carrier_wave_string_file.rb'
+ - 'lib/csv_builder.rb'
+ - 'lib/event_filter.rb'
+ - 'lib/feature.rb'
+ - 'lib/feature/definition.rb'
+ - 'lib/feature/gitaly.rb'
+ - 'lib/feature/logger.rb'
+ - 'lib/feature/shared.rb'
+ - 'lib/file_size_validator.rb'
+ - 'lib/forever.rb'
+ - 'lib/gitlab_danger.rb'
+ - 'lib/learn_gitlab.rb'
+ - 'lib/tasks/gitlab/graphql.rake'
+ - 'lib/tasks/gitlab/seed/group_seed.rake'
+ - 'lib/tasks/import.rake'
+ - 'lib/tasks/tokens.rake'
+ - 'lib/uploaded_file.rb'
+ - 'lib/version_check.rb'
+ - 'qa/spec/specs/helpers/quarantine_spec.rb'
+ - 'spec/controllers/concerns/page_limiter_spec.rb'
+ - 'spec/lib/bitbucket/collection_spec.rb'
+ - 'spec/lib/gitlab/database/bulk_update_spec.rb'
+ - 'spec/lib/gitlab/multi_destination_logger_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_insertable_associations_spec.rb'
+ - 'spec/models/concerns/triggerable_hooks_spec.rb'
+ - 'spec/support/helpers/bare_repo_operations.rb'
+ - 'spec/support/helpers/ci_artifact_metadata_generator.rb'
+ - 'spec/support/helpers/fake_migration_classes.rb'
+ - 'spec/support/helpers/fake_u2f_device.rb'
+ - 'spec/support/helpers/fake_webauthn_device.rb'
+ - 'spec/support/helpers/markdown_feature.rb'
+ - 'spec/support/helpers/redis_without_keys.rb'
+ - 'spec/support/helpers/require_migration.rb'
+ - 'spec/support/inspect_squelch.rb'
+ - 'spec/support/models/merge_request_without_merge_request_diff.rb'
+ - 'spec/support/renameable_upload.rb'
+ - 'spec/support/sidekiq_middleware.rb'
+ - 'spec/tasks/gitlab/task_helpers_spec.rb'
+ - 'spec/uploaders/object_storage_spec.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index d60ab9b2fcc..0189a3d6372 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -141,7 +141,7 @@ Lint/BinaryOperatorWithIdenticalOperands:
- 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- 'spec/helpers/visibility_level_helper_spec.rb'
- 'spec/lib/gitlab/conan_token_spec.rb'
- - 'spec/lib/gitlab/danger/sidekiq_queues_spec.rb'
+ - 'spec/tooling/danger/sidekiq_queues_spec.rb'
- 'spec/lib/gitlab/git/conflict/parser_spec.rb'
- 'spec/lib/gitlab/graphql/lazy_spec.rb'
- 'spec/models/ci/build_trace_chunk_spec.rb'
@@ -155,20 +155,6 @@ Lint/BinaryOperatorWithIdenticalOperands:
Lint/ConstantDefinitionInBlock:
Enabled: false
-# Offense count: 9
-# Cop supports --auto-correct.
-Lint/DeprecatedOpenSSLConstant:
- Exclude:
- - 'app/services/clusters/kubernetes/configure_istio_ingress_service.rb'
- - 'ee/lib/gitlab/geo/oauth/logout_state.rb'
- - 'lib/gitlab/conan_token.rb'
- - 'lib/gitlab/gitaly_client.rb'
- - 'lib/gitlab/kubernetes/helm/v2/certificate.rb'
- - 'spec/lib/gitlab/conan_token_spec.rb'
- - 'spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb'
- - 'spec/support/helpers/smime_helper.rb'
- - 'spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb'
-
# Offense count: 1
Lint/DuplicateRequire:
Exclude:
@@ -185,8 +171,8 @@ Lint/EmptyFile:
# Cop supports --auto-correct.
Lint/IdentityComparison:
Exclude:
- - 'spec/lib/gitlab/danger/weightage/maintainers_spec.rb'
- - 'spec/lib/gitlab/danger/weightage/reviewers_spec.rb'
+ - 'spec/tooling/danger/weightage/maintainers_spec.rb'
+ - 'spec/tooling/danger/weightage/reviewers_spec.rb'
# Offense count: 184
# Configuration parameters: MaximumRangeSize.
@@ -263,7 +249,7 @@ Metrics/CyclomaticComplexity:
- 'lib/banzai/filter/abstract_reference_filter.rb'
- 'lib/declarative_policy/runner.rb'
- 'lib/gitlab/conflict/file.rb'
- - 'lib/gitlab/danger/roulette.rb'
+ - 'tooling/danger/roulette.rb'
- 'lib/gitlab/diff/parser.rb'
- 'lib/gitlab/rack_attack.rb'
- 'lib/gitlab/sidekiq_cluster/cli.rb'
@@ -285,7 +271,7 @@ Metrics/PerceivedComplexity:
- 'lib/banzai/renderer.rb'
- 'lib/declarative_policy/runner.rb'
- 'lib/gitlab/conflict/file.rb'
- - 'lib/gitlab/danger/roulette.rb'
+ - 'tooling/danger/roulette.rb'
- 'lib/gitlab/rack_attack.rb'
- 'lib/gitlab/sidekiq_cluster/cli.rb'
- 'lib/gitlab/utils/merge_hash.rb'
@@ -629,7 +615,7 @@ Rails/IndexBy:
- 'ee/lib/gitlab/analytics/type_of_work/tasks_by_type.rb'
- 'ee/lib/gitlab/elastic/document_reference.rb'
- 'ee/lib/gitlab/group_plans_preloader.rb'
- - 'lib/gitlab/danger/sidekiq_queues.rb'
+ - 'tooling/danger/sidekiq_queues.rb'
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
- 'lib/gitlab/language_detection.rb'
diff --git a/.stylelintrc b/.stylelintrc
index b0ace93e04f..b9174d1dca1 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -1,4 +1,10 @@
{
+ "ignoreFiles": [
+ "app/assets/stylesheets/pages/emojis.scss",
+ "app/assets/stylesheets/startup/startup-*.scss",
+ "app/assets/stylesheets/lazy_bundles/select2.scss",
+ "app/assets/stylesheets/highlight/themes/*.scss"
+ ],
"plugins":[
"./scripts/frontend/stylelint/stylelint-duplicate-selectors.js",
"./scripts/frontend/stylelint/stylelint-utility-classes.js",
@@ -47,7 +53,7 @@
"indentation":2,
"length-zero-no-unit":true,
"max-nesting-depth":[
- 3,
+ 6,
{
"ignoreAtRules":[
"each",
@@ -97,15 +103,22 @@
}
],
"selector-list-comma-newline-after":"always",
- "selector-max-compound-selectors":[3, { "severity": "warning" }],
+ "selector-max-compound-selectors":[6, { "severity": "warning" }],
"selector-max-id":1,
"selector-no-vendor-prefix":true,
"selector-pseudo-element-colon-notation":"double",
"selector-pseudo-element-no-unknown":true,
"shorthand-property-no-redundant-values":true,
"string-quotes":"single",
- "value-no-vendor-prefix":[true, { "ignoreValues": ["sticky"] }],
+ "value-no-vendor-prefix": [true, { "ignoreValues": ["sticky"] }],
"stylelint-gitlab/duplicate-selectors":[true,{ "severity": "warning" }],
- "stylelint-gitlab/utility-classes":[true,{ "severity": "warning" }]
+ "stylelint-gitlab/utility-classes":[true,{ "severity": "warning" }],
+ "declaration-block-no-duplicate-properties": [
+ true,
+ {
+ "ignore": ["consecutive-duplicates"]
+ }
+ ],
+ "no-eol-whitespace": true,
}
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46776b926c1..ea9b789ce05 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -402,6 +402,40 @@ entry.
- Add verbiage + link sast to show it's in core. !51935
+## 13.7.7 (2021-02-11)
+
+### Security (9 changes)
+
+- Cancel running and pending jobs when a project is deleted. !1220
+- Prevent Denial of Service Attack on gitlab-shell.
+- Prevent exposure of confidential issue titles in file browser.
+- Updates authorization for linting API.
+- Check user access on API merge request read actions.
+- Limit daily invitations to groups and projects.
+- Enforce the analytics enabled project setting for project-level analytics features.
+- Perform SSL verification for FortiTokenCloud Integration.
+- Prevent Server-side Request Forgery for Prometheus when secured by Google IAP.
+
+
+## 13.7.6 (2021-02-01)
+
+### Security (5 changes)
+
+- Filter sensitive GraphQL variables from logs.
+- Avoid exposing release links when the user cannot read git-tag/repository.
+- Sanitize target branch on MR page.
+- Fix DNS rebinding protection bypass when allowing an IP address in Outbound Requests setting.
+- Add routes for unmatched url for not-get requests.
+
+
+## 13.7.5 (2021-01-25)
+
+### Fixed (2 changes, 1 of them is from the community)
+
+- New project guidelines are no longer displayed. !50736 (Roger Meier)
+- Fix LFS not working with S3 specific-storage settings. !52296
+
+
## 13.7.4 (2021-01-13)
### Security (1 change)
@@ -904,6 +938,30 @@ entry.
- Update GitLab Workhorse to v8.57.0.
+## 13.6.7 (2021-02-11)
+
+### Security (7 changes)
+
+- Cancel running and pending jobs when a project is deleted. !1220
+- Updates authorization for linting API.
+- Prevent exposure of confidential issue titles in file browser.
+- Check user access on API merge request read actions.
+- Prevent Denial of Service Attack on gitlab-shell.
+- Limit daily invitations to groups and projects.
+- Prevent Server-side Request Forgery for Prometheus when secured by Google IAP.
+
+
+## 13.6.6 (2021-02-01)
+
+### Security (5 changes)
+
+- Filter sensitive GraphQL variables from logs.
+- Avoid exposing release links when the user cannot read git-tag/repository.
+- Sanitize target branch on MR page.
+- Fix DNS rebinding protection bypass when allowing an IP address in Outbound Requests setting.
+- Add routes for unmatched url for not-get requests.
+
+
## 13.6.5 (2021-01-13)
### Security (1 change)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 030624b8df9..1818bca1e46 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,11 +5,11 @@ By submitting code as an individual you agree to the
By submitting code as an entity you agree to the
[corporate contributor license agreement](doc/legal/corporate_contributor_license_agreement.md).
-All Documentation content that resides under the [doc/ directory](/doc) of this
+All Documentation content that resides under the [`doc/` directory](/doc) of this
repository is licensed under Creative Commons:
[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
-_This notice should stay as the first item in the CONTRIBUTING.md file._
+_This notice should stay as the first item in the `CONTRIBUTING.md` file._
## Contributing Documentation has been moved
diff --git a/Dangerfile b/Dangerfile
index cba7226d4b9..34e0efa027a 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -1,12 +1,9 @@
# frozen_string_literal: true
-require_relative 'lib/gitlab_danger'
-require_relative 'lib/gitlab/danger/request_helper'
+require_relative 'tooling/gitlab_danger'
+require_relative 'tooling/danger/request_helper'
-danger.import_plugin('danger/plugins/helper.rb')
-danger.import_plugin('danger/plugins/roulette.rb')
-danger.import_plugin('danger/plugins/changelog.rb')
-danger.import_plugin('danger/plugins/sidekiq_queues.rb')
+Dir["danger/plugins/*.rb"].sort.each { |f| danger.import_plugin(f) }
return if helper.release_automation?
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 355a70a7731..fe38662db7c 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.8.4 \ No newline at end of file
+4e5fe176e6b36866ba305e5af1ca494b031cadc8
diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
index 834f2629538..c8e38b61405 100644
--- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION
+++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
@@ -1 +1 @@
-2.8.0
+2.9.0
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index 44726955203..8ba26053a68 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-13.8.0
+13.9.1
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 2b17ffd5042..2aeaa11ee27 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.34.0
+1.35.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 548118b6e78..592a1a89678 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.15.1
+13.16.1
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index 8c20f999400..661bb99fdf9 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.59.0
+8.63.0
diff --git a/Gemfile b/Gemfile
index c7ed1cd4d71..58eea956427 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
source 'https://rubygems.org'
gem 'rails', '~> 6.0.3.1'
@@ -10,12 +12,12 @@ gem 'responders', '~> 3.0'
gem 'sprockets', '~> 3.7.0'
# Default values for AR models
-gem 'default_value_for', '~> 3.3.0'
+gem 'default_value_for', '~> 3.4.0'
# Supported DBs
gem 'pg', '~> 1.1'
-gem 'rugged', '~> 0.28'
+gem 'rugged', '~> 1.0.1'
gem 'grape-path-helpers', '~> 1.6.1'
gem 'faraday', '~> 1.0'
@@ -25,8 +27,8 @@ gem 'marginalia', '~> 1.10.0'
gem 'devise', '~> 4.7.2'
# TODO: verify ARM compile issue on 3.1.13+ version (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18828)
gem 'bcrypt', '3.1.12'
-gem 'doorkeeper', '~> 5.3.0'
-gem 'doorkeeper-openid_connect', '~> 1.7.4'
+gem 'doorkeeper', '~> 5.5.0.rc2'
+gem 'doorkeeper-openid_connect', '~> 1.7.5'
gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9'
@@ -81,7 +83,7 @@ gem 'gitlab_omniauth-ldap', '~> 2.1.1', require: 'omniauth-ldap'
gem 'net-ldap', '~> 0.16.3'
# API
-gem 'grape', '~> 1.5.1'
+gem 'grape', '~> 1.5.2'
gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.6', require: 'rack/cors'
@@ -103,7 +105,7 @@ gem 'hashie-forbidden_attributes'
gem 'kaminari', '~> 1.0'
# HAML
-gem 'hamlit', '~> 2.11.0'
+gem 'hamlit', '~> 2.14.4'
# Files attachments
gem 'carrierwave', '~> 1.3'
@@ -154,7 +156,7 @@ gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 2.0.10'
gem 'asciidoctor-include-ext', '~> 0.3.1', require: false
gem 'asciidoctor-plantuml', '~> 0.0.12'
-gem 'asciidoctor-kroki', '~> 0.2.2', require: false
+gem 'asciidoctor-kroki', '~> 0.3.0', require: false
gem 'rouge', '~> 3.26.0'
gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 4.2.0'
@@ -266,7 +268,7 @@ gem 'babosa', '~> 1.0.2'
gem 'loofah', '~> 2.2'
# Working with license
-gem 'licensee', '~> 8.9'
+gem 'licensee', '~> 9.14.1'
# Detect and convert string character encoding
gem 'charlock_holmes', '~> 0.7.7'
@@ -284,6 +286,7 @@ gem 'gitlab_chronic_duration', '~> 0.10.6.2'
gem 'rack-proxy', '~> 0.6.0'
gem 'sassc-rails', '~> 2.1.0'
+gem 'autoprefixer-rails', '10.2.0.0'
gem 'terser', '1.0.2'
gem 'addressable', '~> 2.7'
@@ -292,7 +295,7 @@ gem 'gon', '~> 6.2'
gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0'
-gem "gitlab-license", "~> 1.0"
+gem "gitlab-license", "~> 1.3"
# Protect against bruteforcing
gem 'rack-attack', '~> 6.3.0'
@@ -336,6 +339,7 @@ end
group :development do
gem 'brakeman', '~> 4.2', require: false
gem 'danger', '~> 8.0.6', require: false
+ gem 'lefthook', '~> 0.7', require: false
gem 'letter_opener_web', '~> 1.3.4'
@@ -343,12 +347,12 @@ group :development do
gem 'better_errors', '~> 2.7.1'
# thin instead webrick
- gem 'thin', '~> 1.7.0'
+ gem 'thin', '~> 1.8.0'
end
group :development, :test do
gem 'deprecation_toolkit', '~> 1.5.1', require: false
- gem 'bullet', '~> 6.1.0'
+ gem 'bullet', '~> 6.1.3'
gem 'gitlab-pry-byebug', platform: :mri, require: ['pry-byebug', 'pry-byebug/pry_remote_ext']
gem 'pry-rails', '~> 0.3.9'
gem 'pry-remote'
@@ -357,7 +361,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.7.0'
gem 'factory_bot_rails', '~> 6.1.0'
- gem 'rspec-rails', '~> 4.0.1'
+ gem 'rspec-rails', '~> 4.0.2'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.11.0'
@@ -372,7 +376,7 @@ group :development, :test do
gem 'scss_lint', '~> 0.59.0', require: false
gem 'haml_lint', '~> 0.36.0', require: false
- gem 'bundler-audit', '~> 0.6.1', require: false
+ gem 'bundler-audit', '~> 0.7.0.1', require: false
gem 'benchmark-ips', '~> 2.3.0', require: false
@@ -462,7 +466,7 @@ group :ed25519 do
end
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 13.8.0.pre.rc2'
+gem 'gitaly', '~> 13.9.0.pre.rc1'
gem 'grpc', '~> 1.30.2'
@@ -475,7 +479,7 @@ gem 'flipper', '~> 0.17.1'
gem 'flipper-active_record', '~> 0.17.1'
gem 'flipper-active_support_cache_store', '~> 0.17.1'
gem 'unleash', '~> 0.1.5'
-gem 'gitlab-experiment', '~> 0.4.5'
+gem 'gitlab-experiment', '~> 0.4.9'
# Structured logging
gem 'lograge', '~> 0.5'
@@ -517,3 +521,5 @@ gem 'webauthn', '~> 2.3'
# IPAddress utilities
gem 'ipaddress', '~> 0.8.3'
+
+gem 'parslet', '~> 1.8'
diff --git a/Gemfile.lock b/Gemfile.lock
index b370024b95b..bea01cf000d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -81,10 +81,10 @@ GEM
faraday_middleware (~> 1.0)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.4)
- asciidoctor (2.0.10)
+ asciidoctor (2.0.12)
asciidoctor-include-ext (0.3.1)
asciidoctor (>= 1.5.6, < 3.0.0)
- asciidoctor-kroki (0.2.2)
+ asciidoctor-kroki (0.3.0)
asciidoctor (~> 2.0)
asciidoctor-plantuml (0.0.12)
asciidoctor (>= 1.5.6, < 3.0.0)
@@ -94,6 +94,8 @@ GEM
attr_encrypted (3.1.0)
encryptor (~> 3.0.0)
attr_required (1.0.1)
+ autoprefixer-rails (10.2.0.0)
+ execjs
awesome_print (1.8.0)
awrence (1.1.1)
aws-eventstream (1.1.0)
@@ -145,12 +147,12 @@ GEM
brakeman (4.2.1)
browser (4.2.0)
builder (3.2.4)
- bullet (6.1.0)
+ bullet (6.1.3)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
- bundler-audit (0.6.1)
+ bundler-audit (0.7.0.1)
bundler (>= 1.2.0, < 3)
- thor (~> 0.18)
+ thor (>= 0.18, < 2)
byebug (11.1.3)
capybara (3.34.0)
addressable
@@ -205,7 +207,7 @@ GEM
git
css_parser (1.7.0)
addressable
- daemons (1.2.6)
+ daemons (1.3.1)
danger (8.0.6)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
@@ -225,8 +227,8 @@ GEM
html-pipeline
declarative (0.0.20)
declarative-option (0.1.0)
- default_value_for (3.3.0)
- activerecord (>= 3.2.0, < 6.1)
+ default_value_for (3.4.0)
+ activerecord (>= 3.2.0, < 7.0)
deprecation_toolkit (1.5.1)
activesupport (>= 4.2)
derailed_benchmarks (1.8.1)
@@ -260,11 +262,12 @@ GEM
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
- doorkeeper (5.3.3)
+ doorkeeper (5.5.0.rc2)
railties (>= 5)
- doorkeeper-openid_connect (1.7.4)
+ doorkeeper-openid_connect (1.7.5)
doorkeeper (>= 5.2, < 5.5)
json-jwt (>= 1.11.0)
+ dotenv (2.7.6)
dry-configurable (0.12.0)
concurrent-ruby (~> 1.0)
dry-core (~> 0.5, >= 0.5.0)
@@ -417,12 +420,12 @@ GEM
rails (>= 3.2.0)
git (1.7.0)
rchardet (~> 1.8)
- gitaly (13.8.0.pre.rc2)
+ gitaly (13.9.0.pre.rc1)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-experiment (0.4.5)
+ gitlab-experiment (0.4.9)
activesupport (>= 3.0)
scientist (~> 1.5, >= 1.5.0)
gitlab-fog-azure-rm (1.0.0)
@@ -440,7 +443,7 @@ GEM
jaeger-client (~> 1.1)
opentracing (~> 0.4)
redis (> 3.0.0, < 5.0.0)
- gitlab-license (1.0.0)
+ gitlab-license (1.3.0)
gitlab-mail_room (0.0.8)
gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1)
@@ -492,7 +495,7 @@ GEM
signet (~> 0.14)
gpgme (2.0.20)
mini_portile2 (~> 2.3)
- grape (1.5.1)
+ grape (1.5.2)
activesupport
builder
dry-types (>= 1.1)
@@ -557,7 +560,7 @@ GEM
rainbow
rubocop (>= 0.50.0)
sysexits (~> 1.1)
- hamlit (2.11.0)
+ hamlit (2.14.4)
temple (>= 0.8.2)
thor
tilt
@@ -658,6 +661,7 @@ GEM
rest-client (~> 2.0)
launchy (2.4.3)
addressable (~> 2.3)
+ lefthook (0.7.2)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (1.3.4)
@@ -671,8 +675,12 @@ GEM
toml (= 0.2.0)
with_env (= 1.1.0)
xml-simple
- licensee (8.9.2)
- rugged (~> 0.24)
+ licensee (9.14.1)
+ dotenv (~> 2.0)
+ octokit (~> 4.17)
+ reverse_markdown (~> 1.0)
+ rugged (>= 0.24, < 2.0)
+ thor (>= 0.19, < 2.0)
listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
@@ -753,7 +761,7 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
- octokit (4.15.0)
+ octokit (4.20.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
oj (3.10.6)
@@ -987,6 +995,8 @@ GEM
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
retriable (3.1.2)
+ reverse_markdown (1.4.0)
+ nokogiri
rexml (3.2.4)
rinku (2.0.0)
rotp (2.1.2)
@@ -999,12 +1009,12 @@ GEM
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
- rspec-core (3.10.0)
+ rspec-core (3.10.1)
rspec-support (~> 3.10.0)
- rspec-expectations (3.10.0)
+ rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
- rspec-mocks (3.10.0)
+ rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-parameterized (0.4.2)
@@ -1013,17 +1023,17 @@ GEM
proc_to_ast
rspec (>= 2.13, < 4)
unparser
- rspec-rails (4.0.1)
+ rspec-rails (4.0.2)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
- rspec-core (~> 3.9)
- rspec-expectations (~> 3.9)
- rspec-mocks (~> 3.9)
- rspec-support (~> 3.9)
+ rspec-core (~> 3.10)
+ rspec-expectations (~> 3.10)
+ rspec-mocks (~> 3.10)
+ rspec-support (~> 3.10)
rspec-retry (0.6.1)
rspec-core (> 3.3)
- rspec-support (3.10.0)
+ rspec-support (3.10.2)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
rspec_profiling (0.0.6)
@@ -1069,7 +1079,7 @@ GEM
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (2.0.0)
- rugged (0.28.4.1)
+ rugged (1.0.1)
safe_yaml (1.0.4)
safety_net_attestation (0.4.0)
jwt (~> 2.0)
@@ -1170,11 +1180,11 @@ GEM
execjs (>= 0.3.0, < 3)
test-prof (0.12.0)
text (1.3.1)
- thin (1.7.2)
+ thin (1.8.0)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
- thor (0.20.3)
+ thor (1.1.0)
thread_safe (0.3.6)
thrift (0.13.0)
tilt (2.0.10)
@@ -1281,10 +1291,11 @@ DEPENDENCIES
asana (~> 0.10.3)
asciidoctor (~> 2.0.10)
asciidoctor-include-ext (~> 0.3.1)
- asciidoctor-kroki (~> 0.2.2)
+ asciidoctor-kroki (~> 0.3.0)
asciidoctor-plantuml (~> 0.0.12)
atlassian-jwt (~> 0.2.0)
attr_encrypted (~> 3.1.0)
+ autoprefixer-rails (= 10.2.0.0)
awesome_print
aws-sdk-cloudformation (~> 1)
aws-sdk-core (~> 3)
@@ -1301,8 +1312,8 @@ DEPENDENCIES
bootstrap_form (~> 4.2.0)
brakeman (~> 4.2)
browser (~> 4.2)
- bullet (~> 6.1.0)
- bundler-audit (~> 0.6.1)
+ bullet (~> 6.1.3)
+ bundler-audit (~> 0.7.0.1)
capybara (~> 3.34.0)
capybara-screenshot (~> 1.0.22)
carrierwave (~> 1.3)
@@ -1316,7 +1327,7 @@ DEPENDENCIES
danger (~> 8.0.6)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1)
- default_value_for (~> 3.3.0)
+ default_value_for (~> 3.4.0)
deprecation_toolkit (~> 1.5.1)
derailed_benchmarks
device_detector
@@ -1325,8 +1336,8 @@ DEPENDENCIES
diff_match_patch (~> 0.1.0)
diffy (~> 3.3)
discordrb-webhooks-blackst0ne (~> 3.3)
- doorkeeper (~> 5.3.0)
- doorkeeper-openid_connect (~> 1.7.4)
+ doorkeeper (~> 5.5.0.rc2)
+ doorkeeper-openid_connect (~> 1.7.5)
ed25519 (~> 1.2)
elasticsearch-api (~> 6.8.2)
elasticsearch-model (~> 6.1)
@@ -1357,13 +1368,13 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 13.8.0.pre.rc2)
+ gitaly (~> 13.9.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-experiment (~> 0.4.5)
+ gitlab-experiment (~> 0.4.9)
gitlab-fog-azure-rm (~> 1.0)
gitlab-labkit (= 0.14.0)
- gitlab-license (~> 1.0)
+ gitlab-license (~> 1.3)
gitlab-mail_room (~> 0.0.8)
gitlab-markup (~> 1.7.1)
gitlab-net-dns (~> 0.9.1)
@@ -1376,7 +1387,7 @@ DEPENDENCIES
google-api-client (~> 0.33)
google-protobuf (~> 3.12)
gpgme (~> 2.0.19)
- grape (~> 1.5.1)
+ grape (~> 1.5.2)
grape-entity (~> 0.7.1)
grape-path-helpers (~> 1.6.1)
grape_logging (~> 1.7)
@@ -1388,7 +1399,7 @@ DEPENDENCIES
gssapi
guard-rspec
haml_lint (~> 0.36.0)
- hamlit (~> 2.11.0)
+ hamlit (~> 2.14.4)
hangouts-chat (~> 0.0.5)
hashie
hashie-forbidden_attributes
@@ -1410,9 +1421,10 @@ DEPENDENCIES
knapsack (~> 1.17)
kramdown (~> 2.3.0)
kubeclient (~> 4.9.1)
+ lefthook (~> 0.7)
letter_opener_web (~> 1.3.4)
license_finder (~> 6.0)
- licensee (~> 8.9)
+ licensee (~> 9.14.1)
lockbox (~> 0.3.3)
lograge (~> 0.5)
loofah (~> 2.2)
@@ -1452,6 +1464,7 @@ DEPENDENCIES
omniauth_openid_connect (~> 0.3.5)
org-ruby (~> 0.9.12)
parallel (~> 1.19)
+ parslet (~> 1.8)
peek (~> 1.1)
pg (~> 1.1)
pg_query (~> 1.3.0)
@@ -1487,7 +1500,7 @@ DEPENDENCIES
rouge (~> 3.26.0)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
- rspec-rails (~> 4.0.1)
+ rspec-rails (~> 4.0.2)
rspec-retry (~> 0.6.1)
rspec_junit_formatter
rspec_profiling (~> 0.0.6)
@@ -1496,7 +1509,7 @@ DEPENDENCIES
ruby-progressbar (~> 1.10)
ruby_parser (~> 3.15)
rubyzip (~> 2.0.0)
- rugged (~> 0.28)
+ rugged (~> 1.0.1)
sanitize (~> 5.2.1)
sassc-rails (~> 2.1.0)
scss_lint (~> 0.59.0)
@@ -1521,7 +1534,7 @@ DEPENDENCIES
sys-filesystem (~> 1.1.6)
terser (= 1.0.2)
test-prof (~> 0.12.0)
- thin (~> 1.7.0)
+ thin (~> 1.8.0)
timecop (~> 0.9.1)
toml-rb (~> 1.0.0)
truncato (~> 0.7.11)
diff --git a/Rakefile b/Rakefile
index de0d6695c7b..445542e5c00 100755
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,6 @@
#!/usr/bin/env rake
+# frozen_string_literal: true
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
diff --git a/app/assets/images/auth_buttons/openid_64.png b/app/assets/images/auth_buttons/openid_64.png
new file mode 100644
index 00000000000..7b53d129f95
--- /dev/null
+++ b/app/assets/images/auth_buttons/openid_64.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/create-0.png b/app/assets/images/mailers/in_product_marketing/create-0.png
new file mode 100644
index 00000000000..7fc992f14f2
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/create-0.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/create-1.png b/app/assets/images/mailers/in_product_marketing/create-1.png
new file mode 100644
index 00000000000..0315ffefb31
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/create-1.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/create-2.png b/app/assets/images/mailers/in_product_marketing/create-2.png
new file mode 100644
index 00000000000..619f9fcd659
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/create-2.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/gitlab-logo-gray-rgb.png b/app/assets/images/mailers/in_product_marketing/gitlab-logo-gray-rgb.png
new file mode 100644
index 00000000000..31083af512e
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/gitlab-logo-gray-rgb.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/team-0.png b/app/assets/images/mailers/in_product_marketing/team-0.png
new file mode 100644
index 00000000000..f10ae998efa
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/team-0.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/team-1.png b/app/assets/images/mailers/in_product_marketing/team-1.png
new file mode 100644
index 00000000000..cd68464e6e8
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/team-1.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/team-2.png b/app/assets/images/mailers/in_product_marketing/team-2.png
new file mode 100644
index 00000000000..b199c659943
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/team-2.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/trial-0.png b/app/assets/images/mailers/in_product_marketing/trial-0.png
new file mode 100644
index 00000000000..3b0d7a8ecd8
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/trial-0.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/trial-1.png b/app/assets/images/mailers/in_product_marketing/trial-1.png
new file mode 100644
index 00000000000..3a30b2acaee
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/trial-1.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/trial-2.png b/app/assets/images/mailers/in_product_marketing/trial-2.png
new file mode 100644
index 00000000000..95bd965b49f
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/trial-2.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/verify-0.png b/app/assets/images/mailers/in_product_marketing/verify-0.png
new file mode 100644
index 00000000000..04b6f172b37
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/verify-0.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/verify-1.png b/app/assets/images/mailers/in_product_marketing/verify-1.png
new file mode 100644
index 00000000000..8997e8ba575
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/verify-1.png
Binary files differ
diff --git a/app/assets/images/mailers/in_product_marketing/verify-2.png b/app/assets/images/mailers/in_product_marketing/verify-2.png
new file mode 100644
index 00000000000..93c99dee246
--- /dev/null
+++ b/app/assets/images/mailers/in_product_marketing/verify-2.png
Binary files differ
diff --git a/app/assets/javascripts/actioncable_connection_monitor.js b/app/assets/javascripts/actioncable_connection_monitor.js
new file mode 100644
index 00000000000..fc4e436c7fb
--- /dev/null
+++ b/app/assets/javascripts/actioncable_connection_monitor.js
@@ -0,0 +1,142 @@
+/* eslint-disable no-restricted-globals */
+
+import { logger } from '@rails/actioncable';
+
+// This is based on https://github.com/rails/rails/blob/5a477890c809d4a17dc0dede43c6b8cef81d8175/actioncable/app/javascript/action_cable/connection_monitor.js
+// so that we can take advantage of the improved reconnection logic. We can remove this once we upgrade @rails/actioncable to a version that includes this.
+
+// Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting
+// revival reconnections if things go astray. Internal class, not intended for direct user manipulation.
+
+const now = () => new Date().getTime();
+
+const secondsSince = (time) => (now() - time) / 1000;
+class ConnectionMonitor {
+ constructor(connection) {
+ this.visibilityDidChange = this.visibilityDidChange.bind(this);
+ this.connection = connection;
+ this.reconnectAttempts = 0;
+ }
+
+ start() {
+ if (!this.isRunning()) {
+ this.startedAt = now();
+ delete this.stoppedAt;
+ this.startPolling();
+ addEventListener('visibilitychange', this.visibilityDidChange);
+ logger.log(
+ `ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`,
+ );
+ }
+ }
+
+ stop() {
+ if (this.isRunning()) {
+ this.stoppedAt = now();
+ this.stopPolling();
+ removeEventListener('visibilitychange', this.visibilityDidChange);
+ logger.log('ConnectionMonitor stopped');
+ }
+ }
+
+ isRunning() {
+ return this.startedAt && !this.stoppedAt;
+ }
+
+ recordPing() {
+ this.pingedAt = now();
+ }
+
+ recordConnect() {
+ this.reconnectAttempts = 0;
+ this.recordPing();
+ delete this.disconnectedAt;
+ logger.log('ConnectionMonitor recorded connect');
+ }
+
+ recordDisconnect() {
+ this.disconnectedAt = now();
+ logger.log('ConnectionMonitor recorded disconnect');
+ }
+
+ // Private
+
+ startPolling() {
+ this.stopPolling();
+ this.poll();
+ }
+
+ stopPolling() {
+ clearTimeout(this.pollTimeout);
+ }
+
+ poll() {
+ this.pollTimeout = setTimeout(() => {
+ this.reconnectIfStale();
+ this.poll();
+ }, this.getPollInterval());
+ }
+
+ getPollInterval() {
+ const { staleThreshold, reconnectionBackoffRate } = this.constructor;
+ const backoff = (1 + reconnectionBackoffRate) ** Math.min(this.reconnectAttempts, 10);
+ const jitterMax = this.reconnectAttempts === 0 ? 1.0 : reconnectionBackoffRate;
+ const jitter = jitterMax * Math.random();
+ return staleThreshold * 1000 * backoff * (1 + jitter);
+ }
+
+ reconnectIfStale() {
+ if (this.connectionIsStale()) {
+ logger.log(
+ `ConnectionMonitor detected stale connection. reconnectAttempts = ${
+ this.reconnectAttempts
+ }, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${
+ this.constructor.staleThreshold
+ } s`,
+ );
+ this.reconnectAttempts += 1;
+ if (this.disconnectedRecently()) {
+ logger.log(
+ `ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(
+ this.disconnectedAt,
+ )} s`,
+ );
+ } else {
+ logger.log('ConnectionMonitor reopening');
+ this.connection.reopen();
+ }
+ }
+ }
+
+ get refreshedAt() {
+ return this.pingedAt ? this.pingedAt : this.startedAt;
+ }
+
+ connectionIsStale() {
+ return secondsSince(this.refreshedAt) > this.constructor.staleThreshold;
+ }
+
+ disconnectedRecently() {
+ return (
+ this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold
+ );
+ }
+
+ visibilityDidChange() {
+ if (document.visibilityState === 'visible') {
+ setTimeout(() => {
+ if (this.connectionIsStale() || !this.connection.isOpen()) {
+ logger.log(
+ `ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`,
+ );
+ this.connection.reopen();
+ }
+ }, 200);
+ }
+ }
+}
+
+ConnectionMonitor.staleThreshold = 6; // Server::Connections::BEAT_INTERVAL * 2 (missed two pings)
+ConnectionMonitor.reconnectionBackoffRate = 0.15;
+
+export default ConnectionMonitor;
diff --git a/app/assets/javascripts/actioncable_consumer.js b/app/assets/javascripts/actioncable_consumer.js
index 5658ffc1a38..aeb61e61a3d 100644
--- a/app/assets/javascripts/actioncable_consumer.js
+++ b/app/assets/javascripts/actioncable_consumer.js
@@ -1,3 +1,10 @@
import { createConsumer } from '@rails/actioncable';
+import ConnectionMonitor from './actioncable_connection_monitor';
-export default createConsumer();
+const consumer = createConsumer();
+
+if (consumer.connection) {
+ consumer.connection.monitor = new ConnectionMonitor(consumer.connection);
+}
+
+export default consumer;
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index 6b9f46dcfb6..5064d9ee2d2 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -2,8 +2,8 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
-import Pager from './pager';
import { localTimeAgo } from './lib/utils/datetime_utility';
+import Pager from './pager';
export default class Activities {
constructor(container = '') {
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 c58ded3f1f5..5d074698ea4 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,10 +1,11 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlModal, GlTabs, GlTab, GlSearchBoxByType, GlSprintf } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import ReviewTabContainer from '~/add_context_commits_modal/components/review_tab_container.vue';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
findCommitIndex,
setCommitStatus,
@@ -119,7 +120,7 @@ export default {
openModal() {
this.searchCommits();
this.fetchContextCommits();
- this.$root.$emit('bv::show::modal', 'add-review-item');
+ this.$root.$emit(BV_SHOW_MODAL, 'add-review-item');
},
handleTabChange(tabIndex) {
if (tabIndex === 0) {
diff --git a/app/assets/javascripts/add_context_commits_modal/index.js b/app/assets/javascripts/add_context_commits_modal/index.js
index b5cd111fabc..697d32664e8 100644
--- a/app/assets/javascripts/add_context_commits_modal/index.js
+++ b/app/assets/javascripts/add_context_commits_modal/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
-import createStore from './store';
import AddContextCommitsModalTrigger from './components/add_context_commits_modal_trigger.vue';
import AddContextCommitsModalWrapper from './components/add_context_commits_modal_wrapper.vue';
+import createStore from './store';
export default function initAddContextCommitsTriggers() {
const addContextCommitsModalTriggerEl = document.querySelector('.add-review-item-modal-trigger');
diff --git a/app/assets/javascripts/add_context_commits_modal/store/actions.js b/app/assets/javascripts/add_context_commits_modal/store/actions.js
index 1bf54b159ee..7b6f4c81bd2 100644
--- a/app/assets/javascripts/add_context_commits_modal/store/actions.js
+++ b/app/assets/javascripts/add_context_commits_modal/store/actions.js
@@ -1,8 +1,8 @@
import _ from 'lodash';
-import axios from '~/lib/utils/axios_utils';
+import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
-import Api from '~/api';
import * as types from './mutation_types';
export const setBaseConfig = ({ commit }, options) => {
diff --git a/app/assets/javascripts/admin/statistics_panel/components/app.vue b/app/assets/javascripts/admin/statistics_panel/components/app.vue
index 29077d926cf..1f0db422807 100644
--- a/app/assets/javascripts/admin/statistics_panel/components/app.vue
+++ b/app/assets/javascripts/admin/statistics_panel/components/app.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapGetters, mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mapState, mapGetters, mapActions } from 'vuex';
import statisticsLabels from '../constants';
export default {
@@ -26,8 +26,8 @@ export default {
</script>
<template>
- <div class="info-well">
- <div class="well-segment admin-well admin-well-statistics">
+ <div class="gl-card">
+ <div class="gl-card-body">
<h4>{{ __('Statistics') }}</h4>
<gl-loading-icon v-if="isLoading" size="md" class="my-3" />
<template v-else>
diff --git a/app/assets/javascripts/admin/statistics_panel/index.js b/app/assets/javascripts/admin/statistics_panel/index.js
index 8c49fffe630..2f8c3d2e167 100644
--- a/app/assets/javascripts/admin/statistics_panel/index.js
+++ b/app/assets/javascripts/admin/statistics_panel/index.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import StatisticsPanelApp from './components/app.vue';
import createStore from './store';
-export default function (el) {
+export default function initStatisticsPanel(el) {
if (!el) {
return false;
}
diff --git a/app/assets/javascripts/admin/statistics_panel/store/actions.js b/app/assets/javascripts/admin/statistics_panel/store/actions.js
index 149540c4222..459f11c02f1 100644
--- a/app/assets/javascripts/admin/statistics_panel/store/actions.js
+++ b/app/assets/javascripts/admin/statistics_panel/store/actions.js
@@ -1,7 +1,7 @@
import Api from '~/api';
-import { s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import * as types from './mutation_types';
export const requestStatistics = ({ commit }) => commit(types.REQUEST_STATISTICS);
diff --git a/app/assets/javascripts/admin/users/components/actions/activate.vue b/app/assets/javascripts/admin/users/components/actions/activate.vue
new file mode 100644
index 00000000000..99c260bf11e
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/activate.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ modalAttributes() {
+ return {
+ 'data-path': this.path,
+ 'data-method': 'put',
+ 'data-modal-attributes': JSON.stringify({
+ title: sprintf(s__('AdminUsers|Activate user %{username}?'), {
+ username: this.username,
+ }),
+ message: s__('AdminUsers|You can always deactivate their account again if needed.'),
+ okVariant: 'confirm',
+ okTitle: s__('AdminUsers|Activate'),
+ }),
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item>
+ <slot></slot>
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/approve.vue b/app/assets/javascripts/admin/users/components/actions/approve.vue
new file mode 100644
index 00000000000..6fc43c246ea
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/approve.vue
@@ -0,0 +1,21 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown-item :href="path" data-method="put">
+ <slot></slot>
+ </gl-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/block.vue b/app/assets/javascripts/admin/users/components/actions/block.vue
new file mode 100644
index 00000000000..68dfefe14c2
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/block.vue
@@ -0,0 +1,53 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
+const messageHtml = `
+ <p>${s__('AdminUsers|Blocking user has the following effects:')}</p>
+ <ul>
+ <li>${s__('AdminUsers|User will not be able to login')}</li>
+ <li>${s__('AdminUsers|User will not be able to access git repositories')}</li>
+ <li>${s__('AdminUsers|Personal projects will be left')}</li>
+ <li>${s__('AdminUsers|Owned groups will be left')}</li>
+ </ul>
+`;
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ modalAttributes() {
+ return {
+ 'data-path': this.path,
+ 'data-method': 'put',
+ 'data-modal-attributes': JSON.stringify({
+ title: sprintf(s__('AdminUsers|Block user %{username}?'), { username: this.username }),
+ okVariant: 'confirm',
+ okTitle: s__('AdminUsers|Block'),
+ messageHtml,
+ }),
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item>
+ <slot></slot>
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/deactivate.vue b/app/assets/javascripts/admin/users/components/actions/deactivate.vue
new file mode 100644
index 00000000000..7e0c17ba296
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/deactivate.vue
@@ -0,0 +1,60 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
+const messageHtml = `
+ <p>${s__('AdminUsers|Deactivating a user has the following effects:')}</p>
+ <ul>
+ <li>${s__('AdminUsers|The user will be logged out')}</li>
+ <li>${s__('AdminUsers|The user will not be able to access git repositories')}</li>
+ <li>${s__('AdminUsers|The user will not be able to access the API')}</li>
+ <li>${s__('AdminUsers|The user will not receive any notifications')}</li>
+ <li>${s__('AdminUsers|The user will not be able to use slash commands')}</li>
+ <li>${s__(
+ 'AdminUsers|When the user logs back in, their account will reactivate as a fully active account',
+ )}</li>
+ <li>${s__('AdminUsers|Personal projects, group and user history will be left intact')}</li>
+ </ul>
+`;
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ modalAttributes() {
+ return {
+ 'data-path': this.path,
+ 'data-method': 'put',
+ 'data-modal-attributes': JSON.stringify({
+ title: sprintf(s__('AdminUsers|Deactivate user %{username}?'), {
+ username: this.username,
+ }),
+ okVariant: 'confirm',
+ okTitle: s__('AdminUsers|Deactivate'),
+ messageHtml,
+ }),
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item>
+ <slot></slot>
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/delete.vue b/app/assets/javascripts/admin/users/components/actions/delete.vue
new file mode 100644
index 00000000000..725d3dbf388
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/delete.vue
@@ -0,0 +1,25 @@
+<script>
+import SharedDeleteAction from './shared/shared_delete_action.vue';
+
+export default {
+ components: {
+ SharedDeleteAction,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ paths: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <shared-delete-action modal-type="delete" :username="username" :paths="paths">
+ <slot></slot>
+ </shared-delete-action>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue b/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue
new file mode 100644
index 00000000000..0ae15bfbebb
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue
@@ -0,0 +1,25 @@
+<script>
+import SharedDeleteAction from './shared/shared_delete_action.vue';
+
+export default {
+ components: {
+ SharedDeleteAction,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ paths: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <shared-delete-action modal-type="delete-with-contributions" :username="username" :paths="paths">
+ <slot></slot>
+ </shared-delete-action>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/index.js b/app/assets/javascripts/admin/users/components/actions/index.js
new file mode 100644
index 00000000000..e34b01346b9
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/index.js
@@ -0,0 +1,21 @@
+import Activate from './activate.vue';
+import Approve from './approve.vue';
+import Block from './block.vue';
+import Deactivate from './deactivate.vue';
+import Delete from './delete.vue';
+import DeleteWithContributions from './delete_with_contributions.vue';
+import Reject from './reject.vue';
+import Unblock from './unblock.vue';
+import Unlock from './unlock.vue';
+
+export default {
+ Activate,
+ Approve,
+ Block,
+ Deactivate,
+ Delete,
+ DeleteWithContributions,
+ Unblock,
+ Unlock,
+ Reject,
+};
diff --git a/app/assets/javascripts/admin/users/components/actions/reject.vue b/app/assets/javascripts/admin/users/components/actions/reject.vue
new file mode 100644
index 00000000000..a80c1ff5458
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/reject.vue
@@ -0,0 +1,21 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown-item :href="path" data-method="delete">
+ <slot></slot>
+ </gl-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue b/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue
new file mode 100644
index 00000000000..9107d9ccdd9
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue
@@ -0,0 +1,43 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ paths: {
+ type: Object,
+ required: true,
+ },
+ modalType: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ modalAttributes() {
+ return {
+ 'data-block-user-url': this.paths.block,
+ 'data-delete-user-url': this.paths.delete,
+ 'data-gl-modal-action': this.modalType,
+ 'data-username': this.username,
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="js-delete-user-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item>
+ <span class="gl-text-red-500">
+ <slot></slot>
+ </span>
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/unblock.vue b/app/assets/javascripts/admin/users/components/actions/unblock.vue
new file mode 100644
index 00000000000..f2b501caf09
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/unblock.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ modalAttributes() {
+ return {
+ 'data-path': this.path,
+ 'data-method': 'put',
+ 'data-modal-attributes': JSON.stringify({
+ title: sprintf(s__('AdminUsers|Unblock user %{username}?'), { username: this.username }),
+ message: s__(
+ 'AdminUsers|You can always unblock their account, their data will remain intact.',
+ ),
+ okVariant: 'confirm',
+ okTitle: s__('AdminUsers|Unblock'),
+ }),
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item>
+ <slot></slot>
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/unlock.vue b/app/assets/javascripts/admin/users/components/actions/unlock.vue
new file mode 100644
index 00000000000..294aaade7c1
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/actions/unlock.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+import { sprintf, s__, __ } from '~/locale';
+
+export default {
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ username: {
+ type: String,
+ required: true,
+ },
+ path: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ modalAttributes() {
+ return {
+ 'data-path': this.path,
+ 'data-method': 'put',
+ 'data-modal-attributes': JSON.stringify({
+ title: sprintf(s__('AdminUsers|Unlock user %{username}?'), { username: this.username }),
+ message: __('Are you sure?'),
+ okVariant: 'confirm',
+ okTitle: s__('AdminUsers|Unlock'),
+ }),
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item>
+ <slot></slot>
+ </gl-dropdown-item>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue b/app/assets/javascripts/admin/users/components/usage_ping_disabled.vue
index 5da38495010..5da38495010 100644
--- a/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue
+++ b/app/assets/javascripts/admin/users/components/usage_ping_disabled.vue
diff --git a/app/assets/javascripts/admin/users/components/user_actions.vue b/app/assets/javascripts/admin/users/components/user_actions.vue
new file mode 100644
index 00000000000..e92c97b54a3
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/user_actions.vue
@@ -0,0 +1,119 @@
+<script>
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
+} from '@gitlab/ui';
+import { convertArrayToCamelCase } from '~/lib/utils/common_utils';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { I18N_USER_ACTIONS } from '../constants';
+import { generateUserPaths } from '../utils';
+import Actions from './actions';
+
+export default {
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
+ ...Actions,
+ },
+ props: {
+ user: {
+ type: Object,
+ required: true,
+ },
+ paths: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ userActions() {
+ return convertArrayToCamelCase(this.user.actions);
+ },
+ dropdownActions() {
+ return this.userActions.filter((a) => a !== 'edit');
+ },
+ dropdownDeleteActions() {
+ return this.dropdownActions.filter((a) => a.includes('delete'));
+ },
+ dropdownSafeActions() {
+ return this.dropdownActions.filter((a) => !this.dropdownDeleteActions.includes(a));
+ },
+ hasDropdownActions() {
+ return this.dropdownActions.length > 0;
+ },
+ hasDeleteActions() {
+ return this.dropdownDeleteActions.length > 0;
+ },
+ hasEditAction() {
+ return this.userActions.includes('edit');
+ },
+ userPaths() {
+ return generateUserPaths(this.paths, this.user.username);
+ },
+ },
+ methods: {
+ isLdapAction(action) {
+ return action === 'ldapBlocked';
+ },
+ getActionComponent(action) {
+ return Actions[capitalizeFirstCharacter(action)];
+ },
+ },
+ i18n: I18N_USER_ACTIONS,
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-justify-content-end">
+ <gl-button v-if="hasEditAction" data-testid="edit" :href="userPaths.edit">{{
+ $options.i18n.edit
+ }}</gl-button>
+
+ <gl-dropdown
+ v-if="hasDropdownActions"
+ data-testid="actions"
+ right
+ class="gl-ml-2"
+ icon="settings"
+ >
+ <gl-dropdown-section-header>{{ $options.i18n.settings }}</gl-dropdown-section-header>
+
+ <template v-for="action in dropdownSafeActions">
+ <component
+ :is="getActionComponent(action)"
+ v-if="getActionComponent(action)"
+ :key="action"
+ :path="userPaths[action]"
+ :username="user.name"
+ :data-testid="action"
+ >
+ {{ $options.i18n[action] }}
+ </component>
+ <gl-dropdown-item v-else-if="isLdapAction(action)" :key="action" :data-testid="action">
+ {{ $options.i18n[action] }}
+ </gl-dropdown-item>
+ </template>
+
+ <gl-dropdown-divider v-if="hasDeleteActions" />
+
+ <template v-for="action in dropdownDeleteActions">
+ <component
+ :is="getActionComponent(action)"
+ v-if="getActionComponent(action)"
+ :key="action"
+ :paths="userPaths"
+ :username="user.name"
+ :data-testid="`delete-${action}`"
+ >
+ {{ $options.i18n[action] }}
+ </component>
+ </template>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/user_avatar.vue b/app/assets/javascripts/admin/users/components/user_avatar.vue
index 4f79c4fd451..ce22595609d 100644
--- a/app/assets/javascripts/admin/users/components/user_avatar.vue
+++ b/app/assets/javascripts/admin/users/components/user_avatar.vue
@@ -1,12 +1,16 @@
<script>
-import { GlAvatarLink, GlAvatarLabeled, GlBadge } from '@gitlab/ui';
-import { USER_AVATAR_SIZE } from '../constants';
+import { GlAvatarLabeled, GlBadge, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { truncate } from '~/lib/utils/text_utility';
+import { USER_AVATAR_SIZE, LENGTH_OF_USER_NOTE_TOOLTIP } from '../constants';
export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
components: {
- GlAvatarLink,
GlAvatarLabeled,
GlBadge,
+ GlIcon,
},
props: {
user: {
@@ -22,16 +26,23 @@ export default {
adminUserHref() {
return this.adminUserPath.replace('id', this.user.username);
},
+ adminUserMailto() {
+ // NOTE: 'mailto:' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26#possible-false-positives
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `mailto:${this.user.email}`;
+ },
+ userNoteShort() {
+ return truncate(this.user.note, LENGTH_OF_USER_NOTE_TOOLTIP);
+ },
},
USER_AVATAR_SIZE,
};
</script>
<template>
- <gl-avatar-link
+ <div
v-if="user"
- class="js-user-link"
- :href="adminUserHref"
+ class="js-user-link gl-display-inline-block"
:data-user-id="user.id"
:data-username="user.username"
>
@@ -40,8 +51,13 @@ export default {
:src="user.avatarUrl"
:label="user.name"
:sub-label="user.email"
+ :label-link="adminUserHref"
+ :sub-label-link="adminUserMailto"
>
<template #meta>
+ <div v-if="user.note" class="gl-text-gray-500 gl-p-1">
+ <gl-icon v-gl-tooltip="userNoteShort" name="document" />
+ </div>
<div v-for="(badge, idx) in user.badges" :key="idx" class="gl-p-1">
<gl-badge class="gl-display-flex!" size="sm" :variant="badge.variant">{{
badge.text
@@ -49,5 +65,5 @@ export default {
</div>
</template>
</gl-avatar-labeled>
- </gl-avatar-link>
+ </div>
</template>
diff --git a/app/assets/javascripts/admin/users/components/user_date.vue b/app/assets/javascripts/admin/users/components/user_date.vue
new file mode 100644
index 00000000000..38dddbf72c2
--- /dev/null
+++ b/app/assets/javascripts/admin/users/components/user_date.vue
@@ -0,0 +1,29 @@
+<script>
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
+import { SHORT_DATE_FORMAT } from '../constants';
+
+export default {
+ props: {
+ date: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ formattedDate() {
+ const { date } = this;
+ if (date === null) {
+ return __('Never');
+ }
+ return formatDate(new Date(date), SHORT_DATE_FORMAT);
+ },
+ },
+};
+</script>
+<template>
+ <span>
+ {{ formattedDate }}
+ </span>
+</template>
diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue
index 15e31935a4c..8962068601c 100644
--- a/app/assets/javascripts/admin/users/components/users_table.vue
+++ b/app/assets/javascripts/admin/users/components/users_table.vue
@@ -1,7 +1,9 @@
<script>
import { GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
+import UserActions from './user_actions.vue';
import UserAvatar from './user_avatar.vue';
+import UserDate from './user_date.vue';
const DEFAULT_TH_CLASSES =
'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-100! gl-p-5! gl-border-b-1!';
@@ -11,6 +13,8 @@ export default {
components: {
GlTable,
UserAvatar,
+ UserActions,
+ UserDate,
},
props: {
users: {
@@ -62,7 +66,19 @@ export default {
stacked="md"
>
<template #cell(name)="{ item: user }">
- <UserAvatar :user="user" :admin-user-path="paths.adminUser" />
+ <user-avatar :user="user" :admin-user-path="paths.adminUser" />
+ </template>
+
+ <template #cell(createdAt)="{ item: { createdAt } }">
+ <user-date :date="createdAt" />
+ </template>
+
+ <template #cell(lastActivityOn)="{ item: { lastActivityOn } }">
+ <user-date :date="lastActivityOn" show-never />
+ </template>
+
+ <template #cell(settings)="{ item: user }">
+ <user-actions :user="user" :paths="paths" />
</template>
</gl-table>
</div>
diff --git a/app/assets/javascripts/admin/users/constants.js b/app/assets/javascripts/admin/users/constants.js
index 675fcf00c39..8ea1bd3ca7a 100644
--- a/app/assets/javascripts/admin/users/constants.js
+++ b/app/assets/javascripts/admin/users/constants.js
@@ -1 +1,22 @@
+import { s__, __ } from '~/locale';
+
export const USER_AVATAR_SIZE = 32;
+
+export const SHORT_DATE_FORMAT = 'd mmm, yyyy';
+
+export const LENGTH_OF_USER_NOTE_TOOLTIP = 100;
+
+export const I18N_USER_ACTIONS = {
+ edit: __('Edit'),
+ settings: __('Settings'),
+ unlock: __('Unlock'),
+ block: s__('AdminUsers|Block'),
+ unblock: s__('AdminUsers|Unblock'),
+ approve: s__('AdminUsers|Approve'),
+ reject: s__('AdminUsers|Reject'),
+ deactivate: s__('AdminUsers|Deactivate'),
+ activate: s__('AdminUsers|Activate'),
+ ldapBlocked: s__('AdminUsers|Cannot unblock LDAP blocked users'),
+ delete: s__('AdminUsers|Delete user'),
+ deleteWithContributions: s__('AdminUsers|Delete user and contributions'),
+};
diff --git a/app/assets/javascripts/admin/users/index.js b/app/assets/javascripts/admin/users/index.js
index f35b57c4e1a..0365d054fc9 100644
--- a/app/assets/javascripts/admin/users/index.js
+++ b/app/assets/javascripts/admin/users/index.js
@@ -1,8 +1,9 @@
import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import AdminUsersApp from './components/app.vue';
+import UsagePingDisabled from './components/usage_ping_disabled.vue';
-export default function (el = document.querySelector('#js-admin-users-app')) {
+export const initAdminUsersApp = (el = document.querySelector('#js-admin-users-app')) => {
if (!el) {
return false;
}
@@ -19,4 +20,24 @@ export default function (el = document.querySelector('#js-admin-users-app')) {
},
}),
});
-}
+};
+
+export const initCohortsEmptyState = (el = document.querySelector('#js-cohorts-empty-state')) => {
+ if (!el) {
+ return false;
+ }
+
+ const { emptyStateSvgPath, enableUsagePingLink, docsLink } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ svgPath: emptyStateSvgPath,
+ primaryButtonPath: enableUsagePingLink,
+ docsLink,
+ },
+ render(h) {
+ return h(UsagePingDisabled);
+ },
+ });
+};
diff --git a/app/assets/javascripts/admin/users/tabs.js b/app/assets/javascripts/admin/users/tabs.js
new file mode 100644
index 00000000000..9ada77396c7
--- /dev/null
+++ b/app/assets/javascripts/admin/users/tabs.js
@@ -0,0 +1,23 @@
+import { historyPushState } from '~/lib/utils/common_utils';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+
+const COHORTS_PANE = 'cohorts';
+
+const tabClickHandler = (e) => {
+ const { hash } = e.currentTarget;
+ const tab = hash === `#${COHORTS_PANE}` ? COHORTS_PANE : null;
+ const newUrl = mergeUrlParams({ tab }, window.location.href);
+ historyPushState(newUrl);
+};
+
+const initTabs = () => {
+ const tabLinks = document.querySelectorAll('.js-users-tab-item a');
+
+ if (tabLinks.length) {
+ tabLinks.forEach((tabLink) => {
+ tabLink.addEventListener('click', (e) => tabClickHandler(e));
+ });
+ }
+};
+
+export default initTabs;
diff --git a/app/assets/javascripts/admin/users/utils.js b/app/assets/javascripts/admin/users/utils.js
new file mode 100644
index 00000000000..f6c1091ba27
--- /dev/null
+++ b/app/assets/javascripts/admin/users/utils.js
@@ -0,0 +1,7 @@
+export const generateUserPaths = (paths, id) => {
+ return Object.fromEntries(
+ Object.entries(paths).map(([action, genericPath]) => {
+ return [action, genericPath.replace('id', id)];
+ }),
+ );
+};
diff --git a/app/assets/javascripts/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue
deleted file mode 100644
index 895c6e76019..00000000000
--- a/app/assets/javascripts/alert_management/components/alert_details.vue
+++ /dev/null
@@ -1,380 +0,0 @@
-<script>
-import {
- GlAlert,
- GlBadge,
- GlIcon,
- GlLink,
- GlLoadingIcon,
- GlSprintf,
- GlTabs,
- GlTab,
- GlButton,
- GlSafeHtmlDirective,
-} from '@gitlab/ui';
-import * as Sentry from '~/sentry/wrapper';
-import { s__ } from '~/locale';
-import alertQuery from '../graphql/queries/details.query.graphql';
-import sidebarStatusQuery from '../graphql/queries/sidebar_status.query.graphql';
-import { fetchPolicies } from '~/lib/graphql';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
-import initUserPopovers from '~/user_popovers';
-import { ALERTS_SEVERITY_LABELS, trackAlertsDetailsViewsOptions } from '../constants';
-import createIssueMutation from '../graphql/mutations/create_issue_from_alert.mutation.graphql';
-import toggleSidebarStatusMutation from '../graphql/mutations/toggle_sidebar_status.mutation.graphql';
-import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
-import Tracking from '~/tracking';
-import { toggleContainerClasses } from '~/lib/utils/dom_utils';
-import SystemNote from './system_notes/system_note.vue';
-import AlertSidebar from './alert_sidebar.vue';
-import AlertMetrics from './alert_metrics.vue';
-import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
-import AlertSummaryRow from './alert_summary_row.vue';
-
-const containerEl = document.querySelector('.page-with-contextual-sidebar');
-
-export default {
- i18n: {
- errorMsg: s__(
- 'AlertManagement|There was an error displaying the alert. Please refresh the page to try again.',
- ),
- reportedAt: s__('AlertManagement|Reported %{when}'),
- reportedAtWithTool: s__('AlertManagement|Reported %{when} by %{tool}'),
- },
- directives: {
- SafeHtml: GlSafeHtmlDirective,
- },
- severityLabels: ALERTS_SEVERITY_LABELS,
- tabsConfig: [
- {
- id: 'overview',
- title: s__('AlertManagement|Alert details'),
- },
- {
- id: 'metrics',
- title: s__('AlertManagement|Metrics'),
- },
- {
- id: 'activity',
- title: s__('AlertManagement|Activity feed'),
- },
- ],
- components: {
- AlertDetailsTable,
- AlertSummaryRow,
- GlBadge,
- GlAlert,
- GlIcon,
- GlLink,
- GlLoadingIcon,
- GlSprintf,
- GlTab,
- GlTabs,
- GlButton,
- TimeAgoTooltip,
- AlertSidebar,
- SystemNote,
- AlertMetrics,
- },
- inject: {
- projectPath: {
- default: '',
- },
- alertId: {
- default: '',
- },
- projectId: {
- default: '',
- },
- projectIssuesPath: {
- default: '',
- },
- },
- apollo: {
- alert: {
- fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
- query: alertQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- alertId: this.alertId,
- };
- },
- update(data) {
- return data?.project?.alertManagementAlerts?.nodes?.[0] ?? null;
- },
- error(error) {
- this.errored = true;
- Sentry.captureException(error);
- },
- },
- sidebarStatus: {
- query: sidebarStatusQuery,
- },
- },
- data() {
- return {
- alert: null,
- errored: false,
- sidebarStatus: false,
- isErrorDismissed: false,
- createIncidentError: '',
- incidentCreationInProgress: false,
- sidebarErrorMessage: '',
- };
- },
- computed: {
- loading() {
- return this.$apollo.queries.alert.loading;
- },
- reportedAtMessage() {
- return this.alert?.monitoringTool
- ? this.$options.i18n.reportedAtWithTool
- : this.$options.i18n.reportedAt;
- },
- showErrorMsg() {
- return this.errored && !this.isErrorDismissed;
- },
- activeTab() {
- return this.$route.params.tabId || this.$options.tabsConfig[0].id;
- },
- currentTabIndex: {
- get() {
- return this.$options.tabsConfig.findIndex((tab) => tab.id === this.activeTab);
- },
- set(tabIdx) {
- const tabId = this.$options.tabsConfig[tabIdx].id;
- this.$router.replace({ name: 'tab', params: { tabId } });
- },
- },
- environmentName() {
- return this.alert?.environment?.name;
- },
- environmentPath() {
- return this.alert?.environment?.path;
- },
- },
- mounted() {
- this.trackPageViews();
- toggleContainerClasses(containerEl, {
- 'issuable-bulk-update-sidebar': true,
- 'right-sidebar-expanded': true,
- });
- },
- updated() {
- this.$nextTick(() => {
- highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member'));
- initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
- });
- },
- methods: {
- dismissError() {
- this.isErrorDismissed = true;
- this.sidebarErrorMessage = '';
- },
- toggleSidebar() {
- this.$apollo.mutate({ mutation: toggleSidebarStatusMutation });
- toggleContainerClasses(containerEl, {
- 'right-sidebar-collapsed': !this.sidebarStatus,
- 'right-sidebar-expanded': this.sidebarStatus,
- });
- },
- handleAlertSidebarError(errorMessage) {
- this.errored = true;
- this.sidebarErrorMessage = errorMessage;
- },
- createIncident() {
- this.incidentCreationInProgress = true;
-
- this.$apollo
- .mutate({
- mutation: createIssueMutation,
- variables: {
- iid: this.alert.iid,
- projectPath: this.projectPath,
- },
- })
- .then(
- ({
- data: {
- createAlertIssue: { errors, issue },
- },
- }) => {
- if (errors?.length) {
- [this.createIncidentError] = errors;
- this.incidentCreationInProgress = false;
- } else if (issue) {
- visitUrl(this.incidentPath(issue.iid));
- }
- },
- )
- .catch((error) => {
- this.createIncidentError = error;
- this.incidentCreationInProgress = false;
- });
- },
- incidentPath(issueId) {
- return joinPaths(this.projectIssuesPath, issueId);
- },
- trackPageViews() {
- const { category, action } = trackAlertsDetailsViewsOptions;
- Tracking.event(category, action);
- },
- },
-};
-</script>
-
-<template>
- <div>
- <gl-alert v-if="showErrorMsg" variant="danger" @dismiss="dismissError">
- <p v-safe-html="sidebarErrorMessage || $options.i18n.errorMsg"></p>
- </gl-alert>
- <gl-alert
- v-if="createIncidentError"
- variant="danger"
- data-testid="incidentCreationError"
- @dismiss="createIncidentError = null"
- >
- {{ createIncidentError }}
- </gl-alert>
- <div v-if="loading"><gl-loading-icon size="lg" class="gl-mt-5" /></div>
- <div
- v-if="alert"
- class="alert-management-details gl-relative"
- :class="{ 'pr-sm-8': sidebarStatus }"
- >
- <div
- class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-px-1 py-3 py-md-4 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-flex-direction-column gl-sm-flex-direction-row"
- >
- <div data-testid="alert-header">
- <gl-badge class="gl-mr-3">
- <strong>{{ s__('AlertManagement|Alert') }}</strong>
- </gl-badge>
- <span>
- <gl-sprintf :message="reportedAtMessage">
- <template #when>
- <time-ago-tooltip :time="alert.createdAt" />
- </template>
- <template #tool>{{ alert.monitoringTool }}</template>
- </gl-sprintf>
- </span>
- </div>
- <gl-button
- v-if="alert.issueIid"
- class="gl-mt-3 mt-sm-0 align-self-center align-self-sm-baseline alert-details-incident-button"
- data-testid="viewIncidentBtn"
- :href="incidentPath(alert.issueIid)"
- category="primary"
- variant="success"
- >
- {{ s__('AlertManagement|View incident') }}
- </gl-button>
- <gl-button
- v-else
- class="gl-mt-3 mt-sm-0 align-self-center align-self-sm-baseline alert-details-incident-button"
- data-testid="createIncidentBtn"
- :loading="incidentCreationInProgress"
- category="primary"
- variant="success"
- @click="createIncident()"
- >
- {{ s__('AlertManagement|Create incident') }}
- </gl-button>
- <gl-button
- :aria-label="__('Toggle sidebar')"
- category="primary"
- variant="default"
- class="d-sm-none gl-absolute toggle-sidebar-mobile-button"
- type="button"
- icon="chevron-double-lg-left"
- @click="toggleSidebar"
- />
- </div>
- <div
- v-if="alert"
- class="gl-display-flex gl-justify-content-space-between gl-align-items-center"
- >
- <h2 data-testid="title">{{ alert.title }}</h2>
- </div>
- <gl-tabs v-if="alert" v-model="currentTabIndex" data-testid="alertDetailsTabs">
- <gl-tab :data-testid="$options.tabsConfig[0].id" :title="$options.tabsConfig[0].title">
- <alert-summary-row v-if="alert.severity" :label="`${s__('AlertManagement|Severity')}:`">
- <span data-testid="severity">
- <gl-icon
- class="gl-vertical-align-middle"
- :size="12"
- :name="`severity-${alert.severity.toLowerCase()}`"
- :class="`icon-${alert.severity.toLowerCase()}`"
- />
- {{ $options.severityLabels[alert.severity] }}
- </span>
- </alert-summary-row>
- <alert-summary-row
- v-if="environmentName"
- :label="`${s__('AlertManagement|Environment')}:`"
- >
- <gl-link
- v-if="environmentPath"
- class="gl-display-inline-block"
- data-testid="environmentPath"
- :href="environmentPath"
- >
- {{ environmentName }}
- </gl-link>
- <span v-else data-testid="environmentName">{{ environmentName }}</span>
- </alert-summary-row>
- <alert-summary-row
- v-if="alert.startedAt"
- :label="`${s__('AlertManagement|Start time')}:`"
- >
- <time-ago-tooltip data-testid="startTimeItem" :time="alert.startedAt" />
- </alert-summary-row>
- <alert-summary-row
- v-if="alert.eventCount"
- :label="`${s__('AlertManagement|Events')}:`"
- data-testid="eventCount"
- >
- {{ alert.eventCount }}
- </alert-summary-row>
- <alert-summary-row
- v-if="alert.monitoringTool"
- :label="`${s__('AlertManagement|Tool')}:`"
- data-testid="monitoringTool"
- >
- {{ alert.monitoringTool }}
- </alert-summary-row>
- <alert-summary-row
- v-if="alert.service"
- :label="`${s__('AlertManagement|Service')}:`"
- data-testid="service"
- >
- {{ alert.service }}
- </alert-summary-row>
- <alert-summary-row
- v-if="alert.runbook"
- :label="`${s__('AlertManagement|Runbook')}:`"
- data-testid="runbook"
- >
- {{ alert.runbook }}
- </alert-summary-row>
- <alert-details-table :alert="alert" :loading="loading" />
- </gl-tab>
- <gl-tab :data-testid="$options.tabsConfig[1].id" :title="$options.tabsConfig[1].title">
- <alert-metrics :dashboard-url="alert.metricsDashboardUrl" />
- </gl-tab>
- <gl-tab :data-testid="$options.tabsConfig[2].id" :title="$options.tabsConfig[2].title">
- <div v-if="alert.notes.nodes.length > 0" class="issuable-discussion">
- <ul class="notes main-notes-list timeline">
- <system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
- </ul>
- </div>
- </gl-tab>
- </gl-tabs>
- <alert-sidebar
- :alert="alert"
- @toggle-sidebar="toggleSidebar"
- @alert-error="handleAlertSidebarError"
- />
- </div>
- </div>
-</template>
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 2bad15faa85..dd702c4a5d3 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -11,26 +11,22 @@ import {
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
-import { s__, __ } from '~/locale';
+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 PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
+import { s__, __ } from '~/locale';
+import AlertStatus from '~/vue_shared/alert_details/components/alert_status.vue';
import {
tdClass,
thClass,
bodyTrClass,
initialPaginationState,
} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
+import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
-import { convertToSnakeCase } from '~/lib/utils/text_utility';
-import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql';
+import { ALERTS_STATUS_TABS, SEVERITY_LEVELS, trackAlertListViewsOptions } from '../constants';
import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
-import {
- ALERTS_STATUS_TABS,
- ALERTS_SEVERITY_LABELS,
- trackAlertListViewsOptions,
-} from '../constants';
-import AlertStatus from './alert_status.vue';
const TH_TEST_ID = { 'data-testid': 'alert-management-severity-sort' };
@@ -96,7 +92,7 @@ export default {
sortable: true,
},
],
- severityLabels: ALERTS_SEVERITY_LABELS,
+ severityLabels: SEVERITY_LEVELS,
statusTabs: ALERTS_STATUS_TABS,
components: {
GlAlert,
diff --git a/app/assets/javascripts/alert_management/components/alert_sidebar.vue b/app/assets/javascripts/alert_management/components/alert_sidebar.vue
deleted file mode 100644
index 41d77716592..00000000000
--- a/app/assets/javascripts/alert_management/components/alert_sidebar.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<script>
-import SidebarHeader from './sidebar/sidebar_header.vue';
-import SidebarTodo from './sidebar/sidebar_todo.vue';
-import SidebarStatus from './sidebar/sidebar_status.vue';
-import SidebarAssignees from './sidebar/sidebar_assignees.vue';
-
-import sidebarStatusQuery from '../graphql/queries/sidebar_status.query.graphql';
-
-export default {
- components: {
- SidebarAssignees,
- SidebarHeader,
- SidebarTodo,
- SidebarStatus,
- },
- inject: {
- projectPath: {
- default: '',
- },
- projectId: {
- default: '',
- },
- },
- props: {
- alert: {
- type: Object,
- required: true,
- },
- },
- apollo: {
- sidebarStatus: {
- query: sidebarStatusQuery,
- },
- },
- data() {
- return {
- sidebarStatus: false,
- };
- },
- computed: {
- sidebarCollapsedClass() {
- return this.sidebarStatus ? 'right-sidebar-collapsed' : 'right-sidebar-expanded';
- },
- },
-};
-</script>
-
-<template>
- <aside :class="sidebarCollapsedClass" class="right-sidebar alert-sidebar">
- <div class="issuable-sidebar js-issuable-update">
- <sidebar-header
- :sidebar-collapsed="sidebarStatus"
- :project-path="projectPath"
- :alert="alert"
- @toggle-sidebar="$emit('toggle-sidebar')"
- @alert-error="$emit('alert-error', $event)"
- />
- <sidebar-todo
- v-if="sidebarStatus"
- :project-path="projectPath"
- :alert="alert"
- :sidebar-collapsed="sidebarStatus"
- @alert-error="$emit('alert-error', $event)"
- />
- <sidebar-status
- :project-path="projectPath"
- :alert="alert"
- @toggle-sidebar="$emit('toggle-sidebar')"
- @alert-error="$emit('alert-error', $event)"
- />
- <sidebar-assignees
- :project-path="projectPath"
- :project-id="projectId"
- :alert="alert"
- :sidebar-collapsed="sidebarStatus"
- @toggle-sidebar="$emit('toggle-sidebar')"
- @alert-error="$emit('alert-error', $event)"
- />
- <div class="block"></div>
- </div>
- </aside>
-</template>
diff --git a/app/assets/javascripts/alert_management/components/alert_status.vue b/app/assets/javascripts/alert_management/components/alert_status.vue
deleted file mode 100644
index 2afdeb8b6fd..00000000000
--- a/app/assets/javascripts/alert_management/components/alert_status.vue
+++ /dev/null
@@ -1,119 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import Tracking from '~/tracking';
-import { trackAlertStatusUpdateOptions } from '../constants';
-import updateAlertStatusMutation from '~/graphql_shared/mutations/update_alert_status.mutation.graphql';
-
-export default {
- i18n: {
- UPDATE_ALERT_STATUS_ERROR: s__(
- 'AlertManagement|There was an error while updating the status of the alert.',
- ),
- UPDATE_ALERT_STATUS_INSTRUCTION: s__('AlertManagement|Please try again.'),
- },
- statuses: {
- TRIGGERED: s__('AlertManagement|Triggered'),
- ACKNOWLEDGED: s__('AlertManagement|Acknowledged'),
- RESOLVED: s__('AlertManagement|Resolved'),
- },
- components: {
- GlDropdown,
- GlDropdownItem,
- },
- props: {
- projectPath: {
- type: String,
- required: true,
- },
- alert: {
- type: Object,
- required: true,
- },
- isDropdownShowing: {
- type: Boolean,
- required: false,
- },
- isSidebar: {
- type: Boolean,
- required: true,
- },
- },
- computed: {
- dropdownClass() {
- // eslint-disable-next-line no-nested-ternary
- return this.isSidebar ? (this.isDropdownShowing ? 'show' : 'gl-display-none') : '';
- },
- },
- methods: {
- updateAlertStatus(status) {
- this.$emit('handle-updating', true);
- this.$apollo
- .mutate({
- mutation: updateAlertStatusMutation,
- variables: {
- iid: this.alert.iid,
- status: status.toUpperCase(),
- projectPath: this.projectPath,
- },
- })
- .then((resp) => {
- this.trackStatusUpdate(status);
- const errors = resp.data?.updateAlertStatus?.errors || [];
-
- if (errors[0]) {
- this.$emit(
- 'alert-error',
- `${this.$options.i18n.UPDATE_ALERT_STATUS_ERROR} ${errors[0]}`,
- );
- }
-
- this.$emit('hide-dropdown');
- })
- .catch(() => {
- this.$emit(
- 'alert-error',
- `${this.$options.i18n.UPDATE_ALERT_STATUS_ERROR} ${this.$options.i18n.UPDATE_ALERT_STATUS_INSTRUCTION}`,
- );
- })
- .finally(() => {
- this.$emit('handle-updating', false);
- });
- },
- trackStatusUpdate(status) {
- const { category, action, label } = trackAlertStatusUpdateOptions;
- Tracking.event(category, action, { label, property: status });
- },
- },
-};
-</script>
-
-<template>
- <div class="dropdown dropdown-menu-selectable" :class="dropdownClass">
- <gl-dropdown
- ref="dropdown"
- right
- :text="$options.statuses[alert.status]"
- class="w-100"
- toggle-class="dropdown-menu-toggle"
- @keydown.esc.native="$emit('hide-dropdown')"
- @hide="$emit('hide-dropdown')"
- >
- <p v-if="isSidebar" class="gl-new-dropdown-header-top" data-testid="dropdown-header">
- {{ s__('AlertManagement|Assign status') }}
- </p>
- <div class="dropdown-content dropdown-body">
- <gl-dropdown-item
- v-for="(label, field) in $options.statuses"
- :key="field"
- data-testid="statusDropdownItem"
- :active="label.toUpperCase() === alert.status"
- :active-class="'is-active'"
- @click="updateAlertStatus(label)"
- >
- {{ label }}
- </gl-dropdown-item>
- </div>
- </gl-dropdown>
- </div>
-</template>
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue
deleted file mode 100644
index 70902a204f8..00000000000
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_header.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-<script>
-import ToggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
-import SidebarTodo from './sidebar_todo.vue';
-
-export default {
- components: {
- ToggleSidebar,
- SidebarTodo,
- },
- props: {
- alert: {
- type: Object,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- sidebarCollapsed: {
- type: Boolean,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <div class="block gl-display-flex gl-justify-content-space-between">
- <span class="issuable-header-text hide-collapsed">
- {{ __('To-Do') }}
- </span>
- <sidebar-todo
- v-if="!sidebarCollapsed"
- :project-path="projectPath"
- :alert="alert"
- :sidebar-collapsed="sidebarCollapsed"
- @alert-error="$emit('alert-error', $event)"
- />
- <toggle-sidebar :collapsed="sidebarCollapsed" @toggle="$emit('toggle-sidebar')" />
- </div>
-</template>
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
deleted file mode 100644
index 485395bcac2..00000000000
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
+++ /dev/null
@@ -1,149 +0,0 @@
-<script>
-import produce from 'immer';
-import { s__ } from '~/locale';
-import Todo from '~/sidebar/components/todo_toggle/todo.vue';
-import createAlertTodoMutation from '../../graphql/mutations/alert_todo_create.mutation.graphql';
-import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
-import alertQuery from '../../graphql/queries/details.query.graphql';
-
-export default {
- i18n: {
- UPDATE_ALERT_TODO_ERROR: s__(
- 'AlertManagement|There was an error while updating the To-Do of the alert.',
- ),
- },
- components: {
- Todo,
- },
- props: {
- alert: {
- type: Object,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- sidebarCollapsed: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- isUpdating: false,
- };
- },
- computed: {
- alertID() {
- return parseInt(this.alert.iid, 10);
- },
- firstToDoId() {
- return this.alert?.todos?.nodes[0]?.id;
- },
- hasPendingTodos() {
- return this.alert?.todos?.nodes.length > 0;
- },
- getAlertQueryVariables() {
- return {
- fullPath: this.projectPath,
- alertId: this.alert.iid,
- };
- },
- },
- methods: {
- updateToDoCount(add) {
- const oldCount = parseInt(document.querySelector('.js-todos-count').innerText, 10);
- const count = add ? oldCount + 1 : oldCount - 1;
- const headerTodoEvent = new CustomEvent('todo:toggle', {
- detail: {
- count,
- },
- });
-
- return document.dispatchEvent(headerTodoEvent);
- },
- addToDo() {
- this.isUpdating = true;
- return this.$apollo
- .mutate({
- mutation: createAlertTodoMutation,
- variables: {
- iid: this.alert.iid,
- projectPath: this.projectPath,
- },
- })
- .then(({ data: { errors = [] } }) => {
- if (errors[0]) {
- return this.throwError(errors[0]);
- }
- return this.updateToDoCount(true);
- })
- .catch(() => {
- this.throwError();
- })
- .finally(() => {
- this.isUpdating = false;
- });
- },
- markAsDone() {
- this.isUpdating = true;
- return this.$apollo
- .mutate({
- mutation: todoMarkDoneMutation,
- variables: {
- id: this.firstToDoId,
- },
- update: this.updateCache,
- })
- .then(({ data: { errors = [] } }) => {
- if (errors[0]) {
- return this.throwError(errors[0]);
- }
- return this.updateToDoCount(false);
- })
- .catch(() => {
- this.throwError();
- })
- .finally(() => {
- this.isUpdating = false;
- });
- },
- updateCache(store) {
- const sourceData = store.readQuery({
- query: alertQuery,
- variables: this.getAlertQueryVariables,
- });
-
- const data = produce(sourceData, (draftData) => {
- // eslint-disable-next-line no-param-reassign
- draftData.project.alertManagementAlerts.nodes[0].todos.nodes = [];
- });
-
- store.writeQuery({
- query: alertQuery,
- variables: this.getAlertQueryVariables,
- data,
- });
- },
- throwError(err = '') {
- const error = err || s__('AlertManagement|Please try again.');
- this.$emit('alert-error', `${this.$options.i18n.UPDATE_ALERT_TODO_ERROR} ${error}`);
- },
- },
-};
-</script>
-
-<template>
- <div :class="{ 'block todo': sidebarCollapsed, 'gl-ml-auto': !sidebarCollapsed }">
- <todo
- data-testid="alert-todo-button"
- :collapsed="sidebarCollapsed"
- :issuable-id="alertID"
- :is-todo="hasPendingTodos"
- :is-action-active="isUpdating"
- issuable-type="alert"
- @toggleTodo="hasPendingTodos ? markAsDone() : addToDo()"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/alert_management/constants.js b/app/assets/javascripts/alert_management/constants.js
index b79a64646eb..c98d3865621 100644
--- a/app/assets/javascripts/alert_management/constants.js
+++ b/app/assets/javascripts/alert_management/constants.js
@@ -1,12 +1,12 @@
import { s__ } from '~/locale';
-export const ALERTS_SEVERITY_LABELS = {
- CRITICAL: s__('AlertManagement|Critical'),
- HIGH: s__('AlertManagement|High'),
- MEDIUM: s__('AlertManagement|Medium'),
- LOW: s__('AlertManagement|Low'),
- INFO: s__('AlertManagement|Info'),
- UNKNOWN: s__('AlertManagement|Unknown'),
+export const SEVERITY_LEVELS = {
+ CRITICAL: s__('severity|Critical'),
+ HIGH: s__('severity|High'),
+ MEDIUM: s__('severity|Medium'),
+ LOW: s__('severity|Low'),
+ INFO: s__('severity|Info'),
+ UNKNOWN: s__('severity|Unknown'),
};
export const ALERTS_STATUS_TABS = [
@@ -46,20 +46,3 @@ export const trackAlertListViewsOptions = {
category: 'Alert Management',
action: 'view_alerts_list',
};
-
-/**
- * Tracks snowplow event when user views alert details
- */
-export const trackAlertsDetailsViewsOptions = {
- category: 'Alert Management',
- action: 'view_alert_details',
-};
-
-/**
- * Tracks snowplow event when alert status is updated
- */
-export const trackAlertStatusUpdateOptions = {
- category: 'Alert Management',
- action: 'update_alert_status',
- label: 'Status',
-};
diff --git a/app/assets/javascripts/alert_management/details.js b/app/assets/javascripts/alert_management/details.js
deleted file mode 100644
index 4217b702d0a..00000000000
--- a/app/assets/javascripts/alert_management/details.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
-import produce from 'immer';
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-import AlertDetails from './components/alert_details.vue';
-import sidebarStatusQuery from './graphql/queries/sidebar_status.query.graphql';
-import createRouter from './router';
-
-Vue.use(VueApollo);
-
-export default (selector) => {
- const domEl = document.querySelector(selector);
- const { alertId, projectPath, projectIssuesPath, projectId } = domEl.dataset;
- const router = createRouter();
-
- const resolvers = {
- Mutation: {
- toggleSidebarStatus: (_, __, { cache }) => {
- const sourceData = cache.readQuery({ query: sidebarStatusQuery });
- const data = produce(sourceData, (draftData) => {
- // eslint-disable-next-line no-param-reassign
- draftData.sidebarStatus = !draftData.sidebarStatus;
- });
- cache.writeQuery({ query: sidebarStatusQuery, data });
- },
- },
- };
-
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(resolvers, {
- cacheConfig: {
- dataIdFromObject: (object) => {
- // eslint-disable-next-line no-underscore-dangle
- if (object.__typename === 'AlertManagementAlert') {
- return object.iid;
- }
- return defaultDataIdFromObject(object);
- },
- },
- assumeImmutableResults: true,
- }),
- });
-
- apolloProvider.clients.defaultClient.cache.writeData({
- data: {
- sidebarStatus: false,
- },
- });
-
- // eslint-disable-next-line no-new
- new Vue({
- el: selector,
- components: {
- AlertDetails,
- },
- provide: {
- projectPath,
- alertId,
- projectIssuesPath,
- projectId,
- },
- apolloProvider,
- router,
- render(createElement) {
- return createElement('alert-details', {});
- },
- });
-};
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/alert_todo_create.mutation.graphql b/app/assets/javascripts/alert_management/graphql/mutations/alert_todo_create.mutation.graphql
deleted file mode 100644
index ac9858c104f..00000000000
--- a/app/assets/javascripts/alert_management/graphql/mutations/alert_todo_create.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/detail_item.fragment.graphql"
-
-mutation alertTodoCreate($projectPath: ID!, $iid: String!) {
- alertTodoCreate(input: { iid: $iid, projectPath: $projectPath }) {
- errors
- alert {
- ...AlertDetailItem
- }
- }
-}
diff --git a/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql
deleted file mode 100644
index 8881f49b689..00000000000
--- a/app/assets/javascripts/alert_management/graphql/queries/details.query.graphql
+++ /dev/null
@@ -1,11 +0,0 @@
-#import "../fragments/detail_item.fragment.graphql"
-
-query alertDetails($fullPath: ID!, $alertId: String) {
- project(fullPath: $fullPath) {
- alertManagementAlerts(iid: $alertId) {
- nodes {
- ...AlertDetailItem
- }
- }
- }
-}
diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js
index b484841ed2c..f5eac26431f 100644
--- a/app/assets/javascripts/alert_management/list.js
+++ b/app/assets/javascripts/alert_management/list.js
@@ -1,8 +1,9 @@
+import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
+import { PAGE_CONFIG } from '~/vue_shared/alert_details/constants';
import AlertManagementList from './components/alert_management_list_wrapper.vue';
Vue.use(VueApollo);
@@ -59,6 +60,7 @@ export default () => {
populatingAlertsHelpUrl,
emptyAlertSvgPath,
alertManagementEnabled: parseBoolean(alertManagementEnabled),
+ trackAlertStatusUpdateOptions: PAGE_CONFIG.OPERATIONS.TRACK_ALERT_STATUS_UPDATE_OPTIONS,
userCanEnableAlertManagement: parseBoolean(userCanEnableAlertManagement),
},
apolloProvider,
diff --git a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
deleted file mode 100644
index c0e93d315a4..00000000000
--- a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue
+++ /dev/null
@@ -1,187 +0,0 @@
-<script>
-import {
- GlButton,
- GlFormGroup,
- GlFormInput,
- GlLink,
- GlModal,
- GlModalDirective,
- GlSprintf,
-} from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
-import axios from '~/lib/utils/axios_utils';
-import { s__, __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-
-export default {
- i18n: {
- usageSection: s__(
- 'AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.',
- ),
- setupSection: s__(
- "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.",
- ),
- },
- COPY_TO_CLIPBOARD: __('Copy'),
- RESET_KEY: __('Reset key'),
- components: {
- GlButton,
- GlFormGroup,
- GlFormInput,
- GlLink,
- GlModal,
- GlSprintf,
- ClipboardButton,
- ToggleButton,
- },
- directives: {
- 'gl-modal': GlModalDirective,
- },
- props: {
- alertsSetupUrl: {
- type: String,
- required: true,
- },
- alertsUsageUrl: {
- type: String,
- required: true,
- },
- initialAuthorizationKey: {
- type: String,
- required: false,
- default: '',
- },
- formPath: {
- type: String,
- required: true,
- },
- url: {
- type: String,
- required: true,
- },
- initialActivated: {
- type: Boolean,
- required: true,
- },
- isDisabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- activated: this.initialActivated,
- loadingActivated: false,
- authorizationKey: this.initialAuthorizationKey,
- };
- },
- computed: {
- sections() {
- return [
- {
- text: this.$options.i18n.usageSection,
- url: this.alertsUsageUrl,
- },
- {
- text: this.$options.i18n.setupSection,
- url: this.alertsSetupUrl,
- },
- ];
- },
- },
- methods: {
- resetKey() {
- return axios
- .put(this.formPath, { service: { token: '' } })
- .then((res) => {
- this.authorizationKey = res.data.token;
- })
- .catch(() => {
- createFlash(__('Failed to reset key. Please try again.'));
- });
- },
- toggleActivated(value) {
- this.loadingActivated = true;
- return axios
- .put(this.formPath, { service: { active: value } })
- .then(() => {
- this.activated = value;
- this.loadingActivated = false;
- })
- .catch(() => {
- createFlash(__('Update failed. Please try again.'));
- this.loadingActivated = false;
- });
- },
- },
-};
-</script>
-
-<template>
- <div>
- <div data-testid="description">
- <p v-for="section in sections" :key="section.text">
- <gl-sprintf :message="section.text">
- <template #link="{ content }">
- <gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
- <gl-form-group :label="__('Active')" label-for="activated" label-class="label-bold">
- <toggle-button
- id="activated"
- :disabled-input="loadingActivated || isDisabled"
- :is-loading="loadingActivated"
- :value="activated"
- @change="toggleActivated"
- />
- </gl-form-group>
- <gl-form-group :label="__('URL')" label-for="url" label-class="label-bold">
- <div class="input-group">
- <gl-form-input id="url" :readonly="true" :value="url" />
- <span class="input-group-append">
- <clipboard-button
- :text="url"
- :title="$options.COPY_TO_CLIPBOARD"
- :disabled="isDisabled"
- />
- </span>
- </div>
- </gl-form-group>
- <gl-form-group
- :label="__('Authorization key')"
- label-for="authorization-key"
- label-class="label-bold"
- >
- <div class="input-group">
- <gl-form-input id="authorization-key" :readonly="true" :value="authorizationKey" />
- <span class="input-group-append">
- <clipboard-button
- :text="authorizationKey"
- :title="$options.COPY_TO_CLIPBOARD"
- :disabled="isDisabled"
- />
- </span>
- </div>
- <gl-button v-gl-modal.authKeyModal class="gl-mt-2" :disabled="isDisabled">{{
- $options.RESET_KEY
- }}</gl-button>
- <gl-modal
- modal-id="authKeyModal"
- :title="$options.RESET_KEY"
- :ok-title="$options.RESET_KEY"
- ok-variant="danger"
- @ok="resetKey"
- >
- {{
- __(
- 'Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
- )
- }}
- </gl-modal>
- </gl-form-group>
- </div>
-</template>
diff --git a/app/assets/javascripts/alerts_service_settings/index.js b/app/assets/javascripts/alerts_service_settings/index.js
deleted file mode 100644
index ddba966ffb3..00000000000
--- a/app/assets/javascripts/alerts_service_settings/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import AlertsServiceForm from './components/alerts_service_form.vue';
-
-export default (el) => {
- if (!el) {
- return null;
- }
-
- const {
- activated: activatedStr,
- alertsSetupUrl,
- alertsUsageUrl,
- formPath,
- authorizationKey,
- url,
- disabled,
- } = el.dataset;
-
- const activated = parseBoolean(activatedStr);
- const isDisabled = parseBoolean(disabled);
-
- return new Vue({
- el,
- render(createElement) {
- return createElement(AlertsServiceForm, {
- props: {
- alertsSetupUrl,
- alertsUsageUrl,
- initialActivated: activated,
- formPath,
- initialAuthorizationKey: authorizationKey,
- url,
- isDisabled,
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
index c52e9f5c264..1135562834a 100644
--- a/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
+++ b/app/assets/javascripts/alerts_settings/components/alert_mapping_builder.vue
@@ -1,5 +1,4 @@
<script>
-import Vue from 'vue';
import {
GlIcon,
GlFormInput,
@@ -8,11 +7,15 @@ import {
GlSearchBoxByType,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
+import { cloneDeep } from 'lodash';
+import Vue from 'vue';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { s__, __ } from '~/locale';
-// Mocks will be removed when integrating with BE is ready
-// data format is defined and will be the same as mocked (maybe with some minor changes)
-// feature rollout plan - https://gitlab.com/gitlab-org/gitlab/-/issues/262707#note_442529171
-import gitlabFieldsMock from './mocks/gitlabFields.json';
+import {
+ getMappingData,
+ getPayloadFields,
+ transformForSave,
+} from '../utils/mapping_transformations';
export const i18n = {
columns: {
@@ -40,18 +43,25 @@ export default {
directives: {
GlTooltip,
},
- inject: {
- gitlabAlertFields: {
- default: gitlabFieldsMock,
- },
- },
props: {
- payloadFields: {
+ alertFields: {
+ type: Array,
+ required: true,
+ validator: (fields) => {
+ return (
+ fields.length &&
+ fields.every(({ name, types, label }) => {
+ return typeof name === 'string' && Array.isArray(types) && typeof label === 'string';
+ })
+ );
+ },
+ },
+ parsedPayload: {
type: Array,
required: false,
default: () => [],
},
- mapping: {
+ savedMapping: {
type: Array,
required: false,
default: () => [],
@@ -59,31 +69,18 @@ export default {
},
data() {
return {
- gitlabFields: this.gitlabAlertFields,
+ gitlabFields: cloneDeep(this.alertFields),
};
},
computed: {
+ payloadFields() {
+ return getPayloadFields(this.parsedPayload);
+ },
mappingData() {
- return this.gitlabFields.map((gitlabField) => {
- const mappingFields = this.payloadFields.filter(({ type }) =>
- type.some((t) => gitlabField.compatibleTypes.includes(t)),
- );
-
- const foundMapping = this.mapping.find(
- ({ alertFieldName }) => alertFieldName === gitlabField.name,
- );
-
- const { fallbackAlertPaths, payloadAlertPaths } = foundMapping || {};
-
- return {
- mapping: payloadAlertPaths,
- fallback: fallbackAlertPaths,
- searchTerm: '',
- fallbackSearchTerm: '',
- mappingFields,
- ...gitlabField,
- };
- });
+ return getMappingData(this.gitlabFields, this.payloadFields, this.savedMapping);
+ },
+ hasFallbackColumn() {
+ return this.gitlabFields.some(({ numberOfFallbacks }) => Boolean(numberOfFallbacks));
},
},
methods: {
@@ -91,6 +88,7 @@ export default {
const fieldIndex = this.gitlabFields.findIndex((field) => field.name === gitlabKey);
const updatedField = { ...this.gitlabFields[fieldIndex], ...{ [valueKey]: mappingKey } };
Vue.set(this.gitlabFields, fieldIndex, updatedField);
+ this.$emit('onMappingUpdate', transformForSave(this.mappingData));
},
setSearchTerm(search = '', searchFieldKey, gitlabKey) {
const fieldIndex = this.gitlabFields.findIndex((field) => field.name === gitlabKey);
@@ -99,7 +97,6 @@ export default {
},
filterFields(searchTerm = '', fields) {
const search = searchTerm.toLowerCase();
-
return fields.filter((field) => field.label.toLowerCase().includes(search));
},
isSelected(fieldValue, mapping) {
@@ -111,8 +108,10 @@ export default {
this.$options.i18n.makeSelection
);
},
- getFieldValue({ label, type }) {
- return `${label} (${type.join(__(' or '))})`;
+ getFieldValue({ label, types }) {
+ const type = types.map((t) => capitalizeFirstCharacter(t.toLowerCase())).join(__(' or '));
+
+ return `${label} (${type})`;
},
noResults(searchTerm, fields) {
return !this.filterFields(searchTerm, fields).length;
@@ -131,7 +130,11 @@ export default {
<h5 id="parsedFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
{{ $options.i18n.columns.payloadKeyTitle }}
</h5>
- <h5 id="fallbackFieldsHeader" class="gl-display-table-cell gl-py-3 gl-pr-3">
+ <h5
+ v-if="hasFallbackColumn"
+ id="fallbackFieldsHeader"
+ class="gl-display-table-cell gl-py-3 gl-pr-3"
+ >
{{ $options.i18n.columns.fallbackKeyTitle }}
<gl-icon
v-gl-tooltip
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
index 1ae7f826ce6..18372c54b84 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue
@@ -12,18 +12,18 @@ import {
GlModalDirective,
GlToggle,
} from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import MappingBuilder from './alert_mapping_builder.vue';
-import AlertSettingsFormHelpBlock from './alert_settings_form_help_block.vue';
-import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
integrationTypes,
JSON_VALIDATE_DELAY,
targetPrometheusUrlPlaceholder,
typeSet,
} from '../constants';
+import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
+import MappingBuilder from './alert_mapping_builder.vue';
+import AlertSettingsFormHelpBlock from './alert_settings_form_help_block.vue';
// Mocks will be removed when integrating with BE is ready
// data format is defined and will be the same as mocked (maybe with some minor changes)
// feature rollout plan - https://gitlab.com/gitlab-org/gitlab/-/issues/262707#note_442529171
@@ -125,6 +125,9 @@ export default {
prometheus: {
default: {},
},
+ multiIntegrations: {
+ default: false,
+ },
},
props: {
loading: {
@@ -135,6 +138,11 @@ export default {
type: Boolean,
required: true,
},
+ alertFields: {
+ type: Array,
+ required: false,
+ default: null,
+ },
},
apollo: {
currentIntegration: {
@@ -152,6 +160,7 @@ export default {
},
resetSamplePayloadConfirmed: false,
customMapping: null,
+ mapping: [],
parsingPayload: false,
currentIntegration: null,
};
@@ -195,14 +204,16 @@ export default {
},
showMappingBuilder() {
return (
+ this.multiIntegrations &&
this.glFeatures.multipleHttpIntegrationsCustomMapping &&
- this.selectedIntegration === typeSet.http
+ this.selectedIntegration === typeSet.http &&
+ this.alertFields?.length
);
},
- mappingBuilderFields() {
+ parsedSamplePayload() {
return this.customMapping?.samplePayload?.payloadAlerFields?.nodes;
},
- mappingBuilderMapping() {
+ savedMapping() {
return this.customMapping?.storedMapping?.nodes;
},
hasSamplePayload() {
@@ -255,9 +266,20 @@ export default {
},
submit() {
const { name, apiUrl } = this.integrationForm;
+ const customMappingVariables = this.glFeatures.multipleHttpIntegrationsCustomMapping
+ ? {
+ payloadAttributeMappings: this.mapping,
+ payloadExample: this.integrationTestPayload.json,
+ }
+ : {};
+
const variables =
this.selectedIntegration === typeSet.http
- ? { name, active: this.active }
+ ? {
+ name,
+ active: this.active,
+ ...customMappingVariables,
+ }
: { apiUrl, active: this.active };
const integrationPayload = { type: this.selectedIntegration, variables };
@@ -336,6 +358,9 @@ export default {
this.integrationTestPayload.json = res?.samplePayload.body;
});
},
+ updateMapping(mapping) {
+ this.mapping = mapping;
+ },
},
};
</script>
@@ -541,8 +566,10 @@ export default {
>
<span>{{ $options.i18n.integrationFormSteps.step5.intro }}</span>
<mapping-builder
- :payload-fields="mappingBuilderFields"
- :mapping="mappingBuilderMapping"
+ :parsed-payload="parsedSamplePayload"
+ :saved-mapping="savedMapping"
+ :alert-fields="alertFields"
+ @onMappingUpdate="updateMapping"
/>
</gl-form-group>
</div>
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
index d0cac066ffa..366f2209fb2 100644
--- a/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
+++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_wrapper.vue
@@ -1,21 +1,19 @@
<script>
-import { s__ } from '~/locale';
-import { fetchPolicies } from '~/lib/graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
-import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
-import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
+import { fetchPolicies } from '~/lib/graphql';
+import { s__ } from '~/locale';
+import { typeSet } from '../constants';
import createHttpIntegrationMutation from '../graphql/mutations/create_http_integration.mutation.graphql';
import createPrometheusIntegrationMutation from '../graphql/mutations/create_prometheus_integration.mutation.graphql';
-import updateHttpIntegrationMutation from '../graphql/mutations/update_http_integration.mutation.graphql';
-import updatePrometheusIntegrationMutation from '../graphql/mutations/update_prometheus_integration.mutation.graphql';
import destroyHttpIntegrationMutation from '../graphql/mutations/destroy_http_integration.mutation.graphql';
import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutation.graphql';
import resetPrometheusTokenMutation from '../graphql/mutations/reset_prometheus_token.mutation.graphql';
import updateCurrentIntergrationMutation from '../graphql/mutations/update_current_intergration.mutation.graphql';
-import IntegrationsList from './alerts_integrations_list.vue';
-import AlertSettingsForm from './alerts_settings_form.vue';
+import updateHttpIntegrationMutation from '../graphql/mutations/update_http_integration.mutation.graphql';
+import updatePrometheusIntegrationMutation from '../graphql/mutations/update_prometheus_integration.mutation.graphql';
+import getCurrentIntegrationQuery from '../graphql/queries/get_current_integration.query.graphql';
+import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
import service from '../services';
-import { typeSet } from '../constants';
import {
updateStoreAfterIntegrationDelete,
updateStoreAfterIntegrationAdd,
@@ -27,6 +25,8 @@ import {
UPDATE_INTEGRATION_ERROR,
INTEGRATION_PAYLOAD_TEST_ERROR,
} from '../utils/error_messages';
+import IntegrationsList from './alerts_integrations_list.vue';
+import AlertSettingsForm from './alerts_settings_form.vue';
export default {
typeSet,
@@ -57,6 +57,13 @@ export default {
default: false,
},
},
+ props: {
+ alertFields: {
+ type: Array,
+ required: false,
+ default: null,
+ },
+ },
apollo: {
integrations: {
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
@@ -312,6 +319,7 @@ export default {
<alert-settings-form
:loading="isUpdating"
:can-add-integration="canAddIntegration"
+ :alert-fields="alertFields"
@create-new-integration="createNewIntegration"
@update-integration="updateIntegration"
@reset-token="resetToken"
diff --git a/app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json b/app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json
deleted file mode 100644
index ac559a30eda..00000000000
--- a/app/assets/javascripts/alerts_settings/components/mocks/gitlabFields.json
+++ /dev/null
@@ -1,112 +0,0 @@
-[
- {
- "name": "title",
- "label": "Title",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ],
- "numberOfFallbacks": 1
- },
- {
- "name": "description",
- "label": "Description",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "startTime",
- "label": "Start time",
- "type": [
- "DateTime"
- ],
- "compatibleTypes": [
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "service",
- "label": "Service",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "monitoringTool",
- "label": "Monitoring tool",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "hosts",
- "label": "Hosts",
- "type": [
- "String",
- "Array"
- ],
- "compatibleTypes": [
- "String",
- "Array",
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "severity",
- "label": "Severity",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "fingerprint",
- "label": "Fingerprint",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ]
- },
- {
- "name": "environment",
- "label": "Environment",
- "type": [
- "String"
- ],
- "compatibleTypes": [
- "String",
- "Number",
- "DateTime"
- ]
- }
-]
diff --git a/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json b/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json
index 5326678155d..80fbebf2a60 100644
--- a/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json
+++ b/app/assets/javascripts/alerts_settings/components/mocks/parsedMapping.json
@@ -4,95 +4,69 @@
"payloadAlerFields": {
"nodes": [
{
- "name": "dashboardId",
+ "path": ["dashboardId"],
"label": "Dashboard Id",
- "type": [
- "Number"
- ]
+ "type": "string"
},
{
- "name": "evalMatches",
+ "path": ["evalMatches"],
"label": "Eval Matches",
- "type": [
- "Array"
- ]
+ "type": "array"
},
{
- "name": "createdAt",
+ "path": ["createdAt"],
"label": "Created At",
- "type": [
- "DateTime"
- ]
+ "type": "datetime"
},
{
- "name": "imageUrl",
+ "path": ["imageUrl"],
"label": "Image Url",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "message",
+ "path": ["message"],
"label": "Message",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "orgId",
+ "path": ["orgId"],
"label": "Org Id",
- "type": [
- "Number"
- ]
+ "type": "string"
},
{
- "name": "panelId",
+ "path": ["panelId"],
"label": "Panel Id",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "ruleId",
+ "path": ["ruleId"],
"label": "Rule Id",
- "type": [
- "Number"
- ]
+ "type": "string"
},
{
- "name": "ruleName",
+ "path": ["ruleName"],
"label": "Rule Name",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "ruleUrl",
+ "path": ["ruleUrl"],
"label": "Rule Url",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "state",
+ "path": ["state"],
"label": "State",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "title",
+ "path": ["title"],
"label": "Title",
- "type": [
- "String"
- ]
+ "type": "string"
},
{
- "name": "tags",
+ "path": ["tags", "tag"],
"label": "Tags",
- "type": [
- "Object"
- ]
+ "type": "string"
}
]
}
diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js
index 3dbfa69a8e9..5fd05169533 100644
--- a/app/assets/javascripts/alerts_settings/graphql.js
+++ b/app/assets/javascripts/alerts_settings/graphql.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import produce from 'immer';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import getCurrentIntegrationQuery from './graphql/queries/get_current_integration.query.graphql';
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
index d1dacbad40a..f3fc10b4bd4 100644
--- a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
@@ -1,7 +1,21 @@
#import "../fragments/integration_item.fragment.graphql"
-mutation createHttpIntegration($projectPath: ID!, $name: String!, $active: Boolean!) {
- httpIntegrationCreate(input: { projectPath: $projectPath, name: $name, active: $active }) {
+mutation createHttpIntegration(
+ $projectPath: ID!
+ $name: String!
+ $active: Boolean!
+ $payloadExample: JsonString
+ $payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!]
+) {
+ httpIntegrationCreate(
+ input: {
+ projectPath: $projectPath
+ name: $name
+ active: $active
+ payloadExample: $payloadExample
+ payloadAttributeMappings: $payloadAttributeMappings
+ }
+ ) {
errors
integration {
...IntegrationItem
diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js
index 85858956987..8506b3fda01 100644
--- a/app/assets/javascripts/alerts_settings/index.js
+++ b/app/assets/javascripts/alerts_settings/index.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
import apolloProvider from './graphql';
@@ -31,6 +31,7 @@ export default (el) => {
url,
projectPath,
multiIntegrations,
+ alertFields,
} = el.dataset;
return new Vue({
@@ -60,7 +61,14 @@ export default (el) => {
},
apolloProvider,
render(createElement) {
- return createElement('alert-settings-wrapper');
+ return createElement('alert-settings-wrapper', {
+ props: {
+ alertFields:
+ gon.features?.multipleHttpIntegrationsCustomMapping && parseBoolean(multiIntegrations)
+ ? JSON.parse(alertFields)
+ : null,
+ },
+ });
},
});
};
diff --git a/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js b/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js
new file mode 100644
index 00000000000..a86103540c0
--- /dev/null
+++ b/app/assets/javascripts/alerts_settings/utils/mapping_transformations.js
@@ -0,0 +1,61 @@
+/**
+ * Given data for GitLab alert fields, parsed payload fields data and previously stored mapping (if any)
+ * creates an object in a form convenient to build UI && interact with it
+ * @param {Object} gitlabFields - structure describing GitLab alert fields
+ * @param {Object} payloadFields - parsed from sample JSON sample alert fields
+ * @param {Object} savedMapping - GitLab fields to parsed fields mapping
+ *
+ * @return {Object} mapping data for UI mapping builder
+ */
+export const getMappingData = (gitlabFields, payloadFields, savedMapping) => {
+ return gitlabFields.map((gitlabField) => {
+ // find fields from payload that match gitlab alert field by type
+ const mappingFields = payloadFields.filter(({ type }) => gitlabField.types.includes(type));
+
+ // find the mapping that was previously stored
+ const foundMapping = savedMapping.find(({ fieldName }) => fieldName === gitlabField.name);
+
+ const { fallbackAlertPaths, payloadAlertPaths } = foundMapping || {};
+
+ return {
+ mapping: payloadAlertPaths,
+ fallback: fallbackAlertPaths,
+ searchTerm: '',
+ fallbackSearchTerm: '',
+ mappingFields,
+ ...gitlabField,
+ };
+ });
+};
+
+/**
+ * Based on mapping data configured by the user creates an object in a format suitable for save on BE
+ * @param {Object} mappingData - structure describing mapping between GitLab fields and parsed payload fields
+ *
+ * @return {Object} mapping data to send to BE
+ */
+export const transformForSave = (mappingData) => {
+ return mappingData.reduce((acc, field) => {
+ const mapped = field.mappingFields.find(({ name }) => name === field.mapping);
+ if (mapped) {
+ const { path, type, label } = mapped;
+ acc.push({
+ fieldName: field.name.toUpperCase(),
+ path,
+ type: type.toUpperCase(),
+ label,
+ });
+ }
+ return acc;
+ }, []);
+};
+
+/**
+ * Adds `name` prop to each provided by BE parsed payload field
+ * @param {Object} payload - parsed sample payload
+ *
+ * @return {Object} same as input with an extra `name` property which basically serves as a key to make a match
+ */
+export const getPayloadFields = (payload) => {
+ return payload.map((field) => ({ ...field, name: field.path.join('_') }));
+};
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/app.vue b/app/assets/javascripts/analytics/instance_statistics/components/app.vue
index 8df4d2e2524..3bf41eaa008 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/app.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/app.vue
@@ -1,10 +1,10 @@
<script>
+import { TODAY, TOTAL_DAYS_TO_SHOW, START_DATE } from '../constants';
+import ChartsConfig from './charts_config';
import InstanceCounts from './instance_counts.vue';
import InstanceStatisticsCountChart from './instance_statistics_count_chart.vue';
-import UsersChart from './users_chart.vue';
import ProjectsAndGroupsChart from './projects_and_groups_chart.vue';
-import ChartsConfig from './charts_config';
-import { TODAY, TOTAL_DAYS_TO_SHOW, START_DATE } from '../constants';
+import UsersChart from './users_chart.vue';
export default {
name: 'InstanceStatisticsApp',
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/instance_counts.vue b/app/assets/javascripts/analytics/instance_statistics/components/instance_counts.vue
index b331e659a92..f3779ed62e9 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/instance_counts.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/instance_counts.vue
@@ -1,9 +1,9 @@
<script>
-import * as Sentry from '~/sentry/wrapper';
-import { s__ } from '~/locale';
+import MetricCard from '~/analytics/shared/components/metric_card.vue';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
-import MetricCard from '~/analytics/shared/components/metric_card.vue';
+import { s__ } from '~/locale';
+import * as Sentry from '~/sentry/wrapper';
import instanceStatisticsCountQuery from '../graphql/queries/instance_statistics_count.query.graphql';
const defaultPrecision = 0;
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue b/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue
index 620f38bd50f..e2defe0572d 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/instance_statistics_count_chart.vue
@@ -1,16 +1,16 @@
<script>
-import { GlLineChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
import { some, every } from 'lodash';
-import * as Sentry from '~/sentry/wrapper';
-import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import {
differenceInMonths,
formatDateAsMonth,
getDayDifference,
} from '~/lib/utils/datetime_utility';
-import { getAverageByMonth, getEarliestDate, generateDataKeys } from '../utils';
+import * as Sentry from '~/sentry/wrapper';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import { TODAY, START_DATE } from '../constants';
+import { getAverageByMonth, getEarliestDate, generateDataKeys } from '../utils';
const QUERY_DATA_KEY = 'instanceStatisticsMeasurements';
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue b/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue
index 46cc05fc124..3ffec90fb68 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/projects_and_groups_chart.vue
@@ -3,10 +3,10 @@ import { GlAlert } from '@gitlab/ui';
import { GlLineChart } from '@gitlab/ui/dist/charts';
import produce from 'immer';
import { sortBy } from 'lodash';
+import { formatDateAsMonth } from '~/lib/utils/datetime_utility';
+import { s__, __ } from '~/locale';
import * as Sentry from '~/sentry/wrapper';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import { s__, __ } from '~/locale';
-import { formatDateAsMonth } from '~/lib/utils/datetime_utility';
import latestGroupsQuery from '../graphql/queries/groups.query.graphql';
import latestProjectsQuery from '../graphql/queries/projects.query.graphql';
import { getAverageByMonth } from '../utils';
diff --git a/app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue b/app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue
index 03462113630..73940f028a1 100644
--- a/app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue
+++ b/app/assets/javascripts/analytics/instance_statistics/components/users_chart.vue
@@ -3,10 +3,10 @@ import { GlAlert } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import produce from 'immer';
import { sortBy } from 'lodash';
+import { formatDateAsMonth } from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
import * as Sentry from '~/sentry/wrapper';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import { __ } from '~/locale';
-import { formatDateAsMonth } from '~/lib/utils/datetime_utility';
import usersQuery from '../graphql/queries/users.query.graphql';
import { getAverageByMonth } from '../utils';
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 0a3db8ad3a6..c7e6b98a934 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -1,7 +1,7 @@
-import axios from './lib/utils/axios_utils';
-import { joinPaths } from './lib/utils/url_utility';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
+import axios from './lib/utils/axios_utils';
+import { joinPaths } from './lib/utils/url_utility';
const DEFAULT_PER_PAGE = 20;
@@ -81,8 +81,10 @@ const Api = {
usageDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users',
featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists',
featureFlagUserList: '/api/:version/projects/:id/feature_flags_user_lists/:list_iid',
- billableGroupMembersPath: '/api/:version/groups/:id/billable_members',
containerRegistryDetailsPath: '/api/:version/registry/repositories/:id/',
+ projectNotificationSettingsPath: '/api/:version/projects/:id/notification_settings',
+ groupNotificationSettingsPath: '/api/:version/groups/:id/notification_settings',
+ notificationSettingsPath: '/api/:version/notification_settings',
group(groupId, callback = () => {}) {
const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
@@ -179,9 +181,9 @@ const Api = {
});
},
- groupLabels(namespace) {
+ groupLabels(namespace, options = {}) {
const url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespace);
- return axios.get(url).then(({ data }) => data);
+ return axios.get(url, options).then(({ data }) => data);
},
// Return namespaces list. Filtered by query
@@ -442,10 +444,11 @@ const Api = {
});
},
- applySuggestion(id, message) {
+ applySuggestion(id, message = '') {
const url = Api.buildUrl(Api.applySuggestionPath).replace(':id', encodeURIComponent(id));
+ const params = gon.features?.suggestionsCustomCommit ? { commit_message: message } : false;
- return axios.put(url, { commit_message: message });
+ return axios.put(url, params);
},
applySuggestionBatch(ids) {
@@ -879,31 +882,32 @@ const Api = {
return axios.delete(url);
},
- fetchBillableGroupMembersList(namespaceId, options = {}, callback = () => {}) {
- const url = Api.buildUrl(this.billableGroupMembersPath).replace(':id', namespaceId);
- const defaults = {
- per_page: DEFAULT_PER_PAGE,
- page: 1,
- };
+ async updateNotificationSettings(projectId, groupId, data = {}) {
+ let url = Api.buildUrl(this.notificationSettingsPath);
+
+ if (projectId) {
+ url = Api.buildUrl(this.projectNotificationSettingsPath).replace(':id', projectId);
+ } else if (groupId) {
+ url = Api.buildUrl(this.groupNotificationSettingsPath).replace(':id', groupId);
+ }
+
+ const result = await axios.put(url, data);
+
+ return result;
+ },
- const passedOptions = options;
+ async getNotificationSettings(projectId, groupId) {
+ let url = Api.buildUrl(this.notificationSettingsPath);
- // calling search API with empty string will not return results
- if (!passedOptions.search) {
- passedOptions.search = undefined;
+ if (projectId) {
+ url = Api.buildUrl(this.projectNotificationSettingsPath).replace(':id', projectId);
+ } else if (groupId) {
+ url = Api.buildUrl(this.groupNotificationSettingsPath).replace(':id', groupId);
}
- return axios
- .get(url, {
- params: {
- ...defaults,
- ...passedOptions,
- },
- })
- .then(({ data, headers }) => {
- callback(data);
- return { data, headers };
- });
+ const result = await axios.get(url);
+
+ return result;
},
};
diff --git a/app/assets/javascripts/api/user_api.js b/app/assets/javascripts/api/user_api.js
index e5983ec3c58..5efc7063efa 100644
--- a/app/assets/javascripts/api/user_api.js
+++ b/app/assets/javascripts/api/user_api.js
@@ -1,8 +1,8 @@
+import { deprecatedCreateFlash as flash } from '~/flash';
+import { __ } from '~/locale';
import axios from '../lib/utils/axios_utils';
import { buildApiUrl } from './api_utils';
import { DEFAULT_PER_PAGE } from './constants';
-import { deprecatedCreateFlash as flash } from '~/flash';
-import { __ } from '~/locale';
const USER_COUNTS_PATH = '/api/:version/user_counts';
const USERS_PATH = '/api/:version/users.json';
diff --git a/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_application_setting.query.graphql b/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_application_setting.query.graphql
new file mode 100644
index 00000000000..9d833d81a3f
--- /dev/null
+++ b/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_application_setting.query.graphql
@@ -0,0 +1,5 @@
+query getKeepLatestArtifactApplicationSetting {
+ ciApplicationSettings {
+ keepLatestArtifact
+ }
+}
diff --git a/app/assets/javascripts/artifacts_settings/index.js b/app/assets/javascripts/artifacts_settings/index.js
index d99d2be81cf..531b42bc185 100644
--- a/app/assets/javascripts/artifacts_settings/index.js
+++ b/app/assets/javascripts/artifacts_settings/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import KeepLatestArtifactCheckbox from '~/artifacts_settings/keep_latest_artifact_checkbox.vue';
+import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue b/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue
index 5684033f3af..92f1cc8117a 100644
--- a/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue
+++ b/app/assets/javascripts/artifacts_settings/keep_latest_artifact_checkbox.vue
@@ -1,13 +1,23 @@
<script>
import { GlAlert, GlFormCheckbox, GlLink } from '@gitlab/ui';
import { __ } from '~/locale';
-import GetKeepLatestArtifactProjectSetting from './graphql/queries/get_keep_latest_artifact_project_setting.query.graphql';
import UpdateKeepLatestArtifactProjectSetting from './graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql';
-
-const FETCH_ERROR = __('There was a problem fetching the keep latest artifact setting.');
-const UPDATE_ERROR = __('There was a problem updating the keep latest artifact setting.');
+import GetKeepLatestArtifactApplicationSetting from './graphql/queries/get_keep_latest_artifact_application_setting.query.graphql';
+import GetKeepLatestArtifactProjectSetting from './graphql/queries/get_keep_latest_artifact_project_setting.query.graphql';
export default {
+ errors: {
+ fetchError: __('There was a problem fetching the keep latest artifacts setting.'),
+ updateError: __('There was a problem updating the keep latest artifacts setting.'),
+ },
+ i18n: {
+ enabledHelpText: __(
+ 'The latest artifacts created by jobs in the most recent successful pipeline will be stored.',
+ ),
+ disabledHelpText: __('This feature is disabled at the instance level.'),
+ helpLinkText: __('More information'),
+ checkboxText: __('Keep artifacts from most recent successful jobs'),
+ },
components: {
GlAlert,
GlFormCheckbox,
@@ -33,21 +43,33 @@ export default {
return data.project?.ciCdSettings?.keepLatestArtifact;
},
error() {
- this.reportError(FETCH_ERROR);
+ this.reportError(this.$options.errors.fetchError);
+ },
+ },
+ projectSettingDisabled: {
+ query: GetKeepLatestArtifactApplicationSetting,
+ update(data) {
+ return !data.ciApplicationSettings?.keepLatestArtifact;
},
},
},
data() {
return {
- keepLatestArtifact: true,
+ keepLatestArtifact: null,
errorMessage: '',
isAlertDismissed: false,
+ projectSettingDisabled: true,
};
},
computed: {
shouldShowAlert() {
return this.errorMessage && !this.isAlertDismissed;
},
+ helpText() {
+ return this.projectSettingDisabled
+ ? this.$options.i18n.disabledHelpText
+ : this.$options.i18n.enabledHelpText;
+ },
},
methods: {
reportError(error) {
@@ -65,10 +87,10 @@ export default {
});
if (data.ciCdSettingsUpdate.errors.length) {
- this.reportError(UPDATE_ERROR);
+ this.reportError(this.$options.errors.updateError);
}
} catch (error) {
- this.reportError(UPDATE_ERROR);
+ this.reportError(this.$options.errors.updateError);
}
},
},
@@ -84,16 +106,13 @@ export default {
@dismiss="isAlertDismissed = true"
>{{ errorMessage }}</gl-alert
>
- <gl-form-checkbox v-model="keepLatestArtifact" @change="updateSetting"
- ><b class="gl-mr-3">{{ __('Keep artifacts from most recent successful jobs') }}</b>
- <gl-link :href="helpPagePath">{{ __('More information') }}</gl-link></gl-form-checkbox
- >
- <p>
- {{
- __(
- 'The latest artifacts created by jobs in the most recent successful pipeline will be stored.',
- )
- }}
- </p>
+ <gl-form-checkbox
+ v-model="keepLatestArtifact"
+ :disabled="projectSettingDisabled"
+ @change="updateSetting"
+ ><strong class="gl-mr-3">{{ $options.i18n.checkboxText }}</strong>
+ <gl-link :href="helpPagePath">{{ $options.i18n.helpLinkText }}</gl-link>
+ <template v-if="!$apollo.loading" #help>{{ helpText }}</template>
+ </gl-form-checkbox>
</div>
</template>
diff --git a/app/assets/javascripts/authentication/mount_2fa.js b/app/assets/javascripts/authentication/mount_2fa.js
index 6dead2f03db..52ed67b8c7b 100644
--- a/app/assets/javascripts/authentication/mount_2fa.js
+++ b/app/assets/javascripts/authentication/mount_2fa.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import initU2F from './u2f';
-import initWebauthn from './webauthn';
import U2FRegister from './u2f/register';
+import initWebauthn from './webauthn';
import WebAuthnRegister from './webauthn/register';
export const mount2faAuthentication = () => {
diff --git a/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue b/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue
index 87502db8b82..0e589d98668 100644
--- a/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue
+++ b/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue
@@ -1,9 +1,9 @@
<script>
-import Mousetrap from 'mousetrap';
import { GlSprintf, GlButton, GlAlert } from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Tracking from '~/tracking';
+import Mousetrap from 'mousetrap';
import { __ } from '~/locale';
+import Tracking from '~/tracking';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import {
COPY_BUTTON_ACTION,
DOWNLOAD_BUTTON_ACTION,
diff --git a/app/assets/javascripts/authentication/u2f/authenticate.js b/app/assets/javascripts/authentication/u2f/authenticate.js
index f5217e9c9be..22eca904f32 100644
--- a/app/assets/javascripts/authentication/u2f/authenticate.js
+++ b/app/assets/javascripts/authentication/u2f/authenticate.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { template as lodashTemplate, omit } from 'lodash';
-import importU2FLibrary from './util';
import U2FError from './error';
+import importU2FLibrary from './util';
// Authenticate U2F (universal 2nd factor) devices for users to authenticate with.
//
diff --git a/app/assets/javascripts/authentication/u2f/register.js b/app/assets/javascripts/authentication/u2f/register.js
index 52940e1c305..6c98f0978bc 100644
--- a/app/assets/javascripts/authentication/u2f/register.js
+++ b/app/assets/javascripts/authentication/u2f/register.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import { template as lodashTemplate } from 'lodash';
import { __ } from '~/locale';
-import importU2FLibrary from './util';
import U2FError from './error';
+import importU2FLibrary from './util';
// Register U2F (universal 2nd factor) devices for users to authenticate with.
//
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index 22717a3f84c..6fb90551ed7 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -1,15 +1,15 @@
/* eslint-disable class-methods-use-this, @gitlab/require-i18n-strings */
-import $ from 'jquery';
-import { uniq } from 'lodash';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import $ from 'jquery';
import Cookies from 'js-cookie';
-import { __ } from './locale';
-import { isInVueNoteablePage } from './lib/utils/dom_utils';
-import { deprecatedCreateFlash as flash } from './flash';
-import axios from './lib/utils/axios_utils';
+import { uniq } from 'lodash';
import * as Emoji from '~/emoji';
import { dispose, fixTitle } from '~/tooltips';
+import { deprecatedCreateFlash as flash } from './flash';
+import axios from './lib/utils/axios_utils';
+import { isInVueNoteablePage } from './lib/utils/dom_utils';
+import { __ } from './locale';
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
@@ -560,7 +560,7 @@ export class AwardsHandler {
}
findMatchingEmojiElements(query) {
- const emojiMatches = this.emoji.searchEmoji(query, { match: 'fuzzy' }).map(({ name }) => name);
+ const emojiMatches = this.emoji.searchEmoji(query).map((x) => x.emoji.name);
const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]');
const $matchingElements = $emojiElements.filter(
(i, elm) => emojiMatches.indexOf(elm.dataset.name) >= 0,
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 9e09f527a39..20541ad8ccc 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -1,8 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui';
import { escape, debounce } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
import createEmptyBadge from '../empty_badge';
@@ -179,7 +179,7 @@ export default {
id="badge-link-url"
v-model="linkUrl"
type="URL"
- class="form-control"
+ class="form-control gl-form-input"
required
@input="debouncedPreview"
/>
@@ -194,7 +194,7 @@ export default {
id="badge-image-url"
v-model="imageUrl"
type="URL"
- class="form-control"
+ class="form-control gl-form-input"
required
@input="debouncedPreview"
/>
diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue
index 04c2d4a7493..f16a547e441 100644
--- a/app/assets/javascripts/badges/components/badge_list.vue
+++ b/app/assets/javascripts/badges/components/badge_list.vue
@@ -1,8 +1,8 @@
<script>
-import { mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
-import BadgeListRow from './badge_list_row.vue';
+import { mapState } from 'vuex';
import { GROUP_BADGE } from '../constants';
+import BadgeListRow from './badge_list_row.vue';
export default {
name: 'BadgeList',
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index 4ca91e7a589..fda51c98e2c 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlLoadingIcon, GlButton, GlModalDirective } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import { PROJECT_BADGE } from '../constants';
import Badge from './badge.vue';
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index 73c63a72b1c..8d5bd216367 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlSprintf, GlModal } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__ } from '~/locale';
import Badge from './badge.vue';
diff --git a/app/assets/javascripts/badges/store/actions.js b/app/assets/javascripts/badges/store/actions.js
index 3377f6c0996..17a03564432 100644
--- a/app/assets/javascripts/badges/store/actions.js
+++ b/app/assets/javascripts/badges/store/actions.js
@@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
-import types from './mutation_types';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import types from './mutation_types';
export const transformBackendBadge = (badge) => ({
...convertObjectPropsToCamelCase(badge, true),
diff --git a/app/assets/javascripts/badges/store/index.js b/app/assets/javascripts/badges/store/index.js
index 7a5df403a0e..848deb2baa7 100644
--- a/app/assets/javascripts/badges/store/index.js
+++ b/app/assets/javascripts/badges/store/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createState from './state';
import actions from './actions';
import mutations from './mutations';
+import createState from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/badges/store/mutations.js b/app/assets/javascripts/badges/store/mutations.js
index 3f4689aeb17..9e27af21ed6 100644
--- a/app/assets/javascripts/badges/store/mutations.js
+++ b/app/assets/javascripts/badges/store/mutations.js
@@ -1,5 +1,5 @@
-import types from './mutation_types';
import { PROJECT_BADGE } from '../constants';
+import types from './mutation_types';
const reorderBadges = (badges) =>
badges.sort((a, b) => {
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 74069b61f07..e6de724512f 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -1,10 +1,9 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
import NoteableNote from '~/notes/components/noteable_note.vue';
import PublishButton from './publish_button.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
@@ -12,7 +11,6 @@ export default {
PublishButton,
GlButton,
},
- mixins: [glFeatureFlagsMixin()],
props: {
draft: {
type: Object,
@@ -63,14 +61,14 @@ export default {
this.isEditingDraft = false;
},
handleMouseEnter(draft) {
- if (this.glFeatures.multilineComments && draft.position) {
+ if (draft.position) {
this.setSelectedCommentPositionHover(draft.position.line_range);
}
},
handleMouseLeave(draft) {
- // Even though position isn't used here we still don't want to unecessarily call a mutation
+ // Even though position isn't used here we still don't want to unnecessarily call a mutation
// The lack of position tells us that highlighting is irrelevant in this context
- if (this.glFeatures.multilineComments && draft.position) {
+ if (draft.position) {
this.setSelectedCommentPositionHover();
}
},
@@ -79,7 +77,6 @@ export default {
</script>
<template>
<article
- role="article"
class="draft-note-component note-wrapper"
@mouseenter="handleMouseEnter(draft)"
@mouseleave="handleMouseLeave(draft)"
diff --git a/app/assets/javascripts/batch_comments/components/drafts_count.vue b/app/assets/javascripts/batch_comments/components/drafts_count.vue
index 7a8482ac341..5e110b101eb 100644
--- a/app/assets/javascripts/batch_comments/components/drafts_count.vue
+++ b/app/assets/javascripts/batch_comments/components/drafts_count.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlBadge } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
index e18dc344cd7..fb643d441ec 100644
--- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
+import { mapActions, mapGetters } from 'vuex';
import PreviewItem from './preview_item.vue';
export default {
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index 3e93168f0e2..756bcfdb3d0 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -1,22 +1,21 @@
<script>
-import { mapGetters } from 'vuex';
import { GlSprintf, GlIcon } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import { sprintf, __ } from '~/locale';
-import resolvedStatusMixin from '../mixins/resolved_status';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
getStartLineNumber,
getEndLineNumber,
getLineClasses,
} from '~/notes/components/multiline_comment_utils';
+import resolvedStatusMixin from '../mixins/resolved_status';
export default {
components: {
GlIcon,
GlSprintf,
},
- mixins: [resolvedStatusMixin, glFeatureFlagsMixin()],
+ mixins: [resolvedStatusMixin],
props: {
draft: {
type: Object,
@@ -71,6 +70,10 @@ export default {
return this.draft.position || this.discussion.position;
},
startLineNumber() {
+ if (this.position?.position_type === IMAGE_DIFF_POSITION_TYPE) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `${this.position.x}x ${this.position.y}y`;
+ }
return getStartLineNumber(this.position?.line_range);
},
endLineNumber() {
@@ -90,16 +93,12 @@ export default {
<span>
<span class="review-preview-item-header">
<gl-icon class="flex-shrink-0" :name="iconName" />
- <span
- class="bold text-nowrap"
- :class="{ 'gl-align-items-center': glFeatures.multilineComments }"
- >
+ <span class="bold text-nowrap gl-align-items-center">
<span class="review-preview-item-header-text block-truncated">
{{ titleText }}
</span>
<template v-if="showLinePosition">
- <template v-if="!glFeatures.multilineComments">:{{ linePosition }}</template>
- <template v-else-if="startLineNumber === endLineNumber">
+ <template v-if="startLineNumber === endLineNumber">
:<span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span>
</template>
<gl-sprintf v-else :message="__(':%{startLine} to %{endLine}')">
diff --git a/app/assets/javascripts/batch_comments/components/publish_button.vue b/app/assets/javascripts/batch_comments/components/publish_button.vue
index ecced36771e..8568dba5947 100644
--- a/app/assets/javascripts/batch_comments/components/publish_button.vue
+++ b/app/assets/javascripts/batch_comments/components/publish_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import DraftsCount from './drafts_count.vue';
export default {
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
index a29409c52ae..36fef06eeff 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js
@@ -1,9 +1,9 @@
import { deprecatedCreateFlash as flash } from '~/flash';
-import { __ } from '~/locale';
import { scrollToElement } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import { CHANGES_TAB, DISCUSSION_TAB, SHOW_TAB } from '../../../constants';
import service from '../../../services/drafts_service';
import * as types from './mutation_types';
-import { CHANGES_TAB, DISCUSSION_TAB, SHOW_TAB } from '../../../constants';
export const saveDraft = ({ dispatch }, draft) =>
dispatch('saveNote', { ...draft, isDraft: true }, { root: true });
@@ -67,13 +67,23 @@ export const publishReview = ({ commit, dispatch, getters }) => {
.catch(() => commit(types.RECEIVE_PUBLISH_REVIEW_ERROR));
};
-export const updateDiscussionsAfterPublish = ({ dispatch, getters, rootGetters }) =>
- dispatch('fetchDiscussions', { path: getters.getNotesData.discussionsPath }, { root: true }).then(
- () =>
- dispatch('diffs/assignDiscussionsToDiff', rootGetters.discussionsStructuredByLineCode, {
- root: true,
- }),
- );
+export const updateDiscussionsAfterPublish = async ({ dispatch, getters, rootGetters }) => {
+ if (window.gon?.features?.paginatedNotes) {
+ await dispatch('stopPolling', null, { root: true });
+ await dispatch('fetchData', null, { root: true });
+ await dispatch('restartPolling', null, { root: true });
+ } else {
+ await dispatch(
+ 'fetchDiscussions',
+ { path: getters.getNotesData.discussionsPath },
+ { root: true },
+ );
+ }
+
+ dispatch('diffs/assignDiscussionsToDiff', rootGetters.discussionsStructuredByLineCode, {
+ root: true,
+ });
+};
export const updateDraft = (
{ commit, getters },
diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js
index 81dab0566c1..81a51b5ab31 100644
--- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js
+++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/index.js
@@ -1,7 +1,7 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
export default () => ({
namespaced: true,
diff --git a/app/assets/javascripts/behaviors/autosize.js b/app/assets/javascripts/behaviors/autosize.js
index a5404539c17..181d841a068 100644
--- a/app/assets/javascripts/behaviors/autosize.js
+++ b/app/assets/javascripts/behaviors/autosize.js
@@ -1,13 +1,11 @@
import Autosize from 'autosize';
import { waitForCSSLoaded } from '~/helpers/startup_css_helper';
-document.addEventListener('DOMContentLoaded', () => {
- waitForCSSLoaded(() => {
- const autosizeEls = document.querySelectorAll('.js-autosize');
+waitForCSSLoaded(() => {
+ const autosizeEls = document.querySelectorAll('.js-autosize');
- Autosize(autosizeEls);
- Autosize.update(autosizeEls);
+ Autosize(autosizeEls);
+ Autosize.update(autosizeEls);
- autosizeEls.forEach((el) => el.classList.add('js-autosize-initialized'));
- });
+ autosizeEls.forEach((el) => el.classList.add('js-autosize-initialized'));
});
diff --git a/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js b/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js
index c4af34b848b..5e474e56196 100644
--- a/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js
+++ b/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import $ from 'jquery';
/**
* This behavior collapses the right sidebar
diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js
index 1176fa6628d..a31bcc2cb41 100644
--- a/app/assets/javascripts/behaviors/copy_to_clipboard.js
+++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import Clipboard from 'clipboard';
+import $ from 'jquery';
import { sprintf, __ } from '~/locale';
import { fixTitle, show } from '~/tooltips';
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
index 1fa37999d62..bf7a87144f9 100644
--- a/app/assets/javascripts/behaviors/gl_emoji.js
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -1,6 +1,12 @@
import 'document-register-element';
+import {
+ initEmojiMap,
+ getEmojiInfo,
+ emojiFallbackImageSrc,
+ emojiImageTag,
+ FALLBACK_EMOJI_KEY,
+} from '../emoji';
import isEmojiUnicodeSupported from '../emoji/support';
-import { initEmojiMap, getEmojiInfo, emojiFallbackImageSrc, emojiImageTag } from '../emoji';
class GlEmoji extends HTMLElement {
connectedCallback() {
@@ -17,6 +23,10 @@ class GlEmoji extends HTMLElement {
if (emojiInfo) {
if (name !== emojiInfo.name) {
+ if (emojiInfo.name === FALLBACK_EMOJI_KEY && this.innerHTML) {
+ return; // When fallback emoji is used, but there is a <img> provided, use the <img> instead
+ }
+
({ name } = emojiInfo);
this.dataset.name = emojiInfo.name;
}
diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js
index 75659bbf685..bfd025e8dab 100644
--- a/app/assets/javascripts/behaviors/index.js
+++ b/app/assets/javascripts/behaviors/index.js
@@ -2,17 +2,17 @@ import $ from 'jquery';
import './autosize';
import './bind_in_out';
import './markdown/render_gfm';
-import initCopyAsGFM from './markdown/copy_as_gfm';
+import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resize';
import initCopyToClipboard from './copy_to_clipboard';
import installGlEmojiElement from './gl_emoji';
+import { loadStartupCSS } from './load_startup_css';
+import initCopyAsGFM from './markdown/copy_as_gfm';
import './quick_submit';
import './requires_input';
+import initSelect2Dropdowns from './select2';
import initPageShortcuts from './shortcuts';
import './toggler_behavior';
import './preview_markdown';
-import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resize';
-import initSelect2Dropdowns from './select2';
-import { loadStartupCSS } from './load_startup_css';
loadStartupCSS();
@@ -25,19 +25,17 @@ initPageShortcuts();
initCollapseSidebarOnWindowResize();
initSelect2Dropdowns();
-document.addEventListener('DOMContentLoaded', () => {
- window.requestIdleCallback(
- () => {
- // Check if we have to Load GFM Input
- const $gfmInputs = $('.js-gfm-input:not(.js-gfm-input-initialized)');
- if ($gfmInputs.length) {
- import(/* webpackChunkName: 'initGFMInput' */ './markdown/gfm_auto_complete')
- .then(({ default: initGFMInput }) => {
- initGFMInput($gfmInputs);
- })
- .catch(() => {});
- }
- },
- { timeout: 500 },
- );
-});
+window.requestIdleCallback(
+ () => {
+ // Check if we have to Load GFM Input
+ const $gfmInputs = $('.js-gfm-input:not(.js-gfm-input-initialized)');
+ if ($gfmInputs.length) {
+ import(/* webpackChunkName: 'initGFMInput' */ './markdown/gfm_auto_complete')
+ .then(({ default: initGFMInput }) => {
+ initGFMInput($gfmInputs);
+ })
+ .catch(() => {});
+ }
+ },
+ { timeout: 500 },
+);
diff --git a/app/assets/javascripts/behaviors/markdown/editor_extensions.js b/app/assets/javascripts/behaviors/markdown/editor_extensions.js
index 308e31e7047..b512e4dbc8b 100644
--- a/app/assets/javascripts/behaviors/markdown/editor_extensions.js
+++ b/app/assets/javascripts/behaviors/markdown/editor_extensions.js
@@ -1,52 +1,45 @@
-import Doc from './nodes/doc';
-import Paragraph from './nodes/paragraph';
-import Text from './nodes/text';
-
+import Bold from './marks/bold';
+import Code from './marks/code';
+import InlineDiff from './marks/inline_diff';
+import InlineHTML from './marks/inline_html';
+import Italic from './marks/italic';
+import Link from './marks/link';
+import MathMark from './marks/math';
+import Strike from './marks/strike';
+import Audio from './nodes/audio';
import Blockquote from './nodes/blockquote';
+import BulletList from './nodes/bullet_list';
import CodeBlock from './nodes/code_block';
+import DescriptionDetails from './nodes/description_details';
+import DescriptionList from './nodes/description_list';
+import DescriptionTerm from './nodes/description_term';
+import Details from './nodes/details';
+import Doc from './nodes/doc';
+
+import Emoji from './nodes/emoji';
import HardBreak from './nodes/hard_break';
import Heading from './nodes/heading';
import HorizontalRule from './nodes/horizontal_rule';
import Image from './nodes/image';
+import ListItem from './nodes/list_item';
+import OrderedList from './nodes/ordered_list';
+import OrderedTaskList from './nodes/ordered_task_list';
+import Paragraph from './nodes/paragraph';
+import Reference from './nodes/reference';
+import Summary from './nodes/summary';
import Table from './nodes/table';
-import TableHead from './nodes/table_head';
import TableBody from './nodes/table_body';
-import TableHeaderRow from './nodes/table_header_row';
-import TableRow from './nodes/table_row';
import TableCell from './nodes/table_cell';
-
-import Emoji from './nodes/emoji';
-import Reference from './nodes/reference';
-
+import TableHead from './nodes/table_head';
+import TableHeaderRow from './nodes/table_header_row';
import TableOfContents from './nodes/table_of_contents';
-import Video from './nodes/video';
-import Audio from './nodes/audio';
-
-import BulletList from './nodes/bullet_list';
-import OrderedList from './nodes/ordered_list';
-import ListItem from './nodes/list_item';
-
-import DescriptionList from './nodes/description_list';
-import DescriptionTerm from './nodes/description_term';
-import DescriptionDetails from './nodes/description_details';
+import TableRow from './nodes/table_row';
import TaskList from './nodes/task_list';
-import OrderedTaskList from './nodes/ordered_task_list';
import TaskListItem from './nodes/task_list_item';
-
-import Summary from './nodes/summary';
-import Details from './nodes/details';
-
-import Bold from './marks/bold';
-import Italic from './marks/italic';
-import Strike from './marks/strike';
-import InlineDiff from './marks/inline_diff';
-
-import Link from './marks/link';
-import Code from './marks/code';
-import MathMark from './marks/math';
-import InlineHTML from './marks/inline_html';
+import Text from './nodes/text';
+import Video from './nodes/video';
// The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb transform
// GitLab Flavored Markdown (GFM) to HTML.
diff --git a/app/assets/javascripts/behaviors/markdown/marks/bold.js b/app/assets/javascripts/behaviors/markdown/marks/bold.js
index b537954c1cb..d307edd9fd3 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 { Bold as BaseBold } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Bold as BaseBold } from 'tiptap-extensions';
// 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 a760ee80dd0..ccfe2cf5b8d 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 { Code as BaseCode } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Code as BaseCode } from 'tiptap-extensions';
// 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/inline_html.js b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
index 556e6f7df1c..e957f81b774 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { Mark } from 'tiptap';
import { escape } from 'lodash';
+import { Mark } from 'tiptap';
// Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter
export default class InlineHTML extends Mark {
diff --git a/app/assets/javascripts/behaviors/markdown/marks/italic.js b/app/assets/javascripts/behaviors/markdown/marks/italic.js
index 44b35c97739..dbef10536ab 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 { Italic as BaseItalic } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Italic as BaseItalic } from 'tiptap-extensions';
// 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 5c23d6a5ceb..1111c51805d 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 { Link as BaseLink } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Link as BaseLink } from 'tiptap-extensions';
// 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 04441d5d710..382bf5c9b5b 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 { Mark } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Mark } from 'tiptap';
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 b0bc8f79643..bd5868e5524 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 { Blockquote as BaseBlockquote } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Blockquote as BaseBlockquote } from 'tiptap-extensions';
// 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 3b0792e1af8..209e7239998 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 { BulletList as BaseBulletList } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { BulletList as BaseBulletList } from 'tiptap-extensions';
// 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 fec8608cf5d..708da053a2f 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 { Heading as BaseHeading } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Heading as BaseHeading } from 'tiptap-extensions';
// 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 695c7160bde..47a24eae1e8 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 { HorizontalRule as BaseHorizontalRule } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { HorizontalRule as BaseHorizontalRule } from 'tiptap-extensions';
// 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 76746528e72..ade5839d10b 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/image.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/image.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import { Image as BaseImage } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Image as BaseImage } from 'tiptap-extensions';
import { placeholderImage } from '~/lazy_loader';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js
index 4237637ed9a..0f56e89dca6 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 { ListItem as BaseListItem } from 'tiptap-extensions';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { ListItem as BaseListItem } from 'tiptap-extensions';
// 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 dec3207b1bb..93d00f27868 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 { Node } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Node } from 'tiptap';
// 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 9cbd95a7bd8..33bb6e0c31c 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 { Node } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Node } from 'tiptap';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
/**
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js b/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js
index 6e3c16f0a08..2cb2bb9e7fe 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
-import TableRow from './table_row';
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
+import TableRow from './table_row';
const CENTER_ALIGN = 'center';
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/text.js b/app/assets/javascripts/behaviors/markdown/nodes/text.js
index 84838c14999..4eab10c9d98 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 { Node } from 'tiptap';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
+import { Node } from 'tiptap';
export default class Text extends Node {
get name() {
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index 5e9d80e1529..7934eac2f7e 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -1,10 +1,10 @@
import $ from 'jquery';
import syntaxHighlight from '~/syntax_highlight';
+import initUserPopovers from '../../user_popovers';
+import highlightCurrentUser from './highlight_current_user';
import renderMath from './render_math';
import renderMermaid from './render_mermaid';
import renderMetrics from './render_metrics';
-import highlightCurrentUser from './highlight_current_user';
-import initUserPopovers from '../../user_popovers';
// Render GitLab flavoured Markdown
//
diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
index f34fec4d449..5479866c99a 100644
--- a/app/assets/javascripts/behaviors/markdown/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -1,6 +1,6 @@
import { deprecatedCreateFlash as flash } from '~/flash';
-import { s__, sprintf } from '~/locale';
import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
+import { s__, sprintf } from '~/locale';
// Renders math using KaTeX in any element with the
// `js-render-math` class
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index 479782a1f1f..0cb13815c7e 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -140,7 +140,7 @@ function renderMermaids($els) {
'Warning: Displaying this diagram might cause performance issues on this page.',
)}</div>
<div class="gl-alert-actions">
- <button class="js-lazy-render-mermaid btn gl-alert-action btn-warning btn-md new-gl-button">Display</button>
+ <button class="js-lazy-render-mermaid btn gl-alert-action btn-warning btn-md gl-button">Display</button>
</div>
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index def1c567cd5..5405819cfe0 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -1,8 +1,8 @@
/* eslint-disable func-names */
import $ from 'jquery';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
// MarkdownPreview
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index 68e831252d6..12a2baed6e2 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import '../commons/bootstrap';
-import { isInIssuePage } from '../lib/utils/common_utils';
import { __ } from '~/locale';
import { add, show, hide } from '~/tooltips';
+import { isInIssuePage } from '../lib/utils/common_utils';
// Quick Submit behavior
//
diff --git a/app/assets/javascripts/behaviors/secret_values.js b/app/assets/javascripts/behaviors/secret_values.js
index 2f1951c97f9..a34d5dcaef8 100644
--- a/app/assets/javascripts/behaviors/secret_values.js
+++ b/app/assets/javascripts/behaviors/secret_values.js
@@ -1,5 +1,5 @@
-import { n__ } from '../locale';
import { parseBoolean } from '../lib/utils/common_utils';
+import { n__ } from '../locale';
export default class SecretValues {
constructor({
diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
index 10832583783..0513e807ed6 100644
--- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js
+++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js
@@ -1,6 +1,6 @@
import { flatten } from 'lodash';
-import { s__ } from '~/locale';
import AccessorUtilities from '~/lib/utils/accessor';
+import { s__ } from '~/locale';
import { shouldDisableShortcuts } from './shortcuts_toggle';
export const LOCAL_STORAGE_KEY = 'gl-keyboard-shortcuts-customizations';
@@ -29,6 +29,7 @@ export const customizations = parsedCustomizations;
// All available commands
export const TOGGLE_PERFORMANCE_BAR = 'globalShortcuts.togglePerformanceBar';
+export const TOGGLE_CANARY = 'globalShortcuts.toggleCanary';
/** All keybindings, grouped and ordered with descriptions */
export const keybindingGroups = [
@@ -42,6 +43,12 @@ export const keybindingGroups = [
// eslint-disable-next-line @gitlab/require-i18n-strings
defaultKeys: ['p b'],
},
+ {
+ description: s__('KeyboardShortcuts|Toggle GitLab Next'),
+ command: TOGGLE_CANARY,
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ defaultKeys: ['g x'],
+ },
],
},
]
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index 50d2399b312..e4ec68601e0 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -1,15 +1,14 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
+import { flatten } from 'lodash';
import Mousetrap from 'mousetrap';
import Vue from 'vue';
-import { flatten } from 'lodash';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import findAndFollowLink from '~/lib/utils/navigation_utility';
+import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility';
+
+import { keysFor, TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY } from './keybindings';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
-import ShortcutsToggle from './shortcuts_toggle.vue';
-import axios from '../../lib/utils/axios_utils';
-import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility';
-import findAndFollowLink from '../../lib/utils/navigation_utility';
-import { parseBoolean, getCspNonceValue } from '~/lib/utils/common_utils';
-import { keysFor, TOGGLE_PERFORMANCE_BAR } from './keybindings';
const defaultStopCallback = Mousetrap.prototype.stopCallback;
Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
@@ -20,15 +19,6 @@ Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo
return defaultStopCallback.call(this, e, element, combo);
};
-function initToggleButton() {
- return new Vue({
- el: document.querySelector('.js-toggle-shortcuts'),
- render(createElement) {
- return createElement(ShortcutsToggle);
- },
- });
-}
-
/**
* The key used to save and fetch the local Mousetrap instance
* attached to a `<textarea>` element using `jQuery.data`
@@ -65,13 +55,15 @@ function getToolbarBtnToShortcutsMap($textarea) {
export default class Shortcuts {
constructor() {
this.onToggleHelp = this.onToggleHelp.bind(this);
- this.enabledHelp = [];
+ this.helpModalElement = null;
+ this.helpModalVueInstance = null;
Mousetrap.bind('?', this.onToggleHelp);
Mousetrap.bind('s', Shortcuts.focusSearch);
Mousetrap.bind('/', Shortcuts.focusSearch);
Mousetrap.bind('f', this.focusFilter.bind(this));
Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar);
+ Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary);
const findFileURL = document.body.dataset.findFile;
@@ -106,11 +98,33 @@ export default class Shortcuts {
}
onToggleHelp(e) {
- if (e.preventDefault) {
+ if (e?.preventDefault) {
e.preventDefault();
}
- Shortcuts.toggleHelp(this.enabledHelp);
+ if (this.helpModalElement && this.helpModalVueInstance) {
+ this.helpModalVueInstance.$destroy();
+ this.helpModalElement.remove();
+ this.helpModalElement = null;
+ this.helpModalVueInstance = null;
+ } else {
+ this.helpModalElement = document.createElement('div');
+ document.body.append(this.helpModalElement);
+
+ this.helpModalVueInstance = new Vue({
+ el: this.helpModalElement,
+ components: {
+ ShortcutsHelp: () => import('./shortcuts_help.vue'),
+ },
+ render: (createElement) => {
+ return createElement('shortcuts-help', {
+ on: {
+ hidden: this.onToggleHelp,
+ },
+ });
+ },
+ });
+ }
}
static onTogglePerfBar(e) {
@@ -124,6 +138,14 @@ export default class Shortcuts {
refreshCurrentPage();
}
+ static onToggleCanary(e) {
+ e.preventDefault();
+ const canaryCookieName = 'gitlab_canary';
+ const currentValue = parseBoolean(Cookies.get(canaryCookieName));
+ Cookies.set(canaryCookieName, (!currentValue).toString(), { expires: 365, path: '/' });
+ refreshCurrentPage();
+ }
+
static toggleMarkdownPreview(e) {
// Check if short-cut was triggered while in Write Mode
const $target = $(e.target);
@@ -135,34 +157,6 @@ export default class Shortcuts {
$(document).triggerHandler('markdown-preview:toggle', [e]);
}
- static toggleHelp(location) {
- const $modal = $('#modal-shortcuts');
-
- if ($modal.length) {
- $modal.modal('toggle');
- return null;
- }
-
- return axios
- .get(gon.shortcuts_path, {
- responseType: 'text',
- })
- .then(({ data }) => {
- $.globalEval(data, { nonce: getCspNonceValue() });
-
- if (location && location.length > 0) {
- const results = [];
- for (let i = 0, len = location.length; i < len; i += 1) {
- results.push($(location[i]).show());
- }
- return results;
- }
-
- return $('.js-more-help-button').remove();
- })
- .then(initToggleButton);
- }
-
focusFilter(e) {
if (!this.filterInput) {
this.filterInput = $('input[type=search]', '.nav-controls');
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
new file mode 100644
index 00000000000..1277dd0ed37
--- /dev/null
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue
@@ -0,0 +1,525 @@
+<script>
+/* eslint-disable @gitlab/vue-require-i18n-strings */
+import { GlIcon, GlModal } from '@gitlab/ui';
+import ShortcutsToggle from './shortcuts_toggle.vue';
+
+export default {
+ components: {
+ GlIcon,
+ GlModal,
+ ShortcutsToggle,
+ },
+ computed: {
+ ctrlCharacter() {
+ return window.gl.client.isMac ? '⌘' : 'ctrl';
+ },
+ onDotCom() {
+ return window.gon.dot_com;
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ modal-id="keyboard-shortcut-modal"
+ size="lg"
+ data-testid="modal-shortcuts"
+ :visible="true"
+ :hide-footer="true"
+ @hidden="$emit('hidden')"
+ >
+ <template #modal-title>
+ <shortcuts-toggle />
+ </template>
+ <div class="row">
+ <div class="col-lg-4">
+ <table class="shortcut-mappings text-2">
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Global Shortcuts') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>?</kbd>
+ </td>
+ <td>{{ __('Toggle this dialog') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift p</kbd>
+ </td>
+ <td>{{ __('Go to your projects') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift g</kbd>
+ </td>
+ <td>{{ __('Go to your groups') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift a</kbd>
+ </td>
+ <td>{{ __('Go to the activity feed') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift l</kbd>
+ </td>
+ <td>{{ __('Go to the milestone list') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift s</kbd>
+ </td>
+ <td>{{ __('Go to your snippets') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>s</kbd>
+ /
+ <kbd>/</kbd>
+ </td>
+ <td>{{ __('Start search') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift i</kbd>
+ </td>
+ <td>{{ __('Go to your issues') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift m</kbd>
+ </td>
+ <td>{{ __('Go to your merge requests') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>shift t</kbd>
+ </td>
+ <td>{{ __('Go to your To-Do list') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>p</kbd>
+ <kbd>b</kbd>
+ </td>
+ <td>{{ __('Toggle the Performance Bar') }}</td>
+ </tr>
+ <tr v-if="onDotCom">
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>x</kbd>
+ </td>
+ <td>{{ __('Toggle GitLab Next') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Editing') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>{{ ctrlCharacter }} shift p</kbd>
+ </td>
+ <td>{{ __('Toggle Markdown preview') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-up" />
+ </kbd>
+ </td>
+ <td>
+ {{ __('Edit your most recent comment in a thread (from an empty textarea)') }}
+ </td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Wiki') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>e</kbd>
+ </td>
+ <td>{{ __('Edit wiki page') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Repository Graph') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-left" />
+ </kbd>
+ /
+ <kbd>h</kbd>
+ </td>
+ <td>{{ __('Scroll left') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-right" />
+ </kbd>
+ /
+ <kbd>l</kbd>
+ </td>
+ <td>{{ __('Scroll right') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-up" />
+ </kbd>
+ /
+ <kbd>k</kbd>
+ </td>
+ <td>{{ __('Scroll up') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-down" />
+ </kbd>
+ /
+ <kbd>j</kbd>
+ </td>
+ <td>{{ __('Scroll down') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ shift
+ <gl-icon name="arrow-up" />
+ / k
+ </kbd>
+ </td>
+ <td>{{ __('Scroll to top') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ shift
+ <gl-icon name="arrow-down" />
+ / j
+ </kbd>
+ </td>
+ <td>{{ __('Scroll to bottom') }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class="col-lg-4">
+ <table class="shortcut-mappings text-2">
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Project') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>p</kbd>
+ </td>
+ <td>{{ __("Go to the project's overview page") }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>v</kbd>
+ </td>
+ <td>{{ __("Go to the project's activity feed") }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>r</kbd>
+ </td>
+ <td>{{ __('Go to releases') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>f</kbd>
+ </td>
+ <td>{{ __('Go to files') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>t</kbd>
+ </td>
+ <td>{{ __('Go to find file') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>c</kbd>
+ </td>
+ <td>{{ __('Go to commits') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>n</kbd>
+ </td>
+ <td>{{ __('Go to repository graph') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>d</kbd>
+ </td>
+ <td>{{ __('Go to repository charts') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>i</kbd>
+ </td>
+ <td>{{ __('Go to issues') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>i</kbd>
+ </td>
+ <td>{{ __('New issue') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>b</kbd>
+ </td>
+ <td>{{ __('Go to issue boards') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>m</kbd>
+ </td>
+ <td>{{ __('Go to merge requests') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>j</kbd>
+ </td>
+ <td>{{ __('Go to jobs') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>l</kbd>
+ </td>
+ <td>{{ __('Go to metrics') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>e</kbd>
+ </td>
+ <td>{{ __('Go to environments') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>k</kbd>
+ </td>
+ <td>{{ __('Go to kubernetes') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>s</kbd>
+ </td>
+ <td>{{ __('Go to snippets') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>g</kbd>
+ <kbd>w</kbd>
+ </td>
+ <td>{{ __('Go to wiki') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Project Files') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-up" />
+ </kbd>
+ </td>
+ <td>{{ __('Move selection up') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>
+ <gl-icon name="arrow-down" />
+ </kbd>
+ </td>
+ <td>{{ __('Move selection down') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>enter</kbd>
+ </td>
+ <td>{{ __('Open Selection') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>esc</kbd>
+ </td>
+ <td>{{ __('Go back (while searching for files)') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>y</kbd>
+ </td>
+ <td>{{ __('Go to file permalink (while viewing a file)') }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class="col-lg-4">
+ <table class="shortcut-mappings text-2">
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Epics, Issues, and Merge Requests') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>r</kbd>
+ </td>
+ <td>{{ __('Comment/Reply (quoting selected text)') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>e</kbd>
+ </td>
+ <td>{{ __('Edit description') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>l</kbd>
+ </td>
+ <td>{{ __('Change label') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Issues and Merge Requests') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>a</kbd>
+ </td>
+ <td>{{ __('Change assignee') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>m</kbd>
+ </td>
+ <td>{{ __('Change milestone') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Merge Requests') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>]</kbd>
+ /
+ <kbd>j</kbd>
+ </td>
+ <td>{{ __('Next file in diff') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>[</kbd>
+ /
+ <kbd>k</kbd>
+ </td>
+ <td>{{ __('Previous file in diff') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>{{ ctrlCharacter }} p</kbd>
+ </td>
+ <td>{{ __('Go to file') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>n</kbd>
+ </td>
+ <td>{{ __('Next unresolved discussion') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>p</kbd>
+ </td>
+ <td>{{ __('Previous unresolved discussion') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>b</kbd>
+ </td>
+ <td>{{ __('Copy source branch name') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Merge Request Commits') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>c</kbd>
+ </td>
+ <td>{{ __('Next commit') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>x</kbd>
+ </td>
+ <td>{{ __('Previous commit') }}</td>
+ </tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <th></th>
+ <th>{{ __('Web IDE') }}</th>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>{{ ctrlCharacter }} p</kbd>
+ </td>
+ <td>{{ __('Go to file') }}</td>
+ </tr>
+ <tr>
+ <td class="shortcut">
+ <kbd>{{ ctrlCharacter }} enter</kbd>
+ </td>
+ <td>{{ __('Commit (when editing commit message)') }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index 5e8ddeb6af7..476745beb19 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import Mousetrap from 'mousetrap';
-import Sidebar from '../../right_sidebar';
-import Shortcuts from './shortcuts';
-import { CopyAsGFM } from '../markdown/copy_as_gfm';
+import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard';
import { getSelectedFragment } from '~/lib/utils/common_utils';
import { isElementVisible } from '~/lib/utils/dom_utils';
-import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard';
+import Sidebar from '../../right_sidebar';
+import { CopyAsGFM } from '../markdown/copy_as_gfm';
+import Shortcuts from './shortcuts';
export default class ShortcutsIssuable extends Shortcuts {
constructor() {
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js
index 8b7e6a56d25..c609936a02a 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js
@@ -1,6 +1,6 @@
import Mousetrap from 'mousetrap';
-import ShortcutsNavigation from './shortcuts_navigation';
import findAndFollowLink from '../../lib/utils/navigation_utility';
+import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsWiki extends ShortcutsNavigation {
constructor() {
diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js
index 94397d70384..fd064e7ca8f 100644
--- a/app/assets/javascripts/blob/3d_viewer/index.js
+++ b/app/assets/javascripts/blob/3d_viewer/index.js
@@ -1,6 +1,6 @@
-import * as THREE from 'three/build/three.module';
-import STLLoaderClass from 'three-stl-loader';
import OrbitControlsClass from 'three-orbit-controls';
+import STLLoaderClass from 'three-stl-loader';
+import * as THREE from 'three/build/three.module';
import MeshObject from './mesh_object';
const STLLoader = STLLoaderClass(THREE);
diff --git a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
index ebe2c2b3bb8..313bec7e01a 100644
--- a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
+++ b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
@@ -1,5 +1,5 @@
-import sqljs from 'sql.js';
import { template as _template } from 'lodash';
+import sqljs from 'sql.js';
import axios from '~/lib/utils/axios_utils';
import { successCodes } from '~/lib/utils/http_status';
diff --git a/app/assets/javascripts/blob/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq_viewer.js
index fc86f630c4e..c9152db509a 100644
--- a/app/assets/javascripts/blob/balsamiq_viewer.js
+++ b/app/assets/javascripts/blob/balsamiq_viewer.js
@@ -1,6 +1,6 @@
+import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '../flash';
import BalsamiqViewer from './balsamiq/balsamiq_viewer';
-import { __ } from '~/locale';
function onError() {
const flash = new Flash(__('Balsamiq file could not be loaded.'));
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js
index 19bad64155d..e72c5c90986 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js
@@ -1,11 +1,11 @@
/* eslint-disable func-names */
-import $ from 'jquery';
import Dropzone from 'dropzone';
-import { visitUrl } from '../lib/utils/url_utility';
+import $ from 'jquery';
+import { sprintf, __ } from '~/locale';
import { HIDDEN_CLASS } from '../lib/utils/constants';
import csrf from '../lib/utils/csrf';
-import { sprintf, __ } from '~/locale';
+import { visitUrl } from '../lib/utils/url_utility';
Dropzone.autoDiscover = false;
diff --git a/app/assets/javascripts/blob/components/blob_header.vue b/app/assets/javascripts/blob/components/blob_header.vue
index a4a43b7a94e..9c023235428 100644
--- a/app/assets/javascripts/blob/components/blob_header.vue
+++ b/app/assets/javascripts/blob/components/blob_header.vue
@@ -1,7 +1,7 @@
<script>
-import ViewerSwitcher from './blob_header_viewer_switcher.vue';
import DefaultActions from './blob_header_default_actions.vue';
import BlobFilepath from './blob_header_filepath.vue';
+import ViewerSwitcher from './blob_header_viewer_switcher.vue';
import { SIMPLE_BLOB_VIEWER } from './constants';
export default {
@@ -71,7 +71,7 @@ export default {
</template>
</blob-filepath>
- <div class="gl-display-none gl-display-sm-flex">
+ <div class="gl-display-none gl-sm-display-flex">
<viewer-switcher v-if="showViewerSwitcher" v-model="viewer" />
<slot name="actions"></slot>
diff --git a/app/assets/javascripts/blob/components/blob_header_filepath.vue b/app/assets/javascripts/blob/components/blob_header_filepath.vue
index eb8068a8ad7..99fe3938046 100644
--- a/app/assets/javascripts/blob/components/blob_header_filepath.vue
+++ b/app/assets/javascripts/blob/components/blob_header_filepath.vue
@@ -1,7 +1,7 @@
<script>
-import FileIcon from '~/vue_shared/components/file_icon.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
export default {
components: {
diff --git a/app/assets/javascripts/blob/components/constants.js b/app/assets/javascripts/blob/components/constants.js
index 0137bd38d28..a129c537fa5 100644
--- a/app/assets/javascripts/blob/components/constants.js
+++ b/app/assets/javascripts/blob/components/constants.js
@@ -1,5 +1,5 @@
-import { __, sprintf } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
+import { __, sprintf } from '~/locale';
export const BTN_COPY_CONTENTS_TITLE = __('Copy file contents');
export const BTN_RAW_TITLE = __('Open raw');
diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js
index c35f9934004..77910850908 100644
--- a/app/assets/javascripts/blob/file_template_mediator.js
+++ b/app/assets/javascripts/blob/file_template_mediator.js
@@ -1,19 +1,19 @@
import $ from 'jquery';
import Api from '~/api';
-import toast from '~/vue_shared/plugins/global_toast';
-import { __ } from '~/locale';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
+import { __ } from '~/locale';
+import toast from '~/vue_shared/plugins/global_toast';
import { deprecatedCreateFlash as Flash } from '../flash';
-import FileTemplateTypeSelector from './template_selectors/type_selector';
-import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
import BlobCiSyntaxYamlSelector from './template_selectors/ci_syntax_yaml_selector';
+import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
import DockerfileSelector from './template_selectors/dockerfile_selector';
import GitignoreSelector from './template_selectors/gitignore_selector';
import LicenseSelector from './template_selectors/license_selector';
import MetricsDashboardSelector from './template_selectors/metrics_dashboard_selector';
+import FileTemplateTypeSelector from './template_selectors/type_selector';
export default class FileTemplateMediator {
constructor({ editor, currentAction, projectId }) {
diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js
index 2532aeea989..a5c8050b772 100644
--- a/app/assets/javascripts/blob/file_template_selector.js
+++ b/app/assets/javascripts/blob/file_template_selector.js
@@ -66,6 +66,8 @@ export default class FileTemplateSelector {
reportSelectionName(options) {
const opts = options;
opts.query = options.selectedObj.name;
+ opts.data = options.selectedObj;
+ opts.data.source_template_project_id = options.selectedObj.project_id;
this.reportSelection(opts);
}
diff --git a/app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js b/app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js
index 9370e170571..c30ff4f1290 100644
--- a/app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/ci_syntax_yaml_selector.js
@@ -1,5 +1,5 @@
-import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import FileTemplateSelector from '../file_template_selector';
export default class BlobCiSyntaxYamlSelector extends FileTemplateSelector {
constructor({ mediator }) {
diff --git a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
index 3879a6c5742..0cdfd153675 100644
--- a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
@@ -1,5 +1,5 @@
-import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import FileTemplateSelector from '../file_template_selector';
export default class BlobCiYamlSelector extends FileTemplateSelector {
constructor({ mediator }) {
diff --git a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
index 5d976c5acdb..b48b3d6bec3 100644
--- a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
@@ -1,6 +1,6 @@
-import FileTemplateSelector from '../file_template_selector';
-import { __ } from '~/locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from '~/locale';
+import FileTemplateSelector from '../file_template_selector';
export default class DockerfileSelector extends FileTemplateSelector {
constructor({ mediator }) {
diff --git a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
index 1bb1cbb74de..50a11692e98 100644
--- a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
@@ -1,5 +1,5 @@
-import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import FileTemplateSelector from '../file_template_selector';
export default class BlobGitignoreSelector extends FileTemplateSelector {
constructor({ mediator }) {
diff --git a/app/assets/javascripts/blob/template_selectors/license_selector.js b/app/assets/javascripts/blob/template_selectors/license_selector.js
index affa20997e9..e7fabf18ea1 100644
--- a/app/assets/javascripts/blob/template_selectors/license_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/license_selector.js
@@ -1,5 +1,5 @@
-import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import FileTemplateSelector from '../file_template_selector';
export default class BlobLicenseSelector extends FileTemplateSelector {
constructor({ mediator }) {
@@ -30,6 +30,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
const data = {
project: this.$dropdown.data('project'),
fullname: this.$dropdown.data('fullname'),
+ source_template_project_id: query.project_id,
};
this.reportSelection({
diff --git a/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js b/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
index 42adab05ce3..8b10b02ae1d 100644
--- a/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
@@ -1,5 +1,5 @@
-import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import FileTemplateSelector from '../file_template_selector';
export default class MetricsDashboardSelector extends FileTemplateSelector {
constructor({ mediator }) {
diff --git a/app/assets/javascripts/blob/template_selectors/type_selector.js b/app/assets/javascripts/blob/template_selectors/type_selector.js
index f74f7535d99..65e7ff0594c 100644
--- a/app/assets/javascripts/blob/template_selectors/type_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/type_selector.js
@@ -1,5 +1,5 @@
-import FileTemplateSelector from '../file_template_selector';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import FileTemplateSelector from '../file_template_selector';
export default class FileTemplateTypeSelector extends FileTemplateSelector {
constructor({ mediator, dropdownData }) {
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 4e6ec20ec64..b4cd0d5d875 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
+import { __ } from '~/locale';
+import { fixTitle } from '~/tooltips';
import { deprecatedCreateFlash as Flash } from '../../flash';
-import { handleLocationHash } from '../../lib/utils/common_utils';
import axios from '../../lib/utils/axios_utils';
+import { handleLocationHash } from '../../lib/utils/common_utils';
import eventHub from '../../notes/event_hub';
-import { __ } from '~/locale';
-import { fixTitle } from '~/tooltips';
const loadRichBlobViewer = (type) => {
switch (type) {
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index 7c2217a59e9..173c82ef9b0 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -1,12 +1,12 @@
/* eslint-disable no-new */
import $ from 'jquery';
-import NewCommitForm from '../new_commit_form';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import BlobFileDropzone from '../blob/blob_file_dropzone';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
+import BlobFileDropzone from '../blob/blob_file_dropzone';
+import NewCommitForm from '../new_commit_form';
const initPopovers = () => {
const suggestEl = document.querySelector('.js-suggest-gitlab-ci-yml');
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index c7f66a357f3..7c8f6646c0d 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -1,12 +1,12 @@
import $ from 'jquery';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { BLOB_EDITOR_ERROR, BLOB_PREVIEW_ERROR } from './constants';
-import TemplateSelectorMediator from '../blob/file_template_mediator';
-import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
import EditorLite from '~/editor/editor_lite';
import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
import { insertFinalNewline } from '~/lib/utils/text_utility';
+import TemplateSelectorMediator from '../blob/file_template_mediator';
+import { BLOB_EDITOR_ERROR, BLOB_PREVIEW_ERROR } from './constants';
export default class EditBlob {
// The options object has:
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index 965d3571f42..13ad820477f 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,6 +1,6 @@
import { sortBy } from 'lodash';
-import { ListType } from './constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { ListType, NOT_FILTER } from './constants';
export function getMilestone() {
return null;
@@ -144,6 +144,17 @@ export function isListDraggable(list) {
return list.listType !== ListType.backlog && list.listType !== ListType.closed;
}
+export function transformNotFilters(filters) {
+ return Object.keys(filters)
+ .filter((key) => key.startsWith(NOT_FILTER))
+ .reduce((obj, key) => {
+ return {
+ ...obj,
+ [key.substring(4, key.length - 1)]: filters[key],
+ };
+ }, {});
+}
+
// EE-specific feature. Find the implementation in the `ee/`-folder
export function transformBoardConfig() {
return '';
@@ -157,4 +168,5 @@ export default {
fullLabelId,
fullIterationId,
isListDraggable,
+ transformNotFilters,
};
diff --git a/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue b/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
new file mode 100644
index 00000000000..85fca589279
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_add_new_column_trigger.vue
@@ -0,0 +1,21 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { mapActions } from 'vuex';
+
+export default {
+ components: {
+ GlButton,
+ },
+ methods: {
+ ...mapActions(['setAddColumnFormVisibility']),
+ },
+};
+</script>
+
+<template>
+ <span class="gl-ml-3 gl-display-flex gl-align-items-center">
+ <gl-button variant="confirm" @click="setAddColumnFormVisibility(true)"
+ >{{ __('Create list') }}
+ </gl-button>
+ </span>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_assignee_dropdown.vue b/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
deleted file mode 100644
index 5d381f9a570..00000000000
--- a/app/assets/javascripts/boards/components/board_assignee_dropdown.vue
+++ /dev/null
@@ -1,196 +0,0 @@
-<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
-import { cloneDeep } from 'lodash';
-import {
- GlDropdownItem,
- GlDropdownDivider,
- GlAvatarLabeled,
- GlAvatarLink,
- GlSearchBoxByType,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { __, n__ } from '~/locale';
-import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
-import getIssueParticipants from '~/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql';
-import searchUsers from '~/boards/graphql/users_search.query.graphql';
-
-export default {
- noSearchDelay: 0,
- searchDelay: 250,
- i18n: {
- unassigned: __('Unassigned'),
- assignee: __('Assignee'),
- assignees: __('Assignees'),
- assignTo: __('Assign to'),
- },
- components: {
- BoardEditableItem,
- IssuableAssignees,
- MultiSelectDropdown,
- GlDropdownItem,
- GlDropdownDivider,
- GlAvatarLabeled,
- GlAvatarLink,
- GlSearchBoxByType,
- GlLoadingIcon,
- },
- data() {
- return {
- search: '',
- participants: [],
- selected: [],
- };
- },
- apollo: {
- participants: {
- query() {
- return this.isSearchEmpty ? getIssueParticipants : searchUsers;
- },
- variables() {
- if (this.isSearchEmpty) {
- return {
- id: `gid://gitlab/Issue/${this.activeIssue.iid}`,
- };
- }
-
- return {
- search: this.search,
- };
- },
- update(data) {
- if (this.isSearchEmpty) {
- return data.issue?.participants?.nodes || [];
- }
-
- return data.users?.nodes || [];
- },
- debounce() {
- const { noSearchDelay, searchDelay } = this.$options;
-
- return this.isSearchEmpty ? noSearchDelay : searchDelay;
- },
- },
- },
- computed: {
- ...mapGetters(['activeIssue']),
- ...mapState(['isSettingAssignees']),
- assigneeText() {
- return n__('Assignee', '%d Assignees', this.selected.length);
- },
- unSelectedFiltered() {
- return this.participants.filter(({ username }) => {
- return !this.selectedUserNames.includes(username);
- });
- },
- selectedIsEmpty() {
- return this.selected.length === 0;
- },
- selectedUserNames() {
- return this.selected.map(({ username }) => username);
- },
- isSearchEmpty() {
- return this.search === '';
- },
- currentUser() {
- return gon?.current_username;
- },
- },
- created() {
- this.selected = cloneDeep(this.activeIssue.assignees);
- },
- methods: {
- ...mapActions(['setAssignees']),
- async assignSelf() {
- const [currentUserObject] = await this.setAssignees(this.currentUser);
-
- this.selectAssignee(currentUserObject);
- },
- clearSelected() {
- this.selected = [];
- },
- selectAssignee(name) {
- if (name === undefined) {
- this.clearSelected();
- return;
- }
-
- this.selected = this.selected.concat(name);
- },
- unselect(name) {
- this.selected = this.selected.filter((user) => user.username !== name);
- },
- saveAssignees() {
- this.setAssignees(this.selectedUserNames);
- },
- isChecked(id) {
- return this.selectedUserNames.includes(id);
- },
- },
-};
-</script>
-
-<template>
- <board-editable-item :loading="isSettingAssignees" :title="assigneeText" @close="saveAssignees">
- <template #collapsed>
- <issuable-assignees :users="activeIssue.assignees" @assign-self="assignSelf" />
- </template>
-
- <template #default>
- <multi-select-dropdown
- class="w-100"
- :text="$options.i18n.assignees"
- :header-text="$options.i18n.assignTo"
- >
- <template #search>
- <gl-search-box-by-type v-model.trim="search" />
- </template>
- <template #items>
- <gl-loading-icon v-if="$apollo.queries.participants.loading" size="lg" />
- <template v-else>
- <gl-dropdown-item
- :is-checked="selectedIsEmpty"
- data-testid="unassign"
- class="mt-2"
- @click="selectAssignee()"
- >{{ $options.i18n.unassigned }}</gl-dropdown-item
- >
- <gl-dropdown-divider data-testid="unassign-divider" />
- <gl-dropdown-item
- v-for="item in selected"
- :key="item.id"
- :is-checked="isChecked(item.username)"
- @click="unselect(item.username)"
- >
- <gl-avatar-link>
- <gl-avatar-labeled
- :size="32"
- :label="item.name"
- :sub-label="item.username"
- :src="item.avatarUrl || item.avatar"
- />
- </gl-avatar-link>
- </gl-dropdown-item>
- <gl-dropdown-divider v-if="!selectedIsEmpty" data-testid="selected-user-divider" />
- <gl-dropdown-item
- v-for="unselectedUser in unSelectedFiltered"
- :key="unselectedUser.id"
- :data-testid="`item_${unselectedUser.name}`"
- @click="selectAssignee(unselectedUser)"
- >
- <gl-avatar-link>
- <gl-avatar-labeled
- :size="32"
- :label="unselectedUser.name"
- :sub-label="unselectedUser.username"
- :src="unselectedUser.avatarUrl || unselectedUser.avatar"
- />
- </gl-avatar-link>
- </gl-dropdown-item>
- </template>
- </template>
- </multi-select-dropdown>
- </template>
- </board-editable-item>
-</template>
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 31050eef83d..e6009343626 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -1,13 +1,14 @@
<script>
-import BoardCardLayout from './board_card_layout.vue';
-import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
+import eventHub from '../eventhub';
import boardsStore from '../stores/boards_store';
+import BoardCardLayout from './board_card_layout.vue';
+import BoardCardLayoutDeprecated from './board_card_layout_deprecated.vue';
export default {
name: 'BoardsIssueCard',
components: {
- BoardCardLayout,
+ BoardCardLayout: gon.features?.graphqlBoardLists ? BoardCardLayout : BoardCardLayoutDeprecated,
},
props: {
list: {
diff --git a/app/assets/javascripts/boards/components/board_card_layout.vue b/app/assets/javascripts/boards/components/board_card_layout.vue
index 0a2301394c1..5e3c3702519 100644
--- a/app/assets/javascripts/boards/components/board_card_layout.vue
+++ b/app/assets/javascripts/boards/components/board_card_layout.vue
@@ -1,17 +1,13 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
-import IssueCardInner from './issue_card_inner.vue';
-import IssueCardInnerDeprecated from './issue_card_inner_deprecated.vue';
-import boardsStore from '../stores/boards_store';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { ISSUABLE } from '~/boards/constants';
+import IssueCardInner from './issue_card_inner.vue';
export default {
name: 'BoardCardLayout',
components: {
- IssueCardInner: gon.features?.graphqlBoardLists ? IssueCardInner : IssueCardInnerDeprecated,
+ IssueCardInner,
},
- mixins: [glFeatureFlagMixin()],
props: {
list: {
type: Object,
@@ -42,17 +38,17 @@ export default {
data() {
return {
showDetail: false,
- multiSelect: boardsStore.multiSelect,
};
},
computed: {
+ ...mapState(['selectedBoardItems']),
...mapGetters(['isSwimlanesOn']),
multiSelectVisible() {
- return this.multiSelect.list.findIndex((issue) => issue.id === this.issue.id) > -1;
+ return this.selectedBoardItems.findIndex((boardItem) => boardItem.id === this.issue.id) > -1;
},
},
methods: {
- ...mapActions(['setActiveId']),
+ ...mapActions(['setActiveId', 'toggleBoardItemMultiSelection']),
mouseDown() {
this.showDetail = true;
},
@@ -63,16 +59,16 @@ export default {
// Don't do anything if this happened on a no trigger element
if (e.target.classList.contains('js-no-trigger')) return;
- if (this.glFeatures.graphqlBoardLists || this.isSwimlanesOn) {
+ const isMultiSelect = e.ctrlKey || e.metaKey;
+
+ if (!isMultiSelect) {
this.setActiveId({ id: this.issue.id, sidebarType: ISSUABLE });
- return;
+ } else {
+ this.toggleBoardItemMultiSelection(this.issue);
}
- const isMultiSelect = e.ctrlKey || e.metaKey;
-
if (this.showDetail || isMultiSelect) {
this.showDetail = false;
- this.$emit('show', { event: e, isMultiSelect });
}
},
},
diff --git a/app/assets/javascripts/boards/components/board_card_layout_deprecated.vue b/app/assets/javascripts/boards/components/board_card_layout_deprecated.vue
new file mode 100644
index 00000000000..f9a726134a3
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_card_layout_deprecated.vue
@@ -0,0 +1,102 @@
+<script>
+import { mapActions, mapGetters } from 'vuex';
+import { ISSUABLE } from '~/boards/constants';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import boardsStore from '../stores/boards_store';
+import IssueCardInner from './issue_card_inner.vue';
+import IssueCardInnerDeprecated from './issue_card_inner_deprecated.vue';
+
+export default {
+ name: 'BoardCardLayout',
+ components: {
+ IssueCardInner: gon.features?.graphqlBoardLists ? IssueCardInner : IssueCardInnerDeprecated,
+ },
+ mixins: [glFeatureFlagMixin()],
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ issue: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ index: {
+ type: Number,
+ default: 0,
+ required: false,
+ },
+ isActive: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ showDetail: false,
+ multiSelect: boardsStore.multiSelect,
+ };
+ },
+ computed: {
+ ...mapGetters(['isSwimlanesOn']),
+ multiSelectVisible() {
+ return this.multiSelect.list.findIndex((issue) => issue.id === this.issue.id) > -1;
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveId']),
+ mouseDown() {
+ this.showDetail = true;
+ },
+ mouseMove() {
+ this.showDetail = false;
+ },
+ showIssue(e) {
+ // Don't do anything if this happened on a no trigger element
+ if (e.target.classList.contains('js-no-trigger')) return;
+
+ if (this.glFeatures.graphqlBoardLists || this.isSwimlanesOn) {
+ this.setActiveId({ id: this.issue.id, sidebarType: ISSUABLE });
+ return;
+ }
+
+ const isMultiSelect = e.ctrlKey || e.metaKey;
+
+ if (this.showDetail || isMultiSelect) {
+ this.showDetail = false;
+ this.$emit('show', { event: e, isMultiSelect });
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <li
+ :class="{
+ 'multi-select': multiSelectVisible,
+ 'user-can-drag': !disabled && issue.id,
+ 'is-disabled': disabled || !issue.id,
+ 'is-active': isActive,
+ }"
+ :index="index"
+ :data-issue-id="issue.id"
+ :data-issue-iid="issue.iid"
+ :data-issue-path="issue.referencePath"
+ data-testid="board_card"
+ class="board-card gl-p-5 gl-rounded-base"
+ @mousedown="mouseDown"
+ @mousemove="mouseMove"
+ @mouseup="showIssue($event)"
+ >
+ <issue-card-inner :list="list" :issue="issue" :update-filters="true" />
+ </li>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index 9f0eef844f6..41b9ee795eb 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -1,8 +1,8 @@
<script>
import { mapGetters, mapActions, mapState } from 'vuex';
import BoardListHeader from 'ee_else_ce/boards/components/board_list_header.vue';
-import BoardList from './board_list.vue';
import { isListDraggable } from '../boards_util';
+import BoardList from './board_list.vue';
export default {
components: {
@@ -31,8 +31,11 @@ export default {
},
},
computed: {
- ...mapState(['filterParams']),
+ ...mapState(['filterParams', 'highlightedLists']),
...mapGetters(['getIssuesByList']),
+ highlighted() {
+ return this.highlightedLists.includes(this.list.id);
+ },
listIssues() {
return this.getIssuesByList(this.list.id);
},
@@ -48,6 +51,16 @@ export default {
deep: true,
immediate: true,
},
+ highlighted: {
+ handler(highlighted) {
+ if (highlighted) {
+ this.$nextTick(() => {
+ this.$el.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ });
+ }
+ },
+ immediate: true,
+ },
},
methods: {
...mapActions(['fetchIssuesForList']),
@@ -68,6 +81,7 @@ export default {
>
<div
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
+ :class="{ 'board-column-highlighted': highlighted }"
>
<board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
<board-list
diff --git a/app/assets/javascripts/boards/components/board_column_deprecated.vue b/app/assets/javascripts/boards/components/board_column_deprecated.vue
index 35688efceb4..3dc77654e28 100644
--- a/app/assets/javascripts/boards/components/board_column_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_column_deprecated.vue
@@ -2,9 +2,9 @@
// This component is being replaced in favor of './board_column.vue' for GraphQL boards
import Sortable from 'sortablejs';
import BoardListHeader from 'ee_else_ce/boards/components/board_list_header_deprecated.vue';
-import BoardList from './board_list_deprecated.vue';
-import boardsStore from '../stores/boards_store';
import { getBoardSortableDefaultOptions, sortableEnd } from '../mixins/sortable_default_options';
+import boardsStore from '../stores/boards_store';
+import BoardList from './board_list_deprecated.vue';
export default {
components: {
@@ -46,6 +46,7 @@ export default {
watch: {
filter: {
handler() {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.page = 1;
this.list.getIssues(true).catch(() => {
// TODO: handle request error
@@ -53,6 +54,16 @@ export default {
},
deep: true,
},
+ 'list.highlighted': {
+ handler(highlighted) {
+ if (highlighted) {
+ this.$nextTick(() => {
+ this.$el.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ });
+ }
+ },
+ immediate: true,
+ },
},
mounted() {
const instance = this;
@@ -97,6 +108,7 @@ export default {
>
<div
class="board-inner gl-display-flex gl-flex-direction-column gl-relative gl-h-full gl-rounded-base"
+ :class="{ 'board-column-highlighted': list.highlighted }"
>
<board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
<board-list ref="board-list" :disabled="disabled" :issues="listIssues" :list="list" />
diff --git a/app/assets/javascripts/boards/components/board_configuration_options.vue b/app/assets/javascripts/boards/components/board_configuration_options.vue
index b8ee930a8c9..4d79f2a4bc6 100644
--- a/app/assets/javascripts/boards/components/board_configuration_options.vue
+++ b/app/assets/javascripts/boards/components/board_configuration_options.vue
@@ -14,6 +14,10 @@ export default {
type: Boolean,
required: true,
},
+ readonly: {
+ type: Boolean,
+ required: true,
+ },
},
};
</script>
@@ -28,12 +32,14 @@ export default {
</p>
<gl-form-checkbox
:checked="!hideBacklogList"
+ :disabled="readonly"
data-testid="backlog-list-checkbox"
@change="$emit('update:hideBacklogList', !hideBacklogList)"
>{{ __('Show the Open list') }}
</gl-form-checkbox>
<gl-form-checkbox
:checked="!hideClosedList"
+ :disabled="readonly"
data-testid="closed-list-checkbox"
@change="$emit('update:hideClosedList', !hideClosedList)"
>{{ __('Show the Closed list') }}
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index 19254343208..9b10e7d7db5 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -1,13 +1,13 @@
<script>
+import { GlAlert } from '@gitlab/ui';
+import { sortBy } from 'lodash';
import Draggable from 'vuedraggable';
import { mapState, mapGetters, mapActions } from 'vuex';
-import { sortBy } from 'lodash';
-import { GlAlert } from '@gitlab/ui';
-import BoardColumnDeprecated from './board_column_deprecated.vue';
-import BoardColumn from './board_column.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import defaultSortableConfig from '~/sortable/sortable_config';
import { sortableEnd, sortableStart } from '~/boards/mixins/sortable_default_options';
+import defaultSortableConfig from '~/sortable/sortable_config';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import BoardColumn from './board_column.vue';
+import BoardColumnDeprecated from './board_column_deprecated.vue';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index c701ecd3040..f65f00bcccc 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -1,17 +1,17 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { getParameterByName } from '~/lib/utils/common_utils';
import { convertToGraphQLId } from '~/graphql_shared/utils';
-import boardsStore from '~/boards/stores/boards_store';
+import { getParameterByName } from '~/lib/utils/common_utils';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { __, s__ } from '~/locale';
import { fullLabelId, fullBoardId } from '../boards_util';
+import { formType } from '../constants';
-import BoardConfigurationOptions from './board_configuration_options.vue';
-import updateBoardMutation from '../graphql/board_update.mutation.graphql';
import createBoardMutation from '../graphql/board_create.mutation.graphql';
import destroyBoardMutation from '../graphql/board_destroy.mutation.graphql';
+import updateBoardMutation from '../graphql/board_update.mutation.graphql';
+import BoardConfigurationOptions from './board_configuration_options.vue';
const boardDefaults = {
id: false,
@@ -26,12 +26,6 @@ const boardDefaults = {
hide_closed_list: false,
};
-const formType = {
- new: 'new',
- delete: 'delete',
- edit: 'edit',
-};
-
export default {
i18n: {
[formType.new]: { title: s__('Board|Create new board'), btnText: s__('Board|Create board') },
@@ -100,11 +94,14 @@ export default {
type: Object,
required: true,
},
+ currentPage: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
board: { ...boardDefaults, ...this.currentBoard },
- currentPage: boardsStore.state.currentPage,
isLoading: false,
};
},
@@ -256,7 +253,7 @@ export default {
}
},
cancel() {
- boardsStore.showPage('');
+ this.$emit('cancel');
},
resetFormState() {
if (this.isNewForm) {
@@ -308,6 +305,7 @@ export default {
<board-configuration-options
:hide-backlog-list.sync="board.hide_backlog_list"
:hide-closed-list.sync="board.hide_closed_list"
+ :readonly="readonly"
/>
<board-scope
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index b6e4d0980fa..7495b1163be 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -1,13 +1,13 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import Draggable from 'vuedraggable';
import { mapActions, mapState } from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
-import defaultSortableConfig from '~/sortable/sortable_config';
import { sortableStart, sortableEnd } from '~/boards/mixins/sortable_default_options';
-import BoardNewIssue from './board_new_issue.vue';
-import BoardCard from './board_card.vue';
-import eventHub from '../eventhub';
import { sprintf, __ } from '~/locale';
+import defaultSortableConfig from '~/sortable/sortable_config';
+import eventHub from '../eventhub';
+import BoardCard from './board_card.vue';
+import BoardNewIssue from './board_new_issue.vue';
export default {
name: 'BoardList',
diff --git a/app/assets/javascripts/boards/components/board_list_deprecated.vue b/app/assets/javascripts/boards/components/board_list_deprecated.vue
index 24900346bda..9b4961d362d 100644
--- a/app/assets/javascripts/boards/components/board_list_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_list_deprecated.vue
@@ -1,17 +1,18 @@
<script>
-import { Sortable, MultiDrag } from 'sortablejs';
import { GlLoadingIcon } from '@gitlab/ui';
-import boardNewIssue from './board_new_issue_deprecated.vue';
-import boardCard from './board_card.vue';
-import eventHub from '../eventhub';
-import boardsStore from '../stores/boards_store';
-import { sprintf, __ } from '~/locale';
+import { Sortable, MultiDrag } from 'sortablejs';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { sprintf, __ } from '~/locale';
+import eventHub from '../eventhub';
import {
getBoardSortableDefaultOptions,
sortableStart,
sortableEnd,
} from '../mixins/sortable_default_options';
+import boardsStore from '../stores/boards_store';
+import boardCard from './board_card.vue';
+import boardNewIssue from './board_new_issue_deprecated.vue';
// This component is being replaced in favor of './board_list.vue' for GraphQL boards
@@ -63,6 +64,7 @@ export default {
watch: {
filters: {
handler() {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.loadingMore = false;
this.$refs.list.scrollTop = 0;
},
@@ -75,6 +77,7 @@ export default {
this.list.issuesSize > this.list.issues.length &&
this.list.isExpanded
) {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.page += 1;
this.list.getIssues(false).catch(() => {
// TODO: handle request error
@@ -165,7 +168,7 @@ export default {
boardsStore.startMoving(list, issue);
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
sortableStart();
},
@@ -283,6 +286,7 @@ export default {
* issue indexes are far apart, this logic should ever kick in.
*/
setTimeout(() => {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.issues.splice(i, 1);
}, 0);
});
@@ -386,10 +390,12 @@ export default {
loadNextPage() {
const getIssues = this.list.nextPage();
const loadingDone = () => {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.loadingMore = false;
};
if (getIssues) {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.loadingMore = true;
getIssues.then(loadingDone).catch(loadingDone);
}
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index 06f39eceb08..a933370427c 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapState } from 'vuex';
import {
GlButton,
GlButtonGroup,
@@ -9,14 +8,16 @@ import {
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
+import { isListDraggable } from '~/boards/boards_util';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { n__, s__, __ } from '~/locale';
-import AccessorUtilities from '../../lib/utils/accessor';
-import IssueCount from './issue_count.vue';
-import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
+import AccessorUtilities from '../../lib/utils/accessor';
import { inactiveId, LIST, ListType } from '../constants';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import { isListDraggable } from '~/boards/boards_util';
+import eventHub from '../eventhub';
+import IssueCount from './issue_count.vue';
export default {
i18n: {
@@ -85,16 +86,16 @@ export default {
return !this.disabled && this.listType !== ListType.closed;
},
showMilestoneListDetails() {
- return (
- this.listType === ListType.milestone &&
- this.list.milestone &&
- (!this.list.collapsed || !this.isSwimlanesHeader)
- );
+ return this.listType === ListType.milestone && this.list.milestone && this.showListDetails;
},
showAssigneeListDetails() {
- return (
- this.listType === ListType.assignee && (!this.list.collapsed || !this.isSwimlanesHeader)
- );
+ return this.listType === ListType.assignee && this.showListDetails;
+ },
+ showIterationListDetails() {
+ return this.listType === ListType.iteration && this.showListDetails;
+ },
+ showListDetails() {
+ return !this.list.collapsed || !this.isSwimlanesHeader;
},
issuesCount() {
return this.list.issuesCount;
@@ -147,6 +148,7 @@ export default {
eventHub.$emit(`toggle-issue-form-${this.list.id}`);
},
toggleExpanded() {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.collapsed = !this.list.collapsed;
if (!this.isLoggedIn) {
@@ -157,7 +159,7 @@ export default {
// When expanding/collapsing, the tooltip on the caret button sometimes stays open.
// Close all tooltips manually to prevent dangling tooltips.
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
},
addToLocalStorage() {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
@@ -216,6 +218,17 @@ export default {
<gl-icon name="timer" />
</span>
+ <span
+ v-if="showIterationListDetails"
+ aria-hidden="true"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': list.collapsed,
+ 'gl-mr-2': !list.collapsed,
+ }"
+ >
+ <gl-icon name="iteration" />
+ </span>
+
<a
v-if="showAssigneeListDetails"
:href="list.assignee.webUrl"
diff --git a/app/assets/javascripts/boards/components/board_list_header_deprecated.vue b/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
index 21147f1616c..ff043d3aa01 100644
--- a/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_list_header_deprecated.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapState } from 'vuex';
import {
GlButton,
GlButtonGroup,
@@ -9,14 +8,16 @@ import {
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { n__, s__ } from '~/locale';
-import AccessorUtilities from '../../lib/utils/accessor';
-import IssueCount from './issue_count.vue';
-import boardsStore from '../stores/boards_store';
-import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
+import AccessorUtilities from '../../lib/utils/accessor';
import { inactiveId, LIST, ListType } from '../constants';
-import { isScopedLabel } from '~/lib/utils/common_utils';
+import eventHub from '../eventhub';
+import boardsStore from '../stores/boards_store';
+import IssueCount from './issue_count.vue';
// This component is being replaced in favor of './board_list_header.vue' for GraphQL boards
@@ -77,14 +78,16 @@ export default {
return !this.disabled && this.listType !== ListType.closed;
},
showMilestoneListDetails() {
- return (
- this.list.type === 'milestone' &&
- this.list.milestone &&
- (this.list.isExpanded || !this.isSwimlanesHeader)
- );
+ return this.list.type === 'milestone' && this.list.milestone && this.showListDetails;
},
showAssigneeListDetails() {
- return this.list.type === 'assignee' && (this.list.isExpanded || !this.isSwimlanesHeader);
+ return this.list.type === 'assignee' && this.showListDetails;
+ },
+ showIterationListDetails() {
+ return this.listType === ListType.iteration && this.showListDetails;
+ },
+ showListDetails() {
+ return this.list.isExpanded || !this.isSwimlanesHeader;
},
issuesCount() {
return this.list.issuesSize;
@@ -131,6 +134,7 @@ export default {
eventHub.$emit(`toggle-issue-form-${this.list.id}`);
},
toggleExpanded() {
+ // eslint-disable-next-line vue/no-mutating-props
this.list.isExpanded = !this.list.isExpanded;
if (!this.isLoggedIn) {
@@ -141,7 +145,7 @@ export default {
// When expanding/collapsing, the tooltip on the caret button sometimes stays open.
// Close all tooltips manually to prevent dangling tooltips.
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
},
addToLocalStorage() {
if (AccessorUtilities.isLocalStorageAccessSafe()) {
@@ -201,6 +205,17 @@ export default {
<gl-icon name="timer" />
</span>
+ <span
+ v-if="showIterationListDetails"
+ aria-hidden="true"
+ :class="{
+ 'gl-mt-3 gl-rotate-90': !list.isExpanded,
+ 'gl-mr-2': list.isExpanded,
+ }"
+ >
+ <gl-icon name="iteration" />
+ </span>
+
<a
v-if="showAssigneeListDetails"
:href="list.assignee.path"
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 14d28643046..1df154688c8 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,11 +1,11 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { getMilestone } from 'ee_else_ce/boards/boards_util';
+import { __ } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../eventhub';
import ProjectSelect from './project_select.vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { __ } from '~/locale';
export default {
name: 'BoardNewIssue',
diff --git a/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue b/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
index 4fc58742783..eff87ff110e 100644
--- a/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue_deprecated.vue
@@ -2,10 +2,10 @@
import { GlButton } from '@gitlab/ui';
import { getMilestone } from 'ee_else_ce/boards/boards_util';
import ListIssue from 'ee_else_ce/boards/models/issue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../eventhub';
-import ProjectSelect from './project_select_deprecated.vue';
import boardsStore from '../stores/boards_store';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import ProjectSelect from './project_select_deprecated.vue';
// This component is being replaced in favor of './board_new_issue.vue' for GraphQL boards
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index f362fc60bd3..7cfedad0aed 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -1,21 +1,17 @@
<script>
import { GlButton, GlDrawer, GlLabel } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { __ } from '~/locale';
+import { LIST, ListType, ListTypeTitles } from '~/boards/constants';
import boardsStore from '~/boards/stores/boards_store';
-import eventHub from '~/sidebar/event_hub';
import { isScopedLabel } from '~/lib/utils/common_utils';
-import { LIST } from '~/boards/constants';
+import { __ } from '~/locale';
+import eventHub from '~/sidebar/event_hub';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
// NOTE: need to revisit how we handle headerHeight, because we have so many different header and footer options.
export default {
headerHeight: process.env.NODE_ENV === 'development' ? '75px' : '40px',
listSettingsText: __('List settings'),
- assignee: 'assignee',
- milestone: 'milestone',
- label: 'label',
- labelListText: __('Label'),
components: {
GlButton,
GlDrawer,
@@ -33,6 +29,11 @@ export default {
default: false,
},
},
+ data() {
+ return {
+ ListType,
+ };
+ },
computed: {
...mapGetters(['isSidebarOpen', 'shouldUseGraphQL']),
...mapState(['activeId', 'sidebarType', 'boardLists']),
@@ -56,7 +57,7 @@ export default {
return this.activeList.type || this.activeList.listType || null;
},
listTypeTitle() {
- return this.$options.labelListText;
+ return ListTypeTitles[ListType.label];
},
showSidebar() {
return this.sidebarType === LIST;
@@ -98,7 +99,7 @@ export default {
>
<template #header>{{ $options.listSettingsText }}</template>
<template v-if="isSidebarOpen">
- <div v-if="boardListType === $options.label">
+ <div v-if="boardListType === ListType.label">
<label class="js-list-label gl-display-block">{{ listTypeTitle }}</label>
<gl-label
:title="activeListLabel.title"
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index bf3dc5c608f..6d5a13be3ac 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -1,23 +1,26 @@
-/* eslint-disable no-new */
+// This is a true violation of @gitlab/no-runtime-template-compiler, as it
+// relies on app/views/shared/boards/components/_sidebar.html.haml for its
+// template.
+/* eslint-disable no-new, @gitlab/no-runtime-template-compiler */
+import { GlLabel } from '@gitlab/ui';
import $ from 'jquery';
import Vue from 'vue';
-import { GlLabel } from '@gitlab/ui';
-import { deprecatedCreateFlash as Flash } from '~/flash';
-import { sprintf, __ } from '~/locale';
-import Sidebar from '~/right_sidebar';
-import eventHub from '~/sidebar/event_hub';
import DueDateSelectors from '~/due_date_select';
import IssuableContext from '~/issuable_context';
import LabelsSelect from '~/labels_select';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import { sprintf, __ } from '~/locale';
+import MilestoneSelect from '~/milestone_select';
+import Sidebar from '~/right_sidebar';
import AssigneeTitle from '~/sidebar/components/assignees/assignee_title.vue';
import Assignees from '~/sidebar/components/assignees/assignees.vue';
+import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
-import MilestoneSelect from '~/milestone_select';
-import RemoveBtn from './sidebar/remove_issue.vue';
+import eventHub from '~/sidebar/event_hub';
import boardsStore from '../stores/boards_store';
-import { isScopedLabel } from '~/lib/utils/common_utils';
+import RemoveBtn from './sidebar/remove_issue.vue';
export default Vue.extend({
components: {
@@ -29,6 +32,7 @@ export default Vue.extend({
RemoveBtn,
Subscriptions,
TimeTracker,
+ SidebarAssigneesWidget,
},
props: {
currentUser: {
@@ -75,12 +79,6 @@ export default Vue.extend({
detail: {
handler() {
if (this.issue.id !== this.detail.issue.id) {
- $('.block.assignee')
- .find('input:not(.js-vue)[name="issue[assignee_ids][]"]')
- .each((i, el) => {
- $(el).remove();
- });
-
$('.js-issue-board-sidebar', this.$el).each((i, el) => {
$(el).data('deprecatedJQueryDropdown').clearMenu();
});
@@ -93,18 +91,9 @@ export default Vue.extend({
},
},
created() {
- // Get events from deprecatedJQueryDropdown
- eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
- eventHub.$on('sidebar.addAssignee', this.addAssignee);
- eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
- eventHub.$on('sidebar.saveAssignees', this.saveAssignees);
eventHub.$on('sidebar.closeAll', this.closeSidebar);
},
beforeDestroy() {
- eventHub.$off('sidebar.removeAssignee', this.removeAssignee);
- eventHub.$off('sidebar.addAssignee', this.addAssignee);
- eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
- eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
eventHub.$off('sidebar.closeAll', this.closeSidebar);
},
mounted() {
@@ -118,34 +107,8 @@ export default Vue.extend({
closeSidebar() {
this.detail.issue = {};
},
- assignSelf() {
- // Notify gl dropdown that we are now assigning to current user
- this.$refs.assigneeBlock.dispatchEvent(new Event('assignYourself'));
-
- this.addAssignee(this.currentUser);
- this.saveAssignees();
- },
- removeAssignee(a) {
- boardsStore.detail.issue.removeAssignee(a);
- },
- addAssignee(a) {
- boardsStore.detail.issue.addAssignee(a);
- },
- removeAllAssignees() {
- boardsStore.detail.issue.removeAllAssignees();
- },
- saveAssignees() {
- this.loadingAssignees = true;
-
- boardsStore.detail.issue
- .update()
- .then(() => {
- this.loadingAssignees = false;
- })
- .catch(() => {
- this.loadingAssignees = false;
- Flash(__('An error occurred while saving assignees'));
- });
+ setAssignees(data) {
+ boardsStore.detail.issue.setAssignees(data.issueSetAssignees.issue.assignees.nodes);
},
showScopedLabels(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label);
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index fcd1c3fdceb..2a064aaa885 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -1,5 +1,4 @@
<script>
-import { throttle } from 'lodash';
import {
GlLoadingIcon,
GlSearchBoxByType,
@@ -9,14 +8,16 @@ import {
GlDropdownItem,
GlModalDirective,
} from '@gitlab/ui';
+import { throttle } from 'lodash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import projectQuery from '../graphql/project_boards.query.graphql';
+import eventHub from '../eventhub';
import groupQuery from '../graphql/group_boards.query.graphql';
+import projectQuery from '../graphql/project_boards.query.graphql';
-import boardsStore from '../stores/boards_store';
import BoardForm from './board_form.vue';
const MIN_BOARDS_TO_VIEW_RECENT = 10;
@@ -35,6 +36,7 @@ export default {
directives: {
GlModalDirective,
},
+ inject: ['fullPath', 'recentBoardsEndpoint'],
props: {
currentBoard: {
type: Object,
@@ -99,12 +101,11 @@ export default {
scrollFadeInitialized: false,
boards: [],
recentBoards: [],
- state: boardsStore.state,
throttledSetScrollFade: throttle(this.setScrollFade, this.throttleDuration),
contentClientHeight: 0,
maxPosition: 0,
- store: boardsStore,
filterTerm: '',
+ currentPage: '',
};
},
computed: {
@@ -114,16 +115,13 @@ export default {
loading() {
return this.loadingRecentBoards || Boolean(this.loadingBoards);
},
- currentPage() {
- return this.state.currentPage;
- },
filteredBoards() {
return this.boards.filter((board) =>
board.name.toLowerCase().includes(this.filterTerm.toLowerCase()),
);
},
board() {
- return this.state.currentBoard;
+ return this.currentBoard;
},
showDelete() {
return this.boards.length > 1;
@@ -148,11 +146,17 @@ export default {
},
},
created() {
- boardsStore.setCurrentBoard(this.currentBoard);
+ eventHub.$on('showBoardModal', this.showPage);
+ },
+ beforeDestroy() {
+ eventHub.$off('showBoardModal', this.showPage);
},
methods: {
showPage(page) {
- boardsStore.showPage(page);
+ this.currentPage = page;
+ },
+ cancel() {
+ this.showPage('');
},
loadBoards(toggleDropdown = true) {
if (toggleDropdown && this.boards.length > 0) {
@@ -161,7 +165,7 @@ export default {
this.$apollo.addSmartQuery('boards', {
variables() {
- return { fullPath: this.state.endpoints.fullPath };
+ return { fullPath: this.fullPath };
},
query() {
return this.groupId ? groupQuery : projectQuery;
@@ -179,8 +183,10 @@ export default {
});
this.loadingRecentBoards = true;
- boardsStore
- .recentBoards()
+ // 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;
})
@@ -346,6 +352,8 @@ export default {
:weights="weights"
:enable-scoped-labels="enabledScopedLabels"
:current-board="currentBoard"
+ :current-page="currentPage"
+ @cancel="cancel"
/>
</span>
</div>
diff --git a/app/assets/javascripts/boards/components/boards_selector_deprecated.vue b/app/assets/javascripts/boards/components/boards_selector_deprecated.vue
new file mode 100644
index 00000000000..33ad46a0d29
--- /dev/null
+++ b/app/assets/javascripts/boards/components/boards_selector_deprecated.vue
@@ -0,0 +1,357 @@
+<script>
+import {
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
+ GlModalDirective,
+} from '@gitlab/ui';
+import { throttle } from 'lodash';
+
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import httpStatusCodes from '~/lib/utils/http_status';
+
+import groupQuery from '../graphql/group_boards.query.graphql';
+import projectQuery from '../graphql/project_boards.query.graphql';
+
+import boardsStore from '../stores/boards_store';
+import BoardForm from './board_form.vue';
+
+const MIN_BOARDS_TO_VIEW_RECENT = 10;
+
+export default {
+ name: 'BoardsSelector',
+ components: {
+ BoardForm,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ props: {
+ currentBoard: {
+ type: Object,
+ required: true,
+ },
+ throttleDuration: {
+ type: Number,
+ default: 200,
+ required: false,
+ },
+ boardBaseUrl: {
+ type: String,
+ required: true,
+ },
+ hasMissingBoards: {
+ type: Boolean,
+ required: true,
+ },
+ canAdminBoard: {
+ type: Boolean,
+ required: true,
+ },
+ multipleIssueBoardsAvailable: {
+ type: Boolean,
+ required: true,
+ },
+ labelsPath: {
+ type: String,
+ required: true,
+ },
+ labelsWebUrl: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ groupId: {
+ type: Number,
+ required: true,
+ },
+ scopedIssueBoardFeatureEnabled: {
+ type: Boolean,
+ required: true,
+ },
+ weights: {
+ type: Array,
+ required: true,
+ },
+ enabledScopedLabels: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ hasScrollFade: false,
+ loadingBoards: 0,
+ loadingRecentBoards: false,
+ scrollFadeInitialized: false,
+ boards: [],
+ recentBoards: [],
+ state: boardsStore.state,
+ throttledSetScrollFade: throttle(this.setScrollFade, this.throttleDuration),
+ contentClientHeight: 0,
+ maxPosition: 0,
+ store: boardsStore,
+ filterTerm: '',
+ };
+ },
+ computed: {
+ parentType() {
+ return this.groupId ? 'group' : 'project';
+ },
+ loading() {
+ return this.loadingRecentBoards || Boolean(this.loadingBoards);
+ },
+ currentPage() {
+ return this.state.currentPage;
+ },
+ filteredBoards() {
+ return this.boards.filter((board) =>
+ board.name.toLowerCase().includes(this.filterTerm.toLowerCase()),
+ );
+ },
+ board() {
+ return this.state.currentBoard;
+ },
+ showDelete() {
+ return this.boards.length > 1;
+ },
+ scrollFadeClass() {
+ return {
+ 'fade-out': !this.hasScrollFade,
+ };
+ },
+ showRecentSection() {
+ return (
+ this.recentBoards.length &&
+ this.boards.length > MIN_BOARDS_TO_VIEW_RECENT &&
+ !this.filterTerm.length
+ );
+ },
+ },
+ watch: {
+ filteredBoards() {
+ this.scrollFadeInitialized = false;
+ this.$nextTick(this.setScrollFade);
+ },
+ },
+ created() {
+ boardsStore.setCurrentBoard(this.currentBoard);
+ },
+ methods: {
+ showPage(page) {
+ boardsStore.showPage(page);
+ },
+ cancel() {
+ this.showPage('');
+ },
+ loadBoards(toggleDropdown = true) {
+ if (toggleDropdown && this.boards.length > 0) {
+ return;
+ }
+
+ this.$apollo.addSmartQuery('boards', {
+ variables() {
+ return { fullPath: this.state.endpoints.fullPath };
+ },
+ query() {
+ return this.groupId ? groupQuery : projectQuery;
+ },
+ loadingKey: 'loadingBoards',
+ update(data) {
+ if (!data?.[this.parentType]) {
+ return [];
+ }
+ return data[this.parentType].boards.edges.map(({ node }) => ({
+ id: getIdFromGraphQLId(node.id),
+ name: node.name,
+ }));
+ },
+ });
+
+ this.loadingRecentBoards = true;
+ boardsStore
+ .recentBoards()
+ .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;
+ });
+ },
+ isScrolledUp() {
+ const { content } = this.$refs;
+
+ if (!content) {
+ return false;
+ }
+
+ const currentPosition = this.contentClientHeight + content.scrollTop;
+
+ return currentPosition < this.maxPosition;
+ },
+ initScrollFade() {
+ const { content } = this.$refs;
+
+ if (!content) {
+ return;
+ }
+
+ this.scrollFadeInitialized = true;
+
+ this.contentClientHeight = content.clientHeight;
+ this.maxPosition = content.scrollHeight;
+ },
+ setScrollFade() {
+ if (!this.scrollFadeInitialized) this.initScrollFade();
+
+ this.hasScrollFade = this.isScrolledUp();
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="boards-switcher js-boards-selector gl-mr-3">
+ <span class="boards-selector-wrapper js-boards-selector-wrapper">
+ <gl-dropdown
+ data-qa-selector="boards_dropdown"
+ toggle-class="dropdown-menu-toggle js-dropdown-toggle"
+ menu-class="flex-column dropdown-extended-height"
+ :text="board.name"
+ @show="loadBoards"
+ >
+ <p class="gl-new-dropdown-header-top" @mousedown.prevent>
+ {{ s__('IssueBoards|Switch board') }}
+ </p>
+ <gl-search-box-by-type ref="searchBox" v-model="filterTerm" class="m-2" />
+
+ <div
+ v-if="!loading"
+ ref="content"
+ data-qa-selector="boards_dropdown_content"
+ class="dropdown-content flex-fill"
+ @scroll.passive="throttledSetScrollFade"
+ >
+ <gl-dropdown-item
+ v-show="filteredBoards.length === 0"
+ class="gl-pointer-events-none text-secondary"
+ >
+ {{ s__('IssueBoards|No matching boards found') }}
+ </gl-dropdown-item>
+
+ <gl-dropdown-section-header v-if="showRecentSection">
+ {{ __('Recent') }}
+ </gl-dropdown-section-header>
+
+ <template v-if="showRecentSection">
+ <gl-dropdown-item
+ v-for="recentBoard in recentBoards"
+ :key="`recent-${recentBoard.id}`"
+ class="js-dropdown-item"
+ :href="`${boardBaseUrl}/${recentBoard.id}`"
+ >
+ {{ recentBoard.name }}
+ </gl-dropdown-item>
+ </template>
+
+ <gl-dropdown-divider v-if="showRecentSection" />
+
+ <gl-dropdown-section-header v-if="showRecentSection">
+ {{ __('All') }}
+ </gl-dropdown-section-header>
+
+ <gl-dropdown-item
+ v-for="otherBoard in filteredBoards"
+ :key="otherBoard.id"
+ class="js-dropdown-item"
+ :href="`${boardBaseUrl}/${otherBoard.id}`"
+ >
+ {{ otherBoard.name }}
+ </gl-dropdown-item>
+
+ <gl-dropdown-item v-if="hasMissingBoards" class="no-pointer-events">
+ {{
+ s__(
+ 'IssueBoards|Some of your boards are hidden, activate a license to see them again.',
+ )
+ }}
+ </gl-dropdown-item>
+ </div>
+
+ <div
+ v-show="filteredBoards.length > 0"
+ class="dropdown-content-faded-mask"
+ :class="scrollFadeClass"
+ ></div>
+
+ <gl-loading-icon v-if="loading" />
+
+ <div v-if="canAdminBoard">
+ <gl-dropdown-divider />
+
+ <gl-dropdown-item
+ v-if="multipleIssueBoardsAvailable"
+ v-gl-modal-directive="'board-config-modal'"
+ data-qa-selector="create_new_board_button"
+ @click.prevent="showPage('new')"
+ >
+ {{ s__('IssueBoards|Create new board') }}
+ </gl-dropdown-item>
+
+ <gl-dropdown-item
+ v-if="showDelete"
+ v-gl-modal-directive="'board-config-modal'"
+ class="text-danger js-delete-board"
+ @click.prevent="showPage('delete')"
+ >
+ {{ s__('IssueBoards|Delete board') }}
+ </gl-dropdown-item>
+ </div>
+ </gl-dropdown>
+
+ <board-form
+ v-if="currentPage"
+ :labels-path="labelsPath"
+ :labels-web-url="labelsWebUrl"
+ :project-id="projectId"
+ :group-id="groupId"
+ :can-admin-board="canAdminBoard"
+ :scoped-issue-board-feature-enabled="scopedIssueBoardFeatureEnabled"
+ :weights="weights"
+ :enable-scoped-labels="enabledScopedLabels"
+ :current-board="currentBoard"
+ :current-page="state.currentPage"
+ @cancel="cancel"
+ />
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index 457d0d4dcd6..e5ea30df767 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -1,17 +1,17 @@
<script>
+import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { sortBy } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_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.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
+import { ListType } from '../constants';
+import eventHub from '../eventhub';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
-import eventHub from '../eventhub';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import { ListType } from '../constants';
-import { updateHistory } from '~/lib/utils/url_utility';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue b/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
index 75cf1f0b9e1..069cc2cda22 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner_deprecated.vue
@@ -1,15 +1,15 @@
<script>
+import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { sortBy } from 'lodash';
import { mapState } from 'vuex';
-import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
+import { isScopedLabel } from '~/lib/utils/common_utils';
import { sprintf, __, n__ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
+import boardsStore from '../stores/boards_store';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate_deprecated.vue';
-import boardsStore from '../stores/boards_store';
-import { isScopedLabel } from '~/lib/utils/common_utils';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index fb45de6e14d..7e3f36c8a17 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -1,13 +1,13 @@
<script>
-import dateFormat from 'dateformat';
import { GlTooltip, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
+import dateFormat from 'dateformat';
import {
getDayDifference,
getTimeago,
dateInWords,
parsePikadayDate,
} from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index f6b00b695da..42d187b9b40 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltip, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
export default {
i18n: {
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index eb2db260717..486b012e3d2 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
-import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
+import ModalStore from '../../stores/modal_store';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/modal/filters.js b/app/assets/javascripts/boards/components/modal/filters.js
index 56a0fde5a91..2fb38a549f3 100644
--- a/app/assets/javascripts/boards/components/modal/filters.js
+++ b/app/assets/javascripts/boards/components/modal/filters.js
@@ -1,5 +1,5 @@
-import FilteredSearchBoards from '../../filtered_search_boards';
import FilteredSearchContainer from '../../../filtered_search/container';
+import FilteredSearchBoards from '../../filtered_search_boards';
export default {
name: 'modal-filters',
diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue
index 10c29977cae..05e1219bc70 100644
--- a/app/assets/javascripts/boards/components/modal/footer.vue
+++ b/app/assets/javascripts/boards/components/modal/footer.vue
@@ -3,10 +3,10 @@ import { GlButton } from '@gitlab/ui';
import footerEEMixin from 'ee_else_ce/boards/mixins/modal_footer';
import { deprecatedCreateFlash as Flash } from '../../../flash';
import { __, n__ } from '../../../locale';
-import ListsDropdown from './lists_dropdown.vue';
-import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
import boardsStore from '../../stores/boards_store';
+import ModalStore from '../../stores/modal_store';
+import ListsDropdown from './lists_dropdown.vue';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
index 3e96ecca24c..c3a71e7177a 100644
--- a/app/assets/javascripts/boards/components/modal/header.vue
+++ b/app/assets/javascripts/boards/components/modal/header.vue
@@ -2,10 +2,10 @@
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
+import modalMixin from '../../mixins/modal_mixins';
+import ModalStore from '../../stores/modal_store';
import ModalFilters from './filters';
import ModalTabs from './tabs.vue';
-import ModalStore from '../../stores/modal_store';
-import modalMixin from '../../mixins/modal_mixins';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
index 84d687a46b9..5af90c1ee66 100644
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -1,13 +1,13 @@
<script>
/* global ListIssue */
import { GlLoadingIcon } from '@gitlab/ui';
-import { urlParamsToObject } from '~/lib/utils/common_utils';
import boardsStore from '~/boards/stores/boards_store';
+import { urlParamsToObject } from '~/lib/utils/common_utils';
+import ModalStore from '../../stores/modal_store';
+import EmptyState from './empty_state.vue';
+import ModalFooter from './footer.vue';
import ModalHeader from './header.vue';
import ModalList from './list.vue';
-import ModalFooter from './footer.vue';
-import EmptyState from './empty_state.vue';
-import ModalStore from '../../stores/modal_store';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
index 219263bd9b9..bf69f8140d5 100644
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -1,6 +1,6 @@
<script>
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { GlIcon } from '@gitlab/ui';
+import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import ModalStore from '../../stores/modal_store';
import IssueCardInner from '../issue_card_inner.vue';
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index fe10e7fb856..2065568d275 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlIcon } from '@gitlab/ui';
-import ModalStore from '../../stores/modal_store';
import boardsStore from '../../stores/boards_store';
+import ModalStore from '../../stores/modal_store';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue
index b066fb25360..0b717f516db 100644
--- a/app/assets/javascripts/boards/components/modal/tabs.vue
+++ b/app/assets/javascripts/boards/components/modal/tabs.vue
@@ -1,8 +1,8 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
-import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
+import ModalStore from '../../stores/modal_store';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js
index 2bc54155163..2fd16f06455 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
@@ -1,15 +1,15 @@
/* eslint-disable func-names, no-new */
import $ from 'jquery';
-import { __ } from '~/locale';
-import axios from '~/lib/utils/axios_utils';
+import store from '~/boards/stores';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { deprecatedCreateFlash as flash } from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
import CreateLabelDropdown from '../../create_label';
-import boardsStore from '../stores/boards_store';
import { fullLabelId } from '../boards_util';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import store from '~/boards/stores';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import boardsStore from '../stores/boards_store';
function shouldCreateListGraphQL(label) {
return store.getters.shouldUseGraphQL && !store.getters.getListByLabelId(fullLabelId(label));
@@ -51,16 +51,27 @@ export default function initNewListDropdown() {
initDeprecatedJQueryDropdown($dropdownToggle, {
data(term, callback) {
- axios
- .get($dropdownToggle.attr('data-list-labels-path'))
- .then(({ data }) => callback(data))
- .catch(() => {
- $dropdownToggle.data('bs.dropdown').hide();
- flash(__('Error fetching labels.'));
- });
+ const reqFailed = () => {
+ $dropdownToggle.data('bs.dropdown').hide();
+ flash(__('Error fetching labels.'));
+ };
+
+ if (store.getters.shouldUseGraphQL) {
+ store
+ .dispatch('fetchLabels')
+ .then((data) => callback(data))
+ .catch(reqFailed);
+ } else {
+ axios
+ .get($dropdownToggle.attr('data-list-labels-path'))
+ .then(({ data }) => callback(data))
+ .catch(reqFailed);
+ }
},
renderRow(label) {
- const active = boardsStore.findListByLabelId(label.id);
+ const active = store.getters.shouldUseGraphQL
+ ? store.getters.getListByLabelId(label.id)
+ : boardsStore.findListByLabelId(label.id);
const $li = $('<li />');
const $a = $('<a />', {
class: active ? `is-active js-board-list-${getIdFromGraphQLId(active.id)}` : '',
@@ -87,7 +98,7 @@ export default function initNewListDropdown() {
e.preventDefault();
if (shouldCreateListGraphQL(label)) {
- store.dispatch('createList', { labelId: fullLabelId(label) });
+ store.dispatch('createList', { labelId: label.id });
} else if (!boardsStore.findListByLabelId(label.id)) {
boardsStore.new({
title: label.title,
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index 04699d0d3a4..cfc1752a828 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapState } from 'vuex';
import {
GlDropdown,
GlDropdownItem,
@@ -8,6 +7,7 @@ import {
GlIntersectionObserver,
GlLoadingIcon,
} from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
import { ListType } from '../constants';
diff --git a/app/assets/javascripts/boards/components/project_select_deprecated.vue b/app/assets/javascripts/boards/components/project_select_deprecated.vue
index a043dc575ca..5605e9945ea 100644
--- a/app/assets/javascripts/boards/components/project_select_deprecated.vue
+++ b/app/assets/javascripts/boards/components/project_select_deprecated.vue
@@ -6,11 +6,11 @@ import {
GlSearchBoxByType,
GlLoadingIcon,
} from '@gitlab/ui';
-import eventHub from '../eventhub';
import { s__ } from '~/locale';
-import Api from '../../api';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
+import Api from '../../api';
import { ListType } from '../constants';
+import eventHub from '../eventhub';
export default {
name: 'ProjectSelect',
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
index 4a664d5beef..6d928337396 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
@@ -1,9 +1,9 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import { GlButton, GlDatepicker } from '@gitlab/ui';
+import { mapGetters, mapActions } from 'vuex';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
import createFlash from '~/flash';
+import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
export default {
@@ -88,15 +88,13 @@ export default {
</gl-button>
</div>
</template>
- <template>
- <gl-datepicker
- ref="datePicker"
- :value="parsedDueDate"
- show-clear-button
- @input="setDueDate"
- @clear="setDueDate(null)"
- />
- </template>
+ <gl-datepicker
+ ref="datePicker"
+ :value="parsedDueDate"
+ show-clear-button
+ @input="setDueDate"
+ @clear="setDueDate(null)"
+ />
</board-editable-item>
</template>
<style>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
index d0e641daf5c..95864bd62a7 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_issue_title.vue
@@ -1,11 +1,11 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import { GlAlert, GlButton, GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { mapGetters, mapActions } from 'vuex';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
-import { joinPaths } from '~/lib/utils/url_utility';
import createFlash from '~/flash';
+import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
+import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
export default {
components: {
@@ -136,36 +136,34 @@ export default {
<template #collapsed>
<span class="gl-text-gray-800">{{ issue.referencePath }}</span>
</template>
- <template>
- <gl-alert v-if="showChangesAlert" variant="warning" class="gl-mb-5" :dismissible="false">
- {{ $options.i18n.reviewYourChanges }}
- </gl-alert>
- <gl-form @submit.prevent="setTitle">
- <gl-form-group :invalid-feedback="$options.i18n.invalidFeedback" :state="validationState">
- <gl-form-input
- v-model="title"
- v-autofocusonshow
- :placeholder="$options.i18n.issueTitlePlaceholder"
- :state="validationState"
- />
- </gl-form-group>
+ <gl-alert v-if="showChangesAlert" variant="warning" class="gl-mb-5" :dismissible="false">
+ {{ $options.i18n.reviewYourChanges }}
+ </gl-alert>
+ <gl-form @submit.prevent="setTitle">
+ <gl-form-group :invalid-feedback="$options.i18n.invalidFeedback" :state="validationState">
+ <gl-form-input
+ v-model="title"
+ v-autofocusonshow
+ :placeholder="$options.i18n.issueTitlePlaceholder"
+ :state="validationState"
+ />
+ </gl-form-group>
- <div class="gl-display-flex gl-w-full gl-justify-content-space-between gl-mt-5">
- <gl-button
- variant="success"
- size="small"
- data-testid="submit-button"
- :disabled="!title"
- @click="setTitle"
- >
- {{ $options.i18n.submitButton }}
- </gl-button>
+ <div class="gl-display-flex gl-w-full gl-justify-content-space-between gl-mt-5">
+ <gl-button
+ variant="success"
+ size="small"
+ data-testid="submit-button"
+ :disabled="!title"
+ @click="setTitle"
+ >
+ {{ $options.i18n.submitButton }}
+ </gl-button>
- <gl-button size="small" data-testid="cancel-button" @click="cancel">
- {{ $options.i18n.cancelButton }}
- </gl-button>
- </div>
- </gl-form>
- </template>
+ <gl-button size="small" data-testid="cancel-button" @click="cancel">
+ {{ $options.i18n.cancelButton }}
+ </gl-button>
+ </div>
+ </gl-form>
</board-editable-item>
</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
index dcf769e6fe5..55b1596ee18 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
@@ -1,12 +1,12 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import { GlLabel } from '@gitlab/ui';
-import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { mapGetters, mapActions } from 'vuex';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import { isScopedLabel } from '~/lib/utils/common_utils';
import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { isScopedLabel } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
index 144a81f009b..829f1c72806 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_milestone_select.vue
@@ -1,5 +1,4 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import {
GlDropdown,
GlDropdownItem,
@@ -8,11 +7,11 @@ import {
GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
-import { fetchPolicies } from '~/lib/graphql';
+import { mapGetters, mapActions } from 'vuex';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import groupMilestones from '../../graphql/group_milestones.query.graphql';
import createFlash from '~/flash';
import { __, s__ } from '~/locale';
+import projectMilestones from '../../graphql/project_milestones.query.graphql';
export default {
components: {
@@ -34,22 +33,21 @@ export default {
},
apollo: {
milestones: {
- fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
- query: groupMilestones,
+ query: projectMilestones,
debounce: 250,
skip() {
return !this.edit;
},
variables() {
return {
- fullPath: this.groupFullPath,
+ fullPath: this.projectPath,
searchTitle: this.searchTitle,
state: 'active',
- includeDescendants: true,
+ includeAncestors: true,
};
},
update(data) {
- const edges = data?.group?.milestones?.edges ?? [];
+ const edges = data?.project?.milestones?.edges ?? [];
return edges.map((item) => item.node);
},
error() {
@@ -74,21 +72,20 @@ export default {
return this.activeIssue.milestone?.title ?? this.$options.i18n.noMilestone;
},
},
- mounted() {
- this.$root.$on('bv::dropdown::hide', () => {
- this.$refs.sidebarItem.collapse();
- });
- },
methods: {
...mapActions(['setActiveIssueMilestone']),
handleOpen() {
this.edit = true;
this.$refs.dropdown.show();
},
+ handleClose() {
+ this.edit = false;
+ this.$refs.sidebarItem.collapse();
+ },
async setMilestone(milestoneId) {
this.loading = true;
this.searchTitle = '';
- this.$refs.sidebarItem.collapse();
+ this.handleClose();
try {
const input = { milestoneId, projectPath: this.projectPath };
@@ -117,45 +114,44 @@ export default {
:title="$options.i18n.milestone"
:loading="loading"
@open="handleOpen()"
- @close="edit = false"
+ @close="handleClose"
>
<template v-if="hasMilestone" #collapsed>
<strong class="gl-text-gray-900">{{ activeIssue.milestone.title }}</strong>
</template>
- <template>
- <gl-dropdown
- ref="dropdown"
- :text="dropdownText"
- :header-text="$options.i18n.assignMilestone"
- block
+ <gl-dropdown
+ ref="dropdown"
+ :text="dropdownText"
+ :header-text="$options.i18n.assignMilestone"
+ block
+ @hide="handleClose"
+ >
+ <gl-search-box-by-type ref="search" v-model.trim="searchTitle" class="gl-m-3" />
+ <gl-dropdown-item
+ data-testid="no-milestone-item"
+ :is-check-item="true"
+ :is-checked="!activeIssue.milestone"
+ @click="setMilestone(null)"
>
- <gl-search-box-by-type ref="search" v-model.trim="searchTitle" class="gl-m-3" />
+ {{ $options.i18n.noMilestone }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-loading-icon v-if="$apollo.loading" class="gl-py-4" />
+ <template v-else-if="milestones.length > 0">
<gl-dropdown-item
- data-testid="no-milestone-item"
+ v-for="milestone in milestones"
+ :key="milestone.id"
:is-check-item="true"
- :is-checked="!activeIssue.milestone"
- @click="setMilestone(null)"
+ :is-checked="activeIssue.milestone && milestone.id === activeIssue.milestone.id"
+ data-testid="milestone-item"
+ @click="setMilestone(milestone.id)"
>
- {{ $options.i18n.noMilestone }}
+ {{ milestone.title }}
</gl-dropdown-item>
- <gl-dropdown-divider />
- <gl-loading-icon v-if="$apollo.loading" class="gl-py-4" />
- <template v-else-if="milestones.length > 0">
- <gl-dropdown-item
- v-for="milestone in milestones"
- :key="milestone.id"
- :is-check-item="true"
- :is-checked="activeIssue.milestone && milestone.id === activeIssue.milestone.id"
- data-testid="milestone-item"
- @click="setMilestone(milestone.id)"
- >
- {{ milestone.title }}
- </gl-dropdown-item>
- </template>
- <gl-dropdown-text v-else data-testid="no-milestones-found">
- {{ $options.i18n.noMilestonesFound }}
- </gl-dropdown-text>
- </gl-dropdown>
- </template>
+ </template>
+ <gl-dropdown-text v-else data-testid="no-milestones-found">
+ {{ $options.i18n.noMilestonesFound }}
+ </gl-dropdown-text>
+ </gl-dropdown>
</board-editable-item>
</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
index 4aa8d2f55e4..aa4fdcf9a94 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import { GlToggle } from '@gitlab/ui';
+import { mapGetters, mapActions } from 'vuex';
import createFlash from '~/flash';
import { __, s__ } from '~/locale';
diff --git a/app/assets/javascripts/boards/components/toggle_focus.vue b/app/assets/javascripts/boards/components/toggle_focus.vue
new file mode 100644
index 00000000000..74805f8a681
--- /dev/null
+++ b/app/assets/javascripts/boards/components/toggle_focus.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlButton, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { hide } from '~/tooltips';
+
+export default {
+ components: {
+ GlButton,
+ },
+ directives: {
+ GlTooltip,
+ },
+ props: {
+ issueBoardsContentSelector: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isFullscreen: false,
+ };
+ },
+ methods: {
+ toggleFocusMode() {
+ hide(this.$refs.toggleFocusModeButton);
+
+ const issueBoardsContent = document.querySelector(this.issueBoardsContentSelector);
+ issueBoardsContent.classList.toggle('is-focused');
+
+ this.isFullscreen = !this.isFullscreen;
+ },
+ },
+ i18n: {
+ toggleFocusMode: __('Toggle focus mode'),
+ },
+};
+</script>
+
+<template>
+ <div class="board-extra-actions gl-ml-3 gl-display-flex gl-align-items-center">
+ <gl-button
+ ref="toggleFocusModeButton"
+ v-gl-tooltip
+ :icon="isFullscreen ? 'minimize' : 'maximize'"
+ class="js-focus-mode-btn"
+ data-qa-selector="focus_mode_button"
+ :title="$options.i18n.toggleFocusMode"
+ @click="toggleFocusMode"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index 9264fac5eda..3ab89b2c9da 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const BoardType = {
project: 'project',
group: 'group',
@@ -6,16 +8,34 @@ export const BoardType = {
export const ListType = {
assignee: 'assignee',
milestone: 'milestone',
+ iteration: 'iteration',
backlog: 'backlog',
closed: 'closed',
label: 'label',
};
+export const ListTypeTitles = {
+ assignee: __('Assignee'),
+ milestone: __('Milestone'),
+ iteration: __('Iteration'),
+ label: __('Label'),
+};
+
+export const formType = {
+ new: 'new',
+ delete: 'delete',
+ edit: 'edit',
+};
+
export const inactiveId = 0;
export const ISSUABLE = 'issuable';
export const LIST = 'list';
+export const NOT_FILTER = 'not[';
+
+export const flashAnimationDuration = 2000;
+
export default {
BoardType,
ListType,
diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js
index 94b35aadaf1..66580bdd30f 100644
--- a/app/assets/javascripts/boards/filtered_search_boards.js
+++ b/app/assets/javascripts/boards/filtered_search_boards.js
@@ -1,10 +1,10 @@
-import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import FilteredSearchManager from 'ee_else_ce/filtered_search/filtered_search_manager';
import { transformBoardConfig } from 'ee_else_ce/boards/boards_util';
+import FilteredSearchManager from 'ee_else_ce/filtered_search/filtered_search_manager';
+import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
+import { updateHistory } from '~/lib/utils/url_utility';
import FilteredSearchContainer from '../filtered_search/container';
-import boardsStore from './stores/boards_store';
import vuexstore from './stores';
-import { updateHistory } from '~/lib/utils/url_utility';
+import boardsStore from './stores/boards_store';
export default class FilteredSearchBoards extends FilteredSearchManager {
constructor(store, updateUrl = false, cantEdit = []) {
diff --git a/app/assets/javascripts/boards/filters/due_date_filters.js b/app/assets/javascripts/boards/filters/due_date_filters.js
index c35dedde71b..1745ab3bab4 100644
--- a/app/assets/javascripts/boards/filters/due_date_filters.js
+++ b/app/assets/javascripts/boards/filters/due_date_filters.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import dateFormat from 'dateformat';
+import Vue from 'vue';
Vue.filter('due-date', (value) => {
const date = new Date(value);
diff --git a/app/assets/javascripts/boards/graphql/group_milestones.query.graphql b/app/assets/javascripts/boards/graphql/group_milestones.query.graphql
deleted file mode 100644
index f2ab12ef4a7..00000000000
--- a/app/assets/javascripts/boards/graphql/group_milestones.query.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-query groupMilestones(
- $fullPath: ID!
- $state: MilestoneStateEnum
- $includeDescendants: Boolean
- $searchTitle: String
-) {
- group(fullPath: $fullPath) {
- milestones(state: $state, includeDescendants: $includeDescendants, searchTitle: $searchTitle) {
- edges {
- node {
- id
- title
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/graphql/project_milestones.query.graphql b/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
new file mode 100644
index 00000000000..776530ebb83
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
@@ -0,0 +1,17 @@
+query groupMilestones(
+ $fullPath: ID!
+ $state: MilestoneStateEnum
+ $includeAncestors: Boolean
+ $searchTitle: String
+) {
+ project(fullPath: $fullPath) {
+ milestones(state: $state, includeAncestors: $includeAncestors, searchTitle: $searchTitle) {
+ edges {
+ node {
+ id
+ title
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index ef70a094f7c..859295318ed 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { mapActions, mapGetters } from 'vuex';
import 'ee_else_ce/boards/models/issue';
@@ -6,41 +7,39 @@ import 'ee_else_ce/boards/models/list';
import BoardSidebar from 'ee_else_ce/boards/components/board_sidebar';
import initNewListDropdown from 'ee_else_ce/boards/components/new_list_dropdown';
import boardConfigToggle from 'ee_else_ce/boards/config_toggle';
-import toggleLabels from 'ee_else_ce/boards/toggle_labels';
-import toggleEpicsSwimlanes from 'ee_else_ce/boards/toggle_epics_swimlanes';
import {
setWeightFetchingState,
setEpicFetchingState,
getMilestoneTitle,
getBoardsModalData,
} from 'ee_else_ce/boards/ee_functions';
-
-import VueApollo from 'vue-apollo';
+import toggleEpicsSwimlanes from 'ee_else_ce/boards/toggle_epics_swimlanes';
+import toggleLabels from 'ee_else_ce/boards/toggle_labels';
+import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
import BoardContent from '~/boards/components/board_content.vue';
import BoardExtraActions from '~/boards/components/board_extra_actions.vue';
-import createDefaultClient from '~/lib/graphql';
-import { deprecatedCreateFlash as Flash } from '~/flash';
-import { __ } from '~/locale';
import './models/label';
import './models/assignee';
-
-import toggleFocusMode from '~/boards/toggle_focus';
-import FilteredSearchBoards from '~/boards/filtered_search_boards';
-import eventHub from '~/boards/eventhub';
-import sidebarEventHub from '~/sidebar/event_hub';
import '~/boards/models/milestone';
import '~/boards/models/project';
+import '~/boards/filters/due_date_filters';
+import BoardAddIssuesModal from '~/boards/components/modal/index.vue';
+import eventHub from '~/boards/eventhub';
+import FilteredSearchBoards from '~/boards/filtered_search_boards';
+import modalMixin from '~/boards/mixins/modal_mixins';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
import ModalStore from '~/boards/stores/modal_store';
-import modalMixin from '~/boards/mixins/modal_mixins';
-import '~/boards/filters/due_date_filters';
-import BoardAddIssuesModal from '~/boards/components/modal/index.vue';
+import toggleFocusMode from '~/boards/toggle_focus';
+import { deprecatedCreateFlash as Flash } from '~/flash';
+import createDefaultClient from '~/lib/graphql';
import {
NavigationType,
convertObjectPropsToCamelCase,
parseBoolean,
} from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import sidebarEventHub from '~/sidebar/event_hub';
import mountMultipleBoardsSwitcher from './mount_multiple_boards_switcher';
Vue.use(VueApollo);
@@ -73,6 +72,7 @@ export default () => {
boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours);
}
+ // eslint-disable-next-line @gitlab/no-runtime-template-compiler
issueBoardsApp = new Vue({
el: $boardApp,
components: {
@@ -86,7 +86,7 @@ export default () => {
groupId: Number($boardApp.dataset.groupId),
rootPath: $boardApp.dataset.rootPath,
currentUserId: gon.current_user_id || null,
- canUpdate: $boardApp.dataset.canUpdate,
+ canUpdate: parseBoolean($boardApp.dataset.canUpdate),
labelsFetchPath: $boardApp.dataset.labelsFetchPath,
labelsManagePath: $boardApp.dataset.labelsManagePath,
labelsFilterBasePath: $boardApp.dataset.labelsFilterBasePath,
@@ -275,7 +275,7 @@ export default () => {
},
});
- // eslint-disable-next-line no-new
+ // eslint-disable-next-line no-new, @gitlab/no-runtime-template-compiler
new Vue({
el: document.getElementById('js-add-list'),
data: {
@@ -287,6 +287,21 @@ export default () => {
},
});
+ const createColumnTriggerEl = document.querySelector('.js-create-column-trigger');
+ if (createColumnTriggerEl) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: createColumnTriggerEl,
+ components: {
+ BoardAddNewColumnTrigger,
+ },
+ store,
+ render(createElement) {
+ return createElement('board-add-new-column-trigger');
+ },
+ });
+ }
+
boardConfigToggle(boardsStore);
const issueBoardsModal = document.getElementById('js-add-issues-btn');
@@ -341,5 +356,6 @@ export default () => {
mountMultipleBoardsSwitcher({
fullPath: $boardApp.dataset.fullPath,
rootPath: $boardApp.dataset.boardsEndpoint,
+ recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
});
};
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index 1e77326ba9c..46d1239457d 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -6,8 +6,8 @@
import axios from '~/lib/utils/axios_utils';
import './label';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import IssueProject from './project';
import boardsStore from '../stores/boards_store';
+import IssueProject from './project';
class ListIssue {
constructor(obj) {
@@ -53,6 +53,10 @@ class ListIssue {
return boardsStore.findIssueAssignee(this, findAssignee);
}
+ setAssignees(assignees) {
+ boardsStore.setIssueAssignees(this, assignees);
+ }
+
removeAssignee(removeAssignee) {
boardsStore.removeIssueAssignee(this, removeAssignee);
}
diff --git a/app/assets/javascripts/boards/models/iteration.js b/app/assets/javascripts/boards/models/iteration.js
new file mode 100644
index 00000000000..b7bdc204f7c
--- /dev/null
+++ b/app/assets/javascripts/boards/models/iteration.js
@@ -0,0 +1,9 @@
+export default class ListIteration {
+ constructor(obj) {
+ this.id = obj.id;
+ this.title = obj.title;
+ this.state = obj.state;
+ this.webUrl = obj.web_url || obj.webUrl;
+ this.description = obj.description;
+ }
+}
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index be02ac7b889..6c6e2522d92 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -1,9 +1,10 @@
/* eslint-disable class-methods-use-this */
-import { __ } from '~/locale';
-import ListLabel from './label';
-import ListAssignee from './assignee';
import { deprecatedCreateFlash as flash } from '~/flash';
+import { __ } from '~/locale';
import boardsStore from '../stores/boards_store';
+import ListAssignee from './assignee';
+import ListIteration from './iteration';
+import ListLabel from './label';
import ListMilestone from './milestone';
import 'ee_else_ce/boards/models/issue';
@@ -43,6 +44,7 @@ class List {
this.isExpandable = Boolean(typeInfo.isExpandable);
this.isExpanded = !obj.collapsed;
this.page = 1;
+ this.highlighted = obj.highlighted;
this.loading = true;
this.loadingMore = false;
this.issues = obj.issues || [];
@@ -57,6 +59,9 @@ class List {
} else if (IS_EE && obj.milestone) {
this.milestone = new ListMilestone(obj.milestone);
this.title = this.milestone.title;
+ } else if (IS_EE && obj.iteration) {
+ this.iteration = new ListIteration(obj.iteration);
+ this.title = this.iteration.title;
}
// doNotFetchIssues is a temporary workaround until issues are fetched using GraphQL on issue boards
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
index 738c8fb927e..fa58af24ba2 100644
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
@@ -1,8 +1,12 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import { mapGetters } from 'vuex';
+import BoardsSelector from '~/boards/components/boards_selector.vue';
+import BoardsSelectorDeprecated from '~/boards/components/boards_selector_deprecated.vue';
+import store from '~/boards/stores';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
-import BoardsSelector from '~/boards/components/boards_selector.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
Vue.use(VueApollo);
@@ -16,11 +20,15 @@ export default (params = {}) => {
el: boardsSwitcherElement,
components: {
BoardsSelector,
+ BoardsSelectorDeprecated,
},
+ mixins: [glFeatureFlagMixin()],
apolloProvider,
+ store,
provide: {
fullPath: params.fullPath,
rootPath: params.rootPath,
+ recentBoardsEndpoint: params.recentBoardsEndpoint,
},
data() {
const { dataset } = boardsSwitcherElement;
@@ -39,8 +47,16 @@ export default (params = {}) => {
return { boardsSelectorProps };
},
+ computed: {
+ ...mapGetters(['shouldUseGraphQL']),
+ },
render(createElement) {
- return createElement(BoardsSelector, {
+ if (this.shouldUseGraphQL) {
+ return createElement(BoardsSelector, {
+ props: this.boardsSelectorProps,
+ });
+ }
+ return createElement(BoardsSelectorDeprecated, {
props: this.boardsSelectorProps,
});
},
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 1d34f21798a..a7cf1e9e647 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -1,11 +1,9 @@
import { pick } from 'lodash';
-
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
-import createGqClient, { fetchPolicies } from '~/lib/graphql';
+import { BoardType, ListType, inactiveId, flashAnimationDuration } from '~/boards/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { convertObjectPropsToCamelCase, urlParamsToObject } from '~/lib/utils/common_utils';
-import { BoardType, ListType, inactiveId } from '~/boards/constants';
-import * as types from './mutation_types';
import {
formatBoardLists,
formatListIssues,
@@ -14,23 +12,22 @@ import {
formatIssue,
formatIssueInput,
updateListPosition,
+ transformNotFilters,
} from '../boards_util';
-import createFlash from '~/flash';
-import { __ } from '~/locale';
-import updateAssigneesMutation from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql';
-import listsIssuesQuery from '../graphql/lists_issues.query.graphql';
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
import createBoardListMutation from '../graphql/board_list_create.mutation.graphql';
-import updateBoardListMutation from '../graphql/board_list_update.mutation.graphql';
-import issueMoveListMutation from '../graphql/issue_move_list.mutation.graphql';
import destroyBoardListMutation from '../graphql/board_list_destroy.mutation.graphql';
+import updateBoardListMutation from '../graphql/board_list_update.mutation.graphql';
+import groupProjectsQuery from '../graphql/group_projects.query.graphql';
import issueCreateMutation from '../graphql/issue_create.mutation.graphql';
-import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql';
+import issueMoveListMutation from '../graphql/issue_move_list.mutation.graphql';
import issueSetDueDateMutation from '../graphql/issue_set_due_date.mutation.graphql';
-import issueSetSubscriptionMutation from '../graphql/issue_set_subscription.mutation.graphql';
+import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql';
import issueSetMilestoneMutation from '../graphql/issue_set_milestone.mutation.graphql';
+import issueSetSubscriptionMutation from '../graphql/issue_set_subscription.mutation.graphql';
import issueSetTitleMutation from '../graphql/issue_set_title.mutation.graphql';
-import groupProjectsQuery from '../graphql/group_projects.query.graphql';
+import listsIssuesQuery from '../graphql/lists_issues.query.graphql';
+import * as types from './mutation_types';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
@@ -66,6 +63,7 @@ export default {
'releaseTag',
'search',
]);
+ filterParams.not = transformNotFilters(filters);
commit(types.SET_FILTERS, filterParams);
},
@@ -108,9 +106,31 @@ export default {
.catch(() => commit(types.RECEIVE_BOARD_LISTS_FAILURE));
},
- createList: ({ state, commit, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => {
+ highlightList: ({ commit, state }, listId) => {
+ if ([ListType.backlog, ListType.closed].includes(state.boardLists[listId].listType)) {
+ return;
+ }
+
+ commit(types.ADD_LIST_TO_HIGHLIGHTED_LISTS, listId);
+
+ setTimeout(() => {
+ commit(types.REMOVE_LIST_FROM_HIGHLIGHTED_LISTS, listId);
+ }, flashAnimationDuration);
+ },
+
+ createList: (
+ { state, commit, dispatch, getters },
+ { backlog, labelId, milestoneId, assigneeId },
+ ) => {
const { boardId } = state;
+ const existingList = getters.getListByLabelId(labelId);
+
+ if (existingList) {
+ dispatch('highlightList', existingList.id);
+ return;
+ }
+
gqlClient
.mutate({
mutation: createBoardListMutation,
@@ -128,6 +148,7 @@ export default {
} else {
const list = data.boardListCreate?.list;
dispatch('addList', list);
+ dispatch('highlightList', list.id);
}
})
.catch(() => commit(types.CREATE_LIST_FAILURE));
@@ -153,10 +174,10 @@ export default {
variables,
})
.then(({ data }) => {
- const labels = data[boardType]?.labels;
- return labels.nodes;
- })
- .catch(() => commit(types.RECEIVE_LABELS_FAILURE));
+ const labels = data[boardType]?.labels.nodes;
+ commit(types.RECEIVE_LABELS_SUCCESS, labels);
+ return labels;
+ });
},
moveList: (
@@ -308,34 +329,11 @@ export default {
},
setAssignees: ({ commit, getters }, assigneeUsernames) => {
- commit(types.SET_ASSIGNEE_LOADING, true);
-
- return gqlClient
- .mutate({
- mutation: updateAssigneesMutation,
- variables: {
- iid: getters.activeIssue.iid,
- projectPath: getters.activeIssue.referencePath.split('#')[0],
- assigneeUsernames,
- },
- })
- .then(({ data }) => {
- const { nodes } = data.issueSetAssignees?.issue?.assignees || [];
-
- commit('UPDATE_ISSUE_BY_ID', {
- issueId: getters.activeIssue.id,
- prop: 'assignees',
- value: nodes,
- });
-
- return nodes;
- })
- .catch(() => {
- createFlash({ message: __('An error occurred while updating assignees.') });
- })
- .finally(() => {
- commit(types.SET_ASSIGNEE_LOADING, false);
- });
+ commit('UPDATE_ISSUE_BY_ID', {
+ issueId: getters.activeIssue.id,
+ prop: 'assignees',
+ value: assigneeUsernames,
+ });
},
setActiveIssueMilestone: async ({ commit, getters }, input) => {
@@ -534,6 +532,21 @@ export default {
commit(types.SET_SELECTED_PROJECT, project);
},
+ toggleBoardItemMultiSelection: ({ commit, state }, boardItem) => {
+ const { selectedBoardItems } = state;
+ const index = selectedBoardItems.indexOf(boardItem);
+
+ if (index === -1) {
+ commit(types.ADD_BOARD_ITEM_TO_SELECTION, boardItem);
+ } else {
+ commit(types.REMOVE_BOARD_ITEM_FROM_SELECTION, boardItem);
+ }
+ },
+
+ setAddColumnFormVisibility: ({ commit }, visible) => {
+ commit(types.SET_ADD_COLUMN_FORM_VISIBLE, visible);
+ },
+
fetchBacklog: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index f59530ddf8f..fbff736c7e1 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -4,22 +4,22 @@
import { sortBy } from 'lodash';
import Vue from 'vue';
import BoardsStoreEE from 'ee_else_ce/boards/stores/boards_store_ee';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import createDefaultClient from '~/lib/graphql';
+import axios from '~/lib/utils/axios_utils';
import {
urlParamsToObject,
getUrlParamsArray,
parseBoolean,
convertObjectPropsToCamelCase,
} from '~/lib/utils/common_utils';
-import createDefaultClient from '~/lib/graphql';
-import axios from '~/lib/utils/axios_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { ListType, flashAnimationDuration } from '../constants';
import eventHub from '../eventhub';
-import { ListType } from '../constants';
-import IssueProject from '../models/project';
-import ListLabel from '../models/label';
import ListAssignee from '../models/assignee';
+import ListLabel from '../models/label';
import ListMilestone from '../models/milestone';
+import IssueProject from '../models/project';
const PER_PAGE = 20;
export const gqlClient = createDefaultClient();
@@ -106,6 +106,11 @@ const boardsStore = {
list
.save()
.then(() => {
+ list.highlighted = true;
+ setTimeout(() => {
+ list.highlighted = false;
+ }, flashAnimationDuration);
+
// Remove any new issues from the backlog
// as they will be visible in the new list
list.issues.forEach(backlogList.removeIssue.bind(backlogList));
@@ -117,7 +122,6 @@ const boardsStore = {
},
updateNewListDropdown(listId) {
- // eslint-disable-next-line no-unused-expressions
document
.querySelector(`.js-board-list-${getIdFromGraphQLId(listId)}`)
?.classList.remove('is-active');
@@ -720,6 +724,10 @@ const boardsStore = {
}
},
+ setIssueAssignees(issue, assignees) {
+ issue.assignees = [...assignees];
+ },
+
removeIssueLabels(issue, labels) {
labels.forEach(issue.removeLabel.bind(issue));
},
diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js
index d72b5c6fb8e..cab97088bc6 100644
--- a/app/assets/javascripts/boards/stores/getters.js
+++ b/app/assets/javascripts/boards/stores/getters.js
@@ -17,12 +17,20 @@ export default {
return state.issues[state.activeId] || {};
},
+ groupPathForActiveIssue: (_, getters) => {
+ const { referencePath = '' } = getters.activeIssue;
+ return referencePath.slice(0, referencePath.indexOf('/'));
+ },
+
projectPathForActiveIssue: (_, getters) => {
- const referencePath = getters.activeIssue.referencePath || '';
+ const { referencePath = '' } = getters.activeIssue;
return referencePath.slice(0, referencePath.indexOf('#'));
},
getListByLabelId: (state) => (labelId) => {
+ if (!labelId) {
+ return null;
+ }
return find(state.boardLists, (l) => l.label?.id === labelId);
},
diff --git a/app/assets/javascripts/boards/stores/index.js b/app/assets/javascripts/boards/stores/index.js
index 471b952a212..0a87c6ab821 100644
--- a/app/assets/javascripts/boards/stores/index.js
+++ b/app/assets/javascripts/boards/stores/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from 'ee_else_ce/boards/stores/state';
-import getters from 'ee_else_ce/boards/stores/getters';
import actions from 'ee_else_ce/boards/stores/actions';
+import getters from 'ee_else_ce/boards/stores/getters';
import mutations from 'ee_else_ce/boards/stores/mutations';
+import state from 'ee_else_ce/boards/stores/state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index 4697f39498a..a89e961ae2d 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -2,7 +2,7 @@ export const SET_INITIAL_BOARD_DATA = 'SET_INITIAL_BOARD_DATA';
export const SET_FILTERS = 'SET_FILTERS';
export const CREATE_LIST_SUCCESS = 'CREATE_LIST_SUCCESS';
export const CREATE_LIST_FAILURE = 'CREATE_LIST_FAILURE';
-export const RECEIVE_LABELS_FAILURE = 'RECEIVE_LABELS_FAILURE';
+export const RECEIVE_LABELS_SUCCESS = 'RECEIVE_LABELS_SUCCESS';
export const GENERATE_DEFAULT_LISTS_FAILURE = 'GENERATE_DEFAULT_LISTS_FAILURE';
export const RECEIVE_BOARD_LISTS_SUCCESS = 'RECEIVE_BOARD_LISTS_SUCCESS';
export const RECEIVE_BOARD_LISTS_FAILURE = 'RECEIVE_BOARD_LISTS_FAILURE';
@@ -40,3 +40,8 @@ export const REQUEST_GROUP_PROJECTS = 'REQUEST_GROUP_PROJECTS';
export const RECEIVE_GROUP_PROJECTS_SUCCESS = 'RECEIVE_GROUP_PROJECTS_SUCCESS';
export const RECEIVE_GROUP_PROJECTS_FAILURE = 'RECEIVE_GROUP_PROJECTS_FAILURE';
export const SET_SELECTED_PROJECT = 'SET_SELECTED_PROJECT';
+export const ADD_BOARD_ITEM_TO_SELECTION = 'ADD_BOARD_ITEM_TO_SELECTION';
+export const REMOVE_BOARD_ITEM_FROM_SELECTION = 'REMOVE_BOARD_ITEM_FROM_SELECTION';
+export const SET_ADD_COLUMN_FORM_VISIBLE = 'SET_ADD_COLUMN_FORM_VISIBLE';
+export const ADD_LIST_TO_HIGHLIGHTED_LISTS = 'ADD_LIST_TO_HIGHLIGHTED_LISTS';
+export const REMOVE_LIST_FROM_HIGHLIGHTED_LISTS = 'REMOVE_LIST_FROM_HIGHLIGHTED_LISTS';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 6c79b22d308..79c98c3d90c 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -1,9 +1,9 @@
-import Vue from 'vue';
import { pull, union } from 'lodash';
+import Vue from 'vue';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { s__ } from '~/locale';
import { formatIssue, moveIssueListHelper } from '../boards_util';
import * as mutationTypes from './mutation_types';
-import { s__ } from '~/locale';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
@@ -63,8 +63,8 @@ export default {
state.error = s__('Boards|An error occurred while creating the list. Please try again.');
},
- [mutationTypes.RECEIVE_LABELS_FAILURE]: (state) => {
- state.error = s__('Boards|An error occurred while fetching labels. Please reload the page.');
+ [mutationTypes.RECEIVE_LABELS_SUCCESS]: (state, labels) => {
+ state.labels = labels;
},
[mutationTypes.GENERATE_DEFAULT_LISTS_FAILURE]: (state) => {
@@ -258,4 +258,28 @@ export default {
[mutationTypes.SET_SELECTED_PROJECT]: (state, project) => {
state.selectedProject = project;
},
+
+ [mutationTypes.ADD_BOARD_ITEM_TO_SELECTION]: (state, boardItem) => {
+ state.selectedBoardItems = [...state.selectedBoardItems, boardItem];
+ },
+
+ [mutationTypes.REMOVE_BOARD_ITEM_FROM_SELECTION]: (state, boardItem) => {
+ Vue.set(
+ state,
+ 'selectedBoardItems',
+ state.selectedBoardItems.filter((obj) => obj !== boardItem),
+ );
+ },
+
+ [mutationTypes.SET_ADD_COLUMN_FORM_VISIBLE]: (state, visible) => {
+ state.addColumnFormVisible = visible;
+ },
+
+ [mutationTypes.ADD_LIST_TO_HIGHLIGHTED_LISTS]: (state, listId) => {
+ state.highlightedLists.push(listId);
+ },
+
+ [mutationTypes.REMOVE_LIST_FROM_HIGHLIGHTED_LISTS]: (state, listId) => {
+ state.highlightedLists = state.highlightedLists.filter((id) => id !== listId);
+ },
};
diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js
index aba7da373cf..91544d6c9c5 100644
--- a/app/assets/javascripts/boards/stores/state.js
+++ b/app/assets/javascripts/boards/stores/state.js
@@ -14,6 +14,9 @@ export default () => ({
issues: {},
filterParams: {},
boardConfig: {},
+ labels: [],
+ highlightedLists: [],
+ selectedBoardItems: [],
groupProjects: [],
groupProjectsFlags: {
isLoading: false,
@@ -22,6 +25,7 @@ export default () => ({
},
selectedProject: {},
error: undefined,
+ addColumnFormVisible: false,
// TODO: remove after ce/ee split of board_content.vue
isShowingEpicsSwimlanes: false,
});
diff --git a/app/assets/javascripts/boards/toggle_focus.js b/app/assets/javascripts/boards/toggle_focus.js
index 347deb81846..0a230f72dcc 100644
--- a/app/assets/javascripts/boards/toggle_focus.js
+++ b/app/assets/javascripts/boards/toggle_focus.js
@@ -1,45 +1,17 @@
-import $ from 'jquery';
import Vue from 'vue';
-import { GlIcon } from '@gitlab/ui';
-import { hide } from '~/tooltips';
+import ToggleFocus from './components/toggle_focus.vue';
-export default (ModalStore, boardsStore) => {
- const issueBoardsContent = document.querySelector('.content-wrapper > .js-focus-mode-board');
+export default () => {
+ const issueBoardsContentSelector = '.content-wrapper > .js-focus-mode-board';
return new Vue({
- el: document.getElementById('js-toggle-focus-btn'),
- components: {
- GlIcon,
+ el: '#js-toggle-focus-btn',
+ render(h) {
+ return h(ToggleFocus, {
+ props: {
+ issueBoardsContentSelector,
+ },
+ });
},
- data: {
- modal: ModalStore.store,
- store: boardsStore.state,
- isFullscreen: false,
- },
- methods: {
- toggleFocusMode() {
- const $el = $(this.$refs.toggleFocusModeButton);
- hide($el);
-
- issueBoardsContent.classList.toggle('is-focused');
-
- this.isFullscreen = !this.isFullscreen;
- },
- },
- template: `
- <div class="board-extra-actions">
- <a
- href="#"
- class="btn btn-default has-tooltip gl-ml-3 js-focus-mode-btn"
- data-qa-selector="focus_mode_button"
- role="button"
- aria-label="Toggle focus mode"
- title="Toggle focus mode"
- ref="toggleFocusModeButton"
- @click="toggleFocusMode">
- <gl-icon :name="isFullscreen ? 'minimize' : 'maximize'" />
- </a>
- </div>
- `,
});
};
diff --git a/app/assets/javascripts/branches/components/divergence_graph.vue b/app/assets/javascripts/branches/components/divergence_graph.vue
index deaed694b46..c4b522a43d4 100644
--- a/app/assets/javascripts/branches/components/divergence_graph.vue
+++ b/app/assets/javascripts/branches/components/divergence_graph.vue
@@ -1,7 +1,7 @@
<script>
import { sprintf, __ } from '~/locale';
-import GraphBar from './graph_bar.vue';
import { MAX_COMMIT_COUNT } from '../constants';
+import GraphBar from './graph_bar.vue';
export default {
components: {
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
index a577bdca082..ca019bc4178 100644
--- a/app/assets/javascripts/branches/divergence_graph.js
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import { __ } from '../locale';
import { deprecatedCreateFlash as createFlash } from '../flash';
import axios from '../lib/utils/axios_utils';
+import { __ } from '../locale';
import DivergenceGraph from './components/divergence_graph.vue';
export function createGraphVueApp(el, data, maxCommits) {
diff --git a/app/assets/javascripts/build_artifacts.js b/app/assets/javascripts/build_artifacts.js
index 42e0f8b37bd..e895df01f2c 100644
--- a/app/assets/javascripts/build_artifacts.js
+++ b/app/assets/javascripts/build_artifacts.js
@@ -1,9 +1,9 @@
/* eslint-disable func-names */
import $ from 'jquery';
-import { visitUrl } from './lib/utils/url_utility';
-import { parseBoolean } from './lib/utils/common_utils';
import { hide, initTooltips, show } from '~/tooltips';
+import { parseBoolean } from './lib/utils/common_utils';
+import { visitUrl } from './lib/utils/url_utility';
export default class BuildArtifacts {
constructor() {
diff --git a/app/assets/javascripts/captcha/captcha_modal.vue b/app/assets/javascripts/captcha/captcha_modal.vue
new file mode 100644
index 00000000000..e6c73bc9643
--- /dev/null
+++ b/app/assets/javascripts/captcha/captcha_modal.vue
@@ -0,0 +1,110 @@
+<script>
+// NOTE 1: This is similar to recaptcha_modal.vue, but it directly uses the reCAPTCHA Javascript API
+// (https://developers.google.com/recaptcha/docs/display#js_api) and gl-modal, rather than relying
+// on the form-based ReCAPTCHA HTML being pre-rendered by the backend and using deprecated-modal.
+
+// NOTE 2: Even though this modal currently only supports reCAPTCHA, we use 'captcha' instead
+// of 'recaptcha' throughout the code, so that we can easily add support for future alternative
+// captcha implementations other than reCAPTCHA (e.g. FriendlyCaptcha) without having to
+// change the references in the code or API.
+
+import { GlModal } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { initRecaptchaScript } from '~/captcha/init_recaptcha_script';
+
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ needsCaptchaResponse: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ captchaSiteKey: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ modalId: uniqueId('captcha-modal-'),
+ };
+ },
+ watch: {
+ needsCaptchaResponse(newNeedsCaptchaResponse) {
+ // If this is true, we need to present the captcha modal to the user.
+ // When the modal is shown we will also initialize and render the form.
+ if (newNeedsCaptchaResponse) {
+ this.$refs.modal.show();
+ }
+ },
+ },
+ methods: {
+ emitReceivedCaptchaResponse(captchaResponse) {
+ this.$emit('receivedCaptchaResponse', captchaResponse);
+ this.$refs.modal.hide();
+ },
+ emitNullReceivedCaptchaResponse() {
+ this.emitReceivedCaptchaResponse(null);
+ },
+ /**
+ * handler for when modal is shown
+ */
+ shown() {
+ const containerRef = this.$refs.captcha;
+
+ // NOTE: This is the only bit that is specific to Google's reCAPTCHA captcha implementation.
+ initRecaptchaScript()
+ .then((grecaptcha) => {
+ grecaptcha.render(containerRef, {
+ sitekey: this.captchaSiteKey,
+ // This callback will emit and let the parent handle the response
+ callback: this.emitReceivedCaptchaResponse,
+ // TODO: Also need to handle expired-callback and error-callback
+ // See https://gitlab.com/gitlab-org/gitlab/-/issues/217722#future-follow-on-issuesmrs
+ });
+ })
+ .catch((e) => {
+ // TODO: flash the error or notify the user some other way
+ // See https://gitlab.com/gitlab-org/gitlab/-/issues/217722#future-follow-on-issuesmrs
+ this.emitNullReceivedCaptchaResponse();
+ this.$refs.modal.hide();
+
+ // eslint-disable-next-line no-console
+ console.error(
+ '[gitlab] an unexpected exception was caught while initializing captcha',
+ e,
+ );
+ });
+ },
+ /**
+ * handler for when modal is about to hide
+ */
+ hide(bvModalEvent) {
+ // If hide() was called without any argument, the value of trigger will be null.
+ // See https://bootstrap-vue.org/docs/components/modal#prevent-closing
+ if (bvModalEvent.trigger) {
+ this.emitNullReceivedCaptchaResponse();
+ }
+ },
+ },
+};
+</script>
+<template>
+ <!-- Note: The action-cancel button isn't necessary for the functionality of the modal, but -->
+ <!-- there must be at least one button or focusable element, or the gl-modal fails to render. -->
+ <!-- We could modify gl-model to remove this requirement. -->
+ <gl-modal
+ ref="modal"
+ :modal-id="modalId"
+ :title="__('Please solve the captcha')"
+ :action-cancel="{ text: __('Cancel') }"
+ @shown="shown"
+ @hide="hide"
+ >
+ <div ref="captcha"></div>
+ <p>{{ __('We want to be sure it is you, please confirm you are not a robot.') }}</p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/captcha/init_recaptcha_script.js b/app/assets/javascripts/captcha/init_recaptcha_script.js
new file mode 100644
index 00000000000..f546eef7d84
--- /dev/null
+++ b/app/assets/javascripts/captcha/init_recaptcha_script.js
@@ -0,0 +1,48 @@
+// NOTE: This module will be used in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52044
+import { memoize } from 'lodash';
+
+export const RECAPTCHA_API_URL_PREFIX = 'https://www.google.com/recaptcha/api.js';
+export const RECAPTCHA_ONLOAD_CALLBACK_NAME = 'recaptchaOnloadCallback';
+
+/**
+ * Adds the Google reCAPTCHA script tag to the head of the document, and
+ * returns a promise of the grecaptcha object
+ * (https://developers.google.com/recaptcha/docs/display#js_api).
+ *
+ * It is memoized, so there will only be one instance of the script tag ever
+ * added to the document.
+ *
+ * See the reCAPTCHA documentation for more details:
+ *
+ * https://developers.google.com/recaptcha/docs/display#explicit_render
+ *
+ */
+export const initRecaptchaScript = memoize(() => {
+ // Appends the the reCAPTCHA script tag to the head of document
+ const appendRecaptchaScript = () => {
+ const script = document.createElement('script');
+ script.src = `${RECAPTCHA_API_URL_PREFIX}?onload=${RECAPTCHA_ONLOAD_CALLBACK_NAME}&render=explicit`;
+ script.classList.add('js-recaptcha-script');
+ document.head.appendChild(script);
+ };
+
+ return new Promise((resolve) => {
+ // This global callback resolves the Promise and is passed by name to the reCAPTCHA script.
+ window[RECAPTCHA_ONLOAD_CALLBACK_NAME] = () => {
+ // Let's clean up after ourselves. This is also important for testing, because `window` is NOT cleared between tests.
+ // https://github.com/facebook/jest/issues/1224#issuecomment-444586798.
+ delete window[RECAPTCHA_ONLOAD_CALLBACK_NAME];
+ resolve(window.grecaptcha);
+ };
+ appendRecaptchaScript();
+ });
+});
+
+/**
+ * Clears the cached memoization of the default manager.
+ *
+ * This is needed for determinism in tests.
+ */
+export const clearMemoizeCache = () => {
+ initRecaptchaScript.cache.clear();
+};
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint.vue b/app/assets/javascripts/ci_lint/components/ci_lint.vue
index fc47fe8c333..9a55177b15f 100644
--- a/app/assets/javascripts/ci_lint/components/ci_lint.vue
+++ b/app/assets/javascripts/ci_lint/components/ci_lint.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton, GlFormCheckbox, GlIcon, GlLink, GlAlert } from '@gitlab/ui';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
import lintCiMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
index b84c188cd08..0233ffaccdc 100644
--- a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
+++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue
@@ -2,9 +2,9 @@
import { GlTable, GlButton, GlBadge, GlTooltipDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/index.js b/app/assets/javascripts/ci_settings_pipeline_triggers/index.js
index dc79bbb4d97..f2972133aad 100644
--- a/app/assets/javascripts/ci_settings_pipeline_triggers/index.js
+++ b/app/assets/javascripts/ci_settings_pipeline_triggers/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import TriggersList from './components/triggers_list.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import TriggersList from './components/triggers_list.vue';
const parseJsonArray = (triggers) => {
try {
diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
index aa4d311527e..065cb4f5616 100644
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
+import SecretValues from '../behaviors/secret_values';
+import CreateItemDropdown from '../create_item_dropdown';
import { parseBoolean } from '../lib/utils/common_utils';
import { s__ } from '../locale';
import setupToggleButtons from '../toggle_buttons';
-import CreateItemDropdown from '../create_item_dropdown';
-import SecretValues from '../behaviors/secret_values';
const ALL_ENVIRONMENTS_STRING = s__('CiVariable|All environments');
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 da816f85466..af4349083b6 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
@@ -15,17 +15,17 @@ import {
} from '@gitlab/ui';
import Cookies from 'js-cookie';
import { mapActions, mapState } from 'vuex';
-import { mapComputed } from '~/vuex_shared/bindings';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { mapComputed } from '~/vuex_shared/bindings';
import {
AWS_TOKEN_CONSTANTS,
ADD_CI_VARIABLE_MODAL_ID,
AWS_TIP_DISMISSED_COOKIE_NAME,
AWS_TIP_MESSAGE,
} from '../constants';
-import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
+import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
export default {
modalId: ADD_CI_VARIABLE_MODAL_ID,
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue
index 431819124c2..6e6527df63f 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_popover.vue
@@ -38,7 +38,9 @@ export default {
<template>
<div id="popover-container">
<gl-popover :target="target" triggers="hover" placement="top" container="popover-container">
- <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-word-break-all"
+ >
<div class="ci-popover-value gl-pr-3">
{{ displayValue }}
</div>
diff --git a/app/assets/javascripts/ci_variable_list/index.js b/app/assets/javascripts/ci_variable_list/index.js
index a28b52d6b57..37b5f7e6df7 100644
--- a/app/assets/javascripts/ci_variable_list/index.js
+++ b/app/assets/javascripts/ci_variable_list/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
import CiVariableSettings from './components/ci_variable_settings.vue';
import createStore from './store';
-import { parseBoolean } from '~/lib/utils/common_utils';
export default (containerId = 'js-ci-project-variables') => {
const containerEl = document.getElementById(containerId);
diff --git a/app/assets/javascripts/ci_variable_list/store/actions.js b/app/assets/javascripts/ci_variable_list/store/actions.js
index ac595fa0045..8569cecc6a7 100644
--- a/app/assets/javascripts/ci_variable_list/store/actions.js
+++ b/app/assets/javascripts/ci_variable_list/store/actions.js
@@ -1,8 +1,8 @@
-import * as types from './mutation_types';
-import axios from '~/lib/utils/axios_utils';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import * as types from './mutation_types';
import { prepareDataForApi, prepareDataForDisplay, prepareEnvironments } from './utils';
export const toggleValues = ({ commit }, valueState) => {
diff --git a/app/assets/javascripts/ci_variable_list/store/mutations.js b/app/assets/javascripts/ci_variable_list/store/mutations.js
index 961cecee298..0e7c61cecb8 100644
--- a/app/assets/javascripts/ci_variable_list/store/mutations.js
+++ b/app/assets/javascripts/ci_variable_list/store/mutations.js
@@ -1,5 +1,5 @@
-import * as types from './mutation_types';
import { displayText } from '../constants';
+import * as types from './mutation_types';
export default {
[types.REQUEST_VARIABLES](state) {
diff --git a/app/assets/javascripts/clone_panel.js b/app/assets/javascripts/clone_panel.js
index 00bf54e1478..c9fae8f17a4 100644
--- a/app/assets/javascripts/clone_panel.js
+++ b/app/assets/javascripts/clone_panel.js
@@ -18,6 +18,11 @@ export default function initClonePanel() {
e.preventDefault();
const $this = $(e.currentTarget);
const url = $this.attr('href');
+ if (url && (url.startsWith('vscode://') || url.startsWith('xcode://'))) {
+ // Clone with "..." should open like a normal link
+ return;
+ }
+ e.preventDefault();
const cloneType = $this.data('cloneType');
$('.is-active', $cloneOptions).removeClass('is-active');
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index eb2128b2856..5cb3d913210 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,20 +1,20 @@
+import { GlToast } from '@gitlab/ui';
import Visibility from 'visibilityjs';
import Vue from 'vue';
-import { GlToast } from '@gitlab/ui';
import AccessorUtilities from '~/lib/utils/accessor';
-import PersistentUserCallout from '../persistent_user_callout';
-import { s__, sprintf } from '../locale';
+import initProjectSelectDropdown from '~/project_select';
+import initServerlessSurveyBanner from '~/serverless/survey_banner';
import { deprecatedCreateFlash as Flash } from '../flash';
import Poll from '../lib/utils/poll';
+import { s__, sprintf } from '../locale';
+import PersistentUserCallout from '../persistent_user_callout';
import initSettingsPanels from '../settings_panels';
-import eventHub from './event_hub';
+import Applications from './components/applications.vue';
+import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
import { APPLICATION_STATUS, CROSSPLANE, KNATIVE, FLUENTD } from './constants';
+import eventHub from './event_hub';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
-import Applications from './components/applications.vue';
-import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
-import initProjectSelectDropdown from '~/project_select';
-import initServerlessSurveyBanner from '~/serverless/survey_banner';
const Environments = () => import('ee_component/clusters/components/environments.vue');
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index 471c1a0b4a2..76fe076d4ff 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -1,14 +1,13 @@
<script>
import { GlLink, GlModalDirective, GlSprintf, GlButton, GlAlert } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
-import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
+import { APPLICATION_STATUS, ELASTIC_STACK } from '../constants';
+import eventHub from '../event_hub';
import UninstallApplicationButton from './uninstall_application_button.vue';
import UninstallApplicationConfirmationModal from './uninstall_application_confirmation_modal.vue';
import UpdateApplicationConfirmationModal from './update_application_confirmation_modal.vue';
-import { APPLICATION_STATUS, ELASTIC_STACK } from '../constants';
-
export default {
components: {
GlButton,
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index e096a29ce7f..8ef3169dc65 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -1,23 +1,23 @@
<script>
import { GlLoadingIcon, GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
+import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
+import crossplaneLogo from 'images/cluster_app_logos/crossplane.png';
+import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png';
+import fluentdLogo from 'images/cluster_app_logos/fluentd.png';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
import helmLogo from 'images/cluster_app_logos/helm.png';
import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
-import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png';
-import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
-import crossplaneLogo from 'images/cluster_app_logos/crossplane.png';
import knativeLogo from 'images/cluster_app_logos/knative.png';
+import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png';
import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
-import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png';
-import fluentdLogo from 'images/cluster_app_logos/fluentd.png';
-import applicationRow from './application_row.vue';
+import eventHub from '~/clusters/event_hub';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
-import KnativeDomainEditor from './knative_domain_editor.vue';
import { CLUSTER_TYPE, PROVIDER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
-import eventHub from '~/clusters/event_hub';
+import applicationRow from './application_row.vue';
import CrossplaneProviderStack from './crossplane_provider_stack.vue';
-import IngressModsecuritySettings from './ingress_modsecurity_settings.vue';
import FluentdOutputSettings from './fluentd_output_settings.vue';
+import IngressModsecuritySettings from './ingress_modsecurity_settings.vue';
+import KnativeDomainEditor from './knative_domain_editor.vue';
export default {
components: {
@@ -349,6 +349,7 @@ export default {
{{ s__('ClusterIntegration|Issuer Email') }}
</label>
<div class="input-group">
+ <!-- eslint-disable vue/no-mutating-props -->
<input
id="cert-manager-issuer-email"
v-model="applications.cert_manager.email"
@@ -356,6 +357,7 @@ export default {
type="text"
class="form-control js-email"
/>
+ <!-- eslint-enable vue/no-mutating-props -->
</div>
<p class="form-text text-muted">
{{
@@ -522,6 +524,7 @@ export default {
<label for="jupyter-hostname">{{ s__('ClusterIntegration|Jupyter Hostname') }}</label>
<div class="input-group">
+ <!-- eslint-disable vue/no-mutating-props -->
<input
id="jupyter-hostname"
v-model="applications.jupyter.hostname"
@@ -529,6 +532,7 @@ export default {
type="text"
class="form-control js-hostname"
/>
+ <!-- eslint-enable vue/no-mutating-props -->
<span class="input-group-append">
<clipboard-button
:text="jupyterHostname"
diff --git a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
index 84a39874000..369cb2fa0f3 100644
--- a/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
+++ b/app/assets/javascripts/clusters/components/fluentd_output_settings.vue
@@ -1,9 +1,9 @@
<script>
import { GlAlert, GlButton, GlDropdown, GlDropdownItem, GlFormCheckbox } from '@gitlab/ui';
import { mapValues } from 'lodash';
-import { __ } from '~/locale';
import { APPLICATION_STATUS, FLUENTD } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
+import { __ } from '~/locale';
const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
index f05c8db5d56..26767c32275 100644
--- a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
+++ b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
@@ -1,5 +1,4 @@
<script>
-import { escape } from 'lodash';
import {
GlAlert,
GlSprintf,
@@ -10,10 +9,11 @@ import {
GlDropdownItem,
GlIcon,
} from '@gitlab/ui';
+import { escape } from 'lodash';
import modSecurityLogo from 'images/cluster_app_logos/gitlab.png';
-import { s__, __ } from '../../locale';
import { APPLICATION_STATUS, INGRESS, LOGGING_MODE, BLOCKING_MODE } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
+import { s__, __ } from '../../locale';
const { UPDATING, UNINSTALLING, INSTALLING, INSTALLED, UPDATED } = APPLICATION_STATUS;
@@ -130,9 +130,11 @@ export default {
},
resetStatus() {
if (this.initialMode !== null) {
+ // eslint-disable-next-line vue/no-mutating-props
this.ingress.modsecurity_mode = this.initialMode;
}
if (this.initialValue !== null) {
+ // eslint-disable-next-line vue/no-mutating-props
this.ingress.modsecurity_enabled = this.initialValue;
}
this.initialValue = null;
diff --git a/app/assets/javascripts/clusters/components/knative_domain_editor.vue b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
index d80bd6f5b42..89446680173 100644
--- a/app/assets/javascripts/clusters/components/knative_domain_editor.vue
+++ b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
@@ -9,10 +9,10 @@ import {
GlButton,
GlAlert,
} from '@gitlab/ui';
-import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import { APPLICATION_STATUS } from '~/clusters/constants';
import { __, s__ } from '~/locale';
-import { APPLICATION_STATUS } from '~/clusters/constants';
+import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index c157b04b4f5..5cd9baf2c2b 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -1,10 +1,10 @@
<script>
/* eslint-disable vue/no-v-html */
-import { escape } from 'lodash';
import { GlModal, GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
-import SplitButton from '~/vue_shared/components/split_button.vue';
-import { s__, sprintf } from '~/locale';
+import { escape } from 'lodash';
import csrf from '~/lib/utils/csrf';
+import { s__, sprintf } from '~/locale';
+import SplitButton from '~/vue_shared/components/split_button.vue';
const splitButtonActionItems = [
{
@@ -131,48 +131,46 @@ export default {
:title="modalTitle"
kind="danger"
>
- <template>
- <p>{{ warningMessage }}</p>
- <div v-if="confirmCleanup">
- {{ s__('ClusterIntegration|This will permanently delete the following resources:') }}
- <ul>
- <li>
- {{ s__('ClusterIntegration|All installed applications and related resources') }}
- </li>
- <li>
- <gl-sprintf :message="s__('ClusterIntegration|The %{gitlabNamespace} namespace')">
- <template #gitlabNamespace>
- <!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
- <code>{{ 'gitlab-managed-apps' }}</code>
- </template>
- </gl-sprintf>
- </li>
- <li>{{ s__('ClusterIntegration|Any project namespaces') }}</li>
- <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
- <li><code>clusterroles</code></li>
- <li><code>clusterrolebindings</code></li>
- <!-- eslint-enable @gitlab/vue-require-i18n-strings -->
- </ul>
- </div>
- <strong v-html="confirmationTextLabel"></strong>
- <form ref="form" :action="clusterPath" method="post" class="gl-mb-5">
- <input ref="method" type="hidden" name="_method" value="delete" />
- <input :value="csrfToken" type="hidden" name="authenticity_token" />
- <input ref="cleanup" type="hidden" name="cleanup" value="true" />
- <gl-form-input
- v-model="enteredClusterName"
- autofocus
- type="text"
- name="confirm_cluster_name_input"
- autocomplete="off"
- />
- </form>
- <span v-if="confirmCleanup">{{
- s__(
- 'ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration.',
- )
- }}</span>
- </template>
+ <p>{{ warningMessage }}</p>
+ <div v-if="confirmCleanup">
+ {{ s__('ClusterIntegration|This will permanently delete the following resources:') }}
+ <ul>
+ <li>
+ {{ s__('ClusterIntegration|All installed applications and related resources') }}
+ </li>
+ <li>
+ <gl-sprintf :message="s__('ClusterIntegration|The %{gitlabNamespace} namespace')">
+ <template #gitlabNamespace>
+ <!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
+ <code>{{ 'gitlab-managed-apps' }}</code>
+ </template>
+ </gl-sprintf>
+ </li>
+ <li>{{ s__('ClusterIntegration|Any project namespaces') }}</li>
+ <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
+ <li><code>clusterroles</code></li>
+ <li><code>clusterrolebindings</code></li>
+ <!-- eslint-enable @gitlab/vue-require-i18n-strings -->
+ </ul>
+ </div>
+ <strong v-html="confirmationTextLabel"></strong>
+ <form ref="form" :action="clusterPath" method="post" class="gl-mb-5">
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
+ <input ref="cleanup" type="hidden" name="cleanup" value="true" />
+ <gl-form-input
+ v-model="enteredClusterName"
+ autofocus
+ type="text"
+ name="confirm_cluster_name_input"
+ autocomplete="off"
+ />
+ </form>
+ <span v-if="confirmCleanup">{{
+ s__(
+ 'ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration.',
+ )
+ }}</span>
<template #modal-footer>
<gl-button variant="secondary" @click="handleCancel">{{ s__('Cancel') }}</gl-button>
<template v-if="confirmCleanup">
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index 5de487308c5..d45696c98c2 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -1,5 +1,5 @@
-import { s__ } from '../../locale';
import { parseBoolean } from '../../lib/utils/common_utils';
+import { s__ } from '../../locale';
import {
INGRESS,
JUPYTER,
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index 53eec5c8a0d..8f81d967126 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState, mapActions } from 'vuex';
import {
GlBadge,
GlLink,
@@ -10,10 +9,11 @@ import {
GlTable,
GlTooltipDirective,
} from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { __, sprintf } from '~/locale';
+import { CLUSTER_TYPES, STATUSES } from '../constants';
import AncestorNotice from './ancestor_notice.vue';
import NodeErrorHelpText from './node_error_help_text.vue';
-import { CLUSTER_TYPES, STATUSES } from '../constants';
-import { __, sprintf } from '~/locale';
export default {
nodeMemoryText: __('%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)'),
diff --git a/app/assets/javascripts/clusters_list/store/actions.js b/app/assets/javascripts/clusters_list/store/actions.js
index 97ed0a7ab37..45d3e0cbc23 100644
--- a/app/assets/javascripts/clusters_list/store/actions.js
+++ b/app/assets/javascripts/clusters_list/store/actions.js
@@ -1,10 +1,10 @@
-import * as Sentry from '~/sentry/wrapper';
-import Poll from '~/lib/utils/poll';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
+import * as Sentry from '~/sentry/wrapper';
import { MAX_REQUESTS } from '../constants';
-import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import * as types from './mutation_types';
const allNodesPresent = (clusters, retryCount) => {
diff --git a/app/assets/javascripts/clusters_list/store/index.js b/app/assets/javascripts/clusters_list/store/index.js
index 47e17b3624b..7cdd93eeae9 100644
--- a/app/assets/javascripts/clusters_list/store/index.js
+++ b/app/assets/javascripts/clusters_list/store/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/code_navigation/components/app.vue b/app/assets/javascripts/code_navigation/components/app.vue
index 85ec0a60ec5..d38b38947b6 100644
--- a/app/assets/javascripts/code_navigation/components/app.vue
+++ b/app/assets/javascripts/code_navigation/components/app.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapState } from 'vuex';
-import Popover from './popover.vue';
import eventHub from '../../notes/event_hub';
+import Popover from './popover.vue';
export default {
components: {
diff --git a/app/assets/javascripts/code_navigation/index.js b/app/assets/javascripts/code_navigation/index.js
index 38b3467dc33..83906245b81 100644
--- a/app/assets/javascripts/code_navigation/index.js
+++ b/app/assets/javascripts/code_navigation/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createStore from './store';
import App from './components/app.vue';
+import createStore from './store';
export default (initialData) => {
const el = document.getElementById('js-code-navigation');
diff --git a/app/assets/javascripts/code_navigation/store/actions.js b/app/assets/javascripts/code_navigation/store/actions.js
index fb77a70de0b..0b6b8437db5 100644
--- a/app/assets/javascripts/code_navigation/store/actions.js
+++ b/app/assets/javascripts/code_navigation/store/actions.js
@@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
-import * as types from './mutation_types';
import { getCurrentHoverElement, setCurrentHoverElement, addInteractionClass } from '../utils';
+import * as types from './mutation_types';
export default {
setInitialData({ commit }, data) {
diff --git a/app/assets/javascripts/code_navigation/store/index.js b/app/assets/javascripts/code_navigation/store/index.js
index 9b60fc337fe..6b448bc5fb7 100644
--- a/app/assets/javascripts/code_navigation/store/index.js
+++ b/app/assets/javascripts/code_navigation/store/index.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
-import createState from './state';
import actions from './actions';
import mutations from './mutations';
+import createState from './state';
export default () =>
new Vuex.Store({
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index 24033634aad..920ffde3e32 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import commitPipelinesTable from './pipelines_table.vue';
+import CommitPipelinesTable from './pipelines_table.vue';
/**
* Used in:
@@ -8,14 +8,6 @@ import commitPipelinesTable from './pipelines_table.vue';
* - Merge Request details View > Pipelines Tab > Pipelines Table (projects:merge_requests:show)
* - New Merge Request View > Pipelines Tab > Pipelines Table (projects:merge_requests:creations:new)
*/
-
-const CommitPipelinesTable = Vue.extend(commitPipelinesTable);
-
-// export for use in merge_request_tabs.js (TODO: remove this hack when we understand how to load
-// vue.js in merge_request_tabs.js)
-window.gl = window.gl || {};
-window.gl.CommitPipelinesTable = CommitPipelinesTable;
-
export default () => {
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
@@ -34,13 +26,17 @@ export default () => {
});
if (pipelineTableViewEl.dataset.disableInitialization === undefined) {
- const table = new CommitPipelinesTable({
- propsData: {
- endpoint: pipelineTableViewEl.dataset.endpoint,
- helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
- emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
- errorStateSvgPath: pipelineTableViewEl.dataset.errorStateSvgPath,
- autoDevopsHelpPath: pipelineTableViewEl.dataset.helpAutoDevopsPath,
+ const table = new Vue({
+ render(createElement) {
+ return createElement(CommitPipelinesTable, {
+ props: {
+ endpoint: pipelineTableViewEl.dataset.endpoint,
+ helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
+ emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
+ errorStateSvgPath: pipelineTableViewEl.dataset.errorStateSvgPath,
+ autoDevopsHelpPath: pipelineTableViewEl.dataset.helpAutoDevopsPath,
+ },
+ });
},
}).$mount();
pipelineTableViewEl.appendChild(table.$el);
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index fe32868e6d8..787152d00ef 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -1,22 +1,25 @@
<script>
import { GlButton, GlLoadingIcon, GlModal, GlLink } from '@gitlab/ui';
+import { getParameterByName } from '~/lib/utils/common_utils';
+import SvgBlankState from '~/pipelines/components/pipelines_list/blank_state.vue';
+import PipelinesTableComponent from '~/pipelines/components/pipelines_list/pipelines_table.vue';
+import eventHub from '~/pipelines/event_hub';
+import PipelinesMixin from '~/pipelines/mixins/pipelines_mixin';
import PipelinesService from '~/pipelines/services/pipelines_service';
import PipelineStore from '~/pipelines/stores/pipelines_store';
-import pipelinesMixin from '~/pipelines/mixins/pipelines';
-import eventHub from '~/pipelines/event_hub';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
-import { getParameterByName } from '~/lib/utils/common_utils';
-import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
export default {
components: {
- TablePagination,
GlButton,
+ GlLink,
GlLoadingIcon,
GlModal,
- GlLink,
+ PipelinesTableComponent,
+ TablePagination,
+ SvgBlankState,
},
- mixins: [pipelinesMixin, CIPaginationMixin],
+ mixins: [PipelinesMixin],
props: {
endpoint: {
type: String,
@@ -197,7 +200,7 @@ export default {
<gl-button
v-if="canRenderPipelineButton"
block
- class="gl-mt-3 gl-mb-0 gl-display-md-none"
+ class="gl-mt-3 gl-mb-0 gl-md-display-none"
variant="success"
data-testid="run_pipeline_button_mobile"
:loading="state.isRunningMergeRequestPipeline"
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index f82bea134a3..5cbe9a24fc4 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import { n__ } from '~/locale';
+import axios from './lib/utils/axios_utils';
import { localTimeAgo } from './lib/utils/datetime_utility';
import Pager from './pager';
-import axios from './lib/utils/axios_utils';
export default class CommitsList {
constructor(limit = 0) {
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js
index 82384434e8f..314e4e911ee 100644
--- a/app/assets/javascripts/compare_autocomplete.js
+++ b/app/assets/javascripts/compare_autocomplete.js
@@ -1,12 +1,12 @@
/* eslint-disable func-names */
import $ from 'jquery';
-import { __ } from './locale';
-import axios from './lib/utils/axios_utils';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { fixTitle } from '~/tooltips';
import { deprecatedCreateFlash as flash } from './flash';
+import axios from './lib/utils/axios_utils';
import { capitalizeFirstCharacter } from './lib/utils/text_utility';
-import { fixTitle } from '~/tooltips';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from './locale';
export default function initCompareAutocomplete(limitTo = null, clickHandler = () => {}) {
$('.js-compare-dropdown').each(function () {
diff --git a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
index 58fe022b794..2f39bbacc7d 100644
--- a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
+++ b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
@@ -1,8 +1,8 @@
<script>
import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
-import { __ } from '../../locale';
-import { deprecatedCreateFlash as createFlash } from '../../flash';
import Api from '../../api';
+import { deprecatedCreateFlash as createFlash } from '../../flash';
+import { __ } from '../../locale';
import state from '../state';
import Dropdown from './dropdown.vue';
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index f7d24c70864..08cf0197993 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -1,7 +1,7 @@
+import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import { debounce } from 'lodash';
import Cookies from 'js-cookie';
-import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils';
+import { debounce } from 'lodash';
import { parseBoolean } from '~/lib/utils/common_utils';
export const SIDEBAR_COLLAPSED_CLASS = 'js-sidebar-collapsed';
diff --git a/app/assets/javascripts/contributors/components/contributors.vue b/app/assets/javascripts/contributors/components/contributors.vue
index 86580aa170b..7426e570864 100644
--- a/app/assets/javascripts/contributors/components/contributors.vue
+++ b/app/assets/javascripts/contributors/components/contributors.vue
@@ -1,13 +1,13 @@
<script>
-import { debounce, uniq } from 'lodash';
-import { mapActions, mapState, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
-import { __ } from '~/locale';
-import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
+import { debounce, uniq } from 'lodash';
+import { mapActions, mapState, mapGetters } from 'vuex';
import { getDatesInRange } from '~/lib/utils/datetime_utility';
-import { xAxisLabelFormatter, dateFormatter } from '../utils';
+import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
+import { __ } from '~/locale';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
+import { xAxisLabelFormatter, dateFormatter } from '../utils';
export default {
components: {
diff --git a/app/assets/javascripts/contributors/stores/index.js b/app/assets/javascripts/contributors/stores/index.js
index bc739851aa7..38259f46d4c 100644
--- a/app/assets/javascripts/contributors/stores/index.js
+++ b/app/assets/javascripts/contributors/stores/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from './state';
-import mutations from './mutations';
-import * as getters from './getters';
import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue b/app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue
index 7f4c3635119..fa0a17f3643 100644
--- a/app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/components/cluster_form_dropdown.vue
@@ -1,10 +1,10 @@
<script>
-import { isNil } from 'lodash';
-import $ from 'jquery';
import { GlIcon } from '@gitlab/ui';
-import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
-import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
+import $ from 'jquery';
+import { isNil } from 'lodash';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
+import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
+import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
const toArray = (value) => (isNil(value) ? [] : [].concat(value));
const itemsProp = (items, prop) => items.map((item) => item[prop]);
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue
index eb195ad2b30..ba170dc0e19 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue
@@ -1,7 +1,7 @@
<script>
import { mapState } from 'vuex';
-import ServiceCredentialsForm from './service_credentials_form.vue';
import EksClusterConfigurationForm from './eks_cluster_configuration_form.vue';
+import ServiceCredentialsForm from './service_credentials_form.vue';
export default {
components: {
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index a7425735733..4aee02e45c8 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -1,5 +1,4 @@
<script>
-import { createNamespacedHelpers, mapState, mapActions, mapGetters } from 'vuex';
import {
GlFormGroup,
GlFormInput,
@@ -9,8 +8,9 @@ import {
GlSprintf,
GlButton,
} from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { createNamespacedHelpers, mapState, mapActions, mapGetters } from 'vuex';
import ClusterFormDropdown from '~/create_cluster/components/cluster_form_dropdown.vue';
+import { s__ } from '~/locale';
import { KUBERNETES_VERSIONS } from '../constants';
const { mapState: mapRolesState, mapActions: mapRolesActions } = createNamespacedHelpers('roles');
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
index a3f76241bf2..f104eb61e41 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
@@ -1,11 +1,11 @@
<script>
/* eslint-disable vue/no-v-html */
-import { GlButton, GlFormGroup, GlFormInput, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormInput, GlIcon, GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapState, mapActions } from 'vuex';
-import { DEFAULT_REGION } from '../constants';
import { sprintf, s__, __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { DEFAULT_REGION } from '../constants';
export default {
components: {
@@ -16,6 +16,7 @@ export default {
GlLink,
GlSprintf,
ClipboardButton,
+ GlAlert,
},
props: {
accountAndExternalIdsHelpPath: {
@@ -105,9 +106,14 @@ export default {
)
}}
</p>
- <div v-if="createRoleError" class="js-invalid-credentials bs-callout bs-callout-danger">
+ <gl-alert
+ v-if="createRoleError"
+ class="js-invalid-credentials gl-mb-5"
+ variant="danger"
+ :dismissible="false"
+ >
{{ createRoleError }}
- </div>
+ </gl-alert>
<div class="form-row">
<div class="form-group col-md-6">
<label for="gitlab-account-id">{{ __('Account ID') }}</label>
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js b/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js
index c2b59191997..bd9554521b8 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/services/aws_services_facade.js
@@ -1,6 +1,6 @@
-import AWS from 'aws-sdk/global';
import EC2 from 'aws-sdk/clients/ec2';
import IAM from 'aws-sdk/clients/iam';
+import AWS from 'aws-sdk/global';
const lookupVpcName = ({ Tags: tags, VpcId: id }) => {
const nameTag = tags.find(({ Key: key }) => key === 'Name');
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
index 55576efd3b8..8b7c93ad880 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
@@ -1,9 +1,9 @@
-import * as types from './mutation_types';
-import { DEFAULT_REGION } from '../constants';
-import { setAWSConfig } from '../services/aws_services_facade';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { DEFAULT_REGION } from '../constants';
+import { setAWSConfig } from '../services/aws_services_facade';
+import * as types from './mutation_types';
const getErrorMessage = (data) => {
const errorKey = Object.keys(data)[0];
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/index.js b/app/assets/javascripts/create_cluster/eks_cluster/store/index.js
index 262bbb3167a..ed054989771 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/index.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/index.js
@@ -1,11 +1,5 @@
import Vuex from 'vuex';
-import * as actions from './actions';
-import * as getters from './getters';
-import mutations from './mutations';
-import state from './state';
-
import clusterDropdownStore from '~/create_cluster/store/cluster_dropdown';
-
import {
fetchRoles,
fetchKeyPairs,
@@ -13,6 +7,10 @@ import {
fetchSubnets,
fetchSecurityGroups,
} from '../services/aws_services_facade';
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
const createStore = ({ initialState }) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js
index f9d0d86e381..1246fdb19d7 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js
@@ -1,7 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
-import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
+import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
+import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import store from '../store';
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
index acbc4d1b3bc..b6f0bdbf01d 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapGetters, mapActions } from 'vuex';
import { GlSprintf, GlLink, GlIcon } from '@gitlab/ui';
+import { mapState, mapGetters, mapActions } from 'vuex';
import { s__ } from '~/locale';
import gkeDropdownMixin from './gke_dropdown_mixin';
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/index.js b/app/assets/javascripts/create_cluster/gke_cluster/index.js
index c02173fc510..4eafbdb7265 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/index.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/index.js
@@ -1,15 +1,14 @@
import Vue from 'vue';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import GkeProjectIdDropdown from './components/gke_project_id_dropdown.vue';
-import GkeZoneDropdown from './components/gke_zone_dropdown.vue';
import GkeMachineTypeDropdown from './components/gke_machine_type_dropdown.vue';
+import GkeProjectIdDropdown from './components/gke_project_id_dropdown.vue';
import GkeSubmitButton from './components/gke_submit_button.vue';
+import GkeZoneDropdown from './components/gke_zone_dropdown.vue';
+import * as CONSTANTS from './constants';
import gapiLoader from './gapi_loader';
import store from './store';
-import * as CONSTANTS from './constants';
-
const mountComponent = (entryPoint, component, componentName, extraProps = {}) => {
const el = document.querySelector(entryPoint);
if (!el) return false;
diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
index 8977053297a..f4c35dafc22 100644
--- a/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js
@@ -1,5 +1,5 @@
-import * as types from './mutation_types';
import gapiLoader from '../gapi_loader';
+import * as types from './mutation_types';
const gapiResourceListRequest = ({ resource, params, commit, mutation, payloadKey }) =>
new Promise((resolve, reject) => {
diff --git a/app/assets/javascripts/create_cluster/init_create_cluster.js b/app/assets/javascripts/create_cluster/init_create_cluster.js
index f97da3d55db..d367d7ec333 100644
--- a/app/assets/javascripts/create_cluster/init_create_cluster.js
+++ b/app/assets/javascripts/create_cluster/init_create_cluster.js
@@ -1,6 +1,6 @@
+import PersistentUserCallout from '~/persistent_user_callout';
import initGkeDropdowns from './gke_cluster';
import initGkeNamespace from './gke_cluster_namespace';
-import PersistentUserCallout from '~/persistent_user_callout';
const newClusterViews = [':clusters:new', ':clusters:create_gcp', ':clusters:create_user'];
diff --git a/app/assets/javascripts/create_cluster/store/cluster_dropdown/index.js b/app/assets/javascripts/create_cluster/store/cluster_dropdown/index.js
index 0b19589215c..de8cc44fa7c 100644
--- a/app/assets/javascripts/create_cluster/store/cluster_dropdown/index.js
+++ b/app/assets/javascripts/create_cluster/store/cluster_dropdown/index.js
@@ -1,5 +1,5 @@
-import * as getters from './getters';
import actions from './actions';
+import * as getters from './getters';
import mutations from './mutations';
import state from './state';
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index aaaa7055799..35176c19f69 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -1,16 +1,16 @@
/* eslint-disable no-new */
import { debounce } from 'lodash';
-import axios from './lib/utils/axios_utils';
-import { deprecatedCreateFlash as Flash } from './flash';
-import DropLab from './droplab/drop_lab';
-import ISetter from './droplab/plugins/input_setter';
-import { __, sprintf } from './locale';
import {
init as initConfidentialMergeRequest,
isConfidentialIssue,
canCreateConfidentialMergeRequest,
} from './confidential_merge_request';
import confidentialMergeRequestState from './confidential_merge_request/state';
+import DropLab from './droplab/drop_lab';
+import ISetter from './droplab/plugins/input_setter';
+import { deprecatedCreateFlash as Flash } from './flash';
+import axios from './lib/utils/axios_utils';
+import { __, sprintf } from './locale';
// Todo: Remove this when fixing issue in input_setter plugin
const InputSetter = { ...ISetter };
diff --git a/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue b/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue
index 9c28801306c..3158ae9b126 100644
--- a/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue
+++ b/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue
@@ -1,10 +1,10 @@
<script>
import { GlButton } from '@gitlab/ui';
-import { __, s__ } from '~/locale';
import csrf from '~/lib/utils/csrf';
+import { __, s__ } from '~/locale';
+import { formDataValidator } from '../constants';
import CustomMetricsFormFields from './custom_metrics_form_fields.vue';
import DeleteCustomMetricModal from './delete_custom_metric_modal.vue';
-import { formDataValidator } from '../constants';
export default {
components: {
diff --git a/app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue b/app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue
index f3fa28dc2f3..0aae63e1648 100644
--- a/app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue
+++ b/app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue
@@ -8,11 +8,11 @@ import {
GlIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import { __, s__ } from '~/locale';
-import csrf from '~/lib/utils/csrf';
import axios from '~/lib/utils/axios_utils';
-import statusCodes from '~/lib/utils/http_status';
import { backOff } from '~/lib/utils/common_utils';
+import csrf from '~/lib/utils/csrf';
+import statusCodes from '~/lib/utils/http_status';
+import { __, s__ } from '~/locale';
import { queryTypes, formDataValidator } from '../constants';
const VALIDATION_REQUEST_TIMEOUT = 10000;
diff --git a/app/assets/javascripts/cycle_analytics/components/banner.vue b/app/assets/javascripts/cycle_analytics/components/banner.vue
index 4448d909c9b..cf4c35ef12b 100644
--- a/app/assets/javascripts/cycle_analytics/components/banner.vue
+++ b/app/assets/javascripts/cycle_analytics/components/banner.vue
@@ -1,7 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
-import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
import { GlIcon } from '@gitlab/ui';
+import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
export default {
components: {
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index bd5a6cc40c4..847820c965f 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -1,17 +1,21 @@
+// This is a true violation of @gitlab/no-runtime-template-compiler, as it
+// relies on app/views/projects/cycle_analytics/show.html.haml for its
+// template.
+/* eslint-disable @gitlab/no-runtime-template-compiler */
+import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import $ from 'jquery';
-import Vue from 'vue';
import Cookies from 'js-cookie';
-import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
-import { deprecatedCreateFlash as Flash } from '../flash';
+import Vue from 'vue';
import { __ } from '~/locale';
+import { deprecatedCreateFlash as Flash } from '../flash';
import Translate from '../vue_shared/translate';
import banner from './components/banner.vue';
import stageCodeComponent from './components/stage_code_component.vue';
import stageComponent from './components/stage_component.vue';
+import stageNavItem from './components/stage_nav_item.vue';
import stageReviewComponent from './components/stage_review_component.vue';
import stageStagingComponent from './components/stage_staging_component.vue';
import stageTestComponent from './components/stage_test_component.vue';
-import stageNavItem from './components/stage_nav_item.vue';
import CycleAnalyticsService from './cycle_analytics_service';
import CycleAnalyticsStore from './cycle_analytics_store';
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
index 7b04494892e..24ad6ef4c88 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
@@ -1,7 +1,7 @@
/* eslint-disable no-param-reassign */
-import { __ } from '../locale';
import { dasherize } from '../lib/utils/text_utility';
+import { __ } from '../locale';
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
const EMPTY_STAGE_TEXTS = {
diff --git a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
index afc1c2cda8e..d05a0761ae3 100644
--- a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
+++ b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_modal.vue
@@ -1,10 +1,10 @@
<script>
import { GlFormGroup, GlFormInput, GlModal, GlSprintf, GlLink } from '@gitlab/ui';
-import { mapActions, mapState } from 'vuex';
import { isValidCron } from 'cron-validator';
-import { mapComputed } from '~/vuex_shared/bindings';
+import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
+import { mapComputed } from '~/vuex_shared/bindings';
export default {
components: {
diff --git a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_settings.vue b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_settings.vue
index fc2ed10f3ca..0f898f20033 100644
--- a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_settings.vue
+++ b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_settings.vue
@@ -1,6 +1,6 @@
<script>
-import DeployFreezeTable from './deploy_freeze_table.vue';
import DeployFreezeModal from './deploy_freeze_modal.vue';
+import DeployFreezeTable from './deploy_freeze_table.vue';
export default {
components: {
diff --git a/app/assets/javascripts/deploy_freeze/store/actions.js b/app/assets/javascripts/deploy_freeze/store/actions.js
index 9a75c3cad2f..62045d2517d 100644
--- a/app/assets/javascripts/deploy_freeze/store/actions.js
+++ b/app/assets/javascripts/deploy_freeze/store/actions.js
@@ -1,7 +1,7 @@
-import * as types from './mutation_types';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale';
+import * as types from './mutation_types';
export const requestAddFreezePeriod = ({ commit }) => {
commit(types.REQUEST_ADD_FREEZE_PERIOD);
diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue
index 92e80d15902..425cca13ae8 100644
--- a/app/assets/javascripts/deploy_keys/components/app.vue
+++ b/app/assets/javascripts/deploy_keys/components/app.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { s__ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import { s__ } from '~/locale';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import eventHub from '../eventhub';
import DeployKeysService from '../service';
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue
index 3ddaba7abcc..e70ca18bb71 100644
--- a/app/assets/javascripts/deploy_keys/components/key.vue
+++ b/app/assets/javascripts/deploy_keys/components/key.vue
@@ -1,6 +1,6 @@
<script>
-import { head, tail } from 'lodash';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { head, tail } from 'lodash';
import { s__, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@@ -97,7 +97,7 @@ export default {
methods: {
projectTooltipTitle(project) {
return project.can_push
- ? s__('DeployKeys|Write access allowed')
+ ? s__('DeployKeys|Grant write permissions to this key')
: s__('DeployKeys|Read access only');
},
toggleExpanded() {
diff --git a/app/assets/javascripts/deploy_keys/components/keys_panel.vue b/app/assets/javascripts/deploy_keys/components/keys_panel.vue
index 2693cd08cc3..d71f4f5507f 100644
--- a/app/assets/javascripts/deploy_keys/components/keys_panel.vue
+++ b/app/assets/javascripts/deploy_keys/components/keys_panel.vue
@@ -48,7 +48,7 @@ export default {
:project-id="projectId"
/>
</template>
- <div v-else class="settings-message text-center">
+ <div v-else class="settings-message text-center gl-mt-5">
{{ s__('DeployKeys|No deploy keys found. Create one with the form above.') }}
</div>
</div>
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
index 99351231520..162491312a8 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
@@ -1,13 +1,13 @@
/* eslint-disable consistent-return */
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
import $ from 'jquery';
import { escape } from 'lodash';
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import { visitUrl } from '~/lib/utils/url_utility';
import { isObject } from '~/lib/utils/type_utility';
-import renderItem from './render';
-import { GitLabDropdownRemote } from './gl_dropdown_remote';
-import { GitLabDropdownInput } from './gl_dropdown_input';
+import { visitUrl } from '~/lib/utils/url_utility';
import { GitLabDropdownFilter } from './gl_dropdown_filter';
+import { GitLabDropdownInput } from './gl_dropdown_input';
+import { GitLabDropdownRemote } from './gl_dropdown_remote';
+import renderItem from './render';
const LOADING_CLASS = 'is-loading';
@@ -437,6 +437,7 @@ export class GitLabDropdown {
groupName = el.data('group');
if (groupName) {
selectedIndex = el.data('index');
+ this.selectedIndex = selectedIndex;
selectedObject = this.renderedData[groupName][selectedIndex];
} else {
selectedIndex = el.closest('li').index();
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
index ab9fb1ec332..b1d486c5d66 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
@@ -1,7 +1,7 @@
/* eslint-disable consistent-return */
-import $ from 'jquery';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import $ from 'jquery';
import { isObject } from '~/lib/utils/type_utility';
const BLUR_KEYCODES = [27, 40];
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
index ea4d5d7b570..33f0aa00cad 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
@@ -1,20 +1,20 @@
<script>
-import { ApolloMutation } from 'vue-apollo';
import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink, GlBadge } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { ApolloMutation } from 'vue-apollo';
import createFlash from '~/flash';
+import { s__ } from '~/locale';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import allVersionsMixin from '../../mixins/all_versions';
+import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
import createNoteMutation from '../../graphql/mutations/create_note.mutation.graphql';
import toggleResolveDiscussionMutation from '../../graphql/mutations/toggle_resolve_discussion.mutation.graphql';
import activeDiscussionQuery from '../../graphql/queries/active_discussion.query.graphql';
+import allVersionsMixin from '../../mixins/all_versions';
+import { hasErrors } from '../../utils/cache_update';
+import { ADD_DISCUSSION_COMMENT_ERROR } from '../../utils/error_messages';
import DesignNote from './design_note.vue';
import DesignReplyForm from './design_reply_form.vue';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
import ToggleRepliesWidget from './toggle_replies_widget.vue';
-import { hasErrors } from '../../utils/cache_update';
-import { ADD_DISCUSSION_COMMENT_ERROR } from '../../utils/error_messages';
export default {
components: {
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note.vue b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
index 421a4dc274a..2b867217327 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -1,13 +1,13 @@
<script>
-import { ApolloMutation } from 'vue-apollo';
import { GlTooltipDirective, GlIcon, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
-import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import { ApolloMutation } from 'vue-apollo';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import DesignReplyForm from './design_reply_form.vue';
-import { findNoteId, extractDesignNoteId } from '../../utils/design_management_utils';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
import { hasErrors } from '../../utils/cache_update';
+import { findNoteId, extractDesignNoteId } from '../../utils/design_management_utils';
+import DesignReplyForm from './design_reply_form.vue';
export default {
components: {
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue b/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
index 0cc89440754..fb25d3618ab 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton, GlModal } from '@gitlab/ui';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import { s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__ } from '~/locale';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
export default {
name: 'DesignReplyForm',
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index 3c2ce693bc0..ecca8606f89 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -1,9 +1,9 @@
<script>
import { __ } from '~/locale';
-import activeDiscussionQuery from '../graphql/queries/active_discussion.query.graphql';
+import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
+import activeDiscussionQuery from '../graphql/queries/active_discussion.query.graphql';
import DesignNotePin from './design_note_pin.vue';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
export default {
name: 'DesignOverlay',
diff --git a/app/assets/javascripts/design_management/components/design_presentation.vue b/app/assets/javascripts/design_management/components/design_presentation.vue
index a760adf8b14..11d2f3b2e37 100644
--- a/app/assets/javascripts/design_management/components/design_presentation.vue
+++ b/app/assets/javascripts/design_management/components/design_presentation.vue
@@ -1,7 +1,7 @@
<script>
import { throttle } from 'lodash';
-import DesignImage from './image.vue';
import DesignOverlay from './design_overlay.vue';
+import DesignImage from './image.vue';
const CLICK_DRAG_BUFFER_PX = 2;
diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue
index 50b12fd739b..efa1ef2107a 100644
--- a/app/assets/javascripts/design_management/components/design_sidebar.vue
+++ b/app/assets/javascripts/design_management/components/design_sidebar.vue
@@ -1,15 +1,15 @@
<script>
-import Cookies from 'js-cookie';
import { GlCollapse, GlButton, GlPopover } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import Cookies from 'js-cookie';
import { parseBoolean } 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';
+import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
import { extractDiscussions, extractParticipants } from '../utils/design_management_utils';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
import DesignDiscussion from './design_notes/design_discussion.vue';
-import Participants from '~/sidebar/components/participants/participants.vue';
import DesignTodoButton from './design_todo_button.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
diff --git a/app/assets/javascripts/design_management/components/design_todo_button.vue b/app/assets/javascripts/design_management/components/design_todo_button.vue
index db14db79989..da492f03801 100644
--- a/app/assets/javascripts/design_management/components/design_todo_button.vue
+++ b/app/assets/javascripts/design_management/components/design_todo_button.vue
@@ -1,8 +1,8 @@
<script>
import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
-import getDesignQuery from '../graphql/queries/get_design.query.graphql';
-import createDesignTodoMutation from '../graphql/mutations/create_design_todo.mutation.graphql';
import TodoButton from '~/vue_shared/components/todo_button.vue';
+import createDesignTodoMutation from '../graphql/mutations/create_design_todo.mutation.graphql';
+import getDesignQuery from '../graphql/queries/get_design.query.graphql';
import allVersionsMixin from '../mixins/all_versions';
import { updateStoreAfterDeleteDesignTodo } from '../utils/cache_update';
import { findIssueId, findDesignId } from '../utils/design_management_utils';
diff --git a/app/assets/javascripts/design_management/components/image.vue b/app/assets/javascripts/design_management/components/image.vue
index 53062e6ebb0..e64ee4a5a34 100644
--- a/app/assets/javascripts/design_management/components/image.vue
+++ b/app/assets/javascripts/design_management/components/image.vue
@@ -1,6 +1,6 @@
<script>
-import { throttle } from 'lodash';
import { GlIcon } from '@gitlab/ui';
+import { throttle } from 'lodash';
export default {
components: {
diff --git a/app/assets/javascripts/design_management/components/list/item.vue b/app/assets/javascripts/design_management/components/list/item.vue
index fa09c7c15cc..5eabe9ef1bc 100644
--- a/app/assets/javascripts/design_management/components/list/item.vue
+++ b/app/assets/javascripts/design_management/components/list/item.vue
@@ -1,7 +1,7 @@
<script>
-import { GlLoadingIcon, GlIcon, GlIntersectionObserver } from '@gitlab/ui';
-import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
+import { GlLoadingIcon, GlIcon, GlIntersectionObserver, GlTooltipDirective } from '@gitlab/ui';
import { n__, __ } from '~/locale';
+import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { DESIGN_ROUTE_NAME } from '../../router/constants';
export default {
@@ -11,6 +11,9 @@ export default {
GlIcon,
Timeago,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
id: {
type: [Number, String],
@@ -130,7 +133,7 @@ export default {
<div
class="card-body gl-p-0 gl-display-flex gl-align-items-center gl-justify-content-center gl-overflow-hidden gl-relative"
>
- <div v-if="icon.name" data-testid="designEvent" class="design-event gl-absolute">
+ <div v-if="icon.name" data-testid="design-event" class="gl-top-5 gl-right-5 gl-absolute">
<span :title="icon.tooltip" :aria-label="icon.tooltip">
<gl-icon
:name="icon.name"
@@ -153,9 +156,10 @@ export default {
v-show="showImage"
:src="imageLink"
:alt="filename"
- class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
+ class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full design-img"
data-qa-selector="design_image"
:data-qa-filename="filename"
+ :data-testid="`design-img-${id}`"
@load="onImageLoad"
@error="onImageError"
/>
@@ -163,9 +167,14 @@ export default {
</div>
<div class="card-footer gl-display-flex gl-w-full">
<div class="gl-display-flex gl-flex-direction-column str-truncated-100">
- <span class="gl-font-weight-bold str-truncated-100" data-qa-selector="design_file_name">{{
- filename
- }}</span>
+ <span
+ v-gl-tooltip
+ class="gl-font-weight-bold str-truncated-100"
+ data-qa-selector="design_file_name"
+ :data-testid="`design-img-filename-${id}`"
+ :title="filename"
+ >{{ filename }}</span
+ >
<span v-if="updatedAt" class="str-truncated-100">
{{ __('Updated') }} <timeago :time="updatedAt" tooltip-placement="bottom" />
</span>
diff --git a/app/assets/javascripts/design_management/components/toolbar/index.vue b/app/assets/javascripts/design_management/components/toolbar/index.vue
index 3509a701984..a3b0f06fb28 100644
--- a/app/assets/javascripts/design_management/components/toolbar/index.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/index.vue
@@ -3,9 +3,9 @@ import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import DesignNavigation from './design_navigation.vue';
-import DeleteButton from '../delete_button.vue';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
+import DeleteButton from '../delete_button.vue';
+import DesignNavigation from './design_navigation.vue';
export default {
components: {
diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js
index b7aba315168..c6c3e66a01f 100644
--- a/app/assets/javascripts/design_management/graphql.js
+++ b/app/assets/javascripts/design_management/graphql.js
@@ -1,16 +1,16 @@
+import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
+import produce from 'immer';
+import { uniqueId } from 'lodash';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import { uniqueId } from 'lodash';
-import produce from 'immer';
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
-import axios from '~/lib/utils/axios_utils';
import createDefaultClient from '~/lib/graphql';
+import axios from '~/lib/utils/axios_utils';
import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
import getDesignQuery from './graphql/queries/get_design.query.graphql';
import typeDefs from './graphql/typedefs.graphql';
+import { addPendingTodoToStore } from './utils/cache_update';
import { extractTodoIdFromDeletePath, createPendingTodo } from './utils/design_management_utils';
import { CREATE_DESIGN_TODO_EXISTS_ERROR } from './utils/error_messages';
-import { addPendingTodoToStore } from './utils/cache_update';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/design_management/index.js b/app/assets/javascripts/design_management/index.js
index 1a87dd38137..f0930ade1b5 100644
--- a/app/assets/javascripts/design_management/index.js
+++ b/app/assets/javascripts/design_management/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import createRouter from './router';
import App from './components/app.vue';
import apolloProvider from './graphql';
+import createRouter from './router';
export default () => {
const el = document.querySelector('.js-design-management');
diff --git a/app/assets/javascripts/design_management/mixins/all_designs.js b/app/assets/javascripts/design_management/mixins/all_designs.js
index 4783382d563..e92f8006a0d 100644
--- a/app/assets/javascripts/design_management/mixins/all_designs.js
+++ b/app/assets/javascripts/design_management/mixins/all_designs.js
@@ -2,8 +2,8 @@ import { propertyOf } from 'lodash';
import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
import { s__ } from '~/locale';
-import allVersionsMixin from './all_versions';
import { DESIGNS_ROUTE_NAME } from '../router/constants';
+import allVersionsMixin from './all_versions';
export default {
mixins: [allVersionsMixin],
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index 492ed2e8719..8a11c25a795 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -1,21 +1,27 @@
<script>
-import Mousetrap from 'mousetrap';
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
+import Mousetrap from 'mousetrap';
import { ApolloMutation } from 'vue-apollo';
import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import allVersionsMixin from '../../mixins/all_versions';
-import Toolbar from '../../components/toolbar/index.vue';
import DesignDestroyer from '../../components/design_destroyer.vue';
-import DesignScaler from '../../components/design_scaler.vue';
-import DesignPresentation from '../../components/design_presentation.vue';
import DesignReplyForm from '../../components/design_notes/design_reply_form.vue';
+import DesignPresentation from '../../components/design_presentation.vue';
+import DesignScaler from '../../components/design_scaler.vue';
import DesignSidebar from '../../components/design_sidebar.vue';
-import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
+import Toolbar from '../../components/toolbar/index.vue';
+import { ACTIVE_DISCUSSION_SOURCE_TYPES, DESIGN_DETAIL_LAYOUT_CLASSLIST } from '../../constants';
import createImageDiffNoteMutation from '../../graphql/mutations/create_image_diff_note.mutation.graphql';
import repositionImageDiffNoteMutation from '../../graphql/mutations/reposition_image_diff_note.mutation.graphql';
import updateActiveDiscussionMutation from '../../graphql/mutations/update_active_discussion.mutation.graphql';
+import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
+import allVersionsMixin from '../../mixins/all_versions';
+import { DESIGNS_ROUTE_NAME } from '../../router/constants';
+import {
+ updateStoreAfterAddImageDiffNote,
+ updateStoreAfterRepositionImageDiffNote,
+} from '../../utils/cache_update';
import {
extractDiscussions,
extractDesign,
@@ -25,10 +31,6 @@ import {
getPageLayoutElement,
} from '../../utils/design_management_utils';
import {
- updateStoreAfterAddImageDiffNote,
- updateStoreAfterRepositionImageDiffNote,
-} from '../../utils/cache_update';
-import {
ADD_DISCUSSION_COMMENT_ERROR,
ADD_IMAGE_DIFF_NOTE_ERROR,
UPDATE_IMAGE_DIFF_NOTE_ERROR,
@@ -39,8 +41,6 @@ import {
designDeletionError,
} from '../../utils/error_messages';
import { trackDesignDetailView, usagePingDesignDetailView } from '../../utils/tracking';
-import { DESIGNS_ROUTE_NAME } from '../../router/constants';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES, DESIGN_DETAIL_LAYOUT_CLASSLIST } from '../../constants';
const DEFAULT_SCALE = 1;
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 5c82a7331b6..c73c8fb6ca4 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -1,29 +1,22 @@
<script>
import { GlLoadingIcon, GlButton, GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import VueDraggable from 'vuedraggable';
-import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import createFlash, { FLASH_TYPES } from '~/flash';
-import { __, s__, sprintf } from '~/locale';
import { getFilename } from '~/lib/utils/file_upload';
-import UploadButton from '../components/upload/button.vue';
+import { __, s__, sprintf } from '~/locale';
+import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import DeleteButton from '../components/delete_button.vue';
-import Design from '../components/list/item.vue';
import DesignDestroyer from '../components/design_destroyer.vue';
+import Design from '../components/list/item.vue';
+import UploadButton from '../components/upload/button.vue';
import DesignVersionDropdown from '../components/upload/design_version_dropdown.vue';
-import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
-import uploadDesignMutation from '../graphql/mutations/upload_design.mutation.graphql';
+import { VALID_DESIGN_FILE_MIMETYPE } from '../constants';
import moveDesignMutation from '../graphql/mutations/move_design.mutation.graphql';
+import uploadDesignMutation from '../graphql/mutations/upload_design.mutation.graphql';
import allDesignsMixin from '../mixins/all_designs';
-import {
- UPLOAD_DESIGN_ERROR,
- EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
- EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
- MOVE_DESIGN_ERROR,
- UPLOAD_DESIGN_INVALID_FILETYPE_ERROR,
- designUploadSkippedWarning,
- designDeletionError,
-} from '../utils/error_messages';
+import { DESIGNS_ROUTE_NAME } from '../router/constants';
import {
updateStoreAfterUploadDesign,
updateDesignsOnStoreAfterReorder,
@@ -33,9 +26,16 @@ import {
isValidDesignFile,
moveDesignOptimisticResponse,
} from '../utils/design_management_utils';
+import {
+ UPLOAD_DESIGN_ERROR,
+ EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
+ EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
+ MOVE_DESIGN_ERROR,
+ UPLOAD_DESIGN_INVALID_FILETYPE_ERROR,
+ designUploadSkippedWarning,
+ designDeletionError,
+} from '../utils/error_messages';
import { trackDesignCreate, trackDesignUpdate } from '../utils/tracking';
-import { DESIGNS_ROUTE_NAME } from '../router/constants';
-import { VALID_DESIGN_FILE_MIMETYPE } from '../constants';
const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
@@ -347,15 +347,20 @@ export default {
>
<header
v-if="showToolbar"
- class="row-content-block gl-border-t-0 gl-p-3 gl-display-flex"
+ class="row-content-block gl-border-t-0 gl-py-3 gl-display-flex"
data-testid="design-toolbar-wrapper"
>
- <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full">
- <div>
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full gl-flex-wrap"
+ >
+ <div class="gl-display-flex gl-align-items-center gl-my-2">
<span class="gl-font-weight-bold gl-mr-3">{{ s__('DesignManagement|Designs') }}</span>
<design-version-dropdown />
</div>
- <div v-show="hasDesigns" class="qa-selector-toolbar gl-display-flex gl-align-items-center">
+ <div
+ v-show="hasDesigns"
+ class="qa-selector-toolbar gl-display-flex gl-align-items-center gl-my-2"
+ >
<gl-button
v-if="isLatestVersion"
variant="link"
diff --git a/app/assets/javascripts/design_management/router/routes.js b/app/assets/javascripts/design_management/router/routes.js
index 1b07d8aeb76..fb1daecfc35 100644
--- a/app/assets/javascripts/design_management/router/routes.js
+++ b/app/assets/javascripts/design_management/router/routes.js
@@ -1,5 +1,5 @@
-import Home from '../pages/index.vue';
import DesignDetail from '../pages/design/index.vue';
+import Home from '../pages/index.vue';
import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from './constants';
export default [
diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index 0c4ee0bf012..c561eda12ed 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -1,7 +1,7 @@
/* eslint-disable @gitlab/require-i18n-strings */
-import { differenceBy } from 'lodash';
import produce from 'immer';
+import { differenceBy } from 'lodash';
import createFlash from '~/flash';
import { extractCurrentDiscussion, extractDesign, extractDesigns } from './design_management_utils';
import {
diff --git a/app/assets/javascripts/design_management/utils/error_messages.js b/app/assets/javascripts/design_management/utils/error_messages.js
index cb4bb6e26a8..e7b2c814bb3 100644
--- a/app/assets/javascripts/design_management/utils/error_messages.js
+++ b/app/assets/javascripts/design_management/utils/error_messages.js
@@ -44,13 +44,13 @@ export const MOVE_DESIGN_ERROR = __(
'Something went wrong when reordering designs. Please try again',
);
-export const CREATE_DESIGN_TODO_ERROR = __('Failed to create To-Do for the design.');
+export const CREATE_DESIGN_TODO_ERROR = __('Failed to create a to-do item for the design.');
-export const CREATE_DESIGN_TODO_EXISTS_ERROR = __('There is already a To-Do for this design.');
+export const CREATE_DESIGN_TODO_EXISTS_ERROR = __('There is already a to-do item for this design.');
-export const DELETE_DESIGN_TODO_ERROR = __('Failed to remove To-Do for the design.');
+export const DELETE_DESIGN_TODO_ERROR = __('Failed to remove a to-do item for the design.');
-export const TOGGLE_TODO_ERROR = __('Failed to toggle To-Do for the design.');
+export const TOGGLE_TODO_ERROR = __('Failed to toggle the to-do status for the design.');
const MAX_SKIPPED_FILES_LISTINGS = 5;
diff --git a/app/assets/javascripts/design_management/utils/tracking.js b/app/assets/javascripts/design_management/utils/tracking.js
index 37296f5b4ff..905134fa985 100644
--- a/app/assets/javascripts/design_management/utils/tracking.js
+++ b/app/assets/javascripts/design_management/utils/tracking.js
@@ -1,5 +1,5 @@
-import Tracking from '~/tracking';
import Api from '~/api';
+import Tracking from '~/tracking';
// Snowplow tracking constants
const DESIGN_TRACKING_CONTEXT_SCHEMAS = {
diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js
index c4e86638e9d..7200e6c2e3a 100644
--- a/app/assets/javascripts/diff.js
+++ b/app/assets/javascripts/diff.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
-import { getLocationHash } from './lib/utils/url_utility';
import FilesCommentButton from './files_comment_button';
-import SingleFileDiff from './single_file_diff';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
+import { getLocationHash } from './lib/utils/url_utility';
+import SingleFileDiff from './single_file_diff';
const UNFOLD_COUNT = 20;
let isBound = false;
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 32822fe1fe8..4323499ef1f 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -1,32 +1,17 @@
<script>
-import { mapState, mapGetters, mapActions } from 'vuex';
import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Mousetrap from 'mousetrap';
-import { __ } from '~/locale';
-import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
+import { mapState, mapGetters, mapActions } from 'vuex';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { isSingleViewStyle } from '~/helpers/diffs_helper';
+import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import { updateHistory } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
+import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import notesEventHub from '../../notes/event_hub';
-import eventHub from '../event_hub';
-
-import CompareVersions from './compare_versions.vue';
-import DiffFile from './diff_file.vue';
-import NoChanges from './no_changes.vue';
-import CommitWidget from './commit_widget.vue';
-import TreeList from './tree_list.vue';
-
-import HiddenFilesWarning from './hidden_files_warning.vue';
-import MergeConflictWarning from './merge_conflict_warning.vue';
-import CollapsedFilesWarning from './collapsed_files_warning.vue';
-
-import { diffsApp } from '../utils/performance';
-import { fileByFile } from '../utils/preferences';
-
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
@@ -40,6 +25,19 @@ import {
ALERT_COLLAPSED_FILES,
EVT_VIEW_FILE_BY_FILE,
} from '../constants';
+import eventHub from '../event_hub';
+
+import { reviewStatuses } from '../utils/file_reviews';
+import { diffsApp } from '../utils/performance';
+import { fileByFile } from '../utils/preferences';
+import CollapsedFilesWarning from './collapsed_files_warning.vue';
+import CommitWidget from './commit_widget.vue';
+import CompareVersions from './compare_versions.vue';
+import DiffFile from './diff_file.vue';
+import HiddenFilesWarning from './hidden_files_warning.vue';
+import MergeConflictWarning from './merge_conflict_warning.vue';
+import NoChanges from './no_changes.vue';
+import TreeList from './tree_list.vue';
export default {
name: 'DiffsApp',
@@ -169,12 +167,7 @@ export default {
'hasConflicts',
'viewDiffsFileByFile',
]),
- ...mapGetters('diffs', [
- 'whichCollapsedTypes',
- 'isParallelView',
- 'currentDiffIndex',
- 'fileReviews',
- ]),
+ ...mapGetters('diffs', ['whichCollapsedTypes', 'isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
diffs() {
if (!this.viewDiffsFileByFile) {
@@ -232,6 +225,9 @@ export default {
return visible;
},
+ fileReviews() {
+ return reviewStatuses(this.diffFiles, this.mrReviews);
+ },
},
watch: {
commit(newCommit, oldCommit) {
@@ -526,7 +522,7 @@ export default {
:file="file"
:reviewed="fileReviews[index]"
:is-first-file="index === 0"
- :is-last-file="index === diffs.length - 1"
+ :is-last-file="index === diffFilesLength - 1"
:help-page-path="helpPagePath"
:can-current-user-fork="canCurrentUserFork"
:view-diffs-file-by-file="viewDiffsFileByFile"
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index af19f90ee77..92b317eb3f0 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -1,18 +1,16 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapActions } from 'vuex';
import { GlButtonGroup, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { mapActions } from 'vuex';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
-
-import initUserPopovers from '../../user_popovers';
import { setUrlParams } from '../../lib/utils/url_utility';
+import initUserPopovers from '../../user_popovers';
/**
* CommitItem
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 489278fd6ef..6b1e2bfb34e 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,13 +1,12 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlLink, GlButton, GlSprintf } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
-import { polyfillSticky } from '~/lib/utils/sticky';
-import CompareDropdownLayout from './compare_dropdown_layout.vue';
-import SettingsDropdown from './settings_dropdown.vue';
-import DiffStats from './diff_stats.vue';
import { CENTERED_LIMITED_CONTAINER_CLASSES, EVT_EXPAND_ALL_FILES } from '../constants';
import eventHub from '../event_hub';
+import CompareDropdownLayout from './compare_dropdown_layout.vue';
+import DiffStats from './diff_stats.vue';
+import SettingsDropdown from './settings_dropdown.vue';
export default {
components: {
@@ -61,9 +60,6 @@ export default {
created() {
this.CENTERED_LIMITED_CONTAINER_CLASSES = CENTERED_LIMITED_CONTAINER_CLASSES;
},
- mounted() {
- polyfillSticky(this.$el);
- },
methods: {
...mapActions('diffs', ['setInlineDiffViewType', 'setParallelDiffViewType', 'setShowTreeList']),
expandAllFiles() {
diff --git a/app/assets/javascripts/diffs/components/diff_comment_cell.vue b/app/assets/javascripts/diffs/components/diff_comment_cell.vue
index 4b0b603f5a5..4af4b46f94c 100644
--- a/app/assets/javascripts/diffs/components/diff_comment_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_comment_cell.vue
@@ -1,8 +1,8 @@
<script>
import { mapActions } from 'vuex';
+import DiffDiscussionReply from './diff_discussion_reply.vue';
import DiffDiscussions from './diff_discussions.vue';
import DiffLineNoteForm from './diff_line_note_form.vue';
-import DiffDiscussionReply from './diff_discussion_reply.vue';
export default {
components: {
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index f4e2571dd09..663d2bb3cf8 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -1,25 +1,25 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
+import { diffViewerModes } from '~/ide/constants';
+import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
-import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
-import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
-import InlineDiffView from './inline_diff_view.vue';
-import ParallelDiffView from './parallel_diff_view.vue';
-import DiffView from './diff_view.vue';
-import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
+import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import NoteForm from '../../notes/components/note_form.vue';
-import ImageDiffOverlay from './image_diff_overlay.vue';
-import DiffDiscussions from './diff_discussions.vue';
import eventHub from '../../notes/event_hub';
+import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
import { getDiffMode } from '../store/utils';
-import { diffViewerModes } from '~/ide/constants';
+import DiffDiscussions from './diff_discussions.vue';
import { mapInline, mapParallel } from './diff_row_utils';
+import DiffView from './diff_view.vue';
+import ImageDiffOverlay from './image_diff_overlay.vue';
+import InlineDiffView from './inline_diff_view.vue';
+import ParallelDiffView from './parallel_diff_view.vue';
export default {
components: {
diff --git a/app/assets/javascripts/diffs/components/diff_discussion_reply.vue b/app/assets/javascripts/diffs/components/diff_discussion_reply.vue
index 531ebaddacd..9027d0c8aa4 100644
--- a/app/assets/javascripts/diffs/components/diff_discussion_reply.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussion_reply.vue
@@ -1,15 +1,13 @@
<script>
import { mapGetters } from 'vuex';
-import NoteSignedOutWidget from '~/notes/components/note_signed_out_widget.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import NoteSignedOutWidget from '~/notes/components/note_signed_out_widget.vue';
export default {
name: 'DiffDiscussionReply',
components: {
NoteSignedOutWidget,
ReplyPlaceholder,
- UserAvatarLink,
},
props: {
hasForm: {
@@ -36,13 +34,6 @@ export default {
<template v-if="userCanReply">
<slot v-if="hasForm" name="form"></slot>
<template v-else-if="renderReplyPlaceholder">
- <user-avatar-link
- :link-href="currentUser.path"
- :img-src="currentUser.avatar_url"
- :img-alt="currentUser.name"
- :img-size="40"
- class="d-none d-sm-block"
- />
<reply-placeholder
:button-text="__('Start a new discussion...')"
@onClick="$emit('showNewDiscussionForm')"
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index 7b55bd2104d..d0d457d8582 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions } from 'vuex';
import { GlIcon } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import noteableDiscussion from '../../notes/components/noteable_discussion.vue';
export default {
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index 2d1a7237122..67900af8789 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index e613b684345..f77c8d7406b 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,16 +1,14 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlButton, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml, GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
-import { GlButton, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { sprintf } from '~/locale';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { hasDiff } from '~/helpers/diffs_helper';
-import notesEventHub from '../../notes/event_hub';
-import DiffFileHeader from './diff_file_header.vue';
-import DiffContent from './diff_content.vue';
import { diffViewerErrors } from '~/ide/constants';
-import { collapsedType, isCollapsed } from '../utils/diff_file';
+import { sprintf } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import notesEventHub from '../../notes/event_hub';
+
import {
DIFF_FILE_AUTOMATIC_COLLAPSE,
DIFF_FILE_MANUAL_COLLAPSE,
@@ -18,8 +16,11 @@ import {
EVT_PERF_MARK_DIFF_FILES_END,
EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
} from '../constants';
-import { DIFF_FILE, GENERIC_ERROR } from '../i18n';
import eventHub from '../event_hub';
+import { DIFF_FILE, GENERIC_ERROR } from '../i18n';
+import { collapsedType, isCollapsed, getShortShaFromFile } from '../utils/diff_file';
+import DiffContent from './diff_content.vue';
+import DiffFileHeader from './diff_file_header.vue';
export default {
components: {
@@ -27,6 +28,7 @@ export default {
DiffContent,
GlButton,
GlLoadingIcon,
+ GlSprintf,
},
directives: {
SafeHtml,
@@ -81,15 +83,11 @@ export default {
...mapState('diffs', ['currentDiffFileId']),
...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions']),
- viewBlobLink() {
- return sprintf(
- this.$options.i18n.blobView,
- {
- linkStart: `<a href="${escape(this.file.view_path)}">`,
- linkEnd: '</a>',
- },
- false,
- );
+ viewBlobHref() {
+ return escape(this.file.view_path);
+ },
+ shortSha() {
+ return getShortShaFromFile(this.file);
},
showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed);
@@ -98,7 +96,7 @@ export default {
return hasDiff(this.file);
},
isFileTooLarge() {
- return this.file.viewer.error === diffViewerErrors.too_large;
+ return !this.manuallyCollapsed && this.file.viewer.error === diffViewerErrors.too_large;
},
errorMessage() {
return !this.manuallyCollapsed ? this.file.viewer.error_message : '';
@@ -144,6 +142,12 @@ export default {
showContent() {
return !this.isCollapsed && !this.isFileTooLarge;
},
+ showLocalFileReviews() {
+ const loggedIn = Boolean(gon.current_user_id);
+ const featureOn = this.glFeatures.localFileReviews;
+
+ return loggedIn && featureOn;
+ },
},
watch: {
'file.file_hash': {
@@ -181,6 +185,10 @@ export default {
if (this.hasDiff) {
this.postRender();
}
+
+ if (this.reviewed && !this.isCollapsed && this.showLocalFileReviews) {
+ this.handleToggle();
+ }
},
beforeDestroy() {
eventHub.$off(EVT_EXPAND_ALL_FILES, this.expandAllListener);
@@ -273,9 +281,11 @@ export default {
:can-current-user-fork="canCurrentUserFork"
:diff-file="file"
:collapsible="true"
+ :reviewed="reviewed"
:expanded="!isCollapsed"
:add-merge-request-buttons="true"
:view-diffs-file-by-file="viewDiffsFileByFile"
+ :show-local-file-reviews="showLocalFileReviews"
class="js-file-title file-title gl-border-1 gl-border-solid gl-border-gray-100"
:class="hasBodyClasses.header"
@toggleFile="handleToggle"
@@ -309,14 +319,27 @@ export default {
data-testid="loader-icon"
/>
<div v-else-if="errorMessage" class="diff-viewer">
- <div v-safe-html="errorMessage" class="nothing-here-block"></div>
+ <div
+ v-if="isFileTooLarge"
+ class="collapsed-file-warning gl-p-7 gl-bg-orange-50 gl-text-center gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
+ >
+ <p class="gl-mb-5">
+ {{ $options.i18n.tooLarge }}
+ </p>
+ <gl-button data-testid="blob-button" category="secondary" :href="viewBlobHref">
+ <gl-sprintf :message="$options.i18n.blobView">
+ <template #commitSha>{{ shortSha }}</template>
+ </gl-sprintf>
+ </gl-button>
+ </div>
+ <div v-else v-safe-html="errorMessage" class="nothing-here-block"></div>
</div>
<template v-else>
<div
v-show="showWarning"
class="collapsed-file-warning gl-p-7 gl-bg-orange-50 gl-text-center gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
>
- <p class="gl-mb-8">
+ <p class="gl-mb-5">
{{ $options.i18n.autoCollapsed }}
</p>
<gl-button
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 53d1383b82e..1195a7f2565 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -1,6 +1,4 @@
<script>
-import { escape } from 'lodash';
-import { mapActions, mapGetters } from 'vuex';
import {
GlTooltipDirective,
GlSafeHtmlDirective,
@@ -10,17 +8,25 @@ import {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
+ GlFormCheckbox,
GlLoadingIcon,
} from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import FileIcon from '~/vue_shared/components/file_icon.vue';
-import { truncateSha } from '~/lib/utils/text_utility';
-import { __, s__, sprintf } from '~/locale';
+import { escape } from 'lodash';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { diffViewerModes } from '~/ide/constants';
-import DiffStats from './diff_stats.vue';
import { scrollToElement } from '~/lib/utils/common_utils';
-import { isCollapsed } from '../utils/diff_file';
+import { truncateSha } from '~/lib/utils/text_utility';
+import { __, s__, sprintf } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+import { DIFF_FILE_AUTOMATIC_COLLAPSE } from '../constants';
import { DIFF_FILE_HEADER } from '../i18n';
+import { collapsedType, isCollapsed } from '../utils/diff_file';
+import { reviewable } from '../utils/file_reviews';
+
+import DiffStats from './diff_stats.vue';
export default {
components: {
@@ -33,12 +39,14 @@ export default {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
+ GlFormCheckbox,
GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
SafeHtml: GlSafeHtmlDirective,
},
+ mixins: [glFeatureFlagsMixin()],
i18n: {
...DIFF_FILE_HEADER,
},
@@ -76,6 +84,16 @@ export default {
required: false,
default: false,
},
+ showLocalFileReviews: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ reviewed: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -83,6 +101,7 @@ export default {
};
},
computed: {
+ ...mapState('diffs', ['latestDiff']),
...mapGetters('diffs', ['diffHasExpandedDiscussions', 'diffHasDiscussions']),
diffContentIDSelector() {
return `#diff-content-${this.diffFile.file_hash}`;
@@ -170,6 +189,9 @@ export default {
(this.diffFile.edit_path || this.diffFile.ide_edit_path)
);
},
+ isReviewable() {
+ return reviewable(this.diffFile);
+ },
},
methods: {
...mapActions('diffs', [
@@ -177,6 +199,8 @@ export default {
'toggleFileDiscussionWrappers',
'toggleFullDiff',
'toggleActiveFileByHash',
+ 'reviewFile',
+ 'setFileCollapsedByUser',
]),
handleToggleFile() {
this.$emit('toggleFile');
@@ -204,6 +228,26 @@ export default {
setMoreActionsShown(val) {
this.moreActionsShown = val;
},
+ toggleReview(newReviewedStatus) {
+ const autoCollapsed =
+ this.isCollapsed && collapsedType(this.diffFile) === DIFF_FILE_AUTOMATIC_COLLAPSE;
+ const open = this.expanded;
+ const closed = !open;
+ const reviewed = newReviewedStatus;
+
+ this.reviewFile({ file: this.diffFile, reviewed });
+
+ if (reviewed && autoCollapsed) {
+ this.setFileCollapsedByUser({
+ filePath: this.diffFile.file_path,
+ collapsed: true,
+ });
+ }
+
+ if ((open && reviewed) || (closed && !reviewed)) {
+ this.$emit('toggleFile');
+ }
+ },
},
};
</script>
@@ -213,6 +257,8 @@ export default {
ref="header"
:class="{ 'gl-z-dropdown-menu!': moreActionsShown }"
class="js-file-title file-title file-title-flex-parent"
+ data-qa-selector="file_title_container"
+ :data-qa-file-name="filePath"
@click.self="handleToggleFile"
>
<div class="file-header-content">
@@ -289,6 +335,19 @@ export default {
class="file-actions d-flex align-items-center gl-ml-auto gl-align-self-start"
>
<diff-stats :added-lines="diffFile.added_lines" :removed-lines="diffFile.removed_lines" />
+ <gl-form-checkbox
+ v-if="isReviewable && showLocalFileReviews"
+ v-gl-tooltip.hover
+ data-testid="fileReviewCheckbox"
+ class="gl-mb-0"
+ :title="$options.i18n.fileReviewTooltip"
+ :checked="reviewed"
+ @change="toggleReview"
+ >
+ <span class="gl-line-height-20">
+ {{ $options.i18n.fileReviewLabel }}
+ </span>
+ </gl-form-checkbox>
<gl-button-group class="gl-pt-0!">
<gl-button
v-if="diffFile.external_url"
@@ -307,6 +366,7 @@ export default {
right
toggle-class="btn-icon js-diff-more-actions"
class="gl-pt-0!"
+ data-qa-selector="dropdown_button"
@show="setMoreActionsShown(true)"
@hidden="setMoreActionsShown(false)"
>
@@ -340,6 +400,7 @@ export default {
ref="ideEditButton"
:href="diffFile.ide_edit_path"
class="js-ide-edit-blob"
+ data-qa-selector="edit_in_ide_button"
>
{{ __('Edit in Web IDE') }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/diffs/components/diff_file_row.vue b/app/assets/javascripts/diffs/components/diff_file_row.vue
index 6c5d9170c9e..89822ba7878 100644
--- a/app/assets/javascripts/diffs/components/diff_file_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_row.vue
@@ -3,9 +3,9 @@
* This component is an iterative step towards refactoring and simplifying `vue_shared/components/file_row.vue`
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import FileRow from '~/vue_shared/components/file_row.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
+import FileRow from '~/vue_shared/components/file_row.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import FileRowStats from './file_row_stats.vue';
export default {
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index f62b31734c5..1f3ec7092bc 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { n__ } from '~/locale';
import { truncate } from '~/lib/utils/text_utility';
+import { n__ } from '~/locale';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index 463b7f5cff4..2f09f2e24b2 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -1,22 +1,20 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
+import { s__ } from '~/locale';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { s__ } from '~/locale';
-import noteForm from '../../notes/components/note_form.vue';
import MultilineCommentForm from '../../notes/components/multiline_comment_form.vue';
-import autosave from '../../notes/mixins/autosave';
-import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import { DIFF_NOTE_TYPE, INLINE_DIFF_LINES_KEY, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
import {
commentLineOptions,
formatLineRange,
} from '../../notes/components/multiline_comment_utils';
+import noteForm from '../../notes/components/note_form.vue';
+import autosave from '../../notes/mixins/autosave';
+import { DIFF_NOTE_TYPE, INLINE_DIFF_LINES_KEY, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
export default {
components: {
noteForm,
- userAvatarLink,
MultilineCommentForm,
},
mixins: [autosave, diffLineNoteFormMixin, glFeatureFlagsMixin()],
@@ -167,21 +165,13 @@ export default {
<template>
<div class="content discussion-form discussion-form-container discussion-notes">
- <div v-if="glFeatures.multilineComments" class="gl-mb-3 gl-text-gray-500 gl-pb-3">
+ <div class="gl-mb-3 gl-text-gray-500 gl-pb-3">
<multiline-comment-form
v-model="commentLineStart"
:line="line"
:comment-line-options="commentLineOptions"
/>
</div>
- <user-avatar-link
- v-if="author"
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="40"
- class="d-none d-sm-block"
- />
<note-form
ref="noteForm"
:is-editing="true"
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index db03da966c3..ab6890d66b5 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -1,6 +1,8 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
CONTEXT_LINE_CLASS_NAME,
PARALLEL_DIFF_VIEW_TYPE,
@@ -10,7 +12,6 @@ import {
CONFLICT_THEIR,
CONFLICT_MARKER,
} from '../constants';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import * as utils from './diff_row_utils';
@@ -99,10 +100,10 @@ export default {
});
},
addCommentTooltipLeft() {
- return utils.addCommentTooltip(this.line.left);
+ return utils.addCommentTooltip(this.line.left, this.glFeatures.dragCommentSelection);
},
addCommentTooltipRight() {
- return utils.addCommentTooltip(this.line.right);
+ return utils.addCommentTooltip(this.line.right, this.glFeatures.dragCommentSelection);
},
emptyCellRightClassMap() {
return { conflict_their: this.line.left?.type === CONFLICT_OUR };
@@ -111,13 +112,7 @@ export default {
return { conflict_our: this.line.right?.type === CONFLICT_THEIR };
},
shouldRenderCommentButton() {
- return (
- this.isLoggedIn &&
- !this.line.isContextLineLeft &&
- !this.line.isMetaLineLeft &&
- !this.line.hasDiscussionsLeft &&
- !this.line.hasDiscussionsRight
- );
+ return this.isLoggedIn && !this.line.isContextLineLeft && !this.line.isMetaLineLeft;
},
isLeftConflictMarker() {
return [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(this.line.left?.type);
@@ -168,7 +163,7 @@ export default {
this.$emit('enterdragging', { ...line, index });
},
onDragStart(line) {
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
this.dragging = true;
this.$emit('startdragging', line);
},
@@ -199,7 +194,7 @@ export default {
>
<template v-if="!isLeftConflictMarker">
<span
- v-if="shouldRenderCommentButton"
+ v-if="shouldRenderCommentButton && !line.hasDiscussionsLeft"
v-gl-tooltip
data-testid="leftCommentButton"
class="add-diff-note tooltip-wrapper"
@@ -301,7 +296,7 @@ export default {
<div :class="classNameMapCellRight" class="diff-td diff-line-num new_line">
<template v-if="line.right.type !== $options.CONFLICT_MARKER_THEIR">
<span
- v-if="shouldRenderCommentButton"
+ v-if="shouldRenderCommentButton && !line.hasDiscussionsRight"
v-gl-tooltip
data-testid="rightCommentButton"
class="add-diff-note tooltip-wrapper"
diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js
index 7606c39ad37..cd45474afcd 100644
--- a/app/assets/javascripts/diffs/components/diff_row_utils.js
+++ b/app/assets/javascripts/diffs/components/diff_row_utils.js
@@ -50,11 +50,11 @@ export const classNameMapCell = ({ line, hll, isLoggedIn, isHover }) => {
];
};
-export const addCommentTooltip = (line) => {
+export const addCommentTooltip = (line, dragCommentSelectionEnabled = false) => {
let tooltip;
if (!line) return tooltip;
- tooltip = gon.drag_comment_selection
+ tooltip = dragCommentSelectionEnabled
? __('Add a comment to this line or drag for multiple lines')
: __('Add a comment to this line');
const brokenSymlinks = line.commentsDisabled;
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
index f229fc4cf60..0303700f42a 100644
--- a/app/assets/javascripts/diffs/components/diff_stats.vue
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -1,6 +1,6 @@
<script>
-import { isNumber } from 'lodash';
import { GlIcon } from '@gitlab/ui';
+import { isNumber } from 'lodash';
import { n__ } from '~/locale';
export default {
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 79800f835f4..43cfa22073f 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -1,11 +1,11 @@
<script>
import { mapGetters, mapState, mapActions } from 'vuex';
-import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import DraftNote from '~/batch_comments/components/draft_note.vue';
-import DiffRow from './diff_row.vue';
+import draftCommentsMixin from '~/diffs/mixins/draft_comments';
+import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
import DiffCommentCell from './diff_comment_cell.vue';
import DiffExpansionCell from './diff_expansion_cell.vue';
-import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
+import DiffRow from './diff_row.vue';
export default {
components: {
@@ -61,10 +61,10 @@ export default {
...mapActions(['setSelectedCommentPosition']),
...mapActions('diffs', ['showCommentForm']),
showCommentLeft(line) {
- return !this.inline || line.left;
+ return line.left && !line.right;
},
showCommentRight(line) {
- return !this.inline || (line.right && !line.left);
+ return line.right && !line.left;
},
onStartDragging(line) {
this.dragStart = line;
@@ -138,24 +138,30 @@ export default {
:class="line.commentRowClasses"
class="diff-grid-comments diff-tr notes_holder"
>
- <div v-if="showCommentLeft(line)" class="diff-td notes-content parallel old">
+ <div
+ v-if="line.left || !inline"
+ :class="{ parallel: !inline }"
+ class="diff-td notes-content old"
+ >
<diff-comment-cell
- v-if="line.left"
+ v-if="line.left && (line.left.renderDiscussion || line.left.hasCommentForm)"
:line="line.left"
:diff-file-hash="diffFile.file_hash"
:help-page-path="helpPagePath"
- :has-draft="line.left.hasDraft"
line-position="left"
/>
</div>
- <div v-if="showCommentRight(line)" class="diff-td notes-content parallel new">
+ <div
+ v-if="line.right || !inline"
+ :class="{ parallel: !inline }"
+ class="diff-td notes-content new"
+ >
<diff-comment-cell
- v-if="line.right"
+ v-if="line.right && (line.right.renderDiscussion || line.right.hasCommentForm)"
:line="line.right"
:diff-file-hash="diffFile.file_hash"
:line-index="index"
:help-page-path="helpPagePath"
- :has-draft="line.right.hasDraft"
line-position="right"
/>
</div>
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
index 6a1e0d8cbd6..3d05202fb2d 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 { mapActions, mapGetters } from 'vuex';
+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 { GlIcon } from '@gitlab/ui';
function calcPercent(pos, size, renderedSize) {
return (((pos / size) * 100) / ((renderedSize / size) * 100)) * 100;
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index 014b1ebe54b..154f2fdcfc7 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { CONTEXT_LINE_CLASS_NAME } from '../constants';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import {
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index 28485a2fdac..e407609d9e9 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -1,12 +1,12 @@
<script>
import { mapGetters, mapState } from 'vuex';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import DraftNote from '~/batch_comments/components/draft_note.vue';
-import inlineDiffTableRow from './inline_diff_table_row.vue';
+import draftCommentsMixin from '~/diffs/mixins/draft_comments';
+import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import DiffCommentCell from './diff_comment_cell.vue';
import DiffExpansionCell from './diff_expansion_cell.vue';
-import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
+import inlineDiffTableRow from './inline_diff_table_row.vue';
export default {
components: {
diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue
index e0fdbf6ac3a..ab518fcfb16 100644
--- a/app/assets/javascripts/diffs/components/no_changes.vue
+++ b/app/assets/javascripts/diffs/components/no_changes.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlButton, GlSprintf } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
index 47eecef2385..3d20dfd0c9b 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -1,7 +1,7 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
-import $ from 'jquery';
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import $ from 'jquery';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { CONTEXT_LINE_CLASS_NAME, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
import * as utils from './diff_row_utils';
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index 21e0bf18dbf..b167081a379 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -1,11 +1,11 @@
<script>
import { mapGetters, mapState } from 'vuex';
-import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import DraftNote from '~/batch_comments/components/draft_note.vue';
-import parallelDiffTableRow from './parallel_diff_table_row.vue';
+import draftCommentsMixin from '~/diffs/mixins/draft_comments';
+import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
import DiffCommentCell from './diff_comment_cell.vue';
import DiffExpansionCell from './diff_expansion_cell.vue';
-import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
+import parallelDiffTableRow from './parallel_diff_table_row.vue';
export default {
components: {
diff --git a/app/assets/javascripts/diffs/components/settings_dropdown.vue b/app/assets/javascripts/diffs/components/settings_dropdown.vue
index 2fe2fd6b3d8..7d74e81257a 100644
--- a/app/assets/javascripts/diffs/components/settings_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/settings_dropdown.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButtonGroup, GlButton, GlDropdown, GlFormCheckbox } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
-import eventHub from '../event_hub';
import { EVT_VIEW_FILE_BY_FILE } from '../constants';
+import eventHub from '../event_hub';
import { SETTINGS_DROPDOWN } from '../i18n';
export default {
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index 1a258695fa0..39ce849fc03 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { s__, sprintf } from '~/locale';
import FileTree from '~/vue_shared/components/file_tree.vue';
import DiffFileRow from './diff_file_row.vue';
diff --git a/app/assets/javascripts/diffs/i18n.js b/app/assets/javascripts/diffs/i18n.js
index c4ac99ead91..2a061876937 100644
--- a/app/assets/javascripts/diffs/i18n.js
+++ b/app/assets/javascripts/diffs/i18n.js
@@ -1,13 +1,16 @@
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
export const GENERIC_ERROR = __('Something went wrong on our end. Please try again!');
export const DIFF_FILE_HEADER = {
optionsDropdownTitle: __('Options'),
+ fileReviewLabel: __('Viewed'),
+ fileReviewTooltip: __('Collapses this file (only for you) until it’s changed again.'),
};
export const DIFF_FILE = {
- blobView: __('You can %{linkStart}view the blob%{linkEnd} instead.'),
+ tooLarge: s__('MRDiffFile|Changes are too large to be shown.'),
+ blobView: s__('MRDiffFile|View file @ %{commitSha}'),
editInFork: __(
"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.",
),
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index 4e0720c645a..68fe204d955 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -1,15 +1,14 @@
+import Cookies from 'js-cookie';
import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex';
-import Cookies from 'js-cookie';
import { parseBoolean } from '~/lib/utils/common_utils';
import FindFile from '~/vue_shared/components/file_finder/index.vue';
import eventHub from '../notes/event_hub';
import diffsApp from './components/app.vue';
-import { getDerivedMergeRequestInformation } from './utils/merge_request';
-import { getReviewsForMergeRequest } from './utils/file_reviews';
-
import { TREE_LIST_STORAGE_KEY, DIFF_WHITESPACE_COOKIE_NAME } from './constants';
+import { getReviewsForMergeRequest } from './utils/file_reviews';
+import { getDerivedMergeRequestInformation } from './utils/merge_request';
export default function initDiffsApp(store) {
const fileFinderEl = document.getElementById('js-diff-file-finder');
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index e95e9ac3ee4..4b2dc2d45df 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -1,25 +1,14 @@
-import Vue from 'vue';
import Cookies from 'js-cookie';
-import Poll from '~/lib/utils/poll';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
+import Vue from 'vue';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { __, s__ } from '~/locale';
+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';
-import TreeWorker from '../workers/tree_worker';
+import { __, s__ } from '~/locale';
import notesEventHub from '../../notes/event_hub';
-import eventHub from '../event_hub';
-import {
- getDiffPositionByLineCode,
- getNoteFormData,
- convertExpandLines,
- idleCallback,
- allDiscussionWrappersExpanded,
- prepareDiffData,
- prepareLineForRenamedFile,
-} from './utils';
-import * as types from './mutation_types';
import {
PARALLEL_DIFF_VIEW_TYPE,
INLINE_DIFF_VIEW_TYPE,
@@ -48,10 +37,21 @@ import {
DIFF_VIEW_ALL_FILES,
DIFF_FILE_BY_FILE_COOKIE_NAME,
} from '../constants';
-import { diffViewerModes } from '~/ide/constants';
+import eventHub from '../event_hub';
import { isCollapsed } from '../utils/diff_file';
-import { getDerivedMergeRequestInformation } from '../utils/merge_request';
import { markFileReview, setReviewsForMergeRequest } from '../utils/file_reviews';
+import { getDerivedMergeRequestInformation } from '../utils/merge_request';
+import TreeWorker from '../workers/tree_worker';
+import * as types from './mutation_types';
+import {
+ getDiffPositionByLineCode,
+ getNoteFormData,
+ convertExpandLines,
+ idleCallback,
+ allDiscussionWrappersExpanded,
+ prepareDiffData,
+ prepareLineForRenamedFile,
+} from './utils';
export const setBaseConfig = ({ commit }, options) => {
const {
@@ -749,12 +749,10 @@ export const setFileByFile = ({ commit }, { fileByFile }) => {
);
};
-export function reviewFile({ commit, state, getters }, { file, reviewed = true }) {
+export function reviewFile({ commit, state }, { file, reviewed = true }) {
const { mrPath } = getDerivedMergeRequestInformation({ endpoint: file.load_collapsed_diff_url });
- const reviews = setReviewsForMergeRequest(
- mrPath,
- markFileReview(getters.fileReviews(state), file, reviewed),
- );
+ const reviews = markFileReview(state.mrReviews, file, reviewed);
+ setReviewsForMergeRequest(mrPath, reviews);
commit(types.SET_MR_FILE_REVIEWS, reviews);
}
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index a167b6d4694..1fc2a684e95 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,11 +1,11 @@
import { __, n__ } from '~/locale';
-import { parallelizeDiffLines } from './utils';
-import { isFileReviewed } from '../utils/file_reviews';
import {
PARALLEL_DIFF_VIEW_TYPE,
INLINE_DIFF_VIEW_TYPE,
INLINE_DIFF_LINES_KEY,
} from '../constants';
+import { computeSuggestionCommitMessage } from '../utils/suggestions';
+import { parallelizeDiffLines } from './utils';
export * from './getters_versions_dropdowns';
@@ -156,6 +156,17 @@ export const diffLines = (state) => (file, unifiedDiffComponents) => {
);
};
-export function fileReviews(state) {
- return state.diffFiles.map((file) => isFileReviewed(state.mrReviews, file));
+export function suggestionCommitMessage(state) {
+ return (values = {}) =>
+ computeSuggestionCommitMessage({
+ message: state.defaultSuggestionCommitMessage,
+ values: {
+ branch_name: state.branchName,
+ project_path: state.projectPath,
+ project_name: state.projectName,
+ username: state.username,
+ user_full_name: state.userFullName,
+ ...values,
+ },
+ });
}
diff --git a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
index 3f33b0c900e..01811e60caa 100644
--- a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
+++ b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
@@ -1,5 +1,5 @@
-import { __, n__, sprintf } from '~/locale';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
+import { __, n__, sprintf } from '~/locale';
import { DIFF_COMPARE_BASE_VERSION_INDEX, DIFF_COMPARE_HEAD_VERSION_INDEX } from '../constants';
export const selectedTargetIndex = (state) =>
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index aa89c74cef0..f93435363ec 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -47,4 +47,5 @@ export default () => ({
showSuggestPopover: true,
defaultSuggestionCommitMessage: '',
mrReviews: {},
+ latestDiff: true,
});
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 06f0f2c3dfb..d06793c05af 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -1,6 +1,12 @@
import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import {
+ DIFF_FILE_MANUAL_COLLAPSE,
+ DIFF_FILE_AUTOMATIC_COLLAPSE,
+ INLINE_DIFF_LINES_KEY,
+} from '../constants';
+import * as types from './mutation_types';
+import {
findDiffFile,
addLineReferences,
removeMatchLine,
@@ -9,12 +15,6 @@ import {
isDiscussionApplicableToLine,
updateLineInFile,
} from './utils';
-import {
- DIFF_FILE_MANUAL_COLLAPSE,
- DIFF_FILE_AUTOMATIC_COLLAPSE,
- INLINE_DIFF_LINES_KEY,
-} from '../constants';
-import * as types from './mutation_types';
function updateDiffFilesInState(state, files) {
return Object.assign(state, { diffFiles: files });
@@ -159,7 +159,12 @@ export default {
[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { discussion, diffPositionByLineCode, hash }) {
const { latestDiff } = state;
- const discussionLineCodes = [discussion.line_code, ...(discussion.line_codes || [])];
+ const originalStartLineCode = discussion.original_position?.line_range?.start?.line_code;
+ const discussionLineCodes = [
+ discussion.line_code,
+ originalStartLineCode,
+ ...(discussion.line_codes || []),
+ ];
const fileHash = discussion.diff_file.file_hash;
const lineCheck = (line) =>
discussionLineCodes.some(
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index c52da558be2..87b4f33c216 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -1,6 +1,6 @@
import { property, isEqual } from 'lodash';
-import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
import { diffModes, diffViewerModes } from '~/ide/constants';
+import { truncatePathMiddleToLength } from '~/lib/utils/text_utility';
import {
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
diff --git a/app/assets/javascripts/diffs/utils/diff_file.js b/app/assets/javascripts/diffs/utils/diff_file.js
index ce0398e75fc..7e6fde320d2 100644
--- a/app/assets/javascripts/diffs/utils/diff_file.js
+++ b/app/assets/javascripts/diffs/utils/diff_file.js
@@ -1,3 +1,5 @@
+import { truncateSha } from '~/lib/utils/text_utility';
+
import {
DIFF_FILE_SYMLINK_MODE,
DIFF_FILE_DELETED_MODE,
@@ -78,3 +80,7 @@ export function isCollapsed(file) {
return collapsedStates[type];
}
+
+export function getShortShaFromFile(file) {
+ return file.content_sha ? truncateSha(String(file.content_sha)) : null;
+}
diff --git a/app/assets/javascripts/diffs/utils/file_reviews.js b/app/assets/javascripts/diffs/utils/file_reviews.js
index 0047955643a..5fafc1714ae 100644
--- a/app/assets/javascripts/diffs/utils/file_reviews.js
+++ b/app/assets/javascripts/diffs/utils/file_reviews.js
@@ -2,6 +2,16 @@ function getFileReviewsKey(mrPath) {
return `${mrPath}-file-reviews`;
}
+export function isFileReviewed(reviews, file) {
+ const fileReviews = reviews[file.file_identifier_hash];
+
+ return file?.id && fileReviews?.length ? new Set(fileReviews).has(file.id) : false;
+}
+
+export function reviewStatuses(files, reviews) {
+ return files.map((file) => isFileReviewed(reviews, file));
+}
+
export function getReviewsForMergeRequest(mrPath) {
const reviewsForMr = localStorage.getItem(getFileReviewsKey(mrPath));
let reviews = {};
@@ -23,23 +33,17 @@ export function setReviewsForMergeRequest(mrPath, reviews) {
return reviews;
}
-export function isFileReviewed(reviews, file) {
- const fileReviews = reviews[file.file_identifier_hash];
-
- return file?.id && fileReviews?.length ? new Set(fileReviews).has(file.id) : false;
-}
-
export function reviewable(file) {
return Boolean(file.id) && Boolean(file.file_identifier_hash);
}
export function markFileReview(reviews, file, reviewed = true) {
const usableReviews = { ...(reviews || {}) };
- let updatedReviews = usableReviews;
+ const updatedReviews = usableReviews;
let fileReviews;
if (reviewable(file)) {
- fileReviews = new Set([...(usableReviews[file.file_identifier_hash] || [])]);
+ fileReviews = new Set(usableReviews[file.file_identifier_hash] || []);
if (reviewed) {
fileReviews.add(file.id);
@@ -47,10 +51,7 @@ export function markFileReview(reviews, file, reviewed = true) {
fileReviews.delete(file.id);
}
- updatedReviews = {
- ...usableReviews,
- [file.file_identifier_hash]: Array.from(fileReviews),
- };
+ updatedReviews[file.file_identifier_hash] = Array.from(fileReviews);
if (updatedReviews[file.file_identifier_hash].length === 0) {
delete updatedReviews[file.file_identifier_hash];
diff --git a/app/assets/javascripts/diffs/utils/performance.js b/app/assets/javascripts/diffs/utils/performance.js
index dcde6f4ecc4..50bf17001a6 100644
--- a/app/assets/javascripts/diffs/utils/performance.js
+++ b/app/assets/javascripts/diffs/utils/performance.js
@@ -9,7 +9,6 @@ import {
MR_DIFFS_MEASURE_DIFF_FILES_DONE,
} from '../../performance/constants';
-import eventHub from '../event_hub';
import {
EVT_PERF_MARK_FILE_TREE_START,
EVT_PERF_MARK_FILE_TREE_END,
@@ -17,6 +16,7 @@ import {
EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
EVT_PERF_MARK_DIFF_FILES_END,
} from '../constants';
+import eventHub from '../event_hub';
function treeStart() {
performanceMarkAndMeasure({
diff --git a/app/assets/javascripts/diffs/utils/suggestions.js b/app/assets/javascripts/diffs/utils/suggestions.js
new file mode 100644
index 00000000000..a272f7f3257
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/suggestions.js
@@ -0,0 +1,28 @@
+function removeEmptyProperties(dict) {
+ const noBlanks = Object.entries(dict).reduce((final, [key, value]) => {
+ const upd = { ...final };
+
+ // The number 0 shouldn't be falsey when we're printing variables
+ if (value || value === 0) {
+ upd[key] = value;
+ }
+
+ return upd;
+ }, {});
+
+ return noBlanks;
+}
+
+export function computeSuggestionCommitMessage({ message, values = {} } = {}) {
+ const noEmpties = removeEmptyProperties(values);
+ const matchPhrases = Object.keys(noEmpties)
+ .map((key) => `%{${key}}`)
+ .join('|');
+ const replacementExpression = new RegExp(`(${matchPhrases})`, 'gm');
+
+ return message.replace(replacementExpression, (match) => {
+ const key = match.replace(/(^%{|}$)/gm, '');
+
+ return noEmpties[key];
+ });
+}
diff --git a/app/assets/javascripts/diffs/utils/uuids.js b/app/assets/javascripts/diffs/utils/uuids.js
index 1fe5f9f6499..98fe4bf9664 100644
--- a/app/assets/javascripts/diffs/utils/uuids.js
+++ b/app/assets/javascripts/diffs/utils/uuids.js
@@ -12,8 +12,8 @@
*/
import { MersenneTwister } from 'fast-mersenne-twister';
-import stringHash from 'string-hash';
import { isString } from 'lodash';
+import stringHash from 'string-hash';
import { v4 } from 'uuid';
function getSeed(seeds) {
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_form.js b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
index 54fd5f91194..db13daf0799 100644
--- a/app/assets/javascripts/dirty_submit/dirty_submit_form.js
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
@@ -1,5 +1,5 @@
-import { memoize, throttle } from 'lodash';
import $ from 'jquery';
+import { memoize, throttle } from 'lodash';
class DirtySubmitForm {
constructor(form) {
diff --git a/app/assets/javascripts/droplab/drop_down.js b/app/assets/javascripts/droplab/drop_down.js
index f4a0b3ed727..05b741af191 100644
--- a/app/assets/javascripts/droplab/drop_down.js
+++ b/app/assets/javascripts/droplab/drop_down.js
@@ -1,5 +1,5 @@
-import utils from './utils';
import { SELECTED_CLASS, IGNORE_CLASS } from './constants';
+import utils from './utils';
class DropDown {
constructor(list, config = {}) {
diff --git a/app/assets/javascripts/droplab/drop_lab.js b/app/assets/javascripts/droplab/drop_lab.js
index 537a05aebb9..74fa6887ba5 100644
--- a/app/assets/javascripts/droplab/drop_lab.js
+++ b/app/assets/javascripts/droplab/drop_lab.js
@@ -1,8 +1,8 @@
+import { DATA_TRIGGER } from './constants';
import HookButton from './hook_button';
import HookInput from './hook_input';
-import utils from './utils';
import Keyboard from './keyboard';
-import { DATA_TRIGGER } from './constants';
+import utils from './utils';
class DropLab {
constructor() {
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index d7aacfbce60..337f7ae2757 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -1,13 +1,13 @@
-import $ from 'jquery';
import Dropzone from 'dropzone';
+import $ from 'jquery';
import { escape } from 'lodash';
import './behaviors/preview_markdown';
+import { spriteIcon } from '~/lib/utils/common_utils';
+import { getFilename } from '~/lib/utils/file_upload';
+import { n__, __ } from '~/locale';
import PasteMarkdownTable from './behaviors/markdown/paste_markdown_table';
-import csrf from './lib/utils/csrf';
import axios from './lib/utils/axios_utils';
-import { n__, __ } from '~/locale';
-import { getFilename } from '~/lib/utils/file_upload';
-import { spriteIcon } from '~/lib/utils/common_utils';
+import csrf from './lib/utils/csrf';
Dropzone.autoDiscover = false;
diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js
index c311e1b561c..1f57d73d3d3 100644
--- a/app/assets/javascripts/due_date_select.js
+++ b/app/assets/javascripts/due_date_select.js
@@ -1,12 +1,12 @@
/* eslint-disable max-classes-per-file */
+import dateFormat from 'dateformat';
import $ from 'jquery';
import Pikaday from 'pikaday';
-import dateFormat from 'dateformat';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { __ } from '~/locale';
+import boardsStore from './boards/stores/boards_store';
import axios from './lib/utils/axios_utils';
import { timeFor, parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
-import boardsStore from './boards/stores/boards_store';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
class DueDateSelect {
constructor({ $dropdown, $loading } = {}) {
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js
index 8d1a3d17c6e..d9e6a6c13e2 100644
--- a/app/assets/javascripts/editor/constants.js
+++ b/app/assets/javascripts/editor/constants.js
@@ -11,6 +11,11 @@ export const ERROR_INSTANCE_REQUIRED_FOR_EXTENSION = __(
'Editor Lite instance is required to set up an extension.',
);
+export const EDITOR_READY_EVENT = 'editor-ready';
+
+export const EDITOR_TYPE_CODE = 'vs.editor.ICodeEditor';
+export const EDITOR_TYPE_DIFF = 'vs.editor.IDiffEditor';
+
//
// EXTENSIONS' CONSTANTS
//
diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js
index 1808f968b8c..79beb3a4857 100644
--- a/app/assets/javascripts/editor/editor_lite.js
+++ b/app/assets/javascripts/editor/editor_lite.js
@@ -1,12 +1,17 @@
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
-import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
-import languages from '~/ide/lib/languages';
+import { uuids } from '~/diffs/utils/uuids';
import { defaultEditorOptions } from '~/ide/lib/editor_options';
+import languages from '~/ide/lib/languages';
+import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
import { registerLanguages } from '~/ide/utils';
import { joinPaths } from '~/lib/utils/url_utility';
+import {
+ EDITOR_LITE_INSTANCE_ERROR_NO_EL,
+ URI_PREFIX,
+ EDITOR_READY_EVENT,
+ EDITOR_TYPE_DIFF,
+} from './constants';
import { clearDomElement } from './utils';
-import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from './constants';
-import { uuids } from '~/diffs/utils/uuids';
export default class EditorLite {
constructor(options = {}) {
@@ -29,15 +34,12 @@ export default class EditorLite {
monacoEditor.setTheme(theme ? themeName : DEFAULT_THEME);
}
- static updateModelLanguage(path, instance) {
- if (!instance) return;
- const model = instance.getModel();
+ static getModelLanguage(path) {
const ext = `.${path.split('.').pop()}`;
const language = monacoLanguages
.getLanguages()
.find((lang) => lang.extensions.indexOf(ext) !== -1);
- const id = language ? language.id : 'plaintext';
- monacoEditor.setModelLanguage(model, id);
+ return language ? language.id : 'plaintext';
}
static pushToImportsArray(arr, toImport) {
@@ -73,50 +75,19 @@ export default class EditorLite {
});
}
- /**
- * Creates a monaco instance with the given options.
- *
- * @param {Object} options Options used to initialize monaco.
- * @param {Element} options.el The element which will be used to create the monacoEditor.
- * @param {string} options.blobPath The path used as the URI of the model. Monaco uses the extension of this path to determine the language.
- * @param {string} options.blobContent The content to initialize the monacoEditor.
- * @param {string} options.blobGlobalId This is used to help globally identify monaco instances that are created with the same blobPath.
- */
- createInstance({
- el = undefined,
- blobPath = '',
- blobContent = '',
- blobGlobalId = uuids()[0],
- extensions = [],
- ...instanceOptions
- } = {}) {
+ static prepareInstance(el) {
if (!el) {
throw new Error(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
}
clearDomElement(el);
- const uriFilePath = joinPaths(URI_PREFIX, blobGlobalId, blobPath);
-
- const model = monacoEditor.createModel(blobContent, undefined, Uri.file(uriFilePath));
-
monacoEditor.onDidCreateEditor(() => {
delete el.dataset.editorLoading;
});
+ }
- const instance = monacoEditor.create(el, {
- ...this.options,
- ...instanceOptions,
- });
- instance.setModel(model);
- instance.onDidDispose(() => {
- const index = this.instances.findIndex((inst) => inst === instance);
- this.instances.splice(index, 1);
- model.dispose();
- });
- instance.updateModelLanguage = (path) => EditorLite.updateModelLanguage(path, instance);
- instance.use = (args) => this.use(args, instance);
-
+ static manageDefaultExtensions(instance, el, extensions) {
EditorLite.loadExtensions(extensions, instance)
.then((modules) => {
if (modules) {
@@ -126,33 +97,167 @@ export default class EditorLite {
}
})
.then(() => {
- el.dispatchEvent(new Event('editor-ready'));
+ el.dispatchEvent(new Event(EDITOR_READY_EVENT));
})
.catch((e) => {
throw e;
});
+ }
+
+ static createEditorModel({
+ blobPath,
+ blobContent,
+ blobOriginalContent,
+ blobGlobalId,
+ instance,
+ isDiff,
+ } = {}) {
+ if (!instance) {
+ return null;
+ }
+ const uriFilePath = joinPaths(URI_PREFIX, blobGlobalId, blobPath);
+ const uri = Uri.file(uriFilePath);
+ const existingModel = monacoEditor.getModel(uri);
+ const model = existingModel || monacoEditor.createModel(blobContent, undefined, uri);
+ if (!isDiff) {
+ instance.setModel(model);
+ return model;
+ }
+ const diffModel = {
+ original: monacoEditor.createModel(
+ blobOriginalContent,
+ EditorLite.getModelLanguage(model.uri.path),
+ ),
+ modified: model,
+ };
+ instance.setModel(diffModel);
+ return diffModel;
+ }
+
+ static convertMonacoToELInstance = (inst) => {
+ const editorLiteInstanceAPI = {
+ updateModelLanguage: (path) => {
+ return EditorLite.instanceUpdateLanguage(inst, path);
+ },
+ use: (exts = []) => {
+ return EditorLite.instanceApplyExtension(inst, exts);
+ },
+ };
+ const handler = {
+ get(target, prop, receiver) {
+ if (Reflect.has(editorLiteInstanceAPI, prop)) {
+ return editorLiteInstanceAPI[prop];
+ }
+ return Reflect.get(target, prop, receiver);
+ },
+ };
+ return new Proxy(inst, handler);
+ };
+
+ static instanceUpdateLanguage(inst, path) {
+ const lang = EditorLite.getModelLanguage(path);
+ const model = inst.getModel();
+ return monacoEditor.setModelLanguage(model, lang);
+ }
+
+ static instanceApplyExtension(inst, exts = []) {
+ const extensions = [].concat(exts);
+ extensions.forEach((extension) => {
+ EditorLite.mixIntoInstance(extension, inst);
+ });
+ return inst;
+ }
+
+ static instanceRemoveFromRegistry(editor, instance) {
+ const index = editor.instances.findIndex((inst) => inst === instance);
+ editor.instances.splice(index, 1);
+ }
+
+ static instanceDisposeModels(editor, instance, model) {
+ const instanceModel = instance.getModel() || model;
+ if (!instanceModel) {
+ return;
+ }
+ if (instance.getEditorType() === EDITOR_TYPE_DIFF) {
+ const { original, modified } = instanceModel;
+ if (original) {
+ original.dispose();
+ }
+ if (modified) {
+ modified.dispose();
+ }
+ } else {
+ instanceModel.dispose();
+ }
+ }
+
+ /**
+ * Creates a monaco instance with the given options.
+ *
+ * @param {Object} options Options used to initialize monaco.
+ * @param {Element} options.el The element which will be used to create the monacoEditor.
+ * @param {string} options.blobPath The path used as the URI of the model. Monaco uses the extension of this path to determine the language.
+ * @param {string} options.blobContent The content to initialize the monacoEditor.
+ * @param {string} options.blobGlobalId This is used to help globally identify monaco instances that are created with the same blobPath.
+ */
+ createInstance({
+ el = undefined,
+ blobPath = '',
+ blobContent = '',
+ blobOriginalContent = '',
+ blobGlobalId = uuids()[0],
+ extensions = [],
+ isDiff = false,
+ ...instanceOptions
+ } = {}) {
+ EditorLite.prepareInstance(el);
+
+ const createEditorFn = isDiff ? 'createDiffEditor' : 'create';
+ const instance = EditorLite.convertMonacoToELInstance(
+ monacoEditor[createEditorFn].call(this, el, {
+ ...this.options,
+ ...instanceOptions,
+ }),
+ );
+
+ let model;
+ if (instanceOptions.model !== null) {
+ model = EditorLite.createEditorModel({
+ blobGlobalId,
+ blobOriginalContent,
+ blobPath,
+ blobContent,
+ instance,
+ isDiff,
+ });
+ }
+
+ instance.onDidDispose(() => {
+ EditorLite.instanceRemoveFromRegistry(this, instance);
+ EditorLite.instanceDisposeModels(this, instance, model);
+ });
+
+ EditorLite.manageDefaultExtensions(instance, el, extensions);
this.instances.push(instance);
return instance;
}
+ createDiffInstance(args) {
+ return this.createInstance({
+ ...args,
+ isDiff: true,
+ });
+ }
+
dispose() {
this.instances.forEach((instance) => instance.dispose());
}
- use(exts = [], instance = null) {
- const extensions = Array.isArray(exts) ? exts : [exts];
- const initExtensions = (inst) => {
- extensions.forEach((extension) => {
- EditorLite.mixIntoInstance(extension, inst);
- });
- };
- if (instance) {
- initExtensions(instance);
- } else {
- this.instances.forEach((inst) => {
- initExtensions(inst);
- });
- }
+ use(exts) {
+ this.instances.forEach((inst) => {
+ inst.use(exts);
+ });
+ return this;
}
}
diff --git a/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
index eb47c20912e..ae6c89d3942 100644
--- a/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
+++ b/app/assets/javascripts/editor/extensions/editor_ci_schema_ext.js
@@ -1,7 +1,7 @@
import Api from '~/api';
import { registerSchema } from '~/ide/utils';
-import { EditorLiteExtension } from './editor_lite_extension_base';
import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '../constants';
+import { EditorLiteExtension } from './editor_lite_extension_base';
export class CiSchemaExtension extends EditorLiteExtension {
/**
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index fa1024a74a4..d022fcbeabe 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -1,10 +1,11 @@
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { escape, minBy } from 'lodash';
import emojiAliases from 'emojis/aliases.json';
-import axios from '../lib/utils/axios_utils';
import AccessorUtilities from '../lib/utils/accessor';
+import axios from '../lib/utils/axios_utils';
let emojiMap = null;
let validEmojiNames = null;
+export const FALLBACK_EMOJI_KEY = 'grey_question';
export const EMOJI_VERSION = '1';
@@ -30,23 +31,17 @@ async function loadEmoji() {
return data;
}
-async function prepareEmojiMap() {
- emojiMap = await loadEmoji();
+async function loadEmojiWithNames() {
+ return Object.entries(await loadEmoji()).reduce((acc, [key, value]) => {
+ acc[key] = { ...value, name: key };
- validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)];
+ return acc;
+ }, {});
+}
- Object.keys(emojiMap).forEach((name) => {
- emojiMap[name].aliases = [];
- emojiMap[name].name = name;
- });
- Object.entries(emojiAliases).forEach(([alias, name]) => {
- // This check, `if (name in emojiMap)` is necessary during testing. In
- // production, it shouldn't be necessary, because at no point should there
- // be an entry in aliases.json with no corresponding entry in emojis.json.
- // However, during testing, the endpoint for emojis.json is mocked with a
- // small dataset, whereas aliases.json is always `import`ed directly.
- if (name in emojiMap) emojiMap[name].aliases.push(alias);
- });
+async function prepareEmojiMap() {
+ emojiMap = await loadEmojiWithNames();
+ validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)];
}
export function initEmojiMap() {
@@ -63,151 +58,101 @@ export function getValidEmojiNames() {
}
export function isEmojiNameValid(name) {
- return validEmojiNames.indexOf(name) >= 0;
+ if (!emojiMap) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ throw new Error('The emoji map is uninitialized or initialization has not completed');
+ }
+
+ return name in emojiMap || name in emojiAliases;
}
export function getAllEmoji() {
return emojiMap;
}
-/**
- * Retrieves an emoji by name or alias.
- *
- * Note: `initEmojiMap` must have been called and completed before this method
- * can safely be called.
- *
- * @param {String} query The emoji name
- * @param {Boolean} fallback If true, a fallback emoji will be returned if the
- * named emoji does not exist. Defaults to false.
- * @returns {Object} The matching emoji.
- */
-export function getEmoji(query, fallback = false) {
- // TODO https://gitlab.com/gitlab-org/gitlab/-/issues/268208
- const fallbackEmoji = emojiMap.grey_question;
- if (!query) {
- return fallback ? fallbackEmoji : null;
- }
+function getAliasesMatchingQuery(query) {
+ return Object.keys(emojiAliases)
+ .filter((alias) => alias.includes(query))
+ .reduce((map, alias) => {
+ const emojiName = emojiAliases[alias];
+ const score = alias.indexOf(query);
+
+ const prev = map.get(emojiName);
+ // overwrite if we beat the previous score or we're more alphabetical
+ const shouldSet =
+ !prev ||
+ prev.score > score ||
+ (prev.score === score && prev.alias.localeCompare(alias) > 0);
+
+ if (shouldSet) {
+ map.set(emojiName, { score, alias });
+ }
- if (!emojiMap) {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- throw new Error('The emoji map is uninitialized or initialization has not completed');
+ return map;
+ }, new Map());
+}
+
+function getUnicodeMatch(emoji, query) {
+ if (emoji.e === query) {
+ return { score: 0, field: 'e', fieldValue: emoji.name, emoji };
}
- const lowercaseQuery = query.toLowerCase();
- const name = normalizeEmojiName(lowercaseQuery);
+ return null;
+}
- if (name in emojiMap) {
- return emojiMap[name];
+function getDescriptionMatch(emoji, query) {
+ if (emoji.d.includes(query)) {
+ return { score: emoji.d.indexOf(query), field: 'd', fieldValue: emoji.d, emoji };
}
- return fallback ? fallbackEmoji : null;
+ return null;
}
-const searchMatchers = {
- // Fuzzy matching compares using a fuzzy matching library
- fuzzy: (value, query) => {
- const score = fuzzaldrinPlus.score(value, query) > 0;
- return { score, success: score > 0 };
- },
- // Contains matching compares by indexOf
- contains: (value, query) => {
- const index = value.indexOf(query.toLowerCase());
- return { index, success: index >= 0 };
- },
- // Exact matching compares by equality
- exact: (value, query) => {
- return { success: value === query.toLowerCase() };
- },
-};
-
-const searchPredicates = {
- // Search by name
- name: (matcher, query) => (emoji) => {
- const m = matcher(emoji.name, query);
- return [{ ...m, emoji, field: emoji.name }];
- },
- // Search by alias
- alias: (matcher, query) => (emoji) =>
- emoji.aliases.map((alias) => {
- const m = matcher(alias, query);
- return { ...m, emoji, field: alias };
- }),
- // Search by description
- description: (matcher, query) => (emoji) => {
- const m = matcher(emoji.d, query);
- return [{ ...m, emoji, field: emoji.d }];
- },
- // Search by unicode value (always exact)
- unicode: (matcher, query) => (emoji) => {
- return [{ emoji, field: emoji.e, success: emoji.e === query }];
- },
-};
+function getAliasMatch(emoji, matchingAliases) {
+ if (matchingAliases.has(emoji.name)) {
+ const { score, alias } = matchingAliases.get(emoji.name);
-/**
- * Searches emoji by name, aliases, description, and unicode value and returns
- * an array of matches.
- *
- * Behavior is undefined if `opts.fields` is empty or if `opts.match` is fuzzy
- * and the query is empty.
- *
- * Note: `initEmojiMap` must have been called and completed before this method
- * can safely be called.
- *
- * @param {String} query Search query.
- * @param {Object} opts Search options (optional).
- * @param {String[]} opts.fields Fields to search. Choices are 'name', 'alias',
- * 'description', and 'unicode' (value). Default is all (four) fields.
- * @param {String} opts.match Search method to use. Choices are 'exact',
- * 'contains', or 'fuzzy'. All methods are case-insensitive. Exact matching (the
- * default) compares by equality. Contains matching compares by indexOf. Fuzzy
- * matching compares using a fuzzy matching library.
- * @param {Boolean} opts.fallback If true, a fallback emoji will be returned if
- * the result set is empty. Defaults to false.
- * @param {Boolean} opts.raw Returns the raw match data instead of just the
- * matching emoji.
- * @returns {Object[]} A list of emoji that match the query.
- */
-export function searchEmoji(query, opts) {
- if (!emojiMap) {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- throw new Error('The emoji map is uninitialized or initialization has not completed');
+ return { score, field: 'alias', fieldValue: alias, emoji };
}
- const {
- fields = ['name', 'alias', 'description', 'unicode'],
- match = 'exact',
- fallback = false,
- raw = false,
- } = opts || {};
-
- const fallbackEmoji = emojiMap.grey_question;
- if (!query) {
- if (fallback) {
- return raw ? [{ emoji: fallbackEmoji }] : [fallbackEmoji];
- }
+ return null;
+}
- return [];
+function getNameMatch(emoji, query) {
+ if (emoji.name.includes(query)) {
+ return {
+ score: emoji.name.indexOf(query),
+ field: 'name',
+ fieldValue: emoji.name,
+ emoji,
+ };
}
- // optimization for an exact match in name and alias
- if (match === 'exact' && new Set([...fields, 'name', 'alias']).size === 2) {
- const emoji = getEmoji(query, fallback);
- return emoji ? [emoji] : [];
- }
+ return null;
+}
- const matcher = searchMatchers[match] || searchMatchers.exact;
- const predicates = fields.map((f) => searchPredicates[f](matcher, query));
+export function searchEmoji(query) {
+ const lowercaseQuery = query ? `${query}`.toLowerCase() : '';
- const results = Object.values(emojiMap)
- .flatMap((emoji) => predicates.flatMap((predicate) => predicate(emoji)))
- .filter((r) => r.success);
+ const matchingAliases = getAliasesMatchingQuery(lowercaseQuery);
- // Fallback to question mark for unknown emojis
- if (fallback && results.length === 0) {
- return raw ? [{ emoji: fallbackEmoji }] : [fallbackEmoji];
- }
+ return Object.values(emojiMap)
+ .map((emoji) => {
+ const matches = [
+ getUnicodeMatch(emoji, query),
+ getDescriptionMatch(emoji, lowercaseQuery),
+ getAliasMatch(emoji, matchingAliases),
+ getNameMatch(emoji, lowercaseQuery),
+ ].filter(Boolean);
- return raw ? results : results.map((r) => r.emoji);
+ return minBy(matches, (x) => x.score);
+ })
+ .filter(Boolean);
+}
+
+export function sortEmoji(items) {
+ // Sort results by index of and string comparison
+ return [...items].sort((a, b) => a.score - b.score || a.fieldValue.localeCompare(b.fieldValue));
}
let emojiCategoryMap;
@@ -233,11 +178,28 @@ export function getEmojiCategoryMap() {
return emojiCategoryMap;
}
-export function getEmojiInfo(query) {
- return searchEmoji(query, {
- fields: ['name', 'alias'],
- fallback: true,
- })[0];
+/**
+ * Retrieves an emoji by name
+ *
+ * @param {String} query The emoji name
+ * @param {Boolean} fallback If true, a fallback emoji will be returned if the
+ * named emoji does not exist.
+ * @returns {Object} The matching emoji.
+ */
+export function getEmojiInfo(query, fallback = true) {
+ if (!emojiMap) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ throw new Error('The emoji map is uninitialized or initialization has not completed');
+ }
+
+ const lowercaseQuery = query ? `${query}`.toLowerCase() : '';
+ const name = normalizeEmojiName(lowercaseQuery);
+
+ if (name in emojiMap) {
+ return emojiMap[name];
+ }
+
+ return fallback ? emojiMap[FALLBACK_EMOJI_KEY] : null;
}
export function emojiFallbackImageSrc(inputName) {
@@ -257,12 +219,8 @@ export function glEmojiTag(inputName, options) {
const fallbackSpriteClass = `emoji-${name}`;
const fallbackSpriteAttribute = opts.sprite
- ? `data-fallback-sprite-class="${fallbackSpriteClass}"`
+ ? `data-fallback-sprite-class="${escape(fallbackSpriteClass)}" `
: '';
- return `
- <gl-emoji
- ${fallbackSpriteAttribute}
- data-name="${name}"></gl-emoji>
- `;
+ return `<gl-emoji ${fallbackSpriteAttribute}data-name="${escape(name)}"></gl-emoji>`;
}
diff --git a/app/assets/javascripts/environments/components/canary_ingress.vue b/app/assets/javascripts/environments/components/canary_ingress.vue
index f8cdbb96bc2..02d660a91c1 100644
--- a/app/assets/javascripts/environments/components/canary_ingress.vue
+++ b/app/assets/javascripts/environments/components/canary_ingress.vue
@@ -1,6 +1,6 @@
<script>
-import { uniqueId } from 'lodash';
import { GlDropdown, GlDropdownItem, GlModalDirective as GlModal } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
import { s__ } from '~/locale';
import { CANARY_UPDATE_MODAL } from '../constants';
diff --git a/app/assets/javascripts/environments/components/canary_update_modal.vue b/app/assets/javascripts/environments/components/canary_update_modal.vue
index fc63d6272c8..8b1121c7158 100644
--- a/app/assets/javascripts/environments/components/canary_update_modal.vue
+++ b/app/assets/javascripts/environments/components/canary_update_modal.vue
@@ -1,8 +1,8 @@
<script>
import { GlAlert, GlModal, GlSprintf } from '@gitlab/ui';
import { __, s__ } from '~/locale';
-import updateCanaryIngress from '../graphql/mutations/update_canary_ingress.mutation.graphql';
import { CANARY_UPDATE_MODAL } from '../constants';
+import updateCanaryIngress from '../graphql/mutations/update_canary_ingress.mutation.graphql';
export default {
components: {
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
index b2a8571820b..76ad74e04d0 100644
--- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -4,8 +4,8 @@
* Render modal to confirm rollback/redeploy.
*/
-import { escape } from 'lodash';
import { GlModal } from '@gitlab/ui';
+import { escape } from 'lodash';
import { s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index c6b34fecbb7..9e058af56c4 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -26,26 +26,6 @@ export default {
type: Boolean,
required: true,
},
- deployBoardsHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- helpCanaryDeploymentsPath: {
- type: String,
- required: false,
- default: '',
- },
- lockPromotionSvgPath: {
- type: String,
- required: false,
- default: '',
- },
- userCalloutsPath: {
- type: String,
- required: false,
- default: '',
- },
},
methods: {
onChangePage(page) {
@@ -62,14 +42,7 @@ export default {
<slot name="empty-state"></slot>
<div v-if="!isLoading && environments.length > 0" class="table-holder">
- <environment-table
- :environments="environments"
- :can-read-environment="canReadEnvironment"
- :user-callouts-path="userCalloutsPath"
- :lock-promotion-svg-path="lockPromotionSvgPath"
- :help-canary-deployments-path="helpCanaryDeploymentsPath"
- :deploy-boards-help-path="deployBoardsHelpPath"
- />
+ <environment-table :environments="environments" :can-read-environment="canReadEnvironment" />
<table-pagination
v-if="pagination && pagination.totalPages > 1"
diff --git a/app/assets/javascripts/environments/components/deploy_board.vue b/app/assets/javascripts/environments/components/deploy_board.vue
index 07cb968d8d3..f9c4660036b 100644
--- a/app/assets/javascripts/environments/components/deploy_board.vue
+++ b/app/assets/javascripts/environments/components/deploy_board.vue
@@ -9,7 +9,7 @@
* - Button Actions.
* [Mockup](https://gitlab.com/gitlab-org/gitlab-foss/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png)
*/
-import { isEmpty } from 'lodash';
+import deployBoardSvg from '@gitlab/svgs/dist/illustrations/deploy-boards.svg';
import {
GlIcon,
GlLoadingIcon,
@@ -18,9 +18,9 @@ import {
GlTooltipDirective,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
-import deployBoardSvg from '@gitlab/svgs/dist/illustrations/deploy-boards.svg';
-import instanceComponent from '~/vue_shared/components/deployment_instance.vue';
+import { isEmpty } from 'lodash';
import { 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';
@@ -44,11 +44,6 @@ export default {
type: Object,
required: true,
},
- deployBoardsHelpPath: {
- type: String,
- required: false,
- default: '',
- },
isLoading: {
type: Boolean,
required: true,
diff --git a/app/assets/javascripts/environments/components/enable_review_app_modal.vue b/app/assets/javascripts/environments/components/enable_review_app_modal.vue
index 3dd1d5a1bcc..2494968857c 100644
--- a/app/assets/javascripts/environments/components/enable_review_app_modal.vue
+++ b/app/assets/javascripts/environments/components/enable_review_app_modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlModal, GlSprintf } from '@gitlab/ui';
-import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import { s__ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
export default {
components: {
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index 2192d456861..8911380290a 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
import { formatTime } from '~/lib/utils/datetime_utility';
+import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
diff --git a/app/assets/javascripts/environments/components/environment_delete.vue b/app/assets/javascripts/environments/components/environment_delete.vue
index 75d92d3295d..4b7917b4572 100644
--- a/app/assets/javascripts/environments/components/environment_delete.vue
+++ b/app/assets/javascripts/environments/components/environment_delete.vue
@@ -5,6 +5,7 @@
*/
import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
@@ -40,7 +41,7 @@ export default {
},
methods: {
onClick() {
- this.$root.$emit('bv::hide::tooltip', this.$options.deleteEnvironmentTooltipId);
+ this.$root.$emit(BV_HIDE_TOOLTIP, this.$options.deleteEnvironmentTooltipId);
eventHub.$emit('requestDeleteEnvironment', this.environment);
},
onDeleteEnvironment(environment) {
@@ -59,7 +60,7 @@ export default {
:loading="isLoading"
:title="title"
:aria-label="title"
- class="gl-display-none gl-display-md-block"
+ class="gl-display-none gl-md-display-block"
variant="danger"
category="primary"
icon="remove"
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 1724cc692bd..4db0dff16aa 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -1,22 +1,22 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { isEmpty } from 'lodash';
import { GlTooltipDirective, GlIcon, GlLink } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
+import { isEmpty } from 'lodash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import { __, s__, sprintf } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
import CommitComponent from '~/vue_shared/components/commit.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
import eventHub from '../event_hub';
import ActionsComponent from './environment_actions.vue';
+import DeleteComponent from './environment_delete.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import MonitoringButtonComponent from './environment_monitoring.vue';
import PinComponent from './environment_pin.vue';
-import DeleteComponent from './environment_delete.vue';
-import StopComponent from './environment_stop.vue';
import RollbackComponent from './environment_rollback.vue';
+import StopComponent from './environment_stop.vue';
import TerminalButtonComponent from './environment_terminal_button.vue';
/**
@@ -549,7 +549,7 @@ export default {
upcomingDeploymentCellClasses() {
return [
this.tableData.upcoming.spacing,
- { 'gl-display-none gl-display-md-block': !this.upcomingDeployment },
+ { 'gl-display-none gl-md-display-block': !this.upcomingDeployment },
];
},
},
diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue
index 4dc2c0ec1bd..7f70433776d 100644
--- a/app/assets/javascripts/environments/components/environment_monitoring.vue
+++ b/app/assets/javascripts/environments/components/environment_monitoring.vue
@@ -30,7 +30,7 @@ export default {
:href="monitoringUrl"
:title="title"
:aria-label="title"
- class="monitoring-url gl-display-none gl-display-sm-none gl-display-md-block"
+ class="monitoring-url gl-display-none gl-sm-display-none gl-md-display-block"
icon="chart"
rel="noopener noreferrer nofollow"
variant="default"
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 48edde82ce7..397616c654f 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -68,7 +68,7 @@ export default {
<gl-button
v-gl-tooltip
v-gl-modal.confirm-rollback-modal
- class="gl-display-none gl-display-md-block text-secondary"
+ class="gl-display-none gl-md-display-block text-secondary"
:loading="isLoading"
:title="title"
:icon="isLastDeployment ? 'repeat' : 'redo'"
diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue
index 8e100623199..dceaf3cacf1 100644
--- a/app/assets/javascripts/environments/components/environment_stop.vue
+++ b/app/assets/javascripts/environments/components/environment_stop.vue
@@ -5,6 +5,7 @@
*/
import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
@@ -40,7 +41,7 @@ export default {
},
methods: {
onClick() {
- this.$root.$emit('bv::hide::tooltip', this.$options.stopEnvironmentTooltipId);
+ this.$root.$emit(BV_HIDE_TOOLTIP, this.$options.stopEnvironmentTooltipId);
eventHub.$emit('requestStopEnvironment', this.environment);
},
onStopEnvironment(environment) {
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index 6f68c6e864a..ed852895f10 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -2,14 +2,14 @@
import { GlBadge, GlButton, GlModalDirective, GlTab, GlTabs } from '@gitlab/ui';
import { deprecatedCreateFlash as Flash } from '~/flash';
import { s__ } from '~/locale';
-import emptyState from './empty_state.vue';
import eventHub from '../event_hub';
import environmentsMixin from '../mixins/environments_mixin';
-import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
+import EnvironmentsPaginationApiMixin from '../mixins/environments_pagination_api_mixin';
+import ConfirmRollbackModal from './confirm_rollback_modal.vue';
+import DeleteEnvironmentModal from './delete_environment_modal.vue';
+import emptyState from './empty_state.vue';
import EnableReviewAppModal from './enable_review_app_modal.vue';
import StopEnvironmentModal from './stop_environment_modal.vue';
-import DeleteEnvironmentModal from './delete_environment_modal.vue';
-import ConfirmRollbackModal from './confirm_rollback_modal.vue';
export default {
i18n: {
@@ -33,7 +33,7 @@ export default {
directives: {
'gl-modal': GlModalDirective,
},
- mixins: [CIPaginationMixin, environmentsMixin],
+ mixins: [EnvironmentsPaginationApiMixin, environmentsMixin],
props: {
endpoint: {
type: String,
@@ -51,30 +51,10 @@ export default {
type: String,
required: true,
},
- helpCanaryDeploymentsPath: {
- type: String,
- required: false,
- default: '',
- },
helpPagePath: {
type: String,
required: true,
},
- deployBoardsHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- lockPromotionSvgPath: {
- type: String,
- required: false,
- default: '',
- },
- userCalloutsPath: {
- type: String,
- required: false,
- default: '',
- },
},
created() {
@@ -133,7 +113,7 @@ export default {
<confirm-rollback-modal :environment="environmentInRollbackModal" />
<div class="gl-w-full">
- <div class="gl-display-flex gl-flex-direction-column gl-mt-3 gl-display-md-none!">
+ <div class="gl-display-flex gl-flex-direction-column gl-mt-3 gl-md-display-none!">
<gl-button
v-if="state.reviewAppDetails.can_setup_review_app"
v-gl-modal="$options.modal.id"
@@ -167,7 +147,7 @@ export default {
</gl-tab>
<template #tabs-end>
<div
- class="gl-display-none gl-display-md-flex gl-lg-align-items-center gl-lg-flex-direction-row gl-lg-flex-fill-1 gl-lg-justify-content-end gl-lg-mt-0"
+ class="gl-display-none gl-md-display-flex gl-lg-align-items-center gl-lg-flex-direction-row gl-lg-flex-fill-1 gl-lg-justify-content-end gl-lg-mt-0"
>
<gl-button
v-if="state.reviewAppDetails.can_setup_review_app"
@@ -195,10 +175,6 @@ export default {
:environments="state.environments"
:pagination="state.paginationInformation"
:can-read-environment="canReadEnvironment"
- :user-callouts-path="userCalloutsPath"
- :lock-promotion-svg-path="lockPromotionSvgPath"
- :help-canary-deployments-path="helpCanaryDeploymentsPath"
- :deploy-boards-help-path="deployBoardsHelpPath"
@onChangePage="onChangePage"
>
<template v-if="!isLoading && state.environments.length === 0" #empty-state>
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index bbb56ca6f26..cbce887f491 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -5,9 +5,9 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { flow, reverse, sortBy } from 'lodash/fp';
import { s__ } from '~/locale';
-import EnvironmentItem from './environment_item.vue';
-import DeployBoard from './deploy_board.vue';
import CanaryUpdateModal from './canary_update_modal.vue';
+import DeployBoard from './deploy_board.vue';
+import EnvironmentItem from './environment_item.vue';
export default {
components: {
@@ -23,31 +23,11 @@ export default {
required: true,
default: () => [],
},
- deployBoardsHelpPath: {
- type: String,
- required: false,
- default: '',
- },
canReadEnvironment: {
type: Boolean,
required: false,
default: false,
},
- helpCanaryDeploymentsPath: {
- type: String,
- required: false,
- default: '',
- },
- lockPromotionSvgPath: {
- type: String,
- required: false,
- default: '',
- },
- userCalloutsPath: {
- type: String,
- required: false,
- default: '',
- },
},
data() {
return {
@@ -189,7 +169,6 @@ export default {
<div class="deploy-board-container">
<deploy-board
:deploy-board-data="model.deployBoardData"
- :deploy-boards-help-path="deployBoardsHelpPath"
:is-loading="model.isLoadingDeployBoard"
:is-empty="model.isEmptyDeployBoard"
:logs-path="model.logs_path"
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 0832822520d..828a7098b36 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf, GlTooltipDirective, GlModal } from '@gitlab/ui';
-import eventHub from '../event_hub';
import { __, s__ } from '~/locale';
+import eventHub from '../event_hub';
export default {
id: 'stop-environment-modal',
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index e4726412f99..1be9a4608cb 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import environmentsFolderApp from './environments_folder_view.vue';
+import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '../../lib/utils/common_utils';
import Translate from '../../vue_shared/translate';
-import createDefaultClient from '~/lib/graphql';
+import environmentsFolderApp from './environments_folder_view.vue';
Vue.use(Translate);
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index dbb60fa4622..8070f3f12f8 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -1,9 +1,9 @@
<script>
import { GlBadge, GlTab, GlTabs } from '@gitlab/ui';
-import environmentsMixin from '../mixins/environments_mixin';
-import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
-import StopEnvironmentModal from '../components/stop_environment_modal.vue';
import DeleteEnvironmentModal from '../components/delete_environment_modal.vue';
+import StopEnvironmentModal from '../components/stop_environment_modal.vue';
+import environmentsMixin from '../mixins/environments_mixin';
+import EnvironmentsPaginationApiMixin from '../mixins/environments_pagination_api_mixin';
export default {
components: {
@@ -14,7 +14,7 @@ export default {
StopEnvironmentModal,
},
- mixins: [environmentsMixin, CIPaginationMixin],
+ mixins: [environmentsMixin, EnvironmentsPaginationApiMixin],
props: {
endpoint: {
@@ -34,21 +34,6 @@ export default {
type: Boolean,
required: true,
},
- userCalloutsPath: {
- type: String,
- required: false,
- default: '',
- },
- lockPromotionSvgPath: {
- type: String,
- required: false,
- default: '',
- },
- helpCanaryDeploymentsPath: {
- type: String,
- required: false,
- default: '',
- },
},
methods: {
successCallback(resp) {
@@ -88,9 +73,6 @@ export default {
:environments="state.environments"
:pagination="state.paginationInformation"
:can-read-environment="canReadEnvironment"
- :user-callouts-path="userCalloutsPath"
- :lock-promotion-svg-path="lockPromotionSvgPath"
- :help-canary-deployments-path="helpCanaryDeploymentsPath"
@onChangePage="onChangePage"
/>
</div>
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index 4d734a457ab..68348648e61 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import environmentsComponent from './components/environments_app.vue';
+import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '../lib/utils/common_utils';
import Translate from '../vue_shared/translate';
-import createDefaultClient from '~/lib/graphql';
+import environmentsComponent from './components/environments_app.vue';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -30,7 +30,6 @@ export default () => {
endpoint: environmentsData.environmentsDataEndpoint,
newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath,
- deployBoardsHelpPath: environmentsData.deployBoardsHelpPath,
canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
canReadEnvironment: parseBoolean(environmentsData.canReadEnvironment),
};
@@ -41,7 +40,6 @@ export default () => {
endpoint: this.endpoint,
newEnvironmentPath: this.newEnvironmentPath,
helpPagePath: this.helpPagePath,
- deployBoardsHelpPath: this.deployBoardsHelpPath,
canCreateEnvironment: this.canCreateEnvironment,
canReadEnvironment: this.canReadEnvironment,
},
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 15a00c11ee6..d5caff1660a 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -3,18 +3,18 @@
*/
import { isEqual, isFunction, omitBy } from 'lodash';
import Visibility from 'visibilityjs';
-import EnvironmentsStore from '../stores/environments_store';
-import Poll from '../../lib/utils/poll';
+import { deprecatedCreateFlash as Flash } from '../../flash';
import { getParameterByName } from '../../lib/utils/common_utils';
+import Poll from '../../lib/utils/poll';
import { s__ } from '../../locale';
-import { deprecatedCreateFlash as Flash } from '../../flash';
+import tabs from '../../vue_shared/components/navigation_tabs.vue';
+import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
+import container from '../components/container.vue';
+import environmentTable from '../components/environments_table.vue';
import eventHub from '../event_hub';
import EnvironmentsService from '../services/environments_service';
-import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
-import environmentTable from '../components/environments_table.vue';
-import tabs from '../../vue_shared/components/navigation_tabs.vue';
-import container from '../components/container.vue';
+import EnvironmentsStore from '../stores/environments_store';
export default {
components: {
diff --git a/app/assets/javascripts/environments/mixins/environments_pagination_api_mixin.js b/app/assets/javascripts/environments/mixins/environments_pagination_api_mixin.js
new file mode 100644
index 00000000000..b62fe196a6f
--- /dev/null
+++ b/app/assets/javascripts/environments/mixins/environments_pagination_api_mixin.js
@@ -0,0 +1,66 @@
+/**
+ * API callbacks for pagination and tabs
+ *
+ * Components need to have `scope`, `page` and `requestData`
+ */
+import { validateParams } from '~/pipelines/utils';
+import { historyPushState, buildUrlWithCurrentLocation } from '../../lib/utils/common_utils';
+
+export default {
+ methods: {
+ onChangeTab(scope) {
+ if (this.scope === scope) {
+ return;
+ }
+
+ let params = {
+ scope,
+ page: '1',
+ };
+
+ params = this.onChangeWithFilter(params);
+
+ this.updateContent(params);
+ },
+
+ onChangePage(page) {
+ /* URLS parameters are strings, we need to parse to match types */
+ let params = {
+ page: Number(page).toString(),
+ };
+
+ if (this.scope) {
+ params.scope = this.scope;
+ }
+
+ params = this.onChangeWithFilter(params);
+
+ this.updateContent(params);
+ },
+
+ onChangeWithFilter(params) {
+ return { ...params, ...validateParams(this.requestData) };
+ },
+
+ updateInternalState(parameters) {
+ // stop polling
+ this.poll.stop();
+
+ const queryString = Object.keys(parameters)
+ .map((parameter) => {
+ const value = parameters[parameter];
+ // update internal state for UI
+ this[parameter] = value;
+ return `${parameter}=${encodeURIComponent(value)}`;
+ })
+ .join('&');
+
+ // update polling parameters
+ this.requestData = parameters;
+
+ historyPushState(buildUrlWithCurrentLocation(`?${queryString}`));
+
+ this.isLoading = true;
+ },
+ },
+};
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index 8911885e920..f7fdbb03f04 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -1,5 +1,5 @@
-import { setDeployBoard } from './helpers';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import { setDeployBoard } from './helpers';
/**
* Environments Store.
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index e21c6b62b91..03b8df50c54 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import {
GlButton,
GlFormInput,
@@ -13,21 +12,22 @@ import {
GlDropdownDivider,
GlIcon,
} from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __, sprintf, n__ } from '~/locale';
+import Tracking from '~/tracking';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
-import Stacktrace from './stacktrace.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { severityLevel, severityLevelVariant, errorStatus } from './constants';
-import Tracking from '~/tracking';
+import query from '../queries/details.query.graphql';
import {
trackClickErrorLinkToSentryOptions,
trackErrorDetailsViewsOptions,
trackErrorStatusUpdateOptions,
} from '../utils';
-import query from '../queries/details.query.graphql';
+import { severityLevel, severityLevelVariant, errorStatus } from './constants';
+import Stacktrace from './stacktrace.vue';
const SENTRY_TIMEOUT = 10000;
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
index 7ccb6253508..0f564fc3c60 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapState } from 'vuex';
import {
GlEmptyState,
GlButton,
@@ -15,12 +14,14 @@ import {
GlPagination,
} from '@gitlab/ui';
import { isEmpty } from 'lodash';
+import { mapActions, mapState } from 'vuex';
+import { helpPagePath } from '~/helpers/help_page_helper';
import AccessorUtils from '~/lib/utils/accessor';
-import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { __ } from '~/locale';
-import ErrorTrackingActions from './error_tracking_actions.vue';
import Tracking from '~/tracking';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '../utils';
+import ErrorTrackingActions from './error_tracking_actions.vue';
export const tableDataClass = 'table-col d-flex d-md-table-cell align-items-center';
@@ -138,6 +139,9 @@ export default {
paginationRequired() {
return !isEmpty(this.pagination);
},
+ errorTrackingHelpUrl() {
+ return helpPagePath('operations/error_tracking');
+ },
},
watch: {
pagination() {
@@ -404,7 +408,7 @@ export default {
<template #description>
<div>
<span>{{ __('Monitor your errors by integrating with Sentry.') }}</span>
- <gl-link target="_blank" href="/help/user/project/operations/error_tracking.html">{{
+ <gl-link target="_blank" :href="errorTrackingHelpUrl">{{
__('More information')
}}</gl-link>
</div>
diff --git a/app/assets/javascripts/error_tracking/details.js b/app/assets/javascripts/error_tracking/details.js
index 55ab362f805..37b8007d556 100644
--- a/app/assets/javascripts/error_tracking/details.js
+++ b/app/assets/javascripts/error_tracking/details.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import store from './store';
-import ErrorDetails from './components/error_details.vue';
import csrf from '~/lib/utils/csrf';
+import ErrorDetails from './components/error_details.vue';
+import store from './store';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/error_tracking/list.js b/app/assets/javascripts/error_tracking/list.js
index cb656a9ef13..9c729407009 100644
--- a/app/assets/javascripts/error_tracking/list.js
+++ b/app/assets/javascripts/error_tracking/list.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
-import store from './store';
import ErrorTrackingList from './components/error_tracking_list.vue';
+import store from './store';
export default () => {
const selector = '#js-error_tracking';
diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js
index 8f1e7e0b959..a27ebd16956 100644
--- a/app/assets/javascripts/error_tracking/store/actions.js
+++ b/app/assets/javascripts/error_tracking/store/actions.js
@@ -1,8 +1,8 @@
-import service from '../services';
-import * as types from './mutation_types';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
+import service from '../services';
+import * as types from './mutation_types';
export const setStatus = ({ commit }, status) => {
commit(types.SET_ERROR_STATUS, status.toLowerCase());
diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js
index 394dec938cf..7319d45bbd2 100644
--- a/app/assets/javascripts/error_tracking/store/details/actions.js
+++ b/app/assets/javascripts/error_tracking/store/details/actions.js
@@ -1,8 +1,8 @@
-import service from '../../services';
-import * as types from './mutation_types';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
+import service from '../../services';
+import * as types from './mutation_types';
let stackTracePoll;
diff --git a/app/assets/javascripts/error_tracking/store/index.js b/app/assets/javascripts/error_tracking/store/index.js
index d9206bc8d7c..1d8f1998583 100644
--- a/app/assets/javascripts/error_tracking/store/index.js
+++ b/app/assets/javascripts/error_tracking/store/index.js
@@ -2,16 +2,16 @@ import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
-import mutations from './mutations';
+import * as detailsActions from './details/actions';
+import * as detailsGetters from './details/getters';
+import detailsMutations from './details/mutations';
+import detailsState from './details/state';
import * as listActions from './list/actions';
import listMutations from './list/mutations';
import listState from './list/state';
-import * as detailsActions from './details/actions';
-import detailsMutations from './details/mutations';
-import detailsState from './details/state';
-import * as detailsGetters from './details/getters';
+import mutations from './mutations';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/error_tracking/store/list/actions.js b/app/assets/javascripts/error_tracking/store/list/actions.js
index a242c0e4236..f07e546241a 100644
--- a/app/assets/javascripts/error_tracking/store/list/actions.js
+++ b/app/assets/javascripts/error_tracking/store/list/actions.js
@@ -1,8 +1,8 @@
-import Service from '../../services';
-import * as types from './mutation_types';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
+import Service from '../../services';
+import * as types from './mutation_types';
let eTagPoll;
diff --git a/app/assets/javascripts/error_tracking/store/list/mutations.js b/app/assets/javascripts/error_tracking/store/list/mutations.js
index 84a62fa9024..d92a64947ad 100644
--- a/app/assets/javascripts/error_tracking/store/list/mutations.js
+++ b/app/assets/javascripts/error_tracking/store/list/mutations.js
@@ -1,6 +1,6 @@
-import * as types from './mutation_types';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import AccessorUtils from '~/lib/utils/accessor';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import * as types from './mutation_types';
export default {
[types.SET_ERRORS](state, data) {
diff --git a/app/assets/javascripts/error_tracking_settings/components/app.vue b/app/assets/javascripts/error_tracking_settings/components/app.vue
index 786abc8ce49..971eb21ee3b 100644
--- a/app/assets/javascripts/error_tracking_settings/components/app.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/app.vue
@@ -1,8 +1,8 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
-import ProjectDropdown from './project_dropdown.vue';
+import { mapActions, mapGetters, mapState } from 'vuex';
import ErrorTrackingForm from './error_tracking_form.vue';
+import ProjectDropdown from './project_dropdown.vue';
export default {
components: { ProjectDropdown, ErrorTrackingForm, GlButton },
diff --git a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
index b1b699d2e2a..dbcda0877b4 100644
--- a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlFormInput, GlIcon, GlButton } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
export default {
components: { GlFormInput, GlIcon, GlButton },
diff --git a/app/assets/javascripts/error_tracking_settings/store/actions.js b/app/assets/javascripts/error_tracking_settings/store/actions.js
index 2821798f82d..7eb684fb52c 100644
--- a/app/assets/javascripts/error_tracking_settings/store/actions.js
+++ b/app/assets/javascripts/error_tracking_settings/store/actions.js
@@ -1,7 +1,7 @@
-import { __ } from '~/locale';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { __ } from '~/locale';
import { transformFrontendSettings } from '../utils';
import * as types from './mutation_types';
diff --git a/app/assets/javascripts/error_tracking_settings/store/index.js b/app/assets/javascripts/error_tracking_settings/store/index.js
index 560f265a2ea..1cd6d119657 100644
--- a/app/assets/javascripts/error_tracking_settings/store/index.js
+++ b/app/assets/javascripts/error_tracking_settings/store/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
+import createState from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/error_tracking_settings/store/mutations.js b/app/assets/javascripts/error_tracking_settings/store/mutations.js
index 1fc028093c1..2242169aa1e 100644
--- a/app/assets/javascripts/error_tracking_settings/store/mutations.js
+++ b/app/assets/javascripts/error_tracking_settings/store/mutations.js
@@ -1,7 +1,7 @@
import { pick } from 'lodash';
import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
-import * as types from './mutation_types';
import { projectKeys } from '../utils';
+import * as types from './mutation_types';
export default {
[types.CLEAR_PROJECTS](state) {
diff --git a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
index 210212fa900..b1e60066e11 100644
--- a/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/edit_feature_flag.vue
@@ -91,9 +91,9 @@ export default {
<h3 class="page-title gl-m-0">{{ title }}</h3>
</div>
- <div v-if="error.length" class="alert alert-danger">
+ <gl-alert v-if="error.length" variant="warning" class="gl-mb-5" :dismissible="false">
<p v-for="(message, index) in error" :key="index" class="gl-mb-0">{{ message }}</p>
- </div>
+ </gl-alert>
<feature-flag-form
:name="name"
diff --git a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
index 88f1e692f5f..7f316d20f9c 100644
--- a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue
@@ -1,9 +1,9 @@
<script>
-import { debounce } from 'lodash';
import { GlButton, GlSearchBoxByType } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
/**
* Creates a searchable input for environments.
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags.vue b/app/assets/javascripts/feature_flags/components/feature_flags.vue
index ddeefd7b827..348b71dc1c6 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags.vue
@@ -1,20 +1,19 @@
<script>
-import { mapState, mapActions } from 'vuex';
-import { isEmpty } from 'lodash';
import { GlAlert, GlButton, GlModalDirective, GlSprintf, GlTabs } from '@gitlab/ui';
+import { isEmpty } from 'lodash';
+import { mapState, mapActions } from 'vuex';
-import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../constants';
-import FeatureFlagsTab from './feature_flags_tab.vue';
-import FeatureFlagsTable from './feature_flags_table.vue';
-import UserListsTable from './user_lists_table.vue';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import {
buildUrlWithCurrentLocation,
getParameterByName,
historyPushState,
} from '~/lib/utils/common_utils';
-
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../constants';
import ConfigureFeatureFlagsModal from './configure_feature_flags_modal.vue';
+import FeatureFlagsTab from './feature_flags_tab.vue';
+import FeatureFlagsTable from './feature_flags_table.vue';
+import UserListsTable from './user_lists_table.vue';
const SCOPES = { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE };
@@ -198,7 +197,7 @@ export default {
@token="rotateInstanceId()"
/>
<div :class="topAreaBaseClasses">
- <div class="gl-display-flex gl-flex-direction-column gl-display-md-none!">
+ <div class="gl-display-flex gl-flex-direction-column gl-md-display-none!">
<gl-button
v-if="canUserConfigure"
v-gl-modal="'configure-feature-flags'"
@@ -285,7 +284,7 @@ export default {
</feature-flags-tab>
<template #tabs-end>
<li
- class="gl-display-none gl-display-md-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
+ class="gl-display-none gl-md-display-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
>
<gl-button
v-if="canUserConfigure"
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue b/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
index 24b0b54d1be..d0df00e446b 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags_tab.vue
@@ -68,41 +68,39 @@ export default {
<span data-testid="feature-flags-tab-title">{{ title }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">{{ itemCount }}</gl-badge>
</template>
- <template>
- <gl-alert
- v-for="(message, index) in alerts"
- :key="index"
- data-testid="serverErrors"
- variant="danger"
- @dismiss="clearAlert(index)"
- >
- {{ message }}
- </gl-alert>
+ <gl-alert
+ v-for="(message, index) in alerts"
+ :key="index"
+ data-testid="serverErrors"
+ variant="danger"
+ @dismiss="clearAlert(index)"
+ >
+ {{ message }}
+ </gl-alert>
- <gl-loading-icon v-if="isLoading" :label="loadingLabel" size="md" class="gl-mt-4" />
+ <gl-loading-icon v-if="isLoading" :label="loadingLabel" size="md" class="gl-mt-4" />
- <gl-empty-state
- v-else-if="errorState"
- :title="errorTitle"
- :description="s__(`FeatureFlags|Try again in a few moments or contact your support team.`)"
- :svg-path="errorStateSvgPath"
- data-testid="error-state"
- />
+ <gl-empty-state
+ v-else-if="errorState"
+ :title="errorTitle"
+ :description="s__(`FeatureFlags|Try again in a few moments or contact your support team.`)"
+ :svg-path="errorStateSvgPath"
+ data-testid="error-state"
+ />
- <gl-empty-state
- v-else-if="emptyState"
- :title="emptyTitle"
- :svg-path="errorStateSvgPath"
- data-testid="empty-state"
- >
- <template #description>
- {{ emptyDescription }}
- <gl-link :href="featureFlagsHelpPagePath" target="_blank">
- {{ s__('FeatureFlags|More information') }}
- </gl-link>
- </template>
- </gl-empty-state>
- <slot> </slot>
- </template>
+ <gl-empty-state
+ v-else-if="emptyState"
+ :title="emptyTitle"
+ :svg-path="errorStateSvgPath"
+ data-testid="empty-state"
+ >
+ <template #description>
+ {{ emptyDescription }}
+ <gl-link :href="featureFlagsHelpPagePath" target="_blank">
+ {{ s__('FeatureFlags|More information') }}
+ </gl-link>
+ </template>
+ </gl-empty-state>
+ <slot> </slot>
</gl-tab>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
index f3b199b5aca..04a5e5bc3c5 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags_table.vue
@@ -199,7 +199,7 @@ export default {
:key="strategy.id"
data-testid="strategy-badge"
variant="info"
- class="gl-mr-3 gl-mt-2"
+ class="gl-mr-3 gl-mt-2 gl-white-space-normal gl-text-left gl-px-5"
>{{ strategyBadgeText(strategy) }}</gl-badge
>
</template>
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index 253661ece1f..f6a14d9996f 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -1,6 +1,4 @@
<script>
-import Vue from 'vue';
-import { memoize, isString, cloneDeep, isNumber, uniqueId } from 'lodash';
import {
GlButton,
GlBadge,
@@ -10,13 +8,13 @@ import {
GlFormCheckbox,
GlSprintf,
GlIcon,
+ GlToggle,
} from '@gitlab/ui';
-import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
+import { memoize, isString, cloneDeep, isNumber, uniqueId } from 'lodash';
+import Vue from 'vue';
import { s__ } from '~/locale';
+import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
-import EnvironmentsDropdown from './environments_dropdown.vue';
-import Strategy from './strategy.vue';
import {
ROLLOUT_STRATEGY_ALL_USERS,
ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
@@ -27,6 +25,8 @@ import {
LEGACY_FLAG,
} from '../constants';
import { createNewEnvironmentScope } from '../store/helpers';
+import EnvironmentsDropdown from './environments_dropdown.vue';
+import Strategy from './strategy.vue';
export default {
components: {
@@ -37,7 +37,7 @@ export default {
GlTooltip,
GlSprintf,
GlIcon,
- ToggleButton,
+ GlToggle,
EnvironmentsDropdown,
Strategy,
RelatedIssuesRoot,
@@ -372,7 +372,7 @@ export default {
{{ s__('FeatureFlags|Environment Spec') }}
</div>
<div
- class="table-mobile-content js-feature-flag-status d-flex align-items-center justify-content-start"
+ class="table-mobile-content gl-display-flex gl-align-items-center gl-justify-content-start"
>
<p v-if="isAllEnvironment(scope.environmentScope)" class="js-scope-all pl-3">
{{ $options.translations.allEnvironmentsText }}
@@ -398,10 +398,10 @@ export default {
<div class="table-mobile-header" role="rowheader">
{{ s__('FeatureFlags|Status') }}
</div>
- <div class="table-mobile-content js-feature-flag-status">
- <toggle-button
+ <div class="table-mobile-content gl-display-flex gl-justify-content-center">
+ <gl-toggle
:value="scope.active"
- :disabled-input="!active || !canUpdateScope(scope)"
+ :disabled="!active || !canUpdateScope(scope)"
@change="(status) => (scope.active = status)"
/>
</div>
@@ -498,25 +498,26 @@ export default {
<div class="table-mobile-header" role="rowheader">
{{ s__('FeatureFlags|Remove') }}
</div>
- <div class="table-mobile-content js-feature-flag-delete">
+ <div class="table-mobile-content">
<gl-button
v-if="!isAllEnvironment(scope.environmentScope) && canUpdateScope(scope)"
v-gl-tooltip
:title="s__('FeatureFlags|Remove')"
class="js-delete-scope btn-transparent pr-3 pl-3"
icon="clear"
+ data-testid="feature-flag-delete"
@click="removeScope(scope)"
/>
</div>
</div>
</div>
- <div class="js-add-new-scope gl-responsive-table-row" role="row">
+ <div class="gl-responsive-table-row" role="row" data-testid="add-new-scope">
<div class="table-section section-30" role="gridcell">
<div class="table-mobile-header" role="rowheader">
{{ s__('FeatureFlags|Environment Spec') }}
</div>
- <div class="table-mobile-content js-feature-flag-status">
+ <div class="table-mobile-content">
<environments-dropdown
class="js-new-scope-name col-12"
:value="newScope"
@@ -530,9 +531,9 @@ export default {
<div class="table-mobile-header" role="rowheader">
{{ s__('FeatureFlags|Status') }}
</div>
- <div class="table-mobile-content js-feature-flag-status">
- <toggle-button
- :disabled-input="!active"
+ <div class="table-mobile-content gl-display-flex gl-justify-content-center">
+ <gl-toggle
+ :disabled="!active"
:value="false"
@change="createNewScope({ active: true })"
/>
diff --git a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
index f2017c22abf..efe4ff71a9e 100644
--- a/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
+++ b/app/assets/javascripts/feature_flags/components/new_environments_dropdown.vue
@@ -1,5 +1,4 @@
<script>
-import { debounce } from 'lodash';
import {
GlDropdown,
GlDropdownDivider,
@@ -8,9 +7,10 @@ import {
GlLoadingIcon,
GlSearchBoxByType,
} from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
export default {
components: {
diff --git a/app/assets/javascripts/feature_flags/components/new_feature_flag.vue b/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
index 529fefd7e45..19be57f9d27 100644
--- a/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
@@ -1,15 +1,16 @@
<script>
+import { GlAlert } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import axios from '~/lib/utils/axios_utils';
-import FeatureFlagForm from './form.vue';
+import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { NEW_VERSION_FLAG, ROLLOUT_STRATEGY_ALL_USERS } from '../constants';
import { createNewEnvironmentScope } from '../store/helpers';
-
-import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import FeatureFlagForm from './form.vue';
export default {
components: {
FeatureFlagForm,
+ GlAlert,
},
mixins: [featureFlagsMixin()],
inject: {
@@ -61,9 +62,9 @@ export default {
<div>
<h3 class="page-title">{{ s__('FeatureFlags|New feature flag') }}</h3>
- <div v-if="error.length" class="alert alert-danger">
- <p v-for="(message, index) in error" :key="index" class="mb-0">{{ message }}</p>
- </div>
+ <gl-alert v-if="error.length" variant="warning" class="gl-mb-5" :dismissible="false">
+ <p v-for="(message, index) in error" :key="index" class="gl-mb-0">{{ message }}</p>
+ </gl-alert>
<feature-flag-form
:cancel-path="path"
diff --git a/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
index 6a57e9a8759..45fc37da747 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/gitlab_user_list.vue
@@ -1,7 +1,7 @@
<script>
+import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { debounce } from 'lodash';
import { createNamespacedHelpers } from 'vuex';
-import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
import { s__ } from '~/locale';
import ParameterFormGroup from './parameter_form_group.vue';
diff --git a/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue b/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue
index 7f2c6d55db8..822ff92b405 100644
--- a/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue
+++ b/app/assets/javascripts/feature_flags/components/strategies/parameter_form_group.vue
@@ -1,6 +1,6 @@
<script>
-import { uniqueId } from 'lodash';
import { GlFormGroup } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
export default {
components: {
diff --git a/app/assets/javascripts/feature_flags/components/strategy.vue b/app/assets/javascripts/feature_flags/components/strategy.vue
index 9593bcf6487..170f120b036 100644
--- a/app/assets/javascripts/feature_flags/components/strategy.vue
+++ b/app/assets/javascripts/feature_flags/components/strategy.vue
@@ -1,7 +1,7 @@
<script>
-import Vue from 'vue';
-import { isNumber } from 'lodash';
import { GlAlert, GlButton, GlFormSelect, GlFormGroup, GlIcon, GlLink, GlToken } from '@gitlab/ui';
+import { isNumber } from 'lodash';
+import Vue from 'vue';
import { s__, __ } from '~/locale';
import {
EMPTY_PARAMETERS,
diff --git a/app/assets/javascripts/feature_flags/components/strategy_parameters.vue b/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
index a22f081bb92..ded91621cb8 100644
--- a/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
+++ b/app/assets/javascripts/feature_flags/components/strategy_parameters.vue
@@ -9,9 +9,9 @@ import {
import Default from './strategies/default.vue';
import FlexibleRollout from './strategies/flexible_rollout.vue';
+import GitlabUserList from './strategies/gitlab_user_list.vue';
import PercentRollout from './strategies/percent_rollout.vue';
import UsersWithId from './strategies/users_with_id.vue';
-import GitlabUserList from './strategies/gitlab_user_list.vue';
const STRATEGIES = Object.freeze({
[ROLLOUT_STRATEGY_ALL_USERS]: Default,
diff --git a/app/assets/javascripts/feature_flags/edit.js b/app/assets/javascripts/feature_flags/edit.js
index 05a9bbce654..010674592f8 100644
--- a/app/assets/javascripts/feature_flags/edit.js
+++ b/app/assets/javascripts/feature_flags/edit.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
-import createStore from './store/edit';
import EditFeatureFlag from './components/edit_feature_flag.vue';
+import createStore from './store/edit';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/feature_flags/new.js b/app/assets/javascripts/feature_flags/new.js
index 8e18213cc03..f763b12fedb 100644
--- a/app/assets/javascripts/feature_flags/new.js
+++ b/app/assets/javascripts/feature_flags/new.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
-import createStore from './store/new';
import NewFeatureFlag from './components/new_feature_flag.vue';
+import createStore from './store/new';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/feature_flags/store/edit/actions.js b/app/assets/javascripts/feature_flags/store/edit/actions.js
index c4515e07a00..72b17333832 100644
--- a/app/assets/javascripts/feature_flags/store/edit/actions.js
+++ b/app/assets/javascripts/feature_flags/store/edit/actions.js
@@ -1,10 +1,10 @@
-import * as types from './mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale';
import { NEW_VERSION_FLAG } from '../../constants';
import { mapFromScopesViewModel, mapStrategiesToRails } from '../helpers';
+import * as types from './mutation_types';
/**
* Handles the edition of a feature flag.
diff --git a/app/assets/javascripts/feature_flags/store/edit/index.js b/app/assets/javascripts/feature_flags/store/edit/index.js
index 65ea61c3025..16b8a5ae970 100644
--- a/app/assets/javascripts/feature_flags/store/edit/index.js
+++ b/app/assets/javascripts/feature_flags/store/edit/index.js
@@ -1,8 +1,8 @@
import Vuex from 'vuex';
import userLists from '../gitlab_user_list';
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default (data) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/feature_flags/store/edit/mutations.js b/app/assets/javascripts/feature_flags/store/edit/mutations.js
index e60dbaf4a34..0a610f4b395 100644
--- a/app/assets/javascripts/feature_flags/store/edit/mutations.js
+++ b/app/assets/javascripts/feature_flags/store/edit/mutations.js
@@ -1,6 +1,6 @@
-import * as types from './mutation_types';
-import { mapToScopesViewModel, mapStrategiesToViewModel } from '../helpers';
import { LEGACY_FLAG } from '../../constants';
+import { mapToScopesViewModel, mapStrategiesToViewModel } from '../helpers';
+import * as types from './mutation_types';
export default {
[types.REQUEST_FEATURE_FLAG](state) {
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
index 5f2726770d5..8a38f068609 100644
--- a/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/index.js
@@ -1,7 +1,7 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
export default (data) => ({
state: state(data),
diff --git a/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
index bd7c6f68009..31e67a47541 100644
--- a/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
+++ b/app/assets/javascripts/feature_flags/store/gitlab_user_list/mutations.js
@@ -1,5 +1,5 @@
-import statuses from './status';
import * as types from './mutation_types';
+import statuses from './status';
export default {
[types.FETCH_USER_LISTS](state) {
diff --git a/app/assets/javascripts/feature_flags/store/index/actions.js b/app/assets/javascripts/feature_flags/store/index/actions.js
index 6b6b3d55e16..4372c280f39 100644
--- a/app/assets/javascripts/feature_flags/store/index/actions.js
+++ b/app/assets/javascripts/feature_flags/store/index/actions.js
@@ -1,6 +1,6 @@
import Api from '~/api';
-import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
+import * as types from './mutation_types';
export const setFeatureFlagsOptions = ({ commit }, options) =>
commit(types.SET_FEATURE_FLAGS_OPTIONS, options);
diff --git a/app/assets/javascripts/feature_flags/store/index/index.js b/app/assets/javascripts/feature_flags/store/index/index.js
index 76495a33232..96ccb35fa21 100644
--- a/app/assets/javascripts/feature_flags/store/index/index.js
+++ b/app/assets/javascripts/feature_flags/store/index/index.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default (data) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/feature_flags/store/index/mutations.js b/app/assets/javascripts/feature_flags/store/index/mutations.js
index 910b2ec42d4..25eb7da1c72 100644
--- a/app/assets/javascripts/feature_flags/store/index/mutations.js
+++ b/app/assets/javascripts/feature_flags/store/index/mutations.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import * as types from './mutation_types';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '../../constants';
import { mapToScopesViewModel } from '../helpers';
+import * as types from './mutation_types';
const mapFlag = (flag) => ({ ...flag, scopes: mapToScopesViewModel(flag.scopes || []) });
diff --git a/app/assets/javascripts/feature_flags/store/new/actions.js b/app/assets/javascripts/feature_flags/store/new/actions.js
index 6d595603819..d0a1c77a69e 100644
--- a/app/assets/javascripts/feature_flags/store/new/actions.js
+++ b/app/assets/javascripts/feature_flags/store/new/actions.js
@@ -1,8 +1,8 @@
-import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import { NEW_VERSION_FLAG } from '../../constants';
import { mapFromScopesViewModel, mapStrategiesToRails } from '../helpers';
+import * as types from './mutation_types';
/**
* Handles the creation of a new feature flag.
diff --git a/app/assets/javascripts/feature_flags/store/new/index.js b/app/assets/javascripts/feature_flags/store/new/index.js
index 65ea61c3025..16b8a5ae970 100644
--- a/app/assets/javascripts/feature_flags/store/new/index.js
+++ b/app/assets/javascripts/feature_flags/store/new/index.js
@@ -1,8 +1,8 @@
import Vuex from 'vuex';
import userLists from '../gitlab_user_list';
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default (data) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/feature_highlight/constants.js b/app/assets/javascripts/feature_highlight/constants.js
new file mode 100644
index 00000000000..3e4cd11f7d5
--- /dev/null
+++ b/app/assets/javascripts/feature_highlight/constants.js
@@ -0,0 +1 @@
+export const POPOVER_TARGET_ID = 'feature-highlight-trigger';
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js
deleted file mode 100644
index 2da9aadd2b1..00000000000
--- a/app/assets/javascripts/feature_highlight/feature_highlight.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import $ from 'jquery';
-import { getSelector, inserted } from './feature_highlight_helper';
-import { togglePopover, mouseenter, debouncedMouseleave } from '../shared/popover';
-
-export function setupFeatureHighlightPopover(id, debounceTimeout = 300) {
- const $selector = $(getSelector(id));
- const $parent = $selector.parent();
- const $popoverContent = $parent.siblings('.feature-highlight-popover-content');
- const hideOnScroll = togglePopover.bind($selector, false);
-
- $selector
- // Set up popover
- .data('content', $popoverContent.prop('outerHTML'))
- .popover({
- html: true,
- // Override the existing template to add custom CSS classes
- template: `
- <div class="popover feature-highlight-popover" role="tooltip">
- <div class="arrow"></div>
- <div class="popover-body"></div>
- </div>
- `,
- })
- .on('mouseenter', mouseenter)
- .on('mouseleave', debouncedMouseleave(debounceTimeout))
- .on('inserted.bs.popover', inserted)
- .on('show.bs.popover', () => {
- window.addEventListener('scroll', hideOnScroll, { once: true });
- })
- // Display feature highlight
- .removeAttr('disabled');
-}
-
-const getPriority = (e) => parseInt(e.dataset.highlightPriority, 10) || 0;
-
-export function findHighestPriorityFeature() {
- let priorityFeature;
-
- const sortedFeatureEls = [].slice
- .call(document.querySelectorAll('.js-feature-highlight'))
- .sort((a, b) => getPriority(b) - getPriority(a));
-
- const [priorityFeatureEl] = sortedFeatureEls;
- if (priorityFeatureEl) {
- priorityFeature = priorityFeatureEl.dataset.highlight;
- }
-
- return priorityFeature;
-}
-
-export function highlightFeatures() {
- const priorityFeature = findHighestPriorityFeature();
-
- if (priorityFeature) {
- setupFeatureHighlightPopover(priorityFeature);
- }
-
- return priorityFeature;
-}
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
index fabc905d756..7b4bed69fb8 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
@@ -1,15 +1,12 @@
-import $ from 'jquery';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '../lib/utils/axios_utils';
import { __ } from '../locale';
-import { deprecatedCreateFlash as Flash } from '../flash';
-import LazyLoader from '../lazy_loader';
-import { togglePopover } from '../shared/popover';
export const getSelector = (highlightId) => `.js-feature-highlight[data-highlight=${highlightId}]`;
-export function dismiss(highlightId) {
- axios
- .post(this.attr('data-dismiss-endpoint'), {
+export function dismiss(endpoint, highlightId) {
+ return axios
+ .post(endpoint, {
feature_name: highlightId,
})
.catch(() =>
@@ -19,21 +16,4 @@ export function dismiss(highlightId) {
),
),
);
-
- togglePopover.call(this, false);
- this.hide();
-}
-
-export function inserted() {
- const popoverId = this.getAttribute('aria-describedby');
- const highlightId = this.dataset.highlight;
- const $popover = $(this);
- const dismissWrapper = dismiss.bind($popover, highlightId);
-
- $(`#${popoverId} .dismiss-feature-highlight`).on('click', dismissWrapper);
-
- const lazyImg = $(`#${popoverId} .feature-highlight-illustration`)[0];
- if (lazyImg) {
- LazyLoader.loadImage(lazyImg);
- }
}
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_options.js b/app/assets/javascripts/feature_highlight/feature_highlight_options.js
deleted file mode 100644
index c5553f0243f..00000000000
--- a/app/assets/javascripts/feature_highlight/feature_highlight_options.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import { highlightFeatures } from './feature_highlight';
-
-export default function domContentLoaded() {
- if (bp.getBreakpointSize() === 'xl') {
- highlightFeatures();
- return true;
- }
- return false;
-}
-
-document.addEventListener('DOMContentLoaded', domContentLoaded);
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue
new file mode 100644
index 00000000000..2fd92a1bb11
--- /dev/null
+++ b/app/assets/javascripts/feature_highlight/feature_highlight_popover.vue
@@ -0,0 +1,101 @@
+<script>
+import clusterPopover from '@gitlab/svgs/dist/illustrations/cluster_popover.svg';
+import {
+ GlPopover,
+ GlSprintf,
+ GlLink,
+ GlButton,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
+import { __ } from '~/locale';
+import { POPOVER_TARGET_ID } from './constants';
+import { dismiss } from './feature_highlight_helper';
+
+export default {
+ components: {
+ GlPopover,
+ GlSprintf,
+ GlLink,
+ GlButton,
+ },
+ directives: {
+ SafeHtml,
+ },
+ props: {
+ autoDevopsHelpPath: {
+ type: String,
+ required: true,
+ },
+ highlightId: {
+ type: String,
+ required: true,
+ },
+ dismissEndpoint: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ dismissed: false,
+ triggerHidden: false,
+ };
+ },
+ methods: {
+ dismiss() {
+ dismiss(this.dismissEndpoint, this.highlightId);
+ this.$refs.popover.$emit('close');
+ this.dismissed = true;
+ },
+ hideTrigger() {
+ if (this.dismissed) {
+ this.triggerHidden = true;
+ }
+ },
+ },
+ clusterPopover,
+ targetId: POPOVER_TARGET_ID,
+ i18n: {
+ highlightMessage: __('Allows you to add and manage Kubernetes clusters.'),
+ autoDevopsProTipMessage: __(
+ 'Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!',
+ ),
+ dismissButtonLabel: __('Got it!'),
+ },
+};
+</script>
+<template>
+ <div class="gl-ml-3">
+ <span v-if="!triggerHidden" :id="$options.targetId" class="feature-highlight"></span>
+ <gl-popover
+ ref="popover"
+ :target="$options.targetId"
+ :css-classes="['feature-highlight-popover']"
+ triggers="hover"
+ container="body"
+ placement="right"
+ boundary="viewport"
+ @hidden="hideTrigger"
+ >
+ <span
+ v-safe-html="$options.clusterPopover"
+ class="feature-highlight-illustration gl-display-flex gl-justify-content-center gl-py-4 gl-w-full"
+ ></span>
+ <div class="gl-px-4 gl-py-5">
+ <p>
+ {{ $options.i18n.highlightMessage }}
+ </p>
+ <p>
+ <gl-sprintf :message="$options.i18n.autoDevopsProTipMessage">
+ <template #link="{ content }">
+ <gl-link class="gl-font-sm" :href="autoDevopsHelpPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <gl-button size="small" icon="thumb-up" variant="confirm" @click="dismiss">
+ {{ $options.i18n.dismissButtonLabel }}
+ </gl-button>
+ </div>
+ </gl-popover>
+ </div>
+</template>
diff --git a/app/assets/javascripts/feature_highlight/index.js b/app/assets/javascripts/feature_highlight/index.js
new file mode 100644
index 00000000000..3a8b211b3c5
--- /dev/null
+++ b/app/assets/javascripts/feature_highlight/index.js
@@ -0,0 +1,28 @@
+import Vue from 'vue';
+
+const init = async () => {
+ const el = document.querySelector('.js-feature-highlight');
+
+ if (!el) {
+ return null;
+ }
+
+ const { autoDevopsHelpPath, highlight: highlightId, dismissEndpoint } = el.dataset;
+ const { default: FeatureHighlight } = await import(
+ /* webpackChunkName: 'feature_highlight' */ './feature_highlight_popover.vue'
+ );
+
+ return new Vue({
+ el,
+ render: (h) =>
+ h(FeatureHighlight, {
+ props: {
+ autoDevopsHelpPath,
+ highlightId,
+ dismissEndpoint,
+ },
+ }),
+ });
+};
+
+export default init;
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
index 588bd534224..409b4ccbcfa 100644
--- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -1,12 +1,12 @@
+import { mergeUrlParams } from '../lib/utils/url_utility';
+import DropdownAjaxFilter from './dropdown_ajax_filter';
+import DropdownEmoji from './dropdown_emoji';
import DropdownHint from './dropdown_hint';
-import DropdownUser from './dropdown_user';
import DropdownNonUser from './dropdown_non_user';
-import DropdownEmoji from './dropdown_emoji';
-import NullDropdown from './null_dropdown';
-import DropdownAjaxFilter from './dropdown_ajax_filter';
import DropdownOperator from './dropdown_operator';
+import DropdownUser from './dropdown_user';
import DropdownUtils from './dropdown_utils';
-import { mergeUrlParams } from '../lib/utils/url_utility';
+import NullDropdown from './null_dropdown';
export default class AvailableDropdownMappings {
constructor({
diff --git a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
index 2c0c3024d38..e317700b09b 100644
--- a/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
+++ b/app/assets/javascripts/filtered_search/dropdown_ajax_filter.js
@@ -1,9 +1,9 @@
-import { deprecatedCreateFlash as createFlash } from '../flash';
+import { __ } from '~/locale';
import AjaxFilter from '../droplab/plugins/ajax_filter';
-import FilteredSearchDropdown from './filtered_search_dropdown';
+import { deprecatedCreateFlash as createFlash } from '../flash';
import DropdownUtils from './dropdown_utils';
+import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
-import { __ } from '~/locale';
export default class DropdownAjaxFilter extends FilteredSearchDropdown {
constructor(options = {}) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index 001030b5f5f..a22430833a3 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -1,9 +1,9 @@
-import { deprecatedCreateFlash as Flash } from '../flash';
+import { __ } from '~/locale';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
-import FilteredSearchDropdown from './filtered_search_dropdown';
+import { deprecatedCreateFlash as Flash } from '../flash';
import DropdownUtils from './dropdown_utils';
-import { __ } from '~/locale';
+import FilteredSearchDropdown from './filtered_search_dropdown';
export default class DropdownEmoji extends FilteredSearchDropdown {
constructor(options = {}) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js
index 1180f8683a1..47f350dc6a2 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
@@ -1,9 +1,9 @@
import Filter from '~/droplab/plugins/filter';
-import FilteredSearchDropdown from './filtered_search_dropdown';
+import { __ } from '~/locale';
import DropdownUtils from './dropdown_utils';
+import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
-import { __ } from '~/locale';
export default class DropdownHint extends FilteredSearchDropdown {
constructor(options = {}) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index 11261debeda..4df1120f169 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
@@ -1,9 +1,9 @@
-import { deprecatedCreateFlash as Flash } from '../flash';
+import { __ } from '~/locale';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
-import FilteredSearchDropdown from './filtered_search_dropdown';
+import { deprecatedCreateFlash as Flash } from '../flash';
import DropdownUtils from './dropdown_utils';
-import { __ } from '~/locale';
+import FilteredSearchDropdown from './filtered_search_dropdown';
export default class DropdownNonUser extends FilteredSearchDropdown {
constructor(options = {}) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_operator.js b/app/assets/javascripts/filtered_search/dropdown_operator.js
index 8fee3385de1..0da8cd0ad83 100644
--- a/app/assets/javascripts/filtered_search/dropdown_operator.js
+++ b/app/assets/javascripts/filtered_search/dropdown_operator.js
@@ -1,7 +1,7 @@
import Filter from '~/droplab/plugins/filter';
import { __ } from '~/locale';
-import FilteredSearchDropdown from './filtered_search_dropdown';
import DropdownUtils from './dropdown_utils';
+import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js
index 22c98f360ed..c98d1f8e064 100644
--- a/app/assets/javascripts/filtered_search/dropdown_utils.js
+++ b/app/assets/javascripts/filtered_search/dropdown_utils.js
@@ -1,7 +1,7 @@
import { last } from 'lodash';
import FilteredSearchContainer from './container';
-import FilteredSearchTokenizer from './filtered_search_tokenizer';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
+import FilteredSearchTokenizer from './filtered_search_tokenizer';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
export default class DropdownUtils {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
index 7434cc4c5d1..fcc7caa9ff2 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
@@ -1,7 +1,7 @@
+import { FILTER_TYPE } from './constants';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
-import { FILTER_TYPE } from './constants';
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index 3c630c26bc7..ebaa3ef98b1 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -1,11 +1,11 @@
import { last } from 'lodash';
import AvailableDropdownMappings from 'ee_else_ce/filtered_search/available_dropdown_mappings';
import DropLab from '~/droplab/drop_lab';
+import { DROPDOWN_TYPE } from './constants';
import FilteredSearchContainer from './container';
-import FilteredSearchTokenKeys from './filtered_search_token_keys';
import DropdownUtils from './dropdown_utils';
+import FilteredSearchTokenKeys from './filtered_search_token_keys';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
-import { DROPDOWN_TYPE } from './constants';
export default class FilteredSearchDropdownManager {
constructor({
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 11b2eb839ce..69d19074cd0 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -1,19 +1,7 @@
import { last } from 'lodash';
import recentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys';
-import { getParameterByName, getUrlParamsArray } from '~/lib/utils/common_utils';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import { visitUrl } from '../lib/utils/url_utility';
-import { deprecatedCreateFlash as Flash } from '../flash';
-import FilteredSearchContainer from './container';
-import RecentSearchesRoot from './recent_searches_root';
-import RecentSearchesStore from './stores/recent_searches_store';
-import RecentSearchesService from './services/recent_searches_service';
-import eventHub from './event_hub';
-import { addClassIfElementExists } from '../lib/utils/dom_utils';
-import FilteredSearchTokenizer from './filtered_search_tokenizer';
-import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
-import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
-import DropdownUtils from './dropdown_utils';
+import { getParameterByName, getUrlParamsArray } from '~/lib/utils/common_utils';
import {
ENTER_KEY_CODE,
BACKSPACE_KEY_CODE,
@@ -22,6 +10,18 @@ import {
DOWN_KEY_CODE,
} from '~/lib/utils/keycodes';
import { __ } from '~/locale';
+import { deprecatedCreateFlash as Flash } from '../flash';
+import { addClassIfElementExists } from '../lib/utils/dom_utils';
+import { visitUrl } from '../lib/utils/url_utility';
+import FilteredSearchContainer from './container';
+import DropdownUtils from './dropdown_utils';
+import eventHub from './event_hub';
+import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
+import FilteredSearchTokenizer from './filtered_search_tokenizer';
+import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
+import RecentSearchesRoot from './recent_searches_root';
+import RecentSearchesService from './services/recent_searches_service';
+import RecentSearchesStore from './stores/recent_searches_store';
export default class FilteredSearchManager {
constructor({
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
index 4e594dfa910..eec4db41b0a 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -1,6 +1,6 @@
-import VisualTokenValue from './visual_token_value';
import { objectToQueryString, spriteIcon } from '~/lib/utils/common_utils';
import FilteredSearchContainer from './container';
+import VisualTokenValue from './visual_token_value';
export default class FilteredSearchVisualTokens {
static permissibleOperatorValues = ['=', '!='];
diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
index 46867b184c8..2c58506985a 100644
--- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
@@ -1,6 +1,6 @@
import { flattenDeep } from 'lodash';
-import FilteredSearchTokenKeys from './filtered_search_token_keys';
import { __ } from '~/locale';
+import FilteredSearchTokenKeys from './filtered_search_token_keys';
export const tokenKeys = [
{
diff --git a/app/assets/javascripts/filtered_search/recent_searches_root.js b/app/assets/javascripts/filtered_search/recent_searches_root.js
index 6c8e77a7fe5..1182cb34210 100644
--- a/app/assets/javascripts/filtered_search/recent_searches_root.js
+++ b/app/assets/javascripts/filtered_search/recent_searches_root.js
@@ -28,19 +28,18 @@ class RecentSearchesRoot {
const { state } = this.store;
this.vm = new Vue({
el: this.wrapperElement,
- components: {
- RecentSearchesDropdownContent,
- },
data() {
return state;
},
- template: `
- <recent-searches-dropdown-content
- :items="recentSearches"
- :is-local-storage-available="isLocalStorageAvailable"
- :allowed-keys="allowedKeys"
- />
- `,
+ render(h) {
+ return h(RecentSearchesDropdownContent, {
+ props: {
+ items: this.recentSearches,
+ isLocalStorageAvailable: this.isLocalStorageAvailable,
+ allowedKeys: this.allowedKeys,
+ },
+ });
+ },
});
}
diff --git a/app/assets/javascripts/filtered_search/recent_searches_storage_keys.js b/app/assets/javascripts/filtered_search/recent_searches_storage_keys.js
index 54d49821d92..446a0e5eb24 100644
--- a/app/assets/javascripts/filtered_search/recent_searches_storage_keys.js
+++ b/app/assets/javascripts/filtered_search/recent_searches_storage_keys.js
@@ -3,4 +3,6 @@ export default {
merge_requests: 'merge-request-recent-searches',
group_members: 'group-members-recent-searches',
group_invited_members: 'group-invited-members-recent-searches',
+ project_members: 'project-members-recent-searches',
+ project_group_links: 'project-group-links-recent-searches',
};
diff --git a/app/assets/javascripts/filtered_search/services/recent_searches_service.js b/app/assets/javascripts/filtered_search/services/recent_searches_service.js
index a056dea928d..56824977a43 100644
--- a/app/assets/javascripts/filtered_search/services/recent_searches_service.js
+++ b/app/assets/javascripts/filtered_search/services/recent_searches_service.js
@@ -1,5 +1,5 @@
-import RecentSearchesServiceError from './recent_searches_service_error';
import AccessorUtilities from '../../lib/utils/accessor';
+import RecentSearchesServiceError from './recent_searches_service_error';
class RecentSearchesService {
constructor(localStorageKey = 'issuable-recent-searches') {
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index 0d36126943b..7f4445ad4c7 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -1,13 +1,13 @@
import { escape } from 'lodash';
import { USER_TOKEN_TYPES } from 'ee_else_ce/filtered_search/constants';
+import * as Emoji from '~/emoji';
import FilteredSearchContainer from '~/filtered_search/container';
-import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
-import AjaxCache from '~/lib/utils/ajax_cache';
import DropdownUtils from '~/filtered_search/dropdown_utils';
+import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import AjaxCache from '~/lib/utils/ajax_cache';
import UsersCache from '~/lib/utils/users_cache';
import { __ } from '~/locale';
-import * as Emoji from '~/emoji';
export default class VisualTokenValue {
constructor(tokenValue, tokenType, tokenOperator) {
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue
index 68cc8645813..69f89aa3857 100644
--- a/app/assets/javascripts/frequent_items/components/app.vue
+++ b/app/assets/javascripts/frequent_items/components/app.vue
@@ -1,13 +1,13 @@
<script>
-import { mapState, mapActions, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mapState, mapActions, mapGetters } from 'vuex';
import AccessorUtilities from '~/lib/utils/accessor';
-import eventHub from '../event_hub';
import { FREQUENT_ITEMS, STORAGE_KEY } from '../constants';
+import eventHub from '../event_hub';
import { isMobile, updateExistingFrequentItem, sanitizeItem } from '../utils';
-import FrequentItemsSearchInput from './frequent_items_search_input.vue';
import FrequentItemsList from './frequent_items_list.vue';
import frequentItemsMixin from './frequent_items_mixin';
+import FrequentItemsSearchInput from './frequent_items_search_input.vue';
export default {
components: {
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue
index 9d898d1a1a1..6feeb5f03ad 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue
@@ -1,7 +1,7 @@
<script>
+import { sanitizeItem } from '../utils';
import FrequentItemsListItem from './frequent_items_list_item.vue';
import frequentItemsMixin from './frequent_items_mixin';
-import { sanitizeItem } from '../utils';
export default {
components: {
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index 3260d768fd9..6f17e6a5282 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -1,10 +1,10 @@
<script>
/* eslint-disable vue/require-default-prop, vue/no-v-html */
import { mapState } from 'vuex';
-import Identicon from '~/vue_shared/components/identicon.vue';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
import Tracking from '~/tracking';
+import Identicon from '~/vue_shared/components/identicon.vue';
const trackingMixin = Tracking.mixin();
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
index 8042e8c7bc9..b0972246e70 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
@@ -1,16 +1,15 @@
<script>
+import { GlSearchBoxByType } from '@gitlab/ui';
import { debounce } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import { GlIcon } from '@gitlab/ui';
-import eventHub from '../event_hub';
-import frequentItemsMixin from './frequent_items_mixin';
import Tracking from '~/tracking';
+import frequentItemsMixin from './frequent_items_mixin';
const trackingMixin = Tracking.mixin();
export default {
components: {
- GlIcon,
+ GlSearchBoxByType,
},
mixins: [frequentItemsMixin, trackingMixin],
data() {
@@ -32,30 +31,17 @@ export default {
this.setSearchQuery(this.searchQuery);
}, 500),
},
- mounted() {
- eventHub.$on(`${this.namespace}-dropdownOpen`, this.setFocus);
- },
- beforeDestroy() {
- eventHub.$off(`${this.namespace}-dropdownOpen`, this.setFocus);
- },
methods: {
...mapActions(['setSearchQuery']),
- setFocus() {
- this.$refs.search.focus();
- },
},
};
</script>
<template>
<div class="search-input-container d-none d-sm-block">
- <input
- ref="search"
+ <gl-search-box-by-type
v-model="searchQuery"
:placeholder="translations.searchInputPlaceholder"
- type="search"
- class="form-control"
/>
- <gl-icon v-if="!searchQuery" name="search" class="search-icon" />
</div>
</template>
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index cef8be37a40..eb8a404e8a5 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
+import { createStore } from '~/frequent_items/store';
import Translate from '~/vue_shared/translate';
import eventHub from './event_hub';
-import { createStore } from '~/frequent_items/store';
Vue.use(Translate);
diff --git a/app/assets/javascripts/frequent_items/store/actions.js b/app/assets/javascripts/frequent_items/store/actions.js
index f4156487625..90b454d1b42 100644
--- a/app/assets/javascripts/frequent_items/store/actions.js
+++ b/app/assets/javascripts/frequent_items/store/actions.js
@@ -1,7 +1,7 @@
import AccessorUtilities from '~/lib/utils/accessor';
-import * as types from './mutation_types';
-import { getTopFrequentItems } from '../utils';
import { getGroups, getProjects } from '~/rest_api';
+import { getTopFrequentItems } from '../utils';
+import * as types from './mutation_types';
export const setNamespace = ({ commit }, namespace) => {
commit(types.SET_NAMESPACE, namespace);
diff --git a/app/assets/javascripts/frequent_items/utils.js b/app/assets/javascripts/frequent_items/utils.js
index 63fe0ef20b0..88519d934cb 100644
--- a/app/assets/javascripts/frequent_items/utils.js
+++ b/app/assets/javascripts/frequent_items/utils.js
@@ -1,5 +1,5 @@
-import { take } from 'lodash';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import { take } from 'lodash';
import { sanitize } from '~/lib/dompurify';
import { FREQUENT_ITEMS, HOUR_IN_MS } from './constants';
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index cf9ff87f25e..d209a971c39 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,19 +1,23 @@
import $ from 'jquery';
import '~/lib/utils/jquery_at_who';
import { escape, template } from 'lodash';
+import * as Emoji from '~/emoji';
+import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
import { isUserBusy } from '~/set_status_modal/utils';
-import glRegexp from './lib/utils/regexp';
+import SidebarMediator from '~/sidebar/sidebar_mediator';
import AjaxCache from './lib/utils/ajax_cache';
-import axios from '~/lib/utils/axios_utils';
import { spriteIcon } from './lib/utils/common_utils';
-import * as Emoji from '~/emoji';
+import glRegexp from './lib/utils/regexp';
function sanitize(str) {
return str.replace(/<(?:.|\n)*?>/gm, '');
}
+function createMemberSearchString(member) {
+ return `${member.name.replace(/ /g, '')} ${member.username}`;
+}
+
export function membersBeforeSave(members) {
return members.map((member) => {
const GROUP_TYPE = 'Group';
@@ -40,7 +44,7 @@ export function membersBeforeSave(members) {
username: member.username,
avatarTag: autoCompleteAvatar.length === 1 ? txtAvatar : imgAvatar,
title: sanitize(title),
- search: sanitize(`${member.username} ${member.name}`),
+ search: sanitize(createMemberSearchString(member)),
icon: avatarIcon,
availability: member?.availability,
};
@@ -186,59 +190,43 @@ class GfmAutoComplete {
}
setupEmoji($input) {
- const self = this;
- const { filter, ...defaults } = this.getDefaultCallbacks();
+ const fetchData = this.fetchData.bind(this);
// Emoji
$input.atwho({
at: ':',
- displayTpl(value) {
- let tmpl = GfmAutoComplete.Loading.template;
- if (value && value.name) {
- tmpl = GfmAutoComplete.Emoji.templateFunction(value.name);
- }
- return tmpl;
- },
+ displayTpl: GfmAutoComplete.Emoji.templateFunction,
insertTpl: GfmAutoComplete.Emoji.insertTemplateFunction,
skipSpecialCharacterTest: true,
data: GfmAutoComplete.defaultLoadingData,
callbacks: {
- ...defaults,
+ ...this.getDefaultCallbacks(),
matcher(flag, subtext) {
const regexp = new RegExp(`(?:[^${glRegexp.unicodeLetters}0-9:]|\n|^):([^:]*)$`, 'gi');
const match = regexp.exec(subtext);
return match && match.length ? match[1] : null;
},
- filter(query, items, searchKey) {
- const filtered = filter.call(this, query, items, searchKey);
- if (query.length === 0 || GfmAutoComplete.isLoading(items)) {
- return filtered;
+ filter(query, items) {
+ if (GfmAutoComplete.isLoading(items)) {
+ fetchData(this.$inputor, this.at);
+ return items;
}
- // map from value to "<value> is <field> of <emoji>", arranged by emoji
- const emojis = {};
- filtered.forEach(({ name: value }) => {
- self.emojiLookup[value].forEach(({ emoji: { name }, kind }) => {
- let entry = emojis[name];
- if (!entry) {
- entry = {};
- emojis[name] = entry;
- }
- if (!(kind in entry) || value.localeCompare(entry[kind]) < 0) {
- entry[kind] = value;
- }
- });
- });
+ return GfmAutoComplete.Emoji.filter(query);
+ },
+ sorter(query, items) {
+ this.setting.highlightFirst = this.setting.alwaysHighlightFirst || query.length > 0;
+ if (GfmAutoComplete.isLoading(items)) {
+ this.setting.highlightFirst = false;
+ return items;
+ }
- // collate results to list, prefering name > unicode > alias > description
- const results = [];
- Object.values(emojis).forEach(({ name, unicode, alias, description }) => {
- results.push(name || unicode || alias || description);
- });
+ if (query.length === 0) {
+ return items;
+ }
- // return to the form atwho wants
- return results.map((name) => ({ name }));
+ return GfmAutoComplete.Emoji.sorter(items);
},
},
});
@@ -298,9 +286,7 @@ class GfmAutoComplete {
// Cache assignees list for easier filtering later
assignees =
- SidebarMediator.singleton?.store?.assignees?.map(
- (assignee) => `${assignee.username} ${assignee.name}`,
- ) || [];
+ SidebarMediator.singleton?.store?.assignees?.map(createMemberSearchString) || [];
const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers);
return match && match.length ? match[1] : null;
@@ -672,32 +658,7 @@ class GfmAutoComplete {
async loadEmojiData($input, at) {
await Emoji.initEmojiMap();
- // All the emoji
- const emojis = Emoji.getAllEmoji();
-
- // Add all of the fields to atwho's database
- this.loadData($input, at, [
- ...Object.keys(emojis), // Names
- ...Object.values(emojis).flatMap(({ aliases }) => aliases), // Aliases
- ...Object.values(emojis).map(({ e }) => e), // Unicode values
- ...Object.values(emojis).map(({ d }) => d), // Descriptions
- ]);
-
- // Construct a lookup that can correlate a value to "<value> is the <field> of <emoji>"
- const lookup = {};
- const add = (key, kind, emoji) => {
- if (!(key in lookup)) {
- lookup[key] = [];
- }
- lookup[key].push({ kind, emoji });
- };
- Object.values(emojis).forEach((emoji) => {
- add(emoji.name, 'name', emoji);
- add(emoji.d, 'description', emoji);
- add(emoji.e, 'unicode', emoji);
- emoji.aliases.forEach((a) => add(a, 'alias', emoji));
- });
- this.emojiLookup = lookup;
+ this.loadData($input, at, ['loaded']);
GfmAutoComplete.glEmojiTag = Emoji.glEmojiTag;
}
@@ -770,36 +731,38 @@ GfmAutoComplete.typesWithBackendFiltering = ['vulnerabilities'];
GfmAutoComplete.isTypeWithBackendFiltering = (type) =>
GfmAutoComplete.typesWithBackendFiltering.includes(GfmAutoComplete.atTypeMap[type]);
-function findEmoji(name) {
- return Emoji.searchEmoji(name, { match: 'contains', raw: true }).sort((a, b) => {
- if (a.index !== b.index) {
- return a.index - b.index;
- }
- return a.field.localeCompare(b.field);
- });
-}
-
// Emoji
GfmAutoComplete.glEmojiTag = null;
GfmAutoComplete.Emoji = {
insertTemplateFunction(value) {
- const results = findEmoji(value.name);
- if (results.length) {
- return `:${results[0].emoji.name}:`;
- }
- return `:${value.name}:`;
+ return `:${value.emoji.name}:`;
},
- templateFunction(name) {
- // glEmojiTag helper is loaded on-demand in fetchData()
- if (!GfmAutoComplete.glEmojiTag) return `<li>${name}</li>`;
+ templateFunction(item) {
+ if (GfmAutoComplete.isLoading(item)) {
+ return GfmAutoComplete.Loading.template;
+ }
- const results = findEmoji(name);
- if (!results.length) {
- return `<li>${name} ${GfmAutoComplete.glEmojiTag(name)}</li>`;
+ const escapedFieldValue = escape(item.fieldValue);
+ if (!GfmAutoComplete.glEmojiTag) {
+ return `<li>${escapedFieldValue}</li>`;
}
- const { field, emoji } = results[0];
- return `<li>${field} ${GfmAutoComplete.glEmojiTag(emoji.name)}</li>`;
+ return `<li>${escapedFieldValue} ${GfmAutoComplete.glEmojiTag(item.emoji.name)}</li>`;
+ },
+ filter(query) {
+ if (query.length === 0) {
+ return Object.values(Emoji.getAllEmoji())
+ .map((emoji) => ({
+ emoji,
+ fieldValue: emoji.name,
+ }))
+ .slice(0, 20);
+ }
+
+ return Emoji.searchEmoji(query);
+ },
+ sorter(items) {
+ return Emoji.sortEmoji(items);
},
};
// Team Members
diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js
index 3e777c2dc09..3a04779e48d 100644
--- a/app/assets/javascripts/gl_form.js
+++ b/app/assets/javascripts/gl_form.js
@@ -1,9 +1,9 @@
-import $ from 'jquery';
import autosize from 'autosize';
+import $ from 'jquery';
import GfmAutoComplete, { defaultAutocompleteConfig } from 'ee_else_ce/gfm_auto_complete';
+import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
import dropzoneInput from './dropzone_input';
import { addMarkdownListeners, removeMarkdownListeners } from './lib/utils/text_markdown';
-import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
export default class GLForm {
/**
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index 3a8ae56bb8f..cde2cd6d6ab 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import { parseQueryStringIntoObject } from '~/lib/utils/common_utils';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { parseQueryStringIntoObject } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
export default class GpgBadges {
diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
index 7a991ac2455..7b029c6cf54 100644
--- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
+++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
@@ -54,9 +54,9 @@ export default {
<template>
<section id="grafana" class="settings no-animate js-grafana-integration">
<div class="settings-header">
- <h3 class="js-section-header h4">
+ <h4 class="js-section-header">
{{ s__('GrafanaIntegration|Grafana authentication') }}
- </h3>
+ </h4>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
<p class="js-section-sub-header">
{{ s__('GrafanaIntegration|Embed Grafana charts in GitLab issues.') }}
diff --git a/app/assets/javascripts/grafana_integration/index.js b/app/assets/javascripts/grafana_integration/index.js
index a93edab4388..208a92c97c7 100644
--- a/app/assets/javascripts/grafana_integration/index.js
+++ b/app/assets/javascripts/grafana_integration/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import store from './store';
import GrafanaIntegration from './components/grafana_integration.vue';
+import store from './store';
export default () => {
const el = document.querySelector('.js-grafana-integration');
diff --git a/app/assets/javascripts/grafana_integration/store/actions.js b/app/assets/javascripts/grafana_integration/store/actions.js
index 436f92eae84..7c5d4695731 100644
--- a/app/assets/javascripts/grafana_integration/store/actions.js
+++ b/app/assets/javascripts/grafana_integration/store/actions.js
@@ -1,7 +1,7 @@
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import * as mutationTypes from './mutation_types';
export const setGrafanaUrl = ({ commit }, url) => commit(mutationTypes.SET_GRAFANA_URL, url);
diff --git a/app/assets/javascripts/grafana_integration/store/index.js b/app/assets/javascripts/grafana_integration/store/index.js
index e3dcfd31a83..a11bd8089fd 100644
--- a/app/assets/javascripts/grafana_integration/store/index.js
+++ b/app/assets/javascripts/grafana_integration/store/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql
index 74b425717a0..801311301ac 100644
--- a/app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert_note.fragment.graphql
@@ -1,4 +1,4 @@
-#import "~/graphql_shared/fragments/author.fragment.graphql"
+#import "./author.fragment.graphql"
fragment AlertNote on Note {
id
diff --git a/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql b/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql
new file mode 100644
index 00000000000..ba1e607bc10
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/mutations/alert_status_update.mutation.graphql
@@ -0,0 +1,17 @@
+#import "../fragments/alert_note.fragment.graphql"
+
+mutation updateAlertStatus($projectPath: ID!, $status: AlertManagementStatus!, $iid: String!) {
+ updateAlertStatus(input: { iid: $iid, status: $status, projectPath: $projectPath }) {
+ errors
+ alert {
+ iid
+ status
+ endedAt
+ notes {
+ nodes {
+ ...AlertNote
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/graphql_shared/mutations/update_alert_status.mutation.graphql b/app/assets/javascripts/graphql_shared/mutations/update_alert_status.mutation.graphql
deleted file mode 100644
index 42dc388c9d1..00000000000
--- a/app/assets/javascripts/graphql_shared/mutations/update_alert_status.mutation.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-#import "~/graphql_shared/fragments/alert_note.fragment.graphql"
-
-mutation updateAlertStatus($projectPath: ID!, $status: AlertManagementStatus!, $iid: String!) {
- updateAlertStatus(input: { iid: $iid, status: $status, projectPath: $projectPath }) {
- errors
- alert {
- iid
- status
- endedAt
- notes {
- nodes {
- ...AlertNote
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
index e94758ef60e..7a676e67f1b 100644
--- a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
@@ -10,6 +10,7 @@ query getAlerts(
$nextPageCursor: String = ""
$searchTerm: String = ""
$assigneeUsername: String = ""
+ $domain: AlertManagementDomainFilter = operations
) {
project(fullPath: $projectPath) {
alertManagementAlerts(
@@ -21,6 +22,7 @@ query getAlerts(
last: $lastPageSize
after: $nextPageCursor
before: $prevPageCursor
+ domain: $domain
) {
nodes {
...AlertListItem
diff --git a/app/assets/javascripts/group.js b/app/assets/javascripts/group.js
index 6878635b288..39c8a88d485 100644
--- a/app/assets/javascripts/group.js
+++ b/app/assets/javascripts/group.js
@@ -1,7 +1,7 @@
-import { slugify } from './lib/utils/text_utility';
-import fetchGroupPathAvailability from '~/pages/groups/new/fetch_group_path_availability';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
+import fetchGroupPathAvailability from '~/pages/groups/new/fetch_group_path_availability';
+import { slugify } from './lib/utils/text_utility';
export default class Group {
constructor() {
diff --git a/app/assets/javascripts/group_label_subscription.js b/app/assets/javascripts/group_label_subscription.js
index bfaa54080bd..257f5ac9658 100644
--- a/app/assets/javascripts/group_label_subscription.js
+++ b/app/assets/javascripts/group_label_subscription.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import { __ } from '~/locale';
-import axios from './lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from './flash';
import { fixTitle, hide } from '~/tooltips';
+import { deprecatedCreateFlash as flash } from './flash';
+import axios from './lib/utils/axios_utils';
const tooltipTitles = {
group: __('Unsubscribe at group level'),
diff --git a/app/assets/javascripts/group_settings/components/shared_runners_form.vue b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
index d6ed08a9407..a1d706f0f66 100644
--- a/app/assets/javascripts/group_settings/components/shared_runners_form.vue
+++ b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
@@ -1,8 +1,8 @@
<script>
import { GlToggle, GlLoadingIcon, GlTooltip, GlAlert } from '@gitlab/ui';
import { debounce } from 'lodash';
-import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
import {
DEBOUNCE_TOGGLE_DELAY,
ERROR_MESSAGE,
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index 4f26bab8bd3..9d2c7cfe581 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -2,13 +2,13 @@
/* global Flash */
import { GlLoadingIcon, GlModal } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-import { HIDDEN_CLASS } from '~/lib/utils/constants';
import { getParameterByName } from '~/lib/utils/common_utils';
+import { HIDDEN_CLASS } from '~/lib/utils/constants';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { __, s__, sprintf } from '~/locale';
-import eventHub from '../event_hub';
import { COMMON_STR, CONTENT_LIST_CLASS } from '../constants';
+import eventHub from '../event_hub';
import groupsComponent from './groups.vue';
export default {
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index d65ad974c73..d41fa0b2410 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -3,16 +3,14 @@
import { GlLoadingIcon, GlBadge, GlTooltipDirective } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
import identicon from '../../vue_shared/components/identicon.vue';
-import eventHub from '../event_hub';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '../constants';
+import eventHub from '../event_hub';
+import itemActions from './item_actions.vue';
import itemCaret from './item_caret.vue';
-import itemTypeIcon from './item_type_icon.vue';
import itemStats from './item_stats.vue';
import itemStatsValue from './item_stats_value.vue';
-import itemActions from './item_actions.vue';
-
-import { showLearnGitLabGroupItemPopover } from '~/onboarding_issues';
+import itemTypeIcon from './item_type_icon.vue';
export default {
directives: {
@@ -78,11 +76,6 @@ export default {
return this.group.microdata || {};
},
},
- mounted() {
- if (this.group.name === 'Learn GitLab') {
- showLearnGitLabGroupItemPopover(this.group.id);
- }
- },
methods: {
onClickRowGroup(e) {
const NO_EXPAND_CLS = 'no-expand';
@@ -179,7 +172,12 @@ export default {
<div
class="metadata align-items-md-center d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between"
>
- <item-actions v-if="isGroup" :group="group" :parent-group="parentGroup" />
+ <item-actions
+ v-if="isGroup"
+ :group="group"
+ :parent-group="parentGroup"
+ :action="action"
+ />
<item-stats :item="group" class="group-stats gl-mt-2 d-none d-md-flex" />
</div>
</div>
diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue
index c7713cbfafc..d407fdd2b90 100644
--- a/app/assets/javascripts/groups/components/groups.vue
+++ b/app/assets/javascripts/groups/components/groups.vue
@@ -1,7 +1,7 @@
<script>
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
-import eventHub from '../event_hub';
import { getParameterByName } from '../../lib/utils/common_utils';
+import eventHub from '../event_hub';
export default {
components: {
diff --git a/app/assets/javascripts/groups/components/invite_members_banner.vue b/app/assets/javascripts/groups/components/invite_members_banner.vue
index da7adab1d86..81c5e3ce85d 100644
--- a/app/assets/javascripts/groups/components/invite_members_banner.vue
+++ b/app/assets/javascripts/groups/components/invite_members_banner.vue
@@ -1,7 +1,7 @@
<script>
import { GlBanner } from '@gitlab/ui';
-import { s__ } from '~/locale';
import { parseBoolean, setCookie, getCookie } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index ff52f5ef51c..df751a3f37e 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
-import eventHub from '../event_hub';
import { COMMON_STR } from '../constants';
+import eventHub from '../event_hub';
export default {
components: {
diff --git a/app/assets/javascripts/groups/groups_filterable_list.js b/app/assets/javascripts/groups/groups_filterable_list.js
index c33ad8b6ecb..cedf16cd7f1 100644
--- a/app/assets/javascripts/groups/groups_filterable_list.js
+++ b/app/assets/javascripts/groups/groups_filterable_list.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import FilterableList from '~/filterable_list';
-import eventHub from './event_hub';
import { normalizeHeaders, getParameterByName } from '../lib/utils/common_utils';
+import eventHub from './event_hub';
export default class GroupFilterableList extends FilterableList {
constructor({
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
index e11c3aaf984..c34810954a3 100644
--- a/app/assets/javascripts/groups/index.js
+++ b/app/assets/javascripts/groups/index.js
@@ -1,16 +1,16 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
-import UserCallout from '~/user_callout';
+import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
+import UserCallout from '~/user_callout';
import Translate from '../vue_shared/translate';
-import GroupFilterableList from './groups_filterable_list';
-import GroupsStore from './store/groups_store';
-import GroupsService from './service/groups_service';
import groupsApp from './components/app.vue';
import groupFolderComponent from './components/group_folder.vue';
import groupItemComponent from './components/group_item.vue';
import { GROUPS_LIST_HOLDER_CLASS, CONTENT_LIST_CLASS } from './constants';
+import GroupFilterableList from './groups_filterable_list';
+import GroupsService from './service/groups_service';
+import GroupsStore from './store/groups_store';
Vue.use(Translate);
@@ -33,8 +33,8 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
dataEl = containerEl.querySelector(CONTENT_LIST_CLASS);
}
- Vue.component('group-folder', groupFolderComponent);
- Vue.component('group-item', groupItemComponent);
+ Vue.component('GroupFolder', groupFolderComponent);
+ Vue.component('GroupItem', groupItemComponent);
Vue.use(GlToast);
diff --git a/app/assets/javascripts/groups/members/components/app.vue b/app/assets/javascripts/groups/members/components/app.vue
deleted file mode 100644
index 34a2c67fa9f..00000000000
--- a/app/assets/javascripts/groups/members/components/app.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-<script>
-import { mapState, mapMutations } from 'vuex';
-import { GlAlert } from '@gitlab/ui';
-import MembersTable from '~/members/components/table/members_table.vue';
-import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
-import { scrollToElement } from '~/lib/utils/common_utils';
-import { HIDE_ERROR } from '~/members/store/mutation_types';
-
-export default {
- name: 'GroupMembersApp',
- components: { MembersTable, FilterSortContainer, GlAlert },
- computed: {
- ...mapState(['showError', 'errorMessage']),
- },
- watch: {
- showError(value) {
- if (value) {
- this.$nextTick(() => {
- scrollToElement(this.$refs.errorAlert.$el);
- });
- }
- },
- },
- methods: {
- ...mapMutations({
- hideError: HIDE_ERROR,
- }),
- },
-};
-</script>
-
-<template>
- <div>
- <gl-alert v-if="showError" ref="errorAlert" variant="danger" @dismiss="hideError">{{
- errorMessage
- }}</gl-alert>
- <filter-sort-container />
- <members-table />
- </div>
-</template>
diff --git a/app/assets/javascripts/groups/members/constants.js b/app/assets/javascripts/groups/members/constants.js
index 6d71b666d7a..3315712891d 100644
--- a/app/assets/javascripts/groups/members/constants.js
+++ b/app/assets/javascripts/groups/members/constants.js
@@ -1,5 +1 @@
export const GROUP_MEMBER_BASE_PROPERTY_NAME = 'group_member';
-export const GROUP_MEMBER_ACCESS_LEVEL_PROPERTY_NAME = 'access_level';
-
-export const GROUP_LINK_BASE_PROPERTY_NAME = 'group_link';
-export const GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME = 'group_access';
diff --git a/app/assets/javascripts/groups/members/index.js b/app/assets/javascripts/groups/members/index.js
deleted file mode 100644
index 3ec874b8d36..00000000000
--- a/app/assets/javascripts/groups/members/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import { GlToast } from '@gitlab/ui';
-import { parseDataAttributes } from 'ee_else_ce/groups/members/utils';
-import App from './components/app.vue';
-import membersStore from '~/members/store';
-
-export const initGroupMembersApp = (
- el,
- {
- tableFields = [],
- tableAttrs = {},
- tableSortableFields = [],
- requestFormatter = () => {},
- filteredSearchBar = { show: false },
- },
-) => {
- if (!el) {
- return () => {};
- }
-
- Vue.use(Vuex);
- Vue.use(GlToast);
-
- const store = new Vuex.Store(
- membersStore({
- ...parseDataAttributes(el),
- currentUserId: gon.current_user_id || null,
- tableFields,
- tableAttrs,
- tableSortableFields,
- requestFormatter,
- filteredSearchBar,
- }),
- );
-
- return new Vue({
- el,
- components: { App },
- store,
- render: (createElement) => createElement('app'),
- });
-};
diff --git a/app/assets/javascripts/groups/members/utils.js b/app/assets/javascripts/groups/members/utils.js
index 4fcf348b69f..dc4eb7f4422 100644
--- a/app/assets/javascripts/groups/members/utils.js
+++ b/app/assets/javascripts/groups/members/utils.js
@@ -1,45 +1,8 @@
-import { isUndefined } from 'lodash';
-import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
-import {
- GROUP_MEMBER_BASE_PROPERTY_NAME,
- GROUP_MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
- GROUP_LINK_BASE_PROPERTY_NAME,
- GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME,
-} from './constants';
-
-export const parseDataAttributes = (el) => {
- const { members, groupId, memberPath, canManageMembers } = el.dataset;
-
- return {
- members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }),
- sourceId: parseInt(groupId, 10),
- memberPath,
- canManageMembers: parseBoolean(canManageMembers),
- };
-};
-
-const baseRequestFormatter = (basePropertyName, accessLevelPropertyName) => ({
- accessLevel,
- ...otherProperties
-}) => {
- const accessLevelProperty = !isUndefined(accessLevel)
- ? { [accessLevelPropertyName]: accessLevel }
- : {};
+import { MEMBER_ACCESS_LEVEL_PROPERTY_NAME } from '~/members/constants';
+import { baseRequestFormatter } from '~/members/utils';
+import { GROUP_MEMBER_BASE_PROPERTY_NAME } from './constants';
- return {
- [basePropertyName]: {
- ...accessLevelProperty,
- ...otherProperties,
- },
- };
-};
-
-export const memberRequestFormatter = baseRequestFormatter(
+export const groupMemberRequestFormatter = baseRequestFormatter(
GROUP_MEMBER_BASE_PROPERTY_NAME,
- GROUP_MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
-);
-
-export const groupLinkRequestFormatter = baseRequestFormatter(
- GROUP_LINK_BASE_PROPERTY_NAME,
- GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME,
+ MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
);
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
index 59cc779d2ae..d6343f698c0 100644
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ b/app/assets/javascripts/groups/transfer_dropdown.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import { __ } from '~/locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from '~/locale';
export default class TransferDropdown {
constructor() {
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index c65fff432d0..da2890f91fc 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
import { escape } from 'lodash';
-import axios from './lib/utils/axios_utils';
+import { __ } from '~/locale';
import Api from './api';
+import axios from './lib/utils/axios_utils';
import { normalizeHeaders } from './lib/utils/common_utils';
-import { __ } from '~/locale';
import { loadCSSFile } from './lib/utils/css_utils';
const fetchGroups = (params) => {
diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index 9f9708bf879..22c648a76a7 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
import { highCountTrim } from '~/lib/utils/text_utility';
import Tracking from '~/tracking';
+import Translate from '~/vue_shared/translate';
/**
* Updates todo counter when todos are toggled.
@@ -106,7 +106,5 @@ export function initNavUserDropdownTracking() {
}
}
-document.addEventListener('DOMContentLoaded', () => {
- requestIdleCallback(initStatusTriggers);
- requestIdleCallback(initNavUserDropdownTracking);
-});
+requestIdleCallback(initStatusTriggers);
+requestIdleCallback(initNavUserDropdownTracking);
diff --git a/app/assets/javascripts/helpers/avatar_helper.js b/app/assets/javascripts/helpers/avatar_helper.js
index 4f04a1b8c16..35b09e9b027 100644
--- a/app/assets/javascripts/helpers/avatar_helper.js
+++ b/app/assets/javascripts/helpers/avatar_helper.js
@@ -1,6 +1,6 @@
import { escape } from 'lodash';
-import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
export const DEFAULT_SIZE_CLASS = 's40';
export const IDENTICON_BG_COUNT = 7;
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index 644808cb83a..c71d911adfb 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -1,6 +1,7 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { leftSidebarViews } from '../constants';
export default {
@@ -11,7 +12,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
computed: {
- ...mapState(['currentActivityView']),
+ ...mapState(['currentActivityView', 'stagedFiles']),
},
methods: {
...mapActions(['updateActivityBarView']),
@@ -20,7 +21,7 @@ export default {
this.updateActivityBarView(view);
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
},
},
leftSidebarViews,
@@ -81,6 +82,9 @@ 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">
+ {{ stagedFiles.length }}
+ </div>
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue
index c317fadb656..1ae7cf9339d 100644
--- a/app/assets/javascripts/ide/components/branches/search_list.vue
+++ b/app/assets/javascripts/ide/components/branches/search_list.vue
@@ -1,7 +1,7 @@
<script>
-import { mapActions, mapState } from 'vuex';
-import { debounce } from 'lodash';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { mapActions, mapState } from 'vuex';
import Item from './item.vue';
export default {
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index b89329c92ec..273d8d972f7 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,11 +1,14 @@
<script>
+import { GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
-import { GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
-import consts from '../../stores/modules/commit/constants';
-import RadioGroup from './radio_group.vue';
+import {
+ COMMIT_TO_CURRENT_BRANCH,
+ COMMIT_TO_NEW_BRANCH,
+} from '../../stores/modules/commit/constants';
import NewMergeRequestOption from './new_merge_request_option.vue';
+import RadioGroup from './radio_group.vue';
const { mapState: mapCommitState, mapActions: mapCommitActions } = createNamespacedHelpers(
'commit',
@@ -53,14 +56,14 @@ export default {
}
if (this.shouldDefaultToCurrentBranch) {
- this.updateCommitAction(consts.COMMIT_TO_CURRENT_BRANCH);
+ this.updateCommitAction(COMMIT_TO_CURRENT_BRANCH);
} else {
- this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH);
+ this.updateCommitAction(COMMIT_TO_NEW_BRANCH);
}
},
},
- commitToCurrentBranch: consts.COMMIT_TO_CURRENT_BRANCH,
- commitToNewBranch: consts.COMMIT_TO_NEW_BRANCH,
+ commitToCurrentBranch: COMMIT_TO_CURRENT_BRANCH,
+ commitToNewBranch: COMMIT_TO_NEW_BRANCH,
currentBranchPermissionsTooltip: s__(
"IDE|This option is disabled because you don't have write permissions for the current branch.",
),
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
index 53fac09ab66..75f02af28c4 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions } from 'vuex';
import { GlModal, GlButton } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import { sprintf, __ } from '~/locale';
-import FileIcon from '~/vue_shared/components/file_icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index 7c3e522a488..cdb3eaff207 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -1,12 +1,16 @@
<script>
+import { GlModal, GlSafeHtmlDirective, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { mapState, mapActions, mapGetters } from 'vuex';
-import { GlModal, GlSafeHtmlDirective, GlButton } from '@gitlab/ui';
-import { n__, __ } from '~/locale';
-import CommitMessageField from './message_field.vue';
-import Actions from './actions.vue';
-import SuccessMessage from './success_message.vue';
+import { n__, s__ } from '~/locale';
import { leftSidebarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants';
import { createUnexpectedCommitError } from '../../lib/errors';
+import Actions from './actions.vue';
+import CommitMessageField from './message_field.vue';
+import SuccessMessage from './success_message.vue';
+
+const MSG_CANNOT_PUSH_CODE = s__(
+ 'WebIDE|You need permission to edit files directly in this project.',
+);
export default {
components: {
@@ -18,6 +22,7 @@ export default {
},
directives: {
SafeHtml: GlSafeHtmlDirective,
+ GlTooltip: GlTooltipDirective,
},
data() {
return {
@@ -30,15 +35,21 @@ export default {
computed: {
...mapState(['changedFiles', 'stagedFiles', 'currentActivityView', 'lastCommitMsg']),
...mapState('commit', ['commitMessage', 'submitCommitLoading', 'commitError']),
- ...mapGetters(['someUncommittedChanges']),
+ ...mapGetters(['someUncommittedChanges', 'canPushCode']),
...mapGetters('commit', ['discardDraftButtonDisabled', 'preBuiltCommitMessage']),
+ commitButtonDisabled() {
+ return !this.canPushCode || !this.someUncommittedChanges;
+ },
+ commitButtonTooltip() {
+ if (!this.canPushCode) {
+ return MSG_CANNOT_PUSH_CODE;
+ }
+
+ return '';
+ },
overviewText() {
return n__('%d changed file', '%d changed files', this.stagedFiles.length);
},
- commitButtonText() {
- return this.stagedFiles.length ? __('Commit') : __('Stage & Commit');
- },
-
currentViewIsCommitView() {
return this.currentActivityView === leftSidebarViews.commit.name;
},
@@ -73,6 +84,12 @@ export default {
'updateCommitAction',
]),
commit() {
+ // Even though the submit button will be disabled, we need to disable the submission
+ // since hitting enter on the branch name text input also submits the form.
+ if (!this.canPushCode) {
+ return false;
+ }
+
return this.commitChanges();
},
handleCompactState() {
@@ -113,6 +130,8 @@ export default {
this.componentHeight = null;
},
},
+ // Expose for tests
+ MSG_CANNOT_PUSH_CODE,
};
</script>
@@ -134,17 +153,22 @@ export default {
@after-enter="afterEndTransition"
>
<div v-if="isCompact" ref="compactEl" class="commit-form-compact">
- <gl-button
- :disabled="!someUncommittedChanges"
- category="primary"
- variant="info"
- block
- class="qa-begin-commit-button"
- data-testid="begin-commit-button"
- @click="beginCommit"
+ <div
+ v-gl-tooltip="{ title: commitButtonTooltip }"
+ data-testid="begin-commit-button-tooltip"
>
- {{ __('Commit…') }}
- </gl-button>
+ <gl-button
+ :disabled="commitButtonDisabled"
+ category="primary"
+ variant="info"
+ block
+ class="qa-begin-commit-button"
+ data-testid="begin-commit-button"
+ @click="beginCommit"
+ >
+ {{ __('Commit…') }}
+ </gl-button>
+ </div>
<p class="text-center bold">{{ overviewText }}</p>
</div>
<form v-else ref="formEl" @submit.prevent.stop="commit">
@@ -157,16 +181,29 @@ export default {
/>
<div class="clearfix gl-mt-5">
<actions />
+ <div
+ v-gl-tooltip="{ title: commitButtonTooltip }"
+ class="float-left"
+ data-testid="commit-button-tooltip"
+ >
+ <gl-button
+ :disabled="commitButtonDisabled"
+ :loading="submitCommitLoading"
+ data-testid="commit-button"
+ class="qa-commit-button"
+ category="primary"
+ variant="success"
+ @click="commit"
+ >
+ {{ __('Commit') }}
+ </gl-button>
+ </div>
<gl-button
- :loading="submitCommitLoading"
- class="float-left qa-commit-button"
- category="primary"
- variant="success"
- @click="commit"
+ v-if="!discardDraftButtonDisabled"
+ class="float-right"
+ data-testid="discard-draft"
+ @click="discardDraft"
>
- {{ __('Commit') }}
- </gl-button>
- <gl-button v-if="!discardDraftButtonDisabled" class="float-right" @click="discardDraft">
{{ __('Discard draft') }}
</gl-button>
<gl-button
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index 729ff7c74ec..fbe353fc4ba 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions } from 'vuex';
import { GlModal, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import { __, sprintf } from '~/locale';
import ListItem from './list_item.vue';
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
index 4192a002486..79b6fd1ec68 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import { viewerTypes } from '../../constants';
import getCommitIconMap from '../../commit_icon';
+import { viewerTypes } from '../../constants';
export default {
components: {
@@ -85,7 +85,11 @@ export default {
role="button"
@click="openFileInEditor"
>
- <span class="multi-file-commit-list-file-path d-flex align-items-center">
+ <span
+ class="multi-file-commit-list-file-path d-flex align-items-center"
+ data-qa-selector="file_to_commit_content"
+ :data-qa-file-name="file.name"
+ >
<file-icon :file-name="file.name" class="gl-mr-3" />
<template v-if="file.prevName && file.prevName !== file.name">
{{ file.prevName }} &#x2192;
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue b/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
index cdf49866982..121dae4b87e 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
@@ -1,6 +1,6 @@
<script>
-import { createNamespacedHelpers } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
+import { createNamespacedHelpers } from 'vuex';
import { s__ } from '~/locale';
const { mapActions: mapCommitActions, mapGetters: mapCommitGetters } = createNamespacedHelpers(
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
index 91cce44382c..039b4a54b26 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState, mapGetters } from 'vuex';
import { GlTooltipDirective } from '@gitlab/ui';
+import { mapActions, mapState, mapGetters } from 'vuex';
export default {
directives: {
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
index 08635b43b91..d3a52f9f0cf 100644
--- a/app/assets/javascripts/ide/components/error_message.vue
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -1,7 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapActions } from 'vuex';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { mapActions } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue
index fb0d00dc6a1..d80ad723fce 100644
--- a/app/assets/javascripts/ide/components/file_row_extra.vue
+++ b/app/assets/javascripts/ide/components/file_row_extra.vue
@@ -1,10 +1,10 @@
<script>
-import { mapGetters } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { n__ } from '~/locale';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
-import NewDropdown from './new_dropdown/index.vue';
import MrFileIcon from './mr_file_icon.vue';
+import NewDropdown from './new_dropdown/index.vue';
export default {
name: 'FileRowExtra',
diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
index 772dab3fed3..ec61e3374d7 100644
--- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue
+++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
@@ -1,7 +1,7 @@
<script>
+import { GlIcon, GlLoadingIcon } from '@gitlab/ui';
import $ from 'jquery';
import { mapActions, mapState } from 'vuex';
-import { GlIcon, GlLoadingIcon } from '@gitlab/ui';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
export default {
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index aac899fde0d..2816f89d60d 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,7 +1,7 @@
<script>
+import { GlAlert, GlButton, GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import {
WEBIDE_MARK_APP_START,
WEBIDE_MARK_FILE_FINISH,
@@ -10,13 +10,12 @@ import {
WEBIDE_MEASURE_BEFORE_VUE,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { modalTypes } from '../constants';
import eventHub from '../eventhub';
+import { measurePerformance } from '../utils';
import IdeSidebar from './ide_side_bar.vue';
import RepoEditor from './repo_editor.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-import { measurePerformance } from '../utils';
eventHub.$on(WEBIDE_MEASURE_FILE_AFTER_INTERACTION, () =>
measurePerformance(
@@ -26,10 +25,15 @@ eventHub.$on(WEBIDE_MEASURE_FILE_AFTER_INTERACTION, () =>
),
);
+const MSG_CANNOT_PUSH_CODE = s__(
+ 'WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request.',
+);
+
export default {
components: {
IdeSidebar,
RepoEditor,
+ GlAlert,
GlButton,
GlLoadingIcon,
ErrorMessage: () => import(/* webpackChunkName: 'ide_runtime' */ './error_message.vue'),
@@ -59,12 +63,14 @@ export default {
'loading',
]),
...mapGetters([
+ 'canPushCode',
'activeFile',
'someUncommittedChanges',
'isCommitModeActive',
'allBlobs',
'emptyRepo',
'currentTree',
+ 'hasCurrentProject',
'editorTheme',
'getUrlForPath',
]),
@@ -110,6 +116,7 @@ export default {
this.loadDeferred = true;
},
},
+ MSG_CANNOT_PUSH_CODE,
};
</script>
@@ -118,6 +125,9 @@ export default {
class="ide position-relative d-flex flex-column align-items-stretch"
:class="{ [`theme-${themeName}`]: themeName }"
>
+ <gl-alert v-if="!canPushCode" :dismissible="false">{{
+ $options.MSG_CANNOT_PUSH_CODE
+ }}</gl-alert>
<error-message v-if="errorMessage" :message="errorMessage" />
<div class="ide-view flex-grow d-flex">
<template v-if="loadDeferred">
diff --git a/app/assets/javascripts/ide/components/ide_review.vue b/app/assets/javascripts/ide/components/ide_review.vue
index 7d2f0acb08c..bea25d42756 100644
--- a/app/assets/javascripts/ide/components/ide_review.vue
+++ b/app/assets/javascripts/ide/components/ide_review.vue
@@ -1,8 +1,8 @@
<script>
import { mapGetters, mapState, mapActions } from 'vuex';
-import IdeTreeList from './ide_tree_list.vue';
-import EditorModeDropdown from './editor_mode_dropdown.vue';
import { viewerTypes } from '../constants';
+import EditorModeDropdown from './editor_mode_dropdown.vue';
+import IdeTreeList from './ide_tree_list.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 135b28685ed..c3d6494692a 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,12 +1,12 @@
<script>
-import { mapState, mapGetters } from 'vuex';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
-import IdeTree from './ide_tree.vue';
-import ResizablePanel from './resizable_panel.vue';
+import { mapState, mapGetters } from 'vuex';
+import { SIDEBAR_INIT_WIDTH, leftSidebarViews } from '../constants';
import ActivityBar from './activity_bar.vue';
import CommitForm from './commit_sidebar/form.vue';
import IdeProjectHeader from './ide_project_header.vue';
-import { SIDEBAR_INIT_WIDTH, leftSidebarViews } from '../constants';
+import IdeTree from './ide_tree.vue';
+import ResizablePanel from './resizable_panel.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/ide_sidebar_nav.vue b/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
index 9dbed0ace40..d8daf3b7ad6 100644
--- a/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
+++ b/app/assets/javascripts/ide/components/ide_sidebar_nav.vue
@@ -1,7 +1,8 @@
<script>
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { otherSide } from '../utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { SIDE_RIGHT } from '../constants';
+import { otherSide } from '../utils';
export default {
directives: {
@@ -50,7 +51,7 @@ export default {
},
clickTab(e, tab) {
e.currentTarget.blur();
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
if (this.isActiveTab(tab)) {
this.$emit('close');
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index ee292190e06..28ca1b6750f 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -1,13 +1,13 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { mapActions, mapState, mapGetters } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import IdeStatusList from './ide_status_list.vue';
-import IdeStatusMr from './ide_status_mr.vue';
+import { mapActions, mapState, mapGetters } from 'vuex';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import { rightSidebarViews } from '../constants';
+import IdeStatusList from './ide_status_list.vue';
+import IdeStatusMr from './ide_status_mr.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/ide_status_list.vue b/app/assets/javascripts/ide/components/ide_status_list.vue
index aa61c0d9b5e..da393b42dca 100644
--- a/app/assets/javascripts/ide/components/ide_status_list.vue
+++ b/app/assets/javascripts/ide/components/ide_status_list.vue
@@ -1,8 +1,8 @@
<script>
-import { mapGetters } from 'vuex';
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
-import TerminalSyncStatusSafe from './terminal_sync/terminal_sync_status_safe.vue';
+import { mapGetters } from 'vuex';
import { isTextFile, getFileEOL } from '~/ide/utils';
+import TerminalSyncStatusSafe from './terminal_sync/terminal_sync_status_safe.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index e563de6659a..2df998d7518 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -2,9 +2,9 @@
import { mapState, mapGetters, mapActions } from 'vuex';
import { modalTypes, viewerTypes } from '../constants';
import IdeTreeList from './ide_tree_list.vue';
-import Upload from './new_dropdown/upload.vue';
import NewEntryButton from './new_dropdown/button.vue';
import NewModal from './new_dropdown/modal.vue';
+import Upload from './new_dropdown/upload.vue';
export default {
components: {
@@ -58,8 +58,9 @@ export default {
<new-entry-button
:label="__('New file')"
:show-label="false"
- class="d-flex border-0 p-0 mr-3 qa-new-file"
+ class="d-flex border-0 p-0 mr-3"
icon="doc-new"
+ data-qa-selector="new_file_button"
@click="createNewFile()"
/>
<upload
@@ -73,6 +74,7 @@ export default {
:show-label="false"
class="d-flex border-0 p-0"
icon="folder-new"
+ data-qa-selector="new_directory_button"
@click="createNewFolder()"
/>
</div>
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index b67881b14f4..b987adc8bae 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
-import FileTree from '~/vue_shared/components/file_tree.vue';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { WEBIDE_MARK_FILE_CLICKED } from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
+import FileTree from '~/vue_shared/components/file_tree.vue';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index 7f07a5dbe43..8e611503cb4 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -1,11 +1,11 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapActions, mapState } from 'vuex';
-import { throttle } from 'lodash';
import { GlTooltipDirective, GlButton, GlIcon } from '@gitlab/ui';
+import { throttle } from 'lodash';
+import { mapActions, mapState } from 'vuex';
import { __ } from '../../../locale';
-import ScrollButton from './detail/scroll_button.vue';
import JobDescription from './detail/description.vue';
+import ScrollButton from './detail/scroll_button.vue';
const scrollPositions = {
top: 0,
diff --git a/app/assets/javascripts/ide/components/jobs/list.vue b/app/assets/javascripts/ide/components/jobs/list.vue
index 4e0912f3f44..0ce21c5c36c 100644
--- a/app/assets/javascripts/ide/components/jobs/list.vue
+++ b/app/assets/javascripts/ide/components/jobs/list.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import Stage from './stage.vue';
export default {
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index 4b3c6e61e11..680e8841a1f 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -1,10 +1,10 @@
<script>
-import { mapActions, mapState } from 'vuex';
-import { debounce } from 'lodash';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
-import Item from './item.vue';
import TokenedInput from '../shared/tokened_input.vue';
+import Item from './item.vue';
const SEARCH_TYPES = [
{ type: 'created', label: __('Created by me') },
diff --git a/app/assets/javascripts/ide/components/nav_dropdown.vue b/app/assets/javascripts/ide/components/nav_dropdown.vue
index 6ff77e556c0..f5f0db3a7a3 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown.vue
@@ -1,8 +1,8 @@
<script>
import $ from 'jquery';
import { mapGetters } from 'vuex';
-import NavForm from './nav_form.vue';
import NavDropdownButton from './nav_dropdown_button.vue';
+import NavForm from './nav_form.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/nav_dropdown_button.vue b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
index 116d3cec03e..0db43123562 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown_button.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlIcon } from '@gitlab/ui';
+import { mapState } from 'vuex';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
const EMPTY_LABEL = '-';
diff --git a/app/assets/javascripts/ide/components/nav_form.vue b/app/assets/javascripts/ide/components/nav_form.vue
index 70a92b8d3ab..62bb4841760 100644
--- a/app/assets/javascripts/ide/components/nav_form.vue
+++ b/app/assets/javascripts/ide/components/nav_form.vue
@@ -1,6 +1,6 @@
<script>
-import Tabs from '~/vue_shared/components/tabs/tabs';
import Tab from '~/vue_shared/components/tabs/tab.vue';
+import Tabs from '~/vue_shared/components/tabs/tabs';
import BranchesSearchList from './branches/search_list.vue';
import MergeRequestSearchList from './merge_requests/list.vue';
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index 692878de5e1..bdd201aac1b 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -1,10 +1,10 @@
<script>
-import { mapActions } from 'vuex';
import { GlIcon } from '@gitlab/ui';
-import upload from './upload.vue';
-import ItemButton from './button.vue';
+import { mapActions } from 'vuex';
import { modalTypes } from '../../constants';
+import ItemButton from './button.vue';
import NewModal from './modal.vue';
+import upload from './upload.vue';
export default {
components: {
@@ -108,6 +108,7 @@ export default {
class="d-flex"
icon="remove"
icon-classes="mr-2"
+ data-qa-selector="delete_button"
@click="deleteEntry(path)"
/>
</li>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 22eefb6634f..cafb58b0e2c 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState, mapGetters } from 'vuex';
import { GlModal, GlButton } from '@gitlab/ui';
+import { mapActions, mapState, mapGetters } from 'vuex';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __, sprintf, s__ } from '~/locale';
import { modalTypes } from '../../constants';
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index 5704129c10f..76d8a0aff3d 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -1,6 +1,6 @@
<script>
-import ItemButton from './button.vue';
import { isTextFile } from '~/ide/utils';
+import ItemButton from './button.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue
index 46ef08a45a9..da2d4fbe7f0 100644
--- a/app/assets/javascripts/ide/components/panes/right.vue
+++ b/app/assets/javascripts/ide/components/panes/right.vue
@@ -1,13 +1,13 @@
<script>
import { mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
-import CollapsibleSidebar from './collapsible_sidebar.vue';
-import ResizablePanel from '../resizable_panel.vue';
import { rightSidebarViews, SIDEBAR_INIT_WIDTH, SIDEBAR_NAV_WIDTH } from '../../constants';
-import PipelinesList from '../pipelines/list.vue';
import JobsDetail from '../jobs/detail.vue';
+import PipelinesList from '../pipelines/list.vue';
import Clientside from '../preview/clientside.vue';
+import ResizablePanel from '../resizable_panel.vue';
import TerminalView from '../terminal/view.vue';
+import CollapsibleSidebar from './collapsible_sidebar.vue';
// Need to add the width of the nav buttons since the resizable container contains those as well
const WIDTH = SIDEBAR_INIT_WIDTH + SIDEBAR_NAV_WIDTH;
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index a4a13389fbf..2526db0cd7b 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,6 +1,4 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
-import { escape } from 'lodash';
import {
GlLoadingIcon,
GlIcon,
@@ -10,13 +8,14 @@ import {
GlBadge,
GlAlert,
} from '@gitlab/ui';
+import { escape } from 'lodash';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import IDEServices from '~/ide/services';
import { sprintf, __ } from '../../../locale';
-import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import EmptyState from '../../../pipelines/components/pipelines_list/empty_state.vue';
+import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import JobsList from '../jobs/list.vue';
-import IDEServices from '~/ide/services';
-
export default {
components: {
GlIcon,
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index 4c2a369226e..13f2e775fc3 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -1,13 +1,13 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { listen } from 'codesandbox-api';
import { isEmpty, debounce } from 'lodash';
import { Manager } from 'smooshpack';
-import { listen } from 'codesandbox-api';
-import { GlLoadingIcon } from '@gitlab/ui';
-import Navigator from './navigator.vue';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { packageJsonPath, LIVE_PREVIEW_DEBOUNCE } from '../../constants';
-import { createPathWithExt } from '../../utils';
import eventHub from '../../eventhub';
+import { createPathWithExt } from '../../utils';
+import Navigator from './navigator.vue';
export default {
components: {
@@ -165,7 +165,7 @@ export default {
</p>
<a
:href="links.webIDEHelpPagePath"
- class="btn btn-primary"
+ class="btn gl-button btn-confirm"
target="_blank"
rel="noopener noreferrer"
>
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 8986359427f..0c6cb041095 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -1,6 +1,6 @@
<script>
-import { listen } from 'codesandbox-api';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { listen } from 'codesandbox-api';
export default {
components: {
@@ -78,6 +78,7 @@ export default {
this.visitPath(this.path);
},
visitPath(path) {
+ // eslint-disable-next-line vue/no-mutating-props
this.manager.iframe.src = `${this.manager.bundlerURL}${path}`;
},
},
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 8092ef3bce6..854ff74d0af 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -1,8 +1,8 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
-import CommitFilesList from './commit_sidebar/list.vue';
-import EmptyState from './commit_sidebar/empty_state.vue';
import { stageKeys } from '../constants';
+import EmptyState from './commit_sidebar/empty_state.vue';
+import CommitFilesList from './commit_sidebar/list.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index a9c05f2e1ac..690060f5cb0 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -1,9 +1,7 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
-import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
-import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
+import { __ } from '~/locale';
import {
WEBIDE_MARK_FILE_CLICKED,
WEBIDE_MARK_REPO_EDITOR_START,
@@ -12,21 +10,23 @@ import {
WEBIDE_MEASURE_FILE_AFTER_INTERACTION,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
-import eventHub from '../eventhub';
+import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
+import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
+import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import {
leftSidebarViews,
viewerTypes,
FILE_VIEW_MODE_EDITOR,
FILE_VIEW_MODE_PREVIEW,
} from '../constants';
+import eventHub from '../eventhub';
import Editor from '../lib/editor';
-import FileTemplatesBar from './file_templates/bar.vue';
-import { __ } from '~/locale';
-import { extractMarkdownImagesFromEntries } from '../stores/utils';
-import { getFileEditorOrDefault } from '../stores/modules/editor/utils';
-import { getPathParent, readFileAsDataURL, registerSchema, isTextFile } from '../utils';
import { getRulesWithTraversal } from '../lib/editorconfig/parser';
import mapRulesToMonaco from '../lib/editorconfig/rules_mapper';
+import { getFileEditorOrDefault } from '../stores/modules/editor/utils';
+import { extractMarkdownImagesFromEntries } from '../stores/utils';
+import { getPathParent, readFileAsDataURL, registerSchema, isTextFile } from '../utils';
+import FileTemplatesBar from './file_templates/bar.vue';
export default {
name: 'RepoEditor',
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index e3c41eee15e..d28751c9571 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -1,10 +1,10 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
import { GlIcon } from '@gitlab/ui';
+import { mapActions, mapGetters } from 'vuex';
import { __, sprintf } from '~/locale';
-import FileIcon from '~/vue_shared/components/file_icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
import FileStatusIcon from './repo_file_status_icon.vue';
export default {
diff --git a/app/assets/javascripts/ide/components/terminal/session.vue b/app/assets/javascripts/ide/components/terminal/session.vue
index 0e67a2ab45f..3a4128b6207 100644
--- a/app/assets/javascripts/ide/components/terminal/session.vue
+++ b/app/assets/javascripts/ide/components/terminal/session.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
-import Terminal from './terminal.vue';
import { isEndingStatus } from '../../stores/modules/terminal/utils';
+import Terminal from './terminal.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/terminal/terminal.vue b/app/assets/javascripts/ide/components/terminal/terminal.vue
index 0ee4107f9ab..08fb2f5e5a0 100644
--- a/app/assets/javascripts/ide/components/terminal/terminal.vue
+++ b/app/assets/javascripts/ide/components/terminal/terminal.vue
@@ -1,11 +1,11 @@
<script>
-import { mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mapState } from 'vuex';
import { __ } from '~/locale';
import GLTerminal from '~/terminal/terminal';
-import TerminalControls from './terminal_controls.vue';
import { RUNNING, STOPPING } from '../../stores/modules/terminal/constants';
import { isStartingStatus } from '../../stores/modules/terminal/utils';
+import TerminalControls from './terminal_controls.vue';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue b/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
index c3f722d6052..67692c842b8 100644
--- a/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
+++ b/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
@@ -1,6 +1,6 @@
<script>
-import { throttle } from 'lodash';
import { GlTooltipDirective, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { throttle } from 'lodash';
import { mapState } from 'vuex';
import {
MSG_TERMINAL_SYNC_CONNECTING,
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index e5618466395..ed6b750480b 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -16,6 +16,13 @@ export const PERMISSION_CREATE_MR = 'createMergeRequestIn';
export const PERMISSION_READ_MR = 'readMergeRequest';
export const PERMISSION_PUSH_CODE = 'pushCode';
+// The default permission object to use when the project data isn't available yet.
+// This helps us encapsulate checks like `canPushCode` without requiring an
+// additional check like `currentProject && canPushCode`.
+export const DEFAULT_PERMISSIONS = {
+ [PERMISSION_PUSH_CODE]: true,
+};
+
export const viewerTypes = {
mr: 'mrdiff',
edit: 'editor',
@@ -100,3 +107,7 @@ export const SIDE_RIGHT = 'right';
// Live Preview feature
export const LIVE_PREVIEW_DEBOUNCE = 2000;
+
+// This is the maximum number of files to auto open when opening the Web IDE
+// from a Merge Request
+export const MAX_MR_FILES_AUTO_OPEN = 10;
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 0e6775d87f1..cb59cd7a8df 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -1,14 +1,14 @@
import Vue from 'vue';
+import { deprecatedCreateFlash as flash } from '~/flash';
import IdeRouter from '~/ide/ide_router_extension';
import { joinPaths } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
-import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_PROJECT_DATA_START,
WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
WEBIDE_MEASURE_FETCH_PROJECT_DATA,
} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import { syncRouterAndStore } from './sync_router_and_store';
Vue.use(IdeRouter);
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index af408c06556..1b4b59ef62f 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -1,14 +1,14 @@
+import { identity } from 'lodash';
import Vue from 'vue';
import { mapActions } from 'vuex';
-import { identity } from 'lodash';
-import Translate from '~/vue_shared/translate';
import PerformancePlugin from '~/performance/vue_performance_plugin';
-import ide from './components/ide.vue';
-import { createStore } from './stores';
-import { createRouter } from './ide_router';
+import Translate from '~/vue_shared/translate';
import { parseBoolean } from '../lib/utils/common_utils';
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
+import ide from './components/ide.vue';
+import { createRouter } from './ide_router';
import { DEFAULT_THEME } from './lib/themes';
+import { createStore } from './stores';
Vue.use(Translate);
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 4969875439e..46128651547 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -1,9 +1,9 @@
import { editor as monacoEditor, Uri } from 'monaco-editor';
-import Disposable from './disposable';
+import { insertFinalNewline } from '~/lib/utils/text_utility';
import eventHub from '../../eventhub';
import { trimTrailingWhitespace } from '../../utils';
-import { insertFinalNewline } from '~/lib/utils/text_utility';
import { defaultModelOptions } from '../editor_options';
+import Disposable from './disposable';
export default class Model {
constructor(file, head = null) {
diff --git a/app/assets/javascripts/ide/lib/create_diff.js b/app/assets/javascripts/ide/lib/create_diff.js
index 51d4967fb23..17779b6314e 100644
--- a/app/assets/javascripts/ide/lib/create_diff.js
+++ b/app/assets/javascripts/ide/lib/create_diff.js
@@ -1,5 +1,5 @@
-import { commitActionForFile } from '~/ide/stores/utils';
import { commitActionTypes } from '~/ide/constants';
+import { commitActionForFile } from '~/ide/stores/utils';
import createFileDiff from './create_file_diff';
const getDeletedParents = (entries, file) => {
diff --git a/app/assets/javascripts/ide/lib/diff/controller.js b/app/assets/javascripts/ide/lib/diff/controller.js
index 3efe692be13..1d051062637 100644
--- a/app/assets/javascripts/ide/lib/diff/controller.js
+++ b/app/assets/javascripts/ide/lib/diff/controller.js
@@ -1,7 +1,7 @@
-import { Range } from 'monaco-editor';
import { throttle } from 'lodash';
-import DirtyDiffWorker from './diff_worker';
+import { Range } from 'monaco-editor';
import Disposable from '../common/disposable';
+import DirtyDiffWorker from './diff_worker';
export const getDiffChangeType = (change) => {
if (change.modified) {
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index 4fad0c09ce7..80191f635a3 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -1,15 +1,15 @@
import { debounce } from 'lodash';
import { editor as monacoEditor, KeyCode, KeyMod, Range } from 'monaco-editor';
-import DecorationsController from './decorations/controller';
-import DirtyDiffController from './diff/controller';
+import { clearDomElement } from '~/editor/utils';
+import { registerLanguages } from '../utils';
import Disposable from './common/disposable';
import ModelManager from './common/model_manager';
+import DecorationsController from './decorations/controller';
+import DirtyDiffController from './diff/controller';
import { editorOptions, defaultEditorOptions, defaultDiffEditorOptions } from './editor_options';
-import { themes } from './themes';
-import languages from './languages';
import keymap from './keymap.json';
-import { clearDomElement } from '~/editor/utils';
-import { registerLanguages } from '../utils';
+import languages from './languages';
+import { themes } from './themes';
function setupThemes() {
themes.forEach((theme) => {
diff --git a/app/assets/javascripts/ide/lib/errors.js b/app/assets/javascripts/ide/lib/errors.js
index f975034a872..a8a048e588f 100644
--- a/app/assets/javascripts/ide/lib/errors.js
+++ b/app/assets/javascripts/ide/lib/errors.js
@@ -1,6 +1,6 @@
import { escape } from 'lodash';
import { __ } from '~/locale';
-import consts from '../stores/modules/commit/constants';
+import { COMMIT_TO_NEW_BRANCH } from '../stores/modules/commit/constants';
const CODEOWNERS_REGEX = /Push.*protected branches.*CODEOWNERS/;
const BRANCH_CHANGED_REGEX = /changed.*since.*start.*edit/;
@@ -8,7 +8,7 @@ const BRANCH_ALREADY_EXISTS = /branch.*already.*exists/;
const createNewBranchAndCommit = (store) =>
store
- .dispatch('commit/updateCommitAction', consts.COMMIT_TO_NEW_BRANCH)
+ .dispatch('commit/updateCommitAction', COMMIT_TO_NEW_BRANCH)
.then(() => store.dispatch('commit/commitChanges'));
export const createUnexpectedCommitError = (message) => ({
diff --git a/app/assets/javascripts/ide/lib/languages/index.js b/app/assets/javascripts/ide/lib/languages/index.js
index 580ad820bf9..f758cb7dd86 100644
--- a/app/assets/javascripts/ide/lib/languages/index.js
+++ b/app/assets/javascripts/ide/lib/languages/index.js
@@ -1,5 +1,5 @@
-import vue from './vue';
import hcl from './hcl';
+import vue from './vue';
const languages = [vue, hcl];
diff --git a/app/assets/javascripts/ide/lib/mirror.js b/app/assets/javascripts/ide/lib/mirror.js
index 6f9cfec9465..78990953beb 100644
--- a/app/assets/javascripts/ide/lib/mirror.js
+++ b/app/assets/javascripts/ide/lib/mirror.js
@@ -1,6 +1,6 @@
-import createDiff from './create_diff';
import { getWebSocketUrl, mergeUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
+import createDiff from './create_diff';
export const SERVICE_NAME = 'webide-file-sync';
export const PROTOCOL = 'webfilesync.gitlab.com';
diff --git a/app/assets/javascripts/ide/lib/themes/index.js b/app/assets/javascripts/ide/lib/themes/index.js
index bb5be50576c..6a3feb9cab6 100644
--- a/app/assets/javascripts/ide/lib/themes/index.js
+++ b/app/assets/javascripts/ide/lib/themes/index.js
@@ -1,9 +1,9 @@
-import white from './white';
import dark from './dark';
import monokai from './monokai';
-import solarizedLight from './solarized_light';
-import solarizedDark from './solarized_dark';
import none from './none';
+import solarizedDark from './solarized_dark';
+import solarizedLight from './solarized_light';
+import white from './white';
export const themes = [
{
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index 2264d63c737..e98653aedc2 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -1,6 +1,6 @@
+import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
-import Api from '~/api';
import getUserPermissions from '../queries/getUserPermissions.query.graphql';
import { query } from './gql';
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index d62dfc35d15..bf94f9d31c8 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -1,19 +1,19 @@
-import Vue from 'vue';
import { escape } from 'lodash';
-import { __, sprintf } from '~/locale';
-import { visitUrl } from '~/lib/utils/url_utility';
+import Vue from 'vue';
import { deprecatedCreateFlash as flash } from '~/flash';
-import { performanceMarkAndMeasure } from '~/performance/utils';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { __, sprintf } from '~/locale';
import {
WEBIDE_MARK_FETCH_BRANCH_DATA_START,
WEBIDE_MARK_FETCH_BRANCH_DATA_FINISH,
WEBIDE_MEASURE_FETCH_BRANCH_DATA,
} from '~/performance/constants';
-import * as types from './mutation_types';
-import { decorateFiles } from '../lib/files';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import { stageKeys, commitActionTypes } from '../constants';
-import service from '../services';
import eventHub from '../eventhub';
+import { decorateFiles } from '../lib/files';
+import service from '../services';
+import * as types from './mutation_types';
export const redirectToUrl = (self, url) => visitUrl(url);
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 42668dec63a..d1e40920ebc 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -1,16 +1,16 @@
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_FILE_DATA_START,
WEBIDE_MARK_FETCH_FILE_DATA_FINISH,
WEBIDE_MEASURE_FETCH_FILE_DATA,
} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
+import { viewerTypes, stageKeys, commitActionTypes } from '../../constants';
import eventHub from '../../eventhub';
import service from '../../services';
import * as types from '../mutation_types';
import { setPageTitleForFile } from '../utils';
-import { viewerTypes, stageKeys, commitActionTypes } from '../../constants';
export const closeFile = ({ commit, state, dispatch, getters }, file) => {
const { path } = file;
@@ -120,10 +120,6 @@ export const getFileData = (
});
};
-export const setFileMrChange = ({ commit }, { file, mrChange }) => {
- commit(types.SET_FILE_MERGE_REQUEST_CHANGE, { file, mrChange });
-};
-
export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) => {
const file = state.entries[path];
const stagedFile = state.stagedFiles.find((f) => f.path === path);
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 8215cba7ccf..753f6b9cd47 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -1,8 +1,8 @@
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
+import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '../../constants';
import service from '../../services';
import * as types from '../mutation_types';
-import { leftSidebarViews, PERMISSION_READ_MR } from '../../constants';
export const getMergeRequestsForBranch = (
{ commit, state, getters },
@@ -147,70 +147,96 @@ export const getMergeRequestVersions = (
}
});
-export const openMergeRequest = (
- { dispatch, state, getters },
- { projectId, targetProjectId, mergeRequestId } = {},
-) =>
- dispatch('getMergeRequestData', {
- projectId,
- targetProjectId,
- mergeRequestId,
- })
- .then((mr) => {
- dispatch('setCurrentBranchId', mr.source_branch);
-
- return dispatch('getBranchData', {
- projectId,
- branchId: mr.source_branch,
- }).then(() => {
- const branch = getters.findBranch(projectId, mr.source_branch);
-
- return dispatch('getFiles', {
- projectId,
- branchId: mr.source_branch,
- ref: branch.commit.id,
+export const openMergeRequestChanges = async ({ dispatch, getters, state, commit }, changes) => {
+ const entryChanges = changes
+ .map((change) => ({ entry: state.entries[change.new_path], change }))
+ .filter((x) => x.entry);
+
+ const pathsToOpen = entryChanges
+ .slice(0, MAX_MR_FILES_AUTO_OPEN)
+ .map(({ change }) => change.new_path);
+
+ // If there are no changes with entries, do nothing.
+ if (!entryChanges.length) {
+ return;
+ }
+
+ dispatch('updateActivityBarView', leftSidebarViews.review.name);
+
+ entryChanges.forEach(({ change, entry }) => {
+ commit(types.SET_FILE_MERGE_REQUEST_CHANGE, { file: entry, mrChange: change });
+ });
+
+ // Open paths in order as they appear in MR changes
+ pathsToOpen.forEach((path) => {
+ commit(types.TOGGLE_FILE_OPEN, path);
+ });
+
+ // Activate first path.
+ // We don't `getFileData` here since the editor component kicks that off. Otherwise, we'd fetch twice.
+ const [firstPath, ...remainingPaths] = pathsToOpen;
+ await dispatch('router/push', getters.getUrlForPath(firstPath));
+ await dispatch('setFileActive', firstPath);
+
+ // Lastly, eagerly fetch the remaining paths for improved user experience.
+ await Promise.all(
+ remainingPaths.map(async (path) => {
+ try {
+ await dispatch('getFileData', {
+ path,
+ makeFileActive: false,
});
- });
- })
- .then(() =>
- dispatch('getMergeRequestVersions', {
- projectId,
- targetProjectId,
- mergeRequestId,
- }),
- )
- .then(() =>
- dispatch('getMergeRequestChanges', {
- projectId,
- targetProjectId,
- mergeRequestId,
- }),
- )
- .then((mrChanges) => {
- if (mrChanges.changes.length) {
- dispatch('updateActivityBarView', leftSidebarViews.review.name);
+ await dispatch('getRawFileData', { path });
+ } catch (e) {
+ // If one of the file fetches fails, we dont want to blow up the rest of them.
+ // eslint-disable-next-line no-console
+ console.error('[gitlab] An unexpected error occurred fetching MR file data', e);
}
+ }),
+ );
+};
- mrChanges.changes.forEach((change, ind) => {
- const changeTreeEntry = state.entries[change.new_path];
+export const openMergeRequest = async (
+ { dispatch, getters },
+ { projectId, targetProjectId, mergeRequestId } = {},
+) => {
+ try {
+ const mr = await dispatch('getMergeRequestData', {
+ projectId,
+ targetProjectId,
+ mergeRequestId,
+ });
- if (changeTreeEntry) {
- dispatch('setFileMrChange', {
- file: changeTreeEntry,
- mrChange: change,
- });
+ dispatch('setCurrentBranchId', mr.source_branch);
- if (ind < 10) {
- dispatch('getFileData', {
- path: change.new_path,
- makeFileActive: ind === 0,
- openFile: true,
- });
- }
- }
- });
- })
- .catch((e) => {
- flash(__('Error while loading the merge request. Please try again.'));
- throw e;
+ await dispatch('getBranchData', {
+ projectId,
+ branchId: mr.source_branch,
+ });
+
+ const branch = getters.findBranch(projectId, mr.source_branch);
+
+ await dispatch('getFiles', {
+ projectId,
+ branchId: mr.source_branch,
+ ref: branch.commit.id,
});
+
+ await dispatch('getMergeRequestVersions', {
+ projectId,
+ targetProjectId,
+ mergeRequestId,
+ });
+
+ const { changes } = await dispatch('getMergeRequestChanges', {
+ projectId,
+ targetProjectId,
+ mergeRequestId,
+ });
+
+ await dispatch('openMergeRequestChanges', changes);
+ } catch (e) {
+ flash(__('Error while loading the merge request. Please try again.'));
+ throw e;
+ }
+};
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 27f6848f1d6..120a577d44a 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -1,8 +1,8 @@
import { escape } from 'lodash';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __, sprintf } from '~/locale';
-import service from '../../services';
import api from '../../../api';
+import service from '../../services';
import * as types from '../mutation_types';
export const getProjectData = ({ commit, state }, { namespace, projectId, force = false } = {}) =>
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 150dfcb2726..f46d3cbe946 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -1,14 +1,14 @@
import { defer } from 'lodash';
-import { performanceMarkAndMeasure } from '~/performance/utils';
import {
WEBIDE_MARK_FETCH_FILES_FINISH,
WEBIDE_MEASURE_FETCH_FILES,
WEBIDE_MARK_FETCH_FILES_START,
} from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import { __ } from '../../../locale';
+import { decorateFiles } from '../../lib/files';
import service from '../../services';
import * as types from '../mutation_types';
-import { decorateFiles } from '../../lib/files';
export const toggleTreeOpen = ({ commit }, path) => {
commit(types.TOGGLE_TREE_OPEN, path);
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 59e8d37a92a..9b93fc74f76 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -1,13 +1,14 @@
-import { getChangesCountForFiles, filePathMatches } from './utils';
+import Api from '~/api';
+import { addNumericSuffix } from '~/ide/utils';
import {
leftSidebarViews,
packageJsonPath,
+ DEFAULT_PERMISSIONS,
PERMISSION_READ_MR,
PERMISSION_CREATE_MR,
PERMISSION_PUSH_CODE,
} from '../constants';
-import { addNumericSuffix } from '~/ide/utils';
-import Api from '~/api';
+import { getChangesCountForFiles, filePathMatches } from './utils';
export const activeFile = (state) => state.openFiles.find((file) => file.active) || null;
@@ -150,7 +151,7 @@ export const getDiffInfo = (state, getters) => (path) => {
};
export const findProjectPermissions = (state, getters) => (projectId) =>
- getters.findProject(projectId)?.userPermissions || {};
+ getters.findProject(projectId)?.userPermissions || DEFAULT_PERMISSIONS;
export const canReadMergeRequests = (state, getters) =>
Boolean(getters.findProjectPermissions(state.currentProjectId)[PERMISSION_READ_MR]);
diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js
index d543209716a..b660ff178a2 100644
--- a/app/assets/javascripts/ide/stores/index.js
+++ b/app/assets/javascripts/ide/stores/index.js
@@ -1,19 +1,19 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from './state';
import * as actions from './actions';
import * as getters from './getters';
-import mutations from './mutations';
-import commitModule from './modules/commit';
-import pipelines from './modules/pipelines';
-import mergeRequests from './modules/merge_requests';
import branches from './modules/branches';
-import fileTemplates from './modules/file_templates';
-import paneModule from './modules/pane';
import clientsideModule from './modules/clientside';
-import routerModule from './modules/router';
+import commitModule from './modules/commit';
import editorModule from './modules/editor';
import { setupFileEditorsSync } from './modules/editor/setup';
+import fileTemplates from './modules/file_templates';
+import mergeRequests from './modules/merge_requests';
+import paneModule from './modules/pane';
+import pipelines from './modules/pipelines';
+import routerModule from './modules/router';
+import mutations from './mutations';
+import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/ide/stores/modules/branches/actions.js b/app/assets/javascripts/ide/stores/modules/branches/actions.js
index 74a4cd9848b..57a63749d7c 100644
--- a/app/assets/javascripts/ide/stores/modules/branches/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/branches/actions.js
@@ -1,5 +1,5 @@
-import { __ } from '~/locale';
import Api from '~/api';
+import { __ } from '~/locale';
import * as types from './mutation_types';
export const requestBranches = ({ commit }) => commit(types.REQUEST_BRANCHES);
diff --git a/app/assets/javascripts/ide/stores/modules/branches/index.js b/app/assets/javascripts/ide/stores/modules/branches/index.js
index deda95cd0c9..4b7d6d2998b 100644
--- a/app/assets/javascripts/ide/stores/modules/branches/index.js
+++ b/app/assets/javascripts/ide/stores/modules/branches/index.js
@@ -1,6 +1,6 @@
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 29b9a8a9521..29555799074 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -1,14 +1,14 @@
-import { sprintf, __ } from '~/locale';
import { deprecatedCreateFlash as flash } from '~/flash';
-import * as rootTypes from '../../mutation_types';
-import { createCommitPayload, createNewMergeRequestUrl } from '../../utils';
-import service from '../../../services';
-import * as types from './mutation_types';
-import consts from './constants';
+import { addNumericSuffix } from '~/ide/utils';
+import { sprintf, __ } from '~/locale';
import { leftSidebarViews } from '../../../constants';
import eventHub from '../../../eventhub';
import { parseCommitError } from '../../../lib/errors';
-import { addNumericSuffix } from '~/ide/utils';
+import service from '../../../services';
+import * as rootTypes from '../../mutation_types';
+import { createCommitPayload, createNewMergeRequestUrl } from '../../utils';
+import { COMMIT_TO_CURRENT_BRANCH } from './constants';
+import * as types from './mutation_types';
export const updateCommitMessage = ({ commit }, message) => {
commit(types.UPDATE_COMMIT_MESSAGE, message);
@@ -112,7 +112,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
// Pull commit options out because they could change
// During some of the pre and post commit processing
const { shouldCreateMR, shouldHideNewMrOption, isCreatingNewBranch, branchName } = getters;
- const newBranch = state.commitAction !== consts.COMMIT_TO_CURRENT_BRANCH;
+ const newBranch = state.commitAction !== COMMIT_TO_CURRENT_BRANCH;
const stageFilesPromise = rootState.stagedFiles.length
? Promise.resolve()
: dispatch('stageAllChanges', null, { root: true });
@@ -206,7 +206,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
dispatch('updateViewer', 'editor', { root: true });
}
})
- .then(() => dispatch('updateCommitAction', consts.COMMIT_TO_CURRENT_BRANCH))
+ .then(() => dispatch('updateCommitAction', COMMIT_TO_CURRENT_BRANCH))
.then(() => {
if (newBranch) {
const path = rootGetters.activeFile ? rootGetters.activeFile.path : '';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/constants.js b/app/assets/javascripts/ide/stores/modules/commit/constants.js
index c6c3701effe..9f4299e5537 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/constants.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/constants.js
@@ -1,7 +1,2 @@
-const COMMIT_TO_CURRENT_BRANCH = '1';
-const COMMIT_TO_NEW_BRANCH = '2';
-
-export default {
- COMMIT_TO_CURRENT_BRANCH,
- COMMIT_TO_NEW_BRANCH,
-};
+export const COMMIT_TO_CURRENT_BRANCH = '1';
+export const COMMIT_TO_NEW_BRANCH = '2';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
index 2301cf23f9f..f5e367e16f5 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -1,5 +1,5 @@
import { sprintf, n__, __ } from '../../../../locale';
-import consts from './constants';
+import { COMMIT_TO_NEW_BRANCH } from './constants';
const BRANCH_SUFFIX_COUNT = 5;
const createTranslatedTextForFiles = (files, text) => {
@@ -48,7 +48,7 @@ export const preBuiltCommitMessage = (state, _, rootState) => {
.join('\n');
};
-export const isCreatingNewBranch = (state) => state.commitAction === consts.COMMIT_TO_NEW_BRANCH;
+export const isCreatingNewBranch = (state) => state.commitAction === COMMIT_TO_NEW_BRANCH;
export const shouldHideNewMrOption = (_state, getters, _rootState, rootGetters) =>
!getters.isCreatingNewBranch &&
diff --git a/app/assets/javascripts/ide/stores/modules/commit/index.js b/app/assets/javascripts/ide/stores/modules/commit/index.js
index 5cec73bde2e..c5a39249348 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/index.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/index.js
@@ -1,7 +1,7 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/editor/index.js b/app/assets/javascripts/ide/stores/modules/editor/index.js
index 8a7437b427d..b601f0e79d4 100644
--- a/app/assets/javascripts/ide/stores/modules/editor/index.js
+++ b/app/assets/javascripts/ide/stores/modules/editor/index.js
@@ -1,7 +1,7 @@
import * as actions from './actions';
import * as getters from './getters';
-import state from './state';
import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/editor/setup.js b/app/assets/javascripts/ide/stores/modules/editor/setup.js
index 9f3163aa6f5..5899706e38a 100644
--- a/app/assets/javascripts/ide/stores/modules/editor/setup.js
+++ b/app/assets/javascripts/ide/stores/modules/editor/setup.js
@@ -1,5 +1,5 @@
-import eventHub from '~/ide/eventhub';
import { commitActionTypes } from '~/ide/constants';
+import eventHub from '~/ide/eventhub';
const removeUnusedFileEditors = (store) => {
Object.keys(store.state.editor.fileEditors)
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
index 6800f824da0..bc96ec267b5 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
@@ -1,8 +1,8 @@
import Api from '~/api';
-import { __ } from '~/locale';
import { normalizeHeaders } from '~/lib/utils/common_utils';
-import * as types from './mutation_types';
+import { __ } from '~/locale';
import eventHub from '../../../eventhub';
+import * as types from './mutation_types';
export const requestTemplateTypes = ({ commit }) => commit(types.REQUEST_TEMPLATE_TYPES);
export const receiveTemplateTypesError = ({ commit, dispatch }) => {
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
index 0613fe9b12b..9708e5e588c 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js
@@ -1,5 +1,5 @@
-import { leftSidebarViews } from '../../../constants';
import { __ } from '~/locale';
+import { leftSidebarViews } from '../../../constants';
export const templateTypes = () => [
{
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/index.js b/app/assets/javascripts/ide/stores/modules/file_templates/index.js
index 383ff5db392..5f850b8b86a 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/index.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/index.js
@@ -1,7 +1,7 @@
-import createState from './state';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
+import createState from './state';
export default () => ({
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
index 299f7a883d2..8446b93d14a 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
@@ -1,5 +1,5 @@
-import { __ } from '../../../../locale';
import Api from '../../../../api';
+import { __ } from '../../../../locale';
import { scopes } from './constants';
import * as types from './mutation_types';
diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/index.js b/app/assets/javascripts/ide/stores/modules/merge_requests/index.js
index 04e7e0f08f1..d858a855d9e 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/index.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/index.js
@@ -1,6 +1,6 @@
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
index 2c2034d76d0..60561292c9d 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -1,10 +1,10 @@
-import Visibility from 'visibilityjs';
import axios from 'axios';
+import Visibility from 'visibilityjs';
import httpStatus from '../../../../lib/utils/http_status';
-import { __ } from '../../../../locale';
import Poll from '../../../../lib/utils/poll';
-import service from '../../../services';
+import { __ } from '../../../../locale';
import { rightSidebarViews } from '../../../constants';
+import service from '../../../services';
import * as types from './mutation_types';
let eTagPoll;
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/index.js b/app/assets/javascripts/ide/stores/modules/pipelines/index.js
index b44c3141b81..b48f63887ca 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/index.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/index.js
@@ -1,7 +1,7 @@
-import state from './state';
import * as actions from './actions';
-import mutations from './mutations';
import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/router/index.js b/app/assets/javascripts/ide/stores/modules/router/index.js
index 68c81bb4509..1d5af1d4fe5 100644
--- a/app/assets/javascripts/ide/stores/modules/router/index.js
+++ b/app/assets/javascripts/ide/stores/modules/router/index.js
@@ -1,6 +1,6 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
index b2c1ddd877c..91645a34a3d 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/checks.js
@@ -1,9 +1,9 @@
import Api from '~/api';
import httpStatus from '~/lib/utils/http_status';
-import * as types from '../mutation_types';
-import * as messages from '../messages';
-import { CHECK_CONFIG, CHECK_RUNNERS, RETRY_RUNNERS_INTERVAL } from '../constants';
import * as terminalService from '../../../../services/terminals';
+import { CHECK_CONFIG, CHECK_RUNNERS, RETRY_RUNNERS_INTERVAL } from '../constants';
+import * as messages from '../messages';
+import * as types from '../mutation_types';
export const requestConfigCheck = ({ commit }) => {
commit(types.REQUEST_CHECK, CHECK_CONFIG);
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
index aa460859b4c..6c9be6d10c9 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_controls.js
@@ -1,10 +1,10 @@
+import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
-import { deprecatedCreateFlash as flash } from '~/flash';
-import * as types from '../mutation_types';
-import * as messages from '../messages';
import * as terminalService from '../../../../services/terminals';
import { STARTING, STOPPING, STOPPED } from '../constants';
+import * as messages from '../messages';
+import * as types from '../mutation_types';
export const requestStartSession = ({ commit }) => {
commit(types.SET_SESSION_STATUS, STARTING);
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
index 3ab1817e662..da10894c2c6 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/actions/session_status.js
@@ -1,7 +1,7 @@
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
-import * as types from '../mutation_types';
+import axios from '~/lib/utils/axios_utils';
import * as messages from '../messages';
+import * as types from '../mutation_types';
import { isEndingStatus } from '../utils';
export const pollSessionStatus = ({ state, dispatch, commit }) => {
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/messages.js b/app/assets/javascripts/ide/stores/modules/terminal/messages.js
index 967ba80cd2c..ec05ca84754 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/messages.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/messages.js
@@ -1,6 +1,6 @@
import { escape } from 'lodash';
-import { __, sprintf } from '~/locale';
import httpStatus from '~/lib/utils/http_status';
+import { __, sprintf } from '~/locale';
export const UNEXPECTED_ERROR_CONFIG = __(
'An unexpected error occurred while checking the project environment.',
diff --git a/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js b/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
index 006800f58c2..a2cb0666a99 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal_sync/actions.js
@@ -1,5 +1,5 @@
-import * as types from './mutation_types';
import mirror, { canConnect } from '../../../lib/mirror';
+import * as types from './mutation_types';
export const upload = ({ rootState, commit }) => {
commit(types.START_LOADING);
diff --git a/app/assets/javascripts/ide/stores/modules/terminal_sync/index.js b/app/assets/javascripts/ide/stores/modules/terminal_sync/index.js
index 795c2fad724..a0685293839 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal_sync/index.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal_sync/index.js
@@ -1,6 +1,6 @@
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default () => ({
namespaced: true,
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 6ed6798a5b6..576f861a090 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
import * as types from './mutation_types';
-import projectMutations from './mutations/project';
-import mergeRequestMutation from './mutations/merge_request';
+import branchMutations from './mutations/branch';
import fileMutations from './mutations/file';
+import mergeRequestMutation from './mutations/merge_request';
+import projectMutations from './mutations/project';
import treeMutations from './mutations/tree';
-import branchMutations from './mutations/branch';
import {
sortTree,
swapInParentTreeWithSorting,
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index 4446971d5d6..fa9830a7469 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -1,7 +1,7 @@
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { diffModes } from '../../constants';
import * as types from '../mutation_types';
import { sortTree } from '../utils';
-import { diffModes } from '../../constants';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
export default {
[types.SET_FILE_ACTIVE](state, { path, active }) {
diff --git a/app/assets/javascripts/ide/stores/plugins/terminal_sync.js b/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
index d925a5f7567..944a034fe97 100644
--- a/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
+++ b/app/assets/javascripts/ide/stores/plugins/terminal_sync.js
@@ -1,8 +1,8 @@
import { debounce } from 'lodash';
-import eventHub from '~/ide/eventhub';
import { commitActionTypes } from '~/ide/constants';
-import terminalSyncModule from '../modules/terminal_sync';
+import eventHub from '~/ide/eventhub';
import { isEndingStatus, isRunningStatus } from '../modules/terminal/utils';
+import terminalSyncModule from '../modules/terminal_sync';
const UPLOAD_DEBOUNCE = 200;
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index 04eacf271b8..4019703b296 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -1,10 +1,10 @@
-import { commitActionTypes } from '../constants';
import {
relativePathToAbsolute,
isAbsolute,
isRootRelative,
isBlobUrl,
} from '~/lib/utils/url_utility';
+import { commitActionTypes } from '../constants';
export const dataStructure = () => ({
id: '',
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 8eb2d17b876..63c53737119 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -1,7 +1,7 @@
-import { languages } from 'monaco-editor';
import { flatten, isString } from 'lodash';
-import { SIDE_LEFT, SIDE_RIGHT } from './constants';
+import { languages } from 'monaco-editor';
import { performanceMarkAndMeasure } from '~/performance/utils';
+import { SIDE_LEFT, SIDE_RIGHT } from './constants';
const toLowerCase = (x) => x.toLowerCase();
diff --git a/app/assets/javascripts/image_diff/helpers/init_image_diff.js b/app/assets/javascripts/image_diff/helpers/init_image_diff.js
index 8eef930c372..51168b94e6d 100644
--- a/app/assets/javascripts/image_diff/helpers/init_image_diff.js
+++ b/app/assets/javascripts/image_diff/helpers/init_image_diff.js
@@ -1,6 +1,6 @@
+import ImageFile from '../../commit/image_file';
import ImageDiff from '../image_diff';
import ReplacedImageDiff from '../replaced_image_diff';
-import ImageFile from '../../commit/image_file';
function initImageDiff(fileEl, canCreateNote, renderCommentBadge) {
const options = {
diff --git a/app/assets/javascripts/image_diff/image_diff.js b/app/assets/javascripts/image_diff/image_diff.js
index 079f4a63f6e..a0dd8e6f894 100644
--- a/app/assets/javascripts/image_diff/image_diff.js
+++ b/app/assets/javascripts/image_diff/image_diff.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
+import { isImageLoaded } from '../lib/utils/image_utility';
import imageDiffHelper from './helpers/index';
import ImageBadge from './image_badge';
-import { isImageLoaded } from '../lib/utils/image_utility';
export default class ImageDiff {
constructor(el, options) {
diff --git a/app/assets/javascripts/image_diff/replaced_image_diff.js b/app/assets/javascripts/image_diff/replaced_image_diff.js
index 2df15e5e1a5..a3d9b8a138a 100644
--- a/app/assets/javascripts/image_diff/replaced_image_diff.js
+++ b/app/assets/javascripts/image_diff/replaced_image_diff.js
@@ -1,6 +1,6 @@
import imageDiffHelper from './helpers/index';
-import { viewTypes, isValidViewType } from './view_types';
import ImageDiff from './image_diff';
+import { viewTypes, isValidViewType } from './view_types';
export default class ReplacedImageDiff extends ImageDiff {
init(defaultViewType = viewTypes.TWO_UP) {
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
index 80e2e73f420..7c5f48dcafc 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
@@ -1,78 +1,184 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
-import bulkImportSourceGroupsQuery from '../graphql/queries/bulk_import_source_groups.query.graphql';
-import availableNamespacesQuery from '../graphql/queries/available_namespaces.query.graphql';
-import setTargetNamespaceMutation from '../graphql/mutations/set_target_namespace.mutation.graphql';
-import setNewNameMutation from '../graphql/mutations/set_new_name.mutation.graphql';
+import {
+ GlEmptyState,
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ GlSearchBoxByClick,
+ GlSprintf,
+} from '@gitlab/ui';
+import { s__ } from '~/locale';
+import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
import importGroupMutation from '../graphql/mutations/import_group.mutation.graphql';
+import setNewNameMutation from '../graphql/mutations/set_new_name.mutation.graphql';
+import setTargetNamespaceMutation from '../graphql/mutations/set_target_namespace.mutation.graphql';
+import availableNamespacesQuery from '../graphql/queries/available_namespaces.query.graphql';
+import bulkImportSourceGroupsQuery from '../graphql/queries/bulk_import_source_groups.query.graphql';
import ImportTableRow from './import_table_row.vue';
-const mapApolloMutations = (mutations) =>
- Object.fromEntries(
- Object.entries(mutations).map(([key, mutation]) => [
- key,
- function mutate(config) {
- return this.$apollo.mutate({
- mutation,
- ...config,
- });
- },
- ]),
- );
-
export default {
components: {
+ GlEmptyState,
+ GlIcon,
+ GlLink,
GlLoadingIcon,
+ GlSearchBoxByClick,
+ GlSprintf,
ImportTableRow,
+ PaginationLinks,
+ },
+
+ props: {
+ sourceUrl: {
+ type: String,
+ required: true,
+ },
+ },
+
+ data() {
+ return {
+ filter: '',
+ page: 1,
+ };
},
apollo: {
- bulkImportSourceGroups: bulkImportSourceGroupsQuery,
+ bulkImportSourceGroups: {
+ query: bulkImportSourceGroupsQuery,
+ variables() {
+ return { page: this.page, filter: this.filter };
+ },
+ },
availableNamespaces: availableNamespacesQuery,
},
+ computed: {
+ hasGroups() {
+ return this.bulkImportSourceGroups?.nodes?.length > 0;
+ },
+
+ hasEmptyFilter() {
+ return this.filter.length > 0 && !this.hasGroups;
+ },
+
+ statusMessage() {
+ return this.filter.length === 0
+ ? s__('BulkImport|Showing %{start}-%{end} of %{total} from %{link}')
+ : s__(
+ 'BulkImport|Showing %{start}-%{end} of %{total} matching filter "%{filter}" from %{link}',
+ );
+ },
+
+ paginationInfo() {
+ const { page, perPage, total } = this.bulkImportSourceGroups?.pageInfo ?? {
+ page: 1,
+ perPage: 0,
+ total: 0,
+ };
+ const start = (page - 1) * perPage + 1;
+ const end = start + (this.bulkImportSourceGroups.nodes?.length ?? 0) - 1;
+
+ return { start, end, total };
+ },
+ },
+
+ watch: {
+ filter() {
+ this.page = 1;
+ },
+ },
+
methods: {
- ...mapApolloMutations({
- setTargetNamespace: setTargetNamespaceMutation,
- setNewName: setNewNameMutation,
- importGroup: importGroupMutation,
- }),
+ setPage(page) {
+ this.page = page;
+ },
+
+ updateTargetNamespace(sourceGroupId, targetNamespace) {
+ this.$apollo.mutate({
+ mutation: setTargetNamespaceMutation,
+ variables: { sourceGroupId, targetNamespace },
+ });
+ },
+
+ updateNewName(sourceGroupId, newName) {
+ this.$apollo.mutate({
+ mutation: setNewNameMutation,
+ variables: { sourceGroupId, newName },
+ });
+ },
+
+ importGroup(sourceGroupId) {
+ this.$apollo.mutate({
+ mutation: importGroupMutation,
+ variables: { sourceGroupId },
+ });
+ },
},
};
</script>
<template>
<div>
- <gl-loading-icon v-if="$apollo.loading" size="md" class="gl-mt-5" />
- <div v-else-if="bulkImportSourceGroups.length">
- <table class="gl-w-full">
- <thead class="gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1">
- <th class="gl-py-4 import-jobs-from-col">{{ s__('BulkImport|From source group') }}</th>
- <th class="gl-py-4 import-jobs-to-col">{{ s__('BulkImport|To new group') }}</th>
- <th class="gl-py-4 import-jobs-status-col">{{ __('Status') }}</th>
- <th class="gl-py-4 import-jobs-cta-col"></th>
- </thead>
- <tbody>
- <template v-for="group in bulkImportSourceGroups">
- <import-table-row
- :key="group.id"
- :group="group"
- :available-namespaces="availableNamespaces"
- @update-target-namespace="
- setTargetNamespace({
- variables: { sourceGroupId: group.id, targetNamespace: $event },
- })
- "
- @update-new-name="
- setNewName({
- variables: { sourceGroupId: group.id, newName: $event },
- })
- "
- @import-group="importGroup({ variables: { sourceGroupId: group.id } })"
- />
+ <div
+ class="gl-py-5 gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-display-flex gl-align-items-center"
+ >
+ <span>
+ <gl-sprintf v-if="!$apollo.loading && hasGroups" :message="statusMessage">
+ <template #start>
+ <strong>{{ paginationInfo.start }}</strong>
+ </template>
+ <template #end>
+ <strong>{{ paginationInfo.end }}</strong>
</template>
- </tbody>
- </table>
+ <template #total>
+ <strong>{{ n__('%d group', '%d groups', paginationInfo.total) }}</strong>
+ </template>
+ <template #filter>
+ <strong>{{ filter }}</strong>
+ </template>
+ <template #link>
+ <gl-link class="gl-display-inline-block" :href="sourceUrl" target="_blank">
+ {{ sourceUrl }} <gl-icon name="external-link" class="vertical-align-middle" />
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ <gl-search-box-by-click class="gl-ml-auto" @submit="filter = $event" @clear="filter = ''" />
</div>
+ <gl-loading-icon v-if="$apollo.loading" size="md" class="gl-mt-5" />
+ <template v-else>
+ <gl-empty-state v-if="hasEmptyFilter" :title="__('Sorry, your filter produced no results')" />
+ <gl-empty-state
+ v-else-if="!hasGroups"
+ :title="s__('BulkImport|No groups available for import')"
+ />
+ <div v-else class="gl-display-flex gl-flex-direction-column gl-align-items-center">
+ <table class="gl-w-full">
+ <thead class="gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1">
+ <th class="gl-py-4 import-jobs-from-col">{{ s__('BulkImport|From source group') }}</th>
+ <th class="gl-py-4 import-jobs-to-col">{{ s__('BulkImport|To new group') }}</th>
+ <th class="gl-py-4 import-jobs-status-col">{{ __('Status') }}</th>
+ <th class="gl-py-4 import-jobs-cta-col"></th>
+ </thead>
+ <tbody>
+ <template v-for="group in bulkImportSourceGroups.nodes">
+ <import-table-row
+ :key="group.id"
+ :group="group"
+ :available-namespaces="availableNamespaces"
+ @update-target-namespace="updateTargetNamespace(group.id, $event)"
+ @update-new-name="updateNewName(group.id, $event)"
+ @import-group="importGroup(group.id)"
+ />
+ </template>
+ </tbody>
+ </table>
+ <pagination-links
+ :change="setPage"
+ :page-info="bulkImportSourceGroups.pageInfo"
+ class="gl-mt-3"
+ />
+ </div>
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
index 8f2d488d661..8110934efc4 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
@@ -1,15 +1,18 @@
-import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
import createDefaultClient from '~/lib/graphql';
+import axios from '~/lib/utils/axios_utils';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
-import createFlash from '~/flash';
import { STATUSES } from '../../constants';
import availableNamespacesQuery from './queries/available_namespaces.query.graphql';
import { SourceGroupsManager } from './services/source_groups_manager';
import { StatusPoller } from './services/status_poller';
export const clientTypenames = {
+ BulkImportSourceGroupConnection: 'ClientBulkImportSourceGroupConnection',
BulkImportSourceGroup: 'ClientBulkImportSourceGroup',
AvailableNamespace: 'ClientAvailableNamespace',
+ BulkImportPageInfo: 'ClientBulkImportPageInfo',
};
export function createResolvers({ endpoints }) {
@@ -17,22 +20,47 @@ export function createResolvers({ endpoints }) {
return {
Query: {
- async bulkImportSourceGroups(_, __, { client }) {
+ async bulkImportSourceGroups(_, vars, { client }) {
const {
data: { availableNamespaces },
} = await client.query({ query: availableNamespacesQuery });
- return axios.get(endpoints.status).then(({ data }) => {
- return data.importable_data.map((group) => ({
- __typename: clientTypenames.BulkImportSourceGroup,
- ...group,
- status: STATUSES.NONE,
- import_target: {
- new_name: group.full_path,
- target_namespace: availableNamespaces[0].full_path,
+ if (!statusPoller) {
+ statusPoller = new StatusPoller({
+ client,
+ pollPath: endpoints.jobs,
+ });
+ statusPoller.startPolling();
+ }
+
+ return axios
+ .get(endpoints.status, {
+ params: {
+ page: vars.page,
+ per_page: vars.perPage,
+ filter: vars.filter,
},
- }));
- });
+ })
+ .then(({ headers, data }) => {
+ const pagination = parseIntPagination(normalizeHeaders(headers));
+
+ return {
+ __typename: clientTypenames.BulkImportSourceGroupConnection,
+ nodes: data.importable_data.map((group) => ({
+ __typename: clientTypenames.BulkImportSourceGroup,
+ ...group,
+ status: STATUSES.NONE,
+ import_target: {
+ new_name: group.full_path,
+ target_namespace: availableNamespaces[0].full_path,
+ },
+ })),
+ pageInfo: {
+ __typename: clientTypenames.BulkImportPageInfo,
+ ...pagination,
+ },
+ };
+ });
},
availableNamespaces: () =>
@@ -63,7 +91,7 @@ export function createResolvers({ endpoints }) {
const group = groupManager.findById(sourceGroupId);
groupManager.setImportStatus(group, STATUSES.SCHEDULING);
try {
- await axios.post(endpoints.createBulkImport, {
+ const response = await axios.post(endpoints.createBulkImport, {
bulk_import: [
{
source_type: 'group_entity',
@@ -74,10 +102,7 @@ export function createResolvers({ endpoints }) {
],
});
groupManager.setImportStatus(group, STATUSES.STARTED);
- if (!statusPoller) {
- statusPoller = new StatusPoller({ client, interval: 3000 });
- statusPoller.startPolling();
- }
+ SourceGroupsManager.attachImportId(group, response.data.id);
} catch (e) {
createFlash({
message: s__('BulkImport|Importing the group failed'),
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql
index 8d52d94925c..28dfefdf8a7 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql
@@ -1,7 +1,15 @@
#import "../fragments/bulk_import_source_group_item.fragment.graphql"
-query bulkImportSourceGroups {
- bulkImportSourceGroups @client {
- ...BulkImportSourceGroupItem
+query bulkImportSourceGroups($page: Int = 1, $perPage: Int = 20, $filter: String = "") {
+ bulkImportSourceGroups(page: $page, filter: $filter, perPage: $perPage) @client {
+ nodes {
+ ...BulkImportSourceGroupItem
+ }
+ pageInfo {
+ page
+ perPage
+ total
+ totalPages
+ }
}
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js
index 047b04fe7d6..261e30edbbb 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js
@@ -14,6 +14,12 @@ function generateGroupId(id) {
}
export class SourceGroupsManager {
+ static importMap = new Map();
+
+ static attachImportId(group, importId) {
+ SourceGroupsManager.importMap.set(importId, group.id);
+ }
+
constructor({ client }) {
this.client = client;
}
@@ -36,6 +42,10 @@ export class SourceGroupsManager {
this.update(group, fn);
}
+ findByImportId(importId) {
+ return this.findById(SourceGroupsManager.importMap.get(importId));
+ }
+
setImportStatus(group, status) {
this.update(group, (sourceGroup) => {
// eslint-disable-next-line no-param-reassign
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
index 41dd25b9150..63cd6b48fc4 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
@@ -1,68 +1,47 @@
-import gql from 'graphql-tag';
+import Visibility from 'visibilityjs';
import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
import { s__ } from '~/locale';
-import bulkImportSourceGroupsQuery from '../queries/bulk_import_source_groups.query.graphql';
-import { STATUSES } from '../../../constants';
import { SourceGroupsManager } from './source_groups_manager';
-const groupId = (i) => `group${i}`;
-
-function generateGroupsQuery(groups) {
- return gql`{
- ${groups
- .map(
- (g, idx) =>
- `${groupId(idx)}: group(fullPath: "${g.import_target.target_namespace}/${
- g.import_target.new_name
- }") { id }`,
- )
- .join('\n')}
- }`;
-}
-
export class StatusPoller {
- constructor({ client, interval }) {
+ constructor({ client, pollPath }) {
this.client = client;
- this.interval = interval;
- this.timeoutId = null;
- this.groupManager = new SourceGroupsManager({ client });
- }
- startPolling() {
- if (this.timeoutId) {
- return;
- }
+ this.eTagPoll = new Poll({
+ resource: {
+ fetchJobs: () => axios.get(pollPath),
+ },
+ method: 'fetchJobs',
+ successCallback: ({ data }) => this.updateImportsStatuses(data),
+ errorCallback: () =>
+ createFlash({
+ message: s__('BulkImport|Update of import statuses with realtime changes failed'),
+ }),
+ });
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ this.eTagPoll.restart();
+ } else {
+ this.eTagPoll.stop();
+ }
+ });
- this.checkPendingImports();
+ this.groupManager = new SourceGroupsManager({ client });
}
- stopPolling() {
- clearTimeout(this.timeoutId);
- this.timeoutId = null;
+ startPolling() {
+ this.eTagPoll.makeRequest();
}
- async checkPendingImports() {
- try {
- const { bulkImportSourceGroups } = this.client.readQuery({
- query: bulkImportSourceGroupsQuery,
- });
- const groupsInProgress = bulkImportSourceGroups.filter((g) => g.status === STATUSES.STARTED);
- if (groupsInProgress.length) {
- const { data: results } = await this.client.query({
- query: generateGroupsQuery(groupsInProgress),
- fetchPolicy: 'no-cache',
- });
- const completedGroups = groupsInProgress.filter((_, idx) => Boolean(results[groupId(idx)]));
- completedGroups.forEach((group) => {
- this.groupManager.setImportStatus(group, STATUSES.FINISHED);
- });
+ async updateImportsStatuses(importStatuses) {
+ importStatuses.forEach(({ id, status_name: statusName }) => {
+ const group = this.groupManager.findByImportId(id);
+ if (group.id) {
+ this.groupManager.setImportStatus(group, statusName);
}
- } catch (e) {
- createFlash({
- message: s__('BulkImport|Update of import statuses with realtime changes failed'),
- });
- } finally {
- this.timeoutId = setTimeout(() => this.checkPendingImports(), this.interval);
- }
+ });
}
}
diff --git a/app/assets/javascripts/import_entities/import_groups/index.js b/app/assets/javascripts/import_entities/import_groups/index.js
index bf427075564..cd837a840e4 100644
--- a/app/assets/javascripts/import_entities/import_groups/index.js
+++ b/app/assets/javascripts/import_entities/import_groups/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import Translate from '~/vue_shared/translate';
-import { createApolloClient } from './graphql/client_factory';
import ImportTable from './components/import_table.vue';
+import { createApolloClient } from './graphql/client_factory';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -10,13 +10,20 @@ Vue.use(VueApollo);
export function mountImportGroupsApp(mountElement) {
if (!mountElement) return undefined;
- const { statusPath, availableNamespacesPath, createBulkImportPath } = mountElement.dataset;
+ const {
+ statusPath,
+ availableNamespacesPath,
+ createBulkImportPath,
+ jobsPath,
+ sourceUrl,
+ } = mountElement.dataset;
const apolloProvider = new VueApollo({
defaultClient: createApolloClient({
endpoints: {
status: statusPath,
availableNamespaces: availableNamespacesPath,
createBulkImport: createBulkImportPath,
+ jobs: jobsPath,
},
}),
});
@@ -25,7 +32,11 @@ export function mountImportGroupsApp(mountElement) {
el: mountElement,
apolloProvider,
render(createElement) {
- return createElement(ImportTable);
+ return createElement(ImportTable, {
+ props: {
+ sourceUrl,
+ },
+ });
},
});
}
diff --git a/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue b/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
index 192d6e056cd..be09052fb7e 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/import_projects_table.vue
@@ -1,6 +1,6 @@
<script>
+import { GlButton, GlLoadingIcon, GlIntersectionObserver, GlModal, GlFormInput } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { GlButton, GlLoadingIcon, GlIntersectionObserver, GlModal } from '@gitlab/ui';
import { n__, __, sprintf } from '~/locale';
import ProviderRepoTableRow from './provider_repo_table_row.vue';
@@ -12,6 +12,7 @@ export default {
GlButton,
GlModal,
GlIntersectionObserver,
+ GlFormInput,
},
props: {
providerTitle: {
@@ -115,13 +116,13 @@ export default {
<template>
<div>
- <p class="light text-nowrap mt-2">
+ <p class="gl-text-gray-900 gl-white-space-nowrap gl-mt-3">
{{ s__('ImportProjects|Select the repositories you want to import') }}
</p>
<template v-if="hasIncompatibleRepos">
<slot name="incompatible-repos-warning"></slot>
</template>
- <div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
+ <div class="gl-display-flex gl-justify-content-space-between gl-flex-wrap gl-mb-5">
<gl-button
variant="success"
:loading="isImportingAnyRepo"
@@ -148,24 +149,29 @@ export default {
<slot name="actions"></slot>
<form v-if="filterable" class="gl-ml-auto" novalidate @submit.prevent>
- <input
+ <gl-form-input
data-qa-selector="githubish_import_filter_field"
- class="form-control"
name="filter"
:placeholder="__('Filter your repositories by name')"
autofocus
- size="40"
+ size="lg"
@keyup.enter="setFilter($event.target.value)"
/>
</form>
</div>
- <div v-if="repositories.length" class="table-responsive">
- <table class="table import-table">
- <thead>
- <th class="import-jobs-from-col">{{ fromHeaderText }}</th>
- <th class="import-jobs-to-col">{{ __('To GitLab') }}</th>
- <th class="import-jobs-status-col">{{ __('Status') }}</th>
- <th class="import-jobs-cta-col"></th>
+ <div v-if="repositories.length" class="gl-w-full">
+ <table>
+ <thead class="gl-border-0 gl-border-solid gl-border-t-1 gl-border-gray-100">
+ <th class="import-jobs-from-col gl-p-4 gl-vertical-align-top gl-border-b-1">
+ {{ fromHeaderText }}
+ </th>
+ <th class="import-jobs-to-col gl-p-4 gl-vertical-align-top gl-border-b-1">
+ {{ __('To GitLab') }}
+ </th>
+ <th class="import-jobs-status-col gl-p-4 gl-vertical-align-top gl-border-b-1">
+ {{ __('Status') }}
+ </th>
+ <th class="import-jobs-cta-col gl-p-4 gl-vertical-align-top gl-border-b-1"></th>
</thead>
<tbody>
<template v-for="repo in repositories">
@@ -183,9 +189,9 @@ export default {
:key="pagePaginationStateKey"
@appear="fetchRepos"
/>
- <gl-loading-icon v-if="isLoading" class="import-projects-loading-icon" size="md" />
+ <gl-loading-icon v-if="isLoading" class="gl-mt-7" size="md" />
- <div v-if="!isLoading && repositories.length === 0" class="text-center">
+ <div v-if="!isLoading && repositories.length === 0" class="gl-text-center">
<strong>{{ emptyStateText }}</strong>
</div>
</div>
diff --git a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
index 983abda57f7..289c83979bb 100644
--- a/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
+++ b/app/assets/javascripts/import_entities/import_projects/components/provider_repo_table_row.vue
@@ -1,8 +1,8 @@
<script>
+import { GlIcon, GlBadge, GlFormInput, GlButton, GlLink } from '@gitlab/ui';
import { mapState, mapGetters, mapActions } from 'vuex';
-import { GlIcon, GlBadge } from '@gitlab/ui';
-import Select2Select from '~/vue_shared/components/select2_select.vue';
import { __ } from '~/locale';
+import Select2Select from '~/vue_shared/components/select2_select.vue';
import ImportStatus from '../../components/import_status.vue';
import { STATUSES } from '../../constants';
import { isProjectImportable, isIncompatible, getImportStatus } from '../utils';
@@ -12,8 +12,11 @@ export default {
components: {
Select2Select,
ImportStatus,
+ GlFormInput,
+ GlButton,
GlIcon,
GlBadge,
+ GlLink,
},
props: {
repo: {
@@ -61,7 +64,7 @@ export default {
select2Options() {
return {
data: this.availableNamespaces,
- containerCssClass: 'import-namespace-select qa-project-namespace-select w-auto',
+ containerCssClass: 'import-namespace-select qa-project-namespace-select gl-w-auto',
};
},
@@ -97,52 +100,56 @@ export default {
</script>
<template>
- <tr class="qa-project-import-row import-row">
- <td>
- <a
- :href="repo.importSource.providerLink"
- rel="noreferrer noopener"
- target="_blank"
- data-testid="providerLink"
+ <tr
+ class="qa-project-import-row gl-h-11 gl-border-0 gl-border-solid gl-border-t-1 gl-border-gray-100 gl-h-11"
+ >
+ <td class="gl-p-4">
+ <gl-link :href="repo.importSource.providerLink" target="_blank" data-testid="providerLink"
>{{ repo.importSource.fullName }}
<gl-icon v-if="repo.importSource.providerLink" name="external-link" />
- </a>
+ </gl-link>
</td>
- <td class="d-flex flex-wrap flex-lg-nowrap" data-testid="fullPath">
+ <td
+ class="gl-display-flex gl-flex-sm-wrap gl-p-4 gl-pt-5 gl-vertical-align-top"
+ data-testid="fullPath"
+ >
<template v-if="repo.importSource.target">{{ repo.importSource.target }}</template>
<template v-else-if="isImportNotStarted">
- <select2-select v-model="targetNamespaceSelect" :options="select2Options" />
- <span class="px-2 import-slash-divider d-flex justify-content-center align-items-center"
- >/</span
- >
- <input
- v-model="newNameInput"
- type="text"
- class="form-control import-project-name-input qa-project-path-field"
- />
+ <div class="import-entities-target-select gl-display-flex gl-align-items-stretch gl-w-full">
+ <select2-select v-model="targetNamespaceSelect" :options="select2Options" />
+ <div
+ class="import-entities-target-select-separator gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1"
+ >
+ /
+ </div>
+ <gl-form-input
+ v-model="newNameInput"
+ class="gl-rounded-top-left-none gl-rounded-bottom-left-none qa-project-path-field"
+ />
+ </div>
</template>
<template v-else-if="repo.importedProject">{{ displayFullPath }}</template>
</td>
- <td>
+ <td class="gl-p-4">
<import-status :status="importStatus" />
</td>
<td data-testid="actions">
- <a
+ <gl-button
v-if="isFinished"
class="btn btn-default"
:href="repo.importedProject.fullPath"
rel="noreferrer noopener"
target="_blank"
>{{ __('Go to project') }}
- </a>
- <button
+ </gl-button>
+ <gl-button
v-if="isImportNotStarted"
type="button"
- class="qa-import-button btn btn-default"
+ class="qa-import-button"
@click="fetchImport(repo.importSource.id)"
>
{{ importButtonText }}
- </button>
+ </gl-button>
<gl-badge v-else-if="isIncompatible" variant="danger">{{
__('Incompatible project')
}}</gl-badge>
diff --git a/app/assets/javascripts/import_entities/import_projects/index.js b/app/assets/javascripts/import_entities/import_projects/index.js
index 7373b628f2b..6b7fe23ed60 100644
--- a/app/assets/javascripts/import_entities/import_projects/index.js
+++ b/app/assets/javascripts/import_entities/import_projects/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
import { parseBoolean } from '~/lib/utils/common_utils';
+import Translate from '~/vue_shared/translate';
import ImportProjectsTable from './components/import_projects_table.vue';
import createStore from './store';
diff --git a/app/assets/javascripts/import_entities/import_projects/store/actions.js b/app/assets/javascripts/import_entities/import_projects/store/actions.js
index a8217ff1033..33f8dbb8737 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/actions.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/actions.js
@@ -1,14 +1,14 @@
import Visibility from 'visibilityjs';
-import * as types from './mutation_types';
-import { isProjectImportable } from '../utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import Poll from '~/lib/utils/poll';
-import { visitUrl, objectToQuery } from '~/lib/utils/url_utility';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__, sprintf } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
+import Poll from '~/lib/utils/poll';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { visitUrl, objectToQuery } from '~/lib/utils/url_utility';
+import { s__, sprintf } from '~/locale';
+import { isProjectImportable } from '../utils';
+import * as types from './mutation_types';
let eTagPoll;
diff --git a/app/assets/javascripts/import_entities/import_projects/store/index.js b/app/assets/javascripts/import_entities/import_projects/store/index.js
index 7ba12f81eb9..a2880e7d031 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/index.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from './state';
import actionsFactory from './actions';
import * as getters from './getters';
import mutations from './mutations';
+import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/import_entities/import_projects/store/mutations.js b/app/assets/javascripts/import_entities/import_projects/store/mutations.js
index 1a96508bd48..c5e1922597a 100644
--- a/app/assets/javascripts/import_entities/import_projects/store/mutations.js
+++ b/app/assets/javascripts/import_entities/import_projects/store/mutations.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import * as types from './mutation_types';
import { STATUSES } from '../../constants';
+import * as types from './mutation_types';
const makeNewImportedProject = (importedProject) => ({
importSource: {
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 7d44a28b4bb..5638dc064d1 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -10,22 +10,20 @@ import {
GlIcon,
GlEmptyState,
} from '@gitlab/ui';
+import { convertToSnakeCase } from '~/lib/utils/text_utility';
+import { visitUrl, mergeUrlParams, joinPaths } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
import Tracking from '~/tracking';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
import {
tdClass,
thClass,
bodyTrClass,
initialPaginationState,
} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
-import { convertToSnakeCase } from '~/lib/utils/text_utility';
-import { s__ } from '~/locale';
-import { visitUrl, mergeUrlParams, joinPaths } from '~/lib/utils/url_utility';
-import getIncidents from '../graphql/queries/get_incidents.query.graphql';
-import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
-import SeverityToken from '~/sidebar/components/severity/severity.vue';
-import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
+import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
I18N,
INCIDENT_STATUS_TABS,
@@ -37,6 +35,8 @@ import {
trackIncidentCreateNewOptions,
trackIncidentListViewsOptions,
} from '../constants';
+import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
+import getIncidents from '../graphql/queries/get_incidents.query.graphql';
export default {
trackIncidentCreateNewOptions,
@@ -102,7 +102,7 @@ export default {
GlIcon,
PublishedCell: () => import('ee_component/incidents/components/published_cell.vue'),
ServiceLevelAgreementCell: () =>
- import('ee_component/incidents/components/service_level_agreement_cell.vue'),
+ import('ee_component/vue_shared/components/incidents/service_level_agreement.vue'),
GlEmptyState,
SeverityToken,
PaginatedTableWithSearchAndTabs,
diff --git a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
index c90ff8079b8..9d5f37dc3b7 100644
--- a/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
+++ b/app/assets/javascripts/incidents_settings/components/incidents_settings_tabs.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton, GlTabs, GlTab } from '@gitlab/ui';
+import { INTEGRATION_TABS_CONFIG, I18N_INTEGRATION_TABS } from '../constants';
import AlertsSettingsForm from './alerts_form.vue';
import PagerDutySettingsForm from './pagerduty_form.vue';
-import { INTEGRATION_TABS_CONFIG, I18N_INTEGRATION_TABS } from '../constants';
export default {
components: {
@@ -26,7 +26,7 @@ export default {
class="settings no-animate qa-incident-management-settings"
>
<div class="settings-header">
- <h4 ref="sectionHeader" class="gl-my-3! gl-py-1">
+ <h4 ref="sectionHeader">
{{ $options.i18n.headerText }}
</h4>
<gl-button ref="toggleBtn" class="js-settings-toggle">{{
diff --git a/app/assets/javascripts/incidents_settings/incidents_settings_service.js b/app/assets/javascripts/incidents_settings/incidents_settings_service.js
index f0e692f9cbe..82b94c08381 100644
--- a/app/assets/javascripts/incidents_settings/incidents_settings_service.js
+++ b/app/assets/javascripts/incidents_settings/incidents_settings_service.js
@@ -1,6 +1,6 @@
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { ERROR_MSG } from './constants';
export default class IncidentsSettingsService {
diff --git a/app/assets/javascripts/init_changes_dropdown.js b/app/assets/javascripts/init_changes_dropdown.js
index 22667d8ae88..b42264c870b 100644
--- a/app/assets/javascripts/init_changes_dropdown.js
+++ b/app/assets/javascripts/init_changes_dropdown.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import { stickyMonitor } from './lib/utils/sticky';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { stickyMonitor } from './lib/utils/sticky';
export default (stickyTop) => {
stickyMonitor(document.querySelector('.js-diff-files-changed'), stickyTop);
diff --git a/app/assets/javascripts/init_issuable_sidebar.js b/app/assets/javascripts/init_issuable_sidebar.js
index 1e82ecb05b5..59038b3d9fb 100644
--- a/app/assets/javascripts/init_issuable_sidebar.js
+++ b/app/assets/javascripts/init_issuable_sidebar.js
@@ -1,11 +1,11 @@
/* eslint-disable no-new */
-import MilestoneSelect from './milestone_select';
-import LabelsSelect from './labels_select';
+import { mountSidebarLabels, getSidebarOptions } from '~/sidebar/mount_sidebar';
+import DueDateSelectors from './due_date_select';
import IssuableContext from './issuable_context';
+import LabelsSelect from './labels_select';
+import MilestoneSelect from './milestone_select';
import Sidebar from './right_sidebar';
-import DueDateSelectors from './due_date_select';
-import { mountSidebarLabels, getSidebarOptions } from '~/sidebar/mount_sidebar';
export default () => {
const sidebarOptEl = document.querySelector('.js-sidebar-options');
diff --git a/app/assets/javascripts/init_labels.js b/app/assets/javascripts/init_labels.js
index 15da5d5cceb..10bfbf7960c 100644
--- a/app/assets/javascripts/init_labels.js
+++ b/app/assets/javascripts/init_labels.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import LabelManager from './label_manager';
import GroupLabelSubscription from './group_label_subscription';
+import LabelManager from './label_manager';
import ProjectLabelSubscription from './project_label_subscription';
export default () => {
diff --git a/app/assets/javascripts/integrations/edit/components/active_checkbox.vue b/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
index 6698984d02f..8677f139723 100644
--- a/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
+++ b/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import eventHub from '../event_hub';
export default {
diff --git a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
index 93ea1f4f636..bcf4b036fd2 100644
--- a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlModal } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { __ } from '~/locale';
export default {
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index f568f7e6d3d..a4baca20ac9 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -1,10 +1,10 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapGetters } from 'vuex';
-import { capitalize, lowerCase, isEmpty } from 'lodash';
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
-import eventHub from '../event_hub';
+import { capitalize, lowerCase, isEmpty } from 'lodash';
+import { mapGetters } from 'vuex';
import { __, sprintf } from '~/locale';
+import eventHub from '../event_hub';
export default {
name: 'DynamicField',
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index ac8a64d5f3b..3ec0c23e55d 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -1,18 +1,18 @@
<script>
+import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { mapState, mapActions, mapGetters } from 'vuex';
-import { GlButton, GlModalDirective } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import eventHub from '../event_hub';
import { integrationLevels } from '../constants';
+import eventHub from '../event_hub';
-import OverrideDropdown from './override_dropdown.vue';
import ActiveCheckbox from './active_checkbox.vue';
-import JiraTriggerFields from './jira_trigger_fields.vue';
-import JiraIssuesFields from './jira_issues_fields.vue';
-import TriggerFields from './trigger_fields.vue';
-import DynamicField from './dynamic_field.vue';
import ConfirmationModal from './confirmation_modal.vue';
+import DynamicField from './dynamic_field.vue';
+import JiraIssuesFields from './jira_issues_fields.vue';
+import JiraTriggerFields from './jira_trigger_fields.vue';
+import OverrideDropdown from './override_dropdown.vue';
import ResetConfirmationModal from './reset_confirmation_modal.vue';
+import TriggerFields from './trigger_fields.vue';
export default {
name: 'IntegrationForm',
@@ -28,9 +28,17 @@ export default {
GlButton,
},
directives: {
- 'gl-modal': GlModalDirective,
+ GlModal: GlModalDirective,
+ SafeHtml,
},
mixins: [glFeatureFlagsMixin()],
+ props: {
+ helpHtml: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
computed: {
...mapGetters(['currentKey', 'propsSource', 'isDisabled']),
...mapState([
@@ -80,11 +88,14 @@ export default {
this.fetchResetIntegration();
},
},
+ helpHtmlConfig: {
+ ADD_TAGS: ['use'], // to support icon SVGs
+ },
};
</script>
<template>
- <div>
+ <div class="gl-mb-3">
<override-dropdown
v-if="defaultState !== null"
:inherit-from-id="defaultState.id"
@@ -92,80 +103,92 @@ export default {
:learn-more-path="propsSource.learnMorePath"
@change="setOverride"
/>
- <active-checkbox v-if="propsSource.showActive" :key="`${currentKey}-active-checkbox`" />
- <jira-trigger-fields
- v-if="isJira"
- :key="`${currentKey}-jira-trigger-fields`"
- v-bind="propsSource.triggerFieldsProps"
- />
- <trigger-fields
- v-else-if="propsSource.triggerEvents.length"
- :key="`${currentKey}-trigger-fields`"
- :events="propsSource.triggerEvents"
- :type="propsSource.type"
- />
- <dynamic-field
- v-for="field in propsSource.fields"
- :key="`${currentKey}-${field.name}`"
- v-bind="field"
- />
- <jira-issues-fields
- v-if="showJiraIssuesFields"
- :key="`${currentKey}-jira-issues-fields`"
- v-bind="propsSource.jiraIssuesProps"
- />
- <div v-if="isEditable" class="footer-block row-content-block">
- <template v-if="isInstanceOrGroupLevel">
- <gl-button
- v-gl-modal.confirmSaveIntegration
- category="primary"
- variant="success"
- :loading="isSaving"
- :disabled="isDisabled"
- data-qa-selector="save_changes_button"
- >
- {{ __('Save changes') }}
- </gl-button>
- <confirmation-modal @submit="onSaveClick" />
- </template>
- <gl-button
- v-else
- category="primary"
- variant="success"
- type="submit"
- :loading="isSaving"
- :disabled="isDisabled"
- data-qa-selector="save_changes_button"
- @click.prevent="onSaveClick"
- >
- {{ __('Save changes') }}
- </gl-button>
- <gl-button
- v-if="propsSource.canTest"
- :loading="isTesting"
- :disabled="isDisabled"
- :href="propsSource.testPath"
- @click.prevent="onTestClick"
- >
- {{ __('Test settings') }}
- </gl-button>
+ <div class="row">
+ <div class="col-lg-4"></div>
+
+ <div class="col-lg-8">
+ <!-- helpHtml is trusted input -->
+ <div v-if="helpHtml" v-safe-html:[$options.helpHtmlConfig]="helpHtml"></div>
+
+ <active-checkbox v-if="propsSource.showActive" :key="`${currentKey}-active-checkbox`" />
+ <jira-trigger-fields
+ v-if="isJira"
+ :key="`${currentKey}-jira-trigger-fields`"
+ v-bind="propsSource.triggerFieldsProps"
+ />
+ <trigger-fields
+ v-else-if="propsSource.triggerEvents.length"
+ :key="`${currentKey}-trigger-fields`"
+ :events="propsSource.triggerEvents"
+ :type="propsSource.type"
+ />
+ <dynamic-field
+ v-for="field in propsSource.fields"
+ :key="`${currentKey}-${field.name}`"
+ v-bind="field"
+ />
+ <jira-issues-fields
+ v-if="showJiraIssuesFields"
+ :key="`${currentKey}-jira-issues-fields`"
+ v-bind="propsSource.jiraIssuesProps"
+ />
+ <div v-if="isEditable" class="footer-block row-content-block">
+ <template v-if="isInstanceOrGroupLevel">
+ <gl-button
+ v-gl-modal.confirmSaveIntegration
+ category="primary"
+ variant="success"
+ :loading="isSaving"
+ :disabled="isDisabled"
+ data-qa-selector="save_changes_button"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ <confirmation-modal @submit="onSaveClick" />
+ </template>
+ <gl-button
+ v-else
+ category="primary"
+ variant="success"
+ type="submit"
+ :loading="isSaving"
+ :disabled="isDisabled"
+ data-qa-selector="save_changes_button"
+ @click.prevent="onSaveClick"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+
+ <gl-button
+ v-if="propsSource.canTest"
+ :loading="isTesting"
+ :disabled="isDisabled"
+ :href="propsSource.testPath"
+ @click.prevent="onTestClick"
+ >
+ {{ __('Test settings') }}
+ </gl-button>
- <template v-if="showReset">
- <gl-button
- v-gl-modal.confirmResetIntegration
- category="secondary"
- variant="default"
- :loading="isResetting"
- :disabled="isDisabled"
- data-testid="reset-button"
- >
- {{ __('Reset') }}
- </gl-button>
- <reset-confirmation-modal @reset="onResetClick" />
- </template>
+ <template v-if="showReset">
+ <gl-button
+ v-gl-modal.confirmResetIntegration
+ category="secondary"
+ variant="default"
+ :loading="isResetting"
+ :disabled="isDisabled"
+ data-testid="reset-button"
+ >
+ {{ __('Reset') }}
+ </gl-button>
+ <reset-confirmation-modal @reset="onResetClick" />
+ </template>
- <gl-button class="btn-cancel" :href="propsSource.cancelPath">{{ __('Cancel') }}</gl-button>
+ <gl-button class="btn-cancel" :href="propsSource.cancelPath">{{
+ __('Cancel')
+ }}</gl-button>
+ </div>
+ </div>
</div>
</div>
</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 1baa2b440b0..d3d1fd8ddc3 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -8,6 +8,7 @@ import {
GlButton,
GlCard,
} from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../event_hub';
export default {
@@ -20,18 +21,36 @@ export default {
GlLink,
GlButton,
GlCard,
+ JiraIssueCreationVulnerabilities: () =>
+ import('ee_component/integrations/edit/components/jira_issue_creation_vulnerabilities.vue'),
},
+ mixins: [glFeatureFlagsMixin()],
props: {
showJiraIssuesIntegration: {
type: Boolean,
required: false,
default: false,
},
+ showJiraVulnerabilitiesIntegration: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
initialEnableJiraIssues: {
type: Boolean,
required: false,
default: null,
},
+ initialEnableJiraVulnerabilities: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ initialVulnerabilitiesIssuetype: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
initialProjectKey: {
type: String,
required: false,
@@ -45,12 +64,12 @@ export default {
upgradePlanPath: {
type: String,
required: false,
- default: null,
+ default: '',
},
editProjectPath: {
type: String,
required: false,
- default: null,
+ default: '',
},
},
data() {
@@ -64,6 +83,13 @@ export default {
validProjectKey() {
return !this.enableJiraIssues || Boolean(this.projectKey) || !this.validated;
},
+ showJiraVulnerabilitiesOptions() {
+ return (
+ this.enableJiraIssues &&
+ this.showJiraVulnerabilitiesIntegration &&
+ this.glFeatures.jiraForVulnerabilities
+ );
+ },
},
created() {
eventHub.$on('validateForm', this.validateForm);
@@ -75,6 +101,9 @@ export default {
validateForm() {
this.validated = true;
},
+ getJiraIssueTypes() {
+ eventHub.$emit('getJiraIssueTypes');
+ },
},
};
</script>
@@ -105,6 +134,14 @@ export default {
}}
</template>
</gl-form-checkbox>
+ <jira-issue-creation-vulnerabilities
+ v-if="showJiraVulnerabilitiesOptions"
+ :project-key="projectKey"
+ :initial-is-enabled="initialEnableJiraVulnerabilities"
+ :initial-issue-type-id="initialVulnerabilitiesIssuetype"
+ data-testid="jira-for-vulnerabilities"
+ @request-get-issue-types="getJiraIssueTypes"
+ />
</template>
<gl-card v-else class="gl-mt-7">
<strong>{{ __('This is a Premium feature') }}</strong>
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 bc005aa16e9..af4e9acf4ba 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_trigger_fields.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlFormGroup, GlFormCheckbox, GlFormRadio } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { s__ } from '~/locale';
const commentDetailOptions = [
diff --git a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
index 4e2c37ac7f3..7b3a067b186 100644
--- a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
+++ b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlDropdown, GlDropdownItem, GlLink } from '@gitlab/ui';
+import { mapState } from 'vuex';
import { s__ } from '~/locale';
import { defaultIntegrationLevel, overrideDropdownDescriptions } from '../constants';
diff --git a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
index d8503910566..9472a3eeafe 100644
--- a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlModal } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
index 32878c6afa4..1bbecea05ad 100644
--- a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
@@ -1,7 +1,7 @@
<script>
-import { mapGetters } from 'vuex';
-import { startCase } from 'lodash';
import { GlFormGroup, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
+import { startCase } from 'lodash';
+import { mapGetters } from 'vuex';
import { __ } from '~/locale';
const typeWithPlaceholder = {
diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js
index 95a53f1beab..ab9bdd9ca2e 100644
--- a/app/assets/javascripts/integrations/edit/index.js
+++ b/app/assets/javascripts/integrations/edit/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import { createStore } from './store';
import { parseBoolean } from '~/lib/utils/common_utils';
import IntegrationForm from './components/integration_form.vue';
+import { createStore } from './store';
function parseBooleanInData(data) {
const result = {};
@@ -27,6 +27,7 @@ function parseDatasetToProps(data) {
cancelPath,
testPath,
resetPath,
+ vulnerabilitiesIssuetype,
...booleanAttributes
} = data;
const {
@@ -38,7 +39,9 @@ function parseDatasetToProps(data) {
mergeRequestEvents,
enableComments,
showJiraIssuesIntegration,
+ showJiraVulnerabilitiesIntegration,
enableJiraIssues,
+ enableJiraVulnerabilities,
gitlabIssuesEnabled,
} = parseBooleanInData(booleanAttributes);
@@ -59,7 +62,10 @@ function parseDatasetToProps(data) {
},
jiraIssuesProps: {
showJiraIssuesIntegration,
+ showJiraVulnerabilitiesIntegration,
initialEnableJiraIssues: enableJiraIssues,
+ initialEnableJiraVulnerabilities: enableJiraVulnerabilities,
+ initialVulnerabilitiesIssuetype: vulnerabilitiesIssuetype,
initialProjectKey: projectKey,
gitlabIssuesEnabled,
upgradePlanPath,
@@ -80,21 +86,29 @@ export default (el, defaultEl) => {
}
const props = parseDatasetToProps(el.dataset);
-
const initialState = {
defaultState: null,
customState: props,
};
-
if (defaultEl) {
initialState.defaultState = Object.freeze(parseDatasetToProps(defaultEl.dataset));
}
+ // Here, we capture the "helpHtml", so we can pass it to the Vue component
+ // to position it where ever it wants.
+ // Because this node is a _child_ of `el`, it will be removed when the Vue component is mounted,
+ // so we don't need to manually remove it.
+ const helpHtml = el.querySelector('.js-integration-help-html')?.innerHTML;
+
return new Vue({
el,
store: createStore(initialState),
render(createElement) {
- return createElement(IntegrationForm);
+ return createElement(IntegrationForm, {
+ props: {
+ helpHtml,
+ },
+ });
},
});
};
diff --git a/app/assets/javascripts/integrations/edit/store/actions.js b/app/assets/javascripts/integrations/edit/store/actions.js
index 421917b720a..400397c050c 100644
--- a/app/assets/javascripts/integrations/edit/store/actions.js
+++ b/app/assets/javascripts/integrations/edit/store/actions.js
@@ -26,3 +26,18 @@ export const fetchResetIntegration = ({ dispatch, getters }) => {
.then(() => dispatch('receiveResetIntegrationSuccess'))
.catch(() => dispatch('receiveResetIntegrationError'));
};
+
+export const requestJiraIssueTypes = ({ commit }) => {
+ commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, '');
+ commit(types.SET_IS_LOADING_JIRA_ISSUE_TYPES, true);
+};
+export const receiveJiraIssueTypesSuccess = ({ commit }, issueTypes = []) => {
+ commit(types.SET_IS_LOADING_JIRA_ISSUE_TYPES, false);
+ commit(types.SET_JIRA_ISSUE_TYPES, issueTypes);
+};
+
+export const receiveJiraIssueTypesError = ({ commit }, errorMessage) => {
+ commit(types.SET_IS_LOADING_JIRA_ISSUE_TYPES, false);
+ commit(types.SET_JIRA_ISSUE_TYPES, []);
+ commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, errorMessage);
+};
diff --git a/app/assets/javascripts/integrations/edit/store/mutation_types.js b/app/assets/javascripts/integrations/edit/store/mutation_types.js
index 54928148b22..c681056a515 100644
--- a/app/assets/javascripts/integrations/edit/store/mutation_types.js
+++ b/app/assets/javascripts/integrations/edit/store/mutation_types.js
@@ -3,5 +3,9 @@ export const SET_IS_SAVING = 'SET_IS_SAVING';
export const SET_IS_TESTING = 'SET_IS_TESTING';
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/integrations/edit/store/mutations.js b/app/assets/javascripts/integrations/edit/store/mutations.js
index 826757e665b..279df1b9266 100644
--- a/app/assets/javascripts/integrations/edit/store/mutations.js
+++ b/app/assets/javascripts/integrations/edit/store/mutations.js
@@ -19,4 +19,13 @@ export default {
[types.RECEIVE_RESET_INTEGRATION_ERROR](state) {
state.isResetting = false;
},
+ [types.SET_JIRA_ISSUE_TYPES](state, jiraIssueTypes) {
+ state.jiraIssueTypes = jiraIssueTypes;
+ },
+ [types.SET_IS_LOADING_JIRA_ISSUE_TYPES](state, isLoadingJiraIssueTypes) {
+ state.isLoadingJiraIssueTypes = isLoadingJiraIssueTypes;
+ },
+ [types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE](state, errorMessage) {
+ state.loadingJiraIssueTypesErrorMessage = errorMessage;
+ },
};
diff --git a/app/assets/javascripts/integrations/edit/store/state.js b/app/assets/javascripts/integrations/edit/store/state.js
index aae3db1583f..1c0b274e4ef 100644
--- a/app/assets/javascripts/integrations/edit/store/state.js
+++ b/app/assets/javascripts/integrations/edit/store/state.js
@@ -8,5 +8,8 @@ export default ({ defaultState = null, customState = {} } = {}) => {
isSaving: false,
isTesting: false,
isResetting: false,
+ isLoadingJiraIssueTypes: false,
+ loadingJiraIssueTypesErrorMessage: '',
+ jiraIssueTypes: [],
};
};
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index 861655a6a64..801cf3ed27e 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import { delay } from 'lodash';
-import axios from '../lib/utils/axios_utils';
import { __, s__ } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
+import axios from '../lib/utils/axios_utils';
import initForm from './edit';
import eventHub from './edit/event_hub';
@@ -33,6 +33,12 @@ export default class IntegrationSettingsForm {
eventHub.$on('saveIntegration', () => {
this.saveIntegration();
});
+ eventHub.$on('getJiraIssueTypes', () => {
+ // eslint-disable-next-line no-jquery/no-serialize
+ this.getJiraIssueTypes(this.$form.serialize());
+ });
+
+ eventHub.$emit('formInitialized');
}
saveIntegration() {
@@ -80,15 +86,58 @@ export default class IntegrationSettingsForm {
}
/**
+ * Get a list of Jira issue types for the currently configured project
+ *
+ * @param {string} formData - URL encoded string containing the form data
+ *
+ * @return {Promise}
+ */
+ getJiraIssueTypes(formData) {
+ const {
+ $store: { dispatch },
+ } = this.vue;
+
+ dispatch('requestJiraIssueTypes');
+
+ return this.fetchTestSettings(formData)
+ .then(
+ ({
+ data: {
+ issuetypes,
+ error,
+ message = s__('Integrations|Connection failed. Please check your settings.'),
+ },
+ }) => {
+ if (error || !issuetypes?.length) {
+ eventHub.$emit('validateForm');
+ throw new Error(message);
+ }
+
+ dispatch('receiveJiraIssueTypesSuccess', issuetypes);
+ },
+ )
+ .catch(({ message = __('Something went wrong on our end.') }) => {
+ dispatch('receiveJiraIssueTypesError', message);
+ });
+ }
+
+ /**
+ * Send request to the test endpoint which checks if the current config is valid
+ */
+ fetchTestSettings(formData) {
+ return axios.put(this.testEndPoint, formData);
+ }
+
+ /**
* Test Integration config
*/
testSettings(formData) {
- return axios
- .put(this.testEndPoint, formData)
+ return this.fetchTestSettings(formData)
.then(({ data }) => {
if (data.error) {
toast(`${data.message} ${data.service_response}`);
} else {
+ this.vue.$store.dispatch('receiveJiraIssueTypesSuccess', data.issuetypes);
toast(s__('Integrations|Connection successful.'));
}
})
diff --git a/app/assets/javascripts/invite_member/components/invite_member_modal.vue b/app/assets/javascripts/invite_member/components/invite_member_modal.vue
index 3df99bccdb0..144c1a2c22a 100644
--- a/app/assets/javascripts/invite_member/components/invite_member_modal.vue
+++ b/app/assets/javascripts/invite_member/components/invite_member_modal.vue
@@ -1,8 +1,9 @@
<script>
import { GlModal, GlLink } from '@gitlab/ui';
-import eventHub from '../event_hub';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__, __ } from '~/locale';
import { OPEN_MODAL, MODAL_ID } from '../constants';
+import eventHub from '../event_hub';
export default {
cancelProps: {
@@ -38,7 +39,7 @@ export default {
},
methods: {
openModal() {
- this.$root.$emit('bv::show::modal', MODAL_ID);
+ this.$root.$emit(BV_SHOW_MODAL, MODAL_ID);
},
},
};
diff --git a/app/assets/javascripts/invite_member/components/invite_member_trigger.vue b/app/assets/javascripts/invite_member/components/invite_member_trigger.vue
index 6e886e0e002..56cf1ab2fc2 100644
--- a/app/assets/javascripts/invite_member/components/invite_member_trigger.vue
+++ b/app/assets/javascripts/invite_member/components/invite_member_trigger.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink } from '@gitlab/ui';
-import eventHub from '../event_hub';
import { OPEN_MODAL } from '../constants';
+import eventHub from '../event_hub';
export default {
components: {
diff --git a/app/assets/javascripts/invite_member/init_invite_member_modal.js b/app/assets/javascripts/invite_member/init_invite_member_modal.js
index 901e3e315ee..c292bda1931 100644
--- a/app/assets/javascripts/invite_member/init_invite_member_modal.js
+++ b/app/assets/javascripts/invite_member/init_invite_member_modal.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
import InviteMemberModal from './components/invite_member_modal.vue';
Vue.use(GlToast);
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 a92289ca8c1..f5a65882fba 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -10,10 +10,11 @@ import {
GlFormInput,
} from '@gitlab/ui';
import { partition, isString } from 'lodash';
-import eventHub from '../event_hub';
-import { s__, __, sprintf } from '~/locale';
import Api from '~/api';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
+import { s__, __, sprintf } from '~/locale';
+import eventHub from '../event_hub';
export default {
name: 'InviteMembersModal',
@@ -113,10 +114,10 @@ export default {
];
},
openModal() {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
closeModal() {
- this.$root.$emit('bv::hide::modal', this.modalId);
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
},
sendInvite() {
this.submitForm();
diff --git a/app/assets/javascripts/invite_members/components/members_token_select.vue b/app/assets/javascripts/invite_members/components/members_token_select.vue
index 627d4ab2771..233a214013b 100644
--- a/app/assets/javascripts/invite_members/components/members_token_select.vue
+++ b/app/assets/javascripts/invite_members/components/members_token_select.vue
@@ -1,9 +1,9 @@
<script>
-import { debounce } from 'lodash';
import { GlTokenSelector, GlAvatar, GlAvatarLabeled, GlSprintf } from '@gitlab/ui';
+import { debounce } from 'lodash';
import { __ } from '~/locale';
-import { USER_SEARCH_DELAY } from '../constants';
import { getUsers } from '~/rest_api';
+import { USER_SEARCH_DELAY } from '../constants';
export default {
components: {
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 74c374018de..3de99dcc546 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -1,7 +1,7 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import Vue from 'vue';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
Vue.use(GlToast);
diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue
new file mode 100644
index 00000000000..6d063b59922
--- /dev/null
+++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue
@@ -0,0 +1,169 @@
+<script>
+import {
+ GlButton,
+ GlModal,
+ GlModalDirective,
+ GlTooltipDirective,
+ GlSprintf,
+ GlLink,
+ GlFormInputGroup,
+ GlIcon,
+} from '@gitlab/ui';
+import axios from '~/lib/utils/axios_utils';
+import { sprintf, __ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+
+export default {
+ name: 'IssuableByEmail',
+ components: {
+ GlButton,
+ GlModal,
+ GlSprintf,
+ GlLink,
+ GlFormInputGroup,
+ GlIcon,
+ ModalCopyButton,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ GlTooltip: GlTooltipDirective,
+ },
+ inject: {
+ initialEmail: {
+ default: null,
+ },
+ issuableType: {
+ default: '',
+ },
+ emailsHelpPagePath: {
+ default: '',
+ },
+ quickActionsHelpPath: {
+ default: '',
+ },
+ markdownHelpPath: {
+ default: '',
+ },
+ resetPath: {
+ default: '',
+ },
+ },
+ data() {
+ return {
+ email: this.initialEmail,
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ issuableName: this.issuableType === 'issue' ? 'issue' : 'merge request',
+ };
+ },
+ computed: {
+ mailToLink() {
+ const subject = sprintf(__('Enter the %{name} title'), {
+ name: this.issuableName,
+ });
+ const body = sprintf(__('Enter the %{name} description'), {
+ name: this.issuableName,
+ });
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `mailto:${this.email}?subject=${subject}&body=${body}`;
+ },
+ },
+ methods: {
+ async resetIncomingEmailToken() {
+ try {
+ const {
+ data: { new_address: newAddress },
+ } = await axios.put(this.resetPath);
+ this.email = newAddress;
+ } catch {
+ this.$toast.show(__('There was an error when reseting email token.'), { type: 'error' });
+ }
+ },
+ cancelHandler() {
+ this.$refs.modal.hide();
+ },
+ },
+ modalId: 'issuable-email-modal',
+};
+</script>
+
+<template>
+ <div>
+ <gl-button v-gl-modal="$options.modalId" variant="link" data-testid="issuable-email-modal-btn"
+ ><gl-sprintf :message="__('Email a new %{name} to this project')"
+ ><template #name>{{ issuableName }}</template></gl-sprintf
+ ></gl-button
+ >
+ <gl-modal ref="modal" :modal-id="$options.modalId">
+ <template #modal-title>
+ <gl-sprintf :message="__('Create new %{name} by email')">
+ <template #name>{{ issuableName }}</template>
+ </gl-sprintf>
+ </template>
+ <p>
+ <gl-sprintf
+ :message="
+ __(
+ 'You can create a new %{name} inside this project by sending an email to the following email address:',
+ )
+ "
+ >
+ <template #name>{{ issuableName }}</template>
+ </gl-sprintf>
+ </p>
+ <gl-form-input-group :value="email" readonly select-on-click class="gl-mb-4">
+ <template #append>
+ <modal-copy-button :text="email" :title="__('Copy')" :modal-id="$options.modalId" />
+ <gl-button
+ v-gl-tooltip.hover
+ :href="mailToLink"
+ :title="__('Send email')"
+ icon="mail"
+ data-testid="mail-to-btn"
+ />
+ </template>
+ </gl-form-input-group>
+ <p>
+ <gl-sprintf
+ :message="
+ __(
+ '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.',
+ )
+ "
+ >
+ <template #quickActionsLink="{ content }">
+ <gl-link :href="quickActionsHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ <template #markdownLink="{ content }">
+ <gl-link :href="markdownHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ <p>
+ <gl-sprintf
+ :message="
+ __(
+ 'This is a private email address %{helpIcon} generated just for you. Anyone who gets ahold of it can create issues or merge requests as if they were you. You should %{resetLinkStart}reset it%{resetLinkEnd} if that ever happens.',
+ )
+ "
+ >
+ <template #helpIcon>
+ <gl-link :href="emailsHelpPagePath" target="_blank"
+ ><gl-icon class="gl-text-blue-600" name="question-o"
+ /></gl-link>
+ </template>
+ <template #resetLink="{ content }">
+ <gl-button
+ variant="link"
+ data-testid="incoming-email-token-reset"
+ @click="resetIncomingEmailToken"
+ >{{ content }}</gl-button
+ >
+ </template>
+ </gl-sprintf>
+ </p>
+ <template #modal-footer>
+ <gl-button category="secondary" @click="cancelHandler">{{ s__('Cancel') }}</gl-button>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable/init_issuable_by_email.js b/app/assets/javascripts/issuable/init_issuable_by_email.js
new file mode 100644
index 00000000000..984b826234c
--- /dev/null
+++ b/app/assets/javascripts/issuable/init_issuable_by_email.js
@@ -0,0 +1,35 @@
+import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
+import IssuableByEmail from './components/issuable_by_email.vue';
+
+Vue.use(GlToast);
+
+export default () => {
+ const el = document.querySelector('.js-issueable-by-email');
+
+ if (!el) return null;
+
+ const {
+ initialEmail,
+ issuableType,
+ emailsHelpPagePath,
+ quickActionsHelpPath,
+ markdownHelpPath,
+ resetPath,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ initialEmail,
+ issuableType,
+ emailsHelpPagePath,
+ quickActionsHelpPath,
+ markdownHelpPath,
+ resetPath,
+ },
+ render(h) {
+ return h(IssuableByEmail);
+ },
+ });
+};
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js
index 8bb76edbd47..f507f072253 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_actions.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { difference, intersection, union } from 'lodash';
-import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash } from './flash';
+import axios from './lib/utils/axios_utils';
import { __ } from './locale';
export default {
@@ -50,6 +50,7 @@ export default {
subscription_event: this.form.find('input[name="update[subscription_event]"]').val(),
health_status: this.form.find('input[name="update[health_status]"]').val(),
epic_id: this.form.find('input[name="update[epic_id]"]').val(),
+ sprint_id: this.form.find('input[name="update[iteration_id]"]').val(),
add_label_ids: [],
remove_label_ids: [],
},
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js
index b9daa16874a..ef98db5151a 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js
@@ -3,11 +3,11 @@
import $ from 'jquery';
import { property } from 'lodash';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
-import MilestoneSelect from './milestone_select';
import issueStatusSelect from './issue_status_select';
-import subscriptionSelect from './subscription_select';
-import LabelsSelect from './labels_select';
import issueableEventHub from './issues_list/eventhub';
+import LabelsSelect from './labels_select';
+import MilestoneSelect from './milestone_select';
+import subscriptionSelect from './subscription_select';
const HIDDEN_CLASS = 'hidden';
const DISABLED_CONTENT_CLASS = 'disabled-content';
@@ -79,6 +79,16 @@ export default class IssuableBulkUpdateSidebar {
})
.catch(() => {});
}
+
+ if (IS_EE) {
+ import('ee/vue_shared/components/sidebar/iterations_dropdown_bundle')
+ .then(({ default: iterationsDropdown }) => {
+ iterationsDropdown();
+ })
+ .catch((e) => {
+ throw e;
+ });
+ }
}
setupBulkUpdateActions() {
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
index 6fcff90b608..a87d4f077cc 100644
--- a/app/assets/javascripts/issuable_context.js
+++ b/app/assets/javascripts/issuable_context.js
@@ -1,8 +1,8 @@
+import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
import Cookies from 'js-cookie';
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import UsersSelect from './users_select';
import { loadCSSFile } from './lib/utils/css_utils';
+import UsersSelect from './users_select';
export default class IssuableContext {
constructor(currentUser) {
diff --git a/app/assets/javascripts/issuable_create/components/issuable_form.vue b/app/assets/javascripts/issuable_create/components/issuable_form.vue
index d7b88cc7fc8..3cbd5620063 100644
--- a/app/assets/javascripts/issuable_create/components/issuable_form.vue
+++ b/app/assets/javascripts/issuable_create/components/issuable_form.vue
@@ -1,9 +1,8 @@
<script>
import { GlForm, GlFormInput } from '@gitlab/ui';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
export default {
LabelSelectVariant: DropdownVariant,
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index a8fd7aaecdf..1b06dffbae7 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -2,12 +2,12 @@ import $ from 'jquery';
import Pikaday from 'pikaday';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import Autosave from './autosave';
-import UsersSelect from './users_select';
-import ZenMode from './zen_mode';
import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
+import { loadCSSFile } from './lib/utils/css_utils';
import { parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
import { queryToObject, objectToQuery } from './lib/utils/url_utility';
-import { loadCSSFile } from './lib/utils/css_utils';
+import UsersSelect from './users_select';
+import ZenMode from './zen_mode';
const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
const MR_TARGET_BRANCH = 'merge_request[target_branch]';
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index 4f31d26ab5d..4856f9781ce 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -1,35 +1,7 @@
-import $ from 'jquery';
-import axios from './lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from './flash';
-import { s__, __ } from './locale';
import issuableInitBulkUpdateSidebar from './issuable_init_bulk_update_sidebar';
export default class IssuableIndex {
constructor(pagePrefix) {
issuableInitBulkUpdateSidebar.init(pagePrefix);
- IssuableIndex.resetIncomingEmailToken();
- }
-
- static resetIncomingEmailToken() {
- const $resetToken = $('.incoming-email-token-reset');
-
- $resetToken.on('click', (e) => {
- e.preventDefault();
-
- $resetToken.text(s__('EmailToken|resetting...'));
-
- axios
- .put($resetToken.attr('href'))
- .then(({ data }) => {
- $('#issuable_email').val(data.new_address).focus();
-
- $resetToken.text(s__('EmailToken|reset it'));
- })
- .catch(() => {
- flash(__('There was an error when reseting email token.'));
-
- $resetToken.text(s__('EmailToken|reset it'));
- });
- });
}
}
diff --git a/app/assets/javascripts/issuable_init_bulk_update_sidebar.js b/app/assets/javascripts/issuable_init_bulk_update_sidebar.js
index da8969c80f3..179c2b83c6c 100644
--- a/app/assets/javascripts/issuable_init_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_init_bulk_update_sidebar.js
@@ -1,5 +1,5 @@
-import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
import issuableBulkUpdateActions from './issuable_bulk_update_actions';
+import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
export default {
bulkUpdateSidebar: null,
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index 583e5cb703d..39852eba71a 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -1,13 +1,13 @@
<script>
import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlTooltipDirective } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { getTimeago } from '~/lib/utils/datetime_utility';
import { isScopedLabel } from '~/lib/utils/common_utils';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-
+import { getTimeago } from '~/lib/utils/datetime_utility';
+import { isExternal, setUrlFragment } from '~/lib/utils/url_utility';
+import { __, sprintf } from '~/locale';
import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
components: {
@@ -48,17 +48,14 @@ export default {
author() {
return this.issuable.author;
},
+ webUrl() {
+ return this.issuable.gitlabWebUrl || this.issuable.webUrl;
+ },
authorId() {
return getIdFromGraphQLId(`${this.author.id}`);
},
isIssuableUrlExternal() {
- // Check if URL is relative, which means it is internal.
- if (!/^https?:\/\//g.test(this.issuable.webUrl)) {
- return false;
- }
- // In case URL is absolute, it may or may not be internal,
- // hence use `gon.gitlab_url` which is current instance domain.
- return !this.issuable.webUrl.includes(gon.gitlab_url);
+ return isExternal(this.webUrl);
},
labels() {
return this.issuable.labels?.nodes || this.issuable.labels || [];
@@ -92,6 +89,9 @@ export default {
this.hasSlotContents('status') || this.showDiscussions || this.issuable.assignees,
);
},
+ issuableNotesLink() {
+ return setUrlFragment(this.webUrl, 'notes');
+ },
},
methods: {
hasSlotContents(slotName) {
@@ -139,7 +139,13 @@ export default {
<div class="issuable-main-info">
<div data-testid="issuable-title" class="issue-title title">
<span class="issue-title-text" dir="auto">
- <gl-link :href="issuable.webUrl" v-bind="issuableTitleProps"
+ <gl-icon
+ v-if="issuable.confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ />
+ <gl-link :href="webUrl" v-bind="issuableTitleProps"
>{{ issuable.title
}}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
/></gl-link>
@@ -196,12 +202,12 @@ export default {
<li
v-if="showDiscussions"
data-testid="issuable-discussions"
- class="issuable-comments gl-display-none gl-display-sm-block"
+ class="issuable-comments gl-display-none gl-sm-display-block"
>
<gl-link
v-gl-tooltip:tooltipcontainer.top
:title="__('Comments')"
- :href="`${issuable.webUrl}#notes`"
+ :href="issuableNotesLink"
:class="{ 'no-comments': !issuable.userDiscussionsCount }"
class="gl-reset-color!"
>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
index c5475a34d3c..708e175cdb2 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -5,11 +5,10 @@ import { uniqueId } from 'lodash';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import IssuableTabs from './issuable_tabs.vue';
-import IssuableItem from './issuable_item.vue';
-import IssuableBulkEditSidebar from './issuable_bulk_edit_sidebar.vue';
-
import { DEFAULT_SKELETON_COUNT } from '../constants';
+import IssuableBulkEditSidebar from './issuable_bulk_edit_sidebar.vue';
+import IssuableItem from './issuable_item.vue';
+import IssuableTabs from './issuable_tabs.vue';
export default {
components: {
@@ -230,7 +229,7 @@ export default {
:initial-sort-by="initialSortBy"
:show-checkbox="showBulkEditSidebar"
:checkbox-checked="allIssuablesChecked"
- class="gl-flex-grow-1 row-content-block"
+ class="gl-flex-grow-1 gl-border-t-none row-content-block"
@checked-input="handleAllIssuablesCheckedInput"
@onFilter="$emit('filter', $event)"
@onSort="$emit('sort', $event)"
diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
index d9aab004077..57da030e22e 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
@@ -32,7 +32,10 @@ export default {
<template>
<div class="top-area">
- <gl-tabs class="nav-links mobile-separator issuable-state-filters">
+ <gl-tabs
+ class="gl-display-flex gl-flex-fill-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters"
+ nav-class="gl-border-b-0"
+ >
<gl-tab
v-for="tab in tabs"
:key="tab.id"
@@ -41,7 +44,7 @@ export default {
>
<template #title>
<span :title="tab.titleTooltip">{{ tab.title }}</span>
- <gl-badge v-if="tabCounts" variant="neutral" size="sm" class="gl-px-2 gl-py-1!">{{
+ <gl-badge v-if="tabCounts" variant="neutral" size="sm" class="gl-tab-counter-badge">{{
tabCounts[tab.name]
}}</gl-badge>
</template>
diff --git a/app/assets/javascripts/issuable_show/components/issuable_body.vue b/app/assets/javascripts/issuable_show/components/issuable_body.vue
index c084f328f42..02cf7a67727 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_body.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_body.vue
@@ -3,9 +3,9 @@ import { GlLink } from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import IssuableTitle from './issuable_title.vue';
import IssuableDescription from './issuable_description.vue';
import IssuableEditForm from './issuable_edit_form.vue';
+import IssuableTitle from './issuable_title.vue';
export default {
components: {
diff --git a/app/assets/javascripts/issuable_show/components/issuable_description.vue b/app/assets/javascripts/issuable_show/components/issuable_description.vue
index 091a4be5bd8..aa7e530972f 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_description.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_description.vue
@@ -1,6 +1,6 @@
<script>
-import $ from 'jquery';
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
export default {
diff --git a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue b/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
index 830a740ff78..6d139541524 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
@@ -1,6 +1,6 @@
<script>
-import $ from 'jquery';
import { GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import $ from 'jquery';
import Autosave from '~/autosave';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
diff --git a/app/assets/javascripts/issuable_show/components/issuable_header.vue b/app/assets/javascripts/issuable_show/components/issuable_header.vue
index 5404753631d..de17f7e7f6b 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_header.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_header.vue
@@ -2,6 +2,7 @@
import { GlIcon, GlButton, GlTooltipDirective, GlAvatarLink, GlAvatarLabeled } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { isExternal } from '~/lib/utils/url_utility';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
@@ -49,6 +50,9 @@ export default {
authorId() {
return getIdFromGraphQLId(`${this.author.id}`);
},
+ isAuthorExternal() {
+ return isExternal(this.author.webUrl);
+ },
},
mounted() {
this.toggleSidebarButtonEl = document.querySelector('.js-toggle-right-sidebar-button');
@@ -98,7 +102,11 @@ export default {
:src="author.avatarUrl"
:label="author.name"
class="d-none d-sm-inline-flex gl-ml-1"
- />
+ >
+ <template #meta>
+ <gl-icon v-if="isAuthorExternal" name="external-link" />
+ </template>
+ </gl-avatar-labeled>
<strong class="author d-sm-none d-inline">@{{ author.username }}</strong>
</gl-avatar-link>
</div>
@@ -112,7 +120,7 @@ export default {
</div>
<div
data-testid="header-actions"
- class="detail-page-header-actions gl-display-flex gl-display-md-block"
+ class="detail-page-header-actions gl-display-flex gl-md-display-block"
>
<slot name="header-actions"></slot>
</div>
diff --git a/app/assets/javascripts/issuable_show/components/issuable_show_root.vue b/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
index 2443338e8c4..240f35b74c8 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
@@ -1,8 +1,8 @@
<script>
import IssuableSidebar from '~/issuable_sidebar/components/issuable_sidebar_root.vue';
-import IssuableHeader from './issuable_header.vue';
import IssuableBody from './issuable_body.vue';
+import IssuableHeader from './issuable_header.vue';
export default {
components: {
diff --git a/app/assets/javascripts/issuable_show/components/issuable_title.vue b/app/assets/javascripts/issuable_show/components/issuable_title.vue
index d3b42fd2ffb..b7ea4a010a3 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_title.vue
+++ b/app/assets/javascripts/issuable_show/components/issuable_title.vue
@@ -54,7 +54,7 @@ export default {
<template>
<div>
<div class="title-container">
- <h2 v-safe-html="issuable.titleHtml" class="title qa-title" dir="auto"></h2>
+ <h2 v-safe-html="issuable.titleHtml || issuable.title" class="title qa-title" dir="auto"></h2>
<gl-button
v-if="enableEdit"
v-gl-tooltip.bottom
diff --git a/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue b/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
index 7cacba1cb65..8a159139af0 100644
--- a/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
+++ b/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
@@ -1,7 +1,7 @@
<script>
-import Cookies from 'js-cookie';
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';
diff --git a/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql b/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql
index fe01d2c2e78..42e646391a8 100644
--- a/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql
+++ b/app/assets/javascripts/issuable_sidebar/queries/issue_sidebar.query.graphql
@@ -3,6 +3,7 @@
query getProjectIssue($iid: String!, $fullPath: ID!) {
project(fullPath: $fullPath) {
issue(iid: $iid) {
+ id
assignees {
nodes {
...Author
diff --git a/app/assets/javascripts/issuable_suggestions/components/app.vue b/app/assets/javascripts/issuable_suggestions/components/app.vue
index ac5f04147d3..d0642b64e7e 100644
--- a/app/assets/javascripts/issuable_suggestions/components/app.vue
+++ b/app/assets/javascripts/issuable_suggestions/components/app.vue
@@ -1,8 +1,8 @@
<script>
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Suggestion from './item.vue';
import query from '../queries/issues.query.graphql';
+import Suggestion from './item.vue';
export default {
components: {
diff --git a/app/assets/javascripts/issuable_suggestions/components/item.vue b/app/assets/javascripts/issuable_suggestions/components/item.vue
index 6e265b1bf42..dea7608685a 100644
--- a/app/assets/javascripts/issuable_suggestions/components/item.vue
+++ b/app/assets/javascripts/issuable_suggestions/components/item.vue
@@ -1,10 +1,10 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { uniqueId } from 'lodash';
import { GlLink, GlTooltip, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
import { __ } from '~/locale';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import timeago from '~/vue_shared/mixins/timeago';
export default {
diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js
index 9949527106b..8f7f317d6b4 100644
--- a/app/assets/javascripts/issuable_suggestions/index.js
+++ b/app/assets/javascripts/issuable_suggestions/index.js
@@ -5,7 +5,7 @@ import App from './components/app.vue';
Vue.use(VueApollo);
-export default function () {
+export default function initIssuableSuggestions() {
const el = document.getElementById('js-suggestions');
const issueTitle = document.getElementById('issue_title');
const { projectPath } = el.dataset;
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index 91912c684ad..3f25682ab8b 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
+import { joinPaths } from '~/lib/utils/url_utility';
+import CreateMergeRequestDropdown from './create_merge_request_dropdown';
+import { deprecatedCreateFlash as flash } from './flash';
import axios from './lib/utils/axios_utils';
import { addDelimiter } from './lib/utils/text_utility';
-import { deprecatedCreateFlash as flash } from './flash';
-import CreateMergeRequestDropdown from './create_merge_request_dropdown';
-import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from './locale';
export default class Issue {
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index d569ad573a2..e70c18040b3 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -1,20 +1,20 @@
<script>
import { GlIcon, GlIntersectionObserver } from '@gitlab/ui';
import Visibility from 'visibilityjs';
-import { __, s__, sprintf } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { visitUrl } from '~/lib/utils/url_utility';
import Poll from '~/lib/utils/poll';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { __, s__, sprintf } from '~/locale';
+import recaptchaModalImplementor from '~/vue_shared/mixins/recaptcha_modal_implementor';
+import { IssuableStatus, IssuableStatusText, IssuableType } from '../constants';
import eventHub from '../event_hub';
import Service from '../services/index';
import Store from '../stores';
-import titleComponent from './title.vue';
import descriptionComponent from './description.vue';
import editedComponent from './edited.vue';
import formComponent from './form.vue';
import PinnedLinks from './pinned_links.vue';
-import recaptchaModalImplementor from '~/vue_shared/mixins/recaptcha_modal_implementor';
-import { IssuableStatus, IssuableStatusText, IssuableType } from '../constants';
+import titleComponent from './title.vue';
export default {
components: {
@@ -132,6 +132,10 @@ export default {
type: String,
required: true,
},
+ projectId: {
+ type: Number,
+ required: true,
+ },
projectNamespace: {
type: String,
required: true,
@@ -419,6 +423,7 @@ export default {
:markdown-docs-path="markdownDocsPath"
:markdown-preview-path="markdownPreviewPath"
:project-path="projectPath"
+ :project-id="projectId"
:project-namespace="projectNamespace"
:show-delete-button="showDeleteButton"
:can-attach-file="canAttachFile"
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 2a6468c783b..5416d3bebd0 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,11 +1,11 @@
<script>
-import $ from 'jquery';
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
+import $ from 'jquery';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import animateMixin from '../mixins/animate';
+import { s__, sprintf } from '~/locale';
import TaskList from '../../task_list';
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
+import animateMixin from '../mixins/animate';
export default {
directives: {
@@ -154,6 +154,7 @@ export default {
}"
class="md"
></div>
+ <!-- eslint-disable vue/no-mutating-props -->
<textarea
v-if="descriptionText"
ref="textarea"
@@ -163,6 +164,7 @@ export default {
dir="auto"
>
</textarea>
+ <!-- eslint-enable vue/no-mutating-props -->
<recaptcha-modal v-show="showRecaptcha" :html="recaptchaHTML" @close="closeRecaptcha" />
</div>
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 14ada5adcf6..dd378c40b46 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import updateMixin from '../mixins/update';
import eventHub from '../event_hub';
+import updateMixin from '../mixins/update';
const issuableTypes = {
issue: __('Issue'),
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 8d417e32d62..5476a1ef897 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -1,7 +1,7 @@
<script>
-import updateMixin from '../../mixins/update';
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: {
@@ -49,6 +49,7 @@ export default {
:textarea-value="formState.description"
>
<template #textarea>
+ <!-- eslint-disable vue/no-mutating-props -->
<textarea
id="issue-description"
ref="textarea"
@@ -62,6 +63,7 @@ export default {
@keydown.ctrl.enter="updateIssuable"
>
</textarea>
+ <!-- eslint-enable vue/no-mutating-props -->
</template>
</markdown-field>
</div>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
index 71299381aae..dbec6f15cab 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -1,6 +1,6 @@
<script>
-import $ from 'jquery';
import { GlIcon } from '@gitlab/ui';
+import $ from 'jquery';
import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
export default {
@@ -21,6 +21,10 @@ export default {
type: String,
required: true,
},
+ projectId: {
+ type: Number,
+ required: true,
+ },
projectNamespace: {
type: String,
required: true,
@@ -35,6 +39,7 @@ export default {
// Create the editor for the template
const editor = document.querySelector('.detail-page-description .note-textarea') || {};
editor.setValue = (val) => {
+ // eslint-disable-next-line vue/no-mutating-props
this.formState.description = val;
};
editor.getValue = () => this.formState.description;
@@ -48,11 +53,12 @@ export default {
</script>
<template>
- <div class="dropdown js-issuable-selector-wrap" data-issuable-type="issue">
+ <div class="dropdown js-issuable-selector-wrap" data-issuable-type="issues">
<button
ref="toggle"
:data-namespace-path="projectNamespace"
:data-project-path="projectPath"
+ :data-project-id="projectId"
:data-data="issuableTemplatesJson"
class="dropdown-menu-toggle js-issuable-selector"
type="button"
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue
index 34eb0451d53..d331fb47077 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issue_show/components/fields/title.vue
@@ -15,6 +15,7 @@ export default {
<template>
<fieldset>
<label class="sr-only" for="issuable-title">{{ __('Title') }}</label>
+ <!-- eslint-disable vue/no-mutating-props -->
<input
id="issuable-title"
ref="input"
@@ -27,5 +28,6 @@ export default {
@keydown.meta.enter="updateIssuable"
@keydown.ctrl.enter="updateIssuable"
/>
+ <!-- eslint-enable vue/no-mutating-props -->
</fieldset>
</template>
diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue
index d48bf1fe7a9..b7425448052 100644
--- a/app/assets/javascripts/issue_show/components/form.vue
+++ b/app/assets/javascripts/issue_show/components/form.vue
@@ -1,12 +1,12 @@
<script>
import $ from 'jquery';
-import lockedWarning from './locked_warning.vue';
-import titleField from './fields/title.vue';
-import descriptionField from './fields/description.vue';
-import editActions from './edit_actions.vue';
-import descriptionTemplate from './fields/description_template.vue';
import Autosave from '~/autosave';
import eventHub from '../event_hub';
+import editActions from './edit_actions.vue';
+import descriptionField from './fields/description.vue';
+import descriptionTemplate from './fields/description_template.vue';
+import titleField from './fields/title.vue';
+import lockedWarning from './locked_warning.vue';
export default {
components: {
@@ -46,6 +46,10 @@ export default {
type: String,
required: true,
},
+ projectId: {
+ type: Number,
+ required: true,
+ },
projectNamespace: {
type: String,
required: true,
@@ -127,6 +131,7 @@ export default {
:form-state="formState"
:issuable-templates="issuableTemplates"
:project-path="projectPath"
+ :project-id="projectId"
:project-namespace="projectNamespace"
/>
</div>
diff --git a/app/assets/javascripts/issue_show/components/header_actions.vue b/app/assets/javascripts/issue_show/components/header_actions.vue
index 998f740be0e..9c3988d0469 100644
--- a/app/assets/javascripts/issue_show/components/header_actions.vue
+++ b/app/assets/javascripts/issue_show/components/header_actions.vue
@@ -193,7 +193,7 @@ export default {
<template>
<div class="detail-page-header-actions">
<gl-dropdown
- class="gl-display-block gl-display-sm-none!"
+ class="gl-display-block gl-sm-display-none!"
block
:text="dropdownText"
:loading="isToggleStateButtonLoading"
@@ -222,7 +222,7 @@ export default {
<gl-button
v-if="showToggleIssueStateButton"
- class="gl-display-none gl-display-sm-inline-flex!"
+ class="gl-display-none gl-sm-display-inline-flex!"
category="secondary"
:data-qa-selector="qaSelector"
:loading="isToggleStateButtonLoading"
@@ -233,7 +233,7 @@ export default {
</gl-button>
<gl-dropdown
- class="gl-display-none gl-display-sm-inline-flex!"
+ class="gl-display-none gl-sm-display-inline-flex!"
toggle-class="gl-border-0! gl-shadow-none!"
no-caret
right
diff --git a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
index f9f06c3ad5a..84107d3eaca 100644
--- a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
+++ b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
@@ -1,13 +1,13 @@
<script>
import { GlTab, GlTabs } from '@gitlab/ui';
-import DescriptionComponent from '../description.vue';
-import HighlightBar from './highlight_bar.vue';
import createFlash from '~/flash';
+import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
import { s__ } from '~/locale';
-import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import Tracking from '~/tracking';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import DescriptionComponent from '../description.vue';
import getAlert from './graphql/queries/get_alert.graphql';
-import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
+import HighlightBar from './highlight_bar.vue';
export default {
components: {
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index b03a91716fe..806d95ca748 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import animateMixin from '../mixins/animate';
import eventHub from '../event_hub';
+import animateMixin from '../mixins/animate';
export default {
components: {
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
index ccac38811b5..0c81ecdc843 100644
--- a/app/assets/javascripts/issue_show/incident.js
+++ b/app/assets/javascripts/issue_show/incident.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
+import { parseBoolean } from '~/lib/utils/common_utils';
import issuableApp from './components/app.vue';
import incidentTabs from './components/incidents/incident_tabs.vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
index 83fd1355f26..a93abbf64df 100644
--- a/app/assets/javascripts/issue_show/issue.js
+++ b/app/assets/javascripts/issue_show/issue.js
@@ -54,6 +54,7 @@ export function initIssueHeaderActions(store) {
issueType: el.dataset.issueType,
newIssuePath: el.dataset.newIssuePath,
projectPath: el.dataset.projectPath,
+ projectId: el.dataset.projectId,
reportAbusePath: el.dataset.reportAbusePath,
submitAsSpamPath: el.dataset.submitAsSpamPath,
},
diff --git a/app/assets/javascripts/issue_show/utils/parse_data.js b/app/assets/javascripts/issue_show/utils/parse_data.js
index d5e7d2a8807..19d1e0eebcb 100644
--- a/app/assets/javascripts/issue_show/utils/parse_data.js
+++ b/app/assets/javascripts/issue_show/utils/parse_data.js
@@ -1,5 +1,5 @@
-import * as Sentry from '~/sentry/wrapper';
import { sanitize } from '~/lib/dompurify';
+import * as Sentry from '~/sentry/wrapper';
// We currently load + parse the data from the issue app and related merge request
let cachedParsedData;
diff --git a/app/assets/javascripts/issue_status_select.js b/app/assets/javascripts/issue_status_select.js
index 02b10730153..2ede0837930 100644
--- a/app/assets/javascripts/issue_status_select.js
+++ b/app/assets/javascripts/issue_status_select.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import { __ } from './locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from './locale';
export default function issueStatusSelect() {
$('.js-issue-status').each((i, el) => {
diff --git a/app/assets/javascripts/issues_list/components/issuable.vue b/app/assets/javascripts/issues_list/components/issuable.vue
index 3965fd6b0c7..b7af6e098e1 100644
--- a/app/assets/javascripts/issues_list/components/issuable.vue
+++ b/app/assets/javascripts/issues_list/components/issuable.vue
@@ -5,7 +5,7 @@
*/
// TODO: need to move this component to graphql - https://gitlab.com/gitlab-org/gitlab/-/issues/221246
-import { escape, isNumber } from 'lodash';
+import jiraLogo from '@gitlab/svgs/dist/illustrations/logos/jira.svg';
import {
GlLink,
GlTooltipDirective as GlTooltip,
@@ -14,7 +14,8 @@ import {
GlIcon,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
-import jiraLogo from '@gitlab/svgs/dist/illustrations/logos/jira.svg';
+import { escape, isNumber } from 'lodash';
+import { isScopedLabel } from '~/lib/utils/common_utils';
import {
dateInWords,
formatDate,
@@ -23,13 +24,11 @@ import {
timeFor,
newDateAsLocaleTime,
} from '~/lib/utils/datetime_utility';
+import { convertToCamelCase } from '~/lib/utils/text_utility';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
import { sprintf, __ } from '~/locale';
import initUserPopovers from '~/user_popovers';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-
-import { convertToCamelCase } from '~/lib/utils/text_utility';
export default {
i18n: {
@@ -414,7 +413,7 @@ export default {
v-if="meta.visible"
:key="meta.key"
v-gl-tooltip
- class="gl-display-none gl-display-sm-flex gl-align-items-center gl-ml-3"
+ class="gl-display-none gl-sm-display-flex gl-align-items-center gl-ml-3"
:class="meta.class"
:data-testid="meta.dataTestId"
:title="meta.title"
diff --git a/app/assets/javascripts/issues_list/components/issuables_list_app.vue b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
index eda8bc2b61f..0b413ce0b06 100644
--- a/app/assets/javascripts/issues_list/components/issuables_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
@@ -1,11 +1,11 @@
<script>
-import { toNumber, omit } from 'lodash';
import {
GlEmptyState,
GlPagination,
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
+import { toNumber, omit } from 'lodash';
import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import {
@@ -14,9 +14,9 @@ import {
historyPushState,
getParameterByName,
} from '~/lib/utils/common_utils';
+import { setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import initManualOrdering from '~/manual_ordering';
-import Issuable from './issuable.vue';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import {
sortOrderMap,
@@ -26,9 +26,9 @@ import {
PAGE_SIZE_MANUAL,
LOADING_LIST_ITEMS_LENGTH,
} from '../constants';
-import { setUrlParams } from '~/lib/utils/url_utility';
import issueableEventHub from '../eventhub';
import { emptyStateHelper } from '../service_desk_helper';
+import Issuable from './issuable.vue';
export default {
LOADING_LIST_ITEMS_LENGTH,
@@ -333,15 +333,19 @@ export default {
this.fetchIssuables();
},
handleFilter(filters) {
- let search = null;
+ const searchTokens = [];
filters.forEach((filter) => {
- if (typeof filter === 'string') {
- search = filter;
+ if (filter.type === 'filtered-search-term') {
+ if (filter.value.data) {
+ searchTokens.push(filter.value.data);
+ }
}
});
- this.filters.search = search;
+ if (searchTokens.length) {
+ this.filters.search = searchTokens.join(' ');
+ }
this.page = 1;
this.refetchIssuables();
diff --git a/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue b/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue
index 61781c576c0..7396cfe27b3 100644
--- a/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue
+++ b/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue
@@ -1,14 +1,14 @@
<script>
import { GlAlert, GlLabel } from '@gitlab/ui';
import { last } from 'lodash';
-import { n__ } from '~/locale';
-import getIssuesListDetailsQuery from '../queries/get_issues_list_details.query.graphql';
import {
calculateJiraImportLabel,
isInProgress,
setFinishedAlertHideMap,
shouldShowFinishedAlert,
} from '~/jira_import/utils/jira_import_utils';
+import { n__ } from '~/locale';
+import getIssuesListDetailsQuery from '../queries/get_issues_list_details.query.graphql';
export default {
name: 'JiraIssuesList',
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 42e97766b95..5c3910955bc 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -2,8 +2,8 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import JiraIssuesListRoot from './components/jira_issues_list_root.vue';
import IssuablesListApp from './components/issuables_list_app.vue';
+import JiraIssuesListRoot from './components/jira_issues_list_root.vue';
function mountJiraIssuesListApp() {
const el = document.querySelector('.js-projects-issues-root');
diff --git a/app/assets/javascripts/jira_connect/api.js b/app/assets/javascripts/jira_connect/api.js
index d689a2d1962..d78aba0a3f7 100644
--- a/app/assets/javascripts/jira_connect/api.js
+++ b/app/assets/javascripts/jira_connect/api.js
@@ -1,7 +1,23 @@
import axios from 'axios';
-const getJwt = async () => {
- return AP.context.getToken();
+export const getJwt = () => {
+ return new Promise((resolve) => {
+ AP.context.getToken((token) => {
+ resolve(token);
+ });
+ });
+};
+
+export const getLocation = () => {
+ return new Promise((resolve) => {
+ if (typeof AP.getLocation !== 'function') {
+ resolve();
+ }
+
+ AP.getLocation((location) => {
+ resolve(location);
+ });
+ });
};
export const addSubscription = async (addPath, namespace) => {
diff --git a/app/assets/javascripts/jira_connect/components/app.vue b/app/assets/javascripts/jira_connect/components/app.vue
index f5bf30f4488..a4ba86dc6a1 100644
--- a/app/assets/javascripts/jira_connect/components/app.vue
+++ b/app/assets/javascripts/jira_connect/components/app.vue
@@ -1,8 +1,10 @@
<script>
-import { mapState } from 'vuex';
import { GlAlert, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { getLocation } from '~/jira_connect/api';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
import GroupsList from './groups_list.vue';
export default {
@@ -17,17 +19,42 @@ export default {
GlModalDirective,
},
mixins: [glFeatureFlagsMixin()],
+ inject: {
+ usersPath: {
+ default: '',
+ },
+ },
+ data() {
+ return {
+ location: '',
+ };
+ },
computed: {
...mapState(['errorMessage']),
showNewUI() {
return this.glFeatures.newJiraConnectUi;
},
+ usersPathWithReturnTo() {
+ if (this.location) {
+ return `${this.usersPath}?return_to=${this.location}`;
+ }
+
+ return this.usersPath;
+ },
},
modal: {
cancelProps: {
text: __('Cancel'),
},
},
+ created() {
+ this.setLocation();
+ },
+ methods: {
+ async setLocation() {
+ this.location = await getLocation();
+ },
+ },
};
</script>
@@ -37,27 +64,40 @@ export default {
{{ errorMessage }}
</gl-alert>
- <h1>GitLab for Jira Configuration</h1>
+ <h2>{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
<div
v-if="showNewUI"
- class="gl-display-flex gl-justify-content-space-between gl-my-5 gl-pb-4 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
+ class="gl-display-flex gl-justify-content-space-between gl-my-7 gl-pb-4 gl-border-b-solid gl-border-b-1 gl-border-b-gray-200"
>
- <h3 data-testid="new-jira-connect-ui-heading">{{ s__('Integrations|Linked namespaces') }}</h3>
+ <h5 class="gl-align-self-center gl-mb-0" data-testid="new-jira-connect-ui-heading">
+ {{ s__('Integrations|Linked namespaces') }}
+ </h5>
<gl-button
- v-gl-modal-directive="'add-namespace-modal'"
+ v-if="usersPath"
category="primary"
variant="info"
class="gl-align-self-center"
- >{{ s__('Integrations|Add namespace') }}</gl-button
- >
- <gl-modal
- modal-id="add-namespace-modal"
- :title="s__('Integrations|Link namespaces')"
- :action-cancel="$options.modal.cancelProps"
+ :href="usersPathWithReturnTo"
+ target="_blank"
+ >{{ s__('Integrations|Sign in to add namespaces') }}</gl-button
>
- <groups-list />
- </gl-modal>
+ <template v-else>
+ <gl-button
+ v-gl-modal-directive="'add-namespace-modal'"
+ category="primary"
+ variant="info"
+ class="gl-align-self-center"
+ >{{ s__('Integrations|Add namespace') }}</gl-button
+ >
+ <gl-modal
+ modal-id="add-namespace-modal"
+ :title="s__('Integrations|Link namespaces')"
+ :action-cancel="$options.modal.cancelProps"
+ >
+ <groups-list />
+ </gl-modal>
+ </template>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jira_connect/components/groups_list.vue b/app/assets/javascripts/jira_connect/components/groups_list.vue
index eeddd32addc..69f2903388c 100644
--- a/app/assets/javascripts/jira_connect/components/groups_list.vue
+++ b/app/assets/javascripts/jira_connect/components/groups_list.vue
@@ -1,9 +1,9 @@
<script>
-import { GlTabs, GlTab, GlLoadingIcon, GlPagination } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import { GlTabs, GlTab, GlLoadingIcon, GlPagination, GlAlert } from '@gitlab/ui';
import { fetchGroups } from '~/jira_connect/api';
import { defaultPerPage } from '~/jira_connect/constants';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import GroupsListItem from './groups_list_item.vue';
export default {
@@ -12,6 +12,7 @@ export default {
GlTab,
GlLoadingIcon,
GlPagination,
+ GlAlert,
GroupsListItem,
},
inject: {
@@ -26,6 +27,7 @@ export default {
page: 1,
perPage: defaultPerPage,
totalItems: 0,
+ errorMessage: null,
};
},
mounted() {
@@ -46,8 +48,7 @@ export default {
this.groups = response.data;
})
.catch(() => {
- // eslint-disable-next-line no-alert
- alert(s__('Integrations|Failed to load namespaces. Please try again.'));
+ this.errorMessage = s__('Integrations|Failed to load namespaces. Please try again.');
})
.finally(() => {
this.isLoading = false;
@@ -58,31 +59,42 @@ export default {
</script>
<template>
- <gl-tabs>
- <gl-tab :title="__('Groups and subgroups')" class="gl-pt-3">
- <gl-loading-icon v-if="isLoading" size="md" />
- <div v-else-if="groups.length === 0" class="gl-text-center">
- <h5>{{ s__('Integrations|No available namespaces.') }}</h5>
- <p class="gl-mt-5">
- {{
- s__('Integrations|You must have owner or maintainer permissions to link namespaces.')
- }}
- </p>
- </div>
- <ul v-else class="gl-list-style-none gl-pl-0">
- <groups-list-item v-for="group in groups" :key="group.id" :group="group" />
- </ul>
+ <div>
+ <gl-alert v-if="errorMessage" class="gl-mb-6" variant="danger" @dismiss="errorMessage = null">
+ {{ errorMessage }}
+ </gl-alert>
+
+ <gl-tabs>
+ <gl-tab :title="__('Groups and subgroups')" class="gl-pt-3">
+ <gl-loading-icon v-if="isLoading" size="md" />
+ <div v-else-if="groups.length === 0" class="gl-text-center">
+ <h5>{{ s__('Integrations|No available namespaces.') }}</h5>
+ <p class="gl-mt-5">
+ {{
+ s__('Integrations|You must have owner or maintainer permissions to link namespaces.')
+ }}
+ </p>
+ </div>
+ <ul v-else class="gl-list-style-none gl-pl-0">
+ <groups-list-item
+ v-for="group in groups"
+ :key="group.id"
+ :group="group"
+ @error="errorMessage = $event"
+ />
+ </ul>
- <div class="gl-display-flex gl-justify-content-center gl-mt-5">
- <gl-pagination
- v-if="totalItems > perPage && groups.length > 0"
- v-model="page"
- class="gl-mb-0"
- :per-page="perPage"
- :total-items="totalItems"
- @input="loadGroups"
- />
- </div>
- </gl-tab>
- </gl-tabs>
+ <div class="gl-display-flex gl-justify-content-center gl-mt-5">
+ <gl-pagination
+ v-if="totalItems > perPage && groups.length > 0"
+ v-model="page"
+ class="gl-mb-0"
+ :per-page="perPage"
+ :total-items="totalItems"
+ @input="loadGroups"
+ />
+ </div>
+ </gl-tab>
+ </gl-tabs>
+ </div>
</template>
diff --git a/app/assets/javascripts/jira_connect/components/groups_list_item.vue b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
index 15e37ab3cb0..69b09ab0a21 100644
--- a/app/assets/javascripts/jira_connect/components/groups_list_item.vue
+++ b/app/assets/javascripts/jira_connect/components/groups_list_item.vue
@@ -1,10 +1,18 @@
<script>
-import { GlIcon, GlAvatar } from '@gitlab/ui';
+import { GlAvatar, GlButton, GlIcon } from '@gitlab/ui';
+import { addSubscription } from '~/jira_connect/api';
+import { s__ } from '~/locale';
export default {
components: {
- GlIcon,
GlAvatar,
+ GlButton,
+ GlIcon,
+ },
+ inject: {
+ subscriptionsPath: {
+ default: '',
+ },
},
props: {
group: {
@@ -12,6 +20,31 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ isLoading: false,
+ };
+ },
+ methods: {
+ onClick() {
+ this.isLoading = true;
+
+ addSubscription(this.subscriptionsPath, this.group.full_path)
+ .then(() => {
+ AP.navigator.reload();
+ })
+ .catch((error) => {
+ this.$emit(
+ 'error',
+ error?.response?.data?.error ||
+ s__('Integrations|Failed to link namespace. Please try again.'),
+ );
+ })
+ .finally(() => {
+ this.isLoading = false;
+ });
+ },
+ },
};
</script>
@@ -19,7 +52,7 @@ export default {
<li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-200">
<div class="gl-display-flex gl-align-items-center gl-py-3">
<gl-icon name="folder-o" class="gl-mr-3" />
- <div class="gl-display-none gl-flex-shrink-0 gl-display-sm-flex gl-mr-3">
+ <div class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3">
<gl-avatar :size="32" shape="rect" :entity-name="group.name" :src="group.avatar_url" />
</div>
<div class="gl-min-w-0 gl-display-flex gl-flex-grow-1 gl-flex-shrink-1 gl-align-items-center">
@@ -36,6 +69,14 @@ export default {
<p class="gl-mt-2! gl-mb-0 gl-text-gray-600" v-text="group.description"></p>
</div>
</div>
+
+ <gl-button
+ category="secondary"
+ variant="success"
+ :loading="isLoading"
+ @click.prevent="onClick"
+ >{{ __('Link') }}</gl-button
+ >
</div>
</div>
</li>
diff --git a/app/assets/javascripts/jira_connect/index.js b/app/assets/javascripts/jira_connect/index.js
index dc2a77f4e0c..7191fce3c33 100644
--- a/app/assets/javascripts/jira_connect/index.js
+++ b/app/assets/javascripts/jira_connect/index.js
@@ -1,70 +1,73 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import $ from 'jquery';
import setConfigs from '@gitlab/ui/dist/config';
-import Translate from '~/vue_shared/translate';
+import Vue from 'vue';
+import { addSubscription, removeSubscription, getLocation } from '~/jira_connect/api';
import GlFeatureFlagsPlugin from '~/vue_shared/gl_feature_flags_plugin';
+import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
-import { addSubscription, removeSubscription } from '~/jira_connect/api';
import createStore from './store';
import { SET_ERROR_MESSAGE } from './store/mutation_types';
-Vue.use(Vuex);
-
const store = createStore();
-/**
- * Initialize form handlers for the Jira Connect app
- */
-const initJiraFormHandlers = () => {
- const reqComplete = () => {
- AP.navigator.reload();
- };
-
- const reqFailed = (res, fallbackErrorMessage) => {
- const { error = fallbackErrorMessage } = res || {};
-
- store.commit(SET_ERROR_MESSAGE, error);
- };
-
- if (typeof AP.getLocation === 'function') {
- AP.getLocation((location) => {
- $('.js-jira-connect-sign-in').each(function updateSignInLink() {
- const updatedLink = `${$(this).attr('href')}?return_to=${location}`;
- $(this).attr('href', updatedLink);
- });
- });
- }
+const reqComplete = () => {
+ AP.navigator.reload();
+};
- $('#add-subscription-form').on('submit', function onAddSubscriptionForm(e) {
- const addPath = $(this).attr('action');
- const namespace = $('#namespace-input').val();
+const reqFailed = (res, fallbackErrorMessage) => {
+ const { error = fallbackErrorMessage } = res || {};
- e.preventDefault();
+ store.commit(SET_ERROR_MESSAGE, error);
+};
- addSubscription(addPath, namespace)
- .then(reqComplete)
- .catch((err) => reqFailed(err.response.data, 'Failed to add namespace. Please try again.'));
+const updateSignInLinks = async () => {
+ const location = await getLocation();
+ Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
+ const updatedLink = `${el.getAttribute('href')}?return_to=${location}`;
+ el.setAttribute('href', updatedLink);
});
+};
+
+const initRemoveSubscriptionButtonHandlers = () => {
+ Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach((el) => {
+ el.addEventListener('click', function onRemoveSubscriptionClick(e) {
+ e.preventDefault();
+
+ const removePath = e.target.getAttribute('href');
+ removeSubscription(removePath)
+ .then(reqComplete)
+ .catch((err) =>
+ reqFailed(err.response.data, 'Failed to remove namespace. Please try again.'),
+ );
+ });
+ });
+};
+
+const initAddSubscriptionFormHandler = () => {
+ const formEl = document.querySelector('#add-subscription-form');
+ if (!formEl) {
+ return;
+ }
- $('.remove-subscription').on('click', function onRemoveSubscriptionClick(e) {
- const removePath = $(this).attr('href');
+ formEl.addEventListener('submit', function onAddSubscriptionForm(e) {
e.preventDefault();
- removeSubscription(removePath)
+ const addPath = e.target.getAttribute('action');
+ const namespace = (e.target.querySelector('#namespace-input') || {}).value;
+
+ addSubscription(addPath, namespace)
.then(reqComplete)
- .catch((err) =>
- reqFailed(err.response.data, 'Failed to remove namespace. Please try again.'),
- );
+ .catch((err) => reqFailed(err.response.data, 'Failed to add namespace. Please try again.'));
});
};
-function initJiraConnect() {
- const el = document.querySelector('.js-jira-connect-app');
+export async function initJiraConnect() {
+ initAddSubscriptionFormHandler();
+ initRemoveSubscriptionButtonHandlers();
- initJiraFormHandlers();
+ await updateSignInLinks();
+ const el = document.querySelector('.js-jira-connect-app');
if (!el) {
return null;
}
@@ -73,13 +76,15 @@ function initJiraConnect() {
Vue.use(Translate);
Vue.use(GlFeatureFlagsPlugin);
- const { groupsPath } = el.dataset;
+ const { groupsPath, subscriptionsPath, usersPath } = el.dataset;
return new Vue({
el,
store,
provide: {
groupsPath,
+ subscriptionsPath,
+ usersPath,
},
render(createElement) {
return createElement(JiraConnectApp);
diff --git a/app/assets/javascripts/jira_connect/store/index.js b/app/assets/javascripts/jira_connect/store/index.js
index aa7e14269a4..de830e3891a 100644
--- a/app/assets/javascripts/jira_connect/store/index.js
+++ b/app/assets/javascripts/jira_connect/store/index.js
@@ -1,9 +1,12 @@
+import Vue from 'vue';
import Vuex from 'vuex';
import mutations from './mutations';
import state from './state';
+Vue.use(Vuex);
+
export default () =>
new Vuex.Store({
- state,
mutations,
+ state,
});
diff --git a/app/assets/javascripts/jira_import/components/jira_import_form.vue b/app/assets/javascripts/jira_import/components/jira_import_form.vue
index ab475c3c85a..6f2fb41ca15 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_form.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue
@@ -15,10 +15,11 @@ import {
GlTable,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import axios from '~/lib/utils/axios_utils';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import getJiraUserMappingMutation from '../queries/get_jira_user_mapping.mutation.graphql';
import initiateJiraImportMutation from '../queries/initiate_jira_import.mutation.graphql';
+import searchProjectMembersQuery from '../queries/search_project_members.query.graphql';
import { addInProgressImportToStore } from '../utils/cache_update';
import {
debounceWait,
@@ -155,19 +156,23 @@ export default {
});
},
searchUsers() {
- const params = {
- active: true,
- project_id: this.projectId,
- search: this.searchTerm,
- };
-
this.isFetching = true;
- return axios
- .get('/-/autocomplete/users.json', { params })
+ return this.$apollo
+ .query({
+ query: searchProjectMembersQuery,
+ variables: {
+ fullPath: this.projectPath,
+ search: this.searchTerm,
+ },
+ })
.then(({ data }) => {
- this.users = data;
- return data;
+ this.users =
+ data?.project?.projectMembers?.nodes?.map(({ user }) => ({
+ ...user,
+ id: getIdFromGraphQLId(user.id),
+ })) || [];
+ return this.users;
})
.finally(() => {
this.isFetching = false;
diff --git a/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql b/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
new file mode 100644
index 00000000000..06f119e75ed
--- /dev/null
+++ b/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
@@ -0,0 +1,13 @@
+query searchProjectMembers($fullPath: ID!, $search: String) {
+ project(fullPath: $fullPath) {
+ projectMembers(search: $search) {
+ nodes {
+ user {
+ id
+ name
+ username
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/jobs/components/artifacts_block.vue b/app/assets/javascripts/jobs/components/artifacts_block.vue
index 2850a8e86fd..0f34926f689 100644
--- a/app/assets/javascripts/jobs/components/artifacts_block.vue
+++ b/app/assets/javascripts/jobs/components/artifacts_block.vue
@@ -1,13 +1,15 @@
<script>
-import { GlIcon, GlLink } from '@gitlab/ui';
+import { GlButton, GlButtonGroup, GlIcon, GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
components: {
- TimeagoTooltip,
+ GlButton,
+ GlButtonGroup,
GlIcon,
GlLink,
+ TimeagoTooltip,
},
mixins: [timeagoMixin],
props: {
@@ -36,7 +38,7 @@ export default {
</script>
<template>
<div class="block">
- <div class="title font-weight-bold">{{ s__('Job|Job artifacts') }}</div>
+ <div class="title gl-font-weight-bold">{{ s__('Job|Job artifacts') }}</div>
<p
v-if="isExpired || willExpire"
class="build-detail-row"
@@ -61,32 +63,29 @@ export default {
)
}}</span>
</p>
- <div class="btn-group d-flex gl-mt-3" role="group">
- <gl-link
+ <gl-button-group class="gl-display-flex gl-mt-3">
+ <gl-button
v-if="artifact.keep_path"
:href="artifact.keep_path"
- class="btn btn-sm btn-default"
data-method="post"
data-testid="keep-artifacts"
- >{{ s__('Job|Keep') }}</gl-link
+ >{{ s__('Job|Keep') }}</gl-button
>
- <gl-link
+ <gl-button
v-if="artifact.download_path"
:href="artifact.download_path"
- class="btn btn-sm btn-default"
- download
rel="nofollow"
data-testid="download-artifacts"
- >{{ s__('Job|Download') }}</gl-link
+ download
+ >{{ s__('Job|Download') }}</gl-button
>
- <gl-link
+ <gl-button
v-if="artifact.browse_path"
:href="artifact.browse_path"
- class="btn btn-sm btn-default"
data-testid="browse-artifacts"
data-qa-selector="browse_artifacts_button"
- >{{ s__('Job|Browse') }}</gl-link
+ >{{ s__('Job|Browse') }}</gl-button
>
- </div>
+ </gl-button-group>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/empty_state.vue b/app/assets/javascripts/jobs/components/empty_state.vue
index 0ee8cd6c5ad..35b16d73cc7 100644
--- a/app/assets/javascripts/jobs/components/empty_state.vue
+++ b/app/assets/javascripts/jobs/components/empty_state.vue
@@ -85,7 +85,7 @@ export default {
<gl-link
:href="action.path"
:data-method="action.method"
- class="btn btn-primary"
+ class="btn gl-button btn-confirm gl-text-decoration-none!"
data-testid="job-empty-state-action"
>{{ action.button_title }}</gl-link
>
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue
index ec7868d9235..9d451f94e8a 100644
--- a/app/assets/javascripts/jobs/components/environments_block.vue
+++ b/app/assets/javascripts/jobs/components/environments_block.vue
@@ -1,6 +1,6 @@
<script>
-import { isEmpty } from 'lodash';
import { GlSprintf, GlLink } from '@gitlab/ui';
+import { isEmpty } from 'lodash';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { __ } from '../../locale';
@@ -201,9 +201,7 @@ export default {
/>
<template v-else>{{ clusterNameOrLink.name }}</template>
</template>
- <template #kubernetesNamespace>
- <template>{{ kubernetesNamespace }}</template>
- </template>
+ <template #kubernetesNamespace>{{ kubernetesNamespace }}</template>
<template #deploymentLink>
<gl-link
:href="deploymentLink.path"
diff --git a/app/assets/javascripts/jobs/components/erased_block.vue b/app/assets/javascripts/jobs/components/erased_block.vue
index a6d1b41c275..a815689659e 100644
--- a/app/assets/javascripts/jobs/components/erased_block.vue
+++ b/app/assets/javascripts/jobs/components/erased_block.vue
@@ -1,12 +1,14 @@
<script>
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash';
-import { GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
- TimeagoTooltip,
+ GlAlert,
GlLink,
+ GlSprintf,
+ TimeagoTooltip,
},
props: {
user: {
@@ -27,17 +29,21 @@ export default {
};
</script>
<template>
- <div class="gl-mt-3 js-build-erased">
- <div class="erased alert alert-warning">
+ <div class="gl-mt-3">
+ <gl-alert variant="warning" :dismissible="false">
<template v-if="isErasedByUser">
- {{ s__('Job|Job has been erased by') }}
- <gl-link :href="user.web_url"> {{ user.username }} </gl-link>
+ <gl-sprintf :message="s__('Job|Job has been erased by %{userLink}')">
+ <template #userLink>
+ <gl-link :href="user.web_url" target="_blank">{{ user.username }}</gl-link>
+ </template>
+ </gl-sprintf>
</template>
+
<template v-else>
{{ s__('Job|Job has been erased') }}
</template>
<timeago-tooltip :time="erasedAt" />
- </div>
+ </gl-alert>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index b0ba6ce52d1..91ab68d5f39 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -1,21 +1,20 @@
<script>
-import { throttle, isEmpty } from 'lodash';
-import { mapGetters, mapState, mapActions } from 'vuex';
import { GlLoadingIcon, GlIcon, GlSafeHtmlDirective as SafeHtml, GlAlert } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import { throttle, isEmpty } from 'lodash';
+import { mapGetters, mapState, mapActions } from 'vuex';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
-import { polyfillSticky } from '~/lib/utils/sticky';
+import { sprintf } from '~/locale';
import CiHeader from '~/vue_shared/components/header_ci_component.vue';
+import delayedJobMixin from '../mixins/delayed_job_mixin';
import EmptyState from './empty_state.vue';
import EnvironmentsBlock from './environments_block.vue';
import ErasedBlock from './erased_block.vue';
import LogTopBar from './job_log_controllers.vue';
+import Log from './log/log.vue';
+import Sidebar from './sidebar.vue';
import StuckBlock from './stuck_block.vue';
import UnmetPrerequisitesBlock from './unmet_prerequisites_block.vue';
-import Sidebar from './sidebar.vue';
-import { sprintf } from '~/locale';
-import delayedJobMixin from '../mixins/delayed_job_mixin';
-import Log from './log/log.vue';
export default {
name: 'JobPageApp',
@@ -54,11 +53,6 @@ export default {
required: false,
default: null,
},
- runnerHelpUrl: {
- type: String,
- required: false,
- default: null,
- },
deploymentHelpUrl: {
type: String,
required: false,
@@ -140,14 +134,6 @@ export default {
this.fetchJobsForStage(defaultStage);
}
}
-
- if (newVal.archived) {
- this.$nextTick(() => {
- if (this.$refs.sticky) {
- polyfillSticky(this.$refs.sticky);
- }
- });
- }
},
},
created() {
@@ -250,7 +236,6 @@ export default {
v-if="shouldRenderSharedRunnerLimitWarning"
:quota-used="job.runners.quota.used"
:quota-limit="job.runners.quota.limit"
- :runners-path="runnerHelpUrl"
:project-path="projectPath"
:subscriptions-more-minutes-url="subscriptionsMoreMinutesUrl"
/>
@@ -271,7 +256,6 @@ export default {
<div
v-if="job.archived"
- ref="sticky"
class="gl-mt-3 archived-job"
:class="{ 'sticky-top border-bottom-0': hasTrace }"
data-testid="archived-job"
@@ -330,7 +314,6 @@ export default {
'right-sidebar-collapsed': !isSidebarOpen,
}"
:artifact-help-url="artifactHelpUrl"
- :runner-help-url="runnerHelpUrl"
data-testid="job-sidebar"
/>
</div>
diff --git a/app/assets/javascripts/jobs/components/job_container_item.vue b/app/assets/javascripts/jobs/components/job_container_item.vue
index 6b61dc5902b..e68368919ab 100644
--- a/app/assets/javascripts/jobs/components/job_container_item.vue
+++ b/app/assets/javascripts/jobs/components/job_container_item.vue
@@ -1,8 +1,8 @@
<script>
import { GlLink, GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { sprintf } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
export default {
components: {
@@ -51,7 +51,7 @@ export default {
v-gl-tooltip
:href="job.status.details_path"
:title="tooltipText"
- class="js-job-link d-flex"
+ class="js-job-link gl-display-flex gl-align-items-center"
>
<gl-icon
v-if="isActive"
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 7e7d9a0549b..fbdbfddff56 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,7 +1,6 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
-import { polyfillSticky } from '~/lib/utils/sticky';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __, sprintf } from '~/locale';
import scrollDown from '../svg/scroll_down.svg';
@@ -54,9 +53,6 @@ export default {
});
},
},
- mounted() {
- polyfillSticky(this.$el);
- },
methods: {
handleScrollToTop() {
this.$emit('scrollJobLogTop');
diff --git a/app/assets/javascripts/jobs/components/log/duration_badge.vue b/app/assets/javascripts/jobs/components/log/duration_badge.vue
index 8e5dcdcc902..54b76fd9edd 100644
--- a/app/assets/javascripts/jobs/components/log/duration_badge.vue
+++ b/app/assets/javascripts/jobs/components/log/duration_badge.vue
@@ -1,5 +1,10 @@
<script>
+import { GlBadge } from '@gitlab/ui';
+
export default {
+ components: {
+ GlBadge,
+ },
props: {
duration: {
type: String,
@@ -9,7 +14,7 @@ export default {
};
</script>
<template>
- <div class="log-duration-badge rounded align-self-start px-2 ml-2 flex-shrink-0 ws-normal">
+ <gl-badge>
{{ duration }}
- </div>
+ </gl-badge>
</template>
diff --git a/app/assets/javascripts/jobs/components/log/line_header.vue b/app/assets/javascripts/jobs/components/log/line_header.vue
index 4c1c00cb2a7..3bb1f58573c 100644
--- a/app/assets/javascripts/jobs/components/log/line_header.vue
+++ b/app/assets/javascripts/jobs/components/log/line_header.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon } from '@gitlab/ui';
-import LineNumber from './line_number.vue';
import DurationBadge from './duration_badge.vue';
+import LineNumber from './line_number.vue';
export default {
components: {
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index 24276cbe60a..a1f4f7abb77 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -1,8 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlButton } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
-import { GlButton } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
export default {
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 0789bb54f0f..f63fe72a71a 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -1,17 +1,17 @@
<script>
+import { GlButton, GlIcon, GlLink } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlButton, GlIcon, GlLink } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import { JOB_SIDEBAR } from '../constants';
import ArtifactsBlock from './artifacts_block.vue';
-import JobSidebarRetryButton from './job_sidebar_retry_button.vue';
-import JobRetryForwardDeploymentModal from './job_retry_forward_deployment_modal.vue';
-import TriggerBlock from './trigger_block.vue';
import CommitBlock from './commit_block.vue';
-import StagesDropdown from './stages_dropdown.vue';
+import JobRetryForwardDeploymentModal from './job_retry_forward_deployment_modal.vue';
+import JobSidebarRetryButton from './job_sidebar_retry_button.vue';
import JobsContainer from './jobs_container.vue';
import JobSidebarDetailsContainer from './sidebar_job_details_container.vue';
-import { JOB_SIDEBAR } from '../constants';
+import StagesDropdown from './stages_dropdown.vue';
+import TriggerBlock from './trigger_block.vue';
export const forwardDeploymentFailureModalId = 'forward-deployment-failure';
@@ -41,19 +41,14 @@ export default {
required: false,
default: '',
},
- runnerHelpUrl: {
- type: String,
- required: false,
- default: '',
- },
},
computed: {
...mapGetters(['hasForwardDeploymentFailure']),
...mapState(['job', 'stages', 'jobs', 'selectedStage']),
retryButtonClass() {
- let className = 'btn btn-retry';
+ let className = 'btn gl-button gl-text-decoration-none!';
className +=
- this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
+ this.job.status && this.job.recoverable ? ' btn-confirm' : ' btn-confirm-secondary';
return className;
},
hasArtifact() {
@@ -99,7 +94,7 @@ export default {
<gl-link
v-if="job.cancel_path"
:href="job.cancel_path"
- class="btn btn-default"
+ class="btn gl-button btn-default gl-text-decoration-none!"
data-method="post"
data-testid="cancel-button"
rel="nofollow"
@@ -110,7 +105,7 @@ export default {
<gl-button
:aria-label="$options.i18n.toggleSidebar"
category="tertiary"
- class="gl-display-md-none gl-ml-2 js-sidebar-build-toggle"
+ class="gl-md-display-none gl-ml-2 js-sidebar-build-toggle"
icon="chevron-double-lg-right"
@click="toggleSidebar"
/>
@@ -120,7 +115,7 @@ export default {
<gl-link
v-if="job.new_issue_path"
:href="job.new_issue_path"
- class="btn btn-success btn-inverted float-left mr-2"
+ class="btn gl-button btn-success-secondary float-left mr-2 gl-text-decoration-none!"
data-testid="job-new-issue"
>{{ $options.i18n.newIssue }}
</gl-link>
@@ -135,7 +130,7 @@ export default {
<gl-icon :size="14" name="external-link" />
</gl-link>
</div>
- <job-sidebar-details-container :runner-help-url="runnerHelpUrl" />
+ <job-sidebar-details-container />
<artifacts-block v-if="hasArtifact" :artifact="job.artifact" :help-url="artifactHelpUrl" />
<trigger-block v-if="hasTriggers" :trigger="job.trigger" />
<commit-block
diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
index 7d541f93bad..05567328660 100644
--- a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
@@ -34,12 +34,12 @@ export default {
};
</script>
<template>
- <p class="build-detail-row">
- <span v-if="hasTitle" class="font-weight-bold">{{ title }}:</span> {{ value }}
- <span v-if="hasHelpURL" class="help-button float-right">
- <gl-link :href="helpUrl" target="_blank" rel="noopener noreferrer nofollow">
- <gl-icon name="question-o" />
- </gl-link>
- </span>
+ <p class="gl-display-flex gl-justify-content-space-between gl-mb-2">
+ <span v-if="hasTitle"
+ ><b>{{ title }}:</b> {{ value }}</span
+ >
+ <gl-link v-if="hasHelpURL" :href="helpUrl" target="_blank">
+ <gl-icon name="question-o" />
+ </gl-link>
</p>
</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
index 8ad1008278e..62cd30fb320 100644
--- a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
@@ -1,9 +1,10 @@
<script>
import { mapState } from 'vuex';
-import DetailRow from './sidebar_detail_row.vue';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
+import DetailRow from './sidebar_detail_row.vue';
export default {
name: 'JobSidebarDetailsContainer',
@@ -11,13 +12,6 @@ export default {
DetailRow,
},
mixins: [timeagoMixin],
- props: {
- runnerHelpUrl: {
- type: String,
- required: false,
- default: '',
- },
- },
computed: {
...mapState(['job']),
coverage() {
@@ -51,6 +45,11 @@ export default {
queued() {
return timeIntervalInWords(this.job.queued);
},
+ runnerHelpUrl() {
+ return helpPagePath('ci/runners/README.html', {
+ anchor: 'set-maximum-job-timeout-for-a-runner',
+ });
+ },
runnerId() {
return `${this.job.runner.description} (#${this.job.runner.id})`;
},
@@ -96,7 +95,12 @@ export default {
<p v-if="hasTags" class="build-detail-row" data-testid="job-tags">
<span class="font-weight-bold">{{ __('Tags:') }}</span>
- <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary mr-1">{{ tag }}</span>
+ <span
+ v-for="(tag, i) in job.tags"
+ :key="i"
+ class="badge badge-pill badge-primary gl-badge sm"
+ >{{ tag }}</span
+ >
</p>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 7d4fe0a0680..64c4031b002 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -1,6 +1,6 @@
<script>
-import { isEmpty } from 'lodash';
import { GlLink, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { isEmpty } from 'lodash';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
export default {
diff --git a/app/assets/javascripts/jobs/components/stuck_block.vue b/app/assets/javascripts/jobs/components/stuck_block.vue
index 8e8202246a2..abd0c13702a 100644
--- a/app/assets/javascripts/jobs/components/stuck_block.vue
+++ b/app/assets/javascripts/jobs/components/stuck_block.vue
@@ -1,6 +1,6 @@
<script>
import { GlAlert, GlBadge, GlLink } from '@gitlab/ui';
-import { s__ } from '../../locale';
+import { s__ } from '~/locale';
/**
* Renders Stuck Runners block for job's view.
*/
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index 1d46dd8cea4..f6b98777011 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -1,12 +1,31 @@
<script>
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlTable } from '@gitlab/ui';
import { __ } from '~/locale';
-const HIDDEN_VALUE = '••••••';
+const DEFAULT_TD_CLASSES = 'gl-w-half gl-font-sm! gl-border-gray-200!';
+const DEFAULT_TH_CLASSES =
+ 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-200! gl-border-b-1!';
export default {
+ fields: [
+ {
+ key: 'key',
+ label: __('Key'),
+ tdAttr: { 'data-testid': 'trigger-build-key' },
+ tdClass: DEFAULT_TD_CLASSES,
+ thClass: DEFAULT_TH_CLASSES,
+ },
+ {
+ key: 'value',
+ label: __('Value'),
+ tdAttr: { 'data-testid': 'trigger-build-value' },
+ tdClass: DEFAULT_TD_CLASSES,
+ thClass: DEFAULT_TH_CLASSES,
+ },
+ ],
components: {
GlButton,
+ GlTable,
},
props: {
trigger: {
@@ -21,7 +40,7 @@ export default {
},
computed: {
hasVariables() {
- return this.trigger.variables && this.trigger.variables.length > 0;
+ return this.trigger.variables.length > 0;
},
getToggleButtonText() {
return this.showVariableValues ? __('Hide values') : __('Reveal values');
@@ -35,45 +54,41 @@ export default {
this.showVariableValues = !this.showVariableValues;
},
getDisplayValue(value) {
- return this.showVariableValues ? value : HIDDEN_VALUE;
+ return this.showVariableValues ? value : '••••••';
},
},
};
</script>
<template>
- <div class="build-widget block">
+ <div class="block">
<p
v-if="trigger.short_token"
- class="js-short-token"
:class="{ 'gl-mb-2': hasVariables, 'gl-mb-0': !hasVariables }"
+ data-testid="trigger-short-token"
>
- <span class="font-weight-bold">{{ __('Trigger token:') }}</span> {{ trigger.short_token }}
+ <span class="gl-font-weight-bold">{{ __('Trigger token:') }}</span> {{ trigger.short_token }}
</p>
<template v-if="hasVariables">
- <p class="trigger-variables-btn-container d-flex">
- <span class="font-weight-bold">{{ __('Trigger variables:') }}</span>
+ <p class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
+ <span class="gl-font-weight-bold">{{ __('Trigger variables:') }}</span>
<gl-button
v-if="hasValues"
- class="group js-reveal-variables trigger-variables-btn"
+ class="gl-mt-2"
size="small"
+ data-testid="trigger-reveal-values-button"
@click="toggleValues"
>{{ getToggleButtonText }}</gl-button
>
</p>
- <table class="js-build-variables trigger-build-variables">
- <tr v-for="(variable, index) in trigger.variables" :key="`${variable.key}-${index}`">
- <td class="js-build-variable trigger-build-variable trigger-variables-table-cell">
- {{ variable.key }}
- </td>
- <td class="js-build-value trigger-build-value trigger-variables-table-cell">
- {{ getDisplayValue(variable.value) }}
- </td>
- </tr>
- </table>
+ <gl-table :items="trigger.variables" :fields="$options.fields" small bordered>
+ <template #cell(value)="data">
+ {{ getDisplayValue(data.value) }}
+ </template>
+ </gl-table>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/index.js b/app/assets/javascripts/jobs/index.js
index 1ad6292a030..3e00056ee81 100644
--- a/app/assets/javascripts/jobs/index.js
+++ b/app/assets/javascripts/jobs/index.js
@@ -13,7 +13,6 @@ export default () => {
const {
artifactHelpUrl,
deploymentHelpUrl,
- runnerHelpUrl,
runnerSettingsUrl,
variablesSettingsUrl,
subscriptionsMoreMinutesUrl,
@@ -39,7 +38,6 @@ export default () => {
props: {
artifactHelpUrl,
deploymentHelpUrl,
- runnerHelpUrl,
runnerSettingsUrl,
variablesSettingsUrl,
subscriptionsMoreMinutesUrl,
diff --git a/app/assets/javascripts/jobs/store/actions.js b/app/assets/javascripts/jobs/store/actions.js
index e76a3693db9..c89aeada69d 100644
--- a/app/assets/javascripts/jobs/store/actions.js
+++ b/app/assets/javascripts/jobs/store/actions.js
@@ -1,10 +1,9 @@
import Visibility from 'visibilityjs';
-import * as types from './mutation_types';
+import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon';
-import { deprecatedCreateFlash as flash } from '~/flash';
-import { __ } from '~/locale';
+import httpStatusCodes from '~/lib/utils/http_status';
+import Poll from '~/lib/utils/poll';
import {
canScroll,
isScrolledToBottom,
@@ -13,7 +12,8 @@ import {
scrollDown,
scrollUp,
} from '~/lib/utils/scroll_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
+import { __ } from '~/locale';
+import * as types from './mutation_types';
export const init = ({ dispatch }, { endpoint, logState, pagePath }) => {
dispatch('setJobEndpoint', endpoint);
diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js
index 30a4a247dc4..930a225857d 100644
--- a/app/assets/javascripts/jobs/store/getters.js
+++ b/app/assets/javascripts/jobs/store/getters.js
@@ -1,7 +1,7 @@
import { isEmpty, isString } from 'lodash';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
-export const headerTime = (state) => (state.job.started ? state.job.started : state.job.created_at);
+export const headerTime = (state) => state.job.started ?? state.job.created_at;
export const hasForwardDeploymentFailure = (state) =>
state?.job?.failure_reason === 'forward_deployment_failure';
@@ -28,11 +28,9 @@ export const hasEnvironment = (state) => !isEmpty(state.job.deployment_status);
export const hasTrace = (state) =>
state.job.has_trace || (!isEmpty(state.job.status) && state.job.status.group === 'running');
-export const emptyStateIllustration = (state) =>
- (state.job && state.job.status && state.job.status.illustration) || {};
+export const emptyStateIllustration = (state) => state?.job?.status?.illustration || {};
-export const emptyStateAction = (state) =>
- (state.job && state.job.status && state.job.status.action) || null;
+export const emptyStateAction = (state) => state?.job?.status?.action || null;
/**
* Shared runners limit is only rendered when
@@ -48,4 +46,4 @@ export const shouldRenderSharedRunnerLimitWarning = (state) =>
export const isScrollingDown = (state) => isScrolledToBottom() && !state.isTraceComplete;
export const hasRunnersForProject = (state) =>
- state.job.runners.available && !state.job.runners.online;
+ state?.job?.runners?.available && !state?.job?.runners?.online;
diff --git a/app/assets/javascripts/jobs/store/index.js b/app/assets/javascripts/jobs/store/index.js
index bba01426af7..467c692b438 100644
--- a/app/assets/javascripts/jobs/store/index.js
+++ b/app/assets/javascripts/jobs/store/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from './state';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
+import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index 92dffb87e1a..2a020a66fd2 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -2,11 +2,10 @@
import $ from 'jquery';
import Sortable from 'sortablejs';
-
+import { dispose } from '~/tooltips';
import { deprecatedCreateFlash as flash } from './flash';
import axios from './lib/utils/axios_utils';
import { __ } from './locale';
-import { hide, dispose } from '~/tooltips';
export default class LabelManager {
constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
@@ -30,7 +29,6 @@ export default class LabelManager {
}
bindEvents() {
- this.prioritizedLabels.find('.btn-action').on('mousedown', this, this.onButtonActionClick);
return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
}
@@ -46,11 +44,6 @@ export default class LabelManager {
_this.toggleEmptyState($label, $btn, action);
}
- onButtonActionClick(e) {
- e.stopPropagation();
- hide(e.currentTarget);
- }
-
toggleEmptyState() {
this.emptyState.classList.toggle(
'hidden',
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 337d063b02a..56e69ab9418 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -4,15 +4,15 @@
import $ from 'jquery';
import { difference, isEqual, escape, sortBy, template, union } from 'lodash';
-import { sprintf, __ } from './locale';
-import axios from './lib/utils/axios_utils';
-import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import boardsStore from './boards/stores/boards_store';
+import ModalStore from './boards/stores/modal_store';
import CreateLabelDropdown from './create_label';
import { deprecatedCreateFlash as flash } from './flash';
-import ModalStore from './boards/stores/modal_store';
-import boardsStore from './boards/stores/boards_store';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
+import axios from './lib/utils/axios_utils';
+import { sprintf, __ } from './locale';
export default class LabelsSelect {
constructor(els, options = {}) {
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index 5c4bb5ea01f..bda5550a9f4 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -1,11 +1,11 @@
-import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
-import { createUploadLink } from 'apollo-upload-client';
+import { ApolloClient } from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import { BatchHttpLink } from 'apollo-link-batch-http';
+import { createUploadLink } from 'apollo-upload-client';
+import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
import csrf from '~/lib/utils/csrf';
import PerformanceBarService from '~/performance_bar/services/performance_bar_service';
-import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link';
export const fetchPolicies = {
CACHE_FIRST: 'cache-first',
@@ -35,6 +35,16 @@ export default (resolvers = {}, config = {}) => {
batchMax: config.batchMax || 10,
};
+ const requestCounterLink = new ApolloLink((operation, forward) => {
+ window.pendingApolloRequests = window.pendingApolloRequests || 0;
+ window.pendingApolloRequests += 1;
+
+ return forward(operation).map((response) => {
+ window.pendingApolloRequests -= 1;
+ return response;
+ });
+ });
+
const uploadsLink = ApolloLink.split(
(operation) => operation.getContext().hasUpload || operation.getContext().isSingleRequest,
createUploadLink(httpOptions),
@@ -63,7 +73,12 @@ export default (resolvers = {}, config = {}) => {
return new ApolloClient({
typeDefs: config.typeDefs,
- link: ApolloLink.from([performanceBarLink, new StartupJSLink(), uploadsLink]),
+ link: ApolloLink.from([
+ requestCounterLink,
+ performanceBarLink,
+ new StartupJSLink(),
+ uploadsLink,
+ ]),
cache: new InMemoryCache({
...config.cacheConfig,
freezeResults: config.assumeImmutableResults,
diff --git a/app/assets/javascripts/lib/utils/array_utility.js b/app/assets/javascripts/lib/utils/array_utility.js
new file mode 100644
index 00000000000..197e7790ed7
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/array_utility.js
@@ -0,0 +1,20 @@
+/**
+ * Return a shallow copy of an array with two items swapped.
+ *
+ * @param {Array} array - The source array
+ * @param {Number} leftIndex - Index of the first item
+ * @param {Number} rightIndex - Index of the second item
+ * @returns {Array} new array with the left and right items swapped
+ */
+export const swapArrayItems = (array, leftIndex = 0, rightIndex = 0) => {
+ const copy = array.slice();
+
+ if (leftIndex >= array.length || leftIndex < 0 || rightIndex >= array.length || rightIndex < 0) {
+ return copy;
+ }
+
+ const temp = copy[leftIndex];
+ copy[leftIndex] = copy[rightIndex];
+ copy[rightIndex] = temp;
+ return copy;
+};
diff --git a/app/assets/javascripts/lib/utils/axios_utils.js b/app/assets/javascripts/lib/utils/axios_utils.js
index cb479e243b2..204c84b879e 100644
--- a/app/assets/javascripts/lib/utils/axios_utils.js
+++ b/app/assets/javascripts/lib/utils/axios_utils.js
@@ -1,7 +1,7 @@
import axios from 'axios';
+import setupAxiosStartupCalls from './axios_startup_calls';
import csrf from './csrf';
import suppressAjaxErrorsDuringNavigation from './suppress_ajax_errors_during_navigation';
-import setupAxiosStartupCalls from './axios_startup_calls';
axios.defaults.headers.common[csrf.headerKey] = csrf.token;
// Used by Rails to check if it is a valid XHR request
diff --git a/app/assets/javascripts/lib/utils/color_utils.js b/app/assets/javascripts/lib/utils/color_utils.js
index a1f56b15631..ff176f11867 100644
--- a/app/assets/javascripts/lib/utils/color_utils.js
+++ b/app/assets/javascripts/lib/utils/color_utils.js
@@ -23,3 +23,23 @@ export const textColorForBackground = (backgroundColor) => {
}
return '#FFFFFF';
};
+
+/**
+ * Check whether a color matches the expected hex format
+ *
+ * This matches any hex (0-9 and A-F) value which is either 3 or 6 characters in length
+ *
+ * An empty string will return `null` which means that this is neither valid nor invalid.
+ * This is useful for forms resetting the validation state
+ *
+ * @param color string = ''
+ *
+ * @returns {null|boolean}
+ */
+export const validateHexColor = (color = '') => {
+ if (!color) {
+ return null;
+ }
+
+ return /^#([0-9A-F]{3}){1,2}$/i.test(color);
+};
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 128ef5b335e..73eadfe3cbe 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -4,11 +4,11 @@
import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
-import { isFunction, defer } from 'lodash';
import Cookies from 'js-cookie';
-import { getLocationHash } from './url_utility';
+import { isFunction, defer } from 'lodash';
import { convertToCamelCase, convertToSnakeCase } from './text_utility';
import { isObject } from './type_utility';
+import { getLocationHash } from './url_utility';
export const getPagePath = (index = 0) => {
const page = $('body').attr('data-page') || '';
@@ -45,6 +45,7 @@ export const checkPageAndAction = (page, action) => {
export const isInIncidentPage = () => checkPageAndAction('incidents', 'show');
export const isInIssuePage = () => checkPageAndAction('issues', 'show');
+export const isInDesignPage = () => checkPageAndAction('issues', 'designs');
export const isInMRPage = () => checkPageAndAction('merge_requests', 'show');
export const isInEpicPage = () => checkPageAndAction('epics', 'show');
@@ -122,7 +123,7 @@ export const handleLocationHash = () => {
}
if (isInIssuePage()) {
- adjustment -= fixedIssuableTitle.offsetHeight;
+ adjustment -= fixedIssuableTitle?.offsetHeight;
}
if (isInMRPage()) {
@@ -801,3 +802,12 @@ export const removeCookie = (name) => Cookies.remove(name);
* @returns {Boolean} on/off
*/
export const isFeatureFlagEnabled = (flag) => window.gon.features?.[flag];
+
+/**
+ * This method takes in array with snake_case strings
+ * and returns a new array with camelCase strings
+ *
+ * @param {Array[String]} array - Array to be converted
+ * @returns {Array[String]} Converted array
+ */
+export const convertArrayToCamelCase = (array) => array.map((i) => convertToCamelCase(i));
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index 993d51370ec..b19a4a01a5f 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -10,3 +10,9 @@ export const DATETIME_RANGE_TYPES = {
open: 'open',
invalid: 'invalid',
};
+
+export const BV_SHOW_MODAL = 'bv::show::modal';
+export const BV_HIDE_MODAL = 'bv::hide::modal';
+export const BV_HIDE_TOOLTIP = 'bv::hide::tooltip';
+export const BV_DROPDOWN_SHOW = 'bv::dropdown::show';
+export const BV_DROPDOWN_HIDE = 'bv::dropdown::hide';
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 15f7c0c874e..38b3b26dc44 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -1,10 +1,12 @@
+import dateFormat from 'dateformat';
import $ from 'jquery';
import { isString, mapValues, isNumber, reduce } from 'lodash';
import * as timeago from 'timeago.js';
-import dateFormat from 'dateformat';
import { languageCode, s__, __, n__ } from '../../locale';
-const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
+const MILLISECONDS_IN_HOUR = 60 * 60 * 1000;
+const MILLISECONDS_IN_DAY = 24 * MILLISECONDS_IN_HOUR;
+const DAYS_IN_WEEK = 7;
window.timeago = timeago;
@@ -674,50 +676,127 @@ export const secondsToHours = (offset) => {
};
/**
- * Returns the date n days after the date provided
+ * Returns the date `n` days after the date provided
*
* @param {Date} date the initial date
* @param {Number} numberOfDays number of days after
- * @return {Date} the date following the date provided
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` days after the provided `Date`
*/
-export const nDaysAfter = (date, numberOfDays) =>
- new Date(newDate(date)).setDate(date.getDate() + numberOfDays);
+export const nDaysAfter = (date, numberOfDays, { utc = false } = {}) => {
+ const clone = newDate(date);
+
+ const cloneValue = utc
+ ? clone.setUTCDate(date.getUTCDate() + numberOfDays)
+ : clone.setDate(date.getDate() + numberOfDays);
+
+ return new Date(cloneValue);
+};
/**
- * Returns the date n days before the date provided
+ * Returns the date `n` days before the date provided
*
* @param {Date} date the initial date
* @param {Number} numberOfDays number of days before
- * @return {Date} the date preceding the date provided
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ * @return {Date} A `Date` object `n` days before the provided `Date`
*/
-export const nDaysBefore = (date, numberOfDays) => nDaysAfter(date, -numberOfDays);
+export const nDaysBefore = (date, numberOfDays, options) =>
+ nDaysAfter(date, -numberOfDays, options);
/**
- * Returns the date n months after the date provided
+ * Returns the date `n` weeks after the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfWeeks number of weeks after
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` weeks after the provided `Date`
+ */
+export const nWeeksAfter = (date, numberOfWeeks, options) =>
+ nDaysAfter(date, DAYS_IN_WEEK * numberOfWeeks, options);
+
+/**
+ * Returns the date `n` weeks before the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfWeeks number of weeks before
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` weeks before the provided `Date`
+ */
+export const nWeeksBefore = (date, numberOfWeeks, options) =>
+ nWeeksAfter(date, -numberOfWeeks, options);
+
+/**
+ * Returns the date `n` months after the date provided
*
* @param {Date} date the initial date
* @param {Number} numberOfMonths number of months after
- * @return {Date} the date following the date provided
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` months after the provided `Date`
*/
-export const nMonthsAfter = (date, numberOfMonths) =>
- new Date(newDate(date)).setMonth(date.getMonth() + numberOfMonths);
+export const nMonthsAfter = (date, numberOfMonths, { utc = false } = {}) => {
+ const clone = newDate(date);
+
+ const cloneValue = utc
+ ? clone.setUTCMonth(date.getUTCMonth() + numberOfMonths)
+ : clone.setMonth(date.getMonth() + numberOfMonths);
+
+ return new Date(cloneValue);
+};
/**
- * Returns the date n months before the date provided
+ * Returns the date `n` months before the date provided
*
* @param {Date} date the initial date
* @param {Number} numberOfMonths number of months before
- * @return {Date} the date preceding the date provided
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
+ * @return {Date} A `Date` object `n` months before the provided `Date`
*/
-export const nMonthsBefore = (date, numberOfMonths) => nMonthsAfter(date, -numberOfMonths);
+export const nMonthsBefore = (date, numberOfMonths, options) =>
+ nMonthsAfter(date, -numberOfMonths, options);
/**
* Returns the date after the date provided
*
* @param {Date} date the initial date
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC dates.
+ * This will cause Daylight Saving Time to be ignored. Defaults to `false`
+ * if not provided, which causes the calculation to be performed in the
+ * user's timezone.
+ *
* @return {Date} the date following the date provided
*/
-export const dayAfter = (date) => new Date(newDate(date).setDate(date.getDate() + 1));
+export const dayAfter = (date, options) => nDaysAfter(date, 1, options);
/**
* Mimics the behaviour of the rails distance_of_time_in_words function
@@ -859,17 +938,17 @@ export const format24HourTimeStringFromInt = (time) => {
*
* @param {Object} givenPeriodLeft - the first period to compare.
* @param {Object} givenPeriodRight - the second period to compare.
- * @returns {Object} { overlap: number of days the overlap is present, overlapStartDate: the start date of the overlap in time format, overlapEndDate: the end date of the overlap in time format }
+ * @returns {Object} { daysOverlap: number of days the overlap is present, hoursOverlap: number of hours the overlap is present, overlapStartDate: the start date of the overlap in time format, overlapEndDate: the end date of the overlap in time format }
* @throws {Error} Uncaught Error: Invalid period
*
* @example
- * getOverlappingDaysInPeriods(
+ * getOverlapDateInPeriods(
* { start: new Date(2021, 0, 11), end: new Date(2021, 0, 13) },
* { start: new Date(2021, 0, 11), end: new Date(2021, 0, 14) }
- * ) => { daysOverlap: 2, overlapStartDate: 1610323200000, overlapEndDate: 1610496000000 }
+ * ) => { daysOverlap: 2, hoursOverlap: 48, overlapStartDate: 1610323200000, overlapEndDate: 1610496000000 }
*
*/
-export const getOverlappingDaysInPeriods = (givenPeriodLeft = {}, givenPeriodRight = {}) => {
+export const getOverlapDateInPeriods = (givenPeriodLeft = {}, givenPeriodRight = {}) => {
const leftStartTime = new Date(givenPeriodLeft.start).getTime();
const leftEndTime = new Date(givenPeriodLeft.end).getTime();
const rightStartTime = new Date(givenPeriodRight.start).getTime();
@@ -890,8 +969,44 @@ export const getOverlappingDaysInPeriods = (givenPeriodLeft = {}, givenPeriodRig
const differenceInMs = overlapEndDate - overlapStartDate;
return {
+ hoursOverlap: Math.ceil(differenceInMs / MILLISECONDS_IN_HOUR),
daysOverlap: Math.ceil(differenceInMs / MILLISECONDS_IN_DAY),
overlapStartDate,
overlapEndDate,
};
};
+
+/**
+ * A utility function that checks that the date is today
+ *
+ * @param {Date} date
+ *
+ * @return {Boolean} true if provided date is today
+ */
+export const isToday = (date) => {
+ const today = new Date();
+ return (
+ date.getDate() === today.getDate() &&
+ date.getMonth() === today.getMonth() &&
+ date.getFullYear() === today.getFullYear()
+ );
+};
+
+/**
+ * Returns the start of the provided day
+ *
+ * @param {Object} [options={}] Additional options for this calculation
+ * @param {boolean} [options.utc=false] Performs the calculation using UTC time.
+ * If `true`, the time returned will be midnight UTC. If `false` (the default)
+ * the time returned will be midnight in the user's local time.
+ *
+ * @returns {Date} A new `Date` object that represents the start of the day
+ * of the provided date
+ */
+export const getStartOfDay = (date, { utc = false } = {}) => {
+ const clone = newDate(date);
+
+ const cloneValue = utc ? clone.setUTCHours(0, 0, 0, 0) : clone.setHours(0, 0, 0, 0);
+
+ return new Date(cloneValue);
+};
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index d49382733c0..0f29f538b07 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -1,5 +1,5 @@
-import { BYTES_IN_KIB } from './constants';
import { sprintf, __ } from '~/locale';
+import { BYTES_IN_KIB } from './constants';
/**
* Function that allows a number with an X amount of decimals
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index 6ec1bd206e6..71782c9a4ce 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -1,5 +1,5 @@
-import httpStatusCodes, { successCodes } from './http_status';
import { normalizeHeaders } from './common_utils';
+import httpStatusCodes, { successCodes } from './http_status';
/**
* Polling utility for handling realtime updates.
diff --git a/app/assets/javascripts/lib/utils/poll_until_complete.js b/app/assets/javascripts/lib/utils/poll_until_complete.js
index d3b551ca755..3545db3a227 100644
--- a/app/assets/javascripts/lib/utils/poll_until_complete.js
+++ b/app/assets/javascripts/lib/utils/poll_until_complete.js
@@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
-import Poll from './poll';
import httpStatusCodes from './http_status';
+import Poll from './poll';
/**
* Polls an endpoint until it returns either a 200 OK or a error status.
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index 6bb7f09b886..a6d53358cb8 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -1,5 +1,3 @@
-import StickyFill from 'stickyfilljs';
-
export const createPlaceholder = () => {
const placeholder = document.createElement('div');
placeholder.classList.add('sticky-placeholder');
@@ -60,13 +58,3 @@ export const stickyMonitor = (el, stickyTop, insertPlaceholder = true) => {
},
);
};
-
-/**
- * Polyfill the `position: sticky` behavior.
- *
- * - If the current environment supports `position: sticky`, do nothing.
- * - Can receive an iterable element list (NodeList, jQuery collection, etc.) or single HTMLElement.
- */
-export const polyfillSticky = (el) => {
- StickyFill.add(el);
-};
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 2c993c8b128..5e66aa05218 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -1,7 +1,7 @@
/* eslint-disable func-names, no-param-reassign, operator-assignment, consistent-return */
import $ from 'jquery';
-import { insertText } from '~/lib/utils/common_utils';
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
+import { insertText } from '~/lib/utils/common_utils';
const LINK_TAG_PATTERN = '[{text}](url)';
diff --git a/app/assets/javascripts/lib/utils/unit_format/formatter_factory.js b/app/assets/javascripts/lib/utils/unit_format/formatter_factory.js
index 9d47a1b7132..15f9512fe92 100644
--- a/app/assets/javascripts/lib/utils/unit_format/formatter_factory.js
+++ b/app/assets/javascripts/lib/utils/unit_format/formatter_factory.js
@@ -20,8 +20,9 @@ function formatNumber(
return '';
}
+ const locale = document.documentElement.lang || undefined;
const num = value * valueFactor;
- const formatted = num.toLocaleString(undefined, {
+ const formatted = num.toLocaleString(locale, {
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits,
style,
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 44d3e78b334..cc2cf787a8f 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -16,6 +16,50 @@ function decodeUrlParameter(val) {
return decodeURIComponent(val.replace(/\+/g, '%20'));
}
+/**
+ * Safely encodes a string to be used as a path
+ *
+ * Note: This function DOES encode typical URL parts like ?, =, &, #, and +
+ * If you need to use search parameters or URL fragments, they should be
+ * added AFTER calling this function, not before.
+ *
+ * Usecase: An image filename is stored verbatim, and you need to load it in
+ * the browser.
+ *
+ * Example: /some_path/file #1.jpg ==> /some_path/file%20%231.jpg
+ * Example: /some-path/file! Final!.jpg ==> /some-path/file%21%20Final%21.jpg
+ *
+ * Essentially, if a character *could* present a problem in a URL, it's escaped
+ * to the hexadecimal representation instead. This means it's a bit more
+ * aggressive than encodeURIComponent: that built-in function doesn't
+ * encode some characters that *could* be problematic, so this function
+ * adds them (#, !, ~, *, ', (, and )).
+ * Additionally, encodeURIComponent *does* encode `/`, but we want safer
+ * URLs, not non-functional URLs, so this function DEcodes slashes ('%2F').
+ *
+ * @param {String} potentiallyUnsafePath
+ * @returns {String}
+ */
+export function encodeSaferUrl(potentiallyUnsafePath) {
+ const unencode = ['%2F'];
+ const encode = ['#', '!', '~', '\\*', "'", '\\(', '\\)'];
+ let saferPath = encodeURIComponent(potentiallyUnsafePath);
+
+ unencode.forEach((code) => {
+ saferPath = saferPath.replace(new RegExp(code, 'g'), decodeURIComponent(code));
+ });
+ encode.forEach((code) => {
+ const encodedValue = code
+ .codePointAt(code.length - 1)
+ .toString(16)
+ .toUpperCase();
+
+ saferPath = saferPath.replace(new RegExp(code, 'g'), `%${encodedValue}`);
+ });
+
+ return saferPath;
+}
+
export function cleanLeadingSeparator(path) {
return path.replace(PATH_SEPARATOR_LEADING_REGEX, '');
}
@@ -310,6 +354,20 @@ export function isAbsoluteOrRootRelative(url) {
}
/**
+ * Returns true if url is an external URL
+ *
+ * @param {String} url
+ * @returns {Boolean}
+ */
+export function isExternal(url) {
+ if (isRootRelative(url)) {
+ return false;
+ }
+
+ return !url.includes(gon.gitlab_url);
+}
+
+/**
* Converts a relative path to an absolute or a root relative path depending
* on what is passed as a basePath.
*
diff --git a/app/assets/javascripts/lib/utils/webpack.js b/app/assets/javascripts/lib/utils/webpack.js
index 622c40e0f35..07a4d2deb0b 100644
--- a/app/assets/javascripts/lib/utils/webpack.js
+++ b/app/assets/javascripts/lib/utils/webpack.js
@@ -1,6 +1,9 @@
import { joinPaths } from '~/lib/utils/url_utility';
-// tell webpack to load assets from origin so that web workers don't break
+/**
+ * Tell webpack to load assets from origin so that web workers don't break
+ * See https://gitlab.com/gitlab-org/gitlab/-/issues/321656 for a fix
+ */
export function resetServiceWorkersPublicPath() {
// __webpack_public_path__ is a global variable that can be used to adjust
// the webpack publicPath setting at runtime.
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index a114b3c7d4d..5092c6905c4 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -1,6 +1,4 @@
<script>
-import { throttle } from 'lodash';
-import { mapActions, mapState, mapGetters } from 'vuex';
import {
GlSprintf,
GlAlert,
@@ -10,14 +8,15 @@ import {
GlDropdownDivider,
GlInfiniteScroll,
} from '@gitlab/ui';
+import { throttle } from 'lodash';
+import { mapActions, mapState, mapGetters } from 'vuex';
-import LogSimpleFilters from './log_simple_filters.vue';
-import LogAdvancedFilters from './log_advanced_filters.vue';
-import LogControlButtons from './log_control_buttons.vue';
-
-import { defaultTimeRange } from '~/vue_shared/constants';
import { timeRangeFromUrl } from '~/monitoring/utils';
+import { defaultTimeRange } from '~/vue_shared/constants';
import { formatDate } from '../utils';
+import LogAdvancedFilters from './log_advanced_filters.vue';
+import LogControlButtons from './log_control_buttons.vue';
+import LogSimpleFilters from './log_simple_filters.vue';
export default {
components: {
@@ -176,7 +175,7 @@ export default {
id="environments-dropdown"
:text="environments.current || managedApps.current"
:disabled="environments.isLoading"
- class="gl-mr-3 gl-mb-3 gl-display-flex gl-display-md-block js-environments-dropdown"
+ class="gl-mr-3 gl-mb-3 gl-display-flex gl-md-display-block js-environments-dropdown"
>
<gl-dropdown-section-header>
{{ s__('Environments|Environments') }}
diff --git a/app/assets/javascripts/logs/components/log_advanced_filters.vue b/app/assets/javascripts/logs/components/log_advanced_filters.vue
index 37fc4dc3735..9159ca5b9dc 100644
--- a/app/assets/javascripts/logs/components/log_advanced_filters.vue
+++ b/app/assets/javascripts/logs/components/log_advanced_filters.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlFilteredSearch } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { __, s__ } from '~/locale';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import { timeRanges } from '~/vue_shared/constants';
diff --git a/app/assets/javascripts/logs/components/log_simple_filters.vue b/app/assets/javascripts/logs/components/log_simple_filters.vue
index ba30d4628c9..55bdd5f0088 100644
--- a/app/assets/javascripts/logs/components/log_simple_filters.vue
+++ b/app/assets/javascripts/logs/components/log_simple_filters.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlDropdown, GlDropdownSectionHeader, GlDropdownItem } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
export default {
@@ -42,7 +42,7 @@ export default {
ref="podsDropdown"
:text="podDropdownText"
:disabled="disabled"
- class="gl-mr-3 gl-mb-3 gl-display-flex gl-display-md-block qa-pods-dropdown"
+ class="gl-mr-3 gl-mb-3 gl-display-flex gl-md-display-block qa-pods-dropdown"
>
<gl-dropdown-section-header>
{{ s__('Environments|Select pod') }}
diff --git a/app/assets/javascripts/logs/stores/actions.js b/app/assets/javascripts/logs/stores/actions.js
index a26e6f694c9..e813f91d2fa 100644
--- a/app/assets/javascripts/logs/stores/actions.js
+++ b/app/assets/javascripts/logs/stores/actions.js
@@ -1,7 +1,7 @@
-import { backOff } from '~/lib/utils/common_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
+import { backOff } from '~/lib/utils/common_utils';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
+import httpStatusCodes from '~/lib/utils/http_status';
import { TOKEN_TYPE_POD_NAME, tracking, logExplorerOptions } from '../constants';
import trackLogs from '../logs_tracking_helper';
diff --git a/app/assets/javascripts/logs/stores/mutations.js b/app/assets/javascripts/logs/stores/mutations.js
index 147f562057f..21031838adf 100644
--- a/app/assets/javascripts/logs/stores/mutations.js
+++ b/app/assets/javascripts/logs/stores/mutations.js
@@ -1,5 +1,5 @@
-import * as types from './mutation_types';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
+import * as types from './mutation_types';
const mapLine = ({ timestamp, pod, message }) => ({
timestamp,
diff --git a/app/assets/javascripts/logs/stores/state.js b/app/assets/javascripts/logs/stores/state.js
index fbe6589dd84..e2028621ac8 100644
--- a/app/assets/javascripts/logs/stores/state.js
+++ b/app/assets/javascripts/logs/stores/state.js
@@ -1,5 +1,5 @@
-import { timeRanges, defaultTimeRange } from '~/vue_shared/constants';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
+import { timeRanges, defaultTimeRange } from '~/vue_shared/constants';
export default () => ({
/**
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index ef0fef6085b..32ecc0036bd 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -1,4 +1,5 @@
/* global $ */
+/* eslint-disable import/order */
import jQuery from 'jquery';
import Cookies from 'js-cookie';
@@ -12,6 +13,12 @@ import './behaviors';
import applyGitLabUIConfig from '@gitlab/ui/dist/config';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { initRails } from '~/lib/utils/rails_ujs';
+import * as popovers from '~/popovers';
+import * as tooltips from '~/tooltips';
+import initAlertHandler from './alert_handler';
+import { deprecatedCreateFlash as Flash, removeFlashClickListener } from './flash';
+import initTodoToggle from './header';
+import initLayoutNav from './layout_nav';
import {
handleLocationHash,
addSelectOnFocusBehaviour,
@@ -21,25 +28,18 @@ import { localTimeAgo } from './lib/utils/datetime_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
// everything else
-import { deprecatedCreateFlash as Flash, removeFlashClickListener } from './flash';
-import initTodoToggle from './header';
-import initLayoutNav from './layout_nav';
-import initAlertHandler from './alert_handler';
-import './feature_highlight/feature_highlight_options';
+import initFeatureHighlight from './feature_highlight';
import LazyLoader from './lazy_loader';
+import { __ } from './locale';
import initLogoAnimation from './logo';
import initFrequentItemDropdowns from './frequent_items';
import initBreadcrumbs from './breadcrumb';
+import initPersistentUserCallouts from './persistent_user_callouts';
+import { initUserTracking, initDefaultTrackers } from './tracking';
import initUsagePingConsent from './usage_ping_consent';
import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
-import initPersistentUserCallouts from './persistent_user_callouts';
-import { initUserTracking, initDefaultTrackers } from './tracking';
-import { __ } from './locale';
-
-import * as tooltips from '~/tooltips';
-import * as popovers from '~/popovers';
import 'ee_else_ce/main_ee';
@@ -72,7 +72,7 @@ if (gon?.disable_animations) {
// inject test utilities if necessary
if (process.env.NODE_ENV !== 'production' && gon?.test_env) {
disableJQueryAnimations();
- import(/* webpackMode: "eager" */ './test_utils/'); // eslint-disable-line no-unused-expressions
+ import(/* webpackMode: "eager" */ './test_utils/');
}
document.addEventListener('beforeunload', () => {
@@ -115,6 +115,7 @@ function deferredInitialisation() {
initFrequentItemDropdowns();
initPersistentUserCallouts();
initDefaultTrackers();
+ initFeatureHighlight();
const search = document.querySelector('#search');
if (search) {
diff --git a/app/assets/javascripts/manual_ordering.js b/app/assets/javascripts/manual_ordering.js
index 04eaa0c77c3..540314f8f9b 100644
--- a/app/assets/javascripts/manual_ordering.js
+++ b/app/assets/javascripts/manual_ordering.js
@@ -1,11 +1,11 @@
import Sortable from 'sortablejs';
-import { s__ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
getBoardSortableDefaultOptions,
sortableStart,
} from '~/boards/mixins/sortable_default_options';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { s__ } from '~/locale';
const updateIssue = (url, issueList, { move_before_id, move_after_id }) =>
axios
diff --git a/app/assets/javascripts/members.js b/app/assets/javascripts/members.js
index 4cf4fdd12bf..a8edeaf5176 100644
--- a/app/assets/javascripts/members.js
+++ b/app/assets/javascripts/members.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import { Rails } from '~/lib/utils/rails_ujs';
-import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
+import { Rails } from '~/lib/utils/rails_ujs';
import { __, sprintf } from '~/locale';
export default class Members {
diff --git a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
index fcb70dd45a6..35966be7363 100644
--- a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
@@ -1,8 +1,8 @@
<script>
+import { s__, sprintf } from '~/locale';
import ActionButtonGroup from './action_button_group.vue';
-import RemoveMemberButton from './remove_member_button.vue';
import ApproveAccessRequestButton from './approve_access_request_button.vue';
-import { s__, sprintf } from '~/locale';
+import RemoveMemberButton from './remove_member_button.vue';
export default {
name: 'AccessRequestActionButtons',
diff --git a/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue b/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue
index e8a53ff173d..83f266779f2 100644
--- a/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlButton, GlForm, GlTooltipDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
import csrf from '~/lib/utils/csrf';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
index 9a27348f146..0bcc85157f1 100644
--- a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue
@@ -1,8 +1,8 @@
<script>
+import { s__, sprintf } from '~/locale';
import ActionButtonGroup from './action_button_group.vue';
import RemoveMemberButton from './remove_member_button.vue';
import ResendInviteButton from './resend_invite_button.vue';
-import { s__, sprintf } from '~/locale';
export default {
name: 'InviteActionButtons',
diff --git a/app/assets/javascripts/members/components/action_buttons/leave_button.vue b/app/assets/javascripts/members/components/action_buttons/leave_button.vue
index 443a962e0cf..f600a207b8d 100644
--- a/app/assets/javascripts/members/components/action_buttons/leave_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/leave_button.vue
@@ -1,8 +1,8 @@
<script>
import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
-import LeaveModal from '../modals/leave_modal.vue';
import { LEAVE_MODAL_ID } from '../../constants';
+import LeaveModal from '../modals/leave_modal.vue';
export default {
name: 'LeaveButton',
diff --git a/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue
index 9d89cb40676..3b87c29c1bc 100644
--- a/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions } from 'vuex';
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { mapActions } from 'vuex';
import { s__ } from '~/locale';
export default {
@@ -31,6 +31,7 @@ export default {
:title="$options.i18n.buttonTitle"
:aria-label="$options.i18n.buttonTitle"
icon="remove"
+ data-qa-selector="delete_group_access_link"
@click="showRemoveGroupLinkModal(groupLink)"
/>
</template>
diff --git a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
index b0b7ff4ce9a..cb71be39ebc 100644
--- a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
export default {
name: 'RemoveMemberButton',
diff --git a/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue b/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue
index 1cc3fd17e98..261a6279920 100644
--- a/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue
+++ b/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
import csrf from '~/lib/utils/csrf';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
index 0e5df961782..f779d1755a5 100644
--- a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
@@ -1,8 +1,8 @@
<script>
+import { s__, sprintf } from '~/locale';
import ActionButtonGroup from './action_button_group.vue';
-import RemoveMemberButton from './remove_member_button.vue';
import LeaveButton from './leave_button.vue';
-import { s__, sprintf } from '~/locale';
+import RemoveMemberButton from './remove_member_button.vue';
export default {
name: 'UserActionButtons',
diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue
new file mode 100644
index 00000000000..27fceb7374e
--- /dev/null
+++ b/app/assets/javascripts/members/components/app.vue
@@ -0,0 +1,40 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { mapState, mapMutations } from 'vuex';
+import { scrollToElement } from '~/lib/utils/common_utils';
+import { HIDE_ERROR } from '../store/mutation_types';
+import FilterSortContainer from './filter_sort/filter_sort_container.vue';
+import MembersTable from './table/members_table.vue';
+
+export default {
+ name: 'MembersApp',
+ components: { MembersTable, FilterSortContainer, GlAlert },
+ computed: {
+ ...mapState(['showError', 'errorMessage']),
+ },
+ watch: {
+ showError(value) {
+ if (value) {
+ this.$nextTick(() => {
+ scrollToElement(this.$refs.errorAlert.$el);
+ });
+ }
+ },
+ },
+ methods: {
+ ...mapMutations({
+ hideError: HIDE_ERROR,
+ }),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert v-if="showError" ref="errorAlert" variant="danger" @dismiss="hideError">{{
+ errorMessage
+ }}</gl-alert>
+ <filter-sort-container />
+ <members-table />
+ </div>
+</template>
diff --git a/app/assets/javascripts/members/components/avatars/user_avatar.vue b/app/assets/javascripts/members/components/avatars/user_avatar.vue
index e2264085e67..79dda3c1379 100644
--- a/app/assets/javascripts/members/components/avatars/user_avatar.vue
+++ b/app/assets/javascripts/members/components/avatars/user_avatar.vue
@@ -6,9 +6,9 @@ import {
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import { generateBadges } from 'ee_else_ce/members/utils';
+import { glEmojiTag } from '~/emoji';
import { __ } from '~/locale';
import { AVATAR_SIZE } from '../../constants';
-import { glEmojiTag } from '~/emoji';
export default {
name: 'UserAvatar',
@@ -69,7 +69,10 @@ export default {
>
<template #meta>
<div v-if="statusEmoji" class="gl-p-1">
- <span v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)"></span>
+ <span
+ v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)"
+ class="user-status-emoji gl-mr-0"
+ ></span>
</div>
<div v-for="badge in badges" :key="badge.text" class="gl-p-1">
<gl-badge size="sm" :variant="badge.variant">
diff --git a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue
index f869ecd392f..812a8626949 100644
--- a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue
+++ b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue
@@ -19,7 +19,7 @@ export default {
</script>
<template>
- <div v-if="showContainer" class="gl-bg-gray-10 gl-p-3 gl-display-md-flex">
+ <div v-if="showContainer" class="gl-bg-gray-10 gl-p-3 gl-md-display-flex">
<members-filtered-search-bar v-if="filteredSearchBar.show" class="gl-p-3 gl-flex-grow-1" />
<sort-dropdown v-if="showSortDropdown" class="gl-p-3 gl-flex-shrink-0" />
</div>
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 cf7501d84fa..039ee9a0207 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
@@ -1,11 +1,11 @@
<script>
-import { mapState } from 'vuex';
import { GlFilteredSearchToken } from '@gitlab/ui';
-import { setUrlParams, queryToObject } from '~/lib/utils/url_utility';
+import { mapState } from 'vuex';
import { getParameterByName } from '~/lib/utils/common_utils';
+import { setUrlParams, queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
-import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import { SEARCH_TOKEN_TYPE, SORT_PARAM } from '~/members/constants';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
export default {
name: 'MembersFilteredSearchBar',
diff --git a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
index bcfe559768d..9fa8772faf4 100644
--- a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
+++ b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue
@@ -1,9 +1,9 @@
<script>
-import { mapState } from 'vuex';
import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import { mapState } from 'vuex';
import { visitUrl } from '~/lib/utils/url_utility';
-import { parseSortParam, buildSortHref } from '~/members/utils';
import { FIELDS } from '~/members/constants';
+import { parseSortParam, buildSortHref } from '~/members/utils';
export default {
name: 'SortDropdown',
diff --git a/app/assets/javascripts/members/components/modals/leave_modal.vue b/app/assets/javascripts/members/components/modals/leave_modal.vue
index d231c7eabfa..a0f978d85cc 100644
--- a/app/assets/javascripts/members/components/modals/leave_modal.vue
+++ b/app/assets/javascripts/members/components/modals/leave_modal.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlModal, GlForm, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale';
import { LEAVE_MODAL_ID } from '../../constants';
diff --git a/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue b/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue
index 231d014a4ec..1ba6bf9aba6 100644
--- a/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue
+++ b/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlModal, GlSprintf, GlForm } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale';
import { REMOVE_GROUP_LINK_MODAL_ID } from '../../constants';
@@ -52,6 +52,7 @@ export default {
:action-primary="$options.actionPrimary"
:action-cancel="$options.actionCancel"
size="sm"
+ data-qa-selector="remove_group_link_modal_content"
@primary="handlePrimary"
@hide="hideRemoveGroupLinkModal"
>
diff --git a/app/assets/javascripts/members/components/table/member_action_buttons.vue b/app/assets/javascripts/members/components/table/member_action_buttons.vue
index c61ebec33bd..6f15f079d2d 100644
--- a/app/assets/javascripts/members/components/table/member_action_buttons.vue
+++ b/app/assets/javascripts/members/components/table/member_action_buttons.vue
@@ -1,9 +1,9 @@
<script>
-import UserActionButtons from '../action_buttons/user_action_buttons.vue';
+import { MEMBER_TYPES } from '../../constants';
+import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue';
import GroupActionButtons from '../action_buttons/group_action_buttons.vue';
import InviteActionButtons from '../action_buttons/invite_action_buttons.vue';
-import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue';
-import { MEMBER_TYPES } from '../../constants';
+import UserActionButtons from '../action_buttons/user_action_buttons.vue';
export default {
name: 'MemberActionButtons',
diff --git a/app/assets/javascripts/members/components/table/member_avatar.vue b/app/assets/javascripts/members/components/table/member_avatar.vue
index a1f98d4008a..92b757ffcba 100644
--- a/app/assets/javascripts/members/components/table/member_avatar.vue
+++ b/app/assets/javascripts/members/components/table/member_avatar.vue
@@ -1,8 +1,8 @@
<script>
import { kebabCase } from 'lodash';
-import UserAvatar from '../avatars/user_avatar.vue';
-import InviteAvatar from '../avatars/invite_avatar.vue';
import GroupAvatar from '../avatars/group_avatar.vue';
+import InviteAvatar from '../avatars/invite_avatar.vue';
+import UserAvatar from '../avatars/user_avatar.vue';
export default {
name: 'MemberAvatar',
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index 16e0cd5ad4e..9a3edff19ff 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -1,18 +1,18 @@
<script>
-import { mapState } from 'vuex';
import { GlTable, GlBadge } from '@gitlab/ui';
+import { mapState } from 'vuex';
import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue';
import { canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils';
-import { FIELDS } from '../../constants';
import initUserPopovers from '~/user_popovers';
-import MemberAvatar from './member_avatar.vue';
-import MemberSource from './member_source.vue';
+import { FIELDS } from '../../constants';
+import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue';
import CreatedAt from './created_at.vue';
+import ExpirationDatepicker from './expiration_datepicker.vue';
import ExpiresAt from './expires_at.vue';
import MemberActionButtons from './member_action_buttons.vue';
+import MemberAvatar from './member_avatar.vue';
+import MemberSource from './member_source.vue';
import RoleDropdown from './role_dropdown.vue';
-import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue';
-import ExpirationDatepicker from './expiration_datepicker.vue';
export default {
name: 'MembersTable',
@@ -32,7 +32,7 @@ export default {
import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'),
},
computed: {
- ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId', 'sourceId']),
+ ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId']),
filteredFields() {
return FIELDS.filter(
(field) => this.tableFields.includes(field.key) && this.showField(field),
@@ -55,9 +55,9 @@ export default {
methods: {
hasActionButtons(member) {
return (
- canRemove(member, this.sourceId) ||
+ canRemove(member) ||
canResend(member) ||
- canUpdate(member, this.currentUserId, this.sourceId) ||
+ canUpdate(member, this.currentUserId) ||
canOverride(member)
);
},
@@ -80,7 +80,7 @@ export default {
return 'col-actions';
}
- return ['col-actions', 'gl-display-none!', 'gl-display-lg-table-cell!'];
+ return ['col-actions', 'gl-display-none!', 'gl-lg-display-table-cell!'];
},
tbodyTrAttr(member) {
return {
diff --git a/app/assets/javascripts/members/components/table/members_table_cell.vue b/app/assets/javascripts/members/components/table/members_table_cell.vue
index 20aa01b96bc..1f537740f94 100644
--- a/app/assets/javascripts/members/components/table/members_table_cell.vue
+++ b/app/assets/javascripts/members/components/table/members_table_cell.vue
@@ -19,7 +19,7 @@ export default {
},
},
computed: {
- ...mapState(['sourceId', 'currentUserId']),
+ ...mapState(['currentUserId']),
isGroup() {
return isGroup(this.member);
},
@@ -41,19 +41,19 @@ export default {
return MEMBER_TYPES.user;
},
isDirectMember() {
- return isDirectMember(this.member, this.sourceId);
+ return isDirectMember(this.member);
},
isCurrentUser() {
return isCurrentUser(this.member, this.currentUserId);
},
canRemove() {
- return canRemove(this.member, this.sourceId);
+ return canRemove(this.member);
},
canResend() {
return canResend(this.member);
},
canUpdate() {
- return canUpdate(this.member, this.currentUserId, this.sourceId);
+ return canUpdate(this.member, this.currentUserId);
},
},
render() {
diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js
index 77cb150bff6..f68a8814fee 100644
--- a/app/assets/javascripts/members/constants.js
+++ b/app/assets/javascripts/members/constants.js
@@ -98,3 +98,8 @@ export const REMOVE_GROUP_LINK_MODAL_ID = 'remove-group-link-modal-id';
export const SEARCH_TOKEN_TYPE = 'filtered-search-term';
export const SORT_PARAM = 'sort';
+
+export const MEMBER_ACCESS_LEVEL_PROPERTY_NAME = 'access_level';
+
+export const GROUP_LINK_BASE_PROPERTY_NAME = 'group_link';
+export const GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME = 'group_access';
diff --git a/app/assets/javascripts/members/index.js b/app/assets/javascripts/members/index.js
new file mode 100644
index 00000000000..fe174d9beb6
--- /dev/null
+++ b/app/assets/javascripts/members/index.js
@@ -0,0 +1,43 @@
+import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { parseDataAttributes } from 'ee_else_ce/members/utils';
+import App from './components/app.vue';
+import membersStore from './store';
+
+export const initMembersApp = (
+ el,
+ {
+ tableFields = [],
+ tableAttrs = {},
+ tableSortableFields = [],
+ requestFormatter = () => {},
+ filteredSearchBar = { show: false },
+ },
+) => {
+ if (!el) {
+ return () => {};
+ }
+
+ Vue.use(Vuex);
+ Vue.use(GlToast);
+
+ const store = new Vuex.Store(
+ membersStore({
+ ...parseDataAttributes(el),
+ currentUserId: gon.current_user_id || null,
+ tableFields,
+ tableAttrs,
+ tableSortableFields,
+ requestFormatter,
+ filteredSearchBar,
+ }),
+ );
+
+ return new Vue({
+ el,
+ components: { App },
+ store,
+ render: (createElement) => createElement('app'),
+ });
+};
diff --git a/app/assets/javascripts/members/store/actions.js b/app/assets/javascripts/members/store/actions.js
index 4c31b3c9744..7b191dd85d0 100644
--- a/app/assets/javascripts/members/store/actions.js
+++ b/app/assets/javascripts/members/store/actions.js
@@ -1,6 +1,6 @@
-import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import { formatDate } from '~/lib/utils/datetime_utility';
+import * as types from './mutation_types';
export const updateMemberRole = async ({ state, commit }, { memberId, accessLevel }) => {
try {
@@ -11,7 +11,7 @@ export const updateMemberRole = async ({ state, commit }, { memberId, accessLeve
commit(types.RECEIVE_MEMBER_ROLE_SUCCESS, { memberId, accessLevel });
} catch (error) {
- commit(types.RECEIVE_MEMBER_ROLE_ERROR);
+ commit(types.RECEIVE_MEMBER_ROLE_ERROR, { error });
throw error;
}
@@ -37,7 +37,7 @@ export const updateMemberExpiration = async ({ state, commit }, { memberId, expi
expiresAt: expiresAt ? formatDate(expiresAt, 'isoUtcDateTime') : null,
});
} catch (error) {
- commit(types.RECEIVE_MEMBER_EXPIRATION_ERROR);
+ commit(types.RECEIVE_MEMBER_EXPIRATION_ERROR, { error });
throw error;
}
diff --git a/app/assets/javascripts/members/store/index.js b/app/assets/javascripts/members/store/index.js
index 34c102999d2..45f4eefffc9 100644
--- a/app/assets/javascripts/members/store/index.js
+++ b/app/assets/javascripts/members/store/index.js
@@ -1,6 +1,6 @@
-import createState from 'ee_else_ce/members/store/state';
-import mutations from 'ee_else_ce/members/store/mutations';
import * as actions from 'ee_else_ce/members/store/actions';
+import mutations from 'ee_else_ce/members/store/mutations';
+import createState from 'ee_else_ce/members/store/state';
export default (initialState) => ({
state: createState(initialState),
diff --git a/app/assets/javascripts/members/store/mutations.js b/app/assets/javascripts/members/store/mutations.js
index 2415e744290..f4aac1571d6 100644
--- a/app/assets/javascripts/members/store/mutations.js
+++ b/app/assets/javascripts/members/store/mutations.js
@@ -13,10 +13,10 @@ export default {
Vue.set(member, 'accessLevel', accessLevel);
},
- [types.RECEIVE_MEMBER_ROLE_ERROR](state) {
- state.errorMessage = s__(
- "Members|An error occurred while updating the member's role, please try again.",
- );
+ [types.RECEIVE_MEMBER_ROLE_ERROR](state, { error }) {
+ state.errorMessage =
+ error.response?.data?.message ||
+ s__("Members|An error occurred while updating the member's role, please try again.");
state.showError = true;
},
[types.RECEIVE_MEMBER_EXPIRATION_SUCCESS](state, { memberId, expiresAt }) {
@@ -28,10 +28,12 @@ export default {
Vue.set(member, 'expiresAt', expiresAt);
},
- [types.RECEIVE_MEMBER_EXPIRATION_ERROR](state) {
- state.errorMessage = s__(
- "Members|An error occurred while updating the member's expiration date, please try again.",
- );
+ [types.RECEIVE_MEMBER_EXPIRATION_ERROR](state, { error }) {
+ state.errorMessage =
+ error.response?.data?.message ||
+ s__(
+ "Members|An error occurred while updating the member's expiration date, please try again.",
+ );
state.showError = true;
},
[types.HIDE_ERROR](state) {
diff --git a/app/assets/javascripts/members/utils.js b/app/assets/javascripts/members/utils.js
index 780b5a9df57..4de2dadb490 100644
--- a/app/assets/javascripts/members/utils.js
+++ b/app/assets/javascripts/members/utils.js
@@ -1,7 +1,17 @@
-import { __ } from '~/locale';
-import { getParameterByName } from '~/lib/utils/common_utils';
+import { isUndefined } from 'lodash';
+import {
+ getParameterByName,
+ convertObjectPropsToCamelCase,
+ parseBoolean,
+} from '~/lib/utils/common_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
-import { FIELDS, DEFAULT_SORT } from './constants';
+import { __ } from '~/locale';
+import {
+ FIELDS,
+ DEFAULT_SORT,
+ GROUP_LINK_BASE_PROPERTY_NAME,
+ GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME,
+} from './constants';
export const generateBadges = (member, isCurrentUser) => [
{
@@ -25,26 +35,24 @@ export const isGroup = (member) => {
return Boolean(member.sharedWithGroup);
};
-export const isDirectMember = (member, sourceId) => {
- return isGroup(member) || member.source?.id === sourceId;
+export const isDirectMember = (member) => {
+ return isGroup(member) || member.isDirectMember;
};
export const isCurrentUser = (member, currentUserId) => {
return member.user?.id === currentUserId;
};
-export const canRemove = (member, sourceId) => {
- return isDirectMember(member, sourceId) && member.canRemove;
+export const canRemove = (member) => {
+ return isDirectMember(member) && member.canRemove;
};
export const canResend = (member) => {
return Boolean(member.invite?.canResend);
};
-export const canUpdate = (member, currentUserId, sourceId) => {
- return (
- !isCurrentUser(member, currentUserId) && isDirectMember(member, sourceId) && member.canUpdate
- );
+export const canUpdate = (member, currentUserId) => {
+ return !isCurrentUser(member, currentUserId) && isDirectMember(member) && member.canUpdate;
};
export const parseSortParam = (sortableFields) => {
@@ -95,3 +103,35 @@ export const buildSortHref = ({
// Defined in `ee/app/assets/javascripts/vue_shared/components/members/utils.js`
export const canOverride = () => false;
+
+export const parseDataAttributes = (el) => {
+ const { members, sourceId, memberPath, canManageMembers } = el.dataset;
+
+ return {
+ members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }),
+ sourceId: parseInt(sourceId, 10),
+ memberPath,
+ canManageMembers: parseBoolean(canManageMembers),
+ };
+};
+
+export const baseRequestFormatter = (basePropertyName, accessLevelPropertyName) => ({
+ accessLevel,
+ ...otherProperties
+}) => {
+ const accessLevelProperty = !isUndefined(accessLevel)
+ ? { [accessLevelPropertyName]: accessLevel }
+ : {};
+
+ return {
+ [basePropertyName]: {
+ ...accessLevelProperty,
+ ...otherProperties,
+ },
+ };
+};
+
+export const groupLinkRequestFormatter = baseRequestFormatter(
+ GROUP_LINK_BASE_PROPERTY_NAME,
+ GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME,
+);
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
index 338fbd9078a..6eaabbb3519 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
@@ -1,9 +1,12 @@
-/* eslint-disable no-param-reassign */
+// This is a true violation of @gitlab/no-runtime-template-compiler, as it relies on
+// app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
+// for its template.
+/* eslint-disable no-param-reassign, @gitlab/no-runtime-template-compiler */
-import Vue from 'vue';
import { debounce } from 'lodash';
-import axios from '~/lib/utils/axios_utils';
+import Vue from 'vue';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
((global) => {
@@ -90,9 +93,11 @@ import { __ } from '~/locale';
this.saved = true;
// This probably be better placed in the data provider
+ /* eslint-disable vue/no-mutating-props */
this.file.content = this.editor.getValue();
this.file.resolveEditChanged = this.file.content !== this.originalContent;
this.file.promptDiscardConfirmation = false;
+ /* eslint-enable vue/no-mutating-props */
},
resetEditorContent() {
if (this.fileLoaded) {
diff --git a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
index bc926cb9155..47214e288ae 100644
--- a/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
+++ b/app/assets/javascripts/merge_conflicts/components/inline_conflict_lines.js
@@ -1,4 +1,7 @@
-/* eslint-disable no-param-reassign */
+// This is a true violation of @gitlab/no-runtime-template-compiler, as it relies on
+// app/views/projects/merge_requests/conflicts/components/_inline_conflict_lines.html.haml
+// for its template.
+/* eslint-disable no-param-reassign, @gitlab/no-runtime-template-compiler */
import Vue from 'vue';
import actionsMixin from '../mixins/line_conflict_actions';
diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
index bb306e74825..1d5946cd78a 100644
--- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
+++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
@@ -15,6 +15,9 @@ import utilsMixin from '../mixins/line_conflict_utils';
required: true,
},
},
+ // This is a true violation of @gitlab/no-runtime-template-compiler, as it
+ // has a template string.
+ // eslint-disable-next-line @gitlab/no-runtime-template-compiler
template: `
<table class="diff-wrap-lines code js-syntax-highlight">
<tr class="line_holder parallel" v-for="section in file.parallelLines">
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
index 693f0b619a8..fb3444262ea 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
@@ -1,8 +1,8 @@
/* eslint-disable no-param-reassign, babel/camelcase, no-nested-ternary, no-continue */
import $ from 'jquery';
-import Vue from 'vue';
import Cookies from 'js-cookie';
+import Vue from 'vue';
import { s__ } from '~/locale';
((global) => {
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index 229f6f3e339..e3972b8b574 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
@@ -1,15 +1,19 @@
+// This is a true violation of @gitlab/no-runtime-template-compiler, as it
+// relies on app/views/projects/merge_requests/conflicts/show.html.haml for its
+// template.
+/* eslint-disable @gitlab/no-runtime-template-compiler */
import $ from 'jquery';
import Vue from 'vue';
+import { __ } from '~/locale';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { deprecatedCreateFlash as createFlash } from '../flash';
import initIssuableSidebar from '../init_issuable_sidebar';
import './merge_conflict_store';
+import syntaxHighlight from '../syntax_highlight';
import MergeConflictsService from './merge_conflict_service';
import './components/diff_file_editor';
import './components/inline_conflict_lines';
import './components/parallel_conflict_lines';
-import syntaxHighlight from '../syntax_highlight';
-import { __ } from '~/locale';
export default function initMergeConflicts() {
const INTERACTIVE_RESOLVE_MODE = 'interactive';
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index bf9e0a309dd..1a0156f8c0e 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -1,14 +1,14 @@
/* eslint-disable func-names, no-underscore-dangle, consistent-return */
import $ from 'jquery';
-import axios from './lib/utils/axios_utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale';
import eventHub from '~/vue_merge_request_widget/event_hub';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import TaskList from './task_list';
-import MergeRequestTabs from './merge_request_tabs';
+import axios from './lib/utils/axios_utils';
import { addDelimiter } from './lib/utils/text_utility';
import { getParameterValues, setUrlParams } from './lib/utils/url_utility';
+import MergeRequestTabs from './merge_request_tabs';
+import TaskList from './task_list';
function MergeRequest(opts) {
// Initialize MergeRequest behavior
diff --git a/app/assets/javascripts/merge_request/components/status_box.vue b/app/assets/javascripts/merge_request/components/status_box.vue
index fd99802caff..5d2660d65e6 100644
--- a/app/assets/javascripts/merge_request/components/status_box.vue
+++ b/app/assets/javascripts/merge_request/components/status_box.vue
@@ -5,12 +5,14 @@ import mrEventHub from '../eventhub';
const CLASSES = {
opened: 'status-box-open',
+ locked: 'status-box-open',
closed: 'status-box-mr-closed',
merged: 'status-box-mr-merged',
};
const STATUS = {
opened: [__('Open'), 'issue-open-m'],
+ locked: [__('Open'), 'issue-open-m'],
closed: [__('Closed'), 'close'],
merged: [__('Merged'), 'git-merge'],
};
@@ -59,10 +61,10 @@ export default {
<div :class="statusBoxClass" class="issuable-status-box status-box">
<gl-icon
:name="statusIconName"
- class="gl-display-block gl-display-sm-none!"
+ class="gl-display-block gl-sm-display-none!"
data-testid="status-icon"
/>
- <span class="gl-display-none gl-display-sm-block">
+ <span class="gl-display-none gl-sm-display-block">
{{ statusHumanName }}
</span>
</div>
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 81241cd2418..4dab796d8a4 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -1,13 +1,16 @@
/* eslint-disable no-new, class-methods-use-this */
-
-import $ from 'jquery';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import $ from 'jquery';
import Cookies from 'js-cookie';
+import Vue from 'vue';
+import CommitPipelinesTable from '~/commit/pipelines/pipelines_table.vue';
import createEventHub from '~/helpers/event_hub_factory';
-import axios from './lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from './flash';
+import initAddContextCommitsTriggers from './add_context_commits_modal';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
+import Diff from './diff';
+import { deprecatedCreateFlash as flash } from './flash';
import initChangesDropdown from './init_changes_dropdown';
+import axios from './lib/utils/axios_utils';
import {
parseUrlPathname,
handleLocationHash,
@@ -15,15 +18,12 @@ import {
parseBoolean,
scrollToElement,
} from './lib/utils/common_utils';
+import { localTimeAgo } from './lib/utils/datetime_utility';
import { isInVueNoteablePage } from './lib/utils/dom_utils';
import { getLocationHash } from './lib/utils/url_utility';
-import Diff from './diff';
-import { localTimeAgo } from './lib/utils/datetime_utility';
-import syntaxHighlight from './syntax_highlight';
-import Notes from './notes';
-import { polyfillSticky } from './lib/utils/sticky';
-import initAddContextCommitsTriggers from './add_context_commits_modal';
import { __ } from './locale';
+import Notes from './notes';
+import syntaxHighlight from './syntax_highlight';
// MergeRequestTabs
//
@@ -123,7 +123,6 @@ export default class MergeRequestTabs {
) {
this.mergeRequestTabs.querySelector(`a[data-action='${action}']`).click();
}
- this.initAffix();
}
bindEvents() {
@@ -352,26 +351,30 @@ export default class MergeRequestTabs {
mountPipelinesView() {
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
- const { CommitPipelinesTable, mrWidgetData } = gl;
-
- this.commitPipelinesTable = new CommitPipelinesTable({
- propsData: {
- endpoint: pipelineTableViewEl.dataset.endpoint,
- helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
- emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
- errorStateSvgPath: pipelineTableViewEl.dataset.errorStateSvgPath,
- autoDevopsHelpPath: pipelineTableViewEl.dataset.helpAutoDevopsPath,
- canCreatePipelineInTargetProject: Boolean(
- mrWidgetData?.can_create_pipeline_in_target_project,
- ),
- sourceProjectFullPath: mrWidgetData?.source_project_full_path || '',
- targetProjectFullPath: mrWidgetData?.target_project_full_path || '',
- projectId: pipelineTableViewEl.dataset.projectId,
- mergeRequestId: mrWidgetData ? mrWidgetData.iid : null,
- },
+ const { mrWidgetData } = gl;
+
+ this.commitPipelinesTable = new Vue({
provide: {
targetProjectFullPath: mrWidgetData?.target_project_full_path || '',
},
+ render(createElement) {
+ return createElement(CommitPipelinesTable, {
+ props: {
+ endpoint: pipelineTableViewEl.dataset.endpoint,
+ helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
+ emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
+ errorStateSvgPath: pipelineTableViewEl.dataset.errorStateSvgPath,
+ autoDevopsHelpPath: pipelineTableViewEl.dataset.helpAutoDevopsPath,
+ canCreatePipelineInTargetProject: Boolean(
+ mrWidgetData?.can_create_pipeline_in_target_project,
+ ),
+ sourceProjectFullPath: mrWidgetData?.source_project_full_path || '',
+ targetProjectFullPath: mrWidgetData?.target_project_full_path || '',
+ projectId: pipelineTableViewEl.dataset.projectId,
+ mergeRequestId: mrWidgetData ? mrWidgetData.iid : null,
+ },
+ });
+ },
}).$mount();
// $mount(el) replaces the el with the new rendered component. We need it in order to mount
@@ -509,21 +512,4 @@ export default class MergeRequestTabs {
}
}, 0);
}
-
- initAffix() {
- const $tabs = $('.js-tabs-affix');
-
- // Screen space on small screens is usually very sparse
- // So we dont affix the tabs on these
- if (bp.getBreakpointSize() === 'xs' || !$tabs.length) return;
-
- /**
- If the browser does not support position sticky, it returns the position as static.
- If the browser does support sticky, then we allow the browser to handle it, if not
- then we default back to Bootstraps affix
- */
- if ($tabs.css('position') !== 'static') return;
-
- polyfillSticky($tabs);
- }
}
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
index 717766578de..f249fef5ea4 100644
--- a/app/assets/javascripts/milestone.js
+++ b/app/assets/javascripts/milestone.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
-import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from './flash';
-import { mouseenter, debouncedMouseleave, togglePopover } from './shared/popover';
+import axios from './lib/utils/axios_utils';
import { __ } from './locale';
+import { mouseenter, debouncedMouseleave, togglePopover } from './shared/popover';
export default class Milestone {
constructor() {
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 921925e15c5..4cbe0a53307 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -4,16 +4,16 @@
import $ from 'jquery';
import { template, escape } from 'lodash';
-import { __, sprintf } from '~/locale';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import Api from '~/api';
-import axios from './lib/utils/axios_utils';
-import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
-import ModalStore from './boards/stores/modal_store';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __, sprintf } from '~/locale';
import boardsStore, {
boardStoreIssueSet,
boardStoreIssueDelete,
} from './boards/stores/boards_store';
+import ModalStore from './boards/stores/modal_store';
+import axios from './lib/utils/axios_utils';
+import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
export default class MilestoneSelect {
constructor(currentProject, els, options = {}) {
@@ -95,14 +95,19 @@ export default class MilestoneSelect {
name: m.title,
}))
.sort((mA, mB) => {
+ const dueDateA = mA.due_date ? parsePikadayDate(mA.due_date) : null;
+ const dueDateB = mB.due_date ? parsePikadayDate(mB.due_date) : null;
+
// Move all expired milestones to the bottom.
- if (mA.expired) {
- return 1;
- }
- if (mB.expired) {
- return -1;
- }
- return 0;
+ if (mA.expired) return 1;
+ if (mB.expired) return -1;
+
+ // Move milestones without due dates just above expired milestones.
+ if (!dueDateA) return 1;
+ if (!dueDateB) return -1;
+
+ // Sort by due date in ascending order.
+ return dueDateA - dueDateB;
}),
)
.then((data) => {
diff --git a/app/assets/javascripts/milestones/components/milestone_results_section.vue b/app/assets/javascripts/milestones/components/milestone_results_section.vue
index d53a59e58d4..b866977b974 100644
--- a/app/assets/javascripts/milestones/components/milestone_results_section.vue
+++ b/app/assets/javascripts/milestones/components/milestone_results_section.vue
@@ -77,12 +77,7 @@ export default {
</div>
</template>
<template v-else>
- <gl-dropdown-item
- v-for="{ title } in items"
- :key="title"
- role="milestone option"
- @click="$emit('selected', title)"
- >
+ <gl-dropdown-item v-for="{ title } in items" :key="title" @click="$emit('selected', title)">
<span class="gl-pl-6" :class="{ 'selected-item': isSelectedMilestone(title) }">
{{ title }}
</span>
diff --git a/app/assets/javascripts/mirrors/mirror_repos.js b/app/assets/javascripts/mirrors/mirror_repos.js
index f7200f22471..a26c8f85958 100644
--- a/app/assets/javascripts/mirrors/mirror_repos.js
+++ b/app/assets/javascripts/mirrors/mirror_repos.js
@@ -1,10 +1,10 @@
import $ from 'jquery';
import { debounce } from 'lodash';
-import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import SSHMirror from './ssh_mirror';
+import { __ } from '~/locale';
import { hide } from '~/tooltips';
+import SSHMirror from './ssh_mirror';
export default class MirrorRepos {
constructor(container) {
diff --git a/app/assets/javascripts/mirrors/ssh_mirror.js b/app/assets/javascripts/mirrors/ssh_mirror.js
index b692db10e2d..15ded478405 100644
--- a/app/assets/javascripts/mirrors/ssh_mirror.js
+++ b/app/assets/javascripts/mirrors/ssh_mirror.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
import { escape } from 'lodash';
-import { __ } from '~/locale';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { backOff } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
import AUTH_METHOD from './constants';
export default class SSHMirror {
diff --git a/app/assets/javascripts/monitoring/components/alert_widget.vue b/app/assets/javascripts/monitoring/components/alert_widget.vue
index bf31b86561a..9724ef9950b 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget.vue
@@ -1,12 +1,13 @@
<script>
import { GlBadge, GlLoadingIcon, GlModalDirective, GlIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
import { values, get } from 'lodash';
-import { s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import AlertWidgetForm from './alert_widget_form.vue';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
+import { s__ } from '~/locale';
+import { OPERATORS } from '../constants';
import AlertsService from '../services/alerts_service';
import { alertsValidator, queriesValidator } from '../validators';
-import { OPERATORS } from '../constants';
+import AlertWidgetForm from './alert_widget_form.vue';
export default {
components: {
@@ -165,11 +166,11 @@ export default {
return get(alertQuery, 'result[0].values', []).map((value) => get(value, '[1]', null));
},
showModal() {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
hideModal() {
this.errorMessage = null;
- this.$root.$emit('bv::hide::modal', this.modalId);
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
},
handleSetApiAction(apiAction) {
this.apiAction = apiAction;
diff --git a/app/assets/javascripts/monitoring/components/alert_widget_form.vue b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
index b26941891e4..68fd3e256ec 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget_form.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
@@ -1,6 +1,4 @@
<script>
-import { isEmpty, findKey } from 'lodash';
-import Vue from 'vue';
import {
GlLink,
GlButton,
@@ -13,12 +11,14 @@ import {
GlTooltipDirective,
GlIcon,
} from '@gitlab/ui';
+import { isEmpty, findKey } from 'lodash';
+import Vue from 'vue';
import { __, s__ } from '~/locale';
-import Translate from '~/vue_shared/translate';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { alertsValidator, queriesValidator } from '../validators';
+import Translate from '~/vue_shared/translate';
import { OPERATORS } from '../constants';
+import { alertsValidator, queriesValidator } from '../validators';
Vue.use(Translate);
diff --git a/app/assets/javascripts/monitoring/components/charts/anomaly.vue b/app/assets/javascripts/monitoring/components/charts/anomaly.vue
index cb533c38fa0..8569a67da34 100644
--- a/app/assets/javascripts/monitoring/components/charts/anomaly.vue
+++ b/app/assets/javascripts/monitoring/components/charts/anomaly.vue
@@ -1,9 +1,9 @@
<script>
+import { GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import produce from 'immer';
import { flattenDeep, isNumber } from 'lodash';
-import { GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
-import { roundOffFloat } from '~/lib/utils/common_utils';
import { hexToRgb } from '~/lib/utils/color_utils';
+import { roundOffFloat } from '~/lib/utils/common_utils';
import { areaOpacityValues, symbolSizes, colorValues, panelTypes } from '../../constants';
import { graphDataValidatorForAnomalyValues } from '../../utils';
import MonitorTimeSeriesChart from './time_series.vue';
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue
index ba947c2fa9c..37251af2049 100644
--- a/app/assets/javascripts/monitoring/components/charts/column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/column.vue
@@ -1,12 +1,12 @@
<script>
import { GlResizeObserverDirective } from '@gitlab/ui';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import { makeDataSeries } from '~/helpers/monitor_helper';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import { chartHeight } from '../../constants';
-import { makeDataSeries } from '~/helpers/monitor_helper';
+import { timezones } from '../../format_date';
import { graphDataValidatorForValues } from '../../utils';
import { getTimeAxisOptions, getYAxisOptions, getChartGrid } from './options';
-import { timezones } from '../../format_date';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/charts/gauge.vue b/app/assets/javascripts/monitoring/components/charts/gauge.vue
index 63fa60bbdf0..461ff06be72 100644
--- a/app/assets/javascripts/monitoring/components/charts/gauge.vue
+++ b/app/assets/javascripts/monitoring/components/charts/gauge.vue
@@ -2,9 +2,9 @@
import { GlResizeObserverDirective } from '@gitlab/ui';
import { GlGaugeChart } from '@gitlab/ui/dist/charts';
import { isFinite, isArray, isInteger } from 'lodash';
+import { getFormatter, SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
import { graphDataValidatorForValues } from '../../utils';
import { getValidThresholds } from './options';
-import { getFormatter, SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/charts/heatmap.vue b/app/assets/javascripts/monitoring/components/charts/heatmap.vue
index 22214a76aba..ed888ef022c 100644
--- a/app/assets/javascripts/monitoring/components/charts/heatmap.vue
+++ b/app/assets/javascripts/monitoring/components/charts/heatmap.vue
@@ -1,8 +1,8 @@
<script>
import { GlResizeObserverDirective } from '@gitlab/ui';
import { GlHeatmap } from '@gitlab/ui/dist/charts';
-import { graphDataValidatorForValues } from '../../utils';
import { formatDate, timezones, formats } from '../../format_date';
+import { graphDataValidatorForValues } from '../../utils';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/charts/options.js b/app/assets/javascripts/monitoring/components/charts/options.js
index 163a7be6973..643550a7144 100644
--- a/app/assets/javascripts/monitoring/components/charts/options.js
+++ b/app/assets/javascripts/monitoring/components/charts/options.js
@@ -1,8 +1,8 @@
import { isFinite, uniq, sortBy, includes } from 'lodash';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { __, s__ } from '~/locale';
-import { formatDate, timezones, formats } from '../../format_date';
import { thresholdModeTypes } from '../../constants';
+import { formatDate, timezones, formats } from '../../format_date';
const yAxisBoundaryGap = [0.1, 0.1];
/**
diff --git a/app/assets/javascripts/monitoring/components/charts/single_stat.vue b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
index a8ab41ebf26..6d6a7af600b 100644
--- a/app/assets/javascripts/monitoring/components/charts/single_stat.vue
+++ b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
@@ -1,7 +1,7 @@
<script>
import { GlSingleStat } from '@gitlab/ui/dist/charts';
-import { __ } from '~/locale';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
+import { __ } from '~/locale';
import { graphDataValidatorForValues } from '../../utils';
const defaultPrecision = 2;
@@ -45,12 +45,18 @@ export default {
}
if (this.graphData?.maxValue) {
- formatter = getFormatter(SUPPORTED_FORMATS.percent);
- return formatter(this.queryResult / Number(this.graphData.maxValue), defaultPrecision);
+ formatter = getFormatter(SUPPORTED_FORMATS.number);
+ return formatter(
+ (this.queryResult / Number(this.graphData.maxValue)) * 100,
+ defaultPrecision,
+ );
}
formatter = getFormatter(SUPPORTED_FORMATS.number);
- return `${formatter(this.queryResult, defaultPrecision)}${this.queryInfo.unit ?? ''}`;
+ return `${formatter(this.queryResult, defaultPrecision)}`;
+ },
+ unit() {
+ return this.graphData?.maxValue ? '%' : this.queryInfo.unit;
},
graphTitle() {
return this.queryInfo.label;
@@ -60,6 +66,6 @@ export default {
</script>
<template>
<div>
- <gl-single-stat :value="statValue" :title="graphTitle" variant="success" />
+ <gl-single-stat :value="statValue" :title="graphTitle" :unit="unit" variant="success" />
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/charts/stacked_column.vue b/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
index b5ae6bcfd13..a53f899f752 100644
--- a/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/stacked_column.vue
@@ -2,11 +2,11 @@
import { GlResizeObserverDirective } from '@gitlab/ui';
import { GlStackedColumnChart } from '@gitlab/ui/dist/charts';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
-import { chartHeight, legendLayoutTypes } from '../../constants';
import { s__ } from '~/locale';
+import { chartHeight, legendLayoutTypes } from '../../constants';
+import { formats, timezones } from '../../format_date';
import { graphDataValidatorForValues } from '../../utils';
import { getTimeAxisOptions, axisTypes } from './options';
-import { formats, timezones } from '../../format_date';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index e9f7b11c977..99008d047af 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -1,15 +1,15 @@
<script>
-import { isEmpty, omit, throttle } from 'lodash';
import { GlLink, GlTooltip, GlResizeObserverDirective, GlIcon } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
-import { s__ } from '~/locale';
+import { isEmpty, omit, throttle } from 'lodash';
+import { makeDataSeries } from '~/helpers/monitor_helper';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
+import { s__ } from '~/locale';
import { panelTypes, chartHeight, lineTypes, lineWidths, legendLayoutTypes } from '../../constants';
-import { getYAxisOptions, getTimeAxisOptions, getChartGrid, getTooltipFormatter } from './options';
-import { annotationsYAxis, generateAnnotationsSeries } from './annotations';
-import { makeDataSeries } from '~/helpers/monitor_helper';
-import { graphDataValidatorForValues } from '../../utils';
import { formatDate, timezones } from '../../format_date';
+import { graphDataValidatorForValues } from '../../utils';
+import { annotationsYAxis, generateAnnotationsSeries } from './annotations';
+import { getYAxisOptions, getTimeAxisOptions, getChartGrid, getTooltipFormatter } from './options';
export const timestampToISODate = (timestamp) => new Date(timestamp).toISOString();
diff --git a/app/assets/javascripts/monitoring/components/create_dashboard_modal.vue b/app/assets/javascripts/monitoring/components/create_dashboard_modal.vue
index 74799002b17..bfaf8b2bd28 100644
--- a/app/assets/javascripts/monitoring/components/create_dashboard_modal.vue
+++ b/app/assets/javascripts/monitoring/components/create_dashboard_modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlModal, GlSprintf } from '@gitlab/ui';
-import { s__ } from '~/locale';
import { isSafeURL } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
export default {
components: { GlButton, GlModal, GlSprintf },
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 16c2c87a4b7..bfb18206b62 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,31 +1,30 @@
<script>
-import { mapActions, mapState, mapGetters } from 'vuex';
-import VueDraggable from 'vuedraggable';
-import Mousetrap from 'mousetrap';
import { GlButton, GlModalDirective, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import DashboardHeader from './dashboard_header.vue';
-import DashboardPanel from './dashboard_panel.vue';
-import { s__ } from '~/locale';
+import Mousetrap from 'mousetrap';
+import VueDraggable from 'vuedraggable';
+import { mapActions, mapState, mapGetters } from 'vuex';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import invalidUrl from '~/lib/utils/invalid_url';
import { ESC_KEY } from '~/lib/utils/keys';
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
-import invalidUrl from '~/lib/utils/invalid_url';
-
-import GraphGroup from './graph_group.vue';
-import EmptyState from './empty_state.vue';
-import GroupEmptyState from './group_empty_state.vue';
-import VariablesSection from './variables_section.vue';
-import LinksSection from './links_section.vue';
-
+import { s__ } from '~/locale';
+import { defaultTimeRange } from '~/vue_shared/constants';
import TrackEventDirective from '~/vue_shared/directives/track_event';
+import { metricStates, keyboardShortcutKeys } from '../constants';
import {
timeRangeFromUrl,
panelToUrl,
expandedPanelPayloadFromUrl,
convertVariablesForURL,
} from '../utils';
-import { metricStates, keyboardShortcutKeys } from '../constants';
-import { defaultTimeRange } from '~/vue_shared/constants';
+import DashboardHeader from './dashboard_header.vue';
+import DashboardPanel from './dashboard_panel.vue';
+
+import EmptyState from './empty_state.vue';
+import GraphGroup from './graph_group.vue';
+import GroupEmptyState from './group_empty_state.vue';
+import LinksSection from './links_section.vue';
+import VariablesSection from './variables_section.vue';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
index 9d1926dca54..94cfb562ce3 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState, mapGetters, mapActions } from 'vuex';
import {
GlButton,
GlDropdown,
@@ -10,15 +9,16 @@ import {
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
+import { mapState, mapGetters, mapActions } from 'vuex';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
-import { PANEL_NEW_PAGE } from '../router/constants';
-import DuplicateDashboardModal from './duplicate_dashboard_modal.vue';
-import CreateDashboardModal from './create_dashboard_modal.vue';
-import { s__ } from '~/locale';
import invalidUrl from '~/lib/utils/invalid_url';
import { redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
import TrackEventDirective from '~/vue_shared/directives/track_event';
+import { PANEL_NEW_PAGE } from '../router/constants';
import { getAddMetricTrackingOptions } from '../utils';
+import CreateDashboardModal from './create_dashboard_modal.vue';
+import DuplicateDashboardModal from './duplicate_dashboard_modal.vue';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/dashboard_header.vue b/app/assets/javascripts/monitoring/components/dashboard_header.vue
index 0f6a9ce3814..3c423bea368 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_header.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_header.vue
@@ -1,6 +1,4 @@
<script>
-import { debounce } from 'lodash';
-import { mapActions, mapState, mapGetters } from 'vuex';
import {
GlButton,
GlDropdown,
@@ -12,17 +10,18 @@ import {
GlTooltipDirective,
GlIcon,
} from '@gitlab/ui';
-import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
+import { debounce } from 'lodash';
+import { mapActions, mapState, mapGetters } from 'vuex';
import invalidUrl from '~/lib/utils/invalid_url';
+import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
-import DashboardsDropdown from './dashboards_dropdown.vue';
-import RefreshButton from './refresh_button.vue';
-import ActionsMenu from './dashboard_actions_menu.vue';
-
-import { timeRangeToUrl } from '../utils';
import { timeRanges } from '~/vue_shared/constants';
import { timezones } from '../format_date';
+import { timeRangeToUrl } from '../utils';
+import ActionsMenu from './dashboard_actions_menu.vue';
+import DashboardsDropdown from './dashboards_dropdown.vue';
+import RefreshButton from './refresh_button.vue';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 2b0c3d03b8d..55e73d17842 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -1,6 +1,4 @@
<script>
-import { mapState } from 'vuex';
-import { mapValues, pickBy } from 'lodash';
import {
GlResizeObserverDirective,
GlIcon,
@@ -15,26 +13,28 @@ import {
GlTooltip,
GlTooltipDirective,
} from '@gitlab/ui';
-import invalidUrl from '~/lib/utils/invalid_url';
+import { mapValues, pickBy } from 'lodash';
+import { mapState } from 'vuex';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
+import invalidUrl from '~/lib/utils/invalid_url';
import { relativePathToAbsolute, getBaseURL, visitUrl, isSafeURL } from '~/lib/utils/url_utility';
import { __, n__ } from '~/locale';
+import TrackEventDirective from '~/vue_shared/directives/track_event';
import { panelTypes } from '../constants';
-import MonitorEmptyChart from './charts/empty_chart.vue';
-import MonitorTimeSeriesChart from './charts/time_series.vue';
+import { graphDataToCsv } from '../csv_export';
+import { timeRangeToUrl, downloadCSVOptions, generateLinkToChartOptions } from '../utils';
+import AlertWidget from './alert_widget.vue';
import MonitorAnomalyChart from './charts/anomaly.vue';
-import MonitorSingleStatChart from './charts/single_stat.vue';
+import MonitorBarChart from './charts/bar.vue';
+import MonitorColumnChart from './charts/column.vue';
+import MonitorEmptyChart from './charts/empty_chart.vue';
import MonitorGaugeChart from './charts/gauge.vue';
import MonitorHeatmapChart from './charts/heatmap.vue';
-import MonitorColumnChart from './charts/column.vue';
-import MonitorBarChart from './charts/bar.vue';
+import MonitorSingleStatChart from './charts/single_stat.vue';
import MonitorStackedColumnChart from './charts/stacked_column.vue';
-
-import TrackEventDirective from '~/vue_shared/directives/track_event';
-import AlertWidget from './alert_widget.vue';
-import { timeRangeToUrl, downloadCSVOptions, generateLinkToChartOptions } from '../utils';
-import { graphDataToCsv } from '../csv_export';
+import MonitorTimeSeriesChart from './charts/time_series.vue';
const events = {
timeRangeZoom: 'timerangezoom',
@@ -318,7 +318,7 @@ export default {
return isSafeURL(url) ? url : '#';
},
showAlertModal() {
- this.$root.$emit('bv::show::modal', this.alertModalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.alertModalId);
},
showAlertModalFromKeyboardShortcut() {
if (this.isContextualMenuShown) {
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
index bcfa1b04322..847339e814a 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapState } from 'vuex';
import {
GlCard,
GlForm,
@@ -10,6 +9,7 @@ import {
GlAlert,
GlTooltipDirective,
} from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import { timeRanges } from '~/vue_shared/constants';
import DashboardPanel from './dashboard_panel.vue';
diff --git a/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue b/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue
index 1a349aa154a..1238996154d 100644
--- a/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue
+++ b/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState, mapGetters } from 'vuex';
import {
GlIcon,
GlDropdown,
@@ -9,6 +8,7 @@ import {
GlSearchBoxByType,
GlModalDirective,
} from '@gitlab/ui';
+import { mapState, mapGetters } from 'vuex';
const events = {
selectDashboard: 'selectDashboard',
diff --git a/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue b/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue
index b87934a1db2..49d7e3a48a7 100644
--- a/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue
+++ b/app/assets/javascripts/monitoring/components/duplicate_dashboard_modal.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
import { GlAlert, GlLoadingIcon, GlModal } from '@gitlab/ui';
+import { mapActions, mapGetters } from 'vuex';
import { s__ } from '~/locale';
import DuplicateDashboardForm from './duplicate_dashboard_form.vue';
diff --git a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
index c114ae1809f..8eef3d69a4f 100644
--- a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
@@ -1,7 +1,7 @@
<script>
-import { mapState, mapActions, mapGetters } from 'vuex';
-import sum from 'lodash/sum';
import { GlButton, GlCard, GlIcon } from '@gitlab/ui';
+import sum from 'lodash/sum';
+import { mapState, mapActions, mapGetters } from 'vuex';
import { n__ } from '~/locale';
import { monitoringDashboard } from '~/monitoring/stores';
import MetricEmbed from './metric_embed.vue';
diff --git a/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue b/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
index 2fe49152c4f..25500747573 100644
--- a/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
@@ -1,10 +1,10 @@
<script>
import { mapState, mapActions } from 'vuex';
-import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
+import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import { defaultTimeRange } from '~/vue_shared/constants';
-import { timeRangeFromUrl, removeTimeRangeParams } from '../../utils';
import { sidebarAnimationDuration } from '../../constants';
+import { timeRangeFromUrl, removeTimeRangeParams } from '../../utils';
let sidebarMutationObserver;
diff --git a/app/assets/javascripts/monitoring/components/links_section.vue b/app/assets/javascripts/monitoring/components/links_section.vue
index ca1e9c4d0d4..3f9f57d4ac1 100644
--- a/app/assets/javascripts/monitoring/components/links_section.vue
+++ b/app/assets/javascripts/monitoring/components/links_section.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlIcon, GlLink } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
export default {
components: {
@@ -15,12 +15,12 @@ export default {
<template>
<div
ref="linksSection"
- class="gl-display-sm-flex gl-flex-sm-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
+ class="gl-sm-display-flex gl-flex-sm-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
>
<div
v-for="(link, key) in links"
:key="key"
- class="gl-mb-1 gl-mr-5 gl-display-flex gl-display-sm-block gl-hover-text-blue-600-children gl-word-break-all"
+ class="gl-mb-1 gl-mr-5 gl-display-flex gl-sm-display-block gl-hover-text-blue-600-children gl-word-break-all"
>
<gl-link :href="link.url" class="gl-text-gray-900 gl-text-decoration-none!"
><gl-icon name="link" class="gl-text-gray-500 gl-vertical-align-text-bottom gl-mr-2" />{{
diff --git a/app/assets/javascripts/monitoring/components/refresh_button.vue b/app/assets/javascripts/monitoring/components/refresh_button.vue
index e0d9f92440b..3daf5b38933 100644
--- a/app/assets/javascripts/monitoring/components/refresh_button.vue
+++ b/app/assets/javascripts/monitoring/components/refresh_button.vue
@@ -1,6 +1,4 @@
<script>
-import Visibility from 'visibilityjs';
-import { mapActions } from 'vuex';
import {
GlButtonGroup,
GlButton,
@@ -9,6 +7,8 @@ import {
GlDropdownDivider,
GlTooltipDirective,
} from '@gitlab/ui';
+import Visibility from 'visibilityjs';
+import { mapActions } from 'vuex';
import { n__, __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
diff --git a/app/assets/javascripts/monitoring/components/variables_section.vue b/app/assets/javascripts/monitoring/components/variables_section.vue
index 7c4fb135ec8..493d37ce263 100644
--- a/app/assets/javascripts/monitoring/components/variables_section.vue
+++ b/app/assets/javascripts/monitoring/components/variables_section.vue
@@ -1,9 +1,9 @@
<script>
import { mapState, mapActions } from 'vuex';
+import { VARIABLE_TYPES } from '../constants';
+import { setCustomVariablesFromUrl } from '../utils';
import DropdownField from './variables/dropdown_field.vue';
import TextField from './variables/text_field.vue';
-import { setCustomVariablesFromUrl } from '../utils';
-import { VARIABLE_TYPES } from '../constants';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js
index 81ad3137b8b..060ed896d7c 100644
--- a/app/assets/javascripts/monitoring/constants.js
+++ b/app/assets/javascripts/monitoring/constants.js
@@ -151,7 +151,7 @@ export const linkTypes = {
* chart legend layout.
*
* Currently defined in
- * https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/src/utils/charts/constants.js
+ * https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/src/utils/charts/constants.js
*
*/
export const legendLayoutTypes = {
diff --git a/app/assets/javascripts/monitoring/monitoring_app.js b/app/assets/javascripts/monitoring/monitoring_app.js
index 307154c9a84..ee67e5dd827 100644
--- a/app/assets/javascripts/monitoring/monitoring_app.js
+++ b/app/assets/javascripts/monitoring/monitoring_app.js
@@ -1,7 +1,7 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
-import { createStore } from './stores';
+import Vue from 'vue';
import createRouter from './router';
+import { createStore } from './stores';
import { stateAndPropsFromDataset } from './utils';
Vue.use(GlToast);
@@ -26,7 +26,24 @@ export default (props = {}) => {
dashboardProps: { ...dataProps, ...props },
};
},
- template: `<router-view :dashboardProps="dashboardProps"/>`,
+ render(h) {
+ return h('RouterView', {
+ // This is attrs rather than props because:
+ // 1. RouterView only actually defines one prop: `name`.
+ // 2. The RouterView [throws away other props][1] given to it, in
+ // favour of those configured in the route config/params.
+ // 3. The Vue template compiler itself in general compiles anything
+ // like <some-component :foo="bar" /> into roughly
+ // h('some-component', { attrs: { foo: bar } }). Then later, Vue
+ // [extract props from attrs and merges them with props][2],
+ // matching them up according to the component's definition.
+ // [1]: https://github.com/vuejs/vue-router/blob/v3.4.9/src/components/view.js#L124
+ // [2]: https://github.com/vuejs/vue/blob/v2.6.12/src/core/vdom/helpers/extract-props.js#L12-L50
+ attrs: {
+ dashboardProps: this.dashboardProps,
+ },
+ });
+ },
});
}
};
diff --git a/app/assets/javascripts/monitoring/pages/panel_new_page.vue b/app/assets/javascripts/monitoring/pages/panel_new_page.vue
index 8ff6adb47ca..dbda6e80dac 100644
--- a/app/assets/javascripts/monitoring/pages/panel_new_page.vue
+++ b/app/assets/javascripts/monitoring/pages/panel_new_page.vue
@@ -1,9 +1,9 @@
<script>
-import { mapState } from 'vuex';
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
import { s__ } from '~/locale';
-import { DASHBOARD_PAGE } from '../router/constants';
import DashboardPanelBuilder from '../components/dashboard_panel_builder.vue';
+import { DASHBOARD_PAGE } from '../router/constants';
export default {
components: {
diff --git a/app/assets/javascripts/monitoring/requests/index.js b/app/assets/javascripts/monitoring/requests/index.js
index 4a12ca06197..26fedb9c81c 100644
--- a/app/assets/javascripts/monitoring/requests/index.js
+++ b/app/assets/javascripts/monitoring/requests/index.js
@@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
-import statusCodes from '~/lib/utils/http_status';
import { backOff } from '~/lib/utils/common_utils';
+import statusCodes from '~/lib/utils/http_status';
import { PROMETHEUS_TIMEOUT } from '../constants';
const cancellableBackOffRequest = (makeRequestCallback) =>
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 44c200cdb54..8522ac6a57d 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -1,23 +1,23 @@
-import * as Sentry from '~/sentry/wrapper';
-import * as types from './mutation_types';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
+import * as Sentry from '~/sentry/wrapper';
+import { convertObjectPropsToCamelCase } from '../../lib/utils/common_utils';
+import { s__, sprintf } from '../../locale';
+import { ENVIRONMENT_AVAILABLE_STATE, OVERVIEW_DASHBOARD_PATH, VARIABLE_TYPES } from '../constants';
+import trackDashboardLoad from '../monitoring_tracking_helper';
+import getAnnotations from '../queries/getAnnotations.query.graphql';
+import getDashboardValidationWarnings from '../queries/getDashboardValidationWarnings.query.graphql';
+import getEnvironments from '../queries/getEnvironments.query.graphql';
+import { getDashboard, getPrometheusQueryData } from '../requests';
+
+import * as types from './mutation_types';
import {
gqClient,
parseEnvironmentsResponse,
parseAnnotationsResponse,
removeLeadingSlash,
} from './utils';
-import trackDashboardLoad from '../monitoring_tracking_helper';
-import getEnvironments from '../queries/getEnvironments.query.graphql';
-import getAnnotations from '../queries/getAnnotations.query.graphql';
-import getDashboardValidationWarnings from '../queries/getDashboardValidationWarnings.query.graphql';
-import { convertObjectPropsToCamelCase } from '../../lib/utils/common_utils';
-import { s__, sprintf } from '../../locale';
-import { getDashboard, getPrometheusQueryData } from '../requests';
-
-import { ENVIRONMENT_AVAILABLE_STATE, OVERVIEW_DASHBOARD_PATH, VARIABLE_TYPES } from '../constants';
const axiosCancelToken = axios.CancelToken;
let cancelTokenSource;
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index 5c5a7d03b97..e0eaf76b5f6 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -1,10 +1,10 @@
-import Vue from 'vue';
import { pick } from 'lodash';
-import * as types from './mutation_types';
-import { mapToDashboardViewModel, mapPanelToViewModel, normalizeQueryResponseData } from './utils';
-import httpStatusCodes from '~/lib/utils/http_status';
+import Vue from 'vue';
import { BACKOFF_TIMEOUT } from '~/lib/utils/common_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
import { dashboardEmptyStates, endpointKeys, initialStateKeys, metricStates } from '../constants';
+import * as types from './mutation_types';
+import { mapToDashboardViewModel, mapPanelToViewModel, normalizeQueryResponseData } from './utils';
import { optionsFromSeriesData } from './variable_mapping';
/**
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
index ef8b1adb624..3883fa3380d 100644
--- a/app/assets/javascripts/monitoring/stores/state.js
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -1,7 +1,7 @@
import invalidUrl from '~/lib/utils/invalid_url';
-import { timezones } from '../format_date';
-import { dashboardEmptyStates } from '../constants';
import { defaultTimeRange } from '~/vue_shared/constants';
+import { dashboardEmptyStates } from '../constants';
+import { timezones } from '../format_date';
export default () => ({
// API endpoints
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 36e5a135d59..20f7c5cdb60 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -1,12 +1,12 @@
-import { slugify } from '~/lib/utils/text_utility';
-import createGqClient, { fetchPolicies } from '~/lib/graphql';
-import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { mergeURLVariables, parseTemplatingVariables } from './variable_mapping';
+import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { DATETIME_RANGE_TYPES } from '~/lib/utils/constants';
import { timeRangeToParams, getRangeType } from '~/lib/utils/datetime_range';
+import { slugify } from '~/lib/utils/text_utility';
+import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
import { isSafeURL, mergeUrlParams } from '~/lib/utils/url_utility';
import { NOT_IN_DB_PREFIX, linkTypes, OUT_OF_THE_BOX_DASHBOARDS_PATH_PREFIX } from '../constants';
+import { mergeURLVariables, parseTemplatingVariables } from './variable_mapping';
export const gqClient = createGqClient(
{},
diff --git a/app/assets/javascripts/monitoring/stores/variable_mapping.js b/app/assets/javascripts/monitoring/stores/variable_mapping.js
index c9e0e383582..4ca7a0b51d6 100644
--- a/app/assets/javascripts/monitoring/stores/variable_mapping.js
+++ b/app/assets/javascripts/monitoring/stores/variable_mapping.js
@@ -1,6 +1,6 @@
import { isString } from 'lodash';
-import { templatingVariablesFromUrl } from '../utils';
import { VARIABLE_TYPES } from '../constants';
+import { templatingVariablesFromUrl } from '../utils';
/**
* This file exclusively deals with parsing user-defined variables
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index 01cae7127e5..6306415a8b9 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -1,16 +1,16 @@
import { pickBy, mapKeys } from 'lodash';
-import {
- queryToObject,
- mergeUrlParams,
- removeParams,
- updateHistory,
-} from '~/lib/utils/url_utility';
import { parseBoolean } from '~/lib/utils/common_utils';
import {
timeRangeParamNames,
timeRangeFromParams,
timeRangeToParams,
} from '~/lib/utils/datetime_range';
+import {
+ queryToObject,
+ mergeUrlParams,
+ removeParams,
+ updateHistory,
+} from '~/lib/utils/url_utility';
import { VARIABLE_PREFIX } from './constants';
/**
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index fb6ef0249bb..a7696a716d0 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -1,12 +1,14 @@
import Vue from 'vue';
import store from '~/mr_notes/stores';
-import initNotesApp from './init_notes';
+import initCherryPickCommitModal from '~/projects/commit/init_cherry_pick_commit_modal';
+import initRevertCommitModal from '~/projects/commit/init_revert_commit_modal';
import initDiffsApp from '../diffs';
+import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
+import MergeRequest from '../merge_request';
import discussionCounter from '../notes/components/discussion_counter.vue';
import initDiscussionFilters from '../notes/discussion_filters';
import initSortDiscussions from '../notes/sort_discussions';
-import MergeRequest from '../merge_request';
-import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
+import initNotesApp from './init_notes';
export default function initMrNotes() {
resetServiceWorkersPublicPath();
@@ -19,6 +21,11 @@ export default function initMrNotes() {
initNotesApp();
+ document.addEventListener('merged:UpdateActions', () => {
+ initRevertCommitModal();
+ initCherryPickCommitModal();
+ });
+
// eslint-disable-next-line no-new
new Vue({
el: '#js-vue-discussion-counter',
diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js
index ab88a610469..9a93e90c2bb 100644
--- a/app/assets/javascripts/mr_notes/init_notes.js
+++ b/app/assets/javascripts/mr_notes/init_notes.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex';
+import { parseBoolean } from '~/lib/utils/common_utils';
import store from '~/mr_notes/stores';
-import notesApp from '../notes/components/notes_app.vue';
import discussionNavigator from '../notes/components/discussion_navigator.vue';
+import notesApp from '../notes/components/notes_app.vue';
import initWidget from '../vue_merge_request_widget';
-import { parseBoolean } from '~/lib/utils/common_utils';
export default () => {
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/mr_notes/stores/index.js b/app/assets/javascripts/mr_notes/stores/index.js
index 8492b8d0aff..4a0602ad512 100644
--- a/app/assets/javascripts/mr_notes/stores/index.js
+++ b/app/assets/javascripts/mr_notes/stores/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
import batchCommentsModule from '~/batch_comments/stores/modules/batch_comments';
-import notesModule from '~/notes/stores/modules';
import diffsModule from '~/diffs/store/modules';
+import notesModule from '~/notes/stores/modules';
import mrPageModule from './modules';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/mr_popover/components/mr_popover.vue b/app/assets/javascripts/mr_popover/components/mr_popover.vue
index 2058f0c9b76..791fdf7660f 100644
--- a/app/assets/javascripts/mr_popover/components/mr_popover.vue
+++ b/app/assets/javascripts/mr_popover/components/mr_popover.vue
@@ -3,8 +3,8 @@
import { GlPopover, GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import timeagoMixin from '../../vue_shared/mixins/timeago';
-import query from '../queries/merge_request.query.graphql';
import { mrStates, humanMRStates } from '../constants';
+import query from '../queries/merge_request.query.graphql';
export default {
// name: 'MRPopover' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
diff --git a/app/assets/javascripts/mr_popover/index.js b/app/assets/javascripts/mr_popover/index.js
index 03ddfd13d50..714cf67e0bd 100644
--- a/app/assets/javascripts/mr_popover/index.js
+++ b/app/assets/javascripts/mr_popover/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import MRPopover from './components/mr_popover.vue';
import createDefaultClient from '~/lib/graphql';
+import MRPopover from './components/mr_popover.vue';
let renderedPopover;
let renderFn;
diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js
index e668b492ebe..af7a600d1ad 100644
--- a/app/assets/javascripts/namespace_select.js
+++ b/app/assets/javascripts/namespace_select.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { parseBoolean } from '~/lib/utils/common_utils';
import Api from './api';
import { mergeUrlParams } from './lib/utils/url_utility';
-import { parseBoolean } from '~/lib/utils/common_utils';
import { __ } from './locale';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class NamespaceSelect {
constructor(opts) {
diff --git a/app/assets/javascripts/namespaces/leave_by_url.js b/app/assets/javascripts/namespaces/leave_by_url.js
index 7b15253d872..094590804c1 100644
--- a/app/assets/javascripts/namespaces/leave_by_url.js
+++ b/app/assets/javascripts/namespaces/leave_by_url.js
@@ -1,7 +1,7 @@
-import { initRails } from '~/lib/utils/rails_ujs';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import { __, sprintf } from '~/locale';
import { getParameterByName } from '~/lib/utils/common_utils';
+import { initRails } from '~/lib/utils/rails_ujs';
+import { __, sprintf } from '~/locale';
const PARAMETER_NAME = 'leave';
const LEAVE_LINK_SELECTOR = '.js-leave-link';
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index 3574fc47088..1f360e84f68 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -1,8 +1,8 @@
/* eslint-disable func-names, consistent-return */
import $ from 'jquery';
-import { __ } from '../locale';
import axios from '../lib/utils/axios_utils';
+import { __ } from '../locale';
import Raphael from './raphael';
export default class BranchGraph {
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index d1d5ae5265a..e4cde0d4ff3 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -1,7 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
-import marked from 'marked';
import katex from 'katex';
+import marked from 'marked';
import { sanitize } from '~/lib/dompurify';
import Prompt from './prompt.vue';
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 857e5a34db6..8ed40f36103 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -10,24 +10,22 @@ class-methods-use-this */
old_notes_spec.js is the spec for the legacy, jQuery notes application. It has nothing to do with the new, fancy Vue notes app.
*/
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import Autosize from 'autosize';
import $ from 'jquery';
-import '~/lib/utils/jquery_at_who';
-import { escape, uniqueId } from 'lodash';
import Cookies from 'js-cookie';
-import Autosize from 'autosize';
+import { escape, uniqueId } from 'lodash';
import Vue from 'vue';
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import '~/lib/utils/jquery_at_who';
import AjaxCache from '~/lib/utils/ajax_cache';
import syntaxHighlight from '~/syntax_highlight';
-import axios from './lib/utils/axios_utils';
-import { getLocationHash } from './lib/utils/url_utility';
+import Autosave from './autosave';
+import loadAwardsHandler from './awards_handler';
+import CommentTypeToggle from './comment_type_toggle';
import { deprecatedCreateFlash as Flash } from './flash';
import { defaultAutocompleteConfig } from './gfm_auto_complete';
-import CommentTypeToggle from './comment_type_toggle';
import GLForm from './gl_form';
-import loadAwardsHandler from './awards_handler';
-import Autosave from './autosave';
-import TaskList from './task_list';
+import axios from './lib/utils/axios_utils';
import {
isInViewport,
getPagePath,
@@ -36,7 +34,9 @@ import {
isInMRPage,
} from './lib/utils/common_utils';
import { localTimeAgo } from './lib/utils/datetime_utility';
+import { getLocationHash } from './lib/utils/url_utility';
import { sprintf, s__, __ } from './locale';
+import TaskList from './task_list';
window.autosize = Autosize;
@@ -904,18 +904,7 @@ export default class Notes {
// DiffNote
form.find('#note_position').val(dataHolder.attr('data-position'));
- form
- .prepend(
- `<a href="${escape(
- gon.current_username,
- )}" class="user-avatar-link d-none d-sm-block"><img class="avatar s40" src="${encodeURI(
- gon.current_user_avatar_url || gon.default_avatar_url,
- )}" alt="${escape(gon.current_user_fullname)}" /></a>`,
- )
- .append('</div>')
- .find('.js-close-discussion-note-form')
- .show()
- .removeClass('hide');
+ form.append('</div>').find('.js-close-discussion-note-form').show().removeClass('hide');
form.find('.js-note-target-close').remove();
form.find('.js-note-new-discussion').remove();
this.setupNoteForm(form);
diff --git a/app/assets/javascripts/notes/components/comment_field_layout.vue b/app/assets/javascripts/notes/components/comment_field_layout.vue
index aaf64702ffd..47d14783d5d 100644
--- a/app/assets/javascripts/notes/components/comment_field_layout.vue
+++ b/app/assets/javascripts/notes/components/comment_field_layout.vue
@@ -1,6 +1,6 @@
<script>
-import EmailParticipantsWarning from './email_participants_warning.vue';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
+import EmailParticipantsWarning from './email_participants_warning.vue';
const DEFAULT_NOTEABLE_TYPE = 'Issue';
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 111af977ec5..50db3b86025 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -1,29 +1,27 @@
<script>
+import { GlButton, GlIcon, GlFormCheckbox, GlTooltipDirective } from '@gitlab/ui';
+import Autosize from 'autosize';
import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex';
-import { isEmpty } from 'lodash';
-import Autosize from 'autosize';
-import { GlButton, GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import { deprecatedCreateFlash as Flash } from '~/flash';
import Autosave from '~/autosave';
+import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import {
capitalizeFirstCharacter,
convertToCamelCase,
splitCamelCase,
slugifyWithUnderscore,
} from '~/lib/utils/text_utility';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import * as constants from '../constants';
-import eventHub from '../event_hub';
+import { __, sprintf } from '~/locale';
import markdownField from '~/vue_shared/components/markdown/field.vue';
-import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import noteSignedOutWidget from './note_signed_out_widget.vue';
-import discussionLockedWidget from './discussion_locked_widget.vue';
+import * as constants from '../constants';
+import eventHub from '../event_hub';
import issuableStateMixin from '../mixins/issuable_state';
import CommentFieldLayout from './comment_field_layout.vue';
+import discussionLockedWidget from './discussion_locked_widget.vue';
+import noteSignedOutWidget from './note_signed_out_widget.vue';
export default {
name: 'CommentForm',
@@ -31,11 +29,14 @@ export default {
noteSignedOutWidget,
discussionLockedWidget,
markdownField,
- userAvatarLink,
GlButton,
TimelineEntryItem,
GlIcon,
CommentFieldLayout,
+ GlFormCheckbox,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagsMixin(), issuableStateMixin],
props: {
@@ -48,8 +49,8 @@ export default {
return {
note: '',
noteType: constants.COMMENT,
+ noteIsConfidential: false,
isSubmitting: false,
- isSubmitButtonDisabled: true,
};
},
computed: {
@@ -82,6 +83,9 @@ export default {
canCreateNote() {
return this.getNoteableData.current_user.can_create_note;
},
+ canSetConfidential() {
+ return this.getNoteableData.current_user.can_update;
+ },
issueActionButtonTitle() {
const openOrClose = this.isOpen ? 'close' : 'reopen';
@@ -145,13 +149,14 @@ export default {
trackingLabel() {
return slugifyWithUnderscore(`${this.commentButtonTitle} button`);
},
- },
- watch: {
- note(newNote) {
- this.setIsSubmitButtonDisabled(newNote, this.isSubmitting);
+ hasCloseAndCommentButton() {
+ return !this.glFeatures.removeCommentCloseReopen;
},
- isSubmitting(newValue) {
- this.setIsSubmitButtonDisabled(this.note, newValue);
+ confidentialNotesEnabled() {
+ return Boolean(this.glFeatures.confidentialNotes);
+ },
+ disableSubmitButton() {
+ return this.note.length === 0 || this.isSubmitting;
},
},
mounted() {
@@ -172,13 +177,6 @@ export default {
'reopenIssuable',
'toggleIssueLocalState',
]),
- setIsSubmitButtonDisabled(note, isSubmitting) {
- if (!isEmpty(note) && !isSubmitting) {
- this.isSubmitButtonDisabled = false;
- } else {
- this.isSubmitButtonDisabled = true;
- }
- },
handleSave(withIssueAction) {
if (this.note.length) {
const noteData = {
@@ -188,6 +186,7 @@ export default {
note: {
noteable_type: this.noteableType,
noteable_id: this.getNoteableData.id,
+ confidential: this.noteIsConfidential,
note: this.note,
},
merge_request_diff_head_sha: this.getNoteableData.diff_head_sha,
@@ -251,6 +250,7 @@ export default {
if (shouldClear) {
this.note = '';
+ this.noteIsConfidential = false;
this.resizeTextarea();
this.$refs.markdownField.previewMarkdown = false;
}
@@ -301,15 +301,6 @@ export default {
<ul v-else-if="canCreateNote" class="notes notes-form timeline">
<timeline-entry-item class="note-form">
<div class="flash-container error-alert timeline-content"></div>
- <div class="timeline-icon d-none d-md-block">
- <user-avatar-link
- v-if="author"
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="40"
- />
- </div>
<div class="timeline-content timeline-content-form">
<form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form">
<comment-field-layout
@@ -348,11 +339,26 @@ export default {
</markdown-field>
</comment-field-layout>
<div class="note-form-actions">
+ <gl-form-checkbox
+ v-if="confidentialNotesEnabled && canSetConfidential"
+ v-model="noteIsConfidential"
+ class="gl-mb-6"
+ data-testid="confidential-note-checkbox"
+ >
+ {{ s__('Notes|Make this comment confidential') }}
+ <gl-icon
+ v-gl-tooltip:tooltipcontainer.bottom
+ name="question"
+ :size="16"
+ :title="s__('Notes|Confidential comments are only visible to project members')"
+ class="gl-text-gray-500"
+ />
+ </gl-form-checkbox>
<div
class="btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
>
<gl-button
- :disabled="isSubmitButtonDisabled"
+ :disabled="disableSubmitButton"
class="js-comment-button js-comment-submit-button"
data-qa-selector="comment_button"
data-testid="comment-button"
@@ -365,7 +371,7 @@ export default {
>{{ commentButtonTitle }}</gl-button
>
<gl-button
- :disabled="isSubmitButtonDisabled"
+ :disabled="disableSubmitButton"
name="button"
category="primary"
variant="success"
@@ -384,7 +390,7 @@ export default {
class="btn btn-transparent"
@click.prevent="setNoteType('comment')"
>
- <gl-icon name="check" class="icon" />
+ <gl-icon name="check" class="icon gl-flex-shrink-0" />
<div class="description">
<strong>{{ __('Comment') }}</strong>
<p>
@@ -400,10 +406,12 @@ export default {
<li class="divider droplab-item-ignore"></li>
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
<button
+ type="button"
+ class="btn btn-transparent"
data-qa-selector="discussion_menu_item"
@click.prevent="setNoteType('discussion')"
>
- <gl-icon name="check" class="icon" />
+ <gl-icon name="check" class="icon gl-flex-shrink-0" />
<div class="description">
<strong>{{ __('Start thread') }}</strong>
<p>{{ startDiscussionDescription }}</p>
@@ -414,7 +422,7 @@ export default {
</div>
<gl-button
- v-if="canToggleIssueState"
+ v-if="hasCloseAndCommentButton && canToggleIssueState"
:loading="isToggleStateButtonLoading"
category="secondary"
:variant="buttonVariant"
diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue
index ee39a529345..0ce1eb8191a 100644
--- a/app/assets/javascripts/notes/components/diff_discussion_header.vue
+++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue
@@ -1,10 +1,10 @@
<script>
-import { mapActions } from 'vuex';
-import { escape } from 'lodash';
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { escape } from 'lodash';
+import { mapActions } from 'vuex';
-import { s__, __, sprintf } from '~/locale';
import { truncateSha } from '~/lib/utils/text_utility';
+import { s__, __, sprintf } from '~/locale';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteEditedText from './note_edited_text.vue';
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index b7355d4d927..e96e1204f76 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -1,12 +1,12 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapState, mapActions } from 'vuex';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
-import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { getDiffMode } from '~/diffs/store/utils';
import { diffViewerModes } from '~/ide/constants';
+import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import { isCollapsed } from '../../diffs/utils/diff_file';
const FIRST_CHAR_REGEX = /^(\+|-| )/;
diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue
index da4134ab2c4..27408bc3354 100644
--- a/app/assets/javascripts/notes/components/discussion_actions.vue
+++ b/app/assets/javascripts/notes/components/discussion_actions.vue
@@ -1,8 +1,8 @@
<script>
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ReplyPlaceholder from './discussion_reply_placeholder.vue';
import ResolveDiscussionButton from './discussion_resolve_button.vue';
import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'DiscussionActions',
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 0a72627834d..55cf75132a9 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import { GlTooltipDirective, GlIcon, GlButton, GlButtonGroup } from '@gitlab/ui';
+import { mapGetters, mapActions } from 'vuex';
import { __ } from '~/locale';
import discussionNavigation from '../mixins/discussion_navigation';
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index aa61aa9b3cb..88f053aed67 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
+import { mapGetters, mapActions } from 'vuex';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import {
DISCUSSION_FILTERS_DEFAULT_VALUE,
diff --git a/app/assets/javascripts/notes/components/discussion_navigator.vue b/app/assets/javascripts/notes/components/discussion_navigator.vue
index facc53e27a6..fa3c900c337 100644
--- a/app/assets/javascripts/notes/components/discussion_navigator.vue
+++ b/app/assets/javascripts/notes/components/discussion_navigator.vue
@@ -1,8 +1,8 @@
<script>
/* global Mousetrap */
import 'mousetrap';
-import discussionNavigation from '~/notes/mixins/discussion_navigation';
import eventHub from '~/notes/event_hub';
+import discussionNavigation from '~/notes/mixins/discussion_navigation';
export default {
mixins: [discussionNavigation],
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index 8ac915c3c03..0f74d78c8e0 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -1,15 +1,14 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { SYSTEM_NOTE } from '../constants';
import { __ } from '~/locale';
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
import SystemNote from '~/vue_shared/components/notes/system_note.vue';
+import { SYSTEM_NOTE } from '../constants';
+import DiscussionNotesRepliesWrapper from './discussion_notes_replies_wrapper.vue';
+import NoteEditedText from './note_edited_text.vue';
import NoteableNote from './noteable_note.vue';
import ToggleRepliesWidget from './toggle_replies_widget.vue';
-import NoteEditedText from './note_edited_text.vue';
-import DiscussionNotesRepliesWrapper from './discussion_notes_replies_wrapper.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'DiscussionNotes',
@@ -18,7 +17,6 @@ export default {
NoteEditedText,
DiscussionNotesRepliesWrapper,
},
- mixins: [glFeatureFlagsMixin()],
props: {
discussion: {
type: Object,
@@ -96,14 +94,14 @@ export default {
return note.isPlaceholderNote ? note.notes[0] : note;
},
handleMouseEnter(discussion) {
- if (this.glFeatures.multilineComments && discussion.position) {
+ if (discussion.position) {
this.setSelectedCommentPositionHover(discussion.position.line_range);
}
},
handleMouseLeave(discussion) {
- // Even though position isn't used here we still don't want to unecessarily call a mutation
+ // Even though position isn't used here we still don't want to unnecessarily call a mutation
// The lack of position tells us that highlighting is irrelevant in this context
- if (this.glFeatures.multilineComments && discussion.position) {
+ if (discussion.position) {
this.setSelectedCommentPositionHover();
}
},
diff --git a/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue b/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue
index 2ddca56ddd5..dfeda4aae7c 100644
--- a/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue
@@ -16,9 +16,14 @@ export default {
},
render(h, { props, children }) {
if (props.isDiffDiscussion) {
- return h('li', { class: 'discussion-collapsible bordered-box clearfix' }, [
- h('ul', { class: 'notes' }, children),
- ]);
+ return h(
+ 'li',
+ {
+ class:
+ 'discussion-collapsible gl-border-solid gl-border-gray-100 gl-border-1 gl-rounded-base gl-overflow-hidden clearfix',
+ },
+ [h('ul', { class: 'notes' }, children)],
+ );
}
return children;
diff --git a/app/assets/javascripts/notes/components/email_participants_warning.vue b/app/assets/javascripts/notes/components/email_participants_warning.vue
index bb1ff58120a..ecf42fce1d2 100644
--- a/app/assets/javascripts/notes/components/email_participants_warning.vue
+++ b/app/assets/javascripts/notes/components/email_participants_warning.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
import { toNounSeriesText } from '~/lib/utils/grammar';
+import { s__, sprintf } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/notes/components/multiline_comment_form.vue b/app/assets/javascripts/notes/components/multiline_comment_form.vue
index 9fbf2c9265c..6ad565567be 100644
--- a/app/assets/javascripts/notes/components/multiline_comment_form.vue
+++ b/app/assets/javascripts/notes/components/multiline_comment_form.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlFormSelect, GlSprintf } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { getSymbol, getLineClasses } from './multiline_comment_utils';
export default {
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index b85cfa83e09..907a4316a93 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -1,13 +1,14 @@
<script>
-import { mapGetters } from 'vuex';
import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
-import ReplyButton from './note_actions/reply_button.vue';
-import eventHub from '~/sidebar/event_hub';
+import { mapGetters } from 'vuex';
import Api from '~/api';
+import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
import { deprecatedCreateFlash as flash } from '~/flash';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { __, sprintf } from '~/locale';
+import eventHub from '~/sidebar/event_hub';
import { splitCamelCase } from '../../lib/utils/text_utility';
+import ReplyButton from './note_actions/reply_button.vue';
export default {
name: 'NoteActions',
@@ -193,7 +194,7 @@ export default {
},
closeTooltip() {
this.$nextTick(() => {
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
});
},
handleAssigneeUpdate(assignees) {
@@ -243,66 +244,62 @@ export default {
:title="displayContributorBadgeText"
>{{ __('Contributor') }}</span
>
- <div v-if="canResolve" class="gl-ml-2">
- <gl-button
- ref="resolveButton"
- v-gl-tooltip
- size="small"
- category="tertiary"
- :variant="resolveVariant"
- :class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
- :title="resolveButtonTitle"
- :aria-label="resolveButtonTitle"
- :icon="resolveIcon"
- :loading="isResolving"
- class="line-resolve-btn note-action-button"
- @click="onResolve"
- />
- </div>
- <div v-if="canAwardEmoji" class="gl-ml-3 gl-mr-2">
- <a
- v-gl-tooltip
- :class="{ 'js-user-authored': isAuthoredByCurrentUser }"
- class="note-action-button note-emoji-button js-add-award js-note-emoji"
- href="#"
- title="Add reaction"
- data-position="right"
- >
- <gl-icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
- <gl-icon class="link-highlight award-control-icon-positive" name="smiley" />
- <gl-icon class="link-highlight award-control-icon-super-positive" name="smile" />
- </a>
- </div>
+ <gl-button
+ v-if="canResolve"
+ ref="resolveButton"
+ v-gl-tooltip
+ size="small"
+ category="tertiary"
+ :variant="resolveVariant"
+ :class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
+ :title="resolveButtonTitle"
+ :aria-label="resolveButtonTitle"
+ :icon="resolveIcon"
+ :loading="isResolving"
+ class="line-resolve-btn note-action-button"
+ @click="onResolve"
+ />
+ <a
+ v-if="canAwardEmoji"
+ v-gl-tooltip
+ :class="{ 'js-user-authored': isAuthoredByCurrentUser }"
+ class="note-action-button note-emoji-button js-add-award js-note-emoji gl-text-gray-600 gl-m-2"
+ href="#"
+ title="Add reaction"
+ data-position="right"
+ >
+ <gl-icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
+ <gl-icon class="link-highlight award-control-icon-positive" name="smiley" />
+ <gl-icon class="link-highlight award-control-icon-super-positive" name="smile" />
+ </a>
<reply-button
v-if="showReply"
ref="replyButton"
class="js-reply-button"
@startReplying="$emit('startReplying')"
/>
- <div v-if="canEdit" class="gl-ml-2">
- <gl-button
- v-gl-tooltip
- title="Edit comment"
- icon="pencil"
- size="small"
- category="tertiary"
- class="note-action-button js-note-edit btn btn-transparent"
- data-qa-selector="note_edit_button"
- @click="onEdit"
- />
- </div>
- <div v-if="showDeleteAction" class="gl-ml-2">
- <gl-button
- v-gl-tooltip
- title="Delete comment"
- size="small"
- icon="remove"
- category="tertiary"
- class="note-action-button js-note-delete btn btn-transparent"
- @click="onDelete"
- />
- </div>
- <div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions gl-ml-2">
+ <gl-button
+ v-if="canEdit"
+ v-gl-tooltip
+ title="Edit comment"
+ icon="pencil"
+ size="small"
+ category="tertiary"
+ class="note-action-button js-note-edit btn btn-transparent"
+ data-qa-selector="note_edit_button"
+ @click="onEdit"
+ />
+ <gl-button
+ v-if="showDeleteAction"
+ v-gl-tooltip
+ title="Delete comment"
+ size="small"
+ icon="remove"
+ category="tertiary"
+ class="note-action-button js-note-delete btn btn-transparent"
+ @click="onDelete"
+ />
+ <div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions">
<gl-button
v-gl-tooltip
title="More actions"
diff --git a/app/assets/javascripts/notes/components/note_actions/reply_button.vue b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
index acbbee13a6d..5ce03091504 100644
--- a/app/assets/javascripts/notes/components/note_actions/reply_button.vue
+++ b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
@@ -1,7 +1,11 @@
<script>
import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
export default {
+ i18n: {
+ buttonText: __('Reply to comment'),
+ },
name: 'ReplyButton',
components: {
GlButton,
@@ -13,18 +17,15 @@ export default {
</script>
<template>
- <div class="gl-ml-2">
- <gl-button
- ref="button"
- v-gl-tooltip
- data-track-event="click_button"
- data-track-label="reply_comment_button"
- category="tertiary"
- size="small"
- icon="comment"
- :title="__('Reply to comment')"
- :aria-label="__('Reply to comment')"
- @click="$emit('startReplying')"
- />
- </div>
+ <gl-button
+ v-gl-tooltip
+ data-track-event="click_button"
+ data-track-label="reply_comment_button"
+ category="tertiary"
+ size="small"
+ icon="comment"
+ :title="$options.i18n.buttonText"
+ :aria-label="$options.i18n.buttonText"
+ @click="$emit('startReplying')"
+ />
</template>
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index cf3e991986c..9eb7b928ea4 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -1,8 +1,8 @@
<script>
import { mapActions, mapGetters } from 'vuex';
+import { __ } from '~/locale';
import AwardsList from '~/vue_shared/components/awards_list.vue';
import { deprecatedCreateFlash as Flash } from '../../flash';
-import { __ } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 8855ceac3d5..8c5d81c0cc9 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -1,14 +1,16 @@
<script>
/* eslint-disable vue/no-v-html */
-import { mapActions, mapGetters, mapState } from 'vuex';
import $ from 'jquery';
+import { escape } from 'lodash';
+import { mapActions, mapGetters, mapState } from 'vuex';
+
import '~/behaviors/markdown/render_gfm';
-import noteEditedText from './note_edited_text.vue';
-import noteAwardsList from './note_awards_list.vue';
+import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
+import autosave from '../mixins/autosave';
import noteAttachment from './note_attachment.vue';
+import noteAwardsList from './note_awards_list.vue';
+import noteEditedText from './note_edited_text.vue';
import noteForm from './note_form.vue';
-import autosave from '../mixins/autosave';
-import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
export default {
components: {
@@ -29,6 +31,11 @@ export default {
required: false,
default: null,
},
+ file: {
+ type: Object,
+ required: false,
+ default: null,
+ },
canEdit: {
type: Boolean,
required: true,
@@ -46,6 +53,7 @@ export default {
},
computed: {
...mapGetters(['getDiscussion', 'suggestionsCount']),
+ ...mapGetters('diffs', ['suggestionCommitMessage']),
discussion() {
if (!this.note.isDraft) return {};
@@ -54,7 +62,6 @@ export default {
...mapState({
batchSuggestionsInfo: (state) => state.notes.batchSuggestionsInfo,
}),
- ...mapState('diffs', ['defaultSuggestionCommitMessage']),
noteBody() {
return this.note.note;
},
@@ -64,6 +71,21 @@ export default {
lineType() {
return this.line ? this.line.type : null;
},
+ commitMessage() {
+ // Please see this issue comment for why these
+ // are hard-coded to 1:
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/291027#note_468308022
+ const suggestionsCount = 1;
+ const filesCount = 1;
+ const filePaths = this.file ? [this.file.file_path] : [];
+ const suggestion = this.suggestionCommitMessage({
+ file_paths: filePaths.join(', '),
+ suggestions_count: suggestionsCount,
+ files_count: filesCount,
+ });
+
+ return escape(suggestion);
+ },
},
mounted() {
this.renderGFM();
@@ -135,7 +157,7 @@ export default {
:note-html="note.note_html"
:line-type="lineType"
:help-page-path="helpPagePath"
- :default-commit-message="defaultSuggestionCommitMessage"
+ :default-commit-message="commitMessage"
@apply="applySuggestion"
@applyBatch="applySuggestionBatch"
@addToBatch="addSuggestionToBatch"
@@ -156,6 +178,7 @@ export default {
@handleFormUpdate="handleFormUpdate"
@cancelForm="formCancelHandler"
/>
+ <!-- eslint-disable vue/no-mutating-props -->
<textarea
v-if="canEdit"
v-model="note.note"
@@ -163,6 +186,7 @@ export default {
class="hidden js-task-list-field"
dir="auto"
></textarea>
+ <!-- eslint-enable vue/no-mutating-props -->
<note-edited-text
v-if="note.last_edited_at"
:edited-at="note.last_edited_at"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 9acb837c27f..653bc450d0b 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -1,14 +1,15 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlButton } from '@gitlab/ui';
import { mapGetters, mapActions, mapState } from 'vuex';
+import { getDraft, updateDraft } from '~/lib/utils/autosave';
import { mergeUrlParams } from '~/lib/utils/url_utility';
-import eventHub from '../event_hub';
+import { __, sprintf } 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';
-import { __, sprintf } from '~/locale';
-import { getDraft, updateDraft } from '~/lib/utils/autosave';
import CommentFieldLayout from './comment_field_layout.vue';
export default {
@@ -16,6 +17,7 @@ export default {
components: {
markdownField,
CommentFieldLayout,
+ GlButton,
},
mixins: [glFeatureFlagsMixin(), issuableStateMixin, resolvable],
props: {
@@ -378,61 +380,70 @@ export default {
</template>
</label>
</p>
- <div>
- <button
+ <div class="gl-display-sm-flex gl-flex-wrap">
+ <gl-button
:disabled="isDisabled"
- type="button"
- class="btn btn-success"
+ category="primary"
+ variant="success"
+ class="gl-mr-3"
data-qa-selector="start_review_button"
@click="handleAddToReview"
>
<template v-if="hasDrafts">{{ __('Add to review') }}</template>
<template v-else>{{ __('Start a review') }}</template>
- </button>
- <button
+ </gl-button>
+ <gl-button
:disabled="isDisabled"
- type="button"
- class="btn js-comment-button"
+ category="secondary"
+ variant="default"
data-qa-selector="comment_now_button"
+ class="gl-mr-3 js-comment-button"
@click="handleUpdate()"
>
{{ __('Add comment now') }}
- </button>
- <button
- class="btn note-edit-cancel js-close-discussion-note-form"
- type="button"
+ </gl-button>
+ <gl-button
+ class="note-edit-cancel js-close-discussion-note-form"
+ category="secondary"
+ variant="default"
data-testid="cancelBatchCommentsEnabled"
@click="cancelHandler(true)"
>
{{ __('Cancel') }}
- </button>
+ </gl-button>
</div>
</template>
<template v-else>
- <button
- :disabled="isDisabled"
- type="button"
- class="js-vue-issue-save btn btn-success js-comment-button"
- data-qa-selector="reply_comment_button"
- @click="handleUpdate()"
- >
- {{ saveButtonTitle }}
- </button>
- <button
- v-if="discussion.resolvable"
- class="btn btn-default gl-mr-3 js-comment-resolve-button"
- @click.prevent="handleUpdate(true)"
- >
- {{ resolveButtonTitle }}
- </button>
- <button
- class="btn btn-cancel note-edit-cancel js-close-discussion-note-form"
- type="button"
- data-testid="cancel"
- @click="cancelHandler(true)"
- >
- {{ __('Cancel') }}
- </button>
+ <div class="gl-display-sm-flex gl-flex-wrap">
+ <gl-button
+ :disabled="isDisabled"
+ category="primary"
+ variant="success"
+ data-qa-selector="reply_comment_button"
+ class="gl-mr-3 js-vue-issue-save js-comment-button"
+ @click="handleUpdate()"
+ >
+ {{ saveButtonTitle }}
+ </gl-button>
+ <gl-button
+ v-if="discussion.resolvable"
+ category="secondary"
+ variant="default"
+ class="gl-mr-3 js-comment-resolve-button"
+ @click.prevent="handleUpdate(true)"
+ >
+ {{ resolveButtonTitle }}
+ </gl-button>
+ <gl-button
+ class="note-edit-cancel js-close-discussion-note-form"
+ category="secondary"
+ variant="default"
+ data-testid="cancel"
+ @click="cancelHandler(true)"
+ >
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
</template>
</div>
</form>
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 17a995018d3..6932af61c69 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -1,9 +1,9 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import { mapActions } from 'vuex';
-import { GlIcon, GlLoadingIcon, GlTooltipDirective, GlSprintf } from '@gitlab/ui';
-import { isUserBusy } from '~/set_status_modal/utils';
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import UserNameWithStatus from '../../sidebar/components/assignees/user_name_with_status.vue';
export default {
components: {
@@ -12,7 +12,7 @@ export default {
import('ee_component/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'),
GlIcon,
GlLoadingIcon,
- GlSprintf,
+ UserNameWithStatus,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -90,10 +90,6 @@ export default {
}
return false;
},
- authorIsBusy() {
- const { status } = this.author;
- return status?.availability && isUserBusy(status.availability);
- },
emojiElement() {
return this.$refs?.authorStatus?.querySelector('gl-emoji');
},
@@ -133,6 +129,9 @@ export default {
this.$refs.authorNameLink.dispatchEvent(new Event('mouseleave'));
this.isUsernameLinkHovered = false;
},
+ userAvailability(selectedAuthor) {
+ return selectedAuthor?.availability || '';
+ },
},
};
</script>
@@ -158,12 +157,11 @@ export default {
:data-username="author.username"
>
<slot name="note-header-info"></slot>
- <span class="note-header-author-name gl-font-weight-bold">
- <gl-sprintf v-if="authorIsBusy" :message="s__('UserAvailability|%{author} (Busy)')">
- <template #author>{{ authorName }}</template>
- </gl-sprintf>
- <template v-else>{{ authorName }}</template>
- </span>
+ <user-name-with-status
+ :name="authorName"
+ :availability="userAvailability(author)"
+ container-classes="note-header-author-name gl-font-weight-bold"
+ />
</a>
<span
v-if="authorStatus"
@@ -210,9 +208,9 @@ export default {
v-gl-tooltip:tooltipcontainer.bottom
data-testid="confidentialIndicator"
name="eye-slash"
- :size="14"
- :title="s__('Notes|Private comments are accessible by internal staff only')"
- class="gl-ml-1 gl-text-gray-700 align-middle"
+ :size="16"
+ :title="s__('Notes|This comment is confidential and only visible to project members')"
+ class="gl-ml-1 gl-text-orange-700 align-middle"
/>
<slot name="extra-controls"></slot>
<gl-loading-icon
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 0a9a3da6069..34dd21dcbac 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -1,22 +1,22 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
-import { s__, __ } from '~/locale';
+import { mapActions, mapGetters } from 'vuex';
+import DraftNote from '~/batch_comments/components/draft_note.vue';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
+import { s__, __ } from '~/locale';
+import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import DraftNote from '~/batch_comments/components/draft_note.vue';
import { deprecatedCreateFlash as Flash } from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import diffDiscussionHeader from './diff_discussion_header.vue';
-import noteSignedOutWidget from './note_signed_out_widget.vue';
-import noteForm from './note_form.vue';
-import diffWithNote from './diff_with_note.vue';
+import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
-import eventHub from '../event_hub';
-import DiscussionNotes from './discussion_notes.vue';
+import diffDiscussionHeader from './diff_discussion_header.vue';
+import diffWithNote from './diff_with_note.vue';
import DiscussionActions from './discussion_actions.vue';
+import DiscussionNotes from './discussion_notes.vue';
+import noteForm from './note_form.vue';
+import noteSignedOutWidget from './note_signed_out_widget.vue';
export default {
name: 'NoteableDiscussion',
@@ -265,16 +265,8 @@ export default {
<div
v-else-if="showReplies"
:class="{ 'is-replying': isReplying }"
- class="discussion-reply-holder clearfix"
+ class="discussion-reply-holder gl-border-t-0! clearfix"
>
- <user-avatar-link
- v-if="!isReplying && userCanReply"
- :link-href="currentUser.path"
- :img-src="currentUser.avatar_url"
- :img-alt="currentUser.name"
- :img-size="40"
- class="d-none d-sm-block"
- />
<discussion-actions
v-if="!isReplying && userCanReply"
:discussion="discussion"
@@ -285,27 +277,18 @@ export default {
@showReplyForm="showReplyForm"
@resolve="resolveHandler"
/>
- <div v-if="isReplying" class="avatar-note-form-holder">
- <user-avatar-link
- v-if="currentUser"
- :link-href="currentUser.path"
- :img-src="currentUser.avatar_url"
- :img-alt="currentUser.name"
- :img-size="40"
- class="d-none d-sm-block"
- />
- <note-form
- ref="noteForm"
- :discussion="discussion"
- :is-editing="false"
- :line="diffLine"
- save-button-title="Comment"
- :autosave-key="autosaveKey"
- @handleFormUpdateAddToReview="addReplyToReview"
- @handleFormUpdate="saveReply"
- @cancelForm="cancelReplyForm"
- />
- </div>
+ <note-form
+ v-if="isReplying"
+ ref="noteForm"
+ :discussion="discussion"
+ :is-editing="false"
+ :line="diffLine"
+ save-button-title="Comment"
+ :autosave-key="autosaveKey"
+ @handleFormUpdateAddToReview="addReplyToReview"
+ @handleFormUpdate="saveReply"
+ @cancelForm="cancelReplyForm"
+ />
<note-signed-out-widget v-if="!isLoggedIn" />
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index eaa64cf7c01..4343fac3cfa 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -1,21 +1,18 @@
<script>
+import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import $ from 'jquery';
-import { mapGetters, mapActions } from 'vuex';
import { escape } from 'lodash';
-import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { mapGetters, mapActions } from 'vuex';
+import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
+import httpStatusCodes from '~/lib/utils/http_status';
import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import { __, s__, sprintf } from '../../locale';
import { deprecatedCreateFlash as Flash } from '../../flash';
+import { __, s__, sprintf } from '../../locale';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import noteHeader from './note_header.vue';
-import noteActions from './note_actions.vue';
-import NoteBody from './note_body.vue';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
-import httpStatusCodes from '~/lib/utils/http_status';
import {
getStartLineNumber,
getEndLineNumber,
@@ -23,7 +20,9 @@ import {
commentLineOptions,
formatLineRange,
} from './multiline_comment_utils';
-import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
+import noteActions from './note_actions.vue';
+import NoteBody from './note_body.vue';
+import noteHeader from './note_header.vue';
export default {
name: 'NoteableNote',
@@ -38,7 +37,7 @@ export default {
directives: {
SafeHtml,
},
- mixins: [noteable, resolvable, glFeatureFlagsMixin()],
+ mixins: [noteable, resolvable],
props: {
note: {
type: Object,
@@ -160,7 +159,6 @@ export default {
},
showMultiLineComment() {
if (
- !this.glFeatures.multilineComments ||
!this.discussionRoot ||
this.startLineNumber.length === 0 ||
this.endLineNumber.length === 0
@@ -289,6 +287,7 @@ export default {
};
this.isRequesting = true;
this.oldContent = this.note.note_html;
+ // eslint-disable-next-line vue/no-mutating-props
this.note.note_html = escape(noteText);
this.updateNote(data)
@@ -321,6 +320,7 @@ export default {
}
this.$refs.noteBody.resetAutoSave();
if (this.oldContent) {
+ // eslint-disable-next-line vue/no-mutating-props
this.note.note_html = this.oldContent;
this.oldContent = null;
}
@@ -330,6 +330,7 @@ export default {
recoverNoteContent(noteText) {
// we need to do this to prevent noteForm inconsistent content warning
// this is something we intentionally do so we need to recover the content
+ // eslint-disable-next-line vue/no-mutating-props
this.note.note = noteText;
const { noteBody } = this.$refs;
if (noteBody) {
@@ -428,6 +429,7 @@ export default {
ref="noteBody"
:note="note"
:line="line"
+ :file="diffFile"
:can-edit="note.current_user.can_edit"
:is-editing="isEditing"
:help-page-path="helpPagePath"
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index e9e687a8743..2d66e0d24e3 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -1,21 +1,22 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
+import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
+import { __ } from '~/locale';
+import initUserPopovers from '~/user_popovers';
+import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { deprecatedCreateFlash as Flash } from '../../flash';
-import * as constants from '../constants';
-import eventHub from '../event_hub';
-import noteableNote from './noteable_note.vue';
-import noteableDiscussion from './noteable_discussion.vue';
-import discussionFilterNote from './discussion_filter_note.vue';
-import systemNote from '../../vue_shared/components/notes/system_note.vue';
-import commentForm from './comment_form.vue';
+import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
import skeletonLoadingContainer from '../../vue_shared/components/notes/skeleton_note.vue';
-import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
-import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
-import { __ } from '~/locale';
-import initUserPopovers from '~/user_popovers';
+import systemNote from '../../vue_shared/components/notes/system_note.vue';
+import * as constants from '../constants';
+import eventHub from '../event_hub';
+import commentForm from './comment_form.vue';
+import discussionFilterNote from './discussion_filter_note.vue';
+import noteableDiscussion from './noteable_discussion.vue';
+import noteableNote from './noteable_note.vue';
export default {
name: 'NotesApp',
@@ -30,6 +31,7 @@ export default {
discussionFilterNote,
OrderedLayout,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
noteableData: {
type: Object,
@@ -57,7 +59,6 @@ export default {
},
data() {
return {
- isFetching: false,
currentFilter: null,
};
},
@@ -68,6 +69,7 @@ export default {
'convertedDisscussionIds',
'getNotesDataByProp',
'isLoading',
+ 'isFetching',
'commentsDisabled',
'getNoteableData',
'userCanReply',
@@ -103,6 +105,13 @@ export default {
},
},
watch: {
+ async isFetching() {
+ if (!this.isFetching) {
+ await this.$nextTick();
+ await this.startTaskList();
+ await this.checkLocationHash();
+ }
+ },
shouldShow() {
if (!this.isNotesFetched) {
this.fetchNotes();
@@ -153,6 +162,7 @@ export default {
},
methods: {
...mapActions([
+ 'setFetchingState',
'setLoadingState',
'fetchDiscussions',
'poll',
@@ -183,7 +193,11 @@ export default {
fetchNotes() {
if (this.isFetching) return null;
- this.isFetching = true;
+ this.setFetchingState(true);
+
+ if (this.glFeatures.paginatedNotes) {
+ return this.initPolling();
+ }
return this.fetchDiscussions(this.getFetchDiscussionsConfig())
.then(this.initPolling)
@@ -191,11 +205,8 @@ export default {
this.setLoadingState(false);
this.setNotesFetchedState(true);
eventHub.$emit('fetchedNotesData');
- this.isFetching = false;
+ this.setFetchingState(false);
})
- .then(this.$nextTick)
- .then(this.startTaskList)
- .then(this.checkLocationHash)
.catch(() => {
this.setLoadingState(false);
this.setNotesFetchedState(true);
diff --git a/app/assets/javascripts/notes/components/sort_discussion.vue b/app/assets/javascripts/notes/components/sort_discussion.vue
index c279a7107c7..ed1f456c174 100644
--- a/app/assets/javascripts/notes/components/sort_discussion.vue
+++ b/app/assets/javascripts/notes/components/sort_discussion.vue
@@ -2,8 +2,8 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import { __ } from '~/locale';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import Tracking from '~/tracking';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { ASC, DESC } from '../constants';
const SORT_OPTIONS = [
diff --git a/app/assets/javascripts/notes/components/timeline_toggle.vue b/app/assets/javascripts/notes/components/timeline_toggle.vue
index 8162878f80d..87d22e5b986 100644
--- a/app/assets/javascripts/notes/components/timeline_toggle.vue
+++ b/app/assets/javascripts/notes/components/timeline_toggle.vue
@@ -2,9 +2,9 @@
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import { s__ } from '~/locale';
+import TrackEventDirective from '~/vue_shared/directives/track_event';
import { COMMENTS_ONLY_FILTER_VALUE, DESC } from '../constants';
import notesEventHub from '../event_hub';
-import TrackEventDirective from '~/vue_shared/directives/track_event';
import { trackToggleTimelineView } from '../utils';
export const timelineEnabledTooltip = s__('Timeline|Turn timeline view off');
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index ab7fa793bdc..01e3f84d00e 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -1,8 +1,8 @@
<script>
-import { uniqBy } from 'lodash';
import { GlButton, GlIcon } from '@gitlab/ui';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import { uniqBy } from 'lodash';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
export default {
components: {
@@ -39,13 +39,17 @@ export default {
this.$emit('toggle');
},
},
+ ICON_CLASS: 'gl-mr-3 gl-cursor-pointer',
};
</script>
<template>
- <li :class="className" class="replies-toggle js-toggle-replies">
+ <li
+ :class="className"
+ class="replies-toggle js-toggle-replies gl-display-flex! gl-align-items-center gl-flex-wrap"
+ >
<template v-if="collapsed">
- <gl-icon name="chevron-right" @click.native="toggle" />
+ <gl-icon :class="$options.ICON_CLASS" name="chevron-right" @click.native="toggle" />
<div>
<user-avatar-link
v-for="author in uniqueAuthors"
@@ -59,7 +63,7 @@ export default {
/>
</div>
<gl-button
- class="js-replies-text"
+ class="js-replies-text gl-mr-2"
category="tertiary"
variant="link"
data-qa-selector="expand_replies_button"
@@ -68,18 +72,19 @@ export default {
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
</gl-button>
{{ __('Last reply by') }}
- <a :href="lastReply.author.path" class="btn btn-link author-link">
+ <a :href="lastReply.author.path" class="btn btn-link author-link gl-mx-2">
{{ lastReply.author.name }}
</a>
<time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" />
</template>
- <span
+ <div
v-else
- class="collapse-replies-btn js-collapse-replies"
+ class="collapse-replies-btn js-collapse-replies gl-display-flex align-items-center"
data-qa-selector="collapse_replies_button"
@click="toggle"
>
- <gl-icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
- </span>
+ <gl-icon :class="$options.ICON_CLASS" name="chevron-down" />
+ <span class="gl-cursor-pointer">{{ s__('Notes|Collapse replies') }}</span>
+ </div>
</li>
</template>
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index 1f0b2afab9e..e4241669fbc 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -2,8 +2,8 @@ import Vue from 'vue';
import notesApp from './components/notes_app.vue';
import initDiscussionFilters from './discussion_filters';
import initSortDiscussions from './sort_discussions';
-import initTimelineToggle from './timeline';
import { store } from './stores';
+import initTimelineToggle from './timeline';
const el = document.getElementById('js-vue-notes');
diff --git a/app/assets/javascripts/notes/mixins/autosave.js b/app/assets/javascripts/notes/mixins/autosave.js
index b161773f5f1..d670d0bd4c5 100644
--- a/app/assets/javascripts/notes/mixins/autosave.js
+++ b/app/assets/javascripts/notes/mixins/autosave.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
+import { s__ } from '~/locale';
import Autosave from '../../autosave';
import { capitalizeFirstCharacter } from '../../lib/utils/text_utility';
-import { s__ } from '~/locale';
export default {
methods: {
diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
index 5ce541781d4..76342e07c04 100644
--- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js
+++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js
@@ -2,8 +2,8 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils';
import { TEXT_DIFF_POSITION_TYPE, IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__ } from '~/locale';
import { clearDraft } from '~/lib/utils/autosave';
+import { s__ } from '~/locale';
import { formatLineRange } from '~/notes/components/multiline_comment_utils';
export default {
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index c6684efed4d..19403c29cda 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -1,23 +1,24 @@
-import Vue from 'vue';
import $ from 'jquery';
import Visibility from 'visibilityjs';
+import Vue from 'vue';
+import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
-import TaskList from '../../task_list';
-import { deprecatedCreateFlash as Flash } from '../../flash';
-import Poll from '../../lib/utils/poll';
-import * as types from './mutation_types';
-import * as utils from './utils';
-import * as constants from '../constants';
+import { __, sprintf } from '~/locale';
+import updateIssueConfidentialMutation from '~/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql';
+import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql';
+import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql';
import loadAwardsHandler from '../../awards_handler';
-import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
+import { deprecatedCreateFlash as Flash } from '../../flash';
import { isInViewport, scrollToElement, isInMRPage } from '../../lib/utils/common_utils';
+import Poll from '../../lib/utils/poll';
import { mergeUrlParams } from '../../lib/utils/url_utility';
+import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
+import TaskList from '../../task_list';
import mrWidgetEventHub from '../../vue_merge_request_widget/event_hub';
-import updateIssueConfidentialMutation from '~/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql';
-import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql';
-import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql';
-import { __, sprintf } from '~/locale';
-import Api from '~/api';
+import * as constants from '../constants';
+import eventHub from '../event_hub';
+import * as types from './mutation_types';
+import * as utils from './utils';
let eTagPoll;
@@ -420,14 +421,25 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
.catch(processErrors);
};
-const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
+export const setFetchingState = ({ commit }, fetchingState) =>
+ commit(types.SET_NOTES_FETCHING_STATE, fetchingState);
+
+const pollSuccessCallBack = async (resp, commit, state, getters, dispatch) => {
if (state.isResolvingDiscussion) {
return null;
}
+ if (window.gon?.features?.paginatedNotes && !resp.more && state.isFetching) {
+ eventHub.$emit('fetchedNotesData');
+ dispatch('setFetchingState', false);
+ dispatch('setNotesFetchedState', true);
+ dispatch('setLoadingState', false);
+ }
+
if (resp.notes?.length) {
- dispatch('updateOrCreateNotes', resp.notes);
+ await dispatch('updateOrCreateNotes', resp.notes);
dispatch('startTaskList');
+ dispatch('updateResolvableDiscussionsCounts');
}
commit(types.SET_LAST_FETCHED_AT, resp.last_fetched_at);
@@ -727,9 +739,13 @@ export const updateConfidentialityOnIssuable = (
})
.then(({ data }) => {
const {
- issueSetConfidential: { issue },
+ issueSetConfidential: { issue, errors },
} = data;
- setConfidentiality({ commit }, issue.confidential);
+ if (errors?.length) {
+ Flash(errors[0], 'alert');
+ } else {
+ setConfidentiality({ commit }, issue.confidential);
+ }
});
};
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index 5891a2e63e3..43d99937b8d 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -48,6 +48,8 @@ export const persistSortOrder = (state) => state.persistSortOrder;
export const timelineEnabled = (state) => state.isTimelineEnabled;
+export const isFetching = (state) => state.isFetching;
+
export const isLoading = (state) => state.isLoading;
export const getNotesDataByProp = (state) => (prop) => state.notesData[prop];
diff --git a/app/assets/javascripts/notes/stores/modules/index.js b/app/assets/javascripts/notes/stores/modules/index.js
index 144a3d7ba90..f154edd3434 100644
--- a/app/assets/javascripts/notes/stores/modules/index.js
+++ b/app/assets/javascripts/notes/stores/modules/index.js
@@ -1,7 +1,7 @@
+import { ASC } from '../../constants';
import * as actions from '../actions';
import * as getters from '../getters';
import mutations from '../mutations';
-import { ASC } from '../../constants';
export default () => ({
state: {
@@ -47,6 +47,7 @@ export default () => ({
unresolvedDiscussionsCount: 0,
descriptionVersions: {},
isTimelineEnabled: false,
+ isFetching: false,
},
actions,
getters,
diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js
index 5c4f62f4575..2e8b728e013 100644
--- a/app/assets/javascripts/notes/stores/mutation_types.js
+++ b/app/assets/javascripts/notes/stores/mutation_types.js
@@ -14,6 +14,7 @@ export const UPDATE_NOTE = 'UPDATE_NOTE';
export const UPDATE_DISCUSSION = 'UPDATE_DISCUSSION';
export const UPDATE_DISCUSSION_POSITION = 'UPDATE_DISCUSSION_POSITION';
export const SET_DISCUSSION_DIFF_LINES = 'SET_DISCUSSION_DIFF_LINES';
+export const SET_NOTES_FETCHING_STATE = 'SET_NOTES_FETCHING_STATE';
export const SET_NOTES_FETCHED_STATE = 'SET_NOTES_FETCHED_STATE';
export const SET_NOTES_LOADING_STATE = 'SET_NOTES_LOADING_STATE';
export const DISABLE_COMMENTS = 'DISABLE_COMMENTS';
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index 2c51ce0d970..c5fa34dfedd 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -1,7 +1,8 @@
-import * as utils from './utils';
-import * as types from './mutation_types';
-import * as constants from '../constants';
+import { isEqual } from 'lodash';
import { isInMRPage } from '../../lib/utils/common_utils';
+import * as constants from '../constants';
+import * as types from './mutation_types';
+import * as utils from './utils';
export default {
[types.ADD_NEW_NOTE](state, data) {
@@ -31,7 +32,22 @@ export default {
}
}
- note.base_discussion = undefined; // No point keeping a reference to this
+ if (window.gon?.features?.paginatedNotes && note.base_discussion) {
+ if (discussion.diff_file) {
+ discussion.file_hash = discussion.diff_file.file_hash;
+
+ discussion.truncated_diff_lines = utils.prepareDiffLines(
+ discussion.truncated_diff_lines || [],
+ );
+ }
+
+ discussion.resolvable = note.resolvable;
+ discussion.expanded = note.base_discussion.expanded;
+ discussion.resolved = note.resolved;
+ }
+
+ // note.base_discussion = undefined; // No point keeping a reference to this
+ delete note.base_discussion;
discussion.notes = [note];
state.discussions.push(discussion);
@@ -220,6 +236,11 @@ export default {
[types.UPDATE_NOTE](state, note) {
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
+ // Disable eslint here so we can delete the property that we no longer need
+ // in the note object
+ // eslint-disable-next-line no-param-reassign
+ delete note.base_discussion;
+
if (noteObj.individual_note) {
if (note.type === constants.DISCUSSION_NOTE) {
noteObj.individual_note = false;
@@ -228,7 +249,10 @@ export default {
noteObj.notes.splice(0, 1, note);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
- noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note);
+
+ if (!isEqual(comment, note)) {
+ noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note);
+ }
}
},
@@ -313,6 +337,10 @@ export default {
state.isLoading = value;
},
+ [types.SET_NOTES_FETCHING_STATE](state, value) {
+ state.isFetching = value;
+ },
+
[types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) {
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index 6df926e1249..627e405c75c 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -1,7 +1,7 @@
-import AjaxCache from '~/lib/utils/ajax_cache';
import { trimFirstCharOfLineContent } from '~/diffs/store/utils';
-import { sprintf, __ } from '~/locale';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
+import AjaxCache from '~/lib/utils/ajax_cache';
+import { sprintf, __ } from '~/locale';
// factory function because global flag makes RegExp stateful
const createQuickActionsRegex = () => /^\/\w+.*$/gm;
diff --git a/app/assets/javascripts/notifications/components/custom_notifications_modal.vue b/app/assets/javascripts/notifications/components/custom_notifications_modal.vue
new file mode 100644
index 00000000000..0f628897e17
--- /dev/null
+++ b/app/assets/javascripts/notifications/components/custom_notifications_modal.vue
@@ -0,0 +1,128 @@
+<script>
+import { GlModal, GlSprintf, GlLink, GlLoadingIcon, GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
+import Api from '~/api';
+import { i18n } from '../constants';
+
+export default {
+ name: 'CustomNotificationsModal',
+ components: {
+ GlModal,
+ GlSprintf,
+ GlLink,
+ GlLoadingIcon,
+ GlFormGroup,
+ GlFormCheckbox,
+ },
+ inject: {
+ projectId: {
+ default: null,
+ },
+ groupId: {
+ default: null,
+ },
+ helpPagePath: {
+ default: '',
+ },
+ },
+ props: {
+ modalId: {
+ type: String,
+ required: false,
+ default: 'custom-notifications-modal',
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ events: [],
+ };
+ },
+ methods: {
+ open() {
+ this.$refs.modal.show();
+ },
+ buildEvents(events) {
+ return Object.keys(events).map((key) => ({
+ id: key,
+ enabled: Boolean(events[key]),
+ name: this.$options.i18n.eventNames[key] || '',
+ loading: false,
+ }));
+ },
+ async onOpen() {
+ if (!this.events.length) {
+ await this.loadNotificationSettings();
+ }
+ },
+ async loadNotificationSettings() {
+ this.isLoading = true;
+
+ try {
+ const {
+ data: { events },
+ } = await Api.getNotificationSettings(this.projectId, this.groupId);
+
+ this.events = this.buildEvents(events);
+ } catch (error) {
+ this.$toast.show(this.$options.i18n.loadNotificationLevelErrorMessage, { type: 'error' });
+ } finally {
+ this.isLoading = false;
+ }
+ },
+ async updateEvent(isEnabled, event) {
+ const index = this.events.findIndex((e) => e.id === event.id);
+
+ // update loading state for the given event
+ this.$set(this.events, index, { ...this.events[index], loading: true });
+
+ try {
+ const {
+ data: { events },
+ } = await Api.updateNotificationSettings(this.projectId, this.groupId, {
+ [event.id]: isEnabled,
+ });
+
+ this.events = this.buildEvents(events);
+ } catch (error) {
+ this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage, { type: 'error' });
+ }
+ },
+ },
+ i18n,
+};
+</script>
+
+<template>
+ <gl-modal
+ ref="modal"
+ :modal-id="modalId"
+ :title="$options.i18n.customNotificationsModal.title"
+ @show="onOpen"
+ >
+ <div class="container-fluid">
+ <div class="row">
+ <div class="col-lg-4">
+ <h4 class="gl-mt-0" data-testid="modalBodyTitle">
+ {{ $options.i18n.customNotificationsModal.bodyTitle }}
+ </h4>
+ <gl-sprintf :message="$options.i18n.customNotificationsModal.bodyMessage">
+ <template #notificationLink="{ content }">
+ <gl-link :href="helpPagePath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+ <div class="col-lg-8">
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-3" />
+ <template v-else>
+ <gl-form-group v-for="event in events" :key="event.id">
+ <gl-form-checkbox v-model="event.enabled" @change="updateEvent($event, event)">
+ <strong>{{ event.name }}</strong
+ ><gl-loading-icon v-if="event.loading" :inline="true" class="gl-ml-2" />
+ </gl-form-checkbox>
+ </gl-form-group>
+ </template>
+ </div>
+ </div>
+ </div>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/notifications/components/notifications_dropdown.vue b/app/assets/javascripts/notifications/components/notifications_dropdown.vue
new file mode 100644
index 00000000000..e4cedfdb810
--- /dev/null
+++ b/app/assets/javascripts/notifications/components/notifications_dropdown.vue
@@ -0,0 +1,196 @@
+<script>
+import {
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
+ GlDropdownDivider,
+ GlTooltipDirective,
+ GlModalDirective,
+} from '@gitlab/ui';
+import Api from '~/api';
+import { sprintf } from '~/locale';
+import { CUSTOM_LEVEL, i18n } from '../constants';
+import CustomNotificationsModal from './custom_notifications_modal.vue';
+import NotificationsDropdownItem from './notifications_dropdown_item.vue';
+
+export default {
+ name: 'NotificationsDropdown',
+ components: {
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
+ GlDropdownDivider,
+ NotificationsDropdownItem,
+ CustomNotificationsModal,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ 'gl-modal': GlModalDirective,
+ },
+ inject: {
+ containerClass: {
+ default: '',
+ },
+ disabled: {
+ default: false,
+ },
+ dropdownItems: {
+ default: [],
+ },
+ buttonSize: {
+ default: 'medium',
+ },
+ initialNotificationLevel: {
+ default: '',
+ },
+ projectId: {
+ default: null,
+ },
+ groupId: {
+ default: null,
+ },
+ showLabel: {
+ default: false,
+ },
+ },
+ data() {
+ return {
+ selectedNotificationLevel: this.initialNotificationLevel,
+ isLoading: false,
+ };
+ },
+ computed: {
+ notificationLevels() {
+ return this.dropdownItems.map((level) => ({
+ level,
+ title: this.$options.i18n.notificationTitles[level] || '',
+ description: this.$options.i18n.notificationDescriptions[level] || '',
+ }));
+ },
+ isCustomNotification() {
+ return this.selectedNotificationLevel === CUSTOM_LEVEL;
+ },
+ buttonIcon() {
+ if (this.isLoading) {
+ return null;
+ }
+
+ return this.selectedNotificationLevel === 'disabled' ? 'notifications-off' : 'notifications';
+ },
+ buttonText() {
+ return this.showLabel
+ ? this.$options.i18n.notificationTitles[this.selectedNotificationLevel]
+ : null;
+ },
+ buttonTooltip() {
+ const notificationTitle =
+ this.$options.i18n.notificationTitles[this.selectedNotificationLevel] ||
+ this.selectedNotificationLevel;
+
+ return this.disabled
+ ? this.$options.i18n.notificationDescriptions.owner_disabled
+ : sprintf(this.$options.i18n.notificationTooltipTitle, {
+ notification_title: notificationTitle,
+ });
+ },
+ },
+ methods: {
+ selectItem(level) {
+ if (level !== this.selectedNotificationLevel) {
+ this.updateNotificationLevel(level);
+ }
+ },
+ async updateNotificationLevel(level) {
+ this.isLoading = true;
+
+ try {
+ await Api.updateNotificationSettings(this.projectId, this.groupId, { level });
+ this.selectedNotificationLevel = level;
+
+ if (level === CUSTOM_LEVEL) {
+ this.$refs.customNotificationsModal.open();
+ }
+ } catch (error) {
+ this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage, { type: 'error' });
+ } finally {
+ this.isLoading = false;
+ }
+ },
+ },
+ customLevel: CUSTOM_LEVEL,
+ i18n,
+ modalId: 'custom-notifications-modal',
+};
+</script>
+
+<template>
+ <div :class="containerClass">
+ <gl-button-group
+ v-if="isCustomNotification"
+ v-gl-tooltip="{ title: buttonTooltip }"
+ data-testid="notificationButton"
+ :size="buttonSize"
+ >
+ <gl-button
+ v-gl-modal="$options.modalId"
+ :size="buttonSize"
+ :icon="buttonIcon"
+ :loading="isLoading"
+ :disabled="disabled"
+ >
+ <template v-if="buttonText">{{ buttonText }}</template>
+ </gl-button>
+ <gl-dropdown :size="buttonSize" :disabled="disabled">
+ <notifications-dropdown-item
+ v-for="item in notificationLevels"
+ :key="item.level"
+ :level="item.level"
+ :title="item.title"
+ :description="item.description"
+ :notification-level="selectedNotificationLevel"
+ @item-selected="selectItem"
+ />
+ <gl-dropdown-divider />
+ <notifications-dropdown-item
+ :key="$options.customLevel"
+ :level="$options.customLevel"
+ :title="$options.i18n.notificationTitles.custom"
+ :description="$options.i18n.notificationDescriptions.custom"
+ :notification-level="selectedNotificationLevel"
+ @item-selected="selectItem"
+ />
+ </gl-dropdown>
+ </gl-button-group>
+
+ <gl-dropdown
+ v-else
+ v-gl-tooltip="{ title: buttonTooltip }"
+ data-testid="notificationButton"
+ :text="buttonText"
+ :icon="buttonIcon"
+ :loading="isLoading"
+ :size="buttonSize"
+ :disabled="disabled"
+ >
+ <notifications-dropdown-item
+ v-for="item in notificationLevels"
+ :key="item.level"
+ :level="item.level"
+ :title="item.title"
+ :description="item.description"
+ :notification-level="selectedNotificationLevel"
+ @item-selected="selectItem"
+ />
+ <gl-dropdown-divider />
+ <notifications-dropdown-item
+ :key="$options.customLevel"
+ :level="$options.customLevel"
+ :title="$options.i18n.notificationTitles.custom"
+ :description="$options.i18n.notificationDescriptions.custom"
+ :notification-level="selectedNotificationLevel"
+ @item-selected="selectItem"
+ />
+ </gl-dropdown>
+ <custom-notifications-modal ref="customNotificationsModal" :modal-id="$options.modalId" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/notifications/components/notifications_dropdown_item.vue b/app/assets/javascripts/notifications/components/notifications_dropdown_item.vue
new file mode 100644
index 00000000000..73bb9c1b36f
--- /dev/null
+++ b/app/assets/javascripts/notifications/components/notifications_dropdown_item.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ name: 'NotificationsDropdownItem',
+ components: {
+ GlDropdownItem,
+ },
+ props: {
+ level: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ description: {
+ type: String,
+ required: true,
+ },
+ notificationLevel: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ isActive() {
+ return this.notificationLevel === this.level;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown-item is-check-item :is-checked="isActive" @click="$emit('item-selected', level)">
+ <div class="gl-display-flex gl-flex-direction-column">
+ <span class="gl-font-weight-bold">{{ title }}</span>
+ <span class="gl-text-gray-500">{{ description }}</span>
+ </div>
+ </gl-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/notifications/constants.js b/app/assets/javascripts/notifications/constants.js
new file mode 100644
index 00000000000..07c569a0293
--- /dev/null
+++ b/app/assets/javascripts/notifications/constants.js
@@ -0,0 +1,58 @@
+import { __, s__ } from '~/locale';
+
+export const CUSTOM_LEVEL = 'custom';
+
+export const i18n = {
+ notificationTitles: {
+ participating: s__('NotificationLevel|Participate'),
+ mention: s__('NotificationLevel|On mention'),
+ watch: s__('NotificationLevel|Watch'),
+ global: s__('NotificationLevel|Global'),
+ disabled: s__('NotificationLevel|Disabled'),
+ custom: s__('NotificationLevel|Custom'),
+ },
+ notificationTooltipTitle: __('Notification setting - %{notification_title}'),
+ notificationDescriptions: {
+ participating: __('You will only receive notifications for threads you have participated in'),
+ mention: __('You will receive notifications only for comments in which you were @mentioned'),
+ watch: __('You will receive notifications for any activity'),
+ disabled: __('You will not get any notifications via email'),
+ global: __('Use your global notification setting'),
+ custom: __('You will only receive notifications for the events you choose'),
+ owner_disabled: __('Notifications have been disabled by the project or group owner'),
+ },
+ updateNotificationLevelErrorMessage: __(
+ 'An error occured while updating the notification settings. Please try again.',
+ ),
+ loadNotificationLevelErrorMessage: __(
+ 'An error occured while loading the notification settings. Please try again.',
+ ),
+ customNotificationsModal: {
+ title: __('Custom notification events'),
+ bodyTitle: __('Notification events'),
+ bodyMessage: __(
+ '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}.',
+ ),
+ },
+ eventNames: {
+ change_reviewer_merge_request: s__('NotificationEvent|Change reviewer merge request'),
+ close_issue: s__('NotificationEvent|Close issue'),
+ close_merge_request: s__('NotificationEvent|Close merge request'),
+ failed_pipeline: s__('NotificationEvent|Failed pipeline'),
+ fixed_pipeline: s__('NotificationEvent|Fixed pipeline'),
+ issue_due: s__('NotificationEvent|Issue due'),
+ merge_merge_request: s__('NotificationEvent|Merge merge request'),
+ moved_project: s__('NotificationEvent|Moved project'),
+ new_epic: s__('NotificationEvent|New epic'),
+ new_issue: s__('NotificationEvent|New issue'),
+ new_merge_request: s__('NotificationEvent|New merge request'),
+ new_note: s__('NotificationEvent|New note'),
+ new_release: s__('NotificationEvent|New release'),
+ push_to_merge_request: s__('NotificationEvent|Push to merge request'),
+ reassign_issue: s__('NotificationEvent|Reassign issue'),
+ reassign_merge_request: s__('NotificationEvent|Reassign merge request'),
+ reopen_issue: s__('NotificationEvent|Reopen issue'),
+ reopen_merge_request: s__('NotificationEvent|Reopen merge request'),
+ success_pipeline: s__('NotificationEvent|Successful pipeline'),
+ },
+};
diff --git a/app/assets/javascripts/notifications/index.js b/app/assets/javascripts/notifications/index.js
new file mode 100644
index 00000000000..d60a368703c
--- /dev/null
+++ b/app/assets/javascripts/notifications/index.js
@@ -0,0 +1,44 @@
+import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import NotificationsDropdown from './components/notifications_dropdown.vue';
+
+Vue.use(GlToast);
+
+export default () => {
+ const containers = document.querySelectorAll('.js-vue-notification-dropdown');
+
+ if (!containers.length) return false;
+
+ return containers.forEach((el) => {
+ const {
+ containerClass,
+ buttonSize,
+ disabled,
+ dropdownItems,
+ notificationLevel,
+ helpPagePath,
+ projectId,
+ groupId,
+ showLabel,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ containerClass,
+ buttonSize,
+ disabled: parseBoolean(disabled),
+ dropdownItems: JSON.parse(dropdownItems),
+ initialNotificationLevel: notificationLevel,
+ helpPagePath,
+ projectId,
+ groupId,
+ showLabel: parseBoolean(showLabel),
+ },
+ render(h) {
+ return h(NotificationsDropdown);
+ },
+ });
+ });
+};
diff --git a/app/assets/javascripts/notifications_dropdown.js b/app/assets/javascripts/notifications_dropdown.js
index eaa5ec3a2e4..d61defed14d 100644
--- a/app/assets/javascripts/notifications_dropdown.js
+++ b/app/assets/javascripts/notifications_dropdown.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { Rails } from '~/lib/utils/rails_ujs';
-import { deprecatedCreateFlash as Flash } from './flash';
import { __ } from '~/locale';
+import { deprecatedCreateFlash as Flash } from './flash';
export default function notificationsDropdown() {
$(document).on('click', '.update-notification', function updateNotificationCallback(e) {
diff --git a/app/assets/javascripts/notifications_form.js b/app/assets/javascripts/notifications_form.js
index 1b12fece23a..8b90da71bef 100644
--- a/app/assets/javascripts/notifications_form.js
+++ b/app/assets/javascripts/notifications_form.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import { __ } from './locale';
-import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from './flash';
+import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
export default class NotificationsForm {
constructor() {
diff --git a/app/assets/javascripts/onboarding_issues/index.js b/app/assets/javascripts/onboarding_issues/index.js
deleted file mode 100644
index b23a10c9254..00000000000
--- a/app/assets/javascripts/onboarding_issues/index.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import $ from 'jquery';
-import { parseBoolean, getCookie, setCookie, removeCookie } from '~/lib/utils/common_utils';
-import { __, sprintf } from '~/locale';
-import Tracking from '~/tracking';
-
-const COOKIE_NAME = 'onboarding_issues_settings';
-
-const POPOVER_LOCATIONS = {
- GROUPS_SHOW: 'groups#show',
- PROJECTS_SHOW: 'projects#show',
- ISSUES_INDEX: 'issues#index',
-};
-
-const removeLearnGitLabCookie = () => {
- removeCookie(COOKIE_NAME);
-};
-
-function disposePopover(event) {
- event.preventDefault();
- this.popover('dispose');
- removeLearnGitLabCookie();
- Tracking.event('Growth::Conversion::Experiment::OnboardingIssues', 'dismiss_popover');
-}
-
-const showPopover = (el, path, footer, options) => {
- // Cookie value looks like `{ 'groups#show': true, 'projects#show': true, 'issues#index': true }`. When it doesn't exist, don't show the popover.
- const cookie = getCookie(COOKIE_NAME);
- if (!cookie) return;
-
- // When the popover action has already been taken, don't show the popover.
- const settings = JSON.parse(cookie);
- if (!parseBoolean(settings[path])) return;
-
- const defaultOptions = {
- boundary: 'window',
- html: true,
- placement: 'top',
- template: `<div class="popover blue learn-gitlab d-none d-xl-block" role="tooltip">
- <div class="arrow"></div>
- <div class="close cursor-pointer gl-font-base text-white gl-opacity-10 p-2">&#10005</div>
- <div class="popover-body gl-font-base gl-line-height-20 pb-0 px-3"></div>
- <div class="bold text-right text-white p-2">${footer}</div>
- </div>`,
- };
-
- // When one of the popovers is dismissed, remove the cookie.
- const closeButton = () => document.querySelector('.learn-gitlab.popover .close');
-
- // We still have to use jQuery, since Bootstrap's Popover is based on jQuery.
- const jQueryEl = $(el);
- const clickCloseButton = disposePopover.bind(jQueryEl);
-
- jQueryEl
- .popover({ ...defaultOptions, ...options })
- .on('inserted.bs.popover', () => closeButton().addEventListener('click', clickCloseButton))
- .on('hide.bs.dropdown', () => closeButton().removeEventListener('click', clickCloseButton))
- .popover('show');
-
- // The previous popover actions have been taken, don't show those popovers anymore.
- Object.keys(settings).forEach((pathSetting) => {
- if (path !== pathSetting) {
- settings[pathSetting] = false;
- } else {
- setCookie(COOKIE_NAME, settings);
- }
- });
-
- // The final popover action will be taken on click, we then no longer need the cookie.
- if (path === POPOVER_LOCATIONS.ISSUES_INDEX) {
- el.addEventListener('click', removeLearnGitLabCookie);
- }
-};
-
-export const showLearnGitLabGroupItemPopover = (id) => {
- const el = document.querySelector(`#group-${id} .group-text a`);
-
- if (!el) return;
-
- const options = {
- content: __(
- 'Here are all your projects in your group, including the one you just created. To start, let’s take a look at your personalized learning project which will help you learn about GitLab at your own pace.',
- ),
- };
-
- showPopover(el, POPOVER_LOCATIONS.GROUPS_SHOW, '1 / 2', options);
-};
-
-export const showLearnGitLabProjectPopover = () => {
- // Do not show a popover if we are not viewing the 'Learn GitLab' project.
- if (!window.location.pathname.includes('learn-gitlab')) return;
-
- const el = document.querySelector('a.shortcuts-issues');
-
- if (!el) return;
-
- const options = {
- content: sprintf(
- __(
- 'Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board.',
- ),
- { strongStart: '<strong>', strongEnd: '</strong>' },
- false,
- ),
- };
-
- showPopover(el, POPOVER_LOCATIONS.PROJECTS_SHOW, '2 / 2', options);
-};
-
-export const showLearnGitLabIssuesPopover = () => {
- // Do not show a popover if we are not viewing the 'Learn GitLab' project.
- if (!window.location.pathname.includes('learn-gitlab')) return;
-
- const el = document.querySelector('a[data-qa-selector="issue_boards_link"]');
-
- if (!el) return;
-
- const options = {
- content: sprintf(
- __(
- 'Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board.',
- ),
- { strongStart: '<strong>', strongEnd: '</strong>' },
- false,
- ),
- };
-
- showPopover(el, POPOVER_LOCATIONS.ISSUES_INDEX, '2 / 2', options);
-};
diff --git a/app/assets/javascripts/operation_settings/components/form_group/dashboard_timezone.vue b/app/assets/javascripts/operation_settings/components/form_group/dashboard_timezone.vue
index d83146d2f5e..7120ad511d3 100644
--- a/app/assets/javascripts/operation_settings/components/form_group/dashboard_timezone.vue
+++ b/app/assets/javascripts/operation_settings/components/form_group/dashboard_timezone.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import { s__ } from '~/locale';
import { timezones } from '~/monitoring/format_date';
diff --git a/app/assets/javascripts/operation_settings/components/form_group/external_dashboard.vue b/app/assets/javascripts/operation_settings/components/form_group/external_dashboard.vue
index 812c5a3fe9a..2ea5b4e01b1 100644
--- a/app/assets/javascripts/operation_settings/components/form_group/external_dashboard.vue
+++ b/app/assets/javascripts/operation_settings/components/form_group/external_dashboard.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/operation_settings/components/metrics_settings.vue b/app/assets/javascripts/operation_settings/components/metrics_settings.vue
index 2e972dd7154..0c0bbb744b3 100644
--- a/app/assets/javascripts/operation_settings/components/metrics_settings.vue
+++ b/app/assets/javascripts/operation_settings/components/metrics_settings.vue
@@ -1,8 +1,8 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlButton, GlLink } from '@gitlab/ui';
-import ExternalDashboard from './form_group/external_dashboard.vue';
+import { mapState, mapActions } from 'vuex';
import DashboardTimezone from './form_group/dashboard_timezone.vue';
+import ExternalDashboard from './form_group/external_dashboard.vue';
export default {
components: {
@@ -31,9 +31,9 @@ export default {
<template>
<section class="settings no-animate">
<div class="settings-header">
- <h3 class="js-section-header h4">
+ <h4 class="js-section-header">
{{ s__('MetricsSettings|Metrics dashboard') }}
- </h3>
+ </h4>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
<p class="js-section-sub-header">
{{ s__('MetricsSettings|Manage Metrics Dashboard settings.') }}
diff --git a/app/assets/javascripts/operation_settings/index.js b/app/assets/javascripts/operation_settings/index.js
index 426a060949e..faddf9c7b81 100644
--- a/app/assets/javascripts/operation_settings/index.js
+++ b/app/assets/javascripts/operation_settings/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import store from './store';
import MetricsSettingsForm from './components/metrics_settings.vue';
+import store from './store';
export default () => {
const el = document.querySelector('.js-operation-settings');
diff --git a/app/assets/javascripts/operation_settings/store/actions.js b/app/assets/javascripts/operation_settings/store/actions.js
index bbbff6630d3..af66e344b35 100644
--- a/app/assets/javascripts/operation_settings/store/actions.js
+++ b/app/assets/javascripts/operation_settings/store/actions.js
@@ -1,7 +1,7 @@
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import * as mutationTypes from './mutation_types';
export const setExternalDashboardUrl = ({ commit }, url) =>
diff --git a/app/assets/javascripts/operation_settings/store/index.js b/app/assets/javascripts/operation_settings/store/index.js
index e3dcfd31a83..a11bd8089fd 100644
--- a/app/assets/javascripts/operation_settings/store/index.js
+++ b/app/assets/javascripts/operation_settings/store/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/packages/details/components/app.vue b/app/assets/javascripts/packages/details/components/app.vue
index c9f1c8b903c..bcfb17a1529 100644
--- a/app/assets/javascripts/packages/details/components/app.vue
+++ b/app/assets/javascripts/packages/details/components/app.vue
@@ -11,20 +11,20 @@ import {
GlSprintf,
} from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
-import Tracking from '~/tracking';
-import { s__ } from '~/locale';
import { objectToQueryString } from '~/lib/utils/common_utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import PackageHistory from './package_history.vue';
-import PackageTitle from './package_title.vue';
-import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
+import { s__ } from '~/locale';
+import Tracking from '~/tracking';
import PackageListRow from '../../shared/components/package_list_row.vue';
-import { packageTypeToTrackCategory } from '../../shared/utils';
+import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
import { PackageType, TrackingActions, SHOW_DELETE_SUCCESS_ALERT } from '../../shared/constants';
-import DependencyRow from './dependency_row.vue';
+import { packageTypeToTrackCategory } from '../../shared/utils';
import AdditionalMetadata from './additional_metadata.vue';
+import DependencyRow from './dependency_row.vue';
import InstallationCommands from './installation_commands.vue';
import PackageFiles from './package_files.vue';
+import PackageHistory from './package_history.vue';
+import PackageTitle from './package_title.vue';
export default {
name: 'PackagesApp',
diff --git a/app/assets/javascripts/packages/details/components/installation_commands.vue b/app/assets/javascripts/packages/details/components/installation_commands.vue
index 138103020a7..28978913e6e 100644
--- a/app/assets/javascripts/packages/details/components/installation_commands.vue
+++ b/app/assets/javascripts/packages/details/components/installation_commands.vue
@@ -1,11 +1,11 @@
<script>
+import { PackageType } from '../../shared/constants';
+import ComposerInstallation from './composer_installation.vue';
import ConanInstallation from './conan_installation.vue';
import MavenInstallation from './maven_installation.vue';
import NpmInstallation from './npm_installation.vue';
import NugetInstallation from './nuget_installation.vue';
import PypiInstallation from './pypi_installation.vue';
-import ComposerInstallation from './composer_installation.vue';
-import { PackageType } from '../../shared/constants';
export default {
name: 'InstallationCommands',
diff --git a/app/assets/javascripts/packages/details/components/package_files.vue b/app/assets/javascripts/packages/details/components/package_files.vue
index 3add454fda3..c5e929fe2a4 100644
--- a/app/assets/javascripts/packages/details/components/package_files.vue
+++ b/app/assets/javascripts/packages/details/components/package_files.vue
@@ -1,11 +1,11 @@
<script>
import { GlLink, GlTable } from '@gitlab/ui';
import { last } from 'lodash';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
import Tracking from '~/tracking';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
name: 'PackageFiles',
diff --git a/app/assets/javascripts/packages/details/components/package_history.vue b/app/assets/javascripts/packages/details/components/package_history.vue
index 62550602428..0d7a73c12f1 100644
--- a/app/assets/javascripts/packages/details/components/package_history.vue
+++ b/app/assets/javascripts/packages/details/components/package_history.vue
@@ -1,11 +1,11 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { first } from 'lodash';
-import { s__, n__ } from '~/locale';
import { truncateSha } from '~/lib/utils/text_utility';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
+import { s__, n__ } from '~/locale';
import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
+import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
name: 'PackageHistory',
diff --git a/app/assets/javascripts/packages/details/components/package_title.vue b/app/assets/javascripts/packages/details/components/package_title.vue
index 6b7eeacb964..d02a7b3ec27 100644
--- a/app/assets/javascripts/packages/details/components/package_title.vue
+++ b/app/assets/javascripts/packages/details/components/package_title.vue
@@ -1,14 +1,14 @@
<script>
/* eslint-disable vue/v-slot-style */
-import { mapState, mapGetters } from 'vuex';
import { GlIcon, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
-import PackageTags from '../../shared/components/package_tags.vue';
+import { mapState, mapGetters } from 'vuex';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import { __ } from '~/locale';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+import PackageTags from '../../shared/components/package_tags.vue';
export default {
name: 'PackageTitle',
diff --git a/app/assets/javascripts/packages/details/index.js b/app/assets/javascripts/packages/details/index.js
index 233da3e4a99..5b9d58a3860 100644
--- a/app/assets/javascripts/packages/details/index.js
+++ b/app/assets/javascripts/packages/details/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import PackagesApp from './components/app.vue';
import Translate from '~/vue_shared/translate';
+import PackagesApp from './components/app.vue';
import createStore from './store';
Vue.use(Translate);
diff --git a/app/assets/javascripts/packages/details/store/actions.js b/app/assets/javascripts/packages/details/store/actions.js
index 340f60258a0..87216366c8b 100644
--- a/app/assets/javascripts/packages/details/store/actions.js
+++ b/app/assets/javascripts/packages/details/store/actions.js
@@ -1,7 +1,7 @@
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
+import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants';
import * as types from './mutation_types';
export const fetchPackageVersions = ({ commit, state }) => {
diff --git a/app/assets/javascripts/packages/list/components/package_search.vue b/app/assets/javascripts/packages/list/components/package_search.vue
new file mode 100644
index 00000000000..cd61d323d83
--- /dev/null
+++ b/app/assets/javascripts/packages/list/components/package_search.vue
@@ -0,0 +1,50 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { __, s__ } from '~/locale';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import getTableHeaders from '../utils';
+import PackageTypeToken from './tokens/package_type_token.vue';
+
+export default {
+ tokens: [
+ {
+ type: 'type',
+ icon: 'package',
+ title: s__('PackageRegistry|Type'),
+ unique: true,
+ token: PackageTypeToken,
+ operators: [{ value: '=', description: __('is'), default: 'true' }],
+ },
+ ],
+ components: { RegistrySearch },
+ computed: {
+ ...mapState({
+ isGroupPage: (state) => state.config.isGroupPage,
+ sorting: (state) => state.sorting,
+ filter: (state) => state.filter,
+ }),
+ sortableFields() {
+ return getTableHeaders(this.isGroupPage);
+ },
+ },
+ methods: {
+ ...mapActions(['setSorting', 'setFilter']),
+ updateSorting(newValue) {
+ this.setSorting(newValue);
+ this.$emit('update');
+ },
+ },
+};
+</script>
+
+<template>
+ <registry-search
+ :filter="filter"
+ :sorting="sorting"
+ :tokens="$options.tokens"
+ :sortable-fields="sortableFields"
+ @sorting:changed="updateSorting"
+ @filter:changed="setFilter"
+ @filter:submit="$emit('update')"
+ />
+</template>
diff --git a/app/assets/javascripts/packages/list/components/package_title.vue b/app/assets/javascripts/packages/list/components/package_title.vue
index f94a98e4ca7..6176e15ffd4 100644
--- a/app/assets/javascripts/packages/list/components/package_title.vue
+++ b/app/assets/javascripts/packages/list/components/package_title.vue
@@ -1,7 +1,7 @@
<script>
import { n__ } from '~/locale';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '../constants';
export default {
diff --git a/app/assets/javascripts/packages/list/components/packages_filter.vue b/app/assets/javascripts/packages/list/components/packages_filter.vue
deleted file mode 100644
index 17398071217..00000000000
--- a/app/assets/javascripts/packages/list/components/packages_filter.vue
+++ /dev/null
@@ -1,21 +0,0 @@
-<script>
-import { GlSearchBoxByClick } from '@gitlab/ui';
-import { mapActions } from 'vuex';
-
-export default {
- components: {
- GlSearchBoxByClick,
- },
- methods: {
- ...mapActions(['setFilter']),
- },
-};
-</script>
-
-<template>
- <gl-search-box-by-click
- :placeholder="s__('PackageRegistry|Filter by name')"
- @submit="$emit('filter')"
- @input="setFilter"
- />
-</template>
diff --git a/app/assets/javascripts/packages/list/components/packages_list.vue b/app/assets/javascripts/packages/list/components/packages_list.vue
index 1e38ee525b8..23ba070aa26 100644
--- a/app/assets/javascripts/packages/list/components/packages_list.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list.vue
@@ -1,12 +1,12 @@
<script>
-import { mapState, mapGetters } from 'vuex';
import { GlPagination, GlModal, GlSprintf } from '@gitlab/ui';
-import Tracking from '~/tracking';
+import { mapState, mapGetters } from 'vuex';
import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+import PackagesListRow from '../../shared/components/package_list_row.vue';
+import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
import { TrackingActions } from '../../shared/constants';
import { packageTypeToTrackCategory } from '../../shared/utils';
-import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
-import PackagesListRow from '../../shared/components/package_list_row.vue';
export default {
components: {
diff --git a/app/assets/javascripts/packages/list/components/packages_list_app.vue b/app/assets/javascripts/packages/list/components/packages_list_app.vue
index 2a786b92515..a609dfebedf 100644
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue
@@ -1,39 +1,43 @@
<script>
+import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
-import { GlEmptyState, GlTab, GlTabs, GlLink, GlSprintf } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
import createFlash from '~/flash';
import { historyReplaceState } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
-import PackageFilter from './packages_filter.vue';
-import PackageList from './packages_list.vue';
-import PackageSort from './packages_sort.vue';
-import { PACKAGE_REGISTRY_TABS, DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
+import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
+import PackageSearch from './package_search.vue';
import PackageTitle from './package_title.vue';
+import PackageList from './packages_list.vue';
export default {
components: {
GlEmptyState,
- GlTab,
- GlTabs,
GlLink,
GlSprintf,
- PackageFilter,
PackageList,
- PackageSort,
PackageTitle,
+ PackageSearch,
},
computed: {
...mapState({
emptyListIllustration: (state) => state.config.emptyListIllustration,
emptyListHelpUrl: (state) => state.config.emptyListHelpUrl,
- filterQuery: (state) => state.filterQuery,
+ filter: (state) => state.filter,
selectedType: (state) => state.selectedType,
packageHelpUrl: (state) => state.config.packageHelpUrl,
packagesCount: (state) => state.pagination?.total,
}),
- tabsToRender() {
- return PACKAGE_REGISTRY_TABS;
+ emptySearch() {
+ return (
+ this.filter.filter((f) => f.type !== 'filtered-search-term' || f.value?.data).length === 0
+ );
+ },
+
+ emptyStateTitle() {
+ return this.emptySearch
+ ? s__('PackageRegistry|There are no packages yet')
+ : s__('PackageRegistry|Sorry, your filter produced no results');
},
},
mounted() {
@@ -48,27 +52,6 @@ export default {
onPackageDeleteRequest(item) {
return this.requestDeletePackage(item);
},
- tabChanged(index) {
- const selected = PACKAGE_REGISTRY_TABS[index];
-
- if (selected !== this.selectedType) {
- this.setSelectedType(selected);
- this.requestPackagesList();
- }
- },
- emptyStateTitle({ title, type }) {
- if (this.filterQuery) {
- return s__('PackageRegistry|Sorry, your filter produced no results');
- }
-
- if (type) {
- return sprintf(s__('PackageRegistry|There are no %{packageType} packages yet'), {
- packageType: title,
- });
- }
-
- return s__('PackageRegistry|There are no packages yet');
- },
checkDeleteAlert() {
const urlParams = new URLSearchParams(window.location.search);
const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT);
@@ -92,33 +75,21 @@ export default {
<template>
<div>
<package-title :package-help-url="packageHelpUrl" :packages-count="packagesCount" />
+ <package-search @update="requestPackagesList" />
- <gl-tabs @input="tabChanged">
- <template #tabs-end>
- <div
- class="gl-display-flex gl-align-self-center gl-py-2 gl-flex-grow-1 gl-justify-content-end"
- >
- <package-filter class="gl-mr-2" @filter="requestPackagesList" />
- <package-sort @sort:changed="requestPackagesList" />
- </div>
- </template>
-
- <gl-tab v-for="(tab, index) in tabsToRender" :key="index" :title="tab.title">
- <package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
- <template #empty-state>
- <gl-empty-state :title="emptyStateTitle(tab)" :svg-path="emptyListIllustration">
- <template #description>
- <gl-sprintf v-if="filterQuery" :message="$options.i18n.widenFilters" />
- <gl-sprintf v-else :message="$options.i18n.noResults">
- <template #noPackagesLink="{ content }">
- <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
+ <package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
+ <template #empty-state>
+ <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
+ <template #description>
+ <gl-sprintf v-if="!emptySearch" :message="$options.i18n.widenFilters" />
+ <gl-sprintf v-else :message="$options.i18n.noResults">
+ <template #noPackagesLink="{ content }">
+ <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
</template>
- </gl-empty-state>
+ </gl-sprintf>
</template>
- </package-list>
- </gl-tab>
- </gl-tabs>
+ </gl-empty-state>
+ </template>
+ </package-list>
</div>
</template>
diff --git a/app/assets/javascripts/packages/list/components/packages_sort.vue b/app/assets/javascripts/packages/list/components/packages_sort.vue
deleted file mode 100644
index 4b2d9091f8f..00000000000
--- a/app/assets/javascripts/packages/list/components/packages_sort.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-<script>
-import { GlSorting, GlSortingItem } from '@gitlab/ui';
-import { mapState, mapActions } from 'vuex';
-import { ASCENDING_ODER, DESCENDING_ORDER } from '../constants';
-import getTableHeaders from '../utils';
-
-export default {
- name: 'PackageSort',
- components: {
- GlSorting,
- GlSortingItem,
- },
- computed: {
- ...mapState({
- isGroupPage: (state) => state.config.isGroupPage,
- orderBy: (state) => state.sorting.orderBy,
- sort: (state) => state.sorting.sort,
- }),
- sortText() {
- const field = this.sortableFields.find((s) => s.orderBy === this.orderBy);
- return field ? field.label : '';
- },
- sortableFields() {
- return getTableHeaders(this.isGroupPage);
- },
- isSortAscending() {
- return this.sort === ASCENDING_ODER;
- },
- },
- methods: {
- ...mapActions(['setSorting']),
- onDirectionChange() {
- const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER;
- this.setSorting({ sort });
- this.$emit('sort:changed');
- },
- onSortItemClick(item) {
- this.setSorting({ orderBy: item });
- this.$emit('sort:changed');
- },
- },
-};
-</script>
-
-<template>
- <gl-sorting
- :text="sortText"
- :is-ascending="isSortAscending"
- @sortDirectionChange="onDirectionChange"
- >
- <gl-sorting-item
- v-for="item in sortableFields"
- ref="packageListSortItem"
- :key="item.orderBy"
- @click="onSortItemClick(item.orderBy)"
- >
- {{ item.label }}
- </gl-sorting-item>
- </gl-sorting>
-</template>
diff --git a/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue b/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue
new file mode 100644
index 00000000000..74b6774712e
--- /dev/null
+++ b/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue
@@ -0,0 +1,26 @@
+<script>
+import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
+import { PACKAGE_TYPES } from '../../constants';
+
+export default {
+ components: {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ },
+ PACKAGE_TYPES,
+};
+</script>
+
+<template>
+ <gl-filtered-search-token v-bind="{ ...$attrs }" v-on="$listeners">
+ <template #suggestions>
+ <gl-filtered-search-suggestion
+ v-for="(type, index) in $options.PACKAGE_TYPES"
+ :key="index"
+ :value="type.type"
+ >
+ {{ type.title }}
+ </gl-filtered-search-suggestion>
+ </template>
+ </gl-filtered-search-token>
+</template>
diff --git a/app/assets/javascripts/packages/list/constants.js b/app/assets/javascripts/packages/list/constants.js
index e14696e0d1c..d47eb8c3421 100644
--- a/app/assets/javascripts/packages/list/constants.js
+++ b/app/assets/javascripts/packages/list/constants.js
@@ -26,9 +26,6 @@ export const LIST_LABEL_PACKAGE_TYPE = __('Type');
export const LIST_LABEL_CREATED_AT = __('Published');
export const LIST_LABEL_ACTIONS = '';
-export const ASCENDING_ODER = 'asc';
-export const DESCENDING_ORDER = 'desc';
-
// The following is not translated because it is used to build a JavaScript exception error message
export const MISSING_DELETE_PATH_ERROR = 'Missing delete_api_path link';
@@ -55,11 +52,7 @@ export const SORT_FIELDS = [
},
];
-export const PACKAGE_REGISTRY_TABS = [
- {
- title: __('All'),
- type: null,
- },
+export const PACKAGE_TYPES = [
{
title: s__('PackageRegistry|Composer'),
type: PackageType.COMPOSER,
diff --git a/app/assets/javascripts/packages/list/packages_list_app_bundle.js b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
index 2f240cff143..58b09c1ebd1 100644
--- a/app/assets/javascripts/packages/list/packages_list_app_bundle.js
+++ b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import Translate from '~/vue_shared/translate';
-import { createStore } from './stores';
import PackagesListApp from './components/packages_list_app.vue';
-import createDefaultClient from '~/lib/graphql';
+import { createStore } from './stores';
Vue.use(VueApollo);
Vue.use(Translate);
diff --git a/app/assets/javascripts/packages/list/stores/actions.js b/app/assets/javascripts/packages/list/stores/actions.js
index bbc11e3cf13..195117b9ddb 100644
--- a/app/assets/javascripts/packages/list/stores/actions.js
+++ b/app/assets/javascripts/packages/list/stores/actions.js
@@ -1,8 +1,7 @@
import Api from '~/api';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
-import * as types from './mutation_types';
import {
FETCH_PACKAGES_LIST_ERROR_MESSAGE,
DELETE_PACKAGE_SUCCESS_MESSAGE,
@@ -11,11 +10,11 @@ import {
MISSING_DELETE_PATH_ERROR,
} from '../constants';
import { getNewPaginationPage } from '../utils';
+import * as types from './mutation_types';
export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
export const setLoading = ({ commit }, data) => commit(types.SET_MAIN_LOADING, data);
export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
-export const setSelectedType = ({ commit }, data) => commit(types.SET_SELECTED_TYPE, data);
export const setFilter = ({ commit }, data) => commit(types.SET_FILTER, data);
export const receivePackagesListSuccess = ({ commit }, { data, headers }) => {
@@ -29,9 +28,9 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params;
const { sort, orderBy } = state.sorting;
- const type = state.selectedType?.type?.toLowerCase();
- const nameFilter = state.filterQuery?.toLowerCase();
- const packageFilters = { package_type: type, package_name: nameFilter };
+ const type = state.filter.find((f) => f.type === 'type');
+ const name = state.filter.find((f) => f.type === 'filtered-search-term');
+ const packageFilters = { package_type: type?.value?.data, package_name: name?.value?.data };
const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages';
diff --git a/app/assets/javascripts/packages/list/stores/getters.js b/app/assets/javascripts/packages/list/stores/getters.js
index 85c489deda0..482c111b58b 100644
--- a/app/assets/javascripts/packages/list/stores/getters.js
+++ b/app/assets/javascripts/packages/list/stores/getters.js
@@ -1,5 +1,5 @@
-import { LIST_KEY_PROJECT } from '../constants';
import { beautifyPath } from '../../shared/utils';
+import { LIST_KEY_PROJECT } from '../constants';
export default (state) =>
state.packages.map((p) => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) }));
diff --git a/app/assets/javascripts/packages/list/stores/mutation_types.js b/app/assets/javascripts/packages/list/stores/mutation_types.js
index a5a584ccf1f..561ad97f7e3 100644
--- a/app/assets/javascripts/packages/list/stores/mutation_types.js
+++ b/app/assets/javascripts/packages/list/stores/mutation_types.js
@@ -4,5 +4,4 @@ export const SET_PACKAGE_LIST_SUCCESS = 'SET_PACKAGE_LIST_SUCCESS';
export const SET_PAGINATION = 'SET_PAGINATION';
export const SET_MAIN_LOADING = 'SET_MAIN_LOADING';
export const SET_SORTING = 'SET_SORTING';
-export const SET_SELECTED_TYPE = 'SET_SELECTED_TYPE';
export const SET_FILTER = 'SET_FILTER';
diff --git a/app/assets/javascripts/packages/list/stores/mutations.js b/app/assets/javascripts/packages/list/stores/mutations.js
index 2fe7981b3d9..4ce13cfcb29 100644
--- a/app/assets/javascripts/packages/list/stores/mutations.js
+++ b/app/assets/javascripts/packages/list/stores/mutations.js
@@ -1,6 +1,6 @@
-import * as types from './mutation_types';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { GROUP_PAGE_TYPE } from '../constants';
+import * as types from './mutation_types';
export default {
[types.SET_INITIAL_STATE](state, config) {
@@ -28,11 +28,7 @@ export default {
state.sorting = { ...state.sorting, ...sorting };
},
- [types.SET_SELECTED_TYPE](state, type) {
- state.selectedType = type;
- },
-
- [types.SET_FILTER](state, query) {
- state.filterQuery = query;
+ [types.SET_FILTER](state, filter) {
+ state.filter = filter;
},
};
diff --git a/app/assets/javascripts/packages/list/stores/state.js b/app/assets/javascripts/packages/list/stores/state.js
index 18ab2390b87..60f02eddc9f 100644
--- a/app/assets/javascripts/packages/list/stores/state.js
+++ b/app/assets/javascripts/packages/list/stores/state.js
@@ -1,5 +1,3 @@
-import { PACKAGE_REGISTRY_TABS } from '../constants';
-
export default () => ({
/**
* Determine if the component is loading data from the API
@@ -49,9 +47,8 @@ export default () => ({
/**
* The search query that is used to filter packages by name
*/
- filterQuery: '',
+ filter: [],
/**
* The selected TAB of the package types tabs
*/
- selectedType: PACKAGE_REGISTRY_TABS[0],
});
diff --git a/app/assets/javascripts/packages/shared/components/package_list_row.vue b/app/assets/javascripts/packages/shared/components/package_list_row.vue
index d55ca80a7fc..cdfe042c39f 100644
--- a/app/assets/javascripts/packages/shared/components/package_list_row.vue
+++ b/app/assets/javascripts/packages/shared/components/package_list_row.vue
@@ -1,11 +1,11 @@
<script>
import { GlButton, GlIcon, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
-import PackageTags from './package_tags.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+import { getPackageTypeLabel } from '../utils';
import PackagePath from './package_path.vue';
+import PackageTags from './package_tags.vue';
import PublishMethod from './publish_method.vue';
-import { getPackageTypeLabel } from '../utils';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import ListItem from '~/vue_shared/components/registry/list_item.vue';
export default {
name: 'PackageListRow',
@@ -88,7 +88,7 @@ export default {
<div class="gl-display-flex">
<span>{{ packageEntity.version }}</span>
- <div v-if="hasPipeline" class="gl-display-none gl-display-sm-flex gl-ml-2">
+ <div v-if="hasPipeline" class="gl-display-none gl-sm-display-flex gl-ml-2">
<gl-sprintf :message="s__('PackageRegistry|published by %{author}')">
<template #author>{{ packageEntity.pipeline.user.name }}</template>
</gl-sprintf>
diff --git a/app/assets/javascripts/packages/shared/components/package_tags.vue b/app/assets/javascripts/packages/shared/components/package_tags.vue
index 5172b855fc3..5ec950e4d45 100644
--- a/app/assets/javascripts/packages/shared/components/package_tags.vue
+++ b/app/assets/javascripts/packages/shared/components/package_tags.vue
@@ -91,7 +91,7 @@ export default {
variant="muted"
:title="moreTagsTooltip"
size="sm"
- class="gl-display-none gl-display-md-flex gl-ml-2"
+ class="gl-display-none gl-md-display-flex gl-ml-2"
><gl-sprintf :message="__('+%{tags} more')">
<template #tags>
{{ moreTagsDisplay }}
@@ -103,7 +103,7 @@ export default {
v-if="moreTagsDisplay && hideLabel"
data-testid="moreBadge"
variant="muted"
- class="gl-display-md-none gl-ml-2"
+ class="gl-md-display-none gl-ml-2"
>{{ tagsDisplay }}</gl-badge
>
</div>
diff --git a/app/assets/javascripts/packages/shared/components/packages_list_loader.vue b/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
index efd9f8db908..cf555f46f8c 100644
--- a/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
+++ b/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
@@ -21,7 +21,7 @@ export default {
<template>
<div>
- <div class="gl-flex-direction-column gl-display-sm-none" data-testid="mobile-loader">
+ <div class="gl-flex-direction-column gl-sm-display-none" data-testid="mobile-loader">
<gl-skeleton-loader
v-for="index in $options.rowsToRender.mobile"
:key="index"
@@ -37,7 +37,7 @@ export default {
</gl-skeleton-loader>
</div>
<div
- class="gl-display-none gl-display-sm-flex gl-flex-direction-column"
+ class="gl-display-none gl-sm-display-flex gl-flex-direction-column"
data-testid="desktop-loader"
>
<gl-skeleton-loader
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
index a3d507180c6..5cd8261ac23 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
@@ -1,9 +1,13 @@
+import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
+
+import { parseBoolean } from '~/lib/utils/common_utils';
import Translate from '~/vue_shared/translate';
import SettingsApp from './components/group_settings_app.vue';
import { apolloProvider } from './graphql';
Vue.use(Translate);
+Vue.use(GlToast);
export default () => {
const el = document.getElementById('js-packages-and-registries-settings');
@@ -13,6 +17,10 @@ export default () => {
return new Vue({
el,
apolloProvider,
+ provide: {
+ defaultExpanded: parseBoolean(el.dataset.defaultExpanded),
+ groupPath: el.dataset.groupPath,
+ },
render(createElement) {
return createElement(SettingsApp);
},
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
index 6bcecf43a13..933cbeaedce 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
@@ -1,9 +1,138 @@
<script>
+import { GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
+import MavenSettings from '~/packages_and_registries/settings/group/components/maven_settings.vue';
+
+import {
+ PACKAGE_SETTINGS_HEADER,
+ PACKAGE_SETTINGS_DESCRIPTION,
+ PACKAGES_DOCS_PATH,
+ ERROR_UPDATING_SETTINGS,
+ SUCCESS_UPDATING_SETTINGS,
+} from '~/packages_and_registries/settings/group/constants';
+import updateNamespacePackageSettings from '~/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql';
+import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
+import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update';
+import { updateGroupPackagesSettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
+import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
+
export default {
name: 'GroupSettingsApp',
+ i18n: {
+ PACKAGE_SETTINGS_HEADER,
+ PACKAGE_SETTINGS_DESCRIPTION,
+ },
+ links: {
+ PACKAGES_DOCS_PATH,
+ },
+ components: {
+ GlAlert,
+ GlSprintf,
+ GlLink,
+ SettingsBlock,
+ MavenSettings,
+ },
+ inject: ['defaultExpanded', 'groupPath'],
+ apollo: {
+ packageSettings: {
+ query: getGroupPackagesSettingsQuery,
+ variables() {
+ return {
+ fullPath: this.groupPath,
+ };
+ },
+ update(data) {
+ return data.group?.packageSettings;
+ },
+ },
+ },
+ data() {
+ return {
+ packageSettings: {},
+ errors: {},
+ alertMessage: null,
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.packageSettings.loading;
+ },
+ },
+ methods: {
+ dismissAlert() {
+ this.alertMessage = null;
+ },
+ updateSettings(payload) {
+ this.errors = {};
+ return this.$apollo
+ .mutate({
+ mutation: updateNamespacePackageSettings,
+ variables: {
+ input: {
+ namespacePath: this.groupPath,
+ ...payload,
+ },
+ },
+ update: updateGroupPackageSettings(this.groupPath),
+ optimisticResponse: updateGroupPackagesSettingsOptimisticResponse({
+ ...this.packageSettings,
+ ...payload,
+ }),
+ })
+ .then(({ data }) => {
+ if (data.updateNamespacePackageSettings?.errors?.length > 0) {
+ this.alertMessage = ERROR_UPDATING_SETTINGS;
+ } else {
+ this.dismissAlert();
+ this.$toast.show(SUCCESS_UPDATING_SETTINGS, { type: 'success' });
+ }
+ })
+ .catch((e) => {
+ if (e.graphQLErrors) {
+ e.graphQLErrors.forEach((error) => {
+ const [
+ {
+ path: [key],
+ message,
+ },
+ ] = error.extensions.problems;
+ this.errors = { ...this.errors, [key]: message };
+ });
+ }
+ this.alertMessage = ERROR_UPDATING_SETTINGS;
+ });
+ },
+ },
};
</script>
<template>
- <section></section>
+ <div>
+ <gl-alert v-if="alertMessage" variant="warning" class="gl-mt-4" @dismiss="dismissAlert">
+ {{ alertMessage }}
+ </gl-alert>
+
+ <settings-block :default-expanded="defaultExpanded">
+ <template #title> {{ $options.i18n.PACKAGE_SETTINGS_HEADER }}</template>
+ <template #description>
+ <span data-testid="description">
+ <gl-sprintf :message="$options.i18n.PACKAGE_SETTINGS_DESCRIPTION">
+ <template #link="{ content }">
+ <gl-link :href="$options.links.PACKAGES_DOCS_PATH" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ <template #default>
+ <maven-settings
+ :maven-duplicates-allowed="packageSettings.mavenDuplicatesAllowed"
+ :maven-duplicate-exception-regex="packageSettings.mavenDuplicateExceptionRegex"
+ :maven-duplicate-exception-regex-error="errors.mavenDuplicateExceptionRegex"
+ :loading="isLoading"
+ @update="updateSettings"
+ />
+ </template>
+ </settings-block>
+ </div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue
new file mode 100644
index 00000000000..aa7c6e9d8d6
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue
@@ -0,0 +1,113 @@
+<script>
+import { GlSprintf, GlToggle, GlFormGroup, GlFormInput } from '@gitlab/ui';
+
+import {
+ MAVEN_TITLE,
+ MAVEN_SETTINGS_SUBTITLE,
+ MAVEN_DUPLICATES_ALLOWED_DISABLED,
+ MAVEN_DUPLICATES_ALLOWED_ENABLED,
+ MAVEN_SETTING_EXCEPTION_TITLE,
+ MAVEN_SETTINGS_EXCEPTION_LEGEND,
+ MAVEN_DUPLICATES_ALLOWED,
+ MAVEN_DUPLICATE_EXCEPTION_REGEX,
+} from '~/packages_and_registries/settings/group/constants';
+
+export default {
+ name: 'MavenSettings',
+ i18n: {
+ MAVEN_TITLE,
+ MAVEN_SETTINGS_SUBTITLE,
+ MAVEN_SETTING_EXCEPTION_TITLE,
+ MAVEN_SETTINGS_EXCEPTION_LEGEND,
+ },
+ modelNames: {
+ MAVEN_DUPLICATES_ALLOWED,
+ MAVEN_DUPLICATE_EXCEPTION_REGEX,
+ },
+ components: {
+ GlSprintf,
+ GlToggle,
+ GlFormGroup,
+ GlFormInput,
+ },
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ mavenDuplicatesAllowed: {
+ type: Boolean,
+ default: false,
+ required: true,
+ },
+ mavenDuplicateExceptionRegex: {
+ type: String,
+ default: '',
+ required: true,
+ },
+ mavenDuplicateExceptionRegexError: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ },
+ computed: {
+ enabledButtonLabel() {
+ return this.mavenDuplicatesAllowed
+ ? MAVEN_DUPLICATES_ALLOWED_ENABLED
+ : MAVEN_DUPLICATES_ALLOWED_DISABLED;
+ },
+ isMavenDuplicateExceptionRegexValid() {
+ return !this.mavenDuplicateExceptionRegexError;
+ },
+ },
+ methods: {
+ update(type, value) {
+ this.$emit('update', { [type]: value });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h5 class="gl-border-b-solid gl-border-b-1 gl-border-gray-200">
+ {{ $options.i18n.MAVEN_TITLE }}
+ </h5>
+ <p>{{ $options.i18n.MAVEN_SETTINGS_SUBTITLE }}</p>
+ <form>
+ <div class="gl-display-flex">
+ <gl-toggle
+ :value="mavenDuplicatesAllowed"
+ @change="update($options.modelNames.MAVEN_DUPLICATES_ALLOWED, $event)"
+ />
+ <div class="gl-ml-5">
+ <div data-testid="toggle-label">
+ <gl-sprintf :message="enabledButtonLabel">
+ <template #bold="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ </div>
+ <gl-form-group
+ v-if="!mavenDuplicatesAllowed"
+ class="gl-mt-4"
+ :label="$options.i18n.MAVEN_SETTING_EXCEPTION_TITLE"
+ label-size="sm"
+ :state="isMavenDuplicateExceptionRegexValid"
+ :invalid-feedback="mavenDuplicateExceptionRegexError"
+ :description="$options.i18n.MAVEN_SETTINGS_EXCEPTION_LEGEND"
+ label-for="maven-duplicated-settings-regex-input"
+ >
+ <gl-form-input
+ id="maven-duplicated-settings-regex-input"
+ :value="mavenDuplicateExceptionRegex"
+ @change="update($options.modelNames.MAVEN_DUPLICATE_EXCEPTION_REGEX, $event)"
+ />
+ </gl-form-group>
+ </div>
+ </div>
+ </form>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/constants.js b/app/assets/javascripts/packages_and_registries/settings/group/constants.js
new file mode 100644
index 00000000000..72bec74060c
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/constants.js
@@ -0,0 +1,31 @@
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__, __ } from '~/locale';
+
+export const PACKAGE_SETTINGS_HEADER = s__('PackageRegistry|Package Registry');
+export const PACKAGE_SETTINGS_DESCRIPTION = s__(
+ 'PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}',
+);
+
+export const MAVEN_TITLE = s__('PackageRegistry|Maven');
+export const MAVEN_SETTINGS_SUBTITLE = s__('PackageRegistry|Settings for Maven packages');
+export const MAVEN_DUPLICATES_ALLOWED_DISABLED = s__(
+ 'PackageRegistry|%{boldStart}Do not allow duplicates%{boldEnd} - Packages with the same name and version are rejected.',
+);
+export const MAVEN_DUPLICATES_ALLOWED_ENABLED = s__(
+ 'PackageRegistry|%{boldStart}Allow duplicates%{boldEnd} - Packages with the same name and version are accepted.',
+);
+export const MAVEN_SETTING_EXCEPTION_TITLE = __('Exceptions');
+export const MAVEN_SETTINGS_EXCEPTION_LEGEND = s__(
+ 'PackageRegistry|Packages can be published if their name or version matches this regex',
+);
+
+export const SUCCESS_UPDATING_SETTINGS = s__('PackageRegistry|Settings saved successfully');
+export const ERROR_UPDATING_SETTINGS = s__(
+ 'PackageRegistry|An error occurred while saving the settings',
+);
+
+// Parameters
+
+export const PACKAGES_DOCS_PATH = helpPagePath('user/packages');
+export const MAVEN_DUPLICATES_ALLOWED = 'mavenDuplicatesAllowed';
+export const MAVEN_DUPLICATE_EXCEPTION_REGEX = 'mavenDuplicateExceptionRegex';
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql b/app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql
new file mode 100644
index 00000000000..1fc59bd3496
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql
@@ -0,0 +1,9 @@
+mutation updateNamespacePackageSettings($input: UpdateNamespacePackageSettingsInput!) {
+ updateNamespacePackageSettings(input: $input) {
+ packageSettings {
+ mavenDuplicatesAllowed
+ mavenDuplicateExceptionRegex
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql b/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql
new file mode 100644
index 00000000000..2011659887d
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql
@@ -0,0 +1,8 @@
+query getGroupPackagesSettings($fullPath: ID!) {
+ group(fullPath: $fullPath) {
+ packageSettings {
+ mavenDuplicatesAllowed
+ mavenDuplicateExceptionRegex
+ }
+ }
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js
new file mode 100644
index 00000000000..06b57fe013f
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js
@@ -0,0 +1,22 @@
+import { produce } from 'immer';
+import getGroupPackagesSettingsQuery from '../queries/get_group_packages_settings.query.graphql';
+
+export const updateGroupPackageSettings = (fullPath) => (client, { data: updatedData }) => {
+ const queryAndParams = {
+ query: getGroupPackagesSettingsQuery,
+ variables: { fullPath },
+ };
+ const sourceData = client.readQuery(queryAndParams);
+
+ const data = produce(sourceData, (draftState) => {
+ // eslint-disable-next-line no-param-reassign
+ draftState.group.packageSettings = {
+ ...updatedData.updateNamespacePackageSettings.packageSettings,
+ };
+ });
+
+ client.writeQuery({
+ ...queryAndParams,
+ data,
+ });
+};
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js
new file mode 100644
index 00000000000..f2c8de85bf8
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js
@@ -0,0 +1,11 @@
+export const updateGroupPackagesSettingsOptimisticResponse = (changes) => ({
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ __typename: 'Mutation',
+ updateNamespacePackageSettings: {
+ __typename: 'UpdateNamespacePackageSettingsPayload',
+ errors: [],
+ packageSettings: {
+ ...changes,
+ },
+ },
+});
diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
index f9a91ec322b..f78d2b0dbd3 100644
--- a/app/assets/javascripts/pager.js
+++ b/app/assets/javascripts/pager.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import 'vendor/jquery.endless-scroll';
-import { getParameterByName } from '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
+import { getParameterByName } from '~/lib/utils/common_utils';
import { removeParams } from '~/lib/utils/url_utility';
const ENDLESS_SCROLL_BOTTOM_PX = 400;
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js b/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
index da7f81759ea..e78b3f9ec95 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import { truncate } from '../../../lib/utils/text_utility';
import { parseBoolean } from '~/lib/utils/common_utils';
+import { truncate } from '../../../lib/utils/text_utility';
const MAX_MESSAGE_LENGTH = 500;
const MESSAGE_CELL_SELECTOR = '.abuse-reports .message';
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/index.js b/app/assets/javascripts/pages/admin/abuse_reports/index.js
index d97e24d9e0b..5649c47d7e8 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/index.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/index.js
@@ -1,6 +1,6 @@
/* eslint-disable no-new */
-import AbuseReports from './abuse_reports';
import UsersSelect from '~/users_select';
+import AbuseReports from './abuse_reports';
document.addEventListener('DOMContentLoaded', () => {
new AbuseReports();
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/index.js b/app/assets/javascripts/pages/admin/application_settings/general/index.js
index af1595398a8..f7bd32880ff 100644
--- a/app/assets/javascripts/pages/admin/application_settings/general/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/general/index.js
@@ -1,6 +1,10 @@
+// This is a true violation of @gitlab/no-runtime-template-compiler, as it
+// relies on app/views/admin/application_settings/_gitpod.html.haml for its
+// template.
+/* eslint-disable @gitlab/no-runtime-template-compiler */
import Vue from 'vue';
-import initUserInternalRegexPlaceholder from '../account_and_limits';
import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
+import initUserInternalRegexPlaceholder from '../account_and_limits';
document.addEventListener('DOMContentLoaded', () => {
initUserInternalRegexPlaceholder();
diff --git a/app/assets/javascripts/pages/admin/application_settings/index.js b/app/assets/javascripts/pages/admin/application_settings/index.js
index cce30e6b12a..e7e74588bec 100644
--- a/app/assets/javascripts/pages/admin/application_settings/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/index.js
@@ -1,7 +1,8 @@
-import initSettingsPanels from '~/settings_panels';
+import initVariableList from '~/ci_variable_list';
import projectSelect from '~/project_select';
+import initSearchSettings from '~/search_settings';
import selfMonitor from '~/self_monitor';
-import initVariableList from '~/ci_variable_list';
+import initSettingsPanels from '~/settings_panels';
document.addEventListener('DOMContentLoaded', () => {
if (gon.features?.ciInstanceVariablesUi) {
@@ -11,4 +12,5 @@ document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
initSettingsPanels();
projectSelect();
+ initSearchSettings();
});
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 b995cb1d3dd..bc1d4dd6122 100644
--- a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
@@ -1,6 +1,6 @@
+import { deprecatedCreateFlash as flash } from '../../../flash';
import axios from '../../../lib/utils/axios_utils';
import { __ } from '../../../locale';
-import { deprecatedCreateFlash as flash } from '../../../flash';
export default class PayloadPreviewer {
constructor(trigger) {
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
index 9e4c4d9f615..5a16716fe2d 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
import { debounce } from 'lodash';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
-import { __ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
import { textColorForBackground } from '~/lib/utils/color_utils';
+import { __ } from '~/locale';
export default () => {
const $broadcastMessageColor = $('.js-broadcast-message-color');
diff --git a/app/assets/javascripts/pages/admin/clusters/index/index.js b/app/assets/javascripts/pages/admin/clusters/index/index.js
index 744be65bfbe..a99e0dfa4f0 100644
--- a/app/assets/javascripts/pages/admin/clusters/index/index.js
+++ b/app/assets/javascripts/pages/admin/clusters/index/index.js
@@ -1,5 +1,5 @@
-import PersistentUserCallout from '~/persistent_user_callout';
import initClustersListApp from '~/clusters_list';
+import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.gcp-signup-offer');
diff --git a/app/assets/javascripts/pages/admin/clusters/show/index.js b/app/assets/javascripts/pages/admin/clusters/show/index.js
index f87da6c7074..9d94973af0d 100644
--- a/app/assets/javascripts/pages/admin/clusters/show/index.js
+++ b/app/assets/javascripts/pages/admin/clusters/show/index.js
@@ -1,6 +1,6 @@
import ClustersBundle from '~/clusters/clusters_bundle';
-import initClusterHealth from '~/pages/projects/clusters/show/cluster_health';
import initIntegrationForm from '~/clusters/forms/show';
+import initClusterHealth from '~/pages/projects/clusters/show/cluster_health';
document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/admin/cohorts/index.js b/app/assets/javascripts/pages/admin/cohorts/index.js
deleted file mode 100644
index 1cc54df15a1..00000000000
--- a/app/assets/javascripts/pages/admin/cohorts/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import Vue from 'vue';
-import UsagePingDisabled from '~/admin/cohorts/components/usage_ping_disabled.vue';
-
-document.addEventListener('DOMContentLoaded', () => {
- const emptyStateContainer = document.getElementById('js-cohorts-empty-state');
-
- if (!emptyStateContainer) return false;
-
- const { emptyStateSvgPath, enableUsagePingLink, docsLink } = emptyStateContainer.dataset;
-
- return new Vue({
- el: emptyStateContainer,
- provide: {
- svgPath: emptyStateSvgPath,
- primaryButtonPath: enableUsagePingLink,
- docsLink,
- },
- render(h) {
- return h(UsagePingDisabled);
- },
- });
-});
diff --git a/app/assets/javascripts/pages/admin/groups/new/index.js b/app/assets/javascripts/pages/admin/groups/new/index.js
index b94c999ed12..94f7cfd55be 100644
--- a/app/assets/javascripts/pages/admin/groups/new/index.js
+++ b/app/assets/javascripts/pages/admin/groups/new/index.js
@@ -1,6 +1,6 @@
+import initFilePickers from '~/file_pickers';
import BindInOut from '../../../../behaviors/bind_in_out';
import Group from '../../../../group';
-import initFilePickers from '~/file_pickers';
document.addEventListener('DOMContentLoaded', () => {
BindInOut.initAll();
diff --git a/app/assets/javascripts/pages/admin/index.js b/app/assets/javascripts/pages/admin/index.js
index 3f4e658fc8d..792a6eda14e 100644
--- a/app/assets/javascripts/pages/admin/index.js
+++ b/app/assets/javascripts/pages/admin/index.js
@@ -1,6 +1,6 @@
-import initAdmin from './admin';
import initAdminStatisticsPanel from '../../admin/statistics_panel/index';
import initVueAlerts from '../../vue_alerts';
+import initAdmin from './admin';
document.addEventListener('DOMContentLoaded', initVueAlerts);
diff --git a/app/assets/javascripts/pages/admin/integrations/edit/index.js b/app/assets/javascripts/pages/admin/integrations/edit/index.js
index 2d77f2686f7..ba4b271f09e 100644
--- a/app/assets/javascripts/pages/admin/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/admin/integrations/edit/index.js
@@ -1,6 +1,5 @@
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
@@ -11,6 +10,4 @@ document.addEventListener('DOMContentLoaded', () => {
const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
prometheusMetrics.loadActiveMetrics();
}
-
- initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
index d65593963ce..798eeee48bf 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
+++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlModal } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js
index 4df210debb5..46ddb95299d 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/index.js
+++ b/app/assets/javascripts/pages/admin/jobs/index/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
import stopJobsModal from './components/stop_jobs_modal.vue';
@@ -18,7 +19,7 @@ document.addEventListener('DOMContentLoaded', () => {
mounted() {
stopJobsButton.classList.remove('disabled');
stopJobsButton.addEventListener('click', () => {
- this.$root.$emit('bv::show::modal', modalId, `#${buttonId}`);
+ this.$root.$emit(BV_SHOW_MODAL, modalId, `#${buttonId}`);
});
},
render(createElement) {
diff --git a/app/assets/javascripts/pages/admin/projects/index.js b/app/assets/javascripts/pages/admin/projects/index.js
index fa2b0546c02..2286a085143 100644
--- a/app/assets/javascripts/pages/admin/projects/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import ProjectsList from '~/projects_list';
import NamespaceSelect from '~/namespace_select';
+import ProjectsList from '~/projects_list';
import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
function mountRemoveMemberModal() {
diff --git a/app/assets/javascripts/pages/admin/projects/index/index.js b/app/assets/javascripts/pages/admin/projects/index/index.js
index bf512ef395d..1971323abac 100644
--- a/app/assets/javascripts/pages/admin/projects/index/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index/index.js
@@ -1,7 +1,8 @@
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import csrf from '~/lib/utils/csrf';
+import Translate from '~/vue_shared/translate';
import deleteProjectModal from './components/delete_project_modal.vue';
@@ -24,7 +25,7 @@ document.addEventListener('DOMContentLoaded', () => {
deleteModal.deleteProjectUrl = buttonProps.deleteProjectUrl;
deleteModal.projectName = buttonProps.projectName;
- this.$root.$emit('bv::show::modal', 'delete-project-modal');
+ this.$root.$emit(BV_SHOW_MODAL, 'delete-project-modal');
});
});
},
diff --git a/app/assets/javascripts/pages/admin/runners/index.js b/app/assets/javascripts/pages/admin/runners/index.js
index e60c6133c7c..f07ac1d8674 100644
--- a/app/assets/javascripts/pages/admin/runners/index.js
+++ b/app/assets/javascripts/pages/admin/runners/index.js
@@ -1,6 +1,7 @@
-import initFilteredSearch from '~/pages/search/init_filtered_search';
import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
@@ -8,4 +9,6 @@ document.addEventListener('DOMContentLoaded', () => {
filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
useDefaultState: true,
});
+
+ initInstallRunner();
});
diff --git a/app/assets/javascripts/pages/admin/services/edit/index.js b/app/assets/javascripts/pages/admin/services/edit/index.js
index e5e80d2f566..3d692ef4dcc 100644
--- a/app/assets/javascripts/pages/admin/services/edit/index.js
+++ b/app/assets/javascripts/pages/admin/services/edit/index.js
@@ -1,9 +1,6 @@
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
-import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
integrationSettingsForm.init();
-
- initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index 9c303cc6445..d2b83f980d7 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -85,38 +85,36 @@ export default {
<template>
<gl-modal ref="modal" modal-id="delete-user-modal" :title="modalTitle" kind="danger">
- <template>
- <p>
- <gl-sprintf :message="content">
- <template #username>
- <strong>{{ username }}</strong>
- </template>
- <template #strong="props">
- <strong>{{ props.content }}</strong>
- </template>
- </gl-sprintf>
- </p>
+ <p>
+ <gl-sprintf :message="content">
+ <template #username>
+ <strong>{{ username }}</strong>
+ </template>
+ <template #strong="props">
+ <strong>{{ props.content }}</strong>
+ </template>
+ </gl-sprintf>
+ </p>
- <p>
- <gl-sprintf :message="s__('AdminUsers|To confirm, type %{username}')">
- <template #username>
- <code>{{ username }}</code>
- </template>
- </gl-sprintf>
- </p>
+ <p>
+ <gl-sprintf :message="s__('AdminUsers|To confirm, type %{username}')">
+ <template #username>
+ <code>{{ username }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
- <form ref="form" :action="deleteUserUrl" method="post" @submit.prevent>
- <input ref="method" type="hidden" name="_method" value="delete" />
- <input :value="csrfToken" type="hidden" name="authenticity_token" />
- <gl-form-input
- v-model="enteredUsername"
- autofocus
- type="text"
- name="username"
- autocomplete="off"
- />
- </form>
- </template>
+ <form ref="form" :action="deleteUserUrl" method="post" @submit.prevent>
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
+ <gl-form-input
+ v-model="enteredUsername"
+ autofocus
+ type="text"
+ name="username"
+ autocomplete="off"
+ />
+ </form>
<template #modal-footer>
<gl-button @click="onCancel">{{ s__('Cancel') }}</gl-button>
<gl-button
diff --git a/app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue b/app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue
index 24c9fa4cb3f..1dfea3f1e7b 100644
--- a/app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue
+++ b/app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue
@@ -12,6 +12,10 @@ export default {
required: true,
type: String,
},
+ selector: {
+ required: true,
+ type: String,
+ },
},
data() {
return {
@@ -34,22 +38,24 @@ export default {
},
mounted() {
- document.addEventListener('click', this.handleClick);
- },
+ /*
+ * Here we're looking for every button that needs to launch a modal
+ * on click, and then attaching a click event handler to show the modal
+ * if it's correctly configured.
+ *
+ * TODO: Replace this with integrated modal components https://gitlab.com/gitlab-org/gitlab/-/issues/320922
+ */
+ document.querySelectorAll(this.selector).forEach((button) => {
+ button.addEventListener('click', (e) => {
+ if (!button.dataset.glModalAction) return;
- beforeDestroy() {
- document.removeEventListener('click', this.handleClick);
+ e.preventDefault();
+ this.show(button.dataset);
+ });
+ });
},
methods: {
- handleClick(e) {
- const { glModalAction: action } = e.target.dataset;
- if (!action) return;
-
- this.show(e.target.dataset);
- e.preventDefault();
- },
-
show(modalData) {
const { glModalAction: requestedAction } = modalData;
diff --git a/app/assets/javascripts/pages/admin/users/index.js b/app/assets/javascripts/pages/admin/users/index.js
index 75a8284f5f8..b1079c3b068 100644
--- a/app/assets/javascripts/pages/admin/users/index.js
+++ b/app/assets/javascripts/pages/admin/users/index.js
@@ -1,11 +1,13 @@
import Vue from 'vue';
+import { initAdminUsersApp, initCohortsEmptyState } from '~/admin/users';
+import initTabs from '~/admin/users/tabs';
+import initConfirmModal from '~/confirm_modal';
+import csrf from '~/lib/utils/csrf';
import Translate from '~/vue_shared/translate';
import ModalManager from './components/user_modal_manager.vue';
-import csrf from '~/lib/utils/csrf';
-import initConfirmModal from '~/confirm_modal';
-import initAdminUsersApp from '~/admin/users';
+const CONFIRM_DELETE_BUTTON_SELECTOR = '.js-delete-user-modal-button';
const MODAL_TEXTS_CONTAINER_SELECTOR = '#js-modal-texts';
const MODAL_MANAGER_SELECTOR = '#js-delete-user-modal';
@@ -32,6 +34,8 @@ function loadModalsConfigurationFromHtml(modalsElement) {
document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate);
+ initAdminUsersApp();
+
const modalConfiguration = loadModalsConfigurationFromHtml(
document.querySelector(MODAL_TEXTS_CONTAINER_SELECTOR),
);
@@ -49,6 +53,7 @@ document.addEventListener('DOMContentLoaded', () => {
return h(ModalManager, {
ref: 'manager',
props: {
+ selector: CONFIRM_DELETE_BUTTON_SELECTOR,
modalConfiguration,
csrfToken: csrf.token,
},
@@ -57,5 +62,6 @@ document.addEventListener('DOMContentLoaded', () => {
});
initConfirmModal();
- initAdminUsersApp();
+ initCohortsEmptyState();
+ initTabs();
});
diff --git a/app/assets/javascripts/pages/dashboard/issues/index.js b/app/assets/javascripts/pages/dashboard/issues/index.js
index 71cdaf45052..3ad95fb1318 100644
--- a/app/assets/javascripts/pages/dashboard/issues/index.js
+++ b/app/assets/javascripts/pages/dashboard/issues/index.js
@@ -1,8 +1,8 @@
-import projectSelect from '~/project_select';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import { FILTERED_SEARCH } from '~/pages/constants';
import initManualOrdering from '~/manual_ordering';
+import { FILTERED_SEARCH } from '~/pages/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import projectSelect from '~/project_select';
document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index 7adae2cdb05..b099165e3f5 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -1,8 +1,8 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
-import projectSelect from '~/project_select';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import projectSelect from '~/project_select';
document.addEventListener('DOMContentLoaded', () => {
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys, true);
diff --git a/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue b/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue
index bed753b0c40..d17c37e9e1a 100644
--- a/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue
+++ b/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue
@@ -1,7 +1,7 @@
<script>
import { GlBanner } from '@gitlab/ui';
-import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { s__ } from '~/locale';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index bd283201eff..d53cd405504 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -2,13 +2,13 @@
import $ from 'jquery';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { visitUrl } from '~/lib/utils/url_utility';
-import UsersSelect from '~/users_select';
+import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { isMetaClick } from '~/lib/utils/common_utils';
import { addDelimiter } from '~/lib/utils/text_utility';
+import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import { deprecatedCreateFlash as flash } from '~/flash';
-import axios from '~/lib/utils/axios_utils';
+import UsersSelect from '~/users_select';
export default class Todos {
constructor() {
diff --git a/app/assets/javascripts/pages/groups/boards/index.js b/app/assets/javascripts/pages/groups/boards/index.js
index 922f39627c9..bde0007ec6a 100644
--- a/app/assets/javascripts/pages/groups/boards/index.js
+++ b/app/assets/javascripts/pages/groups/boards/index.js
@@ -1,6 +1,6 @@
-import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import initBoards from '~/boards';
+import UsersSelect from '~/users_select';
new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/groups/clusters/index.js b/app/assets/javascripts/pages/groups/clusters/index.js
index 9f466e0d60a..d5ce5d076a2 100644
--- a/app/assets/javascripts/pages/groups/clusters/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/index.js
@@ -1,5 +1,5 @@
-import initCreateCluster from '~/create_cluster/init_create_cluster';
import initIntegrationForm from '~/clusters/forms/show/index';
+import initCreateCluster from '~/create_cluster/init_create_cluster';
document.addEventListener('DOMContentLoaded', () => {
initCreateCluster(document, gon);
diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js
index 744be65bfbe..a99e0dfa4f0 100644
--- a/app/assets/javascripts/pages/groups/clusters/index/index.js
+++ b/app/assets/javascripts/pages/groups/clusters/index/index.js
@@ -1,5 +1,5 @@
-import PersistentUserCallout from '~/persistent_user_callout';
import initClustersListApp from '~/clusters_list';
+import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.gcp-signup-offer');
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 33e552cd1ba..95ee512b71a 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -1,13 +1,13 @@
-import initFilePickers from '~/file_pickers';
-import TransferDropdown from '~/groups/transfer_dropdown';
+import { GROUP_BADGE } from '~/badges/constants';
import initConfirmDangerModal from '~/confirm_danger_modal';
-import initSettingsPanels from '~/settings_panels';
-import setupTransferEdit from '~/transfer_edit';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
-import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
-import { GROUP_BADGE } from '~/badges/constants';
+import initFilePickers from '~/file_pickers';
+import TransferDropdown from '~/groups/transfer_dropdown';
import groupsSelect from '~/groups_select';
+import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import projectSelect from '~/project_select';
+import initSettingsPanels from '~/settings_panels';
+import setupTransferEdit from '~/transfer_edit';
document.addEventListener('DOMContentLoaded', () => {
initFilePickers();
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index 5346e3720e8..3496f699b06 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -1,13 +1,14 @@
import Vue from 'vue';
-import memberExpirationDate from '~/member_expiration_date';
-import UsersSelect from '~/users_select';
+import { groupMemberRequestFormatter } from '~/groups/members/utils';
import groupsSelect from '~/groups_select';
-import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
-import { initGroupMembersApp } from '~/groups/members';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
-import { memberRequestFormatter, groupLinkRequestFormatter } from '~/groups/members/utils';
import { s__ } from '~/locale';
+import memberExpirationDate from '~/member_expiration_date';
+import { initMembersApp } from '~/members/index';
+import { groupLinkRequestFormatter } from '~/members/utils';
+import UsersSelect from '~/users_select';
+import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
function mountRemoveMemberModal() {
const el = document.querySelector('.js-remove-member-modal');
@@ -25,11 +26,11 @@ function mountRemoveMemberModal() {
const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
-initGroupMembersApp(document.querySelector('.js-group-members-list'), {
+initMembersApp(document.querySelector('.js-group-members-list'), {
tableFields: SHARED_FIELDS.concat(['source', 'granted']),
tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
- requestFormatter: memberRequestFormatter,
+ requestFormatter: groupMemberRequestFormatter,
filteredSearchBar: {
show: true,
tokens: ['two_factor', 'with_inherited_permissions'],
@@ -38,7 +39,8 @@ initGroupMembersApp(document.querySelector('.js-group-members-list'), {
recentSearchesStorageKey: 'group_members',
},
});
-initGroupMembersApp(document.querySelector('.js-group-linked-list'), {
+
+initMembersApp(document.querySelector('.js-group-group-links-list'), {
tableFields: SHARED_FIELDS.concat('granted'),
tableAttrs: {
table: { 'data-qa-selector': 'groups_list' },
@@ -46,9 +48,9 @@ initGroupMembersApp(document.querySelector('.js-group-linked-list'), {
},
requestFormatter: groupLinkRequestFormatter,
});
-initGroupMembersApp(document.querySelector('.js-group-invited-members-list'), {
+initMembersApp(document.querySelector('.js-group-invited-members-list'), {
tableFields: SHARED_FIELDS.concat('invited'),
- requestFormatter: memberRequestFormatter,
+ requestFormatter: groupMemberRequestFormatter,
filteredSearchBar: {
show: true,
tokens: [],
@@ -57,9 +59,9 @@ initGroupMembersApp(document.querySelector('.js-group-invited-members-list'), {
recentSearchesStorageKey: 'group_invited_members',
},
});
-initGroupMembersApp(document.querySelector('.js-group-access-requests-list'), {
+initMembersApp(document.querySelector('.js-group-access-requests-list'), {
tableFields: SHARED_FIELDS.concat('requested'),
- requestFormatter: memberRequestFormatter,
+ requestFormatter: groupMemberRequestFormatter,
});
groupsSelect();
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index 5cb21ca61ab..b60607e8857 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -1,10 +1,10 @@
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import initIssuablesList from '~/issues_list';
-import projectSelect from '~/project_select';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
-import { FILTERED_SEARCH } from '~/pages/constants';
+import initIssuablesList from '~/issues_list';
import initManualOrdering from '~/manual_ordering';
+import { FILTERED_SEARCH } from '~/pages/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import projectSelect from '~/project_select';
const ISSUE_BULK_UPDATE_PREFIX = 'issue_';
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index 2832cbed5ac..2f6f9bb16e1 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -1,9 +1,9 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
-import projectSelect from '~/project_select';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
-import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/pages/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import projectSelect from '~/project_select';
const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_';
diff --git a/app/assets/javascripts/pages/groups/milestones/show/index.js b/app/assets/javascripts/pages/groups/milestones/show/index.js
index ebaea5ef3dc..3094fe5cd21 100644
--- a/app/assets/javascripts/pages/groups/milestones/show/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/show/index.js
@@ -1,7 +1,6 @@
-import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
-import initDeleteMilestoneModal from '~/pages/milestones/shared/delete_milestone_modal_init';
-
import Milestone from '~/milestone';
+import initDeleteMilestoneModal from '~/pages/milestones/shared/delete_milestone_modal_init';
+import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
document.addEventListener('DOMContentLoaded', () => {
initMilestonesShow();
diff --git a/app/assets/javascripts/pages/groups/new/group_path_validator.js b/app/assets/javascripts/pages/groups/new/group_path_validator.js
index 97f3d8cf7f5..89dccea2812 100644
--- a/app/assets/javascripts/pages/groups/new/group_path_validator.js
+++ b/app/assets/javascripts/pages/groups/new/group_path_validator.js
@@ -1,9 +1,9 @@
import { debounce } from 'lodash';
-import InputValidator from '~/validators/input_validator';
-import fetchGroupPathAvailability from './fetch_group_path_availability';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __ } from '~/locale';
+import InputValidator from '~/validators/input_validator';
+import fetchGroupPathAvailability from './fetch_group_path_availability';
const debounceTimeoutDuration = 1000;
const invalidInputClass = 'gl-field-error-outline';
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 7021473b380..63515abe698 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import BindInOut from '~/behaviors/bind_in_out';
+import initFilePickers from '~/file_pickers';
import Group from '~/group';
import GroupPathValidator from './group_path_validator';
-import initFilePickers from '~/file_pickers';
const parentId = $('#group_parent_id');
if (!parentId.val()) {
diff --git a/app/assets/javascripts/pages/groups/settings/badges/index.js b/app/assets/javascripts/pages/groups/settings/badges/index.js
index 74e96ee4a8f..3f48e4f281e 100644
--- a/app/assets/javascripts/pages/groups/settings/badges/index.js
+++ b/app/assets/javascripts/pages/groups/settings/badges/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
import { GROUP_BADGE } from '~/badges/constants';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
+import Translate from '~/vue_shared/translate';
Vue.use(Translate);
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index e8d8c985ade..378b8663777 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -1,9 +1,10 @@
-import initSettingsPanels from '~/settings_panels';
import initVariableList from '~/ci_variable_list';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners_filtered_search_token_keys';
-import { FILTERED_SEARCH } from '~/pages/constants';
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
+import { FILTERED_SEARCH } from '~/pages/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
+import initSettingsPanels from '~/settings_panels';
document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
@@ -18,4 +19,6 @@ document.addEventListener('DOMContentLoaded', () => {
initSharedRunnersForm();
initVariableList();
+
+ initInstallRunner();
});
diff --git a/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js b/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
index 2d77f2686f7..ba4b271f09e 100644
--- a/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
@@ -1,6 +1,5 @@
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
@@ -11,6 +10,4 @@ document.addEventListener('DOMContentLoaded', () => {
const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
prometheusMetrics.loadActiveMetrics();
}
-
- initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
diff --git a/app/assets/javascripts/pages/groups/settings/repository/show/index.js b/app/assets/javascripts/pages/groups/settings/repository/show/index.js
index f4b26ba81fe..a1bcf6dbf57 100644
--- a/app/assets/javascripts/pages/groups/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/repository/show/index.js
@@ -1,5 +1,5 @@
-import initSettingsPanels from '~/settings_panels';
import DueDateSelectors from '~/due_date_select';
+import initSettingsPanels from '~/settings_panels';
document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
diff --git a/app/assets/javascripts/pages/groups/shared/group_details.js b/app/assets/javascripts/pages/groups/shared/group_details.js
index 8d956c694c0..8c272e561db 100644
--- a/app/assets/javascripts/pages/groups/shared/group_details.js
+++ b/app/assets/javascripts/pages/groups/shared/group_details.js
@@ -1,13 +1,16 @@
/* eslint-disable no-new */
-import { getPagePath, getDashPath } from '~/lib/utils/common_utils';
+import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants';
+import initInviteMembersBanner from '~/groups/init_invite_members_banner';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
+import { getPagePath, getDashPath } from '~/lib/utils/common_utils';
+import initNotificationsDropdown from '~/notifications';
import notificationsDropdown from '~/notifications_dropdown';
import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list';
-import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GroupTabs from './group_tabs';
-import initInviteMembersBanner from '~/groups/init_invite_members_banner';
export default function initGroupDetails(actionName = 'show') {
const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED];
@@ -20,8 +23,16 @@ export default function initGroupDetails(actionName = 'show') {
new GroupTabs({ parentEl: '.groups-listing', action });
new ShortcutsNavigation();
new NotificationsForm();
- notificationsDropdown();
+
+ if (gon.features?.vueNotificationDropdown) {
+ initNotificationsDropdown();
+ } else {
+ notificationsDropdown();
+ }
+
new ProjectsList();
initInviteMembersBanner();
+ initInviteMembersModal();
+ initInviteMembersTrigger();
}
diff --git a/app/assets/javascripts/pages/groups/shared/group_tabs.js b/app/assets/javascripts/pages/groups/shared/group_tabs.js
index 033843d8504..73d810007dc 100644
--- a/app/assets/javascripts/pages/groups/shared/group_tabs.js
+++ b/app/assets/javascripts/pages/groups/shared/group_tabs.js
@@ -1,5 +1,4 @@
import $ from 'jquery';
-import { removeParams } from '~/lib/utils/url_utility';
import createGroupTree from '~/groups';
import {
ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
@@ -9,8 +8,9 @@ import {
GROUPS_LIST_HOLDER_CLASS,
GROUPS_FILTER_FORM_CLASS,
} from '~/groups/constants';
-import UserTabs from '~/pages/users/user_tabs';
import GroupFilterableList from '~/groups/groups_filterable_list';
+import { removeParams } from '~/lib/utils/url_utility';
+import UserTabs from '~/pages/users/user_tabs';
export default class GroupTabs extends UserTabs {
constructor({ defaultAction = 'subgroups_and_projects', action, parentEl }) {
diff --git a/app/assets/javascripts/pages/help/index/index.js b/app/assets/javascripts/pages/help/index/index.js
index 1bafe564a37..fd8c590eb4e 100644
--- a/app/assets/javascripts/pages/help/index/index.js
+++ b/app/assets/javascripts/pages/help/index/index.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import VersionCheckImage from '~/version_check_image';
import docs from '~/docs/docs_bundle';
+import VersionCheckImage from '~/version_check_image';
document.addEventListener('DOMContentLoaded', () => {
docs();
diff --git a/app/assets/javascripts/pages/import/bulk_imports/index.js b/app/assets/javascripts/pages/import/bulk_imports/status/index.js
index 37ac1a98466..37ac1a98466 100644
--- a/app/assets/javascripts/pages/import/bulk_imports/index.js
+++ b/app/assets/javascripts/pages/import/bulk_imports/status/index.js
diff --git a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
index f47945c5a9f..16f68b94c9a 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
@@ -1,10 +1,10 @@
<script>
import { GlSafeHtmlDirective as SafeHtml, GlModal } from '@gitlab/ui';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as Flash } from '~/flash';
-import { __, n__, s__, sprintf } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
+import { __, n__, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
index ecde11aff40..8d4997586dd 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
@@ -1,9 +1,9 @@
<script>
import { GlModal } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__, sprintf } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
+import { s__, sprintf } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js b/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
index e8b67891c42..3aeff2db2e0 100644
--- a/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
+++ b/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
import DeleteMilestoneModal from './components/delete_milestone_modal.vue';
import eventHub from './event_hub';
@@ -47,7 +48,7 @@ export default () => {
deleteMilestoneButtons.forEach((button) => {
button.removeAttribute('disabled');
button.addEventListener('click', () => {
- this.$root.$emit('bv::show::modal', 'delete-milestone-modal');
+ this.$root.$emit(BV_SHOW_MODAL, 'delete-milestone-modal');
eventHub.$once('deleteMilestoneModal.requestStarted', onRequestStarted);
this.setModalProps({
diff --git a/app/assets/javascripts/pages/oauth/index.js b/app/assets/javascripts/pages/oauth/index.js
new file mode 100644
index 00000000000..2a120a690ef
--- /dev/null
+++ b/app/assets/javascripts/pages/oauth/index.js
@@ -0,0 +1,3 @@
+import initSearchSettings from '~/search_settings';
+
+initSearchSettings();
diff --git a/app/assets/javascripts/pages/profiles/accounts/show/index.js b/app/assets/javascripts/pages/profiles/accounts/show/index.js
index 6c1e953aa83..5350ef61184 100644
--- a/app/assets/javascripts/pages/profiles/accounts/show/index.js
+++ b/app/assets/javascripts/pages/profiles/accounts/show/index.js
@@ -1,5 +1,5 @@
-import initProfileAccount from '~/profile/account';
import { initClose2faSuccessMessage } from '~/authentication/two_factor_auth';
+import initProfileAccount from '~/profile/account';
document.addEventListener('DOMContentLoaded', initProfileAccount);
diff --git a/app/assets/javascripts/pages/profiles/index.js b/app/assets/javascripts/pages/profiles/index.js
index d2b00d0ef45..535fe5fa4eb 100644
--- a/app/assets/javascripts/pages/profiles/index.js
+++ b/app/assets/javascripts/pages/profiles/index.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import '~/profile/gl_crop';
import Profile from '~/profile/profile';
+import initSearchSettings from '~/search_settings';
document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line func-names
@@ -17,4 +18,6 @@ document.addEventListener('DOMContentLoaded', () => {
});
new Profile(); // eslint-disable-line no-new
+
+ initSearchSettings();
});
diff --git a/app/assets/javascripts/pages/profiles/index/index.js b/app/assets/javascripts/pages/profiles/index/index.js
index 9bd430f4f11..586b3be8661 100644
--- a/app/assets/javascripts/pages/profiles/index/index.js
+++ b/app/assets/javascripts/pages/profiles/index/index.js
@@ -1,5 +1,5 @@
-import NotificationsForm from '../../../notifications_form';
import notificationsDropdown from '../../../notifications_dropdown';
+import NotificationsForm from '../../../notifications_form';
document.addEventListener('DOMContentLoaded', () => {
new NotificationsForm(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/profiles/notifications/show/index.js b/app/assets/javascripts/pages/profiles/notifications/show/index.js
index 2e24a10fa5c..639f5deb72c 100644
--- a/app/assets/javascripts/pages/profiles/notifications/show/index.js
+++ b/app/assets/javascripts/pages/profiles/notifications/show/index.js
@@ -1,7 +1,9 @@
-import NotificationsForm from '../../../../notifications_form';
+import initNotificationsDropdown from '~/notifications';
import notificationsDropdown from '../../../../notifications_dropdown';
+import NotificationsForm from '../../../../notifications_form';
document.addEventListener('DOMContentLoaded', () => {
new NotificationsForm(); // eslint-disable-line no-new
notificationsDropdown();
+ initNotificationsDropdown();
});
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index b78f24ca2fb..a24c6ca7754 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -1,10 +1,10 @@
+import emojiRegex from 'emoji-regex';
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
-import emojiRegex from 'emoji-regex';
+import * as Emoji from '~/emoji';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import EmojiMenu from './emoji_menu';
import { __ } from '~/locale';
-import * as Emoji from '~/emoji';
+import EmojiMenu from './emoji_menu';
const defaultStatusEmoji = 'speech_balloon';
diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
index 24dbc312dd2..186072531b8 100644
--- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
+++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
@@ -1,6 +1,6 @@
-import { parseBoolean } from '~/lib/utils/common_utils';
import { mount2faRegistration } from '~/authentication/mount_2fa';
import { initRecoveryCodes } from '~/authentication/two_factor_auth';
+import { parseBoolean } from '~/lib/utils/common_utils';
document.addEventListener('DOMContentLoaded', () => {
const twoFactorNode = document.querySelector('.js-two-factor-auth');
diff --git a/app/assets/javascripts/pages/projects/activity/index.js b/app/assets/javascripts/pages/projects/activity/index.js
index d39ea3d10bf..03fbad0f1ec 100644
--- a/app/assets/javascripts/pages/projects/activity/index.js
+++ b/app/assets/javascripts/pages/projects/activity/index.js
@@ -1,7 +1,5 @@
import Activities from '~/activities';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-document.addEventListener('DOMContentLoaded', () => {
- new Activities(); // eslint-disable-line no-new
- new ShortcutsNavigation(); // eslint-disable-line no-new
-});
+new Activities(); // eslint-disable-line no-new
+new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/alert_management/details/index.js b/app/assets/javascripts/pages/projects/alert_management/details/index.js
index a20f6713c9d..183e07ca1fc 100644
--- a/app/assets/javascripts/pages/projects/alert_management/details/index.js
+++ b/app/assets/javascripts/pages/projects/alert_management/details/index.js
@@ -1,3 +1,3 @@
-import AlertDetails from '~/alert_management/details';
+import AlertDetails from '~/vue_shared/alert_details';
AlertDetails('#js-alert_details');
diff --git a/app/assets/javascripts/pages/projects/artifacts/browse/index.js b/app/assets/javascripts/pages/projects/artifacts/browse/index.js
index 26dc90a56d7..58ba6a500a3 100644
--- a/app/assets/javascripts/pages/projects/artifacts/browse/index.js
+++ b/app/assets/javascripts/pages/projects/artifacts/browse/index.js
@@ -1,5 +1,5 @@
-import BuildArtifacts from '~/build_artifacts';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
+import BuildArtifacts from '~/build_artifacts';
document.addEventListener('DOMContentLoaded', () => {
new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/artifacts/file/index.js b/app/assets/javascripts/pages/projects/artifacts/file/index.js
index 249900d6cb7..eb5ecc27c43 100644
--- a/app/assets/javascripts/pages/projects/artifacts/file/index.js
+++ b/app/assets/javascripts/pages/projects/artifacts/file/index.js
@@ -1,5 +1,5 @@
-import BlobViewer from '~/blob/viewer/index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
+import BlobViewer from '~/blob/viewer/index';
document.addEventListener('DOMContentLoaded', () => {
new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/blame/show/index.js b/app/assets/javascripts/pages/projects/blame/show/index.js
index 80d0bff92fa..fa22c11d1d7 100644
--- a/app/assets/javascripts/pages/projects/blame/show/index.js
+++ b/app/assets/javascripts/pages/projects/blame/show/index.js
@@ -1,3 +1,3 @@
import initBlob from '~/pages/projects/init_blob';
-document.addEventListener('DOMContentLoaded', initBlob);
+initBlob();
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 57c4ffd3933..61ff1c95a38 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -1,11 +1,11 @@
import Vue from 'vue';
-import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
+import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
import BlobViewer from '~/blob/viewer/index';
-import initBlob from '~/pages/projects/init_blob';
import GpgBadges from '~/gpg_badges';
+import initBlob from '~/pages/projects/init_blob';
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
+import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import '~/sourcegraph/load';
-import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/boards/index.js b/app/assets/javascripts/pages/projects/boards/index.js
index 79c3be771d0..3a06d0faa3e 100644
--- a/app/assets/javascripts/pages/projects/boards/index.js
+++ b/app/assets/javascripts/pages/projects/boards/index.js
@@ -1,6 +1,6 @@
-import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import initBoards from '~/boards';
+import UsersSelect from '~/users_select';
document.addEventListener('DOMContentLoaded', () => {
new UsersSelect(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js
index 1124eb5d939..2b5451bd18b 100644
--- a/app/assets/javascripts/pages/projects/clusters/index/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/index/index.js
@@ -1,8 +1,6 @@
import initClustersListApp from 'ee_else_ce/clusters_list';
import PersistentUserCallout from '~/persistent_user_callout';
-document.addEventListener('DOMContentLoaded', () => {
- const callout = document.querySelector('.gcp-signup-offer');
- PersistentUserCallout.factory(callout);
- initClustersListApp();
-});
+const callout = document.querySelector('.gcp-signup-offer');
+PersistentUserCallout.factory(callout);
+initClustersListApp();
diff --git a/app/assets/javascripts/pages/projects/clusters/new/index.js b/app/assets/javascripts/pages/projects/clusters/new/index.js
index 876bab0b339..de9ded87ef3 100644
--- a/app/assets/javascripts/pages/projects/clusters/new/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/new/index.js
@@ -1,5 +1,3 @@
import initNewCluster from '~/clusters/new_cluster';
-document.addEventListener('DOMContentLoaded', () => {
- initNewCluster();
-});
+initNewCluster();
diff --git a/app/assets/javascripts/pages/projects/clusters/show/index.js b/app/assets/javascripts/pages/projects/clusters/show/index.js
index a05ea8ae845..1d019285e23 100644
--- a/app/assets/javascripts/pages/projects/clusters/show/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/show/index.js
@@ -1,7 +1,7 @@
import ClustersBundle from '~/clusters/clusters_bundle';
+import initIntegrationForm from '~/clusters/forms/show';
import initGkeNamespace from '~/create_cluster/gke_cluster_namespace';
import initClusterHealth from './cluster_health';
-import initIntegrationForm from '~/clusters/forms/show';
document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/commit/pipelines/index.js b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
index eaf340f2725..6efd8298bf8 100644
--- a/app/assets/javascripts/pages/projects/commit/pipelines/index.js
+++ b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
@@ -1,5 +1,7 @@
-import { initCommitBoxInfo } from '~/projects/commit_box/info';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
+import initCommitActions from '~/projects/commit';
+import { initCommitBoxInfo } from '~/projects/commit_box/info';
initCommitBoxInfo();
initPipelines();
+initCommitActions();
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index 5cfdb125e4f..90a663802d2 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -1,21 +1,19 @@
/* eslint-disable no-new */
-
import $ from 'jquery';
-import Diff from '~/diff';
-import ZenMode from '~/zen_mode';
+import loadAwardsHandler from '~/awards_handler';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import initNotes from '~/init_notes';
+import Diff from '~/diff';
+import flash from '~/flash';
import initChangesDropdown from '~/init_changes_dropdown';
-import '~/sourcegraph/load';
-import { handleLocationHash } from '~/lib/utils/common_utils';
+import initNotes from '~/init_notes';
import axios from '~/lib/utils/axios_utils';
-import syntaxHighlight from '~/syntax_highlight';
-import flash from '~/flash';
+import { handleLocationHash } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
-import loadAwardsHandler from '~/awards_handler';
+import initCommitActions from '~/projects/commit';
import { initCommitBoxInfo } from '~/projects/commit_box/info';
-import initRevertCommitTrigger from '~/projects/commit/init_revert_commit_trigger';
-import initRevertCommitModal from '~/projects/commit/init_revert_commit_modal';
+import syntaxHighlight from '~/syntax_highlight';
+import ZenMode from '~/zen_mode';
+import '~/sourcegraph/load';
const hasPerfBar = document.querySelector('.with-performance-bar');
const performanceHeight = hasPerfBar ? 35 : 0;
@@ -47,5 +45,4 @@ if (filesContainer.length) {
new Diff();
}
loadAwardsHandler();
-initRevertCommitModal();
-initRevertCommitTrigger();
+initCommitActions();
diff --git a/app/assets/javascripts/pages/projects/commits/show/index.js b/app/assets/javascripts/pages/projects/commits/show/index.js
index 6239e4c99d2..ee74628a994 100644
--- a/app/assets/javascripts/pages/projects/commits/show/index.js
+++ b/app/assets/javascripts/pages/projects/commits/show/index.js
@@ -1,6 +1,6 @@
+import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import CommitsList from '~/commits';
import GpgBadges from '~/gpg_badges';
-import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import mountCommits from '~/projects/commits';
new CommitsList(document.querySelector('.js-project-commits-show').dataset.commitsLimit); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/compare/index/index.js b/app/assets/javascripts/pages/projects/compare/index/index.js
new file mode 100644
index 00000000000..b86c9ec442f
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/compare/index/index.js
@@ -0,0 +1,3 @@
+import initCompareSelector from '~/projects/compare';
+
+initCompareSelector();
diff --git a/app/assets/javascripts/pages/projects/compare/show/index.js b/app/assets/javascripts/pages/projects/compare/show/index.js
index a626ed2d30b..f1cf9caa28b 100644
--- a/app/assets/javascripts/pages/projects/compare/show/index.js
+++ b/app/assets/javascripts/pages/projects/compare/show/index.js
@@ -1,6 +1,6 @@
import Diff from '~/diff';
-import initChangesDropdown from '~/init_changes_dropdown';
import GpgBadges from '~/gpg_badges';
+import initChangesDropdown from '~/init_changes_dropdown';
document.addEventListener('DOMContentLoaded', () => {
new Diff(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js
index 5f1d3edc3ba..9aa7e62e3ee 100644
--- a/app/assets/javascripts/pages/projects/edit/index.js
+++ b/app/assets/javascripts/pages/projects/edit/index.js
@@ -1,36 +1,34 @@
import { PROJECT_BADGE } from '~/badges/constants';
-import initSettingsPanels from '~/settings_panels';
-import setupTransferEdit from '~/transfer_edit';
import initConfirmDangerModal from '~/confirm_danger_modal';
-import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import initFilePickers from '~/file_pickers';
-import initProjectLoadingSpinner from '../shared/save_project_loader';
-import initProjectPermissionsSettings from '../shared/permissions';
+import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import initProjectDeleteButton from '~/projects/project_delete_button';
-import UserCallout from '~/user_callout';
import initServiceDesk from '~/projects/settings_service_desk';
-import mountSearchSettings from './mount_search_settings';
+import initSearchSettings from '~/search_settings';
+import initSettingsPanels from '~/settings_panels';
+import setupTransferEdit from '~/transfer_edit';
+import UserCallout from '~/user_callout';
+import initProjectPermissionsSettings from '../shared/permissions';
+import initProjectLoadingSpinner from '../shared/save_project_loader';
-document.addEventListener('DOMContentLoaded', () => {
- initFilePickers();
- initConfirmDangerModal();
- initSettingsPanels();
- initProjectDeleteButton();
- mountBadgeSettings(PROJECT_BADGE);
+initFilePickers();
+initConfirmDangerModal();
+initSettingsPanels();
+initProjectDeleteButton();
+mountBadgeSettings(PROJECT_BADGE);
- new UserCallout({ className: 'js-service-desk-callout' }); // eslint-disable-line no-new
- initServiceDesk();
+new UserCallout({ className: 'js-service-desk-callout' }); // eslint-disable-line no-new
+initServiceDesk();
- initProjectLoadingSpinner();
- initProjectPermissionsSettings();
- setupTransferEdit('.js-project-transfer-form', 'select.select2');
+initProjectLoadingSpinner();
+initProjectPermissionsSettings();
+setupTransferEdit('.js-project-transfer-form', 'select.select2');
- dirtySubmitFactory(
- document.querySelectorAll(
- '.js-general-settings-form, .js-mr-settings-form, .js-mr-approvals-form',
- ),
- );
+dirtySubmitFactory(
+ document.querySelectorAll(
+ '.js-general-settings-form, .js-mr-settings-form, .js-mr-approvals-form',
+ ),
+);
- mountSearchSettings();
-});
+initSearchSettings();
diff --git a/app/assets/javascripts/pages/projects/edit/mount_search_settings.js b/app/assets/javascripts/pages/projects/edit/mount_search_settings.js
deleted file mode 100644
index 6c477dd7e80..00000000000
--- a/app/assets/javascripts/pages/projects/edit/mount_search_settings.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const mountSearchSettings = async () => {
- const el = document.querySelector('.js-search-settings-app');
-
- if (el) {
- const { default: initSearch } = await import(
- /* webpackChunkName: 'search_settings' */ '~/search_settings'
- );
- initSearch({ el });
- }
-};
-
-export default mountSearchSettings;
diff --git a/app/assets/javascripts/pages/projects/environments/index/index.js b/app/assets/javascripts/pages/projects/environments/index/index.js
index 4d5106f6d5f..554ed4f9786 100644
--- a/app/assets/javascripts/pages/projects/environments/index/index.js
+++ b/app/assets/javascripts/pages/projects/environments/index/index.js
@@ -1,3 +1,3 @@
import initEnvironments from '~/environments/';
-document.addEventListener('DOMContentLoaded', initEnvironments);
+initEnvironments();
diff --git a/app/assets/javascripts/pages/projects/environments/show/index.js b/app/assets/javascripts/pages/projects/environments/show/index.js
index 5d3a153cbd1..a4960037eaa 100644
--- a/app/assets/javascripts/pages/projects/environments/show/index.js
+++ b/app/assets/javascripts/pages/projects/environments/show/index.js
@@ -1,3 +1,3 @@
import initShowEnvironment from '~/environments/mount_show';
-document.addEventListener('DOMContentLoaded', initShowEnvironment);
+initShowEnvironment();
diff --git a/app/assets/javascripts/pages/projects/find_file/show/index.js b/app/assets/javascripts/pages/projects/find_file/show/index.js
index 388d7d7bdda..a8225167c6b 100644
--- a/app/assets/javascripts/pages/projects/find_file/show/index.js
+++ b/app/assets/javascripts/pages/projects/find_file/show/index.js
@@ -1,13 +1,11 @@
import $ from 'jquery';
-import ProjectFindFile from '~/project_find_file';
import ShortcutsFindFile from '~/behaviors/shortcuts/shortcuts_find_file';
+import ProjectFindFile from '~/project_find_file';
-document.addEventListener('DOMContentLoaded', () => {
- const findElement = document.querySelector('.js-file-finder');
- const projectFindFile = new ProjectFindFile($('.file-finder-holder'), {
- url: findElement.dataset.fileFindUrl,
- treeUrl: findElement.dataset.findTreeUrl,
- blobUrlTemplate: findElement.dataset.blobUrlTemplate,
- });
- new ShortcutsFindFile(projectFindFile); // eslint-disable-line no-new
+const findElement = document.querySelector('.js-file-finder');
+const projectFindFile = new ProjectFindFile($('.file-finder-holder'), {
+ url: findElement.dataset.fileFindUrl,
+ treeUrl: findElement.dataset.findTreeUrl,
+ blobUrlTemplate: findElement.dataset.blobUrlTemplate,
});
+new ShortcutsFindFile(projectFindFile); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
index a614443bcd9..bc47b124f8b 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list.vue
@@ -1,8 +1,8 @@
<script>
import { GlTabs, GlTab, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import ForkGroupsListItem from './fork_groups_list_item.vue';
export default {
@@ -14,10 +14,6 @@ export default {
ForkGroupsListItem,
},
props: {
- hasReachedProjectLimit: {
- type: Boolean,
- required: true,
- },
endpoint: {
type: String,
required: true,
@@ -77,7 +73,6 @@ export default {
v-for="(namespace, index) in filteredNamespaces"
:key="index"
:group="namespace"
- :has-reached-project-limit="hasReachedProjectLimit"
/>
</ul>
</gl-tab>
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
index 57838050d55..46d1696b88b 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
@@ -10,7 +10,6 @@ import {
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '~/groups/constants';
-import { __ } from '~/locale';
import csrf from '~/lib/utils/csrf';
export default {
@@ -31,10 +30,6 @@ export default {
type: Object,
required: true,
},
- hasReachedProjectLimit: {
- type: Boolean,
- required: true,
- },
},
data() {
return { namespaces: null, isForking: false };
@@ -60,12 +55,7 @@ export default {
return GROUP_VISIBILITY_TYPE[this.group.visibility];
},
isSelectButtonDisabled() {
- return this.hasReachedProjectLimit || !this.group.can_create_project;
- },
- selectButtonDisabledTooltip() {
- return this.hasReachedProjectLimit
- ? this.$options.i18n.hasReachedProjectLimitMessage
- : this.$options.i18n.insufficientPermissionsMessage;
+ return !this.group.can_create_project;
},
},
@@ -76,13 +66,6 @@ export default {
},
},
- i18n: {
- hasReachedProjectLimitMessage: __('You have reached your project limit'),
- insufficientPermissionsMessage: __(
- 'You must have permission to create a project in a namespace before forking.',
- ),
- },
-
csrf,
};
</script>
@@ -94,7 +77,7 @@ export default {
</div>
<gl-link
:href="group.relative_path"
- class="gl-display-none gl-flex-shrink-0 gl-display-sm-flex gl-mr-3"
+ class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3"
>
<gl-avatar :size="32" shape="rect" :entity-name="group.name" :src="group.avatarUrl" />
</gl-link>
@@ -113,7 +96,7 @@ export default {
<gl-badge
v-if="isGroupPendingRemoval"
variant="warning"
- class="gl-display-none gl-display-sm-flex gl-mt-3 gl-mr-1"
+ class="gl-display-none gl-sm-display-flex gl-mt-3 gl-mr-1"
>{{ __('pending removal') }}</gl-badge
>
<span v-if="group.permission" class="user-access-role gl-mt-3">
@@ -149,7 +132,9 @@ export default {
</form>
</div>
<gl-tooltip v-if="isSelectButtonDisabled" :target="() => $refs.selectButtonWrapper">
- {{ selectButtonDisabledTooltip }}
+ {{
+ __('You must have permission to create a project in a namespace before forking.')
+ }}
</gl-tooltip>
</template>
</div>
diff --git a/app/assets/javascripts/pages/projects/forks/new/index.js b/app/assets/javascripts/pages/projects/forks/new/index.js
index 79485859738..a018d7e0926 100644
--- a/app/assets/javascripts/pages/projects/forks/new/index.js
+++ b/app/assets/javascripts/pages/projects/forks/new/index.js
@@ -1,13 +1,10 @@
import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
import ForkGroupsList from './components/fork_groups_list.vue';
document.addEventListener('DOMContentLoaded', () => {
const mountElement = document.getElementById('fork-groups-mount-element');
- const { endpoint, canCreateProject } = mountElement.dataset;
-
- const hasReachedProjectLimit = !parseBoolean(canCreateProject);
+ const { endpoint } = mountElement.dataset;
return new Vue({
el: mountElement,
@@ -15,7 +12,6 @@ document.addEventListener('DOMContentLoaded', () => {
return h(ForkGroupsList, {
props: {
endpoint,
- hasReachedProjectLimit,
},
});
},
diff --git a/app/assets/javascripts/pages/projects/incidents/show/index.js b/app/assets/javascripts/pages/projects/incidents/show/index.js
index 5b3f03cd57e..a75b68873ef 100644
--- a/app/assets/javascripts/pages/projects/incidents/show/index.js
+++ b/app/assets/javascripts/pages/projects/incidents/show/index.js
@@ -1,9 +1,7 @@
-import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initRelatedIssues from '~/related_issues';
+import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initShow from '../../issues/show';
initShow();
-if (!gon.features?.vueIssuableSidebar) {
- initSidebarBundle();
-}
+initSidebarBundle();
initRelatedIssues();
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index 3e9962a4e72..45e9643b3f3 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,5 +1,5 @@
-import Project from './project';
import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation';
+import Project from './project';
new Project(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js
index 5eb0d323266..06aba866ccf 100644
--- a/app/assets/javascripts/pages/projects/init_blob.js
+++ b/app/assets/javascripts/pages/projects/init_blob.js
@@ -1,9 +1,9 @@
-import LineHighlighter from '~/line_highlighter';
-import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
-import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob';
+import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import BlobForkSuggestion from '~/blob/blob_fork_suggestion';
+import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import initBlobBundle from '~/blob_edit/blob_bundle';
+import LineHighlighter from '~/line_highlighter';
export default () => {
new LineHighlighter(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/init_form.js b/app/assets/javascripts/pages/projects/init_form.js
index 9f20a3e4e46..764c23e9a99 100644
--- a/app/assets/javascripts/pages/projects/init_form.js
+++ b/app/assets/javascripts/pages/projects/init_form.js
@@ -1,7 +1,7 @@
-import ZenMode from '~/zen_mode';
import GLForm from '~/gl_form';
+import ZenMode from '~/zen_mode';
-export default function ($formEl) {
+export default function initProjectForm($formEl) {
new ZenMode(); // eslint-disable-line no-new
new GLForm($formEl); // eslint-disable-line no-new
}
diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js
index 34c7ee2e603..4e35f28ab06 100644
--- a/app/assets/javascripts/pages/projects/issues/form.js
+++ b/app/assets/javascripts/pages/projects/issues/form.js
@@ -2,12 +2,12 @@
import $ from 'jquery';
import IssuableForm from 'ee_else_ce/issuable_form';
+import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GLForm from '~/gl_form';
+import initSuggestions from '~/issuable_suggestions';
import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
-import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
-import initSuggestions from '~/issuable_suggestions';
export default () => {
new ShortcutsNavigation();
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
index f3ccedc47c8..525d90e162d 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -1,15 +1,15 @@
/* eslint-disable no-new */
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import UsersSelect from '~/users_select';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
-import { FILTERED_SEARCH } from '~/pages/constants';
-import { ISSUABLE_INDEX } from '~/pages/projects/constants';
+import initIssuableByEmail from '~/issuable/init_issuable_by_email';
+import IssuableIndex from '~/issuable_index';
import initIssuablesList from '~/issues_list';
import initManualOrdering from '~/manual_ordering';
-import { showLearnGitLabIssuesPopover } from '~/onboarding_issues';
+import { FILTERED_SEARCH } from '~/pages/constants';
+import { ISSUABLE_INDEX } from '~/pages/projects/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import UsersSelect from '~/users_select';
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
@@ -25,4 +25,4 @@ new UsersSelect();
initManualOrdering();
initIssuablesList();
-showLearnGitLabIssuesPopover();
+initIssuableByEmail();
diff --git a/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js b/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js
index ccb453a59ea..bec207aa439 100644
--- a/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js
+++ b/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js
@@ -1,6 +1,6 @@
/* eslint-disable class-methods-use-this */
-import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import FilteredSearchManager from 'ee_else_ce/filtered_search/filtered_search_manager';
+import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
const AUTHOR_PARAM_KEY = 'author_username';
diff --git a/app/assets/javascripts/pages/projects/issues/service_desk/index.js b/app/assets/javascripts/pages/projects/issues/service_desk/index.js
index 231ee6732e9..5be9f6117dc 100644
--- a/app/assets/javascripts/pages/projects/issues/service_desk/index.js
+++ b/app/assets/javascripts/pages/projects/issues/service_desk/index.js
@@ -1,5 +1,5 @@
-import FilteredSearchServiceDesk from './filtered_search';
import initIssuablesList from '~/issues_list';
+import FilteredSearchServiceDesk from './filtered_search';
const supportBotData = JSON.parse(
document.querySelector('.js-service-desk-issues').dataset.supportBot,
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 7068574ecb8..992bf3c54ff 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -1,22 +1,21 @@
import loadAwardsHandler from '~/awards_handler';
+import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initIssuableSidebar from '~/init_issuable_sidebar';
+import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
+import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
+import { IssuableType } from '~/issuable_show/constants';
import Issue from '~/issue';
-import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
-import ZenMode from '~/zen_mode';
import '~/notes/index';
-import { store } from '~/notes/stores';
-import { initIssuableApp, initIssueHeaderActions } from '~/issue_show/issue';
import initIncidentApp from '~/issue_show/incident';
-import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
-import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
-import initRelatedMergeRequestsApp from '~/related_merge_requests';
+import { initIssuableApp, initIssueHeaderActions } from '~/issue_show/issue';
import { parseIssuableData } from '~/issue_show/utils/parse_data';
-import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
-import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
-
-import { IssuableType } from '~/issuable_show/constants';
+import { store } from '~/notes/stores';
+import initRelatedMergeRequestsApp from '~/related_merge_requests';
+import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
+import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
+import ZenMode from '~/zen_mode';
-export default function () {
+export default function initShowIssue() {
const initialDataEl = document.getElementById('js-issuable-app');
const { issueType, ...issuableData } = parseIssuableData(initialDataEl);
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
index 630add51a97..e4f99d1e7fd 100644
--- a/app/assets/javascripts/pages/projects/issues/show/index.js
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -1,9 +1,7 @@
-import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initRelatedIssues from '~/related_issues';
+import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initShow from '../show';
initShow();
-if (gon.features && !gon.features.vueIssuableSidebar) {
- initSidebarBundle();
-}
+initSidebarBundle();
initRelatedIssues();
diff --git a/app/assets/javascripts/pages/projects/jobs/index/index.js b/app/assets/javascripts/pages/projects/jobs/index/index.js
index c343a37b292..6a70d4cf26d 100644
--- a/app/assets/javascripts/pages/projects/jobs/index/index.js
+++ b/app/assets/javascripts/pages/projects/jobs/index/index.js
@@ -1,26 +1,19 @@
import Vue from 'vue';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
-import Tracking from '~/tracking';
document.addEventListener('DOMContentLoaded', () => {
const remainingTimeElements = document.querySelectorAll('.js-remaining-time');
remainingTimeElements.forEach(
(el) =>
new Vue({
- ...GlCountdown,
el,
- propsData: {
- endDateString: el.dateTime,
+ render(h) {
+ return h(GlCountdown, {
+ props: {
+ endDateString: el.dateTime,
+ },
+ });
},
}),
);
-
- const trackButtonClick = () => {
- if (gon.tracking_data) {
- const { category, action, ...data } = gon.tracking_data;
- Tracking.event(category, action, data);
- }
- };
- const buttons = document.querySelectorAll('.js-empty-state-button');
- buttons.forEach((button) => button.addEventListener('click', trackButtonClick));
});
diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
index 8626fd18233..81ffaa6f7a3 100644
--- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
@@ -1,9 +1,9 @@
<script>
import { GlSprintf, GlModal } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__, __, sprintf } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
+import { s__, __, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 4f5e5c8cceb..9f782c07101 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -1,8 +1,9 @@
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
import initLabels from '~/init_labels';
-import eventHub from '../event_hub';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import Translate from '~/vue_shared/translate';
import PromoteLabelModal from '../components/promote_label_modal.vue';
+import eventHub from '../event_hub';
Vue.use(Translate);
@@ -49,7 +50,7 @@ const initLabelIndex = () => {
promoteLabelButtons.forEach((button) => {
button.removeAttribute('disabled');
button.addEventListener('click', () => {
- this.$root.$emit('bv::show::modal', 'promote-label-modal');
+ this.$root.$emit(BV_SHOW_MODAL, 'promote-label-modal');
eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
this.setModalProps({
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue
new file mode 100644
index 00000000000..0393793bfe1
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue
@@ -0,0 +1,27 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import { ACTION_TEXT } from '../constants';
+
+export default {
+ components: { GlLink },
+ i18n: {
+ ACTION_TEXT,
+ },
+ props: {
+ actions: {
+ required: true,
+ type: Object,
+ },
+ },
+};
+</script>
+<template>
+ <ul>
+ <li v-for="(value, action) in actions" :key="action">
+ <span v-if="value.completed">{{ $options.i18n.ACTION_TEXT[action] }}</span>
+ <span v-else>
+ <gl-link :href="value.url">{{ $options.i18n.ACTION_TEXT[action] }}</gl-link>
+ </span>
+ </li>
+ </ul>
+</template>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue
new file mode 100644
index 00000000000..0393793bfe1
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue
@@ -0,0 +1,27 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import { ACTION_TEXT } from '../constants';
+
+export default {
+ components: { GlLink },
+ i18n: {
+ ACTION_TEXT,
+ },
+ props: {
+ actions: {
+ required: true,
+ type: Object,
+ },
+ },
+};
+</script>
+<template>
+ <ul>
+ <li v-for="(value, action) in actions" :key="action">
+ <span v-if="value.completed">{{ $options.i18n.ACTION_TEXT[action] }}</span>
+ <span v-else>
+ <gl-link :href="value.url">{{ $options.i18n.ACTION_TEXT[action] }}</gl-link>
+ </span>
+ </li>
+ </ul>
+</template>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
new file mode 100644
index 00000000000..8606af29785
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js
@@ -0,0 +1,12 @@
+import { s__ } from '~/locale';
+
+export const ACTION_TEXT = {
+ gitWrite: s__('LearnGitLab|Create a repository'),
+ userAdded: s__('LearnGitLab|Invite your colleagues'),
+ pipelineCreated: s__('LearnGitLab|Set-up CI/CD'),
+ trialStarted: s__('LearnGitLab|Start a free trial of GitLab Gold'),
+ codeOwnersEnabled: s__('LearnGitLab|Add code owners'),
+ requiredMrApprovalsEnabled: s__('LearnGitLab|Enable require merge approvals'),
+ mergeRequestCreated: s__('LearnGitLab|Submit a merge request (MR)'),
+ securityScanEnabled: s__('LearnGitLab|Run a Security scan using CI/CD'),
+};
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
new file mode 100644
index 00000000000..c4dec89b984
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
@@ -0,0 +1,25 @@
+import Vue from 'vue';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import LearnGitlabA from '../components/learn_gitlab_a.vue';
+import LearnGitlabB from '../components/learn_gitlab_b.vue';
+
+function initLearnGitlab() {
+ const el = document.getElementById('js-learn-gitlab-app');
+
+ if (!el) {
+ return false;
+ }
+
+ const actions = convertObjectPropsToCamelCase(JSON.parse(el.dataset.actions));
+
+ const { learnGitlabA } = gon.experiments;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(learnGitlabA ? LearnGitlabA : LearnGitlabB, { props: { actions } });
+ },
+ });
+}
+
+initLearnGitlab();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/conflicts/index.js b/app/assets/javascripts/pages/projects/merge_requests/conflicts/index.js
index 28641104c58..05019915fc9 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/conflicts/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/conflicts/index.js
@@ -1,5 +1,5 @@
-import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initMergeConflicts from '~/merge_conflicts/merge_conflicts_bundle';
+import initSidebarBundle from '~/sidebar/sidebar_bundle';
document.addEventListener('DOMContentLoaded', () => {
initSidebarBundle();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/index.js b/app/assets/javascripts/pages/projects/merge_requests/creations/index.js
index febfecebbd2..34d9fa03d24 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/index.js
@@ -1,3 +1,3 @@
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
-document.addEventListener('DOMContentLoaded', initMergeRequest);
+initMergeRequest();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js
index eb2692c7cb4..1a0fa6e544e 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import { localTimeAgo } from '~/lib/utils/datetime_utility';
-import axios from '~/lib/utils/axios_utils';
import initCompareAutocomplete from '~/compare_autocomplete';
+import axios from '~/lib/utils/axios_utils';
+import { localTimeAgo } from '~/lib/utils/datetime_utility';
import initTargetProjectDropdown from './target_project_dropdown';
const updateCommitList = (url, $loadingIndicator, $commitList, params) => {
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js
index 01a0b4870c1..9aecd154483 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js
@@ -1,17 +1,15 @@
-import MergeRequest from '~/merge_request';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
+import MergeRequest from '~/merge_request';
import initCompare from './compare';
-document.addEventListener('DOMContentLoaded', () => {
- const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
- if (mrNewCompareNode) {
- initCompare(mrNewCompareNode);
- } else {
- const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
- // eslint-disable-next-line no-new
- new MergeRequest({
- action: mrNewSubmitNode.dataset.mrSubmitAction,
- });
- initPipelines();
- }
-});
+const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
+if (mrNewCompareNode) {
+ initCompare(mrNewCompareNode);
+} else {
+ const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
+ // eslint-disable-next-line no-new
+ new MergeRequest({
+ action: mrNewSubmitNode.dataset.mrSubmitAction,
+ });
+ initPipelines();
+}
diff --git a/app/assets/javascripts/pages/projects/merge_requests/edit/check_form_state.js b/app/assets/javascripts/pages/projects/merge_requests/edit/check_form_state.js
new file mode 100644
index 00000000000..74178ab96e3
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/merge_requests/edit/check_form_state.js
@@ -0,0 +1,24 @@
+import { serializeForm } from '~/lib/utils/forms';
+
+const findForm = () => document.querySelector('.merge-request-form');
+const serializeFormData = () => JSON.stringify(serializeForm(findForm()));
+
+export default () => {
+ const oldFormData = serializeFormData();
+
+ const compareFormData = (e) => {
+ const newFormData = serializeFormData();
+
+ if (oldFormData !== newFormData) {
+ e.preventDefault();
+ // eslint-disable-next-line no-param-reassign
+ e.returnValue = ''; // Chrome requires returnValue to be set
+ }
+ };
+
+ window.addEventListener('beforeunload', compareFormData);
+
+ findForm().addEventListener('submit', () =>
+ window.removeEventListener('beforeunload', compareFormData),
+ );
+};
diff --git a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
index febfecebbd2..399aebb0c83 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
@@ -1,3 +1,7 @@
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
+import initCheckFormState from './check_form_state';
-document.addEventListener('DOMContentLoaded', initMergeRequest);
+document.addEventListener('DOMContentLoaded', () => {
+ initMergeRequest();
+ initCheckFormState();
+});
diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
index 94a12cc2706..76705256fe2 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
@@ -1,11 +1,12 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
-import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import UsersSelect from '~/users_select';
-import initFilteredSearch from '~/pages/search/init_filtered_search';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import initIssuableByEmail from '~/issuable/init_issuable_by_email';
+import IssuableIndex from '~/issuable_index';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import UsersSelect from '~/users_select';
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
@@ -19,3 +20,5 @@ initFilteredSearch({
new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
+
+initIssuableByEmail();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
index 76d72efb11b..7d5719cf8a8 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
@@ -2,8 +2,8 @@
import $ from 'jquery';
import IssuableForm from 'ee_else_ce/issuable_form';
-import Diff from '~/diff';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
+import Diff from '~/diff';
import GLForm from '~/gl_form';
import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
index 1a0c5860991..d4d5e9f2711 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
@@ -1,16 +1,16 @@
import Vue from 'vue';
-import ZenMode from '~/zen_mode';
-import initIssuableSidebar from '~/init_issuable_sidebar';
+import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
-import { handleLocationHash } from '~/lib/utils/common_utils';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
-import initSourcegraph from '~/sourcegraph';
-import loadAwardsHandler from '~/awards_handler';
-import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
+import initIssuableSidebar from '~/init_issuable_sidebar';
import initInviteMemberModal from '~/invite_member/init_invite_member_modal';
+import initInviteMemberTrigger from '~/invite_member/init_invite_member_trigger';
+import { handleLocationHash } from '~/lib/utils/common_utils';
import StatusBox from '~/merge_request/components/status_box.vue';
+import initSourcegraph from '~/sourcegraph';
+import ZenMode from '~/zen_mode';
-export default function () {
+export default function initMergeRequestShow() {
new ZenMode(); // eslint-disable-line no-new
initIssuableSidebar();
initPipelines();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/show/index.js b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
index 602d749ee07..546fa66eda6 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/show/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
@@ -1,14 +1,12 @@
-import initMrNotes from '~/mr_notes';
import { initReviewBar } from '~/batch_comments';
+import initMrNotes from '~/mr_notes';
+import store from '~/mr_notes/stores';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
-import initShow from '../init_merge_request_show';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
-import store from '~/mr_notes/stores';
+import initShow from '../init_merge_request_show';
initShow();
-if (gon.features && !gon.features.vueIssuableSidebar) {
- initSidebarBundle();
-}
+initSidebarBundle();
initMrNotes();
initReviewBar();
initIssuableHeaderWarning(store);
diff --git a/app/assets/javascripts/pages/projects/milestones/show/index.js b/app/assets/javascripts/pages/projects/milestones/show/index.js
index 84a52421598..a853413e1f7 100644
--- a/app/assets/javascripts/pages/projects/milestones/show/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/show/index.js
@@ -1,5 +1,5 @@
-import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
import milestones from '~/pages/milestones/shared';
+import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
document.addEventListener('DOMContentLoaded', () => {
initMilestonesShow();
diff --git a/app/assets/javascripts/pages/projects/new/index.js b/app/assets/javascripts/pages/projects/new/index.js
index 88f4db3ec08..437594fdf11 100644
--- a/app/assets/javascripts/pages/projects/new/index.js
+++ b/app/assets/javascripts/pages/projects/new/index.js
@@ -1,7 +1,7 @@
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { __ } from '~/locale';
import initProjectVisibilitySelector from '../../../project_visibility';
import initProjectNew from '../../../projects/project_new';
-import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
document.addEventListener('DOMContentLoaded', () => {
initProjectVisibilitySelector();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index aa7414f3ae7..3b19231720a 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -1,7 +1,7 @@
<script>
import { GlFormRadio, GlFormRadioGroup, GlLink, GlSprintf } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
import { getWeekdayNames } from '~/lib/utils/datetime_utility';
+import { s__, sprintf } from '~/locale';
const KEY_EVERY_DAY = 'everyDay';
const KEY_EVERY_WEEK = 'everyWeek';
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 8ee9d481466..92b2bc9644b 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,9 +1,9 @@
<script>
-import Vue from 'vue';
-import Cookies from 'js-cookie';
import { GlButton } from '@gitlab/ui';
-import Translate from '../../../../../vue_shared/translate';
+import Cookies from 'js-cookie';
+import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
+import Translate from '../../../../../vue_shared/translate';
Vue.use(Translate);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
index 497e2c9c0ae..ce0e573fed2 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import Vue from 'vue';
-import Translate from '../../../../vue_shared/translate';
+import setupNativeFormVariableList from '../../../../ci_variable_list/native_form_variable_list';
import GlFieldErrors from '../../../../gl_field_errors';
+import Translate from '../../../../vue_shared/translate';
import intervalPatternInput from './components/interval_pattern_input.vue';
-import TimezoneDropdown from './components/timezone_dropdown';
import TargetBranchDropdown from './components/target_branch_dropdown';
-import setupNativeFormVariableList from '../../../../ci_variable_list/native_form_variable_list';
+import TimezoneDropdown from './components/timezone_dropdown';
Vue.use(Translate);
diff --git a/app/assets/javascripts/pages/projects/pipelines/new/index.js b/app/assets/javascripts/pages/projects/pipelines/new/index.js
index 08c31f2b3c6..32299287a9c 100644
--- a/app/assets/javascripts/pages/projects/pipelines/new/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/new/index.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import NewBranchForm from '~/new_branch_form';
import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
+import NewBranchForm from '~/new_branch_form';
import initNewPipeline from '~/pipeline_new/index';
const el = document.getElementById('js-new-pipeline');
diff --git a/app/assets/javascripts/pages/projects/product_analytics/graphs/index.js b/app/assets/javascripts/pages/projects/product_analytics/graphs/index.js
index 0539d318471..ba03fccdb03 100644
--- a/app/assets/javascripts/pages/projects/product_analytics/graphs/index.js
+++ b/app/assets/javascripts/pages/projects/product_analytics/graphs/index.js
@@ -1,3 +1,3 @@
import initActivityCharts from '~/analytics/product_analytics/activity_charts_bundle';
-document.addEventListener('DOMContentLoaded', () => initActivityCharts());
+initActivityCharts();
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index ef6953db83b..da8dc527d79 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -2,14 +2,14 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
-import { __ } from '~/locale';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { serializeForm } from '~/lib/utils/forms';
-import axios from '~/lib/utils/axios_utils';
+import initClonePanel from '~/clone_panel';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { serializeForm } from '~/lib/utils/forms';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import projectSelect from '../../project_select';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import initClonePanel from '~/clone_panel';
export default class Project {
constructor() {
@@ -126,8 +126,9 @@ export default class Project {
const refs = this.fullData.Branches.concat(this.fullData.Tags);
const currentRef = refs.find((ref) => loc.indexOf(ref) > -1);
if (currentRef) {
- const targetPath = loc.split(currentRef)[1].slice(1);
+ const targetPath = loc.split(currentRef)[1].slice(1).split('#')[0];
selectedUrl.searchParams.set('path', targetPath);
+ selectedUrl.hash = window.location.hash;
}
}
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index 3e0a48ee6a2..ed11b07be4a 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -1,11 +1,13 @@
import Vue from 'vue';
-import Members from '~/members';
-import memberExpirationDate from '~/member_expiration_date';
-import UsersSelect from '~/users_select';
+import { deprecatedCreateFlash as flash } from '~/flash';
import groupsSelect from '~/groups_select';
-import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
+import { __ } from '~/locale';
+import memberExpirationDate from '~/member_expiration_date';
+import Members from '~/members';
+import UsersSelect from '~/users_select';
+import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
function mountRemoveMemberModal() {
const el = document.querySelector('.js-remove-member-modal');
@@ -21,14 +23,74 @@ function mountRemoveMemberModal() {
});
}
-document.addEventListener('DOMContentLoaded', () => {
- groupsSelect();
- memberExpirationDate();
- memberExpirationDate('.js-access-expiration-date-groups');
- mountRemoveMemberModal();
- initInviteMembersModal();
- initInviteMembersTrigger();
-
- new Members(); // eslint-disable-line no-new
- new UsersSelect(); // eslint-disable-line no-new
-});
+groupsSelect();
+memberExpirationDate();
+memberExpirationDate('.js-access-expiration-date-groups');
+mountRemoveMemberModal();
+initInviteMembersModal();
+initInviteMembersTrigger();
+
+new Members(); // eslint-disable-line no-new
+new UsersSelect(); // eslint-disable-line no-new
+
+if (window.gon.features.vueProjectMembersList) {
+ const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
+
+ Promise.all([
+ import('~/members/index'),
+ import('~/members/utils'),
+ import('~/projects/members/utils'),
+ import('~/locale'),
+ ])
+ .then(
+ ([
+ { initMembersApp },
+ { groupLinkRequestFormatter },
+ { projectMemberRequestFormatter },
+ { s__ },
+ ]) => {
+ initMembersApp(document.querySelector('.js-project-members-list'), {
+ tableFields: SHARED_FIELDS.concat(['source', 'granted']),
+ tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
+ tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
+ requestFormatter: projectMemberRequestFormatter,
+ filteredSearchBar: {
+ show: true,
+ tokens: ['with_inherited_permissions'],
+ searchParam: 'search',
+ placeholder: s__('Members|Filter members'),
+ recentSearchesStorageKey: 'project_members',
+ },
+ });
+
+ initMembersApp(document.querySelector('.js-project-group-links-list'), {
+ tableFields: SHARED_FIELDS.concat('granted'),
+ tableAttrs: {
+ table: { 'data-qa-selector': 'groups_list' },
+ tr: { 'data-qa-selector': 'group_row' },
+ },
+ requestFormatter: groupLinkRequestFormatter,
+ filteredSearchBar: {
+ show: true,
+ tokens: [],
+ searchParam: 'search_groups',
+ placeholder: s__('Members|Search groups'),
+ recentSearchesStorageKey: 'project_group_links',
+ },
+ });
+
+ initMembersApp(document.querySelector('.js-project-invited-members-list'), {
+ tableFields: SHARED_FIELDS.concat('invited'),
+ requestFormatter: projectMemberRequestFormatter,
+ });
+
+ initMembersApp(document.querySelector('.js-project-access-requests-list'), {
+ tableFields: SHARED_FIELDS.concat('requested'),
+ requestFormatter: projectMemberRequestFormatter,
+ });
+ },
+ )
+ .catch(() => {
+ flash(__('An error occurred while loading the members, please try again.'));
+ });
+}
diff --git a/app/assets/javascripts/pages/projects/releases/edit/index.js b/app/assets/javascripts/pages/projects/releases/edit/index.js
index efa059dcd6d..e4a8b71eb16 100644
--- a/app/assets/javascripts/pages/projects/releases/edit/index.js
+++ b/app/assets/javascripts/pages/projects/releases/edit/index.js
@@ -1,7 +1,5 @@
-import ZenMode from '~/zen_mode';
import initEditRelease from '~/releases/mount_edit';
+import ZenMode from '~/zen_mode';
-document.addEventListener('DOMContentLoaded', () => {
- new ZenMode(); // eslint-disable-line no-new
- initEditRelease();
-});
+new ZenMode(); // eslint-disable-line no-new
+initEditRelease();
diff --git a/app/assets/javascripts/pages/projects/releases/index/index.js b/app/assets/javascripts/pages/projects/releases/index/index.js
index 24c9cd528b3..caf95ae53c8 100644
--- a/app/assets/javascripts/pages/projects/releases/index/index.js
+++ b/app/assets/javascripts/pages/projects/releases/index/index.js
@@ -1,3 +1,3 @@
import initReleases from '~/releases/mount_index';
-document.addEventListener('DOMContentLoaded', initReleases);
+initReleases();
diff --git a/app/assets/javascripts/pages/projects/releases/new/index.js b/app/assets/javascripts/pages/projects/releases/new/index.js
index 0e314aacf8a..31c1715ce2a 100644
--- a/app/assets/javascripts/pages/projects/releases/new/index.js
+++ b/app/assets/javascripts/pages/projects/releases/new/index.js
@@ -1,7 +1,5 @@
-import ZenMode from '~/zen_mode';
import initNewRelease from '~/releases/mount_new';
+import ZenMode from '~/zen_mode';
-document.addEventListener('DOMContentLoaded', () => {
- new ZenMode(); // eslint-disable-line no-new
- initNewRelease();
-});
+new ZenMode(); // eslint-disable-line no-new
+initNewRelease();
diff --git a/app/assets/javascripts/pages/projects/releases/show/index.js b/app/assets/javascripts/pages/projects/releases/show/index.js
index 4e17e6ff311..0ec70ef24b6 100644
--- a/app/assets/javascripts/pages/projects/releases/show/index.js
+++ b/app/assets/javascripts/pages/projects/releases/show/index.js
@@ -1,3 +1,3 @@
import initShowRelease from '~/releases/mount_show';
-document.addEventListener('DOMContentLoaded', initShowRelease);
+initShowRelease();
diff --git a/app/assets/javascripts/pages/projects/security/configuration/index.js b/app/assets/javascripts/pages/projects/security/configuration/index.js
new file mode 100644
index 00000000000..101cb8356b2
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/security/configuration/index.js
@@ -0,0 +1,3 @@
+import { initStaticSecurityConfiguration } from '~/security_configuration';
+
+initStaticSecurityConfiguration(document.querySelector('#js-security-configuration-static'));
diff --git a/app/assets/javascripts/pages/projects/serverless/index.js b/app/assets/javascripts/pages/projects/serverless/index.js
index a883737ac9b..640301dd478 100644
--- a/app/assets/javascripts/pages/projects/serverless/index.js
+++ b/app/assets/javascripts/pages/projects/serverless/index.js
@@ -1,7 +1,5 @@
import ServerlessBundle from '~/serverless/serverless_bundle';
import initServerlessSurveyBanner from '~/serverless/survey_banner';
-document.addEventListener('DOMContentLoaded', () => {
- initServerlessSurveyBanner();
- new ServerlessBundle(); // eslint-disable-line no-new
-});
+initServerlessSurveyBanner();
+new ServerlessBundle(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/services/edit/index.js b/app/assets/javascripts/pages/projects/services/edit/index.js
index 04f3877ab48..8e603c5c1a2 100644
--- a/app/assets/javascripts/pages/projects/services/edit/index.js
+++ b/app/assets/javascripts/pages/projects/services/edit/index.js
@@ -1,7 +1,6 @@
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
-import CustomMetrics from '~/prometheus_metrics/custom_metrics';
import PrometheusAlerts from '~/prometheus_alerts';
-import initAlertsSettings from '~/alerts_service_settings';
+import CustomMetrics from '~/prometheus_metrics/custom_metrics';
document.addEventListener('DOMContentLoaded', () => {
const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
@@ -15,5 +14,4 @@ document.addEventListener('DOMContentLoaded', () => {
}
PrometheusAlerts();
- initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 1321155b7ec..be9259ec3ca 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -1,11 +1,12 @@
-import initSettingsPanels from '~/settings_panels';
+import initArtifactsSettings from '~/artifacts_settings';
import SecretValues from '~/behaviors/secret_values';
-import registrySettingsApp from '~/registry/settings/registry_settings_bundle';
+import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers';
import initVariableList from '~/ci_variable_list';
import initDeployFreeze from '~/deploy_freeze';
-import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers';
+import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_toggle';
-import initArtifactsSettings from '~/artifacts_settings';
+import registrySettingsApp from '~/registry/settings/registry_settings_bundle';
+import initSettingsPanels from '~/settings_panels';
document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
@@ -39,4 +40,6 @@ document.addEventListener('DOMContentLoaded', () => {
if (gon?.features?.vueifySharedRunnersToggle) {
initSharedRunnersToggle();
}
+
+ initInstallRunner();
});
diff --git a/app/assets/javascripts/pages/projects/settings/operations/show/index.js b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
index 153ccffd472..3a46241e2eb 100644
--- a/app/assets/javascripts/pages/projects/settings/operations/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js
@@ -1,9 +1,9 @@
-import mountErrorTrackingForm from '~/error_tracking_settings';
import mountAlertsSettings from '~/alerts_settings';
-import mountOperationSettings from '~/operation_settings';
+import mountErrorTrackingForm from '~/error_tracking_settings';
import mountGrafanaIntegration from '~/grafana_integration';
-import initSettingsPanels from '~/settings_panels';
import initIncidentsSettings from '~/incidents_settings';
+import mountOperationSettings from '~/operation_settings';
+import initSettingsPanels from '~/settings_panels';
initIncidentsSettings();
mountErrorTrackingForm();
diff --git a/app/assets/javascripts/pages/projects/settings/repository/form.js b/app/assets/javascripts/pages/projects/settings/repository/form.js
index eff45bad603..8d390c8586b 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/form.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/form.js
@@ -1,13 +1,13 @@
/* eslint-disable no-new */
-import ProtectedTagCreate from '~/protected_tags/protected_tag_create';
-import ProtectedTagEditList from '~/protected_tags/protected_tag_edit_list';
-import initSettingsPanels from '~/settings_panels';
import initDeployKeys from '~/deploy_keys';
-import ProtectedBranchCreate from '~/protected_branches/protected_branch_create';
-import ProtectedBranchEditList from '~/protected_branches/protected_branch_edit_list';
import DueDateSelectors from '~/due_date_select';
import fileUpload from '~/lib/utils/file_upload';
+import ProtectedBranchCreate from '~/protected_branches/protected_branch_create';
+import ProtectedBranchEditList from '~/protected_branches/protected_branch_edit_list';
+import ProtectedTagCreate from '~/protected_tags/protected_tag_create';
+import ProtectedTagEditList from '~/protected_tags/protected_tag_edit_list';
+import initSettingsPanels from '~/settings_panels';
export default () => {
new ProtectedTagCreate();
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index 1ef4b460263..e90954c14c5 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,5 +1,5 @@
-import initForm from '../form';
import MirrorRepos from '~/mirrors/mirror_repos';
+import initForm from '../form';
document.addEventListener('DOMContentLoaded', () => {
initForm();
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
index eee666bea05..d62df77ad2c 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
@@ -1,12 +1,11 @@
<script>
-import { GlIcon } from '@gitlab/ui';
-import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
+import { GlIcon, GlToggle } from '@gitlab/ui';
import { featureAccessLevelNone } from '../constants';
export default {
components: {
GlIcon,
- projectFeatureToggle,
+ GlToggle,
},
model: {
prop: 'value',
@@ -78,11 +77,11 @@ export default {
class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0"
>
<input v-if="name" :name="name" :value="value" type="hidden" />
- <project-feature-toggle
+ <gl-toggle
v-if="showToggle"
- class="gl-flex-grow-0 gl-mr-3"
+ class="gl-mr-3"
:value="featureEnabled"
- :disabled-input="disabledInput"
+ :disabled="disabledInput"
@change="toggleFeature"
/>
<div class="select-wrapper gl-flex-fill-1">
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 4af476fbd68..94a9bc168e5 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
@@ -1,11 +1,9 @@
<script>
-import { GlIcon, GlSprintf, GlLink, GlFormCheckbox } from '@gitlab/ui';
+import { GlIcon, GlSprintf, GlLink, GlFormCheckbox, GlToggle } from '@gitlab/ui';
import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin';
import { s__ } from '~/locale';
-import projectFeatureSetting from './project_feature_setting.vue';
-import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
-import projectSettingRow from './project_setting_row.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
visibilityOptions,
visibilityLevelDescriptions,
@@ -15,19 +13,20 @@ import {
featureAccessLevelNone,
} from '../constants';
import { toggleHiddenClassBySelector } from '../external';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import projectFeatureSetting from './project_feature_setting.vue';
+import projectSettingRow from './project_setting_row.vue';
const PAGE_FEATURE_ACCESS_LEVEL = s__('ProjectSettings|Everyone');
export default {
components: {
projectFeatureSetting,
- projectFeatureToggle,
projectSettingRow,
GlIcon,
GlSprintf,
GlLink,
GlFormCheckbox,
+ GlToggle,
},
mixins: [settingsMixin, glFeatureFlagsMixin()],
@@ -75,6 +74,11 @@ export default {
required: false,
default: false,
},
+ securityAndComplianceAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
visibilityHelpPath: {
type: String,
required: false,
@@ -141,6 +145,7 @@ export default {
metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
analyticsAccessLevel: featureAccessLevel.EVERYONE,
requirementsAccessLevel: featureAccessLevel.EVERYONE,
+ securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
operationsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true,
lfsEnabled: true,
@@ -218,11 +223,11 @@ export default {
repositoryHelpText() {
if (this.visibilityLevel === visibilityOptions.PRIVATE) {
- return s__('ProjectSettings|View and edit files in this project');
+ return s__('ProjectSettings|View and edit files in this project.');
}
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 will only have read access.',
);
},
},
@@ -264,6 +269,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.requirementsAccessLevel,
);
+ this.securityAndComplianceAccessLevel = Math.min(
+ featureAccessLevel.PROJECT_MEMBERS,
+ this.securityAndComplianceAccessLevel,
+ );
this.operationsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.operationsAccessLevel,
@@ -390,7 +399,7 @@ export default {
name="project[request_access_enabled]"
/>
<input v-model="requestAccessEnabled" type="checkbox" />
- {{ s__('ProjectSettings|Allow users to request access') }}
+ {{ s__('ProjectSettings|Users can request access') }}
</label>
</project-setting-row>
</div>
@@ -401,7 +410,7 @@ export default {
<project-setting-row
ref="issues-settings"
:label="s__('ProjectSettings|Issues')"
- :help-text="s__('ProjectSettings|Lightweight issue tracking system for this project')"
+ :help-text="s__('ProjectSettings|Lightweight issue tracking system.')"
>
<project-feature-setting
v-model="issuesAccessLevel"
@@ -424,7 +433,7 @@ export default {
<project-setting-row
ref="merge-request-settings"
:label="s__('ProjectSettings|Merge requests')"
- :help-text="s__('ProjectSettings|Submit changes to be merged upstream')"
+ :help-text="s__('ProjectSettings|Submit changes to be merged upstream.')"
>
<project-feature-setting
v-model="mergeRequestsAccessLevel"
@@ -436,9 +445,7 @@ export default {
<project-setting-row
ref="fork-settings"
:label="s__('ProjectSettings|Forks')"
- :help-text="
- s__('ProjectSettings|Allow users to make copies of your repository to a new project')
- "
+ :help-text="s__('ProjectSettings|Users can copy the repository to a new project.')"
>
<project-feature-setting
v-model="forkingAccessLevel"
@@ -450,7 +457,7 @@ export default {
<project-setting-row
ref="pipeline-settings"
:label="s__('ProjectSettings|Pipelines')"
- :help-text="s__('ProjectSettings|Build, test, and deploy your changes')"
+ :help-text="s__('ProjectSettings|Build, test, and deploy your changes.')"
>
<project-feature-setting
v-model="buildsAccessLevel"
@@ -475,9 +482,10 @@ export default {
)
}}
</div>
- <project-feature-toggle
+ <gl-toggle
v-model="containerRegistryEnabled"
- :disabled-input="!repositoryEnabled"
+ class="gl-my-2"
+ :disabled="!repositoryEnabled"
name="project[container_registry_enabled]"
/>
</project-setting-row>
@@ -487,19 +495,20 @@ export default {
:help-path="lfsHelpPath"
:label="s__('ProjectSettings|Git Large File Storage (LFS)')"
:help-text="
- s__('ProjectSettings|Manages large files such as audio, video, and graphics files')
+ s__('ProjectSettings|Manages large files such as audio, video, and graphics files.')
"
>
- <project-feature-toggle
+ <gl-toggle
v-model="lfsEnabled"
- :disabled-input="!repositoryEnabled"
+ class="gl-my-2"
+ :disabled="!repositoryEnabled"
name="project[lfs_enabled]"
/>
<p v-if="!lfsEnabled && lfsObjectsExist">
<gl-sprintf
:message="
s__(
- 'ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}',
+ 'ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}',
)
"
>
@@ -519,12 +528,13 @@ export default {
:help-path="packagesHelpPath"
:label="s__('ProjectSettings|Packages')"
:help-text="
- s__('ProjectSettings|Every project can have its own space to store its packages')
+ s__('ProjectSettings|Every project can have its own space to store its packages.')
"
>
- <project-feature-toggle
+ <gl-toggle
v-model="packagesEnabled"
- :disabled-input="!repositoryEnabled"
+ class="gl-my-2"
+ :disabled="!repositoryEnabled"
name="project[packages_enabled]"
/>
</project-setting-row>
@@ -532,7 +542,7 @@ export default {
<project-setting-row
ref="analytics-settings"
:label="s__('ProjectSettings|Analytics')"
- :help-text="s__('ProjectSettings|View project analytics')"
+ :help-text="s__('ProjectSettings|View project analytics.')"
>
<project-feature-setting
v-model="analyticsAccessLevel"
@@ -544,7 +554,7 @@ export default {
v-if="requirementsAvailable"
ref="requirements-settings"
:label="s__('ProjectSettings|Requirements')"
- :help-text="s__('ProjectSettings|Requirements management system for this project')"
+ :help-text="s__('ProjectSettings|Requirements management system.')"
>
<project-feature-setting
v-model="requirementsAccessLevel"
@@ -553,9 +563,20 @@ export default {
/>
</project-setting-row>
<project-setting-row
+ v-if="securityAndComplianceAvailable"
+ :label="s__('ProjectSettings|Security & Compliance')"
+ :help-text="s__('ProjectSettings|Security & Compliance for this project')"
+ >
+ <project-feature-setting
+ v-model="securityAndComplianceAccessLevel"
+ :options="featureAccessLevelOptions"
+ name="project[project_feature_attributes][security_and_compliance_access_level]"
+ />
+ </project-setting-row>
+ <project-setting-row
ref="wiki-settings"
:label="s__('ProjectSettings|Wiki')"
- :help-text="s__('ProjectSettings|Pages for project documentation')"
+ :help-text="s__('ProjectSettings|Pages for project documentation.')"
>
<project-feature-setting
v-model="wikiAccessLevel"
@@ -566,7 +587,7 @@ export default {
<project-setting-row
ref="snippet-settings"
:label="s__('ProjectSettings|Snippets')"
- :help-text="s__('ProjectSettings|Share code pastes with others out of Git repository')"
+ :help-text="s__('ProjectSettings|Share code with others outside the project.')"
>
<project-feature-setting
v-model="snippetsAccessLevel"
@@ -580,7 +601,7 @@ export default {
:help-path="pagesHelpPath"
:label="s__('ProjectSettings|Pages')"
:help-text="
- s__('ProjectSettings|With GitLab Pages you can host your static websites on GitLab')
+ s__('ProjectSettings|With GitLab Pages you can host your static websites on GitLab.')
"
>
<project-feature-setting
@@ -592,7 +613,7 @@ export default {
<project-setting-row
ref="operations-settings"
:label="s__('ProjectSettings|Operations')"
- :help-text="s__('ProjectSettings|Environments, logs, cluster management, and more')"
+ :help-text="s__('ProjectSettings|Environments, logs, cluster management, and more.')"
>
<project-feature-setting
v-model="operationsAccessLevel"
@@ -604,11 +625,7 @@ export default {
<project-setting-row
ref="metrics-visibility-settings"
:label="__('Metrics Dashboard')"
- :help-text="
- s__(
- 'ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics',
- )
- "
+ :help-text="s__('ProjectSettings|Visualize the project\'s performance metrics.')"
>
<project-feature-setting
v-model="metricsDashboardAccessLevel"
@@ -626,9 +643,7 @@ export default {
{{ s__('ProjectSettings|Disable email notifications') }}
</label>
<span class="form-text text-muted">{{
- s__(
- 'ProjectSettings|This setting will override user notification preferences for all project members.',
- )
+ s__('ProjectSettings|Override user notification preferences for all project members.')
}}</span>
</project-setting-row>
<project-setting-row class="mb-3">
@@ -644,7 +659,7 @@ export default {
{{ s__('ProjectSettings|Show default award emojis') }}
<template #help>{{
s__(
- 'ProjectSettings|When enabled, issues, merge requests, and snippets will always show thumbs-up and thumbs-down award emoji buttons.',
+ 'ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets.',
)
}}</template>
</gl-form-checkbox>
@@ -662,9 +677,7 @@ export default {
<gl-form-checkbox v-model="allowEditingCommitMessages">
{{ s__('ProjectSettings|Allow editing commit messages') }}
<template #help>{{
- s__(
- 'ProjectSettings|When enabled, commit authors will be able to edit commit messages on unprotected branches.',
- )
+ s__('ProjectSettings|Commit authors can edit commit messages on unprotected branches.')
}}</template>
</gl-form-checkbox>
</project-setting-row>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js b/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js
index ae0936417ad..b52e30dae39 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js
@@ -3,6 +3,7 @@ export default {
return {
packagesEnabled: false,
requirementsEnabled: false,
+ securityAndComplianceEnabled: false,
};
},
watch: {
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index cc676b98e49..0494dad6e33 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -1,17 +1,17 @@
import initTree from 'ee_else_ce/repository';
-import { initUploadForm } from '~/blob_edit/blob_bundle';
+import Activities from '~/activities';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import NotificationsForm from '~/notifications_form';
-import UserCallout from '~/user_callout';
import BlobViewer from '~/blob/viewer/index';
-import Activities from '~/activities';
-import initReadMore from '~/read_more';
+import { initUploadForm } from '~/blob_edit/blob_bundle';
+import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import leaveByUrl from '~/namespaces/leave_by_url';
-import Star from '../../../star';
+import initVueNotificationsDropdown from '~/notifications';
+import NotificationsForm from '~/notifications_form';
+import initReadMore from '~/read_more';
+import UserCallout from '~/user_callout';
import notificationsDropdown from '../../../notifications_dropdown';
-import { showLearnGitLabProjectPopover } from '~/onboarding_issues';
-import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
-import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
+import Star from '../../../star';
initReadMore();
new Star(); // eslint-disable-line no-new
@@ -40,9 +40,14 @@ if (document.querySelector('.project-show-activity')) {
leaveByUrl('project');
-showLearnGitLabProjectPopover();
+if (gon.features?.vueNotificationDropdown) {
+ initVueNotificationsDropdown();
+} else {
+ notificationsDropdown();
+}
+
+initVueNotificationsDropdown();
-notificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new
initInviteMembersTrigger();
diff --git a/app/assets/javascripts/pages/projects/tags/index/index.js b/app/assets/javascripts/pages/projects/tags/index/index.js
index 96e52850936..98560c1193b 100644
--- a/app/assets/javascripts/pages/projects/tags/index/index.js
+++ b/app/assets/javascripts/pages/projects/tags/index/index.js
@@ -1,9 +1,7 @@
import { initRemoveTag } from '../remove_tag';
-document.addEventListener('DOMContentLoaded', () => {
- initRemoveTag({
- onDelete: (path) => {
- document.querySelector(`[data-path="${path}"]`).closest('.js-tag-list').remove();
- },
- });
+initRemoveTag({
+ onDelete: (path) => {
+ document.querySelector(`[data-path="${path}"]`).closest('.js-tag-list').remove();
+ },
});
diff --git a/app/assets/javascripts/pages/projects/tags/new/index.js b/app/assets/javascripts/pages/projects/tags/new/index.js
index b3158f7e939..11a19a673b1 100644
--- a/app/assets/javascripts/pages/projects/tags/new/index.js
+++ b/app/assets/javascripts/pages/projects/tags/new/index.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
+import GLForm from '../../../../gl_form';
import RefSelectDropdown from '../../../../ref_select_dropdown';
import ZenMode from '../../../../zen_mode';
-import GLForm from '../../../../gl_form';
document.addEventListener('DOMContentLoaded', () => {
new ZenMode(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/tags/releases/index.js b/app/assets/javascripts/pages/projects/tags/releases/index.js
index d6afc71fb03..abdc97f62d0 100644
--- a/app/assets/javascripts/pages/projects/tags/releases/index.js
+++ b/app/assets/javascripts/pages/projects/tags/releases/index.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import ZenMode from '~/zen_mode';
import GLForm from '~/gl_form';
+import ZenMode from '~/zen_mode';
document.addEventListener('DOMContentLoaded', () => {
new ZenMode(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/tags/remove_tag.js b/app/assets/javascripts/pages/projects/tags/remove_tag.js
index 7e83dbe0565..7b95560df7b 100644
--- a/app/assets/javascripts/pages/projects/tags/remove_tag.js
+++ b/app/assets/javascripts/pages/projects/tags/remove_tag.js
@@ -1,6 +1,6 @@
+import initConfirmModal from '~/confirm_modal';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import initConfirmModal from '~/confirm_modal';
export const initRemoveTag = ({ onDelete = () => {} }) => {
return initConfirmModal({
diff --git a/app/assets/javascripts/pages/projects/tags/show/index.js b/app/assets/javascripts/pages/projects/tags/show/index.js
index 651cc05ca4f..6f5406f554f 100644
--- a/app/assets/javascripts/pages/projects/tags/show/index.js
+++ b/app/assets/javascripts/pages/projects/tags/show/index.js
@@ -1,10 +1,8 @@
import { redirectTo, getBaseURL, stripFinalUrlSegment } from '~/lib/utils/url_utility';
import { initRemoveTag } from '../remove_tag';
-document.addEventListener('DOMContentLoaded', () => {
- initRemoveTag({
- onDelete: (path = '') => {
- redirectTo(stripFinalUrlSegment([getBaseURL(), path].join('')));
- },
- });
+initRemoveTag({
+ onDelete: (path = '') => {
+ redirectTo(stripFinalUrlSegment([getBaseURL(), path].join('')));
+ },
});
diff --git a/app/assets/javascripts/pages/projects/wikis/index.js b/app/assets/javascripts/pages/projects/wikis/index.js
index 9c75531ca40..dead61cf358 100644
--- a/app/assets/javascripts/pages/projects/wikis/index.js
+++ b/app/assets/javascripts/pages/projects/wikis/index.js
@@ -1,3 +1,3 @@
import initWikis from '~/pages/shared/wikis';
-document.addEventListener('DOMContentLoaded', initWikis);
+initWikis();
diff --git a/app/assets/javascripts/pages/registrations/new/index.js b/app/assets/javascripts/pages/registrations/new/index.js
index a33d11f3613..4104025aa59 100644
--- a/app/assets/javascripts/pages/registrations/new/index.js
+++ b/app/assets/javascripts/pages/registrations/new/index.js
@@ -1,6 +1,6 @@
+import NoEmojiValidator from '~/emoji/no_emoji_validator';
import LengthValidator from '~/pages/sessions/new/length_validator';
import UsernameValidator from '~/pages/sessions/new/username_validator';
-import NoEmojiValidator from '~/emoji/no_emoji_validator';
document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/search/show/index.js b/app/assets/javascripts/pages/search/show/index.js
index b6171e08e01..a8c288c3663 100644
--- a/app/assets/javascripts/pages/search/show/index.js
+++ b/app/assets/javascripts/pages/search/show/index.js
@@ -1,7 +1,5 @@
-import Search from './search';
import { initSearchApp } from '~/search';
document.addEventListener('DOMContentLoaded', () => {
- initSearchApp(); // Vue Bootstrap
- return new Search(); // Legacy Search Methods
+ initSearchApp();
});
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
deleted file mode 100644
index cbef5ab1bbc..00000000000
--- a/app/assets/javascripts/pages/search/show/search.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import $ from 'jquery';
-import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
-import Project from '~/pages/projects/project';
-import { visitUrl } from '~/lib/utils/url_utility';
-import refreshCounts from './refresh_counts';
-
-export default class Search {
- constructor() {
- this.searchInput = '.js-search-input';
- this.searchClear = '.js-search-clear';
-
- setHighlightClass(); // Code Highlighting
- this.eventListeners(); // Search Form Actions
- refreshCounts(); // Other Scope Tab Counts
- Project.initRefSwitcher(); // Code Search Branch Picker
- }
-
- eventListeners() {
- $(document).off('keyup', this.searchInput).on('keyup', this.searchInput, this.searchKeyUp);
- $(document)
- .off('click', this.searchClear)
- .on('click', this.searchClear, this.clearSearchField.bind(this));
-
- $('a.js-search-clear').off('click', this.clearSearchFilter).on('click', this.clearSearchFilter);
- }
-
- static submitSearch() {
- return $('.js-search-form').submit();
- }
-
- searchKeyUp() {
- const $input = $(this);
- if ($input.val() === '') {
- $('.js-search-clear').addClass('hidden');
- } else {
- $('.js-search-clear').removeClass('hidden');
- }
- }
-
- clearSearchField() {
- return $(this.searchInput).val('').trigger('keyup').focus();
- }
-
- // We need to manually follow the link on the anchors
- // that have this event bound, as their `click` default
- // behavior is prevented by the toggle logic.
- /* eslint-disable-next-line class-methods-use-this */
- clearSearchFilter(ev) {
- const $target = $(ev.currentTarget);
-
- visitUrl($target.href);
- ev.stopPropagation();
- }
-}
diff --git a/app/assets/javascripts/pages/sessions/new/index.js b/app/assets/javascripts/pages/sessions/new/index.js
index 55bc93a2b13..d39f56cfd03 100644
--- a/app/assets/javascripts/pages/sessions/new/index.js
+++ b/app/assets/javascripts/pages/sessions/new/index.js
@@ -1,10 +1,10 @@
import $ from 'jquery';
-import LengthValidator from './length_validator';
-import UsernameValidator from './username_validator';
import NoEmojiValidator from '../../../emoji/no_emoji_validator';
-import SigninTabsMemoizer from './signin_tabs_memoizer';
+import LengthValidator from './length_validator';
import OAuthRememberMe from './oauth_remember_me';
import preserveUrlFragment from './preserve_url_fragment';
+import SigninTabsMemoizer from './signin_tabs_memoizer';
+import UsernameValidator from './username_validator';
document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js
index f3b0948a40d..338fe1b66f2 100644
--- a/app/assets/javascripts/pages/sessions/new/username_validator.js
+++ b/app/assets/javascripts/pages/sessions/new/username_validator.js
@@ -1,9 +1,9 @@
import { debounce } from 'lodash';
-import InputValidator from '~/validators/input_validator';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import InputValidator from '~/validators/input_validator';
const debounceTimeoutDuration = 1000;
const rootUrl = gon.relative_url_root;
diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
new file mode 100644
index 00000000000..51028e585b8
--- /dev/null
+++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js
@@ -0,0 +1,32 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import InstallRunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+
+Vue.use(VueApollo);
+
+export function initInstallRunner(componentId = 'js-install-runner') {
+ const installRunnerEl = document.getElementById(componentId);
+
+ if (installRunnerEl) {
+ const defaultClient = createDefaultClient();
+ const { projectPath, groupPath } = installRunnerEl.dataset;
+
+ const apolloProvider = new VueApollo({
+ defaultClient,
+ });
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: installRunnerEl,
+ apolloProvider,
+ provide: {
+ projectPath,
+ groupPath,
+ },
+ render(createElement) {
+ return createElement(InstallRunnerInstructions);
+ },
+ });
+ }
+}
diff --git a/app/assets/javascripts/pages/shared/wikis/index.js b/app/assets/javascripts/pages/shared/wikis/index.js
index 5e23b9bab4e..c8dc75828e4 100644
--- a/app/assets/javascripts/pages/shared/wikis/index.js
+++ b/app/assets/javascripts/pages/shared/wikis/index.js
@@ -1,12 +1,12 @@
import $ from 'jquery';
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import csrf from '~/lib/utils/csrf';
import ShortcutsWiki from '~/behaviors/shortcuts/shortcuts_wiki';
-import Wikis from './wikis';
-import ZenMode from '../../../zen_mode';
+import csrf from '~/lib/utils/csrf';
+import Translate from '~/vue_shared/translate';
import GLForm from '../../../gl_form';
+import ZenMode from '../../../zen_mode';
import deleteWikiModal from './components/delete_wiki_modal.vue';
+import Wikis from './wikis';
export default () => {
new Wikis(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 149e666256b..3ff455fad32 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -1,11 +1,11 @@
-import $ from 'jquery';
-import { last } from 'lodash';
import { scaleLinear, scaleThreshold } from 'd3-scale';
import { select } from 'd3-selection';
import dateFormat from 'dateformat';
-import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
-import axios from '~/lib/utils/axios_utils';
+import $ from 'jquery';
+import { last } from 'lodash';
import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
import { n__, s__, __ } from '~/locale';
const d3 = { select, scaleLinear, scaleThreshold };
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index 7c88aa53e4b..80e14842f51 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -1,9 +1,9 @@
-import $ from 'jquery';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import axios from '~/lib/utils/axios_utils';
+import $ from 'jquery';
import Activities from '~/activities';
-import { localTimeAgo } from '~/lib/utils/datetime_utility';
import AjaxCache from '~/lib/utils/ajax_cache';
+import axios from '~/lib/utils/axios_utils';
+import { localTimeAgo } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
import ActivityCalendar from './activity_calendar';
import UserOverviewBlock from './user_overview_block';
@@ -141,7 +141,15 @@ export default class UserTabs {
this.loadOverviewTab();
}
- const loadableActions = ['groups', 'contributed', 'projects', 'starred', 'snippets'];
+ const loadableActions = [
+ 'groups',
+ 'contributed',
+ 'projects',
+ 'starred',
+ 'snippets',
+ 'followers',
+ 'following',
+ ];
if (loadableActions.indexOf(action) > -1) {
this.loadTab(action, endpoint);
}
diff --git a/app/assets/javascripts/performance_bar/components/add_request.vue b/app/assets/javascripts/performance_bar/components/add_request.vue
index 54bca8a1b67..d48a5acb85c 100644
--- a/app/assets/javascripts/performance_bar/components/add_request.vue
+++ b/app/assets/javascripts/performance_bar/components/add_request.vue
@@ -27,7 +27,7 @@ export default {
<div id="peek-view-add-request" class="view">
<form class="form-inline" @submit.prevent>
<button
- class="btn-blank btn-link bold"
+ class="btn-blank btn-link bold gl-text-blue-300"
type="button"
:title="__(`Add request manually`)"
@click="toggleInput"
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index 930c5e50511..de4bbb36141 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlIcon, GlModal, GlModalDirective } from '@gitlab/ui';
+import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import RequestWarning from './request_warning.vue';
export default {
@@ -7,7 +7,6 @@ export default {
RequestWarning,
GlButton,
GlModal,
- GlIcon,
},
directives: {
'gl-modal': GlModalDirective,
@@ -94,10 +93,10 @@ export default {
data-qa-selector="detailed_metric_content"
>
<gl-button v-gl-modal="modalId" class="gl-mr-2" type="button" variant="link">
- {{ metricDetailsLabel }}
+ <span class="gl-text-blue-300 gl-font-weight-bold">{{ metricDetailsLabel }}</span>
</gl-button>
- <gl-modal :modal-id="modalId" :title="header" size="lg" modal-class="gl-mt-7" scrollable>
- <table class="table">
+ <gl-modal :modal-id="modalId" :title="header" size="lg" footer-class="d-none" scrollable>
+ <table class="table gl-table">
<template v-if="detailsList.length">
<tr v-for="(item, index) in detailsList" :key="index">
<td>
@@ -116,14 +115,16 @@ export default {
{{ item[key] }}
<gl-button
v-if="keyIndex == 0 && item.backtrace"
- class="gl-ml-3"
+ class="gl-ml-3 button-ellipsis-horizontal"
data-testid="backtrace-expand-btn"
- type="button"
+ category="primary"
+ variant="default"
+ icon="ellipsis_h"
+ size="small"
+ :selected="itemHasOpenedBacktrace(index)"
:aria-label="__('Toggle backtrace')"
@click="toggleBacktrace(index)"
- >
- <gl-icon :size="12" name="ellipsis_h" />
- </gl-button>
+ />
</div>
<pre v-if="itemHasOpenedBacktrace(index)" class="backtrace-row mt-2">{{
item.backtrace
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 e38771785b7..85789cd1fdf 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -2,10 +2,10 @@
/* eslint-disable vue/no-v-html */
import { glEmojiTag } from '~/emoji';
+import { s__ } from '~/locale';
import AddRequest from './add_request.vue';
import DetailedMetric from './detailed_metric.vue';
import RequestSelector from './request_selector.vue';
-import { s__ } from '~/locale';
export default {
components: {
@@ -64,6 +64,11 @@ export default {
keys: ['request', 'body'],
},
{
+ metric: 'external-http',
+ header: s__('PerformanceBar|External Http calls'),
+ keys: ['label', 'code', 'proxy', 'error'],
+ },
+ {
metric: 'total',
header: s__('PerformanceBar|Frontend resources'),
keys: ['name', 'size'],
@@ -120,7 +125,7 @@ export default {
<div id="js-peek" :class="env">
<div
v-if="currentRequest"
- class="d-flex container-fluid container-limited"
+ class="d-flex container-fluid container-limited justify-content-center"
data-qa-selector="performance_bar"
>
<div id="peek-view-host" class="view">
@@ -147,11 +152,15 @@ export default {
id="peek-view-trace"
class="view"
>
- <a :href="currentRequest.details.tracing.tracing_url">{{ s__('PerformanceBar|trace') }}</a>
+ <a class="gl-text-blue-300" :href="currentRequest.details.tracing.tracing_url">{{
+ s__('PerformanceBar|trace')
+ }}</a>
</div>
<add-request v-on="$listeners" />
<div v-if="currentRequest.details" id="peek-download" class="view">
- <a :download="downloadName" :href="downloadPath">{{ s__('PerformanceBar|Download') }}</a>
+ <a class="gl-text-blue-300" :download="downloadName" :href="downloadPath">{{
+ s__('PerformanceBar|Download')
+ }}</a>
</div>
<request-selector
v-if="currentRequest"
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index 0d5c294ea56..522e34753e9 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -1,13 +1,12 @@
/* eslint-disable @gitlab/require-i18n-strings */
import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
import axios from '~/lib/utils/axios_utils';
+import Translate from '~/vue_shared/translate';
+import initPerformanceBarLog from './performance_bar_log';
import PerformanceBarService from './services/performance_bar_service';
import PerformanceBarStore from './stores/performance_bar_store';
-import initPerformanceBarLog from './performance_bar_log';
-
Vue.use(Translate);
const initPerformanceBar = (el) => {
diff --git a/app/assets/javascripts/performance_bar/performance_bar_log.js b/app/assets/javascripts/performance_bar/performance_bar_log.js
index c61b0cb32e8..aad99e2604e 100644
--- a/app/assets/javascripts/performance_bar/performance_bar_log.js
+++ b/app/assets/javascripts/performance_bar/performance_bar_log.js
@@ -43,7 +43,7 @@ const logUserTimingMetrics = () => {
const initPerformanceBarLog = () => {
console.log(
`%c ${String.fromCodePoint(0x1f98a)} GitLab performance bar`,
- 'width:100%;background-color: #292961; color: #FFFFFF; font-size:24px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto; padding: 10px;display:block;padding-right: 100px;',
+ 'width:100%; background-color: #292961; color: #FFFFFF; padding: 10px; display:block;',
);
initVitalsLog();
diff --git a/app/assets/javascripts/performance_bar/services/performance_bar_service.js b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
index 38255b3a37d..a614342c858 100644
--- a/app/assets/javascripts/performance_bar/services/performance_bar_service.js
+++ b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
@@ -1,5 +1,5 @@
-import axios from '../../lib/utils/axios_utils';
import { parseBoolean } from '~/lib/utils/common_utils';
+import axios from '../../lib/utils/axios_utils';
export default class PerformanceBarService {
static interceptor = null;
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
index db42966d159..e845c8b9df4 100644
--- a/app/assets/javascripts/persistent_user_callout.js
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -1,7 +1,7 @@
-import { parseBoolean } from './lib/utils/common_utils';
+import { deprecatedCreateFlash as Flash } from './flash';
import axios from './lib/utils/axios_utils';
+import { parseBoolean } from './lib/utils/common_utils';
import { __ } from './locale';
-import { deprecatedCreateFlash as Flash } from './flash';
const DEFERRED_LINK_CLASS = 'deferred-link';
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
new file mode 100644
index 00000000000..b40c9a48903
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
@@ -0,0 +1,114 @@
+<script>
+import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
+import { __, s__, sprintf } from '~/locale';
+import { COMMIT_FAILURE, COMMIT_SUCCESS } from '../../constants';
+import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql';
+import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
+
+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.'),
+ [COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
+ },
+ i18n: {
+ defaultCommitMessage: __('Update %{sourcePath} file'),
+ },
+ components: {
+ CommitForm,
+ },
+ inject: ['projectFullPath', 'ciConfigPath', 'defaultBranch', 'newMergeRequestPath'],
+ props: {
+ ciFileContent: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ commit: {},
+ isSaving: false,
+ };
+ },
+ apollo: {
+ commitSha: {
+ query: getCommitSha,
+ },
+ },
+ computed: {
+ defaultCommitMessage() {
+ return sprintf(this.$options.i18n.defaultCommitMessage, { sourcePath: this.ciConfigPath });
+ },
+ },
+ methods: {
+ redirectToNewMergeRequest(sourceBranch) {
+ const url = mergeUrlParams(
+ {
+ [MR_SOURCE_BRANCH]: sourceBranch,
+ [MR_TARGET_BRANCH]: this.defaultBranch,
+ },
+ this.newMergeRequestPath,
+ );
+ redirectTo(url);
+ },
+ async onCommitSubmit({ message, branch, openMergeRequest }) {
+ this.isSaving = true;
+
+ try {
+ const {
+ data: {
+ commitCreate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: commitCIFile,
+ variables: {
+ projectPath: this.projectFullPath,
+ branch,
+ startBranch: this.defaultBranch,
+ message,
+ filePath: this.ciConfigPath,
+ content: this.ciFileContent,
+ lastCommitId: this.commitSha,
+ },
+ update(store, { data }) {
+ const commitSha = data?.commitCreate?.commit?.sha;
+
+ if (commitSha) {
+ store.writeQuery({ query: getCommitSha, data: { commitSha } });
+ }
+ },
+ });
+
+ if (errors?.length) {
+ this.$emit('showError', { type: COMMIT_FAILURE, reasons: errors });
+ } else if (openMergeRequest) {
+ this.redirectToNewMergeRequest(branch);
+ } else {
+ this.$emit('commit', { type: COMMIT_SUCCESS });
+ }
+ } catch (error) {
+ this.$emit('showError', { type: COMMIT_FAILURE, reasons: [error?.message] });
+ } finally {
+ this.isSaving = false;
+ }
+ },
+ onCommitCancel() {
+ this.$emit('resetContent');
+ },
+ },
+};
+</script>
+
+<template>
+ <commit-form
+ :default-branch="defaultBranch"
+ :default-message="defaultCommitMessage"
+ :is-saving="isSaving"
+ @cancel="onCommitCancel"
+ @submit="onCommitSubmit"
+ />
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
new file mode 100644
index 00000000000..007faa4ed0d
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
@@ -0,0 +1,100 @@
+<script>
+import { GlAlert, GlIcon } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { __, s__ } from '~/locale';
+import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
+import { DEFAULT, INVALID_CI_CONFIG } from '~/pipelines/constants';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
+
+export default {
+ i18n: {
+ viewOnlyMessage: s__('Pipelines|Merged YAML is view only'),
+ },
+ errorTexts: {
+ [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'),
+ [DEFAULT]: __('An unknown error occurred.'),
+ },
+ components: {
+ EditorLite,
+ GlAlert,
+ GlIcon,
+ },
+ inject: ['ciConfigPath'],
+ props: {
+ ciConfigData: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ failureType: null,
+ };
+ },
+ computed: {
+ failure() {
+ switch (this.failureType) {
+ case INVALID_CI_CONFIG:
+ return this.$options.errorTexts[INVALID_CI_CONFIG];
+ default:
+ return this.$options.errorTexts[DEFAULT];
+ }
+ },
+ fileGlobalId() {
+ return `${this.ciConfigPath}-${uniqueId()}`;
+ },
+ hasError() {
+ return this.failureType;
+ },
+ isInvalidConfiguration() {
+ return this.ciConfigData.status === CI_CONFIG_STATUS_INVALID;
+ },
+ mergedYaml() {
+ return this.ciConfigData.mergedYaml;
+ },
+ },
+ watch: {
+ ciConfigData: {
+ immediate: true,
+ handler() {
+ if (this.isInvalidConfiguration) {
+ this.reportFailure(INVALID_CI_CONFIG);
+ } else if (this.hasError) {
+ this.resetFailure();
+ }
+ },
+ },
+ },
+ methods: {
+ reportFailure(errorType) {
+ this.failureType = errorType;
+ },
+ resetFailure() {
+ this.failureType = null;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-alert v-if="hasError" variant="danger" :dismissible="false">
+ {{ failure }}
+ </gl-alert>
+ <div v-else>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon :size="18" name="lock" class="gl-text-gray-500 gl-mr-3" />
+ {{ $options.i18n.viewOnlyMessage }}
+ </div>
+ <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1">
+ <editor-lite
+ ref="editor"
+ :value="mergedYaml"
+ :file-name="ciConfigPath"
+ :file-global-id="fileGlobalId"
+ :editor-options="{ readOnly: true }"
+ v-on="$listeners"
+ />
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
new file mode 100644
index 00000000000..872da88d3e6
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
@@ -0,0 +1,52 @@
+<script>
+import { EDITOR_READY_EVENT } from '~/editor/constants';
+import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
+
+export default {
+ components: {
+ EditorLite,
+ },
+ inject: ['ciConfigPath', 'projectPath', 'projectNamespace'],
+ inheritAttrs: false,
+ data() {
+ return {
+ commitSha: '',
+ };
+ },
+ apollo: {
+ commitSha: {
+ query: getCommitSha,
+ },
+ },
+ methods: {
+ onCiConfigUpdate(content) {
+ this.$emit('updateCiConfig', content);
+ },
+ registerCiSchema() {
+ const editorInstance = this.$refs.editor.getEditor();
+
+ editorInstance.use(new CiSchemaExtension());
+ editorInstance.registerCiSchema({
+ projectPath: this.projectPath,
+ projectNamespace: this.projectNamespace,
+ ref: this.commitSha,
+ });
+ },
+ },
+ readyEvent: EDITOR_READY_EVENT,
+};
+</script>
+<template>
+ <div class="gl-border-solid gl-border-gray-100 gl-border-1">
+ <editor-lite
+ ref="editor"
+ :file-name="ciConfigPath"
+ v-bind="$attrs"
+ @[$options.readyEvent]="registerCiSchema"
+ @input="onCiConfigUpdate"
+ v-on="$listeners"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
new file mode 100644
index 00000000000..ab41c0170e9
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
@@ -0,0 +1,30 @@
+<script>
+import ValidationSegment from './validation_segment.vue';
+
+export default {
+ validationSegmentClasses:
+ 'gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base',
+ components: {
+ ValidationSegment,
+ },
+ props: {
+ ciConfigData: {
+ type: Object,
+ required: true,
+ },
+ isCiConfigDataLoading: {
+ type: Boolean,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-mb-5">
+ <validation-segment
+ :class="$options.validationSegmentClasses"
+ :loading="isCiConfigDataLoading"
+ :ci-config="ciConfigData"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
new file mode 100644
index 00000000000..94fb3a66fdd
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
@@ -0,0 +1,84 @@
+<script>
+import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import { CI_CONFIG_STATUS_VALID } from '../../constants';
+
+export const i18n = {
+ learnMore: __('Learn more'),
+ loading: s__('Pipelines|Validating GitLab CI configuration…'),
+ invalid: s__('Pipelines|This GitLab CI configuration is invalid.'),
+ invalidWithReason: s__('Pipelines|This GitLab CI configuration is invalid: %{reason}.'),
+ valid: s__('Pipelines|This GitLab CI configuration is valid.'),
+};
+
+export default {
+ i18n,
+ components: {
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ TooltipOnTruncate,
+ },
+ inject: {
+ ymlHelpPagePath: {
+ default: '',
+ },
+ },
+ props: {
+ ciConfig: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ isValid() {
+ return this.ciConfig?.status === CI_CONFIG_STATUS_VALID;
+ },
+ icon() {
+ if (this.isValid) {
+ return 'check';
+ }
+ return 'warning-solid';
+ },
+ message() {
+ if (this.isValid) {
+ return this.$options.i18n.valid;
+ }
+
+ // Only display first error as a reason
+ const [reason] = this.ciConfig?.errors || [];
+ if (reason) {
+ return sprintf(this.$options.i18n.invalidWithReason, { reason }, false);
+ }
+ return this.$options.i18n.invalid;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <template v-if="loading">
+ <gl-loading-icon inline />
+ {{ $options.i18n.loading }}
+ </template>
+
+ <span v-else class="gl-display-inline-flex gl-white-space-nowrap gl-max-w-full">
+ <tooltip-on-truncate :title="message" class="gl-text-truncate">
+ <gl-icon :name="icon" /> <span data-testid="validationMsg">{{ message }}</span>
+ </tooltip-on-truncate>
+ <span class="gl-flex-shrink-0 gl-pl-2">
+ <gl-link data-testid="learnMoreLink" :href="ymlHelpPagePath">
+ {{ $options.i18n.learnMore }}
+ </gl-link>
+ </span>
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue
deleted file mode 100644
index 22f378c571a..00000000000
--- a/app/assets/javascripts/pipeline_editor/components/info/validation_segment.vue
+++ /dev/null
@@ -1,84 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-import { CI_CONFIG_STATUS_VALID } from '../../constants';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
-
-export const i18n = {
- learnMore: __('Learn more'),
- loading: s__('Pipelines|Validating GitLab CI configuration…'),
- invalid: s__('Pipelines|This GitLab CI configuration is invalid.'),
- invalidWithReason: s__('Pipelines|This GitLab CI configuration is invalid: %{reason}.'),
- valid: s__('Pipelines|This GitLab CI configuration is valid.'),
-};
-
-export default {
- i18n,
- components: {
- GlIcon,
- GlLink,
- GlLoadingIcon,
- TooltipOnTruncate,
- },
- inject: {
- ymlHelpPagePath: {
- default: '',
- },
- },
- props: {
- ciConfig: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- loading: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- isValid() {
- return this.ciConfig?.status === CI_CONFIG_STATUS_VALID;
- },
- icon() {
- if (this.isValid) {
- return 'check';
- }
- return 'warning-solid';
- },
- message() {
- if (this.isValid) {
- return this.$options.i18n.valid;
- }
-
- // Only display first error as a reason
- const [reason] = this.ciConfig?.errors || [];
- if (reason) {
- return sprintf(this.$options.i18n.invalidWithReason, { reason }, false);
- }
- return this.$options.i18n.invalid;
- },
- },
-};
-</script>
-
-<template>
- <div>
- <template v-if="loading">
- <gl-loading-icon inline />
- {{ $options.i18n.loading }}
- </template>
-
- <span v-else class="gl-display-inline-flex gl-white-space-nowrap gl-max-w-full">
- <tooltip-on-truncate :title="message" class="gl-text-truncate">
- <gl-icon :name="icon" /> <span data-testid="validationMsg">{{ message }}</span>
- </tooltip-on-truncate>
- <span class="gl-flex-shrink-0 gl-pl-2">
- <gl-link data-testid="learnMoreLink" :href="ymlHelpPagePath">
- {{ $options.i18n.learnMore }}
- </gl-link>
- </span>
- </span>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
index 58a96c3f725..5d9697c9427 100644
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
@@ -1,9 +1,9 @@
<script>
import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
-import CiLintWarnings from './ci_lint_warnings.vue';
-import CiLintResultsValue from './ci_lint_results_value.vue';
-import CiLintResultsParam from './ci_lint_results_param.vue';
import { __ } from '~/locale';
+import CiLintResultsParam from './ci_lint_results_param.vue';
+import CiLintResultsValue from './ci_lint_results_value.vue';
+import CiLintWarnings from './ci_lint_warnings.vue';
const thBorderColor = 'gl-border-gray-100!';
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue
index 23808bcb292..49225a7cac7 100644
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue
@@ -1,6 +1,6 @@
<script>
-import { __ } from '~/locale';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { __ } from '~/locale';
export default {
props: {
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
new file mode 100644
index 00000000000..3bdcf383bee
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -0,0 +1,121 @@
+<script>
+import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import {
+ CI_CONFIG_STATUS_INVALID,
+ CREATE_TAB,
+ LINT_TAB,
+ MERGED_TAB,
+ VISUALIZE_TAB,
+} from '../constants';
+import CiConfigMergedPreview from './editor/ci_config_merged_preview.vue';
+import TextEditor from './editor/text_editor.vue';
+import CiLint from './lint/ci_lint.vue';
+import EditorTab from './ui/editor_tab.vue';
+
+export default {
+ i18n: {
+ tabEdit: s__('Pipelines|Write pipeline configuration'),
+ tabGraph: s__('Pipelines|Visualize'),
+ tabLint: s__('Pipelines|Lint'),
+ tabMergedYaml: s__('Pipelines|View merged YAML'),
+ },
+ errorTexts: {
+ loadMergedYaml: s__('Pipelines|Could not load merged YAML content'),
+ },
+ tabConstants: {
+ CREATE_TAB,
+ LINT_TAB,
+ MERGED_TAB,
+ VISUALIZE_TAB,
+ },
+ components: {
+ CiConfigMergedPreview,
+ CiLint,
+ EditorTab,
+ GlAlert,
+ GlLoadingIcon,
+ GlTab,
+ GlTabs,
+ PipelineGraph,
+ TextEditor,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ ciConfigData: {
+ type: Object,
+ required: true,
+ },
+ ciFileContent: {
+ type: String,
+ required: true,
+ },
+ isCiConfigDataLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ hasMergedYamlLoadError() {
+ return (
+ !this.ciConfigData?.mergedYaml && this.ciConfigData.status !== CI_CONFIG_STATUS_INVALID
+ );
+ },
+ },
+ methods: {
+ setCurrentTab(tabName) {
+ this.$emit('set-current-tab', tabName);
+ },
+ },
+};
+</script>
+<template>
+ <gl-tabs class="file-editor gl-mb-3">
+ <editor-tab
+ class="gl-mb-3"
+ :title="$options.i18n.tabEdit"
+ lazy
+ data-testid="editor-tab"
+ @click="setCurrentTab($options.tabConstants.CREATE_TAB)"
+ >
+ <text-editor :value="ciFileContent" v-on="$listeners" />
+ </editor-tab>
+ <gl-tab
+ v-if="glFeatures.ciConfigVisualizationTab"
+ class="gl-mb-3"
+ :title="$options.i18n.tabGraph"
+ lazy
+ data-testid="visualization-tab"
+ @click="setCurrentTab($options.tabConstants.VISUALIZE_TAB)"
+ >
+ <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
+ <pipeline-graph v-else :pipeline-data="ciConfigData" />
+ </gl-tab>
+ <editor-tab
+ class="gl-mb-3"
+ :title="$options.i18n.tabLint"
+ data-testid="lint-tab"
+ @click="setCurrentTab($options.tabConstants.LINT_TAB)"
+ >
+ <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
+ <ci-lint v-else :ci-config="ciConfigData" />
+ </editor-tab>
+ <gl-tab
+ v-if="glFeatures.ciConfigMergedTab"
+ class="gl-mb-3"
+ :title="$options.i18n.tabMergedYaml"
+ lazy
+ data-testid="merged-tab"
+ @click="setCurrentTab($options.tabConstants.MERGED_TAB)"
+ >
+ <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
+ <gl-alert v-else-if="hasMergedYamlLoadError" variant="danger" :dismissible="false">
+ {{ $options.errorTexts.loadMergedYaml }}
+ </gl-alert>
+ <ci-config-merged-preview v-else :ci-config-data="ciConfigData" v-on="$listeners" />
+ </gl-tab>
+ </gl-tabs>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/text_editor.vue
deleted file mode 100644
index b8d49d77ea9..00000000000
--- a/app/assets/javascripts/pipeline_editor/components/text_editor.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-<script>
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
-import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
-
-export default {
- components: {
- EditorLite,
- },
- inject: ['projectPath', 'projectNamespace'],
- inheritAttrs: false,
- props: {
- ciConfigPath: {
- type: String,
- required: true,
- },
- commitSha: {
- type: String,
- required: false,
- default: null,
- },
- },
- methods: {
- onEditorReady() {
- const editorInstance = this.$refs.editor.getEditor();
-
- editorInstance.use(new CiSchemaExtension());
- editorInstance.registerCiSchema({
- projectPath: this.projectPath,
- projectNamespace: this.projectNamespace,
- ref: this.commitSha,
- });
- },
- },
-};
-</script>
-<template>
- <div class="gl-border-solid gl-border-gray-100 gl-border-1">
- <editor-lite
- ref="editor"
- :file-name="ciConfigPath"
- v-bind="$attrs"
- @editor-ready="onEditorReady"
- v-on="$listeners"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/ui/confirm_unsaved_changes_dialog.vue b/app/assets/javascripts/pipeline_editor/components/ui/confirm_unsaved_changes_dialog.vue
new file mode 100644
index 00000000000..bc076fbe349
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/ui/confirm_unsaved_changes_dialog.vue
@@ -0,0 +1,26 @@
+<script>
+export default {
+ props: {
+ hasUnsavedChanges: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ created() {
+ window.addEventListener('beforeunload', this.confirmChanges);
+ },
+ destroyed() {
+ window.removeEventListener('beforeunload', this.confirmChanges);
+ },
+ methods: {
+ confirmChanges(e = {}) {
+ if (this.hasUnsavedChanges) {
+ e.preventDefault();
+ // eslint-disable-next-line no-param-reassign
+ e.returnValue = ''; // Chrome requires returnValue to be set
+ }
+ },
+ },
+ render: () => null,
+};
+</script>
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index 70bab8092c0..e676fdeae02 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -1,2 +1,16 @@
export const CI_CONFIG_STATUS_VALID = 'VALID';
export const CI_CONFIG_STATUS_INVALID = 'INVALID';
+
+export const COMMIT_FAILURE = 'COMMIT_FAILURE';
+export const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
+
+export const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
+export const LOAD_FAILURE_NO_FILE = 'LOAD_FAILURE_NO_FILE';
+export const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
+
+export const CREATE_TAB = 'CREATE_TAB';
+export const LINT_TAB = 'LINT_TAB';
+export const MERGED_TAB = 'MERGED_TAB';
+export const VISUALIZE_TAB = 'VISUALIZE_TAB';
+
+export const TABS_WITH_COMMIT_FORM = [CREATE_TAB, LINT_TAB, VISUALIZE_TAB];
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
index 0c58749a8b2..2af0cd5f6d4 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
@@ -1,4 +1,4 @@
-mutation commitCIFileMutation(
+mutation commitCIFile(
$projectPath: ID!
$branch: String!
$startBranch: String
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
index dfddb29701d..30c18a96536 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
@@ -3,6 +3,7 @@
query getCiConfigData($projectPath: ID!, $content: String!) {
ciConfig(projectPath: $projectPath, content: $content) {
errors
+ mergedYaml
status
stages {
...PipelineStagesConnection
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/commit_sha.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/commit_sha.graphql
new file mode 100644
index 00000000000..6c7635887ec
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/commit_sha.graphql
@@ -0,0 +1,3 @@
+query getCommitSha {
+ commitSha @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 583ba555080..dc427f55b5f 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -2,12 +2,17 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import typeDefs from './graphql/typedefs.graphql';
+import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
import { resolvers } from './graphql/resolvers';
-
+import typeDefs from './graphql/typedefs.graphql';
import PipelineEditorApp from './pipeline_editor_app.vue';
export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
+ // Prevent issues loading syntax validation workers
+ // Fixes https://gitlab.com/gitlab-org/gitlab/-/issues/297252
+ // TODO Remove when https://gitlab.com/gitlab-org/gitlab/-/issues/321656 is resolved
+ resetServiceWorkersPublicPath();
+
const el = document.querySelector(selector);
if (!el) {
@@ -15,14 +20,13 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
}
const {
- // props
- ciConfigPath,
+ // Add to apollo cache as it can be updated by future queries
commitSha,
+ // Add to provide/inject API for static values
+ ciConfigPath,
defaultBranch,
- newMergeRequestPath,
-
- // `provide/inject` data
lintHelpPagePath,
+ newMergeRequestPath,
projectFullPath,
projectPath,
projectNamespace,
@@ -35,25 +39,27 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
defaultClient: createDefaultClient(resolvers, { typeDefs }),
});
+ apolloProvider.clients.defaultClient.cache.writeData({
+ data: {
+ commitSha,
+ },
+ });
+
return new Vue({
el,
apolloProvider,
provide: {
+ ciConfigPath,
+ defaultBranch,
lintHelpPagePath,
+ newMergeRequestPath,
projectFullPath,
projectPath,
projectNamespace,
ymlHelpPagePath,
},
render(h) {
- return h(PipelineEditorApp, {
- props: {
- ciConfigPath,
- commitSha,
- defaultBranch,
- newMergeRequestPath,
- },
- });
+ return h(PipelineEditorApp);
},
});
};
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 21993e2120a..b4a818e2472 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,84 +1,55 @@
<script>
-import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
-import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import httpStatusCodes from '~/lib/utils/http_status';
+import { __, s__, sprintf } from '~/locale';
-import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
-import CiLint from './components/lint/ci_lint.vue';
-import CommitForm from './components/commit/commit_form.vue';
-import EditorTab from './components/ui/editor_tab.vue';
-import TextEditor from './components/text_editor.vue';
-import ValidationSegment from './components/info/validation_segment.vue';
-
-import commitCiFileMutation from './graphql/mutations/commit_ci_file.mutation.graphql';
+import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
+import ConfirmUnsavedChangesDialog from './components/ui/confirm_unsaved_changes_dialog.vue';
+import {
+ COMMIT_FAILURE,
+ COMMIT_SUCCESS,
+ DEFAULT_FAILURE,
+ LOAD_FAILURE_NO_FILE,
+ LOAD_FAILURE_UNKNOWN,
+} from './constants';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
-import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
-
-const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
-const MR_TARGET_BRANCH = 'merge_request[target_branch]';
-
-const COMMIT_FAILURE = 'COMMIT_FAILURE';
-const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
-const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
-const LOAD_FAILURE_NO_FILE = 'LOAD_FAILURE_NO_FILE';
-const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
+import PipelineEditorHome from './pipeline_editor_home.vue';
export default {
components: {
- CiLint,
- CommitForm,
- EditorTab,
+ ConfirmUnsavedChangesDialog,
GlAlert,
GlLoadingIcon,
- GlTabs,
- GlTab,
- PipelineGraph,
- TextEditor,
- ValidationSegment,
+ PipelineEditorHome,
},
- mixins: [glFeatureFlagsMixin()],
- inject: ['projectFullPath'],
- props: {
- defaultBranch: {
- type: String,
- required: false,
- default: null,
+ inject: {
+ ciConfigPath: {
+ default: '',
},
- commitSha: {
- type: String,
- required: false,
+ defaultBranch: {
default: null,
},
- ciConfigPath: {
- type: String,
- required: true,
- },
- newMergeRequestPath: {
- type: String,
- required: true,
+ projectFullPath: {
+ default: '',
},
},
data() {
return {
ciConfigData: {},
- content: '',
- contentModel: '',
- lastCommitSha: this.commitSha,
- isSaving: false,
-
// Success and failure state
failureType: null,
- showFailureAlert: false,
failureReasons: [],
- successType: null,
+ initialCiFileContent: '',
+ lastCommittedContent: '',
+ currentCiFileContent: '',
+ showFailureAlert: false,
showSuccessAlert: false,
+ successType: null,
};
},
apollo: {
- content: {
+ initialCiFileContent: {
query: getBlobContent,
variables() {
return {
@@ -91,7 +62,10 @@ export default {
return data?.blobContent?.rawData;
},
result({ data }) {
- this.contentModel = data?.blobContent?.rawData ?? '';
+ const fileContent = data?.blobContent?.rawData ?? '';
+
+ this.lastCommittedContent = fileContent;
+ this.currentCiFileContent = fileContent;
},
error(error) {
this.handleBlobContentError(error);
@@ -100,13 +74,13 @@ export default {
ciConfigData: {
query: getCiConfigData,
// If content is not loaded, we can't lint the data
- skip: ({ contentModel }) => {
- return !contentModel;
+ skip: ({ currentCiFileContent }) => {
+ return !currentCiFileContent;
},
variables() {
return {
projectPath: this.projectFullPath,
- content: this.contentModel,
+ content: this.currentCiFileContent,
};
},
update(data) {
@@ -122,8 +96,11 @@ export default {
},
},
computed: {
+ hasUnsavedChanges() {
+ return this.lastCommittedContent !== this.currentCiFileContent;
+ },
isBlobContentLoading() {
- return this.$apollo.queries.content.loading;
+ return this.$apollo.queries.initialCiFileContent.loading;
},
isBlobContentError() {
return this.failureType === LOAD_FAILURE_NO_FILE;
@@ -131,62 +108,60 @@ export default {
isCiConfigDataLoading() {
return this.$apollo.queries.ciConfigData.loading;
},
- defaultCommitMessage() {
- return sprintf(this.$options.i18n.defaultCommitMessage, { sourcePath: this.ciConfigPath });
- },
- success() {
- switch (this.successType) {
- case COMMIT_SUCCESS:
- return {
- text: this.$options.alertTexts[COMMIT_SUCCESS],
- variant: 'info',
- };
- default:
- return null;
- }
- },
failure() {
switch (this.failureType) {
case LOAD_FAILURE_NO_FILE:
return {
- text: sprintf(this.$options.alertTexts[LOAD_FAILURE_NO_FILE], {
+ text: sprintf(this.$options.errorTexts[LOAD_FAILURE_NO_FILE], {
filePath: this.ciConfigPath,
}),
variant: 'danger',
};
case LOAD_FAILURE_UNKNOWN:
return {
- text: this.$options.alertTexts[LOAD_FAILURE_UNKNOWN],
+ text: this.$options.errorTexts[LOAD_FAILURE_UNKNOWN],
variant: 'danger',
};
case COMMIT_FAILURE:
return {
- text: this.$options.alertTexts[COMMIT_FAILURE],
+ text: this.$options.errorTexts[COMMIT_FAILURE],
variant: 'danger',
};
default:
return {
- text: this.$options.alertTexts[DEFAULT_FAILURE],
+ text: this.$options.errorTexts[DEFAULT_FAILURE],
variant: 'danger',
};
}
},
+ success() {
+ switch (this.successType) {
+ case COMMIT_SUCCESS:
+ return {
+ text: this.$options.successTexts[COMMIT_SUCCESS],
+ variant: 'info',
+ };
+ default:
+ return null;
+ }
+ },
},
i18n: {
- defaultCommitMessage: __('Update %{sourcePath} file'),
tabEdit: s__('Pipelines|Write pipeline configuration'),
tabGraph: s__('Pipelines|Visualize'),
tabLint: s__('Pipelines|Lint'),
},
- alertTexts: {
+ errorTexts: {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
- [COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
[DEFAULT_FAILURE]: __('Something went wrong on our end.'),
[LOAD_FAILURE_NO_FILE]: s__(
'Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again.',
),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
},
+ successTexts: {
+ [COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
+ },
methods: {
handleBlobContentError(error = {}) {
const { networkError } = error;
@@ -207,72 +182,32 @@ export default {
dismissFailure() {
this.showFailureAlert = false;
},
+ dismissSuccess() {
+ this.showSuccessAlert = false;
+ },
reportFailure(type, reasons = []) {
this.showFailureAlert = true;
this.failureType = type;
this.failureReasons = reasons;
},
- dismissSuccess() {
- this.showSuccessAlert = false;
- },
reportSuccess(type) {
this.showSuccessAlert = true;
this.successType = type;
},
-
- redirectToNewMergeRequest(sourceBranch) {
- const url = mergeUrlParams(
- {
- [MR_SOURCE_BRANCH]: sourceBranch,
- [MR_TARGET_BRANCH]: this.defaultBranch,
- },
- this.newMergeRequestPath,
- );
- redirectTo(url);
+ resetContent() {
+ this.currentCiFileContent = this.lastCommittedContent;
},
- async onCommitSubmit(event) {
- this.isSaving = true;
- const { message, branch, openMergeRequest } = event;
-
- try {
- const {
- data: {
- commitCreate: { errors, commit },
- },
- } = await this.$apollo.mutate({
- mutation: commitCiFileMutation,
- variables: {
- projectPath: this.projectFullPath,
- branch,
- startBranch: this.defaultBranch,
- message,
- filePath: this.ciConfigPath,
- content: this.contentModel,
- lastCommitId: this.lastCommitSha,
- },
- });
-
- if (errors?.length) {
- this.reportFailure(COMMIT_FAILURE, errors);
- return;
- }
-
- if (openMergeRequest) {
- this.redirectToNewMergeRequest(branch);
- } else {
- this.reportSuccess(COMMIT_SUCCESS);
-
- // Update latest commit
- this.lastCommitSha = commit.sha;
- }
- } catch (error) {
- this.reportFailure(COMMIT_FAILURE, [error?.message]);
- } finally {
- this.isSaving = false;
- }
+ showErrorAlert({ type, reasons = [] }) {
+ this.reportFailure(type, reasons);
},
- onCommitCancel() {
- this.contentModel = this.content;
+ updateCiConfig(ciFileContent) {
+ this.currentCiFileContent = ciFileContent;
+ },
+ updateOnCommit({ type }) {
+ this.reportSuccess(type);
+ // Keep track of the latest commited content to know
+ // if the user has made changes to the file that are unsaved.
+ this.lastCommittedContent = this.currentCiFileContent;
},
},
};
@@ -280,20 +215,10 @@ export default {
<template>
<div class="gl-mt-4">
- <gl-alert
- v-if="showSuccessAlert"
- :variant="success.variant"
- :dismissible="true"
- @dismiss="dismissSuccess"
- >
+ <gl-alert v-if="showSuccessAlert" :variant="success.variant" @dismiss="dismissSuccess">
{{ success.text }}
</gl-alert>
- <gl-alert
- v-if="showFailureAlert"
- :variant="failure.variant"
- :dismissible="true"
- @dismiss="dismissFailure"
- >
+ <gl-alert v-if="showFailureAlert" :variant="failure.variant" @dismiss="dismissFailure">
{{ failure.text }}
<ul v-if="failureReasons.length" class="gl-mb-0">
<li v-for="reason in failureReasons" :key="reason">{{ reason }}</li>
@@ -301,46 +226,16 @@ export default {
</gl-alert>
<gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" />
<div v-else-if="!isBlobContentError" class="gl-mt-4">
- <div class="file-editor gl-mb-3">
- <div class="info-well gl-display-none gl-display-sm-block">
- <validation-segment
- class="well-segment"
- :loading="isCiConfigDataLoading"
- :ci-config="ciConfigData"
- />
- </div>
-
- <gl-tabs>
- <editor-tab :lazy="true" :title="$options.i18n.tabEdit">
- <text-editor
- v-model="contentModel"
- :ci-config-path="ciConfigPath"
- :commit-sha="lastCommitSha"
- />
- </editor-tab>
- <gl-tab
- v-if="glFeatures.ciConfigVisualizationTab"
- :lazy="true"
- :title="$options.i18n.tabGraph"
- data-testid="visualization-tab"
- >
- <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
- <pipeline-graph v-else :pipeline-data="ciConfigData" />
- </gl-tab>
-
- <editor-tab :title="$options.i18n.tabLint">
- <gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
- <ci-lint v-else :ci-config="ciConfigData" />
- </editor-tab>
- </gl-tabs>
- </div>
- <commit-form
- :default-branch="defaultBranch"
- :default-message="defaultCommitMessage"
- :is-saving="isSaving"
- @cancel="onCommitCancel"
- @submit="onCommitSubmit"
+ <pipeline-editor-home
+ :is-ci-config-data-loading="isCiConfigDataLoading"
+ :ci-config-data="ciConfigData"
+ :ci-file-content="currentCiFileContent"
+ @commit="updateOnCommit"
+ @resetContent="resetContent"
+ @showError="showErrorAlert"
+ @updateCiConfig="updateCiConfig"
/>
</div>
+ <confirm-unsaved-changes-dialog :has-unsaved-changes="hasUnsavedChanges" />
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
new file mode 100644
index 00000000000..8c9aad6ed87
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
@@ -0,0 +1,60 @@
+<script>
+import CommitSection from './components/commit/commit_section.vue';
+import PipelineEditorHeader from './components/header/pipeline_editor_header.vue';
+import PipelineEditorTabs from './components/pipeline_editor_tabs.vue';
+import { TABS_WITH_COMMIT_FORM, CREATE_TAB } from './constants';
+
+export default {
+ components: {
+ CommitSection,
+ PipelineEditorHeader,
+ PipelineEditorTabs,
+ },
+ props: {
+ ciConfigData: {
+ type: Object,
+ required: true,
+ },
+ ciFileContent: {
+ type: String,
+ required: true,
+ },
+ isCiConfigDataLoading: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ currentTab: CREATE_TAB,
+ };
+ },
+ computed: {
+ showCommitForm() {
+ return TABS_WITH_COMMIT_FORM.includes(this.currentTab);
+ },
+ },
+ methods: {
+ setCurrentTab(tabName) {
+ this.currentTab = tabName;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <pipeline-editor-header
+ :ci-config-data="ciConfigData"
+ :is-ci-config-data-loading="isCiConfigDataLoading"
+ />
+ <pipeline-editor-tabs
+ :ci-config-data="ciConfigData"
+ :ci-file-content="ciFileContent"
+ :is-ci-config-data-loading="isCiConfigDataLoading"
+ v-on="$listeners"
+ @set-current-tab="setCurrentTab"
+ />
+ <commit-section v-if="showCommitForm" :ci-file-content="ciFileContent" v-on="$listeners" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
index 70c5713b216..5070971c563 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -1,6 +1,4 @@
<script>
-import Vue from 'vue';
-import { uniqueId } from 'lodash';
import {
GlAlert,
GlIcon,
@@ -9,6 +7,7 @@ import {
GlFormGroup,
GlFormInput,
GlFormSelect,
+ GlFormTextarea,
GlLink,
GlDropdown,
GlDropdownItem,
@@ -18,13 +17,15 @@ import {
GlLoadingIcon,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
-import * as Sentry from '~/sentry/wrapper';
-import { s__, __, n__ } from '~/locale';
+import { uniqueId } from 'lodash';
+import Vue from 'vue';
import axios from '~/lib/utils/axios_utils';
-import { redirectTo } from '~/lib/utils/url_utility';
-import { VARIABLE_TYPE, FILE_TYPE, CONFIG_VARIABLES_TIMEOUT } from '../constants';
import { backOff } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { s__, __, n__ } from '~/locale';
+import * as Sentry from '~/sentry/wrapper';
+import { VARIABLE_TYPE, FILE_TYPE, CONFIG_VARIABLES_TIMEOUT } from '../constants';
export default {
typeOptions: [
@@ -38,6 +39,9 @@ export default {
errorTitle: __('Pipeline cannot be run.'),
warningTitle: __('The form contains the following warning:'),
maxWarningsSummary: __('%{total} warnings found: showing first %{warningsDisplayed}'),
+ // this height value is used inline on the textarea to match the input field height
+ // it's used to prevent the overwrite if 'gl-h-7' or 'gl-h-7!' were used
+ textAreaStyle: { height: '32px' },
components: {
GlAlert,
GlIcon,
@@ -46,6 +50,7 @@ export default {
GlFormGroup,
GlFormInput,
GlFormSelect,
+ GlFormTextarea,
GlLink,
GlDropdown,
GlDropdownItem,
@@ -116,6 +121,7 @@ export default {
totalWarnings: 0,
isWarningDismissed: false,
isLoading: false,
+ submitted: false,
};
},
computed: {
@@ -251,10 +257,6 @@ export default {
return index < this.variables.length - 1;
},
fetchConfigVariables(refValue) {
- if (!gon?.features?.newPipelineFormPrefilledVars) {
- return Promise.resolve({ params: {}, descriptions: {} });
- }
-
this.isLoading = true;
return backOff((next, stop) => {
@@ -298,6 +300,7 @@ export default {
});
},
createPipeline() {
+ this.submitted = true;
const filteredVariables = this.variables
.filter(({ key, value }) => key !== '' && value !== '')
.map(({ variable_type, key, value }) => ({
@@ -317,8 +320,16 @@ export default {
redirectTo(`${this.pipelinesPath}/${data.id}`);
})
.catch((err) => {
- const { errors, warnings, total_warnings: totalWarnings } = err.response.data;
+ // always re-enable submit button
+ this.submitted = false;
+
+ const {
+ errors = [],
+ warnings = [],
+ total_warnings: totalWarnings = 0,
+ } = err?.response?.data;
const [error] = errors;
+
this.error = error;
this.warnings = warnings;
this.totalWarnings = totalWarnings;
@@ -420,10 +431,12 @@ export default {
data-testid="pipeline-form-ci-variable-key"
@change="addEmptyVariable(refFullName)"
/>
- <gl-form-input
+ <gl-form-textarea
v-model="variable.value"
:placeholder="s__('CiVariables|Input variable value')"
class="gl-mb-3"
+ :style="$options.textAreaStyle"
+ :no-resize="false"
data-testid="pipeline-form-ci-variable-value"
/>
@@ -436,12 +449,12 @@ export default {
category="secondary"
@click="removeVariable(index)"
>
- <gl-icon class="gl-mr-0! gl-display-none gl-display-md-block" name="clear" />
- <span class="gl-display-md-none">{{ s__('CiVariables|Remove variable') }}</span>
+ <gl-icon class="gl-mr-0! gl-display-none gl-md-display-block" name="clear" />
+ <span class="gl-md-display-none">{{ s__('CiVariables|Remove variable') }}</span>
</gl-button>
<gl-button
v-else
- class="gl-md-ml-3 gl-mb-3 gl-display-none gl-display-md-block gl-visibility-hidden"
+ class="gl-md-ml-3 gl-mb-3 gl-display-none gl-md-display-block gl-visibility-hidden"
icon="clear"
/>
</template>
@@ -468,6 +481,8 @@ export default {
variant="success"
class="js-no-auto-disable"
data-qa-selector="run_pipeline_button"
+ data-testid="run_pipeline_button"
+ :disabled="submitted"
>{{ s__('Pipeline|Run Pipeline') }}</gl-button
>
<gl-button :href="pipelinesPath">{{ __('Cancel') }}</gl-button>
diff --git a/app/assets/javascripts/pipelines/components/dag/dag.vue b/app/assets/javascripts/pipelines/components/dag/dag.vue
index 2482af2c7f0..e44dedfe2ee 100644
--- a/app/assets/javascripts/pipelines/components/dag/dag.vue
+++ b/app/assets/javascripts/pipelines/components/dag/dag.vue
@@ -1,14 +1,14 @@
<script>
import { GlAlert, GlButton, GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash';
-import { __ } from '~/locale';
import { fetchPolicies } from '~/lib/graphql';
+import { __ } from '~/locale';
+import { DEFAULT, PARSE_FAILURE, LOAD_FAILURE, UNSUPPORTED_DATA } from '../../constants';
import getDagVisData from '../../graphql/queries/get_dag_vis_data.query.graphql';
-import DagGraph from './dag_graph.vue';
-import DagAnnotations from './dag_annotations.vue';
-import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from './constants';
import { parseData } from '../parsing_utils';
-import { DEFAULT, PARSE_FAILURE, LOAD_FAILURE, UNSUPPORTED_DATA } from '../../constants';
+import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from './constants';
+import DagAnnotations from './dag_annotations.vue';
+import DagGraph from './dag_graph.vue';
export default {
// eslint-disable-next-line @gitlab/require-i18n-strings
diff --git a/app/assets/javascripts/pipelines/components/dag/dag_graph.vue b/app/assets/javascripts/pipelines/components/dag/dag_graph.vue
index 5ba0604fa01..7646c11773c 100644
--- a/app/assets/javascripts/pipelines/components/dag/dag_graph.vue
+++ b/app/assets/javascripts/pipelines/components/dag/dag_graph.vue
@@ -1,7 +1,10 @@
<script>
import * as d3 from 'd3';
import { uniqueId } from 'lodash';
+import { PARSE_FAILURE } from '../../constants';
+import { getMaxNodes, removeOrphanNodes } from '../parsing_utils';
import { LINK_SELECTOR, NODE_SELECTOR, ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from './constants';
+import { calculateClip, createLinkPath, createSankey, labelPosition } from './drawing_utils';
import {
currentIsLive,
getLiveLinksAsDict,
@@ -10,9 +13,6 @@ import {
toggleLinkHighlight,
togglePathHighlights,
} from './interactions';
-import { getMaxNodes, removeOrphanNodes } from '../parsing_utils';
-import { calculateClip, createLinkPath, createSankey, labelPosition } from './drawing_utils';
-import { PARSE_FAILURE } from '../../constants';
export default {
viewOptions: {
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index 0ce94d4f02f..1df693704d4 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -1,9 +1,10 @@
<script>
import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { reportToSentry } from './utils';
/**
@@ -62,7 +63,7 @@ export default {
*
*/
onClickAction() {
- this.$root.$emit('bv::hide::tooltip', `js-ci-action-${this.link}`);
+ this.$root.$emit(BV_HIDE_TOOLTIP, `js-ci-action-${this.link}`);
this.isDisabled = true;
this.isLoading = true;
diff --git a/app/assets/javascripts/pipelines/components/graph/constants.js b/app/assets/javascripts/pipelines/components/graph/constants.js
index 6f0deccfef6..caa269f5095 100644
--- a/app/assets/javascripts/pipelines/components/graph/constants.js
+++ b/app/assets/javascripts/pipelines/components/graph/constants.js
@@ -2,5 +2,11 @@ export const DOWNSTREAM = 'downstream';
export const MAIN = 'main';
export const UPSTREAM = 'upstream';
+/*
+ this value is based on the gl-pipeline-job-width class
+ plus some extra for the margins
+*/
+export const ONE_COL_WIDTH = 180;
+
export const REST = 'rest';
export const GRAPHQL = 'graphql';
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index cd403757fe6..93156d5d05b 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,9 +1,9 @@
<script>
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
import LinksLayer from '../graph_shared/links_layer.vue';
+import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH } from './constants';
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import StageColumnComponent from './stage_column_component.vue';
-import { DOWNSTREAM, MAIN, UPSTREAM } from './constants';
import { reportToSentry } from './utils';
export default {
@@ -86,11 +86,11 @@ export default {
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
},
mounted() {
- this.measurements = this.getMeasurements();
+ this.getMeasurements();
},
methods: {
getMeasurements() {
- return {
+ this.measurements = {
width: this.$refs[this.containerId].scrollWidth,
height: this.$refs[this.containerId].scrollHeight,
};
@@ -101,6 +101,13 @@ export default {
setJob(jobName) {
this.hoveredJobName = jobName;
},
+ slidePipelineContainer() {
+ this.$refs.mainPipelineContainer.scrollBy({
+ left: ONE_COL_WIDTH,
+ top: 0,
+ behavior: 'smooth',
+ });
+ },
togglePipelineExpanded(jobName, expanded) {
this.pipelineExpanded = {
expanded,
@@ -116,8 +123,9 @@ export default {
<template>
<div class="js-pipeline-graph">
<div
- class="gl-display-flex gl-position-relative gl-overflow-auto gl-bg-gray-10 gl-white-space-nowrap"
- :class="{ 'gl-pipeline-min-h gl-py-5': !isLinkedPipeline }"
+ ref="mainPipelineContainer"
+ class="gl-display-flex gl-position-relative gl-bg-gray-10 gl-white-space-nowrap"
+ :class="{ 'gl-pipeline-min-h gl-py-5 gl-overflow-auto': !isLinkedPipeline }"
>
<linked-graph-wrapper>
<template #upstream>
@@ -153,6 +161,7 @@ export default {
:pipeline-id="pipeline.id"
@refreshPipelineGraph="$emit('refreshPipelineGraph')"
@jobHover="setJob"
+ @updateMeasurements="getMeasurements"
/>
</links-layer>
</div>
@@ -160,11 +169,13 @@ export default {
<template #downstream>
<linked-pipelines-column
v-if="showDownstreamPipelines"
+ class="gl-mr-6"
:linked-pipelines="downstreamPipelines"
:column-title="__('Downstream')"
:type="$options.pipelineTypeConstants.DOWNSTREAM"
@downstreamHovered="setJob"
@pipelineExpandToggle="togglePipelineExpanded"
+ @scrollContainer="slidePipelineContainer"
@error="onError"
/>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
index 2164dbf4d55..abbf8df6eed 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
@@ -1,10 +1,10 @@
<script>
-import { escape, capitalize } from 'lodash';
import { GlLoadingIcon } from '@gitlab/ui';
-import StageColumnComponentLegacy from './stage_column_component_legacy.vue';
-import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue';
+import { escape, capitalize } from 'lodash';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
+import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue';
+import StageColumnComponentLegacy from './stage_column_component_legacy.vue';
import { reportToSentry } from './utils';
export default {
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 08d6162aeb8..f6aee8c5fcf 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -60,7 +60,7 @@ export default {
>
<div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
<span class="gl-display-flex gl-align-items-center gl-min-w-0">
- <ci-icon :status="group.status" :size="24" />
+ <ci-icon :status="group.status" :size="24" class="gl-line-height-0" />
<span class="gl-text-truncate mw-70p gl-pl-3">
{{ group.name }}
</span>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 8262d728a24..46ef0457d40 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -1,11 +1,12 @@
<script>
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
-import ActionComponent from './action_component.vue';
-import JobNameComponent from './job_name_component.vue';
-import { sprintf } from '~/locale';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { sprintf } from '~/locale';
import { accessValue } from './accessors';
+import ActionComponent from './action_component.vue';
import { REST } from './constants';
+import JobNameComponent from './job_name_component.vue';
import { reportToSentry } from './utils';
/**
@@ -144,7 +145,7 @@ export default {
},
methods: {
hideTooltips() {
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
},
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
index 23a38fc053e..fffd8e1818a 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
@@ -30,7 +30,7 @@ export default {
</script>
<template>
<span class="ci-job-name-component mw-100 gl-display-flex gl-align-items-center">
- <ci-icon :size="iconSize" :status="status" />
+ <ci-icon :size="iconSize" :status="status" class="gl-line-height-0" />
<span class="gl-text-truncate mw-70p gl-pl-3 gl-display-inline-block">
{{ name }}
</span>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index d18e604f087..add7b3445f7 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -1,7 +1,8 @@
<script>
import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon, GlBadge } from '@gitlab/ui';
-import CiStatus from '~/vue_shared/components/ci_icon.vue';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
+import CiStatus from '~/vue_shared/components/ci_icon.vue';
import { accessValue } from './accessors';
import { DOWNSTREAM, REST, UPSTREAM } from './constants';
import { reportToSentry } from './utils';
@@ -126,7 +127,7 @@ export default {
this.$emit('pipelineExpandToggle', this.sourceJobName, !this.expanded);
},
hideTooltips() {
- this.$root.$emit('bv::hide::tooltip');
+ this.$root.$emit(BV_HIDE_TOOLTIP);
},
onDownstreamHovered() {
this.$emit('downstreamHovered', this.sourceJobName);
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
index 40e6a01b88c..3ce77a1c60a 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -1,8 +1,8 @@
<script>
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
-import LinkedPipeline from './linked_pipeline.vue';
import { LOAD_FAILURE } from '../../constants';
-import { UPSTREAM } from './constants';
+import { ONE_COL_WIDTH, UPSTREAM } from './constants';
+import LinkedPipeline from './linked_pipeline.vue';
import { unwrapPipelineData, toggleQueryPollingByVisibility, reportToSentry } from './utils';
export default {
@@ -39,6 +39,7 @@ export default {
'gl-pl-3',
'gl-mb-5',
],
+ minWidth: `${ONE_COL_WIDTH}px`,
computed: {
columnClass() {
const positionValues = {
@@ -47,12 +48,6 @@ export default {
};
return `graph-position-${this.graphPosition} ${positionValues[this.graphPosition]}`;
},
- graphPosition() {
- return this.isUpstream ? 'left' : 'right';
- },
- isUpstream() {
- return this.type === UPSTREAM;
- },
computedTitleClasses() {
const positionalClasses = this.isUpstream
? ['gl-w-full', 'gl-text-right', 'gl-linked-pipeline-padding']
@@ -60,6 +55,15 @@ export default {
return [...this.$options.titleClasses, ...positionalClasses];
},
+ graphPosition() {
+ return this.isUpstream ? 'left' : 'right';
+ },
+ isUpstream() {
+ return this.type === UPSTREAM;
+ },
+ minWidth() {
+ return this.isUpstream ? 0 : this.$options.minWidth;
+ },
},
methods: {
getPipelineData(pipeline) {
@@ -79,6 +83,7 @@ export default {
},
result() {
this.loadingPipelineId = null;
+ this.$emit('scrollContainer');
},
error(err, _vm, _key, type) {
this.$emit('error', LOAD_FAILURE);
@@ -130,6 +135,9 @@ export default {
this.$emit('pipelineExpandToggle', jobName, expanded);
},
+ showContainer(id) {
+ return this.isExpanded(id) || this.isLoadingPipeline(id);
+ },
},
};
</script>
@@ -158,9 +166,13 @@ export default {
@pipelineClicked="onPipelineClick(pipeline)"
@pipelineExpandToggle="onPipelineExpandToggle"
/>
- <div v-if="isExpanded(pipeline.id)" class="gl-display-inline-block">
+ <div
+ v-if="showContainer(pipeline.id)"
+ :style="{ minWidth }"
+ class="gl-display-inline-block"
+ >
<pipeline-graph
- v-if="currentPipeline"
+ v-if="isExpanded(pipeline.id)"
:type="type"
class="d-inline-block gl-mt-n2"
:pipeline="currentPipeline"
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
index 2f1390e07d1..0d1ff94c275 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
@@ -1,6 +1,6 @@
<script>
-import LinkedPipeline from './linked_pipeline.vue';
import { UPSTREAM } from './constants';
+import LinkedPipeline from './linked_pipeline.vue';
import { reportToSentry } from './utils';
export default {
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index 65f8c231885..0a762563114 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -1,11 +1,11 @@
<script>
import { capitalize, escape, isEmpty } from 'lodash';
import MainGraphWrapper from '../graph_shared/main_graph_wrapper.vue';
-import JobItem from './job_item.vue';
-import JobGroupDropdown from './job_group_dropdown.vue';
+import { accessValue } from './accessors';
import ActionComponent from './action_component.vue';
import { GRAPHQL } from './constants';
-import { accessValue } from './accessors';
+import JobGroupDropdown from './job_group_dropdown.vue';
+import JobItem from './job_item.vue';
import { reportToSentry } from './utils';
export default {
@@ -67,6 +67,9 @@ export default {
errorCaptured(err, _vm, info) {
reportToSentry('stage_column_component', `error: ${err}, info: ${info}`);
},
+ mounted() {
+ this.$emit('updateMeasurements');
+ },
methods: {
getGroupId(group) {
return accessValue(GRAPHQL, 'groupId', group);
@@ -75,17 +78,13 @@ export default {
return `ci-badge-${escape(group.name)}`;
},
isFadedOut(jobName) {
- return (
- this.jobHovered &&
- this.highlightedJobs.length > 1 &&
- !this.highlightedJobs.includes(jobName)
- );
+ return this.highlightedJobs.length > 1 && !this.highlightedJobs.includes(jobName);
},
},
};
</script>
<template>
- <main-graph-wrapper class="gl-px-6">
+ <main-graph-wrapper class="gl-px-6" data-testid="stage-column">
<template #stages>
<div
data-testid="stage-column-title"
@@ -123,12 +122,9 @@ export default {
:class="{ 'gl-opacity-3': isFadedOut(group.name) }"
@pipelineActionRequestComplete="$emit('refreshPipelineGraph')"
/>
- <job-group-dropdown
- v-else
- :group="group"
- :pipeline-id="pipelineId"
- :class="{ 'gl-opacity-3': isFadedOut(group.name) }"
- />
+ <div v-else :class="{ 'gl-opacity-3': isFadedOut(group.name) }">
+ <job-group-dropdown :group="group" :pipeline-id="pipelineId" />
+ </div>
</div>
</template>
</main-graph-wrapper>
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
index 059e8f9f8db..2cee2fbbd8f 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
@@ -1,9 +1,9 @@
<script>
import { isEmpty, escape } from 'lodash';
import stageColumnMixin from '../../mixins/stage_column_mixin';
-import JobItem from './job_item.vue';
-import JobGroupDropdown from './job_group_dropdown.vue';
import ActionComponent from './action_component.vue';
+import JobGroupDropdown from './job_group_dropdown.vue';
+import JobItem from './job_item.vue';
import { reportToSentry } from './utils';
export default {
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js b/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
index 65c215be794..202498fb188 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
+++ b/app/assets/javascripts/pipelines/components/graph_shared/drawing_utils.js
@@ -40,10 +40,10 @@ export const generateLinksData = ({ links }, containerID, modifier = '') => {
// positioned in the center of the job node by adding half the height
// of the job pill.
const paddingLeft = parseFloat(
- window.getComputedStyle(containerEl, null).getPropertyValue('padding-left'),
+ window.getComputedStyle(containerEl, null).getPropertyValue('padding-left') || 0,
);
const paddingTop = parseFloat(
- window.getComputedStyle(containerEl, null).getPropertyValue('padding-top'),
+ window.getComputedStyle(containerEl, null).getPropertyValue('padding-top') || 0,
);
const sourceNodeX = sourceNodeCoordinates.right - containerCoordinates.x - paddingLeft;
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
index 89444076ae0..289e04e02c5 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
@@ -118,22 +118,20 @@ export default {
<div class="gl-display-flex gl-relative">
<svg
id="link-svg"
- class="gl-absolute"
+ class="gl-absolute gl-pointer-events-none"
:viewBox="viewBox"
:width="`${containerMeasurements.width}px`"
:height="`${containerMeasurements.height}px`"
>
- <template>
- <path
- v-for="link in links"
- :key="link.path"
- :ref="link.ref"
- :d="link.path"
- class="gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease"
- :class="getLinkClasses(link)"
- :stroke-width="$options.STROKE_WIDTH"
- />
- </template>
+ <path
+ v-for="link in links"
+ :key="link.path"
+ :ref="link.ref"
+ :d="link.path"
+ class="gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease"
+ :class="getLinkClasses(link)"
+ :stroke-width="$options.STROKE_WIDTH"
+ />
</svg>
<slot></slot>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
index 0993892a574..1c1bc7ecb2a 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
@@ -74,13 +74,15 @@ export default {
<div v-else>
<gl-alert
v-if="showAlert"
- class="gl-w-max-content gl-ml-4"
+ class="gl-ml-4 gl-mb-4"
:primary-button-text="$options.i18n.showLinksAnyways"
@primaryAction="overrideShowLinks"
@dismiss="dismissAlert"
>
{{ $options.i18n.tooManyJobs }}
</gl-alert>
- <slot></slot>
+ <div class="gl-display-flex gl-relative">
+ <slot></slot>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index a20bd70e90a..4ce43b92c93 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -1,13 +1,13 @@
<script>
import { GlAlert, GlButton, GlLoadingIcon, GlModal, GlModalDirective } 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 { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
-import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql';
+import { LOAD_FAILURE, POST_FAILURE, DELETE_FAILURE, DEFAULT } 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';
-import cancelPipelineMutation from '../graphql/mutations/cancel_pipeline.mutation.graphql';
-import { LOAD_FAILURE, POST_FAILURE, DELETE_FAILURE, DEFAULT } from '../constants';
+import getPipelineQuery from '../graphql/queries/get_pipeline_header_data.query.graphql';
const DELETE_MODAL_ID = 'pipeline-delete-modal';
const POLL_INTERVAL = 10000;
diff --git a/app/assets/javascripts/pipelines/components/legacy_header_component.vue b/app/assets/javascripts/pipelines/components/legacy_header_component.vue
deleted file mode 100644
index c7b72be36ad..00000000000
--- a/app/assets/javascripts/pipelines/components/legacy_header_component.vue
+++ /dev/null
@@ -1,132 +0,0 @@
-<script>
-import { GlLoadingIcon, GlModal, GlModalDirective, GlButton } from '@gitlab/ui';
-import ciHeader from '~/vue_shared/components/header_ci_component.vue';
-import eventHub from '../event_hub';
-import { __ } from '~/locale';
-
-const DELETE_MODAL_ID = 'pipeline-delete-modal';
-
-export default {
- name: 'PipelineHeaderSection',
- components: {
- ciHeader,
- GlLoadingIcon,
- GlModal,
- GlButton,
- },
- directives: {
- GlModal: GlModalDirective,
- },
- props: {
- pipeline: {
- type: Object,
- required: true,
- },
- isLoading: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- isCanceling: false,
- isRetrying: false,
- isDeleting: false,
- };
- },
-
- computed: {
- status() {
- return this.pipeline.details && this.pipeline.details.status;
- },
- shouldRenderContent() {
- return !this.isLoading && Object.keys(this.pipeline).length;
- },
- deleteModalConfirmationText() {
- return __(
- '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.',
- );
- },
- },
-
- methods: {
- cancelPipeline() {
- this.isCanceling = true;
- eventHub.$emit('headerPostAction', this.pipeline.cancel_path);
- },
- retryPipeline() {
- this.isRetrying = true;
- eventHub.$emit('headerPostAction', this.pipeline.retry_path);
- },
- deletePipeline() {
- this.isDeleting = true;
- eventHub.$emit('headerDeleteAction', this.pipeline.delete_path);
- },
- },
- DELETE_MODAL_ID,
-};
-</script>
-<template>
- <div class="pipeline-header-container">
- <ci-header
- v-if="shouldRenderContent"
- :status="status"
- :item-id="pipeline.id"
- :time="pipeline.created_at"
- :user="pipeline.user"
- item-name="Pipeline"
- >
- <gl-button
- v-if="pipeline.retry_path"
- :loading="isRetrying"
- :disabled="isRetrying"
- data-testid="retryButton"
- category="secondary"
- variant="info"
- @click="retryPipeline()"
- >
- {{ __('Retry') }}
- </gl-button>
-
- <gl-button
- v-if="pipeline.cancel_path"
- :loading="isCanceling"
- :disabled="isCanceling"
- data-testid="cancelPipeline"
- class="gl-ml-3"
- category="primary"
- variant="danger"
- @click="cancelPipeline()"
- >
- {{ __('Cancel running') }}
- </gl-button>
-
- <gl-button
- v-if="pipeline.delete_path"
- v-gl-modal="$options.DELETE_MODAL_ID"
- :loading="isDeleting"
- :disabled="isDeleting"
- data-testid="deletePipeline"
- class="gl-ml-3"
- category="secondary"
- variant="danger"
- >
- {{ __('Delete') }}
- </gl-button>
- </ci-header>
-
- <gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-3 gl-mb-3" />
-
- <gl-modal
- :modal-id="$options.DELETE_MODAL_ID"
- :title="__('Delete pipeline')"
- :ok-title="__('Delete pipeline')"
- ok-variant="danger"
- @ok="deletePipeline()"
- >
- <p>
- {{ deleteModalConfirmationText }}
- </p>
- </gl-modal>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
index 8636808b69e..4a7ee3b2af7 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -1,13 +1,13 @@
<script>
import { GlAlert } from '@gitlab/ui';
import { __ } from '~/locale';
+import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
+import { DRAW_FAILURE, DEFAULT, INVALID_CI_CONFIG, EMPTY_PIPELINE_DATA } from '../../constants';
+import { createJobsHash, generateJobNeedsDict } from '../../utils';
import { generateLinksData } from '../graph_shared/drawing_utils';
+import { parseData } from '../parsing_utils';
import JobPill from './job_pill.vue';
import StagePill from './stage_pill.vue';
-import { parseData } from '../parsing_utils';
-import { DRAW_FAILURE, DEFAULT, INVALID_CI_CONFIG, EMPTY_PIPELINE_DATA } from '../../constants';
-import { createJobsHash, generateJobNeedsDict } from '../../utils';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
export default {
components: {
@@ -224,17 +224,15 @@ export default {
data-testid="graph-container"
>
<svg :viewBox="viewBox" :width="width" :height="height" class="gl-absolute">
- <template>
- <path
- v-for="link in links"
- :key="link.path"
- :ref="link.ref"
- :d="link.path"
- class="gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease"
- :class="getLinkClasses(link)"
- :stroke-width="$options.STROKE_WIDTH"
- />
- </template>
+ <path
+ v-for="link in links"
+ :key="link.path"
+ :ref="link.ref"
+ :d="link.path"
+ class="gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease"
+ :class="getLinkClasses(link)"
+ :stroke-width="$options.STROKE_WIDTH"
+ />
</svg>
<div
v-for="(stage, index) in pipelineStages"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
index ee26ea2f007..8a656bb47f4 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state.vue
@@ -1,24 +1,13 @@
<script>
import { GlButton } from '@gitlab/ui';
-import { isExperimentEnabled } from '~/lib/utils/experimentation';
import { s__ } from '~/locale';
-import Tracking from '~/tracking';
export default {
i18n: {
- control: {
- infoMessage: s__(`Pipelines|Continuous Integration can help
- catch bugs by running your tests automatically,
- while Continuous Deployment can help you deliver
- code to your product environment.`),
- buttonMessage: s__('Pipelines|Get started with Pipelines'),
- },
- experiment: {
- infoMessage: s__(`Pipelines|GitLab CI/CD can automatically build,
+ infoMessage: s__(`Pipelines|GitLab CI/CD can automatically build,
test, and deploy your code. Let GitLab take care of time
consuming tasks, so you can spend more time creating.`),
- buttonMessage: s__('Pipelines|Get started with CI/CD'),
- },
+ buttonMessage: s__('Pipelines|Get started with CI/CD'),
},
name: 'PipelinesEmptyState',
components: {
@@ -38,23 +27,6 @@ export default {
required: true,
},
},
- mounted() {
- this.track('viewed');
- },
- methods: {
- track(action) {
- if (!gon.tracking_data) {
- return;
- }
-
- const { category, value, label, property } = gon.tracking_data;
-
- Tracking.event(category, action, { value, label, property });
- },
- isExperimentEnabled() {
- return isExperimentEnabled('pipelinesEmptyState');
- },
- },
};
</script>
<template>
@@ -70,11 +42,7 @@ export default {
{{ s__('Pipelines|Build with confidence') }}
</h4>
<p data-testid="info-text">
- {{
- isExperimentEnabled()
- ? $options.i18n.experiment.infoMessage
- : $options.i18n.control.infoMessage
- }}
+ {{ $options.i18n.infoMessage }}
</p>
<div class="gl-text-center">
@@ -83,13 +51,8 @@ export default {
variant="info"
category="primary"
data-testid="get-started-pipelines"
- @click="track('documentation_clicked')"
>
- {{
- isExperimentEnabled()
- ? $options.i18n.experiment.buttonMessage
- : $options.i18n.control.buttonMessage
- }}
+ {{ $options.i18n.buttonMessage }}
</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
index 1569b326b31..24b5c85c9d6 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
@@ -1,9 +1,9 @@
<script>
/* eslint-disable vue/no-v-html */
-import { isEmpty } from 'lodash';
import { GlLink, GlModal } from '@gitlab/ui';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { isEmpty } from 'lodash';
import { __, s__, sprintf } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
/**
* Pipeline Stop Modal.
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 d1bac078642..823ada133d2 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -77,6 +77,15 @@ export default {
>{{ __('latest') }}</gl-badge
>
<gl-badge
+ v-if="pipeline.flags.merge_train_pipeline"
+ v-gl-tooltip
+ :title="__('This is a merge train pipeline')"
+ variant="info"
+ size="sm"
+ data-testid="pipeline-url-train"
+ >{{ __('train') }}</gl-badge
+ >
+ <gl-badge
v-if="pipeline.flags.yaml_errors"
v-gl-tooltip
:title="pipeline.yaml_errors"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index ec7c5764be1..48009a9fcb8 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -1,28 +1,34 @@
<script>
+import { GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { isEqual } from 'lodash';
-import { GlIcon } from '@gitlab/ui';
-import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import PipelinesService from '../../services/pipelines_service';
-import pipelinesMixin from '../../mixins/pipelines';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import { getParameterByName } from '~/lib/utils/common_utils';
+import { __, s__ } from '~/locale';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../../constants';
+import PipelinesMixin from '../../mixins/pipelines_mixin';
+import PipelinesService from '../../services/pipelines_service';
+import { validateParams } from '../../utils';
+import SvgBlankState from './blank_state.vue';
+import EmptyState from './empty_state.vue';
import NavigationControls from './nav_controls.vue';
-import { getParameterByName } from '~/lib/utils/common_utils';
-import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
import PipelinesFilteredSearch from './pipelines_filtered_search.vue';
-import { validateParams } from '../../utils';
-import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../../constants';
+import PipelinesTableComponent from './pipelines_table.vue';
export default {
components: {
- TablePagination,
+ EmptyState,
+ GlIcon,
+ GlLoadingIcon,
NavigationTabs,
NavigationControls,
PipelinesFilteredSearch,
- GlIcon,
+ PipelinesTableComponent,
+ SvgBlankState,
+ TablePagination,
},
- mixins: [pipelinesMixin, CIPaginationMixin],
+ mixins: [PipelinesMixin],
props: {
store: {
type: Object,
@@ -217,6 +223,20 @@ export default {
this.requestData = { page: this.page, scope: this.scope, ...this.validatedParams };
},
methods: {
+ onChangeTab(scope) {
+ if (this.scope === scope) {
+ return;
+ }
+
+ let params = {
+ scope,
+ page: '1',
+ };
+
+ params = this.onChangeWithFilter(params);
+
+ this.updateContent(params);
+ },
successCallback(resp) {
// Because we are polling & the user is interacting verify if the response received
// matches the last request made
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
index 1ea71610897..6890cbb9bed 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
@@ -1,7 +1,7 @@
<script>
-import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from '~/flash';
import { s__, __, sprintf } from '~/locale';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
import eventHub from '../../event_hub';
@@ -11,10 +11,10 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
- GlIcon,
GlCountdown,
- GlButton,
- GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
},
props: {
actions: {
@@ -61,7 +61,7 @@ export default {
})
.catch(() => {
this.isLoading = false;
- flash(__('An error occurred while making the request.'));
+ createFlash({ message: __('An error occurred while making the request.') });
});
},
@@ -76,39 +76,27 @@ export default {
};
</script>
<template>
- <div class="btn-group">
- <button
- v-gl-tooltip
- type="button"
- :disabled="isLoading"
- class="dropdown-new btn btn-default js-pipeline-dropdown-manual-actions"
- :title="__('Run manual or delayed jobs')"
- data-toggle="dropdown"
- :aria-label="__('Run manual or delayed jobs')"
+ <gl-dropdown
+ v-gl-tooltip
+ :title="__('Run manual or delayed jobs')"
+ :loading="isLoading"
+ data-testid="pipelines-manual-actions-dropdown"
+ right
+ icon="play"
+ >
+ <gl-dropdown-item
+ v-for="action in actions"
+ :key="action.path"
+ :disabled="isActionDisabled(action)"
+ @click="onClickAction(action)"
>
- <gl-icon name="play" class="icon-play" />
- <gl-icon name="chevron-down" />
- <gl-loading-icon v-if="isLoading" />
- </button>
-
- <ul class="dropdown-menu dropdown-menu-right">
- <li v-for="action in actions" :key="action.path">
- <gl-button
- category="tertiary"
- :class="{ disabled: isActionDisabled(action) }"
- :disabled="isActionDisabled(action)"
- class="js-pipeline-action-link"
- @click="onClickAction(action)"
- >
- <div class="d-flex justify-content-between flex-wrap">
- {{ action.name }}
- <span v-if="action.scheduled_at">
- <gl-icon name="clock" />
- <gl-countdown :end-date-string="action.scheduled_at" />
- </span>
- </div>
- </gl-button>
- </li>
- </ul>
- </div>
+ <div class="gl-display-flex gl-justify-content-space-between gl-flex-wrap">
+ {{ action.name }}
+ <span v-if="action.scheduled_at">
+ <gl-icon name="clock" />
+ <gl-countdown :end-date-string="action.scheduled_at" />
+ </span>
+ </div>
+ </gl-dropdown-item>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
index 127503f1307..492c562ec5c 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
@@ -2,10 +2,10 @@
import { GlFilteredSearch } from '@gitlab/ui';
import { map } from 'lodash';
import { __, s__ } from '~/locale';
-import PipelineTriggerAuthorToken from './tokens/pipeline_trigger_author_token.vue';
import PipelineBranchNameToken from './tokens/pipeline_branch_name_token.vue';
import PipelineStatusToken from './tokens/pipeline_status_token.vue';
import PipelineTagNameToken from './tokens/pipeline_tag_name_token.vue';
+import PipelineTriggerAuthorToken from './tokens/pipeline_trigger_author_token.vue';
export default {
userType: 'username',
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 6c60594efca..24c67184e56 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
@@ -1,8 +1,8 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
-import PipelinesTableRowComponent from './pipelines_table_row.vue';
-import PipelineStopModal from './pipeline_stop_modal.vue';
import eventHub from '../../event_hub';
+import PipelineStopModal from './pipeline_stop_modal.vue';
+import PipelinesTableRowComponent from './pipelines_table_row.vue';
/**
* Pipelines Table Component.
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
index b6c4e617a90..572abe2a24a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
@@ -1,22 +1,17 @@
<script>
import { GlButton, GlTooltipDirective, GlModalDirective } from '@gitlab/ui';
-import eventHub from '../../event_hub';
import { __ } from '~/locale';
+import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+import CommitComponent from '~/vue_shared/components/commit.vue';
+import { PIPELINES_TABLE } from '../../constants';
+import eventHub from '../../event_hub';
+import PipelineTriggerer from './pipeline_triggerer.vue';
+import PipelineUrl from './pipeline_url.vue';
import PipelinesActionsComponent from './pipelines_actions.vue';
import PipelinesArtifactsComponent from './pipelines_artifacts.vue';
-import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import PipelineStage from './stage.vue';
-import PipelineUrl from './pipeline_url.vue';
-import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelinesTimeago from './time_ago.vue';
-import CommitComponent from '~/vue_shared/components/commit.vue';
-import { PIPELINES_TABLE } from '../../constants';
-/**
- * Pipeline table row.
- *
- * Given the received object renders a table row in the pipelines' table.
- */
export default {
i18n: {
cancelTitle: __('Cancel'),
@@ -127,116 +122,30 @@ export default {
return commitAuthorInformation;
},
-
- /**
- * If provided, returns the commit tag.
- * Needed to render the commit component column.
- *
- * @returns {String|Undefined}
- */
commitTag() {
- if (this.pipeline.ref && this.pipeline.ref.tag) {
- return this.pipeline.ref.tag;
- }
- return undefined;
+ return this.pipeline?.ref?.tag;
},
-
- /**
- * If provided, returns the commit ref.
- * Needed to render the commit component column.
- *
- * Matches `path` prop sent in the API to `ref_url` prop needed
- * in the commit component.
- *
- * @returns {Object|Undefined}
- */
commitRef() {
- if (this.pipeline.ref) {
- return Object.keys(this.pipeline.ref).reduce((accumulator, prop) => {
- if (prop === 'path') {
- accumulator.ref_url = this.pipeline.ref[prop];
- } else {
- accumulator[prop] = this.pipeline.ref[prop];
- }
- return accumulator;
- }, {});
- }
-
- return undefined;
+ return this.pipeline?.ref;
},
-
- /**
- * If provided, returns the commit url.
- * Needed to render the commit component column.
- *
- * @returns {String|Undefined}
- */
commitUrl() {
- if (this.pipeline.commit && this.pipeline.commit.commit_path) {
- return this.pipeline.commit.commit_path;
- }
- return undefined;
+ return this.pipeline?.commit?.commit_path;
},
-
- /**
- * If provided, returns the commit short sha.
- * Needed to render the commit component column.
- *
- * @returns {String|Undefined}
- */
commitShortSha() {
- if (this.pipeline.commit && this.pipeline.commit.short_id) {
- return this.pipeline.commit.short_id;
- }
- return undefined;
+ return this.pipeline?.commit?.short_id;
},
-
- /**
- * If provided, returns the commit title.
- * Needed to render the commit component column.
- *
- * @returns {String|Undefined}
- */
commitTitle() {
- if (this.pipeline.commit && this.pipeline.commit.title) {
- return this.pipeline.commit.title;
- }
- return undefined;
+ return this.pipeline?.commit?.title;
},
-
- /**
- * Timeago components expects a number
- *
- * @return {type} description
- */
pipelineDuration() {
- if (this.pipeline.details && this.pipeline.details.duration) {
- return this.pipeline.details.duration;
- }
-
- return 0;
+ return this.pipeline?.details?.duration ?? 0;
},
-
- /**
- * Timeago component expects a String.
- *
- * @return {String}
- */
pipelineFinishedAt() {
- if (this.pipeline.details && this.pipeline.details.finished_at) {
- return this.pipeline.details.finished_at;
- }
-
- return '';
+ return this.pipeline?.details?.finished_at ?? '';
},
-
pipelineStatus() {
- if (this.pipeline.details && this.pipeline.details.status) {
- return this.pipeline.details.status;
- }
- return {};
+ return this.pipeline?.details?.status ?? {};
},
-
displayPipelineActions() {
return (
this.pipeline.flags.retryable ||
@@ -245,11 +154,9 @@ export default {
this.pipeline.details.artifacts.length
);
},
-
isChildView() {
return this.viewType === 'child';
},
-
isCancelling() {
return this.cancelingPipeline === this.pipeline.id;
},
@@ -355,7 +262,7 @@ export default {
:title="$options.i18n.redeployTitle"
:disabled="isRetrying"
:loading="isRetrying"
- class="js-pipelines-retry-button btn-retry"
+ class="js-pipelines-retry-button"
data-qa-selector="pipeline_retry_button"
icon="repeat"
variant="default"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
index a9154d93194..f5dfb9e72d5 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
@@ -11,27 +11,27 @@
* 3. Merge request widget
* 4. Commit widget
*/
-
+import { GlDropdown, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import $ from 'jquery';
-import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { PIPELINES_TABLE } from '../../constants';
import eventHub from '../../event_hub';
import JobItem from '../graph/job_item.vue';
-import { PIPELINES_TABLE } from '../../constants';
export default {
components: {
GlIcon,
- JobItem,
GlLoadingIcon,
+ GlDropdown,
+ JobItem,
},
-
directives: {
GlTooltip: GlTooltipDirective,
},
-
+ mixins: [glFeatureFlagsMixin()],
props: {
stage: {
type: Object,
@@ -50,30 +50,25 @@ export default {
default: '',
},
},
-
data() {
return {
isLoading: false,
- dropdownContent: '',
+ dropdownContent: [],
};
},
-
computed: {
- dropdownClass() {
- return this.dropdownContent.length > 0
- ? 'js-builds-dropdown-container'
- : 'js-builds-dropdown-loading';
+ isCiMiniPipelineGlDropdown() {
+ // Feature flag ci_mini_pipeline_gl_dropdown
+ // See more at https://gitlab.com/gitlab-org/gitlab/-/issues/300400
+ return this.glFeatures?.ciMiniPipelineGlDropdown;
},
-
triggerButtonClass() {
return `ci-status-icon-${this.stage.status.group}`;
},
-
borderlessIcon() {
return `${this.stage.status.icon}_borderless`;
},
},
-
watch: {
updateDropdown() {
if (this.updateDropdown && this.isDropdownOpen() && !this.isLoading) {
@@ -81,14 +76,17 @@ export default {
}
},
},
-
updated() {
- if (this.dropdownContent.length > 0) {
+ if (!this.isCiMiniPipelineGlDropdown && this.dropdownContent.length) {
this.stopDropdownClickPropagation();
}
},
-
methods: {
+ onShowDropdown() {
+ eventHub.$emit('clickedDropdown');
+ this.isLoading = true;
+ this.fetchJobs();
+ },
onClickStage() {
if (!this.isDropdownOpen()) {
eventHub.$emit('clickedDropdown');
@@ -96,7 +94,6 @@ export default {
this.fetchJobs();
}
},
-
fetchJobs() {
axios
.get(this.stage.dropdown_path)
@@ -105,13 +102,16 @@ export default {
this.isLoading = false;
})
.catch(() => {
- this.closeDropdown();
+ if (this.isCiMiniPipelineGlDropdown) {
+ this.$refs.stageGlDropdown.hide();
+ } else {
+ this.closeDropdown();
+ }
this.isLoading = false;
Flash(__('Something went wrong on our end.'));
});
},
-
/**
* When the user right clicks or cmd/ctrl + click in the job name
* the dropdown should not be closed and the link should open in another tab,
@@ -119,6 +119,8 @@ export default {
*
* Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component.
+ *
+ * Note: This should be removed once ci_mini_pipeline_gl_dropdown FF is removed as true.
*/
stopDropdownClickPropagation() {
$(
@@ -128,23 +130,24 @@ export default {
e.stopPropagation();
});
},
-
closeDropdown() {
if (this.isDropdownOpen()) {
$(this.$refs.dropdown).dropdown('toggle');
}
},
-
isDropdownOpen() {
return this.$el.classList.contains('show');
},
-
pipelineActionRequestComplete() {
if (this.type === PIPELINES_TABLE) {
// warn the table to update
eventHub.$emit('refreshPipelinesTable');
+ return;
+ }
+ // close the dropdown in mr widget
+ if (this.isCiMiniPipelineGlDropdown) {
+ this.$refs.stageGlDropdown.hide();
} else {
- // close the dropdown in mr widget
$(this.$refs.dropdown).dropdown('toggle');
}
},
@@ -154,31 +157,30 @@ export default {
<template>
<div class="dropdown">
- <button
- id="stageDropdown"
- ref="dropdown"
+ <gl-dropdown
+ v-if="isCiMiniPipelineGlDropdown"
+ ref="stageGlDropdown"
v-gl-tooltip.hover
- :class="triggerButtonClass"
+ data-testid="mini-pipeline-graph-dropdown"
:title="stage.title"
- class="mini-pipeline-graph-dropdown-toggle js-builds-dropdown-button"
- data-toggle="dropdown"
- data-display="static"
- type="button"
- aria-haspopup="true"
- aria-expanded="false"
- @click="onClickStage"
- >
- <span :aria-label="stage.title" aria-hidden="true" class="gl-pointer-events-none">
- <gl-icon :name="borderlessIcon" />
- </span>
- </button>
-
- <div
- class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
- aria-labelledby="stageDropdown"
+ variant="link"
+ :lazy="true"
+ :popper-opts="{ placement: 'bottom' }"
+ :toggle-class="['mini-pipeline-graph-gl-dropdown-toggle', triggerButtonClass]"
+ menu-class="mini-pipeline-graph-dropdown-menu"
+ @show="onShowDropdown"
>
+ <template #button-content>
+ <span class="gl-pointer-events-none">
+ <gl-icon :name="borderlessIcon" />
+ </span>
+ </template>
<gl-loading-icon v-if="isLoading" />
- <ul v-else class="js-builds-dropdown-list scrollable-menu">
+ <ul
+ v-else
+ class="js-builds-dropdown-list scrollable-menu"
+ data-testid="mini-pipeline-graph-dropdown-menu-list"
+ >
<li v-for="job in dropdownContent" :key="job.id">
<job-item
:dropdown-length="dropdownContent.length"
@@ -188,6 +190,45 @@ export default {
/>
</li>
</ul>
- </div>
+ </gl-dropdown>
+
+ <template v-else>
+ <button
+ id="stageDropdown"
+ ref="dropdown"
+ v-gl-tooltip.hover
+ :class="triggerButtonClass"
+ :title="stage.title"
+ class="mini-pipeline-graph-dropdown-toggle"
+ data-testid="mini-pipeline-graph-dropdown-toggle"
+ data-toggle="dropdown"
+ data-display="static"
+ type="button"
+ aria-haspopup="true"
+ aria-expanded="false"
+ @click="onClickStage"
+ >
+ <span :aria-label="stage.title" aria-hidden="true" class="gl-pointer-events-none">
+ <gl-icon :name="borderlessIcon" />
+ </span>
+ </button>
+
+ <div
+ class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
+ aria-labelledby="stageDropdown"
+ >
+ <gl-loading-icon v-if="isLoading" />
+ <ul v-else class="js-builds-dropdown-list scrollable-menu">
+ <li v-for="job in dropdownContent" :key="job.id">
+ <job-item
+ :dropdown-length="dropdownContent.length"
+ :job="job"
+ css-class-job-name="mini-pipeline-graph-dropdown-item"
+ @pipelineActionRequestComplete="pipelineActionRequestComplete"
+ />
+ </li>
+ </ul>
+ </div>
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
index 24456574a6f..20a232beb83 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue
@@ -2,8 +2,8 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import { FETCH_BRANCH_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { FETCH_BRANCH_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
export default {
components: {
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
index 1241803c612..4a8d89ebe37 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue
@@ -2,8 +2,8 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
import { debounce } from 'lodash';
import Api from '~/api';
-import { FETCH_TAG_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { FETCH_TAG_ERROR_MESSAGE, FILTER_PIPELINES_SEARCH_DELAY } from '../../../constants';
export default {
components: {
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue b/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
index 504cf138d07..2edc84e62cb 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_case_details.vue
@@ -1,12 +1,13 @@
<script>
-import { GlModal } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { GlBadge, GlModal } from '@gitlab/ui';
+import { __, n__, sprintf } from '~/locale';
import CodeBlock from '~/vue_shared/components/code_block.vue';
export default {
name: 'TestCaseDetails',
components: {
CodeBlock,
+ GlBadge,
GlModal,
},
props: {
@@ -17,13 +18,37 @@ export default {
testCase: {
type: Object,
required: true,
- validator: ({ classname, formattedTime, name }) =>
- Boolean(classname) && Boolean(formattedTime) && Boolean(name),
+ },
+ },
+ computed: {
+ failureHistoryMessage() {
+ if (!this.hasRecentFailures) {
+ return null;
+ }
+
+ return sprintf(
+ n__(
+ 'Reports|Failed %{count} time in %{baseBranch} in the last 14 days',
+ 'Reports|Failed %{count} times in %{baseBranch} in the last 14 days',
+ this.recentFailures.count,
+ ),
+ {
+ count: this.recentFailures.count,
+ baseBranch: this.recentFailures.base_branch,
+ },
+ );
+ },
+ hasRecentFailures() {
+ return Boolean(this.recentFailures);
+ },
+ recentFailures() {
+ return this.testCase.recent_failures;
},
},
text: {
name: __('Name'),
duration: __('Execution time'),
+ history: __('History'),
trace: __('System output'),
},
modalCloseButton: {
@@ -53,6 +78,13 @@ export default {
</div>
</div>
+ <div v-if="testCase.recent_failures" class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3">
+ <strong class="gl-text-right col-sm-3">{{ $options.text.history }}</strong>
+ <div class="col-sm-9" data-testid="test-case-recent-failures">
+ <gl-badge variant="warning">{{ failureHistoryMessage }}</gl-badge>
+ </div>
+ </div>
+
<div
v-if="testCase.system_output"
class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3"
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
index a56dcf48d92..58d60e2a185 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
import TestSuiteTable from './test_suite_table.vue';
import TestSummary from './test_summary.vue';
import TestSummaryTable from './test_summary_table.vue';
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
index 4b4fb6082c6..51373e712ff 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
@@ -1,13 +1,14 @@
<script>
-import { mapState, mapGetters, mapActions } from 'vuex';
import {
GlModalDirective,
GlTooltipDirective,
GlFriendlyWrap,
GlIcon,
+ GlLink,
GlButton,
GlPagination,
} from '@gitlab/ui';
+import { mapState, mapGetters, mapActions } from 'vuex';
import { __ } from '~/locale';
import TestCaseDetails from './test_case_details.vue';
@@ -16,6 +17,7 @@ export default {
components: {
GlIcon,
GlFriendlyWrap,
+ GlLink,
GlButton,
GlPagination,
TestCaseDetails,
@@ -97,8 +99,11 @@ export default {
<div class="table-section section-10 section-wrap">
<div role="rowheader" class="table-mobile-header">{{ __('Filename') }}</div>
<div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break">
- <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.file" />
+ <gl-link v-if="testCase.file" :href="testCase.filePath" target="_blank">
+ <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.file" />
+ </gl-link>
<gl-button
+ v-if="testCase.file"
v-gl-tooltip
size="small"
category="tertiary"
@@ -114,7 +119,7 @@ export default {
<div role="rowheader" class="table-mobile-header">{{ __('Status') }}</div>
<div class="table-mobile-content text-center">
<div
- class="add-border ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
+ class="ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
:class="`ci-status-icon-${testCase.status}`"
>
<gl-icon :size="24" :name="testCase.icon" />
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
index 5f9c0be3ccc..2b44ce57faa 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { s__ } from '~/locale';
export default {
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
deleted file mode 100644
index 22cdb6b8f72..00000000000
--- a/app/assets/javascripts/pipelines/mixins/pipelines.js
+++ /dev/null
@@ -1,188 +0,0 @@
-import Visibility from 'visibilityjs';
-import { GlLoadingIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import Poll from '~/lib/utils/poll';
-import EmptyState from '../components/pipelines_list/empty_state.vue';
-import SvgBlankState from '../components/pipelines_list/blank_state.vue';
-import PipelinesTableComponent from '../components/pipelines_list/pipelines_table.vue';
-import eventHub from '../event_hub';
-import { CANCEL_REQUEST } from '../constants';
-
-export default {
- components: {
- PipelinesTableComponent,
- SvgBlankState,
- EmptyState,
- GlLoadingIcon,
- },
- data() {
- return {
- isLoading: false,
- hasError: false,
- isMakingRequest: false,
- updateGraphDropdown: false,
- hasMadeRequest: false,
- };
- },
- computed: {
- shouldRenderPagination() {
- return !this.isLoading;
- },
- },
- beforeMount() {
- this.poll = new Poll({
- resource: this.service,
- method: 'getPipelines',
- data: this.requestData ? this.requestData : undefined,
- successCallback: this.successCallback,
- errorCallback: this.errorCallback,
- notificationCallback: this.setIsMakingRequest,
- });
-
- if (!Visibility.hidden()) {
- this.isLoading = true;
- this.poll.makeRequest();
- } else {
- // If tab is not visible we need to make the first request so we don't show the empty
- // state without knowing if there are any pipelines
- this.fetchPipelines();
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
-
- eventHub.$on('postAction', this.postAction);
- eventHub.$on('retryPipeline', this.postAction);
- eventHub.$on('clickedDropdown', this.updateTable);
- eventHub.$on('updateTable', this.updateTable);
- eventHub.$on('refreshPipelinesTable', this.fetchPipelines);
- eventHub.$on('runMergeRequestPipeline', this.runMergeRequestPipeline);
- },
- beforeDestroy() {
- eventHub.$off('postAction', this.postAction);
- eventHub.$off('retryPipeline', this.postAction);
- eventHub.$off('clickedDropdown', this.updateTable);
- eventHub.$off('updateTable', this.updateTable);
- eventHub.$off('refreshPipelinesTable', this.fetchPipelines);
- eventHub.$off('runMergeRequestPipeline', this.runMergeRequestPipeline);
- },
- destroyed() {
- this.poll.stop();
- },
- methods: {
- /**
- * Handles URL and query parameter changes.
- * When the user uses the pagination or the tabs,
- * - update URL
- * - Make API request to the server with new parameters
- * - Update the polling function
- * - Update the internal state
- */
- updateContent(parameters) {
- this.updateInternalState(parameters);
-
- // fetch new data
- return this.service
- .getPipelines(this.requestData)
- .then((response) => {
- this.isLoading = false;
- this.successCallback(response);
-
- this.poll.enable({ data: this.requestData, response });
- })
- .catch(() => {
- this.isLoading = false;
- this.errorCallback();
-
- // restart polling
- this.poll.restart({ data: this.requestData });
- });
- },
- updateTable() {
- // Cancel ongoing request
- if (this.isMakingRequest) {
- this.service.cancelationSource.cancel(CANCEL_REQUEST);
- }
- // Stop polling
- this.poll.stop();
- // Restarting the poll also makes an initial request
- return this.poll.restart();
- },
- fetchPipelines() {
- if (!this.isMakingRequest) {
- this.isLoading = true;
-
- this.getPipelines();
- }
- },
- getPipelines() {
- return this.service
- .getPipelines(this.requestData)
- .then((response) => this.successCallback(response))
- .catch((error) => this.errorCallback(error));
- },
- setCommonData(pipelines) {
- this.store.storePipelines(pipelines);
- this.isLoading = false;
- this.updateGraphDropdown = true;
- this.hasMadeRequest = true;
-
- // In case the previous polling request returned an error, we need to reset it
- if (this.hasError) {
- this.hasError = false;
- }
- },
- errorCallback(error) {
- this.hasMadeRequest = true;
- this.isLoading = false;
-
- if (error && error.message && error.message !== CANCEL_REQUEST) {
- this.hasError = true;
- this.updateGraphDropdown = false;
- }
- },
- setIsMakingRequest(isMakingRequest) {
- this.isMakingRequest = isMakingRequest;
-
- if (isMakingRequest) {
- this.updateGraphDropdown = false;
- }
- },
- postAction(endpoint) {
- this.service
- .postAction(endpoint)
- .then(() => this.updateTable())
- .catch(() => createFlash(__('An error occurred while making the request.')));
- },
-
- /**
- * When the user clicks on the run pipeline button
- * we toggle the state of the button to be disabled
- *
- * Once the post request has finished, we fetch the
- * pipelines again to show the most recent data
- *
- * Once the pipeline has been updated, we toggle back the
- * loading state and re-enable the run pipeline button
- */
- runMergeRequestPipeline(options) {
- this.store.toggleIsRunningPipeline(true);
-
- this.service
- .runMRPipeline(options)
- .then(() => this.updateTable())
- .catch(() => {
- createFlash(
- __('An error occurred while trying to run a new pipeline for this Merge Request.'),
- );
- })
- .finally(() => this.store.toggleIsRunningPipeline(false));
- },
- },
-};
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
new file mode 100644
index 00000000000..2321728e30c
--- /dev/null
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -0,0 +1,217 @@
+import Visibility from 'visibilityjs';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+import Poll from '~/lib/utils/poll';
+import { __ } from '~/locale';
+import { validateParams } from '~/pipelines/utils';
+import { CANCEL_REQUEST } from '../constants';
+import eventHub from '../event_hub';
+
+export default {
+ data() {
+ return {
+ isLoading: false,
+ hasError: false,
+ isMakingRequest: false,
+ updateGraphDropdown: false,
+ hasMadeRequest: false,
+ };
+ },
+ computed: {
+ shouldRenderPagination() {
+ return !this.isLoading;
+ },
+ },
+ beforeMount() {
+ this.poll = new Poll({
+ resource: this.service,
+ method: 'getPipelines',
+ data: this.requestData ? this.requestData : undefined,
+ successCallback: this.successCallback,
+ errorCallback: this.errorCallback,
+ notificationCallback: this.setIsMakingRequest,
+ });
+
+ if (!Visibility.hidden()) {
+ this.isLoading = true;
+ this.poll.makeRequest();
+ } else {
+ // If tab is not visible we need to make the first request so we don't show the empty
+ // state without knowing if there are any pipelines
+ this.fetchPipelines();
+ }
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ this.poll.restart();
+ } else {
+ this.poll.stop();
+ }
+ });
+
+ eventHub.$on('postAction', this.postAction);
+ eventHub.$on('retryPipeline', this.postAction);
+ eventHub.$on('clickedDropdown', this.updateTable);
+ eventHub.$on('updateTable', this.updateTable);
+ eventHub.$on('refreshPipelinesTable', this.fetchPipelines);
+ eventHub.$on('runMergeRequestPipeline', this.runMergeRequestPipeline);
+ },
+ beforeDestroy() {
+ eventHub.$off('postAction', this.postAction);
+ eventHub.$off('retryPipeline', this.postAction);
+ eventHub.$off('clickedDropdown', this.updateTable);
+ eventHub.$off('updateTable', this.updateTable);
+ eventHub.$off('refreshPipelinesTable', this.fetchPipelines);
+ eventHub.$off('runMergeRequestPipeline', this.runMergeRequestPipeline);
+ },
+ destroyed() {
+ this.poll.stop();
+ },
+ methods: {
+ updateInternalState(parameters) {
+ this.poll.stop();
+
+ const queryString = Object.keys(parameters)
+ .map((parameter) => {
+ const value = parameters[parameter];
+ // update internal state for UI
+ this[parameter] = value;
+ return `${parameter}=${encodeURIComponent(value)}`;
+ })
+ .join('&');
+
+ // update polling parameters
+ this.requestData = parameters;
+
+ historyPushState(buildUrlWithCurrentLocation(`?${queryString}`));
+
+ this.isLoading = true;
+ },
+ /**
+ * Handles URL and query parameter changes.
+ * When the user uses the pagination or the tabs,
+ * - update URL
+ * - Make API request to the server with new parameters
+ * - Update the polling function
+ * - Update the internal state
+ */
+ updateContent(parameters) {
+ this.updateInternalState(parameters);
+
+ // fetch new data
+ return this.service
+ .getPipelines(this.requestData)
+ .then((response) => {
+ this.isLoading = false;
+ this.successCallback(response);
+
+ this.poll.enable({ data: this.requestData, response });
+ })
+ .catch(() => {
+ this.isLoading = false;
+ this.errorCallback();
+
+ // restart polling
+ this.poll.restart({ data: this.requestData });
+ });
+ },
+ updateTable() {
+ // Cancel ongoing request
+ if (this.isMakingRequest) {
+ this.service.cancelationSource.cancel(CANCEL_REQUEST);
+ }
+ // Stop polling
+ this.poll.stop();
+ // Restarting the poll also makes an initial request
+ return this.poll.restart();
+ },
+ fetchPipelines() {
+ if (!this.isMakingRequest) {
+ this.isLoading = true;
+
+ this.getPipelines();
+ }
+ },
+ getPipelines() {
+ return this.service
+ .getPipelines(this.requestData)
+ .then((response) => this.successCallback(response))
+ .catch((error) => this.errorCallback(error));
+ },
+ setCommonData(pipelines) {
+ this.store.storePipelines(pipelines);
+ this.isLoading = false;
+ this.updateGraphDropdown = true;
+ this.hasMadeRequest = true;
+
+ // In case the previous polling request returned an error, we need to reset it
+ if (this.hasError) {
+ this.hasError = false;
+ }
+ },
+ errorCallback(error) {
+ this.hasMadeRequest = true;
+ this.isLoading = false;
+
+ if (error && error.message && error.message !== CANCEL_REQUEST) {
+ this.hasError = true;
+ this.updateGraphDropdown = false;
+ }
+ },
+ setIsMakingRequest(isMakingRequest) {
+ this.isMakingRequest = isMakingRequest;
+
+ if (isMakingRequest) {
+ this.updateGraphDropdown = false;
+ }
+ },
+ postAction(endpoint) {
+ this.service
+ .postAction(endpoint)
+ .then(() => this.updateTable())
+ .catch(() => createFlash(__('An error occurred while making the request.')));
+ },
+
+ /**
+ * When the user clicks on the run pipeline button
+ * we toggle the state of the button to be disabled
+ *
+ * Once the post request has finished, we fetch the
+ * pipelines again to show the most recent data
+ *
+ * Once the pipeline has been updated, we toggle back the
+ * loading state and re-enable the run pipeline button
+ */
+ runMergeRequestPipeline(options) {
+ this.store.toggleIsRunningPipeline(true);
+
+ this.service
+ .runMRPipeline(options)
+ .then(() => this.updateTable())
+ .catch(() => {
+ createFlash(
+ __('An error occurred while trying to run a new pipeline for this Merge Request.'),
+ );
+ })
+ .finally(() => this.store.toggleIsRunningPipeline(false));
+ },
+ onChangePage(page) {
+ /* URLS parameters are strings, we need to parse to match types */
+ let params = {
+ page: Number(page).toString(),
+ };
+
+ if (this.scope) {
+ params.scope = this.scope;
+ }
+
+ params = this.onChangeWithFilter(params);
+
+ this.updateContent(params);
+ },
+
+ onChangeWithFilter(params) {
+ return { ...params, ...validateParams(this.requestData) };
+ },
+ },
+};
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 133608b9801..f837851e5c1 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -1,16 +1,13 @@
import Vue from 'vue';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import Translate from '~/vue_shared/translate';
import { __ } from '~/locale';
-import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
+import Translate from '~/vue_shared/translate';
import PipelineGraphLegacy from './components/graph/graph_component_legacy.vue';
-import createDagApp from './pipeline_details_dag';
-import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin';
-import legacyPipelineHeader from './components/legacy_header_component.vue';
-import eventHub from './event_hub';
+import { reportToSentry } from './components/graph/utils';
import TestReports from './components/test_reports/test_reports.vue';
+import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin';
+import createDagApp from './pipeline_details_dag';
import createTestReportsStore from './stores/test_reports';
-import { reportToSentry } from './components/graph/utils';
Vue.use(Translate);
@@ -59,62 +56,11 @@ const createLegacyPipelinesDetailApp = (mediator) => {
});
};
-const createLegacyPipelineHeaderApp = (mediator) => {
- if (!document.querySelector(SELECTORS.PIPELINE_HEADER)) {
- return;
- }
- // eslint-disable-next-line no-new
- new Vue({
- el: SELECTORS.PIPELINE_HEADER,
- components: {
- legacyPipelineHeader,
- },
- data() {
- return {
- mediator,
- };
- },
- created() {
- eventHub.$on('headerPostAction', this.postAction);
- eventHub.$on('headerDeleteAction', this.deleteAction);
- },
- beforeDestroy() {
- eventHub.$off('headerPostAction', this.postAction);
- eventHub.$off('headerDeleteAction', this.deleteAction);
- },
- errorCaptured(err, _vm, info) {
- reportToSentry('pipeline_details_bundle_legacy', `error: ${err}, info: ${info}`);
- },
- methods: {
- postAction(path) {
- this.mediator.service
- .postAction(path)
- .then(() => this.mediator.refreshPipeline())
- .catch(() => Flash(__('An error occurred while making the request.')));
- },
- deleteAction(path) {
- this.mediator.stopPipelinePoll();
- this.mediator.service
- .deleteAction(path)
- .then(({ request }) => redirectTo(setUrlFragment(request.responseURL, 'delete_success')))
- .catch(() => Flash(__('An error occurred while deleting the pipeline.')));
- },
- },
- render(createElement) {
- return createElement('legacy-pipeline-header', {
- props: {
- isLoading: this.mediator.state.isLoading,
- pipeline: this.mediator.store.state.pipeline,
- },
- });
- },
- });
-};
-
const createTestDetails = () => {
const el = document.querySelector(SELECTORS.PIPELINE_TESTS);
- const { summaryEndpoint, suiteEndpoint } = el?.dataset || {};
+ const { blobPath, summaryEndpoint, suiteEndpoint } = el?.dataset || {};
const testReportsStore = createTestReportsStore({
+ blobPath,
summaryEndpoint,
suiteEndpoint,
});
@@ -132,26 +78,16 @@ const createTestDetails = () => {
});
};
-export default async function () {
+export default async function initPipelineDetailsBundle() {
createTestDetails();
createDagApp();
- const { dataset } = document.querySelector(SELECTORS.PIPELINE_DETAILS);
- let mediator;
+ const canShowNewPipelineDetails =
+ gon.features.graphqlPipelineDetails || gon.features.graphqlPipelineDetailsUsers;
- if (!gon.features.graphqlPipelineHeader || !gon.features.graphqlPipelineDetails) {
- try {
- const { default: PipelinesMediator } = await import(
- /* webpackChunkName: 'PipelinesMediator' */ './pipeline_details_mediator'
- );
- mediator = new PipelinesMediator({ endpoint: dataset.endpoint });
- mediator.fetchPipeline();
- } catch {
- Flash(__('An error occurred while loading the pipeline.'));
- }
- }
+ const { dataset } = document.querySelector(SELECTORS.PIPELINE_DETAILS);
- if (gon.features.graphqlPipelineDetails) {
+ if (canShowNewPipelineDetails) {
try {
const { createPipelinesDetailApp } = await import(
/* webpackChunkName: 'createPipelinesDetailApp' */ './pipeline_details_graph'
@@ -163,19 +99,21 @@ export default async function () {
Flash(__('An error occurred while loading the pipeline.'));
}
} else {
+ const { default: PipelinesMediator } = await import(
+ /* webpackChunkName: 'PipelinesMediator' */ './pipeline_details_mediator'
+ );
+ const mediator = new PipelinesMediator({ endpoint: dataset.endpoint });
+ mediator.fetchPipeline();
+
createLegacyPipelinesDetailApp(mediator);
}
- if (gon.features.graphqlPipelineHeader) {
- try {
- const { createPipelineHeaderApp } = await import(
- /* webpackChunkName: 'createPipelineHeaderApp' */ './pipeline_details_header'
- );
- createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER);
- } catch {
- Flash(__('An error occurred while loading a section of this page.'));
- }
- } else {
- createLegacyPipelineHeaderApp(mediator);
+ try {
+ const { createPipelineHeaderApp } = await import(
+ /* webpackChunkName: 'createPipelineHeaderApp' */ './pipeline_details_header'
+ );
+ createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER);
+ } catch {
+ Flash(__('An error occurred while loading a section of this page.'));
}
}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_dag.js b/app/assets/javascripts/pipelines/pipeline_details_dag.js
index d37c72a4f2a..4ee0ad462d2 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_dag.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_dag.js
@@ -12,7 +12,7 @@ const apolloProvider = new VueApollo({
const createDagApp = () => {
const el = document.querySelector('#js-pipeline-dag-vue');
- if (!window.gon?.features?.dagPipelineTab || !el) {
+ if (!el) {
return;
}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_graph.js b/app/assets/javascripts/pipelines/pipeline_details_graph.js
index 2d46bb5ec26..55f3731a3ca 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_graph.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_graph.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import PipelineGraphWrapper from './components/graph/graph_component_wrapper.vue';
import { GRAPHQL } from './components/graph/constants';
+import PipelineGraphWrapper from './components/graph/graph_component_wrapper.vue';
import { reportToSentry } from './components/graph/utils';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/pipelines/pipeline_details_mediator.js b/app/assets/javascripts/pipelines/pipeline_details_mediator.js
index 74c5fc45644..09637c25654 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_mediator.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_mediator.js
@@ -1,9 +1,9 @@
import Visibility from 'visibilityjs';
-import PipelineStore from './stores/pipeline_store';
import { deprecatedCreateFlash as Flash } from '../flash';
import Poll from '../lib/utils/poll';
import { __ } from '../locale';
import PipelineService from './services/pipeline_service';
+import PipelineStore from './stores/pipeline_store';
export default class pipelinesMediator {
constructor(options = {}) {
diff --git a/app/assets/javascripts/pipelines/pipelines_index.js b/app/assets/javascripts/pipelines/pipelines_index.js
index 4575a99f60f..7bcc51e18e5 100644
--- a/app/assets/javascripts/pipelines/pipelines_index.js
+++ b/app/assets/javascripts/pipelines/pipelines_index.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
-import { __ } from '~/locale';
-import { doesHashExistInUrl } from '~/lib/utils/url_utility';
+import Vue from 'vue';
import {
parseBoolean,
historyReplaceState,
buildUrlWithCurrentLocation,
} from '~/lib/utils/common_utils';
+import { doesHashExistInUrl } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import Translate from '~/vue_shared/translate';
import Pipelines from './components/pipelines_list/pipelines.vue';
import PipelinesStore from './stores/pipelines_store';
diff --git a/app/assets/javascripts/pipelines/services/pipelines_service.js b/app/assets/javascripts/pipelines/services/pipelines_service.js
index 0b06bcf243a..523ca13b6c3 100644
--- a/app/assets/javascripts/pipelines/services/pipelines_service.js
+++ b/app/assets/javascripts/pipelines/services/pipelines_service.js
@@ -1,5 +1,5 @@
-import axios from '../../lib/utils/axios_utils';
import Api from '~/api';
+import axios from '../../lib/utils/axios_utils';
import { validateParams } from '../utils';
export default class PipelinesService {
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/actions.js b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
index 3c664457756..6de345233ae 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/actions.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
@@ -1,7 +1,7 @@
-import axios from '~/lib/utils/axios_utils';
-import * as types from './mutation_types';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
+import * as types from './mutation_types';
export const fetchSummary = ({ state, commit, dispatch }) => {
dispatch('toggleLoading');
@@ -28,16 +28,12 @@ export const fetchTestSuite = ({ state, commit, dispatch }, index) => {
dispatch('toggleLoading');
- const { name = '', build_ids = [] } = state.testReports?.test_suites?.[index] || {};
+ const { build_ids = [] } = state.testReports?.test_suites?.[index] || {};
// Replacing `/:suite_name.json` with the name of the suite. Including the extra characters
// to ensure that we replace exactly the template part of the URL string
- const endpoint = state.suiteEndpoint?.replace(
- '/:suite_name.json',
- `/${encodeURIComponent(name)}.json`,
- );
return axios
- .get(endpoint, { params: { build_ids } })
+ .get(state.suiteEndpoint, { params: { build_ids } })
.then(({ data }) => commit(types.SET_SUITE, { suite: data, index }))
.catch(() => {
createFlash(s__('TestReports|There was an error fetching the test suite.'));
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/getters.js b/app/assets/javascripts/pipelines/stores/test_reports/getters.js
index c31e7dd114f..03680de0fa9 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/getters.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/getters.js
@@ -1,4 +1,4 @@
-import { addIconStatus, formattedTime } from './utils';
+import { addIconStatus, formatFilePath, formattedTime } from './utils';
export const getTestSuites = (state) => {
const { test_suites: testSuites = [] } = state.testReports;
@@ -17,7 +17,15 @@ export const getSuiteTests = (state) => {
const { page, perPage } = state.pageInfo;
const start = (page - 1) * perPage;
- return testCases.map(addIconStatus).slice(start, start + perPage);
+ return testCases
+ .map((testCase) => ({
+ ...testCase,
+ classname: testCase.classname || '',
+ name: testCase.name || '',
+ filePath: testCase.file ? `${state.blobPath}/${formatFilePath(testCase.file)}` : null,
+ }))
+ .map(addIconStatus)
+ .slice(start, start + perPage);
};
export const getSuiteTestCount = (state) => getSelectedSuite(state)?.test_cases?.length || 0;
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/index.js b/app/assets/javascripts/pipelines/stores/test_reports/index.js
index 204dfc2fb01..64d4b8bafb1 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/index.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import state from './state';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
+import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/state.js b/app/assets/javascripts/pipelines/stores/test_reports/state.js
index 7f5da549a9d..0ee6f53fa58 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/state.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/state.js
@@ -1,4 +1,5 @@
-export default ({ summaryEndpoint = '', suiteEndpoint = '' }) => ({
+export default ({ blobPath = '', summaryEndpoint = '', suiteEndpoint = '' }) => ({
+ blobPath,
summaryEndpoint,
suiteEndpoint,
testReports: {},
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/utils.js b/app/assets/javascripts/pipelines/stores/test_reports/utils.js
index 5c1f27b166a..63a58798958 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/utils.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/utils.js
@@ -1,19 +1,28 @@
import { __, sprintf } from '../../../locale';
import { TestStatus } from '../../constants';
+/**
+ * Removes `./` from the beginning of a file path so it can be appended onto a blob path
+ * @param {String} file
+ * @returns {String} - formatted value
+ */
+export function formatFilePath(file) {
+ return file.replace(/^\.?\/*/, '');
+}
+
export function iconForTestStatus(status) {
switch (status) {
case TestStatus.SUCCESS:
- return 'status_success_borderless';
+ return 'status_success';
case TestStatus.FAILED:
- return 'status_failed_borderless';
+ return 'status_failed';
case TestStatus.ERROR:
- return 'status_warning_borderless';
+ return 'status_warning';
case TestStatus.SKIPPED:
- return 'status_skipped_borderless';
+ return 'status_skipped';
case TestStatus.UNKNOWN:
default:
- return 'status_notfound_borderless';
+ return 'status_notfound';
}
}
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 50bb23b7e63..22820fca43e 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -1,6 +1,6 @@
import { pickBy } from 'lodash';
-import { SUPPORTED_FILTER_PARAMETERS } from './constants';
import { createNodeDict } from './components/parsing_utils';
+import { SUPPORTED_FILTER_PARAMETERS } from './constants';
export const validateParams = (params) => {
return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val);
@@ -49,10 +49,10 @@ export const generateJobNeedsDict = (jobs = {}) => {
// to the list of `needs` to ensure we can properly reference it.
const group = jobs[job];
if (group.size > 1) {
- return [job, group.name, ...newNeeds];
+ return [job, group.name, newNeeds];
}
- return [job, ...newNeeds];
+ return [job, newNeeds];
})
.flat(Infinity);
};
diff --git a/app/assets/javascripts/popovers/index.js b/app/assets/javascripts/popovers/index.js
index eebbfbdcc68..7db669b8c52 100644
--- a/app/assets/javascripts/popovers/index.js
+++ b/app/assets/javascripts/popovers/index.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { toArray } from 'lodash';
+import Vue from 'vue';
import PopoversComponent from './components/popovers.vue';
let app;
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index f06dc72d365..2336cb18cb5 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -1,8 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
import csrf from '~/lib/utils/csrf';
+import { __, s__, sprintf } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 869fdccc800..c5478aa0226 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,9 +1,9 @@
<script>
-import { escape } from 'lodash';
import { GlSafeHtmlDirective as SafeHtml, GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { escape } from 'lodash';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__, sprintf } from '~/locale';
-import { deprecatedCreateFlash as Flash } from '~/flash';
export default {
components: {
diff --git a/app/assets/javascripts/profile/account/index.js b/app/assets/javascripts/profile/account/index.js
index 5e89002b3bc..00fe0bcf89b 100644
--- a/app/assets/javascripts/profile/account/index.js
+++ b/app/assets/javascripts/profile/account/index.js
@@ -1,7 +1,8 @@
import Vue from 'vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import Translate from '~/vue_shared/translate';
-import UpdateUsername from './components/update_username.vue';
import deleteAccountModal from './components/delete_account_modal.vue';
+import UpdateUsername from './components/update_username.vue';
export default () => {
Vue.use(Translate);
@@ -31,7 +32,7 @@ export default () => {
mounted() {
deleteAccountButton.classList.remove('disabled');
deleteAccountButton.addEventListener('click', () => {
- this.$root.$emit('bv::show::modal', 'delete-account-modal', '#delete-account-button');
+ this.$root.$emit(BV_SHOW_MODAL, 'delete-account-modal', '#delete-account-button');
});
},
render(createElement) {
diff --git a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
index 8b2006b7c5b..184ee3810ac 100644
--- a/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
+++ b/app/assets/javascripts/profile/preferences/components/profile_preferences.vue
@@ -1,31 +1,92 @@
<script>
-import { s__ } from '~/locale';
+import { GlButton } from '@gitlab/ui';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { INTEGRATION_VIEW_CONFIGS, i18n } from '../constants';
import IntegrationView from './integration_view.vue';
-const INTEGRATION_VIEW_CONFIGS = {
- sourcegraph: {
- title: s__('ProfilePreferences|Sourcegraph'),
- label: s__('ProfilePreferences|Enable integrated code intelligence on code views'),
- formName: 'sourcegraph_enabled',
- },
- gitpod: {
- title: s__('ProfilePreferences|Gitpod'),
- label: s__('ProfilePreferences|Enable Gitpod integration'),
- formName: 'gitpod_enabled',
- },
-};
+function updateClasses(bodyClasses = '', applicationTheme, layout) {
+ // Remove body class for any previous theme, re-add current one
+ document.body.classList.remove(...bodyClasses.split(' '));
+ document.body.classList.add(applicationTheme);
+
+ // Toggle container-fluid class
+ if (layout === 'fluid') {
+ document
+ .querySelector('.content-wrapper .container-fluid')
+ .classList.remove('container-limited');
+ } else {
+ document.querySelector('.content-wrapper .container-fluid').classList.add('container-limited');
+ }
+}
export default {
name: 'ProfilePreferences',
components: {
IntegrationView,
+ GlButton,
},
inject: {
integrationViews: {
default: [],
},
+ themes: {
+ default: [],
+ },
+ userFields: {
+ default: {},
+ },
+ formEl: 'formEl',
+ profilePreferencesPath: 'profilePreferencesPath',
+ bodyClasses: 'bodyClasses',
},
integrationViewConfigs: INTEGRATION_VIEW_CONFIGS,
+ i18n,
+ data() {
+ return {
+ isSubmitEnabled: true,
+ };
+ },
+ computed: {
+ applicationThemes() {
+ return this.themes.reduce((themes, theme) => {
+ const { id, ...rest } = theme;
+ return { ...themes, [id]: rest };
+ }, {});
+ },
+ },
+ created() {
+ this.formEl.addEventListener('ajax:beforeSend', this.handleLoading);
+ this.formEl.addEventListener('ajax:success', this.handleSuccess);
+ this.formEl.addEventListener('ajax:error', this.handleError);
+ },
+ beforeDestroy() {
+ this.formEl.removeEventListener('ajax:beforeSend', this.handleLoading);
+ this.formEl.removeEventListener('ajax:success', this.handleSuccess);
+ this.formEl.removeEventListener('ajax:error', this.handleError);
+ },
+ methods: {
+ handleLoading() {
+ this.isSubmitEnabled = false;
+ },
+ handleSuccess(customEvent) {
+ const formData = new FormData(this.formEl);
+ updateClasses(
+ this.bodyClasses,
+ this.applicationThemes[formData.get('user[theme_id]')].css_class,
+ this.selectedLayout,
+ );
+ const { message = this.$options.i18n.defaultSuccess, type = FLASH_TYPES.NOTICE } =
+ customEvent?.detail?.[0] || {};
+ createFlash({ message, type });
+ this.isSubmitEnabled = true;
+ },
+ handleError(customEvent) {
+ const { message = this.$options.i18n.defaultError, type = FLASH_TYPES.ALERT } =
+ customEvent?.detail?.[0] || {};
+ createFlash({ message, type });
+ this.isSubmitEnabled = true;
+ },
+ },
};
</script>
@@ -36,10 +97,10 @@ export default {
</div>
<div v-if="integrationViews.length" class="col-lg-4 profile-settings-sidebar">
<h4 class="gl-mt-0" data-testid="profile-preferences-integrations-heading">
- {{ s__('ProfilePreferences|Integrations') }}
+ {{ $options.i18n.integrations }}
</h4>
<p>
- {{ s__('ProfilePreferences|Customize integrations with third party services.') }}
+ {{ $options.i18n.integrationsDescription }}
</p>
</div>
<div v-if="integrationViews.length" class="col-lg-8">
@@ -52,5 +113,19 @@ export default {
:config="$options.integrationViewConfigs[view.name]"
/>
</div>
+ <div class="col-lg-4 profile-settings-sidebar"></div>
+ <div class="col-lg-8">
+ <div class="form-group">
+ <gl-button
+ variant="success"
+ name="commit"
+ type="submit"
+ :disabled="!isSubmitEnabled"
+ :value="$options.i18n.saveChanges"
+ >
+ {{ $options.i18n.saveChanges }}
+ </gl-button>
+ </div>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/profile/preferences/constants.js b/app/assets/javascripts/profile/preferences/constants.js
new file mode 100644
index 00000000000..ea8464ba065
--- /dev/null
+++ b/app/assets/javascripts/profile/preferences/constants.js
@@ -0,0 +1,22 @@
+import { s__, __ } from '~/locale';
+
+export const INTEGRATION_VIEW_CONFIGS = {
+ sourcegraph: {
+ title: s__('Preferences|Sourcegraph'),
+ label: s__('Preferences|Enable integrated code intelligence on code views'),
+ formName: 'sourcegraph_enabled',
+ },
+ gitpod: {
+ title: s__('Preferences|Gitpod'),
+ label: s__('Preferences|Enable Gitpod integration'),
+ formName: 'gitpod_enabled',
+ },
+};
+
+export const i18n = {
+ saveChanges: __('Save changes'),
+ defaultSuccess: __('Preferences saved.'),
+ defaultError: s__('Preferences|Failed to save preferences.'),
+ integrations: s__('Preferences|Integrations'),
+ integrationsDescription: s__('Preferences|Customize integrations with third party services.'),
+};
diff --git a/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js b/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
index 744e0174a4e..6520e68d41c 100644
--- a/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
+++ b/app/assets/javascripts/profile/preferences/profile_preferences_bundle.js
@@ -3,16 +3,20 @@ import ProfilePreferences from './components/profile_preferences.vue';
export default () => {
const el = document.querySelector('#js-profile-preferences-app');
- const shouldParse = ['integrationViews', 'userFields'];
+ const formEl = document.querySelector('#profile-preferences-form');
+ const shouldParse = ['integrationViews', 'themes', 'userFields'];
- const provide = Object.keys(el.dataset).reduce((memo, key) => {
- let value = el.dataset[key];
- if (shouldParse.includes(key)) {
- value = JSON.parse(value);
- }
+ const provide = Object.keys(el.dataset).reduce(
+ (memo, key) => {
+ let value = el.dataset[key];
+ if (shouldParse.includes(key)) {
+ value = JSON.parse(value);
+ }
- return { ...memo, [key]: value };
- }, {});
+ return { ...memo, [key]: value };
+ },
+ { formEl },
+ );
return new Vue({
el,
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index bfeeff47163..a7332b81b9f 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
-import { Rails } from '~/lib/utils/rails_ujs';
-import { deprecatedCreateFlash as flash } from '../flash';
import { parseBoolean } from '~/lib/utils/common_utils';
+import { Rails } from '~/lib/utils/rails_ujs';
import TimezoneDropdown, {
formatTimezone,
} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
+import { deprecatedCreateFlash as flash } from '../flash';
export default class Profile {
constructor({ form } = {}) {
@@ -42,6 +42,7 @@ export default class Profile {
$('#user_notification_email').on('select2-selecting', (event) => {
setTimeout(this.submitForm.bind(event.currentTarget));
});
+ $('#user_email_opted_in').on('change', this.submitForm);
$('#user_notified_of_own_activity').on('change', this.submitForm);
this.form.on('submit', this.onSubmitForm);
}
diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js
index ddb8956b664..f44661cb139 100644
--- a/app/assets/javascripts/project_find_file.js
+++ b/app/assets/javascripts/project_find_file.js
@@ -1,12 +1,12 @@
/* eslint-disable func-names, consistent-return, no-return-assign */
-import $ from 'jquery';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import $ from 'jquery';
+import { deprecatedCreateFlash as flash } from '~/flash';
import { sanitize } from '~/lib/dompurify';
import axios from '~/lib/utils/axios_utils';
-import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { spriteIcon } from '~/lib/utils/common_utils';
-import { deprecatedCreateFlash as flash } from '~/flash';
+import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
// highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
diff --git a/app/assets/javascripts/project_label_subscription.js b/app/assets/javascripts/project_label_subscription.js
index 4fefc2ed569..e6dd4145cb8 100644
--- a/app/assets/javascripts/project_label_subscription.js
+++ b/app/assets/javascripts/project_label_subscription.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
-import { __ } from './locale';
-import axios from './lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from './flash';
import { fixTitle } from '~/tooltips';
+import { deprecatedCreateFlash as flash } from './flash';
+import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
const tooltipTitles = {
group: {
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index e68430d7dfd..e1e04d63576 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -2,9 +2,9 @@
import $ from 'jquery';
import Api from './api';
-import ProjectSelectComboButton from './project_select_combo_button';
-import { s__ } from './locale';
import { loadCSSFile } from './lib/utils/css_utils';
+import { s__ } from './locale';
+import ProjectSelectComboButton from './project_select_combo_button';
const projectSelect = () => {
loadCSSFile(gon.select2_css_path)
diff --git a/app/assets/javascripts/projects/commit/components/branches_dropdown.vue b/app/assets/javascripts/projects/commit/components/branches_dropdown.vue
index 3ecc3f1d1d3..3527bcb04c6 100644
--- a/app/assets/javascripts/projects/commit/components/branches_dropdown.vue
+++ b/app/assets/javascripts/projects/commit/components/branches_dropdown.vue
@@ -68,6 +68,7 @@ export default {
autocomplete="off"
:debounce="250"
:placeholder="$options.i18n.searchPlaceholder"
+ data-testid="dropdown-search-box"
@input="searchTermChanged"
/>
<gl-dropdown-item
@@ -77,6 +78,7 @@ export default {
:name="branch"
:is-checked="isSelected(branch)"
is-check-item
+ data-testid="dropdown-item"
@click="selectBranch(branch)"
>
{{ branch }}
diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue
index 6411b1ca921..ed216a91ca0 100644
--- a/app/assets/javascripts/projects/commit/components/form_modal.vue
+++ b/app/assets/javascripts/projects/commit/components/form_modal.vue
@@ -1,8 +1,9 @@
<script>
import { GlModal, GlForm, GlFormCheckbox, GlSprintf, GlFormGroup } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
-import eventHub from '../event_hub';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import csrf from '~/lib/utils/csrf';
+import eventHub from '../event_hub';
import BranchesDropdown from './branches_dropdown.vue';
export default {
@@ -67,7 +68,7 @@ export default {
methods: {
...mapActions(['clearModal', 'setBranch', 'setSelectedBranch']),
show() {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
handlePrimary() {
this.$refs.form.$el.submit();
diff --git a/app/assets/javascripts/projects/commit/components/form_trigger.vue b/app/assets/javascripts/projects/commit/components/form_trigger.vue
index e92854c1ac3..3561b5c2473 100644
--- a/app/assets/javascripts/projects/commit/components/form_trigger.vue
+++ b/app/assets/javascripts/projects/commit/components/form_trigger.vue
@@ -10,6 +10,9 @@ export default {
displayText: {
default: '',
},
+ testId: {
+ default: '',
+ },
},
props: {
openModal: {
@@ -26,7 +29,7 @@ export default {
</script>
<template>
- <gl-link data-is-link="true" data-testid="revert-commit-link" @click="showModal">
+ <gl-link data-is-link="true" :data-testid="testId" @click="showModal">
{{ displayText }}
</gl-link>
</template>
diff --git a/app/assets/javascripts/projects/commit/constants.js b/app/assets/javascripts/projects/commit/constants.js
index 233f43d56b9..b47c744e5fb 100644
--- a/app/assets/javascripts/projects/commit/constants.js
+++ b/app/assets/javascripts/projects/commit/constants.js
@@ -2,6 +2,10 @@ import { s__, __ } from '~/locale';
export const OPEN_REVERT_MODAL = 'openRevertModal';
export const REVERT_MODAL_ID = 'revert-commit-modal';
+export const REVERT_LINK_TEST_ID = 'revert-commit-link';
+export const OPEN_CHERRY_PICK_MODAL = 'openCherryPickModal';
+export const CHERRY_PICK_MODAL_ID = 'cherry-pick-commit-modal';
+export const CHERRY_PICK_LINK_TEST_ID = 'cherry-pick-commit-link';
export const I18N_MODAL = {
startMergeRequest: s__('ChangeTypeAction|Start a %{newMergeRequest} with these changes'),
@@ -20,6 +24,11 @@ export const I18N_REVERT_MODAL = {
actionPrimaryText: s__('ChangeTypeAction|Revert'),
};
+export const I18N_CHERRY_PICK_MODAL = {
+ branchLabel: s__('ChangeTypeAction|Pick into branch'),
+ actionPrimaryText: s__('ChangeTypeAction|Cherry-pick'),
+};
+
export const PREPENDED_MODAL_TEXT = s__(
'ChangeTypeAction|This will create a new commit in order to revert the existing changes.',
);
diff --git a/app/assets/javascripts/projects/commit/index.js b/app/assets/javascripts/projects/commit/index.js
new file mode 100644
index 00000000000..b5fdfc25236
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/index.js
@@ -0,0 +1,11 @@
+import initCherryPickCommitModal from './init_cherry_pick_commit_modal';
+import initCherryPickCommitTrigger from './init_cherry_pick_commit_trigger';
+import initRevertCommitModal from './init_revert_commit_modal';
+import initRevertCommitTrigger from './init_revert_commit_trigger';
+
+export default () => {
+ initRevertCommitModal();
+ initRevertCommitTrigger();
+ initCherryPickCommitModal();
+ initCherryPickCommitTrigger();
+};
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
new file mode 100644
index 00000000000..24baa27ff70
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
@@ -0,0 +1,51 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import CommitFormModal from './components/form_modal.vue';
+import {
+ I18N_MODAL,
+ I18N_CHERRY_PICK_MODAL,
+ OPEN_CHERRY_PICK_MODAL,
+ CHERRY_PICK_MODAL_ID,
+} from './constants';
+import createStore from './store';
+
+export default function initInviteMembersModal() {
+ const el = document.querySelector('.js-cherry-pick-commit-modal');
+ if (!el) {
+ return false;
+ }
+
+ const {
+ title,
+ endpoint,
+ branch,
+ pushCode,
+ branchCollaboration,
+ existingBranch,
+ branchesEndpoint,
+ } = el.dataset;
+
+ const store = createStore({
+ endpoint,
+ branchesEndpoint,
+ branch,
+ pushCode: parseBoolean(pushCode),
+ branchCollaboration: parseBoolean(branchCollaboration),
+ defaultBranch: branch,
+ modalTitle: title,
+ existingBranch,
+ });
+
+ return new Vue({
+ el,
+ store,
+ render: (createElement) =>
+ createElement(CommitFormModal, {
+ props: {
+ i18n: { ...I18N_CHERRY_PICK_MODAL, ...I18N_MODAL },
+ openModal: OPEN_CHERRY_PICK_MODAL,
+ modalId: CHERRY_PICK_MODAL_ID,
+ },
+ }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js
new file mode 100644
index 00000000000..942451dc96a
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js
@@ -0,0 +1,20 @@
+import Vue from 'vue';
+import CommitFormTrigger from './components/form_trigger.vue';
+import { OPEN_CHERRY_PICK_MODAL, CHERRY_PICK_LINK_TEST_ID } from './constants';
+
+export default function initInviteMembersTrigger() {
+ const el = document.querySelector('.js-cherry-pick-commit-trigger');
+
+ if (!el) {
+ return false;
+ }
+
+ const { displayText } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: { displayText, testId: CHERRY_PICK_LINK_TEST_ID },
+ render: (createElement) =>
+ createElement(CommitFormTrigger, { props: { openModal: OPEN_CHERRY_PICK_MODAL } }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_modal.js b/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
index ec0600cd25a..df26aa3c830 100644
--- a/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
+++ b/app/assets/javascripts/projects/commit/init_revert_commit_modal.js
@@ -1,7 +1,6 @@
import Vue from 'vue';
-import CommitFormModal from './components/form_modal.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
-import createStore from './store';
+import CommitFormModal from './components/form_modal.vue';
import {
I18N_MODAL,
I18N_REVERT_MODAL,
@@ -9,6 +8,7 @@ import {
OPEN_REVERT_MODAL,
REVERT_MODAL_ID,
} from './constants';
+import createStore from './store';
export default function initInviteMembersModal() {
const el = document.querySelector('.js-revert-commit-modal');
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js b/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
index 0bb57f22663..dc5168524ca 100644
--- a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
+++ b/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import RevertCommitTrigger from './components/form_trigger.vue';
-import { OPEN_REVERT_MODAL } from './constants';
+import CommitFormTrigger from './components/form_trigger.vue';
+import { OPEN_REVERT_MODAL, REVERT_LINK_TEST_ID } from './constants';
export default function initInviteMembersTrigger() {
const el = document.querySelector('.js-revert-commit-trigger');
@@ -13,8 +13,8 @@ export default function initInviteMembersTrigger() {
return new Vue({
el,
- provide: { displayText },
+ provide: { displayText, testId: REVERT_LINK_TEST_ID },
render: (createElement) =>
- createElement(RevertCommitTrigger, { props: { openModal: OPEN_REVERT_MODAL } }),
+ createElement(CommitFormTrigger, { props: { openModal: OPEN_REVERT_MODAL } }),
});
}
diff --git a/app/assets/javascripts/projects/commit/store/actions.js b/app/assets/javascripts/projects/commit/store/actions.js
index 2ae0370d579..10135e55351 100644
--- a/app/assets/javascripts/projects/commit/store/actions.js
+++ b/app/assets/javascripts/projects/commit/store/actions.js
@@ -1,7 +1,7 @@
-import * as types from './mutation_types';
-import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { PROJECT_BRANCHES_ERROR } from '../constants';
+import * as types from './mutation_types';
export const clearModal = ({ commit }) => {
commit(types.CLEAR_MODAL);
diff --git a/app/assets/javascripts/projects/commit_box/info/index.js b/app/assets/javascripts/projects/commit_box/info/index.js
index 254d178f013..4bbdb5c2357 100644
--- a/app/assets/javascripts/projects/commit_box/info/index.js
+++ b/app/assets/javascripts/projects/commit_box/info/index.js
@@ -1,7 +1,7 @@
-import { loadBranches } from './load_branches';
-import { initDetailsButton } from './init_details_button';
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
+import { initDetailsButton } from './init_details_button';
+import { loadBranches } from './load_branches';
export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') => {
const containerEl = document.querySelector(containerSelector);
diff --git a/app/assets/javascripts/projects/commits/components/author_select.vue b/app/assets/javascripts/projects/commits/components/author_select.vue
index 752bb594794..1566232751d 100644
--- a/app/assets/javascripts/projects/commits/components/author_select.vue
+++ b/app/assets/javascripts/projects/commits/components/author_select.vue
@@ -1,6 +1,4 @@
<script>
-import { debounce } from 'lodash';
-import { mapState, mapActions } from 'vuex';
import {
GlDropdown,
GlDropdownSectionHeader,
@@ -9,8 +7,10 @@ import {
GlDropdownDivider,
GlTooltipDirective,
} from '@gitlab/ui';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { debounce } from 'lodash';
+import { mapState, mapActions } from 'vuex';
import { urlParamsToObject } from '~/lib/utils/common_utils';
+import { redirectTo } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
const tooltipMessage = __('Searching by both author and message is currently not supported.');
diff --git a/app/assets/javascripts/projects/commits/store/actions.js b/app/assets/javascripts/projects/commits/store/actions.js
index 359d81f32f7..72d4f0c31e5 100644
--- a/app/assets/javascripts/projects/commits/store/actions.js
+++ b/app/assets/javascripts/projects/commits/store/actions.js
@@ -1,9 +1,9 @@
-import * as Sentry from '~/sentry/wrapper';
-import * as types from './mutation_types';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { __ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
+import * as Sentry from '~/sentry/wrapper';
+import * as types from './mutation_types';
export default {
setInitialData({ commit }, data) {
diff --git a/app/assets/javascripts/projects/compare/components/app.vue b/app/assets/javascripts/projects/compare/components/app.vue
new file mode 100644
index 00000000000..05bd0f1370b
--- /dev/null
+++ b/app/assets/javascripts/projects/compare/components/app.vue
@@ -0,0 +1,89 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import RevisionDropdown from './revision_dropdown.vue';
+
+export default {
+ csrf,
+ components: {
+ RevisionDropdown,
+ GlButton,
+ },
+ props: {
+ projectCompareIndexPath: {
+ type: String,
+ required: true,
+ },
+ refsProjectPath: {
+ type: String,
+ required: true,
+ },
+ paramsFrom: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ paramsTo: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ projectMergeRequestPath: {
+ type: String,
+ required: true,
+ },
+ createMrPath: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ onSubmit() {
+ this.$refs.form.submit();
+ },
+ },
+};
+</script>
+
+<template>
+ <form
+ ref="form"
+ class="form-inline js-requires-input js-signature-container"
+ method="POST"
+ :action="projectCompareIndexPath"
+ >
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+ <revision-dropdown
+ :refs-project-path="refsProjectPath"
+ revision-text="Source"
+ params-name="to"
+ :params-branch="paramsTo"
+ />
+ <div class="compare-ellipsis gl-display-inline" data-testid="ellipsis">...</div>
+ <revision-dropdown
+ :refs-project-path="refsProjectPath"
+ revision-text="Target"
+ params-name="from"
+ :params-branch="paramsFrom"
+ />
+ <gl-button category="primary" variant="success" class="gl-ml-3" @click="onSubmit">
+ {{ s__('CompareRevisions|Compare') }}
+ </gl-button>
+ <a
+ v-if="projectMergeRequestPath"
+ :href="projectMergeRequestPath"
+ data-testid="projectMrButton"
+ class="btn btn-default gl-button gl-ml-3"
+ >
+ {{ s__('CompareRevisions|View open merge request') }}
+ </a>
+ <a
+ v-else-if="createMrPath"
+ :href="createMrPath"
+ data-testid="createMrButton"
+ class="btn btn-default gl-button gl-ml-3"
+ >
+ {{ s__('CompareRevisions|Create merge request') }}
+ </a>
+ </form>
+</template>
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
new file mode 100644
index 00000000000..13d80b5ae0b
--- /dev/null
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
@@ -0,0 +1,145 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { s__ } from '~/locale';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+ },
+ props: {
+ refsProjectPath: {
+ type: String,
+ required: true,
+ },
+ revisionText: {
+ type: String,
+ required: true,
+ },
+ paramsName: {
+ type: String,
+ required: true,
+ },
+ paramsBranch: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ branches: [],
+ tags: [],
+ loading: true,
+ searchTerm: '',
+ selectedRevision: this.getDefaultBranch(),
+ };
+ },
+ computed: {
+ filteredBranches() {
+ return this.branches.filter((branch) =>
+ branch.toLowerCase().includes(this.searchTerm.toLowerCase()),
+ );
+ },
+ hasFilteredBranches() {
+ return this.filteredBranches.length;
+ },
+ filteredTags() {
+ return this.tags.filter((tag) => tag.toLowerCase().includes(this.searchTerm.toLowerCase()));
+ },
+ hasFilteredTags() {
+ return this.filteredTags.length;
+ },
+ },
+ mounted() {
+ this.fetchBranchesAndTags();
+ },
+ methods: {
+ fetchBranchesAndTags() {
+ const endpoint = this.refsProjectPath;
+
+ return axios
+ .get(endpoint)
+ .then(({ data }) => {
+ this.branches = data.Branches || [];
+ this.tags = data.Tags || [];
+ })
+ .catch(() => {
+ createFlash({
+ message: `${s__(
+ 'CompareRevisions|There was an error while updating the branch/tag list. Please try again.',
+ )}`,
+ });
+ })
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ getDefaultBranch() {
+ return this.paramsBranch || s__('CompareRevisions|Select branch/tag');
+ },
+ onClick(revision) {
+ this.selectedRevision = revision;
+ },
+ onSearchEnter() {
+ this.selectedRevision = this.searchTerm;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="form-group compare-form-group" :class="`js-compare-${paramsName}-dropdown`">
+ <div class="input-group inline-input-group">
+ <span class="input-group-prepend">
+ <div class="input-group-text">
+ {{ revisionText }}
+ </div>
+ </span>
+ <input type="hidden" :name="paramsName" :value="selectedRevision" />
+ <gl-dropdown
+ class="gl-flex-grow-1 gl-flex-basis-0 gl-min-w-0 gl-font-monospace"
+ toggle-class="form-control compare-dropdown-toggle js-compare-dropdown gl-min-w-0 gl-rounded-top-left-none! gl-rounded-bottom-left-none!"
+ :text="selectedRevision"
+ header-text="Select Git revision"
+ :loading="loading"
+ >
+ <template #header>
+ <gl-search-box-by-type
+ v-model.trim="searchTerm"
+ :placeholder="s__('CompareRevisions|Filter by Git revision')"
+ @keyup.enter="onSearchEnter"
+ />
+ </template>
+ <gl-dropdown-section-header v-if="hasFilteredBranches">
+ {{ s__('CompareRevisions|Branches') }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="(branch, index) in filteredBranches"
+ :key="`branch${index}`"
+ is-check-item
+ :is-checked="selectedRevision === branch"
+ @click="onClick(branch)"
+ >
+ {{ branch }}
+ </gl-dropdown-item>
+ <gl-dropdown-section-header v-if="hasFilteredTags">
+ {{ s__('CompareRevisions|Tags') }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="(tag, index) in filteredTags"
+ :key="`tag${index}`"
+ is-check-item
+ :is-checked="selectedRevision === tag"
+ @click="onClick(tag)"
+ >
+ {{ tag }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/compare/index.js b/app/assets/javascripts/projects/compare/index.js
new file mode 100644
index 00000000000..4337eecb667
--- /dev/null
+++ b/app/assets/javascripts/projects/compare/index.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import CompareApp from './components/app.vue';
+
+export default function init() {
+ const el = document.getElementById('js-compare-selector');
+ const {
+ refsProjectPath,
+ paramsFrom,
+ paramsTo,
+ projectCompareIndexPath,
+ projectMergeRequestPath,
+ createMrPath,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ components: {
+ CompareApp,
+ },
+ render(createElement) {
+ return createElement(CompareApp, {
+ props: {
+ refsProjectPath,
+ paramsFrom,
+ paramsTo,
+ projectCompareIndexPath,
+ projectMergeRequestPath,
+ createMrPath,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue
index 5429d51dae0..81d23a563e2 100644
--- a/app/assets/javascripts/projects/components/project_delete_button.vue
+++ b/app/assets/javascripts/projects/components/project_delete_button.vue
@@ -22,10 +22,10 @@ export default {
strings: {
alertTitle: __('You are about to permanently delete this project'),
alertBody: __(
- 'Once 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.',
+ 'Once 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.',
),
modalBody: __(
- "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc.",
+ "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc.",
),
},
};
diff --git a/app/assets/javascripts/projects/components/shared/delete_button.vue b/app/assets/javascripts/projects/components/shared/delete_button.vue
index 051bfcb732a..2e46f437ace 100644
--- a/app/assets/javascripts/projects/components/shared/delete_button.vue
+++ b/app/assets/javascripts/projects/components/shared/delete_button.vue
@@ -1,8 +1,8 @@
<script>
-import { uniqueId } from 'lodash';
import { GlModal, GlModalDirective, GlFormInput, GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { uniqueId } from 'lodash';
import csrf from '~/lib/utils/csrf';
+import { __ } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
index b54f7051806..ef61fba88fe 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
@@ -1,14 +1,14 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlBreadcrumb, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import WelcomePage from './welcome.vue';
-import LegacyContainer from './legacy_container.vue';
import { __, s__ } from '~/locale';
import blankProjectIllustration from '../illustrations/blank-project.svg';
+import ciCdProjectIllustration from '../illustrations/ci-cd-project.svg';
import createFromTemplateIllustration from '../illustrations/create-from-template.svg';
import importProjectIllustration from '../illustrations/import-project.svg';
-import ciCdProjectIllustration from '../illustrations/ci-cd-project.svg';
+import LegacyContainer from './legacy_container.vue';
+import WelcomePage from './welcome.vue';
const BLANK_PANEL = 'blank_project';
const CI_CD_PANEL = 'cicd_for_external_repo';
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/index.js b/app/assets/javascripts/projects/experiment_new_project_creation/index.js
index 06920a5ab19..0414f7ef6a5 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/index.js
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/index.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import NewProjectCreationApp from './components/app.vue';
-export default function (el, props) {
+export default function initNewProjectCreation(el, props) {
return new Vue({
el,
components: {
diff --git a/app/assets/javascripts/projects/members/constants.js b/app/assets/javascripts/projects/members/constants.js
new file mode 100644
index 00000000000..a69a64fe882
--- /dev/null
+++ b/app/assets/javascripts/projects/members/constants.js
@@ -0,0 +1 @@
+export const PROJECT_MEMBER_BASE_PROPERTY_NAME = 'project_member';
diff --git a/app/assets/javascripts/projects/members/utils.js b/app/assets/javascripts/projects/members/utils.js
new file mode 100644
index 00000000000..a8a635e3ce8
--- /dev/null
+++ b/app/assets/javascripts/projects/members/utils.js
@@ -0,0 +1,8 @@
+import { MEMBER_ACCESS_LEVEL_PROPERTY_NAME } from '~/members/constants';
+import { baseRequestFormatter } from '~/members/utils';
+import { PROJECT_MEMBER_BASE_PROPERTY_NAME } from './constants';
+
+export const projectMemberRequestFormatter = baseRequestFormatter(
+ PROJECT_MEMBER_BASE_PROPERTY_NAME,
+ MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
+);
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 7bb62cf4a73..4a8e1424fa8 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -1,44 +1,12 @@
<script>
-import { GlAlert, GlTabs, GlTab } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import getPipelineCountByStatus from '../graphql/queries/get_pipeline_count_by_status.query.graphql';
-import getProjectPipelineStatistics from '../graphql/queries/get_project_pipeline_statistics.query.graphql';
+import { GlTabs, GlTab } from '@gitlab/ui';
+import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import PipelineCharts from './pipeline_charts.vue';
-import {
- DEFAULT,
- LOAD_ANALYTICS_FAILURE,
- LOAD_PIPELINES_FAILURE,
- PARSE_FAILURE,
- UNSUPPORTED_DATA,
-} from '../constants';
-
-const defaultAnalyticsValues = {
- weekPipelinesTotals: [],
- weekPipelinesLabels: [],
- weekPipelinesSuccessful: [],
- monthPipelinesLabels: [],
- monthPipelinesTotals: [],
- monthPipelinesSuccessful: [],
- yearPipelinesLabels: [],
- yearPipelinesTotals: [],
- yearPipelinesSuccessful: [],
- pipelineTimesLabels: [],
- pipelineTimesValues: [],
-};
-
-const defaultCountValues = {
- totalPipelines: {
- count: 0,
- },
- successfulPipelines: {
- count: 0,
- },
-};
+const charts = ['pipelines', 'deployments'];
export default {
components: {
- GlAlert,
GlTabs,
GlTab,
PipelineCharts,
@@ -50,171 +18,42 @@ export default {
type: Boolean,
default: false,
},
- projectPath: {
- type: String,
- default: '',
- },
},
data() {
return {
- showFailureAlert: false,
- failureType: null,
- analytics: { ...defaultAnalyticsValues },
- counts: { ...defaultCountValues },
+ selectedTab: 0,
};
},
- apollo: {
- counts: {
- query: getPipelineCountByStatus,
- variables() {
- return {
- projectPath: this.projectPath,
- };
- },
- update(data) {
- return data?.project;
- },
- error() {
- this.reportFailure(LOAD_PIPELINES_FAILURE);
- },
- },
- analytics: {
- query: getProjectPipelineStatistics,
- variables() {
- return {
- projectPath: this.projectPath,
- };
- },
- update(data) {
- return data?.project?.pipelineAnalytics;
- },
- error() {
- this.reportFailure(LOAD_ANALYTICS_FAILURE);
- },
- },
- },
- computed: {
- failure() {
- switch (this.failureType) {
- case LOAD_ANALYTICS_FAILURE:
- return {
- text: this.$options.errorTexts[LOAD_ANALYTICS_FAILURE],
- variant: 'danger',
- };
- case PARSE_FAILURE:
- return {
- text: this.$options.errorTexts[PARSE_FAILURE],
- variant: 'danger',
- };
- case UNSUPPORTED_DATA:
- return {
- text: this.$options.errorTexts[UNSUPPORTED_DATA],
- variant: 'info',
- };
- default:
- return {
- text: this.$options.errorTexts[DEFAULT],
- variant: 'danger',
- };
- }
- },
- lastWeekChartData() {
- return {
- labels: this.analytics.weekPipelinesLabels,
- totals: this.analytics.weekPipelinesTotals,
- success: this.analytics.weekPipelinesSuccessful,
- };
- },
- lastMonthChartData() {
- return {
- labels: this.analytics.monthPipelinesLabels,
- totals: this.analytics.monthPipelinesTotals,
- success: this.analytics.monthPipelinesSuccessful,
- };
- },
- lastYearChartData() {
- return {
- labels: this.analytics.yearPipelinesLabels,
- totals: this.analytics.yearPipelinesTotals,
- success: this.analytics.yearPipelinesSuccessful,
- };
- },
- timesChartData() {
- return {
- labels: this.analytics.pipelineTimesLabels,
- values: this.analytics.pipelineTimesValues,
- };
- },
- successRatio() {
- const { successfulPipelines, failedPipelines } = this.counts;
- const successfulCount = successfulPipelines?.count;
- const failedCount = failedPipelines?.count;
- const ratio = (successfulCount / (successfulCount + failedCount)) * 100;
-
- return failedCount === 0 ? 100 : ratio;
- },
- formattedCounts() {
- const { totalPipelines, successfulPipelines, failedPipelines } = this.counts;
-
- return {
- total: totalPipelines?.count,
- success: successfulPipelines?.count,
- failed: failedPipelines?.count,
- successRatio: this.successRatio,
- };
- },
+ created() {
+ this.selectTab();
+ window.addEventListener('popstate', this.selectTab);
},
methods: {
- hideAlert() {
- this.showFailureAlert = false;
- },
- reportFailure(type) {
- this.showFailureAlert = true;
- this.failureType = type;
+ selectTab() {
+ const [chart] = getParameterValues('chart') || charts;
+ const tab = charts.indexOf(chart);
+ this.selectedTab = tab >= 0 ? tab : 0;
+ },
+ onTabChange(index) {
+ if (index !== this.selectedTab) {
+ this.selectedTab = index;
+ const path = mergeUrlParams({ chart: charts[index] }, window.location.pathname);
+ updateHistory({ url: path, title: window.title });
+ }
},
},
- errorTexts: {
- [LOAD_ANALYTICS_FAILURE]: s__(
- 'PipelineCharts|An error has ocurred when retrieving the analytics data',
- ),
- [LOAD_PIPELINES_FAILURE]: s__(
- 'PipelineCharts|An error has ocurred when retrieving the pipelines data',
- ),
- [PARSE_FAILURE]: s__('PipelineCharts|There was an error parsing the data for the charts.'),
- [DEFAULT]: s__('PipelineCharts|An unknown error occurred while processing CI/CD analytics.'),
- },
};
</script>
<template>
<div>
- <gl-alert v-if="showFailureAlert" :variant="failure.variant" @dismiss="hideAlert">{{
- failure.text
- }}</gl-alert>
- <gl-tabs v-if="shouldRenderDeploymentFrequencyCharts">
+ <gl-tabs v-if="shouldRenderDeploymentFrequencyCharts" :value="selectedTab" @input="onTabChange">
<gl-tab :title="__('Pipelines')">
- <pipeline-charts
- :counts="formattedCounts"
- :last-week="lastWeekChartData"
- :last-month="lastMonthChartData"
- :last-year="lastYearChartData"
- :times-chart="timesChartData"
- :loading="$apollo.queries.counts.loading"
- @report-failure="reportFailure"
- />
+ <pipeline-charts />
</gl-tab>
<gl-tab :title="__('Deployments')">
<deployment-frequency-charts />
</gl-tab>
</gl-tabs>
- <pipeline-charts
- v-else
- :counts="formattedCounts"
- :last-week="lastWeekChartData"
- :last-month="lastMonthChartData"
- :last-year="lastYearChartData"
- :times-chart="timesChartData"
- :loading="$apollo.queries.counts.loading"
- @report-failure="reportFailure"
- />
+ <pipeline-charts v-else />
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
new file mode 100644
index 00000000000..43b36da8b2c
--- /dev/null
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlSegmentedControl } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+import CiCdAnalyticsAreaChart from './ci_cd_analytics_area_chart.vue';
+
+export default {
+ components: {
+ GlSegmentedControl,
+ CiCdAnalyticsAreaChart,
+ },
+ props: {
+ charts: {
+ required: true,
+ type: Array,
+ },
+ chartOptions: {
+ required: true,
+ type: Object,
+ },
+ },
+ data() {
+ return {
+ selectedChart: 0,
+ };
+ },
+ computed: {
+ chartRanges() {
+ return this.charts.map(({ title }, index) => ({ text: title, value: index }));
+ },
+ chart() {
+ return this.charts[this.selectedChart];
+ },
+ dateRange() {
+ return sprintf(s__('CiCdAnalytics|Date range: %{range}'), { range: this.chart.range });
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-segmented-control v-model="selectedChart" :options="chartRanges" class="gl-mb-4" />
+ <ci-cd-analytics-area-chart
+ v-if="chart"
+ :chart-data="chart.data"
+ :area-chart-options="chartOptions"
+ >
+ {{ dateRange }}
+ </ci-cd-analytics-area-chart>
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue b/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue
index bec4ab407f0..733f833d51a 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/pipeline_charts.vue
@@ -1,63 +1,184 @@
<script>
-import dateFormat from 'dateformat';
+import { GlAlert, GlSkeletonLoader } from '@gitlab/ui';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import { GlSkeletonLoader } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
+import dateFormat from 'dateformat';
import { getDateInPast } from '~/lib/utils/datetime_utility';
+import { __, s__, sprintf } from '~/locale';
import {
+ DEFAULT,
CHART_CONTAINER_HEIGHT,
CHART_DATE_FORMAT,
INNER_CHART_HEIGHT,
ONE_WEEK_AGO_DAYS,
ONE_MONTH_AGO_DAYS,
+ ONE_YEAR_AGO_DAYS,
X_AXIS_LABEL_ROTATION,
X_AXIS_TITLE_OFFSET,
PARSE_FAILURE,
+ LOAD_ANALYTICS_FAILURE,
+ LOAD_PIPELINES_FAILURE,
+ UNSUPPORTED_DATA,
} from '../constants';
+import getPipelineCountByStatus from '../graphql/queries/get_pipeline_count_by_status.query.graphql';
+import getProjectPipelineStatistics from '../graphql/queries/get_project_pipeline_statistics.query.graphql';
+import CiCdAnalyticsCharts from './ci_cd_analytics_charts.vue';
import StatisticsList from './statistics_list.vue';
-import CiCdAnalyticsAreaChart from './ci_cd_analytics_area_chart.vue';
+
+const defaultAnalyticsValues = {
+ weekPipelinesTotals: [],
+ weekPipelinesLabels: [],
+ weekPipelinesSuccessful: [],
+ monthPipelinesLabels: [],
+ monthPipelinesTotals: [],
+ monthPipelinesSuccessful: [],
+ yearPipelinesLabels: [],
+ yearPipelinesTotals: [],
+ yearPipelinesSuccessful: [],
+ pipelineTimesLabels: [],
+ pipelineTimesValues: [],
+};
+
+const defaultCountValues = {
+ totalPipelines: {
+ count: 0,
+ },
+ successfulPipelines: {
+ count: 0,
+ },
+};
export default {
components: {
+ GlAlert,
GlColumnChart,
GlSkeletonLoader,
StatisticsList,
- CiCdAnalyticsAreaChart,
+ CiCdAnalyticsCharts,
+ },
+ inject: {
+ projectPath: {
+ type: String,
+ default: '',
+ },
},
- props: {
+ data() {
+ return {
+ showFailureAlert: false,
+ failureType: null,
+ analytics: { ...defaultAnalyticsValues },
+ counts: { ...defaultCountValues },
+ };
+ },
+ apollo: {
counts: {
- required: true,
- type: Object,
+ query: getPipelineCountByStatus,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update(data) {
+ return data?.project;
+ },
+ error() {
+ this.reportFailure(LOAD_PIPELINES_FAILURE);
+ },
+ },
+ analytics: {
+ query: getProjectPipelineStatistics,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update(data) {
+ return data?.project?.pipelineAnalytics;
+ },
+ error() {
+ this.reportFailure(LOAD_ANALYTICS_FAILURE);
+ },
+ },
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.counts.loading;
},
- loading: {
- required: false,
- default: false,
- type: Boolean,
+ failure() {
+ switch (this.failureType) {
+ case LOAD_ANALYTICS_FAILURE:
+ return {
+ text: this.$options.errorTexts[LOAD_ANALYTICS_FAILURE],
+ variant: 'danger',
+ };
+ case PARSE_FAILURE:
+ return {
+ text: this.$options.errorTexts[PARSE_FAILURE],
+ variant: 'danger',
+ };
+ case UNSUPPORTED_DATA:
+ return {
+ text: this.$options.errorTexts[UNSUPPORTED_DATA],
+ variant: 'info',
+ };
+ default:
+ return {
+ text: this.$options.errorTexts[DEFAULT],
+ variant: 'danger',
+ };
+ }
},
- lastWeek: {
- required: true,
- type: Object,
+ lastWeekChartData() {
+ return {
+ labels: this.analytics.weekPipelinesLabels,
+ totals: this.analytics.weekPipelinesTotals,
+ success: this.analytics.weekPipelinesSuccessful,
+ };
},
- lastMonth: {
- required: true,
- type: Object,
+ lastMonthChartData() {
+ return {
+ labels: this.analytics.monthPipelinesLabels,
+ totals: this.analytics.monthPipelinesTotals,
+ success: this.analytics.monthPipelinesSuccessful,
+ };
},
- lastYear: {
- required: true,
- type: Object,
+ lastYearChartData() {
+ return {
+ labels: this.analytics.yearPipelinesLabels,
+ totals: this.analytics.yearPipelinesTotals,
+ success: this.analytics.yearPipelinesSuccessful,
+ };
},
- timesChart: {
- required: true,
- type: Object,
+ timesChartData() {
+ return {
+ labels: this.analytics.pipelineTimesLabels,
+ values: this.analytics.pipelineTimesValues,
+ };
+ },
+ successRatio() {
+ const { successfulPipelines, failedPipelines } = this.counts;
+ const successfulCount = successfulPipelines?.count;
+ const failedCount = failedPipelines?.count;
+ const ratio = (successfulCount / (successfulCount + failedCount)) * 100;
+
+ return failedCount === 0 ? 100 : ratio;
+ },
+ formattedCounts() {
+ const { totalPipelines, successfulPipelines, failedPipelines } = this.counts;
+
+ return {
+ total: totalPipelines?.count,
+ success: successfulPipelines?.count,
+ failed: failedPipelines?.count,
+ successRatio: this.successRatio,
+ };
},
- },
- computed: {
areaCharts() {
const { lastWeek, lastMonth, lastYear } = this.$options.chartTitles;
+ const { lastWeekRange, lastMonthRange, lastYearRange } = this.$options.chartRanges;
const charts = [
- { title: lastWeek, data: this.lastWeek },
- { title: lastMonth, data: this.lastMonth },
- { title: lastYear, data: this.lastYear },
+ { title: lastWeek, range: lastWeekRange, data: this.lastWeekChartData },
+ { title: lastMonth, range: lastMonthRange, data: this.lastMonthChartData },
+ { title: lastYear, range: lastYearRange, data: this.lastYearChartData },
];
let areaChartsData = [];
@@ -65,7 +186,7 @@ export default {
areaChartsData = charts.map(this.buildAreaChartData);
} catch {
areaChartsData = [];
- this.vm.$emit('report-failure', PARSE_FAILURE);
+ this.reportFailure(PARSE_FAILURE);
}
return areaChartsData;
@@ -74,20 +195,28 @@ export default {
return [
{
name: 'full',
- data: this.mergeLabelsAndValues(this.timesChart.labels, this.timesChart.values),
+ data: this.mergeLabelsAndValues(this.timesChartData.labels, this.timesChartData.values),
},
];
},
},
methods: {
+ hideAlert() {
+ this.showFailureAlert = false;
+ },
+ reportFailure(type) {
+ this.showFailureAlert = true;
+ this.failureType = type;
+ },
mergeLabelsAndValues(labels, values) {
return labels.map((label, index) => [label, values[index]]);
},
- buildAreaChartData({ title, data }) {
+ buildAreaChartData({ title, data, range }) {
const { labels, totals, success } = data;
return {
title,
+ range,
data: [
{
name: 'all',
@@ -118,28 +247,50 @@ export default {
},
yAxis: {
name: s__('Pipeline|Pipelines'),
+ minInterval: 1,
},
},
- get chartTitles() {
+ errorTexts: {
+ [LOAD_ANALYTICS_FAILURE]: s__(
+ 'PipelineCharts|An error has ocurred when retrieving the analytics data',
+ ),
+ [LOAD_PIPELINES_FAILURE]: s__(
+ 'PipelineCharts|An error has ocurred when retrieving the pipelines data',
+ ),
+ [PARSE_FAILURE]: s__('PipelineCharts|There was an error parsing the data for the charts.'),
+ [DEFAULT]: s__('PipelineCharts|An unknown error occurred while processing CI/CD analytics.'),
+ },
+ chartTitles: {
+ lastWeek: __('Last week'),
+ lastMonth: __('Last month'),
+ lastYear: __('Last year'),
+ },
+ get chartRanges() {
const today = dateFormat(new Date(), CHART_DATE_FORMAT);
const pastDate = (timeScale) =>
dateFormat(getDateInPast(new Date(), timeScale), CHART_DATE_FORMAT);
return {
- lastWeek: sprintf(__('Pipelines for last week (%{oneWeekAgo} - %{today})'), {
+ lastWeekRange: sprintf(__('%{oneWeekAgo} - %{today}'), {
oneWeekAgo: pastDate(ONE_WEEK_AGO_DAYS),
today,
}),
- lastMonth: sprintf(__('Pipelines for last month (%{oneMonthAgo} - %{today})'), {
+ lastMonthRange: sprintf(__('%{oneMonthAgo} - %{today}'), {
oneMonthAgo: pastDate(ONE_MONTH_AGO_DAYS),
today,
}),
- lastYear: __('Pipelines for last year'),
+ lastYearRange: sprintf(__('%{oneYearAgo} - %{today}'), {
+ oneYearAgo: pastDate(ONE_YEAR_AGO_DAYS),
+ today,
+ }),
};
},
};
</script>
<template>
<div>
+ <gl-alert v-if="showFailureAlert" :variant="failure.variant" @dismiss="hideAlert">{{
+ failure.text
+ }}</gl-alert>
<div class="gl-mb-3">
<h3>{{ s__('PipelineCharts|CI / CD Analytics') }}</h3>
</div>
@@ -147,7 +298,7 @@ export default {
<div class="row">
<div class="col-md-6">
<gl-skeleton-loader v-if="loading" :lines="5" />
- <statistics-list v-else :counts="counts" />
+ <statistics-list v-else :counts="formattedCounts" />
</div>
<div v-if="!loading" class="col-md-6">
<strong>{{ __('Duration for the last 30 commits') }}</strong>
@@ -164,13 +315,7 @@ export default {
<template v-if="!loading">
<hr />
<h4 class="gl-my-4">{{ __('Pipelines charts') }}</h4>
- <ci-cd-analytics-area-chart
- v-for="(chart, index) in areaCharts"
- :key="index"
- :chart-data="chart.data"
- :area-chart-options="$options.areaChartOptions"
- >{{ chart.title }}</ci-cd-analytics-area-chart
- >
+ <ci-cd-analytics-charts :charts="areaCharts" :chart-options="$options.areaChartOptions" />
</template>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/constants.js b/app/assets/javascripts/projects/pipelines/charts/constants.js
index 079e23943c1..41fe81f21ea 100644
--- a/app/assets/javascripts/projects/pipelines/charts/constants.js
+++ b/app/assets/javascripts/projects/pipelines/charts/constants.js
@@ -10,6 +10,8 @@ export const ONE_WEEK_AGO_DAYS = 7;
export const ONE_MONTH_AGO_DAYS = 31;
+export const ONE_YEAR_AGO_DAYS = 365;
+
export const CHART_DATE_FORMAT = 'dd mmm';
export const DEFAULT = 'default';
diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js
index a62b5d423de..a5e53ee3927 100644
--- a/app/assets/javascripts/projects/settings/access_dropdown.js
+++ b/app/assets/javascripts/projects/settings/access_dropdown.js
@@ -1,17 +1,16 @@
/* eslint-disable no-underscore-dangle, class-methods-use-this */
import { escape, find, countBy } from 'lodash';
-import axios from '~/lib/utils/axios_utils';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { n__, s__, __, sprintf } from '~/locale';
import { LEVEL_TYPES, LEVEL_ID_PROP, ACCESS_LEVELS, ACCESS_LEVEL_NONE } from './constants';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class AccessDropdown {
constructor(options) {
const { $dropdown, accessLevel, accessLevelsData, hasLicense = true } = options;
this.options = options;
this.hasLicense = hasLicense;
- this.deployKeysOnProtectedBranchesEnabled = gon.features.deployKeysOnProtectedBranches;
this.groups = [];
this.accessLevel = accessLevel;
this.accessLevelsData = accessLevelsData.roles;
@@ -330,11 +329,7 @@ export default class AccessDropdown {
);
})
.catch(() => {
- if (this.deployKeysOnProtectedBranchesEnabled) {
- createFlash({ message: __('Failed to load groups, users and deploy keys.') });
- } else {
- createFlash({ message: __('Failed to load groups & users.') });
- }
+ createFlash({ message: __('Failed to load groups, users and deploy keys.') });
});
} else {
this.getDeployKeys(query)
@@ -445,35 +440,33 @@ export default class AccessDropdown {
}
}
- if (this.deployKeysOnProtectedBranchesEnabled) {
- const deployKeys = deployKeysResponse.map((response) => {
- const {
- id,
- fingerprint,
- title,
- owner: { avatar_url, name, username },
- } = response;
-
- const shortFingerprint = `(${fingerprint.substring(0, 14)}...)`;
-
- return {
- id,
- title: title.concat(' ', shortFingerprint),
- avatar_url,
- fullname: name,
- username,
- type: LEVEL_TYPES.DEPLOY_KEY,
- };
- });
+ const deployKeys = deployKeysResponse.map((response) => {
+ const {
+ id,
+ fingerprint,
+ title,
+ owner: { avatar_url, name, username },
+ } = response;
+
+ const shortFingerprint = `(${fingerprint.substring(0, 14)}...)`;
+
+ return {
+ id,
+ title: title.concat(' ', shortFingerprint),
+ avatar_url,
+ fullname: name,
+ username,
+ type: LEVEL_TYPES.DEPLOY_KEY,
+ };
+ });
- if (this.accessLevel === ACCESS_LEVELS.PUSH) {
- if (deployKeys.length) {
- consolidatedData = consolidatedData.concat(
- [{ type: 'divider' }],
- [{ type: 'header', content: s__('AccessDropdown|Deploy Keys') }],
- deployKeys,
- );
- }
+ if (this.accessLevel === ACCESS_LEVELS.PUSH) {
+ if (deployKeys.length) {
+ consolidatedData = consolidatedData.concat(
+ [{ type: 'divider' }],
+ [{ type: 'header', content: s__('AccessDropdown|Deploy Keys') }],
+ deployKeys,
+ );
}
}
@@ -501,19 +494,15 @@ export default class AccessDropdown {
}
getDeployKeys(query) {
- if (this.deployKeysOnProtectedBranchesEnabled) {
- return axios.get(this.buildUrl(gon.relative_url_root, this.deployKeysPath), {
- params: {
- search: query,
- per_page: 20,
- active: true,
- project_id: gon.current_project_id,
- push_code: true,
- },
- });
- }
-
- return Promise.resolve({ data: [] });
+ return axios.get(this.buildUrl(gon.relative_url_root, this.deployKeysPath), {
+ params: {
+ search: query,
+ per_page: 20,
+ active: true,
+ project_id: gon.current_project_id,
+ push_code: true,
+ },
+ });
}
buildUrl(urlRoot, url) {
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 51281def7d0..0786a74f6b1 100644
--- a/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
+++ b/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
@@ -1,7 +1,7 @@
<script>
import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
-import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
const DEFAULT_ERROR_MESSAGE = __('An error occurred while updating the configuration.');
diff --git a/app/assets/javascripts/projects/settings/mount_shared_runners_toggle.js b/app/assets/javascripts/projects/settings/mount_shared_runners_toggle.js
index c5d45fe6fed..eaeb5848b68 100644
--- a/app/assets/javascripts/projects/settings/mount_shared_runners_toggle.js
+++ b/app/assets/javascripts/projects/settings/mount_shared_runners_toggle.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import SharedRunnersToggle from '~/projects/settings/components/shared_runners_toggle.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
+import SharedRunnersToggle from '~/projects/settings/components/shared_runners_toggle.vue';
export default (containerId = 'toggle-shared-runners-form') => {
const containerEl = document.getElementById(containerId);
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
index 909f1afd9f6..9b3c0dd2755 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue
@@ -1,61 +1,43 @@
<script>
import { GlAlert } from '@gitlab/ui';
+import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
import ServiceDeskSetting from './service_desk_setting.vue';
-import ServiceDeskService from '../services/service_desk_service';
-import eventHub from '../event_hub';
export default {
- name: 'ServiceDeskRoot',
components: {
GlAlert,
ServiceDeskSetting,
},
- props: {
+ inject: {
initialIsEnabled: {
- type: Boolean,
- required: true,
+ default: false,
},
endpoint: {
- type: String,
- required: true,
+ default: '',
},
- incomingEmail: {
- type: String,
- required: false,
+ initialIncomingEmail: {
default: '',
},
customEmail: {
- type: String,
- required: false,
default: '',
},
customEmailEnabled: {
- type: Boolean,
- required: false,
+ default: false,
},
selectedTemplate: {
- type: String,
- required: false,
default: '',
},
outgoingName: {
- type: String,
- required: false,
default: '',
},
projectKey: {
- type: String,
- required: false,
default: '',
},
templates: {
- type: Array,
- required: false,
- default: () => [],
+ default: [],
},
},
-
data() {
return {
isEnabled: this.initialIsEnabled,
@@ -63,28 +45,21 @@ export default {
isAlertShowing: false,
alertVariant: 'danger',
alertMessage: '',
+ incomingEmail: this.initialIncomingEmail,
updatedCustomEmail: this.customEmail,
};
},
-
- created() {
- eventHub.$on('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
- eventHub.$on('serviceDeskTemplateSave', this.onSaveTemplate);
- this.service = new ServiceDeskService(this.endpoint);
- },
-
- beforeDestroy() {
- eventHub.$off('serviceDeskEnabledCheckboxToggled', this.onEnableToggled);
- eventHub.$off('serviceDeskTemplateSave', this.onSaveTemplate);
- },
-
methods: {
onEnableToggled(isChecked) {
this.isEnabled = isChecked;
this.incomingEmail = '';
- this.service
- .toggleServiceDesk(isChecked)
+ const body = {
+ service_desk_enabled: isChecked,
+ };
+
+ return axios
+ .put(this.endpoint, body)
.then(({ data }) => {
const email = data.service_desk_address;
if (isChecked && !email) {
@@ -104,8 +79,16 @@ export default {
onSaveTemplate({ selectedTemplate, outgoingName, projectKey }) {
this.isTemplateSaving = true;
- this.service
- .updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
+
+ const body = {
+ issue_template_key: selectedTemplate,
+ outgoing_name: outgoingName,
+ project_key: projectKey,
+ service_desk_enabled: this.isEnabled,
+ };
+
+ return axios
+ .put(this.endpoint, body)
.then(({ data }) => {
this.updatedCustomEmail = data?.service_desk_address;
this.showAlert(__('Changes saved.'), 'success');
@@ -150,6 +133,8 @@ export default {
:initial-project-key="projectKey"
:templates="templates"
:is-template-saving="isTemplateSaving"
+ @save="onSaveTemplate"
+ @toggle="onEnableToggled"
/>
</div>
</template>
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
index a850374fc88..39d9a6a4239 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
@@ -1,12 +1,9 @@
<script>
import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import eventHub from '../event_hub';
export default {
- name: 'ServiceDeskSetting',
components: {
ClipboardButton,
GlButton,
@@ -15,7 +12,6 @@ export default {
GlLoadingIcon,
GlSprintf,
},
- mixins: [glFeatureFlagsMixin()],
props: {
isEnabled: {
type: Boolean,
@@ -84,10 +80,10 @@ export default {
},
methods: {
onCheckboxToggle(isChecked) {
- eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked);
+ this.$emit('toggle', isChecked);
},
onSaveTemplate() {
- eventHub.$emit('serviceDeskTemplateSave', {
+ this.$emit('save', {
selectedTemplate: this.selectedTemplate,
outgoingName: this.outgoingName,
projectKey: this.projectKey,
@@ -111,7 +107,11 @@ export default {
</label>
<div v-if="isEnabled" class="row mt-3">
<div class="col-md-9 mb-0">
- <strong id="incoming-email-describer" class="d-block mb-1">
+ <strong
+ id="incoming-email-describer"
+ class="gl-display-block gl-mb-1"
+ data-testid="incoming-email-describer"
+ >
{{ __('Email address to use for Support Desk') }}
</strong>
<template v-if="email">
@@ -128,11 +128,7 @@ export default {
disabled="true"
/>
<div class="input-group-append">
- <clipboard-button
- :title="__('Copy')"
- :text="email"
- css-class="input-group-text qa-clipboard-button"
- />
+ <clipboard-button :title="__('Copy')" :text="email" css-class="input-group-text" />
</div>
</div>
<span v-if="hasCustomEmail" class="form-text text-muted">
diff --git a/app/assets/javascripts/projects/settings_service_desk/event_hub.js b/app/assets/javascripts/projects/settings_service_desk/event_hub.js
deleted file mode 100644
index e31806ad199..00000000000
--- a/app/assets/javascripts/projects/settings_service_desk/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/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js
index 8f9828dd73d..f842ffaaa2b 100644
--- a/app/assets/javascripts/projects/settings_service_desk/index.js
+++ b/app/assets/javascripts/projects/settings_service_desk/index.js
@@ -3,43 +3,37 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import ServiceDeskRoot from './components/service_desk_root.vue';
export default () => {
- const serviceDeskRootElement = document.querySelector('.js-service-desk-setting-root');
- if (serviceDeskRootElement) {
- // eslint-disable-next-line no-new
- new Vue({
- el: serviceDeskRootElement,
- components: {
- ServiceDeskRoot,
- },
- data() {
- const { dataset } = serviceDeskRootElement;
- return {
- initialIsEnabled: parseBoolean(dataset.enabled),
- endpoint: dataset.endpoint,
- incomingEmail: dataset.incomingEmail,
- customEmail: dataset.customEmail,
- customEmailEnabled: parseBoolean(dataset.customEmailEnabled),
- selectedTemplate: dataset.selectedTemplate,
- outgoingName: dataset.outgoingName,
- projectKey: dataset.projectKey,
- templates: JSON.parse(dataset.templates),
- };
- },
- render(createElement) {
- return createElement('service-desk-root', {
- props: {
- initialIsEnabled: this.initialIsEnabled,
- endpoint: this.endpoint,
- incomingEmail: this.incomingEmail,
- customEmail: this.customEmail,
- customEmailEnabled: this.customEmailEnabled,
- selectedTemplate: this.selectedTemplate,
- outgoingName: this.outgoingName,
- projectKey: this.projectKey,
- templates: this.templates,
- },
- });
- },
- });
+ const el = document.querySelector('.js-service-desk-setting-root');
+
+ if (!el) {
+ return false;
}
+
+ const {
+ customEmail,
+ customEmailEnabled,
+ enabled,
+ endpoint,
+ incomingEmail,
+ outgoingName,
+ projectKey,
+ selectedTemplate,
+ templates,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ customEmail,
+ customEmailEnabled: parseBoolean(customEmailEnabled),
+ endpoint,
+ initialIncomingEmail: incomingEmail,
+ initialIsEnabled: parseBoolean(enabled),
+ outgoingName,
+ projectKey,
+ selectedTemplate,
+ templates: JSON.parse(templates),
+ },
+ render: (createElement) => createElement(ServiceDeskRoot),
+ });
};
diff --git a/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js b/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
deleted file mode 100644
index b68c5bb876f..00000000000
--- a/app/assets/javascripts/projects/settings_service_desk/services/service_desk_service.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import axios from '~/lib/utils/axios_utils';
-
-class ServiceDeskService {
- constructor(endpoint) {
- this.endpoint = endpoint;
- }
-
- toggleServiceDesk(enable) {
- return axios.put(this.endpoint, { service_desk_enabled: enable });
- }
-
- updateTemplate({ selectedTemplate, outgoingName, projectKey = '' }, isEnabled) {
- const body = {
- issue_template_key: selectedTemplate,
- outgoing_name: outgoingName,
- project_key: projectKey,
- service_desk_enabled: isEnabled,
- };
- return axios.put(this.endpoint, body);
- }
-}
-
-export default ServiceDeskService;
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index 0f01167988d..f3d12e0dd00 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -1,10 +1,10 @@
<script>
-import Visibility from 'visibilityjs';
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import ciIcon from '~/vue_shared/components/ci_icon.vue';
-import Poll from '~/lib/utils/poll';
+import Visibility from 'visibilityjs';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import Poll from '~/lib/utils/poll';
import { __, s__, sprintf } from '~/locale';
+import ciIcon from '~/vue_shared/components/ci_icon.vue';
import CommitPipelineService from '../services/commit_pipeline_service';
export default {
diff --git a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
index 91de6d93e19..1a07f5495a1 100644
--- a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
+++ b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
@@ -1,10 +1,10 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlButton, GlFormGroup, GlFormInput, GlModal, GlModalDirective } from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
copyToClipboard: __('Copy'),
diff --git a/app/assets/javascripts/prometheus_metrics/custom_metrics.js b/app/assets/javascripts/prometheus_metrics/custom_metrics.js
index e891b8bf3b6..e10b5bf1807 100644
--- a/app/assets/javascripts/prometheus_metrics/custom_metrics.js
+++ b/app/assets/javascripts/prometheus_metrics/custom_metrics.js
@@ -1,10 +1,10 @@
import $ from 'jquery';
import { escape, sortBy } from 'lodash';
-import PrometheusMetrics from './prometheus_metrics';
-import PANEL_STATE from './constants';
import axios from '~/lib/utils/axios_utils';
-import { s__ } from '~/locale';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { s__ } from '~/locale';
+import PANEL_STATE from './constants';
+import PrometheusMetrics from './prometheus_metrics';
export default class CustomMetrics extends PrometheusMetrics {
constructor(wrapperSelector) {
diff --git a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
index 57f9cec9682..821de0560cd 100644
--- a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
+++ b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
@@ -2,8 +2,8 @@ import $ from 'jquery';
import { escape } from 'lodash';
import { s__, n__, sprintf } from '~/locale';
import axios from '../lib/utils/axios_utils';
-import PANEL_STATE from './constants';
import { backOff } from '../lib/utils/common_utils';
+import PANEL_STATE from './constants';
export default class PrometheusMetrics {
constructor(wrapperSelector) {
diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js b/app/assets/javascripts/protected_branches/protected_branch_create.js
index a5c7b18f709..c9474f0516c 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_create.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_create.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
-import AccessDropdown from '~/projects/settings/access_dropdown';
-import axios from '~/lib/utils/axios_utils';
-import AccessorUtilities from '~/lib/utils/accessor';
-import { deprecatedCreateFlash as Flash } from '~/flash';
import CreateItemDropdown from '~/create_item_dropdown';
-import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
+import { deprecatedCreateFlash as Flash } from '~/flash';
+import AccessorUtilities from '~/lib/utils/accessor';
+import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
+import AccessDropdown from '~/projects/settings/access_dropdown';
+import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
export default class ProtectedBranchCreate {
constructor(options) {
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index f5f27b67c71..986abeecafa 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
@@ -1,9 +1,9 @@
import { find } from 'lodash';
-import AccessDropdown from '~/projects/settings/access_dropdown';
import axios from '~/lib/utils/axios_utils';
-import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
-import { deprecatedCreateFlash as flash } from '../flash';
import { __ } from '~/locale';
+import AccessDropdown from '~/projects/settings/access_dropdown';
+import { deprecatedCreateFlash as flash } from '../flash';
+import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
export default class ProtectedBranchEdit {
constructor(options) {
diff --git a/app/assets/javascripts/protected_tags/constants.js b/app/assets/javascripts/protected_tags/constants.js
new file mode 100644
index 00000000000..3e71ba62877
--- /dev/null
+++ b/app/assets/javascripts/protected_tags/constants.js
@@ -0,0 +1,3 @@
+import { s__ } from '~/locale';
+
+export const FAILED_TO_UPDATE_TAG_MESSAGE = s__('ProjectSettings|Failed to update tag!');
diff --git a/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js b/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
index 202286a5fb4..4094c300a50 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
@@ -1,5 +1,5 @@
-import { __ } from '~/locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from '~/locale';
export default class ProtectedTagAccessDropdown {
constructor(options) {
diff --git a/app/assets/javascripts/protected_tags/protected_tag_create.js b/app/assets/javascripts/protected_tags/protected_tag_create.js
index eb44f0c67fd..e3f427b8408 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_create.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_create.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
-import CreateItemDropdown from '../create_item_dropdown';
import { __ } from '~/locale';
+import CreateItemDropdown from '../create_item_dropdown';
+import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
export default class ProtectedTagCreate {
constructor() {
diff --git a/app/assets/javascripts/protected_tags/protected_tag_edit.js b/app/assets/javascripts/protected_tags/protected_tag_edit.js
index 157ac1c7ebd..ae7855d4638 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_edit.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_edit.js
@@ -1,7 +1,7 @@
import { deprecatedCreateFlash as flash } from '../flash';
import axios from '../lib/utils/axios_utils';
+import { FAILED_TO_UPDATE_TAG_MESSAGE } from './constants';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
-import { __ } from '~/locale';
export default class ProtectedTagEdit {
constructor(options) {
@@ -48,11 +48,8 @@ export default class ProtectedTagEdit {
.catch(() => {
this.$allowedToCreateDropdownButton.enable();
- flash(
- __('Failed to update tag!'),
- 'alert',
- document.querySelector('.js-protected-tags-list'),
- );
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ flash(FAILED_TO_UPDATE_TAG_MESSAGE);
});
}
}
diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue
index 20aec3e12be..8f2805b36f6 100644
--- a/app/assets/javascripts/ref/components/ref_selector.vue
+++ b/app/assets/javascripts/ref/components/ref_selector.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
import {
GlDropdown,
GlDropdownDivider,
@@ -10,8 +9,9 @@ import {
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import createStore from '../stores';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { SEARCH_DEBOUNCE_MS, DEFAULT_I18N } from '../constants';
+import createStore from '../stores';
import RefResultsSection from './ref_results_section.vue';
export default {
diff --git a/app/assets/javascripts/ref/stores/mutations.js b/app/assets/javascripts/ref/stores/mutations.js
index 75026a40175..4dc73dabfe2 100644
--- a/app/assets/javascripts/ref/stores/mutations.js
+++ b/app/assets/javascripts/ref/stores/mutations.js
@@ -1,7 +1,7 @@
-import * as types from './mutation_types';
-import { X_TOTAL_HEADER } from '../constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import httpStatusCodes from '~/lib/utils/http_status';
+import { X_TOTAL_HEADER } from '../constants';
+import * as types from './mutation_types';
export default {
[types.SET_PROJECT_ID](state, projectId) {
diff --git a/app/assets/javascripts/registry/explorer/components/delete_image.vue b/app/assets/javascripts/registry/explorer/components/delete_image.vue
new file mode 100644
index 00000000000..22fe9fc1da6
--- /dev/null
+++ b/app/assets/javascripts/registry/explorer/components/delete_image.vue
@@ -0,0 +1,76 @@
+<script>
+import { produce } from 'immer';
+import { GRAPHQL_PAGE_SIZE } from '../constants/index';
+import deleteContainerRepositoryMutation from '../graphql/mutations/delete_container_repository.mutation.graphql';
+import getContainerRepositoryDetailsQuery from '../graphql/queries/get_container_repository_details.query.graphql';
+
+export default {
+ props: {
+ id: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ useUpdateFn: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ methods: {
+ updateImageStatus(store, { data: { destroyContainerRepository } }) {
+ const variables = {
+ id: this.id,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+ const sourceData = store.readQuery({
+ query: getContainerRepositoryDetailsQuery,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftState) => {
+ // eslint-disable-next-line no-param-reassign
+ draftState.containerRepository.status =
+ destroyContainerRepository.containerRepository.status;
+ });
+
+ store.writeQuery({
+ query: getContainerRepositoryDetailsQuery,
+ variables,
+ data,
+ });
+ },
+ doDelete() {
+ this.$emit('start');
+ return this.$apollo
+ .mutate({
+ mutation: deleteContainerRepositoryMutation,
+ variables: {
+ id: this.id,
+ },
+ update: this.useUpdateFn ? this.updateImageStatus : undefined,
+ })
+ .then(({ data }) => {
+ if (data?.destroyContainerRepository?.errors[0]) {
+ this.$emit('error', data?.destroyContainerRepository?.errors);
+ return;
+ }
+ this.$emit('success');
+ })
+ .catch((e) => {
+ // note: we are adding an array to follow the same format of the error raised above
+ this.$emit('error', [e]);
+ })
+ .finally(() => {
+ this.$emit('end');
+ });
+ },
+ },
+ render() {
+ if (this.$scopedSlots?.default) {
+ return this.$scopedSlots.default({ doDelete: this.doDelete });
+ }
+ return null;
+ },
+};
+</script>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue b/app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue
index 96f221bf71d..0432cf1123c 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue
+++ b/app/assets/javascripts/registry/explorer/components/details_page/delete_modal.vue
@@ -1,7 +1,12 @@
<script>
import { GlModal, GlSprintf } from '@gitlab/ui';
import { n__ } from '~/locale';
-import { REMOVE_TAG_CONFIRMATION_TEXT, REMOVE_TAGS_CONFIRMATION_TEXT } from '../../constants/index';
+import {
+ REMOVE_TAG_CONFIRMATION_TEXT,
+ REMOVE_TAGS_CONFIRMATION_TEXT,
+ DELETE_IMAGE_CONFIRMATION_TITLE,
+ DELETE_IMAGE_CONFIRMATION_TEXT,
+} from '../../constants';
export default {
components: {
@@ -14,9 +19,17 @@ export default {
required: false,
default: () => [],
},
+ deleteImage: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
},
computed: {
- modalAction() {
+ modalTitle() {
+ if (this.deleteImage) {
+ return DELETE_IMAGE_CONFIRMATION_TITLE;
+ }
return n__(
'ContainerRegistry|Remove tag',
'ContainerRegistry|Remove tags',
@@ -24,14 +37,19 @@ export default {
);
},
modalDescription() {
+ if (this.deleteImage) {
+ return {
+ message: DELETE_IMAGE_CONFIRMATION_TEXT,
+ };
+ }
if (this.itemsToBeDeleted.length > 1) {
return {
message: REMOVE_TAGS_CONFIRMATION_TEXT,
item: this.itemsToBeDeleted.length,
};
}
- const [first] = this.itemsToBeDeleted;
+ const [first] = this.itemsToBeDeleted;
return {
message: REMOVE_TAG_CONFIRMATION_TEXT,
item: first?.path,
@@ -51,16 +69,17 @@ export default {
ref="deleteModal"
modal-id="delete-tag-modal"
ok-variant="danger"
- @ok="$emit('confirmDelete')"
+ :action-primary="{ text: __('Confirm'), attributes: { variant: 'danger' } }"
+ :action-cancel="{ text: __('Cancel') }"
+ @primary="$emit('confirmDelete')"
@cancel="$emit('cancelDelete')"
>
- <template #modal-title>{{ modalAction }}</template>
- <template #modal-ok>{{ modalAction }}</template>
+ <template #modal-title>{{ modalTitle }}</template>
<p v-if="modalDescription" data-testid="description">
<gl-sprintf :message="modalDescription.message">
- <template #item
- ><b>{{ modalDescription.item }}</b></template
- >
+ <template #item>
+ <b>{{ modalDescription.item }}</b>
+ </template>
</gl-sprintf>
</p>
</gl-modal>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/details_header.vue b/app/assets/javascripts/registry/explorer/components/details_page/details_header.vue
index ed02aa264ed..a4b4c08bc34 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/details_header.vue
+++ b/app/assets/javascripts/registry/explorer/components/details_page/details_header.vue
@@ -1,8 +1,8 @@
<script>
-import { GlSprintf } from '@gitlab/ui';
+import { GlSprintf, GlButton } from '@gitlab/ui';
import { sprintf, n__ } from '~/locale';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import {
DETAILS_PAGE_TITLE,
@@ -24,7 +24,7 @@ import {
export default {
name: 'DetailsHeader',
- components: { GlSprintf, TitleArea, MetadataItem },
+ components: { GlSprintf, GlButton, TitleArea, MetadataItem },
mixins: [timeagoMixin],
props: {
image: {
@@ -36,6 +36,11 @@ export default {
required: false,
default: false,
},
+ disabled: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
},
computed: {
visibilityIcon() {
@@ -65,6 +70,9 @@ export default {
[UNFINISHED_STATUS]: { text: CLEANUP_UNFINISHED_TEXT, tooltip: CLEANUP_UNFINISHED_TOOLTIP },
}[this.image?.expirationPolicyCleanupStatus];
},
+ deleteButtonDisabled() {
+ return this.disabled || !this.image.canDelete;
+ },
},
i18n: {
DETAILS_PAGE_TITLE,
@@ -75,11 +83,13 @@ export default {
<template>
<title-area :metadata-loading="metadataLoading">
<template #title>
- <gl-sprintf :message="$options.i18n.DETAILS_PAGE_TITLE">
- <template #imageName>
- {{ image.name }}
- </template>
- </gl-sprintf>
+ <span data-testid="title">
+ <gl-sprintf :message="$options.i18n.DETAILS_PAGE_TITLE">
+ <template #imageName>
+ {{ image.name }}
+ </template>
+ </gl-sprintf>
+ </span>
</template>
<template #metadata-tags-count>
<metadata-item icon="tag" :text="tagCountText" data-testid="tags-count" />
@@ -103,5 +113,15 @@ export default {
data-testid="updated-and-visibility"
/>
</template>
+ <template #right-actions>
+ <gl-button
+ v-if="!metadataLoading"
+ variant="danger"
+ :disabled="deleteButtonDisabled"
+ @click="$emit('delete')"
+ >
+ {{ __('Delete') }}
+ </gl-button>
+ </template>
</title-area>
</template>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue b/app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue
new file mode 100644
index 00000000000..a16d95a6b30
--- /dev/null
+++ b/app/assets/javascripts/registry/explorer/components/details_page/empty_state.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlEmptyState } from '@gitlab/ui';
+import {
+ NO_TAGS_TITLE,
+ NO_TAGS_MESSAGE,
+ MISSING_OR_DELETED_IMAGE_TITLE,
+ MISSING_OR_DELETED_IMAGE_MESSAGE,
+} from '../../constants/index';
+
+export default {
+ components: {
+ GlEmptyState,
+ },
+ props: {
+ noContainersImage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ isEmptyImage: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ },
+ computed: {
+ title() {
+ return this.isEmptyImage ? MISSING_OR_DELETED_IMAGE_TITLE : NO_TAGS_TITLE;
+ },
+ description() {
+ return this.isEmptyImage ? MISSING_OR_DELETED_IMAGE_MESSAGE : NO_TAGS_MESSAGE;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-empty-state
+ :title="title"
+ :svg-path="noContainersImage"
+ :description="description"
+ class="gl-mx-auto gl-my-0"
+ />
+</template>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/empty_tags_state.vue b/app/assets/javascripts/registry/explorer/components/details_page/empty_tags_state.vue
deleted file mode 100644
index 0c684d124d5..00000000000
--- a/app/assets/javascripts/registry/explorer/components/details_page/empty_tags_state.vue
+++ /dev/null
@@ -1,33 +0,0 @@
-<script>
-import { GlEmptyState } from '@gitlab/ui';
-import {
- EMPTY_IMAGE_REPOSITORY_TITLE,
- EMPTY_IMAGE_REPOSITORY_MESSAGE,
-} from '../../constants/index';
-
-export default {
- components: {
- GlEmptyState,
- },
- props: {
- noContainersImage: {
- type: String,
- required: false,
- default: '',
- },
- },
- i18n: {
- EMPTY_IMAGE_REPOSITORY_TITLE,
- EMPTY_IMAGE_REPOSITORY_MESSAGE,
- },
-};
-</script>
-
-<template>
- <gl-empty-state
- :title="$options.i18n.EMPTY_IMAGE_REPOSITORY_TITLE"
- :svg-path="noContainersImage"
- :description="$options.i18n.EMPTY_IMAGE_REPOSITORY_MESSAGE"
- class="gl-mx-auto gl-my-0"
- />
-</template>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue b/app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue
new file mode 100644
index 00000000000..fc1504f6c31
--- /dev/null
+++ b/app/assets/javascripts/registry/explorer/components/details_page/status_alert.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+import {
+ IMAGE_STATUS_MESSAGES,
+ IMAGE_STATUS_TITLES,
+ IMAGE_STATUS_ALERT_TYPE,
+ PACKAGE_DELETE_HELP_PAGE_PATH,
+} from '../../constants';
+
+export default {
+ components: {
+ GlAlert,
+ GlSprintf,
+ GlLink,
+ },
+ props: {
+ status: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ message() {
+ return IMAGE_STATUS_MESSAGES[this.status];
+ },
+ title() {
+ return IMAGE_STATUS_TITLES[this.status];
+ },
+ variant() {
+ return IMAGE_STATUS_ALERT_TYPE[this.status];
+ },
+ },
+ links: {
+ PACKAGE_DELETE_HELP_PAGE_PATH,
+ },
+};
+</script>
+<template>
+ <gl-alert :title="title" :variant="variant">
+ <span data-testid="message">
+ <gl-sprintf :message="message">
+ <template #link="{ content }">
+ <gl-link :href="$options.links.PACKAGE_DELETE_HELP_PAGE_PATH" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue
index 1e0736c4a53..bc10246614a 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue
+++ b/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton } from '@gitlab/ui';
-import TagsListRow from './tags_list_row.vue';
import { REMOVE_TAGS_BUTTON_TITLE, TAGS_LIST_TITLE } from '../../constants/index';
+import TagsListRow from './tags_list_row.vue';
export default {
name: 'TagsList',
@@ -20,6 +20,11 @@ export default {
default: true,
required: false,
},
+ disabled: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
},
i18n: {
REMOVE_TAGS_BUTTON_TITLE,
@@ -37,6 +42,9 @@ export default {
showMultiDeleteButton() {
return this.tags.some((tag) => tag.canDelete) && !this.isMobile;
},
+ multiDeleteButtonIsDisabled() {
+ return !this.hasSelectedItems || this.disabled;
+ },
},
methods: {
updateSelectedItems(name) {
@@ -55,7 +63,7 @@ export default {
<gl-button
v-if="showMultiDeleteButton"
- :disabled="!hasSelectedItems"
+ :disabled="multiDeleteButtonIsDisabled"
category="secondary"
variant="danger"
@click="$emit('delete', selectedItems)"
@@ -70,6 +78,7 @@ export default {
:first="index === 0"
:selected="selectedItems[tag.name]"
:is-mobile="isMobile"
+ :disabled="disabled"
@select="updateSelectedItems(tag.name)"
@delete="$emit('delete', { [tag.name]: true })"
/>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue b/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue
index 2e4a489f2cb..c66f92bdd67 100644
--- a/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue
+++ b/app/assets/javascripts/registry/explorer/components/details_page/tags_list_row.vue
@@ -1,13 +1,12 @@
<script>
import { GlFormCheckbox, GlTooltipDirective, GlSprintf, GlIcon } from '@gitlab/ui';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
import { n__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { formatDate } from '~/lib/utils/datetime_utility';
-import ListItem from '~/vue_shared/components/registry/list_item.vue';
-import DeleteButton from '../delete_button.vue';
import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
REMOVE_TAG_BUTTON_TITLE,
DIGEST_LABEL,
@@ -20,6 +19,7 @@ import {
NOT_AVAILABLE_TEXT,
NOT_AVAILABLE_SIZE,
} from '../../constants/index';
+import DeleteButton from '../delete_button.vue';
export default {
components: {
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue b/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
index 264a3c27cde..9ae5b0f9eb1 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue
@@ -1,12 +1,10 @@
<script>
import { GlTooltipDirective, GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
-import { n__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { n__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
-import DeleteButton from '../delete_button.vue';
-
import {
ASYNC_DELETE_IMAGE_ERROR_MESSAGE,
LIST_DELETE_BUTTON_DISABLED,
@@ -16,6 +14,7 @@ import {
IMAGE_DELETE_SCHEDULED_STATUS,
IMAGE_FAILED_DELETED_STATUS,
} from '../../constants/index';
+import DeleteButton from '../delete_button.vue';
export default {
name: 'ImageListRow',
diff --git a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue b/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
index f01e3c9d24a..8d7505dfbae 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
@@ -1,8 +1,8 @@
<script>
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
-import { n__, sprintf } from '~/locale';
import { approximateDuration, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
+import { n__, sprintf } from '~/locale';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import {
CONTAINER_REGISTRY_TITLE,
diff --git a/app/assets/javascripts/registry/explorer/constants/details.js b/app/assets/javascripts/registry/explorer/constants/details.js
index b5627352857..3f04538a18b 100644
--- a/app/assets/javascripts/registry/explorer/constants/details.js
+++ b/app/assets/javascripts/registry/explorer/constants/details.js
@@ -1,3 +1,4 @@
+import { helpPagePath } from '~/helpers/help_page_helper';
import { s__, __ } from '~/locale';
// Translations strings
@@ -32,18 +33,30 @@ export const CONFIGURATION_DETAILS_ROW_TEST = s__(
export const REMOVE_TAG_BUTTON_TITLE = s__('ContainerRegistry|Remove tag');
export const REMOVE_TAGS_BUTTON_TITLE = s__('ContainerRegistry|Delete selected');
+
export const REMOVE_TAG_CONFIRMATION_TEXT = s__(
`ContainerRegistry|You are about to remove %{item}. Are you sure?`,
);
export const REMOVE_TAGS_CONFIRMATION_TEXT = s__(
`ContainerRegistry|You are about to remove %{item} tags. Are you sure?`,
);
-export const EMPTY_IMAGE_REPOSITORY_TITLE = s__('ContainerRegistry|This image has no active tags');
-export const EMPTY_IMAGE_REPOSITORY_MESSAGE = s__(
+export const NO_TAGS_TITLE = s__('ContainerRegistry|This image has no active tags');
+export const NO_TAGS_MESSAGE = s__(
`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.`,
);
+
+export const MISSING_OR_DELETED_IMAGE_TITLE = s__(
+ 'ContainerRegistry|The image repository could not be found.',
+);
+export const MISSING_OR_DELETED_IMAGE_MESSAGE = s__(
+ 'ContainerRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page.',
+);
+export const MISSING_OR_DELETE_IMAGE_BREADCRUMB = s__(
+ 'ContainerRegistry|Image repository not found',
+);
+
export const ADMIN_GARBAGE_COLLECTION_TIP = s__(
'ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage.',
);
@@ -76,6 +89,29 @@ export const CLEANUP_DISABLED_TOOLTIP = s__(
'ContainerRegistry|Cleanup is disabled for this project',
);
+export const DETAILS_DELETE_IMAGE_ERROR_MESSAGE = s__(
+ 'ContainerRegistry|Something went wrong while scheduling the image for deletion.',
+);
+
+export const DELETE_IMAGE_CONFIRMATION_TITLE = s__('ContainerRegistry|Delete image repository?');
+export const DELETE_IMAGE_CONFIRMATION_TEXT = s__(
+ 'ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone.',
+);
+
+export const SCHEDULED_FOR_DELETION_STATUS_TITLE = s__(
+ 'ContainerRegistry|Image repository will be deleted',
+);
+export const SCHEDULED_FOR_DELETION_STATUS_MESSAGE = s__(
+ 'ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}',
+);
+
+export const FAILED_DELETION_STATUS_TITLE = s__(
+ 'ContainerRegistry|Image repository deletion failed',
+);
+export const FAILED_DELETION_STATUS_MESSAGE = s__(
+ 'ContainerRegistry|This image repository has failed to be deleted',
+);
+
// Parameters
export const DEFAULT_PAGE = 1;
@@ -85,15 +121,39 @@ export const ALERT_SUCCESS_TAG = 'success_tag';
export const ALERT_DANGER_TAG = 'danger_tag';
export const ALERT_SUCCESS_TAGS = 'success_tags';
export const ALERT_DANGER_TAGS = 'danger_tags';
+export const ALERT_DANGER_IMAGE = 'danger_image';
+
+export const DELETE_SCHEDULED = 'DELETE_SCHEDULED';
+export const DELETE_FAILED = 'DELETE_FAILED';
export const ALERT_MESSAGES = {
[ALERT_SUCCESS_TAG]: DELETE_TAG_SUCCESS_MESSAGE,
[ALERT_DANGER_TAG]: DELETE_TAG_ERROR_MESSAGE,
[ALERT_SUCCESS_TAGS]: DELETE_TAGS_SUCCESS_MESSAGE,
[ALERT_DANGER_TAGS]: DELETE_TAGS_ERROR_MESSAGE,
+ [ALERT_DANGER_IMAGE]: DETAILS_DELETE_IMAGE_ERROR_MESSAGE,
};
export const UNFINISHED_STATUS = 'UNFINISHED';
export const UNSCHEDULED_STATUS = 'UNSCHEDULED';
export const SCHEDULED_STATUS = 'SCHEDULED';
export const ONGOING_STATUS = 'ONGOING';
+
+export const IMAGE_STATUS_TITLES = {
+ [DELETE_SCHEDULED]: SCHEDULED_FOR_DELETION_STATUS_TITLE,
+ [DELETE_FAILED]: FAILED_DELETION_STATUS_TITLE,
+};
+
+export const IMAGE_STATUS_MESSAGES = {
+ [DELETE_SCHEDULED]: SCHEDULED_FOR_DELETION_STATUS_MESSAGE,
+ [DELETE_FAILED]: FAILED_DELETION_STATUS_MESSAGE,
+};
+
+export const IMAGE_STATUS_ALERT_TYPE = {
+ [DELETE_SCHEDULED]: 'info',
+ [DELETE_FAILED]: 'warning',
+};
+
+export const PACKAGE_DELETE_HELP_PAGE_PATH = helpPagePath('user/packages/container_registry', {
+ anchor: 'delete-images',
+});
diff --git a/app/assets/javascripts/registry/explorer/constants/list.js b/app/assets/javascripts/registry/explorer/constants/list.js
index 37ced72861e..f59b9d7a9f5 100644
--- a/app/assets/javascripts/registry/explorer/constants/list.js
+++ b/app/assets/javascripts/registry/explorer/constants/list.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
// Translations strings
@@ -35,8 +35,6 @@ export const ASYNC_DELETE_IMAGE_ERROR_MESSAGE = s__(
export const DELETE_IMAGE_SUCCESS_MESSAGE = s__(
'ContainerRegistry|%{title} was successfully scheduled for deletion',
);
-export const IMAGE_REPOSITORY_LIST_LABEL = s__('ContainerRegistry|Image Repositories');
-export const SEARCH_PLACEHOLDER_TEXT = s__('ContainerRegistry|Filter by name');
export const EMPTY_RESULT_TITLE = s__('ContainerRegistry|Sorry, your filter produced no results.');
export const EMPTY_RESULT_MESSAGE = s__(
'ContainerRegistry|To widen your search, change or remove the filters above.',
@@ -47,3 +45,9 @@ export const EMPTY_RESULT_MESSAGE = s__(
export const IMAGE_DELETE_SCHEDULED_STATUS = 'DELETE_SCHEDULED';
export const IMAGE_FAILED_DELETED_STATUS = 'DELETE_FAILED';
export const GRAPHQL_PAGE_SIZE = 10;
+
+export const SORT_FIELDS = [
+ { orderBy: 'UPDATED', label: __('Updated') },
+ { orderBy: 'CREATED', label: __('Created') },
+ { orderBy: 'NAME', label: __('Name') },
+];
diff --git a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql b/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
index 8b6d778c655..01cb7fa1cab 100644
--- a/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
+++ b/app/assets/javascripts/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
@@ -6,9 +6,17 @@ query getContainerRepositoriesDetails(
$after: String
$before: String
$isGroupPage: Boolean!
+ $sort: ContainerRepositorySort
) {
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
- containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ containerRepositories(
+ name: $name
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ sort: $sort
+ ) {
nodes {
id
tagsCount
@@ -16,7 +24,14 @@ query getContainerRepositoriesDetails(
}
}
group(fullPath: $fullPath) @include(if: $isGroupPage) {
- containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ containerRepositories(
+ name: $name
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ sort: $sort
+ ) {
nodes {
id
tagsCount
diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js
index a3890ab5c42..f66839a74bf 100644
--- a/app/assets/javascripts/registry/explorer/index.js
+++ b/app/assets/javascripts/registry/explorer/index.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
-import Translate from '~/vue_shared/translate';
+import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import PerformancePlugin from '~/performance/vue_performance_plugin';
-import RegistryExplorer from './pages/index.vue';
+import Translate from '~/vue_shared/translate';
import RegistryBreadcrumb from './components/registry_breadcrumb.vue';
-import createRouter from './router';
import { apolloProvider } from './graphql/index';
+import RegistryExplorer from './pages/index.vue';
+import createRouter from './router';
Vue.use(Translate);
Vue.use(GlToast);
@@ -29,7 +29,14 @@ export default () => {
return null;
}
- const { endpoint, expirationPolicy, isGroupPage, isAdmin, ...config } = el.dataset;
+ const {
+ endpoint,
+ expirationPolicy,
+ isGroupPage,
+ isAdmin,
+ showUnfinishedTagCleanupCallout,
+ ...config
+ } = el.dataset;
// This is a mini state to help the breadcrumb have the correct name in the details page
const breadCrumbState = Vue.observable({
@@ -57,6 +64,7 @@ export default () => {
expirationPolicy: expirationPolicy ? JSON.parse(expirationPolicy) : undefined,
isGroupPage: parseBoolean(isGroupPage),
isAdmin: parseBoolean(isAdmin),
+ showUnfinishedTagCleanupCallout: parseBoolean(showUnfinishedTagCleanupCallout),
},
/* eslint-disable @gitlab/require-i18n-strings */
dockerBuildCommand: `docker build -t ${config.repositoryUrl} .`,
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue
index 0894fd6fcfa..0403467468a 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/registry/explorer/pages/details.vue
@@ -2,28 +2,32 @@
import { GlKeysetPagination, GlResizeObserverDirective } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import createFlash from '~/flash';
-import Tracking from '~/tracking';
+import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
+import Tracking from '~/tracking';
+import DeleteImage from '../components/delete_image.vue';
import DeleteAlert from '../components/details_page/delete_alert.vue';
-import PartialCleanupAlert from '../components/details_page/partial_cleanup_alert.vue';
import DeleteModal from '../components/details_page/delete_modal.vue';
import DetailsHeader from '../components/details_page/details_header.vue';
+import EmptyState from '../components/details_page/empty_state.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 EmptyTagsState from '../components/details_page/empty_tags_state.vue';
-
-import getContainerRepositoryDetailsQuery from '../graphql/queries/get_container_repository_details.query.graphql';
-import deleteContainerRepositoryTagsMutation from '../graphql/mutations/delete_container_repository_tags.mutation.graphql';
import {
ALERT_SUCCESS_TAG,
ALERT_DANGER_TAG,
ALERT_SUCCESS_TAGS,
ALERT_DANGER_TAGS,
+ ALERT_DANGER_IMAGE,
GRAPHQL_PAGE_SIZE,
FETCH_IMAGES_LIST_ERROR_MESSAGE,
UNFINISHED_STATUS,
+ MISSING_OR_DELETE_IMAGE_BREADCRUMB,
} from '../constants/index';
+import deleteContainerRepositoryTagsMutation from '../graphql/mutations/delete_container_repository_tags.mutation.graphql';
+import getContainerRepositoryDetailsQuery from '../graphql/queries/get_container_repository_details.query.graphql';
export default {
name: 'RegistryDetailsPage',
@@ -35,7 +39,9 @@ export default {
DeleteModal,
TagsList,
TagsLoader,
- EmptyTagsState,
+ EmptyState,
+ StatusAlert,
+ DeleteImage,
},
directives: {
GlResizeObserver: GlResizeObserverDirective,
@@ -53,7 +59,7 @@ export default {
},
result({ data }) {
this.tagsPageInfo = data.containerRepository?.tags?.pageInfo;
- this.breadCrumbState.updateName(data.containerRepository?.name);
+ this.updateBreadcrumb();
},
error() {
createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
@@ -68,7 +74,8 @@ export default {
isMobile: false,
mutationLoading: false,
deleteAlertType: null,
- dismissPartialCleanupWarning: false,
+ hidePartialCleanupWarning: false,
+ deleteImageAlert: false,
};
},
computed: {
@@ -86,8 +93,9 @@ export default {
},
showPartialCleanupWarning() {
return (
+ this.config.showUnfinishedTagCleanupCallout &&
this.image?.expirationPolicyCleanupStatus === UNFINISHED_STATUS &&
- !this.dismissPartialCleanupWarning
+ !this.hidePartialCleanupWarning
);
},
tracking() {
@@ -99,14 +107,32 @@ export default {
showPagination() {
return this.tagsPageInfo.hasPreviousPage || this.tagsPageInfo.hasNextPage;
},
+ hasNoTags() {
+ return this.tags.length === 0;
+ },
+ pageActionsAreDisabled() {
+ return Boolean(this.image?.status);
+ },
},
methods: {
+ updateBreadcrumb() {
+ const name = this.image?.name || MISSING_OR_DELETE_IMAGE_BREADCRUMB;
+ this.breadCrumbState.updateName(name);
+ },
deleteTags(toBeDeleted) {
+ this.deleteImageAlert = false;
this.itemsToBeDeleted = this.tags.filter((tag) => toBeDeleted[tag.name]);
this.track('click_button');
this.$refs.deleteModal.show();
},
- async handleDelete() {
+ confirmDelete() {
+ if (this.deleteImageAlert) {
+ this.$refs.deleteImage.doDelete();
+ } else {
+ this.handleDeleteTag();
+ }
+ },
+ async handleDeleteTag() {
this.track('confirm_delete');
const { itemsToBeDeleted } = this;
this.itemsToBeDeleted = [];
@@ -168,51 +194,94 @@ export default {
});
}
},
+ dismissPartialCleanupWarning() {
+ this.hidePartialCleanupWarning = true;
+ axios.post(this.config.userCalloutsPath, {
+ feature_name: this.config.userCalloutId,
+ });
+ },
+ deleteImage() {
+ this.deleteImageAlert = true;
+ this.itemsToBeDeleted = [{ path: this.image.path }];
+ this.$refs.deleteModal.show();
+ },
+ deleteImageError() {
+ this.deleteAlertType = ALERT_DANGER_IMAGE;
+ },
+ deleteImageIniit() {
+ this.itemsToBeDeleted = [];
+ this.mutationLoading = true;
+ },
},
};
</script>
<template>
<div v-gl-resize-observer="handleResize" class="gl-my-3">
- <delete-alert
- v-model="deleteAlertType"
- :garbage-collection-help-page-path="config.garbageCollectionHelpPagePath"
- :is-admin="config.isAdmin"
- class="gl-my-2"
- />
+ <template v-if="image">
+ <delete-alert
+ v-model="deleteAlertType"
+ :garbage-collection-help-page-path="config.garbageCollectionHelpPagePath"
+ :is-admin="config.isAdmin"
+ class="gl-my-2"
+ />
+
+ <partial-cleanup-alert
+ v-if="showPartialCleanupWarning"
+ :run-cleanup-policies-help-page-path="config.runCleanupPoliciesHelpPagePath"
+ :cleanup-policies-help-page-path="config.cleanupPoliciesHelpPagePath"
+ @dismiss="dismissPartialCleanupWarning"
+ />
- <partial-cleanup-alert
- v-if="showPartialCleanupWarning"
- :run-cleanup-policies-help-page-path="config.runCleanupPoliciesHelpPagePath"
- :cleanup-policies-help-page-path="config.cleanupPoliciesHelpPagePath"
- @dismiss="dismissPartialCleanupWarning = true"
- />
+ <status-alert v-if="image.status" :status="image.status" />
- <details-header :image="image" :metadata-loading="isLoading" />
+ <details-header
+ :image="image"
+ :metadata-loading="isLoading"
+ :disabled="pageActionsAreDisabled"
+ @delete="deleteImage"
+ />
- <tags-loader v-if="isLoading" />
- <template v-else>
- <empty-tags-state v-if="tags.length === 0" :no-containers-image="config.noContainersImage" />
+ <tags-loader v-if="isLoading" />
<template v-else>
- <tags-list :tags="tags" :is-mobile="isMobile" @delete="deleteTags" />
- <div class="gl-display-flex gl-justify-content-center">
- <gl-keyset-pagination
- v-if="showPagination"
- :has-next-page="tagsPageInfo.hasNextPage"
- :has-previous-page="tagsPageInfo.hasPreviousPage"
- class="gl-mt-3"
- @prev="fetchPreviousPage"
- @next="fetchNextPage"
+ <empty-state v-if="hasNoTags" :no-containers-image="config.noContainersImage" />
+ <template v-else>
+ <tags-list
+ :tags="tags"
+ :is-mobile="isMobile"
+ :disabled="pageActionsAreDisabled"
+ @delete="deleteTags"
/>
- </div>
+ <div class="gl-display-flex gl-justify-content-center">
+ <gl-keyset-pagination
+ v-if="showPagination"
+ :has-next-page="tagsPageInfo.hasNextPage"
+ :has-previous-page="tagsPageInfo.hasPreviousPage"
+ class="gl-mt-3"
+ @prev="fetchPreviousPage"
+ @next="fetchNextPage"
+ />
+ </div>
+ </template>
</template>
- </template>
- <delete-modal
- ref="deleteModal"
- :items-to-be-deleted="itemsToBeDeleted"
- @confirmDelete="handleDelete"
- @cancel="track('cancel_delete')"
- />
+ <delete-image
+ :id="image.id"
+ ref="deleteImage"
+ use-update-fn
+ @start="deleteImageIniit"
+ @error="deleteImageError"
+ @end="mutationLoading = false"
+ />
+
+ <delete-modal
+ ref="deleteModal"
+ :items-to-be-deleted="itemsToBeDeleted"
+ :delete-image="deleteImageAlert"
+ @confirmDelete="confirmDelete"
+ @cancel="track('cancel_delete')"
+ />
+ </template>
+ <empty-state v-else is-empty-image :no-containers-image="config.noContainersImage" />
</div>
</template>
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 336a997d629..8cad9b4ecfc 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -7,17 +7,15 @@ import {
GlLink,
GlAlert,
GlSkeletonLoader,
- GlSearchBoxByClick,
} from '@gitlab/ui';
import { get } from 'lodash';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
-import Tracking from '~/tracking';
import createFlash from '~/flash';
+import Tracking from '~/tracking';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import DeleteImage from '../components/delete_image.vue';
import RegistryHeader from '../components/list_page/registry_header.vue';
-import getContainerRepositoriesDetails from '../graphql/queries/get_container_repositories_details.query.graphql';
-import deleteContainerRepositoryMutation from '../graphql/mutations/delete_container_repository.mutation.graphql';
-
import {
DELETE_IMAGE_SUCCESS_MESSAGE,
DELETE_IMAGE_ERROR_MESSAGE,
@@ -25,13 +23,13 @@ import {
CONNECTION_ERROR_MESSAGE,
REMOVE_REPOSITORY_MODAL_TEXT,
REMOVE_REPOSITORY_LABEL,
- SEARCH_PLACEHOLDER_TEXT,
- IMAGE_REPOSITORY_LIST_LABEL,
EMPTY_RESULT_TITLE,
EMPTY_RESULT_MESSAGE,
GRAPHQL_PAGE_SIZE,
FETCH_IMAGES_LIST_ERROR_MESSAGE,
+ SORT_FIELDS,
} from '../constants/index';
+import getContainerRepositoriesDetails from '../graphql/queries/get_container_repositories_details.query.graphql';
export default {
name: 'RegistryListPage',
@@ -58,8 +56,9 @@ export default {
GlLink,
GlAlert,
GlSkeletonLoader,
- GlSearchBoxByClick,
RegistryHeader,
+ DeleteImage,
+ RegistrySearch,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -76,11 +75,10 @@ export default {
CONNECTION_ERROR_MESSAGE,
REMOVE_REPOSITORY_MODAL_TEXT,
REMOVE_REPOSITORY_LABEL,
- SEARCH_PLACEHOLDER_TEXT,
- IMAGE_REPOSITORY_LIST_LABEL,
EMPTY_RESULT_TITLE,
EMPTY_RESULT_MESSAGE,
},
+ searchConfig: SORT_FIELDS,
apollo: {
baseImages: {
query: getContainerRepositoriesQuery,
@@ -122,7 +120,8 @@ export default {
containerRepositoriesCount: 0,
itemToDelete: {},
deleteAlertType: null,
- searchValue: null,
+ filter: [],
+ sorting: { orderBy: 'UPDATED', sort: 'desc' },
name: null,
mutationLoading: false,
fetchAdditionalDetails: false,
@@ -141,6 +140,7 @@ export default {
queryVariables() {
return {
name: this.name,
+ sort: this.sortBy,
fullPath: this.config.isGroupPage ? this.config.groupPath : this.config.projectPath,
isGroupPage: this.config.isGroupPage,
first: GRAPHQL_PAGE_SIZE,
@@ -165,6 +165,10 @@ export default {
? DELETE_IMAGE_SUCCESS_MESSAGE
: DELETE_IMAGE_ERROR_MESSAGE;
},
+ sortBy() {
+ const { orderBy, sort } = this.sorting;
+ return `${orderBy}_${sort}`.toUpperCase();
+ },
},
mounted() {
// If the two graphql calls - which are not batched - resolve togheter we will have a race
@@ -179,30 +183,6 @@ export default {
this.itemToDelete = item;
this.$refs.deleteModal.show();
},
- handleDeleteImage() {
- this.track('confirm_delete');
- this.mutationLoading = true;
- return this.$apollo
- .mutate({
- mutation: deleteContainerRepositoryMutation,
- variables: {
- id: this.itemToDelete.id,
- },
- })
- .then(({ data }) => {
- if (data?.destroyContainerRepository?.errors[0]) {
- this.deleteAlertType = 'danger';
- } else {
- this.deleteAlertType = 'success';
- }
- })
- .catch(() => {
- this.deleteAlertType = 'danger';
- })
- .finally(() => {
- this.mutationLoading = false;
- });
- },
dismissDeleteAlert() {
this.deleteAlertType = null;
this.itemToDelete = {};
@@ -250,6 +230,20 @@ export default {
});
}
},
+ startDelete() {
+ this.track('confirm_delete');
+ this.mutationLoading = true;
+ },
+ updateSorting(value) {
+ this.sorting = {
+ ...this.sorting,
+ ...value,
+ };
+ },
+ doFilter() {
+ const search = this.filter.find((i) => i.type === 'filtered-search-term');
+ this.name = search?.value?.data;
+ },
},
};
</script>
@@ -302,6 +296,16 @@ export default {
</template>
</registry-header>
+ <registry-search
+ :filter="filter"
+ :sorting="sorting"
+ :tokens="[]"
+ :sortable-fields="$options.searchConfig"
+ @sorting:changed="updateSorting"
+ @filter:changed="filter = $event"
+ @filter:submit="doFilter"
+ />
+
<div v-if="isLoading" class="gl-mt-5">
<gl-skeleton-loader
v-for="index in $options.loader.repeat"
@@ -317,20 +321,6 @@ export default {
</div>
<template v-else>
<template v-if="images.length > 0 || name">
- <div class="gl-display-flex gl-p-1 gl-mt-3" data-testid="listHeader">
- <div class="gl-flex-fill-1">
- <h5>{{ $options.i18n.IMAGE_REPOSITORY_LIST_LABEL }}</h5>
- </div>
- <div>
- <gl-search-box-by-click
- v-model="searchValue"
- :placeholder="$options.i18n.SEARCH_PLACEHOLDER_TEXT"
- @clear="name = null"
- @submit="name = $event"
- />
- </div>
- </div>
-
<image-list
v-if="images.length"
:images="images"
@@ -358,23 +348,32 @@ export default {
</template>
</template>
- <gl-modal
- ref="deleteModal"
- modal-id="delete-image-modal"
- ok-variant="danger"
- @ok="handleDeleteImage"
- @cancel="track('cancel_delete')"
+ <delete-image
+ :id="itemToDelete.id"
+ @start="startDelete"
+ @error="deleteAlertType = 'danger'"
+ @success="deleteAlertType = 'success'"
+ @end="mutationLoading = false"
>
- <template #modal-title>{{ $options.i18n.REMOVE_REPOSITORY_LABEL }}</template>
- <p>
- <gl-sprintf :message="$options.i18n.REMOVE_REPOSITORY_MODAL_TEXT">
- <template #title>
- <b>{{ itemToDelete.path }}</b>
- </template>
- </gl-sprintf>
- </p>
- <template #modal-ok>{{ __('Remove') }}</template>
- </gl-modal>
+ <template #default="{ doDelete }">
+ <gl-modal
+ ref="deleteModal"
+ modal-id="delete-image-modal"
+ :action-primary="{ text: __('Remove'), attributes: { variant: 'danger' } }"
+ @primary="doDelete"
+ @cancel="track('cancel_delete')"
+ >
+ <template #modal-title>{{ $options.i18n.REMOVE_REPOSITORY_LABEL }}</template>
+ <p>
+ <gl-sprintf :message="$options.i18n.REMOVE_REPOSITORY_MODAL_TEXT">
+ <template #title>
+ <b>{{ itemToDelete.path }}</b>
+ </template>
+ </gl-sprintf>
+ </p>
+ </gl-modal>
+ </template>
+ </delete-image>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/registry/explorer/router.js b/app/assets/javascripts/registry/explorer/router.js
index d8903cf0931..a0c4417d549 100644
--- a/app/assets/javascripts/registry/explorer/router.js
+++ b/app/assets/javascripts/registry/explorer/router.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
-import List from './pages/list.vue';
-import Details from './pages/details.vue';
import { CONTAINER_REGISTRY_TITLE } from './constants/index';
+import Details from './pages/details.vue';
+import List from './pages/list.vue';
Vue.use(VueRouter);
diff --git a/app/assets/javascripts/registry/settings/components/registry_settings_app.vue b/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
index 66eb681784e..480590ec71e 100644
--- a/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
+++ b/app/assets/javascripts/registry/settings/components/registry_settings_app.vue
@@ -1,7 +1,6 @@
<script>
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import { isEqual, get, isEmpty } from 'lodash';
-import expirationPolicyQuery from '../graphql/queries/get_expiration_policy.query.graphql';
import {
FETCH_SETTINGS_ERROR_MESSAGE,
UNAVAILABLE_FEATURE_TITLE,
@@ -9,6 +8,7 @@ import {
UNAVAILABLE_USER_FEATURE_TEXT,
UNAVAILABLE_ADMIN_FEATURE_TEXT,
} from '../constants';
+import expirationPolicyQuery from '../graphql/queries/get_expiration_policy.query.graphql';
import SettingsForm from './settings_form.vue';
diff --git a/app/assets/javascripts/registry/settings/components/settings_form.vue b/app/assets/javascripts/registry/settings/components/settings_form.vue
index 7043cea49ba..eb731c382e1 100644
--- a/app/assets/javascripts/registry/settings/components/settings_form.vue
+++ b/app/assets/javascripts/registry/settings/components/settings_form.vue
@@ -1,6 +1,5 @@
<script>
import { GlCard, GlButton, GlSprintf } from '@gitlab/ui';
-import Tracking from '~/tracking';
import {
UPDATE_SETTINGS_ERROR_MESSAGE,
UPDATE_SETTINGS_SUCCESS_MESSAGE,
@@ -19,13 +18,14 @@ import {
CADENCE_LABEL,
EXPIRATION_POLICY_FOOTER_NOTE,
} from '~/registry/settings/constants';
-import { formOptionsGenerator } from '~/registry/settings/utils';
import updateContainerExpirationPolicyMutation from '~/registry/settings/graphql/mutations/update_container_expiration_policy.mutation.graphql';
import { updateContainerExpirationPolicy } from '~/registry/settings/graphql/utils/cache_update';
+import { formOptionsGenerator } from '~/registry/settings/utils';
+import Tracking from '~/tracking';
import ExpirationDropdown from './expiration_dropdown.vue';
import ExpirationInput from './expiration_input.vue';
-import ExpirationToggle from './expiration_toggle.vue';
import ExpirationRunText from './expiration_run_text.vue';
+import ExpirationToggle from './expiration_toggle.vue';
export default {
components: {
diff --git a/app/assets/javascripts/registry/settings/registry_settings_bundle.js b/app/assets/javascripts/registry/settings/registry_settings_bundle.js
index 6a4584b1b28..65af6f846aa 100644
--- a/app/assets/javascripts/registry/settings/registry_settings_bundle.js
+++ b/app/assets/javascripts/registry/settings/registry_settings_bundle.js
@@ -1,7 +1,7 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
-import Translate from '~/vue_shared/translate';
+import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
+import Translate from '~/vue_shared/translate';
import RegistrySettingsApp from './components/registry_settings_app.vue';
import { apolloProvider } from './graphql/index';
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 6fbae95094a..02929062cee 100644
--- a/app/assets/javascripts/related_issues/components/add_issuable_form.vue
+++ b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
@@ -1,8 +1,7 @@
<script>
import { GlFormGroup, GlFormRadioGroup, GlButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-import RelatedIssuableInput from './related_issuable_input.vue';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import {
issuableTypesMap,
@@ -11,6 +10,7 @@ import {
addRelatedIssueErrorMap,
addRelatedItemErrorMap,
} from '../constants';
+import RelatedIssuableInput from './related_issuable_input.vue';
export default {
name: 'AddIssuableForm',
diff --git a/app/assets/javascripts/related_issues/components/related_issuable_input.vue b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
index a124b055e19..2dc56c3110b 100644
--- a/app/assets/javascripts/related_issues/components/related_issuable_input.vue
+++ b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
@@ -1,13 +1,13 @@
<script>
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
-import issueToken from './issue_token.vue';
import {
autoCompleteTextMap,
inputPlaceholderConfidentialTextMap,
inputPlaceholderTextMap,
issuableTypesMap,
} from '../constants';
+import issueToken from './issue_token.vue';
const SPACE_FACTOR = 1;
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 2591e3e7f48..c042f0eef5f 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -1,13 +1,13 @@
<script>
import { GlLink, GlIcon, GlButton } from '@gitlab/ui';
-import AddIssuableForm from './add_issuable_form.vue';
-import RelatedIssuesList from './related_issues_list.vue';
import {
issuableIconMap,
issuableQaClassMap,
linkedIssueTypesMap,
linkedIssueTypesTextMap,
} from '../constants';
+import AddIssuableForm from './add_issuable_form.vue';
+import RelatedIssuesList from './related_issues_list.vue';
export default {
name: 'RelatedIssuesBlock',
@@ -146,7 +146,7 @@ export default {
class="gl-display-flex gl-align-items-center gl-ml-2 gl-text-gray-500"
:aria-label="__('Read more about related issues')"
>
- <gl-icon name="question" :size="12" role="text" />
+ <gl-icon name="question" :size="12" />
</gl-link>
<div class="gl-display-inline-flex">
diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue
index 8021d390d95..825a4a02b71 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_list.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue
@@ -60,8 +60,8 @@ export default {
const nextItemEl = itemEl.nextElementSibling;
return {
- beforeId: prevItemEl && parseInt(prevItemEl.dataset.orderingId, 0),
- afterId: nextItemEl && parseInt(nextItemEl.dataset.orderingId, 0),
+ beforeId: prevItemEl && parseInt(prevItemEl.dataset.orderingId, 10),
+ afterId: nextItemEl && parseInt(nextItemEl.dataset.orderingId, 10),
};
},
reordered(event) {
diff --git a/app/assets/javascripts/related_issues/components/related_issues_root.vue b/app/assets/javascripts/related_issues/components/related_issues_root.vue
index a81edcf141c..c35a1ff0b63 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_root.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_root.vue
@@ -25,9 +25,6 @@ Your caret can stop touching a `rawReference` can happen in a variety of ways:
*/
import { deprecatedCreateFlash as Flash } from '~/flash';
import { __ } from '~/locale';
-import RelatedIssuesBlock from './related_issues_block.vue';
-import RelatedIssuesStore from '../stores/related_issues_store';
-import RelatedIssuesService from '../services/related_issues_service';
import {
relatedIssuesRemoveErrorMap,
pathIndeterminateErrorMap,
@@ -35,6 +32,9 @@ import {
issuableTypesMap,
PathIdSeparator,
} from '../constants';
+import RelatedIssuesService from '../services/related_issues_service';
+import RelatedIssuesStore from '../stores/related_issues_store';
+import RelatedIssuesBlock from './related_issues_block.vue';
export default {
name: 'RelatedIssuesRoot',
diff --git a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
index 7db76ed576c..ccb92d2aedc 100644
--- a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
+++ b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import { sprintf, n__, s__ } from '~/locale';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import { parseIssuableData } from '../../issue_show/utils/parse_data';
diff --git a/app/assets/javascripts/related_merge_requests/store/actions.js b/app/assets/javascripts/related_merge_requests/store/actions.js
index 7baab165820..e9f0793a350 100644
--- a/app/assets/javascripts/related_merge_requests/store/actions.js
+++ b/app/assets/javascripts/related_merge_requests/store/actions.js
@@ -1,7 +1,7 @@
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import * as types from './mutation_types';
const REQUEST_PAGE_COUNT = 100;
diff --git a/app/assets/javascripts/related_merge_requests/store/index.js b/app/assets/javascripts/related_merge_requests/store/index.js
index dcb70c22bcb..925cc36cd76 100644
--- a/app/assets/javascripts/related_merge_requests/store/index.js
+++ b/app/assets/javascripts/related_merge_requests/store/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index 8d1bc44cba0..b16bb76c305 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -1,12 +1,12 @@
<script>
-import { mapState, mapActions, mapGetters } from 'vuex';
import { GlButton, GlFormInput, GlFormGroup, GlSprintf } from '@gitlab/ui';
+import { mapState, mapActions, mapGetters } from 'vuex';
+import { getParameterByName } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
import { BACK_URL_PARAM } from '~/releases/constants';
-import { getParameterByName } from '~/lib/utils/common_utils';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import AssetLinksForm from './asset_links_form.vue';
-import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
import TagField from './tag_field.vue';
export default {
diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue
index 5064b7dd6ad..32183e454c8 100644
--- a/app/assets/javascripts/releases/components/app_index.vue
+++ b/app/assets/javascripts/releases/components/app_index.vue
@@ -1,11 +1,11 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlEmptyState, GlLink, GlButton } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import { getParameterByName } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import ReleaseBlock from './release_block.vue';
-import ReleasesPagination from './releases_pagination.vue';
import ReleaseSkeletonLoader from './release_skeleton_loader.vue';
+import ReleasesPagination from './releases_pagination.vue';
import ReleasesSort from './releases_sort.vue';
export default {
diff --git a/app/assets/javascripts/releases/components/asset_links_form.vue b/app/assets/javascripts/releases/components/asset_links_form.vue
index 331cc8ade6c..9e095c8a9c2 100644
--- a/app/assets/javascripts/releases/components/asset_links_form.vue
+++ b/app/assets/javascripts/releases/components/asset_links_form.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState, mapActions, mapGetters } from 'vuex';
import {
GlSprintf,
GlLink,
@@ -10,8 +9,9 @@ import {
GlFormInput,
GlFormSelect,
} from '@gitlab/ui';
-import { DEFAULT_ASSET_LINK_TYPE, ASSET_LINK_TYPE } from '../constants';
+import { mapState, mapActions, mapGetters } from 'vuex';
import { s__ } from '~/locale';
+import { DEFAULT_ASSET_LINK_TYPE, ASSET_LINK_TYPE } from '../constants';
export default {
name: 'AssetLinksForm',
diff --git a/app/assets/javascripts/releases/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue
index 6e6017637d4..78831ceefe9 100644
--- a/app/assets/javascripts/releases/components/evidence_block.vue
+++ b/app/assets/javascripts/releases/components/evidence_block.vue
@@ -1,9 +1,9 @@
<script>
-import dateFormat from 'dateformat';
import { GlLink, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import { truncateSha } from '~/lib/utils/text_utility';
+import dateFormat from 'dateformat';
import { getTimeago } from '~/lib/utils/datetime_utility';
+import { truncateSha } from '~/lib/utils/text_utility';
+import { __, sprintf } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ExpandButton from '~/vue_shared/components/expand_button.vue';
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index b89e5f2df3f..68bca2fc6b9 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -1,10 +1,10 @@
<script>
/* eslint-disable vue/no-v-html */
-import { isEmpty } from 'lodash';
import $ from 'jquery';
+import { isEmpty } from 'lodash';
+import { scrollToElement } from '~/lib/utils/common_utils';
import { slugify } from '~/lib/utils/text_utility';
import { getLocationHash } from '~/lib/utils/url_utility';
-import { scrollToElement } from '~/lib/utils/common_utils';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import '~/behaviors/markdown/render_gfm';
import EvidenceBlock from './evidence_block.vue';
diff --git a/app/assets/javascripts/releases/components/release_block_assets.vue b/app/assets/javascripts/releases/components/release_block_assets.vue
index 36929f559b5..1761f4360d1 100644
--- a/app/assets/javascripts/releases/components/release_block_assets.vue
+++ b/app/assets/javascripts/releases/components/release_block_assets.vue
@@ -1,8 +1,8 @@
<script>
import { GlTooltipDirective, GlLink, GlButton, GlCollapse, GlIcon, GlBadge } from '@gitlab/ui';
import { difference, get } from 'lodash';
-import { ASSET_LINK_TYPE } from '../constants';
import { __, s__, sprintf } from '~/locale';
+import { ASSET_LINK_TYPE } from '../constants';
export default {
name: 'ReleaseBlockAssets',
diff --git a/app/assets/javascripts/releases/components/release_block_footer.vue b/app/assets/javascripts/releases/components/release_block_footer.vue
index 3beec466c54..cb795b3cba7 100644
--- a/app/assets/javascripts/releases/components/release_block_footer.vue
+++ b/app/assets/javascripts/releases/components/release_block_footer.vue
@@ -1,8 +1,8 @@
<script>
import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { __, sprintf } from '~/locale';
export default {
name: 'ReleaseBlockFooter',
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index 87538244f1a..356fc0f3bf3 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -1,7 +1,7 @@
<script>
-import { GlTooltipDirective, GlLink, GlBadge, GlButton } from '@gitlab/ui';
-import { BACK_URL_PARAM } from '~/releases/constants';
+import { GlTooltipDirective, GlLink, GlBadge, GlButton, GlIcon } from '@gitlab/ui';
import { setUrlParams } from '~/lib/utils/url_utility';
+import { BACK_URL_PARAM } from '~/releases/constants';
export default {
name: 'ReleaseBlockHeader',
@@ -9,6 +9,7 @@ export default {
GlLink,
GlBadge,
GlButton,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -44,7 +45,19 @@ export default {
<gl-link v-if="selfLink" :href="selfLink" class="font-size-inherit">
{{ release.name }}
</gl-link>
- <template v-else>{{ release.name }}</template>
+ <template v-else>
+ {{ release.name }}
+ <gl-icon
+ v-gl-tooltip
+ name="lock"
+ :title="
+ __(
+ 'Private - Guest users are not allowed to view detailed release information like title and source code.',
+ )
+ "
+ class="text-secondary gl-mb-2"
+ />
+ </template>
<gl-badge v-if="release.upcomingRelease" variant="warning" class="align-middle">{{
__('Upcoming Release')
}}</gl-badge>
diff --git a/app/assets/javascripts/releases/components/releases_pagination_graphql.vue b/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
index cb6f1fa18a1..7d024c47fb9 100644
--- a/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
+++ b/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlKeysetPagination } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
export default {
diff --git a/app/assets/javascripts/releases/components/releases_pagination_rest.vue b/app/assets/javascripts/releases/components/releases_pagination_rest.vue
index 334458a2302..24abb0f4498 100644
--- a/app/assets/javascripts/releases/components/releases_pagination_rest.vue
+++ b/app/assets/javascripts/releases/components/releases_pagination_rest.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapState } from 'vuex';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
export default {
name: 'ReleasesPaginationRest',
diff --git a/app/assets/javascripts/releases/components/tag_field_existing.vue b/app/assets/javascripts/releases/components/tag_field_existing.vue
index 046885fe2f6..3345bbecf6e 100644
--- a/app/assets/javascripts/releases/components/tag_field_existing.vue
+++ b/app/assets/javascripts/releases/components/tag_field_existing.vue
@@ -1,7 +1,7 @@
<script>
-import { mapState } from 'vuex';
-import { uniqueId } from 'lodash';
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { mapState } from 'vuex';
import FormFieldContainer from './form_field_container.vue';
export default {
diff --git a/app/assets/javascripts/releases/components/tag_field_new.vue b/app/assets/javascripts/releases/components/tag_field_new.vue
index 4779feae886..660fd7ac950 100644
--- a/app/assets/javascripts/releases/components/tag_field_new.vue
+++ b/app/assets/javascripts/releases/components/tag_field_new.vue
@@ -1,7 +1,7 @@
<script>
-import { mapState, mapActions, mapGetters } from 'vuex';
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
import { uniqueId } from 'lodash';
+import { mapState, mapActions, mapGetters } from 'vuex';
import { __ } from '~/locale';
import RefSelector from '~/ref/components/ref_selector.vue';
import FormFieldContainer from './form_field_container.vue';
diff --git a/app/assets/javascripts/releases/stores/modules/detail/actions.js b/app/assets/javascripts/releases/stores/modules/detail/actions.js
index 127646826a6..5fa002706c6 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/actions.js
@@ -1,15 +1,15 @@
-import * as types from './mutation_types';
import api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+import oneReleaseQuery from '~/releases/queries/one_release.query.graphql';
import {
releaseToApiJson,
apiJsonToRelease,
gqClient,
convertOneReleaseGraphQLResponse,
} from '~/releases/util';
-import oneReleaseQuery from '~/releases/queries/one_release.query.graphql';
+import * as types from './mutation_types';
export const initializeRelease = ({ commit, dispatch, getters }) => {
if (getters.isExistingRelease) {
diff --git a/app/assets/javascripts/releases/stores/modules/detail/mutations.js b/app/assets/javascripts/releases/stores/modules/detail/mutations.js
index 8f4bfbc9b86..cf282f9ab2c 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/mutations.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/mutations.js
@@ -1,6 +1,6 @@
import { uniqueId, cloneDeep } from 'lodash';
-import * as types from './mutation_types';
import { DEFAULT_ASSET_LINK_TYPE } from '../../../constants';
+import * as types from './mutation_types';
const findReleaseLink = (release, id) => {
return release.assets.links.find((l) => l.id === id);
diff --git a/app/assets/javascripts/releases/stores/modules/list/actions.js b/app/assets/javascripts/releases/stores/modules/list/actions.js
index 4c4f6e19a93..f1add54626a 100644
--- a/app/assets/javascripts/releases/stores/modules/list/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/list/actions.js
@@ -1,15 +1,15 @@
-import * as types from './mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { __ } from '~/locale';
import api from '~/api';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
normalizeHeaders,
parseIntPagination,
convertObjectPropsToCamelCase,
} from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
import allReleasesQuery from '~/releases/queries/all_releases.query.graphql';
-import { gqClient, convertAllReleasesGraphQLResponse } from '../../../util';
import { PAGE_SIZE } from '../../../constants';
+import { gqClient, convertAllReleasesGraphQLResponse } from '../../../util';
+import * as types from './mutation_types';
/**
* Gets a paginated list of releases from the server
diff --git a/app/assets/javascripts/releases/stores/modules/list/index.js b/app/assets/javascripts/releases/stores/modules/list/index.js
index 244f41b6609..d5ca191153a 100644
--- a/app/assets/javascripts/releases/stores/modules/list/index.js
+++ b/app/assets/javascripts/releases/stores/modules/list/index.js
@@ -1,6 +1,6 @@
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
export default (initialState) => ({
namespaced: true,
diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js
index b24a226cf9c..36c17b5b252 100644
--- a/app/assets/javascripts/releases/util.js
+++ b/app/assets/javascripts/releases/util.js
@@ -1,10 +1,10 @@
import { pick } from 'lodash';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
-import { truncateSha } from '~/lib/utils/text_utility';
import {
convertObjectPropsToCamelCase,
convertObjectPropsToSnakeCase,
} from '~/lib/utils/common_utils';
+import { truncateSha } from '~/lib/utils/text_utility';
/**
* Converts a release object into a JSON object that can sent to the public
diff --git a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
index 6f8ddd01df8..c272e3b1dc4 100644
--- a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
+++ b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
@@ -1,8 +1,8 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import { componentNames } from '~/reports/components/issue_body';
-import ReportSection from '~/reports/components/report_section.vue';
import IssuesList from '~/reports/components/issues_list.vue';
+import ReportSection from '~/reports/components/report_section.vue';
import createStore from './store';
export default {
diff --git a/app/assets/javascripts/reports/accessibility_report/store/actions.js b/app/assets/javascripts/reports/accessibility_report/store/actions.js
index bb502020a06..e0142a35291 100644
--- a/app/assets/javascripts/reports/accessibility_report/store/actions.js
+++ b/app/assets/javascripts/reports/accessibility_report/store/actions.js
@@ -1,7 +1,7 @@
import Visibility from 'visibilityjs';
-import Poll from '~/lib/utils/poll';
-import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
+import Poll from '~/lib/utils/poll';
import * as types from './mutation_types';
let eTagPoll;
diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js
index 8f8eec11c7f..20506b1bfd1 100644
--- a/app/assets/javascripts/reports/accessibility_report/store/getters.js
+++ b/app/assets/javascripts/reports/accessibility_report/store/getters.js
@@ -1,5 +1,5 @@
-import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants';
import { s__, n__ } from '~/locale';
+import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants';
export const groupedSummaryText = (state) => {
if (state.isLoading) {
diff --git a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
index d0a5615bb57..e5980f1e539 100644
--- a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
+++ b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue
@@ -4,9 +4,9 @@
* Fixed: [name] in [link]:[line]
*/
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { s__ } from '~/locale';
import ReportLink from '~/reports/components/report_link.vue';
import { STATUS_SUCCESS } from '~/reports/constants';
-import { s__ } from '~/locale';
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '../constants';
export default {
diff --git a/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue b/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
index 5c8f31d7da0..654508f0736 100644
--- a/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
+++ b/app/assets/javascripts/reports/codequality_report/grouped_codequality_reports_app.vue
@@ -1,8 +1,9 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
-import { componentNames } from '~/reports/components/issue_body';
import { s__, sprintf } from '~/locale';
+import { componentNames } from '~/reports/components/issue_body';
import ReportSection from '~/reports/components/report_section.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import createStore from './store';
export default {
@@ -11,6 +12,7 @@ export default {
components: {
ReportSection,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
headPath: {
type: String,
@@ -30,6 +32,11 @@ export default {
required: false,
default: null,
},
+ codequalityReportsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
codequalityHelpPath: {
type: String,
required: true,
@@ -37,7 +44,7 @@ export default {
},
componentNames,
computed: {
- ...mapState(['newIssues', 'resolvedIssues']),
+ ...mapState(['newIssues', 'resolvedIssues', 'hasError', 'statusReason']),
...mapGetters([
'hasCodequalityIssues',
'codequalityStatus',
@@ -51,10 +58,11 @@ export default {
headPath: this.headPath,
baseBlobPath: this.baseBlobPath,
headBlobPath: this.headBlobPath,
+ reportsPath: this.codequalityReportsPath,
helpPath: this.codequalityHelpPath,
});
- this.fetchReports();
+ this.fetchReports(this.glFeatures.codequalityBackendComparison);
},
methods: {
...mapActions(['fetchReports', 'setPaths']),
@@ -80,5 +88,7 @@ export default {
:popover-options="codequalityPopover"
:show-report-section-status-icon="false"
class="js-codequality-widget mr-widget-border-top mr-report"
- />
+ >
+ <template v-if="hasError" #sub-heading>{{ statusReason }}</template>
+ </report-section>
</template>
diff --git a/app/assets/javascripts/reports/codequality_report/store/actions.js b/app/assets/javascripts/reports/codequality_report/store/actions.js
index e5fb5caca2e..ddd1747899f 100644
--- a/app/assets/javascripts/reports/codequality_report/store/actions.js
+++ b/app/assets/javascripts/reports/codequality_report/store/actions.js
@@ -4,9 +4,20 @@ import { parseCodeclimateMetrics, doCodeClimateComparison } from './utils/codequ
export const setPaths = ({ commit }, paths) => commit(types.SET_PATHS, paths);
-export const fetchReports = ({ state, dispatch, commit }) => {
+export const fetchReports = ({ state, dispatch, commit }, diffFeatureFlagEnabled) => {
commit(types.REQUEST_REPORTS);
+ if (diffFeatureFlagEnabled) {
+ return axios
+ .get(state.reportsPath)
+ .then(({ data }) => {
+ return dispatch('receiveReportsSuccess', {
+ newIssues: parseCodeclimateMetrics(data.new_errors, state.headBlobPath),
+ resolvedIssues: parseCodeclimateMetrics(data.resolved_errors, state.baseBlobPath),
+ });
+ })
+ .catch((error) => dispatch('receiveReportsError', error));
+ }
if (!state.basePath) {
return dispatch('receiveReportsError');
}
@@ -18,13 +29,13 @@ export const fetchReports = ({ state, dispatch, commit }) => {
),
)
.then((data) => dispatch('receiveReportsSuccess', data))
- .catch(() => dispatch('receiveReportsError'));
+ .catch((error) => dispatch('receiveReportsError', error));
};
export const receiveReportsSuccess = ({ commit }, data) => {
commit(types.RECEIVE_REPORTS_SUCCESS, data);
};
-export const receiveReportsError = ({ commit }) => {
- commit(types.RECEIVE_REPORTS_ERROR);
+export const receiveReportsError = ({ commit }, error) => {
+ commit(types.RECEIVE_REPORTS_ERROR, error);
};
diff --git a/app/assets/javascripts/reports/codequality_report/store/getters.js b/app/assets/javascripts/reports/codequality_report/store/getters.js
index e017bab976c..c6935291af2 100644
--- a/app/assets/javascripts/reports/codequality_report/store/getters.js
+++ b/app/assets/javascripts/reports/codequality_report/store/getters.js
@@ -1,6 +1,6 @@
-import { LOADING, ERROR, SUCCESS } from '../../constants';
-import { sprintf, __, s__, n__ } from '~/locale';
import { spriteIcon } from '~/lib/utils/common_utils';
+import { sprintf, __, s__, n__ } from '~/locale';
+import { LOADING, ERROR, SUCCESS } from '../../constants';
export const hasCodequalityIssues = (state) =>
Boolean(state.newIssues?.length || state.resolvedIssues?.length);
diff --git a/app/assets/javascripts/reports/codequality_report/store/mutations.js b/app/assets/javascripts/reports/codequality_report/store/mutations.js
index 7ef4f3ce2db..095e6637966 100644
--- a/app/assets/javascripts/reports/codequality_report/store/mutations.js
+++ b/app/assets/javascripts/reports/codequality_report/store/mutations.js
@@ -6,6 +6,7 @@ export default {
state.headPath = paths.headPath;
state.baseBlobPath = paths.baseBlobPath;
state.headBlobPath = paths.headBlobPath;
+ state.reportsPath = paths.reportsPath;
state.helpPath = paths.helpPath;
},
[types.REQUEST_REPORTS](state) {
@@ -13,12 +14,14 @@ export default {
},
[types.RECEIVE_REPORTS_SUCCESS](state, data) {
state.hasError = false;
+ state.statusReason = '';
state.isLoading = false;
state.newIssues = data.newIssues;
state.resolvedIssues = data.resolvedIssues;
},
- [types.RECEIVE_REPORTS_ERROR](state) {
+ [types.RECEIVE_REPORTS_ERROR](state, error) {
state.isLoading = false;
state.hasError = true;
+ state.statusReason = error?.response?.data?.status_reason;
},
};
diff --git a/app/assets/javascripts/reports/codequality_report/store/state.js b/app/assets/javascripts/reports/codequality_report/store/state.js
index 38ab53b432e..b39ff4f9d66 100644
--- a/app/assets/javascripts/reports/codequality_report/store/state.js
+++ b/app/assets/javascripts/reports/codequality_report/store/state.js
@@ -1,12 +1,14 @@
export default () => ({
basePath: null,
headPath: null,
+ reportsPath: null,
baseBlobPath: null,
headBlobPath: null,
isLoading: false,
hasError: false,
+ statusReason: '',
newIssues: [],
resolvedIssues: [],
diff --git a/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js b/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js
index fd775f52f7d..b252c8c9817 100644
--- a/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js
+++ b/app/assets/javascripts/reports/codequality_report/store/utils/codequality_comparison.js
@@ -3,8 +3,10 @@ import CodeQualityComparisonWorker from '../../workers/codequality_comparison_wo
export const parseCodeclimateMetrics = (issues = [], path = '') => {
return issues.map((issue) => {
const parsedIssue = {
- ...issue,
name: issue.description,
+ path: issue.file_path,
+ urlPath: `${path}/${issue.file_path}#L${issue.line}`,
+ ...issue,
};
if (issue?.location?.path) {
diff --git a/app/assets/javascripts/reports/components/grouped_issues_list.vue b/app/assets/javascripts/reports/components/grouped_issues_list.vue
index 1826fbaddac..4d3c5f48e94 100644
--- a/app/assets/javascripts/reports/components/grouped_issues_list.vue
+++ b/app/assets/javascripts/reports/components/grouped_issues_list.vue
@@ -1,7 +1,7 @@
<script>
import { s__ } from '~/locale';
-import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
import ReportItem from '~/reports/components/report_item.vue';
+import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
export default {
components: {
diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
index bf1868d427e..033b8798473 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -1,21 +1,21 @@
<script>
-import { mapActions, mapGetters, mapState } from 'vuex';
-import { once } from 'lodash';
import { GlButton } from '@gitlab/ui';
+import { once } from 'lodash';
+import { mapActions, mapGetters, mapState } from 'vuex';
import { sprintf, s__ } from '~/locale';
-import { componentNames } from './issue_body';
-import ReportSection from './report_section.vue';
-import SummaryRow from './summary_row.vue';
-import IssuesList from './issues_list.vue';
-import Modal from './modal.vue';
-import createStore from '../store';
import Tracking from '~/tracking';
+import createStore from '../store';
import {
summaryTextBuilder,
reportTextBuilder,
statusIcon,
recentFailuresTextBuilder,
} from '../store/utils';
+import { componentNames } from './issue_body';
+import IssuesList from './issues_list.vue';
+import Modal from './modal.vue';
+import ReportSection from './report_section.vue';
+import SummaryRow from './summary_row.vue';
export default {
name: 'GroupedTestReportsApp',
diff --git a/app/assets/javascripts/reports/components/issue_body.js b/app/assets/javascripts/reports/components/issue_body.js
index 1e6dc4f8b78..a0349506b69 100644
--- a/app/assets/javascripts/reports/components/issue_body.js
+++ b/app/assets/javascripts/reports/components/issue_body.js
@@ -1,6 +1,6 @@
-import TestIssueBody from './test_issue_body.vue';
import AccessibilityIssueBody from '../accessibility_report/components/accessibility_issue_body.vue';
import CodequalityIssueBody from '../codequality_report/components/codequality_issue_body.vue';
+import TestIssueBody from './test_issue_body.vue';
export const components = {
AccessibilityIssueBody,
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index 0e9975ea81f..9d0631fbc01 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -2,8 +2,8 @@
import { __ } from '~/locale';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import Popover from '~/vue_shared/components/help_popover.vue';
-import IssuesList from './issues_list.vue';
import { status, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '../constants';
+import IssuesList from './issues_list.vue';
export default {
name: 'ReportSection',
diff --git a/app/assets/javascripts/reports/components/test_issue_body.vue b/app/assets/javascripts/reports/components/test_issue_body.vue
index ad980b334bb..7508e1d1f0d 100644
--- a/app/assets/javascripts/reports/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/components/test_issue_body.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions } from 'vuex';
import { GlBadge, GlSprintf } from '@gitlab/ui';
+import { mapActions } from 'vuex';
export default {
name: 'TestIssueBody',
diff --git a/app/assets/javascripts/reports/store/actions.js b/app/assets/javascripts/reports/store/actions.js
index 301fdce7989..c9b8ee64930 100644
--- a/app/assets/javascripts/reports/store/actions.js
+++ b/app/assets/javascripts/reports/store/actions.js
@@ -1,8 +1,8 @@
import Visibility from 'visibilityjs';
import axios from '../../lib/utils/axios_utils';
+import httpStatusCodes from '../../lib/utils/http_status';
import Poll from '../../lib/utils/poll';
import * as types from './mutation_types';
-import httpStatusCodes from '../../lib/utils/http_status';
export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint);
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index c9862572b16..28d7dec85f4 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -10,8 +10,8 @@ import permissionsQuery from 'shared_queries/repository/permissions.query.graphq
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '../../locale';
import getRefMixin from '../mixins/get_ref';
-import projectShortPathQuery from '../queries/project_short_path.query.graphql';
import projectPathQuery from '../queries/project_path.query.graphql';
+import projectShortPathQuery from '../queries/project_short_path.query.graphql';
const ROW_TYPES = {
header: 'header',
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 0241c803514..a7176853819 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -4,10 +4,10 @@ import { GlTooltipDirective, GlLink, GlButton, GlButtonGroup, GlLoadingIcon } fr
import defaultAvatarUrl from 'images/no_avatar.png';
import pathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql';
import { sprintf, s__ } from '~/locale';
-import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
+import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue
index e2c3f3b81ee..b74c2333148 100644
--- a/app/assets/javascripts/repository/components/preview/index.vue
+++ b/app/assets/javascripts/repository/components/preview/index.vue
@@ -1,8 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
-import { GlIcon, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { handleLocationHash } from '~/lib/utils/common_utils';
import readmeQuery from '../../queries/readme.query.graphql';
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
index c6652c57c1f..22dffb7d2db 100644
--- a/app/assets/javascripts/repository/components/table/index.vue
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -4,8 +4,8 @@ import { sprintf, __ } from '../../../locale';
import getRefMixin from '../../mixins/get_ref';
import projectPathQuery from '../../queries/project_path.query.graphql';
import TableHeader from './header.vue';
-import TableRow from './row.vue';
import ParentRow from './parent_row.vue';
+import TableRow from './row.vue';
export default {
components: {
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index d749a8c0dee..70918dd55e4 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -1,6 +1,5 @@
<script>
/* eslint-disable vue/no-v-html */
-import { escapeRegExp } from 'lodash';
import {
GlBadge,
GlLink,
@@ -9,9 +8,10 @@ import {
GlLoadingIcon,
GlIcon,
} from '@gitlab/ui';
+import { escapeRegExp } from 'lodash';
import { escapeFileUrl } from '~/lib/utils/url_utility';
-import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import getRefMixin from '../../mixins/get_ref';
import commitQuery from '../../queries/commit.query.graphql';
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 7fe6863d006..336237abd8a 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -2,11 +2,11 @@
import filesQuery from 'shared_queries/repository/files.query.graphql';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '../../locale';
-import FileTable from './table/index.vue';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
-import FilePreview from './preview/index.vue';
import { readmeFile } from '../utils/readme';
+import FilePreview from './preview/index.vue';
+import FileTable from './table/index.vue';
const LIMIT = 1000;
const PAGE_SIZE = 100;
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
index dbe129859bc..4a4b9d115b7 100644
--- a/app/assets/javascripts/repository/graphql.js
+++ b/app/assets/javascripts/repository/graphql.js
@@ -1,8 +1,8 @@
+import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
-import axios from '~/lib/utils/axios_utils';
import createDefaultClient from '~/lib/graphql';
+import axios from '~/lib/utils/axios_utils';
import introspectionQueryResultData from './fragmentTypes.json';
import { fetchLogsTree } from './log_tree';
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index f56b141fe5c..747b85f5c1c 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,17 +1,17 @@
import Vue from 'vue';
+import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
+import { parseBoolean } from '../lib/utils/common_utils';
import { escapeFileUrl } from '../lib/utils/url_utility';
-import createRouter from './router';
+import { __ } from '../locale';
import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue';
+import DirectoryDownloadLinks from './components/directory_download_links.vue';
import LastCommit from './components/last_commit.vue';
import TreeActionLink from './components/tree_action_link.vue';
-import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
-import DirectoryDownloadLinks from './components/directory_download_links.vue';
import apolloProvider from './graphql';
-import { setTitle } from './utils/title';
+import createRouter from './router';
import { updateFormAction } from './utils/dom';
-import { parseBoolean } from '../lib/utils/common_utils';
-import { __ } from '../locale';
+import { setTitle } from './utils/title';
export default function setupVueRepositoryList() {
const el = document.getElementById('js-tree-list');
diff --git a/app/assets/javascripts/repository/mixins/preload.js b/app/assets/javascripts/repository/mixins/preload.js
index c1607866941..ffc260ec84f 100644
--- a/app/assets/javascripts/repository/mixins/preload.js
+++ b/app/assets/javascripts/repository/mixins/preload.js
@@ -1,6 +1,6 @@
import filesQuery from 'shared_queries/repository/files.query.graphql';
-import getRefMixin from './get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
+import getRefMixin from './get_ref';
export default {
mixins: [getRefMixin],
diff --git a/app/assets/javascripts/repository/pages/index.vue b/app/assets/javascripts/repository/pages/index.vue
index 29786bf4ec8..0e53235779c 100644
--- a/app/assets/javascripts/repository/pages/index.vue
+++ b/app/assets/javascripts/repository/pages/index.vue
@@ -1,6 +1,6 @@
<script>
-import TreePage from './tree.vue';
import { updateElementsVisibility } from '../utils/dom';
+import TreePage from './tree.vue';
export default {
components: {
diff --git a/app/assets/javascripts/repository/pages/tree.vue b/app/assets/javascripts/repository/pages/tree.vue
index adc332fa370..cbdc62624d4 100644
--- a/app/assets/javascripts/repository/pages/tree.vue
+++ b/app/assets/javascripts/repository/pages/tree.vue
@@ -1,7 +1,7 @@
<script>
import TreeContent from '../components/tree_content.vue';
-import { updateElementsVisibility } from '../utils/dom';
import preloadMixin from '../mixins/preload';
+import { updateElementsVisibility } from '../utils/dom';
export default {
components: {
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
index e2924454239..ad6e32d7055 100644
--- a/app/assets/javascripts/repository/router.js
+++ b/app/assets/javascripts/repository/router.js
@@ -1,6 +1,6 @@
+import { escapeRegExp } from 'lodash';
import Vue from 'vue';
import VueRouter from 'vue-router';
-import { escapeRegExp } from 'lodash';
import { joinPaths } from '../lib/utils/url_utility';
import IndexPage from './pages/index.vue';
import TreePage from './pages/tree.vue';
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index b9bc799fb0b..52ff4e7b100 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -2,10 +2,10 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
+import { fixTitle, hide } from '~/tooltips';
import { deprecatedCreateFlash as flash } from './flash';
import axios from './lib/utils/axios_utils';
import { sprintf, s__, __ } from './locale';
-import { fixTitle, hide } from '~/tooltips';
function Sidebar() {
this.toggleTodo = this.toggleTodo.bind(this);
@@ -123,7 +123,7 @@ Sidebar.prototype.todoUpdateDone = function (data) {
.data('deletePath', deletePath);
if ($el.hasClass('has-tooltip')) {
- fixTitle($el);
+ fixTitle(el);
}
if (typeof $el.data('isCollapsed') !== 'undefined') {
diff --git a/app/assets/javascripts/search/highlight_blob_search_result.js b/app/assets/javascripts/search/highlight_blob_search_result.js
index 3c3ac3582d0..c553d5b14a0 100644
--- a/app/assets/javascripts/search/highlight_blob_search_result.js
+++ b/app/assets/javascripts/search/highlight_blob_search_result.js
@@ -1,7 +1,7 @@
-export default () => {
+export default (search = '') => {
const highlightLineClass = 'hll';
const contentBody = document.getElementById('content-body');
- const searchTerm = contentBody.querySelector('.js-search-input').value.toLowerCase();
+ const searchTerm = search.toLowerCase();
const blobs = contentBody.querySelectorAll('.blob-result');
blobs.forEach((blob) => {
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index d2bb1ccfc44..10c41315972 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -1,14 +1,25 @@
+import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
import { queryToObject } from '~/lib/utils/url_utility';
+import Project from '~/pages/projects/project';
+import refreshCounts from '~/pages/search/show/refresh_counts';
+import { initSidebar } from './sidebar';
+import { initSearchSort } from './sort';
import createStore from './store';
import { initTopbar } from './topbar';
-import { initSidebar } from './sidebar';
export const initSearchApp = () => {
// Similar to url_utility.decodeUrlParameter
// Our query treats + as %20. This replaces the query + symbols with %20.
const sanitizedSearch = window.location.search.replace(/\+/g, '%20');
- const store = createStore({ query: queryToObject(sanitizedSearch) });
+ const query = queryToObject(sanitizedSearch);
+
+ const store = createStore({ query });
initTopbar(store);
initSidebar(store);
+ initSearchSort(store);
+
+ setHighlightClass(query.search); // Code Highlighting
+ refreshCounts(); // Other Scope Tab Counts
+ Project.initRefSwitcher(); // Code Search Branch Picker
};
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index e233d18b716..4640259314b 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -1,8 +1,8 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlButton, GlLink } from '@gitlab/ui';
-import StatusFilter from './status_filter.vue';
+import { mapActions, mapState } from 'vuex';
import ConfidentialityFilter from './confidentiality_filter.vue';
+import StatusFilter from './status_filter.vue';
export default {
name: 'GlobalSearchSidebar',
diff --git a/app/assets/javascripts/search/sidebar/components/radio_filter.vue b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
index b27c4e26fb5..73911b9d319 100644
--- a/app/assets/javascripts/search/sidebar/components/radio_filter.vue
+++ b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
import { sprintf, s__ } from '~/locale';
export default {
diff --git a/app/assets/javascripts/search/sort/components/app.vue b/app/assets/javascripts/search/sort/components/app.vue
new file mode 100644
index 00000000000..e4eba655e39
--- /dev/null
+++ b/app/assets/javascripts/search/sort/components/app.vue
@@ -0,0 +1,103 @@
+<script>
+import {
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { SORT_DIRECTION_UI } from '../constants';
+
+export default {
+ name: 'GlobalSearchSort',
+ components: {
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ searchSortOptions: {
+ type: Array,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['query']),
+ selectedSortOption: {
+ get() {
+ const { sort } = this.query;
+
+ if (!sort) {
+ return this.searchSortOptions[0];
+ }
+
+ const sortOption = this.searchSortOptions.find((option) => {
+ if (!option.sortable) {
+ return option.sortParam === sort;
+ }
+
+ return Object.values(option.sortParam).indexOf(sort) !== -1;
+ });
+
+ // Handle invalid sort param
+ return sortOption || this.searchSortOptions[0];
+ },
+ set(value) {
+ this.setQuery({ key: 'sort', value });
+ this.applyQuery();
+ },
+ },
+ sortDirectionData() {
+ if (!this.selectedSortOption.sortable) {
+ return SORT_DIRECTION_UI.disabled;
+ }
+
+ return this.query?.sort?.includes('asc') ? SORT_DIRECTION_UI.asc : SORT_DIRECTION_UI.desc;
+ },
+ },
+ methods: {
+ ...mapActions(['applyQuery', 'setQuery']),
+ handleSortChange(option) {
+ if (!option.sortable) {
+ this.selectedSortOption = option.sortParam;
+ } else {
+ // Default new sort options to desc
+ this.selectedSortOption = option.sortParam.desc;
+ }
+ },
+ handleSortDirectionChange() {
+ this.selectedSortOption =
+ this.sortDirectionData.direction === 'desc'
+ ? this.selectedSortOption.sortParam.asc
+ : this.selectedSortOption.sortParam.desc;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button-group>
+ <gl-dropdown :text="selectedSortOption.title" :right="true" class="w-100">
+ <gl-dropdown-item
+ v-for="sortOption in searchSortOptions"
+ :key="sortOption.title"
+ is-check-item
+ :is-checked="sortOption.title === selectedSortOption.title"
+ @click="handleSortChange(sortOption)"
+ >{{ sortOption.title }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ <gl-button
+ v-gl-tooltip
+ :disabled="!selectedSortOption.sortable"
+ :title="sortDirectionData.tooltip"
+ :icon="sortDirectionData.icon"
+ @click="handleSortDirectionChange"
+ />
+ </gl-button-group>
+</template>
diff --git a/app/assets/javascripts/search/sort/constants.js b/app/assets/javascripts/search/sort/constants.js
new file mode 100644
index 00000000000..575fba5873b
--- /dev/null
+++ b/app/assets/javascripts/search/sort/constants.js
@@ -0,0 +1,19 @@
+import { __ } from '~/locale';
+
+export const SORT_DIRECTION_UI = {
+ disabled: {
+ direction: null,
+ tooltip: '',
+ icon: 'sort-highest',
+ },
+ desc: {
+ direction: 'desc',
+ tooltip: __('Sort direction: Descending'),
+ icon: 'sort-highest',
+ },
+ asc: {
+ direction: 'asc',
+ tooltip: __('Sort direction: Ascending'),
+ icon: 'sort-lowest',
+ },
+};
diff --git a/app/assets/javascripts/search/sort/index.js b/app/assets/javascripts/search/sort/index.js
new file mode 100644
index 00000000000..84bb5175b1d
--- /dev/null
+++ b/app/assets/javascripts/search/sort/index.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import GlobalSearchSort from './components/app.vue';
+
+Vue.use(Translate);
+
+export const initSearchSort = (store) => {
+ const el = document.getElementById('js-search-sort');
+
+ if (!el) return false;
+
+ let { searchSortOptions } = el.dataset;
+
+ searchSortOptions = JSON.parse(searchSortOptions);
+
+ return new Vue({
+ el,
+ store,
+ render(createElement) {
+ return createElement(GlobalSearchSort, {
+ props: {
+ searchSortOptions,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
index bdfe966d990..0af679644f3 100644
--- a/app/assets/javascripts/search/store/actions.js
+++ b/app/assets/javascripts/search/store/actions.js
@@ -1,7 +1,7 @@
import Api from '~/api';
import createFlash from '~/flash';
-import { __ } from '~/locale';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import * as types from './mutation_types';
export const fetchGroups = ({ commit }, search) => {
diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue
new file mode 100644
index 00000000000..987735ed811
--- /dev/null
+++ b/app/assets/javascripts/search/topbar/components/app.vue
@@ -0,0 +1,73 @@
+<script>
+import { GlForm, GlSearchBoxByType, GlButton } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import GroupFilter from './group_filter.vue';
+import ProjectFilter from './project_filter.vue';
+
+export default {
+ name: 'GlobalSearchTopbar',
+ components: {
+ GlForm,
+ GlSearchBoxByType,
+ GroupFilter,
+ ProjectFilter,
+ GlButton,
+ },
+ props: {
+ groupInitialData: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ projectInitialData: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ computed: {
+ ...mapState(['query']),
+ search: {
+ get() {
+ return this.query ? this.query.search : '';
+ },
+ set(value) {
+ this.setQuery({ key: 'search', value });
+ },
+ },
+ showFilters() {
+ return !this.query.snippets || this.query.snippets === 'false';
+ },
+ },
+ methods: {
+ ...mapActions(['applyQuery', 'setQuery']),
+ },
+};
+</script>
+
+<template>
+ <gl-form class="search-page-form" @submit.prevent="applyQuery">
+ <section class="gl-lg-display-flex gl-align-items-flex-end">
+ <div class="gl-flex-fill-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2">
+ <label>{{ __('What are you searching for?') }}</label>
+ <gl-search-box-by-type
+ id="dashboard_search"
+ v-model="search"
+ name="search"
+ :placeholder="__(`Search for projects, issues, etc.`)"
+ />
+ </div>
+ <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-2">
+ <label class="gl-display-block">{{ __('Group') }}</label>
+ <group-filter :initial-data="groupInitialData" />
+ </div>
+ <div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-2">
+ <label class="gl-display-block">{{ __('Project') }}</label>
+ <project-filter :initial-data="projectInitialData" />
+ </div>
+ <gl-button class="btn-search gl-lg-ml-2" variant="success" type="submit">{{
+ __('Search')
+ }}</gl-button>
+ </section>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/search/topbar/components/group_filter.vue b/app/assets/javascripts/search/topbar/components/group_filter.vue
index fce9ec17d23..2acab4e805d 100644
--- a/app/assets/javascripts/search/topbar/components/group_filter.vue
+++ b/app/assets/javascripts/search/topbar/components/group_filter.vue
@@ -1,9 +1,9 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { isEmpty } from 'lodash';
+import { mapState, mapActions } from 'vuex';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
-import SearchableDropdown from './searchable_dropdown.vue';
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
+import SearchableDropdown from './searchable_dropdown.vue';
export default {
name: 'GroupFilter',
@@ -37,6 +37,7 @@ export default {
<template>
<searchable-dropdown
+ data-testid="group-filter"
:header-text="$options.GROUP_DATA.headerText"
:selected-display-value="$options.GROUP_DATA.selectedDisplayValue"
:items-display-value="$options.GROUP_DATA.itemsDisplayValue"
diff --git a/app/assets/javascripts/search/topbar/components/project_filter.vue b/app/assets/javascripts/search/topbar/components/project_filter.vue
index 3f1f3848ac7..b2dd79fcfa3 100644
--- a/app/assets/javascripts/search/topbar/components/project_filter.vue
+++ b/app/assets/javascripts/search/topbar/components/project_filter.vue
@@ -1,8 +1,8 @@
<script>
import { mapState, mapActions } from 'vuex';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
-import SearchableDropdown from './searchable_dropdown.vue';
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
+import SearchableDropdown from './searchable_dropdown.vue';
export default {
name: 'ProjectFilter',
@@ -27,7 +27,7 @@ export default {
handleProjectChange(project) {
// This determines if we need to update the group filter or not
const queryParams = {
- ...(project.namespace_id && { [GROUP_DATA.queryParam]: project.namespace_id }),
+ ...(project.namespace?.id && { [GROUP_DATA.queryParam]: project.namespace.id }),
[PROJECT_DATA.queryParam]: project.id,
};
@@ -40,6 +40,7 @@ export default {
<template>
<searchable-dropdown
+ data-testid="project-filter"
:header-text="$options.PROJECT_DATA.headerText"
:selected-display-value="$options.PROJECT_DATA.selectedDisplayValue"
:items-display-value="$options.PROJECT_DATA.itemsDisplayValue"
diff --git a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue b/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
index 14577fd7d7a..5fb7217db74 100644
--- a/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
+++ b/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue
@@ -101,7 +101,7 @@ export default {
@keydown.enter.stop="resetDropdown"
@click.stop="resetDropdown"
>
- <gl-icon name="clear" class="gl-text-gray-200! gl-hover-text-blue-800!" />
+ <gl-icon name="clear" />
</gl-button>
<gl-icon name="chevron-down" />
</template>
diff --git a/app/assets/javascripts/search/topbar/index.js b/app/assets/javascripts/search/topbar/index.js
index f0308109b32..87316e10e8d 100644
--- a/app/assets/javascripts/search/topbar/index.js
+++ b/app/assets/javascripts/search/topbar/index.js
@@ -1,44 +1,31 @@
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
-import GroupFilter from './components/group_filter.vue';
-import ProjectFilter from './components/project_filter.vue';
+import GlobalSearchTopbar from './components/app.vue';
Vue.use(Translate);
-const mountSearchableDropdown = (store, { id, component }) => {
- const el = document.getElementById(id);
+export const initTopbar = (store) => {
+ const el = document.getElementById('js-search-topbar');
if (!el) {
return false;
}
- let { initialData } = el.dataset;
+ let { groupInitialData, projectInitialData } = el.dataset;
- initialData = JSON.parse(initialData);
+ groupInitialData = JSON.parse(groupInitialData);
+ projectInitialData = JSON.parse(projectInitialData);
return new Vue({
el,
store,
render(createElement) {
- return createElement(component, {
+ return createElement(GlobalSearchTopbar, {
props: {
- initialData,
+ groupInitialData,
+ projectInitialData,
},
});
},
});
};
-
-const searchableDropdowns = [
- {
- id: 'js-search-group-dropdown',
- component: GroupFilter,
- },
- {
- id: 'js-search-project-dropdown',
- component: ProjectFilter,
- },
-];
-
-export const initTopbar = (store) =>
- searchableDropdowns.map((dropdown) => mountSearchableDropdown(store, dropdown));
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index b8a5836e2d4..9c133a79607 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -2,8 +2,10 @@
import $ from 'jquery';
import { escape, throttle } from 'lodash';
-import { s__, __, sprintf } from '~/locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { getIdenticonBackgroundClass, getIdenticonTitle } from '~/helpers/avatar_helper';
+import { s__, __, sprintf } from '~/locale';
+import Tracking from '~/tracking';
import axios from './lib/utils/axios_utils';
import {
isInGroupsPage,
@@ -12,8 +14,6 @@ import {
getProjectSlug,
spriteIcon,
} from './lib/utils/common_utils';
-import Tracking from '~/tracking';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
/**
* Search input in top navigation bar.
diff --git a/app/assets/javascripts/search_settings/components/search_settings.vue b/app/assets/javascripts/search_settings/components/search_settings.vue
index 820055dc656..116967a62c8 100644
--- a/app/assets/javascripts/search_settings/components/search_settings.vue
+++ b/app/assets/javascripts/search_settings/components/search_settings.vue
@@ -3,20 +3,37 @@ import { GlSearchBoxByType } from '@gitlab/ui';
import { uniq } from 'lodash';
import { EXCLUDED_NODES, HIDE_CLASS, HIGHLIGHT_CLASS, TYPING_DELAY } from '../constants';
+const origExpansions = new Map();
+
const findSettingsSection = (sectionSelector, node) => {
return node.parentElement.closest(sectionSelector);
};
-const resetSections = ({ sectionSelector, expandSection, collapseSection }) => {
- document.querySelectorAll(sectionSelector).forEach((section, index) => {
- section.classList.remove(HIDE_CLASS);
-
- if (index === 0) {
+const restoreExpansionState = ({ expandSection, collapseSection }) => {
+ origExpansions.forEach((isExpanded, section) => {
+ if (isExpanded) {
expandSection(section);
} else {
collapseSection(section);
}
});
+
+ origExpansions.clear();
+};
+
+const saveExpansionState = (sections, { isExpanded }) => {
+ // If we've saved expansions before, don't override it.
+ if (origExpansions.size > 0) {
+ return;
+ }
+
+ sections.forEach((section) => origExpansions.set(section, isExpanded(section)));
+};
+
+const resetSections = ({ sectionSelector }) => {
+ document.querySelectorAll(sectionSelector).forEach((section) => {
+ section.classList.remove(HIDE_CLASS);
+ });
};
const clearHighlights = () => {
@@ -85,6 +102,12 @@ export default {
type: String,
required: true,
},
+ isExpandedFn: {
+ type: Function,
+ required: false,
+ // default to a function that returns false
+ default: () => () => false,
+ },
},
data() {
return {
@@ -97,6 +120,7 @@ export default {
sectionSelector: this.sectionSelector,
expandSection: this.expandSection,
collapseSection: this.collapseSection,
+ isExpanded: this.isExpandedFn,
};
this.searchTerm = value;
@@ -104,7 +128,11 @@ export default {
clearResults(displayOptions);
if (value.length) {
+ saveExpansionState(document.querySelectorAll(this.sectionSelector), displayOptions);
+
displayResults(displayOptions, search(this.searchRoot, value));
+ } else {
+ restoreExpansionState(displayOptions);
}
},
expandSection(section) {
@@ -118,12 +146,10 @@ export default {
};
</script>
<template>
- <div class="gl-mt-5">
- <gl-search-box-by-type
- :value="searchTerm"
- :debounce="$options.TYPING_DELAY"
- :placeholder="__('Search settings')"
- @input="search"
- />
- </div>
+ <gl-search-box-by-type
+ :value="searchTerm"
+ :debounce="$options.TYPING_DELAY"
+ :placeholder="__('Search settings')"
+ @input="search"
+ />
</template>
diff --git a/app/assets/javascripts/search_settings/index.js b/app/assets/javascripts/search_settings/index.js
index 1fb1a378ffb..676c43c5631 100644
--- a/app/assets/javascripts/search_settings/index.js
+++ b/app/assets/javascripts/search_settings/index.js
@@ -1,23 +1,10 @@
-import Vue from 'vue';
-import $ from 'jquery';
-import { expandSection, closeSection } from '~/settings_panels';
-import SearchSettings from '~/search_settings/components/search_settings.vue';
+const initSearch = async () => {
+ const el = document.querySelector('.js-search-settings-app');
-const initSearch = ({ el }) =>
- new Vue({
- el,
- render: (h) =>
- h(SearchSettings, {
- ref: 'searchSettings',
- props: {
- searchRoot: document.querySelector('#content-body'),
- sectionSelector: 'section.settings',
- },
- on: {
- collapse: (section) => closeSection($(section)),
- expand: (section) => expandSection($(section)),
- },
- }),
- });
+ if (el) {
+ const { default: mount } = await import(/* webpackChunkName: 'search_settings' */ './mount');
+ mount({ el });
+ }
+};
export default initSearch;
diff --git a/app/assets/javascripts/search_settings/mount.js b/app/assets/javascripts/search_settings/mount.js
new file mode 100644
index 00000000000..b1086f9ca1f
--- /dev/null
+++ b/app/assets/javascripts/search_settings/mount.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import SearchSettings from '~/search_settings/components/search_settings.vue';
+import { expandSection, closeSection, isExpanded } from '~/settings_panels';
+
+const mountSearch = ({ el }) =>
+ new Vue({
+ el,
+ render: (h) =>
+ h(SearchSettings, {
+ ref: 'searchSettings',
+ props: {
+ searchRoot: document.querySelector('#content-body'),
+ sectionSelector: '.js-search-settings-section, section.settings',
+ isExpandedFn: isExpanded,
+ },
+ on: {
+ collapse: closeSection,
+ expand: expandSection,
+ },
+ }),
+ });
+
+export default mountSearch;
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
new file mode 100644
index 00000000000..513a7353d28
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -0,0 +1,23 @@
+<script>
+import ConfigurationTable from './configuration_table.vue';
+
+export default {
+ components: {
+ ConfigurationTable,
+ },
+};
+</script>
+
+<template>
+ <article>
+ <header>
+ <h4 class="gl-my-5">
+ {{ __('Security Configuration') }}
+ </h4>
+ <h5 class="gl-font-lg gl-mt-7">
+ {{ s__('SecurityConfiguration|Testing & Compliance') }}
+ </h5>
+ </header>
+ <configuration-table />
+ </article>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/configuration_table.vue b/app/assets/javascripts/security_configuration/components/configuration_table.vue
new file mode 100644
index 00000000000..9475cc1781f
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/configuration_table.vue
@@ -0,0 +1,97 @@
+<script>
+import { GlLink, GlSprintf, GlTable, GlAlert } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+import {
+ REPORT_TYPE_SAST,
+ REPORT_TYPE_DAST,
+ REPORT_TYPE_DEPENDENCY_SCANNING,
+ REPORT_TYPE_CONTAINER_SCANNING,
+ REPORT_TYPE_COVERAGE_FUZZING,
+ REPORT_TYPE_LICENSE_COMPLIANCE,
+} from '~/vue_shared/security_reports/constants';
+import { features } from './features_constants';
+import ManageSast from './manage_sast.vue';
+import Upgrade from './upgrade.vue';
+
+const borderClasses = 'gl-border-b-1! gl-border-b-solid! gl-border-gray-100!';
+const thClass = `gl-text-gray-900 gl-bg-transparent! ${borderClasses}`;
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ GlTable,
+ GlAlert,
+ },
+ data: () => ({
+ features,
+ errorMessage: '',
+ }),
+ methods: {
+ getFeatureDocumentationLinkLabel(item) {
+ return sprintf(s__('SecurityConfiguration|Feature documentation for %{featureName}'), {
+ featureName: item.name,
+ });
+ },
+ onError(value) {
+ this.errorMessage = value;
+ },
+ getComponentForItem(item) {
+ const COMPONENTS = {
+ [REPORT_TYPE_SAST]: ManageSast,
+ [REPORT_TYPE_DAST]: Upgrade,
+ [REPORT_TYPE_DEPENDENCY_SCANNING]: Upgrade,
+ [REPORT_TYPE_CONTAINER_SCANNING]: Upgrade,
+ [REPORT_TYPE_COVERAGE_FUZZING]: Upgrade,
+ [REPORT_TYPE_LICENSE_COMPLIANCE]: Upgrade,
+ };
+
+ return COMPONENTS[item.type];
+ },
+ },
+ table: {
+ fields: [
+ {
+ key: 'feature',
+ label: s__('SecurityConfiguration|Security Control'),
+ thClass,
+ },
+ {
+ key: 'manage',
+ label: s__('SecurityConfiguration|Manage'),
+ thClass,
+ },
+ ],
+ items: features,
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert v-if="errorMessage" variant="danger" :dismissible="false">
+ {{ errorMessage }}
+ </gl-alert>
+ <gl-table :items="$options.table.items" :fields="$options.table.fields" stacked="md">
+ <template #cell(feature)="{ item }">
+ <div class="gl-text-gray-900">
+ {{ item.name }}
+ </div>
+ <div>
+ {{ item.description }}
+ <gl-link
+ target="_blank"
+ :href="item.link"
+ :aria-label="getFeatureDocumentationLinkLabel(item)"
+ >
+ {{ s__('SecurityConfiguration|More information') }}
+ </gl-link>
+ </div>
+ </template>
+
+ <template #cell(manage)="{ item }">
+ <component :is="getComponentForItem(item)" :data-testid="item.type" @error="onError" />
+ </template>
+ </gl-table>
+ </div>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/features_constants.js b/app/assets/javascripts/security_configuration/components/features_constants.js
new file mode 100644
index 00000000000..d846a2761d9
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/features_constants.js
@@ -0,0 +1,112 @@
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__ } from '~/locale';
+
+import {
+ REPORT_TYPE_SAST,
+ REPORT_TYPE_DAST,
+ REPORT_TYPE_SECRET_DETECTION,
+ REPORT_TYPE_DEPENDENCY_SCANNING,
+ REPORT_TYPE_CONTAINER_SCANNING,
+ REPORT_TYPE_COVERAGE_FUZZING,
+ REPORT_TYPE_LICENSE_COMPLIANCE,
+} from '~/vue_shared/security_reports/constants';
+
+/**
+ * Translations & helpPagePaths for Static Security Configuration Page
+ */
+export const SAST_NAME = s__('Static Application Security Testing (SAST)');
+export const SAST_DESCRIPTION = s__('Analyze your source code for known vulnerabilities.');
+export const SAST_HELP_PATH = helpPagePath('user/application_security/sast/index');
+
+export const DAST_NAME = s__('Dynamic Application Security Testing (DAST)');
+export const DAST_DESCRIPTION = s__('Analyze a review version of your web application.');
+export const DAST_HELP_PATH = helpPagePath('user/application_security/dast/index');
+
+export const SECRET_DETECTION_NAME = s__('Secret Detection');
+export const SECRET_DETECTION_DESCRIPTION = s__(
+ 'Analyze your source code and git history for secrets.',
+);
+export const SECRET_DETECTION_HELP_PATH = helpPagePath(
+ 'user/application_security/secret_detection/index',
+);
+
+export const DEPENDENCY_SCANNING_NAME = s__('Dependency Scanning');
+export const DEPENDENCY_SCANNING_DESCRIPTION = s__(
+ 'Analyze your dependencies for known vulnerabilities.',
+);
+export const DEPENDENCY_SCANNING_HELP_PATH = helpPagePath(
+ 'user/application_security/dependency_scanning/index',
+);
+
+export const CONTAINER_SCANNING_NAME = s__('Container Scanning');
+export const CONTAINER_SCANNING_DESCRIPTION = s__(
+ 'Check your Docker images for known vulnerabilities.',
+);
+export const CONTAINER_SCANNING_HELP_PATH = helpPagePath(
+ 'user/application_security/container_scanning/index',
+);
+
+export const COVERAGE_FUZZING_NAME = s__('Coverage Fuzzing');
+export const COVERAGE_FUZZING_DESCRIPTION = s__(
+ 'Find bugs in your code with coverage-guided fuzzing.',
+);
+export const COVERAGE_FUZZING_HELP_PATH = helpPagePath(
+ 'user/application_security/coverage_fuzzing/index',
+);
+
+export const LICENSE_COMPLIANCE_NAME = s__('License Compliance');
+export const LICENSE_COMPLIANCE_DESCRIPTION = s__(
+ 'Search your project dependencies for their licenses and apply policies.',
+);
+export const LICENSE_COMPLIANCE_HELP_PATH = helpPagePath(
+ 'user/compliance/license_compliance/index',
+);
+
+export const UPGRADE_CTA = s__(
+ 'SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}',
+);
+
+export const features = [
+ {
+ name: SAST_NAME,
+ description: SAST_DESCRIPTION,
+ helpPath: SAST_HELP_PATH,
+ type: REPORT_TYPE_SAST,
+ },
+ {
+ name: DAST_NAME,
+ description: DAST_DESCRIPTION,
+ helpPath: DAST_HELP_PATH,
+ type: REPORT_TYPE_DAST,
+ },
+ {
+ name: SECRET_DETECTION_NAME,
+ description: SECRET_DETECTION_DESCRIPTION,
+ helpPath: SECRET_DETECTION_HELP_PATH,
+ type: REPORT_TYPE_SECRET_DETECTION,
+ },
+ {
+ name: DEPENDENCY_SCANNING_NAME,
+ description: DEPENDENCY_SCANNING_DESCRIPTION,
+ helpPath: DEPENDENCY_SCANNING_HELP_PATH,
+ type: REPORT_TYPE_DEPENDENCY_SCANNING,
+ },
+ {
+ name: CONTAINER_SCANNING_NAME,
+ description: CONTAINER_SCANNING_DESCRIPTION,
+ helpPath: CONTAINER_SCANNING_HELP_PATH,
+ type: REPORT_TYPE_CONTAINER_SCANNING,
+ },
+ {
+ name: COVERAGE_FUZZING_NAME,
+ description: COVERAGE_FUZZING_DESCRIPTION,
+ helpPath: COVERAGE_FUZZING_HELP_PATH,
+ type: REPORT_TYPE_COVERAGE_FUZZING,
+ },
+ {
+ name: LICENSE_COMPLIANCE_NAME,
+ description: LICENSE_COMPLIANCE_DESCRIPTION,
+ helpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ type: REPORT_TYPE_LICENSE_COMPLIANCE,
+ },
+];
diff --git a/app/assets/javascripts/security_configuration/components/manage_sast.vue b/app/assets/javascripts/security_configuration/components/manage_sast.vue
new file mode 100644
index 00000000000..5169096d563
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/manage_sast.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+import configureSastMutation from '~/security_configuration/graphql/configure_sast.mutation.graphql';
+
+export default {
+ components: {
+ GlButton,
+ },
+ inject: {
+ projectPath: {
+ from: 'projectPath',
+ default: '',
+ },
+ },
+ data: () => ({
+ isLoading: false,
+ }),
+ methods: {
+ async mutate() {
+ this.isLoading = true;
+ try {
+ const { data } = await this.$apollo.mutate({
+ mutation: configureSastMutation,
+ variables: {
+ input: {
+ projectPath: this.projectPath,
+ configuration: { global: [], pipeline: [], analyzers: [] },
+ },
+ },
+ });
+ const { errors, successPath } = data.configureSast;
+
+ if (errors.length > 0) {
+ throw new Error(errors[0]);
+ }
+
+ if (!successPath) {
+ throw new Error(s__('SecurityConfiguration|SAST merge request creation mutation failed'));
+ }
+
+ redirectTo(successPath);
+ } catch (e) {
+ this.$emit('error', e.message);
+ this.isLoading = false;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button :loading="isLoading" variant="success" category="secondary" @click="mutate">{{
+ s__('SecurityConfiguration|Configure via Merge Request')
+ }}</gl-button>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/upgrade.vue b/app/assets/javascripts/security_configuration/components/upgrade.vue
new file mode 100644
index 00000000000..166ee4ff194
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/upgrade.vue
@@ -0,0 +1,26 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { UPGRADE_CTA } from './features_constants';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ i18n: {
+ UPGRADE_CTA,
+ },
+};
+</script>
+
+<template>
+ <span>
+ <gl-sprintf :message="$options.i18n.UPGRADE_CTA">
+ <template #link="{ content }">
+ <gl-link target="_blank" href="https://about.gitlab.com/pricing/">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+</template>
diff --git a/app/assets/javascripts/security_configuration/graphql/configure_sast.mutation.graphql b/app/assets/javascripts/security_configuration/graphql/configure_sast.mutation.graphql
new file mode 100644
index 00000000000..9e826cf9e4b
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/graphql/configure_sast.mutation.graphql
@@ -0,0 +1,6 @@
+mutation configureSast($input: ConfigureSastInput!) {
+ configureSast(input: $input) {
+ successPath
+ errors
+ }
+}
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
new file mode 100644
index 00000000000..c98fa46b32b
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import SecurityConfigurationApp from './components/app.vue';
+
+export const initStaticSecurityConfiguration = (el) => {
+ if (!el) {
+ return null;
+ }
+
+ Vue.use(VueApollo);
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { projectPath } = el.dataset;
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: {
+ projectPath,
+ },
+ render(createElement) {
+ return createElement(SecurityConfigurationApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
index 6776a9ebb22..9b7264e92ce 100644
--- a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
+++ b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
@@ -1,10 +1,11 @@
<script>
/* eslint-disable vue/no-v-html */
-import Vue from 'vue';
import { GlFormGroup, GlButton, GlModal, GlToast, GlToggle } from '@gitlab/ui';
+import Vue from 'vue';
import { mapState, mapActions } from 'vuex';
-import { __, s__, sprintf } from '~/locale';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { visitUrl, getBaseURL } from '~/lib/utils/url_utility';
+import { __, s__, sprintf } from '~/locale';
Vue.use(GlToast);
@@ -98,11 +99,11 @@ export default {
'resetAlert',
]),
hideSelfMonitorModal() {
- this.$root.$emit('bv::hide::modal', this.modalId);
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
this.setSelfMonitor(true);
},
showSelfMonitorModal() {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
saveChangesSelfMonitorProject() {
if (this.projectCreated && !this.projectEnabled) {
diff --git a/app/assets/javascripts/self_monitor/index.js b/app/assets/javascripts/self_monitor/index.js
index 7db87b4c627..384b73e528e 100644
--- a/app/assets/javascripts/self_monitor/index.js
+++ b/app/assets/javascripts/self_monitor/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import store from './store';
import SelfMonitorForm from './components/self_monitor_form.vue';
+import store from './store';
export default () => {
const el = document.querySelector('.js-self-monitoring-settings');
diff --git a/app/assets/javascripts/self_monitor/store/actions.js b/app/assets/javascripts/self_monitor/store/actions.js
index 99731309a62..670ee547b02 100644
--- a/app/assets/javascripts/self_monitor/store/actions.js
+++ b/app/assets/javascripts/self_monitor/store/actions.js
@@ -1,7 +1,7 @@
-import { __, s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
-import statusCodes from '~/lib/utils/http_status';
import { backOff } from '~/lib/utils/common_utils';
+import statusCodes from '~/lib/utils/http_status';
+import { __, s__ } from '~/locale';
import * as types from './mutation_types';
const TWO_MINUTES = 120000;
diff --git a/app/assets/javascripts/self_monitor/store/index.js b/app/assets/javascripts/self_monitor/store/index.js
index 1144fff759a..187c3bdd803 100644
--- a/app/assets/javascripts/self_monitor/store/index.js
+++ b/app/assets/javascripts/self_monitor/store/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/sentry/sentry_config.js b/app/assets/javascripts/sentry/sentry_config.js
index 631d5448d1e..4277ffec545 100644
--- a/app/assets/javascripts/sentry/sentry_config.js
+++ b/app/assets/javascripts/sentry/sentry_config.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import * as Sentry from '~/sentry/wrapper';
import { __ } from '~/locale';
+import * as Sentry from '~/sentry/wrapper';
const IGNORE_ERRORS = [
// Random plugins/extensions
diff --git a/app/assets/javascripts/sentry_error_stack_trace/index.js b/app/assets/javascripts/sentry_error_stack_trace/index.js
index 80fa0988f0a..8e9ee25e7a8 100644
--- a/app/assets/javascripts/sentry_error_stack_trace/index.js
+++ b/app/assets/javascripts/sentry_error_stack_trace/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
import store from '~/error_tracking/store';
+import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
export default function initSentryErrorStacktrace() {
const sentryErrorStackTraceEl = document.querySelector('#js-sentry-error-stack-trace');
diff --git a/app/assets/javascripts/serverless/components/area.vue b/app/assets/javascripts/serverless/components/area.vue
index 056b342cf39..a9584c070fe 100644
--- a/app/assets/javascripts/serverless/components/area.vue
+++ b/app/assets/javascripts/serverless/components/area.vue
@@ -2,9 +2,9 @@
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat';
import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
import { X_INTERVAL } from '../constants';
import { validateGraphData } from '../utils';
-import { __ } from '~/locale';
let debouncedResize;
diff --git a/app/assets/javascripts/serverless/components/environment_row.vue b/app/assets/javascripts/serverless/components/environment_row.vue
index c46dfb66afe..01030172ea8 100644
--- a/app/assets/javascripts/serverless/components/environment_row.vue
+++ b/app/assets/javascripts/serverless/components/environment_row.vue
@@ -1,6 +1,6 @@
<script>
-import FunctionRow from './function_row.vue';
import ItemCaret from '~/groups/components/item_caret.vue';
+import FunctionRow from './function_row.vue';
export default {
components: {
diff --git a/app/assets/javascripts/serverless/components/function_details.vue b/app/assets/javascripts/serverless/components/function_details.vue
index 6ab44eec5cd..d2306c2d8bd 100644
--- a/app/assets/javascripts/serverless/components/function_details.vue
+++ b/app/assets/javascripts/serverless/components/function_details.vue
@@ -1,10 +1,10 @@
<script>
import { isString } from 'lodash';
import { mapState, mapActions, mapGetters } from 'vuex';
-import PodBox from './pod_box.vue';
-import Url from './url.vue';
import AreaChart from './area.vue';
import MissingPrometheus from './missing_prometheus.vue';
+import PodBox from './pod_box.vue';
+import Url from './url.vue';
export default {
components: {
diff --git a/app/assets/javascripts/serverless/components/function_row.vue b/app/assets/javascripts/serverless/components/function_row.vue
index aac7c46a295..fab9c0a75e7 100644
--- a/app/assets/javascripts/serverless/components/function_row.vue
+++ b/app/assets/javascripts/serverless/components/function_row.vue
@@ -1,8 +1,8 @@
<script>
import { isString } from 'lodash';
+import { visitUrl } from '~/lib/utils/url_utility';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import Url from './url.vue';
-import { visitUrl } from '~/lib/utils/url_utility';
export default {
components: {
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index d662cc7b802..b2d7aa75051 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -1,10 +1,10 @@
<script>
-import { mapState, mapActions, mapGetters } from 'vuex';
import { GlLink, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { mapState, mapActions, mapGetters } from 'vuex';
import { sprintf, s__ } from '~/locale';
-import EnvironmentRow from './environment_row.vue';
-import EmptyState from './empty_state.vue';
import { CHECKING_INSTALLED } from '../constants';
+import EmptyState from './empty_state.vue';
+import EnvironmentRow from './environment_row.vue';
export default {
components: {
@@ -69,18 +69,16 @@ export default {
<div v-else-if="isInstalled">
<div v-if="hasFunctionData">
- <template>
- <div class="groups-list-tree-container js-functions-wrapper">
- <ul class="content-list group-list-tree">
- <environment-row
- v-for="(env, index) in getFunctions"
- :key="index"
- :env="env"
- :env-name="index"
- />
- </ul>
- </div>
- </template>
+ <div class="groups-list-tree-container js-functions-wrapper">
+ <ul class="content-list group-list-tree">
+ <environment-row
+ v-for="(env, index) in getFunctions"
+ :key="index"
+ :env="env"
+ :env-name="index"
+ />
+ </ul>
+ </div>
<gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-3 gl-mb-3 js-functions-loader" />
</div>
<div v-else class="empty-state js-empty-state">
diff --git a/app/assets/javascripts/serverless/serverless_bundle.js b/app/assets/javascripts/serverless/serverless_bundle.js
index 24a9b4ac521..e8d87a40fc7 100644
--- a/app/assets/javascripts/serverless/serverless_bundle.js
+++ b/app/assets/javascripts/serverless/serverless_bundle.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import Functions from './components/functions.vue';
import FunctionDetails from './components/function_details.vue';
+import Functions from './components/functions.vue';
import { createStore } from './store';
export default class Serverless {
diff --git a/app/assets/javascripts/serverless/store/actions.js b/app/assets/javascripts/serverless/store/actions.js
index acd7020f70f..a6c0380a789 100644
--- a/app/assets/javascripts/serverless/store/actions.js
+++ b/app/assets/javascripts/serverless/store/actions.js
@@ -1,10 +1,10 @@
-import * as types from './mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import statusCodes from '~/lib/utils/http_status';
import { backOff } from '~/lib/utils/common_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import statusCodes from '~/lib/utils/http_status';
import { __ } from '~/locale';
import { MAX_REQUESTS, CHECKING_INSTALLED, TIMEOUT } from '../constants';
+import * as types from './mutation_types';
export const requestFunctionsLoading = ({ commit }) => commit(types.REQUEST_FUNCTIONS_LOADING);
export const receiveFunctionsSuccess = ({ commit }, data) =>
diff --git a/app/assets/javascripts/serverless/survey_banner.vue b/app/assets/javascripts/serverless/survey_banner.vue
index 18ab8315840..c48c294c0f7 100644
--- a/app/assets/javascripts/serverless/survey_banner.vue
+++ b/app/assets/javascripts/serverless/survey_banner.vue
@@ -1,6 +1,6 @@
<script>
-import Cookies from 'js-cookie';
import { GlBanner } from '@gitlab/ui';
+import Cookies from 'js-cookie';
import { parseBoolean } from '~/lib/utils/common_utils';
export default {
diff --git a/app/assets/javascripts/set_status_modal/components/user_availability_status.vue b/app/assets/javascripts/set_status_modal/components/user_availability_status.vue
deleted file mode 100644
index e86d94f86c6..00000000000
--- a/app/assets/javascripts/set_status_modal/components/user_availability_status.vue
+++ /dev/null
@@ -1,26 +0,0 @@
-<script>
-import { AVAILABILITY_STATUS, isUserBusy, isValidAvailibility } from '../utils';
-
-export default {
- name: 'UserAvailabilityStatus',
- props: {
- availability: {
- type: String,
- required: true,
- validator: isValidAvailibility,
- },
- },
- computed: {
- isBusy() {
- const { availability = AVAILABILITY_STATUS.NOT_SET } = this;
- return isUserBusy(availability);
- },
- },
-};
-</script>
-
-<template>
- <span v-if="isBusy" class="gl-font-weight-normal gl-text-gray-500">{{
- s__('UserAvailability|(Busy)')
- }}</span>
-</template>
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index c8efbd73b48..bed264341a5 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -1,15 +1,16 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlToast, GlModal, GlTooltipDirective, GlIcon, GlFormCheckbox } from '@gitlab/ui';
import $ from 'jquery';
import Vue from 'vue';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
-import { GlToast, GlModal, GlTooltipDirective, GlIcon, GlFormCheckbox } from '@gitlab/ui';
+import * as Emoji from '~/emoji';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { __, s__ } from '~/locale';
import { updateUserStatus } from '~/rest_api';
import EmojiMenuInModal from './emoji_menu_in_modal';
-import { isUserBusy, isValidAvailibility } from './utils';
-import * as Emoji from '~/emoji';
+import { isUserBusy } from './utils';
const emojiMenuClass = 'js-modal-status-emoji-menu';
export const AVAILABILITY_STATUS = {
@@ -45,7 +46,6 @@ export default {
currentAvailability: {
type: String,
required: false,
- validator: isValidAvailibility,
default: '',
},
canSetUserAvailability: {
@@ -76,14 +76,14 @@ export default {
},
},
mounted() {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
beforeDestroy() {
this.emojiMenu.destroy();
},
methods: {
closeModal() {
- this.$root.$emit('bv::hide::modal', this.modalId);
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
},
setupEmojiListAndAutocomplete() {
const toggleEmojiMenuButtonSelector = '#set-user-status-modal .js-toggle-emoji-menu';
diff --git a/app/assets/javascripts/set_status_modal/utils.js b/app/assets/javascripts/set_status_modal/utils.js
index faee4012ef4..e17d95adb25 100644
--- a/app/assets/javascripts/set_status_modal/utils.js
+++ b/app/assets/javascripts/set_status_modal/utils.js
@@ -3,7 +3,5 @@ export const AVAILABILITY_STATUS = {
NOT_SET: 'not_set',
};
-export const isUserBusy = (status) => status === AVAILABILITY_STATUS.BUSY;
-
-export const isValidAvailibility = (availability) =>
- availability.length ? Object.values(AVAILABILITY_STATUS).includes(availability) : true;
+export const isUserBusy = (status = '') =>
+ Boolean(status.length && status.toLowerCase().trim() === AVAILABILITY_STATUS.BUSY);
diff --git a/app/assets/javascripts/settings_panels.js b/app/assets/javascripts/settings_panels.js
index 1f1f6e42576..2c6da5669ef 100644
--- a/app/assets/javascripts/settings_panels.js
+++ b/app/assets/javascripts/settings_panels.js
@@ -1,7 +1,22 @@
import $ from 'jquery';
import { __ } from './locale';
-export function expandSection($section) {
+/**
+ * Returns true if the given section is expanded or not
+ *
+ * For legacy consistency, it supports both jQuery and DOM elements
+ *
+ * @param {jQuery | Element} section
+ */
+export function isExpanded(sectionArg) {
+ const section = sectionArg instanceof $ ? sectionArg[0] : sectionArg;
+
+ return section.classList.contains('expanded');
+}
+
+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);
@@ -13,7 +28,9 @@ export function expandSection($section) {
}
}
-export function closeSection($section) {
+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');
@@ -26,7 +43,7 @@ export function closeSection($section) {
export function toggleSection($section) {
$section.removeClass('no-animate');
- if ($section.hasClass('expanded')) {
+ if (isExpanded($section)) {
closeSection($section);
} else {
expandSection($section);
@@ -38,7 +55,7 @@ export default function initSettingsPanels() {
const $section = $(elm);
$section.on('click.toggleSection', '.js-settings-toggle', () => toggleSection($section));
- if (!$section.hasClass('expanded')) {
+ if (!isExpanded($section)) {
$section.find('.settings-content').on('scroll.expandSection', () => {
$section.removeClass('no-animate');
expandSection($section);
diff --git a/app/assets/javascripts/shared/milestones/form.js b/app/assets/javascripts/shared/milestones/form.js
index 9ee02f923d5..467cd321fb8 100644
--- a/app/assets/javascripts/shared/milestones/form.js
+++ b/app/assets/javascripts/shared/milestones/form.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import ZenMode from '../../zen_mode';
import DueDateSelectors from '../../due_date_select';
import GLForm from '../../gl_form';
+import ZenMode from '../../zen_mode';
export default (initGFM = true) => {
new ZenMode(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
index fbbe2e341a7..d0a65b48522 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
@@ -1,8 +1,46 @@
<script>
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
+import { isUserBusy } from '~/set_status_modal/utils';
import AssigneeAvatar from './assignee_avatar.vue';
+const I18N = {
+ BUSY: __('Busy'),
+ CANNOT_MERGE: __('Cannot merge'),
+ LC_CANNOT_MERGE: __('cannot merge'),
+};
+
+const paranthesize = (str) => `(${str})`;
+
+const generateAssigneeTooltip = ({
+ name,
+ availability,
+ cannotMerge = true,
+ tooltipHasName = false,
+}) => {
+ if (!tooltipHasName) {
+ return cannotMerge ? I18N.CANNOT_MERGE : '';
+ }
+
+ const statusInformation = [];
+ if (availability && isUserBusy(availability)) {
+ statusInformation.push(I18N.BUSY);
+ }
+
+ if (cannotMerge) {
+ statusInformation.push(I18N.LC_CANNOT_MERGE);
+ }
+
+ if (tooltipHasName && statusInformation.length) {
+ return sprintf(__('%{name} %{status}'), {
+ name,
+ status: statusInformation.map(paranthesize).join(' '),
+ });
+ }
+
+ return name;
+};
+
export default {
components: {
AssigneeAvatar,
@@ -37,15 +75,13 @@ export default {
return this.issuableType === 'merge_request' && !this.user.can_merge;
},
tooltipTitle() {
- if (this.cannotMerge && this.tooltipHasName) {
- return sprintf(__('%{userName} (cannot merge)'), { userName: this.user.name });
- } else if (this.cannotMerge) {
- return __('Cannot merge');
- } else if (this.tooltipHasName) {
- return this.user.name;
- }
-
- return '';
+ const { name = '', availability = '' } = this.user;
+ return generateAssigneeTooltip({
+ name,
+ availability,
+ cannotMerge: this.cannotMerge,
+ tooltipHasName: this.tooltipHasName,
+ });
},
tooltipOption() {
return {
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index 84e7110e2b2..c3c009e680a 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -11,10 +11,6 @@ export default {
UncollapsedAssigneeList,
},
props: {
- rootPath: {
- type: String,
- required: true,
- },
users: {
type: Array,
required: true,
@@ -36,7 +32,6 @@ export default {
sortedAssigness() {
const canMergeUsers = this.users.filter((user) => user.can_merge);
const canNotMergeUsers = this.users.filter((user) => !user.can_merge);
-
return [...canMergeUsers, ...canNotMergeUsers];
},
},
@@ -52,9 +47,9 @@ export default {
<div>
<collapsed-assignee-list :users="sortedAssigness" :issuable-type="issuableType" />
- <div class="value hide-collapsed">
+ <div data-testid="expanded-assignee" class="value hide-collapsed">
<template v-if="hasNoUsers">
- <span class="assign-yourself no-value qa-assign-yourself">
+ <span class="assign-yourself no-value">
{{ __('None') }}
<template v-if="editable">
-
@@ -65,12 +60,7 @@ export default {
</span>
</template>
- <uncollapsed-assignee-list
- v-else
- :users="sortedAssigness"
- :root-path="rootPath"
- :issuable-type="issuableType"
- />
+ <uncollapsed-assignee-list v-else :users="sortedAssigness" :issuable-type="issuableType" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
index 0eee287e0c2..ca86d6c6c3e 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
@@ -1,7 +1,7 @@
<script>
+import actionCable from '~/actioncable_consumer';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql';
-import actionCable from '~/actioncable_consumer';
export default {
subscription: null,
diff --git a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue
index 2f654409561..af4227fa48d 100644
--- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue
@@ -1,9 +1,11 @@
<script>
import AssigneeAvatar from './assignee_avatar.vue';
+import UserNameWithStatus from './user_name_with_status.vue';
export default {
components: {
AssigneeAvatar,
+ UserNameWithStatus,
},
props: {
user: {
@@ -16,12 +18,20 @@ export default {
default: 'issue',
},
},
+ computed: {
+ availability() {
+ return this.user?.availability || '';
+ },
+ },
};
</script>
-
<template>
<button type="button" class="btn-link">
<assignee-avatar :user="user" :img-size="24" :issuable-type="issuableType" />
- <span class="author"> {{ user.name }} </span>
+ <user-name-with-status
+ :name="user.name"
+ :availability="availability"
+ container-classes="author"
+ />
</button>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
index b713b0f960c..20667e695ce 100644
--- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
@@ -1,11 +1,30 @@
<script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
+import { isUserBusy } from '~/set_status_modal/utils';
import CollapsedAssignee from './collapsed_assignee.vue';
const DEFAULT_MAX_COUNTER = 99;
const DEFAULT_RENDER_COUNT = 5;
+const generateCollapsedAssigneeTooltip = ({ renderUsers, allUsers, tooltipTitleMergeStatus }) => {
+ const names = renderUsers.map(({ name, availability }) => {
+ if (availability && isUserBusy(availability)) {
+ return sprintf(__('%{name} (Busy)'), { name });
+ }
+ return name;
+ });
+
+ if (!allUsers.length) {
+ return __('Assignee(s)');
+ }
+ if (allUsers.length > names.length) {
+ names.push(sprintf(__('+ %{amount} more'), { amount: allUsers.length - names.length }));
+ }
+ const text = names.join(', ');
+ return tooltipTitleMergeStatus ? `${text} (${tooltipTitleMergeStatus})` : text;
+};
+
export default {
directives: {
GlTooltip: GlTooltipDirective,
@@ -74,19 +93,11 @@ export default {
tooltipTitle() {
const maxRender = Math.min(DEFAULT_RENDER_COUNT, this.users.length);
const renderUsers = this.users.slice(0, maxRender);
- const names = renderUsers.map((u) => u.name);
-
- if (!this.users.length) {
- return __('Assignee(s)');
- }
-
- if (this.users.length > names.length) {
- names.push(sprintf(__('+ %{amount} more'), { amount: this.users.length - names.length }));
- }
-
- const text = names.join(', ');
-
- return this.tooltipTitleMergeStatus ? `${text} (${this.tooltipTitleMergeStatus})` : text;
+ return generateCollapsedAssigneeTooltip({
+ renderUsers,
+ allUsers: this.users,
+ tooltipTitleMergeStatus: this.tooltipTitleMergeStatus,
+ });
},
tooltipOptions() {
diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
index 3c1b3afe889..e2dc37a0ac2 100644
--- a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
@@ -8,12 +8,16 @@ export default {
GlButton,
UncollapsedAssigneeList,
},
- inject: ['rootPath'],
props: {
users: {
type: Array,
required: true,
},
+ issuableType: {
+ type: String,
+ required: false,
+ default: 'issue',
+ },
},
computed: {
assigneesText() {
@@ -36,9 +40,9 @@ export default {
variant="link"
@click="$emit('assign-self')"
>
- <span class="gl-text-gray-400">{{ __('assign yourself') }}</span>
+ <span class="gl-text-gray-500 gl-hover-text-blue-800">{{ __('assign yourself') }}</span>
</gl-button>
</div>
- <uncollapsed-assignee-list v-else :users="users" :root-path="rootPath" />
+ <uncollapsed-assignee-list v-else :users="users" :issuable-type="issuableType" />
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index b9f268629fb..6595debf9a5 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -1,13 +1,13 @@
<script>
+import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AssigneeTitle from './assignee_title.vue';
import Assignees from './assignees.vue';
import AssigneesRealtime from './assignees_realtime.vue';
-import { __ } from '~/locale';
export default {
name: 'SidebarAssignees',
@@ -44,6 +44,11 @@ export default {
type: String,
required: true,
},
+ assigneeAvailabilityStatus: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
data() {
return {
@@ -101,6 +106,13 @@ export default {
return new Flash(__('Error occurred when saving assignees'));
});
},
+ exposeAvailabilityStatus(users) {
+ return users.map(({ username, ...rest }) => ({
+ ...rest,
+ username,
+ availability: this.assigneeAvailabilityStatus[username] || '',
+ }));
+ },
},
};
</script>
@@ -123,7 +135,7 @@ export default {
<assignees
v-if="!store.isFetching.assignees"
:root-path="relativeUrlRoot"
- :users="store.assignees"
+ :users="exposeAvailabilityStatus(store.assignees)"
:editable="store.editable"
:issuable-type="issuableType"
class="value"
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
new file mode 100644
index 00000000000..8f3f77cb5f0
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -0,0 +1,403 @@
+<script>
+import {
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlAvatarLabeled,
+ GlAvatarLink,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { cloneDeep } from 'lodash';
+import Vue from 'vue';
+import createFlash from '~/flash';
+import searchUsers from '~/graphql_shared/queries/users_search.query.graphql';
+import { IssuableType } from '~/issue_show/constants';
+import { __, n__ } from '~/locale';
+import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+import { assigneesQueries } from '~/sidebar/constants';
+import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
+
+export const assigneesWidget = Vue.observable({
+ updateAssignees: null,
+});
+
+export default {
+ i18n: {
+ unassigned: __('Unassigned'),
+ assignee: __('Assignee'),
+ assignees: __('Assignees'),
+ assignTo: __('Assign to'),
+ },
+ assigneesQueries,
+ components: {
+ SidebarEditableItem,
+ IssuableAssignees,
+ MultiSelectDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlAvatarLabeled,
+ GlAvatarLink,
+ GlSearchBoxByType,
+ GlLoadingIcon,
+ },
+ props: {
+ iid: {
+ type: String,
+ required: true,
+ },
+ fullPath: {
+ type: String,
+ required: true,
+ },
+ initialAssignees: {
+ type: Array,
+ required: false,
+ default: null,
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: IssuableType.Issue,
+ validator(value) {
+ return [IssuableType.Issue, IssuableType.MergeRequest].includes(value);
+ },
+ },
+ multipleAssignees: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ search: '',
+ issuable: {},
+ searchUsers: [],
+ selected: [],
+ isSettingAssignees: false,
+ isSearching: false,
+ };
+ },
+ apollo: {
+ issuable: {
+ query() {
+ return this.$options.assigneesQueries[this.issuableType].query;
+ },
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data.issuable || data.project?.issuable;
+ },
+ result({ data }) {
+ const issuable = data.issuable || data.project?.issuable;
+ if (issuable) {
+ this.selected = this.moveCurrentUserToStart(cloneDeep(issuable.assignees.nodes));
+ }
+ },
+ error() {
+ createFlash({ message: __('An error occurred while fetching participants.') });
+ },
+ },
+ searchUsers: {
+ query: searchUsers,
+ variables() {
+ return {
+ search: this.search,
+ };
+ },
+ update(data) {
+ return data.users?.nodes || [];
+ },
+ debounce: 250,
+ skip() {
+ return this.isSearchEmpty;
+ },
+ error() {
+ createFlash({ message: __('An error occurred while searching users.') });
+ this.isSearching = false;
+ },
+ result() {
+ this.isSearching = false;
+ },
+ },
+ },
+ computed: {
+ queryVariables() {
+ return {
+ iid: this.iid,
+ fullPath: this.fullPath,
+ };
+ },
+ assignees() {
+ const currentAssignees = this.$apollo.queries.issuable.loading
+ ? this.initialAssignees
+ : this.issuable?.assignees?.nodes;
+ return currentAssignees || [];
+ },
+ participants() {
+ const users =
+ this.isSearchEmpty || this.isSearching
+ ? this.issuable?.participants?.nodes
+ : this.searchUsers;
+ return this.moveCurrentUserToStart(users);
+ },
+ assigneeText() {
+ const items = this.$apollo.queries.issuable.loading ? this.initialAssignees : this.selected;
+ return n__('Assignee', '%d Assignees', items.length);
+ },
+ selectedFiltered() {
+ if (this.isSearchEmpty || this.isSearching) {
+ return this.selected;
+ }
+
+ const foundUsernames = this.searchUsers.map(({ username }) => username);
+ return this.selected.filter(({ username }) => foundUsernames.includes(username));
+ },
+ unselectedFiltered() {
+ return (
+ this.participants?.filter(({ username }) => !this.selectedUserNames.includes(username)) ||
+ []
+ );
+ },
+ selectedIsEmpty() {
+ return this.selectedFiltered.length === 0;
+ },
+ selectedUserNames() {
+ return this.selected.map(({ username }) => username);
+ },
+ isSearchEmpty() {
+ return this.search === '';
+ },
+ currentUser() {
+ return {
+ username: gon?.current_username,
+ name: gon?.current_user_fullname,
+ avatarUrl: gon?.current_user_avatar_url,
+ };
+ },
+ isAssigneesLoading() {
+ return !this.initialAssignees && this.$apollo.queries.issuable.loading;
+ },
+ isCurrentUserInParticipants() {
+ const isCurrentUser = (user) => user.username === this.currentUser.username;
+ return this.selected.some(isCurrentUser) || this.participants.some(isCurrentUser);
+ },
+ noUsersFound() {
+ return !this.isSearchEmpty && this.unselectedFiltered.length === 0;
+ },
+ showCurrentUser() {
+ return !this.isCurrentUserInParticipants && (this.isSearchEmpty || this.isSearching);
+ },
+ },
+ watch: {
+ // We need to add this watcher to track the moment when user is alredy typing
+ // but query is still not started due to debounce
+ search(newVal) {
+ if (newVal) {
+ this.isSearching = true;
+ }
+ },
+ },
+ created() {
+ assigneesWidget.updateAssignees = this.updateAssignees;
+ },
+ destroyed() {
+ assigneesWidget.updateAssignees = null;
+ },
+ methods: {
+ updateAssignees(assigneeUsernames) {
+ this.isSettingAssignees = true;
+ return this.$apollo
+ .mutate({
+ mutation: this.$options.assigneesQueries[this.issuableType].mutation,
+ variables: {
+ ...this.queryVariables,
+ assigneeUsernames,
+ },
+ })
+ .then(({ data }) => {
+ this.$emit('assignees-updated', data);
+ return data;
+ })
+ .catch(() => {
+ createFlash({ message: __('An error occurred while updating assignees.') });
+ })
+ .finally(() => {
+ this.isSettingAssignees = false;
+ });
+ },
+ selectAssignee(name) {
+ if (name === undefined) {
+ this.clearSelected();
+ return;
+ }
+
+ if (!this.multipleAssignees) {
+ this.selected = [name];
+ this.collapseWidget();
+ } else {
+ this.selected = this.selected.concat(name);
+ }
+ },
+ unselect(name) {
+ this.selected = this.selected.filter((user) => user.username !== name);
+
+ if (!this.multipleAssignees) {
+ this.collapseWidget();
+ }
+ },
+ assignSelf() {
+ this.updateAssignees(this.currentUser.username);
+ },
+ clearSelected() {
+ this.selected = [];
+ },
+ saveAssignees() {
+ this.updateAssignees(this.selectedUserNames);
+ },
+ isChecked(id) {
+ return this.selectedUserNames.includes(id);
+ },
+ async focusSearch() {
+ await this.$nextTick();
+ this.$refs.search.focusInput();
+ },
+ moveCurrentUserToStart(users) {
+ if (!users) {
+ return [];
+ }
+ const usersCopy = [...users];
+ const currentUser = usersCopy.find((user) => user.username === this.currentUser.username);
+
+ if (currentUser) {
+ const index = usersCopy.indexOf(currentUser);
+ usersCopy.splice(0, 0, usersCopy.splice(index, 1)[0]);
+ }
+
+ return usersCopy;
+ },
+ collapseWidget() {
+ this.$refs.toggle.collapse();
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ v-if="isAssigneesLoading"
+ class="gl-display-flex gl-align-items-center assignee"
+ data-testid="loading-assignees"
+ >
+ {{ __('Assignee') }}
+ <gl-loading-icon size="sm" class="gl-ml-2" />
+ </div>
+ <sidebar-editable-item
+ v-else
+ ref="toggle"
+ :loading="isSettingAssignees"
+ :title="assigneeText"
+ @open="focusSearch"
+ @close="saveAssignees"
+ >
+ <template #collapsed>
+ <issuable-assignees
+ :users="assignees"
+ :issuable-type="issuableType"
+ @assign-self="assignSelf"
+ />
+ </template>
+
+ <template #default>
+ <multi-select-dropdown
+ class="gl-w-full dropdown-menu-user"
+ :text="$options.i18n.assignees"
+ :header-text="$options.i18n.assignTo"
+ @toggle="collapseWidget"
+ >
+ <template #search>
+ <gl-search-box-by-type ref="search" v-model.trim="search" />
+ </template>
+ <template #items>
+ <gl-loading-icon
+ v-if="$apollo.queries.searchUsers.loading || $apollo.queries.issuable.loading"
+ data-testid="loading-participants"
+ size="lg"
+ />
+ <template v-else>
+ <template v-if="isSearchEmpty || isSearching">
+ <gl-dropdown-item
+ :is-checked="selectedIsEmpty"
+ :is-check-centered="true"
+ data-testid="unassign"
+ @click="selectAssignee()"
+ >
+ <span :class="selectedIsEmpty ? 'gl-pl-0' : 'gl-pl-6'">{{
+ $options.i18n.unassigned
+ }}</span></gl-dropdown-item
+ >
+ <gl-dropdown-divider data-testid="unassign-divider" />
+ </template>
+ <gl-dropdown-item
+ v-for="item in selectedFiltered"
+ :key="item.id"
+ :is-checked="isChecked(item.username)"
+ :is-check-centered="true"
+ data-testid="selected-participant"
+ @click.stop="unselect(item.username)"
+ >
+ <gl-avatar-link>
+ <gl-avatar-labeled
+ :size="32"
+ :label="item.name"
+ :sub-label="item.username"
+ :src="item.avatarUrl || item.avatar || item.avatar_url"
+ class="gl-align-items-center"
+ />
+ </gl-avatar-link>
+ </gl-dropdown-item>
+ <gl-dropdown-divider v-if="!selectedIsEmpty" data-testid="selected-user-divider" />
+ <template v-if="showCurrentUser">
+ <gl-dropdown-item
+ data-testid="unselected-participant"
+ @click.stop="selectAssignee(currentUser)"
+ >
+ <gl-avatar-link>
+ <gl-avatar-labeled
+ :size="32"
+ :label="currentUser.name"
+ :sub-label="currentUser.username"
+ :src="currentUser.avatarUrl"
+ class="gl-align-items-center"
+ />
+ </gl-avatar-link>
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ </template>
+ <gl-dropdown-item
+ v-for="unselectedUser in unselectedFiltered"
+ :key="unselectedUser.id"
+ data-testid="unselected-participant"
+ @click="selectAssignee(unselectedUser)"
+ >
+ <gl-avatar-link class="gl-pl-6!">
+ <gl-avatar-labeled
+ :size="32"
+ :label="unselectedUser.name"
+ :sub-label="unselectedUser.username"
+ :src="unselectedUser.avatarUrl || unselectedUser.avatar"
+ class="gl-align-items-center"
+ />
+ </gl-avatar-link>
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="noUsersFound && !isSearching">
+ {{ __('No matching results') }}
+ </gl-dropdown-item>
+ </template>
+ </template>
+ </multi-select-dropdown>
+ </template>
+ </sidebar-editable-item>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index 31d5d7c0077..36775648809 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -1,12 +1,14 @@
<script>
import { __, sprintf } from '~/locale';
import AssigneeAvatarLink from './assignee_avatar_link.vue';
+import UserNameWithStatus from './user_name_with_status.vue';
const DEFAULT_RENDER_COUNT = 5;
export default {
components: {
AssigneeAvatarLink,
+ UserNameWithStatus,
},
props: {
users: {
@@ -55,6 +57,9 @@ export default {
toggleShowLess() {
this.showLess = !this.showLess;
},
+ userAvailability(u) {
+ return u?.availability || '';
+ },
},
};
</script>
@@ -68,7 +73,7 @@ export default {
:issuable-type="issuableType"
>
<div class="ml-2 gl-line-height-normal">
- <div>{{ firstUser.name }}</div>
+ <user-name-with-status :name="firstUser.name" :availability="userAvailability(firstUser)" />
<div>{{ username }}</div>
</div>
</assignee-avatar-link>
diff --git a/app/assets/javascripts/sidebar/components/assignees/user_name_with_status.vue b/app/assets/javascripts/sidebar/components/assignees/user_name_with_status.vue
new file mode 100644
index 00000000000..41b3b6c9a45
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/assignees/user_name_with_status.vue
@@ -0,0 +1,40 @@
+<script>
+import { GlSprintf } from '@gitlab/ui';
+import { isUserBusy } from '~/set_status_modal/utils';
+
+export default {
+ name: 'UserNameWithStatus',
+ components: {
+ GlSprintf,
+ },
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ containerClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ availability: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ isBusy() {
+ return isUserBusy(this.availability);
+ },
+ },
+};
+</script>
+<template>
+ <span :class="containerClasses">
+ <gl-sprintf v-if="isBusy" :message="s__('UserAvailability|%{author} (Busy)')">
+ <template #author>{{ name }}</template>
+ </gl-sprintf>
+ <template v-else>{{ name }}</template>
+ </span>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index ce120ff82f3..57b3705e803 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapState } from 'vuex';
import { __, sprintf } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import EditForm from './edit_form.vue';
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
index 17e44cf0e1d..057224d5918 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf } from '@gitlab/ui';
-import editFormButtons from './edit_form_buttons.vue';
import { __ } from '../../../locale';
+import editFormButtons from './edit_form_buttons.vue';
export default {
components: {
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
index d210f9efcb3..154a228c978 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -1,9 +1,9 @@
<script>
-import $ from 'jquery';
import { GlButton } from '@gitlab/ui';
+import $ from 'jquery';
import { mapActions } from 'vuex';
-import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import { __ } from '~/locale';
import eventHub from '../../event_hub';
export default {
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
index e01e1f032e3..c9b6616e067 100644
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -3,13 +3,13 @@ import $ from 'jquery';
import { camelCase, difference, union } from 'lodash';
import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
import createFlash from '~/flash';
+import { getIdFromGraphQLId, MutationOperationMode } from '~/graphql_shared/utils';
import { IssuableType } from '~/issue_show/constants';
import { __ } from '~/locale';
import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
import { toLabelGid } from '~/sidebar/utils';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-import { getIdFromGraphQLId, MutationOperationMode } from '~/graphql_shared/utils';
const mutationMap = {
[IssuableType.Issue]: {
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
index 26a7c8e4a80..c3f31a3d220 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
@@ -1,9 +1,9 @@
<script>
-import $ from 'jquery';
import { GlButton } from '@gitlab/ui';
+import $ from 'jquery';
import { mapActions } from 'vuex';
-import { __, sprintf } from '../../../locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import { __, sprintf } from '../../../locale';
import eventHub from '../../event_hub';
export default {
diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
index b96a2b93712..3468acb38e7 100644
--- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
+++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import editForm from './edit_form.vue';
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue
index b1b04564a62..87780888c2f 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue
@@ -76,8 +76,8 @@ export default {
class="d-inline-block"
>
<!-- use d-flex so that slot can be appropriately styled -->
- <span class="d-flex">
- <reviewer-avatar :user="user" :img-size="32" :issuable-type="issuableType" />
+ <span class="gl-display-flex gl-align-items-center">
+ <reviewer-avatar :user="user" :img-size="24" :issuable-type="issuableType" />
<slot :user="user"></slot>
</span>
</gl-link>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
index cd62fe5be0f..2c52d7142f7 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
@@ -46,6 +46,9 @@ export default {
assignSelf() {
this.$emit('assign-self');
},
+ requestReview(data) {
+ this.$emit('request-review', data);
+ },
},
};
</script>
@@ -56,7 +59,7 @@ export default {
<div class="value hide-collapsed">
<template v-if="hasNoUsers">
- <span class="assign-yourself no-value qa-assign-yourself">
+ <span class="assign-yourself no-value">
{{ __('None') }}
</span>
</template>
@@ -66,6 +69,7 @@ export default {
:users="sortedReviewers"
:root-path="rootPath"
:issuable-type="issuableType"
+ @request-review="requestReview"
/>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
index 1a2473e5f6c..b5cf5df4957 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
@@ -1,14 +1,14 @@
<script>
// NOTE! For the first iteration, we are simply copying the implementation of Assignees
// It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736
-import { deprecatedCreateFlash as Flash } from '~/flash';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
+import { deprecatedCreateFlash as Flash } from '~/flash';
+import { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ReviewerTitle from './reviewer_title.vue';
import Reviewers from './reviewers.vue';
-import { __ } from '~/locale';
export default {
name: 'SidebarReviewers',
@@ -83,6 +83,9 @@ export default {
return new Flash(__('Error occurred when saving reviewers'));
});
},
+ requestReview(data) {
+ this.mediator.requestReview(data);
+ },
},
};
</script>
@@ -101,6 +104,7 @@ export default {
:editable="store.editable"
:issuable-type="issuableType"
class="value"
+ @request-review="requestReview"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
index e82a271d007..cbd68f2513a 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
@@ -1,15 +1,19 @@
<script>
-// NOTE! For the first iteration, we are simply copying the implementation of Assignees
-// It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736
-import { __, sprintf } from '~/locale';
+import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import ReviewerAvatarLink from './reviewer_avatar_link.vue';
-const DEFAULT_RENDER_COUNT = 5;
+const LOADING_STATE = 'loading';
+const SUCCESS_STATE = 'success';
export default {
components: {
+ GlButton,
+ GlIcon,
ReviewerAvatarLink,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
users: {
type: Array,
@@ -28,76 +32,78 @@ export default {
data() {
return {
showLess: true,
+ loadingStates: {},
};
},
- computed: {
- firstUser() {
- return this.users[0];
- },
- hasOneUser() {
- return this.users.length === 1;
- },
- hiddenReviewersLabel() {
- const { numberOfHiddenReviewers } = this;
- return sprintf(__('+ %{numberOfHiddenReviewers} more'), { numberOfHiddenReviewers });
- },
- renderShowMoreSection() {
- return this.users.length > DEFAULT_RENDER_COUNT;
- },
- numberOfHiddenReviewers() {
- return this.users.length - DEFAULT_RENDER_COUNT;
- },
- uncollapsedUsers() {
- const uncollapsedLength = this.showLess
- ? Math.min(this.users.length, DEFAULT_RENDER_COUNT)
- : this.users.length;
- return this.showLess ? this.users.slice(0, uncollapsedLength) : this.users;
- },
- username() {
- return `@${this.firstUser.username}`;
+ watch: {
+ users: {
+ handler(users) {
+ this.loadingStates = users.reduce(
+ (acc, user) => ({
+ ...acc,
+ [user.id]: acc[user.id] || null,
+ }),
+ this.loadingStates,
+ );
+ },
+ immediate: true,
},
},
methods: {
toggleShowLess() {
this.showLess = !this.showLess;
},
+ reRequestReview(userId) {
+ this.loadingStates[userId] = LOADING_STATE;
+ this.$emit('request-review', { userId, callback: this.requestReviewComplete });
+ },
+ requestReviewComplete(userId, success) {
+ if (success) {
+ this.loadingStates[userId] = SUCCESS_STATE;
+
+ setTimeout(() => {
+ this.loadingStates[userId] = null;
+ }, 1500);
+ } else {
+ this.loadingStates[userId] = null;
+ }
+ },
},
+ LOADING_STATE,
+ SUCCESS_STATE,
};
</script>
<template>
- <reviewer-avatar-link
- v-if="hasOneUser"
- #default="{ user }"
- tooltip-placement="left"
- :tooltip-has-name="false"
- :user="firstUser"
- :root-path="rootPath"
- :issuable-type="issuableType"
- >
- <div class="gl-ml-3 gl-line-height-normal">
- <div class="author">{{ user.name }}</div>
- <div class="username">{{ username }}</div>
- </div>
- </reviewer-avatar-link>
- <div v-else>
- <div class="user-list">
- <div v-for="user in uncollapsedUsers" :key="user.id" class="user-item">
- <reviewer-avatar-link :user="user" :root-path="rootPath" :issuable-type="issuableType" />
- </div>
- </div>
- <div v-if="renderShowMoreSection" class="user-list-more">
- <button
- type="button"
- class="btn-link"
- data-qa-selector="more_reviewers_link"
- @click="toggleShowLess"
- >
- <template v-if="showLess">
- {{ hiddenReviewersLabel }}
- </template>
- <template v-else>{{ __('- show less') }}</template>
- </button>
+ <div>
+ <div
+ v-for="(user, index) in users"
+ :key="user.id"
+ :class="{ 'gl-mb-3': index !== users.length - 1 }"
+ data-testid="reviewer"
+ >
+ <reviewer-avatar-link :user="user" :root-path="rootPath" :issuable-type="issuableType">
+ <div class="gl-ml-3">@{{ user.username }}</div>
+ </reviewer-avatar-link>
+ <gl-icon
+ v-if="loadingStates[user.id] === $options.SUCCESS_STATE"
+ :size="24"
+ name="check"
+ class="float-right gl-text-green-500"
+ data-testid="re-request-success"
+ />
+ <gl-button
+ v-else-if="user.can_update_merge_request && user.reviewed"
+ v-gl-tooltip.left
+ :title="__('Re-request review')"
+ :loading="loadingStates[user.id] === $options.LOADING_STATE"
+ class="float-right gl-text-gray-500!"
+ size="small"
+ icon="redo"
+ variant="link"
+ data-testid="re-request-button"
+ @click="reRequestReview(user.id)"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
index 0cf11e83349..6a6300dcde0 100644
--- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -7,10 +7,10 @@ import {
GlSprintf,
GlLink,
} from '@gitlab/ui';
+import createFlash from '~/flash';
import { INCIDENT_SEVERITY, ISSUABLE_TYPES, I18N } from './constants';
import updateIssuableSeverity from './graphql/mutations/update_issuable_severity.mutation.graphql';
import SeverityToken from './severity.vue';
-import createFlash from '~/flash';
export default {
i18n: I18N,
diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
new file mode 100644
index 00000000000..9da839cd133
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+
+export default {
+ components: { GlButton, GlLoadingIcon },
+ inject: ['canUpdate'],
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ edit: false,
+ };
+ },
+ destroyed() {
+ window.removeEventListener('click', this.collapseWhenOffClick);
+ window.removeEventListener('keyup', this.collapseOnEscape);
+ },
+ methods: {
+ collapseWhenOffClick({ target }) {
+ if (!this.$el.contains(target)) {
+ this.collapse();
+ }
+ },
+ collapseOnEscape({ key }) {
+ if (key === 'Escape') {
+ this.collapse();
+ }
+ },
+ expand() {
+ if (this.edit) {
+ return;
+ }
+
+ this.edit = true;
+ this.$emit('open');
+ window.addEventListener('click', this.collapseWhenOffClick);
+ window.addEventListener('keyup', this.collapseOnEscape);
+ },
+ collapse({ emitEvent = true } = {}) {
+ if (!this.edit) {
+ return;
+ }
+
+ this.edit = false;
+ if (emitEvent) {
+ this.$emit('close');
+ }
+ window.removeEventListener('click', this.collapseWhenOffClick);
+ window.removeEventListener('keyup', this.collapseOnEscape);
+ },
+ toggle({ emitEvent = true } = {}) {
+ if (this.edit) {
+ this.collapse({ emitEvent });
+ } else {
+ this.expand();
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-display-flex gl-align-items-center gl-mb-3" @click.self="collapse">
+ <span data-testid="title">{{ title }}</span>
+ <gl-loading-icon v-if="loading" inline class="gl-ml-2" />
+ <gl-button
+ v-if="canUpdate"
+ variant="link"
+ class="gl-text-gray-900! gl-hover-text-blue-800! gl-ml-auto js-sidebar-dropdown-toggle"
+ data-testid="edit-button"
+ @keyup.esc="toggle"
+ @click="toggle"
+ >
+ {{ __('Edit') }}
+ </gl-button>
+ </div>
+ <div v-show="!edit" class="gl-text-gray-500" data-testid="collapsed-content">
+ <slot name="collapsed">{{ __('None') }}</slot>
+ </div>
+ <div v-show="edit" data-testid="expanded-content">
+ <slot :edit="edit"></slot>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
index ee1c98e9d69..3ad097138a3 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
@@ -1,7 +1,7 @@
<script>
-import Store from '../../stores/sidebar_store';
import { deprecatedCreateFlash as Flash } from '../../../flash';
import { __ } from '../../../locale';
+import Store from '../../stores/sidebar_store';
import subscriptions from './subscriptions.vue';
export default {
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
index 6d21936791c..9b06c20a6f3 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -1,8 +1,7 @@
<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlToggle, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
import Tracking from '~/tracking';
-import toggleButton from '~/vue_shared/components/toggle_button.vue';
import eventHub from '../../event_hub';
const ICON_ON = 'notifications';
@@ -16,7 +15,7 @@ export default {
},
components: {
GlIcon,
- toggleButton,
+ GlToggle,
},
mixins: [Tracking.mixin({ label: 'right_sidebar' })],
props: {
@@ -106,7 +105,7 @@ export default {
</script>
<template>
- <div>
+ <div class="gl-display-flex gl-justify-content-space-between">
<span
ref="tooltip"
v-gl-tooltip.viewport.left
@@ -116,13 +115,13 @@ export default {
>
<gl-icon :name="notificationIcon" :size="16" class="sidebar-item-icon is-active" />
</span>
- <span class="issuable-header-text hide-collapsed float-left"> {{ notificationText }} </span>
- <toggle-button
+ <span class="hide-collapsed" data-testid="subscription-title"> {{ notificationText }} </span>
+ <gl-toggle
v-if="!projectEmailsDisabled"
- ref="toggleButton"
:is-loading="showLoadingState"
:value="subscribed"
- class="float-right hide-collapsed js-issuable-subscribe-button"
+ class="hide-collapsed"
+ data-testid="subscription-toggle"
@change="toggleSubscription"
/>
</div>
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 8bc828091c0..e0f60b9af08 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
@@ -1,7 +1,7 @@
<script>
/* eslint-disable vue/no-v-html */
-import { sprintf, s__ } from '../../../locale';
import { joinPaths } from '~/lib/utils/url_utility';
+import { sprintf, s__ } from '../../../locale';
export default {
name: 'TimeTrackingHelpState',
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index 26e0a0da860..c70d99ac178 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -4,11 +4,10 @@ import { intersection } from 'lodash';
import '~/smart_interval';
-import IssuableTimeTracker from './time_tracker.vue';
-
-import Store from '../../stores/sidebar_store';
-import Mediator from '../../sidebar_mediator';
import eventHub from '../../event_hub';
+import Mediator from '../../sidebar_mediator';
+import Store from '../../stores/sidebar_store';
+import IssuableTimeTracker from './time_tracker.vue';
export default {
components: {
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 26b8e087512..4c095006dd7 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,12 +1,11 @@
<script>
import { GlIcon } from '@gitlab/ui';
import { s__, __ } from '~/locale';
-import TimeTrackingHelpState from './help_state.vue';
+import eventHub from '../../event_hub';
import TimeTrackingCollapsedState from './collapsed_state.vue';
-import TimeTrackingSpentOnlyPane from './spent_only_pane.vue';
import TimeTrackingComparisonPane from './comparison_pane.vue';
-
-import eventHub from '../../event_hub';
+import TimeTrackingHelpState from './help_state.vue';
+import TimeTrackingSpentOnlyPane from './spent_only_pane.vue';
export default {
name: 'IssuableTimeTracker',
@@ -48,11 +47,11 @@ export default {
/*
In issue list, "time-tracking-collapsed-state" is always rendered even if the sidebar isn't collapsed.
The actual hiding is controlled with css classes:
- Hide "time-tracking-collapsed-state"
+ Hide "time-tracking-collapsed-state"
if .right-sidebar .right-sidebar-collapsed .sidebar-collapsed-icon
Show "time-tracking-collapsed-state"
if .right-sidebar .right-sidebar-expanded .sidebar-collapsed-icon
-
+
In Swimlanes sidebar, we do not use collapsed state at all.
*/
showCollapsed: {
@@ -99,10 +98,12 @@ export default {
update(data) {
const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent } = data;
+ /* eslint-disable vue/no-mutating-props */
this.timeEstimate = timeEstimate;
this.timeSpent = timeSpent;
this.humanTimeEstimate = humanTimeEstimate;
this.humanTimeSpent = humanTimeSpent;
+ /* eslint-enable vue/no-mutating-props */
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
index 1e3e870ec83..f589e7555b3 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
@@ -3,7 +3,7 @@ import { GlLoadingIcon, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
const MARK_TEXT = __('Mark as done');
-const TODO_TEXT = __('Add a To-Do');
+const TODO_TEXT = __('Add a to do');
export default {
components: {
@@ -42,7 +42,7 @@ export default {
buttonClasses() {
return this.collapsed
? 'btn-blank btn-todo sidebar-collapsed-icon dont-change-state'
- : 'btn btn-default btn-todo issuable-header-btn float-right';
+ : 'gl-button btn btn-default btn-todo issuable-header-btn float-right';
},
buttonLabel() {
return this.isTodo ? MARK_TEXT : TODO_TEXT;
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
new file mode 100644
index 00000000000..274aa237aea
--- /dev/null
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -0,0 +1,16 @@
+import { IssuableType } from '~/issue_show/constants';
+import getIssueParticipants from '~/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql';
+import getMergeRequestParticipants from '~/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql';
+import updateAssigneesMutation from '~/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql';
+import updateMergeRequestParticipantsMutation from '~/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql';
+
+export const assigneesQueries = {
+ [IssuableType.Issue]: {
+ query: getIssueParticipants,
+ mutation: updateAssigneesMutation,
+ },
+ [IssuableType.MergeRequest]: {
+ query: getMergeRequestParticipants,
+ mutation: updateMergeRequestParticipantsMutation,
+ },
+};
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index 55847fc43f0..21cd24b0842 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { escape } from 'lodash';
-import { __ } from '~/locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from '~/locale';
function isValidProjectId(id) {
return id > 0;
diff --git a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
index 4d9e99941d1..b11c8f76a6d 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import timeTracker from './components/time_tracking/time_tracker.vue';
import { parseBoolean } from '~/lib/utils/common_utils';
+import timeTracker from './components/time_tracking/time_tracker.vue';
export default class SidebarMilestone {
constructor() {
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 2760bf431ea..662edbc4f8d 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -1,22 +1,27 @@
import $ from 'jquery';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import SidebarTimeTracking from './components/time_tracking/sidebar_time_tracking.vue';
+import createFlash from '~/flash';
+import createDefaultClient from '~/lib/graphql';
+import {
+ isInIssuePage,
+ isInDesignPage,
+ isInIncidentPage,
+ parseBoolean,
+} from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import Translate from '../vue_shared/translate';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
-import SidebarLabels from './components/labels/sidebar_labels.vue';
-import SidebarReviewers from './components/reviewers/sidebar_reviewers.vue';
import ConfidentialIssueSidebar from './components/confidential/confidential_issue_sidebar.vue';
-import SidebarMoveIssue from './lib/sidebar_move_issue';
+import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
+import SidebarLabels from './components/labels/sidebar_labels.vue';
import IssuableLockForm from './components/lock/issuable_lock_form.vue';
import sidebarParticipants from './components/participants/sidebar_participants.vue';
-import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.vue';
+import SidebarReviewers from './components/reviewers/sidebar_reviewers.vue';
import SidebarSeverity from './components/severity/sidebar_severity.vue';
-import Translate from '../vue_shared/translate';
-import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
-import createDefaultClient from '~/lib/graphql';
-import { isInIssuePage, isInIncidentPage, parseBoolean } from '~/lib/utils/common_utils';
-import createFlash from '~/flash';
-import { __ } from '~/locale';
+import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.vue';
+import SidebarTimeTracking from './components/time_tracking/sidebar_time_tracking.vue';
+import SidebarMoveIssue from './lib/sidebar_move_issue';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -25,6 +30,28 @@ function getSidebarOptions(sidebarOptEl = document.querySelector('.js-sidebar-op
return JSON.parse(sidebarOptEl.innerHTML);
}
+/**
+ * Extracts the list of assignees with availability information from a hidden input
+ * field and converts to a key:value pair for use in the sidebar assignees component.
+ * The assignee username is used as the key and their busy status is the value
+ *
+ * e.g { root: 'busy', admin: '' }
+ *
+ * @returns {Object}
+ */
+function getSidebarAssigneeAvailabilityData() {
+ const sidebarAssigneeEl = document.querySelectorAll('.js-sidebar-assignee-data input');
+ return Array.from(sidebarAssigneeEl)
+ .map((el) => el.dataset)
+ .reduce(
+ (acc, { username, availability = '' }) => ({
+ ...acc,
+ [username]: availability,
+ }),
+ {},
+ );
+}
+
function mountAssigneesComponent(mediator) {
const el = document.getElementById('js-vue-sidebar-assignees');
const apolloProvider = new VueApollo({
@@ -34,6 +61,7 @@ function mountAssigneesComponent(mediator) {
if (!el) return;
const { iid, fullPath } = getSidebarOptions();
+ const assigneeAvailabilityStatus = getSidebarAssigneeAvailabilityData();
// eslint-disable-next-line no-new
new Vue({
el,
@@ -49,7 +77,9 @@ function mountAssigneesComponent(mediator) {
projectPath: fullPath,
field: el.dataset.field,
signedIn: el.hasAttribute('data-signed-in'),
- issuableType: isInIssuePage() || isInIncidentPage() ? 'issue' : 'merge_request',
+ issuableType:
+ isInIssuePage() || isInIncidentPage() || isInDesignPage() ? 'issue' : 'merge_request',
+ assigneeAvailabilityStatus,
},
}),
});
@@ -78,7 +108,7 @@ function mountReviewersComponent(mediator) {
issuableIid: String(iid),
projectPath: fullPath,
field: el.dataset.field,
- issuableType: isInIssuePage() ? 'issue' : 'merge_request',
+ issuableType: isInIssuePage() || isInDesignPage() ? 'issue' : 'merge_request',
},
}),
});
diff --git a/app/assets/javascripts/sidebar/queries/reviewer_rereview.mutation.graphql b/app/assets/javascripts/sidebar/queries/reviewer_rereview.mutation.graphql
new file mode 100644
index 00000000000..73765e7d77b
--- /dev/null
+++ b/app/assets/javascripts/sidebar/queries/reviewer_rereview.mutation.graphql
@@ -0,0 +1,5 @@
+mutation mergeRequestRequestRereview($projectPath: ID!, $iid: String!, $userId: ID!) {
+ mergeRequestReviewerRereview(input: { projectPath: $projectPath, iid: $iid, userId: $userId }) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index a61af631661..f31e4a3e0dd 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -1,6 +1,8 @@
import sidebarDetailsQuery from 'ee_else_ce/sidebar/queries/sidebarDetails.query.graphql';
-import axios from '~/lib/utils/axios_utils';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
+import axios from '~/lib/utils/axios_utils';
+import reviewerRereviewMutation from '../queries/reviewer_rereview.mutation.graphql';
export const gqClient = createGqClient(
{},
@@ -70,4 +72,15 @@ export default class SidebarService {
move_to_project_id: moveToProjectId,
});
}
+
+ requestReview(userId) {
+ return gqClient.mutate({
+ mutation: reviewerRereviewMutation,
+ variables: {
+ userId: convertToGraphQLId('User', `${userId}`), // eslint-disable-line @gitlab/require-i18n-strings
+ projectPath: this.fullPath,
+ iid: this.iid.toString(),
+ },
+ });
+ }
}
diff --git a/app/assets/javascripts/sidebar/sidebar_bundle.js b/app/assets/javascripts/sidebar/sidebar_bundle.js
index 377846db70e..063e3313a3c 100644
--- a/app/assets/javascripts/sidebar/sidebar_bundle.js
+++ b/app/assets/javascripts/sidebar/sidebar_bundle.js
@@ -1,5 +1,5 @@
-import Mediator from './sidebar_mediator';
import { mountSidebar, getSidebarOptions } from './mount_sidebar';
+import Mediator from './sidebar_mediator';
export default () => {
const mediator = new Mediator(getSidebarOptions());
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index d143283653b..bd382ed0fdb 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -1,8 +1,9 @@
import Store from 'ee_else_ce/sidebar/stores/sidebar_store';
-import { visitUrl } from '../lib/utils/url_utility';
+import { __ } from '~/locale';
+import toast from '~/vue_shared/plugins/global_toast';
import { deprecatedCreateFlash as Flash } from '../flash';
+import { visitUrl } from '../lib/utils/url_utility';
import Service from './services/sidebar_service';
-import { __ } from '~/locale';
export default class SidebarMediator {
constructor(options) {
@@ -51,6 +52,17 @@ export default class SidebarMediator {
return this.service.update(field, data);
}
+ requestReview({ userId, callback }) {
+ return this.service
+ .requestReview(userId)
+ .then(() => {
+ this.store.updateReviewer(userId);
+ toast(__('Requested review'));
+ callback(userId, true);
+ })
+ .catch(() => callback(userId, false));
+ }
+
setMoveToProjectId(projectId) {
this.store.setMoveToProjectId(projectId);
}
diff --git a/app/assets/javascripts/sidebar/stores/sidebar_store.js b/app/assets/javascripts/sidebar/stores/sidebar_store.js
index d53393052eb..3c108b06eab 100644
--- a/app/assets/javascripts/sidebar/stores/sidebar_store.js
+++ b/app/assets/javascripts/sidebar/stores/sidebar_store.js
@@ -96,6 +96,14 @@ export default class SidebarStore {
}
}
+ updateReviewer(id) {
+ const reviewer = this.findReviewer({ id });
+
+ if (reviewer) {
+ reviewer.reviewed = false;
+ }
+ }
+
findAssignee(findAssignee) {
return this.assignees.find(({ id }) => id === findAssignee.id);
}
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index 192eb0784d4..687289b6675 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -1,13 +1,13 @@
/* eslint-disable consistent-return */
import $ from 'jquery';
-import { __ } from './locale';
-import axios from './lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from './flash';
+import { spriteIcon } from '~/lib/utils/common_utils';
import FilesCommentButton from './files_comment_button';
+import { deprecatedCreateFlash as createFlash } from './flash';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
+import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
import syntaxHighlight from './syntax_highlight';
-import { spriteIcon } from '~/lib/utils/common_utils';
const WRAPPER = '<div class="diff-content"></div>';
const LOADING_HTML = '<span class="spinner"></span>';
diff --git a/app/assets/javascripts/snippet/snippet_edit.js b/app/assets/javascripts/snippet/snippet_edit.js
index 88677ddd15f..4fbd0b987fe 100644
--- a/app/assets/javascripts/snippet/snippet_edit.js
+++ b/app/assets/javascripts/snippet/snippet_edit.js
@@ -1,6 +1,6 @@
-import ZenMode from '~/zen_mode';
-import SnippetsEdit from '~/snippets/components/edit.vue';
import SnippetsAppFactory from '~/snippets';
+import SnippetsEdit from '~/snippets/components/edit.vue';
+import ZenMode from '~/zen_mode';
SnippetsAppFactory(document.getElementById('js-snippet-edit'), SnippetsEdit);
new ZenMode(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/snippet/snippet_show.js b/app/assets/javascripts/snippet/snippet_show.js
index caa76fc9988..22dffa90cef 100644
--- a/app/assets/javascripts/snippet/snippet_show.js
+++ b/app/assets/javascripts/snippet/snippet_show.js
@@ -1,7 +1,7 @@
-import initNotes from '~/init_notes';
import loadAwardsHandler from '~/awards_handler';
-import SnippetsShow from '~/snippets/components/show.vue';
+import initNotes from '~/init_notes';
import SnippetsAppFactory from '~/snippets';
+import SnippetsShow from '~/snippets/components/show.vue';
import ZenMode from '~/zen_mode';
SnippetsAppFactory(document.getElementById('js-snippet-view'), SnippetsShow);
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index ffb5e242973..9f43ac36df7 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -1,27 +1,28 @@
<script>
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import eventHub from '~/blob/components/eventhub';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import { __, sprintf } from '~/locale';
-import TitleField from '~/vue_shared/components/form/title.vue';
import { redirectTo, joinPaths } from '~/lib/utils/url_utility';
-import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import { __, sprintf } from '~/locale';
import {
SNIPPET_MARK_EDIT_APP_START,
SNIPPET_MEASURE_BLOBS_CONTENT,
} from '~/performance/constants';
-import eventHub from '~/blob/components/eventhub';
import { performanceMarkAndMeasure } from '~/performance/utils';
+import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import TitleField from '~/vue_shared/components/form/title.vue';
-import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
-import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
-import { getSnippetMixin } from '../mixins/snippets';
import { SNIPPET_CREATE_MUTATION_ERROR, SNIPPET_UPDATE_MUTATION_ERROR } from '../constants';
+import { getSnippetMixin } from '../mixins/snippets';
+import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
+import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
import { markBlobPerformance } from '../utils/blob';
+import { getErrorMessage } from '../utils/error';
import SnippetBlobActionsEdit from './snippet_blob_actions_edit.vue';
-import SnippetVisibilityEdit from './snippet_visibility_edit.vue';
import SnippetDescriptionEdit from './snippet_description_edit.vue';
+import SnippetVisibilityEdit from './snippet_visibility_edit.vue';
eventHub.$on(SNIPPET_MEASURE_BLOBS_CONTENT, markBlobPerformance);
@@ -32,6 +33,7 @@ export default {
SnippetBlobActionsEdit,
TitleField,
FormFooterActions,
+ CaptchaModal: () => import('~/captcha/captcha_modal.vue'),
GlButton,
GlLoadingIcon,
},
@@ -66,12 +68,25 @@ export default {
description: '',
visibilityLevel: this.selectedLevel,
},
+ captchaResponse: '',
+ needsCaptchaResponse: false,
+ captchaSiteKey: '',
+ spamLogId: '',
};
},
computed: {
hasBlobChanges() {
return this.actions.length > 0;
},
+ hasNoChanges() {
+ return (
+ this.actions.every(
+ (action) => !action.content && !action.filePath && !action.previousPath,
+ ) &&
+ !this.snippet.title &&
+ !this.snippet.description
+ );
+ },
hasValidBlobs() {
return this.actions.every((x) => x.content);
},
@@ -88,6 +103,8 @@ export default {
description: this.snippet.description,
visibilityLevel: this.snippet.visibilityLevel,
blobActions: this.actions,
+ ...(this.spamLogId && { spamLogId: this.spamLogId }),
+ ...(this.captchaResponse && { captchaResponse: this.captchaResponse }),
};
},
saveButtonLabel() {
@@ -116,7 +133,7 @@ export default {
onBeforeUnload(e = {}) {
const returnValue = __('Are you sure you want to lose unsaved changes?');
- if (!this.hasBlobChanges || this.isUpdating) return undefined;
+ if (!this.hasBlobChanges || this.hasNoChanges || this.isUpdating) return undefined;
Object.assign(e, { returnValue });
return returnValue;
@@ -159,6 +176,13 @@ export default {
.then(({ data }) => {
const baseObj = this.newSnippet ? data?.createSnippet : data?.updateSnippet;
+ if (baseObj.needsCaptchaResponse) {
+ // If we need a captcha response, start process for receiving captcha response.
+ // We will resubmit after the response is obtained.
+ this.requestCaptchaResponse(baseObj.captchaSiteKey, baseObj.spamLogId);
+ return;
+ }
+
const errors = baseObj?.errors;
if (errors.length) {
this.flashAPIFailure(errors[0]);
@@ -167,12 +191,44 @@ export default {
}
})
.catch((e) => {
- this.flashAPIFailure(e);
+ // eslint-disable-next-line no-console
+ console.error('[gitlab] unexpected error while updating snippet', e);
+
+ this.flashAPIFailure(getErrorMessage(e));
});
},
updateActions(actions) {
this.actions = actions;
},
+ /**
+ * Start process for getting captcha response from user
+ *
+ * @param captchaSiteKey Stored in data and used to display the captcha.
+ * @param spamLogId Stored in data and included when the form is re-submitted.
+ */
+ requestCaptchaResponse(captchaSiteKey, spamLogId) {
+ this.captchaSiteKey = captchaSiteKey;
+ this.spamLogId = spamLogId;
+ this.needsCaptchaResponse = true;
+ },
+ /**
+ * Handle the captcha response from the user
+ *
+ * @param captchaResponse The captchaResponse value emitted from the modal.
+ */
+ receivedCaptchaResponse(captchaResponse) {
+ this.needsCaptchaResponse = false;
+ this.captchaResponse = captchaResponse;
+
+ if (this.captchaResponse) {
+ // If the user solved the captcha resubmit the form.
+ this.handleFormSubmit();
+ } else {
+ // If the user didn't solve the captcha (e.g. they just closed the modal),
+ // finish the update and allow them to continue editing or manually resubmit the form.
+ this.isUpdating = false;
+ }
+ },
},
};
</script>
@@ -190,6 +246,11 @@ export default {
class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
+ <captcha-modal
+ :captcha-site-key="captchaSiteKey"
+ :needs-captcha-response="needsCaptchaResponse"
+ @receivedCaptchaResponse="receivedCaptchaResponse"
+ />
<title-field
id="snippet-title"
v-model="snippet.title"
diff --git a/app/assets/javascripts/snippets/components/embed_dropdown.vue b/app/assets/javascripts/snippets/components/embed_dropdown.vue
index a5d2c337d67..f6c9c569b5f 100644
--- a/app/assets/javascripts/snippets/components/embed_dropdown.vue
+++ b/app/assets/javascripts/snippets/components/embed_dropdown.vue
@@ -1,5 +1,4 @@
<script>
-import { escape as esc } from 'lodash';
import {
GlButton,
GlDropdown,
@@ -8,6 +7,7 @@ import {
GlFormInputGroup,
GlTooltipDirective,
} from '@gitlab/ui';
+import { escape as esc } from 'lodash';
import { __ } from '~/locale';
const MSG_EMBED = __('Embed');
diff --git a/app/assets/javascripts/snippets/components/show.vue b/app/assets/javascripts/snippets/components/show.vue
index a3e5535c5fa..46629a569ec 100644
--- a/app/assets/javascripts/snippets/components/show.vue
+++ b/app/assets/javascripts/snippets/components/show.vue
@@ -1,20 +1,20 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import EmbedDropdown from './embed_dropdown.vue';
-import SnippetHeader from './snippet_header.vue';
-import SnippetTitle from './snippet_title.vue';
-import SnippetBlob from './snippet_blob_view.vue';
-import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
-import { SNIPPET_VISIBILITY_PUBLIC } from '~/snippets/constants';
+import eventHub from '~/blob/components/eventhub';
import {
SNIPPET_MARK_VIEW_APP_START,
SNIPPET_MEASURE_BLOBS_CONTENT,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
-import eventHub from '~/blob/components/eventhub';
+import { SNIPPET_VISIBILITY_PUBLIC } from '~/snippets/constants';
+import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
import { getSnippetMixin } from '../mixins/snippets';
import { markBlobPerformance } from '../utils/blob';
+import EmbedDropdown from './embed_dropdown.vue';
+import SnippetBlob from './snippet_blob_view.vue';
+import SnippetHeader from './snippet_header.vue';
+import SnippetTitle from './snippet_title.vue';
eventHub.$on(SNIPPET_MEASURE_BLOBS_CONTENT, markBlobPerformance);
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
index ff27c90a84d..d221195ddc7 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_actions_edit.vue
@@ -2,9 +2,9 @@
import { GlButton } from '@gitlab/ui';
import { cloneDeep } from 'lodash';
import { s__, sprintf } from '~/locale';
-import SnippetBlobEdit from './snippet_blob_edit.vue';
import { SNIPPET_MAX_BLOBS } from '../constants';
import { createBlob, decorateBlob, diffAll } from '../utils/blob';
+import SnippetBlobEdit from './snippet_blob_edit.vue';
export default {
components: {
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
index c8545e334a6..4fb27397039 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
@@ -1,12 +1,12 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
-import { getBaseURL, joinPaths } from '~/lib/utils/url_utility';
-import axios from '~/lib/utils/axios_utils';
-import { SNIPPET_BLOB_CONTENT_FETCH_ERROR } from '~/snippets/constants';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { getBaseURL, joinPaths } from '~/lib/utils/url_utility';
import { sprintf } from '~/locale';
+import { SNIPPET_BLOB_CONTENT_FETCH_ERROR } from '~/snippets/constants';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
export default {
components: {
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_view.vue b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
index 4326c3c3159..27b3a30b40a 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
@@ -1,8 +1,8 @@
<script>
import GetBlobContent from 'shared_queries/snippet/snippet_blob_content.query.graphql';
-import BlobHeader from '~/blob/components/blob_header.vue';
import BlobContent from '~/blob/components/blob_content.vue';
+import BlobHeader from '~/blob/components/blob_header.vue';
import {
SIMPLE_BLOB_VIEWER,
@@ -31,8 +31,10 @@ export default {
},
result() {
if (this.activeViewerType === RICH_BLOB_VIEWER) {
+ // eslint-disable-next-line vue/no-mutating-props
this.blob.richViewer.renderError = null;
} else {
+ // eslint-disable-next-line vue/no-mutating-props
this.blob.simpleViewer.renderError = null;
}
},
diff --git a/app/assets/javascripts/snippets/components/snippet_description_edit.vue b/app/assets/javascripts/snippets/components/snippet_description_edit.vue
index 5e6caf27bdd..bac423f6838 100644
--- a/app/assets/javascripts/snippets/components/snippet_description_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_description_edit.vue
@@ -1,7 +1,7 @@
<script>
import { GlFormInput } from '@gitlab/ui';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import setupCollapsibleInputs from '~/snippet/collapsible_input';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
export default {
components: {
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index 5ba62908b43..bf19b63650e 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -11,14 +11,14 @@ import {
GlButton,
GlTooltipDirective,
} from '@gitlab/ui';
-import CanCreatePersonalSnippet from 'shared_queries/snippet/user_permissions.query.graphql';
import CanCreateProjectSnippet from 'shared_queries/snippet/project_permissions.query.graphql';
+import CanCreatePersonalSnippet from 'shared_queries/snippet/user_permissions.query.graphql';
+import { fetchPolicies } from '~/lib/graphql';
+import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DeleteSnippetMutation from '../mutations/deleteSnippet.mutation.graphql';
-import { joinPaths } from '~/lib/utils/url_utility';
-import { fetchPolicies } from '~/lib/graphql';
export default {
components: {
diff --git a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
index ee5076835ab..18a7d4ad218 100644
--- a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
-import { defaultSnippetVisibilityLevels } from '../utils/blob';
import { SNIPPET_LEVELS_RESTRICTED, SNIPPET_LEVELS_DISABLED } from '~/snippets/constants';
+import { defaultSnippetVisibilityLevels } from '../utils/blob';
export default {
components: {
diff --git a/app/assets/javascripts/snippets/index.js b/app/assets/javascripts/snippets/index.js
index 853ccb0c2fe..789332ce5b7 100644
--- a/app/assets/javascripts/snippets/index.js
+++ b/app/assets/javascripts/snippets/index.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import Translate from '~/vue_shared/translate';
import createDefaultClient from '~/lib/graphql';
import { SNIPPET_LEVELS_MAP, SNIPPET_VISIBILITY_PRIVATE } from '~/snippets/constants';
+import Translate from '~/vue_shared/translate';
Vue.use(VueApollo);
Vue.use(Translate);
diff --git a/app/assets/javascripts/snippets/mixins/snippets.js b/app/assets/javascripts/snippets/mixins/snippets.js
index 89a88958152..7552eae97fc 100644
--- a/app/assets/javascripts/snippets/mixins/snippets.js
+++ b/app/assets/javascripts/snippets/mixins/snippets.js
@@ -11,10 +11,14 @@ export const getSnippetMixin = {
ids: [this.snippetGid],
};
},
- update: (data) => {
+ update(data) {
const res = data.snippets.nodes[0];
+
+ // Set `snippet.blobs` since some child components are coupled to this.
if (res) {
- res.blobs = res.blobs.nodes;
+ // It's possible for us to not get any blobs in a response.
+ // In this case, we should default to current blobs.
+ res.blobs = res.blobs ? res.blobs.nodes : this.blobs;
}
return res;
diff --git a/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
index f688868d1b9..64d5d7c30fa 100644
--- a/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
+++ b/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
@@ -4,5 +4,7 @@ mutation CreateSnippet($input: CreateSnippetInput!) {
snippet {
webUrl
}
+ needsCaptchaResponse
+ captchaSiteKey
}
}
diff --git a/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
index 548725f7357..0a72f71b7c9 100644
--- a/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
+++ b/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
@@ -4,5 +4,8 @@ mutation UpdateSnippet($input: UpdateSnippetInput!) {
snippet {
webUrl
}
+ needsCaptchaResponse
+ captchaSiteKey
+ spamLogId
}
}
diff --git a/app/assets/javascripts/snippets/utils/blob.js b/app/assets/javascripts/snippets/utils/blob.js
index a47418323f2..2a3f590a803 100644
--- a/app/assets/javascripts/snippets/utils/blob.js
+++ b/app/assets/javascripts/snippets/utils/blob.js
@@ -1,4 +1,6 @@
import { uniqueId } from 'lodash';
+import { SNIPPET_MARK_BLOBS_CONTENT, SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
+import { performanceMarkAndMeasure } from '~/performance/utils';
import {
SNIPPET_BLOB_ACTION_CREATE,
SNIPPET_BLOB_ACTION_UPDATE,
@@ -7,8 +9,6 @@ import {
SNIPPET_LEVELS_MAP,
SNIPPET_VISIBILITY,
} from '../constants';
-import { performanceMarkAndMeasure } from '~/performance/utils';
-import { SNIPPET_MARK_BLOBS_CONTENT, SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
const createLocalId = () => uniqueId('blob_local_');
diff --git a/app/assets/javascripts/snippets/utils/error.js b/app/assets/javascripts/snippets/utils/error.js
new file mode 100644
index 00000000000..2d5c2a64038
--- /dev/null
+++ b/app/assets/javascripts/snippets/utils/error.js
@@ -0,0 +1,15 @@
+import { isString } from 'lodash';
+import { __ } from '~/locale';
+
+export const UNEXPECTED_ERROR = __('Unexpected error');
+
+export const getErrorMessage = (e) => {
+ if (!e) {
+ return UNEXPECTED_ERROR;
+ }
+ if (isString(e)) {
+ return e;
+ }
+
+ return e.message || e.networkError || UNEXPECTED_ERROR;
+};
diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js
index 232c97ecae0..eb3eaa66df5 100644
--- a/app/assets/javascripts/star.js
+++ b/app/assets/javascripts/star.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import { deprecatedCreateFlash as Flash } from './flash';
-import { __, s__ } from './locale';
-import { spriteIcon } from './lib/utils/common_utils';
import axios from './lib/utils/axios_utils';
+import { spriteIcon } from './lib/utils/common_utils';
+import { __, s__ } from './locale';
export default class Star {
constructor(container = '.project-home-panel') {
diff --git a/app/assets/javascripts/static_site_editor/components/edit_area.vue b/app/assets/javascripts/static_site_editor/components/edit_area.vue
index b47126cdeb3..a51a4f9f604 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_area.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_area.vue
@@ -1,15 +1,15 @@
<script>
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
-import PublishToolbar from './publish_toolbar.vue';
-import EditHeader from './edit_header.vue';
-import EditDrawer from './edit_drawer.vue';
-import UnsavedChangesConfirmDialog from './unsaved_changes_confirm_dialog.vue';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
+import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
import imageRepository from '../image_repository';
import formatter from '../services/formatter';
-import templater from '../services/templater';
import renderImage from '../services/renderers/render_image';
+import templater from '../services/templater';
+import EditDrawer from './edit_drawer.vue';
+import EditHeader from './edit_header.vue';
+import PublishToolbar from './publish_toolbar.vue';
+import UnsavedChangesConfirmDialog from './unsaved_changes_confirm_dialog.vue';
export default {
components: {
diff --git a/app/assets/javascripts/static_site_editor/components/edit_drawer.vue b/app/assets/javascripts/static_site_editor/components/edit_drawer.vue
index 0484d38dde0..0685dfdb1d1 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_drawer.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_drawer.vue
@@ -22,11 +22,6 @@ export default {
<template>
<gl-drawer class="gl-pt-8" :open="isOpen" @close="$emit('close')">
<template #header>{{ __('Page settings') }}</template>
- <template>
- <front-matter-controls
- :settings="settings"
- @updateSettings="$emit('updateSettings', $event)"
- />
- </template>
+ <front-matter-controls :settings="settings" @updateSettings="$emit('updateSettings', $event)" />
</gl-drawer>
</template>
diff --git a/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue b/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue
index f583d2049af..8c3ee7b9609 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue
@@ -1,12 +1,11 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { __, s__, sprintf } from '~/locale';
import Api from '~/api';
+import { __, s__, sprintf } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-import EditMetaControls from './edit_meta_controls.vue';
-
import { ISSUABLE_TYPE, MR_META_LOCAL_STORAGE_KEY } from '../constants';
+import EditMetaControls from './edit_meta_controls.vue';
export default {
components: {
diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js
index bce320ed805..23f800517c9 100644
--- a/app/assets/javascripts/static_site_editor/graphql/index.js
+++ b/app/assets/javascripts/static_site_editor/graphql/index.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import typeDefs from './typedefs.graphql';
import fileResolver from './resolvers/file';
-import submitContentChangesResolver from './resolvers/submit_content_changes';
import hasSubmittedChangesResolver from './resolvers/has_submitted_changes';
+import submitContentChangesResolver from './resolvers/submit_content_changes';
+import typeDefs from './typedefs.graphql';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/static_site_editor/image_repository.js b/app/assets/javascripts/static_site_editor/image_repository.js
index 56b2434d2e2..57f32ab4847 100644
--- a/app/assets/javascripts/static_site_editor/image_repository.js
+++ b/app/assets/javascripts/static_site_editor/image_repository.js
@@ -1,5 +1,5 @@
-import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
+import { __ } from '~/locale';
import { getBinary } from './services/image_service';
const imageRepository = () => {
diff --git a/app/assets/javascripts/static_site_editor/index.js b/app/assets/javascripts/static_site_editor/index.js
index fbb14be21ba..985579f68e8 100644
--- a/app/assets/javascripts/static_site_editor/index.js
+++ b/app/assets/javascripts/static_site_editor/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils';
import App from './components/app.vue';
-import createRouter from './router';
import createApolloProvider from './graphql';
+import createRouter from './router';
const initStaticSiteEditor = (el) => {
const {
diff --git a/app/assets/javascripts/static_site_editor/pages/home.vue b/app/assets/javascripts/static_site_editor/pages/home.vue
index 6c958cb2d22..22f80ead74b 100644
--- a/app/assets/javascripts/static_site_editor/pages/home.vue
+++ b/app/assets/javascripts/static_site_editor/pages/home.vue
@@ -2,16 +2,16 @@
import { deprecatedCreateFlash as createFlash } from '~/flash';
import Tracking from '~/tracking';
-import SkeletonLoader from '../components/skeleton_loader.vue';
import EditArea from '../components/edit_area.vue';
import EditMetaModal from '../components/edit_meta_modal.vue';
import InvalidContentMessage from '../components/invalid_content_message.vue';
+import SkeletonLoader from '../components/skeleton_loader.vue';
import SubmitChangesError from '../components/submit_changes_error.vue';
-import appDataQuery from '../graphql/queries/app_data.query.graphql';
-import sourceContentQuery from '../graphql/queries/source_content.query.graphql';
+import { LOAD_CONTENT_ERROR, TRACKING_ACTION_INITIALIZE_EDITOR } from '../constants';
import hasSubmittedChangesMutation from '../graphql/mutations/has_submitted_changes.mutation.graphql';
import submitContentChangesMutation from '../graphql/mutations/submit_content_changes.mutation.graphql';
-import { LOAD_CONTENT_ERROR, TRACKING_ACTION_INITIALIZE_EDITOR } from '../constants';
+import appDataQuery from '../graphql/queries/app_data.query.graphql';
+import sourceContentQuery from '../graphql/queries/source_content.query.graphql';
import { SUCCESS_ROUTE } from '../router/constants';
export default {
diff --git a/app/assets/javascripts/static_site_editor/pages/success.vue b/app/assets/javascripts/static_site_editor/pages/success.vue
index 1ee1a3b0edf..70e692a0c86 100644
--- a/app/assets/javascripts/static_site_editor/pages/success.vue
+++ b/app/assets/javascripts/static_site_editor/pages/success.vue
@@ -2,8 +2,8 @@
import { GlButton, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
-import savedContentMetaQuery from '../graphql/queries/saved_content_meta.query.graphql';
import appDataQuery from '../graphql/queries/app_data.query.graphql';
+import savedContentMetaQuery from '../graphql/queries/saved_content_meta.query.graphql';
import { HOME_ROUTE } from '../router/constants';
export default {
diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
index 84e90deacfc..6391cfd6cc2 100644
--- a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
+++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
@@ -1,7 +1,7 @@
import Api from '~/api';
-import Tracking from '~/tracking';
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
import generateBranchName from '~/static_site_editor/services/generate_branch_name';
+import Tracking from '~/tracking';
import {
DEFAULT_TARGET_BRANCH,
diff --git a/app/assets/javascripts/subscription_select.js b/app/assets/javascripts/subscription_select.js
index 354ee00a977..4a688d819b0 100644
--- a/app/assets/javascripts/subscription_select.js
+++ b/app/assets/javascripts/subscription_select.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import { __ } from './locale';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __ } from './locale';
export default function subscriptionSelect() {
$('.js-subscription-event').each((i, element) => {
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index 81d9d9d37a7..bc8a8e425dd 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import 'deckar01-task_list';
import { __ } from '~/locale';
-import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash } from './flash';
+import axios from './lib/utils/axios_utils';
export default class TaskList {
constructor(options = {}) {
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js b/app/assets/javascripts/templates/issuable_template_selector.js
index 22bbd083a5d..1bb5e214c2e 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js
+++ b/app/assets/javascripts/templates/issuable_template_selector.js
@@ -1,16 +1,15 @@
/* eslint-disable no-useless-return */
import $ from 'jquery';
+import { __ } from '~/locale';
import Api from '../api';
import TemplateSelector from '../blob/template_selector';
-import { __ } from '~/locale';
export default class IssuableTemplateSelector extends TemplateSelector {
constructor(...args) {
super(...args);
- this.projectPath = this.dropdown.data('projectPath');
- this.namespacePath = this.dropdown.data('namespacePath');
+ this.projectId = this.dropdown.data('projectId');
this.issuableType = this.$dropdownContainer.data('issuableType');
this.titleInput = $(`#${this.issuableType}_title`);
this.templateWarningEl = $('.js-issuable-template-warning');
@@ -81,21 +80,21 @@ export default class IssuableTemplateSelector extends TemplateSelector {
}
requestFile(query) {
+ const callback = (currentTemplate) => {
+ this.currentTemplate = currentTemplate;
+ this.stopLoadingSpinner();
+ this.setInputValueToTemplateContent();
+ };
+
this.startLoadingSpinner();
- Api.issueTemplate(
- this.namespacePath,
- this.projectPath,
- query.name,
+ Api.projectTemplate(
+ this.projectId,
this.issuableType,
- (err, currentTemplate) => {
- this.currentTemplate = currentTemplate;
- this.stopLoadingSpinner();
- if (err) return; // Error handled by global AJAX error handler
- this.setInputValueToTemplateContent();
- },
+ query.name,
+ { source_template_project_id: query.project_id },
+ callback,
);
- return;
}
setInputValueToTemplateContent() {
diff --git a/app/assets/javascripts/terminal/terminal.js b/app/assets/javascripts/terminal/terminal.js
index 26cc538994f..468f9b54ee0 100644
--- a/app/assets/javascripts/terminal/terminal.js
+++ b/app/assets/javascripts/terminal/terminal.js
@@ -1,5 +1,5 @@
-import { throttle } from 'lodash';
import $ from 'jquery';
+import { throttle } from 'lodash';
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
import * as webLinks from 'xterm/lib/addons/webLinks/webLinks';
diff --git a/app/assets/javascripts/terraform/components/states_table.vue b/app/assets/javascripts/terraform/components/states_table.vue
index d0d49233334..2577664a5e8 100644
--- a/app/assets/javascripts/terraform/components/states_table.vue
+++ b/app/assets/javascripts/terraform/components/states_table.vue
@@ -1,18 +1,29 @@
<script>
-import { GlBadge, GlIcon, GlLink, GlSprintf, GlTable, GlTooltip } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import {
+ GlAlert,
+ GlBadge,
+ GlIcon,
+ 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';
-import StateActions from './states_table_actions.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import StateActions from './states_table_actions.vue';
export default {
components: {
CiBadge,
+ GlAlert,
GlBadge,
GlIcon,
GlLink,
+ GlLoadingIcon,
GlSprintf,
GlTable,
GlTooltip,
@@ -66,15 +77,21 @@ export default {
jobStatus: s__('Terraform|Job status'),
locked: s__('Terraform|Locked'),
lockedByUser: s__('Terraform|Locked by %{user} %{timeAgo}'),
+ lockingState: s__('Terraform|Locking state'),
name: s__('Terraform|Name'),
pipeline: s__('Terraform|Pipeline'),
+ removing: s__('Terraform|Removing'),
unknownUser: s__('Terraform|Unknown User'),
+ unlockingState: s__('Terraform|Unlocking state'),
updatedUser: s__('Terraform|%{user} updated %{timeAgo}'),
},
methods: {
createdByUserName(item) {
return item.latestVersion?.createdByUser?.name;
},
+ loadingLockText(item) {
+ return item.lockedAt ? this.$options.i18n.unlockingState : this.$options.i18n.lockingState;
+ },
lockedByUserName(item) {
return item.lockedByUser?.name || this.$options.i18n.unknownUser;
},
@@ -105,6 +122,7 @@ export default {
:items="states"
:fields="fields"
data-testid="terraform-states-table"
+ details-td-class="gl-p-0!"
fixed
stacked="md"
>
@@ -117,7 +135,27 @@ export default {
{{ item.name }}
</p>
- <div v-if="item.lockedAt" :id="`terraformLockedBadgeContainer${item.name}`" class="gl-mx-2">
+ <div v-if="item.loadingLock" class="gl-mx-3">
+ <p class="gl-display-flex gl-justify-content-start gl-align-items-baseline gl-m-0">
+ <gl-loading-icon class="gl-pr-1" />
+ {{ loadingLockText(item) }}
+ </p>
+ </div>
+
+ <div v-else-if="item.loadingRemove" class="gl-mx-3">
+ <p
+ class="gl-display-flex gl-justify-content-start gl-align-items-baseline gl-m-0 gl-text-red-500"
+ >
+ <gl-loading-icon class="gl-pr-1" />
+ {{ $options.i18n.removing }}
+ </p>
+ </div>
+
+ <div
+ v-else-if="item.lockedAt"
+ :id="`terraformLockedBadgeContainer${item.name}`"
+ class="gl-mx-3"
+ >
<gl-badge :id="`terraformLockedBadge${item.name}`">
<gl-icon name="lock" />
{{ $options.i18n.locked }}
@@ -189,5 +227,21 @@ export default {
<template v-if="terraformAdmin" #cell(actions)="{ item }">
<state-actions :state="item" />
</template>
+
+ <template #row-details="row">
+ <gl-alert
+ data-testid="terraform-states-table-error"
+ variant="danger"
+ @dismiss="row.toggleDetails"
+ >
+ <span
+ v-for="errorMessage in row.item.errorMessages"
+ :key="errorMessage"
+ class="gl-display-flex gl-justify-content-start"
+ >
+ {{ errorMessage }}
+ </span>
+ </gl-alert>
+ </template>
</gl-table>
</template>
diff --git a/app/assets/javascripts/terraform/components/states_table_actions.vue b/app/assets/javascripts/terraform/components/states_table_actions.vue
index 44b0713e544..c4fd97188de 100644
--- a/app/assets/javascripts/terraform/components/states_table_actions.vue
+++ b/app/assets/javascripts/terraform/components/states_table_actions.vue
@@ -9,10 +9,11 @@ import {
GlModal,
GlSprintf,
} from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { s__, sprintf } from '~/locale';
+import addDataToState from '../graphql/mutations/add_data_to_state.mutation.graphql';
import lockState from '../graphql/mutations/lock_state.mutation.graphql';
-import unlockState from '../graphql/mutations/unlock_state.mutation.graphql';
import removeState from '../graphql/mutations/remove_state.mutation.graphql';
+import unlockState from '../graphql/mutations/unlock_state.mutation.graphql';
export default {
components: {
@@ -33,13 +34,13 @@ export default {
},
data() {
return {
- loading: false,
showRemoveModal: false,
removeConfirmText: '',
};
},
i18n: {
downloadJSON: s__('Terraform|Download JSON'),
+ errorUpdate: s__('Terraform|An error occurred while changing the state file'),
lock: s__('Terraform|Lock'),
modalBody: s__(
'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, only the state file with all its versions are to be removed. This action is non-revertible.',
@@ -51,6 +52,7 @@ export default {
),
modalRemove: s__('Terraform|Remove'),
remove: s__('Terraform|Remove state file and versions'),
+ removeSuccessful: s__('Terraform|%{name} successfully removed'),
unlock: s__('Terraform|Unlock'),
},
computed: {
@@ -63,6 +65,9 @@ export default {
disableModalSubmit() {
return this.removeConfirmText !== this.state.name;
},
+ loading() {
+ return this.state.loadingLock || this.state.loadingRemove;
+ },
primaryModalProps() {
return {
text: this.$options.i18n.modalRemove,
@@ -76,19 +81,56 @@ export default {
this.removeConfirmText = '';
},
lock() {
- this.stateMutation(lockState);
+ this.updateStateCache({
+ _showDetails: false,
+ errorMessages: [],
+ loadingLock: true,
+ loadingRemove: false,
+ });
+
+ this.stateActionMutation(lockState);
},
unlock() {
- this.stateMutation(unlockState);
+ this.updateStateCache({
+ _showDetails: false,
+ errorMessages: [],
+ loadingLock: true,
+ loadingRemove: false,
+ });
+
+ this.stateActionMutation(unlockState);
+ },
+ updateStateCache(newData) {
+ this.$apollo.mutate({
+ mutation: addDataToState,
+ variables: {
+ terraformState: {
+ ...this.state,
+ ...newData,
+ },
+ },
+ });
},
remove() {
if (!this.disableModalSubmit) {
this.hideModal();
- this.stateMutation(removeState);
+
+ this.updateStateCache({
+ _showDetails: false,
+ errorMessages: [],
+ loadingLock: false,
+ loadingRemove: true,
+ });
+
+ this.stateActionMutation(
+ removeState,
+ sprintf(this.$options.i18n.removeSuccessful, { name: this.state.name }),
+ );
}
},
- stateMutation(mutation) {
- this.loading = true;
+ stateActionMutation(mutation, successMessage = null) {
+ let errorMessages = [];
+
this.$apollo
.mutate({
mutation,
@@ -99,9 +141,27 @@ export default {
awaitRefetchQueries: true,
notifyOnNetworkStatusChange: true,
})
- .catch(() => {})
+ .then(({ data }) => {
+ errorMessages =
+ data?.terraformStateDelete?.errors ||
+ data?.terraformStateLock?.errors ||
+ data?.terraformStateUnlock?.errors ||
+ [];
+
+ if (errorMessages.length === 0 && successMessage) {
+ this.$toast.show(successMessage);
+ }
+ })
+ .catch(() => {
+ errorMessages = [this.$options.i18n.errorUpdate];
+ })
.finally(() => {
- this.loading = false;
+ this.updateStateCache({
+ _showDetails: Boolean(errorMessages.length),
+ errorMessages,
+ loadingLock: false,
+ loadingRemove: false,
+ });
});
},
},
diff --git a/app/assets/javascripts/terraform/components/terraform_list.vue b/app/assets/javascripts/terraform/components/terraform_list.vue
index b71133d8813..a18f33ebb1f 100644
--- a/app/assets/javascripts/terraform/components/terraform_list.vue
+++ b/app/assets/javascripts/terraform/components/terraform_list.vue
@@ -1,9 +1,9 @@
<script>
import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab, GlTabs } from '@gitlab/ui';
+import { MAX_LIST_COUNT } from '../constants';
import getStatesQuery from '../graphql/queries/get_states.query.graphql';
import EmptyState from './empty_state.vue';
import StatesTable from './states_table.vue';
-import { MAX_LIST_COUNT } from '../constants';
export default {
apollo: {
diff --git a/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql b/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql
index 49f9ae3dd97..fb823336411 100644
--- a/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql
+++ b/app/assets/javascripts/terraform/graphql/fragments/state.fragment.graphql
@@ -2,6 +2,11 @@
#import "./state_version.fragment.graphql"
fragment State on TerraformState {
+ _showDetails @client
+ errorMessages @client
+ loadingLock @client
+ loadingRemove @client
+
id
name
lockedAt
diff --git a/app/assets/javascripts/terraform/graphql/mutations/add_data_to_state.mutation.graphql b/app/assets/javascripts/terraform/graphql/mutations/add_data_to_state.mutation.graphql
new file mode 100644
index 00000000000..645b9766e2b
--- /dev/null
+++ b/app/assets/javascripts/terraform/graphql/mutations/add_data_to_state.mutation.graphql
@@ -0,0 +1,3 @@
+mutation addDataToTerraformState($terraformState: State!) {
+ addDataToTerraformState(terraformState: $terraformState) @client
+}
diff --git a/app/assets/javascripts/terraform/graphql/resolvers.js b/app/assets/javascripts/terraform/graphql/resolvers.js
new file mode 100644
index 00000000000..d27379bdd9f
--- /dev/null
+++ b/app/assets/javascripts/terraform/graphql/resolvers.js
@@ -0,0 +1,45 @@
+import TerraformState from './fragments/state.fragment.graphql';
+
+export default {
+ TerraformState: {
+ _showDetails: (state) => {
+ // eslint-disable-next-line no-underscore-dangle
+ return state._showDetails || false;
+ },
+ errorMessages: (state) => {
+ return state.errorMessages || [];
+ },
+ loadingLock: (state) => {
+ return state.loadingLock || false;
+ },
+ loadingRemove: (state) => {
+ return state.loadingRemove || false;
+ },
+ },
+ Mutation: {
+ addDataToTerraformState: (_, { terraformState }, { client }) => {
+ const fragmentData = {
+ id: terraformState.id,
+ fragment: TerraformState,
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ fragmentName: 'State',
+ };
+
+ const previousTerraformState = client.readFragment(fragmentData);
+
+ if (previousTerraformState) {
+ client.writeFragment({
+ ...fragmentData,
+ data: {
+ ...previousTerraformState,
+ // eslint-disable-next-line no-underscore-dangle
+ _showDetails: terraformState._showDetails,
+ errorMessages: terraformState.errorMessages,
+ loadingLock: terraformState.loadingLock,
+ loadingRemove: terraformState.loadingRemove,
+ },
+ });
+ }
+ },
+ },
+};
diff --git a/app/assets/javascripts/terraform/index.js b/app/assets/javascripts/terraform/index.js
index e27a29433f3..3f986423836 100644
--- a/app/assets/javascripts/terraform/index.js
+++ b/app/assets/javascripts/terraform/index.js
@@ -1,8 +1,12 @@
+import { GlToast } from '@gitlab/ui';
+import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import TerraformList from './components/terraform_list.vue';
import createDefaultClient from '~/lib/graphql';
+import TerraformList from './components/terraform_list.vue';
+import resolvers from './graphql/resolvers';
+Vue.use(GlToast);
Vue.use(VueApollo);
export default () => {
@@ -12,7 +16,13 @@ export default () => {
return null;
}
- const defaultClient = createDefaultClient();
+ const defaultClient = createDefaultClient(resolvers, {
+ cacheConfig: {
+ dataIdFromObject: (object) => {
+ return object.id || defaultDataIdFromObject(object);
+ },
+ },
+ });
const { emptyStateImage, projectPath } = el.dataset;
diff --git a/app/assets/javascripts/toggle_buttons.js b/app/assets/javascripts/toggle_buttons.js
index 2f933823842..03c975d5fe8 100644
--- a/app/assets/javascripts/toggle_buttons.js
+++ b/app/assets/javascripts/toggle_buttons.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { deprecatedCreateFlash as Flash } from './flash';
-import { __ } from './locale';
import { parseBoolean } from './lib/utils/common_utils';
+import { __ } from './locale';
/*
example HAML:
diff --git a/app/assets/javascripts/tooltips/index.js b/app/assets/javascripts/tooltips/index.js
index b216affc818..a9978c03a6e 100644
--- a/app/assets/javascripts/tooltips/index.js
+++ b/app/assets/javascripts/tooltips/index.js
@@ -1,6 +1,5 @@
+import { toArray, isElement } from 'lodash';
import Vue from 'vue';
-import jQuery from 'jquery';
-import { toArray, isFunction, isElement } from 'lodash';
import Tooltips from './components/tooltips.vue';
let app;
@@ -60,72 +59,39 @@ const applyToElements = (elements, handler) => {
toArray(iterable).forEach(handler);
};
-const invokeBootstrapApi = (elements, method) => {
- if (isFunction(elements.tooltip)) {
- elements.tooltip(method);
- } else {
- jQuery(elements).tooltip(method);
- }
-};
-
-const isGlTooltipsEnabled = () => Boolean(window.gon.features?.glTooltips);
-
-const tooltipApiInvoker = ({ glHandler, bsHandler }) => (elements, ...params) => {
- if (isGlTooltipsEnabled()) {
- applyToElements(elements, glHandler);
- } else {
- bsHandler(elements, ...params);
- }
+const createTooltipApiInvoker = (glHandler) => (elements) => {
+ applyToElements(elements, glHandler);
};
export const initTooltips = (config = {}) => {
- if (isGlTooltipsEnabled()) {
- const triggers = config?.triggers || DEFAULT_TRIGGER;
- const events = triggers.split(' ').map((trigger) => EVENTS_MAP[trigger]);
-
- events.forEach((event) => {
- document.addEventListener(
- event,
- (e) => handleTooltipEvent(document, e, config.selector, config),
- true,
- );
- });
-
- return tooltipsApp();
- }
-
- return invokeBootstrapApi(document.body, config);
-};
-export const add = (elements, config = {}) => {
- if (isGlTooltipsEnabled()) {
- return addTooltips(elements, config);
- }
- return invokeBootstrapApi(elements, config);
+ const triggers = config?.triggers || DEFAULT_TRIGGER;
+ const events = triggers.split(' ').map((trigger) => EVENTS_MAP[trigger]);
+
+ events.forEach((event) => {
+ document.addEventListener(
+ event,
+ (e) => handleTooltipEvent(document, e, config.selector, config),
+ true,
+ );
+ });
+
+ return tooltipsApp();
};
-export const dispose = tooltipApiInvoker({
- glHandler: (element) => tooltipsApp().dispose(element),
- bsHandler: (elements) => invokeBootstrapApi(elements, 'dispose'),
-});
-export const fixTitle = tooltipApiInvoker({
- glHandler: (element) => tooltipsApp().fixTitle(element),
- bsHandler: (elements) => invokeBootstrapApi(elements, '_fixTitle'),
-});
-export const enable = tooltipApiInvoker({
- glHandler: (element) => tooltipsApp().triggerEvent(element, 'enable'),
- bsHandler: (elements) => invokeBootstrapApi(elements, 'enable'),
-});
-export const disable = tooltipApiInvoker({
- glHandler: (element) => tooltipsApp().triggerEvent(element, 'disable'),
- bsHandler: (elements) => invokeBootstrapApi(elements, 'disable'),
-});
-export const hide = tooltipApiInvoker({
- glHandler: (element) => tooltipsApp().triggerEvent(element, 'close'),
- bsHandler: (elements) => invokeBootstrapApi(elements, 'hide'),
-});
-export const show = tooltipApiInvoker({
- glHandler: (element) => tooltipsApp().triggerEvent(element, 'open'),
- bsHandler: (elements) => invokeBootstrapApi(elements, 'show'),
-});
+export const add = (elements, config = {}) => addTooltips(elements, config);
+export const dispose = createTooltipApiInvoker((element) => tooltipsApp().dispose(element));
+export const fixTitle = createTooltipApiInvoker((element) => tooltipsApp().fixTitle(element));
+export const enable = createTooltipApiInvoker((element) =>
+ tooltipsApp().triggerEvent(element, 'enable'),
+);
+export const disable = createTooltipApiInvoker((element) =>
+ tooltipsApp().triggerEvent(element, 'disable'),
+);
+export const hide = createTooltipApiInvoker((element) =>
+ tooltipsApp().triggerEvent(element, 'close'),
+);
+export const show = createTooltipApiInvoker((element) =>
+ tooltipsApp().triggerEvent(element, 'open'),
+);
export const destroy = () => {
tooltipsApp().$destroy();
app = null;
diff --git a/app/assets/javascripts/ui_development_kit.js b/app/assets/javascripts/ui_development_kit.js
index 028b047d9f5..1a3fd6c77ed 100644
--- a/app/assets/javascripts/ui_development_kit.js
+++ b/app/assets/javascripts/ui_development_kit.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import Api from './api';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import Api from './api';
export default () => {
initDeprecatedJQueryDropdown($('#js-project-dropdown'), {
diff --git a/app/assets/javascripts/usage_ping_consent.js b/app/assets/javascripts/usage_ping_consent.js
index 94d476d13ae..3876aa62b75 100644
--- a/app/assets/javascripts/usage_ping_consent.js
+++ b/app/assets/javascripts/usage_ping_consent.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash, hideFlash } from './flash';
+import axios from './lib/utils/axios_utils';
import { parseBoolean } from './lib/utils/common_utils';
import { __ } from './locale';
diff --git a/app/assets/javascripts/user_lists/components/edit_user_list.vue b/app/assets/javascripts/user_lists/components/edit_user_list.vue
index d56c3d61027..18f411f6cf2 100644
--- a/app/assets/javascripts/user_lists/components/edit_user_list.vue
+++ b/app/assets/javascripts/user_lists/components/edit_user_list.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { s__, sprintf } from '~/locale';
import statuses from '../constants/edit';
import UserListForm from './user_list_form.vue';
diff --git a/app/assets/javascripts/user_lists/components/new_user_list.vue b/app/assets/javascripts/user_lists/components/new_user_list.vue
index 522e077fb25..17ef4c037d2 100644
--- a/app/assets/javascripts/user_lists/components/new_user_list.vue
+++ b/app/assets/javascripts/user_lists/components/new_user_list.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapState } from 'vuex';
import { GlAlert } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import UserListForm from './user_list_form.vue';
diff --git a/app/assets/javascripts/user_lists/components/user_list.vue b/app/assets/javascripts/user_lists/components/user_list.vue
index 0e2b72c1423..e33a4b3ffb4 100644
--- a/app/assets/javascripts/user_lists/components/user_list.vue
+++ b/app/assets/javascripts/user_lists/components/user_list.vue
@@ -1,5 +1,4 @@
<script>
-import { mapActions, mapState } from 'vuex';
import {
GlAlert,
GlButton,
@@ -7,6 +6,7 @@ import {
GlLoadingIcon,
GlModalDirective as GlModal,
} from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
import { s__, __ } from '~/locale';
import { states, ADD_USER_MODAL_ID } from '../constants/show';
import AddUserModal from './add_user_modal.vue';
diff --git a/app/assets/javascripts/user_lists/store/edit/index.js b/app/assets/javascripts/user_lists/store/edit/index.js
index 3b19b2b12ec..9b9df59ed32 100644
--- a/app/assets/javascripts/user_lists/store/edit/index.js
+++ b/app/assets/javascripts/user_lists/store/edit/index.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
export default (initialState) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/user_lists/store/new/index.js b/app/assets/javascripts/user_lists/store/new/index.js
index 3b19b2b12ec..9b9df59ed32 100644
--- a/app/assets/javascripts/user_lists/store/new/index.js
+++ b/app/assets/javascripts/user_lists/store/new/index.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
export default (initialState) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/user_lists/store/show/index.js b/app/assets/javascripts/user_lists/store/show/index.js
index 3b19b2b12ec..9b9df59ed32 100644
--- a/app/assets/javascripts/user_lists/store/show/index.js
+++ b/app/assets/javascripts/user_lists/store/show/index.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
-import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
+import createState from './state';
export default (initialState) =>
new Vuex.Store({
diff --git a/app/assets/javascripts/user_lists/store/show/mutations.js b/app/assets/javascripts/user_lists/store/show/mutations.js
index 3cf3b2d8371..bb5f9abe79e 100644
--- a/app/assets/javascripts/user_lists/store/show/mutations.js
+++ b/app/assets/javascripts/user_lists/store/show/mutations.js
@@ -1,6 +1,6 @@
import { states } from '../../constants/show';
-import * as types from './mutation_types';
import { parseUserIds } from '../utils';
+import * as types from './mutation_types';
export default {
[types.REQUEST_USER_LIST](state) {
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index 79dc20fd498..e1a4a74b982 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -8,14 +8,15 @@ import {
AJAX_USERS_SELECT_OPTIONS_MAP,
AJAX_USERS_SELECT_PARAMS_MAP,
} from 'ee_else_ce/users_select/constants';
-import axios from '../lib/utils/axios_utils';
-import { s__, __, sprintf } from '../locale';
-import ModalStore from '../boards/stores/modal_store';
-import { parseBoolean, spriteIcon } from '../lib/utils/common_utils';
-import { getAjaxUsersSelectOptions, getAjaxUsersSelectParams } from './utils';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { isUserBusy } from '~/set_status_modal/utils';
import { fixTitle, dispose } from '~/tooltips';
+import ModalStore from '../boards/stores/modal_store';
+import axios from '../lib/utils/axios_utils';
+import { parseBoolean, spriteIcon } from '../lib/utils/common_utils';
import { loadCSSFile } from '../lib/utils/css_utils';
+import { s__, __, sprintf } from '../locale';
+import { getAjaxUsersSelectOptions, getAjaxUsersSelectParams } from './utils';
// TODO: remove eventHub hack after code splitting refactor
window.emitSidebarEvent = window.emitSidebarEvent || $.noop;
@@ -795,13 +796,17 @@ UsersSelect.prototype.renderRow = function (
? `data-container="body" data-placement="left" data-title="${tooltip}"`
: '';
+ const name =
+ user?.availability && isUserBusy(user.availability)
+ ? sprintf(__('%{name} (Busy)'), { name: user.name })
+ : user.name;
return `
<li data-user-id=${user.id}>
<a href="#" class="dropdown-menu-user-link d-flex align-items-center ${linkClasses}" ${tooltipAttributes}>
${this.renderRowAvatar(issuableType, user, img)}
<span class="d-flex flex-column overflow-hidden">
<strong class="dropdown-menu-user-full-name gl-font-weight-bold">
- ${escape(user.name)}
+ ${escape(name)}
</strong>
${
username
@@ -834,7 +839,7 @@ UsersSelect.prototype.renderRowAvatar = function (issuableType, user, img) {
UsersSelect.prototype.renderApprovalRules = function (elsClassName, approvalRules = []) {
const count = approvalRules.length;
- if (!gon.features?.reviewerApprovalRules || !elsClassName?.includes('reviewer') || !count) {
+ if (!elsClassName?.includes('reviewer') || !count) {
return '';
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
index 9b822657184..a5b83167283 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
@@ -1,6 +1,7 @@
<script>
import { GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../../event_hub';
import approvalsMixin from '../../mixins/approvals';
@@ -124,7 +125,7 @@ export default {
methods: {
approve() {
if (this.requirePasswordToApprove) {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
return;
}
@@ -158,6 +159,7 @@ export default {
.then((data) => {
this.mr.setApprovals(data);
eventHub.$emit('MRWidgetUpdateRequested');
+ eventHub.$emit('ApprovalUpdated');
this.$emit('updated');
})
.catch(errFn)
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
index fb342a5d340..ea73ab416de 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
@@ -1,8 +1,8 @@
<script>
-import { n__, sprintf } from '~/locale';
import { toNounSeriesText } from '~/lib/utils/grammar';
-import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
+import { n__, sprintf } from '~/locale';
import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages';
+import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
export default {
components: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/artifacts_list_app.vue b/app/assets/javascripts/vue_merge_request_widget/components/artifacts_list_app.vue
index 730e67761be..ebf42fa0be0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/artifacts_list_app.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/artifacts_list_app.vue
@@ -1,8 +1,8 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
+import createStore from '../stores/artifacts_list';
import ArtifactsList from './artifacts_list.vue';
import MrCollapsibleExtension from './mr_collapsible_extension.vue';
-import createStore from '../stores/artifacts_list';
export default {
store: createStore(),
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment.vue
index f497936e299..d79da9d3b90 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment.vue
@@ -1,7 +1,7 @@
<script>
+import { MANUAL_DEPLOY, WILL_DEPLOY, CREATED } from './constants';
import DeploymentActions from './deployment_actions.vue';
import DeploymentInfo from './deployment_info.vue';
-import { MANUAL_DEPLOY, WILL_DEPLOY, CREATED } from './constants';
export default {
// name: 'Deployment' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26#possible-false-positives
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 215df8acece..513d88ecab6 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,11 +1,9 @@
<script>
-import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
+import { __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MRWidgetService from '../../services/mr_widget_service';
-import DeploymentActionButton from './deployment_action_button.vue';
-import DeploymentViewButton from './deployment_view_button.vue';
import {
MANUAL_DEPLOY,
FAILED,
@@ -15,6 +13,8 @@ import {
REDEPLOYING,
ACT_BUTTON_ICONS,
} from './constants';
+import DeploymentActionButton from './deployment_action_button.vue';
+import DeploymentViewButton from './deployment_view_button.vue';
export default {
name: 'DeploymentActions',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
index 390469dec24..cbace1ad57c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
@@ -3,7 +3,6 @@ import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import MemoryUsage from './memory_usage.vue';
import {
MANUAL_DEPLOY,
WILL_DEPLOY,
@@ -13,6 +12,7 @@ import {
CANCELED,
SKIPPED,
} from './constants';
+import MemoryUsage from './memory_usage.vue';
export default {
name: 'DeploymentInfo',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
index 2f27216f2e9..410d2740e1d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
@@ -1,9 +1,9 @@
<script>
import { GlLoadingIcon, GlSprintf, GlLink } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { backOff } from '~/lib/utils/common_utils';
import statusCodes from '~/lib/utils/http_status';
import { bytesToMiB } from '~/lib/utils/number_utils';
-import { backOff } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import MemoryGraph from '~/vue_shared/components/memory_graph.vue';
import MRWidgetService from '../../services/mr_widget_service';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 6628ab7be83..71ff0fe6fbd 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -1,6 +1,5 @@
<script>
/* eslint-disable vue/no-v-html */
-import { escape } from 'lodash';
import {
GlButton,
GlDropdown,
@@ -9,12 +8,13 @@ import {
GlTooltipDirective,
GlModalDirective,
} from '@gitlab/ui';
-import { n__, s__, sprintf } from '~/locale';
+import { escape } from 'lodash';
import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility';
+import { n__, s__, sprintf } from '~/locale';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
-import MrWidgetIcon from './mr_widget_icon.vue';
import MrWidgetHowToMergeModal from './mr_widget_how_to_merge_modal.vue';
+import MrWidgetIcon from './mr_widget_icon.vue';
export default {
name: 'MRWidgetHeader',
@@ -133,14 +133,12 @@ export default {
v-gl-tooltip
:title="ideButtonTitle"
class="gl-display-none d-md-inline-block gl-mr-3"
- :tabindex="!mr.canPushToSourceBranch ? 0 : null"
+ :tabindex="ideButtonTitle ? 0 : null"
>
<gl-button
:href="webIdePath"
:disabled="!mr.canPushToSourceBranch"
class="js-web-ide"
- tabindex="0"
- role="button"
data-qa-selector="open_in_web_ide_button"
>
{{ s__('mrWidget|Open in Web IDE') }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue
index 785e8ef8e8f..7c50df5f104 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue
@@ -1,8 +1,8 @@
<script>
/* eslint-disable @gitlab/require-i18n-strings */
import { GlModal, GlLink, GlSprintf } from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { __ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
i18n: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index 4c130945487..d022579ef54 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop, vue/no-v-html */
+/* eslint-disable vue/require-default-prop */
import {
GlIcon,
GlLink,
@@ -7,11 +7,12 @@ import {
GlSprintf,
GlTooltip,
GlTooltipDirective,
+ GlSafeHtmlDirective,
} from '@gitlab/ui';
import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline';
import { s__, n__ } from '~/locale';
-import PipelineStage from '~/pipelines/components/pipelines_list/stage.vue';
import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
+import PipelineStage from '~/pipelines/components/pipelines_list/stage.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
@@ -32,6 +33,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
mixins: [mrWidgetPipelineMixin],
props: {
@@ -139,45 +141,38 @@ export default {
<div class="ci-widget media">
<template v-if="hasCIError">
<gl-icon name="status_failed" class="gl-text-red-500" :size="24" />
- <div
- class="gl-flex-fill-1 gl-ml-5"
- tabindex="0"
- role="text"
- :aria-label="$options.errorText"
- data-testid="ci-error-message"
- >
+ <p class="gl-flex-fill-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message">
<gl-sprintf :message="$options.errorText">
<template #link="{ content }">
<gl-link :href="mrTroubleshootingDocsPath">{{ content }}</gl-link>
</template>
</gl-sprintf>
- </div>
+ </p>
</template>
<template v-else-if="!hasPipeline">
<gl-loading-icon size="md" />
- <div class="gl-flex-fill-1 gl-display-flex gl-ml-5" data-testid="monitoring-pipeline-message">
- <span tabindex="0" role="text" :aria-label="$options.monitoringPipelineText">
- <gl-sprintf :message="$options.monitoringPipelineText" />
- </span>
+ <p
+ class="gl-flex-fill-1 gl-display-flex gl-ml-5 gl-mb-0"
+ data-testid="monitoring-pipeline-message"
+ >
+ {{ $options.monitoringPipelineText }}
<gl-link
+ v-gl-tooltip
:href="ciTroubleshootingDocsPath"
target="_blank"
+ :title="__('About this feature')"
class="gl-display-flex gl-align-items-center gl-ml-2"
- tabindex="0"
>
<gl-icon
name="question"
- :size="12"
- tabindex="0"
- role="text"
:aria-label="__('Link to go to GitLab pipeline documentation')"
/>
</gl-link>
- </div>
+ </p>
</template>
<template v-else-if="hasPipeline">
<a :href="status.details_path" class="align-self-start gl-mr-3">
- <ci-icon :status="status" :size="24" :borderless="true" class="add-border" />
+ <ci-icon :status="status" :size="24" />
</a>
<div class="ci-widget-container d-flex">
<div class="ci-widget-content">
@@ -208,10 +203,10 @@ export default {
<template v-if="showSourceBranch">
{{ s__('Pipeline|on') }}
<tooltip-on-truncate
+ v-safe-html="sourceBranchLink"
:title="sourceBranch"
truncate-target="child"
class="label-branch label-truncate gl-font-weight-normal"
- v-html="sourceBranchLink"
/>
</template>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
index 99b55c0f9ee..2bf86c1863a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
@@ -1,10 +1,10 @@
<script>
import { isNumber } from 'lodash';
import { sanitize } from '~/lib/dompurify';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ArtifactsApp from './artifacts_list_app.vue';
import MrWidgetContainer from './mr_widget_container.vue';
import MrWidgetPipeline from './mr_widget_pipeline.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
/**
* Renders the pipeline and related deployments from the store.
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
index bc23ca6b1fc..677c50ed930 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
@@ -43,10 +43,9 @@ export default {
<gl-button
v-if="showDisabledButton"
- type="button"
category="primary"
variant="success"
- class="js-disabled-merge-button"
+ data-testid="disabled-merge-button"
:disabled="true"
>
{{ s__('mrWidget|Merge') }}
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 7acdd695cc2..d2581f57837 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
@@ -1,6 +1,5 @@
<script>
import { GlLink, GlSprintf, GlButton } from '@gitlab/ui';
-import MrWidgetIcon from './mr_widget_icon.vue';
import Tracking from '~/tracking';
import DismissibleContainer from '~/vue_shared/components/dismissible_container.vue';
import {
@@ -13,6 +12,7 @@ import {
SP_HELP_URL,
SP_ICON_NAME,
} from '../constants';
+import MrWidgetIcon from './mr_widget_icon.vue';
const trackingMixin = Tracking.mixin();
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 20ac8f5a467..428641a1109 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -2,14 +2,15 @@
import { GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
import autoMergeEnabledQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { deprecatedCreateFlash as Flash } from '../../../flash';
-import statusIcon from '../mr_widget_status_icon.vue';
-import MrWidgetAuthor from '../mr_widget_author.vue';
-import eventHub from '../../event_hub';
import { AUTO_MERGE_STRATEGIES } from '../../constants';
-import { __ } from '~/locale';
+import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
+import MrWidgetAuthor from '../mr_widget_author.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetAutoMergeEnabled',
@@ -53,7 +54,11 @@ export default {
},
computed: {
loading() {
- return this.glFeatures.mergeRequestWidgetGraphql && this.$apollo.queries.state.loading;
+ return (
+ this.glFeatures.mergeRequestWidgetGraphql &&
+ this.$apollo.queries.state.loading &&
+ Object.keys(this.state).length === 0
+ );
},
mergeUser() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
@@ -78,7 +83,7 @@ export default {
canRemoveSourceBranch() {
const { currentUserId } = this.mr;
const mergeUserId = this.glFeatures.mergeRequestWidgetGraphql
- ? this.state.mergeUser?.id
+ ? getIdFromGraphQLId(this.state.mergeUser?.id)
: this.mr.mergeUserId;
const canRemoveSourceBranch = this.glFeatures.mergeRequestWidgetGraphql
? this.state.userPermissions.removeSourceBranch
@@ -96,7 +101,11 @@ export default {
.cancelAutomaticMerge()
.then((res) => res.data)
.then((data) => {
- eventHub.$emit('UpdateWidgetData', data);
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ eventHub.$emit('MRWidgetUpdateRequested');
+ } else {
+ eventHub.$emit('UpdateWidgetData', data);
+ }
})
.catch(() => {
this.isCancellingAutoMerge = false;
@@ -119,6 +128,11 @@ export default {
eventHub.$emit('MRWidgetUpdateRequested');
}
})
+ .then(() => {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ this.$apollo.queries.state.refetch();
+ }
+ })
.catch(() => {
this.isRemovingSourceBranch = false;
Flash(__('Something went wrong. Please try again.'));
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
index a2771bc4bfb..5f8630bf7b3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
@@ -2,9 +2,9 @@
import { GlLoadingIcon, GlButton } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub';
-import statusIcon from '../mr_widget_status_icon.vue';
-import autoMergeFailedQuery from '../../queries/states/auto_merge_failed.query.graphql';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
+import autoMergeFailedQuery from '../../queries/states/auto_merge_failed.query.graphql';
+import statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetAutoMergeFailed',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
index 3d5daa4979b..2335e2984e4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -1,14 +1,14 @@
<script>
+import { GlButton, GlModalDirective, GlSkeletonLoader } from '@gitlab/ui';
import $ from 'jquery';
import { escape } from 'lodash';
-import { GlButton, GlModalDirective, GlSkeletonLoader } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
-import StatusIcon from '../mr_widget_status_icon.vue';
import userPermissionsQuery from '../../queries/permissions.query.graphql';
import conflictsStateQuery from '../../queries/states/conflicts.query.graphql';
+import StatusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetConflicts',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
index a5ec095b8ec..e973a2350a3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
@@ -1,9 +1,9 @@
<script>
import { GlButton } from '@gitlab/ui';
-import { n__ } from '~/locale';
import { stripHtml } from '~/lib/utils/text_utility';
-import statusIcon from '../mr_widget_status_icon.vue';
+import { sprintf, s__, n__ } from '~/locale';
import eventHub from '../../event_hub';
+import statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetFailedToMerge',
@@ -31,7 +31,15 @@ export default {
computed: {
mergeError() {
- return this.mr.mergeError ? stripHtml(this.mr.mergeError, ' ').trim() : '';
+ const mergeError = this.mr.mergeError ? stripHtml(this.mr.mergeError, ' ').trim() : '';
+
+ return sprintf(
+ s__('mrWidget|%{mergeError}.'),
+ {
+ mergeError,
+ },
+ false,
+ );
},
timerText() {
return n__(
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index 9d646dbfb3e..043d14e32a2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -3,10 +3,12 @@
import { GlLoadingIcon, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { deprecatedCreateFlash as Flash } from '~/flash';
import { s__, __ } from '~/locale';
+import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
+import modalEventHub from '~/projects/commit/event_hub';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import eventHub from '../../event_hub';
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
import statusIcon from '../mr_widget_status_icon.vue';
-import eventHub from '../../event_hub';
export default {
name: 'MRWidgetMerged',
@@ -77,6 +79,9 @@ export default {
return s__('mrWidget|Cherry-pick');
},
},
+ mounted() {
+ document.dispatchEvent(new CustomEvent('merged:UpdateActions'));
+ },
methods: {
removeSourceBranch() {
this.isMakingRequest = true;
@@ -98,6 +103,12 @@ export default {
Flash(__('Something went wrong. Please try again.'));
});
},
+ openRevertModal() {
+ modalEventHub.$emit(OPEN_REVERT_MODAL);
+ },
+ openCherryPickModal() {
+ modalEventHub.$emit(OPEN_CHERRY_PICK_MODAL);
+ },
},
};
</script>
@@ -119,9 +130,7 @@ export default {
size="small"
category="secondary"
variant="warning"
- href="#modal-revert-commit"
- data-toggle="modal"
- data-container="body"
+ @click="openRevertModal"
>
{{ revertLabel }}
</gl-button>
@@ -142,9 +151,7 @@ export default {
v-gl-tooltip.hover
:title="cherryPickTitle"
size="small"
- href="#modal-cherry-pick-commit"
- data-toggle="modal"
- data-container="body"
+ @click="openCherryPickModal"
>
{{ cherryPickLabel }}
</gl-button>
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 3f68979bc0e..f91350d4a82 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,10 +1,10 @@
<script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
-import statusIcon from '../mr_widget_status_icon.vue';
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 statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetMissingBranch',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index bf86e0d8b07..d15794c71b1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -4,12 +4,12 @@ import { GlButton, GlSkeletonLoader } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { deprecatedCreateFlash as Flash } from '../../../flash';
import simplePoll from '../../../lib/utils/simple_poll';
import eventHub from '../../event_hub';
-import statusIcon from '../mr_widget_status_icon.vue';
-import rebaseQuery from '../../queries/states/ready_to_merge.query.graphql';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
-import { deprecatedCreateFlash as Flash } from '../../../flash';
+import rebaseQuery from '../../queries/states/rebase.query.graphql';
+import statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'MRWidgetRebase',
@@ -159,7 +159,7 @@ export default {
<div class="rebase-state-find-class-convention media media-body space-children">
<span
v-if="rebaseInProgress || isMakingRequest"
- class="gl-font-weight-bold gl-ml-0!"
+ class="gl-font-weight-bold"
data-testid="rebase-message"
>{{ __('Rebase in progress') }}</span
>
@@ -181,17 +181,12 @@ export default {
>
{{ __('Rebase') }}
</gl-button>
- <span
- v-if="!rebasingError"
- class="gl-font-weight-bold gl-ml-0!"
- data-testid="rebase-message"
- >{{
- __(
- 'Fast-forward merge is not possible. Rebase the source branch onto the target branch.',
- )
- }}</span
- >
- <span v-else class="gl-font-weight-bold danger gl-ml-0!" data-testid="rebase-message">{{
+ <span v-if="!rebasingError" class="gl-font-weight-bold" data-testid="rebase-message">{{
+ __(
+ 'Fast-forward merge is not possible. Rebase the source branch onto the target branch.',
+ )
+ }}</span>
+ <span v-else class="gl-font-weight-bold danger" data-testid="rebase-message">{{
rebasingError
}}</span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
index 14a29483d3c..f0259a975db 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
@@ -1,9 +1,13 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlButton } from '@gitlab/ui';
import emptyStateSVG from 'icons/_mr_widget_empty_state.svg';
export default {
name: 'MRWidgetNothingToMerge',
+ components: {
+ GlButton,
+ },
props: {
mr: {
type: Object,
@@ -25,11 +29,13 @@ export default {
<span v-html="emptyStateSVG"></span>
</div>
<div class="text col-md-7 order-md-first col-12">
- <span>{{
- s__(
- 'mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others.',
- )
- }}</span>
+ <p class="highlight">
+ {{
+ s__(
+ 'mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others.',
+ )
+ }}
+ </p>
<p>
{{
s__(
@@ -45,9 +51,14 @@ export default {
}}
</p>
<div>
- <a v-if="mr.newBlobPath" :href="mr.newBlobPath" class="btn btn-inverted btn-success">{{
- __('Create file')
- }}</a>
+ <gl-button
+ v-if="mr.newBlobPath"
+ :href="mr.newBlobPath"
+ category="secondary"
+ variant="success"
+ >
+ {{ __('Create file') }}
+ </gl-button>
</div>
</div>
</div>
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 5f56157cb89..b5d2f91c637 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
@@ -1,11 +1,26 @@
<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__ } from '~/locale';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'PipelineFailed',
components: {
+ GlLink,
+ GlSprintf,
statusIcon,
},
+ computed: {
+ troubleshootingDocsPath() {
+ return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' });
+ },
+ },
+ 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.`,
+ ),
+ },
};
</script>
@@ -14,10 +29,13 @@ export default {
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- {{
- s__(`mrWidget|The pipeline for this merge request failed.
-Please retry the job or push a new commit to fix the failure`)
- }}
+ <gl-sprintf :message="$options.i18n.failedMessage">
+ <template #link="{ content }">
+ <gl-link :href="troubleshootingDocsPath" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index a890b176df0..690b6e9c462 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
@@ -1,5 +1,4 @@
<script>
-import { isEmpty } from 'lodash';
import {
GlIcon,
GlButton,
@@ -11,23 +10,24 @@ import {
GlTooltipDirective,
GlSkeletonLoader,
} from '@gitlab/ui';
+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 simplePoll from '~/lib/utils/simple_poll';
import { __ } from '~/locale';
-import MergeRequest from '../../../merge_request';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import { deprecatedCreateFlash as Flash } from '../../../flash';
+import MergeRequest from '../../../merge_request';
+import { AUTO_MERGE_STRATEGIES, DANGER, INFO, WARNING } from '../../constants';
+import eventHub from '../../event_hub';
+import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MergeRequestStore from '../../stores/mr_widget_store';
import statusIcon from '../mr_widget_status_icon.vue';
-import eventHub from '../../event_hub';
-import SquashBeforeMerge from './squash_before_merge.vue';
-import CommitsHeader from './commits_header.vue';
import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
-import { AUTO_MERGE_STRATEGIES, DANGER, INFO, WARNING } from '../../constants';
+import CommitsHeader from './commits_header.vue';
+import SquashBeforeMerge from './squash_before_merge.vue';
const PIPELINE_RUNNING_STATE = 'running';
const PIPELINE_FAILED_STATE = 'failed';
@@ -53,10 +53,13 @@ export default {
result({ data }) {
this.state = {
...data.project.mergeRequest,
- mergeRequestsFfOnlyEnabled: data.mergeRequestsFfOnlyEnabled,
- onlyAllowMergeIfPipelineSucceeds: data.onlyAllowMergeIfPipelineSucceeds,
+ mergeRequestsFfOnlyEnabled: data.project.mergeRequestsFfOnlyEnabled,
+ onlyAllowMergeIfPipelineSucceeds: data.project.onlyAllowMergeIfPipelineSucceeds,
};
- this.removeSourceBranch = data.project.mergeRequest.shouldRemoveSourceBranch;
+ this.removeSourceBranch =
+ data.project.mergeRequest.shouldRemoveSourceBranch ||
+ data.project.mergeRequest.forceRemoveSourceBranch ||
+ false;
this.commitMessage = data.project.mergeRequest.defaultMergeCommitMessage;
this.squashBeforeMerge = data.project.mergeRequest.squashOnMerge;
this.isSquashReadOnly = data.project.squashReadOnly;
@@ -277,7 +280,20 @@ export default {
return this.mr.mergeRequestDiffsPath;
},
},
+ mounted() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ eventHub.$on('ApprovalUpdated', this.updateGraphqlState);
+ }
+ },
+ beforeDestroy() {
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ eventHub.$off('ApprovalUpdated', this.updateGraphqlState);
+ }
+ },
methods: {
+ updateGraphqlState() {
+ return this.$apollo.queries.state.refetch();
+ },
updateMergeCommitMessage(includeDescription) {
const commitMessage = this.glFeatures.mergeRequestWidgetGraphql
? this.state.defaultMergeCommitMessage
@@ -326,6 +342,10 @@ export default {
} else if (hasError) {
eventHub.$emit('FailedToMerge', data.merge_error);
}
+
+ if (this.glFeatures.mergeRequestWidgetGraphql) {
+ this.updateGraphqlState();
+ }
})
.catch(() => {
this.isMakingRequest = false;
@@ -442,6 +462,7 @@ export default {
:variant="mergeButtonVariant"
:disabled="isMergeButtonDisabled"
:loading="isMakingRequest"
+ data-qa-selector="merge_button"
@click="handleMergeButtonClick(isAutoMergeAvailable)"
>{{ mergeButtonText }}</gl-button
>
@@ -532,7 +553,7 @@ export default {
</div>
<merge-train-helper-text
v-if="shouldRenderMergeTrainHelperText"
- :pipeline-id="pipeline.id"
+ :pipeline-id="pipelineId"
:pipeline-link="pipeline.path"
:merge-train-length="stateData.mergeTrainsCount"
:merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
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 78e69b9ff9b..329964d009a 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
@@ -1,7 +1,7 @@
<script>
import { GlButton } from '@gitlab/ui';
-import statusIcon from '../mr_widget_status_icon.vue';
import notesEventHub from '~/notes/event_hub';
+import statusIcon from '../mr_widget_status_icon.vue';
export default {
name: 'UnresolvedDiscussions',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index 3f1db815f95..af305815381 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -1,17 +1,17 @@
<script>
-import $ from 'jquery';
import { GlButton } from '@gitlab/ui';
import { produce } from 'immer';
-import { __ } from '~/locale';
+import $ from 'jquery';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { __ } from '~/locale';
import MergeRequest from '~/merge_request';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import getStateQuery from '../../queries/get_state.query.graphql';
import workInProgressQuery from '../../queries/states/work_in_progress.query.graphql';
import removeWipMutation from '../../queries/toggle_wip.mutation.graphql';
import StatusIcon from '../mr_widget_status_icon.vue';
-import eventHub from '../../event_hub';
export default {
name: 'WorkInProgress',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
index 180db7828a8..25f339b362f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
@@ -1,9 +1,9 @@
<script>
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
-import { n__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
-import MrWidgetExpanableSection from '../mr_widget_expandable_section.vue';
import Poll from '~/lib/utils/poll';
+import { n__ } from '~/locale';
+import MrWidgetExpanableSection from '../mr_widget_expandable_section.vue';
import TerraformPlan from './terraform_plan.vue';
export default {
@@ -128,12 +128,9 @@ export default {
</template>
<template #content>
- <terraform-plan
- v-for="(plan, key) in plansObject"
- :key="key"
- :plan="plan"
- class="mr-widget-body"
- />
+ <div class="mr-widget-body gl-pb-1">
+ <terraform-plan v-for="(plan, key) in plansObject" :key="key" :plan="plan" />
+ </div>
</template>
</mr-widget-expanable-section>
</section>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
index b74e036d9d9..25e3dae92e8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
@@ -15,6 +15,16 @@ export default {
type: Object,
},
},
+ i18n: {
+ changes: s__(
+ 'Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete',
+ ),
+ generationErrored: s__('Terraform|Generating the report caused an error.'),
+ namedReportFailed: s__('Terraform|The report %{name} failed to generate.'),
+ namedReportGenerated: s__('Terraform|The report %{name} was generated in your pipelines.'),
+ reportFailed: s__('Terraform|A report failed to generate.'),
+ reportGenerated: s__('Terraform|A report was generated in your pipelines.'),
+ },
computed: {
addNum() {
return Number(this.plan.create);
@@ -30,23 +40,21 @@ export default {
},
reportChangeText() {
if (this.validPlanValues) {
- return s__(
- 'Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete',
- );
+ return this.$options.i18n.changes;
}
- return s__('Terraform|Generating the report caused an error.');
+ return this.$options.i18n.generationErrored;
},
reportHeaderText() {
if (this.validPlanValues) {
return this.plan.job_name
- ? s__('Terraform|The Terraform report %{name} was generated in your pipelines.')
- : s__('Terraform|A Terraform report was generated in your pipelines.');
+ ? this.$options.i18n.namedReportGenerated
+ : this.$options.i18n.reportGenerated;
}
return this.plan.job_name
- ? s__('Terraform|The Terraform report %{name} failed to generate.')
- : s__('Terraform|A Terraform report failed to generate.');
+ ? this.$options.i18n.namedReportFailed
+ : this.$options.i18n.reportFailed;
},
validPlanValues() {
return this.addNum + this.changeNum + this.deleteNum >= 0;
@@ -56,16 +64,16 @@ export default {
</script>
<template>
- <div class="gl-display-flex">
+ <div class="gl-display-flex gl-pb-3">
<span
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-mr-3 gl-align-self-start gl-mt-1"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-px-2"
>
- <gl-icon :name="iconType" :size="18" data-testid="change-type-icon" />
+ <gl-icon :name="iconType" :size="16" data-testid="change-type-icon" />
</span>
- <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row">
- <div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column">
- <p class="gl-m-0 gl-pr-1">
+ <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row gl-pl-3">
+ <div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column gl-pr-3">
+ <p class="gl-mb-3 gl-line-height-normal">
<gl-sprintf :message="reportHeaderText">
<template #name>
<strong>{{ plan.job_name }}</strong>
@@ -73,7 +81,7 @@ export default {
</gl-sprintf>
</p>
- <p class="gl-m-0">
+ <p class="gl-mb-3 gl-line-height-normal">
<gl-sprintf :message="reportChangeText">
<template #addNum>
<strong>{{ addNum }}</strong>
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index d512877a20d..c1c491f6fe0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -1,8 +1,12 @@
+// This is a false violation of @gitlab/no-runtime-template-compiler, since it
+// creates a new Vue instance by spreading a _valid_ Vue component definition
+// into the Vue constructor.
+/* eslint-disable @gitlab/no-runtime-template-compiler */
import Vue from 'vue';
-import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_options.vue';
import VueApollo from 'vue-apollo';
-import Translate from '../vue_shared/translate';
+import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_options.vue';
import createDefaultClient from '~/lib/graphql';
+import Translate from '../vue_shared/translate';
import { registerExtension } from './components/extensions';
import issueExtension from './extensions/issues';
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 fe512d68ea2..23215982e6e 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
@@ -35,5 +35,8 @@ export default {
shouldRenderMergeTrainHelperText() {
return false;
},
+ pipelineId() {
+ return this.pipeline.id;
+ },
},
};
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 519576d9fe6..2a53eb8b241 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
@@ -1,50 +1,50 @@
<script>
+import { GlSafeHtmlDirective } from '@gitlab/ui';
import { isEmpty } from 'lodash';
-import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
-import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
import MrWidgetApprovals from 'ee_else_ce/vue_merge_request_widget/components/approvals/approvals.vue';
+import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
+import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
import stateMaps from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
-import { GlSafeHtmlDirective } from '@gitlab/ui';
+import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
+import notify from '~/lib/utils/notify';
import { sprintf, s__, __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
-import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import { deprecatedCreateFlash as createFlash } from '../flash';
-import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
+import { setFaviconOverlay } from '../lib/utils/favicon';
+import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
+import GroupedCodequalityReportsApp from '../reports/codequality_report/grouped_codequality_reports_app.vue';
+import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
import Loading from './components/loading.vue';
+import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue';
import WidgetHeader from './components/mr_widget_header.vue';
-import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue';
import WidgetMergeHelp from './components/mr_widget_merge_help.vue';
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
import WidgetRelatedLinks from './components/mr_widget_related_links.vue';
-import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue';
-import MergedState from './components/states/mr_widget_merged.vue';
-import ClosedState from './components/states/mr_widget_closed.vue';
-import MergingState from './components/states/mr_widget_merging.vue';
-import RebaseState from './components/states/mr_widget_rebase.vue';
-import WorkInProgressState from './components/states/work_in_progress.vue';
+import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue';
+import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import ArchivedState from './components/states/mr_widget_archived.vue';
+import MrWidgetAutoMergeEnabled from './components/states/mr_widget_auto_merge_enabled.vue';
+import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
+import CheckingState from './components/states/mr_widget_checking.vue';
+import ClosedState from './components/states/mr_widget_closed.vue';
import ConflictsState from './components/states/mr_widget_conflicts.vue';
-import NothingToMergeState from './components/states/nothing_to_merge.vue';
+import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
+import MergedState from './components/states/mr_widget_merged.vue';
+import MergingState from './components/states/mr_widget_merging.vue';
import MissingBranchState from './components/states/mr_widget_missing_branch.vue';
import NotAllowedState from './components/states/mr_widget_not_allowed.vue';
-import ReadyToMergeState from './components/states/ready_to_merge.vue';
-import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
import PipelineBlockedState from './components/states/mr_widget_pipeline_blocked.vue';
+import RebaseState from './components/states/mr_widget_rebase.vue';
+import NothingToMergeState from './components/states/nothing_to_merge.vue';
import PipelineFailedState from './components/states/pipeline_failed.vue';
-import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
-import MrWidgetAutoMergeEnabled from './components/states/mr_widget_auto_merge_enabled.vue';
-import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
-import CheckingState from './components/states/mr_widget_checking.vue';
+import ReadyToMergeState from './components/states/ready_to_merge.vue';
+import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
+import WorkInProgressState from './components/states/work_in_progress.vue';
// import ExtensionsContainer from './components/extensions/container';
-import eventHub from './event_hub';
-import notify from '~/lib/utils/notify';
-import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import TerraformPlan from './components/terraform/mr_widget_terraform_container.vue';
-import GroupedCodequalityReportsApp from '../reports/codequality_report/grouped_codequality_reports_app.vue';
-import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
-import { setFaviconOverlay } from '../lib/utils/favicon';
-import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
+import eventHub from './event_hub';
+import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
import getStateQuery from './queries/get_state.query.graphql';
export default {
@@ -94,7 +94,6 @@ export default {
state: {
query: getStateQuery,
manual: true,
- pollInterval: 10 * 1000,
skip() {
return !this.mr || !window.gon?.features?.mergeRequestWidgetGraphql;
},
@@ -181,7 +180,7 @@ export default {
);
},
shouldRenderSecurityReport() {
- return Boolean(window.gon?.features?.coreSecurityMrWidget && this.mr.pipeline.id);
+ return Boolean(this.mr.pipeline.id);
},
mergeError() {
let { mergeError } = this.mr;
@@ -191,7 +190,7 @@ export default {
}
return sprintf(
- s__('mrWidget|Merge failed: %{mergeError}. Please try again.'),
+ s__('mrWidget|%{mergeError}. Try again.'),
{
mergeError,
},
@@ -286,6 +285,10 @@ export default {
return new MRWidgetService(this.getServiceEndpoints(store));
},
checkStatus(cb, isRebased) {
+ if (window.gon?.features?.mergeRequestWidgetGraphql) {
+ this.$apollo.queries.state.refetch();
+ }
+
return this.service
.checkStatus()
.then(({ data }) => {
@@ -365,6 +368,7 @@ export default {
const el = document.createElement('div');
el.innerHTML = res.data;
document.body.appendChild(el);
+ document.dispatchEvent(new CustomEvent('merged:UpdateActions'));
Project.initRefSwitcher();
}
})
@@ -464,6 +468,7 @@ export default {
:head-path="mr.codeclimate.head_path"
:head-blob-path="mr.headBlobPath"
:base-blob-path="mr.baseBlobPath"
+ :codequality-reports-path="mr.codequalityReportsPath"
:codequality-help-path="mr.codequalityHelpPath"
/>
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 44fc1cc7f23..13ea07884b1 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
@@ -14,10 +14,12 @@ query getState($projectPath: ID!, $iid: String!) {
pipelines(first: 1) {
nodes {
status
+ warnings
}
}
shouldBeRebased
sourceBranchExists
+ state
targetBranchExists
userPermissions {
canMerge
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
index 64cd70fcf42..ad715599eb1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
@@ -1,6 +1,7 @@
fragment autoMergeEnabled on MergeRequest {
autoMergeStrategy
mergeUser {
+ id
name
username
webUrl
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 bdcb7a8206b..daf21e75b3b 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,7 +4,6 @@ query autoMergeEnabledQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
mergeRequest(iid: $iid) {
...autoMergeEnabled
- mergeTrainsCount
}
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
index 9479ef3cf79..8ee45b05431 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
@@ -5,6 +5,7 @@ fragment ReadyToMerge on Project {
mergeRequest(iid: $iid) {
autoMergeEnabled
shouldRemoveSourceBranch
+ forceRemoveSourceBranch
defaultMergeCommitMessage
defaultMergeCommitMessageWithDescription
defaultSquashCommitMessage
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/actions.js b/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/actions.js
index 419793977f0..5fd5950859b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/actions.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/actions.js
@@ -1,7 +1,7 @@
import Visibility from 'visibilityjs';
import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
import httpStatusCodes from '~/lib/utils/http_status';
+import Poll from '~/lib/utils/poll';
import * as types from './mutation_types';
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/index.js b/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/index.js
index e6cb5ead089..a2edfa94a48 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
-import mutations from './mutations';
import * as getters from './getters';
+import mutations from './mutations';
import state from './state';
Vue.use(Vuex);
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index a6bbab47a06..a0f14f558d2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -1,9 +1,9 @@
import { format } from 'timeago.js';
import getStateKey from 'ee_else_ce/vue_merge_request_widget/stores/get_state_key';
import mrEventHub from '~/merge_request/eventhub';
-import { stateKey } from './state_maps';
import { formatDate } from '../../lib/utils/datetime_utility';
import { MTWPS_MERGE_STRATEGY, MT_MERGE_STRATEGY, MWPS_MERGE_STRATEGY } from '../constants';
+import { stateKey } from './state_maps';
export default class MergeRequestStore {
constructor(data) {
@@ -156,9 +156,9 @@ export default class MergeRequestStore {
this.setState();
- mrEventHub.$emit('mr.state.updated', {
- state: this.mergeRequestState,
- });
+ if (!window.gon?.features?.mergeRequestWidgetGraphql) {
+ this.emitUpdatedState();
+ }
}
setGraphqlData(project) {
@@ -172,6 +172,11 @@ export default class MergeRequestStore {
this.canBeMerged = mergeRequest.mergeStatus === 'can_be_merged';
this.canMerge = mergeRequest.userPermissions.canMerge;
this.ciStatus = pipeline?.status.toLowerCase();
+
+ if (pipeline?.warnings && this.ciStatus === 'success') {
+ this.ciStatus = `${this.ciStatus}-with-warnings`;
+ }
+
this.commitsCount = mergeRequest.commitCount || 10;
this.branchMissing = !mergeRequest.sourceBranchExists || !mergeRequest.targetBranchExists;
this.hasConflicts = mergeRequest.conflicts;
@@ -182,7 +187,9 @@ export default class MergeRequestStore {
this.isSHAMismatch = this.sha !== mergeRequest.diffHeadSha;
this.shouldBeRebased = mergeRequest.shouldBeRebased;
this.workInProgress = mergeRequest.workInProgress;
+ this.mergeRequestState = mergeRequest.state;
+ this.emitUpdatedState();
this.setState();
}
@@ -208,6 +215,12 @@ export default class MergeRequestStore {
}
}
+ emitUpdatedState() {
+ mrEventHub.$emit('mr.state.updated', {
+ state: this.mergeRequestState,
+ });
+ }
+
setPaths(data) {
// Paths are set on the first load of the page and not auto-refreshed
this.squashBeforeMergeHelpPath = data.squash_before_merge_help_path;
@@ -241,10 +254,11 @@ export default class MergeRequestStore {
this.isDismissedSuggestPipeline = data.is_dismissed_suggest_pipeline;
this.securityReportsDocsPath = data.security_reports_docs_path;
- // codeclimate
+ // code quality
const blobPath = data.blob_path || {};
this.headBlobPath = blobPath.head_path || '';
this.baseBlobPath = blobPath.base_path || '';
+ this.codequalityReportsPath = data.codequality_reports_path;
this.codequalityHelpPath = data.codequality_help_path;
this.codeclimate = data.codeclimate;
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
new file mode 100644
index 00000000000..bcea7ca654e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_details.vue
@@ -0,0 +1,392 @@
+<script>
+import {
+ GlAlert,
+ GlBadge,
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ GlSprintf,
+ GlTabs,
+ GlTab,
+ GlButton,
+ GlSafeHtmlDirective,
+} from '@gitlab/ui';
+import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
+import { fetchPolicies } from '~/lib/graphql';
+import { toggleContainerClasses } from '~/lib/utils/dom_utils';
+import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+import * as Sentry from '~/sentry/wrapper';
+import Tracking from '~/tracking';
+import initUserPopovers from '~/user_popovers';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { SEVERITY_LEVELS } from '../constants';
+import createIssueMutation from '../graphql/mutations/alert_issue_create.mutation.graphql';
+import toggleSidebarStatusMutation from '../graphql/mutations/alert_sidebar_status.mutation.graphql';
+import alertQuery from '../graphql/queries/alert_details.query.graphql';
+import sidebarStatusQuery from '../graphql/queries/alert_sidebar_status.query.graphql';
+import AlertMetrics from './alert_metrics.vue';
+import AlertSidebar from './alert_sidebar.vue';
+import AlertSummaryRow from './alert_summary_row.vue';
+import SystemNote from './system_notes/system_note.vue';
+
+const containerEl = document.querySelector('.page-with-contextual-sidebar');
+
+export default {
+ i18n: {
+ errorMsg: s__(
+ 'AlertManagement|There was an error displaying the alert. Please refresh the page to try again.',
+ ),
+ reportedAt: s__('AlertManagement|Reported %{when}'),
+ reportedAtWithTool: s__('AlertManagement|Reported %{when} by %{tool}'),
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ severityLabels: SEVERITY_LEVELS,
+ tabsConfig: [
+ {
+ id: 'overview',
+ title: s__('AlertManagement|Alert details'),
+ },
+ {
+ id: 'metrics',
+ title: s__('AlertManagement|Metrics'),
+ },
+ {
+ id: 'activity',
+ title: s__('AlertManagement|Activity feed'),
+ },
+ ],
+ components: {
+ AlertDetailsTable,
+ AlertSummaryRow,
+ GlBadge,
+ GlAlert,
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ GlSprintf,
+ GlTab,
+ GlTabs,
+ GlButton,
+ TimeAgoTooltip,
+ AlertSidebar,
+ SystemNote,
+ AlertMetrics,
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ alertId: {
+ default: '',
+ },
+ isThreatMonitoringPage: {
+ default: false,
+ },
+ projectId: {
+ default: '',
+ },
+ projectIssuesPath: {
+ default: '',
+ },
+ trackAlertsDetailsViewsOptions: {
+ default: null,
+ },
+ },
+ apollo: {
+ alert: {
+ fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
+ query: alertQuery,
+ variables() {
+ return {
+ fullPath: this.projectPath,
+ alertId: this.alertId,
+ };
+ },
+ update(data) {
+ return data?.project?.alertManagementAlerts?.nodes?.[0] ?? null;
+ },
+ error(error) {
+ this.errored = true;
+ Sentry.captureException(error);
+ },
+ },
+ sidebarStatus: {
+ query: sidebarStatusQuery,
+ },
+ },
+ data() {
+ return {
+ alert: null,
+ errored: false,
+ sidebarStatus: false,
+ isErrorDismissed: false,
+ createIncidentError: '',
+ incidentCreationInProgress: false,
+ sidebarErrorMessage: '',
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.alert.loading;
+ },
+ reportedAtMessage() {
+ return this.alert?.monitoringTool
+ ? this.$options.i18n.reportedAtWithTool
+ : this.$options.i18n.reportedAt;
+ },
+ showErrorMsg() {
+ return this.errored && !this.isErrorDismissed;
+ },
+ activeTab() {
+ return this.$route.params.tabId || this.$options.tabsConfig[0].id;
+ },
+ currentTabIndex: {
+ get() {
+ return this.$options.tabsConfig.findIndex((tab) => tab.id === this.activeTab);
+ },
+ set(tabIdx) {
+ const tabId = this.$options.tabsConfig[tabIdx].id;
+ this.$router.replace({ name: 'tab', params: { tabId } });
+ },
+ },
+ environmentName() {
+ return this.alert?.environment?.name;
+ },
+ environmentPath() {
+ return this.alert?.environment?.path;
+ },
+ },
+ mounted() {
+ if (this.trackAlertsDetailsViewsOptions) {
+ this.trackPageViews();
+ }
+ toggleContainerClasses(containerEl, {
+ 'issuable-bulk-update-sidebar': true,
+ 'right-sidebar-expanded': true,
+ });
+ },
+ updated() {
+ this.$nextTick(() => {
+ highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member'));
+ initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
+ });
+ },
+ methods: {
+ dismissError() {
+ this.isErrorDismissed = true;
+ this.sidebarErrorMessage = '';
+ },
+ toggleSidebar() {
+ this.$apollo.mutate({ mutation: toggleSidebarStatusMutation });
+ toggleContainerClasses(containerEl, {
+ 'right-sidebar-collapsed': !this.sidebarStatus,
+ 'right-sidebar-expanded': this.sidebarStatus,
+ });
+ },
+ handleAlertSidebarError(errorMessage) {
+ this.errored = true;
+ this.sidebarErrorMessage = errorMessage;
+ },
+ createIncident() {
+ this.incidentCreationInProgress = true;
+
+ this.$apollo
+ .mutate({
+ mutation: createIssueMutation,
+ variables: {
+ iid: this.alert.iid,
+ projectPath: this.projectPath,
+ },
+ })
+ .then(
+ ({
+ data: {
+ createAlertIssue: { errors, issue },
+ },
+ }) => {
+ if (errors?.length) {
+ [this.createIncidentError] = errors;
+ this.incidentCreationInProgress = false;
+ } else if (issue) {
+ visitUrl(this.incidentPath(issue.iid));
+ }
+ },
+ )
+ .catch((error) => {
+ this.createIncidentError = error;
+ this.incidentCreationInProgress = false;
+ });
+ },
+ incidentPath(issueId) {
+ return joinPaths(this.projectIssuesPath, issueId);
+ },
+ trackPageViews() {
+ const { category, action } = this.trackAlertsDetailsViewsOptions;
+ Tracking.event(category, action);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-alert v-if="showErrorMsg" variant="danger" @dismiss="dismissError">
+ <p v-safe-html="sidebarErrorMessage || $options.i18n.errorMsg"></p>
+ </gl-alert>
+ <gl-alert
+ v-if="createIncidentError"
+ variant="danger"
+ data-testid="incidentCreationError"
+ @dismiss="createIncidentError = null"
+ >
+ {{ createIncidentError }}
+ </gl-alert>
+ <div v-if="loading"><gl-loading-icon size="lg" class="gl-mt-5" /></div>
+ <div
+ v-if="alert"
+ class="alert-management-details gl-relative"
+ :class="{ 'pr-sm-8': sidebarStatus }"
+ >
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-px-1 py-3 py-md-4 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-flex-direction-column gl-sm-flex-direction-row"
+ >
+ <div data-testid="alert-header">
+ <gl-badge class="gl-mr-3">
+ <strong>{{ s__('AlertManagement|Alert') }}</strong>
+ </gl-badge>
+ <span>
+ <gl-sprintf :message="reportedAtMessage">
+ <template #when>
+ <time-ago-tooltip :time="alert.createdAt" />
+ </template>
+ <template #tool>{{ alert.monitoringTool }}</template>
+ </gl-sprintf>
+ </span>
+ </div>
+ <gl-button
+ v-if="alert.issueIid"
+ class="gl-mt-3 mt-sm-0 align-self-center align-self-sm-baseline alert-details-incident-button"
+ data-testid="viewIncidentBtn"
+ :href="incidentPath(alert.issueIid)"
+ category="primary"
+ variant="success"
+ >
+ {{ s__('AlertManagement|View incident') }}
+ </gl-button>
+ <gl-button
+ v-else
+ class="gl-mt-3 mt-sm-0 align-self-center align-self-sm-baseline alert-details-incident-button"
+ data-testid="createIncidentBtn"
+ :loading="incidentCreationInProgress"
+ category="primary"
+ variant="success"
+ @click="createIncident()"
+ >
+ {{ s__('AlertManagement|Create incident') }}
+ </gl-button>
+ <gl-button
+ :aria-label="__('Toggle sidebar')"
+ category="primary"
+ variant="default"
+ class="d-sm-none gl-absolute toggle-sidebar-mobile-button"
+ type="button"
+ icon="chevron-double-lg-left"
+ @click="toggleSidebar"
+ />
+ </div>
+ <div
+ v-if="alert"
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center"
+ >
+ <h2 data-testid="title">{{ alert.title }}</h2>
+ </div>
+ <gl-tabs v-if="alert" v-model="currentTabIndex" data-testid="alertDetailsTabs">
+ <gl-tab :data-testid="$options.tabsConfig[0].id" :title="$options.tabsConfig[0].title">
+ <alert-summary-row v-if="alert.severity" :label="`${s__('AlertManagement|Severity')}:`">
+ <span data-testid="severity">
+ <gl-icon
+ class="gl-vertical-align-middle"
+ :size="12"
+ :name="`severity-${alert.severity.toLowerCase()}`"
+ :class="`icon-${alert.severity.toLowerCase()}`"
+ />
+ {{ $options.severityLabels[alert.severity] }}
+ </span>
+ </alert-summary-row>
+ <alert-summary-row
+ v-if="environmentName"
+ :label="`${s__('AlertManagement|Environment')}:`"
+ >
+ <gl-link
+ v-if="environmentPath"
+ class="gl-display-inline-block"
+ data-testid="environmentPath"
+ :href="environmentPath"
+ >
+ {{ environmentName }}
+ </gl-link>
+ <span v-else data-testid="environmentName">{{ environmentName }}</span>
+ </alert-summary-row>
+ <alert-summary-row
+ v-if="alert.startedAt"
+ :label="`${s__('AlertManagement|Start time')}:`"
+ >
+ <time-ago-tooltip data-testid="startTimeItem" :time="alert.startedAt" />
+ </alert-summary-row>
+ <alert-summary-row
+ v-if="alert.eventCount"
+ :label="`${s__('AlertManagement|Events')}:`"
+ data-testid="eventCount"
+ >
+ {{ alert.eventCount }}
+ </alert-summary-row>
+ <alert-summary-row
+ v-if="alert.monitoringTool"
+ :label="`${s__('AlertManagement|Tool')}:`"
+ data-testid="monitoringTool"
+ >
+ {{ alert.monitoringTool }}
+ </alert-summary-row>
+ <alert-summary-row
+ v-if="alert.service"
+ :label="`${s__('AlertManagement|Service')}:`"
+ data-testid="service"
+ >
+ {{ alert.service }}
+ </alert-summary-row>
+ <alert-summary-row
+ v-if="alert.runbook"
+ :label="`${s__('AlertManagement|Runbook')}:`"
+ data-testid="runbook"
+ >
+ {{ alert.runbook }}
+ </alert-summary-row>
+ <alert-details-table :alert="alert" :loading="loading" />
+ </gl-tab>
+ <gl-tab
+ v-if="isThreatMonitoringPage"
+ :data-testid="$options.tabsConfig[1].id"
+ :title="$options.tabsConfig[1].title"
+ >
+ <alert-metrics :dashboard-url="alert.metricsDashboardUrl" />
+ </gl-tab>
+ <gl-tab :data-testid="$options.tabsConfig[2].id" :title="$options.tabsConfig[2].title">
+ <div v-if="alert.notes.nodes.length > 0" class="issuable-discussion">
+ <ul class="notes main-notes-list timeline">
+ <system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
+ </ul>
+ </div>
+ </gl-tab>
+ </gl-tabs>
+ <alert-sidebar
+ :alert="alert"
+ @toggle-sidebar="toggleSidebar"
+ @alert-error="handleAlertSidebarError"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/alert_management/components/alert_metrics.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_metrics.vue
index dd4faa03c00..dd4faa03c00 100644
--- a/app/assets/javascripts/alert_management/components/alert_metrics.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_metrics.vue
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue
new file mode 100644
index 00000000000..a01bd462196
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_sidebar.vue
@@ -0,0 +1,86 @@
+<script>
+import sidebarStatusQuery from '../graphql/queries/alert_sidebar_status.query.graphql';
+import SidebarAssignees from './sidebar/sidebar_assignees.vue';
+import SidebarHeader from './sidebar/sidebar_header.vue';
+import SidebarStatus from './sidebar/sidebar_status.vue';
+import SidebarTodo from './sidebar/sidebar_todo.vue';
+
+export default {
+ components: {
+ SidebarAssignees,
+ SidebarHeader,
+ SidebarTodo,
+ SidebarStatus,
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ projectId: {
+ default: '',
+ },
+ // TODO remove this limitation in https://gitlab.com/gitlab-org/gitlab/-/issues/296717
+ isThreatMonitoringPage: {
+ default: false,
+ },
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: true,
+ },
+ },
+ apollo: {
+ sidebarStatus: {
+ query: sidebarStatusQuery,
+ },
+ },
+ data() {
+ return {
+ sidebarStatus: false,
+ };
+ },
+ computed: {
+ sidebarCollapsedClass() {
+ return this.sidebarStatus ? 'right-sidebar-collapsed' : 'right-sidebar-expanded';
+ },
+ },
+};
+</script>
+
+<template>
+ <aside :class="sidebarCollapsedClass" class="right-sidebar alert-sidebar">
+ <div class="issuable-sidebar js-issuable-update">
+ <sidebar-header
+ :sidebar-collapsed="sidebarStatus"
+ :project-path="projectPath"
+ :alert="alert"
+ @toggle-sidebar="$emit('toggle-sidebar')"
+ @alert-error="$emit('alert-error', $event)"
+ />
+ <sidebar-todo
+ v-if="sidebarStatus"
+ :project-path="projectPath"
+ :alert="alert"
+ :sidebar-collapsed="sidebarStatus"
+ @alert-error="$emit('alert-error', $event)"
+ />
+ <sidebar-status
+ v-if="!isThreatMonitoringPage"
+ :project-path="projectPath"
+ :alert="alert"
+ @toggle-sidebar="$emit('toggle-sidebar')"
+ @alert-error="$emit('alert-error', $event)"
+ />
+ <sidebar-assignees
+ :project-path="projectPath"
+ :project-id="projectId"
+ :alert="alert"
+ :sidebar-collapsed="sidebarStatus"
+ @toggle-sidebar="$emit('toggle-sidebar')"
+ @alert-error="$emit('alert-error', $event)"
+ />
+ <div class="block"></div>
+ </div>
+ </aside>
+</template>
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue
new file mode 100644
index 00000000000..8d5eb24ed1d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_status.vue
@@ -0,0 +1,125 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import updateAlertStatusMutation from '~/graphql_shared/mutations/alert_status_update.mutation.graphql';
+import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+
+export default {
+ i18n: {
+ UPDATE_ALERT_STATUS_ERROR: s__(
+ 'AlertManagement|There was an error while updating the status of the alert.',
+ ),
+ UPDATE_ALERT_STATUS_INSTRUCTION: s__('AlertManagement|Please try again.'),
+ },
+ statuses: {
+ TRIGGERED: s__('AlertManagement|Triggered'),
+ ACKNOWLEDGED: s__('AlertManagement|Acknowledged'),
+ RESOLVED: s__('AlertManagement|Resolved'),
+ },
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ inject: {
+ trackAlertStatusUpdateOptions: {
+ default: null,
+ },
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ alert: {
+ type: Object,
+ required: true,
+ },
+ isDropdownShowing: {
+ type: Boolean,
+ required: false,
+ },
+ isSidebar: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ dropdownClass() {
+ // eslint-disable-next-line no-nested-ternary
+ return this.isSidebar ? (this.isDropdownShowing ? 'show' : 'gl-display-none') : '';
+ },
+ },
+ methods: {
+ updateAlertStatus(status) {
+ this.$emit('handle-updating', true);
+ this.$apollo
+ .mutate({
+ mutation: updateAlertStatusMutation,
+ variables: {
+ iid: this.alert.iid,
+ status: status.toUpperCase(),
+ projectPath: this.projectPath,
+ },
+ })
+ .then((resp) => {
+ if (this.trackAlertStatusUpdateOptions) {
+ this.trackStatusUpdate(status);
+ }
+ const errors = resp.data?.updateAlertStatus?.errors || [];
+
+ if (errors[0]) {
+ this.$emit(
+ 'alert-error',
+ `${this.$options.i18n.UPDATE_ALERT_STATUS_ERROR} ${errors[0]}`,
+ );
+ }
+
+ this.$emit('hide-dropdown');
+ })
+ .catch(() => {
+ this.$emit(
+ 'alert-error',
+ `${this.$options.i18n.UPDATE_ALERT_STATUS_ERROR} ${this.$options.i18n.UPDATE_ALERT_STATUS_INSTRUCTION}`,
+ );
+ })
+ .finally(() => {
+ this.$emit('handle-updating', false);
+ });
+ },
+ trackStatusUpdate(status) {
+ const { category, action, label } = this.trackAlertStatusUpdateOptions;
+ Tracking.event(category, action, { label, property: status });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="dropdown dropdown-menu-selectable" :class="dropdownClass">
+ <gl-dropdown
+ ref="dropdown"
+ right
+ :text="$options.statuses[alert.status]"
+ class="w-100"
+ toggle-class="dropdown-menu-toggle"
+ @keydown.esc.native="$emit('hide-dropdown')"
+ @hide="$emit('hide-dropdown')"
+ >
+ <p v-if="isSidebar" class="gl-new-dropdown-header-top" data-testid="dropdown-header">
+ {{ s__('AlertManagement|Assign status') }}
+ </p>
+ <div class="dropdown-content dropdown-body">
+ <gl-dropdown-item
+ v-for="(label, field) in $options.statuses"
+ :key="field"
+ data-testid="statusDropdownItem"
+ :active="label.toUpperCase() === alert.status"
+ :active-class="'is-active'"
+ @click="updateAlertStatus(label)"
+ >
+ {{ label }}
+ </gl-dropdown-item>
+ </div>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/alert_management/components/alert_summary_row.vue b/app/assets/javascripts/vue_shared/alert_details/components/alert_summary_row.vue
index 13835b7e2fa..13835b7e2fa 100644
--- a/app/assets/javascripts/alert_management/components/alert_summary_row.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/alert_summary_row.vue
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignee.vue
index c39a72a45b9..c39a72a45b9 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignee.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignee.vue
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
index 2a999b908f9..2a999b908f9 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_header.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_header.vue
new file mode 100644
index 00000000000..fd40b5d9f65
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_header.vue
@@ -0,0 +1,41 @@
+<script>
+import ToggleSidebar from '~/vue_shared/components/sidebar/toggle_sidebar.vue';
+import SidebarTodo from './sidebar_todo.vue';
+
+export default {
+ components: {
+ ToggleSidebar,
+ SidebarTodo,
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ sidebarCollapsed: {
+ type: Boolean,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="block gl-display-flex gl-justify-content-space-between">
+ <span class="issuable-header-text hide-collapsed">
+ {{ __('To Do') }}
+ </span>
+ <sidebar-todo
+ v-if="!sidebarCollapsed"
+ :project-path="projectPath"
+ :alert="alert"
+ :sidebar-collapsed="sidebarCollapsed"
+ @alert-error="$emit('alert-error', $event)"
+ />
+ <toggle-sidebar :collapsed="sidebarCollapsed" @toggle="$emit('toggle-sidebar')" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
index 0a2bad5510b..0a2bad5510b 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_status.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue
new file mode 100644
index 00000000000..39ac6c7feca
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue
@@ -0,0 +1,149 @@
+<script>
+import produce from 'immer';
+import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
+import { s__ } from '~/locale';
+import Todo from '~/sidebar/components/todo_toggle/todo.vue';
+import createAlertTodoMutation from '../../graphql/mutations/alert_todo_create.mutation.graphql';
+import alertQuery from '../../graphql/queries/alert_details.query.graphql';
+
+export default {
+ i18n: {
+ UPDATE_ALERT_TODO_ERROR: s__(
+ 'AlertManagement|There was an error while updating the to-do item of the alert.',
+ ),
+ },
+ components: {
+ Todo,
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ sidebarCollapsed: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isUpdating: false,
+ };
+ },
+ computed: {
+ alertID() {
+ return parseInt(this.alert.iid, 10);
+ },
+ firstToDoId() {
+ return this.alert?.todos?.nodes[0]?.id;
+ },
+ hasPendingTodos() {
+ return this.alert?.todos?.nodes.length > 0;
+ },
+ getAlertQueryVariables() {
+ return {
+ fullPath: this.projectPath,
+ alertId: this.alert.iid,
+ };
+ },
+ },
+ methods: {
+ updateToDoCount(add) {
+ const oldCount = parseInt(document.querySelector('.js-todos-count').innerText, 10);
+ const count = add ? oldCount + 1 : oldCount - 1;
+ const headerTodoEvent = new CustomEvent('todo:toggle', {
+ detail: {
+ count,
+ },
+ });
+
+ return document.dispatchEvent(headerTodoEvent);
+ },
+ addToDo() {
+ this.isUpdating = true;
+ return this.$apollo
+ .mutate({
+ mutation: createAlertTodoMutation,
+ variables: {
+ iid: this.alert.iid,
+ projectPath: this.projectPath,
+ },
+ })
+ .then(({ data: { errors = [] } }) => {
+ if (errors[0]) {
+ return this.throwError(errors[0]);
+ }
+ return this.updateToDoCount(true);
+ })
+ .catch(() => {
+ this.throwError();
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ markAsDone() {
+ this.isUpdating = true;
+ return this.$apollo
+ .mutate({
+ mutation: todoMarkDoneMutation,
+ variables: {
+ id: this.firstToDoId,
+ },
+ update: this.updateCache,
+ })
+ .then(({ data: { errors = [] } }) => {
+ if (errors[0]) {
+ return this.throwError(errors[0]);
+ }
+ return this.updateToDoCount(false);
+ })
+ .catch(() => {
+ this.throwError();
+ })
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ updateCache(store) {
+ const sourceData = store.readQuery({
+ query: alertQuery,
+ variables: this.getAlertQueryVariables,
+ });
+
+ const data = produce(sourceData, (draftData) => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.alertManagementAlerts.nodes[0].todos.nodes = [];
+ });
+
+ store.writeQuery({
+ query: alertQuery,
+ variables: this.getAlertQueryVariables,
+ data,
+ });
+ },
+ throwError(err = '') {
+ const error = err || s__('AlertManagement|Please try again.');
+ this.$emit('alert-error', `${this.$options.i18n.UPDATE_ALERT_TODO_ERROR} ${error}`);
+ },
+ },
+};
+</script>
+
+<template>
+ <div :class="{ 'block todo': sidebarCollapsed, 'gl-ml-auto': !sidebarCollapsed }">
+ <todo
+ data-testid="alert-todo-button"
+ :collapsed="sidebarCollapsed"
+ :issuable-id="alertID"
+ :is-todo="hasPendingTodos"
+ :is-action-active="isUpdating"
+ issuable-type="alert"
+ @toggleTodo="hasPendingTodos ? markAsDone() : addToDo()"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue b/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue
index 3705e36a579..3705e36a579 100644
--- a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue
diff --git a/app/assets/javascripts/vue_shared/alert_details/constants.js b/app/assets/javascripts/vue_shared/alert_details/constants.js
new file mode 100644
index 00000000000..2ab5160534c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/constants.js
@@ -0,0 +1,31 @@
+import { s__ } from '~/locale';
+
+export const SEVERITY_LEVELS = {
+ CRITICAL: s__('severity|Critical'),
+ HIGH: s__('severity|High'),
+ MEDIUM: s__('severity|Medium'),
+ LOW: s__('severity|Low'),
+ INFO: s__('severity|Info'),
+ UNKNOWN: s__('severity|Unknown'),
+};
+
+/* eslint-disable @gitlab/require-i18n-strings */
+export const PAGE_CONFIG = {
+ OPERATIONS: {
+ TITLE: 'OPERATIONS',
+ // Tracks snowplow event when user views alert details
+ TRACK_ALERTS_DETAILS_VIEWS_OPTIONS: {
+ category: 'Alert Management',
+ action: 'view_alert_details',
+ },
+ // Tracks snowplow event when alert status is updated
+ TRACK_ALERT_STATUS_UPDATE_OPTIONS: {
+ category: 'Alert Management',
+ action: 'update_alert_status',
+ label: 'Status',
+ },
+ },
+ THREAT_MONITORING: {
+ TITLE: 'THREAT_MONITORING',
+ },
+};
diff --git a/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/fragments/alert_detail_item.fragment.graphql
index 9a9ae369519..9a9ae369519 100644
--- a/app/assets/javascripts/alert_management/graphql/fragments/detail_item.fragment.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/fragments/alert_detail_item.fragment.graphql
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql
index bc4d91a51d1..bc4d91a51d1 100644
--- a/app/assets/javascripts/alert_management/graphql/mutations/create_issue_from_alert.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql
index 63d952a4857..63d952a4857 100644
--- a/app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/toggle_sidebar_status.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_sidebar_status.mutation.graphql
index f666fcd6782..f666fcd6782 100644
--- a/app/assets/javascripts/alert_management/graphql/mutations/toggle_sidebar_status.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_sidebar_status.mutation.graphql
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql
new file mode 100644
index 00000000000..dc961b5eb90
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_todo_create.mutation.graphql
@@ -0,0 +1,10 @@
+#import "../fragments/alert_detail_item.fragment.graphql"
+
+mutation alertTodoCreate($projectPath: ID!, $iid: String!) {
+ alertTodoCreate(input: { iid: $iid, projectPath: $projectPath }) {
+ errors
+ alert {
+ ...AlertDetailItem
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql
new file mode 100644
index 00000000000..5ee2cf7ca44
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_details.query.graphql
@@ -0,0 +1,11 @@
+#import "../fragments/alert_detail_item.fragment.graphql"
+
+query alertDetails($fullPath: ID!, $alertId: String) {
+ project(fullPath: $fullPath) {
+ alertManagementAlerts(iid: $alertId) {
+ nodes {
+ ...AlertDetailItem
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/alert_management/graphql/queries/sidebar_status.query.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_status.query.graphql
index 61c570c5cd0..61c570c5cd0 100644
--- a/app/assets/javascripts/alert_management/graphql/queries/sidebar_status.query.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_status.query.graphql
diff --git a/app/assets/javascripts/vue_shared/alert_details/index.js b/app/assets/javascripts/vue_shared/alert_details/index.js
new file mode 100644
index 00000000000..3ea43d7a843
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/alert_details/index.js
@@ -0,0 +1,83 @@
+import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
+import produce from 'immer';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import AlertDetails from './components/alert_details.vue';
+import { PAGE_CONFIG } from './constants';
+import sidebarStatusQuery from './graphql/queries/alert_sidebar_status.query.graphql';
+import createRouter from './router';
+
+Vue.use(VueApollo);
+
+export default (selector) => {
+ const domEl = document.querySelector(selector);
+ const { alertId, projectPath, projectIssuesPath, projectId, page } = domEl.dataset;
+ const router = createRouter();
+
+ const resolvers = {
+ Mutation: {
+ toggleSidebarStatus: (_, __, { cache }) => {
+ const sourceData = cache.readQuery({ query: sidebarStatusQuery });
+ const data = produce(sourceData, (draftData) => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.sidebarStatus = !draftData.sidebarStatus;
+ });
+ cache.writeQuery({ query: sidebarStatusQuery, data });
+ },
+ },
+ };
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(resolvers, {
+ cacheConfig: {
+ dataIdFromObject: (object) => {
+ // eslint-disable-next-line no-underscore-dangle
+ if (object.__typename === 'AlertManagementAlert') {
+ return object.iid;
+ }
+ return defaultDataIdFromObject(object);
+ },
+ },
+ assumeImmutableResults: true,
+ }),
+ });
+
+ apolloProvider.clients.defaultClient.cache.writeData({
+ data: {
+ sidebarStatus: false,
+ },
+ });
+
+ const provide = {
+ projectPath,
+ alertId,
+ page,
+ projectIssuesPath,
+ projectId,
+ };
+
+ if (page === PAGE_CONFIG.OPERATIONS.TITLE) {
+ const { TRACK_ALERTS_DETAILS_VIEWS_OPTIONS, TRACK_ALERT_STATUS_UPDATE_OPTIONS } = PAGE_CONFIG[
+ page
+ ];
+ provide.trackAlertsDetailsViewsOptions = TRACK_ALERTS_DETAILS_VIEWS_OPTIONS;
+ provide.trackAlertStatusUpdateOptions = TRACK_ALERT_STATUS_UPDATE_OPTIONS;
+ } else if (page === PAGE_CONFIG.THREAT_MONITORING.TITLE) {
+ provide.isThreatMonitoringPage = true;
+ }
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: selector,
+ components: {
+ AlertDetails,
+ },
+ provide,
+ apolloProvider,
+ router,
+ render(createElement) {
+ return createElement('alert-details', {});
+ },
+ });
+};
diff --git a/app/assets/javascripts/alert_management/router.js b/app/assets/javascripts/vue_shared/alert_details/router.js
index 5687fe4e0f5..5687fe4e0f5 100644
--- a/app/assets/javascripts/alert_management/router.js
+++ b/app/assets/javascripts/vue_shared/alert_details/router.js
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue
index 2dc2c27f7ea..13472b48e84 100644
--- a/app/assets/javascripts/vue_shared/components/actions_button.vue
+++ b/app/assets/javascripts/vue_shared/components/actions_button.vue
@@ -76,14 +76,13 @@ export default {
<template v-for="(action, index) in actions">
<gl-dropdown-item
:key="action.key"
- class="gl-dropdown-item-deprecated-adapter"
:is-check-item="true"
:is-checked="action.key === selectedAction.key"
:secondary-text="action.secondaryText"
:data-testid="`action_${action.key}`"
@click="handleItemClick(action)"
>
- {{ action.text }}
+ <span class="gl-font-weight-bold">{{ action.text }}</span>
</gl-dropdown-item>
<gl-dropdown-divider v-if="index != actions.length - 1" :key="action.key + '_divider'" />
</template>
diff --git a/app/assets/javascripts/vue_shared/components/alert_details_table.vue b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
index 655b867574d..3d49a1cb1c5 100644
--- a/app/assets/javascripts/vue_shared/components/alert_details_table.vue
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -1,12 +1,12 @@
<script>
import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { reduce } from 'lodash';
-import { s__ } from '~/locale';
import {
capitalizeFirstCharacter,
convertToSentenceCase,
splitCamelCase,
} from '~/lib/utils/text_utility';
+import { s__ } from '~/locale';
const thClass = 'gl-bg-transparent! gl-border-1! gl-border-b-solid! gl-border-gray-200!';
const tdClass = 'gl-border-gray-100! gl-p-5!';
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index c1da2b8c305..ce67d33d4a1 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -1,9 +1,9 @@
<script>
/* eslint-disable vue/no-v-html */
-import { groupBy } from 'lodash';
import { GlIcon, GlButton, GlTooltipDirective } from '@gitlab/ui';
-import { glEmojiTag } from '../../emoji';
+import { groupBy } from 'lodash';
import { __, sprintf } from '~/locale';
+import { glEmojiTag } from '../../emoji';
// Internal constant, specific to this component, used when no `currentUserId` is given
const NO_USER_ID = -1;
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js b/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
index 6f7723955bf..db61d0f6b05 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/mixins.js
@@ -1,5 +1,5 @@
-import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
import eventHub from '~/blob/components/eventhub';
+import { SNIPPET_MEASURE_BLOBS_CONTENT } from '~/performance/constants';
export default {
props: {
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
index d0f5570db6b..a8a053c0d9e 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
@@ -1,8 +1,8 @@
<script>
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { handleBlobRichViewer } from '~/blob/viewer';
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
import ViewerMixin from './mixins';
-import { handleBlobRichViewer } from '~/blob/viewer';
export default {
components: {
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 646e1703f1e..5bb31f55e6c 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,8 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlIcon } from '@gitlab/ui';
-import ViewerMixin from './mixins';
import { HIGHLIGHT_CLASS_NAME } from './constants';
+import ViewerMixin from './mixins';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
index 5c6bd5892ae..cd5f63afc79 100644
--- a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
@@ -6,8 +6,8 @@ import {
GlButton,
GlTooltipDirective,
} from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
import { getHTTPProtocol } from '~/lib/utils/url_utility';
+import { __, sprintf } from '~/locale';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue b/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue
index 6977692e30c..0ff33e462b4 100644
--- a/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue
@@ -3,12 +3,16 @@
* Renders a color picker input with preset colors to choose from
*
* @example
- * <color-picker :label="__('Background color')" set-color="#FF0000" />
+ * <color-picker
+ :invalid-feedback="__('Please enter a valid hex (#RRGGBB or #RGB) color value')"
+ :label="__('Background color')"
+ :value="#FF0000"
+ state="isValidColor"
+ />
*/
import { GlFormGroup, GlFormInput, GlFormInputGroup, GlLink, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
-const VALID_RGB_HEX_COLOR = /^#([0-9A-F]{3}){1,2}$/i;
const PREVIEW_COLOR_DEFAULT_CLASSES =
'gl-relative gl-w-7 gl-bg-gray-10 gl-rounded-top-left-base gl-rounded-bottom-left-base';
@@ -24,21 +28,26 @@ export default {
GlTooltip: GlTooltipDirective,
},
props: {
+ invalidFeedback: {
+ type: String,
+ required: false,
+ default: __('Please enter a valid hex (#RRGGBB or #RGB) color value'),
+ },
label: {
type: String,
required: false,
default: '',
},
- setColor: {
+ value: {
type: String,
required: false,
default: '',
},
- },
- data() {
- return {
- selectedColor: this.setColor.trim() || '',
- };
+ state: {
+ type: Boolean,
+ required: false,
+ default: null,
+ },
},
computed: {
description() {
@@ -50,46 +59,30 @@ export default {
return gon.suggested_label_colors;
},
previewColor() {
- if (this.isValidColor) {
- return { backgroundColor: this.selectedColor };
+ if (this.state) {
+ return { backgroundColor: this.value };
}
return {};
},
previewColorClasses() {
- const borderStyle = this.isInvalidColor
- ? 'gl-inset-border-1-red-500'
- : 'gl-inset-border-1-gray-400';
+ const borderStyle =
+ this.state === false ? 'gl-inset-border-1-red-500' : 'gl-inset-border-1-gray-400';
return `${PREVIEW_COLOR_DEFAULT_CLASSES} ${borderStyle}`;
},
hasSuggestedColors() {
return Object.keys(this.suggestedColors).length;
},
- isInvalidColor() {
- return this.isValidColor === false;
- },
- isValidColor() {
- if (this.selectedColor === '') {
- return null;
- }
-
- return VALID_RGB_HEX_COLOR.test(this.selectedColor);
- },
},
methods: {
handleColorChange(color) {
- this.selectedColor = color.trim();
-
- if (this.isValidColor) {
- this.$emit('input', this.selectedColor);
- }
+ this.$emit('input', color.trim());
},
},
i18n: {
fullDescription: __('Choose any color. Or you can choose one of the suggested colors below'),
shortDescription: __('Choose any color'),
- invalid: __('Please enter a valid hex (#RRGGBB or #RGB) color value'),
},
};
</script>
@@ -100,17 +93,17 @@ export default {
:label="label"
label-for="color-picker"
:description="description"
- :invalid-feedback="this.$options.i18n.invalid"
- :state="isValidColor"
+ :invalid-feedback="invalidFeedback"
+ :state="state"
:class="{ 'gl-mb-3!': hasSuggestedColors }"
>
<gl-form-input-group
id="color-picker"
- :state="isValidColor"
max-length="7"
type="text"
class="gl-align-center gl-rounded-0 gl-rounded-top-right-base gl-rounded-bottom-right-base"
- :value="selectedColor"
+ :value="value"
+ :state="state"
@input="handleColorChange"
>
<template #prepend>
@@ -119,7 +112,7 @@ export default {
type="color"
class="gl-absolute gl-top-0 gl-left-0 gl-h-full! gl-p-0! gl-m-0! gl-cursor-pointer gl-opacity-0"
tabindex="-1"
- :value="selectedColor"
+ :value="value"
@input="handleColorChange"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index deca934e283..d1eee62683b 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,6 +1,6 @@
<script>
-import { isString, isEmpty } from 'lodash';
import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
+import { isString, isEmpty } from 'lodash';
import { __, sprintf } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
@@ -133,6 +133,9 @@ export default {
? sprintf(__("%{username}'s avatar"), { username: this.author.username })
: null;
},
+ refUrl() {
+ return this.commitRef.ref_url || this.commitRef.path;
+ },
},
};
</script>
@@ -156,9 +159,10 @@ export default {
<gl-link
v-else
v-gl-tooltip
- :href="commitRef.ref_url"
+ :href="refUrl"
:title="commitRef.name"
class="ref-name"
+ data-testid="ref-name"
>{{ commitRef.name }}</gl-link
>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
index 9ff35132ac9..1370f7b2a8c 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
@@ -1,7 +1,7 @@
<script>
-import MarkdownViewer from './viewers/markdown_viewer.vue';
-import ImageViewer from './viewers/image_viewer.vue';
import DownloadViewer from './viewers/download_viewer.vue';
+import ImageViewer from './viewers/image_viewer.vue';
+import MarkdownViewer from './viewers/markdown_viewer.vue';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
index 9ece6a52805..a49eb7fd611 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
@@ -1,6 +1,7 @@
<script>
import { throttle } from 'lodash';
-import { numberToHumanSize } from '../../../../lib/utils/number_utils';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
+import { encodeSaferUrl } from '~/lib/utils/url_utility';
export default {
props: {
@@ -43,6 +44,9 @@ export default {
hasDimensions() {
return this.width && this.height;
},
+ safePath() {
+ return encodeSaferUrl(this.path);
+ },
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeThrottled, false);
@@ -84,7 +88,7 @@ export default {
<template>
<div data-testid="image-viewer" data-qa-selector="image_viewer_container">
<div :class="innerCssClasses" class="position-relative">
- <img ref="contentImg" :src="path" @load="onImgLoad" />
+ <img ref="contentImg" :src="safePath" @load="onImgLoad" />
<slot
name="image-overlay"
:rendered-width="renderedWidth"
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index 24386c90954..3790a509f26 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -1,9 +1,8 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
-
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { forEach, escape } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
index d0c2672b162..1a96cabf755 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
@@ -1,8 +1,7 @@
<script>
import { GlIcon, GlButton, GlDropdown, GlDropdownItem, GlFormGroup } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-
import { convertToFixedRange, isEqualTimeRanges, findTimeRange } from '~/lib/utils/datetime_range';
+import { __, sprintf } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import DateTimePickerInput from './date_time_picker_input.vue';
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue
index 39c1caf928e..190d4e1f104 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker_input.vue
@@ -1,6 +1,6 @@
<script>
-import { uniqueId } from 'lodash';
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
import { __, sprintf } from '~/locale';
import { dateFormats } from './date_time_picker_lib';
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
index e755494a668..7080e046b30 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
@@ -1,9 +1,9 @@
<script>
import { diffViewerModes, diffModes } from '~/ide/constants';
-import ImageDiffViewer from './viewers/image_diff_viewer.vue';
import DownloadDiffViewer from './viewers/download_diff_viewer.vue';
-import RenamedFile from './viewers/renamed.vue';
+import ImageDiffViewer from './viewers/image_diff_viewer.vue';
import ModeChanged from './viewers/mode_changed.vue';
+import RenamedFile from './viewers/renamed.vue';
export default {
props: {
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue
index 433aafdeb9e..a3d9b0ace34 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue
@@ -1,6 +1,6 @@
<script>
-import { pixeliseValue } from '../../../lib/utils/dom_utils';
import ImageViewer from '../../../content_viewer/viewers/image_viewer.vue';
+import { pixeliseValue } from '../../../lib/utils/dom_utils';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
index acca6ba117f..41acc63cea9 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
@@ -1,7 +1,7 @@
<script>
import { throttle } from 'lodash';
-import { pixeliseValue } from '../../../lib/utils/dom_utils';
import ImageViewer from '../../../content_viewer/viewers/image_viewer.vue';
+import { pixeliseValue } from '../../../lib/utils/dom_utils';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
index 00033145603..f5ac65bcd1f 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
@@ -1,9 +1,9 @@
<script>
import ImageViewer from '../../content_viewer/viewers/image_viewer.vue';
-import TwoUpViewer from './image_diff/two_up_viewer.vue';
-import SwipeViewer from './image_diff/swipe_viewer.vue';
-import OnionSkinViewer from './image_diff/onion_skin_viewer.vue';
import { diffModes, imageViewMode } from '../constants';
+import OnionSkinViewer from './image_diff/onion_skin_viewer.vue';
+import SwipeViewer from './image_diff/swipe_viewer.vue';
+import TwoUpViewer from './image_diff/two_up_viewer.vue';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/renamed.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/renamed.vue
index eba6dd4d14c..d6f99e9a049 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/renamed.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/renamed.vue
@@ -1,8 +1,7 @@
<script>
-import { mapActions } from 'vuex';
import { GlAlert, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import { mapActions } from 'vuex';
-import { __ } from '~/locale';
import {
TRANSITION_LOAD_START,
TRANSITION_LOAD_ERROR,
@@ -14,6 +13,7 @@ import {
RENAMED_DIFF_TRANSITIONS,
} from '~/diffs/constants';
import { truncateSha } from '~/lib/utils/text_utility';
+import { __ } from '~/locale';
export default {
STATE_LOADING,
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue b/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue
index 2a28b13e7bf..c4dfcf93a18 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue
@@ -1,7 +1,7 @@
<script>
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { slugifyWithUnderscore } from '~/lib/utils/text_utility';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
index 7e82d8f3f9c..eb8400e81c7 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
@@ -36,10 +36,8 @@ export default {
aria-expanded="false"
>
<gl-loading-icon v-show="isLoading" :inline="true" />
- <template>
- <slot v-if="$slots.default"></slot>
- <span v-else class="dropdown-toggle-text"> {{ toggleText }} </span>
- </template>
+ <slot v-if="$slots.default"></slot>
+ <span v-else class="dropdown-toggle-text"> {{ toggleText }} </span>
<gl-icon
v-show="!isLoading"
class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500"
diff --git a/app/assets/javascripts/vue_shared/components/editor_lite.vue b/app/assets/javascripts/vue_shared/components/editor_lite.vue
index 7218b84cf8a..c3bddabea21 100644
--- a/app/assets/javascripts/vue_shared/components/editor_lite.vue
+++ b/app/assets/javascripts/vue_shared/components/editor_lite.vue
@@ -1,7 +1,7 @@
<script>
import { debounce } from 'lodash';
+import { CONTENT_UPDATE_DEBOUNCE, EDITOR_READY_EVENT } from '~/editor/constants';
import Editor from '~/editor/editor_lite';
-import { CONTENT_UPDATE_DEBOUNCE } from '~/editor/constants';
function initEditorLite({ el, ...args }) {
const editor = new Editor({
@@ -88,6 +88,7 @@ export default {
return this.editor;
},
},
+ readyEvent: EDITOR_READY_EVENT,
};
</script>
<template>
@@ -95,7 +96,7 @@ export default {
:id="`editor-lite-${fileGlobalId}`"
ref="editor"
data-editor-loading
- @editor-ready="$emit('editor-ready')"
+ @[$options.readyEvent]="$emit($options.readyEvent)"
>
<pre class="editor-loading-content">{{ value }}</pre>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/index.vue b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
index 27933f87929..4ec54b33bce 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/index.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
@@ -1,10 +1,10 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import Mousetrap from 'mousetrap';
import VirtualList from 'vue-virtual-scroll-list';
-import { GlIcon } from '@gitlab/ui';
-import Item from './item.vue';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
+import Item from './item.vue';
export const MAX_FILE_FINDER_RESULTS = 40;
export const FILE_FINDER_ROW_HEIGHT = 55;
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/item.vue b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
index 4c496ba3f9b..7816c1d74ec 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/item.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
@@ -1,8 +1,8 @@
<script>
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
import { GlIcon } from '@gitlab/ui';
-import FileIcon from '../file_icon.vue';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
import ChangedFileIcon from '../changed_file_icon.vue';
+import FileIcon from '../file_icon.vue';
const MAX_PATH_LENGTH = 60;
diff --git a/app/assets/javascripts/vue_shared/components/file_icon.vue b/app/assets/javascripts/vue_shared/components/file_icon.vue
index 6190b07962d..8ac8a3beb7d 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/file_icon.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import getIconForFile from './file_icon/file_icon_map';
import { FILE_SYMLINK_MODE } from '../constants';
+import getIconForFile from './file_icon/file_icon_map';
/* This is a re-usable vue component for rendering a svg sprite
icon
@@ -90,6 +90,12 @@ export default {
<svg v-else-if="!folder" :key="spriteHref" :class="[iconSizeClass, cssClasses]">
<use v-bind="{ 'xlink:href': spriteHref }" />
</svg>
- <gl-icon v-else :name="folderIconName" :size="size" class="folder-icon" />
+ <gl-icon
+ v-else
+ :name="folderIconName"
+ :size="size"
+ class="folder-icon"
+ data-qa-selector="folder_icon_content"
+ />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 96567111bbc..0b0a416b7ef 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -1,8 +1,8 @@
<script>
import { GlTruncate } from '@gitlab/ui';
-import FileHeader from '~/vue_shared/components/file_row_header.vue';
-import FileIcon from '~/vue_shared/components/file_icon.vue';
import { escapeFileUrl } from '~/lib/utils/url_utility';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
+import FileHeader from '~/vue_shared/components/file_row_header.vue';
export default {
name: 'FileRow',
@@ -147,6 +147,7 @@ export default {
:style="levelIndentation"
class="file-row-name"
data-qa-selector="file_name_content"
+ :data-qa-file-name="file.name"
data-testid="file-row-name-container"
:class="[fileClasses, { 'str-truncated': !truncateMiddle, 'gl-min-w-0': truncateMiddle }]"
>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
index a4c5ca28494..97a8f681faf 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
@@ -10,14 +10,13 @@ import {
} from '@gitlab/ui';
import RecentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys';
-import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-
-import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
+import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { __ } from '~/locale';
-import { stripQuotes, uniqueTokens } from './filtered_search_utils';
import { SortDirection } from './constants';
+import { stripQuotes, uniqueTokens } from './filtered_search_utils';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
index 411654d15f4..4dfc61f1fff 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js
@@ -1,7 +1,7 @@
+import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
-import Api from '~/api';
import * as types from './mutation_types';
export const setEndpoints = ({ commit }, params) => {
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/index.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/index.js
index 665bb29a17e..cdcbecdd313 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/index.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/index.js
@@ -1,6 +1,6 @@
-import state from './state';
import * as actions from './actions';
import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
index d59e9200e6c..9c2a644b7a9 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue
@@ -9,12 +9,11 @@ import {
import { debounce } from 'lodash';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { __ } from '~/locale';
-
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
-import { stripQuotes } from '../filtered_search_utils';
import { DEFAULT_LABELS, DEBOUNCE_DELAY } from '../constants';
+import { stripQuotes } from '../filtered_search_utils';
export default {
components: {
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 0dd7820073a..cda6e4d6726 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
@@ -10,8 +10,8 @@ import { debounce } from 'lodash';
import createFlash from '~/flash';
import { __ } from '~/locale';
-import { stripQuotes } from '../filtered_search_utils';
import { DEFAULT_MILESTONES, DEBOUNCE_DELAY } from '../constants';
+import { stripQuotes } from '../filtered_search_utils';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
index 809932b0f29..44c3fc34ba6 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/utils.js
@@ -84,7 +84,7 @@ export const tributeConfig = {
value.type === groupType ? last(value.name.split(' / ')) : `${value.name}${value.username}`,
menuItemLimit: memberLimit,
menuItemTemplate: ({ original }) => {
- const commonClasses = 'gl-avatar gl-avatar-s24 gl-flex-shrink-0';
+ 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`;
@@ -111,7 +111,7 @@ export const tributeConfig = {
return `
<div class="gl-display-flex gl-align-items-center">
${avatar}
- <div class="gl-font-sm gl-line-height-normal gl-ml-3">
+ <div class="gl-line-height-normal gl-ml-4">
<div>${escape(displayName)}${count}</div>
<div class="gl-text-gray-700">${escape(parentGroupOrUsername)}</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue b/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue
index e14f6a04d3c..96d99faa952 100644
--- a/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_modal_vuex.vue
@@ -1,6 +1,7 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlModal } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
/**
* This component keeps the GlModal's visibility in sync with the given vuex module.
@@ -46,11 +47,11 @@ export default {
},
}),
bsShow() {
- this.$root.$emit('bv::show::modal', this.modalId);
+ this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
bsHide() {
// $root.$emit is a workaround because other b-modal approaches don't work yet with gl-modal
- this.$root.$emit('bv::hide::modal', this.modalId);
+ this.$root.$emit(BV_HIDE_MODAL, this.modalId);
},
cancel() {
this.$emit('cancel');
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 79d9ba6df57..80ca62a0e9b 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,11 +1,11 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlButton, GlTooltip } from '@gitlab/ui';
+import { glEmojiTag } from '../../emoji';
+import { __, sprintf } from '../../locale';
import CiIconBadge from './ci_badge_link.vue';
import TimeagoTooltip from './time_ago_tooltip.vue';
import UserAvatarImage from './user_avatar/user_avatar_image.vue';
-import { glEmojiTag } from '../../emoji';
-import { __, sprintf } from '../../locale';
/**
* Renders header component for job and pipeline page based on UI mockups
@@ -105,7 +105,7 @@ export default {
<section class="header-main-content">
<ci-icon-badge :status="status" />
- <strong> {{ itemName }} #{{ itemId }} </strong>
+ <strong data-testid="ci-header-item-text"> {{ itemName }} #{{ itemId }} </strong>
<template v-if="shouldRenderTriggeredLabel">{{ __('triggered') }}</template>
<template v-else>{{ __('created') }}</template>
@@ -142,13 +142,13 @@ export default {
</template>
</section>
- <section v-if="$slots.default" data-testid="headerButtons" class="gl-display-flex">
+ <section v-if="$slots.default" data-testid="ci-header-action-buttons" class="gl-display-flex">
<slot></slot>
</section>
<gl-button
v-if="hasSidebarButton"
class="d-sm-none js-sidebar-build-toggle gl-ml-auto"
- icon="angle-double-left"
+ icon="chevron-double-lg-left"
:aria-label="__('Toggle sidebar')"
@click="onClickSidebarButton"
/>
diff --git a/app/assets/javascripts/vue_shared/components/help_popover.vue b/app/assets/javascripts/vue_shared/components/help_popover.vue
index 821ae6cec52..051c65bae70 100644
--- a/app/assets/javascripts/vue_shared/components/help_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/help_popover.vue
@@ -1,8 +1,5 @@
<script>
-import $ from 'jquery';
-import { GlButton } from '@gitlab/ui';
-import { inserted } from '~/feature_highlight/feature_highlight_helper';
-import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover';
+import { GlButton, GlPopover } from '@gitlab/ui';
/**
* Render a button with a question mark icon
@@ -12,6 +9,7 @@ export default {
name: 'HelpPopover',
components: {
GlButton,
+ GlPopover,
},
props: {
options: {
@@ -20,28 +18,20 @@ export default {
default: () => ({}),
},
},
- mounted() {
- const $el = $(this.$el);
-
- $el
- .popover({
- html: true,
- trigger: 'focus',
- container: 'body',
- placement: 'top',
- template:
- '<div class="popover" role="tooltip"><div class="arrow"></div><p class="popover-header"></p><div class="popover-body"></div></div>',
- ...this.options,
- })
- .on('mouseenter', mouseenter)
- .on('mouseleave', debouncedMouseleave(300))
- .on('inserted.bs.popover', inserted)
- .on('show.bs.popover', () => {
- window.addEventListener('scroll', togglePopover.bind($el, false), { once: true });
- });
- },
};
</script>
<template>
- <gl-button variant="link" icon="question" tabindex="0" />
+ <span>
+ <gl-button ref="popoverTrigger" variant="link" icon="question" tabindex="0" />
+ <gl-popover triggers="hover focus" :target="() => $refs.popoverTrigger.$el" v-bind="options">
+ <template #title>
+ <!-- eslint-disable-next-line vue/no-v-html -->
+ <span v-html="options.title"></span>
+ </template>
+ <template #default>
+ <!-- eslint-disable-next-line vue/no-v-html -->
+ <div v-html="options.content"></div>
+ </template>
+ </gl-popover>
+ </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue b/app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue
index 37995b434c4..56adbe8c606 100644
--- a/app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue
+++ b/app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue
@@ -1,6 +1,6 @@
<script>
-import { mapGetters } from 'vuex';
import { GlIcon } from '@gitlab/ui';
+import { mapGetters } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue b/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
index c745ea61f8b..6a0c21602bd 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
@@ -1,8 +1,8 @@
<script>
import { GlTooltip, GlIcon } from '@gitlab/ui';
+import { timeFor, parsePikadayDate, dateInWords } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { timeFor, parsePikadayDate, dateInWords } from '~/lib/utils/datetime_utility';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
index 2ff4033a07e..be0c843ef00 100644
--- a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
@@ -2,12 +2,12 @@
/* eslint-disable vue/no-v-html */
import '~/commons/bootstrap';
import { GlIcon, GlTooltip, GlTooltipDirective, GlButton } from '@gitlab/ui';
-import { sprintf } from '~/locale';
-import IssueMilestone from './issue_milestone.vue';
-import IssueAssignees from './issue_assignees.vue';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import { sprintf } from '~/locale';
import relatedIssuableMixin from '../../mixins/related_issuable_mixin';
import CiIcon from '../ci_icon.vue';
+import IssueAssignees from './issue_assignees.vue';
+import IssueMilestone from './issue_milestone.vue';
export default {
name: 'IssueItem',
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index b6e167524aa..25d01dc550f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -1,19 +1,19 @@
<script>
/* eslint-disable vue/no-v-html */
+import { GlIcon } from '@gitlab/ui';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { unescape } from 'lodash';
-import { GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import { stripHtml } from '~/lib/utils/text_utility';
import { deprecatedCreateFlash as Flash } from '~/flash';
import GLForm from '~/gl_form';
-import MarkdownHeader from './header.vue';
-import MarkdownToolbar from './toolbar.vue';
+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 axios from '~/lib/utils/axios_utils';
+import MarkdownHeader from './header.vue';
+import MarkdownToolbar from './toolbar.vue';
export default {
components: {
@@ -110,11 +110,6 @@ export default {
return this.referencedUsers.length >= referencedUsersThreshold;
},
lineContent() {
- const [firstSuggestion] = this.suggestions;
- if (firstSuggestion) {
- return firstSuggestion.from_content;
- }
-
if (this.line) {
const { rich_text: richText, text } = this.line;
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 173d192dab0..5bc1786d692 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,8 +1,8 @@
<script>
-import $ from 'jquery';
import { GlPopover, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import $ from 'jquery';
import { getSelectedFragment } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm';
import ToolbarButton from './toolbar_button.vue';
@@ -172,6 +172,7 @@ export default {
:cursor-offset="4"
:tag-content="lineContent"
icon="doc-code"
+ data-qa-selector="suggestion_button"
class="js-suggestion-btn"
@click="handleSuggestDismissed"
/>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
index 93a270b8a97..bcd8c02e968 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -1,7 +1,7 @@
<script>
+import { selectDiffLines } from '../lib/utils/diff_utils';
import SuggestionDiffHeader from './suggestion_diff_header.vue';
import SuggestionDiffRow from './suggestion_diff_row.vue';
-import { selectDiffLines } from '../lib/utils/diff_utils';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index 63341b433e0..4c6fa71398d 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -88,7 +88,12 @@ export default {
applySuggestion(message) {
if (!this.canApply) return;
this.isApplyingSingle = true;
- this.$emit('apply', this.applySuggestionCallback, message);
+
+ this.$emit(
+ 'apply',
+ this.applySuggestionCallback,
+ gon.features?.suggestionsCustomCommit ? message : undefined,
+ );
},
applySuggestionCallback() {
this.isApplyingSingle = false;
@@ -131,6 +136,7 @@ export default {
<gl-button
v-gl-tooltip.viewport="__('This also resolves all related threads')"
class="btn-inverted js-apply-batch-btn btn-grouped"
+ data-qa-selector="apply_suggestions_batch_button"
:disabled="isApplying"
variant="success"
@click="applySuggestionBatch"
@@ -145,6 +151,7 @@ export default {
<gl-button
v-if="suggestionsCount > 1 && canBeBatched && !isDisableButton"
class="btn-inverted js-add-to-batch-btn btn-grouped"
+ data-qa-selector="add_suggestion_batch_button"
:disabled="isDisableButton"
@click="addSuggestionToBatch"
>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 5ee51764555..53d1cca7af3 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -1,9 +1,9 @@
<script>
-import Vue from 'vue';
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import Vue from 'vue';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import { __ } from '~/locale';
import SuggestionDiff from './suggestion_diff.vue';
-import { deprecatedCreateFlash as Flash } from '~/flash';
export default {
directives: {
@@ -64,6 +64,11 @@ export default {
mounted() {
this.renderSuggestions();
},
+ beforeDestroy() {
+ if (this.suggestionsWatch) {
+ this.suggestionsWatch();
+ }
+ },
methods: {
renderSuggestions() {
// swaps out suggestion(s) markdown with rich diff components
@@ -108,6 +113,13 @@ export default {
},
});
+ // We're using `$watch` as `suggestionsCount` updates do not
+ // propagate to this component for some unknown reason while
+ // using a traditional prop watcher.
+ this.suggestionsWatch = this.$watch('suggestionsCount', () => {
+ suggestionDiff.suggestionsCount = this.suggestionsCount;
+ });
+
suggestionDiff.$on('apply', ({ suggestionId, callback, message }) => {
this.$emit('apply', { suggestionId, callback, flashContainer: this.$el, message });
});
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 15c5b9d6733..387b100a04f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -60,9 +60,7 @@ export default {
</div>
<span v-if="canAttachFile" class="uploading-container">
<span class="uploading-progress-container hide">
- <template>
- <gl-icon name="media" />
- </template>
+ <gl-icon name="media" />
<span class="attaching-file-message"></span>
<!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
<span class="uploading-progress">0%</span>
diff --git a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
index e3a7f144321..7b36d57dfbf 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -2,6 +2,7 @@
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import Clipboard from 'clipboard';
import { uniqueId } from 'lodash';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
export default {
components: {
@@ -76,7 +77,7 @@ export default {
});
this.clipboard
.on('success', (e) => {
- this.$root.$emit('bv::hide::tooltip', this.id);
+ this.$root.$emit(BV_HIDE_TOOLTIP, this.id);
this.$emit('success', e);
// Clear the selection and blur the trigger so it loses its border
e.clearSelection();
diff --git a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
index 653ee7f20e9..a069d1cd756 100644
--- a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
@@ -1,6 +1,6 @@
<script>
-import $ from 'jquery';
import { GlBadge, GlTabs, GlTab } from '@gitlab/ui';
+import $ from 'jquery';
/**
* Given an array of tabs, renders non linked bootstrap tabs.
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index cc1203f83f0..50972a8c32c 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -18,8 +18,6 @@
* }"
* />
*/
-import $ from 'jquery';
-import { mapGetters, mapActions, mapState } from 'vuex';
import {
GlButton,
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
@@ -27,12 +25,14 @@ import {
GlIcon,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
+import $ from 'jquery';
+import { mapGetters, mapActions, mapState } from 'vuex';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
+import initMRPopovers from '~/mr_popover/';
import noteHeader from '~/notes/components/note_header.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import TimelineEntryItem from './timeline_entry_item.vue';
import { spriteIcon } from '../../../lib/utils/common_utils';
-import initMRPopovers from '~/mr_popover/';
+import TimelineEntryItem from './timeline_entry_item.vue';
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
index d03987bbbe0..e2591362611 100644
--- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue
@@ -1,13 +1,13 @@
<script>
import { GlAlert, GlBadge, GlPagination, GlTab, GlTabs } from '@gitlab/ui';
import Api from '~/api';
-import Tracking from '~/tracking';
-import { __ } from '~/locale';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
-import { initialPaginationState, defaultI18n, defaultPageSize } from './constants';
-import { isAny } from './utils';
+import { __ } from '~/locale';
+import Tracking from '~/tracking';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
+import { initialPaginationState, defaultI18n, defaultPageSize } from './constants';
+import { isAny } from './utils';
export default {
defaultI18n,
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index 65bd4e4382d..ddc8bbf9b27 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
@@ -2,9 +2,9 @@
/* eslint-disable vue/no-v-html */
import { GlButton, GlIcon } from '@gitlab/ui';
import { isString } from 'lodash';
-import ProjectAvatar from '~/vue_shared/components/project_avatar/default.vue';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
+import ProjectAvatar from '~/vue_shared/components/project_avatar/default.vue';
export default {
name: 'ProjectListItem',
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
index e659e2155fb..a0c5a0559de 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
@@ -1,6 +1,6 @@
<script>
-import { debounce } from 'lodash';
import { GlLoadingIcon, GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
+import { debounce } from 'lodash';
import { __, n__, sprintf } from '~/locale';
import ProjectListItem from './project_list_item.vue';
diff --git a/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue b/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue
index 08ee23d25bf..bc7f8a2b17a 100644
--- a/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue
@@ -1,7 +1,7 @@
<script>
import { uniqueId } from 'lodash';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Tracking from '~/tracking';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
name: 'CodeInstruction',
diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
index 8965dba3e83..9db5d6953d7 100644
--- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -54,19 +54,17 @@ export default {
class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1"
:class="optionalClasses"
>
- <div class="gl-display-flex gl-align-items-center gl-py-5">
+ <div class="gl-display-flex gl-align-items-center gl-py-3">
<div
v-if="$slots['left-action']"
- class="gl-w-7 gl-display-none gl-display-sm-flex gl-justify-content-start gl-pl-2"
+ class="gl-w-7 gl-display-none gl-sm-display-flex gl-justify-content-start gl-pl-2"
>
<slot name="left-action"></slot>
</div>
<div
class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1"
>
- <div
- class="gl-display-flex gl-flex-direction-column gl-justify-content-space-between gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
- >
+ <div class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1">
<div
v-if="$slots['left-primary']"
class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0"
@@ -77,13 +75,13 @@ export default {
:selected="isDetailsShown"
icon="ellipsis_h"
size="small"
- class="gl-ml-2 gl-display-none gl-display-sm-block"
+ class="gl-ml-2 gl-display-none gl-sm-display-block"
@click="toggleDetails"
/>
</div>
<div
v-if="$slots['left-secondary']"
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
>
<slot name="left-secondary"></slot>
</div>
@@ -99,7 +97,7 @@ export default {
</div>
<div
v-if="$slots['right-secondary']"
- class="gl-display-flex gl-align-items-center gl-mt-1 gl-min-h-6"
+ class="gl-display-flex gl-align-items-center gl-min-h-6"
>
<slot name="right-secondary"></slot>
</div>
@@ -107,7 +105,7 @@ export default {
</div>
<div
v-if="$slots['right-action']"
- class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-1"
+ class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
>
<slot name="right-action"></slot>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
new file mode 100644
index 00000000000..62453a25f62
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue
@@ -0,0 +1,90 @@
+<script>
+import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
+
+const ASCENDING_ORDER = 'asc';
+const DESCENDING_ORDER = 'desc';
+
+export default {
+ components: {
+ GlSorting,
+ GlSortingItem,
+ GlFilteredSearch,
+ },
+ props: {
+ filter: {
+ type: Array,
+ required: true,
+ },
+ sorting: {
+ type: Object,
+ required: true,
+ },
+ tokens: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ sortableFields: {
+ type: Array,
+ required: true,
+ },
+ },
+ computed: {
+ internalFilter: {
+ get() {
+ return this.filter;
+ },
+ set(value) {
+ this.$emit('filter:changed', value);
+ },
+ },
+ sortText() {
+ const field = this.sortableFields.find((s) => s.orderBy === this.sorting.orderBy);
+ return field ? field.label : '';
+ },
+ isSortAscending() {
+ return this.sorting.sort === ASCENDING_ORDER;
+ },
+ },
+ methods: {
+ onDirectionChange() {
+ const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ORDER;
+ this.$emit('sorting:changed', { sort });
+ },
+ onSortItemClick(item) {
+ this.$emit('sorting:changed', { orderBy: item });
+ },
+ clearSearch() {
+ this.$emit('filter:changed', []);
+ this.$emit('filter:submit');
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100">
+ <gl-filtered-search
+ v-model="internalFilter"
+ class="gl-mr-4 gl-flex-fill-1"
+ :placeholder="__('Filter results')"
+ :available-tokens="tokens"
+ @submit="$emit('filter:submit')"
+ @clear="clearSearch"
+ />
+ <gl-sorting
+ :text="sortText"
+ :is-ascending="isSortAscending"
+ @sortDirectionChange="onDirectionChange"
+ >
+ <gl-sorting-item
+ v-for="item in sortableFields"
+ ref="packageListSortItem"
+ :key="item.orderBy"
+ @click="onSortItemClick(item.orderBy)"
+ >
+ {{ item.label }}
+ </gl-sorting-item>
+ </gl-sorting>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
index 5d4c192c78f..8988dab85d2 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/rich_content_editor.vue
@@ -2,9 +2,9 @@
import 'codemirror/lib/codemirror.css';
import '@toast-ui/editor/dist/toastui-editor.css';
+import { EDITOR_TYPES, EDITOR_HEIGHT, EDITOR_PREVIEW_STYLE, CUSTOM_EVENTS } from './constants';
import AddImageModal from './modals/add_image/add_image_modal.vue';
import InsertVideoModal from './modals/insert_video_modal.vue';
-import { EDITOR_TYPES, EDITOR_HEIGHT, EDITOR_PREVIEW_STYLE, CUSTOM_EVENTS } from './constants';
import {
registerHTMLToMarkdownRenderer,
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
index 624b5b09b38..6ffd280e005 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
@@ -1,12 +1,12 @@
import { union, mapValues } from 'lodash';
-import renderBlockHtml from './renderers/render_html_block';
+import renderAttributeDefinition from './renderers/render_attribute_definition';
+import renderFontAwesomeHtmlInline from './renderers/render_font_awesome_html_inline';
import renderHeading from './renderers/render_heading';
+import renderBlockHtml from './renderers/render_html_block';
import renderIdentifierInstanceText from './renderers/render_identifier_instance_text';
import renderIdentifierParagraph from './renderers/render_identifier_paragraph';
-import renderFontAwesomeHtmlInline from './renderers/render_font_awesome_html_inline';
-import renderSoftbreak from './renderers/render_softbreak';
-import renderAttributeDefinition from './renderers/render_attribute_definition';
import renderListItem from './renderers/render_list_item';
+import renderSoftbreak from './renderers/render_softbreak';
const htmlInlineRenderers = [renderFontAwesomeHtmlInline];
const htmlBlockRenderers = [renderBlockHtml];
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
index be78651d38d..026a4069d9b 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
@@ -1,9 +1,9 @@
-import Vue from 'vue';
import { defaults } from 'lodash';
+import Vue from 'vue';
+import { TOOLBAR_ITEM_CONFIGS, VIDEO_ATTRIBUTES } from '../constants';
import ToolbarItem from '../toolbar_item.vue';
-import buildHtmlToMarkdownRenderer from './build_html_to_markdown_renderer';
import buildCustomHTMLRenderer from './build_custom_renderer';
-import { TOOLBAR_ITEM_CONFIGS, VIDEO_ATTRIBUTES } from '../constants';
+import buildHtmlToMarkdownRenderer from './build_html_to_markdown_renderer';
import sanitizeHTML from './sanitize_html';
const buildWrapper = (propsData) => {
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
index 30012c1123f..710b807275b 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_html_block.js
@@ -1,6 +1,6 @@
-import { buildUneditableHtmlAsTextTokens } from './build_uneditable_token';
-import { ALLOWED_VIDEO_ORIGINS } from '../../constants';
import { getURLOrigin } from '~/lib/utils/url_utility';
+import { ALLOWED_VIDEO_ORIGINS } from '../../constants';
+import { buildUneditableHtmlAsTextTokens } from './build_uneditable_token';
const isVideoFrame = (html) => {
const parser = new DOMParser();
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
index cb0f1d51cb1..486d88466b7 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/sanitize_html.js
@@ -1,6 +1,6 @@
import createSanitizer from 'dompurify';
-import { ALLOWED_VIDEO_ORIGINS } from '../constants';
import { getURLOrigin } from '~/lib/utils/url_utility';
+import { ALLOWED_VIDEO_ORIGINS } from '../constants';
const sanitizer = createSanitizer(window);
const ADD_TAGS = ['iframe'];
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js b/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js
new file mode 100644
index 00000000000..facace0d809
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js
@@ -0,0 +1,18 @@
+import { s__ } from '~/locale';
+
+export const PLATFORMS_WITHOUT_ARCHITECTURES = ['docker', 'kubernetes'];
+
+export const INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES = {
+ docker: {
+ instructions: s__(
+ 'Runners|To install Runner in a container follow the instructions described in the GitLab documentation',
+ ),
+ link: 'https://docs.gitlab.com/runner/install/docker.html',
+ },
+ kubernetes: {
+ instructions: s__(
+ 'Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation.',
+ ),
+ link: 'https://docs.gitlab.com/runner/install/kubernetes.html',
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
new file mode 100644
index 00000000000..ff0626167a9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql
@@ -0,0 +1,20 @@
+query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) {
+ runnerPlatforms {
+ nodes {
+ name
+ humanReadableName
+ architectures {
+ nodes {
+ name
+ downloadLocation
+ }
+ }
+ }
+ }
+ project(fullPath: $projectPath) {
+ id
+ }
+ group(fullPath: $groupPath) {
+ id
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
new file mode 100644
index 00000000000..643c1991807
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql
@@ -0,0 +1,16 @@
+query runnerSetupInstructions(
+ $platform: String!
+ $architecture: String!
+ $projectId: ID!
+ $groupId: ID!
+) {
+ runnerSetup(
+ platform: $platform
+ architecture: $architecture
+ projectId: $projectId
+ groupId: $groupId
+ ) {
+ installInstructions
+ registerInstructions
+ }
+}
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
new file mode 100644
index 00000000000..1d6db576942
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -0,0 +1,261 @@
+<script>
+import {
+ GlAlert,
+ GlButton,
+ GlModal,
+ GlModalDirective,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+} from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
+import {
+ PLATFORMS_WITHOUT_ARCHITECTURES,
+ INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES,
+} from './constants';
+import getRunnerPlatforms from './graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructions from './graphql/queries/get_runner_setup.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlIcon,
+ ModalCopyButton,
+ },
+ directives: {
+ GlModalDirective,
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ groupPath: {
+ default: '',
+ },
+ },
+ apollo: {
+ runnerPlatforms: {
+ query: getRunnerPlatforms,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ groupPath: this.groupPath,
+ };
+ },
+ error() {
+ this.showAlert = true;
+ },
+ result({ data }) {
+ this.project = data?.project;
+ this.group = data?.group;
+
+ this.selectPlatform(this.platforms[0].name);
+ },
+ },
+ },
+ data() {
+ return {
+ showAlert: false,
+ selectedPlatformArchitectures: [],
+ selectedPlatform: {
+ name: '',
+ },
+ selectedArchitecture: {},
+ runnerPlatforms: {},
+ instructions: {},
+ project: {},
+ group: {},
+ };
+ },
+ computed: {
+ isPlatformSelected() {
+ return Object.keys(this.selectedPlatform).length > 0;
+ },
+ instructionsEmpty() {
+ return Object.keys(this.instructions).length === 0;
+ },
+ groupId() {
+ return this.group?.id ?? '';
+ },
+ projectId() {
+ return this.project?.id ?? '';
+ },
+ platforms() {
+ return this.runnerPlatforms?.nodes;
+ },
+ hasArchitecureList() {
+ return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatform?.name);
+ },
+ instructionsWithoutArchitecture() {
+ return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.instructions;
+ },
+ runnerInstallationLink() {
+ return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.link;
+ },
+ },
+ methods: {
+ selectPlatform(name) {
+ this.selectedPlatform = this.platforms.find((platform) => platform.name === name);
+ if (this.hasArchitecureList) {
+ this.selectedPlatformArchitectures = this.selectedPlatform?.architectures?.nodes;
+ [this.selectedArchitecture] = this.selectedPlatformArchitectures;
+ this.selectArchitecture(this.selectedArchitecture);
+ }
+ },
+ selectArchitecture(architecture) {
+ this.selectedArchitecture = architecture;
+
+ this.$apollo.addSmartQuery('instructions', {
+ variables() {
+ return {
+ platform: this.selectedPlatform.name,
+ architecture: this.selectedArchitecture.name,
+ projectId: this.projectId,
+ groupId: this.groupId,
+ };
+ },
+ query: getRunnerSetupInstructions,
+ update(data) {
+ return data?.runnerSetup;
+ },
+ error() {
+ this.showAlert = true;
+ },
+ });
+ },
+ toggleAlert(state) {
+ this.showAlert = state;
+ },
+ },
+ modalId: 'installation-instructions-modal',
+ i18n: {
+ installARunner: s__('Runners|Install a Runner'),
+ architecture: s__('Runners|Architecture'),
+ downloadInstallBinary: s__('Runners|Download and Install Binary'),
+ downloadLatestBinary: s__('Runners|Download Latest Binary'),
+ registerRunner: s__('Runners|Register Runner'),
+ method: __('Method'),
+ fetchError: s__('Runners|An error has occurred fetching instructions'),
+ instructions: s__('Runners|Show Runner installation instructions'),
+ copyInstructions: s__('Runners|Copy instructions'),
+ },
+ closeButton: {
+ text: __('Close'),
+ attributes: [{ variant: 'default' }],
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-button
+ v-gl-modal-directive="$options.modalId"
+ class="gl-mt-4"
+ data-testid="show-modal-button"
+ >
+ {{ $options.i18n.instructions }}
+ </gl-button>
+ <gl-modal
+ :modal-id="$options.modalId"
+ :title="$options.i18n.installARunner"
+ :action-secondary="$options.closeButton"
+ >
+ <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)">
+ {{ $options.i18n.fetchError }}
+ </gl-alert>
+ <h5>{{ __('Environment') }}</h5>
+ <gl-button-group class="gl-mb-5">
+ <gl-button
+ v-for="platform in platforms"
+ :key="platform.name"
+ data-testid="platform-button"
+ @click="selectPlatform(platform.name)"
+ >
+ {{ platform.humanReadableName }}
+ </gl-button>
+ </gl-button-group>
+ <template v-if="hasArchitecureList">
+ <template v-if="isPlatformSelected">
+ <h5>
+ {{ $options.i18n.architecture }}
+ </h5>
+ <gl-dropdown class="gl-mb-5" :text="selectedArchitecture.name">
+ <gl-dropdown-item
+ v-for="architecture in selectedPlatformArchitectures"
+ :key="architecture.name"
+ data-testid="architecture-dropdown-item"
+ @click="selectArchitecture(architecture)"
+ >
+ {{ architecture.name }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <div class="gl-display-flex gl-align-items-center gl-mb-5">
+ <h5>{{ $options.i18n.downloadInstallBinary }}</h5>
+ <gl-button
+ class="gl-ml-auto"
+ :href="selectedArchitecture.downloadLocation"
+ download
+ data-testid="binary-download-button"
+ >
+ {{ $options.i18n.downloadLatestBinary }}
+ </gl-button>
+ </div>
+ </template>
+ <template v-if="!instructionsEmpty">
+ <div class="gl-display-flex">
+ <pre
+ class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="binary-instructions"
+ >
+
+ {{ instructions.installInstructions }}
+ </pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyInstructions"
+ :text="instructions.installInstructions"
+ :modal-id="$options.modalId"
+ css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ />
+ </div>
+
+ <hr />
+ <h5 class="gl-mb-5">{{ $options.i18n.registerRunner }}</h5>
+ <h5 class="gl-mb-5">{{ $options.i18n.method }}</h5>
+ <div class="gl-display-flex">
+ <pre
+ class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
+ data-testid="runner-instructions"
+ >
+ {{ instructions.registerInstructions }}
+ </pre
+ >
+ <modal-copy-button
+ :title="$options.i18n.copyInstructions"
+ :text="instructions.registerInstructions"
+ :modal-id="$options.modalId"
+ css-classes="gl-align-self-start gl-ml-2 gl-mt-2"
+ category="tertiary"
+ />
+ </div>
+ </template>
+ </template>
+ <template v-else>
+ <div>
+ <p>{{ instructionsWithoutArchitecture }}</p>
+ <gl-button :href="runnerInstallationLink">
+ <gl-icon name="external-link" />
+ {{ s__('Runners|View installation instructions') }}
+ </gl-button>
+ </div>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/settings/settings_block.vue b/app/assets/javascripts/vue_shared/components/settings/settings_block.vue
new file mode 100644
index 00000000000..31094b985a2
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/settings/settings_block.vue
@@ -0,0 +1,45 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: { GlButton },
+ props: {
+ defaultExpanded: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ },
+ data() {
+ return {
+ sectionExpanded: false,
+ };
+ },
+ computed: {
+ expanded() {
+ return this.defaultExpanded || this.sectionExpanded;
+ },
+ toggleText() {
+ return this.expanded ? __('Collapse') : __('Expand');
+ },
+ },
+};
+</script>
+
+<template>
+ <section class="settings no-animate" :class="{ expanded }">
+ <div class="settings-header">
+ <h4><slot name="title"></slot></h4>
+ <gl-button @click="sectionExpanded = !sectionExpanded">
+ {{ toggleText }}
+ </gl-button>
+ <p>
+ <slot name="description"></slot>
+ </p>
+ </div>
+ <div class="settings-content">
+ <slot></slot>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
index 80c61627b8f..a1dca65a423 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
@@ -1,7 +1,7 @@
<script>
+import { dateInWords, timeFor } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { dateInWords, timeFor } from '~/lib/utils/datetime_utility';
import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
index 6caf8bc92c2..075681de320 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
@@ -1,10 +1,10 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { dateInWords } from '../../../lib/utils/datetime_utility';
import datePicker from '../pikaday.vue';
-import toggleSidebar from './toggle_sidebar.vue';
import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
-import { dateInWords } from '../../../lib/utils/datetime_utility';
-import { __ } from '~/locale';
+import toggleSidebar from './toggle_sidebar.vue';
export default {
name: 'SidebarDatePicker',
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
index 22d86ee25d1..88c4d132d61 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
@@ -1,20 +1,19 @@
<script>
-import $ from 'jquery';
import { GlLoadingIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
+import $ from 'jquery';
import LabelsSelect from '~/labels_select';
+import { __ } from '~/locale';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-import DropdownTitle from './dropdown_title.vue';
-import DropdownValue from './dropdown_value.vue';
-import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
+import { DropdownVariant } from '../labels_select_vue/constants';
import DropdownButton from './dropdown_button.vue';
+import DropdownCreateLabel from './dropdown_create_label.vue';
+import DropdownFooter from './dropdown_footer.vue';
import DropdownHeader from './dropdown_header.vue';
import DropdownSearchInput from './dropdown_search_input.vue';
-import DropdownFooter from './dropdown_footer.vue';
-import DropdownCreateLabel from './dropdown_create_label.vue';
-
-import { DropdownVariant } from '../labels_select_vue/constants';
+import DropdownTitle from './dropdown_title.vue';
+import DropdownValue from './dropdown_value.vue';
+import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
export default {
DropdownVariant,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
index c65266fce5a..60111210f5d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
@@ -1,6 +1,6 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
import { GlButton, GlIcon } from '@gitlab/ui';
+import { mapActions, mapGetters } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
index 267c3be5f50..e3704198ad0 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
@@ -1,8 +1,8 @@
<script>
import { mapState } from 'vuex';
-import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue';
import DropdownContentsCreateView from './dropdown_contents_create_view.vue';
+import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
index 41308e352e3..f8cc981ba3d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
index a365673f7a1..6065b6c160c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState, mapGetters, mapActions } from 'vuex';
import {
GlIntersectionObserver,
GlLoadingIcon,
@@ -8,6 +7,7 @@ import {
GlLink,
} from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { mapState, mapGetters, mapActions } from 'vuex';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
index 2d6a4a9758c..5d1663bc1fd 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState, mapActions } from 'vuex';
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
index a6f99289df4..f173c8db540 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
@@ -1,6 +1,6 @@
<script>
-import { mapState } from 'vuex';
import { GlLabel } from '@gitlab/ui';
+import { mapState } from 'vuex';
import { isScopedLabel } from '~/lib/utils/common_utils';
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index 683889b8611..93fdae19a8d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
@@ -7,14 +7,12 @@ import { __ } from '~/locale';
import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
-import labelsSelectModule from './store';
-
-import DropdownTitle from './dropdown_title.vue';
-import DropdownValue from './dropdown_value.vue';
+import { DropdownVariant } from './constants';
import DropdownButton from './dropdown_button.vue';
import DropdownContents from './dropdown_contents.vue';
-
-import { DropdownVariant } from './constants';
+import DropdownTitle from './dropdown_title.vue';
+import DropdownValue from './dropdown_value.vue';
+import labelsSelectModule from './store';
Vue.use(Vuex);
@@ -35,11 +33,13 @@ export default {
},
allowLabelEdit: {
type: Boolean,
- required: true,
+ required: false,
+ default: false,
},
allowLabelCreate: {
type: Boolean,
- required: true,
+ required: false,
+ default: false,
},
allowMultiselect: {
type: Boolean,
@@ -48,7 +48,8 @@ export default {
},
allowScopedLabels: {
type: Boolean,
- required: true,
+ required: false,
+ default: false,
},
variant: {
type: String,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
index 14b46c1c431..89f96ab916b 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
@@ -1,6 +1,6 @@
import { deprecatedCreateFlash as flash } from '~/flash';
-import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
import * as types from './mutation_types';
export const setInitialState = ({ commit }, props) => commit(types.SET_INITIAL_STATE, props);
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
index 6de436ffd13..55716e1105e 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
@@ -1,5 +1,5 @@
-import * as types from './mutation_types';
import { DropdownVariant } from '../constants';
+import * as types from './mutation_types';
export default {
[types.SET_INITIAL_STATE](state, props) {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
index c5bbe1b33fb..132abcab82b 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/multiselect_dropdown.vue
@@ -20,7 +20,7 @@ export default {
</script>
<template>
- <gl-dropdown class="show" :text="text" :header-text="headerText">
+ <gl-dropdown class="show" :text="text" :header-text="headerText" @toggle="$emit('toggle')">
<slot name="search"></slot>
<gl-dropdown-form>
<slot name="items"></slot>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
deleted file mode 100644
index 612a0c02e82..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-query issueParticipants($id: IssueID!) {
- issue(id: $id) {
- participants {
- nodes {
- username
- name
- webUrl
- avatarUrl
- id
- }
- }
- }
-}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
new file mode 100644
index 00000000000..62c0b05426b
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
@@ -0,0 +1,19 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+query issueParticipants($fullPath: ID!, $iid: String!) {
+ project(fullPath: $fullPath) {
+ issuable: issue(iid: $iid) {
+ id
+ participants {
+ nodes {
+ ...User
+ }
+ }
+ assignees {
+ nodes {
+ ...User
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
new file mode 100644
index 00000000000..a75ce85a1dc
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql
@@ -0,0 +1,19 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+query getMrParticipants($fullPath: ID!, $iid: String!) {
+ project(fullPath: $fullPath) {
+ issuable: mergeRequest(iid: $iid) {
+ id
+ participants {
+ nodes {
+ ...User
+ }
+ }
+ assignees {
+ nodes {
+ ...User
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
deleted file mode 100644
index 9ead95a3801..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-mutation issueSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $projectPath: ID!) {
- issueSetAssignees(
- input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $projectPath }
- ) {
- issue {
- assignees {
- nodes {
- username
- id
- name
- webUrl
- avatarUrl
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql
new file mode 100644
index 00000000000..2eb9bb4b07b
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_issue_assignees.mutation.graphql
@@ -0,0 +1,21 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+mutation issueSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $fullPath: ID!) {
+ issueSetAssignees(
+ input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $fullPath }
+ ) {
+ issue {
+ id
+ assignees {
+ nodes {
+ ...User
+ }
+ }
+ participants {
+ nodes {
+ ...User
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql
new file mode 100644
index 00000000000..a0f15a07692
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/update_mr_assignees.mutation.graphql
@@ -0,0 +1,21 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+
+mutation mergeRequestSetAssignees($iid: String!, $assigneeUsernames: [String!]!, $fullPath: ID!) {
+ mergeRequestSetAssignees(
+ input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $fullPath }
+ ) {
+ mergeRequest {
+ id
+ assignees {
+ nodes {
+ ...User
+ }
+ }
+ participants {
+ nodes {
+ ...User
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/split_button.vue b/app/assets/javascripts/vue_shared/components/split_button.vue
index 61b317d0d1d..994fa68fb1a 100644
--- a/app/assets/javascripts/vue_shared/components/split_button.vue
+++ b/app/assets/javascripts/vue_shared/components/split_button.vue
@@ -1,6 +1,6 @@
<script>
-import { isString } from 'lodash';
import { GlDropdown, GlDropdownDivider, GlDropdownItem } from '@gitlab/ui';
+import { isString } from 'lodash';
const isValidItem = (item) =>
isString(item.eventName) && isString(item.title) && isString(item.description);
diff --git a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
index 9b6d0a87374..e639a2d966b 100644
--- a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
+++ b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
@@ -1,7 +1,7 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
import { roundDownFloat } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
export default {
directives: {
diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
index f1db26ff4fc..b9ee74d6a03 100644
--- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
@@ -1,8 +1,8 @@
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { secondsToHours } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
-import { secondsToHours } from '~/lib/utils/datetime_utility';
export default {
name: 'TimezoneDropdown',
diff --git a/app/assets/javascripts/vue_shared/components/todo_button.vue b/app/assets/javascripts/vue_shared/components/todo_button.vue
index a9d4f8403fa..935d222a1a9 100644
--- a/app/assets/javascripts/vue_shared/components/todo_button.vue
+++ b/app/assets/javascripts/vue_shared/components/todo_button.vue
@@ -15,7 +15,7 @@ export default {
},
computed: {
buttonLabel() {
- return this.isTodo ? __('Mark as done') : __('Add a To Do');
+ return this.isTodo ? __('Mark as done') : __('Add a to do');
},
},
};
diff --git a/app/assets/javascripts/vue_shared/components/toggle_button.vue b/app/assets/javascripts/vue_shared/components/toggle_button.vue
deleted file mode 100644
index 861661d3519..00000000000
--- a/app/assets/javascripts/vue_shared/components/toggle_button.vue
+++ /dev/null
@@ -1,88 +0,0 @@
-<script>
-import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { s__ } from '../../locale';
-
-const ICON_ON = 'status_success_borderless';
-const ICON_OFF = 'status_failed_borderless';
-const LABEL_ON = s__('ToggleButton|Toggle Status: ON');
-const LABEL_OFF = s__('ToggleButton|Toggle Status: OFF');
-
-export default {
- components: {
- GlIcon,
- GlLoadingIcon,
- },
-
- model: {
- prop: 'value',
- event: 'change',
- },
-
- props: {
- name: {
- type: String,
- required: false,
- default: null,
- },
- value: {
- type: Boolean,
- required: false,
- default: null,
- },
- disabledInput: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
-
- computed: {
- toggleIcon() {
- return this.value ? ICON_ON : ICON_OFF;
- },
- ariaLabel() {
- return this.value ? LABEL_ON : LABEL_OFF;
- },
- },
-
- methods: {
- toggleFeature() {
- if (!this.disabledInput) this.$emit('change', !this.value);
- },
- },
-};
-</script>
-
-<template>
- <label class="gl-mt-2">
- <input v-if="name" :name="name" :value="value" type="hidden" />
- <button
- type="button"
- role="switch"
- class="project-feature-toggle"
- :aria-label="ariaLabel"
- :aria-checked="value"
- :class="{
- 'is-checked': value,
- 'gl-blue-500': value,
- 'is-disabled': disabledInput,
- 'is-loading': isLoading,
- }"
- @click.prevent="toggleFeature"
- >
- <gl-loading-icon class="loading-icon" />
- <span class="toggle-icon">
- <gl-icon
- :size="18"
- :name="toggleIcon"
- :class="value ? 'gl-text-blue-500' : 'gl-text-gray-400'"
- />
- </span>
- </button>
- </label>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
index b48dfa8b452..8aa6e29adf1 100644
--- a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
+++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
@@ -1,7 +1,7 @@
<script>
import { isFunction } from 'lodash';
-import tooltip from '../directives/tooltip';
import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
+import tooltip from '../directives/tooltip';
export default {
directives: {
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 01ba2cf5c39..5a08e992084 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
@@ -1,8 +1,8 @@
<script>
import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
-import { isValidImage } from './utils';
import { VALID_DATA_TRANSFER_TYPE, VALID_IMAGE_FILE_MIMETYPE } from './constants';
+import { isValidImage } from './utils';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index 2ab4c55d9b0..37bde089de8 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -6,9 +6,9 @@ import {
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlIcon,
} from '@gitlab/ui';
-import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
-import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
+import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
import { glEmojiTag } from '../../../emoji';
+import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
const MAX_SKELETON_LINES = 4;
@@ -26,7 +26,7 @@ export default {
GlPopover,
GlSkeletonLoading,
UserAvatarImage,
- UserAvailabilityStatus,
+ UserNameWithStatus,
},
props: {
target: {
@@ -66,7 +66,7 @@ export default {
);
},
availabilityStatus() {
- return this.user?.status?.availability || null;
+ return this.user?.status?.availability || '';
},
},
};
@@ -93,11 +93,7 @@ export default {
<template v-else>
<div class="gl-mb-3">
<h5 class="gl-m-0">
- {{ user.name }}
- <user-availability-status
- v-if="availabilityStatus"
- :availability="availabilityStatus"
- />
+ <user-name-with-status :name="user.name" :availability="availabilityStatus" />
</h5>
<span class="gl-text-gray-500">@{{ user.username }}</span>
</div>
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 c957876f8ab..4bd3e352fd2 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -1,8 +1,8 @@
<script>
import $ from 'jquery';
import { __ } from '~/locale';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import ActionsButton from '~/vue_shared/components/actions_button.vue';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
const KEY_EDIT = 'edit';
const KEY_WEB_IDE = 'webide';
diff --git a/app/assets/javascripts/vue_shared/directives/validation.js b/app/assets/javascripts/vue_shared/directives/validation.js
index ece09df272c..176954891e9 100644
--- a/app/assets/javascripts/vue_shared/directives/validation.js
+++ b/app/assets/javascripts/vue_shared/directives/validation.js
@@ -86,7 +86,7 @@ const createValidator = (context, feedbackMap) => ({ el, reportInvalidInput = fa
* @param {Object<string, { message: string, isValid: ?function}>} customFeedbackMap
* @returns {{ inserted: function, update: function }} validateDirective
*/
-export default function (customFeedbackMap = {}) {
+export default function initValidation(customFeedbackMap = {}) {
const feedbackMap = merge(defaultFeedbackMap, customFeedbackMap);
const elDataMap = new WeakMap();
diff --git a/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js b/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
deleted file mode 100644
index be04ff158e7..00000000000
--- a/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * API callbacks for pagination and tabs
- * shared between Pipelines and Environments table.
- *
- * Components need to have `scope`, `page` and `requestData`
- */
-import { historyPushState, buildUrlWithCurrentLocation } from '../../lib/utils/common_utils';
-import { validateParams } from '~/pipelines/utils';
-
-export default {
- methods: {
- onChangeTab(scope) {
- if (this.scope === scope) {
- return;
- }
-
- let params = {
- scope,
- page: '1',
- };
-
- params = this.onChangeWithFilter(params);
-
- this.updateContent(params);
- },
-
- onChangePage(page) {
- /* URLS parameters are strings, we need to parse to match types */
- let params = {
- page: Number(page).toString(),
- };
-
- if (this.scope) {
- params.scope = this.scope;
- }
-
- params = this.onChangeWithFilter(params);
-
- this.updateContent(params);
- },
-
- onChangeWithFilter(params) {
- return { ...params, ...validateParams(this.requestData) };
- },
-
- updateInternalState(parameters) {
- // stop polling
- this.poll.stop();
-
- const queryString = Object.keys(parameters)
- .map((parameter) => {
- const value = parameters[parameter];
- // update internal state for UI
- this[parameter] = value;
- return `${parameter}=${encodeURIComponent(value)}`;
- })
- .join('&');
-
- // update polling parameters
- this.requestData = parameters;
-
- historyPushState(buildUrlWithCurrentLocation(`?${queryString}`));
-
- this.isLoading = true;
- },
- },
-};
diff --git a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
index 56da2637825..52ded0e0cc1 100644
--- a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
+++ b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
@@ -1,6 +1,6 @@
import { isEmpty } from 'lodash';
-import { sprintf, __ } from '~/locale';
import { formatDate } from '~/lib/utils/datetime_utility';
+import { sprintf, __ } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
const mixins = {
diff --git a/app/assets/javascripts/vue_shared/plugins/global_toast.js b/app/assets/javascripts/vue_shared/plugins/global_toast.js
index 7a2e5d80a5d..bfea2bedd40 100644
--- a/app/assets/javascripts/vue_shared/plugins/global_toast.js
+++ b/app/assets/javascripts/vue_shared/plugins/global_toast.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
Vue.use(GlToast);
const instance = new Vue();
diff --git a/app/assets/javascripts/vue_shared/security_reports/constants.js b/app/assets/javascripts/vue_shared/security_reports/constants.js
index dd591f7bba3..aac5a5c1def 100644
--- a/app/assets/javascripts/vue_shared/security_reports/constants.js
+++ b/app/assets/javascripts/vue_shared/security_reports/constants.js
@@ -17,7 +17,13 @@ export const REPORT_FILE_TYPES = {
* Security scan report types, as provided by the backend.
*/
export const REPORT_TYPE_SAST = 'sast';
+export const REPORT_TYPE_DAST = 'dast';
export const REPORT_TYPE_SECRET_DETECTION = 'secret_detection';
+export const REPORT_TYPE_DEPENDENCY_SCANNING = 'dependency_scanning';
+export const REPORT_TYPE_CONTAINER_SCANNING = 'container_scanning';
+export const REPORT_TYPE_COVERAGE_FUZZING = 'coverage_fuzzing';
+export const REPORT_TYPE_LICENSE_COMPLIANCE = 'license_compliance';
+export const REPORT_TYPE_API_FUZZING = 'api_fuzzing';
/**
* SecurityReportTypeEnum values for use with GraphQL.
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 a6c7b59aa71..b27dd33835f 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
@@ -1,31 +1,26 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import { GlLink, GlSprintf } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import ReportSection from '~/reports/components/report_section.vue';
-import { LOADING, ERROR, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '~/reports/constants';
-import { s__ } from '~/locale';
-import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
import createFlash from '~/flash';
-import Api from '~/api';
+import { s__ } from '~/locale';
+import ReportSection from '~/reports/components/report_section.vue';
+import { ERROR, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '~/reports/constants';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import HelpIcon from './components/help_icon.vue';
import SecurityReportDownloadDropdown from './components/security_report_download_dropdown.vue';
import SecuritySummary from './components/security_summary.vue';
-import store from './store';
-import { MODULE_SAST, MODULE_SECRET_DETECTION } from './store/constants';
import {
REPORT_TYPE_SAST,
REPORT_TYPE_SECRET_DETECTION,
reportTypeToSecurityReportTypeEnum,
} from './constants';
import securityReportDownloadPathsQuery from './queries/security_report_download_paths.query.graphql';
+import store from './store';
+import { MODULE_SAST, MODULE_SECRET_DETECTION } from './store/constants';
import { extractSecurityReportArtifacts } from './utils';
export default {
store,
components: {
- GlLink,
- GlSprintf,
ReportSection,
HelpIcon,
SecurityReportDownloadDropdown,
@@ -101,9 +96,6 @@ export default {
),
};
},
- skip() {
- return !this.canShowDownloads;
- },
update(data) {
return extractSecurityReportArtifacts(this.$options.reportTypes, data);
},
@@ -124,9 +116,6 @@ export default {
},
computed: {
...mapGetters(['groupedSummaryText', 'summaryStatus']),
- canShowDownloads() {
- return this.glFeatures.coreSecurityMrWidgetDownloads;
- },
hasSecurityReports() {
return this.availableSecurityReports.length > 0;
},
@@ -139,23 +128,6 @@ export default {
isLoadingReportArtifacts() {
return this.$apollo.queries.reportArtifacts.loading;
},
- shouldShowDownloadGuidance() {
- return !this.canShowDownloads && this.summaryStatus !== LOADING;
- },
- scansHaveRunMessage() {
- return this.canShowDownloads
- ? this.$options.i18n.scansHaveRun
- : this.$options.i18n.scansHaveRunWithDownloadGuidance;
- },
- },
- created() {
- if (!this.canShowDownloads) {
- this.checkAvailableSecurityReports(this.$options.reportTypes)
- .then((availableSecurityReports) => {
- this.onCheckingAvailableSecurityReports(Array.from(availableSecurityReports));
- })
- .catch(this.showError);
- }
},
methods: {
...mapActions(MODULE_SAST, {
@@ -166,36 +138,6 @@ export default {
setSecretDetectionDiffEndpoint: 'setDiffEndpoint',
fetchSecretDetectionDiff: 'fetchDiff',
}),
- async checkAvailableSecurityReports(reportTypes) {
- const reportTypesSet = new Set(reportTypes);
- const availableReportTypes = new Set();
-
- let page = 1;
- while (page) {
- // eslint-disable-next-line no-await-in-loop
- const { data: jobs, headers } = await Api.pipelineJobs(this.projectId, this.pipelineId, {
- per_page: 100,
- page,
- });
-
- jobs.forEach(({ artifacts = [] }) => {
- artifacts.forEach(({ file_type }) => {
- if (reportTypesSet.has(file_type)) {
- availableReportTypes.add(file_type);
- }
- });
- });
-
- // If we've found artifacts for all the report types, stop looking!
- if (availableReportTypes.size === reportTypesSet.size) {
- return availableReportTypes;
- }
-
- page = parseIntPagination(normalizeHeaders(headers)).nextPage;
- }
-
- return availableReportTypes;
- },
fetchCounts() {
if (!this.glFeatures.coreSecurityMrWidgetCounts) {
return;
@@ -213,11 +155,6 @@ export default {
this.canShowCounts = true;
}
},
- activatePipelinesTab() {
- if (window.mrTabs) {
- window.mrTabs.tabShown('pipelines');
- }
- },
onCheckingAvailableSecurityReports(availableSecurityReports) {
this.availableSecurityReports = availableSecurityReports;
this.fetchCounts();
@@ -236,12 +173,6 @@ export default {
'SecurityReports|Failed to get security report information. Please reload the page or try again later.',
),
scansHaveRun: s__('SecurityReports|Security scans have run'),
- scansHaveRunWithDownloadGuidance: s__(
- 'SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports',
- ),
- downloadFromPipelineTab: s__(
- 'SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports',
- ),
},
summarySlots: [SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR],
};
@@ -265,22 +196,7 @@ export default {
</span>
</template>
- <template v-if="shouldShowDownloadGuidance" #sub-heading>
- <span class="gl-font-sm">
- <gl-sprintf :message="$options.i18n.downloadFromPipelineTab">
- <template #link="{ content }">
- <gl-link
- class="gl-font-sm"
- data-testid="show-pipelines"
- @click="activatePipelinesTab"
- >{{ content }}</gl-link
- >
- </template>
- </gl-sprintf>
- </span>
- </template>
-
- <template v-if="canShowDownloads" #action-buttons>
+ <template #action-buttons>
<security-report-download-dropdown
:artifacts="reportArtifacts"
:loading="isLoadingReportArtifacts"
@@ -298,13 +214,7 @@ export default {
data-testid="security-mr-widget"
>
<template #error>
- <gl-sprintf :message="scansHaveRunMessage">
- <template #link="{ content }">
- <gl-link data-testid="show-pipelines" @click="activatePipelinesTab">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
+ {{ $options.i18n.scansHaveRun }}
<help-icon
:help-path="securityReportsDocsPath"
@@ -312,7 +222,7 @@ export default {
/>
</template>
- <template v-if="canShowDownloads" #action-buttons>
+ <template #action-buttons>
<security-report-download-dropdown
:artifacts="reportArtifacts"
:loading="isLoadingReportArtifacts"
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/getters.js b/app/assets/javascripts/vue_shared/security_reports/store/getters.js
index 443255b0e6a..08f6bcca15b 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/getters.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/getters.js
@@ -1,7 +1,7 @@
import { s__, sprintf } from '~/locale';
-import { countVulnerabilities, groupedTextBuilder } from './utils';
import { LOADING, ERROR, SUCCESS } from '~/reports/constants';
import { TRANSLATION_IS_LOADING } from './messages';
+import { countVulnerabilities, groupedTextBuilder } from './utils';
export const summaryCounts = (state) =>
countVulnerabilities(
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/index.js b/app/assets/javascripts/vue_shared/security_reports/store/index.js
index 10705e04a21..164faa86744 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/index.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/index.js
@@ -1,9 +1,9 @@
import Vuex from 'vuex';
-import * as getters from './getters';
-import state from './state';
import { MODULE_SAST, MODULE_SECRET_DETECTION } from './constants';
+import * as getters from './getters';
import sast from './modules/sast';
import secretDetection from './modules/secret_detection';
+import state from './state';
export default () =>
new Vuex.Store({
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
index 0f26e3c30ef..4f92e181f9f 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/actions.js
@@ -1,5 +1,5 @@
-import * as types from './mutation_types';
import { fetchDiffData } from '../../utils';
+import * as types from './mutation_types';
export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
index 68c81bb4509..1d5af1d4fe5 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/index.js
@@ -1,6 +1,6 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
index 5f6153ca3b1..11aa71d2b6b 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/sast/mutations.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import * as types from './mutation_types';
import { parseDiff } from '../../utils';
+import * as types from './mutation_types';
export default {
[types.SET_DIFF_ENDPOINT](state, path) {
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
index 68c81bb4509..1d5af1d4fe5 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/modules/secret_detection/index.js
@@ -1,6 +1,6 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
export default {
namespaced: true,
diff --git a/app/assets/javascripts/vue_shared/security_reports/store/utils.js b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
index fd6613ae11c..458bacce915 100644
--- a/app/assets/javascripts/vue_shared/security_reports/store/utils.js
+++ b/app/assets/javascripts/vue_shared/security_reports/store/utils.js
@@ -1,5 +1,5 @@
-import pollUntilComplete from '~/lib/utils/poll_until_complete';
import axios from '~/lib/utils/axios_utils';
+import pollUntilComplete from '~/lib/utils/poll_until_complete';
import { __, n__, sprintf } from '~/locale';
import { CRITICAL, HIGH } from '~/vulnerabilities/constants';
import {
diff --git a/app/assets/javascripts/vuex_shared/modules/modal/index.js b/app/assets/javascripts/vuex_shared/modules/modal/index.js
index c349d875c24..21ebfb22e2e 100644
--- a/app/assets/javascripts/vuex_shared/modules/modal/index.js
+++ b/app/assets/javascripts/vuex_shared/modules/modal/index.js
@@ -1,6 +1,6 @@
-import state from './state';
-import mutations from './mutations';
import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
export default () => ({
namespaced: true,
diff --git a/app/assets/javascripts/webpack_non_compiled_placeholder.js b/app/assets/javascripts/webpack_non_compiled_placeholder.js
new file mode 100644
index 00000000000..8cd1d2eb2ca
--- /dev/null
+++ b/app/assets/javascripts/webpack_non_compiled_placeholder.js
@@ -0,0 +1,24 @@
+const div = document.createElement('div');
+
+Object.assign(div.style, {
+ width: '100vw',
+ height: '100vh',
+ position: 'fixed',
+ top: 0,
+ left: 0,
+ 'z-index': 100000,
+ background: 'rgba(0,0,0,0.9)',
+ 'font-size': '25px',
+ 'font-family': 'monospace',
+ color: 'white',
+ padding: '2.5em',
+ 'text-align': 'center',
+});
+
+div.innerHTML = `
+<h1 style="color:white">🧙 Webpack is doing its magic 🧙</h1>
+<p>If you use Hot Module reloading, the page will reload in a few seconds.</p>
+<p>If you do not use Hot Module reloading, please <a href="">reload the page manually in a few seconds</a></p>
+`;
+
+document.body.append(div);
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
index 0a81f172fe9..f4ac4f81eac 100644
--- a/app/assets/javascripts/whats_new/components/app.vue
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState, mapActions } from 'vuex';
import {
GlDrawer,
GlInfiniteScroll,
@@ -9,10 +8,11 @@ import {
GlBadge,
GlLoadingIcon,
} from '@gitlab/ui';
-import SkeletonLoader from './skeleton_loader.vue';
-import Feature from './feature.vue';
+import { mapState, mapActions } from 'vuex';
import Tracking from '~/tracking';
import { getDrawerBodyHeight } from '../utils/get_drawer_body_height';
+import Feature from './feature.vue';
+import SkeletonLoader from './skeleton_loader.vue';
const trackingMixin = Tracking.mixin();
diff --git a/app/assets/javascripts/whats_new/store/actions.js b/app/assets/javascripts/whats_new/store/actions.js
index 0e5eeda742a..4b3cfa55977 100644
--- a/app/assets/javascripts/whats_new/store/actions.js
+++ b/app/assets/javascripts/whats_new/store/actions.js
@@ -1,6 +1,6 @@
-import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import * as types from './mutation_types';
export default {
closeDrawer({ commit }) {
diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js
index 06ba2496a99..134c2858849 100644
--- a/app/assets/javascripts/zen_mode.js
+++ b/app/assets/javascripts/zen_mode.js
@@ -5,8 +5,8 @@
/*= provides zen_mode:enter */
/*= provides zen_mode:leave */
-import $ from 'jquery';
import Dropzone from 'dropzone';
+import $ from 'jquery';
import Mousetrap from 'mousetrap';
import 'mousetrap/plugins/pause/mousetrap-pause';
import { scrollToElement } from '~/lib/utils/common_utils';
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index 42d15635566..20ff78d32d3 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -1,4 +1,3 @@
-@import './pages/admin';
@import './pages/branches';
@import './pages/ci_projects';
@import './pages/clusters';
diff --git a/app/assets/stylesheets/components/batch_comments/review_bar.scss b/app/assets/stylesheets/components/batch_comments/review_bar.scss
index 76bf7ac81e8..d769ea73101 100644
--- a/app/assets/stylesheets/components/batch_comments/review_bar.scss
+++ b/app/assets/stylesheets/components/batch_comments/review_bar.scss
@@ -4,7 +4,7 @@
left: 0;
width: 100%;
background: $white;
- z-index: 300;
+ z-index: $zindex-dropdown-menu;
padding: 7px 0 6px; // to keep aligned with "collapse sidebar" button on the left sidebar
border-top: 1px solid $border-color;
padding-left: $contextual-sidebar-width;
diff --git a/app/assets/stylesheets/components/design_management/design_list_item.scss b/app/assets/stylesheets/components/design_management/design_list_item.scss
index b7f6b2026fe..09af4da37e9 100644
--- a/app/assets/stylesheets/components/design_management/design_list_item.scss
+++ b/app/assets/stylesheets/components/design_management/design_list_item.scss
@@ -8,11 +8,6 @@
top: 10px;
}
- .design-event {
- top: $gl-padding;
- right: $gl-padding;
- }
-
.card-body {
height: 230px;
}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index e40b95cdce6..7931f4deea0 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -15,7 +15,6 @@
@import 'framework/badges';
@import 'framework/calendar';
@import 'framework/callout';
-@import 'framework/carousel';
@import 'framework/common';
@import 'framework/dropdowns';
@import 'framework/files';
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index d9ad4992458..a7623b65539 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -14,7 +14,7 @@
top: 0;
margin-top: 3px;
padding: $gl-padding;
- z-index: 300;
+ z-index: $zindex-dropdown-menu;
width: $award-emoji-width;
font-size: 14px;
background-color: $white;
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 182c58c3931..b51fec925cb 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -95,8 +95,6 @@
&:active,
&.active {
- box-shadow: $gl-btn-active-background;
-
background-color: $dark;
border-color: $border-dark;
color: $color;
@@ -348,14 +346,6 @@
}
}
-.btn-build {
- margin-left: 10px;
-
- svg {
- fill: $gl-text-color-secondary;
- }
-}
-
.clone-dropdown-btn a {
color: $gray-700;
@@ -437,19 +427,6 @@
}
}
-.btn-missing {
- color: $gl-text-color-secondary;
- border: 1px dashed $border-gray-normal-dashed;
- border-radius: $border-radius-default;
-
- &:hover,
- &:active,
- &:focus {
- color: $gl-text-color-secondary;
- background-color: $white-normal;
- }
-}
-
// The .btn-svg class is available for legacy icon buttons to
// preserve a 34px height and have 16x16 icons at the same time.
// Once a button is migrated (to the current 32px height)
diff --git a/app/assets/stylesheets/framework/carousel.scss b/app/assets/stylesheets/framework/carousel.scss
deleted file mode 100644
index d51a9f9c173..00000000000
--- a/app/assets/stylesheets/framework/carousel.scss
+++ /dev/null
@@ -1,202 +0,0 @@
-// Notes on the classes:
-//
-// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically)
-// even when their scroll action started on a carousel, but for compatibility (with Firefox)
-// we're preventing all actions instead
-// 2. The .carousel-item-left and .carousel-item-right is used to indicate where
-// the active slide is heading.
-// 3. .active.carousel-item is the current slide.
-// 4. .active.carousel-item-left and .active.carousel-item-right is the current
-// slide in its in-transition state. Only one of these occurs at a time.
-// 5. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right
-// is the upcoming slide in transition.
-
-.carousel {
- position: relative;
-
- &.pointer-event {
- touch-action: pan-y;
- }
-}
-
-
-.carousel-inner {
- position: relative;
- width: 100%;
- overflow: hidden;
- @include clearfix();
-}
-
-.carousel-item {
- position: relative;
- display: none;
- float: left;
- width: 100%;
- margin-right: -100%;
- backface-visibility: hidden;
- @include transition($carousel-transition);
-}
-
-.carousel-item.active,
-.carousel-item-next,
-.carousel-item-prev {
- display: block;
-}
-
-.carousel-item-next:not(.carousel-item-left),
-.active.carousel-item-right {
- transform: translateX(100%);
-}
-
-.carousel-item-prev:not(.carousel-item-right),
-.active.carousel-item-left {
- transform: translateX(-100%);
-}
-
-
-//
-// Alternate transitions
-//
-
-.carousel-fade {
- .carousel-item {
- opacity: 0;
- transition-property: opacity;
- transform: none;
- }
-
- .carousel-item.active,
- .carousel-item-next.carousel-item-left,
- .carousel-item-prev.carousel-item-right {
- z-index: 1;
- opacity: 1;
- }
-
- .active.carousel-item-left,
- .active.carousel-item-right {
- z-index: 0;
- opacity: 0;
- @include transition(0s $carousel-transition-duration opacity);
- }
-}
-
-
-//
-// Left/right controls for nav
-//
-
-.carousel-control-prev,
-.carousel-control-next {
- position: absolute;
- top: 0;
- bottom: 0;
- z-index: 1;
- // Use flex for alignment (1-3)
- display: flex; // 1. allow flex styles
- align-items: center; // 2. vertically center contents
- justify-content: center; // 3. horizontally center contents
- width: $carousel-control-width;
- color: $carousel-control-color;
- text-align: center;
- opacity: $carousel-control-opacity;
- @include transition($carousel-control-transition);
-
- // Hover/focus state
- @include hover-focus {
- color: $carousel-control-color;
- text-decoration: none;
- outline: 0;
- opacity: $carousel-control-hover-opacity;
- }
-}
-
-.carousel-control-prev {
- left: 0;
- @if $enable-gradients {
- background: linear-gradient(90deg, rgba($black, 0.25), rgba($black, 0.001));
- }
-}
-
-.carousel-control-next {
- right: 0;
- @if $enable-gradients {
- background: linear-gradient(270deg, rgba($black, 0.25), rgba($black, 0.001));
- }
-}
-
-// Icons for within
-.carousel-control-prev-icon,
-.carousel-control-next-icon {
- display: inline-block;
- width: $carousel-control-icon-width;
- height: $carousel-control-icon-width;
- background: no-repeat 50% / 100% 100%;
-}
-
-.carousel-control-prev-icon {
- background-image: $carousel-control-prev-icon-bg;
-}
-
-.carousel-control-next-icon {
- background-image: $carousel-control-next-icon-bg;
-}
-
-
-// Optional indicator pips
-//
-// Add an ordered list with the following class and add a list item for each
-// slide your carousel holds.
-
-.carousel-indicators {
- position: absolute;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 15;
- display: flex;
- justify-content: center;
- padding-left: 0; // override <ol> default
- // Use the .carousel-control's width as margin so we don't overlay those
- margin-right: $carousel-control-width;
- margin-left: $carousel-control-width;
- list-style: none;
-
- li {
- box-sizing: content-box;
- flex: 0 1 auto;
- width: $carousel-indicator-width;
- height: $carousel-indicator-height;
- margin-right: $carousel-indicator-spacer;
- margin-left: $carousel-indicator-spacer;
- text-indent: -999px;
- cursor: pointer;
- background-color: $carousel-indicator-active-bg;
- background-clip: padding-box;
- // Use transparent borders to increase the hit area by 10px on top and bottom.
- border-top: $carousel-indicator-hit-area-height solid transparent;
- border-bottom: $carousel-indicator-hit-area-height solid transparent;
- opacity: 0.5;
- @include transition($carousel-indicator-transition);
- }
-
- .active {
- opacity: 1;
- }
-}
-
-
-// Optional captions
-//
-//
-
-.carousel-caption {
- position: absolute;
- right: (100% - $carousel-caption-width) / 2;
- bottom: 20px;
- left: (100% - $carousel-caption-width) / 2;
- z-index: 10;
- padding-top: 20px;
- padding-bottom: 20px;
- color: $carousel-caption-color;
- text-align: center;
-}
diff --git a/app/assets/stylesheets/framework/ci_variable_list.scss b/app/assets/stylesheets/framework/ci_variable_list.scss
index 2204b037f69..95025459cc9 100644
--- a/app/assets/stylesheets/framework/ci_variable_list.scss
+++ b/app/assets/stylesheets/framework/ci_variable_list.scss
@@ -98,13 +98,3 @@
color: $gl-text-color-disabled;
}
}
-
-.group-variable-list {
- color: $gray-500;
-
- .table-section:not(:first-child) {
- @include media-breakpoint-down(sm) {
- border-top: hidden;
- }
- }
-}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 3b59c028437..5d182373fb1 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -110,7 +110,7 @@ pre {
}
hr {
- margin: 24px 0;
+ margin: 1.5rem 0;
border-top: 1px solid $gray-darker;
}
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 745d469e3e8..c5467c304ec 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -471,7 +471,7 @@
background-color: $black-transparent;
height: 100%;
width: 100%;
- z-index: 300;
+ z-index: $zindex-dropdown-menu;
}
}
}
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index 499b9c00116..e30caeb1dfb 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -1136,10 +1136,6 @@ table.code {
display: block;
}
}
-
- .note-edit-form {
- margin-left: $note-icon-gutter-width;
- }
}
.discussion-body .image .frame {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 41fc4d3dd4e..f56d8f2c2a9 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -216,7 +216,7 @@
position: absolute;
width: auto;
top: 100%;
- z-index: 300;
+ z-index: $zindex-dropdown-menu;
min-width: 240px;
max-width: 500px;
margin-top: $dropdown-vertical-offset;
@@ -326,7 +326,7 @@
color: $gl-text-color-secondary;
}
- .badge.badge-pill + span:not(.badge.badge-pill) {
+ .badge.badge-pill + span:not(.badge):not(.badge-pill) {
// Expects up to 3 digits on the badge
margin-right: 40px;
}
@@ -497,7 +497,7 @@
li {
a,
button,
- .dropdown-item {
+ .dropdown-item:not(.open-with-link) {
padding: 8px 40px;
position: relative;
@@ -525,7 +525,7 @@
&.is-active {
/* stylelint-disable-next-line function-url-quotes */
- background: url(asset_path('checkmark.png')) no-repeat 14px 8px;
+ background: url(asset_path('checkmark.png')) no-repeat 14px center;
}
}
}
@@ -896,7 +896,7 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
position: absolute;
top: 13px;
right: 25px;
- color: $gray-50;
+ color: $gray-300;
}
}
@@ -1093,17 +1093,3 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
width: $gl-dropdown-width-wide;
}
}
-
-.gl-dropdown-item-deprecated-adapter {
- .dropdown-item {
- align-items: flex-start;
-
- .gl-new-dropdown-item-text-primary {
- @include gl-font-weight-bold;
- }
-
- .gl-new-dropdown-item-text-secondary {
- color: inherit;
- }
- }
-}
diff --git a/app/assets/stylesheets/framework/feature_highlight.scss b/app/assets/stylesheets/framework/feature_highlight.scss
index 8d411747b28..36f1b1f2903 100644
--- a/app/assets/stylesheets/framework/feature_highlight.scss
+++ b/app/assets/stylesheets/framework/feature_highlight.scss
@@ -1,14 +1,7 @@
.feature-highlight {
- position: relative;
- margin-left: $gl-padding;
- width: 20px;
- height: 20px;
- cursor: pointer;
-
&::before {
content: '';
display: block;
- position: absolute;
top: 6px;
left: 6px;
width: 8px;
@@ -29,56 +22,22 @@
}
}
-.feature-highlight-popover-content {
- display: none;
-
- hr {
- margin: $gl-padding 0;
- }
-
- .btn-link {
- svg {
- @include btn-svg;
-
- path {
- fill: currentColor;
- }
- }
- }
-
- .feature-highlight-illustration {
- width: 100%;
- height: 100px;
- padding-top: 12px;
- padding-bottom: 12px;
- background-color: $indigo-50;
- border-top-left-radius: 2px;
- border-top-right-radius: 2px;
- border-bottom: 1px solid darken($gray-normal, 8%);
- }
-}
-
-.popover .feature-highlight-popover-content {
- display: block;
+.feature-highlight-illustration {
+ background-color: $indigo-50;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ border-bottom: 1px solid darken($gray-normal, 8%);
}
.feature-highlight-popover {
width: 240px;
- &.right > .arrow {
- border-right-color: $border-color;
- }
-
.popover-body {
padding: 0;
}
}
-.feature-highlight-popover-sub-content {
- padding: $gl-padding $gl-padding-12;
-}
-
@include keyframes(pulse-highlight) {
0% {
box-shadow: 0 0 0 0 rgba($blue-200, 0.4);
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index fe8c27ae9b6..bda123fa7ea 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -2,6 +2,14 @@
* File content holder
*
*/
+.container-fluid.container-limited.limit-container-width {
+ .file-holder.readme-holder.limited-width-container .file-content {
+ max-width: $limited-layout-width;
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
.file-holder {
border: 1px solid $border-color;
border-top: 0;
@@ -17,12 +25,6 @@
&.readme-holder {
margin: $gl-padding 0;
-
- &.limited-width-container .file-content {
- max-width: $limited-layout-width;
- margin-left: auto;
- margin-right: auto;
- }
}
.file-title {
@@ -351,23 +353,17 @@ span.idiff {
color: $gl-text-color;
}
- .file-actions .btn:not(.btn-icon) {
- padding: 0 10px;
- font-size: 13px;
- line-height: 28px;
- display: inline-block;
- float: none;
- }
-
.file-actions .ide-edit-button {
z-index: 2;
}
- @include media-breakpoint-down(sm) {
- display: block;
-
+ @include media-breakpoint-down(md) {
.file-actions {
- margin-top: 5px;
+ margin-top: $gl-padding-8;
+
+ .btn {
+ margin-bottom: $gl-padding-8;
+ }
}
}
}
@@ -442,12 +438,6 @@ span.idiff {
.user-avatar-link.new-comment {
position: absolute;
margin: 40px $gl-padding 0 116px;
-
- ~ .note-edit-form form.edit-note {
- @include media-breakpoint-up(sm) {
- margin-left: $note-icon-gutter-width;
- }
- }
}
}
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index 5f56fa3be86..07d59847829 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -475,6 +475,15 @@
}
}
+ .sort-dropdown-container {
+ // This property is set to have borders
+ // around sort dropdown match with filter
+ // input field.
+ .gl-button {
+ box-shadow: inset 0 0 0 1px $gray-400;
+ }
+ }
+
@include media-breakpoint-up(md) {
.sort-dropdown-container {
margin-left: 10px;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 730e10114c3..ffcc20b624b 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -516,28 +516,8 @@
left: auto;
max-height: $dropdown-max-height-lg;
- li.current-user {
- padding: $dropdown-item-padding-y $dropdown-item-padding-x;
-
- .user-name {
- display: block;
- }
-
- .user-status {
- margin-right: 0;
- max-width: 240px;
- font-size: $gl-font-size-small;
-
- gl-emoji {
- font-size: $gl-font-size-small;
- }
-
- .user-status-emoji {
- gl-emoji {
- font-size: $gl-font-size;
- }
- }
- }
+ .user-status {
+ max-width: 240px;
}
svg {
diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss
index 5623d38d66e..222e10f51ad 100644
--- a/app/assets/stylesheets/framework/icons.scss
+++ b/app/assets/stylesheets/framework/icons.scss
@@ -3,10 +3,6 @@
svg {
fill: $green-500;
}
-
- &.add-border {
- @include borderless-status-icon($green-500);
- }
}
.ci-status-icon-error,
@@ -14,10 +10,6 @@
svg {
fill: $red-500;
}
-
- &.add-border {
- @include borderless-status-icon($red-500);
- }
}
.ci-status-icon-pending,
@@ -27,59 +19,29 @@
svg {
fill: $orange-500;
}
-
- &.add-border {
- @include borderless-status-icon($orange-500);
- }
-}
-
-.ci-status-icon-preparing {
- svg {
- fill: $gray-300;
- }
-
- &.add-border {
- @include borderless-status-icon($gray-300);
- }
}
.ci-status-icon-running {
svg {
fill: $blue-400;
}
-
- &.add-border {
- @include borderless-status-icon($blue-400);
- }
}
.ci-status-icon-canceled,
-.ci-status-icon-disabled {
+.ci-status-icon-disabled,
+.ci-status-icon-scheduled,
+.ci-status-icon-manual {
svg {
fill: $gl-text-color;
}
-
- &.add-border {
- @include borderless-status-icon($gl-text-color);
- }
}
+.ci-status-icon-preparing,
.ci-status-icon-created,
.ci-status-icon-skipped,
.ci-status-icon-notfound {
svg {
- fill: $gray-darkest;
- }
-
- &.add-border {
- @include borderless-status-icon($gray-darkest);
- }
-}
-
-.ci-status-icon-scheduled,
-.ci-status-icon-manual {
- svg {
- fill: $gl-text-color;
+ fill: var(--gray-400, $gray-400);
}
}
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index e3d02d01496..e29e204b14f 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -354,13 +354,6 @@
}
}
-@mixin borderless-status-icon($color) {
- svg {
- border: 1px solid $color;
- border-radius: 50%;
- }
-}
-
@mixin emoji-menu-toggle-button {
line-height: 1;
padding: 0;
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index bef33bd2ef0..241aaad015e 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -75,7 +75,7 @@
.right-sidebar-expanded {
padding-right: 0;
- z-index: 300;
+ z-index: $zindex-dropdown-menu;
@include media-breakpoint-only(sm) {
&:not(.wiki-sidebar):not(.build-sidebar):not(.issuable-bulk-update-sidebar) .content-wrapper {
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 89713fdbbea..92405c00c5e 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -69,9 +69,6 @@ table {
}
}
- td {
- border-color: $white-normal;
- }
}
.thead-white {
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 1a568bb41a5..496e2aba421 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -458,7 +458,7 @@
h6 {
a.anchor {
float: left;
- margin-left: -16px;
+ margin-left: -20px;
text-decoration: none;
outline: none;
@@ -471,6 +471,11 @@
&:hover > a.anchor::after {
visibility: visible;
}
+
+ > a.anchor:focus::after {
+ visibility: visible;
+ outline: auto;
+ }
}
.big {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 674ba1a307b..4bf9236407f 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -433,6 +433,7 @@ $browser-scrollbar-size: 10px;
*/
$header-height: 40px;
$header-zindex: 1000;
+$zindex-dropdown-menu: 300;
$suggestion-header-height: 46px;
$ide-statusbar-height: 25px;
$fixed-layout-width: 1280px;
@@ -626,7 +627,6 @@ $search-input-xl-width: 320px;
$note-disabled-comment-color: #b2b2b2;
$note-targe3-outside: #fffff0;
$note-targe3-inside: #ffffd3;
-$note-icon-gutter-width: 55px;
/*
* Identicon
@@ -871,6 +871,27 @@ $add-to-slack-well-max-width: 750px;
$add-to-slack-logo-size: 100px;
/*
+Security & Compliance Carousel
+*/
+$security-and-compliance-carousel-image-carousel-width: 1000px;
+$security-and-compliance-carousel-image-discover-button-width: 45%;
+$security-and-compliance-carousel-image-discover-buttons-max-width: 280px;
+$security-and-compliance-carousel-image-discover-footer-max-width: 500px;
+$security-and-compliance-carousel-image-discover-feedback-width: 30%;
+$security-and-compliance-carousel-image-discover-text-carousel-max-width: 650px;
+$security-and-compliance-carousel-image-discover-text-carousel-caption-height: 100%;
+$security-and-compliance-carousel-image-discover-text-carousel-caption-max-width: 500px;
+$security-and-compliance-carousel-control-icon-width: 10px;
+$security-and-compliance-carousel-control-position: -5%;
+$security-and-compliance-carousel-inner-width: 90%;
+$security-and-compliance-carousel-indicators-bottom: -20px;
+$security-and-compliance-carousel-indicators-bottom-lg: -15px;
+$security-and-compliance-carousel-indicators-dimension: 6px;
+$security-and-compliance-carousel-indicators-border-radius: 100%;
+$security-and-compliance-carousel-prev-icon-background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23666666' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
+$security-and-compliance-carousel-next-icon-background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23666666' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E");
+
+/*
Popup
*/
$popup-triangle-size: 15px;
diff --git a/app/assets/stylesheets/mailer.scss b/app/assets/stylesheets/mailer.scss
index 27c6ef20269..4f76deeb991 100644
--- a/app/assets/stylesheets/mailer.scss
+++ b/app/assets/stylesheets/mailer.scss
@@ -14,13 +14,15 @@ $mailer-line-cell-bg-color: #6b4fbb;
$mailer-wrapper-cell-bg-color: #fff;
$mailer-wrapper-cell-border-color: #ededed;
$mailer-header-footer-text-color: #5c5c5c;
+$full-width: 640px;
+$half-width: 320px;
body {
margin: 0 !important;
background-color: $mailer-bg-color;
padding: 0;
text-align: center;
- min-width: 640px;
+ min-width: $full-width;
width: 100%;
height: 100%;
font-family: $mailer-font;
@@ -31,7 +33,7 @@ table#body {
margin: 0;
padding: 0;
text-align: center;
- min-width: 640px;
+ min-width: $full-width;
width: 100%;
}
@@ -44,6 +46,11 @@ a {
}
}
+.mail-avatar {
+ border-radius: 50%;
+ display: block;
+}
+
.highlight {
font-weight: 500;
}
@@ -77,10 +84,18 @@ a {
margin-left: 4px;
}
+.half-width {
+ min-width: $half-width;
+}
+
tr td {
font-family: $mailer-font;
}
+tr.border-top td {
+ border-top: 2px solid $gray-100;
+}
+
tr.line td {
font-family: $mailer-font;
background-color: $mailer-line-cell-bg-color;
@@ -100,7 +115,7 @@ td.footer-message {
}
table.wrapper {
- width: 640px;
+ width: $full-width;
margin: 0 auto;
border-collapse: separate;
border-spacing: 0;
@@ -149,7 +164,7 @@ tr.footer td {
}
.gitlab-info-text {
- max-width: 640px;
+ max-width: $full-width;
margin: 0 auto;
text-align: center;
color: $gray-400;
diff --git a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
index 093cba3560f..7336d555f79 100644
--- a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
@@ -5,7 +5,7 @@
$bs-input-focus-border: #80bdff;
$bs-input-focus-box-shadow: rgba(0, 123, 255, 0.25);
- a:not(.btn):not(.gl-tab-nav-item),
+ a:not(.btn),
.gl-button.btn-link,
.gl-button.btn-link:hover,
.gl-button.btn-link:focus,
@@ -34,6 +34,7 @@
.ide-pipeline .top-bar .controllers .controllers-buttons,
.controllers-buttons svg,
.nav-links li a.active,
+ .gl-tabs-nav li a.gl-tab-nav-item-active,
.md-area.is-focused {
color: var(--ide-text-color, $gl-text-color);
}
@@ -44,13 +45,15 @@
}
.nav-links:not(.quick-links) li:not(.md-header-toolbar) a,
+ .gl-tabs-nav li a,
.dropdown-menu-inner-content,
.file-row .file-row-icon svg,
.file-row:hover .file-row-icon svg {
color: var(--ide-text-color-secondary, $gl-text-color-secondary);
}
- .nav-links:not(.quick-links) li:not(.md-header-toolbar) {
+ .nav-links:not(.quick-links) li:not(.md-header-toolbar),
+ .gl-tabs-nav li {
&:hover a,
&.active a,
a:hover,
@@ -61,6 +64,10 @@
border-color: var(--ide-input-border, $gray-darkest);
}
}
+
+ a.gl-tab-nav-item-active {
+ box-shadow: inset 0 -2px 0 0 var(--ide-input-border, $gray-darkest);
+ }
}
.drag-handle:hover {
@@ -142,6 +149,7 @@
.md table:not(.code) tbody td,
.md table:not(.code) tr th,
.nav-links:not(.quick-links),
+ .gl-tabs-nav,
.common-note-form .md-area.is-focused .nav-links {
border-color: var(--ide-border-color-alt, $white-dark);
}
@@ -175,6 +183,10 @@
border-color: var(--ide-highlight-accent, $gl-text-color);
}
+ .gl-tabs-nav li a.gl-tab-nav-item-active {
+ box-shadow: inset 0 -2px 0 0 var(--ide-highlight-accent, $gl-text-color);
+ }
+
// for other themes, suppress different avatar default colors for simplicity
.avatar-container {
&,
@@ -241,7 +253,6 @@
.btn-default:not(.gl-button),
.dropdown,
.dropdown-menu-toggle {
- background-color: var(--ide-input-background, $white) !important;
color: var(--ide-input-color, $gl-text-color) !important;
border-color: var(--ide-btn-default-border, $border-color);
}
@@ -304,6 +315,11 @@
border-color: var(--ide-dropdown-hover-background, $border-color);
}
+ .gl-tabs-nav {
+ background-color: var(--ide-dropdown-hover-background, $white);
+ box-shadow: inset 0 -2px 0 0 var(--ide-dropdown-hover-background, $border-color);
+ }
+
.divider {
background-color: var(--ide-dropdown-hover-background, $gray-100);
border-color: var(--ide-dropdown-hover-background, $gray-100);
diff --git a/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss b/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
index 72e2a45565e..0d6f360112b 100644
--- a/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
+++ b/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
@@ -98,7 +98,6 @@
@include mini-pipeline-graph-color(var(--white, $white), $orange-50, $orange-100, $orange-500, $orange-600, $orange-700);
}
- &.ci-status-icon-preparing,
&.ci-status-icon-running {
@include mini-pipeline-graph-color(var(--white, $white), $blue-100, $blue-200, $blue-500, $blue-600, $blue-700);
}
@@ -106,14 +105,15 @@
&.ci-status-icon-canceled,
&.ci-status-icon-scheduled,
&.ci-status-icon-disabled,
- &.ci-status-icon-not-found,
&.ci-status-icon-manual {
@include mini-pipeline-graph-color(var(--white, $white), $gray-500, $gray-700, $gray-900, $gray-950, $black);
}
+ &.ci-status-icon-preparing,
&.ci-status-icon-created,
+ &.ci-status-icon-not-found,
&.ci-status-icon-skipped {
- @include mini-pipeline-graph-color(var(--white, $white), $gray-100, $gray-200, $gray-300, $gray-400, $gray-500);
+ @include mini-pipeline-graph-color(var(--white, $white), var(--gray-100, $gray-100), var(--gray-200, $gray-200), var(--gray-400, $gray-400), var(--gray-500, $gray-500), var(--gray-600, $gray-600));
}
}
diff --git a/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss b/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss
new file mode 100644
index 00000000000..41bb6d107f1
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss
@@ -0,0 +1,3 @@
+.usage-data {
+ max-height: 400px;
+}
diff --git a/app/assets/stylesheets/page_bundles/admin/jobs_index.scss b/app/assets/stylesheets/page_bundles/admin/jobs_index.scss
new file mode 100644
index 00000000000..7844cae5f87
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/admin/jobs_index.scss
@@ -0,0 +1,5 @@
+.admin-builds-table {
+ td:last-child {
+ min-width: 120px;
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index 3d1ae3519a9..620b37914d8 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -138,6 +138,47 @@
border: 1px solid var(--gray-100, $gray-100);
}
+// to highlight columns we have animated pulse of box-shadow
+// we don't want to actually animate the box-shadow property
+// because that causes costly repaints. Instead we can add a
+// pseudo-element that is the same size as our element, then
+// animate opacity/transform to give a soothing single pulse
+.board-column-highlighted::after {
+ content: '';
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ pointer-events: none;
+ opacity: 0;
+ z-index: -1;
+ box-shadow: 0 0 6px 3px $blue-200;
+ animation-name: board-column-flash-border;
+ animation-duration: 1.2s;
+ animation-fill-mode: forwards;
+ animation-timing-function: ease-in-out;
+}
+
+@keyframes board-column-flash-border {
+ 0%,
+ 100% {
+ opacity: 0;
+ transform: scale(0.98);
+ }
+
+ 25%,
+ 75% {
+ opacity: 1;
+ transform: scale(0.99);
+ }
+
+ 50% {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
.board-header {
&.has-border::before {
border-top: 3px solid;
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index f6b9473d235..7c4d51ab677 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -97,7 +97,8 @@ $ide-commit-header-height: 48px;
border-right: 1px solid var(--ide-border-color, $white-dark);
border-bottom: 1px solid var(--ide-border-color, $white-dark);
- &.active {
+ &.active,
+ .gl-tab-nav-item-active {
background-color: var(--ide-highlight-background, $white);
border-bottom-color: transparent;
}
@@ -114,6 +115,42 @@ $ide-commit-header-height: 48px;
}
}
}
+
+ .gl-tab-content {
+ padding: 0;
+ }
+
+ .gl-tabs-nav {
+ border-width: 0;
+
+ li {
+ padding: 0 !important;
+ background: transparent !important;
+ border: 0 !important;
+
+ a {
+ display: flex;
+ align-items: center;
+ padding: $grid-size $gl-padding !important;
+ box-shadow: none !important;
+ font-weight: normal !important;
+
+ background-color: var(--ide-background-hover, $gray-normal);
+ border-right: 1px solid var(--ide-border-color, $white-dark);
+ border-bottom: 1px solid var(--ide-border-color, $white-dark);
+
+ &.gl-tab-nav-item-active {
+ background-color: var(--ide-highlight-background, $white);
+ border-color: var(--ide-border-color, $white-dark);
+ border-bottom-color: transparent;
+ }
+
+ .multi-file-tab-close svg {
+ top: 0;
+ }
+ }
+ }
+ }
}
.multi-file-tab {
@@ -605,6 +642,17 @@ $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 {
@@ -623,7 +671,8 @@ $ide-commit-header-height: 48px;
height: 100%;
}
- .nav-links {
+ .nav-links,
+ .gl-tabs-nav {
height: 30px;
}
@@ -965,17 +1014,25 @@ $ide-commit-header-height: 48px;
}
.ide-nav-form {
- .nav-links li {
+ .nav-links li,
+ .gl-tabs-nav li {
width: 50%;
padding-left: 0;
padding-right: 0;
a {
text-align: center;
+ font-size: 14px;
+ line-height: 30px;
- &:not(.active) {
+ &:not(.active),
+ &:not(.gl-tab-nav-item-active) {
background-color: var(--ide-dropdown-background, $gray-light);
}
+
+ &.gl-tab-nav-item-active {
+ font-weight: bold;
+ }
}
}
diff --git a/app/assets/stylesheets/page_bundles/import.scss b/app/assets/stylesheets/page_bundles/import.scss
index 5f43d5df7e3..453b810196b 100644
--- a/app/assets/stylesheets/page_bundles/import.scss
+++ b/app/assets/stylesheets/page_bundles/import.scss
@@ -12,35 +12,6 @@
width: 1%;
}
-.import-project-name-input {
- border-radius: 0 $border-radius-default $border-radius-default 0;
- position: relative;
- left: -1px;
- max-width: 300px;
-}
-
-.import-slash-divider {
- background-color: $gray-lightest;
- border: 1px solid $border-color;
-}
-
-.import-row {
- height: 55px;
-}
-
-.import-table {
- .import-jobs-from-col,
- .import-jobs-to-col,
- .import-jobs-status-col,
- .import-jobs-cta-col {
- border-bottom-width: 1px;
- padding-left: $gl-padding;
- }
-}
-
-.import-projects-loading-icon {
- margin-top: $gl-padding-32;
-}
.import-entities-target-select {
&.disabled {
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index 231723ca4e3..25401a161da 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -79,12 +79,6 @@ $header-height: 40px;
margin-top: 16px;
}
-.heading-with-border {
- border-bottom: 1px solid $gray-100;
- display: inline-block;
- padding-bottom: 16px;
-}
-
svg {
fill: currentColor;
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index be74503c21f..3263a5067ea 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -7,7 +7,6 @@
.diff-files-holder {
flex: 1;
min-width: 0;
- z-index: 201;
}
.diff-tree-list {
diff --git a/app/assets/stylesheets/page_bundles/oncall_schedules.scss b/app/assets/stylesheets/page_bundles/oncall_schedules.scss
index 1b190024457..a6668f00147 100644
--- a/app/assets/stylesheets/page_bundles/oncall_schedules.scss
+++ b/app/assets/stylesheets/page_bundles/oncall_schedules.scss
@@ -37,12 +37,6 @@
&.gl-modal .modal-md {
max-width: 640px;
}
-
- // TODO: move to gitlab/ui utilities
- // https://gitlab.com/gitlab-org/gitlab/-/issues/297502
- .gl-w-fit-content {
- width: fit-content;
- }
}
//// Copied from roadmaps.scss - adapted for on-call schedules
@@ -91,9 +85,6 @@ $column-right-gradient: linear-gradient(to right, $gradient-dark-gray 0%, $gradi
}
.timeline-header-item {
- // container size minus left panel width divided by 2 week timeframes
- width: calc((100% - #{$details-cell-width}) / 2);
-
&:last-of-type .item-label {
@include gl-border-r-0;
}
@@ -174,9 +165,6 @@ $column-right-gradient: linear-gradient(to right, $gradient-dark-gray 0%, $gradi
.timeline-cell {
@include gl-relative;
- // width: $timeline-cell-width;
- // container size minus left panel width divided by 2 week timeframes
- width: calc((100% - #{$details-cell-width}) / 2);
@include gl-bg-transparent;
border-right: $border-style;
diff --git a/app/assets/stylesheets/page_bundles/pipelines.scss b/app/assets/stylesheets/page_bundles/pipelines.scss
index dbde7933a8b..ae36f7e3ac1 100644
--- a/app/assets/stylesheets/page_bundles/pipelines.scss
+++ b/app/assets/stylesheets/page_bundles/pipelines.scss
@@ -67,7 +67,8 @@
// Mini Pipelines
.stage-cell {
- .mini-pipeline-graph-dropdown-toggle {
+ .mini-pipeline-graph-dropdown-toggle,
+ .mini-pipeline-graph-gl-dropdown-toggle {
svg {
height: $ci-action-icon-size;
width: $ci-action-icon-size;
@@ -138,7 +139,13 @@
}
// Dropdown button in mini pipeline graph
-button.mini-pipeline-graph-dropdown-toggle {
+button.mini-pipeline-graph-dropdown-toggle,
+// As the `mini-pipeline-item` mixin specificity is lower
+// than the toggle of dropdown with 'variant="link"' we add
+// classes ".gl-button.btn-link" to make it more specific.
+// Once FF ci_mini_pipeline_gl_dropdown is removed, the `mini-pipeline-item`
+// itself could increase its specificity to simplify this selector
+button.gl-button.btn-link.mini-pipeline-graph-gl-dropdown-toggle {
@include mini-pipeline-item();
}
diff --git a/app/assets/stylesheets/page_bundles/signup.scss b/app/assets/stylesheets/page_bundles/signup.scss
index 9ed48b693b9..a207c10b04f 100644
--- a/app/assets/stylesheets/page_bundles/signup.scss
+++ b/app/assets/stylesheets/page_bundles/signup.scss
@@ -73,3 +73,7 @@
text-decoration: none;
}
}
+
+.edit-profile {
+ max-width: 460px;
+}
diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss
deleted file mode 100644
index af1eefd7587..00000000000
--- a/app/assets/stylesheets/pages/admin.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-.info-well {
- .admin-well-statistics,
- .admin-well-features {
- padding-bottom: 46px;
- }
-}
-
-.usage-data {
- max-height: 400px;
-}
-
-[data-page='admin:jobs:index'] {
- .admin-builds-table {
- td:last-child {
- min-width: 120px;
- }
- }
-}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 9b17da80023..7111d3d4107 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -240,11 +240,6 @@
.commit,
.generic-commit-status {
- a,
- button {
- vertical-align: baseline;
- }
-
a {
color: $gl-text-color;
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 52bd16d1a79..ef737e11799 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -74,14 +74,10 @@
justify-content: flex-end;
}
- .encoding-selector,
.soft-wrap-toggle {
display: inline-block;
vertical-align: top;
font-family: $regular-font;
- }
-
- .soft-wrap-toggle {
margin: 0 $btn-side-margin;
.soft-wrap {
@@ -128,15 +124,6 @@
margin: 3px 0;
}
- .encoding-selector {
- display: block;
- margin: 3px 0;
-
- button {
- width: 100%;
- }
- }
-
@media(max-width: map-get($grid-breakpoints, md)-1) {
clear: both;
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index aeda91c1714..87307fd682e 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -260,7 +260,6 @@
}
.pipeline-quota {
- border-top: 1px solid $table-border-color;
border-bottom: 1px solid $table-border-color;
margin: 0 0 $gl-padding;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index e5528c25e82..a6ab5459a84 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -117,6 +117,11 @@
}
}
+.reviewer .merge-icon {
+ bottom: -3px;
+ right: -3px;
+}
+
.right-sidebar {
position: fixed;
top: $header-height;
@@ -156,14 +161,6 @@
color: inherit;
}
- // TODO remove this class once we can generate a correct hover utility from `gitlab/ui`,
- // see here: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39286#note_396767000
- .btn-link-hover:hover {
- * {
- @include gl-text-blue-800;
- }
- }
-
.issuable-header-text {
margin-top: 7px;
}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 1caf62067a6..2a8a86615f6 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -108,18 +108,6 @@ ul.related-merge-requests > li {
}
}
-.issuable-email-modal-btn {
- padding: 0;
- color: $blue-600;
- background-color: transparent;
- border: 0;
- outline: 0;
-
- &:hover {
- text-decoration: underline;
- }
-}
-
.email-modal-input-group {
margin-bottom: 10px;
@@ -203,15 +191,9 @@ ul.related-merge-requests > li {
}
}
-.discussion-reply-holder {
- .avatar-note-form-holder .note-edit-form {
- display: block;
- margin-left: $note-icon-gutter-width;
-
- @include media-breakpoint-down(xs) {
- margin-left: 0;
- }
- }
+.discussion-reply-holder,
+.note-edit-form {
+ display: block;
}
.issue-sort-dropdown {
@@ -221,6 +203,10 @@ ul.related-merge-requests > li {
.reverse-sort-btn {
color: $gl-text-color-secondary;
+
+ &.disabled {
+ color: $gl-text-color-disabled;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 4d93702f1c2..b7d05fc411a 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -120,7 +120,7 @@
}
.labels-container {
- background-color: $gray-light;
+ background-color: $gray-100;
border-radius: $border-radius-default;
padding: $gl-padding $gl-padding-8;
}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 81a70470c65..019d827798c 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -42,8 +42,7 @@
.login-box,
.omniauth-container {
box-shadow: 0 0 0 1px $border-color;
- border-bottom-right-radius: $border-radius;
- border-bottom-left-radius: $border-radius;
+ border-radius: $border-radius;
padding: 15px;
.login-heading h3 {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index b99e619cc98..a62df1258af 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -221,7 +221,7 @@ $mr-widget-min-height: 69px;
.mr-widget-pipeline-graph {
.dropdown-menu {
- z-index: 300;
+ z-index: $zindex-dropdown-menu;
}
}
@@ -375,13 +375,14 @@ $mr-widget-min-height: 69px;
}
.text {
- span {
- font-weight: $gl-font-weight-bold;
- }
-
p {
margin-top: $gl-padding;
}
+
+ .highlight {
+ margin: 0 0 $gl-padding;
+ font-weight: $gl-font-weight-bold;
+ }
}
}
@@ -981,7 +982,14 @@ $mr-widget-min-height: 69px;
}
.mini-pipeline-graph-dropdown-toggle,
- .stage-cell .mini-pipeline-graph-dropdown-toggle svg {
+ .stage-cell .mini-pipeline-graph-dropdown-toggle svg,
+ // As the `mini-pipeline-item` mixin specificity is lower
+ // than the toggle of dropdown with 'variant="link"' we add
+ // classes ".gl-button.btn-link" to make it more specific.
+ // Once FF ci_mini_pipeline_gl_dropdown is removed, the `mini-pipeline-item`
+ // itself could increase its specificity to simplify this selector
+ button.gl-button.btn-link.mini-pipeline-graph-gl-dropdown-toggle,
+ .stage-cell button.gl-button.btn-link.mini-pipeline-graph-gl-dropdown-toggle svg {
height: $ci-action-icon-size-lg;
width: $ci-action-icon-size-lg;
}
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 254ad96bb57..ffbfa47f9bd 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -212,8 +212,12 @@ table {
}
}
-.note-edit-form {
+// Snippets are the only non-vue form left
+.snippets.note-edit-form {
display: none;
+}
+
+.note-edit-form {
font-size: 14px;
.md-area {
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 4216091e8a9..190bdcb1efd 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -1,6 +1,5 @@
$system-note-icon-size: 32px;
$system-note-svg-size: 16px;
-$note-form-margin-left: 72px;
@mixin vertical-line($left) {
&::before {
@@ -54,16 +53,6 @@ $note-form-margin-left: 72px;
&.note-form {
margin-left: 0;
- @include notes-media('min', map-get($grid-breakpoints, md)) {
- margin-left: $note-form-margin-left;
- }
-
- .timeline-icon {
- @include notes-media('min', map-get($grid-breakpoints, sm)) {
- margin-left: -$note-icon-gutter-width;
- }
- }
-
.timeline-content {
margin-left: 0;
}
@@ -84,36 +73,17 @@ $note-form-margin-left: 72px;
.replies-toggle {
background-color: $gray-light;
padding: $gl-padding-8 $gl-padding;
- border-top: 1px solid $gray-50;
- border-bottom: 1px solid $gray-50;
+ border-top: 1px solid $gray-100;
+ border-bottom: 1px solid $gray-100;
.collapse-replies-btn:hover {
color: $blue-600;
}
- &.expanded {
- span {
- cursor: pointer;
- }
-
- svg {
- position: relative;
- top: 3px;
- }
- }
-
&.collapsed {
color: $gl-text-color-secondary;
border-radius: 0 0 $border-radius-default $border-radius-default;
- svg {
- float: left;
- position: relative;
- top: $gl-padding-4;
- margin-right: $gl-padding-8;
- cursor: pointer;
- }
-
img {
margin: -2px 4px 0 0;
}
@@ -178,7 +148,6 @@ $note-form-margin-left: 72px;
> li {
display: block;
position: relative;
- border-bottom: 0;
&.being-posted {
pointer-events: none;
@@ -549,21 +518,6 @@ $note-form-margin-left: 72px;
.code-commit .notes-content,
.diff-viewer > .image ~ .note-container {
background-color: $white;
-
- .avatar-note-form-holder {
- .user-avatar-link img {
- margin: 13px $gl-padding $gl-padding;
- }
-
- form,
- ~ .discussion-form-container {
- padding: $gl-padding;
-
- @include media-breakpoint-up(sm) {
- margin-left: $note-icon-gutter-width;
- }
- }
- }
}
.diff-viewer > .image ~ .note-container form.new-note {
@@ -953,14 +907,6 @@ $note-form-margin-left: 72px;
.discussion-filter-container {
.dropdown-menu {
margin-bottom: $gl-padding-4;
-
- @include media-breakpoint-down(md) {
- margin-left: $btn-side-margin + $contextual-sidebar-collapsed-width;
- }
-
- @include media-breakpoint-down(xs) {
- margin-left: $btn-side-margin;
- }
}
}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 3605283245f..6a2fa2ee7a1 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -138,6 +138,13 @@
}
}
+.social-provider-btn-image {
+ > img {
+ width: 16px;
+ vertical-align: inherit;
+ }
+}
+
.provider-btn-image {
display: inline-block;
padding: 5px 10px;
@@ -378,19 +385,6 @@ table.u2f-registrations,
display: inline;
margin-right: $gl-padding / 4;
}
-
- .badge-verification-status {
- border-width: 1px;
- border-style: solid;
-
- &.verified {
- @include green-status-color;
- }
-
- &.unverified {
- @include status-color($gray-dark, color('gray'), $common-gray-dark);
- }
- }
}
.edit-user {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 7fafd28be56..8251cdb9bbb 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -571,10 +571,6 @@
top: 0;
}
}
-
- .btn-missing {
- @extend .btn-missing;
- }
}
}
@@ -996,6 +992,20 @@ pre.light-well {
width: auto;
}
}
+
+ // Remove once gitlab/ui solution is implemented:
+ // https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1157
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/300405
+ .gl-search-box-by-type-input {
+ width: 100%;
+ }
+
+ // Remove once gitlab/ui solution is implemented
+ // https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1158
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/300405
+ .gl-new-dropdown-button-text {
+ @include str-truncated;
+ }
}
.clearable-input {
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 352050f7b01..fa008a05e11 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -49,8 +49,6 @@
position: relative;
.dropdown-menu {
- min-width: 100%;
- width: 100%;
left: inherit;
right: 0;
}
@@ -114,7 +112,7 @@
}
th {
- border-top-color: $gray-light;
+ border: 0;
}
td {
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index 31a501f3a36..849749ee7c7 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -903,7 +903,7 @@ table a code {
padding: 0;
background-color: #4f4f4f;
}
-.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) {
margin-right: 40px;
}
.dropdown-select {
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 7f6e537af8f..44da509481d 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -736,7 +736,6 @@ body {
white-space: nowrap;
}
.btn:active, .btn.active {
- box-shadow: rgba(0, 0, 0, 0.16);
background-color: #eaeaea;
border-color: #e3e3e3;
color: #303030;
@@ -903,7 +902,7 @@ table a code {
padding: 0;
background-color: #dbdbdb;
}
-.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) {
margin-right: 40px;
}
.dropdown-select {
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index af43c532b7c..4b88b94f3a6 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -1174,7 +1174,7 @@ table a code {
padding: 0;
background-color: #dbdbdb;
}
-.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+.dropdown-menu .badge.badge-pill + span:not(.badge):not(.badge-pill) {
margin-right: 40px;
}
.dropdown-select {
@@ -2093,8 +2093,7 @@ table.code {
.login-page .login-box,
.login-page .omniauth-container {
box-shadow: 0 0 0 1px #dbdbdb;
- border-bottom-right-radius: 0.25rem;
- border-bottom-left-radius: 0.25rem;
+ border-radius: 0.25rem;
padding: 15px;
}
.login-page .login-box .nav .active a,
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index ab330ed69c6..d424dcbf8f2 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -110,7 +110,7 @@
// This utility is used to force the z-index to match that of dropdown menu's
.gl-z-dropdown-menu\! {
- z-index: 300 !important;
+ z-index: $zindex-dropdown-menu !important;
}
.gl-flex-basis-quarter {
@@ -143,3 +143,17 @@
flex-direction: column !important;
}
}
+
+// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1165
+.gl-xs-mb-4 {
+ @media (max-width: $breakpoint-sm) {
+ margin-bottom: $gl-spacing-scale-4;
+ }
+}
+
+// Same as above
+.gl-xs-mb-4\! {
+ @media (max-width: $breakpoint-sm) {
+ margin-bottom: $gl-spacing-scale-4 !important;
+ }
+}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 179e6ef60fb..7f7d38a09c5 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -238,11 +238,13 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
*::ApplicationSettingsHelper.visible_attributes,
*::ApplicationSettingsHelper.external_authorization_service_attributes,
*ApplicationSetting.repository_storages_weighted_attributes,
+ *ApplicationSetting.kroki_formats_attributes.keys.map { |key| "kroki_formats_#{key}".to_sym },
:lets_encrypt_notification_email,
:lets_encrypt_terms_of_service_accepted,
:domain_denylist_file,
:raw_blob_request_limit,
:issues_create_limit,
+ :notes_create_limit,
:default_branch_name,
disabled_oauth_sign_in_sources: [],
import_sources: [],
diff --git a/app/controllers/admin/cohorts_controller.rb b/app/controllers/admin/cohorts_controller.rb
index a26dc554506..9bb73c822b0 100644
--- a/app/controllers/admin/cohorts_controller.rb
+++ b/app/controllers/admin/cohorts_controller.rb
@@ -1,19 +1,11 @@
# frozen_string_literal: true
class Admin::CohortsController < Admin::ApplicationController
- include Analytics::UniqueVisitsHelper
-
- track_unique_visits :index, target_id: 'i_analytics_cohorts'
-
feature_category :devops_reports
+ # Backwards compatibility. Remove it and routing in 14.0
+ # @see https://gitlab.com/gitlab-org/gitlab/-/issues/299303
def index
- if Gitlab::CurrentSettings.usage_ping_enabled
- cohorts_results = Rails.cache.fetch('cohorts', expires_in: 1.day) do
- CohortsService.new.execute
- end
-
- @cohorts = CohortsSerializer.new.represent(cohorts_results)
- end
+ redirect_to admin_users_path(tab: 'cohorts')
end
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 3fe972d1917..d0761083c8b 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -2,6 +2,7 @@
class Admin::UsersController < Admin::ApplicationController
include RoutableActions
+ include Analytics::UniqueVisitsHelper
before_action :user, except: [:index, :new, :create]
before_action :check_impersonation_availability, only: :impersonate
@@ -15,6 +16,10 @@ class Admin::UsersController < Admin::ApplicationController
@users = @users.includes(:authorized_projects) # rubocop: disable CodeReuse/ActiveRecord
@users = @users.sort_by_attribute(@sort = params[:sort])
@users = @users.page(params[:page])
+
+ @cohorts = load_cohorts
+
+ track_cohorts_visit if params[:tab] == 'cohorts'
end
def show
@@ -307,6 +312,22 @@ class Admin::UsersController < Admin::ApplicationController
def log_impersonation_event
Gitlab::AppLogger.info(_("User %{current_user_username} has started impersonating %{username}") % { current_user_username: current_user.username, username: user.username })
end
+
+ def load_cohorts
+ if Gitlab::CurrentSettings.usage_ping_enabled
+ cohorts_results = Rails.cache.fetch('cohorts', expires_in: 1.day) do
+ CohortsService.new.execute
+ end
+
+ CohortsSerializer.new.represent(cohorts_results)
+ end
+ end
+
+ def track_cohorts_visit
+ if request.format.html? && request.headers['DNT'] != '1'
+ track_visit('i_analytics_cohorts')
+ end
+ end
end
Admin::UsersController.prepend_if_ee('EE::Admin::UsersController')
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 3cb7373a970..5f14d95ffed 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -556,4 +556,4 @@ class ApplicationController < ActionController::Base
end
end
-ApplicationController.prepend_if_ee('EE::ApplicationController')
+ApplicationController.prepend_ee_mod
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 9ee69c7c07f..79e45bcf929 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -18,7 +18,7 @@ class AutocompleteController < ApplicationController
.new(params: params, current_user: current_user, project: project, group: group)
.execute
- render json: UserSerializer.new(params).represent(users, project: project)
+ render json: UserSerializer.new(params.merge({ current_user: current_user })).represent(users, project: project)
end
def user
diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb
index e0d1f313fc7..0ec6a2cb38a 100644
--- a/app/controllers/chaos_controller.rb
+++ b/app/controllers/chaos_controller.rb
@@ -23,6 +23,15 @@ class ChaosController < ActionController::Base
do_chaos :kill, Chaos::KillWorker
end
+ def gc
+ gc_stat = Gitlab::Chaos.run_gc
+
+ render json: {
+ worker_id: Prometheus::PidProvider.worker_id,
+ gc_stat: gc_stat
+ }
+ end
+
private
def do_chaos(method, worker, *args)
diff --git a/app/controllers/concerns/boards_actions.rb b/app/controllers/concerns/boards_actions.rb
index b382e338a78..79e6f027c2f 100644
--- a/app/controllers/concerns/boards_actions.rb
+++ b/app/controllers/concerns/boards_actions.rb
@@ -34,16 +34,26 @@ module BoardsActions
def boards
strong_memoize(:boards) do
- Boards::ListService.new(parent, current_user).execute
+ existing_boards = boards_finder.execute
+ if existing_boards.any?
+ existing_boards
+ else
+ # if no board exists, create one
+ [board_create_service.execute.payload]
+ end
end
end
def board
strong_memoize(:board) do
- boards.find(params[:id])
+ board_finder.execute.first
end
end
+ def board_type
+ board_klass.to_type
+ end
+
def serializer
BoardSerializer.new(current_user: current_user)
end
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb
index d8bc1320db4..6e6686f225c 100644
--- a/app/controllers/concerns/boards_responses.rb
+++ b/app/controllers/concerns/boards_responses.rb
@@ -66,7 +66,11 @@ module BoardsResponses
end
def respond_with_board
- respond_with(@board) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ return render_404 unless @board
+
+ respond_with(@board)
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
end
def serialize_as_json(resource)
diff --git a/app/controllers/concerns/comment_and_close_flag.rb b/app/controllers/concerns/comment_and_close_flag.rb
new file mode 100644
index 00000000000..e2f3272abbc
--- /dev/null
+++ b/app/controllers/concerns/comment_and_close_flag.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module CommentAndCloseFlag
+ extend ActiveSupport::Concern
+
+ included do
+ before_action do
+ push_frontend_feature_flag(:remove_comment_close_reopen, @group)
+ end
+ end
+end
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
index baebedb8e5d..a3ea39d9c3d 100644
--- a/app/controllers/concerns/integrations_actions.rb
+++ b/app/controllers/concerns/integrations_actions.rb
@@ -34,10 +34,6 @@ module IntegrationsActions
end
end
- def custom_integration_projects
- Project.with_custom_integration_compared_to(integration).page(params[:page]).per(20)
- end
-
def test
render json: {}, status: :ok
end
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 816a93f14c6..9e3625d1b36 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -18,18 +18,26 @@ module MembershipActions
def update
update_params = params.require(root_params_key).permit(:access_level, :expires_at)
member = membershipable.members_and_requesters.find(params[:id])
- member = Members::UpdateService
+ result = Members::UpdateService
.new(current_user, update_params)
.execute(member)
- if member.expires?
- render json: {
- expires_in: helpers.distance_of_time_in_words_to_now(member.expires_at),
- expires_soon: member.expires_soon?,
- expires_at_formatted: member.expires_at.to_time.in_time_zone.to_s(:medium)
- }
+ member = result[:member]
+
+ member_data = if member.expires?
+ {
+ expires_in: helpers.distance_of_time_in_words_to_now(member.expires_at),
+ expires_soon: member.expires_soon?,
+ expires_at_formatted: member.expires_at.to_time.in_time_zone.to_s(:medium)
+ }
+ else
+ {}
+ end
+
+ if result[:status] == :success
+ render json: member_data
else
- render json: {}
+ render json: { message: result[:message] }, status: :unprocessable_entity
end
end
diff --git a/app/controllers/concerns/multiple_boards_actions.rb b/app/controllers/concerns/multiple_boards_actions.rb
index 370b8c72bfe..5206f5759d8 100644
--- a/app/controllers/concerns/multiple_boards_actions.rb
+++ b/app/controllers/concerns/multiple_boards_actions.rb
@@ -65,6 +65,7 @@ module MultipleBoardsActions
private
def redirect_to_recent_board
+ return unless board_type == Board.to_type
return if request.format.json? || !parent.multiple_issue_boards_available? || !latest_visited_board
redirect_to board_path(latest_visited_board.board)
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index bfa7a30bc65..036d95622ef 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -31,9 +31,9 @@ module NotesActions
# We know there's more data, so tell the frontend to poll again after 1ms
set_polling_interval_header(interval: 1) if meta[:more]
- # Only present an ETag for the empty response to ensure pagination works
- # as expected
- ::Gitlab::EtagCaching::Middleware.skip!(response) if notes.present?
+ # We might still want to investigate further adjusting ETag caching with paginated notes, but
+ # let's avoid ETag caching for now until we confirm the viability of paginated notes.
+ ::Gitlab::EtagCaching::Middleware.skip!(response)
render json: meta.merge(notes: notes)
end
@@ -243,7 +243,8 @@ module NotesActions
:type,
:note,
:line_code, # LegacyDiffNote
- :position # DiffNote
+ :position, # DiffNote
+ :confidential
).tap do |create_params|
create_params.merge!(
params.permit(:merge_request_diff_head_sha, :in_reply_to_discussion_id)
diff --git a/app/controllers/concerns/redis_tracking.rb b/app/controllers/concerns/redis_tracking.rb
index d71935356b8..a7e75f802a8 100644
--- a/app/controllers/concerns/redis_tracking.rb
+++ b/app/controllers/concerns/redis_tracking.rb
@@ -7,30 +7,26 @@
#
# include RedisTracking
#
-# track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :my_feature
-#
-# if the feature flag is enabled by default you should use
-# track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :my_feature, feature_default_enabled: true
+# track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score'
#
# You can also pass custom conditions using `if:`, using the same format as with Rails callbacks.
module RedisTracking
extend ActiveSupport::Concern
class_methods do
- def track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false, if: nil)
+ def track_redis_hll_event(*controller_actions, name:, if: nil)
custom_conditions = Array.wrap(binding.local_variable_get('if'))
conditions = [:trackable_request?, *custom_conditions]
after_action only: controller_actions, if: conditions do
- track_unique_redis_hll_event(name, feature, feature_default_enabled)
+ track_unique_redis_hll_event(name)
end
end
end
private
- def track_unique_redis_hll_event(event_name, feature, feature_default_enabled)
- return unless metric_feature_enabled?(feature, feature_default_enabled)
+ def track_unique_redis_hll_event(event_name)
return unless visitor_id
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: visitor_id)
@@ -40,10 +36,6 @@ module RedisTracking
request.format.html? && request.headers['DNT'] != '1'
end
- def metric_feature_enabled?(feature, default_enabled)
- Feature.enabled?(feature, default_enabled: default_enabled)
- end
-
def visitor_id
return cookies[:visitor_id] if cookies[:visitor_id].present?
return unless current_user
diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb
index c295290a123..3cab198c1f9 100644
--- a/app/controllers/concerns/service_params.rb
+++ b/app/controllers/concerns/service_params.rb
@@ -12,6 +12,7 @@ module ServiceParams
:api_version,
:bamboo_url,
:branches_to_be_notified,
+ :labels_to_be_notified,
:build_key,
:build_type,
:ca_pem,
diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb
index c93e75b438b..0ee8d0c9307 100644
--- a/app/controllers/concerns/snippets_actions.rb
+++ b/app/controllers/concerns/snippets_actions.rb
@@ -15,7 +15,7 @@ module SnippetsActions
skip_before_action :verify_authenticity_token,
if: -> { action_name == 'show' && js_request? }
- track_redis_hll_event :show, name: 'i_snippets_show', feature: :usage_data_i_snippets_show, feature_default_enabled: true
+ track_redis_hll_event :show, name: 'i_snippets_show'
respond_to :html
end
diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb
index 4ec561014a8..b285faee9bc 100644
--- a/app/controllers/concerns/spammable_actions.rb
+++ b/app/controllers/concerns/spammable_actions.rb
@@ -3,9 +3,6 @@
module SpammableActions
extend ActiveSupport::Concern
- include Recaptcha::Verify
- include Gitlab::Utils::StrongMemoize
-
included do
before_action :authorize_submit_spammable!, only: :mark_as_spam
end
@@ -20,17 +17,11 @@ module SpammableActions
private
- def ensure_spam_config_loaded!
- strong_memoize(:spam_config_loaded) do
- Gitlab::Recaptcha.load_configurations!
- end
- end
-
def recaptcha_check_with_fallback(should_redirect = true, &fallback)
if should_redirect && spammable.valid?
redirect_to spammable_path
- elsif render_recaptcha?
- ensure_spam_config_loaded!
+ elsif spammable.render_recaptcha?
+ Gitlab::Recaptcha.load_configurations!
respond_to do |format|
format.html do
@@ -50,33 +41,30 @@ module SpammableActions
end
def spammable_params
- default_params = { request: request }
-
- recaptcha_check = recaptcha_response &&
- ensure_spam_config_loaded! &&
- verify_recaptcha(response: recaptcha_response)
-
- return default_params unless recaptcha_check
-
- { recaptcha_verified: true,
- spam_log_id: params[:spam_log_id] }.merge(default_params)
- end
-
- def recaptcha_response
- # NOTE: This field name comes from `Recaptcha::ClientHelper#recaptcha_tags` in the recaptcha
- # gem, which is called from the HAML `_recaptcha_form.html.haml` form.
+ # NOTE: For the legacy reCAPTCHA implementation based on the HTML/HAML form, the
+ # 'g-recaptcha-response' field name comes from `Recaptcha::ClientHelper#recaptcha_tags` in the
+ # recaptcha gem, which is called from the HAML `_recaptcha_form.html.haml` form.
#
- # It is used in the `Recaptcha::Verify#verify_recaptcha` if the `response` option is not
- # passed explicitly.
+ # It is used in the `Recaptcha::Verify#verify_recaptcha` to extract the value from `params`,
+ # if the `response` option is not passed explicitly.
#
# Instead of relying on this behavior, we are extracting and passing it explicitly. This will
# make it consistent with the newer, modern reCAPTCHA verification process as it will be
# implemented via the GraphQL API and in Vue components via the native reCAPTCHA Javascript API,
# which requires that the recaptcha response param be obtained and passed explicitly.
#
- # After this newer GraphQL/JS API process is fully supported by the backend, we can remove this
- # (and other) HAML-specific support.
- params['g-recaptcha-response']
+ # It can also be expanded to multiple fields when we move to future alternative captcha
+ # implementations such as FriendlyCaptcha. See https://gitlab.com/gitlab-org/gitlab/-/issues/273480
+
+ # After this newer GraphQL/JS API process is fully supported by the backend, we can remove the
+ # check for the 'g-recaptcha-response' field and other HTML/HAML form-specific support.
+ captcha_response = params['g-recaptcha-response']
+
+ {
+ request: request,
+ spam_log_id: params[:spam_log_id],
+ captcha_response: captcha_response
+ }
end
def spammable
@@ -90,11 +78,4 @@ module SpammableActions
def authorize_submit_spammable!
access_denied! unless current_user.admin?
end
-
- def render_recaptcha?
- return false if spammable.errors.count > 1 # re-render "new" template in case there are other errors
- return false unless Gitlab::Recaptcha.enabled?
-
- spammable.needs_recaptcha?
- end
end
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index 1ae90edd8f7..4014e4f0024 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -36,8 +36,7 @@ module WikiActions
# NOTE: We want to include wiki page views in the same counter as the other
# Event-based wiki actions tracked through TrackUniqueEvents, so we use the same event name.
- track_redis_hll_event :show, name: Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION.to_s,
- feature: :track_unique_wiki_page_views, feature_default_enabled: true
+ track_redis_hll_event :show, name: Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION.to_s
helper_method :view_file_button, :diff_file_html_data
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index a88cf64d842..29cb60ad3cc 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -33,6 +33,21 @@ class DashboardController < Dashboard::ApplicationController
protected
def load_events
+ @events =
+ if params[:filter] == "followed"
+ load_user_events
+ else
+ load_project_events
+ end
+
+ Events::RenderService.new(current_user).execute(@events)
+ end
+
+ def load_user_events
+ UserRecentEventsFinder.new(current_user, current_user.followees, event_filter, params).execute
+ end
+
+ def load_project_events
projects =
if params[:filter] == "starred"
ProjectsFinder.new(current_user: current_user, params: { starred: true }).execute
@@ -40,12 +55,10 @@ class DashboardController < Dashboard::ApplicationController
current_user.authorized_projects
end
- @events = EventCollection
+ EventCollection
.new(projects, offset: params[:offset].to_i, filter: event_filter)
.to_a
.map(&:present)
-
- Events::RenderService.new(current_user).execute(@events)
end
def set_show_full_reference
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 1852405e7cf..152f07b4c16 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -20,6 +20,7 @@ class GraphqlController < ApplicationController
before_action :authorize_access_api!
before_action(only: [:execute]) { authenticate_sessionless_user!(:api) }
before_action :set_user_last_activity
+ before_action :track_vs_code_usage
# Since we deactivate authentication from the main ApplicationController and
# defer it to :authorize_access_api!, we need to override the bypass session
@@ -64,6 +65,10 @@ class GraphqlController < ApplicationController
Users::ActivityService.new(current_user).execute
end
+ def track_vs_code_usage
+ Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter.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 093cdf258b2..fa109021b7d 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -3,6 +3,7 @@
class Groups::BoardsController < Groups::ApplicationController
include BoardsActions
include RecordUserLastActivity
+ include Gitlab::Utils::StrongMemoize
before_action :authorize_read_board!, only: [:index, :show]
before_action :assign_endpoint_vars
@@ -14,10 +15,32 @@ class Groups::BoardsController < Groups::ApplicationController
private
+ def board_klass
+ Board
+ end
+
+ def boards_finder
+ strong_memoize :boards_finder do
+ Boards::ListService.new(parent, current_user)
+ end
+ end
+
+ def board_finder
+ strong_memoize :board_finder do
+ Boards::ListService.new(parent, current_user, board_id: params[:id])
+ end
+ end
+
+ def board_create_service
+ strong_memoize :board_create_service do
+ Boards::CreateService.new(parent, current_user)
+ end
+ end
+
def assign_endpoint_vars
- @boards_endpoint = group_boards_url(group)
+ @boards_endpoint = group_boards_path(group)
@namespace_path = group.to_param
- @labels_endpoint = group_labels_url(group)
+ @labels_endpoint = group_labels_path(group)
end
def authorize_read_board!
diff --git a/app/controllers/groups/email_campaigns_controller.rb b/app/controllers/groups/email_campaigns_controller.rb
new file mode 100644
index 00000000000..cbb0176ea7b
--- /dev/null
+++ b/app/controllers/groups/email_campaigns_controller.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+class Groups::EmailCampaignsController < Groups::ApplicationController
+ include InProductMarketingHelper
+ include Gitlab::Tracking::ControllerConcern
+
+ EMAIL_CAMPAIGNS_SCHEMA_URL = 'iglu:com.gitlab/email_campaigns/jsonschema/1-0-0'
+
+ feature_category :navigation
+
+ before_action :check_params
+
+ def index
+ track_click
+ redirect_to redirect_link
+ end
+
+ private
+
+ def track_click
+ data = {
+ namespace_id: group.id,
+ track: @track,
+ series: @series,
+ subject_line: subject_line(@track, @series)
+ }
+
+ track_self_describing_event(EMAIL_CAMPAIGNS_SCHEMA_URL, data: data)
+ end
+
+ def redirect_link
+ case @track
+ when :create
+ create_track_url
+ when :verify
+ project_pipelines_url(group.projects.first)
+ when :trial
+ 'https://about.gitlab.com/free-trial/'
+ when :team
+ group_group_members_url(group)
+ end
+ end
+
+ def create_track_url
+ [
+ new_project_url,
+ new_project_url(anchor: 'import_project'),
+ help_page_url('user/project/repository/repository_mirroring')
+ ][@series]
+ end
+
+ def check_params
+ @track = params[:track]&.to_sym
+ @series = params[:series]&.to_i
+
+ track_valid = @track.in?(Namespaces::InProductMarketingEmailsService::TRACKS.keys)
+ series_valid = @series.in?(0..Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.size - 1)
+
+ render_404 unless track_valid && series_valid
+ end
+end
diff --git a/app/controllers/groups/settings/packages_and_registries_controller.rb b/app/controllers/groups/settings/packages_and_registries_controller.rb
index dbc1e68742b..0135c03026c 100644
--- a/app/controllers/groups/settings/packages_and_registries_controller.rb
+++ b/app/controllers/groups/settings/packages_and_registries_controller.rb
@@ -4,11 +4,18 @@ module Groups
module Settings
class PackagesAndRegistriesController < Groups::ApplicationController
before_action :authorize_admin_group!
+ before_action :verify_packages_enabled!
feature_category :package_registry
def index
end
+
+ private
+
+ def verify_packages_enabled!
+ render_404 unless group.packages_feature_enabled?
+ end
end
end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 068815f7f07..9d7aebe4505 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -30,6 +30,7 @@ class GroupsController < Groups::ApplicationController
before_action do
push_frontend_feature_flag(:vue_issuables_list, @group)
+ push_frontend_feature_flag(:vue_notification_dropdown, @group, default_enabled: :yaml)
end
before_action do
@@ -319,9 +320,7 @@ class GroupsController < Groups::ApplicationController
private
- def successful_creation_hooks
- track_experiment_event(:onboarding_issues, 'created_namespace')
- end
+ def successful_creation_hooks; end
def groups
if @group.supports_events?
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index 5a5200452de..e995562f0c4 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -84,7 +84,16 @@ class HelpController < ApplicationController
end
def documentation_base_url
- @documentation_base_url ||= Gitlab::CurrentSettings.current_application_settings.help_page_documentation_base_url.presence
+ @documentation_base_url ||= documentation_base_url_from_yml_configuration || documentation_base_url_from_db
+ end
+
+ # DEPRECATED
+ def documentation_base_url_from_db
+ Gitlab::CurrentSettings.current_application_settings.help_page_documentation_base_url.presence
+ end
+
+ def documentation_base_url_from_yml_configuration
+ ::Gitlab.config.gitlab_docs.host.presence if ::Gitlab.config.gitlab_docs.enabled
end
def documentation_file_path
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 7394e8bf615..ef32ba4d119 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -22,7 +22,13 @@ class Import::BulkImportsController < ApplicationController
def status
respond_to do |format|
format.json do
- render json: { importable_data: serialized_importable_data }
+ data = importable_data
+
+ pagination_headers.each do |header|
+ response.set_header(header, data.headers[header])
+ end
+
+ render json: { importable_data: serialized_data(data.parsed_response) }
end
format.html do
@source_url = session[url_key]
@@ -31,9 +37,8 @@ class Import::BulkImportsController < ApplicationController
end
def create
- BulkImportService.new(current_user, create_params, credentials).execute
-
- render json: :ok
+ result = BulkImportService.new(current_user, create_params, credentials).execute
+ render json: result.to_json(only: [:id])
end
def realtime_changes
@@ -44,8 +49,12 @@ class Import::BulkImportsController < ApplicationController
private
- def serialized_importable_data
- serializer.represent(importable_data, {}, Import::BulkImportEntity)
+ def pagination_headers
+ %w[x-next-page x-page x-per-page x-prev-page x-total x-total-pages]
+ end
+
+ def serialized_data(data)
+ serializer.represent(data, {}, Import::BulkImportEntity)
end
def serializer
@@ -53,7 +62,7 @@ class Import::BulkImportsController < ApplicationController
end
def importable_data
- client.get('groups', query_params).parsed_response
+ client.get('groups', query_params)
end
# Default query string params used to fetch groups from GitLab source instance
@@ -74,7 +83,9 @@ class Import::BulkImportsController < ApplicationController
def client
@client ||= BulkImports::Clients::Http.new(
uri: session[url_key],
- token: session[access_token_key]
+ token: session[access_token_key],
+ per_page: params[:per_page],
+ page: params[:page]
)
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index ad92645c23e..08a23dc8927 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -6,6 +6,7 @@ class InvitesController < ApplicationController
before_action :member
before_action :ensure_member_exists
before_action :invite_details
+ before_action :set_invite_type, only: :show
skip_before_action :authenticate_user!, only: :decline
helper_method :member?, :current_user_matches_invite?
@@ -15,11 +16,16 @@ class InvitesController < ApplicationController
feature_category :authentication_and_authorization
def show
+ experiment('members/invite_email', actor: member).track(:opened) if initial_invite_email?
+
accept if skip_invitation_prompt?
end
def accept
if member.accept_invite!(current_user)
+ experiment('members/invite_email', actor: member).track(:accepted) if initial_invite_email?
+ session.delete(:invite_type)
+
redirect_to invite_details[:path], notice: _("You have been granted %{member_human_access} access to %{title} %{name}.") %
{ member_human_access: member.human_access, title: invite_details[:title], name: invite_details[:name] }
else
@@ -29,7 +35,7 @@ class InvitesController < ApplicationController
def decline
if member.decline_invite!
- return render layout: 'devise_experimental_onboarding_issues' if !current_user && member.invite_to_unknown_user? && member.created_by
+ return render layout: 'signup_onboarding' if !current_user && member.invite_to_unknown_user? && member.created_by
path =
if current_user
@@ -47,6 +53,14 @@ class InvitesController < ApplicationController
private
+ def set_invite_type
+ session[:invite_type] = params[:invite_type] if params[:invite_type].in?([Members::InviteEmailExperiment::INVITE_TYPE])
+ end
+
+ def initial_invite_email?
+ session[:invite_type] == Members::InviteEmailExperiment::INVITE_TYPE
+ end
+
def skip_invitation_prompt?
!member? && current_user_matches_invite?
end
diff --git a/app/controllers/jira_connect/users_controller.rb b/app/controllers/jira_connect/users_controller.rb
index 571d9f87779..569dc42fed3 100644
--- a/app/controllers/jira_connect/users_controller.rb
+++ b/app/controllers/jira_connect/users_controller.rb
@@ -3,7 +3,7 @@
class JiraConnect::UsersController < ApplicationController
feature_category :integrations
- layout 'devise_experimental_onboarding_issues'
+ layout 'signup_onboarding'
def show
@jira_app_link = params.delete(:return_to)
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index a3e7638cdbc..0a73239709a 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -29,7 +29,7 @@ class Profiles::NotificationsController < Profiles::ApplicationController
end
def user_params
- params.require(:user).permit(:notification_email, :notified_of_own_activity)
+ params.require(:user).permit(:notification_email, :email_opted_in, :notified_of_own_activity)
end
private
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 4d88491e9a8..add5046e213 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -9,23 +9,18 @@ class Profiles::PreferencesController < Profiles::ApplicationController
end
def update
- begin
- result = Users::UpdateService.new(current_user, preferences_params.merge(user: user)).execute
-
- if result[:status] == :success
- flash[:notice] = _('Preferences saved.')
- else
- flash[:alert] = _('Failed to save preferences.')
- end
- rescue ArgumentError => e
- # Raised when `dashboard` is given an invalid value.
- flash[:alert] = _("Failed to save preferences (%{error_message}).") % { error_message: e.message }
- end
+ result = Users::UpdateService.new(current_user, preferences_params.merge(user: user)).execute
+ if result[:status] == :success
+ message = _('Preferences saved.')
- respond_to do |format|
- format.html { redirect_to profile_preferences_path }
- format.js
+ render json: { type: :notice, message: message }
+ else
+ render status: :bad_request, json: { type: :alert, message: _('Failed to save preferences.') }
end
+ rescue ArgumentError => e
+ # Raised when `dashboard` is given an invalid value.
+ message = _("Failed to save preferences (%{error_message}).") % { error_message: e.message }
+ render status: :bad_request, json: { type: :alert, message: message }
end
private
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index 855965ca6e1..f75ab5cdbf2 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -9,7 +9,7 @@ class Projects::BadgesController < Projects::ApplicationController
feature_category :continuous_integration
def pipeline
- pipeline_status = Gitlab::Badge::Pipeline::Status
+ pipeline_status = Gitlab::Ci::Badge::Pipeline::Status
.new(project, params[:ref], opts: {
ignore_skipped: params[:ignore_skipped],
key_text: params[:key_text],
@@ -20,7 +20,7 @@ class Projects::BadgesController < Projects::ApplicationController
end
def coverage
- coverage_report = Gitlab::Badge::Coverage::Report
+ coverage_report = Gitlab::Ci::Badge::Coverage::Report
.new(project, params[:ref], opts: {
job: params[:job],
key_text: params[:key_text],
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 8c66f45dd79..3bb00978aac 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -35,7 +35,7 @@ class Projects::BlobController < Projects::ApplicationController
record_experiment_user(:ci_syntax_templates, namespace_id: @project.namespace_id) if params[:file_name] == @project.ci_config_path_or_default
end
- track_redis_hll_event :create, :update, name: 'g_edit_by_sfe', feature: :track_editor_edit_actions, feature_default_enabled: true
+ track_redis_hll_event :create, :update, name: 'g_edit_by_sfe'
feature_category :source_code_management
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 51c9bf3699a..d2e5d319f96 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -15,6 +15,28 @@ class Projects::BoardsController < Projects::ApplicationController
private
+ def board_klass
+ Board
+ end
+
+ def boards_finder
+ strong_memoize :boards_finder do
+ Boards::ListService.new(parent, current_user)
+ end
+ end
+
+ def board_finder
+ strong_memoize :board_finder do
+ Boards::ListService.new(parent, current_user, board_id: params[:id])
+ end
+ end
+
+ def board_create_service
+ strong_memoize :board_create_service do
+ Boards::CreateService.new(parent, current_user)
+ end
+ end
+
def assign_endpoint_vars
@boards_endpoint = project_boards_path(project)
@bulk_issues_path = bulk_update_project_issues_path(project)
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index a753d5705aa..6f3c96fa654 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -177,10 +177,8 @@ class Projects::BranchesController < Projects::ApplicationController
def fetch_branches_by_mode
return fetch_branches_for_overview if @mode == 'overview'
- # active/stale/all view mode
- @branches = BranchesFinder.new(@repository, params.merge(sort: @sort)).execute
- @branches = @branches.select { |b| b.state.to_s == @mode } if %w[active stale].include?(@mode)
- @branches = Kaminari.paginate_array(@branches).page(params[:page])
+ @branches, @prev_path, @next_path =
+ Projects::BranchesByModeService.new(@project, params.merge(sort: @sort, mode: @mode)).execute
end
def fetch_branches_for_overview
diff --git a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb
index d05ab1b4977..aabcb74cefa 100644
--- a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb
+++ b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb
@@ -40,7 +40,25 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati
end
def report_results
- Ci::DailyBuildGroupReportResultsFinder.new(**finder_params).execute
+ if ::Gitlab::Ci::Features.use_coverage_data_new_finder?(project)
+ ::Ci::Testing::DailyBuildGroupReportResultsFinder.new(
+ params: new_finder_params,
+ current_user: current_user
+ ).execute
+ else
+ Ci::DailyBuildGroupReportResultsFinder.new(**finder_params).execute
+ end
+ end
+
+ def new_finder_params
+ {
+ project: project,
+ coverage: true,
+ start_date: start_date,
+ end_date: end_date,
+ ref_path: params[:ref_path],
+ sort: true
+ }
end
def finder_params
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index ef9025ae52f..3552915b561 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -4,6 +4,7 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
before_action :check_can_collaborate!
before_action do
push_frontend_feature_flag(:ci_config_visualization_tab, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:ci_config_merged_tab, @project, default_enabled: :yaml)
end
feature_category :pipeline_authoring
diff --git a/app/controllers/projects/ci/prometheus_metrics/histograms_controller.rb b/app/controllers/projects/ci/prometheus_metrics/histograms_controller.rb
new file mode 100644
index 00000000000..003441d4b91
--- /dev/null
+++ b/app/controllers/projects/ci/prometheus_metrics/histograms_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Projects
+ module Ci
+ module PrometheusMetrics
+ class HistogramsController < Projects::ApplicationController
+ feature_category :pipeline_authoring
+
+ respond_to :json, only: [:create]
+
+ def create
+ result = ::Ci::PrometheusMetrics::ObserveHistogramsService.new(project, permitted_params).execute
+
+ render json: result.payload, status: result.http_status
+ end
+
+ private
+
+ def permitted_params
+ params.permit(histograms: [:name, :value])
+ end
+ end
+ end
+ end
+end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 2e48f2f0e45..ffdd9fca95b 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -18,8 +18,12 @@ class Projects::CommitController < Projects::ApplicationController
before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests]
before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
+ before_action only: [:pipelines] do
+ push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, @project, type: :development, default_enabled: :yaml)
+ end
BRANCH_SEARCH_LIMIT = 1000
+ COMMIT_DIFFS_PER_PAGE = 75
feature_category :source_code_management
diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb
index b9ab1076999..708b7a6c7ba 100644
--- a/app/controllers/projects/discussions_controller.rb
+++ b/app/controllers/projects/discussions_controller.rb
@@ -18,7 +18,7 @@ class Projects::DiscussionsController < Projects::ApplicationController
end
def unresolve
- discussion.unresolve!
+ Discussions::UnresolveService.new(discussion, current_user).execute
render_discussion
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 1c2930f6e9b..5576d5766c7 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -86,7 +86,7 @@ class Projects::ForksController < Projects::ApplicationController
def fork_service
strong_memoize(:fork_service) do
- ::Projects::ForkService.new(project, current_user, namespace: fork_namespace)
+ ::Projects::ForkService.new(project, current_user, fork_params)
end
end
@@ -96,6 +96,12 @@ class Projects::ForksController < Projects::ApplicationController
end
end
+ def fork_params
+ params.permit(:path, :name, :description, :visibility).tap do |param|
+ param[:namespace] = fork_namespace
+ end
+ end
+
def authorize_fork_namespace!
access_denied! unless fork_namespace && fork_service.valid_fork_target?
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 3a0e40f9745..2816977277a 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -9,6 +9,7 @@ class Projects::IssuesController < Projects::ApplicationController
include IssuesCalendar
include SpammableActions
include RecordUserLastActivity
+ include CommentAndCloseFlag
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
SET_ISSUEABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
@@ -41,7 +42,6 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :create_rate_limit, only: [:create]
before_action do
- push_frontend_feature_flag(:vue_issuable_sidebar, project.group)
push_frontend_feature_flag(:tribute_autocomplete, @project)
push_frontend_feature_flag(:vue_issuables_list, project)
push_frontend_feature_flag(:usage_data_design_action, project, default_enabled: true)
@@ -52,6 +52,7 @@ class Projects::IssuesController < Projects::ApplicationController
real_time_enabled = Gitlab::ActionCable::Config.in_app? || Feature.enabled?(real_time_feature_flag, @project)
push_to_gon_attributes(:features, real_time_feature_flag, real_time_enabled)
+ push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)
@@ -60,8 +61,7 @@ class Projects::IssuesController < Projects::ApplicationController
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
before_action :run_null_hypothesis_experiment,
- only: [:index, :new, :create],
- if: -> { Feature.enabled?(:gitlab_experiments) }
+ only: [:index, :new, :create]
respond_to :html
@@ -106,7 +106,7 @@ class Projects::IssuesController < Projects::ApplicationController
build_params = issue_create_params.merge(
merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
discussion_to_resolve: params[:discussion_to_resolve],
- confidential: !!Gitlab::Utils.to_boolean(params[:issue][:confidential])
+ confidential: !!Gitlab::Utils.to_boolean(issue_create_params[:confidential])
)
service = ::Issues::BuildService.new(project, current_user, build_params)
@@ -131,7 +131,7 @@ class Projects::IssuesController < Projects::ApplicationController
service = ::Issues::CreateService.new(project, current_user, create_params)
@issue = service.execute
- create_vulnerability_issue_link(issue)
+ create_vulnerability_issue_feedback(issue)
if service.discussions_to_resolve.count(&:resolved?) > 0
flash[:notice] = if service.discussion_to_resolve_id
@@ -145,9 +145,6 @@ class Projects::IssuesController < Projects::ApplicationController
format.html do
recaptcha_check_with_fallback { render :new }
end
- format.js do
- @link = @issue.attachment.url.to_js
- end
end
end
@@ -403,7 +400,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
# Overridden in EE
- def create_vulnerability_issue_link(issue); end
+ def create_vulnerability_issue_feedback(issue); end
end
Projects::IssuesController.prepend_if_ee('EE::Projects::IssuesController')
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index d2703f5cc38..8a2ea51ba9d 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -15,9 +15,6 @@ class Projects::JobsController < Projects::ApplicationController
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :authorize_create_proxy_build!, only: :proxy_websocket_authorize
before_action :verify_proxy_request!, only: :proxy_websocket_authorize
- before_action only: :index do
- frontend_experimentation_tracking_data(:jobs_empty_state, 'click_button')
- end
layout 'project'
diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/app/controllers/projects/learn_gitlab_controller.rb
new file mode 100644
index 00000000000..162ba9bd5cb
--- /dev/null
+++ b/app/controllers/projects/learn_gitlab_controller.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class Projects::LearnGitlabController < Projects::ApplicationController
+ before_action :authenticate_user!
+ before_action :check_experiment_enabled?
+
+ feature_category :users
+
+ def index
+ push_frontend_experiment(:learn_gitlab_a, subject: current_user)
+ push_frontend_experiment(:learn_gitlab_b, subject: current_user)
+ end
+
+ private
+
+ def check_experiment_enabled?
+ return access_denied! unless helpers.learn_gitlab_experiment_enabled?(project)
+ end
+end
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index 9cac9f37eb7..e74717a44ab 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -20,7 +20,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
end
def preloadable_mr_relations
- [:metrics, :assignees, { author: :status }]
+ [:metrics, { assignees: :status }, { author: :status }]
end
def merge_request_params
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index 858bdc066c1..e79c19c3b67 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -12,9 +12,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
before_action :build_merge_request, except: [:create]
before_action do
- push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true)
push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
- push_frontend_feature_flag(:reviewer_approval_rules, @project, default_enabled: :yaml)
end
def new
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 9180b3f6b62..98ef9d918ae 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -122,10 +122,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
end
- if render_merge_ref_head_diff?
- return CompareService.new(@project, @merge_request.merge_ref_head.sha)
- .execute(@project, @merge_request.target_branch)
- end
+ return @merge_request.merge_head_diff if render_merge_ref_head_diff?
if @start_sha
@merge_request_diff.compare_with(@start_sha)
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index d452a5e02e2..c9e9a34ad88 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -11,6 +11,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include RecordUserLastActivity
include SourcegraphDecorator
include DiffHelper
+ include CommentAndCloseFlag
skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv]
before_action :apply_diff_view_cookie!, only: [:show]
@@ -22,37 +23,35 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
:coverage_reports,
:terraform_reports,
:accessibility_reports,
- :codequality_reports
+ :codequality_reports,
+ :codequality_mr_diff_reports
]
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: [:show] do
- push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true)
push_frontend_feature_flag(:file_identifier_hash)
push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true)
push_frontend_feature_flag(:merge_request_widget_graphql, @project)
push_frontend_feature_flag(:drag_comment_selection, @project, default_enabled: true)
push_frontend_feature_flag(:unified_diff_components, @project, default_enabled: true)
- push_frontend_feature_flag(:default_merge_ref_for_diffs, @project)
- push_frontend_feature_flag(:core_security_mr_widget, @project, default_enabled: true)
+ 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(:core_security_mr_widget_downloads, @project, default_enabled: true)
push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true)
push_frontend_feature_flag(:diffs_gradual_load, @project, default_enabled: true)
- push_frontend_feature_flag(:codequality_mr_diff, @project)
- push_frontend_feature_flag(:suggestions_custom_commit, @project)
+ push_frontend_feature_flag(:codequality_backend_comparison, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:suggestions_custom_commit, @project, default_enabled: true)
+ push_frontend_feature_flag(:local_file_reviews, default_enabled: :yaml)
+ push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, @project, type: :development, default_enabled: :yaml)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)
end
before_action do
- push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
- push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true)
push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
- push_frontend_feature_flag(:reviewer_approval_rules, @project, default_enabled: :yaml)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
@@ -68,7 +67,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
:toggle_award_emoji, :toggle_subscription, :update
]
- feature_category :code_testing, [:test_reports, :coverage_reports]
+ feature_category :code_testing, [:test_reports, :coverage_reports, :codequality_mr_diff_reports]
feature_category :accessibility_testing, [:accessibility_reports]
feature_category :infrastructure_as_code, [:terraform_reports]
@@ -168,6 +167,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
}
end
+ def sast_reports
+ reports_response(merge_request.compare_sast_reports(current_user), head_pipeline)
+ end
+
+ def secret_detection_reports
+ reports_response(merge_request.compare_secret_detection_reports(current_user), head_pipeline)
+ end
+
def context_commits
return render_404 unless project.context_commits_enabled?
@@ -197,6 +204,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
end
+ def codequality_mr_diff_reports
+ reports_response(@merge_request.find_codequality_mr_diff_reports)
+ end
+
def codequality_reports
reports_response(@merge_request.compare_codequality_reports)
end
@@ -491,7 +502,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
params = request.query_parameters
params[:view] = "inline"
- if Feature.enabled?(:default_merge_ref_for_diffs, project)
+ if Feature.enabled?(:default_merge_ref_for_diffs, project, default_enabled: :yaml)
params = params.merge(diff_head: true)
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 77fd7688caf..71a93701dc4 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -10,6 +10,7 @@ class Projects::NotesController < Projects::ApplicationController
before_action :authorize_read_note!
before_action :authorize_create_note!, only: [:create]
before_action :authorize_resolve_note!, only: [:resolve, :unresolve]
+ before_action :create_rate_limit, only: [:create]
feature_category :issue_tracking
@@ -90,4 +91,20 @@ class Projects::NotesController < Projects::ApplicationController
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42383')
end
+
+ def create_rate_limit
+ key = :notes_create
+ return unless rate_limiter.throttled?(key, scope: [current_user], users_allowlist: rate_limit_users_allowlist)
+
+ rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
+ render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
+ end
+
+ def rate_limiter
+ ::Gitlab::ApplicationRateLimiter
+ end
+
+ def rate_limit_users_allowlist
+ Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
+ end
end
diff --git a/app/controllers/projects/pipelines/tests_controller.rb b/app/controllers/projects/pipelines/tests_controller.rb
index 924d52898ea..1702783b10f 100644
--- a/app/controllers/projects/pipelines/tests_controller.rb
+++ b/app/controllers/projects/pipelines/tests_controller.rb
@@ -42,9 +42,13 @@ module Projects
end
def test_suite
- builds.map do |build|
+ suite = builds.map do |build|
build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new)
end.sum
+
+ Gitlab::Ci::Reports::TestFailureHistory.new(suite.failed.values, project).load!
+
+ suite
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index ae8b3d9b51d..59b14bbb91d 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -13,15 +13,14 @@ 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 do
- push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true)
push_frontend_feature_flag(:pipelines_security_report_summary, project)
push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true)
- push_frontend_feature_flag(:graphql_pipeline_header, project, type: :development, default_enabled: false)
- push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: false)
- push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development, default_enabled: true)
+ push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml)
+ push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
+ push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, project, type: :development, default_enabled: :yaml)
+ push_frontend_feature_flag(:jira_for_vulnerabilities, project, type: :development, default_enabled: :yaml)
end
before_action :ensure_pipeline, only: [:show]
- before_action :push_experiment_to_gon, only: :index, if: :html_request?
# Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596
before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? }
@@ -46,11 +45,7 @@ class Projects::PipelinesController < Projects::ApplicationController
@pipelines_count = limited_pipelines_count(project)
respond_to do |format|
- format.html do
- record_empty_pipeline_experiment
-
- render :index
- end
+ format.html
format.json do
Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL)
@@ -301,20 +296,6 @@ class Projects::PipelinesController < Projects::ApplicationController
def index_params
params.permit(:scope, :username, :ref, :status)
end
-
- def record_empty_pipeline_experiment
- return unless @pipelines_count.to_i == 0
- return if helpers.has_gitlab_ci?(@project)
-
- record_experiment_user(:pipelines_empty_state)
- end
-
- def push_experiment_to_gon
- return unless current_user
-
- push_frontend_experiment(:pipelines_empty_state, subject: current_user)
- frontend_experimentation_tracking_data(:pipelines_empty_state, 'view', project.namespace_id, subject: current_user)
- end
end
Projects::PipelinesController.prepend_if_ee('EE::Projects::PipelinesController')
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index 5972b29a298..a7c7839dc9f 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -8,6 +8,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController
# Authorize
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
+ before_action do
+ push_frontend_feature_flag(:vue_project_members_list, @project, default_enabled: :yaml)
+ end
+
feature_category :authentication_and_authorization
def index
diff --git a/app/controllers/projects/security/configuration_controller.rb b/app/controllers/projects/security/configuration_controller.rb
new file mode 100644
index 00000000000..9366ca7b0ed
--- /dev/null
+++ b/app/controllers/projects/security/configuration_controller.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Projects
+ module Security
+ class ConfigurationController < Projects::ApplicationController
+ feature_category :static_application_security_testing
+
+ def show
+ return render_404 unless feature_enabled?
+
+ render_403 unless can?(current_user, :read_security_configuration, project)
+ end
+
+ private
+
+ def feature_enabled?
+ ::Feature.enabled?(:secure_security_and_compliance_configuration_page_on_ce, @project, default_enabled: :yaml)
+ end
+ end
+ end
+end
+
+Projects::Security::ConfigurationController.prepend_if_ee('EE::Projects::Security::ConfigurationController')
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 6ed9f74297d..b5c73f29784 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -14,7 +14,7 @@ class Projects::ServicesController < Projects::ApplicationController
before_action only: :edit do
push_frontend_feature_flag(:jira_issues_integration, @project, type: :licensed, default_enabled: true)
push_frontend_feature_flag(:jira_vulnerabilities_integration, @project, type: :licensed, default_enabled: true)
- push_frontend_feature_flag(:jira_for_vulnerabilities, @project, type: :development, default_enabled: false)
+ push_frontend_feature_flag(:jira_for_vulnerabilities, @project, type: :development, 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 31533dfeea0..34b11c456b9 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -144,8 +144,8 @@ module Projects
def define_badges_variables
@ref = params[:ref] || @project.default_branch || 'master'
- @badges = [Gitlab::Badge::Pipeline::Status,
- Gitlab::Badge::Coverage::Report]
+ @badges = [Gitlab::Ci::Badge::Pipeline::Status,
+ Gitlab::Ci::Badge::Coverage::Report]
@badges.map! do |badge|
badge.new(@project, @ref).metadata
diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb
index dd50ab1bc7a..821560e32ba 100644
--- a/app/controllers/projects/settings/repository_controller.rb
+++ b/app/controllers/projects/settings/repository_controller.rb
@@ -7,7 +7,6 @@ module Projects
before_action :define_variables, only: [:create_deploy_token]
before_action do
push_frontend_feature_flag(:ajax_new_deploy_token, @project)
- push_frontend_feature_flag(:deploy_keys_on_protected_branches, @project)
end
feature_category :source_code_management, [:show, :cleanup]
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index f4726638777..ab05c9694fd 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -24,10 +24,8 @@ class Projects::TemplatesController < Projects::ApplicationController
end
def names
- templates = @template_type.dropdown_names(project)
-
respond_to do |format|
- format.json { render json: templates }
+ format.json { render json: TemplateFinder.all_template_names_array(project, params[:template_type].to_s.pluralize) }
end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 0c40478d877..ebffb62cff3 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -14,7 +14,7 @@ class ProjectsController < Projects::ApplicationController
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
- before_action :whitelist_query_limiting, only: [:create]
+ before_action :whitelist_query_limiting, only: [:show, :create]
before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve, :unfoldered_environment_names]
before_action :redirect_git_extension, only: [:show]
before_action :project, except: [:index, :new, :create, :resolve]
@@ -31,8 +31,11 @@ class ProjectsController < Projects::ApplicationController
# Project Export Rate Limit
before_action :export_rate_limit, only: [:export, :download_export, :generate_new_export]
+ before_action do
+ push_frontend_feature_flag(:vue_notification_dropdown, @project, default_enabled: :yaml)
+ end
+
before_action only: [:edit] do
- push_frontend_feature_flag(:approval_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:allow_editing_commit_messages, @project)
end
@@ -71,6 +74,7 @@ class ProjectsController < Projects::ApplicationController
@project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute
if @project.saved?
+ experiment(:new_project_readme, actor: current_user).track(:created, property: active_new_project_tab)
redirect_to(
project_path(@project, custom_import_params),
notice: _("Project '%{project_name}' was successfully created.") % { project_name: @project.name }
@@ -392,6 +396,14 @@ class ProjectsController < Projects::ApplicationController
]
end
+ def project_setting_attributes
+ %i[
+ show_default_award_emojis
+ squash_option
+ allow_editing_commit_messages
+ ]
+ end
+
def project_params_attributes
[
:allow_merge_on_skipped_pipeline,
@@ -429,11 +441,7 @@ class ProjectsController < Projects::ApplicationController
:suggestion_commit_message,
:packages_enabled,
:service_desk_enabled,
- project_setting_attributes: %i[
- show_default_award_emojis
- squash_option
- allow_editing_commit_messages
- ]
+ project_setting_attributes: project_setting_attributes
] + [project_feature_attributes: project_feature_attributes]
end
@@ -493,17 +501,19 @@ class ProjectsController < Projects::ApplicationController
render_404 unless Gitlab::CurrentSettings.project_export_enabled?
end
+ # Redirect from localhost/group/project.git to localhost/group/project
def redirect_git_extension
- # Redirect from
- # localhost/group/project.git
- # to
- # localhost/group/project
- #
- redirect_to request.original_url.sub(%r{\.git/?\Z}, '') if params[:format] == 'git'
+ return unless params[:format] == 'git'
+
+ # `project` calls `find_routable!`, so this will trigger the usual not-found
+ # behaviour when the user isn't authorized to see the project
+ return unless project
+
+ redirect_to(request.original_url.sub(%r{\.git/?\Z}, ''))
end
def whitelist_query_limiting
- Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42440')
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/20826')
end
def present_project
diff --git a/app/controllers/registrations/experience_levels_controller.rb b/app/controllers/registrations/experience_levels_controller.rb
index 23126983eb5..b6ed0366177 100644
--- a/app/controllers/registrations/experience_levels_controller.rb
+++ b/app/controllers/registrations/experience_levels_controller.rb
@@ -2,9 +2,8 @@
module Registrations
class ExperienceLevelsController < ApplicationController
- layout 'devise_experimental_onboarding_issues'
+ layout 'signup_onboarding'
- before_action :check_experiment_enabled
before_action :ensure_namespace_path_param
feature_category :navigation
@@ -14,9 +13,8 @@ module Registrations
if current_user.save
hide_advanced_issues
- record_experiment_user(:default_to_issues_board)
- if experiment_enabled?(:default_to_issues_board) && learn_gitlab.available?
+ if learn_gitlab.available?
redirect_to namespace_project_board_path(params[:namespace_path], learn_gitlab.project, learn_gitlab.board)
else
redirect_to group_path(params[:namespace_path])
@@ -28,10 +26,6 @@ module Registrations
private
- def check_experiment_enabled
- access_denied! unless experiment_enabled?(:onboarding_issues)
- end
-
def ensure_namespace_path_param
redirect_to root_path unless params[:namespace_path].present?
end
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 4a6fef56ef5..a1a6a057171 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -16,9 +16,7 @@ module Registrations
result = ::Users::SignupService.new(current_user, update_params).execute
if result[:status] == :success
- process_gitlab_com_tracking
-
- return redirect_to new_users_sign_up_group_path if experiment_enabled?(:onboarding_issues) && show_onboarding_issues_experiment?
+ return redirect_to new_users_sign_up_group_path if show_signup_onboarding?
redirect_to path_for_signed_in_user(current_user)
else
@@ -36,14 +34,6 @@ module Registrations
current_user.role.present? && !current_user.setup_for_company.nil?
end
- def process_gitlab_com_tracking
- return false unless ::Gitlab.com?
- return false unless show_onboarding_issues_experiment?
-
- track_experiment_event(:onboarding_issues, 'signed_up')
- record_experiment_user(:onboarding_issues)
- end
-
def update_params
params.require(:user).permit(:role, :other_role, :setup_for_company)
end
@@ -61,11 +51,8 @@ module Registrations
stored_location_for(user) || dashboard_projects_path
end
- def show_onboarding_issues_experiment?
- !helpers.in_subscription_flow? &&
- !helpers.in_invitation_flow? &&
- !helpers.in_oauth_flow? &&
- !helpers.in_trial_flow?
+ def show_signup_onboarding?
+ false
end
end
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index e7872eeac27..44c08863dd6 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -31,6 +31,8 @@ class RegistrationsController < Devise::RegistrationsController
NotificationService.new.new_instance_access_request(new_user)
end
+ after_request_hook(new_user)
+
yield new_user if block_given?
end
@@ -85,6 +87,10 @@ class RegistrationsController < Devise::RegistrationsController
super
end
+ def after_request_hook(user)
+ # overridden by EE module
+ end
+
def after_sign_up_path_for(user)
Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?))
diff --git a/app/controllers/repositories/git_http_controller.rb b/app/controllers/repositories/git_http_controller.rb
index 3cf0a23b7f6..9ad700404ff 100644
--- a/app/controllers/repositories/git_http_controller.rb
+++ b/app/controllers/repositories/git_http_controller.rb
@@ -78,6 +78,8 @@ module Repositories
def update_fetch_statistics
return unless project
return if Gitlab::Database.read_only?
+ return if Feature.enabled?(:disable_git_http_fetch_writes)
+
return unless repo_type.project?
OnboardingProgressService.new(project.namespace).execute(action: :git_read)
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 196b1887ca7..820b00a902e 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -5,11 +5,11 @@ class SearchController < ApplicationController
include SearchHelper
include RedisTracking
- track_redis_hll_event :show, name: 'i_search_total', feature: :search_track_unique_users, feature_default_enabled: true
+ track_redis_hll_event :show, name: 'i_search_total'
around_action :allow_gitaly_ref_name_caching
- before_action :block_anonymous_global_searches
+ before_action :block_anonymous_global_searches, except: :opensearch
skip_before_action :authenticate_user!
requires_cross_project_access if: -> do
search_term_present = params[:search].present? || params[:term].present?
@@ -67,6 +67,9 @@ class SearchController < ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
+ def opensearch
+ end
+
private
# overridden in EE
diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb
index 8532257cb8d..8a4e8edbf3c 100644
--- a/app/controllers/snippets/notes_controller.rb
+++ b/app/controllers/snippets/notes_controller.rb
@@ -23,7 +23,7 @@ class Snippets::NotesController < ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def snippet
- PersonalSnippet.find_by(id: params[:snippet_id])
+ @snippet ||= PersonalSnippet.find_by(id: params[:snippet_id])
end
# rubocop: enable CodeReuse/ActiveRecord
alias_method :noteable, :snippet
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 62208d838c1..54d97f588fc 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class UsersController < ApplicationController
+ include InternalRedirect
include RoutableActions
include RendersMemberAccess
include RendersProjectsList
@@ -13,13 +14,15 @@ class UsersController < ApplicationController
contributed: false,
snippets: true,
calendar: false,
+ followers: false,
+ following: false,
calendar_activities: true
skip_before_action :authenticate_user!
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
- before_action :user, except: [:exists, :suggests]
+ before_action :user, except: [:exists, :suggests, :ssh_keys]
before_action :authorize_read_user_profile!,
- only: [:calendar, :calendar_activities, :groups, :projects, :contributed, :starred, :snippets]
+ only: [:calendar, :calendar_activities, :groups, :projects, :contributed, :starred, :snippets, :followers, :following]
feature_category :users
@@ -41,7 +44,12 @@ class UsersController < ApplicationController
# Get all keys of a user(params[:username]) in a text format
# Helpful for sysadmins to put in respective servers
+ #
+ # Uses `UserFinder` rather than `find_routable!` because this endpoint should
+ # be publicly available regardless of instance visibility settings.
def ssh_keys
+ user = UserFinder.new(params[:username]).find_by_username
+
render plain: user.all_ssh_keys.join("\n")
end
@@ -92,6 +100,18 @@ class UsersController < ApplicationController
present_projects(@starred_projects)
end
+ def followers
+ @user_followers = user.followers.page(params[:page])
+
+ present_users(@user_followers)
+ end
+
+ def following
+ @user_following = user.followees.page(params[:page])
+
+ present_users(@user_following)
+ end
+
def present_projects(projects)
skip_pagination = Gitlab::Utils.to_boolean(params[:skip_pagination])
skip_namespace = Gitlab::Utils.to_boolean(params[:skip_namespace])
@@ -141,6 +161,22 @@ class UsersController < ApplicationController
render json: { exists: exists, suggests: suggestions }
end
+ def follow
+ current_user.follow(user)
+
+ redirect_path = referer_path(request) || @user
+
+ redirect_to redirect_path
+ end
+
+ def unfollow
+ current_user.unfollow(user)
+
+ redirect_path = referer_path(request) || @user
+
+ redirect_to redirect_path
+ end
+
private
def user
@@ -164,7 +200,7 @@ class UsersController < ApplicationController
end
def load_events
- @events = UserRecentEventsFinder.new(current_user, user, params).execute
+ @events = UserRecentEventsFinder.new(current_user, user, nil, params).execute
Events::RenderService.new(current_user).execute(@events, atom_request: request.format.atom?)
end
@@ -211,6 +247,17 @@ class UsersController < ApplicationController
def authorize_read_user_profile!
access_denied! unless can?(current_user, :read_user_profile, user)
end
+
+ def present_users(users)
+ respond_to do |format|
+ format.html { render 'show' }
+ format.json do
+ render json: {
+ html: view_to_html_string("shared/users/index", users: users)
+ }
+ end
+ end
+ end
end
UsersController.prepend_if_ee('EE::UsersController')
diff --git a/app/controllers/whats_new_controller.rb b/app/controllers/whats_new_controller.rb
index cba86c65848..12a52f30bd0 100644
--- a/app/controllers/whats_new_controller.rb
+++ b/app/controllers/whats_new_controller.rb
@@ -5,7 +5,6 @@ class WhatsNewController < ApplicationController
skip_before_action :authenticate_user!
- before_action :check_feature_flag
before_action :check_valid_page_param, :set_pagination_headers, unless: -> { has_version_param? }
feature_category :navigation
@@ -13,17 +12,13 @@ class WhatsNewController < ApplicationController
def index
respond_to do |format|
format.js do
- render json: highlight_items
+ render json: highlights.items
end
end
end
private
- def check_feature_flag
- render_404 unless Feature.enabled?(:whats_new_drawer, current_user)
- end
-
def check_valid_page_param
render_404 if current_page < 1
end
@@ -42,10 +37,6 @@ class WhatsNewController < ApplicationController
end
end
- def highlight_items
- highlights.map {|item| Gitlab::WhatsNew::ItemPresenter.present(item) }
- end
-
def set_pagination_headers
response.set_header('X-Next-Page', highlights.next_page)
end
diff --git a/app/experiments/application_experiment.rb b/app/experiments/application_experiment.rb
index 7a8851d11ce..317514d088b 100644
--- a/app/experiments/application_experiment.rb
+++ b/app/experiments/application_experiment.rb
@@ -1,13 +1,20 @@
# frozen_string_literal: true
-class ApplicationExperiment < Gitlab::Experiment
+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're in an environment that allows experiments
+
+ Feature.get(feature_flag_name).state != :off # rubocop:disable Gitlab/AvoidFeatureGet
+ end
+
def publish(_result)
track(:assignment) # track that we've assigned a variant for this context
Gon.global.push({ experiment: { name => signature } }, true) # push to client
end
def track(action, **event_args)
- return if excluded? # no events for opted out actors or excluded subjects
+ return unless should_track? # no events for opted out actors or excluded subjects
Gitlab::Tracking.event(name, action.to_s, **event_args.merge(
context: (event_args[:context] || []) << SnowplowTracker::SelfDescribingJson.new(
@@ -16,10 +23,39 @@ class ApplicationExperiment < Gitlab::Experiment
))
end
+ def rollout_strategy
+ # no-op override in inherited class as desired
+ end
+
+ def variants
+ # override as desired in inherited class with all variants + control
+ # %i[variant1 variant2 control]
+ #
+ # this will make sure we supply variants as these go together - rollout_strategy of :round_robin must have variants
+ raise NotImplementedError, "Inheriting class must supply variants as an array if :round_robin strategy is used" if rollout_strategy == :round_robin
+ end
+
private
+ def feature_flag_name
+ name.tr('/', '_')
+ end
+
def resolve_variant_name
- return variant_names.first if Feature.enabled?(name, self, type: :experiment)
+ case rollout_strategy
+ when :round_robin
+ round_robin_rollout
+ else
+ percentage_rollout
+ end
+ end
+
+ def round_robin_rollout
+ Strategy::RoundRobin.new(feature_flag_name, variants).execute
+ end
+
+ def percentage_rollout
+ return variant_names.first if Feature.enabled?(feature_flag_name, self, type: :experiment, default_enabled: :yaml)
nil # Returning nil vs. :control is important for not caching and rollouts.
end
@@ -41,7 +77,7 @@ class ApplicationExperiment < Gitlab::Experiment
# default cache key strategy. So running `cache.fetch("foo:bar", "value")`
# would create/update a hash with the key of "foo", with a field named
# "bar" that has "value" assigned to it.
- class Cache < ActiveSupport::Cache::Store
+ class Cache < ActiveSupport::Cache::Store # rubocop:disable Gitlab/NamespacedClass
# Clears the entire cache for a given experiment. Be careful with this
# since it would reset all resolved variants for the entire experiment.
def clear(key:)
@@ -72,7 +108,6 @@ class ApplicationExperiment < Gitlab::Experiment
end
def write_entry(key, entry, **options)
- return false unless Feature.enabled?(:caching_experiments)
return false if entry.value.blank? # don't cache any empty values
pool { |redis| redis.hset(*hkey(key), entry.value) }
diff --git a/app/experiments/members/invite_email_experiment.rb b/app/experiments/members/invite_email_experiment.rb
new file mode 100644
index 00000000000..4a03ebb7726
--- /dev/null
+++ b/app/experiments/members/invite_email_experiment.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Members
+ class InviteEmailExperiment < ApplicationExperiment
+ exclude { context.actor.created_by.blank? }
+ exclude { context.actor.created_by.avatar_url.nil? }
+
+ INVITE_TYPE = 'initial_email'
+
+ def rollout_strategy
+ :round_robin
+ end
+
+ def variants
+ %i[avatar permission_info control]
+ end
+ end
+end
diff --git a/app/experiments/new_project_readme_experiment.rb b/app/experiments/new_project_readme_experiment.rb
new file mode 100644
index 00000000000..8f88ad2adc1
--- /dev/null
+++ b/app/experiments/new_project_readme_experiment.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+class NewProjectReadmeExperiment < ApplicationExperiment # rubocop:disable Gitlab/NamespacedClass
+ include Gitlab::Git::WrapsGitalyErrors
+
+ INITIAL_WRITE_LIMIT = 3
+ EXPERIMENT_START_DATE = DateTime.parse('2021/1/20')
+ MAX_ACCOUNT_AGE = 7.days
+
+ exclude { context.value[:actor].nil? }
+ exclude { context.actor.created_at < MAX_ACCOUNT_AGE.ago }
+
+ def control_behavior
+ false # we don't want the checkbox to be checked
+ end
+
+ def candidate_behavior
+ true # check the checkbox by default
+ end
+
+ def track_initial_writes(project)
+ return unless should_track? # early return if we don't need to ask for commit counts
+ return unless project.created_at > EXPERIMENT_START_DATE # early return for older projects
+ return unless (commit_count = commit_count_for(project)) < INITIAL_WRITE_LIMIT
+
+ track(:write, property: project.created_at.to_s, value: commit_count)
+ end
+
+ private
+
+ def commit_count_for(project)
+ raw_repo = project.repository&.raw_repository
+ return INITIAL_WRITE_LIMIT unless raw_repo&.root_ref
+
+ begin
+ Gitlab::GitalyClient::CommitService.new(raw_repo).commit_count(raw_repo.root_ref, {
+ all: true, # include all branches
+ max_count: INITIAL_WRITE_LIMIT # limit as an optimization
+ })
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e, experiment: name)
+ INITIAL_WRITE_LIMIT
+ end
+ end
+end
diff --git a/app/experiments/strategy/round_robin.rb b/app/experiments/strategy/round_robin.rb
new file mode 100644
index 00000000000..7b80c0e984d
--- /dev/null
+++ b/app/experiments/strategy/round_robin.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Strategy
+ class RoundRobin
+ CacheError = Class.new(StandardError)
+
+ COUNTER_EXPIRE_TIME = 86400 # one day
+
+ def initialize(key, variants)
+ @key = key
+ @variants = variants
+ end
+
+ def execute
+ increment_counter
+ resolve_variant_name
+ end
+
+ # When the counter would expire
+ #
+ # @api private Used internally by SRE and debugging purpose
+ # @return [Integer] Number in seconds until expiration or false if never
+ def counter_expires_in
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.ttl(key)
+ end
+ end
+
+ # Return the actual counter value
+ #
+ # @return [Integer] value
+ def counter_value
+ Gitlab::Redis::SharedState.with do |redis|
+ (redis.get(key) || 0).to_i
+ end
+ end
+
+ # Reset the counter
+ #
+ # @private Used internally by SRE and debugging purpose
+ # @return [Boolean] whether reset was a success
+ def reset!
+ redis_cmd do |redis|
+ redis.del(key)
+ end
+ end
+
+ private
+
+ attr_reader :key, :variants
+
+ # Increase the counter
+ #
+ # @return [Boolean] whether operation was a success
+ def increment_counter
+ redis_cmd do |redis|
+ redis.incr(key)
+ redis.expire(key, COUNTER_EXPIRE_TIME)
+ end
+ end
+
+ def resolve_variant_name
+ remainder = counter_value % variants.size
+
+ variants[remainder]
+ end
+
+ def redis_cmd
+ Gitlab::Redis::SharedState.with { |redis| yield(redis) }
+
+ true
+ rescue CacheError => e
+ Gitlab::AppLogger.warn("GitLab: An unexpected error occurred in writing to Redis: #{e}")
+
+ false
+ end
+ end
+end
diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb
index 8dc3c2320ed..ff5d9ea7d19 100644
--- a/app/finders/autocomplete/users_finder.rb
+++ b/app/finders/autocomplete/users_finder.rb
@@ -38,7 +38,9 @@ module Autocomplete
end
end
- items.uniq
+ items.uniq.tap do |unique_items|
+ preload_associations(unique_items)
+ end
end
private
@@ -91,6 +93,12 @@ module Autocomplete
User.none
end
end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def preload_associations(items)
+ ActiveRecord::Associations::Preloader.new.preload(items, :status)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/finders/ci/jobs_finder.rb b/app/finders/ci/jobs_finder.rb
index 78791d737da..4408c9cdb6d 100644
--- a/app/finders/ci/jobs_finder.rb
+++ b/app/finders/ci/jobs_finder.rb
@@ -45,11 +45,12 @@ module Ci
return unless pipeline
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_build, pipeline)
- jobs_by_type(pipeline, type).latest
+ jobs_scope = jobs_by_type(pipeline, type)
+ params[:include_retried] ? jobs_scope : jobs_scope.latest
end
def filter_by_scope(builds)
- return filter_by_statuses!(params[:scope], builds) if params[:scope].is_a?(Array)
+ return filter_by_statuses!(builds) if params[:scope].is_a?(Array)
case params[:scope]
when 'pending'
@@ -63,7 +64,7 @@ module Ci
end
end
- def filter_by_statuses!(statuses, builds)
+ def filter_by_statuses!(builds)
unknown_statuses = params[:scope] - ::CommitStatus::AVAILABLE_STATUSES
raise ArgumentError, 'Scope contains invalid value(s)' unless unknown_statuses.empty?
diff --git a/app/finders/ci/testing/daily_build_group_report_results_finder.rb b/app/finders/ci/testing/daily_build_group_report_results_finder.rb
new file mode 100644
index 00000000000..70d9e55dc47
--- /dev/null
+++ b/app/finders/ci/testing/daily_build_group_report_results_finder.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+# DailyBuildGroupReportResultsFinder
+#
+# Used to filter DailyBuildGroupReportResults by set of params
+#
+# Arguments:
+# current_user
+# params:
+# project: integer
+# group: integer
+# coverage: boolean
+# ref_path: string
+# start_date: date
+# end_date: date
+# sort: boolean
+# limit: integer
+
+module Ci
+ module Testing
+ class DailyBuildGroupReportResultsFinder
+ include Gitlab::Allowable
+
+ MAX_ITEMS = 1_000
+
+ attr_reader :params, :current_user
+
+ def initialize(params: {}, current_user: nil)
+ @params = params
+ @current_user = current_user
+ end
+
+ def execute
+ return Ci::DailyBuildGroupReportResult.none unless query_allowed?
+
+ collection = Ci::DailyBuildGroupReportResult.by_projects(params[:project])
+ collection = filter_report_results(collection)
+ collection
+ end
+
+ private
+
+ def query_allowed?
+ can?(current_user, :read_build_report_results, params[:project])
+ end
+
+ def filter_report_results(collection)
+ collection = by_coverage(collection)
+ collection = by_ref_path(collection)
+ collection = by_dates(collection)
+
+ collection = sort(collection)
+ collection = limit_by(collection)
+ collection
+ end
+
+ def by_coverage(items)
+ params[:coverage].present? ? items.with_coverage : items
+ end
+
+ def by_ref_path(items)
+ params[:ref_path].present? ? items.by_ref_path(params[:ref_path]) : items.with_default_branch
+ end
+
+ def by_dates(items)
+ params[:start_date].present? && params[:end_date].present? ? items.by_dates(params[:start_date], params[:end_date]) : items
+ end
+
+ def sort(items)
+ params[:sort].present? ? items.ordered_by_date_and_group_name : items
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def limit_by(items)
+ items.limit(limit)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def limit
+ return MAX_ITEMS unless params[:limit].present?
+
+ [params[:limit].to_i, MAX_ITEMS].min
+ end
+ end
+ end
+end
+
+Ci::Testing::DailyBuildGroupReportResultsFinder.prepend_if_ee('::EE::Ci::Testing::DailyBuildGroupReportResultsFinder')
diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb
index 524e7aa7ff9..30bc0ff7909 100644
--- a/app/finders/concerns/packages/finder_helper.rb
+++ b/app/finders/concerns/packages/finder_helper.rb
@@ -4,6 +4,9 @@ module Packages
module FinderHelper
extend ActiveSupport::Concern
+ InvalidPackageTypeError = Class.new(StandardError)
+ InvalidStatusError = Class.new(StandardError)
+
private
def packages_visible_to_user(user, within_group:)
@@ -25,5 +28,35 @@ module Packages
::Project.in_namespace(namespace_ids)
.public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
end
+
+ def package_type
+ params[:package_type].presence
+ end
+
+ def filter_by_package_type(packages)
+ return packages unless package_type
+ raise InvalidPackageTypeError unless ::Packages::Package.package_types.key?(package_type)
+
+ packages.with_package_type(package_type)
+ end
+
+ def filter_by_package_name(packages)
+ return packages unless params[:package_name].present?
+
+ packages.search_by_name(params[:package_name])
+ end
+
+ def filter_with_version(packages)
+ return packages if params[:include_versionless].present?
+
+ packages.has_version
+ end
+
+ def filter_by_status(packages)
+ return packages.displayable unless params[:status].present?
+ raise InvalidStatusError unless Package.statuses.key?(params[:status])
+
+ packages.with_status(params[:status])
+ end
end
end
diff --git a/app/finders/container_repositories_finder.rb b/app/finders/container_repositories_finder.rb
index 5109efb361b..14e4d6799d8 100644
--- a/app/finders/container_repositories_finder.rb
+++ b/app/finders/container_repositories_finder.rb
@@ -14,7 +14,8 @@ class ContainerRepositoriesFinder
return unless authorized?
repositories = @subject.is_a?(Project) ? project_repositories : group_repositories
- filter_by_image_name(repositories)
+ repositories = filter_by_image_name(repositories)
+ sort(repositories)
end
private
@@ -39,6 +40,12 @@ class ContainerRepositoriesFinder
repositories.search_by_name(@params[:name])
end
+ def sort(repositories)
+ return repositories unless @params[:sort]
+
+ repositories.order_by(@params[:sort])
+ end
+
def authorized?
Ability.allowed?(@user, :read_container_image, @subject)
end
diff --git a/app/finders/deployments_finder.rb b/app/finders/deployments_finder.rb
index 4038f93cf2d..89a28d9dfb8 100644
--- a/app/finders/deployments_finder.rb
+++ b/app/finders/deployments_finder.rb
@@ -1,57 +1,56 @@
# frozen_string_literal: true
+# WARNING: This finder does not check permissions!
+#
+# Arguments:
+# params:
+# project: Project model - Find deployments for this project
+# updated_after: DateTime
+# updated_before: DateTime
+# finished_after: DateTime
+# finished_before: DateTime
+# environment: String
+# status: String (see Deployment.statuses)
+# order_by: String (see ALLOWED_SORT_VALUES constant)
+# sort: String (asc | desc)
class DeploymentsFinder
- attr_reader :project, :params
+ attr_reader :params
- ALLOWED_SORT_VALUES = %w[id iid created_at updated_at ref].freeze
+ ALLOWED_SORT_VALUES = %w[id iid created_at updated_at ref finished_at].freeze
DEFAULT_SORT_VALUE = 'id'
ALLOWED_SORT_DIRECTIONS = %w[asc desc].freeze
DEFAULT_SORT_DIRECTION = 'asc'
- def initialize(project, params = {})
- @project = project
+ def initialize(params = {})
@params = params
end
def execute
items = init_collection
items = by_updated_at(items)
+ items = by_finished_at(items)
items = by_environment(items)
items = by_status(items)
- sort(items)
+ items = preload_associations(items)
+ items = sort(items)
+
+ items
end
private
- # rubocop: disable CodeReuse/ActiveRecord
def init_collection
- project
- .deployments
- .includes(
- :user,
- environment: [],
- deployable: {
- job_artifacts: [],
- pipeline: {
- project: {
- route: [],
- namespace: :route
- }
- },
- project: {
- namespace: :route
- }
- }
- )
+ if params[:project]
+ params[:project].deployments
+ else
+ Deployment.none
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def sort(items)
- items.order(sort_params)
+ items.order(sort_params) # rubocop: disable CodeReuse/ActiveRecord
end
- # rubocop: enable CodeReuse/ActiveRecord
def by_updated_at(items)
items = items.updated_before(params[:updated_before]) if params[:updated_before].present?
@@ -60,6 +59,13 @@ class DeploymentsFinder
items
end
+ def by_finished_at(items)
+ items = items.finished_before(params[:finished_before]) if params[:finished_before].present?
+ items = items.finished_after(params[:finished_after]) if params[:finished_after].present?
+
+ items
+ end
+
def by_environment(items)
if params[:environment].present?
items.for_environment_name(params[:environment])
@@ -87,4 +93,27 @@ class DeploymentsFinder
sort_values['id'] = sort_values.delete('created_at') if sort_values['created_at'] # Sorting by `id` produces the same result as sorting by `created_at`
end
end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def preload_associations(scope)
+ scope.includes(
+ :user,
+ environment: [],
+ deployable: {
+ job_artifacts: [],
+ pipeline: {
+ project: {
+ route: [],
+ namespace: :route
+ }
+ },
+ project: {
+ namespace: :route
+ }
+ }
+ )
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
+
+DeploymentsFinder.prepend_if_ee('EE::DeploymentsFinder')
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index 4358cf249f7..bedd6891d02 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -100,6 +100,10 @@ class LabelsFinder < UnionFinder
strong_memoize(:group_ids) do
groups = groups_to_include(group)
+ # Because we are sure that all groups are in the same hierarchy tree
+ # we can preset root group for all of them to optimize permission checks
+ Group.preset_root_ancestor_for(groups)
+
groups_user_can_read_labels(groups).map(&:id)
end
end
@@ -173,7 +177,7 @@ class LabelsFinder < UnionFinder
end
if group?
- @projects = if params[:include_subgroups]
+ @projects = if params[:include_descendant_groups]
@projects.in_namespace(group.self_and_descendants.select(:id))
else
@projects.in_namespace(group.id)
diff --git a/app/finders/license_template_finder.rb b/app/finders/license_template_finder.rb
index 4d68b963dc3..c4cb33235af 100644
--- a/app/finders/license_template_finder.rb
+++ b/app/finders/license_template_finder.rb
@@ -28,6 +28,10 @@ class LicenseTemplateFinder
end
end
+ def template_names
+ ::Gitlab::Template::BaseTemplate.template_names_by_category(vendored_licenses)
+ end
+
private
def vendored_licenses
@@ -36,6 +40,7 @@ class LicenseTemplateFinder
LicenseTemplate.new(
key: license.key,
name: license.name,
+ project: project,
nickname: license.nickname,
category: (license.featured? ? :Popular : :Other),
content: license.content,
diff --git a/app/finders/merge_request/metrics_finder.rb b/app/finders/merge_request/metrics_finder.rb
new file mode 100644
index 00000000000..d93e53d1636
--- /dev/null
+++ b/app/finders/merge_request/metrics_finder.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+class MergeRequest::MetricsFinder
+ include Gitlab::Allowable
+
+ def initialize(current_user, params = {})
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return klass.none if target_project.blank? || user_not_authorized?
+
+ items = init_collection
+ items = by_target_project(items)
+ items = by_merged_after(items)
+ items = by_merged_before(items)
+
+ items
+ end
+
+ private
+
+ attr_reader :current_user, :params
+
+ def by_target_project(items)
+ items.by_target_project(target_project)
+ end
+
+ def by_merged_after(items)
+ return items unless merged_after
+
+ items.merged_after(merged_after)
+ end
+
+ def by_merged_before(items)
+ return items unless merged_before
+
+ items.merged_before(merged_before)
+ end
+
+ def user_not_authorized?
+ !can?(current_user, :read_merge_request, target_project)
+ end
+
+ def init_collection
+ klass.all
+ end
+
+ def klass
+ MergeRequest::Metrics
+ end
+
+ def target_project
+ params[:target_project]
+ end
+
+ def merged_after
+ params[:merged_after]
+ end
+
+ def merged_before
+ params[:merged_before]
+ end
+end
diff --git a/app/finders/merge_requests/oldest_per_commit_finder.rb b/app/finders/merge_requests/oldest_per_commit_finder.rb
new file mode 100644
index 00000000000..f50db43d7d2
--- /dev/null
+++ b/app/finders/merge_requests/oldest_per_commit_finder.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ # OldestPerCommitFinder is used to retrieve the oldest merge requests for
+ # every given commit, grouped per commit SHA.
+ #
+ # This finder is useful when you need to efficiently retrieve the first/oldest
+ # merge requests for multiple commits, and you want to do so in batches;
+ # instead of running a query for every commit.
+ class OldestPerCommitFinder
+ def initialize(project)
+ @project = project
+ end
+
+ # Returns a Hash that maps a commit ID to the oldest merge request that
+ # introduced that commit.
+ def execute(commits)
+ id_rows = MergeRequestDiffCommit
+ .oldest_merge_request_id_per_commit(@project.id, commits.map(&:id))
+
+ mrs = MergeRequest
+ .preload_target_project
+ .id_in(id_rows.map { |r| r[:merge_request_id] })
+ .index_by(&:id)
+
+ id_rows.each_with_object({}) do |row, hash|
+ if (mr = mrs[row[:merge_request_id]])
+ hash[row[:sha]] = mr
+ end
+ end
+ end
+ end
+end
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 860c4068b31..db5161d6e16 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -2,9 +2,7 @@
module Packages
class GroupPackagesFinder
- attr_reader :current_user, :group, :params
-
- InvalidPackageTypeError = Class.new(StandardError)
+ include ::Packages::FinderHelper
def initialize(current_user, group, params = { exclude_subgroups: false, order_by: 'created_at', sort: 'asc' })
@current_user = current_user
@@ -20,6 +18,8 @@ module Packages
private
+ attr_reader :current_user, :group, :params
+
def packages_for_group_projects
packages = ::Packages::Package
.including_build_info
@@ -32,6 +32,7 @@ module Packages
packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
+ packages = filter_by_status(packages)
packages
end
@@ -46,10 +47,6 @@ module Packages
.with_feature_available_for_user(:repository, current_user)
end
- def package_type
- params[:package_type].presence
- end
-
def groups
return [group] if exclude_subgroups?
@@ -59,24 +56,5 @@ module Packages
def exclude_subgroups?
params[:exclude_subgroups]
end
-
- def filter_by_package_type(packages)
- return packages unless package_type
- raise InvalidPackageTypeError unless Package.package_types.key?(package_type)
-
- packages.with_package_type(package_type)
- end
-
- def filter_by_package_name(packages)
- return packages unless params[:package_name].present?
-
- packages.search_by_name(params[:package_name])
- end
-
- def filter_with_version(packages)
- return packages if params[:include_versionless].present?
-
- packages.has_version
- end
end
end
diff --git a/app/finders/packages/nuget/package_finder.rb b/app/finders/packages/nuget/package_finder.rb
index 8f585f045a1..2f66bd145ee 100644
--- a/app/finders/packages/nuget/package_finder.rb
+++ b/app/finders/packages/nuget/package_finder.rb
@@ -5,7 +5,7 @@ module Packages
class PackageFinder
include ::Packages::FinderHelper
- MAX_PACKAGES_COUNT = 50
+ MAX_PACKAGES_COUNT = 300
def initialize(current_user, project_or_group, package_name:, package_version: nil, limit: MAX_PACKAGES_COUNT)
@current_user = current_user
diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb
index 72a63224d2f..bd9e62e3f2a 100644
--- a/app/finders/packages/packages_finder.rb
+++ b/app/finders/packages/packages_finder.rb
@@ -2,7 +2,7 @@
module Packages
class PackagesFinder
- attr_reader :params, :project
+ include ::Packages::FinderHelper
def initialize(project, params = {})
@project = project
@@ -21,29 +21,14 @@ module Packages
packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
+ packages = filter_by_status(packages)
packages = order_packages(packages)
packages
end
private
- def filter_with_version(packages)
- return packages if params[:include_versionless].present?
-
- packages.has_version
- end
-
- def filter_by_package_type(packages)
- return packages unless params[:package_type]
-
- packages.with_package_type(params[:package_type])
- end
-
- def filter_by_package_name(packages)
- return packages unless params[:package_name]
-
- packages.search_by_name(params[:package_name])
- end
+ attr_reader :params, :project
def order_packages(packages)
packages.sort_by_attribute("#{params[:order_by]}_#{params[:sort]}")
diff --git a/app/finders/repositories/commits_with_trailer_finder.rb b/app/finders/repositories/commits_with_trailer_finder.rb
new file mode 100644
index 00000000000..4bd643c345b
--- /dev/null
+++ b/app/finders/repositories/commits_with_trailer_finder.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Repositories
+ # Finder for obtaining commits between two refs, with a Git trailer set.
+ class CommitsWithTrailerFinder
+ # The maximum number of commits to retrieve per page.
+ #
+ # This value is arbitrarily chosen. Lowering it means more Gitaly calls, but
+ # less data being loaded into memory at once. Increasing it has the opposite
+ # effect.
+ #
+ # This amount is based around the number of commits that usually go in a
+ # GitLab release. Some examples for GitLab's own releases:
+ #
+ # * 13.6.0: 4636 commits
+ # * 13.5.0: 5912 commits
+ # * 13.4.0: 5541 commits
+ #
+ # Using this limit should result in most (very large) projects only needing
+ # 5-10 Gitaly calls, while keeping memory usage at a reasonable amount.
+ COMMITS_PER_PAGE = 1024
+
+ # The `project` argument specifies the project for which to obtain the
+ # commits.
+ #
+ # The `from` and `to` arguments specify the range of commits to include. The
+ # commit specified in `from` won't be included itself. The commit specified
+ # in `to` _is_ included.
+ #
+ # The `per_page` argument specifies how many commits are retrieved in a single
+ # Gitaly API call.
+ def initialize(project:, from:, to:, per_page: COMMITS_PER_PAGE)
+ @project = project
+ @from = from
+ @to = to
+ @per_page = per_page
+ end
+
+ # Fetches all commits that have the given trailer set.
+ #
+ # The commits are yielded to the supplied block in batches. This allows
+ # other code to process these commits in batches too, instead of first
+ # having to load all commits into memory.
+ #
+ # Example:
+ #
+ # CommitsWithTrailerFinder.new(...).each_page('Signed-off-by') do |commits|
+ # commits.each do |commit|
+ # ...
+ # end
+ # end
+ def each_page(trailer)
+ return to_enum(__method__, trailer) unless block_given?
+
+ offset = 0
+ response = fetch_commits
+
+ while response.any?
+ commits = []
+
+ response.each do |commit|
+ commits.push(commit) if commit.trailers.key?(trailer)
+ end
+
+ yield commits
+
+ offset += response.length
+ response = fetch_commits(offset)
+ end
+ end
+
+ private
+
+ def fetch_commits(offset = 0)
+ range = "#{@from}..#{@to}"
+
+ @project
+ .repository
+ .commits(range, limit: @per_page, offset: offset, trailers: true)
+ end
+ end
+end
diff --git a/app/finders/repositories/previous_tag_finder.rb b/app/finders/repositories/previous_tag_finder.rb
new file mode 100644
index 00000000000..150a6332c29
--- /dev/null
+++ b/app/finders/repositories/previous_tag_finder.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Repositories
+ # A finder class for getting the tag of the last release before a given
+ # version.
+ #
+ # Imagine a project with the following tags:
+ #
+ # * v1.0.0
+ # * v1.1.0
+ # * v2.0.0
+ #
+ # If the version supplied is 2.1.0, the tag returned will be v2.0.0. And when
+ # the version is 1.1.1, or 1.2.0, the returned tag will be v1.1.0.
+ #
+ # This finder expects that all tags to consider meet the following
+ # requirements:
+ #
+ # * They start with the letter "v"
+ # * They use semantic versioning for the tag format
+ #
+ # Tags not meeting these requirements are ignored.
+ class PreviousTagFinder
+ TAG_REGEX = /\Av(?<version>#{Gitlab::Regex.unbounded_semver_regex})\z/.freeze
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute(new_version)
+ tags = {}
+ versions = [new_version]
+
+ @project.repository.tags.each do |tag|
+ matches = tag.name.match(TAG_REGEX)
+
+ next unless matches
+
+ version = matches[:version]
+ tags[version] = tag
+ versions << version
+ end
+
+ VersionSorter.sort!(versions)
+
+ index = versions.index(new_version)
+
+ tags[versions[index - 1]] if index&.positive?
+ end
+ end
+end
diff --git a/app/finders/template_finder.rb b/app/finders/template_finder.rb
index dac7c526474..36f8d144908 100644
--- a/app/finders/template_finder.rb
+++ b/app/finders/template_finder.rb
@@ -21,6 +21,18 @@ class TemplateFinder
new(type, project, params)
end
end
+
+ def all_template_names(project, type)
+ return {} if !VENDORED_TEMPLATES.key?(type.to_s) && type.to_s != 'licenses'
+
+ build(type, project).template_names
+ end
+
+ # This is issues and merge requests description templates only.
+ # This will be removed once we introduce group level inherited templates
+ def all_template_names_array(project, type)
+ all_template_names(project, type).values.flatten.uniq
+ end
end
attr_reader :type, :project, :params
@@ -43,6 +55,10 @@ class TemplateFinder
vendored_templates.all(project)
end
end
+
+ def template_names
+ vendored_templates.template_names(project)
+ end
end
TemplateFinder.prepend_if_ee('::EE::TemplateFinder')
diff --git a/app/finders/terraform/states_finder.rb b/app/finders/terraform/states_finder.rb
new file mode 100644
index 00000000000..bbe90fead2b
--- /dev/null
+++ b/app/finders/terraform/states_finder.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Terraform
+ class StatesFinder
+ def initialize(project, current_user, params: {})
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return ::Terraform::State.none unless can_read_terraform_states?
+
+ states = project.terraform_states
+ states = states.with_name(params[:name]) if params[:name].present?
+
+ states.ordered_by_name
+ end
+
+ private
+
+ attr_reader :project, :current_user, :params
+
+ def can_read_terraform_states?
+ current_user.can?(:read_terraform_state, project)
+ end
+ end
+end
diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb
index f376b26ab9c..596a413782e 100644
--- a/app/finders/user_recent_events_finder.rb
+++ b/app/finders/user_recent_events_finder.rb
@@ -15,40 +15,47 @@ class UserRecentEventsFinder
requires_cross_project_access
- attr_reader :current_user, :target_user, :params
+ attr_reader :current_user, :target_user, :params, :event_filter
DEFAULT_LIMIT = 20
MAX_LIMIT = 100
- def initialize(current_user, target_user, params = {})
+ def initialize(current_user, target_user, event_filter, params = {})
@current_user = current_user
@target_user = target_user
@params = params
+ @event_filter = event_filter || EventFilter.new(EventFilter::ALL)
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute
+ if target_user.is_a? User
+ execute_single
+ else
+ execute_multi
+ end
+ end
+
+ private
+
+ def execute_single
return Event.none unless can?(current_user, :read_user_profile, target_user)
- recent_events(params[:offset] || 0)
- .joins(:project)
+ event_filter.apply_filter(target_events
.with_associations
.limit_recent(limit, params[:offset])
+ .order_created_desc)
end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
# rubocop: disable CodeReuse/ActiveRecord
- def recent_events(offset)
- sql = <<~SQL
- (#{projects}) AS projects_for_join
- JOIN (#{target_events.to_sql}) AS #{Event.table_name}
- ON #{Event.table_name}.project_id = projects_for_join.id
- SQL
+ def execute_multi
+ users = []
+ @target_user.each do |user|
+ users.append(user.id) if can?(current_user, :read_user_profile, user)
+ end
+
+ return Event.none if users.empty?
- # Workaround for https://github.com/rails/rails/issues/24193
- Event.from([Arel.sql(sql)])
+ event_filter.apply_filter(Event.where(author: users).limit_recent(limit, params[:offset] || 0))
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -58,10 +65,6 @@ class UserRecentEventsFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- def projects
- target_user.project_interactions.to_sql
- end
-
def limit
return DEFAULT_LIMIT unless params[:limit].present?
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
index 3a57cb9670d..86908c1449c 100644
--- a/app/graphql/mutations/alert_management/base.rb
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -21,7 +21,7 @@ module Mutations
field :todo,
Types::TodoType,
null: true,
- description: "The todo after mutation."
+ description: "The to-do item after mutation."
field :issue,
Types::IssueType,
diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb
index ff165d7f302..2d7bffb4333 100644
--- a/app/graphql/mutations/alert_management/http_integration/create.rb
+++ b/app/graphql/mutations/alert_management/http_integration/create.rb
@@ -4,7 +4,7 @@ module Mutations
module AlertManagement
module HttpIntegration
class Create < HttpIntegrationBase
- include ResolvesProject
+ include FindsProject
graphql_name 'HttpIntegrationCreate'
@@ -21,27 +21,14 @@ module Mutations
description: 'Whether the integration is receiving alerts.'
def resolve(args)
- @project = authorized_find!(full_path: args[:project_path])
+ project = authorized_find!(args[:project_path])
response ::AlertManagement::HttpIntegrations::CreateService.new(
project,
current_user,
- http_integration_params(args)
+ http_integration_params(project, args)
).execute
end
-
- private
-
- attr_reader :project
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- # overriden in EE
- def http_integration_params(args)
- args.slice(:name, :active)
- end
end
end
end
diff --git a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
index 147df982bec..e33b7bb399a 100644
--- a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
+++ b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
@@ -23,7 +23,14 @@ module Mutations
errors: result.errors
}
end
+
+ # overriden in EE
+ def http_integration_params(_project, args)
+ args.slice(:name, :active)
+ end
end
end
end
end
+
+Mutations::AlertManagement::HttpIntegration::HttpIntegrationBase.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::HttpIntegrationBase')
diff --git a/app/graphql/mutations/alert_management/http_integration/update.rb b/app/graphql/mutations/alert_management/http_integration/update.rb
index 431fccaa5e5..b1e4ce841ee 100644
--- a/app/graphql/mutations/alert_management/http_integration/update.rb
+++ b/app/graphql/mutations/alert_management/http_integration/update.rb
@@ -24,10 +24,12 @@ module Mutations
response ::AlertManagement::HttpIntegrations::UpdateService.new(
integration,
current_user,
- args.slice(:name, :active)
+ http_integration_params(integration.project, args)
).execute
end
end
end
end
end
+
+Mutations::AlertManagement::HttpIntegration::Update.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::Update')
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
index c676cde90b4..87e6bc46937 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/create.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -4,7 +4,7 @@ module Mutations
module AlertManagement
module PrometheusIntegration
class Create < PrometheusIntegrationBase
- include ResolvesProject
+ include FindsProject
graphql_name 'PrometheusIntegrationCreate'
@@ -21,7 +21,7 @@ module Mutations
description: 'Endpoint at which prometheus can be queried.'
def resolve(args)
- project = authorized_find!(full_path: args[:project_path])
+ project = authorized_find!(args[:project_path])
return integration_exists if project.prometheus_service
@@ -37,10 +37,6 @@ module Mutations
private
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
def integration_exists
response(nil, message: _('Multiple Prometheus integrations are not supported'))
end
diff --git a/app/graphql/mutations/boards/lists/base.rb b/app/graphql/mutations/boards/lists/base.rb
deleted file mode 100644
index 34c138bddc9..00000000000
--- a/app/graphql/mutations/boards/lists/base.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Boards
- module Lists
- class Base < BaseMutation
- include Mutations::ResolvesIssuable
-
- argument :board_id, ::Types::GlobalIDType[::Board],
- required: true,
- description: 'Global ID of the issue board to mutate.'
-
- field :list,
- Types::BoardListType,
- null: true,
- description: 'List of the issue board.'
-
- authorize :admin_list
-
- private
-
- def find_object(id:)
- GitlabSchema.object_from_id(id, expected_type: ::Board)
- end
- end
- end
- end
-end
diff --git a/app/graphql/mutations/boards/lists/base_create.rb b/app/graphql/mutations/boards/lists/base_create.rb
new file mode 100644
index 00000000000..a21c7feece3
--- /dev/null
+++ b/app/graphql/mutations/boards/lists/base_create.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Boards
+ module Lists
+ class BaseCreate < BaseMutation
+ argument :backlog, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Create the backlog list.'
+
+ argument :label_id, ::Types::GlobalIDType[::Label],
+ required: false,
+ description: 'Global ID of an existing label.'
+
+ def ready?(**args)
+ if args.slice(*mutually_exclusive_args).size != 1
+ arg_str = mutually_exclusive_args.map { |x| x.to_s.camelize(:lower) }.join(' or ')
+ raise Gitlab::Graphql::Errors::ArgumentError, "one and only one of #{arg_str} is required"
+ end
+
+ super
+ end
+
+ def resolve(**args)
+ board = authorized_find!(id: args[:board_id])
+ params = create_list_params(args)
+
+ response = create_list(board, params)
+
+ {
+ list: response.success? ? response.payload[:list] : nil,
+ errors: response.errors
+ }
+ end
+
+ private
+
+ def create_list(board, params)
+ raise NotImplementedError
+ end
+
+ def create_list_params(args)
+ params = args.slice(*mutually_exclusive_args).with_indifferent_access
+ params[:label_id] &&= ::GitlabSchema.parse_gid(params[:label_id], expected_type: ::Label).model_id
+
+ params
+ end
+
+ def mutually_exclusive_args
+ [:backlog, :label_id]
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/boards/lists/create.rb b/app/graphql/mutations/boards/lists/create.rb
index 9eb9a4d4b87..f3aae9ac9c8 100644
--- a/app/graphql/mutations/boards/lists/create.rb
+++ b/app/graphql/mutations/boards/lists/create.rb
@@ -3,59 +3,32 @@
module Mutations
module Boards
module Lists
- class Create < Base
+ class Create < BaseCreate
graphql_name 'BoardListCreate'
- argument :backlog, GraphQL::BOOLEAN_TYPE,
- required: false,
- description: 'Create the backlog list.'
+ argument :board_id, ::Types::GlobalIDType[::Board],
+ required: true,
+ description: 'Global ID of the issue board to mutate.'
- argument :label_id, ::Types::GlobalIDType[::Label],
- required: false,
- description: 'Global ID of an existing label.'
+ field :list,
+ Types::BoardListType,
+ null: true,
+ description: 'Issue list in the issue board.'
- def ready?(**args)
- if args.slice(*mutually_exclusive_args).size != 1
- arg_str = mutually_exclusive_args.map { |x| x.to_s.camelize(:lower) }.join(' or ')
- raise Gitlab::Graphql::Errors::ArgumentError, "one and only one of #{arg_str} is required"
- end
+ authorize :admin_list
- super
- end
-
- def resolve(**args)
- board = authorized_find!(id: args[:board_id])
- params = create_list_params(args)
-
- response = create_list(board, params)
+ private
- {
- list: response.success? ? response.payload[:list] : nil,
- errors: response.errors
- }
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_type: ::Board)
end
- private
-
def create_list(board, params)
create_list_service =
::Boards::Lists::CreateService.new(board.resource_parent, current_user, params)
create_list_service.execute(board)
end
-
- # Overridden in EE
- def create_list_params(args)
- params = args.slice(*mutually_exclusive_args).with_indifferent_access
- params[:label_id] &&= ::GitlabSchema.parse_gid(params[:label_id], expected_type: ::Label).model_id
-
- params
- end
-
- # Overridden in EE
- def mutually_exclusive_args
- [:backlog, :label_id]
- end
end
end
end
diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb
index 9fe9bef5403..6354976f1ea 100644
--- a/app/graphql/mutations/branches/create.rb
+++ b/app/graphql/mutations/branches/create.rb
@@ -3,7 +3,7 @@
module Mutations
module Branches
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'CreateBranch'
@@ -28,7 +28,7 @@ module Mutations
authorize :push_code
def resolve(project_path:, name:, ref:)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
context.scoped_set!(:branch_project, project)
@@ -40,12 +40,6 @@ module Mutations
errors: Array.wrap(result[:message])
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index ae14401558b..84933fee5d2 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -3,7 +3,7 @@
module Mutations
module Commits
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'CommitCreate'
@@ -37,7 +37,7 @@ module Mutations
authorize :push_code
def resolve(project_path:, branch:, message:, actions:, **args)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
attributes = {
commit_message: message,
@@ -53,12 +53,6 @@ module Mutations
errors: Array.wrap(result[:message])
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
new file mode 100644
index 00000000000..2d4983f0d6e
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Mutations
+ # This concern can be mixed into a mutation to provide support for spam checking,
+ # and optionally support the workflow to allow clients to display and solve CAPTCHAs.
+ module CanMutateSpammable
+ extend ActiveSupport::Concern
+
+ # NOTE: The arguments and fields are intentionally named with 'captcha' instead of 'recaptcha',
+ # so that they can be applied to future alternative CAPTCHA implementations other than
+ # reCAPTCHA (e.g. FriendlyCaptcha) without having to change the names and descriptions in the API.
+ included do
+ argument :captcha_response, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'A 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::INT_TYPE,
+ required: false,
+ description: 'The 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::BOOLEAN_TYPE,
+ null: true,
+ 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::BOOLEAN_TYPE,
+ null: true,
+ 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::INT_TYPE,
+ null: true,
+ description: 'The 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::STRING_TYPE,
+ null: true,
+ description: 'The 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
+
+ private
+
+ # additional_spam_params -> hash
+ #
+ # Used from a spammable mutation's #resolve method to generate
+ # the required additional spam/recaptcha params which must be merged into the params
+ # passed to the constructor of a service, where they can then be used in the service
+ # to perform spam checking via SpamActionService.
+ #
+ # Also accesses the #context of the mutation's Resolver superclass to obtain the request.
+ #
+ # Example:
+ #
+ # existing_args.merge!(additional_spam_params)
+ def additional_spam_params
+ {
+ api: true,
+ request: context[:request]
+ }
+ end
+
+ # with_spam_action_fields(spammable) { {other_fields: true} } -> hash
+ #
+ # Takes a Spammable and a block as arguments.
+ #
+ # The block passed should be a hash, which the spam action fields will be merged into.
+ def with_spam_action_fields(spammable)
+ spam_action_fields = {
+ spam: spammable.spam?,
+ # NOTE: These fields are intentionally named with 'captcha' instead of 'recaptcha', so
+ # that they can be applied to future alternative CAPTCHA implementations other than
+ # reCAPTCHA (such as FriendlyCaptcha) without having to change the response field name
+ # in the API.
+ needs_captcha_response: spammable.render_recaptcha?,
+ spam_log_id: spammable.spam_log&.id,
+ captcha_site_key: Gitlab::CurrentSettings.recaptcha_site_key
+ }
+
+ yield.merge(spam_action_fields)
+ end
+ end
+end
diff --git a/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
index e2b3f4b046f..b8ef675c3d4 100644
--- a/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
+++ b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
@@ -9,11 +9,11 @@ module Mutations
included do
argument :project_path, GraphQL::ID_TYPE,
required: false,
- description: 'The project full path the resource is associated with.'
+ description: 'Full path of the project with which the resource is associated.'
argument :group_path, GraphQL::ID_TYPE,
required: false,
- description: 'The group full path the resource is associated with.'
+ description: 'Full path of the group with which the resource is associated.'
end
def ready?(**args)
diff --git a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb b/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
deleted file mode 100644
index e5df8565618..00000000000
--- a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module SpammableMutationFields
- extend ActiveSupport::Concern
-
- included do
- field :spam,
- GraphQL::BOOLEAN_TYPE,
- null: true,
- description: 'Indicates whether the operation returns a record detected as spam.'
- end
-
- def with_spam_params(&block)
- request = Feature.enabled?(:snippet_spam) ? context[:request] : nil
-
- yield.merge({ api: true, request: request })
- end
-
- def with_spam_fields(spammable, &block)
- { spam: spammable.spam? }.merge!(yield)
- end
- end
-end
diff --git a/app/graphql/mutations/container_expiration_policies/update.rb b/app/graphql/mutations/container_expiration_policies/update.rb
index 37cf2fa6bf3..f61d852bb6c 100644
--- a/app/graphql/mutations/container_expiration_policies/update.rb
+++ b/app/graphql/mutations/container_expiration_policies/update.rb
@@ -3,7 +3,7 @@
module Mutations
module ContainerExpirationPolicies
class Update < Mutations::BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'UpdateContainerExpirationPolicy'
@@ -50,7 +50,7 @@ module Mutations
description: 'The container expiration policy after mutation.'
def resolve(project_path:, **args)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
result = ::ContainerExpirationPolicies::UpdateService
.new(container: project, current_user: current_user, params: args)
@@ -61,12 +61,6 @@ module Mutations
errors: result.errors
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/discussions/toggle_resolve.rb b/app/graphql/mutations/discussions/toggle_resolve.rb
index c9834c946b2..6639252ec67 100644
--- a/app/graphql/mutations/discussions/toggle_resolve.rb
+++ b/app/graphql/mutations/discussions/toggle_resolve.rb
@@ -69,7 +69,7 @@ module Mutations
end
def unresolve!(discussion)
- discussion.unresolve!
+ ::Discussions::UnresolveService.new(discussion, current_user).execute
end
end
end
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 18b80ff1736..37fddd92832 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -3,7 +3,7 @@
module Mutations
module Issues
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'CreateIssue'
authorize :create_issue
@@ -70,7 +70,7 @@ module Mutations
end
def resolve(project_path:, **attributes)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = build_create_issue_params(attributes.merge(author_id: current_user.id))
issue = ::Issues::CreateService.new(project, current_user, params).execute
@@ -98,10 +98,6 @@ module Mutations
def mutually_exclusive_label_args
[:labels, :label_ids]
end
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/jira_import/import_users.rb b/app/graphql/mutations/jira_import/import_users.rb
index 616ef390657..af2bb18161f 100644
--- a/app/graphql/mutations/jira_import/import_users.rb
+++ b/app/graphql/mutations/jira_import/import_users.rb
@@ -3,10 +3,12 @@
module Mutations
module JiraImport
class ImportUsers < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'JiraImportUsers'
+ authorize :admin_project
+
field :jira_users,
[Types::JiraUserType],
null: true,
@@ -20,7 +22,7 @@ module Mutations
description: 'The index of the record the import should started at, default 0 (50 records returned).'
def resolve(project_path:, start_at: 0)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
service_response = ::JiraImport::UsersImporter.new(context[:current_user], project, start_at.to_i).execute
@@ -29,16 +31,6 @@ module Mutations
errors: service_response.errors
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- def authorized_resource?(project)
- Ability.allowed?(context[:current_user], :admin_project, project)
- end
end
end
end
diff --git a/app/graphql/mutations/jira_import/start.rb b/app/graphql/mutations/jira_import/start.rb
index 3d50ebde13a..e31aaf53a09 100644
--- a/app/graphql/mutations/jira_import/start.rb
+++ b/app/graphql/mutations/jira_import/start.rb
@@ -3,10 +3,12 @@
module Mutations
module JiraImport
class Start < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'JiraImportStart'
+ authorize :admin_project
+
field :jira_import,
Types::JiraImportType,
null: true,
@@ -27,7 +29,7 @@ module Mutations
description: 'The mapping of Jira to GitLab users.'
def resolve(project_path:, jira_project_key:, users_mapping:)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
mapping = users_mapping.to_ary.map { |map| map.to_hash }
service_response = ::JiraImport::StartImportService
@@ -40,16 +42,6 @@ module Mutations
errors: service_response.errors
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- def authorized_resource?(project)
- Ability.allowed?(context[:current_user], :admin_project, project)
- end
end
end
end
diff --git a/app/graphql/mutations/merge_requests/create.rb b/app/graphql/mutations/merge_requests/create.rb
index 64fa8417e50..9ac8f70be95 100644
--- a/app/graphql/mutations/merge_requests/create.rb
+++ b/app/graphql/mutations/merge_requests/create.rb
@@ -3,7 +3,7 @@
module Mutations
module MergeRequests
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'MergeRequestCreate'
@@ -39,7 +39,7 @@ module Mutations
authorize :create_merge_request_from
def resolve(project_path:, **attributes)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = attributes.merge(author_id: current_user.id)
merge_request = ::MergeRequests::CreateService.new(project, current_user, params).execute
@@ -49,12 +49,6 @@ module Mutations
errors: errors_on_object(merge_request)
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/merge_requests/reviewer_rereview.rb b/app/graphql/mutations/merge_requests/reviewer_rereview.rb
new file mode 100644
index 00000000000..f6f4881654e
--- /dev/null
+++ b/app/graphql/mutations/merge_requests/reviewer_rereview.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module MergeRequests
+ class ReviewerRereview < Base
+ graphql_name 'MergeRequestReviewerRereview'
+
+ argument :user_id, ::Types::GlobalIDType[::User],
+ loads: Types::UserType,
+ required: true,
+ description: <<~DESC
+ The user ID for the user that has been requested for a new review.
+ DESC
+
+ def resolve(project_path:, iid:, user:)
+ merge_request = authorized_find!(project_path: project_path, iid: iid)
+
+ result = ::MergeRequests::RequestReviewService.new(merge_request.project, current_user).execute(merge_request, user)
+
+ {
+ merge_request: merge_request,
+ errors: Array(result[:message])
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/update.rb b/app/graphql/mutations/merge_requests/update.rb
index 4721ebab41b..6a94d2f37b2 100644
--- a/app/graphql/mutations/merge_requests/update.rb
+++ b/app/graphql/mutations/merge_requests/update.rb
@@ -19,9 +19,14 @@ module Mutations
required: false,
description: copy_field_description(Types::MergeRequestType, :description)
- def resolve(args)
- merge_request = authorized_find!(**args.slice(:project_path, :iid))
- attributes = args.slice(:title, :description, :target_branch).compact
+ argument :state, ::Types::MergeRequestStateEventEnum,
+ required: false,
+ as: :state_event,
+ description: 'The action to perform to change the state.'
+
+ def resolve(project_path:, iid:, **args)
+ merge_request = authorized_find!(project_path: project_path, iid: iid)
+ attributes = args.compact
::MergeRequests::UpdateService
.new(merge_request.project, current_user, attributes)
diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb
index 2351af01813..a157a5abdf2 100644
--- a/app/graphql/mutations/notes/create/base.rb
+++ b/app/graphql/mutations/notes/create/base.rb
@@ -25,6 +25,7 @@ module Mutations
def resolve(args)
noteable = authorized_find!(id: args[:noteable_id])
+ verify_rate_limit!(current_user)
note = ::Notes::CreateService.new(
noteable.project,
@@ -54,6 +55,20 @@ module Mutations
confidential: args[:confidential]
}
end
+
+ def verify_rate_limit!(current_user)
+ return unless rate_limit_throttled?
+
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable,
+ 'This endpoint has been requested too many times. Try again later.'
+ end
+
+ def rate_limit_throttled?
+ rate_limiter = ::Gitlab::ApplicationRateLimiter
+ allowlist = Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
+
+ rate_limiter.throttled?(:notes_create, scope: [current_user], users_allowlist: allowlist)
+ end
end
end
end
diff --git a/app/graphql/mutations/releases/base.rb b/app/graphql/mutations/releases/base.rb
index dd1724fe320..610e9cd9cde 100644
--- a/app/graphql/mutations/releases/base.rb
+++ b/app/graphql/mutations/releases/base.rb
@@ -3,17 +3,11 @@
module Mutations
module Releases
class Base < BaseMutation
- include ResolvesProject
+ include FindsProject
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'Full path of the project the release is associated with.'
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/releases/create.rb b/app/graphql/mutations/releases/create.rb
index 91ac256033e..914c1302094 100644
--- a/app/graphql/mutations/releases/create.rb
+++ b/app/graphql/mutations/releases/create.rb
@@ -41,7 +41,7 @@ module Mutations
authorize :create_release
def resolve(project_path:, assets: nil, **scalars)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = {
**scalars,
diff --git a/app/graphql/mutations/releases/delete.rb b/app/graphql/mutations/releases/delete.rb
index e887b702cce..020c9133b58 100644
--- a/app/graphql/mutations/releases/delete.rb
+++ b/app/graphql/mutations/releases/delete.rb
@@ -17,7 +17,7 @@ module Mutations
authorize :destroy_release
def resolve(project_path:, tag:)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = { tag: tag }.with_indifferent_access
diff --git a/app/graphql/mutations/releases/update.rb b/app/graphql/mutations/releases/update.rb
index dff743254bd..35f2a7b3d4b 100644
--- a/app/graphql/mutations/releases/update.rb
+++ b/app/graphql/mutations/releases/update.rb
@@ -47,7 +47,7 @@ module Mutations
end
def resolve(project_path:, **scalars)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = scalars.with_indifferent_access
diff --git a/app/graphql/mutations/security/ci_configuration/configure_sast.rb b/app/graphql/mutations/security/ci_configuration/configure_sast.rb
new file mode 100644
index 00000000000..e4a3f815396
--- /dev/null
+++ b/app/graphql/mutations/security/ci_configuration/configure_sast.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Security
+ module CiConfiguration
+ class ConfigureSast < BaseMutation
+ include FindsProject
+
+ graphql_name 'ConfigureSast'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Full path of the project.'
+
+ argument :configuration, ::Types::CiConfiguration::Sast::InputType,
+ required: true,
+ description: 'SAST CI configuration for the project.'
+
+ field :status, GraphQL::STRING_TYPE, null: false,
+ description: 'Status of creating the commit for the supplied SAST CI configuration.'
+
+ field :success_path, GraphQL::STRING_TYPE, null: true,
+ description: 'Redirect path to use when the response is successful.'
+
+ authorize :push_code
+
+ def resolve(project_path:, configuration:)
+ project = authorized_find!(project_path)
+
+ result = ::Security::CiConfiguration::SastCreateService.new(project, current_user, configuration).execute
+ prepare_response(result)
+ end
+
+ private
+
+ def prepare_response(result)
+ {
+ status: result[:status],
+ success_path: result[:success_path],
+ errors: Array(result[:errors])
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index b4485e28c5a..73eac9f0f3b 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -3,7 +3,8 @@
module Mutations
module Snippets
class Create < BaseMutation
- include SpammableMutationFields
+ include ServiceCompatibility
+ include CanMutateSpammable
authorize :create_snippet
@@ -45,18 +46,17 @@ module Mutations
authorize!(:global)
end
- service_response = ::Snippets::CreateService.new(project,
- current_user,
- create_params(args)).execute
+ process_args_for_params!(args)
- snippet = service_response.payload[:snippet]
+ service_response = ::Snippets::CreateService.new(project, current_user, args).execute
# Only when the user is not an api user and the operation was successful
if !api_user? && service_response.success?
::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
end
- with_spam_fields(snippet) do
+ snippet = service_response.payload[:snippet]
+ with_spam_action_fields(snippet) do
{
snippet: service_response.success? ? snippet : nil,
errors: errors_on_object(snippet)
@@ -70,18 +70,25 @@ module Mutations
Project.find_by_full_path(full_path)
end
- def create_params(args)
- with_spam_params do
- args.tap do |create_args|
- # We need to rename `blob_actions` into `snippet_actions` because
- # it's the expected key param
- create_args[:snippet_actions] = create_args.delete(:blob_actions)&.map(&:to_h)
-
- # We need to rename `uploaded_files` into `files` because
- # it's the expected key param
- create_args[:files] = create_args.delete(:uploaded_files)
- end
+ # process_args_for_params!(args) -> nil
+ #
+ # Modifies/adds/deletes mutation resolve args as necessary to be passed as params to service layer.
+ def process_args_for_params!(args)
+ convert_blob_actions_to_snippet_actions!(args)
+
+ # We need to rename `uploaded_files` into `files` because
+ # it's the expected key param
+ args[:files] = args.delete(:uploaded_files)
+
+ if Feature.enabled?(:snippet_spam)
+ args.merge!(additional_spam_params)
+ else
+ args[:disable_spam_action_service] = true
end
+
+ # Return nil to make it explicit that this method is mutating the args parameter, and that
+ # the return value is not relevant and is not to be used.
+ nil
end
end
end
diff --git a/app/graphql/mutations/snippets/service_compatibility.rb b/app/graphql/mutations/snippets/service_compatibility.rb
new file mode 100644
index 00000000000..0e7ee5d78bf
--- /dev/null
+++ b/app/graphql/mutations/snippets/service_compatibility.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Snippets
+ # Translates graphql mutation field params to be compatible with those expected by the service layer
+ module ServiceCompatibility
+ extend ActiveSupport::Concern
+
+ # convert_blob_actions_to_snippet_actions!(args) -> nil
+ #
+ # Converts the blob_actions mutation argument into the
+ # snippet_actions hash which the service layer expects
+ def convert_blob_actions_to_snippet_actions!(args)
+ # We need to rename `blob_actions` into `snippet_actions` because
+ # it's the expected key param
+ args[:snippet_actions] = args.delete(:blob_actions)&.map(&:to_h)
+
+ # Return nil to make it explicit that this method is mutating the args parameter
+ nil
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 930440fbd35..af8e6f384b7 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -3,7 +3,8 @@
module Mutations
module Snippets
class Update < Base
- include SpammableMutationFields
+ include ServiceCompatibility
+ include CanMutateSpammable
graphql_name 'UpdateSnippet'
@@ -30,19 +31,23 @@ module Mutations
def resolve(id:, **args)
snippet = authorized_find!(id: id)
- result = ::Snippets::UpdateService.new(snippet.project,
- current_user,
- update_params(args)).execute(snippet)
- snippet = result.payload[:snippet]
+ process_args_for_params!(args)
+
+ service_response = ::Snippets::UpdateService.new(snippet.project, current_user, args).execute(snippet)
+
+ # TODO: DRY this up - From here down, this is all duplicated with Mutations::Snippets::Create#resolve, except for
+ # `snippet.reset`, which is required in order to return the object in its non-dirty, unmodified, database state
+ # See issue here: https://gitlab.com/gitlab-org/gitlab/-/issues/300250
# Only when the user is not an api user and the operation was successful
- if !api_user? && result.success?
+ if !api_user? && service_response.success?
::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
end
- with_spam_fields(snippet) do
+ snippet = service_response.payload[:snippet]
+ with_spam_action_fields(snippet) do
{
- snippet: result.success? ? snippet : snippet.reset,
+ snippet: service_response.success? ? snippet : snippet.reset,
errors: errors_on_object(snippet)
}
end
@@ -50,18 +55,25 @@ module Mutations
private
- def ability_name
- 'update'
- end
+ # process_args_for_params!(args) -> nil
+ #
+ # Modifies/adds/deletes mutation resolve args as necessary to be passed as params to service layer.
+ def process_args_for_params!(args)
+ convert_blob_actions_to_snippet_actions!(args)
- def update_params(args)
- with_spam_params do
- args.tap do |update_args|
- # We need to rename `blob_actions` into `snippet_actions` because
- # it's the expected key param
- update_args[:snippet_actions] = update_args.delete(:blob_actions)&.map(&:to_h)
- end
+ if Feature.enabled?(:snippet_spam)
+ args.merge!(additional_spam_params)
+ else
+ args[:disable_spam_action_service] = true
end
+
+ # Return nil to make it explicit that this method is mutating the args parameter, and that
+ # the return value is not relevant and is not to be used.
+ nil
+ end
+
+ def ability_name
+ 'update'
end
end
end
diff --git a/app/graphql/mutations/todos/create.rb b/app/graphql/mutations/todos/create.rb
index 814f7ec4fc4..b6250b0228c 100644
--- a/app/graphql/mutations/todos/create.rb
+++ b/app/graphql/mutations/todos/create.rb
@@ -14,7 +14,7 @@ module Mutations
field :todo, Types::TodoType,
null: true,
- description: 'The to-do created.'
+ description: 'The to-do item created.'
def resolve(target_id:)
id = ::Types::GlobalIDType[Todoable].coerce_isolated_input(target_id)
diff --git a/app/graphql/mutations/todos/mark_all_done.rb b/app/graphql/mutations/todos/mark_all_done.rb
index c8359953567..22a5893d4ec 100644
--- a/app/graphql/mutations/todos/mark_all_done.rb
+++ b/app/graphql/mutations/todos/mark_all_done.rb
@@ -10,12 +10,12 @@ module Mutations
field :updated_ids,
[::Types::GlobalIDType[::Todo]],
null: false,
- deprecated: { reason: 'Use todos', milestone: '13.2' },
- description: 'Ids of the updated todos.'
+ deprecated: { reason: 'Use to-do items', milestone: '13.2' },
+ description: 'IDs of the updated to-do items.'
field :todos, [::Types::TodoType],
null: false,
- description: 'Updated todos.'
+ description: 'Updated to-do items.'
def resolve
authorize!(current_user)
diff --git a/app/graphql/mutations/todos/mark_done.rb b/app/graphql/mutations/todos/mark_done.rb
index 95144abb040..a78cc91da68 100644
--- a/app/graphql/mutations/todos/mark_done.rb
+++ b/app/graphql/mutations/todos/mark_done.rb
@@ -10,11 +10,11 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Todo],
required: true,
- description: 'The global ID of the todo to mark as done.'
+ description: 'The global ID of the to-do item to mark as done.'
field :todo, Types::TodoType,
null: false,
- description: 'The requested todo.'
+ description: 'The requested to-do item.'
def resolve(id:)
todo = authorized_find!(id: id)
diff --git a/app/graphql/mutations/todos/restore.rb b/app/graphql/mutations/todos/restore.rb
index e496627aec2..70c33c439c4 100644
--- a/app/graphql/mutations/todos/restore.rb
+++ b/app/graphql/mutations/todos/restore.rb
@@ -10,11 +10,11 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Todo],
required: true,
- description: 'The global ID of the todo to restore.'
+ description: 'The global ID of the to-do item to restore.'
field :todo, Types::TodoType,
null: false,
- description: 'The requested todo.'
+ description: 'The requested to-do item.'
def resolve(id:)
todo = authorized_find!(id: id)
diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb
index 9263c1d9afe..dc02ffadada 100644
--- a/app/graphql/mutations/todos/restore_many.rb
+++ b/app/graphql/mutations/todos/restore_many.rb
@@ -10,16 +10,16 @@ module Mutations
argument :ids,
[::Types::GlobalIDType[::Todo]],
required: true,
- description: 'The global IDs of the todos to restore (a maximum of 50 is supported at once).'
+ description: 'The global IDs of the to-do items to restore (a maximum of 50 is supported at once).'
field :updated_ids, [::Types::GlobalIDType[Todo]],
null: false,
- description: 'The IDs of the updated todo items.',
- deprecated: { reason: 'Use todos', milestone: '13.2' }
+ description: 'The IDs of the updated to-do items.',
+ deprecated: { reason: 'Use to-do items', milestone: '13.2' }
field :todos, [::Types::TodoType],
null: false,
- description: 'Updated todos.'
+ description: 'Updated to-do items.'
def resolve(ids:)
check_update_amount_limit!(ids)
@@ -46,7 +46,7 @@ module Mutations
end
def raise_too_many_todos_requested_error
- raise Gitlab::Graphql::Errors::ArgumentError, 'Too many todos requested.'
+ raise Gitlab::Graphql::Errors::ArgumentError, 'Too many to-do items requested.'
end
def check_update_amount_limit!(ids)
diff --git a/app/graphql/queries/container_registry/get_container_repositories.query.graphql b/app/graphql/queries/container_registry/get_container_repositories.query.graphql
index 6171233c446..4683ef9dfdb 100644
--- a/app/graphql/queries/container_registry/get_container_repositories.query.graphql
+++ b/app/graphql/queries/container_registry/get_container_repositories.query.graphql
@@ -6,11 +6,19 @@ query getProjectContainerRepositories(
$after: String
$before: String
$isGroupPage: Boolean!
+ $sort: ContainerRepositorySort
) {
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
__typename
containerRepositoriesCount
- containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ containerRepositories(
+ name: $name
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ sort: $sort
+ ) {
__typename
nodes {
id
@@ -35,7 +43,14 @@ query getProjectContainerRepositories(
group(fullPath: $fullPath) @include(if: $isGroupPage) {
__typename
containerRepositoriesCount
- containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
+ containerRepositories(
+ name: $name
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ sort: $sort
+ ) {
__typename
nodes {
id
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index 539e37db1c2..5db618254cb 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -118,7 +118,7 @@ module Resolvers
end
def offset_pagination(relation)
- ::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(relation)
+ ::Gitlab::Graphql::Pagination::OffsetPaginatedRelation.new(relation)
end
override :object
diff --git a/app/graphql/resolvers/board_lists_resolver.rb b/app/graphql/resolvers/board_lists_resolver.rb
index 7bdff8ba61f..a97ac3220d5 100644
--- a/app/graphql/resolvers/board_lists_resolver.rb
+++ b/app/graphql/resolvers/board_lists_resolver.rb
@@ -28,7 +28,7 @@ module Resolvers
context.scoped_set!(:issue_filters, issue_filters(issue_filters))
if load_preferences?(lookahead)
- List.preload_preferences_for_user(lists, context[:current_user])
+ List.preload_preferences_for_user(lists, current_user)
end
offset_pagination(lists)
@@ -39,7 +39,7 @@ module Resolvers
def board_lists(id)
service = ::Boards::Lists::ListService.new(
board.resource_parent,
- context[:current_user],
+ current_user,
list_id: extract_list_id(id)
)
@@ -47,7 +47,8 @@ module Resolvers
end
def load_preferences?(lookahead)
- lookahead&.selection(:edges)&.selection(:node)&.selects?(:collapsed)
+ lookahead&.selection(:edges)&.selection(:node)&.selects?(:collapsed) ||
+ lookahead&.selection(:nodes)&.selects?(:collapsed)
end
def extract_list_id(gid)
diff --git a/app/graphql/resolvers/board_resolver.rb b/app/graphql/resolvers/board_resolver.rb
index 582707cc1e4..2c2922c3fbf 100644
--- a/app/graphql/resolvers/board_resolver.rb
+++ b/app/graphql/resolvers/board_resolver.rb
@@ -13,7 +13,7 @@ module Resolvers
def resolve(id: nil)
return unless parent
- ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute(create_default_board: false).first
+ ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute.first
rescue ActiveRecord::RecordNotFound
nil
end
diff --git a/app/graphql/resolvers/boards_resolver.rb b/app/graphql/resolvers/boards_resolver.rb
index cdb15dc8f37..be2f22175dc 100644
--- a/app/graphql/resolvers/boards_resolver.rb
+++ b/app/graphql/resolvers/boards_resolver.rb
@@ -16,7 +16,7 @@ module Resolvers
return Board.none unless parent
- ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute(create_default_board: false)
+ ::Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute
rescue ActiveRecord::RecordNotFound
Board.none
end
diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb
index 72d3ae30d73..852bb47e215 100644
--- a/app/graphql/resolvers/ci/config_resolver.rb
+++ b/app/graphql/resolvers/ci/config_resolver.rb
@@ -29,6 +29,12 @@ module Resolvers
.new(project: project, current_user: context[:current_user])
.validate(content, dry_run: dry_run)
+ response(result).merge(merged_yaml: result.merged_yaml)
+ end
+
+ private
+
+ def response(result)
if result.errors.empty?
{
status: :valid,
@@ -43,8 +49,6 @@ module Resolvers
end
end
- private
-
def make_jobs(config_jobs)
config_jobs.map do |job|
{
diff --git a/app/graphql/resolvers/container_repositories_resolver.rb b/app/graphql/resolvers/container_repositories_resolver.rb
index 8042a368e33..17af2a2f070 100644
--- a/app/graphql/resolvers/container_repositories_resolver.rb
+++ b/app/graphql/resolvers/container_repositories_resolver.rb
@@ -10,8 +10,13 @@ module Resolvers
required: false,
description: 'Filter the container repositories by their name.'
- def resolve(name: nil)
- ContainerRepositoriesFinder.new(user: current_user, subject: object, params: { name: name })
+ argument :sort, Types::ContainerRepositorySortEnum,
+ description: 'Sort container repositories by this criteria.',
+ required: false,
+ default_value: :created_desc
+
+ def resolve(name: nil, sort: nil)
+ ContainerRepositoriesFinder.new(user: current_user, subject: object, params: { name: name, sort: sort })
.execute
.tap { track_event(:list_repositories, :container) }
end
diff --git a/app/graphql/resolvers/group_labels_resolver.rb b/app/graphql/resolvers/group_labels_resolver.rb
new file mode 100644
index 00000000000..5c2f950bbc0
--- /dev/null
+++ b/app/graphql/resolvers/group_labels_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class GroupLabelsResolver < LabelsResolver
+ type Types::LabelType.connection_type, null: true
+
+ argument :include_descendant_groups, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Include labels from descendant groups.',
+ default_value: false
+
+ argument :only_group_labels, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Include only group level labels.',
+ default_value: false
+ end
+end
diff --git a/app/graphql/resolvers/labels_resolver.rb b/app/graphql/resolvers/labels_resolver.rb
new file mode 100644
index 00000000000..1b523b8a240
--- /dev/null
+++ b/app/graphql/resolvers/labels_resolver.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class LabelsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ authorize :read_label
+
+ type Types::LabelType.connection_type, null: true
+
+ argument :search_term, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'A search term to find labels with.'
+
+ argument :include_ancestor_groups, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Include labels from ancestor groups.',
+ default_value: false
+
+ def resolve(**args)
+ return Label.none if parent.nil?
+
+ authorize!(parent)
+
+ # LabelsFinder uses `search` param, so we transform `search_term` into `search`
+ args[:search] = args.delete(:search_term)
+ LabelsFinder.new(current_user, parent_param.merge(args)).execute
+ end
+
+ private
+
+ def parent
+ object.respond_to?(:sync) ? object.sync : object
+ end
+
+ def parent_param
+ key = case parent
+ when Group then :group
+ when Project then :project
+ else raise "Unexpected parent type: #{parent.class}"
+ end
+
+ { "#{key}": parent }
+ end
+ end
+end
diff --git a/app/graphql/resolvers/package_details_resolver.rb b/app/graphql/resolvers/package_details_resolver.rb
index dcf4430e55f..e688e34599a 100644
--- a/app/graphql/resolvers/package_details_resolver.rb
+++ b/app/graphql/resolvers/package_details_resolver.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
module Resolvers
- # No return types defined because they can be different.
- # rubocop: disable Graphql/ResolverType
class PackageDetailsResolver < BaseResolver
+ type ::Types::Packages::PackageType, null: true
+
argument :id, ::Types::GlobalIDType[::Packages::Package],
required: true,
description: 'The global ID of the package.'
diff --git a/app/graphql/resolvers/packages_resolver.rb b/app/graphql/resolvers/packages_resolver.rb
index d19099e94d4..3eeed48ff7e 100644
--- a/app/graphql/resolvers/packages_resolver.rb
+++ b/app/graphql/resolvers/packages_resolver.rb
@@ -2,7 +2,7 @@
module Resolvers
class PackagesResolver < BaseResolver
- type Types::Packages::PackageType, null: true
+ type Types::Packages::PackageType.connection_type, null: true
def resolve(**args)
return unless packages_available?
diff --git a/app/graphql/resolvers/project_merge_requests_resolver.rb b/app/graphql/resolvers/project_merge_requests_resolver.rb
index 830649d5e52..9628a6dfd7a 100644
--- a/app/graphql/resolvers/project_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/project_merge_requests_resolver.rb
@@ -6,5 +6,38 @@ module Resolvers
accept_assignee
accept_author
accept_reviewer
+
+ def resolve(**args)
+ scope = super
+
+ if only_count_is_selected_with_merged_at_filter?(args) && Feature.enabled?(:optimized_merge_request_count_with_merged_at_filter, default_enabled: :yaml)
+ MergeRequest::MetricsFinder
+ .new(current_user, args.merge(target_project: project))
+ .execute
+ else
+ scope
+ end
+ end
+
+ def only_count_is_selected_with_merged_at_filter?(args)
+ return unless lookahead
+
+ argument_names = args.compact.except(:lookahead, :sort, :merged_before, :merged_after).keys
+
+ # no extra filtering arguments are provided
+ return unless argument_names.empty?
+ return unless args[:merged_after] || args[:merged_before]
+
+ # Detecting a specific query pattern:
+ # mergeRequests(mergedAfter: "X", mergedBefore: "Y") {
+ # count
+ # totalTimeToMerge
+ # }
+ allowed_selected_fields = [:count, :total_time_to_merge]
+ selected_fields = lookahead.selections.map(&:field).map(&:original_name) - [:__typename] # ignore __typename meta field
+
+ # only the allowed_selected_fields are present
+ (selected_fields - allowed_selected_fields).empty?
+ end
end
end
diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb
index 868d34ae7ad..672214df7d5 100644
--- a/app/graphql/resolvers/snippets/blobs_resolver.rb
+++ b/app/graphql/resolvers/snippets/blobs_resolver.rb
@@ -15,13 +15,10 @@ module Resolvers
required: false,
description: 'Paths of the blobs.'
- def resolve(**args)
+ def resolve(paths: [])
authorize!(snippet)
-
return [snippet.blob] if snippet.empty_repo?
- paths = Array(args.fetch(:paths, []))
-
if paths.empty?
snippet.blobs
else
diff --git a/app/graphql/resolvers/terraform/states_resolver.rb b/app/graphql/resolvers/terraform/states_resolver.rb
index 38b26a948b1..f543eb182e8 100644
--- a/app/graphql/resolvers/terraform/states_resolver.rb
+++ b/app/graphql/resolvers/terraform/states_resolver.rb
@@ -3,20 +3,20 @@
module Resolvers
module Terraform
class StatesResolver < BaseResolver
- type Types::Terraform::StateType, null: true
+ type Types::Terraform::StateType.connection_type, null: true
alias_method :project, :object
- def resolve(**args)
- return ::Terraform::State.none unless can_read_terraform_states?
-
- project.terraform_states.ordered_by_name
+ when_single do
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Name of the Terraform state.'
end
- private
-
- def can_read_terraform_states?
- current_user.can?(:read_terraform_state, project)
+ def resolve(**args)
+ ::Terraform::StatesFinder
+ .new(project, current_user, params: args)
+ .execute
end
end
end
diff --git a/app/graphql/types/access_level_type.rb b/app/graphql/types/access_level_type.rb
index c7f915f5038..21c3669979c 100644
--- a/app/graphql/types/access_level_type.rb
+++ b/app/graphql/types/access_level_type.rb
@@ -7,11 +7,11 @@ module Types
description 'Represents the access level of a relationship between a User and object that it is related to'
field :integer_value, GraphQL::INT_TYPE, null: true,
- description: 'Integer representation of access level',
+ description: 'Integer representation of access level.',
method: :to_i
field :string_value, Types::AccessLevelEnum, null: true,
- description: 'String representation of access level',
+ description: 'String representation of access level.',
method: :to_i
end
end
diff --git a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
index eab42c2b78d..17a5af8d36b 100644
--- a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
+++ b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
@@ -12,13 +12,13 @@ module Types
authorize :read_instance_statistics_measurements
field :recorded_at, Types::TimeType, null: true,
- description: 'The time the measurement was recorded'
+ description: 'The time the measurement was recorded.'
field :count, GraphQL::INT_TYPE, null: false,
- description: 'Object count'
+ description: 'Object count.'
field :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum, null: false,
- description: 'The type of objects being measured'
+ description: 'The type of objects being measured.'
end
end
end
diff --git a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb
index 93dd49b3c38..996300edad3 100644
--- a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb
+++ b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb
@@ -12,17 +12,17 @@ module Types
field :completed,
GraphQL::BOOLEAN_TYPE,
null: true,
- description: 'Whether or not the entire queue was processed in time; if not, retrying the same request is safe'
+ description: 'Whether or not the entire queue was processed in time; if not, retrying the same request is safe.'
field :deleted_jobs,
GraphQL::INT_TYPE,
null: true,
- description: 'The number of matching jobs deleted'
+ description: 'The number of matching jobs deleted.'
field :queue_size,
GraphQL::INT_TYPE,
null: true,
- description: 'The queue size after processing'
+ description: 'The queue size after processing.'
end
end
end
diff --git a/app/graphql/types/alert_management/alert_status_counts_type.rb b/app/graphql/types/alert_management/alert_status_counts_type.rb
index a84be705445..14a81735fa5 100644
--- a/app/graphql/types/alert_management/alert_status_counts_type.rb
+++ b/app/graphql/types/alert_management/alert_status_counts_type.rb
@@ -19,12 +19,12 @@ module Types
field :open,
GraphQL::INT_TYPE,
null: true,
- description: 'Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project'
+ description: 'Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project.'
field :all,
GraphQL::INT_TYPE,
null: true,
- description: 'Total number of alerts for the project'
+ description: 'Total number of alerts for the project.'
end
end
end
diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb
index 623762de208..6b7e7030c1f 100644
--- a/app/graphql/types/alert_management/alert_type.rb
+++ b/app/graphql/types/alert_management/alert_type.rb
@@ -15,115 +15,115 @@ module Types
field :iid,
GraphQL::ID_TYPE,
null: false,
- description: 'Internal ID of the alert'
+ description: 'Internal ID of the alert.'
field :issue_iid,
GraphQL::ID_TYPE,
null: true,
- description: 'Internal ID of the GitLab issue attached to the alert'
+ description: 'Internal ID of the GitLab issue attached to the alert.'
field :title,
GraphQL::STRING_TYPE,
null: true,
- description: 'Title of the alert'
+ description: 'Title of the alert.'
field :description,
GraphQL::STRING_TYPE,
null: true,
- description: 'Description of the alert'
+ description: 'Description of the alert.'
field :severity,
AlertManagement::SeverityEnum,
null: true,
- description: 'Severity of the alert'
+ description: 'Severity of the alert.'
field :status,
AlertManagement::StatusEnum,
null: true,
- description: 'Status of the alert',
+ description: 'Status of the alert.',
method: :status_name
field :service,
GraphQL::STRING_TYPE,
null: true,
- description: 'Service the alert came from'
+ description: 'Service the alert came from.'
field :monitoring_tool,
GraphQL::STRING_TYPE,
null: true,
- description: 'Monitoring tool the alert came from'
+ description: 'Monitoring tool the alert came from.'
field :hosts,
[GraphQL::STRING_TYPE],
null: true,
- description: 'List of hosts the alert came from'
+ description: 'List of hosts the alert came from.'
field :started_at,
Types::TimeType,
null: true,
- description: 'Timestamp the alert was raised'
+ description: 'Timestamp the alert was raised.'
field :ended_at,
Types::TimeType,
null: true,
- description: 'Timestamp the alert ended'
+ description: 'Timestamp the alert ended.'
field :environment,
Types::EnvironmentType,
null: true,
- description: 'Environment for the alert'
+ description: 'Environment for the alert.'
field :event_count,
GraphQL::INT_TYPE,
null: true,
- description: 'Number of events of this alert',
+ description: 'Number of events of this alert.',
method: :events
field :details, # rubocop:disable Graphql/JSONType
GraphQL::Types::JSON,
null: true,
- description: 'Alert details'
+ description: 'Alert details.'
field :created_at,
Types::TimeType,
null: true,
- description: 'Timestamp the alert was created'
+ description: 'Timestamp the alert was created.'
field :updated_at,
Types::TimeType,
null: true,
- description: 'Timestamp the alert was last updated'
+ description: 'Timestamp the alert was last updated.'
field :assignees,
Types::UserType.connection_type,
null: true,
- description: 'Assignees of the alert'
+ description: 'Assignees of the alert.'
field :metrics_dashboard_url,
GraphQL::STRING_TYPE,
null: true,
- description: 'URL for metrics embed for the alert'
+ description: 'URL for metrics embed for the alert.'
field :runbook,
GraphQL::STRING_TYPE,
null: true,
- description: 'Runbook for the alert as defined in alert details'
+ description: 'Runbook for the alert as defined in alert details.'
field :todos,
Types::TodoType.connection_type,
null: true,
- description: 'Todos of the current user for the alert',
+ description: 'To-do items of the current user for the alert.',
resolver: Resolvers::TodoResolver
field :details_url,
GraphQL::STRING_TYPE,
null: false,
- description: 'The URL of the alert detail page'
+ description: 'The URL of the alert detail page.'
field :prometheus_alert,
Types::PrometheusAlertType,
null: true,
- description: 'The alert condition for Prometheus'
+ description: 'The alert condition for Prometheus.'
def notes
object.ordered_notes
diff --git a/app/graphql/types/alert_management/integration_type.rb b/app/graphql/types/alert_management/integration_type.rb
index bf599885584..d26d7348765 100644
--- a/app/graphql/types/alert_management/integration_type.rb
+++ b/app/graphql/types/alert_management/integration_type.rb
@@ -9,37 +9,37 @@ module Types
field :id,
GraphQL::ID_TYPE,
null: false,
- description: 'ID of the integration'
+ description: 'ID of the integration.'
field :type,
AlertManagement::IntegrationTypeEnum,
null: false,
- description: 'Type of integration'
+ description: 'Type of integration.'
field :name,
GraphQL::STRING_TYPE,
null: true,
- description: 'Name of the integration'
+ description: 'Name of the integration.'
field :active,
GraphQL::BOOLEAN_TYPE,
null: true,
- description: 'Whether the endpoint is currently accepting alerts'
+ description: 'Whether the endpoint is currently accepting alerts.'
field :token,
GraphQL::STRING_TYPE,
null: true,
- description: 'Token used to authenticate alert notification requests'
+ description: 'Token used to authenticate alert notification requests.'
field :url,
GraphQL::STRING_TYPE,
null: true,
- description: 'Endpoint which accepts alert notifications'
+ description: 'Endpoint which accepts alert notifications.'
field :api_url,
GraphQL::STRING_TYPE,
null: true,
- description: 'URL at which Prometheus metrics can be queried to populate the metrics dashboard'
+ description: 'URL at which Prometheus metrics can be queried to populate the metrics dashboard.'
definition_methods do
def resolve_type(object, context)
diff --git a/app/graphql/types/award_emojis/award_emoji_type.rb b/app/graphql/types/award_emojis/award_emoji_type.rb
index cd7a2f34ba6..9409304e28f 100644
--- a/app/graphql/types/award_emojis/award_emoji_type.rb
+++ b/app/graphql/types/award_emojis/award_emoji_type.rb
@@ -13,32 +13,32 @@ module Types
field :name,
GraphQL::STRING_TYPE,
null: false,
- description: 'The emoji name'
+ description: 'The emoji name.'
field :description,
GraphQL::STRING_TYPE,
null: false,
- description: 'The emoji description'
+ description: 'The emoji description.'
field :unicode,
GraphQL::STRING_TYPE,
null: false,
- description: 'The emoji in unicode'
+ description: 'The emoji in Unicode.'
field :emoji,
GraphQL::STRING_TYPE,
null: false,
- description: 'The emoji as an icon'
+ description: 'The emoji as an icon.'
field :unicode_version,
GraphQL::STRING_TYPE,
null: false,
- description: 'The unicode version for this emoji'
+ description: 'The Unicode version for this emoji.'
field :user,
Types::UserType,
null: false,
- description: 'The user who awarded the emoji'
+ description: 'The user who awarded the emoji.'
def user
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.user_id).find
diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb
index cbd45b46dd6..4d470aceca4 100644
--- a/app/graphql/types/base_enum.rb
+++ b/app/graphql/types/base_enum.rb
@@ -21,7 +21,7 @@ module Types
graphql_name(enum_mod.name) if use_name
description(enum_mod.description) if use_description
- enum_mod.definition.each { |key, content| value(key.to_s.upcase, content) }
+ enum_mod.definition.each { |key, content| value(key.to_s.upcase, **content) }
end
def value(*args, **kwargs, &block)
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index c4ce2cecd8b..f145b9d45c3 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -30,7 +30,7 @@ module Types
def resolve_field(obj, args, ctx)
ctx.schema.after_lazy(obj) do |after_obj|
query_ctx = ctx.query.context
- inner_obj = after_obj && after_obj.object
+ inner_obj = after_obj&.object
ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
if authorized?(inner_obj, ruby_args, query_ctx)
diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb
index 7999e77eb30..46b49c5d8a4 100644
--- a/app/graphql/types/board_list_type.rb
+++ b/app/graphql/types/board_list_type.rb
@@ -9,22 +9,22 @@ module Types
description 'Represents a list for an issue board'
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID (global ID) of the list'
+ description: 'ID (global ID) of the list.'
field :title, GraphQL::STRING_TYPE, null: false,
- description: 'Title of the list'
+ description: 'Title of the list.'
field :list_type, GraphQL::STRING_TYPE, null: false,
- description: 'Type of the list'
+ description: 'Type of the list.'
field :position, GraphQL::INT_TYPE, null: true,
- description: 'Position of list within the board'
+ description: 'Position of list within the board.'
field :label, Types::LabelType, null: true,
- description: 'Label of the list'
+ description: 'Label of the list.'
field :collapsed, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if list is collapsed for this user'
+ description: 'Indicates if list is collapsed for this user.'
field :issues_count, GraphQL::INT_TYPE, null: true,
- description: 'Count of issues in the list'
+ description: 'Count of issues in the list.'
field :issues, ::Types::IssueType.connection_type, null: true,
- description: 'Board issues',
+ description: 'Board issues.',
resolver: ::Resolvers::BoardListIssuesResolver
def issues_count
diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb
index f576fd83840..f8bd31d5fa0 100644
--- a/app/graphql/types/board_type.rb
+++ b/app/graphql/types/board_type.rb
@@ -10,20 +10,20 @@ module Types
present_using BoardPresenter
field :id, type: GraphQL::ID_TYPE, null: false,
- description: 'ID (global ID) of the board'
+ description: 'ID (global ID) of the board.'
field :name, type: GraphQL::STRING_TYPE, null: true,
- description: 'Name of the board'
+ description: 'Name of the board.'
field :hide_backlog_list, type: GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Whether or not backlog list is hidden'
+ description: 'Whether or not backlog list is hidden.'
field :hide_closed_list, type: GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Whether or not closed list is hidden'
+ description: 'Whether or not closed list is hidden.'
field :lists,
Types::BoardListType.connection_type,
null: true,
- description: 'Lists of the board',
+ description: 'Lists of the board.',
resolver: Resolvers::BoardListsResolver,
extras: [:lookahead]
diff --git a/app/graphql/types/boards/board_issue_input_base_type.rb b/app/graphql/types/boards/board_issue_input_base_type.rb
index 1187b3352cd..dab1414760b 100644
--- a/app/graphql/types/boards/board_issue_input_base_type.rb
+++ b/app/graphql/types/boards/board_issue_input_base_type.rb
@@ -6,27 +6,27 @@ module Types
class BoardIssueInputBaseType < BaseInputObject
argument :label_name, GraphQL::STRING_TYPE.to_list_type,
required: false,
- description: 'Filter by label name'
+ description: 'Filter by label name.'
argument :milestone_title, GraphQL::STRING_TYPE,
required: false,
- description: 'Filter by milestone title'
+ description: 'Filter by milestone title.'
argument :assignee_username, GraphQL::STRING_TYPE.to_list_type,
required: false,
- description: 'Filter by assignee username'
+ description: 'Filter by assignee username.'
argument :author_username, GraphQL::STRING_TYPE,
required: false,
- description: 'Filter by author username'
+ description: 'Filter by author username.'
argument :release_tag, GraphQL::STRING_TYPE,
required: false,
- description: 'Filter by release tag'
+ description: 'Filter by release tag.'
argument :my_reaction_emoji, GraphQL::STRING_TYPE,
required: false,
- description: 'Filter by reaction emoji'
+ description: 'Filter by reaction emoji.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb
index 40d065d8ea9..62a402ee724 100644
--- a/app/graphql/types/boards/board_issue_input_type.rb
+++ b/app/graphql/types/boards/board_issue_input_type.rb
@@ -11,11 +11,11 @@ module Types
argument :not, NegatedBoardIssueInputType,
required: false,
- description: 'List of negated params. Warning: this argument is experimental and a subject to change in future'
+ description: 'List of negated params. Warning: this argument is experimental and a subject to change in future.'
argument :search, GraphQL::STRING_TYPE,
required: false,
- description: 'Search query for issue title or description'
+ description: 'Search query for issue title or description.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/branch_type.rb b/app/graphql/types/branch_type.rb
index b15038a46de..b788ba79769 100644
--- a/app/graphql/types/branch_type.rb
+++ b/app/graphql/types/branch_type.rb
@@ -8,11 +8,11 @@ module Types
field :name,
GraphQL::STRING_TYPE,
null: false,
- description: 'Name of the branch'
+ description: 'Name of the branch.'
field :commit, Types::CommitType,
null: true, resolver: Resolvers::BranchCommitResolver,
- description: 'Commit for the branch'
+ description: 'Commit for the branch.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/analytics_type.rb b/app/graphql/types/ci/analytics_type.rb
index c8b12c6a9b8..ba987b133bd 100644
--- a/app/graphql/types/ci/analytics_type.rb
+++ b/app/graphql/types/ci/analytics_type.rb
@@ -7,27 +7,27 @@ module Types
graphql_name 'PipelineAnalytics'
field :week_pipelines_totals, [GraphQL::INT_TYPE], null: true,
- description: 'Total weekly pipeline count'
+ description: 'Total weekly pipeline count.'
field :week_pipelines_successful, [GraphQL::INT_TYPE], null: true,
- description: 'Total weekly successful pipeline count'
+ description: 'Total weekly successful pipeline count.'
field :week_pipelines_labels, [GraphQL::STRING_TYPE], null: true,
- description: 'Labels for the weekly pipeline count'
+ description: 'Labels for the weekly pipeline count.'
field :month_pipelines_totals, [GraphQL::INT_TYPE], null: true,
- description: 'Total monthly pipeline count'
+ description: 'Total monthly pipeline count.'
field :month_pipelines_successful, [GraphQL::INT_TYPE], null: true,
- description: 'Total monthly successful pipeline count'
+ description: 'Total monthly successful pipeline count.'
field :month_pipelines_labels, [GraphQL::STRING_TYPE], null: true,
- description: 'Labels for the monthly pipeline count'
+ description: 'Labels for the monthly pipeline count.'
field :year_pipelines_totals, [GraphQL::INT_TYPE], null: true,
- description: 'Total yearly pipeline count'
+ description: 'Total yearly pipeline count.'
field :year_pipelines_successful, [GraphQL::INT_TYPE], null: true,
- description: 'Total yearly successful pipeline count'
+ description: 'Total yearly successful pipeline count.'
field :year_pipelines_labels, [GraphQL::STRING_TYPE], null: true,
- description: 'Labels for the yearly pipeline count'
+ description: 'Labels for the yearly pipeline count.'
field :pipeline_times_values, [GraphQL::INT_TYPE], null: true,
- description: 'Pipeline times'
+ description: 'Pipeline times.'
field :pipeline_times_labels, [GraphQL::STRING_TYPE], null: true,
- description: 'Pipeline times labels'
+ description: 'Pipeline times labels.'
end
end
end
diff --git a/app/graphql/types/ci/application_setting_type.rb b/app/graphql/types/ci/application_setting_type.rb
new file mode 100644
index 00000000000..8616280057c
--- /dev/null
+++ b/app/graphql/types/ci/application_setting_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class ApplicationSettingType < BaseObject
+ graphql_name 'CiApplicationSettings'
+
+ authorize :read_application_setting
+
+ field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true,
+ description: 'Whether to keep the latest jobs artifacts.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb
index e80771cdf9d..b34a91446a2 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -14,7 +14,8 @@ module Types
description: 'Whether merge trains are enabled.',
method: :merge_trains_enabled?
field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Whether to keep the latest builds artifacts.'
+ description: 'Whether to keep the latest builds artifacts.',
+ method: :keep_latest_artifacts_available?
field :project, Types::ProjectType, null: true,
description: 'Project the CI/CD settings belong to.'
end
diff --git a/app/graphql/types/ci/config/config_type.rb b/app/graphql/types/ci/config/config_type.rb
index 29093c6d3c9..88caf21c376 100644
--- a/app/graphql/types/ci/config/config_type.rb
+++ b/app/graphql/types/ci/config/config_type.rb
@@ -8,13 +8,13 @@ module Types
graphql_name 'CiConfig'
field :errors, [GraphQL::STRING_TYPE], null: true,
- description: 'Linting errors'
+ description: 'Linting errors.'
field :merged_yaml, GraphQL::STRING_TYPE, null: true,
- description: 'Merged CI config YAML'
+ description: 'Merged CI configuration YAML.'
field :stages, Types::Ci::Config::StageType.connection_type, null: true,
- description: 'Stages of the pipeline'
+ description: 'Stages of the pipeline.'
field :status, Types::Ci::Config::StatusEnum, null: true,
- description: 'Status of linting, can be either valid or invalid'
+ description: 'Status of linting, can be either valid or invalid.'
end
end
end
diff --git a/app/graphql/types/ci/config/group_type.rb b/app/graphql/types/ci/config/group_type.rb
index 8e133bbcba8..11be701e73f 100644
--- a/app/graphql/types/ci/config/group_type.rb
+++ b/app/graphql/types/ci/config/group_type.rb
@@ -8,11 +8,11 @@ module Types
graphql_name 'CiConfigGroup'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the job group'
+ description: 'Name of the job group.'
field :jobs, Types::Ci::Config::JobType.connection_type, null: true,
- description: 'Jobs in group'
+ description: 'Jobs in group.'
field :size, GraphQL::INT_TYPE, null: true,
- description: 'Size of the job group'
+ description: 'Size of the job group.'
end
end
end
diff --git a/app/graphql/types/ci/config/need_type.rb b/app/graphql/types/ci/config/need_type.rb
index a442450b9ae..01f73100409 100644
--- a/app/graphql/types/ci/config/need_type.rb
+++ b/app/graphql/types/ci/config/need_type.rb
@@ -8,7 +8,7 @@ module Types
graphql_name 'CiConfigNeed'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the need'
+ description: 'Name of the need.'
end
end
end
diff --git a/app/graphql/types/ci/config/stage_type.rb b/app/graphql/types/ci/config/stage_type.rb
index 2008c553629..060efb7d45c 100644
--- a/app/graphql/types/ci/config/stage_type.rb
+++ b/app/graphql/types/ci/config/stage_type.rb
@@ -8,9 +8,9 @@ module Types
graphql_name 'CiConfigStage'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the stage'
+ description: 'Name of the stage.'
field :groups, Types::Ci::Config::GroupType.connection_type, null: true,
- description: 'Groups of jobs for the stage'
+ description: 'Groups of jobs for the stage.'
end
end
end
diff --git a/app/graphql/types/ci/detailed_status_type.rb b/app/graphql/types/ci/detailed_status_type.rb
index 80d73e9b174..0b643a6b676 100644
--- a/app/graphql/types/ci/detailed_status_type.rb
+++ b/app/graphql/types/ci/detailed_status_type.rb
@@ -7,26 +7,27 @@ module Types
graphql_name 'DetailedStatus'
field :group, GraphQL::STRING_TYPE, null: true,
- description: 'Group of the status'
+ description: 'Group of the status.'
field :icon, GraphQL::STRING_TYPE, null: true,
- description: 'Icon of the status'
+ description: 'Icon of the status.'
field :favicon, GraphQL::STRING_TYPE, null: true,
- description: 'Favicon of the status'
+ description: 'Favicon of the status.'
field :details_path, GraphQL::STRING_TYPE, null: true,
- description: 'Path of the details for the status'
+ description: 'Path of the details for the status.'
field :has_details, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if the status has further details',
+ description: 'Indicates if the status has further details.',
method: :has_details?
field :label, GraphQL::STRING_TYPE, null: true,
- description: 'Label of the status'
+ calls_gitaly: true,
+ description: 'Label of the status.'
field :text, GraphQL::STRING_TYPE, null: true,
- description: 'Text of the status'
+ description: 'Text of the status.'
field :tooltip, GraphQL::STRING_TYPE, null: true,
- description: 'Tooltip associated with the status',
+ description: 'Tooltip associated with the status.',
method: :status_tooltip
field :action, Types::Ci::StatusActionType, null: true,
- calls_gitaly: true,
- description: 'Action information for the status. This includes method, button title, icon, path, and title'
+ calls_gitaly: true,
+ description: 'Action information for the status. This includes method, button title, icon, path, and title.'
def action
if object.has_action?
diff --git a/app/graphql/types/ci/group_type.rb b/app/graphql/types/ci/group_type.rb
index 03fd50d5dbb..d6d4252e8d7 100644
--- a/app/graphql/types/ci/group_type.rb
+++ b/app/graphql/types/ci/group_type.rb
@@ -7,13 +7,13 @@ module Types
graphql_name 'CiGroup'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the job group'
+ description: 'Name of the job group.'
field :size, GraphQL::INT_TYPE, null: true,
- description: 'Size of the group'
+ description: 'Size of the group.'
field :jobs, Ci::JobType.connection_type, null: true,
- description: 'Jobs in group'
+ description: 'Jobs in group.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the group'
+ description: 'Detailed status of the group.'
def detailed_status
object.detailed_status(context[:current_user])
diff --git a/app/graphql/types/ci/job_artifact_type.rb b/app/graphql/types/ci/job_artifact_type.rb
index c34a12dcc61..7dc93041b53 100644
--- a/app/graphql/types/ci/job_artifact_type.rb
+++ b/app/graphql/types/ci/job_artifact_type.rb
@@ -7,10 +7,10 @@ module Types
graphql_name 'CiJobArtifact'
field :download_path, GraphQL::STRING_TYPE, null: true,
- description: "URL for downloading the artifact's file"
+ description: "URL for downloading the artifact's file."
field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true,
- description: 'File type of the artifact'
+ description: 'File type of the artifact.'
def download_path
::Gitlab::Routing.url_helpers.download_project_job_artifacts_path(
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index f8bf1732e63..ba463cdd9c1 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -7,17 +7,17 @@ module Types
authorize :read_commit_status
field :pipeline, Types::Ci::PipelineType, null: true,
- description: 'Pipeline the job belongs to'
+ description: 'Pipeline the job belongs to.'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the job'
+ description: 'Name of the job.'
field :needs, BuildNeedType.connection_type, null: true,
- description: 'References to builds that must complete before the jobs run'
+ description: 'References to builds that must complete before the jobs run.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the job'
+ description: 'Detailed status of the job.'
field :scheduled_at, Types::TimeType, null: true,
- description: 'Schedule for the build'
+ description: 'Schedule for the build.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
- description: 'Artifacts generated by the job'
+ description: 'Artifacts generated by the job.'
def pipeline
Gitlab::Graphql::Loaders::BatchModelLoader.new(::Ci::Pipeline, object.pipeline_id).find
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 4709d5e8dd6..2c386c9b564 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -8,94 +8,98 @@ module Types
connection_type_class(Types::CountableConnectionType)
authorize :read_pipeline
+ present_using ::Ci::PipelinePresenter
expose_permissions Types::PermissionTypes::Ci::Pipeline
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the pipeline'
+ description: 'ID of the pipeline.'
field :iid, GraphQL::STRING_TYPE, null: false,
- description: 'Internal ID of the pipeline'
+ description: 'Internal ID of the pipeline.'
field :sha, GraphQL::STRING_TYPE, null: false,
- description: "SHA of the pipeline's commit"
+ description: "SHA of the pipeline's commit."
field :before_sha, GraphQL::STRING_TYPE, null: true,
- description: 'Base SHA of the source branch'
+ description: 'Base SHA of the source branch.'
field :status, PipelineStatusEnum, null: false,
description: "Status of the pipeline (#{::Ci::Pipeline.all_state_names.compact.join(', ').upcase})"
+ field :warnings, GraphQL::BOOLEAN_TYPE, null: false, method: :has_warnings?,
+ description: "Indicates if a pipeline has warnings."
+
field :detailed_status, Types::Ci::DetailedStatusType, null: false,
- description: 'Detailed status of the pipeline'
+ description: 'Detailed status of the pipeline.'
field :config_source, PipelineConfigSourceEnum, null: true,
- description: "Config source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})"
+ description: "Configuration source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})"
field :duration, GraphQL::INT_TYPE, null: true,
- description: 'Duration of the pipeline in seconds'
+ description: 'Duration of the pipeline in seconds.'
field :coverage, GraphQL::FLOAT_TYPE, null: true,
- description: 'Coverage percentage'
+ description: 'Coverage percentage.'
field :created_at, Types::TimeType, null: false,
- description: "Timestamp of the pipeline's creation"
+ description: "Timestamp of the pipeline's creation."
field :updated_at, Types::TimeType, null: false,
- description: "Timestamp of the pipeline's last activity"
+ description: "Timestamp of the pipeline's last activity."
field :started_at, Types::TimeType, null: true,
- description: 'Timestamp when the pipeline was started'
+ description: 'Timestamp when the pipeline was started.'
field :finished_at, Types::TimeType, null: true,
- description: "Timestamp of the pipeline's completion"
+ description: "Timestamp of the pipeline's completion."
field :committed_at, Types::TimeType, null: true,
- description: "Timestamp of the pipeline's commit"
+ description: "Timestamp of the pipeline's commit."
field :stages, Types::Ci::StageType.connection_type, null: true,
- description: 'Stages of the pipeline',
+ description: 'Stages of the pipeline.',
extras: [:lookahead],
resolver: Resolvers::Ci::PipelineStagesResolver
field :user, Types::UserType, null: true,
- description: 'Pipeline user'
+ description: 'Pipeline user.'
field :retryable, GraphQL::BOOLEAN_TYPE,
- description: 'Specifies if a pipeline can be retried',
+ description: 'Specifies if a pipeline can be retried.',
method: :retryable?,
null: false
field :cancelable, GraphQL::BOOLEAN_TYPE,
- description: 'Specifies if a pipeline can be canceled',
+ description: 'Specifies if a pipeline can be canceled.',
method: :cancelable?,
null: false
field :jobs,
::Types::Ci::JobType.connection_type,
null: true,
- description: 'Jobs belonging to the pipeline',
+ description: 'Jobs belonging to the pipeline.',
resolver: ::Resolvers::Ci::JobsResolver
field :source_job, Types::Ci::JobType, null: true,
- description: 'Job where pipeline was triggered from'
+ description: 'Job where pipeline was triggered from.'
field :downstream, Types::Ci::PipelineType.connection_type, null: true,
- description: 'Pipelines this pipeline will trigger',
+ description: 'Pipelines this pipeline will trigger.',
method: :triggered_pipelines_with_preloads
field :upstream, Types::Ci::PipelineType, null: true,
- description: 'Pipeline that triggered the pipeline',
+ description: 'Pipeline that triggered the pipeline.',
method: :triggered_by_pipeline
field :path, GraphQL::STRING_TYPE, null: true,
- description: "Relative path to the pipeline's page"
+ description: "Relative path to the pipeline's page."
field :project, Types::ProjectType, null: true,
- description: 'Project the pipeline belongs to'
+ description: 'Project the pipeline belongs to.'
field :active, GraphQL::BOOLEAN_TYPE, null: false, method: :active?,
- description: 'Indicates if the pipeline is active'
+ description: 'Indicates if the pipeline is active.'
def detailed_status
object.detailed_status(context[:current_user])
diff --git a/app/graphql/types/ci/runner_architecture_type.rb b/app/graphql/types/ci/runner_architecture_type.rb
index 526348abd9d..229974d4d13 100644
--- a/app/graphql/types/ci/runner_architecture_type.rb
+++ b/app/graphql/types/ci/runner_architecture_type.rb
@@ -7,9 +7,9 @@ module Types
graphql_name 'RunnerArchitecture'
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Name of the runner platform architecture'
+ description: 'Name of the runner platform architecture.'
field :download_location, GraphQL::STRING_TYPE, null: false,
- description: 'Download location for the runner for the platform architecture'
+ description: 'Download location for the runner for the platform architecture.'
end
end
end
diff --git a/app/graphql/types/ci/runner_platform_type.rb b/app/graphql/types/ci/runner_platform_type.rb
index 64719bc4908..5636f88835e 100644
--- a/app/graphql/types/ci/runner_platform_type.rb
+++ b/app/graphql/types/ci/runner_platform_type.rb
@@ -7,11 +7,11 @@ module Types
graphql_name 'RunnerPlatform'
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Name slug of the runner platform'
+ description: 'Name slug of the runner platform.'
field :human_readable_name, GraphQL::STRING_TYPE, null: false,
- description: 'Human readable name of the runner platform'
+ description: 'Human readable name of the runner platform.'
field :architectures, Types::Ci::RunnerArchitectureType.connection_type, null: true,
- description: 'Runner architectures supported for the platform'
+ description: 'Runner architectures supported for the platform.'
end
end
end
diff --git a/app/graphql/types/ci/runner_setup_type.rb b/app/graphql/types/ci/runner_setup_type.rb
index 66abcf65adf..61a2ea2a411 100644
--- a/app/graphql/types/ci/runner_setup_type.rb
+++ b/app/graphql/types/ci/runner_setup_type.rb
@@ -7,9 +7,9 @@ module Types
graphql_name 'RunnerSetup'
field :install_instructions, GraphQL::STRING_TYPE, null: false,
- description: 'Instructions for installing the runner on the specified architecture'
+ description: 'Instructions for installing the runner on the specified architecture.'
field :register_instructions, GraphQL::STRING_TYPE, null: true,
- description: 'Instructions for registering the runner'
+ description: 'Instructions for registering the runner.'
end
end
end
diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb
index 695e7c61bd9..836f2430890 100644
--- a/app/graphql/types/ci/stage_type.rb
+++ b/app/graphql/types/ci/stage_type.rb
@@ -7,12 +7,12 @@ module Types
graphql_name 'CiStage'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the stage'
+ description: 'Name of the stage.'
field :groups, Ci::GroupType.connection_type, null: true,
extras: [:lookahead],
- description: 'Group of jobs for the stage'
+ description: 'Group of jobs for the stage.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the stage'
+ description: 'Detailed status of the stage.'
def detailed_status
object.detailed_status(context[:current_user])
diff --git a/app/graphql/types/ci/status_action_type.rb b/app/graphql/types/ci/status_action_type.rb
index 08cbb6d3b59..9f7299c0270 100644
--- a/app/graphql/types/ci/status_action_type.rb
+++ b/app/graphql/types/ci/status_action_type.rb
@@ -6,16 +6,16 @@ module Types
graphql_name 'StatusAction'
field :button_title, GraphQL::STRING_TYPE, null: true,
- description: 'Title for the button, for example: Retry this job'
+ description: 'Title for the button, for example: Retry this job.'
field :icon, GraphQL::STRING_TYPE, null: true,
- description: 'Icon used in the action button'
+ description: 'Icon used in the action button.'
field :method, GraphQL::STRING_TYPE, null: true,
- description: 'Method for the action, for example: :post',
+ description: 'Method for the action, for example: :post.',
resolver_method: :action_method
field :path, GraphQL::STRING_TYPE, null: true,
- description: 'Path for the action'
+ description: 'Path for the action.'
field :title, GraphQL::STRING_TYPE, null: true,
- description: 'Title for the action, for example: Retry'
+ description: 'Title for the action, for example: Retry.'
def action_method
object[:method]
diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb
new file mode 100644
index 00000000000..9835a7ef208
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ # rubocop: disable Graphql/AuthorizeTypes
+ class AnalyzersEntityInputType < BaseInputObject
+ graphql_name 'SastCiConfigurationAnalyzersEntityInput'
+ description 'Represents the analyzers entity in SAST CI configuration'
+
+ argument :name, GraphQL::STRING_TYPE, required: true,
+ description: 'Name of analyzer.'
+
+ argument :enabled, GraphQL::BOOLEAN_TYPE, required: true,
+ description: 'State of the analyzer.'
+
+ argument :variables, [::Types::CiConfiguration::Sast::EntityInputType],
+ description: 'List of variables for the analyzer.',
+ required: false
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb
new file mode 100644
index 00000000000..3c6202ca7e0
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ # rubocop: disable Graphql/AuthorizeTypes
+ class AnalyzersEntityType < BaseObject
+ graphql_name 'SastCiConfigurationAnalyzersEntity'
+ description 'Represents an analyzer entity in SAST CI configuration'
+
+ field :name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the analyzer.'
+
+ field :label, GraphQL::STRING_TYPE, null: true,
+ description: 'Analyzer label used in the config UI.'
+
+ field :enabled, GraphQL::BOOLEAN_TYPE, null: true,
+ description: 'Indicates whether an analyzer is enabled.'
+
+ field :description, GraphQL::STRING_TYPE, null: true,
+ description: 'Analyzer description that is displayed on the form.'
+
+ field :variables, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
+ description: 'List of supported variables.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/entity_input_type.rb b/app/graphql/types/ci_configuration/sast/entity_input_type.rb
new file mode 100644
index 00000000000..39b3efb3db8
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/entity_input_type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ # rubocop: disable Graphql/AuthorizeTypes
+ class EntityInputType < BaseInputObject
+ graphql_name 'SastCiConfigurationEntityInput'
+ description 'Represents an entity in SAST CI configuration'
+
+ argument :field, GraphQL::STRING_TYPE, required: true,
+ description: 'CI keyword of entity.'
+
+ argument :default_value, GraphQL::STRING_TYPE, required: true,
+ description: 'Default value that is used if value is empty.'
+
+ argument :value, GraphQL::STRING_TYPE, required: true,
+ description: 'Current value of the entity.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/entity_type.rb b/app/graphql/types/ci_configuration/sast/entity_type.rb
new file mode 100644
index 00000000000..eeb9025391f
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/entity_type.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ # rubocop: disable Graphql/AuthorizeTypes
+ class EntityType < BaseObject
+ graphql_name 'SastCiConfigurationEntity'
+ description 'Represents an entity in SAST CI configuration'
+
+ field :field, GraphQL::STRING_TYPE, null: true,
+ description: 'CI keyword of entity.'
+
+ field :label, GraphQL::STRING_TYPE, null: true,
+ description: 'Label for entity used in the form.'
+
+ field :type, GraphQL::STRING_TYPE, null: true,
+ description: 'Type of the field value.'
+
+ field :options, ::Types::CiConfiguration::Sast::OptionsEntityType.connection_type, null: true,
+ description: 'Different possible values of the field.'
+
+ field :default_value, GraphQL::STRING_TYPE, null: true,
+ description: 'Default value that is used if value is empty.'
+
+ field :description, GraphQL::STRING_TYPE, null: true,
+ description: 'Entity description that is displayed on the form.'
+
+ field :value, GraphQL::STRING_TYPE, null: true,
+ description: 'Current value of the entity.'
+
+ field :size, ::Types::CiConfiguration::Sast::UiComponentSizeEnum, null: true,
+ description: 'Size of the UI component.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/input_type.rb b/app/graphql/types/ci_configuration/sast/input_type.rb
new file mode 100644
index 00000000000..615436683f6
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/input_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ class InputType < BaseInputObject # rubocop:disable Graphql/AuthorizeTypes
+ graphql_name 'SastCiConfigurationInput'
+ description 'Represents a CI configuration of SAST'
+
+ argument :global, [::Types::CiConfiguration::Sast::EntityInputType],
+ description: 'List of global entities related to SAST configuration.',
+ required: false
+
+ argument :pipeline, [::Types::CiConfiguration::Sast::EntityInputType],
+ description: 'List of pipeline entities related to SAST configuration.',
+ required: false
+
+ argument :analyzers, [::Types::CiConfiguration::Sast::AnalyzersEntityInputType],
+ description: 'List of analyzers and related variables for the SAST configuration.',
+ required: false
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/options_entity_type.rb b/app/graphql/types/ci_configuration/sast/options_entity_type.rb
new file mode 100644
index 00000000000..86d104a7fda
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/options_entity_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ # rubocop: disable Graphql/AuthorizeTypes
+ class OptionsEntityType < BaseObject
+ graphql_name 'SastCiConfigurationOptionsEntity'
+ description 'Represents an entity for options in SAST CI configuration'
+
+ field :label, GraphQL::STRING_TYPE, null: true,
+ description: 'Label of option entity.'
+
+ field :value, GraphQL::STRING_TYPE, null: true,
+ description: 'Value of option entity.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/type.rb b/app/graphql/types/ci_configuration/sast/type.rb
new file mode 100644
index 00000000000..35d11584ac7
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/type.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ # rubocop: disable Graphql/AuthorizeTypes
+ class Type < BaseObject
+ graphql_name 'SastCiConfiguration'
+ description 'Represents a CI configuration of SAST'
+
+ field :global, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
+ description: 'List of global entities related to SAST configuration.'
+
+ field :pipeline, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
+ description: 'List of pipeline entities related to SAST configuration.'
+
+ field :analyzers, ::Types::CiConfiguration::Sast::AnalyzersEntityType.connection_type, null: true,
+ description: 'List of analyzers entities attached to SAST configuration.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb b/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb
new file mode 100644
index 00000000000..3a208f9d3e4
--- /dev/null
+++ b/app/graphql/types/ci_configuration/sast/ui_component_size_enum.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ module CiConfiguration
+ module Sast
+ class UiComponentSizeEnum < BaseEnum
+ graphql_name 'SastUiComponentSize'
+ description 'Size of UI component in SAST configuration page'
+
+ value 'SMALL'
+ value 'MEDIUM'
+ value 'LARGE'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/commit_action_type.rb b/app/graphql/types/commit_action_type.rb
index 7674abb11eb..e14e7157752 100644
--- a/app/graphql/types/commit_action_type.rb
+++ b/app/graphql/types/commit_action_type.rb
@@ -4,19 +4,19 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class CommitActionType < BaseInputObject
argument :action, type: Types::CommitActionModeEnum, required: true,
- description: 'The action to perform, create, delete, move, update, chmod'
+ description: 'The action to perform, create, delete, move, update, chmod.'
argument :file_path, type: GraphQL::STRING_TYPE, required: true,
- description: 'Full path to the file'
+ description: 'Full path to the file.'
argument :content, type: GraphQL::STRING_TYPE, required: false,
- description: 'Content of the file'
+ description: 'Content of the file.'
argument :previous_path, type: GraphQL::STRING_TYPE, required: false,
- description: 'Original full path to the file being moved'
+ description: 'Original full path to the file being moved.'
argument :last_commit_id, type: GraphQL::STRING_TYPE, required: false,
- description: 'Last known file commit ID'
+ description: 'Last known file commit ID.'
argument :execute_filemode, type: GraphQL::BOOLEAN_TYPE, required: false,
- description: 'Enables/disables the execute flag on the file'
+ description: 'Enables/disables the execute flag on the file.'
argument :encoding, type: Types::CommitEncodingEnum, required: false,
- description: 'Encoding of the file. Default is text'
+ description: 'Encoding of the file. Default is text.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index 37d19b4148b..d137901380b 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -9,39 +9,39 @@ module Types
present_using CommitPresenter
field :id, type: GraphQL::ID_TYPE, null: false,
- description: 'ID (global ID) of the commit'
+ description: 'ID (global ID) of the commit.'
field :sha, type: GraphQL::STRING_TYPE, null: false,
- description: 'SHA1 ID of the commit'
+ description: 'SHA1 ID of the commit.'
field :short_id, type: GraphQL::STRING_TYPE, null: false,
- description: 'Short SHA1 ID of the commit'
+ description: 'Short SHA1 ID of the commit.'
field :title, type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
- description: 'Title of the commit message'
+ description: 'Title of the commit message.'
markdown_field :title_html, null: true
field :description, type: GraphQL::STRING_TYPE, null: true,
- description: 'Description of the commit message'
+ description: 'Description of the commit message.'
markdown_field :description_html, null: true
field :message, type: GraphQL::STRING_TYPE, null: true,
- description: 'Raw commit message'
+ description: 'Raw commit message.'
field :authored_date, type: Types::TimeType, null: true,
- description: 'Timestamp of when the commit was authored'
+ description: 'Timestamp of when the commit was authored.'
field :web_url, type: GraphQL::STRING_TYPE, null: false,
- description: 'Web URL of the commit'
+ description: 'Web URL of the commit.'
field :web_path, type: GraphQL::STRING_TYPE, null: false,
- description: 'Web path of the commit'
+ description: 'Web path of the commit.'
field :signature_html, type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
- description: 'Rendered HTML of the commit signature'
+ description: 'Rendered HTML of the commit signature.'
field :author_name, type: GraphQL::STRING_TYPE, null: true,
- description: 'Commit authors name'
+ description: 'Commit authors name.'
field :author_gravatar, type: GraphQL::STRING_TYPE, null: true,
- description: 'Commit authors gravatar'
+ description: 'Commit authors gravatar.'
# models/commit lazy loads the author by email
field :author, type: Types::UserType, null: true,
- description: 'Author of the commit'
+ description: 'Author of the commit.'
field :pipelines,
null: true,
- description: 'Pipelines of the commit ordered latest first',
+ description: 'Pipelines of the commit ordered latest first.',
resolver: Resolvers::CommitPipelinesResolver
def author_gravatar
diff --git a/app/graphql/types/container_expiration_policy_type.rb b/app/graphql/types/container_expiration_policy_type.rb
index f19aa964377..2b01474617a 100644
--- a/app/graphql/types/container_expiration_policy_type.rb
+++ b/app/graphql/types/container_expiration_policy_type.rb
@@ -8,14 +8,14 @@ module Types
authorize :destroy_container_image
- field :created_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was created'
- field :updated_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was updated'
- field :enabled, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether this container expiration policy is enabled'
- field :older_than, Types::ContainerExpirationPolicyOlderThanEnum, null: true, description: 'Tags older that this will expire'
- field :cadence, Types::ContainerExpirationPolicyCadenceEnum, null: false, description: 'This container expiration policy schedule'
- field :keep_n, Types::ContainerExpirationPolicyKeepEnum, null: true, description: 'Number of tags to retain'
- field :name_regex, Types::UntrustedRegexp, null: true, description: 'Tags with names matching this regex pattern will expire'
- field :name_regex_keep, Types::UntrustedRegexp, null: true, description: 'Tags with names matching this regex pattern will be preserved'
- field :next_run_at, Types::TimeType, null: true, description: 'Next time that this container expiration policy will get executed'
+ field :created_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was created.'
+ field :updated_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was updated.'
+ field :enabled, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether this container expiration policy is enabled.'
+ field :older_than, Types::ContainerExpirationPolicyOlderThanEnum, null: true, description: 'Tags older that this will expire.'
+ field :cadence, Types::ContainerExpirationPolicyCadenceEnum, null: false, description: 'This container expiration policy schedule.'
+ field :keep_n, Types::ContainerExpirationPolicyKeepEnum, null: true, description: 'Number of tags to retain.'
+ field :name_regex, Types::UntrustedRegexp, null: true, description: 'Tags with names matching this regex pattern will expire.'
+ field :name_regex_keep, Types::UntrustedRegexp, null: true, description: 'Tags with names matching this regex pattern will be preserved.'
+ field :next_run_at, Types::TimeType, null: true, description: 'Next time that this container expiration policy will get executed.'
end
end
diff --git a/app/graphql/types/container_repository_details_type.rb b/app/graphql/types/container_repository_details_type.rb
index 34523f3ea4a..1a9f57e701f 100644
--- a/app/graphql/types/container_repository_details_type.rb
+++ b/app/graphql/types/container_repository_details_type.rb
@@ -11,7 +11,7 @@ module Types
field :tags,
Types::ContainerRepositoryTagType.connection_type,
null: true,
- description: 'Tags of the container repository',
+ description: 'Tags of the container repository.',
max_page_size: 20
def can_delete
diff --git a/app/graphql/types/container_repository_sort_enum.rb b/app/graphql/types/container_repository_sort_enum.rb
new file mode 100644
index 00000000000..96210c0546b
--- /dev/null
+++ b/app/graphql/types/container_repository_sort_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositorySortEnum < SortEnum
+ graphql_name 'ContainerRepositorySort'
+ description 'Values for sorting container repositories'
+
+ value 'NAME_ASC', 'Name by ascending order', value: :name_asc
+ value 'NAME_DESC', 'Name by descending order', value: :name_desc
+ end
+end
diff --git a/app/graphql/types/container_repository_type.rb b/app/graphql/types/container_repository_type.rb
index 8735f8a173d..48c2b9f460f 100644
--- a/app/graphql/types/container_repository_type.rb
+++ b/app/graphql/types/container_repository_type.rb
@@ -19,7 +19,7 @@ module Types
field :status, Types::ContainerRepositoryStatusEnum, null: true, description: 'Status of the container repository.'
field :tags_count, GraphQL::INT_TYPE, null: false, description: 'Number of tags associated with this image.'
field :can_delete, GraphQL::BOOLEAN_TYPE, null: false, description: 'Can the current user delete the container repository.'
- field :project, Types::ProjectType, null: false, description: 'Project of the container registry'
+ field :project, Types::ProjectType, null: false, description: 'Project of the container registry.'
def can_delete
Ability.allowed?(current_user, :update_container_image, object)
diff --git a/app/graphql/types/countable_connection_type.rb b/app/graphql/types/countable_connection_type.rb
index f67194d99b3..0a9699a4570 100644
--- a/app/graphql/types/countable_connection_type.rb
+++ b/app/graphql/types/countable_connection_type.rb
@@ -4,7 +4,7 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class CountableConnectionType < GraphQL::Types::Relay::BaseConnection
field :count, GraphQL::INT_TYPE, null: false,
- description: 'Total count of collection'
+ description: 'Total count of collection.'
def count
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/graphql/types/current_user_todos.rb b/app/graphql/types/current_user_todos.rb
index e610286c1a9..79a430af1d7 100644
--- a/app/graphql/types/current_user_todos.rb
+++ b/app/graphql/types/current_user_todos.rb
@@ -8,10 +8,10 @@ module Types
field_class Types::BaseField
field :current_user_todos, Types::TodoType.connection_type,
- description: 'Todos for the current user',
+ description: 'To-do items for the current user.',
null: false do
argument :state, Types::TodoStateEnum,
- description: 'State of the todos',
+ description: 'State of the to-do items.',
required: false
end
diff --git a/app/graphql/types/custom_emoji_type.rb b/app/graphql/types/custom_emoji_type.rb
index f7d1a7800bc..246b60ce184 100644
--- a/app/graphql/types/custom_emoji_type.rb
+++ b/app/graphql/types/custom_emoji_type.rb
@@ -9,19 +9,19 @@ module Types
field :id, ::Types::GlobalIDType[::CustomEmoji],
null: false,
- description: 'The ID of the emoji'
+ description: 'The ID of the emoji.'
field :name, GraphQL::STRING_TYPE,
null: false,
- description: 'The name of the emoji'
+ description: 'The name of the emoji.'
field :url, GraphQL::STRING_TYPE,
null: false,
method: :file,
- description: 'The link to file of the emoji'
+ description: 'The link to file of the emoji.'
field :external, GraphQL::BOOLEAN_TYPE,
null: false,
- description: 'Whether the emoji is an external link'
+ description: 'Whether the emoji is an external link.'
end
end
diff --git a/app/graphql/types/design_management/design_at_version_type.rb b/app/graphql/types/design_management/design_at_version_type.rb
index e10a0de1715..4240b8f3aae 100644
--- a/app/graphql/types/design_management/design_at_version_type.rb
+++ b/app/graphql/types/design_management/design_at_version_type.rb
@@ -18,12 +18,12 @@ module Types
field :version,
Types::DesignManagement::VersionType,
null: false,
- description: 'The version this design-at-versions is pinned to'
+ description: 'The version this design-at-versions is pinned to.'
field :design,
Types::DesignManagement::DesignType,
null: false,
- description: 'The underlying design'
+ description: 'The underlying design.'
def cached_stateful_version(_parent)
version
diff --git a/app/graphql/types/design_management/design_collection_type.rb b/app/graphql/types/design_management/design_collection_type.rb
index 26fbac15b30..570eac907f3 100644
--- a/app/graphql/types/design_management/design_collection_type.rb
+++ b/app/graphql/types/design_management/design_collection_type.rb
@@ -9,40 +9,40 @@ module Types
authorize :read_design
field :project, Types::ProjectType, null: false,
- description: 'Project associated with the design collection'
+ description: 'Project associated with the design collection.'
field :issue, Types::IssueType, null: false,
- description: 'Issue associated with the design collection'
+ description: 'Issue associated with the design collection.'
field :designs,
Types::DesignManagement::DesignType.connection_type,
null: false,
resolver: Resolvers::DesignManagement::DesignsResolver,
- description: 'All designs for the design collection',
+ description: 'All designs for the design collection.',
complexity: 5
field :versions,
Types::DesignManagement::VersionType.connection_type,
resolver: Resolvers::DesignManagement::VersionsResolver,
- description: 'All versions related to all designs, ordered newest first'
+ description: 'All versions related to all designs, ordered newest first.'
field :version,
Types::DesignManagement::VersionType,
resolver: Resolvers::DesignManagement::VersionsResolver.single,
- description: 'A specific version'
+ description: 'A specific version.'
field :design_at_version, ::Types::DesignManagement::DesignAtVersionType,
null: true,
resolver: ::Resolvers::DesignManagement::DesignAtVersionResolver,
- description: 'Find a design as of a version'
+ description: 'Find a design as of a version.'
field :design, ::Types::DesignManagement::DesignType,
null: true,
resolver: ::Resolvers::DesignManagement::DesignResolver,
- description: 'Find a specific design'
+ description: 'Find a specific design.'
field :copy_state, ::Types::DesignManagement::DesignCollectionCopyStateEnum,
null: true,
- description: 'Copy state of the design collection'
+ description: 'Copy state of the design collection.'
end
end
end
diff --git a/app/graphql/types/design_management/design_fields.rb b/app/graphql/types/design_management/design_fields.rb
index b03b3927392..b770e30f5be 100644
--- a/app/graphql/types/design_management/design_fields.rb
+++ b/app/graphql/types/design_management/design_fields.rb
@@ -7,12 +7,12 @@ module Types
field_class Types::BaseField
- field :id, GraphQL::ID_TYPE, description: 'The ID of this design', null: false
- field :project, Types::ProjectType, null: false, description: 'The project the design belongs to'
- field :issue, Types::IssueType, null: false, description: 'The issue the design belongs to'
- field :filename, GraphQL::STRING_TYPE, null: false, description: 'The filename of the design'
- field :full_path, GraphQL::STRING_TYPE, null: false, description: 'The full path to the design file'
- field :image, GraphQL::STRING_TYPE, null: false, extras: [:parent], description: 'The URL of the full-sized image'
+ field :id, GraphQL::ID_TYPE, description: 'The ID of this design.', null: false
+ field :project, Types::ProjectType, null: false, description: 'The project the design belongs to.'
+ field :issue, Types::IssueType, null: false, description: 'The issue the design belongs to.'
+ field :filename, GraphQL::STRING_TYPE, null: false, description: 'The filename of the design.'
+ field :full_path, GraphQL::STRING_TYPE, null: false, description: 'The full path to the design file.'
+ field :image, GraphQL::STRING_TYPE, null: false, extras: [:parent], description: 'The URL of the full-sized image.'
field :image_v432x230, GraphQL::STRING_TYPE, null: true, extras: [:parent],
description: 'The URL of the design resized to fit within the bounds of 432x230. ' \
'This will be `null` if the image has not been generated'
@@ -20,16 +20,16 @@ module Types
null: false,
calls_gitaly: true,
extras: [:parent],
- description: 'The diff refs for this design'
+ description: 'The diff refs for this design.'
field :event, Types::DesignManagement::DesignVersionEventEnum,
null: false,
extras: [:parent],
- description: 'How this design was changed in the current version'
+ description: 'How this design was changed in the current version.'
field :notes_count,
GraphQL::INT_TYPE,
null: false,
method: :user_notes_count,
- description: 'The total count of user-created notes for this design'
+ description: 'The total count of user-created notes for this design.'
def diff_refs(parent:)
version = cached_stateful_version(parent)
diff --git a/app/graphql/types/design_management/design_type.rb b/app/graphql/types/design_management/design_type.rb
index bab22015dc4..44e87905f92 100644
--- a/app/graphql/types/design_management/design_type.rb
+++ b/app/graphql/types/design_management/design_type.rb
@@ -17,7 +17,7 @@ module Types
field :versions,
Types::DesignManagement::VersionType.connection_type,
resolver: Resolvers::DesignManagement::VersionsResolver,
- description: "All versions related to this design ordered newest first",
+ description: "All versions related to this design ordered newest first.",
extras: [:parent]
# Returns a `DesignManagement::Version` for this query based on the
diff --git a/app/graphql/types/design_management/version_type.rb b/app/graphql/types/design_management/version_type.rb
index c774f5d1bdf..4bc71aef0f4 100644
--- a/app/graphql/types/design_management/version_type.rb
+++ b/app/graphql/types/design_management/version_type.rb
@@ -12,25 +12,25 @@ module Types
authorize :read_design
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the design version'
+ description: 'ID of the design version.'
field :sha, GraphQL::ID_TYPE, null: false,
- description: 'SHA of the design version'
+ description: 'SHA of the design version.'
field :designs,
::Types::DesignManagement::DesignType.connection_type,
null: false,
- description: 'All designs that were changed in the version'
+ description: 'All designs that were changed in the version.'
field :designs_at_version,
::Types::DesignManagement::DesignAtVersionType.connection_type,
null: false,
- description: 'All designs that are visible at this version, as of this version',
+ description: 'All designs that are visible at this version, as of this version.',
resolver: ::Resolvers::DesignManagement::Version::DesignsAtVersionResolver
field :design_at_version,
::Types::DesignManagement::DesignAtVersionType,
null: false,
- description: 'A particular design as of this version, provided it is visible at this version',
+ description: 'A particular design as of this version, provided it is visible at this version.',
resolver: ::Resolvers::DesignManagement::Version::DesignsAtVersionResolver.single
end
end
diff --git a/app/graphql/types/design_management_type.rb b/app/graphql/types/design_management_type.rb
index ec85b8a0c1f..be0fb8253ca 100644
--- a/app/graphql/types/design_management_type.rb
+++ b/app/graphql/types/design_management_type.rb
@@ -8,11 +8,11 @@ module Types
field :version, ::Types::DesignManagement::VersionType,
null: true,
resolver: ::Resolvers::DesignManagement::VersionResolver,
- description: 'Find a version'
+ description: 'Find a version.'
field :design_at_version, ::Types::DesignManagement::DesignAtVersionType,
null: true,
resolver: ::Resolvers::DesignManagement::DesignAtVersionResolver,
- description: 'Find a design as of a version'
+ description: 'Find a design as of a version.'
end
end
diff --git a/app/graphql/types/diff_paths_input_type.rb b/app/graphql/types/diff_paths_input_type.rb
index 43feddd9827..864cec1ab07 100644
--- a/app/graphql/types/diff_paths_input_type.rb
+++ b/app/graphql/types/diff_paths_input_type.rb
@@ -4,9 +4,9 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class DiffPathsInputType < BaseInputObject
argument :old_path, GraphQL::STRING_TYPE, required: false,
- description: 'The path of the file on the start sha'
+ description: 'The path of the file on the start sha.'
argument :new_path, GraphQL::STRING_TYPE, required: false,
- description: 'The path of the file on the head sha'
+ description: 'The path of the file on the head sha.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/diff_refs_type.rb b/app/graphql/types/diff_refs_type.rb
index 4049a204f66..3c8f934f1eb 100644
--- a/app/graphql/types/diff_refs_type.rb
+++ b/app/graphql/types/diff_refs_type.rb
@@ -7,11 +7,11 @@ module Types
graphql_name 'DiffRefs'
field :head_sha, GraphQL::STRING_TYPE, null: false,
- description: 'SHA of the HEAD at the time the comment was made'
+ description: 'SHA of the HEAD at the time the comment was made.'
field :base_sha, GraphQL::STRING_TYPE, null: true,
- description: 'Merge base of the branch the comment was made on'
+ description: 'Merge base of the branch the comment was made on.'
field :start_sha, GraphQL::STRING_TYPE, null: false,
- description: 'SHA of the branch being compared against'
+ description: 'SHA of the branch being compared against.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/diff_stats_summary_type.rb b/app/graphql/types/diff_stats_summary_type.rb
index 956400fd21b..78c0e2f2b4c 100644
--- a/app/graphql/types/diff_stats_summary_type.rb
+++ b/app/graphql/types/diff_stats_summary_type.rb
@@ -9,13 +9,13 @@ module Types
description 'Aggregated summary of changes'
field :additions, GraphQL::INT_TYPE, null: false,
- description: 'Number of lines added'
+ description: 'Number of lines added.'
field :deletions, GraphQL::INT_TYPE, null: false,
- description: 'Number of lines deleted'
+ description: 'Number of lines deleted.'
field :changes, GraphQL::INT_TYPE, null: false,
- description: 'Number of lines changed'
+ description: 'Number of lines changed.'
field :file_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of files changed'
+ description: 'Number of files changed.'
def changes
object[:additions] + object[:deletions]
diff --git a/app/graphql/types/diff_stats_type.rb b/app/graphql/types/diff_stats_type.rb
index 6c79a4c389d..8a6840e5a94 100644
--- a/app/graphql/types/diff_stats_type.rb
+++ b/app/graphql/types/diff_stats_type.rb
@@ -9,11 +9,11 @@ module Types
description 'Changes to a single file'
field :path, GraphQL::STRING_TYPE, null: false,
- description: 'File path, relative to repository root'
+ description: 'File path, relative to repository root.'
field :additions, GraphQL::INT_TYPE, null: false,
- description: 'Number of lines added to this file'
+ description: 'Number of lines added to this file.'
field :deletions, GraphQL::INT_TYPE, null: false,
- description: 'Number of lines deleted from this file'
+ description: 'Number of lines deleted from this file.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/environment_type.rb b/app/graphql/types/environment_type.rb
index e3885668643..2e6417f08ea 100644
--- a/app/graphql/types/environment_type.rb
+++ b/app/graphql/types/environment_type.rb
@@ -10,24 +10,24 @@ module Types
authorize :read_environment
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Human-readable name of the environment'
+ description: 'Human-readable name of the environment.'
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the environment'
+ description: 'ID of the environment.'
field :state, GraphQL::STRING_TYPE, null: false,
- description: 'State of the environment, for example: available/stopped'
+ description: 'State of the environment, for example: available/stopped.'
field :path, GraphQL::STRING_TYPE, null: false,
description: 'The path to the environment.'
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
- description: 'Metrics dashboard schema for the environment',
+ description: 'Metrics dashboard schema for the environment.',
resolver: Resolvers::Metrics::DashboardResolver
field :latest_opened_most_severe_alert,
Types::AlertManagement::AlertType,
null: true,
- description: 'The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned'
+ description: 'The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned.'
end
end
diff --git a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
index cfde9fa0d6a..59bd97e3448 100644
--- a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
+++ b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
@@ -12,93 +12,93 @@ module Types
field :id, GraphQL::ID_TYPE,
null: false,
- description: 'ID (global ID) of the error'
+ description: 'ID (global ID) of the error.'
field :sentry_id, GraphQL::STRING_TYPE,
method: :id,
null: false,
- description: 'ID (Sentry ID) of the error'
+ description: 'ID (Sentry ID) of the error.'
field :title, GraphQL::STRING_TYPE,
null: false,
- description: 'Title of the error'
+ description: 'Title of the error.'
field :type, GraphQL::STRING_TYPE,
null: false,
- description: 'Type of the error'
+ description: 'Type of the error.'
field :user_count, GraphQL::INT_TYPE,
null: false,
- description: 'Count of users affected by the error'
+ description: 'Count of users affected by the error.'
field :count, GraphQL::INT_TYPE,
null: false,
- description: 'Count of occurrences'
+ description: 'Count of occurrences.'
field :first_seen, Types::TimeType,
null: false,
- description: 'Timestamp when the error was first seen'
+ description: 'Timestamp when the error was first seen.'
field :last_seen, Types::TimeType,
null: false,
- description: 'Timestamp when the error was last seen'
+ description: 'Timestamp when the error was last seen.'
field :message, GraphQL::STRING_TYPE,
null: true,
- description: 'Sentry metadata message of the error'
+ description: 'Sentry metadata message of the error.'
field :culprit, GraphQL::STRING_TYPE,
null: false,
- description: 'Culprit of the error'
+ description: 'Culprit of the error.'
field :external_base_url, GraphQL::STRING_TYPE,
null: false,
- description: 'External Base URL of the Sentry Instance'
+ description: 'External Base URL of the Sentry Instance.'
field :external_url, GraphQL::STRING_TYPE,
null: false,
- description: 'External URL of the error'
+ description: 'External URL of the error.'
field :sentry_project_id, GraphQL::ID_TYPE,
method: :project_id,
null: false,
- description: 'ID of the project (Sentry project)'
+ description: 'ID of the project (Sentry project).'
field :sentry_project_name, GraphQL::STRING_TYPE,
method: :project_name,
null: false,
- description: 'Name of the project affected by the error'
+ description: 'Name of the project affected by the error.'
field :sentry_project_slug, GraphQL::STRING_TYPE,
method: :project_slug,
null: false,
- description: 'Slug of the project affected by the error'
+ description: 'Slug of the project affected by the error.'
field :short_id, GraphQL::STRING_TYPE,
null: false,
- description: 'Short ID (Sentry ID) of the error'
+ description: 'Short ID (Sentry ID) of the error.'
field :status, Types::ErrorTracking::SentryErrorStatusEnum,
null: false,
- description: 'Status of the error'
+ description: 'Status of the error.'
field :frequency, [Types::ErrorTracking::SentryErrorFrequencyType],
null: false,
- description: 'Last 24hr stats of the error'
+ description: 'Last 24hr stats of the error.'
field :first_release_last_commit, GraphQL::STRING_TYPE,
null: true,
- description: 'Commit the error was first seen'
+ description: 'Commit the error was first seen.'
field :last_release_last_commit, GraphQL::STRING_TYPE,
null: true,
- description: 'Commit the error was last seen'
+ description: 'Commit the error was last seen.'
field :first_release_short_version, GraphQL::STRING_TYPE,
null: true,
- description: 'Release short version the error was first seen'
+ description: 'Release short version the error was first seen.'
field :last_release_short_version, GraphQL::STRING_TYPE,
null: true,
- description: 'Release short version the error was last seen'
+ description: 'Release short version the error was last seen.'
field :first_release_version, GraphQL::STRING_TYPE,
null: true,
- description: 'Release version the error was first seen'
+ description: 'Release version the error was first seen.'
field :last_release_version, GraphQL::STRING_TYPE,
null: true,
- description: 'Release version the error was last seen'
+ description: 'Release version the error was last seen.'
field :gitlab_commit, GraphQL::STRING_TYPE,
null: true,
- description: 'GitLab commit SHA attributed to the Error based on the release version'
+ description: 'GitLab commit SHA attributed to the Error based on the release version.'
field :gitlab_commit_path, GraphQL::STRING_TYPE,
null: true,
- description: 'Path to the GitLab page for the GitLab commit attributed to the error'
+ description: 'Path to the GitLab page for the GitLab commit attributed to the error.'
field :gitlab_issue_path, GraphQL::STRING_TYPE,
method: :gitlab_issue,
null: true,
- description: 'URL of GitLab Issue'
+ description: 'URL of GitLab Issue.'
field :tags, Types::ErrorTracking::SentryErrorTagsType,
null: false,
- description: 'Tags associated with the Sentry Error'
+ description: 'Tags associated with the Sentry Error.'
end
end
end
diff --git a/app/graphql/types/error_tracking/sentry_error_collection_type.rb b/app/graphql/types/error_tracking/sentry_error_collection_type.rb
index 49d5d62c860..d3941b7c410 100644
--- a/app/graphql/types/error_tracking/sentry_error_collection_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_collection_type.rb
@@ -9,18 +9,18 @@ module Types
authorize :read_sentry_issue
field :errors,
- description: "Collection of Sentry Errors",
+ description: "Collection of Sentry Errors.",
resolver: Resolvers::ErrorTracking::SentryErrorsResolver
field :detailed_error,
- description: 'Detailed version of a Sentry error on the project',
+ description: 'Detailed version of a Sentry error on the project.',
resolver: Resolvers::ErrorTracking::SentryDetailedErrorResolver
field :error_stack_trace,
- description: 'Stack Trace of Sentry Error',
+ description: 'Stack Trace of Sentry Error.',
resolver: Resolvers::ErrorTracking::SentryErrorStackTraceResolver
field :external_url,
GraphQL::STRING_TYPE,
null: true,
- description: "External URL for Sentry"
+ description: "External URL for Sentry."
end
end
end
diff --git a/app/graphql/types/error_tracking/sentry_error_frequency_type.rb b/app/graphql/types/error_tracking/sentry_error_frequency_type.rb
index a44ca0684b6..05af1391af3 100644
--- a/app/graphql/types/error_tracking/sentry_error_frequency_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_frequency_type.rb
@@ -8,10 +8,10 @@ module Types
field :time, Types::TimeType,
null: false,
- description: "Time the error frequency stats were recorded"
+ description: "Time the error frequency stats were recorded."
field :count, GraphQL::INT_TYPE,
null: false,
- description: "Count of errors received since the previously recorded time"
+ description: "Count of errors received since the previously recorded time."
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb
index e6d02c948d5..0b3c4cf55b9 100644
--- a/app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb
@@ -10,11 +10,11 @@ module Types
field :line,
GraphQL::INT_TYPE,
null: false,
- description: 'Line number of the context'
+ description: 'Line number of the context.'
field :code,
GraphQL::STRING_TYPE,
null: false,
- description: 'Code number of the context'
+ description: 'Code number of the context.'
def line
object[0]
diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
index 2e6c40b233b..c9915d052f9 100644
--- a/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
@@ -9,19 +9,19 @@ module Types
field :function, GraphQL::STRING_TYPE,
null: true,
- description: 'Function in which the Sentry error occurred'
+ description: 'Function in which the Sentry error occurred.'
field :col, GraphQL::STRING_TYPE,
null: true,
- description: 'Function in which the Sentry error occurred'
+ description: 'Function in which the Sentry error occurred.'
field :line, GraphQL::STRING_TYPE,
null: true,
- description: 'Function in which the Sentry error occurred'
+ description: 'Function in which the Sentry error occurred.'
field :file_name, GraphQL::STRING_TYPE,
null: true,
- description: 'File in which the Sentry error occurred'
+ description: 'File in which the Sentry error occurred.'
field :trace_context, [Types::ErrorTracking::SentryErrorStackTraceContextType],
null: true,
- description: 'Context of the Sentry error'
+ description: 'Context of the Sentry error.'
def function
object['function']
diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
index 1bbe7e0c77b..52959a9329b 100644
--- a/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
@@ -10,13 +10,13 @@ module Types
field :issue_id, GraphQL::STRING_TYPE,
null: false,
- description: 'ID of the Sentry error'
+ description: 'ID of the Sentry error.'
field :date_received, GraphQL::STRING_TYPE,
null: false,
- description: 'Time the stack trace was received by Sentry'
+ description: 'Time the stack trace was received by Sentry.'
field :stack_trace_entries, [Types::ErrorTracking::SentryErrorStackTraceEntryType],
null: false,
- description: 'Stack trace entries for the Sentry error'
+ description: 'Stack trace entries for the Sentry error.'
end
end
end
diff --git a/app/graphql/types/error_tracking/sentry_error_tags_type.rb b/app/graphql/types/error_tracking/sentry_error_tags_type.rb
index e6d96571561..e2b051998c5 100644
--- a/app/graphql/types/error_tracking/sentry_error_tags_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_tags_type.rb
@@ -9,10 +9,10 @@ module Types
field :level, GraphQL::STRING_TYPE,
null: true,
- description: "Severity level of the Sentry Error"
+ description: "Severity level of the Sentry Error."
field :logger, GraphQL::STRING_TYPE,
null: true,
- description: "Logger of the Sentry Error"
+ description: "Logger of the Sentry Error."
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/error_tracking/sentry_error_type.rb b/app/graphql/types/error_tracking/sentry_error_type.rb
index 693ab0c4f8f..c0e09fb8c65 100644
--- a/app/graphql/types/error_tracking/sentry_error_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_type.rb
@@ -11,59 +11,59 @@ module Types
field :id, GraphQL::ID_TYPE,
null: false,
- description: 'ID (global ID) of the error'
+ description: 'ID (global ID) of the error.'
field :sentry_id, GraphQL::STRING_TYPE,
method: :id,
null: false,
- description: 'ID (Sentry ID) of the error'
+ description: 'ID (Sentry ID) of the error.'
field :first_seen, Types::TimeType,
null: false,
- description: 'Timestamp when the error was first seen'
+ description: 'Timestamp when the error was first seen.'
field :last_seen, Types::TimeType,
null: false,
- description: 'Timestamp when the error was last seen'
+ description: 'Timestamp when the error was last seen.'
field :title, GraphQL::STRING_TYPE,
null: false,
- description: 'Title of the error'
+ description: 'Title of the error.'
field :type, GraphQL::STRING_TYPE,
null: false,
- description: 'Type of the error'
+ description: 'Type of the error.'
field :user_count, GraphQL::INT_TYPE,
null: false,
- description: 'Count of users affected by the error'
+ description: 'Count of users affected by the error.'
field :count, GraphQL::INT_TYPE,
null: false,
- description: 'Count of occurrences'
+ description: 'Count of occurrences.'
field :message, GraphQL::STRING_TYPE,
null: true,
- description: 'Sentry metadata message of the error'
+ description: 'Sentry metadata message of the error.'
field :culprit, GraphQL::STRING_TYPE,
null: false,
- description: 'Culprit of the error'
+ description: 'Culprit of the error.'
field :external_url, GraphQL::STRING_TYPE,
null: false,
- description: 'External URL of the error'
+ description: 'External URL of the error.'
field :short_id, GraphQL::STRING_TYPE,
null: false,
- description: 'Short ID (Sentry ID) of the error'
+ description: 'Short ID (Sentry ID) of the error.'
field :status, Types::ErrorTracking::SentryErrorStatusEnum,
null: false,
- description: 'Status of the error'
+ description: 'Status of the error.'
field :frequency, [Types::ErrorTracking::SentryErrorFrequencyType],
null: false,
- description: 'Last 24hr stats of the error'
+ description: 'Last 24hr stats of the error.'
field :sentry_project_id, GraphQL::ID_TYPE,
method: :project_id,
null: false,
- description: 'ID of the project (Sentry project)'
+ description: 'ID of the project (Sentry project).'
field :sentry_project_name, GraphQL::STRING_TYPE,
method: :project_name,
null: false,
- description: 'Name of the project affected by the error'
+ description: 'Name of the project affected by the error.'
field :sentry_project_slug, GraphQL::STRING_TYPE,
method: :project_slug,
null: false,
- description: 'Slug of the project affected by the error'
+ description: 'Slug of the project affected by the error.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/event_action_enum.rb b/app/graphql/types/event_action_enum.rb
new file mode 100644
index 00000000000..79931fa48cb
--- /dev/null
+++ b/app/graphql/types/event_action_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class EventActionEnum < BaseEnum
+ graphql_name 'EventAction'
+ description 'Event action'
+
+ ::Event.actions.keys.each do |target_type|
+ value target_type.upcase, value: target_type, description: "#{target_type.titleize} action"
+ end
+ end
+end
diff --git a/app/graphql/types/event_type.rb b/app/graphql/types/event_type.rb
new file mode 100644
index 00000000000..2a4c2e7c60a
--- /dev/null
+++ b/app/graphql/types/event_type.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Types
+ class EventType < BaseObject
+ graphql_name 'Event'
+ description 'Representing an event'
+
+ present_using EventPresenter
+
+ authorize :read_event
+
+ field :id, GraphQL::ID_TYPE,
+ description: 'ID of the event.',
+ null: false
+
+ field :author, Types::UserType,
+ description: 'Author of this event.',
+ null: false
+
+ field :action, Types::EventActionEnum,
+ description: 'Action of the event.',
+ null: false
+
+ field :created_at, Types::TimeType,
+ description: 'When this event was created.',
+ null: false
+
+ field :updated_at, Types::TimeType,
+ description: 'When this event was updated.',
+ null: false
+
+ def author
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
+ end
+ end
+end
diff --git a/app/graphql/types/eventable_type.rb b/app/graphql/types/eventable_type.rb
new file mode 100644
index 00000000000..eba2154e7fa
--- /dev/null
+++ b/app/graphql/types/eventable_type.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Types
+ module EventableType
+ include Types::BaseInterface
+
+ field :events, Types::EventType.connection_type, null: true, description: 'A list of events associated with the object.'
+ end
+end
diff --git a/app/graphql/types/evidence_type.rb b/app/graphql/types/evidence_type.rb
index a2fc9953c67..6e56ad7d407 100644
--- a/app/graphql/types/evidence_type.rb
+++ b/app/graphql/types/evidence_type.rb
@@ -10,12 +10,12 @@ module Types
present_using Releases::EvidencePresenter
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the evidence'
+ description: 'ID of the evidence.'
field :sha, GraphQL::STRING_TYPE, null: true,
- description: 'SHA1 ID of the evidence hash'
+ description: 'SHA1 ID of the evidence hash.'
field :filepath, GraphQL::STRING_TYPE, null: true,
- description: 'URL from where the evidence can be downloaded'
+ description: 'URL from where the evidence can be downloaded.'
field :collected_at, Types::TimeType, null: true,
- description: 'Timestamp when the evidence was collected'
+ description: 'Timestamp when the evidence was collected.'
end
end
diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb
index 4c51d4248dd..ed28c3ffd7e 100644
--- a/app/graphql/types/global_id_type.rb
+++ b/app/graphql/types/global_id_type.rb
@@ -46,7 +46,7 @@ module Types
@id_types[model_class] ||= Class.new(self) do
graphql_name "#{model_class.name.gsub(/::/, '')}ID"
- description "Identifier of #{model_class.name}"
+ description "Identifier of #{model_class.name}."
self.define_singleton_method(:to_s) do
graphql_name
diff --git a/app/graphql/types/grafana_integration_type.rb b/app/graphql/types/grafana_integration_type.rb
index 6625af36f82..630d3a10e36 100644
--- a/app/graphql/types/grafana_integration_type.rb
+++ b/app/graphql/types/grafana_integration_type.rb
@@ -7,14 +7,14 @@ module Types
authorize :admin_operations
field :id, GraphQL::ID_TYPE, null: false,
- description: 'Internal ID of the Grafana integration'
+ description: 'Internal ID of the Grafana integration.'
field :grafana_url, GraphQL::STRING_TYPE, null: false,
- description: 'URL for the Grafana host for the Grafana integration'
+ description: 'URL for the Grafana host for the Grafana integration.'
field :enabled, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates whether Grafana integration is enabled'
+ description: 'Indicates whether Grafana integration is enabled.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of the issue\'s creation'
+ description: 'Timestamp of the issue\'s creation.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of the issue\'s last activity'
+ description: 'Timestamp of the issue\'s last activity.'
end
end
diff --git a/app/graphql/types/group_invitation_type.rb b/app/graphql/types/group_invitation_type.rb
index efb0c8a41c8..06a997bbc14 100644
--- a/app/graphql/types/group_invitation_type.rb
+++ b/app/graphql/types/group_invitation_type.rb
@@ -11,7 +11,7 @@ module Types
description 'Represents a Group Invitation'
field :group, Types::GroupType, null: true,
- description: 'Group that a User is invited to'
+ description: 'Group that a User is invited to.'
def group
Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, object.source_id).find
diff --git a/app/graphql/types/group_member_type.rb b/app/graphql/types/group_member_type.rb
index 204da5a302a..8b8e69d795d 100644
--- a/app/graphql/types/group_member_type.rb
+++ b/app/graphql/types/group_member_type.rb
@@ -11,7 +11,7 @@ module Types
description 'Represents a Group Membership'
field :group, Types::GroupType, null: true,
- description: 'Group that a User is a member of'
+ description: 'Group that a User is a member of.'
def group
Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, object.source_id).find
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 0ee8a19c1a3..0aaeb8d20df 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -9,91 +9,91 @@ module Types
expose_permissions Types::PermissionTypes::Group
field :web_url, GraphQL::STRING_TYPE, null: false,
- description: 'Web URL of the group'
+ description: 'Web URL of the group.'
field :avatar_url, GraphQL::STRING_TYPE, null: true,
- description: 'Avatar URL of the group'
+ description: 'Avatar URL of the group.'
field :custom_emoji, Types::CustomEmojiType.connection_type, null: true,
- description: 'Custom emoji within this namespace',
+ description: 'Custom emoji within this namespace.',
feature_flag: :custom_emoji
field :share_with_group_lock, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if sharing a project with another group within this group is prevented'
+ description: 'Indicates if sharing a project with another group within this group is prevented.'
field :project_creation_level, GraphQL::STRING_TYPE, null: true, method: :project_creation_level_str,
- description: 'The permission level required to create projects in the group'
+ description: 'The permission level required to create projects in the group.'
field :subgroup_creation_level, GraphQL::STRING_TYPE, null: true, method: :subgroup_creation_level_str,
- description: 'The permission level required to create subgroups within the group'
+ description: 'The permission level required to create subgroups within the group.'
field :require_two_factor_authentication, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if all users in this group are required to set up two-factor authentication'
+ description: 'Indicates if all users in this group are required to set up two-factor authentication.'
field :two_factor_grace_period, GraphQL::INT_TYPE, null: true,
- description: 'Time before two-factor authentication is enforced'
+ description: 'Time before two-factor authentication is enforced.'
field :auto_devops_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates whether Auto DevOps is enabled for all projects within this group'
+ description: 'Indicates whether Auto DevOps is enabled for all projects within this group.'
field :emails_disabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if a group has email notifications disabled'
+ description: 'Indicates if a group has email notifications disabled.'
field :mentions_disabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if a group is disabled from getting mentioned'
+ description: 'Indicates if a group is disabled from getting mentioned.'
field :parent, GroupType, null: true,
- description: 'Parent group'
+ description: 'Parent group.'
field :issues,
Types::IssueType.connection_type,
null: true,
- description: 'Issues for projects in this group',
+ description: 'Issues for projects in this group.',
resolver: Resolvers::GroupIssuesResolver
field :merge_requests,
Types::MergeRequestType.connection_type,
null: true,
- description: 'Merge requests for projects in this group',
+ description: 'Merge requests for projects in this group.',
resolver: Resolvers::GroupMergeRequestsResolver
field :milestones, Types::MilestoneType.connection_type, null: true,
- description: 'Milestones of the group',
+ description: 'Milestones of the group.',
resolver: Resolvers::GroupMilestonesResolver
field :boards,
Types::BoardType.connection_type,
null: true,
- description: 'Boards of the group',
+ description: 'Boards of the group.',
max_page_size: 2000,
resolver: Resolvers::BoardsResolver
field :board,
Types::BoardType,
null: true,
- description: 'A single board of the group',
+ description: 'A single board of the group.',
resolver: Resolvers::BoardResolver
field :label,
Types::LabelType,
null: true,
- description: 'A label available on this group' do
+ description: 'A label available on this group.' do
argument :title, GraphQL::STRING_TYPE,
required: true,
- description: 'Title of the label'
+ description: 'Title of the label.'
end
field :group_members,
- description: 'A membership of a user within this group',
+ description: 'A membership of a user within this group.',
resolver: Resolvers::GroupMembersResolver
field :container_repositories,
Types::ContainerRepositoryType.connection_type,
null: true,
- description: 'Container repositories of the group',
+ description: 'Container repositories of the group.',
resolver: Resolvers::ContainerRepositoriesResolver,
authorize: :read_container_image
field :container_repositories_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of container repositories in the group'
+ description: 'Number of container repositories in the group.'
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|
@@ -107,17 +107,8 @@ module Types
field :labels,
Types::LabelType.connection_type,
null: true,
- description: 'Labels available on this group' do
- argument :search_term, GraphQL::STRING_TYPE,
- required: false,
- description: 'A search term to find labels with'
- end
-
- def labels(search_term: nil)
- LabelsFinder
- .new(current_user, group: group, search: search_term)
- .execute
- end
+ description: 'Labels available on this group.',
+ resolver: Resolvers::GroupLabelsResolver
def avatar_url
object.avatar_url(only_path: false)
diff --git a/app/graphql/types/invitation_interface.rb b/app/graphql/types/invitation_interface.rb
index a29716c292e..b1f69f043f2 100644
--- a/app/graphql/types/invitation_interface.rb
+++ b/app/graphql/types/invitation_interface.rb
@@ -5,25 +5,25 @@ module Types
include BaseInterface
field :email, GraphQL::STRING_TYPE, null: false,
- description: 'Email of the member to invite'
+ description: 'Email of the member to invite.'
field :access_level, Types::AccessLevelType, null: true,
- description: 'GitLab::Access level'
+ description: 'GitLab::Access level.'
field :created_by, Types::UserType, null: true,
- description: 'User that authorized membership'
+ description: 'User that authorized membership.'
field :created_at, Types::TimeType, null: true,
- description: 'Date and time the membership was created'
+ description: 'Date and time the membership was created.'
field :updated_at, Types::TimeType, null: true,
- description: 'Date and time the membership was last updated'
+ description: 'Date and time the membership was last updated.'
field :expires_at, Types::TimeType, null: true,
- description: 'Date and time the membership expires'
+ description: 'Date and time the membership expires.'
field :user, Types::UserType, null: true,
- description: 'User that is associated with the member object'
+ description: 'User that is associated with the member object.'
definition_methods do
def resolve_type(object, context)
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 78fb20650e9..f15ab69f2d4 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -16,113 +16,113 @@ module Types
present_using IssuePresenter
field :id, GraphQL::ID_TYPE, null: false,
- description: "ID of the issue"
+ description: "ID of the issue."
field :iid, GraphQL::ID_TYPE, null: false,
- description: "Internal ID of the issue"
+ description: "Internal ID of the issue."
field :title, GraphQL::STRING_TYPE, null: false,
- description: 'Title of the issue'
+ description: 'Title of the issue.'
markdown_field :title_html, null: true
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description of the issue'
+ description: 'Description of the issue.'
markdown_field :description_html, null: true
field :state, IssueStateEnum, null: false,
- description: 'State of the issue'
+ description: 'State of the issue.'
field :reference, GraphQL::STRING_TYPE, null: false,
- description: 'Internal reference of the issue. Returned in shortened format by default',
+ description: 'Internal reference of the issue. Returned in shortened format by default.',
method: :to_reference do
argument :full, GraphQL::BOOLEAN_TYPE, required: false, default_value: false,
- description: 'Boolean option specifying whether the reference should be returned in full'
+ description: 'Boolean option specifying whether the reference should be returned in full.'
end
field :author, Types::UserType, null: false,
- description: 'User that created the issue'
+ description: 'User that created the issue.'
field :assignees, Types::UserType.connection_type, null: true,
- description: 'Assignees of the issue'
+ description: 'Assignees of the issue.'
field :updated_by, Types::UserType, null: true,
- description: 'User that last updated the issue'
+ description: 'User that last updated the issue.'
field :labels, Types::LabelType.connection_type, null: true,
- description: 'Labels of the issue'
+ description: 'Labels of the issue.'
field :milestone, Types::MilestoneType, null: true,
- description: 'Milestone of the issue'
+ description: 'Milestone of the issue.'
field :due_date, Types::TimeType, null: true,
- description: 'Due date of the issue'
+ description: 'Due date of the issue.'
field :confidential, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates the issue is confidential'
+ description: 'Indicates the issue is confidential.'
field :discussion_locked, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates discussion is locked on the issue'
+ description: 'Indicates discussion is locked on the issue.'
field :upvotes, GraphQL::INT_TYPE, null: false,
- description: 'Number of upvotes the issue has received'
+ description: 'Number of upvotes the issue has received.'
field :downvotes, GraphQL::INT_TYPE, null: false,
- description: 'Number of downvotes the issue has received'
+ description: 'Number of downvotes the issue has received.'
field :user_notes_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of user notes of the issue',
+ description: 'Number of user notes of the issue.',
resolver: Resolvers::UserNotesCountResolver
field :user_discussions_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of user discussions in the issue',
+ description: 'Number of user discussions in the issue.',
resolver: Resolvers::UserDiscussionsCountResolver
field :web_path, GraphQL::STRING_TYPE, null: false, method: :issue_path,
- description: 'Web path of the issue'
+ description: 'Web path of the issue.'
field :web_url, GraphQL::STRING_TYPE, null: false,
- description: 'Web URL of the issue'
+ description: 'Web URL of the issue.'
field :relative_position, GraphQL::INT_TYPE, null: true,
- description: 'Relative position of the issue (used for positioning in epic tree and issue boards)'
+ description: 'Relative position of the issue (used for positioning in epic tree and issue boards).'
field :participants, Types::UserType.connection_type, null: true, complexity: 5,
- description: 'List of participants in the issue'
+ description: 'List of participants in the issue.'
field :emails_disabled, GraphQL::BOOLEAN_TYPE, null: false,
method: :project_emails_disabled?,
- description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled'
+ description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled.'
field :subscribed, GraphQL::BOOLEAN_TYPE, method: :subscribed?, null: false, complexity: 5,
- description: 'Indicates the currently logged in user is subscribed to the issue'
+ description: 'Indicates the currently logged in user is subscribed to the issue.'
field :time_estimate, GraphQL::INT_TYPE, null: false,
- description: 'Time estimate of the issue'
+ description: 'Time estimate of the issue.'
field :total_time_spent, GraphQL::INT_TYPE, null: false,
- description: 'Total time reported as spent on the issue'
+ description: 'Total time reported as spent on the issue.'
field :human_time_estimate, GraphQL::STRING_TYPE, null: true,
- description: 'Human-readable time estimate of the issue'
+ description: 'Human-readable time estimate of the issue.'
field :human_total_time_spent, GraphQL::STRING_TYPE, null: true,
- description: 'Human-readable total time reported as spent on the issue'
+ description: 'Human-readable total time reported as spent on the issue.'
field :closed_at, Types::TimeType, null: true,
- description: 'Timestamp of when the issue was closed'
+ description: 'Timestamp of when the issue was closed.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of when the issue was created'
+ description: 'Timestamp of when the issue was created.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of when the issue was last updated'
+ description: 'Timestamp of when the issue was last updated.'
field :task_completion_status, Types::TaskCompletionStatus, null: false,
- description: 'Task completion status of the issue'
+ description: 'Task completion status of the issue.'
field :design_collection, Types::DesignManagement::DesignCollectionType, null: true,
- description: 'Collection of design images associated with this issue'
+ description: 'Collection of design images associated with this issue.'
field :type, Types::IssueTypeEnum, null: true,
method: :issue_type,
- description: 'Type of the issue'
+ description: 'Type of the issue.'
field :alert_management_alert,
Types::AlertManagement::AlertType,
null: true,
- description: 'Alert associated to this issue'
+ description: 'Alert associated to this issue.'
field :severity, Types::IssuableSeverityEnum, null: true,
- description: 'Severity level of the incident'
+ description: 'Severity level of the incident.'
field :moved, GraphQL::BOOLEAN_TYPE, method: :moved?, null: true,
- description: 'Indicates if issue got moved from other project'
+ description: 'Indicates if issue got moved from other project.'
field :moved_to, Types::IssueType, null: true,
- description: 'Updated Issue after it got moved to another project'
+ description: 'Updated Issue after it got moved to another project.'
field :create_note_email, GraphQL::STRING_TYPE, null: true,
- description: 'User specific email address for the issue'
+ description: 'User specific email address for the issue.'
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find
diff --git a/app/graphql/types/jira_import_type.rb b/app/graphql/types/jira_import_type.rb
index b3854487cec..6fa115933ac 100644
--- a/app/graphql/types/jira_import_type.rb
+++ b/app/graphql/types/jira_import_type.rb
@@ -7,19 +7,19 @@ module Types
graphql_name 'JiraImport'
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of when the Jira import was created'
+ description: 'Timestamp of when the Jira import was created.'
field :scheduled_at, Types::TimeType, null: true,
- description: 'Timestamp of when the Jira import was scheduled'
+ description: 'Timestamp of when the Jira import was scheduled.'
field :scheduled_by, Types::UserType, null: true,
- description: 'User that started the Jira import'
+ description: 'User that started the Jira import.'
field :jira_project_key, GraphQL::STRING_TYPE, null: false,
- description: 'Project key for the imported Jira project'
+ description: 'Project key for the imported Jira project.'
field :imported_issues_count, GraphQL::INT_TYPE, null: false,
- description: 'Count of issues that were successfully imported'
+ description: 'Count of issues that were successfully imported.'
field :failed_to_import_count, GraphQL::INT_TYPE, null: false,
- description: 'Count of issues that failed to import'
+ description: 'Count of issues that failed to import.'
field :total_issue_count, GraphQL::INT_TYPE, null: false,
- description: 'Total count of issues that were attempted to import'
+ description: 'Total count of issues that were attempted to import.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/jira_user_type.rb b/app/graphql/types/jira_user_type.rb
index 394820d23be..7ccb7ad6791 100644
--- a/app/graphql/types/jira_user_type.rb
+++ b/app/graphql/types/jira_user_type.rb
@@ -7,17 +7,17 @@ module Types
graphql_name 'JiraUser'
field :jira_account_id, GraphQL::STRING_TYPE, null: false,
- description: 'Account ID of the Jira user'
+ description: 'Account ID of the Jira user.'
field :jira_display_name, GraphQL::STRING_TYPE, null: false,
- description: 'Display name of the Jira user'
+ description: 'Display name of the Jira user.'
field :jira_email, GraphQL::STRING_TYPE, null: true,
- description: 'Email of the Jira user, returned only for users with public emails'
+ description: 'Email of the Jira user, returned only for users with public emails.'
field :gitlab_id, GraphQL::INT_TYPE, null: true,
- description: 'ID of the matched GitLab user'
+ description: 'ID of the matched GitLab user.'
field :gitlab_username, GraphQL::STRING_TYPE, null: true,
- description: 'Username of the matched GitLab user'
+ description: 'Username of the matched GitLab user.'
field :gitlab_name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the matched GitLab user'
+ description: 'Name of the matched GitLab user.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/jira_users_mapping_input_type.rb b/app/graphql/types/jira_users_mapping_input_type.rb
index d5b4b2f618a..0c26ea87df2 100644
--- a/app/graphql/types/jira_users_mapping_input_type.rb
+++ b/app/graphql/types/jira_users_mapping_input_type.rb
@@ -8,11 +8,11 @@ module Types
argument :jira_account_id,
GraphQL::STRING_TYPE,
required: true,
- description: 'Jira account ID of the user'
+ description: 'Jira account ID of the user.'
argument :gitlab_id,
GraphQL::INT_TYPE,
required: false,
- description: 'Id of the GitLab user'
+ description: 'Id of the GitLab user.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/label_type.rb b/app/graphql/types/label_type.rb
index 28dee2a9db5..94fd15e075c 100644
--- a/app/graphql/types/label_type.rb
+++ b/app/graphql/types/label_type.rb
@@ -9,15 +9,15 @@ module Types
authorize :read_label
field :id, GraphQL::ID_TYPE, null: false,
- description: 'Label ID'
+ description: 'Label ID.'
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description of the label (Markdown rendered as HTML for caching)'
+ description: 'Description of the label (Markdown rendered as HTML for caching).'
markdown_field :description_html, null: true
field :title, GraphQL::STRING_TYPE, null: false,
- description: 'Content of the label'
+ description: 'Content of the label.'
field :color, GraphQL::STRING_TYPE, null: false,
- description: 'Background color of the label'
+ description: 'Background color of the label.'
field :text_color, GraphQL::STRING_TYPE, null: false,
- description: 'Text color of the label'
+ description: 'Text color of the label.'
end
end
diff --git a/app/graphql/types/member_interface.rb b/app/graphql/types/member_interface.rb
index 615a45413cb..1c7257487d9 100644
--- a/app/graphql/types/member_interface.rb
+++ b/app/graphql/types/member_interface.rb
@@ -5,25 +5,25 @@ module Types
include BaseInterface
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the member'
+ description: 'ID of the member.'
field :access_level, Types::AccessLevelType, null: true,
- description: 'GitLab::Access level'
+ description: 'GitLab::Access level.'
field :created_by, Types::UserType, null: true,
- description: 'User that authorized membership'
+ description: 'User that authorized membership.'
field :created_at, Types::TimeType, null: true,
- description: 'Date and time the membership was created'
+ description: 'Date and time the membership was created.'
field :updated_at, Types::TimeType, null: true,
- description: 'Date and time the membership was last updated'
+ description: 'Date and time the membership was last updated.'
field :expires_at, Types::TimeType, null: true,
- description: 'Date and time the membership expires'
+ description: 'Date and time the membership expires.'
field :user, Types::UserType, null: false,
- description: 'User that is associated with the member object'
+ description: 'User that is associated with the member object.'
definition_methods do
def resolve_type(object, context)
diff --git a/app/graphql/types/merge_request_connection_type.rb b/app/graphql/types/merge_request_connection_type.rb
index da06bb86929..d009b67bc0f 100644
--- a/app/graphql/types/merge_request_connection_type.rb
+++ b/app/graphql/types/merge_request_connection_type.rb
@@ -4,7 +4,7 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class MergeRequestConnectionType < Types::CountableConnectionType
field :total_time_to_merge, GraphQL::FLOAT_TYPE, null: true,
- description: 'Total sum of time to merge, in seconds, for the collection of merge requests'
+ description: 'Total sum of time to merge, in seconds, for the collection of merge requests.'
# rubocop: disable CodeReuse/ActiveRecord
def total_time_to_merge
diff --git a/app/graphql/types/merge_request_state_enum.rb b/app/graphql/types/merge_request_state_enum.rb
index 92f52726ab3..c14b9f80a53 100644
--- a/app/graphql/types/merge_request_state_enum.rb
+++ b/app/graphql/types/merge_request_state_enum.rb
@@ -5,6 +5,6 @@ module Types
graphql_name 'MergeRequestState'
description 'State of a GitLab merge request'
- value 'merged'
+ value 'merged', description: "Merge Request has been merged"
end
end
diff --git a/app/graphql/types/merge_request_state_event_enum.rb b/app/graphql/types/merge_request_state_event_enum.rb
new file mode 100644
index 00000000000..ebb8b9638db
--- /dev/null
+++ b/app/graphql/types/merge_request_state_event_enum.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ class MergeRequestStateEventEnum < BaseEnum
+ graphql_name 'MergeRequestNewState'
+ description 'New state to apply to a merge request.'
+
+ value 'OPEN',
+ value: 'reopen',
+ description: 'Open the merge request if it is closed.'
+
+ value 'CLOSED',
+ value: 'close',
+ description: 'Close the merge request if it is open.'
+ end
+end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index ee7d5780f7a..10f324e901a 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -16,169 +16,169 @@ module Types
present_using MergeRequestPresenter
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the merge request'
+ description: 'ID of the merge request.'
field :iid, GraphQL::STRING_TYPE, null: false,
- description: 'Internal ID of the merge request'
+ description: 'Internal ID of the merge request.'
field :title, GraphQL::STRING_TYPE, null: false,
- description: 'Title of the merge request'
+ description: 'Title of the merge request.'
markdown_field :title_html, null: true
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description of the merge request (Markdown rendered as HTML for caching)'
+ description: 'Description of the merge request (Markdown rendered as HTML for caching).'
markdown_field :description_html, null: true
field :state, MergeRequestStateEnum, null: false,
- description: 'State of the merge request'
+ description: 'State of the merge request.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of when the merge request was created'
+ description: 'Timestamp of when the merge request was created.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of when the merge request was last updated'
+ description: 'Timestamp of when the merge request was last updated.'
field :merged_at, Types::TimeType, null: true, complexity: 5,
- description: 'Timestamp of when the merge request was merged, null if not merged'
+ description: 'Timestamp of when the merge request was merged, null if not merged.'
field :source_project, Types::ProjectType, null: true,
- description: 'Source project of the merge request'
+ description: 'Source project of the merge request.'
field :target_project, Types::ProjectType, null: false,
- description: 'Target project of the merge request'
+ description: 'Target project of the merge request.'
field :diff_refs, Types::DiffRefsType, null: true,
- description: 'References of the base SHA, the head SHA, and the start SHA for this merge request'
+ description: 'References of the base SHA, the head SHA, and the start SHA for this merge request.'
field :project, Types::ProjectType, null: false,
- description: 'Alias for target_project'
+ description: 'Alias for target_project.'
field :project_id, GraphQL::INT_TYPE, null: false, method: :target_project_id,
- description: 'ID of the merge request project'
+ description: 'ID of the merge request project.'
field :source_project_id, GraphQL::INT_TYPE, null: true,
- description: 'ID of the merge request source project'
+ description: 'ID of the merge request source project.'
field :target_project_id, GraphQL::INT_TYPE, null: false,
- description: 'ID of the merge request target project'
+ description: 'ID of the merge request target project.'
field :source_branch, GraphQL::STRING_TYPE, null: false,
- description: 'Source branch of the merge request'
+ description: 'Source branch of the merge request.'
field :source_branch_protected, GraphQL::BOOLEAN_TYPE, null: false, calls_gitaly: true,
- description: 'Indicates if the source branch is protected'
+ description: 'Indicates if the source branch is protected.'
field :target_branch, GraphQL::STRING_TYPE, null: false,
- description: 'Target branch of the merge request'
+ description: 'Target branch of the merge request.'
field :work_in_progress, GraphQL::BOOLEAN_TYPE, method: :work_in_progress?, null: false,
- description: 'Indicates if the merge request is a work in progress (WIP)'
+ description: 'Indicates if the merge request is a work in progress (WIP).'
field :merge_when_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS)'
+ description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).'
field :diff_head_sha, GraphQL::STRING_TYPE, null: true,
- description: 'Diff head SHA of the merge request'
+ description: 'Diff head SHA of the merge request.'
field :diff_stats, [Types::DiffStatsType], null: true, calls_gitaly: true,
- description: 'Details about which files were changed in this merge request' do
- argument :path, GraphQL::STRING_TYPE, required: false, description: 'A specific file-path'
+ description: 'Details about which files were changed in this merge request.' do
+ argument :path, GraphQL::STRING_TYPE, required: false, description: 'A specific file-path.'
end
field :diff_stats_summary, Types::DiffStatsSummaryType, null: true, calls_gitaly: true,
- description: 'Summary of which files were changed in this merge request'
+ description: 'Summary of which files were changed in this merge request.'
field :merge_commit_sha, GraphQL::STRING_TYPE, null: true,
- description: 'SHA of the merge request commit (set once merged)'
+ description: 'SHA of the merge request commit (set once merged).'
field :user_notes_count, GraphQL::INT_TYPE, null: true,
- description: 'User notes count of the merge request',
+ description: 'User notes count of the merge request.',
resolver: Resolvers::UserNotesCountResolver
field :user_discussions_count, GraphQL::INT_TYPE, null: true,
- description: 'Number of user discussions in the merge request',
+ description: 'Number of user discussions in the merge request.',
resolver: Resolvers::UserDiscussionsCountResolver
field :should_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :should_remove_source_branch?, null: true,
- description: 'Indicates if the source branch of the merge request will be deleted after merge'
+ description: 'Indicates if the source branch of the merge request will be deleted after merge.'
field :force_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :force_remove_source_branch?, null: true,
- description: 'Indicates if the project settings will lead to source branch deletion after merge'
+ description: 'Indicates if the project settings will lead to source branch deletion after merge.'
field :merge_status, GraphQL::STRING_TYPE, method: :public_merge_status, null: true,
- description: 'Status of the merge request'
+ description: 'Status of the merge request.'
field :in_progress_merge_commit_sha, GraphQL::STRING_TYPE, null: true,
- description: 'Commit SHA of the merge request if merge is in progress'
+ description: 'Commit SHA of the merge request if merge is in progress.'
field :merge_error, GraphQL::STRING_TYPE, null: true,
- description: 'Error message due to a merge error'
+ description: 'Error message due to a merge error.'
field :allow_collaboration, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if members of the target project can push to the fork'
+ description: 'Indicates if members of the target project can push to the fork.'
field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, calls_gitaly: true,
- description: 'Indicates if the merge request will be rebased'
+ description: 'Indicates if the merge request will be rebased.'
field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true,
- description: 'Rebase commit SHA of the merge request'
+ description: 'Rebase commit SHA of the merge request.'
field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true,
- description: 'Indicates if there is a rebase currently in progress for the merge request'
+ description: 'Indicates if there is a rebase currently in progress for the merge request.'
field :default_merge_commit_message, GraphQL::STRING_TYPE, null: true,
- description: 'Default merge commit message of the merge request'
+ description: 'Default merge commit message of the merge request.'
field :default_merge_commit_message_with_description, GraphQL::STRING_TYPE, null: true,
- description: 'Default merge commit message of the merge request with description'
+ description: 'Default merge commit message of the merge request with description.'
field :default_squash_commit_message, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
- description: 'Default squash commit message of the merge request'
+ description: 'Default squash commit message of the merge request.'
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false,
- description: 'Indicates if a merge is currently occurring'
+ description: 'Indicates if a merge is currently occurring.'
field :source_branch_exists, GraphQL::BOOLEAN_TYPE,
null: false, calls_gitaly: true,
method: :source_branch_exists?,
- description: 'Indicates if the source branch of the merge request exists'
+ description: 'Indicates if the source branch of the merge request exists.'
field :target_branch_exists, GraphQL::BOOLEAN_TYPE,
null: false, calls_gitaly: true,
method: :target_branch_exists?,
- description: 'Indicates if the target branch of the merge request exists'
+ description: 'Indicates if the target branch of the merge request exists.'
field :mergeable_discussions_state, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged'
+ description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.'
field :web_url, GraphQL::STRING_TYPE, null: true,
- description: 'Web URL of the merge request'
+ description: 'Web URL of the merge request.'
field :upvotes, GraphQL::INT_TYPE, null: false,
- description: 'Number of upvotes for the merge request'
+ description: 'Number of upvotes for the merge request.'
field :downvotes, GraphQL::INT_TYPE, null: false,
- description: 'Number of downvotes for the merge request'
+ description: 'Number of downvotes for the merge request.'
field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline,
- description: 'The pipeline running on the branch HEAD of the merge request'
+ description: 'The pipeline running on the branch HEAD of the merge request.'
field :pipelines,
null: true,
description: 'Pipelines for the merge request. Note: for performance reasons, no more than the most recent 500 pipelines will be returned.',
resolver: Resolvers::MergeRequestPipelinesResolver
field :milestone, Types::MilestoneType, null: true,
- description: 'The milestone of the merge request'
+ description: 'The milestone of the merge request.'
field :assignees, Types::UserType.connection_type, null: true, complexity: 5,
- description: 'Assignees of the merge request'
+ description: 'Assignees of the merge request.'
field :reviewers, Types::UserType.connection_type, null: true, complexity: 5,
description: 'Users from whom a review has been requested.'
field :author, Types::UserType, null: true,
- description: 'User who created this merge request'
+ description: 'User who created this merge request.'
field :participants, Types::UserType.connection_type, null: true, complexity: 15,
description: 'Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.'
field :subscribed, GraphQL::BOOLEAN_TYPE, method: :subscribed?, null: false, complexity: 5,
- description: 'Indicates if the currently logged in user is subscribed to this merge request'
+ description: 'Indicates if the currently logged in user is subscribed to this merge request.'
field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
- description: 'Labels of the merge request'
+ description: 'Labels of the merge request.'
field :discussion_locked, GraphQL::BOOLEAN_TYPE,
- description: 'Indicates if comments on the merge request are locked to members only',
+ description: 'Indicates if comments on the merge request are locked to members only.',
null: false
field :time_estimate, GraphQL::INT_TYPE, null: false,
- description: 'Time estimate of the merge request'
+ description: 'Time estimate of the merge request.'
field :total_time_spent, GraphQL::INT_TYPE, null: false,
- description: 'Total time reported as spent on the merge request'
+ description: 'Total time reported as spent on the merge request.'
field :reference, GraphQL::STRING_TYPE, null: false, method: :to_reference,
- description: 'Internal reference of the merge request. Returned in shortened format by default' do
+ description: 'Internal reference of the merge request. Returned in shortened format by default.' do
argument :full, GraphQL::BOOLEAN_TYPE, required: false, default_value: false,
- description: 'Boolean option specifying whether the reference should be returned in full'
+ description: 'Boolean option specifying whether the reference should be returned in full.'
end
field :task_completion_status, Types::TaskCompletionStatus, null: false,
description: Types::TaskCompletionStatus.description
- field :commit_count, GraphQL::INT_TYPE, null: true,
- description: 'Number of commits in the merge request'
+ field :commit_count, GraphQL::INT_TYPE, null: true, method: :commits_count,
+ description: 'Number of commits in the merge request.'
field :conflicts, GraphQL::BOOLEAN_TYPE, null: false, method: :cannot_be_merged?,
- description: 'Indicates if the merge request has conflicts'
+ description: 'Indicates if the merge request has conflicts.'
field :auto_merge_enabled, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if auto merge is enabled for the merge request'
+ description: 'Indicates if auto merge is enabled for the merge request.'
field :approved_by, Types::UserType.connection_type, null: true,
- description: 'Users who approved the merge request'
+ description: 'Users who approved the merge request.'
field :squash_on_merge, GraphQL::BOOLEAN_TYPE, null: false, method: :squash_on_merge?,
- description: 'Indicates if squash on merge is enabled'
+ description: 'Indicates if squash on merge is enabled.'
field :squash, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if squash on merge is enabled'
+ description: 'Indicates if squash on merge is enabled.'
field :available_auto_merge_strategies, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
- description: 'Array of available auto merge strategies'
+ description: 'Array of available auto merge strategies.'
field :has_ci, GraphQL::BOOLEAN_TYPE, null: false, method: :has_ci?,
- description: 'Indicates if the merge request has CI'
+ description: 'Indicates if the merge request has CI.'
field :mergeable, GraphQL::BOOLEAN_TYPE, null: false, method: :mergeable?, calls_gitaly: true,
- description: 'Indicates if the merge request is mergeable'
+ description: 'Indicates if the merge request is mergeable.'
field :commits_without_merge_commits, Types::CommitType.connection_type, null: true,
- calls_gitaly: true, description: 'Merge request commits excluding merge commits'
+ calls_gitaly: true, description: 'Merge request commits excluding merge commits.'
field :security_auto_fix, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if the merge request is created by @GitLab-Security-Bot.'
field :auto_merge_strategy, GraphQL::STRING_TYPE, null: true,
- description: 'Selected auto merge strategy'
+ description: 'Selected auto merge strategy.'
field :merge_user, Types::UserType, null: true,
- description: 'User who merged this merge request'
+ description: 'User who merged this merge request.'
def approved_by
object.approved_by_users
@@ -218,10 +218,6 @@ module Types
BatchLoaders::MergeRequestDiffSummaryBatchLoader.load_for(object)
end
- def commit_count
- object&.metrics&.commits_count
- end
-
def source_branch_protected
object.source_project.present? && ProtectedBranch.protected?(object.source_project, object.source_branch)
end
@@ -247,7 +243,7 @@ module Types
end
def reviewers
- object.reviewers if object.allows_reviewers?
+ object.reviewers
end
end
end
diff --git a/app/graphql/types/metadata_type.rb b/app/graphql/types/metadata_type.rb
index 1998b036a53..0c360d4f292 100644
--- a/app/graphql/types/metadata_type.rb
+++ b/app/graphql/types/metadata_type.rb
@@ -7,8 +7,8 @@ module Types
authorize :read_instance_metadata
field :version, GraphQL::STRING_TYPE, null: false,
- description: 'Version'
+ description: 'Version.'
field :revision, GraphQL::STRING_TYPE, null: false,
- description: 'Revision'
+ description: 'Revision.'
end
end
diff --git a/app/graphql/types/metrics/dashboard_type.rb b/app/graphql/types/metrics/dashboard_type.rb
index 47502356773..40d2c2f195c 100644
--- a/app/graphql/types/metrics/dashboard_type.rb
+++ b/app/graphql/types/metrics/dashboard_type.rb
@@ -8,13 +8,13 @@ module Types
graphql_name 'MetricsDashboard'
field :path, GraphQL::STRING_TYPE, null: true,
- description: 'Path to a file with the dashboard definition'
+ description: 'Path to a file with the dashboard definition.'
field :schema_validation_warnings, [GraphQL::STRING_TYPE], null: true,
- description: 'Dashboard schema validation warnings'
+ description: 'Dashboard schema validation warnings.'
field :annotations, Types::Metrics::Dashboards::AnnotationType.connection_type, null: true,
- description: 'Annotations added to the dashboard',
+ description: 'Annotations added to the dashboard.',
resolver: Resolvers::Metrics::Dashboards::AnnotationResolver
# In order to maintain backward compatibility we need to return NULL when there are no warnings
diff --git a/app/graphql/types/metrics/dashboards/annotation_type.rb b/app/graphql/types/metrics/dashboards/annotation_type.rb
index 0f8f95c187b..b9e040dd063 100644
--- a/app/graphql/types/metrics/dashboards/annotation_type.rb
+++ b/app/graphql/types/metrics/dashboards/annotation_type.rb
@@ -8,19 +8,19 @@ module Types
graphql_name 'MetricsDashboardAnnotation'
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description of the annotation'
+ description: 'Description of the annotation.'
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the annotation'
+ description: 'ID of the annotation.'
field :panel_id, GraphQL::STRING_TYPE, null: true,
- description: 'ID of a dashboard panel to which the annotation should be scoped'
+ description: 'ID of a dashboard panel to which the annotation should be scoped.'
field :starting_at, Types::TimeType, null: true,
- description: 'Timestamp marking start of annotated time span'
+ description: 'Timestamp marking start of annotated time span.'
field :ending_at, Types::TimeType, null: true,
- description: 'Timestamp marking end of annotated time span'
+ description: 'Timestamp marking end of annotated time span.'
def panel_id
object.panel_xid
diff --git a/app/graphql/types/milestone_state_enum.rb b/app/graphql/types/milestone_state_enum.rb
index 032571ac88f..e3b60395c9b 100644
--- a/app/graphql/types/milestone_state_enum.rb
+++ b/app/graphql/types/milestone_state_enum.rb
@@ -2,7 +2,10 @@
module Types
class MilestoneStateEnum < BaseEnum
- value 'active'
- value 'closed'
+ graphql_name 'MilestoneStateEnum'
+ description 'Current state of milestone'
+
+ value 'active', description: 'Milestone is currently active'
+ value 'closed', description: 'Milestone is closed'
end
end
diff --git a/app/graphql/types/milestone_stats_type.rb b/app/graphql/types/milestone_stats_type.rb
index ef533af59e7..e313b880e0d 100644
--- a/app/graphql/types/milestone_stats_type.rb
+++ b/app/graphql/types/milestone_stats_type.rb
@@ -8,9 +8,9 @@ module Types
authorize :read_milestone
field :total_issues_count, GraphQL::INT_TYPE, null: true,
- description: 'Total number of issues associated with the milestone'
+ description: 'Total number of issues associated with the milestone.'
field :closed_issues_count, GraphQL::INT_TYPE, null: true,
- description: 'Number of closed issues associated with the milestone'
+ description: 'Number of closed issues associated with the milestone.'
end
end
diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb
index 8603043804e..c3816116e2b 100644
--- a/app/graphql/types/milestone_type.rb
+++ b/app/graphql/types/milestone_type.rb
@@ -12,46 +12,46 @@ module Types
alias_method :milestone, :object
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the milestone'
+ description: 'ID of the milestone.'
field :title, GraphQL::STRING_TYPE, null: false,
- description: 'Title of the milestone'
+ description: 'Title of the milestone.'
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description of the milestone'
+ description: 'Description of the milestone.'
field :state, Types::MilestoneStateEnum, null: false,
- description: 'State of the milestone'
+ description: 'State of the milestone.'
field :web_path, GraphQL::STRING_TYPE, null: false, method: :milestone_path,
- description: 'Web path of the milestone'
+ description: 'Web path of the milestone.'
field :due_date, Types::TimeType, null: true,
- description: 'Timestamp of the milestone due date'
+ description: 'Timestamp of the milestone due date.'
field :start_date, Types::TimeType, null: true,
- description: 'Timestamp of the milestone start date'
+ description: 'Timestamp of the milestone start date.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of milestone creation'
+ description: 'Timestamp of milestone creation.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of last milestone update'
+ description: 'Timestamp of last milestone update.'
field :project_milestone, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if milestone is at project level',
+ description: 'Indicates if milestone is at project level.',
method: :project_milestone?
field :group_milestone, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if milestone is at group level',
+ description: 'Indicates if milestone is at group level.',
method: :group_milestone?
field :subgroup_milestone, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if milestone is at subgroup level',
+ description: 'Indicates if milestone is at subgroup level.',
method: :subgroup_milestone?
field :stats, Types::MilestoneStatsType, null: true,
- description: 'Milestone statistics'
+ description: 'Milestone statistics.'
def stats
return unless Feature.enabled?(:graphql_milestone_stats, milestone.project || milestone.group, default_enabled: true)
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index f9dd11cbe37..166f5617da2 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -15,6 +15,7 @@ module Types
mount_mutation Mutations::AlertManagement::HttpIntegration::Update
mount_mutation Mutations::AlertManagement::HttpIntegration::ResetToken
mount_mutation Mutations::AlertManagement::HttpIntegration::Destroy
+ mount_mutation Mutations::Security::CiConfiguration::ConfigureSast
mount_mutation Mutations::AlertManagement::PrometheusIntegration::Create
mount_mutation Mutations::AlertManagement::PrometheusIntegration::Update
mount_mutation Mutations::AlertManagement::PrometheusIntegration::ResetToken
@@ -50,6 +51,7 @@ module Types
mount_mutation Mutations::MergeRequests::SetSubscription
mount_mutation Mutations::MergeRequests::SetWip, calls_gitaly: true
mount_mutation Mutations::MergeRequests::SetAssignees
+ mount_mutation Mutations::MergeRequests::ReviewerRereview
mount_mutation Mutations::Metrics::Dashboard::Annotations::Create
mount_mutation Mutations::Metrics::Dashboard::Annotations::Delete
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
@@ -97,5 +99,4 @@ module Types
end
::Types::MutationType.prepend(::Types::DeprecatedMutations)
-::Types::MutationType.prepend_if_ee('EE::Types::DeprecatedMutations')
::Types::MutationType.prepend_if_ee('::EE::Types::MutationType')
diff --git a/app/graphql/types/namespace_type.rb b/app/graphql/types/namespace_type.rb
index ab614d92b06..da983399a11 100644
--- a/app/graphql/types/namespace_type.rb
+++ b/app/graphql/types/namespace_type.rb
@@ -7,40 +7,40 @@ module Types
authorize :read_namespace
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the namespace'
+ description: 'ID of the namespace.'
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Name of the namespace'
+ description: 'Name of the namespace.'
field :path, GraphQL::STRING_TYPE, null: false,
- description: 'Path of the namespace'
+ description: 'Path of the namespace.'
field :full_name, GraphQL::STRING_TYPE, null: false,
- description: 'Full name of the namespace'
+ description: 'Full name of the namespace.'
field :full_path, GraphQL::ID_TYPE, null: false,
- description: 'Full path of the namespace'
+ description: 'Full path of the namespace.'
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description of the namespace'
+ description: 'Description of the namespace.'
markdown_field :description_html, null: true
field :visibility, GraphQL::STRING_TYPE, null: true,
- description: 'Visibility of the namespace'
+ description: 'Visibility of the namespace.'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, method: :lfs_enabled?,
- description: 'Indicates if Large File Storage (LFS) is enabled for namespace'
+ description: 'Indicates if Large File Storage (LFS) is enabled for namespace.'
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if users can request access to namespace'
+ description: 'Indicates if users can request access to namespace.'
field :root_storage_statistics, Types::RootStorageStatisticsType,
null: true,
- description: 'Aggregated storage statistics of the namespace. Only available for root namespaces'
+ description: 'Aggregated storage statistics of the namespace. Only available for root namespaces.'
field :projects, Types::ProjectType.connection_type, null: false,
- description: 'Projects within this namespace',
+ description: 'Projects within this namespace.',
resolver: ::Resolvers::NamespaceProjectsResolver
field :package_settings,
Types::Namespace::PackageSettingsType,
null: true,
- description: 'The package settings for the namespace'
+ description: 'The package settings for the namespace.'
def root_storage_statistics
Gitlab::Graphql::Loaders::BatchRootStorageStatisticsLoader.new(object.id).find
diff --git a/app/graphql/types/notes/diff_position_type.rb b/app/graphql/types/notes/diff_position_type.rb
index 13d9be49484..67747a13dcf 100644
--- a/app/graphql/types/notes/diff_position_type.rb
+++ b/app/graphql/types/notes/diff_position_type.rb
@@ -8,32 +8,32 @@ module Types
graphql_name 'DiffPosition'
field :diff_refs, Types::DiffRefsType, null: false,
- description: 'Information about the branch, HEAD, and base at the time of commenting'
+ description: 'Information about the branch, HEAD, and base at the time of commenting.'
field :file_path, GraphQL::STRING_TYPE, null: false,
- description: 'Path of the file that was changed'
+ description: 'Path of the file that was changed.'
field :old_path, GraphQL::STRING_TYPE, null: true,
- description: 'Path of the file on the start SHA'
+ description: 'Path of the file on the start SHA.'
field :new_path, GraphQL::STRING_TYPE, null: true,
- description: 'Path of the file on the HEAD SHA'
+ description: 'Path of the file on the HEAD SHA.'
field :position_type, Types::Notes::PositionTypeEnum, null: false,
- description: 'Type of file the position refers to'
+ description: 'Type of file the position refers to.'
# Fields for text positions
field :old_line, GraphQL::INT_TYPE, null: true,
- description: 'Line on start SHA that was changed'
+ description: 'Line on start SHA that was changed.'
field :new_line, GraphQL::INT_TYPE, null: true,
- description: 'Line on HEAD SHA that was changed'
+ description: 'Line on HEAD SHA that was changed.'
# Fields for image positions
field :x, GraphQL::INT_TYPE, null: true,
- description: 'X position of the note'
+ description: 'X position of the note.'
field :y, GraphQL::INT_TYPE, null: true,
- description: 'Y position of the note'
+ description: 'Y position of the note.'
field :width, GraphQL::INT_TYPE, null: true,
- description: 'Total width of the image'
+ description: 'Total width of the image.'
field :height, GraphQL::INT_TYPE, null: true,
- description: 'Total height of the image'
+ description: 'Total height of the image.'
def old_line
object.old_line if object.on_text?
diff --git a/app/graphql/types/notes/discussion_type.rb b/app/graphql/types/notes/discussion_type.rb
index a51d253097d..17cb4debd63 100644
--- a/app/graphql/types/notes/discussion_type.rb
+++ b/app/graphql/types/notes/discussion_type.rb
@@ -3,24 +3,26 @@
module Types
module Notes
class DiscussionType < BaseObject
+ DiscussionID = ::Types::GlobalIDType[::Discussion]
+
graphql_name 'Discussion'
authorize :read_note
implements(Types::ResolvableInterface)
- field :id, GraphQL::ID_TYPE, null: false,
- description: "ID of this discussion"
- field :reply_id, GraphQL::ID_TYPE, null: false,
- description: 'ID used to reply to this discussion'
+ field :id, DiscussionID, null: false,
+ description: "ID of this discussion."
+ field :reply_id, DiscussionID, null: false,
+ description: 'ID used to reply to this discussion.'
field :created_at, Types::TimeType, null: false,
- description: "Timestamp of the discussion's creation"
+ description: "Timestamp of the discussion's creation."
field :notes, Types::Notes::NoteType.connection_type, null: false,
- description: 'All notes in the discussion'
+ description: 'All notes in the discussion.'
- # The gem we use to generate Global IDs is hard-coded to work with
- # `id` properties. To generate a GID for the `reply_id` property,
- # we must use the ::Gitlab::GlobalId module.
+ # DiscussionID.coerce_result is suitable here, but will always mark this
+ # as being a 'Discussion'. Using `GlobalId.build` guarantees that we get
+ # the correct class, and that it matches `id`.
def reply_id
::Gitlab::GlobalId.build(object, id: object.reply_id)
end
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index 84b61340e93..751cf7c10f1 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -11,44 +11,44 @@ module Types
implements(Types::ResolvableInterface)
- field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the note'
+ field :id, ::Types::GlobalIDType[::Note], null: false,
+ description: 'ID of the note.'
field :project, Types::ProjectType,
null: true,
- description: 'Project associated with the note'
+ description: 'Project associated with the note.'
field :author, Types::UserType,
null: false,
- description: 'User who wrote this note'
+ description: 'User who wrote this note.'
field :system, GraphQL::BOOLEAN_TYPE,
null: false,
- description: 'Indicates whether this note was created by the system or by a user'
+ description: 'Indicates whether this note was created by the system or by a user.'
field :system_note_icon_name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the icon corresponding to a system note'
+ description: 'Name of the icon corresponding to a system note.'
field :body, GraphQL::STRING_TYPE,
null: false,
method: :note,
- description: 'Content of the note'
+ description: 'Content of the note.'
markdown_field :body_html, null: true, method: :note
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of the note creation'
+ description: 'Timestamp of the note creation.'
field :updated_at, Types::TimeType, null: false,
- description: "Timestamp of the note's last activity"
+ description: "Timestamp of the note's last activity."
field :discussion, Types::Notes::DiscussionType, null: true,
- description: 'The discussion this note is a part of'
+ description: 'The discussion this note is a part of.'
field :position, Types::Notes::DiffPositionType, null: true,
- description: 'The position of this note on a diff'
+ description: 'The position of this note on a diff.'
field :confidential, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if this note is confidential',
+ description: 'Indicates if this note is confidential.',
method: :confidential?
field :url, GraphQL::STRING_TYPE,
null: true,
- description: 'URL to view this Note in the Web UI'
+ description: 'URL to view this Note in the Web UI.'
def url
::Gitlab::UrlBuilder.build(object)
diff --git a/app/graphql/types/notes/noteable_type.rb b/app/graphql/types/notes/noteable_type.rb
index 602634d9292..f8626d249a1 100644
--- a/app/graphql/types/notes/noteable_type.rb
+++ b/app/graphql/types/notes/noteable_type.rb
@@ -5,8 +5,8 @@ module Types
module NoteableType
include Types::BaseInterface
- field :notes, Types::Notes::NoteType.connection_type, null: false, description: "All notes on this noteable"
- field :discussions, Types::Notes::DiscussionType.connection_type, null: false, description: "All discussions on this noteable"
+ field :notes, Types::Notes::NoteType.connection_type, null: false, description: "All notes on this noteable."
+ field :discussions, Types::Notes::DiscussionType.connection_type, null: false, description: "All discussions on this noteable."
def self.resolve_type(object, context)
case object
diff --git a/app/graphql/types/packages/composer/details_type.rb b/app/graphql/types/packages/composer/details_type.rb
deleted file mode 100644
index 8c6845a6fb3..00000000000
--- a/app/graphql/types/packages/composer/details_type.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module Packages
- module Composer
- class DetailsType < Types::Packages::PackageType
- graphql_name 'PackageComposerDetails'
- description 'Details of a Composer package'
-
- authorize :read_package
-
- field :composer_metadatum, Types::Packages::Composer::MetadatumType, null: false, description: 'The Composer metadatum.'
- end
- end
- end
-end
diff --git a/app/graphql/types/packages/composer/metadatum_type.rb b/app/graphql/types/packages/composer/metadatum_type.rb
index a97818b1fb8..9d4ce3cebd4 100644
--- a/app/graphql/types/packages/composer/metadatum_type.rb
+++ b/app/graphql/types/packages/composer/metadatum_type.rb
@@ -4,8 +4,8 @@ module Types
module Packages
module Composer
class MetadatumType < BaseObject
- graphql_name 'PackageComposerMetadatumType'
- description 'Composer metadatum'
+ graphql_name 'ComposerMetadata'
+ description 'Composer metadata'
authorize :read_package
diff --git a/app/graphql/types/packages/metadata_type.rb b/app/graphql/types/packages/metadata_type.rb
new file mode 100644
index 00000000000..26c43b51a69
--- /dev/null
+++ b/app/graphql/types/packages/metadata_type.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class MetadataType < BaseUnion
+ graphql_name 'PackageMetadata'
+ description 'Represents metadata associated with a Package'
+
+ possible_types ::Types::Packages::Composer::MetadatumType
+
+ def self.resolve_type(object, context)
+ case object
+ when ::Packages::Composer::Metadatum
+ ::Types::Packages::Composer::MetadatumType
+ else
+ # NOTE: This method must be kept in sync with `PackageWithoutVersionsType#metadata`,
+ # which must never produce data that this discriminator cannot handle.
+ raise 'Unsupported metadata type'
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
index b13d16e91c6..331898a1e84 100644
--- a/app/graphql/types/packages/package_type.rb
+++ b/app/graphql/types/packages/package_type.rb
@@ -2,26 +2,13 @@
module Types
module Packages
- class PackageType < BaseObject
+ class PackageType < PackageWithoutVersionsType
graphql_name 'Package'
description 'Represents a package in the Package Registry'
-
authorize :read_package
- field :id, GraphQL::ID_TYPE, null: false, description: 'The ID of the package.'
- field :name, GraphQL::STRING_TYPE, null: false, description: 'The name of the package.'
- field :created_at, Types::TimeType, null: false, description: 'The created date.'
- field :updated_at, Types::TimeType, null: false, description: 'The updated date.'
- field :version, GraphQL::STRING_TYPE, null: true, description: 'The version of the package.'
- field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'The type of the package.'
- field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'The package tags.'
- field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
- field :pipelines, Types::Ci::PipelineType.connection_type, null: true, description: 'Pipelines that built the package.'
- field :versions, Types::Packages::PackageType.connection_type, null: true, description: 'The other versions of the package.'
-
- def project
- Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
- end
+ field :versions, ::Types::Packages::PackageWithoutVersionsType.connection_type, null: true,
+ description: 'The other versions of the package.'
end
end
end
diff --git a/app/graphql/types/packages/package_type_enum.rb b/app/graphql/types/packages/package_type_enum.rb
index 9713c9d49b1..e2b5cf3163e 100644
--- a/app/graphql/types/packages/package_type_enum.rb
+++ b/app/graphql/types/packages/package_type_enum.rb
@@ -5,7 +5,7 @@ module Types
class PackageTypeEnum < BaseEnum
PACKAGE_TYPE_NAMES = {
pypi: 'PyPI',
- npm: 'NPM'
+ npm: 'npm'
}.freeze
::Packages::Package.package_types.keys.each do |package_type|
diff --git a/app/graphql/types/packages/package_without_versions_type.rb b/app/graphql/types/packages/package_without_versions_type.rb
new file mode 100644
index 00000000000..9c6bb37e6cc
--- /dev/null
+++ b/app/graphql/types/packages/package_without_versions_type.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageWithoutVersionsType < ::Types::BaseObject
+ graphql_name 'PackageWithoutVersions'
+ description 'Represents a version of a package in the Package Registry'
+
+ authorize :read_package
+
+ field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
+ description: 'ID of the package.'
+
+ field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package.'
+ field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
+ field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
+ field :version, GraphQL::STRING_TYPE, null: true, description: 'Version string.'
+ field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
+ field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
+ field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
+ field :pipelines, Types::Ci::PipelineType.connection_type, null: true,
+ description: 'Pipelines that built the package.'
+ field :metadata, Types::Packages::MetadataType, null: true,
+ description: 'Package metadata.'
+
+ def project
+ Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
+ end
+
+ # NOTE: This method must be kept in sync with the union
+ # type: `Types::Packages::MetadataType`.
+ #
+ # `Types::Packages::MetadataType.resolve_type(metadata, ctx)` must never raise.
+ def metadata
+ case object.package_type
+ when 'composer'
+ object.composer_metadatum
+ else
+ nil
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_invitation_type.rb b/app/graphql/types/project_invitation_type.rb
index a5367a4f204..507dc2d59c3 100644
--- a/app/graphql/types/project_invitation_type.rb
+++ b/app/graphql/types/project_invitation_type.rb
@@ -12,7 +12,7 @@ module Types
authorize :read_project
field :project, Types::ProjectType, null: true,
- description: 'Project ID for the project of the invitation'
+ description: 'Project ID for the project of the invitation.'
def project
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.source_id).find
diff --git a/app/graphql/types/project_member_type.rb b/app/graphql/types/project_member_type.rb
index 01731531ae2..1f00df84641 100644
--- a/app/graphql/types/project_member_type.rb
+++ b/app/graphql/types/project_member_type.rb
@@ -12,7 +12,7 @@ module Types
authorize :read_project
field :project, Types::ProjectType, null: true,
- description: 'Project that User is a member of'
+ description: 'Project that User is a member of.'
def project
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.source_id).find
diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb
index 26cb5ab59b5..ee8476f50de 100644
--- a/app/graphql/types/project_statistics_type.rb
+++ b/app/graphql/types/project_statistics_type.rb
@@ -7,23 +7,23 @@ module Types
authorize :read_statistics
field :commit_count, GraphQL::FLOAT_TYPE, null: false,
- description: 'Commit count of the project'
+ description: 'Commit count of the project.'
field :storage_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Storage size of the project in bytes'
+ description: 'Storage size of the project in bytes.'
field :repository_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Repository size of the project in bytes'
+ description: 'Repository size of the project in bytes.'
field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Large File Storage (LFS) object size of the project in bytes'
+ description: 'Large File Storage (LFS) object size of the project in bytes.'
field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Build artifacts size of the project in bytes'
+ description: 'Build artifacts size of the project in bytes.'
field :packages_size, GraphQL::FLOAT_TYPE, null: false,
- description: 'Packages size of the project in bytes'
+ description: 'Packages size of the project in bytes.'
field :wiki_size, GraphQL::FLOAT_TYPE, null: true,
- description: 'Wiki size of the project in bytes'
+ description: 'Wiki size of the project in bytes.'
field :snippets_size, GraphQL::FLOAT_TYPE, null: true,
- description: 'Snippets size of the project in bytes'
+ description: 'Snippets size of the project in bytes.'
field :uploads_size, GraphQL::FLOAT_TYPE, null: true,
- description: 'Uploads size of the project in bytes'
+ description: 'Uploads size of the project in bytes.'
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index f66d8926a9f..7205c615271 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -9,54 +9,58 @@ module Types
expose_permissions Types::PermissionTypes::Project
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the project'
+ description: 'ID of the project.'
field :full_path, GraphQL::ID_TYPE, null: false,
- description: 'Full path of the project'
+ description: 'Full path of the project.'
field :path, GraphQL::STRING_TYPE, null: false,
- description: 'Path of the project'
+ description: 'Path of the project.'
+
+ field :sast_ci_configuration, Types::CiConfiguration::Sast::Type, null: true,
+ calls_gitaly: true,
+ description: 'SAST CI configuration for the project.'
field :name_with_namespace, GraphQL::STRING_TYPE, null: false,
- description: 'Full name of the project with its namespace'
+ description: 'Full name of the project with its namespace.'
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Name of the project (without namespace)'
+ description: 'Name of the project (without namespace).'
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Short description of the project'
+ description: 'Short description of the project.'
markdown_field :description_html, null: true
field :tag_list, GraphQL::STRING_TYPE, null: true,
- description: 'List of project topics (not Git tags)'
+ description: 'List of project topics (not Git tags).'
field :ssh_url_to_repo, GraphQL::STRING_TYPE, null: true,
- description: 'URL to connect to the project via SSH'
+ description: 'URL to connect to the project via SSH.'
field :http_url_to_repo, GraphQL::STRING_TYPE, null: true,
- description: 'URL to connect to the project via HTTPS'
+ description: 'URL to connect to the project via HTTPS.'
field :web_url, GraphQL::STRING_TYPE, null: true,
- description: 'Web URL of the project'
+ description: 'Web URL of the project.'
field :star_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of times the project has been starred'
+ description: 'Number of times the project has been starred.'
field :forks_count, GraphQL::INT_TYPE, null: false, calls_gitaly: true, # 4 times
- description: 'Number of times the project has been forked'
+ description: 'Number of times the project has been forked.'
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of the project creation'
+ description: 'Timestamp of the project creation.'
field :last_activity_at, Types::TimeType, null: true,
- description: 'Timestamp of the project last activity'
+ description: 'Timestamp of the project last activity.'
field :archived, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates the archived status of the project'
+ description: 'Indicates the archived status of the project.'
field :visibility, GraphQL::STRING_TYPE, null: true,
- description: 'Visibility of the project'
+ description: 'Visibility of the project.'
field :container_registry_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if the project stores Docker container images in a container registry'
+ description: 'Indicates if the project stores Docker container images in a container registry.'
field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if shared runners are enabled for the project'
+ description: 'Indicates if shared runners are enabled for the project.'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if the project has Large File Storage (LFS) enabled'
+ description: 'Indicates if the project has Large File Storage (LFS) enabled.'
field :merge_requests_ff_only_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.'
@@ -67,7 +71,7 @@ module Types
description: 'E-mail address of the service desk.'
field :avatar_url, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
- description: 'URL to avatar image file of the project'
+ description: 'URL to avatar image file of the project.'
%i[issues merge_requests wiki snippets].each do |feature|
field "#{feature}_enabled", GraphQL::BOOLEAN_TYPE, null: true,
@@ -79,240 +83,246 @@ module Types
end
field :jobs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if CI/CD pipeline jobs are enabled for the current user'
+ description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
field :public_jobs, GraphQL::BOOLEAN_TYPE, method: :public_builds, null: true,
- description: 'Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts'
+ description: 'Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.'
field :open_issues_count, GraphQL::INT_TYPE, null: true,
- description: 'Number of open issues for the project'
+ description: 'Number of open issues for the project.'
field :import_status, GraphQL::STRING_TYPE, null: true,
- description: 'Status of import background job of the project'
+ description: 'Status of import background job of the project.'
field :jira_import_status, GraphQL::STRING_TYPE, null: true,
- description: 'Status of Jira import background job of the project'
+ description: 'Status of Jira import background job of the project.'
field :only_allow_merge_if_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if merge requests of the project can only be merged with successful jobs'
+ description: 'Indicates if merge requests of the project can only be merged with successful jobs.'
field :allow_merge_on_skipped_pipeline, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs'
+ description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs.'
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if users can request member access to the project'
+ description: 'Indicates if users can request member access to the project.'
field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved'
+ description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved.'
field :printing_merge_request_link_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: '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'
+ description: '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.'
field :remove_source_branch_after_merge, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project'
+ description: 'Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.'
field :autoclose_referenced_issues, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if issues referenced by merge requests and commits within the default branch are closed automatically'
+ description: 'Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.'
field :suggestion_commit_message, GraphQL::STRING_TYPE, null: true,
- description: 'The commit message used to apply merge request suggestions'
+ description: 'The commit message used to apply merge request suggestions.'
field :squash_read_only, GraphQL::BOOLEAN_TYPE, null: false, method: :squash_readonly?,
- description: 'Indicates if squash readonly is enabled'
+ description: 'Indicates if `squashReadOnly` is enabled.'
field :namespace, Types::NamespaceType, null: true,
- description: 'Namespace of the project'
+ description: 'Namespace of the project.'
field :group, Types::GroupType, null: true,
- description: 'Group of the project'
+ description: 'Group of the project.'
field :statistics, Types::ProjectStatisticsType,
null: true,
- description: 'Statistics of the project'
+ description: 'Statistics of the project.'
field :repository, Types::RepositoryType, null: true,
- description: 'Git repository of the project'
+ description: 'Git repository of the project.'
field :merge_requests,
Types::MergeRequestType.connection_type,
null: true,
- description: 'Merge requests of the project',
+ description: 'Merge requests of the project.',
extras: [:lookahead],
resolver: Resolvers::ProjectMergeRequestsResolver
field :merge_request,
Types::MergeRequestType,
null: true,
- description: 'A single merge request of the project',
+ description: 'A single merge request of the project.',
resolver: Resolvers::MergeRequestsResolver.single
field :issues,
Types::IssueType.connection_type,
null: true,
- description: 'Issues of the project',
+ description: 'Issues of the project.',
extras: [:lookahead],
resolver: Resolvers::IssuesResolver
field :issue_status_counts,
Types::IssueStatusCountsType,
null: true,
- description: 'Counts of issues by status for the project',
+ description: 'Counts of issues by status for the project.',
extras: [:lookahead],
resolver: Resolvers::IssueStatusCountsResolver
field :milestones, Types::MilestoneType.connection_type, null: true,
- description: 'Milestones of the project',
+ description: 'Milestones of the project.',
resolver: Resolvers::ProjectMilestonesResolver
field :project_members,
- description: 'Members of the project',
+ description: 'Members of the project.',
resolver: Resolvers::ProjectMembersResolver
field :environments,
Types::EnvironmentType.connection_type,
null: true,
- description: 'Environments of the project',
+ description: 'Environments of the project.',
resolver: Resolvers::EnvironmentsResolver
field :environment,
Types::EnvironmentType,
null: true,
- description: 'A single environment of the project',
+ description: 'A single environment of the project.',
resolver: Resolvers::EnvironmentsResolver.single
field :issue,
Types::IssueType,
null: true,
- description: 'A single issue of the project',
+ description: 'A single issue of the project.',
resolver: Resolvers::IssuesResolver.single
- field :packages, Types::Packages::PackageType.connection_type, null: true,
- description: 'Packages of the project',
+ field :packages,
+ description: 'Packages of the project.',
resolver: Resolvers::PackagesResolver
field :pipelines,
null: true,
- description: 'Build pipelines of the project',
+ description: 'Build pipelines of the project.',
extras: [:lookahead],
resolver: Resolvers::ProjectPipelinesResolver
field :pipeline,
Types::Ci::PipelineType,
null: true,
- description: 'Build pipeline of the project',
+ description: 'Build pipeline of the project.',
resolver: Resolvers::ProjectPipelineResolver
field :ci_cd_settings,
Types::Ci::CiCdSettingType,
null: true,
- description: 'CI/CD settings for the project'
+ description: 'CI/CD settings for the project.'
field :sentry_detailed_error,
Types::ErrorTracking::SentryDetailedErrorType,
null: true,
- description: 'Detailed version of a Sentry error on the project',
+ description: 'Detailed version of a Sentry error on the project.',
resolver: Resolvers::ErrorTracking::SentryDetailedErrorResolver
field :grafana_integration,
Types::GrafanaIntegrationType,
null: true,
- description: 'Grafana integration details for the project',
+ description: 'Grafana integration details for the project.',
resolver: Resolvers::Projects::GrafanaIntegrationResolver
field :snippets,
Types::SnippetType.connection_type,
null: true,
- description: 'Snippets of the project',
+ description: 'Snippets of the project.',
resolver: Resolvers::Projects::SnippetsResolver
field :sentry_errors,
Types::ErrorTracking::SentryErrorCollectionType,
null: true,
- description: 'Paginated collection of Sentry errors on the project',
+ description: 'Paginated collection of Sentry errors on the project.',
resolver: Resolvers::ErrorTracking::SentryErrorCollectionResolver
field :boards,
Types::BoardType.connection_type,
null: true,
- description: 'Boards of the project',
+ description: 'Boards of the project.',
max_page_size: 2000,
resolver: Resolvers::BoardsResolver
field :board,
Types::BoardType,
null: true,
- description: 'A single board of the project',
+ description: 'A single board of the project.',
resolver: Resolvers::BoardResolver
field :jira_imports,
Types::JiraImportType.connection_type,
null: true,
- description: 'Jira imports into the project'
+ description: 'Jira imports into the project.'
field :services,
Types::Projects::ServiceType.connection_type,
null: true,
- description: 'Project services',
+ description: 'Project services.',
resolver: Resolvers::Projects::ServicesResolver
field :alert_management_alerts,
Types::AlertManagement::AlertType.connection_type,
null: true,
- description: 'Alert Management alerts of the project',
+ description: 'Alert Management alerts of the project.',
extras: [:lookahead],
resolver: Resolvers::AlertManagement::AlertResolver
field :alert_management_alert,
Types::AlertManagement::AlertType,
null: true,
- description: 'A single Alert Management alert of the project',
+ description: 'A single Alert Management alert of the project.',
resolver: Resolvers::AlertManagement::AlertResolver.single
field :alert_management_alert_status_counts,
Types::AlertManagement::AlertStatusCountsType,
null: true,
- description: 'Counts of alerts by status for the project',
+ description: 'Counts of alerts by status for the project.',
resolver: Resolvers::AlertManagement::AlertStatusCountsResolver
field :alert_management_integrations,
Types::AlertManagement::IntegrationType.connection_type,
null: true,
- description: 'Integrations which can receive alerts for the project',
+ description: 'Integrations which can receive alerts for the project.',
resolver: Resolvers::AlertManagement::IntegrationsResolver
field :releases,
Types::ReleaseType.connection_type,
null: true,
- description: 'Releases of the project',
+ description: 'Releases of the project.',
resolver: Resolvers::ReleasesResolver
field :release,
Types::ReleaseType,
null: true,
- description: 'A single release of the project',
+ description: 'A single release of the project.',
resolver: Resolvers::ReleasesResolver.single,
authorize: :download_code
field :container_expiration_policy,
Types::ContainerExpirationPolicyType,
null: true,
- description: 'The container expiration policy of the project'
+ description: 'The container expiration policy of the project.'
field :container_repositories,
Types::ContainerRepositoryType.connection_type,
null: true,
- description: 'Container repositories of the project',
+ description: 'Container repositories of the project.',
resolver: Resolvers::ContainerRepositoriesResolver
field :container_repositories_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of container repositories in the project'
+ description: 'Number of container repositories in the project.'
field :label,
Types::LabelType,
null: true,
- description: 'A label available on this project' do
+ description: 'A label available on this project.' do
argument :title, GraphQL::STRING_TYPE,
required: true,
- description: 'Title of the label'
+ description: 'Title of the label.'
end
+ field :terraform_state,
+ Types::Terraform::StateType,
+ null: true,
+ description: 'Find a single Terraform state by name.',
+ resolver: Resolvers::Terraform::StatesResolver.single
+
field :terraform_states,
Types::Terraform::StateType.connection_type,
null: true,
- description: 'Terraform states associated with the project',
+ description: 'Terraform states associated with the project.',
resolver: Resolvers::Terraform::StatesResolver
field :pipeline_analytics, Types::Ci::AnalyticsType, null: true,
- description: 'Pipeline analytics',
+ description: 'Pipeline analytics.',
resolver: Resolvers::ProjectPipelineStatisticsResolver
def label(title:)
@@ -327,17 +337,8 @@ module Types
field :labels,
Types::LabelType.connection_type,
null: true,
- description: 'Labels available on this project' do
- argument :search_term, GraphQL::STRING_TYPE,
- required: false,
- description: 'A search term to find labels with'
- end
-
- def labels(search_term: nil)
- LabelsFinder
- .new(current_user, project: project, search: search_term)
- .execute
- end
+ description: 'Labels available on this project.',
+ resolver: Resolvers::LabelsResolver
def avatar_url
object.avatar_url(only_path: false)
@@ -359,6 +360,12 @@ module Types
project.container_repositories.size
end
+ def sast_ci_configuration
+ return unless Ability.allowed?(current_user, :download_code, object)
+
+ ::Security::CiConfiguration::SastParserService.new(object).configuration
+ end
+
private
def project
diff --git a/app/graphql/types/projects/service_type.rb b/app/graphql/types/projects/service_type.rb
index 4ae7cb77904..9ce325c4655 100644
--- a/app/graphql/types/projects/service_type.rb
+++ b/app/graphql/types/projects/service_type.rb
@@ -9,9 +9,9 @@ module Types
# TODO: Add all the fields that we want to expose for the project services integrations
# https://gitlab.com/gitlab-org/gitlab/-/issues/213088
field :type, GraphQL::STRING_TYPE, null: true,
- description: 'Class name of the service'
+ description: 'Class name of the service.'
field :active, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if the service is active'
+ description: 'Indicates if the service is active.'
definition_methods do
def resolve_type(object, context)
diff --git a/app/graphql/types/projects/service_type_enum.rb b/app/graphql/types/projects/service_type_enum.rb
index 34e06c67be6..fcb36fc233d 100644
--- a/app/graphql/types/projects/service_type_enum.rb
+++ b/app/graphql/types/projects/service_type_enum.rb
@@ -6,7 +6,7 @@ module Types
graphql_name 'ServiceType'
::Service.available_services_types(include_dev: false).each do |service_type|
- value service_type.underscore.upcase, value: service_type
+ value service_type.underscore.upcase, value: service_type, description: "#{service_type} type"
end
end
end
diff --git a/app/graphql/types/projects/services/jira_project_type.rb b/app/graphql/types/projects/services/jira_project_type.rb
index ccf9107f398..90abce2b4c3 100644
--- a/app/graphql/types/projects/services/jira_project_type.rb
+++ b/app/graphql/types/projects/services/jira_project_type.rb
@@ -8,12 +8,12 @@ module Types
graphql_name 'JiraProject'
field :key, GraphQL::STRING_TYPE, null: false,
- description: 'Key of the Jira project'
+ description: 'Key of the Jira project.'
field :project_id, GraphQL::INT_TYPE, null: false,
- description: 'ID of the Jira project',
+ description: 'ID of the Jira project.',
method: :id
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the Jira project'
+ description: 'Name of the Jira project.'
end
# rubocop:enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/projects/services/jira_service_type.rb b/app/graphql/types/projects/services/jira_service_type.rb
index cb0712249e3..425a283c674 100644
--- a/app/graphql/types/projects/services/jira_service_type.rb
+++ b/app/graphql/types/projects/services/jira_service_type.rb
@@ -13,7 +13,7 @@ module Types
field :projects,
Types::Projects::Services::JiraProjectType.connection_type,
null: true,
- description: 'List of all Jira projects fetched through Jira REST API',
+ description: 'List of all Jira projects fetched through Jira REST API.',
resolver: Resolvers::Projects::JiraProjectsResolver
end
end
diff --git a/app/graphql/types/prometheus_alert_type.rb b/app/graphql/types/prometheus_alert_type.rb
index 1d09a8dbeb7..8e800536675 100644
--- a/app/graphql/types/prometheus_alert_type.rb
+++ b/app/graphql/types/prometheus_alert_type.rb
@@ -10,11 +10,11 @@ module Types
present_using PrometheusAlertPresenter
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the alert condition'
+ description: 'ID of the alert condition.'
field :humanized_text,
GraphQL::STRING_TYPE,
null: false,
- description: 'The human-readable text of the alert condition'
+ description: 'The human-readable text of the alert condition.'
end
end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 0e0c060f374..1d1ab4f2e17 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -10,90 +10,93 @@ module Types
field :project, Types::ProjectType,
null: true,
resolver: Resolvers::ProjectResolver,
- description: "Find a project"
+ description: "Find a project."
field :projects, Types::ProjectType.connection_type,
null: true,
resolver: Resolvers::ProjectsResolver,
- description: "Find projects visible to the current user"
+ description: "Find projects visible to the current user."
field :group, Types::GroupType,
null: true,
resolver: Resolvers::GroupResolver,
- description: "Find a group"
+ description: "Find a group."
field :current_user, Types::UserType,
null: true,
- description: "Get information about current user"
+ description: "Get information about current user."
field :namespace, Types::NamespaceType,
null: true,
resolver: Resolvers::NamespaceResolver,
- description: "Find a namespace"
+ description: "Find a namespace."
field :metadata, Types::MetadataType,
null: true,
resolver: Resolvers::MetadataResolver,
- description: 'Metadata about GitLab'
+ description: 'Metadata about GitLab.'
field :snippets,
Types::SnippetType.connection_type,
null: true,
resolver: Resolvers::SnippetsResolver,
- description: 'Find Snippets visible to the current user'
+ description: 'Find Snippets visible to the current user.'
field :design_management, Types::DesignManagementType,
null: false,
- description: 'Fields related to design management'
+ description: 'Fields related to design management.'
field :milestone, ::Types::MilestoneType,
null: true,
- description: 'Find a milestone' do
- argument :id, ::Types::GlobalIDType[Milestone], required: true, description: 'Find a milestone by its ID'
+ description: 'Find a milestone.' do
+ argument :id, ::Types::GlobalIDType[Milestone], required: true, description: 'Find a milestone by its ID.'
end
field :container_repository, Types::ContainerRepositoryDetailsType,
null: true,
- description: 'Find a container repository' do
- argument :id, ::Types::GlobalIDType[::ContainerRepository], required: true, description: 'The global ID of the container repository'
+ description: 'Find a container repository.' do
+ argument :id, ::Types::GlobalIDType[::ContainerRepository], required: true, description: 'The global ID of the container repository.'
end
- field :package_composer_details, Types::Packages::Composer::DetailsType,
- null: true,
- description: 'Find a composer package',
+ field :package,
+ description: 'Find a package.',
resolver: Resolvers::PackageDetailsResolver
field :user, Types::UserType,
null: true,
- description: 'Find a user',
+ description: 'Find a user.',
resolver: Resolvers::UserResolver
field :users, Types::UserType.connection_type,
null: true,
- description: 'Find users',
+ description: 'Find users.',
resolver: Resolvers::UsersResolver
field :echo, GraphQL::STRING_TYPE, null: false,
- description: 'Text to echo back',
+ description: 'Text to echo back.',
resolver: Resolvers::EchoResolver
field :issue, Types::IssueType,
null: true,
- description: 'Find an issue' do
- argument :id, ::Types::GlobalIDType[::Issue], required: true, description: 'The global ID of the Issue'
+ description: 'Find an issue.' do
+ argument :id, ::Types::GlobalIDType[::Issue], required: true, description: 'The global ID of the Issue.'
end
field :instance_statistics_measurements, Types::Admin::Analytics::InstanceStatistics::MeasurementType.connection_type,
null: true,
- description: 'Get statistics on the instance',
+ description: 'Get statistics on the instance.',
resolver: Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsResolver
+ field :ci_application_settings, Types::Ci::ApplicationSettingType,
+ null: true,
+ description: 'CI related settings that apply to the entire instance.'
+
field :runner_platforms, Types::Ci::RunnerPlatformType.connection_type,
- null: true, description: 'Supported runner platforms',
+ null: true, description: 'Supported runner platforms.',
resolver: Resolvers::Ci::RunnerPlatformsResolver
field :runner_setup, Types::Ci::RunnerSetupType, null: true,
- description: 'Get runner setup instructions',
+ description: 'Get runner setup instructions.',
resolver: Resolvers::Ci::RunnerSetupResolver
field :ci_config, Types::Ci::Config::ConfigType, null: true,
@@ -129,6 +132,14 @@ module Types
def current_user
context[:current_user]
end
+
+ def ci_application_settings
+ application_settings
+ end
+
+ def application_settings
+ Gitlab::CurrentSettings.current_application_settings
+ end
end
end
diff --git a/app/graphql/types/range_input_type.rb b/app/graphql/types/range_input_type.rb
index 766e523a99e..b75c3669fbf 100644
--- a/app/graphql/types/range_input_type.rb
+++ b/app/graphql/types/range_input_type.rb
@@ -9,11 +9,11 @@ module Types
@subtypes[[type, closed]] ||= Class.new(self) do
argument :start, type,
required: closed,
- description: 'The start of the range'
+ description: 'The start of the range.'
argument :end, type,
required: closed,
- description: 'The end of the range'
+ description: 'The end of the range.'
end
end
diff --git a/app/graphql/types/release_asset_link_input_type.rb b/app/graphql/types/release_asset_link_input_type.rb
index d13861fad8f..242d19b683f 100644
--- a/app/graphql/types/release_asset_link_input_type.rb
+++ b/app/graphql/types/release_asset_link_input_type.rb
@@ -8,18 +8,18 @@ module Types
argument :name, GraphQL::STRING_TYPE,
required: true,
- description: 'Name of the asset link'
+ description: 'Name of the asset link.'
argument :url, GraphQL::STRING_TYPE,
required: true,
- description: 'URL of the asset link'
+ description: 'URL of the asset link.'
argument :direct_asset_path, GraphQL::STRING_TYPE,
required: false, as: :filepath,
- description: 'Relative path for a direct asset link'
+ description: 'Relative path for a direct asset link.'
argument :link_type, Types::ReleaseAssetLinkTypeEnum,
required: false, default_value: 'other',
- description: 'The type of the asset link'
+ description: 'The type of the asset link.'
end
end
diff --git a/app/graphql/types/release_asset_link_type.rb b/app/graphql/types/release_asset_link_type.rb
index 8fb051f5627..c27e1cf19b3 100644
--- a/app/graphql/types/release_asset_link_type.rb
+++ b/app/graphql/types/release_asset_link_type.rb
@@ -8,18 +8,18 @@ module Types
authorize :read_release
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the link'
+ description: 'ID of the link.'
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the link'
+ description: 'Name of the link.'
field :url, GraphQL::STRING_TYPE, null: true,
- description: 'URL of the link'
+ description: 'URL of the link.'
field :link_type, Types::ReleaseAssetLinkTypeEnum, null: true,
- description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`'
+ description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.'
field :external, GraphQL::BOOLEAN_TYPE, null: true, method: :external?,
- description: 'Indicates the link points to an external resource'
+ description: 'Indicates the link points to an external resource.'
field :direct_asset_url, GraphQL::STRING_TYPE, null: true,
- description: 'Direct asset URL of the link'
+ description: 'Direct asset URL of the link.'
def direct_asset_url
return object.url unless object.filepath
diff --git a/app/graphql/types/release_assets_input_type.rb b/app/graphql/types/release_assets_input_type.rb
index 3fcb517e044..f50be89d43f 100644
--- a/app/graphql/types/release_assets_input_type.rb
+++ b/app/graphql/types/release_assets_input_type.rb
@@ -8,6 +8,6 @@ module Types
argument :links, [Types::ReleaseAssetLinkInputType],
required: false,
- description: 'A list of asset links to associate to the release'
+ description: 'A list of asset links to associate to the release.'
end
end
diff --git a/app/graphql/types/release_assets_type.rb b/app/graphql/types/release_assets_type.rb
index d6042bdbc0b..79c132358e0 100644
--- a/app/graphql/types/release_assets_type.rb
+++ b/app/graphql/types/release_assets_type.rb
@@ -12,10 +12,10 @@ module Types
present_using ReleasePresenter
field :count, GraphQL::INT_TYPE, null: true, method: :assets_count,
- description: 'Number of assets of the release'
+ description: 'Number of assets of the release.'
field :links, Types::ReleaseAssetLinkType.connection_type, null: true,
- description: 'Asset links of the release'
+ description: 'Asset links of the release.'
field :sources, Types::ReleaseSourceType.connection_type, null: true,
- description: 'Sources of the release'
+ description: 'Sources of the release.'
end
end
diff --git a/app/graphql/types/release_links_type.rb b/app/graphql/types/release_links_type.rb
index 619bb1e6c3a..a51b80e1e13 100644
--- a/app/graphql/types/release_links_type.rb
+++ b/app/graphql/types/release_links_type.rb
@@ -11,19 +11,19 @@ module Types
present_using ReleasePresenter
field :self_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the release'
+ description: 'HTTP URL of the release.'
field :edit_url, GraphQL::STRING_TYPE, null: true,
- description: "HTTP URL of the release's edit page",
+ description: "HTTP URL of the release's edit page.",
authorize: :update_release
field :opened_merge_requests_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the merge request page, filtered by this release and `state=open`'
+ description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.'
field :merged_merge_requests_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`'
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.'
field :closed_merge_requests_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`'
+ description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.'
field :opened_issues_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the issues page, filtered by this release and `state=open`'
+ description: 'HTTP URL of the issues page, filtered by this release and `state=open`.'
field :closed_issues_url, GraphQL::STRING_TYPE, null: true,
- description: 'HTTP URL of the issues page, filtered by this release and `state=closed`'
+ description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.'
end
end
diff --git a/app/graphql/types/release_source_type.rb b/app/graphql/types/release_source_type.rb
index 891da472116..10fc202514d 100644
--- a/app/graphql/types/release_source_type.rb
+++ b/app/graphql/types/release_source_type.rb
@@ -8,8 +8,8 @@ module Types
authorize :download_code
field :format, GraphQL::STRING_TYPE, null: true,
- description: 'Format of the source'
+ description: 'Format of the source.'
field :url, GraphQL::STRING_TYPE, null: true,
- description: 'Download URL of the source'
+ description: 'Download URL of the source.'
end
end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index e7afa7ce7f7..81813a10a3e 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -14,34 +14,34 @@ module Types
present_using ReleasePresenter
field :tag_name, GraphQL::STRING_TYPE, null: true, method: :tag,
- description: 'Name of the tag associated with the release',
+ description: 'Name of the tag associated with the release.',
authorize: :download_code
field :tag_path, GraphQL::STRING_TYPE, null: true,
- description: 'Relative web path to the tag associated with the release',
+ description: 'Relative web path to the tag associated with the release.',
authorize: :download_code
field :description, GraphQL::STRING_TYPE, null: true,
- description: 'Description (also known as "release notes") of the release'
+ description: 'Description (also known as "release notes") of the release.'
markdown_field :description_html, null: true
field :name, GraphQL::STRING_TYPE, null: true,
- description: 'Name of the release'
+ description: 'Name of the release.'
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of when the release was created'
+ description: 'Timestamp of when the release was created.'
field :released_at, Types::TimeType, null: true,
- description: 'Timestamp of when the release was released'
+ description: 'Timestamp of when the release was released.'
field :upcoming_release, GraphQL::BOOLEAN_TYPE, null: true, method: :upcoming_release?,
- description: 'Indicates the release is an upcoming release'
+ description: 'Indicates the release is an upcoming release.'
field :assets, Types::ReleaseAssetsType, null: true, method: :itself,
- description: 'Assets of the release'
+ description: 'Assets of the release.'
field :links, Types::ReleaseLinksType, null: true, method: :itself,
- description: 'Links of the release'
+ description: 'Links of the release.'
field :milestones, Types::MilestoneType.connection_type, null: true,
- description: 'Milestones associated to the release',
+ description: 'Milestones associated to the release.',
resolver: ::Resolvers::ReleaseMilestonesResolver
field :evidences, Types::EvidenceType.connection_type, null: true,
- description: 'Evidence for the release'
+ description: 'Evidence for the release.'
field :author, Types::UserType, null: true,
- description: 'User that created the release'
+ description: 'User that created the release.'
def author
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, release.author_id).find
@@ -49,7 +49,7 @@ module Types
field :commit, Types::CommitType, null: true,
complexity: 10, calls_gitaly: true,
- description: 'The commit associated with the release'
+ description: 'The commit associated with the release.'
def commit
return if release.sha.nil?
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index 5b86871142c..e319a5f3124 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -7,12 +7,12 @@ module Types
authorize :download_code
field :root_ref, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
- description: 'Default branch of the repository'
+ description: 'Default branch of the repository.'
field :empty, GraphQL::BOOLEAN_TYPE, null: false, method: :empty?, calls_gitaly: true,
- description: 'Indicates repository has no visible content'
+ description: 'Indicates repository has no visible content.'
field :exists, GraphQL::BOOLEAN_TYPE, null: false, method: :exists?, calls_gitaly: true,
- description: 'Indicates a corresponding Git repository exists on disk'
+ description: 'Indicates a corresponding Git repository exists on disk.'
field :tree, Types::Tree::TreeType, null: true, resolver: Resolvers::TreeResolver, calls_gitaly: true,
- description: 'Tree of the repository'
+ description: 'Tree of the repository.'
end
end
diff --git a/app/graphql/types/resolvable_interface.rb b/app/graphql/types/resolvable_interface.rb
index a39092c70ca..a9d745c2bc1 100644
--- a/app/graphql/types/resolvable_interface.rb
+++ b/app/graphql/types/resolvable_interface.rb
@@ -8,7 +8,7 @@ module Types
field :resolved_by, Types::UserType,
null: true,
- description: 'User who resolved the object'
+ description: 'User who resolved the object.'
def resolved_by
return unless object.resolved_by_id
@@ -17,12 +17,12 @@ module Types
end
field :resolved, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if the object is resolved',
+ description: 'Indicates if the object is resolved.',
method: :resolved?
field :resolvable, GraphQL::BOOLEAN_TYPE, null: false,
- description: 'Indicates if the object can be resolved',
+ description: 'Indicates if the object can be resolved.',
method: :resolvable?
field :resolved_at, Types::TimeType, null: true,
- description: 'Timestamp of when the object was resolved'
+ description: 'Timestamp of when the object was resolved.'
end
end
diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb
index 21448b33bb5..102639f19d9 100644
--- a/app/graphql/types/root_storage_statistics_type.rb
+++ b/app/graphql/types/root_storage_statistics_type.rb
@@ -6,14 +6,14 @@ module Types
authorize :read_statistics
- field :storage_size, GraphQL::FLOAT_TYPE, null: false, description: 'The total storage in bytes'
- field :repository_size, GraphQL::FLOAT_TYPE, null: false, description: 'The Git repository size in bytes'
- field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false, description: 'The LFS objects size in bytes'
- field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI artifacts size in bytes'
- field :packages_size, GraphQL::FLOAT_TYPE, null: false, description: 'The packages size in bytes'
- field :wiki_size, GraphQL::FLOAT_TYPE, null: false, description: 'The wiki size in bytes'
- field :snippets_size, GraphQL::FLOAT_TYPE, null: false, description: 'The snippets size in bytes'
- field :pipeline_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI pipeline artifacts size in bytes'
- field :uploads_size, GraphQL::FLOAT_TYPE, null: false, description: 'The uploads size in bytes'
+ field :storage_size, GraphQL::FLOAT_TYPE, null: false, description: 'The total storage in bytes.'
+ field :repository_size, GraphQL::FLOAT_TYPE, null: false, description: 'The Git repository size in bytes.'
+ field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false, description: 'The LFS objects size in bytes.'
+ field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI artifacts size in bytes.'
+ field :packages_size, GraphQL::FLOAT_TYPE, null: false, description: 'The packages size in bytes.'
+ field :wiki_size, GraphQL::FLOAT_TYPE, null: false, description: 'The wiki size in bytes.'
+ field :snippets_size, GraphQL::FLOAT_TYPE, null: false, description: 'The snippets size in bytes.'
+ field :pipeline_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI pipeline artifacts size in bytes.'
+ field :uploads_size, GraphQL::FLOAT_TYPE, null: false, description: 'The uploads size in bytes.'
end
end
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index f587adf207f..2f79ec48c04 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -14,15 +14,15 @@ module Types
expose_permissions Types::PermissionTypes::Snippet
field :id, Types::GlobalIDType[::Snippet],
- description: 'ID of the snippet',
+ description: 'ID of the snippet.',
null: false
field :title, GraphQL::STRING_TYPE,
- description: 'Title of the snippet',
+ description: 'Title of the snippet.',
null: false
field :project, Types::ProjectType,
- description: 'The project the snippet is associated with',
+ description: 'The project the snippet is associated with.',
null: true,
authorize: :read_project
@@ -30,56 +30,56 @@ module Types
# when the admin setting restricted visibility
# level is set to public
field :author, Types::UserType,
- description: 'The owner of the snippet',
+ description: 'The owner of the snippet.',
null: true
field :file_name, GraphQL::STRING_TYPE,
- description: 'File Name of the snippet',
+ description: 'File Name of the snippet.',
null: true
field :description, GraphQL::STRING_TYPE,
- description: 'Description of the snippet',
+ description: 'Description of the snippet.',
null: true
field :visibility_level, Types::VisibilityLevelsEnum,
- description: 'Visibility Level of the snippet',
+ description: 'Visibility Level of the snippet.',
null: false
field :created_at, Types::TimeType,
- description: 'Timestamp this snippet was created',
+ description: 'Timestamp this snippet was created.',
null: false
field :updated_at, Types::TimeType,
- description: 'Timestamp this snippet was updated',
+ description: 'Timestamp this snippet was updated.',
null: false
field :web_url, type: GraphQL::STRING_TYPE,
- description: 'Web URL of the snippet',
+ description: 'Web URL of the snippet.',
null: false
field :raw_url, type: GraphQL::STRING_TYPE,
- description: 'Raw URL of the snippet',
+ description: 'Raw URL of the snippet.',
null: false
field :blob, type: Types::Snippets::BlobType,
- description: 'Snippet blob',
+ description: 'Snippet blob.',
calls_gitaly: true,
null: false,
deprecated: { reason: 'Use `blobs`', milestone: '13.3' }
field :blobs, type: Types::Snippets::BlobType.connection_type,
- description: 'Snippet blobs',
+ description: 'Snippet blobs.',
calls_gitaly: true,
null: true,
resolver: Resolvers::Snippets::BlobsResolver
field :ssh_url_to_repo, type: GraphQL::STRING_TYPE,
- description: 'SSH URL to the snippet repository',
+ description: 'SSH URL to the snippet repository.',
calls_gitaly: true,
null: true
field :http_url_to_repo, type: GraphQL::STRING_TYPE,
- description: 'HTTP URL to the snippet repository',
+ description: 'HTTP URL to the snippet repository.',
calls_gitaly: true,
null: true
diff --git a/app/graphql/types/snippets/blob_action_input_type.rb b/app/graphql/types/snippets/blob_action_input_type.rb
index ccb6ae3f2c1..c4289375f6b 100644
--- a/app/graphql/types/snippets/blob_action_input_type.rb
+++ b/app/graphql/types/snippets/blob_action_input_type.rb
@@ -7,19 +7,19 @@ module Types
description 'Represents an action to perform over a snippet file'
argument :action, Types::Snippets::BlobActionEnum,
- description: 'Type of input action',
+ description: 'Type of input action.',
required: true
argument :previous_path, GraphQL::STRING_TYPE,
- description: 'Previous path of the snippet file',
+ description: 'Previous path of the snippet file.',
required: false
argument :file_path, GraphQL::STRING_TYPE,
- description: 'Path of the snippet file',
+ description: 'Path of the snippet file.',
required: true
argument :content, GraphQL::STRING_TYPE,
- description: 'Snippet file content',
+ description: 'Snippet file content.',
required: false
end
end
diff --git a/app/graphql/types/snippets/blob_type.rb b/app/graphql/types/snippets/blob_type.rb
index dcde1e5a73b..fb0c1d9409b 100644
--- a/app/graphql/types/snippets/blob_type.rb
+++ b/app/graphql/types/snippets/blob_type.rb
@@ -9,53 +9,53 @@ module Types
present_using SnippetBlobPresenter
field :rich_data, GraphQL::STRING_TYPE,
- description: 'Blob highlighted data',
+ description: 'Blob highlighted data.',
null: true
field :plain_data, GraphQL::STRING_TYPE,
- description: 'Blob plain highlighted data',
+ description: 'Blob plain highlighted data.',
calls_gitaly: true,
null: true
field :raw_path, GraphQL::STRING_TYPE,
- description: 'Blob raw content endpoint path',
+ description: 'Blob raw content endpoint path.',
null: false
field :size, GraphQL::INT_TYPE,
- description: 'Blob size',
+ description: 'Blob size.',
null: false
field :binary, GraphQL::BOOLEAN_TYPE,
- description: 'Shows whether the blob is binary',
+ description: 'Shows whether the blob is binary.',
method: :binary?,
null: false
field :name, GraphQL::STRING_TYPE,
- description: 'Blob name',
+ description: 'Blob name.',
null: true
field :path, GraphQL::STRING_TYPE,
- description: 'Blob path',
+ description: 'Blob path.',
null: true
field :simple_viewer, type: Types::Snippets::BlobViewerType,
- description: 'Blob content simple viewer',
+ description: 'Blob content simple viewer.',
null: false
field :rich_viewer, type: Types::Snippets::BlobViewerType,
- description: 'Blob content rich viewer',
+ description: 'Blob content rich viewer.',
null: true
field :mode, type: GraphQL::STRING_TYPE,
- description: 'Blob mode',
+ description: 'Blob mode.',
null: true
field :external_storage, type: GraphQL::STRING_TYPE,
- description: 'Blob external storage',
+ description: 'Blob external storage.',
null: true
field :rendered_as_text, type: GraphQL::BOOLEAN_TYPE,
- description: 'Shows whether the blob is rendered as text',
+ description: 'Shows whether the blob is rendered as text.',
method: :rendered_as_text?,
null: false
end
diff --git a/app/graphql/types/snippets/blob_viewer_type.rb b/app/graphql/types/snippets/blob_viewer_type.rb
index a2ffa144066..9e77457c843 100644
--- a/app/graphql/types/snippets/blob_viewer_type.rb
+++ b/app/graphql/types/snippets/blob_viewer_type.rb
@@ -7,34 +7,34 @@ module Types
description 'Represents how the blob content should be displayed'
field :type, Types::BlobViewers::TypeEnum,
- description: 'Type of blob viewer',
+ description: 'Type of blob viewer.',
null: false
field :load_async, GraphQL::BOOLEAN_TYPE,
- description: 'Shows whether the blob content is loaded async',
+ description: 'Shows whether the blob content is loaded asynchronously.',
null: false
field :collapsed, GraphQL::BOOLEAN_TYPE,
- description: 'Shows whether the blob should be displayed collapsed',
+ description: 'Shows whether the blob should be displayed collapsed.',
method: :collapsed?,
null: false
field :too_large, GraphQL::BOOLEAN_TYPE,
- description: 'Shows whether the blob too large to be displayed',
+ description: 'Shows whether the blob too large to be displayed.',
method: :too_large?,
null: false
field :render_error, GraphQL::STRING_TYPE,
- description: 'Error rendering the blob content',
+ description: 'Error rendering the blob content.',
null: true
field :file_type, GraphQL::STRING_TYPE,
- description: 'Content file type',
+ description: 'Content file type.',
method: :partial_name,
null: false
field :loading_partial_name, GraphQL::STRING_TYPE,
- description: 'Loading partial name',
+ description: 'Loading partial name.',
null: false
def collapsed
diff --git a/app/graphql/types/task_completion_status.rb b/app/graphql/types/task_completion_status.rb
index 73a8b4f3020..6837256f202 100644
--- a/app/graphql/types/task_completion_status.rb
+++ b/app/graphql/types/task_completion_status.rb
@@ -9,9 +9,9 @@ module Types
description 'Completion status of tasks'
field :count, GraphQL::INT_TYPE, null: false,
- description: 'Number of total tasks'
+ description: 'Number of total tasks.'
field :completed_count, GraphQL::INT_TYPE, null: false,
- description: 'Number of completed tasks'
+ description: 'Number of completed tasks.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/terraform/state_type.rb b/app/graphql/types/terraform/state_type.rb
index d97e673bf31..9e2c47a9ece 100644
--- a/app/graphql/types/terraform/state_type.rb
+++ b/app/graphql/types/terraform/state_type.rb
@@ -11,32 +11,32 @@ module Types
field :id, GraphQL::ID_TYPE,
null: false,
- description: 'ID of the Terraform state'
+ description: 'ID of the Terraform state.'
field :name, GraphQL::STRING_TYPE,
null: false,
- description: 'Name of the Terraform state'
+ description: 'Name of the Terraform state.'
field :locked_by_user, Types::UserType,
null: true,
- description: 'The user currently holding a lock on the Terraform state'
+ description: 'The user currently holding a lock on the Terraform state.'
field :locked_at, Types::TimeType,
null: true,
- description: 'Timestamp the Terraform state was locked'
+ description: 'Timestamp the Terraform state was locked.'
field :latest_version, Types::Terraform::StateVersionType,
complexity: 3,
null: true,
- description: 'The latest version of the Terraform state'
+ description: 'The latest version of the Terraform state.'
field :created_at, Types::TimeType,
null: false,
- description: 'Timestamp the Terraform state was created'
+ description: 'Timestamp the Terraform state was created.'
field :updated_at, Types::TimeType,
null: false,
- description: 'Timestamp the Terraform state was updated'
+ description: 'Timestamp the Terraform state was updated.'
def locked_by_user
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.locked_by_user_id).find
diff --git a/app/graphql/types/terraform/state_version_type.rb b/app/graphql/types/terraform/state_version_type.rb
index a3af5c876ca..2cd2ec8dcda 100644
--- a/app/graphql/types/terraform/state_version_type.rb
+++ b/app/graphql/types/terraform/state_version_type.rb
@@ -11,32 +11,32 @@ module Types
field :id, GraphQL::ID_TYPE,
null: false,
- description: 'ID of the Terraform state version'
+ description: 'ID of the Terraform state version.'
field :created_by_user, Types::UserType,
null: true,
- description: 'The user that created this version'
+ description: 'The user that created this version.'
field :download_path, GraphQL::STRING_TYPE,
null: true,
- description: "URL for downloading the version's JSON file"
+ description: "URL for downloading the version's JSON file."
field :job, Types::Ci::JobType,
null: true,
- description: 'The job that created this version'
+ description: 'The job that created this version.'
field :serial, GraphQL::INT_TYPE,
null: true,
- description: 'Serial number of the version',
+ description: 'Serial number of the version.',
method: :version
field :created_at, Types::TimeType,
null: false,
- description: 'Timestamp the version was created'
+ description: 'Timestamp the version was created.'
field :updated_at, Types::TimeType,
null: false,
- description: 'Timestamp the version was updated'
+ description: 'Timestamp the version was updated.'
def created_by_user
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.created_by_user_id).find
diff --git a/app/graphql/types/todo_type.rb b/app/graphql/types/todo_type.rb
index 3694980ef93..3b983060de2 100644
--- a/app/graphql/types/todo_type.rb
+++ b/app/graphql/types/todo_type.rb
@@ -3,49 +3,49 @@
module Types
class TodoType < BaseObject
graphql_name 'Todo'
- description 'Representing a todo entry'
+ description 'Representing a to-do entry'
present_using TodoPresenter
authorize :read_todo
field :id, GraphQL::ID_TYPE,
- description: 'ID of the todo',
+ description: 'ID of the to-do item.',
null: false
field :project, Types::ProjectType,
- description: 'The project this todo is associated with',
+ description: 'The project this to-do item is associated with.',
null: true,
authorize: :read_project
field :group, Types::GroupType,
- description: 'Group this todo is associated with',
+ description: 'Group this to-do item is associated with.',
null: true,
authorize: :read_group
field :author, Types::UserType,
- description: 'The author of this todo',
+ description: 'The author of this to-do item.',
null: false
field :action, Types::TodoActionEnum,
- description: 'Action of the todo',
+ description: 'Action of the to-do item.',
null: false
field :target_type, Types::TodoTargetEnum,
- description: 'Target type of the todo',
+ description: 'Target type of the to-do item.',
null: false
field :body, GraphQL::STRING_TYPE,
- description: 'Body of the todo',
+ description: 'Body of the to-do item.',
null: false,
calls_gitaly: true # TODO This is only true when `target_type` is `Commit`. See https://gitlab.com/gitlab-org/gitlab/issues/34757#note_234752665
field :state, Types::TodoStateEnum,
- description: 'State of the todo',
+ description: 'State of the to-do item.',
null: false
field :created_at, Types::TimeType,
- description: 'Timestamp this todo was created',
+ description: 'Timestamp this to-do item was created.',
null: false
def project
diff --git a/app/graphql/types/tree/blob_type.rb b/app/graphql/types/tree/blob_type.rb
index a7b90d2533b..3823bd94083 100644
--- a/app/graphql/types/tree/blob_type.rb
+++ b/app/graphql/types/tree/blob_type.rb
@@ -11,13 +11,13 @@ module Types
graphql_name 'Blob'
field :web_url, GraphQL::STRING_TYPE, null: true,
- description: 'Web URL of the blob'
+ description: 'Web URL of the blob.'
field :web_path, GraphQL::STRING_TYPE, null: true,
- description: 'Web path of the blob'
+ description: 'Web path of the blob.'
field :lfs_oid, GraphQL::STRING_TYPE, null: true,
- description: 'LFS ID of the blob'
+ description: 'LFS ID of the blob.'
field :mode, GraphQL::STRING_TYPE, null: true,
- description: 'Blob mode in numeric format'
+ description: 'Blob mode in numeric format.'
def lfs_oid
Gitlab::Graphql::Loaders::BatchLfsOidLoader.new(object.repository, object.id).find
diff --git a/app/graphql/types/tree/entry_type.rb b/app/graphql/types/tree/entry_type.rb
index b40e38ec9d1..c0150b77c55 100644
--- a/app/graphql/types/tree/entry_type.rb
+++ b/app/graphql/types/tree/entry_type.rb
@@ -5,17 +5,17 @@ module Types
include Types::BaseInterface
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the entry'
+ description: 'ID of the entry.'
field :sha, GraphQL::STRING_TYPE, null: false,
- description: 'Last commit sha for the entry', method: :id
+ description: 'Last commit SHA for the entry.', method: :id
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Name of the entry'
+ description: 'Name of the entry.'
field :type, Tree::TypeEnum, null: false,
- description: 'Type of tree entry'
+ description: 'Type of tree entry.'
field :path, GraphQL::STRING_TYPE, null: false,
- description: 'Path of the entry'
+ description: 'Path of the entry.'
field :flat_path, GraphQL::STRING_TYPE, null: false,
- description: 'Flat path of the entry'
+ description: 'Flat path of the entry.'
end
end
end
diff --git a/app/graphql/types/tree/submodule_type.rb b/app/graphql/types/tree/submodule_type.rb
index d41fa4afd4b..519e866ebb0 100644
--- a/app/graphql/types/tree/submodule_type.rb
+++ b/app/graphql/types/tree/submodule_type.rb
@@ -9,9 +9,9 @@ module Types
graphql_name 'Submodule'
field :web_url, type: GraphQL::STRING_TYPE, null: true,
- description: 'Web URL for the sub-module'
+ description: 'Web URL for the sub-module.'
field :tree_url, type: GraphQL::STRING_TYPE, null: true,
- description: 'Tree URL for the sub-module'
+ description: 'Tree URL for the sub-module.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/tree/tree_entry_type.rb b/app/graphql/types/tree/tree_entry_type.rb
index aff2e025761..daf4b5421fb 100644
--- a/app/graphql/types/tree/tree_entry_type.rb
+++ b/app/graphql/types/tree/tree_entry_type.rb
@@ -12,9 +12,9 @@ module Types
description 'Represents a directory'
field :web_url, GraphQL::STRING_TYPE, null: true,
- description: 'Web URL for the tree entry (directory)'
+ description: 'Web URL for the tree entry (directory).'
field :web_path, GraphQL::STRING_TYPE, null: true,
- description: 'Web path for the tree entry (directory)'
+ description: 'Web path for the tree entry (directory).'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/tree/tree_type.rb b/app/graphql/types/tree/tree_type.rb
index fecd6c0f309..011cff0c89c 100644
--- a/app/graphql/types/tree/tree_type.rb
+++ b/app/graphql/types/tree/tree_type.rb
@@ -9,17 +9,17 @@ module Types
# Complexity 10 as it triggers a Gitaly call on each render
field :last_commit, Types::CommitType,
null: true, complexity: 10, calls_gitaly: true, resolver: Resolvers::LastCommitResolver,
- description: 'Last commit for the tree'
+ description: 'Last commit for the tree.'
field :trees, Types::Tree::TreeEntryType.connection_type, null: false,
- description: 'Trees of the tree'
+ description: 'Trees of the tree.'
field :submodules, Types::Tree::SubmoduleType.connection_type, null: false,
- description: 'Sub-modules of the tree',
+ description: 'Sub-modules of the tree.',
calls_gitaly: true
field :blobs, Types::Tree::BlobType.connection_type, null: false,
- description: 'Blobs of the tree',
+ description: 'Blobs of the tree.',
calls_gitaly: true
def trees
diff --git a/app/graphql/types/user_status_type.rb b/app/graphql/types/user_status_type.rb
index 9cf6c862d3d..c1a736a3722 100644
--- a/app/graphql/types/user_status_type.rb
+++ b/app/graphql/types/user_status_type.rb
@@ -8,10 +8,10 @@ module Types
markdown_field :message_html, null: true,
description: 'HTML of the user status message'
field :message, GraphQL::STRING_TYPE, null: true,
- description: 'User status message'
+ description: 'User status message.'
field :emoji, GraphQL::STRING_TYPE, null: true,
- description: 'String representation of emoji'
+ description: 'String representation of emoji.'
field :availability, Types::AvailabilityEnum, null: false,
- description: 'User availability status'
+ description: 'User availability status.'
end
end
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index 93503268319..0cefc84633d 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -11,58 +11,61 @@ module Types
expose_permissions Types::PermissionTypes::User
field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the user'
+ description: 'ID of the user.'
+ field :bot, GraphQL::BOOLEAN_TYPE, null: false,
+ description: 'Indicates if the user is a bot.',
+ method: :bot?
field :username, GraphQL::STRING_TYPE, null: false,
- description: 'Username of the user. Unique within this instance of GitLab'
+ description: 'Username of the user. Unique within this instance of GitLab.'
field :name, GraphQL::STRING_TYPE, null: false,
- description: 'Human-readable name of the user'
+ description: 'Human-readable name of the user.'
field :state, Types::UserStateEnum, null: false,
- description: 'State of the user'
+ description: 'State of the user.'
field :email, GraphQL::STRING_TYPE, null: true,
- description: 'User email', method: :public_email,
+ description: 'User email.', method: :public_email,
deprecated: { reason: 'Use public_email', milestone: '13.7' }
field :public_email, GraphQL::STRING_TYPE, null: true,
- description: "User's public email"
+ description: "User's public email."
field :avatar_url, GraphQL::STRING_TYPE, null: true,
- description: "URL of the user's avatar"
+ description: "URL of the user's avatar."
field :web_url, GraphQL::STRING_TYPE, null: false,
- description: 'Web URL of the user'
+ description: 'Web URL of the user.'
field :web_path, GraphQL::STRING_TYPE, null: false,
- description: 'Web path of the user'
+ description: 'Web path of the user.'
field :todos, Types::TodoType.connection_type, null: false,
resolver: Resolvers::TodoResolver,
- description: 'Todos of the user'
+ description: 'To-do items of the user.'
field :group_memberships, Types::GroupMemberType.connection_type, null: true,
- description: 'Group memberships of the user'
+ description: 'Group memberships of the user.'
field :group_count, GraphQL::INT_TYPE, null: true,
resolver: Resolvers::Users::GroupCountResolver,
- description: 'Group count for the user',
+ description: 'Group count for the user.',
feature_flag: :user_group_counts
field :status, Types::UserStatusType, null: true,
- description: 'User status'
+ description: 'User status.'
field :location, ::GraphQL::STRING_TYPE, null: true,
description: 'The location of the user.'
field :project_memberships, Types::ProjectMemberType.connection_type, null: true,
- description: 'Project memberships of the user'
+ description: 'Project memberships of the user.'
field :starred_projects, Types::ProjectType.connection_type, null: true,
- description: 'Projects starred by the user',
+ description: 'Projects starred by the user.',
resolver: Resolvers::UserStarredProjectsResolver
# Merge request field: MRs can be authored, assigned, or assigned-for-review:
field :authored_merge_requests,
resolver: Resolvers::AuthoredMergeRequestsResolver,
- description: 'Merge Requests authored by the user'
+ description: 'Merge Requests authored by the user.'
field :assigned_merge_requests,
resolver: Resolvers::AssignedMergeRequestsResolver,
- description: 'Merge Requests assigned to the user'
+ description: 'Merge Requests assigned to the user.'
field :review_requested_merge_requests,
resolver: Resolvers::ReviewRequestedMergeRequestsResolver,
- description: 'Merge Requests assigned to the user for review'
+ description: 'Merge Requests assigned to the user for review.'
field :snippets,
Types::SnippetType.connection_type,
null: true,
- description: 'Snippets authored by the user',
+ description: 'Snippets authored by the user.',
resolver: Resolvers::Users::SnippetsResolver
end
end
diff --git a/app/helpers/analytics/cycle_analytics_helper.rb b/app/helpers/analytics/cycle_analytics_helper.rb
new file mode 100644
index 00000000000..c43ac545bf8
--- /dev/null
+++ b/app/helpers/analytics/cycle_analytics_helper.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Analytics
+ module CycleAnalyticsHelper
+ def cycle_analytics_default_stage_config
+ Gitlab::Analytics::CycleAnalytics::DefaultStages.all.map do |stage_params|
+ Analytics::CycleAnalytics::StagePresenter.new(stage_params)
+ end
+ end
+ end
+end
diff --git a/app/helpers/analytics/unique_visits_helper.rb b/app/helpers/analytics/unique_visits_helper.rb
index 4c709b2ed23..337a5dc9536 100644
--- a/app/helpers/analytics/unique_visits_helper.rb
+++ b/app/helpers/analytics/unique_visits_helper.rb
@@ -14,7 +14,6 @@ module Analytics
end
def track_visit(target_id)
- return unless Feature.enabled?(:track_unique_visits, default_enabled: true)
return unless visitor_id
Gitlab::Analytics::UniqueVisits.new.track_visit(visitor_id, target_id)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 2a1652cf2ba..8268ab1ad56 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -280,7 +280,7 @@ module ApplicationHelper
def page_class
class_names = []
- class_names << 'issue-boards-page' if current_controller?(:boards)
+ class_names << 'issue-boards-page gl-overflow-hidden' if current_controller?(:boards)
class_names << 'environment-logs-page' if current_controller?(:logs)
class_names << 'with-performance-bar' if performance_bar_enabled?
class_names << system_message_class
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index ed30adfabf0..30ae535b06f 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -26,6 +26,16 @@ module ApplicationSettingsHelper
end
end
+ def kroki_available_formats
+ ApplicationSetting.kroki_formats_attributes.map do |key, value|
+ {
+ name: "kroki_formats_#{key}",
+ label: value[:label],
+ value: @application_setting.kroki_formats[key] || false
+ }
+ end
+ end
+
def storage_weights
ApplicationSetting.repository_storages_weighted_attributes.map do |attribute|
storage = attribute.to_s.delete_prefix('repository_storages_weighted_')
@@ -181,7 +191,7 @@ module ApplicationSettingsHelper
:asset_proxy_enabled,
:asset_proxy_secret_key,
:asset_proxy_url,
- :asset_proxy_whitelist,
+ :asset_proxy_allowlist,
:static_objects_external_storage_auth_token,
:static_objects_external_storage_url,
:authorized_keys_enabled,
@@ -259,6 +269,7 @@ module ApplicationSettingsHelper
:personal_access_token_prefix,
:kroki_enabled,
:kroki_url,
+ :kroki_formats,
:plantuml_enabled,
:plantuml_url,
:polling_interval_multiplier,
@@ -328,6 +339,8 @@ module ApplicationSettingsHelper
:email_restrictions_enabled,
:email_restrictions,
:issues_create_limit,
+ :notes_create_limit,
+ :notes_create_limit_allowlist_raw,
:raw_blob_request_limit,
:project_import_limit,
:project_export_limit,
@@ -337,7 +350,10 @@ module ApplicationSettingsHelper
:group_download_export_limit,
:wiki_page_max_content_bytes,
:container_registry_delete_tags_service_timeout,
- :rate_limiting_response_text
+ :rate_limiting_response_text,
+ :container_registry_expiration_policies_worker_capacity,
+ :container_registry_cleanup_tags_service_max_list_size,
+ :keep_latest_artifact
]
end
@@ -353,9 +369,11 @@ module ApplicationSettingsHelper
]
end
+ # ok to remove in REST API v5
def deprecated_attributes
[
- :admin_notification_email # ok to remove in REST API v5
+ :admin_notification_email,
+ :asset_proxy_whitelist
]
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 0b79d4c36a1..24c1d224c89 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module AuthHelper
- PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce atlassian_oauth2).freeze
+ PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce atlassian_oauth2 openid_connect).freeze
LDAP_PROVIDER = /\Aldap/.freeze
def ldap_enabled?
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index bca53dfb88a..28a947a6ca1 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -64,7 +64,7 @@ module BlobHelper
def edit_blob_button(project = @project, ref = @ref, path = @path, options = {})
return unless blob = readable_blob(options, path, project, ref)
- common_classes = "btn btn-primary js-edit-blob gl-mr-3 #{options[:extra_class]}"
+ common_classes = "btn gl-button btn-confirm js-edit-blob gl-ml-3 #{options[:extra_class]}"
data = { track_event: 'click_edit', track_label: 'Edit' }
if Feature.enabled?(:web_ide_primary_edit, project.group)
@@ -84,7 +84,7 @@ module BlobHelper
def ide_edit_button(project = @project, ref = @ref, path = @path, blob:)
return unless blob
- common_classes = 'btn btn-primary ide-edit-button gl-mr-3'
+ common_classes = 'btn gl-button btn-confirm ide-edit-button gl-ml-3'
data = { track_event: 'click_edit_ide', track_label: 'Web IDE' }
unless Feature.enabled?(:web_ide_primary_edit, project.group)
@@ -105,7 +105,7 @@ module BlobHelper
return unless current_user
return unless blob
- common_classes = "btn btn-#{btn_class}"
+ common_classes = "btn gl-button btn-default btn-#{btn_class}"
base_button = button_tag(label, class: "#{common_classes} disabled", disabled: true)
if !on_top_of_branch?(project, ref)
@@ -194,40 +194,28 @@ module BlobHelper
@ref_project ||= @target_project || @project
end
- def template_dropdown_names(items)
- grouped = items.group_by(&:category)
- categories = grouped.keys
-
- categories.each_with_object({}) do |category, hash|
- hash[category] = grouped[category].map do |item|
- { name: item.name, id: item.key }
- end
- end
- end
- private :template_dropdown_names
-
def licenses_for_select(project)
- @licenses_for_select ||= template_dropdown_names(TemplateFinder.build(:licenses, project).execute)
+ @licenses_for_select ||= TemplateFinder.all_template_names(project, :licenses)
end
def gitignore_names(project)
- @gitignore_names ||= template_dropdown_names(TemplateFinder.build(:gitignores, project).execute)
+ @gitignore_names ||= TemplateFinder.all_template_names(project, :gitignores)
end
def gitlab_ci_ymls(project)
- @gitlab_ci_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_ymls, project).execute)
+ @gitlab_ci_ymls ||= TemplateFinder.all_template_names(project, :gitlab_ci_ymls)
end
def gitlab_ci_syntax_ymls(project)
- @gitlab_ci_syntax_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_syntax_ymls, project).execute)
+ @gitlab_ci_syntax_ymls ||= TemplateFinder.all_template_names(project, :gitlab_ci_syntax_ymls)
end
def metrics_dashboard_ymls(project)
- @metrics_dashboard_ymls ||= template_dropdown_names(TemplateFinder.build(:metrics_dashboard_ymls, project).execute)
+ @metrics_dashboard_ymls ||= TemplateFinder.all_template_names(project, :metrics_dashboard_ymls)
end
def dockerfile_names(project)
- @dockerfile_names ||= template_dropdown_names(TemplateFinder.build(:dockerfiles, project).execute)
+ @dockerfile_names ||= TemplateFinder.all_template_names(project, :dockerfiles)
end
def blob_editor_paths(project)
@@ -241,13 +229,13 @@ module BlobHelper
end
def copy_file_path_button(file_path)
- clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'btn-clipboard btn-transparent', title: _('Copy file path'))
+ clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'gl-button btn btn-default-tertiary btn-icon btn-sm', title: _('Copy file path'))
end
def copy_blob_source_button(blob)
return unless blob.rendered_as_text?(ignore_errors: false)
- clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}'] > pre", class: "btn btn-sm js-copy-blob-source-btn", title: _("Copy file contents"))
+ clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}'] > pre", class: "btn gl-button btn-default btn-icon js-copy-blob-source-btn", title: _("Copy file contents"))
end
def open_raw_blob_button(blob)
@@ -257,7 +245,7 @@ module BlobHelper
title = _('Open raw')
link_to sprite_icon('doc-code'),
external_storage_url_or_path(blob_raw_path),
- class: 'btn btn-sm has-tooltip',
+ class: 'btn gl-button btn-default btn-icon has-tooltip',
target: '_blank',
rel: 'noopener noreferrer',
aria: { label: title },
@@ -272,7 +260,7 @@ module BlobHelper
link_to sprite_icon('download'),
external_storage_url_or_path(blob_raw_path(inline: false)),
download: @path,
- class: 'btn btn-sm has-tooltip',
+ class: 'btn gl-button btn-default btn-icon has-tooltip',
target: '_blank',
rel: 'noopener noreferrer',
aria: { label: title },
@@ -373,7 +361,7 @@ module BlobHelper
end
def edit_link_tag(link_text, edit_path, common_classes, data)
- link_to link_text, edit_path, class: "#{common_classes} btn-sm", data: data
+ link_to link_text, edit_path, class: "#{common_classes}", data: data
end
def edit_button_tag(blob, common_classes, text, edit_path, project, ref, data)
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index c827fb4dd95..73e7476b55d 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -21,7 +21,8 @@ module BoardsHelper
group_id: @group&.id,
labels_filter_base_path: build_issue_link_base,
labels_fetch_path: labels_fetch_path,
- labels_manage_path: labels_manage_path
+ labels_manage_path: labels_manage_path,
+ board_type: board.to_type
}
end
@@ -99,23 +100,6 @@ module BoardsHelper
}
end
- def board_sidebar_user_data
- dropdown_options = assignees_dropdown_options('issue')
-
- {
- toggle: 'dropdown',
- field_name: 'issue[assignee_ids][]',
- first_user: current_user&.username,
- current_user: 'true',
- project_id: @project&.id,
- group_id: @group&.id,
- null_user: 'true',
- multi_select: 'true',
- 'dropdown-header': dropdown_options[:data][:'dropdown-header'],
- 'max-select': dropdown_options[:data][:'max-select']
- }
- end
-
def boards_link_text
if current_board_parent.multiple_issue_boards_available?
s_("IssueBoards|Boards")
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index d47f6195c61..ec17eccf693 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -8,7 +8,6 @@ module Ci
"project_path" => @project.full_path,
"artifact_help_url" => help_page_path('user/gitlab_com/index.html', anchor: 'gitlab-cicd'),
"deployment_help_url" => help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting'),
- "runner_help_url" => help_page_path('ci/runners/README.html', anchor: 'set-maximum-job-timeout-for-a-runner'),
"runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
"variables_settings_url" => project_variables_path(@build.project, anchor: 'js-cicd-variables-settings'),
"page_path" => project_job_path(@project, @build),
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index e6e2b5b128b..f5c75d62097 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -105,31 +105,35 @@ module CommitsHelper
tooltip = _("Browse Directory")
end
- link_to url, class: "btn btn-default has-tooltip", title: tooltip, data: { container: "body" } do
+ link_to url, class: "btn gl-button btn-default has-tooltip", title: tooltip, data: { container: "body" } do
sprite_icon('folder-open')
end
end
- def revert_commit_link(commit, continue_to_path, btn_class: nil, pajamas: false)
+ def revert_commit_link
return unless current_user
- action = 'revert'
-
- if pajamas && can_collaborate_with_project?(@project)
- tag(:div, data: { display_text: action.capitalize }, class: "js-revert-commit-trigger")
- else
- commit_action_link(action, commit, continue_to_path, btn_class: btn_class, has_tooltip: false)
- end
+ tag(:div, data: { display_text: 'Revert' }, class: "js-revert-commit-trigger")
end
- def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
- commit_action_link('cherry-pick', commit, continue_to_path, btn_class: btn_class, has_tooltip: has_tooltip)
+ def cherry_pick_commit_link
+ return unless current_user
+
+ tag(:div, data: { display_text: 'Cherry-pick' }, class: "js-cherry-pick-commit-trigger")
end
def commit_signature_badge_classes(additional_classes)
%w(btn gpg-status-box) + Array(additional_classes)
end
+ def conditionally_paginate_diff_files(diffs, paginate:, per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE)
+ if paginate && Feature.enabled?(:paginate_commit_view, @project, type: :development)
+ Kaminari.paginate_array(diffs.diff_files.to_a).page(params[:page]).per(per)
+ else
+ diffs.diff_files
+ end
+ end
+
protected
# Private: Returns a link to a person. If the person has a matching user and
@@ -143,7 +147,7 @@ module CommitsHelper
def commit_person_link(commit, options = {})
user = commit.public_send(options[:source]) # rubocop:disable GitlabSecurity/PublicSend
- source_name = clean(commit.public_send(:"#{options[:source]}_name")) # rubocop:disable GitlabSecurity/PublicSend
+ source_name = clean(commit.public_send(:"#{options[:source]}_name")) # rubocop:disable GitlabSecurity/PublicSend
source_email = clean(commit.public_send(:"#{options[:source]}_email")) # rubocop:disable GitlabSecurity/PublicSend
person_name = user.try(:name) || source_name
@@ -166,33 +170,11 @@ module CommitsHelper
end
end
- def commit_action_link(action, commit, continue_to_path, btn_class: nil, has_tooltip: true)
- return unless current_user
-
- tooltip = "#{action.capitalize} this #{commit.change_type_title(current_user)} in a new merge request" if has_tooltip
- btn_class = "btn btn-#{btn_class}" unless btn_class.nil?
-
- if can_collaborate_with_project?(@project)
- link_to action.capitalize, "#modal-#{action}-commit", 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
- elsif can?(current_user, :fork_project, @project)
- continue_params = {
- to: continue_to_path,
- notice: "#{edit_in_new_fork_notice} Try to #{action} this commit again.",
- notice_now: edit_in_new_fork_notice_now
- }
- fork_path = project_forks_path(@project,
- namespace_key: current_user.namespace.id,
- continue: continue_params)
-
- link_to action.capitalize, fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
- end
- end
-
def view_file_button(commit_sha, diff_new_path, project, replaced: false)
path = project_blob_path(project, tree_join(commit_sha, diff_new_path))
title = replaced ? _('View replaced file @ ') : _('View file @ ')
- link_to(path, class: 'btn') do
+ link_to(path, class: 'btn gl-button btn-default') do
raw(title) + content_tag(:span, truncate_sha(commit_sha), class: 'commit-sha')
end
end
@@ -203,7 +185,7 @@ module CommitsHelper
external_url = environment.external_url_for(diff_new_path, commit_sha)
return unless external_url
- link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
+ link_to(external_url, class: 'btn gl-button btn-default btn-file-option has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
sprite_icon('external-link')
end
end
diff --git a/app/helpers/container_registry_helper.rb b/app/helpers/container_registry_helper.rb
index 0efc8c50d58..1b77b639ce1 100644
--- a/app/helpers/container_registry_helper.rb
+++ b/app/helpers/container_registry_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module ContainerRegistryHelper
- def limit_delete_tags_service?
+ def container_registry_expiration_policies_throttling?
Feature.enabled?(:container_registry_expiration_policies_throttling) &&
ContainerRegistry::Client.supports_tag_delete?
end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 69a2efebb1f..233a8260036 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -133,7 +133,7 @@ module DiffHelper
].join('').html_safe
tooltip = _('Compare submodule commit revisions')
- link = content_tag(:span, link_to(link_text, compare_url, class: 'btn has-tooltip', title: tooltip), class: 'submodule-compare')
+ link = content_tag(:span, link_to(link_text, compare_url, class: 'btn gl-button has-tooltip', title: tooltip), class: 'submodule-compare')
end
link
@@ -203,6 +203,26 @@ module DiffHelper
set_secure_cookie(:diff_view, params.delete(:view), type: CookiesHelper::COOKIE_TYPE_PERMANENT) if params[:view].present?
end
+ def collapsed_diff_url(diff_file)
+ url_for(
+ safe_params.merge(
+ action: :diff_for_path,
+ old_path: diff_file.old_path,
+ new_path: diff_file.new_path,
+ file_identifier: diff_file.file_identifier
+ )
+ )
+ end
+
+ # As the fork suggestion button is identical every time, we cache it for a full page load
+ def render_fork_suggestion
+ return unless current_user
+
+ strong_memoize(:fork_suggestion) do
+ render partial: "projects/fork_suggestion"
+ end
+ end
+
private
def diff_btn(title, name, selected)
@@ -212,7 +232,7 @@ module DiffHelper
# Always use HTML to handle case where JSON diff rendered this button
params_copy.delete(:format)
- link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn active' : 'btn'), data: { view_type: name } do
+ link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn gl-button active' : 'btn gl-button'), data: { view_type: name } do
title
end
end
@@ -241,7 +261,7 @@ module DiffHelper
end
def toggle_whitespace_link(url, options)
- options[:class] = [*options[:class], 'btn btn-default'].join(' ')
+ options[:class] = [*options[:class], 'btn gl-button btn-default'].join(' ')
link_to "#{hide_whitespace? ? 'Show' : 'Hide'} whitespace changes", url, class: options[:class]
end
@@ -254,7 +274,7 @@ module DiffHelper
end
def code_navigation_path(diffs)
- Gitlab::CodeNavigationPath.new(merge_request.project, diffs.diff_refs&.head_sha)
+ Gitlab::CodeNavigationPath.new(merge_request.project, merge_request.diff_head_sha)
end
def conflicts
diff --git a/app/helpers/enable_search_settings_helper.rb b/app/helpers/enable_search_settings_helper.rb
new file mode 100644
index 00000000000..aa92a1b0b1e
--- /dev/null
+++ b/app/helpers/enable_search_settings_helper.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module EnableSearchSettingsHelper
+ def enable_search_settings(locals: {})
+ content_for :before_content do
+ render "shared/search_settings", locals
+ end
+ end
+end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index e6603237676..52b8ac915f1 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -178,8 +178,8 @@ module EventsHelper
def event_note_target_url(event)
if event.commit_note?
project_commit_url(event.project, event.note_target, anchor: dom_id(event.target))
- elsif event.project_snippet_note?
- project_snippet_url(event.project, event.note_target, anchor: dom_id(event.target))
+ elsif event.snippet_note?
+ gitlab_snippet_url(event.note_target, anchor: dom_id(event.target))
elsif event.issue_note?
project_issue_url(event.project, id: event.note_target, anchor: dom_id(event.target))
elsif event.merge_request_note?
diff --git a/app/helpers/external_link_helper.rb b/app/helpers/external_link_helper.rb
index bf47087543f..058302d1ed8 100644
--- a/app/helpers/external_link_helper.rb
+++ b/app/helpers/external_link_helper.rb
@@ -3,7 +3,7 @@
module ExternalLinkHelper
def external_link(body, url, options = {})
link_to url, { target: '_blank', rel: 'noopener noreferrer' }.merge(options) do
- "#{body} #{sprite_icon('external-link')}".html_safe
+ "#{body}#{sprite_icon('external-link', css_class: 'gl-ml-1')}".html_safe
end
end
end
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
index a4159ed6b19..3e7d6febabf 100644
--- a/app/helpers/groups/group_members_helper.rb
+++ b/app/helpers/groups/group_members_helper.rb
@@ -13,12 +13,12 @@ module Groups::GroupMembersHelper
render 'shared/members/invite_member', submit_url: group_group_members_path(group), access_levels: group.access_level_roles, default_access_level: default_access_level
end
- def linked_groups_data_json(group_links)
- GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json
+ def group_group_links_data_json(group_links)
+ GroupLink::GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json
end
def members_data_json(group, members)
- MemberSerializer.new.represent(members, { current_user: current_user, group: group }).to_json
+ MemberSerializer.new.represent(members, { current_user: current_user, group: group, source: group }).to_json
end
# Overridden in `ee/app/helpers/ee/groups/group_members_helper.rb`
@@ -26,16 +26,16 @@ module Groups::GroupMembersHelper
{
members: members_data_json(group, members),
member_path: group_group_member_path(group, ':id'),
- group_id: group.id,
+ source_id: group.id,
can_manage_members: can?(current_user, :admin_group_member, group).to_s
}
end
- def linked_groups_list_data_attributes(group)
+ def group_group_links_list_data_attributes(group)
{
- members: linked_groups_data_json(group.shared_with_group_links),
+ members: group_group_links_data_json(group.shared_with_group_links),
member_path: group_group_link_path(group, ':id'),
- group_id: group.id
+ source_id: group.id
}
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 133d9d21a14..eeeffb7b3ae 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -62,6 +62,14 @@ module GroupsHelper
can?(current_user, :set_emails_disabled, group) && !group.parent&.emails_disabled?
end
+ def group_open_issues_count(group)
+ if Feature.enabled?(:cached_sidebar_open_issues_count, group)
+ cached_open_group_issues_count(group)
+ else
+ number_with_delimiter(group_issues_count(state: 'opened'))
+ end
+ end
+
def group_issues_count(state:)
IssuesFinder
.new(current_user, group_id: @group.id, state: state, non_archived: true, include_subgroups: true)
@@ -69,6 +77,21 @@ module GroupsHelper
.count
end
+ def cached_open_group_issues_count(group)
+ count_service = Groups::OpenIssuesCountService
+ issues_count = count_service.new(group, current_user).count
+
+ if issues_count > count_service::CACHED_COUNT_THRESHOLD
+ ActiveSupport::NumberHelper
+ .number_to_human(
+ issues_count,
+ units: { thousand: 'k', million: 'm' }, precision: 1, significant: false, format: '%n%u'
+ )
+ else
+ number_with_delimiter(issues_count)
+ end
+ end
+
def group_merge_requests_count(state:)
MergeRequestsFinder
.new(current_user, group_id: @group.id, state: state, non_archived: true, include_subgroups: true)
diff --git a/app/helpers/in_product_marketing_helper.rb b/app/helpers/in_product_marketing_helper.rb
new file mode 100644
index 00000000000..a0e533d3fb8
--- /dev/null
+++ b/app/helpers/in_product_marketing_helper.rb
@@ -0,0 +1,350 @@
+# frozen_string_literal: true
+
+module InProductMarketingHelper
+ def subject_line(track, series)
+ {
+ create: [
+ s_('InProductMarketing|Create a project in GitLab in 5 minutes'),
+ s_('InProductMarketing|Import your project and code from GitHub, Bitbucket and others'),
+ s_('InProductMarketing|Understand repository mirroring')
+ ],
+ verify: [
+ s_('InProductMarketing|Feel the need for speed?'),
+ s_('InProductMarketing|3 ways to dive into GitLab CI/CD'),
+ s_('InProductMarketing|Explore the power of GitLab CI/CD')
+ ],
+ trial: [
+ s_('InProductMarketing|Go farther with GitLab'),
+ s_('InProductMarketing|Automated security scans directly within GitLab'),
+ s_('InProductMarketing|Take your source code management to the next level')
+ ],
+ team: [
+ s_('InProductMarketing|Working in GitLab = more efficient'),
+ s_("InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"),
+ s_('InProductMarketing|Your teams can be more efficient')
+ ]
+ }[track][series]
+ end
+
+ def in_product_marketing_logo(track, series)
+ inline_image_link('mailers/in_product_marketing', "#{track}-#{series}.png", { width: '150', style: 'width: 150px;' })
+ end
+
+ def about_link(folder, image, width)
+ link_to inline_image_link(folder, image, { width: width, style: "width: #{width}px;", alt: s_('InProductMarketing|go to about.gitlab.com') }), 'https://about.gitlab.com/'
+ end
+
+ def in_product_marketing_tagline(track, series)
+ {
+ create: [
+ s_('InProductMarketing|Get started today'),
+ s_('InProductMarketing|Get our import guides'),
+ s_('InProductMarketing|Need an alternative to importing?')
+ ],
+ verify: [
+ s_('InProductMarketing|Use GitLab CI/CD'),
+ s_('InProductMarketing|Test, create, deploy'),
+ s_('InProductMarketing|Are your runners ready?')
+ ],
+ trial: [
+ s_('InProductMarketing|Start a free trial of GitLab Gold – no CC required'),
+ s_('InProductMarketing|Improve app security with a 30-day trial'),
+ s_('InProductMarketing|Start with a GitLab Gold free trial')
+ ],
+ team: [
+ s_('InProductMarketing|Invite your colleagues to join in less than one minute'),
+ s_('InProductMarketing|Get your team set up on GitLab'),
+ nil
+ ]
+ }[track][series]
+ end
+
+ def in_product_marketing_title(track, series)
+ {
+ create: [
+ s_('InProductMarketing|Take your first steps with GitLab'),
+ s_('InProductMarketing|Start by importing your projects'),
+ s_('InProductMarketing|How (and why) mirroring makes sense')
+ ],
+ verify: [
+ s_('InProductMarketing|Rapid development, simplified'),
+ s_('InProductMarketing|Get started with GitLab CI/CD'),
+ s_('InProductMarketing|Launch GitLab CI/CD in 20 minutes or less')
+ ],
+ trial: [
+ s_('InProductMarketing|Give us one minute...'),
+ s_("InProductMarketing|Security that's integrated into your development lifecycle"),
+ s_('InProductMarketing|Improve code quality and streamline reviews')
+ ],
+ team: [
+ s_('InProductMarketing|Team work makes the dream work'),
+ s_('InProductMarketing|*GitLab*, noun: a synonym for efficient teams'),
+ s_('InProductMarketing|Find out how your teams are really doing')
+ ]
+ }[track][series]
+ end
+
+ def in_product_marketing_subtitle(track, series)
+ {
+ create: [
+ s_('InProductMarketing|Dig in and create a project and a repo'),
+ s_("InProductMarketing|Here's what you need to know"),
+ s_('InProductMarketing|Try it out')
+ ],
+ verify: [
+ s_('InProductMarketing|How to build and test faster'),
+ s_('InProductMarketing|Explore the options'),
+ s_('InProductMarketing|Follow our steps')
+ ],
+ trial: [
+ s_('InProductMarketing|...and you can get a free trial of GitLab Gold'),
+ s_('InProductMarketing|Try GitLab Gold for free'),
+ s_('InProductMarketing|Better code in less time')
+ ],
+ team: [
+ s_('InProductMarketing|Actually, GitLab makes the team work (better)'),
+ s_('InProductMarketing|Our tool brings all the things together'),
+ s_("InProductMarketing|It's all in the stats")
+ ]
+ }[track][series]
+ end
+
+ def in_product_marketing_body_line1(track, series, format: nil)
+ {
+ create: [
+ s_("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}.") % { project_link: project_link(format), repo_link: repo_link(format) },
+ s_("InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}.") % { github_link: github_link(format), bitbucket_link: bitbucket_link(format) },
+ s_("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.") % { mirroring_link: mirroring_link(format) }
+ ],
+ verify: [
+ s_("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}.") % { ci_link: ci_link(format) },
+ s_("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:"),
+ s_("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.") % { quick_start_link: quick_start_link(format) }
+ ],
+ trial: [
+ [
+ s_("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:"),
+ list([
+ s_('InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels').html_safe % strong_options(format),
+ s_('InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals').html_safe % strong_options(format),
+ s_('InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection').html_safe % strong_options(format),
+ s_('InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream').html_safe % strong_options(format)
+ ], format)
+ ].join("\n"),
+ s_('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.'),
+ s_('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.')
+ ],
+ team: [
+ [
+ s_('InProductMarketing|Did you know teams that use GitLab are far more efficient?'),
+ list([
+ s_('InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day'),
+ s_('InProductMarketing|Ticketmaster decreased their CI build time by 15X')
+ ], format)
+ ].join("\n"),
+ s_("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 Gold and your teams will be on it from day one."),
+ [
+ s_('InProductMarketing|Stop wondering and use GitLab to answer questions like:'),
+ list([
+ s_('InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?'),
+ s_('InProductMarketing|How many days does it take our team to complete various tasks?'),
+ s_('InProductMarketing|What does our value stream timeline look like from product to development to review and production?')
+ ], format)
+ ].join("\n")
+ ]
+ }[track][series]
+ end
+
+ def in_product_marketing_body_line2(track, series, format: nil)
+ {
+ create: [
+ s_("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.") % { basics_link: basics_link(format) },
+ s_("InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}.") % { import_link: import_link(format) },
+ s_("InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD.") % { external_repo_link: external_repo_link(format) }
+ ],
+ verify: [
+ nil,
+ list([
+ s_('InProductMarketing|Start by %{performance_link}').html_safe % { performance_link: performance_link(format) },
+ s_('InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}').html_safe % { ci_template_link: ci_template_link(format) },
+ s_('InProductMarketing|And finally %{deploy_link} a Python application.').html_safe % { deploy_link: deploy_link(format) }
+ ], format),
+ nil
+ ],
+ trial: [
+ s_('InProductMarketing|Start a GitLab Gold trial today in less than one minute, no credit card required.'),
+ s_('InProductMarketing|Get started today with a 30-day GitLab Gold trial, no credit card required.'),
+ s_('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 Gold and enable these features in less than 5 minutes with no credit card required.')
+ ],
+ team: [
+ s_('InProductMarketing|Invite your colleagues and start shipping code faster.'),
+ s_("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."),
+ s_('InProductMarketing|When your team is on GitLab these answers are a click away.')
+ ]
+ }[track][series]
+ end
+
+ def cta_link(track, series, group, format: nil)
+ case format
+ when :html
+ link_to in_product_marketing_cta_text(track, series), group_email_campaigns_url(group, track: track, series: series), target: '_blank', rel: 'noopener noreferrer'
+ else
+ [in_product_marketing_cta_text(track, series), group_email_campaigns_url(group, track: track, series: series)].join(' >> ')
+ end
+ end
+
+ def in_product_marketing_progress(track, series)
+ s_('InProductMarketing|This is email %{series} of 3 in the %{track} series.') % { series: series + 1, track: track.to_s.humanize }
+ end
+
+ def footer_links(format: nil)
+ links = [
+ [s_('InProductMarketing|Blog'), 'https://about.gitlab.com/blog'],
+ [s_('InProductMarketing|Twitter'), 'https://twitter.com/gitlab'],
+ [s_('InProductMarketing|Facebook'), 'https://www.facebook.com/gitlab'],
+ [s_('InProductMarketing|YouTube'), 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg']
+ ]
+ case format
+ when :html
+ links.map do |text, link|
+ link_to(text, link)
+ end
+ else
+ '| ' + links.map do |text, link|
+ [text, link].join(' ')
+ end.join("\n| ")
+ end
+ end
+
+ def address(format: nil)
+ s_('InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA').html_safe % strong_options(format)
+ end
+
+ def unsubscribe(format: nil)
+ parts = [
+ s_('InProductMarketing|If you no longer wish to receive marketing emails from us,'),
+ s_('InProductMarketing|you may %{unsubscribe_link} at any time.') % { unsubscribe_link: unsubscribe_link(format) }
+ ]
+ case format
+ when :html
+ parts.join(' ')
+ else
+ parts.join("\n" + ' ' * 16)
+ end
+ end
+
+ private
+
+ def in_product_marketing_cta_text(track, series)
+ {
+ create: [
+ s_('InProductMarketing|Create your first project!'),
+ s_('InProductMarketing|Master the art of importing!'),
+ s_('InProductMarketing|Understand your project options')
+ ],
+ verify: [
+ s_('InProductMarketing|Get to know GitLab CI/CD'),
+ s_('InProductMarketing|Try it yourself'),
+ s_('InProductMarketing|Explore GitLab CI/CD')
+ ],
+ trial: [
+ s_('InProductMarketing|Start a trial'),
+ s_('InProductMarketing|Beef up your security'),
+ s_('InProductMarketing|Go for the gold!')
+ ],
+ team: [
+ s_('InProductMarketing|Invite your colleagues today'),
+ s_('InProductMarketing|Invite your team in less than 60 seconds'),
+ s_('InProductMarketing|Invite your team now')
+ ]
+ }[track][series]
+ end
+
+ def project_link(format)
+ link(s_('InProductMarketing|create a project'), help_page_url('gitlab-basics/create-project'), format)
+ end
+
+ def repo_link(format)
+ link(s_('InProductMarketing|set up a repo'), help_page_url('user/project/repository/index', anchor: 'create-a-repository'), format)
+ end
+
+ def github_link(format)
+ link(s_('InProductMarketing|GitHub Enterprise projects to GitLab'), help_page_url('integration/github'), format)
+ end
+
+ def bitbucket_link(format)
+ link(s_('InProductMarketing|from Bitbucket'), help_page_url('user/project/import/bitbucket_server'), format)
+ end
+
+ def mirroring_link(format)
+ link(s_('InProductMarketing|repository mirroring'), help_page_url('user/project/repository/repository_mirroring'), format)
+ end
+
+ def ci_link(format)
+ link(s_('InProductMarketing|how easy it is to get started'), help_page_url('ci/README'), format)
+ end
+
+ def performance_link(format)
+ link(s_('InProductMarketing|testing browser performance'), help_page_url('user/project/merge_requests/browser_performance_testing'), format)
+ end
+
+ def ci_template_link(format)
+ link(s_('InProductMarketing|using a CI/CD template'), help_page_url('user/project/pages/getting_started/pages_ci_cd_template'), format)
+ end
+
+ def deploy_link(format)
+ link(s_('InProductMarketing|test and deploy'), help_page_url('ci/examples/test-and-deploy-python-application-to-heroku'), format)
+ end
+
+ def quick_start_link(format)
+ link(s_('InProductMarketing|quick start guide'), help_page_url('ci/quick_start/README'), format)
+ end
+
+ def basics_link(format)
+ link(s_('InProductMarketing|Git basics'), help_page_url('gitlab-basics/README'), format)
+ end
+
+ def import_link(format)
+ link(s_('InProductMarketing|comprehensive guide'), help_page_url('user/project/import/index'), format)
+ end
+
+ def external_repo_link(format)
+ link(s_('InProductMarketing|connect an external repository'), new_project_url(anchor: 'cicd_for_external_repo'), format)
+ end
+
+ def unsubscribe_link(format)
+ link(s_('InProductMarketing|unsubscribe'), '%tag_unsubscribe_url%', format)
+ end
+
+ def link(text, link, format)
+ case format
+ when :html
+ link_to text, link
+ else
+ "#{text} (#{link})"
+ end
+ end
+
+ def list(array, format)
+ case format
+ when :html
+ tag.ul { array.map { |item| concat tag.li item} }
+ else
+ '- ' + array.join("\n- ")
+ end
+ end
+
+ def strong_options(format)
+ case format
+ when :html
+ { strong_start: '<b>'.html_safe, strong_end: '</b>'.html_safe }
+ else
+ { strong_start: '', strong_end: '' }
+ end
+ end
+
+ def inline_image_link(folder, image, **options)
+ attachments.inline[image] = File.read(Rails.root.join("app/assets/images", folder, image))
+ image_tag attachments[image].url, **options
+ end
+end
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index a643fea6d5a..889365e39de 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -3,10 +3,14 @@
module InviteMembersHelper
include Gitlab::Utils::StrongMemoize
- def invite_members_allowed?(group)
+ def can_invite_members_for_group?(group)
Feature.enabled?(:invite_members_group_modal, group) && can?(current_user, :admin_group_member, group)
end
+ def can_invite_members_for_project?(project)
+ Feature.enabled?(:invite_members_group_modal, project.group) && can_import_members?
+ end
+
def directly_invite_members?
strong_memoize(:directly_invite_members) do
experiment_enabled?(:invite_members_version_a) && can_import_members?
@@ -27,8 +31,8 @@ module InviteMembersHelper
link_to invite_members_url(form_model),
data: {
'track-event': 'click_link',
- 'track-label': tracking_label(current_user),
- 'track-property': experiment_tracking_category_and_group(:invite_members_new_dropdown, subject: current_user)
+ 'track-label': tracking_label,
+ 'track-property': experiment_tracking_category_and_group(:invite_members_new_dropdown)
} do
invite_member_link_content
end
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
new file mode 100644
index 00000000000..110b3954900
--- /dev/null
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module IssuablesDescriptionTemplatesHelper
+ include Gitlab::Utils::StrongMemoize
+ include GitlabRoutingHelper
+
+ def template_dropdown_tag(issuable, &block)
+ title = selected_template(issuable) || "Choose a template"
+ options = {
+ toggle_class: 'js-issuable-selector',
+ title: title,
+ filter: true,
+ placeholder: 'Filter',
+ footer_content: true,
+ data: {
+ data: issuable_templates(ref_project, issuable.to_ability_name),
+ field_name: 'issuable_template',
+ selected: selected_template(issuable),
+ project_id: ref_project.id
+ }
+ }
+
+ dropdown_tag(title, options: options) do
+ capture(&block)
+ end
+ end
+
+ def issuable_templates(project, issuable_type)
+ @template_types ||= {}
+ @template_types[project.id] ||= {}
+ @template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names_array(project, issuable_type.pluralize)
+ end
+
+ def issuable_templates_names(issuable)
+ issuable_templates(ref_project, issuable.to_ability_name).map { |template| template[:name] }
+ end
+
+ def selected_template(issuable)
+ params[:issuable_template] if issuable_templates(ref_project, issuable.to_ability_name).any? { |template| template[:name] == params[:issuable_template] }
+ end
+
+ def template_names_path(parent, issuable)
+ return '' unless parent.is_a?(Project)
+
+ project_template_names_path(parent, template_type: issuable.to_ability_name)
+ end
+end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index da142cbed0e..41e9f61cf9f 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -2,6 +2,7 @@
module IssuablesHelper
include GitlabRoutingHelper
+ include IssuablesDescriptionTemplatesHelper
def sidebar_gutter_toggle_icon
content_tag(:span, class: 'js-sidebar-toggle-container', data: { is_expanded: !sidebar_gutter_collapsed? }) do
@@ -75,28 +76,6 @@ module IssuablesHelper
.to_json
end
- def template_dropdown_tag(issuable, &block)
- title = selected_template(issuable) || "Choose a template"
- options = {
- toggle_class: 'js-issuable-selector',
- title: title,
- filter: true,
- placeholder: 'Filter',
- footer_content: true,
- data: {
- data: issuable_templates(issuable),
- field_name: 'issuable_template',
- selected: selected_template(issuable),
- project_path: ref_project.path,
- namespace_path: ref_project.namespace.full_path
- }
- }
-
- dropdown_tag(title, options: options) do
- capture(&block)
- end
- end
-
def users_dropdown_label(selected_users)
case selected_users.length
when 0
@@ -215,24 +194,12 @@ module IssuablesHelper
state_title = titles[state] || state.to_s.humanize
html = content_tag(:span, state_title)
- if display_count
- count = issuables_count_for_state(issuable_type, state)
- tag =
- if count == -1
- tooltip = _("Couldn't calculate number of %{issuables}.") % { issuables: issuable_type.to_s.humanize(capitalize: false) }
-
- content_tag(
- :span,
- '?',
- class: 'badge badge-pill has-tooltip',
- aria: { label: tooltip },
- title: tooltip
- )
- else
- content_tag(:span, number_with_delimiter(count), class: 'badge badge-pill')
- end
-
- html << " " << tag
+ return html.html_safe unless display_count
+
+ count = issuables_count_for_state(issuable_type, state)
+
+ if count != -1
+ html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge badge-pill')
end
html.html_safe
@@ -294,6 +261,7 @@ module IssuablesHelper
{
projectPath: ref_project.path,
+ projectId: ref_project.id,
projectNamespace: ref_project.namespace.full_path
}
end
@@ -346,6 +314,7 @@ module IssuablesHelper
def assignee_sidebar_data(assignee, merge_request: nil)
{ avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }.tap do |data|
data[:can_merge] = merge_request.can_be_merged_by?(assignee) if merge_request
+ data[:availability] = assignee.status.availability if assignee.association(:status).loaded? && assignee.status&.availability
end
end
@@ -369,24 +338,6 @@ module IssuablesHelper
cookies[:collapsed_gutter] == 'true'
end
- def issuable_templates(issuable)
- @issuable_templates ||=
- case issuable
- when Issue
- ref_project.repository.issue_template_names
- when MergeRequest
- ref_project.repository.merge_request_template_names
- end
- end
-
- def issuable_templates_names(issuable)
- issuable_templates(issuable).map { |template| template[:name] }
- end
-
- def selected_template(issuable)
- params[:issuable_template] if issuable_templates(issuable).any? { |template| template[:name] == params[:issuable_template] }
- end
-
def issuable_todo_button_data(issuable, is_collapsed)
{
todo_text: _('Add a to do'),
@@ -424,12 +375,6 @@ module IssuablesHelper
end
end
- def template_names_path(parent, issuable)
- return '' unless parent.is_a?(Project)
-
- project_template_names_path(parent, template_type: issuable.class.name.underscore)
- end
-
def issuable_sidebar_options(issuable)
{
endpoint: "#{issuable[:issuable_json_path]}?serializer=sidebar_extras",
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index f1527b9b85a..080883fd594 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -5,9 +5,15 @@ module JiraConnectHelper
Feature.enabled?(:new_jira_connect_ui, type: :development, default_enabled: :yaml)
end
- def jira_connect_app_data
+ def jira_connect_app_data(subscriptions)
+ return {} unless new_jira_connect_ui?
+
+ skip_groups = subscriptions.map(&:namespace_id)
+
{
- groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER })
+ groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
+ subscriptions_path: jira_connect_subscriptions_path,
+ users_path: current_user ? nil : jira_connect_users_path
}
end
end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 312d535a92c..cfc4075100b 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -80,27 +80,27 @@ module LabelsHelper
def suggested_colors
{
- '#0033CC' => s_('SuggestedColors|UA blue'),
- '#428BCA' => s_('SuggestedColors|Moderate blue'),
- '#44AD8E' => s_('SuggestedColors|Lime green'),
- '#A8D695' => s_('SuggestedColors|Feijoa'),
- '#5CB85C' => s_('SuggestedColors|Slightly desaturated green'),
- '#69D100' => s_('SuggestedColors|Bright green'),
- '#004E00' => s_('SuggestedColors|Very dark lime green'),
- '#34495E' => s_('SuggestedColors|Very dark desaturated blue'),
- '#7F8C8D' => s_('SuggestedColors|Dark grayish cyan'),
- '#A295D6' => s_('SuggestedColors|Slightly desaturated blue'),
- '#5843AD' => s_('SuggestedColors|Dark moderate blue'),
- '#8E44AD' => s_('SuggestedColors|Dark moderate violet'),
- '#FFECDB' => s_('SuggestedColors|Very pale orange'),
- '#AD4363' => s_('SuggestedColors|Dark moderate pink'),
- '#D10069' => s_('SuggestedColors|Strong pink'),
- '#CC0033' => s_('SuggestedColors|Strong red'),
- '#FF0000' => s_('SuggestedColors|Pure red'),
- '#D9534F' => s_('SuggestedColors|Soft red'),
- '#D1D100' => s_('SuggestedColors|Strong yellow'),
- '#F0AD4E' => s_('SuggestedColors|Soft orange'),
- '#AD8D43' => s_('SuggestedColors|Dark moderate orange')
+ '#009966' => s_('SuggestedColors|Green-cyan'),
+ '#8fbc8f' => s_('SuggestedColors|Dark sea green'),
+ '#3cb371' => s_('SuggestedColors|Medium sea green'),
+ '#00b140' => s_('SuggestedColors|Green screen'),
+ '#013220' => s_('SuggestedColors|Dark green'),
+ '#6699cc' => s_('SuggestedColors|Blue-gray'),
+ '#0000ff' => s_('SuggestedColors|Blue'),
+ '#e6e6fa' => s_('SuggestedColors|Lavendar'),
+ '#9400d3' => s_('SuggestedColors|Dark violet'),
+ '#330066' => s_('SuggestedColors|Deep violet'),
+ '#808080' => s_('SuggestedColors|Gray'),
+ '#36454f' => s_('SuggestedColors|Charcoal grey'),
+ '#f7e7ce' => s_('SuggestedColors|Champagne'),
+ '#c21e56' => s_('SuggestedColors|Rose red'),
+ '#cc338b' => s_('SuggestedColors|Magenta-pink'),
+ '#dc143c' => s_('SuggestedColors|Crimson'),
+ '#ff0000' => s_('SuggestedColors|Red'),
+ '#cd5b45' => s_('SuggestedColors|Dark coral'),
+ '#eee600' => s_('SuggestedColors|Titanium yellow'),
+ '#ed9121' => s_('SuggestedColors|Carrot orange'),
+ '#c39953' => s_('SuggestedColors|Aztec Gold')
}
end
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
new file mode 100644
index 00000000000..e72a9c83fc9
--- /dev/null
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module LearnGitlabHelper
+ def learn_gitlab_experiment_enabled?(project)
+ return false unless current_user
+ return false unless experiment_enabled_for_user?
+
+ learn_gitlab_onboarding_available?(project)
+ end
+
+ def onboarding_actions_data(project)
+ attributes = onboarding_progress(project).attributes.symbolize_keys
+
+ action_urls.map do |action, url|
+ [
+ action,
+ url: url,
+ completed: attributes[OnboardingProgress.column_name(action)].present?
+ ]
+ end.to_h
+ end
+
+ private
+
+ ACTION_ISSUE_IDS = {
+ git_write: 2,
+ pipeline_created: 4,
+ merge_request_created: 6,
+ user_added: 7,
+ trial_started: 13,
+ required_mr_approvals_enabled: 15,
+ code_owners_enabled: 16
+ }.freeze
+
+ ACTION_DOC_URLS = {
+ security_scan_enabled: 'https://docs.gitlab.com/ee/user/application_security/security_dashboard/#gitlab-security-dashboard-security-center-and-vulnerability-reports'
+ }.freeze
+
+ def action_urls
+ ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }.merge(ACTION_DOC_URLS)
+ end
+
+ def learn_gitlab_project
+ @learn_gitlab_project ||= LearnGitlab.new(current_user).project
+ end
+
+ def onboarding_progress(project)
+ OnboardingProgress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def experiment_enabled_for_user?
+ Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_a, subject: current_user) ||
+ Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_b, subject: current_user)
+ end
+
+ def learn_gitlab_onboarding_available?(project)
+ OnboardingProgress.onboarding?(project.namespace) &&
+ LearnGitlab.new(current_user).available?
+ end
+end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 6ab5f499b9a..ff1305f8cc5 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -174,15 +174,9 @@ module MergeRequestsHelper
end
end
- def merge_request_reviewers_enabled?
- Feature.enabled?(:merge_request_reviewers, default_enabled: :yaml)
- end
-
private
def review_requested_merge_requests_count
- return 0 unless merge_request_reviewers_enabled?
-
current_user.review_requested_open_merge_requests_count
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 3c757a4ef26..c170e58b4ce 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -64,7 +64,7 @@ module NavHelper
end
def admin_analytics_nav_links
- %w(dev_ops_report cohorts)
+ %w(dev_ops_report)
end
def group_issues_sub_menu_items
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 871d19c6a8c..62580124c0f 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -175,7 +175,9 @@ module NotesHelper
end
end
- def notes_data(issuable)
+ def notes_data(issuable, start_at_zero = false)
+ initial_last_fetched_at = start_at_zero ? 0 : Time.current.to_i * ::Gitlab::UpdatedNotesPaginator::MICROSECOND
+
data = {
discussionsPath: discussions_path(issuable),
registerPath: new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'),
@@ -186,7 +188,7 @@ module NotesHelper
reopenPath: reopen_issuable_path(issuable),
notesPath: notes_url,
prerenderedNotesCount: issuable.capped_notes_count(MAX_PRERENDERED_NOTES),
- lastFetchedAt: Time.now.to_i * ::Gitlab::UpdatedNotesPaginator::MICROSECOND
+ lastFetchedAt: initial_last_fetched_at
}
if issuable.is_a?(MergeRequest)
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 2b68d953431..729585be84a 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -125,4 +125,13 @@ module NotificationsHelper
def can_read_project?(project)
can?(current_user, :read_project, project)
end
+
+ def notification_dropdown_items(notification_setting)
+ NotificationSetting.levels.each_key.map do |level|
+ next if level == "custom"
+ next if level == "global" && notification_setting.source.nil?
+
+ level
+ end.compact
+ end
end
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index db7527d9d58..03da679cfdd 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -8,4 +8,30 @@ module NotifyHelper
def issue_reference_link(entity, *args, full: false)
link_to(entity.to_reference(full: full), issue_url(entity, *args))
end
+
+ def invited_role_description(role_name)
+ case role_name
+ when "Guest"
+ s_("InviteEmail|As a guest, you can view projects, leave comments, and create issues.")
+ when "Reporter"
+ s_("InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues.")
+ when "Developer"
+ s_("InviteEmail|As a developer, you have full access to projects, so you can take an idea from concept to production.")
+ when "Maintainer"
+ s_("InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production.")
+ when "Owner"
+ s_("InviteEmail|As an owner, you have full access to projects and can manage access to the group, including inviting new members.")
+ when "Minimal Access"
+ s_("InviteEmail|As a user with minimal access, you can view the high-level group from the UI and API.")
+ end
+ end
+
+ def invited_to_description(source)
+ case source
+ when "project"
+ s_('InviteEmail|Projects can be used to host your code, track issues, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD.')
+ when "group"
+ s_('InviteEmail|Groups assemble related projects together and grant members access to several projects at once.')
+ end
+ end
end
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 6d721776f0d..51f4304911b 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -17,7 +17,7 @@ module OperationsHelper
'prometheus_authorization_key' => @project.alerting_setting&.token,
'prometheus_api_url' => prometheus_service.api_url,
'prometheus_url' => notify_project_prometheus_alerts_url(@project, format: :json),
- 'alerts_setup_url' => help_page_path('operations/incident_management/alert_integrations.md', anchor: 'generic-http-endpoint'),
+ 'alerts_setup_url' => help_page_path('operations/incident_management/integrations.md', anchor: 'configuration'),
'alerts_usage_url' => project_alert_management_index_path(@project),
'disabled' => disabled.to_s,
'project_path' => @project.full_path,
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index 58f1abb2818..b705258f133 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -5,8 +5,8 @@ module Projects::AlertManagementHelper
{
'project-path' => project.full_path,
'enable-alert-management-path' => project_settings_operations_path(project, anchor: 'js-alert-management-settings'),
- 'alerts-help-url' => help_page_url('operations/incident_management/index.md'),
- 'populating-alerts-help-url' => help_page_url('operations/incident_management/index.md', anchor: 'enable-alert-management'),
+ 'alerts-help-url' => help_page_url('operations/incident_management/alerts.md'),
+ 'populating-alerts-help-url' => help_page_url('operations/incident_management/integrations.md', anchor: 'configuration'),
'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => can?(current_user, :admin_operations, project).to_s,
'alert-management-enabled' => alert_management_enabled?(project).to_s,
@@ -20,7 +20,8 @@ module Projects::AlertManagementHelper
'alert-id' => alert_id,
'project-path' => project.full_path,
'project-id' => project.id,
- 'project-issues-path' => project_issues_path(project)
+ 'project-issues-path' => project_issues_path(project),
+ 'page' => 'OPERATIONS'
}
end
diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb
index 168526d2abb..99c1b742da4 100644
--- a/app/helpers/projects/project_members_helper.rb
+++ b/app/helpers/projects/project_members_helper.rb
@@ -26,4 +26,30 @@ module Projects::ProjectMembersHelper
project.group.has_owner?(current_user)
end
+
+ def project_group_links_data_json(group_links)
+ GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json
+ end
+
+ def project_members_data_json(project, members)
+ MemberSerializer.new.represent(members, { current_user: current_user, group: project.group, source: project }).to_json
+ end
+
+ def project_members_list_data_attributes(project, members)
+ {
+ members: project_members_data_json(project, members),
+ member_path: project_project_member_path(project, ':id'),
+ source_id: project.id,
+ can_manage_members: can_manage_project_members?(project)
+ }
+ end
+
+ def project_group_links_list_data_attributes(project, group_links)
+ {
+ members: project_group_links_data_json(group_links),
+ member_path: project_group_link_path(project, ':id'),
+ source_id: project.id,
+ can_manage_members: can_manage_project_members?(project)
+ }
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index b21d3ca51db..f5cd89d96b4 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -139,6 +139,10 @@ module ProjectsHelper
project_nav_tabs.include? name
end
+ def any_project_nav_tab?(tabs)
+ tabs.any? { |tab| project_nav_tab?(tab) }
+ end
+
def project_for_deploy_key(deploy_key)
if deploy_key.has_access_to?(@project)
@project
@@ -267,10 +271,6 @@ module ProjectsHelper
"xcode://clone?repo=#{CGI.escape(default_url_to_repo(project))}"
end
- def link_to_filter_repo
- link_to 'git filter-repo', 'https://github.com/newren/git-filter-repo', target: '_blank', rel: 'noopener noreferrer'
- end
-
def explore_projects_tab?
current_page?(explore_projects_path) ||
current_page?(trending_explore_projects_path) ||
@@ -378,6 +378,20 @@ module ProjectsHelper
private
+ def can_read_security_configuration?(project, current_user)
+ ::Feature.enabled?(:secure_security_and_compliance_configuration_page_on_ce, @subject, default_enabled: :yaml) &&
+ can?(current_user, :read_security_configuration, project)
+ end
+
+ def get_project_security_nav_tabs(project, current_user)
+ if can_read_security_configuration?(project, current_user)
+ [:security_and_compliance, :security_configuration]
+ else
+ []
+ end
+ end
+
+ # rubocop:disable Metrics/CyclomaticComplexity
def get_project_nav_tabs(project, current_user)
nav_tabs = [:home]
@@ -386,6 +400,8 @@ module ProjectsHelper
nav_tabs << :releases if can?(current_user, :read_release, project)
end
+ nav_tabs += get_project_security_nav_tabs(project, current_user)
+
if project.repo_exists? && can?(current_user, :read_merge_request, project)
nav_tabs << :merge_requests
end
@@ -417,8 +433,11 @@ module ProjectsHelper
nav_tabs += package_nav_tabs(project, current_user)
+ nav_tabs << :learn_gitlab if learn_gitlab_experiment_enabled?(project)
+
nav_tabs
end
+ # rubocop:enable Metrics/CyclomaticComplexity
def package_nav_tabs(project, current_user)
[].tap do |tabs|
@@ -699,6 +718,12 @@ module ProjectsHelper
"#{request.path}?#{options.to_param}"
end
+ def sidebar_security_configuration_paths
+ %w[
+ projects/security/configuration#show
+ ]
+ end
+
def sidebar_projects_paths
%w[
projects#show
@@ -763,6 +788,10 @@ module ProjectsHelper
]
end
+ def sidebar_security_paths
+ %w[projects/security/configuration#show]
+ end
+
def user_can_see_auto_devops_implicitly_enabled_banner?(project, user)
Ability.allowed?(user, :admin_project, project) &&
project.has_auto_devops_implicitly_enabled? &&
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index bdc86043ddc..a7acc0cd7db 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -129,6 +129,27 @@ module SearchHelper
@search_service ||= ::SearchService.new(current_user, params.merge(confidential: Gitlab::Utils.to_boolean(params[:confidential])))
end
+ def search_sort_options
+ [
+ {
+ title: _('Created date'),
+ sortable: true,
+ sortParam: {
+ asc: 'created_asc',
+ desc: 'created_desc'
+ }
+ },
+ {
+ title: _('Last updated'),
+ sortable: true,
+ sortParam: {
+ asc: 'updated_asc',
+ desc: 'updated_desc'
+ }
+ }
+ ]
+ end
+
private
# Autocomplete results for various settings pages
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index 5f361e6653d..14d20e7c622 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -128,6 +128,13 @@ module ServicesHelper
!Gitlab.com?
end
+ def jira_issue_breadcrumb_link(issue_reference)
+ link_to '', { class: 'gl-display-flex gl-align-items-center gl-white-space-nowrap' } do
+ icon = image_tag image_path('illustrations/logos/jira.svg'), width: 15, height: 15, class: 'gl-mr-2'
+ [icon, issue_reference].join.html_safe
+ end
+ end
+
extend self
private
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 38758957dba..35c8b140bfe 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -30,8 +30,7 @@ module SortingHelper
sort_value_contacted_date => sort_title_contacted_date,
sort_value_relative_position => sort_title_relative_position,
sort_value_size => sort_title_size,
- sort_value_expire_date => sort_title_expire_date,
- sort_value_relevant => sort_title_relevant
+ sort_value_expire_date => sort_title_expire_date
}
end
@@ -85,13 +84,6 @@ module SortingHelper
}
end
- def search_reverse_sort_options_hash
- {
- sort_value_recently_created => sort_value_oldest_created,
- sort_value_oldest_created => sort_value_recently_created
- }
- end
-
def groups_sort_options_hash
{
sort_value_name => sort_title_name,
@@ -229,10 +221,6 @@ module SortingHelper
sort_options_hash[sort_value]
end
- def search_sort_option_title(sort_value)
- sort_options_hash[sort_value]
- end
-
def sort_direction_icon(sort_value)
case sort_value
when sort_value_milestone, sort_value_due_date, /_asc\z/
@@ -271,13 +259,6 @@ module SortingHelper
sort_direction_button(url, reverse_sort, sort_value)
end
- def search_sort_direction_button(sort_value)
- reverse_sort = search_reverse_sort_options_hash[sort_value]
- url = page_filter_path(sort: reverse_sort)
-
- sort_direction_button(url, reverse_sort, sort_value)
- end
-
def packages_sort_options_hash
{
sort_value_recently_created => sort_title_created_date,
diff --git a/app/helpers/sorting_titles_values_helper.rb b/app/helpers/sorting_titles_values_helper.rb
index 27f3638dc73..651a6437479 100644
--- a/app/helpers/sorting_titles_values_helper.rb
+++ b/app/helpers/sorting_titles_values_helper.rb
@@ -166,10 +166,6 @@ module SortingTitlesValuesHelper
s_('SortOptions|Expired date')
end
- def sort_title_relevant
- s_('SortOptions|Relevant')
- end
-
# Values.
def sort_value_access_level_asc
'access_level_asc'
@@ -330,10 +326,6 @@ module SortingTitlesValuesHelper
def sort_value_expire_date
'expired_asc'
end
-
- def sort_value_relevant
- 'relevant'
- end
end
SortingHelper.include_if_ee('::EE::SortingTitlesValuesHelper')
diff --git a/app/helpers/stat_anchors_helper.rb b/app/helpers/stat_anchors_helper.rb
index 76e58b45912..1e8e6371284 100644
--- a/app/helpers/stat_anchors_helper.rb
+++ b/app/helpers/stat_anchors_helper.rb
@@ -11,14 +11,14 @@ module StatAnchorsHelper
private
def button_attribute(anchor)
- "btn-#{anchor.class_modifier || 'missing'}"
+ "btn-#{anchor.class_modifier || 'dashed'}"
end
def extra_classes(anchor)
if anchor.is_link
'stat-link'
else
- "btn #{button_attribute(anchor)}"
+ "gl-button btn #{button_attribute(anchor)}"
end
end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index f24aa5d3bcb..b050f533d77 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -4,30 +4,6 @@ module TreeHelper
include BlobHelper
include WebIdeButtonHelper
- FILE_LIMIT = 1_000
-
- # Sorts a repository's tree so that folders are before files and renders
- # their corresponding partials
- #
- # tree - A `Tree` object for the current tree
- # rubocop: disable CodeReuse/ActiveRecord
- def render_tree(tree)
- # Sort submodules and folders together by name ahead of files
- folders, files, submodules = tree.trees, tree.blobs, tree.submodules
- tree = []
- items = (folders + submodules).sort_by(&:name) + files
-
- if items.size > FILE_LIMIT
- tree << render(partial: 'projects/tree/truncated_notice_tree_row',
- locals: { limit: FILE_LIMIT, total: items.size })
- items = items.take(FILE_LIMIT)
- end
-
- tree << render(partial: 'projects/tree/tree_row', collection: items) if items.present?
- tree.join.html_safe
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
# Return an image icon depending on the file type and mode
#
# type - String type of the tree item; either 'folder' or 'file'
@@ -37,20 +13,6 @@ module TreeHelper
sprite_icon(file_type_icon_class(type, mode, name))
end
- # Using Rails `*_path` methods can be slow, especially when generating
- # many paths, as with a repository tree that has thousands of items.
- def fast_project_blob_path(project, blob_path)
- ActionDispatch::Journey::Router::Utils.escape_path(
- File.join(relative_url_root, project.path_with_namespace, '-', 'blob', blob_path)
- )
- end
-
- def fast_project_tree_path(project, tree_path)
- ActionDispatch::Journey::Router::Utils.escape_path(
- File.join(relative_url_root, project.path_with_namespace, '-', 'tree', tree_path)
- )
- end
-
# Simple shortcut to File.join
def tree_join(*args)
File.join(*args)
@@ -167,13 +129,6 @@ module TreeHelper
Gitlab.config.gitlab.relative_url_root.presence || '/'
end
- # project and path are used on the EE version
- def tree_content_data(logs_path, project, path)
- {
- "logs-path" => logs_path
- }
- end
-
def breadcrumb_data_attributes
attrs = {
can_collaborate: can_collaborate_with_project?(@project).to_s,
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index a06a31ddf32..f55a6c3c9e5 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -11,6 +11,7 @@ module UserCalloutsHelper
CUSTOMIZE_HOMEPAGE = 'customize_homepage'
FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
+ UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
def show_admin_integrations_moved?
!user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
@@ -56,6 +57,10 @@ module UserCalloutsHelper
!user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
end
+ def show_unfinished_tag_cleanup_callout?
+ !user_dismissed?(UNFINISHED_TAG_CLEANUP_CALLOUT)
+ end
+
def show_registration_enabled_user_callout?
!Gitlab.com? &&
current_user&.admin? &&
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index a5d4d6872df..1979426f844 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -242,7 +242,7 @@ module UsersHelper
tabs = []
if can?(current_user, :read_user_profile, @user)
- tabs += [:overview, :activity, :groups, :contributed, :projects, :starred, :snippets]
+ tabs += [:overview, :activity, :groups, :contributed, :projects, :starred, :snippets, :followers, :following]
end
tabs
@@ -299,6 +299,27 @@ module UsersHelper
html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization }
end
+
+ def user_table_headers
+ [
+ {
+ section_class_name: 'section-40',
+ header_text: _('Name')
+ },
+ {
+ section_class_name: 'section-10',
+ header_text: _('Projects')
+ },
+ {
+ section_class_name: 'section-15',
+ header_text: _('Created on')
+ },
+ {
+ section_class_name: 'section-15',
+ header_text: _('Last activity')
+ }
+ ]
+ end
end
UsersHelper.prepend_if_ee('EE::UsersHelper')
diff --git a/app/mailers/emails/in_product_marketing.rb b/app/mailers/emails/in_product_marketing.rb
new file mode 100644
index 00000000000..0be9ec5f915
--- /dev/null
+++ b/app/mailers/emails/in_product_marketing.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Emails
+ module InProductMarketing
+ include InProductMarketingHelper
+
+ FROM_ADDRESS = 'GitLab <team@gitlab.com>'.freeze
+ CUSTOM_HEADERS = {
+ 'X-Mailgun-Track' => 'yes',
+ 'X-Mailgun-Track-Clicks' => 'yes',
+ 'X-Mailgun-Track-Opens' => 'yes',
+ 'X-Mailgun-Tag' => 'marketing'
+ }.freeze
+
+ def in_product_marketing_email(recipient_id, group_id, track, series)
+ @track = track
+ @series = series
+ @group = Group.find(group_id)
+
+ email = User.find(recipient_id).notification_email_for(@group)
+ subject = subject_line(track, series)
+ mail_to(to: email, subject: subject)
+ end
+
+ private
+
+ def mail_to(to:, subject:)
+ mail(to: to, subject: subject, from: FROM_ADDRESS, reply_to: FROM_ADDRESS, **CUSTOM_HEADERS) do |format|
+ format.html { render layout: nil }
+ format.text { render layout: nil }
+ end
+ end
+ end
+end
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 69f5fe1430a..f4d3676dc5c 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -4,9 +4,11 @@ module Emails
module Members
extend ActiveSupport::Concern
include MembersHelper
+ include Gitlab::Experiment::Dsl
included do
helper_method :member_source, :member
+ helper_method :experiment
end
def member_access_requested_email(member_source_type, member_id, recipient_id)
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 4faa1a11276..494d9875ce4 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -82,6 +82,13 @@ module Emails
mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
end
+ def request_review_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
+ setup_merge_request_mail(merge_request_id, recipient_id)
+
+ @updated_by = User.find(updated_by_user_id)
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ end
+
def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index ebf6dd68ec7..8f947ea7113 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -21,6 +21,7 @@ class Notify < ApplicationMailer
include Emails::Groups
include Emails::Reviews
include Emails::ServiceDesk
+ include Emails::InProductMarketing
helper TimeboxesHelper
helper MergeRequestsHelper
@@ -32,6 +33,7 @@ class Notify < ApplicationMailer
helper AvatarsHelper
helper GitlabRoutingHelper
helper IssuablesHelper
+ helper InProductMarketingHelper
def test_email(recipient_email, subject, body)
mail(to: recipient_email,
diff --git a/app/models/active_session.rb b/app/models/active_session.rb
index dded0eb1dc3..823685f78f4 100644
--- a/app/models/active_session.rb
+++ b/app/models/active_session.rb
@@ -1,5 +1,24 @@
# frozen_string_literal: true
+# Backing store for GitLab session data.
+#
+# The raw session information is stored by the Rails session store
+# (config/initializers/session_store.rb). These entries are accessible by the
+# rack_key_name class method and consistute the base of the session data
+# entries. All other entries in the session store can be traced back to these
+# entries.
+#
+# After a user logs in (config/initializers/warden.rb) a further entry is made
+# in Redis. This entry holds a record of the user's logged in session. These
+# are accessible with the key_name(user_id, session_id) class method. These
+# entries will expire. Lookups to these entries are lazilly cleaned on future
+# user access.
+#
+# There is a reference to all sessions that belong to a specific user. A
+# user may login through multiple browsers/devices and thus record multiple
+# login sessions. These are accessible through the lookup_key_name(user_id)
+# class method.
+#
class ActiveSession
include ActiveModel::Model
@@ -143,6 +162,10 @@ class ActiveSession
list(user).reject(&:is_impersonated)
end
+ def self.rack_key_name(session_id)
+ "#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}"
+ end
+
def self.key_name(user_id, session_id = '*')
"#{Gitlab::Redis::SharedState::USER_SESSIONS_NAMESPACE}:#{user_id}:#{session_id}"
end
@@ -197,7 +220,7 @@ class ActiveSession
end
def self.rack_session_keys(rack_session_ids)
- rack_session_ids.map { |session_id| "#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}" }
+ rack_session_ids.map { |session_id| rack_key_name(session_id)}
end
def self.raw_active_session_entries(redis, session_ids, user_id)
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 5655ea4d4bf..33c058dab96 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -29,6 +29,21 @@ class ApplicationSetting < ApplicationRecord
@repository_storages_weighted_atributes ||= Gitlab.config.repositories.storages.keys.map { |k| "repository_storages_weighted_#{k}".to_sym }.freeze
end
+ def self.kroki_formats_attributes
+ {
+ blockdiag: {
+ label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag and RackDiag)'
+ },
+ bpmn: {
+ label: 'BPMN'
+ },
+ excalidraw: {
+ label: 'Excalidraw'
+ }
+ }
+ end
+
+ store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true
store_accessor :repository_storages_weighted, *Gitlab.config.repositories.storages.keys, prefix: true
# Include here so it can override methods from
@@ -43,6 +58,8 @@ class ApplicationSetting < ApplicationRecord
serialize :domain_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_denylist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :asset_proxy_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/300916
serialize :asset_proxy_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
cache_markdown_field :sign_in_text
@@ -52,6 +69,7 @@ class ApplicationSetting < ApplicationRecord
default_value_for :id, 1
default_value_for :repository_storages_weighted, {}
+ default_value_for :kroki_formats, {}
chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds
@@ -133,6 +151,8 @@ class ApplicationSetting < ApplicationRecord
validate :validate_kroki_url, if: :kroki_enabled
+ validates :kroki_formats, json_schema: { filename: 'application_setting_kroki_formats' }
+
validates :plantuml_url,
presence: true,
if: :plantuml_enabled
@@ -442,6 +462,13 @@ class ApplicationSetting < ApplicationRecord
presence: true,
numericality: { only_integer: true, greater_than: 0 }
+ validates :notes_create_limit,
+ numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+
+ validates :notes_create_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,
@@ -523,6 +550,10 @@ class ApplicationSetting < ApplicationRecord
current_without_cache
end
+ def self.find_or_create_without_cache
+ current_without_cache || create_from_defaults
+ end
+
# Due to the frequency with which settings are accessed, it is
# likely that during a backup restore a running GitLab process
# will insert a new `application_settings` row before the
@@ -557,6 +588,25 @@ class ApplicationSetting < ApplicationRecord
end
end
+ kroki_formats_attributes.keys.each do |key|
+ define_method :"kroki_formats_#{key}=" do |value|
+ super(::Gitlab::Utils.to_boolean(value))
+ end
+ end
+
+ def kroki_format_supported?(diagram_type)
+ case diagram_type
+ when 'excalidraw'
+ return kroki_formats_excalidraw
+ when 'bpmn'
+ return kroki_formats_bpmn
+ end
+
+ return kroki_formats_blockdiag if ::Gitlab::Kroki::BLOCKDIAG_FORMATS.include?(diagram_type)
+
+ ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.include?(diagram_type)
+ end
+
private
def parsed_grafana_url
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index b05355f14b4..2911ae6b1c8 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -100,6 +100,8 @@ module ApplicationSettingImplementation
max_import_size: 0,
minimum_password_length: DEFAULT_MINIMUM_PASSWORD_LENGTH,
mirror_available: true,
+ notes_create_limit: 300,
+ notes_create_limit_allowlist: [],
notify_on_unknown_sign_in: true,
outbound_local_requests_whitelist: [],
password_authentication_enabled_for_git: true,
@@ -174,6 +176,7 @@ module ApplicationSettingImplementation
container_registry_expiration_policies_worker_capacity: 0,
kroki_enabled: false,
kroki_url: nil,
+ kroki_formats: { blockdiag: false, bpmn: false, excalidraw: false },
rate_limiting_response_text: nil
}
end
@@ -269,13 +272,21 @@ module ApplicationSettingImplementation
self.protected_paths = strings_to_array(values)
end
- def asset_proxy_whitelist=(values)
+ def notes_create_limit_allowlist_raw
+ array_to_string(self.notes_create_limit_allowlist)
+ end
+
+ def notes_create_limit_allowlist_raw=(values)
+ self.notes_create_limit_allowlist = strings_to_array(values).map(&:downcase)
+ end
+
+ def asset_proxy_allowlist=(values)
values = strings_to_array(values) if values.is_a?(String)
- # make sure we always whitelist the running host
+ # make sure we always allow the running host
values << Gitlab.config.gitlab.host unless values.include?(Gitlab.config.gitlab.host)
- self[:asset_proxy_whitelist] = values
+ self[:asset_proxy_allowlist] = values
end
def repository_storages
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index d1c0bb11dc8..32c9d44f836 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -55,15 +55,20 @@ class AuditEvent < ApplicationRecord
end
def author_name
- lazy_author.name
+ author&.name
end
def formatted_details
details.merge(details.slice(:from, :to).transform_values(&:to_s))
end
+ def author
+ lazy_author&.itself.presence ||
+ ::Gitlab::Audit::NullAuthor.for(author_id, (self[:author_name] || details[:author_name]))
+ end
+
def lazy_author
- BatchLoader.for(author_id).batch(default_value: default_author_value, replace_methods: false) do |author_ids, loader|
+ BatchLoader.for(author_id).batch(replace_methods: false) do |author_ids, loader|
User.select(:id, :name, :username).where(id: author_ids).find_each do |user|
loader.call(user.id, user)
end
diff --git a/app/models/board.rb b/app/models/board.rb
index a57d101b30a..85fad762ebe 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -44,6 +44,14 @@ class Board < ApplicationRecord
def scoped?
false
end
+
+ def self.to_type
+ name.demodulize
+ end
+
+ def to_type
+ self.class.to_type
+ end
end
Board.prepend_if_ee('EE::Board')
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index a4d0b7485ba..16224fde502 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -43,6 +43,8 @@ class BulkImports::Entity < ApplicationRecord
validate :validate_parent_is_a_group, if: :parent
validate :validate_imported_entity_type
+ validate :validate_destination_namespace_ascendency, if: :group_entity?
+
enum source_type: { group_entity: 0, project_entity: 1 }
state_machine :status, initial: :created do
@@ -107,4 +109,17 @@ class BulkImports::Entity < ApplicationRecord
)
end
end
+
+ def validate_destination_namespace_ascendency
+ source = Group.find_by_full_path(source_full_path)
+
+ return unless source
+
+ if source.self_and_descendants.any? { |namespace| namespace.full_path == destination_namespace }
+ errors.add(
+ :destination_namespace,
+ s_('BulkImport|destination group cannot be part of the source group tree')
+ )
+ end
+ end
end
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index ef3891908f7..ca400cebe4e 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -27,7 +27,7 @@ module Ci
# rubocop:enable Cop/ActiveRecordSerialize
state_machine :status do
- after_transition [:created, :manual] => :pending do |bridge|
+ after_transition [:created, :manual, :waiting_for_resource] => :pending do |bridge|
next unless bridge.downstream_project
bridge.run_after_commit do
@@ -156,6 +156,10 @@ module Ci
false
end
+ def any_unmet_prerequisites?
+ false
+ end
+
def expanded_environment_name
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 5e3f42d7c2c..db151126caf 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -20,7 +20,6 @@ module Ci
belongs_to :runner
belongs_to :trigger_request
belongs_to :erased_by, class_name: 'User'
- belongs_to :resource_group, class_name: 'Ci::ResourceGroup', inverse_of: :builds
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
RUNNER_FEATURES = {
@@ -38,7 +37,6 @@ module Ci
DEGRADATION_THRESHOLD_VARIABLE_NAME = 'DEGRADATION_THRESHOLD'
has_one :deployment, as: :deployable, class_name: 'Deployment'
- has_one :resource, class_name: 'Ci::Resource', inverse_of: :build
has_one :pending_state, class_name: 'Ci::BuildPendingState', inverse_of: :build
has_many :trace_sections, class_name: 'Ci::BuildTraceSection'
has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id, inverse_of: :build
@@ -230,27 +228,20 @@ module Ci
end
def with_preloads
- preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
+ preload(:job_artifacts_archive, :job_artifacts, :tags, project: [:namespace])
end
end
state_machine :status do
event :enqueue do
- transition [:created, :skipped, :manual, :scheduled] => :waiting_for_resource, if: :requires_resource?
transition [:created, :skipped, :manual, :scheduled] => :preparing, if: :any_unmet_prerequisites?
end
event :enqueue_scheduled do
- transition scheduled: :waiting_for_resource, if: :requires_resource?
transition scheduled: :preparing, if: :any_unmet_prerequisites?
transition scheduled: :pending
end
- event :enqueue_waiting_for_resource do
- transition waiting_for_resource: :preparing, if: :any_unmet_prerequisites?
- transition waiting_for_resource: :pending
- end
-
event :enqueue_preparing do
transition preparing: :pending
end
@@ -279,23 +270,6 @@ module Ci
build.scheduled_at = build.options_scheduled_at
end
- before_transition any => :waiting_for_resource do |build|
- build.waiting_for_resource_at = Time.current
- end
-
- before_transition on: :enqueue_waiting_for_resource do |build|
- next unless build.requires_resource?
-
- build.resource_group.assign_resource_to(build) # If false is returned, it stops the transition
- end
-
- after_transition any => :waiting_for_resource do |build|
- build.run_after_commit do
- Ci::ResourceGroups::AssignResourceFromResourceGroupWorker
- .perform_async(build.resource_group_id)
- end
- end
-
before_transition on: :enqueue_preparing do |build|
!build.any_unmet_prerequisites? # If false is returned, it stops the transition
end
@@ -328,16 +302,6 @@ module Ci
end
end
- after_transition any => ::Ci::Build.completed_statuses do |build|
- next unless build.resource_group_id.present?
- next unless build.resource_group.release_resource_from(build)
-
- build.run_after_commit do
- Ci::ResourceGroups::AssignResourceFromResourceGroupWorker
- .perform_async(build.resource_group_id)
- end
- end
-
after_transition any => [:success, :failed, :canceled] do |build|
build.run_after_commit do
build.run_status_commit_hooks!
@@ -403,7 +367,7 @@ module Ci
def detailed_status(current_user)
Gitlab::Ci::Status::Build::Factory
- .new(self, current_user)
+ .new(self.present, current_user)
.fabricate!
end
@@ -467,6 +431,11 @@ module Ci
pipeline.builds.retried.where(name: self.name).count
end
+ override :all_met_to_become_pending?
+ def all_met_to_become_pending?
+ super && !any_unmet_prerequisites?
+ end
+
def any_unmet_prerequisites?
prerequisites.present?
end
@@ -501,10 +470,6 @@ module Ci
end
end
- def requires_resource?
- self.resource_group_id.present?
- end
-
def has_environment?
environment.present?
end
@@ -821,7 +786,9 @@ module Ci
end
def artifacts_file_for_type(type)
- job_artifacts.find_by(file_type: Ci::JobArtifact.file_types[type])&.file
+ file_types = Ci::JobArtifact.associated_file_types_for(type)
+ file_types_ids = file_types&.map { |file_type| Ci::JobArtifact.file_types[file_type] }
+ job_artifacts.find_by(file_type: file_types_ids)&.file
end
def coverage_regex
@@ -941,19 +908,12 @@ module Ci
end
def collect_coverage_reports!(coverage_report)
- project_path, worktree_paths = if Feature.enabled?(:smart_cobertura_parser, project)
- # If the flag is disabled, we intentionally pass nil
- # for both project_path and worktree_paths to fallback
- # to the non-smart behavior of the parser
- [project.full_path, pipeline.all_worktree_paths]
- end
-
each_report(Ci::JobArtifact::COVERAGE_REPORT_FILE_TYPES) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(
blob,
coverage_report,
- project_path: project_path,
- worktree_paths: worktree_paths
+ project_path: project.full_path,
+ worktree_paths: pipeline.all_worktree_paths
)
end
@@ -1122,7 +1082,6 @@ module Ci
end
def conditionally_allow_failure!(exit_code)
- return unless ::Gitlab::Ci::Features.allow_failure_with_exit_codes_enabled?
return unless exit_code
if allowed_to_fail_with_code?(exit_code)
diff --git a/app/models/ci/build_dependencies.rb b/app/models/ci/build_dependencies.rb
index a6abeb517c1..b50ecf99439 100644
--- a/app/models/ci/build_dependencies.rb
+++ b/app/models/ci/build_dependencies.rb
@@ -103,7 +103,7 @@ module Ci
end
def valid_local?
- return true if Feature.enabled?(:ci_disable_validates_dependencies)
+ return true unless Gitlab::Ci::Features.validate_build_dependencies?(project)
local.all?(&:valid_dependency?)
end
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index ceefb6a8b8a..d4f9f78a1ac 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -77,6 +77,22 @@ module Ci
end
##
+ # Sometime we need to ensure that the first read goes to a primary
+ # database, what is especially important in EE. This method does not
+ # change the behavior in CE.
+ #
+ def with_read_consistency(build, &block)
+ return yield unless consistent_reads_enabled?(build)
+
+ ::Gitlab::Database::Consistency
+ .with_read_consistency(&block)
+ end
+
+ def consistent_reads_enabled?(build)
+ Feature.enabled?(:gitlab_ci_trace_read_consistency, build.project, type: :development, default_enabled: true)
+ end
+
+ ##
# Sometimes we do not want to read raw data. This method makes it easier
# to find attributes that are just metadata excluding raw data.
#
@@ -154,8 +170,8 @@ module Ci
in_lock(lock_key, **lock_params) do # exclusive Redis lock is acquired first
raise FailedToPersistDataError, 'Modifed build trace chunk detected' if has_changes_to_save?
- self.reset.then do |chunk| # we ensure having latest lock_version
- chunk.unsafe_persist_data! # we migrate the data and update data store
+ self.class.with_read_consistency(build) do
+ self.reset.then { |chunk| chunk.unsafe_persist_data! }
end
end
rescue FailedToObtainLockError
diff --git a/app/models/ci/build_trace_chunks/fog.rb b/app/models/ci/build_trace_chunks/fog.rb
index 27b579bf428..cbf0c0a1696 100644
--- a/app/models/ci/build_trace_chunks/fog.rb
+++ b/app/models/ci/build_trace_chunks/fog.rb
@@ -14,15 +14,7 @@ module Ci
end
def set_data(model, new_data)
- if Feature.enabled?(:ci_live_trace_use_fog_attributes, default_enabled: true)
- files.create(create_attributes(model, new_data))
- else
- # TODO: Support AWS S3 server side encryption
- files.create({
- key: key(model),
- body: new_data
- })
- end
+ files.create(create_attributes(model, new_data))
end
def append_data(model, new_data, offset)
diff --git a/app/models/ci/build_trace_section.rb b/app/models/ci/build_trace_section.rb
index 8be42eb48d6..5091e3ff04a 100644
--- a/app/models/ci/build_trace_section.rb
+++ b/app/models/ci/build_trace_section.rb
@@ -2,6 +2,7 @@
module Ci
class BuildTraceSection < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
extend Gitlab::Ci::Model
belongs_to :build, class_name: 'Ci::Build'
diff --git a/app/models/ci/daily_build_group_report_result.rb b/app/models/ci/daily_build_group_report_result.rb
index e9f3366b939..23c96e63724 100644
--- a/app/models/ci/daily_build_group_report_result.rb
+++ b/app/models/ci/daily_build_group_report_result.rb
@@ -9,14 +9,19 @@ module Ci
belongs_to :last_pipeline, class_name: 'Ci::Pipeline', foreign_key: :last_pipeline_id
belongs_to :project
+ belongs_to :group
validates :data, json_schema: { filename: "daily_build_group_report_result_data" }
scope :with_included_projects, -> { includes(:project) }
+ scope :by_ref_path, -> (ref_path) { where(ref_path: ref_path) }
scope :by_projects, -> (ids) { where(project_id: ids) }
+ scope :by_group, -> (group_id) { where(group_id: group_id) }
scope :with_coverage, -> { where("(data->'coverage') IS NOT NULL") }
scope :with_default_branch, -> { where(default_branch: true) }
scope :by_date, -> (start_date) { where(date: report_window(start_date)..Date.current) }
+ scope :by_dates, -> (start_date, end_date) { where(date: start_date..end_date) }
+ scope :ordered_by_date_and_group_name, -> { order(date: :desc, group_name: :asc) }
store_accessor :data, :coverage
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index f13be3b3c86..f927111758a 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -19,6 +19,8 @@ module Ci
NON_ERASABLE_FILE_TYPES = %w[trace].freeze
TERRAFORM_REPORT_FILE_TYPES = %w[terraform].freeze
UNSUPPORTED_FILE_TYPES = %i[license_management].freeze
+ SAST_REPORT_TYPES = %w[sast].freeze
+ SECRET_DETECTION_REPORT_TYPES = %w[secret_detection].freeze
DEFAULT_FILE_NAMES = {
archive: nil,
metadata: nil,
@@ -150,6 +152,14 @@ module Ci
with_file_types(REPORT_TYPES.keys.map(&:to_s))
end
+ scope :sast_reports, -> do
+ with_file_types(SAST_REPORT_TYPES)
+ end
+
+ scope :secret_detection_reports, -> do
+ with_file_types(SECRET_DETECTION_REPORT_TYPES)
+ end
+
scope :test_reports, -> do
with_file_types(TEST_REPORT_FILE_TYPES)
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 88c7002b1b6..3be107ea2e1 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -251,6 +251,7 @@ module Ci
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
pipeline.run_after_commit do
::Ci::PipelineArtifacts::CoverageReportWorker.perform_async(pipeline.id)
+ ::Ci::PipelineArtifacts::CreateQualityReportWorker.perform_async(pipeline.id)
end
end
@@ -263,8 +264,6 @@ module Ci
end
after_transition any => any do |pipeline|
- next unless Feature.enabled?(:jira_sync_builds, pipeline.project)
-
pipeline.run_after_commit do
# Passing the seq-id ensures this is idempotent
seq_id = ::Atlassian::JiraConnect::Client.generate_update_sequence_id
@@ -678,7 +677,7 @@ module Ci
def number_of_warnings
BatchLoader.for(id).batch(default_value: 0) do |pipeline_ids, loader|
- ::Ci::Build.where(commit_id: pipeline_ids)
+ ::CommitStatus.where(commit_id: pipeline_ids)
.latest
.failed_but_allowed
.group(:commit_id)
@@ -805,7 +804,7 @@ module Ci
variables.concat(merge_request.predefined_variables)
end
- if Gitlab::Ci::Features.pipeline_open_merge_requests?(project) && open_merge_requests_refs.any?
+ if open_merge_requests_refs.any?
variables.append(key: 'CI_OPEN_MERGE_REQUESTS', value: open_merge_requests_refs.join(','))
end
@@ -962,7 +961,7 @@ module Ci
def detailed_status(current_user)
Gitlab::Ci::Status::Pipeline::Factory
- .new(self, current_user)
+ .new(self.present, current_user)
.fabricate!
end
@@ -998,13 +997,23 @@ module Ci
end
def has_coverage_reports?
- pipeline_artifacts&.has_code_coverage?
+ pipeline_artifacts&.report_exists?(:code_coverage)
end
def can_generate_coverage_reports?
has_reports?(Ci::JobArtifact.coverage_reports)
end
+ def has_codequality_mr_diff_report?
+ pipeline_artifacts&.report_exists?(:code_quality_mr_diff)
+ end
+
+ def can_generate_codequality_reports?
+ return false unless ::Gitlab::Ci::Features.display_quality_on_mr_diff?(project)
+
+ has_reports?(Ci::JobArtifact.codequality_reports)
+ end
+
def test_report_summary
strong_memoize(:test_report_summary) do
Gitlab::Ci::Reports::TestReportSummary.new(latest_builds_report_results)
@@ -1206,6 +1215,21 @@ module Ci
end
# rubocop:enable Rails/FindEach
+ # EE-only
+ def merge_train_pipeline?
+ false
+ end
+
+ def security_reports(report_types: [])
+ reports_scope = report_types.empty? ? ::Ci::JobArtifact.security_reports : ::Ci::JobArtifact.security_reports(file_types: report_types)
+
+ ::Gitlab::Ci::Reports::Security::Reports.new(self).tap do |security_reports|
+ latest_report_builds(reports_scope).each do |build|
+ build.collect_security_reports!(security_reports)
+ end
+ end
+ end
+
private
def add_message(severity, content)
diff --git a/app/models/ci/pipeline_artifact.rb b/app/models/ci/pipeline_artifact.rb
index b6db8cad667..f538a4cd808 100644
--- a/app/models/ci/pipeline_artifact.rb
+++ b/app/models/ci/pipeline_artifact.rb
@@ -14,7 +14,13 @@ module Ci
EXPIRATION_DATE = 1.week.freeze
DEFAULT_FILE_NAMES = {
- code_coverage: 'code_coverage.json'
+ code_coverage: 'code_coverage.json',
+ code_quality_mr_diff: 'code_quality_mr_diff.json'
+ }.freeze
+
+ REPORT_TYPES = {
+ code_coverage: :raw,
+ code_quality_mr_diff: :raw
}.freeze
belongs_to :project, class_name: "Project", inverse_of: :pipeline_artifacts
@@ -30,15 +36,20 @@ module Ci
update_project_statistics project_statistics_name: :pipeline_artifacts_size
enum file_type: {
- code_coverage: 1
+ code_coverage: 1,
+ code_quality_mr_diff: 2
}
- def self.has_code_coverage?
- where(file_type: :code_coverage).exists?
- end
+ class << self
+ def report_exists?(file_type)
+ return false unless REPORT_TYPES.key?(file_type)
+
+ where(file_type: file_type).exists?
+ end
- def self.find_with_code_coverage
- find_by(file_type: :code_coverage)
+ def find_by_file_type(file_type)
+ find_by(file_type: file_type)
+ end
end
def present
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 8c9ad343f32..2fae077dd87 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -21,7 +21,7 @@ module Ci
validates :cron_timezone, cron_timezone: true, presence: { unless: :importing? }
validates :ref, presence: { unless: :importing? }
validates :description, presence: true
- validates :variables, variable_duplicates: true
+ validates :variables, nested_attributes_duplicates: true
strip_attributes :cron
diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb
index 6aaf6ac530b..fae65ed0632 100644
--- a/app/models/ci/processable.rb
+++ b/app/models/ci/processable.rb
@@ -3,6 +3,11 @@
module Ci
class Processable < ::CommitStatus
include Gitlab::Utils::StrongMemoize
+ extend ::Gitlab::Utils::Override
+
+ has_one :resource, class_name: 'Ci::Resource', foreign_key: 'build_id', inverse_of: :processable
+
+ belongs_to :resource_group, class_name: 'Ci::ResourceGroup', inverse_of: :processables
accepts_nested_attributes_for :needs
@@ -20,6 +25,48 @@ module Ci
where('NOT EXISTS (?)', needs)
end
+ state_machine :status do
+ event :enqueue do
+ transition [:created, :skipped, :manual, :scheduled] => :waiting_for_resource, if: :with_resource_group?
+ end
+
+ event :enqueue_scheduled do
+ transition scheduled: :waiting_for_resource, if: :with_resource_group?
+ end
+
+ event :enqueue_waiting_for_resource do
+ transition waiting_for_resource: :preparing, if: :any_unmet_prerequisites?
+ transition waiting_for_resource: :pending
+ end
+
+ before_transition any => :waiting_for_resource do |processable|
+ processable.waiting_for_resource_at = Time.current
+ end
+
+ before_transition on: :enqueue_waiting_for_resource do |processable|
+ next unless processable.with_resource_group?
+
+ processable.resource_group.assign_resource_to(processable)
+ end
+
+ after_transition any => :waiting_for_resource do |processable|
+ processable.run_after_commit do
+ Ci::ResourceGroups::AssignResourceFromResourceGroupWorker
+ .perform_async(processable.resource_group_id)
+ end
+ end
+
+ after_transition any => ::Ci::Processable.completed_statuses do |processable|
+ next unless processable.with_resource_group?
+ next unless processable.resource_group.release_resource_from(processable)
+
+ processable.run_after_commit do
+ Ci::ResourceGroups::AssignResourceFromResourceGroupWorker
+ .perform_async(processable.resource_group_id)
+ end
+ end
+ end
+
def self.select_with_aggregated_needs(project)
aggregated_needs_names = Ci::BuildNeed
.scoped_build
@@ -77,6 +124,15 @@ module Ci
raise NotImplementedError
end
+ override :all_met_to_become_pending?
+ def all_met_to_become_pending?
+ super && !with_resource_group?
+ end
+
+ def with_resource_group?
+ self.resource_group_id.present?
+ end
+
# Overriding scheduling_type enum's method for nil `scheduling_type`s
def scheduling_type_dag?
scheduling_type.nil? ? find_legacy_scheduling_type == :dag : super
diff --git a/app/models/ci/resource.rb b/app/models/ci/resource.rb
index ee5b6546165..e0e1fab642d 100644
--- a/app/models/ci/resource.rb
+++ b/app/models/ci/resource.rb
@@ -5,9 +5,9 @@ module Ci
extend Gitlab::Ci::Model
belongs_to :resource_group, class_name: 'Ci::ResourceGroup', inverse_of: :resources
- belongs_to :build, class_name: 'Ci::Build', inverse_of: :resource
+ belongs_to :processable, class_name: 'Ci::Processable', foreign_key: 'build_id', inverse_of: :resource
- scope :free, -> { where(build: nil) }
- scope :retained_by, -> (build) { where(build: build) }
+ scope :free, -> { where(processable: nil) }
+ scope :retained_by, -> (processable) { where(processable: processable) }
end
end
diff --git a/app/models/ci/resource_group.rb b/app/models/ci/resource_group.rb
index eb18f3da0bf..85fbe03e1c9 100644
--- a/app/models/ci/resource_group.rb
+++ b/app/models/ci/resource_group.rb
@@ -7,7 +7,7 @@ module Ci
belongs_to :project, inverse_of: :resource_groups
has_many :resources, class_name: 'Ci::Resource', inverse_of: :resource_group
- has_many :builds, class_name: 'Ci::Build', inverse_of: :resource_group
+ has_many :processables, class_name: 'Ci::Processable', inverse_of: :resource_group
validates :key,
length: { maximum: 255 },
@@ -19,12 +19,12 @@ module Ci
##
# NOTE: This is concurrency-safe method that the subquery in the `UPDATE`
# works as explicit locking.
- def assign_resource_to(build)
- resources.free.limit(1).update_all(build_id: build.id) > 0
+ def assign_resource_to(processable)
+ resources.free.limit(1).update_all(build_id: processable.id) > 0
end
- def release_resource_from(build)
- resources.retained_by(build).update_all(build_id: nil) > 0
+ def release_resource_from(processable)
+ resources.retained_by(processable).update_all(build_id: nil) > 0
end
private
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index cc6bd1870b9..ae80692d598 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -118,7 +118,7 @@ module Ci
def number_of_warnings
BatchLoader.for(id).batch(default_value: 0) do |stage_ids, loader|
- ::Ci::Build.where(stage_id: stage_ids)
+ ::CommitStatus.where(stage_id: stage_ids)
.latest
.failed_but_allowed
.group(:stage_id)
diff --git a/app/models/clusters/agent.rb b/app/models/clusters/agent.rb
index c58a3bab1a9..c5b9dddb1da 100644
--- a/app/models/clusters/agent.rb
+++ b/app/models/clusters/agent.rb
@@ -4,6 +4,7 @@ module Clusters
class Agent < ApplicationRecord
self.table_name = 'cluster_agents'
+ belongs_to :created_by_user, class_name: 'User', optional: true
belongs_to :project, class_name: '::Project' # Otherwise, it will load ::Clusters::Project
has_many :agent_tokens, class_name: 'Clusters::AgentToken'
diff --git a/app/models/clusters/agent_token.rb b/app/models/clusters/agent_token.rb
index 5c9561ffa98..b260822f784 100644
--- a/app/models/clusters/agent_token.rb
+++ b/app/models/clusters/agent_token.rb
@@ -8,6 +8,7 @@ module Clusters
self.table_name = 'cluster_agent_tokens'
belongs_to :agent, class_name: 'Clusters::Agent'
+ belongs_to :created_by_user, class_name: 'User', optional: true
before_save :ensure_token
end
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
index 8560826928a..2a051233de2 100644
--- a/app/models/clusters/applications/cert_manager.rb
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -2,6 +2,8 @@
module Clusters
module Applications
+ # DEPRECATED for removal in %14.0
+ # See https://gitlab.com/groups/gitlab-org/-/epics/4280
class CertManager < ApplicationRecord
VERSION = 'v0.10.1'
CRD_VERSION = '0.10'
diff --git a/app/models/clusters/applications/crossplane.rb b/app/models/clusters/applications/crossplane.rb
index 2b1a86706a4..07378b4e8dc 100644
--- a/app/models/clusters/applications/crossplane.rb
+++ b/app/models/clusters/applications/crossplane.rb
@@ -2,6 +2,8 @@
module Clusters
module Applications
+ # DEPRECATED for removal in %14.0
+ # See https://gitlab.com/groups/gitlab-org/-/epics/4280
class Crossplane < ApplicationRecord
VERSION = '0.4.1'
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 36324e7f3e0..e7d4d737b8e 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -2,6 +2,8 @@
module Clusters
module Applications
+ # DEPRECATED for removal in %14.0
+ # See https://gitlab.com/groups/gitlab-org/-/epics/4280
class Ingress < ApplicationRecord
VERSION = '1.40.2'
INGRESS_CONTAINER_NAME = 'nginx-ingress-controller'
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index ff907c6847f..8d7d9c20bfa 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -4,6 +4,8 @@ require 'securerandom'
module Clusters
module Applications
+ # DEPRECATED for removal in %14.0
+ # See https://gitlab.com/groups/gitlab-org/-/epics/4280
class Jupyter < ApplicationRecord
VERSION = '0.9.0'
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 7c131e031c1..6867d7b6934 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -2,6 +2,8 @@
module Clusters
module Applications
+ # DEPRECATED for removal in %14.0
+ # See https://gitlab.com/groups/gitlab-org/-/epics/4280
class Knative < ApplicationRecord
VERSION = '0.10.0'
REPOSITORY = 'https://charts.gitlab.io'
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 56acac53e0b..f87eccecf9f 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.24.0'
+ VERSION = '0.25.0'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index e3dcd5b0d07..da5f4cc1862 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -7,6 +7,7 @@ module Clusters
include EnumWithNil
include AfterCommitQueue
include ReactiveCaching
+ include NullifyIfBlank
RESERVED_NAMESPACES = %w(gitlab-managed-apps).freeze
@@ -25,7 +26,6 @@ module Clusters
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-cbc'
- before_validation :nullify_blank_namespace
before_validation :enforce_namespace_to_lower_case
before_validation :enforce_ca_whitespace_trimming
@@ -64,6 +64,8 @@ module Clusters
default_value_for :authorization_type, :rbac
+ nullify_if_blank :namespace
+
def predefined_variables(project:, environment_name:, kubernetes_namespace: nil)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'KUBE_URL', value: api_url)
@@ -255,10 +257,6 @@ module Clusters
true
end
- def nullify_blank_namespace
- self.namespace = nil if namespace.blank?
- end
-
def extract_relevant_pod_data(pods)
pods.map do |pod|
{
diff --git a/app/models/commit.rb b/app/models/commit.rb
index edce9ad293e..bf168aaacc5 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -36,7 +36,7 @@ class Commit
LINK_EXTENSION_PATTERN = /(patch)/.freeze
cache_markdown_field :title, pipeline: :single_line
- cache_markdown_field :full_title, pipeline: :single_line
+ cache_markdown_field :full_title, pipeline: :single_line, limit: 1.kilobyte
cache_markdown_field :description, pipeline: :commit_description, limit: 1.megabyte
class << self
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index c2aecc524d4..ea2f425c5f6 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -209,14 +209,26 @@ class CommitStatus < ApplicationRecord
end
def group_name
- # 'rspec:linux: 1/10' => 'rspec:linux'
- common_name = name.to_s.gsub(%r{\b\d+[\s:\/\\]+\d+\s*}, '')
+ simplified_commit_status_group_name_feature_flag = Gitlab::SafeRequestStore.fetch("project:#{project_id}:simplified_commit_status_group_name") do
+ Feature.enabled?(:simplified_commit_status_group_name, project, default_enabled: false)
+ end
+
+ if simplified_commit_status_group_name_feature_flag
+ # Only remove one or more [...] "X/Y" "X Y" from the end of build names.
+ # More about the regular expression logic: https://docs.gitlab.com/ee/ci/jobs/#group-jobs-in-a-pipeline
+
+ name.to_s.sub(%r{([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z}, '').strip
+ else
+ # Prior implementation, remove [...] "X/Y" "X Y" from the beginning and middle of build names
+ # 'rspec:linux: 1/10' => 'rspec:linux'
+ common_name = name.to_s.gsub(%r{\b\d+[\s:\/\\]+\d+\s*}, '')
- # 'rspec:linux: [aws, max memory]' => 'rspec:linux', 'rspec:linux: [aws]' => 'rspec:linux'
- common_name.gsub!(%r{: \[.*\]\s*\z}, '')
+ # 'rspec:linux: [aws, max memory]' => 'rspec:linux', 'rspec:linux: [aws]' => 'rspec:linux'
+ common_name.gsub!(%r{: \[.*\]\s*\z}, '')
- common_name.strip!
- common_name
+ common_name.strip!
+ common_name
+ end
end
def failed_but_allowed?
@@ -256,15 +268,7 @@ class CommitStatus < ApplicationRecord
end
def all_met_to_become_pending?
- !any_unmet_prerequisites? && !requires_resource?
- end
-
- def any_unmet_prerequisites?
- false
- end
-
- def requires_resource?
- false
+ true
end
def auto_canceled?
diff --git a/app/models/concerns/analytics/cycle_analytics/stage.rb b/app/models/concerns/analytics/cycle_analytics/stage.rb
index f1c39dda49d..080ff07ec0c 100644
--- a/app/models/concerns/analytics/cycle_analytics/stage.rb
+++ b/app/models/concerns/analytics/cycle_analytics/stage.rb
@@ -49,6 +49,14 @@ module Analytics
end
end
+ def start_event_identifier
+ backward_compatible_identifier(:start_event_identifier) || super
+ end
+
+ def end_event_identifier
+ backward_compatible_identifier(:end_event_identifier) || super
+ end
+
def start_event_label_based?
start_event_identifier && start_event.label_based?
end
@@ -128,6 +136,17 @@ module Analytics
.id_in(label_id)
.exists?
end
+
+ # Temporary, will be removed in 13.10
+ def backward_compatible_identifier(attribute_name)
+ removed_identifier = 6 # References IssueFirstMentionedInCommit removed on https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51975
+ replacement_identifier = :issue_first_mentioned_in_commit
+
+ # ActiveRecord returns nil if the column value is not part of the Enum definition
+ if self[attribute_name].nil? && read_attribute_before_type_cast(attribute_name) == removed_identifier
+ replacement_identifier
+ end
+ end
end
end
end
diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb
index baa99fa5a7f..bbf9ecbcfe9 100644
--- a/app/models/concerns/atomic_internal_id.rb
+++ b/app/models/concerns/atomic_internal_id.rb
@@ -26,20 +26,31 @@
module AtomicInternalId
extend ActiveSupport::Concern
+ MissingValueError = Class.new(StandardError)
+
class_methods do
def has_internal_id( # rubocop:disable Naming/PredicateName
- column, scope:, init: :not_given, ensure_if: nil, track_if: nil,
- presence: true, backfill: false, hook_names: :create)
+ column, scope:, init: :not_given, ensure_if: nil, track_if: nil, presence: true, hook_names: :create)
raise "has_internal_id init must not be nil if given." if init.nil?
raise "has_internal_id needs to be defined on association." unless self.reflect_on_association(scope)
init = infer_init(scope) if init == :not_given
- before_validation :"track_#{scope}_#{column}!", on: hook_names, if: track_if
- before_validation :"ensure_#{scope}_#{column}!", on: hook_names, if: ensure_if
- validates column, presence: presence
+ callback_names = Array.wrap(hook_names).map { |hook_name| :"before_#{hook_name}" }
+ callback_names.each do |callback_name|
+ # rubocop:disable GitlabSecurity/PublicSend
+ public_send(callback_name, :"track_#{scope}_#{column}!", if: track_if)
+ public_send(callback_name, :"ensure_#{scope}_#{column}!", if: ensure_if)
+ # rubocop:enable GitlabSecurity/PublicSend
+ end
+ after_rollback :"clear_#{scope}_#{column}!", on: hook_names, if: ensure_if
+
+ if presence
+ before_create :"validate_#{column}_exists!"
+ before_update :"validate_#{column}_exists!"
+ end
define_singleton_internal_id_methods(scope, column, init)
- define_instance_internal_id_methods(scope, column, init, backfill)
+ define_instance_internal_id_methods(scope, column, init)
end
private
@@ -62,10 +73,8 @@ module AtomicInternalId
# - track_{scope}_{column}!
# - reset_{scope}_{column}
# - {column}=
- def define_instance_internal_id_methods(scope, column, init, backfill)
+ def define_instance_internal_id_methods(scope, column, init)
define_method("ensure_#{scope}_#{column}!") do
- return if backfill && self.class.where(column => nil).exists?
-
scope_value = internal_id_read_scope(scope)
value = read_attribute(column)
return value unless scope_value
@@ -79,6 +88,8 @@ module AtomicInternalId
internal_id_scope_usage,
init)
write_attribute(column, value)
+
+ @internal_id_set_manually = false
end
value
@@ -110,6 +121,7 @@ module AtomicInternalId
super(value).tap do |v|
# Indicate the iid was set from externally
@internal_id_needs_tracking = true
+ @internal_id_set_manually = true
end
end
@@ -128,6 +140,20 @@ module AtomicInternalId
read_attribute(column)
end
+
+ define_method("clear_#{scope}_#{column}!") do
+ return if @internal_id_set_manually
+
+ return unless public_send(:"#{column}_previously_changed?") # rubocop:disable GitlabSecurity/PublicSend
+
+ write_attribute(column, nil)
+ end
+
+ define_method("validate_#{column}_exists!") do
+ value = read_attribute(column)
+
+ raise MissingValueError, "#{column} was unexpectedly blank!" if value.blank?
+ end
end
# Defines class methods:
diff --git a/app/models/concerns/cacheable_attributes.rb b/app/models/concerns/cacheable_attributes.rb
index de176ffde5c..ee56322cce7 100644
--- a/app/models/concerns/cacheable_attributes.rb
+++ b/app/models/concerns/cacheable_attributes.rb
@@ -83,6 +83,6 @@ module CacheableAttributes
end
def cache!
- self.class.cache_backend.write(self.class.cache_key, self, expires_in: 1.minute)
+ self.class.cache_backend.write(self.class.cache_key, self, expires_in: Gitlab.config.gitlab['application_settings_cache_seconds'] || 60)
end
end
diff --git a/app/models/concerns/can_move_repository_storage.rb b/app/models/concerns/can_move_repository_storage.rb
index 52c3a4106e3..1132e4e79ac 100644
--- a/app/models/concerns/can_move_repository_storage.rb
+++ b/app/models/concerns/can_move_repository_storage.rb
@@ -16,10 +16,10 @@ module CanMoveRepositoryStorage
!skip_git_transfer_check && git_transfer_in_progress?
raise RepositoryReadOnlyError, _('Repository already read-only') if
- self.class.where(id: id).pick(:repository_read_only)
+ _safe_read_repository_read_only_column
raise ActiveRecord::RecordNotSaved, _('Database update failed') unless
- update_column(:repository_read_only, true)
+ _update_repository_read_only_column(true)
nil
end
@@ -30,7 +30,7 @@ module CanMoveRepositoryStorage
def set_repository_writable!
with_lock do
raise ActiveRecord::RecordNotSaved, _('Database update failed') unless
- update_column(:repository_read_only, false)
+ _update_repository_read_only_column(false)
nil
end
@@ -43,4 +43,19 @@ module CanMoveRepositoryStorage
def reference_counter(type:)
Gitlab::ReferenceCounter.new(type.identifier_for_container(self))
end
+
+ private
+
+ # Not all resources that can move repositories have the `repository_read_only`
+ # in their table, for example groups. We need these methods to override the
+ # behavior in those classes in order to access the column.
+ def _safe_read_repository_read_only_column
+ # This was added originally this way because of
+ # https://gitlab.com/gitlab-org/gitlab/-/commit/43f9b98302d3985312c9f8b66018e2835d8293d2
+ self.class.where(id: id).pick(:repository_read_only)
+ end
+
+ def _update_repository_read_only_column(value)
+ update_column(:repository_read_only, value)
+ end
end
diff --git a/app/models/concerns/enums/ci/pipeline.rb b/app/models/concerns/enums/ci/pipeline.rb
index e1f07fa162c..f8314d8b429 100644
--- a/app/models/concerns/enums/ci/pipeline.rb
+++ b/app/models/concerns/enums/ci/pipeline.rb
@@ -10,6 +10,9 @@ module Enums
unknown_failure: 0,
config_error: 1,
external_validation_failure: 2,
+ activity_limit_exceeded: 20,
+ size_limit_exceeded: 21,
+ job_activity_limit_exceeded: 22,
deployments_limit_exceeded: 23
}
end
@@ -71,11 +74,10 @@ module Enums
remote_source: 4,
external_project_source: 5,
bridge_source: 6,
- parameter_source: 7
+ parameter_source: 7,
+ compliance_source: 8
}
end
end
end
end
-
-Enums::Ci::Pipeline.prepend_if_ee('EE::Enums::Ci::Pipeline')
diff --git a/app/models/concerns/featurable.rb b/app/models/concerns/featurable.rb
index 20b72957ec2..ed9bce87da1 100644
--- a/app/models/concerns/featurable.rb
+++ b/app/models/concerns/featurable.rb
@@ -88,9 +88,6 @@ module Featurable
end
def feature_available?(feature, user)
- # This feature might not be behind a feature flag at all, so default to true
- return false unless ::Feature.enabled?(feature, user, default_enabled: true)
-
get_permission(user, feature)
end
diff --git a/app/models/concerns/has_repository.rb b/app/models/concerns/has_repository.rb
index 9692941d8b2..b9ad78c14fd 100644
--- a/app/models/concerns/has_repository.rb
+++ b/app/models/concerns/has_repository.rb
@@ -15,15 +15,6 @@ module HasRepository
delegate :base_dir, :disk_path, to: :storage
- class_methods do
- def pick_repository_storage
- # We need to ensure application settings are fresh when we pick
- # a repository storage to use.
- Gitlab::CurrentSettings.expire_current_application_settings
- Gitlab::CurrentSettings.pick_repository_storage
- end
- end
-
def valid_repo?
repository.exists?
rescue
diff --git a/app/models/concerns/nullify_if_blank.rb b/app/models/concerns/nullify_if_blank.rb
new file mode 100644
index 00000000000..5a5cc51509b
--- /dev/null
+++ b/app/models/concerns/nullify_if_blank.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+# Helper that sets attributes to nil prior to validation if they
+# are blank (are false, empty or contain only whitespace), to avoid
+# unnecessarily persisting empty strings.
+#
+# Model usage:
+#
+# class User < ApplicationRecord
+# include NullifyIfBlank
+#
+# nullify_if_blank :name, :email
+# end
+#
+#
+# Test usage:
+#
+# RSpec.describe User do
+# it { is_expected.to nullify_if_blank(:name) }
+# it { is_expected.to nullify_if_blank(:email) }
+# end
+#
+module NullifyIfBlank
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def nullify_if_blank(*attributes)
+ self.attributes_to_nullify += attributes
+ end
+ end
+
+ included do
+ class_attribute :attributes_to_nullify,
+ instance_accessor: false,
+ instance_predicate: false,
+ default: Set.new
+
+ before_validation :nullify_blank_attributes
+ end
+
+ private
+
+ def nullify_blank_attributes
+ self.class.attributes_to_nullify.each do |attribute|
+ assign_attributes(attribute => nil) if read_attribute(attribute).blank?
+ end
+ end
+end
diff --git a/app/models/concerns/optimized_issuable_label_filter.rb b/app/models/concerns/optimized_issuable_label_filter.rb
index 82055822cfb..c7af841e450 100644
--- a/app/models/concerns/optimized_issuable_label_filter.rb
+++ b/app/models/concerns/optimized_issuable_label_filter.rb
@@ -13,7 +13,7 @@ module OptimizedIssuableLabelFilter
def by_label(items)
return items unless params.labels?
- return super if Feature.disabled?(:optimized_issuable_label_filter)
+ return super if Feature.disabled?(:optimized_issuable_label_filter, default_enabled: :yaml)
target_model = items.model
@@ -29,7 +29,7 @@ module OptimizedIssuableLabelFilter
# Taken from IssuableFinder
def count_by_state
return super if root_namespace.nil?
- return super if Feature.disabled?(:optimized_issuable_label_filter)
+ return super if Feature.disabled?(:optimized_issuable_label_filter, default_enabled: :yaml)
count_params = params.merge(state: nil, sort: nil, force_cte: true)
finder = self.class.new(current_user, count_params)
diff --git a/app/models/concerns/packages/debian/architecture.rb b/app/models/concerns/packages/debian/architecture.rb
index 4aa633e0357..760ebb49980 100644
--- a/app/models/concerns/packages/debian/architecture.rb
+++ b/app/models/concerns/packages/debian/architecture.rb
@@ -7,6 +7,12 @@ module Packages
included do
belongs_to :distribution, class_name: "Packages::Debian::#{container_type.capitalize}Distribution", inverse_of: :architectures
+ # files must be destroyed by ruby code in order to properly remove carrierwave uploads
+ has_many :files,
+ class_name: "Packages::Debian::#{container_type.capitalize}ComponentFile",
+ foreign_key: :architecture_id,
+ inverse_of: :architecture,
+ dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
validates :distribution,
presence: true
diff --git a/app/models/concerns/packages/debian/component.rb b/app/models/concerns/packages/debian/component.rb
new file mode 100644
index 00000000000..7b342c7b684
--- /dev/null
+++ b/app/models/concerns/packages/debian/component.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ module Component
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :distribution, class_name: "Packages::Debian::#{container_type.capitalize}Distribution", inverse_of: :components
+ # files must be destroyed by ruby code in order to properly remove carrierwave uploads
+ has_many :files,
+ class_name: "Packages::Debian::#{container_type.capitalize}ComponentFile",
+ foreign_key: :component_id,
+ inverse_of: :component,
+ dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+
+ validates :distribution,
+ presence: true
+
+ validates :name,
+ presence: true,
+ length: { maximum: 255 },
+ uniqueness: { scope: %i[distribution_id] },
+ format: { with: Gitlab::Regex.debian_component_regex }
+
+ scope :with_distribution, ->(distribution) { where(distribution: distribution) }
+ scope :with_name, ->(name) { where(name: name) }
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/packages/debian/component_file.rb b/app/models/concerns/packages/debian/component_file.rb
new file mode 100644
index 00000000000..3cc2c291e96
--- /dev/null
+++ b/app/models/concerns/packages/debian/component_file.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ module ComponentFile
+ extend ActiveSupport::Concern
+
+ included do
+ include Sortable
+ include FileStoreMounter
+
+ def self.container_foreign_key
+ "#{container_type}_id".to_sym
+ end
+
+ def self.distribution_class
+ "::Packages::Debian::#{container_type.capitalize}Distribution".constantize
+ end
+
+ belongs_to :component, class_name: "Packages::Debian::#{container_type.capitalize}Component", inverse_of: :files
+ belongs_to :architecture, class_name: "Packages::Debian::#{container_type.capitalize}Architecture", inverse_of: :files, optional: true
+
+ enum file_type: { packages: 1, source: 2, di_packages: 3 }
+ enum compression_type: { gz: 1, bz2: 2, xz: 3 }
+
+ validates :component, presence: true
+ validates :file_type, presence: true
+ validates :architecture, presence: true, unless: :source?
+ validates :architecture, absence: true, if: :source?
+ validates :file, length: { minimum: 0, allow_nil: false }
+ validates :size, presence: true
+ validates :file_store, presence: true
+ validates :file_md5, presence: true
+ validates :file_sha256, presence: true
+
+ scope :with_container, ->(container) do
+ joins(component: :distribution)
+ .where("packages_debian_#{container_type}_distributions" => { container_foreign_key => container.id })
+ end
+
+ scope :with_codename_or_suite, ->(codename_or_suite) do
+ joins(component: :distribution)
+ .merge(distribution_class.with_codename_or_suite(codename_or_suite))
+ end
+
+ scope :with_component_name, ->(component_name) do
+ joins(:component)
+ .where("packages_debian_#{container_type}_components" => { name: component_name })
+ end
+
+ scope :with_file_type, ->(file_type) { where(file_type: file_type) }
+
+ scope :with_architecture_name, ->(architecture_name) do
+ left_outer_joins(:architecture)
+ .where("packages_debian_#{container_type}_architectures" => { name: architecture_name })
+ end
+
+ scope :with_compression_type, ->(compression_type) { where(compression_type: compression_type) }
+ scope :with_file_sha256, ->(file_sha256) { where(file_sha256: file_sha256) }
+
+ scope :preload_distribution, -> { includes(component: :distribution) }
+
+ mount_file_store_uploader Packages::Debian::ComponentFileUploader
+
+ before_validation :update_size_from_file
+
+ def file_name
+ case file_type
+ when 'di_packages'
+ 'Packages'
+ else
+ file_type.capitalize
+ end
+ end
+
+ def relative_path
+ case file_type
+ when 'packages'
+ "#{component.name}/binary-#{architecture.name}/#{file_name}#{extension}"
+ when 'source'
+ "#{component.name}/source/#{file_name}#{extension}"
+ when 'di_packages'
+ "#{component.name}/debian-installer/binary-#{architecture.name}/#{file_name}#{extension}"
+ end
+ end
+
+ private
+
+ def extension
+ return '' unless compression_type
+
+ ".#{compression_type}"
+ end
+
+ def update_size_from_file
+ self.size ||= file.size
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/packages/debian/distribution.rb b/app/models/concerns/packages/debian/distribution.rb
index 285d293c9ee..08fb9ccf3ea 100644
--- a/app/models/concerns/packages/debian/distribution.rb
+++ b/app/models/concerns/packages/debian/distribution.rb
@@ -18,6 +18,16 @@ module Packages
belongs_to container_type
belongs_to :creator, class_name: 'User'
+ # component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
+ has_many :components,
+ class_name: "Packages::Debian::#{container_type.capitalize}Component",
+ foreign_key: :distribution_id,
+ inverse_of: :distribution,
+ dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :component_files,
+ through: :components,
+ source: :files,
+ class_name: "Packages::Debian::#{container_type.capitalize}ComponentFile"
has_many :architectures,
class_name: "Packages::Debian::#{container_type.capitalize}Architecture",
foreign_key: :distribution_id,
diff --git a/app/models/concerns/protected_ref.rb b/app/models/concerns/protected_ref.rb
index 65195a8d5aa..cf23a27244c 100644
--- a/app/models/concerns/protected_ref.rb
+++ b/app/models/concerns/protected_ref.rb
@@ -40,20 +40,26 @@ module ProtectedRef
end
def protected_ref_accessible_to?(ref, user, project:, action:, protected_refs: nil)
- access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
+ all_matching_rules_allow?(ref, action: action, protected_refs: protected_refs) do |access_level|
access_level.check_access(user)
end
end
def developers_can?(action, ref, protected_refs: nil)
- access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
+ all_matching_rules_allow?(ref, action: action, protected_refs: protected_refs) do |access_level|
access_level.access_level == Gitlab::Access::DEVELOPER
end
end
- def access_levels_for_ref(ref, action:, protected_refs: nil)
- self.matching(ref, protected_refs: protected_refs)
- .flat_map(&:"#{action}_access_levels")
+ def all_matching_rules_allow?(ref, action:, protected_refs: nil, &block)
+ access_levels_groups =
+ self.matching(ref, protected_refs: protected_refs).map(&:"#{action}_access_levels")
+
+ return false if access_levels_groups.blank?
+
+ access_levels_groups.all? do |access_levels|
+ access_levels.any?(&block)
+ end
end
# Returns all protected refs that match the given ref name.
diff --git a/app/models/concerns/repositories/can_housekeep_repository.rb b/app/models/concerns/repositories/can_housekeep_repository.rb
index 2b79851a07c..946f82c5f36 100644
--- a/app/models/concerns/repositories/can_housekeep_repository.rb
+++ b/app/models/concerns/repositories/can_housekeep_repository.rb
@@ -16,6 +16,10 @@ module Repositories
Gitlab::Redis::SharedState.with { |redis| redis.del(pushes_since_gc_redis_shared_state_key) }
end
+ def git_garbage_collect_worker_klass
+ raise NotImplementedError
+ end
+
private
def pushes_since_gc_redis_shared_state_key
diff --git a/app/models/concerns/repository_storage_movable.rb b/app/models/concerns/repository_storage_movable.rb
index a45b4626628..8607f0d94f4 100644
--- a/app/models/concerns/repository_storage_movable.rb
+++ b/app/models/concerns/repository_storage_movable.rb
@@ -20,7 +20,7 @@ module RepositoryStorageMovable
validate :container_repository_writable, on: :create
default_value_for(:destination_storage_name, allows_nil: false) do
- pick_repository_storage
+ Repository.pick_storage_shard
end
state_machine initial: :initial do
@@ -68,6 +68,18 @@ module RepositoryStorageMovable
storage_move.update_repository_storage(storage_move.destination_storage_name)
end
+ after_transition started: :replicated do |storage_move|
+ # We have several scripts in place that replicate some statistics information
+ # to other databases. Some of them depend on the updated_at column
+ # to identify the models they need to extract.
+ #
+ # If we don't update the `updated_at` of the container after a repository storage move,
+ # the scripts won't know that they need to sync them.
+ #
+ # See https://gitlab.com/gitlab-data/analytics/-/issues/7868
+ storage_move.container.touch
+ end
+
before_transition started: :failed do |storage_move|
storage_move.container.set_repository_writable!
end
@@ -82,16 +94,6 @@ module RepositoryStorageMovable
end
end
- class_methods do
- private
-
- def pick_repository_storage
- container_klass = reflect_on_association(:container).class_name.constantize
-
- container_klass.pick_repository_storage
- end
- end
-
# Projects, snippets, and group wikis has different db structure. In projects,
# we need to update some columns in this step, but we don't with the other resources.
#
diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb
index 9cd1a22b203..2daea388939 100644
--- a/app/models/concerns/spammable.rb
+++ b/app/models/concerns/spammable.rb
@@ -45,6 +45,17 @@ module Spammable
self.needs_recaptcha = true
end
+ ##
+ # Indicates if a recaptcha should be rendered before allowing this model to be saved.
+ #
+ def render_recaptcha?
+ return false unless Gitlab::Recaptcha.enabled?
+
+ return false if self.errors.count > 1 # captcha should not be rendered if are still other errors
+
+ self.needs_recaptcha?
+ end
+
def spam!
self.spam = true
end
diff --git a/app/models/concerns/suppress_composite_primary_key_warning.rb b/app/models/concerns/suppress_composite_primary_key_warning.rb
new file mode 100644
index 00000000000..32634e7bc72
--- /dev/null
+++ b/app/models/concerns/suppress_composite_primary_key_warning.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# When extended, silences this warning below:
+# WARNING: Active Record does not support composite primary key.
+#
+# project_authorizations has composite primary key. Composite primary key is ignored.
+#
+# See https://gitlab.com/gitlab-org/gitlab/-/issues/292909
+module SuppressCompositePrimaryKeyWarning
+ extend ActiveSupport::Concern
+
+ private
+
+ def suppress_composite_primary_key(pk)
+ silence_warnings do
+ super
+ end
+ end
+end
diff --git a/app/models/concerns/token_authenticatable_strategies/encrypted.rb b/app/models/concerns/token_authenticatable_strategies/encrypted.rb
index 4728cb658dc..672402ee4d6 100644
--- a/app/models/concerns/token_authenticatable_strategies/encrypted.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encrypted.rb
@@ -85,10 +85,18 @@ module TokenAuthenticatableStrategies
end
def find_by_encrypted_token(token, unscoped)
- encrypted_value = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
+ nonce = Feature.enabled?(:dynamic_nonce_creation) ? find_hashed_iv(token) : Gitlab::CryptoHelper::AES256_GCM_IV_STATIC
+ encrypted_value = Gitlab::CryptoHelper.aes256_gcm_encrypt(token, nonce: nonce)
+
relation(unscoped).find_by(encrypted_field => encrypted_value)
end
+ def find_hashed_iv(token)
+ token_record = TokenWithIv.find_by_plaintext_token(token)
+
+ token_record&.iv || Gitlab::CryptoHelper::AES256_GCM_IV_STATIC
+ end
+
def insecure_strategy
@insecure_strategy ||= TokenAuthenticatableStrategies::Insecure
.new(klass, token_field, options)
diff --git a/app/models/concerns/triggerable_hooks.rb b/app/models/concerns/triggerable_hooks.rb
index 473b430bb04..db5df6c2c9f 100644
--- a/app/models/concerns/triggerable_hooks.rb
+++ b/app/models/concerns/triggerable_hooks.rb
@@ -16,7 +16,8 @@ module TriggerableHooks
deployment_hooks: :deployment_events,
feature_flag_hooks: :feature_flag_events,
release_hooks: :releases_events,
- member_hooks: :member_events
+ member_hooks: :member_events,
+ subgroup_hooks: :subgroup_events
}.freeze
extend ActiveSupport::Concern
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index 0d7ce966537..e2bdf8ffce2 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -4,6 +4,7 @@ class ContainerRepository < ApplicationRecord
include Gitlab::Utils::StrongMemoize
include Gitlab::SQL::Pattern
include EachBatch
+ include Sortable
WAITING_CLEANUP_STATUSES = %i[cleanup_scheduled cleanup_unfinished].freeze
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 4f8f86965d7..f4c914c6a3a 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class CustomEmoji < ApplicationRecord
+ NAME_REGEXP = /[a-z0-9_-]+/.freeze
+
belongs_to :namespace, inverse_of: :custom_emoji
belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
@@ -17,7 +19,12 @@ class CustomEmoji < ApplicationRecord
uniqueness: { scope: [:namespace_id, :name] },
presence: true,
length: { maximum: 36 },
- format: { with: /\A[a-z0-9][a-z0-9\-_]*[a-z0-9]\z/ }
+
+ format: { with: /\A#{NAME_REGEXP}\z/ }
+
+ scope :by_name, -> (names) { where(name: names) }
+
+ alias_attribute :url, :file # this might need a change in https://gitlab.com/gitlab-org/gitlab/-/issues/230467
private
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 6f40466394a..f000e474605 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -38,6 +38,7 @@ class Deployment < ApplicationRecord
scope :for_status, -> (status) { where(status: status) }
scope :for_project, -> (project_id) { where(project_id: project_id) }
+ scope :for_projects, -> (projects) { where(project: projects) }
scope :visible, -> { where(status: %i[running success failed canceled]) }
scope :stoppable, -> { where.not(on_stop: nil).where.not(deployable_id: nil).success }
@@ -45,11 +46,8 @@ class Deployment < ApplicationRecord
scope :older_than, -> (deployment) { where('deployments.id < ?', deployment.id) }
scope :with_deployable, -> { joins('INNER JOIN ci_builds ON ci_builds.id = deployments.deployable_id').preload(:deployable) }
- scope :finished_between, -> (start_date, end_date = nil) do
- selected = where('deployments.finished_at >= ?', start_date)
- selected = selected.where('deployments.finished_at < ?', end_date) if end_date
- selected
- end
+ scope :finished_after, ->(date) { where('finished_at >= ?', date) }
+ scope :finished_before, ->(date) { where('finished_at < ?', date) }
FINISHED_STATUSES = %i[success failed canceled].freeze
@@ -112,7 +110,6 @@ class Deployment < ApplicationRecord
after_transition any => any - [:skipped] do |deployment, transition|
next if transition.loopback?
- next unless Feature.enabled?(:jira_sync_deployments, deployment.project)
deployment.run_after_commit do
::JiraConnect::SyncDeploymentsWorker.perform_async(id)
@@ -121,8 +118,6 @@ class Deployment < ApplicationRecord
end
after_create unless: :importing? do |deployment|
- next unless Feature.enabled?(:jira_sync_deployments, deployment.project)
-
run_after_commit do
::JiraConnect::SyncDeploymentsWorker.perform_async(deployment.id)
end
@@ -353,6 +348,13 @@ class Deployment < ApplicationRecord
File.join(environment.ref_path, 'deployments', iid.to_s)
end
+ def equal_to?(params)
+ ref == params[:ref] &&
+ tag == params[:tag] &&
+ sha == params[:sha] &&
+ status == params[:status]
+ end
+
private
def legacy_finished_at
diff --git a/app/models/deployment_merge_request.rb b/app/models/deployment_merge_request.rb
index 64a578e16bf..7949bd81605 100644
--- a/app/models/deployment_merge_request.rb
+++ b/app/models/deployment_merge_request.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class DeploymentMergeRequest < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
belongs_to :deployment, optional: false
belongs_to :merge_request, optional: false
diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb
index f5e52c04944..e2d10cc7e78 100644
--- a/app/models/design_management/design.rb
+++ b/app/models/design_management/design.rb
@@ -228,17 +228,6 @@ module DesignManagement
project
end
- def immediately_before?(next_design)
- return false if next_design.relative_position <= relative_position
-
- interloper = self.class.on_issue(issue).where(
- "relative_position <@ int4range(?, ?, '()')",
- *[self, next_design].map(&:relative_position)
- )
-
- !interloper.exists?
- end
-
def notes_with_associations
notes.includes(:author)
end
diff --git a/app/models/event.rb b/app/models/event.rb
index 671def16151..401dfc4cb02 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -294,10 +294,14 @@ class Event < ApplicationRecord
note? && target && target.for_merge_request?
end
- def project_snippet_note?
+ def snippet_note?
note? && target && target.for_snippet?
end
+ def project_snippet_note?
+ note? && target && target.for_project_snippet?
+ end
+
def personal_snippet_note?
note? && target && target.for_personal_snippet?
end
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index 7dbc95f617a..354b1e0b6b9 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -10,6 +10,10 @@ class Experiment < ApplicationRecord
find_or_create_by!(name: name).record_user_and_group(user, group_type, context)
end
+ def self.add_group(name, variant:, group:)
+ find_or_create_by!(name: name).record_group_and_variant!(group, variant)
+ end
+
def self.record_conversion_event(name, user)
find_or_create_by!(name: name).record_conversion_event_for_user(user)
end
@@ -24,4 +28,8 @@ class Experiment < ApplicationRecord
def record_conversion_event_for_user(user)
experiment_users.find_by(user: user, converted_at: nil)&.touch(:converted_at)
end
+
+ def record_group_and_variant!(group, variant)
+ experiment_subjects.find_or_initialize_by(group: group).update!(variant: variant)
+ end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 903d0154969..1eaa4499eb5 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -48,6 +48,7 @@ class Group < Namespace
has_many :labels, class_name: 'GroupLabel'
has_many :variables, class_name: 'Ci::GroupVariable'
+ has_many :daily_build_group_report_results, class_name: 'Ci::DailyBuildGroupReportResult'
has_many :custom_attributes, class_name: 'GroupCustomAttribute'
has_many :boards
@@ -75,7 +76,7 @@ class Group < Namespace
has_many :dependency_proxy_blobs, class_name: 'DependencyProxy::Blob'
has_many :dependency_proxy_manifests, class_name: 'DependencyProxy::Manifest'
- # debian_distributions must be destroyed by ruby code in order to properly remove carrierwave uploads
+ # debian_distributions and associated component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
has_many :debian_distributions, class_name: 'Packages::Debian::GroupDistribution', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
accepts_nested_attributes_for :variables, allow_destroy: true
@@ -84,7 +85,7 @@ class Group < Namespace
validate :visibility_level_allowed_by_sub_groups
validate :visibility_level_allowed_by_parent
validate :two_factor_authentication_allowed
- validates :variables, variable_duplicates: true
+ validates :variables, nested_attributes_duplicates: true
validates :two_factor_grace_period, presence: true, numericality: { greater_than_or_equal_to: 0 }
@@ -169,6 +170,15 @@ class Group < Namespace
where('NOT EXISTS (?)', services)
end
+ # This method can be used only if all groups have the same top-level
+ # group
+ def preset_root_ancestor_for(groups)
+ return groups if groups.size < 2
+
+ root = groups.first.root_ancestor
+ groups.drop(1).each { |group| group.root_ancestor = root }
+ end
+
private
def public_to_user_arel(user)
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 5da9f67f6ef..79d0229a281 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -132,7 +132,7 @@ class Issue < ApplicationRecord
scope :counts_by_state, -> { reorder(nil).group(:state_id).count }
scope :service_desk, -> { where(author: ::User.support_bot) }
- scope :inc_relations_for_view, -> { includes(author: :status) }
+ scope :inc_relations_for_view, -> { includes(author: :status, assignees: :status) }
# An issue can be uniquely identified by project_id and iid
# Takes one or more sets of composite IDs, expressed as hash-like records of
diff --git a/app/models/issue_assignee.rb b/app/models/issue_assignee.rb
index 7f3d552b3d9..d62f0eb170c 100644
--- a/app/models/issue_assignee.rb
+++ b/app/models/issue_assignee.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class IssueAssignee < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
belongs_to :issue
belongs_to :assignee, class_name: "User", foreign_key: :user_id, inverse_of: :issue_assignees
diff --git a/app/models/issue_link.rb b/app/models/issue_link.rb
index 5448ebdf50b..ba97874ed39 100644
--- a/app/models/issue_link.rb
+++ b/app/models/issue_link.rb
@@ -17,9 +17,11 @@ class IssueLink < ApplicationRecord
TYPE_RELATES_TO = 'relates_to'
TYPE_BLOCKS = 'blocks'
+ # we don't store is_blocked_by in the db but need it for displaying the relation
+ # from the target (used in IssueLink.inverse_link_type)
TYPE_IS_BLOCKED_BY = 'is_blocked_by'
- enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1, TYPE_IS_BLOCKED_BY => 2 }
+ enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1 }
def self.inverse_link_type(type)
type
diff --git a/app/models/label.rb b/app/models/label.rb
index 54129c7c7f3..7a31b095cfc 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -12,7 +12,7 @@ class Label < ApplicationRecord
cache_markdown_field :description, pipeline: :single_line
- DEFAULT_COLOR = '#428BCA'
+ DEFAULT_COLOR = '#6699cc'
default_value_for :color, DEFAULT_COLOR
diff --git a/app/models/license_template.rb b/app/models/license_template.rb
index bd24259984b..548066107c1 100644
--- a/app/models/license_template.rb
+++ b/app/models/license_template.rb
@@ -12,11 +12,12 @@ class LicenseTemplate
(fullname|name\sof\s(author|copyright\sowner))
[\>\}\]]}xi.freeze
- attr_reader :key, :name, :category, :nickname, :url, :meta
+ attr_reader :key, :name, :project, :category, :nickname, :url, :meta
- def initialize(key:, name:, category:, content:, nickname: nil, url: nil, meta: {})
+ def initialize(key:, name:, project:, category:, content:, nickname: nil, url: nil, meta: {})
@key = key
@name = name
+ @project = project
@category = category
@content = content
@nickname = nickname
@@ -24,6 +25,10 @@ class LicenseTemplate
@meta = meta
end
+ def project_id
+ project&.id
+ end
+
def popular?
category == :Popular
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 64b8223a1f0..1374e8a814a 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -50,12 +50,15 @@ class MergeRequest < ApplicationRecord
end
end
- has_many :merge_request_diffs
+ has_many :merge_request_diffs,
+ -> { regular }, inverse_of: :merge_request
has_many :merge_request_context_commits, inverse_of: :merge_request
has_many :merge_request_context_commit_diff_files, through: :merge_request_context_commits, source: :diff_files
has_one :merge_request_diff,
- -> { order('merge_request_diffs.id DESC') }, inverse_of: :merge_request
+ -> { regular.order('merge_request_diffs.id DESC') }, inverse_of: :merge_request
+ has_one :merge_head_diff,
+ -> { merge_head }, inverse_of: :merge_request, class_name: 'MergeRequestDiff'
has_one :cleanup_schedule, inverse_of: :merge_request
belongs_to :latest_merge_request_diff, class_name: 'MergeRequestDiff'
@@ -270,8 +273,7 @@ class MergeRequest < ApplicationRecord
by_commit_sha(sha),
by_squash_commit_sha(sha),
by_merge_commit_sha(sha)
- ],
- remove_duplicates: false
+ ]
)
end
scope :by_cherry_pick_sha, -> (sha) do
@@ -477,13 +479,17 @@ class MergeRequest < ApplicationRecord
# This is used after project import, to reset the IDs to the correct
# values. It is not intended to be called without having already scoped the
# relation.
+ #
+ # Only set `regular` merge request diffs as latest so `merge_head` diff
+ # won't be considered as `MergeRequest#merge_request_diff`.
def self.set_latest_merge_request_diff_ids!
- update = '
+ update = "
latest_merge_request_diff_id = (
SELECT MAX(id)
FROM merge_request_diffs
WHERE merge_requests.id = merge_request_diffs.merge_request_id
- )'.squish
+ AND merge_request_diffs.diff_type = #{MergeRequestDiff.diff_types[:regular]}
+ )".squish
self.each_batch do |batch|
batch.update_all(update)
@@ -915,6 +921,10 @@ class MergeRequest < ApplicationRecord
closed? && !source_project_missing? && source_branch_exists?
end
+ def can_be_closed?
+ opened?
+ end
+
def ensure_merge_request_diff
merge_request_diff.persisted? || create_merge_request_diff
end
@@ -922,7 +932,7 @@ class MergeRequest < ApplicationRecord
def create_merge_request_diff
fetch_ref!
- # n+1: https://gitlab.com/gitlab-org/gitlab-foss/issues/37435
+ # n+1: https://gitlab.com/gitlab-org/gitlab/-/issues/19377
Gitlab::GitalyClient.allow_n_plus_1_calls do
merge_request_diffs.create!
reload_merge_request_diff
@@ -996,7 +1006,7 @@ class MergeRequest < ApplicationRecord
# rubocop: enable CodeReuse/ServiceClass
def diffable_merge_ref?
- open? && merge_ref_head.present? && (Feature.enabled?(:display_merge_conflicts_in_diff, project) || can_be_merged?)
+ open? && merge_head_diff.present? && (Feature.enabled?(:display_merge_conflicts_in_diff, project) || can_be_merged?)
end
# Returns boolean indicating the merge_status should be rechecked in order to
@@ -1478,8 +1488,26 @@ class MergeRequest < ApplicationRecord
compare_reports(Ci::GenerateCoverageReportsService)
end
+ def has_codequality_mr_diff_report?
+ return false unless ::Gitlab::Ci::Features.display_quality_on_mr_diff?(project)
+
+ actual_head_pipeline&.has_codequality_mr_diff_report?
+ end
+
+ # TODO: this method and compare_test_reports use the same
+ # result type, which is handled by the controller's #reports_response.
+ # we should minimize mistakes by isolating the common parts.
+ # issue: https://gitlab.com/gitlab-org/gitlab/issues/34224
+ def find_codequality_mr_diff_reports
+ unless has_codequality_mr_diff_report?
+ return { status: :error, status_reason: 'This merge request does not have codequality mr diff reports' }
+ end
+
+ compare_reports(Ci::GenerateCodequalityMrDiffReportService)
+ end
+
def has_codequality_reports?
- return false unless Feature.enabled?(:codequality_mr_diff, project)
+ return false unless ::Gitlab::Ci::Features.display_codequality_backend_comparison?(project)
actual_head_pipeline&.has_reports?(Ci::JobArtifact.codequality_reports)
end
@@ -1530,6 +1558,26 @@ class MergeRequest < ApplicationRecord
end || { status: :parsing }
end
+ def has_sast_reports?
+ !!actual_head_pipeline&.has_reports?(::Ci::JobArtifact.sast_reports)
+ end
+
+ def has_secret_detection_reports?
+ !!actual_head_pipeline&.has_reports?(::Ci::JobArtifact.secret_detection_reports)
+ end
+
+ def compare_sast_reports(current_user)
+ return missing_report_error("SAST") unless has_sast_reports?
+
+ compare_reports(::Ci::CompareSecurityReportsService, current_user, 'sast')
+ end
+
+ def compare_secret_detection_reports(current_user)
+ return missing_report_error("secret detection") unless has_secret_detection_reports?
+
+ compare_reports(::Ci::CompareSecurityReportsService, current_user, 'secret_detection')
+ end
+
def calculate_reactive_cache(identifier, current_user_id = nil, report_type = nil, *args)
service_class = identifier.constantize
@@ -1760,7 +1808,7 @@ class MergeRequest < ApplicationRecord
end
def allows_reviewers?
- Feature.enabled?(:merge_request_reviewers, project, default_enabled: true)
+ true
end
def allows_multiple_reviewers?
@@ -1771,8 +1819,23 @@ class MergeRequest < ApplicationRecord
true
end
+ def find_reviewer(user)
+ merge_request_reviewers.find_by(user_id: user.id)
+ end
+
+ def enabled_reports
+ {
+ sast: report_type_enabled?(:sast),
+ secret_detection: report_type_enabled?(:secret_detection)
+ }
+ end
+
private
+ def missing_report_error(report_type)
+ { status: :error, status_reason: "This merge request does not have #{report_type} reports" }
+ end
+
def with_rebase_lock
if Feature.enabled?(:merge_request_rebase_nowait_lock, default_enabled: true)
with_retried_nowait_lock { yield }
@@ -1814,6 +1877,10 @@ class MergeRequest < ApplicationRecord
key = Gitlab::Routing.url_helpers.cached_widget_project_json_merge_request_path(project, self, format: :json)
Gitlab::EtagCaching::Store.new.touch(key)
end
+
+ def report_type_enabled?(report_type)
+ !!actual_head_pipeline&.batch_lookup_report_artifact_for_file_type(report_type)
+ end
end
MergeRequest.prepend_if_ee('::EE::MergeRequest')
diff --git a/app/models/merge_request/metrics.rb b/app/models/merge_request/metrics.rb
index d3fe256fb1b..5c611da0684 100644
--- a/app/models/merge_request/metrics.rb
+++ b/app/models/merge_request/metrics.rb
@@ -5,12 +5,14 @@ class MergeRequest::Metrics < ApplicationRecord
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :pipeline_id
belongs_to :latest_closed_by, class_name: 'User'
belongs_to :merged_by, class_name: 'User'
+ belongs_to :target_project, class_name: 'Project', inverse_of: :merge_requests
before_save :ensure_target_project_id
scope :merged_after, ->(date) { where(arel_table[:merged_at].gteq(date)) }
scope :merged_before, ->(date) { where(arel_table[:merged_at].lteq(date)) }
scope :with_valid_time_to_merge, -> { where(arel_table[:merged_at].gt(arel_table[:created_at])) }
+ scope :by_target_project, ->(project) { where(target_project_id: project) }
def self.time_to_merge_expression
Arel.sql('EXTRACT(epoch FROM SUM(AGE(merge_request_metrics.merged_at, merge_request_metrics.created_at)))')
@@ -21,6 +23,12 @@ class MergeRequest::Metrics < ApplicationRecord
def ensure_target_project_id
self.target_project_id ||= merge_request.target_project_id
end
+
+ def self.total_time_to_merge
+ with_valid_time_to_merge
+ .pluck(time_to_merge_expression)
+ .first
+ end
end
MergeRequest::Metrics.prepend_if_ee('EE::MergeRequest::Metrics')
diff --git a/app/models/merge_request_context_commit.rb b/app/models/merge_request_context_commit.rb
index 59cc82cfaf5..e081a96dc10 100644
--- a/app/models/merge_request_context_commit.rb
+++ b/app/models/merge_request_context_commit.rb
@@ -12,6 +12,9 @@ class MergeRequestContextCommit < ApplicationRecord
validates :sha, presence: true
validates :sha, uniqueness: { message: 'has already been added' }
+ serialize :trailers, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ validates :trailers, json_schema: { filename: 'git_trailers' }
+
# Sort by committed date in descending order to ensure latest commits comes on the top
scope :order_by_committed_date_desc, -> { order('committed_date DESC') }
diff --git a/app/models/merge_request_context_commit_diff_file.rb b/app/models/merge_request_context_commit_diff_file.rb
index b89d1983ce3..6f15df1b70f 100644
--- a/app/models/merge_request_context_commit_diff_file.rb
+++ b/app/models/merge_request_context_commit_diff_file.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class MergeRequestContextCommitDiffFile < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
include Gitlab::EncodingHelper
include ShaAttribute
include DiffFile
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index d23e66b9697..fb873ddbbab 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -32,6 +32,7 @@ class MergeRequestDiff < ApplicationRecord
has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) }
validates :base_commit_sha, :head_commit_sha, :start_commit_sha, sha: true
+ validates :merge_request_id, uniqueness: { scope: :diff_type }, if: :merge_head?
state_machine :state, initial: :empty do
event :clean do
@@ -50,6 +51,11 @@ class MergeRequestDiff < ApplicationRecord
state :overflow_diff_lines_limit
end
+ enum diff_type: {
+ regular: 1,
+ merge_head: 2
+ }
+
scope :with_files, -> { without_states(:without_files, :empty) }
scope :viewable, -> { without_state(:empty) }
scope :by_commit_sha, ->(sha) do
@@ -72,6 +78,7 @@ class MergeRequestDiff < ApplicationRecord
join_condition = merge_requests[:id].eq(mr_diffs[:merge_request_id])
.and(mr_diffs[:id].not_eq(merge_requests[:latest_merge_request_diff_id]))
+ .and(mr_diffs[:diff_type].eq(diff_types[:regular]))
arel_join = mr_diffs.join(merge_requests).on(join_condition)
joins(arel_join.join_sources)
@@ -196,6 +203,10 @@ class MergeRequestDiff < ApplicationRecord
end
def set_as_latest_diff
+ # Don't set merge_head diff as latest so it won't get considered as the
+ # MergeRequest#merge_request_diff.
+ return if merge_head?
+
MergeRequest
.where('id = ? AND COALESCE(latest_merge_request_diff_id, 0) < ?', self.merge_request_id, self.id)
.update_all(latest_merge_request_diff_id: self.id)
@@ -203,8 +214,16 @@ class MergeRequestDiff < ApplicationRecord
def ensure_commit_shas
self.start_commit_sha ||= merge_request.target_branch_sha
- self.head_commit_sha ||= merge_request.source_branch_sha
- self.base_commit_sha ||= find_base_sha
+
+ if merge_head? && merge_request.merge_ref_head.present?
+ diff_refs = merge_request.merge_ref_head.diff_refs
+
+ self.head_commit_sha ||= diff_refs.head_sha
+ self.base_commit_sha ||= diff_refs.base_sha
+ else
+ self.head_commit_sha ||= merge_request.source_branch_sha
+ self.base_commit_sha ||= find_base_sha
+ end
end
# Override head_commit_sha to keep compatibility with merge request diff
@@ -749,7 +768,7 @@ class MergeRequestDiff < ApplicationRecord
end
def sort_diffs?
- Feature.enabled?(:sort_diffs, project, default_enabled: false)
+ Feature.enabled?(:sort_diffs, project, default_enabled: :yaml)
end
end
diff --git a/app/models/merge_request_diff_commit.rb b/app/models/merge_request_diff_commit.rb
index 9f6933d0879..259690ef308 100644
--- a/app/models/merge_request_diff_commit.rb
+++ b/app/models/merge_request_diff_commit.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class MergeRequestDiffCommit < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
include BulkInsertSafe
include ShaAttribute
include CachedCommit
@@ -10,6 +12,9 @@ class MergeRequestDiffCommit < ApplicationRecord
sha_attribute :sha
alias_attribute :id, :sha
+ serialize :trailers, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ validates :trailers, json_schema: { filename: 'git_trailers' }
+
# Deprecated; use `bulk_insert!` from `BulkInsertSafe` mixin instead.
# cf. https://gitlab.com/gitlab-org/gitlab/issues/207989 for progress
def self.create_bulk(merge_request_diff_id, commits)
@@ -23,10 +28,30 @@ class MergeRequestDiffCommit < ApplicationRecord
relative_order: index,
sha: Gitlab::Database::ShaAttribute.serialize(sha), # rubocop:disable Cop/ActiveRecordSerialize
authored_date: Gitlab::Database.sanitize_timestamp(commit_hash[:authored_date]),
- committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date])
+ committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date]),
+ trailers: commit_hash.fetch(:trailers, {}).to_json
)
end
Gitlab::Database.bulk_insert(self.table_name, rows) # rubocop:disable Gitlab/BulkInsert
end
+
+ def self.oldest_merge_request_id_per_commit(project_id, shas)
+ # This method is defined here and not on MergeRequest, otherwise the SHA
+ # values used in the WHERE below won't be encoded correctly.
+ select(['merge_request_diff_commits.sha AS sha', 'min(merge_requests.id) AS merge_request_id'])
+ .joins(:merge_request_diff)
+ .joins(
+ 'INNER JOIN merge_requests ' \
+ 'ON merge_requests.latest_merge_request_diff_id = merge_request_diffs.id'
+ )
+ .where(sha: shas)
+ .where(
+ merge_requests: {
+ target_project_id: project_id,
+ state_id: MergeRequest.available_states[:merged]
+ }
+ )
+ .group(:sha)
+ end
end
diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb
index 817e77bf12f..f3f64971426 100644
--- a/app/models/merge_request_diff_file.rb
+++ b/app/models/merge_request_diff_file.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class MergeRequestDiffFile < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
include BulkInsertSafe
include Gitlab::EncodingHelper
include DiffFile
diff --git a/app/models/merge_request_reviewer.rb b/app/models/merge_request_reviewer.rb
index c4e5274f832..4a1f31a7f39 100644
--- a/app/models/merge_request_reviewer.rb
+++ b/app/models/merge_request_reviewer.rb
@@ -1,6 +1,15 @@
# frozen_string_literal: true
class MergeRequestReviewer < ApplicationRecord
+ enum state: {
+ unreviewed: 0,
+ reviewed: 1
+ }
+
+ validates :state,
+ presence: true,
+ inclusion: { in: MergeRequestReviewer.states.keys }
+
belongs_to :merge_request
belongs_to :reviewer, class_name: 'User', foreign_key: :user_id, inverse_of: :merge_request_reviewers
end
diff --git a/app/models/milestone_release.rb b/app/models/milestone_release.rb
index 2f2bf91e436..c6b5a967af9 100644
--- a/app/models/milestone_release.rb
+++ b/app/models/milestone_release.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class MilestoneRelease < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
belongs_to :milestone
belongs_to :release
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 6f7b377ee52..3342fb1fce9 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -12,6 +12,7 @@ class Namespace < ApplicationRecord
include FromUnion
include Gitlab::Utils::StrongMemoize
include IgnorableColumns
+ include Namespaces::Traversal::Recursive
# Prevent users from creating unreasonably deep level of nesting.
# The number 20 was taken based on maximum nesting level of
@@ -103,6 +104,10 @@ class Namespace < ApplicationRecord
)
end
+ # Make sure that the name is same as strong_memoize name in root_ancestor
+ # method
+ attr_writer :root_ancestor
+
class << self
def by_path(path)
find_by('lower(path) = :value', value: path.downcase)
@@ -243,50 +248,6 @@ class Namespace < ApplicationRecord
projects.with_shared_runners.any?
end
- # Returns all ancestors, self, and descendants of the current namespace.
- def self_and_hierarchy
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .all_objects
- end
-
- # Returns all the ancestors of the current namespaces.
- def ancestors
- return self.class.none unless parent_id
-
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: parent_id))
- .base_and_ancestors
- end
-
- # returns all ancestors upto but excluding the given namespace
- # when no namespace is given, all ancestors upto the top are returned
- def ancestors_upto(top = nil, hierarchy_order: nil)
- Gitlab::ObjectHierarchy.new(self.class.where(id: id))
- .ancestors(upto: top, hierarchy_order: hierarchy_order)
- end
-
- def self_and_ancestors(hierarchy_order: nil)
- return self.class.where(id: id) unless parent_id
-
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .base_and_ancestors(hierarchy_order: hierarchy_order)
- end
-
- # Returns all the descendants of the current namespace.
- def descendants
- Gitlab::ObjectHierarchy
- .new(self.class.where(parent_id: id))
- .base_and_descendants
- end
-
- def self_and_descendants
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .base_and_descendants
- end
-
def user_ids_for_project_authorizations
[owner_id]
end
@@ -312,14 +273,6 @@ class Namespace < ApplicationRecord
parent_id.present? || parent.present?
end
- def root_ancestor
- return self if persisted? && parent_id.nil?
-
- strong_memoize(:root_ancestor) do
- self_and_ancestors.reorder(nil).find_by(parent_id: nil)
- end
- end
-
def subgroup?
has_parent?
end
diff --git a/app/models/namespaces/traversal/recursive.rb b/app/models/namespaces/traversal/recursive.rb
new file mode 100644
index 00000000000..c46cc521735
--- /dev/null
+++ b/app/models/namespaces/traversal/recursive.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Namespaces
+ module Traversal
+ module Recursive
+ extend ActiveSupport::Concern
+
+ def root_ancestor
+ return self if persisted? && parent_id.nil?
+
+ strong_memoize(:root_ancestor) do
+ self_and_ancestors.reorder(nil).find_by(parent_id: nil)
+ end
+ end
+
+ # Returns all ancestors, self, and descendants of the current namespace.
+ def self_and_hierarchy
+ Gitlab::ObjectHierarchy
+ .new(self.class.where(id: id))
+ .all_objects
+ end
+
+ # Returns all the ancestors of the current namespaces.
+ def ancestors
+ return self.class.none unless parent_id
+
+ Gitlab::ObjectHierarchy
+ .new(self.class.where(id: parent_id))
+ .base_and_ancestors
+ end
+
+ # returns all ancestors upto but excluding the given namespace
+ # when no namespace is given, all ancestors upto the top are returned
+ def ancestors_upto(top = nil, hierarchy_order: nil)
+ Gitlab::ObjectHierarchy.new(self.class.where(id: id))
+ .ancestors(upto: top, hierarchy_order: hierarchy_order)
+ end
+
+ def self_and_ancestors(hierarchy_order: nil)
+ return self.class.where(id: id) unless parent_id
+
+ Gitlab::ObjectHierarchy
+ .new(self.class.where(id: id))
+ .base_and_ancestors(hierarchy_order: hierarchy_order)
+ end
+
+ # Returns all the descendants of the current namespace.
+ def descendants
+ Gitlab::ObjectHierarchy
+ .new(self.class.where(parent_id: id))
+ .base_and_descendants
+ end
+
+ def self_and_descendants
+ Gitlab::ObjectHierarchy
+ .new(self.class.where(id: id))
+ .base_and_descendants
+ end
+ end
+ end
+end
diff --git a/app/models/note.rb b/app/models/note.rb
index 77f7726079c..fdc972d9726 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -259,6 +259,10 @@ class Note < ApplicationRecord
noteable_type == 'AlertManagement::Alert'
end
+ def for_project_snippet?
+ noteable.is_a?(ProjectSnippet)
+ end
+
def for_personal_snippet?
noteable.is_a?(PersonalSnippet)
end
@@ -542,7 +546,7 @@ class Note < ApplicationRecord
end
def skip_notification?
- review.present?
+ review.present? || author.blocked? || author.ghost?
end
private
diff --git a/app/models/onboarding_progress.rb b/app/models/onboarding_progress.rb
index 419bbd595e9..8a444f8934e 100644
--- a/app/models/onboarding_progress.rb
+++ b/app/models/onboarding_progress.rb
@@ -22,6 +22,24 @@ class OnboardingProgress < ApplicationRecord
:repository_mirrored
].freeze
+ scope :incomplete_actions, -> (actions) do
+ Array.wrap(actions).inject(self) { |scope, action| scope.where(column_name(action) => nil) }
+ end
+
+ scope :completed_actions, -> (actions) do
+ Array.wrap(actions).inject(self) { |scope, action| scope.where.not(column_name(action) => nil) }
+ end
+
+ scope :completed_actions_with_latest_in_range, -> (actions, range) do
+ actions = Array(actions)
+ if actions.size == 1
+ where(column_name(actions[0]) => range)
+ else
+ action_columns = actions.map { |action| arel_table[column_name(action)] }
+ completed_actions(actions).where(Arel::Nodes::NamedFunction.new('GREATEST', action_columns).between(range))
+ end
+ end
+
class << self
def onboard(namespace)
return unless root_namespace?(namespace)
@@ -29,6 +47,10 @@ class OnboardingProgress < ApplicationRecord
safe_find_or_create_by(namespace: namespace)
end
+ def onboarding?(namespace)
+ where(namespace: namespace).any?
+ end
+
def register(namespace, action)
return unless root_namespace?(namespace) && ACTIONS.include?(action)
@@ -44,12 +66,12 @@ class OnboardingProgress < ApplicationRecord
where(namespace: namespace).where.not(action_column => nil).exists?
end
- private
-
def column_name(action)
:"#{action}_at"
end
+ private
+
def root_namespace?(namespace)
namespace && namespace.root?
end
diff --git a/app/models/operations/feature_flag.rb b/app/models/operations/feature_flag.rb
index 442f9d36c43..be3f719ddb3 100644
--- a/app/models/operations/feature_flag.rb
+++ b/app/models/operations/feature_flag.rb
@@ -6,6 +6,7 @@ module Operations
include AtomicInternalId
include IidRoutes
include Limitable
+ include Referable
self.table_name = 'operations_feature_flags'
self.limit_scope = :project
@@ -65,6 +66,31 @@ module Operations
.reorder(:id)
.references(:operations_scopes)
end
+
+ def reference_prefix
+ '[feature_flag:'
+ end
+
+ def reference_pattern
+ @reference_pattern ||= %r{
+ #{Regexp.escape(reference_prefix)}(#{::Project.reference_pattern}\/)?(?<feature_flag>\d+)#{Regexp.escape(reference_postfix)}
+ }x
+ end
+
+ def link_reference_pattern
+ @link_reference_pattern ||= super("feature_flags", /(?<feature_flag>\d+)\/edit/)
+ end
+
+ def reference_postfix
+ ']'
+ end
+ end
+
+ def to_reference(from = nil, full: false)
+ project
+ .to_reference_base(from, full: full)
+ .then { |reference_base| reference_base.present? ? "#{reference_base}/" : nil }
+ .then { |reference_base| "#{self.class.reference_prefix}#{reference_base}#{iid}#{self.class.reference_postfix}" }
end
def related_issues(current_user, preload:)
diff --git a/app/models/packages/composer/cache_file.rb b/app/models/packages/composer/cache_file.rb
new file mode 100644
index 00000000000..ecd7596b989
--- /dev/null
+++ b/app/models/packages/composer/cache_file.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Packages
+ module Composer
+ class CacheFile < ApplicationRecord
+ include FileStoreMounter
+
+ self.table_name = 'packages_composer_cache_files'
+
+ mount_file_store_uploader Packages::Composer::CacheUploader
+
+ belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
+ belongs_to :namespace
+
+ validates :namespace, presence: true
+
+ scope :with_namespace, ->(namespace) { where(namespace: namespace) }
+ scope :with_sha, ->(sha) { where(file_sha256: sha) }
+ scope :expired, -> { where("delete_at <= ?", Time.current) }
+ scope :without_namespace, -> { where(namespace_id: nil) }
+ end
+ end
+end
diff --git a/app/models/packages/composer/metadatum.rb b/app/models/packages/composer/metadatum.rb
index 3026f5ea878..363858a3ed1 100644
--- a/app/models/packages/composer/metadatum.rb
+++ b/app/models/packages/composer/metadatum.rb
@@ -9,6 +9,9 @@ module Packages
belongs_to :package, -> { where(package_type: :composer) }, inverse_of: :composer_metadatum
validates :package, :target_sha, :composer_json, presence: true
+
+ scope :for_package, ->(name, project_id) { joins(:package).where(packages_packages: { name: name, project_id: project_id, package_type: Packages::Package.package_types[:composer] }) }
+ scope :locked_for_update, -> { lock('FOR UPDATE') }
end
end
end
diff --git a/app/models/packages/debian/group_component.rb b/app/models/packages/debian/group_component.rb
new file mode 100644
index 00000000000..81e02c363b0
--- /dev/null
+++ b/app/models/packages/debian/group_component.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::GroupComponent < ApplicationRecord
+ def self.container_type
+ :group
+ end
+
+ include Packages::Debian::Component
+end
diff --git a/app/models/packages/debian/group_component_file.rb b/app/models/packages/debian/group_component_file.rb
new file mode 100644
index 00000000000..333aab044a4
--- /dev/null
+++ b/app/models/packages/debian/group_component_file.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::GroupComponentFile < ApplicationRecord
+ def self.container_type
+ :group
+ end
+
+ include Packages::Debian::ComponentFile
+end
diff --git a/app/models/packages/debian/project_component.rb b/app/models/packages/debian/project_component.rb
new file mode 100644
index 00000000000..98cd7fd589b
--- /dev/null
+++ b/app/models/packages/debian/project_component.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::ProjectComponent < ApplicationRecord
+ def self.container_type
+ :project
+ end
+
+ include Packages::Debian::Component
+end
diff --git a/app/models/packages/debian/project_component_file.rb b/app/models/packages/debian/project_component_file.rb
new file mode 100644
index 00000000000..60ac29f91c2
--- /dev/null
+++ b/app/models/packages/debian/project_component_file.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Packages::Debian::ProjectComponentFile < ApplicationRecord
+ def self.container_type
+ :project
+ end
+
+ include Packages::Debian::ComponentFile
+end
diff --git a/app/models/packages/debian/project_distribution.rb b/app/models/packages/debian/project_distribution.rb
index a73c12d172d..22f1008b3b5 100644
--- a/app/models/packages/debian/project_distribution.rb
+++ b/app/models/packages/debian/project_distribution.rb
@@ -5,5 +5,8 @@ class Packages::Debian::ProjectDistribution < ApplicationRecord
:project
end
+ has_many :publications, class_name: 'Packages::Debian::Publication', inverse_of: :distribution, foreign_key: :distribution_id
+ has_many :packages, class_name: 'Packages::Package', through: :publications
+
include Packages::Debian::Distribution
end
diff --git a/app/models/packages/debian/publication.rb b/app/models/packages/debian/publication.rb
new file mode 100644
index 00000000000..93f5aa11d81
--- /dev/null
+++ b/app/models/packages/debian/publication.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class Packages::Debian::Publication < ApplicationRecord
+ belongs_to :package,
+ -> { where(package_type: :debian).where.not(version: nil) },
+ inverse_of: :debian_publication,
+ class_name: 'Packages::Package'
+ belongs_to :distribution,
+ inverse_of: :publications,
+ class_name: 'Packages::Debian::ProjectDistribution',
+ foreign_key: :distribution_id
+
+ validates :package, presence: true
+ validate :valid_debian_package_type
+
+ validates :distribution, presence: true
+
+ private
+
+ def valid_debian_package_type
+ return errors.add(:package, _('type must be Debian')) unless package&.debian?
+ return errors.add(:package, _('must be a Debian package')) unless package.debian_package?
+ end
+end
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 2067a800ad5..391540634be 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -17,13 +17,18 @@ class Packages::Package < ApplicationRecord
has_one :maven_metadatum, inverse_of: :package, class_name: 'Packages::Maven::Metadatum'
has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum'
has_one :composer_metadatum, inverse_of: :package, class_name: 'Packages::Composer::Metadatum'
+ has_one :rubygems_metadatum, inverse_of: :package, class_name: 'Packages::Rubygems::Metadatum'
has_many :build_infos, inverse_of: :package
has_many :pipelines, through: :build_infos
+ has_one :debian_publication, inverse_of: :package, class_name: 'Packages::Debian::Publication'
+ has_one :debian_distribution, through: :debian_publication, source: :distribution, inverse_of: :packages, class_name: 'Packages::Debian::ProjectDistribution'
accepts_nested_attributes_for :conan_metadatum
+ accepts_nested_attributes_for :debian_publication
accepts_nested_attributes_for :maven_metadatum
delegate :recipe, :recipe_path, to: :conan_metadatum, prefix: :conan
+ delegate :codename, :suite, to: :debian_distribution, prefix: :debian_distribution
validates :project, presence: true
validates :name, presence: true
@@ -31,7 +36,8 @@ class Packages::Package < ApplicationRecord
validates :name, format: { with: Gitlab::Regex.package_name_regex }, unless: -> { conan? || generic? || debian? }
validates :name,
- uniqueness: { scope: %i[project_id version package_type] }, unless: :conan?
+ uniqueness: { scope: %i[project_id version package_type] }, unless: -> { conan? || debian_package? }
+ validate :unique_debian_package_name, if: :debian_package?
validate :valid_conan_package_recipe, if: :conan?
validate :valid_npm_package_name, if: :npm?
@@ -59,7 +65,11 @@ class Packages::Package < ApplicationRecord
if: :debian_package?
validate :forbidden_debian_changes, if: :debian?
- enum package_type: { maven: 1, npm: 2, conan: 3, nuget: 4, pypi: 5, composer: 6, generic: 7, golang: 8, debian: 9 }
+ enum package_type: { maven: 1, npm: 2, conan: 3, nuget: 4, pypi: 5,
+ composer: 6, generic: 7, golang: 8, debian: 9,
+ rubygems: 10 }
+
+ enum status: { default: 0, hidden: 1, processing: 2 }
scope :with_name, ->(name) { where(name: name) }
scope :with_name_like, ->(name) { where(arel_table[:name].matches(name)) }
@@ -68,6 +78,8 @@ class Packages::Package < ApplicationRecord
scope :with_version, ->(version) { where(version: version) }
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }
scope :with_package_type, ->(package_type) { where(package_type: package_type) }
+ scope :with_status, ->(status) { where(status: status) }
+ scope :displayable, -> { with_status(:default) }
scope :including_build_info, -> { includes(pipelines: :user) }
scope :including_project_route, -> { includes(project: { namespace: :route }) }
scope :including_tags, -> { includes(:tags) }
@@ -251,6 +263,18 @@ class Packages::Package < ApplicationRecord
end
end
+ def unique_debian_package_name
+ return unless debian_publication&.distribution
+
+ package_exists = debian_publication.distribution.packages
+ .with_name(name)
+ .with_version(version)
+ .id_not_in(id)
+ .exists?
+
+ errors.add(:base, _('Debian package already exists in Distribution')) if package_exists
+ end
+
def forbidden_debian_changes
return unless persisted?
diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb
index 389edaea392..9059f61b5de 100644
--- a/app/models/packages/package_file.rb
+++ b/app/models/packages/package_file.rb
@@ -55,10 +55,6 @@ class Packages::PackageFile < ApplicationRecord
Gitlab::Routing.url_helpers.download_project_package_file_path(project, self)
end
- def local?
- file_store == ::Packages::PackageFileUploader::Store::LOCAL
- end
-
private
def update_size_from_file
diff --git a/app/models/packages/rubygems/metadatum.rb b/app/models/packages/rubygems/metadatum.rb
new file mode 100644
index 00000000000..42db1f3defc
--- /dev/null
+++ b/app/models/packages/rubygems/metadatum.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Packages
+ module Rubygems
+ class Metadatum < ApplicationRecord
+ self.table_name = 'packages_rubygems_metadata'
+ self.primary_key = :package_id
+
+ belongs_to :package, -> { where(package_type: :rubygems) }, inverse_of: :rubygems_metadatum
+
+ validates :package, presence: true
+
+ validate :rubygems_package_type
+
+ private
+
+ def rubygems_package_type
+ unless package&.rubygems?
+ errors.add(:base, _('Package type must be RubyGems'))
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 84928468ad1..c6781f8f6e3 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -4,6 +4,8 @@ module Pages
class LookupPath
include Gitlab::Utils::StrongMemoize
+ LegacyStorageDisabledError = Class.new(::StandardError)
+
def initialize(project, trim_prefix: nil, domain: nil)
@project = project
@domain = domain
@@ -24,7 +26,7 @@ module Pages
end
def source
- zip_source || file_source
+ zip_source || legacy_source
end
def prefix
@@ -52,6 +54,8 @@ module Pages
return if deployment.file.file_storage? && !Feature.enabled?(:pages_serve_with_zip_file_protocol, project)
+ return if deployment.migrated? && !Feature.enabled?(:pages_serve_from_migrated_zip, project)
+
global_id = ::Gitlab::GlobalId.build(deployment, id: deployment.id).to_s
{
@@ -64,11 +68,17 @@ module Pages
}
end
- def file_source
+ def legacy_source
+ raise LegacyStorageDisabledError unless Feature.enabled?(:pages_serve_from_legacy_storage, default_enabled: true)
+
{
type: 'file',
path: File.join(project.full_path, 'public/')
}
+ rescue LegacyStorageDisabledError => e
+ Gitlab::ErrorTracking.track_exception(e)
+
+ nil
end
end
end
diff --git a/app/models/pages/virtual_domain.rb b/app/models/pages/virtual_domain.rb
index 7e42b8e6ae2..90cb8253b52 100644
--- a/app/models/pages/virtual_domain.rb
+++ b/app/models/pages/virtual_domain.rb
@@ -17,9 +17,16 @@ module Pages
end
def lookup_paths
- projects.map do |project|
+ paths = projects.map do |project|
project.pages_lookup_path(trim_prefix: trim_prefix, domain: domain)
- end.sort_by(&:prefix).reverse
+ end
+
+ # TODO: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/297524
+ # source can only be nil if pages_serve_from_legacy_storage FF is disabled
+ # we can remove this filtering once we remove legacy storage
+ paths = paths.select(&:source)
+
+ paths.sort_by(&:prefix).reverse
end
private
diff --git a/app/models/pages_deployment.rb b/app/models/pages_deployment.rb
index 61818a63764..d67a92af6af 100644
--- a/app/models/pages_deployment.rb
+++ b/app/models/pages_deployment.rb
@@ -2,14 +2,18 @@
# PagesDeployment stores a zip archive containing GitLab Pages web-site
class PagesDeployment < ApplicationRecord
+ include EachBatch
include FileStoreMounter
+ MIGRATED_FILE_NAME = "_migrated.zip"
+
attribute :file_store, :integer, default: -> { ::Pages::DeploymentUploader.default_store }
belongs_to :project, optional: false
belongs_to :ci_build, class_name: 'Ci::Build', optional: true
scope :older_than, -> (id) { where('id < ?', id) }
+ scope :migrated_from_legacy_storage, -> { where(file: MIGRATED_FILE_NAME) }
validates :file, presence: true
validates :file_store, presence: true, inclusion: { in: ObjectStorage::SUPPORTED_STORES }
@@ -25,6 +29,10 @@ class PagesDeployment < ApplicationRecord
# this is to be adressed in https://gitlab.com/groups/gitlab-org/-/epics/589
end
+ def migrated?
+ file.filename == MIGRATED_FILE_NAME
+ end
+
private
def set_size
diff --git a/app/models/project.rb b/app/models/project.rb
index ec790798806..2b9b7dcf733 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -75,7 +75,7 @@ class Project < ApplicationRecord
default_value_for :resolve_outdated_diff_discussions, false
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
default_value_for(:repository_storage) do
- pick_repository_storage
+ Repository.pick_storage_shard
end
default_value_for(:shared_runners_enabled) { Gitlab::CurrentSettings.shared_runners_enabled }
@@ -117,7 +117,7 @@ class Project < ApplicationRecord
use_fast_destroy :build_trace_chunks
- after_destroy -> { run_after_commit { remove_pages } }
+ after_destroy -> { run_after_commit { legacy_remove_pages } }
after_destroy :remove_exports
after_validation :check_pending_delete
@@ -200,7 +200,7 @@ class Project < ApplicationRecord
# Packages
has_many :packages, class_name: 'Packages::Package'
has_many :package_files, through: :packages, class_name: 'Packages::PackageFile'
- # debian_distributions must be destroyed by ruby code in order to properly remove carrierwave uploads
+ # debian_distributions and associated component_files must be destroyed by ruby code in order to properly remove carrierwave uploads
has_many :debian_distributions, class_name: 'Packages::Debian::ProjectDistribution', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :import_state, autosave: true, class_name: 'ProjectImportState', inverse_of: :project
@@ -218,6 +218,7 @@ class Project < ApplicationRecord
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
+ has_many :merge_request_metrics, foreign_key: 'target_project', class_name: 'MergeRequest::Metrics', inverse_of: :target_project
has_many :source_of_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
has_many :issues
has_many :labels, class_name: 'ProjectLabel'
@@ -410,7 +411,7 @@ class Project < ApplicationRecord
delegate :dashboard_timezone, to: :metrics_setting, allow_nil: true, prefix: true
delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci
delegate :forward_deployment_enabled, :forward_deployment_enabled=, :forward_deployment_enabled?, to: :ci_cd_settings, prefix: :ci
- delegate :keep_latest_artifact, :keep_latest_artifact=, :keep_latest_artifact?, to: :ci_cd_settings, prefix: :ci
+ delegate :keep_latest_artifact, :keep_latest_artifact=, :keep_latest_artifact?, :keep_latest_artifacts_available?, to: :ci_cd_settings
delegate :restrict_user_defined_variables, :restrict_user_defined_variables=, :restrict_user_defined_variables?,
to: :ci_cd_settings
delegate :actual_limits, :actual_plan_name, to: :namespace, allow_nil: true
@@ -456,7 +457,7 @@ class Project < ApplicationRecord
validates :repository_storage,
presence: true,
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
- validates :variables, variable_duplicates: { scope: :environment_scope }
+ 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 }
@@ -836,8 +837,12 @@ class Project < ApplicationRecord
webide_pipelines.running_or_pending.for_user(user)
end
- def latest_pipeline_locked
- ci_keep_latest_artifact? ? :artifacts_locked : :unlocked
+ def default_pipeline_lock
+ if keep_latest_artifacts_available?
+ return :artifacts_locked
+ end
+
+ :unlocked
end
def autoclose_referenced_issues
@@ -1314,21 +1319,11 @@ class Project < ApplicationRecord
end
def external_issue_tracker
- if has_external_issue_tracker.nil?
- cache_has_external_issue_tracker
- end
+ cache_has_external_issue_tracker if has_external_issue_tracker.nil?
- if has_external_issue_tracker?
- strong_memoize(:external_issue_tracker) do
- services.external_issue_trackers.first
- end
- else
- nil
- end
- end
+ return unless has_external_issue_tracker?
- def cache_has_external_issue_tracker
- update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) if Gitlab::Database.read_write?
+ @external_issue_tracker ||= services.external_issue_trackers.first
end
def external_references_supported?
@@ -1356,9 +1351,9 @@ class Project < ApplicationRecord
end
def disabled_services
- return %w(datadog alerts) unless Feature.enabled?(:datadog_ci_integration, self)
+ return %w(datadog) unless Feature.enabled?(:datadog_ci_integration, self)
- %w(alerts)
+ []
end
def find_or_initialize_service(name)
@@ -1797,16 +1792,16 @@ class Project < ApplicationRecord
.delete_all
end
- # TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal?
+ # TODO: remove this method https://gitlab.com/gitlab-org/gitlab/-/issues/320775
# rubocop: disable CodeReuse/ServiceClass
- def remove_pages
+ def legacy_remove_pages
+ return unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+
# Projects with a missing namespace cannot have their pages removed
return unless namespace
mark_pages_as_not_deployed unless destroyed?
- DestroyPagesDeploymentsWorker.perform_async(id)
-
# 1. We rename pages to temporary directory
# 2. We wait 5 minutes, due to NFS caching
# 3. We asynchronously remove pages with force
@@ -2532,6 +2527,11 @@ class Project < ApplicationRecord
tracing_setting&.external_url
end
+ override :git_garbage_collect_worker_klass
+ def git_garbage_collect_worker_klass
+ Projects::GitGarbageCollectWorker
+ end
+
private
def find_service(services, name)
@@ -2690,6 +2690,10 @@ class Project < ApplicationRecord
def cache_has_external_wiki
update_column(:has_external_wiki, services.external_wikis.any?) if Gitlab::Database.read_write?
end
+
+ def cache_has_external_issue_tracker
+ update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) if Gitlab::Database.read_write?
+ end
end
Project.prepend_if_ee('EE::Project')
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index 366852d93bf..2c3f70654f8 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class ProjectAuthorization < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
include FromUnion
belongs_to :user
diff --git a/app/models/project_ci_cd_setting.rb b/app/models/project_ci_cd_setting.rb
index e5fc481b035..31be0759cd0 100644
--- a/app/models/project_ci_cd_setting.rb
+++ b/app/models/project_ci_cd_setting.rb
@@ -21,6 +21,11 @@ class ProjectCiCdSetting < ApplicationRecord
super && ::Feature.enabled?(:forward_deployment_enabled, project, default_enabled: true)
end
+ def keep_latest_artifacts_available?
+ # The project level feature can only be enabled when the feature is enabled instance wide
+ Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact? && keep_latest_artifact?
+ end
+
private
def set_default_git_depth
diff --git a/app/models/project_pages_metadatum.rb b/app/models/project_pages_metadatum.rb
index 2bef0056732..58dbac9057f 100644
--- a/app/models/project_pages_metadatum.rb
+++ b/app/models/project_pages_metadatum.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class ProjectPagesMetadatum < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
include EachBatch
self.primary_key = :project_id
@@ -11,4 +13,5 @@ class ProjectPagesMetadatum < ApplicationRecord
scope :deployed, -> { where(deployed: true) }
scope :only_on_legacy_storage, -> { deployed.where(pages_deployment: nil) }
+ scope :with_project_route_and_deployment, -> { preload(:pages_deployment, project: [:namespace, :route]) }
end
diff --git a/app/models/project_services/alerts_service.rb b/app/models/project_services/alerts_service.rb
deleted file mode 100644
index 4afce0dfe95..00000000000
--- a/app/models/project_services/alerts_service.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-# This service is scheduled for removal. All records must
-# be deleted before the class can be removed.
-# https://gitlab.com/groups/gitlab-org/-/epics/5056
-class AlertsService < Service
- before_save :prevent_save
-
- def self.to_param
- 'alerts'
- end
-
- def self.supported_events
- %w()
- end
-
- private
-
- def prevent_save
- errors.add(:base, _('Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead.'))
- log_error('Prevented attempt to save or update deprecated AlertsService')
-
- # Stops execution of callbacks and database operation while
- # preserving expectations of #save (will not raise) & #save! (raises)
- # https://guides.rubyonrails.org/active_record_callbacks.html#halting-execution
- throw :abort # rubocop:disable Cop/BanCatchThrow
- end
-end
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index c9e97efb4ac..1d50d5cf19e 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -11,11 +11,13 @@ class ChatNotificationService < Service
tag_push pipeline wiki_page deployment
].freeze
+ SUPPORTED_EVENTS_FOR_LABEL_FILTER = %w[issue confidential_issue merge_request note confidential_note].freeze
+
EVENT_CHANNEL = proc { |event| "#{event}_channel" }
default_value_for :category, 'chat'
- prop_accessor :webhook, :username, :channel, :branches_to_be_notified
+ prop_accessor :webhook, :username, :channel, :branches_to_be_notified, :labels_to_be_notified
# Custom serialized properties initialization
prop_accessor(*SUPPORTED_EVENTS.map { |event| EVENT_CHANNEL[event] })
@@ -62,12 +64,16 @@ class ChatNotificationService < Service
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}", required: true }.freeze,
{ type: 'text', name: 'username', placeholder: 'e.g. GitLab' }.freeze,
{ type: 'checkbox', name: 'notify_only_broken_pipelines' }.freeze,
- { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze
+ { type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze,
+ { type: 'text', name: 'labels_to_be_notified', placeholder: 'e.g. ~backend', help: 'Only supported for issue, merge request and note events.' }.freeze
].freeze
end
def execute(data)
return unless supported_events.include?(data[:object_kind])
+
+ return unless notify_label?(data)
+
return unless webhook.present?
object_kind = data[:object_kind]
@@ -114,6 +120,22 @@ class ChatNotificationService < Service
private
+ def labels_to_be_notified_list
+ return [] if labels_to_be_notified.nil?
+
+ labels_to_be_notified.delete('~').split(',').map(&:strip)
+ end
+
+ def notify_label?(data)
+ return true unless SUPPORTED_EVENTS_FOR_LABEL_FILTER.include?(data[:object_kind]) && labels_to_be_notified.present?
+
+ issue_labels = data.dig(:issue, :labels) || []
+ merge_request_labels = data.dig(:merge_request, :labels) || []
+ label_titles = (issue_labels + merge_request_labels).pluck(:title)
+
+ (labels_to_be_notified_list & label_titles).any?
+ end
+
# every notifier must implement this independently
def notify(message, opts)
raise NotImplementedError
diff --git a/app/models/project_services/confluence_service.rb b/app/models/project_services/confluence_service.rb
index 6db446fc04c..8a6f4de540c 100644
--- a/app/models/project_services/confluence_service.rb
+++ b/app/models/project_services/confluence_service.rb
@@ -30,8 +30,8 @@ class ConfluenceService < Service
s_('ConfluenceService|Connect a Confluence Cloud Workspace to GitLab')
end
- def detailed_description
- return unless project.wiki_enabled?
+ def help
+ return unless project&.wiki_enabled?
if activated?
wiki_url = project.wiki.web_url
diff --git a/app/models/project_services/datadog_service.rb b/app/models/project_services/datadog_service.rb
index 3a742bfdcda..a48dea71645 100644
--- a/app/models/project_services/datadog_service.rb
+++ b/app/models/project_services/datadog_service.rb
@@ -12,14 +12,22 @@ class DatadogService < Service
prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env
- with_options presence: true, if: :activated? do
- validates :api_key, format: { with: /\A\w+\z/ }
- validates :datadog_site, format: { with: /\A[\w\.]+\z/ }, unless: :api_url
- validates :api_url, public_url: true, unless: :datadog_site
+ with_options if: :activated? do
+ validates :api_key, presence: true, format: { with: /\A\w+\z/ }
+ validates :datadog_site, format: { with: /\A[\w\.]+\z/, allow_blank: true }
+ 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? }
end
after_save :compose_service_hook, if: :activated?
+ def initialize_properties
+ super
+
+ self.datadog_site ||= DEFAULT_SITE
+ end
+
def self.supported_events
SUPPORTED_EVENTS
end
@@ -54,27 +62,37 @@ class DatadogService < Service
def fields
[
{
- type: 'text', name: 'datadog_site',
- placeholder: DEFAULT_SITE, default: DEFAULT_SITE,
+ type: 'text',
+ name: 'datadog_site',
+ placeholder: DEFAULT_SITE,
help: 'Choose the Datadog site to send data to. Set to "datadoghq.eu" to send data to the EU site',
required: false
},
{
- type: 'text', name: 'api_url', title: 'Custom URL',
+ type: 'text',
+ name: 'api_url',
+ title: 'API URL',
help: '(Advanced) Define the full URL for your Datadog site directly',
required: false
},
{
- type: 'password', name: 'api_key', title: 'API key',
+ type: 'password',
+ name: 'api_key',
+ title: 'API key',
help: "<a href=\"#{api_keys_url}\" target=\"_blank\">API key</a> used for authentication with Datadog",
required: true
},
{
- type: 'text', name: 'datadog_service', title: 'Service', placeholder: 'gitlab-ci',
+ type: 'text',
+ name: 'datadog_service',
+ title: 'Service',
+ placeholder: 'gitlab-ci',
help: 'Name of this GitLab instance that all data will be tagged with'
},
{
- type: 'text', name: 'datadog_env', title: 'Env',
+ type: 'text',
+ name: 'datadog_env',
+ title: 'Env',
help: 'The environment tag that traces will be tagged with'
}
]
@@ -90,7 +108,7 @@ class DatadogService < Service
url = api_url.presence || sprintf(URL_TEMPLATE, datadog_site: datadog_site)
url = URI.parse(url)
url.path = File.join(url.path || '/', api_key)
- query = { service: datadog_service, env: datadog_env }.compact
+ query = { service: datadog_service.presence, env: datadog_env.presence }.compact
url.query = query.to_query unless query.empty?
url.to_s
end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index dafd3d095ec..5857d86f921 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# Accessible as Project#external_issue_tracker
class JiraService < IssueTrackerService
extend ::Gitlab::Utils::Override
include Gitlab::Routing
@@ -30,7 +31,8 @@ class JiraService < IssueTrackerService
# TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab/issues/29404
- data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled, :vulnerabilities_enabled, :vulnerabilities_issuetype
+ data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled,
+ :vulnerabilities_enabled, :vulnerabilities_issuetype, :proxy_address, :proxy_port, :proxy_username, :proxy_password
before_update :reset_password
after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type?
@@ -157,11 +159,14 @@ class JiraService < IssueTrackerService
# support any events.
end
- def find_issue(issue_key)
- jira_request { client.Issue.find(issue_key) }
+ def find_issue(issue_key, rendered_fields: false)
+ options = {}
+ options = options.merge(expand: 'renderedFields') if rendered_fields
+
+ jira_request { client.Issue.find(issue_key, options) }
end
- def close_issue(entity, external_issue)
+ def close_issue(entity, external_issue, current_user)
issue = find_issue(external_issue.iid)
return if issue.nil? || has_resolution?(issue) || !jira_issue_transition_id.present?
@@ -178,6 +183,7 @@ class JiraService < IssueTrackerService
# if it is closed, so we don't have one comment for every commit.
issue = find_issue(issue.key) if transition_issue(issue)
add_issue_solved_comment(issue, commit_id, commit_url) if has_resolution?(issue)
+ log_usage(:close_issue, current_user)
end
def create_cross_reference_note(mentioned, noteable, author)
@@ -213,7 +219,7 @@ class JiraService < IssueTrackerService
}
}
- add_comment(data, jira_issue)
+ add_comment(data, jira_issue).tap { log_usage(:cross_reference, author) }
end
def valid_connection?
@@ -274,6 +280,12 @@ class JiraService < IssueTrackerService
end
end
+ def log_usage(action, user)
+ key = "i_ecosystem_jira_service_#{action}"
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user.id)
+ end
+
def add_issue_solved_comment(issue, commit_id, commit_url)
link_title = "Solved by commit #{commit_id}."
comment = "Issue solved with [#{commit_id}|#{commit_url}]."
diff --git a/app/models/project_services/jira_tracker_data.rb b/app/models/project_services/jira_tracker_data.rb
index 00b6ab6a70f..6cbcb1550c1 100644
--- a/app/models/project_services/jira_tracker_data.rb
+++ b/app/models/project_services/jira_tracker_data.rb
@@ -7,6 +7,15 @@ class JiraTrackerData < ApplicationRecord
attr_encrypted :api_url, encryption_options
attr_encrypted :username, encryption_options
attr_encrypted :password, encryption_options
+ attr_encrypted :proxy_address, encryption_options
+ attr_encrypted :proxy_port, encryption_options
+ attr_encrypted :proxy_username, encryption_options
+ attr_encrypted :proxy_password, encryption_options
+
+ validates :proxy_address, length: { maximum: 2048 }
+ validates :proxy_port, length: { maximum: 5 }
+ validates :proxy_username, length: { maximum: 255 }
+ validates :proxy_password, length: { maximum: 255 }
enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
end
diff --git a/app/models/project_services/mock_deployment_service.rb b/app/models/project_services/mock_deployment_service.rb
deleted file mode 100644
index e55335d9aae..00000000000
--- a/app/models/project_services/mock_deployment_service.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-# Deprecated, to be deleted in 13.8 (https://gitlab.com/gitlab-org/gitlab/-/issues/293914)
-#
-# This was a class used only in development environment but became unusable
-# since DeploymentService was deleted
-class MockDeploymentService < Service
- default_value_for :category, 'deployment'
-
- def title
- 'Mock deployment'
- end
-
- def description
- 'Mock deployment service'
- end
-
- def self.to_param
- 'mock_deployment'
- end
-
- # No terminals support
- def terminals(environment)
- []
- end
-
- def self.supported_events
- %w()
- end
-
- def predefined_variables(project:, environment_name:)
- []
- end
-
- def can_test?
- false
- end
-end
diff --git a/app/models/project_setting.rb b/app/models/project_setting.rb
index aca7eec3382..83ff0702b88 100644
--- a/app/models/project_setting.rb
+++ b/app/models/project_setting.rb
@@ -21,4 +21,4 @@ class ProjectSetting < ApplicationRecord
end
end
-ProjectSetting.prepend_if_ee('EE::ProjectSetting')
+ProjectSetting.prepend_ee_mod
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index 7605ef54d5b..8c3dcaa7c0f 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -31,6 +31,7 @@ class ProjectStatistics < ApplicationRecord
scope :for_project_ids, ->(project_ids) { where(project_id: project_ids) }
scope :for_namespaces, -> (namespaces) { where(namespace: namespaces) }
+ scope :with_any_ci_minutes_used, -> { where.not(shared_runners_seconds: 0) }
def total_repository_size
repository_size + lfs_objects_size
diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb
index f28440f2444..ea51dca8a42 100644
--- a/app/models/protected_branch/push_access_level.rb
+++ b/app/models/protected_branch/push_access_level.rb
@@ -19,7 +19,7 @@ class ProtectedBranch::PushAccessLevel < ApplicationRecord
end
def check_access(user)
- if Feature.enabled?(:deploy_keys_on_protected_branches, project) && user && deploy_key.present?
+ if user && deploy_key.present?
return true if user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user)
end
diff --git a/app/models/push_event_payload.rb b/app/models/push_event_payload.rb
index 6a32c480b04..2786ecb641a 100644
--- a/app/models/push_event_payload.rb
+++ b/app/models/push_event_payload.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class PushEventPayload < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
include ShaAttribute
belongs_to :event, inverse_of: :push_event_payload
diff --git a/app/models/readme_blob.rb b/app/models/readme_blob.rb
deleted file mode 100644
index 695b4e3ffe3..00000000000
--- a/app/models/readme_blob.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class ReadmeBlob < SimpleDelegator
- include BlobActiveModel
-
- attr_reader :repository
-
- def initialize(blob, repository)
- @repository = repository
-
- super(blob)
- end
-
- def rendered_markup
- repository.rendered_readme
- end
-end
diff --git a/app/models/release.rb b/app/models/release.rb
index 2b82fdc37f6..60c2abcacb3 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -24,6 +24,7 @@ class Release < ApplicationRecord
validates :project, :tag, presence: true
validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
+ validates :links, nested_attributes_duplicates: { scope: :release, child_attributes: %i[name url filepath] }
scope :sorted, -> { order(released_at: :desc) }
scope :preloaded, -> { includes(:evidences, :milestones, project: [:project_feature, :route, { namespace: :route }]) }
diff --git a/app/models/repository.rb b/app/models/repository.rb
index c19448332f8..06a13194e1a 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -39,11 +39,11 @@ class Repository
#
# For example, for entry `:commit_count` there's a method called `commit_count` which
# stores its data in the `commit_count` cache key.
- CACHED_METHODS = %i(size commit_count rendered_readme readme_path contribution_guide
+ CACHED_METHODS = %i(size commit_count readme_path contribution_guide
changelog license_blob license_key gitignore
gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref merged_branch_names
- has_visible_content? issue_template_names merge_request_template_names
+ has_visible_content? issue_template_names_by_category merge_request_template_names_by_category
user_defined_metrics_dashboard_paths xcode_project? has_ambiguous_refs?).freeze
# Methods that use cache_method but only memoize the value
@@ -53,15 +53,15 @@ class Repository
# changed. This Hash maps file types (as returned by Gitlab::FileDetector) to
# the corresponding methods to call for refreshing caches.
METHOD_CACHES_FOR_FILE_TYPES = {
- readme: %i(rendered_readme readme_path),
+ readme: %i(readme_path),
changelog: :changelog,
license: %i(license_blob license_key license),
contributing: :contribution_guide,
gitignore: :gitignore,
gitlab_ci: :gitlab_ci_yml,
avatar: :avatar,
- issue_template: :issue_template_names,
- merge_request_template: :merge_request_template_names,
+ issue_template: :issue_template_names_by_category,
+ merge_request_template: :merge_request_template_names_by_category,
metrics_dashboard: :user_defined_metrics_dashboard_paths,
xcode_config: :xcode_project?
}.freeze
@@ -151,7 +151,8 @@ class Repository
all: !!opts[:all],
first_parent: !!opts[:first_parent],
order: opts[:order],
- literal_pathspec: opts.fetch(:literal_pathspec, true)
+ literal_pathspec: opts.fetch(:literal_pathspec, true),
+ trailers: opts[:trailers]
}
commits = Gitlab::Git::Commit.where(options)
@@ -497,23 +498,7 @@ class Repository
end
def blob_at(sha, path)
- blob = Blob.decorate(raw_repository.blob_at(sha, path), container)
-
- # Don't attempt to return a special result if there is no blob at all
- return unless blob
-
- # Don't attempt to return a special result if this can't be a README
- return blob unless Gitlab::FileDetector.type_of(blob.name) == :readme
-
- # Don't attempt to return a special result unless we're looking at HEAD
- return blob unless head_commit&.sha == sha
-
- case path
- when head_tree&.readme_path
- ReadmeBlob.new(blob, self)
- else
- blob
- end
+ Blob.decorate(raw_repository.blob_at(sha, path), container)
rescue Gitlab::Git::Repository::NoRepository
nil
end
@@ -587,15 +572,16 @@ class Repository
end
cache_method :avatar
- def issue_template_names
- Gitlab::Template::IssueTemplate.dropdown_names(project)
+ # store issue_template_names as hash
+ def issue_template_names_by_category
+ Gitlab::Template::IssueTemplate.repository_template_names(project)
end
- cache_method :issue_template_names, fallback: []
+ cache_method :issue_template_names_by_category, fallback: {}
- def merge_request_template_names
- Gitlab::Template::MergeRequestTemplate.dropdown_names(project)
+ def merge_request_template_names_by_category
+ Gitlab::Template::MergeRequestTemplate.repository_template_names(project)
end
- cache_method :merge_request_template_names, fallback: []
+ cache_method :merge_request_template_names_by_category, fallback: {}
def user_defined_metrics_dashboard_paths
Gitlab::Metrics::Dashboard::RepoDashboardFinder.list_dashboards(project)
@@ -611,15 +597,6 @@ class Repository
end
cache_method :readme_path
- def rendered_readme
- return unless readme
-
- context = { project: project }
-
- MarkupHelper.markup_unsafe(readme.name, readme.data, context)
- end
- cache_method :rendered_readme
-
def contribution_guide
file_on_head(:contributing)
end
@@ -1058,6 +1035,10 @@ class Repository
blob_data_at(sha, '.lfsconfig')
end
+ def changelog_config(ref = 'HEAD')
+ blob_data_at(ref, Gitlab::Changelog::Config::FILE_PATH)
+ end
+
def fetch_ref(source_repository, source_ref:, target_ref:)
raw_repository.fetch_ref(source_repository.raw_repository, source_ref: source_ref, target_ref: target_ref)
end
@@ -1142,6 +1123,13 @@ class Repository
end
end
+ # Choose one of the available repository storage options based on a normalized weighted probability.
+ # We should always use the latest settings, to avoid picking a deleted shard.
+ def self.pick_storage_shard(expire: true)
+ Gitlab::CurrentSettings.expire_current_application_settings if expire
+ Gitlab::CurrentSettings.pick_repository_storage
+ end
+
private
# TODO Genericize finder, later split this on finders by Ref or Oid
diff --git a/app/models/repository_language.rb b/app/models/repository_language.rb
index 6b1793a551f..b7a96211fb1 100644
--- a/app/models/repository_language.rb
+++ b/app/models/repository_language.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class RepositoryLanguage < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
belongs_to :project
belongs_to :programming_language
diff --git a/app/models/service.rb b/app/models/service.rb
index e5626462dd3..c49e0869b21 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -46,7 +46,6 @@ class Service < ApplicationRecord
after_initialize :initialize_properties
after_commit :reset_updated_properties
- after_commit :cache_project_has_external_issue_tracker
belongs_to :project, inverse_of: :services
belongs_to :group, inverse_of: :services
@@ -55,11 +54,11 @@ class Service < ApplicationRecord
validates :project_id, presence: true, unless: -> { template? || instance? || group_id }
validates :group_id, presence: true, unless: -> { template? || instance? || project_id }
validates :project_id, :group_id, absence: true, if: -> { template? || instance? }
- validates :type, uniqueness: { scope: :project_id }, unless: -> { template? || instance? || group_id }, on: :create
- validates :type, uniqueness: { scope: :group_id }, unless: -> { template? || instance? || project_id }
validates :type, presence: true
- validates :template, uniqueness: { scope: :type }, if: -> { template? }
- validates :instance, uniqueness: { scope: :type }, if: -> { instance? }
+ validates :type, uniqueness: { scope: :template }, if: :template?
+ validates :type, uniqueness: { scope: :instance }, if: :instance?
+ validates :type, uniqueness: { scope: :project_id }, if: :project_id?
+ validates :type, uniqueness: { scope: :group_id }, if: :group_id?
validate :validate_is_instance_or_template
validate :validate_belongs_to_project_or_group
@@ -438,10 +437,6 @@ class Service < ApplicationRecord
ProjectServiceWorker.perform_async(id, data)
end
- def external_issue_tracker?
- category == :issue_tracker && active?
- end
-
def external_wiki?
type == 'ExternalWikiService' && active?
end
@@ -461,12 +456,6 @@ class Service < ApplicationRecord
errors.add(:project_id, 'The service cannot belong to both a project and a group') if project_id && group_id
end
- def cache_project_has_external_issue_tracker
- if project && !project.destroyed?
- project.cache_has_external_issue_tracker
- end
- end
-
def valid_recipients?
activated? && !importing?
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index c4a7c5e25dc..ab8782ed87f 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -317,7 +317,7 @@ class Snippet < ApplicationRecord
end
def repository_storage
- snippet_repository&.shard_name || self.class.pick_repository_storage
+ snippet_repository&.shard_name || Repository.pick_storage_shard
end
# Repositories are created by default with the `master` branch.
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index efbbd86ae4a..eb7d465d585 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -22,7 +22,9 @@ module Terraform
scope :versioning_not_enabled, -> { where(versioning_enabled: false) }
scope :ordered_by_name, -> { order(:name) }
+ scope :with_name, -> (name) { where(name: name) }
+ validates :name, presence: true, uniqueness: { scope: :project_id }
validates :project_id, presence: true
validates :uuid, presence: true, uniqueness: true, length: { is: UUID_LENGTH },
format: { with: HEX_REGEXP, message: 'only allows hex characters' }
diff --git a/app/models/terraform/state_version.rb b/app/models/terraform/state_version.rb
index 19d708616fc..432ac5b6422 100644
--- a/app/models/terraform/state_version.rb
+++ b/app/models/terraform/state_version.rb
@@ -9,16 +9,14 @@ module Terraform
belongs_to :build, class_name: 'Ci::Build', optional: true, foreign_key: :ci_build_id
scope :ordered_by_version_desc, -> { order(version: :desc) }
+ scope :with_files_stored_locally, -> { where(file_store: Terraform::StateUploader::Store::LOCAL) }
+ scope :preload_state, -> { includes(:terraform_state) }
default_value_for(:file_store) { StateUploader.default_store }
mount_file_store_uploader StateUploader
delegate :project_id, :uuid, to: :terraform_state, allow_nil: true
-
- def local?
- file_store == ObjectStorage::Store::LOCAL
- end
end
end
diff --git a/app/models/token_with_iv.rb b/app/models/token_with_iv.rb
new file mode 100644
index 00000000000..115f40b4a82
--- /dev/null
+++ b/app/models/token_with_iv.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# rubocop: todo Gitlab/NamespacedClass
+class TokenWithIv < ApplicationRecord
+ validates :hashed_token, presence: true
+ validates :iv, presence: true
+ validates :hashed_plaintext_token, presence: true
+
+ def self.find_by_hashed_token(value)
+ find_by(hashed_token: ::Digest::SHA256.digest(value))
+ end
+
+ def self.find_by_plaintext_token(value)
+ find_by(hashed_plaintext_token: ::Digest::SHA256.digest(value))
+ end
+
+ def self.find_nonce_by_hashed_token(value)
+ return unless table_exists?
+
+ token_record = find_by_hashed_token(value)
+ token_record&.iv
+ end
+end
diff --git a/app/models/u2f_registration.rb b/app/models/u2f_registration.rb
index 1a389081913..65dc7a47533 100644
--- a/app/models/u2f_registration.rb
+++ b/app/models/u2f_registration.rb
@@ -4,11 +4,19 @@
class U2fRegistration < ApplicationRecord
belongs_to :user
- after_commit :schedule_webauthn_migration, on: :create
- after_commit :update_webauthn_registration, on: :update, if: :counter_changed?
- def schedule_webauthn_migration
- BackgroundMigrationWorker.perform_async('MigrateU2fWebauthn', [id, id])
+ after_create :create_webauthn_registration
+ after_update :update_webauthn_registration, if: :counter_changed?
+
+ def create_webauthn_registration
+ converter = Gitlab::Auth::U2fWebauthnConverter.new(self)
+ WebauthnRegistration.create!(converter.convert)
+ rescue StandardError => ex
+ Gitlab::AppJsonLogger.error(
+ event: 'u2f_migration',
+ error: ex.class.name,
+ backtrace: ::Gitlab::BacktraceCleaner.clean_backtrace(ex.backtrace),
+ message: "U2F to WebAuthn conversion failed")
end
def update_webauthn_registration
diff --git a/app/models/user.rb b/app/models/user.rb
index b4ec6064ff8..1f8b680c7e5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -116,6 +116,13 @@ class User < ApplicationRecord
has_one :user_synced_attributes_metadata, autosave: true
has_one :aws_role, class_name: 'Aws::Role'
+ # Followers
+ has_many :followed_users, foreign_key: :follower_id, class_name: 'Users::UserFollowUser'
+ has_many :followees, through: :followed_users
+
+ has_many :following_users, foreign_key: :followee_id, class_name: 'Users::UserFollowUser'
+ has_many :followers, through: :following_users
+
# Groups
has_many :members
has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, source: 'GroupMember'
@@ -960,8 +967,8 @@ class User < ApplicationRecord
end
# rubocop: disable CodeReuse/ServiceClass
- def refresh_authorized_projects
- Users::RefreshAuthorizedProjectsService.new(self).execute
+ def refresh_authorized_projects(source: nil)
+ Users::RefreshAuthorizedProjectsService.new(self, source: source).execute
end
# rubocop: enable CodeReuse/ServiceClass
@@ -1442,6 +1449,29 @@ class User < ApplicationRecord
end
end
+ def following?(user)
+ self.followees.exists?(user.id)
+ end
+
+ def follow(user)
+ return false if self.id == user.id
+
+ begin
+ followee = Users::UserFollowUser.create(follower_id: self.id, followee_id: user.id)
+ self.followees.reset if followee.persisted?
+ rescue ActiveRecord::RecordNotUnique
+ false
+ end
+ end
+
+ def unfollow(user)
+ if Users::UserFollowUser.where(follower_id: self.id, followee_id: user.id).delete_all > 0
+ self.followees.reset
+ else
+ false
+ end
+ end
+
def manageable_namespaces
@manageable_namespaces ||= [namespace] + manageable_groups
end
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index ad5651f9439..d93fe611538 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -7,19 +7,19 @@ class UserCallout < ApplicationRecord
gke_cluster_integration: 1,
gcp_signup_offer: 2,
cluster_security_warning: 3,
- gold_trial: 4, # EE-only
- geo_enable_hashed_storage: 5, # EE-only
- geo_migrate_hashed_storage: 6, # EE-only
- canary_deployment: 7, # EE-only
- gold_trial_billings: 8, # EE-only
+ gold_trial: 4, # EE-only
+ geo_enable_hashed_storage: 5, # EE-only
+ geo_migrate_hashed_storage: 6, # EE-only
+ canary_deployment: 7, # EE-only
+ gold_trial_billings: 8, # EE-only
suggest_popover_dismissed: 9,
tabs_position_highlight: 10,
- threat_monitoring_info: 11, # EE-only
- account_recovery_regular_check: 12, # EE-only
+ threat_monitoring_info: 11, # EE-only
+ account_recovery_regular_check: 12, # EE-only
webhooks_moved: 13,
service_templates_deprecated: 14,
admin_integrations_moved: 15,
- web_ide_alert_dismissed: 16, # no longer in use
+ web_ide_alert_dismissed: 16, # no longer in use
active_user_count_threshold: 18, # EE-only
buy_pipeline_minutes_notification_dot: 19, # EE-only
personal_access_token_expiry: 21, # EE-only
@@ -27,7 +27,9 @@ class UserCallout < ApplicationRecord
customize_homepage: 23,
feature_flags_new_version: 24,
registration_enabled_callout: 25,
- new_user_signups_cap_reached: 26 # EE-only
+ new_user_signups_cap_reached: 26, # EE-only
+ unfinished_tag_cleanup_callout: 27,
+ eoa_bronze_plan_banner: 28 # EE-only
}
validates :user, presence: true
diff --git a/app/models/user_interacted_project.rb b/app/models/user_interacted_project.rb
index 7e7a387d3d4..4c8cc5fc83a 100644
--- a/app/models/user_interacted_project.rb
+++ b/app/models/user_interacted_project.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class UserInteractedProject < ApplicationRecord
+ extend SuppressCompositePrimaryKeyWarning
+
belongs_to :user
belongs_to :project
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 0e1ae0b7338..1c8634e47c3 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -7,6 +7,16 @@ class UserStatus < ApplicationRecord
DEFAULT_EMOJI = 'speech_balloon'
+ CLEAR_STATUS_QUICK_OPTIONS = {
+ '30_minutes' => 30.minutes,
+ '3_hours' => 3.hours,
+ '8_hours' => 8.hours,
+ '1_day' => 1.day,
+ '3_days' => 3.days,
+ '7_days' => 7.days,
+ '30_days' => 30.days
+ }.freeze
+
belongs_to :user
enum availability: { not_set: 0, busy: 1 }
@@ -15,5 +25,11 @@ class UserStatus < ApplicationRecord
validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names }
validates :message, length: { maximum: 100 }, allow_blank: true
+ scope :scheduled_for_cleanup, -> { where(arel_table[:clear_status_at].lteq(Time.current)) }
+
cache_markdown_field :message, pipeline: :emoji
+
+ def clear_status_after=(value)
+ self.clear_status_at = CLEAR_STATUS_QUICK_OPTIONS[value]&.from_now
+ end
end
diff --git a/app/models/users/user_follow_user.rb b/app/models/users/user_follow_user.rb
new file mode 100644
index 00000000000..a94239a746c
--- /dev/null
+++ b/app/models/users/user_follow_user.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+module Users
+ class UserFollowUser < ApplicationRecord
+ belongs_to :follower, class_name: 'User'
+ belongs_to :followee, class_name: 'User'
+ end
+end
diff --git a/app/models/vulnerability.rb b/app/models/vulnerability.rb
index ab29afd0d08..7728c9c174e 100644
--- a/app/models/vulnerability.rb
+++ b/app/models/vulnerability.rb
@@ -12,17 +12,9 @@ class Vulnerability < ApplicationRecord
'[vulnerability:'
end
- def self.reference_prefix_escaped
- '[vulnerability&lbrack;'
- end
-
def self.reference_postfix
']'
end
-
- def self.reference_postfix_escaped
- '&rbrack;'
- end
end
-Vulnerability.prepend_if_ee('EE::Vulnerability')
+Vulnerability.prepend_ee_mod
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index 11c10a61d18..45747c0b03c 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -104,7 +104,7 @@ class Wiki
end
def empty?
- list_pages(limit: 1).empty?
+ !repository_exists? || list_pages(limit: 1).empty?
end
def exists?
@@ -256,6 +256,15 @@ class Wiki
def after_post_receive
end
+ override :git_garbage_collect_worker_klass
+ def git_garbage_collect_worker_klass
+ Wikis::GitGarbageCollectWorker
+ end
+
+ def cleanup
+ @repository = nil
+ end
+
private
def commit_details(action, message = nil, title = nil)
diff --git a/app/policies/application_setting_policy.rb b/app/policies/application_setting_policy.rb
new file mode 100644
index 00000000000..114c71fd99d
--- /dev/null
+++ b/app/policies/application_setting_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ApplicationSettingPolicy < BasePolicy # rubocop:disable Gitlab/NamespacedClass
+ rule { admin }.enable :read_application_setting
+end
diff --git a/app/policies/event_policy.rb b/app/policies/event_policy.rb
new file mode 100644
index 00000000000..5587956855e
--- /dev/null
+++ b/app/policies/event_policy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class EventPolicy < BasePolicy # rubocop:disable Gitlab/NamespacedClass
+ condition(:visible_to_user) do
+ subject.visible_to_user?(user)
+ end
+
+ rule { visible_to_user }.enable :read_event
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 6135523a2f8..aaf985d6c63 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -30,6 +30,9 @@ class ProjectPolicy < BasePolicy
desc "User has maintainer access"
condition(:maintainer) { team_access_level >= Gitlab::Access::MAINTAINER }
+ desc "User is a project bot"
+ condition(:project_bot) { user.project_bot? && team_member? }
+
desc "Project is public"
condition(:public_project, scope: :subject, score: 0) { project.public? }
@@ -79,7 +82,7 @@ class ProjectPolicy < BasePolicy
with_scope :subject
condition(:metrics_dashboard_allowed) do
- feature_available?(:metrics_dashboard)
+ access_allowed_to?(:metrics_dashboard)
end
with_scope :global
@@ -158,7 +161,7 @@ class ProjectPolicy < BasePolicy
features.each do |f|
# these are scored high because they are unlikely
desc "Project has #{f} disabled"
- condition(:"#{f}_disabled", score: 32) { !feature_available?(f.to_sym) }
+ condition(:"#{f}_disabled", score: 32) { !access_allowed_to?(f.to_sym) }
end
# `:read_project` may be prevented in EE, but `:read_project_for_iids` should
@@ -583,6 +586,10 @@ class ProjectPolicy < BasePolicy
enable :read_issue_link
end
+ rule { can?(:developer_access) }.policy do
+ enable :read_security_configuration
+ end
+
# Design abilities could also be prevented in the issue policy.
rule { design_management_disabled }.policy do
prevent :read_design
@@ -621,10 +628,14 @@ class ProjectPolicy < BasePolicy
prevent :read_project
end
+ rule { project_bot }.enable :project_bot_access
+
rule { resource_access_token_available & can?(:admin_project) }.policy do
enable :admin_resource_access_tokens
end
+ rule { can?(:project_bot_access) }.prevent :admin_resource_access_tokens
+
rule { user_defined_variables_allowed | can?(:maintainer_access) }.policy do
enable :set_pipeline_variables
end
@@ -690,7 +701,7 @@ class ProjectPolicy < BasePolicy
project.team.max_member_access(@user.id)
end
- def feature_available?(feature)
+ def access_allowed_to?(feature)
return false unless project.project_feature
case project.project_feature.access_level(feature)
diff --git a/app/presenters/ci/build_presenter.rb b/app/presenters/ci/build_presenter.rb
index 03cbb57eb84..51a81158f78 100644
--- a/app/presenters/ci/build_presenter.rb
+++ b/app/presenters/ci/build_presenter.rb
@@ -50,3 +50,5 @@ module Ci
end
end
end
+
+Ci::BuildPresenter.prepend_if_ee('EE::Ci::BuildPresenter')
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index ffa33dc9f15..dbb77143e2e 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -93,22 +93,10 @@ module Ci
end
def refspec_for_persistent_ref
- #
- # End-to-end test coverage for CI fetching seems to not be strong, so we
- # are using a feature flag here to close the confidence gap. My (JV)
- # confidence about the change is very high but if something is wrong
- # with it after all, this would cause all CI jobs on gitlab.com to fail.
- #
- # The roll-out will be tracked in
+ # Use persistent_ref.sha because it sometimes causes 'git fetch' to do
+ # less work. See
# https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746.
- #
- if Feature.enabled?(:scalability_ci_fetch_sha, type: :ops)
- # Use persistent_ref.sha because it causes 'git fetch' to do less work.
- # See https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746.
- "+#{pipeline.persistent_ref.sha}:#{pipeline.persistent_ref.path}"
- else
- "+#{pipeline.persistent_ref.path}:#{pipeline.persistent_ref.path}"
- end
+ "+#{pipeline.persistent_ref.sha}:#{pipeline.persistent_ref.path}"
end
def persistent_ref_exist?
diff --git a/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb b/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb
index 098e839132c..6312bd44118 100644
--- a/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb
+++ b/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb
@@ -2,7 +2,7 @@
module Ci
module PipelineArtifacts
- class CodeCoveragePresenter < ProcessablePresenter
+ class CodeCoveragePresenter < Gitlab::View::Presenter::Delegated
include Gitlab::Utils::StrongMemoize
def for_files(filenames)
diff --git a/app/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter.rb b/app/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter.rb
new file mode 100644
index 00000000000..2fe3104fe69
--- /dev/null
+++ b/app/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class CodeQualityMrDiffPresenter < Gitlab::View::Presenter::Delegated
+ include Gitlab::Utils::StrongMemoize
+
+ def for_files(filenames)
+ quality_files = raw_report["files"].select { |key| filenames.include?(key) }
+
+ { files: quality_files }
+ end
+
+ private
+
+ def raw_report
+ strong_memoize(:raw_report) do
+ self.each_blob do |blob|
+ Gitlab::Json.parse(blob).with_indifferent_access
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index f3bb63b31c3..0c68c33cbbe 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -11,6 +11,9 @@ module Ci
{ unknown_failure: 'Unknown pipeline failure!',
config_error: 'CI/CD YAML configuration error!',
external_validation_failure: 'External pipeline validation failed!',
+ activity_limit_exceeded: 'Pipeline activity limit exceeded!',
+ size_limit_exceeded: 'Pipeline size limit exceeded!',
+ job_activity_limit_exceeded: 'Pipeline job activity limit exceeded!',
deployments_limit_exceeded: 'Pipeline deployments limit exceeded!' }
end
diff --git a/app/presenters/dev_ops_score/metric_presenter.rb b/app/presenters/dev_ops_report/metric_presenter.rb
index e7363293435..e7363293435 100644
--- a/app/presenters/dev_ops_score/metric_presenter.rb
+++ b/app/presenters/dev_ops_report/metric_presenter.rb
diff --git a/app/presenters/gitlab/whats_new/item_presenter.rb b/app/presenters/gitlab/whats_new/item_presenter.rb
deleted file mode 100644
index 9f66e19ade0..00000000000
--- a/app/presenters/gitlab/whats_new/item_presenter.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module WhatsNew
- class ItemPresenter
- DICTIONARY = {
- core: 'Free',
- starter: 'Bronze',
- premium: 'Silver',
- ultimate: 'Gold'
- }.freeze
-
- def self.present(item)
- if Gitlab.com?
- item['packages'] = item['packages'].map { |p| DICTIONARY[p.downcase.to_sym] }
- end
-
- item
- end
- end
- end
-end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 55b550d8544..e13ef7a3811 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -17,7 +17,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
MAX_TOPICS_TO_SHOW = 3
def statistic_icon(icon_name = 'plus-square-o')
- sprite_icon(icon_name, css_class: 'icon gl-mr-2')
+ sprite_icon(icon_name, css_class: 'icon gl-mr-2 gl-text-gray-500')
end
def statistics_anchors(show_auto_devops_callout:)
@@ -239,7 +239,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
AnchorData.new(false,
statistic_icon + _('New file'),
new_file_path,
- 'missing')
+ 'dashed')
end
end
diff --git a/app/serializers/README.md b/app/serializers/README.md
index 89721f572e0..97e9625eb6f 100644
--- a/app/serializers/README.md
+++ b/app/serializers/README.md
@@ -99,7 +99,7 @@ create a JSON response according to your needs.
```ruby
class PipelineSerializer < BaseSerializer
- entity PipelineEntity
+ entity Ci::PipelineEntity
def represent_details(resource)
represent(resource, only: [:details])
diff --git a/app/serializers/admin/user_entity.rb b/app/serializers/admin/user_entity.rb
index ad96c101822..8908d610046 100644
--- a/app/serializers/admin/user_entity.rb
+++ b/app/serializers/admin/user_entity.rb
@@ -10,6 +10,7 @@ module Admin
expose :email
expose :last_activity_on
expose :avatar_url
+ expose :note
expose :badges do |user|
user_badges_in_admin_section(user)
end
diff --git a/app/serializers/admin/user_serializer.rb b/app/serializers/admin/user_serializer.rb
index 09036428bab..edd28e88553 100644
--- a/app/serializers/admin/user_serializer.rb
+++ b/app/serializers/admin/user_serializer.rb
@@ -2,6 +2,6 @@
module Admin
class UserSerializer < BaseSerializer
- entity UserEntity
+ entity Admin::UserEntity
end
end
diff --git a/app/serializers/base_discussion_entity.rb b/app/serializers/base_discussion_entity.rb
index 5ca4d1d6cc9..8d4c3906847 100644
--- a/app/serializers/base_discussion_entity.rb
+++ b/app/serializers/base_discussion_entity.rb
@@ -15,6 +15,7 @@ class BaseDiscussionEntity < Grape::Entity
expose :for_commit?, as: :for_commit
expose :individual_note?, as: :individual_note
expose :resolvable?, as: :resolvable
+ expose :resolved_by_push?, as: :resolved_by_push
expose :truncated_diff_lines, using: DiffLineEntity, if: -> (d, _) { d.diff_discussion? && d.on_text? && (d.expanded? || render_truncated_diff_lines?) }
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 2432a6a0e4d..ea72b2b89e7 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -9,7 +9,7 @@ class BuildDetailsEntity < JobEntity
expose :user, using: UserEntity
expose :runner, using: RunnerEntity
expose :metadata, using: BuildMetadataEntity
- expose :pipeline, using: PipelineEntity
+ expose :pipeline, using: Ci::PipelineEntity
expose :deployment_status, if: -> (*) { build.starts_environment? } do
expose :deployment_status, as: :status
diff --git a/app/serializers/ci/codequality_mr_diff_entity.rb b/app/serializers/ci/codequality_mr_diff_entity.rb
new file mode 100644
index 00000000000..99e7cc54017
--- /dev/null
+++ b/app/serializers/ci/codequality_mr_diff_entity.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Ci
+ class CodequalityMrDiffEntity < Grape::Entity
+ expose :files
+ end
+end
diff --git a/app/serializers/ci/codequality_mr_diff_report_serializer.rb b/app/serializers/ci/codequality_mr_diff_report_serializer.rb
new file mode 100644
index 00000000000..e9b51930b99
--- /dev/null
+++ b/app/serializers/ci/codequality_mr_diff_report_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Ci
+ class CodequalityMrDiffReportSerializer < BaseSerializer
+ entity CodequalityMrDiffEntity
+ end
+end
diff --git a/app/serializers/ci/pipeline_entity.rb b/app/serializers/ci/pipeline_entity.rb
new file mode 100644
index 00000000000..86f93929a5d
--- /dev/null
+++ b/app/serializers/ci/pipeline_entity.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+class Ci::PipelineEntity < Grape::Entity
+ include RequestAwareEntity
+ include Gitlab::Utils::StrongMemoize
+
+ delegate :name, :failure_reason, to: :presented_pipeline
+
+ expose :id
+ expose :user, using: UserEntity
+ expose :active?, as: :active
+
+ # Coverage isn't always necessary (e.g. when displaying project pipelines in
+ # the UI). Instead of creating an entirely different entity we just allow the
+ # disabling of this specific field whenever necessary.
+ expose :coverage, unless: proc { options[:disable_coverage] }
+ expose :source
+
+ expose :created_at, :updated_at
+
+ expose :path do |pipeline|
+ project_pipeline_path(pipeline.project, pipeline)
+ end
+
+ expose :flags do
+ expose :stuck?, as: :stuck
+ expose :auto_devops_source?, as: :auto_devops
+ expose :merge_request?, as: :merge_request
+ expose :has_yaml_errors?, as: :yaml_errors
+ expose :can_retry?, as: :retryable
+ expose :can_cancel?, as: :cancelable
+ expose :failure_reason?, as: :failure_reason
+ expose :detached_merge_request_pipeline?, as: :detached_merge_request_pipeline
+ expose :merge_request_pipeline?, as: :merge_request_pipeline
+ end
+
+ expose :details do
+ expose :detailed_status, as: :status, with: DetailedStatusEntity
+ expose :stages, using: StageEntity
+ expose :duration
+ expose :finished_at
+ expose :name
+ end
+
+ expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline|
+ pipeline.merge_request.present(current_user: request.current_user)
+ end
+
+ expose :ref do
+ expose :name do |pipeline|
+ pipeline.ref
+ end
+
+ expose :path do |pipeline|
+ if pipeline.ref
+ project_ref_path(pipeline.project, pipeline.ref)
+ end
+ end
+
+ expose :tag?, as: :tag
+ expose :branch?, as: :branch
+ expose :merge_request?, as: :merge_request
+ end
+
+ expose :commit, using: CommitEntity
+ expose :merge_request_event_type, if: -> (pipeline, _) { pipeline.merge_request? }
+ expose :source_sha, if: -> (pipeline, _) { pipeline.merge_request_pipeline? }
+ expose :target_sha, if: -> (pipeline, _) { pipeline.merge_request_pipeline? }
+ expose :yaml_errors, if: -> (pipeline, _) { pipeline.has_yaml_errors? }
+ expose :failure_reason, if: -> (pipeline, _) { pipeline.failure_reason? }
+
+ expose :retry_path, if: -> (*) { can_retry? } do |pipeline|
+ retry_project_pipeline_path(pipeline.project, pipeline)
+ end
+
+ expose :cancel_path, if: -> (*) { can_cancel? } do |pipeline|
+ cancel_project_pipeline_path(pipeline.project, pipeline)
+ end
+
+ expose :delete_path, if: -> (*) { can_delete? } do |pipeline|
+ project_pipeline_path(pipeline.project, pipeline)
+ end
+
+ expose :failed_builds, if: -> (*) { can_retry? }, using: JobEntity do |pipeline|
+ pipeline.failed_builds.each do |build|
+ build.project = pipeline.project
+ end
+ end
+
+ private
+
+ alias_method :pipeline, :object
+
+ def can_retry?
+ can?(request.current_user, :update_pipeline, pipeline) &&
+ pipeline.retryable?
+ end
+
+ def can_cancel?
+ can?(request.current_user, :update_pipeline, pipeline) &&
+ pipeline.cancelable?
+ end
+
+ def can_delete?
+ can?(request.current_user, :destroy_pipeline, pipeline)
+ end
+
+ def has_presentable_merge_request?
+ pipeline.merge_request? &&
+ can?(request.current_user, :read_merge_request, pipeline.merge_request)
+ end
+
+ def detailed_status
+ pipeline.detailed_status(request.current_user)
+ end
+
+ def presented_pipeline
+ strong_memoize(:presented_pipeline) do
+ pipeline.present
+ end
+ end
+end
+
+Ci::PipelineEntity.prepend_if_ee('EE::Ci::PipelineEntity')
diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb
index fcf6700cb59..ca2854224a7 100644
--- a/app/serializers/concerns/user_status_tooltip.rb
+++ b/app/serializers/concerns/user_status_tooltip.rb
@@ -16,6 +16,10 @@ module UserStatusTooltip
status_loaded? && show_status_emoji?(user.status)
end
+ expose :availability, if: -> (*) { status_loaded? } do |user|
+ user.status&.availability
+ end
+
private
def status_loaded?
diff --git a/app/serializers/diff_file_metadata_entity.rb b/app/serializers/diff_file_metadata_entity.rb
index 460f4967e99..70a5b266be1 100644
--- a/app/serializers/diff_file_metadata_entity.rb
+++ b/app/serializers/diff_file_metadata_entity.rb
@@ -7,6 +7,7 @@ class DiffFileMetadataEntity < Grape::Entity
expose :old_path
expose :new_file?, as: :new_file
expose :deleted_file?, as: :deleted_file
+ expose :submodule?, as: :submodule
expose :file_identifier_hash
expose :file_hash
end
diff --git a/app/serializers/diffs_entity.rb b/app/serializers/diffs_entity.rb
index f573bbe8385..4bc6644a5cb 100644
--- a/app/serializers/diffs_entity.rb
+++ b/app/serializers/diffs_entity.rb
@@ -79,7 +79,9 @@ class DiffsEntity < Grape::Entity
end
expose :definition_path_prefix do |diffs|
- project_blob_path(merge_request.project, diffs.diff_refs&.head_sha)
+ next unless merge_request.diff_head_sha
+
+ project_blob_path(merge_request.project, merge_request.diff_head_sha)
end
def merge_request
diff --git a/app/serializers/group_child_entity.rb b/app/serializers/group_child_entity.rb
index a7fe4d3f9b9..adbda790dee 100644
--- a/app/serializers/group_child_entity.rb
+++ b/app/serializers/group_child_entity.rb
@@ -20,7 +20,7 @@ class GroupChildEntity < Grape::Entity
# We know `type` will be one either `project` or `group`.
# The `edit_polymorphic_path` helper would try to call the path helper
# with a plural: `edit_groups_path(instance)` or `edit_projects_path(instance)`
- # while our methods are `edit_group_path` or `edit_group_path`
+ # while our methods are `edit_group_path` or `edit_project_path`
public_send("edit_#{type}_path", instance) # rubocop:disable GitlabSecurity/PublicSend
end
diff --git a/app/serializers/group_group_link_entity.rb b/app/serializers/group_group_link_entity.rb
deleted file mode 100644
index 1e736214f54..00000000000
--- a/app/serializers/group_group_link_entity.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-class GroupGroupLinkEntity < Grape::Entity
- include RequestAwareEntity
-
- expose :id
- expose :created_at
- expose :expires_at do |group_link|
- group_link.expires_at&.to_time
- end
-
- expose :can_update do |group_link|
- can_manage?(group_link)
- end
-
- expose :can_remove do |group_link|
- can_manage?(group_link)
- end
-
- expose :access_level do
- expose :human_access, as: :string_value
- expose :group_access, as: :integer_value
- end
-
- expose :valid_roles do |group_link|
- group_link.class.access_options
- end
-
- expose :shared_with_group do
- expose :avatar_url do |group_link|
- group_link.shared_with_group.avatar_url(only_path: false)
- end
-
- expose :web_url do |group_link|
- group_link.shared_with_group.web_url
- end
-
- expose :shared_with_group, merge: true, using: GroupBasicEntity
- end
-
- private
-
- def current_user
- options[:current_user]
- end
-
- def can_manage?(group_link)
- can?(current_user, :admin_group_member, group_link.shared_group)
- end
-end
diff --git a/app/serializers/group_group_link_serializer.rb b/app/serializers/group_group_link_serializer.rb
deleted file mode 100644
index 6ae8daf9207..00000000000
--- a/app/serializers/group_group_link_serializer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class GroupGroupLinkSerializer < BaseSerializer
- entity GroupGroupLinkEntity
-end
diff --git a/app/serializers/group_link/group_group_link_entity.rb b/app/serializers/group_link/group_group_link_entity.rb
new file mode 100644
index 00000000000..cedc8bd8582
--- /dev/null
+++ b/app/serializers/group_link/group_group_link_entity.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module GroupLink
+ class GroupGroupLinkEntity < GroupLink::GroupLinkEntity
+ include RequestAwareEntity
+
+ expose :can_update do |group_link|
+ can_manage?(group_link)
+ end
+
+ expose :can_remove do |group_link|
+ can_manage?(group_link)
+ end
+
+ private
+
+ def current_user
+ options[:current_user]
+ end
+
+ def can_manage?(group_link)
+ can?(current_user, :admin_group_member, group_link.shared_group)
+ end
+ end
+end
diff --git a/app/serializers/group_link/group_group_link_serializer.rb b/app/serializers/group_link/group_group_link_serializer.rb
new file mode 100644
index 00000000000..1e3f861f09a
--- /dev/null
+++ b/app/serializers/group_link/group_group_link_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module GroupLink
+ class GroupGroupLinkSerializer < BaseSerializer
+ entity GroupLink::GroupGroupLinkEntity
+ end
+end
diff --git a/app/serializers/group_link/group_link_entity.rb b/app/serializers/group_link/group_link_entity.rb
new file mode 100644
index 00000000000..12349320b6f
--- /dev/null
+++ b/app/serializers/group_link/group_link_entity.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module GroupLink
+ class GroupLinkEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :created_at
+ expose :expires_at do |group_link|
+ group_link.expires_at&.to_time
+ end
+
+ expose :access_level do
+ expose :human_access, as: :string_value
+ expose :group_access, as: :integer_value
+ end
+
+ expose :valid_roles do |group_link|
+ group_link.class.access_options
+ end
+
+ expose :shared_with_group do
+ expose :avatar_url do |group_link|
+ group_link.shared_with_group.avatar_url(only_path: false, size: Member::AVATAR_SIZE)
+ end
+
+ expose :web_url do |group_link|
+ group_link.shared_with_group.web_url
+ end
+
+ expose :shared_with_group, merge: true, using: GroupBasicEntity
+ end
+ end
+end
diff --git a/app/serializers/group_link/project_group_link_entity.rb b/app/serializers/group_link/project_group_link_entity.rb
new file mode 100644
index 00000000000..2ff275fff01
--- /dev/null
+++ b/app/serializers/group_link/project_group_link_entity.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module GroupLink
+ class ProjectGroupLinkEntity < GroupLink::GroupLinkEntity
+ include RequestAwareEntity
+ include Projects::ProjectMembersHelper
+
+ expose :can_update do |group_link|
+ can_manage_project_members?(group_link.project)
+ end
+
+ expose :can_remove do |group_link|
+ can_manage_project_members?(group_link.project)
+ end
+
+ private
+
+ def current_user
+ options[:current_user]
+ end
+ end
+end
diff --git a/app/serializers/group_link/project_group_link_serializer.rb b/app/serializers/group_link/project_group_link_serializer.rb
new file mode 100644
index 00000000000..b2559e61e31
--- /dev/null
+++ b/app/serializers/group_link/project_group_link_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module GroupLink
+ class ProjectGroupLinkSerializer < BaseSerializer
+ entity GroupLink::ProjectGroupLinkEntity
+ end
+end
diff --git a/app/serializers/member_entity.rb b/app/serializers/member_entity.rb
index 584ba4c62de..e8f2bb28d60 100644
--- a/app/serializers/member_entity.rb
+++ b/app/serializers/member_entity.rb
@@ -23,6 +23,10 @@ class MemberEntity < Grape::Entity
member.can_remove?
end
+ expose :is_direct_member do |member, options|
+ member.source == options[:source]
+ end
+
expose :access_level do
expose :human_access, as: :string_value
expose :access_level, as: :integer_value
diff --git a/app/serializers/merge_request_basic_entity.rb b/app/serializers/merge_request_basic_entity.rb
index 9e2bce53c8a..7d45484fc2f 100644
--- a/app/serializers/merge_request_basic_entity.rb
+++ b/app/serializers/merge_request_basic_entity.rb
@@ -10,7 +10,7 @@ class MergeRequestBasicEntity < Grape::Entity
expose :milestone, using: API::Entities::Milestone
expose :labels, using: LabelEntity
expose :assignees, using: API::Entities::UserBasic
- expose :reviewers, if: -> (m) { m.allows_reviewers? }, using: API::Entities::UserBasic
+ expose :reviewers, using: API::Entities::UserBasic
expose :task_status, :task_status_short
expose :lock_version, :lock_version
end
diff --git a/app/serializers/merge_request_sidebar_extras_entity.rb b/app/serializers/merge_request_sidebar_extras_entity.rb
index 261b6e8e519..1a0111fe5d0 100644
--- a/app/serializers/merge_request_sidebar_extras_entity.rb
+++ b/app/serializers/merge_request_sidebar_extras_entity.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
class MergeRequestSidebarExtrasEntity < IssuableSidebarExtrasEntity
- expose :assignees do |merge_request|
- MergeRequestUserEntity.represent(merge_request.assignees, merge_request: merge_request)
+ expose :assignees do |merge_request, options|
+ MergeRequestUserEntity.represent(merge_request.assignees, options.merge(merge_request: merge_request))
end
- expose :reviewers, if: -> (m) { m.allows_reviewers? } do |merge_request|
- MergeRequestUserEntity.represent(merge_request.reviewers, merge_request: merge_request)
+ expose :reviewers do |merge_request, options|
+ MergeRequestUserEntity.represent(merge_request.reviewers, options.merge(merge_request: merge_request))
end
end
diff --git a/app/serializers/merge_request_user_entity.rb b/app/serializers/merge_request_user_entity.rb
index 604c9cabd50..edb7e10bac5 100644
--- a/app/serializers/merge_request_user_entity.rb
+++ b/app/serializers/merge_request_user_entity.rb
@@ -1,9 +1,22 @@
# frozen_string_literal: true
class MergeRequestUserEntity < ::API::Entities::UserBasic
+ include UserStatusTooltip
+ include RequestAwareEntity
+
expose :can_merge do |reviewer, options|
options[:merge_request]&.can_be_merged_by?(reviewer)
end
+
+ expose :can_update_merge_request do |reviewer, options|
+ request.current_user&.can?(:update_merge_request, options[:merge_request])
+ end
+
+ expose :reviewed, if: -> (_, options) { options[:merge_request] && options[:merge_request].allows_reviewers? } do |reviewer, options|
+ reviewer = options[:merge_request].find_reviewer(reviewer)
+
+ reviewer&.reviewed?
+ end
end
MergeRequestUserEntity.prepend_if_ee('EE::MergeRequestUserEntity')
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index ca4e16bc5ff..560dd2ea08b 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -133,6 +133,10 @@ class MergeRequestWidgetEntity < Grape::Entity
help_page_path('user/application_security/index.md', anchor: 'viewing-security-scan-information-in-merge-requests')
end
+ expose :enabled_reports do |merge_request|
+ merge_request.enabled_reports
+ end
+
private
delegate :current_user, to: :request
diff --git a/app/serializers/pipeline_details_entity.rb b/app/serializers/pipeline_details_entity.rb
index e53fa7873ac..4fec543eca8 100644
--- a/app/serializers/pipeline_details_entity.rb
+++ b/app/serializers/pipeline_details_entity.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class PipelineDetailsEntity < PipelineEntity
+class PipelineDetailsEntity < Ci::PipelineEntity
expose :project, using: ProjectEntity
expose :flags do
diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb
deleted file mode 100644
index 2d278f0e30d..00000000000
--- a/app/serializers/pipeline_entity.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-# frozen_string_literal: true
-
-class PipelineEntity < Grape::Entity
- include RequestAwareEntity
- include Gitlab::Utils::StrongMemoize
-
- delegate :name, :failure_reason, to: :presented_pipeline
-
- expose :id
- expose :user, using: UserEntity
- expose :active?, as: :active
-
- # Coverage isn't always necessary (e.g. when displaying project pipelines in
- # the UI). Instead of creating an entirely different entity we just allow the
- # disabling of this specific field whenever necessary.
- expose :coverage, unless: proc { options[:disable_coverage] }
- expose :source
-
- expose :created_at, :updated_at
-
- expose :path do |pipeline|
- project_pipeline_path(pipeline.project, pipeline)
- end
-
- expose :flags do
- expose :stuck?, as: :stuck
- expose :auto_devops_source?, as: :auto_devops
- expose :merge_request?, as: :merge_request
- expose :has_yaml_errors?, as: :yaml_errors
- expose :can_retry?, as: :retryable
- expose :can_cancel?, as: :cancelable
- expose :failure_reason?, as: :failure_reason
- expose :detached_merge_request_pipeline?, as: :detached_merge_request_pipeline
- expose :merge_request_pipeline?, as: :merge_request_pipeline
- end
-
- expose :details do
- expose :detailed_status, as: :status, with: DetailedStatusEntity
- expose :stages, using: StageEntity
- expose :duration
- expose :finished_at
- expose :name
- end
-
- expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline|
- pipeline.merge_request.present(current_user: request.current_user)
- end
-
- expose :ref do
- expose :name do |pipeline|
- pipeline.ref
- end
-
- expose :path do |pipeline|
- if pipeline.ref
- project_ref_path(pipeline.project, pipeline.ref)
- end
- end
-
- expose :tag?, as: :tag
- expose :branch?, as: :branch
- expose :merge_request?, as: :merge_request
- end
-
- expose :commit, using: CommitEntity
- expose :merge_request_event_type, if: -> (pipeline, _) { pipeline.merge_request? }
- expose :source_sha, if: -> (pipeline, _) { pipeline.merge_request_pipeline? }
- expose :target_sha, if: -> (pipeline, _) { pipeline.merge_request_pipeline? }
- expose :yaml_errors, if: -> (pipeline, _) { pipeline.has_yaml_errors? }
- expose :failure_reason, if: -> (pipeline, _) { pipeline.failure_reason? }
-
- expose :retry_path, if: -> (*) { can_retry? } do |pipeline|
- retry_project_pipeline_path(pipeline.project, pipeline)
- end
-
- expose :cancel_path, if: -> (*) { can_cancel? } do |pipeline|
- cancel_project_pipeline_path(pipeline.project, pipeline)
- end
-
- expose :delete_path, if: -> (*) { can_delete? } do |pipeline|
- project_pipeline_path(pipeline.project, pipeline)
- end
-
- expose :failed_builds, if: -> (*) { can_retry? }, using: JobEntity do |pipeline|
- pipeline.failed_builds.each do |build|
- build.project = pipeline.project
- end
- end
-
- private
-
- alias_method :pipeline, :object
-
- def can_retry?
- can?(request.current_user, :update_pipeline, pipeline) &&
- pipeline.retryable?
- end
-
- def can_cancel?
- can?(request.current_user, :update_pipeline, pipeline) &&
- pipeline.cancelable?
- end
-
- def can_delete?
- can?(request.current_user, :destroy_pipeline, pipeline)
- end
-
- def has_presentable_merge_request?
- pipeline.merge_request? &&
- can?(request.current_user, :read_merge_request, pipeline.merge_request)
- end
-
- def detailed_status
- pipeline.detailed_status(request.current_user)
- end
-
- def presented_pipeline
- strong_memoize(:presented_pipeline) do
- pipeline.present
- end
- end
-end
diff --git a/app/services/alert_management/http_integrations/update_service.rb b/app/services/alert_management/http_integrations/update_service.rb
index 220c4e759f0..af079f670b8 100644
--- a/app/services/alert_management/http_integrations/update_service.rb
+++ b/app/services/alert_management/http_integrations/update_service.rb
@@ -9,7 +9,7 @@ module AlertManagement
def initialize(integration, current_user, params)
@integration = integration
@current_user = current_user
- @params = params
+ @params = params.with_indifferent_access
end
def execute
@@ -17,7 +17,7 @@ module AlertManagement
params[:token] = nil if params.delete(:regenerate_token)
- if integration.update(params)
+ if integration.update(permitted_params)
success
else
error(integration.errors.full_messages.to_sentence)
@@ -32,6 +32,15 @@ module AlertManagement
current_user&.can?(:admin_operations, integration)
end
+ def permitted_params
+ params.slice(*permitted_params_keys)
+ end
+
+ # overriden in EE
+ def permitted_params_keys
+ %i[name active token]
+ end
+
def error(message)
ServiceResponse.error(message: message)
end
@@ -46,3 +55,5 @@ module AlertManagement
end
end
end
+
+::AlertManagement::HttpIntegrations::UpdateService.prepend_if_ee('::EE::AlertManagement::HttpIntegrations::UpdateService')
diff --git a/app/services/alert_management/process_prometheus_alert_service.rb b/app/services/alert_management/process_prometheus_alert_service.rb
index 753162bfdbf..0591376bcdf 100644
--- a/app/services/alert_management/process_prometheus_alert_service.rb
+++ b/app/services/alert_management/process_prometheus_alert_service.rb
@@ -2,9 +2,8 @@
module AlertManagement
class ProcessPrometheusAlertService
- include BaseServiceUtility
- include Gitlab::Utils::StrongMemoize
- include ::IncidentManagement::Settings
+ extend ::Gitlab::Utils::Override
+ include ::AlertManagement::AlertProcessing
def initialize(project, payload)
@project = project
@@ -14,11 +13,10 @@ module AlertManagement
def execute
return bad_request unless incoming_payload.has_required_attributes?
- process_alert_management_alert
+ process_alert
return bad_request unless alert.persisted?
- process_incident_issues if process_issues?
- send_alert_email if send_email?
+ complete_post_processing_tasks
ServiceResponse.success
end
@@ -27,110 +25,14 @@ module AlertManagement
attr_reader :project, :payload
- def process_alert_management_alert
- if incoming_payload.resolved?
- process_resolved_alert_management_alert
- else
- process_firing_alert_management_alert
- end
- end
-
- def process_firing_alert_management_alert
- if alert.persisted?
- alert.register_new_event!
- reset_alert_management_alert_status
- else
- create_alert_management_alert
- end
- end
-
- def reset_alert_management_alert_status
- return if alert.trigger
-
- logger.warn(
- message: 'Unable to update AlertManagement::Alert status to triggered',
- project_id: project.id,
- alert_id: alert.id
- )
- end
-
- def create_alert_management_alert
- if alert.save
- alert.execute_services
- SystemNoteService.create_new_alert(alert, Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus])
- return
- end
-
- logger.warn(
- message: 'Unable to create AlertManagement::Alert',
- project_id: project.id,
- alert_errors: alert.errors.messages
- )
- end
-
- def process_resolved_alert_management_alert
- return unless alert.persisted?
- return unless auto_close_incident?
-
- if alert.resolve(incoming_payload.ends_at)
- close_issue(alert.issue)
- return
- end
-
- logger.warn(
- message: 'Unable to update AlertManagement::Alert status to resolved',
- project_id: project.id,
- alert_id: alert.id
- )
- end
-
- def close_issue(issue)
- return if issue.blank? || issue.closed?
-
- Issues::CloseService
- .new(project, User.alert_bot)
- .execute(issue, system_note: false)
+ override :process_new_alert
+ def process_new_alert
+ return if resolving_alert?
- SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
- end
-
- def process_incident_issues
- return if alert.issue || alert.resolved?
-
- IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
- end
-
- def send_alert_email
- notification_service
- .async
- .prometheus_alerts_fired(project, [alert])
- end
-
- def logger
- @logger ||= Gitlab::AppLogger
- end
-
- def alert
- strong_memoize(:alert) do
- existing_alert || new_alert
- end
- end
-
- def existing_alert
- strong_memoize(:existing_alert) do
- AlertManagement::Alert.not_resolved.for_fingerprint(project, incoming_payload.gitlab_fingerprint).first
- end
- end
-
- def new_alert
- strong_memoize(:new_alert) do
- AlertManagement::Alert.new(
- **incoming_payload.alert_params,
- ended_at: nil
- )
- end
+ super
end
+ override :incoming_payload
def incoming_payload
strong_memoize(:incoming_payload) do
Gitlab::AlertManagement::Payload.parse(
@@ -141,6 +43,11 @@ module AlertManagement
end
end
+ override :resolving_alert?
+ def resolving_alert?
+ incoming_payload.resolved?
+ end
+
def bad_request
ServiceResponse.error(message: 'Bad Request', http_status: :bad_request)
end
diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb
index 7792b811b4e..5e5c8ae2177 100644
--- a/app/services/application_settings/update_service.rb
+++ b/app/services/application_settings/update_service.rb
@@ -6,7 +6,7 @@ module ApplicationSettings
attr_reader :params, :application_setting
- MARKDOWN_CACHE_INVALIDATING_PARAMS = %w(asset_proxy_enabled asset_proxy_url asset_proxy_secret_key asset_proxy_whitelist).freeze
+ MARKDOWN_CACHE_INVALIDATING_PARAMS = %w(asset_proxy_enabled asset_proxy_url asset_proxy_secret_key asset_proxy_allowlist).freeze
def execute
result = update_settings
diff --git a/app/services/authorized_project_update/recalculate_for_user_range_service.rb b/app/services/authorized_project_update/recalculate_for_user_range_service.rb
index 14b0f5d6117..f300c45f019 100644
--- a/app/services/authorized_project_update/recalculate_for_user_range_service.rb
+++ b/app/services/authorized_project_update/recalculate_for_user_range_service.rb
@@ -9,7 +9,7 @@ module AuthorizedProjectUpdate
def execute
User.where(id: start_user_id..end_user_id).select(:id).find_each do |user| # rubocop: disable CodeReuse/ActiveRecord
- Users::RefreshAuthorizedProjectsService.new(user).execute
+ Users::RefreshAuthorizedProjectsService.new(user, source: self.class.name).execute
end
end
diff --git a/app/services/boards/create_service.rb b/app/services/boards/create_service.rb
index 2ccaea64d14..54dab581686 100644
--- a/app/services/boards/create_service.rb
+++ b/app/services/boards/create_service.rb
@@ -13,11 +13,11 @@ module Boards
private
def can_create_board?
- parent.boards.empty? || parent.multiple_issue_boards_available?
+ parent_board_collection.empty? || parent.multiple_issue_boards_available?
end
def create_board!
- board = parent.boards.create(params)
+ board = parent_board_collection.create(params)
unless board.persisted?
return ServiceResponse.error(message: "There was an error when creating a board.", payload: board)
@@ -30,6 +30,10 @@ module Boards
ServiceResponse.success(payload: board)
end
+
+ def parent_board_collection
+ parent.boards
+ end
end
end
diff --git a/app/services/boards/list_service.rb b/app/services/boards/list_service.rb
index 729bca6580e..80ceb91f56d 100644
--- a/app/services/boards/list_service.rb
+++ b/app/services/boards/list_service.rb
@@ -2,9 +2,7 @@
module Boards
class ListService < Boards::BaseService
- def execute(create_default_board: true)
- create_board! if create_default_board && parent.boards.empty?
-
+ def execute
find_boards
end
@@ -18,10 +16,6 @@ module Boards
parent.boards.first_board
end
- def create_board!
- Boards::CreateService.new(parent, current_user).execute
- end
-
def find_boards
found =
if parent.multiple_issue_boards_available?
diff --git a/app/services/boards/lists/base_create_service.rb b/app/services/boards/lists/base_create_service.rb
new file mode 100644
index 00000000000..8399b1cc149
--- /dev/null
+++ b/app/services/boards/lists/base_create_service.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Boards
+ module Lists
+ # This class is used by issue and epic board lists
+ # for creating new list
+ class BaseCreateService < Boards::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute(board)
+ list = case type
+ when :backlog
+ create_backlog(board)
+ else
+ target = target(board)
+ position = next_position(board)
+
+ return ServiceResponse.error(message: _('%{board_target} not found') % { board_target: type.to_s.capitalize }) if target.blank?
+
+ create_list(board, type, target, position)
+ end
+
+ return ServiceResponse.error(message: list.errors.full_messages) unless list.persisted?
+
+ ServiceResponse.success(payload: { list: list })
+ end
+
+ private
+
+ def type
+ # We don't ever expect to have more than one list
+ # type param at once.
+ if params.key?('backlog')
+ :backlog
+ else
+ :label
+ end
+ end
+
+ def target(board)
+ strong_memoize(:target) do
+ available_labels.find_by(id: params[:label_id]) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+
+ def available_labels
+ ::Labels::AvailableLabelsService.new(current_user, parent, {})
+ .available_labels
+ end
+
+ def next_position(board)
+ max_position = board.lists.movable.maximum(:position)
+ max_position.nil? ? 0 : max_position.succ
+ end
+
+ def create_list(board, type, target, position)
+ board.lists.create(create_list_attributes(type, target, position))
+ end
+
+ def create_list_attributes(type, target, position)
+ { type => target, list_type: type, position: position }
+ end
+
+ def create_backlog(board)
+ return board.lists.backlog.first if board.lists.backlog.exists?
+
+ board.lists.create(list_type: :backlog, position: nil)
+ end
+ end
+ end
+end
diff --git a/app/services/boards/lists/create_service.rb b/app/services/boards/lists/create_service.rb
index a21ceee083f..37fe0a815bd 100644
--- a/app/services/boards/lists/create_service.rb
+++ b/app/services/boards/lists/create_service.rb
@@ -2,68 +2,7 @@
module Boards
module Lists
- class CreateService < Boards::BaseService
- include Gitlab::Utils::StrongMemoize
-
- def execute(board)
- list = case type
- when :backlog
- create_backlog(board)
- else
- target = target(board)
- position = next_position(board)
-
- return ServiceResponse.error(message: _('%{board_target} not found') % { board_target: type.to_s.capitalize }) if target.blank?
-
- create_list(board, type, target, position)
- end
-
- return ServiceResponse.error(message: list.errors.full_messages) unless list.persisted?
-
- ServiceResponse.success(payload: { list: list })
- end
-
- private
-
- def type
- # We don't ever expect to have more than one list
- # type param at once.
- if params.key?('backlog')
- :backlog
- else
- :label
- end
- end
-
- def target(board)
- strong_memoize(:target) do
- available_labels.find_by(id: params[:label_id]) # rubocop: disable CodeReuse/ActiveRecord
- end
- end
-
- def available_labels
- ::Labels::AvailableLabelsService.new(current_user, parent, {})
- .available_labels
- end
-
- def next_position(board)
- max_position = board.lists.movable.maximum(:position)
- max_position.nil? ? 0 : max_position.succ
- end
-
- def create_list(board, type, target, position)
- board.lists.create(create_list_attributes(type, target, position))
- end
-
- def create_list_attributes(type, target, position)
- { type => target, list_type: type, position: position }
- end
-
- def create_backlog(board)
- return board.lists.backlog.first if board.lists.backlog.exists?
-
- board.lists.create(list_type: :backlog, position: nil)
- end
+ class CreateService < Boards::Lists::BaseCreateService
end
end
end
diff --git a/app/services/boards/visits/create_service.rb b/app/services/boards/visits/create_service.rb
index e2adf755511..428ed1a8bcc 100644
--- a/app/services/boards/visits/create_service.rb
+++ b/app/services/boards/visits/create_service.rb
@@ -5,6 +5,7 @@ module Boards
class CreateService < Boards::BaseService
def execute(board)
return unless current_user && Gitlab::Database.read_write?
+ return unless board.is_a?(Board) # other board types do not support board visits yet
if parent.is_a?(Group)
BoardGroupRecentVisit.visited!(current_user, board)
diff --git a/app/services/bulk_create_integration_service.rb b/app/services/bulk_create_integration_service.rb
index df78c3645c7..ae756d0856e 100644
--- a/app/services/bulk_create_integration_service.rb
+++ b/app/services/bulk_create_integration_service.rb
@@ -11,8 +11,6 @@ class BulkCreateIntegrationService
service_list = ServiceList.new(batch, service_hash, association).to_array
Service.transaction do
- run_callbacks(batch) if association == 'project'
-
results = bulk_insert(*service_list)
if integration.data_fields_present?
@@ -33,14 +31,6 @@ class BulkCreateIntegrationService
klass.insert_all(items_to_insert, returning: [:id])
end
- # rubocop: disable CodeReuse/ActiveRecord
- def run_callbacks(batch)
- if integration.external_issue_tracker?
- Project.where(id: batch.select(:id)).update_all(has_external_issue_tracker: true)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
def service_hash
if integration.template?
integration.to_service_hash
diff --git a/app/services/bulk_import_service.rb b/app/services/bulk_import_service.rb
index bebf9153ce7..29439a79afe 100644
--- a/app/services/bulk_import_service.rb
+++ b/app/services/bulk_import_service.rb
@@ -38,6 +38,8 @@ class BulkImportService
bulk_import = create_bulk_import
BulkImportWorker.perform_async(bulk_import.id)
+
+ bulk_import
end
private
diff --git a/app/services/captcha/captcha_verification_service.rb b/app/services/captcha/captcha_verification_service.rb
new file mode 100644
index 00000000000..45a5a52367c
--- /dev/null
+++ b/app/services/captcha/captcha_verification_service.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Captcha
+ ##
+ # Encapsulates logic of checking captchas.
+ #
+ class CaptchaVerificationService
+ include Recaptcha::Verify
+
+ ##
+ # Performs verification of a captcha response.
+ #
+ # 'captcha_response' parameter is the response from the user solving a client-side captcha.
+ #
+ # 'request' parameter is the request which submitted the captcha.
+ #
+ # NOTE: Currently only supports reCAPTCHA, and is not yet used in all places of the app in which
+ # captchas are verified, but these can be addressed in future MRs. See:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/273480
+ def execute(captcha_response: nil, request:)
+ return false unless captcha_response
+
+ @request = request
+
+ Gitlab::Recaptcha.load_configurations!
+
+ # NOTE: We could pass the model and let the recaptcha gem automatically add errors to it,
+ # but we do not, for two reasons:
+ #
+ # 1. We want control over when the errors are added
+ # 2. We want control over the wording and i18n of the message
+ # 3. We want a consistent interface and behavior when adding support for other captcha
+ # libraries which may not support automatically adding errors to the model.
+ verify_recaptcha(response: captcha_response)
+ end
+
+ private
+
+ # The recaptcha library's Recaptcha::Verify#verify_recaptcha method requires that
+ # 'request' be a readable attribute - it doesn't support passing it as an options argument.
+ attr_reader :request
+ end
+end
diff --git a/app/services/ci/create_job_artifacts_service.rb b/app/services/ci/create_job_artifacts_service.rb
index 5efb3805bf7..f1fdc8e2490 100644
--- a/app/services/ci/create_job_artifacts_service.rb
+++ b/app/services/ci/create_job_artifacts_service.rb
@@ -7,6 +7,7 @@ module Ci
ArtifactsExistError = Class.new(StandardError)
LSIF_ARTIFACT_TYPE = 'lsif'
+ METRICS_REPORT_UPLOAD_EVENT_NAME = 'i_testing_metrics_report_artifact_uploaders'
OBJECT_STORAGE_ERRORS = [
Errno::EIO,
@@ -42,6 +43,8 @@ module Ci
artifact, artifact_metadata = build_artifact(artifacts_file, params, metadata_file)
result = parse_artifact(artifact)
+ track_artifact_uploader(artifact)
+
return result unless result[:status] == :success
persist_artifact(artifact, artifact_metadata, params)
@@ -152,6 +155,12 @@ module Ci
)
end
+ def track_artifact_uploader(artifact)
+ return unless artifact.file_type == 'metrics'
+
+ track_usage_event(METRICS_REPORT_UPLOAD_EVENT_NAME, @job.user_id)
+ end
+
def parse_dotenv_artifact(artifact)
Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact)
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index d3001e54288..dc42411dfa1 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -123,7 +123,6 @@ module Ci
def record_conversion_event
Experiments::RecordConversionEventWorker.perform_async(:ci_syntax_templates, current_user.id)
- Experiments::RecordConversionEventWorker.perform_async(:pipelines_empty_state, current_user.id)
end
def create_namespace_onboarding_action
diff --git a/app/services/ci/daily_build_group_report_result_service.rb b/app/services/ci/daily_build_group_report_result_service.rb
index bc966fb9634..820e6e08fc5 100644
--- a/app/services/ci/daily_build_group_report_result_service.rb
+++ b/app/services/ci/daily_build_group_report_result_service.rb
@@ -14,7 +14,8 @@ module Ci
ref_path: pipeline.source_ref_path,
date: pipeline.created_at.to_date,
last_pipeline_id: pipeline.id,
- default_branch: pipeline.default_branch?
+ default_branch: pipeline.default_branch?,
+ group_id: pipeline.project&.group&.id
}
aggregate(pipeline.builds.with_coverage).map do |group_name, group|
diff --git a/app/services/ci/generate_codequality_mr_diff_report_service.rb b/app/services/ci/generate_codequality_mr_diff_report_service.rb
new file mode 100644
index 00000000000..3b1bd319a4f
--- /dev/null
+++ b/app/services/ci/generate_codequality_mr_diff_report_service.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Ci
+ # TODO: a couple of points with this approach:
+ # + reuses existing architecture and reactive caching
+ # - it's not a report comparison and some comparing features must be turned off.
+ # see CompareReportsBaseService for more notes.
+ # issue: https://gitlab.com/gitlab-org/gitlab/issues/34224
+ class GenerateCodequalityMrDiffReportService < CompareReportsBaseService
+ def execute(base_pipeline, head_pipeline)
+ merge_request = MergeRequest.find_by_id(params[:id])
+ {
+ status: :parsed,
+ key: key(base_pipeline, head_pipeline),
+ data: head_pipeline.pipeline_artifacts.find_by_file_type(:code_quality_mr_diff).present.for_files(merge_request.new_paths)
+ }
+ rescue => e
+ Gitlab::ErrorTracking.track_exception(e, project_id: project.id)
+ {
+ status: :error,
+ key: key(base_pipeline, head_pipeline),
+ status_reason: _('An error occurred while fetching codequality mr diff reports.')
+ }
+ end
+
+ def latest?(base_pipeline, head_pipeline, data)
+ data&.fetch(:key, nil) == key(base_pipeline, head_pipeline)
+ end
+ end
+end
diff --git a/app/services/ci/generate_coverage_reports_service.rb b/app/services/ci/generate_coverage_reports_service.rb
index 063fb966183..b3aa7b3091b 100644
--- a/app/services/ci/generate_coverage_reports_service.rb
+++ b/app/services/ci/generate_coverage_reports_service.rb
@@ -12,7 +12,7 @@ module Ci
{
status: :parsed,
key: key(base_pipeline, head_pipeline),
- data: head_pipeline.pipeline_artifacts.find_with_code_coverage.present.for_files(merge_request.new_paths)
+ data: head_pipeline.pipeline_artifacts.find_by_file_type(:code_coverage).present.for_files(merge_request.new_paths)
}
rescue => e
Gitlab::ErrorTracking.track_exception(e, project_id: project.id)
diff --git a/app/services/ci/pipeline_artifacts/coverage_report_service.rb b/app/services/ci/pipeline_artifacts/coverage_report_service.rb
index 9f5c445c91a..8209639fa22 100644
--- a/app/services/ci/pipeline_artifacts/coverage_report_service.rb
+++ b/app/services/ci/pipeline_artifacts/coverage_report_service.rb
@@ -11,7 +11,7 @@ module Ci
pipeline.pipeline_artifacts.create!(
project_id: pipeline.project_id,
file_type: :code_coverage,
- file_format: :raw,
+ file_format: Ci::PipelineArtifact::REPORT_TYPES.fetch(:code_coverage),
size: file["tempfile"].size,
file: file,
expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now
diff --git a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb
new file mode 100644
index 00000000000..5c52eef7ba6
--- /dev/null
+++ b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+module Ci
+ module PipelineArtifacts
+ class CreateCodeQualityMrDiffReportService
+ def execute(pipeline)
+ return unless pipeline.can_generate_codequality_reports?
+ return if pipeline.has_codequality_mr_diff_report?
+
+ file = build_carrierwave_file(pipeline)
+
+ pipeline.pipeline_artifacts.create!(
+ project_id: pipeline.project_id,
+ file_type: :code_quality_mr_diff,
+ file_format: Ci::PipelineArtifact::REPORT_TYPES.fetch(:code_quality_mr_diff),
+ size: file["tempfile"].size,
+ file: file,
+ expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now
+ )
+ end
+
+ private
+
+ def build_carrierwave_file(pipeline)
+ CarrierWaveStringFile.new_file(
+ file_content: build_quality_mr_diff_report(pipeline),
+ filename: Ci::PipelineArtifact::DEFAULT_FILE_NAMES.fetch(:code_quality_mr_diff),
+ content_type: 'application/json'
+ )
+ end
+
+ def build_quality_mr_diff_report(pipeline)
+ mr_diff_report = Gitlab::Ci::Reports::CodequalityMrDiff.new(pipeline.codequality_reports)
+
+ Ci::CodequalityMrDiffReportSerializer.new.represent(mr_diff_report).to_json # rubocop: disable CodeReuse/Serializer
+ end
+ end
+ end
+end
diff --git a/app/services/ci/pipeline_trigger_service.rb b/app/services/ci/pipeline_trigger_service.rb
index a31f5e9056e..dbbaefb2b2f 100644
--- a/app/services/ci/pipeline_trigger_service.rb
+++ b/app/services/ci/pipeline_trigger_service.rb
@@ -17,6 +17,9 @@ module Ci
private
+ PAYLOAD_VARIABLE_KEY = 'TRIGGER_PAYLOAD'
+ PAYLOAD_VARIABLE_HIDDEN_PARAMS = %i(token).freeze
+
def create_pipeline_from_trigger(trigger)
# this check is to not leak the presence of the project if user cannot read it
return unless trigger.project == project
@@ -70,9 +73,23 @@ module Ci
end
def variables
+ if ::Feature.enabled?(:ci_trigger_payload_into_pipeline, project, default_enabled: :yaml)
+ param_variables + [payload_variable]
+ else
+ param_variables
+ end
+ end
+
+ def param_variables
params[:variables].to_h.map do |key, value|
{ key: key, value: value }
end
end
+
+ def payload_variable
+ { key: PAYLOAD_VARIABLE_KEY,
+ value: params.except(*PAYLOAD_VARIABLE_HIDDEN_PARAMS).to_json,
+ variable_type: :file }
+ end
end
end
diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb
index dd7b562cdb7..733aa75f255 100644
--- a/app/services/ci/process_build_service.rb
+++ b/app/services/ci/process_build_service.rb
@@ -26,7 +26,7 @@ module Ci
end
def valid_statuses_for_build(build)
- if ::Feature.enabled?(:skip_dag_manual_and_delayed_jobs, default_enabled: :yaml)
+ if ::Feature.enabled?(:skip_dag_manual_and_delayed_jobs, build.project, default_enabled: :yaml)
current_valid_statuses_for_build(build)
else
legacy_valid_statuses_for_build(build)
diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb
index e511e26adfe..678b386fbbf 100644
--- a/app/services/ci/process_pipeline_service.rb
+++ b/app/services/ci/process_pipeline_service.rb
@@ -38,10 +38,15 @@ module Ci
# mark builds that are retried
if latest_statuses.any?
- pipeline.latest_statuses
- .where(name: latest_statuses.map(&:second))
- .where.not(id: latest_statuses.map(&:first))
- .update_all(retried: true)
+ updated_count = pipeline.latest_statuses
+ .where(name: latest_statuses.map(&:second))
+ .where.not(id: latest_statuses.map(&:first))
+ .update_all(retried: true)
+
+ # This counter is temporary. It will be used to check whether if we still use this method or not
+ # after setting correct value of `GenericCommitStatus#retried`.
+ # More info: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50465#note_491657115
+ metrics.legacy_update_jobs_counter.increment if updated_count > 0
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/ci/prometheus_metrics/observe_histograms_service.rb b/app/services/ci/prometheus_metrics/observe_histograms_service.rb
new file mode 100644
index 00000000000..527d87f19c2
--- /dev/null
+++ b/app/services/ci/prometheus_metrics/observe_histograms_service.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Ci
+ module PrometheusMetrics
+ class ObserveHistogramsService
+ class << self
+ def available_histograms
+ @available_histograms ||= [
+ histogram(:pipeline_graph_link_calculation_duration_seconds, 'Total time spent calculating links, in seconds', {}, [0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.8, 1, 2]),
+ histogram(:pipeline_graph_links_total, 'Number of links per graph', {}, [1, 5, 10, 25, 50, 100, 200]),
+ histogram(:pipeline_graph_links_per_job_ratio, 'Ratio of links to job per graph', {}, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1])
+ ].to_h
+ end
+
+ private
+
+ def histogram(name, *attrs)
+ [name.to_s, proc { Gitlab::Metrics.histogram(name, *attrs) }]
+ end
+ end
+
+ def initialize(project, params)
+ @project = project
+ @params = params
+ end
+
+ def execute
+ return ServiceResponse.success(http_status: :accepted) unless enabled?
+
+ params
+ .fetch(:histograms, [])
+ .each(&method(:observe))
+
+ ServiceResponse.success(http_status: :created)
+ end
+
+ private
+
+ attr_reader :project, :params
+
+ def observe(data)
+ histogram = find_histogram(data[:name])
+ histogram.observe({}, data[:value].to_f)
+ end
+
+ def find_histogram(name)
+ self.class.available_histograms
+ .fetch(name) { raise ActiveRecord::RecordNotFound }
+ .call
+ end
+
+ def enabled?
+ ::Feature.enabled?(:ci_accept_frontend_prometheus_metrics, project, default_enabled: :yaml)
+ end
+ end
+ end
+end
diff --git a/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb b/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
index a4bcca8e8b3..9e3e6de3928 100644
--- a/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
+++ b/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
@@ -7,8 +7,8 @@ module Ci
def execute(resource_group)
free_resources = resource_group.resources.free.count
- resource_group.builds.waiting_for_resource.take(free_resources).each do |build|
- build.enqueue_waiting_for_resource
+ resource_group.processables.waiting_for_resource.take(free_resources).each do |processable|
+ processable.enqueue_waiting_for_resource
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/clusters/kubernetes/configure_istio_ingress_service.rb b/app/services/clusters/kubernetes/configure_istio_ingress_service.rb
index 53c3c686f07..3b7e094bc97 100644
--- a/app/services/clusters/kubernetes/configure_istio_ingress_service.rb
+++ b/app/services/clusters/kubernetes/configure_istio_ingress_service.rb
@@ -60,7 +60,7 @@ module Clusters
cert.public_key = key.public_key
cert.subject = name
cert.issuer = name
- cert.sign(key, OpenSSL::Digest::SHA256.new)
+ cert.sign(key, OpenSSL::Digest.new('SHA256'))
serverless_domain_cluster.update!(
key: key.to_pem,
diff --git a/app/services/concerns/alert_management/alert_processing.rb b/app/services/concerns/alert_management/alert_processing.rb
new file mode 100644
index 00000000000..9b15c5d7b4b
--- /dev/null
+++ b/app/services/concerns/alert_management/alert_processing.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+module AlertManagement
+ # Module to support the processing of new alert payloads
+ # from various sources. Payloads may be for new alerts,
+ # existing alerts, or acting as a resolving alert.
+ #
+ # Performs processing-related tasks, such as creating system
+ # notes, creating or resolving related issues, and notifying
+ # stakeholders of the alert.
+ #
+ # Requires #project [Project] and #payload [Hash] methods
+ # to be defined.
+ module AlertProcessing
+ include BaseServiceUtility
+ include Gitlab::Utils::StrongMemoize
+ include ::IncidentManagement::Settings
+
+ # Updates or creates alert from payload for project
+ # including system notes
+ def process_alert
+ if alert.persisted?
+ process_existing_alert
+ else
+ process_new_alert
+ end
+ end
+
+ # Creates or closes issue for alert and notifies stakeholders
+ def complete_post_processing_tasks
+ process_incident_issues if process_issues?
+ send_alert_email if send_email? && notifying_alert?
+ end
+
+ def process_existing_alert
+ if resolving_alert?
+ process_resolved_alert
+ else
+ process_firing_alert
+ end
+ end
+
+ def process_resolved_alert
+ return unless auto_close_incident?
+ return close_issue(alert.issue) if alert.resolve(incoming_payload.ends_at)
+
+ logger.warn(
+ message: 'Unable to update AlertManagement::Alert status to resolved',
+ project_id: project.id,
+ alert_id: alert.id
+ )
+ end
+
+ def process_firing_alert
+ alert.register_new_event!
+ end
+
+ def close_issue(issue)
+ return if issue.blank? || issue.closed?
+
+ ::Issues::CloseService
+ .new(project, User.alert_bot)
+ .execute(issue, system_note: false)
+
+ SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
+ end
+
+ def process_new_alert
+ if alert.save
+ alert.execute_services
+ SystemNoteService.create_new_alert(alert, alert_source)
+ else
+ logger.warn(
+ message: "Unable to create AlertManagement::Alert from #{alert_source}",
+ project_id: project.id,
+ alert_errors: alert.errors.messages
+ )
+ end
+ end
+
+ def process_incident_issues
+ return if alert.issue || alert.resolved?
+
+ ::IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
+ end
+
+ def send_alert_email
+ notification_service
+ .async
+ .prometheus_alerts_fired(project, [alert])
+ end
+
+ def incoming_payload
+ strong_memoize(:incoming_payload) do
+ Gitlab::AlertManagement::Payload.parse(project, payload.to_h, integration: integration)
+ end
+ end
+
+ def alert
+ strong_memoize(:alert) do
+ find_existing_alert || build_new_alert
+ end
+ end
+
+ def find_existing_alert
+ return unless incoming_payload.gitlab_fingerprint
+
+ AlertManagement::Alert.not_resolved.for_fingerprint(project, incoming_payload.gitlab_fingerprint).first
+ end
+
+ def build_new_alert
+ AlertManagement::Alert.new(**incoming_payload.alert_params, ended_at: nil)
+ end
+
+ def resolving_alert?
+ incoming_payload.ends_at.present?
+ end
+
+ def notifying_alert?
+ alert.triggered? || alert.resolved?
+ end
+
+ def alert_source
+ alert.monitoring_tool
+ end
+
+ def logger
+ @logger ||= Gitlab::AppLogger
+ end
+ end
+end
+
+AlertManagement::AlertProcessing.prepend_ee_mod
diff --git a/app/services/concerns/integrations/project_test_data.rb b/app/services/concerns/integrations/project_test_data.rb
index 72c12cfb394..57bcba98b49 100644
--- a/app/services/concerns/integrations/project_test_data.rb
+++ b/app/services/concerns/integrations/project_test_data.rb
@@ -9,35 +9,40 @@ module Integrations
end
def note_events_data
- note = project.notes.first
+ note = NotesFinder.new(current_user, project: project, target: project).execute.reorder(nil).last # rubocop: disable CodeReuse/ActiveRecord
+
return { error: s_('TestHooks|Ensure the project has notes.') } unless note.present?
Gitlab::DataBuilder::Note.build(note, current_user)
end
def issues_events_data
- issue = project.issues.first
+ issue = IssuesFinder.new(current_user, project_id: project.id, sort: 'created_desc').execute.first
+
return { error: s_('TestHooks|Ensure the project has issues.') } unless issue.present?
issue.to_hook_data(current_user)
end
def merge_requests_events_data
- merge_request = project.merge_requests.first
+ merge_request = MergeRequestsFinder.new(current_user, project_id: project.id, sort: 'created_desc').execute.first
+
return { error: s_('TestHooks|Ensure the project has merge requests.') } unless merge_request.present?
merge_request.to_hook_data(current_user)
end
def job_events_data
- build = project.builds.first
+ build = Ci::JobsFinder.new(current_user: current_user, project: project).execute.first
+
return { error: s_('TestHooks|Ensure the project has CI jobs.') } unless build.present?
Gitlab::DataBuilder::Build.build(build)
end
def pipeline_events_data
- pipeline = project.ci_pipelines.newest_first.first
+ pipeline = Ci::PipelinesFinder.new(project, current_user, order_by: 'id', sort: 'desc').execute.first
+
return { error: s_('TestHooks|Ensure the project has CI pipelines.') } unless pipeline.present?
Gitlab::DataBuilder::Pipeline.build(pipeline)
@@ -45,6 +50,7 @@ module Integrations
def wiki_page_events_data
page = project.wiki.list_pages(limit: 1).first
+
if !project.wiki_enabled? || page.blank?
return { error: s_('TestHooks|Ensure the wiki is enabled and has pages.') }
end
@@ -53,14 +59,16 @@ module Integrations
end
def deployment_events_data
- deployment = project.deployments.first
+ deployment = DeploymentsFinder.new(project: project, order_by: 'created_at', sort: 'desc').execute.first
+
return { error: s_('TestHooks|Ensure the project has deployments.') } unless deployment.present?
Gitlab::DataBuilder::Deployment.build(deployment)
end
def releases_events_data
- release = project.releases.first
+ release = ReleasesFinder.new(project, current_user, order_by: :created_at, sort: :desc).execute.first
+
return { error: s_('TestHooks|Ensure the project has releases.') } unless release.present?
release.to_hook_data('create')
diff --git a/app/services/concerns/spam_check_methods.rb b/app/services/concerns/spam_check_methods.rb
deleted file mode 100644
index 939f8f183ab..00000000000
--- a/app/services/concerns/spam_check_methods.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-# SpamCheckMethods
-#
-# Provide helper methods for checking if a given spammable object has
-# potential spam data.
-#
-# Dependencies:
-# - params with :request
-
-module SpamCheckMethods
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- def filter_spam_check_params
- @request = params.delete(:request)
- @api = params.delete(:api)
- @recaptcha_verified = params.delete(:recaptcha_verified)
- @spam_log_id = params.delete(:spam_log_id)
- end
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
-
- # In order to be proceed to the spam check process, @spammable has to be
- # a dirty instance, which means it should be already assigned with the new
- # attribute values.
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- def spam_check(spammable, user, action:)
- raise ArgumentError.new('Please provide an action, such as :create') unless action
-
- Spam::SpamActionService.new(
- spammable: spammable,
- request: @request,
- user: user,
- context: { action: action }
- ).execute(
- api: @api,
- recaptcha_verified: @recaptcha_verified,
- spam_log_id: @spam_log_id)
- end
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
-end
diff --git a/app/services/concerns/update_repository_storage_methods.rb b/app/services/concerns/update_repository_storage_methods.rb
index c3a55e9379e..6e4824bd784 100644
--- a/app/services/concerns/update_repository_storage_methods.rb
+++ b/app/services/concerns/update_repository_storage_methods.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
module UpdateRepositoryStorageMethods
+ include Gitlab::Utils::StrongMemoize
+
Error = Class.new(StandardError)
- SameFilesystemError = Class.new(Error)
attr_reader :repository_storage_move
delegate :container, :source_storage_name, :destination_storage_name, to: :repository_storage_move
@@ -18,9 +19,7 @@ module UpdateRepositoryStorageMethods
repository_storage_move.start!
end
- raise SameFilesystemError if same_filesystem?(source_storage_name, destination_storage_name)
-
- mirror_repositories
+ mirror_repositories unless same_filesystem?
repository_storage_move.transaction do
repository_storage_move.finish_replication!
@@ -28,8 +27,10 @@ module UpdateRepositoryStorageMethods
track_repository(destination_storage_name)
end
- remove_old_paths
- enqueue_housekeeping
+ unless same_filesystem?
+ remove_old_paths
+ enqueue_housekeeping
+ end
repository_storage_move.finish_cleanup!
@@ -80,8 +81,10 @@ module UpdateRepositoryStorageMethods
end
end
- def same_filesystem?(old_storage, new_storage)
- Gitlab::GitalyClient.filesystem_id(old_storage) == Gitlab::GitalyClient.filesystem_id(new_storage)
+ def same_filesystem?
+ strong_memoize(:same_filesystem) do
+ Gitlab::GitalyClient.filesystem_id(source_storage_name) == Gitlab::GitalyClient.filesystem_id(destination_storage_name)
+ end
end
def remove_old_paths
diff --git a/app/services/container_expiration_policies/cleanup_service.rb b/app/services/container_expiration_policies/cleanup_service.rb
index b9e623e2e07..69e5620d986 100644
--- a/app/services/container_expiration_policies/cleanup_service.rb
+++ b/app/services/container_expiration_policies/cleanup_service.rb
@@ -4,7 +4,7 @@ module ContainerExpirationPolicies
class CleanupService
attr_reader :repository
- SERVICE_RESULT_FIELDS = %i[original_size before_truncate_size after_truncate_size before_delete_size].freeze
+ SERVICE_RESULT_FIELDS = %i[original_size before_truncate_size after_truncate_size before_delete_size deleted_size].freeze
def initialize(repository)
@repository = repository
@@ -15,9 +15,15 @@ module ContainerExpirationPolicies
repository.start_expiration_policy!
- service_result = Projects::ContainerRepository::CleanupTagsService
- .new(project, nil, policy_params.merge('container_expiration_policy' => true))
- .execute(repository)
+ begin
+ service_result = Projects::ContainerRepository::CleanupTagsService
+ .new(project, nil, policy_params.merge('container_expiration_policy' => true))
+ .execute(repository)
+ rescue
+ repository.cleanup_unfinished!
+
+ raise
+ end
if service_result[:status] == :success
repository.update!(
@@ -25,6 +31,7 @@ module ContainerExpirationPolicies
expiration_policy_started_at: nil,
expiration_policy_completed_at: Time.zone.now
)
+
success(:finished, service_result)
else
repository.cleanup_unfinished!
diff --git a/app/services/deployments/create_service.rb b/app/services/deployments/create_service.rb
index 7355747d778..ebf2b077bca 100644
--- a/app/services/deployments/create_service.rb
+++ b/app/services/deployments/create_service.rb
@@ -11,6 +11,8 @@ module Deployments
end
def execute
+ return last_deployment if last_deployment&.equal_to?(params)
+
environment.deployments.build(deployment_attributes).tap do |deployment|
# Deployment#change_status already saves the model, so we only need to
# call #save ourselves if no status is provided.
@@ -36,5 +38,11 @@ module Deployments
on_stop: params[:on_stop]
}
end
+
+ private
+
+ def last_deployment
+ @environment.last_deployment
+ end
end
end
diff --git a/app/services/design_management/move_designs_service.rb b/app/services/design_management/move_designs_service.rb
index ca715b10351..129f93edf5e 100644
--- a/app/services/design_management/move_designs_service.rb
+++ b/app/services/design_management/move_designs_service.rb
@@ -16,7 +16,6 @@ module DesignManagement
return error(:cannot_move) unless current_user.can?(:move_design, current_design)
return error(:no_neighbors) unless neighbors.present?
return error(:not_distinct) unless all_distinct?
- return error(:not_adjacent) if any_in_gap?
return error(:not_same_issue) unless all_same_issue?
move_nulls_to_end
@@ -54,12 +53,6 @@ module DesignManagement
ids.uniq.size == ids.size
end
- def any_in_gap?
- return false unless previous_design&.relative_position && next_design&.relative_position
-
- !previous_design.immediately_before?(next_design)
- end
-
def all_same_issue?
issue.designs.id_in(ids).count == ids.size
end
diff --git a/app/services/discussions/resolve_service.rb b/app/services/discussions/resolve_service.rb
index cd5925cd9be..91c3cf136a4 100644
--- a/app/services/discussions/resolve_service.rb
+++ b/app/services/discussions/resolve_service.rb
@@ -40,7 +40,13 @@ module Discussions
discussion.resolve!(current_user)
@resolved_count += 1
- MergeRequests::ResolvedDiscussionNotificationService.new(project, current_user).execute(merge_request) if merge_request
+ if merge_request
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ .track_resolve_thread_action(user: current_user)
+
+ MergeRequests::ResolvedDiscussionNotificationService.new(project, current_user).execute(merge_request)
+ end
+
SystemNoteService.discussion_continued_in_issue(discussion, project, current_user, follow_up_issue) if follow_up_issue
end
diff --git a/app/services/discussions/unresolve_service.rb b/app/services/discussions/unresolve_service.rb
new file mode 100644
index 00000000000..fbd96ceafe7
--- /dev/null
+++ b/app/services/discussions/unresolve_service.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Discussions
+ class UnresolveService < Discussions::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(discussion, user)
+ @discussion = discussion
+ @user = user
+
+ super
+ end
+
+ def execute
+ @discussion.unresolve!
+
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ .track_unresolve_thread_action(user: @user)
+ end
+ end
+end
diff --git a/app/services/draft_notes/publish_service.rb b/app/services/draft_notes/publish_service.rb
index 316abff4552..82917241347 100644
--- a/app/services/draft_notes/publish_service.rb
+++ b/app/services/draft_notes/publish_service.rb
@@ -38,6 +38,8 @@ module DraftNotes
end
draft_notes.delete_all
+ set_reviewed
+
notification_service.async.new_review(review)
MergeRequests::ResolvedDiscussionNotificationService.new(project, current_user).execute(merge_request)
end
@@ -64,5 +66,9 @@ module DraftNotes
discussion.unresolve!
end
end
+
+ def set_reviewed
+ ::MergeRequests::MarkReviewerReviewedService.new(project, current_user).execute(merge_request)
+ end
end
end
diff --git a/app/services/feature_flags/base_service.rb b/app/services/feature_flags/base_service.rb
index c11c465252e..f48f95e2550 100644
--- a/app/services/feature_flags/base_service.rb
+++ b/app/services/feature_flags/base_service.rb
@@ -41,7 +41,6 @@ module FeatureFlags
def sync_to_jira(feature_flag)
return unless feature_flag.present?
- return unless Feature.enabled?(:jira_sync_feature_flags, feature_flag.project)
seq_id = ::Atlassian::JiraConnect::Client.generate_update_sequence_id
feature_flag.run_after_commit do
diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb
index 4edcff0e3d0..825faf59c13 100644
--- a/app/services/git/branch_hooks_service.rb
+++ b/app/services/git/branch_hooks_service.rb
@@ -2,6 +2,8 @@
module Git
class BranchHooksService < ::Git::BaseHooksService
+ extend ::Gitlab::Utils::Override
+
def execute
execute_branch_hooks
@@ -41,14 +43,15 @@ module Git
super
end
+ override :invalidated_file_types
def invalidated_file_types
return super unless default_branch? && !creating_branch?
- paths = limited_commits.each_with_object(Set.new) do |commit, set|
- commit.raw_deltas.each do |diff|
- set << diff.new_path
- end
- end
+ modified_file_types
+ end
+
+ def modified_file_types
+ paths = commit_paths.values.reduce(&:merge) || Set.new
Gitlab::FileDetector.types_in_paths(paths)
end
@@ -77,6 +80,7 @@ module Git
enqueue_process_commit_messages
enqueue_jira_connect_sync_messages
enqueue_metrics_dashboard_sync
+ track_ci_config_change_event
end
def branch_remove_hooks
@@ -85,10 +89,23 @@ module Git
def enqueue_metrics_dashboard_sync
return unless default_branch?
+ return unless modified_file_types.include?(:metrics_dashboard)
::Metrics::Dashboard::SyncDashboardsWorker.perform_async(project.id)
end
+ def track_ci_config_change_event
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+ return unless ::Feature.enabled?(:usage_data_unique_users_committing_ciconfigfile, project, default_enabled: :yaml)
+ return unless default_branch?
+
+ commits_changing_ci_config.each do |commit|
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(
+ 'o_pipeline_authoring_unique_users_committing_ciconfigfile', values: commit.author&.id
+ )
+ end
+ end
+
# Schedules processing of commit messages
def enqueue_process_commit_messages
referencing_commits = limited_commits.select(&:matches_cross_reference_regex?)
@@ -190,6 +207,23 @@ module Git
set
end
+
+ def commits_changing_ci_config
+ commit_paths.select do |commit, paths|
+ next if commit.merge_commit?
+
+ paths.include?(project.ci_config_path_or_default)
+ end.keys
+ end
+
+ def commit_paths
+ strong_memoize(:commit_paths) do
+ limited_commits.to_h do |commit|
+ paths = Set.new(commit.raw_deltas.map(&:new_path))
+ [commit, paths]
+ end
+ end
+ end
end
end
diff --git a/app/services/git/wiki_push_service.rb b/app/services/git/wiki_push_service.rb
index 87e2be858c0..0905b2d98df 100644
--- a/app/services/git/wiki_push_service.rb
+++ b/app/services/git/wiki_push_service.rb
@@ -16,6 +16,7 @@ module Git
wiki.after_post_receive
process_changes
+ perform_housekeeping
end
private
@@ -72,6 +73,14 @@ module Git
def default_branch_changes
@default_branch_changes ||= changes.select { |change| on_default_branch?(change) }
end
+
+ def perform_housekeeping
+ housekeeping = Repositories::HousekeepingService.new(wiki)
+ housekeeping.increment!
+ housekeeping.execute if housekeeping.needed?
+ rescue Repositories::HousekeepingService::LeaseTaken
+ # no-op
+ end
end
end
diff --git a/app/services/groups/import_export/export_service.rb b/app/services/groups/import_export/export_service.rb
index abac0ffc5d9..a436aec1b39 100644
--- a/app/services/groups/import_export/export_service.rb
+++ b/app/services/groups/import_export/export_service.rb
@@ -12,40 +12,44 @@ module Groups
end
def async_execute
- GroupExportWorker.perform_async(@current_user.id, @group.id, @params)
+ GroupExportWorker.perform_async(current_user.id, group.id, params)
end
def execute
validate_user_permissions
- remove_existing_export! if @group.export_file_exists?
+ remove_existing_export! if group.export_file_exists?
save!
ensure
- remove_base_tmp_dir
+ remove_archive_tmp_dir
end
private
+ attr_reader :group, :current_user, :params
attr_accessor :shared
def validate_user_permissions
- unless @current_user.can?(:admin_group, @group)
- @shared.error(::Gitlab::ImportExport::Error.permission_error(@current_user, @group))
+ unless current_user.can?(:admin_group, group)
+ shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
notify_error!
end
end
def remove_existing_export!
- import_export_upload = @group.import_export_upload
+ import_export_upload = group.import_export_upload
import_export_upload.remove_export_file!
import_export_upload.save
end
def save!
- if savers.all?(&:save)
+ # We cannot include the file_saver with the other savers because
+ # it removes the tmp dir. This means that if we want to add new savers
+ # in EE the data won't be available.
+ if savers.all?(&:save) && file_saver.save
notify_success
else
notify_error!
@@ -53,36 +57,40 @@ module Groups
end
def savers
- [version_saver, tree_exporter, file_saver]
+ [version_saver, tree_exporter]
end
def tree_exporter
tree_exporter_class.new(
- group: @group,
- current_user: @current_user,
- shared: @shared,
- params: @params
+ group: group,
+ current_user: current_user,
+ shared: shared,
+ params: params
)
end
def tree_exporter_class
- if ::Feature.enabled?(:group_export_ndjson, @group&.parent, default_enabled: true)
+ if ndjson?
Gitlab::ImportExport::Group::TreeSaver
else
Gitlab::ImportExport::Group::LegacyTreeSaver
end
end
+ def ndjson?
+ ::Feature.enabled?(:group_export_ndjson, group&.parent, default_enabled: :yaml)
+ end
+
def version_saver
Gitlab::ImportExport::VersionSaver.new(shared: shared)
end
def file_saver
- Gitlab::ImportExport::Saver.new(exportable: @group, shared: @shared)
+ Gitlab::ImportExport::Saver.new(exportable: group, shared: shared)
end
- def remove_base_tmp_dir
- FileUtils.rm_rf(shared.base_path) if shared&.base_path
+ def remove_archive_tmp_dir
+ FileUtils.rm_rf(shared.archive_path) if shared&.archive_path
end
def notify_error!
@@ -94,22 +102,22 @@ module Groups
def notify_success
@logger.info(
message: 'Group Export succeeded',
- group_id: @group.id,
- group_name: @group.name
+ group_id: group.id,
+ group_name: group.name
)
- notification_service.group_was_exported(@group, @current_user)
+ notification_service.group_was_exported(group, current_user)
end
def notify_error
@logger.error(
message: 'Group Export failed',
- group_id: @group.id,
- group_name: @group.name,
- errors: @shared.errors.join(', ')
+ group_id: group.id,
+ group_name: group.name,
+ errors: shared.errors.join(', ')
)
- notification_service.group_was_not_exported(@group, @current_user, @shared.errors)
+ notification_service.group_was_not_exported(group, current_user, shared.errors)
end
def notification_service
@@ -118,3 +126,5 @@ module Groups
end
end
end
+
+Groups::ImportExport::ExportService.prepend_if_ee('EE::Groups::ImportExport::ExportService')
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index a0ddc50e5e0..bf3f09f22d4 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -3,7 +3,7 @@
module Groups
module ImportExport
class ImportService
- attr_reader :current_user, :group, :params
+ attr_reader :current_user, :group, :shared
def initialize(group:, user:)
@group = group
@@ -26,10 +26,10 @@ module Groups
end
def execute
- if valid_user_permissions? && import_file && restorer.restore
+ if valid_user_permissions? && import_file && restorers.all?(&:restore)
notify_success
- @group
+ group
else
notify_error!
end
@@ -43,37 +43,41 @@ module Groups
def import_file
@import_file ||= Gitlab::ImportExport::FileImporter.import(
- importable: @group,
+ importable: group,
archive_file: nil,
- shared: @shared
+ shared: shared
)
end
- def restorer
- @restorer ||=
+ def restorers
+ [tree_restorer]
+ end
+
+ def tree_restorer
+ @tree_restorer ||=
if ndjson?
Gitlab::ImportExport::Group::TreeRestorer.new(
- user: @current_user,
- shared: @shared,
- group: @group
+ user: current_user,
+ shared: shared,
+ group: group
)
else
Gitlab::ImportExport::Group::LegacyTreeRestorer.new(
- user: @current_user,
- shared: @shared,
- group: @group,
+ user: current_user,
+ shared: shared,
+ group: group,
group_hash: nil
)
end
end
def ndjson?
- ::Feature.enabled?(:group_import_ndjson, @group&.parent, default_enabled: true) &&
- File.exist?(File.join(@shared.export_path, 'tree/groups/_all.ndjson'))
+ ::Feature.enabled?(:group_import_ndjson, group&.parent, default_enabled: true) &&
+ File.exist?(File.join(shared.export_path, 'tree/groups/_all.ndjson'))
end
def remove_import_file
- upload = @group.import_export_upload
+ upload = group.import_export_upload
return unless upload&.import_file&.file
@@ -85,7 +89,7 @@ module Groups
if current_user.can?(:admin_group, group)
true
else
- @shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
+ shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
false
end
@@ -93,16 +97,16 @@ module Groups
def notify_success
@logger.info(
- group_id: @group.id,
- group_name: @group.name,
+ group_id: group.id,
+ group_name: group.name,
message: 'Group Import/Export: Import succeeded'
)
end
def notify_error
@logger.error(
- group_id: @group.id,
- group_name: @group.name,
+ group_id: group.id,
+ group_name: group.name,
message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details"
)
end
@@ -110,12 +114,14 @@ module Groups
def notify_error!
notify_error
- raise Gitlab::ImportExport::Error.new(@shared.errors.to_sentence)
+ raise Gitlab::ImportExport::Error.new(shared.errors.to_sentence)
end
def remove_base_tmp_dir
- FileUtils.rm_rf(@shared.base_path)
+ FileUtils.rm_rf(shared.base_path)
end
end
end
end
+
+Groups::ImportExport::ImportService.prepend_if_ee('EE::Groups::ImportExport::ImportService')
diff --git a/app/services/groups/open_issues_count_service.rb b/app/services/groups/open_issues_count_service.rb
new file mode 100644
index 00000000000..db1ca09212a
--- /dev/null
+++ b/app/services/groups/open_issues_count_service.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Groups
+ # Service class for counting and caching the number of open issues of a group.
+ class OpenIssuesCountService < BaseCountService
+ include Gitlab::Utils::StrongMemoize
+
+ VERSION = 1
+ PUBLIC_COUNT_KEY = 'group_public_open_issues_count'
+ TOTAL_COUNT_KEY = 'group_total_open_issues_count'
+ CACHED_COUNT_THRESHOLD = 1000
+ EXPIRATION_TIME = 24.hours
+
+ attr_reader :group, :user
+
+ def initialize(group, user = nil)
+ @group = group
+ @user = user
+ end
+
+ # Reads count value from cache and return it if present.
+ # If empty or expired, #uncached_count will calculate the issues count for the group and
+ # compare it with the threshold. If it is greater, it will be written to the cache and returned.
+ # If below, it will be returned without being cached.
+ # This results in only caching large counts and calculating the rest with every call to maintain
+ # accuracy.
+ def count
+ cached_count = Rails.cache.read(cache_key)
+ return cached_count unless cached_count.blank?
+
+ refreshed_count = uncached_count
+ update_cache_for_key(cache_key) { refreshed_count } if refreshed_count > CACHED_COUNT_THRESHOLD
+ refreshed_count
+ end
+
+ def cache_key(key = nil)
+ ['groups', 'open_issues_count_service', VERSION, group.id, cache_key_name]
+ end
+
+ private
+
+ def cache_options
+ super.merge({ expires_in: EXPIRATION_TIME })
+ end
+
+ def cache_key_name
+ public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY
+ end
+
+ def public_only?
+ !user_is_at_least_reporter?
+ end
+
+ def user_is_at_least_reporter?
+ strong_memoize(:user_is_at_least_reporter) do
+ group.member?(user, Gitlab::Access::REPORTER)
+ end
+ end
+
+ def relation_for_count
+ IssuesFinder.new(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true, public_only: public_only?).execute
+ end
+ end
+end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 6d41d449683..094b31b4ad6 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -190,11 +190,7 @@ class IssuableBaseService < BaseService
change_additional_attributes(issuable)
old_associations = associations_before_update(issuable)
- label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids)
- if labels_changing?(issuable.label_ids, label_ids)
- params[:label_ids] = label_ids
- issuable.touch
- end
+ assign_requested_labels(issuable)
if issuable.changed? || params.present?
issuable.assign_attributes(params)
@@ -262,6 +258,11 @@ class IssuableBaseService < BaseService
invalidate_cache_counts(issuable, users: issuable.assignees.to_a)
after_update(issuable)
execute_hooks(issuable, 'update', old_associations: nil)
+
+ if issuable.is_a?(MergeRequest)
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ .track_task_item_status_changed(user: current_user)
+ end
end
end
@@ -297,10 +298,6 @@ class IssuableBaseService < BaseService
update_task(issuable)
end
- def labels_changing?(old_label_ids, new_label_ids)
- old_label_ids.sort != new_label_ids.sort
- end
-
def has_title_or_description_changed?(issuable)
issuable.title_changed? || issuable.description_changed?
end
@@ -349,6 +346,20 @@ class IssuableBaseService < BaseService
end
# rubocop: enable CodeReuse/ActiveRecord
+ def assign_requested_labels(issuable)
+ label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids)
+ return unless ids_changing?(issuable.label_ids, label_ids)
+
+ params[:label_ids] = label_ids
+ issuable.touch
+ end
+
+ # Arrays of ids are used, but we should really use sets of ids, so
+ # let's have an helper to properly check if some ids are changing
+ def ids_changing?(old_array, new_array)
+ old_array.sort != new_array.sort
+ end
+
def toggle_award(issuable)
award = params.delete(:emoji_award)
AwardEmojis::ToggleService.new(issuable, award, current_user).execute if award
diff --git a/app/services/issue_rebalancing_service.rb b/app/services/issue_rebalancing_service.rb
index 4138c6441c8..849afc4edb8 100644
--- a/app/services/issue_rebalancing_service.rb
+++ b/app/services/issue_rebalancing_service.rb
@@ -17,8 +17,21 @@ class IssueRebalancingService
start = RelativePositioning::START_POSITION - (gaps / 2) * gap_size
- Issue.transaction do
- indexed_ids.each_slice(100) { |pairs| assign_positions(start, pairs) }
+ if Feature.enabled?(:issue_rebalancing_optimization)
+ Issue.transaction do
+ assign_positions(start, indexed_ids)
+ .sort_by(&:first)
+ .each_slice(100) do |pairs_with_position|
+ update_positions(pairs_with_position, 'rebalance issue positions in batches ordered by id')
+ end
+ end
+ else
+ Issue.transaction do
+ indexed_ids.each_slice(100) do |pairs|
+ pairs_with_position = assign_positions(start, pairs)
+ update_positions(pairs_with_position, 'rebalance issue positions')
+ end
+ end
end
end
@@ -32,13 +45,22 @@ class IssueRebalancingService
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
- def assign_positions(start, positions)
- values = positions.map do |id, index|
- "(#{id}, #{start + (index * gap_size)})"
+ def assign_positions(start, pairs)
+ pairs.map do |id, index|
+ [id, start + (index * gap_size)]
+ end
+ end
+
+ def update_positions(pairs_with_position, query_name)
+ values = pairs_with_position.map do |id, index|
+ "(#{id}, #{index})"
end.join(', ')
- Issue.connection.exec_query(<<~SQL, "rebalance issue positions")
+ run_update_query(values, query_name)
+ end
+
+ def run_update_query(values, query_name)
+ Issue.connection.exec_query(<<~SQL, query_name)
WITH cte(cte_id, new_pos) AS (
SELECT *
FROM (VALUES #{values}) as t (id, pos)
@@ -49,7 +71,6 @@ class IssueRebalancingService
WHERE cte_id = id
SQL
end
- # rubocop: enable CodeReuse/ActiveRecord
def issue_count
@issue_count ||= base.count
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index baf7974c45d..746f7d1f4c1 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -55,7 +55,7 @@ module Issues
def close_external_issue(issue, closed_via)
return unless project.external_issue_tracker&.support_close_issue?
- project.external_issue_tracker.close_issue(closed_via, issue)
+ project.external_issue_tracker.close_issue(closed_via, issue, current_user)
todo_service.close_issue(issue, current_user)
end
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 44de8eb6389..d2285a375a1 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -2,20 +2,26 @@
module Issues
class CreateService < Issues::BaseService
- include SpamCheckMethods
include ResolveDiscussions
def execute(skip_system_notes: false)
+ @request = params.delete(:request)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+
@issue = BuildService.new(project, current_user, params).execute
- filter_spam_check_params
filter_resolve_discussion_params
create(@issue, skip_system_notes: skip_system_notes)
end
def before_create(issue)
- spam_check(issue, current_user, action: :create)
+ Spam::SpamActionService.new(
+ spammable: issue,
+ request: request,
+ user: current_user,
+ action: :create
+ ).execute(spam_params: spam_params)
# current_user (defined in BaseService) is not available within run_after_commit block
user = current_user
@@ -46,8 +52,10 @@ module Issues
private
+ attr_reader :request, :spam_params
+
def user_agent_detail_service
- UserAgentDetailService.new(@issue, @request)
+ UserAgentDetailService.new(@issue, request)
end
# Applies label "incident" (creates it if missing) to incident issues.
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 127ed04cf51..2906bdf62a7 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -2,12 +2,14 @@
module Issues
class UpdateService < Issues::BaseService
- include SpamCheckMethods
extend ::Gitlab::Utils::Override
def execute(issue)
handle_move_between_ids(issue)
- filter_spam_check_params
+
+ @request = params.delete(:request)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+
change_issue_duplicate(issue)
move_issue_to_new_project(issue) || clone_issue(issue) || update_task_event(issue) || update(issue)
end
@@ -30,7 +32,14 @@ module Issues
end
def before_update(issue, skip_spam_check: false)
- spam_check(issue, current_user, action: :update) unless skip_spam_check
+ return if skip_spam_check
+
+ Spam::SpamActionService.new(
+ spammable: issue,
+ request: request,
+ user: current_user,
+ action: :update
+ ).execute(spam_params: spam_params)
end
def after_update(issue)
@@ -126,6 +135,8 @@ module Issues
private
+ attr_reader :request, :spam_params
+
def clone_issue(issue)
target_project = params.delete(:target_clone_project)
with_notes = params.delete(:clone_with_notes)
diff --git a/app/services/jira/requests/base.rb b/app/services/jira/requests/base.rb
index 098aae9284c..bae8298d5c8 100644
--- a/app/services/jira/requests/base.rb
+++ b/app/services/jira/requests/base.rb
@@ -18,15 +18,15 @@ module Jira
request
end
+ private
+
+ attr_reader :jira_service, :project
+
# We have to add the context_path here because the Jira client is not taking it into account
def base_api_url
"#{context_path}/rest/api/#{api_version}"
end
- private
-
- attr_reader :jira_service, :project
-
def context_path
client.options[:context_path].to_s
end
diff --git a/app/services/members/update_service.rb b/app/services/members/update_service.rb
index b5c27caafa2..5c6e51201c2 100644
--- a/app/services/members/update_service.rb
+++ b/app/services/members/update_service.rb
@@ -16,7 +16,11 @@ module Members
enqueue_delete_todos(member) if downgrading_to_guest?
end
- member
+ if member.errors.any?
+ error(member.errors.full_messages.to_sentence, pass_back: { member: member })
+ else
+ success(member: member)
+ end
end
private
diff --git a/app/services/merge_requests/add_context_service.rb b/app/services/merge_requests/add_context_service.rb
index bb82fa23468..b693f8509a2 100644
--- a/app/services/merge_requests/add_context_service.rb
+++ b/app/services/merge_requests/add_context_service.rb
@@ -66,7 +66,8 @@ module MergeRequests
relative_order: index,
sha: sha,
authored_date: Gitlab::Database.sanitize_timestamp(commit_hash[:authored_date]),
- committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date])
+ committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date]),
+ trailers: commit_hash.fetch(:trailers, {}).to_json
)
end
end
diff --git a/app/services/merge_requests/approval_service.rb b/app/services/merge_requests/approval_service.rb
index 150ec85fca9..59d8f553eff 100644
--- a/app/services/merge_requests/approval_service.rb
+++ b/app/services/merge_requests/approval_service.rb
@@ -14,6 +14,7 @@ module MergeRequests
create_approval_note(merge_request)
mark_pending_todos_as_done(merge_request)
execute_approval_hooks(merge_request, current_user)
+ merge_request_activity_counter.track_approve_mr_action(user: current_user)
success
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 0613c061f2e..6bd31e26748 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -108,7 +108,7 @@ module MergeRequests
def filter_reviewer(merge_request)
return if params[:reviewer_ids].blank?
- unless can_admin_issuable?(merge_request) && merge_request.allows_reviewers?
+ unless can_admin_issuable?(merge_request)
params.delete(:reviewer_ids)
return
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 80991657688..12c901aa1a1 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -16,30 +16,17 @@ module MergeRequests
merge_request.source_project = find_source_project
merge_request.target_project = find_target_project
- # Source project sets the default source branch removal setting
- merge_request.merge_params['force_remove_source_branch'] =
- if params.key?(:force_remove_source_branch)
- params.delete(:force_remove_source_branch)
- else
- merge_request.source_project.remove_source_branch_after_merge?
- end
+ # Force remove the source branch?
+ merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch
+ # Only assign merge requests params that are allowed
self.params = assign_allowed_merge_params(merge_request, params)
+ # Filter out params that are either not allowed or invalid
filter_params(merge_request)
- # merge_request.assign_attributes(...) below is a Rails
- # method that only work if all the params it is passed have
- # corresponding fields in the database. As there are no fields
- # in the database for :add_label_ids and :remove_label_ids, we
- # need to remove them from the params before the call to
- # merge_request.assign_attributes(...)
- #
- # IssuableBaseService#process_label_ids takes care
- # of the removal.
- params[:label_ids] = process_label_ids(params, extra_label_ids: merge_request.label_ids.to_a)
-
- merge_request.assign_attributes(params.to_h.compact)
+ # Filter out :add_label_ids and :remove_label_ids params
+ filter_label_id_params
merge_request.compare_commits = []
set_merge_request_target_branch
@@ -74,6 +61,29 @@ module MergeRequests
:errors,
to: :merge_request
+ def force_remove_source_branch
+ if params.key?(:force_remove_source_branch)
+ params.delete(:force_remove_source_branch)
+ else
+ merge_request.source_project.remove_source_branch_after_merge?
+ end
+ end
+
+ def filter_label_id_params
+ # merge_request.assign_attributes(...) below is a Rails
+ # method that only work if all the params it is passed have
+ # corresponding fields in the database. As there are no fields
+ # in the database for :add_label_ids and :remove_label_ids, we
+ # need to remove them from the params before the call to
+ # merge_request.assign_attributes(...)
+ #
+ # IssuableBaseService#process_label_ids takes care
+ # of the removal.
+ params[:label_ids] = process_label_ids(params, extra_label_ids: merge_request.label_ids.to_a)
+
+ merge_request.assign_attributes(params.to_h.compact)
+ end
+
def find_source_project
source_project = project_from_params(:source_project)
return source_project if source_project.present? && can?(current_user, :create_merge_request_from, source_project)
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index 78b462174c9..b43e697d3ab 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -25,6 +25,7 @@ module MergeRequests
new_merge_request = create(merge_request)
if new_merge_request.valid?
+ merge_request_activity_counter.track_mr_create_from_issue(user: current_user)
SystemNoteService.new_merge_request(issue, project, current_user, new_merge_request)
success(new_merge_request)
diff --git a/app/services/merge_requests/mark_reviewer_reviewed_service.rb b/app/services/merge_requests/mark_reviewer_reviewed_service.rb
new file mode 100644
index 00000000000..766a4ca0a49
--- /dev/null
+++ b/app/services/merge_requests/mark_reviewer_reviewed_service.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class MarkReviewerReviewedService < MergeRequests::BaseService
+ def execute(merge_request)
+ return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
+
+ reviewer = merge_request.find_reviewer(current_user)
+
+ if reviewer
+ return error("Failed to update reviewer") unless reviewer.update(state: :reviewed)
+
+ success
+ else
+ error("Reviewer not found")
+ end
+ end
+ end
+end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index f4454db0af8..fc4405ef704 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -8,6 +8,8 @@ module MergeRequests
# Executed when you do merge via GitLab UI
#
class MergeService < MergeRequests::MergeBaseService
+ GENERIC_ERROR_MESSAGE = 'An error occurred while merging'
+
delegate :merge_jid, :state, to: :@merge_request
def execute(merge_request, options = {})
@@ -79,7 +81,7 @@ module MergeRequests
if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
else
- raise_error('Conflicts detected during merge')
+ raise_error(GENERIC_ERROR_MESSAGE)
end
merge_request.update!(merge_commit_sha: commit_id)
@@ -96,7 +98,7 @@ module MergeRequests
"Something went wrong during merge pre-receive hook. #{e.message}".strip
rescue => e
handle_merge_error(log_message: e.message)
- raise_error('Something went wrong during merge')
+ raise_error(GENERIC_ERROR_MESSAGE)
end
def after_merge
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
index 96a2322f6a0..9fecab85cc1 100644
--- a/app/services/merge_requests/mergeability_check_service.rb
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -114,6 +114,7 @@ module MergeRequests
merge_to_ref_success = merge_to_ref
+ reload_merge_head_diff
update_diff_discussion_positions! if merge_to_ref_success
if merge_to_ref_success && can_git_merge?
@@ -123,6 +124,10 @@ module MergeRequests
end
end
+ def reload_merge_head_diff
+ MergeRequests::ReloadMergeHeadDiffService.new(merge_request).execute
+ end
+
def update_diff_discussion_positions!
Discussions::CaptureDiffNotePositionsService.new(merge_request).execute
end
@@ -153,6 +158,7 @@ module MergeRequests
def merge_to_ref
params = { allow_conflicts: Feature.enabled?(:display_merge_conflicts_in_diff, project) }
result = MergeRequests::MergeToRefService.new(project, merge_request.author, params).execute(merge_request)
+
result[:status] == :success
end
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index f04ec3c3e80..aafba9bfcef 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -9,6 +9,8 @@ module MergeRequests
class PostMergeService < MergeRequests::BaseService
include RemovesRefs
+ MAX_RETARGET_MERGE_REQUESTS = 4
+
def execute(merge_request)
merge_request.mark_as_merged
close_issues(merge_request)
@@ -18,6 +20,7 @@ module MergeRequests
merge_request_activity_counter.track_merge_mr_action(user: current_user)
notification_service.merge_mr(merge_request, current_user)
execute_hooks(merge_request, 'merge')
+ retarget_chain_merge_requests(merge_request)
invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
delete_non_latest_diffs(merge_request)
@@ -28,6 +31,34 @@ module MergeRequests
private
+ def retarget_chain_merge_requests(merge_request)
+ return unless Feature.enabled?(:retarget_merge_requests, merge_request.target_project)
+
+ # we can only retarget MRs that are targeting the same project
+ # and have a remove source branch set
+ return unless merge_request.for_same_project? && merge_request.remove_source_branch?
+
+ # find another merge requests that
+ # - as a target have a current source project and branch
+ other_merge_requests = merge_request.source_project
+ .merge_requests
+ .opened
+ .by_target_branch(merge_request.source_branch)
+ .preload_source_project
+ .at_most(MAX_RETARGET_MERGE_REQUESTS)
+
+ other_merge_requests.find_each do |other_merge_request|
+ # Update only MRs on projects that we have access to
+ next unless can?(current_user, :update_merge_request, other_merge_request.source_project)
+
+ ::MergeRequests::UpdateService
+ .new(other_merge_request.source_project, current_user,
+ target_branch: merge_request.target_branch,
+ target_branch_was_deleted: true)
+ .execute(other_merge_request)
+ end
+ end
+
def close_issues(merge_request)
return unless merge_request.target_branch == project.default_branch
diff --git a/app/services/merge_requests/reload_merge_head_diff_service.rb b/app/services/merge_requests/reload_merge_head_diff_service.rb
new file mode 100644
index 00000000000..f02a9bd3139
--- /dev/null
+++ b/app/services/merge_requests/reload_merge_head_diff_service.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ReloadMergeHeadDiffService
+ include BaseServiceUtility
+
+ def initialize(merge_request)
+ @merge_request = merge_request
+ end
+
+ def execute
+ return error("default_merge_ref_for_diffs feature flag is disabled") unless enabled?
+ return error("Merge request has no merge ref head.") unless merge_request.merge_ref_head.present?
+
+ error_msg = recreate_merge_head_diff
+
+ return error(error_msg) if error_msg
+
+ success
+ end
+
+ private
+
+ attr_reader :merge_request
+
+ def enabled?
+ Feature.enabled?(:default_merge_ref_for_diffs, merge_request.project, default_enabled: :yaml)
+ end
+
+ def recreate_merge_head_diff
+ merge_request.merge_head_diff&.destroy!
+
+ # n+1: https://gitlab.com/gitlab-org/gitlab/-/issues/19377
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ merge_request.create_merge_head_diff!
+ end
+
+ # Reset the merge request so it won't load the merge head diff as the
+ # MergeRequest#merge_request_diff.
+ merge_request.reset
+
+ nil
+ rescue StandardError => e
+ message = "Failed to recreate merge head diff: #{e.message}"
+
+ Gitlab::AppLogger.error(message: message, merge_request_id: merge_request.id)
+ message
+ end
+ end
+end
diff --git a/app/services/merge_requests/remove_approval_service.rb b/app/services/merge_requests/remove_approval_service.rb
index 3164d0b4069..f2bf5de61c1 100644
--- a/app/services/merge_requests/remove_approval_service.rb
+++ b/app/services/merge_requests/remove_approval_service.rb
@@ -16,6 +16,7 @@ module MergeRequests
reset_approvals_cache(merge_request)
create_note(merge_request)
+ merge_request_activity_counter.track_unapprove_mr_action(user: current_user)
end
success
diff --git a/app/services/merge_requests/request_review_service.rb b/app/services/merge_requests/request_review_service.rb
new file mode 100644
index 00000000000..b061ed45fee
--- /dev/null
+++ b/app/services/merge_requests/request_review_service.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class RequestReviewService < MergeRequests::BaseService
+ def execute(merge_request, user)
+ return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
+
+ reviewer = merge_request.find_reviewer(user)
+
+ if reviewer
+ return error("Failed to update reviewer") unless reviewer.update(state: :unreviewed)
+
+ notify_reviewer(merge_request, user)
+
+ success
+ else
+ error("Reviewer not found")
+ end
+ end
+
+ private
+
+ def notify_reviewer(merge_request, reviewer)
+ notification_service.async.review_requested_of_merge_request(merge_request, current_user, reviewer)
+ todo_service.create_request_review_todo(merge_request, current_user, reviewer)
+ end
+ end
+end
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index d2e5a2a1619..1707daff734 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -4,6 +4,12 @@ module MergeRequests
class UpdateService < MergeRequests::BaseService
extend ::Gitlab::Utils::Override
+ def initialize(project, user = nil, params = {})
+ super
+
+ @target_branch_was_deleted = @params.delete(:target_branch_was_deleted)
+ end
+
def execute(merge_request)
# We don't allow change of source/target projects and source branch
# after merge request was created
@@ -36,7 +42,9 @@ module MergeRequests
end
if merge_request.previous_changes.include?('target_branch')
- create_branch_change_note(merge_request, 'target',
+ create_branch_change_note(merge_request,
+ 'target',
+ target_branch_was_deleted ? 'delete' : 'update',
merge_request.previous_changes['target_branch'].first,
merge_request.target_branch)
@@ -87,12 +95,51 @@ module MergeRequests
MergeRequests::CloseService
end
+ def before_update(issuable, skip_spam_check: false)
+ return unless issuable.changed?
+
+ @issuable_changes = issuable.changes
+ end
+
def after_update(issuable)
issuable.cache_merge_request_closes_issues!(current_user)
+
+ return unless @issuable_changes
+
+ %w(title description).each do |action|
+ next unless @issuable_changes.key?(action)
+
+ # Track edits to title or description
+ #
+ merge_request_activity_counter
+ .public_send("track_#{action}_edit_action".to_sym, user: current_user) # rubocop:disable GitlabSecurity/PublicSend
+
+ # Track changes to Draft/WIP status
+ #
+ if action == "title"
+ old_title, new_title = @issuable_changes["title"]
+ old_title_wip = MergeRequest.work_in_progress?(old_title)
+ new_title_wip = MergeRequest.work_in_progress?(new_title)
+
+ if !old_title_wip && new_title_wip
+ # Marked as Draft/WIP
+ #
+ merge_request_activity_counter
+ .track_marked_as_draft_action(user: current_user)
+ elsif old_title_wip && !new_title_wip
+ # Unmarked as Draft/WIP
+ #
+ merge_request_activity_counter
+ .track_unmarked_as_draft_action(user: current_user)
+ end
+ end
+ end
end
private
+ attr_reader :target_branch_was_deleted
+
def handle_milestone_change(merge_request)
return if skip_milestone_email
@@ -109,6 +156,9 @@ module MergeRequests
create_assignee_note(merge_request, old_assignees)
notification_service.async.reassigned_merge_request(merge_request, current_user, old_assignees)
todo_service.reassigned_assignable(merge_request, current_user, old_assignees)
+
+ new_assignees = merge_request.assignees - old_assignees
+ merge_request_activity_counter.track_users_assigned_to_mr(users: new_assignees)
end
def handle_reviewers_change(merge_request, old_reviewers)
@@ -117,11 +167,14 @@ module MergeRequests
notification_service.async.changed_reviewer_of_merge_request(merge_request, current_user, old_reviewers)
todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
invalidate_cache_counts(merge_request, users: affected_reviewers.compact)
+
+ new_reviewers = merge_request.reviewers - old_reviewers
+ merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
end
- def create_branch_change_note(issuable, branch_type, old_branch, new_branch)
+ def create_branch_change_note(issuable, branch_type, event_type, old_branch, new_branch)
SystemNoteService.change_branch(
- issuable, issuable.project, current_user, branch_type,
+ issuable, issuable.project, current_user, branch_type, event_type,
old_branch, new_branch)
end
diff --git a/app/services/namespaces/in_product_marketing_emails_service.rb b/app/services/namespaces/in_product_marketing_emails_service.rb
new file mode 100644
index 00000000000..45b4619ddbe
--- /dev/null
+++ b/app/services/namespaces/in_product_marketing_emails_service.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class InProductMarketingEmailsService
+ include Gitlab::Experimentation::GroupTypes
+
+ INTERVAL_DAYS = [1, 5, 10].freeze
+ TRACKS = {
+ create: :git_write,
+ verify: :pipeline_created,
+ trial: :trial_started,
+ team: :user_added
+ }.freeze
+
+ def self.send_for_all_tracks_and_intervals
+ TRACKS.each_key do |track|
+ INTERVAL_DAYS.each do |interval|
+ new(track, interval).execute
+ end
+ end
+ end
+
+ def initialize(track, interval)
+ @track = track
+ @interval = interval
+ @sent_email_user_ids = []
+ end
+
+ def execute
+ groups_for_track.each_batch do |groups|
+ groups.each do |group|
+ send_email_for_group(group)
+ end
+ end
+ end
+
+ private
+
+ attr_reader :track, :interval, :sent_email_user_ids
+
+ def send_email_for_group(group)
+ experiment_enabled_for_group = experiment_enabled_for_group?(group)
+ experiment_add_group(group, experiment_enabled_for_group)
+ return unless experiment_enabled_for_group
+
+ users_for_group(group).each do |user|
+ send_email(user, group) if can_perform_action?(user, group)
+ end
+ end
+
+ def experiment_enabled_for_group?(group)
+ Gitlab::Experimentation.in_experiment_group?(:in_product_marketing_emails, subject: group)
+ end
+
+ def experiment_add_group(group, experiment_enabled_for_group)
+ variant = experiment_enabled_for_group ? GROUP_EXPERIMENTAL : GROUP_CONTROL
+ Experiment.add_group(:in_product_marketing_emails, variant: variant, group: group)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def groups_for_track
+ onboarding_progress_scope = OnboardingProgress
+ .completed_actions_with_latest_in_range(completed_actions, range)
+ .incomplete_actions(incomplete_action)
+
+ Group.joins(:onboarding_progress).merge(onboarding_progress_scope)
+ end
+
+ def users_for_group(group)
+ group.users.where(email_opted_in: true)
+ .where.not(id: sent_email_user_ids)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def can_perform_action?(user, group)
+ case track
+ when :create
+ user.can?(:create_projects, group)
+ when :verify
+ user.can?(:create_projects, group)
+ when :trial
+ user.can?(:start_trial, group)
+ when :team
+ user.can?(:admin_group_member, group)
+ else
+ raise NotImplementedError, "No ability defined for track #{track}"
+ end
+ end
+
+ def send_email(user, group)
+ NotificationService.new.in_product_marketing(user.id, group.id, track, series)
+ sent_email_user_ids << user.id
+ end
+
+ def completed_actions
+ index = TRACKS.keys.index(track)
+ index == 0 ? [:created] : TRACKS.values[0..index - 1]
+ end
+
+ def range
+ (interval + 1).days.ago.beginning_of_day..(interval + 1).days.ago.end_of_day
+ end
+
+ def incomplete_action
+ TRACKS[track]
+ end
+
+ def series
+ INTERVAL_DAYS.index(interval)
+ end
+ end
+end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 04b7fba207b..488c847dcbb 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -27,7 +27,11 @@ module Notes
end
note_saved = note.with_transaction_returning_status do
- !only_commands && note.save
+ break false if only_commands
+
+ note.save.tap do
+ update_discussions(note)
+ end
end
when_saved(note) if note_saved
@@ -54,12 +58,17 @@ module Notes
@quick_actions_service ||= QuickActionsService.new(project, current_user)
end
- def when_saved(note)
+ def update_discussions(note)
+ # Ensure that individual notes that are promoted into discussions are
+ # updated in a transaction with the note creation to avoid inconsistencies:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/301237
if note.part_of_discussion? && note.discussion.can_convert_to_discussion?
note.discussion.convert_to_discussion!.save
note.clear_memoization(:discussion)
end
+ end
+ def when_saved(note)
todo_service.new_note(note, current_user)
clear_noteable_diffs_cache(note)
Suggestions::CreateService.new(note).execute
diff --git a/app/services/notification_recipients/build_service.rb b/app/services/notification_recipients/build_service.rb
index 040ecc29d3a..52070abbad7 100644
--- a/app/services/notification_recipients/build_service.rb
+++ b/app/services/notification_recipients/build_service.rb
@@ -36,5 +36,9 @@ module NotificationRecipients
def self.build_new_review_recipients(*args)
::NotificationRecipients::Builder::NewReview.new(*args).notification_recipients
end
+
+ def self.build_requested_review_recipients(*args)
+ ::NotificationRecipients::Builder::RequestReview.new(*args).notification_recipients
+ end
end
end
diff --git a/app/services/notification_recipients/builder/request_review.rb b/app/services/notification_recipients/builder/request_review.rb
new file mode 100644
index 00000000000..911d89c6a8e
--- /dev/null
+++ b/app/services/notification_recipients/builder/request_review.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module NotificationRecipients
+ module Builder
+ class RequestReview < Base
+ attr_reader :merge_request, :current_user, :reviewer
+
+ def initialize(merge_request, current_user, reviewer)
+ @merge_request, @current_user, @reviewer = merge_request, current_user, reviewer
+ end
+
+ def target
+ merge_request
+ end
+
+ def build!
+ add_recipients(reviewer, :mention, NotificationReason::REVIEW_REQUESTED)
+ end
+ end
+ end
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 5a71e0eac7c..50247532f69 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -265,6 +265,14 @@ class NotificationService
end
end
+ def review_requested_of_merge_request(merge_request, current_user, reviewer)
+ recipients = NotificationRecipients::BuildService.build_requested_review_recipients(merge_request, current_user, reviewer)
+
+ recipients.each do |recipient|
+ mailer.request_review_merge_request_email(recipient.user.id, merge_request.id, current_user.id, recipient.reason).deliver_later
+ end
+ end
+
# When we add labels to a merge request we should send an email to:
#
# * watchers of the mr's labels
@@ -664,6 +672,10 @@ class NotificationService
end
end
+ def in_product_marketing(user_id, group_id, track, series)
+ mailer.in_product_marketing_email(user_id, group_id, track, series).deliver_later
+ end
+
protected
def new_resource_email(target, method)
diff --git a/app/services/packages/create_package_service.rb b/app/services/packages/create_package_service.rb
index fcf252cf971..3dc06497d9f 100644
--- a/app/services/packages/create_package_service.rb
+++ b/app/services/packages/create_package_service.rb
@@ -9,7 +9,9 @@ module Packages
.packages
.with_package_type(package_type)
.safe_find_or_create_by!(name: name, version: version) do |package|
+ package.status = params[:status] if params[:status]
package.creator = package_creator
+
add_build_info(package)
end
end
@@ -29,8 +31,9 @@ module Packages
{
creator: package_creator,
name: params[:name],
- version: params[:version]
- }.merge(attrs)
+ version: params[:version],
+ status: params[:status]
+ }.compact.merge(attrs)
end
def package_creator
diff --git a/app/services/packages/debian/create_distribution_service.rb b/app/services/packages/debian/create_distribution_service.rb
new file mode 100644
index 00000000000..c6df033e3c1
--- /dev/null
+++ b/app/services/packages/debian/create_distribution_service.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class CreateDistributionService
+ def initialize(container, user, params)
+ @container, @params = container, params
+ @params[:creator] = user
+
+ @components = params.delete(:components) || ['main']
+
+ @architectures = params.delete(:architectures) || ['amd64']
+ @architectures += ['all']
+
+ @distribution = nil
+ @errors = []
+ end
+
+ def execute
+ create_distribution
+ end
+
+ private
+
+ attr_reader :container, :params, :components, :architectures, :distribution, :errors
+
+ def append_errors(record, prefix = '')
+ return if record.valid?
+
+ prefix = "#{prefix} " unless prefix.empty?
+ @errors += record.errors.full_messages.map { |message| "#{prefix}#{message}" }
+ end
+
+ def create_distribution
+ @distribution = container.debian_distributions.new(params)
+
+ append_errors(distribution)
+ return error unless errors.empty?
+
+ distribution.transaction do
+ if distribution.save
+ create_components
+ create_architectures
+
+ success
+ end
+ end || error
+ end
+
+ def create_components
+ create_objects(distribution.components, components, error_label: 'Component')
+ end
+
+ def create_architectures
+ create_objects(distribution.architectures, architectures, error_label: 'Architecture')
+ end
+
+ def create_objects(objects, object_names_from_params, error_label: )
+ object_names_from_params.each do |name|
+ new_object = objects.create(name: name)
+ append_errors(new_object, error_label)
+ raise ActiveRecord::Rollback unless new_object.persisted?
+ end
+ end
+
+ def success
+ ServiceResponse.success(payload: { distribution: distribution }, http_status: :created)
+ end
+
+ def error
+ ServiceResponse.error(message: errors.to_sentence, payload: { distribution: distribution })
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/destroy_distribution_service.rb b/app/services/packages/debian/destroy_distribution_service.rb
new file mode 100644
index 00000000000..bef1127fece
--- /dev/null
+++ b/app/services/packages/debian/destroy_distribution_service.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class DestroyDistributionService
+ def initialize(distribution)
+ @distribution = distribution
+ end
+
+ def execute
+ destroy_distribution
+ end
+
+ private
+
+ def destroy_distribution
+ if @distribution.destroy
+ success
+ else
+ error("Unable to destroy Debian #{@distribution.model_name.human.downcase}")
+ end
+ end
+
+ def success
+ ServiceResponse.success
+ end
+
+ def error(message)
+ ServiceResponse.error(message: message, payload: { distribution: @distribution })
+ end
+ end
+ end
+end
diff --git a/app/services/packages/debian/update_distribution_service.rb b/app/services/packages/debian/update_distribution_service.rb
new file mode 100644
index 00000000000..5bb59b854e9
--- /dev/null
+++ b/app/services/packages/debian/update_distribution_service.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Packages
+ module Debian
+ class UpdateDistributionService
+ def initialize(distribution, params)
+ @distribution, @params = distribution, params
+
+ @components = params.delete(:components)
+
+ @architectures = params.delete(:architectures)
+ @architectures += ['all'] unless @architectures.nil?
+
+ @errors = []
+ end
+
+ def execute
+ update_distribution
+ end
+
+ private
+
+ attr_reader :distribution, :params, :components, :architectures, :errors
+
+ def append_errors(record, prefix = '')
+ return if record.valid?
+
+ prefix = "#{prefix} " unless prefix.empty?
+ @errors += record.errors.full_messages.map { |message| "#{prefix}#{message}" }
+ end
+
+ def update_distribution
+ distribution.transaction do
+ if distribution.update(params)
+ update_components if components
+ update_architectures if architectures
+
+ success
+ else
+ append_errors(distribution)
+ error
+ end
+ end || error
+ end
+
+ def update_components
+ update_objects(distribution.components, components, error_label: 'Component')
+ end
+
+ def update_architectures
+ update_objects(distribution.architectures, architectures, error_label: 'Architecture')
+ end
+
+ def update_objects(objects, object_names_from_params, error_label: )
+ current_object_names = objects.map(&:name)
+ missing_object_names = object_names_from_params - current_object_names
+ extra_object_names = current_object_names - object_names_from_params
+
+ missing_object_names.each do |name|
+ new_object = objects.create(name: name)
+ append_errors(new_object, error_label)
+ raise ActiveRecord::Rollback unless new_object.persisted?
+ end
+
+ extra_object_names.each do |name|
+ object = objects.with_name(name).first
+ raise ActiveRecord::Rollback unless object.destroy
+ end
+ end
+
+ def success
+ ServiceResponse.success(payload: { distribution: distribution })
+ end
+
+ def error
+ ServiceResponse.error(message: errors.to_sentence, payload: { distribution: distribution })
+ end
+ end
+ end
+end
diff --git a/app/services/packages/generic/create_package_file_service.rb b/app/services/packages/generic/create_package_file_service.rb
index b14b1c193ec..1451a022a39 100644
--- a/app/services/packages/generic/create_package_file_service.rb
+++ b/app/services/packages/generic/create_package_file_service.rb
@@ -15,13 +15,16 @@ module Packages
package_params = {
name: params[:package_name],
version: params[:package_version],
- build: params[:build]
+ build: params[:build],
+ status: params[:status]
}
package = ::Packages::Generic::FindOrCreatePackageService
.new(project, current_user, package_params)
.execute
+ package.update_column(:status, params[:status]) if params[:status] && params[:status] != package.status
+
package.build_infos.safe_find_or_create_by!(pipeline: params[:build].pipeline) if params[:build].present?
package
end
diff --git a/app/services/packages/maven/find_or_create_package_service.rb b/app/services/packages/maven/find_or_create_package_service.rb
index 8ee449cbfdc..4c916d264a7 100644
--- a/app/services/packages/maven/find_or_create_package_service.rb
+++ b/app/services/packages/maven/find_or_create_package_service.rb
@@ -11,12 +11,7 @@ module Packages
.execute
unless Namespace::PackageSetting.duplicates_allowed?(package)
- files = package&.package_files || []
- current_maven_files = files.map { |file| extname(file.file_name) }
-
- if current_maven_files.compact.include?(extname(params[:file_name]))
- return ServiceResponse.error(message: 'Duplicate package is not allowed')
- end
+ return ServiceResponse.error(message: 'Duplicate package is not allowed') if target_package_is_duplicate?(package)
end
unless package
@@ -47,6 +42,7 @@ module Packages
package_params = {
name: package_name,
path: params[:path],
+ status: params[:status],
version: version
}
@@ -67,6 +63,17 @@ module Packages
File.extname(filename)
end
+
+ def target_package_is_duplicate?(package)
+ # duplicate metadata files can be uploaded multiple times
+ return false if package.version.nil?
+
+ package
+ .package_files
+ .map { |file| extname(file.file_name) }
+ .compact
+ .include?(extname(params[:file_name]))
+ end
end
end
end
diff --git a/app/services/pages/delete_service.rb b/app/services/pages/delete_service.rb
index fc5d01a93a1..3dc9254718e 100644
--- a/app/services/pages/delete_service.rb
+++ b/app/services/pages/delete_service.rb
@@ -3,7 +3,13 @@
module Pages
class DeleteService < BaseService
def execute
- PagesRemoveWorker.perform_async(project.id)
+ project.mark_pages_as_not_deployed # prevents domain from updating config when deleted
+ project.pages_domains.delete_all
+
+ DestroyPagesDeploymentsWorker.perform_async(project.id)
+
+ # TODO: remove this call https://gitlab.com/gitlab-org/gitlab/-/issues/320775
+ PagesRemoveWorker.perform_async(project.id) if Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
end
end
end
diff --git a/app/services/pages/migrate_from_legacy_storage_service.rb b/app/services/pages/migrate_from_legacy_storage_service.rb
new file mode 100644
index 00000000000..9b36b3f11b4
--- /dev/null
+++ b/app/services/pages/migrate_from_legacy_storage_service.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Pages
+ class MigrateFromLegacyStorageService
+ def initialize(logger, migration_threads:, batch_size:, ignore_invalid_entries:)
+ @logger = logger
+ @migration_threads = migration_threads
+ @batch_size = batch_size
+ @ignore_invalid_entries = ignore_invalid_entries
+
+ @migrated = 0
+ @errored = 0
+ @counters_lock = Mutex.new
+ end
+
+ def execute
+ @queue = SizedQueue.new(1)
+
+ threads = start_migration_threads
+
+ ProjectPagesMetadatum.only_on_legacy_storage.each_batch(of: @batch_size) do |batch|
+ @queue.push(batch)
+ end
+
+ @queue.close
+
+ @logger.info("Waiting for threads to finish...")
+ threads.each(&:join)
+
+ { migrated: @migrated, errored: @errored }
+ end
+
+ def start_migration_threads
+ Array.new(@migration_threads) do
+ Thread.new do
+ while batch = @queue.pop
+ Rails.application.executor.wrap do
+ process_batch(batch)
+ end
+ end
+ end
+ end
+ end
+
+ def process_batch(batch)
+ batch.with_project_route_and_deployment.each do |metadatum|
+ project = metadatum.project
+
+ migrate_project(project)
+ end
+
+ @logger.info("#{@migrated} projects are migrated successfully, #{@errored} projects failed to be migrated")
+ rescue => e
+ # This method should never raise exception otherwise all threads might be killed
+ # and this will result in queue starving (and deadlock)
+ Gitlab::ErrorTracking.track_exception(e)
+ @logger.error("failed processing a batch: #{e.message}")
+ end
+
+ def migrate_project(project)
+ result = nil
+ time = Benchmark.realtime do
+ result = ::Pages::MigrateLegacyStorageToDeploymentService.new(project, ignore_invalid_entries: @ignore_invalid_entries).execute
+ end
+
+ if result[:status] == :success
+ @logger.info("project_id: #{project.id} #{project.pages_path} has been migrated in #{time.round(2)} seconds")
+ @counters_lock.synchronize { @migrated += 1 }
+ else
+ @logger.error("project_id: #{project.id} #{project.pages_path} failed to be migrated in #{time.round(2)} seconds: #{result[:message]}")
+ @counters_lock.synchronize { @errored += 1 }
+ end
+ rescue => e
+ @counters_lock.synchronize { @errored += 1 }
+ @logger.error("project_id: #{project&.id} #{project&.pages_path} failed to be migrated: #{e.message}")
+ Gitlab::ErrorTracking.track_exception(e, project_id: project&.id)
+ end
+ end
+end
diff --git a/app/services/pages/migrate_legacy_storage_to_deployment_service.rb b/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
index dac994b2ccc..63410b9fe4a 100644
--- a/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
+++ b/app/services/pages/migrate_legacy_storage_to_deployment_service.rb
@@ -9,8 +9,9 @@ module Pages
attr_reader :project
- def initialize(project)
+ def initialize(project, ignore_invalid_entries: false)
@project = project
+ @ignore_invalid_entries = ignore_invalid_entries
end
def execute
@@ -26,7 +27,7 @@ module Pages
private
def execute_unsafe
- zip_result = ::Pages::ZipDirectoryService.new(project.pages_path).execute
+ zip_result = ::Pages::ZipDirectoryService.new(project.pages_path, ignore_invalid_entries: @ignore_invalid_entries).execute
if zip_result[:status] == :error
if !project.pages_metadatum&.reload&.pages_deployment &&
diff --git a/app/services/pages/zip_directory_service.rb b/app/services/pages/zip_directory_service.rb
index ba7a8571e88..ae08d40ee37 100644
--- a/app/services/pages/zip_directory_service.rb
+++ b/app/services/pages/zip_directory_service.rb
@@ -10,12 +10,17 @@ module Pages
PUBLIC_DIR = 'public'
- def initialize(input_dir)
+ attr_reader :public_dir, :real_dir
+
+ def initialize(input_dir, ignore_invalid_entries: false)
@input_dir = input_dir
+ @ignore_invalid_entries = ignore_invalid_entries
end
def execute
- return error("Can not find valid public dir in #{@input_dir}") unless valid_path?(public_dir)
+ unless resolve_public_dir
+ return error("Can not find valid public dir in #{@input_dir}")
+ end
output_file = File.join(real_dir, "@migrated.zip") # '@' to avoid any name collision with groups or projects
@@ -35,24 +40,36 @@ module Pages
private
+ def resolve_public_dir
+ @real_dir = File.realpath(@input_dir)
+ @public_dir = File.join(real_dir, PUBLIC_DIR)
+
+ valid_path?(public_dir)
+ rescue Errno::ENOENT
+ false
+ end
+
def write_entry(zipfile, zipfile_path)
disk_file_path = File.join(real_dir, zipfile_path)
unless valid_path?(disk_file_path)
# archive with invalid entry will just have this entry missing
- raise InvalidEntryError
+ raise InvalidEntryError, "#{disk_file_path} is invalid, input_dir: #{@input_dir}"
end
- case File.lstat(disk_file_path).ftype
+ ftype = File.lstat(disk_file_path).ftype
+ case ftype
when 'directory'
recursively_zip_directory(zipfile, disk_file_path, zipfile_path)
when 'file', 'link'
zipfile.add(zipfile_path, disk_file_path)
else
- raise InvalidEntryError
+ raise InvalidEntryError, "#{disk_file_path} has invalid ftype: #{ftype}, input_dir: #{@input_dir}"
end
- rescue InvalidEntryError => e
+ rescue Errno::ENOENT, Errno::ELOOP, InvalidEntryError => e
Gitlab::ErrorTracking.track_exception(e, input_dir: @input_dir, disk_file_path: disk_file_path)
+
+ raise e unless @ignore_invalid_entries
end
def recursively_zip_directory(zipfile, disk_file_path, zipfile_path)
@@ -70,31 +87,11 @@ module Pages
end
end
- # that should never happen, but we want to be safer
- # in theory without this we would allow to use symlinks
- # to pack any directory on disk
- # it isn't possible because SafeZip doesn't extract such archives
+ # SafeZip was introduced only recently,
+ # so we have invalid entries on disk
def valid_path?(disk_file_path)
realpath = File.realpath(disk_file_path)
-
realpath == public_dir || realpath.start_with?(public_dir + "/")
- # happens if target of symlink isn't there
- rescue => e
- Gitlab::ErrorTracking.track_exception(e, input_dir: real_dir, disk_file_path: disk_file_path)
-
- false
- end
-
- def real_dir
- strong_memoize(:real_dir) do
- File.realpath(@input_dir) rescue nil
- end
- end
-
- def public_dir
- strong_memoize(:public_dir) do
- File.join(real_dir, PUBLIC_DIR) rescue nil
- end
end
end
end
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
index 014fb0e3ed3..2ba64b73699 100644
--- a/app/services/projects/alerting/notify_service.rb
+++ b/app/services/projects/alerting/notify_service.rb
@@ -3,9 +3,8 @@
module Projects
module Alerting
class NotifyService
- include BaseServiceUtility
- include Gitlab::Utils::StrongMemoize
- include ::IncidentManagement::Settings
+ extend ::Gitlab::Utils::Override
+ include ::AlertManagement::AlertProcessing
def initialize(project, payload)
@project = project
@@ -22,8 +21,7 @@ module Projects
process_alert
return bad_request unless alert.persisted?
- process_incident_issues if process_issues?
- send_alert_email if send_email?
+ complete_post_processing_tasks
ServiceResponse.success
end
@@ -32,93 +30,15 @@ module Projects
attr_reader :project, :payload, :integration
- def process_alert
- if alert.persisted?
- process_existing_alert
- else
- create_alert
- end
- end
-
- def process_existing_alert
- if incoming_payload.ends_at.present?
- process_resolved_alert
- else
- alert.register_new_event!
- end
-
- alert
- end
-
- def process_resolved_alert
- return unless auto_close_incident?
-
- if alert.resolve(incoming_payload.ends_at)
- close_issue(alert.issue)
- end
-
- alert
- end
-
- def close_issue(issue)
- return if issue.blank? || issue.closed?
-
- ::Issues::CloseService
- .new(project, User.alert_bot)
- .execute(issue, system_note: false)
-
- SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
- end
-
- def create_alert
- return unless alert.save
-
- alert.execute_services
- SystemNoteService.create_new_alert(alert, notification_source)
- end
-
- def process_incident_issues
- return if alert.issue || alert.resolved?
-
- ::IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
- end
-
- def send_alert_email
- notification_service
- .async
- .prometheus_alerts_fired(project, [alert])
- end
-
- def alert
- strong_memoize(:alert) do
- existing_alert || new_alert
- end
- end
-
- def existing_alert
- return unless incoming_payload.gitlab_fingerprint
-
- AlertManagement::Alert.not_resolved.for_fingerprint(project, incoming_payload.gitlab_fingerprint).first
- end
-
- def new_alert
- AlertManagement::Alert.new(**incoming_payload.alert_params, ended_at: nil)
- end
-
- def incoming_payload
- strong_memoize(:incoming_payload) do
- Gitlab::AlertManagement::Payload.parse(project, payload.to_h)
- end
+ def valid_payload_size?
+ Gitlab::Utils::DeepSize.new(payload).valid?
end
- def notification_source
+ override :alert_source
+ def alert_source
alert.monitoring_tool || integration&.name || 'Generic Alert Endpoint'
end
- def valid_payload_size?
- Gitlab::Utils::DeepSize.new(payload).valid?
- end
-
def active_integration?
integration&.active?
end
diff --git a/app/services/projects/branches_by_mode_service.rb b/app/services/projects/branches_by_mode_service.rb
new file mode 100644
index 00000000000..fb66bfa073b
--- /dev/null
+++ b/app/services/projects/branches_by_mode_service.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+# Projects::BranchesByModeService uses Gitaly page-token pagination
+# in order to optimally fetch branches.
+# The drawback of the page-token pagination is that it doesn't provide
+# an option of going to the previous page of the collection.
+# That's why we need to fall back to offset pagination when previous page
+# is requested.
+class Projects::BranchesByModeService
+ include Gitlab::Routing
+
+ attr_reader :project, :params
+
+ def initialize(project, params = {})
+ @project = project
+ @params = params
+ end
+
+ def execute
+ return fetch_branches_via_gitaly_pagination if use_gitaly_pagination?
+
+ fetch_branches_via_offset_pagination
+ end
+
+ private
+
+ def mode
+ params[:mode]
+ end
+
+ def by_mode(branches)
+ return branches unless %w[active stale].include?(mode)
+
+ branches.select { |b| b.state.to_s == mode }
+ end
+
+ def use_gitaly_pagination?
+ return false if params[:page].present? || params[:search].present?
+
+ Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: true)
+ end
+
+ def fetch_branches_via_offset_pagination
+ branches = BranchesFinder.new(project.repository, params).execute
+ branches = Kaminari.paginate_array(by_mode(branches)).page(params[:page])
+
+ branches_with_links(branches, last_page: branches.last_page?)
+ end
+
+ def fetch_branches_via_gitaly_pagination
+ per_page = Kaminari.config.default_per_page
+ options = params.merge(per_page: per_page + 1, page_token: params[:page_token])
+
+ branches = BranchesFinder.new(project.repository, options).execute(gitaly_pagination: true)
+
+ # Branch is stale if it hasn't been updated for 3 months
+ # This logic is specified in Gitlab Rails and isn't specified in Gitaly
+ # To display stale branches we fetch branches sorted as most-stale-at-the-top
+ # If the result contains active branches we filter them out and define that no more stale branches left
+ # Same logic applies to fetching active branches
+ branches = by_mode(branches)
+ last_page = branches.size <= per_page
+
+ branches = branches.take(per_page) # rubocop:disable CodeReuse/ActiveRecord
+
+ branches_with_links(branches, last_page: last_page)
+ end
+
+ def branches_with_links(branches, last_page:)
+ # To fall back to offset pagination we need to track current page via offset param
+ # And increase it whenever we go to the next page
+ previous_offset = params[:offset].to_i
+
+ previous_path, next_path = nil, nil
+
+ return [branches, previous_path, next_path] if branches.blank?
+
+ unless last_page
+ next_path = project_branches_filtered_path(project, state: mode, page_token: branches.last.name, sort: params[:sort], offset: previous_offset + 1)
+ end
+
+ if previous_offset > 0
+ previous_path = project_branches_filtered_path(project, state: mode, sort: params[:sort], page: previous_offset, offset: previous_offset - 1)
+ end
+
+ [branches, previous_path, next_path]
+ end
+end
diff --git a/app/services/projects/cleanup_service.rb b/app/services/projects/cleanup_service.rb
index 6e3b320afbe..7bcaee75813 100644
--- a/app/services/projects/cleanup_service.rb
+++ b/app/services/projects/cleanup_service.rb
@@ -40,7 +40,7 @@ module Projects
apply_bfg_object_map!
# Remove older objects that are no longer referenced
- GitGarbageCollectWorker.new.perform(project.id, :prune, "project_cleanup:gc:#{project.id}")
+ Projects::GitGarbageCollectWorker.new.perform(project.id, :prune, "project_cleanup:gc:#{project.id}")
# The cache may now be inaccurate, and holding onto it could prevent
# bugs assuming the presence of some object from manifesting for some
diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb
index af0107436c8..793d2fec033 100644
--- a/app/services/projects/container_repository/cleanup_tags_service.rb
+++ b/app/services/projects/container_repository/cleanup_tags_service.rb
@@ -25,6 +25,7 @@ module Projects
result[:before_truncate_size] = before_truncate_size
result[:after_truncate_size] = after_truncate_size
result[:before_delete_size] = tags.size
+ result[:deleted_size] = result[:deleted]&.size
result[:status] = :error if before_truncate_size != after_truncate_size
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index a01db4b498c..08f569662a8 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -127,7 +127,7 @@ module Projects
access_level: group_access_level)
end
- if Feature.enabled?(:specialized_project_authorization_workers)
+ if Feature.enabled?(:specialized_project_authorization_workers, default_enabled: :yaml)
AuthorizedProjectUpdate::ProjectCreateWorker.perform_async(@project.id)
# AuthorizedProjectsWorker uses an exclusive lease per user but
# specialized workers might have synchronization issues. Until we
@@ -210,16 +210,22 @@ module Projects
end
def set_project_name_from_path
- # Set project name from path
- if @project.name.present? && @project.path.present?
- # if both name and path set - everything is ok
- elsif @project.path.present?
+ # if both name and path set - everything is ok
+ return if @project.name.present? && @project.path.present?
+
+ if @project.path.present?
# Set project name from path
@project.name = @project.path.dup
elsif @project.name.present?
# For compatibility - set path from name
- # TODO: remove this in 8.0
- @project.path = @project.name.dup.parameterize
+ @project.path = @project.name.dup
+
+ # TODO: Retained for backwards compatibility. Remove in API v5.
+ # When removed, validation errors will get bubbled up automatically.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52725
+ unless @project.path.match?(Gitlab::PathRegex.project_path_format_regex)
+ @project.path = @project.path.parameterize
+ end
end
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 050bfdd862d..fd9b64a4ee0 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -43,8 +43,8 @@ module Projects
def new_fork_params
new_params = {
forked_from_project: @project,
- visibility_level: allowed_visibility_level,
- description: @project.description,
+ visibility_level: target_visibility_level,
+ description: target_description,
name: target_name,
path: target_path,
shared_runners_enabled: @project.shared_runners_enabled,
@@ -107,6 +107,10 @@ module Projects
@target_name ||= @params[:name] || @project.name
end
+ def target_description
+ @target_description ||= @params[:description] || @project.description
+ end
+
def target_namespace
@target_namespace ||= @params[:namespace] || current_user.namespace
end
@@ -115,8 +119,9 @@ module Projects
@skip_disk_validation ||= @params[:skip_disk_validation] || false
end
- def allowed_visibility_level
+ def target_visibility_level
target_level = [@project.visibility_level, target_namespace.visibility_level].min
+ target_level = [target_level, Gitlab::VisibilityLevel.level_value(params[:visibility])].min if params.key?(:visibility)
Gitlab::VisibilityLevel.closest_allowed_level(target_level)
end
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index 031b99753c3..c2a8db7b657 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -86,11 +86,11 @@ module Projects
end
def repo_saver
- Gitlab::ImportExport::RepoSaver.new(project: project, shared: shared)
+ Gitlab::ImportExport::RepoSaver.new(exportable: project, shared: shared)
end
def wiki_repo_saver
- Gitlab::ImportExport::WikiRepoSaver.new(project: project, shared: shared)
+ Gitlab::ImportExport::WikiRepoSaver.new(exportable: project, shared: shared)
end
def lfs_saver
@@ -102,7 +102,7 @@ module Projects
end
def design_repo_saver
- Gitlab::ImportExport::DesignRepoSaver.new(project: project, shared: shared)
+ Gitlab::ImportExport::DesignRepoSaver.new(exportable: project, shared: shared)
end
def cleanup
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 25d46ada885..29e92d725e2 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -80,6 +80,10 @@ module Projects
end
def deploy_to_legacy_storage(artifacts_path)
+ # path today used by one project can later be used by another
+ # so we can't really scope this feature flag by project or group
+ return unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+
# Create temporary directory in which we will extract the artifacts
make_secure_tmp_dir(tmp_path) do |tmp_path|
extract_archive!(artifacts_path, tmp_path)
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 50a544ed1a5..8384bfa813f 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -56,11 +56,25 @@ module Projects
raise ValidationError.new(s_('UpdateProject|Cannot rename project because it contains container registry tags!'))
end
- if changing_default_branch?
- raise ValidationError.new(s_("UpdateProject|Could not set the default branch")) unless project.change_head(params[:default_branch])
+ validate_default_branch_change
+ end
+
+ def validate_default_branch_change
+ return unless changing_default_branch?
+
+ previous_default_branch = project.default_branch
+
+ if project.change_head(params[:default_branch])
+ after_default_branch_change(previous_default_branch)
+ else
+ raise ValidationError.new(s_("UpdateProject|Could not set the default branch"))
end
end
+ def after_default_branch_change(previous_default_branch)
+ # overridden by EE module
+ end
+
def remove_unallowed_params
params.delete(:emails_disabled) unless can?(current_user, :set_emails_disabled, project)
end
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index de1cd7cd981..ea90d8e3dd8 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -164,6 +164,7 @@ module QuickActions
next unless definition
definition.execute(self, arg)
+ usage_ping_tracking(name, arg)
end
end
@@ -178,6 +179,14 @@ module QuickActions
ext.references(type)
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def usage_ping_tracking(quick_action_name, arg)
+ Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter.track_unique_action(
+ quick_action_name,
+ args: arg&.strip,
+ user: current_user
+ )
+ end
end
end
diff --git a/app/services/repositories/changelog_service.rb b/app/services/repositories/changelog_service.rb
new file mode 100644
index 00000000000..96a63865a49
--- /dev/null
+++ b/app/services/repositories/changelog_service.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+module Repositories
+ # A service class for generating a changelog section.
+ class ChangelogService
+ DEFAULT_TRAILER = 'Changelog'
+ DEFAULT_FILE = 'CHANGELOG.md'
+
+ # The `project` specifies the `Project` to generate the changelog section
+ # for.
+ #
+ # The `user` argument specifies a `User` to use for committing the changes
+ # to the Git repository.
+ #
+ # The `version` arguments must be a version `String` using semantic
+ # versioning as the format.
+ #
+ # The arguments `from` and `to` must specify a Git ref or SHA to use for
+ # fetching the commits to include in the changelog. The SHA/ref set in the
+ # `from` argument isn't included in the list.
+ #
+ # The `date` argument specifies the date of the release, and defaults to the
+ # current time/date.
+ #
+ # The `branch` argument specifies the branch to commit the changes to. The
+ # branch must already exist.
+ #
+ # The `trailer` argument is the Git trailer to use for determining what
+ # commits to include in the changelog.
+ #
+ # The `file` arguments specifies the name/path of the file to commit the
+ # changes to. If the file doesn't exist, it's created automatically.
+ #
+ # The `message` argument specifies the commit message to use when committing
+ # the changelog changes.
+ #
+ # rubocop: disable Metrics/ParameterLists
+ def initialize(
+ project,
+ user,
+ version:,
+ to:,
+ from: nil,
+ date: DateTime.now,
+ branch: project.default_branch_or_master,
+ trailer: DEFAULT_TRAILER,
+ file: DEFAULT_FILE,
+ message: "Add changelog for version #{version}"
+ )
+ @project = project
+ @user = user
+ @version = version
+ @from = from
+ @to = to
+ @date = date
+ @branch = branch
+ @trailer = trailer
+ @file = file
+ @message = message
+ end
+ # rubocop: enable Metrics/ParameterLists
+
+ def execute
+ from = start_of_commit_range
+
+ # For every entry we want to only include the merge request that
+ # originally introduced the commit, which is the oldest merge request that
+ # contains the commit. We fetch there merge requests in batches, reducing
+ # the number of SQL queries needed to get this data.
+ mrs_finder = MergeRequests::OldestPerCommitFinder.new(@project)
+ config = Gitlab::Changelog::Config.from_git(@project)
+ release = Gitlab::Changelog::Release
+ .new(version: @version, date: @date, config: config)
+
+ commits =
+ CommitsWithTrailerFinder.new(project: @project, from: from, to: @to)
+
+ commits.each_page(@trailer) do |page|
+ mrs = mrs_finder.execute(page)
+
+ # Preload the authors. This ensures we only need a single SQL query per
+ # batch of commits, instead of needing a query for every commit.
+ page.each(&:lazy_author)
+
+ page.each do |commit|
+ release.add_entry(
+ title: commit.title,
+ commit: commit,
+ category: commit.trailers.fetch(@trailer),
+ author: commit.author,
+ merge_request: mrs[commit.id]
+ )
+ end
+ end
+
+ Gitlab::Changelog::Committer
+ .new(@project, @user)
+ .commit(release: release, file: @file, branch: @branch, message: @message)
+ end
+
+ def start_of_commit_range
+ return @from if @from
+
+ if (prev_tag = PreviousTagFinder.new(@project).execute(@version))
+ return prev_tag.target_commit.id
+ end
+
+ raise(
+ Gitlab::Changelog::Error,
+ 'The commit start range is unspecified, and no previous tag ' \
+ 'could be found to use instead'
+ )
+ end
+ end
+end
diff --git a/app/services/repositories/housekeeping_service.rb b/app/services/repositories/housekeeping_service.rb
index 6a2fa95d25f..de80390e60b 100644
--- a/app/services/repositories/housekeeping_service.rb
+++ b/app/services/repositories/housekeeping_service.rb
@@ -45,7 +45,7 @@ module Repositories
private
def execute_gitlab_shell_gc(lease_uuid)
- GitGarbageCollectWorker.perform_async(@resource.id, task, lease_key, lease_uuid)
+ @resource.git_garbage_collect_worker_klass.perform_async(@resource.id, task, lease_key, lease_uuid)
ensure
if pushes_since_gc >= gc_period
Gitlab::Metrics.measure(:reset_pushes_since_gc) do
diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb
index 70e09be9407..36858f33b49 100644
--- a/app/services/resource_access_tokens/create_service.rb
+++ b/app/services/resource_access_tokens/create_service.rb
@@ -10,7 +10,7 @@ module ResourceAccessTokens
end
def execute
- return error("User does not have permission to create #{resource_type} Access Token") unless has_permission_to_create?
+ return error("User does not have permission to create #{resource_type} access token") unless has_permission_to_create?
user = create_user
@@ -26,6 +26,7 @@ module ResourceAccessTokens
token_response = create_personal_access_token(user)
if token_response.success?
+ log_event(token_response.payload[:personal_access_token])
success(token_response.payload[:personal_access_token])
else
delete_failed_user(user)
@@ -105,6 +106,10 @@ module ResourceAccessTokens
resource.add_user(user, :maintainer, expires_at: params[:expires_at])
end
+ def log_event(token)
+ ::Gitlab::AppLogger.info "PROJECT ACCESS TOKEN CREATION: created_by: #{current_user.username}, project_id: #{resource.id}, token_user: #{token.user.name}, token_id: #{token.id}"
+ end
+
def error(message)
ServiceResponse.error(message: message)
end
@@ -114,3 +119,5 @@ module ResourceAccessTokens
end
end
end
+
+ResourceAccessTokens::CreateService.prepend_if_ee('EE::ResourceAccessTokens::CreateService')
diff --git a/app/services/resource_access_tokens/revoke_service.rb b/app/services/resource_access_tokens/revoke_service.rb
index ece928dac31..59402701ddc 100644
--- a/app/services/resource_access_tokens/revoke_service.rb
+++ b/app/services/resource_access_tokens/revoke_service.rb
@@ -21,6 +21,8 @@ module ResourceAccessTokens
destroy_bot_user
+ log_event
+
success("Access token #{access_token.name} has been revoked and the bot user has been scheduled for deletion.")
rescue StandardError => error
log_error("Failed to revoke access token for #{bot_user.name}: #{error.message}")
@@ -57,6 +59,10 @@ module ResourceAccessTokens
end
end
+ def log_event
+ ::Gitlab::AppLogger.info "PROJECT ACCESS TOKEN REVOCATION: revoked_by: #{current_user.username}, project_id: #{resource.id}, token_user: #{access_token.user.name}, token_id: #{access_token.id}"
+ end
+
def error(message)
ServiceResponse.error(message: message)
end
@@ -66,3 +72,5 @@ module ResourceAccessTokens
end
end
end
+
+ResourceAccessTokens::RevokeService.prepend_if_ee('EE::ResourceAccessTokens::RevokeService')
diff --git a/app/services/resource_events/base_change_timebox_service.rb b/app/services/resource_events/base_change_timebox_service.rb
index 5c83f7b12f7..d802bbee107 100644
--- a/app/services/resource_events/base_change_timebox_service.rb
+++ b/app/services/resource_events/base_change_timebox_service.rb
@@ -2,12 +2,11 @@
module ResourceEvents
class BaseChangeTimeboxService
- attr_reader :resource, :user, :event_created_at
+ attr_reader :resource, :user
- def initialize(resource, user, created_at: Time.current)
+ def initialize(resource, user)
@resource = resource
@user = user
- @event_created_at = created_at
end
def execute
@@ -27,7 +26,7 @@ module ResourceEvents
{
user_id: user.id,
- created_at: event_created_at,
+ created_at: resource.system_note_timestamp,
key => resource.id
}
end
diff --git a/app/services/resource_events/change_milestone_service.rb b/app/services/resource_events/change_milestone_service.rb
index dcdf87599ac..24935a3327a 100644
--- a/app/services/resource_events/change_milestone_service.rb
+++ b/app/services/resource_events/change_milestone_service.rb
@@ -4,8 +4,8 @@ module ResourceEvents
class ChangeMilestoneService < BaseChangeTimeboxService
attr_reader :milestone, :old_milestone
- def initialize(resource, user, created_at: Time.current, old_milestone:)
- super(resource, user, created_at: created_at)
+ def initialize(resource, user, old_milestone:)
+ super(resource, user)
@milestone = resource&.milestone
@old_milestone = old_milestone
diff --git a/app/services/security/ci_configuration/sast_create_service.rb b/app/services/security/ci_configuration/sast_create_service.rb
new file mode 100644
index 00000000000..8fc3b8d078c
--- /dev/null
+++ b/app/services/security/ci_configuration/sast_create_service.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class SastCreateService < ::BaseService
+ def initialize(project, current_user, params)
+ @project = project
+ @current_user = current_user
+ @params = params
+ @branch_name = @project.repository.next_branch('set-sast-config')
+ end
+
+ def execute
+ attributes_for_commit = attributes
+ result = ::Files::MultiService.new(@project, @current_user, attributes_for_commit).execute
+
+ if result[:status] == :success
+ result[:success_path] = successful_change_path
+ track_event(attributes_for_commit)
+ else
+ result[:errors] = result[:message]
+ end
+
+ result
+
+ rescue Gitlab::Git::PreReceiveError => e
+ { status: :error, errors: e.message }
+ end
+
+ private
+
+ def attributes
+ actions = Security::CiConfiguration::SastBuildActions.new(@project.auto_devops_enabled?, @params, existing_gitlab_ci_content).generate
+
+ @project.repository.add_branch(@current_user, @branch_name, @project.default_branch)
+ message = _('Set .gitlab-ci.yml to enable or configure SAST')
+
+ {
+ commit_message: message,
+ branch_name: @branch_name,
+ start_branch: @branch_name,
+ actions: actions
+ }
+ end
+
+ def existing_gitlab_ci_content
+ gitlab_ci_yml = @project.repository.gitlab_ci_yml_for(@project.repository.root_ref_sha)
+ YAML.safe_load(gitlab_ci_yml) if gitlab_ci_yml
+ end
+
+ def successful_change_path
+ description = _('Set .gitlab-ci.yml to enable or configure SAST security scanning 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.')
+ merge_request_params = { source_branch: @branch_name, description: description }
+ Gitlab::Routing.url_helpers.project_new_merge_request_url(@project, merge_request: merge_request_params)
+ end
+
+ def track_event(attributes_for_commit)
+ action = attributes_for_commit[:actions].first
+
+ Gitlab::Tracking.event(
+ self.class.to_s, action[:action], label: action[:default_values_overwritten].to_s
+ )
+ end
+ end
+ end
+end
diff --git a/app/services/security/ci_configuration/sast_parser_service.rb b/app/services/security/ci_configuration/sast_parser_service.rb
new file mode 100644
index 00000000000..a8fe5764d19
--- /dev/null
+++ b/app/services/security/ci_configuration/sast_parser_service.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ # This class parses SAST template file and .gitlab-ci.yml to populate default and current values into the JSON
+ # read from app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+ class SastParserService < ::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ SAST_UI_SCHEMA_PATH = 'app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json'
+
+ def initialize(project)
+ @project = project
+ end
+
+ def configuration
+ result = Gitlab::Json.parse(File.read(Rails.root.join(SAST_UI_SCHEMA_PATH))).with_indifferent_access
+ populate_default_value_for(result, :global)
+ populate_default_value_for(result, :pipeline)
+ fill_current_value_with_default_for(result, :global)
+ fill_current_value_with_default_for(result, :pipeline)
+ populate_current_value_for(result, :global)
+ populate_current_value_for(result, :pipeline)
+
+ fill_current_value_with_default_for_analyzers(result)
+ populate_current_value_for_analyzers(result)
+
+ result
+ end
+
+ private
+
+ def sast_template_content
+ Gitlab::Template::GitlabCiYmlTemplate.find('SAST').content
+ end
+
+ def populate_default_value_for(config, level)
+ set_each(config[level], key: :default_value, with: sast_template_attributes)
+ end
+
+ def populate_current_value_for(config, level)
+ set_each(config[level], key: :value, with: gitlab_ci_yml_attributes)
+ end
+
+ def fill_current_value_with_default_for(config, level)
+ set_each(config[level], key: :value, with: sast_template_attributes)
+ end
+
+ def set_each(config_attributes, key:, with:)
+ config_attributes.each do |entity|
+ entity[key] = with[entity[:field]] if with[entity[:field]]
+ end
+ end
+
+ def fill_current_value_with_default_for_analyzers(result)
+ result[:analyzers].each do |analyzer|
+ analyzer[:variables].each do |entity|
+ entity[:value] = entity[:default_value] if entity[:default_value]
+ end
+ end
+ end
+
+ def populate_current_value_for_analyzers(result)
+ result[:analyzers].each do |analyzer|
+ analyzer[:enabled] = analyzer_enabled?(analyzer[:name])
+ populate_current_value_for(analyzer, :variables)
+ end
+ end
+
+ def analyzer_enabled?(analyzer_name)
+ # Unless explicitly listed in the excluded analyzers, consider it enabled
+ sast_excluded_analyzers.exclude?(analyzer_name)
+ end
+
+ def sast_excluded_analyzers
+ strong_memoize(:sast_excluded_analyzers) do
+ all_analyzers = Security::CiConfiguration::SastBuildActions::SAST_DEFAULT_ANALYZERS.split(', ') rescue []
+ enabled_analyzers = sast_default_analyzers.split(',').map(&:strip) rescue []
+
+ excluded_analyzers = gitlab_ci_yml_attributes["SAST_EXCLUDED_ANALYZERS"] || sast_template_attributes["SAST_EXCLUDED_ANALYZERS"]
+ excluded_analyzers = excluded_analyzers.split(',').map(&:strip) rescue []
+ ((all_analyzers - enabled_analyzers) + excluded_analyzers).uniq
+ end
+ end
+
+ def sast_default_analyzers
+ @sast_default_analyzers ||= gitlab_ci_yml_attributes["SAST_DEFAULT_ANALYZERS"] || sast_template_attributes["SAST_DEFAULT_ANALYZERS"]
+ end
+
+ def sast_template_attributes
+ @sast_template_attributes ||= build_sast_attributes(sast_template_content)
+ end
+
+ def gitlab_ci_yml_attributes
+ @gitlab_ci_yml_attributes ||= begin
+ config_content = @project.repository.blob_data_at(@project.repository.root_ref_sha, ci_config_file)
+ return {} unless config_content
+
+ build_sast_attributes(config_content)
+ end
+ end
+
+ def ci_config_file
+ '.gitlab-ci.yml'
+ end
+
+ def build_sast_attributes(content)
+ options = { project: @project, user: current_user, sha: @project.repository.commit.sha }
+ yaml_result = Gitlab::Ci::YamlProcessor.new(content, options).execute
+ return {} unless yaml_result.valid?
+
+ sast_attributes = yaml_result.build_attributes(:sast)
+ extract_required_attributes(sast_attributes)
+ end
+
+ def extract_required_attributes(attributes)
+ result = {}
+ attributes[:yaml_variables].each do |variable|
+ result[variable[:key]] = variable[:value]
+ end
+
+ result[:stage] = attributes[:stage]
+ result.with_indifferent_access
+ end
+ end
+ end
+end
diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb
index 278857b7933..415cfcb7d8f 100644
--- a/app/services/snippets/base_service.rb
+++ b/app/services/snippets/base_service.rb
@@ -2,8 +2,6 @@
module Snippets
class BaseService < ::BaseService
- include SpamCheckMethods
-
UPDATE_COMMIT_MSG = 'Update snippet'
INITIAL_COMMIT_MSG = 'Initial commit'
@@ -18,8 +16,6 @@ module Snippets
input_actions = Array(@params.delete(:snippet_actions).presence)
@snippet_actions = SnippetInputActionCollection.new(input_actions, allowed_actions: restricted_files_actions)
-
- filter_spam_check_params
end
private
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index 0881be73eaf..802bfd813dc 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -3,20 +3,32 @@
module Snippets
class CreateService < Snippets::BaseService
def execute
+ # NOTE: disable_spam_action_service can be removed when the ':snippet_spam' feature flag is removed.
+ disable_spam_action_service = params.delete(:disable_spam_action_service) == true
+ @request = params.delete(:request)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+
@snippet = build_from_params
return invalid_params_error(@snippet) unless valid_params?
- unless visibility_allowed?(@snippet, @snippet.visibility_level)
- return forbidden_visibility_error(@snippet)
+ unless visibility_allowed?(snippet, snippet.visibility_level)
+ return forbidden_visibility_error(snippet)
end
@snippet.author = current_user
- spam_check(@snippet, current_user, action: :create)
+ unless disable_spam_action_service
+ Spam::SpamActionService.new(
+ spammable: @snippet,
+ request: request,
+ user: current_user,
+ action: :create
+ ).execute(spam_params: spam_params)
+ end
if save_and_commit
- UserAgentDetailService.new(@snippet, @request).create
+ UserAgentDetailService.new(@snippet, request).create
Gitlab::UsageDataCounters::SnippetCounter.count(:create)
move_temporary_files
@@ -29,6 +41,8 @@ module Snippets
private
+ attr_reader :snippet, :request, :spam_params
+
def build_from_params
if project
project.snippets.build(create_params)
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index b982ff98747..5b427817a02 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -7,6 +7,11 @@ module Snippets
UpdateError = Class.new(StandardError)
def execute(snippet)
+ # NOTE: disable_spam_action_service can be removed when the ':snippet_spam' feature flag is removed.
+ disable_spam_action_service = params.delete(:disable_spam_action_service) == true
+ @request = params.delete(:request)
+ @spam_params = Spam::SpamActionService.filter_spam_params!(params)
+
return invalid_params_error(snippet) unless valid_params?
if visibility_changed?(snippet) && !visibility_allowed?(snippet, visibility_level)
@@ -14,12 +19,20 @@ module Snippets
end
update_snippet_attributes(snippet)
- spam_check(snippet, current_user, action: :update)
+
+ unless disable_spam_action_service
+ Spam::SpamActionService.new(
+ spammable: snippet,
+ request: request,
+ user: current_user,
+ action: :update
+ ).execute(spam_params: spam_params)
+ end
if save_and_commit(snippet)
Gitlab::UsageDataCounters::SnippetCounter.count(:update)
- ServiceResponse.success(payload: { snippet: snippet } )
+ ServiceResponse.success(payload: { snippet: snippet })
else
snippet_error_response(snippet, 400)
end
@@ -27,6 +40,8 @@ module Snippets
private
+ attr_reader :request, :spam_params
+
def visibility_changed?(snippet)
visibility_level && visibility_level.to_i != snippet.visibility_level
end
diff --git a/app/services/spam/spam_action_service.rb b/app/services/spam/spam_action_service.rb
index b3d617256ff..ff32bc32d93 100644
--- a/app/services/spam/spam_action_service.rb
+++ b/app/services/spam/spam_action_service.rb
@@ -4,37 +4,69 @@ module Spam
class SpamActionService
include SpamConstants
+ ##
+ # Utility method to filter SpamParams from parameters, which will later be passed to #execute
+ # after the spammable is created/updated based on the remaining parameters.
+ #
+ # Takes a hash of parameters from an incoming request to modify a model (via a controller,
+ # service, or GraphQL mutation).
+ #
+ # Deletes the parameters which are related to spam and captcha processing, and returns
+ # them in a SpamParams parameters object. See:
+ # https://refactoring.com/catalog/introduceParameterObject.html
+ def self.filter_spam_params!(params)
+ # NOTE: The 'captcha_response' field can be expanded to multiple fields when we move to future
+ # alternative captcha implementations such as FriendlyCaptcha. See
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/273480
+ captcha_response = params.delete(:captcha_response)
+
+ SpamParams.new(
+ api: params.delete(:api),
+ captcha_response: captcha_response,
+ spam_log_id: params.delete(:spam_log_id)
+ )
+ end
+
attr_accessor :target, :request, :options
attr_reader :spam_log
- def initialize(spammable:, request:, user:, context: {})
+ def initialize(spammable:, request:, user:, action:)
@target = spammable
@request = request
@user = user
- @context = context
+ @action = action
@options = {}
+ end
- if @request
- @options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s
- @options[:user_agent] = @request.env['HTTP_USER_AGENT']
- @options[:referrer] = @request.env['HTTP_REFERRER']
+ def execute(spam_params:)
+ if request
+ options[:ip_address] = request.env['action_dispatch.remote_ip'].to_s
+ options[:user_agent] = request.env['HTTP_USER_AGENT']
+ options[:referrer] = request.env['HTTP_REFERRER']
else
- @options[:ip_address] = @target.ip_address
- @options[:user_agent] = @target.user_agent
+ # TODO: This code is never used, because we do not perform a verification if there is not a
+ # request. Why? Should it be deleted? Or should we check even if there is no request?
+ options[:ip_address] = target.ip_address
+ options[:user_agent] = target.user_agent
end
- end
- def execute(api: false, recaptcha_verified:, spam_log_id:)
+ recaptcha_verified = Captcha::CaptchaVerificationService.new.execute(
+ captcha_response: spam_params.captcha_response,
+ request: request
+ )
+
if recaptcha_verified
- # If it's a request which is already verified through reCAPTCHA,
+ # If it's a request which is already verified through captcha,
# update the spam log accordingly.
- SpamLog.verify_recaptcha!(user_id: user.id, id: spam_log_id)
+ SpamLog.verify_recaptcha!(user_id: user.id, id: spam_params.spam_log_id)
+ ServiceResponse.success(message: "Captcha was successfully verified")
else
- return if allowlisted?(user)
- return unless request
- return unless check_for_spam?
+ return ServiceResponse.success(message: 'Skipped spam check because user was allowlisted') if allowlisted?(user)
+ return ServiceResponse.success(message: 'Skipped spam check because request was not present') unless request
+ return ServiceResponse.success(message: 'Skipped spam check because it was not required') unless check_for_spam?
- perform_spam_service_check(api)
+ perform_spam_service_check(spam_params.api)
+ ServiceResponse.success(message: "Spam check performed, check #{target.class.name} spammable model for any errors or captcha requirement")
end
end
@@ -42,13 +74,27 @@ module Spam
private
- attr_reader :user, :context
+ attr_reader :user, :action
+
+ ##
+ # In order to be proceed to the spam check process, the target must be
+ # a dirty instance, which means it should be already assigned with the new
+ # attribute values.
+ def ensure_target_is_dirty
+ msg = "Target instance of #{target.class.name} must be dirty (must have changes to save)"
+ raise(msg) unless target.has_changes_to_save?
+ end
def allowlisted?(user)
user.try(:gitlab_employee?) || user.try(:gitlab_bot?) || user.try(:gitlab_service_user?)
end
+ ##
+ # Performs the spam check using the spam verdict service, and modifies the target model
+ # accordingly based on the result.
def perform_spam_service_check(api)
+ ensure_target_is_dirty
+
# since we can check for spam, and recaptcha is not verified,
# ask the SpamVerdictService what to do with the target.
spam_verdict_service.execute.tap do |result|
@@ -79,7 +125,7 @@ module Spam
description: target.spam_description,
source_ip: options[:ip_address],
user_agent: options[:user_agent],
- noteable_type: notable_type,
+ noteable_type: noteable_type,
via_api: api
}
)
@@ -88,14 +134,19 @@ module Spam
end
def spam_verdict_service
+ context = {
+ action: action,
+ target_type: noteable_type
+ }
+
SpamVerdictService.new(target: target,
user: user,
- request: @request,
+ request: request,
options: options,
- context: context.merge(target_type: notable_type))
+ context: context)
end
- def notable_type
+ def noteable_type
@notable_type ||= target.class.to_s
end
end
diff --git a/app/services/spam/spam_params.rb b/app/services/spam/spam_params.rb
new file mode 100644
index 00000000000..fef5355c7f3
--- /dev/null
+++ b/app/services/spam/spam_params.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Spam
+ ##
+ # This class is a Parameter Object (https://refactoring.com/catalog/introduceParameterObject.html)
+ # which acts as an container abstraction for multiple parameter values related to spam and
+ # captcha processing for a request.
+ #
+ # Values contained are:
+ #
+ # api: A boolean flag indicating if the request was submitted via the REST or GraphQL API
+ # captcha_response: The response resulting from the user solving a captcha. Currently it is
+ # a scalar reCAPTCHA response string, but it can be expanded to an object in the future to
+ # support other captcha implementations such as FriendlyCaptcha.
+ # spam_log_id: The id of a SpamLog record.
+ class SpamParams
+ attr_reader :api, :captcha_response, :spam_log_id
+
+ def initialize(api:, captcha_response:, spam_log_id:)
+ @api = api.present?
+ @captcha_response = captcha_response
+ @spam_log_id = spam_log_id
+ end
+
+ def ==(other)
+ other.class == self.class &&
+ other.api == self.api &&
+ other.captcha_response == self.captcha_response &&
+ other.spam_log_id == self.spam_log_id
+ end
+ end
+end
diff --git a/app/services/suggestions/apply_service.rb b/app/services/suggestions/apply_service.rb
index ab80b23a37b..f9783f4271f 100644
--- a/app/services/suggestions/apply_service.rb
+++ b/app/services/suggestions/apply_service.rb
@@ -2,8 +2,9 @@
module Suggestions
class ApplyService < ::BaseService
- def initialize(current_user, *suggestions)
+ def initialize(current_user, *suggestions, message: nil)
@current_user = current_user
+ @message = message
@suggestion_set = Gitlab::Suggestions::SuggestionSet.new(suggestions)
end
@@ -30,6 +31,9 @@ module Suggestions
Suggestion.id_in(suggestion_set.suggestions)
.update_all(commit_id: result[:result], applied: true)
+
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
+ .track_apply_suggestion_action(user: current_user)
end
def multi_service
@@ -44,7 +48,7 @@ module Suggestions
end
def commit_message
- Gitlab::Suggestions::CommitMessage.new(current_user, suggestion_set).message
+ Gitlab::Suggestions::CommitMessage.new(current_user, suggestion_set, @message).message
end
end
end
diff --git a/app/services/suggestions/create_service.rb b/app/services/suggestions/create_service.rb
index 93d2bd11426..a97c36fa0ca 100644
--- a/app/services/suggestions/create_service.rb
+++ b/app/services/suggestions/create_service.rb
@@ -27,6 +27,8 @@ module Suggestions
rows.in_groups_of(100, false) do |rows|
Gitlab::Database.bulk_insert('suggestions', rows) # rubocop:disable Gitlab/BulkInsert
end
+
+ Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_add_suggestion_action(user: @note.author)
end
end
end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 881a139437a..5273dedb56f 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class SystemHooksService
- BUILDER_DRIVEN_EVENT_DATA_AVAILABLE_FOR_CLASSES = [GroupMember].freeze
+ BUILDER_DRIVEN_EVENT_DATA_AVAILABLE_FOR_CLASSES = [GroupMember, Group].freeze
def execute_hooks_for(model, event)
data = build_event_data(model, event)
@@ -58,15 +58,6 @@ class SystemHooksService
end
when ProjectMember
data.merge!(project_member_data(model))
- when Group
- data.merge!(group_data(model))
-
- if event == :rename
- data.merge!(
- old_path: model.path_before_last_save,
- old_full_path: model.full_path_before_last_save
- )
- end
end
data
@@ -114,19 +105,6 @@ class SystemHooksService
}
end
- def group_data(model)
- owner = model.owner
-
- {
- name: model.name,
- path: model.path,
- full_path: model.full_path,
- group_id: model.id,
- owner_name: owner.try(:name),
- owner_email: owner.try(:email)
- }
- end
-
def user_data(model)
{
name: model.name,
@@ -141,10 +119,14 @@ class SystemHooksService
end
def builder_driven_event_data(model, event)
- case model
- when GroupMember
- Gitlab::HookData::GroupMemberBuilder.new(model).build(event)
- end
+ builder_class = case model
+ when GroupMember
+ Gitlab::HookData::GroupMemberBuilder
+ when Group
+ Gitlab::HookData::GroupBuilder
+ end
+
+ builder_class.new(model).build(event)
end
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 58f72e9badc..7d654ca7f5b 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -168,16 +168,19 @@ module SystemNoteService
# project - Project owning noteable
# author - User performing the change
# branch_type - 'source' or 'target'
+ # event_type - the source of event: 'update' or 'delete'
# old_branch - old branch name
# new_branch - new branch name
#
- # Example Note text:
+ # Example Note text is based on event_type:
#
- # "changed target branch from `Old` to `New`"
+ # update: "changed target branch from `Old` to `New`"
+ # delete: "changed automatically target branch to `New` because `Old` was deleted"
#
# Returns the created Note object
- def change_branch(noteable, project, author, branch_type, old_branch, new_branch)
- ::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).change_branch(branch_type, old_branch, new_branch)
+ def change_branch(noteable, project, author, branch_type, event_type, old_branch, new_branch)
+ ::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author)
+ .change_branch(branch_type, event_type, old_branch, new_branch)
end
# Called when a branch in Noteable is added or deleted
diff --git a/app/services/system_notes/merge_requests_service.rb b/app/services/system_notes/merge_requests_service.rb
index a51e2053394..99e03e67bf1 100644
--- a/app/services/system_notes/merge_requests_service.rb
+++ b/app/services/system_notes/merge_requests_service.rb
@@ -83,16 +83,26 @@ module SystemNotes
# Called when a branch in Noteable is changed
#
# branch_type - 'source' or 'target'
+ # event_type - the source of event: 'update' or 'delete'
# old_branch - old branch name
# new_branch - new branch name
+
+ # Example Note text is based on event_type:
#
- # Example Note text:
- #
- # "changed target branch from `Old` to `New`"
+ # update: "changed target branch from `Old` to `New`"
+ # delete: "changed automatically target branch to `New` because `Old` was deleted"
#
# Returns the created Note object
- def change_branch(branch_type, old_branch, new_branch)
- body = "changed #{branch_type} branch from `#{old_branch}` to `#{new_branch}`"
+ def change_branch(branch_type, event_type, old_branch, new_branch)
+ body =
+ case event_type.to_s
+ when 'delete'
+ "changed automatically #{branch_type} branch to `#{new_branch}` because `#{old_branch}` was deleted"
+ when 'update'
+ "changed #{branch_type} branch from `#{old_branch}` to `#{new_branch}`"
+ else
+ raise ArgumentError, "invalid value for event_type: #{event_type}"
+ end
create_note(NoteSummary.new(noteable, project, author, body, action: 'branch'))
end
diff --git a/app/services/terraform/remote_state_handler.rb b/app/services/terraform/remote_state_handler.rb
index 7e79cb9e007..9500a821071 100644
--- a/app/services/terraform/remote_state_handler.rb
+++ b/app/services/terraform/remote_state_handler.rb
@@ -68,12 +68,14 @@ module Terraform
find_params = { project: project, name: params[:name] }
- if find_only
- Terraform::State.find_by(find_params) || # rubocop: disable CodeReuse/ActiveRecord
- raise(ActiveRecord::RecordNotFound.new("Couldn't find state"))
- else
- Terraform::State.create_or_find_by(find_params)
- end
+ return find_state!(find_params) if find_only
+
+ state = Terraform::State.create_or_find_by(find_params)
+
+ # https://github.com/rails/rails/issues/36027
+ return state unless state.errors.of_kind? :name, :taken
+
+ find_state(find_params)
end
def lock_matches?(state)
@@ -86,5 +88,13 @@ module Terraform
def can_modify_state?
current_user.can?(:admin_terraform_state, project)
end
+
+ def find_state(find_params)
+ Terraform::State.find_by(find_params) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def find_state!(find_params)
+ find_state(find_params) || raise(ActiveRecord::RecordNotFound.new("Couldn't find state"))
+ end
end
end
diff --git a/app/services/test_hooks/system_service.rb b/app/services/test_hooks/system_service.rb
index 66d78bfc578..10d23421719 100644
--- a/app/services/test_hooks/system_service.rb
+++ b/app/services/test_hooks/system_service.rb
@@ -20,7 +20,8 @@ module TestHooks
end
def merge_requests_events_data
- merge_request = MergeRequest.of_projects(current_user.projects.select(:id)).first
+ merge_request = MergeRequest.of_projects(current_user.projects.select(:id)).last
+
return { error: s_('TestHooks|Ensure one of your projects has merge requests.') } unless merge_request.present?
merge_request.to_hook_data(current_user)
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 12d26fe890b..dea116c8546 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -212,6 +212,11 @@ class TodoService
current_user.update_todos_count_cache
end
+ def create_request_review_todo(target, author, reviewers)
+ attributes = attributes_for_todo(target.project, target, author, Todo::REVIEW_REQUESTED)
+ create_todos(reviewers, attributes)
+ end
+
private
def create_todos(users, attributes)
@@ -266,8 +271,7 @@ class TodoService
def create_reviewer_todo(target, author, old_reviewers = [])
if target.reviewers.any?
reviewers = target.reviewers - old_reviewers
- attributes = attributes_for_todo(target.project, target, author, Todo::REVIEW_REQUESTED)
- create_todos(reviewers, attributes)
+ create_request_review_todo(target, author, reviewers)
end
end
diff --git a/app/services/users/approve_service.rb b/app/services/users/approve_service.rb
index debd1e8cd17..fea7fc55d90 100644
--- a/app/services/users/approve_service.rb
+++ b/app/services/users/approve_service.rb
@@ -8,8 +8,7 @@ module Users
def execute(user)
return error(_('You are not allowed to approve a user'), :forbidden) unless allowed?
- return error(_('The user you are trying to approve is not pending an approval'), :conflict) if user.active?
- return error(_('The user you are trying to approve is not pending an approval'), :conflict) unless approval_required?(user)
+ return error(_('The user you are trying to approve is not pending approval'), :conflict) if user.active? || !approval_required?(user)
if user.activate
# Resends confirmation email if the user isn't confirmed yet.
@@ -18,6 +17,7 @@ module Users
user.accept_pending_invitations! if user.active_for_authentication?
DeviseMailer.user_admin_approval(user).deliver_later
+ log_event(user)
after_approve_hook(user)
success(message: 'Success', http_status: :created)
else
@@ -40,6 +40,10 @@ module Users
def approval_required?(user)
user.blocked_pending_approval?
end
+
+ def log_event(user)
+ Gitlab::AppLogger.info(message: "User instance access request approved", user: "#{user.username}", email: "#{user.email}", approved_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}")
+ end
end
end
diff --git a/app/services/users/batch_status_cleaner_service.rb b/app/services/users/batch_status_cleaner_service.rb
new file mode 100644
index 00000000000..ea6142f13cc
--- /dev/null
+++ b/app/services/users/batch_status_cleaner_service.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Users
+ class BatchStatusCleanerService
+ BATCH_SIZE = 100.freeze
+
+ # Cleanup BATCH_SIZE user_statuses records
+ # rubocop: disable CodeReuse/ActiveRecord
+ def self.execute(batch_size: BATCH_SIZE)
+ scope = UserStatus
+ .select(:user_id)
+ .scheduled_for_cleanup
+ .lock('FOR UPDATE SKIP LOCKED')
+ .limit(batch_size)
+
+ deleted_rows = UserStatus.where(user_id: scope).delete_all
+
+ { deleted_rows: deleted_rows }
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index d0939d5a542..24e3fb73370 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -14,13 +14,14 @@ module Users
# service = Users::RefreshAuthorizedProjectsService.new(some_user)
# service.execute
class RefreshAuthorizedProjectsService
- attr_reader :user
+ attr_reader :user, :source
LEASE_TIMEOUT = 1.minute.to_i
# user - The User for which to refresh the authorized projects.
- def initialize(user, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil)
+ def initialize(user, source: nil, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil)
@user = user
+ @source = source
@incorrect_auth_found_callback = incorrect_auth_found_callback
@missing_auth_found_callback = missing_auth_found_callback
@@ -91,6 +92,8 @@ module Users
# remove - The IDs of the authorization rows to remove.
# add - Rows to insert in the form `[user id, project id, access level]`
def update_authorizations(remove = [], add = [])
+ log_refresh_details(remove.length, add.length)
+
User.transaction do
user.remove_project_authorizations(remove) unless remove.empty?
ProjectAuthorization.insert_authorizations(add) unless add.empty?
@@ -101,6 +104,13 @@ module Users
user.reset
end
+ def log_refresh_details(rows_deleted, rows_added)
+ Gitlab::AppJsonLogger.info(event: 'authorized_projects_refresh',
+ 'authorized_projects_refresh.source': source,
+ 'authorized_projects_refresh.rows_deleted': rows_deleted,
+ 'authorized_projects_refresh.rows_added': rows_added)
+ end
+
def fresh_access_levels_per_project
fresh_authorizations.each_with_object({}) do |row, hash|
hash[row.project_id] = row.access_level
diff --git a/app/services/users/reject_service.rb b/app/services/users/reject_service.rb
index dd72547c688..0e3eb3e5dde 100644
--- a/app/services/users/reject_service.rb
+++ b/app/services/users/reject_service.rb
@@ -12,8 +12,12 @@ module Users
user.delete_async(deleted_by: current_user, params: { hard_delete: true })
+ after_reject_hook(user)
+
NotificationService.new.user_admin_rejection(user.name, user.email)
+ log_event(user)
+
success
end
@@ -24,5 +28,15 @@ module Users
def allowed?
can?(current_user, :reject_user)
end
+
+ def after_reject_hook(user)
+ # overridden by EE module
+ end
+
+ def log_event(user)
+ Gitlab::AppLogger.info(message: "User instance access request rejected", user: "#{user.username}", email: "#{user.email}", rejected_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}")
+ end
end
end
+
+Users::RejectService.prepend_if_ee('EE::Users::RejectService')
diff --git a/app/uploaders/packages/composer/cache_uploader.rb b/app/uploaders/packages/composer/cache_uploader.rb
new file mode 100644
index 00000000000..f8052ec4810
--- /dev/null
+++ b/app/uploaders/packages/composer/cache_uploader.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+class Packages::Composer::CacheUploader < GitlabUploader
+ include ObjectStorage::Concern
+
+ storage_options Gitlab.config.packages
+
+ after :store, :schedule_background_upload
+
+ alias_method :upload, :model
+
+ def filename
+ "#{model.file_sha256}.json"
+ end
+
+ def store_dir
+ dynamic_segment
+ end
+
+ private
+
+ def dynamic_segment
+ raise ObjectNotReadyError, 'Package model not ready' unless model.id
+
+ Gitlab::HashedPath.new("packages", "composer_cache", model.namespace_id, root_hash: model.namespace_id)
+ end
+end
diff --git a/app/uploaders/packages/debian/component_file_uploader.rb b/app/uploaders/packages/debian/component_file_uploader.rb
new file mode 100644
index 00000000000..e4d637fecac
--- /dev/null
+++ b/app/uploaders/packages/debian/component_file_uploader.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+class Packages::Debian::ComponentFileUploader < GitlabUploader
+ extend Workhorse::UploadPath
+ include ObjectStorage::Concern
+
+ storage_options Gitlab.config.packages
+
+ after :store, :schedule_background_upload
+
+ alias_method :upload, :model
+
+ def filename
+ model.file_name
+ end
+
+ def store_dir
+ dynamic_segment
+ end
+
+ private
+
+ def dynamic_segment
+ raise ObjectNotReadyError, 'Package model not ready' unless model.id && model.component.distribution.container_id
+
+ Gitlab::HashedPath.new("debian_#{model.class.container_type}_component_file", model.id, root_hash: model.component.distribution.container_id)
+ end
+end
diff --git a/app/uploaders/terraform/state_uploader.rb b/app/uploaders/terraform/state_uploader.rb
index d80725cb051..091b253b0ed 100644
--- a/app/uploaders/terraform/state_uploader.rb
+++ b/app/uploaders/terraform/state_uploader.rb
@@ -6,6 +6,10 @@ module Terraform
storage_options Gitlab.config.terraform_state
+ # TODO: Remove this line
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/232917
+ alias_method :upload, :model
+
delegate :terraform_state, :project_id, to: :model
# Use Lockbox to encrypt/decrypt the stored file (registers CarrierWave callbacks)
diff --git a/app/validators/json_schemas/application_setting_kroki_formats.json b/app/validators/json_schemas/application_setting_kroki_formats.json
new file mode 100644
index 00000000000..460dc74069f
--- /dev/null
+++ b/app/validators/json_schemas/application_setting_kroki_formats.json
@@ -0,0 +1,10 @@
+{
+ "description": "Kroki formats",
+ "type": "object",
+ "properties": {
+ "bpmn": { "type": "boolean" },
+ "excalidraw": { "type": "boolean" },
+ "blockdiag": { "type": "boolean" }
+ },
+ "additionalProperties": false
+}
diff --git a/app/validators/json_schemas/git_trailers.json b/app/validators/json_schemas/git_trailers.json
new file mode 100644
index 00000000000..18ac97226a7
--- /dev/null
+++ b/app/validators/json_schemas/git_trailers.json
@@ -0,0 +1,9 @@
+{
+ "description": "Git trailer key/value pairs",
+ "type": "object",
+ "patternProperties": {
+ ".*": {
+ "type": "string"
+ }
+ }
+}
diff --git a/app/validators/nested_attributes_duplicates_validator.rb b/app/validators/nested_attributes_duplicates_validator.rb
new file mode 100644
index 00000000000..b60350a6311
--- /dev/null
+++ b/app/validators/nested_attributes_duplicates_validator.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+# NestedAttributesDuplicates
+#
+# This validator is designed for especially the following condition
+# - Use `accepts_nested_attributes_for :xxx` in a parent model
+# - Use `validates :xxx, uniqueness: { scope: :xxx_id }` in a child model
+class NestedAttributesDuplicatesValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ return if child_attributes.any? { |child_attribute| record.errors.include?(:"#{attribute}.#{child_attribute}") }
+
+ if options[:scope]
+ scoped = value.group_by do |variable|
+ Array(options[:scope]).map { |attr| variable.send(attr) } # rubocop:disable GitlabSecurity/PublicSend
+ end
+ scoped.each_value { |scope| validate_duplicates(record, attribute, scope) }
+ else
+ validate_duplicates(record, attribute, value)
+ end
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def validate_duplicates(record, attribute, values)
+ child_attributes.each do |child_attribute|
+ duplicates = values.reject(&:marked_for_destruction?).group_by(&:"#{child_attribute}").select { |_, v| v.many? }.map(&:first)
+ if duplicates.any?
+ error_message = +"have duplicate values (#{duplicates.join(", ")})"
+ error_message << " for #{values.first.send(options[:scope])} scope" if options[:scope] # rubocop:disable GitlabSecurity/PublicSend
+ record.errors.add(attribute, error_message)
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def child_attributes
+ options[:child_attributes] || %i[key]
+ end
+end
diff --git a/app/validators/variable_duplicates_validator.rb b/app/validators/variable_duplicates_validator.rb
deleted file mode 100644
index d36a56e81b9..00000000000
--- a/app/validators/variable_duplicates_validator.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-# VariableDuplicatesValidator
-#
-# This validator is designed for especially the following condition
-# - Use `accepts_nested_attributes_for :xxx` in a parent model
-# - Use `validates :xxx, uniqueness: { scope: :xxx_id }` in a child model
-class VariableDuplicatesValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- return if record.errors.include?(:"#{attribute}.key")
-
- if options[:scope]
- scoped = value.group_by do |variable|
- Array(options[:scope]).map { |attr| variable.send(attr) } # rubocop:disable GitlabSecurity/PublicSend
- end
- scoped.each_value { |scope| validate_duplicates(record, attribute, scope) }
- else
- validate_duplicates(record, attribute, value)
- end
- end
-
- private
-
- # rubocop: disable CodeReuse/ActiveRecord
- def validate_duplicates(record, attribute, values)
- duplicates = values.reject(&:marked_for_destruction?).group_by(&:key).select { |_, v| v.many? }.map(&:first)
- if duplicates.any?
- error_message = +"have duplicate values (#{duplicates.join(", ")})"
- error_message << " for #{values.first.send(options[:scope])} scope" if options[:scope] # rubocop:disable GitlabSecurity/PublicSend
- record.errors.add(attribute, error_message)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-end
diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml
index c6781e91cfd..09b16c54700 100644
--- a/app/views/abuse_reports/new.html.haml
+++ b/app/views/abuse_reports/new.html.haml
@@ -25,4 +25,4 @@
= _("Explain the problem. If appropriate, provide a link to the relevant issue or comment.")
.form-actions
- = f.submit _("Send report"), class: "btn btn-success"
+ = f.submit _("Send report"), class: "gl-button btn btn-success"
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index c3d7fac6df7..3e1a76f31e1 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -13,7 +13,7 @@
%td
%strong.subheading.d-block.d-sm-none
= _('Reported by %{reporter}').html_safe % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
- .light.gl-display-none.gl-display-sm-block
+ .light.gl-display-none.gl-sm-display-block
= link_to(reporter.name, reporter)
.light.small
= time_ago_with_tooltip(abuse_report.created_at)
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
index 67ac9d1c7b8..e6f12f4785a 100644
--- a/app/views/admin/appearances/_form.html.haml
+++ b/app/views/admin/appearances/_form.html.haml
@@ -54,10 +54,10 @@
.col-lg-8
.form-group
= f.label :title, class: 'col-form-label label-bold'
- = f.text_field :title, class: "form-control"
+ = f.text_field :title, class: "form-control gl-form-input"
.form-group
= f.label :description, class: 'col-form-label label-bold'
- = f.text_area :description, class: "form-control", rows: 10
+ = f.text_area :description, class: "form-control gl-form-input", rows: 10
.hint
= parsed_with_gfm
.form-group
@@ -83,7 +83,7 @@
.form-group
= f.label :new_project_guidelines, class: 'col-form-label label-bold'
%p
- = f.text_area :new_project_guidelines, class: "form-control", rows: 10
+ = f.text_area :new_project_guidelines, class: "form-control gl-form-input", rows: 10
.hint
= parsed_with_gfm
@@ -96,7 +96,7 @@
.form-group
= f.label :profile_image_guidelines, class: 'col-form-label label-bold'
%p
- = f.text_area :profile_image_guidelines, class: "form-control", rows: 10
+ = f.text_area :profile_image_guidelines, class: "form-control gl-form-input", rows: 10
.hint
= parsed_with_gfm
diff --git a/app/views/admin/appearances/_system_header_footer_form.html.haml b/app/views/admin/appearances/_system_header_footer_form.html.haml
index b50778a1076..4571d34a497 100644
--- a/app/views/admin/appearances/_system_header_footer_form.html.haml
+++ b/app/views/admin/appearances/_system_header_footer_form.html.haml
@@ -9,10 +9,10 @@
.col-lg-8
.form-group
= form.label :header_message, _('Header message'), class: 'col-form-label label-bold'
- = form.text_area :header_message, placeholder: _('State your message to activate'), class: "form-control js-autosize"
+ = form.text_area :header_message, placeholder: _('State your message to activate'), class: "form-control gl-form-input js-autosize"
.form-group
= form.label :footer_message, _('Footer message'), class: 'col-form-label label-bold'
- = form.text_area :footer_message, placeholder: _('State your message to activate'), class: "form-control js-autosize"
+ = form.text_area :footer_message, placeholder: _('State your message to activate'), class: "form-control gl-form-input js-autosize"
.form-group
.form-check
= form.check_box :email_header_and_footer_enabled, class: 'form-check-input'
@@ -27,7 +27,7 @@
= _('Customize colors')
.form-group.js-toggle-colors-container.hide
= form.label :message_background_color, _('Background Color'), class: 'col-form-label label-bold'
- = form.color_field :message_background_color, class: "form-control"
+ = form.color_field :message_background_color, class: "form-control gl-form-input"
.form-group.js-toggle-colors-container.hide
= form.label :message_font_color, _('Font Color'), class: 'col-form-label label-bold'
- = form.color_field :message_font_color, class: "form-control"
+ = form.color_field :message_font_color, class: "form-control gl-form-input"
diff --git a/app/views/admin/appearances/preview_sign_in.html.haml b/app/views/admin/appearances/preview_sign_in.html.haml
index eec4719c13c..6e5bb45c3cc 100644
--- a/app/views/admin/appearances/preview_sign_in.html.haml
+++ b/app/views/admin/appearances/preview_sign_in.html.haml
@@ -3,10 +3,10 @@
%form.gl-show-field-errors
.form-group
= label_tag :login
- = text_field_tag :login, nil, class: "form-control top", title: 'Please provide your username or email address.'
+ = text_field_tag :login, nil, class: "form-control gl-form-input top", title: 'Please provide your username or email address.'
.form-group
= label_tag :password
- = password_field_tag :password, nil, class: "form-control bottom", title: 'This field is required.'
+ = password_field_tag :password, nil, class: "form-control gl-form-input bottom", title: 'This field is required.'
.form-group
= button_tag "Sign in", class: "btn gl-button btn-success"
diff --git a/app/views/admin/application_settings/_abuse.html.haml b/app/views/admin/application_settings/_abuse.html.haml
index c77615f9040..ea9bdbed9ae 100644
--- a/app/views/admin/application_settings/_abuse.html.haml
+++ b/app/views/admin/application_settings/_abuse.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :abuse_notification_email, 'Abuse reports notification email', class: 'label-bold'
- = f.text_field :abuse_notification_email, class: 'form-control'
+ = f.text_field :abuse_notification_email, class: 'form-control gl-form-input'
.form-text.text-muted
Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.
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 46155f3f670..009e0732911 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -10,27 +10,29 @@
.form-group
= f.label :default_projects_limit, _('Default projects limit'), class: 'label-bold'
- = f.number_field :default_projects_limit, class: 'form-control', title: _('Maximum number of projects.'), data: { toggle: 'tooltip', container: 'body' }
+ = f.number_field :default_projects_limit, class: 'form-control gl-form-input', title: _('Maximum number of projects.'), data: { toggle: 'tooltip', container: 'body' }
.form-group
= f.label :max_attachment_size, _('Maximum attachment size (MB)'), class: 'label-bold'
- = f.number_field :max_attachment_size, class: 'form-control', title: _('Maximum size of individual attachments in comments.'), data: { toggle: 'tooltip', container: 'body' }
+ = 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_if_exists 'admin/application_settings/repository_size_limit_setting', form: f
.form-group
= f.label :receive_max_input_size, _('Maximum push size (MB)'), class: 'label-light'
- = f.number_field :receive_max_input_size, class: 'form-control qa-receive-max-input-size-field', title: _('Maximum size limit for a single commit.'), data: { toggle: 'tooltip', container: 'body' }
+ = f.number_field :receive_max_input_size, class: 'form-control gl-form-input qa-receive-max-input-size-field', title: _('Maximum size limit for a single commit.'), data: { toggle: 'tooltip', container: 'body' }
.form-group
= f.label :max_import_size, _('Maximum import size (MB)'), class: 'label-light'
- = f.number_field :max_import_size, class: 'form-control qa-receive-max-import-size-field', title: _('Maximum size of import files.'), data: { toggle: 'tooltip', container: 'body' }
+ = f.number_field :max_import_size, class: 'form-control gl-form-input qa-receive-max-import-size-field', title: _('Maximum size of import files.'), data: { toggle: 'tooltip', container: 'body' }
%span.form-text.text-muted= _('0 for unlimited, only effective with remote storage enabled.')
.form-group
= f.label :session_expire_delay, _('Session duration (minutes)'), class: 'label-light'
- = f.number_field :session_expire_delay, class: 'form-control', title: _('Maximum duration of a session.'), data: { toggle: 'tooltip', container: 'body' }
+ = f.number_field :session_expire_delay, class: 'form-control gl-form-input', title: _('Maximum duration of a session.'), data: { toggle: 'tooltip', container: 'body' }
%span.form-text.text-muted#session_expire_delay_help_block= _('GitLab restart is required to apply changes.')
+ = render_if_exists 'admin/application_settings/git_two_factor_session_expiry', form: f
= render_if_exists 'admin/application_settings/personal_access_token_expiration_policy', form: f
= render_if_exists 'admin/application_settings/enforce_pat_expiration', form: f
+ = render_if_exists 'admin/application_settings/enforce_ssh_key_expiration', form: f
.form-group
= f.label :user_oauth_applications, _('User OAuth applications'), class: 'label-bold'
@@ -46,14 +48,14 @@
= _('Newly registered users will by default be external')
.gl-mt-3
= _('Internal users')
- = f.text_field :user_default_internal_regex, placeholder: _('Regex pattern'), class: 'form-control gl-mt-2'
+ = f.text_field :user_default_internal_regex, placeholder: _('Regex pattern'), class: 'form-control gl-form-input gl-mt-2'
.help-block
= _('Specify an e-mail address regex pattern to identify default internal users.')
= link_to _('More information'), help_page_path('user/permissions', anchor: 'setting-new-users-to-external'),
target: '_blank'
.form-group
= f.label :personal_access_token_prefix, _('Personal Access Token prefix'), class: 'label-light'
- = f.text_field :personal_access_token_prefix, placeholder: _('Max 20 characters'), class: 'form-control'
+ = f.text_field :personal_access_token_prefix, placeholder: _('Max 20 characters'), class: 'form-control gl-form-input'
.form-group
= f.label :user_show_add_ssh_key_message, _('Prompt users to upload SSH keys'), class: 'label-bold'
.form-check
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 9f384519c3a..f11770b397e 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -14,7 +14,7 @@
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank'
.form-group
= f.label :auto_devops_domain, s_('AdminSettings|Auto DevOps domain'), class: 'label-bold'
- = f.text_field :auto_devops_domain, class: 'form-control', placeholder: 'domain.com'
+ = f.text_field :auto_devops_domain, class: 'form-control gl-form-input', placeholder: 'domain.com'
.form-text.text-muted
= s_("AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages.")
.form-group
@@ -27,23 +27,31 @@
.form-group
= f.label :shared_runners_text, class: 'label-bold'
- = f.text_area :shared_runners_text, class: 'form-control', rows: 4
+ = f.text_area :shared_runners_text, class: 'form-control gl-form-input', rows: 4
.form-text.text-muted= _("Markdown enabled")
.form-group
= f.label :max_artifacts_size, _('Maximum artifacts size (MB)'), class: 'label-bold'
- = f.number_field :max_artifacts_size, class: 'form-control'
+ = f.number_field :max_artifacts_size, class: 'form-control gl-form-input'
.form-text.text-muted
= _("Set the maximum file size for each job's artifacts")
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size')
.form-group
= f.label :default_artifacts_expire_in, _('Default artifacts expiration'), class: 'label-bold'
- = f.text_field :default_artifacts_expire_in, class: 'form-control'
+ = f.text_field :default_artifacts_expire_in, class: 'form-control gl-form-input'
.form-text.text-muted
= html_escape(_("Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'default-artifacts-expiration')
.form-group
+ .form-check
+ = f.check_box :keep_latest_artifact, class: 'form-check-input'
+ = f.label :keep_latest_artifact, class: 'form-check-label' do
+ %strong
+ = s_('AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines')
+ .form-text.text-muted
+ = s_('AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire.')
+ .form-group
= f.label :archive_builds_in_human_readable, _('Archive jobs'), class: 'label-bold'
- = f.text_field :archive_builds_in_human_readable, class: 'form-control', placeholder: 'never'
+ = f.text_field :archive_builds_in_human_readable, class: 'form-control gl-form-input', placeholder: 'never'
.form-text.text-muted
= html_escape(_("Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
.form-group
@@ -51,13 +59,13 @@
= f.check_box :protected_ci_variables, class: 'form-check-input'
= f.label :protected_ci_variables, class: 'form-check-label' do
= s_('AdminSettings|Environment variables are protected by default')
- .form-text.text-muted
- = s_('AdminSettings|When creating a new environment variable it will be protected by default.')
+ .form-text.text-muted
+ = s_('AdminSettings|When creating a new environment variable it will be protected by default.')
.form-group
= f.label :ci_config_path, _('Default CI configuration path'), class: 'label-bold'
- = f.text_field :default_ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
+ = f.text_field :default_ci_config_path, class: 'form-control gl-form-input', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= _("The default CI configuration path for new projects.").html_safe
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-path'), target: '_blank'
= f.submit _('Save changes'), class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
index 6811c1e10d6..494558a6c2d 100644
--- a/app/views/admin/application_settings/_diff_limits.html.haml
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :diff_max_patch_bytes, 'Maximum diff patch size (Bytes)', class: 'label-light'
- = f.number_field :diff_max_patch_bytes, class: 'form-control'
+ = f.number_field :diff_max_patch_bytes, class: 'form-control gl-form-input'
%span.form-text.text-muted
Diff files surpassing this limit will be presented as 'too large'
and won't be expandable.
diff --git a/app/views/admin/application_settings/_eks.html.haml b/app/views/admin/application_settings/_eks.html.haml
index 589d754be04..8897d0eb14b 100644
--- a/app/views/admin/application_settings/_eks.html.haml
+++ b/app/views/admin/application_settings/_eks.html.haml
@@ -20,16 +20,16 @@
Enable Amazon EKS integration
.form-group
= f.label :eks_account_id, 'Account ID', class: 'label-bold'
- = f.text_field :eks_account_id, class: 'form-control'
+ = f.text_field :eks_account_id, class: 'form-control gl-form-input'
.form-group
= f.label :eks_access_key_id, 'Access key ID', class: 'label-bold'
- = f.text_field :eks_access_key_id, class: 'form-control'
+ = f.text_field :eks_access_key_id, class: 'form-control gl-form-input'
.form-text.text-muted
= _('AWS Access Key. Only required if not using role instance credentials')
.form-group
= f.label :eks_secret_access_key, 'Secret access key', class: 'label-bold'
- = f.password_field :eks_secret_access_key, autocomplete: 'off', class: 'form-control'
+ = f.password_field :eks_secret_access_key, autocomplete: 'off', class: 'form-control gl-form-input'
.form-text.text-muted
= _('AWS Secret Access Key. Only required if not using role instance credentials')
diff --git a/app/views/admin/application_settings/_email.html.haml b/app/views/admin/application_settings/_email.html.haml
index dd1be876505..89946c63bb0 100644
--- a/app/views/admin/application_settings/_email.html.haml
+++ b/app/views/admin/application_settings/_email.html.haml
@@ -18,7 +18,7 @@
= _('By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format.')
.form-group
= f.label :commit_email_hostname, _('Custom hostname (for private commit emails)'), class: 'label-bold'
- = f.text_field :commit_email_hostname, class: 'form-control'
+ = f.text_field :commit_email_hostname, class: 'form-control gl-form-input'
.form-text.text-muted
- commit_email_hostname_docs_link = link_to _('Learn more'), help_page_path('user/admin_area/settings/email.md', anchor: 'custom-hostname-for-private-commit-emails'), target: '_blank'
= _("This setting will update the hostname that is used to generate private commit emails. %{learn_more}").html_safe % { learn_more: commit_email_hostname_docs_link }
diff --git a/app/views/admin/application_settings/_external_authorization_service_form.html.haml b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
index c8c1f3e6214..07256c9f4fe 100644
--- a/app/views/admin/application_settings/_external_authorization_service_form.html.haml
+++ b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
@@ -2,7 +2,7 @@
.settings-header
%h4
= _('External authentication')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
= _('External Classification Policy Authorization')
@@ -22,29 +22,29 @@
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/external_authorization')
.form-group
= f.label :external_authorization_service_url, _('Service URL'), class: 'label-bold'
- = f.text_field :external_authorization_service_url, class: 'form-control'
+ = f.text_field :external_authorization_service_url, class: 'form-control gl-form-input'
%span.form-text.text-muted
= external_authorization_url_help_text
.form-group
= f.label :external_authorization_service_timeout, _('External authorization request timeout'), class: 'label-bold'
- = f.number_field :external_authorization_service_timeout, class: 'form-control', min: 0.001, max: 10, step: 0.001
+ = f.number_field :external_authorization_service_timeout, class: 'form-control gl-form-input', min: 0.001, max: 10, step: 0.001
%span.form-text.text-muted
= external_authorization_timeout_help_text
= f.label :external_auth_client_cert, _('Client authentication certificate'), class: 'label-bold'
- = f.text_area :external_auth_client_cert, class: 'form-control'
+ = f.text_area :external_auth_client_cert, class: 'form-control gl-form-input'
%span.form-text.text-muted
= external_authorization_client_certificate_help_text
.form-group
= f.label :external_auth_client_key, _('Client authentication key'), class: 'label-bold'
- = f.text_area :external_auth_client_key, class: 'form-control'
+ = f.text_area :external_auth_client_key, class: 'form-control gl-form-input'
%span.form-text.text-muted
= external_authorization_client_key_help_text
.form-group
= f.label :external_auth_client_key_pass, _('Client authentication key password'), class: 'label-bold'
- = f.password_field :external_auth_client_key_pass, class: 'form-control'
+ = f.password_field :external_auth_client_key_pass, class: 'form-control gl-form-input'
%span.form-text.text-muted
= external_authorization_client_pass_help_text
.form-group
= f.label :external_authorization_service_default_label, _('Default classification label'), class: 'label-bold'
- = f.text_field :external_authorization_service_default_label, class: 'form-control'
+ = f.text_field :external_authorization_service_default_label, class: 'form-control gl-form-input'
= f.submit 'Save changes', class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_gitaly.html.haml b/app/views/admin/application_settings/_gitaly.html.haml
index a0cd70b4d7c..56ec35d9329 100644
--- a/app/views/admin/application_settings/_gitaly.html.haml
+++ b/app/views/admin/application_settings/_gitaly.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :gitaly_timeout_default, 'Default Timeout Period', class: 'label-bold'
- = f.number_field :gitaly_timeout_default, class: 'form-control'
+ = f.number_field :gitaly_timeout_default, class: 'form-control gl-form-input'
.form-text.text-muted
Timeout for Gitaly calls from the GitLab application (in seconds). This timeout is not enforced
for git fetch/push operations or Sidekiq jobs.
@@ -13,14 +13,14 @@
the worker.
.form-group
= f.label :gitaly_timeout_fast, 'Fast Timeout Period', class: 'label-bold'
- = f.number_field :gitaly_timeout_fast, class: 'form-control'
+ = f.number_field :gitaly_timeout_fast, class: 'form-control gl-form-input'
.form-text.text-muted
Fast operation timeout (in seconds). Some Gitaly operations are expected to be fast.
If they exceed this threshold, there may be a problem with a storage shard and 'failing fast'
can help maintain the stability of the GitLab instance.
.form-group
= f.label :gitaly_timeout_medium, 'Medium Timeout Period', class: 'label-bold'
- = f.number_field :gitaly_timeout_medium, class: 'form-control'
+ = f.number_field :gitaly_timeout_medium, class: 'form-control gl-form-input'
.form-text.text-muted
Medium operation timeout (in seconds). This should be a value between the Fast and the Default timeout.
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
index 7f78cce4575..cca81136bb9 100644
--- a/app/views/admin/application_settings/_gitpod.html.haml
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -22,7 +22,7 @@
= f.label :gitpod_enabled, s_('Gitpod|Enable Gitpod integration'), class: 'form-check-label'
.form-group
= f.label :gitpod_url, s_('Gitpod|Gitpod URL'), class: 'label-bold'
- = f.text_field :gitpod_url, class: 'form-control', placeholder: s_('Gitpod|e.g. https://gitpod.example.com')
+ = f.text_field :gitpod_url, class: 'form-control gl-form-input', placeholder: s_('Gitpod|e.g. https://gitpod.example.com')
.form-text.text-muted
= s_('Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects.')
= f.submit s_('Save changes'), class: 'gl-button btn btn-success'
diff --git a/app/views/admin/application_settings/_grafana.html.haml b/app/views/admin/application_settings/_grafana.html.haml
index bd2b2094311..368b4db4549 100644
--- a/app/views/admin/application_settings/_grafana.html.haml
+++ b/app/views/admin/application_settings/_grafana.html.haml
@@ -12,6 +12,6 @@
= _('Enable access to Grafana')
.form-group
= f.label :grafana_url, _('Grafana URL'), class: 'label-bold'
- = f.text_field :grafana_url, class: 'form-control', placeholder: '/-/grafana'
+ = f.text_field :grafana_url, class: 'form-control gl-form-input', placeholder: '/-/grafana'
= f.submit _('Save changes'), class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_help_page.html.haml b/app/views/admin/application_settings/_help_page.html.haml
index fc31f612b8c..858df44bd98 100644
--- a/app/views/admin/application_settings/_help_page.html.haml
+++ b/app/views/admin/application_settings/_help_page.html.haml
@@ -6,7 +6,7 @@
.form-group
= f.label :help_page_text, class: 'label-bold'
- = f.text_area :help_page_text, class: 'form-control', rows: 4
+ = f.text_area :help_page_text, class: 'form-control gl-form-input', rows: 4
.form-text.text-muted= _('Markdown enabled')
.form-group
.form-check
@@ -15,12 +15,12 @@
= _('Hide marketing-related entries from help')
.form-group
= f.label :help_page_support_url, _('Support page URL'), class: 'label-bold'
- = f.text_field :help_page_support_url, class: 'form-control', placeholder: 'http://company.example.com/getting-help', :'aria-describedby' => 'support_help_block'
+ = f.text_field :help_page_support_url, class: 'form-control gl-form-input', placeholder: 'http://company.example.com/getting-help', :'aria-describedby' => 'support_help_block'
%span.form-text.text-muted#support_help_block= _('Alternate support URL for help page and help dropdown')
- if show_documentation_base_url_field?
.form-group
= f.label :help_page_documentation_base_url, _('Documentation pages URL'), class: 'label-bold'
- = f.text_field :help_page_documentation_base_url, class: 'form-control', placeholder: 'https://docs.gitlab.com'
+ = f.text_field :help_page_documentation_base_url, class: 'form-control gl-form-input', placeholder: 'https://docs.gitlab.com'
= f.submit _('Save changes'), class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_import_export_limits.html.haml b/app/views/admin/application_settings/_import_export_limits.html.haml
index 58218a41282..e1a58c888a5 100644
--- a/app/views/admin/application_settings/_import_export_limits.html.haml
+++ b/app/views/admin/application_settings/_import_export_limits.html.haml
@@ -4,31 +4,31 @@
%fieldset
.form-group
= f.label :project_import_limit, _('Max Project Import requests per minute per user'), class: 'label-bold'
- = f.number_field :project_import_limit, class: 'form-control'
+ = f.number_field :project_import_limit, class: 'form-control gl-form-input'
%fieldset
.form-group
= f.label :project_export_limit, _('Max Project Export requests per minute per user'), class: 'label-bold'
- = f.number_field :project_export_limit, class: 'form-control'
+ = f.number_field :project_export_limit, class: 'form-control gl-form-input'
%fieldset
.form-group
= f.label :project_download_export_limit, _('Max Project Export Download requests per minute per user'), class: 'label-bold'
- = f.number_field :project_download_export_limit, class: 'form-control'
+ = f.number_field :project_download_export_limit, class: 'form-control gl-form-input'
%fieldset
.form-group
= f.label :group_import_limit, _('Max Group Import requests per minute per user'), class: 'label-bold'
- = f.number_field :group_import_limit, class: 'form-control'
+ = f.number_field :group_import_limit, class: 'form-control gl-form-input'
%fieldset
.form-group
= f.label :group_export_limit, _('Max Group Export requests per minute per user'), class: 'label-bold'
- = f.number_field :group_export_limit, class: 'form-control'
+ = f.number_field :group_export_limit, class: 'form-control gl-form-input'
%fieldset
.form-group
= f.label :group_download_export_limit, _('Max Group Export Download requests per minute per user'), class: 'label-bold'
- = f.number_field :group_download_export_limit, class: 'form-control'
+ = f.number_field :group_download_export_limit, class: 'form-control gl-form-input'
= f.submit 'Save changes', class: "gl-button btn btn-success", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_initial_branch_name.html.haml b/app/views/admin/application_settings/_initial_branch_name.html.haml
index bab841fcade..e7718f94b90 100644
--- a/app/views/admin/application_settings/_initial_branch_name.html.haml
+++ b/app/views/admin/application_settings/_initial_branch_name.html.haml
@@ -6,7 +6,7 @@
%fieldset
.form-group
= f.label :default_branch_name, _('Default initial branch name'), class: 'label-light'
- = f.text_field :default_branch_name, placeholder: 'master', class: 'form-control'
+ = f.text_field :default_branch_name, placeholder: 'master', class: 'form-control gl-form-input'
%span.form-text.text-muted
= (_("Changes affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used.") % { branch_name_default: fallback_branch_name } ).html_safe
diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml
index 11ffe3f56e3..a603eaec913 100644
--- a/app/views/admin/application_settings/_ip_limits.html.haml
+++ b/app/views/admin/application_settings/_ip_limits.html.haml
@@ -13,10 +13,10 @@
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
= f.label :throttle_unauthenticated_requests_per_period, 'Max unauthenticated requests per period per IP', class: 'label-bold'
- = f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control'
+ = f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control gl-form-input'
.form-group
= f.label :throttle_unauthenticated_period_in_seconds, 'Unauthenticated rate limit period in seconds', class: 'label-bold'
- = f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control'
+ = f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control gl-form-input'
%hr
%h5
= _('Authenticated API request rate limit')
@@ -29,10 +29,10 @@
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
= f.label :throttle_authenticated_api_requests_per_period, 'Max authenticated API requests per period per user', class: 'label-bold'
- = f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control'
+ = f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control gl-form-input'
.form-group
= f.label :throttle_authenticated_api_period_in_seconds, 'Authenticated API rate limit period in seconds', class: 'label-bold'
- = f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control'
+ = f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control gl-form-input'
%hr
%h5
= _('Authenticated web request rate limit')
@@ -45,16 +45,16 @@
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
= f.label :throttle_authenticated_web_requests_per_period, 'Max authenticated web requests per period per user', class: 'label-bold'
- = f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control'
+ = f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control gl-form-input'
.form-group
= f.label :throttle_authenticated_web_period_in_seconds, 'Authenticated web rate limit period in seconds', class: 'label-bold'
- = f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control'
+ = f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control gl-form-input'
%hr
%h5
= _('Response text')
.form-group
= f.label :rate_limiting_response_text, class: 'label-bold' do
= _('A plain-text response to show to clients that hit the rate limit.')
- = f.text_area :rate_limiting_response_text, placeholder: ::Gitlab::Throttle::DEFAULT_RATE_LIMITING_RESPONSE_TEXT, class: 'form-control', rows: 5
+ = f.text_area :rate_limiting_response_text, placeholder: ::Gitlab::Throttle::DEFAULT_RATE_LIMITING_RESPONSE_TEXT, class: 'form-control gl-form-input', rows: 5
= f.submit 'Save changes', class: "gl-button btn btn-success", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_issue_limits.html.haml b/app/views/admin/application_settings/_issue_limits.html.haml
index 200ea3a8ec1..e16561b4489 100644
--- a/app/views/admin/application_settings/_issue_limits.html.haml
+++ b/app/views/admin/application_settings/_issue_limits.html.haml
@@ -4,6 +4,6 @@
%fieldset
.form-group
= f.label :issues_create_limit, 'Max requests per minute per user', class: 'label-bold'
- = f.number_field :issues_create_limit, class: 'form-control'
+ = f.number_field :issues_create_limit, class: 'form-control gl-form-input'
= f.submit 'Save changes', class: "gl-button btn btn-success", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_kroki.html.haml b/app/views/admin/application_settings/_kroki.html.haml
index 1547b28c651..cd57d4cca65 100644
--- a/app/views/admin/application_settings/_kroki.html.haml
+++ b/app/views/admin/application_settings/_kroki.html.haml
@@ -18,8 +18,16 @@
= f.label :kroki_enabled, _('Enable Kroki'), class: 'form-check-label'
.form-group
= f.label :kroki_url, 'Kroki URL', class: 'label-bold'
- = f.text_field :kroki_url, class: 'form-control', placeholder: 'http://your-kroki-instance:8000'
+ = f.text_field :kroki_url, class: 'form-control gl-form-input', placeholder: 'http://your-kroki-instance:8000'
.form-text.text-muted
= (_('When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you\'ve installed Kroki, make sure to update the server URL to point to your instance.') % { kroki_public_url: '<code>https://kroki.io</code>', install_link: link_to('install Kroki', 'https://docs.kroki.io/kroki/setup/install/', target: '_blank') }).html_safe
+ .form-group
+ = f.label :kroki_formats, 'Additional diagram formats', class: 'label-bold'
+ .form-text.text-muted
+ = (_('Using additional formats requires starting the companion containers. Make sure that all %{kroki_images} are running.') % { kroki_images: link_to('required containers', 'https://docs.kroki.io/kroki/setup/install/#_images', target: '_blank') }).html_safe
+ - kroki_available_formats.each do |format|
+ .form-check
+ = f.check_box format[:name], class: 'form-check-input'
+ = f.label format[:name], format[:label], class: 'form-check-label'
= f.submit _('Save changes'), class: "btn gl-button btn-success"
diff --git a/app/views/admin/application_settings/_note_limits.html.haml b/app/views/admin/application_settings/_note_limits.html.haml
new file mode 100644
index 00000000000..9578da90170
--- /dev/null
+++ b/app/views/admin/application_settings/_note_limits.html.haml
@@ -0,0 +1,12 @@
+= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-note-limits-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ .form-group
+ = f.label :notes_create_limit, _('Max requests per minute per user'), class: 'label-bold'
+ = f.number_field :notes_create_limit, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :notes_create_limit_allowlist, _('List of users to be excluded from the limit'), class: 'label-bold'
+ = f.text_area :notes_create_limit_allowlist_raw, placeholder: 'username1, username2', class: 'form-control gl-form-input', rows: 5
+
+ = f.submit _('Save changes'), class: "gl-button btn btn-success", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml
index db0a87c366e..694cc9deab6 100644
--- a/app/views/admin/application_settings/_outbound.html.haml
+++ b/app/views/admin/application_settings/_outbound.html.haml
@@ -15,7 +15,7 @@
.form-group
= f.label :outbound_local_requests_allowlist_raw, class: 'label-bold' do
= _('Local IP addresses and domain names that hooks and services may access.')
- = f.text_area :outbound_local_requests_allowlist_raw, placeholder: "example.com, 192.168.1.1", class: 'form-control', rows: 8
+ = f.text_area :outbound_local_requests_allowlist_raw, placeholder: "example.com, 192.168.1.1", class: 'form-control gl-form-input', rows: 8
%span.form-text.text-muted
= _('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.')
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
index 8c956a43e22..86df1aa6e02 100644
--- a/app/views/admin/application_settings/_package_registry.html.haml
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -31,20 +31,20 @@
= f.hidden_field(:plan_id, value: plan.id)
.form-group
= f.label :conan_max_file_size, _('Maximum Conan package file size in bytes'), class: 'label-bold'
- = f.number_field :conan_max_file_size, class: 'form-control'
+ = f.number_field :conan_max_file_size, class: 'form-control gl-form-input'
.form-group
= f.label :maven_max_file_size, _('Maximum Maven package file size in bytes'), class: 'label-bold'
- = f.number_field :maven_max_file_size, class: 'form-control'
+ = f.number_field :maven_max_file_size, class: 'form-control gl-form-input'
.form-group
= f.label :npm_max_file_size, _('Maximum NPM package file size in bytes'), class: 'label-bold'
- = f.number_field :npm_max_file_size, class: 'form-control'
+ = f.number_field :npm_max_file_size, class: 'form-control gl-form-input'
.form-group
= f.label :nuget_max_file_size, _('Maximum NuGet package file size in bytes'), class: 'label-bold'
- = f.number_field :nuget_max_file_size, class: 'form-control'
+ = f.number_field :nuget_max_file_size, class: 'form-control gl-form-input'
.form-group
= f.label :pypi_max_file_size, _('Maximum PyPI package file size in bytes'), class: 'label-bold'
- = f.number_field :pypi_max_file_size, class: 'form-control'
+ = f.number_field :pypi_max_file_size, class: 'form-control gl-form-input'
.form-group
= f.label :generic_packages_max_file_size, _('Generic package file size in bytes'), class: 'label-bold'
- = f.number_field :generic_packages_max_file_size, class: 'form-control'
+ = f.number_field :generic_packages_max_file_size, class: 'form-control gl-form-input'
= f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, class: 'btn gl-button btn-success'
diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml
index d42987eb7d8..503aae861d0 100644
--- a/app/views/admin/application_settings/_pages.html.haml
+++ b/app/views/admin/application_settings/_pages.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'label-bold'
- = f.number_field :max_pages_size, class: 'form-control'
+ = f.number_field :max_pages_size, class: 'form-control gl-form-input'
.form-text.text-muted
= _("0 for unlimited")
.form-group
@@ -31,7 +31,7 @@
= _("%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites.").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: '</a>'.html_safe }
.form-group
= f.label :lets_encrypt_notification_email, _("Email"), class: 'label-bold'
- = f.text_field :lets_encrypt_notification_email, class: 'form-control'
+ = f.text_field :lets_encrypt_notification_email, class: 'form-control gl-form-input'
.form-text.text-muted
= _("A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates.")
.form-group
diff --git a/app/views/admin/application_settings/_performance.html.haml b/app/views/admin/application_settings/_performance.html.haml
index 2d27bceef10..3efe163de7b 100644
--- a/app/views/admin/application_settings/_performance.html.haml
+++ b/app/views/admin/application_settings/_performance.html.haml
@@ -17,17 +17,17 @@
.form-group
= f.label :raw_blob_request_limit, _('Raw blob request rate limit per minute'), class: 'label-bold'
- = f.number_field :raw_blob_request_limit, class: 'form-control'
+ = f.number_field :raw_blob_request_limit, class: 'form-control gl-form-input'
.form-text.text-muted
= _('Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0.')
.form-group
= f.label :push_event_hooks_limit, class: 'label-bold'
- = f.number_field :push_event_hooks_limit, class: 'form-control'
+ = f.number_field :push_event_hooks_limit, class: 'form-control gl-form-input'
.form-text.text-muted
= _("Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value.")
.form-group
= f.label :push_event_activities_limit, class: 'label-bold'
- = f.number_field :push_event_activities_limit, class: 'form-control'
+ = f.number_field :push_event_activities_limit, class: 'form-control gl-form-input'
.form-text.text-muted
= _('Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value.')
diff --git a/app/views/admin/application_settings/_performance_bar.html.haml b/app/views/admin/application_settings/_performance_bar.html.haml
index 1036cc94bd0..2db22552596 100644
--- a/app/views/admin/application_settings/_performance_bar.html.haml
+++ b/app/views/admin/application_settings/_performance_bar.html.haml
@@ -9,6 +9,6 @@
Enable access to the Performance Bar
.form-group
= f.label :performance_bar_allowed_group_path, 'Allowed group', class: 'label-bold'
- = f.text_field :performance_bar_allowed_group_path, class: 'form-control', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
+ = f.text_field :performance_bar_allowed_group_path, class: 'form-control gl-form-input', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
= f.submit 'Save changes', class: 'gl-button btn btn-success qa-save-changes-button'
diff --git a/app/views/admin/application_settings/_plantuml.html.haml b/app/views/admin/application_settings/_plantuml.html.haml
index 77a310c73a8..93fcc90f044 100644
--- a/app/views/admin/application_settings/_plantuml.html.haml
+++ b/app/views/admin/application_settings/_plantuml.html.haml
@@ -18,7 +18,7 @@
= f.label :plantuml_enabled, _('Enable PlantUML'), class: 'form-check-label'
.form-group
= f.label :plantuml_url, 'PlantUML URL', class: 'label-bold'
- = f.text_field :plantuml_url, class: 'form-control', placeholder: 'http://your-plantuml-instance:8080'
+ = f.text_field :plantuml_url, class: 'form-control gl-form-input', placeholder: 'http://your-plantuml-instance:8080'
.form-text.text-muted
Allow rendering of
= link_to "PlantUML", "http://plantuml.com"
diff --git a/app/views/admin/application_settings/_prometheus.html.haml b/app/views/admin/application_settings/_prometheus.html.haml
index c571ec1c1b0..c394bc65046 100644
--- a/app/views/admin/application_settings/_prometheus.html.haml
+++ b/app/views/admin/application_settings/_prometheus.html.haml
@@ -25,7 +25,7 @@
= link_to sprite_icon('question-o'), help_page_path('administration/monitoring/prometheus/gitlab_metrics', anchor: 'metrics-shared-directory')
.form-group
= f.label :metrics_method_call_threshold, 'Method Call Threshold (ms)', class: 'label-bold'
- = f.number_field :metrics_method_call_threshold, class: 'form-control'
+ = f.number_field :metrics_method_call_threshold, class: 'form-control gl-form-input'
.form-text.text-muted
A method call is only tracked when it takes longer to complete than
the given amount of milliseconds.
diff --git a/app/views/admin/application_settings/_protected_paths.html.haml b/app/views/admin/application_settings/_protected_paths.html.haml
index fce64369f17..57bba4f970a 100644
--- a/app/views/admin/application_settings/_protected_paths.html.haml
+++ b/app/views/admin/application_settings/_protected_paths.html.haml
@@ -17,15 +17,15 @@
= _('Helps reduce request volume for protected paths')
.form-group
= f.label :throttle_protected_paths_requests_per_period, 'Max requests per period per user', class: 'label-bold'
- = f.number_field :throttle_protected_paths_requests_per_period, class: 'form-control'
+ = f.number_field :throttle_protected_paths_requests_per_period, class: 'form-control gl-form-input'
.form-group
= f.label :throttle_protected_paths_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold'
- = f.number_field :throttle_protected_paths_period_in_seconds, class: 'form-control'
+ = f.number_field :throttle_protected_paths_period_in_seconds, class: 'form-control gl-form-input'
.form-group
= f.label :protected_paths, class: 'label-bold' do
- relative_url_link = 'https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab'
- relative_url_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: relative_url_link }
= _('All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}.').html_safe % { relative_url_link_start: relative_url_link_start, relative_url_link_end: '</a>'.html_safe }
- = f.text_area :protected_paths_raw, placeholder: '/users/sign_in,/users/password', class: 'form-control', rows: 10
+ = f.text_area :protected_paths_raw, placeholder: '/users/sign_in,/users/password', class: 'form-control gl-form-input', rows: 10
= f.submit 'Save changes', class: 'gl-button btn btn-success'
diff --git a/app/views/admin/application_settings/_realtime.html.haml b/app/views/admin/application_settings/_realtime.html.haml
index cf0b2b53eff..2b54a15d615 100644
--- a/app/views/admin/application_settings/_realtime.html.haml
+++ b/app/views/admin/application_settings/_realtime.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :polling_interval_multiplier, 'Polling interval multiplier', class: 'label-bold'
- = f.text_field :polling_interval_multiplier, class: 'form-control'
+ = f.text_field :polling_interval_multiplier, class: 'form-control gl-form-input'
.form-text.text-muted
Change this value to influence how frequently the GitLab UI polls for updates.
If you set the value to 2 all polling intervals are multiplied
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index dd64d0ae419..5fb5effaa55 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'label-bold'
- = f.number_field :container_registry_token_expire_delay, class: 'form-control'
+ = f.number_field :container_registry_token_expire_delay, class: 'form-control gl-form-input'
.form-group
.form-check
= f.check_box :container_expiration_policies_enable_historic_entries, class: 'form-check-input'
@@ -14,11 +14,21 @@
.form-text.text-muted
= _("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.")
= link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/index', anchor: 'use-with-external-container-registries')
- - if limit_delete_tags_service?
+ - if container_registry_expiration_policies_throttling?
.form-group
= f.label :container_registry_delete_tags_service_timeout, _('Cleanup policy maximum processing time (seconds)'), class: 'label-bold'
- = f.number_field :container_registry_delete_tags_service_timeout, min: 0, class: 'form-control'
+ = f.number_field :container_registry_delete_tags_service_timeout, min: 0, class: 'form-control gl-form-input'
.form-text.text-muted
= _("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.")
+ .form-group
+ = f.label :container_registry_expiration_policies_worker_capacity, _('Cleanup policy maximum workers running concurrently'), class: 'label-bold'
+ = f.number_field :container_registry_expiration_policies_worker_capacity, min: 0, class: 'form-control'
+ .form-text.text-muted
+ = _("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.")
+ .form-group
+ = f.label :container_registry_cleanup_tags_service_max_list_size, _('Cleanup policy maximum number of tags to be deleted'), class: 'label-bold'
+ = f.number_field :container_registry_cleanup_tags_service_max_list_size, min: 0, class: 'form-control'
+ .form-text.text-muted
+ = _("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.")
= f.submit 'Save changes', class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_repository_check.html.haml b/app/views/admin/application_settings/_repository_check.html.haml
index b9c2e406b78..24e74dd0f1b 100644
--- a/app/views/admin/application_settings/_repository_check.html.haml
+++ b/app/views/admin/application_settings/_repository_check.html.haml
@@ -41,17 +41,17 @@
bitmaps should accelerate 'git clone' performance.
.form-group
= f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'label-bold'
- = f.number_field :housekeeping_incremental_repack_period, class: 'form-control'
+ = f.number_field :housekeeping_incremental_repack_period, class: 'form-control gl-form-input'
.form-text.text-muted
Number of Git pushes after which an incremental 'git repack' is run.
.form-group
= f.label :housekeeping_full_repack_period, 'Full repack period', class: 'label-bold'
- = f.number_field :housekeeping_full_repack_period, class: 'form-control'
+ = f.number_field :housekeeping_full_repack_period, class: 'form-control gl-form-input'
.form-text.text-muted
Number of Git pushes after which a full 'git repack' is run.
.form-group
= f.label :housekeeping_gc_period, 'Git GC period', class: 'label-bold'
- = f.number_field :housekeeping_gc_period, class: 'form-control'
+ = f.number_field :housekeeping_gc_period, class: 'form-control gl-form-input'
.form-text.text-muted
Number of Git pushes after which 'git gc' is run.
diff --git a/app/views/admin/application_settings/_repository_static_objects.html.haml b/app/views/admin/application_settings/_repository_static_objects.html.haml
index 00b9b4b8964..42fe2b24bb2 100644
--- a/app/views/admin/application_settings/_repository_static_objects.html.haml
+++ b/app/views/admin/application_settings/_repository_static_objects.html.haml
@@ -5,13 +5,13 @@
.form-group
= f.label :static_objects_external_storage_url, class: 'label-bold' do
= _('External storage URL')
- = f.text_field :static_objects_external_storage_url, class: 'form-control'
+ = f.text_field :static_objects_external_storage_url, class: 'form-control gl-form-input'
%span.form-text.text-muted#static_objects_external_storage_url_help_block
= _('URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...).')
.form-group
= f.label :static_objects_external_storage_auth_token, class: 'label-bold' do
= _('External storage authentication token')
- = f.text_field :static_objects_external_storage_auth_token, class: 'form-control'
+ = f.text_field :static_objects_external_storage_auth_token, class: 'form-control gl-form-input'
%span.form-text.text-muted#static_objects_external_storage_auth_token_help_block
= _('A secure token that identifies an external storage request.')
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 66fd0087c3e..23a7856e483 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -43,18 +43,18 @@
target: '_blank'
.form-group
= f.label :two_factor_authentication, 'Two-factor grace period (hours)', class: 'label-bold'
- = f.number_field :two_factor_grace_period, min: 0, class: 'form-control', placeholder: '0'
+ = f.number_field :two_factor_grace_period, min: 0, class: 'form-control gl-form-input', placeholder: '0'
.form-text.text-muted Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication
.form-group
= f.label :home_page_url, 'Home page URL', class: 'label-bold'
- = f.text_field :home_page_url, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block'
+ = f.text_field :home_page_url, class: 'form-control gl-form-input', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block'
%span.form-text.text-muted#home_help_block We will redirect non-logged in users to this page
.form-group
= f.label :after_sign_out_path, _('After sign-out path'), class: 'label-bold'
- = f.text_field :after_sign_out_path, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'after_sign_out_path_help_block'
+ = f.text_field :after_sign_out_path, class: 'form-control gl-form-input', placeholder: 'http://company.example.com', :'aria-describedby' => 'after_sign_out_path_help_block'
%span.form-text.text-muted#after_sign_out_path_help_block We will redirect users to this page after they sign out
.form-group
= f.label :sign_in_text, _('Sign-in text'), class: 'label-bold'
- = f.text_area :sign_in_text, class: 'form-control', rows: 4
+ = f.text_area :sign_in_text, class: 'form-control gl-form-input', rows: 4
.form-text.text-muted Markdown enabled
= f.submit 'Save changes', class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index 92477dff3d8..82824f1d436 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -26,13 +26,13 @@
.form-group
= f.label :minimum_password_length, _('Minimum password length (number of characters)'), class: 'label-bold'
- = f.number_field :minimum_password_length, class: 'form-control', rows: 4, min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH, max: Devise.password_length.max
+ = f.number_field :minimum_password_length, class: 'form-control gl-form-input', rows: 4, min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH, max: Devise.password_length.max
- password_policy_guidelines_link = link_to _('Password Policy Guidelines'), 'https://about.gitlab.com/handbook/security/#gitlab-password-policy-guidelines', target: '_blank', rel: 'noopener noreferrer nofollow'
.form-text.text-muted
= _("See GitLab's %{password_policy_guidelines}").html_safe % { password_policy_guidelines: password_policy_guidelines_link }
.form-group
= f.label :domain_allowlist, _('Allowed domains for sign-ups'), class: 'label-bold'
- = f.text_area :domain_allowlist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
+ = f.text_area :domain_allowlist_raw, placeholder: 'domain.com', class: 'form-control gl-form-input', rows: 8
.form-text.text-muted 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
.form-group
= f.label :domain_denylist_enabled, _('Domain denylist'), class: 'label-bold'
@@ -53,11 +53,11 @@
Enter denylist manually
.form-group.js-denylist-file
= f.label :domain_denylist_file, _('Denylist file'), class: 'label-bold'
- = f.file_field :domain_denylist_file, class: 'form-control', accept: '.txt,.conf'
+ = f.file_field :domain_denylist_file, class: 'form-control gl-form-input', accept: '.txt,.conf'
.form-text.text-muted 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.
.form-group.js-denylist-raw
= f.label :domain_denylist, _('Denied domains for sign-ups'), class: 'label-bold'
- = f.text_area :domain_denylist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
+ = f.text_area :domain_denylist_raw, placeholder: 'domain.com', class: 'form-control gl-form-input', rows: 8
.form-text.text-muted 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
.form-group
= f.label :email_restrictions_enabled, _('Email restrictions'), class: 'label-bold'
@@ -67,7 +67,7 @@
= _('Enable email restrictions for sign ups')
.form-group
= f.label :email_restrictions, _('Email restrictions for sign-ups'), class: 'label-bold'
- = f.text_area :email_restrictions, class: 'form-control', rows: 4
+ = f.text_area :email_restrictions, class: 'form-control gl-form-input', rows: 4
.form-text.text-muted
- supported_syntax_link_url = 'https://github.com/google/re2/wiki/Syntax'
- supported_syntax_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: supported_syntax_link_url }
@@ -75,6 +75,6 @@
.form-group
= f.label :after_sign_up_text, class: 'label-bold'
- = f.text_area :after_sign_up_text, class: 'form-control', rows: 4
+ = f.text_area :after_sign_up_text, class: 'form-control gl-form-input', rows: 4
.form-text.text-muted Markdown enabled
= f.submit 'Save changes', class: "gl-button btn btn-success", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index c1edaf9ff29..5f5a3a6992c 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -18,12 +18,12 @@
= f.label :snowplow_enabled, _('Enable snowplow tracking'), class: 'form-check-label'
.form-group
= f.label :snowplow_collector_hostname, _('Collector hostname'), class: 'label-light'
- = f.text_field :snowplow_collector_hostname, class: 'form-control', placeholder: 'snowplow.example.com'
+ = f.text_field :snowplow_collector_hostname, class: 'form-control gl-form-input', placeholder: 'snowplow.example.com'
.form-group
= f.label :snowplow_app_id, _('App ID'), class: 'label-light'
- = f.text_field :snowplow_app_id, class: 'form-control'
+ = f.text_field :snowplow_app_id, class: 'form-control gl-form-input'
.form-group
= f.label :snowplow_cookie_domain, _('Cookie domain'), class: 'label-light'
- = f.text_field :snowplow_cookie_domain, class: 'form-control'
+ = f.text_field :snowplow_cookie_domain, class: 'form-control gl-form-input'
= f.submit _('Save changes'), class: 'gl-button btn btn-success'
diff --git a/app/views/admin/application_settings/_sourcegraph.html.haml b/app/views/admin/application_settings/_sourcegraph.html.haml
index 2a4e8f87c31..e1af269c6fd 100644
--- a/app/views/admin/application_settings/_sourcegraph.html.haml
+++ b/app/views/admin/application_settings/_sourcegraph.html.haml
@@ -32,7 +32,7 @@
= s_('SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph.')
.form-group
= f.label :sourcegraph_url, s_('SourcegraphAdmin|Sourcegraph URL'), class: 'label-bold'
- = f.text_field :sourcegraph_url, class: 'form-control', placeholder: s_('SourcegraphAdmin|e.g. https://sourcegraph.example.com')
+ = f.text_field :sourcegraph_url, class: 'form-control gl-form-input', placeholder: s_('SourcegraphAdmin|e.g. https://sourcegraph.example.com')
.form-text.text-muted
= s_('SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects.')
= f.submit s_('SourcegraphAdmin|Save changes'), class: 'gl-button btn btn-success'
diff --git a/app/views/admin/application_settings/_spam.html.haml b/app/views/admin/application_settings/_spam.html.haml
index 2b871d3693c..6085cea4f5d 100644
--- a/app/views/admin/application_settings/_spam.html.haml
+++ b/app/views/admin/application_settings/_spam.html.haml
@@ -18,7 +18,7 @@
= _('Helps prevent bots from brute-force attacks.')
.form-group
= f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'label-bold'
- = f.text_field :recaptcha_site_key, class: 'form-control'
+ = f.text_field :recaptcha_site_key, class: 'form-control gl-form-input'
.form-text.text-muted
Generate site and private keys at
%a{ href: 'http://www.google.com/recaptcha', target: 'blank' } http://www.google.com/recaptcha
@@ -26,7 +26,7 @@
.form-group
= f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'label-bold'
.form-group
- = f.text_field :recaptcha_private_key, class: 'form-control'
+ = f.text_field :recaptcha_private_key, class: 'form-control gl-form-input'
.form-group
.form-check
@@ -45,7 +45,7 @@
.form-group
= f.label :akismet_api_key, 'Akismet API Key', class: 'label-bold'
- = f.text_field :akismet_api_key, class: 'form-control'
+ = f.text_field :akismet_api_key, class: 'form-control gl-form-input'
.form-text.text-muted
Generate API key at
%a{ href: 'http://www.akismet.com', target: 'blank' } http://www.akismet.com
@@ -60,13 +60,13 @@
.form-group
= f.label :unique_ips_limit_per_user, 'IPs per user', class: 'label-bold'
- = f.number_field :unique_ips_limit_per_user, class: 'form-control'
+ = f.number_field :unique_ips_limit_per_user, class: 'form-control gl-form-input'
.form-text.text-muted
Maximum number of unique IPs per user
.form-group
= f.label :unique_ips_limit_time_window, 'IP expiration time', class: 'label-bold'
- = f.number_field :unique_ips_limit_time_window, class: 'form-control'
+ = f.number_field :unique_ips_limit_time_window, class: 'form-control gl-form-input'
.form-text.text-muted
How many seconds an IP will be counted towards the limit
@@ -77,6 +77,6 @@
.form-text.text-muted= _('Define custom rules for what constitutes spam, independent of Akismet')
.form-group
= f.label :spam_check_endpoint_url, _('URL of the external Spam Check endpoint'), class: 'label-bold'
- = f.text_field :spam_check_endpoint_url, class: 'form-control'
+ = f.text_field :spam_check_endpoint_url, class: 'form-control gl-form-input'
= f.submit 'Save changes', class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_terminal.html.haml b/app/views/admin/application_settings/_terminal.html.haml
index 7bc5b2405e8..8f89cf27291 100644
--- a/app/views/admin/application_settings/_terminal.html.haml
+++ b/app/views/admin/application_settings/_terminal.html.haml
@@ -4,7 +4,7 @@
%fieldset
.form-group
= f.label :terminal_max_session_time, 'Max session time', class: 'label-bold'
- = f.number_field :terminal_max_session_time, class: 'form-control'
+ = f.number_field :terminal_max_session_time, class: 'form-control gl-form-input'
.form-text.text-muted
Maximum time for web terminal websocket connection (in seconds).
0 for unlimited.
diff --git a/app/views/admin/application_settings/_terms.html.haml b/app/views/admin/application_settings/_terms.html.haml
index 10db1e23d7b..717b2220336 100644
--- a/app/views/admin/application_settings/_terms.html.haml
+++ b/app/views/admin/application_settings/_terms.html.haml
@@ -12,7 +12,7 @@
.form-group
= f.label :terms do
= _("Terms of Service Agreement and Privacy Policy")
- = f.text_area :terms, class: 'form-control', rows: 8
+ = f.text_area :terms, class: 'form-control gl-form-input', rows: 8
.form-text.text-muted
= _("Markdown enabled")
= f.submit _("Save changes"), class: "gl-button btn btn-success"
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index 709ce497132..0931ba50aa7 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -35,11 +35,11 @@
.form-check= source
%span.form-text.text-muted#import-sources-help
= _('Enabled sources for code import during project creation. OmniAuth must be configured for GitHub')
- = link_to "(?)", help_page_path("integration/github")
+ = link_to sprite_icon('question-o'), help_page_path("integration/github")
, Bitbucket
- = link_to "(?)", help_page_path("integration/bitbucket")
+ = link_to sprite_icon('question-o'), help_page_path("integration/bitbucket")
and GitLab.com
- = link_to "(?)", help_page_path("integration/gitlab")
+ = link_to sprite_icon('question-o'), help_page_path("integration/gitlab")
= render_if_exists 'admin/application_settings/ldap_access_setting', form: f
@@ -57,7 +57,7 @@
.form-group
= f.label :custom_http_clone_url_root, _('Custom Git clone URL for HTTP(S)'), class: 'label-bold'
- = f.text_field :custom_http_clone_url_root, class: 'form-control', placeholder: 'https://git.example.com', :'aria-describedby' => 'custom_http_clone_url_root_help_block'
+ = f.text_field :custom_http_clone_url_root, class: 'form-control gl-form-input', placeholder: 'https://git.example.com', :'aria-describedby' => 'custom_http_clone_url_root_help_block'
%span.form-text.text-muted#custom_http_clone_url_root_help_block
= _('Replaces the clone URL root.')
diff --git a/app/views/admin/application_settings/ci/_header.html.haml b/app/views/admin/application_settings/ci/_header.html.haml
index 0a0f8aaf032..aa4cebdb603 100644
--- a/app/views/admin/application_settings/ci/_header.html.haml
+++ b/app/views/admin/application_settings/ci/_header.html.haml
@@ -2,19 +2,18 @@
%h4
= _('Variables')
- = link_to sprite_icon('question-o', css_class: 'gl-vertical-align-baseline!'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = html_escape(_('Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
-
+ = _('Variables store information, like passwords and secret keys, that you can use in job scripts. All projects on the instance can use these variables.')
+ = link_to s_('Learn more.'), help_page_path('ci/variables/README', anchor: 'instance-level-cicd-variables'), target: '_blank', rel: 'noopener noreferrer'
+%p
+ = _('Variables can be:')
%ul
%li
- = html_escape(_('%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li
- = html_escape(_('%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so).')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
-
-%p
- = link_to _('More information'), help_page_path('ci/variables/README', anchor: 'instance-level-cicd-environment-variables')
+ = html_escape(_('%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = link_to _('Learn more.'), help_page_path('ci/variables/README', anchor: 'masked-variable-requirements'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index b05e8621d07..485fb71d111 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -10,7 +10,7 @@
- if ci_variable_protected_by_default?
%p.settings-message.text-center
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable') }
- = s_('Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = s_('Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
#js-instance-variables{ data: { endpoint: admin_ci_variables_path, group: 'true', maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} }
%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded_by_default?) }
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index 8f15dcac40a..794e02787f5 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -104,7 +104,6 @@
= f.submit _('Save changes'), class: "gl-button btn btn-success"
= render_if_exists 'admin/application_settings/maintenance_mode_settings_form'
-= render_if_exists 'admin/application_settings/elasticsearch_form'
= render 'admin/application_settings/gitpod'
= render 'admin/application_settings/kroki'
= render 'admin/application_settings/plantuml'
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index ed4f63d0b82..949908b09a7 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -9,9 +9,9 @@
= sprite_icon('close', css_class: 'gl-icon')
.gl-alert-body
%h4.gl-alert-title= s_('AdminSettings|Some settings have moved')
- = html_escape_once(s_('AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General.')).html_safe
+ = html_escape_once(s_('AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General.')).html_safe
.gl-alert-actions
- = link_to s_('AdminSettings|Go to General Settings'), general_admin_application_settings_path, class: 'btn gl-alert-action btn-info new-gl-button'
+ = link_to s_('AdminSettings|Go to General Settings'), general_admin_application_settings_path, class: 'btn gl-alert-action btn-info gl-button'
%h4= s_('AdminSettings|Apply integration settings to all Projects')
%p
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index 4959e596148..113ff20e910 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -1,3 +1,5 @@
+- add_page_specific_style 'page_bundles/admin/application_settings_metrics_and_profiling'
+
- breadcrumb_title _("Metrics and profiling")
- page_title _("Metrics and profiling")
- @content_class = "limit-container-width" unless fluid_layout
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index f977a8c93fa..72716e76013 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -61,6 +61,17 @@
.settings-content
= render 'issue_limits'
+%section.settings.as-note-limits.no-animate#js-note-limits-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Notes Rate Limits')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Configure limit for notes created per minute by web and API requests.')
+ .settings-content
+ = render 'note_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/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml
index 787760516ce..fd5ce890648 100644
--- a/app/views/admin/application_settings/preferences.html.haml
+++ b/app/views/admin/application_settings/preferences.html.haml
@@ -6,7 +6,7 @@
.settings-header
%h4
= _('Email')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Various email settings.')
@@ -17,7 +17,7 @@
.settings-header
%h4
= _('Help page')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Help page text and support page url.')
@@ -28,7 +28,7 @@
.settings-header
%h4
= _('Pages')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Size and domain settings for static websites')
@@ -39,7 +39,7 @@
.settings-header
%h4
= _('Real-time features')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Change this value to influence how frequently the GitLab UI polls for updates.')
@@ -50,7 +50,7 @@
.settings-header
%h4
= _('Gitaly')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure Gitaly timeouts.')
@@ -61,7 +61,7 @@
.settings-header
%h4
= _('Localization')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Various localization settings.')
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index 6ea139844d4..914a09ff5db 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -6,7 +6,7 @@
.settings-header
%h4
= _('Spam and Anti-bot Protection')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- recaptcha_v2_link_url = 'https://developers.google.com/recaptcha/docs/versions'
@@ -19,7 +19,7 @@
.settings-header
%h4
= _('Abuse reports')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set notification email for abuse reports.')
diff --git a/app/views/admin/application_settings/repository.html.haml b/app/views/admin/application_settings/repository.html.haml
index 18e093f7b2c..4365d8937bd 100644
--- a/app/views/admin/application_settings/repository.html.haml
+++ b/app/views/admin/application_settings/repository.html.haml
@@ -7,7 +7,7 @@
.settings-header
%h4
= _('Default initial branch name')
- %button.gl-button.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Set the default name of the initial branch when creating new repositories through the user interface.')
@@ -18,7 +18,7 @@
.settings-header
%h4
= _('Repository mirroring')
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? 'Collapse' : 'Expand'
%p
= _('Configure repository mirroring.')
@@ -29,7 +29,7 @@
.settings-header
%h4
= _('Repository storage')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure storage path settings.')
@@ -40,7 +40,7 @@
.settings-header
%h4
= _('Repository maintenance')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Configure automatic git checks and housekeeping on repositories.')
@@ -51,7 +51,7 @@
.settings-header
%h4
= _('Repository static objects')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Serve repository static objects (e.g. archives, blobs, ...) from an external storage (e.g. a CDN).')
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
index 0c3a4e73e30..14044d6eecb 100644
--- a/app/views/admin/applications/_form.html.haml
+++ b/app/views/admin/applications/_form.html.haml
@@ -5,14 +5,14 @@
.col-sm-2.col-form-label
= f.label :name
.col-sm-10
- = f.text_field :name, class: 'form-control'
+ = f.text_field :name, class: 'form-control gl-form-input'
= doorkeeper_errors_for application, :name
= content_tag :div, class: 'form-group row' do
.col-sm-2.col-form-label
= f.label :redirect_uri
.col-sm-10
- = f.text_area :redirect_uri, class: 'form-control'
+ = f.text_area :redirect_uri, class: 'form-control gl-form-input'
= doorkeeper_errors_for application, :redirect_uri
%span.form-text.text-muted
Use one line per URI
@@ -23,7 +23,7 @@
.col-sm-10
= f.check_box :trusted
%span.form-text.text-muted
- Trusted applications are automatically authorized on GitLab OAuth flow.
+ Trusted applications are automatically authorized on GitLab OAuth flow. It's highly recommended for the security of users that trusted applications have the confidential setting set to true.
= content_tag :div, class: 'form-group row' do
.col-sm-2.col-form-label.pt-0
diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml
index c1c1c2a4cfe..7ac55157f65 100644
--- a/app/views/admin/applications/index.html.haml
+++ b/app/views/admin/applications/index.html.haml
@@ -1,28 +1,35 @@
- page_title _("Applications")
%h3.page-title
- System OAuth applications
+ = _('System OAuth applications')
%p.light
- System OAuth applications don't belong to any user and can only be managed by admins
+ = _('System OAuth applications don\'t belong to any user and can only be managed by admins')
%hr
-%p= link_to 'New application', new_admin_application_path, class: 'gl-button btn btn-success'
-%table.table
- %thead
- %tr
- %th Name
- %th Callback URL
- %th Clients
- %th Trusted
- %th Confidential
- %th
- %th
- %tbody.oauth-applications
- - @applications.each do |application|
- %tr{ :id => "application_#{application.id}" }
- %td= link_to application.name, admin_application_path(application)
- %td= application.redirect_uri
- %td= @application_counts[application.id].to_i
- %td= application.trusted? ? 'Y': 'N'
- %td= application.confidential? ? 'Y': 'N'
- %td= link_to 'Edit', edit_admin_application_path(application), class: 'gl-button btn btn-link'
- %td= render 'delete_form', application: application
+%p= link_to _('New application'), new_admin_application_path, class: 'gl-button btn btn-success'
+.table-responsive
+ %table.table
+ %thead
+ %tr
+ %th
+ = _('Name')
+ %th
+ = _('Callback URL')
+ %th
+ = _('Clients')
+ %th
+ = _('Trusted')
+ %th
+ = _('Confidential')
+ %th
+ %th
+ %tbody.oauth-applications
+ - @applications.each do |application|
+ %tr{ :id => "application_#{application.id}" }
+ %td= link_to application.name, admin_application_path(application)
+ %td= application.redirect_uri
+ %td= @application_counts[application.id].to_i
+ %td= application.trusted? ? _('Yes'): _('No')
+ %td= application.confidential? ? _('Yes'): _('No')
+ %td= link_to 'Edit', edit_admin_application_path(application), class: 'gl-button btn btn-link'
+ %td= render 'delete_form', application: application
+
= paginate @applications, theme: 'gitlab'
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index f029da6b3af..8d643a7a4bc 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -45,5 +45,5 @@
= render "shared/tokens/scopes_list", token: @application
.form-actions
- = link_to 'Edit', edit_admin_application_path(@application), class: 'gl-button btn btn-primary wide float-left'
- = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger gl-ml-3'
+ = link_to 'Edit', edit_admin_application_path(@application), class: 'gl-button btn btn-confirm wide float-left'
+ = render 'delete_form', application: @application, submit_btn_css: 'gl-button btn btn-danger gl-ml-3'
diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml
index 9693a97367f..89fccff954d 100644
--- a/app/views/admin/broadcast_messages/_form.html.haml
+++ b/app/views/admin/broadcast_messages/_form.html.haml
@@ -21,7 +21,7 @@
.col-sm-2.col-form-label
= f.label :message
.col-sm-10
- = f.text_area :message, class: "form-control js-autosize js-broadcast-message-message",
+ = f.text_area :message, class: "form-control gl-form-input js-autosize js-broadcast-message-message",
required: true,
dir: 'auto',
data: { preview_path: preview_admin_broadcast_messages_path }
@@ -38,7 +38,7 @@
.input-group-prepend
.input-group-text.label-color-preview{ :style => 'background-color: ' + @broadcast_message.color + '; color: ' + @broadcast_message.font }
= '&nbsp;'.html_safe
- = f.text_field :color, class: "form-control js-broadcast-message-color"
+ = f.text_field :color, class: "form-control gl-form-input js-broadcast-message-color"
.form-text.text-muted
= _('Choose any color.')
%br
@@ -57,12 +57,12 @@
.col-sm-2.col-form-label
= f.label :font, "Font Color"
.col-sm-10
- = f.color_field :font, class: "form-control text-font-color"
+ = f.color_field :font, class: "form-control gl-form-input text-font-color"
.form-group.row
.col-sm-2.col-form-label
= f.label :target_path, _('Target Path')
.col-sm-10
- = f.text_field :target_path, class: "form-control"
+ = f.text_field :target_path, class: "form-control gl-form-input"
.form-text.text-muted
= _('Paths can contain wildcards, like */welcome')
.form-group.row
diff --git a/app/views/admin/cohorts/index.html.haml b/app/views/admin/cohorts/index.html.haml
deleted file mode 100644
index 03cd392d370..00000000000
--- a/app/views/admin/cohorts/index.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-- breadcrumb_title _("Cohorts")
-- page_title _("Cohorts")
-
-- if @cohorts
- = render 'cohorts_table'
-- else
- #js-cohorts-empty-state{ data: { empty_state_svg_path: image_path('illustrations/convdev/convdev_no_index.svg'), enable_usage_ping_link: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), docs_link: help_page_path('user/admin_area/analytics/user_cohorts') } }
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 8cc04392752..f6ebc4c465d 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -15,49 +15,63 @@
= render_if_exists 'admin/licenses/breakdown'
.admin-dashboard.gl-mt-3
+ .h3.gl-mb-5.gl-mt-0= _('Instance overview')
.row
- .col-sm-4
- .info-well.dark-well.flex-fill
- .well-segment.well-centered
- = link_to admin_projects_path do
- %h3.text-center
- = s_('AdminArea|Projects: %{number_of_projects}') % { number_of_projects: approximate_count_with_delimiters(@counts, Project) }
- %hr
- = link_to(s_('AdminArea|New project'), new_project_path, class: "btn gl-button btn-success gl-w-full")
- .col-sm-4
- .info-well.dark-well
- .well-segment.well-centered.gl-text-center
- = link_to admin_users_path do
- %h3.gl-display-inline-block.gl-mb-0
- = s_('AdminArea|Users: %{number_of_users}') % { number_of_users: approximate_count_with_delimiters(@counts, User) }
-
- %span.gl-outline-0.gl-ml-2{ href: "#", tabindex: "0", data: { container: "body",
- toggle: "popover",
- placement: "top",
- html: "true",
- trigger: "focus",
- content: s_("AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}.").html_safe % { billable_users_link_start: billable_users_link_start, billable_users_link_end: '</a>'.html_safe },
- } }
- = sprite_icon('question', size: 16, css_class: 'gl-text-gray-700 gl-mb-1')
-
- %hr
- .btn-group.d-flex{ role: 'group' }
- = link_to s_('AdminArea|New user'), new_admin_user_path, class: "btn gl-button btn-success gl-w-full"
- = link_to s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: 'btn gl-button btn-info gl-w-full'
- .col-sm-4
- .info-well.dark-well
- .well-segment.well-centered
- = link_to admin_groups_path do
- %h3.text-center
- = s_('AdminArea|Groups: %{number_of_groups}') % { number_of_groups: approximate_count_with_delimiters(@counts, Group) }
- %hr
- = link_to s_('AdminArea|New group'), new_admin_group_path, class: "btn gl-button btn-success gl-w-full"
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body.d-flex.justify-content-between.align-items-center.gl-p-6
+ %span
+ .d-flex.align-items-center
+ = sprite_icon('project', size: 16, css_class: 'gl-text-gray-700')
+ %h3.gl-m-0.gl-ml-3= approximate_count_with_delimiters(@counts, Project)
+ .gl-mt-3.text-uppercase= s_('AdminArea|Projects')
+ = link_to(s_('AdminArea|New project'), new_project_path, class: "btn gl-button btn-default")
+ .gl-card-footer.gl-bg-transparent
+ .d-flex.align-items-center
+ = link_to(s_('AdminArea|View latest projects'), admin_projects_path)
+ = sprite_icon('angle-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body.d-flex.justify-content-between.align-items-center.gl-p-6
+ %span
+ .d-flex.align-items-center
+ = sprite_icon('users', size: 16, css_class: 'gl-text-gray-700')
+ %h3.gl-m-0.gl-ml-3= approximate_count_with_delimiters(@counts, User)
+ %span.gl-outline-0.gl-ml-3{ tabindex: "0", data: { container: "body",
+ toggle: "popover",
+ placement: "top",
+ html: "true",
+ trigger: "focus",
+ content: s_("AdminArea|All users created in the instance, including users who are not %{billable_users_link_start}billable users%{billable_users_link_end}.").html_safe % { billable_users_link_start: billable_users_link_start, billable_users_link_end: '</a>'.html_safe },
+ } }
+ = sprite_icon('question', size: 16, css_class: 'gl-text-gray-700')
+ .gl-mt-3.text-uppercase
+ = s_('AdminArea|Users')
+ = link_to(s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: "text-capitalize gl-ml-2")
+ = link_to(s_('AdminArea|New user'), new_admin_user_path, class: "btn gl-button btn-default")
+ .gl-card-footer.gl-bg-transparent
+ .d-flex.align-items-center
+ = link_to(s_('AdminArea|View latest users'), admin_users_path)
+ = sprite_icon('angle-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body.d-flex.justify-content-between.align-items-center.gl-p-6
+ %span
+ .d-flex.align-items-center
+ = sprite_icon('group', size: 16, css_class: 'gl-text-gray-700')
+ %h3.gl-m-0.gl-ml-3= approximate_count_with_delimiters(@counts, Group)
+ .gl-mt-3.text-uppercase= s_('AdminArea|Projects')
+ = link_to(s_('AdminArea|New group'), new_admin_group_path, class: "btn gl-button btn-default")
+ .gl-card-footer.gl-bg-transparent
+ .d-flex.align-items-center
+ = link_to(s_('AdminArea|View latest groups'), admin_groups_path)
+ = sprite_icon('angle-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.row
- .col-md-4
+ .col-md-4.gl-mb-6
#js-admin-statistics-container
- .col-md-4
- .info-well
- .well-segment.admin-well.admin-well-features
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body
%h4= s_('AdminArea|Features')
= feature_entry(_('Sign up'),
href: general_admin_application_settings_path(anchor: 'js-signup-settings'),
@@ -94,9 +108,9 @@
= feature_entry(_('Shared Runners'),
href: admin_runners_path,
enabled: Gitlab.config.gitlab_ci.shared_runners_enabled)
- .col-md-4
- .info-well
- .well-segment.admin-well
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body
%h4
= s_('AdminArea|Components')
- if Gitlab::CurrentSettings.version_check_enabled
@@ -146,18 +160,18 @@
%p
= link_to _("Gitaly Servers"), admin_gitaly_servers_path
.row
- .col-md-4
- .info-well
- .well-segment.admin-well
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body
%h4= s_('AdminArea|Latest projects')
- @projects.each do |project|
%p
= link_to project.full_name, admin_project_path(project), class: 'str-truncated-60'
%span.light.float-right
#{time_ago_with_tooltip(project.created_at)}
- .col-md-4
- .info-well
- .well-segment.admin-well
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body
%h4= s_('AdminArea|Latest users')
- @users.each do |user|
%p
@@ -165,9 +179,9 @@
= user.name
%span.light.float-right
#{time_ago_with_tooltip(user.created_at)}
- .col-md-4
- .info-well
- .well-segment.admin-well
+ .col-md-4.gl-mb-6
+ .gl-card
+ .gl-card-body
%h4= s_('AdminArea|Latest groups')
- @groups.each do |group|
%p
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index e4517dca6d0..c2599238bce 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -31,7 +31,7 @@
= render 'shared/group_tips'
.form-actions
= f.submit _('Create group'), class: "gl-button btn btn-success"
- = link_to _('Cancel'), admin_groups_path, class: "gl-button btn btn-cancel"
+ = link_to _('Cancel'), admin_groups_path, class: "gl-button btn btn-default btn-cancel"
- else
.form-actions
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index a667fc7ca04..dc122d74e90 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -14,7 +14,7 @@
.description
= markdown_field(group, :description)
- .stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-display-sm-flex
+ .stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-sm-display-flex
%span.badge.badge-pill
= storage_counter(group.storage_size)
@@ -33,5 +33,5 @@
= visibility_level_icon(group.visibility_level)
.controls.gl-flex-shrink-0.gl-ml-5
- = link_to _('Edit'), admin_group_edit_path(group), id: "edit_#{dom_id(group)}", class: 'btn'
+ = link_to _('Edit'), admin_group_edit_path(group), id: "edit_#{dom_id(group)}", class: 'gl-button btn'
= 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'
diff --git a/app/views/admin/hooks/_form.html.haml b/app/views/admin/hooks/_form.html.haml
index e6abd8ff85a..459df5c8d85 100644
--- a/app/views/admin/hooks/_form.html.haml
+++ b/app/views/admin/hooks/_form.html.haml
@@ -2,30 +2,31 @@
.form-group
= form.label :url, _('URL'), class: 'label-bold'
- = form.text_field :url, class: 'form-control'
+ = form.text_field :url, class: 'form-control gl-form-input'
+ %p.form-text.text-muted= _('URL must be percent-encoded if neccessary.')
.form-group
- = form.label :token, _('Secret Token'), class: 'label-bold'
- = form.text_field :token, class: 'form-control'
- %p.form-text.text-muted= _('Use this token to validate received payloads')
+ = form.label :token, _('Secret token'), class: 'label-bold'
+ = form.text_field :token, class: 'form-control gl-form-input'
+ %p.form-text.text-muted= _('Use this token to validate received payloads.')
.form-group
= form.label :url, _('Trigger'), class: 'label-bold'
- .form-text.text-secondary.gl-mb-5= _('System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events.')
+ .form-text.text-secondary.gl-mb-5= _('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.')
%fieldset.form-group.form-check
= form.check_box :repository_update_events, class: 'form-check-input'
= form.label :repository_update_events, _('Repository update events'), class: 'label-bold form-check-label'
- .text-secondary= _('This URL will be triggered when repository is updated')
+ .text-secondary= _('URL is triggered when repository is updated')
%fieldset.form-group.form-check
= form.check_box :push_events, class: 'form-check-input'
= form.label :push_events, _('Push events'), class: 'label-bold form-check-label'
- .text-secondary= _('This URL will be triggered for each branch updated to the repository')
+ .text-secondary= _('URL is triggered for each branch updated to the repository')
%fieldset.form-group.form-check
= form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, _('Tag push events'), class: 'label-bold form-check-label'
- .text-secondary= _('This URL will be triggered when a new tag is pushed to the repository')
+ .text-secondary= _('URL is triggered when a new tag is pushed to the repository')
%fieldset.form-group.form-check
= form.check_box :merge_requests_events, class: 'form-check-input'
= form.label :merge_requests_events, _('Merge request events'), class: 'label-bold form-check-label'
- .text-secondary= _('This URL will be triggered when a merge request is created/updated/merged')
+ .text-secondary= _('URL is triggered when a merge request is created, updated, or merged')
.form-group
= form.label :enable_ssl_verification, _('SSL verification'), class: 'label-bold checkbox'
.form-check
diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml
index ce377eeea54..670628f7463 100644
--- a/app/views/admin/jobs/index.html.haml
+++ b/app/views/admin/jobs/index.html.haml
@@ -1,4 +1,5 @@
- add_page_specific_style 'page_bundles/ci_status'
+- add_page_specific_style 'page_bundles/admin/jobs_index'
- breadcrumb_title _("Jobs")
- page_title _("Jobs")
diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml
index 664081339f3..12c7acd7668 100644
--- a/app/views/admin/labels/_form.html.haml
+++ b/app/views/admin/labels/_form.html.haml
@@ -5,12 +5,12 @@
.col-sm-2.col-form-label
= f.label :title
.col-sm-10
- = f.text_field :title, class: "form-control", required: true
+ = f.text_field :title, class: "form-control gl-form-input", required: true
.form-group.row
.col-sm-2.col-form-label
= f.label :description
.col-sm-10
- = f.text_field :description, class: "form-control js-quick-submit"
+ = f.text_field :description, class: "form-control gl-form-input js-quick-submit"
.form-group.row
.col-sm-2.col-form-label
= f.label :color, _("Background color")
@@ -18,7 +18,7 @@
.input-group
.input-group-prepend
.input-group-text.label-color-preview &nbsp;
- = f.text_field :color, class: "form-control"
+ = f.text_field :color, class: "form-control gl-form-input"
.form-text.text-muted
= _('Choose any color.')
%br
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index 44317eb7f6e..4131c8b7edd 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -4,8 +4,8 @@
- @projects.each_with_index do |project|
%li.project-row{ class: ('no-description' if project.description.blank?) }
.controls
- = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn"
- %button.delete-project-button.btn.btn-danger{ data: { delete_project_url: admin_project_path(project), project_name: project.name } }
+ = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "gl-button btn"
+ %button.delete-project-button.gl-button.btn.btn-danger{ data: { delete_project_url: admin_project_path(project), project_name: project.name } }
= s_('AdminProjects|Delete')
.stats
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index bcf09dfc0d2..d9ff4404519 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -32,6 +32,6 @@
= render 'shared/projects/dropdown'
= link_to new_project_path, class: 'gl-button btn btn-success' do
New Project
- = button_tag "Search", class: "gl-button btn btn-primary btn-search hide"
+ = button_tag "Search", class: "gl-button btn btn-confirm btn-search hide"
= render 'projects'
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index aae1d5b6a4e..2085515e349 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -150,7 +150,7 @@
.form-group.row
.offset-sm-3.col-sm-9
- = f.submit _('Transfer'), class: 'gl-button btn btn-primary'
+ = f.submit _('Transfer'), class: 'gl-button btn btn-confirm'
.card.repository-check
.card-header
@@ -170,7 +170,7 @@
= link_to sprite_icon('question-o'), help_page_path('administration/repository_checks')
.form-group
- = f.submit _('Trigger repository check'), class: 'gl-button btn btn-primary'
+ = f.submit _('Trigger repository check'), class: 'gl-button btn btn-confirm'
.col-md-6
- if @group
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 9f19d3f5d4e..8e62dae6c4d 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -39,7 +39,9 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
type: 'shared',
- reset_token_url: reset_registration_token_admin_application_settings_path }
+ reset_token_url: reset_registration_token_admin_application_settings_path,
+ project_path: '',
+ group_path: '' }
.row
.col-sm-9
@@ -48,7 +50,7 @@
.filtered-search-box
= dropdown_tag(_('Recent searches'),
options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
- toggle_class: 'gl-button btn filtered-search-history-dropdown-toggle-button',
+ toggle_class: 'btn filtered-search-history-dropdown-toggle-button',
dropdown_class: 'filtered-search-history-dropdown',
content_class: 'filtered-search-history-dropdown-content' }) do
.js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index 3ba01e8a350..573580bc5c5 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -5,7 +5,7 @@
.col-sm-2.col-form-label
= f.label :projects_limit
.col-sm-10
- = f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control'
+ = f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label.gl-pt-0
diff --git a/app/views/admin/users/_admin_notes.html.haml b/app/views/admin/users/_admin_notes.html.haml
index 4da70a504f7..a20b2fbffc4 100644
--- a/app/views/admin/users/_admin_notes.html.haml
+++ b/app/views/admin/users/_admin_notes.html.haml
@@ -4,4 +4,4 @@
.col-sm-2.col-form-label
= f.label :note, s_('AdminNote|Note')
.col-sm-10
- = f.text_area :note, class: 'form-control'
+ = f.text_area :note, class: 'form-control gl-form-input gl-form-textarea'
diff --git a/app/views/admin/users/_cohorts.html.haml b/app/views/admin/users/_cohorts.html.haml
new file mode 100644
index 00000000000..013c6072165
--- /dev/null
+++ b/app/views/admin/users/_cohorts.html.haml
@@ -0,0 +1,4 @@
+- if @cohorts
+ = render 'cohorts_table'
+- else
+ #js-cohorts-empty-state{ data: { empty_state_svg_path: image_path('illustrations/convdev/convdev_no_index.svg'), enable_usage_ping_link: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), docs_link: help_page_path('user/admin_area/analytics/user_cohorts') } }
diff --git a/app/views/admin/cohorts/_cohorts_table.html.haml b/app/views/admin/users/_cohorts_table.html.haml
index bb6266b38f6..bb6266b38f6 100644
--- a/app/views/admin/cohorts/_cohorts_table.html.haml
+++ b/app/views/admin/users/_cohorts_table.html.haml
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 61c31d2d864..40393f0db99 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -8,19 +8,19 @@
.col-sm-2.col-form-label
= f.label :name
.col-sm-10
- = f.text_field :name, required: true, autocomplete: 'off', class: 'form-control'
+ = f.text_field :name, required: true, autocomplete: 'off', class: 'form-control gl-form-input'
%span.help-inline * required
.form-group.row
.col-sm-2.col-form-label
= f.label :username
.col-sm-10
- = f.text_field :username, required: true, autocomplete: 'off', autocorrect: 'off', autocapitalize: 'off', spellcheck: false, class: 'form-control'
+ = f.text_field :username, required: true, autocomplete: 'off', autocorrect: 'off', autocapitalize: 'off', spellcheck: false, class: 'form-control gl-form-input'
%span.help-inline * required
.form-group.row
.col-sm-2.col-form-label
= f.label :email
.col-sm-10
- = f.text_field :email, required: true, autocomplete: 'off', class: 'form-control'
+ = f.text_field :email, required: true, autocomplete: 'off', class: 'form-control gl-form-input'
%span.help-inline * required
- if @user.new_record?
@@ -41,12 +41,12 @@
.col-sm-2.col-form-label
= f.label :password
.col-sm-10
- = f.password_field :password, disabled: f.object.force_random_password, class: 'form-control'
+ = f.password_field :password, disabled: f.object.force_random_password, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :password_confirmation
.col-sm-10
- = f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control'
+ = f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control gl-form-input'
= render partial: 'access_levels', locals: { f: f }
@@ -66,22 +66,22 @@
.col-sm-2.col-form-label
= f.label :skype
.col-sm-10
- = f.text_field :skype, class: 'form-control'
+ = f.text_field :skype, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :linkedin
.col-sm-10
- = f.text_field :linkedin, class: 'form-control'
+ = f.text_field :linkedin, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :twitter
.col-sm-10
- = f.text_field :twitter, class: 'form-control'
+ = f.text_field :twitter, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :website_url
.col-sm-10
- = f.text_field :website_url, class: 'form-control'
+ = f.text_field :website_url, class: 'form-control gl-form-input'
= render 'admin/users/admin_notes', f: f
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index 4abcdef7e27..8a4a1a54c58 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -15,7 +15,8 @@
- if @user.deactivated?
%span.cred
= s_('AdminUsers|(Deactivated)')
- = render_if_exists 'admin/users/audtior_user_badge'
+ = render_if_exists 'admin/users/auditor_user_badge'
+ = render_if_exists 'admin/users/gma_user_badge'
.float-right
- if impersonation_enabled? && @user != current_user && @user.can?(:log_in)
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
index 31fd3aea94d..224a3cea28d 100644
--- a/app/views/admin/users/_user.html.haml
+++ b/app/views/admin/users/_user.html.haml
@@ -59,13 +59,13 @@
%li.divider
- if user.can_be_removed?
%li
- %button.delete-user-button.btn.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete',
+ %button.js-delete-user-modal-button.btn.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete',
delete_user_url: admin_user_path(user),
block_user_url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
= s_('AdminUsers|Delete user')
%li
- %button.delete-user-button.btn.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
+ %button.js-delete-user-modal-button.btn.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
delete_user_url: admin_user_path(user, hard_delete: true),
block_user_url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
diff --git a/app/views/admin/users/_user_detail.html.haml b/app/views/admin/users/_user_detail.html.haml
index 3bafd1cb396..05e387e6479 100644
--- a/app/views/admin/users/_user_detail.html.haml
+++ b/app/views/admin/users/_user_detail.html.haml
@@ -9,9 +9,10 @@
= render 'admin/users/user_listing_note', user: user
- user_badges_in_admin_section(user).each do |badge|
- - css_badge = "badge badge-#{badge[:variant]}" if badge[:variant].present?
- %span{ class: css_badge }
- = badge[:text]
+ - css_badge = "badge gl-badge sm badge-pill badge-#{badge[:variant]}" if badge[:variant].present?
+ %span.px-1.py-1
+ %span{ class: css_badge }
+ = badge[:text]
.row-second-line.str-truncated-100
= mail_to user.email, user.email, class: 'text-secondary'
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
new file mode 100644
index 00000000000..57edb9abe90
--- /dev/null
+++ b/app/views/admin/users/_users.html.haml
@@ -0,0 +1,88 @@
+.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)
+ %ul.nav-links.nav.nav-tabs.scrolling-tabs
+ = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do
+ = link_to admin_users_path do
+ = s_('AdminUsers|Active')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.active_without_ghosts)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do
+ = link_to admin_users_path(filter: "admins") do
+ = s_('AdminUsers|Admins')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.admins)
+ = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do
+ = link_to admin_users_path(filter: 'two_factor_enabled') do
+ = s_('AdminUsers|2FA Enabled')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor)
+ = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do
+ = link_to admin_users_path(filter: 'two_factor_disabled') do
+ = s_('AdminUsers|2FA Disabled')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do
+ = link_to admin_users_path(filter: 'external') do
+ = s_('AdminUsers|External')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.external)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do
+ = link_to admin_users_path(filter: "blocked") do
+ = s_('AdminUsers|Blocked')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked)
+ = nav_link(html_options: { class: "#{active_when(params[:filter] == 'blocked_pending_approval')} filter-blocked-pending-approval" }) do
+ = link_to admin_users_path(filter: "blocked_pending_approval"), data: { qa_selector: 'pending_approval_tab' } do
+ = s_('AdminUsers|Pending approval')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked_pending_approval)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'deactivated') }) do
+ = link_to admin_users_path(filter: "deactivated") do
+ = s_('AdminUsers|Deactivated')
+ %small.badge.badge-pill= limited_counter_with_delimiter(User.deactivated)
+ = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do
+ = link_to admin_users_path(filter: "wop") do
+ = s_('AdminUsers|Without projects')
+ %small.badge.badge-pill= 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'
+ = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn gl-button btn-success btn-search float-right'
+
+.filtered-search-block.row-content-block.border-top-0
+ = form_tag admin_users_path, method: :get do
+ - if params[:filter].present?
+ = hidden_field_tag "filter", h(params[:filter])
+ .search-holder
+ .search-field-holder.gl-mb-4
+ = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false, data: { qa_selector: 'user_search_field' }
+ - if @sort.present?
+ = hidden_field_tag :sort, @sort
+ = sprite_icon('search', css_class: 'search-icon')
+ = button_tag s_('AdminUsers|Search users') if Rails.env.test?
+ .dropdown.user-sort-dropdown
+ = label_tag 'Sort by', nil, class: 'label-bold'
+ - toggle_text = @sort.present? ? users_sort_options_hash[@sort] : sort_title_name
+ = dropdown_toggle(toggle_text, { toggle: 'dropdown' })
+ %ul.dropdown-menu.dropdown-menu-right
+ %li.dropdown-header
+ = s_('AdminUsers|Sort by')
+ %li
+ - users_sort_options_hash.each do |value, title|
+ = link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do
+ = title
+
+- if Feature.enabled?(:vue_admin_users)
+ #js-admin-users-app{ data: admin_users_data_attributes(@users) }
+ .gl-spinner-container.gl-my-7
+ %span.gl-vertical-align-bottom.gl-spinner.gl-spinner-dark.gl-spinner-lg{ aria: { label: _('Loading') } }
+- elsif @users.empty?
+ .nothing-here-block.border-top-0
+ = s_('AdminUsers|No users found')
+- else
+ .table-holder
+ .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' }
+ - user_table_headers.each do |header|
+ .table-section{ class: header[:section_class_name], role: 'rowheader' }= header[:header_text]
+
+ = render partial: 'admin/users/user', collection: @users
+
+= paginate @users, theme: "gitlab"
+
+= render partial: 'admin/users/modals'
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index cef16b1881e..8da0c7f4300 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -1,92 +1,17 @@
- page_title _("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)
- %ul.nav-links.nav.nav-tabs.scrolling-tabs
- = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do
- = link_to admin_users_path do
- = s_('AdminUsers|Active')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.active_without_ghosts)
- = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do
- = link_to admin_users_path(filter: "admins") do
- = s_('AdminUsers|Admins')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.admins)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do
- = link_to admin_users_path(filter: 'two_factor_enabled') do
- = s_('AdminUsers|2FA Enabled')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do
- = link_to admin_users_path(filter: 'two_factor_disabled') do
- = s_('AdminUsers|2FA Disabled')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor)
- = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do
- = link_to admin_users_path(filter: 'external') do
- = s_('AdminUsers|External')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.external)
- = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do
- = link_to admin_users_path(filter: "blocked") do
- = s_('AdminUsers|Blocked')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked)
- = nav_link(html_options: { class: "#{active_when(params[:filter] == 'blocked_pending_approval')} filter-blocked-pending-approval" }) do
- = link_to admin_users_path(filter: "blocked_pending_approval"), data: { qa_selector: 'pending_approval_tab' } do
- = s_('AdminUsers|Pending approval')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked_pending_approval)
- = nav_link(html_options: { class: active_when(params[:filter] == 'deactivated') }) do
- = link_to admin_users_path(filter: "deactivated") do
- = s_('AdminUsers|Deactivated')
- %small.badge.badge-pill= limited_counter_with_delimiter(User.deactivated)
- = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do
- = link_to admin_users_path(filter: "wop") do
- = s_('AdminUsers|Without projects')
- %small.badge.badge-pill= 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'
- = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn gl-button btn-success btn-search float-right'
+%ul.nav-links.nav-tabs.nav.js-users-tabs{ role: 'tablist' }
+ %li.nav-item.js-users-tab-item{ role: 'presentation' }
+ %a.nav-link{ href: '#users', class: active_when(params[:tab] != 'cohorts'), data: { toggle: 'tab' }, role: 'tab' }
+ = s_('AdminUsers|Users')
+ %li.nav-item.js-users-tab-item{ role: 'presentation' }
+ %a.nav-link{ href: '#cohorts', class: active_when(params[:tab] == 'cohorts'), data: { toggle: 'tab', track: { event: 'i_analytics_cohorts', action: 'click_tab' } }, role: 'tab' }
+ = s_('AdminUsers|Cohorts')
-.filtered-search-block.row-content-block.border-top-0
- = form_tag admin_users_path, method: :get do
- - if params[:filter].present?
- = hidden_field_tag "filter", h(params[:filter])
- .search-holder
- .search-field-holder.gl-mb-4
- = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false, data: { qa_selector: 'user_search_field' }
- - if @sort.present?
- = hidden_field_tag :sort, @sort
- = sprite_icon('search', css_class: 'search-icon')
- = button_tag s_('AdminUsers|Search users') if Rails.env.test?
- .dropdown.user-sort-dropdown
- = label_tag 'Sort by', nil, class: 'label-bold'
- - toggle_text = @sort.present? ? users_sort_options_hash[@sort] : sort_title_name
- = dropdown_toggle(toggle_text, { toggle: 'dropdown' })
- %ul.dropdown-menu.dropdown-menu-right
- %li.dropdown-header
- = s_('AdminUsers|Sort by')
- %li
- - users_sort_options_hash.each do |value, title|
- = link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do
- = title
+.tab-content
+ .tab-pane{ id: 'users', class: ('active' if params[:tab] != 'cohorts') }
+ = render 'users'
+ .tab-pane{ id: 'cohorts', class: ('active' if params[:tab] == 'cohorts') }
+ = render 'cohorts'
-- if Feature.enabled?(:vue_admin_users)
- #js-admin-users-app{ data: admin_users_data_attributes(@users) }
- .gl-spinner-container.gl-my-7
- %span.gl-vertical-align-bottom.gl-spinner.gl-spinner-dark.gl-spinner-lg{ aria: { label: _('Loading') } }
-- elsif @users.empty?
- .nothing-here-block.border-top-0
- = s_('AdminUsers|No users found')
-- else
- .table-holder
- .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' }
- .table-section.section-40{ role: 'rowheader' }= _('Name')
- .table-section.section-10{ role: 'rowheader' }= _('Projects')
- .table-section.section-15{ role: 'rowheader' }= _('Created on')
- .table-section.section-15{ role: 'rowheader' }= _('Last activity')
- = render partial: 'admin/users/user', collection: @users
-
-= paginate @users, theme: "gitlab"
-
-= render partial: 'admin/users/modals'
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 26f78ea4d6a..c7ec3ab66d7 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -138,10 +138,10 @@
.col-md-6
- unless @user == current_user
- if can_force_email_confirmation?(@user)
- .card.border-info
- .card-header.bg-info.text-white
+ .gl-card.border-info.gl-mb-5
+ .gl-card-header.bg-info.text-white
Confirm user
- .card-body
+ .gl-card-body
- if @user.unconfirmed_email.present?
- email = " (#{@user.unconfirmed_email})"
%p This user has an unconfirmed email address#{email}. You may force a confirmation.
@@ -152,19 +152,19 @@
- unless @user.internal?
- if @user.deactivated?
- .card.border-info
- .card-header.bg-info.text-white
+ .gl-card.border-info.gl-mb-5
+ .gl-card-header.bg-info.text-white
Reactivate this user
- .card-body
+ .gl-card-body
= render partial: 'admin/users/user_activation_effects'
%br
%button.btn.gl-button.btn-info.js-confirm-modal-button{ data: user_activation_data(@user) }
= s_('AdminUsers|Activate user')
- elsif @user.can_be_deactivated?
- .card.border-warning
- .card-header.bg-warning.text-white
+ .gl-card.border-warning.gl-mb-5
+ .gl-card-header.bg-warning.text-white
Deactivate this user
- .card-body
+ .gl-card-body
= user_deactivation_effects
%br
%button.btn.gl-button.btn-warning.js-confirm-modal-button{ data: user_deactivation_data(@user, s_('AdminUsers|You can always re-activate their account, their data will remain intact.')) }
@@ -174,10 +174,10 @@
= render 'admin/users/approve_user', user: @user
= render 'admin/users/reject_pending_user', user: @user
- else
- .card.border-info
- .card-header.gl-bg-blue-500.gl-text-white
+ .gl-card.border-info.gl-mb-5
+ .gl-card-header.gl-bg-blue-500.gl-text-white
This user is blocked
- .card-body
+ .gl-card-body
%p A blocked user cannot:
%ul
%li Log in
@@ -189,7 +189,7 @@
= render 'admin/users/block_user', user: @user
- if @user.access_locked?
- .card.border-info
+ .card.border-info.gl-mb-5
.card-header.bg-info.text-white
This account has been locked
.card-body
@@ -197,15 +197,15 @@
%br
= link_to 'Unlock user', unlock_admin_user_path(@user), method: :put, class: "btn gl-button btn-info", data: { confirm: 'Are you sure?' }
- if !@user.blocked_pending_approval?
- .card.border-danger
- .card-header.bg-danger.text-white
+ .gl-card.border-danger.gl-mb-5
+ .gl-card-header.bg-danger.text-white
= s_('AdminUsers|Delete user')
- .card-body
+ .gl-card-body
- if @user.can_be_removed? && can?(current_user, :destroy_user, @user)
%p Deleting a user has the following effects:
= render 'users/deletion_guidance', user: @user
%br
- %button.delete-user-button.btn.gl-button.btn-danger{ data: { 'gl-modal-action': 'delete',
+ %button.js-delete-user-modal-button.btn.gl-button.btn-danger{ data: { 'gl-modal-action': 'delete',
delete_user_url: admin_user_path(@user),
block_user_url: block_admin_user_path(@user),
username: sanitize_name(@user.name) } }
@@ -221,10 +221,10 @@
%p
You don't have access to delete this user.
- .card.border-danger
- .card-header.bg-danger.text-white
+ .gl-card.border-danger
+ .gl-card-header.bg-danger.text-white
= s_('AdminUsers|Delete user and contributions')
- .card-body
+ .gl-card-body
- if can?(current_user, :destroy_user, @user)
%p
This option deletes the user and any contributions that
@@ -235,7 +235,7 @@
the user, and projects in them, will also be removed. Commits
to other projects are unaffected.
%br
- %button.delete-user-button.btn.gl-button.btn-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
+ %button.js-delete-user-modal-button.btn.gl-button.btn-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
delete_user_url: admin_user_path(@user, hard_delete: true),
block_user_url: block_admin_user_path(@user),
username: @user.name } }
diff --git a/app/views/authentication/_authenticate.html.haml b/app/views/authentication/_authenticate.html.haml
index 17e855dbddd..2d8948ae9aa 100644
--- a/app/views/authentication/_authenticate.html.haml
+++ b/app/views/authentication/_authenticate.html.haml
@@ -7,7 +7,7 @@
%script#js-authenticate-token-2fa-error{ type: "text/template" }
%div
%p <%= error_message %> (<%= error_name %>)
- %a.btn.btn-block.btn-warning#js-token-2fa-try-again= _("Try again?")
+ %a.btn.gl-button.btn-block.btn-warning#js-token-2fa-try-again= _("Try again?")
%script#js-authenticate-token-2fa-authenticated{ type: "text/template" }
%div
diff --git a/app/views/authentication/_register.html.haml b/app/views/authentication/_register.html.haml
index f1aa76d115a..d250cddf0f8 100644
--- a/app/views/authentication/_register.html.haml
+++ b/app/views/authentication/_register.html.haml
@@ -7,13 +7,13 @@
- if current_user.two_factor_otp_enabled?
.row.gl-mb-3
.col-md-5
- %button#js-setup-token-2fa-device.btn.btn-info= _("Set up new device")
+ %button#js-setup-token-2fa-device.gl-button.btn.btn-confirm= _("Set up new device")
.col-md-7
%p= _("Your device needs to be set up. Plug it in (if needed) and click the button on the left.")
- else
.row.gl-mb-3
.col-md-4
- %button#js-setup-token-2fa-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new device")
+ %button#js-setup-token-2fa-device.gl-button.btn.btn-confirm.btn-block{ disabled: true }= _("Set up new device")
.col-md-8
%p= _("You need to register a two-factor authentication app before you can set up a device.")
@@ -21,7 +21,7 @@
%div
%p
%span <%= error_message %> (<%= error_name %>)
- %a.btn.btn-warning#js-token-2fa-try-again= _("Try again?")
+ %a.btn.gl-button.btn-warning#js-token-2fa-try-again= _("Try again?")
%script#js-register-token-2fa-registered{ type: "text/template" }
.row.gl-mb-3
diff --git a/app/views/ci/group_variables/_content.html.haml b/app/views/ci/group_variables/_content.html.haml
index db5f1021f57..fe8155cd9f7 100644
--- a/app/views/ci/group_variables/_content.html.haml
+++ b/app/views/ci/group_variables/_content.html.haml
@@ -1 +1 @@
-= _("These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables.")
+= _("These variables are inherited from the parent group.")
diff --git a/app/views/ci/group_variables/_index.html.haml b/app/views/ci/group_variables/_index.html.haml
index 84bcd42e07c..a74dbe793a6 100644
--- a/app/views/ci/group_variables/_index.html.haml
+++ b/app/views/ci/group_variables/_index.html.haml
@@ -1,13 +1,12 @@
- variables = @project.group.self_and_ancestors.map(&:variables).flatten
-.row
- .col-lg-12
- .group-variable-list
- = render 'ci/group_variables/variable_header'
- - variables.each do |variable|
- .group-variable-row.d-flex.w-100.border-bottom.pt-2.pb-2
- .table-section.section-40.gl-mr-3.key
- = variable.key
- .table-section.section-40.gl-mr-3
- %a.group-origin-link{ href: group_settings_ci_cd_path(variable.group) }
- = variable.group.name
+.ci-variable-table
+ %table.gl-table.gl-w-full.gl-table-layout-fixed
+ = render 'ci/group_variables/variable_header'
+ - variables.each do |variable|
+ %tr
+ %td.gl-text-truncate
+ = variable.key
+ %td.gl-text-truncate
+ %a.group-origin-link{ href: group_settings_ci_cd_path(variable.group) }
+ = variable.group.name
diff --git a/app/views/ci/group_variables/_variable_header.html.haml b/app/views/ci/group_variables/_variable_header.html.haml
index a8d533da0e0..ec512ab37e7 100644
--- a/app/views/ci/group_variables/_variable_header.html.haml
+++ b/app/views/ci/group_variables/_variable_header.html.haml
@@ -1,5 +1,5 @@
-.group-variable-keys.d-flex.w-100.align-items-center.pb-2.border-bottom
- .bold.table-section.section-40.gl-mr-3
+%tr
+ %th
= s_('Key')
- .bold.table-section.section-40.gl-mr-3
- = s_('Origin')
+ %th
+ = s_('Group')
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 fc3d5360f9b..6c2e4c69d83 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -21,3 +21,5 @@
= button_to _("Reset registration token"), reset_token_url,
method: :put, class: 'gl-button btn btn-default',
data: { confirm: _("Are you sure you want to reset the registration token?") }
+
+#js-install-runner{ data: { project_path: project_path, group_path: group_path } }
diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml
index bf695d871f8..fd4b546e150 100644
--- a/app/views/ci/variables/_content.html.haml
+++ b/app/views/ci/variables/_content.html.haml
@@ -1,8 +1,10 @@
-= html_escape(_('Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+= _('Variables store information, like passwords and secret keys, that you can use in job scripts.')
+= link_to s_('Learn more.'), help_page_path('ci/variables/README'), target: '_blank', rel: 'noopener noreferrer'
+%p
+ = _('Variables can be:')
%ul
%li
- = html_escape(_('%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = html_escape(_('%{code_open}Protected:%{code_close} Only exposed to protected branches or tags.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
%li
- = html_escape(_('%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so).')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
-
-= link_to _('More information'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables')
+ = html_escape(_('%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = link_to _('Learn more.'), help_page_path('ci/variables/README', anchor: 'masked-variable-requirements'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/ci/variables/_header.html.haml b/app/views/ci/variables/_header.html.haml
index f4e2a8584d8..a1b7f6efe54 100644
--- a/app/views/ci/variables/_header.html.haml
+++ b/app/views/ci/variables/_header.html.haml
@@ -2,9 +2,8 @@
%h4
= _('Variables')
- = link_to sprite_icon('question-o', css_class: 'gl-vertical-align-baseline!'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
-%button.btn.btn-default.js-settings-toggle{ type: 'button' }
+%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index 3f6d60c2620..fc0e3488e57 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -3,7 +3,7 @@
- if ci_variable_protected_by_default?
%p.settings-message.text-center
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable') }
- = s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- is_group = !@group.nil?
diff --git a/app/views/dashboard/_activity_head.html.haml b/app/views/dashboard/_activity_head.html.haml
index 3f39555a1d4..0daadd20f54 100644
--- a/app/views/dashboard/_activity_head.html.haml
+++ b/app/views/dashboard/_activity_head.html.haml
@@ -5,7 +5,10 @@
%ul.nav-links.nav.nav-tabs
%li{ class: active_when(params[:filter].nil?) }>
= link_to activity_dashboard_path, class: 'shortcuts-activity', data: {placement: 'right'} do
- Your projects
+ = _('Your projects')
%li{ class: active_when(params[:filter] == 'starred') }>
= link_to activity_dashboard_path(filter: 'starred'), data: {placement: 'right'} do
- Starred projects
+ = _('Starred projects')
+ %li{ class: active_when(params[:filter] == 'followed') }>
+ = link_to activity_dashboard_path(filter: 'followed'), data: {placement: 'right'} do
+ = _('Followed users')
diff --git a/app/views/dashboard/issues.atom.builder b/app/views/dashboard/issues.atom.builder
index 6034389b897..729e966e48a 100644
--- a/app/views/dashboard/issues.atom.builder
+++ b/app/views/dashboard/issues.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop: disable CodeReuse/ActiveRecord
xml.title "#{current_user.name} issues"
xml.link href: url_for(safe_params), rel: "self", type: "application/atom+xml"
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 923e78ad360..872099f98fc 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -17,12 +17,11 @@
.nav-controls
= render 'shared/milestones/search_form'
-.milestones
- %ul.content-list
- - if @milestones.blank?
- %li
- .nothing-here-block No milestones to show
- - else
+- if @milestones.blank?
+ = render 'shared/empty_states/milestones'
+- else
+ .milestones
+ %ul.content-list
- @milestones.each do |milestone|
= render 'milestone', milestone: milestone
- = paginate @milestones, theme: 'gitlab'
+ = paginate @milestones, theme: 'gitlab'
diff --git a/app/views/dashboard/projects/_starred_empty_state.html.haml b/app/views/dashboard/projects/_starred_empty_state.html.haml
index bea27f1a456..6db018d72da 100644
--- a/app/views/dashboard/projects/_starred_empty_state.html.haml
+++ b/app/views/dashboard/projects/_starred_empty_state.html.haml
@@ -3,7 +3,7 @@
.svg-content.svg-250
= image_tag 'illustrations/starred_empty.svg'
.text-content
- %h4.text-center
+ %h4.gl-text-center
= s_("StarredProjectsEmptyState|You don't have starred projects yet.")
- %p.text-secondary
+ %p.gl-text-gray-500
= s_("StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page.")
diff --git a/app/views/dashboard/projects/index.atom.builder b/app/views/dashboard/projects/index.atom.builder
index 747c53b440e..85709266548 100644
--- a/app/views/dashboard/projects/index.atom.builder
+++ b/app/views/dashboard/projects/index.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.title "Activity"
xml.link href: dashboard_projects_url(rss_url_options), rel: "self", type: "application/atom+xml"
xml.link href: dashboard_projects_url, rel: "alternate", type: "text/html"
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index d458f1d8eba..6f4d53c79a7 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -5,7 +5,7 @@
- if show_customize_homepage_banner?(@customize_homepage)
= content_for :customize_homepage_banner do
- .gl-display-none.gl-display-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
+ .gl-display-none.gl-md-display-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
callouts_path: user_callouts_path,
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index 8e038baf14d..f2f8afb636d 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -48,14 +48,14 @@
- if todo.pending?
.todo-actions
- = link_to dashboard_todo_path(todo), method: :delete, class: 'gl-button btn btn-loading d-flex align-items-center js-done-todo', data: { href: dashboard_todo_path(todo) } do
+ = link_to dashboard_todo_path(todo), method: :delete, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-done-todo', data: { href: dashboard_todo_path(todo) } do
Done
%span.spinner.ml-1
- = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-loading d-flex align-items-center js-undo-todo hidden', data: { href: restore_dashboard_todo_path(todo) } do
+ = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-undo-todo hidden', data: { href: restore_dashboard_todo_path(todo) } do
Undo
%span.spinner.ml-1
- else
.todo-actions
- = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-loading d-flex align-items-center js-add-todo', data: { href: restore_dashboard_todo_path(todo) } do
+ = link_to restore_dashboard_todo_path(todo), method: :patch, class: 'gl-button btn btn-default btn-loading d-flex align-items-center js-add-todo', data: { href: restore_dashboard_todo_path(todo) } do
Add a to do
%span.spinner.ml-1
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index bf61d0bd1f0..9301f24d6a4 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -27,10 +27,10 @@
.nav-controls
- if @todos.any?(&:pending?)
.gl-mr-3
- = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'gl-button btn btn-loading align-items-center js-todos-mark-all', method: :delete, data: { href: destroy_all_dashboard_todos_path(todos_filter_params) } do
+ = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'gl-button btn btn-default btn-loading align-items-center js-todos-mark-all', method: :delete, data: { href: destroy_all_dashboard_todos_path(todos_filter_params) } do
Mark all as done
%span.spinner.ml-1
- = link_to bulk_restore_dashboard_todos_path, class: 'gl-button btn btn-loading align-items-center js-todos-undo-all hidden', method: :patch , data: { href: bulk_restore_dashboard_todos_path(todos_filter_params) } do
+ = link_to bulk_restore_dashboard_todos_path, class: 'gl-button btn btn-default btn-loading align-items-center js-todos-undo-all hidden', method: :patch , data: { href: bulk_restore_dashboard_todos_path(todos_filter_params) } do
Undo mark all as done
%span.spinner.ml-1
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index 770a29a629e..ace80ba16dd 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -6,7 +6,7 @@
= render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
- = f.email_field :email, class: "form-control", required: true, title: 'Please provide a valid email address.', value: nil
+ = f.email_field :email, class: "form-control gl-form-input", required: true, title: 'Please provide a valid email address.', value: nil
.clearfix
= f.submit "Resend", class: 'gl-button btn btn-success'
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 42e301d88ae..7876aed2c0a 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -7,12 +7,12 @@
= f.hidden_field :reset_password_token
.form-group
= f.label 'New password', for: "user_password"
- = f.password_field :password, class: "form-control top", required: true, title: 'This field is required', data: { qa_selector: 'password_field'}
+ = f.password_field :password, class: "form-control gl-form-input top", required: true, title: 'This field is required', data: { qa_selector: 'password_field'}
.form-group
= f.label 'Confirm new password', for: "user_password_confirmation"
- = f.password_field :password_confirmation, class: "form-control bottom", title: 'This field is required', data: { qa_selector: 'password_confirmation_field' }, required: true
+ = f.password_field :password_confirmation, class: "form-control gl-form-input bottom", title: 'This field is required', data: { qa_selector: 'password_confirmation_field' }, required: true
.clearfix
- = f.submit "Change your password", class: "gl-button btn btn-primary", data: { qa_selector: 'change_password_button' }
+ = f.submit "Change your password", class: "gl-button btn btn-confirm", data: { qa_selector: 'change_password_button' }
.clearfix.prepend-top-20
%p
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index fe999851605..c4672a5b25e 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -1,4 +1,3 @@
-= render 'devise/shared/tab_single', tab_title: 'Reset Password'
.login-box
.login-body
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
@@ -6,9 +5,9 @@
= render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
- = f.email_field :email, class: "form-control", required: true, value: params[:user_email], autofocus: true, title: 'Please provide a valid email address.'
+ = f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: 'Please provide a valid email address.'
.clearfix
- = f.submit "Reset password", class: "btn-primary btn"
+ = f.submit "Reset password", class: "gl-button btn-confirm btn"
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index a1a1a767847..270652483b7 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -1,10 +1,10 @@
= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive'}) do |f|
.form-group
= f.label _('Username or email'), for: 'user_login', class: 'label-bold'
- = f.text_field :login, value: @invite_email, class: 'form-control top', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field' }
+ = f.text_field :login, value: @invite_email, class: 'form-control gl-form-input top', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field' }
.form-group
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: 'form-control bottom', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
+ = f.password_field :password, class: 'form-control gl-form-input bottom', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
- if devise_mapping.rememberable?
.remember-me
%label{ for: 'user_remember_me' }
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 3fc99b6a47d..8f397de41b7 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -5,10 +5,10 @@
= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "gl-show-field-errors") do
.form-group
= label_tag :username, "#{server['label']} Username"
- = text_field_tag :username, nil, { class: "form-control top", title: "This field is required.", autofocus: "autofocus", data: { qa_selector: 'username_field' }, required: true }
+ = text_field_tag :username, nil, { class: "form-control gl-form-input top", title: "This field is required.", autofocus: "autofocus", data: { qa_selector: 'username_field' }, required: true }
.form-group
= label_tag :password
- = password_field_tag :password, nil, { class: "form-control bottom", title: "This field is required.", data: { qa_selector: 'password_field' }, required: true }
+ = password_field_tag :password, nil, { class: "form-control gl-form-input bottom", title: "This field is required.", data: { qa_selector: 'password_field' }, required: true }
- if !hide_remember_me && devise_mapping.rememberable?
.remember-me
%label{ for: "remember_me" }
@@ -16,4 +16,4 @@
%span Remember me
.submit-container.move-submit-down
- = submit_tag submit_message, class: "btn-success btn", data: { qa_selector: 'sign_in_button' }
+ = submit_tag submit_message, class: "gl-button btn-success btn", data: { qa_selector: 'sign_in_button' }
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index f5f76eb92b1..8704bd16a13 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -8,7 +8,7 @@
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
= f.label 'Two-Factor Authentication code', name: :otp_attempt
- = f.text_field :otp_attempt, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.', data: { qa_selector: 'two_fa_code_field' }
+ = f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.', data: { qa_selector: 'two_fa_code_field' }
%p.form-text.text-muted.hint 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.
.prepend-top-20
= f.submit "Verify code", class: "gl-button btn btn-success", data: { qa_selector: 'verify_code_button' }
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 67e6e510923..705fd9bbd0f 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -7,7 +7,7 @@
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "gl-button btn d-flex align-items-center omniauth-btn text-left oauth-login #{qa_class_for_provider(provider)}" do
+ = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default d-flex align-items-center omniauth-btn text-left oauth-login #{qa_class_for_provider(provider)}" do
- if has_icon
= provider_image_tag(provider)
%span
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index acbf3b398b0..aa2224b3ea3 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -15,22 +15,22 @@
.name.form-row
.col.form-group
= f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
- = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _('This field is required.')
+ = f.text_field :first_name, class: 'form-control gl-form-input top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _('This field is required.')
.col.form-group
= f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
- = f.text_field :last_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_last_name_length, :max_length_message => s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _('This field is required.')
+ = f.text_field :last_name, class: 'form-control gl-form-input top js-block-emoji js-validate-length', :data => { :max_length => max_last_name_length, :max_length_message => s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _('This field is required.')
.username.form-group
= f.label :username, class: 'label-bold'
- = f.text_field :username, class: 'form-control middle js-block-emoji js-validate-length js-validate-username', :data => { :api_path => suggestion_path, :min_length => min_username_length, :min_length_message => s_('SignUp|Username is too short (minimum is %{min_length} characters).') % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_('SignUp|Username is too long (maximum is %{max_length} characters).') % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _('Please create a username with only alphanumeric characters.')
+ = f.text_field :username, class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username', :data => { :api_path => suggestion_path, :min_length => min_username_length, :min_length_message => s_('SignUp|Username is too short (minimum is %{min_length} characters).') % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_('SignUp|Username is too long (maximum is %{max_length} characters).') % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _('Please create a username with only alphanumeric characters.')
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
.form-group
= f.label :email, class: 'label-bold'
- = f.email_field :email, value: @invite_email, class: 'form-control middle', data: { qa_selector: 'new_user_email_field' }, required: true, title: _('Please provide a valid email address.')
+ = f.email_field :email, value: @invite_email, class: 'form-control gl-form-input middle', data: { qa_selector: 'new_user_email_field' }, required: true, title: _('Please provide a valid email address.')
.form-group.gl-mb-5#password-strength
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: 'form-control bottom', data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
+ = f.password_field :password, class: 'form-control gl-form-input bottom', data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%div
- if show_recaptcha_sign_up?
diff --git a/app/views/devise/shared/_signup_omniauth_provider_list.haml b/app/views/devise/shared/_signup_omniauth_provider_list.haml
index ece886b3cdd..43e0802ee2a 100644
--- a/app/views/devise/shared/_signup_omniauth_provider_list.haml
+++ b/app/views/devise/shared/_signup_omniauth_provider_list.haml
@@ -2,7 +2,7 @@
= _("Create an account using:")
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button gl-display-flex gl-align-items-center gl-text-left gl-mb-2 gl-p-2 omniauth-btn oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-display-flex gl-align-items-center gl-text-left gl-mb-2 gl-p-2 omniauth-btn oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
- if provider_has_icon?(provider)
= provider_image_tag(provider)
%span.ml-2
diff --git a/app/views/discussions/_notes.html.haml b/app/views/discussions/_notes.html.haml
index 7db318f83b1..beac4946fd7 100644
--- a/app/views/discussions/_notes.html.haml
+++ b/app/views/discussions/_notes.html.haml
@@ -19,8 +19,6 @@
.discussion-reply-holder
- if can_create_note?
- %a.user-avatar-link.d-none.d-sm-block{ href: user_path(current_user) }
- = image_tag avatar_icon_for_user(current_user), alt: current_user.to_reference, class: 'avatar s40'
.discussion-with-resolve-btn
= link_to_reply_discussion(discussion)
- elsif !current_user
diff --git a/app/views/doorkeeper/applications/_delete_form.html.haml b/app/views/doorkeeper/applications/_delete_form.html.haml
index 3d6361a90ca..13ae18af2c5 100644
--- a/app/views/doorkeeper/applications/_delete_form.html.haml
+++ b/app/views/doorkeeper/applications/_delete_form.html.haml
@@ -2,7 +2,7 @@
= form_tag oauth_application_path(application) do
%input{ :name => "_method", :type => "hidden", :value => "delete" }/
- if defined? small
- = button_tag type: "submit", class: "gl-button btn btn-transparent", data: { confirm: _("Are you sure?") } do
+ = button_tag type: "submit", class: "gl-button btn btn-default", data: { confirm: _("Are you sure?") } do
%span.sr-only
= _('Destroy')
= sprite_icon('remove')
diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml
index fbae24410bb..39529e59aee 100644
--- a/app/views/doorkeeper/applications/_form.html.haml
+++ b/app/views/doorkeeper/applications/_form.html.haml
@@ -3,11 +3,11 @@
.form-group
= f.label :name, class: 'label-bold'
- = f.text_field :name, class: 'form-control', required: true
+ = f.text_field :name, class: 'form-control gl-form-input', required: true
.form-group
= f.label :redirect_uri, class: 'label-bold'
- = f.text_area :redirect_uri, class: 'form-control', required: true
+ = f.text_area :redirect_uri, class: 'form-control gl-form-input gl-form-textarea', required: true
%span.form-text.text-muted
= _('Use one line per URI')
diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml
index 2daba4586e1..827a839234f 100644
--- a/app/views/doorkeeper/applications/index.html.haml
+++ b/app/views/doorkeeper/applications/index.html.haml
@@ -40,8 +40,8 @@
- application.redirect_uri.split.each do |uri|
%div= uri
%td= application.access_tokens.count
- %td
- = link_to edit_oauth_application_path(application), class: "gl-button btn btn-transparent gl-mr-2" do
+ %td.gl-display-flex
+ = link_to edit_oauth_application_path(application), class: "gl-button btn btn-default gl-mr-2" do
%span.sr-only
= _('Edit')
= sprite_icon('pencil')
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 0a091aa7586..046d44bc47f 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -43,5 +43,5 @@
= render "shared/tokens/scopes_list", token: @application
.form-actions
- = link_to _('Edit'), edit_oauth_application_path(@application), class: 'gl-button btn btn-primary wide float-left'
- = render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger gl-ml-3'
+ = link_to _('Edit'), edit_oauth_application_path(@application), class: 'gl-button btn btn-confirm wide float-left'
+ = render 'delete_form', application: @application, submit_btn_css: 'gl-button btn btn-danger gl-ml-3'
diff --git a/app/views/events/_event.atom.builder b/app/views/events/_event.atom.builder
index 406e8a93194..17bf43a4590 100644
--- a/app/views/events/_event.atom.builder
+++ b/app/views/events/_event.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
return unless event.visible_to_user?(current_user)
event = event.present
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 67f278a06f3..37c4ecc09f3 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -23,7 +23,11 @@
.home-panel-buttons.col-md-12.col-lg-6
- if current_user
.gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2{ data: { testid: 'group-buttons' } }
- = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn gl-button gl-sm-w-auto gl-w-full', dropdown_container_class: 'gl-mr-0 gl-px-2 gl-sm-w-auto gl-w-full', emails_disabled: emails_disabled
+ - if Feature.enabled?(:vue_notification_dropdown, @group, default_enabled: :yaml)
+ - if @notification_setting
+ .js-vue-notification-dropdown{ data: { disabled: emails_disabled, 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-mr-3 gl-mt-3 gl-vertical-align-top' } }
+ - else
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn gl-button gl-sm-w-auto gl-w-full', dropdown_container_class: 'gl-mr-0 gl-px-2 gl-sm-w-auto gl-w-full', emails_disabled: emails_disabled
- 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-success btn-md gl-button btn-success-secondary 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_another_instance_panel.html.haml b/app/views/groups/_import_group_from_another_instance_panel.html.haml
index c95e7c16161..83d2e13d345 100644
--- a/app/views/groups/_import_group_from_another_instance_panel.html.haml
+++ b/app/views/groups/_import_group_from_another_instance_panel.html.haml
@@ -2,9 +2,18 @@
= form_errors(@group)
.gl-border-l-solid.gl-border-r-solid.gl-border-gray-100.gl-border-1.gl-p-5
- %h4
+ %h4.gl-display-flex
= s_('GroupsNew|Import groups from another instance of GitLab')
- %p
+ %span.badge.badge-info.badge-pill.gl-badge.md.gl-ml-3
+ = _('Beta')
+ .gl-alert.gl-alert-warning{ role: 'alert' }
+ = sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
+ .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') }
+ - feedback_link_start = '<a href="https://gitlab.com/gitlab-org/gitlab/-/issues/284495" target="_blank" rel="noopener noreferrer">'.html_safe
+ - link_end = '</a>'.html_safe
+ = s_('GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end, feedback_link_start: feedback_link_start, feedback_link_end: link_end }
+ %p.gl-mt-3
= s_('GroupsNew|Provide credentials for another instance of GitLab to import your groups directly.')
.form-group.gl-display-flex.gl-flex-direction-column
= f.label :bulk_import_gitlab_url, s_('GroupsNew|GitLab source URL'), for: 'import_gitlab_url'
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index bd53f73230e..ba6dfcb70ff 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -1,4 +1,4 @@
-- if invite_members_allowed?(group)
+- if can_invite_members_for_group?(group)
.js-invite-members-modal{ data: { id: group.id,
name: group.name,
is_project: 'false',
diff --git a/app/views/groups/_invite_members_side_nav_link.html.haml b/app/views/groups/_invite_members_side_nav_link.html.haml
deleted file mode 100644
index 4f1c06d9fe3..00000000000
--- a/app/views/groups/_invite_members_side_nav_link.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- if invite_members_allowed?(group) && body_data_page == 'groups:show'
- %li
- .js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
diff --git a/app/views/groups/_new_group_fields.html.haml b/app/views/groups/_new_group_fields.html.haml
index 3872bbcd062..64860c61082 100644
--- a/app/views/groups/_new_group_fields.html.haml
+++ b/app/views/groups/_new_group_fields.html.haml
@@ -18,5 +18,5 @@
= render_if_exists 'shared/groups/invite_members'
.row
.form-actions.col-sm-12
- = f.submit _('Create group'), class: "btn btn-success"
- = link_to _('Cancel'), dashboard_groups_path, class: 'btn btn-cancel'
+ = f.submit _('Create group'), class: "btn gl-button btn-success"
+ = link_to _('Cancel'), dashboard_groups_path, class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 229e04a371a..d1c4e1a7deb 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -26,6 +26,7 @@
.settings-content
= render 'groups/settings/permissions'
+= render_if_exists 'groups/merge_request_approval_settings', expanded: expanded, group: @group, user: current_user
= render_if_exists 'groups/insights', expanded: expanded
%section.settings.no-animate#js-badge-settings{ class: ('expanded' if expanded) }
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index ab3998be009..a5257ff20bc 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -14,12 +14,12 @@
= _('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 invite_members_allowed?(@group)
+ - if can_invite_members_for_group?(@group)
.gl-w-half.gl-xs-w-full
.gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2.gl-mb-3
.js-invite-members-trigger.gl-px-2.gl-sm-w-auto.gl-w-full.gl-mb-4{ data: { classes: 'btn btn-success gl-button gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite members') } }
- = render_if_exists 'groups/invite_members_modal', group: @group
- - if can_manage_members && !invite_members_allowed?(@group)
+ = render 'groups/invite_members_modal', group: @group
+ - if can_manage_members && !can_invite_members_for_group?(@group)
%hr.gl-mt-4
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
@@ -66,7 +66,7 @@
= paginate @members, theme: 'gitlab', params: { invited_members_page: nil, search_invited: nil }
- if @group.shared_with_group_links.any?
#tab-groups.tab-pane
- .js-group-linked-list{ data: linked_groups_list_data_attributes(@group) }
+ .js-group-group-links-list{ data: group_group_links_list_data_attributes(@group) }
.loading
.spinner.spinner-md
- if show_invited_members
diff --git a/app/views/groups/issues.atom.builder b/app/views/groups/issues.atom.builder
index 2fd96c9d158..6f29a4e439c 100644
--- a/app/views/groups/issues.atom.builder
+++ b/app/views/groups/issues.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop: disable CodeReuse/ActiveRecord
xml.title "#{@group.name} issues"
xml.link href: url_for(safe_params), rel: "self", type: "application/atom+xml"
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index c93b24d14f0..2d5dc4c931d 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -8,17 +8,16 @@
= render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @group)
- = link_to "New milestone", new_group_milestone_path(@group), class: "btn gl-button btn-success", data: { qa_selector: "new_group_milestone_link" }
+ = link_to _('New milestone'), new_group_milestone_path(@group), class: "btn gl-button btn-success", data: { qa_selector: "new_group_milestone_link" }
-.milestones
- %ul.content-list
- - if @milestones.blank?
- %li
- .nothing-here-block No milestones to show
- - else
+- if @milestones.blank?
+ = render 'shared/empty_states/milestones'
+- else
+ .milestones
+ %ul.content-list
- @milestones.each do |milestone|
- if milestone.project_milestone?
= render 'projects/milestones/milestone', milestone: milestone
- else
= render 'milestone', milestone: milestone
- = paginate @milestones, theme: "gitlab"
+ = paginate @milestones, theme: "gitlab"
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index 4fa2fc6fd4d..784f477673a 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -7,15 +7,15 @@
projects:
- if can? current_user, :admin_group, @group
.controls
- = link_to new_project_path(namespace_id: @group.id), class: "btn btn-sm btn-success" do
+ = link_to new_project_path(namespace_id: @group.id), class: "btn gl-button btn-sm btn-success" do
New project
%ul.projects-list.content-list.group-settings-projects
- @projects.each do |project|
%li.project-row{ class: ('no-description' if project.description.blank?) }
.controls
- = link_to _('Members'), project_project_members_path(project), id: "edit_#{dom_id(project)}", class: "btn"
- = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn"
- = link_to _('Delete'), project, data: { confirm: remove_project_message(project)}, method: :delete, class: "gl-button btn btn-danger"
+ = link_to _('Members'), project_project_members_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button"
+ = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button"
+ = link_to _('Delete'), project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn gl-button btn-danger"
.stats
%span.badge.badge-pill
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index 6d0a3e03019..899e58050af 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -1,6 +1,6 @@
- page_title _("Container Registry")
- @content_class = "limit-container-width" unless fluid_layout
-- add_page_startup_graphql_call('container_registry/get_container_repositories', { fullPath: @group.full_path, first: 10, name: nil, isGroupPage: true} )
+- add_page_startup_graphql_call('container_registry/get_container_repositories', { fullPath: @group.full_path, first: 10, name: nil, isGroupPage: true, sort: nil} )
%section
#js-container-registry{ data: { endpoint: group_container_registries_path(@group),
@@ -17,4 +17,7 @@
is_group_page: "true",
"group_path": @group.full_path,
"gid_prefix": container_repository_gid_prefix,
- character_error: @character_error.to_s } }
+ character_error: @character_error.to_s,
+ user_callouts_path: user_callouts_path,
+ user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
+ show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s } }
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index 944ef3435c1..f60cdc9f8da 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -17,5 +17,7 @@
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @group.runners_token,
type: 'group',
- reset_token_url: reset_registration_token_group_settings_ci_cd_path }
+ reset_token_url: reset_registration_token_group_settings_ci_cd_path,
+ project_path: '',
+ group_path: @group.path }
%br
diff --git a/app/views/groups/runners/_runner.html.haml b/app/views/groups/runners/_runner.html.haml
index 3fc50cc86d2..80739395713 100644
--- a/app/views/groups/runners/_runner.html.haml
+++ b/app/views/groups/runners/_runner.html.haml
@@ -77,8 +77,9 @@
= link_to resume_group_runner_path(@group, runner), method: :post, class: 'btn btn-default has-tooltip', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
= sprite_icon('play')
- if runner.belongs_to_more_than_one_project?
- .btn-group
- .btn.btn-danger.has-tooltip{ 'aria-label' => 'Remove', 'data-container' => 'body', 'data-original-title' => _('Multi-project Runners cannot be removed'), 'data-placement' => 'top', disabled: 'disabled' }
+ - delete_runner_tooltip = _('Multi-project Runners cannot be removed')
+ .btn-group.has-tooltip{ data: { container: 'body', placement: 'top' }, title: delete_runner_tooltip }
+ .btn.btn-danger{ 'aria-label' => delete_runner_tooltip, disabled: 'disabled' }
= sprite_icon('close')
- else
.btn-group
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index c421a569a14..627807841c5 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -22,7 +22,7 @@
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
title: s_('GroupSettings|Please choose a group URL with no special characters.'),
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
- = f.submit s_('GroupSettings|Change group URL'), class: 'btn btn-warning'
+ = f.submit s_('GroupSettings|Change group URL'), class: 'btn gl-button btn-warning'
.sub-section
%h4.warning-title= s_('GroupSettings|Transfer group')
@@ -38,7 +38,7 @@
%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.")
- = f.submit s_('GroupSettings|Transfer group'), class: 'btn btn-warning'
+ = f.submit s_('GroupSettings|Transfer group'), class: 'btn gl-button btn-warning'
= render 'groups/settings/remove', group: @group
= render_if_exists 'groups/settings/restore', group: @group
diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml
index 94466b76ac8..f818f45cf53 100644
--- a/app/views/groups/settings/_export.html.haml
+++ b/app/views/groups/settings/_export.html.haml
@@ -20,9 +20,9 @@
%p= _('Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page.')
- if group.export_file_exists?
= link_to _('Regenerate export'), export_group_path(group),
- method: :post, class: 'btn btn-default', data: { qa_selector: 'regenerate_export_group_link' }
+ 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 btn-default', data: { qa_selector: 'download_export_link' }
+ rel: 'nofollow', method: :get, class: 'btn gl-button btn-default', data: { qa_selector: 'download_export_link' }
- else
= link_to _('Export group'), export_group_path(group),
- method: :post, class: 'btn btn-default', data: { qa_selector: 'export_group_link' }
+ 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 35d82084263..8ad5755fef8 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -29,4 +29,4 @@
= link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link'
= 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 btn-success mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' }
+ = f.submit _('Save changes'), class: 'btn gl-button btn-success mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' }
diff --git a/app/views/groups/settings/_pages_settings.html.haml b/app/views/groups/settings/_pages_settings.html.haml
index b6cf05d96ab..273714d4dcc 100644
--- a/app/views/groups/settings/_pages_settings.html.haml
+++ b/app/views/groups/settings/_pages_settings.html.haml
@@ -2,4 +2,4 @@
= render_if_exists 'shared/pages/max_pages_size_input', form: f
.gl-mt-3
- = f.submit s_('GitLabPages|Save'), class: 'btn btn-success'
+ = f.submit s_('GitLabPages|Save'), class: 'btn gl-button btn-success'
diff --git a/app/views/groups/settings/_permanent_deletion.html.haml b/app/views/groups/settings/_permanent_deletion.html.haml
index 14719200b45..8bd47fbea44 100644
--- a/app/views/groups/settings/_permanent_deletion.html.haml
+++ b/app/views/groups/settings/_permanent_deletion.html.haml
@@ -5,4 +5,4 @@
= _('Removing this group also removes all child projects, including archived projects, and their resources.')
%br
%strong= _('Removed group can not be restored!')
- = button_to _('Remove group'), '#', class: 'gl-button btn btn-danger js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(group) }
+ = button_to _('Remove group'), '#', class: 'btn gl-button btn-danger js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(group) }
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index 21d6a888d7b..6e2c28ba2e8 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -41,4 +41,4 @@
= render 'groups/settings/two_factor_auth', f: f, group: @group
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
= render_if_exists 'groups/member_lock_setting', f: f, group: @group
- = f.submit _('Save changes'), class: 'btn btn-success gl-mt-3 js-dirty-submit', data: { qa_selector: 'save_permissions_changes_button' }
+ = f.submit _('Save changes'), class: 'btn gl-button btn-success gl-mt-3 js-dirty-submit', data: { qa_selector: 'save_permissions_changes_button' }
diff --git a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
index 8f1ce11ce40..c18fe79be05 100644
--- a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
@@ -12,4 +12,4 @@
.form-text.text-muted
= s_('GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
= link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank'
- = f.submit _('Save changes'), class: 'btn btn-success gl-mt-5'
+ = f.submit _('Save changes'), class: 'btn gl-button btn-success gl-mt-5'
diff --git a/app/views/groups/settings/ci_cd/_form.html.haml b/app/views/groups/settings/ci_cd/_form.html.haml
index 8fad73f1249..eb61ecf5536 100644
--- a/app/views/groups/settings/ci_cd/_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_form.html.haml
@@ -4,10 +4,10 @@
= form_errors(group)
%fieldset.builds-feature
.form-group
- = f.label :max_artifacts_size, _('Maximum artifacts size (MB)'), class: 'label-bold'
+ = f.label :max_artifacts_size, _('Maximum artifacts size'), class: 'label-bold'
= f.number_field :max_artifacts_size, class: 'form-control'
%p.form-text.text-muted
- = _("Set the maximum file size for each job's artifacts")
+ = _("The maximum file size in megabytes for individual job artifacts.")
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank'
- = f.submit _('Save changes'), class: "btn btn-success"
+ = f.submit _('Save changes'), class: "btn gl-button btn-success"
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 4a0a92fa91f..1badb7b6ba1 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -32,7 +32,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
- = link_to s_('How do I configure runners?'), help_page_path('ci/runners/README')
+ = link_to s_('How do I configure runners?'), help_page_path('ci/runners/README'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'groups/runners/index'
diff --git a/app/views/groups/settings/packages_and_registries/index.html.haml b/app/views/groups/settings/packages_and_registries/index.html.haml
index 33719d56af1..1a12ad4902b 100644
--- a/app/views/groups/settings/packages_and_registries/index.html.haml
+++ b/app/views/groups/settings/packages_and_registries/index.html.haml
@@ -2,4 +2,4 @@
- page_title _('Packages & Registries')
- @content_class = 'limit-container-width' unless fluid_layout
-%section#js-packages-and-registries-settings
+%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s, group_path: @group.full_path } }
diff --git a/app/views/groups/settings/repository/_initial_branch_name.html.haml b/app/views/groups/settings/repository/_initial_branch_name.html.haml
index 3ef8dccae08..1881ec31b0c 100644
--- a/app/views/groups/settings/repository/_initial_branch_name.html.haml
+++ b/app/views/groups/settings/repository/_initial_branch_name.html.haml
@@ -19,4 +19,4 @@
= (_("Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used.") % { branch_name_default: fallback_branch_name }).html_safe
= f.hidden_field :redirect_target, value: "repository_settings"
- = f.submit _('Save changes'), class: 'gl-button btn-success'
+ = f.submit _('Save changes'), class: 'btn gl-button btn-success'
diff --git a/app/views/groups/show.atom.builder b/app/views/groups/show.atom.builder
index 0f67b15c301..5610746ad01 100644
--- a/app/views/groups/show.atom.builder
+++ b/app/views/groups/show.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.title "#{@group.name} activity"
xml.link href: group_url(@group, rss_url_options), rel: "self", type: "application/atom+xml"
xml.link href: group_url(@group), rel: "alternate", type: "text/html"
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 109e7c3831e..d1787d36cd2 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -16,6 +16,11 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
+= content_for :invite_members_sidebar do
+ - if can_invite_members_for_group?(@group)
+ %li
+ .js-invite-members-trigger{ data: { icon: 'plus', classes: 'gl-text-decoration-none! gl-shadow-none!', display_text: _('Invite team members') } }
+
= render partial: 'flash_messages'
= render_if_exists 'trials/banner', namespace: @group
@@ -26,7 +31,7 @@
= render_if_exists 'groups/group_activity_analytics', group: @group
-= render_if_exists 'groups/invite_members_modal', group: @group
+= render 'groups/invite_members_modal', group: @group
.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.top-area.group-nav-container.justify-content-between
diff --git a/app/views/groups/sidebar/_packages_settings.html.haml b/app/views/groups/sidebar/_packages_settings.html.haml
new file mode 100644
index 00000000000..87300ed39ed
--- /dev/null
+++ b/app/views/groups/sidebar/_packages_settings.html.haml
@@ -0,0 +1,5 @@
+- if group_packages_list_nav?
+ = nav_link(controller: :packages_and_registries) do
+ = link_to group_settings_packages_and_registries_path(@group), title: _('Packages & Registries') do
+ %span
+ = _('Packages & Registries')
diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml
deleted file mode 100644
index 6f917e81fb0..00000000000
--- a/app/views/help/_shortcuts.html.haml
+++ /dev/null
@@ -1,347 +0,0 @@
-#modal-shortcuts.modal{ tabindex: -1 }
- .modal-dialog.modal-lg.modal-1040
- .modal-content
- .modal-header
- .js-toggle-shortcuts
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
- .modal-body
- .row
- .col-lg-4
- %table.shortcut-mappings.text-2
- %tbody
- %tr
- %th
- %th= _('Global Shortcuts')
- %tr
- %td.shortcut
- %kbd ?
- %td= _('Toggle this dialog')
- %tr
- %td.shortcut
- %kbd shift p
- %td= _('Go to your projects')
- %tr
- %td.shortcut
- %kbd shift g
- %td= _('Go to your groups')
- %tr
- %td.shortcut
- %kbd shift a
- %td= _('Go to the activity feed')
- %tr
- %td.shortcut
- %kbd shift l
- %td= _('Go to the milestone list')
- %tr
- %td.shortcut
- %kbd shift s
- %td= _('Go to your snippets')
- %tr
- %td.shortcut
- %kbd s
- \/
- %kbd /
- %td= _('Start search')
- %tr
- %td.shortcut
- %kbd shift i
- %td= _('Go to your issues')
- %tr
- %td.shortcut
- %kbd shift m
- %td= _('Go to your merge requests')
- %tr
- %td.shortcut
- %kbd shift t
- %td= _('Go to your To-Do list')
- %tr
- %td.shortcut
- %kbd p
- %kbd b
- %td= _('Toggle the Performance Bar')
- %tbody
- %tr
- %th
- %th= _('Editing')
- %tr
- %td.shortcut
- - if browser.platform.mac?
- %kbd &#8984; shift p
- - else
- %kbd ctrl shift p
- %td= _('Toggle Markdown preview')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-up', size: 12)
- %td= _('Edit your most recent comment in a thread (from an empty textarea)')
- %tbody
- %tr
- %th
- %th= _('Wiki')
- %tr
- %td.shortcut
- %kbd e
- %td= _('Edit wiki page')
- %tbody
- %tr
- %th
- %th= _('Repository Graph')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-left', size: 12)
- \/
- %kbd h
- %td= _('Scroll left')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-right', size: 12)
- \/
- %kbd l
- %td= _('Scroll right')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-up', size: 12)
- \/
- %kbd k
- %td= _('Scroll up')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-down', size: 12)
- \/
- %kbd j
- %td= _('Scroll down')
- %tr
- %td.shortcut
- %kbd
- shift
- = sprite_icon('arrow-up', size: 12)
- \/ k
- %td= _('Scroll to top')
- %tr
- %td.shortcut
- %kbd
- shift
- = sprite_icon('arrow-down', size: 12)
- \/ j
- %td= _('Scroll to bottom')
- .col-lg-4
- %table.shortcut-mappings.text-2
- %tbody
- %tr
- %th
- %th= _('Project')
- %tr
- %td.shortcut
- %kbd g
- %kbd p
- %td= _('Go to the project\'s overview page')
- %tr
- %td.shortcut
- %kbd g
- %kbd v
- %td= _('Go to the project\'s activity feed')
- %tr
- %td.shortcut
- %kbd g
- %kbd r
- %td= _('Go to releases')
- %tr
- %td.shortcut
- %kbd g
- %kbd f
- %td= _('Go to files')
- %tr
- %td.shortcut
- %kbd t
- %td= _('Go to find file')
- %tr
- %td.shortcut
- %kbd g
- %kbd c
- %td= _('Go to commits')
- %tr
- %td.shortcut
- %kbd g
- %kbd n
- %td= _('Go to repository graph')
- %tr
- %td.shortcut
- %kbd g
- %kbd d
- %td= _('Go to repository charts')
- %tr
- %td.shortcut
- %kbd g
- %kbd i
- %td= _('Go to issues')
- %tr
- %td.shortcut
- %kbd i
- %td= _('New issue')
- %tr
- %td.shortcut
- %kbd g
- %kbd b
- %td= _('Go to issue boards')
- %tr
- %td.shortcut
- %kbd g
- %kbd m
- %td= _('Go to merge requests')
- %tr
- %td.shortcut
- %kbd g
- %kbd j
- %td= _('Go to jobs')
- %tr
- %td.shortcut
- %kbd g
- %kbd l
- %td= _('Go to metrics')
- %tr
- %td.shortcut
- %kbd g
- %kbd e
- %td= _('Go to environments')
- %tr
- %td.shortcut
- %kbd g
- %kbd k
- %td= _('Go to kubernetes')
- %tr
- %td.shortcut
- %kbd g
- %kbd s
- %td= _('Go to snippets')
- %tr
- %td.shortcut
- %kbd g
- %kbd w
- %td= _('Go to wiki')
- %tbody
- %tr
- %th
- %th= _('Project Files')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-up', size: 12)
- %td= _('Move selection up')
- %tr
- %td.shortcut
- %kbd
- = sprite_icon('arrow-down', size: 12)
- %td= _('Move selection down')
- %tr
- %td.shortcut
- %kbd enter
- %td= _('Open Selection')
- %tr
- %td.shortcut
- %kbd esc
- %td= _('Go back (while searching for files)')
- %tr
- %td.shortcut
- %kbd y
- %td= _('Go to file permalink (while viewing a file)')
- .col-lg-4
- %table.shortcut-mappings.text-2
- %tbody
- %tr
- %th
- %th= _('Epics, Issues, and Merge Requests')
- %tr
- %td.shortcut
- %kbd r
- %td= _('Comment/Reply (quoting selected text)')
- %tr
- %td.shortcut
- %kbd e
- %td= _('Edit description')
- %tr
- %td.shortcut
- %kbd l
- %td= _('Change label')
- %tbody
- %tr
- %th
- %th= _('Issues and Merge Requests')
- %tr
- %td.shortcut
- %kbd a
- %td= _('Change assignee')
- %tr
- %td.shortcut
- %kbd m
- %td= _('Change milestone')
- %tbody
- %tr
- %th
- %th= _('Merge Requests')
- %tr
- %td.shortcut
- %kbd ]
- \/
- %kbd j
- %td= _('Next file in diff')
- %tr
- %td.shortcut
- %kbd [
- \/
- %kbd k
- %td= _('Previous file in diff')
- %tr
- %td.shortcut
- - if browser.platform.mac?
- %kbd &#8984; p
- - else
- %kbd ctrl p
- %td= _('Go to file')
- %tr
- %td.shortcut
- %kbd n
- %td= _('Next unresolved discussion')
- %tr
- %td.shortcut
- %kbd p
- %td= _('Previous unresolved discussion')
- %tr
- %td.shortcut
- %kbd b
- %td= _('Copy source branch name')
- %tbody
- %tr
- %th
- %th= _('Merge Request Commits')
- %tr
- %td.shortcut
- %kbd c
- %td= _('Next commit')
- %tr
- %td.shortcut
- %kbd x
- %td= _('Previous commit')
- %tbody
- %tr
- %th
- %th= _('Web IDE')
- %tr
- %td.shortcut
- - if browser.platform.mac?
- %kbd &#8984; p
- - else
- %kbd ctrl p
- %td= _('Go to file')
- %tr
- %td.shortcut
- - if browser.platform.mac?
- %kbd &#8984; enter
- - else
- %kbd ctrl enter
- %td= _('Commit (when editing commit message)')
diff --git a/app/views/help/shortcuts.js.haml b/app/views/help/shortcuts.js.haml
deleted file mode 100644
index 99ed042ea3b..00000000000
--- a/app/views/help/shortcuts.js.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-:plain
- $("body").append("#{escape_javascript(render('shortcuts'))}");
- $("#modal-shortcuts").modal();
diff --git a/app/views/import/bulk_imports/status.html.haml b/app/views/import/bulk_imports/status.html.haml
index 6757c32d1e1..778bc1ef1a4 100644
--- a/app/views/import/bulk_imports/status.html.haml
+++ b/app/views/import/bulk_imports/status.html.haml
@@ -1,12 +1,12 @@
-- add_to_breadcrumbs 'New group', admin_users_path
+- add_to_breadcrumbs _('New group'), new_group_path
- add_page_specific_style 'page_bundles/import'
- breadcrumb_title _('Import groups')
%h1.gl-my-0.gl-py-4.gl-font-size-h1.gl-border-solid.gl-border-gray-200.gl-border-0.gl-border-b-1
= s_('BulkImport|Import groups from GitLab')
-%p.gl-my-0.gl-py-5.gl-border-solid.gl-border-gray-200.gl-border-0.gl-border-b-1
- = s_('BulkImport|Importing groups from %{link}').html_safe % { link: external_link(@source_url, @source_url) }
#import-groups-mount-element{ data: { status_path: status_import_bulk_imports_path(format: :json),
available_namespaces_path: import_available_namespaces_path(format: :json),
- create_bulk_import_path: import_bulk_imports_path(format: :json) } }
+ create_bulk_import_path: import_bulk_imports_path(format: :json),
+ jobs_path: realtime_changes_import_bulk_imports_path(format: :json),
+ source_url: @source_url } }
diff --git a/app/views/issues/_issue.atom.builder b/app/views/issues/_issue.atom.builder
index 94c32df7c60..e2ab360a3e4 100644
--- a/app/views/issues/_issue.atom.builder
+++ b/app/views/issues/_issue.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.entry do
xml.id project_issue_url(issue.project, issue)
xml.link href: project_issue_url(issue.project, issue)
diff --git a/app/views/issues/_issues_calendar.ics.ruby b/app/views/issues/_issues_calendar.ics.ruby
index 94c3099ace2..c21c4dac9f0 100644
--- a/app/views/issues/_issues_calendar.ics.ruby
+++ b/app/views/issues/_issues_calendar.ics.ruby
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
cal = Icalendar::Calendar.new
cal.prodid = '-//GitLab//NONSGML GitLab//EN'
cal.x_wr_calname = 'GitLab Issues'
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
index ed765f80b74..a549ed3540b 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -3,24 +3,24 @@
.jira-connect-user
- if current_user
- - user_link = link_to(current_user.to_reference, user_path(current_user), target: '_blank', rel: 'noopener noreferrer')
+ - user_link = link_to(current_user.to_reference, jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in')
= _('Signed in to GitLab as %{user_link}').html_safe % { user_link: user_link }
- elsif @subscriptions.present?
= link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
.jira-connect-app
- if current_user.blank? && @subscriptions.empty?
- %h1
- GitLab for Jira Configuration
- %h2.heading-with-border Sign in to GitLab.com to get started.
+ %h2= s_('JiraService|GitLab for Jira Configuration')
+ %p= s_('JiraService|Sign in to GitLab.com to get started.')
- .gl-mt-5
- = external_link _('Sign in to GitLab'), jira_connect_users_path, class: 'ak-button ak-button__appearance-primary js-jira-connect-sign-in'
+ .gl-mt-7
+ - sign_in_button_class = new_jira_connect_ui? ? 'btn gl-button btn-confirm' : 'ak-button ak-button__appearance-primary'
+ = external_link _('Sign in to GitLab'), jira_connect_users_path, class: "#{sign_in_button_class} js-jira-connect-sign-in"
- .gl-mt-5
+ .gl-mt-7
%p Note: this integration only works with accounts on GitLab.com (SaaS).
- else
- .js-jira-connect-app{ data: jira_connect_app_data }
+ .js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
- unless new_jira_connect_ui?
%form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
@@ -34,7 +34,7 @@
Link namespace to Jira
- if @subscriptions.present?
- %table.subscriptions
+ %table.subscriptions.gl-w-full
%thead
%tr
%th Namespace
@@ -45,7 +45,7 @@
%tr
%td= subscription.namespace.full_path
%td= subscription.created_at
- %td= link_to 'Remove', jira_connect_subscription_path(subscription), class: 'remove-subscription'
+ %td= link_to 'Remove', jira_connect_subscription_path(subscription), class: 'js-jira-connect-remove-subscription'
- else
%h4.empty-subscriptions
No linked namespaces
@@ -55,10 +55,8 @@
%strong Browser limitations:
Adding a namespace currently works only in browsers that allow cross‑site cookies. Please make sure to use
%a{ href: 'https://www.mozilla.org/en-US/firefox/', target: '_blank', rel: 'noopener noreferrer' } Firefox
- or
- %a{ href: 'https://www.google.com/chrome/index.html', target: '_blank', rel: 'noopener noreferrer' } Google Chrome
or enable cross‑site cookies in your browser when adding a namespace.
- %a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more
+ = 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/_head.html.haml b/app/views/layouts/_head.html.haml
index 7aa57331c51..8b430f579e9 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -79,6 +79,9 @@
= favicon_link_tag 'touch-icon-ipad-retina.png', rel: 'apple-touch-icon', sizes: '152x152'
%link{ rel: 'mask-icon', href: image_path('logo.svg'), color: 'rgb(226, 67, 41)' }
+ -# OpenSearch
+ %link{ href: search_opensearch_path(format: :xml), rel: 'search', title: 'Search GitLab', type: 'application/opensearchdescription+xml' }
+
-# Windows 8 pinned site tile
%meta{ name: 'msapplication-TileImage', content: image_path('msapplication-tile.png') }
%meta{ name: 'msapplication-TileColor', content: '#30353E' }
diff --git a/app/views/layouts/_matomo.html.haml b/app/views/layouts/_matomo.html.haml
index fcd3156a162..81721baba64 100644
--- a/app/views/layouts/_matomo.html.haml
+++ b/app/views/layouts/_matomo.html.haml
@@ -4,6 +4,7 @@
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
+ #{extra_config.matomo_disable_cookies ? '_paq.push(["disableCookies"])' : ""};
(function() {
var u="//#{extra_config.matomo_url}/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index c552454caa7..1f2fcd1c70b 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -22,6 +22,7 @@
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
- .content{ id: "content-body", **page_itemtype }
+ %main.content{ id: "content-body", **page_itemtype }
= render "layouts/flash", extra_flash_class: 'limit-container-width'
+ = yield :before_content
= yield
diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml
index 35b91c8d35e..7d3cfe28007 100644
--- a/app/views/layouts/_startup_css.haml
+++ b/app/views/layouts/_startup_css.haml
@@ -1,5 +1,5 @@
- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general'
-%style{ type: "text/css" }
+%style
= Rails.application.assets_manifest.find_sources("themes/#{user_application_theme_css_filename}.css").first.to_s.html_safe if user_application_theme_css_filename
= Rails.application.assets_manifest.find_sources("startup/startup-#{startup_filename}.css").first.to_s.html_safe
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index 31259b8ac25..85fff22a3b7 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -3,4 +3,9 @@
- nav "admin"
- @left_sidebar = true
+-# This active_nav_link check is also used in `app/views/layouts/nav/sidebar/_admin.html.haml`
+- is_application_settings = active_nav_link?(controller: [:application_settings, :integrations])
+
+- enable_search_settings if is_application_settings
+
= render template: "layouts/application"
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index d7ca93a296b..5ac0db4137f 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -2,18 +2,12 @@
%ul
%li.current-user
- .user-name.gl-font-weight-bold
- = current_user.name
- - if current_user&.status && user_status_set_to_busy?(current_user.status)
- %span.gl-font-weight-normal.gl-text-gray-500= s_("UserProfile|(Busy)")
- = current_user.to_reference
- - if current_user.status
- .user-status.d-flex.align-items-center.gl-mt-2.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
- - if show_status_emoji?(current_user.status)
- .user-status-emoji.d-flex.align-items-center
- = emoji_icon current_user.status.emoji
- %span.user-status-message.str-truncated
- = current_user.status.message_html.html_safe
+ - if current_user_menu?(:profile)
+ = link_to current_user, class: 'gl-line-height-20!', data: { user: current_user.username, testid: 'user-profile-link' } do
+ = render 'layouts/header/current_user_dropdown_item'
+ - else
+ .gl-py-3.gl-px-4
+ = render 'layouts/header/current_user_dropdown_item'
%li.divider
- if can?(current_user, :update_user_status, current_user)
%li
@@ -22,17 +16,16 @@
= s_('SetStatusModal|Edit status')
- else
= s_('SetStatusModal|Set status')
- - if current_user_menu?(:profile)
- %li
- = link_to s_("CurrentUser|Profile"), current_user, class: 'profile-link', data: { user: current_user.username }
- if current_user_menu?(:start_trial)
%li
%a.trial-link{ href: trials_link_url }
- = s_("CurrentUser|Start a Gold trial")
+ = s_("CurrentUser|Start an Ultimate trial")
= emoji_icon('rocket')
- if current_user_menu?(:settings)
%li
- = link_to s_("CurrentUser|Settings"), profile_path, data: { qa_selector: 'settings_link' }
+ = link_to s_("CurrentUser|Edit profile"), profile_path, data: { qa_selector: 'edit_profile_link' }
+ %li
+ = link_to s_("CurrentUser|Preferences"), profile_preferences_path
= render_if_exists 'layouts/header/buy_pipeline_minutes', project: @project, namespace: @group
= render_if_exists 'layouts/header/upgrade'
diff --git a/app/views/layouts/header/_current_user_dropdown_item.html.haml b/app/views/layouts/header/_current_user_dropdown_item.html.haml
new file mode 100644
index 00000000000..06c597b4932
--- /dev/null
+++ b/app/views/layouts/header/_current_user_dropdown_item.html.haml
@@ -0,0 +1,12 @@
+.gl-font-weight-bold
+ = current_user.name
+ - if current_user&.status && user_status_set_to_busy?(current_user.status)
+ %span.gl-font-weight-normal.gl-text-gray-500= s_("UserProfile|(Busy)")
+= current_user.to_reference
+- if current_user.status
+ .user-status.d-flex.align-items-center.gl-mt-2.gl-mr-0.gl-font-sm.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
+ - if show_status_emoji?(current_user.status)
+ .user-status-emoji.d-flex.align-items-center
+ = emoji_icon current_user.status.emoji
+ %span.user-status-message.str-truncated
+ = current_user.status.message_html.html_safe
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index f7e93182ca2..c54ad23c094 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -15,7 +15,7 @@
%span.logo-text.d-none.d-lg-block.gl-ml-3
= logo_text
- if Gitlab.com_and_canary?
- = link_to 'https://next.gitlab.com', class: 'canary-badge bg-transparent', target: :_blank do
+ = link_to 'https://next.gitlab.com', class: 'canary-badge bg-transparent', target: :_blank, rel: :_noopener do
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
@@ -47,11 +47,10 @@
%span.badge.badge-pill.issues-count.green-badge{ class: ('hidden' if issues_count == 0) }
= number_with_delimiter(issues_count)
- if header_link?(:merge_requests)
- - reviewers_enabled = merge_request_reviewers_enabled?
- = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter #{reviewers_enabled ? 'dropdown' : ''}" }) do
+ = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter dropdown" }) do
= link_to assigned_mrs_dashboard_path, class: 'dashboard-shortcuts-merge_requests', title: _('Merge requests'), aria: { label: _('Merge requests') },
data: { qa_selector: 'merge_requests_shortcut_button',
- toggle: reviewers_enabled ? "dropdown" : "tooltip",
+ toggle: "dropdown",
placement: 'bottom',
track_label: 'main_navigation',
track_event: 'click_merge_link',
@@ -60,23 +59,21 @@
= sprite_icon('git-merge')
%span.badge.badge-pill.merge-requests-count.js-merge-requests-count{ class: ('hidden' if user_merge_requests_counts[:total] == 0) }
= number_with_delimiter(user_merge_requests_counts[:total])
- - if reviewers_enabled
- = sprite_icon('chevron-down', css_class: 'caret-down gl-mx-0!')
- - if reviewers_enabled
- .dropdown-menu.dropdown-menu-right
- %ul
- %li.dropdown-header
- = _('Merge requests')
- %li
- = link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center' do
- = _('Assigned to you')
- %span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-assigned-mr-count{ class: "" }
- = user_merge_requests_counts[:assigned]
- %li
- = link_to reviewer_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center' do
- = _('Review requests for you')
- %span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-reviewer-mr-count{ class: "" }
- = user_merge_requests_counts[:review_requested]
+ = sprite_icon('chevron-down', css_class: 'caret-down gl-mx-0!')
+ .dropdown-menu.dropdown-menu-right
+ %ul
+ %li.dropdown-header
+ = _('Merge requests')
+ %li
+ = link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center' do
+ = _('Assigned to you')
+ %span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-assigned-mr-count{ class: "" }
+ = user_merge_requests_counts[:assigned]
+ %li
+ = link_to reviewer_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center' do
+ = _('Review requests for you')
+ %span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-reviewer-mr-count{ class: "" }
+ = user_merge_requests_counts[:review_requested]
- if header_link?(:todos)
= nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
= link_to dashboard_todos_path, title: _('To-Do List'), aria: { label: _('To-Do List') }, class: 'shortcuts-todos',
@@ -120,8 +117,7 @@
= sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
-- if ::Feature.enabled?(:whats_new_drawer, current_user)
- #whats-new-app{ data: { storage_key: whats_new_storage_key, versions: whats_new_versions, gitlab_dot_com: Gitlab.dev_env_org_or_com? } }
+#whats-new-app{ data: { storage_key: whats_new_storage_key, versions: whats_new_versions, gitlab_dot_com: Gitlab.dev_env_org_or_com? } }
- if can?(current_user, :update_user_status, current_user)
.js-set-status-modal-wrapper{ data: user_status_data }
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index 40bf45db80d..c3769dd2993 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -1,6 +1,6 @@
%ul
- if current_user_menu?(:help)
- = render_if_exists 'layouts/header/whats_new_dropdown_item'
+ = render 'layouts/header/whats_new_dropdown_item'
%li
= link_to _("Help"), help_path
%li
diff --git a/app/views/layouts/header/_whats_new_dropdown_item.html.haml b/app/views/layouts/header/_whats_new_dropdown_item.html.haml
new file mode 100644
index 00000000000..f79b741ced0
--- /dev/null
+++ b/app/views/layouts/header/_whats_new_dropdown_item.html.haml
@@ -0,0 +1,5 @@
+%li
+ %button.gl-justify-content-space-between.gl-align-items-center.js-whats-new-trigger{ type: 'button', data: { storage_key: whats_new_storage_key }, class: 'gl-display-flex!' }
+ = _("What's new")
+ %span.js-whats-new-notification-count.whats-new-notification-count
+ = whats_new_most_recent_release_items_count
diff --git a/app/views/layouts/jira_connect.html.haml b/app/views/layouts/jira_connect.html.haml
index d996b3387a3..da45d84a83b 100644
--- a/app/views/layouts/jira_connect.html.haml
+++ b/app/views/layouts/jira_connect.html.haml
@@ -9,7 +9,6 @@
= yield :page_specific_styles
= javascript_include_tag 'https://connect-cdn.atl-paas.net/all.js'
- = javascript_include_tag 'https://unpkg.com/jquery@3.3.1/dist/jquery.min.js'
= Gon::Base.render_data(nonce: content_security_policy_nonce)
= yield :head
%body
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index dd2c5e2a19e..aeeffb6f4b6 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -3,7 +3,7 @@
- unless @skip_current_level_breadcrumb
- push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
-%nav.breadcrumbs{ role: "navigation", class: [container, @content_class] }
+%nav.breadcrumbs{ class: [container, @content_class], 'aria-label': _('Breadcrumbs') }
.breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border) }
- if defined?(@left_sidebar)
= button_tag class: 'toggle-mobile-nav', type: 'button' do
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index da16be707eb..f887d335807 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,4 +1,4 @@
-.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
+%aside.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation') }
.nav-sidebar-inner-scroll
.context-header
= link_to admin_root_path, title: _('Admin Overview') do
@@ -65,10 +65,6 @@
= link_to admin_dev_ops_report_path, title: _('DevOps Report') do
%span
= _('DevOps Report')
- = nav_link(controller: :cohorts) do
- = link_to admin_cohorts_path, title: _('Cohorts') do
- %span
- = _('Cohorts')
- if Feature.enabled?(:instance_statistics, default_enabled: true)
= nav_link(controller: :instance_statistics) do
= link_to admin_instance_statistics_path, title: _('Usage Trends') do
@@ -251,6 +247,7 @@
= _('Settings')
%ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_settings_submenu_content' } }
+ -# This active_nav_link check is also used in `app/views/layouts/admin.html.haml`
= nav_link(controller: [:application_settings, :integrations], html_options: { class: "fly-out-top-item" } ) do
= link_to general_admin_application_settings_path do
%strong.fly-out-top-item-name
@@ -260,6 +257,9 @@
= link_to general_admin_application_settings_path, title: _('General'), class: 'qa-admin-settings-general-item' do
%span
= _('General')
+
+ = render_if_exists 'layouts/nav/sidebar/advanced_search', class: 'qa-admin-settings-advanced-search'
+
- if instance_level_integrations?
= nav_link(path: ['application_settings#integrations', 'integrations#edit']) do
= link_to integrations_admin_application_settings_path, title: _('Integrations'), data: { qa_selector: 'integration_settings_link' } do
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 473a0d131b8..e99b2f443be 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1,7 +1,9 @@
-- issues_count = group_issues_count(state: 'opened')
+- issues_count = group_open_issues_count(@group)
- merge_requests_count = group_merge_requests_count(state: 'opened')
+- aside_title = @group.subgroup? ? _('Subgroup navigation') : _('Group navigation')
+- overview_title = @group.subgroup? ? _('Subgroup overview') : _('Group overview')
-.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation') }
+%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation'), 'aria-label': aside_title }
.nav-sidebar-inner-scroll
.context-header
= link_to group_path(@group), title: @group.name do
@@ -19,19 +21,13 @@
.nav-icon-container
= sprite_icon('home')
%span.nav-item-name
- - if @group.subgroup?
- = _('Subgroup overview')
- - else
- = _('Group overview')
+ = overview_title
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#show', 'groups#details', 'groups#activity', 'groups#subgroups'], html_options: { class: "fly-out-top-item" } ) do
= link_to group_path(@group) do
%strong.fly-out-top-item-name
- - if @group.subgroup?
- = _('Subgroup overview')
- - else
- = _('Group overview')
+ = overview_title
%li.divider.fly-out-top-item
= nav_link(path: ['groups#show', 'groups#details', 'groups#subgroups'], html_options: { class: 'home' }) do
@@ -54,14 +50,14 @@
= sprite_icon('issues')
%span.nav-item-name
= _('Issues')
- %span.badge.badge-pill.count= number_with_delimiter(issues_count)
+ %span.badge.badge-pill.count= issues_count
%ul.sidebar-sub-level-items{ data: { qa_selector: 'group_issues_sidebar_submenu'} }
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index', 'iterations#index'], html_options: { class: "fly-out-top-item" } ) do
= link_to issues_group_path(@group) do
%strong.fly-out-top-item-name
= _('Issues')
- %span.badge.badge-pill.count.issue_counter.fly-out-badge= number_with_delimiter(issues_count)
+ %span.badge.badge-pill.count.issue_counter.fly-out-badge= issues_count
%li.divider.fly-out-top-item
= nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
@@ -121,7 +117,7 @@
%strong.fly-out-top-item-name
= _('Kubernetes')
- = render_if_exists 'groups/sidebar/packages'
+ = render 'groups/sidebar/packages'
= render 'layouts/nav/sidebar/analytics_links', links: group_analytics_navbar_links(@group, current_user)
@@ -141,7 +137,7 @@
%strong.fly-out-top-item-name
= _('Members')
- = render_if_exists 'groups/invite_members_side_nav_link', group: @group
+ = content_for :invite_members_sidebar
- if group_sidebar_link?(:settings)
= nav_link(path: group_settings_nav_link_paths) do
@@ -181,11 +177,7 @@
%span
= _('CI / CD')
- - if Feature.enabled?(:packages_and_registries_group_settings, @group)
- = nav_link(controller: :packages_and_registries) do
- = link_to group_settings_packages_and_registries_path(@group), title: _('Packages & Registries') do
- %span
- = _('Packages & Registries')
+ = render 'groups/sidebar/packages_settings'
= render_if_exists "groups/ee/settings_nav"
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index dadab554c02..a66110f28e8 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -1,4 +1,4 @@
-.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('user_side_navigation', 'render', 'user_side_navigation') }
+%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('user_side_navigation', 'render', 'user_side_navigation'), 'aria-label': _('User settings') }
.nav-sidebar-inner-scroll
.context-header
= link_to profile_path, title: _('Profile Settings') do
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index e02b8333c60..8bb009bfd17 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -1,4 +1,4 @@
-.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation') }
+%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation'), 'aria-label': _('Project navigation') }
.nav-sidebar-inner-scroll
.context-header
= link_to project_path(@project), title: @project.name do
@@ -33,6 +33,13 @@
= link_to project_releases_path(@project), title: _('Releases'), class: 'shortcuts-project-releases' do
%span= _('Releases')
+ - if project_nav_tab? :learn_gitlab
+ = nav_link(controller: :learn_gitlab, html_options: { class: 'home' }) do
+ = link_to project_learn_gitlab_path(@project) do
+ .nav-icon-container
+ = sprite_icon('home')
+ %span.nav-item-name
+ = _('Learn GitLab')
- if project_nav_tab? :files
= nav_link(controller: sidebar_repository_paths, unless: -> { current_path?('projects/graphs#charts') }) do
@@ -212,7 +219,8 @@
= render_if_exists "layouts/nav/test_cases_link", project: @project
- = render_if_exists 'layouts/nav/sidebar/project_security_link' # EE-specific
+ - if project_nav_tab? :security_and_compliance
+ = render_if_exists 'layouts/nav/sidebar/project_security_link' # EE-specific
- if project_nav_tab? :operations
= nav_link(controller: sidebar_operations_paths) do
@@ -283,27 +291,14 @@
%span
= _('Kubernetes')
- if show_cluster_hint
- .feature-highlight.js-feature-highlight{ disabled: true,
+ .js-feature-highlight{ disabled: true,
data: { trigger: 'manual',
container: 'body',
placement: 'right',
highlight: UserCalloutsHelper::GKE_CLUSTER_INTEGRATION,
highlight_priority: UserCallout.feature_names[:GKE_CLUSTER_INTEGRATION],
- dismiss_endpoint: user_callouts_path } }
- - if show_cluster_hint
- .feature-highlight-popover-content
- = image_tag 'illustrations/cluster_popover.svg', class: 'feature-highlight-illustration', lazy: false, alt: _('Kubernetes popover')
- .feature-highlight-popover-sub-content
- %p= _('Allows you to add and manage Kubernetes clusters.')
- %p
- = _('Protip:')
- = link_to _('Auto DevOps'), help_page_path('topics/autodevops/index.md')
- %span= _('uses Kubernetes clusters to deploy your code!')
- %hr
- %button.gl-button.btn.btn-success.btn-sm.dismiss-feature-highlight{ type: 'button' }
- %span.gl-mr-2= _("Got it!")
- = sprite_icon('thumb-up')
-
+ dismiss_endpoint: user_callouts_path,
+ auto_devops_help_path: help_page_path('topics/autodevops/index.md') } }
- if project_nav_tab? :environments
= nav_link(controller: :environments, action: [:index, :folder, :show, :new, :edit, :create, :update, :stop, :terminal]) do
= link_to project_environments_path(@project), title: _('Environments'), class: 'shortcuts-environments qa-operations-environments-link' do
@@ -383,7 +378,7 @@
%strong.fly-out-top-item-name
= _('Members')
- = render_if_exists 'projects/invite_members_side_nav_link', project: @project
+ = content_for :invite_members_sidebar
- if project_nav_tab? :settings
= nav_link(path: sidebar_settings_paths) do
@@ -438,8 +433,6 @@
%span
= _('Pages')
- = render 'shared/sidebar_toggle_button'
-
-# Shortcut to Project > Activity
%li.hidden
= link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
@@ -474,3 +467,5 @@
- if project_nav_tab?(:issues)
%li.hidden
= link_to _('Issue Boards'), project_boards_path(@project), title: _('Issue Boards'), class: 'shortcuts-issue-boards'
+
+ = render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/sidebar/_project_security_link.html.haml b/app/views/layouts/nav/sidebar/_project_security_link.html.haml
new file mode 100644
index 00000000000..426845639e3
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_project_security_link.html.haml
@@ -0,0 +1,21 @@
+- top_level_link = project_security_configuration_path(@project)
+- top_level_qa_selector = 'security_configuration_link'
+- if any_project_nav_tab?([:security_configuration])
+ = nav_link(path: sidebar_security_paths) do
+ = link_to top_level_link, data: { qa_selector: top_level_qa_selector } do
+ .nav-icon-container
+ = sprite_icon('shield')
+ %span.nav-item-name
+ = _('Security & Compliance')
+
+ %ul.sidebar-sub-level-items
+ = nav_link(path: sidebar_security_paths, html_options: { class: "fly-out-top-item" } ) do
+ = link_to top_level_link do
+ %strong.fly-out-top-item-name
+ = _('Security & Compliance')
+
+ %li.divider.fly-out-top-item
+ - if project_nav_tab?(:security_configuration)
+ = nav_link(path: sidebar_security_configuration_paths) do
+ = link_to project_security_configuration_path(@project), title: _('Configuration'), data: { qa_selector: 'security_configuration_link'} do
+ %span= _('Configuration')
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 7aca64663e0..17153e72e6e 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -4,4 +4,5 @@
- nav "profile"
- @left_sidebar = true
+- enable_search_settings locals: { container_class: 'gl-my-5' }
= render template: "layouts/application"
diff --git a/app/views/layouts/devise_experimental_onboarding_issues.html.haml b/app/views/layouts/signup_onboarding.html.haml
index f768fba84ca..f768fba84ca 100644
--- a/app/views/layouts/devise_experimental_onboarding_issues.html.haml
+++ b/app/views/layouts/signup_onboarding.html.haml
diff --git a/app/views/layouts/welcome.html.haml b/app/views/layouts/welcome.html.haml
index 48921e9ff89..944f524d692 100644
--- a/app/views/layouts/welcome.html.haml
+++ b/app/views/layouts/welcome.html.haml
@@ -1,8 +1,8 @@
!!! 5
%html.subscriptions-layout-html{ lang: 'en' }
= render 'layouts/head'
- %body.ui-indigo.d-flex.vh-100.gl-bg-gray-10
+ %body.ui-indigo.gl-display-flex.vh-100
= render "layouts/header/logo_with_title"
= render "layouts/broadcast"
- .container.d-flex.flex-grow-1.m-0
+ .container.gl-display-flex.gl-flex-grow-1
= yield
diff --git a/app/views/layouts/xml.atom.builder b/app/views/layouts/xml.atom.builder
index 4ee09cb87a1..7144b6305a2 100644
--- a/app/views/layouts/xml.atom.builder
+++ b/app/views/layouts/xml.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.instruct!
xml.feed 'xmlns' => 'http://www.w3.org/2005/Atom', 'xmlns:media' => 'http://search.yahoo.com/mrss/' do
xml << yield
diff --git a/app/views/notify/in_product_marketing_email.html.haml b/app/views/notify/in_product_marketing_email.html.haml
new file mode 100644
index 00000000000..be517516a98
--- /dev/null
+++ b/app/views/notify/in_product_marketing_email.html.haml
@@ -0,0 +1,204 @@
+!!!
+%html{ lang: "en" }
+ %head
+ %meta{ content: "text/html; charset=utf-8", "http-equiv" => "Content-Type" }
+ %meta{ content: "width=device-width, initial-scale=1", name: "viewport" }
+ %link{ href: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600", rel: "stylesheet", type: "text/css" }
+ %title= message.subject
+ :css
+ /* CLIENT-SPECIFIC STYLES */
+ body,
+ table,
+ td,
+ a {
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+ }
+
+ table,
+ td {
+ mso-table-lspace: 0pt;
+ mso-table-rspace: 0pt;
+ }
+
+ img {
+ -ms-interpolation-mode: bicubic;
+ }
+
+ /* RESET STYLES */
+ img {
+ border: 0;
+ height: auto;
+ line-height: 100%;
+ outline: none;
+ text-decoration: none;
+ }
+
+ table {
+ border-collapse: collapse !important;
+ }
+
+ body {
+ height: 100% !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ width: 100% !important;
+ background-color: #ffffff;
+ color: #424242;
+ }
+
+ a {
+ color: #6b4fbb;
+ text-decoration: underline;
+ }
+
+ .cta_link a {
+ font-size: 24px;
+ font-family: 'Source Sans Pro', helvetica, arial, sans-serif;
+ color: #ffffff;
+ text-decoration: none;
+ border-radius: 5px;
+ -webkit-border-radius: 5px;
+ background-color: #6e49cb;
+ border-top: 15px solid #6e49cb;
+ border-bottom: 15px solid #6e49cb;
+ border-right: 40px solid #6e49cb;
+ border-left: 40px solid #6e49cb;
+ display: inline-block;
+ }
+
+ .footernav {
+ display: inline !important;
+ }
+
+ .footernav a {
+ color: #6e49cb;
+ }
+
+ .address {
+ margin: 0;
+ font-size: 16px;
+ line-height: 26px;
+ }
+
+ :css
+ /* iOS BLUE LINKS */
+ a[x-apple-data-detectors] {
+ color: inherit !important;
+ text-decoration: none !important;
+ font-size: inherit !important;
+ font-family: inherit !important;
+ font-weight: inherit !important;
+ line-height: inherit !important;
+ }
+ /[if gte mso 9]
+ <xml>
+ <o:OfficeDocumentSettings>
+ <o:AllowPNG/>
+ <o:PixelsPerInch>96</o:PixelsPerInch>
+ </o:OfficeDocumentSettings>
+ </xml>
+ /[if (mso)|(mso 16)]
+ <style type="text/css">
+ body, table, td, a, span { font-family: Arial, Helvetica, sans-serif !important; }
+ </style>
+ :css
+ @media only screen and (max-width: 595px) {
+
+ .wrapper {
+ width: 100% !important;
+ margin: 0 auto !important;
+ padding: 0 !important;
+ }
+
+ p,
+ li {
+ font-size: 18px !important;
+ line-height: 26px !important;
+ }
+
+ .stack {
+ width: 100% !important;
+ }
+
+ .stack-mobile-padding {
+ width: 100% !important;
+ margin-top: 20px !important;
+ }
+
+ .callout {
+ padding-bottom: 20px !important;
+ }
+
+ .redbutton {
+ text-align: center;
+ }
+
+ .stack33 {
+ display: block !important;
+ width: 100% !important;
+ max-width: 100% !important;
+ direction: ltr !important;
+ text-align: center !important;
+ }
+ }
+
+ @media only screen and (max-width: 480px) {
+ u~div {
+ width: 100vw !important;
+ }
+
+ div>u~div {
+ width: 100% !important;
+ }
+ }
+ %body#body{ width: "100%" }
+ %table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
+ %tr
+ %td{ align: "center", style: "padding: 0px;" }
+ %table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "600" }
+ %tr
+ %td{ style: "padding: 0px;" }
+ #main-story.mktEditable{ mktoname: "main-story" }
+ %table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
+ %tr
+ %td{ align: "left", style: "padding: 0 20px;" }
+ = about_link('mailers/in_product_marketing', 'gitlab-logo-gray-rgb.png', 200)
+ %tr
+ %td{ "aria-hidden" => "true", height: "30", style: "font-size: 0; line-height: 0;" }
+ %tr
+ %td{ bgcolor: "#ffffff", height: "auto", style: "max-width: 600px; width: 100%; text-align: center; height: 200px; padding: 25px 15px; mso-line-height-rule: exactly; min-height: 40px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;", valign: "middle", width: "100%" }
+ = in_product_marketing_logo(@track, @series)
+ %h1{ style: "font-size: 40px; line-height: 46x; color: #000000; padding: 20px 0 0 0; font-weight: normal;" }
+ = in_product_marketing_title(@track, @series)
+ %h2{ style: "font-size: 28px; line-height: 34px; color: #000000; padding: 0; font-weight: 400;" }
+ = in_product_marketing_subtitle(@track, @series)
+ %tr
+ %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
+ %p{ style: "margin: 0 0 20px 0;" }
+ = in_product_marketing_body_line1(@track, @series, format: :html).html_safe
+ %p{ style: "margin: 0 0 20px 0;" }
+ = in_product_marketing_body_line2(@track, @series, format: :html).html_safe
+ %tr
+ %td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ .cta_link= cta_link(@track, @series, @group, format: :html)
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ style: "color: #424242; padding: 10px 30px; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;font-size: 16px; line-height: 22px; border: 1px solid #dddddd" }
+ %p
+ = in_product_marketing_progress(@track, @series)
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "center", style: "padding:75px 20px 25px;" }
+ = about_link('', 'gitlab_logo.png', 80)
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "center", style: "padding:0px ;" }
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "center", style: "padding:0px 10px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; " }
+ %span.footernav{ style: "color: #6e49cb; font-size: 16px; line-height: 26px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ = footer_links(format: :html).join('&nbsp;' * 3 + '|' + '&nbsp;' * 4).html_safe
+ %tr{ style: "background-color:#ffffff;" }
+ %td{ align: "center", style: "padding: 40px 30px 20px 30px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ .address= address(format: :html)
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "left", style: "padding:20px 30px 20px 30px;" }
+ %span.footernav{ style: "color: #6e49cb; font-size: 14px; line-height: 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#424242;" }
+ = unsubscribe(format: :html).html_safe
diff --git a/app/views/notify/in_product_marketing_email.text.erb b/app/views/notify/in_product_marketing_email.text.erb
new file mode 100644
index 00000000000..ecc4c565b73
--- /dev/null
+++ b/app/views/notify/in_product_marketing_email.text.erb
@@ -0,0 +1,23 @@
+<%= in_product_marketing_tagline(@track, @series) %>
+
+<%= in_product_marketing_title(@track, @series) %>
+<%= in_product_marketing_subtitle(@track, @series) %>
+
+
+<%= in_product_marketing_body_line1(@track, @series) %>
+
+<%= in_product_marketing_body_line2(@track, @series) %>
+
+<%= cta_link(@track, @series, @group) %>
+
+
+
+
+
+
+
+<%= footer_links %>
+
+<%= address %>
+
+<%= unsubscribe %>
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index 5ff1e2393c9..f7dc1fa662c 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -1,12 +1,40 @@
- placeholders = { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, br_tag: '<br/>'.html_safe, role: member.human_access.downcase }
-%tr
- %td.text-content
- %h2.invite-header
- = s_('InviteEmail|You are invited!')
- %p
- - if member.created_by
- = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
- - else
- = html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
- %p.invite-actions
- = link_to s_('InviteEmail|Join now'), invite_url(@token), class: 'invite-btn-join'
+
+- experiment('members/invite_email', actor: member) do |experiment_instance|
+ - experiment_instance.use do
+ %tr
+ %td.text-content
+ %h2.invite-header
+ = s_('InviteEmail|You are invited!')
+ %p
+ - if member.created_by
+ = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
+ - else
+ = html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
+ %p.invite-actions
+ = link_to s_('InviteEmail|Join now'), invite_url(@token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE), class: 'invite-btn-join'
+ - experiment_instance.try(:avatar) do
+ %tr
+ %td.text-content
+ %img.mail-avatar{ height: "60", src: avatar_icon_for_user(member.created_by, 60, only_path: false), width: "60", alt: "" }
+ %p
+ = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
+ %p.invite-actions
+ = link_to s_('InviteEmail|Join now'), invite_url(@token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE), class: 'invite-btn-join'
+ - experiment_instance.try(:permission_info) do
+ %tr
+ %td.text-content{ colspan: 2 }
+ %img.mail-avatar{ height: "60", src: avatar_icon_for_user(member.created_by, 60, only_path: false), width: "60", alt: "" }
+ %p
+ = html_escape(s_("InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} with the %{role} permission level.")) % placeholders.merge({ inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe })
+ %p.invite-actions
+ = link_to s_('InviteEmail|Join now'), invite_url(@token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE), class: 'invite-btn-join'
+ %tr.border-top
+ %td.text-content.half-width
+ %h4
+ = s_('InviteEmail|What is a GitLab %{project_or_group}?') % { project_or_group: member_source.model_name.singular }
+ %p= invited_to_description(member_source.model_name.singular)
+ %td.text-content.half-width
+ %h4
+ = s_('InviteEmail|What can I do with the %{role} permission level?') % { role: member.human_access.downcase }
+ %p= invited_role_description(member.human_access)
diff --git a/app/views/notify/provisioned_member_access_granted_email.erb b/app/views/notify/provisioned_member_access_granted_email.erb
deleted file mode 100644
index 485ee5a5242..00000000000
--- a/app/views/notify/provisioned_member_access_granted_email.erb
+++ /dev/null
@@ -1,14 +0,0 @@
-<% source_link = member_source.web_url %>
-
-<%= _('An Enterprise User GitLab account has been created for you by your organization:') %>
-<%= _('Username: %{username}') % { username: @user.username } %>
-<%= _('Email: %{email}') % { email: @user.email } %>
-<%= _('GitLab group: %{source_link}').html_safe % { source_link: source_link } %>
-
-
-<%= _('By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. ') %>
-<%= _('To ensure no loss of personal content, an Individual User should create a separate account under their own personal email address, not tied to the Enterprise email domain or name-space.') %>
-<%- unless @user.confirmed? %>
- <%= _('To get started, click the link below to confirm your account.') %>
- <%= confirmation_url(@user, confirmation_token: @user.confirmation_token) %>
-<%- end %>
diff --git a/app/views/notify/provisioned_member_access_granted_email.haml b/app/views/notify/provisioned_member_access_granted_email.haml
deleted file mode 100644
index 2f2fd33145a..00000000000
--- a/app/views/notify/provisioned_member_access_granted_email.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- source_link = link_to(member_source.human_name, member_source.web_url, target: '_blank', rel: 'noopener noreferrer', class: :highlight)
-- confirmation_link = confirmation_url(@user, confirmation_token: @user.confirmation_token)
-
-%tr
- %td.text-content
- %p
- = _('An Enterprise User GitLab account has been created for you by your organization:')
- %p
- = _('Username: %{username}') % { username: @user.username }
- %br
- = _('Email: %{email}') % { email: @user.email }
- %br
- = _('GitLab group: %{source_link}').html_safe % { source_link: source_link }
-
-%tr
- %td.text-content
- %p
- = _('By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. ')
- = _('To ensure no loss of personal content, an Individual User should create a separate account under their own personal email address, not tied to the Enterprise email domain or name-space.')
- - unless @user.confirmed?
- %p
- = _('To get started, click the link below to confirm your account.')
- %p
- = link_to 'Confirm your account', confirmation_link
diff --git a/app/views/notify/provisioned_member_access_granted_email.html.haml b/app/views/notify/provisioned_member_access_granted_email.html.haml
new file mode 100644
index 00000000000..515254d1454
--- /dev/null
+++ b/app/views/notify/provisioned_member_access_granted_email.html.haml
@@ -0,0 +1,25 @@
+- source_link = link_to(member_source.human_name, member_source.web_url, target: '_blank', rel: 'noopener noreferrer', class: :highlight)
+- confirmation_link = confirmation_url(@user, confirmation_token: @user.confirmation_token)
+
+%tr
+ %td.text-content
+ %p
+ = _('An Enterprise User GitLab account has been created for you by your organization:')
+ %p
+ = _('Username: %{username}') % { username: @user.username }
+ %br
+ = _('Email: %{email}') % { email: @user.email }
+ %br
+ = _('GitLab group: %{source_link}').html_safe % { source_link: source_link }
+
+%tr
+ %td.text-content
+ %p
+ = _('By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. ')
+ = _('To ensure no loss of personal content, this account should only be used for matters related to %{group_name}.') % { group_name: member_source.human_name }
+ = _('For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group.')
+ - unless @user.confirmed?
+ %p
+ = _('To get started, click the link below to confirm your account.')
+ %p
+ = link_to 'Confirm your account', confirmation_link
diff --git a/app/views/notify/provisioned_member_access_granted_email.text.erb b/app/views/notify/provisioned_member_access_granted_email.text.erb
new file mode 100644
index 00000000000..b143b8d6f54
--- /dev/null
+++ b/app/views/notify/provisioned_member_access_granted_email.text.erb
@@ -0,0 +1,15 @@
+<% source_link = member_source.web_url %>
+
+<%= _('An Enterprise User GitLab account has been created for you by your organization:') %>
+<%= _('Username: %{username}') % { username: @user.username } %>
+<%= _('Email: %{email}') % { email: @user.email } %>
+<%= _('GitLab group: %{source_link}').html_safe % { source_link: source_link } %>
+
+
+<%= _('By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. ') %>
+<%= _('To ensure no loss of personal content, this account should only be used for matters related to %{group_name}.') % { group_name: member_source.human_name } %>
+<%= _('For individual use, create a separate account under your personal email address, not tied to the Enterprise email domain or group.') %>
+<%- unless @user.confirmed? %>
+ <%= _('To get started, click the link below to confirm your account.') %>
+ <%= confirmation_url(@user, confirmation_token: @user.confirmation_token) %>
+<%- end %>
diff --git a/app/views/notify/request_review_merge_request_email.html.haml b/app/views/notify/request_review_merge_request_email.html.haml
new file mode 100644
index 00000000000..d1f72f6529a
--- /dev/null
+++ b/app/views/notify/request_review_merge_request_email.html.haml
@@ -0,0 +1,2 @@
+%p
+ #{sanitize_name(@updated_by.name)} requested a new review on #{merge_request_reference_link(@merge_request)}.
diff --git a/app/views/notify/request_review_merge_request_email.text.erb b/app/views/notify/request_review_merge_request_email.text.erb
new file mode 100644
index 00000000000..9ab15332c51
--- /dev/null
+++ b/app/views/notify/request_review_merge_request_email.text.erb
@@ -0,0 +1 @@
+<%= sanitize_name(@updated_by.name) %> requested a new review on <%= merge_request_reference_link(@merge_request) %>.
diff --git a/app/views/profiles/_email_settings.html.haml b/app/views/profiles/_email_settings.html.haml
index c05d42a5846..977116af88f 100644
--- a/app/views/profiles/_email_settings.html.haml
+++ b/app/views/profiles/_email_settings.html.haml
@@ -4,7 +4,7 @@
- read_only_help_text = readonly ? s_("Profiles|Your email address was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:email) } : user_email_help_text(@user)
- help_text = email_change_disabled ? s_("Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO.") % { group_name: @user.managing_group.name } : read_only_help_text
-= form.text_field :email, required: true, class: 'input-lg', value: (@user.email unless @user.temp_oauth_email?), help: help_text.html_safe, readonly: readonly || email_change_disabled
+= form.text_field :email, required: true, class: 'input-lg gl-form-input', value: (@user.email unless @user.temp_oauth_email?), help: help_text.html_safe, readonly: readonly || email_change_disabled
= form.select :public_email, options_for_select(@user.public_verified_emails, selected: @user.public_email),
{ help: s_("Profiles|This email will be displayed on your public profile"), include_blank: s_("Profiles|Do not show on profile") },
control_class: 'select2 input-lg', disabled: email_change_disabled
diff --git a/app/views/profiles/_name.html.haml b/app/views/profiles/_name.html.haml
index 87f1634b4f3..aea38bf4c3b 100644
--- a/app/views/profiles/_name.html.haml
+++ b/app/views/profiles/_name.html.haml
@@ -1,5 +1,5 @@
- if user.read_only_attribute?(:name)
- = form.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' },
+ = form.text_field :name, class: 'gl-form-input', required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' },
help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) }
- else
- = form.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
+ = form.text_field :name, class: 'gl-form-input', label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name rspec-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml
index f7368c5e921..5c0044ed825 100644
--- a/app/views/profiles/accounts/_providers.html.haml
+++ b/app/views/profiles/accounts/_providers.html.haml
@@ -1,3 +1,5 @@
+- button_class = 'btn btn-default gl-button gl-mb-3 gl-mr-3'
+
%label.label-bold
= s_('Profiles|Connected Accounts')
%p= s_('Profiles|Click on icon to activate signin with one of the following services')
@@ -5,17 +7,19 @@
- unlink_allowed = unlink_provider_allowed?(provider)
- link_allowed = link_provider_allowed?(provider)
- if unlink_allowed || link_allowed
- .provider-btn-group
- .provider-btn-image
- = provider_image_tag(provider)
- - if auth_active?(provider)
- - if unlink_allowed
- = link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'provider-btn' do
+ - if auth_active?(provider)
+ - if unlink_allowed
+ = link_to unlink_profile_account_path(provider: provider), method: :delete, class: button_class do
+ .social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
+ .gl-button-text
= s_('Profiles|Disconnect %{provider}') % { provider: label_for_provider(provider) }
- - else
- %a.provider-btn
+ - else
+ %a{ class: button_class }
+ .gl-button-text
= s_('Profiles|%{provider} Active') % { provider: label_for_provider(provider) }
- - elsif link_allowed
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn gl-text-blue-500' do
+ - elsif link_allowed
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: button_class do
+ .social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
+ .gl-button-text
= s_('Profiles|Connect %{provider}') % { provider: label_for_provider(provider) }
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index ca64c5f57b3..e936cc133bd 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -13,9 +13,9 @@
%button.gl-alert-dismiss.js-close-2fa-enabled-success-alert{ type: 'button', aria: { label: _('Close') } }
= sprite_icon('close', size: 16)
.gl-alert-body
- = _('Congratulations! You have enabled Two-factor Authentication!')
+ = html_escape(_('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}.')) % { anchorOpen: '<a href="%{href}">'.html_safe % { href: help_page_path('user/profile/account/two_factor_authentication', anchor: 'generate-new-recovery-codes-using-ssh') }, anchorClose: '</a>'.html_safe }
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= s_('Profiles|Two-Factor Authentication')
@@ -25,14 +25,15 @@
%p
#{_('Status')}: #{current_user.two_factor_enabled? ? _('Enabled') : _('Disabled')}
- if current_user.two_factor_enabled?
- = link_to _('Manage two-factor authentication'), profile_two_factor_auth_path, class: 'gl-button btn btn-info'
+ = link_to _('Manage two-factor authentication'), profile_two_factor_auth_path, class: 'gl-button btn btn-confirm'
- else
.gl-mb-3
= link_to _('Enable two-factor authentication'), profile_two_factor_auth_path, class: 'gl-button btn btn-success', data: { qa_selector: 'enable_2fa_button' }
+ .col-lg-12
+ %hr
-%hr
- if display_providers_on_profile?
- .row.gl-mt-3
+ .row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= s_('Profiles|Social sign-in')
@@ -40,9 +41,10 @@
= s_('Profiles|Activate signin with one of the following services')
.col-lg-8
= render 'providers', providers: button_based_providers, group_saml_identities: local_assigns[:group_saml_identities]
- %hr
+ .col-lg-12
+ %hr
- if current_user.can_change_username?
- .row.gl-mt-3
+ .row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0.warning-title
= s_('Profiles|Change username')
@@ -53,9 +55,10 @@
.col-lg-8
- data = { initial_username: current_user.username, root_url: root_url, action_url: update_username_profile_path(format: :json) }
#update-username{ data: data }
- %hr
+ .col-lg-12
+ %hr
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0.danger-title
= s_('Profiles|Delete account')
@@ -81,9 +84,9 @@
= s_('Profiles|You must transfer ownership or delete these groups before you can delete your account.')
- elsif !current_user.can_remove_self?
%p
- = s_('Profiles|GitLab is unable to verify your identity automatically.')
+ = s_('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.').html_safe % { openingTag: "<a href='#{reset_profile_password_path}' rel=\"nofollow\" data-method=\"put\">".html_safe, closingTag: '</a>'.html_safe}
%p
- = s_('Profiles|Please email %{data_request} to begin the account deletion process.').html_safe % { data_request: mail_to('personal-data-request@gitlab.com') }
+ = s_('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.').html_safe % { data_request: mail_to('personal-data-request@gitlab.com') }
- else
%p
= s_("Profiles|You don't have access to delete this user.")
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 0c6dc1a05d8..89198b0a65b 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -13,7 +13,7 @@
= form_for 'email', url: profile_emails_path do |f|
.form-group
= f.label :email, _('Email'), class: 'label-bold'
- = f.text_field :email, class: 'form-control', data: { qa_selector: 'email_address_field' }
+ = f.text_field :email, class: 'form-control gl-form-input', data: { qa_selector: 'email_address_field' }
.gl-mt-3
= f.submit _('Add email address'), class: 'gl-button btn btn-success', data: { qa_selector: 'add_email_address_button' }
%hr
@@ -37,23 +37,23 @@
%li
= render partial: 'shared/email_with_badge', locals: { email: @primary_email, verified: current_user.confirmed? }
%span.float-right
- %span.badge.badge-success= s_('Profiles|Primary email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-success= s_('Profiles|Primary email')
- if @primary_email === current_user.commit_email
- %span.badge.badge-info= s_('Profiles|Commit email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Commit email')
- if @primary_email === current_user.public_email
- %span.badge.badge-info= s_('Profiles|Public email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Public email')
- if @primary_email === current_user.notification_email
- %span.badge.badge-info= s_('Profiles|Default notification email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Default notification email')
- @emails.each do |email|
%li{ data: { qa_selector: 'email_row_content' } }
= render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
%span.float-right
- if email.email === current_user.commit_email
- %span.badge.badge-info= s_('Profiles|Commit email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Commit email')
- if email.email === current_user.public_email
- %span.badge.badge-info= s_('Profiles|Public email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Public email')
- if email.email === current_user.notification_email
- %span.badge.badge-info= s_('Profiles|Notification email')
+ %span.badge.badge-muted.badge-pill.gl-badge.badge-info= s_('Profiles|Notification email')
- unless email.confirmed?
- confirm_title = "#{email.confirmation_sent_at ? _('Resend confirmation email') : _('Send confirmation email')}"
= link_to confirm_title, resend_confirmation_instructions_profile_email_path(email), method: :put, class: 'gl-button btn btn-sm btn-warning gl-ml-3'
diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml
index eaf00ce6709..cc2e2a30052 100644
--- a/app/views/profiles/keys/_key.html.haml
+++ b/app/views/profiles/keys/_key.html.haml
@@ -1,32 +1,33 @@
-%li.d-flex.align-items-center.key-list-item
- .gl-mr-3
- - if key.valid?
- - if key.expired?
- %span.d-inline-block.has-tooltip{ title: s_('Profiles|Your key has expired') }
- = sprite_icon('warning-solid', css_class: 'settings-list-icon d-none d-sm-block')
- - else
- = sprite_icon('key', css_class: 'settings-list-icon d-none d-sm-block ')
- - else
- %span.d-inline-block.has-tooltip{ title: key.errors.full_messages.join(', ') }
- = sprite_icon('warning-solid', css_class: 'settings-list-icon d-none d-sm-block')
+%li.key-list-item
+ .gl-display-flex.gl-align-items-flex-start
+ .key-list-item-info.gl-w-full.float-none
+ = link_to path_to_key(key, is_admin), class: "title text-3" do
+ = key.title
- .key-list-item-info.w-100.float-none
- = link_to path_to_key(key, is_admin), class: "title" do
- = key.title
- %span.text-truncate
- = key.fingerprint
+ .gl-display-flex.gl-align-items-center.gl-mt-2
+ - if key.valid?
+ - if key.expired?
+ %span.gl-display-inline-block.has-tooltip{ title: s_('Profiles|Your key has expired') }
+ = sprite_icon('warning-solid', css_class: 'settings-list-icon gl-display-none gl-sm-display-block')
+ - else
+ = sprite_icon('key', css_class: 'settings-list-icon gl-display-none gl-sm-display-block')
+ - else
+ %span.gl-display-inline-block.has-tooltip{ title: key.errors.full_messages.join(', ') }
+ = sprite_icon('warning-solid', css_class: 'settings-list-icon gl-display-none gl-sm-display-block')
- .key-list-item-dates.d-flex.align-items-start.justify-content-between
- %span.last-used-at.gl-mr-3
- = s_('Profiles|Last used:')
- = key.last_used_at ? time_ago_with_tooltip(key.last_used_at) : _('Never')
- %span.expires.gl-mr-3
- = s_('Profiles|Expires:')
- = key.expires_at ? key.expires_at.to_date : _('Never')
- %span.key-created-at.gl-display-flex.gl-align-items-center
- = s_('Profiles|Created%{time_ago}'.html_safe) % { time_ago: time_ago_with_tooltip(key.created_at, html_class: 'gl-ml-2')}
- - if key.can_delete?
- .gl-ml-3
- = button_to '#', class: "btn btn-default gl-button btn-default-tertiary js-confirm-modal-button", data: ssh_key_delete_modal_data(key, path_to_key(key, is_admin)) do
- %span.sr-only= _('Delete')
- = sprite_icon('remove')
+ %span.gl-text-truncate.gl-sm-ml-3
+ = key.fingerprint
+
+ .gl-mt-3= s_('Profiles|Created%{time_ago}'.html_safe) % { time_ago: time_ago_with_tooltip(key.created_at, html_class: 'gl-ml-2')}
+
+ .key-list-item-dates
+ %span.last-used-at.gl-mr-3
+ = s_('Profiles|Last used:')
+ = key.last_used_at ? time_ago_with_tooltip(key.last_used_at) : _('Never')
+ %span.expires.gl-mr-3
+ = s_('Profiles|Expires:')
+ = key.expires_at ? key.expires_at.to_date : _('Never')
+ %span.key-created-at.gl-display-flex.gl-align-items-center
+ - if key.can_delete?
+ .gl-ml-3
+ = render 'shared/ssh_keys/key_delete', html_class: "btn gl-button btn-icon btn-danger js-confirm-modal-button", button_data: ssh_key_delete_modal_data(key, path_to_key(key, is_admin))
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index 22d795ca831..8016d989ff1 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -38,4 +38,4 @@
.col-md-12
.float-right
- if @key.can_delete?
- = button_to _('Delete'), '#', class: "btn btn-danger gl-button delete-key js-confirm-modal-button", data: ssh_key_delete_modal_data(@key, path_to_key(@key, is_admin))
+ = render 'shared/ssh_keys/key_delete', text: _('Delete'), html_class: "btn btn-danger gl-button delete-key js-confirm-modal-button", button_data: ssh_key_delete_modal_data(@key, path_to_key(@key, is_admin))
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 7b7c24f3ac8..80027cdfed0 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -11,8 +11,8 @@
%h5.gl-mt-0
= _('Add an SSH key')
%p.profile-settings-content
- - generate_link_url = help_page_path("ssh/README", anchor: 'generating-a-new-ssh-key-pair')
- - existing_link_url = help_page_path("ssh/README", anchor: 'review-existing-ssh-keys')
+ - generate_link_url = help_page_path("ssh/README", anchor: 'generate-an-ssh-key-pair')
+ - existing_link_url = help_page_path("ssh/README", anchor: 'see-if-you-have-an-existing-ssh-key-pair')
- generate_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: generate_link_url }
- existing_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: existing_link_url }
= _('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}.').html_safe % { generate_link_start: generate_link_start, existing_link_start: existing_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/profiles/notifications/_email_settings.html.haml b/app/views/profiles/notifications/_email_settings.html.haml
index 7ac3ef9b141..f452a5b2eb5 100644
--- a/app/views/profiles/notifications/_email_settings.html.haml
+++ b/app/views/profiles/notifications/_email_settings.html.haml
@@ -4,3 +4,7 @@
= form.select :notification_email, @user.public_verified_emails, { include_blank: false }, class: "select2", disabled: local_assigns.fetch(:email_change_disabled, nil)
.help-block
= local_assigns.fetch(:help_text, nil)
+.form-group
+ %label{ for: 'user_email_opted_in' }
+ = form.check_box :email_opted_in
+ %span= _('Receive product marketing emails')
diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml
index b1578886098..abbfbd995b6 100644
--- a/app/views/profiles/notifications/_group_settings.html.haml
+++ b/app/views/profiles/notifications/_group_settings.html.haml
@@ -9,7 +9,11 @@
= link_to group.name, group_path(group)
.table-section.section-30.text-right
- = render 'shared/notifications/button', notification_setting: setting, emails_disabled: emails_disabled
+ - if Feature.enabled?(:vue_notification_dropdown, default_enabled: :yaml)
+ - if setting
+ .js-vue-notification-dropdown{ data: { disabled: emails_disabled, dropdown_items: notification_dropdown_items(setting).to_json, notification_level: setting.level, group_id: group.id, container_class: 'gl-mr-3', show_label: "true" } }
+ - else
+ = render 'shared/notifications/button', notification_setting: setting, emails_disabled: emails_disabled
.table-section.section-30
= form_for setting, url: profile_notifications_group_path(group), method: :put, html: { class: 'update-notifications gl-display-flex' } do |f|
diff --git a/app/views/profiles/notifications/_project_settings.html.haml b/app/views/profiles/notifications/_project_settings.html.haml
index 6e81d585f24..8cd552caa3d 100644
--- a/app/views/profiles/notifications/_project_settings.html.haml
+++ b/app/views/profiles/notifications/_project_settings.html.haml
@@ -8,4 +8,8 @@
= link_to_project(project)
.float-right
- = render 'shared/notifications/button', notification_setting: setting, emails_disabled: emails_disabled
+ - if Feature.enabled?(:vue_notification_dropdown, default_enabled: :yaml)
+ - if setting
+ .js-vue-notification-dropdown{ data: { disabled: emails_disabled, dropdown_items: notification_dropdown_items(setting).to_json, notification_level: setting.level, project_id: project.id, container_class: 'gl-mr-3', show_label: "true" } }
+ - else
+ = render 'shared/notifications/button', notification_setting: setting, emails_disabled: emails_disabled
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index e1345a94fb1..cb0ada414ed 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -32,7 +32,11 @@
%br
.clearfix
.form-group.float-left.global-notification-setting
- = render 'shared/notifications/button', notification_setting: @global_notification_setting
+ - if Feature.enabled?(:vue_notification_dropdown, default_enabled: :yaml)
+ - if @global_notification_setting
+ .js-vue-notification-dropdown{ data: { dropdown_items: notification_dropdown_items(@global_notification_setting).to_json, notification_level: @global_notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), show_label: 'true' } }
+ - else
+ = render 'shared/notifications/button', notification_setting: @global_notification_setting
.clearfix
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 1ee5f52e407..b281dbb4367 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -20,15 +20,15 @@
- unless @user.password_automatically_set?
.form-group
= f.label :current_password, _('Current password'), class: 'label-bold'
- = f.password_field :current_password, required: true, class: 'form-control', data: { qa_selector: 'current_password_field' }
+ = f.password_field :current_password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
%p.form-text.text-muted
= _('You must provide your current password in order to change it.')
.form-group
= f.label :password, _('New password'), class: 'label-bold'
- = f.password_field :password, required: true, class: 'form-control', data: { qa_selector: 'new_password_field' }
+ = f.password_field :password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' }
.form-group
= f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
- = f.password_field :password_confirmation, required: true, class: 'form-control', data: { qa_selector: 'confirm_password_field' }
+ = f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
.gl-mt-3.gl-mb-3
= f.submit _('Save password'), class: "gl-button btn btn-success gl-mr-3", data: { qa_selector: 'save_password_button' }
- unless @user.password_automatically_set?
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index f6783528243..ffec6baa20e 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -16,16 +16,16 @@
.col-sm-2.col-form-label
= f.label :current_password, _('Current password')
.col-sm-10
- = f.password_field :current_password, required: true, class: 'form-control'
+ = f.password_field :current_password, required: true, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :password, _('New password')
.col-sm-10
- = f.password_field :password, required: true, class: 'form-control'
+ = f.password_field :password, required: true, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :password_confirmation, _('Password confirmation')
.col-sm-10
- = f.password_field :password_confirmation, required: true, class: 'form-control'
+ = f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input'
.form-actions
= f.submit _('Set new password'), class: 'gl-button btn btn-success'
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index 577b64ba17a..ee04d9142b1 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -4,7 +4,7 @@
- type_plural = _('personal access tokens')
- @content_class = 'limit-container-width' unless fluid_layout
-.row.gl-mt-3
+.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
@@ -33,8 +33,9 @@
revoke_route_helper: ->(token) { revoke_profile_personal_access_token_path(token) }
- unless Gitlab::CurrentSettings.disable_feed_token
- %hr
- .row.gl-mt-3
+ .col-lg-12
+ %hr
+ .row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= s_('AccessTokens|Feed token')
@@ -44,15 +45,16 @@
= s_('AccessTokens|It cannot be used to access any other data.')
.col-lg-8.feed-token-reset
= label_tag :feed_token, s_('AccessTokens|Feed token'), class: 'label-bold'
- = text_field_tag :feed_token, current_user.feed_token, class: 'form-control js-select-on-focus', readonly: true
+ = text_field_tag :feed_token, current_user.feed_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
%p.form-text.text-muted
- reset_link = link_to s_('AccessTokens|reset it'), [:reset, :feed_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.') }
- reset_message = s_('AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens.') % { link_reset_it: reset_link }
= reset_message.html_safe
- if incoming_email_token_enabled?
- %hr
- .row.gl-mt-3
+ .col-lg-12
+ %hr
+ .row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= s_('AccessTokens|Incoming email token')
@@ -62,15 +64,16 @@
= s_('AccessTokens|It cannot be used to access any other data.')
.col-lg-8.incoming-email-token-reset
= label_tag :incoming_email_token, s_('AccessTokens|Incoming email token'), class: 'label-bold'
- = text_field_tag :incoming_email_token, current_user.incoming_email_token, class: 'form-control js-select-on-focus', readonly: true
+ = text_field_tag :incoming_email_token, current_user.incoming_email_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
%p.form-text.text-muted
- reset_link = link_to s_('AccessTokens|reset it'), [:reset, :incoming_email_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.') }
- reset_message = s_('AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens.') % { link_reset_it: reset_link }
= reset_message.html_safe
- if static_objects_external_storage_enabled?
- %hr
- .row.gl-mt-3
+ .col-lg-12
+ %hr
+ .row.gl-mt-3.js-search-settings-section
.col-lg-4
%h4.gl-mt-0
= s_('AccessTokens|Static object token')
@@ -80,7 +83,7 @@
= s_('AccessTokens|It cannot be used to access any other data.')
.col-lg-8
= label_tag :static_object_token, s_('AccessTokens|Static object token'), class: "label-bold"
- = text_field_tag :static_object_token, current_user.static_object_token, class: 'form-control', readonly: true, onclick: 'this.select()'
+ = text_field_tag :static_object_token, current_user.static_object_token, class: 'form-control gl-form-input', readonly: true, onclick: 'this.select()'
%p.form-text.text-muted
- reset_link = url_for [:reset, :static_object_token, :profile]
- reset_link_start = '<a data-confirm="%{confirm}" rel="nofollow" data-method="put" href="%{url}">'.html_safe % { confirm: s_('AccessTokens|Are you sure?'), url: reset_link }
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index aeecb0c0d72..cd76a67b692 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -1,14 +1,15 @@
- page_title _('Preferences')
- @content_class = "limit-container-width" unless fluid_layout
-- user_fields = { gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }
- user_theme_id = Gitlab::Themes.for_user(@user).id
-- data_attributes = { integration_views: integration_views.to_json, user_fields: user_fields.to_json }
+- user_fields = { theme: user_theme_id, gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }.to_json
+- @themes = Gitlab::Themes::THEMES.to_json
+- data_attributes = { themes: @themes, integration_views: integration_views.to_json, user_fields: user_fields, body_classes: Gitlab::Themes.body_classes, profile_preferences_path: profile_preferences_path }
- Gitlab::Themes.each do |theme|
= stylesheet_link_tag "themes/#{theme.css_filename}" if theme.css_filename
-= form_for @user, url: profile_preferences_path, remote: true, method: :put do |f|
- .row.gl-mt-3.js-preferences-form
+= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: { id: "profile-preferences-form" } do |f|
+ .row.gl-mt-3.js-preferences-form.js-search-settings-section
.col-lg-4.application-theme#navigation-theme
%h4.gl-mt-0
= s_('Preferences|Navigation theme')
@@ -25,6 +26,7 @@
.col-sm-12
%hr
+ .row.js-preferences-form.js-search-settings-section
.col-lg-4.profile-settings-sidebar#syntax-highlighting-theme
%h4.gl-mt-0
= s_('Preferences|Syntax highlighting theme')
@@ -42,6 +44,7 @@
.col-sm-12
%hr
+ .row.js-preferences-form.js-search-settings-section
.col-lg-4.profile-settings-sidebar#behavior
%h4.gl-mt-0
= s_('Preferences|Behavior')
@@ -97,7 +100,7 @@
.col-sm-12
%hr
-
+ .row.js-preferences-form.js-search-settings-section
.col-lg-4.profile-settings-sidebar#localization
%h4.gl-mt-0
= _('Localization')
@@ -141,10 +144,4 @@
.form-text.text-muted
= s_('Preferences|For example: 30 mins ago.')
- #js-profile-preferences-app{ data: data_attributes, user_fields: user_fields.to_json }
-
- .row.gl-mt-3.js-preferences-form
- .col-lg-4.profile-settings-sidebar
- .col-lg-8
- .form-group
- = f.submit _('Save changes'), class: 'gl-button btn btn-success'
+ #js-profile-preferences-app{ data: data_attributes }
diff --git a/app/views/profiles/preferences/update.js.erb b/app/views/profiles/preferences/update.js.erb
deleted file mode 100644
index 241262880c1..00000000000
--- a/app/views/profiles/preferences/update.js.erb
+++ /dev/null
@@ -1,20 +0,0 @@
-// Remove body class for any previous theme, re-add current one
-$('body').removeClass('<%= Gitlab::Themes.body_classes %>')
-$('body').addClass('<%= user_application_theme %>')
-
-// Toggle container-fluid class
-if ('<%= current_user.layout %>' === 'fluid') {
- $('.content-wrapper .container-fluid').removeClass('container-limited')
-} else {
- $('.content-wrapper .container-fluid').addClass('container-limited')
-}
-
-// Re-enable the "Save" button
-$('input[type=submit]').enable()
-
-// Show flash messages
-<% if flash.notice %>
- new Flash({ message: '<%= flash.discard(:notice) %>', type: 'notice'})
-<% elsif flash.alert %>
- new Flash({ message: '<%= flash.discard(:alert) %>', type: 'alert'})
-<% end %>
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 41699d6f01f..4689fd5272a 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -8,7 +8,7 @@
= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user gl-mt-3 js-quick-submit gl-show-field-errors' }, authenticity_token: true do |f|
= form_errors(@user)
- .row
+ .row.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= s_("Profiles|Public Avatar")
@@ -32,16 +32,16 @@
= image_tag avatar_icon_for_user(@user, 160), alt: '', class: 'avatar s160'
%h5.gl-mt-0= s_("Profiles|Upload new avatar")
.gl-mt-2.gl-mb-3
- %button.btn.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
+ %button.gl-button.btn.js-choose-user-avatar-button{ type: 'button' }= s_("Profiles|Choose file...")
%span.avatar-file-name.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen")
= f.file_field_without_bootstrap :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*'
.form-text.text-muted= s_("Profiles|The maximum file size allowed is 200KB.")
- if @user.avatar?
%hr
= link_to s_("Profiles|Remove avatar"), profile_avatar_path, data: { confirm: s_("Profiles|Avatar will be removed. Are you sure?") }, method: :delete, class: 'gl-button btn btn-danger btn-inverted'
-
- %hr
- .row
+ .col-lg-12
+ %hr
+ .row.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0= s_("Profiles|Current status")
%p= s_("Profiles|This emoji and message will appear on your profile and throughout the interface.")
@@ -65,7 +65,7 @@
= status_form.hidden_field :emoji, id: 'js-status-emoji-field'
= status_form.text_field :message,
id: 'js-status-message-field',
- class: 'form-control input-lg',
+ class: 'form-control gl-form-input input-lg',
label: s_("Profiles|Your status"),
prepend: emoji_button,
append: reset_message_button,
@@ -74,21 +74,22 @@
.checkbox-icon-inline-wrapper
= status_form.check_box :availability, { data: { testid: "user-availability-checkbox" }, label: s_("Profiles|Busy"), wrapper_class: 'gl-mr-0 gl-font-weight-bold' }, availability["busy"], availability["not_set"]
.gl-text-gray-600.gl-ml-5= s_('Profiles|"Busy" will be shown next to your name')
- - if Feature.enabled?(:user_time_settings)
- %hr
- .row.user-time-preferences
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0= s_("Profiles|Time settings")
- %p= s_("Profiles|You can set your current timezone here")
- .col-lg-8
- -# TODO: might need an entry in user/profile.md to describe some of these settings
- -# https://gitlab.com/gitlab-org/gitlab-foss/issues/60070
- %h5= ("Time zone")
- = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
- %input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
-
- %hr
- .row
+ - if Feature.enabled?(:user_time_settings)
+ .col-lg-12
+ %hr
+ .row.user-time-preferences.js-search-settings-section
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0= s_("Profiles|Time settings")
+ %p= s_("Profiles|You can set your current timezone here")
+ .col-lg-8
+ -# TODO: might need an entry in user/profile.md to describe some of these settings
+ -# https://gitlab.com/gitlab-org/gitlab-foss/issues/60070
+ %h5= ("Time zone")
+ = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
+ %input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
+ .col-lg-12
+ %hr
+ .row.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= s_("Profiles|Main settings")
@@ -99,20 +100,20 @@
.col-lg-8
.row
= render 'profiles/name', form: f, user: @user
- = f.text_field :id, readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
+ = f.text_field :id, class: 'gl-form-input', readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
= render_if_exists 'profiles/email_settings', form: f
- = f.text_field :skype, class: 'input-md', placeholder: s_("Profiles|username")
- = f.text_field :linkedin, class: 'input-md', help: s_("Profiles|Your LinkedIn profile name from linkedin.com/in/profilename")
- = f.text_field :twitter, class: 'input-md', placeholder: s_("Profiles|@username")
- = f.text_field :website_url, class: 'input-lg', placeholder: s_("Profiles|website.com")
+ = f.text_field :skype, class: 'input-md gl-form-input', placeholder: s_("Profiles|username")
+ = f.text_field :linkedin, class: 'input-md gl-form-input', help: s_("Profiles|Your LinkedIn profile name from linkedin.com/in/profilename")
+ = f.text_field :twitter, class: 'input-md gl-form-input', placeholder: s_("Profiles|@username")
+ = f.text_field :website_url, class: 'input-lg gl-form-input', placeholder: s_("Profiles|website.com")
- if @user.read_only_attribute?(:location)
- = f.text_field :location, readonly: true, help: s_("Profiles|Your location was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:location) }
+ = f.text_field :location, class: 'gl-form-input', readonly: true, help: s_("Profiles|Your location was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:location) }
- else
- = f.text_field :location, label: s_('Profiles|Location'), class: 'input-lg', placeholder: s_("Profiles|City, country")
- = f.text_field :job_title, class: 'input-md'
- = f.text_field :organization, label: s_('Profiles|Organization'), class: 'input-md', help: s_("Profiles|Who you represent or work for")
- = f.text_area :bio, label: s_('Profiles|Bio'), rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters")
+ = f.text_field :location, label: s_('Profiles|Location'), class: 'input-lg gl-form-input', placeholder: s_("Profiles|City, country")
+ = f.text_field :job_title, class: 'input-md gl-form-input'
+ = f.text_field :organization, label: s_('Profiles|Organization'), class: 'input-md gl-form-input', help: s_("Profiles|Who you represent or work for")
+ = f.text_area :bio, class: 'gl-form-input', label: s_('Profiles|Bio'), rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters")
%hr
%h5= s_("Private profile")
.checkbox-icon-inline-wrapper
@@ -124,9 +125,10 @@
= f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true
.help-block
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
- .gl-mt-3.gl-mb-3
- = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-success'
- = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-cancel'
+ .row.gl-mt-3.gl-mb-3.gl-justify-content-end
+ .col-lg-8
+ = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-success'
+ = link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-cancel'
.modal.modal-profile-crop{ data: { cropper_css_path: ActionController::Base.helpers.stylesheet_path('lazy_bundles/cropper.css') } }
.modal-dialog
@@ -141,12 +143,12 @@
%img.modal-profile-crop-image{ alt: s_("Profiles|Avatar cropper") }
.crop-controls
.btn-group
- %button.btn.btn-primary{ data: { method: 'zoom', option: '-0.1' } }
+ %button.btn.gl-button.btn-confirm{ data: { method: 'zoom', option: '-0.1' } }
%span
= sprite_icon('search-minus')
- %button.btn.btn-primary{ data: { method: 'zoom', option: '0.1' } }
+ %button.btn.gl-button.btn-confirm{ data: { method: 'zoom', option: '0.1' } }
%span
= sprite_icon('search-plus')
.modal-footer
- %button.btn.btn-primary.js-upload-user-avatar{ type: 'button' }
+ %button.btn.gl-button.btn-confirm.js-upload-user-avatar{ type: 'button' }
= s_("Profiles|Set new profile picture")
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index ff4ddd4ad69..0284c779cfa 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -22,12 +22,11 @@
data: { confirm: webauthn_enabled ? _('Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices.') : _('Are you sure? This will invalidate your registered applications and U2F devices.') },
class: 'gl-button btn btn-danger gl-mr-3'
= form_tag codes_profile_two_factor_auth_path, {style: 'display: inline-block', method: :post} do |f|
- = submit_tag _('Regenerate recovery codes'), class: 'btn'
+ = submit_tag _('Regenerate recovery codes'), class: 'gl-button btn btn-default'
- else
%p
- - help_link_start = '<a href="%{url}" target="_blank">' % { url: help_page_path('user/profile/account/two_factor_authentication') }
- - register_2fa_token = _('Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}.') % { free_otp_link:'<a href="https://freeotp.github.io/">FreeOTP</a>', help_link_start:help_link_start, help_link_end:'</a>' }
+ - register_2fa_token = _('We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device.')
= register_2fa_token.html_safe
.row.gl-mb-3
.col-md-4
diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml
index c47ca81c431..db0f13843dd 100644
--- a/app/views/projects/_activity.html.haml
+++ b/app/views/projects/_activity.html.haml
@@ -1,15 +1,14 @@
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
-%div{ class: container_class }
- .nav-block.d-none.d-sm-flex.activities.gl-static
- = render 'shared/event_filter'
- .controls.gl-display-flex
- = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip' do
- = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon')
- - if is_project_overview && can?(current_user, :download_code, @project)
- .project-clone-holder.d-none.d-md-inline-flex.gl-ml-2
- = render "projects/buttons/clone", dropdown_class: 'dropdown-menu-right'
+.nav-block.d-none.d-sm-flex.activities.gl-static
+ = render 'shared/event_filter'
+ .controls.gl-display-flex
+ = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip' do
+ = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon')
+ - if is_project_overview && can?(current_user, :download_code, @project)
+ .project-clone-holder.d-none.d-md-inline-flex.gl-ml-2
+ = render "projects/buttons/clone", dropdown_class: 'dropdown-menu-right'
- .content_list.project-activity{ :"data-href" => activity_project_path(@project) }
- .loading
- .spinner.spinner-md
+.content_list.project-activity{ :"data-href" => activity_project_path(@project) }
+.loading
+ .spinner.spinner-md
diff --git a/app/views/projects/_export.html.haml b/app/views/projects/_export.html.haml
index 86dfcda6d1b..eb4630b84d5 100644
--- a/app/views/projects/_export.html.haml
+++ b/app/views/projects/_export.html.haml
@@ -4,27 +4,25 @@
.sub-section{ data: { qa_selector: 'export_project_content' } }
%h4= _('Export project')
- %p= _('Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.')
-
- .bs-callout.bs-callout-info
- %p.gl-mb-0
- %p= _('The following items will be exported:')
- %ul
- - project_export_descriptions.each do |desc|
- %li= desc
- %p= _('The following items will NOT be exported:')
- %ul
- %li= _('Job logs and artifacts')
- %li= _('Container registry images')
- %li= _('CI variables')
- %li= _('Webhooks')
- %li= _('Any encrypted tokens')
- %p= _('Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page.')
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/import_export') }
+ %p= _('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}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ %p.gl-mb-0
+ %p= _('The following items will be exported:')
+ %ul
+ - project_export_descriptions.each do |desc|
+ %li= desc
+ %p= _('The following items will NOT be exported:')
+ %ul
+ %li= _('Job logs and artifacts')
+ %li= _('Container registry images')
+ %li= _('CI variables')
+ %li= _('Webhooks')
+ %li= _('Any encrypted tokens')
- if project.export_status == :finished
= link_to _('Download export'), download_export_project_path(project),
- rel: 'nofollow', download: '', method: :get, class: "btn btn-default", data: { qa_selector: 'download_export_link' }
+ rel: 'nofollow', download: '', method: :get, class: "btn gl-button btn-default", data: { qa_selector: 'download_export_link' }
= link_to _('Generate new export'), generate_new_export_project_path(project),
- method: :post, class: "btn btn-default"
+ method: :post, class: "btn gl-button btn-default"
- else
= link_to _('Export project'), export_project_path(project),
- method: :post, class: "btn btn-default", data: { qa_selector: 'export_project_link' }
+ method: :post, class: "btn gl-button btn-default", data: { qa_selector: 'export_project_link' }
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 88dcc74a465..30d885964b5 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -11,7 +11,7 @@
= render 'projects/tree/tree_header', tree: @tree
#js-last-commit
- .info-well.gl-display-none.gl-display-sm-flex.project-last-commit
+ .info-well.gl-display-none.gl-sm-display-flex.project-last-commit
.gl-spinner-container.m-auto
= loading_icon(size: 'md', color: 'dark', css_class: 'align-text-bottom')
diff --git a/app/views/projects/_find_file_link.html.haml b/app/views/projects/_find_file_link.html.haml
index c3b4a61c28a..a4bf72edf12 100644
--- a/app/views/projects/_find_file_link.html.haml
+++ b/app/views/projects/_find_file_link.html.haml
@@ -1,2 +1,2 @@
-= link_to project_find_file_path(@project, @ref), class: 'gl-button btn shortcuts-find-file', rel: 'nofollow' do
+= link_to project_find_file_path(@project, @ref), class: 'gl-button btn btn-default shortcuts-find-file', rel: 'nofollow' do
= _('Find file')
diff --git a/app/views/projects/_fork_suggestion.html.haml b/app/views/projects/_fork_suggestion.html.haml
index 9e6ff4a5d7a..59c9c279a39 100644
--- a/app/views/projects/_fork_suggestion.html.haml
+++ b/app/views/projects/_fork_suggestion.html.haml
@@ -1,11 +1,10 @@
-- if current_user
- .js-file-fork-suggestion-section.file-fork-suggestion.hidden
- %span.file-fork-suggestion-note
- You're not allowed to
- %span.js-file-fork-suggestion-section-action
- edit
- files in this project directly. Please fork this project,
- make your changes there, and submit a merge request.
- = link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button gl-button btn btn-grouped btn-inverted btn-success'
- %button.js-cancel-fork-suggestion-button.gl-button.btn.btn-grouped{ type: 'button' }
- Cancel
+.js-file-fork-suggestion-section.file-fork-suggestion.hidden
+ %span.file-fork-suggestion-note
+ You're not allowed to
+ %span.js-file-fork-suggestion-section-action
+ edit
+ files in this project directly. Please fork this project,
+ make your changes there, and submit a merge request.
+ = link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button gl-button btn btn-grouped btn-inverted btn-success'
+ %button.js-cancel-fork-suggestion-button.gl-button.btn.btn-grouped{ type: 'button' }
+ Cancel
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 3e1d08e646e..0d3049cd9a2 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -3,7 +3,7 @@
- max_project_topic_length = 15
- emails_disabled = @project.emails_disabled?
-= render_if_exists 'projects/invite_members_modal', project: @project
+= render 'projects/invite_members_modal', project: @project
.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
.row.gl-mb-3
@@ -46,7 +46,11 @@
.project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
- if current_user
.d-inline-flex
- = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs', dropdown_container_class: 'gl-mr-3', emails_disabled: emails_disabled
+ - if Feature.enabled?(:vue_notification_dropdown, @project, default_enabled: :yaml)
+ - if @notification_setting
+ .js-vue-notification-dropdown{ data: { button_size: "small", disabled: emails_disabled, 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, container_class: 'gl-mr-3 gl-mt-5 gl-vertical-align-top' } }
+ - else
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs', dropdown_container_class: 'gl-mr-3', emails_disabled: emails_disabled
.count-buttons.d-inline-flex
= render 'projects/buttons/star'
@@ -65,7 +69,7 @@
.home-panel-description.text-break
.home-panel-description-markdown.read-more-container{ itemprop: 'description' }
= markdown_field(@project, :description)
- %button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
+ %button.btn.gl-button.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
- if @project.forked?
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index 27d75591d3e..e6ded3ad912 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -8,7 +8,7 @@
.import-buttons
- if gitlab_project_import_enabled?
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
- = link_to new_import_gitlab_project_path, class: 'gl-button btn-default btn btn_import_gitlab_project project-submit', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
+ = link_to new_import_gitlab_project_path, class: 'gl-button btn-default btn btn_import_gitlab_project', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
.gl-button-icon
= sprite_icon('tanuki')
= _("GitLab export")
diff --git a/app/views/projects/_invite_members_link.html.haml b/app/views/projects/_invite_members_link.html.haml
new file mode 100644
index 00000000000..95cfc75d955
--- /dev/null
+++ b/app/views/projects/_invite_members_link.html.haml
@@ -0,0 +1,4 @@
+- return unless can_invite_members_for_project?(@project)
+
+%li
+ .js-invite-members-trigger{ data: { icon: 'plus', classes: 'gl-text-decoration-none! gl-shadow-none!', display_text: _('Invite team members') } }
diff --git a/app/views/projects/_invite_members_modal.html.haml b/app/views/projects/_invite_members_modal.html.haml
index e8f61336882..b1bba5b59ca 100644
--- a/app/views/projects/_invite_members_modal.html.haml
+++ b/app/views/projects/_invite_members_modal.html.haml
@@ -1,4 +1,4 @@
-- if invite_members_allowed?(project.group)
+- if can_invite_members_for_project?(project)
.js-invite-members-modal{ data: { id: project.id,
name: project.name,
is_project: 'true',
diff --git a/app/views/projects/_invite_members_side_nav_link.html.haml b/app/views/projects/_invite_members_side_nav_link.html.haml
deleted file mode 100644
index 15e0b75cf57..00000000000
--- a/app/views/projects/_invite_members_side_nav_link.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- if invite_members_allowed?(project.group) && body_data_page == 'projects:show'
- %li
- .js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
diff --git a/app/views/projects/_issuable_by_email.html.haml b/app/views/projects/_issuable_by_email.html.haml
deleted file mode 100644
index c11ee765cca..00000000000
--- a/app/views/projects/_issuable_by_email.html.haml
+++ /dev/null
@@ -1,49 +0,0 @@
-- name = issuable_type == 'issue' ? 'issue' : 'merge request'
-
-.issuable-footer.text-center
- %button.issuable-email-modal-btn{ type: "button", data: { toggle: "modal", target: "#issuable-email-modal" } }
- Email a new #{name} to this project
-
-#issuable-email-modal.modal.fade{ tabindex: "-1", role: "dialog" }
- .modal-dialog{ role: "document" }
- .modal-content
- .modal-header
- %h4.modal-title
- Create new #{name} by email
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
- .modal-body
- %p
- You can create a new #{name} inside this project by sending an email to the following email address:
- .email-modal-input-group.input-group
- = text_field_tag :issuable_email, email, class: "monospace js-select-on-focus form-control", readonly: true
- .input-group-append
- = clipboard_button(target: '#issuable_email', class: 'btn btn-clipboard input-group-text btn-transparent d-none d-sm-block')
-
- - if issuable_type == 'issue'
- - enter_title_text = _('Enter the issue title')
- - enter_description_text = _('Enter the issue description')
- - else
- - enter_title_text = _('Enter the merge request title')
- - enter_description_text = _('Enter the merge request description')
- = mail_to email, class: 'btn btn-clipboard btn-transparent',
- subject: enter_title_text,
- body: enter_description_text,
- title: _('Send email'),
- data: { toggle: 'tooltip', placement: 'bottom' } do
- = sprite_icon('mail')
-
- %p
- = render 'by_email_description'
- %p
- This is a private email address
- %span<
- = link_to help_page_path('development/emails', anchor: 'email-namespace'), target: '_blank', rel: 'noopener', aria: { label: 'Learn more about incoming email addresses' } do
- = sprite_icon('question-o')
-
- generated just for you.
-
- Anyone who gets ahold of it can create issues or merge requests as if they were you.
- You should
- = link_to 'reset it', new_issuable_address_project_path(@project, issuable_type: issuable_type), class: 'incoming-email-token-reset'
- if that ever happens.
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 3b66fdbdf1a..afe42b334ba 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -15,5 +15,5 @@
- if can?(current_user, :create_merge_request_in, event.project.default_merge_request_target)
.flex-right
- = link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm qa-create-merge-request" do
+ = link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn gl-button btn-info btn-sm qa-create-merge-request" do
#{ _('Create merge request') }
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 7a5997bbcfd..b099eb6800e 100644
--- a/app/views/projects/_merge_request_merge_checks_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml
@@ -24,3 +24,4 @@
= form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input', data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' }
= form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
= s_('ProjectSettings|All discussions must be resolved')
+ = render_if_exists 'projects/merge_request_merge_checks_jira_enforcement', form: form, project: @project
diff --git a/app/views/projects/_merge_request_merge_options_settings.html.haml b/app/views/projects/_merge_request_merge_options_settings.html.haml
index 8951f2ed22f..80dabeceeb0 100644
--- a/app/views/projects/_merge_request_merge_options_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_options_settings.html.haml
@@ -1,6 +1,6 @@
- form = local_assigns.fetch(:form)
-.form-group
+.form-group#project-merge-options{ data: { project_full_path: @project.full_path } }
%b= s_('ProjectSettings|Merge options')
%p.text-secondary= s_('ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed')
= render_if_exists 'projects/merge_pipelines_settings', form: form
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 258cf86ab05..31a85a204be 100644
--- a/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
@@ -9,7 +9,7 @@
anchor: 'configure-the-commit-message-for-applied-suggestions'),
target: '_blank'
.mb-2
- = form.text_field :suggestion_commit_message, class: 'form-control mb-2', placeholder: Gitlab::Suggestions::CommitMessage::DEFAULT_SUGGESTION_COMMIT_MESSAGE
+ = form.text_field :suggestion_commit_message, class: 'form-control gl-form-input mb-2', placeholder: Gitlab::Suggestions::CommitMessage::DEFAULT_SUGGESTION_COMMIT_MESSAGE
%p.form-text.text-muted
= s_('ProjectSettings|The variables GitLab supports:')
- Gitlab::Suggestions::CommitMessage::PLACEHOLDERS.keys.each do |placeholder|
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index e69972e8163..a54eb2dddac 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -4,8 +4,7 @@
= render 'projects/merge_request_merge_options_settings', project: @project, form: form
-- if Feature.enabled?(:squash_options, @project, default_enabled: true)
- = render 'projects/merge_request_squash_options_settings', form: form
+= render 'projects/merge_request_squash_options_settings', form: form
= render 'projects/merge_request_merge_checks_settings', project: @project, form: form
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index ee35f734e3e..41992ee5ea9 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -54,12 +54,13 @@
.form-group.row.initialize-with-readme-setting
%div{ :class => "col-sm-12" }
.form-check
- = check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input qa-initialize-with-readme-checkbox', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "init_with_readme", track_value: "" }
+ - experiment(:new_project_readme, actor: current_user) do |e|
+ = check_box_tag 'project[initialize_with_readme]', '1', e.run, class: 'form-check-input qa-initialize-with-readme-checkbox', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "init_with_readme", track_value: "" }
= label_tag 'project[initialize_with_readme]', class: 'form-check-label' do
.option-title
%strong= s_('ProjectsNew|Initialize repository with a README')
.option-description
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
-= f.submit _('Create project'), class: "btn btn-success project-submit", data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
-= link_to _('Cancel'), dashboard_projects_path, class: 'btn btn-cancel', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "cancel", track_value: "" }
+= f.submit _('Create project'), class: "btn gl-button btn-success", data: { track_label: "#{track_label}", track_event: "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_event: "click_button", track_property: "cancel", track_value: "" }
diff --git a/app/views/projects/_new_project_push_tip.html.haml b/app/views/projects/_new_project_push_tip.html.haml
index e008130436c..a63b4bed9de 100644
--- a/app/views/projects/_new_project_push_tip.html.haml
+++ b/app/views/projects/_new_project_push_tip.html.haml
@@ -8,4 +8,4 @@
%span.input-group-append
= clipboard_button(text: push_to_create_project_command, title: _("Copy command"), class: 'input-group-text', placement: "right")
%p
- = link_to("What does this command do?", help_page_path("gitlab-basics/create-project", anchor: "push-to-create-a-new-project"), target: "_blank")
+ = link_to("What does this command do?", help_page_path("user/project/working_with_projects", anchor: "push-to-create-a-new-project"), target: "_blank")
diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml
index d1ff52548cd..949397755ba 100644
--- a/app/views/projects/_project_templates.html.haml
+++ b/app/views/projects/_project_templates.html.haml
@@ -1,15 +1,15 @@
- f ||= local_assigns[:f]
-.project-templates-buttons.col-sm-12
+.project-templates-buttons
%ul.nav-tabs.nav-links.nav.scrolling-tabs
%li.built-in-tab
%a.nav-link.active{ href: "#built-in", data: { toggle: 'tab'} }
= _('Built-in')
- %span.badge.badge-pill= Gitlab::SampleDataTemplate.all.count + Gitlab::ProjectTemplate.all.count
+ %span.badge.badge-pill= Gitlab::ProjectTemplate.all.count + Gitlab::SampleDataTemplate.all.count
.tab-content
.project-templates-buttons.import-buttons.tab-pane.active#built-in
- = render partial: 'projects/project_templates/template', collection: Gitlab::SampleDataTemplate.all + Gitlab::ProjectTemplate.all
+ = render partial: 'projects/project_templates/template', collection: Gitlab::ProjectTemplate.all + Gitlab::SampleDataTemplate.all
.project-fields-form
= render 'projects/project_templates/project_fields_form'
diff --git a/app/views/projects/_remove.html.haml b/app/views/projects/_remove.html.haml
index c246c45d0f7..e991a9b0ec7 100644
--- a/app/views/projects/_remove.html.haml
+++ b/app/views/projects/_remove.html.haml
@@ -3,7 +3,8 @@
.sub-section
%h4.danger-title= _('Delete project')
%p
- %strong= _('Deleting the project will delete its repository and all related resources including issues, merge requests etc.')
+ %strong= _('Deleting the project will delete its repository and all related resources including issues, merge requests, etc.')
+ = 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: project.path } }
diff --git a/app/views/projects/_remove_fork.html.haml b/app/views/projects/_remove_fork.html.haml
index 2a7453902a8..8fa21966683 100644
--- a/app/views/projects/_remove_fork.html.haml
+++ b/app/views/projects/_remove_fork.html.haml
@@ -7,4 +7,5 @@
= form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f|
%p
%strong= _('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.')
+ = link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'removing-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
= button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 153235c37d2..0998cd480d3 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -2,7 +2,7 @@
%section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
%p= _('Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/_stat_anchor_list.html.haml b/app/views/projects/_stat_anchor_list.html.haml
index 8a93d93a538..13ff8abe499 100644
--- a/app/views/projects/_stat_anchor_list.html.haml
+++ b/app/views/projects/_stat_anchor_list.html.haml
@@ -6,4 +6,4 @@
- anchors.each do |anchor|
%li.nav-item
= link_to_if(anchor.link, anchor.label, anchor.link, stat_anchor_attrs(anchor)) do
- .stat-text.d-flex.align-items-center{ class: ('btn btn-default disabled' if project_buttons) }= anchor.label
+ .stat-text.d-flex.align-items-center{ class: ('btn gl-button btn-default disabled' if project_buttons) }= anchor.label
diff --git a/app/views/projects/_transfer.html.haml b/app/views/projects/_transfer.html.haml
index eb7feb7bd3b..ee717c2deca 100644
--- a/app/views/projects/_transfer.html.haml
+++ b/app/views/projects/_transfer.html.haml
@@ -4,13 +4,14 @@
%h4.danger-title= _('Transfer project')
= form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f|
.form-group
- = label_tag :new_namespace_id, nil, class: 'label-bold' do
- %span= _('Select a new namespace')
- .form-group
- = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'transferring-an-existing-project-into-another-namespace') }
+ %p= _("Transfer your project into another namespace. %{link_start}Learn more.%{link_end}").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
%ul
%li= _("Be careful. Changing the project's namespace can have unintended side effects.")
%li= _('You can only transfer the project to namespaces you manage.')
%li= _('You will need to update your local repositories to point to the new location.')
%li= _('Project visibility level will be changed to match namespace rules when transferring to a group.')
+ = label_tag :new_namespace_id, _('Select a new namespace'), class: 'gl-font-weight-bold'
+ .form-group
+ = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
= f.submit 'Transfer project', class: "gl-button btn btn-danger js-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) }
diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml
index 182164d2175..990ac9fefb9 100644
--- a/app/views/projects/_visibility_modal.html.haml
+++ b/app/views/projects/_visibility_modal.html.haml
@@ -24,6 +24,6 @@
.form-group
= text_field_tag 'confirm_path_input', '', class: 'form-control js-confirm-danger-input qa-confirm-input'
.form-actions
- %button.btn.btn-default.gl-mr-4{ type: "button", "data-dismiss": "modal" }
+ %button.btn.gl-button.btn-default.gl-mr-4{ type: "button", "data-dismiss": "modal" }
= _('Cancel')
- = submit_tag _('Reduce project visibility'), class: "btn btn-danger js-confirm-danger-submit qa-confirm-button", disabled: true
+ = submit_tag _('Reduce project visibility'), class: "btn gl-button btn-danger js-confirm-danger-submit qa-confirm-button", disabled: true
diff --git a/app/views/projects/_wiki.html.haml b/app/views/projects/_wiki.html.haml
index 991c95153da..2669c4c0042 100644
--- a/app/views/projects/_wiki.html.haml
+++ b/app/views/projects/_wiki.html.haml
@@ -14,4 +14,4 @@
- if can_create_wiki
%p
= _("Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message.")
- = link_to _("Create your first page"), wiki_path(@project.wiki) + '?view=create', class: "btn btn-primary"
+ = link_to _("Create your first page"), wiki_path(@project.wiki) + '?view=create', class: "btn gl-button btn-primary"
diff --git a/app/views/projects/artifacts/_artifact.html.haml b/app/views/projects/artifacts/_artifact.html.haml
index 233a41a37b5..229de2f759c 100644
--- a/app/views/projects/artifacts/_artifact.html.haml
+++ b/app/views/projects/artifacts/_artifact.html.haml
@@ -50,12 +50,12 @@
.table-action-buttons
.btn-group
- if can?(current_user, :read_build, @project)
- = link_to download_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', download: '', title: _('Download artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Download artifacts') }, class: 'gl-button btn btn-build has-tooltip ml-0' do
- = sprite_icon('download')
+ = link_to download_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', download: '', title: _('Download artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Download artifacts') }, class: 'gl-button btn btn-default btn-icon has-tooltip' do
+ = sprite_icon('download', css_class: 'gl-icon')
- = link_to browse_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', title: _('Browse artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Browse artifacts') }, class: 'gl-button btn btn-build has-tooltip' do
- = sprite_icon('folder-open')
+ = link_to browse_project_job_artifacts_path(@project, artifact.job), rel: 'nofollow', title: _('Browse artifacts'), data: { placement: 'top', container: 'body' }, ref: 'tooltip', aria: { label: _('Browse artifacts') }, class: 'gl-button btn btn-default btn-icon has-tooltip' do
+ = sprite_icon('folder-open', css_class: 'gl-icon')
- if can?(current_user, :destroy_artifacts, @project)
- = link_to project_artifact_path(@project, artifact), data: { placement: 'top', container: 'body', confirm: _('Are you sure you want to delete these artifacts?') }, method: :delete, title: _('Delete artifacts'), ref: 'tooltip', aria: { label: _('Delete artifacts') }, class: 'gl-button btn btn-danger has-tooltip' do
- = sprite_icon('remove')
+ = link_to project_artifact_path(@project, artifact), data: { placement: 'top', container: 'body', confirm: _('Are you sure you want to delete these artifacts?') }, method: :delete, title: _('Delete artifacts'), ref: 'tooltip', aria: { label: _('Delete artifacts') }, class: 'gl-button btn btn-danger btn-icon has-tooltip' do
+ = sprite_icon('remove', css_class: 'gl-icon')
diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml
index 710417f90e3..e666bb237bd 100644
--- a/app/views/projects/blob/_breadcrumb.html.haml
+++ b/app/views/projects/blob/_breadcrumb.html.haml
@@ -23,13 +23,13 @@
- if blob.readable_text?
- if blame
= link_to 'Normal view', project_blob_path(@project, @id),
- class: 'gl-button btn'
+ class: 'gl-button btn btn-default'
- else
= link_to 'Blame', project_blame_path(@project, @id),
- class: 'gl-button btn js-blob-blame-link' unless blob.empty?
+ class: 'gl-button btn btn-default js-blob-blame-link' unless blob.empty?
= link_to 'History', project_commits_path(@project, @id),
- class: 'gl-button btn'
+ class: 'gl-button btn btn-default'
= link_to 'Permalink', project_blob_path(@project,
- tree_join(@commit.sha, @path)), class: 'gl-button btn js-data-file-blob-permalink-url'
+ tree_join(@commit.sha, @path)), class: 'gl-button btn btn-default js-data-file-blob-permalink-url'
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index b0317d84cdc..7d3a0c4a026 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -10,14 +10,14 @@
- if current_action?(:edit) || current_action?(:update)
%span.float-left.gl-mr-3
= text_field_tag 'file_path', (params[:file_path] || @path),
- class: 'form-control new-file-path js-file-path-name-input'
+ class: 'form-control gl-form-input new-file-path js-file-path-name-input'
= render 'template_selectors'
- if current_action?(:new) || current_action?(:create)
%span.float-left.gl-mr-3
\/
= text_field_tag 'file_name', params[:file_name], placeholder: "File name",
- required: true, class: 'form-control new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '')
+ required: true, class: 'form-control gl-form-input new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '')
= render 'template_selectors'
- if should_suggest_gitlab_ci_yml?
.js-suggest-gitlab-ci-yml{ data: { target: '#gitlab-ci-yml-selector',
@@ -36,8 +36,6 @@
%span.soft-wrap
= custom_icon('icon_soft_wrap')
Soft wrap
- .encoding-selector
- = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2', tabindex: '-1'
.file-editor.code
.js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true } }<
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index 6d01206a128..a7f13989ca7 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -2,23 +2,23 @@
.js-file-title.file-title-flex-parent
= render 'projects/blob/header_content', blob: blob
- .file-actions.gl-display-flex.gl-flex-fill-1.gl-align-self-start.gl-md-justify-content-end<
+ .file-actions.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-md-justify-content-end<
= render 'projects/blob/viewer_switcher', blob: blob unless blame
- if Feature.enabled?(:consolidated_edit_button, @project)
= render 'shared/web_ide_button', blob: blob
- else
= edit_blob_button(@project, @ref, @path, blob: blob)
= ide_edit_button(@project, @ref, @path, blob: blob)
- .btn-group.ml-2{ role: "group" }>
+ .btn-group{ role: "group", class: ("gl-ml-3" if current_user) }>
= render_if_exists 'projects/blob/header_file_locks_link'
- if current_user
= replace_blob_link(@project, @ref, @path, blob: blob)
= delete_blob_link(@project, @ref, @path, blob: blob)
- .btn-group.ml-2{ role: "group" }
+ .btn-group.gl-ml-3{ role: "group" }
= copy_blob_source_button(blob) unless blame
= open_raw_blob_button(blob)
= download_blob_button(blob)
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
-= render 'projects/fork_suggestion'
+= render_fork_suggestion
= render_if_exists 'projects/blob/header_file_locks', project: @project, path: @path
diff --git a/app/views/projects/blob/_viewer_switcher.html.haml b/app/views/projects/blob/_viewer_switcher.html.haml
index c6b13deaece..043b8629289 100644
--- a/app/views/projects/blob/_viewer_switcher.html.haml
+++ b/app/views/projects/blob/_viewer_switcher.html.haml
@@ -2,11 +2,11 @@
- simple_viewer = blob.simple_viewer
- rich_viewer = blob.rich_viewer
- .btn-group.js-blob-viewer-switcher.ml-2{ role: "group" }>
+ .btn-group.js-blob-viewer-switcher.gl-ml-3{ role: "group" }>
- simple_label = "Display #{simple_viewer.switcher_title}"
- %button.btn.gl-button.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
+ %button.btn.gl-button.btn-default.btn-icon.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
= sprite_icon(simple_viewer.switcher_icon)
- rich_label = "Display #{rich_viewer.switcher_title}"
- %button.btn.gl-button.btn-default.btn-sm.js-blob-viewer-switch-btn.gl-mr-3.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
+ %button.btn.gl-button.btn-default.btn-icon.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
= sprite_icon(rich_viewer.switcher_icon)
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index dc4172e2f09..fcf073e1e09 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -8,13 +8,13 @@
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name gl-ml-3 qa-branch-name' do
= branch.name
- if branch.name == @repository.root_ref
- %span.badge.badge-primary.gl-ml-2 default
+ %span.badge.gl-badge.sm.badge-pill.badge-primary.gl-ml-2 default
- elsif merged
- %span.badge.badge-info.has-tooltip.gl-ml-2{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
+ %span.badge.gl-badge.sm.badge-pill.badge-info.has-tooltip.gl-ml-2{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
= s_('Branches|merged')
- if protected_branch?(@project, branch)
- %span.badge.badge-success.gl-ml-2
+ %span.badge.gl-badge.sm.badge-pill.badge-success.gl-ml-2
= s_('Branches|protected')
= render_if_exists 'projects/branches/diverged_from_upstream', branch: branch
@@ -50,10 +50,10 @@
- if can?(current_user, :push_code, @project)
- if branch.name == @project.repository.root_ref
- %button{ class: "gl-button btn btn-danger remove-row has-tooltip disabled",
- disabled: true,
- title: s_('Branches|The default branch cannot be deleted') }
- = sprite_icon("remove")
+ - delete_default_branch_tooltip = s_('Branches|The default branch cannot be deleted')
+ %span.has-tooltip{ title: delete_default_branch_tooltip }
+ %button{ class: "gl-button btn btn-danger remove-row disabled", disabled: true, 'aria-label' => delete_default_branch_tooltip }
+ = sprite_icon("remove")
- elsif protected_branch?(@project, branch)
- if can?(current_user, :push_to_delete_protected_branch, @project)
%button{ class: "gl-button btn btn-danger remove-row has-tooltip",
@@ -65,10 +65,10 @@
is_merged: ("true" if merged) } }
= sprite_icon("remove")
- else
- %button{ class: "gl-button btn btn-danger remove-row has-tooltip disabled",
- disabled: true,
- title: s_('Branches|Only a project maintainer or owner can delete a protected branch') }
- = sprite_icon("remove")
+ - delete_protected_branch_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
+ %span.has-tooltip{ title: delete_protected_branch_tooltip }
+ %button{ class: "gl-button btn btn-danger remove-row disabled", disabled: true, 'aria-label' => delete_protected_branch_tooltip }
+ = sprite_icon("remove")
- else
= link_to project_branch_path(@project, branch.name),
class: "gl-button btn btn-danger remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 46cce59f67a..beccf458138 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -60,7 +60,10 @@
%ul.content-list.all-branches
- @branches.each do |branch|
= render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
- = paginate @branches, theme: 'gitlab'
+ - if Feature.enabled?(:branches_pagination_without_count, @project, default_enabled: true)
+ = render('kaminari/gitlab/without_count', previous_path: @prev_path, next_path: @next_path)
+ - else
+ = paginate @branches, theme: 'gitlab'
- else
.nothing-here-block
= s_('Branches|No branches to show')
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index 938dfc69500..0ec47744fc9 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -6,9 +6,9 @@
%span.gl-mr-2.js-clone-dropdown-label
= _('Clone')
= sprite_icon("chevron-down", css_class: "icon")
- %ul.p-3.dropdown-menu.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options{ class: dropdown_class }
+ %ul.dropdown-menu.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options{ class: dropdown_class }
- if ssh_enabled?
- %li
+ %li{ class: 'gl-px-4!' }
%label.label-bold
= _('Clone with SSH')
.input-group
@@ -17,7 +17,7 @@
= clipboard_button(target: '#ssh_project_clone', title: _("Copy URL"), class: "input-group-text btn-default btn-clipboard")
= render_if_exists 'projects/buttons/geo'
- if http_enabled?
- %li.pt-2
+ %li.pt-2{ class: 'gl-px-4!' }
%label.label-bold
= _('Clone with %{http_label}') % { http_label: gitlab_config.protocol.upcase }
.input-group
@@ -25,4 +25,15 @@
.input-group-append
= clipboard_button(target: '#http_project_clone', title: _("Copy URL"), class: "input-group-text btn-default btn-clipboard")
= render_if_exists 'projects/buttons/geo'
+ %li.divider.mt-2
+ %li.pt-2.gl-new-dropdown-item
+ %label.label-bold{ class: 'gl-px-4!' }
+ = _('Open in your IDE')
+ %a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + CGI.escape(project.http_url_to_repo) }
+ .gl-new-dropdown-item-text-wrapper
+ = _('Visual Studio Code')
+ - if show_xcode_link?(@project)
+ %a.dropdown-item.open-with-link{ href: xcode_uri_to_repo(@project) }
+ .gl-new-dropdown-item-text-wrapper
+ = _("Xcode")
= render_if_exists 'projects/buttons/kerberos_clone_field'
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index 0fcbf2ca1eb..3071e5ea5f8 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -3,7 +3,7 @@
- if !project.empty_repo? && can?(current_user, :download_code, project)
- archive_prefix = "#{project.path}-#{ref.tr('/', '-')}"
.project-action-button.dropdown.inline>
- %button.gl-button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
+ %button.gl-button.btn.btn-default.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
= sprite_icon('download')
%span.sr-only= _('Select Archive Format')
= sprite_icon("chevron-down")
diff --git a/app/views/projects/buttons/_download_links.html.haml b/app/views/projects/buttons/_download_links.html.haml
index c997df578c0..f6084cfcde8 100644
--- a/app/views/projects/buttons/_download_links.html.haml
+++ b/app/views/projects/buttons/_download_links.html.haml
@@ -1,4 +1,4 @@
.btn-group.ml-0.w-100
- Gitlab::Workhorse::ARCHIVE_FORMATS.each_with_index do |fmt, index|
- archive_path = project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt)
- = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-xs #{"btn-primary" if index == 0}"
+ = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? "btn-confirm" : "btn-default"}"
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index dbe0bf35b98..fad168da71e 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -7,11 +7,11 @@
%span= s_('ProjectOverview|Fork')
- else
- can_create_fork = current_user.can?(:create_fork)
- = link_to new_project_fork_path(@project),
- class: "btn btn-default btn-xs has-tooltip count-badge-button d-flex align-items-center fork-btn #{'has-tooltip disabled' unless can_create_fork}",
- title: (s_('ProjectOverview|You have reached your project limit') unless can_create_fork) do
- = sprite_icon('fork', css_class: 'icon')
- %span= s_('ProjectOverview|Fork')
+ - disabled_fork_tooltip = s_('ProjectOverview|You have reached your project limit')
+ %span.has-tooltip{ title: (disabled_fork_tooltip unless can_create_fork) }
+ = link_to new_project_fork_path(@project), class: "btn btn-default btn-xs count-badge-button d-flex align-items-center fork-btn #{' disabled' unless can_create_fork }", 'aria-label' => (disabled_fork_tooltip unless can_create_fork) do
+ = sprite_icon('fork', css_class: 'icon')
+ %span= s_('ProjectOverview|Fork')
%span.fork-count.count-badge-count.d-flex.align-items-center
= link_to project_forks_path(@project), title: n_(s_('ProjectOverview|Fork'), s_('ProjectOverview|Forks'), @project.forks_count), class: 'count' do
= @project.forks_count
diff --git a/app/views/projects/buttons/_remove_tag.html.haml b/app/views/projects/buttons/_remove_tag.html.haml
index ae776e93203..68a9d715674 100644
--- a/app/views/projects/buttons/_remove_tag.html.haml
+++ b/app/views/projects/buttons/_remove_tag.html.haml
@@ -2,5 +2,5 @@
- tag = local_assigns.fetch(:tag, nil)
- return unless project && tag
-%button{ type: "button", class: "js-remove-tag js-confirm-modal-button gl-button btn btn-danger remove-row has-tooltip gl-ml-3 #{protected_tag?(project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), data: { container: 'body', path: project_tag_path(@project, tag.name), modal_attributes: delete_tag_modal_attributes(tag.name) } }
+%button{ type: "button", class: "js-remove-tag js-confirm-modal-button gl-button btn btn-danger btn-icon remove-row has-tooltip gl-ml-3 #{protected_tag?(project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), data: { container: 'body', path: project_tag_path(@project, tag.name), modal_attributes: delete_tag_modal_attributes(tag.name) } }
= sprite_icon("remove")
diff --git a/app/views/projects/buttons/_xcode_link.html.haml b/app/views/projects/buttons/_xcode_link.html.haml
deleted file mode 100644
index e0f47f1ca3d..00000000000
--- a/app/views/projects/buttons/_xcode_link.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-%a.gl-button.btn.btn-default{ href: xcode_uri_to_repo(@project) }
- = _("Open in Xcode")
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 017c804ced0..0cc595de7be 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -98,35 +98,35 @@
%td
.gl-display-flex
- - if can?(current_user, :read_job_artifacts, job) && job.artifacts?
- = link_to download_project_job_artifacts_path(job.project, job), rel: 'nofollow', download: '', title: _('Download artifacts'), class: 'btn btn-build gl-button btn-icon btn-svg' do
- = sprite_icon('download')
- - if can?(current_user, :update_build, job)
- - if job.active?
- = link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: _('Cancel'), class: 'btn gl-button btn-build' do
- = sprite_icon('close')
- - elsif job.scheduled?
- .btn-group
- .btn.gl-button.btn-default{ disabled: true }
- = sprite_icon('planning')
+ .btn-group
+ - if can?(current_user, :read_job_artifacts, job) && job.artifacts?
+ = link_to download_project_job_artifacts_path(job.project, job), rel: 'nofollow', download: '', title: _('Download artifacts'), class: 'gl-button btn btn-default btn-icon' do
+ = sprite_icon('download', css_class: 'gl-icon')
+ - if can?(current_user, :update_build, job)
+ - if job.active?
+ = link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: _('Cancel'), class: 'gl-button btn btn-default btn-icon' do
+ = sprite_icon('close', css_class: 'gl-icon')
+ - elsif job.scheduled?
+ .gl-button.btn.btn-default.btn-icon.disabled{ disabled: true }
+ = sprite_icon('planning', css_class: 'gl-icon')
%time.js-remaining-time{ datetime: job.scheduled_at.utc.iso8601 }
= duration_in_numbers(job.execute_in)
- confirmation_message = s_("DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes.") % { job_name: job.name }
= link_to play_project_job_path(job.project, job, return_to: request.original_url),
method: :post,
title: s_('DelayedJobs|Start now'),
- class: 'btn gl-button btn-default btn-build has-tooltip',
+ class: 'gl-button btn btn-default btn-icon has-tooltip',
data: { confirm: confirmation_message } do
- = sprite_icon('play')
+ = sprite_icon('play', css_class: 'gl-icon')
= link_to unschedule_project_job_path(job.project, job, return_to: request.original_url),
method: :post,
title: s_('DelayedJobs|Unschedule'),
- class: 'btn gl-button btn-default btn-build has-tooltip' do
- = sprite_icon('time-out')
- - elsif allow_retry
- - if job.playable? && !admin && can?(current_user, :update_build, job)
- = link_to play_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: _('Play'), class: 'btn gl-button btn-build' do
- = custom_icon('icon_play')
- - elsif job.retryable?
- = link_to retry_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: _('Retry'), class: 'btn btn-build gl-button btn-icon btn-default' do
- = sprite_icon('repeat', css_class: 'gl-icon')
+ class: 'gl-button btn btn-default btn-icon has-tooltip' do
+ = sprite_icon('time-out', css_class: 'gl-icon')
+ - elsif allow_retry
+ - if job.playable? && !admin && can?(current_user, :update_build, job)
+ = link_to play_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: _('Play'), class: 'gl-button btn btn-default btn-icon' do
+ = sprite_icon('play', css_class: 'gl-icon')
+ - elsif job.retryable?
+ = link_to retry_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: _('Retry'), class: 'gl-button btn btn-default btn-icon' do
+ = sprite_icon('repeat', css_class: 'gl-icon')
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index 37ec63cc871..e693082461f 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -6,7 +6,10 @@
%button.btn.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
%p
- = _("Clean up after running %{filter_repo} on the repository" % { filter_repo: link_to_filter_repo }).html_safe
+ - link_url = 'https://github.com/newren/git-filter-repo'
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: link_url }
+ - link_end = '</a>'.html_safe
+ = _("Clean up after running %{link_start}git filter-repo%{link_end} on the repository.").html_safe % { link_start: link_start, link_end: link_end }
= link_to sprite_icon('question-o'),
help_page_path('user/project/repository/reducing_the_repo_size_using_git.md'),
target: '_blank', rel: 'noopener noreferrer'
@@ -24,6 +27,6 @@
= _("No file selected")
= f.file_field :bfg_object_map, class: "hidden js-object-map-input", required: true
.form-text.text-muted
- = _("The maximum file size allowed is %{size}.") % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
+ = _("The maximum file size is %{size}.") % { size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) }
= f.submit _('Start cleanup'), class: 'gl-button btn btn-success'
diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml
index 69b20fbc6d0..bda8ec39e81 100644
--- a/app/views/projects/commit/_change.html.haml
+++ b/app/views/projects/commit/_change.html.haml
@@ -1,25 +1,24 @@
- case type.to_s
- when 'revert'
- - label = s_('ChangeTypeAction|Revert')
- - branch_label = s_('ChangeTypeActionLabel|Revert in branch')
- revert_merge_request = _('Revert this merge request')
- revert_commit = _('Revert this commit')
- - description = s_('ChangeTypeAction|This will create a new commit in order to revert the existing changes.')
- title = commit.merged_merge_request(current_user) ? revert_merge_request : revert_commit
- - if defined?(pajamas)
- .js-revert-commit-modal{ data: { title: title,
- endpoint: revert_namespace_project_commit_path(commit, namespace_id: @project.namespace.full_path, project_id: @project),
- branch: @project.default_branch,
- push_code: can?(current_user, :push_code, @project).to_s,
- branch_collaboration: @project.branch_allows_collaboration?(current_user, selected_branch).to_s,
- existing_branch: ERB::Util.html_escape(selected_branch),
- branches_endpoint: project_branches_path(@project) } }
- - else
- = render "projects/commit/commit_modal", title: title, type: type, commit: commit, branch_label: branch_label, description: description, label: label
+ .js-revert-commit-modal{ data: { title: title,
+ endpoint: revert_namespace_project_commit_path(commit, namespace_id: @project.namespace.full_path, project_id: @project),
+ branch: @project.default_branch,
+ push_code: can?(current_user, :push_code, @project).to_s,
+ branch_collaboration: @project.branch_allows_collaboration?(current_user, selected_branch).to_s,
+ existing_branch: ERB::Util.html_escape(selected_branch),
+ branches_endpoint: project_branches_path(@project) } }
- when 'cherry-pick'
- - label = s_('ChangeTypeAction|Cherry-pick')
- - branch_label = s_('ChangeTypeActionLabel|Pick into branch')
- title = commit.merged_merge_request(current_user) ? _('Cherry-pick this merge request') : _('Cherry-pick this commit')
- = render "projects/commit/commit_modal", title: title, type: type, commit: commit, branch_label: branch_label, description: description, label: label
+
+ .js-cherry-pick-commit-modal{ data: { title: title,
+ endpoint: cherry_pick_namespace_project_commit_path(commit, namespace_id: @project.namespace.full_path, project_id: @project),
+ branch: @project.default_branch,
+ push_code: can?(current_user, :push_code, @project).to_s,
+ branch_collaboration: @project.branch_allows_collaboration?(current_user, selected_branch).to_s,
+ existing_branch: ERB::Util.html_escape(selected_branch),
+ branches_endpoint: project_branches_path(@project) } }
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index e8d524daced..53b9fd733ec 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -22,13 +22,13 @@
.header-action-buttons
- if defined?(@notes_count) && @notes_count > 0
- %span.btn.disabled.gl-button.btn-icon.d-none.d-sm-inline.gl-mr-3.has-tooltip{ title: n_("%d comment on this commit", "%d comments on this commit", @notes_count) % @notes_count }
+ %span.btn.gl-button.btn-default.disabled.gl-button.btn-icon.d-none.d-sm-inline.gl-mr-3.has-tooltip{ title: n_("%d comment on this commit", "%d comments on this commit", @notes_count) % @notes_count }
= sprite_icon('comment')
= @notes_count
- = link_to project_tree_path(@project, @commit), class: "btn gl-button gl-mr-3 d-none d-md-inline" do
+ = link_to project_tree_path(@project, @commit), class: "btn gl-button btn-default gl-mr-3 d-none d-md-inline" do
#{ _('Browse files') }
.dropdown.inline
- %a.btn.gl-button.dropdown-toggle.qa-options-button.d-md-inline{ data: { toggle: "dropdown" } }
+ %a.btn.gl-button.btn-default.dropdown-toggle.qa-options-button.d-md-inline{ data: { toggle: "dropdown" } }
%span= _('Options')
= sprite_icon('chevron-down', css_class: 'gl-text-gray-500')
%ul.dropdown-menu.dropdown-menu-right
@@ -37,10 +37,10 @@
#{ _('Browse Files') }
- if can_collaborate && !@commit.has_been_reverted?(current_user)
%li.clearfix
- = revert_commit_link(@commit, project_commit_path(@project, @commit.id), pajamas: true)
+ = revert_commit_link
- if can_collaborate
%li.clearfix
- = cherry_pick_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false)
+ = cherry_pick_commit_link
- if can?(current_user, :push_code, @project)
%li.clearfix
= link_to s_('CreateTag|Tag'), new_project_tag_path(@project, ref: @commit)
@@ -48,8 +48,8 @@
%li.dropdown-header
#{ _('Download') }
- unless @commit.parents.length > 1
- %li= link_to s_('DownloadCommit|Email Patches'), project_commit_path(@project, @commit, format: :patch), class: "qa-email-patches"
- %li= link_to s_('DownloadCommit|Plain Diff'), project_commit_path(@project, @commit, format: :diff), class: "qa-plain-diff"
+ %li= link_to s_('DownloadCommit|Email Patches'), project_commit_path(@project, @commit, format: :patch), class: "qa-email-patches", rel: 'nofollow', download: ''
+ %li= link_to s_('DownloadCommit|Plain Diff'), project_commit_path(@project, @commit, format: :diff), class: "qa-plain-diff", rel: 'nofollow', download: ''
.commit-box{ data: { project_path: project_path(@project) } }
%h3.commit-title
diff --git a/app/views/projects/commit/_commit_modal.html.haml b/app/views/projects/commit/_commit_modal.html.haml
deleted file mode 100644
index a82d77fdc91..00000000000
--- a/app/views/projects/commit/_commit_modal.html.haml
+++ /dev/null
@@ -1,26 +0,0 @@
-.modal{ id: "modal-#{type}-commit", tabindex: -1 }
- .modal-dialog
- .modal-content
- .modal-header
- %h3.page-title= title
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": true } &times;
- .modal-body
- - if description
- %p= description
- = form_tag [type.underscore, @project, commit], method: :post, remote: false, class: "js-#{type}-form js-requires-input" do
- .form-group.branch
- = label_tag 'start_branch', branch_label, class: 'label-bold'
-
- = hidden_field_tag :start_branch, @project.default_branch, id: 'start_branch'
- = dropdown_tag(@project.default_branch, options: { title: s_("BranchSwitcherTitle|Switch branch"), filter: true, placeholder: s_("BranchSwitcherPlaceholder|Search branches"), toggle_class: 'js-project-refs-dropdown dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "start_branch", selected: @project.default_branch, start_branch: @project.default_branch, refs_url: project_branches_path(@project), submit_form_on_click: false } })
-
- - if can?(current_user, :push_code, @project)
- = render 'shared/new_merge_request_checkbox'
- - else
- = hidden_field_tag 'create_merge_request', 1, id: nil
- .form-actions
- = submit_tag label, class: 'gl-button btn btn-success'
- = link_to _("Cancel"), '#', class: "gl-button btn btn-cancel", "data-dismiss" => "modal"
-
- = render 'shared/projects/edit_information'
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index 8004a5facd7..7c896cd71ef 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -28,7 +28,7 @@
= _('GPG Key ID:')
%span.monospace= signature.gpg_key_primary_keyid
- = link_to(_('Learn more about signing commits'), help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
+ = link_to(_('Learn more about signing commits'), help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link gl-display-block')
%a{ role: 'button', tabindex: 0, class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } }
= label
diff --git a/app/views/projects/commit/pipelines.html.haml b/app/views/projects/commit/pipelines.html.haml
index 0dbd6e53212..cd49dd899a0 100644
--- a/app/views/projects/commit/pipelines.html.haml
+++ b/app/views/projects/commit/pipelines.html.haml
@@ -4,3 +4,7 @@
= render 'commit_box'
= render 'ci_menu'
= render 'projects/commit/pipelines_list', endpoint: pipelines_project_commit_path(@project, @commit.id)
+
+- if can_collaborate_with_project?(@project)
+ = render "projects/commit/change", type: 'revert', commit: @commit
+ = render "projects/commit/change", type: 'cherry-pick', commit: @commit
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index e7b2e757ce4..5652b503a6d 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -12,10 +12,10 @@
.container-fluid{ class: [limited_container_width, container_class] }
= render "commit_box"
= render "ci_menu"
- = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, diff_page_context: "is-commit"
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, diff_page_context: "is-commit", paginate_diffs: true
.limited-width-notes
= render "shared/notes/notes_with_form", :autocomplete => true
- if can_collaborate_with_project?(@project)
- = render "projects/commit/change", type: 'revert', commit: @commit, pajamas: true
- = render "projects/commit/change", type: 'cherry-pick', commit: @commit, title: @commit.title
+ = render "projects/commit/change", type: 'revert', commit: @commit
+ = render "projects/commit/change", type: 'cherry-pick', commit: @commit
diff --git a/app/views/projects/commits/_commit.atom.builder b/app/views/projects/commits/_commit.atom.builder
index 640b5ecf99e..8a27649af50 100644
--- a/app/views/projects/commits/_commit.atom.builder
+++ b/app/views/projects/commits/_commit.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.entry do
xml.id project_commit_url(@project, id: commit.id)
xml.link href: project_commit_url(@project, id: commit.id)
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 179b0c5efbd..c708efe7c7b 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -32,7 +32,7 @@
&middot;
= commit.short_id
- if commit.description? && collapsible
- %button.text-expander.js-toggle-button
+ %button.gl-button.btn.btn-default.button-ellipsis-horizontal.btn-sm.gl-ml-2.text-expander.js-toggle-button
= sprite_icon('ellipsis_h', size: 12)
.committer
diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder
index a9b77631474..a4db3c47f59 100644
--- a/app/views/projects/commits/show.atom.builder
+++ b/app/views/projects/commits/show.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.title "#{@project.name}:#{@ref} commits"
xml.link href: project_commits_url(@project, @ref, rss_url_options), rel: "self", type: "application/atom+xml"
xml.link href: project_commits_url(@project, @ref), rel: "alternate", type: "text/html"
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index a14f75259ec..802df664241 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -24,9 +24,9 @@
.control
= form_tag(project_commits_path(@project, @id), method: :get, class: 'commits-search-form js-signature-container', data: { 'signatures-path' => namespace_project_signatures_path }) do
- = search_field_tag :search, params[:search], { placeholder: _('Search by message'), id: 'commits-search', class: 'form-control gl-form-input input-short gl-mt-3 gl-sm-mt-0 gl-min-w-full gl-inset-border-1-gray-200!', spellcheck: false }
+ = search_field_tag :search, params[:search], { placeholder: _('Search by message'), id: 'commits-search', class: 'form-control gl-form-input input-short gl-mt-3 gl-sm-mt-0 gl-min-w-full', spellcheck: false }
.control.d-none.d-md-block
- = link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn gl-button btn-svg' do
+ = link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn gl-button btn-default btn-icon' do
= sprite_icon('rss', css_class: 'qa-rss-icon')
= render_if_exists 'projects/commits/mirror_status'
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index 0c0530110c5..17134613b17 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -1,7 +1,4 @@
= form_tag project_compare_index_path(@project), method: :post, class: 'form-inline js-requires-input js-signature-container', data: { 'signatures-path' => signatures_namespace_project_compare_index_path } do
- - if params[:to] && params[:from]
- .compare-switch-container
- = link_to sprite_icon('substitute'), { from: params[:to], to: params[:from] }, class: 'commits-compare-switch has-tooltip btn gl-button btn-white', title: 'Swap revisions'
.form-group.dropdown.compare-form-group.to.js-compare-to-dropdown
.input-group.inline-input-group
%span.input-group-prepend
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index e45ea209e8c..3f9aa24a569 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -13,4 +13,8 @@
= 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
- = render "form"
+ #js-compare-selector{ data: { project_compare_index_path: project_compare_index_path(@project),
+ refs_project_path: refs_project_path(@project),
+ params_from: params[:from], params_to: params[:to],
+ project_merge_request_path: @merge_request.present? ? project_merge_request_path(@project, @merge_request) : '',
+ create_mr_path: create_mr_button? ? create_mr_path : '' } }
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index a1c7f5027c5..0c7649e93d7 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -2,11 +2,11 @@
%section.settings.no-animate#default-branch-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4= _('Default Branch')
+ %h4= _('Default branch')
%button.btn.js-settings-toggle
= expanded ? _('Collapse') : _('Expand')
%p
- = _('Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one.')
+ = _('Set the default branch for this project. All merge requests and commits are made against this branch unless you specify a different one.')
.settings-content
= form_for @project, remote: true, html: { multipart: true, anchor: 'default-branch-settings' }, authenticity_token: true do |f|
@@ -16,7 +16,7 @@
= _('A default branch cannot be chosen for an empty project.')
- else
.form-group
- = f.label :default_branch, "Default Branch", class: 'label-bold'
+ = f.label :default_branch, "Default branch", class: 'label-bold'
= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'})
.form-group
@@ -25,7 +25,7 @@
= f.label :autoclose_referenced_issues, class: 'form-check-label' do
%strong= _("Auto-close referenced issues on default branch")
.form-text.text-muted
- = _("Issues referenced by merge requests and commits within the default branch will be closed automatically")
+ = _("When merge requests and commits in the default branch close, any issues they reference also close.")
= link_to sprite_icon('question-o'), help_page_path('user/project/issues/managing_issues.md', anchor: 'disabling-automatic-issue-closing'), target: '_blank'
= f.submit _('Save changes'), class: "gl-button btn btn-success"
diff --git a/app/views/projects/deployments/_rollback.haml b/app/views/projects/deployments/_rollback.haml
index c5e884473ff..78972a5b7b9 100644
--- a/app/views/projects/deployments/_rollback.haml
+++ b/app/views/projects/deployments/_rollback.haml
@@ -1,8 +1,8 @@
- if deployment.deployable && can?(current_user, :create_deployment, deployment)
- tooltip = deployment.last? ? s_('Environments|Re-deploy to environment') : s_('Environments|Rollback environment')
- = button_tag class: 'btn gl-button btn-default btn-build has-tooltip', type: 'button', data: { toggle: 'modal', target: "#confirm-rollback-modal-#{deployment.id}" }, title: tooltip do
+ = button_tag class: 'gl-button btn btn-default btn-icon has-tooltip', type: 'button', data: { toggle: 'modal', target: "#confirm-rollback-modal-#{deployment.id}" }, title: tooltip do
- if deployment.last?
- = sprite_icon('repeat')
+ = sprite_icon('repeat', css_class: 'gl-icon')
- else
- = sprite_icon('redo')
+ = sprite_icon('redo', css_class: 'gl-icon')
= render 'projects/deployments/confirm_rollback_modal', deployment: deployment
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 8364311796f..2f533b5848d 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -1,9 +1,10 @@
- environment = local_assigns.fetch(:environment, nil)
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
-- diff_files = diffs.diff_files
- diff_page_context = local_assigns.fetch(:diff_page_context, nil)
- load_diff_files_async = Feature.enabled?(:async_commit_diff_files, @project) && diff_page_context == "is-commit"
+- paginate_diffs = local_assigns.fetch(:paginate_diffs, false) && !load_diff_files_async && Feature.enabled?(:paginate_commit_view, @project, type: :development)
+- diff_files = conditionally_paginate_diff_files(diffs, paginate: paginate_diffs)
.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed
.files-changed-inner
@@ -27,7 +28,6 @@
- if render_overflow_warning?(diffs)
= render 'projects/diffs/warning', diff_files: diffs
-
.files{ data: { can_create_note: can_create_note } }
- if load_diff_files_async
- url = url_for(safe_params.merge(action: 'diff_files'))
@@ -36,3 +36,6 @@
%span.spinner.spinner-md
- else
= render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: diff_page_context }
+
+ - if paginate_diffs
+ = paginate(diff_files, theme: "gitlab")
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 18da238d445..4b198717790 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -16,7 +16,7 @@
- unless diff_file.submodule?
.file-actions.d-none.d-sm-block
- if diff_file.blob&.readable_text?
- = link_to '#', class: 'js-toggle-diff-comments gl-button btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do
+ = link_to '#', class: 'js-toggle-diff-comments btn gl-button active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do
= sprite_icon('comment')
\
- if editable_diff?(diff_file)
@@ -30,6 +30,6 @@
= view_file_button(diff_file.content_sha, diff_file.file_path, project)
= view_on_environment_button(diff_file.content_sha, diff_file.file_path, environment) if environment
- = render 'projects/fork_suggestion'
+ = render_fork_suggestion
= render 'projects/diffs/content', diff_file: diff_file
diff --git a/app/views/projects/diffs/viewers/_collapsed.html.haml b/app/views/projects/diffs/viewers/_collapsed.html.haml
index 94dcda38bd6..02f499144c0 100644
--- a/app/views/projects/diffs/viewers/_collapsed.html.haml
+++ b/app/views/projects/diffs/viewers/_collapsed.html.haml
@@ -1,5 +1,3 @@
-- diff_file = viewer.diff_file
-- url = url_for(safe_params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
-.nothing-here-block.diff-collapsed{ data: { diff_for_path: url } }
+.nothing-here-block.diff-collapsed{ data: { diff_for_path: collapsed_diff_url(viewer.diff_file) } }
= _("This diff is collapsed.")
%button.click-to-expand.btn.btn-link= _("Click to expand it.")
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index cde8a5f69dd..c26017ccb79 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -3,20 +3,20 @@
- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
-= render "shared/search_settings"
+- enable_search_settings
%section.settings.general-settings.no-animate.expanded#js-general-settings
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Naming, topics, avatar')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= _('Collapse')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= _('Collapse')
%p= _('Update your project name, topics, description, and avatar.')
.settings-content= render 'projects/settings/general'
%section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded), data: { qa_selector: 'visibility_features_permissions_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Visibility, project features, permissions')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
- %p= _('Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions.')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %p= _('Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji.')
.settings-content
= form_for @project, remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f|
@@ -25,12 +25,12 @@
.js-project-permissions-form
- if show_visibility_confirm_modal?(@project)
= render "visibility_modal"
- = f.submit _('Save changes'), class: "btn btn-success #{('js-confirm-danger' if show_visibility_confirm_modal?(@project))}", data: { qa_selector: 'visibility_features_permissions_save_button', check_field_name: ("project[visibility_level]" if show_visibility_confirm_modal?(@project)), check_compare_value: @project.visibility_level }
+ = f.submit _('Save changes'), class: "btn gl-button btn-success #{('js-confirm-danger' if show_visibility_confirm_modal?(@project))}", data: { qa_selector: 'visibility_features_permissions_save_button', check_field_name: ("project[visibility_level]" if show_visibility_confirm_modal?(@project)), check_compare_value: @project.visibility_level }
%section.qa-merge-request-settings.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)] }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Merge requests')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
= render_if_exists 'projects/merge_request_settings_description_text'
.settings-content
@@ -39,7 +39,7 @@
= form_for @project, remote: true, html: { multipart: true, class: "merge-request-settings-form js-mr-settings-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-settings' }
= render 'projects/merge_request_settings', form: f
- = f.submit _('Save changes'), class: "btn btn-succes qa-save-merge-request-changes rspec-save-merge-request-changes"
+ = f.submit _('Save changes'), class: "btn gl-button btn-success qa-save-merge-request-changes rspec-save-merge-request-changes"
= render_if_exists 'projects/merge_request_approvals_settings', expanded: expanded
@@ -48,7 +48,8 @@
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('ProjectSettings|Badges')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded ? _('Collapse') : _('Expand')
%p
= s_('ProjectSettings|Customize this project\'s badges.')
= link_to s_('ProjectSettings|What are badges?'), help_page_path('user/project/badges')
@@ -62,15 +63,17 @@
%section.qa-advanced-settings.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }= expanded ? _('Collapse') : _('Expand')
%p= _('Housekeeping, export, path, transfer, remove, archive.')
.settings-content
.sub-section
%h4= _('Housekeeping')
- %p= _('Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects.')
+ %p
+ = _('Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects.')
+ = link_to _('Learn more.'), help_page_path('administration/housekeeping'), target: '_blank', rel: 'noopener noreferrer'
= link_to _('Run housekeeping'), housekeeping_project_path(@project),
- method: :post, class: "btn btn-default"
+ method: :post, class: "btn gl-button btn-default"
= render 'export', project: @project
@@ -80,6 +83,13 @@
= render 'projects/errors'
= form_for @project do |f|
.form-group
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'renaming-a-repository') }
+ %p= _("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}").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ %ul
+ %li= _("Be careful. Renaming a project's repository can have unintended side effects.")
+ %li= _('You will need to update your local repositories to point to the new location.')
+ - if @project.deployment_platform.present?
+ %li= _('Your deployment services will be broken, you will need to manually fix the services after renaming.')
= f.label :path, _('Path'), class: 'label-bold'
.form-group
.input-group
@@ -87,12 +97,7 @@
.input-group-text
#{Gitlab::Utils.append_path(root_url, @project.namespace.full_path)}/
= f.text_field :path, class: 'form-control qa-project-path-field h-auto'
- %ul
- %li= _("Be careful. Renaming a project's repository can have unintended side effects.")
- %li= _('You will need to update your local repositories to point to the new location.')
- - if @project.deployment_platform.present?
- %li= _('Your deployment services will be broken, you will need to manually fix the services after renaming.')
- = f.submit _('Change path'), class: "btn btn-warning qa-change-path-button"
+ = f.submit _('Change path'), class: "gl-button btn btn-warning qa-change-path-button"
= render 'transfer', project: @project
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 2936eff45df..2c245c1a914 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -2,6 +2,9 @@
- default_branch_name = @project.default_branch || "master"
- @skip_current_level_breadcrumb = true
+= content_for :invite_members_sidebar do
+ = render partial: 'projects/invite_members_link'
+
= render partial: 'flash_messages', locals: { project: @project }
= render "home_panel"
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 067c987e721..5da9c25b780 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -6,5 +6,4 @@
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project),
"help-page-path" => help_page_path("ci/environments/index.md"),
- "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards"),
"project-path" => @project.full_path } }
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index 45d314a1088..ccef28a2cf3 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -14,5 +14,5 @@
%h5.gl-mt-0.gl-mb-0.gl-ml-3.gl-mr-3
= _("Select a namespace to fork the project")
= render 'fork_button', namespace: @own_namespace
- #fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json), can_create_project: current_user.can_create_project?.to_s } }
+ #fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json) } }
diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml
index a92b02701c5..40280e0787f 100644
--- a/app/views/projects/graphs/charts.html.haml
+++ b/app/views/projects/graphs/charts.html.haml
@@ -22,10 +22,10 @@
#{@daily_coverage_options[:base_params][:start_date].strftime('%b %d')}
- end_date = capture do
#{@daily_coverage_options[:base_params][:end_date].strftime('%b %d')}
- = (_("Code coverage statistics for master %{start_date} - %{end_date}") % {start_date: start_date, end_date: end_date})
+ = (_("Code coverage statistics for %{ref} %{start_date} - %{end_date}") % { ref: "<strong>#{h @ref}</strong>", start_date: start_date, end_date: end_date }).html_safe
- download_path = capture do
#{@daily_coverage_options[:download_path]}
- %a.btn.gl-button.btn-sm{ href: "#{download_path}?#{@daily_coverage_options[:base_params].to_query}" }
+ %a.btn.gl-button.btn-default.btn-sm{ href: "#{download_path}?#{@daily_coverage_options[:base_params].to_query}" }
%small
= _("Download raw data (.csv)")
#js-code-coverage-chart{ data: { graph_endpoint: "#{@daily_coverage_options[:graph_api_path]}?#{@daily_coverage_options[:base_params].to_query}" } }
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index c7508ef4d47..c62d4a35973 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -3,6 +3,6 @@
.sub-header-block.bg-gray-light.gl-p-5
.tree-ref-holder.inline.vertical-align-middle
= render 'shared/ref_switcher', destination: 'graphs'
- = link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn gl-button'
+ = link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn gl-button btn-default'
.js-contributors-graph{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json),'data-project-branch': current_ref }
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 008340a3fe7..d299d2846c6 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -47,17 +47,17 @@
.form-group
%label{ for: 'new-branch-name' }
= _('Branch name')
- %input#new-branch-name.js-branch-name.form-control{ type: 'text', placeholder: "#{@issue.to_branch_name}", value: "#{@issue.to_branch_name}" }
+ %input#new-branch-name.js-branch-name.form-control.gl-form-input{ type: 'text', placeholder: "#{@issue.to_branch_name}", value: "#{@issue.to_branch_name}" }
%span.js-branch-message.form-text
.form-group
%label{ for: 'source-name' }
= _('Source (branch or tag)')
- %input#source-name.js-ref.ref.form-control{ type: 'text', placeholder: "#{@project.default_branch}", value: "#{@project.default_branch}", data: { value: "#{@project.default_branch}" } }
+ %input#source-name.js-ref.ref.form-control.gl-form-input{ type: 'text', placeholder: "#{@project.default_branch}", value: "#{@project.default_branch}", data: { value: "#{@project.default_branch}" } }
%span.js-ref-message.form-text.text-muted
.form-group
- %button.btn.btn-success.js-create-target{ type: 'button', data: { action: 'create-mr' } }
+ %button.btn.gl-button.btn-success.js-create-target{ type: 'button', data: { action: 'create-mr' } }
= create_mr_text
- if can_create_confidential_merge_request?
diff --git a/app/views/projects/issues/import_csv/_button.html.haml b/app/views/projects/issues/import_csv/_button.html.haml
index e60460687a9..229eb0654a8 100644
--- a/app/views/projects/issues/import_csv/_button.html.haml
+++ b/app/views/projects/issues/import_csv/_button.html.haml
@@ -2,7 +2,7 @@
- can_edit = can?(current_user, :admin_project, @project)
.dropdown.btn-group
- %button.btn.gl-button.rounded-right.text-center{ class: ('has-tooltip' if type == :icon), title: (_('Import issues') if type == :icon),
+ %button.btn.gl-button.rounded-right.btn-default.btn-icon.text-center{ class: ('has-tooltip' if type == :icon), title: (_('Import issues') if type == :icon),
data: { toggle: 'dropdown', qa_selector: 'import_issues_button' }, 'aria-label' => _('Import issues'), 'aria-haspopup' => 'true', 'aria-expanded' => 'false' }
- if type == :icon
= sprite_icon('import')
diff --git a/app/views/projects/issues/index.atom.builder b/app/views/projects/issues/index.atom.builder
index 6566866be82..4de9c0ed34b 100644
--- a/app/views/projects/issues/index.atom.builder
+++ b/app/views/projects/issues/index.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop: disable CodeReuse/ActiveRecord
xml.title "#{@project.name} issues"
xml.link href: url_for(safe_params), rel: "self", type: "application/atom+xml"
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 842b3432991..dd66e00b813 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -3,6 +3,7 @@
- page_title _("Issues")
- new_issue_email = @project.new_issuable_address(current_user, 'issue')
- add_page_specific_style 'page_bundles/issues_list'
+- issuable_type = 'issue'
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues")
@@ -24,7 +25,8 @@
.issues-holder
= render 'issues'
- if new_issue_email
- = render 'projects/issuable_by_email', email: new_issue_email, issuable_type: 'issue'
+ .issuable-footer.text-center
+ .js-issueable-by-email{ data: { initial_email: new_issue_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
- else
- new_project_issue_button_path = @project.archived? ? false : new_project_issue_path(@project)
= render 'shared/empty_states/issues', new_project_issue_button_path: new_project_issue_button_path, show_import_button: true
diff --git a/app/views/projects/jobs/_table.html.haml b/app/views/projects/jobs/_table.html.haml
index b126b452dea..402f7ddb38d 100644
--- a/app/views/projects/jobs/_table.html.haml
+++ b/app/views/projects/jobs/_table.html.haml
@@ -1,7 +1,7 @@
- admin = local_assigns.fetch(:admin, false)
- if builds.blank?
- - if experiment_enabled?(:jobs_empty_state)
+ - if @project
.row.empty-state
.col-12
.svg-content.svg-250
@@ -12,7 +12,7 @@
= s_('Jobs|Use jobs to automate your tasks')
%p
= s_('Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project.')
- = link_to s_('Jobs|Create CI/CD configuration file'), help_page_path('ci/quick_start/README'), class: 'btn gl-button btn-info js-empty-state-button'
+ = link_to s_('Jobs|Create CI/CD configuration file'), @project.present(current_user: current_user).add_ci_yml_path, class: 'btn gl-button btn-info js-empty-state-button'
- else
.nothing-here-block= s_('Jobs|No jobs to show')
- else
diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index e14473708af..a0ec6002db7 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -7,9 +7,6 @@
.nav-controls
- if can?(current_user, :update_build, @project)
- - if !@repository.gitlab_ci_yml && !experiment_enabled?(:jobs_empty_state)
- = link_to s_('Pipelines|Get started with Pipelines'), help_page_path('ci/quick_start/README'), class: 'btn gl-button btn-info js-empty-state-button'
-
= link_to project_ci_lint_path(@project), class: 'btn gl-button btn-default' do
%span
= _('CI Lint')
diff --git a/app/views/projects/learn_gitlab/index.html.haml b/app/views/projects/learn_gitlab/index.html.haml
new file mode 100644
index 00000000000..d5fdbc10eb4
--- /dev/null
+++ b/app/views/projects/learn_gitlab/index.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _("Learn GitLab")
+- page_title _("Learn GitLab")
+
+#js-learn-gitlab-app{ data: { actions: onboarding_actions_data(@project).to_json } }
diff --git a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
index 3a8629b3b6e..5fa8f908122 100644
--- a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
+++ b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
@@ -3,7 +3,7 @@
- button_class = "btn gl-button #{!@merge_request.closed? && 'js-draft-toggle-button'}"
- toggle_class = "btn gl-button dropdown-toggle"
-.float-left.btn-group.gl-ml-3.gl-display-none.gl-display-md-flex
+.float-left.btn-group.gl-ml-3.gl-display-none.gl-md-display-flex
= link_to @merge_request.closed? ? reopen_issuable_path(@merge_request) : toggle_draft_merge_request_path(@merge_request), method: :put, class: "#{button_class} #{button_action_class}" do
- if @merge_request.closed?
= _('Reopen')
diff --git a/app/views/projects/merge_requests/_commits.html.haml b/app/views/projects/merge_requests/_commits.html.haml
index 178e57b08b3..ecf5df5d3b4 100644
--- a/app/views/projects/merge_requests/_commits.html.haml
+++ b/app/views/projects/merge_requests/_commits.html.haml
@@ -8,7 +8,7 @@
- if @project&.context_commits_enabled? && can_update_merge_request
%p
= _('Push commits to the source branch or add previously merged commits to review them.')
- %button.btn.btn-primary.add-review-item-modal-trigger{ type: "button", data: { commits_empty: 'true', context_commits_empty: 'true' } }
+ %button.btn.gl-button.btn-confirm.add-review-item-modal-trigger{ type: "button", data: { commits_empty: 'true', context_commits_empty: 'true' } }
= _('Add previously merged commits')
- else
%ol#commits-list.list-unstyled
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 4711143c900..b1463693fb4 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -55,7 +55,7 @@
- if merge_request.assignees.any?
%li.gl-display-flex.gl-align-items-center
= render 'shared/issuable/assignees', project: merge_request.project, issuable: merge_request
- - if Feature.enabled?(:merge_request_reviewers, @project, default_enabled: true) && merge_request.reviewers.any?
+ - if merge_request.reviewers.any?
%li.gl-display-flex.issuable-reviewers
= render 'shared/issuable/reviewers', project: merge_request.project, issuable: merge_request
= render 'projects/merge_requests/approvals_count', merge_request: merge_request
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 6a42f33db7d..61747fe2c8d 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -13,8 +13,8 @@
.detail-page-header.border-bottom-0.pt-0.pb-0
.detail-page-header-body
.issuable-status-box.status-box.js-mr-status-box{ class: status_box_class(@merge_request), data: { state: @merge_request.state } }
- = sprite_icon(state_icon_name, css_class: 'gl-display-block gl-display-sm-none!')
- %span.gl-display-none.gl-display-sm-block
+ = sprite_icon(state_icon_name, css_class: 'gl-display-block gl-sm-display-none!')
+ %span.gl-display-none.gl-sm-display-block
= state_human_name
.issuable-meta
@@ -26,7 +26,7 @@
.detail-page-header-actions.js-issuable-actions
.clearfix.dropdown
- %button.gl-button.btn.btn-default.float-left.gl-display-md-none.gl-w-full{ type: "button", data: { toggle: "dropdown" } }
+ %button.gl-button.btn.btn-default.float-left.gl-md-display-none.gl-w-full{ type: "button", data: { toggle: "dropdown" } }
Options
= sprite_icon('chevron-down', css_class: 'gl-text-gray-500')
.dropdown-menu.dropdown-menu-right
@@ -45,9 +45,9 @@
%li= link_to 'Report abuse', new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request))
- if can_update_merge_request
- = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-md-block btn gl-button btn-grouped js-issuable-edit qa-edit-button"
+ = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-md-block btn gl-button btn-default btn-grouped js-issuable-edit qa-edit-button"
- if can_update_merge_request && !are_close_and_open_buttons_hidden
= render 'projects/merge_requests/close_reopen_draft_report_toggle'
- elsif !@merge_request.merged?
- = link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'gl-display-none gl-display-md-block gl-button btn btn-warning-secondary float-right gl-ml-3', title: _('Report abuse')
+ = link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'gl-display-none gl-md-display-block gl-button btn btn-warning-secondary float-right gl-ml-3', title: _('Report abuse')
diff --git a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
index 15655e2b162..87356f33b1e 100644
--- a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
+++ b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
@@ -21,4 +21,4 @@
%button.btn.gl-button.btn-success.js-submit-button{ type: "button", "@click" => "commit()", ":disabled" => "!readyToCommit" }
%span {{commitButtonText}}
.col-6.text-right
- = link_to "Cancel", project_merge_request_path(@merge_request.project, @merge_request), class: "gl-button btn btn-cancel"
+ = link_to "Cancel", project_merge_request_path(@merge_request.project, @merge_request), class: "gl-button btn btn-default"
diff --git a/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml b/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
index 7294c5d321a..4ba5ec5795a 100644
--- a/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
+++ b/app/views/projects/merge_requests/conflicts/components/_diff_file_editor.html.haml
@@ -4,7 +4,7 @@
.discard-changes-alert
Are you sure you want to discard your changes?
.discard-actions
- %button.btn.btn-sm.btn-close{ "@click" => "acceptDiscardConfirmation(file)" } Discard changes
- %button.btn.btn-sm{ "@click" => "cancelDiscardConfirmation(file)" } Cancel
+ %button.btn.btn-sm.btn-danger-secondary.gl-button{ "@click" => "acceptDiscardConfirmation(file)" } Discard changes
+ %button.btn.btn-default.btn-sm.gl-button{ "@click" => "cancelDiscardConfirmation(file)" } Cancel
.editor-wrap{ ":class" => "classObject" }
.editor{ "style" => "height: 350px", data: { 'editor-loading': true } }
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index 36b1cf0796f..62a251c7015 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -1,6 +1,7 @@
- @can_bulk_update = can?(current_user, :admin_merge_request, @project)
- merge_project = merge_request_source_project_for_project(@project)
- new_merge_request_path = project_new_merge_request_path(merge_project) if merge_project
+- issuable_type = 'merge_request'
- page_title _("Merge Requests")
- new_merge_request_email = @project.new_issuable_address(current_user, 'merge_request')
@@ -21,6 +22,7 @@
.merge-requests-holder
= render 'merge_requests'
- if new_merge_request_email
- = render 'projects/issuable_by_email', email: new_merge_request_email, issuable_type: 'merge_request'
+ .issuable-footer.text-center
+ .js-issueable-by-email{ data: { initial_email: new_merge_request_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
- else
= render 'shared/empty_states/merge_requests', button_path: new_merge_request_path
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 849cfac825f..453a34d1e7a 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -56,10 +56,13 @@
= render "projects/merge_requests/widget"
= render "projects/merge_requests/awards_block"
- if mr_action === "show"
- - add_page_startup_api_call discussions_path(@merge_request)
+ - if Feature.enabled?(:paginated_notes, @project)
+ - add_page_startup_api_call notes_url
+ - else
+ - add_page_startup_api_call discussions_path(@merge_request)
- add_page_startup_api_call widget_project_json_merge_request_path(@project, @merge_request, format: :json)
- add_page_startup_api_call cached_widget_project_json_merge_request_path(@project, @merge_request, format: :json)
- #js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request).to_json,
+ #js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request, Feature.enabled?(:paginated_notes, @project)).to_json,
noteable_data: serialize_issuable(@merge_request, serializer: 'noteable'),
noteable_type: 'MergeRequest',
target_type: 'merge_request',
@@ -75,7 +78,7 @@
- if mr_action === "diffs"
- add_page_startup_api_call @endpoint_metadata_url
- params = request.query_parameters
- - if Feature.enabled?(:default_merge_ref_for_diffs, @project)
+ - if Feature.enabled?(:default_merge_ref_for_diffs, @project, default_enabled: :yaml)
- params = params.merge(diff_head: true)
= render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: { "is-locked": @merge_request.discussion_locked?,
endpoint: diffs_project_merge_request_path(@project, @merge_request, 'json', params),
@@ -100,8 +103,8 @@
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch
- if @merge_request.can_be_reverted?(current_user)
- = render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
+ = render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit
- if @merge_request.can_be_cherry_picked?
- = render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit, title: @merge_request.title
+ = render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit
#js-review-bar
diff --git a/app/views/projects/merge_requests/widget/_commit_change_content.html.haml b/app/views/projects/merge_requests/widget/_commit_change_content.html.haml
index ad0ce7bf501..572d9e7578c 100644
--- a/app/views/projects/merge_requests/widget/_commit_change_content.html.haml
+++ b/app/views/projects/merge_requests/widget/_commit_change_content.html.haml
@@ -1,4 +1,4 @@
- if @merge_request.can_be_reverted?(current_user)
- = render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
+ = render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit
- if @merge_request.can_be_cherry_picked?
- = render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit, title: @merge_request.title
+ = render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index a21f519da0e..f6e4442d4fb 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -21,8 +21,8 @@
.form-actions
- if @milestone.new_record?
- = f.submit _('Create milestone'), class: 'btn-success btn', data: { qa_selector: 'create_milestone_button' }
+ = f.submit _('Create milestone'), class: 'gl-button btn-success btn', data: { qa_selector: 'create_milestone_button' }
= link_to _('Cancel'), project_milestones_path(@project), class: 'gl-button btn btn-cancel'
- else
- = f.submit _('Save changes'), class: 'btn-success btn'
+ = f.submit _('Save changes'), class: 'gl-button btn-success btn'
= link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'gl-button btn btn-cancel'
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index b964c8b1a93..c0df986e1ca 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -11,15 +11,14 @@
= link_to new_project_milestone_path(@project), class: 'gl-button btn btn-success', data: { qa_selector: "new_project_milestone_link" }, title: _('New milestone') do
= _('New milestone')
-.milestones
- #js-delete-milestone-modal
- #promote-milestone-modal
+- if @milestones.blank?
+ = render 'shared/empty_states/milestones'
+- else
+ .milestones
+ #js-delete-milestone-modal
+ #promote-milestone-modal
- %ul.content-list
- = render @milestones
+ %ul.content-list
+ = render @milestones
- - if @milestones.blank?
- %li
- .nothing-here-block= _('No milestones to show')
-
- = paginate @milestones, theme: 'gitlab'
+ = paginate @milestones, theme: 'gitlab'
diff --git a/app/views/projects/mirrors/_authentication_method.html.haml b/app/views/projects/mirrors/_authentication_method.html.haml
index 88bd7da7fef..94f8703657b 100644
--- a/app/views/projects/mirrors/_authentication_method.html.haml
+++ b/app/views/projects/mirrors/_authentication_method.html.haml
@@ -6,11 +6,11 @@
.select-wrapper
= f.select :auth_method,
options_for_select(auth_options, mirror.auth_method),
- {}, { class: "form-control select-control js-mirror-auth-type qa-authentication-method" }
+ {}, { class: "form-control gl-form-input select-control js-mirror-auth-type qa-authentication-method" }
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
= f.hidden_field :auth_method, value: "password", class: "js-hidden-mirror-auth-type"
.form-group
.well-password-auth.collapse.js-well-password-auth
= f.label :password, _("Password"), class: "label-bold"
- = f.password_field :password, value: mirror.password, class: 'form-control qa-password', autocomplete: 'new-password'
+ = f.password_field :password, value: mirror.password, class: 'form-control gl-form-input qa-password', autocomplete: 'new-password'
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 98d35845b31..d6ad6147e6e 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -21,7 +21,7 @@
.form-group.has-feedback
= label_tag :url, _('Git repository URL'), class: 'label-light'
- = text_field_tag :url, nil, class: 'form-control js-mirror-url js-repo-url qa-mirror-repository-url-input', placeholder: _('Input the remote repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", autocomplete: 'new-password'
+ = text_field_tag :url, nil, class: 'form-control gl-form-input js-mirror-url js-repo-url qa-mirror-repository-url-input', placeholder: _('Input the remote repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", autocomplete: 'new-password'
= render 'projects/mirrors/instructions'
diff --git a/app/views/projects/mirrors/_mirror_repos_form.html.haml b/app/views/projects/mirrors/_mirror_repos_form.html.haml
index 215d0a59d1b..dca01ebbe90 100644
--- a/app/views/projects/mirrors/_mirror_repos_form.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_form.html.haml
@@ -1,7 +1,7 @@
.form-group
= label_tag :mirror_direction, _('Mirror direction'), class: 'label-light'
.select-wrapper
- = select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control select-control js-mirror-direction qa-mirror-direction', disabled: true
+ = select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control gl-form-input select-control js-mirror-direction qa-mirror-direction', disabled: true
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
= render partial: "projects/mirrors/mirror_repos_push", locals: { f: f }
diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml
index 30ba22ba53c..774fbc79430 100644
--- a/app/views/projects/network/show.html.haml
+++ b/app/views/projects/network/show.html.haml
@@ -1,12 +1,12 @@
- breadcrumb_title _("Graph")
- page_title _("Graph"), @ref
= render "head"
-%div{ class: container_class }
+.gl-mt-5
.project-network.gl-border-1.gl-border-solid.gl-border-gray-300
.controls.gl-bg-gray-50.gl-p-2.gl-font-base.gl-text-gray-400.gl-border-b-1.gl-border-b-solid.gl-border-b-gray-300
= form_tag project_network_path(@project, @id), method: :get, class: 'form-inline network-form' do |f|
- = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: _("Git revision"), class: 'search-input form-control input-mx-250 search-sha'
- = button_tag class: 'btn btn-success' do
+ = text_field_tag :extended_sha1, @options[:extended_sha1], placeholder: _("Git revision"), class: 'search-input form-control gl-form-input input-mx-250 search-sha gl-mr-2'
+ = button_tag class: 'btn gl-button btn-success btn-icon' do
= sprite_icon('search')
.inline.gl-ml-5
.form-check.light
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 6af185696b0..45e7eae8c70 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -28,7 +28,7 @@
%p
%strong= _("Tip:")
= _("You can also create a project from the command line.")
- %a.push-new-project-tip{ data: { title: _("Push to create a project") }, href: help_page_path('gitlab-basics/create-project', anchor: 'push-to-create-a-new-project'), target: "_blank", rel: "noopener noreferrer" }
+ %a.push-new-project-tip{ data: { title: _("Push to create a project") }, href: help_page_path('user/project/working_with_projects', anchor: 'push-to-create-a-new-project'), target: "_blank", rel: "noopener noreferrer" }
= _("Show command")
%template.push-new-project-tip-template= render partial: "new_project_push_tip"
diff --git a/app/views/projects/no_repo.html.haml b/app/views/projects/no_repo.html.haml
index d7853c1b466..3c7afff57f6 100644
--- a/app/views/projects/no_repo.html.haml
+++ b/app/views/projects/no_repo.html.haml
@@ -12,17 +12,17 @@
#{ _('This means you can not push code until you create an empty repository or import existing one.') }
%hr
-= render_if_exists 'projects/invite_members_modal', project: @project
+= render 'projects/invite_members_modal', project: @project
.no-repo-actions
- = link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do
+ = link_to project_repository_path(@project), method: :post, class: 'btn gl-button btn-confirm' do
#{ _('Create empty repository') }
%strong.gl-ml-3.gl-mr-3 or
- = link_to new_project_import_path(@project), class: 'btn' do
+ = link_to new_project_import_path(@project), class: 'btn gl-button btn-default' do
#{ _('Import repository') }
- 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: "gl-button btn btn-danger btn-danger-secondary float-right"
+ = link_to _('Delete project'), project_path(@project), data: { confirm: remove_project_message(@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 a785e36fad5..d11b61466e2 100644
--- a/app/views/projects/notes/_actions.html.haml
+++ b/app/views/projects/notes/_actions.html.haml
@@ -39,15 +39,15 @@
- if can?(current_user, :award_emoji, note)
- if note.emoji_awardable?
.note-actions-item
- = button_tag title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji has-tooltip btn btn-transparent", data: { position: 'right', container: 'body' } do
- %span{ class: 'link-highlight award-control-icon-neutral' }= sprite_icon('slight-smile')
- %span{ class: 'link-highlight award-control-icon-positive' }= sprite_icon('smiley')
- %span{ class: 'link-highlight award-control-icon-super-positive' }= sprite_icon('smile')
+ = button_tag title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji has-tooltip btn gl-button btn-icon btn-default-tertiary btn-transparent", data: { position: 'right', container: 'body' } do
+ = sprite_icon('slight-smile', css_class: 'link-highlight award-control-icon-neutral gl-button-icon gl-icon gl-text-gray-400')
+ = sprite_icon('smiley', css_class: 'link-highlight award-control-icon-positive gl-button-icon gl-icon gl-left-3!')
+ = sprite_icon('smile', css_class: 'link-highlight award-control-icon-super-positive gl-button-icon gl-icon gl-left-3! ')
- if note_editable
- .note-actions-item
- = button_tag title: 'Edit comment', class: 'note-action-button js-note-edit has-tooltip btn btn-transparent', data: { container: 'body', qa_selector: 'edit_comment_button' } do
+ .note-actions-item.gl-ml-0
+ = button_tag title: 'Edit comment', class: 'note-action-button js-note-edit has-tooltip btn gl-button btn-default-tertiary btn-transparent gl-px-2!', data: { container: 'body', qa_selector: 'edit_comment_button' } do
%span.link-highlight
- = custom_icon('icon_pencil')
+ = sprite_icon('pencil', css_class: 'gl-button-icon gl-icon gl-text-gray-400 s16')
= render 'projects/notes/more_actions_dropdown', note: note, note_editable: note_editable
diff --git a/app/views/projects/notes/_more_actions_dropdown.html.haml b/app/views/projects/notes/_more_actions_dropdown.html.haml
index 8cf1b6b9294..c81a3683e90 100644
--- a/app/views/projects/notes/_more_actions_dropdown.html.haml
+++ b/app/views/projects/notes/_more_actions_dropdown.html.haml
@@ -1,10 +1,9 @@
- is_current_user = current_user == note.author
- if note_editable || !is_current_user
- .dropdown.more-actions.note-actions-item
- = button_tag title: 'More actions', class: 'note-action-button more-actions-toggle has-tooltip btn btn-transparent', data: { toggle: 'dropdown', container: 'body', qa_selector: 'more_actions_dropdown' } do
- %span.icon
- = custom_icon('ellipsis_v')
+ %div{ class: "dropdown more-actions note-actions-item gl-ml-0!" }
+ = button_tag title: 'More actions', class: 'note-action-button more-actions-toggle has-tooltip btn gl-button btn-default-tertiary btn-transparent gl-pl-2! gl-pr-0!', data: { toggle: 'dropdown', container: 'body', qa_selector: 'more_actions_dropdown' } do
+ = sprite_icon('ellipsis_v', css_class: 'gl-button-icon gl-icon gl-text-gray-400')
%ul.dropdown-menu.more-actions-dropdown.dropdown-open-left
%li
= clipboard_button(text: noteable_note_url(note), title: _('Copy reference'), button_text: _('Copy link'), class: 'btn-clipboard', hide_tooltip: true, hide_button_icon: true)
diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml
index e9ace8c72f1..ec3fc27dc20 100644
--- a/app/views/projects/pages/_use.html.haml
+++ b/app/views/projects/pages/_use.html.haml
@@ -4,7 +4,8 @@
= s_('GitLabPages|Configure pages')
.card-body
%p.gl-mb-0
- - link_start = "<a href='#{help_page_path('user/project/pages/index.md')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/index.md')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer'>".html_safe
+ - templates_link_start = "<a href='https://gitlab.com/gitlab-org/project-templates' target='_blank' rel='noopener noreferrer'>".html_safe
- link_end = '</a>'.html_safe
- = s_('GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}.').html_safe % { link_start: link_start,
- link_end: link_end }
+ = s_('GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}.').html_safe % { docs_link_start: docs_link_start, samples_link_start: samples_link_start, templates_link_start: templates_link_start, link_end: link_end }
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index ee0fe43e79c..8a369202555 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -39,5 +39,5 @@
= f.check_box :active, required: false, value: @schedule.active?
= f.label :active, _('Active'), class: 'gl-font-weight-normal'
.footer-block.row-content-block
- = f.submit _('Save pipeline schedule'), class: 'btn btn-success'
- = link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn btn-cancel'
+ = f.submit _('Save pipeline schedule'), class: 'btn gl-button btn-success'
+ = link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index 45aaf2b64bf..e17c905e092 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -27,14 +27,14 @@
%td
.float-right.btn-group
- if can?(current_user, :play_pipeline_schedule, pipeline_schedule)
- = link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('Play'), class: 'btn btn-svg gl-display-flex gl-align-items-center gl-justify-content-center' do
+ = link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('Play'), class: 'btn gl-button btn-default btn-svg' do
= sprite_icon('play')
- if can?(current_user, :take_ownership_pipeline_schedule, pipeline_schedule)
- = link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('PipelineSchedules|Take ownership'), class: 'btn' do
+ = link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('PipelineSchedules|Take ownership'), class: 'btn gl-button btn-default' do
= s_('PipelineSchedules|Take ownership')
- if can?(current_user, :update_pipeline_schedule, pipeline_schedule)
- = link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-display-flex' do
+ = link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-button btn-default' 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: 'gl-button btn btn-danger', 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', data: { confirm: _("Are you sure you want to delete this pipeline schedule?") } do
= sprite_icon('remove')
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index 90417a852d5..558c12c04e4 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -9,7 +9,7 @@
- if can?(current_user, :create_pipeline_schedule, @project)
.nav-controls
- = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-success' do
+ = link_to new_project_pipeline_schedule_path(@project), class: 'btn gl-button btn-success' do
%span= _('New schedule')
- if @schedules.present?
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 77aa537dfdb..4a10f6aee1c 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -28,6 +28,9 @@
- if @pipeline.latest?
%span.js-pipeline-url-latest.badge.badge-pill.gl-badge.sm.badge-success.has-tooltip{ title: _("Latest pipeline for the most recent commit on this branch") }
latest
+ - if @pipeline.merge_train_pipeline?
+ %span.js-pipeline-url-train.badge.badge-pill.gl-badge.sm.badge-info.has-tooltip{ title: _("This is a merge train pipeline") }
+ train
- if @pipeline.has_yaml_errors?
%span.js-pipeline-url-yaml.badge.badge-pill.gl-badge.sm.badge-danger.has-tooltip{ title: @pipeline.yaml_errors }
yaml invalid
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index b41c3f4fc27..904b3d6f483 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -1,15 +1,13 @@
- return if pipeline_has_errors
-- dag_pipeline_tab_enabled = Feature.enabled?(:dag_pipeline_tab, @project, default_enabled: true)
.tabs-holder
%ul.pipelines-tabs.nav-links.no-top.no-bottom.mobile-separator.nav.nav-tabs
%li.js-pipeline-tab-link
= link_to project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-pipeline', action: 'pipelines', toggle: 'tab' }, class: 'pipeline-tab' do
= _('Pipeline')
- - if dag_pipeline_tab_enabled
- %li.js-dag-tab-link
- = link_to dag_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-dag', action: 'dag', toggle: 'tab' }, class: 'dag-tab' do
- = _('Needs')
+ %li.js-dag-tab-link
+ = link_to dag_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-dag', action: 'dag', toggle: 'tab' }, class: 'dag-tab' do
+ = _('Needs')
%li.js-builds-tab-link
= link_to builds_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do
= _('Jobs')
@@ -69,7 +67,7 @@
= build.present.callout_failure_message
%td.responsive-table-cell.build-actions
- if can?(current_user, :update_build, job) && job.retryable?
- = link_to retry_project_job_path(build.project, build, return_to: request.original_url), method: :post, title: _('Retry'), class: 'btn btn-build gl-button btn-icon btn-default' do
+ = link_to retry_project_job_path(build.project, build, return_to: request.original_url), method: :post, title: _('Retry'), class: 'gl-button btn btn-default btn-icon' do
= sprite_icon('repeat', css_class: 'gl-icon')
- if can?(current_user, :read_build, job)
%tr.build-trace-row.responsive-table-border-end
@@ -79,11 +77,11 @@
%code.bash.js-build-output
= build_summary(build)
- - if dag_pipeline_tab_enabled
- #js-tab-dag.tab-pane
- #js-pipeline-dag-vue{ data: { pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, empty_svg_path: image_path('illustrations/empty-state/empty-dag-md.svg'), about_dag_doc_path: help_page_path('ci/directed_acyclic_graph/index.md'), dag_doc_path: help_page_path('ci/yaml/README.md', anchor: 'needs')} }
+ #js-tab-dag.tab-pane
+ #js-pipeline-dag-vue{ data: { pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, empty_svg_path: image_path('illustrations/empty-state/empty-dag-md.svg'), about_dag_doc_path: help_page_path('ci/directed_acyclic_graph/index.md'), dag_doc_path: help_page_path('ci/yaml/README.md', anchor: 'needs')} }
#js-tab-tests.tab-pane
#js-pipeline-tests-detail{ data: { summary_endpoint: summary_project_pipeline_tests_path(@project, @pipeline, format: :json),
- suite_endpoint: project_pipeline_test_path(@project, @pipeline, suite_name: ':suite_name', format: :json) } }
+ suite_endpoint: project_pipeline_test_path(@project, @pipeline, suite_name: 'suite', format: :json),
+ blob_path: project_blob_path(@project, @pipeline.sha) } }
= render_if_exists "projects/pipelines/tabs_content", pipeline: @pipeline, project: @project
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index b3ad210aa47..b431ef202b3 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -6,7 +6,7 @@
- add_page_specific_style 'page_bundles/reports'
- add_page_specific_style 'page_bundles/ci_status'
-- if Feature.enabled?(:graphql_pipeline_details, @project)
+- if Feature.enabled?(:graphql_pipeline_details, @project, default_enabled: :yaml) || Feature.enabled?(:graphql_pipeline_details_users, @current_user, default_enabled: :yaml)
- add_page_startup_graphql_call('pipelines/get_pipeline_details', { projectPath: @project.full_path, iid: @pipeline.iid })
.js-pipeline-container{ data: { controller_action: "#{controller.action_name}" } }
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index cf39ac4dd56..beb435d268a 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,10 +1,11 @@
- page_title _("Members")
- group = @project.group
+- vue_project_members_list_enabled = Feature.enabled?(:vue_project_members_list, @project, default_enabled: :yaml)
.js-remove-member-modal
.row.gl-mt-3
.col-lg-12
- - if invite_members_allowed?(group)
+ - if can_invite_members_for_project?(@project)
.row
.col-md-12.col-lg-6.gl-display-flex
.gl-flex-direction-column.gl-flex-wrap.align-items-baseline
@@ -19,7 +20,7 @@
.col-md-12.col-lg-6
.gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2.gl-mb-3
.js-invite-members-trigger.gl-px-2.gl-sm-w-auto.gl-w-full.gl-mb-4{ data: { classes: 'btn btn-success gl-button gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite members') } }
- = render_if_exists 'projects/invite_members_modal', project: @project
+ = render 'projects/invite_members_modal', project: @project
- else
- if project_can_be_shared?
@@ -31,7 +32,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 !invite_members_allowed?(group) && can_manage_project_members?(@project) && project_can_be_shared?
+ - if !can_invite_members_for_project?(@project) && can_manage_project_members?(@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' }
@@ -74,24 +75,44 @@
%span.badge.badge-pill= @requesters.count
.tab-content
#tab-members.tab-pane{ class: ('active' unless groups_tab_active?) }
- = render 'projects/project_members/team', project: @project, group: group, members: @project_members, current_user_is_group_owner: current_user_is_group_owner?(@project)
+ - if vue_project_members_list_enabled
+ .js-project-members-list{ data: project_members_list_data_attributes(@project, @project_members) }
+ .loading
+ .spinner.spinner-md
+ - else
+ = render 'projects/project_members/team', project: @project, group: group, members: @project_members, current_user_is_group_owner: current_user_is_group_owner?(@project)
= paginate @project_members, theme: "gitlab", params: { search_groups: nil }
- if show_groups?(@group_links)
#tab-groups.tab-pane{ class: ('active' if groups_tab_active?) }
- = render 'projects/project_members/groups', group_links: @group_links
+ - if vue_project_members_list_enabled
+ .js-project-group-links-list{ data: project_group_links_list_data_attributes(@project, @group_links) }
+ .loading
+ .spinner.spinner-md
+ - else
+ = render 'projects/project_members/groups', group_links: @group_links
- if show_invited_members?(@project, @invited_members)
#tab-invited-members.tab-pane
- .card.card-without-border
- = render 'shared/members/tab_pane/header' do
- = render 'shared/members/tab_pane/title' do
- = html_escape(_('Members invited to %{strong_start}%{project_name}%{strong_end}')) % { project_name: @project.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- %ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @invited_members, as: :member, locals: { membership_source: @project, group: group, current_user_is_group_owner: current_user_is_group_owner?(@project) }
+ - if vue_project_members_list_enabled
+ .js-project-invited-members-list{ data: project_members_list_data_attributes(@project, @invited_members) }
+ .loading
+ .spinner.spinner-md
+ - else
+ .card.card-without-border
+ = render 'shared/members/tab_pane/header' do
+ = render 'shared/members/tab_pane/title' do
+ = html_escape(_('Members invited to %{strong_start}%{project_name}%{strong_end}')) % { project_name: @project.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
+ %ul.content-list.members-list
+ = render partial: 'shared/members/member', collection: @invited_members, as: :member, locals: { membership_source: @project, group: group, current_user_is_group_owner: current_user_is_group_owner?(@project) }
- if show_access_requests?(@project, @requesters)
#tab-access-requests.tab-pane
- .card.card-without-border
- = render 'shared/members/tab_pane/header' do
- = render 'shared/members/tab_pane/title' do
- = html_escape(_('Users requesting access to %{strong_start}%{project_name}%{strong_end}')) % { project_name: @project.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- %ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @requesters, as: :member, locals: { membership_source: @project, group: group }
+ - if vue_project_members_list_enabled
+ .js-project-access-requests-list{ data: project_members_list_data_attributes(@project, @requesters) }
+ .loading
+ .spinner.spinner-md
+ - else
+ .card.card-without-border
+ = render 'shared/members/tab_pane/header' do
+ = render 'shared/members/tab_pane/title' do
+ = html_escape(_('Users requesting access to %{strong_start}%{project_name}%{strong_end}')) % { project_name: @project.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
+ %ul.content-list.members-list
+ = render partial: 'shared/members/member', collection: @requesters, as: :member, locals: { membership_source: @project, group: group }
diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml
index 33be875d9a6..20cd45be6da 100644
--- a/app/views/projects/protected_branches/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml
@@ -1,5 +1,3 @@
-- select_mode_for_dropdown = Feature.enabled?(:deploy_keys_on_protected_branches, @project) ? 'js-multiselect' : ''
-
- content_for :merge_access_levels do
.merge_access_levels-container
= dropdown_tag('Select',
@@ -9,7 +7,7 @@
- content_for :push_access_levels do
.push_access_levels-container
= dropdown_tag('Select',
- options: { toggle_class: "js-allowed-to-push qa-allowed-to-push-select #{select_mode_for_dropdown} wide",
+ options: { toggle_class: "js-allowed-to-push qa-allowed-to-push-select js-multiselect wide",
dropdown_class: 'dropdown-menu-selectable qa-allowed-to-push-dropdown rspec-allowed-to-push-dropdown capitalize-header',
data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }})
diff --git a/app/views/projects/protected_branches/shared/_index.html.haml b/app/views/projects/protected_branches/shared/_index.html.haml
index 66173c4759b..1d3e3fb11ae 100644
--- a/app/views/projects/protected_branches/shared/_index.html.haml
+++ b/app/views/projects/protected_branches/shared/_index.html.haml
@@ -3,7 +3,7 @@
%section.settings.no-animate#js-protected-branches-settings{ class: ('expanded' if expanded), data: { qa_selector: 'protected_branches_settings_content' } }
.settings-header
%h4
- Protected Branches
+ Protected branches
%button.btn.js-settings-toggle.qa-expand-protected-branches{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
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 d62e9513d56..02ec778b97c 100644
--- a/app/views/projects/protected_branches/shared/_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_protected_branch.html.haml
@@ -5,7 +5,7 @@
%span.ref-name= protected_branch.name
- if @project.root_ref?(protected_branch.name)
- %span.badge.badge-info.d-inline default
+ %span.badge.gl-badge.badge-pill.badge-info.d-inline default
%div
- if protected_branch.wildcard?
@@ -20,4 +20,4 @@
- if can_admin_project
%td
- = link_to 'Unprotect', [@project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning"
+ = link_to 'Unprotect', [@project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, 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 5734b7dc3c9..67eadd39ed6 100644
--- a/app/views/projects/protected_tags/shared/_index.html.haml
+++ b/app/views/projects/protected_tags/shared/_index.html.haml
@@ -3,7 +3,7 @@
%section.settings.no-animate#js-protected-tags-settings{ class: ('expanded' if expanded), data: { qa_selector: 'protected_tag_settings_content' } }
.settings-header
%h4
- Protected Tags
+ Protected tags
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
diff --git a/app/views/projects/protected_tags/shared/_tags_list.html.haml b/app/views/projects/protected_tags/shared/_tags_list.html.haml
index a5a43072744..f3cf4013898 100644
--- a/app/views/projects/protected_tags/shared/_tags_list.html.haml
+++ b/app/views/projects/protected_tags/shared/_tags_list.html.haml
@@ -23,7 +23,6 @@
%th
%tbody
%tr
- %td.flash-container{ colspan: 4 }
= yield
= paginate @protected_tags, theme: 'gitlab'
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 97bc366544f..a2009b96c0d 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -1,6 +1,6 @@
- page_title _("Container Registry")
- @content_class = "limit-container-width" unless fluid_layout
-- add_page_startup_graphql_call('container_registry/get_container_repositories', { fullPath: @project.full_path, first: 10, name: nil, isGroupPage: false} )
+- add_page_startup_graphql_call('container_registry/get_container_repositories', { fullPath: @project.full_path, first: 10, name: nil, isGroupPage: false, sort: nil} )
%section
#js-container-registry{ data: { endpoint: project_container_registry_index_path(@project),
@@ -19,4 +19,7 @@
"project_path": @project.full_path,
"gid_prefix": container_repository_gid_prefix,
"is_admin": current_user&.admin.to_s,
- character_error: @character_error.to_s } }
+ character_error: @character_error.to_s,
+ user_callouts_path: user_callouts_path,
+ user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
+ show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s, } }
diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml
index 9415516d6f6..6e46423cde0 100644
--- a/app/views/projects/runners/_group_runners.html.haml
+++ b/app/views/projects/runners/_group_runners.html.haml
@@ -13,10 +13,10 @@
%br
%br
- if @project.group_runners_enabled?
- = link_to toggle_group_runners_project_runners_path(@project), class: 'btn btn-close', method: :post do
+ = link_to toggle_group_runners_project_runners_path(@project), class: 'btn gl-button btn-warning-secondary', method: :post do
= _('Disable group runners')
- else
- = link_to toggle_group_runners_project_runners_path(@project), class: 'btn btn-success btn-inverted', method: :post do
+ = link_to toggle_group_runners_project_runners_path(@project), class: 'btn gl-button btn-success btn-inverted', method: :post do
= _('Enable group runners')
&nbsp;
= _('for this project')
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 85bd0335b92..41159df1435 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -10,8 +10,8 @@
= sprite_icon('lock')
%small.edit-runner
- = link_to edit_project_runner_path(@project, runner), class: 'btn btn-edit' do
- = sprite_icon('pencil')
+ = link_to edit_project_runner_path(@project, runner), class: 'btn gl-button btn-edit' do
+ = sprite_icon('pencil', css_class: 'gl-my-2')
- else
%span.commit-sha
= runner.short_sha
@@ -19,18 +19,18 @@
.float-right
- if @project_runners.include?(runner)
- if runner.active?
- = link_to _('Pause'), pause_project_runner_path(@project, runner), method: :post, class: 'btn btn-sm btn-danger', data: { confirm: _("Are you sure?") }
+ = link_to _('Pause'), pause_project_runner_path(@project, runner), method: :post, class: 'btn gl-button btn-sm btn-danger', data: { confirm: _("Are you sure?") }
- else
- = link_to _('Resume'), resume_project_runner_path(@project, runner), method: :post, class: 'btn btn-success btn-sm'
+ = link_to _('Resume'), resume_project_runner_path(@project, runner), method: :post, class: 'btn gl-button btn-success btn-sm'
- if runner.belongs_to_one_project?
- = link_to _('Remove runner'), project_runner_path(@project, runner), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn btn-danger btn-sm'
+ = link_to _('Remove runner'), project_runner_path(@project, runner), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn gl-button btn-danger btn-sm'
- else
- runner_project = @project.runner_projects.find_by(runner_id: runner) # rubocop: disable CodeReuse/ActiveRecord
- = link_to _('Disable for this project'), project_runner_project_path(@project, runner_project), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn btn-danger btn-sm'
+ = link_to _('Disable for this project'), project_runner_project_path(@project, runner_project), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn gl-button btn-danger btn-sm'
- elsif runner.project_type?
= form_for [@project, @project.runner_projects.new] do |f|
= f.hidden_field :runner_id, value: runner.id
- = f.submit _('Enable for this project'), class: 'btn btn-sm'
+ = f.submit _('Enable for this project'), class: 'btn gl-button btn-sm'
.float-right
%small.light
\##{runner.id}
diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml
index fd8b4eb0d39..484d8f8a40c 100644
--- a/app/views/projects/runners/_shared_runners.html.haml
+++ b/app/views/projects/runners/_shared_runners.html.haml
@@ -9,10 +9,10 @@
= _('Shared runners disabled on group level')
- else
- if @project.shared_runners_enabled?
- = link_to toggle_shared_runners_project_runners_path(@project), class: 'btn btn-close', method: :post do
+ = link_to toggle_shared_runners_project_runners_path(@project), class: 'btn gl-button btn-warning-secondary', method: :post do
= _('Disable shared runners')
- else
- = link_to toggle_shared_runners_project_runners_path(@project), class: 'btn btn-success', method: :post do
+ = link_to toggle_shared_runners_project_runners_path(@project), class: 'btn gl-button btn-success', method: :post do
= _('Enable shared runners')
&nbsp; for this project
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 3e325b80efd..88895634990 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -9,9 +9,11 @@
clusters_path: project_clusters_path(@project) }
%hr
= render partial: 'ci/runner/how_to_setup_runner',
- locals: { registration_token: @project.runners_token,
- type: 'specific',
- reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path }
+ locals: { registration_token: @project.runners_token,
+ type: 'specific',
+ reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path,
+ project_path: @project.path_with_namespace,
+ group_path: '' }
%hr
diff --git a/app/views/projects/security/configuration/show.html.haml b/app/views/projects/security/configuration/show.html.haml
new file mode 100644
index 00000000000..fe47ce327c2
--- /dev/null
+++ b/app/views/projects/security/configuration/show.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _("Security Configuration")
+- page_title _("Security Configuration")
+
+#js-security-configuration-static{ data: {project_path: @project.full_path} }
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 59b3afa476f..3c99b4c5e68 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -1,19 +1,14 @@
- if lookup_context.template_exists?('top', "projects/services/#{@service.to_param}", true)
= render "projects/services/#{@service.to_param}/top"
-.row.gl-mt-3.gl-mb-3
- .col-lg-4
- %h3.page-title.gl-mt-0
- = @service.title
- - if @service.operating?
- = sprite_icon('check', css_class: 'gl-text-green-500')
+%h3.page-title
+ = @service.title
+ - if @service.operating?
+ = sprite_icon('check', css_class: 'gl-text-green-500')
- - if @service.respond_to?(:detailed_description)
- %p= @service.detailed_description
- .col-lg-8
- = form_for(@service, as: :service, url: scoped_integration_path(@service), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, @service) } }) do |form|
- = render 'shared/service_settings', form: form, integration: @service
- %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referrer }
+= form_for(@service, as: :service, url: scoped_integration_path(@service), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, @service) } }) do |form|
+ = render 'shared/service_settings', form: form, integration: @service
+ %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referrer }
- if lookup_context.template_exists?('show', "projects/services/#{@service.to_param}", true)
%hr
diff --git a/app/views/projects/services/prometheus/_top.html.haml b/app/views/projects/services/prometheus/_top.html.haml
index 0238a45b75f..db02ea85865 100644
--- a/app/views/projects/services/prometheus/_top.html.haml
+++ b/app/views/projects/services/prometheus/_top.html.haml
@@ -7,4 +7,4 @@
.gl-alert-body
= s_('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.')
.gl-alert-actions
- = link_to _('Visit settings page'), project_settings_operations_path(@project, anchor: 'js-alert-management-settings'), class: 'btn gl-alert-action btn-info gl-button'
+ = link_to _('Visit settings page'), project_settings_operations_path(@project, anchor: 'js-alert-management-settings'), class: 'gl-button btn gl-alert-action btn-info'
diff --git a/app/views/projects/settings/_archive.html.haml b/app/views/projects/settings/_archive.html.haml
index 4133129fde2..4300ebb4852 100644
--- a/app/views/projects/settings/_archive.html.haml
+++ b/app/views/projects/settings/_archive.html.haml
@@ -7,12 +7,14 @@
- else
= _('Archive project')
- if @project.archived?
- %p= _("Unarchiving the project will restore people's 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}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
+ - 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),
data: { confirm: _("Are you sure that you want to unarchive this project?"), qa_selector: 'unarchive_project_link' },
- method: :post, class: "btn btn-success"
+ method: :post, class: "gl-button btn btn-success"
- else
- %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}").html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
+ - 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' },
- method: :post, class: "btn btn-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 5d5f1d54439..3b03e213983 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -7,17 +7,17 @@
.form-group.col-md-5
= f.label :name, class: 'label-bold', for: 'project_name_edit' do
= _('Project name')
- = f.text_field :name, class: 'form-control qa-project-name-field', id: "project_name_edit"
+ = f.text_field :name, class: 'form-control gl-form-input qa-project-name-field', id: "project_name_edit"
.form-group.col-md-7
= f.label :id, class: 'label-bold' do
= _('Project ID')
- = f.text_field :id, class: 'form-control w-auto', readonly: true
+ = f.text_field :id, class: 'form-control gl-form-input w-auto', readonly: true
.row
.form-group.col-md-9
= f.label :tag_list, _('Topics (optional)'), class: 'label-bold'
- = f.text_field :tag_list, value: @project.tag_list.join(', '), maxlength: 2000, class: "form-control"
+ = f.text_field :tag_list, value: @project.tag_list.join(', '), maxlength: 2000, class: "form-control gl-form-input"
%p.form-text.text-muted= _('Separate topics with commas.')
= render_if_exists 'compliance_management/compliance_framework/project_settings', f: f
@@ -25,14 +25,14 @@
.row
.form-group.col-md-9
= f.label :description, _('Project description (optional)'), class: 'label-bold'
- = f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
+ = f.text_area :description, class: 'form-control gl-form-input', rows: 3, maxlength: 250
.row= render_if_exists 'projects/classification_policy_settings', f: f
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group.gl-mt-3.gl-mb-3
- .avatar-container.s90
+ .avatar-container.rect-avatar.s90
= project_icon(@project, alt: _('Project avatar'), class: 'avatar project-avatar s90')
= f.label :avatar, _('Project avatar'), class: 'label-bold d-block'
= render 'shared/choose_avatar_button', f: f
@@ -40,4 +40,4 @@
%hr
= link_to _('Remove avatar'), project_avatar_path(@project), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link'
- = f.submit _('Save changes'), class: "btn btn-success mt-4 qa-save-naming-topics-avatar-button"
+ = f.submit _('Save changes'), class: "gl-button btn btn-success gl-mt-6 qa-save-naming-topics-avatar-button"
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
index 2e4542a033e..5f79dd3d4bb 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -54,4 +54,4 @@
= s_('CICD|Automatic deployment to staging, manual deployment to production')
= link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'incremental-rollout-to-production'), target: '_blank'
- = f.submit _('Save changes'), class: "btn btn-success gl-mt-5", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), class: "btn gl-button btn-success gl-mt-5", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index d247e73a5b4..e0c4a3d624e 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -4,10 +4,46 @@
= form_errors(@project)
%fieldset.builds-feature
.form-group
+ .form-check
+ = f.check_box :public_builds, { class: 'form-check-input' }
+ = f.label :public_builds, class: 'form-check-label' do
+ %strong= _("Public pipelines")
+ .form-text.text-muted
+ = _("Allow public access to pipelines and job details, including output logs and artifacts.")
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank'
+
+ .form-group
+ .form-check
+ = f.check_box :auto_cancel_pending_pipelines, { class: 'form-check-input' }, 'enabled', 'disabled'
+ = f.label :auto_cancel_pending_pipelines, class: 'form-check-label' do
+ %strong= _("Auto-cancel redundant pipelines")
+ .form-text.text-muted
+ = _("New pipelines cause older pending pipelines on the same branch to be cancelled.")
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'auto-cancel-redundant-pipelines'), target: '_blank'
+
+ .form-group
+ .form-check
+ = f.fields_for :ci_cd_settings_attributes, @project.ci_cd_settings do |form|
+ = form.check_box :forward_deployment_enabled, { class: 'form-check-input' }
+ = form.label :forward_deployment_enabled, class: 'form-check-label' do
+ %strong= _("Skip outdated deployment jobs")
+ .form-text.text-muted
+ = _("When a deployment job is successful, skip older deployment jobs that are still pending.")
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'skip-outdated-deployment-jobs'), target: '_blank'
+
+ .form-group
+ = f.label :ci_config_path, _('CI/CD configuration file'), class: 'label-bold'
+ = f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
+ %p.form-text.text-muted
+ = html_escape(_("The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close}).")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-path'), target: '_blank'
+
+ %hr
+ .form-group
%h5.gl-mt-0
- = _("Git strategy for pipelines")
+ = _("Git strategy")
%p
- = html_escape(_("Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = _("Choose which Git strategy to use when fetching the project.")
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'git-strategy'), target: '_blank'
.form-check
= f.radio_button :build_allow_git_fetch, 'false', { class: 'form-check-input' }
@@ -15,137 +51,50 @@
%strong git clone
%br
%span
- = _("Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job")
+ = _("For each job, clone the repository.")
.form-check
= f.radio_button :build_allow_git_fetch, 'true', { class: 'form-check-input' }
= f.label :build_allow_git_fetch_true, class: 'form-check-label' do
%strong git fetch
%br
%span
- = _("Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)")
+ = html_escape(_("For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- %hr
.form-group
= f.fields_for :ci_cd_settings_attributes, @project.ci_cd_settings do |form|
= form.label :default_git_depth, _('Git shallow clone'), class: 'label-bold'
- = form.number_field :default_git_depth, { class: 'form-control', min: 0, max: 1000 }
+ = form.number_field :default_git_depth, { class: 'form-control gl-form-input', min: 0, max: 1000 }
%p.form-text.text-muted
- = _('The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time.')
+ = html_escape(_('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')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'git-shallow-clone'), target: '_blank'
%hr
.form-group
= f.label :build_timeout_human_readable, _('Timeout'), class: 'label-bold'
- = f.text_field :build_timeout_human_readable, class: 'form-control'
+ = f.text_field :build_timeout_human_readable, class: 'form-control gl-form-input'
%p.form-text.text-muted
- = _('If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like "1 hour". Values without specification represent seconds.')
+ = html_escape(_('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}.')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'timeout'), target: '_blank'
- if can?(current_user, :update_max_artifacts_size, @project)
- %hr
.form-group
- = f.label :max_artifacts_size, _('Maximum artifacts size (MB)'), class: 'label-bold'
- = f.number_field :max_artifacts_size, class: 'form-control'
+ = f.label :max_artifacts_size, _('Maximum artifacts size'), class: 'label-bold'
+ = f.number_field :max_artifacts_size, class: 'form-control gl-form-input'
%p.form-text.text-muted
- = _("Set the maximum file size for each job's artifacts")
+ = _("The maximum file size in megabytes for individual job artifacts.")
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank'
- %hr
- .form-group
- = f.label :ci_config_path, _('Custom CI configuration path'), class: 'label-bold'
- = f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
- %p.form-text.text-muted
- = html_escape(_("The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
-
- %hr
- .form-group
- .form-check
- = f.check_box :public_builds, { class: 'form-check-input' }
- = f.label :public_builds, class: 'form-check-label' do
- %strong= _("Public pipelines")
- .form-text.text-muted
- = _("Allow public access to pipelines and job details, including output logs and artifacts")
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank'
- .bs-callout.bs-callout-info
- %p #{_("If enabled")}:
- %ul
- %li
- = _("For public projects, anyone can view pipelines and access job details (output logs and artifacts)")
- %li
- = _("For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)")
- %li
- = _("For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)")
- %p
- = _("If disabled, the access level will depend on the user's permissions in the project.")
-
- %hr
- .form-group
- .form-check
- = f.check_box :auto_cancel_pending_pipelines, { class: 'form-check-input' }, 'enabled', 'disabled'
- = f.label :auto_cancel_pending_pipelines, class: 'form-check-label' do
- %strong= _("Auto-cancel redundant, pending pipelines")
- .form-text.text-muted
- = _("New pipelines will cancel older, pending pipelines on the same branch")
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'auto-cancel-pending-pipelines'), target: '_blank'
-
- .form-group
- .form-check
- = f.fields_for :ci_cd_settings_attributes, @project.ci_cd_settings do |form|
- = form.check_box :forward_deployment_enabled, { class: 'form-check-input' }
- = form.label :forward_deployment_enabled, class: 'form-check-label' do
- %strong= _("Skip outdated deployment jobs")
- .form-text.text-muted
- = _("When a deployment job is successful, skip older deployment jobs that are still pending")
- = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'skip-outdated-deployment-jobs'), target: '_blank'
-
- %hr
.form-group
= f.label :build_coverage_regex, _("Test coverage parsing"), class: 'label-bold'
.input-group
%span.input-group-prepend
.input-group-text /
- = f.text_field :build_coverage_regex, class: 'form-control', placeholder: 'Regular expression', data: { qa_selector: 'build_coverage_regex_field' }
+ = f.text_field :build_coverage_regex, class: 'form-control gl-form-input', placeholder: 'Regular expression', data: { qa_selector: 'build_coverage_regex_field' }
%span.input-group-append
.input-group-text /
%p.form-text.text-muted
- = _("A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable")
+ = 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: 'test-coverage-parsing'), target: '_blank'
- .bs-callout.bs-callout-info
- %p= _("Below are examples of regex for existing tools:")
- %ul
- %li
- Simplecov (Ruby) -
- %code \(\d+.\d+\%\) covered
- %li
- pytest-cov (Python) -
- %code ^TOTAL.+?(\d+\%)$
- %li
- Scoverage (Scala) -
- %code Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)
- %li
- phpunit --coverage-text --colors=never (PHP) -
- %code ^\s*Lines:\s*\d+.\d+\%
- %li
- gcovr (C/C++) -
- %code ^TOTAL.*\s+(\d+\%)$
- %li
- tap --coverage-report=text-summary (NodeJS) -
- %code ^Statements\s*:\s*([^%]+)
- %li
- nyc npm test (NodeJS) -
- %code All files[^|]*\|[^|]*\s+([\d\.]+)
- %li
- excoveralls (Elixir) -
- %code \[TOTAL\]\s+(\d+\.\d+)%
- %li
- mix test --cover (Elixir) -
- %code \d+.\d+\%\s+\|\s+Total
- %li
- JaCoCo (Java/Kotlin)
- %code Total.*?([0-9]{1,3})%
- %li
- go test -cover (Go)
- %code coverage: \d+.\d+% of statements
= f.submit _('Save changes'), class: "btn btn-success", data: { qa_selector: 'save_general_pipelines_changes_button' }
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 55b6cf372fb..ee49377595b 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -9,10 +9,10 @@
.settings-header
%h4
= _("General pipelines")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _("Customize your pipeline configuration, view your pipeline status and coverage report.")
+ = _("Customize your pipeline configuration and coverage report.")
.settings-content
= render 'form'
@@ -20,7 +20,7 @@
.settings-header
%h4
= s_('CICD|Auto DevOps')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- auto_devops_url = help_page_path('topics/autodevops/index')
@@ -37,11 +37,11 @@
.settings-header
%h4
= _("Runners")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
- = link_to s_('How do I configure runners?'), help_page_path('ci/runners/README')
+ = link_to s_('How do I configure runners?'), help_page_path('ci/runners/README'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/runners/index'
@@ -49,7 +49,7 @@
.settings-header
%h4
= _("Artifacts")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _("A job artifact is an archive of files and directories saved by a job when it finishes.")
@@ -66,10 +66,11 @@
.settings-header
%h4
= _("Pipeline triggers")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _("Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions.")
+ = _("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.")
+ = link_to _('Learn more.'), help_page_path('ci/triggers/README'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/triggers/index'
@@ -78,11 +79,11 @@
.settings-header
%h4
= _("Clean up image tags")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _("Save space and find images in the Container Registry. Remove unneeded tags and keep only the ones you want.")
- = link_to _('How does cleanup work?'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy', target: '_blank', rel: 'noopener noreferrer')
+ = link_to _('How does cleanup work?'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/registry/settings/index'
@@ -93,16 +94,16 @@
.settings-header
%h4
= _("Deploy freezes")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- freeze_period_docs = help_page_path('user/project/releases/index', anchor: 'prevent-unintentional-releases-by-setting-a-deploy-freeze')
- freeze_period_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: freeze_period_docs }
- = html_escape(s_('DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}.')) % { freeze_period_link_start: freeze_period_link_start, freeze_period_link_end: '</a>'.html_safe, filename: tag.code('gitlab-ci.yml') }
+ = html_escape(s_('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}')) % { freeze_period_link_start: freeze_period_link_start, freeze_period_link_end: '</a>'.html_safe, filename: tag.code('.gitlab-ci.yml') }
- cron_syntax_url = 'https://crontab.guru/'
- cron_syntax_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: cron_syntax_url }
- = s_('DeployFreeze|You can specify deploy freezes using only %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}.').html_safe % { cron_syntax_link_start: cron_syntax_link_start, cron_syntax_link_end: "</a>".html_safe }
+ = s_('DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}.').html_safe % { cron_syntax_link_start: cron_syntax_link_start, cron_syntax_link_end: "</a>".html_safe }
.settings-content
= render 'ci/deploy_freeze/index'
diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml
index 18c6cb31874..3f5fd765b11 100644
--- a/app/views/projects/settings/integrations/show.html.haml
+++ b/app/views/projects/settings/integrations/show.html.haml
@@ -10,7 +10,7 @@
.gl-alert-body
= _('Webhooks have moved. They can now be found under the Settings menu.')
.gl-alert-actions
- = link_to _('Go to Webhooks'), project_hooks_path(@project), class: 'btn gl-alert-action btn-info new-gl-button'
+ = link_to _('Go to Webhooks'), project_hooks_path(@project), class: 'gl-button btn gl-alert-action btn-info'
%h4= _('Integrations')
- integrations_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('user/project/integrations/overview') }
diff --git a/app/views/projects/settings/operations/_alert_management.html.haml b/app/views/projects/settings/operations/_alert_management.html.haml
index 46f45df00df..079812f7077 100644
--- a/app/views/projects/settings/operations/_alert_management.html.haml
+++ b/app/views/projects/settings/operations/_alert_management.html.haml
@@ -5,7 +5,7 @@
%section.settings.no-animate#js-alert-management-settings{ class: ('expanded' if expanded) }
.settings-header
- %h3{ :class => "h4" }
+ %h4
= _('Alerts')
%button.btn.js-settings-toggle{ type: 'button' }
= _('Expand')
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index 6ab8beff99f..fe302978da6 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -4,7 +4,7 @@
%section.settings.no-animate.js-error-tracking-settings
.settings-header
- %h3{ :class => "h4" }
+ %h4
= _('Error tracking')
%button.btn.js-settings-toggle{ type: 'button' }
= _('Expand')
diff --git a/app/views/projects/settings/operations/_tracing.html.haml b/app/views/projects/settings/operations/_tracing.html.haml
index f654c723e36..03970dfe0b9 100644
--- a/app/views/projects/settings/operations/_tracing.html.haml
+++ b/app/views/projects/settings/operations/_tracing.html.haml
@@ -3,7 +3,7 @@
%section.settings.border-0.no-animate
.settings-header{ :class => "border-top" }
- %h3{ :class => "h4" }
+ %h4
= _("Jaeger tracing")
%button.btn.gl-button.js-settings-toggle{ type: 'button' }
= _('Expand')
@@ -24,7 +24,7 @@
.form-group
= f.fields_for :tracing_setting_attributes, setting do |form|
= form.label :external_url, _('Jaeger URL'), class: 'label-bold'
- = form.url_field :external_url, class: 'form-control', placeholder: 'e.g. https://jaeger.mycompany.com'
+ = form.url_field :external_url, class: 'form-control gl-form-input', placeholder: 'e.g. https://jaeger.mycompany.com'
%p.form-text.text-muted
- jaeger_help_url = "https://www.jaegertracing.io/docs/1.7/getting-started/"
- link_start_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: jaeger_help_url }
diff --git a/app/views/projects/show.atom.builder b/app/views/projects/show.atom.builder
index 39f8cb9a0e0..95b49aa0406 100644
--- a/app/views/projects/show.atom.builder
+++ b/app/views/projects/show.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.title "#{@project.name} activity"
xml.link href: project_url(@project, rss_url_options), rel: "self", type: "application/atom+xml"
xml.link href: project_url(@project), rel: "alternate", type: "text/html"
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 40faf91eadf..e1774c955bc 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -6,6 +6,9 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
+= content_for :invite_members_sidebar do
+ = render partial: 'projects/invite_members_link'
+
= render partial: 'flash_messages', locals: { project: @project }
= render "projects/last_push"
diff --git a/app/views/projects/tags/_tag.atom.builder b/app/views/projects/tags/_tag.atom.builder
index e4b2428d267..1d5b6832357 100644
--- a/app/views/projects/tags/_tag.atom.builder
+++ b/app/views/projects/tags/_tag.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
commit = @repository.commit(tag.dereferenced_target)
release = @releases.find { |r| r.tag == tag.name }
tag_url = project_tag_url(@project, tag.name)
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index 9d4e5d629f4..61b357831fd 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -41,6 +41,6 @@
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :admin_tag, @project)
- = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
+ = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn gl-button btn-default btn-icon btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
= sprite_icon("pencil")
= render 'projects/buttons/remove_tag', project: @project, tag: tag
diff --git a/app/views/projects/tags/index.atom.builder b/app/views/projects/tags/index.atom.builder
index b9b58b7beaa..68d51ebc89c 100644
--- a/app/views/projects/tags/index.atom.builder
+++ b/app/views/projects/tags/index.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.title "#{@project.name} tags"
xml.link href: project_tags_url(@project, @ref, rss_url_options), rel: 'self', type: 'application/atom+xml'
xml.link href: project_tags_url(@project, @ref), rel: 'alternate', type: 'text/html'
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 2fe5c5888f5..04d8c1f42bc 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -24,9 +24,9 @@
%li
= link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value)
- if can?(current_user, :admin_tag, @project)
- = link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn', data: { qa_selector: "new_tag_button" } do
+ = link_to new_project_tag_path(@project), class: 'btn gl-button btn-success', data: { qa_selector: "new_tag_button" } do
= s_('TagsPage|New tag')
- = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn btn-svg d-none d-sm-inline-block has-tooltip' do
+ = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-block has-tooltip' do
= sprite_icon('rss', css_class: 'qa-rss-icon')
= render_if_exists 'projects/commits/mirror_status'
diff --git a/app/views/projects/tags/releases/edit.html.haml b/app/views/projects/tags/releases/edit.html.haml
index 896dbe454e6..d82c89a3f9f 100644
--- a/app/views/projects/tags/releases/edit.html.haml
+++ b/app/views/projects/tags/releases/edit.html.haml
@@ -15,5 +15,5 @@
= render 'shared/notes/hints'
.error-alert
.gl-mt-3
- = f.submit 'Save changes', class: 'btn btn-success'
- = link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn btn-default btn-cancel"
+ = f.submit 'Save changes', class: 'btn gl-button btn-success'
+ = link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn gl-button btn-default btn-cancel"
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index d726d2ab233..b3a75494ccc 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -42,13 +42,13 @@
- if @tag.has_signature?
= render partial: 'projects/commit/signature', object: @tag.signature
- if can?(current_user, :admin_tag, @project)
- = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-icon btn-edit gl-button controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
+ = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-icon btn-edit gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= sprite_icon("pencil", css_class: 'gl-icon')
- = link_to project_tree_path(@project, @tag.name), class: 'btn btn-icon gl-button controls-item has-tooltip', title: s_('TagsPage|Browse files') do
+ = link_to project_tree_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Browse files') do
= sprite_icon('folder-open', css_class: 'gl-icon')
- = link_to project_commits_path(@project, @tag.name), class: 'btn btn-icon gl-button controls-item has-tooltip', title: s_('TagsPage|Browse commits') do
+ = link_to project_commits_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Browse commits') do
= sprite_icon('history', css_class: 'gl-icon')
- .btn-container.controls-item
+ .controls-item
= render 'projects/buttons/download', project: @project, ref: @tag.name
- if can?(current_user, :admin_tag, @project)
.btn-container.controls-item-full
diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml
deleted file mode 100644
index 6d2bdda8254..00000000000
--- a/app/views/projects/tree/_readme.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- if readme.rich_viewer
- %article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout)] }
- .js-file-title.file-title-flex-parent
- .file-header-content
- = blob_icon readme.mode, readme.name
- = link_to project_blob_path(@project, tree_join(@ref, readme.path)) do
- %strong
- = readme.name
-
- = render 'projects/blob/viewer', viewer: readme.rich_viewer, viewer_url: project_blob_path(@project, tree_join(@ref, readme.path), viewer: :rich, format: :json)
diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml
deleted file mode 100644
index a4427c6eedb..00000000000
--- a/app/views/projects/tree/_tree_content.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-.tree-content-holder.js-tree-content{ data: tree_content_data(@logs_path, @project, @path) }
- .table-holder.bordered-box
- %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" }
- %thead
- %tr
- %th= s_('ProjectFileTree|Name')
- %th.d-none.d-sm-table-cell
- .float-left= _('Last commit')
- %th.text-right= _('Last update')
- - if @path.present?
- %tr.tree-item
- %td.tree-item-file-name
- = link_to "..", project_tree_path(@project, up_dir_path), class: 'gl-ml-3'
- %td
- %td.d-none.d-sm-table-cell
-
- = render_tree(tree)
-
- - if tree.readme
- = render "projects/tree/readme", readme: tree.readme
-
-- if can_edit_tree?
- = render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
- = render 'projects/blob/new_dir'
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index cd6e85d60ed..6d33fbb535e 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -11,11 +11,6 @@
= render 'projects/find_file_link'
= render 'shared/web_ide_button', blob: nil
-
- - if show_xcode_link?(@project)
- .project-action-button.project-xcode<
- = render "projects/buttons/xcode_link"
-
= render 'projects/buttons/download', project: @project, ref: @ref
.project-clone-holder.d-none.d-md-inline-block>
diff --git a/app/views/projects/tree/_tree_row.html.haml b/app/views/projects/tree/_tree_row.html.haml
deleted file mode 100644
index 04496914c02..00000000000
--- a/app/views/projects/tree/_tree_row.html.haml
+++ /dev/null
@@ -1,27 +0,0 @@
-- tree_row_name = tree_row.name
-- tree_row_type = tree_row.type
-
-%tr{ class: "tree-item file_#{hexdigest(tree_row_name)}" }
- %td.tree-item-file-name
- - if tree_row_type == :tree
- = tree_icon('folder', tree_row.mode, tree_row.name)
- - path = flatten_tree(@path, tree_row)
- %a.str-truncated{ href: fast_project_tree_path(@project, tree_join(@id || @commit.id, path)), title: path }
- %span= path
-
- - elsif tree_row_type == :blob
- = tree_icon('file', tree_row.mode, tree_row_name)
- %a.str-truncated{ href: fast_project_blob_path(@project, tree_join(@id || @commit.id, tree_row_name)), title: tree_row_name }
- %span= tree_row_name
- - if @lfs_blob_ids.include?(tree_row.id)
- %span.badge.label-lfs.gl-ml-2 LFS
-
- - elsif tree_row_type == :commit
- = tree_icon('archive', tree_row.mode, tree_row.name)
- = submodule_link(tree_row, @ref)
-
- %td.d-none.d-sm-table-cell.tree-commit
- %td.tree-time-ago.text-right
- %span.log_loading.hide
- = loading_icon
- Loading commit data...
diff --git a/app/views/projects/tree/_truncated_notice_tree_row.html.haml b/app/views/projects/tree/_truncated_notice_tree_row.html.haml
deleted file mode 100644
index a03e0a549ee..00000000000
--- a/app/views/projects/tree/_truncated_notice_tree_row.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-%tr.tree-truncated-warning
- %td{ colspan: '3' }
- = sprite_icon('warning-solid')
- %span
- Too many items to show. To preserve performance only
- %strong #{number_with_delimiter(limit)} of #{number_with_delimiter(total)}
- items are displayed.
diff --git a/app/views/projects/triggers/_form.html.haml b/app/views/projects/triggers/_form.html.haml
index dec71cdb56a..1dbf8addb57 100644
--- a/app/views/projects/triggers/_form.html.haml
+++ b/app/views/projects/triggers/_form.html.haml
@@ -7,5 +7,5 @@
%p.form-control-plaintext= @trigger.token
.form-group
= f.label :key, "Description", class: "label-bold"
- = f.text_field :description, class: "form-control", required: true, title: 'Trigger description is required.', placeholder: "Trigger description"
+ = f.text_field :description, class: 'form-control gl-form-input', required: true, title: 'Trigger description is required.', placeholder: "Trigger description"
= f.submit btn_text, class: "btn btn-success"
diff --git a/app/views/projects/triggers/_index.html.haml b/app/views/projects/triggers/_index.html.haml
index 4f39c839630..c7cb051e40d 100644
--- a/app/views/projects/triggers/_index.html.haml
+++ b/app/views/projects/triggers/_index.html.haml
@@ -2,7 +2,7 @@
.col-lg-12
.card
.card-header
- Manage your project's triggers
+ = s_("Manage your project's triggers")
.card-body
= render "projects/triggers/form", btn_text: "Add trigger"
%hr
@@ -14,39 +14,33 @@
%table.table
%thead
%th
- %strong Token
+ %strong
+ = s_("Token")
%th
- %strong Description
+ %strong
+ = s_("Description")
%th
- %strong Owner
+ %strong
+ = s_("Owner")
%th
- %strong Last used
+ %strong
+ = s_("Last used")
%th
= render partial: 'projects/triggers/trigger', collection: @triggers, as: :trigger
- else
%p.settings-message.text-center.gl-mb-3{ data: { testid: 'no_triggers_content' } }
- No triggers have been created yet. Add one using the form above.
+ = s_("No triggers exist yet. Use the form above to create one.")
.card-footer
%p
- In the following examples, you can see the exact API call you need to
- make in order to rebuild a specific
- %code ref
- (branch or tag) with a trigger token.
- %p
- All you need to do is replace the
- %code TOKEN
- and
- %code REF_NAME
- with the trigger token and the branch or tag name respectively.
-
- %h5.gl-mt-3
- Use cURL
+ = s_("These examples show how to trigger this project's pipeline for a branch or tag.")
%p.light
- Copy one of the tokens above, set your branch or tag name, and that
- reference will be rebuilt.
+ = s_("Triggers|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.").html_safe % { code_start: "<code>".html_safe, code_end: "</code>".html_safe }
+
+ %h5.gl-mt-3
+ = s_("Use cURL")
%pre
:plain
@@ -55,39 +49,26 @@
-F ref=REF_NAME \
#{builds_trigger_url(@project.id)}
%h5.gl-mt-3
- Use .gitlab-ci.yml
-
- %p.light
- In the
- %code .gitlab-ci.yml
- of another project, include the following snippet.
- The project will be rebuilt at the end of the pipeline.
+ = s_("Use .gitlab-ci.yml")
%pre
:plain
- trigger_build:
- stage: deploy
- script:
- - "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}"
+ script:
+ - "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}"
%h5.gl-mt-3
- Use webhook
-
- %p.light
- Add the following webhook to another project for Push and Tag push events.
- The project will be rebuilt at the corresponding event.
+ = s_("Use webhook")
%pre
:plain
- #{builds_trigger_url(@project.id, ref: 'REF_NAME')}?token=TOKEN
+ #{builds_trigger_url(@project.id, ref: 'REF_NAME')}?token=TOKEN
%h5.gl-mt-3
- Pass job variables
+ = s_("Pass job variables")
%p.light
- Add
- %code variables[VARIABLE]=VALUE
- to an API request. Variable values can be used to distinguish between triggered pipelines and normal pipelines.
+ = s_("Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request.").html_safe % { code_start: "<code>".html_safe, code_end: "</code>".html_safe }
- With cURL:
+ %p.light
+ = s_("cURL:")
%pre
:plain
@@ -97,8 +78,8 @@
-F "variables[RUN_NIGHTLY_BUILD]=true" \
#{builds_trigger_url(@project.id)}
%p.light
- With webhook:
+ = s_("Webhook:")
%pre.gl-mb-0
:plain
- #{builds_trigger_url(@project.id, ref: 'REF_NAME')}?token=TOKEN&variables[RUN_NIGHTLY_BUILD]=true
+ #{builds_trigger_url(@project.id, ref: 'REF_NAME')}?token=TOKEN&variables[RUN_NIGHTLY_BUILD]=true
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index 68de80f26f6..d2a2853ecd7 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -1,13 +1,12 @@
- page_title _('Your profile')
+- add_page_specific_style 'page_bundles/signup'
.row.gl-flex-grow-1
.d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-p-5
.edit-profile.login-page.d-flex.flex-column.gl-align-items-center.pt-lg-3
= render_if_exists "registrations/welcome/progress_bar"
- %h2.gl-text-center= html_escape(_('Welcome to GitLab%{br_tag}%{name}!')) % { name: html_escape(current_user.first_name), br_tag: '<br/>'.html_safe }
- %p
- .gl-text-center= html_escape(_('In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you.')) % { br_tag: '<br/>'.html_safe }
-
+ %h2.gl-text-center= html_escape(_('Welcome to GitLab,%{br_tag}%{name}!')) % { name: html_escape(current_user.first_name), br_tag: '<br/>'.html_safe }
+ %p.gl-text-center= html_escape(_('To personalize your GitLab experience, we\'d like to know a bit more about you. We won\'t share this information with anyone.')) % { br_tag: '<br/>'.html_safe }
= form_for(current_user, url: users_sign_up_welcome_path, html: { class: 'card gl-w-full! gl-p-5', 'aria-live' => 'assertive' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: current_user
@@ -20,10 +19,6 @@
.form-group.col-sm-12.js-other-role-group{ class: ("hidden") }
= f.label :other_role, _('What is your job title? (optional)'), class: 'form-check-label gl-mb-3'
= f.text_field :other_role, class: 'form-control'
- - else
- .row
- .form-group.col-sm-12
- .form-text.gl-text-gray-500.gl-mt-0.gl-line-height-normal.gl-px-1= _('This will help us personalize your onboarding experience.')
= render_if_exists "registrations/welcome/setup_for_company", f: f
.row
.form-group.col-sm-12.gl-mb-0
diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml
deleted file mode 100644
index e9c6b581c90..00000000000
--- a/app/views/search/_filter.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-- if params[:group_id].present?
- = hidden_field_tag :group_id, params[:group_id]
-- if params[:project_id].present?
- = hidden_field_tag :project_id, params[:project_id]
-- project_attributes = @project&.attributes&.slice('id', 'namespace_id', 'name')&.merge(name_with_namespace: @project&.name_with_namespace)
-
-.dropdown.form-group.mb-lg-0.mx-lg-1.gl-p-0{ data: { testid: "group-filter" } }
- %label.d-block{ for: "dashboard_search_group" }
- = _("Group")
- %input#js-search-group-dropdown.dropdown-menu-toggle{ value: "Loading...", data: { "initial-data": @group.to_json } }
-.dropdown.form-group.mb-lg-0.mx-lg-1.gl-p-0{ data: { testid: "project-filter" } }
- %label.d-block{ for: "dashboard_search_project" }
- = _("Project")
- %input#js-search-project-dropdown.dropdown-menu-toggle{ value: "Loading...", data: { "initial-data": project_attributes.to_json } }
diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml
deleted file mode 100644
index a9eee1dd2d6..00000000000
--- a/app/views/search/_form.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-= form_tag search_path, method: :get, class: 'search-page-form js-search-form' do |f|
- = hidden_field_tag :snippets, params[:snippets]
- = hidden_field_tag :scope, params[:scope]
- = hidden_field_tag :repository_ref, params[:repository_ref]
-
- .d-lg-flex.align-items-end
- .search-field-holder.form-group.mr-lg-1.mb-lg-0
- %label{ for: "dashboard_search" }
- = _("What are you searching for?")
- .gl-search-box-by-type
- = search_field_tag :search, params[:search], placeholder: _("Search for projects, issues, etc."), class: "gl-form-input form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false
- = sprite_icon('search', css_class: 'gl-search-box-by-type-search-icon gl-icon')
- %button.search-clear.js-search-clear{ class: [("hidden" if params[:search].blank?), "has-tooltip"], type: "button", tabindex: "-1", title: _('Clear') }
- = sprite_icon('clear')
- %span.sr-only
- = _("Clear search")
- - unless params[:snippets].eql? 'true'
- = render 'filter'
- .d-flex-center.flex-column.flex-lg-row
- = button_tag _("Search"), class: "gl-button btn btn-success btn-search mt-lg-0 ml-lg-1 align-self-end"
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 80d0253d273..d5fbee34fa0 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,7 +1,7 @@
- search_bar_classes = 'search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4'
- if @search_objects.to_a.empty?
- .gl-display-md-flex
+ .gl-md-display-flex
- if %w(issues merge_requests).include?(@scope)
#js-search-sidebar{ class: search_bar_classes }
.gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
@@ -11,7 +11,7 @@
= render partial: 'search/results_status', locals: { search_service: @search_service }
= render_if_exists 'shared/promotions/promote_advanced_search'
- .results.gl-display-md-flex.gl-mt-3
+ .results.gl-md-display-flex.gl-mt-3
- if %w(issues merge_requests).include?(@scope)
#js-search-sidebar{ class: search_bar_classes }
.gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
diff --git a/app/views/search/_results_status.html.haml b/app/views/search/_results_status.html.haml
index e55f225b162..dcfab046514 100644
--- a/app/views/search/_results_status.html.haml
+++ b/app/views/search/_results_status.html.haml
@@ -4,7 +4,7 @@
.search-results-status
.row-content-block.gl-display-flex
- .gl-display-md-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
+ .gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
- unless search_service.without_count?
= search_entries_info(search_service.search_objects, search_service.scope, params[:search])
- unless search_service.show_snippets?
@@ -21,5 +21,5 @@
- link_to_group = link_to(search_service.group.name, search_service.group, class: 'ml-md-1')
= _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
- if search_service.show_sort_dropdown?
- .gl-display-md-flex.gl-flex-direction-column
- = render partial: 'search/sort_dropdown'
+ .gl-md-display-flex.gl-flex-direction-column
+ #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } }
diff --git a/app/views/search/_sort_dropdown.html.haml b/app/views/search/_sort_dropdown.html.haml
deleted file mode 100644
index 4ae6513d395..00000000000
--- a/app/views/search/_sort_dropdown.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-- sort_value = @sort
-- sort_title = search_sort_option_title(sort_value)
-
-.dropdown.gl-display-inline-block.gl-ml-3.filter-dropdown-container
- .btn-group{ role: 'group' }
- .btn-group{ role: 'group' }
- %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
- = sort_title
- = sprite_icon('chevron-down', css_class: 'dropdown-menu-toggle-icon gl-top-3')
- %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
- %li
- = render_if_exists('search/sort_by_relevancy', sort_title: sort_title)
- = sortable_item(sort_title_recently_created, page_filter_path(sort: sort_value_recently_created), sort_title)
- = search_sort_direction_button(sort_value)
diff --git a/app/views/search/opensearch.xml.erb b/app/views/search/opensearch.xml.erb
new file mode 100644
index 00000000000..9d08f56f290
--- /dev/null
+++ b/app/views/search/opensearch.xml.erb
@@ -0,0 +1,9 @@
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+ xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>GitLab</ShortName>
+ <Description>Search GitLab</Description>
+ <InputEncoding>UTF-8</InputEncoding>
+ <Image width="16" height="16" type="image/x-icon"><%= root_url %>favicon.ico</Image>
+ <Url type="text/html" method="get" template="<%= search_url %>?search={searchTerms}"/>
+ <moz:SearchForm><%= search_url %></moz:SearchForm>
+</OpenSearchDescription> \ No newline at end of file
diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml
index 288ac53a954..8aad4848aa2 100644
--- a/app/views/search/results/_issuable.html.haml
+++ b/app/views/search/results/_issuable.html.haml
@@ -5,6 +5,6 @@
= link_to issuable_path(issuable), data: { track_event: 'click_text', track_label: "#{issuable.class.name.downcase}_title", track_property: 'search_result' }, class: 'gl-w-full' do
%span.term.str-truncated.gl-font-weight-bold.gl-ml-2= issuable.title
.gl-text-gray-500.gl-my-3
- = sprintf(s_(' %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}'), { project_name: issuable.project.full_name, issuable_iid: issuable.iid, issuable_created: time_ago_with_tooltip(issuable.created_at, placement: 'bottom'), author: link_to_member(@project, issuable.author, avatar: false) }).html_safe
+ = sprintf(s_(' %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}'), { project_name: issuable.project.full_name, issuable_iid: issuable.iid, issuable_created: time_ago_with_tooltip(issuable.created_at, placement: 'bottom'), issuable_updated: time_ago_with_tooltip(issuable.updated_at, placement: 'bottom'), author: link_to_member(@project, issuable.author, avatar: false) }).html_safe
.description.term.col-sm-10.gl-px-0
= highlight_and_truncate_issuable(issuable, @search_term, @search_highlight)
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 3fb91428c56..d54310bfa82 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -1,6 +1,11 @@
- @hide_top_links = true
- page_title @search_term
- @hide_breadcrumbs = true
+- if params[:group_id].present?
+ = hidden_field_tag :group_id, params[:group_id]
+- if params[:project_id].present?
+ = hidden_field_tag :project_id, params[:project_id]
+- project_attributes = @project&.attributes&.slice('id', 'namespace_id', 'name')&.merge(name_with_namespace: @project&.name_with_namespace)
- if @search_results
- page_description(_("%{count} %{scope} for term '%{term}'") % { count: @search_results.formatted_count(@scope), scope: @scope, term: @search_term })
@@ -11,7 +16,7 @@
= render_if_exists 'search/form_elasticsearch', attrs: { class: 'mb-2 mb-sm-0 align-self-center' }
.gl-mt-3
- = render 'search/form'
+ #js-search-topbar{ data: { "group-initial-data": @group.to_json, "project-initial-data": project_attributes.to_json } }
- if @search_term
= render 'search/category'
= render 'search/results'
diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml
index a286693e2b6..cacfd601d4d 100644
--- a/app/views/sent_notifications/unsubscribe.html.haml
+++ b/app/views/sent_notifications/unsubscribe.html.haml
@@ -15,5 +15,5 @@
%p
= link_to _('Unsubscribe'), unsubscribe_sent_notification_path(@sent_notification, force: true),
- class: 'gl-button btn btn-primary gl-mr-3'
+ class: 'gl-button btn btn-confirm gl-mr-3'
= link_to _('Cancel'), new_user_session_path, class: 'gl-button btn gl-mr-3'
diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml
index 443d801d672..d6d84b2181f 100644
--- a/app/views/shared/_auto_devops_callout.html.haml
+++ b/app/views/shared/_auto_devops_callout.html.haml
@@ -8,7 +8,7 @@
%p
- link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer')
= s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link }
- = link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), class: 'btn btn-md new-gl-button js-close-callout'
+ = link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), class: 'btn btn-md btn-default gl-button js-close-callout'
%button.gl-banner-close.close.js-close-callout{ type: 'button',
'aria-label' => s_('AutoDevOps|Dismiss Auto DevOps box') }
diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml
index d65b7492690..47ecc75af1f 100644
--- a/app/views/shared/_commit_message_container.html.haml
+++ b/app/views/shared/_commit_message_container.html.haml
@@ -8,7 +8,7 @@
.max-width-marker
= text_area_tag 'commit_message',
(params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]),
- class: 'form-control js-commit-message', placeholder: local_assigns[:placeholder],
+ class: 'form-control gl-form-input js-commit-message', placeholder: local_assigns[:placeholder],
data: descriptions,
required: true, rows: (local_assigns[:rows] || 3),
id: "commit_message-#{nonce}"
diff --git a/app/views/shared/_email_with_badge.html.haml b/app/views/shared/_email_with_badge.html.haml
index 294fe74a5ca..8b9ca966ed6 100644
--- a/app/views/shared/_email_with_badge.html.haml
+++ b/app/views/shared/_email_with_badge.html.haml
@@ -1,5 +1,5 @@
-- css_classes = %w(badge badge-verification-status)
-- css_classes << (verified ? 'verified': 'unverified')
+- css_classes = %w(badge gl-badge)
+- css_classes << (verified ? 'badge-success': 'badge-danger')
- text = verified ? _('Verified') : _('Unverified')
.email-badge
diff --git a/app/views/shared/_file_picker_button.html.haml b/app/views/shared/_file_picker_button.html.haml
index 8c10e4958b9..9e6a7626d89 100644
--- a/app/views/shared/_file_picker_button.html.haml
+++ b/app/views/shared/_file_picker_button.html.haml
@@ -1,7 +1,7 @@
- classes = local_assigns.fetch(:classes, '')
%span.js-filepicker
- %button.btn.js-filepicker-button{ type: 'button', class: classes }= _("Choose file…")
+ %button.gl-button.btn.js-filepicker-button{ type: 'button', class: classes }= _("Choose file…")
%span.file_name.js-filepicker-filename= _("No file chosen")
= f.file_field field, class: "js-filepicker-input hidden"
- if help_text.present?
diff --git a/app/views/shared/_issuable_meta_data.html.haml b/app/views/shared/_issuable_meta_data.html.haml
index 352d51dbb8e..4b006bddbf6 100644
--- a/app/views/shared/_issuable_meta_data.html.haml
+++ b/app/views/shared/_issuable_meta_data.html.haml
@@ -5,23 +5,23 @@
- issuable_mr = @issuable_meta_data[issuable.id].merge_requests_count
- if issuable_mr > 0
- %li.issuable-mr.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Related merge requests') }
+ %li.issuable-mr.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Related merge requests') }
= sprite_icon('merge-request', css_class: "gl-vertical-align-middle")
= issuable_mr
- if upvotes > 0
- %li.issuable-upvotes.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Upvotes') }
+ %li.issuable-upvotes.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Upvotes') }
= sprite_icon('thumb-up', css_class: "gl-vertical-align-middle")
= upvotes
- if downvotes > 0
- %li.issuable-downvotes.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Downvotes') }
+ %li.issuable-downvotes.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Downvotes') }
= sprite_icon('thumb-down', css_class: "gl-vertical-align-middle")
= downvotes
= render_if_exists 'shared/issuable/blocking_issues_count', issuable: issuable
-%li.issuable-comments.gl-display-none.gl-display-sm-block
+%li.issuable-comments.gl-display-none.gl-sm-display-block
= link_to issuable_path, class: ['has-tooltip', ('no-comments' if note_count == 0)], title: _('Comments') do
= sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom')
= note_count
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index 4b09e8de896..95d7f075964 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -29,7 +29,7 @@
%ul
- if label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group)
%li
- %button.js-promote-project-label-button.btn.btn-transparent.btn-action{ disabled: true, type: 'button',
+ %button.js-promote-project-label-button.btn.btn-transparent{ disabled: true, type: 'button',
data: { url: promote_project_label_path(label.project, label),
label_title: label.title,
label_color: label.color,
@@ -43,10 +43,10 @@
- if current_user
%li.inline.label-subscription
- if label.can_subscribe_to_label_in_different_levels?
- %button.js-unsubscribe-button.label-subscribe-button.btn.btn-default{ class: ('hidden' if status.unsubscribed?), data: { url: toggle_subscription_path, toggle: 'tooltip' }, title: tooltip_title }
+ %button.js-unsubscribe-button.gl-button.label-subscribe-button.btn.btn-default.gl-ml-3{ class: ('hidden' if status.unsubscribed?), data: { url: toggle_subscription_path, toggle: 'tooltip' }, title: tooltip_title }
%span= _('Unsubscribe')
.dropdown.dropdown-group-label{ class: ('hidden' unless status.unsubscribed?) }
- %button.label-subscribe-button.btn.btn-default{ data: { toggle: 'dropdown' } }
+ %button.gl-button.label-subscribe-button.btn.btn-default.gl-ml-3{ data: { toggle: 'dropdown' } }
%span
= _('Subscribe')
= sprite_icon('chevron-down')
@@ -59,7 +59,7 @@
%button.js-subscribe-button.js-group-level.label-subscribe-button.btn.btn-default{ class: ('hidden' unless status.unsubscribed?), data: { status: status, url: toggle_subscription_group_label_path(label.group, label) } }
%span= _('Subscribe at group level')
- else
- %button.js-subscribe-button.label-subscribe-button.btn.btn-default{ data: { status: status, url: toggle_subscription_path, toggle: 'tooltip' }, title: tooltip_title }
+ %button.gl-button.js-subscribe-button.label-subscribe-button.btn.btn-default.gl-ml-3{ data: { status: status, url: toggle_subscription_path, toggle: 'tooltip' }, title: tooltip_title }
%span= label_subscription_toggle_button_text(label, @project)
= render 'shared/delete_label_modal', label: label
diff --git a/app/views/shared/_milestone_expired.html.haml b/app/views/shared/_milestone_expired.html.haml
index 2261e9e3121..171ae9d2c07 100644
--- a/app/views/shared/_milestone_expired.html.haml
+++ b/app/views/shared/_milestone_expired.html.haml
@@ -1,6 +1,6 @@
- if milestone.expired? and not milestone.closed?
- .status-box.status-box-expired.gl-mb-2= _('Expired')
+ .gl-badge.badge-warning.badge-pill.gl-mb-2= _('Expired')
- if milestone.upcoming?
- .status-box.status-box-mr-merged.gl-mb-2= _('Upcoming')
+ .gl-badge.badge-primary.badge-pill.gl-mb-2= _('Upcoming')
- if milestone.closed?
- .status-box.status-box-closed.gl-mb-2= _('Closed')
+ .gl-badge.badge-danger.badge-pill.gl-mb-2= _('Closed')
diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml
index 81c33eeea4f..62ba89e2576 100644
--- a/app/views/shared/_new_commit_form.html.haml
+++ b/app/views/shared/_new_commit_form.html.haml
@@ -10,7 +10,7 @@
.form-group.row.branch
= label_tag 'branch_name', _('Target Branch'), class: 'col-form-label col-sm-2'
.col-sm-10
- = text_field_tag 'branch_name', branch_name, required: true, class: "form-control js-branch-name ref-name"
+ = text_field_tag 'branch_name', branch_name, required: true, class: "form-control gl-form-input js-branch-name ref-name"
.js-create-merge-request-container
= render 'shared/new_merge_request_checkbox'
diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml
index 0a7fa2a3c1e..2c6ceb58654 100644
--- a/app/views/shared/_no_ssh.html.haml
+++ b/app/views/shared/_no_ssh.html.haml
@@ -6,5 +6,5 @@
.gl-alert-body
= s_("MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile")
.gl-alert-actions
- = link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "btn gl-alert-action btn-warning btn-md new-gl-button"
+ = link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "btn gl-alert-action btn-warning btn-md gl-button"
= link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: {hide_no_ssh_key: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-warning gl-button btn-warning-secondary'
diff --git a/app/views/shared/_project_limit.html.haml b/app/views/shared/_project_limit.html.haml
index 3d5229f87b5..9110f5a7f31 100644
--- a/app/views/shared/_project_limit.html.haml
+++ b/app/views/shared/_project_limit.html.haml
@@ -1,5 +1,5 @@
- if cookies[:hide_project_limit_message].blank? && !current_user.hide_project_limit && !current_user.can_create_project? && current_user.projects_limit > 0
- .project-limit-message.gl-alert.gl-alert-warning.gl-display-none.gl-display-sm-block
+ .project-limit-message.gl-alert.gl-alert-warning.gl-display-none.gl-sm-display-block
= _("You won't be able to create new projects because you have reached your project limit.")
.float-right
diff --git a/app/views/shared/_search_settings.html.haml b/app/views/shared/_search_settings.html.haml
index ea3d7b97327..d689e9ae5c0 100644
--- a/app/views/shared/_search_settings.html.haml
+++ b/app/views/shared/_search_settings.html.haml
@@ -1,2 +1,6 @@
+- container_class = local_assigns.fetch(:container_class, 'gl-mt-5')
+
- if Feature.enabled?(:search_settings_in_page, @project, default_enabled: false)
- .js-search-settings-app
+ %div{ class: container_class }
+ .js-search-settings-app
+ %input.gl-form-input.form-control{ type: "text", placeholder: _("Search settings"), aria_label: _("Search settings"), disabled: true }
diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml
index 194e0eb57f2..7af356c0820 100644
--- a/app/views/shared/_service_settings.html.haml
+++ b/app/views/shared/_service_settings.html.haml
@@ -1,13 +1,14 @@
= form_errors(integration)
-- if lookup_context.template_exists?('help', "projects/services/#{integration.to_param}", true)
- = render "projects/services/#{integration.to_param}/help", subject: integration
-- elsif integration.help.present?
- .info-well
- .well-segment
- = markdown integration.help
-
.service-settings
- if @default_integration
.js-vue-default-integration-settings{ data: integration_form_data(@default_integration, group: @group) }
.js-vue-integration-settings{ data: integration_form_data(integration, group: @group) }
+ .js-integration-help-html.gl-display-none
+ -# All content below will be repositioned in Vue
+ - if lookup_context.template_exists?('help', "projects/services/#{integration.to_param}", true)
+ = render "projects/services/#{integration.to_param}/help", subject: integration
+ - elsif integration.help.present?
+ .info-well
+ .well-segment
+ = markdown integration.help
diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml
index f206a2152c2..089643f4748 100644
--- a/app/views/shared/access_tokens/_form.html.haml
+++ b/app/views/shared/access_tokens/_form.html.haml
@@ -30,4 +30,4 @@
= render 'shared/tokens/scopes_form', prefix: prefix, token: token, scopes: scopes
.gl-mt-3
- = f.submit _('Create %{type}') % { type: type }, class: 'btn btn-success', data: { qa_selector: 'create_token_button' }
+ = f.submit _('Create %{type}') % { type: type }, class: 'gl-button btn btn-success', data: { qa_selector: 'create_token_button' }
diff --git a/app/views/shared/access_tokens/_table.html.haml b/app/views/shared/access_tokens/_table.html.haml
index 50daa400e6c..d7c74255578 100644
--- a/app/views/shared/access_tokens/_table.html.haml
+++ b/app/views/shared/access_tokens/_table.html.haml
@@ -43,7 +43,7 @@
- else
%span.token-never-expires-label= _('Never')
%td= token.scopes.present? ? token.scopes.join(', ') : _('no scopes selected')
- %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: 'btn btn-danger float-right qa-revoke-button', 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 float-right qa-revoke-button', data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type } }
- else
.settings-message.text-center
= no_active_tokens_message
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index e4222d8a4fe..ababbdc7eb9 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -6,7 +6,10 @@
- @no_breadcrumb_container = true
- @no_container = true
- @content_class = "issue-boards-content js-focus-mode-board"
-- breadcrumb_title _("Issue Boards")
+- if board.to_type == "EpicBoard"
+ - breadcrumb_title _("Epic Boards")
+- else
+ - breadcrumb_title _("Issue Boards")
- page_title("#{board.name}", _("Boards"))
- add_page_specific_style 'page_bundles/boards'
diff --git a/app/views/shared/boards/components/_sidebar.html.haml b/app/views/shared/boards/components/_sidebar.html.haml
index b4f75967a67..3daa13fb488 100644
--- a/app/views/shared/boards/components/_sidebar.html.haml
+++ b/app/views/shared/boards/components/_sidebar.html.haml
@@ -1,6 +1,6 @@
%board-sidebar{ "inline-template" => true, ":current-user" => (UserSerializer.new.represent(current_user) || {}).to_json }
%transition{ name: "boards-sidebar-slide" }
- %aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" }
+ %aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar", 'aria-label': s_('Boards|Board') }
.issuable-sidebar
.block.issuable-sidebar-header.position-relative
%span.issuable-header-text.hide-collapsed.float-left
diff --git a/app/views/shared/boards/components/sidebar/_assignee.html.haml b/app/views/shared/boards/components/sidebar/_assignee.html.haml
index e22a7807b3b..c36f2c7c969 100644
--- a/app/views/shared/boards/components/sidebar/_assignee.html.haml
+++ b/app/views/shared/boards/components/sidebar/_assignee.html.haml
@@ -1,31 +1,9 @@
+- dropdown_options = assignees_dropdown_options('issue')
+
.block.assignee{ ref: "assigneeBlock" }
%template{ "v-if" => "issue.assignees" }
- %assignee-title{ ":number-of-assignees" => "issue.assignees.length",
- ":loading" => "loadingAssignees",
- ":editable" => can_admin_issue? }
- %assignees.value{ "root-path" => "#{root_url}",
- ":users" => "issue.assignees",
- ":editable" => can_admin_issue?,
- "@assign-self" => "assignSelf" }
-
- - if can_admin_issue?
- .selectbox.hide-collapsed
- %input.js-vue{ type: "hidden",
- name: "issue[assignee_ids][]",
- ":value" => "assignee.id",
- "v-if" => "issue.assignees",
- "v-for" => "assignee in issue.assignees",
- ":data-avatar_url" => "assignee.avatar",
- ":data-name" => "assignee.name",
- ":data-username" => "assignee.username" }
- .dropdown
- - dropdown_options = assignees_dropdown_options('issue')
- %button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: board_sidebar_user_data,
- ":data-issuable-id" => "issue.iid" }
- = dropdown_options[:title]
- = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
- .dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author
- = dropdown_title("Assign to")
- = dropdown_filter("Search users")
- = dropdown_content
- = dropdown_loading
+ %sidebar-assignees-widget{ ":iid" => "String(issue.iid)",
+ ":full-path" => "issue.path.split('/-/')[0].substring(1)",
+ ":initial-assignees" => "issue.assignees",
+ ":multiple-assignees" => "!Boolean(#{dropdown_options[:data][:"max-select"]})",
+ "@assignees-updated" => "setAssignees" }
diff --git a/app/views/shared/deploy_keys/_form.html.haml b/app/views/shared/deploy_keys/_form.html.haml
index 94742d96af7..37a56057268 100644
--- a/app/views/shared/deploy_keys/_form.html.haml
+++ b/app/views/shared/deploy_keys/_form.html.haml
@@ -6,7 +6,7 @@
.form-group
= form.label :title, class: 'col-form-label col-sm-2'
- .col-sm-10= form.text_field :title, class: 'form-control', readonly: ('readonly' unless can?(current_user, :update_deploy_key, deploy_key))
+ .col-sm-10= form.text_field :title, class: 'form-control gl-form-input', readonly: ('readonly' unless can?(current_user, :update_deploy_key, deploy_key))
.form-group
- if deploy_key.new_record?
@@ -15,12 +15,12 @@
%p.light
- link_start = "<a href='#{help_page_path('ssh/README')}' target='_blank' rel='noreferrer noopener'>".html_safe
- link_end = '</a>'
- = _('Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}').html_safe % { link_start: link_start, link_end: link_end.html_safe }
- = form.text_area :key, class: 'form-control thin_area', rows: 5
+ = _('Paste a public key here. %{link_start}How do I generate it?%{link_end}').html_safe % { link_start: link_start, link_end: link_end.html_safe }
+ = form.text_area :key, class: 'form-control gl-form-input thin_area', rows: 5
- else
= form.label :fingerprint, class: 'col-form-label col-sm-2'
.col-sm-10
- = form.text_field :fingerprint, class: 'form-control', readonly: 'readonly'
+ = form.text_field :fingerprint, class: 'form-control gl-form-input', readonly: 'readonly'
- if deploy_keys_project.present?
= form.fields_for :deploy_keys_projects, deploy_keys_project do |deploy_keys_project_form|
@@ -29,6 +29,6 @@
.col-sm-10
= deploy_keys_project_form.label :can_push do
= deploy_keys_project_form.check_box :can_push
- %strong= _('Write access allowed')
+ %strong= _('Grant write permissions to this key')
%p.light.gl-mb-0
- = _('Allow this key to push to repository as well? (Default only allows pull access.)')
+ = _('Allow this key to push to this repository')
diff --git a/app/views/shared/deploy_keys/_index.html.haml b/app/views/shared/deploy_keys/_index.html.haml
index f2f577383f8..5d9c2cd25b4 100644
--- a/app/views/shared/deploy_keys/_index.html.haml
+++ b/app/views/shared/deploy_keys/_index.html.haml
@@ -1,14 +1,14 @@
- expanded = expanded_by_default?
%section.qa-deploy-keys-settings.settings.no-animate#js-deploy-keys-settings{ class: ('expanded' if expanded), data: { qa_selector: 'deploy_keys_settings_content' } }
.settings-header
- %h4= _('Deploy Keys')
+ %h4= _('Deploy keys')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
- = _('Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one.')
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/deploy_keys/index') }
+ = _("Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.settings-content
%h5.gl-mt-0
- = _('Create a new deploy key for this project')
= render @deploy_keys.form_partial_path
%hr
#js-deploy-keys{ data: { endpoint: project_deploy_keys_path(@project), project_id: @project.id } }
diff --git a/app/views/shared/deploy_keys/_project_group_form.html.haml b/app/views/shared/deploy_keys/_project_group_form.html.haml
index 179ec33ee65..bad25086d9f 100644
--- a/app/views/shared/deploy_keys/_project_group_form.html.haml
+++ b/app/views/shared/deploy_keys/_project_group_form.html.haml
@@ -2,23 +2,23 @@
= form_errors(@deploy_keys.new_key)
.form-group.row
= f.label :title, class: "label-bold"
- = f.text_field :title, class: 'form-control', required: true
+ = f.text_field :title, class: 'form-control gl-form-input', required: true
.form-group.row
= f.label :key, class: "label-bold"
- = f.text_area :key, class: "form-control", rows: 5, required: true
+ = f.text_area :key, class: 'form-control gl-form-input', rows: 5, required: true
.form-group.row
%p.light.gl-mb-0
- = _('Paste a machine public key here. Read more about how to generate it')
- = link_to "here", help_page_path("ssh/README")
+ = _('Paste a public key here.')
+ = link_to _('How do I generate it?'), help_page_path("ssh/README")
= f.fields_for :deploy_keys_projects do |deploy_keys_project_form|
.form-group.row
= deploy_keys_project_form.label :can_push do
= deploy_keys_project_form.check_box :can_push
- %strong= _('Write access allowed')
+ %strong= _('Grant write permissions to this key')
.form-group.row
%p.light.gl-mb-0
- = _('Allow this key to push to repository as well? (Default only allows pull access.)')
+ = _('Allow this key to push to this repository')
.form-group.row
= f.submit _("Add key"), class: "btn-success btn"
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index da634d37c55..052d68baf71 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -1,50 +1,51 @@
%p.profile-settings-content
- = s_("DeployTokens|Pick a name for the application, and we'll give you a unique deploy token.")
+ = s_("DeployTokens|Pick a name for your unique deploy token.")
= form_for token, url: create_deploy_token_path(group_or_project, anchor: 'js-deploy-tokens'), method: :post, remote: Feature.enabled?(:ajax_new_deploy_token, group_or_project) do |f|
= form_errors(token)
.form-group
= f.label :name, class: 'label-bold'
- = f.text_field :name, class: 'form-control qa-deploy-token-name', required: true
+ = f.text_field :name, class: 'form-control gl-form-input qa-deploy-token-name', required: true
.form-group
- = f.label :expires_at, class: 'label-bold'
+ = f.label :expires_at, _('Expires at (optional)'), class: 'label-bold'
= f.text_field :expires_at, class: 'datepicker form-control qa-deploy-token-expires-at', value: f.object.expires_at
+ .text-secondary= s_('DeployTokens|Unless you enter a date, the token does not expire.')
.form-group
- = f.label :username, class: 'label-bold'
+ = f.label :username, _('Username (optional)'), class: 'label-bold'
= f.text_field :username, class: 'form-control qa-deploy-token-username'
- .text-secondary= s_('DeployTokens|Default format is "gitlab+deploy-token-{n}". Enter custom username if you want to change it.')
+ .text-secondary= s_('DeployTokens|Unless you specify a username, it is set to "gitlab+deploy-token-{n}".')
.form-group
- = f.label :scopes, class: 'label-bold'
+ = f.label :scopes, _('Scopes [Select 1 or more]'), class: 'label-bold'
%fieldset.form-group.form-check
= f.check_box :read_repository, class: 'form-check-input qa-deploy-token-read-repository'
= label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label'
- .text-secondary= s_('DeployTokens|Allows read-only access to the repository')
+ .text-secondary= s_('DeployTokens|Allows read-only access to the repository.')
- if container_registry_enabled?(group_or_project)
%fieldset.form-group.form-check
= f.check_box :read_registry, class: 'form-check-input qa-deploy-token-read-registry'
= label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label'
- .text-secondary= s_('DeployTokens|Allows read-only access to the registry images')
+ .text-secondary= s_('DeployTokens|Allows read-only access to registry images.')
%fieldset.form-group.form-check
= f.check_box :write_registry, class: 'form-check-input'
= label_tag ("deploy_token_write_registry"), 'write_registry', class: 'label-bold form-check-label'
- .text-secondary= s_('DeployTokens|Allows write access to the registry images')
+ .text-secondary= s_('DeployTokens|Allows write access to registry images.')
- if packages_registry_enabled?(group_or_project)
%fieldset.form-group.form-check
= f.check_box :read_package_registry, class: 'form-check-input'
= label_tag ("deploy_token_read_package_registry"), 'read_package_registry', class: 'label-bold form-check-label'
- .text-secondary= s_('DeployTokens|Allows read access to the package registry')
+ .text-secondary= s_('DeployTokens|Allows read access to the package registry.')
%fieldset.form-group.form-check
= f.check_box :write_package_registry, class: 'form-check-input'
= label_tag ("deploy_token_write_package_registry"), 'write_package_registry', class: 'label-bold form-check-label'
- .text-secondary= s_('DeployTokens|Allows write access to the package registry')
+ .text-secondary= s_('DeployTokens|Allows write access to the package registry.')
.gl-mt-3
- = f.submit s_('DeployTokens|Create deploy token'), class: 'btn btn-success qa-create-deploy-token'
+ = f.submit s_('DeployTokens|Create deploy token'), class: 'btn gl-button btn-success qa-create-deploy-token'
diff --git a/app/views/shared/deploy_tokens/_index.html.haml b/app/views/shared/deploy_tokens/_index.html.haml
index c26400690a6..e64b8634cf5 100644
--- a/app/views/shared/deploy_tokens/_index.html.haml
+++ b/app/views/shared/deploy_tokens/_index.html.haml
@@ -2,7 +2,7 @@
%section.qa-deploy-tokens-settings.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded), data: { qa_selector: 'deploy_tokens_settings_content' } }
.settings-header
- %h4= s_('DeployTokens|Deploy Tokens')
+ %h4= s_('DeployTokens|Deploy tokens')
%button.gl-button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
diff --git a/app/views/shared/deploy_tokens/_new_deploy_token.html.haml b/app/views/shared/deploy_tokens/_new_deploy_token.html.haml
index 738f2f9db70..41e50138220 100644
--- a/app/views/shared/deploy_tokens/_new_deploy_token.html.haml
+++ b/app/views/shared/deploy_tokens/_new_deploy_token.html.haml
@@ -1,18 +1,24 @@
.qa-created-deploy-token-section.created-deploy-token-container.info-well
.well-segment
%h5.gl-mt-0
- = s_('DeployTokens|Your New Deploy Token')
+ = s_('DeployTokens|Your new Deploy Token username')
.form-group
.input-group
= text_field_tag 'deploy-token-user', deploy_token.username, readonly: true, class: 'deploy-token-field form-control js-select-on-focus qa-deploy-token-user'
.input-group-append
= clipboard_button(text: deploy_token.username, title: s_('DeployTokens|Copy username'), placement: 'left')
- %span.deploy-token-help-block.gl-mt-2.text-success= s_("DeployTokens|Use this username as a login.")
+ %span.deploy-token-help-block.gl-mt-2.text-success
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/deploy_tokens/index.md') }
+ - link_end = "</a>".html_safe
+ = s_("DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}").html_safe % { link_start: link_start, link_end: link_end }
.form-group
.input-group
= text_field_tag 'deploy-token', deploy_token.token, readonly: true, class: 'deploy-token-field form-control js-select-on-focus qa-deploy-token'
.input-group-append
= clipboard_button(text: deploy_token.token, title: s_('DeployTokens|Copy deploy token'), placement: 'left')
- %span.deploy-token-help-block.gl-mt-2.text-danger= s_("DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again.")
+ %span.deploy-token-help-block.gl-mt-2.text-danger
+ - i_start = "<i>".html_safe
+ - i_end = "</i>".html_safe
+ = s_("DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered.").html_safe % { i_start: i_start, i_end: i_end }
diff --git a/app/views/shared/deploy_tokens/_table.html.haml b/app/views/shared/deploy_tokens/_table.html.haml
index 361471af0ad..ad3c53c4925 100644
--- a/app/views/shared/deploy_tokens/_table.html.haml
+++ b/app/views/shared/deploy_tokens/_table.html.haml
@@ -24,7 +24,7 @@
- else
%span.token-never-expires-label= _('Never')
%td= token.scopes.present? ? token.scopes.join(', ') : _('no scopes selected')
- %td= link_to s_('DeployTokens|Revoke'), "#", class: "btn btn-danger float-right", data: { toggle: "modal", target: "#revoke-modal-#{token.id}"}
+ %td= link_to s_('DeployTokens|Revoke'), "#", class: "gl-button btn btn-danger float-right", data: { toggle: "modal", target: "#revoke-modal-#{token.id}"}
= render 'shared/deploy_tokens/revoke_modal', token: token, group_or_project: group_or_project
- else
.settings-message.text-center
diff --git a/app/views/shared/empty_states/_deploy_keys.html.haml b/app/views/shared/empty_states/_deploy_keys.html.haml
index da34b866aa6..6fca64d805b 100644
--- a/app/views/shared/empty_states/_deploy_keys.html.haml
+++ b/app/views/shared/empty_states/_deploy_keys.html.haml
@@ -4,6 +4,6 @@
= image_tag 'illustrations/empty-state/empty-deploy-keys-lg.svg'
.gl-flex-grow-0.gl-flex-shrink-0
.text-content.gl-mx-auto.gl-my-0.gl-p-5
- %h4.h4= _('Deploy keys allow read-only or read-write (if enabled) access to your repository')
- %p= _('Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one.')
+ %h4.h4= _('Deploy Keys')
+ %p= _('Deploy keys grant read/write access to all repositories in your instance')
= link_to _('New deploy key'), new_admin_deploy_key_path, class: 'btn btn-success btn-md gl-button'
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 8c5319e2178..997bc7b8a98 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -42,7 +42,7 @@
- if project_select_button
= render 'shared/new_project_item_select', path: 'issues/new', label: _('New issue'), type: :issues, with_feature_enabled: 'issues'
- else
- = link_to _('New issue'), button_path, class: 'btn btn-success', id: 'new_issue_link'
+ = link_to _('New issue'), button_path, class: 'btn gl-button btn-success', id: 'new_issue_link'
- if show_import_button
= render 'projects/issues/import_csv/button', type: :text
diff --git a/app/views/shared/empty_states/_milestones.html.haml b/app/views/shared/empty_states/_milestones.html.haml
new file mode 100644
index 00000000000..c22869fb7e6
--- /dev/null
+++ b/app/views/shared/empty_states/_milestones.html.haml
@@ -0,0 +1,7 @@
+.row.empty-state
+ .col-12
+ .svg-content
+ = image_tag 'illustrations/milestone_burndown_chart.svg'
+ .col-12
+ .text-content
+ %h4.text-center= _('No milestones to show')
diff --git a/app/views/shared/empty_states/_profile_tabs.html.haml b/app/views/shared/empty_states/_profile_tabs.html.haml
index 38c9fe7179c..abcf9740200 100644
--- a/app/views/shared/empty_states/_profile_tabs.html.haml
+++ b/app/views/shared/empty_states/_profile_tabs.html.haml
@@ -1,5 +1,6 @@
- current_user_empty_message_description = local_assigns.fetch(:current_user_empty_message_description, nil)
- secondary_button_link = local_assigns.fetch(:secondary_button_link, nil)
+- primary_button_link = local_assigns.fetch(:primary_button_link, nil)
.nothing-here-block
.svg-content
@@ -12,9 +13,9 @@
%p= current_user_empty_message_description
- if secondary_button_link.present?
- = link_to secondary_button_label, secondary_button_link, class: 'btn btn-success btn-inverted'
+ = link_to secondary_button_label, secondary_button_link, class: 'gl-button btn btn-success btn-inverted'
- if primary_button_link.present?
- = link_to primary_button_label, primary_button_link, class: 'btn btn-success'
+ = link_to primary_button_label, primary_button_link, class: 'gl-button btn btn-success'
- else
%h5= visitor_empty_message
diff --git a/app/views/shared/empty_states/_snippets.html.haml b/app/views/shared/empty_states/_snippets.html.haml
index aa762782c46..105efcc3c88 100644
--- a/app/views/shared/empty_states/_snippets.html.haml
+++ b/app/views/shared/empty_states/_snippets.html.haml
@@ -12,7 +12,7 @@
= s_('SnippetsEmptyState|Store, share, and embed small pieces of code and text.')
.mt-2<
- if button_path
- = link_to s_('SnippetsEmptyState|New snippet'), button_path, class: 'btn btn-success', title: s_('SnippetsEmptyState|New snippet'), id: 'new_snippet_link', data: { qa_selector: 'create_first_snippet_link' }
- = link_to s_('SnippetsEmptyState|Documentation'), help_page_path('user/snippets.md'), class: 'btn btn-default', title: s_('SnippetsEmptyState|Documentation')
+ = link_to s_('SnippetsEmptyState|New snippet'), button_path, class: 'btn gl-button btn-success', title: s_('SnippetsEmptyState|New snippet'), id: 'new_snippet_link', data: { qa_selector: 'create_first_snippet_link' }
+ = link_to s_('SnippetsEmptyState|Documentation'), help_page_path('user/snippets.md'), class: 'btn gl-button btn-default', title: s_('SnippetsEmptyState|Documentation')
- else
%h4.text-center= s_('SnippetsEmptyState|There are no snippets to show.')
diff --git a/app/views/shared/integrations/_form.html.haml b/app/views/shared/integrations/_form.html.haml
index 11e390a47e2..62f8d986296 100644
--- a/app/views/shared/integrations/_form.html.haml
+++ b/app/views/shared/integrations/_form.html.haml
@@ -1,10 +1,7 @@
- integration = local_assigns.fetch(:integration)
-.row.gl-mt-3
- .col-lg-4
- %h3.page-title.gl-mt-0
- = integration.title
+%h3.page-title
+ = integration.title
- .col-lg-8
- = form_for integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => scoped_test_integration_path(integration) } } do |form|
- = render 'shared/service_settings', form: form, integration: integration
+= form_for integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => scoped_test_integration_path(integration) } } do |form|
+ = render 'shared/service_settings', form: form, integration: integration
diff --git a/app/views/shared/issuable/_board_create_list_dropdown.html.haml b/app/views/shared/issuable/_board_create_list_dropdown.html.haml
index b6cf23faff8..1a22a66d185 100644
--- a/app/views/shared/issuable/_board_create_list_dropdown.html.haml
+++ b/app/views/shared/issuable/_board_create_list_dropdown.html.haml
@@ -1,5 +1,5 @@
-.dropdown.gl-ml-3#js-add-list
- %button.btn.btn-success.btn-inverted.js-new-board-list{ type: "button", data: board_list_data }
+.dropdown.gl-display-flex.gl-align-items-center.gl-ml-3#js-add-list
+ %button.gl-button.btn.btn-confirm.btn-confirm-secondary.js-new-board-list{ type: "button", data: board_list_data }
Add list
.dropdown-menu.dropdown-extended-height.dropdown-menu-paging.dropdown-menu-right.dropdown-menu-issues-board-new.dropdown-menu-selectable.js-tab-container-labels
= render partial: "shared/issuable/label_page_default", locals: { show_footer: true, show_create: true, show_boards_content: true, title: "Add list" }
diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
index 2f30958c877..b6fc1f4955b 100644
--- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml
+++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
@@ -1,14 +1,13 @@
- type = local_assigns.fetch(:type)
-- bulk_issue_health_status_flag = type == :issues && @project&.group&.feature_available?(:issuable_health_status)
-- epic_bulk_edit_flag = @project&.group&.feature_available?(:epics) && type == :issues
+- is_issue = type == :issues
-%aside.issues-bulk-update.js-right-sidebar.right-sidebar{ "aria-live" => "polite", data: { 'signed-in': current_user.present? } }
+%aside.issues-bulk-update.js-right-sidebar.right-sidebar{ "aria-live" => "polite", data: { 'signed-in': current_user.present? }, 'aria-label': _('Bulk update') }
.issuable-sidebar.hidden
= form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do
.block.issuable-sidebar-header
.filter-item.inline.update-issues-btn.float-left
- = button_tag _('Update all'), class: "btn update-selected-issues btn-info", disabled: true
- = button_tag _('Cancel'), class: "btn btn-default js-bulk-update-menu-hide float-right"
+ = button_tag _('Update all'), class: "gl-button btn update-selected-issues btn-info", disabled: true
+ = button_tag _('Cancel'), class: "gl-button btn btn-default js-bulk-update-menu-hide float-right"
- if params[:state] != 'merged'
.block
.title
@@ -29,30 +28,22 @@
- field_name = "update[assignee_ids][]"
= dropdown_tag(_("Select assignee"), options: { toggle_class: "js-user-search js-update-assignee js-filter-submit js-filter-bulk-update", title: _("Assign to"), filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable",
placeholder: _("Search authors"), data: { first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: @project.id, field_name: field_name } })
- - if epic_bulk_edit_flag
- .block
- .title
- = _('Epic')
- .filter-item.epic-bulk-edit
- #js-epic-select-root{ data: { group_id: @project&.group&.id, show_header: "true" } }
- %input{ id: 'issue_epic_id', type: 'hidden', name: 'update[epic_id]' }
+ - if is_issue
+ = render_if_exists 'shared/issuable/epic_dropdown', parent: @project.group
.block
.title
= _('Milestone')
.filter-item
= dropdown_tag(_("Select milestone"), options: { title: _("Assign milestone"), toggle_class: "js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: _("Search milestones"), data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, use_id: true, default_label: _("Milestone") } })
+ - if is_issue
+ = render_if_exists 'shared/issuable/iterations_dropdown', parent: @project.group
.block
.title
= _('Labels')
.filter-item.labels-filter
= render "shared/issuable/label_dropdown", classes: ["js-filter-bulk-update", "js-multiselect"], dropdown_title: _("Apply a label"), show_create: false, show_footer: false, extra_options: false, filter_submit: false, data_options: { persist_when_hide: "true", field_name: "update[label_ids][]", show_no: false, show_any: false, use_id: true, default_label: _("Labels") }, label_name: _("Select labels"), no_default_styles: true
- - if bulk_issue_health_status_flag
- .block
- .title
- = _('Health status')
- .filter-item.health-status.health-status-filter
- #js-bulk-update-health-status-root
- %input{ id: 'issue_health_status_value', type: 'hidden', name: 'update[health_status]' }
+ - if is_issue
+ = render_if_exists 'shared/issuable/health_status_dropdown', parent: @project
.block
.title
= _('Subscriptions')
diff --git a/app/views/shared/issuable/_feed_buttons.html.haml b/app/views/shared/issuable/_feed_buttons.html.haml
index 86c2e243718..c3e4c3a15cc 100644
--- a/app/views/shared/issuable/_feed_buttons.html.haml
+++ b/app/views/shared/issuable/_feed_buttons.html.haml
@@ -1,4 +1,4 @@
-= link_to safe_params.merge(rss_url_options), class: 'btn btn-svg has-tooltip', data: { container: 'body', testid: 'rss-feed-link' }, title: _('Subscribe to RSS feed') do
+= link_to safe_params.merge(rss_url_options), class: 'btn gl-button btn-default btn-icon has-tooltip', data: { container: 'body', testid: 'rss-feed-link' }, title: _('Subscribe to RSS feed') do
= sprite_icon('rss', css_class: 'qa-rss-icon')
-= link_to safe_params.merge(calendar_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: _('Subscribe to calendar') do
+= link_to safe_params.merge(calendar_url_options), class: 'btn gl-button btn-default btn-icon has-tooltip', data: { container: 'body' }, title: _('Subscribe to calendar') do
= sprite_icon('calendar')
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 552f83906e1..2a91ffbdbaa 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -64,17 +64,17 @@
.row-content-block{ class: (is_footer ? "footer-block" : "middle-block") }
.float-right
- if issuable.new_record?
- = link_to 'Cancel', polymorphic_path([@project, issuable.class]), class: 'btn btn-cancel'
+ = link_to 'Cancel', polymorphic_path([@project, issuable.class]), class: 'gl-button btn btn-cancel'
- else
- if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project)
= link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: "#{issuable.human_class_name} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped'
- = link_to 'Cancel', polymorphic_path([@project, issuable]), class: 'btn btn-grouped btn-cancel'
+ = link_to 'Cancel', polymorphic_path([@project, issuable]), class: 'gl-button btn btn-grouped btn-cancel'
%span.gl-mr-3
- if issuable.new_record?
- = form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'btn btn-success qa-issuable-create-button'
+ = form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'gl-button btn btn-success qa-issuable-create-button'
- else
- = form.submit 'Save changes', class: 'btn btn-success'
+ = form.submit 'Save changes', class: 'gl-button btn btn-success'
- if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = issuable.project.present.contribution_guide_path)
.inline.gl-mt-3
diff --git a/app/views/shared/issuable/_label_page_create.html.haml b/app/views/shared/issuable/_label_page_create.html.haml
index a0d3bc64f1f..005b76180fd 100644
--- a/app/views/shared/issuable/_label_page_create.html.haml
+++ b/app/views/shared/issuable/_label_page_create.html.haml
@@ -19,7 +19,7 @@
%input.js-add-list{ type: "checkbox", name: "add_list", checked: add_list }
%span= _('Add list')
.clearfix
- %button.btn.btn-primary.float-left.js-new-label-btn{ type: "button" }
+ %button.gl-button.btn.btn-success.float-left.js-new-label-btn{ type: "button" }
= _('Create')
- %button.btn.btn-default.float-right.js-cancel-label-btn{ type: "button" }
+ %button.gl-button.btn.btn-default.float-right.js-cancel-label-btn{ type: "button" }
= _('Cancel')
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 79d86500bd9..d1e74cc771e 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -193,13 +193,16 @@
.filter-dropdown-container.d-flex.flex-column.flex-md-row
- if type == :boards
#js-board-labels-toggle
+ - if current_user
+ #js-board-epics-swimlanes-toggle
.js-board-config{ data: { can_admin_list: user_can_admin_list, has_scope: board.scoped? } }
- if user_can_admin_list
- = render 'shared/issuable/board_create_list_dropdown', board: board
+ - if Feature.enabled?(:board_new_list, board.resource_parent, default_enabled: :yaml)
+ .js-create-column-trigger{ data: board_list_data }
+ - else
+ = render 'shared/issuable/board_create_list_dropdown', board: board
- if @project
- #js-add-issues-btn.gl-ml-3{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
- - if current_user
- #js-board-epics-swimlanes-toggle
+ #js-add-issues-btn{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
#js-toggle-focus-btn
- elsif is_not_boards_modal_or_productivity_analytics && show_sorting_dropdown
= render 'shared/issuable/sort_dropdown'
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 911bef482dd..f26f4adc19a 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -8,7 +8,7 @@
- add_page_startup_api_call "#{issuable_sidebar[:issuable_json_path]}?serializer=sidebar_extras"
- reviewers = local_assigns.fetch(:reviewers, nil)
-%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
+%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': issuable_type }
.issuable-sidebar
.block.issuable-sidebar-header
- if signed_in
@@ -26,7 +26,7 @@
.block.assignee.qa-assignee-block
= render "shared/issuable/sidebar_assignees", issuable_sidebar: issuable_sidebar, assignees: assignees, signed_in: signed_in
- - if Feature.enabled?(:merge_request_reviewers, @project, default_enabled: true) && reviewers
+ - if reviewers
.block.reviewer.qa-reviewer-block
= render "shared/issuable/sidebar_reviewers", issuable_sidebar: issuable_sidebar, reviewers: reviewers, signed_in: signed_in
@@ -59,7 +59,7 @@
= f.hidden_field 'milestone_id', value: milestone[:id], id: nil
= dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable_type}[milestone_id]", project_id: issuable_sidebar[:project_id], issuable_id: issuable_sidebar[:id], ability_name: issuable_type, issue_update: issuable_sidebar[:issuable_json_path], use_id: true, default_no: true, selected: milestone[:title], null_default: true, display: 'static' }})
- if @project.group.present? && issuable_sidebar[:supports_iterations]
- = render_if_exists 'shared/issuable/iteration_select', can_edit: can_edit_issuable, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
+ = render_if_exists 'shared/issuable/iteration_select', can_edit: can_edit_issuable.to_s, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
- if issuable_sidebar[:supports_time_tracking]
#issuable-time-tracker.block
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index a7f435edb90..2b6920ed80f 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -5,7 +5,7 @@
= _('Assignee')
= loading_icon(css_class: 'gl-vertical-align-text-bottom')
-.selectbox.hide-collapsed
+.js-sidebar-assignee-data.selectbox.hide-collapsed
- if assignees.none?
= hidden_field_tag "#{issuable_type}[assignee_ids][]", 0, id: nil
- else
diff --git a/app/views/shared/issuable/_sidebar_todo.html.haml b/app/views/shared/issuable/_sidebar_todo.html.haml
index 7b5926fc186..a867421298b 100644
--- a/app/views/shared/issuable/_sidebar_todo.html.haml
+++ b/app/views/shared/issuable/_sidebar_todo.html.haml
@@ -6,10 +6,10 @@
- button_icon = has_todo ? todo_button_data[:mark_icon] : todo_button_data[:todo_icon]
%button.issuable-todo-btn.js-issuable-todo{ type: 'button',
- class: (is_collapsed ? 'btn-blank sidebar-collapsed-icon dont-change-state has-tooltip' : 'btn btn-default issuable-header-btn float-right'),
+ class: (is_collapsed ? 'btn-blank sidebar-collapsed-icon dont-change-state has-tooltip' : 'gl-button btn btn-default issuable-header-btn float-right'),
title: button_title,
'aria-label' => button_title,
data: todo_button_data }
%span.issuable-todo-inner.js-issuable-todo-inner<
= is_collapsed ? button_icon : button_title
- = loading_icon
+ = loading_icon(css_class: is_collapsed ? '' : 'gl-ml-3')
diff --git a/app/views/shared/issuable/csv_export/_button.html.haml b/app/views/shared/issuable/csv_export/_button.html.haml
index 3584c9c1ed5..8134b7eb161 100644
--- a/app/views/shared/issuable/csv_export/_button.html.haml
+++ b/app/views/shared/issuable/csv_export/_button.html.haml
@@ -1,4 +1,4 @@
- if current_user
- %button.csv_download_link.btn.gl-button.has-tooltip{ title: _('Export as CSV'),
+ %button.csv_download_link.btn.gl-button.btn-default.btn-icon.has-tooltip{ title: _('Export as CSV'),
data: { toggle: 'modal', target: ".#{issuable_type}-export-modal", qa_selector: 'export_as_csv_button' } }
= sprite_icon('export')
diff --git a/app/views/shared/issuable/form/_template_selector.html.haml b/app/views/shared/issuable/form/_template_selector.html.haml
index bf34ea4a1b2..c870bb17a85 100644
--- a/app/views/shared/issuable/form/_template_selector.html.haml
+++ b/app/views/shared/issuable/form/_template_selector.html.haml
@@ -1,9 +1,9 @@
- issuable = local_assigns.fetch(:issuable, nil)
-- return unless issuable && issuable_templates(issuable).any?
+- return unless issuable && issuable_templates(ref_project, issuable.to_ability_name).any?
.issuable-form-select-holder.selectbox.form-group
- .js-issuable-selector-wrap{ data: { issuable_type: issuable.to_ability_name } }
+ .js-issuable-selector-wrap{ data: { issuable_type: issuable.to_ability_name.pluralize, qa_selector: 'template_dropdown' } }
= template_dropdown_tag(issuable) do
%ul.dropdown-footer-list
%li
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index 98c9f73fa3a..94d0c395fa6 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -1,7 +1,7 @@
- issuable = local_assigns.fetch(:issuable)
- has_wip_commits = local_assigns.fetch(:has_wip_commits)
- form = local_assigns.fetch(:form)
-- no_issuable_templates = issuable_templates(issuable).empty?
+- no_issuable_templates = issuable_templates(ref_project, issuable.to_ability_name).empty?
- div_class = no_issuable_templates ? 'col-sm-10' : 'col-sm-7 col-lg-8'
- toggle_wip_link_start = '<a href="" class="js-toggle-wip">'
- toggle_wip_link_end = '</a>'
diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml
index d6226760ba5..7e150c544bd 100644
--- a/app/views/shared/issue_type/_details_header.html.haml
+++ b/app/views/shared/issue_type/_details_header.html.haml
@@ -1,12 +1,12 @@
.detail-page-header
.detail-page-header-body
.issuable-status-box.status-box.status-box-issue-closed{ class: issue_status_visibility(issuable, status_box: :closed) }
- = sprite_icon('mobile-issue-close', css_class: 'gl-display-block gl-display-sm-none!')
- .gl-display-none.gl-display-sm-block!
+ = sprite_icon('mobile-issue-close', css_class: 'gl-display-block gl-sm-display-none!')
+ .gl-display-none.gl-sm-display-block!
= issue_closed_text(issuable, current_user)
.issuable-status-box.status-box.status-box-open{ class: issue_status_visibility(issuable, status_box: :open) }
- = sprite_icon('issue-open-m', css_class: 'gl-display-block gl-display-sm-none!')
- %span.gl-display-none.gl-display-sm-block!
+ = sprite_icon('issue-open-m', css_class: 'gl-display-block gl-sm-display-none!')
+ %span.gl-display-none.gl-sm-display-block!
= _('Open')
.issuable-meta
diff --git a/app/views/shared/milestones/_labels_tab.html.haml b/app/views/shared/milestones/_labels_tab.html.haml
index a419e749f35..d2bee57992d 100644
--- a/app/views/shared/milestones/_labels_tab.html.haml
+++ b/app/views/shared/milestones/_labels_tab.html.haml
@@ -8,7 +8,7 @@
= markdown_field(label, :description)
.float-right.d-none.d-lg-block
- = link_to milestones_issues_path(options.merge(state: 'opened')), class: 'btn gl-button btn-default-tertiary btn-action' do
+ = link_to milestones_issues_path(options.merge(state: 'opened')), class: 'btn gl-button btn-default-tertiary' do
- pluralize milestone_issues_by_label_count(@milestone, label, state: :opened), _('open issue')
- = link_to milestones_issues_path(options.merge(state: 'closed')), class: 'btn gl-button btn-default-tertiary btn-action' do
+ = link_to milestones_issues_path(options.merge(state: 'closed')), class: 'btn gl-button btn-default-tertiary' do
- pluralize milestone_issues_by_label_count(@milestone, label, state: :closed), _('closed issue')
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 48a97ed66bb..4301bf01858 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -29,10 +29,10 @@
%div
= render('shared/milestone_expired', milestone: milestone)
- if milestone.group_milestone?
- .label-badge.gl-bg-blue-50.d-inline-block
+ .gl-badge.badge-info.badge-pill
= milestone.group.full_name
- if milestone.project_milestone?
- .label-badge.gl-bg-gray-50.d-inline-block
+ .gl-badge.badge-muted.badge-pill
= milestone.project.full_name
.col-sm-4.milestone-progress
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index d9d7d18c732..661ace8feaa 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -1,7 +1,7 @@
- affix_offset = local_assigns.fetch(:affix_offset, "50")
- project = local_assigns[:project]
-%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
+%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': _('Milestone') }
.issuable-sidebar.milestone-sidebar
.block.milestone-progress.issuable-sidebar-header
%a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", href: "#", "aria-label" => s_('MilestoneSidebar|Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }
diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml
index eb03608e18a..4f1aa3a7b01 100644
--- a/app/views/shared/notes/_comment_button.html.haml
+++ b/app/views/shared/notes/_comment_button.html.haml
@@ -1,15 +1,15 @@
- noteable_name = @note.noteable.human_class_name
.float-left.btn-group.gl-mr-3.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
- %input.btn.btn-success.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment'), data: { qa_selector: 'comment_button' } }
+ %input.btn.gl-button.btn-success.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment'), data: { qa_selector: 'comment_button' } }
- if @note.can_be_discussion_note?
- = button_tag type: 'button', class: 'btn dropdown-toggle btn-success js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => _('Open comment type dropdown') do
+ = button_tag type: 'button', class: 'gl-button btn dropdown-toggle btn-success js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => _('Open comment type dropdown') do
= sprite_icon('chevron-down')
%ul#resolvable-comment-menu.dropdown-menu.dropdown-open-top{ data: { dropdown: true } }
%li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => _('Comment'), 'close-text' => _("Comment & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Comment & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
- %button.btn.btn-transparent
+ %button.btn.gl-button.btn-transparent
= sprite_icon('check', css_class: 'icon')
.description
%strong= _("Comment")
@@ -19,7 +19,7 @@
%li.divider.droplab-item-ignore
%li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => _('Start thread'), 'close-text' => _("Start thread & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Start thread & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
- %button.btn.btn-transparent
+ %button.btn.gl-button.btn-transparent
= sprite_icon('check', css_class: 'icon')
.description
%strong= _("Start thread")
diff --git a/app/views/shared/notes/_edit_form.html.haml b/app/views/shared/notes/_edit_form.html.haml
index d783fa0d777..63c895a5a03 100644
--- a/app/views/shared/notes/_edit_form.html.haml
+++ b/app/views/shared/notes/_edit_form.html.haml
@@ -1,4 +1,4 @@
-.note-edit-form
+.snippets.note-edit-form
= form_tag '#', method: :put, class: 'edit-note common-note-form js-quick-submit' do
= hidden_field_tag :target_id, '', class: 'js-form-target-id'
= hidden_field_tag :target_type, '', class: 'js-form-target-type'
@@ -9,6 +9,6 @@
.note-form-actions.clearfix
.settings-message.note-edit-warning.js-finish-edit-warning
= _("Finish editing this message first!")
- = submit_tag _('Save comment'), class: 'btn btn-success js-comment-save-button', data: { qa_selector: 'save_comment_button' }
- %button.btn.btn-cancel.note-edit-cancel{ type: 'button' }
+ = submit_tag _('Save comment'), class: 'gl-button btn btn-success js-comment-save-button', data: { qa_selector: 'save_comment_button' }
+ %button.btn.gl-button.btn-cancel.note-edit-cancel{ type: 'button' }
= _("Cancel")
diff --git a/app/views/shared/notes/_form.html.haml b/app/views/shared/notes/_form.html.haml
index 2cf074b9d3f..6f54c54d0a9 100644
--- a/app/views/shared/notes/_form.html.haml
+++ b/app/views/shared/notes/_form.html.haml
@@ -38,5 +38,5 @@
.note-form-actions.clearfix
= render partial: 'shared/notes/comment_button'
- %a.btn.btn-cancel.js-close-discussion-note-form.hide{ role: "button", data: { cancel_text: _("Cancel") } }
+ %a.btn.gl-button.btn-cancel.js-close-discussion-note-form.hide{ role: "button", data: { cancel_text: _("Cancel") } }
= _('Cancel')
diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml
index 1b03225d48d..f7f5c02370d 100644
--- a/app/views/shared/notes/_notes_with_form.html.haml
+++ b/app/views/shared/notes/_notes_with_form.html.haml
@@ -12,9 +12,6 @@
.timeline-entry-inner
.flash-container.timeline-content
- .timeline-icon.d-none.d-md-block
- %a.author-link{ href: user_path(current_user) }
- = image_tag avatar_icon_for_user(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
- elsif !current_user
diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml
index 14f4b04ef78..4b008601783 100644
--- a/app/views/shared/notifications/_new_button.html.haml
+++ b/app/views/shared/notifications/_new_button.html.haml
@@ -17,14 +17,14 @@
.js-notification-toggle-btns
%div{ class: ("btn-group" if notification_setting.custom?) }
- if notification_setting.custom?
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => button_title, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
+ %button.dropdown-new.btn.gl-button.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => button_title, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= notification_setting_icon(notification_setting)
%span.js-notification-loading.fa.hidden
- %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" }
+ %button.btn.gl-button.btn-default.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" }
= sprite_icon("chevron-down", css_class: "icon mr-0")
.sr-only Toggle dropdown
- else
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => button_title, data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
+ %button.dropdown-new.btn.gl-button.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => button_title, data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= notification_setting_icon(notification_setting)
%span.js-notification-loading.fa.hidden
= sprite_icon("chevron-down", css_class: "icon")
diff --git a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
index cb954c20b48..d1b32df7139 100644
--- a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
+++ b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
@@ -1,5 +1,3 @@
-- select_mode_for_dropdown = Feature.enabled?(:deploy_keys_on_protected_branches, protected_branch.project) ? 'js-multiselect' : ''
-
- merge_access_levels = protected_branch.merge_access_levels.for_role
- push_access_levels = protected_branch.push_access_levels.for_role
@@ -25,7 +23,7 @@
%td.push_access_levels-container
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", push_access_levels.first&.access_level
= dropdown_tag( (push_access_levels.first&.humanize || 'Select') ,
- options: { toggle_class: "js-allowed-to-push #{select_mode_for_dropdown}", dropdown_class: 'dropdown-menu-selectable js-allowed-to-push-container capitalize-header',
+ options: { toggle_class: "js-allowed-to-push js-multiselect", dropdown_class: 'dropdown-menu-selectable js-allowed-to-push-container capitalize-header',
data: { field_name: "allowed_to_push_#{protected_branch.id}", preselected_items: access_levels_data(push_access_levels) }})
- if user_push_access_levels.any?
%p.small
diff --git a/app/views/shared/ssh_keys/_key_delete.html.haml b/app/views/shared/ssh_keys/_key_delete.html.haml
new file mode 100644
index 00000000000..1526e5d3eda
--- /dev/null
+++ b/app/views/shared/ssh_keys/_key_delete.html.haml
@@ -0,0 +1,6 @@
+- if defined?(text)
+ = button_to text, '#', class: html_class, data: button_data
+- else
+ = button_to '#', class: html_class, data: button_data do
+ %span.sr-only= _('Delete')
+ = sprite_icon('remove')
diff --git a/app/views/shared/users/_user.html.haml b/app/views/shared/users/_user.html.haml
new file mode 100644
index 00000000000..f92c12102bb
--- /dev/null
+++ b/app/views/shared/users/_user.html.haml
@@ -0,0 +1,13 @@
+- user = local_assigns.fetch(:user)
+
+.col-lg-3.col-md-4.col-sm-12
+ .gl-card.gl-mb-5
+ .gl-card-body
+ = image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
+
+ .user-info
+ .block-truncated
+ = link_to user.name, user_path(user), class: 'user js-user-link', data: { user_id: user.id }
+
+ .block-truncated
+ %span.gl-text-gray-900= user.to_reference
diff --git a/app/views/shared/users/index.html.haml b/app/views/shared/users/index.html.haml
new file mode 100644
index 00000000000..dd6b14d6be2
--- /dev/null
+++ b/app/views/shared/users/index.html.haml
@@ -0,0 +1,20 @@
+- followers_illustration_path = 'illustrations/starred_empty.svg'
+- followers_visitor_empty_message = s_('UserProfile|This user doesn\'t have any followers.')
+- followers_current_user_empty_message_header = s_('UserProfile|You do not have any followers.')
+- following_illustration_path = 'illustrations/starred_empty.svg'
+- following_visitor_empty_message = s_('UserProfile|This user isn\'t following other users.')
+- following_current_user_empty_message_header = s_('UserProfile|You are not following other users.')
+
+- if users.size > 0
+ .row.gl-mt-3
+ = render partial: 'shared/users/user', collection: users, as: :user
+ = paginate users, theme: 'gitlab'
+- else
+ - if @user_followers
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: followers_illustration_path,
+ visitor_empty_message: followers_visitor_empty_message,
+ current_user_empty_message_header: followers_current_user_empty_message_header}
+ - elsif @user_following
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: following_illustration_path,
+ visitor_empty_message: following_visitor_empty_message,
+ current_user_empty_message_header: following_current_user_empty_message_header}
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index c37a34f9be8..ad84ce1d343 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -2,96 +2,99 @@
.form-group
= form.label :url, s_('Webhooks|URL'), class: 'label-bold'
- = form.text_field :url, class: 'form-control', placeholder: 'http://example.com/trigger-ci.json'
+ = form.text_field :url, class: 'form-control gl-form-input', placeholder: 'http://example.com/trigger-ci.json'
+ %p.form-text.text-muted
+ = s_('Webhooks|URL must be percent-encoded if neccessary.')
.form-group
- = form.label :token, s_('Webhooks|Secret Token'), class: 'label-bold'
- = form.text_field :token, class: 'form-control', placeholder: ''
+ = form.label :token, s_('Webhooks|Secret token'), class: 'label-bold'
+ = form.text_field :token, class: 'form-control gl-form-input', placeholder: ''
%p.form-text.text-muted
- = s_('Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header.')
+ = s_('Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header.')
.form-group
= form.label :url, s_('Webhooks|Trigger'), class: 'label-bold'
%ul.list-unstyled.gl-ml-6
%li
= form.check_box :push_events, class: 'form-check-input'
- = form.label :push_events, class: 'list-label form-check-label gl-ml-1' do
+ = form.label :push_events, class: 'list-label form-check-label gl-ml-1 gl-mb-3' do
%strong= s_('Webhooks|Push events')
- = form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
+ = form.text_field :push_events_branch_filter, class: 'form-control gl-form-input', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered by a push to the repository')
+ = s_('Webhooks|URL is triggered by a push to the repository')
%li
= form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Tag push events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when a new tag is pushed to the repository')
+ = s_('Webhooks|URL is triggered when a new tag is pushed to the repository')
%li
= form.check_box :note_events, class: 'form-check-input'
= form.label :note_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Comments')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when someone adds a comment')
+ = s_('Webhooks|URL is triggered when someone adds a comment')
%li
= form.check_box :confidential_note_events, class: 'form-check-input'
= form.label :confidential_note_events, class: 'list-label form-check-label gl-ml-1' do
- %strong= s_('Webhooks|Confidential Comments')
+ %strong= s_('Webhooks|Confidential comments')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when someone adds a comment on a confidential issue')
+ = s_('Webhooks|URL is triggered when someone adds a comment on a confidential issue')
%li
= form.check_box :issues_events, class: 'form-check-input'
= form.label :issues_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Issues events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when an issue is created/updated/merged')
+ = s_('Webhooks|URL is triggered when an issue is created, updated, or merged')
%li
= form.check_box :confidential_issues_events, class: 'form-check-input'
= form.label :confidential_issues_events, class: 'list-label form-check-label gl-ml-1' do
- %strong= s_('Webhooks|Confidential Issues events')
+ %strong= s_('Webhooks|Confidential issues events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when a confidential issue is created/updated/merged')
+ = s_('Webhooks|URL is triggered when a confidential issue is created, updated, or merged')
- if @group
= render_if_exists 'groups/hooks/member_events', form: form
+ = render_if_exists 'groups/hooks/subgroup_events', form: form
%li
= form.check_box :merge_requests_events, class: 'form-check-input'
= form.label :merge_requests_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Merge request events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when a merge request is created/updated/merged')
+ = s_('Webhooks|URL is triggered when a merge request is created, updated, or merged')
%li
= form.check_box :job_events, class: 'form-check-input'
= form.label :job_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Job events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when the job status changes')
+ = s_('Webhooks|URL is triggered when the job status changes')
%li
= form.check_box :pipeline_events, class: 'form-check-input'
= form.label :pipeline_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Pipeline events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when the pipeline status changes')
+ = s_('Webhooks|URL is triggered when the pipeline status changes')
%li
= form.check_box :wiki_page_events, class: 'form-check-input'
= form.label :wiki_page_events, class: 'list-label form-check-label gl-ml-1' do
- %strong= s_('Webhooks|Wiki Page events')
+ %strong= s_('Webhooks|Wiki page events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL will be triggered when a wiki page is created/updated')
+ = s_('Webhooks|URL is triggered when a wiki page is created or updated')
%li
= form.check_box :deployment_events, class: 'form-check-input'
= form.label :deployment_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Deployment events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled')
+ = s_('Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled')
%li
= form.check_box :feature_flag_events, class: 'form-check-input'
= form.label :feature_flag_events, class: 'list-label form-check-label gl-ml-1' do
- %strong= s_('Webhooks|Feature Flag events')
+ %strong= s_('Webhooks|Feature flag events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL is triggered when a feature flag is turned on or off')
+ = s_('Webhooks|URL is triggered when a feature flag is turned on or off')
%li
= form.check_box :releases_events, class: 'form-check-input'
= form.label :releases_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Releases events')
%p.text-muted.gl-ml-1
- = s_('Webhooks|This URL is triggered when a release is created/updated')
+ = s_('Webhooks|URL is triggered when a release is created or updated')
.form-group
= form.label :enable_ssl_verification, s_('Webhooks|SSL verification'), class: 'label-bold checkbox'
.form-check
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index 13fe8f76bd3..5437748a57e 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -12,5 +12,5 @@
.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 gl-mr-3'
- %span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn btn-sm gl-mr-3'
- = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn btn-sm'
+ %span>= link_to _('Edit'), edit_hook_path(hook), class: 'gl-button btn btn-sm gl-mr-3'
+ = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'gl-button btn btn-sm'
diff --git a/app/views/shared/web_hooks/_test_button.html.haml b/app/views/shared/web_hooks/_test_button.html.haml
index c46b8a99886..a683f75c779 100644
--- a/app/views/shared/web_hooks/_test_button.html.haml
+++ b/app/views/shared/web_hooks/_test_button.html.haml
@@ -3,7 +3,7 @@
- triggers = hook.class.triggers
.hook-test-button.dropdown.inline>
- %button.btn{ 'data-toggle' => 'dropdown', class: button_class }
+ %button.btn.gl-button{ 'data-toggle' => 'dropdown', class: button_class }
= _('Test')
= sprite_icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right{ role: 'menu' }
diff --git a/app/views/shared/wikis/_sidebar.html.haml b/app/views/shared/wikis/_sidebar.html.haml
index 4e9fdc8b95a..5f181371663 100644
--- a/app/views/shared/wikis/_sidebar.html.haml
+++ b/app/views/shared/wikis/_sidebar.html.haml
@@ -1,6 +1,6 @@
- editing ||= false
-%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" } }
+%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" }, 'aria-label': _('Wiki') }
.sidebar-container
.block.wiki-sidebar-header.gl-mb-3.w-100
%a.gutter-toggle.float-right.d-block.d-md-none.js-sidebar-wiki-toggle{ href: "#" }
diff --git a/app/views/users/show.atom.builder b/app/views/users/show.atom.builder
index e95814875f1..43e67347cd0 100644
--- a/app/views/users/show.atom.builder
+++ b/app/views/users/show.atom.builder
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
xml.title "#{@user.name} activity"
xml.link href: user_url(@user, :atom), rel: "self", type: "application/atom+xml"
xml.link href: user_url(@user), rel: "alternate", type: "text/html"
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 9f6b0bc2373..cdaa739a7b3 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -14,22 +14,31 @@
.cover-block.user-cover-block{ class: [('border-bottom' if profile_tabs.empty?)] }
= render layout: 'users/cover_controls' do
- if @user == current_user
- = link_to profile_path, class: link_classes + 'btn gl-button btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do
+ = link_to profile_path, class: link_classes + 'btn gl-button btn-default btn-icon has-tooltip',
+ title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('pencil')
- elsif current_user
- if @user.abuse_report
- %button{ class: link_classes + 'btn gl-button btn-danger', title: s_('UserProfile|Already reported for abuse'),
+ %button{ class: link_classes + 'btn gl-button btn-danger btn-icon', title: s_('UserProfile|Already reported for abuse'),
data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } }>
= sprite_icon('error')
- else
- = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: link_classes + 'btn gl-button',
+ = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: link_classes + 'btn gl-button btn-default btn-icon',
title: s_('UserProfile|Report abuse'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('error')
+ - if current_user && current_user.id != @user.id
+ - if current_user.following?(@user)
+ = link_to user_unfollow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
+ = _('Unfollow')
+ - else
+ = link_to user_follow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
+ = _('Follow')
- if can?(current_user, :read_user_profile, @user)
- = link_to user_path(@user, rss_url_options), class: link_classes + 'btn gl-button btn-svg btn-default has-tooltip', title: s_('UserProfile|Subscribe'), 'aria-label': 'Subscribe' do
+ = link_to user_path(@user, rss_url_options), class: link_classes + 'btn gl-button btn-default btn-icon has-tooltip',
+ title: s_('UserProfile|Subscribe'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= sprite_icon('rss', css_class: 'qa-rss-icon')
- if current_user && current_user.admin?
- = link_to [:admin, @user], class: link_classes + 'btn gl-button btn-default', title: s_('UserProfile|View user in admin area'),
+ = link_to [:admin, @user], class: link_classes + 'btn gl-button btn-default btn-icon', title: s_('UserProfile|View user in admin area'),
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('user')
@@ -51,8 +60,8 @@
%span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle= s_("UserProfile|(Busy)")
- if show_status_emoji?(@user.status)
- .cover-status
- = emoji_icon(@user.status.emoji)
+ .cover-status.gl-display-inline-flex.gl-align-items-center
+ = emoji_icon(@user.status.emoji, class: 'gl-mr-2')
= markdown_field(@user.status, :message)
= render "users/profile_basic_info"
.cover-desc.cgray.mb-1.mb-sm-2
@@ -87,6 +96,16 @@
- unless @user.public_email.blank?
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
= link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link', itemprop: 'email'
+ .cover-desc.gl-text-gray-900.gl-mb-2.mb-sm-2
+ = sprite_icon('users', css_class: 'gl-vertical-align-middle gl-text-gray-500')
+ .profile-link-holder.middle-dot-divider
+ = link_to user_followers_path, class: 'text-link' do
+ - count = @user.followers.count
+ = n_('1 follower', '%{count} followers', count) % { count: count }
+ .profile-link-holder.middle-dot-divider
+ = link_to user_following_path, class: 'text-link' do
+ = @user.followees.count
+ = _('following')
- if @user.bio.present?
.cover-desc.cgray
.profile-user-bio
@@ -127,6 +146,14 @@
%li.js-snippets-tab
= link_to user_snippets_path, data: { target: 'div#snippets', action: 'snippets', toggle: 'tab', endpoint: user_snippets_path(format: :json) } do
= s_('UserProfile|Snippets')
+ - if profile_tab?(:followers)
+ %li.js-followers-tab
+ = link_to user_followers_path, data: { target: 'div#followers', action: 'followers', toggle: 'tab', endpoint: user_followers_path(format: :json) } do
+ = s_('UserProfile|Followers')
+ - if profile_tab?(:following)
+ %li.js-following-tab
+ = link_to user_following_path, data: { target: 'div#following', action: 'following', toggle: 'tab', endpoint: user_following_path(format: :json) } do
+ = s_('UserProfile|Following')
%div{ class: container_class }
.tab-content
@@ -163,6 +190,14 @@
#snippets.tab-pane
-# This tab is always loaded via AJAX
+ - if profile_tab?(:followers)
+ #followers.tab-pane
+ -# This tab is always loaded via AJAX
+
+ - if profile_tab?(:following)
+ #following.tab-pane
+ -# This tab is always loaded via AJAX
+
.loading.hide
.spinner.spinner-md
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 4c4a314a1e6..59ab0a4d05b 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -251,6 +251,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: cronjob:namespaces_in_product_marketing_emails
+ :feature_category: :subgroups
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: cronjob:namespaces_prune_aggregation_schedules
:feature_category: :source_code_management
:has_external_dependencies:
@@ -259,6 +267,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:packages_composer_cache_cleanup
+ :feature_category: :package_registry
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:pages_domain_removal_cron
:feature_category: :pages
:has_external_dependencies:
@@ -459,6 +475,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: cronjob:user_status_cleanup_batch
+ :feature_category: :users
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:users_create_statistics
:feature_category: :users
:has_external_dependencies:
@@ -1076,24 +1100,23 @@
:idempotent:
:tags:
- :requires_disk_io
-- :name: pipeline_background:ci_build_report_result
+- :name: pipeline_background:ci_build_trace_chunk_flush
:feature_category: :continuous_integration
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
- :tags:
- - :requires_disk_io
-- :name: pipeline_background:ci_build_trace_chunk_flush
- :feature_category: :continuous_integration
+ :tags: []
+- :name: pipeline_background:ci_daily_build_group_report_results
+ :feature_category: :code_testing
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
-- :name: pipeline_background:ci_daily_build_group_report_results
+- :name: pipeline_background:ci_pipeline_artifacts_coverage_report
:feature_category: :code_testing
:has_external_dependencies:
:urgency: :low
@@ -1101,7 +1124,7 @@
:weight: 1
:idempotent: true
:tags: []
-- :name: pipeline_background:ci_pipeline_artifacts_coverage_report
+- :name: pipeline_background:ci_pipeline_artifacts_create_quality_report
:feature_category: :code_testing
:has_external_dependencies:
:urgency: :low
@@ -1165,24 +1188,6 @@
:weight: 4
:idempotent:
:tags: []
-- :name: pipeline_default:build_coverage
- :feature_category: :continuous_integration
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 3
- :idempotent:
- :tags:
- - :requires_disk_io
-- :name: pipeline_default:build_trace_sections
- :feature_category: :continuous_integration
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 3
- :idempotent:
- :tags:
- - :requires_disk_io
- :name: pipeline_default:ci_create_cross_project_pipeline
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1999,6 +2004,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: projects_git_garbage_collect
+ :feature_category: :gitaly
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: prometheus_create_default_alerts
:feature_category: :incident_management
:has_external_dependencies:
@@ -2223,6 +2236,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: wikis_git_garbage_collect
+ :feature_category: :gitaly
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: x509_certificate_revoke
:feature_category: :source_code_management
:has_external_dependencies:
diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb
index f5132459131..6e07d6d0f71 100644
--- a/app/workers/authorized_projects_worker.rb
+++ b/app/workers/authorized_projects_worker.rb
@@ -25,7 +25,7 @@ class AuthorizedProjectsWorker
def perform(user_id)
user = User.find_by(id: user_id)
- user&.refresh_authorized_projects
+ user&.refresh_authorized_projects(source: self.class.name)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/build_coverage_worker.rb b/app/workers/build_coverage_worker.rb
deleted file mode 100644
index d63d8549f09..00000000000
--- a/app/workers/build_coverage_worker.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class BuildCoverageWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
- include PipelineQueue
-
- tags :requires_disk_io
-
- # rubocop: disable CodeReuse/ActiveRecord
- def perform(build_id)
- Ci::Build.find_by(id: build_id)&.update_coverage
- end
- # rubocop: enable CodeReuse/ActiveRecord
-end
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index d7a5fcf4f18..4d15bcd16f7 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -29,9 +29,9 @@ class BuildFinishedWorker # rubocop:disable Scalability/IdempotentWorker
# @param [Ci::Build] build The build to process.
def process_build(build)
# We execute these in sync to reduce IO.
- BuildTraceSectionsWorker.new.perform(build.id)
- BuildCoverageWorker.new.perform(build.id)
- Ci::BuildReportResultWorker.new.perform(build.id)
+ build.parse_trace_sections!
+ build.update_coverage
+ Ci::BuildReportResultService.new.execute(build)
# We execute these async as these are independent operations.
BuildHooksWorker.perform_async(build.id)
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index 9693d3eb57f..ce4aa7229aa 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -10,7 +10,8 @@ class BuildHooksWorker # rubocop:disable Scalability/IdempotentWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
- Ci::Build.find_by(id: build_id)
+ Ci::Build.includes({ runner: :tags })
+ .find_by(id: build_id)
.try(:execute_hooks)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/build_trace_sections_worker.rb b/app/workers/build_trace_sections_worker.rb
deleted file mode 100644
index 59f019b827e..00000000000
--- a/app/workers/build_trace_sections_worker.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class BuildTraceSectionsWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
- include PipelineQueue
-
- tags :requires_disk_io
-
- # rubocop: disable CodeReuse/ActiveRecord
- def perform(build_id)
- Ci::Build.find_by(id: build_id)&.parse_trace_sections!
- end
- # rubocop: enable CodeReuse/ActiveRecord
-end
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
index 81099d4e5f7..e6bc54895a7 100644
--- a/app/workers/bulk_import_worker.rb
+++ b/app/workers/bulk_import_worker.rb
@@ -27,6 +27,10 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
end
re_enqueue
+ rescue => e
+ Gitlab::ErrorTracking.track_exception(e, bulk_import_id: @bulk_import&.id)
+
+ @bulk_import&.fail_op
end
private
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
index 9b29ad8f326..5b41ccbdea1 100644
--- a/app/workers/bulk_imports/entity_worker.rb
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -18,6 +18,16 @@ module BulkImports
BulkImports::Importers::GroupImporter.new(entity).execute
end
+
+ rescue => e
+ extra = {
+ bulk_import_id: entity&.bulk_import&.id,
+ entity_id: entity&.id
+ }
+
+ Gitlab::ErrorTracking.track_exception(e, extra)
+
+ entity&.fail_op
end
end
end
diff --git a/app/workers/ci/build_report_result_worker.rb b/app/workers/ci/build_report_result_worker.rb
deleted file mode 100644
index 01a45490541..00000000000
--- a/app/workers/ci/build_report_result_worker.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class BuildReportResultWorker
- include ApplicationWorker
- include PipelineBackgroundQueue
-
- tags :requires_disk_io
-
- idempotent!
-
- def perform(build_id)
- Ci::Build.find_by_id(build_id).try do |build|
- Ci::BuildReportResultService.new.execute(build)
- end
- end
- end
-end
diff --git a/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb b/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb
new file mode 100644
index 00000000000..810106e8d9c
--- /dev/null
+++ b/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class CreateQualityReportWorker
+ include ApplicationWorker
+
+ queue_namespace :pipeline_background
+ feature_category :code_testing
+
+ idempotent!
+
+ def perform(pipeline_id)
+ Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
+ Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService.new.execute(pipeline)
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/concerns/git_garbage_collect_methods.rb b/app/workers/concerns/git_garbage_collect_methods.rb
new file mode 100644
index 00000000000..17a80d1ddb3
--- /dev/null
+++ b/app/workers/concerns/git_garbage_collect_methods.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+module GitGarbageCollectMethods
+ extend ActiveSupport::Concern
+
+ included do
+ include ApplicationWorker
+
+ sidekiq_options retry: false
+ feature_category :gitaly
+ loggable_arguments 1, 2, 3
+ end
+
+ # Timeout set to 24h
+ LEASE_TIMEOUT = 86400
+
+ def perform(resource_id, task = :gc, lease_key = nil, lease_uuid = nil)
+ resource = find_resource(resource_id)
+ lease_key ||= default_lease_key(task, resource)
+ active_uuid = get_lease_uuid(lease_key)
+
+ if active_uuid
+ return unless active_uuid == lease_uuid
+
+ renew_lease(lease_key, active_uuid)
+ else
+ lease_uuid = try_obtain_lease(lease_key)
+
+ return unless lease_uuid
+ end
+
+ task = task.to_sym
+
+ before_gitaly_call(task, resource)
+ gitaly_call(task, resource)
+
+ # Refresh the branch cache in case garbage collection caused a ref lookup to fail
+ flush_ref_caches(resource) if gc?(task)
+
+ update_repository_statistics(resource) if task != :pack_refs
+
+ # In case pack files are deleted, release libgit2 cache and open file
+ # descriptors ASAP instead of waiting for Ruby garbage collection
+ resource.cleanup
+ ensure
+ cancel_lease(lease_key, lease_uuid) if lease_key.present? && lease_uuid.present?
+ end
+
+ private
+
+ def default_lease_key(task, resource)
+ "git_gc:#{task}:#{resource.class.name.underscore.pluralize}:#{resource.id}"
+ end
+
+ def find_resource(id)
+ raise NotImplementedError
+ end
+
+ def gc?(task)
+ task == :gc || task == :prune
+ end
+
+ def try_obtain_lease(key)
+ ::Gitlab::ExclusiveLease.new(key, timeout: LEASE_TIMEOUT).try_obtain
+ end
+
+ def renew_lease(key, uuid)
+ ::Gitlab::ExclusiveLease.new(key, uuid: uuid, timeout: LEASE_TIMEOUT).renew
+ end
+
+ def cancel_lease(key, uuid)
+ ::Gitlab::ExclusiveLease.cancel(key, uuid)
+ end
+
+ def get_lease_uuid(key)
+ ::Gitlab::ExclusiveLease.get_uuid(key)
+ end
+
+ def before_gitaly_call(task, resource)
+ # no-op
+ end
+
+ def gitaly_call(task, resource)
+ repository = resource.repository.raw_repository
+
+ client = get_gitaly_client(task, repository)
+
+ case task
+ when :prune, :gc
+ client.garbage_collect(bitmaps_enabled?, prune: task == :prune)
+ when :full_repack
+ client.repack_full(bitmaps_enabled?)
+ when :incremental_repack
+ client.repack_incremental
+ when :pack_refs
+ client.pack_refs
+ end
+ rescue GRPC::NotFound => e
+ Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found")
+ raise Gitlab::Git::Repository::NoRepository.new(e)
+ rescue GRPC::BadStatus => e
+ Gitlab::GitLogger.error("#{__method__} failed:\n#{e}")
+ raise Gitlab::Git::CommandError.new(e)
+ end
+
+ def get_gitaly_client(task, repository)
+ if task == :pack_refs
+ Gitlab::GitalyClient::RefService
+ else
+ Gitlab::GitalyClient::RepositoryService
+ end.new(repository)
+ end
+
+ def bitmaps_enabled?
+ Gitlab::CurrentSettings.housekeeping_bitmaps_enabled
+ end
+
+ def flush_ref_caches(resource)
+ resource.repository.expire_branches_cache
+ resource.repository.branch_names
+ resource.repository.has_visible_content?
+ end
+
+ def update_repository_statistics(resource)
+ resource.repository.expire_statistics_caches
+
+ return if Gitlab::Database.read_only? # GitGarbageCollectWorker may be run on a Geo secondary
+
+ update_db_repository_statistics(resource)
+ end
+
+ def update_db_repository_statistics(resource)
+ # no-op
+ end
+end
diff --git a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
index 7c86b194574..53220a7afed 100644
--- a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
+++ b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb
@@ -18,6 +18,7 @@ module ContainerExpirationPolicies
cleanup_tags_service_before_truncate_size
cleanup_tags_service_after_truncate_size
cleanup_tags_service_before_delete_size
+ cleanup_tags_service_deleted_size
].freeze
def perform_work
@@ -25,6 +26,7 @@ module ContainerExpirationPolicies
return unless container_repository
log_extra_metadata_on_done(:container_repository_id, container_repository.id)
+ log_extra_metadata_on_done(:project_id, project.id)
unless allowed_to_run?(container_repository)
container_repository.cleanup_unscheduled!
@@ -78,7 +80,7 @@ module ContainerExpirationPolicies
end
def project
- container_repository&.project
+ container_repository.project
end
def container_repository
@@ -116,6 +118,7 @@ module ContainerExpirationPolicies
after_truncate_size &&
before_truncate_size != after_truncate_size
log_extra_metadata_on_done(:cleanup_tags_service_truncated, !!truncated)
+ log_extra_metadata_on_done(:running_jobs_count, running_jobs_count)
end
end
end
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
index e1dcb16bafb..a2aab23db7b 100644
--- a/app/workers/git_garbage_collect_worker.rb
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -1,5 +1,11 @@
# frozen_string_literal: true
+# According to our docs, we can only remove workers on major releases
+# https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#removing-workers.
+#
+# We need to still maintain this until 14.0 but with the current functionality.
+#
+# In https://gitlab.com/gitlab-org/gitlab/-/issues/299290 we track that removal.
class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
@@ -7,117 +13,7 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :gitaly
loggable_arguments 1, 2, 3
- # Timeout set to 24h
- LEASE_TIMEOUT = 86400
-
def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil)
- lease_key ||= "git_gc:#{task}:#{project_id}"
- project = Project.find(project_id)
- active_uuid = get_lease_uuid(lease_key)
-
- if active_uuid
- return unless active_uuid == lease_uuid
-
- renew_lease(lease_key, active_uuid)
- else
- lease_uuid = try_obtain_lease(lease_key)
-
- return unless lease_uuid
- end
-
- task = task.to_sym
-
- if gc?(task)
- ::Projects::GitDeduplicationService.new(project).execute
- cleanup_orphan_lfs_file_references(project)
- end
-
- gitaly_call(task, project)
-
- # Refresh the branch cache in case garbage collection caused a ref lookup to fail
- flush_ref_caches(project) if gc?(task)
-
- update_repository_statistics(project) if task != :pack_refs
-
- # In case pack files are deleted, release libgit2 cache and open file
- # descriptors ASAP instead of waiting for Ruby garbage collection
- project.cleanup
- ensure
- cancel_lease(lease_key, lease_uuid) if lease_key.present? && lease_uuid.present?
- end
-
- private
-
- def gc?(task)
- task == :gc || task == :prune
- end
-
- def try_obtain_lease(key)
- ::Gitlab::ExclusiveLease.new(key, timeout: LEASE_TIMEOUT).try_obtain
- end
-
- def renew_lease(key, uuid)
- ::Gitlab::ExclusiveLease.new(key, uuid: uuid, timeout: LEASE_TIMEOUT).renew
- end
-
- def cancel_lease(key, uuid)
- ::Gitlab::ExclusiveLease.cancel(key, uuid)
- end
-
- def get_lease_uuid(key)
- ::Gitlab::ExclusiveLease.get_uuid(key)
- end
-
- def gitaly_call(task, project)
- repository = project.repository.raw_repository
-
- client = if task == :pack_refs
- Gitlab::GitalyClient::RefService.new(repository)
- else
- Gitlab::GitalyClient::RepositoryService.new(repository)
- end
-
- case task
- when :prune, :gc
- client.garbage_collect(bitmaps_enabled?, prune: task == :prune)
- when :full_repack
- client.repack_full(bitmaps_enabled?)
- when :incremental_repack
- client.repack_incremental
- when :pack_refs
- client.pack_refs
- end
- rescue GRPC::NotFound => e
- Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found")
- raise Gitlab::Git::Repository::NoRepository.new(e)
- rescue GRPC::BadStatus => e
- Gitlab::GitLogger.error("#{__method__} failed:\n#{e}")
- raise Gitlab::Git::CommandError.new(e)
- end
-
- def cleanup_orphan_lfs_file_references(project)
- return if Gitlab::Database.read_only? # GitGarbageCollectWorker may be run on a Geo secondary
-
- ::Gitlab::Cleanup::OrphanLfsFileReferences.new(project, dry_run: false, logger: logger).run!
- rescue => err
- Gitlab::GitLogger.warn(message: "Cleaning up orphan LFS objects files failed", error: err.message)
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(err)
- end
-
- def flush_ref_caches(project)
- project.repository.expire_branches_cache
- project.repository.branch_names
- project.repository.has_visible_content?
- end
-
- def update_repository_statistics(project)
- project.repository.expire_statistics_caches
- return if Gitlab::Database.read_only? # GitGarbageCollectWorker may be run on a Geo secondary
-
- Projects::UpdateStatisticsService.new(project, nil, statistics: [:repository_size, :lfs_objects_size]).execute
- end
-
- def bitmaps_enabled?
- Gitlab::CurrentSettings.housekeeping_bitmaps_enabled
+ ::Projects::GitGarbageCollectWorker.new.perform(project_id, task, lease_key, lease_uuid)
end
end
diff --git a/app/workers/issuable_export_csv_worker.rb b/app/workers/issuable_export_csv_worker.rb
index 33452b14edb..eb96a78497c 100644
--- a/app/workers/issuable_export_csv_worker.rb
+++ b/app/workers/issuable_export_csv_worker.rb
@@ -10,29 +10,21 @@ class IssuableExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
def perform(type, current_user_id, project_id, params)
user = User.find(current_user_id)
project = Project.find(project_id)
- finder_params = map_params(params, project_id)
- export_service(type.to_sym, user, project, finder_params).email(user)
+ export_service(type, user, project, params).email(user)
rescue ActiveRecord::RecordNotFound => error
logger.error("Failed to export CSV (current_user_id:#{current_user_id}, project_id:#{project_id}): #{error.message}")
end
private
- def map_params(params, project_id)
- params
- .symbolize_keys
- .except(:sort)
- .merge(project_id: project_id)
- end
-
def export_service(type, user, project, params)
- issuable_class = service_classes_for(type)
- issuables = issuable_class[:finder].new(user, params).execute
- issuable_class[:service].new(issuables, project)
+ issuable_classes = issuable_classes_for(type.to_sym)
+ issuables = issuable_classes[:finder].new(user, parse_params(params, project.id)).execute
+ issuable_classes[:service].new(issuables, project)
end
- def service_classes_for(type)
+ def issuable_classes_for(type)
case type
when :issue
{ finder: IssuesFinder, service: Issues::ExportCsvService }
@@ -43,6 +35,13 @@ class IssuableExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
end
end
+ def parse_params(params, project_id)
+ params
+ .symbolize_keys
+ .except(:sort)
+ .merge(project_id: project_id)
+ end
+
def type_error_message(type)
"Type parameter must be :issue or :merge_request, it was #{type}"
end
diff --git a/app/workers/jira_connect/sync_builds_worker.rb b/app/workers/jira_connect/sync_builds_worker.rb
index c1c749f6041..9cb5d5d247d 100644
--- a/app/workers/jira_connect/sync_builds_worker.rb
+++ b/app/workers/jira_connect/sync_builds_worker.rb
@@ -14,7 +14,6 @@ module JiraConnect
pipeline = Ci::Pipeline.find_by_id(pipeline_id)
return unless pipeline
- return unless Feature.enabled?(:jira_sync_builds, pipeline.project)
::JiraConnect::SyncService
.new(pipeline.project)
diff --git a/app/workers/jira_connect/sync_deployments_worker.rb b/app/workers/jira_connect/sync_deployments_worker.rb
index 0f261e29464..7272d35f4cb 100644
--- a/app/workers/jira_connect/sync_deployments_worker.rb
+++ b/app/workers/jira_connect/sync_deployments_worker.rb
@@ -14,7 +14,6 @@ module JiraConnect
deployment = Deployment.find_by_id(deployment_id)
return unless deployment
- return unless Feature.enabled?(:jira_sync_deployments, deployment.project)
::JiraConnect::SyncService
.new(deployment.project)
diff --git a/app/workers/jira_connect/sync_feature_flags_worker.rb b/app/workers/jira_connect/sync_feature_flags_worker.rb
index 7e98d0eada7..496b9f1626d 100644
--- a/app/workers/jira_connect/sync_feature_flags_worker.rb
+++ b/app/workers/jira_connect/sync_feature_flags_worker.rb
@@ -14,7 +14,6 @@ module JiraConnect
feature_flag = ::Operations::FeatureFlag.find_by_id(feature_flag_id)
return unless feature_flag
- return unless Feature.enabled?(:jira_sync_feature_flags, feature_flag.project)
::JiraConnect::SyncService
.new(feature_flag.project)
diff --git a/app/workers/merge_request_cleanup_refs_worker.rb b/app/workers/merge_request_cleanup_refs_worker.rb
index 6b991a2253f..fbd62ac0a91 100644
--- a/app/workers/merge_request_cleanup_refs_worker.rb
+++ b/app/workers/merge_request_cleanup_refs_worker.rb
@@ -7,6 +7,8 @@ class MergeRequestCleanupRefsWorker
idempotent!
def perform(merge_request_id)
+ return unless Feature.enabled?(:merge_request_refs_cleanup, default_enabled: false)
+
merge_request = MergeRequest.find_by_id(merge_request_id)
unless merge_request
diff --git a/app/workers/namespaces/in_product_marketing_emails_worker.rb b/app/workers/namespaces/in_product_marketing_emails_worker.rb
new file mode 100644
index 00000000000..66d140928a7
--- /dev/null
+++ b/app/workers/namespaces/in_product_marketing_emails_worker.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class InProductMarketingEmailsWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ feature_category :subgroups
+ urgency :low
+
+ def perform
+ return unless Gitlab::Experimentation.active?(:in_product_marketing_emails)
+
+ Namespaces::InProductMarketingEmailsService.send_for_all_tracks_and_intervals
+ end
+ end
+end
diff --git a/app/workers/packages/composer/cache_cleanup_worker.rb b/app/workers/packages/composer/cache_cleanup_worker.rb
new file mode 100644
index 00000000000..638e50e18c4
--- /dev/null
+++ b/app/workers/packages/composer/cache_cleanup_worker.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Packages
+ module Composer
+ class CacheCleanupWorker
+ include ApplicationWorker
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ feature_category :package_registry
+
+ idempotent!
+
+ def perform
+ ::Packages::Composer::CacheFile.without_namespace.find_in_batches do |cache_files|
+ cache_files.each(&:destroy)
+ rescue ActiveRecord::RecordNotFound
+ # ignore. likely due to object already being deleted.
+ end
+
+ ::Packages::Composer::CacheFile.expired.find_in_batches do |cache_files|
+ cache_files.each(&:destroy)
+ rescue ActiveRecord::RecordNotFound
+ # ignore. likely due to object already being deleted.
+ end
+ rescue => e
+ Gitlab::ErrorTracking.log_exception(e)
+ end
+ end
+ end
+end
diff --git a/app/workers/pages_remove_worker.rb b/app/workers/pages_remove_worker.rb
index b83168fd7bd..67ea18545a7 100644
--- a/app/workers/pages_remove_worker.rb
+++ b/app/workers/pages_remove_worker.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# TODO: remove this worker https://gitlab.com/gitlab-org/gitlab/-/issues/320775
class PagesRemoveWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
@@ -11,7 +12,6 @@ class PagesRemoveWorker # rubocop:disable Scalability/IdempotentWorker
project = Project.find_by_id(project_id)
return unless project
- project.remove_pages
- project.pages_domains.delete_all
+ project.legacy_remove_pages
end
end
diff --git a/app/workers/pages_transfer_worker.rb b/app/workers/pages_transfer_worker.rb
index f78564cc69d..5d395c9e38a 100644
--- a/app/workers/pages_transfer_worker.rb
+++ b/app/workers/pages_transfer_worker.rb
@@ -9,7 +9,7 @@ class PagesTransferWorker # rubocop:disable Scalability/IdempotentWorker
loggable_arguments 0, 1
def perform(method, args)
- return unless Gitlab::PagesTransfer::Async::METHODS.include?(method)
+ return unless Gitlab::PagesTransfer::METHODS.include?(method)
result = Gitlab::PagesTransfer.new.public_send(method, *args) # rubocop:disable GitlabSecurity/PublicSend
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
index 85ecdd02fb5..b8dd4768cfb 100644
--- a/app/workers/pipeline_hooks_worker.rb
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -10,7 +10,8 @@ class PipelineHooksWorker # rubocop:disable Scalability/IdempotentWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
- Ci::Pipeline.find_by(id: pipeline_id)
+ Ci::Pipeline.includes({ builds: { runner: :tags } })
+ .find_by(id: pipeline_id)
.try(:execute_hooks)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 9fe7dd31e68..ac55f883fc5 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -2,6 +2,7 @@
class PostReceive # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
+ include Gitlab::Experiment::Dsl
feature_category :source_code_management
urgency :high
@@ -121,6 +122,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
end
def after_project_changes_hooks(project, user, refs, changes)
+ experiment(:new_project_readme, actor: user).track_initial_writes(project)
repository_update_hook_data = Gitlab::DataBuilder::Repository.update(project, user, changes, refs)
SystemHooksService.new.execute_hooks(repository_update_hook_data, :repository_update_hooks)
Gitlab::UsageDataCounters::SourceCodeCounter.count(:pushes)
diff --git a/app/workers/projects/git_garbage_collect_worker.rb b/app/workers/projects/git_garbage_collect_worker.rb
new file mode 100644
index 00000000000..4f908529b34
--- /dev/null
+++ b/app/workers/projects/git_garbage_collect_worker.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Projects
+ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
+ extend ::Gitlab::Utils::Override
+ include GitGarbageCollectMethods
+
+ private
+
+ override :find_resource
+ def find_resource(id)
+ Project.find(id)
+ end
+
+ override :before_gitaly_call
+ def before_gitaly_call(task, resource)
+ return unless gc?(task)
+
+ ::Projects::GitDeduplicationService.new(resource).execute
+ cleanup_orphan_lfs_file_references(resource)
+ end
+
+ def cleanup_orphan_lfs_file_references(resource)
+ return if Gitlab::Database.read_only? # GitGarbageCollectWorker may be run on a Geo secondary
+
+ ::Gitlab::Cleanup::OrphanLfsFileReferences.new(resource, dry_run: false, logger: logger).run!
+ rescue => err
+ Gitlab::GitLogger.warn(message: "Cleaning up orphan LFS objects files failed", error: err.message)
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(err)
+ end
+
+ override :update_db_repository_statistics
+ def update_db_repository_statistics(resource)
+ Projects::UpdateStatisticsService.new(resource, nil, statistics: [:repository_size, :lfs_objects_size]).execute
+ end
+ end
+end
diff --git a/app/workers/schedule_merge_request_cleanup_refs_worker.rb b/app/workers/schedule_merge_request_cleanup_refs_worker.rb
index 59b8993f78f..967032f99e5 100644
--- a/app/workers/schedule_merge_request_cleanup_refs_worker.rb
+++ b/app/workers/schedule_merge_request_cleanup_refs_worker.rb
@@ -16,6 +16,7 @@ class ScheduleMergeRequestCleanupRefsWorker
def perform
return if Gitlab::Database.read_only?
+ return unless Feature.enabled?(:merge_request_refs_cleanup, default_enabled: false)
ids = MergeRequest::CleanupSchedule.scheduled_merge_request_ids(LIMIT).map { |id| [id] }
diff --git a/app/workers/user_status_cleanup/batch_worker.rb b/app/workers/user_status_cleanup/batch_worker.rb
new file mode 100644
index 00000000000..0c1087cc4d2
--- /dev/null
+++ b/app/workers/user_status_cleanup/batch_worker.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module UserStatusCleanup
+ # This worker will run every minute to look for user status records to clean up.
+ class BatchWorker
+ include ApplicationWorker
+ # rubocop:disable Scalability/CronWorkerContext
+ include CronjobQueue
+ # rubocop:enable Scalability/CronWorkerContext
+
+ feature_category :users
+
+ idempotent!
+
+ # Avoid running too many UPDATE queries at once
+ MAX_RUNTIME = 30.seconds
+
+ def perform
+ return unless UserStatus.scheduled_for_cleanup.exists?
+
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ loop do
+ result = Users::BatchStatusCleanerService.execute
+ break if result[:deleted_rows] < Users::BatchStatusCleanerService::BATCH_SIZE
+
+ current_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ break if (current_time - start_time) > MAX_RUNTIME
+ end
+ end
+ end
+end
diff --git a/app/workers/wikis/git_garbage_collect_worker.rb b/app/workers/wikis/git_garbage_collect_worker.rb
new file mode 100644
index 00000000000..1b455c50618
--- /dev/null
+++ b/app/workers/wikis/git_garbage_collect_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Wikis
+ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
+ extend ::Gitlab::Utils::Override
+ include GitGarbageCollectMethods
+
+ private
+
+ override :find_resource
+ def find_resource(id)
+ Project.find(id).wiki
+ end
+
+ override :update_db_repository_statistics
+ def update_db_repository_statistics(resource)
+ Projects::UpdateStatisticsService.new(resource.container, nil, statistics: [:wiki_size]).execute
+ end
+ end
+end
diff --git a/babel.config.js b/babel.config.js
index 64898bfdf50..6c9d4640535 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -9,24 +9,6 @@ let presets = [
useBuiltIns: 'usage',
corejs: { version: 3, proposals: true },
modules: false,
- /**
- * This list of browsers is a conservative first definition, based on
- * https://docs.gitlab.com/ee/install/requirements.html#supported-web-browsers
- * with the following reasoning:
- *
- * - Edge: Pick the last two major version before the Chrome switch
- * - Rest: We should support the latest ESR of Firefox: 68, because it used quite a lot.
- * For the rest, pick browser versions that have a similar age to Firefox 68.
- *
- * See also this follow-up epic:
- * https://gitlab.com/groups/gitlab-org/-/epics/3957
- */
- targets: {
- chrome: '73',
- edge: '17',
- firefox: '68',
- safari: '12',
- },
},
],
];
diff --git a/bin/secpick b/bin/secpick
index 517465d3f5d..07bac9270c9 100755
--- a/bin/secpick
+++ b/bin/secpick
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
-# frozen_string_literal: false
+# frozen_string_literal: true
require 'active_support/core_ext/object/to_query'
require 'optparse'
@@ -9,12 +9,12 @@ require 'rainbow/refinement'
using Rainbow
module Secpick
- BRANCH_PREFIX = 'security'.freeze
- STABLE_SUFFIX = 'stable'.freeze
+ BRANCH_PREFIX = 'security'
+ STABLE_SUFFIX = 'stable'
- DEFAULT_REMOTE = 'security'.freeze
+ DEFAULT_REMOTE = 'security'
- SECURITY_MR_URL = 'https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/new'.freeze
+ SECURITY_MR_URL = 'https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/new'
class SecurityFix
def initialize
@@ -27,12 +27,12 @@ module Secpick
def source_branch
branch = "#{@options[:branch]}-#{@options[:version]}"
- branch.prepend("#{BRANCH_PREFIX}-") unless branch.start_with?("#{BRANCH_PREFIX}-")
- branch.freeze
+ branch = "#{BRANCH_PREFIX}-#{branch}" unless branch.start_with?("#{BRANCH_PREFIX}-")
+ branch
end
def stable_branch
- "#{@options[:version]}-#{STABLE_SUFFIX}-ee".freeze
+ "#{@options[:version]}-#{STABLE_SUFFIX}-ee"
end
def git_commands
diff --git a/changelogs/archive-12.md b/changelogs/archive-12.md
index 6cc890b7f12..61e72deea49 100644
--- a/changelogs/archive-12.md
+++ b/changelogs/archive-12.md
@@ -1265,7 +1265,7 @@
- Time series extends axis options correctly. !25399
- Fix "Edit Release" page. !25469
- Fix upgrade failure in EE displaying license. !25788
-- Fixed last commit widget when Gravatar is disabled.
+- Fixed last commit widget when Gravatar is disabled. !25800
## 12.8.0
diff --git a/changelogs/unreleased/14615-remove-compare-swap-revision.yml b/changelogs/unreleased/14615-remove-compare-swap-revision.yml
new file mode 100644
index 00000000000..b461e0c577c
--- /dev/null
+++ b/changelogs/unreleased/14615-remove-compare-swap-revision.yml
@@ -0,0 +1,5 @@
+---
+title: Remove compare switch revision button
+merge_request: 52547
+author:
+type: changed
diff --git a/changelogs/unreleased/15013-fork-to-different-name.yml b/changelogs/unreleased/15013-fork-to-different-name.yml
new file mode 100644
index 00000000000..54689ab10a2
--- /dev/null
+++ b/changelogs/unreleased/15013-fork-to-different-name.yml
@@ -0,0 +1,5 @@
+---
+title: Support setting more attributes when forking a project
+merge_request: 51962
+author:
+type: added
diff --git a/changelogs/unreleased/16827-escape-markdown-avoid-namespace-pollution.yml b/changelogs/unreleased/16827-escape-markdown-avoid-namespace-pollution.yml
new file mode 100644
index 00000000000..2032143de3a
--- /dev/null
+++ b/changelogs/unreleased/16827-escape-markdown-avoid-namespace-pollution.yml
@@ -0,0 +1,5 @@
+---
+title: Escaped markdown should not be interpreted as shortcuts
+merge_request: 45922
+author:
+type: changed
diff --git a/changelogs/unreleased/18292-project-name-to-path-conversion-in-api-mangles-dots.yml b/changelogs/unreleased/18292-project-name-to-path-conversion-in-api-mangles-dots.yml
new file mode 100644
index 00000000000..30adb6d1034
--- /dev/null
+++ b/changelogs/unreleased/18292-project-name-to-path-conversion-in-api-mangles-dots.yml
@@ -0,0 +1,5 @@
+---
+title: "API: do not mangle dots when creating project with a name"
+merge_request: 52725
+author:
+type: fixed
diff --git a/changelogs/unreleased/196628-move-number-of-changed-files-into-web-ide-sidebar-badge.yml b/changelogs/unreleased/196628-move-number-of-changed-files-into-web-ide-sidebar-badge.yml
new file mode 100644
index 00000000000..8db518b89d5
--- /dev/null
+++ b/changelogs/unreleased/196628-move-number-of-changed-files-into-web-ide-sidebar-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Move "number of changed files" into Web IDE sidebar badge
+merge_request: 51166
+author: Kev @KevSlashNull
+type: added
diff --git a/changelogs/unreleased/196835-fix-epic-feed.yml b/changelogs/unreleased/196835-fix-epic-feed.yml
new file mode 100644
index 00000000000..6cf42de8a6f
--- /dev/null
+++ b/changelogs/unreleased/196835-fix-epic-feed.yml
@@ -0,0 +1,5 @@
+---
+title: Display epic related events on user activity feed
+merge_request: 52611
+author:
+type: added
diff --git a/changelogs/unreleased/207385-services-unique-constraint-on-type.yml b/changelogs/unreleased/207385-services-unique-constraint-on-type.yml
new file mode 100644
index 00000000000..bafc9787de2
--- /dev/null
+++ b/changelogs/unreleased/207385-services-unique-constraint-on-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add unique index on services project_id and type
+merge_request: 52563
+author:
+type: changed
diff --git a/changelogs/unreleased/207385-simplify-service-uniqueness-validations.yml b/changelogs/unreleased/207385-simplify-service-uniqueness-validations.yml
new file mode 100644
index 00000000000..2d637499608
--- /dev/null
+++ b/changelogs/unreleased/207385-simplify-service-uniqueness-validations.yml
@@ -0,0 +1,5 @@
+---
+title: Clean up uniqueness validations for service type
+merge_request: 52565
+author:
+type: changed
diff --git a/changelogs/unreleased/207473-allow-set-confidential-note-attribute.yml b/changelogs/unreleased/207473-allow-set-confidential-note-attribute.yml
new file mode 100644
index 00000000000..78eb6e32060
--- /dev/null
+++ b/changelogs/unreleased/207473-allow-set-confidential-note-attribute.yml
@@ -0,0 +1,5 @@
+---
+title: Support setting confidential note attribute in UI
+merge_request: 52949
+author: Lee Tickett @leetickett
+type: added
diff --git a/changelogs/unreleased/212322-remove-duplicate-vulnerabilities.yml b/changelogs/unreleased/212322-remove-duplicate-vulnerabilities.yml
new file mode 100644
index 00000000000..4e8fd48b152
--- /dev/null
+++ b/changelogs/unreleased/212322-remove-duplicate-vulnerabilities.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicates from vulnerability_occurrences
+merge_request: 49937
+author:
+type: other
diff --git a/changelogs/unreleased/213581-ide-alert-when-cannot-push-code.yml b/changelogs/unreleased/213581-ide-alert-when-cannot-push-code.yml
new file mode 100644
index 00000000000..71618431dec
--- /dev/null
+++ b/changelogs/unreleased/213581-ide-alert-when-cannot-push-code.yml
@@ -0,0 +1,5 @@
+---
+title: Web IDE shows alert and disable buttons when user cannot push code
+merge_request: 51710
+author:
+type: changed
diff --git a/changelogs/unreleased/214631-remove-duplicated-vsa-stage-event.yml b/changelogs/unreleased/214631-remove-duplicated-vsa-stage-event.yml
new file mode 100644
index 00000000000..67c1c93c632
--- /dev/null
+++ b/changelogs/unreleased/214631-remove-duplicated-vsa-stage-event.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate incorrect value stream group stage records
+merge_request: 51975
+author:
+type: fixed
diff --git a/changelogs/unreleased/216761-add-image-repository-level-delete-functionality-to-the-image-repos.yml b/changelogs/unreleased/216761-add-image-repository-level-delete-functionality-to-the-image-repos.yml
new file mode 100644
index 00000000000..950a1b061be
--- /dev/null
+++ b/changelogs/unreleased/216761-add-image-repository-level-delete-functionality-to-the-image-repos.yml
@@ -0,0 +1,5 @@
+---
+title: Add delete functionality to the Image Repository detail view
+merge_request: 51980
+author:
+type: added
diff --git a/changelogs/unreleased/216761-proper-404-page-registry-details.yml b/changelogs/unreleased/216761-proper-404-page-registry-details.yml
new file mode 100644
index 00000000000..35d405c7dce
--- /dev/null
+++ b/changelogs/unreleased/216761-proper-404-page-registry-details.yml
@@ -0,0 +1,5 @@
+---
+title: Add 404 state to container registry details page
+merge_request: 52466
+author:
+type: changed
diff --git a/changelogs/unreleased/21686_filter_duplicates.yml b/changelogs/unreleased/21686_filter_duplicates.yml
new file mode 100644
index 00000000000..b1e0da45806
--- /dev/null
+++ b/changelogs/unreleased/21686_filter_duplicates.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicates from related_commit_sha query
+merge_request: 51888
+author:
+type: fixed
diff --git a/changelogs/unreleased/216912-jira-proxy-settings.yml b/changelogs/unreleased/216912-jira-proxy-settings.yml
new file mode 100644
index 00000000000..141e756b511
--- /dev/null
+++ b/changelogs/unreleased/216912-jira-proxy-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add Jira proxy settings columns
+merge_request: 52119
+author:
+type: added
diff --git a/changelogs/unreleased/220957-Open-with-IDE.yml b/changelogs/unreleased/220957-Open-with-IDE.yml
new file mode 100644
index 00000000000..c37adfed6b1
--- /dev/null
+++ b/changelogs/unreleased/220957-Open-with-IDE.yml
@@ -0,0 +1,5 @@
+---
+title: Allow opening projects with VS Code
+merge_request: 49460
+author: Kev @KevSlashNull
+type: added
diff --git a/changelogs/unreleased/223101-replace-angle-double-left-icon-with-svg.yml b/changelogs/unreleased/223101-replace-angle-double-left-icon-with-svg.yml
new file mode 100644
index 00000000000..bc759b102b7
--- /dev/null
+++ b/changelogs/unreleased/223101-replace-angle-double-left-icon-with-svg.yml
@@ -0,0 +1,5 @@
+---
+title: Replace angle-double-left icon with chevron-double-lg-left
+merge_request: 52393
+author:
+type: other
diff --git a/changelogs/unreleased/223618-project-labels-api-return-404-label-not-found-if-label-name-contai.yml b/changelogs/unreleased/223618-project-labels-api-return-404-label-not-found-if-label-name-contai.yml
new file mode 100644
index 00000000000..1b580214c19
--- /dev/null
+++ b/changelogs/unreleased/223618-project-labels-api-return-404-label-not-found-if-label-name-contai.yml
@@ -0,0 +1,5 @@
+---
+title: Allow dots in label names through REST API
+merge_request: 52591
+author:
+type: fixed
diff --git a/changelogs/unreleased/227349-package-registry-expand-the-filter-and-sort-functionality-on-the-p.yml b/changelogs/unreleased/227349-package-registry-expand-the-filter-and-sort-functionality-on-the-p.yml
new file mode 100644
index 00000000000..043bb4531e0
--- /dev/null
+++ b/changelogs/unreleased/227349-package-registry-expand-the-filter-and-sort-functionality-on-the-p.yml
@@ -0,0 +1,5 @@
+---
+title: Redesign the search UI for the package list
+merge_request: 52575
+author:
+type: changed
diff --git a/changelogs/unreleased/229174_use_unix_time_for_jira_update_sequence_id.yml b/changelogs/unreleased/229174_use_unix_time_for_jira_update_sequence_id.yml
new file mode 100644
index 00000000000..5d51d8c99ea
--- /dev/null
+++ b/changelogs/unreleased/229174_use_unix_time_for_jira_update_sequence_id.yml
@@ -0,0 +1,5 @@
+---
+title: Change Jira Connect update sequence id to use Unix Time
+merge_request: 51697
+author:
+type: fixed
diff --git a/changelogs/unreleased/229293-migrate-to-GlButton-note-form.yml b/changelogs/unreleased/229293-migrate-to-GlButton-note-form.yml
new file mode 100644
index 00000000000..782d51e7c32
--- /dev/null
+++ b/changelogs/unreleased/229293-migrate-to-GlButton-note-form.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate button to gitlab ui in note form
+merge_request: 42221
+author:
+type: changed
diff --git a/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-cherry-picking-com.yml b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-cherry-picking-com.yml
new file mode 100644
index 00000000000..b8625f0f98c
--- /dev/null
+++ b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-cherry-picking-com.yml
@@ -0,0 +1,5 @@
+---
+title: "[MR Page] Migrate to GlModal for Cherry-pick MR"
+merge_request: 53169
+author:
+type: other
diff --git a/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert-cherry-picking-com.yml b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert-cherry-picking-com.yml
new file mode 100644
index 00000000000..6648c60600f
--- /dev/null
+++ b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert-cherry-picking-com.yml
@@ -0,0 +1,5 @@
+---
+title: "[Commit Page] Migrate to GlModal for cherry-pick commit"
+merge_request: 51650
+author:
+type: other
diff --git a/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert.yml b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert.yml
new file mode 100644
index 00000000000..9c4364de70c
--- /dev/null
+++ b/changelogs/unreleased/229679-migrate-data-toggle-modal-to-glmodal-for-revert.yml
@@ -0,0 +1,5 @@
+---
+title: "[MR Page] Migrate to GlModal for revert MR"
+merge_request: 52019
+author:
+type: other
diff --git a/changelogs/unreleased/231044-convert-runner-buttons-to-pajamas.yml b/changelogs/unreleased/231044-convert-runner-buttons-to-pajamas.yml
new file mode 100644
index 00000000000..3902f543bf8
--- /dev/null
+++ b/changelogs/unreleased/231044-convert-runner-buttons-to-pajamas.yml
@@ -0,0 +1,5 @@
+---
+title: Convert project runner buttons to pajamas
+merge_request: 52358
+author:
+type: other
diff --git a/changelogs/unreleased/231083-yo-gitlab-ui.yml b/changelogs/unreleased/231083-yo-gitlab-ui.yml
new file mode 100644
index 00000000000..095acff22e8
--- /dev/null
+++ b/changelogs/unreleased/231083-yo-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in ee/app/views/users directory
+merge_request: 51783
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/231153-deploy-token-button-pajamas.yml b/changelogs/unreleased/231153-deploy-token-button-pajamas.yml
new file mode 100644
index 00000000000..163c93b949f
--- /dev/null
+++ b/changelogs/unreleased/231153-deploy-token-button-pajamas.yml
@@ -0,0 +1,5 @@
+---
+title: Convert deploy token button to pajamas
+merge_request: 52277
+author:
+type: other
diff --git a/changelogs/unreleased/231173-gl-button.yml b/changelogs/unreleased/231173-gl-button.yml
new file mode 100644
index 00000000000..9c65888b56e
--- /dev/null
+++ b/changelogs/unreleased/231173-gl-button.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in gitlab_slack_application file
+merge_request: 53478
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/231179-app-projects-buttons.yml b/changelogs/unreleased/231179-app-projects-buttons.yml
new file mode 100644
index 00000000000..ce7c135513b
--- /dev/null
+++ b/changelogs/unreleased/231179-app-projects-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button class in relevant places on project html
+merge_request: 52183
+author: Gary Bell @garybell
+type: other
diff --git a/changelogs/unreleased/231199-yo-gitlab-ui.yml b/changelogs/unreleased/231199-yo-gitlab-ui.yml
new file mode 100644
index 00000000000..eaf132aa1cb
--- /dev/null
+++ b/changelogs/unreleased/231199-yo-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to button in geo
+merge_request: 51777
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/231204-projects-notes.yml b/changelogs/unreleased/231204-projects-notes.yml
new file mode 100644
index 00000000000..e1952e214a3
--- /dev/null
+++ b/changelogs/unreleased/231204-projects-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in app/views/projects/notes directory
+merge_request: 44107
+author: Lakshit
+type: other
diff --git a/changelogs/unreleased/231219-yo-gitlab-ui.yml b/changelogs/unreleased/231219-yo-gitlab-ui.yml
new file mode 100644
index 00000000000..c42b88a8d69
--- /dev/null
+++ b/changelogs/unreleased/231219-yo-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to buttons in group settings
+merge_request: 51781
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/233708-fix-resource-event-timestamps.yml b/changelogs/unreleased/233708-fix-resource-event-timestamps.yml
new file mode 100644
index 00000000000..17d19b82e15
--- /dev/null
+++ b/changelogs/unreleased/233708-fix-resource-event-timestamps.yml
@@ -0,0 +1,6 @@
+---
+title: Use user-provided timestamp when updating issue and merge request milestones,
+ iterations, and weights using the API
+merge_request: 53237
+author:
+type: fixed
diff --git a/changelogs/unreleased/235525-test-report-recent-failures.yml b/changelogs/unreleased/235525-test-report-recent-failures.yml
new file mode 100644
index 00000000000..787a40cdc14
--- /dev/null
+++ b/changelogs/unreleased/235525-test-report-recent-failures.yml
@@ -0,0 +1,5 @@
+---
+title: Show recent test case failures in the pipeline test report
+merge_request: 52606
+author:
+type: added
diff --git a/changelogs/unreleased/239172-add-entity-columns-to-vulnerability-occurrences.yml b/changelogs/unreleased/239172-add-entity-columns-to-vulnerability-occurrences.yml
new file mode 100644
index 00000000000..612d05809d7
--- /dev/null
+++ b/changelogs/unreleased/239172-add-entity-columns-to-vulnerability-occurrences.yml
@@ -0,0 +1,5 @@
+---
+title: Add entity columns to vulnerability occurrences
+merge_request: 51739
+author:
+type: changed
diff --git a/changelogs/unreleased/241376-max-nuget-packages-returned.yml b/changelogs/unreleased/241376-max-nuget-packages-returned.yml
new file mode 100644
index 00000000000..82ad553278c
--- /dev/null
+++ b/changelogs/unreleased/241376-max-nuget-packages-returned.yml
@@ -0,0 +1,5 @@
+---
+title: Update max number of NuGet packages returned
+merge_request: 52265
+author:
+type: fixed
diff --git a/changelogs/unreleased/241744-additional-formats-kroki.yml b/changelogs/unreleased/241744-additional-formats-kroki.yml
new file mode 100644
index 00000000000..f305ee13553
--- /dev/null
+++ b/changelogs/unreleased/241744-additional-formats-kroki.yml
@@ -0,0 +1,5 @@
+---
+title: "Enable/disable additional diagram formats on Kroki"
+merge_request: 49304
+author: Guillaume Grossetie
+type: added
diff --git a/changelogs/unreleased/24488-expose-tag-list.yml b/changelogs/unreleased/24488-expose-tag-list.yml
new file mode 100644
index 00000000000..9c54470b439
--- /dev/null
+++ b/changelogs/unreleased/24488-expose-tag-list.yml
@@ -0,0 +1,5 @@
+---
+title: Add tag_list attribute to the JSON output for Jobs API
+merge_request: 44859
+author: Alon Liszt
+type: added
diff --git a/changelogs/unreleased/245260-fix-git-url-project-disclosure.yml b/changelogs/unreleased/245260-fix-git-url-project-disclosure.yml
new file mode 100644
index 00000000000..4dd6b465e57
--- /dev/null
+++ b/changelogs/unreleased/245260-fix-git-url-project-disclosure.yml
@@ -0,0 +1,5 @@
+---
+title: Don't expose project existence by redirecting from its .git URL
+merge_request: 52818
+author:
+type: fixed
diff --git a/changelogs/unreleased/250480-enforce-ssh-key-expiry.yml b/changelogs/unreleased/250480-enforce-ssh-key-expiry.yml
new file mode 100644
index 00000000000..4f4dd4efe95
--- /dev/null
+++ b/changelogs/unreleased/250480-enforce-ssh-key-expiry.yml
@@ -0,0 +1,5 @@
+---
+title: Add enforced SSH key expiration
+merge_request: 51921
+author:
+type: added
diff --git a/changelogs/unreleased/25381-add-a-custom-commit-message-when-applying-a-suggested-change.yml b/changelogs/unreleased/25381-add-a-custom-commit-message-when-applying-a-suggested-change.yml
new file mode 100644
index 00000000000..653cf94d94b
--- /dev/null
+++ b/changelogs/unreleased/25381-add-a-custom-commit-message-when-applying-a-suggested-change.yml
@@ -0,0 +1,5 @@
+---
+title: Add a commit message parameter for the suggestion endpoints
+merge_request: 51245
+author:
+type: added
diff --git a/changelogs/unreleased/25381-add-request-review-alias.yml b/changelogs/unreleased/25381-add-request-review-alias.yml
new file mode 100644
index 00000000000..f450ec48280
--- /dev/null
+++ b/changelogs/unreleased/25381-add-request-review-alias.yml
@@ -0,0 +1,5 @@
+---
+title: Add a /request_review alias for /assign_reviewer
+merge_request: 51751
+author:
+type: added
diff --git a/changelogs/unreleased/25381-suggestion-custom-commit-ff-default-true.yml b/changelogs/unreleased/25381-suggestion-custom-commit-ff-default-true.yml
new file mode 100644
index 00000000000..04aeec3fbfd
--- /dev/null
+++ b/changelogs/unreleased/25381-suggestion-custom-commit-ff-default-true.yml
@@ -0,0 +1,5 @@
+---
+title: Enable suggestions custom commit message feature flag by default
+merge_request: 53342
+author:
+type: changed
diff --git a/changelogs/unreleased/254256-replace-bootstrap-modal-in-app-views-projects-_issuable_by_email-h.yml b/changelogs/unreleased/254256-replace-bootstrap-modal-in-app-views-projects-_issuable_by_email-h.yml
new file mode 100644
index 00000000000..f544eda8eb0
--- /dev/null
+++ b/changelogs/unreleased/254256-replace-bootstrap-modal-in-app-views-projects-_issuable_by_email-h.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap modal in issuable_by_email HAML template
+merge_request: 53599
+author:
+type: changed
diff --git a/changelogs/unreleased/254643-fix-broken-testsuite-link-when-containing-dot.yml b/changelogs/unreleased/254643-fix-broken-testsuite-link-when-containing-dot.yml
new file mode 100644
index 00000000000..accfee61a16
--- /dev/null
+++ b/changelogs/unreleased/254643-fix-broken-testsuite-link-when-containing-dot.yml
@@ -0,0 +1,5 @@
+---
+title: Fix broken testsuite link if the suite contains a dot
+merge_request: 51828
+author: Michael Aigner @tonka3000
+type: fixed
diff --git a/changelogs/unreleased/255394-runner-tags-in-webhook.yml b/changelogs/unreleased/255394-runner-tags-in-webhook.yml
new file mode 100644
index 00000000000..89af3ecc62f
--- /dev/null
+++ b/changelogs/unreleased/255394-runner-tags-in-webhook.yml
@@ -0,0 +1,5 @@
+---
+title: Add 'tags' field to runners in job/pipeline webhook payloads
+merge_request: 51633
+author:
+type: changed
diff --git a/changelogs/unreleased/258-collecting-mau-for-gitlab-workflow-vs-code-extension.yml b/changelogs/unreleased/258-collecting-mau-for-gitlab-workflow-vs-code-extension.yml
new file mode 100644
index 00000000000..b8923b741b8
--- /dev/null
+++ b/changelogs/unreleased/258-collecting-mau-for-gitlab-workflow-vs-code-extension.yml
@@ -0,0 +1,5 @@
+---
+title: Track API requests from the the VS Code extension
+merge_request: 52484
+author:
+type: other
diff --git a/changelogs/unreleased/258550-fix-long-ci-variable-name-overflows-on-origin.yml b/changelogs/unreleased/258550-fix-long-ci-variable-name-overflows-on-origin.yml
new file mode 100644
index 00000000000..37e0c666fe3
--- /dev/null
+++ b/changelogs/unreleased/258550-fix-long-ci-variable-name-overflows-on-origin.yml
@@ -0,0 +1,5 @@
+---
+title: Fix long CI variable name overflows on origin
+merge_request: 51021
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/259719-rollout-optimized-labels-ff.yml b/changelogs/unreleased/259719-rollout-optimized-labels-ff.yml
new file mode 100644
index 00000000000..5e0bc464762
--- /dev/null
+++ b/changelogs/unreleased/259719-rollout-optimized-labels-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Improve the performance of merge request and issue search by label(s)
+merge_request: 52495
+author:
+type: performance
diff --git a/changelogs/unreleased/260419-add-subgroup-events-column-to-webhooks-table.yml b/changelogs/unreleased/260419-add-subgroup-events-column-to-webhooks-table.yml
new file mode 100644
index 00000000000..b337b9eafb3
--- /dev/null
+++ b/changelogs/unreleased/260419-add-subgroup-events-column-to-webhooks-table.yml
@@ -0,0 +1,5 @@
+---
+title: Add subgroup_events column to web_hooks table
+merge_request: 52648
+author:
+type: added
diff --git a/changelogs/unreleased/262047-order-milestones-by-due-date.yml b/changelogs/unreleased/262047-order-milestones-by-due-date.yml
new file mode 100644
index 00000000000..99641240b34
--- /dev/null
+++ b/changelogs/unreleased/262047-order-milestones-by-due-date.yml
@@ -0,0 +1,5 @@
+---
+title: Sort milestone dropdown items by due date
+merge_request: 53242
+author:
+type: changed
diff --git a/changelogs/unreleased/262063-global-search-topbar-vue.yml b/changelogs/unreleased/262063-global-search-topbar-vue.yml
new file mode 100644
index 00000000000..c9c9c7516a9
--- /dev/null
+++ b/changelogs/unreleased/262063-global-search-topbar-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Global Search - UX Cleanup of Search Bar
+merge_request: 51409
+author:
+type: changed
diff --git a/changelogs/unreleased/262086-schedule-user-unset-status.yml b/changelogs/unreleased/262086-schedule-user-unset-status.yml
new file mode 100644
index 00000000000..4617f283de5
--- /dev/null
+++ b/changelogs/unreleased/262086-schedule-user-unset-status.yml
@@ -0,0 +1,5 @@
+---
+title: Add clear_status_at column to user_status table
+merge_request: 53620
+author:
+type: other
diff --git a/changelogs/unreleased/262102-fix-stay-on-page-alert-showing-in-empty-snippet.yml b/changelogs/unreleased/262102-fix-stay-on-page-alert-showing-in-empty-snippet.yml
new file mode 100644
index 00000000000..abec645e57d
--- /dev/null
+++ b/changelogs/unreleased/262102-fix-stay-on-page-alert-showing-in-empty-snippet.yml
@@ -0,0 +1,5 @@
+---
+title: Fix "Stay on Page" alert showing in empty snippet
+merge_request: 50400
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/262860-persist-shift-job.yml b/changelogs/unreleased/262860-persist-shift-job.yml
new file mode 100644
index 00000000000..a8affe26180
--- /dev/null
+++ b/changelogs/unreleased/262860-persist-shift-job.yml
@@ -0,0 +1,5 @@
+---
+title: Add job to persist On-call shifts
+merge_request: 50239
+author:
+type: added
diff --git a/changelogs/unreleased/262863-delete-oncall-rotation-graphql.yml b/changelogs/unreleased/262863-delete-oncall-rotation-graphql.yml
new file mode 100644
index 00000000000..dabfe3a861c
--- /dev/null
+++ b/changelogs/unreleased/262863-delete-oncall-rotation-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add On-call Rotations destroy mutation to GraphQL
+merge_request: 51860
+author:
+type: added
diff --git a/changelogs/unreleased/263452-display-busy-status-in-issue-sidebar.yml b/changelogs/unreleased/263452-display-busy-status-in-issue-sidebar.yml
new file mode 100644
index 00000000000..dc6ed606ac3
--- /dev/null
+++ b/changelogs/unreleased/263452-display-busy-status-in-issue-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: Display user busy status in issue sidebar
+merge_request: 54165
+author:
+type: added
diff --git a/changelogs/unreleased/263452-sidebar-display-busy-status.yml b/changelogs/unreleased/263452-sidebar-display-busy-status.yml
new file mode 100644
index 00000000000..db1ecfa7590
--- /dev/null
+++ b/changelogs/unreleased/263452-sidebar-display-busy-status.yml
@@ -0,0 +1,5 @@
+---
+title: Display the user busy status in the MR sidebar
+merge_request: 47769
+author:
+type: changed
diff --git a/changelogs/unreleased/264262-users-who-have-reached-their-personal-project-limit-cannot-fork-to.yml b/changelogs/unreleased/264262-users-who-have-reached-their-personal-project-limit-cannot-fork-to.yml
new file mode 100644
index 00000000000..d463636130c
--- /dev/null
+++ b/changelogs/unreleased/264262-users-who-have-reached-their-personal-project-limit-cannot-fork-to.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users to fork to a group when their personal namespace is full
+merge_request: 53632
+author:
+type: fixed
diff --git a/changelogs/unreleased/267140-add-user-bot-gql.yml b/changelogs/unreleased/267140-add-user-bot-gql.yml
new file mode 100644
index 00000000000..cf2f13116a9
--- /dev/null
+++ b/changelogs/unreleased/267140-add-user-bot-gql.yml
@@ -0,0 +1,5 @@
+---
+title: Add bot to User GraphQL Type
+merge_request: 52933
+author:
+type: added
diff --git a/changelogs/unreleased/267140-check-if-user-is-bot.yml b/changelogs/unreleased/267140-check-if-user-is-bot.yml
new file mode 100644
index 00000000000..6347dc5b0d4
--- /dev/null
+++ b/changelogs/unreleased/267140-check-if-user-is-bot.yml
@@ -0,0 +1,5 @@
+---
+title: Expose if user is a bot in the REST api
+merge_request: 52003
+author:
+type: added
diff --git a/changelogs/unreleased/267344-test-report-file-name-link.yml b/changelogs/unreleased/267344-test-report-file-name-link.yml
new file mode 100644
index 00000000000..7b572f7e2a7
--- /dev/null
+++ b/changelogs/unreleased/267344-test-report-file-name-link.yml
@@ -0,0 +1,5 @@
+---
+title: Add link to test case file in pipeline test report
+merge_request: 53650
+author:
+type: added
diff --git a/changelogs/unreleased/267522-sshkey-delete-parital.yml b/changelogs/unreleased/267522-sshkey-delete-parital.yml
new file mode 100644
index 00000000000..2c27cbe551a
--- /dev/null
+++ b/changelogs/unreleased/267522-sshkey-delete-parital.yml
@@ -0,0 +1,5 @@
+---
+title: New Shared Partial for SSH Key Deletion
+merge_request: 50825
+author: Mehul Sharma
+type: other
diff --git a/changelogs/unreleased/270130-policy-preview-for-egress-deny-all-reports-egress-allow-all.yml b/changelogs/unreleased/270130-policy-preview-for-egress-deny-all-reports-egress-allow-all.yml
new file mode 100644
index 00000000000..3797c251e2e
--- /dev/null
+++ b/changelogs/unreleased/270130-policy-preview-for-egress-deny-all-reports-egress-allow-all.yml
@@ -0,0 +1,5 @@
+---
+title: Correct the egress 'deny all' policy preview from Allow to Deny
+merge_request: 52370
+author:
+type: fixed
diff --git a/changelogs/unreleased/271263-piwik-support-the-disabling-of-cookies.yml b/changelogs/unreleased/271263-piwik-support-the-disabling-of-cookies.yml
new file mode 100644
index 00000000000..654b69c2b58
--- /dev/null
+++ b/changelogs/unreleased/271263-piwik-support-the-disabling-of-cookies.yml
@@ -0,0 +1,5 @@
+---
+title: 'Matomo: Support the disabling of cookies'
+merge_request: 52831
+author: 'otheus@gmail.com'
+type: added
diff --git a/changelogs/unreleased/271530-improve-user-menu.yml b/changelogs/unreleased/271530-improve-user-menu.yml
new file mode 100644
index 00000000000..78ba0964841
--- /dev/null
+++ b/changelogs/unreleased/271530-improve-user-menu.yml
@@ -0,0 +1,5 @@
+---
+title: Improve user dropdown items
+merge_request: 53175
+author:
+type: changed
diff --git a/changelogs/unreleased/273067-fix-ide-open-mr-highligh-first-file.yml b/changelogs/unreleased/273067-fix-ide-open-mr-highligh-first-file.yml
new file mode 100644
index 00000000000..27928522b76
--- /dev/null
+++ b/changelogs/unreleased/273067-fix-ide-open-mr-highligh-first-file.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Web IDE open MR to show opened files consistently
+merge_request: 53927
+author:
+type: fixed
diff --git a/changelogs/unreleased/273288-update-blob-page-buttons.yml b/changelogs/unreleased/273288-update-blob-page-buttons.yml
new file mode 100644
index 00000000000..6e1b7bcc1b0
--- /dev/null
+++ b/changelogs/unreleased/273288-update-blob-page-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update blob page buttons to gitlab-ui pajamas styles
+merge_request: 53775
+author:
+type: changed
diff --git a/changelogs/unreleased/273328-global-search-sort-ux.yml b/changelogs/unreleased/273328-global-search-sort-ux.yml
new file mode 100644
index 00000000000..c18fa66dd31
--- /dev/null
+++ b/changelogs/unreleased/273328-global-search-sort-ux.yml
@@ -0,0 +1,5 @@
+---
+title: Global Search - UX Refresh for Sort Button
+merge_request: 52387
+author:
+type: changed
diff --git a/changelogs/unreleased/273574-fix-bad-data-in-projects-has_external_issue_tracker.yml b/changelogs/unreleased/273574-fix-bad-data-in-projects-has_external_issue_tracker.yml
new file mode 100644
index 00000000000..74bd2ee5f79
--- /dev/null
+++ b/changelogs/unreleased/273574-fix-bad-data-in-projects-has_external_issue_tracker.yml
@@ -0,0 +1,5 @@
+---
+title: Cleanup incorrect data in projects.has_external_wiki
+merge_request: 53790
+author:
+type: fixed
diff --git a/changelogs/unreleased/276583-make-keep-latest-artifact-an-instance-level-configuration.yml b/changelogs/unreleased/276583-make-keep-latest-artifact-an-instance-level-configuration.yml
new file mode 100644
index 00000000000..548453c8a11
--- /dev/null
+++ b/changelogs/unreleased/276583-make-keep-latest-artifact-an-instance-level-configuration.yml
@@ -0,0 +1,5 @@
+---
+title: Add keep latest artifact option for instances
+merge_request: 50889
+author:
+type: added
diff --git a/changelogs/unreleased/276882-Allow-metadata-duplicates.yml b/changelogs/unreleased/276882-Allow-metadata-duplicates.yml
new file mode 100644
index 00000000000..9aadeaf3f4c
--- /dev/null
+++ b/changelogs/unreleased/276882-Allow-metadata-duplicates.yml
@@ -0,0 +1,6 @@
+---
+title: Allow versionless maven-metadata.xml file duplicates even when maven duplicates
+ are disabled
+merge_request: 51758
+author:
+type: fixed
diff --git a/changelogs/unreleased/276917-remove-default_merge_ref_for_diffs-feature-flag.yml b/changelogs/unreleased/276917-remove-default_merge_ref_for_diffs-feature-flag.yml
new file mode 100644
index 00000000000..69287c045eb
--- /dev/null
+++ b/changelogs/unreleased/276917-remove-default_merge_ref_for_diffs-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Make merge-ref base the default comparison mode
+merge_request: 54017
+author:
+type: added
diff --git a/changelogs/unreleased/277327_populate_uuid_values_for_security_findings.yml b/changelogs/unreleased/277327_populate_uuid_values_for_security_findings.yml
new file mode 100644
index 00000000000..1d00778d0a1
--- /dev/null
+++ b/changelogs/unreleased/277327_populate_uuid_values_for_security_findings.yml
@@ -0,0 +1,6 @@
+---
+title: Populate the `uuid` attributes of the `security_findings` records and the `finding_uuid`
+ attribute of the related `vulnerability_feedback` records
+merge_request: 51472
+author:
+type: added
diff --git a/changelogs/unreleased/277436-2fa-ux-text-changes.yml b/changelogs/unreleased/277436-2fa-ux-text-changes.yml
new file mode 100644
index 00000000000..59fc9215b91
--- /dev/null
+++ b/changelogs/unreleased/277436-2fa-ux-text-changes.yml
@@ -0,0 +1,5 @@
+---
+title: Change UI text for 2FA setup
+merge_request: 53677
+author:
+type: changed
diff --git a/changelogs/unreleased/281677_space_in_filename.yml b/changelogs/unreleased/281677_space_in_filename.yml
new file mode 100644
index 00000000000..30ae5bcfa0d
--- /dev/null
+++ b/changelogs/unreleased/281677_space_in_filename.yml
@@ -0,0 +1,5 @@
+---
+title: Improve search filter by taking space in file path into account
+merge_request: 52392
+author:
+type: fixed
diff --git a/changelogs/unreleased/281963-move-cohorts-to-users.yml b/changelogs/unreleased/281963-move-cohorts-to-users.yml
new file mode 100644
index 00000000000..3ef6ea39d34
--- /dev/null
+++ b/changelogs/unreleased/281963-move-cohorts-to-users.yml
@@ -0,0 +1,5 @@
+---
+title: Move Cohorts page to Overiew-Users
+merge_request: 51707
+author:
+type: changed
diff --git a/changelogs/unreleased/283897-fix-inaccessible-pipeline-status-icon-colors-in-mr-widget.yml b/changelogs/unreleased/283897-fix-inaccessible-pipeline-status-icon-colors-in-mr-widget.yml
new file mode 100644
index 00000000000..defcbdc38fb
--- /dev/null
+++ b/changelogs/unreleased/283897-fix-inaccessible-pipeline-status-icon-colors-in-mr-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Improve accessibility of gray color CI status icons
+merge_request: 52356
+author:
+type: changed
diff --git a/changelogs/unreleased/283911-tf-alignment.yml b/changelogs/unreleased/283911-tf-alignment.yml
new file mode 100644
index 00000000000..04d8e979586
--- /dev/null
+++ b/changelogs/unreleased/283911-tf-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Update styles for terraform MR widget
+merge_request: 52627
+author:
+type: changed
diff --git a/changelogs/unreleased/283912-remove-redundant-text.yml b/changelogs/unreleased/283912-remove-redundant-text.yml
new file mode 100644
index 00000000000..6b02d648185
--- /dev/null
+++ b/changelogs/unreleased/283912-remove-redundant-text.yml
@@ -0,0 +1,5 @@
+---
+title: Remove redundant text in Terraform Widget
+merge_request: 52013
+author:
+type: changed
diff --git a/changelogs/unreleased/284283-change-error-message-for-user-approval-error.yml b/changelogs/unreleased/284283-change-error-message-for-user-approval-error.yml
new file mode 100644
index 00000000000..e0d36c631a9
--- /dev/null
+++ b/changelogs/unreleased/284283-change-error-message-for-user-approval-error.yml
@@ -0,0 +1,5 @@
+---
+title: Change error message for user approval error
+merge_request: 52103
+author:
+type: changed
diff --git a/changelogs/unreleased/285287-include-submodule-information-for-files-in-diff-metadata.yml b/changelogs/unreleased/285287-include-submodule-information-for-files-in-diff-metadata.yml
new file mode 100644
index 00000000000..5dacccd02cd
--- /dev/null
+++ b/changelogs/unreleased/285287-include-submodule-information-for-files-in-diff-metadata.yml
@@ -0,0 +1,5 @@
+---
+title: Include submodule information for files in diff metadata
+merge_request: 50346
+author: Simon Stieger @sim0
+type: fixed
diff --git a/changelogs/unreleased/285464_improve_highlighting_for_diffs.yml b/changelogs/unreleased/285464_improve_highlighting_for_diffs.yml
new file mode 100644
index 00000000000..1e6bf23b379
--- /dev/null
+++ b/changelogs/unreleased/285464_improve_highlighting_for_diffs.yml
@@ -0,0 +1,5 @@
+---
+title: Improve highlighting for merge diffs
+merge_request: 53980
+author:
+type: added
diff --git a/changelogs/unreleased/285507-fix-reply-box-border.yml b/changelogs/unreleased/285507-fix-reply-box-border.yml
new file mode 100644
index 00000000000..9633ee3a6a0
--- /dev/null
+++ b/changelogs/unreleased/285507-fix-reply-box-border.yml
@@ -0,0 +1,5 @@
+---
+title: Fix reply box border on diffs
+merge_request: 52084
+author:
+type: fixed
diff --git a/changelogs/unreleased/287690-issue-comment-option-icons-are-not-aligned-consistently.yml b/changelogs/unreleased/287690-issue-comment-option-icons-are-not-aligned-consistently.yml
new file mode 100644
index 00000000000..e227e4fad15
--- /dev/null
+++ b/changelogs/unreleased/287690-issue-comment-option-icons-are-not-aligned-consistently.yml
@@ -0,0 +1,5 @@
+---
+title: Align note actions icons
+merge_request: 53753
+author: Claudius Ellsel (@clel)
+type: fixed
diff --git a/changelogs/unreleased/288715-populate-and-migration-issue_email_participants.yml b/changelogs/unreleased/288715-populate-and-migration-issue_email_participants.yml
new file mode 100644
index 00000000000..135dad3cc16
--- /dev/null
+++ b/changelogs/unreleased/288715-populate-and-migration-issue_email_participants.yml
@@ -0,0 +1,5 @@
+---
+title: Populate and migrate issue_email_participants
+merge_request: 48711
+author: Lee Tickett @leetickett
+type: added
diff --git a/changelogs/unreleased/288822-audit-event-removed-user-bug.yml b/changelogs/unreleased/288822-audit-event-removed-user-bug.yml
new file mode 100644
index 00000000000..23409642246
--- /dev/null
+++ b/changelogs/unreleased/288822-audit-event-removed-user-bug.yml
@@ -0,0 +1,5 @@
+---
+title: Fix batch query issue when primary key is -1
+merge_request: 51716
+author:
+type: fixed
diff --git a/changelogs/unreleased/289836_monkey_patch_net_http_proxy_crendetial_encoding.yml b/changelogs/unreleased/289836_monkey_patch_net_http_proxy_crendetial_encoding.yml
new file mode 100644
index 00000000000..8dc20e08826
--- /dev/null
+++ b/changelogs/unreleased/289836_monkey_patch_net_http_proxy_crendetial_encoding.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Net::HTTP proxy encoding username and password
+merge_request: 52368
+author:
+type: fixed
diff --git a/changelogs/unreleased/290112_add_security_dashboard_access_level_into_project_features.yml b/changelogs/unreleased/290112_add_security_dashboard_access_level_into_project_features.yml
new file mode 100644
index 00000000000..d3b0056ddbd
--- /dev/null
+++ b/changelogs/unreleased/290112_add_security_dashboard_access_level_into_project_features.yml
@@ -0,0 +1,6 @@
+---
+title: Add `security_and_compliance_access_level` column into the `project_features`
+ table
+merge_request: 52551
+author:
+type: added
diff --git a/changelogs/unreleased/290116-enable-webhook-test-reorder-feature.yml b/changelogs/unreleased/290116-enable-webhook-test-reorder-feature.yml
new file mode 100644
index 00000000000..246e31bfbff
--- /dev/null
+++ b/changelogs/unreleased/290116-enable-webhook-test-reorder-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Select the newest records for webhook test payloads
+merge_request: 54030
+author:
+type: changed
diff --git a/changelogs/unreleased/290231-warning-message-for-group-migration.yml b/changelogs/unreleased/290231-warning-message-for-group-migration.yml
new file mode 100644
index 00000000000..bb51802e835
--- /dev/null
+++ b/changelogs/unreleased/290231-warning-message-for-group-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Add warning message for GitLab group migration
+merge_request: 51214
+author:
+type: changed
diff --git a/changelogs/unreleased/290288-composer-cache-pages.yml b/changelogs/unreleased/290288-composer-cache-pages.yml
new file mode 100644
index 00000000000..908e0951daf
--- /dev/null
+++ b/changelogs/unreleased/290288-composer-cache-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Add Composer cache classes and table
+merge_request: 51509
+author:
+type: other
diff --git a/changelogs/unreleased/290302-sort-container-repositories.yml b/changelogs/unreleased/290302-sort-container-repositories.yml
new file mode 100644
index 00000000000..71f409aa259
--- /dev/null
+++ b/changelogs/unreleased/290302-sort-container-repositories.yml
@@ -0,0 +1,5 @@
+---
+title: Add sort argument to container_repositories graphql resolver
+merge_request: 53404
+author:
+type: changed
diff --git a/changelogs/unreleased/290302-update-the-default-sort-order-of-the-image-repository-list.yml b/changelogs/unreleased/290302-update-the-default-sort-order-of-the-image-repository-list.yml
new file mode 100644
index 00000000000..7d68ada42ed
--- /dev/null
+++ b/changelogs/unreleased/290302-update-the-default-sort-order-of-the-image-repository-list.yml
@@ -0,0 +1,5 @@
+---
+title: Add sort to container registry list page
+merge_request: 53820
+author:
+type: changed
diff --git a/changelogs/unreleased/290622-display-warning-mr-edit.yml b/changelogs/unreleased/290622-display-warning-mr-edit.yml
new file mode 100644
index 00000000000..0810655495e
--- /dev/null
+++ b/changelogs/unreleased/290622-display-warning-mr-edit.yml
@@ -0,0 +1,5 @@
+---
+title: Display unload warning if MR edit changed
+merge_request: 53438
+author:
+type: added
diff --git a/changelogs/unreleased/290715-has_external_issue_tracker_trigger.yml b/changelogs/unreleased/290715-has_external_issue_tracker_trigger.yml
new file mode 100644
index 00000000000..d9d40c99c5c
--- /dev/null
+++ b/changelogs/unreleased/290715-has_external_issue_tracker_trigger.yml
@@ -0,0 +1,5 @@
+---
+title: Add PostgreSQL trigger to maintain projects.has_external_issue_tracker
+merge_request: 51852
+author:
+type: changed
diff --git a/changelogs/unreleased/290741-packages-hidden-status.yml b/changelogs/unreleased/290741-packages-hidden-status.yml
new file mode 100644
index 00000000000..03c5fd0f4eb
--- /dev/null
+++ b/changelogs/unreleased/290741-packages-hidden-status.yml
@@ -0,0 +1,5 @@
+---
+title: Add status attribute to packages and ability to set 'hidden' for generic packages
+merge_request: 53385
+author:
+type: added
diff --git a/changelogs/unreleased/290944-pull-by-digest.yml b/changelogs/unreleased/290944-pull-by-digest.yml
new file mode 100644
index 00000000000..911f6be7e9c
--- /dev/null
+++ b/changelogs/unreleased/290944-pull-by-digest.yml
@@ -0,0 +1,5 @@
+---
+title: Add content_type column to dependency_proxy_manifests
+merge_request: 52805
+author:
+type: changed
diff --git a/changelogs/unreleased/291048-allow-unfinished-tag-cleanup-alert-to-be-permanently-dismissible-f.yml b/changelogs/unreleased/291048-allow-unfinished-tag-cleanup-alert-to-be-permanently-dismissible-f.yml
new file mode 100644
index 00000000000..a01a8f0f273
--- /dev/null
+++ b/changelogs/unreleased/291048-allow-unfinished-tag-cleanup-alert-to-be-permanently-dismissible-f.yml
@@ -0,0 +1,5 @@
+---
+title: Add callout disabling feature to cleanup policy alert
+merge_request: 52327
+author:
+type: changed
diff --git a/changelogs/unreleased/291140-query-single-state.yml b/changelogs/unreleased/291140-query-single-state.yml
new file mode 100644
index 00000000000..ba7e586a493
--- /dev/null
+++ b/changelogs/unreleased/291140-query-single-state.yml
@@ -0,0 +1,5 @@
+---
+title: Add GraphQL query for single Terraform state
+merge_request: 51145
+author:
+type: added
diff --git a/changelogs/unreleased/291170-issue-mr-list-tabs-icons-sometimes-display-as.yml b/changelogs/unreleased/291170-issue-mr-list-tabs-icons-sometimes-display-as.yml
new file mode 100644
index 00000000000..66662aada71
--- /dev/null
+++ b/changelogs/unreleased/291170-issue-mr-list-tabs-icons-sometimes-display-as.yml
@@ -0,0 +1,5 @@
+---
+title: Remove MR List counts if they cannot be generated
+merge_request: 52698
+author:
+type: fixed
diff --git a/changelogs/unreleased/292035-convert-the-assignees-feature-into-a-widget.yml b/changelogs/unreleased/292035-convert-the-assignees-feature-into-a-widget.yml
new file mode 100644
index 00000000000..bbc2ee0708c
--- /dev/null
+++ b/changelogs/unreleased/292035-convert-the-assignees-feature-into-a-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Create new assignees widget for boards
+merge_request: 50054
+author:
+type: changed
diff --git a/changelogs/unreleased/292391-quickactions-usage-ping.yml b/changelogs/unreleased/292391-quickactions-usage-ping.yml
new file mode 100644
index 00000000000..64050f281bb
--- /dev/null
+++ b/changelogs/unreleased/292391-quickactions-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Track monthly active users for QuickActions
+merge_request: 52398
+author:
+type: added
diff --git a/changelogs/unreleased/292498-editor-lite-diff-editor.yml b/changelogs/unreleased/292498-editor-lite-diff-editor.yml
new file mode 100644
index 00000000000..3f9d9576013
--- /dev/null
+++ b/changelogs/unreleased/292498-editor-lite-diff-editor.yml
@@ -0,0 +1,5 @@
+---
+title: 'Editor Lite: support for Diff Instance'
+merge_request: 51470
+author:
+type: added
diff --git a/changelogs/unreleased/292507-batch-merge-ref-diff.yml b/changelogs/unreleased/292507-batch-merge-ref-diff.yml
new file mode 100644
index 00000000000..fb000c4f160
--- /dev/null
+++ b/changelogs/unreleased/292507-batch-merge-ref-diff.yml
@@ -0,0 +1,5 @@
+---
+title: Support batch loading of merge head diffs
+merge_request: 51078
+author:
+type: performance
diff --git a/changelogs/unreleased/292713-remove-loading-tf.yml b/changelogs/unreleased/292713-remove-loading-tf.yml
new file mode 100644
index 00000000000..e5f11a2cad6
--- /dev/null
+++ b/changelogs/unreleased/292713-remove-loading-tf.yml
@@ -0,0 +1,5 @@
+---
+title: Display loading when removing Terraform state
+merge_request: 53897
+author:
+type: changed
diff --git a/changelogs/unreleased/292713-tf-lock-loading.yml b/changelogs/unreleased/292713-tf-lock-loading.yml
new file mode 100644
index 00000000000..e6ea8b01ecc
--- /dev/null
+++ b/changelogs/unreleased/292713-tf-lock-loading.yml
@@ -0,0 +1,5 @@
+---
+title: Add loading display to Terraform lock action
+merge_request: 53475
+author:
+type: changed
diff --git a/changelogs/unreleased/292714-allow-reviewers-to-be-updated-via-api.yml b/changelogs/unreleased/292714-allow-reviewers-to-be-updated-via-api.yml
new file mode 100644
index 00000000000..aa491ecfdcb
--- /dev/null
+++ b/changelogs/unreleased/292714-allow-reviewers-to-be-updated-via-api.yml
@@ -0,0 +1,5 @@
+---
+title: Allow reviewers to be updated via MergeRequest API
+merge_request: 51186
+author:
+type: added
diff --git a/changelogs/unreleased/292820-update-user-api-docs-and-enable-ff.yml b/changelogs/unreleased/292820-update-user-api-docs-and-enable-ff.yml
new file mode 100644
index 00000000000..7c8824ed38a
--- /dev/null
+++ b/changelogs/unreleased/292820-update-user-api-docs-and-enable-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Schedule user status cleanup after a given time interval via the REST API
+merge_request: 54207
+author:
+type: added
diff --git a/changelogs/unreleased/292825-track-approver-metrics-for-a-merge-request.yml b/changelogs/unreleased/292825-track-approver-metrics-for-a-merge-request.yml
new file mode 100644
index 00000000000..7b5e253b7e0
--- /dev/null
+++ b/changelogs/unreleased/292825-track-approver-metrics-for-a-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Add metrics for merge request approvals and revoking approvals
+merge_request: 53201
+author:
+type: added
diff --git a/changelogs/unreleased/292828-track-suggestion-metrics.yml b/changelogs/unreleased/292828-track-suggestion-metrics.yml
new file mode 100644
index 00000000000..4d6e87baedf
--- /dev/null
+++ b/changelogs/unreleased/292828-track-suggestion-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Track suggestion add/apply metrics
+merge_request: 52189
+author:
+type: other
diff --git a/changelogs/unreleased/293477-update-pages-help-text.yml b/changelogs/unreleased/293477-update-pages-help-text.yml
new file mode 100644
index 00000000000..5117aec4fcc
--- /dev/null
+++ b/changelogs/unreleased/293477-update-pages-help-text.yml
@@ -0,0 +1,5 @@
+---
+title: Update links in Pages settings
+merge_request: 51847
+author:
+type: other
diff --git a/changelogs/unreleased/293720-agent-created-by.yml b/changelogs/unreleased/293720-agent-created-by.yml
new file mode 100644
index 00000000000..52f37f321ae
--- /dev/null
+++ b/changelogs/unreleased/293720-agent-created-by.yml
@@ -0,0 +1,5 @@
+---
+title: Add created_by_user to cluster agents
+merge_request: 54011
+author:
+type: added
diff --git a/changelogs/unreleased/293720-token-created-by.yml b/changelogs/unreleased/293720-token-created-by.yml
new file mode 100644
index 00000000000..efbefa9e169
--- /dev/null
+++ b/changelogs/unreleased/293720-token-created-by.yml
@@ -0,0 +1,5 @@
+---
+title: Add created_by_user to cluster agent tokens
+merge_request: 54019
+author:
+type: added
diff --git a/changelogs/unreleased/293819-enable-sort-diffs-default.yml b/changelogs/unreleased/293819-enable-sort-diffs-default.yml
new file mode 100644
index 00000000000..008f779a656
--- /dev/null
+++ b/changelogs/unreleased/293819-enable-sort-diffs-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable sorting diffs by default
+merge_request: 54210
+author:
+type: other
diff --git a/changelogs/unreleased/294004-enable-jira-sync-builds.yml b/changelogs/unreleased/294004-enable-jira-sync-builds.yml
new file mode 100644
index 00000000000..5a81425a89c
--- /dev/null
+++ b/changelogs/unreleased/294004-enable-jira-sync-builds.yml
@@ -0,0 +1,5 @@
+---
+title: Sync pipeline builds to Jira
+merge_request: 51627
+author:
+type: added
diff --git a/changelogs/unreleased/294007-bump-workhorse.yml b/changelogs/unreleased/294007-bump-workhorse.yml
new file mode 100644
index 00000000000..9c9cc468715
--- /dev/null
+++ b/changelogs/unreleased/294007-bump-workhorse.yml
@@ -0,0 +1,5 @@
+---
+title: Update Workhorse to v8.60.0
+merge_request: 51965
+author:
+type: changed
diff --git a/changelogs/unreleased/294156-fix-merge-request-changes-comment-fullscreen-mode.yml b/changelogs/unreleased/294156-fix-merge-request-changes-comment-fullscreen-mode.yml
new file mode 100644
index 00000000000..958224a13ca
--- /dev/null
+++ b/changelogs/unreleased/294156-fix-merge-request-changes-comment-fullscreen-mode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix fullscreen mode not working for comments in merge request changes view
+merge_request: 53009
+author: Simon Stieger @sim0
+type: fixed
diff --git a/changelogs/unreleased/295211-create-BV_x_MODEL-constants.yml b/changelogs/unreleased/295211-create-BV_x_MODEL-constants.yml
new file mode 100644
index 00000000000..aa950388149
--- /dev/null
+++ b/changelogs/unreleased/295211-create-BV_x_MODEL-constants.yml
@@ -0,0 +1,5 @@
+---
+title: Create constants for bv::show::modal and bv::hide::modal
+merge_request: 52518
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/295311-add-updated-at-to-search-results.yml b/changelogs/unreleased/295311-add-updated-at-to-search-results.yml
new file mode 100644
index 00000000000..b43e37e0481
--- /dev/null
+++ b/changelogs/unreleased/295311-add-updated-at-to-search-results.yml
@@ -0,0 +1,5 @@
+---
+title: Add updated_at output to search results
+merge_request: 53958
+author:
+type: changed
diff --git a/changelogs/unreleased/295311-sort-mr-issues-last-updated.yml b/changelogs/unreleased/295311-sort-mr-issues-last-updated.yml
new file mode 100644
index 00000000000..16317279ee0
--- /dev/null
+++ b/changelogs/unreleased/295311-sort-mr-issues-last-updated.yml
@@ -0,0 +1,5 @@
+---
+title: 'Search: Add Sort by Last Updated to Issue/MR'
+merge_request: 53589
+author:
+type: changed
diff --git a/changelogs/unreleased/295621-rename-asset-proxy-whitelist-setting.yml b/changelogs/unreleased/295621-rename-asset-proxy-whitelist-setting.yml
new file mode 100644
index 00000000000..2073e3ea750
--- /dev/null
+++ b/changelogs/unreleased/295621-rename-asset-proxy-whitelist-setting.yml
@@ -0,0 +1,5 @@
+---
+title: Rename asset_proxy_whitelist column on application_settings
+merge_request: 50824
+author:
+type: changed
diff --git a/changelogs/unreleased/295626-when-epic-swimlanes-are-enabled-milestones-are-incorrectly-scoped-.yml b/changelogs/unreleased/295626-when-epic-swimlanes-are-enabled-milestones-are-incorrectly-scoped-.yml
new file mode 100644
index 00000000000..7125d944591
--- /dev/null
+++ b/changelogs/unreleased/295626-when-epic-swimlanes-are-enabled-milestones-are-incorrectly-scoped-.yml
@@ -0,0 +1,5 @@
+---
+title: Scope milestones on swimlane boards to project and its ancestors
+merge_request: 52199
+author:
+type: fixed
diff --git a/changelogs/unreleased/296133-engineering-in-product-email-campaigns-in-saas.yml b/changelogs/unreleased/296133-engineering-in-product-email-campaigns-in-saas.yml
new file mode 100644
index 00000000000..c796d23c93f
--- /dev/null
+++ b/changelogs/unreleased/296133-engineering-in-product-email-campaigns-in-saas.yml
@@ -0,0 +1,5 @@
+---
+title: Add indexes for onboarding progress table
+merge_request: 50679
+author:
+type: performance
diff --git a/changelogs/unreleased/296521-leave-this-group-button-not-working.yml b/changelogs/unreleased/296521-leave-this-group-button-not-working.yml
new file mode 100644
index 00000000000..9fea6214cae
--- /dev/null
+++ b/changelogs/unreleased/296521-leave-this-group-button-not-working.yml
@@ -0,0 +1,5 @@
+---
+title: Missing action prop on group page
+merge_request: 52379
+author:
+type: fixed
diff --git a/changelogs/unreleased/296645-removed-unused-dropdown.yml b/changelogs/unreleased/296645-removed-unused-dropdown.yml
new file mode 100644
index 00000000000..754f1d2118f
--- /dev/null
+++ b/changelogs/unreleased/296645-removed-unused-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: Removed unused Text dropdown
+merge_request: 53464
+author:
+type: removed
diff --git a/changelogs/unreleased/296667-fix-branch-change-with-line-selected.yml b/changelogs/unreleased/296667-fix-branch-change-with-line-selected.yml
new file mode 100644
index 00000000000..f42e04a193c
--- /dev/null
+++ b/changelogs/unreleased/296667-fix-branch-change-with-line-selected.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug branch change with line selected
+merge_request: 52285
+author:
+type: fixed
diff --git a/changelogs/unreleased/296669-migration-support-customizable-timeouts-for-git-cli-2fa.yml b/changelogs/unreleased/296669-migration-support-customizable-timeouts-for-git-cli-2fa.yml
new file mode 100644
index 00000000000..a21210270f2
--- /dev/null
+++ b/changelogs/unreleased/296669-migration-support-customizable-timeouts-for-git-cli-2fa.yml
@@ -0,0 +1,5 @@
+---
+title: Add git_two_factor_session_expiry column to application_settings table
+merge_request: 52761
+author:
+type: added
diff --git a/changelogs/unreleased/296754-followup-from-refactor-namespaceonboardingaction-model-to-onboardi.yml b/changelogs/unreleased/296754-followup-from-refactor-namespaceonboardingaction-model-to-onboardi.yml
new file mode 100644
index 00000000000..226033c26ba
--- /dev/null
+++ b/changelogs/unreleased/296754-followup-from-refactor-namespaceonboardingaction-model-to-onboardi.yml
@@ -0,0 +1,5 @@
+---
+title: Remove namespace_onboarding_actions table
+merge_request: 53488
+author:
+type: other
diff --git a/changelogs/unreleased/296756-cablett-remove-index.yml b/changelogs/unreleased/296756-cablett-remove-index.yml
new file mode 100644
index 00000000000..a0d19eb24bd
--- /dev/null
+++ b/changelogs/unreleased/296756-cablett-remove-index.yml
@@ -0,0 +1,5 @@
+---
+title: Remove inconsistent index in backup_labels table
+merge_request: 53189
+author:
+type: other
diff --git a/changelogs/unreleased/296856-prevent-creating-duplicate-pipelines-manually.yml b/changelogs/unreleased/296856-prevent-creating-duplicate-pipelines-manually.yml
new file mode 100644
index 00000000000..b1baef8036b
--- /dev/null
+++ b/changelogs/unreleased/296856-prevent-creating-duplicate-pipelines-manually.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent creating duplicate pipelines manually
+merge_request: 51076
+author: Kev @KevSlashNull
+type: changed
diff --git a/changelogs/unreleased/296895-group-setting-to-allow-or-prevent-duplicate-maven-uploads.yml b/changelogs/unreleased/296895-group-setting-to-allow-or-prevent-duplicate-maven-uploads.yml
new file mode 100644
index 00000000000..cfa7478ed09
--- /dev/null
+++ b/changelogs/unreleased/296895-group-setting-to-allow-or-prevent-duplicate-maven-uploads.yml
@@ -0,0 +1,5 @@
+---
+title: Enable group setting to allow or prevent duplicate Maven uploads
+merge_request: 53591
+author:
+type: added
diff --git a/changelogs/unreleased/296943-expose-user-availability.yml b/changelogs/unreleased/296943-expose-user-availability.yml
new file mode 100644
index 00000000000..a12629468de
--- /dev/null
+++ b/changelogs/unreleased/296943-expose-user-availability.yml
@@ -0,0 +1,5 @@
+---
+title: Expose user availablility data on issuable pages
+merge_request: 52333
+author:
+type: other
diff --git a/changelogs/unreleased/296948-container-and-package-list-ui-polish-condense-spacing-to-match-iss.yml b/changelogs/unreleased/296948-container-and-package-list-ui-polish-condense-spacing-to-match-iss.yml
new file mode 100644
index 00000000000..74d5504951b
--- /dev/null
+++ b/changelogs/unreleased/296948-container-and-package-list-ui-polish-condense-spacing-to-match-iss.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce vertical padding of registry list item
+merge_request: 51961
+author:
+type: changed
diff --git a/changelogs/unreleased/296990-enable-jira-ff-sync.yml b/changelogs/unreleased/296990-enable-jira-ff-sync.yml
new file mode 100644
index 00000000000..ac9b71bc37d
--- /dev/null
+++ b/changelogs/unreleased/296990-enable-jira-ff-sync.yml
@@ -0,0 +1,5 @@
+---
+title: Enable synchronization of feature flags to Jira
+merge_request: 51796
+author:
+type: added
diff --git a/changelogs/unreleased/297346-flaky-spec-in-ee-spec-features-burnup_charts_spec-rb-burnup-charts.yml b/changelogs/unreleased/297346-flaky-spec-in-ee-spec-features-burnup_charts_spec-rb-burnup-charts.yml
new file mode 100644
index 00000000000..72e55f73bcc
--- /dev/null
+++ b/changelogs/unreleased/297346-flaky-spec-in-ee-spec-features-burnup_charts_spec-rb-burnup-charts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix charts sometimes being hidden on milestone page
+merge_request: 52552
+author:
+type: fixed
diff --git a/changelogs/unreleased/297644-jira-association-requirements-be.yml b/changelogs/unreleased/297644-jira-association-requirements-be.yml
new file mode 100644
index 00000000000..88ec9e2a980
--- /dev/null
+++ b/changelogs/unreleased/297644-jira-association-requirements-be.yml
@@ -0,0 +1,5 @@
+---
+title: Adds jira issue enforcement field
+merge_request: 52896
+author:
+type: added
diff --git a/changelogs/unreleased/297664-maintain-data-parity-between-experimentuser-experimentsubject.yml b/changelogs/unreleased/297664-maintain-data-parity-between-experimentuser-experimentsubject.yml
new file mode 100644
index 00000000000..0227569839e
--- /dev/null
+++ b/changelogs/unreleased/297664-maintain-data-parity-between-experimentuser-experimentsubject.yml
@@ -0,0 +1,6 @@
+---
+title: Add converted_at(timestamp) & context(jsonb) columns to the experiment_subjects
+ table
+merge_request: 51659
+author:
+type: changed
diff --git a/changelogs/unreleased/298703-terraform-name-validation.yml b/changelogs/unreleased/298703-terraform-name-validation.yml
new file mode 100644
index 00000000000..678bb2e48e8
--- /dev/null
+++ b/changelogs/unreleased/298703-terraform-name-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Add name validation to Terraform state
+merge_request: 52102
+author:
+type: changed
diff --git a/changelogs/unreleased/298783-log-user-instance-request-in-audit-events.yml b/changelogs/unreleased/298783-log-user-instance-request-in-audit-events.yml
new file mode 100644
index 00000000000..21383599b5b
--- /dev/null
+++ b/changelogs/unreleased/298783-log-user-instance-request-in-audit-events.yml
@@ -0,0 +1,5 @@
+---
+title: Log user approval/rejection in application logs
+merge_request: 51768
+author:
+type: added
diff --git a/changelogs/unreleased/298790-the-options-to-show-hide-the-open-and-closed-lists-in-boards-shoul.yml b/changelogs/unreleased/298790-the-options-to-show-hide-the-open-and-closed-lists-in-boards-shoul.yml
new file mode 100644
index 00000000000..37ef33c8ad2
--- /dev/null
+++ b/changelogs/unreleased/298790-the-options-to-show-hide-the-open-and-closed-lists-in-boards-shoul.yml
@@ -0,0 +1,5 @@
+---
+title: Disable board configuration options for users without edit permission
+merge_request: 52077
+author:
+type: fixed
diff --git a/changelogs/unreleased/298801-group-migration-show-import-status-frontend.yml b/changelogs/unreleased/298801-group-migration-show-import-status-frontend.yml
new file mode 100644
index 00000000000..e65b975199b
--- /dev/null
+++ b/changelogs/unreleased/298801-group-migration-show-import-status-frontend.yml
@@ -0,0 +1,5 @@
+---
+title: Use realtime_changes endpoint for reporting group import status
+merge_request: 52796
+author:
+type: changed
diff --git a/changelogs/unreleased/298822-ci-cd-general-pipelines-settings-ui-text.yml b/changelogs/unreleased/298822-ci-cd-general-pipelines-settings-ui-text.yml
new file mode 100644
index 00000000000..279be572394
--- /dev/null
+++ b/changelogs/unreleased/298822-ci-cd-general-pipelines-settings-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Update CI general pipeline settings UI text
+merge_request: 51806
+author:
+type: other
diff --git a/changelogs/unreleased/298975-search-autodiscovery.yml b/changelogs/unreleased/298975-search-autodiscovery.yml
new file mode 100644
index 00000000000..3969c1745ea
--- /dev/null
+++ b/changelogs/unreleased/298975-search-autodiscovery.yml
@@ -0,0 +1,5 @@
+---
+title: Add OpenSearch support
+merge_request: 52583
+author:
+type: added
diff --git a/changelogs/unreleased/299052-fj-add-repository-read-only-column-to-namespace-settings.yml b/changelogs/unreleased/299052-fj-add-repository-read-only-column-to-namespace-settings.yml
new file mode 100644
index 00000000000..3838938be30
--- /dev/null
+++ b/changelogs/unreleased/299052-fj-add-repository-read-only-column-to-namespace-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Add repository_read_only column to NamespaceSettings table
+merge_request: 52300
+author:
+type: added
diff --git a/changelogs/unreleased/299087-track-assignees-and-reviewers-for-merge-requests.yml b/changelogs/unreleased/299087-track-assignees-and-reviewers-for-merge-requests.yml
new file mode 100644
index 00000000000..d07f84133b2
--- /dev/null
+++ b/changelogs/unreleased/299087-track-assignees-and-reviewers-for-merge-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Track the number of users who are assigned and get requested for reviews
+merge_request: 52194
+author:
+type: other
diff --git a/changelogs/unreleased/299102-fix-spelling.yml b/changelogs/unreleased/299102-fix-spelling.yml
new file mode 100644
index 00000000000..f5aee2a1a44
--- /dev/null
+++ b/changelogs/unreleased/299102-fix-spelling.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Add a to do spelling on epics
+merge_request: 52292
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/299213-project-filter-regression.yml b/changelogs/unreleased/299213-project-filter-regression.yml
new file mode 100644
index 00000000000..243b408ebf8
--- /dev/null
+++ b/changelogs/unreleased/299213-project-filter-regression.yml
@@ -0,0 +1,5 @@
+---
+title: Global Search - Project Filter sets Group
+merge_request: 52015
+author:
+type: fixed
diff --git a/changelogs/unreleased/299263-rubygems-metadata-migration.yml b/changelogs/unreleased/299263-rubygems-metadata-migration.yml
new file mode 100644
index 00000000000..be5842a17d6
--- /dev/null
+++ b/changelogs/unreleased/299263-rubygems-metadata-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Add rubygems metadata table
+merge_request: 52639
+author:
+type: added
diff --git a/changelogs/unreleased/299264-track-create-merge-request-from-issues.yml b/changelogs/unreleased/299264-track-create-merge-request-from-issues.yml
new file mode 100644
index 00000000000..8cf9c5509ed
--- /dev/null
+++ b/changelogs/unreleased/299264-track-create-merge-request-from-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Track when a merge request is created from an issue
+merge_request: 53808
+author:
+type: other
diff --git a/changelogs/unreleased/299343-fj-enable-housekeeping-for-wikis.yml b/changelogs/unreleased/299343-fj-enable-housekeeping-for-wikis.yml
new file mode 100644
index 00000000000..7ae645820f0
--- /dev/null
+++ b/changelogs/unreleased/299343-fj-enable-housekeeping-for-wikis.yml
@@ -0,0 +1,5 @@
+---
+title: Enable housekeeping for project and group wiki repos
+merge_request: 53011
+author:
+type: added
diff --git a/changelogs/unreleased/299403-usage_data_unique_users_committing_ciconfigfile.yml b/changelogs/unreleased/299403-usage_data_unique_users_committing_ciconfigfile.yml
new file mode 100644
index 00000000000..f62b78d1b8d
--- /dev/null
+++ b/changelogs/unreleased/299403-usage_data_unique_users_committing_ciconfigfile.yml
@@ -0,0 +1,5 @@
+---
+title: Add tracking to measure the number of unique users committing CI config
+merge_request: 54192
+author:
+type: other
diff --git a/changelogs/unreleased/299457-user-cannot-merge-an-issue.yml b/changelogs/unreleased/299457-user-cannot-merge-an-issue.yml
new file mode 100644
index 00000000000..20ca2c6cc38
--- /dev/null
+++ b/changelogs/unreleased/299457-user-cannot-merge-an-issue.yml
@@ -0,0 +1,5 @@
+---
+title: 'Resolve User cannot merge an issue'
+merge_request: 52311
+author:
+type: fixed
diff --git a/changelogs/unreleased/299494-add-tooltips-to-requirement-import-and-export.yml b/changelogs/unreleased/299494-add-tooltips-to-requirement-import-and-export.yml
new file mode 100644
index 00000000000..1c09b95b3fd
--- /dev/null
+++ b/changelogs/unreleased/299494-add-tooltips-to-requirement-import-and-export.yml
@@ -0,0 +1,5 @@
+---
+title: Add tooltips to requirement import and export buttons
+merge_request: 52582
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/299559-remove-add-border-borderless-prop-from-ci-icon-when-used-together.yml b/changelogs/unreleased/299559-remove-add-border-borderless-prop-from-ci-icon-when-used-together.yml
new file mode 100644
index 00000000000..c2e5fa78629
--- /dev/null
+++ b/changelogs/unreleased/299559-remove-add-border-borderless-prop-from-ci-icon-when-used-together.yml
@@ -0,0 +1,6 @@
+---
+title: Make CI Icon in merge request pipeline detail consistent with other widget
+ icons
+merge_request: 52516
+author:
+type: fixed
diff --git a/changelogs/unreleased/299719-fj-fix-bug-personal-snippet-thread-discussion.yml b/changelogs/unreleased/299719-fj-fix-bug-personal-snippet-thread-discussion.yml
new file mode 100644
index 00000000000..d19b98eb120
--- /dev/null
+++ b/changelogs/unreleased/299719-fj-fix-bug-personal-snippet-thread-discussion.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug in personal snippet thread discussions
+merge_request: 52490
+author:
+type: fixed
diff --git a/changelogs/unreleased/299828-okr-ci-cd-variables-review-and-revise-settings-related-ui-text.yml b/changelogs/unreleased/299828-okr-ci-cd-variables-review-and-revise-settings-related-ui-text.yml
new file mode 100644
index 00000000000..04f2904aebb
--- /dev/null
+++ b/changelogs/unreleased/299828-okr-ci-cd-variables-review-and-revise-settings-related-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Improve variable settings ui text
+merge_request: 52462
+author:
+type: other
diff --git a/changelogs/unreleased/299925-fix-i18n-syntax-in-app-views-projects-cleanup-_show-html-haml.yml b/changelogs/unreleased/299925-fix-i18n-syntax-in-app-views-projects-cleanup-_show-html-haml.yml
new file mode 100644
index 00000000000..bef1ee88a9e
--- /dev/null
+++ b/changelogs/unreleased/299925-fix-i18n-syntax-in-app-views-projects-cleanup-_show-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Make text on Repository Cleanup page translatable
+merge_request: 52529
+author:
+type: fixed
diff --git a/changelogs/unreleased/299954-feature-flag-rollout-of-vue_project_members_list.yml b/changelogs/unreleased/299954-feature-flag-rollout-of-vue_project_members_list.yml
new file mode 100644
index 00000000000..2ede10d9617
--- /dev/null
+++ b/changelogs/unreleased/299954-feature-flag-rollout-of-vue_project_members_list.yml
@@ -0,0 +1,5 @@
+---
+title: Improve project members management, filtering, and sorting
+merge_request: 53935
+author:
+type: changed
diff --git a/changelogs/unreleased/299982-Remove-v-html-from-mr_widget_pipeline-vue.yml b/changelogs/unreleased/299982-Remove-v-html-from-mr_widget_pipeline-vue.yml
new file mode 100644
index 00000000000..93209496010
--- /dev/null
+++ b/changelogs/unreleased/299982-Remove-v-html-from-mr_widget_pipeline-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Remove v-html from mr_widget_pipeline.vue
+merge_request: 52564
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/2fa-gl-button.yml b/changelogs/unreleased/2fa-gl-button.yml
new file mode 100644
index 00000000000..0ac2a85ae7e
--- /dev/null
+++ b/changelogs/unreleased/2fa-gl-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button to Set up new device button in 2fa settings
+merge_request: 51283
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/300048-leipert-allow-head-requests.yml b/changelogs/unreleased/300048-leipert-allow-head-requests.yml
new file mode 100644
index 00000000000..2c62d779b3b
--- /dev/null
+++ b/changelogs/unreleased/300048-leipert-allow-head-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Allow HEAD requests for read_api and read_user scope tokens
+merge_request: 53088
+author:
+type: fixed
diff --git a/changelogs/unreleased/300067-mermaid-markdown-er-diagram-does-not-render-attributes.yml b/changelogs/unreleased/300067-mermaid-markdown-er-diagram-does-not-render-attributes.yml
new file mode 100644
index 00000000000..27b100680de
--- /dev/null
+++ b/changelogs/unreleased/300067-mermaid-markdown-er-diagram-does-not-render-attributes.yml
@@ -0,0 +1,5 @@
+---
+title: Update mermaid.js to v8.9.0
+merge_request: 53123
+author:
+type: other
diff --git a/changelogs/unreleased/300105-remove-integrations_test_webhook_optimizations-feature-flag.yml b/changelogs/unreleased/300105-remove-integrations_test_webhook_optimizations-feature-flag.yml
new file mode 100644
index 00000000000..5d6d82ab97d
--- /dev/null
+++ b/changelogs/unreleased/300105-remove-integrations_test_webhook_optimizations-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Fix timeouts affecting certain test webhooks
+merge_request: 53676
+author:
+type: fixed
diff --git a/changelogs/unreleased/300156-external-request-tracking-errors-on-ipv6-host.yml b/changelogs/unreleased/300156-external-request-tracking-errors-on-ipv6-host.yml
new file mode 100644
index 00000000000..919b550cc2c
--- /dev/null
+++ b/changelogs/unreleased/300156-external-request-tracking-errors-on-ipv6-host.yml
@@ -0,0 +1,5 @@
+---
+title: Handle IPv6 hostname in ExternalHTTP instrumenter
+merge_request: 52691
+author:
+type: fixed
diff --git a/changelogs/unreleased/300209-fix-suggestions-bad-request.yml b/changelogs/unreleased/300209-fix-suggestions-bad-request.yml
new file mode 100644
index 00000000000..0d0d0d8e454
--- /dev/null
+++ b/changelogs/unreleased/300209-fix-suggestions-bad-request.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bad request error when applying suggestions
+merge_request: 52735
+author:
+type: fixed
diff --git a/changelogs/unreleased/300220-add-security-orchestration-policy-configuration-model.yml b/changelogs/unreleased/300220-add-security-orchestration-policy-configuration-model.yml
new file mode 100644
index 00000000000..6cd82ca949a
--- /dev/null
+++ b/changelogs/unreleased/300220-add-security-orchestration-policy-configuration-model.yml
@@ -0,0 +1,5 @@
+---
+title: Add Security Orchestration Policy Configuration
+merge_request: 53743
+author:
+type: added
diff --git a/changelogs/unreleased/300263-remove-btn-build-class.yml b/changelogs/unreleased/300263-remove-btn-build-class.yml
new file mode 100644
index 00000000000..d952957e639
--- /dev/null
+++ b/changelogs/unreleased/300263-remove-btn-build-class.yml
@@ -0,0 +1,6 @@
+---
+title: Align action buttons in jobs page. Reduce icon buttons width in jobs, artifacts
+ and environment pages.
+merge_request: 53155
+author:
+type: changed
diff --git a/changelogs/unreleased/300367-breadcrumb-links-to-404-page.yml b/changelogs/unreleased/300367-breadcrumb-links-to-404-page.yml
new file mode 100644
index 00000000000..7bd2bcec3b9
--- /dev/null
+++ b/changelogs/unreleased/300367-breadcrumb-links-to-404-page.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incorrect breadcrumb path for import groups page
+merge_request: 54211
+author:
+type: fixed
diff --git a/changelogs/unreleased/300524-create-worker-to-clean-up-composer-cache-pages.yml b/changelogs/unreleased/300524-create-worker-to-clean-up-composer-cache-pages.yml
new file mode 100644
index 00000000000..4acbc9dae00
--- /dev/null
+++ b/changelogs/unreleased/300524-create-worker-to-clean-up-composer-cache-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Cleanup composer cache pages
+merge_request: 53005
+author:
+type: other
diff --git a/changelogs/unreleased/300546-add-new-plans.yml b/changelogs/unreleased/300546-add-new-plans.yml
new file mode 100644
index 00000000000..156302c05a2
--- /dev/null
+++ b/changelogs/unreleased/300546-add-new-plans.yml
@@ -0,0 +1,5 @@
+---
+title: Migration to add new Premium and Ultimate plan records
+merge_request: 53465
+author:
+type: added
diff --git a/changelogs/unreleased/300652-fix-prom-metrics-in-puma-single.yml b/changelogs/unreleased/300652-fix-prom-metrics-in-puma-single.yml
new file mode 100644
index 00000000000..a3821c51291
--- /dev/null
+++ b/changelogs/unreleased/300652-fix-prom-metrics-in-puma-single.yml
@@ -0,0 +1,5 @@
+---
+title: Move CleanupMultiprocDirService out of config.ru
+merge_request: 53139
+author:
+type: other
diff --git a/changelogs/unreleased/300661-fix-readiness-for-puma-single-2.yml b/changelogs/unreleased/300661-fix-readiness-for-puma-single-2.yml
new file mode 100644
index 00000000000..ae84cfc2785
--- /dev/null
+++ b/changelogs/unreleased/300661-fix-readiness-for-puma-single-2.yml
@@ -0,0 +1,5 @@
+---
+title: Fix /-/readiness probe for Puma Single
+merge_request: 53708
+author:
+type: other
diff --git a/changelogs/unreleased/300847-fix-link.yml b/changelogs/unreleased/300847-fix-link.yml
new file mode 100644
index 00000000000..adb25997c00
--- /dev/null
+++ b/changelogs/unreleased/300847-fix-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes broken password reset link in account deletion message
+merge_request: 53274
+author:
+type: fixed
diff --git a/changelogs/unreleased/300860-jobs-empty-state-successful-cleanup.yml b/changelogs/unreleased/300860-jobs-empty-state-successful-cleanup.yml
new file mode 100644
index 00000000000..1442d008f88
--- /dev/null
+++ b/changelogs/unreleased/300860-jobs-empty-state-successful-cleanup.yml
@@ -0,0 +1,5 @@
+---
+title: Add empty jobs page with link to editor
+merge_request: 53240
+author:
+type: added
diff --git a/changelogs/unreleased/300910-drop-puma-clustered-validation.yml b/changelogs/unreleased/300910-drop-puma-clustered-validation.yml
new file mode 100644
index 00000000000..430e995919a
--- /dev/null
+++ b/changelogs/unreleased/300910-drop-puma-clustered-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Allow running Puma in Single mode
+merge_request: 53830
+author:
+type: other
diff --git a/changelogs/unreleased/301100-gma-badge.yml b/changelogs/unreleased/301100-gma-badge.yml
new file mode 100644
index 00000000000..67f6eccb9a9
--- /dev/null
+++ b/changelogs/unreleased/301100-gma-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Add indicator in admin dashboard if user is group managed
+merge_request: 54027
+author:
+type: added
diff --git a/changelogs/unreleased/301140-conditionally-render-test-case-file.yml b/changelogs/unreleased/301140-conditionally-render-test-case-file.yml
new file mode 100644
index 00000000000..2c5efb40db6
--- /dev/null
+++ b/changelogs/unreleased/301140-conditionally-render-test-case-file.yml
@@ -0,0 +1,5 @@
+---
+title: Conditionally render test case file
+merge_request: 53497
+author:
+type: fixed
diff --git a/changelogs/unreleased/301236-fix-test-report-not-rendering.yml b/changelogs/unreleased/301236-fix-test-report-not-rendering.yml
new file mode 100644
index 00000000000..66f4624dd86
--- /dev/null
+++ b/changelogs/unreleased/301236-fix-test-report-not-rendering.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline test report not rendering when missing properties
+merge_request: 54363
+author:
+type: fixed
diff --git a/changelogs/unreleased/30141-improve-merge-failed-error-fe.yml b/changelogs/unreleased/30141-improve-merge-failed-error-fe.yml
new file mode 100644
index 00000000000..697a1819d83
--- /dev/null
+++ b/changelogs/unreleased/30141-improve-merge-failed-error-fe.yml
@@ -0,0 +1,5 @@
+---
+title: Improve merge failed error
+merge_request: 52555
+author:
+type: changed
diff --git a/changelogs/unreleased/30141-merge-error-msg-update.yml b/changelogs/unreleased/30141-merge-error-msg-update.yml
new file mode 100644
index 00000000000..4abe2c6ebf6
--- /dev/null
+++ b/changelogs/unreleased/30141-merge-error-msg-update.yml
@@ -0,0 +1,5 @@
+---
+title: Show more appropriate error message when merging fails
+merge_request: 52671
+author:
+type: fixed
diff --git a/changelogs/unreleased/302-improve-visibility-of-time-spent-with-external-io.yml b/changelogs/unreleased/302-improve-visibility-of-time-spent-with-external-io.yml
new file mode 100644
index 00000000000..dfe39e01723
--- /dev/null
+++ b/changelogs/unreleased/302-improve-visibility-of-time-spent-with-external-io.yml
@@ -0,0 +1,5 @@
+---
+title: Improve visibility of time spent with external HTTP calls
+merge_request: 50696
+author:
+type: added
diff --git a/changelogs/unreleased/31064-ensure-diff-patch-size-limit-is-monitorable.yml b/changelogs/unreleased/31064-ensure-diff-patch-size-limit-is-monitorable.yml
new file mode 100644
index 00000000000..59bdb1905be
--- /dev/null
+++ b/changelogs/unreleased/31064-ensure-diff-patch-size-limit-is-monitorable.yml
@@ -0,0 +1,5 @@
+---
+title: Add `patch_hard_limit_bytes_hit` metric for monitoring diff patch size limit hits
+merge_request: 52456
+author:
+type: added
diff --git a/changelogs/unreleased/320792-add-an-api-rate-limit-for-new-notes-using-application-rate-limits.yml b/changelogs/unreleased/320792-add-an-api-rate-limit-for-new-notes-using-application-rate-limits.yml
new file mode 100644
index 00000000000..7882a1d7f98
--- /dev/null
+++ b/changelogs/unreleased/320792-add-an-api-rate-limit-for-new-notes-using-application-rate-limits.yml
@@ -0,0 +1,5 @@
+---
+title: Add application rate limit for Notes creation
+merge_request: 53637
+author:
+type: added
diff --git a/changelogs/unreleased/320836-display-compare-button.yml b/changelogs/unreleased/320836-display-compare-button.yml
new file mode 100644
index 00000000000..4d258903170
--- /dev/null
+++ b/changelogs/unreleased/320836-display-compare-button.yml
@@ -0,0 +1,5 @@
+---
+title: Safe guard repo compare when data is undefined
+merge_request: 54371
+author:
+type: fixed
diff --git a/changelogs/unreleased/320965-confidential-issue.yml b/changelogs/unreleased/320965-confidential-issue.yml
new file mode 100644
index 00000000000..c884c28a3f3
--- /dev/null
+++ b/changelogs/unreleased/320965-confidential-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Add an allowlist to exclude users from the rate limit on notes creation
+merge_request: 53866
+author:
+type: added
diff --git a/changelogs/unreleased/321040-jira-list-search-not-working.yml b/changelogs/unreleased/321040-jira-list-search-not-working.yml
new file mode 100644
index 00000000000..13937b8ef4d
--- /dev/null
+++ b/changelogs/unreleased/321040-jira-list-search-not-working.yml
@@ -0,0 +1,5 @@
+---
+title: Fix search functionality in Jira issues list
+merge_request: 54312
+author:
+type: fixed
diff --git a/changelogs/unreleased/321447-fix-foss.yml b/changelogs/unreleased/321447-fix-foss.yml
new file mode 100644
index 00000000000..9cff6ebec6a
--- /dev/null
+++ b/changelogs/unreleased/321447-fix-foss.yml
@@ -0,0 +1,5 @@
+---
+title: Move GMA user badging in admin to EE only
+merge_request: 54125
+author:
+type: fixed
diff --git a/changelogs/unreleased/36705-search-across-full-name-for-assignee-autocomplete.yml b/changelogs/unreleased/36705-search-across-full-name-for-assignee-autocomplete.yml
new file mode 100644
index 00000000000..0b9d01960e0
--- /dev/null
+++ b/changelogs/unreleased/36705-search-across-full-name-for-assignee-autocomplete.yml
@@ -0,0 +1,5 @@
+---
+title: Search across full name for mentions autocomplete
+merge_request: 52488
+author:
+type: added
diff --git a/changelogs/unreleased/52756-pipeline_schedule_worker_cron.yml b/changelogs/unreleased/52756-pipeline_schedule_worker_cron.yml
new file mode 100644
index 00000000000..ddcecb52d99
--- /dev/null
+++ b/changelogs/unreleased/52756-pipeline_schedule_worker_cron.yml
@@ -0,0 +1,5 @@
+---
+title: Run pipeline_schedule_worker at every 10th minute from 3 through 59
+merge_request: 52756
+author: Ben Bodenmiller (@bbodenmiller)
+type: changed
diff --git a/changelogs/unreleased/5788-geo-automatic-recover-from-leader-change-in-primary-site-docs.yml b/changelogs/unreleased/5788-geo-automatic-recover-from-leader-change-in-primary-site-docs.yml
new file mode 100644
index 00000000000..45ae309b686
--- /dev/null
+++ b/changelogs/unreleased/5788-geo-automatic-recover-from-leader-change-in-primary-site-docs.yml
@@ -0,0 +1,6 @@
+---
+title: Geo - Update Patroni replication docs to automatic recover from a leader change
+ on the primary site
+merge_request: 53424
+author:
+type: other
diff --git a/changelogs/unreleased/64320-refactor-mr-services.yml b/changelogs/unreleased/64320-refactor-mr-services.yml
new file mode 100644
index 00000000000..18f59c36400
--- /dev/null
+++ b/changelogs/unreleased/64320-refactor-mr-services.yml
@@ -0,0 +1,5 @@
+---
+title: Code extraction - refactoring of MR services classes
+merge_request: 49827
+author:
+type: changed
diff --git a/changelogs/unreleased/84402-remove-avatar-from-comment-forms.yml b/changelogs/unreleased/84402-remove-avatar-from-comment-forms.yml
new file mode 100644
index 00000000000..5662f79a071
--- /dev/null
+++ b/changelogs/unreleased/84402-remove-avatar-from-comment-forms.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Avatar from Comment Forms
+merge_request: 52180
+author: Lee Tickett @leetickett
+type: other
diff --git a/changelogs/unreleased/ApplyGItLabUIstylesto_edit_form-html-haml.yml b/changelogs/unreleased/ApplyGItLabUIstylesto_edit_form-html-haml.yml
new file mode 100644
index 00000000000..1eeb8dfddb3
--- /dev/null
+++ b/changelogs/unreleased/ApplyGItLabUIstylesto_edit_form-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Adds GitLab UI styles to button in _edit_form.html.haml
+merge_request: 51156
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_hook-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_hook-html-haml.yml
new file mode 100644
index 00000000000..518fc1e18a4
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_hook-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Update buttons in _hook.html.haml to use GitLab UI
+merge_request: 51065
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_test_button-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_test_button-html-haml.yml
new file mode 100644
index 00000000000..9a140d2c1ee
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsin_test_button-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Adds GitLabUI button styles in _test_button.html.haml
+merge_request: 51070
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_table-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_table-html-haml.yml
new file mode 100644
index 00000000000..82e0ca5e42f
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIbuttonstylestobuttonsindeploytokens_table-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Adds GitLabUI button styles in deploy tokens _table.html.haml
+merge_request: 51082
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIstylesin_notifications_directory.yml b/changelogs/unreleased/ApplyGitLabUIstylesin_notifications_directory.yml
new file mode 100644
index 00000000000..f66ea40f48b
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIstylesin_notifications_directory.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI styles to buttons in notification directory _new_button.html.haml
+merge_request: 51148
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIstylesto_comment_button-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIstylesto_comment_button-html-haml.yml
new file mode 100644
index 00000000000..cc38b047d27
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIstylesto_comment_button-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI styles to buttons in _comment_button.html.haml
+merge_request: 51152
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ApplyGitLabUIstylestobuttonin_form-html-haml.yml b/changelogs/unreleased/ApplyGitLabUIstylestobuttonin_form-html-haml.yml
new file mode 100644
index 00000000000..4f86af7b884
--- /dev/null
+++ b/changelogs/unreleased/ApplyGitLabUIstylestobuttonin_form-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Adds GitLab UI styles to button in _form.html.haml
+merge_request: 51160
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Lint-DeprecatedOpenSSLConstant.yml b/changelogs/unreleased/Lint-DeprecatedOpenSSLConstant.yml
new file mode 100644
index 00000000000..45b0d7ebb99
--- /dev/null
+++ b/changelogs/unreleased/Lint-DeprecatedOpenSSLConstant.yml
@@ -0,0 +1,5 @@
+---
+title: Replace OpenSSL constants with strings
+merge_request: 52432
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/Replace-bootstrap-event-strings-with-constants.yml b/changelogs/unreleased/Replace-bootstrap-event-strings-with-constants.yml
new file mode 100644
index 00000000000..c0661ecd14a
--- /dev/null
+++ b/changelogs/unreleased/Replace-bootstrap-event-strings-with-constants.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap event strings with constants
+merge_request: 52777
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/Set-min-width-of-breadcrumb-dropdown-to-200px.yml b/changelogs/unreleased/Set-min-width-of-breadcrumb-dropdown-to-200px.yml
new file mode 100644
index 00000000000..ac3254afabd
--- /dev/null
+++ b/changelogs/unreleased/Set-min-width-of-breadcrumb-dropdown-to-200px.yml
@@ -0,0 +1,5 @@
+---
+title: Fix breadcrumb dropdown on mobile being too narrow
+merge_request: 51092
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/ab-ci-builds-metadata-index.yml b/changelogs/unreleased/ab-ci-builds-metadata-index.yml
new file mode 100644
index 00000000000..2124c9879b6
--- /dev/null
+++ b/changelogs/unreleased/ab-ci-builds-metadata-index.yml
@@ -0,0 +1,5 @@
+---
+title: Extend index on ci_builds_metadata
+merge_request: 52123
+author:
+type: performance
diff --git a/changelogs/unreleased/add-labels-resolver.yml b/changelogs/unreleased/add-labels-resolver.yml
new file mode 100644
index 00000000000..1594c35de19
--- /dev/null
+++ b/changelogs/unreleased/add-labels-resolver.yml
@@ -0,0 +1,6 @@
+---
+title: Adds only_group_labels and include_ancestor_labels and include_descendant_groups
+ arguments to the project and group labels resolvers respectively
+merge_request: 53639
+author:
+type: fixed
diff --git a/changelogs/unreleased/add-missing-known-event-ecs-deploy-template.yml b/changelogs/unreleased/add-missing-known-event-ecs-deploy-template.yml
new file mode 100644
index 00000000000..cbb5b48162f
--- /dev/null
+++ b/changelogs/unreleased/add-missing-known-event-ecs-deploy-template.yml
@@ -0,0 +1,5 @@
+---
+title: Fix missing known usage data event
+merge_request: 53729
+author:
+type: fixed
diff --git a/changelogs/unreleased/add-recaptcha-fields-to-snippet-mutations.yml b/changelogs/unreleased/add-recaptcha-fields-to-snippet-mutations.yml
new file mode 100644
index 00000000000..b7f96a00979
--- /dev/null
+++ b/changelogs/unreleased/add-recaptcha-fields-to-snippet-mutations.yml
@@ -0,0 +1,5 @@
+---
+title: Add captcha-related fields to snippet GraphQL mutations
+merge_request: 51956
+author:
+type: added
diff --git a/changelogs/unreleased/add-user-setting-for-opting-into-marketing-emails.yml b/changelogs/unreleased/add-user-setting-for-opting-into-marketing-emails.yml
new file mode 100644
index 00000000000..d169e43d047
--- /dev/null
+++ b/changelogs/unreleased/add-user-setting-for-opting-into-marketing-emails.yml
@@ -0,0 +1,5 @@
+---
+title: Add user setting for opting into marketing emails
+merge_request: 53921
+author:
+type: added
diff --git a/changelogs/unreleased/add-webp-to-file-type-detection.yml b/changelogs/unreleased/add-webp-to-file-type-detection.yml
new file mode 100644
index 00000000000..1738cb07ae7
--- /dev/null
+++ b/changelogs/unreleased/add-webp-to-file-type-detection.yml
@@ -0,0 +1,5 @@
+---
+title: Render WebP attachments as image by default
+merge_request: 51088
+author: Kev @KevSlashNull
+type: changed
diff --git a/changelogs/unreleased/ajk-294034-enable-jira-deployments.yml b/changelogs/unreleased/ajk-294034-enable-jira-deployments.yml
new file mode 100644
index 00000000000..5c0f7943a91
--- /dev/null
+++ b/changelogs/unreleased/ajk-294034-enable-jira-deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Send deployment information to Jira
+merge_request: 51629
+author:
+type: added
diff --git a/changelogs/unreleased/ajk-add-state-events-to-mr-update-mutation.yml b/changelogs/unreleased/ajk-add-state-events-to-mr-update-mutation.yml
new file mode 100644
index 00000000000..c8539b73688
--- /dev/null
+++ b/changelogs/unreleased/ajk-add-state-events-to-mr-update-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Add state events to merge request update mutation
+merge_request: 54133
+author:
+type: added
diff --git a/changelogs/unreleased/ajk-graphql-packages.yml b/changelogs/unreleased/ajk-graphql-packages.yml
new file mode 100644
index 00000000000..c24ffd2430f
--- /dev/null
+++ b/changelogs/unreleased/ajk-graphql-packages.yml
@@ -0,0 +1,5 @@
+---
+title: 'Breaking change: Prevent mutual recursion in GraphQL Package'
+merge_request: 52131
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-jira-connect-fix-ff-url.yml b/changelogs/unreleased/ajk-jira-connect-fix-ff-url.yml
new file mode 100644
index 00000000000..25e36d4c994
--- /dev/null
+++ b/changelogs/unreleased/ajk-jira-connect-fix-ff-url.yml
@@ -0,0 +1,5 @@
+---
+title: Fix URL in JiraConnect feature flag serializer
+merge_request: 52221
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-remove-adjacency-check.yml b/changelogs/unreleased/ajk-remove-adjacency-check.yml
new file mode 100644
index 00000000000..c1ffaa4b6df
--- /dev/null
+++ b/changelogs/unreleased/ajk-remove-adjacency-check.yml
@@ -0,0 +1,5 @@
+---
+title: Fix spurious not-adjacent error when moving designs
+merge_request: 53771
+author:
+type: fixed
diff --git a/changelogs/unreleased/align-graph-page.yml b/changelogs/unreleased/align-graph-page.yml
new file mode 100644
index 00000000000..31f00b526e3
--- /dev/null
+++ b/changelogs/unreleased/align-graph-page.yml
@@ -0,0 +1,5 @@
+---
+title: Add margin and remove padding in project graph page
+merge_request: 53557
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/alipniagov-disable-nakayoshi-by-default.yml b/changelogs/unreleased/alipniagov-disable-nakayoshi-by-default.yml
new file mode 100644
index 00000000000..e767f390839
--- /dev/null
+++ b/changelogs/unreleased/alipniagov-disable-nakayoshi-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Disable nakayoshi_fork by default in examples
+merge_request: 52209
+author:
+type: other
diff --git a/changelogs/unreleased/allow-environment-scopes-to-wrap-feature-flags.yml b/changelogs/unreleased/allow-environment-scopes-to-wrap-feature-flags.yml
new file mode 100644
index 00000000000..37f6617fe99
--- /dev/null
+++ b/changelogs/unreleased/allow-environment-scopes-to-wrap-feature-flags.yml
@@ -0,0 +1,5 @@
+---
+title: Allow Environment Scopes to Wrap on Feature Flags Table
+merge_request: 52617
+author:
+type: fixed
diff --git a/changelogs/unreleased/apply-gl-button-schedules.yml b/changelogs/unreleased/apply-gl-button-schedules.yml
new file mode 100644
index 00000000000..301f5a98b9b
--- /dev/null
+++ b/changelogs/unreleased/apply-gl-button-schedules.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in pipeline schedules
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/ar-color-name-changes.yml b/changelogs/unreleased/ar-color-name-changes.yml
new file mode 100644
index 00000000000..e10b9a0a6cd
--- /dev/null
+++ b/changelogs/unreleased/ar-color-name-changes.yml
@@ -0,0 +1,5 @@
+---
+title: Update the HEX values and names of the color options for labels
+merge_request: 50393
+author:
+type: changed
diff --git a/changelogs/unreleased/ar-fix-border-color.yml b/changelogs/unreleased/ar-fix-border-color.yml
new file mode 100644
index 00000000000..7558e2ecf79
--- /dev/null
+++ b/changelogs/unreleased/ar-fix-border-color.yml
@@ -0,0 +1,5 @@
+---
+title: Fix protected branches/tags border
+merge_request: 52816
+author:
+type: changed
diff --git a/changelogs/unreleased/ar-update-project-avatar-border-radius.yml b/changelogs/unreleased/ar-update-project-avatar-border-radius.yml
new file mode 100644
index 00000000000..1c7ea85ce85
--- /dev/null
+++ b/changelogs/unreleased/ar-update-project-avatar-border-radius.yml
@@ -0,0 +1,5 @@
+---
+title: Change the project avatar preview into a rectangle
+merge_request: 51511
+author: Austin Regnery
+type: changed
diff --git a/changelogs/unreleased/arty-fix-auditor-badge.yml b/changelogs/unreleased/arty-fix-auditor-badge.yml
new file mode 100644
index 00000000000..c4a244b5cae
--- /dev/null
+++ b/changelogs/unreleased/arty-fix-auditor-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Fix to show auditor badging in admin user view
+merge_request: 52943
+author:
+type: fixed
diff --git a/changelogs/unreleased/arty-spt-selfserve-del.yml b/changelogs/unreleased/arty-spt-selfserve-del.yml
new file mode 100644
index 00000000000..58cec2e8af0
--- /dev/null
+++ b/changelogs/unreleased/arty-spt-selfserve-del.yml
@@ -0,0 +1,5 @@
+---
+title: Add additional instructions on deleting account on Gitlab.com
+merge_request: 52538
+author:
+type: other
diff --git a/changelogs/unreleased/asciidoctor-2-0-12.yml b/changelogs/unreleased/asciidoctor-2-0-12.yml
new file mode 100644
index 00000000000..0ee92803fc5
--- /dev/null
+++ b/changelogs/unreleased/asciidoctor-2-0-12.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Asciidoctor to 2.0.12
+merge_request: 54121
+author: Guillaume Grossetie
+type: changed
diff --git a/changelogs/unreleased/auto-delete-at.yml b/changelogs/unreleased/auto-delete-at.yml
new file mode 100644
index 00000000000..e9823e99126
--- /dev/null
+++ b/changelogs/unreleased/auto-delete-at.yml
@@ -0,0 +1,5 @@
+---
+title: Add auto_delete_at to environments
+merge_request: 52788
+author:
+type: added
diff --git a/changelogs/unreleased/automatically-authenticate-with-the-dependency-proxy.yml b/changelogs/unreleased/automatically-authenticate-with-the-dependency-proxy.yml
new file mode 100644
index 00000000000..38dead31211
--- /dev/null
+++ b/changelogs/unreleased/automatically-authenticate-with-the-dependency-proxy.yml
@@ -0,0 +1,5 @@
+---
+title: Pass dependency proxy credentials to runners to log in automatically
+merge_request: 51927
+author:
+type: added
diff --git a/changelogs/unreleased/bjk-splay_puma_restarts.yml b/changelogs/unreleased/bjk-splay_puma_restarts.yml
new file mode 100644
index 00000000000..cd5490acb6f
--- /dev/null
+++ b/changelogs/unreleased/bjk-splay_puma_restarts.yml
@@ -0,0 +1,5 @@
+---
+title: Increase splay of Puma worker restarts
+merge_request: 52079
+author:
+type: other
diff --git a/changelogs/unreleased/btn-confirm-2fa.yml b/changelogs/unreleased/btn-confirm-2fa.yml
new file mode 100644
index 00000000000..521a74955cb
--- /dev/null
+++ b/changelogs/unreleased/btn-confirm-2fa.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in 2fa and changed deprecated info to confirm
+merge_request: 52580
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-default-cicd_for_external_repov.yml b/changelogs/unreleased/btn-default-cicd_for_external_repov.yml
new file mode 100644
index 00000000000..53ceb4aede1
--- /dev/null
+++ b/changelogs/unreleased/btn-default-cicd_for_external_repov.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in connect repo buttons in new project page
+merge_request: 53455
+author:
+type: other
diff --git a/changelogs/unreleased/btn-default-history.yml b/changelogs/unreleased/btn-default-history.yml
new file mode 100644
index 00000000000..055da67283a
--- /dev/null
+++ b/changelogs/unreleased/btn-default-history.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for history button in the contributors page
+merge_request: 52861
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-default-lock-unlock.yml b/changelogs/unreleased/btn-default-lock-unlock.yml
new file mode 100644
index 00000000000..786ad6a6bb3
--- /dev/null
+++ b/changelogs/unreleased/btn-default-lock-unlock.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for unlock button in locked files page
+merge_request: 52858
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-default-push-rules.yml b/changelogs/unreleased/btn-default-push-rules.yml
new file mode 100644
index 00000000000..a21df8cab11
--- /dev/null
+++ b/changelogs/unreleased/btn-default-push-rules.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default to settings toggle button in push rules
+merge_request: 52430
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-default-rss.yml b/changelogs/unreleased/btn-default-rss.yml
new file mode 100644
index 00000000000..8b9e86677be
--- /dev/null
+++ b/changelogs/unreleased/btn-default-rss.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for RSS button in commits page
+merge_request: 52900
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-icon-gpg.yml b/changelogs/unreleased/btn-icon-gpg.yml
new file mode 100644
index 00000000000..2ea6df5c995
--- /dev/null
+++ b/changelogs/unreleased/btn-icon-gpg.yml
@@ -0,0 +1,5 @@
+---
+title: Redesign SSH keys list
+merge_request: 53351
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/btn-icon-issues.yml b/changelogs/unreleased/btn-icon-issues.yml
new file mode 100644
index 00000000000..6a06d53f8f4
--- /dev/null
+++ b/changelogs/unreleased/btn-icon-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-icon class for icon only buttons in issues header
+merge_request: 53562
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/btn-icon-user-profile.yml b/changelogs/unreleased/btn-icon-user-profile.yml
new file mode 100644
index 00000000000..aee888b0c12
--- /dev/null
+++ b/changelogs/unreleased/btn-icon-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-icon class for action buttons in the user profile
+merge_request: 52901
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/changelog-api.yml b/changelogs/unreleased/changelog-api.yml
new file mode 100644
index 00000000000..c6ab3248996
--- /dev/null
+++ b/changelogs/unreleased/changelog-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add API for generating Markdown changelogs
+merge_request: 52116
+author:
+type: added
diff --git a/changelogs/unreleased/chat_notification_label_support.yml b/changelogs/unreleased/chat_notification_label_support.yml
new file mode 100644
index 00000000000..b6e7b3a89bd
--- /dev/null
+++ b/changelogs/unreleased/chat_notification_label_support.yml
@@ -0,0 +1,5 @@
+---
+title: Add chat notification label support
+merge_request: 52105
+author:
+type: added
diff --git a/changelogs/unreleased/ci-allow-deep-nesting-for-scripts.yml b/changelogs/unreleased/ci-allow-deep-nesting-for-scripts.yml
new file mode 100644
index 00000000000..643957d7338
--- /dev/null
+++ b/changelogs/unreleased/ci-allow-deep-nesting-for-scripts.yml
@@ -0,0 +1,5 @@
+---
+title: Accept deeply nested arrays for CI script keyword
+merge_request: 53737
+author:
+type: changed
diff --git a/changelogs/unreleased/cngo-add-landmarks-and-provide-names.yml b/changelogs/unreleased/cngo-add-landmarks-and-provide-names.yml
new file mode 100644
index 00000000000..7c734797ecd
--- /dev/null
+++ b/changelogs/unreleased/cngo-add-landmarks-and-provide-names.yml
@@ -0,0 +1,5 @@
+---
+title: Add site landmarks for screen readers
+merge_request: 52514
+author:
+type: added
diff --git a/changelogs/unreleased/cngo-migrate-feature-flag-toggles-to-gl-toggle.yml b/changelogs/unreleased/cngo-migrate-feature-flag-toggles-to-gl-toggle.yml
new file mode 100644
index 00000000000..c60aa1cdbef
--- /dev/null
+++ b/changelogs/unreleased/cngo-migrate-feature-flag-toggles-to-gl-toggle.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate feature flags page toggles to GlToggle
+merge_request: 52728
+author:
+type: changed
diff --git a/changelogs/unreleased/cngo-migrate-project-settings-to-use-gl-toggle.yml b/changelogs/unreleased/cngo-migrate-project-settings-to-use-gl-toggle.yml
new file mode 100644
index 00000000000..233f4e59667
--- /dev/null
+++ b/changelogs/unreleased/cngo-migrate-project-settings-to-use-gl-toggle.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate project settings to use GlToggle
+merge_request: 52729
+author:
+type: changed
diff --git a/changelogs/unreleased/cngo-migrate-subscription-toggle-to-gitlab-ui.yml b/changelogs/unreleased/cngo-migrate-subscription-toggle-to-gitlab-ui.yml
new file mode 100644
index 00000000000..1bc12d43d8b
--- /dev/null
+++ b/changelogs/unreleased/cngo-migrate-subscription-toggle-to-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate toggle button in subscription to GitLab UI component
+merge_request: 52717
+author:
+type: changed
diff --git a/changelogs/unreleased/compliance_pipeline_configuration.yml b/changelogs/unreleased/compliance_pipeline_configuration.yml
new file mode 100644
index 00000000000..cd2a9649f7b
--- /dev/null
+++ b/changelogs/unreleased/compliance_pipeline_configuration.yml
@@ -0,0 +1,5 @@
+---
+title: Database migration for compliance pipeline configuration location
+merge_request: 51663
+author:
+type: added
diff --git a/changelogs/unreleased/consistent-question-mark-mr.yml b/changelogs/unreleased/consistent-question-mark-mr.yml
new file mode 100644
index 00000000000..ba8f1ea2c29
--- /dev/null
+++ b/changelogs/unreleased/consistent-question-mark-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Update question mark icon while checking pipeline status
+merge_request: 52760
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/consistent-tooltip-user-profile.yml b/changelogs/unreleased/consistent-tooltip-user-profile.yml
new file mode 100644
index 00000000000..4136b900130
--- /dev/null
+++ b/changelogs/unreleased/consistent-tooltip-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Show bottom tooltip for edit button in user profile
+merge_request: 53459
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/count-implicit-auto-devops-inclusions-separately.yml b/changelogs/unreleased/count-implicit-auto-devops-inclusions-separately.yml
new file mode 100644
index 00000000000..cbf81e90e8e
--- /dev/null
+++ b/changelogs/unreleased/count-implicit-auto-devops-inclusions-separately.yml
@@ -0,0 +1,5 @@
+---
+title: Track YAML-less Auto DevOps inclusions separately
+merge_request: 53383
+author:
+type: changed
diff --git a/changelogs/unreleased/custom-emoji-banzai-filter.yml b/changelogs/unreleased/custom-emoji-banzai-filter.yml
new file mode 100644
index 00000000000..3623d50bce4
--- /dev/null
+++ b/changelogs/unreleased/custom-emoji-banzai-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Add Banzai filter for CustomEmoji
+merge_request: 47122
+author: Rajendra Kadam
+type: added
diff --git a/changelogs/unreleased/darneas-296853.yml b/changelogs/unreleased/darneas-296853.yml
new file mode 100644
index 00000000000..dce902365dc
--- /dev/null
+++ b/changelogs/unreleased/darneas-296853.yml
@@ -0,0 +1,5 @@
+---
+title: Show correct ref name in code coverage statistics header
+merge_request: 51385
+author: Andreas Schmidt
+type: fixed
diff --git a/changelogs/unreleased/dblessing_fix_ssh_key_regression.yml b/changelogs/unreleased/dblessing_fix_ssh_key_regression.yml
new file mode 100644
index 00000000000..2fd6444cfb5
--- /dev/null
+++ b/changelogs/unreleased/dblessing_fix_ssh_key_regression.yml
@@ -0,0 +1,5 @@
+---
+title: Allow user SSH public key endpoint to be publicly accessible again
+merge_request: 52227
+author:
+type: fixed
diff --git a/changelogs/unreleased/debian_component_files.yml b/changelogs/unreleased/debian_component_files.yml
new file mode 100644
index 00000000000..8be864479e5
--- /dev/null
+++ b/changelogs/unreleased/debian_component_files.yml
@@ -0,0 +1,5 @@
+---
+title: Debian Group and Project Distribution Component Files
+merge_request: 52885
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/debian_distribution_components.yml b/changelogs/unreleased/debian_distribution_components.yml
new file mode 100644
index 00000000000..1f5cf6b50e2
--- /dev/null
+++ b/changelogs/unreleased/debian_distribution_components.yml
@@ -0,0 +1,5 @@
+---
+title: Debian Group and Project Distribution Components
+merge_request: 51732
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/debian_publications.yml b/changelogs/unreleased/debian_publications.yml
new file mode 100644
index 00000000000..d9310539e62
--- /dev/null
+++ b/changelogs/unreleased/debian_publications.yml
@@ -0,0 +1,5 @@
+---
+title: Debian Publications
+merge_request: 52916
+author: Mathieu Parent
+type: added
diff --git a/changelogs/unreleased/deprecate_gma_apps.yml b/changelogs/unreleased/deprecate_gma_apps.yml
new file mode 100644
index 00000000000..4443ebd896b
--- /dev/null
+++ b/changelogs/unreleased/deprecate_gma_apps.yml
@@ -0,0 +1,5 @@
+---
+title: Deprecate GitLab-managed (v1) apps that will be removed in 14.0
+merge_request: 54162
+author:
+type: deprecated
diff --git a/changelogs/unreleased/devops-adoption-pivot.yml b/changelogs/unreleased/devops-adoption-pivot.yml
new file mode 100644
index 00000000000..f5d5d71569c
--- /dev/null
+++ b/changelogs/unreleased/devops-adoption-pivot.yml
@@ -0,0 +1,5 @@
+---
+title: Change DevopsAdoption feature to work with single group only
+merge_request: 52871
+author:
+type: changed
diff --git a/changelogs/unreleased/diff-view-speed.yml b/changelogs/unreleased/diff-view-speed.yml
new file mode 100644
index 00000000000..8ac020bc468
--- /dev/null
+++ b/changelogs/unreleased/diff-view-speed.yml
@@ -0,0 +1,5 @@
+---
+title: Lower allocations in _collapsed partial
+merge_request: 53233
+author:
+type: performance
diff --git a/changelogs/unreleased/docs-ci-starter.yml b/changelogs/unreleased/docs-ci-starter.yml
new file mode 100644
index 00000000000..e1b119932bf
--- /dev/null
+++ b/changelogs/unreleased/docs-ci-starter.yml
@@ -0,0 +1,5 @@
+---
+title: Allow new docs badges in UI links
+merge_request: 52651
+author:
+type: other
diff --git a/changelogs/unreleased/docs-redirects-removal-6.yml b/changelogs/unreleased/docs-redirects-removal-6.yml
new file mode 100644
index 00000000000..f03d5df1442
--- /dev/null
+++ b/changelogs/unreleased/docs-redirects-removal-6.yml
@@ -0,0 +1,5 @@
+---
+title: Update links to redirected docs
+merge_request: 53004
+author:
+type: other
diff --git a/changelogs/unreleased/docs-ui-text-settings-deploy-freezes.yml b/changelogs/unreleased/docs-ui-text-settings-deploy-freezes.yml
new file mode 100644
index 00000000000..ea1ba3649f9
--- /dev/null
+++ b/changelogs/unreleased/docs-ui-text-settings-deploy-freezes.yml
@@ -0,0 +1,5 @@
+---
+title: Review UI text - deploy freezes
+merge_request: 52884
+author:
+type: other
diff --git a/changelogs/unreleased/docs-ui-text-settings-deploy-keys.yml b/changelogs/unreleased/docs-ui-text-settings-deploy-keys.yml
new file mode 100644
index 00000000000..92ddbee8f2f
--- /dev/null
+++ b/changelogs/unreleased/docs-ui-text-settings-deploy-keys.yml
@@ -0,0 +1,5 @@
+---
+title: Review UI text - deploy keys settings
+merge_request: 52830
+author:
+type: other
diff --git a/changelogs/unreleased/download-patch-diff-new-tab.yml b/changelogs/unreleased/download-patch-diff-new-tab.yml
new file mode 100644
index 00000000000..1aca6adf69d
--- /dev/null
+++ b/changelogs/unreleased/download-patch-diff-new-tab.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug, where the download email patches and plain diffs links did not download from the commit page
+merge_request: 52899
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/eb-code-quality-version-0-85-22.yml b/changelogs/unreleased/eb-code-quality-version-0-85-22.yml
new file mode 100644
index 00000000000..cfd67cf2f09
--- /dev/null
+++ b/changelogs/unreleased/eb-code-quality-version-0-85-22.yml
@@ -0,0 +1,5 @@
+---
+title: Update code quality template to use 0.85.22
+merge_request: 52913
+author:
+type: changed
diff --git a/changelogs/unreleased/eb-prometheus-monitoring-report-parsers.yml b/changelogs/unreleased/eb-prometheus-monitoring-report-parsers.yml
new file mode 100644
index 00000000000..7cdbe4a3b0d
--- /dev/null
+++ b/changelogs/unreleased/eb-prometheus-monitoring-report-parsers.yml
@@ -0,0 +1,5 @@
+---
+title: Instrument CI parsers
+merge_request: 51241
+author:
+type: added
diff --git a/changelogs/unreleased/eb-remove-smart-cobertura-parser-flag.yml b/changelogs/unreleased/eb-remove-smart-cobertura-parser-flag.yml
new file mode 100644
index 00000000000..946d1a1ddd6
--- /dev/null
+++ b/changelogs/unreleased/eb-remove-smart-cobertura-parser-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Introduce automatic class path correction in Cobertura parser
+merge_request: 53236
+author:
+type: changed
diff --git a/changelogs/unreleased/ek-display-full-design-name-in-tooltip.yml b/changelogs/unreleased/ek-display-full-design-name-in-tooltip.yml
new file mode 100644
index 00000000000..16fcd67aebb
--- /dev/null
+++ b/changelogs/unreleased/ek-display-full-design-name-in-tooltip.yml
@@ -0,0 +1,5 @@
+---
+title: Display full design name in tooltip
+merge_request: 51421
+author:
+type: changed
diff --git a/changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml b/changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml
new file mode 100644
index 00000000000..c6b2df789e7
--- /dev/null
+++ b/changelogs/unreleased/eliminate-tz-sensitivity-ci-analytics-charts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix empty pipeline analytics charts when time_zone is non-UTC
+merge_request: 52971
+author:
+type: fixed
diff --git a/changelogs/unreleased/enable-query_deployments_via_finished_at_in_vsa-ff.yml b/changelogs/unreleased/enable-query_deployments_via_finished_at_in_vsa-ff.yml
new file mode 100644
index 00000000000..33d507995d6
--- /dev/null
+++ b/changelogs/unreleased/enable-query_deployments_via_finished_at_in_vsa-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Filter deployments by finished_at in Value Stream Analytics
+merge_request: 53861
+author:
+type: changed
diff --git a/changelogs/unreleased/enable_specialized_project_create_ff.yml b/changelogs/unreleased/enable_specialized_project_create_ff.yml
new file mode 100644
index 00000000000..edc9027e021
--- /dev/null
+++ b/changelogs/unreleased/enable_specialized_project_create_ff.yml
@@ -0,0 +1,5 @@
+---
+title: Project creation to use specialized worker to calculate project authorizations
+merge_request: 52719
+author:
+type: performance
diff --git a/changelogs/unreleased/eread-add-URL-help-text.yml b/changelogs/unreleased/eread-add-URL-help-text.yml
new file mode 100644
index 00000000000..935d34a63af
--- /dev/null
+++ b/changelogs/unreleased/eread-add-URL-help-text.yml
@@ -0,0 +1,5 @@
+---
+title: Add URL help text and edit other UI text
+merge_request: 53578
+author:
+type: other
diff --git a/changelogs/unreleased/feat-bypass-admin-mode-on-git.yml b/changelogs/unreleased/feat-bypass-admin-mode-on-git.yml
new file mode 100644
index 00000000000..d2b23d322ce
--- /dev/null
+++ b/changelogs/unreleased/feat-bypass-admin-mode-on-git.yml
@@ -0,0 +1,5 @@
+---
+title: Bypass admin mode for internal api operations (ssh git & http rails)
+merge_request: 52697
+author: Diego Louzán
+type: changed
diff --git a/changelogs/unreleased/feat-follow-eachother.yml b/changelogs/unreleased/feat-follow-eachother.yml
new file mode 100644
index 00000000000..ba80e35535e
--- /dev/null
+++ b/changelogs/unreleased/feat-follow-eachother.yml
@@ -0,0 +1,5 @@
+---
+title: Add follow each other model, API and UI(profile, activity view)
+merge_request: 45451
+author: Roger Meier
+type: added
diff --git a/changelogs/unreleased/feat-release-tooltip-for-guest-users.yml b/changelogs/unreleased/feat-release-tooltip-for-guest-users.yml
new file mode 100644
index 00000000000..22cef8bd01f
--- /dev/null
+++ b/changelogs/unreleased/feat-release-tooltip-for-guest-users.yml
@@ -0,0 +1,5 @@
+---
+title: Add release tooltip for guest users
+merge_request: 53722
+author: Jonas Wälter @wwwjon
+type: changed
diff --git a/changelogs/unreleased/feature-file-review-docs.yml b/changelogs/unreleased/feature-file-review-docs.yml
new file mode 100644
index 00000000000..98e9d707b7a
--- /dev/null
+++ b/changelogs/unreleased/feature-file-review-docs.yml
@@ -0,0 +1,6 @@
+---
+title: Enable local file reviews (marking files as viewed) by default and add documentation
+ for that feature
+merge_request: 48976
+author:
+type: added
diff --git a/changelogs/unreleased/feature-file-review.yml b/changelogs/unreleased/feature-file-review.yml
new file mode 100644
index 00000000000..2b41cc0d5ac
--- /dev/null
+++ b/changelogs/unreleased/feature-file-review.yml
@@ -0,0 +1,5 @@
+---
+title: Mark files as reviewed locally
+merge_request: 51513
+author:
+type: added
diff --git a/changelogs/unreleased/feature-flag-contextual-issue-links.yml b/changelogs/unreleased/feature-flag-contextual-issue-links.yml
new file mode 100644
index 00000000000..486b72446a5
--- /dev/null
+++ b/changelogs/unreleased/feature-flag-contextual-issue-links.yml
@@ -0,0 +1,5 @@
+---
+title: Add GFM reference format for feature flags
+merge_request: 53021
+author:
+type: added
diff --git a/changelogs/unreleased/feature-flag-enable-ci-config-merged-tab.yml b/changelogs/unreleased/feature-flag-enable-ci-config-merged-tab.yml
new file mode 100644
index 00000000000..3febd18659a
--- /dev/null
+++ b/changelogs/unreleased/feature-flag-enable-ci-config-merged-tab.yml
@@ -0,0 +1,5 @@
+---
+title: Add merged Yaml tab feature to Pipeline Editor
+merge_request: 54223
+author:
+type: added
diff --git a/changelogs/unreleased/fix-avatar-alignment-edit-board.yml b/changelogs/unreleased/fix-avatar-alignment-edit-board.yml
new file mode 100644
index 00000000000..4d42a1fd36c
--- /dev/null
+++ b/changelogs/unreleased/fix-avatar-alignment-edit-board.yml
@@ -0,0 +1,5 @@
+---
+title: Fix assignee avatar alignment in edit board modal
+merge_request: 52453
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/fix-back-button-ci-cd-analytics.yml b/changelogs/unreleased/fix-back-button-ci-cd-analytics.yml
new file mode 100644
index 00000000000..2a4c6ebd142
--- /dev/null
+++ b/changelogs/unreleased/fix-back-button-ci-cd-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Back Button now switches to last active analytics tab
+merge_request: 53495
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-button-alignment-applications.yml b/changelogs/unreleased/fix-button-alignment-applications.yml
new file mode 100644
index 00000000000..25515be0e1b
--- /dev/null
+++ b/changelogs/unreleased/fix-button-alignment-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Fix action button alignment for application inside the table in oauth/applications
+merge_request: 52465
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/fix-ci-variable-popover-copy-button.yml b/changelogs/unreleased/fix-ci-variable-popover-copy-button.yml
new file mode 100644
index 00000000000..fb7331f8862
--- /dev/null
+++ b/changelogs/unreleased/fix-ci-variable-popover-copy-button.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent long variable names from overflowing the popover in CI/CD settings
+merge_request: 51018
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/fix-crypto-helper-issue.yml b/changelogs/unreleased/fix-crypto-helper-issue.yml
new file mode 100644
index 00000000000..18d3f914436
--- /dev/null
+++ b/changelogs/unreleased/fix-crypto-helper-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Add token_with_iv table
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/fix-email-icon.yml b/changelogs/unreleased/fix-email-icon.yml
new file mode 100644
index 00000000000..ef9f62da263
--- /dev/null
+++ b/changelogs/unreleased/fix-email-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Remove space next to the icon in email button on admin/users page
+merge_request: 52451
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/fix-merge-trains-cannot-be-retried.yml b/changelogs/unreleased/fix-merge-trains-cannot-be-retried.yml
new file mode 100644
index 00000000000..319026a1ad6
--- /dev/null
+++ b/changelogs/unreleased/fix-merge-trains-cannot-be-retried.yml
@@ -0,0 +1,5 @@
+---
+title: Fix retry option does not work in Merge Trains
+merge_request: 52463
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-opensearch.yml b/changelogs/unreleased/fix-opensearch.yml
new file mode 100644
index 00000000000..2ded63e6fdd
--- /dev/null
+++ b/changelogs/unreleased/fix-opensearch.yml
@@ -0,0 +1,5 @@
+---
+title: Fix opensearch for anonymous users
+merge_request: 53056
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-overflowing-design-buttons.yml b/changelogs/unreleased/fix-overflowing-design-buttons.yml
new file mode 100644
index 00000000000..7e01779f438
--- /dev/null
+++ b/changelogs/unreleased/fix-overflowing-design-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Fix overflowing design buttons on mobile
+merge_request: 54381
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-pipeline-and-stage-status.yml b/changelogs/unreleased/fix-pipeline-and-stage-status.yml
new file mode 100644
index 00000000000..6a3f4e7e31d
--- /dev/null
+++ b/changelogs/unreleased/fix-pipeline-and-stage-status.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline and stage show success without considering bridge status
+merge_request: 52192
+author: Cong Chen @gentcys
+type: fixed
diff --git a/changelogs/unreleased/fix-social-connect-icons-margin.yml b/changelogs/unreleased/fix-social-connect-icons-margin.yml
new file mode 100644
index 00000000000..c6429b5f389
--- /dev/null
+++ b/changelogs/unreleased/fix-social-connect-icons-margin.yml
@@ -0,0 +1,5 @@
+---
+title: Fix margins in social connect button on account settings
+merge_request: 52581
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/fix-spacing-labels.yml b/changelogs/unreleased/fix-spacing-labels.yml
new file mode 100644
index 00000000000..9afd9e3bd25
--- /dev/null
+++ b/changelogs/unreleased/fix-spacing-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Fix spacing before toggle subscribe button on labels
+merge_request: 52459
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/fix-svg-flex.yml b/changelogs/unreleased/fix-svg-flex.yml
new file mode 100644
index 00000000000..1fd64903d07
--- /dev/null
+++ b/changelogs/unreleased/fix-svg-flex.yml
@@ -0,0 +1,5 @@
+---
+title: Fix comment form dropdown check alignment
+merge_request: 51787
+author: Lee Tickett @leetickett
+type: fixed
diff --git a/changelogs/unreleased/fix-table-header-space.yml b/changelogs/unreleased/fix-table-header-space.yml
new file mode 100644
index 00000000000..8fd2b3a8063
--- /dev/null
+++ b/changelogs/unreleased/fix-table-header-space.yml
@@ -0,0 +1,5 @@
+---
+title: Fix gap in tree table header
+merge_request: 54025
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-unneeded-left-margin-discussion-filter-container.yml b/changelogs/unreleased/fix-unneeded-left-margin-discussion-filter-container.yml
new file mode 100644
index 00000000000..4ee35e81eba
--- /dev/null
+++ b/changelogs/unreleased/fix-unneeded-left-margin-discussion-filter-container.yml
@@ -0,0 +1,5 @@
+---
+title: Fix unneeded left margin in discussion filter container on mobile
+merge_request: 54379
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-backfill-project-updated_at-after-repository-move.yml b/changelogs/unreleased/fj-backfill-project-updated_at-after-repository-move.yml
new file mode 100644
index 00000000000..d1295687cd9
--- /dev/null
+++ b/changelogs/unreleased/fj-backfill-project-updated_at-after-repository-move.yml
@@ -0,0 +1,5 @@
+---
+title: Add post migration to backfill projects updated at after repository move
+merge_request: 53845
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-create-group-repository-storage-move-table.yml b/changelogs/unreleased/fj-create-group-repository-storage-move-table.yml
new file mode 100644
index 00000000000..bd0b61cf944
--- /dev/null
+++ b/changelogs/unreleased/fj-create-group-repository-storage-move-table.yml
@@ -0,0 +1,5 @@
+---
+title: Create Groups::RepositoryStorageMove table
+merge_request: 51803
+author:
+type: added
diff --git a/changelogs/unreleased/fj-fix-api-when-snippet-does-not-exist.yml b/changelogs/unreleased/fj-fix-api-when-snippet-does-not-exist.yml
new file mode 100644
index 00000000000..c3d22285cd2
--- /dev/null
+++ b/changelogs/unreleased/fj-fix-api-when-snippet-does-not-exist.yml
@@ -0,0 +1,5 @@
+---
+title: Fix snippet repository storage move API when snippet does not exist
+merge_request: 53211
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-fix-bug-rendering-snippet-activity.yml b/changelogs/unreleased/fj-fix-bug-rendering-snippet-activity.yml
new file mode 100644
index 00000000000..53e7633953d
--- /dev/null
+++ b/changelogs/unreleased/fj-fix-bug-rendering-snippet-activity.yml
@@ -0,0 +1,5 @@
+---
+title: Fix bug rendering snippet activity
+merge_request: 53993
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-update-update-at-column-after-repository-storage-move.yml b/changelogs/unreleased/fj-update-update-at-column-after-repository-storage-move.yml
new file mode 100644
index 00000000000..d43f621f6d6
--- /dev/null
+++ b/changelogs/unreleased/fj-update-update-at-column-after-repository-storage-move.yml
@@ -0,0 +1,5 @@
+---
+title: Update column 'updated_at' in container after repository storage move
+merge_request: 53821
+author:
+type: fixed
diff --git a/changelogs/unreleased/georgekoltsov-group-migration-epic-award-emoji.yml b/changelogs/unreleased/georgekoltsov-group-migration-epic-award-emoji.yml
new file mode 100644
index 00000000000..e4c4a3026fe
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-group-migration-epic-award-emoji.yml
@@ -0,0 +1,5 @@
+---
+title: Import epic award emojis when using Bulk Import
+merge_request: 53747
+author:
+type: added
diff --git a/changelogs/unreleased/georgekoltsov-track-bulk-import-exceptions.yml b/changelogs/unreleased/georgekoltsov-track-bulk-import-exceptions.yml
new file mode 100644
index 00000000000..cb5ba15fc7d
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-track-bulk-import-exceptions.yml
@@ -0,0 +1,5 @@
+---
+title: Track exceptions when using Bulk Import
+merge_request: 52011
+author:
+type: changed
diff --git a/changelogs/unreleased/georgekoltsov-update-project-export-temp-folder-cleanup.yml b/changelogs/unreleased/georgekoltsov-update-project-export-temp-folder-cleanup.yml
new file mode 100644
index 00000000000..71cab10b58d
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-update-project-export-temp-folder-cleanup.yml
@@ -0,0 +1,5 @@
+---
+title: Update Project/Group Exporter temp folder cleanup
+merge_request: 51969
+author:
+type: fixed
diff --git a/changelogs/unreleased/gfm-emoji-refactor.yml b/changelogs/unreleased/gfm-emoji-refactor.yml
new file mode 100644
index 00000000000..4825b3f29fe
--- /dev/null
+++ b/changelogs/unreleased/gfm-emoji-refactor.yml
@@ -0,0 +1,5 @@
+---
+title: Remove fuzzy search for awards emoji and refactor GFM autocomplete emoji support
+merge_request: 51972
+author: Ethan Reesor (@firelizzard)
+type: other
diff --git a/changelogs/unreleased/gitaly-trailer-parsing.yml b/changelogs/unreleased/gitaly-trailer-parsing.yml
new file mode 100644
index 00000000000..096ef4a94a7
--- /dev/null
+++ b/changelogs/unreleased/gitaly-trailer-parsing.yml
@@ -0,0 +1,5 @@
+---
+title: Add finder for getting commits with a trailer set
+merge_request: 49243
+author:
+type: added
diff --git a/changelogs/unreleased/gl-badge-branch-list.yml b/changelogs/unreleased/gl-badge-branch-list.yml
new file mode 100644
index 00000000000..0b5f89c6eda
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-branch-list.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for badges in the project branch list
+merge_request: 52868
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-badge-job.yml b/changelogs/unreleased/gl-badge-job.yml
new file mode 100644
index 00000000000..f92981ae6d9
--- /dev/null
+++ b/changelogs/unreleased/gl-badge-job.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for badge in job page sidebar
+merge_request: 53386
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-ci-cd.yml b/changelogs/unreleased/gl-button-ci-cd.yml
new file mode 100644
index 00000000000..90223c403da
--- /dev/null
+++ b/changelogs/unreleased/gl-button-ci-cd.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for toggle buttons in CI/CD settings page
+merge_request: 53556
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-commit-page.yml b/changelogs/unreleased/gl-button-commit-page.yml
new file mode 100644
index 00000000000..f3461f52d4b
--- /dev/null
+++ b/changelogs/unreleased/gl-button-commit-page.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in commit page
+merge_request: 53555
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-create-mr.yml b/changelogs/unreleased/gl-button-create-mr.yml
new file mode 100644
index 00000000000..850385f4c45
--- /dev/null
+++ b/changelogs/unreleased/gl-button-create-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for create mr button from issue
+merge_request: 53467
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-done.yml b/changelogs/unreleased/gl-button-done.yml
new file mode 100644
index 00000000000..fa7a6227e89
--- /dev/null
+++ b/changelogs/unreleased/gl-button-done.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default to buttons in todos page
+merge_request:
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-download.yml b/changelogs/unreleased/gl-button-download.yml
new file mode 100644
index 00000000000..6489f558116
--- /dev/null
+++ b/changelogs/unreleased/gl-button-download.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for the download button in graphs page
+merge_request: 52857
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-empty-issue-placeholder.yml b/changelogs/unreleased/gl-button-empty-issue-placeholder.yml
new file mode 100644
index 00000000000..a40c63fe36e
--- /dev/null
+++ b/changelogs/unreleased/gl-button-empty-issue-placeholder.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in empty issue placeholder
+merge_request: 53554
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-file.yml b/changelogs/unreleased/gl-button-file.yml
new file mode 100644
index 00000000000..c6f7613471e
--- /dev/null
+++ b/changelogs/unreleased/gl-button-file.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in blob header
+merge_request: 52429
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-fix-tag.yml b/changelogs/unreleased/gl-button-fix-tag.yml
new file mode 100644
index 00000000000..a21519d02c7
--- /dev/null
+++ b/changelogs/unreleased/gl-button-fix-tag.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default to buttons in tag action on the single tag page
+merge_request: 52866
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-issues.yml b/changelogs/unreleased/gl-button-issues.yml
new file mode 100644
index 00000000000..ae00abd29e3
--- /dev/null
+++ b/changelogs/unreleased/gl-button-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI style for todo button in the issuable sidebar
+merge_request: 52779
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-job.yml b/changelogs/unreleased/gl-button-job.yml
new file mode 100644
index 00000000000..a9b6b679448
--- /dev/null
+++ b/changelogs/unreleased/gl-button-job.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in pipeline page
+merge_request: 53364
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-new-group.yml b/changelogs/unreleased/gl-button-new-group.yml
new file mode 100644
index 00000000000..9eb6c7f6520
--- /dev/null
+++ b/changelogs/unreleased/gl-button-new-group.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in new group page
+merge_request: 53456
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-new-project.yml b/changelogs/unreleased/gl-button-new-project.yml
new file mode 100644
index 00000000000..3903f462ff0
--- /dev/null
+++ b/changelogs/unreleased/gl-button-new-project.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in create project page
+merge_request: 53454
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-no-repo-actions.yml b/changelogs/unreleased/gl-button-no-repo-actions.yml
new file mode 100644
index 00000000000..256cafd546f
--- /dev/null
+++ b/changelogs/unreleased/gl-button-no-repo-actions.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for no repo action buttons
+merge_request: 53580
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-resolve-conflict.yml b/changelogs/unreleased/gl-button-resolve-conflict.yml
new file mode 100644
index 00000000000..83886355e22
--- /dev/null
+++ b/changelogs/unreleased/gl-button-resolve-conflict.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in MR resolve conflicts page
+merge_request: 52783
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-single-tag.yml b/changelogs/unreleased/gl-button-single-tag.yml
new file mode 100644
index 00000000000..02a38ead89e
--- /dev/null
+++ b/changelogs/unreleased/gl-button-single-tag.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in the tag edit page
+merge_request: 52863
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-snippets.yml b/changelogs/unreleased/gl-button-snippets.yml
new file mode 100644
index 00000000000..a50a9879474
--- /dev/null
+++ b/changelogs/unreleased/gl-button-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in empty project snippets placeholder
+merge_request: 53157
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-social.yml b/changelogs/unreleased/gl-button-social.yml
new file mode 100644
index 00000000000..59fc817debb
--- /dev/null
+++ b/changelogs/unreleased/gl-button-social.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for social buttons in login and signup page
+merge_request: 53347
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-tags.yml b/changelogs/unreleased/gl-button-tags.yml
new file mode 100644
index 00000000000..5415c3a6502
--- /dev/null
+++ b/changelogs/unreleased/gl-button-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in tags page
+merge_request: 52862
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-button-utf-try-again.yml b/changelogs/unreleased/gl-button-utf-try-again.yml
new file mode 100644
index 00000000000..f6d93f2d49d
--- /dev/null
+++ b/changelogs/unreleased/gl-button-utf-try-again.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI class for U2F try again button
+merge_request: 52759
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-card-advanced-search.yml b/changelogs/unreleased/gl-card-advanced-search.yml
new file mode 100644
index 00000000000..79dc47cd062
--- /dev/null
+++ b/changelogs/unreleased/gl-card-advanced-search.yml
@@ -0,0 +1,5 @@
+---
+title: Move the sub-section to gl-card in advanced search settings in admin
+merge_request: 52585
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/gl-form-input-user-applications.yml b/changelogs/unreleased/gl-form-input-user-applications.yml
new file mode 100644
index 00000000000..f8c976b6376
--- /dev/null
+++ b/changelogs/unreleased/gl-form-input-user-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in user applications
+merge_request: 52425
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-form-input-user-email.yml b/changelogs/unreleased/gl-form-input-user-email.yml
new file mode 100644
index 00000000000..4bc1552100a
--- /dev/null
+++ b/changelogs/unreleased/gl-form-input-user-email.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in user email settings
+merge_request: 52427
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-form-input-user-pat.yml b/changelogs/unreleased/gl-form-input-user-pat.yml
new file mode 100644
index 00000000000..569141cc554
--- /dev/null
+++ b/changelogs/unreleased/gl-form-input-user-pat.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in user personal access token settings
+merge_request: 52426
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-form-input-user-profile.yml b/changelogs/unreleased/gl-form-input-user-profile.yml
new file mode 100644
index 00000000000..e8663751377
--- /dev/null
+++ b/changelogs/unreleased/gl-form-input-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in user profile settings
+merge_request: 52424
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-new-trials.yml b/changelogs/unreleased/gl-new-trials.yml
new file mode 100644
index 00000000000..695bf2b083c
--- /dev/null
+++ b/changelogs/unreleased/gl-new-trials.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for new trial page
+merge_request: 53447
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gl-ui-graph-page.yml b/changelogs/unreleased/gl-ui-graph-page.yml
new file mode 100644
index 00000000000..b98c6053f99
--- /dev/null
+++ b/changelogs/unreleased/gl-ui-graph-page.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons and input in the project graph page
+merge_request: 52864
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/gy-artifact-download-multiple-types.yml b/changelogs/unreleased/gy-artifact-download-multiple-types.yml
new file mode 100644
index 00000000000..15f9fa78372
--- /dev/null
+++ b/changelogs/unreleased/gy-artifact-download-multiple-types.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust job report artifacts downloads to handle multiple types
+merge_request: 53141
+author:
+type: fixed
diff --git a/changelogs/unreleased/gy-clarify-sample-data.yml b/changelogs/unreleased/gy-clarify-sample-data.yml
new file mode 100644
index 00000000000..91380325a5c
--- /dev/null
+++ b/changelogs/unreleased/gy-clarify-sample-data.yml
@@ -0,0 +1,5 @@
+---
+title: Update Sample GitLab Project Template to be clearer and adjust prominent placement
+merge_request: 53750
+author:
+type: changed
diff --git a/changelogs/unreleased/gy-fix-sample-template.yml b/changelogs/unreleased/gy-fix-sample-template.yml
new file mode 100644
index 00000000000..d19fa0e64f6
--- /dev/null
+++ b/changelogs/unreleased/gy-fix-sample-template.yml
@@ -0,0 +1,5 @@
+---
+title: Update Sample GitLab Project Template with MR conflicts fix
+merge_request: 54248
+author:
+type: fixed
diff --git a/changelogs/unreleased/id-bump-bullet.yml b/changelogs/unreleased/id-bump-bullet.yml
new file mode 100644
index 00000000000..2c6ce6e49aa
--- /dev/null
+++ b/changelogs/unreleased/id-bump-bullet.yml
@@ -0,0 +1,5 @@
+---
+title: Update bullet gem version to 6.1.3
+merge_request: 53217
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-doorkeeper-to-5-4-0.yml b/changelogs/unreleased/id-bump-doorkeeper-to-5-4-0.yml
new file mode 100644
index 00000000000..46790583400
--- /dev/null
+++ b/changelogs/unreleased/id-bump-doorkeeper-to-5-4-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump doorkeeper to 5.4.0
+merge_request: 51559
+author:
+type: other
diff --git a/changelogs/unreleased/id-bump-grape.yml b/changelogs/unreleased/id-bump-grape.yml
new file mode 100644
index 00000000000..b3225a04bfe
--- /dev/null
+++ b/changelogs/unreleased/id-bump-grape.yml
@@ -0,0 +1,5 @@
+---
+title: Update grape gem to 1.5.2
+merge_request: 53547
+author:
+type: other
diff --git a/changelogs/unreleased/id-fix-no-route-error.yml b/changelogs/unreleased/id-fix-no-route-error.yml
new file mode 100644
index 00000000000..85061ed731e
--- /dev/null
+++ b/changelogs/unreleased/id-fix-no-route-error.yml
@@ -0,0 +1,5 @@
+---
+title: Fix viewing blobs for broken MRs
+merge_request: 52483
+author:
+type: fixed
diff --git a/changelogs/unreleased/id-optimize-branches-index.yml b/changelogs/unreleased/id-optimize-branches-index.yml
new file mode 100644
index 00000000000..e79b89d188c
--- /dev/null
+++ b/changelogs/unreleased/id-optimize-branches-index.yml
@@ -0,0 +1,5 @@
+---
+title: Use Gitaly keyset pagination to optimize branches page
+merge_request: 53409
+author:
+type: performance
diff --git a/changelogs/unreleased/id-restrict-protected-rules.yml b/changelogs/unreleased/id-restrict-protected-rules.yml
new file mode 100644
index 00000000000..caa604bee2a
--- /dev/null
+++ b/changelogs/unreleased/id-restrict-protected-rules.yml
@@ -0,0 +1,5 @@
+---
+title: Most restrictive protected branch rule takes precedence
+merge_request: 52319
+author:
+type: fixed
diff --git a/changelogs/unreleased/id-update-bundler-audit.yml b/changelogs/unreleased/id-update-bundler-audit.yml
new file mode 100644
index 00000000000..99cca4f2319
--- /dev/null
+++ b/changelogs/unreleased/id-update-bundler-audit.yml
@@ -0,0 +1,5 @@
+---
+title: Update bundler-audit gem to 0.7.0.1
+merge_request: 52269
+author:
+type: other
diff --git a/changelogs/unreleased/id-update-default-value-for.yml b/changelogs/unreleased/id-update-default-value-for.yml
new file mode 100644
index 00000000000..e696aef5ab6
--- /dev/null
+++ b/changelogs/unreleased/id-update-default-value-for.yml
@@ -0,0 +1,5 @@
+---
+title: Update default_value_for gem to 3.4.0
+merge_request: 52271
+author:
+type: other
diff --git a/changelogs/unreleased/id-update-doorkeeper-gem.yml b/changelogs/unreleased/id-update-doorkeeper-gem.yml
new file mode 100644
index 00000000000..a6504b7dcf5
--- /dev/null
+++ b/changelogs/unreleased/id-update-doorkeeper-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Update doorkeeper to 5.5.0.rc2
+merge_request: 52171
+author:
+type: other
diff --git a/changelogs/unreleased/id-update-rspec-mocks.yml b/changelogs/unreleased/id-update-rspec-mocks.yml
new file mode 100644
index 00000000000..9cb06503b7e
--- /dev/null
+++ b/changelogs/unreleased/id-update-rspec-mocks.yml
@@ -0,0 +1,5 @@
+---
+title: Update rspec-* gem versions
+merge_request: 52873
+author:
+type: other
diff --git a/changelogs/unreleased/improve-system-oauth-app-layout.yml b/changelogs/unreleased/improve-system-oauth-app-layout.yml
new file mode 100644
index 00000000000..3561232e529
--- /dev/null
+++ b/changelogs/unreleased/improve-system-oauth-app-layout.yml
@@ -0,0 +1,5 @@
+---
+title: Make System OAuth app index table responsive and externalize text
+merge_request: 50979
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/improve-uniquness-validator-on-release.yml b/changelogs/unreleased/improve-uniquness-validator-on-release.yml
new file mode 100644
index 00000000000..31e18af5c6c
--- /dev/null
+++ b/changelogs/unreleased/improve-uniquness-validator-on-release.yml
@@ -0,0 +1,5 @@
+---
+title: Improve duplication validation on Release Links
+merge_request: 51951
+author:
+type: fixed
diff --git a/changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml b/changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml
new file mode 100644
index 00000000000..c66e3afadf8
--- /dev/null
+++ b/changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml
@@ -0,0 +1,5 @@
+---
+title: 'Improve Vulnerability Tracking: Add fingerprints table'
+merge_request: 52720
+author:
+type: added
diff --git a/changelogs/unreleased/instrument-and-log-memory-usage.yml b/changelogs/unreleased/instrument-and-log-memory-usage.yml
new file mode 100644
index 00000000000..1e3da46bdd0
--- /dev/null
+++ b/changelogs/unreleased/instrument-and-log-memory-usage.yml
@@ -0,0 +1,5 @@
+---
+title: Use a custom Ruby patch to instrument memory usage
+merge_request: 52306
+author:
+type: added
diff --git a/changelogs/unreleased/jdb-fix-drag-comment-tooltip.yml b/changelogs/unreleased/jdb-fix-drag-comment-tooltip.yml
new file mode 100644
index 00000000000..40405d7dfb6
--- /dev/null
+++ b/changelogs/unreleased/jdb-fix-drag-comment-tooltip.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tooltip when drag comment selection is enabled
+merge_request: 52595
+author:
+type: fixed
diff --git a/changelogs/unreleased/jdb-fix-project-index-file-no-longer-fluid.yml b/changelogs/unreleased/jdb-fix-project-index-file-no-longer-fluid.yml
new file mode 100644
index 00000000000..5c7d5fd7cc4
--- /dev/null
+++ b/changelogs/unreleased/jdb-fix-project-index-file-no-longer-fluid.yml
@@ -0,0 +1,5 @@
+---
+title: Add css to fix fluid layout for index file
+merge_request: 50626
+author:
+type: fixed
diff --git a/changelogs/unreleased/jimcser-openapi-readme.yml b/changelogs/unreleased/jimcser-openapi-readme.yml
new file mode 100644
index 00000000000..ee693d76727
--- /dev/null
+++ b/changelogs/unreleased/jimcser-openapi-readme.yml
@@ -0,0 +1,5 @@
+---
+title: Adds README to OpenAPI docs
+merge_request: 52637
+author: Jim Cser @jimcser
+type: added
diff --git a/changelogs/unreleased/jivanvl-convert-gl-badge-duration-component.yml b/changelogs/unreleased/jivanvl-convert-gl-badge-duration-component.yml
new file mode 100644
index 00000000000..e885cae047a
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-convert-gl-badge-duration-component.yml
@@ -0,0 +1,5 @@
+---
+title: Change the badge design in the jobs page
+merge_request: 53168
+author:
+type: changed
diff --git a/changelogs/unreleased/jivanvl-remove-graphql-pipeline-header-ff.yml b/changelogs/unreleased/jivanvl-remove-graphql-pipeline-header-ff.yml
new file mode 100644
index 00000000000..b17a6242dd1
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-graphql-pipeline-header-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove graphql_pipeline_header feature flag
+merge_request: 52247
+author:
+type: other
diff --git a/changelogs/unreleased/jivanvl-remove-runner-instructions-ff.yml b/changelogs/unreleased/jivanvl-remove-runner-instructions-ff.yml
new file mode 100644
index 00000000000..866e5a576a5
--- /dev/null
+++ b/changelogs/unreleased/jivanvl-remove-runner-instructions-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Add runner instructions modal in the CI/CD settings section
+merge_request: 53087
+author:
+type: changed
diff --git a/changelogs/unreleased/jj-remove-caching-experiments.yml b/changelogs/unreleased/jj-remove-caching-experiments.yml
new file mode 100644
index 00000000000..7a99c9b0ca2
--- /dev/null
+++ b/changelogs/unreleased/jj-remove-caching-experiments.yml
@@ -0,0 +1,5 @@
+---
+title: Remove caching_experiments feature flag
+merge_request: 53901
+author:
+type: other
diff --git a/changelogs/unreleased/jl-improve-profile-status-emoji-alignment.yml b/changelogs/unreleased/jl-improve-profile-status-emoji-alignment.yml
new file mode 100644
index 00000000000..e2b7e592465
--- /dev/null
+++ b/changelogs/unreleased/jl-improve-profile-status-emoji-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Improve profile status emoji alignment
+merge_request: 54078
+author:
+type: other
diff --git a/changelogs/unreleased/jswain_whats_new_remove_feature_flag.yml b/changelogs/unreleased/jswain_whats_new_remove_feature_flag.yml
new file mode 100644
index 00000000000..36c20c4eb09
--- /dev/null
+++ b/changelogs/unreleased/jswain_whats_new_remove_feature_flag.yml
@@ -0,0 +1,5 @@
+---
+title: Add "What's new" item to the help dropdown
+merge_request: 52020
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-bulkimports-avoid-recursive-group-migration.yml b/changelogs/unreleased/kassio-bulkimports-avoid-recursive-group-migration.yml
new file mode 100644
index 00000000000..7025c2632bd
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-avoid-recursive-group-migration.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: avoid infinity recursion on group migration'
+merge_request: 52931
+author:
+type: fixed
diff --git a/changelogs/unreleased/kassio-bulkimports-group-labels-pipeline.yml b/changelogs/unreleased/kassio-bulkimports-group-labels-pipeline.yml
new file mode 100644
index 00000000000..75a3b40cc00
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-group-labels-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: Import Group Labels'
+merge_request: 52260
+author:
+type: added
diff --git a/changelogs/unreleased/kassio-bulkimports-import-group-membership.yml b/changelogs/unreleased/kassio-bulkimports-import-group-membership.yml
new file mode 100644
index 00000000000..bf75f1f68af
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-import-group-membership.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: Migrate Group Membership'
+merge_request: 53083
+author:
+type: added
diff --git a/changelogs/unreleased/kassio-bulkimports-log-pipeline-step-on-failures.yml b/changelogs/unreleased/kassio-bulkimports-log-pipeline-step-on-failures.yml
new file mode 100644
index 00000000000..70f9c3c7d45
--- /dev/null
+++ b/changelogs/unreleased/kassio-bulkimports-log-pipeline-step-on-failures.yml
@@ -0,0 +1,5 @@
+---
+title: 'BulkImports: Add pipeline step to the failures log'
+merge_request: 52345
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-manage-import-gmau-metrics.yml b/changelogs/unreleased/kassio-manage-import-gmau-metrics.yml
new file mode 100644
index 00000000000..bea16475837
--- /dev/null
+++ b/changelogs/unreleased/kassio-manage-import-gmau-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Add the Manage::Import total GMAU metric
+merge_request: 51496
+author:
+type: added
diff --git a/changelogs/unreleased/kcomoli-copy-fixes-welcome-page.yml b/changelogs/unreleased/kcomoli-copy-fixes-welcome-page.yml
new file mode 100644
index 00000000000..0b4fca343a8
--- /dev/null
+++ b/changelogs/unreleased/kcomoli-copy-fixes-welcome-page.yml
@@ -0,0 +1,6 @@
+---
+title: Improve overall copy, remove redundant reassurance in the form, and fix empty
+ %p rendered in the DOM of the welcome page.
+merge_request: 52660
+author:
+type: other
diff --git a/changelogs/unreleased/leipert-remove-sticky-polyfill.yml b/changelogs/unreleased/leipert-remove-sticky-polyfill.yml
new file mode 100644
index 00000000000..1deb36df8ea
--- /dev/null
+++ b/changelogs/unreleased/leipert-remove-sticky-polyfill.yml
@@ -0,0 +1,5 @@
+---
+title: Remove position sticky polyfill
+merge_request: 54299
+author:
+type: changed
diff --git a/changelogs/unreleased/link-new-line-gpg.yml b/changelogs/unreleased/link-new-line-gpg.yml
new file mode 100644
index 00000000000..7cc450b100e
--- /dev/null
+++ b/changelogs/unreleased/link-new-line-gpg.yml
@@ -0,0 +1,5 @@
+---
+title: Show helper link on a new line in GPG status popover
+merge_request: 52894
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/lm-add-merged-yaml.yml b/changelogs/unreleased/lm-add-merged-yaml.yml
new file mode 100644
index 00000000000..518a6f0c4fe
--- /dev/null
+++ b/changelogs/unreleased/lm-add-merged-yaml.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: Add mergedYaml to CiConfigResolver response'
+merge_request: 53081
+author:
+type: changed
diff --git a/changelogs/unreleased/lm-adds-gitaly-call-label.yml b/changelogs/unreleased/lm-adds-gitaly-call-label.yml
new file mode 100644
index 00000000000..48e324cfa3d
--- /dev/null
+++ b/changelogs/unreleased/lm-adds-gitaly-call-label.yml
@@ -0,0 +1,6 @@
+---
+title: Increase the complexity score of GraphQL detailedStatus#label as it can call
+ Gitaly
+merge_request: 52708
+author:
+type: changed
diff --git a/changelogs/unreleased/loading-space-todo.yml b/changelogs/unreleased/loading-space-todo.yml
new file mode 100644
index 00000000000..b5d2886bdbf
--- /dev/null
+++ b/changelogs/unreleased/loading-space-todo.yml
@@ -0,0 +1,5 @@
+---
+title: Add Space before loading icon in toggle todo button
+merge_request: 53463
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/make-lifecycle-hooks-to-be-fatal.yml b/changelogs/unreleased/make-lifecycle-hooks-to-be-fatal.yml
new file mode 100644
index 00000000000..2bf1fdd7a72
--- /dev/null
+++ b/changelogs/unreleased/make-lifecycle-hooks-to-be-fatal.yml
@@ -0,0 +1,5 @@
+---
+title: Make LifecycleEvents exceptions to be fatal
+merge_request: 52881
+author:
+type: fixed
diff --git a/changelogs/unreleased/map-prometheus-payload-severity.yml b/changelogs/unreleased/map-prometheus-payload-severity.yml
new file mode 100644
index 00000000000..4fe69286c09
--- /dev/null
+++ b/changelogs/unreleased/map-prometheus-payload-severity.yml
@@ -0,0 +1,5 @@
+---
+title: Map common severity values from a Prometheus alert payload
+merge_request: 50871
+author:
+type: added
diff --git a/changelogs/unreleased/mc-api-pipeline-webhook-remove-retried-jobs.yml b/changelogs/unreleased/mc-api-pipeline-webhook-remove-retried-jobs.yml
new file mode 100644
index 00000000000..f75824b04ce
--- /dev/null
+++ b/changelogs/unreleased/mc-api-pipeline-webhook-remove-retried-jobs.yml
@@ -0,0 +1,5 @@
+---
+title: Send only latest jobs in pipeline webhook payload.
+merge_request: 53159
+author:
+type: fixed
diff --git a/changelogs/unreleased/mc-backstage-reduce-db-updates-ci-minute-reset.yml b/changelogs/unreleased/mc-backstage-reduce-db-updates-ci-minute-reset.yml
new file mode 100644
index 00000000000..7770e9a597f
--- /dev/null
+++ b/changelogs/unreleased/mc-backstage-reduce-db-updates-ci-minute-reset.yml
@@ -0,0 +1,5 @@
+---
+title: Reset CI minutes only for namespaces that used minutes.
+merge_request: 53740
+author:
+type: changed
diff --git a/changelogs/unreleased/mc-backstage-schedule-artifact-expiration-backfill-properly.yml b/changelogs/unreleased/mc-backstage-schedule-artifact-expiration-backfill-properly.yml
new file mode 100644
index 00000000000..8d1b972639c
--- /dev/null
+++ b/changelogs/unreleased/mc-backstage-schedule-artifact-expiration-backfill-properly.yml
@@ -0,0 +1,5 @@
+---
+title: Schedule artifact expiry date backfill background jobs.
+merge_request: 51822
+author:
+type: fixed
diff --git a/changelogs/unreleased/memoize-fork-button.yml b/changelogs/unreleased/memoize-fork-button.yml
new file mode 100644
index 00000000000..d5df12c4a6a
--- /dev/null
+++ b/changelogs/unreleased/memoize-fork-button.yml
@@ -0,0 +1,5 @@
+---
+title: Memoize the fork suggestion button partial
+merge_request: 53256
+author:
+type: performance
diff --git a/changelogs/unreleased/mjang-deploy-tokens-okr-update.yml b/changelogs/unreleased/mjang-deploy-tokens-okr-update.yml
new file mode 100644
index 00000000000..55114563a47
--- /dev/null
+++ b/changelogs/unreleased/mjang-deploy-tokens-okr-update.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 52267
+author:
+type: other
diff --git a/changelogs/unreleased/mk-fix-cleanup-rake-task-limit.yml b/changelogs/unreleased/mk-fix-cleanup-rake-task-limit.yml
new file mode 100644
index 00000000000..4b33395abe2
--- /dev/null
+++ b/changelogs/unreleased/mk-fix-cleanup-rake-task-limit.yml
@@ -0,0 +1,5 @@
+---
+title: Fix gitlab:cleanup:orphan_job_artifact_files rake task limit
+merge_request: 52056
+author:
+type: fixed
diff --git a/changelogs/unreleased/mo-add-group-id-to-coverage-data.yml b/changelogs/unreleased/mo-add-group-id-to-coverage-data.yml
new file mode 100644
index 00000000000..05ac93ce8fc
--- /dev/null
+++ b/changelogs/unreleased/mo-add-group-id-to-coverage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Add group_id to ci_daily_build_group_report_result
+merge_request: 53494
+author:
+type: added
diff --git a/changelogs/unreleased/move-vulnerability-report-to-card.yml b/changelogs/unreleased/move-vulnerability-report-to-card.yml
new file mode 100644
index 00000000000..a2a98f5751e
--- /dev/null
+++ b/changelogs/unreleased/move-vulnerability-report-to-card.yml
@@ -0,0 +1,5 @@
+---
+title: Move vulnerability report counts to GlCard
+merge_request: 52416
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/move_mutations_to_ce_for_sast_config.yml b/changelogs/unreleased/move_mutations_to_ce_for_sast_config.yml
new file mode 100644
index 00000000000..edaf88df906
--- /dev/null
+++ b/changelogs/unreleased/move_mutations_to_ce_for_sast_config.yml
@@ -0,0 +1,5 @@
+---
+title: 'Move to CE: mutation to create MR for SAST Configuration'
+merge_request: 51634
+author:
+type: changed
diff --git a/changelogs/unreleased/msj-todo-alerts.yml b/changelogs/unreleased/msj-todo-alerts.yml
new file mode 100644
index 00000000000..ee57d24466e
--- /dev/null
+++ b/changelogs/unreleased/msj-todo-alerts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix formatting of "to do" in alert sidebar and error
+merge_request: 53037
+author:
+type: fixed
diff --git a/changelogs/unreleased/msj-todo-design-errors.yml b/changelogs/unreleased/msj-todo-design-errors.yml
new file mode 100644
index 00000000000..d7c1417949e
--- /dev/null
+++ b/changelogs/unreleased/msj-todo-design-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Change to-do formatting in Design error messages and sidebar
+merge_request: 53040
+author:
+type: fixed
diff --git a/changelogs/unreleased/mwaw-add_index_to_security_scans_on_created_at_and_build_id.yml b/changelogs/unreleased/mwaw-add_index_to_security_scans_on_created_at_and_build_id.yml
new file mode 100644
index 00000000000..c6b696c30a4
--- /dev/null
+++ b/changelogs/unreleased/mwaw-add_index_to_security_scans_on_created_at_and_build_id.yml
@@ -0,0 +1,5 @@
+---
+title: Add database index to improve performance of usage ping metrics calculation
+merge_request: 48671
+author:
+type: performance
diff --git a/changelogs/unreleased/nadia_sotnikova-master-patch-51286.yml b/changelogs/unreleased/nadia_sotnikova-master-patch-51286.yml
new file mode 100644
index 00000000000..dcbd84bcaa8
--- /dev/null
+++ b/changelogs/unreleased/nadia_sotnikova-master-patch-51286.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 51348
+author:
+type: other
diff --git a/changelogs/unreleased/new-gitlab-ui-blob-editor.yml b/changelogs/unreleased/new-gitlab-ui-blob-editor.yml
new file mode 100644
index 00000000000..ffec3021a33
--- /dev/null
+++ b/changelogs/unreleased/new-gitlab-ui-blob-editor.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input fields in file editor
+merge_request: 52461
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/new-tab-links.yml b/changelogs/unreleased/new-tab-links.yml
new file mode 100644
index 00000000000..35da06e7820
--- /dev/null
+++ b/changelogs/unreleased/new-tab-links.yml
@@ -0,0 +1,5 @@
+---
+title: Open CI/CD settings help links in new tab by default
+merge_request: 52948
+author:
+type: other
diff --git a/changelogs/unreleased/nfriend-add-mininterval-to-pipeline-charts.yml b/changelogs/unreleased/nfriend-add-mininterval-to-pipeline-charts.yml
new file mode 100644
index 00000000000..7d0961e7757
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-mininterval-to-pipeline-charts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Y axis units of pipeline charts when values are small
+merge_request: 52024
+author:
+type: fixed
diff --git a/changelogs/unreleased/nicolasdular-cleanup-pipelines-empty-state-experiment.yml b/changelogs/unreleased/nicolasdular-cleanup-pipelines-empty-state-experiment.yml
new file mode 100644
index 00000000000..1691991e5c9
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-cleanup-pipelines-empty-state-experiment.yml
@@ -0,0 +1,5 @@
+---
+title: Change pipeline empty state language
+merge_request: 53281
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-fix-welcome-page.yml b/changelogs/unreleased/nicolasdular-fix-welcome-page.yml
new file mode 100644
index 00000000000..b9d6914e1af
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-fix-welcome-page.yml
@@ -0,0 +1,5 @@
+---
+title: Fix welcome page alignment on CE
+merge_request: 53265
+author:
+type: fixed
diff --git a/changelogs/unreleased/paginate-commit.yml b/changelogs/unreleased/paginate-commit.yml
new file mode 100644
index 00000000000..c75435cdf3b
--- /dev/null
+++ b/changelogs/unreleased/paginate-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Paginate single commit view
+merge_request: 52819
+author:
+type: performance
diff --git a/changelogs/unreleased/pb-bold-font.yml b/changelogs/unreleased/pb-bold-font.yml
new file mode 100644
index 00000000000..1cef577d916
--- /dev/null
+++ b/changelogs/unreleased/pb-bold-font.yml
@@ -0,0 +1,5 @@
+---
+title: Bold metricDetailsLabel in the performance bar
+merge_request: 52417
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/pb-change-mr-pipeline-failed-message.yml b/changelogs/unreleased/pb-change-mr-pipeline-failed-message.yml
new file mode 100644
index 00000000000..3fc0e14cd79
--- /dev/null
+++ b/changelogs/unreleased/pb-change-mr-pipeline-failed-message.yml
@@ -0,0 +1,5 @@
+---
+title: Change UI text for failed pipeline on an MR
+merge_request: 52023
+author:
+type: changed
diff --git a/changelogs/unreleased/pb-dm-modal-text-color.yml b/changelogs/unreleased/pb-dm-modal-text-color.yml
new file mode 100644
index 00000000000..8bef521a57a
--- /dev/null
+++ b/changelogs/unreleased/pb-dm-modal-text-color.yml
@@ -0,0 +1,6 @@
+---
+title: Remove gl-text-black-normal from detailed metric which is not visible in dark
+ mode
+merge_request: 53563
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/pb-move-pipeline-new-input-to-textarea.yml b/changelogs/unreleased/pb-move-pipeline-new-input-to-textarea.yml
new file mode 100644
index 00000000000..e7e4b50202e
--- /dev/null
+++ b/changelogs/unreleased/pb-move-pipeline-new-input-to-textarea.yml
@@ -0,0 +1,6 @@
+---
+title: Support multi-line string variable values when running a manual pipeline in
+ the UI.
+merge_request: 53292
+author:
+type: fixed
diff --git a/changelogs/unreleased/pb-use-gl-alert-erased-block.yml b/changelogs/unreleased/pb-use-gl-alert-erased-block.yml
new file mode 100644
index 00000000000..4f40e54f5ba
--- /dev/null
+++ b/changelogs/unreleased/pb-use-gl-alert-erased-block.yml
@@ -0,0 +1,5 @@
+---
+title: Replace erase job alert background color with color consistent with UI
+merge_request: 52810
+author:
+type: changed
diff --git a/changelogs/unreleased/peterhegman-fix-assignee-dropdown-checkmark.yml b/changelogs/unreleased/peterhegman-fix-assignee-dropdown-checkmark.yml
new file mode 100644
index 00000000000..eb29e0828ae
--- /dev/null
+++ b/changelogs/unreleased/peterhegman-fix-assignee-dropdown-checkmark.yml
@@ -0,0 +1,5 @@
+---
+title: Fix misalignment of assignee dropdown checkmark
+merge_request: 53664
+author:
+type: fixed
diff --git a/changelogs/unreleased/peterhegman-fix-members-status-emoji-size.yml b/changelogs/unreleased/peterhegman-fix-members-status-emoji-size.yml
new file mode 100644
index 00000000000..ccb4e06ad95
--- /dev/null
+++ b/changelogs/unreleased/peterhegman-fix-members-status-emoji-size.yml
@@ -0,0 +1,5 @@
+---
+title: Fix size of group member user status emoji
+merge_request: 52730
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-227161-fixDiscussonsOnCommits.yml b/changelogs/unreleased/ph-227161-fixDiscussonsOnCommits.yml
new file mode 100644
index 00000000000..af45d8f1a93
--- /dev/null
+++ b/changelogs/unreleased/ph-227161-fixDiscussonsOnCommits.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed discussions on merge request commits not showing
+merge_request: 53143
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-235741-fixSuggestionsUpdatingIncorrectly.yml b/changelogs/unreleased/ph-235741-fixSuggestionsUpdatingIncorrectly.yml
new file mode 100644
index 00000000000..2b7bbef0223
--- /dev/null
+++ b/changelogs/unreleased/ph-235741-fixSuggestionsUpdatingIncorrectly.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed notes polling incorrectly overwriting suggestions in the DOM
+merge_request: 51988
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-255626-allowMultipleCommentsInInlineView.yml b/changelogs/unreleased/ph-255626-allowMultipleCommentsInInlineView.yml
new file mode 100644
index 00000000000..c1a88fd784f
--- /dev/null
+++ b/changelogs/unreleased/ph-255626-allowMultipleCommentsInInlineView.yml
@@ -0,0 +1,5 @@
+---
+title: Allow multiple comments on diff lines in inline view
+merge_request: 52111
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-293891-fixSuggestionsToReplies.yml b/changelogs/unreleased/ph-293891-fixSuggestionsToReplies.yml
new file mode 100644
index 00000000000..1060ef22c5a
--- /dev/null
+++ b/changelogs/unreleased/ph-293891-fixSuggestionsToReplies.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed sdiff suggestions not working when replying to comments
+merge_request: 52100
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-300006-fixDiffsDiscussionWrongSide.yml b/changelogs/unreleased/ph-300006-fixDiffsDiscussionWrongSide.yml
new file mode 100644
index 00000000000..798da9e15a6
--- /dev/null
+++ b/changelogs/unreleased/ph-300006-fixDiffsDiscussionWrongSide.yml
@@ -0,0 +1,5 @@
+---
+title: Fix diff discussions rendering on the wrong side
+merge_request: 52579
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-fixMRGraphQlCommitsCount.yml b/changelogs/unreleased/ph-fixMRGraphQlCommitsCount.yml
new file mode 100644
index 00000000000..fd7204b9117
--- /dev/null
+++ b/changelogs/unreleased/ph-fixMRGraphQlCommitsCount.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes GraphQl merge request types commits count
+merge_request: 52218
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-mergeRequestLockedStatus.yml b/changelogs/unreleased/ph-mergeRequestLockedStatus.yml
new file mode 100644
index 00000000000..069e2b6ae5c
--- /dev/null
+++ b/changelogs/unreleased/ph-mergeRequestLockedStatus.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed merge requests locked status not showing
+merge_request: 52078
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-ph-fixWidgetGraphqlPipelineWarnings.yml b/changelogs/unreleased/ph-ph-fixWidgetGraphqlPipelineWarnings.yml
new file mode 100644
index 00000000000..a1fb41ac716
--- /dev/null
+++ b/changelogs/unreleased/ph-ph-fixWidgetGraphqlPipelineWarnings.yml
@@ -0,0 +1,5 @@
+---
+title: Added warnings field to the pipelines GraphQL type
+merge_request: 54296
+author:
+type: added
diff --git a/changelogs/unreleased/ph-reRequestReview.yml b/changelogs/unreleased/ph-reRequestReview.yml
new file mode 100644
index 00000000000..36d8bbfc647
--- /dev/null
+++ b/changelogs/unreleased/ph-reRequestReview.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users to re-request a review from a reviewer
+merge_request: 50068
+author:
+type: added
diff --git a/changelogs/unreleased/ph-requestReviewBackend.yml b/changelogs/unreleased/ph-requestReviewBackend.yml
new file mode 100644
index 00000000000..42f2c52c6fe
--- /dev/null
+++ b/changelogs/unreleased/ph-requestReviewBackend.yml
@@ -0,0 +1,5 @@
+---
+title: Added ability to re-request a review from a reviewer
+merge_request: 52321
+author:
+type: added
diff --git a/changelogs/unreleased/philipcunningham-create-dast-scan-model-295243.yml b/changelogs/unreleased/philipcunningham-create-dast-scan-model-295243.yml
new file mode 100644
index 00000000000..2aaebc076d5
--- /dev/null
+++ b/changelogs/unreleased/philipcunningham-create-dast-scan-model-295243.yml
@@ -0,0 +1,5 @@
+---
+title: Add dast_profiles database table
+merge_request: 51296
+author:
+type: added
diff --git a/changelogs/unreleased/pipeline-editor-confirm-dialog.yml b/changelogs/unreleased/pipeline-editor-confirm-dialog.yml
new file mode 100644
index 00000000000..1871b4bd611
--- /dev/null
+++ b/changelogs/unreleased/pipeline-editor-confirm-dialog.yml
@@ -0,0 +1,5 @@
+---
+title: Show confirmation dialog when exiting pipeline editor
+merge_request: 52458
+author:
+type: added
diff --git a/changelogs/unreleased/pkce-cors.yml b/changelogs/unreleased/pkce-cors.yml
new file mode 100644
index 00000000000..151fa5e55fa
--- /dev/null
+++ b/changelogs/unreleased/pkce-cors.yml
@@ -0,0 +1,5 @@
+---
+title: Allow cross-origin requests on /oauth/token
+merge_request: 52641
+author:
+type: fixed
diff --git a/changelogs/unreleased/pks-gitaly-fix-force-routing.yml b/changelogs/unreleased/pks-gitaly-fix-force-routing.yml
new file mode 100644
index 00000000000..69d0a86ec9c
--- /dev/null
+++ b/changelogs/unreleased/pks-gitaly-fix-force-routing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix force-routing to Gitaly primary with empty hook env
+merge_request: 54317
+author:
+type: fixed
diff --git a/changelogs/unreleased/pks-gitaly-force-primary-routing-with-hookenv.yml b/changelogs/unreleased/pks-gitaly-force-primary-routing-with-hookenv.yml
new file mode 100644
index 00000000000..1f625c03985
--- /dev/null
+++ b/changelogs/unreleased/pks-gitaly-force-primary-routing-with-hookenv.yml
@@ -0,0 +1,5 @@
+---
+title: 'gitaly: Fix access checks with transactions and quarantine environments'
+merge_request: 53449
+author:
+type: fixed
diff --git a/changelogs/unreleased/pl-generic-payload-severity.yml b/changelogs/unreleased/pl-generic-payload-severity.yml
new file mode 100644
index 00000000000..a0a70c2cb36
--- /dev/null
+++ b/changelogs/unreleased/pl-generic-payload-severity.yml
@@ -0,0 +1,5 @@
+---
+title: Handle severity for generic payloads more gracefully
+merge_request: 53999
+author:
+type: fixed
diff --git a/changelogs/unreleased/preset_ancestor.yml b/changelogs/unreleased/preset_ancestor.yml
new file mode 100644
index 00000000000..6fc42e6e02e
--- /dev/null
+++ b/changelogs/unreleased/preset_ancestor.yml
@@ -0,0 +1,5 @@
+---
+title: Optimized loading of descendant group labels
+merge_request: 53356
+author:
+type: performance
diff --git a/changelogs/unreleased/prevent-notifications-from-ghost-user.yml b/changelogs/unreleased/prevent-notifications-from-ghost-user.yml
new file mode 100644
index 00000000000..22a2813331b
--- /dev/null
+++ b/changelogs/unreleased/prevent-notifications-from-ghost-user.yml
@@ -0,0 +1,5 @@
+---
+title: Skip new note notifications when author is deleted
+merge_request: 53699
+author:
+type: changed
diff --git a/changelogs/unreleased/prevent_blocked_user_notification.yml b/changelogs/unreleased/prevent_blocked_user_notification.yml
new file mode 100644
index 00000000000..0ffe0819929
--- /dev/null
+++ b/changelogs/unreleased/prevent_blocked_user_notification.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent blocked user from triggering notifications
+merge_request: 53788
+author:
+type: other
diff --git a/changelogs/unreleased/ps-clean-new-gl-button-refs.yml b/changelogs/unreleased/ps-clean-new-gl-button-refs.yml
new file mode 100644
index 00000000000..41aa28962b8
--- /dev/null
+++ b/changelogs/unreleased/ps-clean-new-gl-button-refs.yml
@@ -0,0 +1,6 @@
+---
+title: Update button style for consistency in Settings > Integrations, Mermaid Diagram
+ warning, and No SSH warning
+merge_request: 51864
+author:
+type: other
diff --git a/changelogs/unreleased/ps-refactor-snippets-edit-spec-no-vm.yml b/changelogs/unreleased/ps-refactor-snippets-edit-spec-no-vm.yml
new file mode 100644
index 00000000000..908708cfbda
--- /dev/null
+++ b/changelogs/unreleased/ps-refactor-snippets-edit-spec-no-vm.yml
@@ -0,0 +1,5 @@
+---
+title: Improve error message reporting in snippet create or update
+merge_request: 53576
+author:
+type: other
diff --git a/changelogs/unreleased/ps-remove-gl-dropdown-item-deprecated-adapter.yml b/changelogs/unreleased/ps-remove-gl-dropdown-item-deprecated-adapter.yml
new file mode 100644
index 00000000000..dda80285413
--- /dev/null
+++ b/changelogs/unreleased/ps-remove-gl-dropdown-item-deprecated-adapter.yml
@@ -0,0 +1,5 @@
+---
+title: Change secondary text color on Gitpod editor dropdown button
+merge_request: 53437
+author:
+type: other
diff --git a/changelogs/unreleased/psi-board-list-highlight.yml b/changelogs/unreleased/psi-board-list-highlight.yml
new file mode 100644
index 00000000000..e97f6696049
--- /dev/null
+++ b/changelogs/unreleased/psi-board-list-highlight.yml
@@ -0,0 +1,5 @@
+---
+title: Highlight board lists when they are added
+merge_request: 53779
+author:
+type: changed
diff --git a/changelogs/unreleased/psi-board-search-align.yml b/changelogs/unreleased/psi-board-search-align.yml
new file mode 100644
index 00000000000..a75601080a5
--- /dev/null
+++ b/changelogs/unreleased/psi-board-search-align.yml
@@ -0,0 +1,5 @@
+---
+title: Align and reorder boards search bar buttons
+merge_request: 53690
+author:
+type: changed
diff --git a/changelogs/unreleased/psi-pipeline-icon-align.yml b/changelogs/unreleased/psi-pipeline-icon-align.yml
new file mode 100644
index 00000000000..a5d0c261f3b
--- /dev/null
+++ b/changelogs/unreleased/psi-pipeline-icon-align.yml
@@ -0,0 +1,5 @@
+---
+title: Vertically centre CI icons on pipeline page
+merge_request: 53427
+author:
+type: fixed
diff --git a/changelogs/unreleased/qmnguyen0711-640-sidekiq-jobretry-skip-should-not-mask-the-underlying-sid.yml b/changelogs/unreleased/qmnguyen0711-640-sidekiq-jobretry-skip-should-not-mask-the-underlying-sid.yml
new file mode 100644
index 00000000000..21c991359ae
--- /dev/null
+++ b/changelogs/unreleased/qmnguyen0711-640-sidekiq-jobretry-skip-should-not-mask-the-underlying-sid.yml
@@ -0,0 +1,5 @@
+---
+title: Unwrap Sidekiq exceptions and jobs in the structured logs and metrics
+merge_request: 53006
+author:
+type: changed
diff --git a/changelogs/unreleased/qmnguyen0711-751-rack-attack-redis-calls-showing-up-in-the-slowlog.yml b/changelogs/unreleased/qmnguyen0711-751-rack-attack-redis-calls-showing-up-in-the-slowlog.yml
new file mode 100644
index 00000000000..a9ca08b1dd1
--- /dev/null
+++ b/changelogs/unreleased/qmnguyen0711-751-rack-attack-redis-calls-showing-up-in-the-slowlog.yml
@@ -0,0 +1,5 @@
+---
+title: Monitor RackAttack redis usage and enrich auth structured logs
+merge_request: 52471
+author:
+type: changed
diff --git a/changelogs/unreleased/redesign-download-button.yml b/changelogs/unreleased/redesign-download-button.yml
new file mode 100644
index 00000000000..53f93047d76
--- /dev/null
+++ b/changelogs/unreleased/redesign-download-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update download button size to sm from xs and add btn-default
+merge_request: 52867
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/redo-changelog-index.yml b/changelogs/unreleased/redo-changelog-index.yml
new file mode 100644
index 00000000000..a65586a2a81
--- /dev/null
+++ b/changelogs/unreleased/redo-changelog-index.yml
@@ -0,0 +1,5 @@
+---
+title: Re-add migration to fix invalid merge request index
+merge_request: 53042
+author:
+type: other
diff --git a/changelogs/unreleased/remove-banzai-commit-full-title.yml b/changelogs/unreleased/remove-banzai-commit-full-title.yml
new file mode 100644
index 00000000000..2447d03eb30
--- /dev/null
+++ b/changelogs/unreleased/remove-banzai-commit-full-title.yml
@@ -0,0 +1,5 @@
+---
+title: Introduce a rendering limit for commit titles
+merge_request: 52904
+author:
+type: performance
diff --git a/changelogs/unreleased/remove-ci-custom-tags-ff-300155.yml b/changelogs/unreleased/remove-ci-custom-tags-ff-300155.yml
new file mode 100644
index 00000000000..ba5ac89a7ec
--- /dev/null
+++ b/changelogs/unreleased/remove-ci-custom-tags-ff-300155.yml
@@ -0,0 +1,5 @@
+---
+title: Add '!reference' YAML tag to help merge CI configurations
+merge_request: 54198
+author:
+type: added
diff --git a/changelogs/unreleased/remove-extra-margin-project-template.yml b/changelogs/unreleased/remove-extra-margin-project-template.yml
new file mode 100644
index 00000000000..c062cba887f
--- /dev/null
+++ b/changelogs/unreleased/remove-extra-margin-project-template.yml
@@ -0,0 +1,5 @@
+---
+title: Remove extra margin below tab on project template page
+merge_request: 52454
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/remove-feature-flag-deploy_keys_on_protected_branches.yml b/changelogs/unreleased/remove-feature-flag-deploy_keys_on_protected_branches.yml
new file mode 100644
index 00000000000..458adc96b73
--- /dev/null
+++ b/changelogs/unreleased/remove-feature-flag-deploy_keys_on_protected_branches.yml
@@ -0,0 +1,5 @@
+---
+title: Allow deploy keys to push to a protected branch
+merge_request: 53812
+author:
+type: added
diff --git a/changelogs/unreleased/remove-feature_flag_contextual_issue.yml b/changelogs/unreleased/remove-feature_flag_contextual_issue.yml
new file mode 100644
index 00000000000..e99cdaf7a11
--- /dev/null
+++ b/changelogs/unreleased/remove-feature_flag_contextual_issue.yml
@@ -0,0 +1,5 @@
+---
+title: Support Markdown for Feature Flags
+merge_request: 53816
+author:
+type: added
diff --git a/changelogs/unreleased/remove-implicit-feature-flag-check-on-featurable.yml b/changelogs/unreleased/remove-implicit-feature-flag-check-on-featurable.yml
new file mode 100644
index 00000000000..b476dfb474f
--- /dev/null
+++ b/changelogs/unreleased/remove-implicit-feature-flag-check-on-featurable.yml
@@ -0,0 +1,5 @@
+---
+title: Remove implicit FF check on `Featurable`
+merge_request: 52223
+author:
+type: removed
diff --git a/changelogs/unreleased/remove-merge-request-reviewer-ff.yml b/changelogs/unreleased/remove-merge-request-reviewer-ff.yml
new file mode 100644
index 00000000000..ee102e05557
--- /dev/null
+++ b/changelogs/unreleased/remove-merge-request-reviewer-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove merge_request_reviewers feature flag
+merge_request: 52468
+author:
+type: removed
diff --git a/changelogs/unreleased/remove-owner-data-from-group-webhooks.yml b/changelogs/unreleased/remove-owner-data-from-group-webhooks.yml
new file mode 100644
index 00000000000..0b1114ab974
--- /dev/null
+++ b/changelogs/unreleased/remove-owner-data-from-group-webhooks.yml
@@ -0,0 +1,5 @@
+---
+title: Remove group owner data from webhooks
+merge_request: 52071
+author:
+type: changed
diff --git a/changelogs/unreleased/remove-tmp-index-oauth-applications.yml b/changelogs/unreleased/remove-tmp-index-oauth-applications.yml
new file mode 100644
index 00000000000..ae8a4d5b66d
--- /dev/null
+++ b/changelogs/unreleased/remove-tmp-index-oauth-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Remove temp index in oauth_applications table
+merge_request: 52157
+author:
+type: other
diff --git a/changelogs/unreleased/reposition-integration-form-elements.yml b/changelogs/unreleased/reposition-integration-form-elements.yml
new file mode 100644
index 00000000000..05880ddcdea
--- /dev/null
+++ b/changelogs/unreleased/reposition-integration-form-elements.yml
@@ -0,0 +1,5 @@
+---
+title: Move integration inheritance override dropdown above grid layout
+merge_request: 49325
+author:
+type: changed
diff --git a/changelogs/unreleased/reset-admin-password-rake-task.yml b/changelogs/unreleased/reset-admin-password-rake-task.yml
new file mode 100644
index 00000000000..d2a0058d3dd
--- /dev/null
+++ b/changelogs/unreleased/reset-admin-password-rake-task.yml
@@ -0,0 +1,5 @@
+---
+title: Add rake task to reset user password
+merge_request: 52347
+author:
+type: added
diff --git a/changelogs/unreleased/retarget-branch.yml b/changelogs/unreleased/retarget-branch.yml
new file mode 100644
index 00000000000..a879f7fdbec
--- /dev/null
+++ b/changelogs/unreleased/retarget-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Automatically retarget merge requests
+merge_request: 53710
+author:
+type: added
diff --git a/changelogs/unreleased/return-all-jobs.yml b/changelogs/unreleased/return-all-jobs.yml
new file mode 100644
index 00000000000..3e19cd888d1
--- /dev/null
+++ b/changelogs/unreleased/return-all-jobs.yml
@@ -0,0 +1,5 @@
+---
+title: Allow to retrieve all jobs for a given pipeline
+merge_request: 48589
+author: Alexander Kutelev
+type: fixed
diff --git a/changelogs/unreleased/revert-3c18ef0b.yml b/changelogs/unreleased/revert-3c18ef0b.yml
new file mode 100644
index 00000000000..b31edcd52ca
--- /dev/null
+++ b/changelogs/unreleased/revert-3c18ef0b.yml
@@ -0,0 +1,5 @@
+---
+title: Drop repository_read_only column from namespaces table
+merge_request: 52181
+author:
+type: changed
diff --git a/changelogs/unreleased/revert-project-has_external_wiki.yml b/changelogs/unreleased/revert-project-has_external_wiki.yml
new file mode 100644
index 00000000000..b5961fd54a3
--- /dev/null
+++ b/changelogs/unreleased/revert-project-has_external_wiki.yml
@@ -0,0 +1,5 @@
+---
+title: Set projects.has_external_wiki default to null if default value is present
+merge_request: 53216
+author:
+type: other
diff --git a/changelogs/unreleased/revert-pull-by-digest.yml b/changelogs/unreleased/revert-pull-by-digest.yml
new file mode 100644
index 00000000000..b2de5e27638
--- /dev/null
+++ b/changelogs/unreleased/revert-pull-by-digest.yml
@@ -0,0 +1,6 @@
+---
+title: Remove dependency_proxy_manifests records with content_type to prevent Dependency
+ Proxy failures
+merge_request: 53506
+author:
+type: fixed
diff --git a/changelogs/unreleased/rf-update-brakeman-rules.yml b/changelogs/unreleased/rf-update-brakeman-rules.yml
new file mode 100644
index 00000000000..61fa8f0838c
--- /dev/null
+++ b/changelogs/unreleased/rf-update-brakeman-rules.yml
@@ -0,0 +1,5 @@
+---
+title: Update Ruby detection rules for SAST
+merge_request: 53414
+author:
+type: changed
diff --git a/changelogs/unreleased/russell-update-project-visibility-settings-ui-text.yml b/changelogs/unreleased/russell-update-project-visibility-settings-ui-text.yml
new file mode 100644
index 00000000000..a1d09aec758
--- /dev/null
+++ b/changelogs/unreleased/russell-update-project-visibility-settings-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Edited UI copy wording to comply with GitLab style
+merge_request: 50676
+author:
+type: other
diff --git a/changelogs/unreleased/selhorn-okr-triggers.yml b/changelogs/unreleased/selhorn-okr-triggers.yml
new file mode 100644
index 00000000000..601cb313184
--- /dev/null
+++ b/changelogs/unreleased/selhorn-okr-triggers.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 52284
+author:
+type: other
diff --git a/changelogs/unreleased/semgrep-docs-n-template.yml b/changelogs/unreleased/semgrep-docs-n-template.yml
new file mode 100644
index 00000000000..12509881ff3
--- /dev/null
+++ b/changelogs/unreleased/semgrep-docs-n-template.yml
@@ -0,0 +1,5 @@
+---
+title: Add semgrep SAST analyzer
+merge_request: 53815
+author: Daniel Paul Searles
+type: added
diff --git a/changelogs/unreleased/sfang-project-access-token-api.yml b/changelogs/unreleased/sfang-project-access-token-api.yml
new file mode 100644
index 00000000000..96de9cea3e5
--- /dev/null
+++ b/changelogs/unreleased/sfang-project-access-token-api.yml
@@ -0,0 +1,5 @@
+---
+title: Project access token management via API
+merge_request: 52139
+author:
+type: added
diff --git a/changelogs/unreleased/sh-add-openid-sso-icon.yml b/changelogs/unreleased/sh-add-openid-sso-icon.yml
new file mode 100644
index 00000000000..7993ded80fa
--- /dev/null
+++ b/changelogs/unreleased/sh-add-openid-sso-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Add OpenID SSO icon
+merge_request: 54026
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-disable-ci-live-trace-ff.yml b/changelogs/unreleased/sh-disable-ci-live-trace-ff.yml
new file mode 100644
index 00000000000..ac2858260e8
--- /dev/null
+++ b/changelogs/unreleased/sh-disable-ci-live-trace-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove ci_live_trace_use_fog_attributes feature flag
+merge_request: 52939
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-fix-discussion-note-promotion-failure-handling.yml b/changelogs/unreleased/sh-fix-discussion-note-promotion-failure-handling.yml
new file mode 100644
index 00000000000..dfabb8e3089
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-discussion-note-promotion-failure-handling.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure note is promoted to discussion within reply create transaction
+merge_request: 53542
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-handle-fog-host-params.yml b/changelogs/unreleased/sh-handle-fog-host-params.yml
new file mode 100644
index 00000000000..4cfcac84b6d
--- /dev/null
+++ b/changelogs/unreleased/sh-handle-fog-host-params.yml
@@ -0,0 +1,5 @@
+---
+title: Support fog-aws host options for Workhorse S3 client
+merge_request: 53326
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-prepend-marginalia-comments.yml b/changelogs/unreleased/sh-prepend-marginalia-comments.yml
new file mode 100644
index 00000000000..3ebdd0527ec
--- /dev/null
+++ b/changelogs/unreleased/sh-prepend-marginalia-comments.yml
@@ -0,0 +1,5 @@
+---
+title: Prepend the Marginalia comment in SQL query
+merge_request: 54015
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-update-hamlit-for-gc.yml b/changelogs/unreleased/sh-update-hamlit-for-gc.yml
new file mode 100644
index 00000000000..abfb61e0ba7
--- /dev/null
+++ b/changelogs/unreleased/sh-update-hamlit-for-gc.yml
@@ -0,0 +1,5 @@
+---
+title: Update hamlit to v2.14.2
+merge_request: 52177
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-update-rugged-v1-0-1.yml b/changelogs/unreleased/sh-update-rugged-v1-0-1.yml
new file mode 100644
index 00000000000..16bd92fa7ca
--- /dev/null
+++ b/changelogs/unreleased/sh-update-rugged-v1-0-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update Rugged to v1.0.1
+merge_request: 53212
+author:
+type: changed
diff --git a/changelogs/unreleased/skr-ide.yml b/changelogs/unreleased/skr-ide.yml
new file mode 100644
index 00000000000..0af94cc0783
--- /dev/null
+++ b/changelogs/unreleased/skr-ide.yml
@@ -0,0 +1,5 @@
+---
+title: Removed ugly border around ellipsis dropdown Gitlab IDE
+merge_request: 53963
+author: Shubham Kumar @imskr
+type: fixed
diff --git a/changelogs/unreleased/skr-refactor-users.yml b/changelogs/unreleased/skr-refactor-users.yml
new file mode 100644
index 00000000000..c64cb1b6275
--- /dev/null
+++ b/changelogs/unreleased/skr-refactor-users.yml
@@ -0,0 +1,5 @@
+---
+title: Refactored admin user table headers
+merge_request: 52891
+author: Shubham Kumar (@imskr)
+type: changed
diff --git a/changelogs/unreleased/sselhorn-sentence-case-ui.yml b/changelogs/unreleased/sselhorn-sentence-case-ui.yml
new file mode 100644
index 00000000000..066ac6a77c4
--- /dev/null
+++ b/changelogs/unreleased/sselhorn-sentence-case-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to be sentence case
+merge_request: 53323
+author:
+type: other
diff --git a/changelogs/unreleased/support-ci-resource-group-in-cross-project-pipeline.yml b/changelogs/unreleased/support-ci-resource-group-in-cross-project-pipeline.yml
new file mode 100644
index 00000000000..b34a6ce32bc
--- /dev/null
+++ b/changelogs/unreleased/support-ci-resource-group-in-cross-project-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Pipeline-level concurrency control with Cross-Project/Parent-Child pipelines
+merge_request: 53007
+author:
+type: added
diff --git a/changelogs/unreleased/sy-add-shift-timeframe-index.yml b/changelogs/unreleased/sy-add-shift-timeframe-index.yml
new file mode 100644
index 00000000000..2c92c54d72a
--- /dev/null
+++ b/changelogs/unreleased/sy-add-shift-timeframe-index.yml
@@ -0,0 +1,5 @@
+---
+title: Add index to incident management oncall shifts table
+merge_request: 52961
+author:
+type: performance
diff --git a/changelogs/unreleased/sy-remove-alert-retriggering.yml b/changelogs/unreleased/sy-remove-alert-retriggering.yml
new file mode 100644
index 00000000000..0bc5f23119c
--- /dev/null
+++ b/changelogs/unreleased/sy-remove-alert-retriggering.yml
@@ -0,0 +1,6 @@
+---
+title: Stop notifying users of acknowledged alerts and stop changing the status of
+ acknowledged Prometheus alerts to Triggered
+merge_request: 53330
+author:
+type: changed
diff --git a/changelogs/unreleased/sy-remove-final-alerts-service-pieces.yml b/changelogs/unreleased/sy-remove-final-alerts-service-pieces.yml
new file mode 100644
index 00000000000..af5bfb319ef
--- /dev/null
+++ b/changelogs/unreleased/sy-remove-final-alerts-service-pieces.yml
@@ -0,0 +1,5 @@
+---
+title: Remove legacy alerts service data and table
+merge_request: 53534
+author:
+type: removed
diff --git a/changelogs/unreleased/sy-update-alerts-docs-urls.yml b/changelogs/unreleased/sy-update-alerts-docs-urls.yml
new file mode 100644
index 00000000000..8b23e7e0b87
--- /dev/null
+++ b/changelogs/unreleased/sy-update-alerts-docs-urls.yml
@@ -0,0 +1,5 @@
+---
+title: Link to more helpful docs from alert management pages
+merge_request: 51665
+author:
+type: changed
diff --git a/changelogs/unreleased/terraform-state-errors-graphql.yml b/changelogs/unreleased/terraform-state-errors-graphql.yml
new file mode 100644
index 00000000000..93b115ae93d
--- /dev/null
+++ b/changelogs/unreleased/terraform-state-errors-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Display Terraform list errors to user
+merge_request: 51397
+author:
+type: changed
diff --git a/changelogs/unreleased/terraform-states-migrate-task.yml b/changelogs/unreleased/terraform-states-migrate-task.yml
new file mode 100644
index 00000000000..8b1f967be88
--- /dev/null
+++ b/changelogs/unreleased/terraform-states-migrate-task.yml
@@ -0,0 +1,5 @@
+---
+title: Add rake task to migrate Terraform states to object storage
+merge_request: 50740
+author:
+type: added
diff --git a/changelogs/unreleased/test_update_merge_request_worker_performance.yml b/changelogs/unreleased/test_update_merge_request_worker_performance.yml
new file mode 100644
index 00000000000..6aea28b2be6
--- /dev/null
+++ b/changelogs/unreleased/test_update_merge_request_worker_performance.yml
@@ -0,0 +1,5 @@
+---
+title: Speed up update merge request worker by memoizing whether a push is a force or not
+merge_request: 53536
+author:
+type: performance
diff --git a/changelogs/unreleased/tor-defect-commit-message-placeholders.yml b/changelogs/unreleased/tor-defect-commit-message-placeholders.yml
new file mode 100644
index 00000000000..093dfdda81a
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-commit-message-placeholders.yml
@@ -0,0 +1,6 @@
+---
+title: Fill default commit message values in the placeholder instead of showing the
+ variable slugs
+merge_request: 52851
+author:
+type: fixed
diff --git a/changelogs/unreleased/tor-defect-untranslated-strings.yml b/changelogs/unreleased/tor-defect-untranslated-strings.yml
new file mode 100644
index 00000000000..0aebf4d0f23
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-untranslated-strings.yml
@@ -0,0 +1,5 @@
+---
+title: Switch to correct localization function that strips namespaces
+merge_request: 53244
+author:
+type: fixed
diff --git a/changelogs/unreleased/tor-defect-urlencode-image-diff-octothorpe.yml b/changelogs/unreleased/tor-defect-urlencode-image-diff-octothorpe.yml
new file mode 100644
index 00000000000..3ca89861bb3
--- /dev/null
+++ b/changelogs/unreleased/tor-defect-urlencode-image-diff-octothorpe.yml
@@ -0,0 +1,5 @@
+---
+title: Fix some image diff URLs with special characters causing the diff to not show
+merge_request: 53638
+author:
+type: fixed
diff --git a/changelogs/unreleased/tor-feature-highlight-too-large-diffs.yml b/changelogs/unreleased/tor-feature-highlight-too-large-diffs.yml
new file mode 100644
index 00000000000..1a26e2d4171
--- /dev/null
+++ b/changelogs/unreleased/tor-feature-highlight-too-large-diffs.yml
@@ -0,0 +1,5 @@
+---
+title: When an MR diff is Too Large, highlight it like other collapsed diffs
+merge_request: 52146
+author:
+type: other
diff --git a/changelogs/unreleased/track-5-mins-prod-app-usage.yml b/changelogs/unreleased/track-5-mins-prod-app-usage.yml
new file mode 100644
index 00000000000..db6eb85e9fd
--- /dev/null
+++ b/changelogs/unreleased/track-5-mins-prod-app-usage.yml
@@ -0,0 +1,5 @@
+---
+title: Track 5 mins production app template usage
+merge_request: 53618
+author:
+type: other
diff --git a/changelogs/unreleased/track-ci-minutes-monthly.yml b/changelogs/unreleased/track-ci-minutes-monthly.yml
new file mode 100644
index 00000000000..168e543916a
--- /dev/null
+++ b/changelogs/unreleased/track-ci-minutes-monthly.yml
@@ -0,0 +1,5 @@
+---
+title: Track CI minutes for namespace on a monthly basis
+merge_request: 52915
+author:
+type: added
diff --git a/changelogs/unreleased/track-project-ci-minutes-monthly.yml b/changelogs/unreleased/track-project-ci-minutes-monthly.yml
new file mode 100644
index 00000000000..1bdccff7790
--- /dev/null
+++ b/changelogs/unreleased/track-project-ci-minutes-monthly.yml
@@ -0,0 +1,5 @@
+---
+title: Track CI minutes on a monthly basis at project level
+merge_request: 53460
+author:
+type: added
diff --git a/changelogs/unreleased/ui-text-default-branch.yml b/changelogs/unreleased/ui-text-default-branch.yml
new file mode 100644
index 00000000000..7881d0f79ef
--- /dev/null
+++ b/changelogs/unreleased/ui-text-default-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 51658
+author:
+type: other
diff --git a/changelogs/unreleased/ui-text-protected-environments.yml b/changelogs/unreleased/ui-text-protected-environments.yml
new file mode 100644
index 00000000000..9f8fa029993
--- /dev/null
+++ b/changelogs/unreleased/ui-text-protected-environments.yml
@@ -0,0 +1,5 @@
+---
+title: Updated UI text to match style guidelines
+merge_request: 52152
+author:
+type: other
diff --git a/changelogs/unreleased/update-feature-flag-error-banner.yml b/changelogs/unreleased/update-feature-flag-error-banner.yml
new file mode 100644
index 00000000000..97921fa2db4
--- /dev/null
+++ b/changelogs/unreleased/update-feature-flag-error-banner.yml
@@ -0,0 +1,5 @@
+---
+title: Update styling of validation messages in New Feature Flag form
+merge_request: 52217
+author:
+type: changed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-25-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-25-0.yml
new file mode 100644
index 00000000000..8db1aa7cdb0
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-25-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.25.0
+merge_request: 52095
+author:
+type: other
diff --git a/changelogs/unreleased/update-input.yml b/changelogs/unreleased/update-input.yml
new file mode 100644
index 00000000000..8457008dff1
--- /dev/null
+++ b/changelogs/unreleased/update-input.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for search in frequent items search
+merge_request: 53368
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/update-starred-empty-state.yml b/changelogs/unreleased/update-starred-empty-state.yml
new file mode 100644
index 00000000000..66577393fa3
--- /dev/null
+++ b/changelogs/unreleased/update-starred-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Update starred empty state with new GitLab UI classes
+merge_request: 52467
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/update-table-pb.yml b/changelogs/unreleased/update-table-pb.yml
new file mode 100644
index 00000000000..e0b7c2caf32
--- /dev/null
+++ b/changelogs/unreleased/update-table-pb.yml
@@ -0,0 +1,5 @@
+---
+title: Update table and ellipsis button in performance bar metrics modal
+merge_request: 52762
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/update-workhorse-8-61-0.yml b/changelogs/unreleased/update-workhorse-8-61-0.yml
new file mode 100644
index 00000000000..05a8af6ac83
--- /dev/null
+++ b/changelogs/unreleased/update-workhorse-8-61-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Workhorse to v8.61.0
+merge_request: 52195
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-workhorse-8-63.yml b/changelogs/unreleased/update-workhorse-8-63.yml
new file mode 100644
index 00000000000..38f9e7cc101
--- /dev/null
+++ b/changelogs/unreleased/update-workhorse-8-63.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Workhorse to v8.63.0
+merge_request: 54315
+author:
+type: other
diff --git a/changelogs/unreleased/update_db_on_move_when_identical.yml b/changelogs/unreleased/update_db_on_move_when_identical.yml
new file mode 100644
index 00000000000..1356aea20af
--- /dev/null
+++ b/changelogs/unreleased/update_db_on_move_when_identical.yml
@@ -0,0 +1,5 @@
+---
+title: Update the database when moving repos between identical storages
+merge_request: 52743
+author:
+type: fixed
diff --git a/changelogs/unreleased/upgrade-cluster-applications-v0-40-0.yml b/changelogs/unreleased/upgrade-cluster-applications-v0-40-0.yml
new file mode 100644
index 00000000000..5551747ebeb
--- /dev/null
+++ b/changelogs/unreleased/upgrade-cluster-applications-v0-40-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump cluster applications CI template to v0.40.0
+merge_request: 53183
+author:
+type: other
diff --git a/changelogs/unreleased/upgrade-pages-1-35.yml b/changelogs/unreleased/upgrade-pages-1-35.yml
new file mode 100644
index 00000000000..584af2c23d6
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-1-35.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to v1.35.0
+merge_request: 54167
+author:
+type: added
diff --git a/changelogs/unreleased/use-segmented-controls-ci-cd-analytics.yml b/changelogs/unreleased/use-segmented-controls-ci-cd-analytics.yml
new file mode 100644
index 00000000000..61a9a0fc429
--- /dev/null
+++ b/changelogs/unreleased/use-segmented-controls-ci-cd-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Only Display One Chart at a Time
+merge_request: 52952
+author:
+type: changed
diff --git a/changelogs/unreleased/variables-in-include-enable.yml b/changelogs/unreleased/variables-in-include-enable.yml
new file mode 100644
index 00000000000..95a6c31ed1b
--- /dev/null
+++ b/changelogs/unreleased/variables-in-include-enable.yml
@@ -0,0 +1,5 @@
+---
+title: Support Project variables in `include` section of `gitlab-ci.yml`
+merge_request: 52108
+author:
+type: added
diff --git a/changelogs/unreleased/vs-fix-alignment-rebase-in-progress.yml b/changelogs/unreleased/vs-fix-alignment-rebase-in-progress.yml
new file mode 100644
index 00000000000..ed2989dfcb0
--- /dev/null
+++ b/changelogs/unreleased/vs-fix-alignment-rebase-in-progress.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment of 'Rebase in progress' label
+merge_request: 54189
+author:
+type: fixed
diff --git a/changelogs/unreleased/vs-fix-margin-for-rebase-based-workflows.yml b/changelogs/unreleased/vs-fix-margin-for-rebase-based-workflows.yml
new file mode 100644
index 00000000000..1815933af09
--- /dev/null
+++ b/changelogs/unreleased/vs-fix-margin-for-rebase-based-workflows.yml
@@ -0,0 +1,5 @@
+---
+title: Fix left margin of Merge button in FF merge mode
+merge_request: 53756
+author:
+type: fixed
diff --git a/changelogs/unreleased/wc-rsync-exclude-path.yml b/changelogs/unreleased/wc-rsync-exclude-path.yml
new file mode 100644
index 00000000000..9cc53674429
--- /dev/null
+++ b/changelogs/unreleased/wc-rsync-exclude-path.yml
@@ -0,0 +1,5 @@
+---
+title: Fix exclude path for backup rsync command
+merge_request: 52503
+author:
+type: fixed
diff --git a/changelogs/unreleased/workhorse-8-62-0.yml b/changelogs/unreleased/workhorse-8-62-0.yml
new file mode 100644
index 00000000000..054c7ca1540
--- /dev/null
+++ b/changelogs/unreleased/workhorse-8-62-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Workhorse to v8.62.0
+merge_request: 53864
+author:
+type: other
diff --git a/changelogs/unreleased/xanf-add-filtering-and-pagination-to-bulk-import.yml b/changelogs/unreleased/xanf-add-filtering-and-pagination-to-bulk-import.yml
new file mode 100644
index 00000000000..bf8345bd121
--- /dev/null
+++ b/changelogs/unreleased/xanf-add-filtering-and-pagination-to-bulk-import.yml
@@ -0,0 +1,5 @@
+---
+title: 'Add pagination and filtering to htoup imports'
+merge_request: 52340
+author:
+type: changed
diff --git a/changelogs/unreleased/yo-add-btn-default-ci.yml b/changelogs/unreleased/yo-add-btn-default-ci.yml
new file mode 100644
index 00000000000..9dfe87b37e0
--- /dev/null
+++ b/changelogs/unreleased/yo-add-btn-default-ci.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class for btn-build buttons
+merge_request: 52093
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-btn-default-repo.yml b/changelogs/unreleased/yo-btn-default-repo.yml
new file mode 100644
index 00000000000..7f1c972b007
--- /dev/null
+++ b/changelogs/unreleased/yo-btn-default-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default class to button in project breadcrumb
+merge_request: 51910
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-btn-info-fix.yml b/changelogs/unreleased/yo-btn-info-fix.yml
new file mode 100644
index 00000000000..893107094ee
--- /dev/null
+++ b/changelogs/unreleased/yo-btn-info-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Move btn-primary to btn-confirm class as a part of Pajamas migration
+merge_request: 52090
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/yo-canary-shortcut.yml b/changelogs/unreleased/yo-canary-shortcut.yml
new file mode 100644
index 00000000000..46321e95b5d
--- /dev/null
+++ b/changelogs/unreleased/yo-canary-shortcut.yml
@@ -0,0 +1,5 @@
+---
+title: Keyboard shortcut for switching to GitLab next (Canary)
+merge_request: 51834
+author: Yogi (@yo)
+type: added
diff --git a/changelogs/unreleased/yo-empty-labels-container.yml b/changelogs/unreleased/yo-empty-labels-container.yml
new file mode 100644
index 00000000000..bbd5843c301
--- /dev/null
+++ b/changelogs/unreleased/yo-empty-labels-container.yml
@@ -0,0 +1,5 @@
+---
+title: Update empty labels container background color
+merge_request: 51792
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-empty-milestone.yml b/changelogs/unreleased/yo-empty-milestone.yml
new file mode 100644
index 00000000000..237942aedd8
--- /dev/null
+++ b/changelogs/unreleased/yo-empty-milestone.yml
@@ -0,0 +1,5 @@
+---
+title: Add empty state placeholder for milestones
+merge_request: 51887
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-fix-alertpage-alignment.yml b/changelogs/unreleased/yo-fix-alertpage-alignment.yml
new file mode 100644
index 00000000000..630981b6d3d
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-alertpage-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment and font issues in project operations settings page
+merge_request: 51825
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-fix-border-radius.yml b/changelogs/unreleased/yo-fix-border-radius.yml
new file mode 100644
index 00000000000..f63d79b4d49
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-border-radius.yml
@@ -0,0 +1,5 @@
+---
+title: Fix top border-radius of the login box
+merge_request: 51950
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-fix-mr-edit-button.yml b/changelogs/unreleased/yo-fix-mr-edit-button.yml
new file mode 100644
index 00000000000..c26888e2b96
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-mr-edit-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add btn-default to MR edit button
+merge_request: 51879
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-fix-notes-bb.yml b/changelogs/unreleased/yo-fix-notes-bb.yml
new file mode 100644
index 00000000000..385e3ca6fee
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-notes-bb.yml
@@ -0,0 +1,5 @@
+---
+title: Fix border bottom color collapsed replies
+merge_request: 51871
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-fix-social-buttons.yml b/changelogs/unreleased/yo-fix-social-buttons.yml
new file mode 100644
index 00000000000..871abe9e132
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-social-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Move Social connect button to new GitLab UI
+merge_request: 51835
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-fix-toggle-collapse-replies.yml b/changelogs/unreleased/yo-fix-toggle-collapse-replies.yml
new file mode 100644
index 00000000000..272cff27659
--- /dev/null
+++ b/changelogs/unreleased/yo-fix-toggle-collapse-replies.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alignment of chevron-down icon in toggle replies
+merge_request: 51872
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-gl-badge-milestone.yml b/changelogs/unreleased/yo-gl-badge-milestone.yml
new file mode 100644
index 00000000000..a6cc1c9a77b
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge-milestone.yml
@@ -0,0 +1,5 @@
+---
+title: Update milestone badge to gl-badge
+merge_request: 51794
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge-protected-branch.yml b/changelogs/unreleased/yo-gl-badge-protected-branch.yml
new file mode 100644
index 00000000000..52513d57679
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge-protected-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for badge and button in project's protected branch settings
+merge_request: 52207
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge-user-emails.yml b/changelogs/unreleased/yo-gl-badge-user-emails.yml
new file mode 100644
index 00000000000..d4c529d4aab
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge-user-emails.yml
@@ -0,0 +1,5 @@
+---
+title: Move email badges to new GitLab UI badges
+merge_request: 51915
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-badge-users-admin.yml b/changelogs/unreleased/yo-gl-badge-users-admin.yml
new file mode 100644
index 00000000000..08b371e54e1
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-badge-users-admin.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI badge for users in the admin page
+merge_request: 52289
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-admin.yml b/changelogs/unreleased/yo-gl-button-admin.yml
new file mode 100644
index 00000000000..bd438854fac
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-admin.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons in admin settings
+merge_request: 51789
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-create-file-mr.yml b/changelogs/unreleased/yo-gl-button-create-file-mr.yml
new file mode 100644
index 00000000000..670edb8d862
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-create-file-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI for create file button in MR
+merge_request: 51795
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-issuable-create-button.yml b/changelogs/unreleased/yo-gl-button-issuable-create-button.yml
new file mode 100644
index 00000000000..06301056054
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-issuable-create-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button to new issues and MR page
+merge_request: 51295
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-issues.yml b/changelogs/unreleased/yo-gl-button-issues.yml
new file mode 100644
index 00000000000..7a68ea32d7f
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for subscribe buttons in issues
+merge_request: 52401
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-mirror-update.yml b/changelogs/unreleased/yo-gl-button-mirror-update.yml
new file mode 100644
index 00000000000..a0d2f27f122
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-mirror-update.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI style to mirror update button and add space after icon
+merge_request: 51808
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-project-page.yml b/changelogs/unreleased/yo-gl-button-project-page.yml
new file mode 100644
index 00000000000..4002da78ae4
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-project-page.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button to nav buttons in the project page
+merge_request: 51427
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-promotion.yml b/changelogs/unreleased/yo-gl-button-promotion.yml
new file mode 100644
index 00000000000..a7d1e131a64
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-promotion.yml
@@ -0,0 +1,5 @@
+---
+title: Add `gl-button` to promotion buttons on issue sidebar
+merge_request: 51287
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-button-ra.yml b/changelogs/unreleased/yo-gl-button-ra.yml
new file mode 100644
index 00000000000..a992682a35d
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-ra.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for report abuse button
+merge_request: 52049
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-gl-button-revoke-button.yml b/changelogs/unreleased/yo-gl-button-revoke-button.yml
new file mode 100644
index 00000000000..9d5e8c61e54
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-button-revoke-button.yml
@@ -0,0 +1,5 @@
+---
+title: Add gl-button to personal access token page
+merge_request: 51294
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-card-admin.yml b/changelogs/unreleased/yo-gl-card-admin.yml
new file mode 100644
index 00000000000..3874bd7949b
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-card-admin.yml
@@ -0,0 +1,5 @@
+---
+title: Move user action card to new GitLab UI card in admin
+merge_request: 51914
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-input-admin-application_settings.yml b/changelogs/unreleased/yo-gl-input-admin-application_settings.yml
new file mode 100644
index 00000000000..ff5a7b8d1e6
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-input-admin-application_settings.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for inputs in admin/application_settings directory
+merge_request: 52402
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-input-admin-users.yml b/changelogs/unreleased/yo-gl-input-admin-users.yml
new file mode 100644
index 00000000000..8e13e24e09e
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-input-admin-users.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for inputs in admin/users directory
+merge_request: 52290
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-input.yml b/changelogs/unreleased/yo-gl-new-input.yml
new file mode 100644
index 00000000000..13381f713e7
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-input.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for form inputs project settings page
+merge_request: 52097
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-ui-admin-appearance.yml b/changelogs/unreleased/yo-gl-new-ui-admin-appearance.yml
new file mode 100644
index 00000000000..b7e5a8ad9a7
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-ui-admin-appearance.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in admin/appearance
+merge_request: 52409
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-ui-admin-applications.yml b/changelogs/unreleased/yo-gl-new-ui-admin-applications.yml
new file mode 100644
index 00000000000..bfe4acabedf
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-ui-admin-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in admin/applications
+merge_request: 52410
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-ui-admin-broadcast-messages.yml b/changelogs/unreleased/yo-gl-new-ui-admin-broadcast-messages.yml
new file mode 100644
index 00000000000..583398df940
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-ui-admin-broadcast-messages.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in admin/broadcast_messages
+merge_request: 52411
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-ui-admin-hooks.yml b/changelogs/unreleased/yo-gl-new-ui-admin-hooks.yml
new file mode 100644
index 00000000000..ce3643057e4
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-ui-admin-hooks.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in admin/hooks
+merge_request: 52412
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-ui-admin-labels.yml b/changelogs/unreleased/yo-gl-new-ui-admin-labels.yml
new file mode 100644
index 00000000000..5ca3acdf0eb
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-ui-admin-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input field in admin/labels
+merge_request: 52413
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-gl-new-ui-admin-license.yml b/changelogs/unreleased/yo-gl-new-ui-admin-license.yml
new file mode 100644
index 00000000000..6e5cfe57fd6
--- /dev/null
+++ b/changelogs/unreleased/yo-gl-new-ui-admin-license.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for buttons and card in admin/license
+merge_request: 52408
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-master-patch-87785.yml b/changelogs/unreleased/yo-master-patch-87785.yml
new file mode 100644
index 00000000000..fc4578b621a
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-87785.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI button styles to button _blank_state_ee_trial
+merge_request: 51778
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-move-to-gl-button.yml b/changelogs/unreleased/yo-move-to-gl-button.yml
new file mode 100644
index 00000000000..68120ce9286
--- /dev/null
+++ b/changelogs/unreleased/yo-move-to-gl-button.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate old button classes to our Pajamas style GitLab button in multiple areas
+merge_request: 51826
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-new-admin-header.yml b/changelogs/unreleased/yo-new-admin-header.yml
new file mode 100644
index 00000000000..516e989fc30
--- /dev/null
+++ b/changelogs/unreleased/yo-new-admin-header.yml
@@ -0,0 +1,5 @@
+---
+title: Admin dashboard basic stats redesign
+merge_request: 52176
+author: Yogi (@yo)
+type: changed
diff --git a/changelogs/unreleased/yo-new-input-auth.yml b/changelogs/unreleased/yo-new-input-auth.yml
new file mode 100644
index 00000000000..976287241ca
--- /dev/null
+++ b/changelogs/unreleased/yo-new-input-auth.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for input fields in auth screens
+merge_request: 52167
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-pb-improve.yml b/changelogs/unreleased/yo-pb-improve.yml
new file mode 100644
index 00000000000..5d3ba5e6618
--- /dev/null
+++ b/changelogs/unreleased/yo-pb-improve.yml
@@ -0,0 +1,5 @@
+---
+title: Improve Performance bar design
+merge_request: 51788
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-question-icon.yml b/changelogs/unreleased/yo-question-icon.yml
new file mode 100644
index 00000000000..2bc997a74aa
--- /dev/null
+++ b/changelogs/unreleased/yo-question-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Update (?) link to sprite question icon
+merge_request: 52655
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-remove-activity-container.yml b/changelogs/unreleased/yo-remove-activity-container.yml
new file mode 100644
index 00000000000..b16b12ff50d
--- /dev/null
+++ b/changelogs/unreleased/yo-remove-activity-container.yml
@@ -0,0 +1,5 @@
+---
+title: Remove container_class in project activity which removes extra padding
+merge_request: 51878
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-remove-space.yml b/changelogs/unreleased/yo-remove-space.yml
new file mode 100644
index 00000000000..c25daa54e67
--- /dev/null
+++ b/changelogs/unreleased/yo-remove-space.yml
@@ -0,0 +1,5 @@
+---
+title: Remove huge bottom margin for expand file button
+merge_request: 51802
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-remove-top-border-usage-quotos.yml b/changelogs/unreleased/yo-remove-top-border-usage-quotos.yml
new file mode 100644
index 00000000000..beb7fe11860
--- /dev/null
+++ b/changelogs/unreleased/yo-remove-top-border-usage-quotos.yml
@@ -0,0 +1,5 @@
+---
+title: Remove extra border-top on pipeline quota in the settings page
+merge_request: 52059
+author: Yogi (@yo)
+type: fixed
diff --git a/changelogs/unreleased/yo-update-gl-button.yml b/changelogs/unreleased/yo-update-gl-button.yml
new file mode 100644
index 00000000000..8353c8bb288
--- /dev/null
+++ b/changelogs/unreleased/yo-update-gl-button.yml
@@ -0,0 +1,5 @@
+---
+title: Apply new GitLab UI for commit browse file button
+merge_request: 51805
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/yo-verified-gl-badge.yml b/changelogs/unreleased/yo-verified-gl-badge.yml
new file mode 100644
index 00000000000..ec2921c8ea0
--- /dev/null
+++ b/changelogs/unreleased/yo-verified-gl-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GitLab UI to email status badge
+merge_request: 51916
+author: Yogi (@yo)
+type: other
diff --git a/changelogs/unreleased/zj-no-duplicate-deployments.yml b/changelogs/unreleased/zj-no-duplicate-deployments.yml
new file mode 100644
index 00000000000..13d9a13e8fe
--- /dev/null
+++ b/changelogs/unreleased/zj-no-duplicate-deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Deployments::CreateService executions are idempotent for duplicate params
+merge_request: 47610
+author:
+type: added
diff --git a/config.ru b/config.ru
index 750c84f7642..0c50b3fdf6f 100644
--- a/config.ru
+++ b/config.ru
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This file is used by Rack-based servers to start the application.
if defined?(Unicorn)
@@ -22,12 +24,6 @@ def master_process?
end
warmup do |app|
- # The following is necessary to ensure stale Prometheus metrics don't accumulate over time.
- # It needs to be done as early as here to ensure metrics files aren't deleted.
- # After we hit our app in `warmup`, first metrics and corresponding files already being created,
- # for example in `lib/gitlab/metrics/requests_rack_middleware.rb`.
- Prometheus::CleanupMultiprocDirService.new.execute if master_process?
-
client = Rack::MockRequest.new(app)
client.get('/')
end
diff --git a/config/application.rb b/config/application.rb
index a8b6bc937cf..7e15d02a6da 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -176,12 +176,15 @@ module Gitlab
config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css"
config.assets.precompile << "page_bundles/_mixins_and_variables_and_functions.css"
+ config.assets.precompile << "page_bundles/admin/application_settings_metrics_and_profiling.css"
+ config.assets.precompile << "page_bundles/admin/jobs_index.css"
config.assets.precompile << "page_bundles/alert_management_details.css"
config.assets.precompile << "page_bundles/alert_management_settings.css"
config.assets.precompile << "page_bundles/boards.css"
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/security_discover.css"
config.assets.precompile << "page_bundles/dev_ops_report.css"
config.assets.precompile << "page_bundles/environments.css"
config.assets.precompile << "page_bundles/epics.css"
@@ -287,6 +290,14 @@ module Gitlab
methods: :any,
expose: headers_to_expose
end
+
+ # Cross-origin requests must be enabled for the Authorization code with PKCE OAuth flow when used from a browser.
+ allow do
+ origins '*'
+ resource '/oauth/token',
+ credentials: false,
+ methods: [:post]
+ end
end
# Use caching across all environments
@@ -368,30 +379,5 @@ module Gitlab
end
end
end
-
- config.after_initialize do
- # Devise (see initializers/8_devise.rb) already reloads routes if
- # eager loading is enabled, so don't do this twice since it's
- # expensive.
- Rails.application.reload_routes! unless config.eager_load
-
- project_url_helpers = Module.new do
- extend ActiveSupport::Concern
-
- Gitlab::Application.routes.named_routes.helper_names.each do |name|
- next unless name.include?('namespace_project')
-
- define_method(name.sub('namespace_project', 'project')) do |project, *args|
- send(name, project&.namespace, project, *args)
- end
- end
- end
-
- # We add the MilestonesRoutingHelper because we know that this does not
- # conflict with the methods defined in `project_url_helpers`, and we want
- # these methods available in the same places.
- Gitlab::Routing.add_helpers(project_url_helpers)
- Gitlab::Routing.add_helpers(TimeboxesRoutingHelper)
- end
end
end
diff --git a/config/boot.rb b/config/boot.rb
index da4e6b7290c..41bf7953737 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
# Set up gems listed in the Gemfile.
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index c12ede63fba..774254d2ff1 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -310,7 +310,7 @@
- dompurify
- Apache-2.0
- :who: Lukas Eipert
- :why: "https://github.com/cure53/DOMPurify/blob/main/LICENSE and https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31928#note_346604841"
+ :why: https://github.com/cure53/DOMPurify/blob/main/LICENSE and https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31928#note_346604841
:versions: []
:when: 2020-08-13 13:42:46.508082000 Z
- - :permit
@@ -325,3 +325,9 @@
:why: Used to generate documentation. https://pypi.org/project/docutils/0.13.1/
:versions: []
:when: 2020-10-05 20:22:55.955189491 Z
+- - :permit
+ - WTFPL
+ - :who: Stan Hu
+ :why: https://github.com/xijo/reverse_markdown/blob/master/LICENSE
+ :versions: []
+ :when: 2021-02-03 08:47:28.792907000 Z
diff --git a/config/environment.rb b/config/environment.rb
index 426333bb469..d5abe55806c 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Load the Rails application.
require_relative 'application'
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 31a3af77ba1..50d394859bc 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb
@@ -9,7 +11,13 @@ Rails.application.configure do
# Show full error reports and disable caching
config.active_record.verbose_query_logs = true
config.consider_all_requests_local = true
- config.action_controller.perform_caching = false
+
+ if Rails.root.join('tmp', 'caching-dev.txt').exist?
+ config.action_controller.perform_caching = true
+ config.action_controller.enable_fragment_cache_logging = true
+ else
+ config.action_controller.perform_caching = false
+ end
# Show a warning when a large data set is loaded into memory
config.active_record.warn_on_records_fetched_greater_than = 1000
diff --git a/config/environments/production.rb b/config/environments/production.rb
index d9b3ee354b0..e1a7db8d860 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 4e359cd308c..2c6ab3bbc79 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'gitlab/testing/request_blocker_middleware'
require 'gitlab/testing/robots_blocker_middleware'
require 'gitlab/testing/request_inspector_middleware'
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index 805cc3b50a3..5c7ae175d1d 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -66,6 +66,7 @@
- jenkins_importer
- jira_importer
- kubernetes_management
+- license
- license_compliance
- live_preview
- load_testing
@@ -84,7 +85,6 @@
- privacy_control_center
- product_analytics
- projects
-- provision
- purchase
- quality_management
- release_evidence
@@ -113,6 +113,7 @@
- usability_testing
- usage_ping
- users
+- utilization
- value_stream_management
- vulnerability_database
- vulnerability_management
diff --git a/config/feature_flags/development/add_issues_button.yml b/config/feature_flags/development/add_issues_button.yml
index cc4727a29c4..12a6ef61bba 100644
--- a/config/feature_flags/development/add_issues_button.yml
+++ b/config/feature_flags/development/add_issues_button.yml
@@ -1,7 +1,7 @@
---
name: add_issues_button
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47898
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292803
milestone: '13.6'
type: development
group: group::project management
diff --git a/config/feature_flags/development/ajax_new_deploy_token.yml b/config/feature_flags/development/ajax_new_deploy_token.yml
index 9a6826e6993..6b0d9697006 100644
--- a/config/feature_flags/development/ajax_new_deploy_token.yml
+++ b/config/feature_flags/development/ajax_new_deploy_token.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27141
rollout_issue_url:
milestone: '12.10'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: false
diff --git a/config/feature_flags/development/allow_group_deploy_token.yml b/config/feature_flags/development/allow_group_deploy_token.yml
index 91437352ad8..83f8f86b02c 100644
--- a/config/feature_flags/development/allow_group_deploy_token.yml
+++ b/config/feature_flags/development/allow_group_deploy_token.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23460
rollout_issue_url:
milestone: '12.8'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/api_always_use_application_json.yml b/config/feature_flags/development/api_always_use_application_json.yml
new file mode 100644
index 00000000000..4405ef64012
--- /dev/null
+++ b/config/feature_flags/development/api_always_use_application_json.yml
@@ -0,0 +1,8 @@
+---
+name: api_always_use_application_json
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42229
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270067
+milestone: '13.6'
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/api_json_content_type.yml b/config/feature_flags/development/api_json_content_type.yml
deleted file mode 100644
index 5653a834e62..00000000000
--- a/config/feature_flags/development/api_json_content_type.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: api_json_content_type
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42229
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/270067
-milestone: '13.6'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/approval_suggestions.yml b/config/feature_flags/development/approval_suggestions.yml
deleted file mode 100644
index 14961d2e248..00000000000
--- a/config/feature_flags/development/approval_suggestions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: approval_suggestions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38992
-rollout_issue_url:
-milestone: '13.3'
-type: development
-group: group::composition analysis
-default_enabled: true
diff --git a/config/feature_flags/development/archive_rate_limit.yml b/config/feature_flags/development/archive_rate_limit.yml
index ee4af4d2835..3318d7fa939 100644
--- a/config/feature_flags/development/archive_rate_limit.yml
+++ b/config/feature_flags/development/archive_rate_limit.yml
@@ -1,8 +1,8 @@
---
name: archive_rate_limit
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25750
rollout_issue_url:
-milestone:
+milestone: '12.9'
type: development
-group:
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/development/batch_suggestions.yml b/config/feature_flags/development/batch_suggestions.yml
index f2bb0a8f9cb..6a13094f0ab 100644
--- a/config/feature_flags/development/batch_suggestions.yml
+++ b/config/feature_flags/development/batch_suggestions.yml
@@ -1,8 +1,8 @@
---
name: batch_suggestions
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34782
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320755
+milestone: '13.1'
type: development
-group:
+group: group::code review
default_enabled: true
diff --git a/config/feature_flags/development/board_new_list.yml b/config/feature_flags/development/board_new_list.yml
new file mode 100644
index 00000000000..e80da8c554f
--- /dev/null
+++ b/config/feature_flags/development/board_new_list.yml
@@ -0,0 +1,8 @@
+---
+name: board_new_list
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52061
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299366
+milestone: '13.8'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/branches_pagination_without_count.yml b/config/feature_flags/development/branches_pagination_without_count.yml
new file mode 100644
index 00000000000..e342f302b2c
--- /dev/null
+++ b/config/feature_flags/development/branches_pagination_without_count.yml
@@ -0,0 +1,8 @@
+---
+name: branches_pagination_without_count
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50759
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/development/builds.yml b/config/feature_flags/development/builds.yml
deleted file mode 100644
index 9787c2b1e20..00000000000
--- a/config/feature_flags/development/builds.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: builds
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/cached_sidebar_open_issues_count.yml b/config/feature_flags/development/cached_sidebar_open_issues_count.yml
new file mode 100644
index 00000000000..e94566057fc
--- /dev/null
+++ b/config/feature_flags/development/cached_sidebar_open_issues_count.yml
@@ -0,0 +1,8 @@
+---
+name: cached_sidebar_open_issues_count
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49739
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::product planning
+default_enabled: false
diff --git a/config/feature_flags/development/caching_experiments.yml b/config/feature_flags/development/caching_experiments.yml
deleted file mode 100644
index 3d540aca476..00000000000
--- a/config/feature_flags/development/caching_experiments.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: caching_experiments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49669
-rollout_issue_url:
-milestone: '13.7'
-type: development
-group: group::adoption
-default_enabled: false
diff --git a/config/feature_flags/development/canary_ingress_weight_control.yml b/config/feature_flags/development/canary_ingress_weight_control.yml
index b2b5a3e5dfa..66d3f2de0ea 100644
--- a/config/feature_flags/development/canary_ingress_weight_control.yml
+++ b/config/feature_flags/development/canary_ingress_weight_control.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43816
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/260295
milestone: '13.5'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/ci_accept_frontend_prometheus_metrics.yml b/config/feature_flags/development/ci_accept_frontend_prometheus_metrics.yml
new file mode 100644
index 00000000000..b795b2505d8
--- /dev/null
+++ b/config/feature_flags/development/ci_accept_frontend_prometheus_metrics.yml
@@ -0,0 +1,8 @@
+---
+name: ci_accept_frontend_prometheus_metrics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52820
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300770
+milestone: '13.9'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml b/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
deleted file mode 100644
index 1d33a162445..00000000000
--- a/config/feature_flags/development/ci_allow_failure_with_exit_codes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_allow_failure_with_exit_codes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49145
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292024
-milestone: '13.7'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_auto_cancel_all_pipelines.yml b/config/feature_flags/development/ci_auto_cancel_all_pipelines.yml
deleted file mode 100644
index 7dfc6146b08..00000000000
--- a/config/feature_flags/development/ci_auto_cancel_all_pipelines.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_auto_cancel_all_pipelines
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46686
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/275997
-milestone: '13.6'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_config_merged_tab.yml b/config/feature_flags/development/ci_config_merged_tab.yml
new file mode 100644
index 00000000000..8ccdf105951
--- /dev/null
+++ b/config/feature_flags/development/ci_config_merged_tab.yml
@@ -0,0 +1,8 @@
+---
+name: ci_config_merged_tab
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53299
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/301103
+milestone: '13.9'
+type: development
+group: group::pipeline authoring
+default_enabled: true
diff --git a/config/feature_flags/development/ci_disable_validates_dependencies.yml b/config/feature_flags/development/ci_disable_validates_dependencies.yml
deleted file mode 100644
index fd5b3d41eef..00000000000
--- a/config/feature_flags/development/ci_disable_validates_dependencies.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_disable_validates_dependencies
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14009
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257847
-milestone: '10.3'
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml b/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
index 4b134457a20..3962af65540 100644
--- a/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
+++ b/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40724
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235119
milestone: '13.4'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: false
diff --git a/config/feature_flags/development/ci_instance_variables_ui.yml b/config/feature_flags/development/ci_instance_variables_ui.yml
index f5cd2d21bd1..73bc0346818 100644
--- a/config/feature_flags/development/ci_instance_variables_ui.yml
+++ b/config/feature_flags/development/ci_instance_variables_ui.yml
@@ -1,7 +1,7 @@
---
name: ci_instance_variables_ui
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33510
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299879
milestone: '13.1'
type: development
group: group::continuous integration
diff --git a/config/feature_flags/development/ci_job_jwt.yml b/config/feature_flags/development/ci_job_jwt.yml
index cba278c9103..ef2f43175ed 100644
--- a/config/feature_flags/development/ci_job_jwt.yml
+++ b/config/feature_flags/development/ci_job_jwt.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28063
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/207125
milestone: '12.10'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/ci_jwt_include_environment.yml b/config/feature_flags/development/ci_jwt_include_environment.yml
new file mode 100644
index 00000000000..ea55ce0c569
--- /dev/null
+++ b/config/feature_flags/development/ci_jwt_include_environment.yml
@@ -0,0 +1,8 @@
+---
+name: ci_jwt_include_environment
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53431
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321206
+milestone: '13.9'
+type: development
+group: group::configure
+default_enabled: false
diff --git a/config/feature_flags/development/ci_jwt_signing_key.yml b/config/feature_flags/development/ci_jwt_signing_key.yml
index 4f37b49d797..021f4e49e41 100644
--- a/config/feature_flags/development/ci_jwt_signing_key.yml
+++ b/config/feature_flags/development/ci_jwt_signing_key.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34249
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258546
milestone: '13.6'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/ci_live_trace_use_fog_attributes.yml b/config/feature_flags/development/ci_live_trace_use_fog_attributes.yml
deleted file mode 100644
index 20a38d77407..00000000000
--- a/config/feature_flags/development/ci_live_trace_use_fog_attributes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_live_trace_use_fog_attributes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47536
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285079
-milestone: '13.6'
-type: development
-group: group::testing
-default_enabled: true
diff --git a/config/feature_flags/development/ci_mini_pipeline_gl_dropdown.yml b/config/feature_flags/development/ci_mini_pipeline_gl_dropdown.yml
new file mode 100644
index 00000000000..50e1e6715df
--- /dev/null
+++ b/config/feature_flags/development/ci_mini_pipeline_gl_dropdown.yml
@@ -0,0 +1,8 @@
+---
+name: ci_mini_pipeline_gl_dropdown
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52821
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300400
+milestone: '13.9'
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_open_merge_requests.yml b/config/feature_flags/development/ci_pipeline_open_merge_requests.yml
deleted file mode 100644
index 7e2ae1edd34..00000000000
--- a/config/feature_flags/development/ci_pipeline_open_merge_requests.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pipeline_open_merge_requests
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38673
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292727
-milestone: '13.7'
-group: group::memory
-type: development
-default_enabled: true
diff --git a/config/feature_flags/development/ci_store_pipeline_messages.yml b/config/feature_flags/development/ci_store_pipeline_messages.yml
index ae20b11f79c..702e4d891a9 100644
--- a/config/feature_flags/development/ci_store_pipeline_messages.yml
+++ b/config/feature_flags/development/ci_store_pipeline_messages.yml
@@ -1,7 +1,7 @@
---
name: ci_store_pipeline_messages
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33762
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/224199
milestone: '13.2'
type: development
group: group::continuous integration
diff --git a/config/feature_flags/development/ci_synchronous_artifact_parsing.yml b/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
index a5cf148559f..ab3a35e409b 100644
--- a/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
+++ b/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26247
rollout_issue_url:
milestone: '12.9'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/ci_trigger_payload_into_pipeline.yml b/config/feature_flags/development/ci_trigger_payload_into_pipeline.yml
new file mode 100644
index 00000000000..93dd7113f2a
--- /dev/null
+++ b/config/feature_flags/development/ci_trigger_payload_into_pipeline.yml
@@ -0,0 +1,8 @@
+---
+name: ci_trigger_payload_into_pipeline
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53837
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321027
+milestone: '13.9'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_validate_build_dependencies.yml b/config/feature_flags/development/ci_validate_build_dependencies.yml
new file mode 100644
index 00000000000..885bdcf0c20
--- /dev/null
+++ b/config/feature_flags/development/ci_validate_build_dependencies.yml
@@ -0,0 +1,8 @@
+---
+name: ci_validate_build_dependencies
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14009
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257852
+milestone: '10.3'
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/ci_validate_build_dependencies_override.yml b/config/feature_flags/development/ci_validate_build_dependencies_override.yml
new file mode 100644
index 00000000000..bce4b88ca39
--- /dev/null
+++ b/config/feature_flags/development/ci_validate_build_dependencies_override.yml
@@ -0,0 +1,8 @@
+---
+name: ci_validate_build_dependencies_override
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14009
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257852
+milestone: '10.3'
+type: development
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/clear_status_with_quick_options.yml b/config/feature_flags/development/clear_status_with_quick_options.yml
new file mode 100644
index 00000000000..3a8af1569c2
--- /dev/null
+++ b/config/feature_flags/development/clear_status_with_quick_options.yml
@@ -0,0 +1,8 @@
+---
+name: clear_status_with_quick_options
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53620
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320777
+milestone: '13.9'
+type: development
+group: group::optimize
+default_enabled: true
diff --git a/config/feature_flags/development/codequality_backend_comparison.yml b/config/feature_flags/development/codequality_backend_comparison.yml
new file mode 100644
index 00000000000..f7c3c14f674
--- /dev/null
+++ b/config/feature_flags/development/codequality_backend_comparison.yml
@@ -0,0 +1,8 @@
+---
+name: codequality_backend_comparison
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53068
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300796
+milestone: '13.9'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/confidential_notes.yml b/config/feature_flags/development/confidential_notes.yml
new file mode 100644
index 00000000000..4e9add5eb3c
--- /dev/null
+++ b/config/feature_flags/development/confidential_notes.yml
@@ -0,0 +1,8 @@
+---
+name: confidential_notes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52949
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/207474
+milestone: '13.9'
+type: development
+group: group::product planning
+default_enabled: false
diff --git a/config/feature_flags/development/context_commits.yml b/config/feature_flags/development/context_commits.yml
index 270a058558b..521ab5d0a6f 100644
--- a/config/feature_flags/development/context_commits.yml
+++ b/config/feature_flags/development/context_commits.yml
@@ -1,8 +1,8 @@
---
name: context_commits
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23701
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320757
+milestone: '12.8'
type: development
-group:
+group: group::code review
default_enabled: true
diff --git a/config/feature_flags/development/core_security_mr_widget.yml b/config/feature_flags/development/core_security_mr_widget.yml
deleted file mode 100644
index dfeb30cd83a..00000000000
--- a/config/feature_flags/development/core_security_mr_widget.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: core_security_mr_widget
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44639
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249543
-milestone: '13.5'
-type: development
-group: group::static analysis
-default_enabled: true
diff --git a/config/feature_flags/development/core_security_mr_widget_downloads.yml b/config/feature_flags/development/core_security_mr_widget_downloads.yml
deleted file mode 100644
index d89fbc302b3..00000000000
--- a/config/feature_flags/development/core_security_mr_widget_downloads.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: core_security_mr_widget_downloads
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48769
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273418
-milestone: '13.7'
-type: development
-group: group::static analysis
-default_enabled: true
diff --git a/config/feature_flags/development/coverage_data_new_finder.yml b/config/feature_flags/development/coverage_data_new_finder.yml
new file mode 100644
index 00000000000..a7c283ce3db
--- /dev/null
+++ b/config/feature_flags/development/coverage_data_new_finder.yml
@@ -0,0 +1,8 @@
+---
+name: coverage_data_new_finder
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53670
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/301093
+milestone: '13.9'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/dag_pipeline_tab.yml b/config/feature_flags/development/dag_pipeline_tab.yml
deleted file mode 100644
index f2ae897df8e..00000000000
--- a/config/feature_flags/development/dag_pipeline_tab.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: dag_pipeline_tab
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30310
-rollout_issue_url:
-milestone: '13.0'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/database_sourced_aggregated_metrics.yml b/config/feature_flags/development/database_sourced_aggregated_metrics.yml
new file mode 100644
index 00000000000..d971ad0b9d2
--- /dev/null
+++ b/config/feature_flags/development/database_sourced_aggregated_metrics.yml
@@ -0,0 +1,8 @@
+---
+name: database_sourced_aggregated_metrics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52784
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300411
+milestone: '13.9'
+type: development
+group: group::product intelligence
+default_enabled: false
diff --git a/config/feature_flags/development/default_merge_ref_for_diffs.yml b/config/feature_flags/development/default_merge_ref_for_diffs.yml
index 1058cff5e8f..f197044d47f 100644
--- a/config/feature_flags/development/default_merge_ref_for_diffs.yml
+++ b/config/feature_flags/development/default_merge_ref_for_diffs.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276917
milestone: '13.4'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/deploy_keys_on_protected_branches.yml b/config/feature_flags/development/deploy_keys_on_protected_branches.yml
deleted file mode 100644
index 438726c0315..00000000000
--- a/config/feature_flags/development/deploy_keys_on_protected_branches.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: deploy_keys_on_protected_branches
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35638
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247866
-milestone: '13.5'
-type: development
-group: group::progressive delivery
-default_enabled: false
diff --git a/config/feature_flags/development/deploy_tokens_api.yml b/config/feature_flags/development/deploy_tokens_api.yml
deleted file mode 100644
index b9741e05d7e..00000000000
--- a/config/feature_flags/development/deploy_tokens_api.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: deploy_tokens_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25219
-rollout_issue_url:
-milestone: '12.9'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/disable_git_http_fetch_writes.yml b/config/feature_flags/development/disable_git_http_fetch_writes.yml
new file mode 100644
index 00000000000..aba9df97d95
--- /dev/null
+++ b/config/feature_flags/development/disable_git_http_fetch_writes.yml
@@ -0,0 +1,8 @@
+---
+name: disable_git_http_fetch_writes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54322
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/883
+milestone: '13.9'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/disable_ssh_key_used_tracking.yml b/config/feature_flags/development/disable_ssh_key_used_tracking.yml
new file mode 100644
index 00000000000..2efd38b073a
--- /dev/null
+++ b/config/feature_flags/development/disable_ssh_key_used_tracking.yml
@@ -0,0 +1,8 @@
+---
+name: disable_ssh_key_used_tracking
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54335
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/889
+milestone: '13.9'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/drop_license_management_artifact.yml b/config/feature_flags/development/drop_license_management_artifact.yml
index 1be40187b43..23c2290c07d 100644
--- a/config/feature_flags/development/drop_license_management_artifact.yml
+++ b/config/feature_flags/development/drop_license_management_artifact.yml
@@ -1,8 +1,8 @@
---
name: drop_license_management_artifact
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31247
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299114
+milestone: 13.0
type: development
group: group::composition analysis
default_enabled: true
diff --git a/config/feature_flags/development/dynamic_nonce_creation.yml b/config/feature_flags/development/dynamic_nonce_creation.yml
new file mode 100644
index 00000000000..b135f288554
--- /dev/null
+++ b/config/feature_flags/development/dynamic_nonce_creation.yml
@@ -0,0 +1,8 @@
+---
+name: dynamic_nonce_creation
+introduced_by_url:
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::manage
+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
index 70b19dfe594..63164b6e9fe 100644
--- a/config/feature_flags/development/export_reduce_relation_batch_size.yml
+++ b/config/feature_flags/development/export_reduce_relation_batch_size.yml
@@ -1,8 +1,8 @@
---
name: export_reduce_relation_batch_size
-introduced_by_url:
-rollout_issue_url:
-milestone:
+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/feature_flag_api.yml b/config/feature_flags/development/feature_flag_api.yml
index 3dc1d87d741..167b5ff4cf2 100644
--- a/config/feature_flags/development/feature_flag_api.yml
+++ b/config/feature_flags/development/feature_flag_api.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18198
rollout_issue_url:
milestone: '12.4'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: false
diff --git a/config/feature_flags/development/feature_flag_permissions.yml b/config/feature_flags/development/feature_flag_permissions.yml
index b7a4e8cb1bb..48371af5221 100644
--- a/config/feature_flags/development/feature_flag_permissions.yml
+++ b/config/feature_flags/development/feature_flag_permissions.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10096
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254981
milestone: '11.10'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: false
diff --git a/config/feature_flags/development/file_identifier_hash.yml b/config/feature_flags/development/file_identifier_hash.yml
index d5dc2b03eb6..84879e6c33e 100644
--- a/config/feature_flags/development/file_identifier_hash.yml
+++ b/config/feature_flags/development/file_identifier_hash.yml
@@ -1,8 +1,8 @@
---
name: file_identifier_hash
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33028
rollout_issue_url:
-milestone:
+milestone: '13.1'
type: development
-group:
+group: group::code review
default_enabled: false
diff --git a/config/feature_flags/development/forking.yml b/config/feature_flags/development/forking.yml
deleted file mode 100644
index 77e223d6268..00000000000
--- a/config/feature_flags/development/forking.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: forking
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/forward_deployment_enabled.yml b/config/feature_flags/development/forward_deployment_enabled.yml
index b4ad2e75561..750fad15f15 100644
--- a/config/feature_flags/development/forward_deployment_enabled.yml
+++ b/config/feature_flags/development/forward_deployment_enabled.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24412
rollout_issue_url:
milestone: '12.8'
type: development
-group: group::progressive delivery
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/generic_packages.yml b/config/feature_flags/development/generic_packages.yml
index aa41fb58a56..b2ab35c713c 100644
--- a/config/feature_flags/development/generic_packages.yml
+++ b/config/feature_flags/development/generic_packages.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40045
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/239133
milestone: '13.4'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/gitaly_catfile-cache.yml b/config/feature_flags/development/gitaly_catfile-cache.yml
deleted file mode 100644
index 14268e328f0..00000000000
--- a/config/feature_flags/development/gitaly_catfile-cache.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitaly_catfile-cache
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: false
diff --git a/config/feature_flags/development/gitaly_deny_disk_access.yml b/config/feature_flags/development/gitaly_deny_disk_access.yml
deleted file mode 100644
index b9c401e90d4..00000000000
--- a/config/feature_flags/development/gitaly_deny_disk_access.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitaly_deny_disk_access
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: false
diff --git a/config/feature_flags/development/gitaly_upload_pack_gitaly_hooks.yml b/config/feature_flags/development/gitaly_upload_pack_gitaly_hooks.yml
new file mode 100644
index 00000000000..86e268af772
--- /dev/null
+++ b/config/feature_flags/development/gitaly_upload_pack_gitaly_hooks.yml
@@ -0,0 +1,8 @@
+---
+name: gitaly_upload_pack_gitaly_hooks
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/807
+milestone: '13.9'
+type: development
+group:
+default_enabled: false
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
new file mode 100644
index 00000000000..c2a64263f08
--- /dev/null
+++ b/config/feature_flags/development/gitlab_ci_archived_trace_consistent_reads.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_ci_archived_trace_consistent_reads
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53716
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::continuous integration
+default_enabled: false
diff --git a/config/feature_flags/development/gitlab_ci_trace_read_consistency.yml b/config/feature_flags/development/gitlab_ci_trace_read_consistency.yml
new file mode 100644
index 00000000000..ee0b4e46924
--- /dev/null
+++ b/config/feature_flags/development/gitlab_ci_trace_read_consistency.yml
@@ -0,0 +1,8 @@
+---
+name: gitlab_ci_trace_read_consistency
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46976
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320938
+milestone: '13.9'
+type: development
+group: group::continuous integration
+default_enabled: true
diff --git a/config/feature_flags/development/gitlab_experiments.yml b/config/feature_flags/development/gitlab_experiments.yml
deleted file mode 100644
index 51fa6aa4529..00000000000
--- a/config/feature_flags/development/gitlab_experiments.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gitlab_experiments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45840
-rollout_issue_url:
-milestone: '13.7'
-type: development
-group: group::adoption
-default_enabled: false
diff --git a/config/feature_flags/development/gl_tooltips.yml b/config/feature_flags/development/gl_tooltips.yml
deleted file mode 100644
index 22c67019c33..00000000000
--- a/config/feature_flags/development/gl_tooltips.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: gl_tooltips
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292972
-milestone: '13.8'
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/graphql_individual_release_page.yml b/config/feature_flags/development/graphql_individual_release_page.yml
index 07eac51d380..8cf13ca4854 100644
--- a/config/feature_flags/development/graphql_individual_release_page.yml
+++ b/config/feature_flags/development/graphql_individual_release_page.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44779
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263522
milestone: '13.5'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/graphql_milestone_stats.yml b/config/feature_flags/development/graphql_milestone_stats.yml
index f6873e1c9e9..2f09f2b188a 100644
--- a/config/feature_flags/development/graphql_milestone_stats.yml
+++ b/config/feature_flags/development/graphql_milestone_stats.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35066
rollout_issue_url:
milestone: '13.2'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/graphql_pipeline_details_users.yml b/config/feature_flags/development/graphql_pipeline_details_users.yml
new file mode 100644
index 00000000000..a52cf23c878
--- /dev/null
+++ b/config/feature_flags/development/graphql_pipeline_details_users.yml
@@ -0,0 +1,8 @@
+---
+name: graphql_pipeline_details_users
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299112
+milestone: '13.9'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/graphql_pipeline_header.yml b/config/feature_flags/development/graphql_pipeline_header.yml
deleted file mode 100644
index 1d400c17452..00000000000
--- a/config/feature_flags/development/graphql_pipeline_header.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: graphql_pipeline_header
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39494
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254235
-milestone: '13.5'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/graphql_release_data.yml b/config/feature_flags/development/graphql_release_data.yml
index ef1f3dbba4c..a49d0ee1a6a 100644
--- a/config/feature_flags/development/graphql_release_data.yml
+++ b/config/feature_flags/development/graphql_release_data.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30753
rollout_issue_url:
milestone: '13.0'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/graphql_releases_page.yml b/config/feature_flags/development/graphql_releases_page.yml
index 541cf04bd79..b267f0543ec 100644
--- a/config/feature_flags/development/graphql_releases_page.yml
+++ b/config/feature_flags/development/graphql_releases_page.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33095
rollout_issue_url:
milestone: '13.4'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/group_ci_cd_analytics_page.yml b/config/feature_flags/development/group_ci_cd_analytics_page.yml
index 9f25ca7e6ad..1ee7bda169b 100644
--- a/config/feature_flags/development/group_ci_cd_analytics_page.yml
+++ b/config/feature_flags/development/group_ci_cd_analytics_page.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292601
milestone: '13.8'
type: development
group: group::release
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/group_import_export.yml b/config/feature_flags/development/group_import_export.yml
index 59204f2d16e..0eb01340bef 100644
--- a/config/feature_flags/development/group_import_export.yml
+++ b/config/feature_flags/development/group_import_export.yml
@@ -1,8 +1,8 @@
---
name: group_import_export
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22423
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282245
+milestone: '12.8'
type: development
group: group::import
default_enabled: true
diff --git a/config/feature_flags/development/honor_escaped_markdown.yml b/config/feature_flags/development/honor_escaped_markdown.yml
new file mode 100644
index 00000000000..6a8f62d5b74
--- /dev/null
+++ b/config/feature_flags/development/honor_escaped_markdown.yml
@@ -0,0 +1,8 @@
+---
+name: honor_escaped_markdown
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45922
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300531
+milestone: '13.9'
+type: development
+group: 'group::project management'
+default_enabled: false
diff --git a/config/feature_flags/development/import_requirements_csv.yml b/config/feature_flags/development/import_requirements_csv.yml
deleted file mode 100644
index 736d2204b44..00000000000
--- a/config/feature_flags/development/import_requirements_csv.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: import_requirements_csv
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48060
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284846
-milestone: '13.7'
-type: development
-group: group::product planning
-default_enabled: true
diff --git a/config/feature_flags/development/improved_merge_diff_highlighting.yml b/config/feature_flags/development/improved_merge_diff_highlighting.yml
new file mode 100644
index 00000000000..b397405a12c
--- /dev/null
+++ b/config/feature_flags/development/improved_merge_diff_highlighting.yml
@@ -0,0 +1,8 @@
+---
+name: improved_merge_diff_highlighting
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52499
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299884
+milestone: '13.9'
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/development/instance_statistics.yml b/config/feature_flags/development/instance_statistics.yml
index b5354561d03..3caddad8b69 100644
--- a/config/feature_flags/development/instance_statistics.yml
+++ b/config/feature_flags/development/instance_statistics.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40583
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241711
milestone: '13.4'
type: development
-group: group::analytics
+group: group::optimize
default_enabled: true
diff --git a/config/feature_flags/development/issue_rebalancing_optimization.yml b/config/feature_flags/development/issue_rebalancing_optimization.yml
new file mode 100644
index 00000000000..abaeb53f63d
--- /dev/null
+++ b/config/feature_flags/development/issue_rebalancing_optimization.yml
@@ -0,0 +1,8 @@
+---
+name: issue_rebalancing_optimization
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53384
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/issues.yml b/config/feature_flags/development/issues.yml
deleted file mode 100644
index a6ff572da52..00000000000
--- a/config/feature_flags/development/issues.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: issues
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/jira_for_vulnerabilities.yml b/config/feature_flags/development/jira_for_vulnerabilities.yml
index 32500c48da8..e00bd15cd09 100644
--- a/config/feature_flags/development/jira_for_vulnerabilities.yml
+++ b/config/feature_flags/development/jira_for_vulnerabilities.yml
@@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46982
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276893
type: development
group: group::threat insights
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/jira_issues_show_integration.yml b/config/feature_flags/development/jira_issues_show_integration.yml
new file mode 100644
index 00000000000..dd89ace22be
--- /dev/null
+++ b/config/feature_flags/development/jira_issues_show_integration.yml
@@ -0,0 +1,8 @@
+---
+name: jira_issues_show_integration
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52446
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299832
+milestone: '13.9'
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/jira_sync_builds.yml b/config/feature_flags/development/jira_sync_builds.yml
deleted file mode 100644
index 8cb054b848d..00000000000
--- a/config/feature_flags/development/jira_sync_builds.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_sync_builds
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49348
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292013
-milestone: '13.7'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/jira_sync_deployments.yml b/config/feature_flags/development/jira_sync_deployments.yml
deleted file mode 100644
index 8a644d43ba0..00000000000
--- a/config/feature_flags/development/jira_sync_deployments.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_sync_deployments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49757
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294034
-milestone: '13.7'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/jira_sync_feature_flags.yml b/config/feature_flags/development/jira_sync_feature_flags.yml
deleted file mode 100644
index c5925766919..00000000000
--- a/config/feature_flags/development/jira_sync_feature_flags.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jira_sync_feature_flags
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50390
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296990
-milestone: '13.8'
-type: development
-group: group::ecosystem
-default_enabled: false
diff --git a/config/feature_flags/development/kubernetes_agent_on_gitlab_com.yml b/config/feature_flags/development/kubernetes_agent_on_gitlab_com.yml
new file mode 100644
index 00000000000..fac509224e0
--- /dev/null
+++ b/config/feature_flags/development/kubernetes_agent_on_gitlab_com.yml
@@ -0,0 +1,8 @@
+---
+name: kubernetes_agent_on_gitlab_com
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53322
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300960
+milestone: '13.9'
+type: development
+group: group::configure
+default_enabled: false
diff --git a/config/feature_flags/development/lfs_check.yml b/config/feature_flags/development/lfs_check.yml
index 1a6413bd016..8e13d46a02f 100644
--- a/config/feature_flags/development/lfs_check.yml
+++ b/config/feature_flags/development/lfs_check.yml
@@ -1,8 +1,8 @@
---
name: lfs_check
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27451
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233550
milestone: '11.11'
type: development
-group:
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/local_file_reviews.yml b/config/feature_flags/development/local_file_reviews.yml
new file mode 100644
index 00000000000..4001f6ade72
--- /dev/null
+++ b/config/feature_flags/development/local_file_reviews.yml
@@ -0,0 +1,8 @@
+---
+name: local_file_reviews
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296674
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/log_import_export_relation_creation.yml b/config/feature_flags/development/log_import_export_relation_creation.yml
index ca7223c52b0..04d1b1e5d4f 100644
--- a/config/feature_flags/development/log_import_export_relation_creation.yml
+++ b/config/feature_flags/development/log_import_export_relation_creation.yml
@@ -1,8 +1,8 @@
---
name: log_import_export_relation_creation
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27605
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282245
+milestone: '12.10'
type: development
group: group::import
default_enabled: false
diff --git a/config/feature_flags/development/maintenance_mode.yml b/config/feature_flags/development/maintenance_mode.yml
deleted file mode 100644
index 53ecea7ba2b..00000000000
--- a/config/feature_flags/development/maintenance_mode.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: maintenance_mode
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28158
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/217895
-milestone: '12.10'
-type: development
-group: group::geo
-default_enabled: false
diff --git a/config/feature_flags/development/merge_request_draft_filter.yml b/config/feature_flags/development/merge_request_draft_filter.yml
index 0614485d37c..3c08e0304d2 100644
--- a/config/feature_flags/development/merge_request_draft_filter.yml
+++ b/config/feature_flags/development/merge_request_draft_filter.yml
@@ -1,7 +1,7 @@
---
name: merge_request_draft_filter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35942
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/298776
milestone: '13.3'
type: development
group: group::code review
diff --git a/config/feature_flags/development/merge_request_rebase_nowait_lock.yml b/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
index 3ea69762c1d..e0d837a3757 100644
--- a/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
+++ b/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
@@ -1,8 +1,8 @@
---
name: merge_request_rebase_nowait_lock
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18481
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320758
+milestone: '12.5'
type: development
-group:
+group: group::code review
default_enabled: true
diff --git a/config/feature_flags/development/merge_request_refs_cleanup.yml b/config/feature_flags/development/merge_request_refs_cleanup.yml
new file mode 100644
index 00000000000..79ea3c8b7a7
--- /dev/null
+++ b/config/feature_flags/development/merge_request_refs_cleanup.yml
@@ -0,0 +1,8 @@
+---
+name: merge_request_refs_cleanup
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51558
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296874
+milestone: '13.8'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/merge_request_reviewers.yml b/config/feature_flags/development/merge_request_reviewers.yml
deleted file mode 100644
index 85582ee25f9..00000000000
--- a/config/feature_flags/development/merge_request_reviewers.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_request_reviewers
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40488
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/245190
-milestone: '13.4'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/merge_requests.yml b/config/feature_flags/development/merge_requests.yml
deleted file mode 100644
index 27f5f8b1085..00000000000
--- a/config/feature_flags/development/merge_requests.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_requests
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/metrics_dashboard.yml b/config/feature_flags/development/metrics_dashboard.yml
deleted file mode 100644
index 39a7fd1260b..00000000000
--- a/config/feature_flags/development/metrics_dashboard.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: metrics_dashboard
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29634
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257902
-milestone: '13.0'
-type: development
-group: group::monitor
-default_enabled: true
diff --git a/config/feature_flags/development/migrate_user_mentions.yml b/config/feature_flags/development/migrate_user_mentions.yml
index df9e5477590..2b250994b5a 100644
--- a/config/feature_flags/development/migrate_user_mentions.yml
+++ b/config/feature_flags/development/migrate_user_mentions.yml
@@ -1,7 +1,7 @@
---
name: migrate_user_mentions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34378
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231175
milestone: '13.3'
type: development
group: group::project management
diff --git a/config/feature_flags/development/multiline_comments.yml b/config/feature_flags/development/multiline_comments.yml
deleted file mode 100644
index ed38e1a575f..00000000000
--- a/config/feature_flags/development/multiline_comments.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: multiline_comments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37114
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/211255
-milestone: '13.2'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/new_jira_connect_ui.yml b/config/feature_flags/development/new_jira_connect_ui.yml
index 8783c1ed7fd..3420141ce2d 100644
--- a/config/feature_flags/development/new_jira_connect_ui.yml
+++ b/config/feature_flags/development/new_jira_connect_ui.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/295647
milestone: '13.8'
type: development
group: group::ecosystem
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml b/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml
deleted file mode 100644
index 0354b18fafd..00000000000
--- a/config/feature_flags/development/new_pipeline_form_prefilled_vars.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_pipeline_form_prefilled_vars
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44120
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263276
-milestone: '13.5'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/development/new_release_page.yml b/config/feature_flags/development/new_release_page.yml
index c3f757bfc41..7b73c296e4e 100644
--- a/config/feature_flags/development/new_release_page.yml
+++ b/config/feature_flags/development/new_release_page.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35367
rollout_issue_url:
milestone: '13.2'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/not_issuable_queries.yml b/config/feature_flags/development/not_issuable_queries.yml
index 80aba0fef0f..e5770d1a2ea 100644
--- a/config/feature_flags/development/not_issuable_queries.yml
+++ b/config/feature_flags/development/not_issuable_queries.yml
@@ -1,7 +1,7 @@
---
name: not_issuable_queries
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27639
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292809
milestone: '13.0'
type: development
group: group::project management
diff --git a/config/feature_flags/development/operations.yml b/config/feature_flags/development/operations.yml
deleted file mode 100644
index 5b5537ed740..00000000000
--- a/config/feature_flags/development/operations.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: operations
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48347
-rollout_issue_url:
-milestone: '13.7'
-type: development
-group: group::editor
-default_enabled: true
diff --git a/config/feature_flags/development/optimized_issuable_label_filter.yml b/config/feature_flags/development/optimized_issuable_label_filter.yml
index 4712cdaf230..8385b85e143 100644
--- a/config/feature_flags/development/optimized_issuable_label_filter.yml
+++ b/config/feature_flags/development/optimized_issuable_label_filter.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34503
rollout_issue_url:
milestone: '13.4'
type: development
-group: group::analytics
-default_enabled: false
+group: group::optimize
+default_enabled: true
diff --git a/config/feature_flags/development/optimized_merge_request_count_with_merged_at_filter.yml b/config/feature_flags/development/optimized_merge_request_count_with_merged_at_filter.yml
new file mode 100644
index 00000000000..a7a458e3d29
--- /dev/null
+++ b/config/feature_flags/development/optimized_merge_request_count_with_merged_at_filter.yml
@@ -0,0 +1,8 @@
+---
+name: optimized_merge_request_count_with_merged_at_filter
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52113
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299347
+milestone: '13.9'
+type: development
+group: group::optimize
+default_enabled: true
diff --git a/config/feature_flags/development/optimized_timebox_queries.yml b/config/feature_flags/development/optimized_timebox_queries.yml
index 215242046c5..eea0b149079 100644
--- a/config/feature_flags/development/optimized_timebox_queries.yml
+++ b/config/feature_flags/development/optimized_timebox_queries.yml
@@ -1,8 +1,8 @@
---
name: optimized_timebox_queries
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32953
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34043
+milestone: '13.1'
type: development
-group:
+group: group::project management
default_enabled: true
diff --git a/config/feature_flags/development/optional_code_owners_sections.yml b/config/feature_flags/development/optional_code_owners_sections.yml
deleted file mode 100644
index a7933f42fc9..00000000000
--- a/config/feature_flags/development/optional_code_owners_sections.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: optional_code_owners_sections
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51002
-rollout_issue_url:
-milestone: '13.8'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/packages_and_registries_group_settings.yml b/config/feature_flags/development/packages_and_registries_group_settings.yml
deleted file mode 100644
index 8712fa4895d..00000000000
--- a/config/feature_flags/development/packages_and_registries_group_settings.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: packages_and_registries_group_settings
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51460
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297371
-milestone: '13.8'
-type: development
-group: group::package
-default_enabled: false
diff --git a/config/feature_flags/development/pages.yml b/config/feature_flags/development/pages.yml
deleted file mode 100644
index b32ab9af770..00000000000
--- a/config/feature_flags/development/pages.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pages
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/pages_serve_from_deployments.yml b/config/feature_flags/development/pages_serve_from_deployments.yml
index f73e9f5b49d..d13bf2dfaa5 100644
--- a/config/feature_flags/development/pages_serve_from_deployments.yml
+++ b/config/feature_flags/development/pages_serve_from_deployments.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46320
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2932
milestone: '13.6'
type: development
-group: group::Release Management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/pages_serve_from_legacy_storage.yml b/config/feature_flags/development/pages_serve_from_legacy_storage.yml
new file mode 100644
index 00000000000..37d83106737
--- /dev/null
+++ b/config/feature_flags/development/pages_serve_from_legacy_storage.yml
@@ -0,0 +1,8 @@
+---
+name: pages_serve_from_legacy_storage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297228
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297524
+milestone: '13.8'
+type: development
+group: group::release
+default_enabled: true
diff --git a/config/feature_flags/development/pages_serve_from_migrated_zip.yml b/config/feature_flags/development/pages_serve_from_migrated_zip.yml
new file mode 100644
index 00000000000..18b912215b6
--- /dev/null
+++ b/config/feature_flags/development/pages_serve_from_migrated_zip.yml
@@ -0,0 +1,8 @@
+---
+name: pages_serve_from_migrated_zip
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52573
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300021
+milestone: '13.9'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml b/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml
index 7700cf7fae5..836702debba 100644
--- a/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml
+++ b/config/feature_flags/development/pages_serve_with_zip_file_protocol.yml
@@ -1,8 +1,8 @@
---
name: pages_serve_with_zip_file_protocol
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46320
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321677
milestone: '13.6'
type: development
-group: group::Release Management
+group: group::release
default_enabled: false
diff --git a/config/feature_flags/development/pages_update_legacy_storage.yml b/config/feature_flags/development/pages_update_legacy_storage.yml
new file mode 100644
index 00000000000..4a228b4cb8b
--- /dev/null
+++ b/config/feature_flags/development/pages_update_legacy_storage.yml
@@ -0,0 +1,8 @@
+---
+name: pages_update_legacy_storage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50683
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296138
+milestone: '13.9'
+type: development
+group: group::release
+default_enabled: true
diff --git a/config/feature_flags/development/paginate_commit_view.yml b/config/feature_flags/development/paginate_commit_view.yml
new file mode 100644
index 00000000000..ee89788a219
--- /dev/null
+++ b/config/feature_flags/development/paginate_commit_view.yml
@@ -0,0 +1,8 @@
+---
+name: paginate_commit_view
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52819
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300540
+milestone: '13.9'
+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
index cf90ccd0f69..916312b1005 100644
--- a/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
+++ b/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
@@ -1,8 +1,8 @@
---
name: prohibit_hexadecimal_branch_names
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/28439ca4b1dd14f22a5a6ad14530f6bf1046f8bc
rollout_issue_url:
-milestone:
+milestone: '12.10'
type: development
-group:
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/project_list_filter_bar.yml b/config/feature_flags/development/project_list_filter_bar.yml
index 7f8ea867990..29d5d67af95 100644
--- a/config/feature_flags/development/project_list_filter_bar.yml
+++ b/config/feature_flags/development/project_list_filter_bar.yml
@@ -1,8 +1,8 @@
---
name: project_list_filter_bar
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/11209
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321404
+milestone: '11.11'
type: development
-group:
+group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/query_deploymenys_via_finished_at_in_vsa.yml b/config/feature_flags/development/query_deploymenys_via_finished_at_in_vsa.yml
new file mode 100644
index 00000000000..4dcb4ddde64
--- /dev/null
+++ b/config/feature_flags/development/query_deploymenys_via_finished_at_in_vsa.yml
@@ -0,0 +1,8 @@
+---
+name: query_deploymenys_via_finished_at_in_vsa
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53050
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300649
+milestone: '13.9'
+type: development
+group: group::optimize
+default_enabled: true
diff --git a/config/feature_flags/development/release_evidence.yml b/config/feature_flags/development/release_evidence.yml
index 87648e6a261..3ba5ed86c71 100644
--- a/config/feature_flags/development/release_evidence.yml
+++ b/config/feature_flags/development/release_evidence.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26509
rollout_issue_url:
milestone: '12.10'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/release_mr_issue_urls.yml b/config/feature_flags/development/release_mr_issue_urls.yml
index b017a716b51..4f9b43ce4e1 100644
--- a/config/feature_flags/development/release_mr_issue_urls.yml
+++ b/config/feature_flags/development/release_mr_issue_urls.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18727
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276619
milestone: '12.4'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/remove_comment_close_reopen.yml b/config/feature_flags/development/remove_comment_close_reopen.yml
new file mode 100644
index 00000000000..1d3bf305cae
--- /dev/null
+++ b/config/feature_flags/development/remove_comment_close_reopen.yml
@@ -0,0 +1,8 @@
+---
+name: remove_comment_close_reopen
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49614
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/198562
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/remove_resolve_note.yml b/config/feature_flags/development/remove_resolve_note.yml
index 0f792dffd0b..008a469e16d 100644
--- a/config/feature_flags/development/remove_resolve_note.yml
+++ b/config/feature_flags/development/remove_resolve_note.yml
@@ -1,7 +1,7 @@
---
name: remove_resolve_note
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45549
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320756
milestone: '13.6'
type: development
group: group::code review
diff --git a/config/feature_flags/development/repository.yml b/config/feature_flags/development/repository.yml
deleted file mode 100644
index a9dd6cbdcb5..00000000000
--- a/config/feature_flags/development/repository.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: repository
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/repository_archive_hotlinking_interception.yml b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
index 6b684e5a8c7..56943627231 100644
--- a/config/feature_flags/development/repository_archive_hotlinking_interception.yml
+++ b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
@@ -1,8 +1,8 @@
---
name: repository_archive_hotlinking_interception
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/50c11f278d18fe1f3fb12eb595067216bb58ade2
rollout_issue_url:
-milestone:
+milestone: '12.10'
type: development
-group:
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/retarget_merge_requests.yml b/config/feature_flags/development/retarget_merge_requests.yml
new file mode 100644
index 00000000000..39ac4be0219
--- /dev/null
+++ b/config/feature_flags/development/retarget_merge_requests.yml
@@ -0,0 +1,8 @@
+---
+name: retarget_merge_requests
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53710
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320895
+milestone: '13.9'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/reviewer_approval_rules.yml b/config/feature_flags/development/reviewer_approval_rules.yml
deleted file mode 100644
index 78bc52de5b3..00000000000
--- a/config/feature_flags/development/reviewer_approval_rules.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: reviewer_approval_rules
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46738
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/293742
-milestone: '13.7'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/rubygem_packages.yml b/config/feature_flags/development/rubygem_packages.yml
new file mode 100644
index 00000000000..9f394f091bb
--- /dev/null
+++ b/config/feature_flags/development/rubygem_packages.yml
@@ -0,0 +1,8 @@
+---
+name: rubygem_packages
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52147
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299383
+milestone: '13.9'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/secure_security_and_compliance_configuration_page_on_ce.yml b/config/feature_flags/development/secure_security_and_compliance_configuration_page_on_ce.yml
new file mode 100644
index 00000000000..e86211243a1
--- /dev/null
+++ b/config/feature_flags/development/secure_security_and_compliance_configuration_page_on_ce.yml
@@ -0,0 +1,8 @@
+---
+name: secure_security_and_compliance_configuration_page_on_ce
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50282
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294076
+milestone: '13.9'
+type: development
+group: group::static analysis
+default_enabled: false
diff --git a/config/feature_flags/development/similarity_search.yml b/config/feature_flags/development/similarity_search.yml
index 312ab767eb0..978095c94b5 100644
--- a/config/feature_flags/development/similarity_search.yml
+++ b/config/feature_flags/development/similarity_search.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37300/
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38675
milestone: '13.3'
type: development
-group: group::analytics
+group: group::optimize
default_enabled: true
diff --git a/config/feature_flags/development/simplified_commit_status_group_name.yml b/config/feature_flags/development/simplified_commit_status_group_name.yml
new file mode 100644
index 00000000000..410d351de5f
--- /dev/null
+++ b/config/feature_flags/development/simplified_commit_status_group_name.yml
@@ -0,0 +1,8 @@
+---
+name: simplified_commit_status_group_name
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52644
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::testing
+default_enabled: false
diff --git a/config/feature_flags/development/smart_cobertura_parser.yml b/config/feature_flags/development/smart_cobertura_parser.yml
deleted file mode 100644
index a3aa182e412..00000000000
--- a/config/feature_flags/development/smart_cobertura_parser.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: smart_cobertura_parser
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48048
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284822
-milestone: '13.7'
-type: development
-group: group::testing
-default_enabled: false
diff --git a/config/feature_flags/development/snippets.yml b/config/feature_flags/development/snippets.yml
deleted file mode 100644
index ee06c54e237..00000000000
--- a/config/feature_flags/development/snippets.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: snippets
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group:
-default_enabled: true
diff --git a/config/feature_flags/development/sort_diffs.yml b/config/feature_flags/development/sort_diffs.yml
index 505b5f0e0b5..49f04c30f49 100644
--- a/config/feature_flags/development/sort_diffs.yml
+++ b/config/feature_flags/development/sort_diffs.yml
@@ -1,8 +1,8 @@
---
name: sort_diffs
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49118
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/293819
milestone: '13.7'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/specialized_project_authorization_workers.yml b/config/feature_flags/development/specialized_project_authorization_workers.yml
index f3dbf09af14..16d6d4ed82f 100644
--- a/config/feature_flags/development/specialized_project_authorization_workers.yml
+++ b/config/feature_flags/development/specialized_project_authorization_workers.yml
@@ -1,8 +1,8 @@
---
name: specialized_project_authorization_workers
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31377
-rollout_issue_url:
+rollout_issue_url:
milestone: '13.0'
type: development
group: group::access
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/squash_options.yml b/config/feature_flags/development/squash_options.yml
deleted file mode 100644
index bea03c6e9b2..00000000000
--- a/config/feature_flags/development/squash_options.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: squash_options
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33930
-rollout_issue_url:
-milestone: '13.2'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/suggestions_custom_commit.yml b/config/feature_flags/development/suggestions_custom_commit.yml
index e51e219ee1d..44455664813 100644
--- a/config/feature_flags/development/suggestions_custom_commit.yml
+++ b/config/feature_flags/development/suggestions_custom_commit.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297404
milestone: '13.9'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/trace_memory_allocations.yml b/config/feature_flags/development/trace_memory_allocations.yml
new file mode 100644
index 00000000000..78f21d2e520
--- /dev/null
+++ b/config/feature_flags/development/trace_memory_allocations.yml
@@ -0,0 +1,8 @@
+---
+name: trace_memory_allocations
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52306
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299524
+milestone: '13.9'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/track_issue_activity_actions.yml b/config/feature_flags/development/track_issue_activity_actions.yml
deleted file mode 100644
index c755dac8e75..00000000000
--- a/config/feature_flags/development/track_issue_activity_actions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: track_issue_activity_actions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40904
-rollout_issue_url:
-milestone: '13.4'
-type: development
-group: group::project management
-default_enabled: true
diff --git a/config/feature_flags/development/track_unique_visits.yml b/config/feature_flags/development/track_unique_visits.yml
index 80d969cc65b..b11539e830b 100644
--- a/config/feature_flags/development/track_unique_visits.yml
+++ b/config/feature_flags/development/track_unique_visits.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33146
rollout_issue_url:
milestone: '13.2'
type: development
-group: group::analytics
+group: group::optimize
default_enabled: true
diff --git a/config/feature_flags/development/track_unique_wiki_page_views.yml b/config/feature_flags/development/track_unique_wiki_page_views.yml
deleted file mode 100644
index 39d25352e73..00000000000
--- a/config/feature_flags/development/track_unique_wiki_page_views.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: track_unique_wiki_page_views
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44622
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/267162
-milestone: '13.5'
-type: development
-group: group::editor
-default_enabled: true
diff --git a/config/feature_flags/development/tribute_autocomplete.yml b/config/feature_flags/development/tribute_autocomplete.yml
index 47fbd11f844..02094350b32 100644
--- a/config/feature_flags/development/tribute_autocomplete.yml
+++ b/config/feature_flags/development/tribute_autocomplete.yml
@@ -1,7 +1,7 @@
---
name: tribute_autocomplete
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32671
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292804
milestone: '13.2'
type: development
group: group::project management
diff --git a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
index 986f002aa1d..c94b48d8329 100644
--- a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
+++ b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
@@ -1,8 +1,8 @@
---
name: unlink_fork_network_upon_visibility_decrease
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20466
rollout_issue_url:
-milestone:
+milestone: '12.6'
type: development
-group:
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml b/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
index 58a28139a35..de3ca4fc689 100644
--- a/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
+++ b/config/feature_flags/development/usage_data_i_ci_secrets_management_vault_build_created.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46515
rollout_issue_url:
milestone: '13.6'
type: development
-group: group::release management
+group: group::release
default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_edit_mr_desc.yml b/config/feature_flags/development/usage_data_i_code_review_edit_mr_desc.yml
new file mode 100644
index 00000000000..cd49759c1d8
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_edit_mr_desc.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_edit_mr_desc
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292830
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_edit_mr_title.yml b/config/feature_flags/development/usage_data_i_code_review_edit_mr_title.yml
new file mode 100644
index 00000000000..61d238b312a
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_edit_mr_title.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_edit_mr_title
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292830
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_add_suggestion.yml b/config/feature_flags/development/usage_data_i_code_review_user_add_suggestion.yml
new file mode 100644
index 00000000000..832be26d50d
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_add_suggestion.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_add_suggestion
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52189
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_apply_suggestion.yml b/config/feature_flags/development/usage_data_i_code_review_user_apply_suggestion.yml
new file mode 100644
index 00000000000..03aa1691825
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_apply_suggestion.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_apply_suggestion
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52189
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_added.yml b/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_added.yml
new file mode 100644
index 00000000000..749b17f9e0c
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_added.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_approval_rule_added
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320966
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_deleted.yml b/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_deleted.yml
new file mode 100644
index 00000000000..ef97df30aeb
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_deleted.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_approval_rule_deleted
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320966
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_edited.yml b/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_edited.yml
new file mode 100644
index 00000000000..5ecdaf3a2d0
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_approval_rule_edited.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_approval_rule_edited
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320966
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_approve_mr.yml b/config/feature_flags/development/usage_data_i_code_review_user_approve_mr.yml
new file mode 100644
index 00000000000..c20d201de7c
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_approve_mr.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_approve_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53201
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_assigned.yml b/config/feature_flags/development/usage_data_i_code_review_user_assigned.yml
new file mode 100644
index 00000000000..f18208e44dc
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_assigned.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_assigned
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52194
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_create_mr_from_issue.yml b/config/feature_flags/development/usage_data_i_code_review_user_create_mr_from_issue.yml
new file mode 100644
index 00000000000..1cd95061a66
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_create_mr_from_issue.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_create_mr_from_issue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53808
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_marked_as_draft.yml b/config/feature_flags/development/usage_data_i_code_review_user_marked_as_draft.yml
new file mode 100644
index 00000000000..82dc1582558
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_marked_as_draft.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_marked_as_draft
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/301223
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_resolve_thread.yml b/config/feature_flags/development/usage_data_i_code_review_user_resolve_thread.yml
new file mode 100644
index 00000000000..8c7af83bab4
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_resolve_thread.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_resolve_thread
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52130
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_review_requested.yml b/config/feature_flags/development/usage_data_i_code_review_user_review_requested.yml
new file mode 100644
index 00000000000..540ac1f61e1
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_review_requested.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_review_requested
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52194
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_toggled_task_item_status.yml b/config/feature_flags/development/usage_data_i_code_review_user_toggled_task_item_status.yml
new file mode 100644
index 00000000000..f2db27d0549
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_toggled_task_item_status.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_toggled_task_item_status
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/320851
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_unapprove_mr.yml b/config/feature_flags/development/usage_data_i_code_review_user_unapprove_mr.yml
new file mode 100644
index 00000000000..9d31ad6a482
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_unapprove_mr.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_unapprove_mr
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53201
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_unmarked_as_draft.yml b/config/feature_flags/development/usage_data_i_code_review_user_unmarked_as_draft.yml
new file mode 100644
index 00000000000..9582562ff74
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_unmarked_as_draft.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_unmarked_as_draft
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/301223
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_unresolve_thread.yml b/config/feature_flags/development/usage_data_i_code_review_user_unresolve_thread.yml
new file mode 100644
index 00000000000..49b860416c5
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_unresolve_thread.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_unresolve_thread
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52130
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_code_review_user_vs_code_api_request.yml b/config/feature_flags/development/usage_data_i_code_review_user_vs_code_api_request.yml
new file mode 100644
index 00000000000..531832ad633
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_code_review_user_vs_code_api_request.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_code_review_user_vs_code_api_request
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52484
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::code review
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml b/config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml
new file mode 100644
index 00000000000..c4850caaf9d
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_group_code_coverage_project_click_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_group_code_coverage_project_click_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51411
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299893
+milestone: '13.8'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_load_performance_widget_total.yml b/config/feature_flags/development/usage_data_i_testing_load_performance_widget_total.yml
new file mode 100644
index 00000000000..3ffb9bceb99
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_load_performance_widget_total.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_load_performance_widget_total
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52688
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml b/config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml
new file mode 100644
index 00000000000..968ab3e63f1
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_metrics_report_artifact_uploaders
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51670
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml b/config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml
new file mode 100644
index 00000000000..adf850aa8bc
--- /dev/null
+++ b/config/feature_flags/development/usage_data_track_ecosystem_jira_service.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_track_ecosystem_jira_service
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52110
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300447
+milestone: '13.9'
+type: development
+group: group::ecosystem
+default_enabled: false
diff --git a/config/feature_flags/development/usage_data_track_quickactions.yml b/config/feature_flags/development/usage_data_track_quickactions.yml
new file mode 100644
index 00000000000..57f698f7031
--- /dev/null
+++ b/config/feature_flags/development/usage_data_track_quickactions.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_track_quickactions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52398
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml b/config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml
new file mode 100644
index 00000000000..1d3092ed615
--- /dev/null
+++ b/config/feature_flags/development/usage_data_unique_users_committing_ciconfigfile.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_unique_users_committing_ciconfigfile
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52172
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299403
+milestone: '13.9'
+type: development
+group: group::pipeline authoring
+default_enabled: true
diff --git a/config/feature_flags/development/use_workhorse_s3_client.yml b/config/feature_flags/development/use_workhorse_s3_client.yml
index 7f14d51a66c..3c34c420ebf 100644
--- a/config/feature_flags/development/use_workhorse_s3_client.yml
+++ b/config/feature_flags/development/use_workhorse_s3_client.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35480
rollout_issue_url:
milestone: '13.2'
type: development
-group:
+group: group::source code
default_enabled: true
diff --git a/config/feature_flags/development/user_mode_in_session.yml b/config/feature_flags/development/user_mode_in_session.yml
index a3c4d44e4ce..1b0a0053cf4 100644
--- a/config/feature_flags/development/user_mode_in_session.yml
+++ b/config/feature_flags/development/user_mode_in_session.yml
@@ -1,8 +1,8 @@
---
name: user_mode_in_session
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16981
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321025
+milestone: 12.4
type: development
-group:
+group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/user_time_settings.yml b/config/feature_flags/development/user_time_settings.yml
index eaeb7f17794..098b96e97f0 100644
--- a/config/feature_flags/development/user_time_settings.yml
+++ b/config/feature_flags/development/user_time_settings.yml
@@ -1,8 +1,8 @@
---
name: user_time_settings
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25381
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321407
+milestone: '11.11'
type: development
-group:
+group: group::access
default_enabled: false
diff --git a/config/feature_flags/development/validate_import_decompressed_archive_size.yml b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
index 644a936a67c..675586bc9ee 100644
--- a/config/feature_flags/development/validate_import_decompressed_archive_size.yml
+++ b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
@@ -1,8 +1,8 @@
---
name: validate_import_decompressed_archive_size
-introduced_by_url:
-rollout_issue_url:
-milestone:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39686
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/282245
+milestone: '13.4'
type: development
group: group::import
default_enabled: false
diff --git a/config/feature_flags/development/variables_in_include_section_ci.yml b/config/feature_flags/development/variables_in_include_section_ci.yml
deleted file mode 100644
index f6fc810e6f2..00000000000
--- a/config/feature_flags/development/variables_in_include_section_ci.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: variables_in_include_section_ci
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50188/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/294294
-milestone: '13.8'
-type: development
-group: group::compliance
-default_enabled: false
diff --git a/config/feature_flags/development/vue_epics_list.yml b/config/feature_flags/development/vue_epics_list.yml
new file mode 100644
index 00000000000..22e2a53aeee
--- /dev/null
+++ b/config/feature_flags/development/vue_epics_list.yml
@@ -0,0 +1,8 @@
+---
+name: vue_epics_list
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46769
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276189
+milestone: '13.9'
+type: development
+group: group::product planning
+default_enabled: false
diff --git a/config/feature_flags/development/vue_issuable_sidebar.yml b/config/feature_flags/development/vue_issuable_sidebar.yml
deleted file mode 100644
index 47c17db1206..00000000000
--- a/config/feature_flags/development/vue_issuable_sidebar.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: vue_issuable_sidebar
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18199
-rollout_issue_url:
-milestone: '12.4'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/vue_notification_dropdown.yml b/config/feature_flags/development/vue_notification_dropdown.yml
new file mode 100644
index 00000000000..4c4f67fe928
--- /dev/null
+++ b/config/feature_flags/development/vue_notification_dropdown.yml
@@ -0,0 +1,8 @@
+---
+name: vue_notification_dropdown
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52068
+rollout_issue_url:
+milestone: '13.8'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/config/feature_flags/development/vue_project_members_list.yml b/config/feature_flags/development/vue_project_members_list.yml
new file mode 100644
index 00000000000..55f4d2bf62a
--- /dev/null
+++ b/config/feature_flags/development/vue_project_members_list.yml
@@ -0,0 +1,8 @@
+---
+name: vue_project_members_list
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52148
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299954
+milestone: '13.9'
+type: development
+group: group::access
+default_enabled: true
diff --git a/config/feature_flags/development/webperf_experiment.yml b/config/feature_flags/development/webperf_experiment.yml
deleted file mode 100644
index 50408df0555..00000000000
--- a/config/feature_flags/development/webperf_experiment.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: webperf_experiment
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group: group::editor
-default_enabled: false
diff --git a/config/feature_flags/development/whats_new_drawer.yml b/config/feature_flags/development/whats_new_drawer.yml
deleted file mode 100644
index c06dfbe1fe6..00000000000
--- a/config/feature_flags/development/whats_new_drawer.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: whats_new_drawer
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38975
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/254186
-milestone: '13.3'
-type: development
-group: group::retention
-default_enabled: false
diff --git a/config/feature_flags/development/wiki.yml b/config/feature_flags/development/wiki.yml
deleted file mode 100644
index 008852d2c13..00000000000
--- a/config/feature_flags/development/wiki.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: wiki
-introduced_by_url:
-rollout_issue_url:
-milestone:
-type: development
-group: group::editor
-default_enabled: true
diff --git a/config/feature_flags/development/workhorse_archive_cache_disabled.yml b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
index e7871d9062b..e40741863d4 100644
--- a/config/feature_flags/development/workhorse_archive_cache_disabled.yml
+++ b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
@@ -1,8 +1,8 @@
---
name: workhorse_archive_cache_disabled
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/16325
rollout_issue_url:
-milestone:
+milestone: '10.5'
type: development
-group:
+group: group::source code
default_enabled: false
diff --git a/config/feature_flags/experiment/default_to_issues_board_experiment_percentage.yml b/config/feature_flags/experiment/default_to_issues_board_experiment_percentage.yml
deleted file mode 100644
index d4a695502f9..00000000000
--- a/config/feature_flags/experiment/default_to_issues_board_experiment_percentage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: default_to_issues_board_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43939
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268298
-milestone: '13.5'
-type: experiment
-group: group::conversion
-default_enabled: true
diff --git a/config/feature_flags/experiment/in_product_marketing_emails_experiment_percentage.yml b/config/feature_flags/experiment/in_product_marketing_emails_experiment_percentage.yml
new file mode 100644
index 00000000000..8cb198a2102
--- /dev/null
+++ b/config/feature_flags/experiment/in_product_marketing_emails_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: in_product_marketing_emails_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50679
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/303
+milestone: "13.9"
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
index 6fac63b381c..216726178f1 100644
--- a/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
+++ b/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
@@ -1,7 +1,7 @@
---
name: invite_members_new_dropdown_experiment_percentage
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50069
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268129
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/291
milestone: '13.8'
type: experiment
group: group::expansion
diff --git a/config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml b/config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml
deleted file mode 100644
index 33a15e28d44..00000000000
--- a/config/feature_flags/experiment/jobs_empty_state_experiment_percentage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: jobs_empty_state_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48686
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281054
-milestone: '13.7'
-type: experiment
-group: group::activation
-default_enabled: false
diff --git a/config/feature_flags/experiment/learn_gitlab_a_experiment_percentage.yml b/config/feature_flags/experiment/learn_gitlab_a_experiment_percentage.yml
new file mode 100644
index 00000000000..54b7ea465f1
--- /dev/null
+++ b/config/feature_flags/experiment/learn_gitlab_a_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: learn_gitlab_a_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53089
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/281022
+milestone: '13.9'
+type: experiment
+group: group::conversion
+default_enabled: false
diff --git a/config/feature_flags/experiment/learn_gitlab_b_experiment_percentage.yml b/config/feature_flags/experiment/learn_gitlab_b_experiment_percentage.yml
new file mode 100644
index 00000000000..cca5d35baf3
--- /dev/null
+++ b/config/feature_flags/experiment/learn_gitlab_b_experiment_percentage.yml
@@ -0,0 +1,8 @@
+---
+name: learn_gitlab_b_experiment_percentage
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53089
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/306
+milestone: '13.9'
+type: experiment
+group: group::conversion
+default_enabled: false
diff --git a/config/feature_flags/experiment/members_invite_email.yml b/config/feature_flags/experiment/members_invite_email.yml
new file mode 100644
index 00000000000..5bf0b9d10d0
--- /dev/null
+++ b/config/feature_flags/experiment/members_invite_email.yml
@@ -0,0 +1,8 @@
+---
+name: members_invite_email
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51223
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/325
+milestone: '13.9'
+type: experiment
+group: group::expansion
+default_enabled: false
diff --git a/config/feature_flags/experiment/onboarding_issues_experiment_percentage.yml b/config/feature_flags/experiment/onboarding_issues_experiment_percentage.yml
deleted file mode 100644
index 7a8f3074d96..00000000000
--- a/config/feature_flags/experiment/onboarding_issues_experiment_percentage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: onboarding_issues_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31656/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/224515
-milestone: '13.0'
-type: experiment
-group: group::conversion
-default_enabled: true
diff --git a/config/feature_flags/experiment/pipelines_empty_state_experiment_percentage.yml b/config/feature_flags/experiment/pipelines_empty_state_experiment_percentage.yml
deleted file mode 100644
index beb8e8a21c6..00000000000
--- a/config/feature_flags/experiment/pipelines_empty_state_experiment_percentage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: pipelines_empty_state_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47952
-rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/289
-milestone: '13.8'
-type: experiment
-group: group::activation
-default_enabled: false
diff --git a/config/feature_flags/ops/scalability_ci_fetch_sha.yml b/config/feature_flags/ops/scalability_ci_fetch_sha.yml
deleted file mode 100644
index e8133f16072..00000000000
--- a/config/feature_flags/ops/scalability_ci_fetch_sha.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: scalability_ci_fetch_sha
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51208
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746
-milestone: '13.8'
-type: ops
-group: team::Scalability
-default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 92e7501d49d..65627b0e166 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -165,6 +165,9 @@ production: &base
## Disable jQuery and CSS animations
# disable_animations: true
+ ## Application settings cache expiry in seconds (default: 60)
+ # application_settings_cache_seconds: 60
+
## Reply by email
# Allow users to comment on issues and merge requests by replying to notification emails.
# For documentation on how to set this up, see http://doc.gitlab.com/ce/administration/reply_by_email.html
@@ -413,7 +416,7 @@ production: &base
## Gravatar
## If using gravatar.com, there's nothing to change here. For Libravatar
## you'll need to provide the custom URLs. For more information,
- ## see: https://docs.gitlab.com/ee/customization/libravatar.html
+ ## see: https://docs.gitlab.com/ee/administration/libravatar.html
gravatar:
# Gravatar/Libravatar URLs: possible placeholders: %{hash} %{size} %{email} %{username}
# plain_url: "http://..." # default: https://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
@@ -432,7 +435,7 @@ production: &base
cron: "0 * * * *"
# Execute scheduled triggers
pipeline_schedule_worker:
- cron: "19 * * * *"
+ cron: "3-59/10 * * * *"
# Remove expired build artifacts
expire_build_artifacts_worker:
cron: "*/7 * * * *"
@@ -587,7 +590,7 @@ production: &base
# enabled: true
# primary_api_url: http://localhost:5000/ # internal address to the primary registry, will be used by GitLab to directly communicate with primary registry API
- ## Feature Flag https://docs.gitlab.com/ee/user/project/operations/feature_flags.html
+ ## Feature Flag https://docs.gitlab.com/ee/operations/feature_flags.html
feature_flags:
unleash:
# enabled: false
@@ -1239,6 +1242,7 @@ production: &base
## Matomo analytics.
# matomo_url: '_your_matomo_url'
# matomo_site_id: '_your_matomo_site_id'
+ # matomo_disable_cookies: false
rack_attack:
git_basic_auth:
diff --git a/config/helpers/incremental_webpack_compiler.js b/config/helpers/incremental_webpack_compiler.js
new file mode 100644
index 00000000000..786bb6071fa
--- /dev/null
+++ b/config/helpers/incremental_webpack_compiler.js
@@ -0,0 +1,128 @@
+const fs = require('fs');
+const path = require('path');
+
+const log = (msg, ...rest) => console.log(`IncrementalWebpackCompiler: ${msg}`, ...rest);
+
+// If we force a recompile immediately, the page reload doesn't seem to work.
+// Five seconds seem to work fine and the user can read the message
+const TIMEOUT = 5000;
+
+class NoopCompiler {
+ constructor() {
+ this.enabled = false;
+ }
+
+ filterEntryPoints(entryPoints) {
+ return entryPoints;
+ }
+
+ logStatus() {}
+
+ setupMiddleware() {}
+}
+
+class IncrementalWebpackCompiler {
+ constructor(historyFilePath) {
+ this.enabled = true;
+ this.history = {};
+ this.compiledEntryPoints = new Set([
+ // Login page
+ 'pages.sessions.new',
+ // Explore page
+ 'pages.root',
+ ]);
+ this.historyFilePath = historyFilePath;
+ this._loadFromHistory();
+ }
+
+ filterEntryPoints(entrypoints) {
+ return Object.fromEntries(
+ Object.entries(entrypoints).map(([key, val]) => {
+ if (this.compiledEntryPoints.has(key)) {
+ return [key, val];
+ }
+ return [key, ['./webpack_non_compiled_placeholder.js']];
+ }),
+ );
+ }
+
+ logStatus(totalCount) {
+ const current = this.compiledEntryPoints.size;
+ log(`Currently compiling route entrypoints: ${current} of ${totalCount}`);
+ }
+
+ setupMiddleware(app, server) {
+ app.use((req, res, next) => {
+ const fileName = path.basename(req.url);
+
+ /**
+ * We are only interested in files that have a name like `pages.foo.bar.chunk.js`
+ * because those are the ones corresponding to our entry points.
+ *
+ * This filters out hot update files that are for example named "pages.foo.bar.[hash].hot-update.js"
+ */
+ if (fileName.startsWith('pages.') && fileName.endsWith('.chunk.js')) {
+ const chunk = fileName.replace(/\.chunk\.js$/, '');
+
+ this._addToHistory(chunk);
+
+ if (!this.compiledEntryPoints.has(chunk)) {
+ log(`First time we are seeing ${chunk}. Adding to compilation.`);
+
+ this.compiledEntryPoints.add(chunk);
+
+ setTimeout(() => {
+ server.middleware.invalidate(() => {
+ if (server.sockets) {
+ server.sockWrite(server.sockets, 'content-changed');
+ }
+ });
+ }, TIMEOUT);
+ }
+ }
+
+ next();
+ });
+ }
+
+ // private methods
+
+ _addToHistory(chunk) {
+ if (!this.history[chunk]) {
+ this.history[chunk] = { lastVisit: null, count: 0 };
+ }
+ this.history[chunk].lastVisit = Date.now();
+ this.history[chunk].count += 1;
+
+ try {
+ fs.writeFileSync(this.historyFilePath, JSON.stringify(this.history), 'utf8');
+ } catch (e) {
+ log('Warning – Could not write to history', e.message);
+ }
+ }
+
+ _loadFromHistory() {
+ try {
+ this.history = JSON.parse(fs.readFileSync(this.historyFilePath, 'utf8'));
+ const entryPoints = Object.keys(this.history);
+ log(`Successfully loaded history containing ${entryPoints.length} entry points`);
+ /*
+ TODO: Let's ask a few folks to give us their history file after a milestone of usage
+ Then we can make smarter decisions on when to throw out rather than rendering everything
+ Something like top 20/30/40 entries visited in the last 7/10/15 days might be sufficient
+ */
+ this.compiledEntryPoints = new Set([...this.compiledEntryPoints, ...entryPoints]);
+ } catch (e) {
+ log(`No history found...`);
+ }
+ }
+}
+
+module.exports = (enabled, historyFilePath) => {
+ log(`Status – ${enabled ? 'enabled' : 'disabled'}`);
+
+ if (enabled) {
+ return new IncrementalWebpackCompiler(historyFilePath);
+ }
+ return new NoopCompiler();
+};
diff --git a/config/initializers/01_secret_token.rb b/config/initializers/01_secret_token.rb
index d7e725477eb..c4520b4b313 100644
--- a/config/initializers/01_secret_token.rb
+++ b/config/initializers/01_secret_token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# WARNING: Before you make a change to secrets.yml, read the development guide for GitLab secrets
# doc/development/application_secrets.md.
#
diff --git a/config/initializers/0_acts_as_taggable.rb b/config/initializers/0_acts_as_taggable.rb
index 50dc47673ab..9a92b8f2d18 100644
--- a/config/initializers/0_acts_as_taggable.rb
+++ b/config/initializers/0_acts_as_taggable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
ActsAsTaggableOn.strict_case_match = true
# tags_counter enables caching count of tags which results in an update whenever a tag is added or removed
diff --git a/config/initializers/0_inject_enterprise_edition_module.rb b/config/initializers/0_inject_enterprise_edition_module.rb
index b3ebb44ef25..7478727f869 100644
--- a/config/initializers/0_inject_enterprise_edition_module.rb
+++ b/config/initializers/0_inject_enterprise_edition_module.rb
@@ -6,12 +6,7 @@ module InjectEnterpriseEditionModule
def prepend_if_ee(constant, with_descendants: false)
return unless Gitlab.ee?
- ee_module = constant.constantize
- prepend(ee_module)
-
- if with_descendants
- descendants.each { |descendant| descendant.prepend(ee_module) }
- end
+ prepend_module(constant.constantize, with_descendants)
end
def extend_if_ee(constant)
@@ -21,6 +16,34 @@ module InjectEnterpriseEditionModule
def include_if_ee(constant)
include(constant.constantize) if Gitlab.ee?
end
+
+ def prepend_ee_mod(with_descendants: false)
+ return unless Gitlab.ee?
+
+ prepend_module(ee_module, with_descendants)
+ end
+
+ def extend_ee_mod
+ extend(ee_module) if Gitlab.ee?
+ end
+
+ def include_ee_mod
+ include(ee_module) if Gitlab.ee?
+ end
+
+ private
+
+ def prepend_module(mod, with_descendants)
+ prepend(mod)
+
+ if with_descendants
+ descendants.each { |descendant| descendant.prepend(mod) }
+ end
+ end
+
+ def ee_module
+ ::EE.const_get(name, false)
+ end
end
Module.prepend(InjectEnterpriseEditionModule)
diff --git a/config/initializers/0_inject_feature_flags.rb b/config/initializers/0_inject_feature_flags.rb
index 5b33b3bb4ea..daf208bd960 100644
--- a/config/initializers/0_inject_feature_flags.rb
+++ b/config/initializers/0_inject_feature_flags.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This needs to be loaded after
# config/initializers/0_inject_enterprise_edition_module.rb
diff --git a/config/initializers/0_marginalia.rb b/config/initializers/0_marginalia.rb
index 5c6cf7752c4..952dd75886d 100644
--- a/config/initializers/0_marginalia.rb
+++ b/config/initializers/0_marginalia.rb
@@ -9,6 +9,11 @@ require 'marginalia'
# Refer: https://github.com/basecamp/marginalia/blob/v1.8.0/lib/marginalia/railtie.rb#L67
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Marginalia::ActiveRecordInstrumentation)
+# By default, PostgreSQL only tracks the first 1024 bytes of a SQL
+# query. Prepending the comment allows us to trace the source of the
+# query without having to increase the `track_activity_query_size`
+# parameter.
+Marginalia::Comment.prepend_comment = true unless Rails.env.test? # Some tests do string matching against raw SQL
Marginalia::Comment.components = [:application, :controller, :action, :correlation_id, :jid, :job_class]
# As mentioned in https://github.com/basecamp/marginalia/pull/93/files,
diff --git a/config/initializers/0_post_deployment_migrations.rb b/config/initializers/0_post_deployment_migrations.rb
index 2d647f72840..dabb82c8525 100644
--- a/config/initializers/0_post_deployment_migrations.rb
+++ b/config/initializers/0_post_deployment_migrations.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Post deployment migrations are included by default. This file must be loaded
# before other initializers as Rails may otherwise memoize a list of migrations
# excluding the post deployment migrations.
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index bbed08f5044..c478123f4eb 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../settings'
require_relative '../object_store_settings'
require_relative '../smime_signature_settings'
@@ -309,6 +311,13 @@ Settings.pages['storage_path'] = Settings.pages['path']
Settings.pages['object_store'] = ObjectStoreSettings.legacy_parse(Settings.pages['object_store'])
#
+# GitLab documentation
+#
+Settings['gitlab_docs'] ||= Settingslogic.new({})
+Settings.gitlab_docs['enabled'] ||= false
+Settings.gitlab_docs['host'] = nil unless Settings.gitlab_docs.enabled
+
+#
# Geo
#
Gitlab.ee do
@@ -416,7 +425,7 @@ Settings.cron_jobs['stuck_ci_jobs_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['stuck_ci_jobs_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['stuck_ci_jobs_worker']['job_class'] = 'StuckCiJobsWorker'
Settings.cron_jobs['pipeline_schedule_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['pipeline_schedule_worker']['cron'] ||= '19 * * * *'
+Settings.cron_jobs['pipeline_schedule_worker']['cron'] ||= '3-59/10 * * * *'
Settings.cron_jobs['pipeline_schedule_worker']['job_class'] = 'PipelineScheduleWorker'
Settings.cron_jobs['expire_build_artifacts_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['expire_build_artifacts_worker']['cron'] ||= '*/7 * * * *'
@@ -445,6 +454,9 @@ Settings.cron_jobs['personal_access_tokens_expired_notification_worker']['job_cl
Settings.cron_jobs['repository_archive_cache_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['repository_archive_cache_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['repository_archive_cache_worker']['job_class'] = 'RepositoryArchiveCacheWorker'
+Settings.cron_jobs['packages_composer_cache_cleanup_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['packages_composer_cache_cleanup_worker']['cron'] ||= '30 * * * *'
+Settings.cron_jobs['packages_composer_cache_cleanup_worker']['job_class'] = 'Packages::Composer::CacheCleanupWorker'
Settings.cron_jobs['import_export_project_cleanup_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['import_export_project_cleanup_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['import_export_project_cleanup_worker']['job_class'] = 'ImportExportProjectCleanupWorker'
@@ -544,6 +556,15 @@ Settings.cron_jobs['schedule_merge_request_cleanup_refs_worker']['job_class'] =
Settings.cron_jobs['manage_evidence_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['manage_evidence_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['manage_evidence_worker']['job_class'] = 'Releases::ManageEvidenceWorker'
+Settings.cron_jobs['user_status_cleanup_batch_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['user_status_cleanup_batch_worker']['cron'] ||= '* * * * *'
+Settings.cron_jobs['user_status_cleanup_batch_worker']['job_class'] = 'UserStatusCleanup::BatchWorker'
+
+Gitlab.com do
+ Settings.cron_jobs['namespaces_in_product_marketing_emails_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['cron'] ||= '0 9 * * *'
+ Settings.cron_jobs['namespaces_in_product_marketing_emails_worker']['job_class'] = 'Namespaces::InProductMarketingEmailsWorker'
+end
Gitlab.ee do
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker'] ||= Settingslogic.new({})
@@ -597,6 +618,9 @@ Gitlab.ee do
Settings.cron_jobs['incident_sla_exceeded_check_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['incident_sla_exceeded_check_worker']['cron'] ||= '*/2 * * * *'
Settings.cron_jobs['incident_sla_exceeded_check_worker']['job_class'] = 'IncidentManagement::IncidentSlaExceededCheckWorker'
+ Settings.cron_jobs['incident_management_persist_oncall_rotation_worker'] ||= Settingslogic.new({})
+ Settings.cron_jobs['incident_management_persist_oncall_rotation_worker']['cron'] ||= '*/5 * * * *'
+ Settings.cron_jobs['incident_management_persist_oncall_rotation_worker']['job_class'] = 'IncidentManagement::OncallRotations::PersistAllRotationsShiftsJob'
Settings.cron_jobs['import_software_licenses_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['import_software_licenses_worker']['cron'] ||= '0 3 * * 0'
Settings.cron_jobs['import_software_licenses_worker']['job_class'] = 'ImportSoftwareLicensesWorker'
@@ -808,6 +832,7 @@ Settings.forti_token_cloud['enabled'] = false if Settings.forti_token_cloud['ena
Settings['extra'] ||= Settingslogic.new({})
Settings.extra['matomo_site_id'] ||= Settings.extra['piwik_site_id'] if Settings.extra['piwik_site_id'].present?
Settings.extra['matomo_url'] ||= Settings.extra['piwik_url'] if Settings.extra['piwik_url'].present?
+Settings.extra['matomo_disable_cookies'] = false if Settings.extra['matomo_disable_cookies'].nil?
#
# Rack::Attack settings
diff --git a/config/initializers/2_gitlab.rb b/config/initializers/2_gitlab.rb
index 8b7f245b7b0..5b78a471f8a 100644
--- a/config/initializers/2_gitlab.rb
+++ b/config/initializers/2_gitlab.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
require_dependency 'gitlab'
diff --git a/config/initializers/5_backend.rb b/config/initializers/5_backend.rb
index 46854af9b55..78910bb7675 100644
--- a/config/initializers/5_backend.rb
+++ b/config/initializers/5_backend.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.test?
required_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version_required)
current_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version)
diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb
index 827b15e5c8d..060b04be824 100644
--- a/config/initializers/6_validations.rb
+++ b/config/initializers/6_validations.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
def storage_validation_error(message)
raise "#{message}. Please fix this in your gitlab.yml before starting GitLab."
end
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 65ff6b656b9..a304f861db8 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'prometheus/client'
# Keep separate directories for separate processes
@@ -39,6 +41,32 @@ Sidekiq.configure_server do |config|
end
if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
+ # When running Puma in a Single mode, `on_master_start` and `on_worker_start` are the same.
+ # Thus, we order these events to run `reinitialize_on_pid_change` with `force: true` first.
+ Gitlab::Cluster::LifecycleEvents.on_master_start do
+ # Ensure that stale Prometheus metrics don't accumulate over time
+ Prometheus::CleanupMultiprocDirService.new.execute
+
+ ::Prometheus::Client.reinitialize_on_pid_change(force: true)
+
+ if Gitlab::Runtime.unicorn?
+ Gitlab::Metrics::Samplers::UnicornSampler.instance(Settings.monitoring.unicorn_sampler_interval).start
+ elsif Gitlab::Runtime.puma?
+ Gitlab::Metrics::Samplers::PumaSampler.instance.start
+ end
+
+ Gitlab::Metrics.gauge(:deployments, 'GitLab Version', {}, :max).set({ version: Gitlab::VERSION }, 1)
+
+ unless Gitlab::Runtime.sidekiq?
+ Gitlab::Metrics::RequestsRackMiddleware.initialize_metrics
+ end
+
+ Gitlab::Ci::Parsers.instrument!
+ rescue IOError => e
+ Gitlab::ErrorTracking.track_exception(e)
+ Gitlab::Metrics.error_detected!
+ end
+
Gitlab::Cluster::LifecycleEvents.on_worker_start do
defined?(::Prometheus::Client.reinitialize_on_pid_change) && Prometheus::Client.reinitialize_on_pid_change
@@ -53,25 +81,8 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
if Gitlab.ee? && Gitlab::Runtime.sidekiq?
Gitlab::Metrics::Samplers::GlobalSearchSampler.instance.start
end
- rescue IOError => e
- Gitlab::ErrorTracking.track_exception(e)
- Gitlab::Metrics.error_detected!
- end
-
- Gitlab::Cluster::LifecycleEvents.on_master_start do
- ::Prometheus::Client.reinitialize_on_pid_change(force: true)
-
- if Gitlab::Runtime.unicorn?
- Gitlab::Metrics::Samplers::UnicornSampler.instance(Settings.monitoring.unicorn_sampler_interval).start
- elsif Gitlab::Runtime.puma?
- Gitlab::Metrics::Samplers::PumaSampler.instance.start
- end
- Gitlab::Metrics.gauge(:deployments, 'GitLab Version', {}, :max).set({ version: Gitlab::VERSION }, 1)
-
- unless Gitlab::Runtime.sidekiq?
- Gitlab::Metrics::RequestsRackMiddleware.initialize_metrics
- end
+ Gitlab::Ci::Parsers.instrument!
rescue IOError => e
Gitlab::ErrorTracking.track_exception(e)
Gitlab::Metrics.error_detected!
diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb
index af4967521b8..a6025a6dbf0 100644
--- a/config/initializers/7_redis.rb
+++ b/config/initializers/7_redis.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Make sure we initialize a Redis connection pool before multi-threaded
# execution starts by
# 1. Sidekiq
diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb
index a4841a11a00..3cac012c2f7 100644
--- a/config/initializers/8_devise.rb
+++ b/config/initializers/8_devise.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Use this hook to configure devise mailer, warden hooks and so forth. The first
# four configuration values can also be set straight in your models.
Devise.setup do |config|
diff --git a/config/initializers/8_gitaly.rb b/config/initializers/8_gitaly.rb
index f4f116e67f7..d7b5bfbc269 100644
--- a/config/initializers/8_gitaly.rb
+++ b/config/initializers/8_gitaly.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'uri'
Gitlab.config.repositories.storages.keys.each do |storage|
diff --git a/config/initializers/9_fast_gettext.rb b/config/initializers/9_fast_gettext.rb
index f836e6e971d..0c28a1b7ce8 100644
--- a/config/initializers/9_fast_gettext.rb
+++ b/config/initializers/9_fast_gettext.rb
@@ -1,2 +1,4 @@
+# frozen_string_literal: true
+
FastGettext.default_available_locales = Gitlab::I18n.available_locales
I18n.available_locales = Gitlab::I18n.available_locales
diff --git a/config/initializers/action_dispatch_http_mime_negotiation.rb b/config/initializers/action_dispatch_http_mime_negotiation.rb
index 6c31de2de55..2d6afb97a60 100644
--- a/config/initializers/action_dispatch_http_mime_negotiation.rb
+++ b/config/initializers/action_dispatch_http_mime_negotiation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Starting with Rails 5, Rails tries to determine the request format based on
# the extension of the full URL path if no explicit `format` param or `Accept`
# header is provided, like when simply browsing to a page in your browser.
diff --git a/config/initializers/action_mailer_hooks.rb b/config/initializers/action_mailer_hooks.rb
index 41e34b6eb20..46d5e387d9d 100644
--- a/config/initializers/action_mailer_hooks.rb
+++ b/config/initializers/action_mailer_hooks.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Gitlab.config.gitlab.email_enabled
ActionMailer::Base.register_interceptor(::Gitlab::Email::Hook::DisableEmailInterceptor)
ActionMailer::Base.logger = nil
diff --git a/config/initializers/active_record_data_types.rb b/config/initializers/active_record_data_types.rb
index 3fa999e9908..f8f0a69622f 100644
--- a/config/initializers/active_record_data_types.rb
+++ b/config/initializers/active_record_data_types.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# ActiveRecord custom data type for storing datetimes with timezone information.
# See https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/11229
diff --git a/config/initializers/active_record_ping.rb b/config/initializers/active_record_ping.rb
index 349a7e4a496..196f587f565 100644
--- a/config/initializers/active_record_ping.rb
+++ b/config/initializers/active_record_ping.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# # frozen_string_literal: true
if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: false)
diff --git a/config/initializers/active_record_preloader.rb b/config/initializers/active_record_preloader.rb
index d585ecda307..349ca6c4831 100644
--- a/config/initializers/active_record_preloader.rb
+++ b/config/initializers/active_record_preloader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveRecord
module Associations
class Preloader
diff --git a/config/initializers/active_record_schema_ignore_tables.rb b/config/initializers/active_record_schema_ignore_tables.rb
index 0a840bbf1d8..55c44e00c40 100644
--- a/config/initializers/active_record_schema_ignore_tables.rb
+++ b/config/initializers/active_record_schema_ignore_tables.rb
@@ -1,2 +1,4 @@
+# frozen_string_literal: true
+
# Ignore dynamically managed partitions in static application schema
ActiveRecord::SchemaDumper.ignore_tables += ["#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.*"]
diff --git a/config/initializers/active_record_table_definition.rb b/config/initializers/active_record_table_definition.rb
index 9220620da41..3c6311f034f 100644
--- a/config/initializers/active_record_table_definition.rb
+++ b/config/initializers/active_record_table_definition.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# ActiveRecord custom method definitions with timezone information.
# See https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/11229
diff --git a/config/initializers/ar_speed_up_migration_checking.rb b/config/initializers/ar_speed_up_migration_checking.rb
index c4ffcc54cb2..778b2ee0cb1 100644
--- a/config/initializers/ar_speed_up_migration_checking.rb
+++ b/config/initializers/ar_speed_up_migration_checking.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Rails.env.test?
require 'active_record/migration'
diff --git a/config/initializers/asset_proxy_settings.rb b/config/initializers/asset_proxy_settings.rb
index 92247aba1b8..48eedcee681 100644
--- a/config/initializers/asset_proxy_settings.rb
+++ b/config/initializers/asset_proxy_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#
# Asset proxy settings
#
diff --git a/config/initializers/attr_encrypted_no_db_connection.rb b/config/initializers/attr_encrypted_no_db_connection.rb
index 7ad458929db..f8d0effbbad 100644
--- a/config/initializers/attr_encrypted_no_db_connection.rb
+++ b/config/initializers/attr_encrypted_no_db_connection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module AttrEncrypted
module Adapters
module ActiveRecord
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
index 2f892f78112..f3e01d23448 100644
--- a/config/initializers/backtrace_silencers.rb
+++ b/config/initializers/backtrace_silencers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.backtrace_cleaner.remove_silencers!
# This allows us to see the proper caller of SQL calls in {development,test}.log
diff --git a/config/initializers/batch_loader.rb b/config/initializers/batch_loader.rb
index 2e2256b0eb9..d88b43fbcea 100644
--- a/config/initializers/batch_loader.rb
+++ b/config/initializers/batch_loader.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Rails.application.config.middleware.use(BatchLoader::Middleware)
diff --git a/config/initializers/bootstrap_form.rb b/config/initializers/bootstrap_form.rb
index bbc1d83a63f..8121bc8bf1d 100644
--- a/config/initializers/bootstrap_form.rb
+++ b/config/initializers/bootstrap_form.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module BootstrapFormBuilderCustomization
def label_class
"label-bold"
diff --git a/config/initializers/bullet.rb b/config/initializers/bullet.rb
index d1f72ca3ce7..2d21514b121 100644
--- a/config/initializers/bullet.rb
+++ b/config/initializers/bullet.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
def bullet_enabled?
Gitlab::Utils.to_boolean(ENV['ENABLE_BULLET'].to_s)
end
diff --git a/config/initializers/cluster_events_before_phased_restart.rb b/config/initializers/cluster_events_before_phased_restart.rb
index aae5470d6ae..d029adbe363 100644
--- a/config/initializers/cluster_events_before_phased_restart.rb
+++ b/config/initializers/cluster_events_before_phased_restart.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Technical debt, this should be ideally upstreamed.
#
# However, there's currently no way to hook before doing
diff --git a/config/initializers/console_message.rb b/config/initializers/console_message.rb
index fe47195062b..2c05c2c9a24 100644
--- a/config/initializers/console_message.rb
+++ b/config/initializers/console_message.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Rails/Output
if Gitlab::Runtime.console?
# note that this will not print out when using `spring`
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
index e9a71f32581..375a23fdfd6 100644
--- a/config/initializers/cookies_serializer.rb
+++ b/config/initializers/cookies_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.use_cookies_with_metadata = true
diff --git a/config/initializers/date_time_formats.rb b/config/initializers/date_time_formats.rb
index 1939ced512d..44d07869033 100644
--- a/config/initializers/date_time_formats.rb
+++ b/config/initializers/date_time_formats.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# :short - 10 Nov
# :medium - Nov 10, 2007
# :long - November 10, 2007
diff --git a/config/initializers/default_url_options.rb b/config/initializers/default_url_options.rb
index de2cdc6ecae..138a8e467c7 100644
--- a/config/initializers/default_url_options.rb
+++ b/config/initializers/default_url_options.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
default_url_options = {
host: Gitlab.config.gitlab.host,
protocol: Gitlab.config.gitlab.protocol,
diff --git a/config/initializers/deprecations.rb b/config/initializers/deprecations.rb
index 2b07ca665e2..3d03efe67e0 100644
--- a/config/initializers/deprecations.rb
+++ b/config/initializers/deprecations.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Rails.env.development? || ENV['GITLAB_LEGACY_PATH_LOG_MESSAGE']
deprecator = ActiveSupport::Deprecation.new('11.0', 'GitLab')
diff --git a/config/initializers/direct_upload_support.rb b/config/initializers/direct_upload_support.rb
index 919b80b79c0..880aea7d114 100644
--- a/config/initializers/direct_upload_support.rb
+++ b/config/initializers/direct_upload_support.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DirectUploadsValidator
SUPPORTED_DIRECT_UPLOAD_PROVIDERS = [ObjectStorage::Config::GOOGLE_PROVIDER,
ObjectStorage::Config::AWS_PROVIDER,
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 6b54b5074d5..1cf70909997 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Doorkeeper.configure do
# Change the ORM that doorkeeper will use.
# Currently supported options are :active_record, :mongoid2, :mongoid3, :mongo_mapper
diff --git a/config/initializers/doorkeeper_openid_connect.rb b/config/initializers/doorkeeper_openid_connect.rb
index 3523776c4f7..12a963ce45d 100644
--- a/config/initializers/doorkeeper_openid_connect.rb
+++ b/config/initializers/doorkeeper_openid_connect.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Doorkeeper::OpenidConnect.configure do
issuer Gitlab.config.gitlab.url
diff --git a/config/initializers/etag_caching.rb b/config/initializers/etag_caching.rb
index eba88801141..2e5574d2602 100644
--- a/config/initializers/etag_caching.rb
+++ b/config/initializers/etag_caching.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This middleware has to come after Gitlab::Metrics::RackMiddleware
# in the middleware stack, because it tracks events with
# GitLab Performance Monitoring
diff --git a/config/initializers/faraday.rb b/config/initializers/faraday.rb
new file mode 100644
index 00000000000..2700751e79f
--- /dev/null
+++ b/config/initializers/faraday.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+::Faraday::Request.register_middleware(gitlab_error_callback: -> { ::Gitlab::Faraday::ErrorCallback })
diff --git a/config/initializers/fill_shards.rb b/config/initializers/fill_shards.rb
index 90c0d63e4fe..e2889f59574 100644
--- a/config/initializers/fill_shards.rb
+++ b/config/initializers/fill_shards.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# The explicit schema version check is needed because during our migration rollback testing,
# `Shard.connected?` could be cached and return true even though the table doesn't exist
return unless Shard.connected?
diff --git a/config/initializers/fix_local_cache_middleware.rb b/config/initializers/fix_local_cache_middleware.rb
index 2644ee6a7d3..94da6d9c0e0 100644
--- a/config/initializers/fix_local_cache_middleware.rb
+++ b/config/initializers/fix_local_cache_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module LocalCacheRegistryCleanupWithEnsure
LocalCacheRegistry =
ActiveSupport::Cache::Strategy::LocalCache::LocalCacheRegistry
diff --git a/config/initializers/fog_google_https_private_urls.rb b/config/initializers/fog_google_https_private_urls.rb
index ef6afb2b686..78cbd41a609 100644
--- a/config/initializers/fog_google_https_private_urls.rb
+++ b/config/initializers/fog_google_https_private_urls.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#
# Monkey patching the https support for private urls
# See https://gitlab.com/gitlab-org/gitlab/issues/4879
diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb
index f505fb5843a..85ec8cad0a3 100644
--- a/config/initializers/forbid_sidekiq_in_transactions.rb
+++ b/config/initializers/forbid_sidekiq_in_transactions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Sidekiq
module Worker
EnqueueFromTransactionError = Class.new(StandardError)
diff --git a/config/initializers/gettext_rails_i18n_patch.rb b/config/initializers/gettext_rails_i18n_patch.rb
index 09c9b325a04..c23049e93c9 100644
--- a/config/initializers/gettext_rails_i18n_patch.rb
+++ b/config/initializers/gettext_rails_i18n_patch.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'gettext_i18n_rails/haml_parser'
require 'gettext_i18n_rails_js/parser/javascript'
require 'json'
diff --git a/config/initializers/gitlab_kas_secret.rb b/config/initializers/gitlab_kas_secret.rb
index 5e86e954684..8955f71a597 100644
--- a/config/initializers/gitlab_kas_secret.rb
+++ b/config/initializers/gitlab_kas_secret.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Gitlab::Kas.ensure_secret!
diff --git a/config/initializers/gitlab_shell_secret_token.rb b/config/initializers/gitlab_shell_secret_token.rb
index 529dcdd4644..e11f65bb8ca 100644
--- a/config/initializers/gitlab_shell_secret_token.rb
+++ b/config/initializers/gitlab_shell_secret_token.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Gitlab::Shell.ensure_secret_token!
diff --git a/config/initializers/gitlab_workhorse_secret.rb b/config/initializers/gitlab_workhorse_secret.rb
index ed54dc11098..5c959a72bd1 100644
--- a/config/initializers/gitlab_workhorse_secret.rb
+++ b/config/initializers/gitlab_workhorse_secret.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
begin
Gitlab::Workhorse.secret
rescue
diff --git a/config/initializers/go_get.rb b/config/initializers/go_get.rb
index 7e7896b4900..830579f4a8a 100644
--- a/config/initializers/go_get.rb
+++ b/config/initializers/go_get.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Rails.application.config.middleware.use(Gitlab::Middleware::Go)
diff --git a/config/initializers/grpc.rb b/config/initializers/grpc.rb
index b96962fe7db..66b212ef131 100644
--- a/config/initializers/grpc.rb
+++ b/config/initializers/grpc.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
GRPC_LOGGER = Logger.new(Rails.root.join('log/grpc.log'))
diff --git a/config/initializers/hamlit.rb b/config/initializers/hamlit.rb
index b5bcae4bbfc..dda38d2a61f 100644
--- a/config/initializers/hamlit.rb
+++ b/config/initializers/hamlit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Hamlit::RailsTemplate.set_options(attr_quote: '"')
Hamlit::Filters.remove_filter('coffee')
diff --git a/config/initializers/health_check.rb b/config/initializers/health_check.rb
index 1496f20afc1..0b35aaf115b 100644
--- a/config/initializers/health_check.rb
+++ b/config/initializers/health_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
HealthCheck.setup do |config|
config.standard_checks = %w(database migrations cache)
config.full_checks = %w(database migrations cache)
diff --git a/config/initializers/http_hostname_override.rb b/config/initializers/http_hostname_override.rb
index 58dd380326f..5d2739c1f58 100644
--- a/config/initializers/http_hostname_override.rb
+++ b/config/initializers/http_hostname_override.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This override allows passing `@hostname_override` to the SNI protocol,
# which is used to lookup the correct SSL certificate in the
# request handshake process.
diff --git a/config/initializers/kaminari_active_record_relation_methods_with_limit.rb b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
index 55b98cda520..982cb69e532 100644
--- a/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
+++ b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Kaminari
# Active Record specific page scope methods implementations
module ActiveRecordRelationMethodsWithLimit
diff --git a/config/initializers/kaminari_config.rb b/config/initializers/kaminari_config.rb
index 3cbe9a058d7..8e10079ce36 100644
--- a/config/initializers/kaminari_config.rb
+++ b/config/initializers/kaminari_config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Kaminari.configure do |config|
config.default_per_page = 20
config.max_per_page = 100
diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb
index 5b068c15aad..e8479bc6aa4 100644
--- a/config/initializers/lograge.rb
+++ b/config/initializers/lograge.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Only use Lograge for Rails
unless Gitlab::Runtime.sidekiq?
Rails.application.reloader.to_prepare do
diff --git a/config/initializers/mail_encoding_patch.rb b/config/initializers/mail_encoding_patch.rb
index d53b058ba75..11a96625e08 100644
--- a/config/initializers/mail_encoding_patch.rb
+++ b/config/initializers/mail_encoding_patch.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Monkey patch mail 2.7.1 to fix quoted-printable issues with newlines
# The issues upstream invalidate SMIME signatures under some conditions
# This was working properly in 2.6.6
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
index acbdf8de5a6..5329232cc92 100644
--- a/config/initializers/mime_types.rb
+++ b/config/initializers/mime_types.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
diff --git a/config/initializers/mini_magick.rb b/config/initializers/mini_magick.rb
index db0e7bbaaa3..8e3e55279f7 100644
--- a/config/initializers/mini_magick.rb
+++ b/config/initializers/mini_magick.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
MiniMagick.configure do |config|
config.cli = :graphicsmagick
end
diff --git a/config/initializers/net_http_patch.rb b/config/initializers/net_http_patch.rb
new file mode 100644
index 00000000000..a50ba7580cc
--- /dev/null
+++ b/config/initializers/net_http_patch.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+# Monkey patch Net::HTTP to fix missing URL decoding for username and password in proxy settings
+#
+# See proposed upstream fix https://github.com/ruby/net-http/pull/5
+# See Ruby-lang issue https://bugs.ruby-lang.org/issues/17542
+# See issue on GitLab https://gitlab.com/gitlab-org/gitlab/-/issues/289836
+
+module Net
+ class HTTP < Protocol
+ def proxy_user
+ if environment_variable_is_multiuser_safe? && @proxy_from_env
+ user = proxy_uri&.user
+ CGI.unescape(user) unless user.nil?
+ else
+ @proxy_user
+ end
+ end
+
+ def proxy_pass
+ if environment_variable_is_multiuser_safe? && @proxy_from_env
+ pass = proxy_uri&.password
+ CGI.unescape(pass) unless pass.nil?
+ else
+ @proxy_pass
+ end
+ end
+
+ def environment_variable_is_multiuser_safe?
+ ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE
+ end
+ end
+end
diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb
index 115ee08dbb6..3d3ee5299e2 100644
--- a/config/initializers/new_framework_defaults.rb
+++ b/config/initializers/new_framework_defaults.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Remove this `if` condition when upgraded to rails 5.0.
# The body must be kept.
# Be sure to restart your server when you modify this file.
diff --git a/config/initializers/octokit.rb b/config/initializers/octokit.rb
index b3749258ec5..cd8c8ec24ee 100644
--- a/config/initializers/octokit.rb
+++ b/config/initializers/octokit.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Octokit.middleware.insert_after Octokit::Middleware::FollowRedirects, Gitlab::Octokit::Middleware
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index a2720ab9986..85984772d05 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Gitlab::Auth::Ldap::Config.enabled?
module OmniAuth::Strategies
Gitlab::Auth::Ldap::Config.available_servers.each do |server|
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index fa74d8620f4..85bfc4f0214 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'peek/adapters/redis'
Peek::Adapters::Redis.prepend ::Gitlab::PerformanceBar::RedisAdapterWhenPeekEnabled
@@ -11,6 +13,7 @@ Peek.into Peek::Views::Gitaly
Peek.into Peek::Views::RedisDetailed
Peek.into Peek::Views::Elasticsearch
Peek.into Peek::Views::Rugged
+Peek.into Peek::Views::ExternalHttp
Peek.into Peek::Views::BulletDetailed if defined?(Bullet)
Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled?
diff --git a/config/initializers/postgresql_cte.rb b/config/initializers/postgresql_cte.rb
index 68d53c4edbf..1ea0b4cfb58 100644
--- a/config/initializers/postgresql_cte.rb
+++ b/config/initializers/postgresql_cte.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Adds support for WITH statements when using PostgreSQL. The code here is taken
# from https://github.com/shmay/ctes_in_my_pg which at the time of writing has
# not been pushed to RubyGems. The license of this repository is as follows:
diff --git a/config/initializers/premailer.rb b/config/initializers/premailer.rb
index 87f8e67ef1c..77077888af3 100644
--- a/config/initializers/premailer.rb
+++ b/config/initializers/premailer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# See https://github.com/fphilipe/premailer-rails#configuration
Premailer::Rails.config.merge!(
generate_text_part: false,
diff --git a/config/initializers/query_limiting.rb b/config/initializers/query_limiting.rb
index 66864d1898e..66aefc97c6a 100644
--- a/config/initializers/query_limiting.rb
+++ b/config/initializers/query_limiting.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Gitlab::QueryLimiting.enable?
require_dependency 'gitlab/query_limiting/active_support_subscriber'
require_dependency 'gitlab/query_limiting/transaction'
diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb
deleted file mode 100644
index 7b0a8f0d7dd..00000000000
--- a/config/initializers/rack_attack_logging.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-#
-# Adds logging for all Rack Attack blocks and throttling events.
-
-ActiveSupport::Notifications.subscribe(/rack_attack/) do |name, start, finish, request_id, payload|
- req = payload[:request]
-
- case req.env['rack.attack.match_type']
- when :throttle, :blocklist, :track
- rack_attack_info = {
- message: 'Rack_Attack',
- env: req.env['rack.attack.match_type'],
- remote_ip: req.ip,
- request_method: req.request_method,
- path: req.fullpath,
- matched: req.env['rack.attack.matched']
- }
-
- throttles_with_user_information = [
- :throttle_authenticated_api,
- :throttle_authenticated_web,
- :throttle_authenticated_protected_paths_api,
- :throttle_authenticated_protected_paths_web
- ]
-
- if throttles_with_user_information.include? req.env['rack.attack.matched'].to_sym
- user_id = req.env['rack.attack.match_discriminator']
- user = User.find_by(id: user_id)
-
- rack_attack_info[:user_id] = user_id
- rack_attack_info['meta.user'] = user.username unless user.nil?
- end
-
- Gitlab::AuthLogger.error(rack_attack_info)
- when :safelist
- Gitlab::Instrumentation::Throttle.safelist = req.env['rack.attack.matched']
- end
-end
diff --git a/config/initializers/rack_lineprof.rb b/config/initializers/rack_lineprof.rb
index f7172fce9bc..e66bfd88907 100644
--- a/config/initializers/rack_lineprof.rb
+++ b/config/initializers/rack_lineprof.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# The default colors of rack-lineprof can be very hard to look at in terminals
# with darker backgrounds. This patch tweaks the colors a bit so the output is
# actually readable.
diff --git a/config/initializers/relative_naming_ci_namespace.rb b/config/initializers/relative_naming_ci_namespace.rb
index d9d3034150f..7380597722a 100644
--- a/config/initializers/relative_naming_ci_namespace.rb
+++ b/config/initializers/relative_naming_ci_namespace.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Description: https://coderwall.com/p/heed_q/rails-routing-and-namespaced-models
#
# This allows us to use CI ActiveRecord objects in all routes and use it:
diff --git a/config/initializers/request_context.rb b/config/initializers/request_context.rb
index f79f1f32d70..99e51ce498a 100644
--- a/config/initializers/request_context.rb
+++ b/config/initializers/request_context.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do |config|
config.middleware.insert_after RequestStore::Middleware, Gitlab::Middleware::RequestContext
end
diff --git a/config/initializers/request_profiler.rb b/config/initializers/request_profiler.rb
index fb5a7b8372e..8e426772b9a 100644
--- a/config/initializers/request_profiler.rb
+++ b/config/initializers/request_profiler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do |config|
config.middleware.use(Gitlab::RequestProfiler::Middleware)
end
diff --git a/config/initializers/routing_draw.rb b/config/initializers/routing_draw.rb
index f0f74954eef..4978073633c 100644
--- a/config/initializers/routing_draw.rb
+++ b/config/initializers/routing_draw.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Adds draw method into Rails routing
# It allows us to keep routing split into files
ActionDispatch::Routing::Mapper.prepend Gitlab::Patch::DrawRoute
diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb
index a1eddd6a2c2..df80d4f7f73 100644
--- a/config/initializers/sentry.rb
+++ b/config/initializers/sentry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Be sure to restart your server when you modify this file.
require 'gitlab/current_settings'
diff --git a/config/initializers/server_uptime.rb b/config/initializers/server_uptime.rb
index 46bf242e143..9e58a848007 100644
--- a/config/initializers/server_uptime.rb
+++ b/config/initializers/server_uptime.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Rails.application.config.booted_at = Time.now
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index da24881885e..6e0cd33aa96 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Be sure to restart your server when you modify this file.
require 'gitlab/current_settings'
diff --git a/config/initializers/sherlock.rb b/config/initializers/sherlock.rb
index 8f2ababb712..ba33ffa13c5 100644
--- a/config/initializers/sherlock.rb
+++ b/config/initializers/sherlock.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Gitlab::Sherlock.enabled?
Rails.application.configure do |config|
config.middleware.use(Gitlab::Sherlock::Middleware)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 43beae3f50d..19c5e4df854 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -31,9 +31,9 @@ Sidekiq.configure_server do |config|
Sidekiq.logger.formatter = Gitlab::SidekiqLogging::JSONFormatter.new
config.options[:job_logger] = Gitlab::SidekiqLogging::StructuredLogger
- # Remove the default-provided handler
+ # Remove the default-provided handler. The exception is logged inside
+ # Gitlab::SidekiqLogging::StructuredLogger
config.error_handlers.reject! { |handler| handler.is_a?(Sidekiq::ExceptionHandler::Logger) }
- config.error_handlers << Gitlab::SidekiqLogging::ExceptionHandler.new
end
config.redis = queues_config_hash
diff --git a/config/initializers/sprockets.rb b/config/initializers/sprockets.rb
index a20b7dc75e9..d0660574eb6 100644
--- a/config/initializers/sprockets.rb
+++ b/config/initializers/sprockets.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
Sprockets.register_compressor 'application/javascript', :terser, Terser::Compressor
diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb
index 4e19fec084a..3cdb5a5abcf 100644
--- a/config/initializers/static_files.rb
+++ b/config/initializers/static_files.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
app = Rails.application
if app.config.public_file_server.enabled
diff --git a/config/initializers/time_zone.rb b/config/initializers/time_zone.rb
index bca7411ad63..8ad6b2d3447 100644
--- a/config/initializers/time_zone.rb
+++ b/config/initializers/time_zone.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Time.zone = Gitlab.config.gitlab.time_zone || Time.zone
# The default is normally set by Rails in the
# active_support.initialize_time_zone Railtie, but we need to set it
diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb
index 3058bdeb84e..3f066953c23 100644
--- a/config/initializers/tracing.rb
+++ b/config/initializers/tracing.rb
@@ -8,6 +8,7 @@ if Labkit::Tracing.enabled?
# Instrument Redis
Labkit::Tracing::Redis.instrument
+ Labkit::Tracing::ExternalHttp.instrument
# Instrument Rails
Labkit::Tracing::Rails::ActiveRecordSubscriber.instrument
diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb
index a4528020c06..79e4b831c5e 100644
--- a/config/initializers/trusted_proxies.rb
+++ b/config/initializers/trusted_proxies.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Override Rack::Request to make use of the same list of trusted_proxies
# as the ActionDispatch::Request object. This is necessary for libraries
# like rack_attack where they don't use ActionDispatch, and we want them
diff --git a/config/initializers/validate_puma.rb b/config/initializers/validate_puma.rb
index ac5678c4b5a..9723765d00f 100644
--- a/config/initializers/validate_puma.rb
+++ b/config/initializers/validate_puma.rb
@@ -1,5 +1,11 @@
# frozen_string_literal: true
-if Gitlab::Runtime.puma? && ::Puma.cli_config.options[:workers].to_i == 0
- raise 'Puma is only supported in Cluster-mode: workers > 0'
+def max_puma_workers
+ Puma.cli_config.options[:workers].to_i
+end
+
+if Gitlab::Runtime.puma? && !Gitlab::Runtime.puma_in_clustered_mode?
+ raise 'Puma is only supported in Clustered mode (workers > 0)' if Gitlab.com?
+
+ warn 'WARNING: Puma is running in Single mode (workers = 0). Some features may not work. Please refer to https://gitlab.com/groups/gitlab-org/-/epics/5303 for info.'
end
diff --git a/config/initializers/warden.rb b/config/initializers/warden.rb
index 3cfab52efd1..2517c0cf5c2 100644
--- a/config/initializers/warden.rb
+++ b/config/initializers/warden.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do |config|
Warden::Manager.after_set_user(scope: :user) do |user, auth, opts|
Gitlab::Auth::UniqueIpsLimiter.limit_user!(user)
diff --git a/config/initializers/workhorse_multipart.rb b/config/initializers/workhorse_multipart.rb
index 9c170d1adfa..b68a6fc6ee5 100644
--- a/config/initializers/workhorse_multipart.rb
+++ b/config/initializers/workhorse_multipart.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rails.application.configure do |config|
# ApolloUploadServer::Middleware expects to find uploaded files ready to use
config.middleware.insert_before(ApolloUploadServer::Middleware, Gitlab::Middleware::Multipart)
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
index 999df20181e..85b2d840618 100644
--- a/config/initializers/wrap_parameters.rb
+++ b/config/initializers/wrap_parameters.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Be sure to restart your server when you modify this file.
#
# This file contains settings for ActionController::ParamsWrapper which
diff --git a/config/initializers/zz_metrics.rb b/config/initializers/zz_metrics.rb
index 430e4d60d61..7da1779f87b 100644
--- a/config/initializers/zz_metrics.rb
+++ b/config/initializers/zz_metrics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This file was prefixed with zz_ because we want to load it the last!
# See: https://gitlab.com/gitlab-org/gitlab-foss/issues/55611
@@ -88,6 +90,7 @@ def instrument_classes(instrumentation)
instrumentation.instrument_methods(Gitlab::Highlight)
instrumentation.instrument_instance_methods(Gitlab::Highlight)
+ instrumentation.instrument_instance_method(Gitlab::Ci::Config::Yaml::Tags::Resolver, :to_hash)
Gitlab.ee do
instrumentation.instrument_instance_methods(Elastic::Latest::GitInstanceProxy)
@@ -154,9 +157,13 @@ if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && d
# of the ActiveRecord methods. This has to take place _after_ initializing as
# for some unknown reason calling eager_load! earlier breaks Devise.
Gitlab::Application.config.after_initialize do
- Rails.application.eager_load!
+ # We should move all the logic of this file to somewhere else
+ # and require it after `Rails.application.initialize!` in `environment.rb` file.
+ models_path = Rails.root.join('app', 'models').to_s
- models = Rails.root.join('app', 'models').to_s
+ Dir.glob("**/*.rb", base: models_path).sort.each do |file|
+ require_dependency file
+ end
regex = Regexp.union(
ActiveRecord::Querying.public_instance_methods(false).map(&:to_s)
@@ -172,7 +179,7 @@ if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && d
else
loc = method.source_location
- loc && loc[0].start_with?(models) && method.source =~ regex
+ loc && loc[0].start_with?(models_path) && method.source =~ regex
end
end
@@ -202,4 +209,8 @@ if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && d
class ::Redis::Client
prepend TrackNewRedisConnections
end
+
+ Labkit::NetHttpPublisher.labkit_prepend!
+ Labkit::ExconPublisher.labkit_prepend!
+ Labkit::HTTPClientPublisher.labkit_prepend!
end
diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb
index 85c53ab4320..9eb1ebe77bf 100644
--- a/config/initializers_before_autoloader/000_inflections.rb
+++ b/config/initializers_before_autoloader/000_inflections.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format
diff --git a/config/known_invalid_graphql_queries.yml b/config/known_invalid_graphql_queries.yml
index 8ea9b662aa7..3dc4b10a6a8 100644
--- a/config/known_invalid_graphql_queries.yml
+++ b/config/known_invalid_graphql_queries.yml
@@ -1,5 +1,5 @@
---
filenames:
- - ee/app/assets/javascripts/on_demand_scans/graphql/dast_scan_create.mutation.graphql
- ee/app/assets/javascripts/oncall_schedules/graphql/mutations/update_oncall_schedule_rotation.mutation.graphql
- - ee/app/assets/javascripts/oncall_schedules/graphql/mutations/destroy_oncall_rotation.mutation.graphql
+ - ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/api_fuzzing_ci_configuration.query.graphql
+ - ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/create_api_fuzzing_configuration.mutation.graphql
diff --git a/config/metrics/counts_28d/20210201124930_deployments.yml b/config/metrics/counts_28d/20210201124930_deployments.yml
new file mode 100644
index 00000000000..e03785d62ba
--- /dev/null
+++ b/config/metrics/counts_28d/20210201124930_deployments.yml
@@ -0,0 +1,20 @@
+---
+key_path: counts_monthly.deployments
+description: Total deployments count for recent 28 days
+product_section: ops
+product_stage: release
+product_group: group::ops release
+product_category:
+value_type: number
+status: data_available
+milestone: 13.2
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35493
+time_frame: 28d
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/deployments.yml b/config/metrics/counts_28d/deployments.yml
deleted file mode 100644
index dabd50ef5be..00000000000
--- a/config/metrics/counts_28d/deployments.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: deployments
-description: Total deployments count for recent 28 days
-value_type: integer
-stage: release
-status: data_available
-default_generation: generation_1
-full_path:
- generation_1: counts_monthy.deployments
-milestone: 13.2
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35493
-group: 'group::ops release'
-time_frame: 28d
-data_source: database
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
diff --git a/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml b/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
new file mode 100644
index 00000000000..07b20fd2938
--- /dev/null
+++ b/config/metrics/counts_7d/20210201124931_g_project_management_issue_title_changed_weekly.yml
@@ -0,0 +1,20 @@
+---
+key_path: redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly
+description: Distinct users count that changed issue title in a group for last recent week
+product_stage: plan
+product_group: group::project management
+product_category: issue_tracking
+value_type: number
+status: data_available
+milestone: 13.6
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
+time_frame: 7d
+data_source: redis_hll
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
+
diff --git a/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml b/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml
deleted file mode 100644
index 997263f9e30..00000000000
--- a/config/metrics/counts_7d/g_project_management_issue_title_changed_weekly.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: g_project_management_issue_title_changed_weekly
-description: Distinct users count that changed issue title in a group for last recent week
-value_type: integer
-product_category: issue_tracking
-stage: plan
-status: data_available
-default_generation: generation_1
-full_path:
- generation_1: redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly
-milestone: 13.6
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/229918
-group: 'group::project management'
-time_frame: 7d
-data_source: redis_hll
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
diff --git a/config/metrics/counts_all/20210201124934_deployments.yml b/config/metrics/counts_all/20210201124934_deployments.yml
new file mode 100644
index 00000000000..8b93eaf989d
--- /dev/null
+++ b/config/metrics/counts_all/20210201124934_deployments.yml
@@ -0,0 +1,19 @@
+---
+key_path: counts.deployments
+description: Total deployments count
+product_section: ops
+product_stage: release
+product_group: group::ops release
+value_type: number
+status: data_available
+milestone: 8.12
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735
+time_frame: all
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20210204124930_servers.yml b/config/metrics/counts_all/20210204124930_servers.yml
new file mode 100644
index 00000000000..3103797ccce
--- /dev/null
+++ b/config/metrics/counts_all/20210204124930_servers.yml
@@ -0,0 +1,14 @@
+---
+key_path: gitaly.servers
+description: Total Gitalty Servers
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: number
+status: data_available
+time_frame: all
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/counts_all/20210204124932_clusters.yml b/config/metrics/counts_all/20210204124932_clusters.yml
new file mode 100644
index 00000000000..1bb86905502
--- /dev/null
+++ b/config/metrics/counts_all/20210204124932_clusters.yml
@@ -0,0 +1,14 @@
+---
+key_path: gitaly.clusters
+description: Total GitLab Managed clusters both enabled and disabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: number
+status: data_available
+time_frame: all
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/counts_all/deployments.yml b/config/metrics/counts_all/deployments.yml
deleted file mode 100644
index bb78e8d6144..00000000000
--- a/config/metrics/counts_all/deployments.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: deployments
-description: Total deployments count
-value_type: integer
-stage: release
-status: data_available
-default_generation: generation_1
-full_path:
- generation_1: counts.deployments
-milestone: 8.12
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735
-group: 'group::ops release'
-time_frame: all
-data_source: database
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
diff --git a/config/metrics/license/20210201124932_recorded_at.yml b/config/metrics/license/20210201124932_recorded_at.yml
new file mode 100644
index 00000000000..af60dcb329e
--- /dev/null
+++ b/config/metrics/license/20210201124932_recorded_at.yml
@@ -0,0 +1,20 @@
+---
+key_path: recorded_at
+description: When the Usage Ping computation was started
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+milestone: 8.10
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557
+time_frame: none
+data_source: ruby
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/license/20210201124933_uuid.yml b/config/metrics/license/20210201124933_uuid.yml
new file mode 100644
index 00000000000..6cd4ca58ef8
--- /dev/null
+++ b/config/metrics/license/20210201124933_uuid.yml
@@ -0,0 +1,20 @@
+---
+key_path: uuid
+description: GitLab instance unique identifier
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+milestone: 9.1
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521
+time_frame: none
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/license/20210204124827_hostname.yml b/config/metrics/license/20210204124827_hostname.yml
new file mode 100644
index 00000000000..6f878f04863
--- /dev/null
+++ b/config/metrics/license/20210204124827_hostname.yml
@@ -0,0 +1,19 @@
+---
+key_path: hostname
+description: Host name of GitLab instance
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source:
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+skip_validation: true
diff --git a/config/metrics/license/20210204124829_active_user_count.yml b/config/metrics/license/20210204124829_active_user_count.yml
new file mode 100644
index 00000000000..21dacb43d92
--- /dev/null
+++ b/config/metrics/license/20210204124829_active_user_count.yml
@@ -0,0 +1,19 @@
+---
+key_path: active_user_count
+description: This is named the instance_user_count in the Versions application.
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+skip_validation: true
diff --git a/config/metrics/license/20210204124854_license_management_jobs.yml b/config/metrics/license/20210204124854_license_management_jobs.yml
new file mode 100644
index 00000000000..f89df165662
--- /dev/null
+++ b/config/metrics/license/20210204124854_license_management_jobs.yml
@@ -0,0 +1,16 @@
+---
+key_path: counts.license_management_jobs
+description: Name on the GitLab license
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: number
+status: data_available
+time_frame: none
+data_source: database
+distribution: []
+tier:
+- premium
+- ultimate
+skip_validation: true
diff --git a/config/metrics/license/20210204124926_license_trial_ends_on.yml b/config/metrics/license/20210204124926_license_trial_ends_on.yml
new file mode 100644
index 00000000000..6e78c6239e9
--- /dev/null
+++ b/config/metrics/license/20210204124926_license_trial_ends_on.yml
@@ -0,0 +1,14 @@
+---
+key_path: license_trial_ends_on
+description: Date the license ends on
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/license/20210204124928_version.yml b/config/metrics/license/20210204124928_version.yml
new file mode 100644
index 00000000000..a5e8acb1eaa
--- /dev/null
+++ b/config/metrics/license/20210204124928_version.yml
@@ -0,0 +1,14 @@
+---
+key_path: gitaly.version
+description: Version of Gitaly
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/license/20210204124936_version.yml b/config/metrics/license/20210204124936_version.yml
new file mode 100644
index 00000000000..f9c28d40d3d
--- /dev/null
+++ b/config/metrics/license/20210204124936_version.yml
@@ -0,0 +1,14 @@
+---
+key_path: gitlab_pages.version
+description: The version number of GitLab Pages
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/license/20210204124938_recording_ce_finished_at.yml b/config/metrics/license/20210204124938_recording_ce_finished_at.yml
new file mode 100644
index 00000000000..bc8a3e57b45
--- /dev/null
+++ b/config/metrics/license/20210204124938_recording_ce_finished_at.yml
@@ -0,0 +1,16 @@
+---
+key_path: recording_ce_finished_at
+description: When the core features were computed
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source:
+distribution:
+- ce
+- ee
+tier: []
+skip_validation: true
diff --git a/config/metrics/license/recorded_at.yml b/config/metrics/license/recorded_at.yml
deleted file mode 100644
index 5b2b3b37290..00000000000
--- a/config/metrics/license/recorded_at.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: recorded_at
-description: When the Usage Ping computation was started
-value_type: string
-product_category: collection
-stage: growth
-status: data_available
-default_generation: generation_1
-full_path:
- generation_1: recorded_at
-milestone: 8.10
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557
-group: group::product analytics
-time_frame: none
-data_source: ruby
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
diff --git a/config/metrics/license/uuid.yml b/config/metrics/license/uuid.yml
deleted file mode 100644
index 38e0d74fc22..00000000000
--- a/config/metrics/license/uuid.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: uuid
-description: GitLab instance unique identifier
-value_type: string
-product_category: collection
-stage: growth
-status: data_available
-default_generation: generation_1
-full_path:
- generation_1: uuid
- generation_2: license.uuid
-milestone: 9.1
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521
-group: group::product analytics
-time_frame: none
-data_source: database
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
diff --git a/config/metrics/schema.json b/config/metrics/schema.json
index 4d1120a7d8d..d71eddab469 100644
--- a/config/metrics/schema.json
+++ b/config/metrics/schema.json
@@ -1,32 +1,32 @@
{
"type": "object",
- "required": ["name", "description", "value_type", "status", "default_generation", "full_path", "group", "time_frame", "data_source", "distribution", "tier"],
+ "required": ["key_path", "description", "value_type", "status", "product_group", "time_frame", "data_source", "distribution", "tier"],
"properties": {
- "name": {
+ "key_path": {
"type": "string"
},
"description": {
"type": "string"
},
- "value_type": {
- "type": "string",
- "enum": ["integer", "string", "number", "boolean"]
+ "product_section": {
+ "type": ["string", "null"]
},
- "product_category": {
+ "product_stage": {
"type": ["string", "null"]
},
- "stage": {
+ "product_group": {
+ "type": "string"
+ },
+ "product_category": {
"type": ["string", "null"]
},
+ "value_type": {
+ "type": "string",
+ "enum": ["integer", "string", "number", "boolean"]
+ },
"status": {
"type": ["string"],
- "enum": ["data_available", "planned", "in_progress", "implmented"]
- },
- "default_generation": {
- "type": "string"
- },
- "full_path": {
- "type": "object"
+ "enum": ["data_available", "planned", "in_progress", "implemented"]
},
"milestone": {
"type": ["number", "null"]
@@ -37,9 +37,6 @@
"introduced_by_url": {
"type": ["string", "null"]
},
- "group": {
- "type": "string"
- },
"time_frame": {
"type": "string",
"enum": ["7d", "28d", "all", "none"]
@@ -61,6 +58,9 @@
"type": "string",
"enum": ["free", "starter", "premium", "ultimate", "bronze", "silver", "gold"]
}
+ },
+ "skip_validation": {
+ "type": "boolean"
}
}
}
diff --git a/config/metrics/settings/20210201124935_database_adapter.yml b/config/metrics/settings/20210201124935_database_adapter.yml
new file mode 100644
index 00000000000..020325995b1
--- /dev/null
+++ b/config/metrics/settings/20210201124935_database_adapter.yml
@@ -0,0 +1,18 @@
+---
+key_path: database.adapter
+description: This metric only returns a value of PostgreSQL in supported versions of GitLab. It could be removed from the usage ping. Historically MySQL was also supported.
+product_section: enablement
+product_stage: enablement
+product_group: group::enablement distribution
+product_category: collection
+value_type: string
+status: data_available
+time_frame: none
+data_source: database
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml b/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml
new file mode 100644
index 00000000000..41f6d432b78
--- /dev/null
+++ b/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: instance_auto_devops_enabled
+description: Whether auto DevOps is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124858_container_registry_enabled.yml b/config/metrics/settings/20210204124858_container_registry_enabled.yml
new file mode 100644
index 00000000000..53567998a76
--- /dev/null
+++ b/config/metrics/settings/20210204124858_container_registry_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: container_registry_enabled
+description: Whether container registry is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml b/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml
new file mode 100644
index 00000000000..cecb9035dc6
--- /dev/null
+++ b/config/metrics/settings/20210204124900_dependency_proxy_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: dependency_proxy_enabled
+description: Whether dependency proxy is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml b/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml
new file mode 100644
index 00000000000..5cdb62237e4
--- /dev/null
+++ b/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: gitlab_shared_runners_enabled
+description: Whether shared runners is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124904_gravatar_enabled.yml b/config/metrics/settings/20210204124904_gravatar_enabled.yml
new file mode 100644
index 00000000000..7102c96332a
--- /dev/null
+++ b/config/metrics/settings/20210204124904_gravatar_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: gravatar_enabled
+description: Whether gravatar is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124906_ldap_enabled.yml b/config/metrics/settings/20210204124906_ldap_enabled.yml
new file mode 100644
index 00000000000..b0bdeded7d9
--- /dev/null
+++ b/config/metrics/settings/20210204124906_ldap_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: ldap_enabled
+description: Whether LDAP is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124908_mattermost_enabled.yml b/config/metrics/settings/20210204124908_mattermost_enabled.yml
new file mode 100644
index 00000000000..7082b6c4ec5
--- /dev/null
+++ b/config/metrics/settings/20210204124908_mattermost_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: mattermost_enabled
+description: Whether Mattermost is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124910_omniauth_enabled.yml b/config/metrics/settings/20210204124910_omniauth_enabled.yml
new file mode 100644
index 00000000000..10483bd977b
--- /dev/null
+++ b/config/metrics/settings/20210204124910_omniauth_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: omniauth_enabled
+description: Whether OmniAuth is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124912_prometheus_enabled.yml b/config/metrics/settings/20210204124912_prometheus_enabled.yml
new file mode 100644
index 00000000000..0e6199e9976
--- /dev/null
+++ b/config/metrics/settings/20210204124912_prometheus_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: prometheus_enabled
+description: Whether the bundled Prometheus is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml b/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
new file mode 100644
index 00000000000..50b08c15919
--- /dev/null
+++ b/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: prometheus_metrics_enabled
+description: Whether Prometheus Metrics endpoint is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124916_reply_by_email_enabled.yml b/config/metrics/settings/20210204124916_reply_by_email_enabled.yml
new file mode 100644
index 00000000000..82defcf4014
--- /dev/null
+++ b/config/metrics/settings/20210204124916_reply_by_email_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: reply_by_email_enabled
+description: Whether incoming email is setup
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124918_signup_enabled.yml b/config/metrics/settings/20210204124918_signup_enabled.yml
new file mode 100644
index 00000000000..49d997bd2a8
--- /dev/null
+++ b/config/metrics/settings/20210204124918_signup_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: signup_enabled
+description: Whether public signup is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml b/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml
new file mode 100644
index 00000000000..d3eb20e93fd
--- /dev/null
+++ b/config/metrics/settings/20210204124920_web_ide_clientside_preview_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: web_ide_clientside_preview_enabled
+description: Whether web ide clientside preview is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124922_grafana_link_enabled.yml b/config/metrics/settings/20210204124922_grafana_link_enabled.yml
new file mode 100644
index 00000000000..a78936d3324
--- /dev/null
+++ b/config/metrics/settings/20210204124922_grafana_link_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: grafana_link_enabled
+description: Whether Grafana is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124924_elasticsearch_enabled.yml b/config/metrics/settings/20210204124924_elasticsearch_enabled.yml
new file mode 100644
index 00000000000..4b7d560b4ef
--- /dev/null
+++ b/config/metrics/settings/20210204124924_elasticsearch_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: elasticsearch_enabled
+description: Whether Elasticsearch is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/20210204124934_enabled.yml b/config/metrics/settings/20210204124934_enabled.yml
new file mode 100644
index 00000000000..3f4c8653dd1
--- /dev/null
+++ b/config/metrics/settings/20210204124934_enabled.yml
@@ -0,0 +1,14 @@
+---
+key_path: gitlab_pages.enabled
+description: Whether GitLab Pages is enabled
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: collection
+value_type: boolean
+status: data_available
+time_frame: none
+data_source:
+distribution: []
+tier: []
+skip_validation: true
diff --git a/config/metrics/settings/database_adapter.yml b/config/metrics/settings/database_adapter.yml
deleted file mode 100644
index b24fc933a08..00000000000
--- a/config/metrics/settings/database_adapter.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: adapter
-description: This metric only returns a value of PostgreSQL in supported versions of GitLab. It could be removed from the usage ping. Historically MySQL was also supported.
-value_type: string
-product_category: collection
-stage: growth
-status: data_available
-default_generation: generation_1
-full_path:
- generation_1: database.adapter
-group: group::enablement distribution
-time_frame: none
-data_source: database
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
diff --git a/config/object_store_settings.rb b/config/object_store_settings.rb
index 9f5323426d9..938129757f1 100644
--- a/config/object_store_settings.rb
+++ b/config/object_store_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Set default values for object_store settings
class ObjectStoreSettings
SUPPORTED_TYPES = %w(artifacts external_diffs lfs uploads packages dependency_proxy terraform_state pages).freeze
@@ -78,7 +80,7 @@ class ObjectStoreSettings
# "background_upload" => false,
# "proxy_download" => false,
# "remote_directory" => "artifacts"
- # }
+ # }
#
# Settings.lfs['object_store'] = {
# "enabled" => true,
@@ -97,7 +99,7 @@ class ObjectStoreSettings
# "background_upload" => false,
# "proxy_download" => true,
# "remote_directory" => "lfs-objects"
- # }
+ # }
#
# Note that with the common config:
# 1. Only one object store credentials can now be used. This is
@@ -124,6 +126,9 @@ class ObjectStoreSettings
target_config = common_config.merge(overrides.slice(*ALLOWED_OBJECT_STORE_OVERRIDES))
section = settings.try(store_type)
+ # Admins can selectively disable object storage for a specific
+ # type as an override in the consolidated settings.
+ next unless overrides.fetch('enabled', true)
next unless section
if section['enabled'] && target_config['bucket'].blank?
@@ -140,6 +145,8 @@ class ObjectStoreSettings
target_config['consolidated_settings'] = true
section['object_store'] = target_config
end
+
+ settings
end
private
@@ -152,8 +159,9 @@ class ObjectStoreSettings
return false unless settings.dig('object_store', 'connection').present?
WORKHORSE_ACCELERATED_TYPES.each do |store|
- # to_h is needed because something strange happens to
- # Settingslogic#dig when stub_storage_settings is run in tests:
+ # to_h is needed because we define `default` as a Gitaly storage name
+ # in stub_storage_settings. This causes Settingslogic to redefine Hash#default,
+ # which causes Hash#dig to fail when the key doesn't exist: https://gitlab.com/gitlab-org/gitlab/-/issues/286873
#
# (byebug) section.dig
# *** ArgumentError Exception: wrong number of arguments (given 0, expected 1+)
diff --git a/config/puma.example.development.rb b/config/puma.example.development.rb
index 28c2af3acb3..1901b5a0c1c 100644
--- a/config/puma.example.development.rb
+++ b/config/puma.example.development.rb
@@ -86,7 +86,7 @@ end
# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#nakayoshi_fork
if defined?(nakayoshi_fork)
- nakayoshi_fork unless ENV['DISABLE_PUMA_NAKAYOSHI_FORK'] == 'true'
+ nakayoshi_fork if ENV['ENABLE_PUMA_NAKAYOSHI_FORK'] == 'true'
end
# Use json formatter
diff --git a/config/puma.rb.example b/config/puma.rb.example
index 9fc354a8fe8..6684919e912 100644
--- a/config/puma.rb.example
+++ b/config/puma.rb.example
@@ -76,7 +76,7 @@ end
# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#nakayoshi_fork
if defined?(nakayoshi_fork)
- nakayoshi_fork unless ENV['DISABLE_PUMA_NAKAYOSHI_FORK'] == 'true'
+ nakayoshi_fork if ENV['ENABLE_PUMA_NAKAYOSHI_FORK'] == 'true'
end
# Use json formatter
diff --git a/config/puma_actioncable.example.development.rb b/config/puma_actioncable.example.development.rb
index d0da3dcd8f2..a12b4523848 100644
--- a/config/puma_actioncable.example.development.rb
+++ b/config/puma_actioncable.example.development.rb
@@ -86,7 +86,7 @@ end
# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#nakayoshi_fork
if defined?(nakayoshi_fork)
- nakayoshi_fork unless ENV['DISABLE_PUMA_NAKAYOSHI_FORK'] == 'true'
+ nakayoshi_fork if ENV['ENABLE_PUMA_NAKAYOSHI_FORK'] == 'true'
end
# Use json formatter
diff --git a/config/routes.rb b/config/routes.rb
index 31e483df326..90a26c0a20f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'sidekiq/web'
require 'sidekiq/cron/web'
require 'product_analytics/collector_app'
@@ -60,9 +62,10 @@ Rails.application.routes.draw do
end
# Search
- get 'search' => 'search#show'
+ get 'search' => 'search#show', as: :search
get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete
get 'search/count' => 'search#count', as: :search_count
+ get 'search/opensearch' => 'search#opensearch', as: :search_opensearch
# JSON Web Token
get 'jwt/auth' => 'jwt#auth'
@@ -158,6 +161,7 @@ Rails.application.routes.draw do
get :db_spin
get :sleep
get :kill
+ post :gc
end
end
@@ -288,7 +292,28 @@ Rails.application.routes.draw do
get '/sitemap' => 'sitemap#show', format: :xml
end
+ # Creates shorthand helper methods for project resources.
+ # For example; for the `namespace_project_path` this also creates `project_path`.
+ #
+ # TODO: We don't need the `Gitlab::Routing` module at all as we can use
+ # the `direct` DSL method of Rails to define url helpers. Move all the
+ # custom url helpers to use the `direct` DSL method and remove the `Gitlab::Routing`.
+ # For more information: https://gitlab.com/gitlab-org/gitlab/-/issues/299583
+ Gitlab::Application.routes.set.filter_map { |route| route.name if route.name&.include?('namespace_project') }.each do |name|
+ new_name = name.sub('namespace_project', 'project')
+
+ direct(new_name) do |project, *args|
+ # This is due to a bug I've found in Rails.
+ # For more information: https://gitlab.com/gitlab-org/gitlab/-/issues/299591
+ args.pop if args.last == {}
+
+ send("#{name}_url", project&.namespace, project, *args)
+ end
+ end
+
root to: "root#index"
get '*unmatched_route', to: 'application#route_not_found'
end
+
+Gitlab::Routing.add_helpers(TimeboxesRoutingHelper)
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index 71a927f59b9..3e04f0d97cb 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :admin do
resources :users, constraints: { id: %r{[a-zA-Z./0-9_\-]+} } do
resources :keys, only: [:show, :destroy]
diff --git a/config/routes/api.rb b/config/routes/api.rb
index 5dbfcc98f0f..dcbc98991e2 100644
--- a/config/routes/api.rb
+++ b/config/routes/api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
post '/api/graphql', to: 'graphql#execute'
mount GraphiQL::Rails::Engine, at: '/-/graphql-explorer', graphql_path: Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, '/api/graphql')
diff --git a/config/routes/dashboard.rb b/config/routes/dashboard.rb
index 7e29a36f020..6a3aa5ff0c1 100644
--- a/config/routes/dashboard.rb
+++ b/config/routes/dashboard.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
resource :dashboard, controller: 'dashboard', only: [] do
get :issues, action: :issues_calendar, constraints: lambda { |req| req.format == :ics }
get :issues
diff --git a/config/routes/development.rb b/config/routes/development.rb
index 9b2b47c6a21..4ea53e14120 100644
--- a/config/routes/development.rb
+++ b/config/routes/development.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Rails.env.development?
# Make the built-in Rails routes available in development, otherwise they'd
# get swallowed by the `namespace/project` route matcher below.
diff --git a/config/routes/explore.rb b/config/routes/explore.rb
index 59b53bdcf42..c6bf98b6fb3 100644
--- a/config/routes/explore.rb
+++ b/config/routes/explore.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :explore do
resources :projects, only: [:index] do
collection do
diff --git a/config/routes/git_http.rb b/config/routes/git_http.rb
index 715d4b5cc59..6899a89cc7d 100644
--- a/config/routes/git_http.rb
+++ b/config/routes/git_http.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
scope(path: '*repository_path', format: false) do
constraints(repository_path: Gitlab::PathRegex.repository_git_route_regex) do
scope(module: :repositories) do
@@ -42,7 +44,7 @@ scope(path: '*repository_path', format: false) do
wiki_redirect = redirect do |params, request|
container_path = params[:repository_path].delete_suffix('.wiki.git')
path = File.join(container_path, '-', 'wikis')
- path << "?#{request.query_string}" unless request.query_string.blank?
+ path += "?#{request.query_string}" unless request.query_string.blank?
path
end
@@ -54,7 +56,7 @@ scope(path: '*repository_path', format: false) do
constraints(repository_path: Gitlab::PathRegex.repository_route_regex) do
ref_redirect = redirect do |params, request|
path = "#{params[:repository_path]}.git/info/refs"
- path << "?#{request.query_string}" unless request.query_string.blank?
+ path += "?#{request.query_string}" unless request.query_string.blank?
path
end
diff --git a/config/routes/google_api.rb b/config/routes/google_api.rb
index a119b47c176..06f8d988072 100644
--- a/config/routes/google_api.rb
+++ b/config/routes/google_api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
scope '-' do
namespace :google_api do
resource :auth, only: [], controller: :authorizations do
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 012d5926872..e1ae860f6ec 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -111,6 +111,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resources :container_registries, only: [:index, :show], controller: 'registry/repositories'
resource :dependency_proxy, only: [:show, :update]
+ resources :email_campaigns, only: :index
end
scope(path: '*id',
diff --git a/config/routes/help.rb b/config/routes/help.rb
index 446310ba314..2a0aba8b632 100644
--- a/config/routes/help.rb
+++ b/config/routes/help.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
get 'help' => 'help#index'
get 'help/shortcuts' => 'help#shortcuts'
get 'help/instance_configuration' => 'help#instance_configuration'
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 5f94fb8d058..64830ef1e52 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Alias import callbacks under the /users/auth endpoint so that
# the OAuth2 callback URL can be restricted under http://example.com/users/auth
# instead of http://example.com.
diff --git a/config/routes/legacy_builds.rb b/config/routes/legacy_builds.rb
index 5ab2b953ce1..c08b581e101 100644
--- a/config/routes/legacy_builds.rb
+++ b/config/routes/legacy_builds.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do
collection do
resources :artifacts, only: [], controller: 'build_artifacts' do
diff --git a/config/routes/merge_requests.rb b/config/routes/merge_requests.rb
index 41d831f239e..b0bab1717a6 100644
--- a/config/routes/merge_requests.rb
+++ b/config/routes/merge_requests.rb
@@ -18,6 +18,7 @@ resources :merge_requests, concerns: :awardable, except: [:new, :create, :show],
get :coverage_reports
get :terraform_reports
get :codequality_reports
+ get :codequality_mr_diff_reports
scope constraints: ->(req) { req.format == :json }, as: :json do
get :commits
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 2e61bc8175e..21dfe173715 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -37,6 +37,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
+ namespace :security do
+ resource :configuration, only: [:show], controller: :configuration
+ end
+
resources :artifacts, only: [:index, :destroy]
resources :packages, only: [:index, :show, :destroy], module: :packages
@@ -83,10 +87,15 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
+ get :learn_gitlab, action: :index, controller: 'learn_gitlab'
+
namespace :ci do
resource :lint, only: [:show, :create]
resource :pipeline_editor, only: [:show], controller: :pipeline_editor, path: 'editor'
resources :daily_build_group_report_results, only: [:index], constraints: { format: /(csv|json)/ }
+ namespace :prometheus_metrics do
+ resources :histograms, only: [:create], constraints: { format: 'json' }
+ end
end
namespace :settings do
@@ -132,7 +141,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :project_members, except: [:show, :new, :edit], constraints: { id: %r{[a-zA-Z./0-9_\-#%+]+} }, concerns: :access_requestable do
+ resources :project_members, except: [:show, :new, :edit], constraints: { id: %r{[a-zA-Z./0-9_\-#%+:]+} }, concerns: :access_requestable do
collection do
delete :leave
@@ -219,7 +228,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :starrers, only: [:index]
resources :forks, only: [:index, :new, :create]
- resources :group_links, only: [:create, :update, :destroy], constraints: { id: /\d+/ }
+ resources :group_links, only: [:create, :update, :destroy], constraints: { id: /\d+|:id/ }
resource :import, only: [:new, :create, :show]
resource :avatar, only: [:show, :destroy]
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 43837f2ce34..61a407d5a35 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# All routing related to repository browsing
resource :repository, only: [:create] do
diff --git a/config/routes/sherlock.rb b/config/routes/sherlock.rb
index c9969f91c36..a9be434dba7 100644
--- a/config/routes/sherlock.rb
+++ b/config/routes/sherlock.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
if Gitlab::Sherlock.enabled?
namespace :sherlock do
resources :transactions, only: [:index, :show] do
diff --git a/config/routes/sidekiq.rb b/config/routes/sidekiq.rb
index 36ec8bc1d54..5f6755fc3b3 100644
--- a/config/routes/sidekiq.rb
+++ b/config/routes/sidekiq.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
constraints ::Constraints::AdminConstrainer.new do
mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
end
diff --git a/config/routes/snippets.rb b/config/routes/snippets.rb
index 9e0c42fa07d..5c162d0c37f 100644
--- a/config/routes/snippets.rb
+++ b/config/routes/snippets.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
resources :snippets, except: [:create, :update, :destroy], concerns: :awardable, constraints: { id: /\d+/ } do
member do
get :raw
diff --git a/config/routes/uploads.rb b/config/routes/uploads.rb
index fb8af76397c..71a868175a9 100644
--- a/config/routes/uploads.rb
+++ b/config/routes/uploads.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
scope path: :uploads do
# Note attachments and User/Group/Project avatars
get "-/system/:model/:mounted_as/:id/:filename",
diff --git a/config/routes/user.rb b/config/routes/user.rb
index 515a9a23360..41319b6d730 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -46,9 +46,13 @@ scope(constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }) d
get :contributed, as: :contributed_projects
get :starred, as: :starred_projects
get :snippets
+ get :followers
+ get :following
get :exists
get :suggests
get :activity
+ post :follow
+ post :unfollow
get '/', to: redirect('%{username}'), as: nil
end
end
diff --git a/config/routes/wiki.rb b/config/routes/wiki.rb
index 49ad39e8369..4d14743b3d3 100644
--- a/config/routes/wiki.rb
+++ b/config/routes/wiki.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
scope(controller: :wikis) do
scope(path: 'wikis', as: :wikis) do
get :git_access
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index d5b3925131e..678b585e6d7 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -158,6 +158,12 @@
- 1
- - group_saml_group_sync
- 1
+- - group_wikis_git_garbage_collect
+ - 1
+- - groups_schedule_bulk_repository_shard_moves
+ - 1
+- - groups_update_repository_storage
+ - 1
- - hashed_storage
- 1
- - import_issues_csv
@@ -166,6 +172,8 @@
- 2
- - incident_management_apply_incident_sla_exceeded_label
- 1
+- - incident_management_oncall_rotations_persist_shifts_job
+ - 1
- - invalid_gpg_signature_update
- 2
- - irker
@@ -270,6 +278,8 @@
- 1
- - project_update_repository_storage
- 1
+- - projects_git_garbage_collect
+ - 1
- - prometheus_create_default_alerts
- 1
- - propagate_integration
@@ -360,5 +370,7 @@
- 1
- - web_hooks_destroy
- 1
+- - wikis_git_garbage_collect
+ - 1
- - x509_certificate_revoke
- 1
diff --git a/config/smime_signature_settings.rb b/config/smime_signature_settings.rb
index 4a8cf1a06f7..4b50e01dba0 100644
--- a/config/smime_signature_settings.rb
+++ b/config/smime_signature_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Set default values for email_smime settings
class SmimeSignatureSettings
def self.parse(email_smime)
diff --git a/config/spring.rb b/config/spring.rb
index 0092d0fd1b0..3f00e6ab23f 100644
--- a/config/spring.rb
+++ b/config/spring.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
%w(
.ruby-version
.rbenv-vars
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 958b27d674d..19059c35c46 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -9,6 +9,7 @@ const MonacoWebpackPlugin = require('./plugins/monaco_webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const vendorDllHash = require('./helpers/vendor_dll_hash');
+const createIncrementalWebpackCompiler = require('./helpers/incremental_webpack_compiler');
const ROOT_PATH = path.resolve(__dirname, '..');
const VENDOR_DLL = process.env.WEBPACK_VENDOR_DLL && process.env.WEBPACK_VENDOR_DLL !== 'false';
@@ -23,6 +24,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';
const DEV_SERVER_LIVERELOAD = IS_DEV_SERVER && process.env.DEV_SERVER_LIVERELOAD !== 'false';
+const INCREMENTAL_COMPILER_ENABLED =
+ IS_DEV_SERVER &&
+ process.env.DEV_SERVER_INCREMENTAL &&
+ process.env.DEV_SERVER_INCREMENTAL !== 'false';
const WEBPACK_REPORT = process.env.WEBPACK_REPORT && process.env.WEBPACK_REPORT !== 'false';
const WEBPACK_MEMORY_TEST =
process.env.WEBPACK_MEMORY_TEST && process.env.WEBPACK_MEMORY_TEST !== 'false';
@@ -48,6 +53,11 @@ let autoEntriesCount = 0;
let watchAutoEntries = [];
const defaultEntries = ['./main'];
+const incrementalCompiler = createIncrementalWebpackCompiler(
+ INCREMENTAL_COMPILER_ENABLED,
+ path.join(CACHE_PATH, 'incremental-webpack-compiler-history.json'),
+);
+
function generateEntries() {
// generate automatic entry points
const autoEntries = {};
@@ -97,7 +107,7 @@ function generateEntries() {
jira_connect_app: './jira_connect/index.js',
};
- return Object.assign(manualEntries, autoEntries);
+ return Object.assign(manualEntries, incrementalCompiler.filterEntryPoints(autoEntries));
}
const alias = {
@@ -495,9 +505,13 @@ module.exports = {
watchAutoEntries.forEach((watchPath) => compilation.contextDependencies.add(watchPath));
// report our auto-generated bundle count
- console.log(
- `${autoEntriesCount} entries from '/pages' automatically added to webpack output.`,
- );
+ if (incrementalCompiler.enabled) {
+ incrementalCompiler.logStatus(autoEntriesCount);
+ } else {
+ console.log(
+ `${autoEntriesCount} entries from '/pages' automatically added to webpack output.`,
+ );
+ }
callback();
});
@@ -576,8 +590,10 @@ module.exports = {
*/
new webpack.IgnorePlugin(/moment/, /pikaday/),
].filter(Boolean),
-
devServer: {
+ before(app, server) {
+ incrementalCompiler.setupMiddleware(app, server);
+ },
host: DEV_SERVER_HOST,
port: DEV_SERVER_PORT,
public: DEV_SERVER_PUBLIC_ADDR,
diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile
index 06593a04093..c8474157fa5 100644
--- a/danger/changelog/Dangerfile
+++ b/danger/changelog/Dangerfile
@@ -35,7 +35,7 @@ def check_changelog_yaml(path)
elsif yaml["merge_request"] != gitlab.mr_json["iid"] && !cherry_pick_against_stable_branch
fail "Merge request ID was not set to #{gitlab.mr_json["iid"]}! #{SEE_DOC}"
end
-rescue Psych::SyntaxError, Psych::DisallowedClass, Psych::BadAlias
+rescue Psych::Exception
# YAML could not be parsed, fail the build.
fail "#{gitlab.html_link(path)} isn't valid YAML! #{SEE_DOC}"
rescue StandardError => e
diff --git a/danger/changes_size/Dangerfile b/danger/changes_size/Dangerfile
index 2c1d59427af..f37632ced33 100644
--- a/danger/changes_size/Dangerfile
+++ b/danger/changes_size/Dangerfile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# FIXME: git.info_for_file raises the following error
# /usr/local/bundle/gems/git-1.4.0/lib/git/lib.rb:956:in `command': (Danger::DSLError)
# [!] Invalid `Dangerfile` file:
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
index 816d7384a2d..96a0c08c184 100644
--- a/danger/commit_messages/Dangerfile
+++ b/danger/commit_messages/Dangerfile
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require_relative File.expand_path('../../lib/gitlab/danger/commit_linter', __dir__)
-require_relative File.expand_path('../../lib/gitlab/danger/merge_request_linter', __dir__)
+require_relative File.expand_path('../../tooling/danger/commit_linter', __dir__)
+require_relative File.expand_path('../../tooling/danger/merge_request_linter', __dir__)
COMMIT_MESSAGE_GUIDELINES = "https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#commit-messages-guidelines"
MORE_INFO = "For more information, take a look at our [Commit message guidelines](#{COMMIT_MESSAGE_GUIDELINES})."
@@ -54,7 +54,7 @@ end
# https://github.com/jonallured/danger-commit_lint because its output is not
# very helpful, and it doesn't offer the means of ignoring merge commits.
def lint_commit(commit)
- linter = Gitlab::Danger::CommitLinter.new(commit)
+ linter = Tooling::Danger::CommitLinter.new(commit)
# For now we'll ignore merge commits, as getting rid of those is a problem
# separate from enforcing good commit messages.
@@ -93,7 +93,7 @@ end
def lint_mr_title(mr_title)
commit = Struct.new(:message, :sha).new(mr_title)
- Gitlab::Danger::MergeRequestLinter.new(commit).lint
+ Tooling::Danger::MergeRequestLinter.new(commit).lint
end
def count_non_fixup_commits(commit_linters)
diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile
new file mode 100644
index 00000000000..c90f60640f2
--- /dev/null
+++ b/danger/feature_flag/Dangerfile
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+# rubocop:disable Style/SignalException
+
+SEE_DOC = "See the [feature flag documentation](https://docs.gitlab.com/ee/development/feature_flags/development.html#feature-flag-definition-and-validation)."
+
+SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT
+```suggestion
+group: "%<group>s"
+```
+
+#{SEE_DOC}
+SUGGEST_COMMENT
+
+def check_feature_flag_yaml(feature_flag)
+ mr_group_label = helper.group_label(gitlab.mr_labels)
+
+ if feature_flag.group.nil?
+ message_for_feature_flag_missing_group!(feature_flag: feature_flag, mr_group_label: mr_group_label)
+ else
+ message_for_feature_flag_with_group!(feature_flag: feature_flag, mr_group_label: mr_group_label)
+ end
+rescue Psych::Exception
+ # YAML could not be parsed, fail the build.
+ fail "#{gitlab.html_link(feature_flag.path)} isn't valid YAML! #{SEE_DOC}"
+rescue StandardError => e
+ warn "There was a problem trying to check the Feature Flag file. Exception: #{e.class.name} - #{e.message}"
+end
+
+def message_for_feature_flag_missing_group!(feature_flag:, mr_group_label:)
+ if mr_group_label.nil?
+ warn "Consider setting `group` in #{gitlab.html_link(feature_flag.path)}. #{SEE_DOC}"
+ else
+ mr_line = feature_flag.raw.lines.find_index("group:\n")
+
+ if mr_line
+ markdown(format(SUGGEST_MR_COMMENT, group: mr_group_label), file: feature_flag.path, line: mr_line.succ)
+ else
+ warn %(Consider setting `group: "#{mr_group_label}"` in #{gitlab.html_link(feature_flag.path)}. #{SEE_DOC})
+ end
+ end
+end
+
+def message_for_feature_flag_with_group!(feature_flag:, mr_group_label:)
+ return if feature_flag.group_match_mr_label?(mr_group_label)
+
+ if mr_group_label.nil?
+ gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
+ gitlab.mr_json['iid'],
+ add_labels: feature_flag.group)
+ else
+ fail %(`group` is set to ~"#{feature_flag.group}" in #{gitlab.html_link(feature_flag.path)}, which does not match ~"#{mr_group_label}" set on the MR!)
+ end
+end
+
+def feature_flag_file_added_or_removed?
+ feature_flag.feature_flag_files(change_type: :added).any? || feature_flag.feature_flag_files(change_type: :deleted).any?
+end
+
+feature_flag.feature_flag_files(change_type: :added).each do |feature_flag|
+ check_feature_flag_yaml(feature_flag)
+end
+
+if feature_flag_file_added_or_removed?
+ new_mr_title = helper.mr_title.dup
+ new_mr_title << ' [RUN ALL RSPEC]' unless helper.run_all_rspec_mr?
+ new_mr_title << ' [RUN AS-IF-FOSS]' unless helper.run_as_if_foss_mr?
+
+ if new_mr_title != helper.mr_title
+ gitlab.api.update_merge_request(
+ gitlab.mr_json['project_id'],
+ gitlab.mr_json['iid'],
+ title: new_mr_title
+ )
+ gitlab.api.post("/projects/#{gitlab.mr_json['project_id']}/merge_requests/#{gitlab.mr_json['iid']}/pipelines")
+ else
+ message "You're adding or removing a feature flag, your MR title needs to include `[RUN ALL RSPEC] [RUN AS-IF-FOSS]` (we may have updated it automatically for you and started a new MR pipeline) to ensure everything is covered."
+ end
+end
diff --git a/danger/frozen_string/Dangerfile b/danger/frozen_string/Dangerfile
deleted file mode 100644
index bc598b16463..00000000000
--- a/danger/frozen_string/Dangerfile
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-FILE_EXTENSION = ".rb"
-FROZEN_STRING_MAGIC_COMMENT = "# frozen_string_literal: true"
-SHEBANG_COMMENT = "#!"
-
-def get_files_with_no_magic_comment(files)
- files.select do |path|
- path.end_with?(FILE_EXTENSION) &&
- !file_has_frozen_string_magic_comment?(path)
- end
-end
-
-def file_has_frozen_string_magic_comment?(path)
- File.open(path) do |file|
- first_line = file.gets
-
- line_has_frozen_string_magic_comment?(first_line) ||
- (line_has_shebang?(first_line) &&
- line_has_frozen_string_magic_comment?(file.gets))
- end
-end
-
-def line_has_frozen_string_magic_comment?(line)
- line&.start_with?(FROZEN_STRING_MAGIC_COMMENT)
-end
-
-def line_has_shebang?(line)
- line&.start_with?(SHEBANG_COMMENT)
-end
-
-files_to_fix = get_files_with_no_magic_comment(git.added_files)
-
-if files_to_fix.any?
- warn 'This merge request adds files that do not enforce frozen string literal. ' \
- 'See https://gitlab.com/gitlab-org/gitlab-foss/issues/47424 for more information.'
-
- if GitlabDanger.new(helper.gitlab_helper).ci?
- markdown(<<~MARKDOWN)
- ## Enable Frozen String Literal
-
- The following files should have `#{FROZEN_STRING_MAGIC_COMMENT}` on the first line:
-
- * #{files_to_fix.map { |path| "`#{path}`" }.join("\n* ")}
- MARKDOWN
- end
-end
diff --git a/danger/metadata/Dangerfile b/danger/metadata/Dangerfile
index b98d10d0654..d74c4f4a5af 100644
--- a/danger/metadata/Dangerfile
+++ b/danger/metadata/Dangerfile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Style/SignalException
THROUGHPUT_LABELS = [
@@ -17,10 +19,6 @@ if gitlab.mr_body.size < 5
fail "Please provide a proper merge request description."
end
-if gitlab.mr_labels.empty?
- fail "Please add labels to this merge request."
-end
-
if (THROUGHPUT_LABELS & gitlab.mr_labels).empty?
warn 'Please add a [throughput label](https://about.gitlab.com/handbook/engineering/management/throughput/#implementation) to this merge request.'
end
diff --git a/danger/pipeline/Dangerfile b/danger/pipeline/Dangerfile
index 0342a39554b..c71fb86325d 100644
--- a/danger/pipeline/Dangerfile
+++ b/danger/pipeline/Dangerfile
@@ -7,9 +7,12 @@ This Merge Request contains changes to the pipeline configuration for the GitLab
Please consider the effect of the changes in this Merge Request on the following:
- Effects on different [pipeline types](https://docs.gitlab.com/ee/development/pipelines.html#pipelines-for-merge-requests)
-- Effects on non-canonical projects (`gitlab-foss`, `security`, etc)
+- Effects on non-canonical projects:
+ - `gitlab-foss`
+ - `security`
+ - `dev`
+ - personal forks
- Effects on [pipeline performance](https://about.gitlab.com/handbook/engineering/quality/performance-indicators/#average-merge-request-pipeline-duration-for-gitlab)
-- Effects on fork pipelines
Please consider communicating these changes to the broader team following the [communication guideline for pipeline changes](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity-team/#pipeline-changes)
MESSAGE
diff --git a/danger/plugins/changelog.rb b/danger/plugins/changelog.rb
index 84f399e9e97..fd2dad5932a 100644
--- a/danger/plugins/changelog.rb
+++ b/danger/plugins/changelog.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require_relative '../../lib/gitlab/danger/changelog'
+require_relative '../../tooling/danger/changelog'
module Danger
class Changelog < Plugin
# Put the helper code somewhere it can be tested
- include Gitlab::Danger::Changelog
+ include Tooling::Danger::Changelog
end
end
diff --git a/danger/plugins/feature_flag.rb b/danger/plugins/feature_flag.rb
new file mode 100644
index 00000000000..8db8daba6d9
--- /dev/null
+++ b/danger/plugins/feature_flag.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require_relative '../../tooling/danger/feature_flag'
+
+module Danger
+ class FeatureFlag < Plugin
+ # Put the helper code somewhere it can be tested
+ include Tooling::Danger::FeatureFlag
+ end
+end
diff --git a/danger/plugins/helper.rb b/danger/plugins/helper.rb
index 2d7a933e801..8602868d817 100644
--- a/danger/plugins/helper.rb
+++ b/danger/plugins/helper.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
-require_relative '../../lib/gitlab/danger/helper'
+require_relative '../../tooling/danger/helper'
module Danger
- # Common helper functions for our danger scripts. See Gitlab::Danger::Helper
+ # Common helper functions for our danger scripts. See Tooling::Danger::Helper
# for more details
class Helper < Plugin
# Put the helper code somewhere it can be tested
- include Gitlab::Danger::Helper
+ include Tooling::Danger::Helper
end
end
diff --git a/danger/plugins/roulette.rb b/danger/plugins/roulette.rb
index 7c62cff0c92..2aa0132852e 100644
--- a/danger/plugins/roulette.rb
+++ b/danger/plugins/roulette.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require_relative '../../lib/gitlab/danger/roulette'
+require_relative '../../tooling/danger/roulette'
module Danger
class Roulette < Plugin
# Put the helper code somewhere it can be tested
- include Gitlab::Danger::Roulette
+ include Tooling::Danger::Roulette
end
end
diff --git a/danger/plugins/sidekiq_queues.rb b/danger/plugins/sidekiq_queues.rb
index 1edeb6da3d5..dd436e5cb2b 100644
--- a/danger/plugins/sidekiq_queues.rb
+++ b/danger/plugins/sidekiq_queues.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require_relative '../../lib/gitlab/danger/sidekiq_queues'
+require_relative '../../tooling/danger/sidekiq_queues'
module Danger
class SidekiqQueues < Plugin
# Put the helper code somewhere it can be tested
- include Gitlab::Danger::SidekiqQueues
+ include Tooling::Danger::SidekiqQueues
end
end
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
index ec432544977..5fd5b962993 100644
--- a/danger/product_intelligence/Dangerfile
+++ b/danger/product_intelligence/Dangerfile
@@ -1,8 +1,9 @@
# frozen_string_literal: true
+# rubocop:disable Style/SignalException
CHANGED_FILES_MESSAGE = <<~MSG
For the following files, a review from the [Data team and Product Intelligence team](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
-Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/product_analytics/usage_ping.html) and reach out to %<engineers_group>s group for a review.
+Please check the ~"product intelligence" [guide](https://docs.gitlab.com/ee/development/usage_ping.html) and reach out to %<engineers_group>s group for a review.
%<changed_files>s
@@ -16,21 +17,41 @@ MSG
ENGINEERS_GROUP = '@gitlab-org/growth/product-intelligence/engineers'
+UPDATE_DICTIONARY_MESSAGE = <<~MSG
+ When updating metrics definitions, please update [Metrics Dictionary](https://docs.gitlab.com/ee/development/usage_ping/dictionary.html)
+
+ ```shell
+ bundle exec rake gitlab:usage_data:generate_metrics_dictionary
+ ```
+MSG
+
+all_changed_files = helper.all_changed_files
+
tracking_files = [
'lib/gitlab/tracking.rb',
'spec/lib/gitlab/tracking_spec.rb',
'app/helpers/tracking_helper.rb',
'spec/helpers/tracking_helper_spec.rb',
'app/assets/javascripts/tracking.js',
- 'spec/frontend/tracking_spec.js'
+ 'spec/frontend/tracking_spec.js',
+ 'generator_templates/usage_metric_definition/metric_definition.yml',
+ 'lib/generators/rails/usage_metric_definition_generator.rb',
+ 'spec/lib/generators/usage_metric_definition_generator_spec.rb',
+ 'config/metrics/schema.json'
]
-usage_data_changed_files = helper.changed_files(/usage_data/)
-snowplow_events_changed_files = git.modified_files & tracking_files
+tracking_changed_files = all_changed_files & tracking_files
+usage_data_changed_files = all_changed_files.grep(%r{(usage_data)})
+metrics_changed_files = all_changed_files.grep(%r{((ee/)?config/metrics/.*\.yml)})
+dictionary_changed_file = all_changed_files.grep(%r{(doc/development/usage_ping/dictionary.md)})
-changed_files = (usage_data_changed_files + snowplow_events_changed_files)
+snowplow_changed_files = all_changed_files.select do |file|
+ helper.changed_lines(file).grep(%r{Gitlab::Tracking\.event}).any?
+end
+
+matching_changed_files = usage_data_changed_files + tracking_changed_files + metrics_changed_files + dictionary_changed_file + snowplow_changed_files
-if changed_files.any?
+if matching_changed_files.any?
mention = if helper.draft_mr?
"`#{ENGINEERS_GROUP}`"
@@ -38,8 +59,10 @@ if changed_files.any?
ENGINEERS_GROUP
end
- warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(changed_files), engineers_group: mention)
- warn format(UPDATE_METRICS_DEFINITIONS_MESSAGE) unless helper.changed_files(/usage_ping\.md/).any?
+ warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(matching_changed_files), engineers_group: mention)
+ warn format(UPDATE_METRICS_DEFINITIONS_MESSAGE) if usage_data_changed_files.any?
+
+ fail format(UPDATE_DICTIONARY_MESSAGE) if metrics_changed_files.any? && dictionary_changed_file.empty?
labels = ['product intelligence']
labels << 'product intelligence::review pending' unless helper.mr_has_labels?('product intelligence::approved')
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 424114a3d33..3096ef471dd 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -24,8 +24,8 @@ and [code review guidelines](https://docs.gitlab.com/ee/development/code_review.
Please consider assigning a reviewer or maintainer who is a
[domain expert](https://about.gitlab.com/handbook/engineering/projects/#gitlab) in the area of the merge request.
-Once you've decided who will review this merge request, mention them as you
-normally would! Danger does not automatically notify them for you.
+Once you've decided who will review this merge request, assign them as a reviewer!
+Danger does not automatically notify them for you.
| Category | Reviewer | Maintainer |
| -------- | -------- | ---------- |
@@ -35,7 +35,7 @@ UNKNOWN_FILES_MESSAGE = <<MARKDOWN
These files couldn't be categorised, so Danger was unable to suggest a reviewer.
Please consider creating a merge request to
-[add support](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/danger/helper.rb)
+[add support](https://gitlab.com/gitlab-org/gitlab/blob/master/tooling/danger/helper.rb)
for them.
MARKDOWN
diff --git a/data/whats_new/202008180001_12_10.yml b/data/whats_new/202008180001_12_10.yml
index f3a2467c91b..a21e9d795a1 100644
--- a/data/whats_new/202008180001_12_10.yml
+++ b/data/whats_new/202008180001_12_10.yml
@@ -20,7 +20,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/12_10/jwt-vault-1.png
published_at: 2020-04-22
@@ -48,7 +48,7 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/import/jira.html
image_url: https://about.gitlab.com/images/12_10/jira-importer.png
published_at: 2020-04-22
@@ -61,7 +61,7 @@
stage: Verify
self-managed: true
gitlab-com: false
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate/-/blob/master/docs/README.md
image_url: https://about.gitlab.com/images/12_9/autoscaling_ci_fargate.png
published_at: 2020-04-22
diff --git a/data/whats_new/202008180002_13_0.yml b/data/whats_new/202008180002_13_0.yml
index b8363adb8f4..e82fa82cae0 100644
--- a/data/whats_new/202008180002_13_0.yml
+++ b/data/whats_new/202008180002_13_0.yml
@@ -7,7 +7,7 @@
stage: Create
self-managed: true
gitlab-com: false
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/administration/gitaly/praefect.html
image_url: https://about.gitlab.com/images/13_0/praefect-architecture.png
published_at: 2020-05-22
@@ -20,7 +20,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/topics/autodevops/index.html#aws-ecs
image_url: https://docs.gitlab.com/ee/ci/img/ecs_dashboard_v12_9.png
published_at: 2020-05-22
@@ -46,7 +46,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/snippets.html#versioned-snippets
image_url: https://about.gitlab.com/images/13_0/phikai-versioned-snippets.png
published_at: 2020-05-22
@@ -59,7 +59,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/web_ide/#themes
image_url: https://about.gitlab.com/images/13_0/phikai-web-ide-dark-theme.png
published_at: 2020-05-22
diff --git a/data/whats_new/202008180003_13_01.yml b/data/whats_new/202008180003_13_01.yml
index ff2dc0322ba..9f8a87ebe27 100644
--- a/data/whats_new/202008180003_13_01.yml
+++ b/data/whats_new/202008180003_13_01.yml
@@ -7,8 +7,8 @@
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/operations/alert_management.html
+ packages: [Free, Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/operations/incident_management/index.html
image_url: https://about.gitlab.com/images/13_1/alert_management.png
published_at: 2020-06-22
release: 13.1
@@ -20,7 +20,7 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/merge_requests/accessibility_testing.html#accessibility-merge-request-widget
image_url: https://about.gitlab.com/images/13_1/a11y-merge-request-widget.png
published_at: 2020-06-22
@@ -31,18 +31,18 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads
image_url: https://about.gitlab.com/images/13_1/resolve-design-comment.gif
published_at: 2020-06-22
release: 13.1
-- title: Merge Request Reviews moved to Core
+- title: Merge Request Reviews moved to Free
body: |
Originally introduced in GitLab 11.4 as a GitLab Premium feature, Merge Request Reviews allow merge request reviewers to submit multiple comments at once, cutting down on notification noise for the merge request author, and allowing for a more cohesive and streamlined review process.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/discussions/index.html#merge-request-reviews
image_url: https://about.gitlab.com/images/13_1/batch_comments.png
published_at: 2020-06-22
diff --git a/data/whats_new/202008210001_13_02.yml b/data/whats_new/202008210001_13_02.yml
index 9048e15aa26..ce562abbf29 100644
--- a/data/whats_new/202008210001_13_02.yml
+++ b/data/whats_new/202008210001_13_02.yml
@@ -7,7 +7,7 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Starter, Premium, Ultimate]
+ packages: [Premium, Ultimate]
url: https://www.youtube.com/watch?v=31pNKjenlJY&feature=emb_title
image_url: https://img.youtube.com/vi/31pNKjenlJY/hqdefault.jpg
published_at: 2020-07-22
@@ -20,7 +20,7 @@
stage: Defend
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://www.youtube.com/watch?v=WxBzBz76FxU&feature=youtu.be
image_url: https://img.youtube.com/vi/WxBzBz76FxU/hqdefault.jpg
published_at: 2020-07-22
@@ -33,22 +33,22 @@
stage: Create
self-managed: false
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#gitlab-figma-plugin
image_url: https://about.gitlab.com/images/13_2/figma-plugin.png
published_at: 2020-07-22
release: 13.2
-- title: Cluster health monitoring now available in Core
+- title: Cluster health monitoring now available in Free
body: |
To understand system performance, your development team must monitor the health and performance of the underlying infrastructure.
- We want our metrics solution to be available to all GitLab users, so as part of our [2020 gift](https://about.gitlab.com/blog/2019/12/16/observability/), we’ve moved cluster health in the Monitor stage from GitLab Ultimate to GitLab Core.
+ We want our metrics solution to be available to all GitLab users, so as part of our [2020 gift](https://about.gitlab.com/blog/2019/12/16/observability/), we’ve moved cluster health in the Monitor stage from GitLab Ultimate to GitLab Free.
Beginning with GitLab 13.2, all users can connect a cluster and monitor its health in the GitLab user interface.
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/clusters/#visualizing-cluster-health
image_url: https://about.gitlab.com/images/13_2/k8s_cluster_monitoring.png
published_at: 2020-07-22
diff --git a/data/whats_new/202009150001_13_03.yml b/data/whats_new/202009150001_13_03.yml
index 92b4e144543..3f51112d531 100644
--- a/data/whats_new/202009150001_13_03.yml
+++ b/data/whats_new/202009150001_13_03.yml
@@ -18,7 +18,7 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/yaml/#parallel-matrix-jobs
image_url: https://about.gitlab.com/images/13_3/cartesian-matrix.png
published_at: 2020-08-22
@@ -46,7 +46,7 @@
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/application_security/sast/#making-sast-analyzers-available-to-all-gitlab-tiers
image_url: https://about.gitlab.com/images/13_3/sast-gitlab-languages.png
published_at: 2020-08-22
diff --git a/data/whats_new/202009300001_13_04.yml b/data/whats_new/202009300001_13_04.yml
index dc48b2fbf26..4ba278def0c 100644
--- a/data/whats_new/202009300001_13_04.yml
+++ b/data/whats_new/202009300001_13_04.yml
@@ -55,19 +55,6 @@
image_url: https://about.gitlab.com/images/13_4/instance_vulnerability_report.png
published_at: 2020-09-22
release: 13.4
-- title: Feature Flags made available in GitLab Starter
- body: |
- Earlier this year, GitLab committed to [moving 18 features](https://about.gitlab.com/blog/2020/03/30/new-features-to-core/) to our open source core product. With this release of GitLab we've finished moving Feature Flags to Starter, and we are continuing to migrate our Feature Flag service to Core in [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/212318).
-
- We're excited about bringing these features to more users and seeing what use cases and workflows you use them for.
- stage: Release
- self-managed: true
- gitlab-com: true
- packages: [Starter, Premium, Ultimate]
- url: https://www.youtube.com/embed/1FBRaBQTQZk
- image_url: https://img.youtube.com/vi/1FBRaBQTQZk/hqdefault.jpg
- published_at: 2020-09-22
- release: 13.4
- title: Quick navigation using the Search bar
body: |
When navigating through GitLab, sometimes you just want to go to a specific project and not a search result page. Using the Global search bar, you can now quickly jump to recent issues, groups, projects, settings, and help topics.
@@ -76,7 +63,7 @@
stage: Enablement
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/search/#autocomplete-suggestions
image_url: https://about.gitlab.com/images/13_4/enablement_global_search.gif
published_at: 2020-09-22
diff --git a/data/whats_new/202010230001_13_05.yml b/data/whats_new/202010230001_13_05.yml
index 6a36e27d2ee..84a286fb590 100644
--- a/data/whats_new/202010230001_13_05.yml
+++ b/data/whats_new/202010230001_13_05.yml
@@ -39,7 +39,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/snippets.html#multiple-files-by-snippet
image_url: https://about.gitlab.com/images/13_5/phikai-snippets-multiple-files.png
published_at: 2020-10-22
@@ -52,7 +52,7 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/runners/README.html#disable-shared-runners
image_url: https://about.gitlab.com/images/13_5/enable_shared_runners_v2.png
published_at: 2020-10-22
@@ -65,7 +65,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/operations/feature_flags.html#percent-rollout
image_url: https://about.gitlab.com/images/13_5/percent-rollout.png
published_at: 2020-10-22
@@ -78,7 +78,7 @@
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
image_url: https://about.gitlab.com/images/13_5/sast-gitlab-mobile.png
published_at: 2020-10-22
diff --git a/data/whats_new/202011230001_13_06.yml b/data/whats_new/202011230001_13_06.yml
index 94d26f5e217..47e8526408f 100644
--- a/data/whats_new/202011230001_13_06.yml
+++ b/data/whats_new/202011230001_13_06.yml
@@ -9,7 +9,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/cloud_deployment/#custom-build-job-for-auto-devops
image_url: https://img.youtube.com/vi/4B-qSwKnacA/hqdefault.jpg
published_at: 2020-11-22
@@ -22,7 +22,7 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-widget
image_url: https://about.gitlab.com/images/13_6/code_quality_severity.png
published_at: 2020-11-22
@@ -58,7 +58,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/admin_area/settings/project_integration_management.html
image_url: https://about.gitlab.com/images/13_6/project-integration-inheriting-settings.png
published_at: 2020-11-22
@@ -75,7 +75,7 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Starter, Premium, Ultimate]
+ packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html#burnup-charts
image_url: https://about.gitlab.com/images/13_6/burnup-chart.png
published_at: 2020-11-22
diff --git a/data/whats_new/202012160001_13_07.yml b/data/whats_new/202012160001_13_07.yml
index 14ed04aa0f7..702c757a280 100644
--- a/data/whats_new/202012160001_13_07.yml
+++ b/data/whats_new/202012160001_13_07.yml
@@ -20,7 +20,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/merge_requests/getting_started#reviewer
image_url: https://about.gitlab.com/images/13_7/reviewers_sidebar.png
published_at: 2020-12-22
@@ -33,13 +33,13 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/quick_actions.html
image_url: https://about.gitlab.com/images/13_7/clone_issue_with_quick_action.png
published_at: 2020-12-22
release: 13.7
- title: GitLab Runner for Red Hat OpenShift
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
self-managed: true
gitlab-com: true
url: 'https://docs.gitlab.com/runner/install/openshift.html'
diff --git a/data/whats_new/202101140001_13_08.yml b/data/whats_new/202101140001_13_08.yml
index 826259fe7be..3c1f33f1c9c 100644
--- a/data/whats_new/202101140001_13_08.yml
+++ b/data/whats_new/202101140001_13_08.yml
@@ -7,7 +7,7 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/pipeline_editor/index.html
image_url: https://img.youtube.com/vi/MQpSyvMpsHA/hqdefault.jpg
published_at: 2021-01-22
@@ -18,7 +18,7 @@
stage: verify
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/yaml/visualization.html
image_url: https://about.gitlab.com/images/13_8/pipeline_visual_builder.png
published_at: 2021-01-22
@@ -40,7 +40,7 @@
stage: plan
self-managed: true
gitlab-com: true
- packages: [Starter, Premium, Ultimate]
+ packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/issue_board.html#configurable-issue-boards
image_url: https://about.gitlab.com/images/13_8/scope_board_to_current_iteration.png
published_at: 2021-01-22
@@ -51,7 +51,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#downloading-artifacts
image_url: https://about.gitlab.com/images/13_8/artifact_mr.png
published_at: 2021-01-22
@@ -64,7 +64,7 @@
stage: create
self-managed: true
gitlab-com: true
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics
image_url: https://about.gitlab.com/images/13_8/rebase_comment.png
published_at: 2021-01-22
@@ -75,7 +75,7 @@
stage: enablement
self-managed: true
gitlab-com: false
- packages: [Core, Starter, Premium, Ultimate]
+ packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/charts/charts/gitlab/gitlab-pages/index.html
image_url: https://about.gitlab.com/images/home/kubernetes.png
published_at: 2021-01-22
diff --git a/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml b/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
new file mode 100644
index 00000000000..74915c19f95
--- /dev/null
+++ b/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
@@ -0,0 +1,32 @@
+# This is a template for a "Whats New" release.
+# A release typically contains multiple entries of features that we'd like to highlight.
+#
+# 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. All attributes are required.
+#
+# For more information please refer to the handbook documentation here:
+# https://about.gitlab.com/handbook/marketing/blog/release-posts/index.html#create-mr-for-whats-new-entries
+#
+# Please delete this line and above before submitting your Merge Request.
+
+- title: # Match the release post entry
+ body: | # Do not modify this line, instead modify the lines below.
+ <!-- START OF BODY COMMENT
+
+ This area supports markdown.
+
+ It is recommended to copy and paste the release post entry content here.
+
+ You can shorten it if needed, but remember that the entry itself has already been reviewed by Tech Writing so don't feel like you need to reword anything.
+
+ Delete this entire comment and replace it with your markdown content.
+
+ END OF BODY COMMENT -->
+ stage: # String value of the stage that the feature was created in. e.g., Growth
+ self-managed: # Boolean value (true or false)
+ gitlab-com: # Boolean value (true or false)
+ packages: # Array of strings. The Array brackets are required here. e.g., [Core, Starter, Premium, Ultimate]
+ url: # This is the documentation URL, but can be a URL to a video if there is one
+ image_url: # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ published_at: # YYYY-MM-DD
+ release: # XX.Y
diff --git a/db/fixtures/development/25_api_personal_access_token.rb b/db/fixtures/development/25_api_personal_access_token.rb
index 9b0427b3a88..1413f468be1 100644
--- a/db/fixtures/development/25_api_personal_access_token.rb
+++ b/db/fixtures/development/25_api_personal_access_token.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require './spec/support/sidekiq_middleware'
-
# Create an api access token for root user with the value:
token = 'ypCa3Dzb23o5nvsixwPA'
scopes = Gitlab::Auth.all_available_scopes
diff --git a/db/fixtures/development/30_composer_packages.rb b/db/fixtures/development/30_composer_packages.rb
new file mode 100644
index 00000000000..fa8c648de9e
--- /dev/null
+++ b/db/fixtures/development/30_composer_packages.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require './spec/support/sidekiq_middleware'
+
+class Gitlab::Seeder::ComposerPackages
+ def group
+ @group ||= Group.find_by(path: 'composer')
+
+ unless @group
+ @group = Group.create!(
+ name: 'Composer',
+ path: 'composer',
+ description: FFaker::Lorem.sentence
+ )
+
+ @group.add_owner(user)
+ @group.create_namespace_settings
+ end
+
+ @group
+ end
+
+ def user
+ @user ||= User.first
+ end
+
+ def create_real_project!(url)
+ project_path = url.split('/').last
+
+ project_path.gsub!(".git", "")
+
+ project = group.projects.find_by(name: project_path.titleize)
+
+ return project if project.present?
+
+ params = {
+ import_url: url,
+ namespace_id: group.id,
+ name: project_path.titleize,
+ description: FFaker::Lorem.sentence,
+ visibility_level: Gitlab::VisibilityLevel.values.sample,
+ skip_disk_validation: true
+ }
+
+ Sidekiq::Worker.skipping_transaction_check do
+ project = ::Projects::CreateService.new(user, params).execute
+
+ # Seed-Fu runs this entire fixture in a transaction, so the `after_commit`
+ # hook won't run until after the fixture is loaded. That is too late
+ # since the Sidekiq::Testing block has already exited. Force clearing
+ # the `after_commit` queue to ensure the job is run now.
+ project.send(:_run_after_commit_queue)
+ project.import_state.send(:_run_after_commit_queue)
+
+ # Expire repository cache after import to ensure
+ # valid_repo? call below returns a correct answer
+ project.repository.expire_all_method_caches
+ end
+
+ if project.valid? && project.valid_repo?
+ print '.'
+ return project
+ else
+ puts project.errors.full_messages
+ print 'F'
+ return nil
+ end
+ end
+end
+
+COMPOSER_PACKAGES = {
+ 'https://github.com/php-fig/log.git' => [
+ { branch: 'master' },
+ { tag: 'v1.5.2' }
+ ],
+ 'https://github.com/ryssbowh/craft-themes.git' => [
+ { tag: '1.0.2' }
+ ],
+ 'https://github.com/php-fig/http-message.git' => [
+ { tag: '1.0.1' }
+ ],
+ 'https://github.com/doctrine/instantiator.git' => [
+ { branch: '1.4.x' }
+ ]
+}.freeze
+
+Gitlab::Seeder.quiet do
+ flag = 'SEED_COMPOSER'
+
+ unless ENV[flag]
+ puts "Use the `#{flag}` environment variable to seed composer packages"
+ next
+ end
+
+ Sidekiq::Testing.inline! do
+ COMPOSER_PACKAGES.each do |path, versions|
+ project = Gitlab::Seeder::ComposerPackages.new.create_real_project!(path)
+
+ versions.each do |version|
+ params = {}
+
+ if version[:branch]
+ params[:branch] = project.repository.find_branch(version[:branch])
+ elsif version[:tag]
+ params[:tag] = project.repository.find_tag(version[:tag])
+ end
+
+ if params[:branch].nil? && params[:tag].nil?
+ puts "version #{version.inspect} not found"
+ next
+ end
+
+ ::Packages::Composer::CreatePackageService
+ .new(project, project.owner, params)
+ .execute
+
+ puts "version #{version.inspect} created!"
+ end
+ end
+ end
+end
diff --git a/db/migrate/20190225152525_add_auto_dev_ops_enabled_to_namespaces.rb b/db/migrate/20190225152525_add_auto_dev_ops_enabled_to_namespaces.rb
index 93e7a84fb02..e4757b6bada 100644
--- a/db/migrate/20190225152525_add_auto_dev_ops_enabled_to_namespaces.rb
+++ b/db/migrate/20190225152525_add_auto_dev_ops_enabled_to_namespaces.rb
@@ -4,6 +4,6 @@ class AddAutoDevOpsEnabledToNamespaces < ActiveRecord::Migration[5.0]
DOWNTIME = false
def change
- add_column :namespaces, :auto_devops_enabled, :boolean
+ add_column :namespaces, :auto_devops_enabled, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190325080727_truncate_user_fullname.rb b/db/migrate/20190325080727_truncate_user_fullname.rb
index e5f88671eef..29255d173d8 100644
--- a/db/migrate/20190325080727_truncate_user_fullname.rb
+++ b/db/migrate/20190325080727_truncate_user_fullname.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Migration/UpdateLargeTable
class TruncateUserFullname < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb b/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb
index c264a23cda0..53b2e9f01fe 100644
--- a/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb
+++ b/db/migrate/20190606014128_add_last_ci_minutes_notification_at_to_namespaces.rb
@@ -7,6 +7,6 @@ class AddLastCiMinutesNotificationAtToNamespaces < ActiveRecord::Migration[5.1]
DOWNTIME = false
def change
- add_column :namespaces, :last_ci_minutes_notification_at, :datetime_with_timezone
+ add_column :namespaces, :last_ci_minutes_notification_at, :datetime_with_timezone # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190621022810_add_last_ci_minutes_usage_notification_level_to_namespaces.rb b/db/migrate/20190621022810_add_last_ci_minutes_usage_notification_level_to_namespaces.rb
index 1611340284c..02e06703acc 100644
--- a/db/migrate/20190621022810_add_last_ci_minutes_usage_notification_level_to_namespaces.rb
+++ b/db/migrate/20190621022810_add_last_ci_minutes_usage_notification_level_to_namespaces.rb
@@ -4,6 +4,6 @@ class AddLastCiMinutesUsageNotificationLevelToNamespaces < ActiveRecord::Migrati
DOWNTIME = false
def change
- add_column :namespaces, :last_ci_minutes_usage_notification_level, :integer
+ add_column :namespaces, :last_ci_minutes_usage_notification_level, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190626175626_add_group_creation_level_to_namespaces.rb b/db/migrate/20190626175626_add_group_creation_level_to_namespaces.rb
index 3b75c92e518..6fcadc0c82c 100644
--- a/db/migrate/20190626175626_add_group_creation_level_to_namespaces.rb
+++ b/db/migrate/20190626175626_add_group_creation_level_to_namespaces.rb
@@ -6,7 +6,7 @@ class AddGroupCreationLevelToNamespaces < ActiveRecord::Migration[5.1]
DOWNTIME = false
def up
- add_column(:namespaces, :subgroup_creation_level, :integer)
+ add_column(:namespaces, :subgroup_creation_level, :integer) # rubocop:disable Migration/AddColumnsToWideTables
change_column_default(:namespaces,
:subgroup_creation_level,
::Gitlab::Access::MAINTAINER_SUBGROUP_ACCESS)
diff --git a/db/migrate/20190715215549_add_group_emails_disabled.rb b/db/migrate/20190715215549_add_group_emails_disabled.rb
index d3fd4d2d923..63a815cb880 100644
--- a/db/migrate/20190715215549_add_group_emails_disabled.rb
+++ b/db/migrate/20190715215549_add_group_emails_disabled.rb
@@ -4,6 +4,6 @@ class AddGroupEmailsDisabled < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :namespaces, :emails_disabled, :boolean
+ add_column :namespaces, :emails_disabled, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb b/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb
index 6f3650ca966..1b238907af6 100644
--- a/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb
+++ b/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AddNotNullConstraintsToPrometheusMetricsYLabelAndUnit < ActiveRecord::Migration[5.2]
DOWNTIME = false
diff --git a/db/migrate/20190828172831_create_package_tag.rb b/db/migrate/20190828172831_create_package_tag.rb
index 3d26b7ce602..a70b71db51d 100644
--- a/db/migrate/20190828172831_create_package_tag.rb
+++ b/db/migrate/20190828172831_create_package_tag.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# frozen_string_literal: true .
class CreatePackageTag < ActiveRecord::Migration[5.2]
diff --git a/db/migrate/20190911115109_add_namespaces_max_pages_size.rb b/db/migrate/20190911115109_add_namespaces_max_pages_size.rb
index c14dfa74a5a..d3054714188 100644
--- a/db/migrate/20190911115109_add_namespaces_max_pages_size.rb
+++ b/db/migrate/20190911115109_add_namespaces_max_pages_size.rb
@@ -4,6 +4,6 @@ class AddNamespacesMaxPagesSize < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :namespaces, :max_pages_size, :integer
+ add_column :namespaces, :max_pages_size, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20190911115222_add_namespaces_max_artifacts_size.rb b/db/migrate/20190911115222_add_namespaces_max_artifacts_size.rb
index 60c594c47a6..bec81d6c7e1 100644
--- a/db/migrate/20190911115222_add_namespaces_max_artifacts_size.rb
+++ b/db/migrate/20190911115222_add_namespaces_max_artifacts_size.rb
@@ -4,6 +4,6 @@ class AddNamespacesMaxArtifactsSize < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :namespaces, :max_artifacts_size, :integer
+ add_column :namespaces, :max_artifacts_size, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20191003195218_add_pendo_enabled_to_application_settings.rb b/db/migrate/20191003195218_add_pendo_enabled_to_application_settings.rb
index 29ae831d4f4..2d937327ca1 100644
--- a/db/migrate/20191003195218_add_pendo_enabled_to_application_settings.rb
+++ b/db/migrate/20191003195218_add_pendo_enabled_to_application_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AddPendoEnabledToApplicationSettings < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20191003195620_add_pendo_url_to_application_settings.rb b/db/migrate/20191003195620_add_pendo_url_to_application_settings.rb
index 6763cb5544c..cbeb1ef5186 100644
--- a/db/migrate/20191003195620_add_pendo_url_to_application_settings.rb
+++ b/db/migrate/20191003195620_add_pendo_url_to_application_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AddPendoUrlToApplicationSettings < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20191114132259_add_mentions_disabled_to_namespaces.rb b/db/migrate/20191114132259_add_mentions_disabled_to_namespaces.rb
index dbd69568ef2..a67d032795d 100644
--- a/db/migrate/20191114132259_add_mentions_disabled_to_namespaces.rb
+++ b/db/migrate/20191114132259_add_mentions_disabled_to_namespaces.rb
@@ -4,6 +4,6 @@ class AddMentionsDisabledToNamespaces < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
- add_column :namespaces, :mentions_disabled, :boolean
+ add_column :namespaces, :mentions_disabled, :boolean # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20191120200015_add_index_to_grafana_integrations.rb b/db/migrate/20191120200015_add_index_to_grafana_integrations.rb
index 87292c86e97..c67f6850baf 100644
--- a/db/migrate/20191120200015_add_index_to_grafana_integrations.rb
+++ b/db/migrate/20191120200015_add_index_to_grafana_integrations.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AddIndexToGrafanaIntegrations < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb b/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb
index 6eb650e6b6a..56a30b02290 100644
--- a/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb
+++ b/db/migrate/20200207062728_add_default_branch_protection_to_namespaces.rb
@@ -7,7 +7,7 @@ class AddDefaultBranchProtectionToNamespaces < ActiveRecord::Migration[6.0]
def up
with_lock_retries do
- add_column :namespaces, :default_branch_protection, :integer, limit: 2
+ add_column :namespaces, :default_branch_protection, :integer, limit: 2 # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200229171700_create_custom_emojis.rb b/db/migrate/20200229171700_create_custom_emojis.rb
index 1a60d7c8a63..f0574831f33 100644
--- a/db/migrate/20200229171700_create_custom_emojis.rb
+++ b/db/migrate/20200229171700_create_custom_emojis.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CreateCustomEmojis < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb b/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb
index 2aa58c92c3e..19e6573af9b 100644
--- a/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb
+++ b/db/migrate/20200304124406_add_unlock_membership_to_ldap_of_groups.rb
@@ -7,7 +7,7 @@ class AddUnlockMembershipToLdapOfGroups < ActiveRecord::Migration[5.2]
def up
with_lock_retries do
- add_column(:namespaces, :unlock_membership_to_ldap, :boolean)
+ add_column(:namespaces, :unlock_membership_to_ldap, :boolean) # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb b/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
index 907c832ce46..7388d6bbc13 100644
--- a/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
+++ b/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
@@ -7,7 +7,7 @@ class AddMaxPersonalAccessTokenLifetimeToNamespaces < ActiveRecord::Migration[6.
def up
with_lock_retries do
- add_column :namespaces, :max_personal_access_token_lifetime, :integer
+ add_column :namespaces, :max_personal_access_token_lifetime, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200407120000_add_push_rule_id_to_groups.rb b/db/migrate/20200407120000_add_push_rule_id_to_groups.rb
index 4b4e99052aa..738f0a4c605 100644
--- a/db/migrate/20200407120000_add_push_rule_id_to_groups.rb
+++ b/db/migrate/20200407120000_add_push_rule_id_to_groups.rb
@@ -7,7 +7,7 @@ class AddPushRuleIdToGroups < ActiveRecord::Migration[6.0]
def up
with_lock_retries do
- add_column :namespaces, :push_rule_id, :bigint
+ add_column :namespaces, :push_rule_id, :bigint # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb b/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb
index 2555a50be44..1adc421b9af 100644
--- a/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb
+++ b/db/migrate/20200424102023_add_shared_runners_enabled_and_override_to_namespaces.rb
@@ -7,8 +7,8 @@ class AddSharedRunnersEnabledAndOverrideToNamespaces < ActiveRecord::Migration[6
def up
with_lock_retries do
- add_column :namespaces, :shared_runners_enabled, :boolean, default: true, null: false
- add_column :namespaces, :allow_descendants_override_disabled_shared_runners, :boolean, default: false, null: false
+ add_column :namespaces, :shared_runners_enabled, :boolean, default: true, null: false # rubocop:disable Migration/AddColumnsToWideTables
+ add_column :namespaces, :allow_descendants_override_disabled_shared_runners, :boolean, default: false, null: false # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb b/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb
index d7f282b69f8..3041d7a8e58 100644
--- a/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb
+++ b/db/migrate/20200609012539_add_traversal_ids_to_namespaces.rb
@@ -7,7 +7,7 @@ class AddTraversalIdsToNamespaces < ActiveRecord::Migration[6.0]
def up
with_lock_retries do
- add_column :namespaces, :traversal_ids, :integer, array: true, default: [], null: false
+ add_column :namespaces, :traversal_ids, :integer, array: true, default: [], null: false # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb b/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb
index 2d5bbc1cba1..fcc08723520 100644
--- a/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb
+++ b/db/migrate/20200701190523_add_delayed_project_removal_to_namespaces.rb
@@ -7,7 +7,7 @@ class AddDelayedProjectRemovalToNamespaces < ActiveRecord::Migration[6.0]
def up
with_lock_retries do
- add_column :namespaces, :delayed_project_removal, :boolean, default: false, null: false
+ add_column :namespaces, :delayed_project_removal, :boolean, default: false, null: false # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb b/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb
index 7a59e706bf3..73028b6b795 100644
--- a/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb
+++ b/db/migrate/20201004163918_remove_project_id_and_id_index_from_vulnerabilities_table.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class RemoveProjectIdAndIdIndexFromVulnerabilitiesTable < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20201027101010_create_user_follow_users.rb b/db/migrate/20201027101010_create_user_follow_users.rb
new file mode 100644
index 00000000000..7c1f831f3b2
--- /dev/null
+++ b/db/migrate/20201027101010_create_user_follow_users.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CreateUserFollowUsers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ execute <<~SQL
+ CREATE TABLE user_follow_users (
+ follower_id integer not null references users (id) on delete cascade,
+ followee_id integer not null references users (id) on delete cascade,
+ PRIMARY KEY (follower_id, followee_id)
+ );
+ CREATE INDEX ON user_follow_users (followee_id);
+ SQL
+ end
+ end
+
+ def down
+ drop_table :user_follow_users
+ end
+end
diff --git a/db/migrate/20201108134919_add_finding_fingerprint_table.rb b/db/migrate/20201108134919_add_finding_fingerprint_table.rb
new file mode 100644
index 00000000000..dd8ffe8e8aa
--- /dev/null
+++ b/db/migrate/20201108134919_add_finding_fingerprint_table.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class AddFindingFingerprintTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ FINGERPRINT_IDX = :idx_vuln_fingerprints_on_occurrences_id_and_fingerprint
+ UNIQ_IDX = :idx_vuln_fingerprints_uniqueness
+
+ def up
+ with_lock_retries do
+ create_table :vulnerability_finding_fingerprints do |t|
+ t.references :finding,
+ index: true,
+ null: false,
+ foreign_key: { to_table: :vulnerability_occurrences, column: :finding_id, on_delete: :cascade }
+
+ t.timestamps_with_timezone null: false
+
+ t.integer :algorithm_type, null: false
+ t.binary :fingerprint_sha256, null: false
+
+ t.index %i[finding_id fingerprint_sha256],
+ name: FINGERPRINT_IDX,
+ unique: true # only one link should exist between occurrence and the fingerprint
+
+ t.index %i[finding_id algorithm_type fingerprint_sha256],
+ name: UNIQ_IDX,
+ unique: true # these should be unique
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :vulnerability_finding_fingerprints
+ end
+ end
+end
diff --git a/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb b/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
index 157f0de0821..e944cee24e4 100644
--- a/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
+++ b/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
@@ -3,6 +3,7 @@
class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration[6.0]
DOWNTIME = false
+ # rubocop:disable Migration/CreateTableWithForeignKeys
def change
create_table :vulnerability_findings_remediations do |t|
t.references :vulnerability_occurrence, index: false, foreign_key: { on_delete: :cascade }
@@ -13,4 +14,5 @@ class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration
t.index [:vulnerability_occurrence_id, :vulnerability_remediation_id], unique: true, name: 'index_vulnerability_findings_remediations_on_unique_keys'
end
end
+ # rubocop:enable Migration/CreateTableWithForeignKeys
end
diff --git a/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb b/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb
new file mode 100644
index 00000000000..a059099dbc4
--- /dev/null
+++ b/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddKrokiFormatsToApplicationSettingsTable < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_table :application_settings do |t|
+ t.jsonb :kroki_formats, null: false, default: {}
+ end
+ end
+end
diff --git a/db/migrate/20201120144823_create_tokens_with_iv.rb b/db/migrate/20201120144823_create_tokens_with_iv.rb
new file mode 100644
index 00000000000..f8dc75513fb
--- /dev/null
+++ b/db/migrate/20201120144823_create_tokens_with_iv.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateTokensWithIv < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :token_with_ivs do |t|
+ t.binary :hashed_token, null: false
+ t.binary :hashed_plaintext_token, null: false
+ t.binary :iv, null: false
+
+ t.index :hashed_token, name: 'index_token_with_ivs_on_hashed_token', unique: true, using: :btree
+ t.index :hashed_plaintext_token, name: 'index_token_with_ivs_on_hashed_plaintext_token', unique: true, using: :btree
+ end
+ end
+end
diff --git a/db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb b/db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb
new file mode 100644
index 00000000000..c9bbe8ab77d
--- /dev/null
+++ b/db/migrate/20201127104228_add_index_to_security_scans_on_created_at_and_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexToSecurityScansOnCreatedAtAndId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_security_scans_on_date_created_at_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :security_scans, "date(timezone('UTC', created_at)), id", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:security_scans, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20201204111200_create_packages_debian_project_components.rb b/db/migrate/20201204111200_create_packages_debian_project_components.rb
new file mode 100644
index 00000000000..76946967357
--- /dev/null
+++ b/db/migrate/20201204111200_create_packages_debian_project_components.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianProjectComponents < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ UNIQUE_NAME = 'uniq_pkgs_deb_proj_components_on_distribution_id_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:packages_debian_project_components)
+ create_table :packages_debian_project_components do |t|
+ t.timestamps_with_timezone
+ t.references :distribution,
+ foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade },
+ null: false,
+ index: false
+ t.text :name, null: false
+
+ t.index %w(distribution_id name),
+ name: UNIQUE_NAME,
+ unique: true,
+ using: :btree
+ end
+ end
+
+ add_text_limit :packages_debian_project_components, :name, 255
+ end
+
+ def down
+ drop_table :packages_debian_project_components
+ end
+end
diff --git a/db/migrate/20201204111300_create_packages_debian_group_components.rb b/db/migrate/20201204111300_create_packages_debian_group_components.rb
new file mode 100644
index 00000000000..c69f8d10c2b
--- /dev/null
+++ b/db/migrate/20201204111300_create_packages_debian_group_components.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianGroupComponents < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ UNIQUE_NAME = 'uniq_pkgs_deb_grp_components_on_distribution_id_and_name'
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:packages_debian_group_components)
+ create_table :packages_debian_group_components do |t|
+ t.timestamps_with_timezone
+ t.references :distribution,
+ foreign_key: { to_table: :packages_debian_group_distributions, on_delete: :cascade },
+ null: false,
+ index: false
+ t.text :name, null: false
+
+ t.index %w(distribution_id name),
+ name: UNIQUE_NAME,
+ unique: true,
+ using: :btree
+ end
+ end
+
+ add_text_limit :packages_debian_group_components, :name, 255
+ end
+
+ def down
+ drop_table :packages_debian_group_components
+ end
+end
diff --git a/db/migrate/20201204111400_create_packages_debian_project_component_files.rb b/db/migrate/20201204111400_create_packages_debian_project_component_files.rb
new file mode 100644
index 00000000000..74ee1e9c4cf
--- /dev/null
+++ b/db/migrate/20201204111400_create_packages_debian_project_component_files.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianProjectComponentFiles < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_ARCHITECTURE = 'idx_packages_debian_project_component_files_on_architecture_id'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:packages_debian_project_component_files)
+ create_table :packages_debian_project_component_files do |t|
+ t.timestamps_with_timezone
+ t.references :component,
+ foreign_key: { to_table: :packages_debian_project_components, on_delete: :restrict },
+ null: false,
+ index: true
+ t.references :architecture,
+ foreign_key: { to_table: :packages_debian_project_architectures, on_delete: :restrict },
+ index: { name: INDEX_ARCHITECTURE }
+ t.integer :size, null: false
+ t.integer :file_type, limit: 2, null: false
+ t.integer :compression_type, limit: 2
+ t.integer :file_store, limit: 2, default: 1, null: false
+ t.text :file, null: false
+ t.binary :file_md5, null: false
+ t.binary :file_sha256, null: false
+ end
+ end
+ end
+
+ add_text_limit :packages_debian_project_component_files, :file, 255
+ end
+
+ def down
+ drop_table :packages_debian_project_component_files
+ end
+end
diff --git a/db/migrate/20201204111500_create_packages_debian_group_component_files.rb b/db/migrate/20201204111500_create_packages_debian_group_component_files.rb
new file mode 100644
index 00000000000..2592d5b108a
--- /dev/null
+++ b/db/migrate/20201204111500_create_packages_debian_group_component_files.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianGroupComponentFiles < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_ARCHITECTURE = 'idx_packages_debian_group_component_files_on_architecture_id'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ unless table_exists?(:packages_debian_group_component_files)
+ create_table :packages_debian_group_component_files do |t|
+ t.timestamps_with_timezone
+ t.references :component,
+ foreign_key: { to_table: :packages_debian_group_components, on_delete: :restrict },
+ null: false,
+ index: true
+ t.references :architecture,
+ foreign_key: { to_table: :packages_debian_group_architectures, on_delete: :restrict },
+ index: { name: INDEX_ARCHITECTURE }
+ t.integer :size, null: false
+ t.integer :file_type, limit: 2, null: false
+ t.integer :compression_type, limit: 2
+ t.integer :file_store, limit: 2, default: 1, null: false
+ t.text :file, null: false
+ t.binary :file_md5, null: false
+ t.binary :file_sha256, null: false
+ end
+ end
+ end
+
+ add_text_limit :packages_debian_group_component_files, :file, 255
+ end
+
+ def down
+ drop_table :packages_debian_group_component_files
+ end
+end
diff --git a/db/migrate/20201204111600_create_packages_debian_publications.rb b/db/migrate/20201204111600_create_packages_debian_publications.rb
new file mode 100644
index 00000000000..2fd26c2c367
--- /dev/null
+++ b/db/migrate/20201204111600_create_packages_debian_publications.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreatePackagesDebianPublications < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :packages_debian_publications do |t|
+ t.references :package,
+ index: { unique: true },
+ null: false,
+ foreign_key: { to_table: :packages_packages, on_delete: :cascade }
+ t.references :distribution,
+ null: false,
+ foreign_key: { to_table: :packages_debian_project_distributions, on_delete: :cascade }
+ end
+ end
+end
diff --git a/db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb b/db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb
index 0d97d54f3e4..47eec16807b 100644
--- a/db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb
+++ b/db/migrate/20201214000000_change_mr_allow_maintainer_to_push_default.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ChangeMrAllowMaintainerToPushDefault < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20201221225303_add_service_desk_reply_to_is_not_null_index_on_issues.rb b/db/migrate/20201221225303_add_service_desk_reply_to_is_not_null_index_on_issues.rb
new file mode 100644
index 00000000000..fb5429af458
--- /dev/null
+++ b/db/migrate/20201221225303_add_service_desk_reply_to_is_not_null_index_on_issues.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddServiceDeskReplyToIsNotNullIndexOnIssues < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'idx_on_issues_where_service_desk_reply_to_is_not_null'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:issues, [:id], name: INDEX_NAME, where: 'service_desk_reply_to IS NOT NULL')
+ end
+
+ def down
+ remove_concurrent_index_by_name(:issues, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210105052034_rename_asset_proxy_whitelist_on_application_settings.rb b/db/migrate/20210105052034_rename_asset_proxy_whitelist_on_application_settings.rb
new file mode 100644
index 00000000000..cdfbd368070
--- /dev/null
+++ b/db/migrate/20210105052034_rename_asset_proxy_whitelist_on_application_settings.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RenameAssetProxyWhitelistOnApplicationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers::V2
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :application_settings,
+ :asset_proxy_whitelist,
+ :asset_proxy_allowlist
+ end
+
+ def down
+ undo_rename_column_concurrently :application_settings,
+ :asset_proxy_whitelist,
+ :asset_proxy_allowlist
+ end
+end
diff --git a/db/migrate/20210105153342_add_entity_columns_to_vulnerability_occurrences.rb b/db/migrate/20210105153342_add_entity_columns_to_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..3b5ffff7645
--- /dev/null
+++ b/db/migrate/20210105153342_add_entity_columns_to_vulnerability_occurrences.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddEntityColumnsToVulnerabilityOccurrences < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20200501000002_add_text_limit_to_sprints_extended_title
+ def change
+ add_column :vulnerability_occurrences, :description, :text
+ add_column :vulnerability_occurrences, :message, :text
+ add_column :vulnerability_occurrences, :solution, :text
+ add_column :vulnerability_occurrences, :cve, :text
+ add_column :vulnerability_occurrences, :location, :jsonb
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20210105154321_add_text_limit_to_vulnerability_occurrences_entity_columns.rb b/db/migrate/20210105154321_add_text_limit_to_vulnerability_occurrences_entity_columns.rb
new file mode 100644
index 00000000000..c2e138303d8
--- /dev/null
+++ b/db/migrate/20210105154321_add_text_limit_to_vulnerability_occurrences_entity_columns.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddTextLimitToVulnerabilityOccurrencesEntityColumns < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :vulnerability_occurrences, :description, 15000
+ add_text_limit :vulnerability_occurrences, :message, 3000
+ add_text_limit :vulnerability_occurrences, :solution, 7000
+ add_text_limit :vulnerability_occurrences, :cve, 48400
+ end
+
+ def down
+ remove_text_limit :vulnerability_occurrences, :description
+ remove_text_limit :vulnerability_occurrences, :message
+ remove_text_limit :vulnerability_occurrences, :solution
+ remove_text_limit :vulnerability_occurrences, :cve
+ end
+end
diff --git a/db/migrate/20210106155209_add_merge_request_diff_commit_trailers.rb b/db/migrate/20210106155209_add_merge_request_diff_commit_trailers.rb
new file mode 100644
index 00000000000..906efa58bcd
--- /dev/null
+++ b/db/migrate/20210106155209_add_merge_request_diff_commit_trailers.rb
@@ -0,0 +1,22 @@
+# 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 AddMergeRequestDiffCommitTrailers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :merge_request_diff_commits, :trailers, :jsonb, default: {}, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :merge_request_diff_commits, :trailers
+ end
+ end
+end
diff --git a/db/migrate/20210106225424_add_keep_latest_artifacts_to_application_settings.rb b/db/migrate/20210106225424_add_keep_latest_artifacts_to_application_settings.rb
new file mode 100644
index 00000000000..884159ddedb
--- /dev/null
+++ b/db/migrate/20210106225424_add_keep_latest_artifacts_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddKeepLatestArtifactsToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ # This is named keep_latest_artifact for consistency with the project level setting but
+ # turning it on keeps all (multiple) artifacts on the latest pipeline per ref
+ add_column :application_settings, :keep_latest_artifact, :boolean, default: true, null: false
+ end
+end
diff --git a/db/migrate/20210107105306_add_diff_type_to_merge_request_diffs.rb b/db/migrate/20210107105306_add_diff_type_to_merge_request_diffs.rb
new file mode 100644
index 00000000000..0b9b5e93054
--- /dev/null
+++ b/db/migrate/20210107105306_add_diff_type_to_merge_request_diffs.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class AddDiffTypeToMergeRequestDiffs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ UNIQUE_INDEX_NAME = 'index_merge_request_diffs_on_unique_merge_request_id'
+
+ def up
+ unless column_exists?(:merge_request_diffs, :diff_type)
+ with_lock_retries do
+ add_column :merge_request_diffs, :diff_type, :integer, null: false, limit: 2, default: 1
+ end
+ end
+
+ add_concurrent_index :merge_request_diffs, :merge_request_id, unique: true, where: 'diff_type = 2', name: UNIQUE_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:merge_request_diffs, UNIQUE_INDEX_NAME)
+
+ if column_exists?(:merge_request_diffs, :diff_type)
+ with_lock_retries do
+ remove_column :merge_request_diffs, :diff_type
+ end
+ end
+ end
+end
diff --git a/db/migrate/20210107154615_add_merge_request_context_commit_trailers.rb b/db/migrate/20210107154615_add_merge_request_context_commit_trailers.rb
new file mode 100644
index 00000000000..e7bd7c2ea56
--- /dev/null
+++ b/db/migrate/20210107154615_add_merge_request_context_commit_trailers.rb
@@ -0,0 +1,12 @@
+# 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 AddMergeRequestContextCommitTrailers < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :merge_request_context_commits, :trailers, :jsonb, default: {}, null: false
+ end
+end
diff --git a/db/migrate/20210111051045_create_dast_profiles.rb b/db/migrate/20210111051045_create_dast_profiles.rb
new file mode 100644
index 00000000000..f2667e1222e
--- /dev/null
+++ b/db/migrate/20210111051045_create_dast_profiles.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class CreateDastProfiles < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ table_comment = { owner: 'group::dynamic analysis', description: 'Profile used to run a DAST on-demand scan' }
+
+ create_table_with_constraints :dast_profiles, comment: table_comment.to_json do |t| # rubocop:disable Migration/AddLimitToTextColumns
+ t.references :project, null: false, foreign_key: false, index: false
+ t.references :dast_site_profile, null: false, foreign_key: { on_delete: :cascade }
+ t.references :dast_scanner_profile, null: false, foreign_key: { on_delete: :cascade }
+
+ t.timestamps_with_timezone
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ t.text :name, null: false
+ t.text :description, null: false
+ # rubocop:enable Migration/AddLimitToTextColumns
+
+ t.index [:project_id, :name], unique: true
+
+ t.text_limit :name, 255
+ t.text_limit :description, 255
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :dast_profiles
+ end
+ end
+end
diff --git a/db/migrate/20210111053308_add_project_fk_for_dast_profile.rb b/db/migrate/20210111053308_add_project_fk_for_dast_profile.rb
new file mode 100644
index 00000000000..5dc057b5f70
--- /dev/null
+++ b/db/migrate/20210111053308_add_project_fk_for_dast_profile.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddProjectFkForDastProfile < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :dast_profiles, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :dast_profiles, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20210111075104_add_temporary_index_on_security_findings_scan_id.rb b/db/migrate/20210111075104_add_temporary_index_on_security_findings_scan_id.rb
new file mode 100644
index 00000000000..a8f4e130f07
--- /dev/null
+++ b/db/migrate/20210111075104_add_temporary_index_on_security_findings_scan_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddTemporaryIndexOnSecurityFindingsScanId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'tmp_index_on_security_findings_scan_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :security_findings, :scan_id, where: 'uuid is null', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210112202949_create_composer_cache_file.rb b/db/migrate/20210112202949_create_composer_cache_file.rb
new file mode 100644
index 00000000000..b1c2a1608dd
--- /dev/null
+++ b/db/migrate/20210112202949_create_composer_cache_file.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class CreateComposerCacheFile < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ # rubocop:disable Migration/AddLimitToTextColumns
+ create_table_with_constraints :packages_composer_cache_files do |t|
+ t.timestamps_with_timezone
+
+ # record can be deleted after `delete_at`
+ t.datetime_with_timezone :delete_at
+
+ # which namespace it belongs to
+ t.integer :namespace_id, null: true
+
+ # file storage related fields
+ t.integer :file_store, limit: 2, null: false, default: 1
+ t.text :file, null: false
+ t.binary :file_sha256, null: false
+
+ t.index [:namespace_id, :file_sha256], name: "index_packages_composer_cache_namespace_and_sha", using: :btree, unique: true
+ t.foreign_key :namespaces, column: :namespace_id, on_delete: :nullify
+
+ t.text_limit :file, 255
+ end
+ end
+
+ def down
+ drop_table :packages_composer_cache_files
+ end
+end
diff --git a/db/migrate/20210113224909_add_pipeline_configuration_full_path_to_compliance_pipeline.rb b/db/migrate/20210113224909_add_pipeline_configuration_full_path_to_compliance_pipeline.rb
new file mode 100644
index 00000000000..408d0579031
--- /dev/null
+++ b/db/migrate/20210113224909_add_pipeline_configuration_full_path_to_compliance_pipeline.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddPipelineConfigurationFullPathToCompliancePipeline < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20210119162812_add_text_limit_to_compliance_pipeline_configuration_full_path.rb
+ def up
+ add_column :compliance_management_frameworks, :pipeline_configuration_full_path, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+
+ def down
+ remove_column :compliance_management_frameworks, :pipeline_configuration_full_path
+ end
+end
diff --git a/db/migrate/20210113231532_add_converted_at_to_experiment_subjects.rb b/db/migrate/20210113231532_add_converted_at_to_experiment_subjects.rb
new file mode 100644
index 00000000000..25571b25af9
--- /dev/null
+++ b/db/migrate/20210113231532_add_converted_at_to_experiment_subjects.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddConvertedAtToExperimentSubjects < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :experiment_subjects, :converted_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20210113231546_add_context_to_experiment_subjects.rb b/db/migrate/20210113231546_add_context_to_experiment_subjects.rb
new file mode 100644
index 00000000000..7fac45e9952
--- /dev/null
+++ b/db/migrate/20210113231546_add_context_to_experiment_subjects.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddContextToExperimentSubjects < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :experiment_subjects, :context, :jsonb, default: {}, null: false
+ end
+end
diff --git a/db/migrate/20210114142443_add_indexes_to_onboarding_progresses.rb b/db/migrate/20210114142443_add_indexes_to_onboarding_progresses.rb
new file mode 100644
index 00000000000..39964047e7f
--- /dev/null
+++ b/db/migrate/20210114142443_add_indexes_to_onboarding_progresses.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddIndexesToOnboardingProgresses < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ CREATE_TRACK_INDEX_NAME = 'index_onboarding_progresses_for_create_track'
+ VERIFY_TRACK_INDEX_NAME = 'index_onboarding_progresses_for_verify_track'
+ TRIAL_TRACK_INDEX_NAME = 'index_onboarding_progresses_for_trial_track'
+ TEAM_TRACK_INDEX_NAME = 'index_onboarding_progresses_for_team_track'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :onboarding_progresses, :created_at, where: 'git_write_at IS NULL', name: CREATE_TRACK_INDEX_NAME
+ add_concurrent_index :onboarding_progresses, :git_write_at, where: 'git_write_at IS NOT NULL AND pipeline_created_at IS NULL', name: VERIFY_TRACK_INDEX_NAME
+ add_concurrent_index :onboarding_progresses, 'GREATEST(git_write_at, pipeline_created_at)', where: 'git_write_at IS NOT NULL AND pipeline_created_at IS NOT NULL AND trial_started_at IS NULL', name: TRIAL_TRACK_INDEX_NAME
+ add_concurrent_index :onboarding_progresses, 'GREATEST(git_write_at, pipeline_created_at, trial_started_at)', where: 'git_write_at IS NOT NULL AND pipeline_created_at IS NOT NULL AND trial_started_at IS NOT NULL AND user_added_at IS NULL', name: TEAM_TRACK_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :onboarding_progresses, CREATE_TRACK_INDEX_NAME
+ remove_concurrent_index_by_name :onboarding_progresses, VERIFY_TRACK_INDEX_NAME
+ remove_concurrent_index_by_name :onboarding_progresses, TRIAL_TRACK_INDEX_NAME
+ remove_concurrent_index_by_name :onboarding_progresses, TEAM_TRACK_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210115090452_create_group_repository_storage_move.rb b/db/migrate/20210115090452_create_group_repository_storage_move.rb
new file mode 100644
index 00000000000..bd168dce5ac
--- /dev/null
+++ b/db/migrate/20210115090452_create_group_repository_storage_move.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class CreateGroupRepositoryStorageMove < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:group_repository_storage_moves)
+ with_lock_retries do
+ create_table :group_repository_storage_moves do |t|
+ t.timestamps_with_timezone
+ t.references :group, references: :namespace, column: :group_id, index: true, null: false
+ t.integer :state, limit: 2, default: 1, null: false
+ t.text :source_storage_name, null: false
+ t.text :destination_storage_name, null: false
+
+ t.foreign_key :namespaces, column: :group_id, on_delete: :cascade
+ end
+ end
+ end
+
+ add_text_limit(:group_repository_storage_moves, :source_storage_name, 255, constraint_name: 'group_repository_storage_moves_source_storage_name')
+ add_text_limit(:group_repository_storage_moves, :destination_storage_name, 255, constraint_name: 'group_repository_storage_moves_destination_storage_name')
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :group_repository_storage_moves
+ end
+ end
+end
diff --git a/db/migrate/20210117210226_add_has_external_issue_tracker_trigger.rb b/db/migrate/20210117210226_add_has_external_issue_tracker_trigger.rb
new file mode 100644
index 00000000000..20fe0ee0fd1
--- /dev/null
+++ b/db/migrate/20210117210226_add_has_external_issue_tracker_trigger.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+class AddHasExternalIssueTrackerTrigger < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::SchemaHelpers
+
+ DOWNTIME = false
+ FUNCTION_NAME = 'set_has_external_issue_tracker'
+ TRIGGER_ON_INSERT_NAME = 'trigger_has_external_issue_tracker_on_insert'
+ TRIGGER_ON_UPDATE_NAME = 'trigger_has_external_issue_tracker_on_update'
+ TRIGGER_ON_DELETE_NAME = 'trigger_has_external_issue_tracker_on_delete'
+
+ def up
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ UPDATE projects SET has_external_issue_tracker = (
+ EXISTS
+ (
+ SELECT 1
+ FROM services
+ WHERE project_id = COALESCE(NEW.project_id, OLD.project_id)
+ AND active = TRUE
+ AND category = 'issue_tracker'
+ )
+ )
+ WHERE projects.id = COALESCE(NEW.project_id, OLD.project_id);
+ RETURN NULL;
+ SQL
+ end
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_ON_INSERT_NAME}
+ AFTER INSERT ON services
+ FOR EACH ROW
+ WHEN (NEW.category = 'issue_tracker' AND NEW.active = TRUE AND NEW.project_id IS NOT NULL)
+ EXECUTE FUNCTION #{FUNCTION_NAME}();
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_ON_UPDATE_NAME}
+ AFTER UPDATE ON services
+ FOR EACH ROW
+ WHEN (NEW.category = 'issue_tracker' AND OLD.active != NEW.active AND NEW.project_id IS NOT NULL)
+ EXECUTE FUNCTION #{FUNCTION_NAME}();
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{TRIGGER_ON_DELETE_NAME}
+ AFTER DELETE ON services
+ FOR EACH ROW
+ WHEN (OLD.category = 'issue_tracker' AND OLD.active = TRUE AND OLD.project_id IS NOT NULL)
+ EXECUTE FUNCTION #{FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:services, TRIGGER_ON_INSERT_NAME)
+ drop_trigger(:services, TRIGGER_ON_UPDATE_NAME)
+ drop_trigger(:services, TRIGGER_ON_DELETE_NAME)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20210118111307_add_enforce_ssh_key_expiration_to_application_settings.rb b/db/migrate/20210118111307_add_enforce_ssh_key_expiration_to_application_settings.rb
new file mode 100644
index 00000000000..fd1ed4f207b
--- /dev/null
+++ b/db/migrate/20210118111307_add_enforce_ssh_key_expiration_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddEnforceSshKeyExpirationToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :enforce_ssh_key_expiration, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20210119153801_add_proxy_settings_to_jira_tracker_data.rb b/db/migrate/20210119153801_add_proxy_settings_to_jira_tracker_data.rb
new file mode 100644
index 00000000000..237ea25554d
--- /dev/null
+++ b/db/migrate/20210119153801_add_proxy_settings_to_jira_tracker_data.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddProxySettingsToJiraTrackerData < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :jira_tracker_data, :encrypted_proxy_address, :text
+ add_column :jira_tracker_data, :encrypted_proxy_address_iv, :text
+ add_column :jira_tracker_data, :encrypted_proxy_port, :text
+ add_column :jira_tracker_data, :encrypted_proxy_port_iv, :text
+ add_column :jira_tracker_data, :encrypted_proxy_username, :text
+ add_column :jira_tracker_data, :encrypted_proxy_username_iv, :text
+ add_column :jira_tracker_data, :encrypted_proxy_password, :text
+ add_column :jira_tracker_data, :encrypted_proxy_password_iv, :text
+ end
+end
diff --git a/db/migrate/20210119162812_add_text_limit_to_compliance_pipeline_configuration_full_path.rb b/db/migrate/20210119162812_add_text_limit_to_compliance_pipeline_configuration_full_path.rb
new file mode 100644
index 00000000000..2958dc8d0ec
--- /dev/null
+++ b/db/migrate/20210119162812_add_text_limit_to_compliance_pipeline_configuration_full_path.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddTextLimitToCompliancePipelineConfigurationFullPath < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :compliance_management_frameworks, :pipeline_configuration_full_path, 255
+ end
+
+ def down
+ remove_text_limit :compliance_management_frameworks, :pipeline_configuration_full_path
+ end
+end
diff --git a/db/migrate/20210120180956_extend_index_on_ci_builds_metadata.rb b/db/migrate/20210120180956_extend_index_on_ci_builds_metadata.rb
new file mode 100644
index 00000000000..421a2fac1ae
--- /dev/null
+++ b/db/migrate/20210120180956_extend_index_on_ci_builds_metadata.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class ExtendIndexOnCiBuildsMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ OLD_INDEX = :index_ci_builds_metadata_on_build_id_and_interruptible
+ NEW_INDEX = :index_ci_builds_metadata_on_build_id_and_id_and_interruptible
+
+ TABLE = :ci_builds_metadata
+
+ def up
+ create_covering_index(TABLE, NEW_INDEX)
+
+ remove_concurrent_index_by_name TABLE, OLD_INDEX
+ end
+
+ def down
+ add_concurrent_index TABLE, :build_id, where: 'interruptible = true', name: OLD_INDEX
+
+ remove_concurrent_index_by_name TABLE, NEW_INDEX
+ end
+
+ private
+
+ def create_covering_index(table, name)
+ return if index_exists_by_name?(table, name)
+
+ disable_statement_timeout do
+ execute <<~SQL
+ CREATE INDEX CONCURRENTLY #{name}
+ ON #{table} (build_id) INCLUDE (id)
+ WHERE interruptible = true
+ SQL
+ end
+ end
+end
diff --git a/db/migrate/20210120221743_delete_oauth_applications_tmp_index.rb b/db/migrate/20210120221743_delete_oauth_applications_tmp_index.rb
new file mode 100644
index 00000000000..d29e63ba5da
--- /dev/null
+++ b/db/migrate/20210120221743_delete_oauth_applications_tmp_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class DeleteOauthApplicationsTmpIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'tmp_index_oauth_applications_on_id_where_trusted'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :oauth_applications, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :oauth_applications, :id, where: 'trusted = true', name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210121093618_remove_repository_read_only_to_groups.rb b/db/migrate/20210121093618_remove_repository_read_only_to_groups.rb
new file mode 100644
index 00000000000..0b353ba5d88
--- /dev/null
+++ b/db/migrate/20210121093618_remove_repository_read_only_to_groups.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class RemoveRepositoryReadOnlyToGroups < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ if column_exists?(:namespaces, :repository_read_only)
+ with_lock_retries do
+ remove_column :namespaces, :repository_read_only # rubocop:disable Migration/RemoveColumn
+ end
+ end
+ end
+
+ def down
+ unless column_exists?(:namespaces, :repository_read_only)
+ with_lock_retries do
+ add_column :namespaces, :repository_read_only, :boolean, default: false, null: false # rubocop:disable Migration/AddColumnsToWideTables
+ end
+ end
+ end
+end
diff --git a/db/migrate/20210121100038_add_devops_adoption_group_segment.rb b/db/migrate/20210121100038_add_devops_adoption_group_segment.rb
new file mode 100644
index 00000000000..619657e7f56
--- /dev/null
+++ b/db/migrate/20210121100038_add_devops_adoption_group_segment.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddDevopsAdoptionGroupSegment < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column :analytics_devops_adoption_segments, :namespace_id, :integer, if_not_exists: true
+ add_concurrent_index :analytics_devops_adoption_segments, :namespace_id, unique: true
+ end
+
+ def down
+ remove_column :analytics_devops_adoption_segments, :namespace_id
+ end
+end
diff --git a/db/migrate/20210121121102_optional_devops_adoption_segment_name.rb b/db/migrate/20210121121102_optional_devops_adoption_segment_name.rb
new file mode 100644
index 00000000000..d7fda093cfc
--- /dev/null
+++ b/db/migrate/20210121121102_optional_devops_adoption_segment_name.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class OptionalDevopsAdoptionSegmentName < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_analytics_devops_adoption_segments_on_name'
+
+ def up
+ change_column_null :analytics_devops_adoption_segments, :name, true
+ remove_concurrent_index_by_name :analytics_devops_adoption_segments, INDEX_NAME
+ end
+
+ def down
+ transaction do
+ execute "DELETE FROM analytics_devops_adoption_segments WHERE name IS NULL"
+ change_column_null :analytics_devops_adoption_segments, :name, false
+ end
+ add_concurrent_index :analytics_devops_adoption_segments, :name, unique: true, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210122073805_add_repository_read_only_to_namespace_settings.rb b/db/migrate/20210122073805_add_repository_read_only_to_namespace_settings.rb
new file mode 100644
index 00000000000..f6479bdb3a4
--- /dev/null
+++ b/db/migrate/20210122073805_add_repository_read_only_to_namespace_settings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddRepositoryReadOnlyToNamespaceSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :namespace_settings, :repository_read_only, :boolean, default: false, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :namespace_settings, :repository_read_only
+ end
+ end
+end
diff --git a/db/migrate/20210122153259_add_state_to_merge_request_reviewers.rb b/db/migrate/20210122153259_add_state_to_merge_request_reviewers.rb
new file mode 100644
index 00000000000..dd0c98615f7
--- /dev/null
+++ b/db/migrate/20210122153259_add_state_to_merge_request_reviewers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddStateToMergeRequestReviewers < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ REVIEW_DEFAULT_STATE = 0
+
+ def change
+ add_column :merge_request_reviewers, :state, :smallint, default: REVIEW_DEFAULT_STATE, null: false
+ end
+end
diff --git a/db/migrate/20210122155158_add_pipeline_step_to_bulk_imports_failures.rb b/db/migrate/20210122155158_add_pipeline_step_to_bulk_imports_failures.rb
new file mode 100644
index 00000000000..749e0b16eaf
--- /dev/null
+++ b/db/migrate/20210122155158_add_pipeline_step_to_bulk_imports_failures.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class AddPipelineStepToBulkImportsFailures < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:bulk_import_failures, :pipeline_step, :text)
+ with_lock_retries do
+ add_column :bulk_import_failures, :pipeline_step, :text
+ end
+ end
+
+ add_text_limit :bulk_import_failures, :pipeline_step, 255
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :bulk_import_failures, :pipeline_step
+ end
+ end
+end
diff --git a/db/migrate/20210125105410_add_devops_adoption_segment_namespace_fk.rb b/db/migrate/20210125105410_add_devops_adoption_segment_namespace_fk.rb
new file mode 100644
index 00000000000..c7c18ae69d0
--- /dev/null
+++ b/db/migrate/20210125105410_add_devops_adoption_segment_namespace_fk.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddDevopsAdoptionSegmentNamespaceFk < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :analytics_devops_adoption_segments, :namespaces, column: :namespace_id
+ end
+
+ def down
+ remove_foreign_key_if_exists :analytics_devops_adoption_segments, :namespaces, column: :namespace_id
+ end
+end
diff --git a/db/migrate/20210126030249_add_security_dashboard_access_level_into_project_features.rb b/db/migrate/20210126030249_add_security_dashboard_access_level_into_project_features.rb
new file mode 100644
index 00000000000..cd325747282
--- /dev/null
+++ b/db/migrate/20210126030249_add_security_dashboard_access_level_into_project_features.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddSecurityDashboardAccessLevelIntoProjectFeatures < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ PRIVATE_ACCESS_LEVEL = 10
+
+ def up
+ with_lock_retries do
+ add_column :project_features, :security_and_compliance_access_level, :integer, default: PRIVATE_ACCESS_LEVEL, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_features, :security_and_compliance_access_level
+ end
+ end
+end
diff --git a/db/migrate/20210126091713_add_unique_index_services_project_id_and_type.rb b/db/migrate/20210126091713_add_unique_index_services_project_id_and_type.rb
new file mode 100644
index 00000000000..272dca70a8b
--- /dev/null
+++ b/db/migrate/20210126091713_add_unique_index_services_project_id_and_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexServicesProjectIdAndType < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_services_on_project_id_and_type_unique'
+
+ def up
+ add_concurrent_index :services, [:project_id, :type], name: INDEX_NAME, unique: true
+ end
+
+ def down
+ remove_concurrent_index_by_name :services, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210126092102_remove_index_services_project_id_and_type.rb b/db/migrate/20210126092102_remove_index_services_project_id_and_type.rb
new file mode 100644
index 00000000000..49780d03b7b
--- /dev/null
+++ b/db/migrate/20210126092102_remove_index_services_project_id_and_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveIndexServicesProjectIdAndType < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_services_on_project_id_and_type'
+
+ # Replaced by the index added in 20210126091713_add_unique_index_services_project_id_and_type.rb
+ def up
+ remove_concurrent_index_by_name :services, name: INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :services, [:project_id, :type], name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210126233608_add_rubygems_max_file_size_to_plan_limits.rb b/db/migrate/20210126233608_add_rubygems_max_file_size_to_plan_limits.rb
new file mode 100644
index 00000000000..e0e7e773d17
--- /dev/null
+++ b/db/migrate/20210126233608_add_rubygems_max_file_size_to_plan_limits.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddRubygemsMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :plan_limits, :rubygems_max_file_size, :bigint, default: 3.gigabytes, null: false
+ end
+end
diff --git a/db/migrate/20210127052226_add_subgroup_events_to_web_hooks.rb b/db/migrate/20210127052226_add_subgroup_events_to_web_hooks.rb
new file mode 100644
index 00000000000..fe2b2ef412d
--- /dev/null
+++ b/db/migrate/20210127052226_add_subgroup_events_to_web_hooks.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddSubgroupEventsToWebHooks < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :web_hooks, :subgroup_events, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20210127143025_add_oldest_merge_requests_index.rb b/db/migrate/20210127143025_add_oldest_merge_requests_index.rb
new file mode 100644
index 00000000000..c25e12d89af
--- /dev/null
+++ b/db/migrate/20210127143025_add_oldest_merge_requests_index.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddOldestMergeRequestsIndex < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ # replaced by db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb
+ end
+
+ def down
+ # replaced by db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb
+ end
+end
diff --git a/db/migrate/20210128044930_add_git_two_factor_session_expiry_to_application_settings.rb b/db/migrate/20210128044930_add_git_two_factor_session_expiry_to_application_settings.rb
new file mode 100644
index 00000000000..77a1dd2131b
--- /dev/null
+++ b/db/migrate/20210128044930_add_git_two_factor_session_expiry_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddGitTwoFactorSessionExpiryToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :git_two_factor_session_expiry, :integer, default: 15, null: false
+ end
+end
diff --git a/db/migrate/20210128101707_add_prevent_merge_without_jira_issue_to_project_settings.rb b/db/migrate/20210128101707_add_prevent_merge_without_jira_issue_to_project_settings.rb
new file mode 100644
index 00000000000..18f186294f1
--- /dev/null
+++ b/db/migrate/20210128101707_add_prevent_merge_without_jira_issue_to_project_settings.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPreventMergeWithoutJiraIssueToProjectSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :project_settings, :prevent_merge_without_jira_issue, :boolean, null: false, default: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :project_settings, :prevent_merge_without_jira_issue
+ end
+ end
+end
diff --git a/db/migrate/20210128114526_add_auto_delete_at_to_environments.rb b/db/migrate/20210128114526_add_auto_delete_at_to_environments.rb
new file mode 100644
index 00000000000..8f89c2f2ad0
--- /dev/null
+++ b/db/migrate/20210128114526_add_auto_delete_at_to_environments.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddAutoDeleteAtToEnvironments < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :environments, :auto_delete_at, :datetime_with_timezone
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :environments, :auto_delete_at
+ end
+ end
+end
diff --git a/db/migrate/20210128140157_add_content_type_to_dependency_proxy_manifests.rb b/db/migrate/20210128140157_add_content_type_to_dependency_proxy_manifests.rb
new file mode 100644
index 00000000000..d016e3c20e2
--- /dev/null
+++ b/db/migrate/20210128140157_add_content_type_to_dependency_proxy_manifests.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AddContentTypeToDependencyProxyManifests < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20210128140232_add_text_limit_to_dependency_proxy_manifests_content_type.rb
+ def change
+ add_column :dependency_proxy_manifests, :content_type, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20210128140232_add_text_limit_to_dependency_proxy_manifests_content_type.rb b/db/migrate/20210128140232_add_text_limit_to_dependency_proxy_manifests_content_type.rb
new file mode 100644
index 00000000000..035e4795ce0
--- /dev/null
+++ b/db/migrate/20210128140232_add_text_limit_to_dependency_proxy_manifests_content_type.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddTextLimitToDependencyProxyManifestsContentType < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :dependency_proxy_manifests, :content_type, 255
+ end
+
+ def down
+ remove_text_limit :dependency_proxy_manifests, :content_type
+ end
+end
diff --git a/db/migrate/20210128152830_create_ci_namespace_monthly_usage.rb b/db/migrate/20210128152830_create_ci_namespace_monthly_usage.rb
new file mode 100644
index 00000000000..d6ee057a56b
--- /dev/null
+++ b/db/migrate/20210128152830_create_ci_namespace_monthly_usage.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class CreateCiNamespaceMonthlyUsage < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ create_table :ci_namespace_monthly_usages, if_not_exists: true do |t|
+ t.references :namespace, index: false, null: false
+ t.date :date, null: false
+ t.integer :additional_amount_available, null: false, default: 0
+ t.decimal :amount_used, null: false, default: 0.0, precision: 18, scale: 2
+
+ t.index [:namespace_id, :date], unique: true
+ end
+ end
+
+ add_check_constraint :ci_namespace_monthly_usages, "(date = date_trunc('month', date))", 'ci_namespace_monthly_usages_year_month_constraint'
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :ci_namespace_monthly_usages
+ end
+ end
+end
diff --git a/db/migrate/20210129225244_add_index_to_oncall_shfts_on_starts_at_and_ends_at.rb b/db/migrate/20210129225244_add_index_to_oncall_shfts_on_starts_at_and_ends_at.rb
new file mode 100644
index 00000000000..8285aceb24a
--- /dev/null
+++ b/db/migrate/20210129225244_add_index_to_oncall_shfts_on_starts_at_and_ends_at.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class AddIndexToOncallShftsOnStartsAtAndEndsAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ NEW_NAME = 'index_oncall_shifts_on_rotation_id_and_starts_at_and_ends_at'
+ OLD_NAME = 'index_incident_management_oncall_shifts_on_rotation_id'
+
+ def up
+ add_concurrent_index :incident_management_oncall_shifts, %i[rotation_id starts_at ends_at], name: NEW_NAME
+
+ remove_concurrent_index_by_name :incident_management_oncall_shifts, OLD_NAME
+ end
+
+ def down
+ add_concurrent_index :incident_management_oncall_shifts, :rotation_id, name: OLD_NAME
+
+ remove_concurrent_index_by_name :incident_management_oncall_shifts, NEW_NAME
+ end
+end
diff --git a/db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb b/db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb
new file mode 100644
index 00000000000..a3fed9e576a
--- /dev/null
+++ b/db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+class AddOldestMergeRequestsIndexAgain < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::SchemaHelpers
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ INDEX = 'index_on_merge_requests_for_latest_diffs'
+
+ def up
+ execute "DROP INDEX CONCURRENTLY #{INDEX}" if invalid_index?
+
+ return if index_exists_by_name?('merge_requests', INDEX)
+
+ begin
+ disable_statement_timeout do
+ execute "CREATE INDEX CONCURRENTLY #{INDEX} ON merge_requests " \
+ 'USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id)'
+ end
+ rescue ActiveRecord::StatementInvalid => ex
+ # Due to https://github.com/lfittl/pg_query/issues/184, if the CREATE
+ # INDEX statement fails, we trigger a separate error due to the Gem not
+ # supporting the INCLUDE syntax.
+ #
+ # To work around this, we raise a custom error instead, as these won't
+ # have a query context injected.
+ raise "The index #{INDEX} couldn't be added: #{ex.message}"
+ end
+
+ create_comment(
+ 'INDEX',
+ INDEX,
+ 'Index used to efficiently obtain the oldest merge request for a commit SHA'
+ )
+ end
+
+ def down
+ return unless index_exists_by_name?('merge_requests', INDEX)
+
+ disable_statement_timeout do
+ execute "DROP INDEX CONCURRENTLY #{INDEX}"
+ end
+ end
+
+ def invalid_index?
+ result = execute(<<~SQL)
+ SELECT pg_class.relname
+ FROM pg_class, pg_index
+ WHERE pg_index.indisvalid = false
+ AND pg_index.indexrelid = pg_class.oid
+ AND pg_class.relname = '#{INDEX}';
+ SQL
+
+ result.values.any?
+ end
+end
diff --git a/db/migrate/20210203002331_drop_backup_label_index.rb b/db/migrate/20210203002331_drop_backup_label_index.rb
new file mode 100644
index 00000000000..430d2d0fb79
--- /dev/null
+++ b/db/migrate/20210203002331_drop_backup_label_index.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class DropBackupLabelIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'backup_labels_project_id_title_idx'
+
+ def up
+ remove_concurrent_index_by_name(:backup_labels, name: INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :backup_labels, [:project_id, :title], name: INDEX_NAME, unique: true, where: 'group_id = NULL::integer'
+ end
+end
diff --git a/db/migrate/20210203092540_remove_has_external_wiki_constraint.rb b/db/migrate/20210203092540_remove_has_external_wiki_constraint.rb
new file mode 100644
index 00000000000..80b0cc11685
--- /dev/null
+++ b/db/migrate/20210203092540_remove_has_external_wiki_constraint.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveHasExternalWikiConstraint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ # This reverts the following migration: add_not_null_constraint :projects, :has_external_wiki, validate: false
+ if check_not_null_constraint_exists?(:projects, :has_external_wiki)
+ remove_not_null_constraint :projects, :has_external_wiki
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210203092549_restore_has_external_wiki_default_value.rb b/db/migrate/20210203092549_restore_has_external_wiki_default_value.rb
new file mode 100644
index 00000000000..37111b370a5
--- /dev/null
+++ b/db/migrate/20210203092549_restore_has_external_wiki_default_value.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class RestoreHasExternalWikiDefaultValue < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class TmpProject < ActiveRecord::Base
+ self.table_name = 'projects'
+ end
+
+ # This reverts the following migration: change_column_default(:projects, :has_external_wiki, from: nil, to: false)
+ # We only change the column when the current default value is false
+ def up
+ # Find out the current default value
+ column = TmpProject.columns.find { |c| c.name == 'has_external_wiki' }
+ return unless column
+
+ if column.default == 'false'
+ with_lock_retries do
+ change_column_default(:projects, :has_external_wiki, from: false, to: nil)
+ end
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20210203221631_create_packages_rubygems_metadata.rb b/db/migrate/20210203221631_create_packages_rubygems_metadata.rb
new file mode 100644
index 00000000000..f4ad5abf7e5
--- /dev/null
+++ b/db/migrate/20210203221631_create_packages_rubygems_metadata.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+class CreatePackagesRubygemsMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ create_table_with_constraints :packages_rubygems_metadata, id: false do |t|
+ t.timestamps_with_timezone
+ t.references :package, primary_key: true, index: false, default: nil, null: false, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :bigint
+ t.text :authors
+ t.text :files
+ t.text :summary
+
+ t.text :description
+ t.text :email
+ t.text :homepage
+ t.text :licenses
+ t.text :metadata
+
+ t.text :author
+ t.text :bindir
+ t.text :cert_chain
+ t.text :executables
+ t.text :extensions
+ t.text :extra_rdoc_files
+ t.text :platform
+ t.text :post_install_message
+ t.text :rdoc_options
+ t.text :require_paths
+ t.text :required_ruby_version
+ t.text :required_rubygems_version
+ t.text :requirements
+ t.text :rubygems_version
+ t.text :signing_key
+
+ t.text_limit :authors, 255
+ t.text_limit :files, 255
+ t.text_limit :summary, 1024
+
+ t.text_limit :description, 1024
+ t.text_limit :email, 255
+ t.text_limit :homepage, 255
+ t.text_limit :licenses, 255
+ t.text_limit :metadata, 255
+
+ t.text_limit :author, 255
+ t.text_limit :bindir, 255
+ t.text_limit :cert_chain, 255
+ t.text_limit :executables, 255
+ t.text_limit :extensions, 255
+ t.text_limit :extra_rdoc_files, 255
+ t.text_limit :platform, 255
+ t.text_limit :post_install_message, 255
+ t.text_limit :rdoc_options, 255
+ t.text_limit :require_paths, 255
+ t.text_limit :required_ruby_version, 255
+ t.text_limit :required_rubygems_version, 255
+ t.text_limit :requirements, 255
+ t.text_limit :rubygems_version, 255
+ t.text_limit :signing_key, 255
+ end
+ end
+
+ def down
+ drop_table :packages_rubygems_metadata
+ end
+end
diff --git a/db/migrate/20210203222620_add_expired_index_to_composer_cache_files.rb b/db/migrate/20210203222620_add_expired_index_to_composer_cache_files.rb
new file mode 100644
index 00000000000..9c6a27812a5
--- /dev/null
+++ b/db/migrate/20210203222620_add_expired_index_to_composer_cache_files.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddExpiredIndexToComposerCacheFiles < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'composer_cache_files_index_on_deleted_at'
+
+ def up
+ add_concurrent_index :packages_composer_cache_files, [:delete_at, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :packages_composer_cache_files, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210203223551_add_orphan_index_to_composer_cache_files.rb b/db/migrate/20210203223551_add_orphan_index_to_composer_cache_files.rb
new file mode 100644
index 00000000000..e2853977e5f
--- /dev/null
+++ b/db/migrate/20210203223551_add_orphan_index_to_composer_cache_files.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddOrphanIndexToComposerCacheFiles < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_composer_cache_files_where_namespace_id_is_null'
+
+ def up
+ add_concurrent_index :packages_composer_cache_files, :id, name: INDEX_NAME, where: 'namespace_id IS NULL'
+ end
+
+ def down
+ remove_concurrent_index_by_name :packages_composer_cache_files, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210204152257_add_status_to_packages_packages.rb b/db/migrate/20210204152257_add_status_to_packages_packages.rb
new file mode 100644
index 00000000000..4fd441048c6
--- /dev/null
+++ b/db/migrate/20210204152257_add_status_to_packages_packages.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddStatusToPackagesPackages < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :packages_packages, :status, :smallint, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20210204212850_add_group_id_to_ci_daily_build_group_report_results.rb b/db/migrate/20210204212850_add_group_id_to_ci_daily_build_group_report_results.rb
new file mode 100644
index 00000000000..ba0464f5ad6
--- /dev/null
+++ b/db/migrate/20210204212850_add_group_id_to_ci_daily_build_group_report_results.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddGroupIdToCiDailyBuildGroupReportResults < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column(:ci_daily_build_group_report_results, :group_id, :bigint)
+ end
+end
diff --git a/db/migrate/20210205084357_create_ci_project_monthly_usage.rb b/db/migrate/20210205084357_create_ci_project_monthly_usage.rb
new file mode 100644
index 00000000000..c91bfa5ee1c
--- /dev/null
+++ b/db/migrate/20210205084357_create_ci_project_monthly_usage.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class CreateCiProjectMonthlyUsage < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ create_table :ci_project_monthly_usages, if_not_exists: true do |t|
+ t.references :project, foreign_key: { on_delete: :cascade }, index: false, null: false
+ t.date :date, null: false
+ t.decimal :amount_used, null: false, default: 0.0, precision: 18, scale: 2
+
+ t.index [:project_id, :date], unique: true
+ end
+ end
+
+ add_check_constraint :ci_project_monthly_usages, "(date = date_trunc('month', date))", 'ci_project_monthly_usages_year_month_constraint'
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :ci_project_monthly_usages
+ end
+ end
+end
diff --git a/db/migrate/20210205143926_remove_namespace_id_foreign_key_on_namespace_onboarding_actions.rb b/db/migrate/20210205143926_remove_namespace_id_foreign_key_on_namespace_onboarding_actions.rb
new file mode 100644
index 00000000000..6fe66430dd0
--- /dev/null
+++ b/db/migrate/20210205143926_remove_namespace_id_foreign_key_on_namespace_onboarding_actions.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveNamespaceIdForeignKeyOnNamespaceOnboardingActions < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ remove_foreign_key :namespace_onboarding_actions, :namespaces
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_foreign_key :namespace_onboarding_actions, :namespaces, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20210205213915_remove_foreign_keys_from_alerts_service_data.rb b/db/migrate/20210205213915_remove_foreign_keys_from_alerts_service_data.rb
new file mode 100644
index 00000000000..1d539f783b4
--- /dev/null
+++ b/db/migrate/20210205213915_remove_foreign_keys_from_alerts_service_data.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveForeignKeysFromAlertsServiceData < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists :alerts_service_data, column: :service_id
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_foreign_key :alerts_service_data, :services, column: :service_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20210208125050_add_status_expires_at_to_user_statuses.rb b/db/migrate/20210208125050_add_status_expires_at_to_user_statuses.rb
new file mode 100644
index 00000000000..3ec1f6014a8
--- /dev/null
+++ b/db/migrate/20210208125050_add_status_expires_at_to_user_statuses.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddStatusExpiresAtToUserStatuses < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column(:user_statuses, :clear_status_at, :datetime_with_timezone, null: true)
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column(:user_statuses, :clear_status_at)
+ end
+ end
+end
diff --git a/db/migrate/20210208125248_add_index_on_user_statuses_status_expires_at.rb b/db/migrate/20210208125248_add_index_on_user_statuses_status_expires_at.rb
new file mode 100644
index 00000000000..98f3449c2e8
--- /dev/null
+++ b/db/migrate/20210208125248_add_index_on_user_statuses_status_expires_at.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexOnUserStatusesStatusExpiresAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_user_statuses_on_clear_status_at_not_null'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:user_statuses, :clear_status_at, name: INDEX_NAME, where: 'clear_status_at IS NOT NULL')
+ end
+
+ def down
+ remove_concurrent_index_by_name(:user_statuses, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210208144134_add_index_group_id_to_ci_daily_build_group_report_results.rb b/db/migrate/20210208144134_add_index_group_id_to_ci_daily_build_group_report_results.rb
new file mode 100644
index 00000000000..422d8174043
--- /dev/null
+++ b/db/migrate/20210208144134_add_index_group_id_to_ci_daily_build_group_report_results.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddIndexGroupIdToCiDailyBuildGroupReportResults < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_daily_build_group_report_results_on_group_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:ci_daily_build_group_report_results, :group_id, name: INDEX_NAME)
+ add_concurrent_foreign_key(:ci_daily_build_group_report_results, :namespaces, column: :group_id)
+ end
+
+ def down
+ remove_foreign_key_if_exists(:ci_daily_build_group_report_results, column: :group_id)
+ remove_concurrent_index_by_name(:ci_daily_build_group_report_results, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20210208161207_add_notes_create_limit_to_application_settings.rb b/db/migrate/20210208161207_add_notes_create_limit_to_application_settings.rb
new file mode 100644
index 00000000000..4468da77e6c
--- /dev/null
+++ b/db/migrate/20210208161207_add_notes_create_limit_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddNotesCreateLimitToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :notes_create_limit, :integer, default: 300, null: false
+ end
+end
diff --git a/db/migrate/20210209160510_create_security_orchestration_policy_configurations.rb b/db/migrate/20210209160510_create_security_orchestration_policy_configurations.rb
new file mode 100644
index 00000000000..896593c803f
--- /dev/null
+++ b/db/migrate/20210209160510_create_security_orchestration_policy_configurations.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class CreateSecurityOrchestrationPolicyConfigurations < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_PREFIX = 'index_sop_configs_'
+
+ def up
+ table_comment = { owner: 'group::container security', description: 'Configuration used to store relationship between project and security policy repository' }
+
+ create_table_with_constraints :security_orchestration_policy_configurations, comment: table_comment.to_json do |t|
+ t.references :project, null: false, foreign_key: { to_table: :projects, on_delete: :cascade }, index: { name: INDEX_PREFIX + 'on_project_id', unique: true }
+ t.references :security_policy_management_project, null: false, foreign_key: { to_table: :projects, on_delete: :restrict }, index: { name: INDEX_PREFIX + 'on_security_policy_management_project_id', unique: true }
+
+ t.timestamps_with_timezone
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :security_orchestration_policy_configurations, force: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20210209171525_add_status_index_to_packages_packages.rb b/db/migrate/20210209171525_add_status_index_to_packages_packages.rb
new file mode 100644
index 00000000000..cb956165d6e
--- /dev/null
+++ b/db/migrate/20210209171525_add_status_index_to_packages_packages.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddStatusIndexToPackagesPackages < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_packages_packages_on_project_id_and_status'
+
+ def up
+ add_concurrent_index :packages_packages, [:project_id, :status], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :packages_packages, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20210210210232_add_notes_create_limit_allowlist_to_application_settings.rb b/db/migrate/20210210210232_add_notes_create_limit_allowlist_to_application_settings.rb
new file mode 100644
index 00000000000..56feed3688c
--- /dev/null
+++ b/db/migrate/20210210210232_add_notes_create_limit_allowlist_to_application_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddNotesCreateLimitAllowlistToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :notes_create_limit_allowlist, :text, array: true, default: [], null: false
+ end
+end
diff --git a/db/migrate/20210211195543_add_created_by_user_for_cluster_agent_token.rb b/db/migrate/20210211195543_add_created_by_user_for_cluster_agent_token.rb
new file mode 100644
index 00000000000..94dc8192037
--- /dev/null
+++ b/db/migrate/20210211195543_add_created_by_user_for_cluster_agent_token.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddCreatedByUserForClusterAgentToken < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_cluster_agent_tokens_on_created_by_user_id'
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:cluster_agent_tokens, :created_by_user_id)
+ add_column :cluster_agent_tokens, :created_by_user_id, :bigint
+ end
+
+ add_concurrent_index :cluster_agent_tokens, :created_by_user_id, name: INDEX_NAME
+ add_concurrent_foreign_key :cluster_agent_tokens, :users, column: :created_by_user_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :cluster_agent_tokens, :users, column: :created_by_user_id
+ end
+
+ remove_concurrent_index_by_name :cluster_agent_tokens, INDEX_NAME
+ remove_column :cluster_agent_tokens, :created_by_user_id
+ end
+end
diff --git a/db/migrate/20210216135504_add_created_by_to_cluster_agent.rb b/db/migrate/20210216135504_add_created_by_to_cluster_agent.rb
new file mode 100644
index 00000000000..fd679a1c525
--- /dev/null
+++ b/db/migrate/20210216135504_add_created_by_to_cluster_agent.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddCreatedByToClusterAgent < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_cluster_agents_on_created_by_user_id'
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:cluster_agents, :created_by_user_id)
+ with_lock_retries do
+ add_column :cluster_agents, :created_by_user_id, :bigint
+ end
+ end
+
+ add_concurrent_index :cluster_agents, :created_by_user_id, name: INDEX_NAME
+ add_concurrent_foreign_key :cluster_agents, :users, column: :created_by_user_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :cluster_agents, :created_by_user_id
+ end
+ end
+end
diff --git a/db/optional_migrations/composite_primary_keys.rb b/db/optional_migrations/composite_primary_keys.rb
index 1fcb9664ff6..13bc58b8692 100644
--- a/db/optional_migrations/composite_primary_keys.rb
+++ b/db/optional_migrations/composite_primary_keys.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This migration adds a primary key constraint to tables
# that only have a composite unique key.
#
diff --git a/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb b/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb
index c05ad73d616..34536e22bbf 100644
--- a/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb
+++ b/db/post_migrate/20190214112022_schedule_sync_issuables_state_id.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ScheduleSyncIssuablesStateId < ActiveRecord::Migration[5.0]
# This migration schedules the sync of state_id for issues and merge requests
# which are converting the state column from string to integer.
diff --git a/db/post_migrate/20190606175050_encrypt_feature_flags_clients_tokens.rb b/db/post_migrate/20190606175050_encrypt_feature_flags_clients_tokens.rb
index cb7d723670f..b8df41767f0 100644
--- a/db/post_migrate/20190606175050_encrypt_feature_flags_clients_tokens.rb
+++ b/db/post_migrate/20190606175050_encrypt_feature_flags_clients_tokens.rb
@@ -10,7 +10,7 @@ class EncryptFeatureFlagsClientsTokens < ActiveRecord::Migration[5.1]
def up
say_with_time("Encrypting tokens from operations_feature_flags_clients") do
FeatureFlagsClient.where('token_encrypted is NULL AND token IS NOT NULL').find_each do |feature_flags_client|
- token_encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(feature_flags_client.token)
+ token_encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(feature_flags_client.token, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
feature_flags_client.update!(token_encrypted: token_encrypted)
end
end
diff --git a/db/post_migrate/20190711201818_encrypt_deploy_tokens_tokens.rb b/db/post_migrate/20190711201818_encrypt_deploy_tokens_tokens.rb
index 2eb8d1ee11c..b2de98118b7 100644
--- a/db/post_migrate/20190711201818_encrypt_deploy_tokens_tokens.rb
+++ b/db/post_migrate/20190711201818_encrypt_deploy_tokens_tokens.rb
@@ -10,7 +10,7 @@ class EncryptDeployTokensTokens < ActiveRecord::Migration[5.1]
def up
say_with_time("Encrypting tokens from deploy_tokens") do
DeploymentTokens.where('token_encrypted is NULL AND token IS NOT NULL').find_each(batch_size: 10000) do |deploy_token|
- token_encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(deploy_token.token)
+ token_encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(deploy_token.token, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
deploy_token.update!(token_encrypted: token_encrypted)
end
end
diff --git a/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb b/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb
index cfe0daaf50f..a303b9d1869 100644
--- a/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb
+++ b/db/post_migrate/20200408132152_remove_namespaces_trial_ends_on.rb
@@ -18,7 +18,7 @@ class RemoveNamespacesTrialEndsOn < ActiveRecord::Migration[6.0]
def down
unless column_exists?(:namespaces, :trial_ends_on)
with_lock_retries do
- add_column :namespaces, :trial_ends_on, :datetime_with_timezone
+ add_column :namespaces, :trial_ends_on, :datetime_with_timezone # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb b/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
index 16a56b16e5a..b05f2da648a 100644
--- a/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
+++ b/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
@@ -16,7 +16,7 @@ class DropNamespacesPlanId < ActiveRecord::Migration[6.0]
def down
unless column_exists?(:namespaces, :plan_id)
with_lock_retries do
- add_column :namespaces, :plan_id, :integer
+ add_column :namespaces, :plan_id, :integer # rubocop:disable Migration/AddColumnsToWideTables
end
end
diff --git a/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb b/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb
index 2cb7c9c5250..6a031c28ed7 100644
--- a/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb
+++ b/db/post_migrate/20201030121314_schedule_update_existing_users_that_require_two_factor_auth.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# # frozen_string_literal: true
class ScheduleUpdateExistingUsersThatRequireTwoFactorAuth < ActiveRecord::Migration[6.0]
diff --git a/db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb b/db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb
new file mode 100644
index 00000000000..d05516bd255
--- /dev/null
+++ b/db/post_migrate/20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class ScheduleRemoveDuplicateVulnerabilitiesFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'tmp_idx_deduplicate_vulnerability_occurrences'
+
+ MIGRATION = 'RemoveDuplicateVulnerabilitiesFindings'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 5_000
+
+ disable_ddl_transaction!
+
+ class VulnerabilitiesFinding < ActiveRecord::Base
+ include ::EachBatch
+ self.table_name = "vulnerability_occurrences"
+ end
+
+ def up
+ add_concurrent_index :vulnerability_occurrences,
+ %i[project_id report_type location_fingerprint primary_identifier_id id],
+ name: INDEX_NAME
+
+ say "Scheduling #{MIGRATION} jobs"
+ queue_background_migration_jobs_by_range_at_intervals(
+ VulnerabilitiesFinding,
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb b/db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb
new file mode 100644
index 00000000000..6fea683944c
--- /dev/null
+++ b/db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class SchedulePopulateIssueEmailParticipants < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 2.minutes
+ MIGRATION = 'PopulateIssueEmailParticipants'
+
+ disable_ddl_transaction!
+
+ class Issue < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'issues'
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ Issue.where.not(service_desk_reply_to: nil),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb b/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb
new file mode 100644
index 00000000000..73725062bb3
--- /dev/null
+++ b/db/post_migrate/20210105030125_cleanup_projects_with_bad_has_external_wiki_data.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+class CleanupProjectsWithBadHasExternalWikiData < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ TMP_INDEX_NAME = 'tmp_index_projects_on_id_where_has_external_wiki_is_true'.freeze
+ BATCH_SIZE = 100
+
+ disable_ddl_transaction!
+
+ class Service < ActiveRecord::Base
+ include EachBatch
+ belongs_to :project
+
+ self.table_name = 'services'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class Project < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'projects'
+ end
+
+ def up
+ update_projects_with_active_external_wikis
+ update_projects_without_active_external_wikis
+ end
+
+ def down
+ # no-op : can't go back to incorrect data
+ end
+
+ private
+
+ def update_projects_with_active_external_wikis
+ # 11 projects are scoped in this query on GitLab.com.
+ scope = Service.where(active: true, type: 'ExternalWikiService').where.not(project_id: nil)
+
+ scope.each_batch(of: BATCH_SIZE) do |relation|
+ scope_with_projects = relation
+ .joins(:project)
+ .select('project_id')
+ .merge(Project.where(has_external_wiki: false).where(pending_delete: false).where(archived: false))
+
+ execute(<<~SQL)
+ WITH project_ids_to_update (id) AS (
+ #{scope_with_projects.to_sql}
+ )
+ UPDATE projects SET has_external_wiki = true WHERE id IN (SELECT id FROM project_ids_to_update)
+ SQL
+ end
+ end
+
+ def update_projects_without_active_external_wikis
+ # Add a temporary index to speed up the scoping of projects.
+ index_where = <<~SQL
+ (
+ "projects"."has_external_wiki" = TRUE
+ )
+ AND "projects"."pending_delete" = FALSE
+ AND "projects"."archived" = FALSE
+ SQL
+
+ add_concurrent_index(:projects, :id, where: index_where, name: TMP_INDEX_NAME)
+
+ services_sub_query = Service
+ .select('1')
+ .where('services.project_id = projects.id')
+ .where(type: 'ExternalWikiService')
+ .where(active: true)
+
+ # 322 projects are scoped in this query on GitLab.com.
+ Project.where(index_where).each_batch(of: BATCH_SIZE) do |relation|
+ relation_with_exists_query = relation.where('NOT EXISTS (?)', services_sub_query)
+ execute(<<~SQL)
+ WITH project_ids_to_update (id) AS (
+ #{relation_with_exists_query.select(:id).to_sql}
+ )
+ UPDATE projects SET has_external_wiki = false WHERE id IN (SELECT id FROM project_ids_to_update)
+ SQL
+ end
+
+ # Drop the temporary index.
+ remove_concurrent_index_by_name(:projects, TMP_INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20210105052229_clean_up_asset_proxy_whitelist_rename_on_application_settings.rb b/db/post_migrate/20210105052229_clean_up_asset_proxy_whitelist_rename_on_application_settings.rb
new file mode 100644
index 00000000000..8f6d312ae5e
--- /dev/null
+++ b/db/post_migrate/20210105052229_clean_up_asset_proxy_whitelist_rename_on_application_settings.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class CleanUpAssetProxyWhitelistRenameOnApplicationSettings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers::V2
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :application_settings,
+ :asset_proxy_whitelist,
+ :asset_proxy_allowlist
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :application_settings,
+ :asset_proxy_whitelist,
+ :asset_proxy_allowlist
+ end
+end
diff --git a/db/post_migrate/20210111075105_schedule_uuid_population_for_security_findings.rb b/db/post_migrate/20210111075105_schedule_uuid_population_for_security_findings.rb
new file mode 100644
index 00000000000..92241378495
--- /dev/null
+++ b/db/post_migrate/20210111075105_schedule_uuid_population_for_security_findings.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class ScheduleUuidPopulationForSecurityFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION_CLASS = 'PopulateUuidsForSecurityFindings'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 25
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration::PopulateUuidsForSecurityFindings.security_findings.each_batch(column: :scan_id, of: BATCH_SIZE) do |batch, index|
+ migrate_in(
+ DELAY_INTERVAL * index,
+ MIGRATION_CLASS,
+ batch.pluck(:scan_id)
+ )
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb b/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb
new file mode 100644
index 00000000000..44a76321495
--- /dev/null
+++ b/db/post_migrate/20210115220610_schedule_artifact_expiry_backfill.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+class ScheduleArtifactExpiryBackfill < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION = 'BackfillArtifactExpiryDate'.freeze
+ SWITCH_DATE = Date.new(2020, 06, 22).freeze
+ INDEX_NAME = 'expired_artifacts_temp_index'.freeze
+ OLD_INDEX_CONDITION = "expire_at IS NULL AND created_at < '#{SWITCH_DATE}'"
+ INDEX_CONDITION = "expire_at IS NULL AND date(created_at AT TIME ZONE 'UTC') < '2020-06-22'::date".freeze
+
+ disable_ddl_transaction!
+
+ class JobArtifact < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'ci_job_artifacts'
+
+ scope :without_expiry_date, -> { where(expire_at: nil) }
+ scope :before_switch, -> { where("date(created_at AT TIME ZONE 'UTC') < ?::date", SWITCH_DATE) }
+ end
+
+ def up
+ # Create temporary index for expired artifacts
+ # Needs to be removed in a later migration
+ remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
+ add_concurrent_index(:ci_job_artifacts, %i(id created_at), where: INDEX_CONDITION, name: INDEX_NAME)
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ JobArtifact.without_expiry_date.before_switch,
+ MIGRATION,
+ 2.minutes,
+ batch_size: 200_000
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
+ add_concurrent_index(:ci_job_artifacts, %i(id created_at), where: OLD_INDEX_CONDITION, name: INDEX_NAME)
+
+ Gitlab::BackgroundMigration.steal(MIGRATION) do |job|
+ job.delete
+
+ false
+ end
+ end
+end
diff --git a/db/post_migrate/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value.rb b/db/post_migrate/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value.rb
new file mode 100644
index 00000000000..132d72e180b
--- /dev/null
+++ b/db/post_migrate/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class AlterVsaIssueFirstMentionedInCommitValue < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ ISSUE_FIRST_MENTIONED_IN_COMMIT_FOSS = 2
+ ISSUE_FIRST_MENTIONED_IN_COMMIT_EE = 6
+
+ class GroupStage < ActiveRecord::Base
+ self.table_name = 'analytics_cycle_analytics_group_stages'
+
+ include EachBatch
+ end
+
+ def up
+ GroupStage.each_batch(of: 100) do |relation|
+ relation
+ .where(start_event_identifier: ISSUE_FIRST_MENTIONED_IN_COMMIT_EE)
+ .update_all(start_event_identifier: ISSUE_FIRST_MENTIONED_IN_COMMIT_FOSS)
+
+ relation
+ .where(end_event_identifier: ISSUE_FIRST_MENTIONED_IN_COMMIT_EE)
+ .update_all(end_event_identifier: ISSUE_FIRST_MENTIONED_IN_COMMIT_FOSS)
+ end
+ end
+
+ def down
+ # rollback is not needed, the identifier "6" is the same as identifier "2" on the application level
+ end
+end
diff --git a/db/post_migrate/20210203143131_migrate_existing_devops_segments_to_groups.rb b/db/post_migrate/20210203143131_migrate_existing_devops_segments_to_groups.rb
new file mode 100644
index 00000000000..5267e0fd658
--- /dev/null
+++ b/db/post_migrate/20210203143131_migrate_existing_devops_segments_to_groups.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# Data migration to migrate multi-selection segments into separate segments.
+# Both tables involved are pretty-low traffic and the number
+# of records in DB cannot exceed 400
+class MigrateExistingDevopsSegmentsToGroups < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ Gitlab::BackgroundMigration::MigrateDevopsSegmentsToGroups.new.perform
+ end
+
+ def down
+ end
+end
diff --git a/db/post_migrate/20210205104425_add_new_post_eoa_plans.rb b/db/post_migrate/20210205104425_add_new_post_eoa_plans.rb
new file mode 100644
index 00000000000..d1a5afbd314
--- /dev/null
+++ b/db/post_migrate/20210205104425_add_new_post_eoa_plans.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddNewPostEoaPlans < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ execute "INSERT INTO plans (name, title, created_at, updated_at) VALUES ('premium', 'Premium (Formerly Silver)', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
+ execute "INSERT INTO plans (name, title, created_at, updated_at) VALUES ('ultimate', 'Ultimate (Formerly Gold)', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
+ end
+
+ def down
+ execute "DELETE FROM plans WHERE name IN ('premium', 'ultimate')"
+ end
+end
diff --git a/db/post_migrate/20210205144537_remove_namespace_onboarding_actions_table.rb b/db/post_migrate/20210205144537_remove_namespace_onboarding_actions_table.rb
new file mode 100644
index 00000000000..210b1d7822c
--- /dev/null
+++ b/db/post_migrate/20210205144537_remove_namespace_onboarding_actions_table.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class RemoveNamespaceOnboardingActionsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ drop_table :namespace_onboarding_actions
+ end
+ end
+
+ def down
+ with_lock_retries do
+ create_table :namespace_onboarding_actions do |t|
+ t.references :namespace, index: true, null: false
+ t.datetime_with_timezone :created_at, null: false
+ t.integer :action, limit: 2, null: false
+ end
+ end
+ end
+end
diff --git a/db/post_migrate/20210205174154_remove_bad_dependency_proxy_manifests.rb b/db/post_migrate/20210205174154_remove_bad_dependency_proxy_manifests.rb
new file mode 100644
index 00000000000..eb302fb7009
--- /dev/null
+++ b/db/post_migrate/20210205174154_remove_bad_dependency_proxy_manifests.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveBadDependencyProxyManifests < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ # We run destroy on each record because we need the callback to remove
+ # the underlying files
+ DependencyProxy::Manifest.where.not(content_type: nil).destroy_all # rubocop:disable Cop/DestroyAll
+ end
+
+ def down
+ # no op
+ end
+end
diff --git a/db/post_migrate/20210205213933_drop_alerts_service_data.rb b/db/post_migrate/20210205213933_drop_alerts_service_data.rb
new file mode 100644
index 00000000000..6ad6c90290e
--- /dev/null
+++ b/db/post_migrate/20210205213933_drop_alerts_service_data.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class DropAlertsServiceData < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ drop_table :alerts_service_data
+ end
+ end
+
+ # rubocop:disable Migration/PreventStrings
+ def down
+ with_lock_retries do
+ create_table :alerts_service_data do |t|
+ t.bigint :service_id, null: false
+ t.timestamps_with_timezone
+ t.string :encrypted_token, limit: 255
+ t.string :encrypted_token_iv, limit: 255
+ end
+ end
+ end
+ # rubocop:enable Migration/PreventStrings
+end
diff --git a/db/post_migrate/20210205214003_remove_alerts_service_records_again.rb b/db/post_migrate/20210205214003_remove_alerts_service_records_again.rb
new file mode 100644
index 00000000000..aabc6fc00cd
--- /dev/null
+++ b/db/post_migrate/20210205214003_remove_alerts_service_records_again.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveAlertsServiceRecordsAgain < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Service < ActiveRecord::Base
+ self.table_name = 'services'
+ end
+
+ def up
+ Service.delete_by(type: 'AlertsService')
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20210210093901_backfill_updated_at_after_repository_storage_move.rb b/db/post_migrate/20210210093901_backfill_updated_at_after_repository_storage_move.rb
new file mode 100644
index 00000000000..0631cc8095e
--- /dev/null
+++ b/db/post_migrate/20210210093901_backfill_updated_at_after_repository_storage_move.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class BackfillUpdatedAtAfterRepositoryStorageMove < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 10_000
+ INTERVAL = 2.minutes
+ MIGRATION_CLASS = 'BackfillProjectUpdatedAtAfterRepositoryStorageMove'
+
+ disable_ddl_transaction!
+
+ class ProjectRepositoryStorageMove < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'project_repository_storage_moves'
+ end
+
+ def up
+ ProjectRepositoryStorageMove.reset_column_information
+
+ ProjectRepositoryStorageMove.select(:project_id).distinct.each_batch(of: BATCH_SIZE, column: :project_id) do |batch, index|
+ migrate_in(
+ INTERVAL * index,
+ MIGRATION_CLASS,
+ batch.pluck(:project_id)
+ )
+ end
+ end
+
+ def down
+ # No-op
+ end
+end
diff --git a/db/schema_migrations/20201027101010 b/db/schema_migrations/20201027101010
new file mode 100644
index 00000000000..68628373757
--- /dev/null
+++ b/db/schema_migrations/20201027101010
@@ -0,0 +1 @@
+d6b324e808265c4ba8b6216c77b7abfa96b4b8b4c9fbd8d0a15240548526c4f3 \ No newline at end of file
diff --git a/db/schema_migrations/20201108134919 b/db/schema_migrations/20201108134919
new file mode 100644
index 00000000000..10e88ae9359
--- /dev/null
+++ b/db/schema_migrations/20201108134919
@@ -0,0 +1 @@
+6643e5b4c5597d92c94115f392bfbd5cfce9884eb0bcb18f9629855f3711eed0 \ No newline at end of file
diff --git a/db/schema_migrations/20201112130710 b/db/schema_migrations/20201112130710
new file mode 100644
index 00000000000..a13668cf3ce
--- /dev/null
+++ b/db/schema_migrations/20201112130710
@@ -0,0 +1 @@
+322d7270e942c161cc8b50b8c3f531c93b6e6e938e415c1b6010a70b630bf82e \ No newline at end of file
diff --git a/db/schema_migrations/20201120092000 b/db/schema_migrations/20201120092000
new file mode 100644
index 00000000000..eaa6c37cff2
--- /dev/null
+++ b/db/schema_migrations/20201120092000
@@ -0,0 +1 @@
+c8f837a5fe7a1959af41f19f93b6dd96d8907a476626f124876ee8b10b120b71 \ No newline at end of file
diff --git a/db/schema_migrations/20201120144823 b/db/schema_migrations/20201120144823
new file mode 100644
index 00000000000..4f0c5c43978
--- /dev/null
+++ b/db/schema_migrations/20201120144823
@@ -0,0 +1 @@
+dde424c434c78e22087123fa30eec75c07268a9079fea44339915747aae235e0 \ No newline at end of file
diff --git a/db/schema_migrations/20201127104228 b/db/schema_migrations/20201127104228
new file mode 100644
index 00000000000..9a582600854
--- /dev/null
+++ b/db/schema_migrations/20201127104228
@@ -0,0 +1 @@
+a66f13cf62740c590aa195dd510f1e9f4a36e12d29fd0c824fbd0ace03717706 \ No newline at end of file
diff --git a/db/schema_migrations/20201128210234 b/db/schema_migrations/20201128210234
new file mode 100644
index 00000000000..6c85130bf58
--- /dev/null
+++ b/db/schema_migrations/20201128210234
@@ -0,0 +1 @@
+7c2f83a5821765f3657a6dd6f69bc8711a3b9388aec7335293748b883f7ab872 \ No newline at end of file
diff --git a/db/schema_migrations/20201204111200 b/db/schema_migrations/20201204111200
new file mode 100644
index 00000000000..34628516bf8
--- /dev/null
+++ b/db/schema_migrations/20201204111200
@@ -0,0 +1 @@
+2aad94b0577882df4fec3df3806993858dad9f4eb20db71c94f8590c6640d62e \ No newline at end of file
diff --git a/db/schema_migrations/20201204111300 b/db/schema_migrations/20201204111300
new file mode 100644
index 00000000000..69a114bed98
--- /dev/null
+++ b/db/schema_migrations/20201204111300
@@ -0,0 +1 @@
+e1265a293640d0d067672cb0426987c4a308025cf5a15b17bac8e30267dc8eaf \ No newline at end of file
diff --git a/db/schema_migrations/20201204111400 b/db/schema_migrations/20201204111400
new file mode 100644
index 00000000000..54fcc022f10
--- /dev/null
+++ b/db/schema_migrations/20201204111400
@@ -0,0 +1 @@
+6fcaa4184ae69fabd6f2668cad19c38a8ae7c187053d60cdf4fcbdbc0443aa42 \ No newline at end of file
diff --git a/db/schema_migrations/20201204111500 b/db/schema_migrations/20201204111500
new file mode 100644
index 00000000000..d482fb6d31a
--- /dev/null
+++ b/db/schema_migrations/20201204111500
@@ -0,0 +1 @@
+3f422a916b50cafd46b4a7486b6c3cc0a9992831a7dbc40c51323c835d845a0a \ No newline at end of file
diff --git a/db/schema_migrations/20201204111600 b/db/schema_migrations/20201204111600
new file mode 100644
index 00000000000..d6c5e232962
--- /dev/null
+++ b/db/schema_migrations/20201204111600
@@ -0,0 +1 @@
+51967d740ce184b27d0d9417fc86cb896fd3e3aa8a5e40759b290f47b9f3e99b \ No newline at end of file
diff --git a/db/schema_migrations/20201221225303 b/db/schema_migrations/20201221225303
new file mode 100644
index 00000000000..d1824217b99
--- /dev/null
+++ b/db/schema_migrations/20201221225303
@@ -0,0 +1 @@
+06dcd1a1f4bc0598357d48d9a0e838d9af1cf078234f2aabaa53ff9df01d2c17 \ No newline at end of file
diff --git a/db/schema_migrations/20210105030125 b/db/schema_migrations/20210105030125
new file mode 100644
index 00000000000..d2495a23b63
--- /dev/null
+++ b/db/schema_migrations/20210105030125
@@ -0,0 +1 @@
+c5a780e5b5e62043fb04e77ebf89f7d04dfc9bfdc70df8d89c16a3f3fd960ea3 \ No newline at end of file
diff --git a/db/schema_migrations/20210105052034 b/db/schema_migrations/20210105052034
new file mode 100644
index 00000000000..d2c1eacddf6
--- /dev/null
+++ b/db/schema_migrations/20210105052034
@@ -0,0 +1 @@
+4eef64fb237f783cdb07e012356d48a4ec9afc349721de1c53cf3def95e83858 \ No newline at end of file
diff --git a/db/schema_migrations/20210105052229 b/db/schema_migrations/20210105052229
new file mode 100644
index 00000000000..19b7f359482
--- /dev/null
+++ b/db/schema_migrations/20210105052229
@@ -0,0 +1 @@
+ef994f0c65154825906fb0952b9b3073f4cb0692f01c90280edf06a4ea2ec339 \ No newline at end of file
diff --git a/db/schema_migrations/20210105153342 b/db/schema_migrations/20210105153342
new file mode 100644
index 00000000000..cb970b9b3cc
--- /dev/null
+++ b/db/schema_migrations/20210105153342
@@ -0,0 +1 @@
+7a252c5d76c1e71421c3aa3e01584cdeeec6a5002ba6ef0824674c64f92e2764 \ No newline at end of file
diff --git a/db/schema_migrations/20210105154321 b/db/schema_migrations/20210105154321
new file mode 100644
index 00000000000..2f7f2477526
--- /dev/null
+++ b/db/schema_migrations/20210105154321
@@ -0,0 +1 @@
+9327676097c49bb1a221d79dd351ad8c57a434f19e32f49951c0d6d655c2fa4e \ No newline at end of file
diff --git a/db/schema_migrations/20210106155209 b/db/schema_migrations/20210106155209
new file mode 100644
index 00000000000..10dde1cf874
--- /dev/null
+++ b/db/schema_migrations/20210106155209
@@ -0,0 +1 @@
+4aeff45663a9f5a41a8dd92298afb4b0b57aa6f190f4648455df2fa1e39e174f \ No newline at end of file
diff --git a/db/schema_migrations/20210106225424 b/db/schema_migrations/20210106225424
new file mode 100644
index 00000000000..84878ee30f4
--- /dev/null
+++ b/db/schema_migrations/20210106225424
@@ -0,0 +1 @@
+a0561e52982756aded22563e833ab8005b4f45b84c81e872dd8c7188aeb84434 \ No newline at end of file
diff --git a/db/schema_migrations/20210107105306 b/db/schema_migrations/20210107105306
new file mode 100644
index 00000000000..fe66a041837
--- /dev/null
+++ b/db/schema_migrations/20210107105306
@@ -0,0 +1 @@
+f76ce27a82f4773dcda324d79cc93a044f21317dbb9fdff035879502b5752da3 \ No newline at end of file
diff --git a/db/schema_migrations/20210107154615 b/db/schema_migrations/20210107154615
new file mode 100644
index 00000000000..f8b6f97d3fe
--- /dev/null
+++ b/db/schema_migrations/20210107154615
@@ -0,0 +1 @@
+3e867ceefcab4f043b89d3c04e6e0a1182423039e1a9245e611128efe77c0e88 \ No newline at end of file
diff --git a/db/schema_migrations/20210111051045 b/db/schema_migrations/20210111051045
new file mode 100644
index 00000000000..842c164fc20
--- /dev/null
+++ b/db/schema_migrations/20210111051045
@@ -0,0 +1 @@
+6075e469081fcca124c0c4b485071a086545b502c398314cca05052765072caf \ No newline at end of file
diff --git a/db/schema_migrations/20210111053308 b/db/schema_migrations/20210111053308
new file mode 100644
index 00000000000..b7968a03c32
--- /dev/null
+++ b/db/schema_migrations/20210111053308
@@ -0,0 +1 @@
+a98ca25378df3fc798b6ae361b3a47b697f6b853796975221329db023cb98466 \ No newline at end of file
diff --git a/db/schema_migrations/20210111075104 b/db/schema_migrations/20210111075104
new file mode 100644
index 00000000000..f0d8f6da529
--- /dev/null
+++ b/db/schema_migrations/20210111075104
@@ -0,0 +1 @@
+3568bda1b43710880c8bfe2777d346aba1172217c27b5e690e7151aec9da2288 \ No newline at end of file
diff --git a/db/schema_migrations/20210111075105 b/db/schema_migrations/20210111075105
new file mode 100644
index 00000000000..d058560ead2
--- /dev/null
+++ b/db/schema_migrations/20210111075105
@@ -0,0 +1 @@
+d48f5e042f3f919041f0c93e6492bcf56c19f4268d4819bd231ddffe70ba7c6b \ No newline at end of file
diff --git a/db/schema_migrations/20210112202949 b/db/schema_migrations/20210112202949
new file mode 100644
index 00000000000..5926b701b1a
--- /dev/null
+++ b/db/schema_migrations/20210112202949
@@ -0,0 +1 @@
+56595e67e9e78a9558e6874d75bdcc295b89ab0096d1b37e4d9366e1574d241c \ No newline at end of file
diff --git a/db/schema_migrations/20210113224909 b/db/schema_migrations/20210113224909
new file mode 100644
index 00000000000..ab03538f520
--- /dev/null
+++ b/db/schema_migrations/20210113224909
@@ -0,0 +1 @@
+e6841491cd7d2cc015fd628f5c14270720d59cbb17b7efb160937963f074f5c2 \ No newline at end of file
diff --git a/db/schema_migrations/20210113231532 b/db/schema_migrations/20210113231532
new file mode 100644
index 00000000000..eb39ac161ba
--- /dev/null
+++ b/db/schema_migrations/20210113231532
@@ -0,0 +1 @@
+1a430ce6d137ee896cbd37bb822ccd18c9e87204b765b1192928dd82efb28602 \ No newline at end of file
diff --git a/db/schema_migrations/20210113231546 b/db/schema_migrations/20210113231546
new file mode 100644
index 00000000000..3286727b72c
--- /dev/null
+++ b/db/schema_migrations/20210113231546
@@ -0,0 +1 @@
+5d7bbf376acbf5679d111866e70b69eebba26a487a9e7d6bd571f15dc423e3e3 \ No newline at end of file
diff --git a/db/schema_migrations/20210114142443 b/db/schema_migrations/20210114142443
new file mode 100644
index 00000000000..d4e771a56f5
--- /dev/null
+++ b/db/schema_migrations/20210114142443
@@ -0,0 +1 @@
+7ef5cb1f167c133c67fc98c0abe929516ec700179747d3353d19cf8219ebd0ef \ No newline at end of file
diff --git a/db/schema_migrations/20210115090452 b/db/schema_migrations/20210115090452
new file mode 100644
index 00000000000..92c5574e71f
--- /dev/null
+++ b/db/schema_migrations/20210115090452
@@ -0,0 +1 @@
+5415850ae27c507fd8b1df20951e25b42352f4f9ec8e1402019533170edabdb8 \ No newline at end of file
diff --git a/db/schema_migrations/20210115220610 b/db/schema_migrations/20210115220610
new file mode 100644
index 00000000000..002c37e54ec
--- /dev/null
+++ b/db/schema_migrations/20210115220610
@@ -0,0 +1 @@
+541a6626d3afd4fd421fd59fe5eb8ab7764952ae780c83c3805fd4a29e3f42fb \ No newline at end of file
diff --git a/db/schema_migrations/20210117210226 b/db/schema_migrations/20210117210226
new file mode 100644
index 00000000000..a68f7f6d93e
--- /dev/null
+++ b/db/schema_migrations/20210117210226
@@ -0,0 +1 @@
+c0d22d00d52a516347930e1a36f350113c0949214925176f08ceed81999746bd \ No newline at end of file
diff --git a/db/schema_migrations/20210118111307 b/db/schema_migrations/20210118111307
new file mode 100644
index 00000000000..036d909f5ad
--- /dev/null
+++ b/db/schema_migrations/20210118111307
@@ -0,0 +1 @@
+f33cc3eebc9197db381d81150a140582e30905d3964d6fb444caad6c9eff1b31 \ No newline at end of file
diff --git a/db/schema_migrations/20210119122354 b/db/schema_migrations/20210119122354
new file mode 100644
index 00000000000..a17b2dab2df
--- /dev/null
+++ b/db/schema_migrations/20210119122354
@@ -0,0 +1 @@
+e8264993f6503268cd99e8ca26ccdc0e986f31a2818b9bbef2a9cef36191e686 \ No newline at end of file
diff --git a/db/schema_migrations/20210119153801 b/db/schema_migrations/20210119153801
new file mode 100644
index 00000000000..f84f7ad1d48
--- /dev/null
+++ b/db/schema_migrations/20210119153801
@@ -0,0 +1 @@
+c8b5485f158fdec0ab6813e4014713786dfa231b901e77ea610a873d03f8f0f0 \ No newline at end of file
diff --git a/db/schema_migrations/20210119162812 b/db/schema_migrations/20210119162812
new file mode 100644
index 00000000000..dfbf33a9fcf
--- /dev/null
+++ b/db/schema_migrations/20210119162812
@@ -0,0 +1 @@
+cd7643fc762d8b9236ef5ac7cc285ffbd29f1953178b9b6e129082efd7b9e07b \ No newline at end of file
diff --git a/db/schema_migrations/20210120180956 b/db/schema_migrations/20210120180956
new file mode 100644
index 00000000000..395c9c09df9
--- /dev/null
+++ b/db/schema_migrations/20210120180956
@@ -0,0 +1 @@
+897815c347f04093da5eba420e95b6310454bd493412914e60a296bd710ebde1 \ No newline at end of file
diff --git a/db/schema_migrations/20210120221743 b/db/schema_migrations/20210120221743
new file mode 100644
index 00000000000..ce54788b86c
--- /dev/null
+++ b/db/schema_migrations/20210120221743
@@ -0,0 +1 @@
+4bf1d277affdfa9ee772d69cb713f49f257140fb58c40bc8659d563b4cc3de29 \ No newline at end of file
diff --git a/db/schema_migrations/20210121093618 b/db/schema_migrations/20210121093618
new file mode 100644
index 00000000000..f12566f1aa9
--- /dev/null
+++ b/db/schema_migrations/20210121093618
@@ -0,0 +1 @@
+e2be30f71b2a4a410b21e57ee53c3b54cf0214a08bc65cd92b2cb4b93bde9451 \ No newline at end of file
diff --git a/db/schema_migrations/20210121100038 b/db/schema_migrations/20210121100038
new file mode 100644
index 00000000000..0f9379ff019
--- /dev/null
+++ b/db/schema_migrations/20210121100038
@@ -0,0 +1 @@
+12a5eba74f0bb5b63cddd32d32009ad073e638a9defb40eeee5c16f559ebe951 \ No newline at end of file
diff --git a/db/schema_migrations/20210121121102 b/db/schema_migrations/20210121121102
new file mode 100644
index 00000000000..6bce3892276
--- /dev/null
+++ b/db/schema_migrations/20210121121102
@@ -0,0 +1 @@
+359231b3f18a2c1e56ffba4872a51d01fd4ca834ef722e1133a5a9f01e4271e9 \ No newline at end of file
diff --git a/db/schema_migrations/20210122073805 b/db/schema_migrations/20210122073805
new file mode 100644
index 00000000000..322c90eb820
--- /dev/null
+++ b/db/schema_migrations/20210122073805
@@ -0,0 +1 @@
+f5231b1eec17ea1a67f2d2f4ca759314afb85b2c8fb431e3303d530d44bdb1ef \ No newline at end of file
diff --git a/db/schema_migrations/20210122153259 b/db/schema_migrations/20210122153259
new file mode 100644
index 00000000000..887f0ac4a5c
--- /dev/null
+++ b/db/schema_migrations/20210122153259
@@ -0,0 +1 @@
+4c697cc183a000ee8c18b516e4b1d77d0f8d2d3d7abe11121f2240a60c03216c \ No newline at end of file
diff --git a/db/schema_migrations/20210122155158 b/db/schema_migrations/20210122155158
new file mode 100644
index 00000000000..f521f910346
--- /dev/null
+++ b/db/schema_migrations/20210122155158
@@ -0,0 +1 @@
+5f326f101ff06993e9160b0486d24d615abd6d5027b375e422f776181ad8a193 \ No newline at end of file
diff --git a/db/schema_migrations/20210125105410 b/db/schema_migrations/20210125105410
new file mode 100644
index 00000000000..d685894bd8a
--- /dev/null
+++ b/db/schema_migrations/20210125105410
@@ -0,0 +1 @@
+0c80fa1c88f67ef34bbfab52b1b75eadc4a6f07557986f0fbe4ffd83e20df52a \ No newline at end of file
diff --git a/db/schema_migrations/20210126030249 b/db/schema_migrations/20210126030249
new file mode 100644
index 00000000000..068f5eeb9c5
--- /dev/null
+++ b/db/schema_migrations/20210126030249
@@ -0,0 +1 @@
+b5c219d1b1443ddf482f26d8280a1c7318456affce3ad57a082eb8f9efc32206 \ No newline at end of file
diff --git a/db/schema_migrations/20210126091713 b/db/schema_migrations/20210126091713
new file mode 100644
index 00000000000..b75636bd437
--- /dev/null
+++ b/db/schema_migrations/20210126091713
@@ -0,0 +1 @@
+3906739d07514e6e59f79a4a81d28859a2481614a299c95ec1b1d9825a07ec64 \ No newline at end of file
diff --git a/db/schema_migrations/20210126092102 b/db/schema_migrations/20210126092102
new file mode 100644
index 00000000000..803643389f6
--- /dev/null
+++ b/db/schema_migrations/20210126092102
@@ -0,0 +1 @@
+124c5ae1a1ccade5dec01f72b726e03febc8f56411d7d8990f976bb2a9516037 \ No newline at end of file
diff --git a/db/schema_migrations/20210126233608 b/db/schema_migrations/20210126233608
new file mode 100644
index 00000000000..adab3a3f365
--- /dev/null
+++ b/db/schema_migrations/20210126233608
@@ -0,0 +1 @@
+4105ae45742c2eda67fe5c54256732e55555ab7832e4cbf0fcb041599c23bd29 \ No newline at end of file
diff --git a/db/schema_migrations/20210127052226 b/db/schema_migrations/20210127052226
new file mode 100644
index 00000000000..ca7d44edff8
--- /dev/null
+++ b/db/schema_migrations/20210127052226
@@ -0,0 +1 @@
+e978687e9b27db5288862ea85053f3fc04a8e841702b16ca17c01398a86654d0 \ No newline at end of file
diff --git a/db/schema_migrations/20210127143025 b/db/schema_migrations/20210127143025
new file mode 100644
index 00000000000..a4875304c0b
--- /dev/null
+++ b/db/schema_migrations/20210127143025
@@ -0,0 +1 @@
+c173ba86340efe39977f1b319d1ebcead634e3bfe819a30e230fb4f81766f28a \ No newline at end of file
diff --git a/db/schema_migrations/20210128044930 b/db/schema_migrations/20210128044930
new file mode 100644
index 00000000000..4965cd9a9c6
--- /dev/null
+++ b/db/schema_migrations/20210128044930
@@ -0,0 +1 @@
+6164ef91c60bd614310cbda6ad8ab1a205cae17c4d037fafa89eaf95d06323e4 \ No newline at end of file
diff --git a/db/schema_migrations/20210128101707 b/db/schema_migrations/20210128101707
new file mode 100644
index 00000000000..f10f080c1df
--- /dev/null
+++ b/db/schema_migrations/20210128101707
@@ -0,0 +1 @@
+ae84fa35fcc5a0780d86887294a32e250d2ac13dcf607750f834df5828e5bece \ No newline at end of file
diff --git a/db/schema_migrations/20210128114526 b/db/schema_migrations/20210128114526
new file mode 100644
index 00000000000..107c86913ba
--- /dev/null
+++ b/db/schema_migrations/20210128114526
@@ -0,0 +1 @@
+ad83205a0203427ccad1c25933e28cf13ebfb0274865ce5f0f2d578e84bb07a3 \ No newline at end of file
diff --git a/db/schema_migrations/20210128140157 b/db/schema_migrations/20210128140157
new file mode 100644
index 00000000000..2b71db39920
--- /dev/null
+++ b/db/schema_migrations/20210128140157
@@ -0,0 +1 @@
+0fa84b2038f33e27e549bdb3eb137e1813f604b6e81abc67a49a54d3e1e4bcf5 \ No newline at end of file
diff --git a/db/schema_migrations/20210128140232 b/db/schema_migrations/20210128140232
new file mode 100644
index 00000000000..ee335323fce
--- /dev/null
+++ b/db/schema_migrations/20210128140232
@@ -0,0 +1 @@
+93f337364eb5ca5c67f4d4767d1aee9972bfe0596c89f006317dd6103558e35c \ No newline at end of file
diff --git a/db/schema_migrations/20210128152830 b/db/schema_migrations/20210128152830
new file mode 100644
index 00000000000..36d3de788eb
--- /dev/null
+++ b/db/schema_migrations/20210128152830
@@ -0,0 +1 @@
+932509d18f1cfdfa09f1565e4ac2f197b7ca792263ff5da3e5b712fae7279925 \ No newline at end of file
diff --git a/db/schema_migrations/20210129225244 b/db/schema_migrations/20210129225244
new file mode 100644
index 00000000000..1b05096b07f
--- /dev/null
+++ b/db/schema_migrations/20210129225244
@@ -0,0 +1 @@
+6cb54c71a9835ec1b3cf801a19c2cd385d224e0438c7924b6a29d298ecebe8a7 \ No newline at end of file
diff --git a/db/schema_migrations/20210201140434 b/db/schema_migrations/20210201140434
new file mode 100644
index 00000000000..00671276b1c
--- /dev/null
+++ b/db/schema_migrations/20210201140434
@@ -0,0 +1 @@
+71220cfc36215f6c22d22d1fb0b74389e90c58733214b5fa36dcb8da0377a120 \ No newline at end of file
diff --git a/db/schema_migrations/20210203002331 b/db/schema_migrations/20210203002331
new file mode 100644
index 00000000000..f1ed6bf23f6
--- /dev/null
+++ b/db/schema_migrations/20210203002331
@@ -0,0 +1 @@
+b8a19b2ebf648a1b79a488a7a2847f6a392e594464c1ba0ae96f274f583559e3 \ No newline at end of file
diff --git a/db/schema_migrations/20210203092540 b/db/schema_migrations/20210203092540
new file mode 100644
index 00000000000..12367417d44
--- /dev/null
+++ b/db/schema_migrations/20210203092540
@@ -0,0 +1 @@
+fa0b69df96069dd29971f69a51ce4eb691480904c5693fa480f6daa83b042e77 \ No newline at end of file
diff --git a/db/schema_migrations/20210203092549 b/db/schema_migrations/20210203092549
new file mode 100644
index 00000000000..967b0d3acc7
--- /dev/null
+++ b/db/schema_migrations/20210203092549
@@ -0,0 +1 @@
+096d13548e156a13b9ccdbb39ed83b3be7ef64a57df5daea2e3cd870f3e2b448 \ No newline at end of file
diff --git a/db/schema_migrations/20210203143131 b/db/schema_migrations/20210203143131
new file mode 100644
index 00000000000..6b318f8c219
--- /dev/null
+++ b/db/schema_migrations/20210203143131
@@ -0,0 +1 @@
+1f05176d9f6a88e9d740000084b7c9f5c72c61a59dbe1f68f43b3b5606ecd9d8 \ No newline at end of file
diff --git a/db/schema_migrations/20210203221631 b/db/schema_migrations/20210203221631
new file mode 100644
index 00000000000..ed9efcd2b5f
--- /dev/null
+++ b/db/schema_migrations/20210203221631
@@ -0,0 +1 @@
+ec6832ba26fca8d8427383cd0189765191a0a7f17bb78d61b900c5b541d5725e \ No newline at end of file
diff --git a/db/schema_migrations/20210203222620 b/db/schema_migrations/20210203222620
new file mode 100644
index 00000000000..2c8c3ffc111
--- /dev/null
+++ b/db/schema_migrations/20210203222620
@@ -0,0 +1 @@
+6d3250533b72c6aa307570d386725fa3ebe1ec49c36edc0f7d6dc8a1d5092826 \ No newline at end of file
diff --git a/db/schema_migrations/20210203223551 b/db/schema_migrations/20210203223551
new file mode 100644
index 00000000000..53b3a9f65aa
--- /dev/null
+++ b/db/schema_migrations/20210203223551
@@ -0,0 +1 @@
+4ccf450bbc9061edae81cabcfafd9360f1f57cfd25af3ad016fbbb344f9fe694 \ No newline at end of file
diff --git a/db/schema_migrations/20210204152257 b/db/schema_migrations/20210204152257
new file mode 100644
index 00000000000..c98d4637d05
--- /dev/null
+++ b/db/schema_migrations/20210204152257
@@ -0,0 +1 @@
+cb9f4b4e627cbc163653fc01c0542ef0ce87139b376c55bbaa4d7ab23e9b8973 \ No newline at end of file
diff --git a/db/schema_migrations/20210204212850 b/db/schema_migrations/20210204212850
new file mode 100644
index 00000000000..ffa4ca8393e
--- /dev/null
+++ b/db/schema_migrations/20210204212850
@@ -0,0 +1 @@
+2a40acf9a3ac2716120388cfe79be13130e4587286d215596e9c75097af1e436 \ No newline at end of file
diff --git a/db/schema_migrations/20210205084357 b/db/schema_migrations/20210205084357
new file mode 100644
index 00000000000..6babb782c70
--- /dev/null
+++ b/db/schema_migrations/20210205084357
@@ -0,0 +1 @@
+5bd622f36126b06c7c585ee14a8140750843d36092e79b6cc35b62c06afb1178 \ No newline at end of file
diff --git a/db/schema_migrations/20210205104425 b/db/schema_migrations/20210205104425
new file mode 100644
index 00000000000..c51f201b5a6
--- /dev/null
+++ b/db/schema_migrations/20210205104425
@@ -0,0 +1 @@
+4df2229fca7652cb836c867b621da91f1194899c50bb0a8be2fbae58f29dc788 \ No newline at end of file
diff --git a/db/schema_migrations/20210205143926 b/db/schema_migrations/20210205143926
new file mode 100644
index 00000000000..00a8c3528a7
--- /dev/null
+++ b/db/schema_migrations/20210205143926
@@ -0,0 +1 @@
+cdf55e9f2b1b9c375920198a438d29fe3c9ab7147f3c670b0d66b11d499573d9 \ No newline at end of file
diff --git a/db/schema_migrations/20210205144537 b/db/schema_migrations/20210205144537
new file mode 100644
index 00000000000..6ca27521248
--- /dev/null
+++ b/db/schema_migrations/20210205144537
@@ -0,0 +1 @@
+d9cfb7515805e642c562b8be58b6cd482c24e62e76245db35a7d91b25c327d8d \ No newline at end of file
diff --git a/db/schema_migrations/20210205174154 b/db/schema_migrations/20210205174154
new file mode 100644
index 00000000000..fc8c4b6cff1
--- /dev/null
+++ b/db/schema_migrations/20210205174154
@@ -0,0 +1 @@
+483d1b4a24086fa57efe7f3b3fa872cf793352f80aba5c25614f07eafa2d30c5 \ No newline at end of file
diff --git a/db/schema_migrations/20210205213915 b/db/schema_migrations/20210205213915
new file mode 100644
index 00000000000..5849abd1d03
--- /dev/null
+++ b/db/schema_migrations/20210205213915
@@ -0,0 +1 @@
+c7c2936062f4a7c764938453fb28dc2f461a06f0a21cc74b1750edbde9398fa1 \ No newline at end of file
diff --git a/db/schema_migrations/20210205213933 b/db/schema_migrations/20210205213933
new file mode 100644
index 00000000000..f3ebb2672c7
--- /dev/null
+++ b/db/schema_migrations/20210205213933
@@ -0,0 +1 @@
+caec7f6c66a0277561f650ae513fedaba581ab35bb238351eccccfef1132d118 \ No newline at end of file
diff --git a/db/schema_migrations/20210205214003 b/db/schema_migrations/20210205214003
new file mode 100644
index 00000000000..4d1ea7570f5
--- /dev/null
+++ b/db/schema_migrations/20210205214003
@@ -0,0 +1 @@
+6ca08c885fddccd3c82fc8651d20140655b65019e56f9c6136e92140401386d1 \ No newline at end of file
diff --git a/db/schema_migrations/20210208125050 b/db/schema_migrations/20210208125050
new file mode 100644
index 00000000000..35877cfc029
--- /dev/null
+++ b/db/schema_migrations/20210208125050
@@ -0,0 +1 @@
+b9200d6c754f7c450ba0c718171806e8f4f9720d870e532f4800640ca707f24f \ No newline at end of file
diff --git a/db/schema_migrations/20210208125248 b/db/schema_migrations/20210208125248
new file mode 100644
index 00000000000..91d5c4bb950
--- /dev/null
+++ b/db/schema_migrations/20210208125248
@@ -0,0 +1 @@
+3a7fb1b7959f09b9ba464253a72d52bcb744e7f78aac4f44e1d9201fa3c8387d \ No newline at end of file
diff --git a/db/schema_migrations/20210208144134 b/db/schema_migrations/20210208144134
new file mode 100644
index 00000000000..1afe893eba0
--- /dev/null
+++ b/db/schema_migrations/20210208144134
@@ -0,0 +1 @@
+845636d8a0c6e9b6b39194cb44ffeceea3464023c22fadb2a4da44fed5dd973f \ No newline at end of file
diff --git a/db/schema_migrations/20210208161207 b/db/schema_migrations/20210208161207
new file mode 100644
index 00000000000..7064a636822
--- /dev/null
+++ b/db/schema_migrations/20210208161207
@@ -0,0 +1 @@
+818fcf0f0fec9d2833b091ef380005a2d485486522fb63e2a7b2fd01dbf1ff79 \ No newline at end of file
diff --git a/db/schema_migrations/20210209160510 b/db/schema_migrations/20210209160510
new file mode 100644
index 00000000000..3aa90658d4e
--- /dev/null
+++ b/db/schema_migrations/20210209160510
@@ -0,0 +1 @@
+601d67a2911c461881064ec18a2246ef9e5b2835eb0fdf40e701c9360e19eca4 \ No newline at end of file
diff --git a/db/schema_migrations/20210209171525 b/db/schema_migrations/20210209171525
new file mode 100644
index 00000000000..0c421b99a39
--- /dev/null
+++ b/db/schema_migrations/20210209171525
@@ -0,0 +1 @@
+5c661c453922181b350b8551d9a8f9b097e568459a2c2d128e41d9aefb026ab5 \ No newline at end of file
diff --git a/db/schema_migrations/20210210093901 b/db/schema_migrations/20210210093901
new file mode 100644
index 00000000000..c1bbb93de21
--- /dev/null
+++ b/db/schema_migrations/20210210093901
@@ -0,0 +1 @@
+961c147e9c8e35eac5b8dd33f879582e173b7f6e31659b2d00989bc38afc6f5a \ No newline at end of file
diff --git a/db/schema_migrations/20210210210232 b/db/schema_migrations/20210210210232
new file mode 100644
index 00000000000..96f31a2adef
--- /dev/null
+++ b/db/schema_migrations/20210210210232
@@ -0,0 +1 @@
+e1bd58eeaf63caf473680a8c4b7269cc63e7c0d6e8d4e71636608e10c9731c85 \ No newline at end of file
diff --git a/db/schema_migrations/20210211195543 b/db/schema_migrations/20210211195543
new file mode 100644
index 00000000000..7f15ca21d36
--- /dev/null
+++ b/db/schema_migrations/20210211195543
@@ -0,0 +1 @@
+484338ddc83bfb44523d08da92ac7f5b9d13e1a66ad1c9c3f7590f91fc9305c0 \ No newline at end of file
diff --git a/db/schema_migrations/20210216135504 b/db/schema_migrations/20210216135504
new file mode 100644
index 00000000000..99cda90b2ee
--- /dev/null
+++ b/db/schema_migrations/20210216135504
@@ -0,0 +1 @@
+8c676b4142db828b1d2d5dc6bd891eb929d12ab13e9073693ab7d830bcea599a \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index c1f13a2fca4..97a2850fd5c 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -10,6 +10,26 @@ CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
+CREATE FUNCTION set_has_external_issue_tracker() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+UPDATE projects SET has_external_issue_tracker = (
+ EXISTS
+ (
+ SELECT 1
+ FROM services
+ WHERE project_id = COALESCE(NEW.project_id, OLD.project_id)
+ AND active = TRUE
+ AND category = 'issue_tracker'
+ )
+)
+WHERE projects.id = COALESCE(NEW.project_id, OLD.project_id);
+RETURN NULL;
+
+END
+$$;
+
CREATE FUNCTION set_has_external_wiki() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -8865,24 +8885,6 @@ CREATE SEQUENCE alert_management_http_integrations_id_seq
ALTER SEQUENCE alert_management_http_integrations_id_seq OWNED BY alert_management_http_integrations.id;
-CREATE TABLE alerts_service_data (
- id bigint NOT NULL,
- service_id integer NOT NULL,
- created_at timestamp with time zone NOT NULL,
- updated_at timestamp with time zone NOT NULL,
- encrypted_token character varying(255),
- encrypted_token_iv character varying(255)
-);
-
-CREATE SEQUENCE alerts_service_data_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE alerts_service_data_id_seq OWNED BY alerts_service_data.id;
-
CREATE TABLE allowed_email_domains (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -8988,10 +8990,11 @@ ALTER SEQUENCE analytics_devops_adoption_segment_selections_id_seq OWNED BY anal
CREATE TABLE analytics_devops_adoption_segments (
id bigint NOT NULL,
- name text NOT NULL,
+ name text,
last_recorded_at timestamp with time zone,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
+ namespace_id integer,
CONSTRAINT check_4be7a006fd CHECK ((char_length(name) <= 255))
);
@@ -9273,7 +9276,6 @@ CREATE TABLE application_settings (
instance_administration_project_id bigint,
asset_proxy_enabled boolean DEFAULT false NOT NULL,
asset_proxy_url character varying,
- asset_proxy_whitelist text,
encrypted_asset_proxy_secret_key text,
encrypted_asset_proxy_secret_key_iv character varying,
static_objects_external_storage_url character varying(255),
@@ -9390,6 +9392,13 @@ CREATE TABLE application_settings (
rate_limiting_response_text text,
invisible_captcha_enabled boolean DEFAULT false NOT NULL,
container_registry_cleanup_tags_service_max_list_size integer DEFAULT 200 NOT NULL,
+ enforce_ssh_key_expiration boolean DEFAULT false NOT NULL,
+ git_two_factor_session_expiry integer DEFAULT 15 NOT NULL,
+ asset_proxy_allowlist text,
+ keep_latest_artifact boolean DEFAULT true NOT NULL,
+ notes_create_limit integer DEFAULT 300 NOT NULL,
+ notes_create_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
+ kroki_formats jsonb DEFAULT '{}'::jsonb 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_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),
@@ -10054,8 +10063,10 @@ CREATE TABLE bulk_import_failures (
exception_class text NOT NULL,
exception_message text NOT NULL,
correlation_id_value text,
+ pipeline_step text,
CONSTRAINT check_053d65c7a4 CHECK ((char_length(pipeline_class) <= 255)),
CONSTRAINT check_6eca8f972e CHECK ((char_length(exception_message) <= 255)),
+ CONSTRAINT check_721a422375 CHECK ((char_length(pipeline_step) <= 255)),
CONSTRAINT check_c7dba8398e CHECK ((char_length(exception_class) <= 255)),
CONSTRAINT check_e787285882 CHECK ((char_length(correlation_id_value) <= 255))
);
@@ -10355,7 +10366,8 @@ CREATE TABLE ci_daily_build_group_report_results (
ref_path text NOT NULL,
group_name text NOT NULL,
data jsonb NOT NULL,
- default_branch boolean DEFAULT false NOT NULL
+ default_branch boolean DEFAULT false NOT NULL,
+ group_id bigint
);
CREATE SEQUENCE ci_daily_build_group_report_results_id_seq
@@ -10495,6 +10507,24 @@ CREATE SEQUENCE ci_job_variables_id_seq
ALTER SEQUENCE ci_job_variables_id_seq OWNED BY ci_job_variables.id;
+CREATE TABLE ci_namespace_monthly_usages (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ date date NOT NULL,
+ additional_amount_available integer DEFAULT 0 NOT NULL,
+ amount_used numeric(18,2) DEFAULT 0.0 NOT NULL,
+ CONSTRAINT ci_namespace_monthly_usages_year_month_constraint CHECK ((date = date_trunc('month'::text, (date)::timestamp with time zone)))
+);
+
+CREATE SEQUENCE ci_namespace_monthly_usages_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_namespace_monthly_usages_id_seq OWNED BY ci_namespace_monthly_usages.id;
+
CREATE TABLE ci_pipeline_artifacts (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -10692,6 +10722,23 @@ CREATE SEQUENCE ci_platform_metrics_id_seq
ALTER SEQUENCE ci_platform_metrics_id_seq OWNED BY ci_platform_metrics.id;
+CREATE TABLE ci_project_monthly_usages (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ date date NOT NULL,
+ amount_used numeric(18,2) DEFAULT 0.0 NOT NULL,
+ CONSTRAINT ci_project_monthly_usages_year_month_constraint CHECK ((date = date_trunc('month'::text, (date)::timestamp with time zone)))
+);
+
+CREATE SEQUENCE ci_project_monthly_usages_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_project_monthly_usages_id_seq OWNED BY ci_project_monthly_usages.id;
+
CREATE TABLE ci_refs (
id bigint NOT NULL,
project_id bigint NOT NULL,
@@ -10978,6 +11025,7 @@ CREATE TABLE cluster_agent_tokens (
updated_at timestamp with time zone NOT NULL,
agent_id bigint NOT NULL,
token_encrypted text NOT NULL,
+ created_by_user_id bigint,
CONSTRAINT check_c60daed227 CHECK ((char_length(token_encrypted) <= 255))
);
@@ -10996,6 +11044,7 @@ CREATE TABLE cluster_agents (
updated_at timestamp with time zone NOT NULL,
project_id bigint NOT NULL,
name text NOT NULL,
+ created_by_user_id bigint,
CONSTRAINT check_3498369510 CHECK ((char_length(name) <= 255))
);
@@ -11437,9 +11486,11 @@ CREATE TABLE compliance_management_frameworks (
color text NOT NULL,
namespace_id integer NOT NULL,
regulated boolean DEFAULT true NOT NULL,
+ pipeline_configuration_full_path text,
CONSTRAINT check_08cd34b2c2 CHECK ((char_length(color) <= 10)),
CONSTRAINT check_1617e0b87e CHECK ((char_length(description) <= 255)),
- CONSTRAINT check_ab00bc2193 CHECK ((char_length(name) <= 255))
+ CONSTRAINT check_ab00bc2193 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_e7a9972435 CHECK ((char_length(pipeline_configuration_full_path) <= 255))
);
CREATE SEQUENCE compliance_management_frameworks_id_seq
@@ -11569,6 +11620,30 @@ CREATE SEQUENCE custom_emoji_id_seq
ALTER SEQUENCE custom_emoji_id_seq OWNED BY custom_emoji.id;
+CREATE TABLE dast_profiles (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ dast_site_profile_id bigint NOT NULL,
+ dast_scanner_profile_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ name text NOT NULL,
+ description text NOT NULL,
+ CONSTRAINT check_5fcf73bf61 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_c34e505c24 CHECK ((char_length(description) <= 255))
+);
+
+COMMENT ON TABLE dast_profiles IS '{"owner":"group::dynamic analysis","description":"Profile used to run a DAST on-demand scan"}';
+
+CREATE SEQUENCE dast_profiles_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_profiles_id_seq OWNED BY dast_profiles.id;
+
CREATE TABLE dast_scanner_profiles (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11725,7 +11800,9 @@ CREATE TABLE dependency_proxy_manifests (
file_name text NOT NULL,
file text NOT NULL,
digest text NOT NULL,
+ content_type text,
CONSTRAINT check_079b293a7b CHECK ((char_length(file) <= 255)),
+ CONSTRAINT check_167a9a8a91 CHECK ((char_length(content_type) <= 255)),
CONSTRAINT check_c579e3f586 CHECK ((char_length(file_name) <= 255)),
CONSTRAINT check_f5d9996bf1 CHECK ((char_length(digest) <= 255))
);
@@ -12057,7 +12134,8 @@ CREATE TABLE environments (
environment_type character varying,
state character varying DEFAULT 'available'::character varying NOT NULL,
slug character varying NOT NULL,
- auto_stop_at timestamp with time zone
+ auto_stop_at timestamp with time zone,
+ auto_delete_at timestamp with time zone
);
CREATE SEQUENCE environments_id_seq
@@ -12215,6 +12293,8 @@ CREATE TABLE experiment_subjects (
variant smallint DEFAULT 0 NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
+ converted_at timestamp with time zone,
+ context jsonb DEFAULT '{}'::jsonb NOT NULL,
CONSTRAINT chk_has_one_subject CHECK ((num_nonnulls(user_id, group_id, project_id) = 1))
);
@@ -12998,6 +13078,27 @@ CREATE TABLE group_merge_request_approval_settings (
allow_author_approval boolean DEFAULT false NOT NULL
);
+CREATE TABLE group_repository_storage_moves (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ group_id bigint NOT NULL,
+ state smallint DEFAULT 1 NOT NULL,
+ source_storage_name text NOT NULL,
+ destination_storage_name text NOT NULL,
+ CONSTRAINT group_repository_storage_moves_destination_storage_name CHECK ((char_length(destination_storage_name) <= 255)),
+ CONSTRAINT group_repository_storage_moves_source_storage_name CHECK ((char_length(source_storage_name) <= 255))
+);
+
+CREATE SEQUENCE group_repository_storage_moves_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE group_repository_storage_moves_id_seq OWNED BY group_repository_storage_moves.id;
+
CREATE TABLE group_wiki_repositories (
shard_id bigint NOT NULL,
group_id bigint NOT NULL,
@@ -13526,6 +13627,14 @@ CREATE TABLE jira_tracker_data (
deployment_type smallint DEFAULT 0 NOT NULL,
vulnerabilities_issuetype text,
vulnerabilities_enabled boolean DEFAULT false NOT NULL,
+ encrypted_proxy_address text,
+ encrypted_proxy_address_iv text,
+ encrypted_proxy_port text,
+ encrypted_proxy_port_iv text,
+ encrypted_proxy_username text,
+ encrypted_proxy_username_iv text,
+ encrypted_proxy_password text,
+ encrypted_proxy_password_iv text,
CONSTRAINT check_0bf84b76e9 CHECK ((char_length(vulnerabilities_issuetype) <= 255)),
CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
);
@@ -13863,7 +13972,8 @@ CREATE TABLE merge_request_context_commits (
committer_name text,
committer_email text,
message text,
- merge_request_id bigint
+ merge_request_id bigint,
+ trailers jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE merge_request_context_commits_id_seq
@@ -13885,7 +13995,8 @@ CREATE TABLE merge_request_diff_commits (
author_email text,
committer_name text,
committer_email text,
- message text
+ message text,
+ trailers jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE TABLE merge_request_diff_details (
@@ -13940,6 +14051,7 @@ CREATE TABLE merge_request_diffs (
stored_externally boolean,
files_count smallint,
sorted boolean DEFAULT false NOT NULL,
+ diff_type smallint DEFAULT 1 NOT NULL,
CONSTRAINT check_93ee616ac9 CHECK ((external_diff_store IS NOT NULL))
);
@@ -13992,7 +14104,8 @@ CREATE TABLE merge_request_reviewers (
id bigint NOT NULL,
user_id bigint NOT NULL,
merge_request_id bigint NOT NULL,
- created_at timestamp with time zone NOT NULL
+ created_at timestamp with time zone NOT NULL,
+ state smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE merge_request_reviewers_id_seq
@@ -14197,22 +14310,6 @@ CREATE TABLE namespace_limits (
temporary_storage_increase_ends_on date
);
-CREATE TABLE namespace_onboarding_actions (
- id bigint NOT NULL,
- namespace_id bigint NOT NULL,
- created_at timestamp with time zone NOT NULL,
- action smallint NOT NULL
-);
-
-CREATE SEQUENCE namespace_onboarding_actions_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE namespace_onboarding_actions_id_seq OWNED BY namespace_onboarding_actions.id;
-
CREATE TABLE namespace_package_settings (
namespace_id bigint NOT NULL,
maven_duplicates_allowed boolean DEFAULT true NOT NULL,
@@ -14241,6 +14338,7 @@ CREATE TABLE namespace_settings (
prevent_forking_outside_group boolean DEFAULT false NOT NULL,
allow_mfa_for_subgroups boolean DEFAULT true NOT NULL,
default_branch_name text,
+ repository_read_only boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
);
@@ -14709,6 +14807,27 @@ CREATE SEQUENCE packages_build_infos_id_seq
ALTER SEQUENCE packages_build_infos_id_seq OWNED BY packages_build_infos.id;
+CREATE TABLE packages_composer_cache_files (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ delete_at timestamp with time zone,
+ namespace_id integer,
+ file_store smallint DEFAULT 1 NOT NULL,
+ file text NOT NULL,
+ file_sha256 bytea NOT NULL,
+ CONSTRAINT check_84f5ba81f5 CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE packages_composer_cache_files_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_composer_cache_files_id_seq OWNED BY packages_composer_cache_files.id;
+
CREATE TABLE packages_composer_metadata (
package_id bigint NOT NULL,
target_sha bytea NOT NULL,
@@ -14784,6 +14903,49 @@ CREATE SEQUENCE packages_debian_group_architectures_id_seq
ALTER SEQUENCE packages_debian_group_architectures_id_seq OWNED BY packages_debian_group_architectures.id;
+CREATE TABLE packages_debian_group_component_files (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ component_id bigint NOT NULL,
+ architecture_id bigint,
+ size integer NOT NULL,
+ file_type smallint NOT NULL,
+ compression_type smallint,
+ file_store smallint DEFAULT 1 NOT NULL,
+ file text NOT NULL,
+ file_md5 bytea NOT NULL,
+ file_sha256 bytea NOT NULL,
+ CONSTRAINT check_839e1685bc CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_component_files_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_component_files_id_seq OWNED BY packages_debian_group_component_files.id;
+
+CREATE TABLE packages_debian_group_components (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_a9bc7d85be CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_group_components_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_group_components_id_seq OWNED BY packages_debian_group_components.id;
+
CREATE TABLE packages_debian_group_distributions (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -14843,6 +15005,49 @@ CREATE SEQUENCE packages_debian_project_architectures_id_seq
ALTER SEQUENCE packages_debian_project_architectures_id_seq OWNED BY packages_debian_project_architectures.id;
+CREATE TABLE packages_debian_project_component_files (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ component_id bigint NOT NULL,
+ architecture_id bigint,
+ size integer NOT NULL,
+ file_type smallint NOT NULL,
+ compression_type smallint,
+ file_store smallint DEFAULT 1 NOT NULL,
+ file text NOT NULL,
+ file_md5 bytea NOT NULL,
+ file_sha256 bytea NOT NULL,
+ CONSTRAINT check_e5af03fa2d CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_component_files_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_component_files_id_seq OWNED BY packages_debian_project_component_files.id;
+
+CREATE TABLE packages_debian_project_components (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ distribution_id bigint NOT NULL,
+ name text NOT NULL,
+ CONSTRAINT check_517559f298 CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE packages_debian_project_components_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_project_components_id_seq OWNED BY packages_debian_project_components.id;
+
CREATE TABLE packages_debian_project_distributions (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -14884,6 +15089,21 @@ CREATE SEQUENCE packages_debian_project_distributions_id_seq
ALTER SEQUENCE packages_debian_project_distributions_id_seq OWNED BY packages_debian_project_distributions.id;
+CREATE TABLE packages_debian_publications (
+ id bigint NOT NULL,
+ package_id bigint NOT NULL,
+ distribution_id bigint NOT NULL
+);
+
+CREATE SEQUENCE packages_debian_publications_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE packages_debian_publications_id_seq OWNED BY packages_debian_publications.id;
+
CREATE TABLE packages_dependencies (
id bigint NOT NULL,
name character varying(255) NOT NULL,
@@ -15024,7 +15244,8 @@ CREATE TABLE packages_packages (
name character varying NOT NULL,
version character varying,
package_type smallint NOT NULL,
- creator_id integer
+ creator_id integer,
+ status smallint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE packages_packages_id_seq
@@ -15043,6 +15264,58 @@ CREATE TABLE packages_pypi_metadata (
CONSTRAINT check_379019d5da CHECK ((char_length(required_python) <= 255))
);
+CREATE TABLE packages_rubygems_metadata (
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ package_id bigint NOT NULL,
+ authors text,
+ files text,
+ summary text,
+ description text,
+ email text,
+ homepage text,
+ licenses text,
+ metadata text,
+ author text,
+ bindir text,
+ cert_chain text,
+ executables text,
+ extensions text,
+ extra_rdoc_files text,
+ platform text,
+ post_install_message text,
+ rdoc_options text,
+ require_paths text,
+ required_ruby_version text,
+ required_rubygems_version text,
+ requirements text,
+ rubygems_version text,
+ signing_key text,
+ CONSTRAINT check_0154a18c82 CHECK ((char_length(description) <= 1024)),
+ CONSTRAINT check_22814c771b CHECK ((char_length(email) <= 255)),
+ CONSTRAINT check_242293030e CHECK ((char_length(extensions) <= 255)),
+ CONSTRAINT check_27619a7922 CHECK ((char_length(rubygems_version) <= 255)),
+ CONSTRAINT check_3d1b6f3a39 CHECK ((char_length(post_install_message) <= 255)),
+ CONSTRAINT check_545f7606f9 CHECK ((char_length(required_rubygems_version) <= 255)),
+ CONSTRAINT check_5988451714 CHECK ((char_length(executables) <= 255)),
+ CONSTRAINT check_5f9c84ea17 CHECK ((char_length(platform) <= 255)),
+ CONSTRAINT check_64f1cecf05 CHECK ((char_length(requirements) <= 255)),
+ CONSTRAINT check_6ac7043c50 CHECK ((char_length(extra_rdoc_files) <= 255)),
+ CONSTRAINT check_6ff3abe325 CHECK ((char_length(cert_chain) <= 255)),
+ CONSTRAINT check_7cb01436df CHECK ((char_length(licenses) <= 255)),
+ CONSTRAINT check_8be21d92e7 CHECK ((char_length(summary) <= 1024)),
+ CONSTRAINT check_946cb96acb CHECK ((char_length(homepage) <= 255)),
+ CONSTRAINT check_9824fc9efc CHECK ((char_length(bindir) <= 255)),
+ CONSTRAINT check_994b68eb64 CHECK ((char_length(authors) <= 255)),
+ CONSTRAINT check_9d42fa48ae CHECK ((char_length(signing_key) <= 255)),
+ CONSTRAINT check_b0f4f8c853 CHECK ((char_length(files) <= 255)),
+ CONSTRAINT check_b7b296b420 CHECK ((char_length(author) <= 255)),
+ CONSTRAINT check_bf16b21a47 CHECK ((char_length(rdoc_options) <= 255)),
+ CONSTRAINT check_ca641a3354 CHECK ((char_length(required_ruby_version) <= 255)),
+ CONSTRAINT check_ea02f4800f CHECK ((char_length(metadata) <= 255)),
+ CONSTRAINT check_f76bad1a9a CHECK ((char_length(require_paths) <= 255))
+);
+
CREATE TABLE packages_tags (
id bigint NOT NULL,
package_id integer NOT NULL,
@@ -15255,7 +15528,8 @@ CREATE TABLE plan_limits (
ci_max_artifact_size_api_fuzzing integer DEFAULT 0 NOT NULL,
ci_pipeline_deployments integer DEFAULT 500 NOT NULL,
pull_mirror_interval_seconds integer DEFAULT 300 NOT NULL,
- daily_invites integer DEFAULT 0 NOT NULL
+ daily_invites integer DEFAULT 0 NOT NULL,
+ rubygems_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
@@ -15702,7 +15976,8 @@ CREATE TABLE project_features (
metrics_dashboard_access_level integer,
requirements_access_level integer DEFAULT 20 NOT NULL,
operations_access_level integer DEFAULT 20 NOT NULL,
- analytics_access_level integer DEFAULT 20 NOT NULL
+ analytics_access_level integer DEFAULT 20 NOT NULL,
+ security_and_compliance_access_level integer DEFAULT 10 NOT NULL
);
CREATE SEQUENCE project_features_id_seq
@@ -15903,6 +16178,7 @@ CREATE TABLE project_settings (
has_confluence boolean DEFAULT false NOT NULL,
has_vulnerabilities boolean DEFAULT false NOT NULL,
allow_editing_commit_messages boolean DEFAULT false NOT NULL,
+ prevent_merge_without_jira_issue boolean DEFAULT false NOT NULL,
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
);
@@ -16717,6 +16993,25 @@ CREATE SEQUENCE security_findings_id_seq
ALTER SEQUENCE security_findings_id_seq OWNED BY security_findings.id;
+CREATE TABLE security_orchestration_policy_configurations (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ security_policy_management_project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL
+);
+
+COMMENT ON TABLE security_orchestration_policy_configurations IS '{"owner":"group::container security","description":"Configuration used to store relationship between project and security policy repository"}';
+
+CREATE SEQUENCE security_orchestration_policy_configurations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE security_orchestration_policy_configurations_id_seq OWNED BY security_orchestration_policy_configurations.id;
+
CREATE TABLE security_scans (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -17327,6 +17622,22 @@ CREATE SEQUENCE todos_id_seq
ALTER SEQUENCE todos_id_seq OWNED BY todos.id;
+CREATE TABLE token_with_ivs (
+ id bigint NOT NULL,
+ hashed_token bytea NOT NULL,
+ hashed_plaintext_token bytea NOT NULL,
+ iv bytea NOT NULL
+);
+
+CREATE SEQUENCE token_with_ivs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE token_with_ivs_id_seq OWNED BY token_with_ivs.id;
+
CREATE TABLE trending_projects (
id integer NOT NULL,
project_id integer NOT NULL
@@ -17479,6 +17790,11 @@ CREATE SEQUENCE user_details_user_id_seq
ALTER SEQUENCE user_details_user_id_seq OWNED BY user_details.user_id;
+CREATE TABLE user_follow_users (
+ follower_id integer NOT NULL,
+ followee_id integer NOT NULL
+);
+
CREATE TABLE user_highest_roles (
user_id bigint NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -17553,7 +17869,8 @@ CREATE TABLE user_statuses (
emoji character varying DEFAULT 'speech_balloon'::character varying NOT NULL,
message character varying(100),
message_html character varying,
- availability smallint DEFAULT 0 NOT NULL
+ availability smallint DEFAULT 0 NOT NULL,
+ clear_status_at timestamp with time zone
);
CREATE SEQUENCE user_statuses_user_id_seq
@@ -17858,6 +18175,24 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
+CREATE TABLE vulnerability_finding_fingerprints (
+ id bigint NOT NULL,
+ finding_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ algorithm_type integer NOT NULL,
+ fingerprint_sha256 bytea NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_finding_fingerprints_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_fingerprints_id_seq OWNED BY vulnerability_finding_fingerprints.id;
+
CREATE TABLE vulnerability_finding_links (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -18010,7 +18345,16 @@ CREATE TABLE vulnerability_occurrences (
metadata_version character varying NOT NULL,
raw_metadata text NOT NULL,
vulnerability_id bigint,
- details jsonb DEFAULT '{}'::jsonb NOT NULL
+ details jsonb DEFAULT '{}'::jsonb NOT NULL,
+ description text,
+ message text,
+ solution text,
+ cve text,
+ location jsonb,
+ CONSTRAINT check_4a3a60f2ba CHECK ((char_length(solution) <= 7000)),
+ CONSTRAINT check_ade261da6b CHECK ((char_length(description) <= 15000)),
+ CONSTRAINT check_df6dd20219 CHECK ((char_length(message) <= 3000)),
+ CONSTRAINT check_f602da68dd CHECK ((char_length(cve) <= 48400))
);
CREATE SEQUENCE vulnerability_occurrences_id_seq
@@ -18160,7 +18504,8 @@ CREATE TABLE web_hooks (
deployment_events boolean DEFAULT false NOT NULL,
releases_events boolean DEFAULT false NOT NULL,
feature_flag_events boolean DEFAULT false NOT NULL,
- member_events boolean DEFAULT false NOT NULL
+ member_events boolean DEFAULT false NOT NULL,
+ subgroup_events boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE web_hooks_id_seq
@@ -18317,8 +18662,6 @@ ALTER TABLE ONLY alert_management_alerts ALTER COLUMN id SET DEFAULT nextval('al
ALTER TABLE ONLY alert_management_http_integrations ALTER COLUMN id SET DEFAULT nextval('alert_management_http_integrations_id_seq'::regclass);
-ALTER TABLE ONLY alerts_service_data ALTER COLUMN id SET DEFAULT nextval('alerts_service_data_id_seq'::regclass);
-
ALTER TABLE ONLY allowed_email_domains ALTER COLUMN id SET DEFAULT nextval('allowed_email_domains_id_seq'::regclass);
ALTER TABLE ONLY analytics_cycle_analytics_group_stages ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_group_stages_id_seq'::regclass);
@@ -18443,6 +18786,8 @@ ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_ar
ALTER TABLE ONLY ci_job_variables ALTER COLUMN id SET DEFAULT nextval('ci_job_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_namespace_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_namespace_monthly_usages_id_seq'::regclass);
+
ALTER TABLE ONLY ci_pipeline_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_artifacts_id_seq'::regclass);
ALTER TABLE ONLY ci_pipeline_chat_data ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_chat_data_id_seq'::regclass);
@@ -18461,6 +18806,8 @@ ALTER TABLE ONLY ci_pipelines_config ALTER COLUMN pipeline_id SET DEFAULT nextva
ALTER TABLE ONLY ci_platform_metrics ALTER COLUMN id SET DEFAULT nextval('ci_platform_metrics_id_seq'::regclass);
+ALTER TABLE ONLY ci_project_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_project_monthly_usages_id_seq'::regclass);
+
ALTER TABLE ONLY ci_refs ALTER COLUMN id SET DEFAULT nextval('ci_refs_id_seq'::regclass);
ALTER TABLE ONLY ci_resource_groups ALTER COLUMN id SET DEFAULT nextval('ci_resource_groups_id_seq'::regclass);
@@ -18543,6 +18890,8 @@ ALTER TABLE ONLY csv_issue_imports ALTER COLUMN id SET DEFAULT nextval('csv_issu
ALTER TABLE ONLY custom_emoji ALTER COLUMN id SET DEFAULT nextval('custom_emoji_id_seq'::regclass);
+ALTER TABLE ONLY dast_profiles ALTER COLUMN id SET DEFAULT nextval('dast_profiles_id_seq'::regclass);
+
ALTER TABLE ONLY dast_scanner_profiles ALTER COLUMN id SET DEFAULT nextval('dast_scanner_profiles_id_seq'::regclass);
ALTER TABLE ONLY dast_site_profiles ALTER COLUMN id SET DEFAULT nextval('dast_site_profiles_id_seq'::regclass);
@@ -18675,6 +19024,8 @@ ALTER TABLE ONLY group_group_links ALTER COLUMN id SET DEFAULT nextval('group_gr
ALTER TABLE ONLY group_import_states ALTER COLUMN group_id SET DEFAULT nextval('group_import_states_group_id_seq'::regclass);
+ALTER TABLE ONLY group_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('group_repository_storage_moves_id_seq'::regclass);
+
ALTER TABLE ONLY historical_data ALTER COLUMN id SET DEFAULT nextval('historical_data_id_seq'::regclass);
ALTER TABLE ONLY identities ALTER COLUMN id SET DEFAULT nextval('identities_id_seq'::regclass);
@@ -18779,8 +19130,6 @@ ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT ne
ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
-ALTER TABLE ONLY namespace_onboarding_actions ALTER COLUMN id SET DEFAULT nextval('namespace_onboarding_actions_id_seq'::regclass);
-
ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('namespace_statistics_id_seq'::regclass);
ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
@@ -18821,18 +19170,30 @@ ALTER TABLE ONLY operations_user_lists ALTER COLUMN id SET DEFAULT nextval('oper
ALTER TABLE ONLY packages_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_build_infos_id_seq'::regclass);
+ALTER TABLE ONLY packages_composer_cache_files ALTER COLUMN id SET DEFAULT nextval('packages_composer_cache_files_id_seq'::regclass);
+
ALTER TABLE ONLY packages_conan_file_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_file_metadata_id_seq'::regclass);
ALTER TABLE ONLY packages_conan_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_metadata_id_seq'::regclass);
ALTER TABLE ONLY packages_debian_group_architectures ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_architectures_id_seq'::regclass);
+ALTER TABLE ONLY packages_debian_group_component_files ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_component_files_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_group_components ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_components_id_seq'::regclass);
+
ALTER TABLE ONLY packages_debian_group_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_group_distributions_id_seq'::regclass);
ALTER TABLE ONLY packages_debian_project_architectures ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_architectures_id_seq'::regclass);
+ALTER TABLE ONLY packages_debian_project_component_files ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_component_files_id_seq'::regclass);
+
+ALTER TABLE ONLY packages_debian_project_components ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_components_id_seq'::regclass);
+
ALTER TABLE ONLY packages_debian_project_distributions ALTER COLUMN id SET DEFAULT nextval('packages_debian_project_distributions_id_seq'::regclass);
+ALTER TABLE ONLY packages_debian_publications ALTER COLUMN id SET DEFAULT nextval('packages_debian_publications_id_seq'::regclass);
+
ALTER TABLE ONLY packages_dependencies ALTER COLUMN id SET DEFAULT nextval('packages_dependencies_id_seq'::regclass);
ALTER TABLE ONLY packages_dependency_links ALTER COLUMN id SET DEFAULT nextval('packages_dependency_links_id_seq'::regclass);
@@ -18977,6 +19338,8 @@ ALTER TABLE ONLY scim_oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('s
ALTER TABLE ONLY security_findings ALTER COLUMN id SET DEFAULT nextval('security_findings_id_seq'::regclass);
+ALTER TABLE ONLY security_orchestration_policy_configurations ALTER COLUMN id SET DEFAULT nextval('security_orchestration_policy_configurations_id_seq'::regclass);
+
ALTER TABLE ONLY security_scans ALTER COLUMN id SET DEFAULT nextval('security_scans_id_seq'::regclass);
ALTER TABLE ONLY self_managed_prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('self_managed_prometheus_alert_events_id_seq'::regclass);
@@ -19031,6 +19394,8 @@ ALTER TABLE ONLY timelogs ALTER COLUMN id SET DEFAULT nextval('timelogs_id_seq':
ALTER TABLE ONLY todos ALTER COLUMN id SET DEFAULT nextval('todos_id_seq'::regclass);
+ALTER TABLE ONLY token_with_ivs ALTER COLUMN id SET DEFAULT nextval('token_with_ivs_id_seq'::regclass);
+
ALTER TABLE ONLY trending_projects ALTER COLUMN id SET DEFAULT nextval('trending_projects_id_seq'::regclass);
ALTER TABLE ONLY u2f_registrations ALTER COLUMN id SET DEFAULT nextval('u2f_registrations_id_seq'::regclass);
@@ -19071,6 +19436,8 @@ ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_finding_fingerprints ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_fingerprints_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_finding_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_links_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_findings_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_findings_remediations_id_seq'::regclass);
@@ -19323,9 +19690,6 @@ ALTER TABLE ONLY alert_management_alerts
ALTER TABLE ONLY alert_management_http_integrations
ADD CONSTRAINT alert_management_http_integrations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY alerts_service_data
- ADD CONSTRAINT alerts_service_data_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY allowed_email_domains
ADD CONSTRAINT allowed_email_domains_pkey PRIMARY KEY (id);
@@ -19539,6 +19903,9 @@ ALTER TABLE ONLY ci_job_artifacts
ALTER TABLE ONLY ci_job_variables
ADD CONSTRAINT ci_job_variables_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_namespace_monthly_usages
+ ADD CONSTRAINT ci_namespace_monthly_usages_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_pipeline_artifacts
ADD CONSTRAINT ci_pipeline_artifacts_pkey PRIMARY KEY (id);
@@ -19566,6 +19933,9 @@ ALTER TABLE ONLY ci_pipelines
ALTER TABLE ONLY ci_platform_metrics
ADD CONSTRAINT ci_platform_metrics_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_project_monthly_usages
+ ADD CONSTRAINT ci_project_monthly_usages_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_refs
ADD CONSTRAINT ci_refs_pkey PRIMARY KEY (id);
@@ -19692,6 +20062,9 @@ ALTER TABLE ONLY csv_issue_imports
ALTER TABLE ONLY custom_emoji
ADD CONSTRAINT custom_emoji_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY dast_profiles
+ ADD CONSTRAINT dast_profiles_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY dast_scanner_profiles
ADD CONSTRAINT dast_scanner_profiles_pkey PRIMARY KEY (id);
@@ -19908,6 +20281,9 @@ ALTER TABLE ONLY group_import_states
ALTER TABLE ONLY group_merge_request_approval_settings
ADD CONSTRAINT group_merge_request_approval_settings_pkey PRIMARY KEY (group_id);
+ALTER TABLE ONLY group_repository_storage_moves
+ ADD CONSTRAINT group_repository_storage_moves_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY group_wiki_repositories
ADD CONSTRAINT group_wiki_repositories_pkey PRIMARY KEY (group_id);
@@ -20103,9 +20479,6 @@ ALTER TABLE ONLY namespace_aggregation_schedules
ALTER TABLE ONLY namespace_limits
ADD CONSTRAINT namespace_limits_pkey PRIMARY KEY (namespace_id);
-ALTER TABLE ONLY namespace_onboarding_actions
- ADD CONSTRAINT namespace_onboarding_actions_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY namespace_package_settings
ADD CONSTRAINT namespace_package_settings_pkey PRIMARY KEY (namespace_id);
@@ -20175,6 +20548,9 @@ ALTER TABLE ONLY operations_user_lists
ALTER TABLE ONLY packages_build_infos
ADD CONSTRAINT packages_build_infos_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_composer_cache_files
+ ADD CONSTRAINT packages_composer_cache_files_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_composer_metadata
ADD CONSTRAINT packages_composer_metadata_pkey PRIMARY KEY (package_id);
@@ -20190,15 +20566,30 @@ ALTER TABLE ONLY packages_debian_file_metadata
ALTER TABLE ONLY packages_debian_group_architectures
ADD CONSTRAINT packages_debian_group_architectures_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_group_component_files
+ ADD CONSTRAINT packages_debian_group_component_files_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_group_components
+ ADD CONSTRAINT packages_debian_group_components_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_debian_group_distributions
ADD CONSTRAINT packages_debian_group_distributions_pkey PRIMARY KEY (id);
ALTER TABLE ONLY packages_debian_project_architectures
ADD CONSTRAINT packages_debian_project_architectures_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_project_component_files
+ ADD CONSTRAINT packages_debian_project_component_files_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY packages_debian_project_components
+ ADD CONSTRAINT packages_debian_project_components_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_debian_project_distributions
ADD CONSTRAINT packages_debian_project_distributions_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY packages_debian_publications
+ ADD CONSTRAINT packages_debian_publications_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY packages_dependencies
ADD CONSTRAINT packages_dependencies_pkey PRIMARY KEY (id);
@@ -20229,6 +20620,9 @@ ALTER TABLE ONLY packages_packages
ALTER TABLE ONLY packages_pypi_metadata
ADD CONSTRAINT packages_pypi_metadata_pkey PRIMARY KEY (package_id);
+ALTER TABLE ONLY packages_rubygems_metadata
+ ADD CONSTRAINT packages_rubygems_metadata_pkey PRIMARY KEY (package_id);
+
ALTER TABLE ONLY packages_tags
ADD CONSTRAINT packages_tags_pkey PRIMARY KEY (id);
@@ -20454,6 +20848,9 @@ ALTER TABLE ONLY scim_oauth_access_tokens
ALTER TABLE ONLY security_findings
ADD CONSTRAINT security_findings_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY security_orchestration_policy_configurations
+ ADD CONSTRAINT security_orchestration_policy_configurations_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY security_scans
ADD CONSTRAINT security_scans_pkey PRIMARY KEY (id);
@@ -20547,6 +20944,9 @@ ALTER TABLE ONLY timelogs
ALTER TABLE ONLY todos
ADD CONSTRAINT todos_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY token_with_ivs
+ ADD CONSTRAINT token_with_ivs_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY trending_projects
ADD CONSTRAINT trending_projects_pkey PRIMARY KEY (id);
@@ -20571,6 +20971,9 @@ ALTER TABLE ONLY user_custom_attributes
ALTER TABLE ONLY user_details
ADD CONSTRAINT user_details_pkey PRIMARY KEY (user_id);
+ALTER TABLE ONLY user_follow_users
+ ADD CONSTRAINT user_follow_users_pkey PRIMARY KEY (follower_id, followee_id);
+
ALTER TABLE ONLY user_highest_roles
ADD CONSTRAINT user_highest_roles_pkey PRIMARY KEY (user_id);
@@ -20616,6 +21019,9 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_fingerprints
+ ADD CONSTRAINT vulnerability_finding_fingerprints_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_finding_links
ADD CONSTRAINT vulnerability_finding_links_pkey PRIMARY KEY (id);
@@ -20831,8 +21237,6 @@ CREATE INDEX backup_labels_group_id_title_idx ON backup_labels USING btree (grou
CREATE INDEX backup_labels_project_id_idx ON backup_labels USING btree (project_id);
-CREATE UNIQUE INDEX backup_labels_project_id_title_idx ON backup_labels USING btree (project_id, title) WHERE (group_id = NULL::integer);
-
CREATE INDEX backup_labels_template_idx ON backup_labels USING btree (template) WHERE template;
CREATE INDEX backup_labels_title_idx ON backup_labels USING btree (title);
@@ -20847,6 +21251,8 @@ CREATE INDEX code_owner_approval_required ON protected_branches USING btree (pro
CREATE INDEX commit_id_and_note_id_index ON commit_user_mentions USING btree (commit_id, note_id);
+CREATE INDEX composer_cache_files_index_on_deleted_at ON packages_composer_cache_files USING btree (delete_at, id);
+
CREATE UNIQUE INDEX design_management_designs_versions_uniqueness ON design_management_designs_versions USING btree (design_id, version_id);
CREATE INDEX design_user_mentions_on_design_id_and_note_id_index ON design_user_mentions USING btree (design_id, note_id);
@@ -20855,7 +21261,7 @@ CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_and_note_id_index ON epic_user
CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_index ON epic_user_mentions USING btree (epic_id) WHERE (note_id IS NULL);
-CREATE INDEX expired_artifacts_temp_index ON ci_job_artifacts USING btree (id, created_at) WHERE ((expire_at IS NULL) AND (created_at < '2020-06-22 00:00:00+00'::timestamp with time zone));
+CREATE INDEX expired_artifacts_temp_index ON ci_job_artifacts USING btree (id, created_at) WHERE ((expire_at IS NULL) AND (date(timezone('UTC'::text, created_at)) < '2020-06-22'::date));
CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
@@ -20911,8 +21317,14 @@ CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_c
CREATE UNIQUE INDEX idx_on_compliance_management_frameworks_namespace_id_name ON compliance_management_frameworks USING btree (namespace_id, name);
+CREATE INDEX idx_on_issues_where_service_desk_reply_to_is_not_null ON issues USING btree (id) WHERE (service_desk_reply_to IS NOT NULL);
+
CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
+CREATE INDEX idx_packages_debian_group_component_files_on_architecture_id ON packages_debian_group_component_files USING btree (architecture_id);
+
+CREATE INDEX idx_packages_debian_project_component_files_on_architecture_id ON packages_debian_project_component_files USING btree (architecture_id);
+
CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type);
CREATE INDEX idx_pkgs_deb_grp_architectures_on_distribution_id ON packages_debian_group_architectures USING btree (distribution_id);
@@ -20951,6 +21363,10 @@ 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 UNIQUE INDEX idx_vuln_fingerprints_on_occurrences_id_and_fingerprint ON vulnerability_finding_fingerprints USING btree (finding_id, fingerprint_sha256);
+
+CREATE UNIQUE INDEX idx_vuln_fingerprints_uniqueness ON vulnerability_finding_fingerprints USING btree (finding_id, algorithm_type, fingerprint_sha256);
+
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue ON vulnerability_external_issue_links USING btree (vulnerability_id, external_type, external_project_key, external_issue_key);
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_link_type ON vulnerability_external_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 1);
@@ -20983,8 +21399,6 @@ CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id_and_note_id ON alert_m
CREATE UNIQUE INDEX index_alert_user_mentions_on_note_id ON alert_management_alert_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE INDEX index_alerts_service_data_on_service_id ON alerts_service_data USING btree (service_id);
-
CREATE INDEX index_allowed_email_domains_on_group_id ON allowed_email_domains USING btree (group_id);
CREATE INDEX index_analytics_ca_group_stages_on_end_event_label_id ON analytics_cycle_analytics_group_stages USING btree (end_event_label_id);
@@ -21011,7 +21425,7 @@ CREATE INDEX index_analytics_ca_project_stages_on_start_event_label_id ON analyt
CREATE INDEX index_analytics_cycle_analytics_group_stages_custom_only ON analytics_cycle_analytics_group_stages USING btree (id) WHERE (custom = true);
-CREATE UNIQUE INDEX index_analytics_devops_adoption_segments_on_name ON analytics_devops_adoption_segments USING btree (name);
+CREATE UNIQUE INDEX index_analytics_devops_adoption_segments_on_namespace_id ON analytics_devops_adoption_segments USING btree (namespace_id);
CREATE INDEX index_application_settings_on_custom_project_templates_group_id ON application_settings USING btree (custom_project_templates_group_id);
@@ -21211,7 +21625,7 @@ CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id ON ci_builds_metadata U
CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
-CREATE INDEX index_ci_builds_metadata_on_build_id_and_interruptible ON ci_builds_metadata USING btree (build_id) WHERE (interruptible = true);
+CREATE INDEX index_ci_builds_metadata_on_build_id_and_id_and_interruptible ON ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true);
CREATE INDEX index_ci_builds_metadata_on_project_id ON ci_builds_metadata USING btree (project_id);
@@ -21261,6 +21675,8 @@ CREATE INDEX index_ci_builds_project_id_and_status_for_live_jobs_partial2 ON ci_
CREATE UNIQUE INDEX index_ci_builds_runner_session_on_build_id ON ci_builds_runner_session USING btree (build_id);
+CREATE INDEX index_ci_daily_build_group_report_results_on_group_id ON ci_daily_build_group_report_results USING btree (group_id);
+
CREATE INDEX index_ci_daily_build_group_report_results_on_last_pipeline_id ON ci_daily_build_group_report_results USING btree (last_pipeline_id);
CREATE INDEX index_ci_daily_build_group_report_results_on_project_and_date ON ci_daily_build_group_report_results USING btree (project_id, date DESC) WHERE ((default_branch = true) AND ((data -> 'coverage'::text) IS NOT NULL));
@@ -21291,6 +21707,8 @@ CREATE INDEX index_ci_job_variables_on_job_id ON ci_job_variables USING btree (j
CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables USING btree (key, job_id);
+CREATE UNIQUE INDEX index_ci_namespace_monthly_usages_on_namespace_id_and_date ON ci_namespace_monthly_usages USING btree (namespace_id, date);
+
CREATE INDEX index_ci_pipeline_artifacts_on_expire_at ON ci_pipeline_artifacts USING btree (expire_at);
CREATE INDEX index_ci_pipeline_artifacts_on_pipeline_id ON ci_pipeline_artifacts USING btree (pipeline_id);
@@ -21355,6 +21773,8 @@ CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_config_source ON c
CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_source ON ci_pipelines USING btree (user_id, created_at, source);
+CREATE UNIQUE INDEX index_ci_project_monthly_usages_on_project_id_and_date ON ci_project_monthly_usages USING btree (project_id, date);
+
CREATE UNIQUE INDEX index_ci_refs_on_project_id_and_ref_path ON ci_refs USING btree (project_id, ref_path);
CREATE UNIQUE INDEX index_ci_resource_groups_on_project_id_and_key ON ci_resource_groups USING btree (project_id, key);
@@ -21427,8 +21847,12 @@ CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_sco
CREATE INDEX index_cluster_agent_tokens_on_agent_id ON cluster_agent_tokens USING btree (agent_id);
+CREATE INDEX index_cluster_agent_tokens_on_created_by_user_id ON cluster_agent_tokens USING btree (created_by_user_id);
+
CREATE UNIQUE INDEX index_cluster_agent_tokens_on_token_encrypted ON cluster_agent_tokens USING btree (token_encrypted);
+CREATE INDEX index_cluster_agents_on_created_by_user_id ON cluster_agents USING btree (created_by_user_id);
+
CREATE UNIQUE INDEX index_cluster_agents_on_project_id_and_name ON cluster_agents USING btree (project_id, name);
CREATE UNIQUE INDEX index_cluster_groups_on_cluster_id_and_group_id ON cluster_groups USING btree (cluster_id, group_id);
@@ -21495,6 +21919,8 @@ CREATE INDEX index_clusters_on_user_id ON clusters USING btree (user_id);
CREATE UNIQUE INDEX index_commit_user_mentions_on_note_id ON commit_user_mentions USING btree (note_id);
+CREATE INDEX index_composer_cache_files_where_namespace_id_is_null ON packages_composer_cache_files USING btree (id) WHERE (namespace_id IS NULL);
+
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_project_id ON container_repositories USING btree (project_id);
@@ -21515,6 +21941,12 @@ CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON custom_emoji
CREATE UNIQUE INDEX index_daily_build_group_report_results_unique_columns ON ci_daily_build_group_report_results USING btree (project_id, ref_path, date, group_name);
+CREATE INDEX index_dast_profiles_on_dast_scanner_profile_id ON dast_profiles USING btree (dast_scanner_profile_id);
+
+CREATE INDEX index_dast_profiles_on_dast_site_profile_id ON dast_profiles USING btree (dast_site_profile_id);
+
+CREATE UNIQUE INDEX index_dast_profiles_on_project_id_and_name ON dast_profiles USING btree (project_id, name);
+
CREATE UNIQUE INDEX index_dast_scanner_profiles_on_project_id_and_name ON dast_scanner_profiles USING btree (project_id, name);
CREATE INDEX index_dast_site_profiles_on_dast_site_id ON dast_site_profiles USING btree (dast_site_id);
@@ -21883,6 +22315,8 @@ CREATE INDEX index_group_import_states_on_group_id ON group_import_states USING
CREATE INDEX index_group_import_states_on_user_id ON group_import_states USING btree (user_id) WHERE (user_id IS NOT NULL);
+CREATE INDEX index_group_repository_storage_moves_on_group_id ON group_repository_storage_moves USING btree (group_id);
+
CREATE UNIQUE INDEX index_group_stages_on_group_id_group_value_stream_id_and_name ON analytics_cycle_analytics_group_stages USING btree (group_id, group_value_stream_id, name);
CREATE UNIQUE INDEX index_group_wiki_repositories_on_disk_path ON group_wiki_repositories USING btree (disk_path);
@@ -21927,8 +22361,6 @@ CREATE INDEX index_incident_management_oncall_schedules_on_project_id ON inciden
CREATE INDEX index_incident_management_oncall_shifts_on_participant_id ON incident_management_oncall_shifts USING btree (participant_id);
-CREATE INDEX index_incident_management_oncall_shifts_on_rotation_id ON incident_management_oncall_shifts USING btree (rotation_id);
-
CREATE UNIQUE INDEX index_index_statuses_on_project_id ON index_statuses USING btree (project_id);
CREATE INDEX index_insights_on_namespace_id ON insights USING btree (namespace_id);
@@ -22123,6 +22555,8 @@ CREATE INDEX index_merge_request_diffs_on_external_diff_store ON merge_request_d
CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id ON merge_request_diffs USING btree (merge_request_id, id);
+CREATE UNIQUE INDEX index_merge_request_diffs_on_unique_merge_request_id ON merge_request_diffs USING btree (merge_request_id) WHERE (diff_type = 2);
+
CREATE INDEX index_merge_request_metrics_on_first_deployed_to_production_at ON merge_request_metrics USING btree (first_deployed_to_production_at);
CREATE INDEX index_merge_request_metrics_on_latest_closed_at ON merge_request_metrics USING btree (latest_closed_at) WHERE (latest_closed_at IS NOT NULL);
@@ -22237,8 +22671,6 @@ CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_time_to_merge ON me
CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON namespace_aggregation_schedules USING btree (namespace_id);
-CREATE INDEX index_namespace_onboarding_actions_on_namespace_id ON namespace_onboarding_actions USING btree (namespace_id);
-
CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON namespace_root_storage_statistics USING btree (namespace_id);
CREATE UNIQUE INDEX index_namespace_statistics_on_namespace_id ON namespace_statistics USING btree (namespace_id);
@@ -22335,6 +22767,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_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';
+
CREATE INDEX index_on_namespaces_lower_name ON namespaces USING btree (lower((name)::text));
CREATE INDEX index_on_namespaces_lower_path ON namespaces USING btree (lower((path)::text));
@@ -22359,8 +22795,18 @@ CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username
CREATE INDEX index_on_users_name_lower ON users USING btree (lower((name)::text));
+CREATE INDEX index_onboarding_progresses_for_create_track ON onboarding_progresses USING btree (created_at) WHERE (git_write_at IS NULL);
+
+CREATE INDEX index_onboarding_progresses_for_team_track ON onboarding_progresses USING btree (GREATEST(git_write_at, pipeline_created_at, trial_started_at)) WHERE ((git_write_at IS NOT NULL) AND (pipeline_created_at IS NOT NULL) AND (trial_started_at IS NOT NULL) AND (user_added_at IS NULL));
+
+CREATE INDEX index_onboarding_progresses_for_trial_track ON onboarding_progresses USING btree (GREATEST(git_write_at, pipeline_created_at)) WHERE ((git_write_at IS NOT NULL) AND (pipeline_created_at IS NOT NULL) AND (trial_started_at IS NULL));
+
+CREATE INDEX index_onboarding_progresses_for_verify_track ON onboarding_progresses USING btree (git_write_at) WHERE ((git_write_at IS NOT NULL) AND (pipeline_created_at IS NULL));
+
CREATE UNIQUE INDEX index_onboarding_progresses_on_namespace_id ON onboarding_progresses USING btree (namespace_id);
+CREATE INDEX index_oncall_shifts_on_rotation_id_and_starts_at_and_ends_at ON incident_management_oncall_shifts USING btree (rotation_id, starts_at, ends_at);
+
CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id);
CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON operations_feature_flags_issues USING btree (issue_id);
@@ -22385,20 +22831,30 @@ CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list
CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_packages_composer_cache_namespace_and_sha ON packages_composer_cache_files USING btree (namespace_id, file_sha256);
+
CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha);
CREATE UNIQUE INDEX index_packages_conan_file_metadata_on_package_file_id ON packages_conan_file_metadata USING btree (package_file_id);
CREATE UNIQUE INDEX index_packages_conan_metadata_on_package_id_username_channel ON packages_conan_metadata USING btree (package_id, package_username, package_channel);
+CREATE INDEX index_packages_debian_group_component_files_on_component_id ON packages_debian_group_component_files USING btree (component_id);
+
CREATE INDEX index_packages_debian_group_distributions_on_creator_id ON packages_debian_group_distributions USING btree (creator_id);
CREATE INDEX index_packages_debian_group_distributions_on_group_id ON packages_debian_group_distributions USING btree (group_id);
+CREATE INDEX index_packages_debian_project_component_files_on_component_id ON packages_debian_project_component_files USING btree (component_id);
+
CREATE INDEX index_packages_debian_project_distributions_on_creator_id ON packages_debian_project_distributions USING btree (creator_id);
CREATE INDEX index_packages_debian_project_distributions_on_project_id ON packages_debian_project_distributions USING btree (project_id);
+CREATE INDEX index_packages_debian_publications_on_distribution_id ON packages_debian_publications USING btree (distribution_id);
+
+CREATE UNIQUE INDEX index_packages_debian_publications_on_package_id ON packages_debian_publications USING btree (package_id);
+
CREATE UNIQUE INDEX index_packages_dependencies_on_name_and_version_pattern ON packages_dependencies USING btree (name, version_pattern);
CREATE INDEX index_packages_dependency_links_on_dependency_id ON packages_dependency_links USING btree (dependency_id);
@@ -22431,6 +22887,8 @@ CREATE INDEX index_packages_packages_on_project_id_and_created_at ON packages_pa
CREATE INDEX index_packages_packages_on_project_id_and_package_type ON packages_packages USING btree (project_id, package_type);
+CREATE INDEX index_packages_packages_on_project_id_and_status ON packages_packages USING btree (project_id, status);
+
CREATE INDEX index_packages_packages_on_project_id_and_version ON packages_packages USING btree (project_id, version);
CREATE INDEX index_packages_project_id_name_partial_for_nuget ON packages_packages USING btree (project_id, name) WHERE (((name)::text <> 'NuGet.Temporary.Package'::text) AND (version IS NOT NULL) AND (package_type = 4));
@@ -22885,6 +23343,8 @@ CREATE INDEX index_security_findings_on_severity ON security_findings USING btre
CREATE UNIQUE INDEX index_security_findings_on_uuid_and_scan_id ON security_findings USING btree (uuid, scan_id);
+CREATE INDEX index_security_scans_on_date_created_at_and_id ON security_scans USING btree (date(timezone('UTC'::text, created_at)), id);
+
CREATE INDEX index_self_managed_prometheus_alert_events_on_environment_id ON self_managed_prometheus_alert_events USING btree (environment_id);
CREATE INDEX index_sent_notifications_on_noteable_type_noteable_id ON sent_notifications USING btree (noteable_id) WHERE ((noteable_type)::text = 'Issue'::text);
@@ -22903,7 +23363,7 @@ CREATE INDEX index_service_desk_enabled_projects_on_id_creator_id_created_at ON
CREATE INDEX index_services_on_inherit_from_id ON services USING btree (inherit_from_id);
-CREATE INDEX index_services_on_project_id_and_type ON services USING btree (project_id, type);
+CREATE UNIQUE INDEX index_services_on_project_id_and_type_unique ON services USING btree (project_id, type);
CREATE INDEX index_services_on_template ON services USING btree (template);
@@ -22967,6 +23427,10 @@ CREATE INDEX index_software_licenses_on_spdx_identifier ON software_licenses USI
CREATE UNIQUE INDEX index_software_licenses_on_unique_name ON software_licenses USING btree (name);
+CREATE UNIQUE INDEX index_sop_configs_on_project_id ON security_orchestration_policy_configurations USING btree (project_id);
+
+CREATE UNIQUE INDEX index_sop_configs_on_security_policy_management_project_id ON security_orchestration_policy_configurations USING btree (security_policy_management_project_id);
+
CREATE INDEX index_sprints_on_description_trigram ON sprints USING gin (description gin_trgm_ops);
CREATE INDEX index_sprints_on_due_date ON sprints USING btree (due_date);
@@ -23059,6 +23523,10 @@ CREATE INDEX index_todos_on_user_id_and_id_done ON todos USING btree (user_id, i
CREATE INDEX index_todos_on_user_id_and_id_pending ON todos USING btree (user_id, id) WHERE ((state)::text = 'pending'::text);
+CREATE UNIQUE INDEX index_token_with_ivs_on_hashed_plaintext_token ON token_with_ivs USING btree (hashed_plaintext_token);
+
+CREATE UNIQUE INDEX index_token_with_ivs_on_hashed_token ON token_with_ivs USING btree (hashed_token);
+
CREATE UNIQUE INDEX index_trending_projects_on_project_id ON trending_projects USING btree (project_id);
CREATE INDEX index_u2f_registrations_on_key_handle ON u2f_registrations USING btree (key_handle);
@@ -23103,6 +23571,8 @@ CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING
CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
+CREATE INDEX index_user_statuses_on_clear_status_at_not_null ON user_statuses USING btree (clear_status_at) WHERE (clear_status_at IS NOT NULL);
+
CREATE INDEX index_user_statuses_on_user_id ON user_statuses USING btree (user_id);
CREATE UNIQUE INDEX index_user_synced_attributes_metadata_on_user_id ON user_synced_attributes_metadata USING btree (user_id);
@@ -23215,6 +23685,8 @@ CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON vulnerability_f
CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON vulnerability_feedback USING btree (pipeline_id);
+CREATE INDEX index_vulnerability_finding_fingerprints_on_finding_id ON vulnerability_finding_fingerprints USING btree (finding_id);
+
CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vulnerability_findings_remediations USING btree (vulnerability_remediation_id);
CREATE UNIQUE INDEX index_vulnerability_findings_remediations_on_unique_keys ON vulnerability_findings_remediations USING btree (vulnerability_occurrence_id, vulnerability_remediation_id);
@@ -23349,14 +23821,20 @@ CREATE INDEX temporary_index_vulnerabilities_on_id ON vulnerabilities USING btre
CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
-CREATE INDEX tmp_index_oauth_applications_on_id_where_trusted ON oauth_applications USING btree (id) WHERE (trusted = true);
+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_index_on_security_findings_scan_id ON security_findings USING btree (scan_id) WHERE (uuid IS NULL);
CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING btree (id) WHERE (state <> 2);
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name);
+CREATE UNIQUE INDEX uniq_pkgs_deb_grp_components_on_distribution_id_and_name ON packages_debian_group_components USING btree (distribution_id, name);
+
CREATE UNIQUE INDEX uniq_pkgs_deb_proj_architectures_on_distribution_id_and_name ON packages_debian_project_architectures USING btree (distribution_id, name);
+CREATE UNIQUE INDEX uniq_pkgs_deb_proj_components_on_distribution_id_and_name ON packages_debian_project_components USING btree (distribution_id, name);
+
CREATE UNIQUE INDEX uniq_pkgs_debian_group_distributions_group_id_and_codename ON packages_debian_group_distributions USING btree (group_id, codename);
CREATE UNIQUE INDEX uniq_pkgs_debian_group_distributions_group_id_and_suite ON packages_debian_group_distributions USING btree (group_id, suite);
@@ -23367,6 +23845,8 @@ CREATE UNIQUE INDEX uniq_pkgs_debian_project_distributions_project_id_and_suite
CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
+CREATE INDEX user_follow_users_followee_id_idx ON user_follow_users USING btree (followee_id);
+
CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
@@ -23629,6 +24109,12 @@ ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_p
CREATE TRIGGER table_sync_trigger_ee39a25f9d AFTER INSERT OR DELETE OR UPDATE ON audit_events FOR EACH ROW EXECUTE PROCEDURE table_sync_function_2be879775d();
+CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON services FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_issue_tracker();
+
+CREATE TRIGGER trigger_has_external_issue_tracker_on_insert AFTER INSERT ON services FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (new.active = true) AND (new.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_issue_tracker();
+
+CREATE TRIGGER trigger_has_external_issue_tracker_on_update AFTER UPDATE ON services FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (old.active <> new.active) AND (new.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_issue_tracker();
+
CREATE TRIGGER trigger_has_external_wiki_on_delete AFTER DELETE ON services FOR EACH ROW WHEN ((((old.type)::text = 'ExternalWikiService'::text) AND (old.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_wiki();
CREATE TRIGGER trigger_has_external_wiki_on_insert AFTER INSERT ON services FOR EACH ROW WHEN (((new.active = true) AND ((new.type)::text = 'ExternalWikiService'::text) AND (new.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_wiki();
@@ -23893,6 +24379,9 @@ ALTER TABLE ONLY vulnerabilities
ALTER TABLE ONLY index_statuses
ADD CONSTRAINT fk_74b2492545 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_agent_tokens
+ ADD CONSTRAINT fk_75008f3553 FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT fk_76bc5f5455 FOREIGN KEY (resolved_by_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -24058,6 +24547,9 @@ ALTER TABLE ONLY merge_requests
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_aa5798e761 FOREIGN KEY (closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY dast_profiles
+ ADD CONSTRAINT fk_aa76ef30e9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY alert_management_alerts
ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
@@ -24289,6 +24781,12 @@ ALTER TABLE ONLY ci_pipeline_variables
ALTER TABLE ONLY design_management_designs_versions
ADD CONSTRAINT fk_f4d25ba00c FOREIGN KEY (version_id) REFERENCES design_management_versions(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_devops_adoption_segments
+ ADD CONSTRAINT fk_f5aa768998 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY cluster_agents
+ ADD CONSTRAINT fk_f7d43dee13 FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY protected_tag_create_access_levels
ADD CONSTRAINT fk_f7dfda8c51 FOREIGN KEY (protected_tag_id) REFERENCES protected_tags(id) ON DELETE CASCADE;
@@ -24301,6 +24799,9 @@ 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 ci_daily_build_group_report_results
+ ADD CONSTRAINT fk_fd1858fefd FOREIGN KEY (group_id) REFERENCES namespaces(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;
@@ -24370,6 +24871,9 @@ ALTER TABLE ONLY ci_subscriptions_projects
ALTER TABLE ONLY trending_projects
ADD CONSTRAINT fk_rails_09feecd872 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_orchestration_policy_configurations
+ ADD CONSTRAINT fk_rails_0a22dcd52d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_deploy_tokens
ADD CONSTRAINT fk_rails_0aca134388 FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE;
@@ -24532,6 +25036,9 @@ ALTER TABLE ONLY service_desk_settings
ALTER TABLE ONLY saml_group_links
ADD CONSTRAINT fk_rails_22e312c530 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_profiles
+ ADD CONSTRAINT fk_rails_23cae5abe1 FOREIGN KEY (dast_scanner_profile_id) REFERENCES dast_scanner_profiles(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY group_custom_attributes
ADD CONSTRAINT fk_rails_246e0db83a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -24577,6 +25084,9 @@ ALTER TABLE ONLY group_group_links
ALTER TABLE ONLY geo_repository_updated_events
ADD CONSTRAINT fk_rails_2b70854c08 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_component_files
+ ADD CONSTRAINT fk_rails_2b8992dd83 FOREIGN KEY (architecture_id) REFERENCES packages_debian_group_architectures(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY boards_epic_board_labels
ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
@@ -24703,6 +25213,9 @@ ALTER TABLE ONLY epic_issues
ALTER TABLE ONLY ci_refs
ADD CONSTRAINT fk_rails_4249db8cc3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_orchestration_policy_configurations
+ ADD CONSTRAINT fk_rails_42ed6c25ec FOREIGN KEY (security_policy_management_project_id) REFERENCES projects(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY ci_resources
ADD CONSTRAINT fk_rails_430336af2d FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE CASCADE;
@@ -24721,9 +25234,6 @@ ALTER TABLE ONLY merge_request_assignees
ALTER TABLE ONLY packages_dependency_links
ADD CONSTRAINT fk_rails_4437bf4070 FOREIGN KEY (dependency_id) REFERENCES packages_dependencies(id) ON DELETE CASCADE;
-ALTER TABLE ONLY namespace_onboarding_actions
- ADD CONSTRAINT fk_rails_4504f6875a FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY project_auto_devops
ADD CONSTRAINT fk_rails_45436b12b2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -24784,6 +25294,9 @@ ALTER TABLE ONLY aws_roles
ALTER TABLE ONLY security_scans
ADD CONSTRAINT fk_rails_4ef1e6b4c6 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_publications
+ ADD CONSTRAINT fk_rails_4fc8ebd03e FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_diff_files
ADD CONSTRAINT fk_rails_501aa0a391 FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
@@ -24793,6 +25306,9 @@ 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;
@@ -25027,6 +25543,9 @@ ALTER TABLE ONLY x509_certificates
ALTER TABLE ONLY pages_domain_acme_orders
ADD CONSTRAINT fk_rails_76581b1c16 FOREIGN KEY (pages_domain_id) REFERENCES pages_domains(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_publications
+ ADD CONSTRAINT fk_rails_7668c1d606 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY boards_epic_user_preferences
ADD CONSTRAINT fk_rails_76c4e9732d FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -25171,12 +25690,18 @@ ALTER TABLE ONLY scim_identities
ALTER TABLE ONLY packages_debian_project_distributions
ADD CONSTRAINT fk_rails_94b95e1f84 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY packages_rubygems_metadata
+ ADD CONSTRAINT fk_rails_95a3f5ce78 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY packages_pypi_metadata
ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
ALTER TABLE ONLY packages_dependency_links
ADD CONSTRAINT fk_rails_96ef1c00d3 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_repository_storage_moves
+ ADD CONSTRAINT fk_rails_982bb5daf1 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT fk_rails_9851a00031 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -25201,6 +25726,9 @@ ALTER TABLE ONLY users_ops_dashboard_projects
ALTER TABLE ONLY project_incident_management_settings
ADD CONSTRAINT fk_rails_9c2ea1b7dd FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_components
+ ADD CONSTRAINT fk_rails_9d072b5073 FOREIGN KEY (distribution_id) REFERENCES packages_debian_project_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY gpg_keys
ADD CONSTRAINT fk_rails_9d1f5d8719 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -25336,14 +25864,17 @@ ALTER TABLE ONLY merge_trains
ALTER TABLE ONLY application_settings
ADD CONSTRAINT fk_rails_b53e481273 FOREIGN KEY (custom_project_templates_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY packages_debian_project_component_files
+ ADD CONSTRAINT fk_rails_b543a9622b FOREIGN KEY (architecture_id) REFERENCES packages_debian_project_architectures(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT fk_rails_b565c8d16c FOREIGN KEY (namespace_id) REFERENCES namespaces(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;
-ALTER TABLE ONLY alerts_service_data
- ADD CONSTRAINT fk_rails_b93215a42c FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_composer_cache_files
+ ADD CONSTRAINT fk_rails_b82cea43a0 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE SET NULL;
ALTER TABLE ONLY merge_trains
ADD CONSTRAINT fk_rails_b9d67af01d FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25357,6 +25888,9 @@ ALTER TABLE ONLY lists
ALTER TABLE ONLY security_findings
ADD CONSTRAINT fk_rails_bb63863cf1 FOREIGN KEY (scan_id) REFERENCES security_scans(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_project_component_files
+ ADD CONSTRAINT fk_rails_bbe9ebfbd9 FOREIGN KEY (component_id) REFERENCES packages_debian_project_components(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_bc8972fa55 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -25525,6 +26059,9 @@ ALTER TABLE ONLY vulnerability_occurrence_pipelines
ALTER TABLE ONLY deployment_merge_requests
ADD CONSTRAINT fk_rails_dcbce9f4df FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_debian_group_component_files
+ ADD CONSTRAINT fk_rails_dd262386e9 FOREIGN KEY (component_id) REFERENCES packages_debian_group_components(id) ON DELETE RESTRICT;
+
ALTER TABLE ONLY user_callouts
ADD CONSTRAINT fk_rails_ddfdd80f3d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -25606,6 +26143,9 @@ ALTER TABLE ONLY alert_management_alert_user_mentions
ALTER TABLE ONLY snippet_statistics
ADD CONSTRAINT fk_rails_ebc283ccf1 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_profiles
+ ADD CONSTRAINT fk_rails_ed1e66fbbf FOREIGN KEY (dast_site_profile_id) REFERENCES dast_site_profiles(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY project_security_settings
ADD CONSTRAINT fk_rails_ed4abe1338 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -25660,6 +26200,9 @@ ALTER TABLE ONLY board_group_recent_visits
ALTER TABLE ONLY resource_state_events
ADD CONSTRAINT fk_rails_f5827a7ccd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY packages_debian_group_components
+ ADD CONSTRAINT fk_rails_f5f1ef54c6 FOREIGN KEY (distribution_id) REFERENCES packages_debian_group_distributions(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY incident_management_oncall_shifts
ADD CONSTRAINT fk_rails_f6eef06841 FOREIGN KEY (participant_id) REFERENCES incident_management_oncall_participants(id) ON DELETE CASCADE;
@@ -25684,6 +26227,9 @@ ALTER TABLE ONLY merge_trains
ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_fingerprints
+ ADD CONSTRAINT fk_rails_fa411253b2 FOREIGN KEY (finding_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY requirements_management_test_reports
ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES requirements(id) ON DELETE CASCADE;
@@ -25730,6 +26276,12 @@ ALTER TABLE ONLY u2f_registrations
ADD CONSTRAINT fk_u2f_registrations_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE product_analytics_events_experimental
- ADD CONSTRAINT product_analytics_events_experimental_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;-- schema_migrations.version information is no longer stored in this file,
+ ADD CONSTRAINT product_analytics_events_experimental_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY user_follow_users
+ ADD CONSTRAINT user_follow_users_followee_id_fkey FOREIGN KEY (followee_id) REFERENCES users(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY user_follow_users
+ ADD CONSTRAINT user_follow_users_follower_id_fkey FOREIGN KEY (follower_id) REFERENCES users(id) ON DELETE CASCADE;-- schema_migrations.version information is no longer stored in this file,
-- but instead tracked in the db/schema_migrations directory
-- see https://gitlab.com/gitlab-org/gitlab/-/issues/218590 for details
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 481da94c627..f7077413c9e 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -27,6 +27,8 @@ exceptions:
- CNA
- CNAME
- CORE
+ - CVS
+ - FREE
- CPU
- CRIME
- CSRF
@@ -41,12 +43,14 @@ exceptions:
- DSA
- DVCS
- ECDSA
+ - EFS
- EKS
- EOL
- EXIF
- FAQ
- FOSS
- FQDN
+ - FREE
- GCP
- GDK
- GDPR
@@ -90,7 +94,6 @@ exceptions:
- NFS
- NGINX
- NOTE
- - NPM
- NTP
- ONLY
- OWASP
@@ -116,11 +119,13 @@ exceptions:
- RSS
- RVM
- SAML
+ - SAAS
- SAST
- SCIM
- SCP
- SCSS
- SDK
+ - SELF
- SEO
- SHA
- SLA
@@ -128,6 +133,7 @@ exceptions:
- SMTP
- SOC
- SOX
+ - SPDX
- SPF
- SQL
- SSD
@@ -138,11 +144,14 @@ exceptions:
- SVG
- SVN
- TCP
+ - TIFF
- TIP
- TLD
- TLS
- TODO
- TOML
+ - TTL
+ - UDP
- UNIX
- URI
- URL
@@ -157,3 +166,5 @@ exceptions:
- XML
- XSS
- YAML
+ - ZAP
+ - ZIP
diff --git a/doc/.vale/gitlab/Admin.yml b/doc/.vale/gitlab/Admin.yml
index 96325ad2ef4..d74621bde8e 100644
--- a/doc/.vale/gitlab/Admin.yml
+++ b/doc/.vale/gitlab/Admin.yml
@@ -5,9 +5,9 @@
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
-message: 'Use "administration", "administrator", "administer", or "Admin Area" instead of "admin" or "admin area".'
+message: 'Verify this use of the word "admin". Can it be updated to "administration", "administrator", "administer", or "Admin Area"?'
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html
-level: warning
+level: suggestion
ignorecase: true
swap:
- 'admin ?\w*': '(?:Admin Area|[Aa]dminist(ration|rator|er|rative))'
+ 'admin ?\w*': '(?:Admin Area|[Aa]dminist(ration|rator|rators|er|rative))'
diff --git a/doc/.vale/gitlab/SubstitutionSuggestions.yml b/doc/.vale/gitlab/SubstitutionSuggestions.yml
index ab6658f0943..eac738d9eec 100644
--- a/doc/.vale/gitlab/SubstitutionSuggestions.yml
+++ b/doc/.vale/gitlab/SubstitutionSuggestions.yml
@@ -18,4 +18,6 @@ swap:
once the: '"after the"'
once you: '"after you"'
since: '"because" or "after"'
+ sub-group: '"subgroup"'
+ sub-groups: '"subgroups"'
within: '"in"'
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index 987785c7a22..b31bead3bcd 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -11,6 +11,7 @@ link: https://about.gitlab.com/handbook/communication/#top-misused-terms
level: error
ignorecase: true
swap:
+ codequality: code quality
Customer [Pp]ortal: Customers Portal
frontmatter: front matter
GitLabber: GitLab team member
@@ -20,7 +21,7 @@ swap:
param: parameter
params: parameters
pg: PostgreSQL
- postgres: PostgreSQL
+ 'postgres$': PostgreSQL
raketask: Rake task
raketasks: Rake tasks
rspec: RSpec
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 6ce0ced52b3..375cecfdee4 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -1,20 +1,29 @@
+accessor
+accessors
Akismet
Alertmanager
Algolia
Alibaba
+Aliyun
allowlist
+allowlisted
allowlisting
allowlists
+anonymization
anonymized
Ansible
Anthos
approvers
architected
+architecting
+archiver
+Arel
Artifactory
Asana
Asciidoctor
Assembla
Atlassian
+auditability
Auth0
Authentiq
autocomplete
@@ -31,6 +40,7 @@ autoscaler
autoscales
autoscaling
awardable
+awardables
Axios
Azure
B-tree
@@ -52,8 +62,13 @@ blockquoted
blockquotes
blockquoting
boolean
+booleans
Bootsnap
browsable
+bugfix
+bugfixed
+bugfixes
+bugfixing
Bugzilla
Buildkite
buildpack
@@ -62,9 +77,17 @@ bundler
bundlers
burndown
burnup
+burstable
cacheable
+Caddy
+callstack
+callstacks
+Camo
+canonicalized
CentOS
Certbot
+changeset
+changesets
chai
chatbot
chatbots
@@ -86,6 +109,7 @@ Conda
Consul
Contentful
Corosync
+Coursier
cron
crons
crontab
@@ -96,15 +120,22 @@ crosslinks
Crossplane
CrowdIn
CSV
+cybersecurity
Dangerfile
datetime
Debian
+Decompressor
+decryptable
deduplicate
deduplicated
deduplicates
deduplicating
deduplication
deliverables
+denormalize
+denormalized
+denormalizes
+denormalizing
denylist
denylisting
denylists
@@ -118,11 +149,16 @@ dequarantine
dequarantined
dequarantining
DevOps
+disambiguates
discoverability
+dismissable
Disqus
Divio
Dockerfile
Dockerfiles
+Dockerize
+Dockerized
+Dockerizing
dogfood
dogfooding
dogfoods
@@ -135,6 +171,7 @@ Ecto
Elasticsearch
enablement
enqueued
+enqueues
enum
enums
ETag
@@ -145,20 +182,28 @@ failover
failovers
failsafe
Falco
+falsy
fastlane
+Fastzip
favicon
+favorited
Figma
Filebeat
Fio
firewalled
+firewalling
Flawfinder
Flowdock
Fluentd
Forgerock
+formatters
Fugit
+fuzzer
Gantt
Gemnasium
Gemojione
+Getter
+Getters
gettext
Git
Gitaly
@@ -167,9 +212,11 @@ GitHub
GitLab
gitlabsos
Gitleaks
+Gitpod
Gitter
globals
Gmail
+Godep
Gollum
Google
goroutine
@@ -177,17 +224,20 @@ goroutines
Gosec
Gradle
Grafana
+Grafonnet
gravatar
Gzip
Haml
hardcode
hardcoded
hardcodes
+Haswell
heatmap
heatmaps
Helm
Heroku
Herokuish
+Hexo
HipChat
hostname
hostnames
@@ -199,17 +249,22 @@ http
https
idempotence
idmapper
+Iglu
inclusivity
Ingress
initializer
initializers
+innersource
+innersourcing
interdependencies
interdependency
interruptible
Irker
+issuables
Istio
Jaeger
jasmine-jquery
+Javafuzz
JavaScript
Jenkins
Jenkinsfile
@@ -217,6 +272,7 @@ Jira
jq
jQuery
jsdom
+Jsonnet
JupyterHub
kanban
kanbans
@@ -224,8 +280,11 @@ kaniko
Karma
Kerberos
keyset
+keytab
+keytabs
Kibana
Kinesis
+Klar
Knative
Kramdown
Kroki
@@ -233,13 +292,18 @@ Kubecost
kubectl
Kubernetes
Kubesec
+Kustomize
Laravel
ldapsearch
Lefthook
Leiningen
+libFuzzer
Libravatar
liveness
+Lodash
Lograge
+logrotate
+Logrus
Logstash
lookahead
lookaheads
@@ -250,6 +314,7 @@ loopback
Lucene
Maildir
Mailgun
+Mailroom
Makefile
Makefiles
Markdown
@@ -297,9 +362,14 @@ namespaces
namespacing
namespacings
Nanoc
+negatable
Netlify
Nokogiri
+noteable
+noteables
npm
+nullability
+nullable
Nurtch
nyc
OAuth
@@ -312,6 +382,7 @@ onboarding
OpenID
OpenShift
Opsgenie
+Overcommit
Packagist
parallelization
parallelizations
@@ -319,10 +390,12 @@ passwordless
Patroni
performant
PgBouncer
+pgLoader
Phabricator
phaser
phasers
phpenv
+pipenv
Pipfile
Pipfiles
Piwik
@@ -331,6 +404,7 @@ Poedit
polyfill
polyfills
pooler
+postgres.ai
PostgreSQL
precompile
preconfigure
@@ -362,12 +436,22 @@ pseudocode
pseudonymized
pseudonymizer
Puma
+pytest
Python
Qualys
+queryable
+Quicktime
Rackspace
Raspbian
Rdoc
reachability
+Realplayer
+reauthenticate
+reauthenticated
+reauthenticates
+reauthenticating
+rebalancing
+rebar
rebase
rebased
rebases
@@ -383,6 +467,8 @@ referer
referers
reflog
reflogs
+refspec
+refspecs
reindex
reindexed
reindexes
@@ -402,6 +488,10 @@ resync
resynced
resyncing
resyncs
+retarget
+retargeted
+retargeting
+retargets
reusability
reverified
reverifies
@@ -414,10 +504,12 @@ rsync
rsynced
rsyncing
rsyncs
+Rubinius
Rubix
Rubocop
Rubular
ruleset
+rulesets
runbook
runbooks
runit
@@ -430,19 +522,24 @@ sbt
scatterplot
scatterplots
Schemastore
+scrollable
Sendmail
Sentry
serializer
serializers
serializing
serverless
+sharded
sharding
shfmt
Shibboleth
+Shopify
Sidekiq
+Silverlight
Sisense
Sitespeed
Slack
+Slackbot
Slony
smartcard
smartcards
@@ -455,6 +552,9 @@ spidering
Splunk
SpotBugs
Stackdriver
+Stackprof
+starrer
+starrers
storable
storages
strace
@@ -465,6 +565,8 @@ subfolder
subfolders
subgraph
subgraphs
+subgroup
+subgroups
subkey
subkeys
sublicense
@@ -475,22 +577,44 @@ subnet
subnets
subnetting
subpath
+subproject
+subprojects
subqueried
subqueries
subquery
subquerying
substring
substrings
+subtask
+subtasks
+subtest
+subtests
subtree
subtrees
sudo
+supercookie
+supercookies
+supertype
+supertypes
+swappiness
swimlane
swimlanes
+syncable
+Sysbench
+syscall
+syscalls
syslog
tanuki
tcpdump
+templated
Thanos
+Thoughtbot
+throughputs
Tiller
+timebox
+timeboxed
+timeboxes
+timeboxing
timecop
todos
tokenizer
@@ -498,22 +622,33 @@ Tokenizers
tokenizing
toolchain
toolchains
+toolkit
+toolkits
tooltip
tooltips
transpile
+transpiled
transpiles
transpiling
Trello
+triaged
+triages
triaging
+truthy
+Truststore
Twilio
Twitter
TypeScript
Ubuntu
unapplied
+unapprove
+unapproved
+unapproving
unarchive
unarchived
unarchives
unarchiving
+unary
unassign
unassigning
unassigns
@@ -524,6 +659,7 @@ unchecks
uncomment
uncommented
uncommenting
+uncordon
unencode
unencoded
unencoder
@@ -534,6 +670,8 @@ unindexed
unlink
unlinking
unlinks
+unmappable
+unmapped
unmergeable
unmerged
unmerges
@@ -543,9 +681,11 @@ unoptimize
unoptimized
unoptimizes
unoptimizing
+unpatched
unprioritized
unprotect
unprotected
+unprotecting
unprotects
unprovision
unprovisioned
@@ -554,6 +694,7 @@ unpublish
unpublished
unpublishes
unpublishing
+unpushed
unreferenced
unregister
unregistered
@@ -562,8 +703,12 @@ unreplicated
unresolve
unresolved
unresolving
+unsanitized
unschedule
unscoped
+unshare
+unshared
+unshares
unstage
unstaged
unstages
@@ -574,6 +719,7 @@ unstarted
unstash
unstashed
unstashing
+unsynced
untarred
untracked
untrusted
@@ -583,8 +729,12 @@ unverify
unverifying
uploader
uploaders
+upstreams
+upvote
upvoted
upvotes
+URIs
+Vagrantfile
validator
validators
vendored
@@ -601,6 +751,9 @@ WebdriverIO
Webex
webpack
webserver
+Webservice
+websocket
+websockets
whitepaper
whitepapers
wireframe
@@ -611,9 +764,11 @@ Wireshark
Wordpress
worktree
worktrees
+Worldline
Xcode
Xeon
YouTrack
+Yubico
Zeitwerk
Zendesk
zsh
diff --git a/doc/README.md b/doc/README.md
index 41a68df09d0..4c4b0cd3a15 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -23,32 +23,32 @@ Here you can access the complete documentation for GitLab, the single applicatio
No matter how you use GitLab, we have documentation for you.
-| Essential documentation | Essential documentation |
-|:---------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| Essential documentation | Essential documentation |
+|:------------------------|:------------------------|
| [**User documentation**](user/index.md)<br>Discover features and concepts for GitLab users. | [**Administrator documentation**](administration/index.md)<br/>Everything GitLab self-managed administrators need to know. |
-| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](#new-to-git-and-gitlab)<br/>We have the resources to get you started. |
-| [**Build an integration with GitLab**](#build-an-integration-with-gitlab)<br/>Consult our integration documentation. | [**Coming to GitLab from another platform?**](#coming-to-gitlab-from-another-platform)<br/>Consult our guides. |
-| [**Install GitLab**](https://about.gitlab.com/install/)<br/>Installation options for different platforms. | [**Customers**](subscriptions/index.md)<br/>Information for new and existing customers. |
-| [**Update GitLab**](update/README.md)<br/>Update your GitLab self-managed instance to the latest version. | [**Reference Architectures**](administration/reference_architectures/index.md)<br/>GitLab reference architectures |
-| [**GitLab releases**](https://about.gitlab.com/releases/)<br/>What's new in GitLab. | |
+| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](#new-to-git-and-gitlab)<br/>We have the resources to get you started. |
+| [**Build an integration with GitLab**](#build-an-integration-with-gitlab)<br/>Consult our integration documentation. | [**Coming to GitLab from another platform?**](#coming-to-gitlab-from-another-platform)<br/>Consult our guides. |
+| [**Install GitLab**](https://about.gitlab.com/install/)<br/>Installation options for different platforms. | [**Customers**](subscriptions/index.md)<br/>Information for new and existing customers. |
+| [**Update GitLab**](update/index.md)<br/>Update your GitLab self-managed instance to the latest version. | [**Reference Architectures**](administration/reference_architectures/index.md)<br/>GitLab reference architectures. |
+| [**GitLab releases**](https://about.gitlab.com/releases/)<br/>What's new in GitLab. | |
## Popular topics
Have a look at some of our most popular topics:
-| Popular topic | Description |
-|:-----------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------|
-| [Two-factor authentication](user/profile/account/two_factor_authentication.md) | Improve the security of your GitLab account. |
-| [GitLab groups](user/group/index.md) | Manage projects together. |
-| [GitLab CI/CD pipeline configuration reference](ci/yaml/README.md) | Available configuration options for `.gitlab-ci.yml` files. |
-| [Activate GitLab EE with a license](user/admin_area/license.md) **(STARTER ONLY)** | Activate GitLab Enterprise Edition functionality with a license. |
-| [Back up and restore GitLab](raketasks/backup_restore.md) **(CORE ONLY)** | Rake tasks for backing up and restoring GitLab self-managed instances. |
-| [GitLab release and maintenance policy](policy/maintenance.md) | Policies for version naming and cadence, and also upgrade recommendations. |
-| [Elasticsearch integration](integration/elasticsearch.md) **(STARTER ONLY)** | Integrate Elasticsearch with GitLab to enable advanced searching. |
-| [Omnibus GitLab database settings](https://docs.gitlab.com/omnibus/settings/database.html) **(CORE ONLY)** | Database settings for Omnibus GitLab self-managed instances. |
-| [Omnibus GitLab NGINX settings](https://docs.gitlab.com/omnibus/settings/nginx.html) **(CORE ONLY)** | NGINX settings for Omnibus GitLab self-managed instances. |
-| [Omnibus GitLab SSL configuration](https://docs.gitlab.com/omnibus/settings/ssl.html) **(CORE ONLY)** | SSL settings for Omnibus GitLab self-managed instances. |
-| [GitLab.com settings](user/gitlab_com/index.md) | Settings used for GitLab.com. |
+| Popular topic | Description |
+|:-------------------------------------------------------------------------------------------|:------------|
+| [Two-factor authentication](user/profile/account/two_factor_authentication.md) | Improve the security of your GitLab account. |
+| [GitLab groups](user/group/index.md) | Manage projects together. |
+| [GitLab CI/CD pipeline configuration reference](ci/yaml/README.md) | Available configuration options for `.gitlab-ci.yml` files. |
+| [Activate GitLab EE with a license](user/admin_area/license.md) | Activate GitLab Enterprise Edition functionality with a license. |
+| [Back up and restore GitLab](raketasks/backup_restore.md) | Rake tasks for backing up and restoring GitLab self-managed instances. |
+| [GitLab release and maintenance policy](policy/maintenance.md) | Policies for version naming and cadence, and also upgrade recommendations. |
+| [Elasticsearch integration](integration/elasticsearch.md) | Integrate Elasticsearch with GitLab to enable advanced searching. |
+| [Omnibus GitLab database settings](https://docs.gitlab.com/omnibus/settings/database.html) | Database settings for Omnibus GitLab self-managed instances. |
+| [Omnibus GitLab NGINX settings](https://docs.gitlab.com/omnibus/settings/nginx.html) | NGINX settings for Omnibus GitLab self-managed instances. |
+| [Omnibus GitLab SSL configuration](https://docs.gitlab.com/omnibus/settings/ssl.html) | SSL settings for Omnibus GitLab self-managed instances. |
+| [GitLab.com settings](user/gitlab_com/index.md) | Settings used for GitLab.com. |
## The entire DevOps lifecycle
@@ -64,53 +64,53 @@ Working with new systems can be daunting.
We have the following documentation to rapidly uplift your GitLab knowledge:
-| Topic | Description |
-|:--------------------------------------------------------------------------------------------------|:---------------------------------------------------------------|
-| [GitLab basics guides](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
-| [GitLab workflow overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
-| [Get started with GitLab CI/CD](ci/quick_start/README.md) | Quickly implement GitLab CI/CD. |
-| [Auto DevOps](topics/autodevops/index.md) | Learn more about Auto DevOps in GitLab. |
-| [GitLab Markdown](user/markdown.md) | Advanced formatting system (GitLab Flavored Markdown) |
+| Topic | Description |
+|:--------------------------------------------------------------------------------------------------|:------------|
+| [GitLab basics guides](gitlab-basics/index.md) | Start working on the command line and with GitLab. |
+| [GitLab workflow overview](https://about.gitlab.com/blog/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
+| [Get started with GitLab CI/CD](ci/quick_start/index.md) | Quickly implement GitLab CI/CD. |
+| [Auto DevOps](topics/autodevops/index.md) | Learn more about Auto DevOps in GitLab. |
+| [GitLab Markdown](user/markdown.md) | Advanced formatting system (GitLab Flavored Markdown). |
### User account
Learn more about GitLab account management:
-| Topic | Description |
-|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
-| [User account](user/profile/index.md) | Manage your account. |
+| Topic | Description |
+|:-----------------------------------------------------------|:------------|
+| [User account](user/profile/index.md) | Manage your account. |
| [Authentication](topics/authentication/index.md) | Account security with two-factor authentication, set up your SSH keys, and deploy keys for secure access to your projects. |
-| [Profile settings](user/profile/index.md#profile-settings) | Manage your profile settings, two factor authentication, and more. |
-| [User permissions](user/permissions.md) | Learn what each role in a project can do. |
+| [User settings](user/profile/index.md#user-settings) | Manage your user settings, two factor authentication, and more. |
+| [User permissions](user/permissions.md) | Learn what each role in a project can do. |
### Git and GitLab
Learn more about using Git, and using Git with GitLab:
-| Topic | Description |
-|:-----------------------------------------------------------------------------|:---------------------------------------------------------------------------|
+| Topic | Description |
+|:-----------------------------------------------------------------------------|:------------|
| [Git](topics/git/index.md) | Getting started with Git, branching strategies, Git LFS, and advanced use. |
-| [Git cheat sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) | Download a PDF describing the most used Git operations. |
-| [GitLab Flow](topics/gitlab_flow.md) | Explore the best of Git with the GitLab Flow strategy. |
+| [Git cheat sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) | Download a PDF describing the most used Git operations. |
+| [GitLab Flow](topics/gitlab_flow.md) | Explore the best of Git with the GitLab Flow strategy. |
## Coming to GitLab from another platform
If you are coming to GitLab from another platform, the following information is useful:
-| Topic | Description |
-|:----------------------------------------------------|:---------------------------------------------------------------------------------------|
+| Topic | Description |
+|:----------------------------------------------------|:------------|
| [Importing to GitLab](user/project/import/index.md) | Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz, and SVN into GitLab. |
-| [Migrating from SVN](user/project/import/svn.md) | Convert a SVN repository to Git and GitLab. |
+| [Migrating from SVN](user/project/import/svn.md) | Convert a SVN repository to Git and GitLab. |
## Build an integration with GitLab
There are many ways to integrate with GitLab, including:
-| Topic | Description |
-|:-------------------------------------------|:---------------------------------------------|
-| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. |
+| Topic | Description |
+|:-------------------------------------------|:------------|
+| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. |
| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. |
-| [Integrations](integration/README.md) | Integrations with third-party products. |
+| [Integrations](integration/README.md) | Integrations with third-party products. |
## Contributing to GitLab
@@ -119,8 +119,8 @@ and GitLab Enterprise Edition is [open-core](https://gitlab.com/gitlab-org/gitla
Learn how to contribute to GitLab with the following resources:
-| Topic | Description |
-|:------------------------------------------------------------|:-----------------------------------------|
+| Topic | Description |
+|:------------------------------------------------------------|:------------|
| [Development](development/README.md) | How to contribute to GitLab development. |
-| [Legal](legal/README.md) | Contributor license agreements. |
-| [Writing documentation](development/documentation/index.md) | How to contribute to GitLab Docs. |
+| [Legal](legal/index.md) | Contributor license agreements. |
+| [Writing documentation](development/documentation/index.md) | How to contribute to GitLab Docs. |
diff --git a/doc/administration/application_settings_cache.md b/doc/administration/application_settings_cache.md
new file mode 100644
index 00000000000..b6c09129c79
--- /dev/null
+++ b/doc/administration/application_settings_cache.md
@@ -0,0 +1,47 @@
+---
+stage: Enablement
+group: Memory
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Changing application settings cache expiry interval **(FREE SELF)**
+
+Application settings are cached for 60 seconds by default which should work
+for most installations. A higher value would mean a greater delay between
+changing an application setting and noticing that change come into effect.
+A value of `0` would result in the `application_settings` table being
+loaded for every request causing extra load on Redis and/or PostgreSQL.
+It is therefore recommended to keep the value above zero.
+
+## Change the application settings cache expiry
+
+To change the expiry value:
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['application_settings_cache_seconds'] = 60
+ ```
+
+1. Save the file, and reconfigure and restart GitLab for the changes to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ gitlab-ctl restart
+ ```
+
+---
+
+**For installations from source**
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ gitlab:
+ application_settings_cache_seconds: 60
+ ```
+
+1. Save the file and [restart](restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index 27f6bbcd028..d5755474c00 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -4,12 +4,12 @@ group: Compliance
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Audit Events **(STARTER)**
+# Audit Events **(PREMIUM)**
GitLab offers a way to view the changes made within the GitLab server for owners and administrators on a [paid plan](https://about.gitlab.com/pricing/).
GitLab system administrators can also take advantage of the logs located on the
-file system. See [the logs system documentation](logs.md) for more details.
+file system. See [the logs system documentation](logs.md#audit_jsonlog) for more details.
You can generate an [Audit report](audit_reports.md) of audit events.
@@ -36,13 +36,18 @@ There are two kinds of events logged:
- Instance events scoped to the whole GitLab instance, used by your Compliance team to
perform formal audits.
-### Impersonation data **(PREMIUM)**
+### Impersonation data
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/536) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
-Impersonation is where an administrator uses credentials to perform an action as a different user.
+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:
-### Group events **(STARTER)**
+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.
+
+![audit events](img/impersonated_audit_events_v13_8.png)
+
+### Group events **(PREMIUM)**
A user with a Owner role (or above) can retrieve group audit events of all users.
A user with a Developer or Maintainer role is limited to group audit events based on their individual actions.
@@ -72,7 +77,7 @@ From there, you can see the following actions:
Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
-### Project events **(STARTER)**
+### Project events **(PREMIUM)**
A user with a Maintainer role (or above) can retrieve project audit events of all users.
A user with a Developer role is limited to project audit events based on their individual actions.
@@ -99,13 +104,15 @@ From there, you can see the following actions:
- Number of required approvals was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
- Added or removed users and groups from project approval groups ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213603) in GitLab 13.2)
- Project CI/CD variable added, removed, or protected status changed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.4)
-- User was approved via Admin Area ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276250) in GitLab 13.6)
+- Project access token was successfully created or revoked ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230007) in GitLab 13.9)
+- Failed attempt to create or revoke a project access token ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230007) in GitLab 13.9)
+- When default branch changes for a project ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/52339) in GitLab 13.9)
Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events).
Project event queries are limited to a maximum of 30 days.
-### Instance events **(PREMIUM ONLY)**
+### Instance events **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2336) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.3.
@@ -129,6 +136,9 @@ recorded:
- Changed username ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7797) in GitLab 12.8)
- User was deleted ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/251) in GitLab 12.8)
- User was added ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/251) in GitLab 12.8)
+- User requests access to an instance ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/298783) in GitLab 13.9)
+- User was approved via Admin Area ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276250) in GitLab 13.6)
+- User was rejected via Admin Area ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/298783) in GitLab 13.9)
- User was blocked via Admin Area ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/251) in GitLab 12.8)
- User was blocked via API ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25872) in GitLab 12.9)
- Failed second-factor authentication attempt ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16826) in GitLab 13.5)
@@ -189,7 +199,7 @@ The search filters you can see depends on which audit level you are at.
![audit events](img/audit_log_v13_6.png)
-## Export to CSV **(PREMIUM ONLY)**
+## Export to CSV **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1449) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/285441) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
index 7db20efb03f..96bfbd88ddf 100644
--- a/doc/administration/auditor_users.md
+++ b/doc/administration/auditor_users.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Auditor users **(PREMIUM ONLY)**
+# Auditor users **(PREMIUM SELF)**
Auditor users are given read-only access to all projects, groups, and other
resources on the GitLab instance.
@@ -19,7 +19,7 @@ snippets, and create milestones on their groups, while also having read-only
access to all projects on the server to which they haven't been explicitly
[given access](../user/permissions.md).
-The Auditor role is _not_ a read-only version of the Admin role. Auditor users
+The `Auditor` access level is _not_ a read-only version of the `Admin` access level. Auditor users
can't access the project or group settings pages, or the Admin Area.
Assuming you have signed in as an Auditor user:
@@ -33,7 +33,7 @@ Assuming you have signed in as an Auditor user:
have the same access as their given [permissions](../user/permissions.md).
For example, if they were added as a Developer, they can push commits or
comment on issues.
-- The Auditor can't view the Admin Area, or perform any admin actions.
+- The Auditor can't view the Admin Area, or perform any administration actions.
For more information about what an Auditor can or can't do, see the
[Permissions and restrictions of an Auditor user](#permissions-and-restrictions-of-an-auditor-user)
@@ -47,7 +47,7 @@ helpful:
- Your compliance department wants to run tests against the entire GitLab base
to ensure users are complying with password, credit card, and other sensitive
data policies. With Auditor users, this can be achieved very without having
- to give them user admin rights or using the API to add them to all projects.
+ to give them user administration rights or using the API to add them to all projects.
- If particular users need visibility or access to most of all projects in
your GitLab instance, instead of manually adding the user to all projects,
you can create an Auditor user and then share the credentials with those users
@@ -68,6 +68,8 @@ To create a new Auditor user:
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).
+
## Permissions and restrictions of an Auditor user
An Auditor user should be able to access all projects and groups of a GitLab
@@ -81,7 +83,7 @@ instance, with the following permissions and restrictions:
- Can read all files in a repository
- Can read issues and MRs
- Can read project snippets
-- Cannot be Admin and Auditor at the same time
+- Cannot be Administrator and Auditor at the same time
- Cannot access the Admin Area
- In a group or project they're not a member of:
- Cannot access project settings
diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md
index cc3421d3133..69220113940 100644
--- a/doc/administration/auth/README.md
+++ b/doc/administration/auth/README.md
@@ -22,7 +22,8 @@ providers:
- [Facebook](../../integration/facebook.md)
- [GitHub](../../integration/github.md)
- [GitLab.com](../../integration/gitlab.md)
-- [Google](../../integration/google.md)
+- [Google OAuth](../../integration/google.md)
+- [Google Workspace SSO](../../integration/google_workspace_saml.md)
- [JWT](jwt.md)
- [Kerberos](../../integration/kerberos.md)
- [LDAP](ldap/index.md): Includes Active Directory, Apple Open Directory, Open LDAP,
@@ -31,9 +32,9 @@ providers:
- [Okta](okta.md)
- [Salesforce](../../integration/salesforce.md)
- [SAML](../../integration/saml.md)
-- [SAML for GitLab.com groups](../../user/group/saml_sso/index.md) **(SILVER ONLY)**
+- [SAML for GitLab.com groups](../../user/group/saml_sso/index.md) **(PREMIUM SAAS)**
- [Shibboleth](../../integration/shibboleth.md)
-- [Smartcard](smartcard.md) **(PREMIUM ONLY)**
+- [Smartcard](smartcard.md) **(PREMIUM SELF)**
- [Twitter](../../integration/twitter.md)
NOTE:
diff --git a/doc/administration/auth/google_secure_ldap.md b/doc/administration/auth/google_secure_ldap.md
deleted file mode 100644
index 37366b00f73..00000000000
--- a/doc/administration/auth/google_secure_ldap.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'ldap/google_secure_ldap.md'
----
-
-This document was moved to [another location](ldap/google_secure_ldap.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md b/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
deleted file mode 100644
index ffce06afb63..00000000000
--- a/doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../ldap/index.md'
----
-
-This document was moved to [another location](../ldap/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md b/doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md
deleted file mode 100644
index ffce06afb63..00000000000
--- a/doc/administration/auth/how_to_configure_ldap_gitlab_ee/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../ldap/index.md'
----
-
-This document was moved to [another location](../ldap/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/img/okta_admin_panel_v13_9.png b/doc/administration/auth/img/okta_admin_panel_v13_9.png
new file mode 100644
index 00000000000..2ebb1f0112c
--- /dev/null
+++ b/doc/administration/auth/img/okta_admin_panel_v13_9.png
Binary files differ
diff --git a/doc/administration/auth/ldap-ee.md b/doc/administration/auth/ldap-ee.md
deleted file mode 100644
index 6d56654a44b..00000000000
--- a/doc/administration/auth/ldap-ee.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'ldap/index.md'
----
-
-This document was moved to [another location](ldap/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/ldap-troubleshooting.md b/doc/administration/auth/ldap-troubleshooting.md
deleted file mode 100644
index 1e02755e3e5..00000000000
--- a/doc/administration/auth/ldap-troubleshooting.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'ldap/ldap-troubleshooting.md'
----
-
-This document was moved to [another location](ldap/ldap-troubleshooting.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
deleted file mode 100644
index 6d56654a44b..00000000000
--- a/doc/administration/auth/ldap.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'ldap/index.md'
----
-
-This document was moved to [another location](ldap/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index 6fecf74d935..2b75d864352 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -5,7 +5,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Google Secure LDAP **(CORE ONLY)**
+# Google Secure LDAP **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46391) in GitLab 11.9.
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index de0f123acf1..466ae8e108c 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -29,7 +29,7 @@ stands for **Lightweight Directory Access Protocol**, which is a standard
application protocol for accessing and maintaining distributed directory
information services over an Internet Protocol (IP) network.
-## Security **(CORE ONLY)**
+## Security **(FREE SELF)**
GitLab assumes that LDAP users:
@@ -44,7 +44,7 @@ We recommend against using LDAP integration if your LDAP users are
allowed to change their 'mail', 'email' or 'userPrincipalName' attribute on
the LDAP server or share email addresses.
-### User deletion **(CORE ONLY)**
+### User deletion **(FREE SELF)**
If a user is deleted from the LDAP server, they are also blocked in GitLab.
Users are immediately blocked from logging in. However, there is an
@@ -53,16 +53,16 @@ are already logged in or are using Git over SSH are be able to access
GitLab for up to one hour. Manually block the user in the GitLab Admin Area to
immediately block all access.
-GitLab Enterprise Edition Starter supports a
-[configurable sync time](#adjusting-ldap-user-sync-schedule). **(STARTER)**
+GitLab Enterprise Edition Premium supports a
+[configurable sync time](#adjusting-ldap-user-sync-schedule). **(PREMIUM)**
-## Git password authentication **(CORE ONLY)**
+## Git password authentication **(FREE SELF)**
LDAP-enabled users can always authenticate with Git using their GitLab username
or email and LDAP password, even if password authentication for Git is disabled
in the application settings.
-## Enabling LDAP sign-in for existing GitLab users **(CORE ONLY)**
+## Enabling LDAP sign-in for existing GitLab users **(FREE SELF)**
When a user signs in to GitLab with LDAP for the first time, and their LDAP
email address is the primary email address of an existing GitLab user, then
@@ -73,7 +73,7 @@ In other words, if an existing GitLab user wants to enable LDAP sign-in for
themselves, they should check that their GitLab email address matches their
LDAP email address, and then sign into GitLab via their LDAP credentials.
-## Google Secure LDAP **(CORE ONLY)**
+## Google Secure LDAP **(FREE SELF)**
> Introduced in GitLab 11.9.
@@ -81,7 +81,7 @@ LDAP email address, and then sign into GitLab via their LDAP credentials.
LDAP service that can be configured with GitLab for authentication and group sync.
See [Google Secure LDAP](google_secure_ldap.md) for detailed configuration instructions.
-## Configuration **(CORE ONLY)**
+## Configuration **(FREE SELF)**
To enable LDAP integration you need to add your LDAP server settings in
`/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml` for Omnibus
@@ -100,7 +100,7 @@ would be on port 389. `plain` also operates on port 389. Removed values: `tls` w
LDAP users must have a set email address, regardless of whether or not it's used
to sign in.
-### Example Configurations **(CORE ONLY)**
+### Example Configurations **(FREE SELF)**
**Omnibus Configuration**
@@ -163,7 +163,7 @@ production:
...
```
-### Basic Configuration Settings **(CORE ONLY)**
+### Basic Configuration Settings **(FREE SELF)**
| Setting | Description | Required | Examples |
| ------- | ----------- | -------- | -------- |
@@ -183,7 +183,7 @@ production:
| `user_filter` | Filter LDAP users. Format: [RFC 4515](https://tools.ietf.org/search/rfc4515) Note: GitLab does not support `omniauth-ldap`'s custom filter syntax. | no | `'(employeeType=developer)'` or `'(&(objectclass=user)(|(samaccountname=momo)(samaccountname=toto)))'` |
| `lowercase_usernames` | If lowercase_usernames is enabled, GitLab converts the name to lower case. | no | boolean |
-### SSL Configuration Settings **(CORE ONLY)**
+### SSL Configuration Settings **(FREE SELF)**
| Setting | Description | Required | Examples |
| ------- | ----------- | -------- | -------- |
@@ -193,7 +193,7 @@ production:
| `cert` | Client certificate | no | `'-----BEGIN CERTIFICATE----- <REDACTED> -----END CERTIFICATE -----'` |
| `key` | Client private key | no | `'-----BEGIN PRIVATE KEY----- <REDACTED> -----END PRIVATE KEY -----'` |
-### Attribute Configuration Settings **(CORE ONLY)**
+### Attribute Configuration Settings **(FREE SELF)**
LDAP attributes that GitLab uses to create an account for the LDAP user. The specified attribute can either be the attribute name as a string (for example, `'mail'`), or an array of attribute names to try in order (for example, `['mail', 'email']`). Note that the user's LDAP sign-in is the attribute specified as `uid` above.
@@ -205,7 +205,7 @@ LDAP attributes that GitLab uses to create an account for the LDAP user. The spe
| `first_name` | LDAP attribute for user first name. Used when the attribute configured for `name` does not exist. | no | `'givenName'` |
| `last_name` | LDAP attribute for user last name. Used when the attribute configured for `name` does not exist. | no | `'sn'` |
-### LDAP Sync Configuration Settings **(STARTER ONLY)**
+### LDAP Sync Configuration Settings **(PREMIUM SELF)**
| Setting | Description | Required | Examples |
| ------- | ----------- | -------- | -------- |
@@ -214,7 +214,7 @@ LDAP attributes that GitLab uses to create an account for the LDAP user. The spe
| `external_groups` | An array of CNs of groups containing users that should be considered external. Note: Not `cn=interns` or the full DN. | no | `['interns', 'contractors']` |
| `sync_ssh_keys` | The LDAP attribute containing a user's public SSH key. | no | `'sshPublicKey'` or false if not set |
-### Set up LDAP user filter **(CORE ONLY)**
+### Set up LDAP user filter **(FREE SELF)**
If you want to limit all GitLab access to a subset of the LDAP users on your
LDAP server, the first step should be to narrow the configured `base`. However,
@@ -254,12 +254,12 @@ group, you can use the following syntax:
For more information about this "LDAP_MATCHING_RULE_IN_CHAIN" filter, see the following
[Microsoft Search Filter Syntax](https://docs.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax) document.
Support for nested members in the user filter should not be confused with
-[group sync nested groups support](#supported-ldap-group-typesattributes). **(STARTER ONLY)**
+[group sync nested groups support](#supported-ldap-group-typesattributes). **(PREMIUM SELF)**
Please note that GitLab does not support the custom filter syntax used by
OmniAuth LDAP.
-#### Escaping special characters **(CORE ONLY)**
+#### Escaping special characters **(FREE SELF)**
The `user_filter` DN can contain special characters. For example:
@@ -290,7 +290,7 @@ The `user_filter` DN can contain special characters. For example:
OU=Gitlab \28Inc\29,DC=gitlab,DC=com
```
-### Enabling LDAP username lowercase **(CORE ONLY)**
+### Enabling LDAP username lowercase **(FREE SELF)**
Some LDAP servers, depending on their configurations, can return uppercase usernames.
This can lead to several confusing issues such as creating links or namespaces with uppercase names.
@@ -328,7 +328,7 @@ the configuration option `lowercase_usernames`. By default, this configuration o
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-### Disable LDAP web sign in **(CORE ONLY)**
+### Disable LDAP web sign in **(FREE SELF)**
It can be useful to prevent using LDAP credentials through the web UI when
an alternative such as SAML is preferred. This allows LDAP to be used for group
@@ -360,7 +360,7 @@ This does not disable [using LDAP credentials for Git access](#git-password-auth
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-### Using encrypted credentials **(CORE ONLY)**
+### Using encrypted credentials **(FREE SELF)**
Instead of having the LDAP integration credentials stored in plaintext in the configuration files, you can optionally
use an encrypted file for the LDAP credentials. To use this feature, you first need to enable
@@ -447,7 +447,7 @@ If initially your LDAP configuration looked like:
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-## Encryption **(CORE ONLY)**
+## Encryption **(FREE SELF)**
### TLS Server Authentication
@@ -467,7 +467,7 @@ You should disable anonymous LDAP authentication and enable simple or SASL
authentication. The TLS client authentication setting in your LDAP server cannot
be mandatory and clients cannot be authenticated with the TLS protocol.
-## Multiple LDAP servers **(STARTER ONLY)**
+## Multiple LDAP servers **(PREMIUM SELF)**
With GitLab Enterprise Edition Starter, you can configure multiple LDAP servers
that your GitLab instance connects to.
@@ -515,7 +515,7 @@ gitlab_rails['ldap_servers'] = {
If you configure multiple LDAP servers, use a unique naming convention for the `label` section of each entry. That label is used as the display name of the tab shown on the sign-in page.
-## User sync **(STARTER ONLY)**
+## User sync **(PREMIUM SELF)**
Once per day, GitLab runs a worker to check and update GitLab
users against LDAP.
@@ -530,7 +530,12 @@ The process executes the following access checks:
In Active Directory, a user is marked as disabled/blocked if the user
account control attribute (`userAccountControl:1.2.840.113556.1.4.803`)
has bit 2 set.
-For more information, see <https://ctovswild.com/2009/09/03/bitmask-searches-in-ldap/>
+
+<!-- vale gitlab.Spelling = NO -->
+
+For more information, see [Bitmask Searches in LDAP](https://ctovswild.com/2009/09/03/bitmask-searches-in-ldap/).
+
+<!-- vale gitlab.Spelling = YES -->
The user is set to an `ldap_blocked` state in GitLab if the previous conditions
fail. This means the user is not able to sign in or push/pull code.
@@ -546,7 +551,7 @@ The LDAP sync process:
- Updates existing users.
- Creates new users on first sign in.
-### Adjusting LDAP user sync schedule **(STARTER ONLY)**
+### Adjusting LDAP user sync schedule **(PREMIUM SELF)**
By default, GitLab runs a worker once per day at 01:30 a.m. server time to
check and update GitLab users against LDAP.
@@ -579,7 +584,7 @@ sync to run once every 12 hours at the top of the hour.
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-## Group Sync **(STARTER ONLY)**
+## Group Sync **(PREMIUM SELF)**
If your LDAP supports the `memberof` property, when the user signs in for the
first time GitLab triggers a sync for groups the user should be a member of.
@@ -629,11 +634,11 @@ following.
To take advantage of group sync, group owners or maintainers need to [create one
or more LDAP group links](#adding-group-links).
-### Adding group links **(STARTER ONLY)**
+### Adding group links **(PREMIUM SELF)**
For information on adding group links via CNs and filters, refer to [the GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
-### Administrator sync **(STARTER ONLY)**
+### Administrator sync **(PREMIUM SELF)**
As an extension of group sync, you can automatically manage your global GitLab
administrators. Specify a group CN for `admin_group` and all members of the
@@ -642,8 +647,8 @@ like the following.
NOTE:
Administrators are not synced unless `group_base` is also
-specified alongside `admin_group`. Also, only specify the CN of the admin
-group, as opposed to the full DN.
+specified alongside `admin_group`. Also, only specify the CN of the `admin_group`,
+as opposed to the full DN.
**Omnibus configuration**
@@ -677,7 +682,7 @@ group, as opposed to the full DN.
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-### Global group memberships lock **(STARTER ONLY)**
+### Global group memberships lock **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1793) in GitLab 12.0.
@@ -693,10 +698,10 @@ When enabled, the following applies:
To enable it you need to:
1. [Enable LDAP](#configuration)
-1. Navigate to **(admin)** **Admin Area > Settings -> Visibility and access controls**.
+1. Navigate to **Admin Area > Settings -> Visibility and access controls**.
1. Make sure the "Lock memberships to LDAP synchronization" checkbox is enabled.
-### Adjusting LDAP group sync schedule **(STARTER ONLY)**
+### Adjusting LDAP group sync schedule **(PREMIUM SELF)**
By default, GitLab runs a group sync process every hour, on the hour.
The values shown are in cron format. If needed, you can use a
@@ -735,7 +740,7 @@ sync to run once every 2 hours at the top of the hour.
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-### External groups **(STARTER ONLY)**
+### External groups **(PREMIUM SELF)**
Using the `external_groups` setting will allow you to mark all users belonging
to these groups as [external users](../../../user/permissions.md#external-users).
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index 1976bab03c6..438f591856b 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -52,7 +52,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
admin_group: 'my_admin_group'
```
-#### Query LDAP **(STARTER ONLY)**
+#### Query LDAP **(PREMIUM SELF)**
The following allows you to perform a search in LDAP using the rails console.
Depending on what you're trying to do, it may make more sense to query [a
@@ -148,11 +148,11 @@ We have a workaround, based on toggling the access level of affected users:
1. As an administrator, go to **Admin Area > Overview > Users**.
1. Select the name of the affected user.
1. In the user's administrative page, press **Edit** on the top right of the page.
-1. Change the user's access level from **Regular** to **Admin** (or vice versa),
+1. Change the user's access level from `Regular` to `Admin` (or vice versa),
and press **Save changes** at the bottom of the page.
1. Press **Edit** on the top right of the user's profile page
again.
-1. Restore the user's original access level (**Regular** or **Admin**)
+1. Restore the user's original access level (`Regular` or `Admin`)
and press **Save changes** again.
The user should now be able to sign in.
@@ -191,7 +191,7 @@ have to be taken here:
will associate this profile to the LDAP identity.
The user can do either of these steps [in their
-profile](../../../user/profile/index.md#user-profile) or an admin can do it.
+profile](../../../user/profile/index.md#user-profile) or an administrator can do it.
#### Debug LDAP user filter
@@ -210,7 +210,7 @@ ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$ba
port.
- We are assuming the password for the `bind_dn` user is in `bind_dn_password.txt`.
-#### Sync all users **(STARTER ONLY)**
+#### Sync all users **(PREMIUM SELF)**
The output from a manual [user sync](index.md#user-sync) can show you what happens when
GitLab tries to sync its users against LDAP. Enter the [rails console](#rails-console)
@@ -225,7 +225,7 @@ LdapSyncWorker.new.perform
Next, [learn how to read the
output](#example-console-output-after-a-user-sync).
-##### Example console output after a user sync **(STARTER ONLY)**
+##### Example console output after a user sync **(PREMIUM SELF)**
The output from a [manual user sync](#sync-all-users) will be very verbose, and a
single user's successful sync can look like this:
@@ -316,9 +316,9 @@ adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP pr
Gitlab::Auth::Ldap::Person.find_by_uid('<uid>', adapter)
```
-### Group memberships **(STARTER ONLY)**
+### Group memberships **(PREMIUM SELF)**
-#### Membership(s) not granted **(STARTER ONLY)**
+#### Membership(s) not granted **(PREMIUM SELF)**
Sometimes you may think a particular user should be added to a GitLab group via
LDAP group sync, but for some reason it's not happening. There are several
@@ -358,17 +358,17 @@ the rails console.
UIDs here should match the 'Identifier' from the LDAP identity checked earlier. If it doesn't,
the user does not appear to be in the LDAP group.
-#### Admin privileges not granted
+#### Administrator privileges not granted
When [Administrator sync](index.md#administrator-sync) has been configured
-but the configured users aren't granted the correct admin privileges, confirm
+but the configured users aren't granted the correct administrator privileges, confirm
the following are true:
- A [`group_base` is also configured](index.md#group-sync).
- The configured `admin_group` in the `gitlab.rb` is a CN, rather than a DN or an array.
- This CN falls under the scope of the configured `group_base`.
- The members of the `admin_group` have already signed into GitLab with their LDAP
- credentials. GitLab will only grant this admin access to the users whose
+ credentials. GitLab will only grant this administrator access to the users whose
accounts are already connected to LDAP.
If all the above are true and the users are still not getting access, [run a manual
@@ -376,7 +376,7 @@ group sync](#sync-all-groups) in the rails console and [look through the
output](#example-console-output-after-a-group-sync) to see what happens when
GitLab syncs the `admin_group`.
-#### Sync all groups **(STARTER ONLY)**
+#### Sync all groups **(PREMIUM SELF)**
NOTE:
To sync all groups manually when debugging is unnecessary, [use the Rake
@@ -394,7 +394,7 @@ LdapAllGroupsSyncWorker.new.perform
Next, [learn how to read the
output](#example-console-output-after-a-group-sync).
-##### Example console output after a group sync **(STARTER ONLY)**
+##### Example console output after a group sync **(PREMIUM SELF)**
Like the output from the user sync, the output from the [manual group
sync](#sync-all-groups) will also be very verbose. However, it contains lots
@@ -477,14 +477,14 @@ this line will indicate the sync is finished:
Finished syncing admin users for 'ldapmain' provider
```
-If [admin sync](index.md#administrator-sync) is not configured, you'll see a message
+If [administrator sync](index.md#administrator-sync) is not configured, you'll see a message
stating as such:
```shell
No `admin_group` configured for 'ldapmain' provider. Skipping
```
-#### Sync one group **(STARTER ONLY)**
+#### Sync one group **(PREMIUM SELF)**
[Syncing all groups](#sync-all-groups) can produce a lot of noise in the output, which can be
distracting when you're only interested in troubleshooting the memberships of
@@ -506,7 +506,7 @@ EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)
The output will be similar to
[that you'd get from syncing all groups](#example-console-output-after-a-group-sync).
-#### Query a group in LDAP **(STARTER ONLY)**
+#### Query a group in LDAP **(PREMIUM SELF)**
When you'd like to confirm that GitLab can read a LDAP group and see all its members,
you can run the following:
@@ -562,7 +562,7 @@ emails.each do |username, email|
end
```
-You can then [run a UserSync](#sync-all-users) **(STARTER ONLY)** to sync the latest DN
+You can then [run a UserSync](#sync-all-users) **(PREMIUM SELF)** to sync the latest DN
for each of these users.
## Debugging Tools
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 158182edfb5..cde8944fadc 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -130,8 +130,7 @@ different providers with Omnibus GitLab.
### Google
-See the [Google
-documentation](https://developers.google.com/identity/protocols/oauth2/openid-connect)
+See the [Google documentation](https://developers.google.com/identity/protocols/oauth2/openid-connect)
for more details:
```ruby
@@ -156,6 +155,44 @@ for more details:
}
```
+### Microsoft Azure
+
+The OpenID Connect (OIDC) protocol for Microsoft Azure uses the [Microsoft identity platform (v2) endpoints](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison).
+To get started, sign in to the [Azure Portal](https://portal.azure.com). For your app, you'll need the
+following information:
+
+- A tenant ID. You may already have one. For more information, review the
+ [Microsoft Azure Tenant](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant) documentation.
+- A client ID and a client secret. Follow the instructions in the
+ [Microsoft Quickstart Register an Application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) documentation.
+to obtain the tenant ID, client ID, and client secret for your app.
+
+Example Omnibus configuration block:
+
+```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ 'name' => 'openid_connect',
+ 'label' => 'Azure OIDC',
+ 'args' => {
+ 'name' => 'openid_connect',
+ 'scope' => ['openid', 'profile', 'email'],
+ 'response_type' => 'code',
+ 'issuer' => 'https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0',
+ 'client_auth_method' => 'query',
+ 'discovery' => true,
+ 'uid_field' => 'preferred_username',
+ 'client_options' => {
+ 'identifier' => '<YOUR APP CLIENT ID>',
+ 'secret' => '<YOUR APP CLIENT SECRET>',
+ 'redirect_uri' => 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ }
+ }
+ }
+```
+
+Microsoft has documented how its platform works with [the OIDC protocol](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc).
+
## Troubleshooting
If you're having trouble, here are some tips:
@@ -175,6 +212,6 @@ If you're having trouble, here are some tips:
OAuth2 access token if `client_auth_method` is not defined or if set to `basic`.
If you are seeing 401 errors upon retrieving the `userinfo` endpoint, you may
want to check your OpenID Web server configuration. For example, for
- [oauth2-server-php](https://github.com/bshaffer/oauth2-server-php), you
+ [`oauth2-server-php`](https://github.com/bshaffer/oauth2-server-php), you
may need to [add a configuration parameter to
Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index 50dc3b58680..0f2851890e2 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -16,16 +16,16 @@ The following documentation enables Okta as a SAML provider.
The following guidance is based on this Okta article, on adding a [SAML Application with an Okta Developer account](https://support.okta.com/help/s/article/Why-can-t-I-add-a-SAML-Application-with-an-Okta-Developer-account?language=en_US):
-1. On Okta admin section, make sure to select Classic UI view in the top left corner. From there, choose to **Add an App**.
+1. In the Okta admin section, make sure to select Classic UI view in the top left corner. From there, choose to **Add an App**.
1. When the app screen comes up you see another button to **Create an App** and
choose SAML 2.0 on the next screen.
-1. Now, very important, add a logo
+1. Optionally you can add a logo
(you can choose it from <https://about.gitlab.com/press/>). You'll have to
crop and resize it.
-1. Next, you'll need the to fill in the SAML general configuration. Here's an example
+1. Next, you'll need the to fill in the SAML general configuration. Here's an example (showing the required URLs and attribute mapping):
image.
- ![Okta admin panel view](img/okta_admin_panel.png)
+ ![Okta admin panel view](img/okta_admin_panel_v13_9.png)
1. The last part of the configuration is the feedback section where you can
just say you're a customer and creating an app for internal use.
diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md
index 9790802e413..dfeee5e7ac4 100644
--- a/doc/administration/auth/smartcard.md
+++ b/doc/administration/auth/smartcard.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Smartcard authentication **(PREMIUM ONLY)**
+# Smartcard authentication **(PREMIUM SELF)**
GitLab supports authentication using smartcards.
diff --git a/doc/administration/availability/index.md b/doc/administration/availability/index.md
deleted file mode 100644
index 4f934646ed6..00000000000
--- a/doc/administration/availability/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: ../reference_architectures/index.md
----
-
-This document was moved to [another location](../reference_architectures/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/build_artifacts.md b/doc/administration/build_artifacts.md
deleted file mode 100644
index e42f50b2e54..00000000000
--- a/doc/administration/build_artifacts.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'job_artifacts.md'
----
-
-This document was moved to [job_artifacts](job_artifacts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 6079e838ac6..721b0dbb957 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -13,17 +13,17 @@ documentation.
The [security features](../security/README.md) in GitLab may also help you meet
relevant compliance standards.
-|Feature |GitLab tier |GitLab.com | Product level |
+|Feature |GitLab tier |GitLab SaaS | Product level |
| ---------| :--------: | :-------: | :-----------: |
-|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+||Instance|
-|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Core+|✓|Instance, Group, Project|
-|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||Instance|
-|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+|||Instance
-|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Starter+||Instance|
-|**[Lock project membership to group](../user/group/index.md#member-lock)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|Group|
-|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+||Instance|
+|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Free+||Instance|
+|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Free+|✓|Instance, Group, Project|
+|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Free+||Instance|
+|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An administrator can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Premium+||Instance|
+|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Premium+||Instance|
+|**[Lock project membership to group](../user/group/index.md#member-lock)**<br>Group owners can prevent new members from being added to projects within a group.|Premium+|✓|Group|
+|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives administrators the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Premium+||Instance|
|**[LDAP group sync filters](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+||Instance|
-|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives admins the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change.|Premium+|✓|Instance, Group, Project|
+|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives administrators the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change.|Premium+|✓|Instance, Group, Project|
|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance.|Premium+||Instance|
|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. |Ultimate||Instance|
-|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#protected-branches-approval-by-code-owners) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-ci-configuration-path)**<br> GitLab Silver and Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles.|Premium+|✓|Project|
+|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#protected-branches-approval-by-code-owners) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-cicd-configuration-path)**<br> GitLab Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles.|Premium+|✓|Project|
diff --git a/doc/administration/consul.md b/doc/administration/consul.md
index 5b577443c7c..dfc859e30c2 100644
--- a/doc/administration/consul.md
+++ b/doc/administration/consul.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# How to set up Consul **(PREMIUM ONLY)**
+# How to set up Consul **(PREMIUM SELF)**
A Consul cluster consists of both
[server and client agents](https://www.consul.io/docs/agent).
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
deleted file mode 100644
index 52941556237..00000000000
--- a/doc/administration/container_registry.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'packages/container_registry.md'
----
-
-This document was moved to [another location](packages/container_registry.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/custom_hooks.md b/doc/administration/custom_hooks.md
deleted file mode 100644
index 0580540eef9..00000000000
--- a/doc/administration/custom_hooks.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'server_hooks.md'
----
-
-This document was moved to [another location](server_hooks.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
index 45243afd8ac..fe30d98b92d 100644
--- a/doc/administration/database_load_balancing.md
+++ b/doc/administration/database_load_balancing.md
@@ -4,7 +4,7 @@ group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Database Load Balancing **(PREMIUM ONLY)**
+# Database Load Balancing **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1283) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
diff --git a/doc/administration/dependency_proxy.md b/doc/administration/dependency_proxy.md
deleted file mode 100644
index c0e0643b5de..00000000000
--- a/doc/administration/dependency_proxy.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'packages/dependency_proxy.md'
----
-
-This document was moved to [another location](packages/dependency_proxy.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/encrypted_configuration.md b/doc/administration/encrypted_configuration.md
index 01a1cf66bdc..508f4314694 100644
--- a/doc/administration/encrypted_configuration.md
+++ b/doc/administration/encrypted_configuration.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Encrypted Configuration **(CORE ONLY)**
+# Encrypted Configuration **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45712) in GitLab 13.7.
@@ -34,4 +34,4 @@ The new secret can be generated by running:
bundle exec rake gitlab:env:info RAILS_ENV=production GITLAB_GENERATE_ENCRYPTED_SETTINGS_KEY_BASE=true
```
-This will print general info on the GitLab instance, but will also cause the key to be generated in `<path-to-gitlab-rails>/config/secrets.yml`
+This will print general information on the GitLab instance, but will also cause the key to be generated in `<path-to-gitlab-rails>/config/secrets.yml`
diff --git a/doc/administration/external_database.md b/doc/administration/external_database.md
deleted file mode 100644
index 7424b4e1e83..00000000000
--- a/doc/administration/external_database.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-redirect_to: 'postgresql/external.md'
----
-
-# Configure GitLab using an external PostgreSQL service
-
-This content has been moved to a [new location](postgresql/external.md).
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index 272009c1f3a..55727822654 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -6,7 +6,7 @@ type: reference
description: "GitLab administrator: enable and disable GitLab features deployed behind feature flags"
---
-# Enable and disable GitLab features deployed behind feature flags **(CORE ONLY)**
+# Enable and disable GitLab features deployed behind feature flags **(FREE SELF)**
GitLab adopted [feature flags strategies](../development/feature_flags/index.md)
to deploy features in an early stage of development so that they can be
diff --git a/doc/administration/file_hooks.md b/doc/administration/file_hooks.md
index 5de2e4aec3f..1d028b80257 100644
--- a/doc/administration/file_hooks.md
+++ b/doc/administration/file_hooks.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# File hooks
+# File hooks **(FREE)**
> - Introduced in GitLab 10.6.
> - Until GitLab 12.8, the feature name was Plugins.
@@ -19,19 +19,20 @@ directly to the GitLab source code and contribute back upstream. This way we can
ensure functionality is preserved across versions and covered by tests.
NOTE:
-File hooks must be configured on the filesystem of the GitLab server. Only GitLab
-server administrators will be able to complete these tasks. Explore
-[system hooks](../system_hooks/system_hooks.md) or [webhooks](../user/project/integrations/webhooks.md) as an option if you do not have filesystem access.
-
-A file hook will run on each event so it's up to you to filter events or projects
-within a file hook code. You can have as many file hooks as you want. Each file hook will
-be triggered by GitLab asynchronously in case of an event. For a list of events
+File hooks must be configured on the file system of the GitLab server. Only GitLab
+server administrators can complete these tasks. Explore
+[system hooks](../system_hooks/system_hooks.md) or [webhooks](../user/project/integrations/webhooks.md)
+as an option if you do not have file system access.
+
+A file hook runs on each event. You can filter events or projects
+in a file hook's code, and create many file hooks as you need. Each file hook is
+triggered by GitLab asynchronously in case of an event. For a list of events
see the [system hooks](../system_hooks/system_hooks.md) documentation.
## Setup
The file hooks must be placed directly into the `file_hooks` directory, subdirectories
-will be ignored. There is an
+are ignored. There is an
[`example` directory inside `file_hooks`](https://gitlab.com/gitlab-org/gitlab/tree/master/file_hooks/examples)
where you can find some basic examples.
@@ -52,23 +53,23 @@ Follow the steps below to set up a custom hook:
in any language, and ensure the 'shebang' at the top properly reflects the
language type. For example, if the script is in Ruby the shebang will
probably be `#!/usr/bin/env ruby`.
-1. The data to the file hook will be provided as JSON on STDIN. It will be exactly
+1. The data to the file hook is provided as JSON on STDIN. It is exactly the
same as for [system hooks](../system_hooks/system_hooks.md).
-That's it! Assuming the file hook code is properly implemented, the hook will fire
+That's it! Assuming the file hook code is properly implemented, the hook fires
as appropriate. The file hooks file list is updated for each event, there is no
need to restart GitLab to apply a new file hook.
If a file hook executes with non-zero exit code or GitLab fails to execute it, a
-message will be logged to:
+message is logged to:
- `gitlab-rails/plugin.log` in an Omnibus installation.
- `log/plugin.log` in a source installation.
## Creating file hooks
-Below is an example that will only response on the event `project_create` and
-will inform the admins from the GitLab instance that a new project has been created.
+This example responds only on the event `project_create`, and
+the GitLab instance informs the administrators that a new project has been created.
```ruby
#!/opt/gitlab/embedded/bin/ruby
@@ -97,7 +98,7 @@ end
Writing your own file hook can be tricky and it's easier if you can check it
without altering the system. A Rake task is provided so that you can use it
in a staging environment to test your file hook before using it in production.
-The Rake task will use a sample data and execute each of file hook. The output
+The Rake task uses a sample data and execute each of file hook. The output
should be enough to determine if the system sees your file hook and if it was
executed without errors.
diff --git a/doc/administration/geo/disaster_recovery/background_verification.md b/doc/administration/geo/disaster_recovery/background_verification.md
index f2854d0538b..f573b64b5f1 100644
--- a/doc/administration/geo/disaster_recovery/background_verification.md
+++ b/doc/administration/geo/disaster_recovery/background_verification.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Automatic background verification **(PREMIUM ONLY)**
+# Automatic background verification **(PREMIUM SELF)**
NOTE:
Automatic background verification of repositories and wikis was added in
@@ -146,8 +146,8 @@ If the **primary** and **secondary** nodes have a checksum verification mismatch
**Edit** button:
![Projects dashboard](img/checksum-differences-admin-projects.png)
-1. On the project admin page get the **Gitaly storage name**, and **Gitaly relative path**:
- ![Project admin page](img/checksum-differences-admin-project-page.png)
+1. On the project administration page get the **Gitaly storage name**, and **Gitaly relative path**:
+ ![Project administration page](img/checksum-differences-admin-project-page.png)
1. Navigate to the project's repository directory on both **primary** and **secondary** nodes
(the path is usually `/var/opt/gitlab/git-data/repositories`). Note that if `git_data_dirs`
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
index 3f86e03bd7f..d06f11bbe09 100644
--- a/doc/administration/geo/disaster_recovery/bring_primary_back.md
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Bring a demoted primary node back online **(PREMIUM ONLY)**
+# Bring a demoted primary node back online **(PREMIUM SELF)**
After a failover, it is possible to fail back to the demoted **primary** node to
restore your original configuration. This process consists of two steps:
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index 2b0a3e2f114..43e5dc1d224 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Disaster Recovery (Geo) **(PREMIUM ONLY)**
+# Disaster Recovery (Geo) **(PREMIUM SELF)**
Geo replicates your database, your Git repositories, and few other assets.
We will support and replicate more data in the future, that will enable you to
@@ -145,6 +145,13 @@ Note the following when promoting a secondary:
a point-in-time recovery to the last known state.
Data that was created on the primary while the secondary was paused will be lost.
+ NOTE:
+ In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
+ this command reports `ERROR - Replication is not up-to-date` even if
+ replication is actually up-to-date. If replication and verification output
+ shows that it is complete, you can add `--skip-preflight-checks` to make the
+ command complete promotion. This bug was fixed in GitLab 13.8 and later.
+
To promote the secondary node to primary along with preflight checks:
```shell
@@ -245,12 +252,6 @@ Data that was created on the primary while the secondary was paused will be lost
sudo gitlab-ctl promote-db
```
-1. Disable Patroni auto-failover:
-
- ```shell
- sudo gitlab-ctl patroni pause
- ```
-
1. Edit `/etc/gitlab/gitlab.rb` on every application and Sidekiq nodes in the secondary to reflect its new status as primary by removing any lines that enabled the `geo_secondary_role`:
```ruby
@@ -273,12 +274,6 @@ Data that was created on the primary while the secondary was paused will be lost
sudo gitlab-ctl reconfigure
```
-1. Resume Patroni auto-failover:
-
- ```shell
- sudo gitlab-ctl patroni resume
- ```
-
1. Promote the **secondary** to **primary**. SSH into a single application server and execute:
```shell
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index 1468c5cd39d..e64d0d4983e 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Disaster recovery for planned failover **(PREMIUM ONLY)**
+# Disaster recovery for planned failover **(PREMIUM SELF)**
The primary use-case of Disaster Recovery is to ensure business continuity in
the event of unplanned outage, but it can be used in conjunction with a planned
@@ -45,6 +45,12 @@ be found in `/var/opt/gitlab/gitlab-rails/shared/pages` if using Omnibus).
## Preflight checks
+NOTE:
+In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
+this command reports `ERROR - Replication is not up-to-date` even if
+replication is actually up-to-date. This bug was fixed in GitLab 13.8 and
+later.
+
Run this command to list out all preflight checks and automatically check if replication and verification are complete before scheduling a planned failover to ensure the process will go smoothly:
```shell
@@ -138,41 +144,10 @@ will take to finish syncing. An example message would be:
## Prevent updates to the **primary** node
-Until a [read-only mode](https://gitlab.com/gitlab-org/gitlab/-/issues/14609) is implemented, updates must be prevented
-from happening manually. Note that your **secondary** node still needs read-only
-access to the **primary** node during the maintenance window.
-
-1. At the scheduled time, using your cloud provider or your node's firewall, block
- all HTTP, HTTPS and SSH traffic to/from the **primary** node, **except** for your IP and
- the **secondary** node's IP.
-
- For instance, you might run the following commands on the server(s) making up your **primary** node:
-
- ```shell
- sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 22 -j ACCEPT
- sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 22 -j ACCEPT
- sudo iptables -A INPUT --destination-port 22 -j REJECT
-
- sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 80 -j ACCEPT
- sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 80 -j ACCEPT
- sudo iptables -A INPUT --tcp-dport 80 -j REJECT
-
- sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 443 -j ACCEPT
- sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 443 -j ACCEPT
- sudo iptables -A INPUT --tcp-dport 443 -j REJECT
- ```
-
- From this point, users will be unable to view their data or make changes on the
- **primary** node. They will also be unable to log in to the **secondary** node.
- However, existing sessions will work for the remainder of the maintenance period, and
- public data will be accessible throughout.
-
-1. Verify the **primary** node is blocked to HTTP traffic by visiting it in browser via
- another IP. The server should refuse connection.
+To ensure that all data is replicated to a secondary site, updates (write requests) need to
+be disabled on the primary site:
-1. Verify the **primary** node is blocked to Git over SSH traffic by attempting to pull an
- existing Git repository with an SSH remote URL. The server should refuse
- connection.
+1. Enable [maintenance mode](../../maintenance_mode/index.md).
1. Disable non-Geo periodic background jobs on the **primary** node by navigating
to **Admin Area > Monitoring > Background Jobs > Cron**, pressing `Disable All`,
diff --git a/doc/administration/geo/disaster_recovery/promotion_runbook.md b/doc/administration/geo/disaster_recovery/promotion_runbook.md
deleted file mode 100644
index eef1e7ae9dd..00000000000
--- a/doc/administration/geo/disaster_recovery/promotion_runbook.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: runbooks/planned_failover_single_node.md
----
-
-This document was moved to [another location](runbooks/planned_failover_single_node.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
index f17990ce5f8..3227fafca0f 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
@@ -9,7 +9,7 @@ WARNING:
This runbook is in **alpha**. For complete, production-ready documentation, see the
[disaster recovery documentation](../index.md).
-# Disaster Recovery (Geo) promotion runbooks **(PREMIUM ONLY)**
+# Disaster Recovery (Geo) promotion runbooks **(PREMIUM SELF)**
## Geo planned failover for a multi-node configuration
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
index a2a9350e411..7f311d172ef 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
@@ -9,7 +9,7 @@ WARNING:
This runbook is in **alpha**. For complete, production-ready documentation, see the
[disaster recovery documentation](../index.md).
-# Disaster Recovery (Geo) promotion runbooks **(PREMIUM ONLY)**
+# Disaster Recovery (Geo) promotion runbooks **(PREMIUM SELF)**
## Geo planned failover for a single-node configuration
@@ -233,12 +233,25 @@ To promote the secondary node:
check if replication and verification are complete before scheduling a planned
failover to ensure the process will go smoothly:
+ NOTE:
+ In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
+ this command reports `ERROR - Replication is not up-to-date` even if
+ replication is actually up-to-date. This bug was fixed in GitLab 13.8 and
+ later.
+
```shell
gitlab-ctl promotion-preflight-checks
```
1. Promote the **secondary**:
+ NOTE:
+ In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
+ this command reports `ERROR - Replication is not up-to-date` even if
+ replication is actually up-to-date. If replication and verification output
+ shows that it is complete, you can add `--skip-preflight-checks` to make the
+ command complete promotion. This bug was fixed in GitLab 13.8 and later.
+
```shell
gitlab-ctl promote-to-primary-node
```
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 1985ea2e04c..296500e35e2 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo **(PREMIUM ONLY)**
+# Geo **(PREMIUM SELF)**
> - Introduced in GitLab Enterprise Edition 8.9.
> - Using Geo in combination with
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 5adf256f6fa..154815efa51 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo configuration **(PREMIUM ONLY)**
+# Geo configuration **(PREMIUM SELF)**
## Configuring a new **secondary** node
@@ -229,7 +229,7 @@ keys must be manually replicated to the **secondary** node.
gitlab-rake gitlab:geo:check
```
-Once added to the admin panel and restarted, the **secondary** node will automatically start
+Once added to the Geo administration page and restarted, the **secondary** node will automatically start
replicating missing data from the **primary** node in a process known as **backfill**.
Meanwhile, the **primary** node will start to notify each **secondary** node of any changes, so
that the **secondary** node can act on those notifications immediately.
@@ -299,7 +299,7 @@ Currently, this is what is synced:
## Selective synchronization
-Geo supports selective synchronization, which allows admins to choose
+Geo supports selective synchronization, which allows administrators to choose
which projects should be synchronized by **secondary** nodes.
A subset of projects can be chosen, either by group or by storage shard. The
former is ideal for replicating data belonging to a subset of users, while the
diff --git a/doc/administration/geo/replication/database.md b/doc/administration/geo/replication/database.md
deleted file mode 100644
index 099a73e93d8..00000000000
--- a/doc/administration/geo/replication/database.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../setup/database.md'
----
-
-This document was moved to [another location](../setup/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index 0d2922c3347..f2913dd55ce 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo data types support **(PREMIUM ONLY)**
+# Geo data types support **(PREMIUM SELF)**
A Geo data type is a specific class of data that is required by one or more GitLab features to
store relevant information.
@@ -35,21 +35,21 @@ verification methods:
| Git | Object pools for forked project deduplication | Geo with Gitaly | _Not implemented_ |
| Git | Project Snippets | Geo with Gitaly | _Not implemented_ |
| Git | Personal Snippets | Geo with Gitaly | _Not implemented_ |
-| Blobs | User uploads _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | User uploads _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | LFS objects _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | LFS objects _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | CI job artifacts _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | CI job artifacts _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | Archived CI build traces _(filesystem)_ | Geo with API | _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_ |
-| Blobs | Container registry _(filesystem)_ | Geo with API/Docker API | _Not implemented_ |
+| Blobs | Container registry _(file system)_ | Geo with API/Docker API | _Not implemented_ |
| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | _Not implemented_ |
-| Blobs | Package registry _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | Package registry _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | Versioned Terraform State _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | Versioned Terraform State _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | External Merge Request Diffs _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | External Merge Request Diffs _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo nodes.
@@ -63,14 +63,14 @@ is responsible for allowing access and operations on the locally stored Git repo
on a machine with a single disk, multiple disks mounted as a single mount-point (like with a RAID array),
or using LVM.
-It requires no special filesystem and can work with NFS or a mounted Storage Appliance (there may be
-performance limitations when using a remote filesystem).
+It requires no special file system and can work with NFS or a mounted Storage Appliance (there may be
+performance limitations when using a remote file system).
Communication is done via Gitaly's own gRPC API. There are three possible ways of synchronization:
- Using regular Git clone/fetch from one Geo node to another (with special authentication).
- Using repository snapshots (for when the first method fails or repository is corrupt).
-- Manual trigger from the Admin UI (a combination of both of the above).
+- Manual trigger from the Admin Area (a combination of both of the above).
Each project can have at most 3 different repositories:
@@ -88,13 +88,13 @@ Both types will be synced to a secondary node.
GitLab stores files and blobs such as Issue attachments or LFS objects into either:
-- The filesystem in a specific location.
+- The file system in a specific location.
- An [Object Storage](../../object_storage.md) solution. Object Storage solutions can be:
- Cloud based like Amazon S3 Google Cloud Storage.
- Hosted by you (like MinIO).
- A Storage Appliance that exposes an Object Storage-compatible API.
-When using the filesystem store instead of Object Storage, you need to use network mounted filesystems
+When using the file system store instead of Object Storage, you need to use network mounted file systems
to run GitLab when using more than one server.
With respect to replication and verification:
@@ -144,9 +144,9 @@ The replication for some data types is behind a corresponding feature flag:
> - They're enabled on GitLab.com.
> - They can't be enabled or disabled per-project.
> - They are recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable them](#enable-or-disable-replication-for-some-data-types). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable them](#enable-or-disable-replication-for-some-data-types). **(FREE SELF)**
-#### Enable or disable replication (for some data types) **(CORE ONLY)**
+#### Enable or disable replication (for some data types)
Replication for some data types are released behind feature flags that are **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../feature_flags.md) can opt to disable it for your instance. You can find feature flag names of each of those data types in the notes column of the table below.
@@ -173,7 +173,7 @@ successfully, you must replicate their data using some other means.
| Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | Object Storage replication (see [Geo with Object Storage](object_storage.md)) | Notes |
|:---------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------|:----------------------------------------------------------|:-------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Application data in PostgreSQL](../../postgresql/index.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
-| [Project repository](../../..//user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | No | |
+| [Project repository](../../../user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | No | |
| [Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No |
| [Group wiki repository](../../../user/group/index.md#group-wikis) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | |
| [Uploads](../../uploads.md) | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | No | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them. |
@@ -186,13 +186,13 @@ successfully, you must replicate their data using some other means.
| [Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
| [Content in object storage (beta)](object_storage.md) | **Yes** (12.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) | No | |
| [Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | Via Object Storage provider if supported. Native Geo support (Beta). | |
-| [NPM Registry](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Maven Repository](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Conan Repository](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [NuGet Repository](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [PyPI Repository](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
-| [Generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for npm](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for Maven](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for Conan](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for NuGet](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for PyPI](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for Composer](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Package Registry for generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
| [Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default |
| [External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_merge_request_diff_replication`, enabled by default |
| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
@@ -201,4 +201,4 @@ successfully, you must replicate their data using some other means.
| [GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | No | |
| [CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Persists additional artifacts after a pipeline completes |
| [Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked on [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Note that replication of this cache is not needed for Disaster Recovery purposes because it can be recreated from external sources. |
-| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
+| [Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerabilities) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index e8767a56266..a26adcefef5 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Disabling Geo **(PREMIUM ONLY)**
+# Disabling Geo **(PREMIUM SELF)**
If you want to revert to a regular Omnibus setup after a test, or you have encountered a Disaster Recovery
situation and you want to disable Geo momentarily, you can use these instructions to disable your
diff --git a/doc/administration/geo/replication/docker_registry.md b/doc/administration/geo/replication/docker_registry.md
index f92a878662e..1669abbc52a 100644
--- a/doc/administration/geo/replication/docker_registry.md
+++ b/doc/administration/geo/replication/docker_registry.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Docker Registry for a secondary node **(PREMIUM ONLY)**
+# Docker Registry for a secondary node **(PREMIUM SELF)**
You can set up a [Docker Registry](https://docs.docker.com/registry/) on your
**secondary** Geo node that mirrors the one on the **primary** Geo node.
diff --git a/doc/administration/geo/replication/external_database.md b/doc/administration/geo/replication/external_database.md
deleted file mode 100644
index dfaf6819fa0..00000000000
--- a/doc/administration/geo/replication/external_database.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../setup/external_database.md'
----
-
-This document was moved to [another location](../setup/external_database.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index ab8199c3717..73a36f5e674 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo Frequently Asked Questions **(PREMIUM ONLY)**
+# Geo Frequently Asked Questions **(PREMIUM SELF)**
## What are the minimum requirements to run Geo?
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index 2d701458e66..f050d3e708c 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo validation tests **(PREMIUM ONLY)**
+# Geo validation tests **(PREMIUM SELF)**
The Geo team performs manual testing and validation on common deployment configurations to ensure
that Geo works when upgrading between minor GitLab versions and major PostgreSQL database versions.
@@ -53,7 +53,7 @@ The following are GitLab upgrade validation tests we performed.
- Outcome: Partial success because we did not run the looping pipeline during the demo to validate
zero-downtime.
- Follow up issues:
- - [Clarify hup Puma/Unicorn should include deploy node](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5460)
+ - [Clarify how Puma/Unicorn should include deploy node](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5460)
- [Investigate MR creation failure after upgrade to 12.9.10](https://gitlab.com/gitlab-org/gitlab/-/issues/223282) Closed as false positive.
### February 2020
@@ -128,7 +128,7 @@ The following are PostgreSQL upgrade validation tests we performed.
PostgreSQL 12 with a database cluster on the primary is not recommended until the issues are resolved.
- Known issues for PostgreSQL clusters:
- [Ensure Patroni detects PostgreSQL update](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5423)
- - [Allow configuring permanent replication slots in patroni](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5628)
+ - [Allow configuring permanent replication slots in Patroni](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5628)
### August 2020
diff --git a/doc/administration/geo/replication/high_availability.md b/doc/administration/geo/replication/high_availability.md
deleted file mode 100644
index 1da4246db1f..00000000000
--- a/doc/administration/geo/replication/high_availability.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'multiple_servers.md'
----
-
-This document was moved to [another location](multiple_servers.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/index.md b/doc/administration/geo/replication/index.md
deleted file mode 100644
index 955e05491d2..00000000000
--- a/doc/administration/geo/replication/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../index.md'
----
-
-This document was moved to [another location](../index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/geo/replication/location_aware_git_url.md b/doc/administration/geo/replication/location_aware_git_url.md
index f2cf8c9bda0..0eea792d374 100644
--- a/doc/administration/geo/replication/location_aware_git_url.md
+++ b/doc/administration/geo/replication/location_aware_git_url.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Location-aware Git remote URL with AWS Route53 **(PREMIUM ONLY)**
+# Location-aware Git remote URL with AWS Route53 **(PREMIUM SELF)**
You can provide GitLab users with a single remote URL that automatically uses
the Geo node closest to them. This means users don't need to update their Git
diff --git a/doc/administration/geo/replication/multiple_servers.md b/doc/administration/geo/replication/multiple_servers.md
index 0ab972c9077..f83e0e14e54 100644
--- a/doc/administration/geo/replication/multiple_servers.md
+++ b/doc/administration/geo/replication/multiple_servers.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo for multiple nodes **(PREMIUM ONLY)**
+# Geo for multiple nodes **(PREMIUM SELF)**
This document describes a minimal reference architecture for running Geo
in a multi-node configuration. If your multi-node setup differs from the one
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
index ce791d66b34..ad419f999b3 100644
--- a/doc/administration/geo/replication/object_storage.md
+++ b/doc/administration/geo/replication/object_storage.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo with Object storage **(PREMIUM ONLY)**
+# Geo with Object storage **(PREMIUM SELF)**
Geo can be used in combination with Object Storage (AWS S3, or other compatible object storage).
@@ -29,7 +29,7 @@ WARNING:
This is a [**beta** feature](https://about.gitlab.com/handbook/product/#beta) and is not ready yet for production use at any scale. The main limitations are a lack of testing at scale and no verification of any replicated data.
**Secondary** nodes can replicate files stored on the **primary** node regardless of
-whether they are stored on the local filesystem or in object storage.
+whether they are stored on the local file system or in object storage.
To enable GitLab replication, you must:
diff --git a/doc/administration/geo/replication/remove_geo_node.md b/doc/administration/geo/replication/remove_geo_node.md
index 519b93b447b..26150a6f536 100644
--- a/doc/administration/geo/replication/remove_geo_node.md
+++ b/doc/administration/geo/replication/remove_geo_node.md
@@ -5,15 +5,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Removing secondary Geo nodes **(PREMIUM ONLY)**
+# Removing secondary Geo nodes **(PREMIUM SELF)**
-**Secondary** nodes can be removed from the Geo cluster using the Geo admin page of the **primary** node. To remove a **secondary** node:
+**Secondary** nodes can be removed from the Geo cluster using the Geo administration page of the **primary** node. To remove a **secondary** node:
1. Navigate to **Admin Area > Geo** (`/admin/geo/nodes`).
1. Click the **Remove** button for the **secondary** node you want to remove.
1. Confirm by clicking **Remove** when the prompt appears.
-Once removed from the Geo admin page, you must stop and uninstall the **secondary** node:
+Once removed from the Geo administration page, you must stop and uninstall the **secondary** node:
1. On the **secondary** node, stop GitLab:
diff --git a/doc/administration/geo/replication/security_review.md b/doc/administration/geo/replication/security_review.md
index 7c15662340c..c31881910bc 100644
--- a/doc/administration/geo/replication/security_review.md
+++ b/doc/administration/geo/replication/security_review.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo security review (Q&A) **(PREMIUM ONLY)**
+# Geo security review (Q&A) **(PREMIUM SELF)**
The following security review of the Geo feature set focuses on security aspects of
the feature as they apply to customers running their own GitLab instances. The review
@@ -78,7 +78,7 @@ from [owasp.org](https://owasp.org/).
### Who has administrative capabilities in the application?
- Nothing Geo-specific. Any user where `admin: true` is set in the database is
- considered an admin with super-user privileges.
+ considered an administrator with super-user privileges.
- See also: [more granular access control](https://gitlab.com/gitlab-org/gitlab/-/issues/18242)
(not Geo-specific).
- Much of Geo’s integration (database replication, for instance) must be
@@ -194,7 +194,7 @@ from [owasp.org](https://owasp.org/).
administrator via SSH, and then back out to the **secondary** node in the same manner.
In particular, this includes the PostgreSQL replication credentials and a secret
key (`db_key_base`) which is used to decrypt certain columns in the database.
- The `db_key_base` secret is stored unencrypted on the filesystem, in
+ The `db_key_base` secret is stored unencrypted on the file system, in
`/etc/gitlab/gitlab-secrets.json`, along with a number of other secrets. There is
no at-rest protection for them.
@@ -217,7 +217,7 @@ from [owasp.org](https://owasp.org/).
- **Secondary** nodes and **primary** nodes interact via HTTP/HTTPS (secured with JSON web
tokens) and via PostgreSQL streaming replication.
-- Within a **primary** node or **secondary** node, the SSOT is the filesystem and the database
+- Within a **primary** node or **secondary** node, the SSOT is the file system and the database
(including Geo tracking database on **secondary** node). The various internal components
are orchestrated to make alterations to these stores.
@@ -231,7 +231,7 @@ from [owasp.org](https://owasp.org/).
### What data is or may need to be encrypted and what key management requirements have been defined?
-- Neither **primary** nodes or **secondary** nodes encrypt Git repository or filesystem data at
+- Neither **primary** nodes or **secondary** nodes encrypt Git repository or file system data at
rest. A subset of database columns are encrypted at rest using the `db_otp_key`.
- A static secret shared across all hosts in a GitLab deployment.
- In transit, data should be encrypted, although the application does permit
@@ -287,5 +287,5 @@ from [owasp.org](https://owasp.org/).
### What application auditing requirements have been defined? How are audit and debug logs accessed, stored, and secured?
-- Structured JSON log is written to the filesystem, and can also be ingested
+- Structured JSON log is written to the file system, and can also be ingested
into a Kibana installation for further analysis.
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index 2c0160ed02a..3b1f60a0f3f 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Troubleshooting Geo **(PREMIUM ONLY)**
+# Troubleshooting Geo **(PREMIUM SELF)**
Setting up Geo requires careful attention to details and sometimes it's easy to
miss a step.
@@ -219,7 +219,7 @@ sudo gitlab-rake gitlab:geo:check
```
- Ensure that you have added the secondary node in the Admin Area of the **primary** node.
- - Ensure that you entered the `external_url` or `gitlab_rails['geo_node_name']` when adding the secondary node in the admin are of the **primary** node.
+ - Ensure that you entered the `external_url` or `gitlab_rails['geo_node_name']` when adding the secondary node in the Admin Area of the **primary** node.
- Prior to GitLab 12.4, edit the secondary node in the Admin Area of the **primary** node and ensure that there is a trailing `/` in the `Name` field.
1. Check returns `Exception: PG::UndefinedTable: ERROR: relation "geo_nodes" does not exist`
@@ -396,6 +396,69 @@ In GitLab 13.4, a seed project is added when GitLab is first installed. This mak
on a new Geo secondary node. There is an [issue to account for seed projects](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5618)
when checking the database.
+### Message: `Synchronization failed - Error syncing repository`
+
+WARNING:
+If large repositories are affected by this problem,
+their resync may take a long time and cause significant load on your Geo nodes,
+storage and network systems.
+
+If you get the error `Synchronization failed - Error syncing repository` along with the following log messages, this indicates that the expected `geo` remote is not present in the `.git/config` file
+of a repository on the secondary Geo node's filesystem:
+
+```json
+{
+ "created": "@1603481145.084348757",
+ "description": "Error received from peer unix:/var/opt/gitlab/gitaly/gitaly.socket",
+ …
+ "grpc_message": "exit status 128",
+ "grpc_status": 13
+}
+{ …
+ "grpc.request.fullMethod": "/gitaly.RemoteService/FindRemoteRootRef",
+ "grpc.request.glProjectPath": "<namespace>/<project>",
+ …
+ "level": "error",
+ "msg": "fatal: 'geo' does not appear to be a git repository
+ fatal: Could not read from remote repository. …",
+}
+```
+
+To solve this:
+
+1. Log into the secondary Geo node.
+
+1. Back up [the `.git` folder](../../repository_storage_types.md#translating-hashed-storage-paths).
+
+1. Optional: [Spot-check](../../troubleshooting/log_parsing.md#find-all-projects-affected-by-a-fatal-git-problem))
+ a few of those IDs whether they indeed correspond
+ to a project with known Geo replication failures.
+ Use `fatal: 'geo'` as the `grep` term and the following API call:
+
+ ```shell
+ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<first_failed_geo_sync_ID>"
+ ```
+
+1. Enter the [Rails console](../../troubleshooting/navigating_gitlab_via_rails_console.md) and run:
+
+ ```ruby
+ failed_geo_syncs = Geo::ProjectRegistry.failed.pluck(:id)
+ failed_geo_syncs.each do |fgs|
+ puts Geo::ProjectRegistry.failed.find(fgs).project_id
+ end
+ ```
+
+1. Run the following commands to reset each project's
+ Geo-related attributes and execute a new sync:
+
+ ```ruby
+ failed_geo_syncs.each do |fgs|
+ registry = Geo::ProjectRegistry.failed.find(fgs)
+ registry.update(resync_repository: true, force_to_redownload_repository: false, repository_retry_count: 0)
+ Geo::RepositorySyncService.new(registry.project).execute
+ end
+ ```
+
### Very large repositories never successfully synchronize on the **secondary** node
GitLab places a timeout on all repository clones, including project imports
@@ -678,19 +741,19 @@ sudo /opt/gitlab/embedded/bin/gitlab-pg-ctl promote
GitLab 12.9 and later are [unaffected by this error](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5147).
-### Two-factor authentication is broken after a failover
+### Message: `ERROR - Replication is not up-to-date` during `gitlab-ctl promotion-preflight-checks`
+
+In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
+this command reports `ERROR - Replication is not up-to-date` even if
+replication is actually up-to-date. This bug was fixed in GitLab 13.8 and
+later.
-The setup instructions for Geo prior to 10.5 failed to replicate the
-`otp_key_base` secret, which is used to encrypt the two-factor authentication
-secrets stored in the database. If it differs between **primary** and **secondary**
-nodes, users with two-factor authentication enabled won't be able to log in
-after a failover.
+### Message: `ERROR - Replication is not up-to-date` during `gitlab-ctl promote-to-primary-node`
-If you still have access to the old **primary** node, you can follow the
-instructions in the
-[Upgrading to GitLab 10.5](../replication/version_specific_updates.md#updating-to-gitlab-105)
-section to resolve the error. Otherwise, the secret is lost and you'll need to
-[reset two-factor authentication for all users](../../../security/two_factor_authentication.md#disabling-2fa-for-everyone).
+In GitLab 13.7 and earlier, if you have a data type with zero items to sync,
+this command reports `ERROR - Replication is not up-to-date` even if
+replication is actually up-to-date. If replication and verification output
+shows that it is complete, you can add `--skip-preflight-checks` to make the command complete promotion. This bug was fixed in GitLab 13.8 and later.
## Expired artifacts
@@ -717,7 +780,7 @@ node's URL matches its external URL.
## Fixing common errors
-This section documents common errors reported in the Admin UI and how to fix them.
+This section documents common errors reported in the Admin Area and how to fix them.
### Geo database configuration file is missing
diff --git a/doc/administration/geo/replication/tuning.md b/doc/administration/geo/replication/tuning.md
index 183180e5ade..a4aad3dec68 100644
--- a/doc/administration/geo/replication/tuning.md
+++ b/doc/administration/geo/replication/tuning.md
@@ -5,11 +5,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Tuning Geo **(PREMIUM ONLY)**
+# Tuning Geo **(PREMIUM SELF)**
## Changing the sync/verification capacity values
-In the Geo admin page at **Admin Area > Geo** (`/admin/geo/nodes`),
+In **Admin Area > Geo** (`/admin/geo/nodes`),
there are several variables that can be tuned to improve performance of Geo:
- Repository sync capacity
diff --git a/doc/administration/geo/replication/updating_the_geo_nodes.md b/doc/administration/geo/replication/updating_the_geo_nodes.md
index ff3a1e8689b..0c68adf162d 100644
--- a/doc/administration/geo/replication/updating_the_geo_nodes.md
+++ b/doc/administration/geo/replication/updating_the_geo_nodes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Updating the Geo nodes **(PREMIUM ONLY)**
+# Updating the Geo nodes **(PREMIUM SELF)**
WARNING:
Read these sections carefully before updating your Geo nodes. Not following
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
index 743b1b384db..7578b6bf61a 100644
--- a/doc/administration/geo/replication/using_a_geo_server.md
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -7,7 +7,7 @@ type: howto
<!-- Please update EE::GitLab::GeoGitAccess::GEO_SERVER_DOCS_URL if this file is moved) -->
-# Using a Geo Server **(PREMIUM ONLY)**
+# Using a Geo Server **(PREMIUM SELF)**
After you set up the [database replication and configure the Geo nodes](../index.md#setup-instructions), use your closest GitLab node as you would a normal standalone GitLab instance.
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index 0d8eba555ab..be2ce0ac2c0 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -5,23 +5,37 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Version specific update instructions
+# Version-specific update instructions
-Check this document if it includes instructions for the version you are updating.
-These steps go together with the [general steps](updating_the_geo_nodes.md#general-update-steps)
+Review this page for update instructions for your version. These steps
+accompany the [general steps](updating_the_geo_nodes.md#general-update-steps)
for updating Geo nodes.
+## Updating to GitLab 13.7
+
+We've detected an issue with the `FetchRemove` call used by Geo secondaries.
+This causes performance issues as we execute reference transaction hooks for
+each updated reference. Delay any upgrade attempts until this is in the
+[13.7.5 patch release.](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3002).
+More details are available [in this issue](https://gitlab.com/gitlab-org/git/-/issues/79).
+
## Updating to GitLab 13.5
-In GitLab 13.5, there is a [regression that prevents viewing a list of container repositories and registries](https://gitlab.com/gitlab-org/gitlab/-/issues/285475) on Geo secondaries. This issue is fixed in GitLab 13.6.1 and later.
+GitLab 13.5 has a [regression that prevents viewing a list of container repositories and registries](https://gitlab.com/gitlab-org/gitlab/-/issues/285475)
+on Geo secondaries. This issue is fixed in GitLab 13.6.1 and later.
## Updating to GitLab 13.3
-In GitLab 13.3, Geo removed the PostgreSQL [Foreign Data Wrapper](https://www.postgresql.org/docs/11/postgres-fdw.html) dependency for the tracking database.
+In GitLab 13.3, Geo removed the PostgreSQL [Foreign Data Wrapper](https://www.postgresql.org/docs/11/postgres-fdw.html)
+dependency for the tracking database.
-The FDW server, user, and the extension will be removed during the upgrade process on each **secondary** node. The GitLab settings related to the FDW in the `/etc/gitlab/gitlab.rb` have been deprecated and can be safely removed.
+The FDW server, user, and the extension will be removed during the upgrade
+process on each secondary node. 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 tracking database where the FDW settings must be removed manually. Enter the PostgreSQL console of that instance and remove them:
+There are some scenarios like using an external PostgreSQL instance for the
+tracking database where the FDW settings must be removed manually. Enter the
+PostgreSQL console of that instance and remove them:
```shell
DROP SERVER gitlab_secondary CASCADE;
@@ -36,7 +50,10 @@ upgrade to GitLab 13.4 or later.
## Updating to GitLab 13.2
-In GitLab 13.2, promoting a secondary node to a primary while the secondary is paused fails. **Do not pause replication before promoting a secondary.** If the node is paused, please resume before promoting. To avoid this issue, upgrade to GitLab 13.4 or later.
+In GitLab 13.2, promoting a secondary node 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,
+upgrade to GitLab 13.4 or later.
## Updating to GitLab 13.0
@@ -59,12 +76,13 @@ GitLab 12.9.0 through GitLab 12.9.3 are affected by [a bug that stops
repository verification](https://gitlab.com/gitlab-org/gitlab/-/issues/213523).
The issue is fixed in GitLab 12.9.4. Upgrade to GitLab 12.9.4 or later.
-By default, GitLab 12.9 will attempt to automatically update the embedded
-PostgreSQL server to 10.12 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. For the recommended procedure, see the
+By default, GitLab 12.9 attempts to update the embedded PostgreSQL server
+version from 9.6 to 10.12, which requires downtime on secondaries while
+reinitializing streaming replication. For the recommended procedure, see the
[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-This can be temporarily disabled by running the following before updating:
+You can temporarily disable this behavior by running the following before
+updating:
```shell
sudo touch /etc/gitlab/disable-postgresql-upgrade
@@ -72,12 +90,13 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.8
-By default, GitLab 12.8 will attempt to automatically update the embedded
-PostgreSQL server to 10.12 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. For the recommended procedure, see
-the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
+By default, GitLab 12.8 attempts to update the embedded PostgreSQL server
+version from 9.6 to 10.12, which requires downtime on secondaries while
+reinitializing streaming replication. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-This can be temporarily disabled by running the following before updating:
+You can temporarily disable this behavior by running the following before
+updating:
```shell
sudo touch /etc/gitlab/disable-postgresql-upgrade
@@ -87,18 +106,17 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
WARNING:
Only upgrade to GitLab 12.7.5 or later. Do not upgrade to versions 12.7.0
-through 12.7.4 because there is [an initialization order
-bug](https://gitlab.com/gitlab-org/gitlab/-/issues/199672) that causes Geo
-**secondaries** to set the incorrect database connection pool size. [The
-fix](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24021) was
+through 12.7.4 because there is [an initialization order bug](https://gitlab.com/gitlab-org/gitlab/-/issues/199672) that causes Geo secondaries to set the incorrect database connection pool size.
+[The fix](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24021) was
shipped in 12.7.5.
-By default, GitLab 12.7 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. For the recommended procedure, see
-the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
+By default, GitLab 12.7 attempts to update the embedded PostgreSQL server
+version from 9.6 to 10.9, which requires downtime on secondaries while
+reinitializing streaming replication. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-This can be temporarily disabled by running the following before updating:
+You can temporarily disable this behavior by running the following before
+updating:
```shell
sudo touch /etc/gitlab/disable-postgresql-upgrade
@@ -106,12 +124,13 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.6
-By default, GitLab 12.6 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. For the recommended procedure, see
-the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
+By default, GitLab 12.6 attempts to update the embedded PostgreSQL server
+version from 9.6 to 10.9, which requires downtime on secondaries while
+reinitializing streaming replication. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-This can be temporarily disabled by running the following before updating:
+You can temporarily disable this behavior by running the following before
+updating:
```shell
sudo touch /etc/gitlab/disable-postgresql-upgrade
@@ -119,12 +138,13 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.5
-By default, GitLab 12.5 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. For the recommended procedure, see
-the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
+By default, GitLab 12.5 attempts to update the embedded PostgreSQL server
+version from 9.6 to 10.9, which requires downtime on secondaries while
+reinitializing streaming replication. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-This can be temporarily disabled by running the following before updating:
+You can temporarily disable this behavior by running the following before
+updating:
```shell
sudo touch /etc/gitlab/disable-postgresql-upgrade
@@ -132,12 +152,13 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.4
-By default, GitLab 12.4 will attempt to automatically update the embedded
-PostgreSQL server to 10.9 from 9.6, which requires downtime on secondaries
-while reinitializing streaming replication. For the recommended procedure, see
-the [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
+By default, GitLab 12.4 attempts to update the embedded PostgreSQL server
+version from 9.6 to 10.9, which requires downtime on secondaries while
+reinitializing streaming replication. For the recommended procedure, see the
+[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-This can be temporarily disabled by running the following before updating:
+You can temporarily disable this behavior by running the following before
+updating:
```shell
sudo touch /etc/gitlab/disable-postgresql-upgrade
@@ -146,9 +167,9 @@ sudo touch /etc/gitlab/disable-postgresql-upgrade
## Updating to GitLab 12.3
WARNING:
-If the existing PostgreSQL server version is 9.6.x, it is recommended to
-upgrade to GitLab 12.4 or later. By default, GitLab 12.3 attempts to update the
-embedded PostgreSQL server from 9.6 to 10.9. In certain circumstances, it will
+If the existing PostgreSQL server version is 9.6.x, we recommend upgrading to
+GitLab 12.4 or later. By default, GitLab 12.3 attempts to update the embedded
+PostgreSQL server version from 9.6 to 10.9. In certain circumstances, it can
fail. For more information, see the
[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
@@ -160,23 +181,23 @@ For the recommended procedure, see the
## Updating to GitLab 12.2
WARNING:
-If the existing PostgreSQL server version is 9.6.x, it is recommended to
-upgrade to GitLab 12.4 or later. By default, GitLab 12.2 attempts to update the
-embedded PostgreSQL server from 9.6 to 10.9. In certain circumstances, it will
+If the existing PostgreSQL server version is 9.6.x, we recommend upgrading to
+GitLab 12.4 or later. By default, GitLab 12.2 attempts to update the embedded
+PostgreSQL server version from 9.6 to 10.9. In certain circumstances, it can
fail. For more information, see the
[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
-Additionally, if the PostgreSQL upgrade does not fail, a successful upgrade
+Additionally, if the PostgreSQL upgrade doesn't fail, a successful upgrade
requires downtime for secondaries while reinitializing streaming replication.
For the recommended procedure, see the
[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
GitLab 12.2 includes the following minor PostgreSQL updates:
-- To version `9.6.14` if you run PostgreSQL 9.6.
-- To version `10.9` if you run PostgreSQL 10.
+- To version `9.6.14`, if you run PostgreSQL 9.6.
+- To version `10.9`, if you run PostgreSQL 10.
-This update will occur even if major PostgreSQL updates are disabled.
+This update occurs even if major PostgreSQL updates are disabled.
Before [refreshing Foreign Data Wrapper during a Geo upgrade](https://docs.gitlab.com/omnibus/update/README.html#run-post-deployment-migrations-and-checks),
restart the Geo tracking database:
@@ -185,14 +206,15 @@ restart the Geo tracking database:
sudo gitlab-ctl restart geo-postgresql
```
-The restart avoids a version mismatch when PostgreSQL tries to load the FDW extension.
+The restart avoids a version mismatch when PostgreSQL tries to load the FDW
+extension.
## Updating to GitLab 12.1
WARNING:
-If the existing PostgreSQL server version is 9.6.x, it is recommended to
-upgrade to GitLab 12.4 or later. By default, GitLab 12.1 attempts to update the
-embedded PostgreSQL server from 9.6 to 10.9. In certain circumstances, it will
+If the existing PostgreSQL server version is 9.6.x, we recommend upgrading to
+GitLab 12.4 or later. By default, GitLab 12.1 attempts to update the embedded
+PostgreSQL server version from 9.6 to 10.9. In certain circumstances, it can
fail. For more information, see the
[Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
@@ -206,419 +228,11 @@ 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).
-The issue is fixed in GitLab 12.1; be sure to upgrade to GitLab 12.1 or later.
+The issue is fixed in GitLab 12.1. Be sure to upgrade to GitLab 12.1 or later.
## Updating to GitLab 11.11
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).
-The issue is fixed in GitLab 12.1; be sure to upgrade to GitLab 12.1 or later.
-
-## Updating to GitLab 10.8
-
-Before 10.8, broadcast messages would not propagate without flushing
-the cache on the **secondary** nodes. This has been fixed in 10.8, but
-requires one last cache flush on each **secondary** node:
-
-```shell
-sudo gitlab-rake cache:clear
-```
-
-## Updating to GitLab 10.6
-
-In 10.4, we started to recommend that you define a password for database user (`gitlab`).
-
-We now require this change as we use this password to enable the Foreign Data Wrapper, as a way to optimize
-the Geo Tracking Database. We are also improving security by disabling the use of **trust**
-authentication method.
-
-1. **(primary)** Login to your **primary** node and run:
-
- ```shell
- gitlab-ctl pg-password-md5 gitlab
- # Enter password: <your_password_here>
- # Confirm password: <your_password_here>
- # fca0b89a972d69f00eb3ec98a5838484
- ```
-
- Copy the generated hash and edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
- postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
-
- # Every node that runs Unicorn or Sidekiq needs to have the database
- # password specified as below.
- # This must be present in all application nodes.
- gitlab_rails['db_password'] = '<your_password_here>'
- ```
-
- Still in the configuration file, locate and remove the `trust_auth_cidr_address`:
-
- ```ruby
- postgresql['trust_auth_cidr_addresses'] = ['127.0.0.1/32','1.2.3.4/32'] # <- Remove this
- ```
-
-1. **(primary)** Reconfigure and restart:
-
- ```shell
- sudo gitlab-ctl reconfigure
- sudo gitlab-ctl restart
- ```
-
-1. **(secondary)** Login to all **secondary** nodes and edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
- postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
-
- # Every node that runs Unicorn or Sidekiq needs to have the database
- # password specified as below.
- # This must be present in all application nodes.
- gitlab_rails['db_password'] = '<your_password_here>'
-
- # Enable Foreign Data Wrapper
- geo_secondary['db_fdw'] = true
-
- # Secondary address in CIDR format, for example '5.6.7.8/32'
- postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']
- ```
-
- Still in the configuration file, locate and remove the `trust_auth_cidr_address`:
-
- ```ruby
- postgresql['trust_auth_cidr_addresses'] = ['127.0.0.1/32','5.6.7.8/32'] # <- Remove this
- ```
-
-1. **(secondary)** Reconfigure and restart:
-
- ```shell
- sudo gitlab-ctl reconfigure
- sudo gitlab-ctl restart
- ```
-
-## Updating to GitLab 10.5
-
-For Geo Disaster Recovery to work with minimum downtime, your **secondary** node
-should use the same set of secrets as the **primary** node. However, setup instructions
-prior to the 10.5 release only synchronized the `db_key_base` secret.
-
-To rectify this error on existing installations, you should **overwrite** the
-contents of `/etc/gitlab/gitlab-secrets.json` on each **secondary** node with the
-contents of `/etc/gitlab/gitlab-secrets.json` on the **primary** node, then run the
-following command on each **secondary** node:
-
-```shell
-sudo gitlab-ctl reconfigure
-```
-
-If you do not perform this step, you may find that two-factor authentication
-[is broken following DR](troubleshooting.md#two-factor-authentication-is-broken-after-a-failover).
-
-To prevent SSH requests to the newly promoted **primary** node from failing
-due to SSH host key mismatch when updating the **primary** node domain's DNS record
-you should perform the step to [Manually replicate **primary** SSH host keys](configuration.md#step-2-manually-replicate-the-primary-nodes-ssh-host-keys) in each
-**secondary** node.
-
-## Updating to GitLab 10.3
-
-### Support for SSH repository synchronization removed
-
-In GitLab 10.2, synchronizing secondaries over SSH was deprecated. In 10.3,
-support is removed entirely. All installations will switch to the HTTP/HTTPS
-cloning method instead. Before updating, ensure that all your Geo nodes are
-configured to use this method and that it works for your installation. In
-particular, ensure that [Git access over HTTP/HTTPS is enabled](configuration.md#step-5-enable-git-access-over-httphttps).
-
-Synchronizing repositories over the public Internet using HTTP is insecure, so
-you should ensure that you have HTTPS configured before updating. Note that
-file synchronization is **also** insecure in these cases!
-
-## Updating to GitLab 10.2
-
-### Secure PostgreSQL replication
-
-Support for TLS-secured PostgreSQL replication has been added. If you are
-currently using PostgreSQL replication across the open internet without an
-external means of securing the connection (e.g., a site-to-site VPN), then you
-should immediately reconfigure your **primary** and **secondary** PostgreSQL instances
-according to the [updated instructions](../setup/database.md).
-
-If you *are* securing the connections externally and wish to continue doing so,
-ensure you include the new option `--sslmode=prefer` in future invocations of
-`gitlab-ctl replicate-geo-database`.
-
-### HTTPS repository sync
-
-Support for replicating repositories and wikis over HTTP/HTTPS has been added.
-Replicating over SSH has been deprecated, and support for this option will be
-removed in a future release.
-
-To switch to HTTP/HTTPS replication, log into the **primary** node as an admin and visit
-**Admin Area > Geo** (`/admin/geo/nodes`). For each **secondary** node listed,
-press the "Edit" button, change the "Repository cloning" setting from
-"SSH (deprecated)" to "HTTP/HTTPS", and press "Save changes". This should take
-effect immediately.
-
-Any new secondaries should be created using HTTP/HTTPS replication - this is the
-default setting.
-
-After you've verified that HTTP/HTTPS replication is working, you should remove
-the now-unused SSH keys from your secondaries, as they may cause problems if the
-**secondary** node if ever promoted to a **primary** node:
-
-1. **(secondary)** Login to **all** your **secondary** nodes and run:
-
- ```ruby
- sudo -u git -H rm ~git/.ssh/id_rsa ~git/.ssh/id_rsa.pub
- ```
-
-### Hashed Storage
-
-WARNING:
-Hashed storage is in **Alpha**. It is considered experimental and not
-production-ready. See [Hashed Storage](../../repository_storage_types.md) for more detail.
-
-If you previously enabled Hashed Storage and migrated all your existing
-projects to Hashed Storage, disabling hashed storage will not migrate projects
-to their previous project based storage path. As such, once enabled and
-migrated we recommend leaving Hashed Storage enabled.
-
-## Updating to GitLab 10.1
-
-WARNING:
-Hashed storage is in **Alpha**. It is considered experimental and not
-production-ready. See [Hashed Storage](../../repository_storage_types.md) for more detail.
-
-[Hashed storage](../../repository_storage_types.md) was introduced in
-GitLab 10.0, and a [migration path](../../raketasks/storage.md) for
-existing repositories was added in GitLab 10.1.
-
-## Updating to GitLab 10.0
-
-In GitLab 10.0 and later, we require all **Geo** systems to [use SSH key lookups via
-the database](../../operations/fast_ssh_key_lookup.md) to avoid having to maintain consistency of the
-`authorized_keys` file for SSH access. Failing to do this will prevent users
-from being able to clone via SSH.
-
-Note that in older versions of Geo, attachments downloaded on the **secondary**
-nodes would be saved to the wrong directory. We recommend that you do the
-following to clean this up.
-
-On the **secondary** Geo nodes, run as root:
-
-```shell
-mv /var/opt/gitlab/gitlab-rails/working /var/opt/gitlab/gitlab-rails/working.old
-mkdir /var/opt/gitlab/gitlab-rails/working
-chmod 700 /var/opt/gitlab/gitlab-rails/working
-chown git:git /var/opt/gitlab/gitlab-rails/working
-```
-
-You may delete `/var/opt/gitlab/gitlab-rails/working.old` any time.
-
-Once this is done, we advise restarting GitLab on the **secondary** nodes for the
-new working directory to be used:
-
-```shell
-sudo gitlab-ctl restart
-```
-
-## Updating from GitLab 9.3 or older
-
-If you started running Geo on GitLab 9.3 or older, we recommend that you
-resync your **secondary** PostgreSQL databases to use replication slots. If you
-started using Geo with GitLab 9.4 or 10.x, no further action should be
-required because replication slots are used by default. However, if you
-started with GitLab 9.3 and updated later, you should still follow the
-instructions below.
-
-When in doubt, it doesn't hurt to do a resync. The easiest way to do this in
-Omnibus is the following:
-
-1. Make sure you have Omnibus GitLab on the **primary** server.
-1. Run `gitlab-ctl reconfigure` and `gitlab-ctl restart postgresql`. This will enable replication slots on the **primary** database.
-1. Check the steps about defining `postgresql['sql_user_password']`, `gitlab_rails['db_password']`.
-1. Make sure `postgresql['max_replication_slots']` matches the number of **secondary** Geo nodes locations.
-1. Install GitLab on the **secondary** server.
-1. Re-run the [database replication process](../setup/database.md#step-3-initiate-the-replication-process).
-
-## Updating to GitLab 9.0
-
-> **IMPORTANT**:
-With GitLab 9.0, the PostgreSQL version is updated to 9.6 and manual steps are
-required to update the **secondary** nodes and keep the Streaming Replication
-working. Downtime is required, so plan ahead.
-
-The following steps apply only if you update from a 8.17 GitLab version to
-9.0+. For previous versions, update to GitLab 8.17 first before attempting to
-update to 9.0+.
-
----
-
-Make sure to follow the steps in the exact order as they appear below and pay
-extra attention in what node (either **primary** or **secondary**) you execute them! Each step
-is prepended with the relevant node for better clarity:
-
-1. **(secondary)** Log in to **all** your **secondary** nodes and stop all services:
-
- ```ruby
- sudo gitlab-ctl stop
- ```
-
-1. **(secondary)** Make a backup of the `recovery.conf` file on **all**
- **secondary** nodes to preserve PostgreSQL's credentials:
-
- ```shell
- sudo cp /var/opt/gitlab/postgresql/data/recovery.conf /var/opt/gitlab/
- ```
-
-1. **(primary)** Update the **primary** node to GitLab 9.0 following the
- [regular update docs](../../../update/README.md). At the end of the
- update, the **primary** node will be running with PostgreSQL 9.6.
-
-1. **(primary)** To prevent a de-synchronization of the repository replication,
- stop all services except `postgresql` as we will use it to re-initialize the
- **secondary** node's database:
-
- ```shell
- sudo gitlab-ctl stop
- sudo gitlab-ctl start postgresql
- ```
-
-1. **(secondary)** Run the following steps on each of the **secondary** nodes:
-
- 1. **(secondary)** Stop all services:
-
- ```shell
- sudo gitlab-ctl stop
- ```
-
- 1. **(secondary)** Prevent running database migrations:
-
- ```shell
- sudo touch /etc/gitlab/skip-auto-migrations
- ```
-
- 1. **(secondary)** Move the old database to another directory:
-
- ```shell
- sudo mv /var/opt/gitlab/postgresql{,.bak}
- ```
-
- 1. **(secondary)** Update to GitLab 9.0 following the [regular update docs](../../../update/README.md).
- At the end of the update, the node will be running with PostgreSQL 9.6.
-
- 1. **(secondary)** Make sure all services are up:
-
- ```shell
- sudo gitlab-ctl start
- ```
-
- 1. **(secondary)** Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
- 1. **(secondary)** Run the PostgreSQL upgrade command:
-
- ```shell
- sudo gitlab-ctl pg-upgrade
- ```
-
- 1. **(secondary)** See the stored credentials for the database that you will
- need to re-initialize the replication:
-
- ```shell
- sudo grep -s primary_conninfo /var/opt/gitlab/recovery.conf
- ```
-
- 1. **(secondary)** Save the snippet below in a file, let's say `/tmp/replica.sh`. Modify the
- embedded paths if necessary:
-
- ```shell
- #!/bin/bash
-
- PORT="5432"
- USER="gitlab_replicator"
- echo ---------------------------------------------------------------
- echo WARNING: Make sure this script is run from the secondary server
- echo ---------------------------------------------------------------
- echo
- echo Enter the IP or FQDN of the primary PostgreSQL server
- read HOST
- echo Enter the password for $USER@$HOST
- read -s PASSWORD
- echo Enter the required sslmode
- read SSLMODE
-
- echo Stopping PostgreSQL and all GitLab services
- sudo service gitlab stop
- sudo service postgresql stop
-
- echo Backing up postgresql.conf
- sudo -u postgres mv /var/opt/gitlab/postgresql/data/postgresql.conf /var/opt/gitlab/postgresql/
-
- echo Cleaning up old cluster directory
- sudo -u postgres rm -rf /var/opt/gitlab/postgresql/data
-
- echo Starting base backup as the replicator user
- echo Enter the password for $USER@$HOST
- sudo -u postgres /opt/gitlab/embedded/bin/pg_basebackup -h $HOST -D /var/opt/gitlab/postgresql/data -U gitlab_replicator -v -x -P
-
- echo Writing recovery.conf file
- sudo -u postgres bash -c "cat > /var/opt/gitlab/postgresql/data/recovery.conf <<- _EOF1_
- standby_mode = 'on'
- primary_conninfo = 'host=$HOST port=$PORT user=$USER password=$PASSWORD sslmode=$SSLMODE'
- _EOF1_
- "
-
- echo Restoring postgresql.conf
- sudo -u postgres mv /var/opt/gitlab/postgresql/postgresql.conf /var/opt/gitlab/postgresql/data/
-
- echo Starting PostgreSQL
- sudo service postgresql start
- ```
-
- 1. **(secondary)** Run the recovery script using the credentials from the
- previous step:
-
- ```shell
- sudo bash /tmp/replica.sh
- ```
-
- 1. **(secondary)** Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
- 1. **(secondary)** Start all services:
-
- ```shell
- sudo gitlab-ctl start
- ```
-
- 1. **(secondary)** Repeat the steps for the remaining **secondary** nodes.
-
-1. **(primary)** After all **secondary** nodes are updated, start all services in
- **primary** node:
-
- ```shell
- sudo gitlab-ctl start
- ```
-
-### Update tracking database on **secondary** node
-
-After updating a **secondary** node, you might need to run migrations on the
-tracking database. The tracking database was added in GitLab 9.1, and is
-required in GitLab 10.0 and later.
-
-1. Run database migrations on tracking database:
-
- ```shell
- sudo gitlab-rake geo:db:migrate
- ```
-
-1. Repeat this step for each **secondary** node.
+The issue is fixed in GitLab 12.1. Be sure to upgrade to GitLab 12.1 or later.
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index 95f67b20ab5..1272e7d1419 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo database replication **(PREMIUM ONLY)**
+# Geo database replication **(PREMIUM SELF)**
NOTE:
If your GitLab installation uses external (not managed by Omnibus) PostgreSQL
@@ -472,33 +472,31 @@ information, see [High Availability with Omnibus GitLab](../../postgresql/replic
## Patroni support
Support for Patroni is intended to replace `repmgr` as a
-[highly availabile PostgreSQL solution](../../postgresql/replication_and_failover.md)
+[highly available PostgreSQL solution](../../postgresql/replication_and_failover.md)
on the primary node, but it can also be used for PostgreSQL HA on a secondary
-node.
+site.
Starting with GitLab 13.5, Patroni is available for _experimental_ use with Geo
-primary and secondary nodes. Due to its experimental nature, Patroni support is
+primary and secondary sites. Due to its experimental nature, Patroni support is
subject to change without notice.
This experimental implementation has the following limitations:
-- Whenever a new Leader is elected, the PgBouncer instance must be reconfigured
- to point to the new Leader.
-- Whenever a new Leader is elected on the primary node, the Standby Leader on
- the secondary needs to be reconfigured to point to the new Leader.
- Whenever `gitlab-ctl reconfigure` runs on a Patroni Leader instance, there's a
chance the node will be demoted due to the required short-time restart. To
avoid this, you can pause auto-failover by running `gitlab-ctl patroni pause`.
- After a reconfigure, it unpauses on its own.
+ After a reconfigure, it resumes on its own.
-For instructions about how to set up Patroni on the primary node, see the
+For instructions about how to set up Patroni on the primary site, see the
[PostgreSQL replication and failover with Omnibus GitLab](../../postgresql/replication_and_failover.md#patroni) page.
-If you are currently using `repmgr` on your Geo primary, see [these instructions](#migrating-from-repmgr-to-patroni) for migrating from `repmgr` to Patroni.
+If you are currently using `repmgr` on your Geo primary site, see [these instructions](#migrating-from-repmgr-to-patroni) for migrating from `repmgr` to Patroni.
-A production-ready and secure setup requires at least three Patroni instances on
-the primary site, and a similar configuration on the secondary sites. Be sure to
-use password credentials and other database best practices.
+A production-ready and secure setup requires at least three Consul nodes, three
+Patroni nodes, one internal load-balancing node on the primary site, and a similar
+configuration for the secondary site. The internal load balancer provides a single
+endpoint for connecting to the Patroni cluster's leader whenever a new leader is
+elected. Be sure to use [password credentials](../..//postgresql/replication_and_failover.md#database-authorization-for-patroni) and other database best practices.
Similar to `repmgr`, using Patroni on a secondary node is optional.
@@ -555,7 +553,51 @@ Leader instance**:
gitlab-ctl reconfigure
```
-### Step 2. Configure a Standby cluster on the secondary site
+### Step 2. Configure the internal load balancer on the primary site
+
+To avoid reconfiguring the Standby Leader on the secondary site whenever a new
+Leader is elected on the primary site, we'll need to set up a TCP internal load
+balancer which will give a single endpoint for connecting to the Patroni
+cluster's Leader.
+
+The Omnibus GitLab packages do not include a Load Balancer. Here's how you
+could do it with [HAProxy](https://www.haproxy.org/).
+
+The following IPs and names will be used as an example:
+
+- `10.6.0.21`: Patroni 1 (`patroni1.internal`)
+- `10.6.0.21`: Patroni 2 (`patroni2.internal`)
+- `10.6.0.22`: Patroni 3 (`patroni3.internal`)
+
+```plaintext
+global
+ log /dev/log local0
+ log localhost local1 notice
+ log stdout format raw local0
+
+defaults
+ log global
+ default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
+
+frontend internal-postgresql-tcp-in
+ bind *:5000
+ mode tcp
+ option tcplog
+
+ default_backend postgresql
+
+backend postgresql
+ option httpchk
+ http-check expect status 200
+
+ server patroni1.internal 10.6.0.21:5432 maxconn 100 check port 8008
+ server patroni2.internal 10.6.0.22:5432 maxconn 100 check port 8008
+ server patroni3.internal 10.6.0.23.195:5432 maxconn 100 check port 8008
+```
+
+Refer to your preferred Load Balancer's documentation for further guidance.
+
+### Step 3. Configure a Standby cluster on the secondary site
NOTE:
If you are converting a secondary site to a Patroni Cluster, you must start
@@ -589,8 +631,8 @@ For each Patroni instance on the secondary site:
patroni['enable'] = false
patroni['standby_cluster']['enable'] = true
- patroni['standby_cluster']['host'] = 'PATRONI_PRIMARY_LEADER_IP' # This needs to be changed anytime the primary Leader changes
- patroni['standby_cluster']['port'] = 5432
+ patroni['standby_cluster']['host'] = 'INTERNAL_LOAD_BALANCER_PRIMARY_IP'
+ patroni['standby_cluster']['port'] = INTERNAL_LOAD_BALANCER_PRIMARY_PORT
patroni['standby_cluster']['primary_slot_name'] = 'geo_secondary' # Or the unique replication slot name you setup before
patroni['replication_password'] = 'PLAIN_TEXT_POSTGRESQL_REPLICATION_PASSWORD'
patroni['use_pg_rewind'] = true
@@ -642,10 +684,11 @@ With Patroni it's now possible to support that. In order to migrate the existing
1. Make sure you have a Consul cluster setup on the secondary (similar to how you set it up on the primary).
1. [Configure a permanent replication slot](#step-1-configure-patroni-permanent-replication-slot-on-the-primary-site).
-1. [Configure a Standby Cluster](#step-2-configure-a-standby-cluster-on-the-secondary-site)
+1. [Configure the internal load balancer](#step-2-configure-the-internal-load-balancer-on-the-primary-site).
+1. [Configure a Standby Cluster](#step-3-configure-a-standby-cluster-on-the-secondary-site)
on that single node machine.
-
-You will end up with a "Standby Cluster" with a single node. That allows you to later on add additional patroni nodes
+
+You will end up with a "Standby Cluster" with a single node. That allows you to later on add additional Patroni nodes
by following the same instructions above.
## Troubleshooting
diff --git a/doc/administration/geo/setup/external_database.md b/doc/administration/geo/setup/external_database.md
index 1fb41fbb53a..8e7d8049467 100644
--- a/doc/administration/geo/setup/external_database.md
+++ b/doc/administration/geo/setup/external_database.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo with external PostgreSQL instances **(PREMIUM ONLY)**
+# Geo with external PostgreSQL instances **(PREMIUM SELF)**
This document is relevant if you are using a PostgreSQL instance that is *not
managed by Omnibus*. This includes cloud-managed instances like AWS RDS, or
diff --git a/doc/administration/git_annex.md b/doc/administration/git_annex.md
index e21a8ac7e84..07b7b1730e3 100644
--- a/doc/administration/git_annex.md
+++ b/doc/administration/git_annex.md
@@ -38,7 +38,7 @@ very fast file copying tool.
## GitLab git-annex Configuration
-`git-annex` is disabled by default in GitLab. Below you will find the
+`git-annex` is disabled by default in GitLab. Below are the
configuration options required to enable it.
### Requirements
@@ -60,7 +60,7 @@ sudo yum install epel-release && sudo yum install git-annex
### Configuration for Omnibus packages
For Omnibus GitLab packages, only one configuration setting is needed.
-The Omnibus package will internally set the correct options in all locations.
+The Omnibus package internally sets the correct options in all locations.
1. In `/etc/gitlab/gitlab.rb` add the following line:
@@ -148,15 +148,15 @@ To example.com:group/project.git
ok
```
-Your files can be found in the `master` branch, but you'll notice that there
-are more branches created by the `annex sync` command.
+Your files can be found in the `master` branch, but more branches are created
+by the `annex sync` command.
-Git Annex will also create a new directory at `.git/annex/` and will record the
+Git Annex creates a new directory at `.git/annex/` and records the
tracked files in the `.git/config` file. The files you assign to be tracked
-with `git-annex` will not affect the existing `.git/config` records. The files
+with `git-annex` don't affect the existing `.git/config` records. The files
are turned into symbolic links that point to data in `.git/annex/objects/`.
-The `debian.iso` file in the example will contain the symbolic link:
+The `debian.iso` file in the example contain the symbolic link:
```plaintext
.git/annex/objects/ZW/1k/SHA256E-s82701--6384039733b5035b559efd5a2e25a493ab6e09aabfd5162cc03f6f0ec238429d.png/SHA256E-s82701--6384039733b5035b559efd5a2e25a493ab6e09aabfd5162cc03f6f0ec238429d.iso
@@ -167,7 +167,7 @@ repository.
---
-Downloading a single large file is also very simple:
+You can download a single large file with these commands:
```shell
git clone git@gitlab.example.com:group/project.git
@@ -185,7 +185,7 @@ git annex sync --content # sync Git branches and download all the large files
```
By using `git-annex` without GitLab, anyone that can access the server can also
-access the files of all projects, but GitLab Annex ensures that you can only
+access the files of all projects. GitLab Annex ensures that you can only
access files of projects you have access to (developer, maintainer, or owner role).
## How it works
diff --git a/doc/administration/git_protocol.md b/doc/administration/git_protocol.md
index ca4fa0549d0..acc05a77bee 100644
--- a/doc/administration/git_protocol.md
+++ b/doc/administration/git_protocol.md
@@ -6,7 +6,7 @@ type: reference
description: "Set and configure Git protocol v2"
---
-# Configuring Git Protocol v2
+# Configuring Git Protocol v2 **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46555) in GitLab 11.4.
> - [Temporarily disabled](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55769) in GitLab 11.5.8, 11.6.6, 11.7.1, and 11.8+.
@@ -29,11 +29,11 @@ server to accept the `GIT_PROTOCOL` environment.
In installations using [GitLab Helm Charts](https://docs.gitlab.com/charts/)
and [All-in-one Docker image](https://docs.gitlab.com/omnibus/docker/), the SSH
-service is already configured to accept the `GIT_PROTOCOL` environment and users
+service is already configured to accept the `GIT_PROTOCOL` environment. Users
need not do anything more.
-For Omnibus GitLab and installations from source, you have to manually update
-the SSH configuration of your server by adding the line below to the `/etc/ssh/sshd_config` file:
+For Omnibus GitLab and installations from source, update
+the SSH configuration of your server manually by adding this line to the `/etc/ssh/sshd_config` file:
```plaintext
AcceptEnv GIT_PROTOCOL
@@ -120,5 +120,7 @@ production environment, you can use the following Prometheus query:
sum(rate(gitaly_git_protocol_requests_total[1m])) by (grpc_method,git_protocol,grpc_service)
```
+<!-- This link sporadically returns a 503 during automated link checking but is correct -->
+
You can view what Git protocol versions are being used on GitLab.com at
<https://dashboards.gitlab.com/d/pqlQq0xik/git-protocol-versions>.
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 9577fb40abe..f02b9b8fc1a 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -19,7 +19,7 @@ In the Gitaly documentation:
- [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell).
- [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse).
-GitLab end users do not have direct access to Gitaly. Gitaly only manages Git
+GitLab end users do not have direct access to Gitaly. Gitaly manages only Git
repository access for GitLab. Other types of GitLab data aren't accessed using Gitaly.
<!-- vale gitlab.FutureTense = NO -->
@@ -40,7 +40,7 @@ The following is a high-level architecture overview of how Gitaly is used.
## Configure Gitaly
-The Gitaly service itself is configured via a [TOML configuration file](reference.md).
+The Gitaly service itself is configured by using a [TOML configuration file](reference.md).
To change Gitaly settings:
@@ -91,8 +91,8 @@ When running Gitaly on its own server, note the following regarding GitLab versi
- From GitLab 11.4, Gitaly was able to serve all Git requests without requiring a shared NFS mount
for Git repository data, except for the
[Elasticsearch indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer).
-- From GitLab 11.8, the Elasticsearch indexer uses Gitaly for data access as well. NFS can still be
- leveraged for redundancy on block-level Git data, but only has to be mounted on the Gitaly
+- From GitLab 11.8, the Elasticsearch indexer also uses Gitaly for data access. NFS can still be
+ leveraged for redundancy on block-level Git data, but should be mounted only on the Gitaly
servers.
- From GitLab 11.8 to 12.2, it is possible to use Elasticsearch in a Gitaly setup that doesn't use
NFS. To use Elasticsearch in these versions, the
@@ -121,7 +121,7 @@ The following list depicts the network architecture of Gitaly:
- GitLab Shell.
- Elasticsearch indexer.
- Gitaly itself.
-- A Gitaly server must be able to make RPC calls **to itself** via its own
+- A Gitaly server must be able to make RPC calls **to itself** by using its own
`(Gitaly address, Gitaly token)` pair as specified in `/config/gitlab.yml`.
- Authentication is done through a static token which is shared among the Gitaly and GitLab Rails
nodes.
@@ -497,16 +497,16 @@ gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem"
gitaly['key_path'] = "/etc/gitlab/ssl/key.pem"
```
-`path` can only be included for storage shards on the local Gitaly server.
+`path` can be included only for storage shards on the local Gitaly server.
If it's excluded, default Git storage directory is used for that storage shard.
### Disable Gitaly where not required (optional)
-If you are running Gitaly [as a remote service](#run-gitaly-on-its-own-server), you may want to
-disable the local Gitaly service that runs on your GitLab server by default and have it only running
-where required.
+If you run Gitaly [as a remote service](#run-gitaly-on-its-own-server), consider
+disabling the local Gitaly service that runs on your GitLab server by default, and run it
+only where required.
-Disabling Gitaly on the GitLab instance only makes sense when you run GitLab in a custom cluster configuration, where
+Disabling Gitaly on the GitLab instance makes sense only when you run GitLab in a custom cluster configuration, where
Gitaly runs on a separate machine from the GitLab instance. Disabling Gitaly on all machines in the cluster is not
a valid configuration (some machines much act as Gitaly servers).
@@ -538,7 +538,7 @@ To disable Gitaly on a GitLab server:
> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/3160) in GitLab 13.6, outgoing TLS connections to GitLab provide client certificates if configured.
Gitaly supports TLS encryption. To communicate with a Gitaly instance that listens for secure
-connections, you must use `tls://` URL scheme in the `gitaly_address` of the corresponding
+connections, use the `tls://` URL scheme in the `gitaly_address` of the corresponding
storage entry in the GitLab configuration.
Gitaly provides the same server certificates as client certificates in TLS
@@ -724,7 +724,7 @@ Gitaly Go process. Some examples of things that are implemented in `gitaly-ruby`
We recommend:
-- At least 300MB memory per worker.
+- At least 300 MB memory per worker.
- No more than one worker per core.
NOTE:
@@ -752,7 +752,7 @@ settings:
gitaly['ruby_num_workers'] = 4
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
**For installations from source**
@@ -810,9 +810,42 @@ You can observe the behavior of this queue using the Gitaly logs and Prometheus:
- `gitaly_rate_limiting_seconds`.
NOTE:
-Though the name of the Prometheus metric contains `rate_limiting`, it is a concurrency limiter, not
-a rate limiter. If a Gitaly client makes 1000 requests in a row very quickly, concurrency does not
-exceed 1 and the concurrency limiter has no effect.
+Although the name of the Prometheus metric contains `rate_limiting`, it's a concurrency limiter, not
+a rate limiter. If a Gitaly client makes 1,000 requests in a row very quickly, concurrency doesn't
+exceed 1, and the concurrency limiter has no effect.
+
+## Background Repository Optimization
+
+Empty directories and unneeded config settings may accumulate in a repository and
+slow down Git operations. Gitaly can schedule a daily background task with a maximum duration
+to clean up these items and improve performance.
+
+WARNING:
+This is an experimental feature and may place significant load on the host while running.
+Make sure to schedule this during off-peak hours and keep the duration short (for example, 30-60 minutes).
+
+**For Omnibus GitLab**
+
+Edit `/etc/gitlab/gitlab.rb` and add:
+
+```ruby
+gitaly['daily_maintenance_start_hour'] = 4
+gitaly['daily_maintenance_start_minute'] = 30
+gitaly['daily_maintenance_duration'] = '30m'
+gitaly['daily_maintenance_storages'] = ["default"]
+```
+
+**For installations from source**
+
+Edit `/home/git/gitaly/config.toml` and add:
+
+```toml
+[daily_maintenance]
+start_hour = 4
+start_minute = 30
+duration = '30m'
+storages = ["default"]
+```
## Rotate Gitaly authentication token
@@ -847,7 +880,7 @@ see something like this:
{enforced="true",status="ok"} 4424.985419441742
```
-There may also be other numbers with rate 0. We only care about the non-zero numbers.
+There may also be other numbers with rate 0. We care only about the non-zero numbers.
The only non-zero number should have `enforced="true",status="ok"`. If you have other non-zero
numbers, something is wrong in your configuration.
@@ -906,7 +939,7 @@ After the new token is set, and all services involved have been restarted, you w
- `status="would be ok"`.
- `status="denied"`.
-After the new token has been picked up by all Gitaly clients and Gitaly servers, the
+After the new token is picked up by all Gitaly clients and Gitaly servers, the
**only non-zero rate** should be `enforced="false",status="would be ok"`.
### Disable "auth transitioning" mode
@@ -935,12 +968,13 @@ Note that `enforced="true"` means that authentication is being enforced.
## Direct Git access bypassing Gitaly
-While it is possible to access Gitaly repositories stored on disk directly with a Git client,
-it is not advisable because Gitaly is being continuously improved and changed. Theses improvements may invalidate assumptions, resulting in performance degradation, instability, and even data loss.
+GitLab doesn't advise directly accessing Gitaly repositories stored on disk with
+a Git client, because Gitaly is being continuously improved and changed. These
+improvements may invalidate assumptions, resulting in performance degradation, instability, and even data loss.
Gitaly has optimizations, such as the
[`info/refs` advertisement cache](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md),
-that rely on Gitaly controlling and monitoring access to repositories via the
+that rely on Gitaly controlling and monitoring access to repositories by using the
official gRPC interface. Likewise, Praefect has optimizations, such as fault
tolerance and distributed reads, that depend on the gRPC interface and
database to determine repository state.
@@ -979,11 +1013,11 @@ lookup. Even when Gitaly is able to re-use an already-running `git` process (for
a commit), you still have:
- The cost of a network roundtrip to Gitaly.
-- Within Gitaly, a write/read roundtrip on the Unix pipes that connect Gitaly to the `git` process.
+- Inside Gitaly, a write/read roundtrip on the Unix pipes that connect Gitaly to the `git` process.
Using GitLab.com to measure, we reduced the number of Gitaly calls per request until the loss of
Rugged's efficiency was no longer felt. It also helped that we run Gitaly itself directly on the Git
-file severs, rather than via NFS mounts. This gave us a speed boost that counteracted the negative
+file severs, rather than by using NFS mounts. This gave us a speed boost that counteracted the negative
effect of not using Rugged anymore.
Unfortunately, other deployments of GitLab could not remove NFS like we did on GitLab.com, and they
@@ -1018,7 +1052,7 @@ The result of these checks is cached.
To see if GitLab can access the repository file system directly, we use the following heuristic:
- Gitaly ensures that the file system has a metadata file in its root with a UUID in it.
-- Gitaly reports this UUID to GitLab via the `ServerInfo` RPC.
+- Gitaly reports this UUID to GitLab by using the `ServerInfo` RPC.
- GitLab Rails tries to read the metadata file directly. If it exists, and if the UUID's match,
assume we have direct access.
@@ -1085,7 +1119,7 @@ app nodes).
### Client side gRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
-client has its own log file which may contain useful information when
+client has its own log file which may contain debugging information when
you are seeing Gitaly errors. You can control the log level of the
gRPC client with the `GRPC_LOG_LEVEL` environment variable. The
default level is `WARN`.
@@ -1100,7 +1134,7 @@ sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
Sometimes you need to find out which Gitaly RPC created a particular Git process.
-One method for doing this is via `DEBUG` logging. However, this needs to be enabled
+One method for doing this is by using `DEBUG` logging. However, this needs to be enabled
ahead of time and the logs produced are quite verbose.
A lightweight method for doing this correlation is by inspecting the environment
@@ -1111,7 +1145,7 @@ PID=<Git process ID>
sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=
```
-Please note that this method is not reliable for `git cat-file` processes because Gitaly
+This method isn't reliable for `git cat-file` processes, because Gitaly
internally pools and re-uses those across RPCs.
### Observing `gitaly-ruby` traffic
@@ -1127,7 +1161,7 @@ not differentiate between `gitaly-ruby` and other RPCs, but in practice
(as of GitLab 11.9), all gRPC calls made by Gitaly itself are internal
calls from the main Gitaly process to one of its `gitaly-ruby` sidecars.
-Assuming your `grpc_client_handled_total` counter only observes Gitaly,
+Assuming your `grpc_client_handled_total` counter observes only Gitaly,
the following query shows you RPCs are (most likely) internally
implemented as calls to `gitaly-ruby`:
@@ -1137,16 +1171,19 @@ sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0
### Repository changes fail with a `401 Unauthorized` error
-If you're running Gitaly on its own server and notice that users can
-successfully clone and fetch repositories (via both SSH and HTTPS), but can't
-push to them or make changes to the repository in the web UI without getting a
-`401 Unauthorized` message, then it's possible Gitaly is failing to authenticate
-with the Gitaly client due to having the [wrong secrets file](#configure-gitaly-servers).
+If you run Gitaly on its own server and notice these conditions:
+
+- Users can successfully clone and fetch repositories by using both SSH and HTTPS.
+- Users can't push to repositories, or receive a `401 Unauthorized` message when attempting to
+ make changes to them in the web UI.
+
+Gitaly may be failing to authenticate with the Gitaly client because it has the
+[wrong secrets file](#configure-gitaly-servers).
Confirm the following are all true:
- When any user performs a `git push` to any repository on this Gitaly server, it
- fails with the following error (note the `401 Unauthorized`):
+ fails with a `401 Unauthorized` error:
```shell
remote: GitLab: 401 Unauthorized
@@ -1157,8 +1194,8 @@ Confirm the following are all true:
- When any user adds or modifies a file from the repository using the GitLab
UI, it immediately fails with a red `401 Unauthorized` banner.
-- Creating a new project and [initializing it with a README](../../gitlab-basics/create-project.md#blank-projects)
- successfully creates the project but doesn't create the README.
+- Creating a new project and [initializing it with a README](../../user/project/working_with_projects.md#blank-projects)
+ successfully creates the project, but doesn't create the README.
- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server)
on a Gitaly client and reproducing the error, you get `401` errors
when reaching the `/api/v4/internal/allowed` endpoint:
@@ -1229,11 +1266,11 @@ update the secrets file on the Gitaly server to match the Gitaly client, then
### Command line tools cannot connect to Gitaly
-If you are having trouble connecting to a Gitaly server with command line (CLI) tools,
+If you can't connect to a Gitaly server with command line (CLI) tools,
and certain actions result in a `14: Connect Failed` error message,
-it means that gRPC cannot reach your Gitaly server.
+gRPC cannot reach your Gitaly server.
-Verify that you can reach Gitaly via TCP:
+Verify you can reach Gitaly by using TCP:
```shell
sudo gitlab-rake gitlab:tcp_check[GITALY_SERVER_IP,GITALY_LISTEN_PORT]
@@ -1269,8 +1306,8 @@ If this error occurs even though file permissions are correct, it's likely that
the Gitaly server is experiencing
[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
-Please ensure that the Gitaly clients and servers are synchronized and use an NTP time
-server to keep them synchronized if possible.
+Ensure the Gitaly clients and servers are synchronized, and use an NTP time
+server to keep them synchronized, if possible.
### Praefect
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index fe8b3e5f566..45f478b8d16 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -5,12 +5,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Gitaly Cluster **(CORE ONLY)**
+# Gitaly Cluster **(FREE SELF)**
[Gitaly](index.md), the service that provides storage for Git repositories, can
be run in a clustered configuration to increase fault tolerance. In this
configuration, every Git repository is stored on every Gitaly node in the
-cluster. Multiple clusters (or shards) can be configured.
+cluster. Multiple clusters (or storage shards) can be configured.
NOTE:
Technical support for Gitaly clusters is limited to GitLab Premium and Ultimate
@@ -21,7 +21,7 @@ component for running a Gitaly Cluster.
![Architecture diagram](img/praefect_architecture_v12_10.png)
-Using a Gitaly Cluster increase fault tolerance by:
+Using a Gitaly Cluster increases fault tolerance by:
- Replicating write operations to warm standby Gitaly nodes.
- Detecting Gitaly node failures.
@@ -53,7 +53,7 @@ Gitaly Cluster supports:
- Reporting of possible data loss if replication queue is non-empty.
- Marking repositories as [read only](#read-only-mode) if data loss is detected to prevent data inconsistencies.
-Follow the [HA Gitaly epic](https://gitlab.com/groups/gitlab-org/-/epics/1489)
+Follow the [Gitaly Cluster epic](https://gitlab.com/groups/gitlab-org/-/epics/1489)
for improvements including
[horizontally distributing reads](https://gitlab.com/groups/gitlab-org/-/epics/2013).
@@ -65,7 +65,7 @@ Gitaly Cluster and [Geo](../geo/index.md) both provide redundancy. However the r
not aware when Gitaly Cluster is used.
- Geo provides [replication](../geo/index.md) and [disaster recovery](../geo/disaster_recovery/index.md) for
an entire instance of GitLab. Users know when they are using Geo for
- [replication](../geo/index.md). Geo [replicates multiple datatypes](../geo/replication/datatypes.md#limitations-on-replicationverification),
+ [replication](../geo/index.md). Geo [replicates multiple data types](../geo/replication/datatypes.md#limitations-on-replicationverification),
including Git data.
The following table outlines the major differences between Gitaly Cluster and Geo:
@@ -80,23 +80,65 @@ For more information, see:
- [Gitaly architecture](index.md#architecture).
- Geo [use cases](../geo/index.md#use-cases) and [architecture](../geo/index.md#architecture).
-## Cluster or shard
+## Where Gitaly Cluster fits
+
+GitLab accesses [repositories](../../user/project/repository/index.md) through the configured
+[repository storages](../repository_storage_paths.md). Each new repository is stored on one of the
+repository storages based on their configured weights. Each repository storage is either:
+
+- A Gitaly storage served directly by Gitaly. These map to a directory on the file system of a
+ Gitaly node.
+- A [virtual storage](#virtual-storage-or-direct-gitaly-storage) served by Praefect. A virtual
+ storage is a cluster of Gitaly storages that appear as a single repository storage.
+
+Virtual storages are a feature of Gitaly Cluster. They support replicating the repositories to
+multiple storages for fault tolerance. Virtual storages can improve performance by distributing
+requests across Gitaly nodes. Their distributed nature makes it viable to have a single repository
+storage in GitLab to simplify repository management.
+
+## Components of Gitaly Cluster
+
+Gitaly Cluster consists of multiple components:
+
+- [Load balancer](#load-balancer) for distributing requests and providing fault-tolerant access to
+ Praefect nodes.
+- [Praefect](#praefect) nodes for managing the cluster and routing requests to Gitaly nodes.
+- [PostgreSQL database](#postgresql) for persisting cluster metadata and [PgBouncer](#pgbouncer),
+ recommended for pooling Praefect's database connections.
+- [Gitaly](index.md) nodes to provide repository storage and Git access.
+
+![Cluster example](img/cluster_example_v13_3.png)
+
+In this example:
+
+- Repositories are stored on a virtual storage called `storage-1`.
+- Three Gitaly nodes provide `storage-1` access: `gitaly-1`, `gitaly-2`, and `gitaly-3`.
+- The three Gitaly nodes store data on their file systems.
+
+### Virtual storage or direct Gitaly storage
Gitaly supports multiple models of scaling:
- Clustering using Gitaly Cluster, where each repository is stored on multiple Gitaly nodes in the
cluster. Read requests are distributed between repository replicas and write requests are
- broadcast to repository replicas.
-- Sharding using [repository storage paths](../repository_storage_paths.md), where each repository
- is stored on the assigned Gitaly node. All requests are routed to this node.
+ broadcast to repository replicas. GitLab accesses virtual storage.
+- Direct access to Gitaly storage using [repository storage paths](../repository_storage_paths.md),
+ where each repository is stored on the assigned Gitaly node. All requests are routed to this node.
+
+The following is Gitaly set up to use direct access to Gitaly instead of Gitaly Cluster:
+
+![Shard example](img/shard_example_v13_3.png)
-| Cluster | Shard |
-|:--------------------------------------------------|:----------------------------------------------|
-| ![Cluster example](img/cluster_example_v13_3.png) | ![Shard example](img/shard_example_v13_3.png) |
+In this example:
-Generally, Gitaly Cluster can replace sharded configurations, at the expense of additional storage
-needed to store each repository on multiple Gitaly nodes. The benefit of using Gitaly Cluster over
-sharding is:
+- Each repository is stored on one of three Gitaly storages: `storage-1`, `storage-2`,
+ or `storage-3`.
+- Each storage is serviced by a Gitaly node.
+- The three Gitaly nodes store data in three separate hashed storage locations.
+
+Generally, virtual storage with Gitaly Cluster can replace direct Gitaly storage configurations, at
+the expense of additional storage needed to store each repository on multiple Gitaly nodes. The
+benefit of using Gitaly Cluster over direct Gitaly storage is:
- Improved fault tolerance, because each Gitaly node has a copy of every repository.
- Improved resource utilization, reducing the need for over-provisioning for shard-specific peak
@@ -105,7 +147,7 @@ sharding is:
replicas.
- Simpler management, because all Gitaly nodes are identical.
-Under some workloads, CPU and memory requirements may require a large fleet of Gitaly nodes and it
+Under some workloads, CPU and memory requirements may require a large fleet of Gitaly nodes. It
can be uneconomical to have one to one replication factor.
A hybrid approach can be used in these instances, where each shard is configured as a smaller
@@ -157,18 +199,18 @@ You need the IP/host address for each node.
1. `LOAD_BALANCER_SERVER_ADDRESS`: the IP/host address of the load balancer
1. `POSTGRESQL_SERVER_ADDRESS`: the IP/host address of the PostgreSQL server
1. `PRAEFECT_HOST`: the IP/host address of the Praefect server
-1. `GITALY_HOST`: the IP/host address of each Gitaly server
+1. `GITALY_HOST_*`: the IP or host address of each Gitaly server
1. `GITLAB_HOST`: the IP/host address of the GitLab server
If you are using a cloud provider, you can look up the addresses for each server through your cloud provider's management console.
-If you are using Google Cloud Platform, SoftLayer, or any other vendor that provides a virtual private cloud (VPC) you can use the private addresses for each cloud instance (corresponds to “internal address†for Google Cloud Platform) for `PRAEFECT_HOST`, `GITALY_HOST`, and `GITLAB_HOST`.
+If you are using Google Cloud Platform, SoftLayer, or any other vendor that provides a virtual private cloud (VPC) you can use the private addresses for each cloud instance (corresponds to “internal address†for Google Cloud Platform) for `PRAEFECT_HOST`, `GITALY_HOST_*`, and `GITLAB_HOST`.
#### Secrets
The communication between components is secured with different secrets, which
are described below. Before you begin, generate a unique secret for each, and
-make note of it. This makes it easy to replace these placeholder tokens
+make note of it. This enables you to replace these placeholder tokens
with secure tokens as you complete the setup process.
1. `GITLAB_SHELL_SECRET_TOKEN`: this is used by Git hooks to make callback HTTP
@@ -260,13 +302,12 @@ this, set the corresponding IP or host address of the PgBouncer instance in
- `praefect['database_port']`, for the port.
Because PgBouncer manages resources more efficiently, Praefect still requires a
-direct connection to the PostgreSQL database because it uses
+direct connection to the PostgreSQL database. It uses the
[LISTEN](https://www.postgresql.org/docs/11/sql-listen.html)
-functionality that is [not supported](https://www.pgbouncer.org/features.html) by
+feature that is [not supported](https://www.pgbouncer.org/features.html) by
PgBouncer with `pool_mode = transaction`.
-
-Therefore, `praefect['database_host_no_proxy']` and `praefect['database_port_no_proxy']`
-should be set to a direct connection and not a PgBouncer connection.
+Set `praefect['database_host_no_proxy']` and `praefect['database_port_no_proxy']`
+to a direct connection, and not a PgBouncer connection.
Save the changes to `/etc/gitlab/gitlab.rb` and
[reconfigure Praefect](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -424,32 +465,43 @@ application server, or a Gitaly node.
Praefect when communicating with Gitaly nodes in the cluster. This token is
distinct from the `PRAEFECT_EXTERNAL_TOKEN`.
- Replace `GITALY_HOST` with the IP/host address of the each Gitaly node.
+ Replace `GITALY_HOST_*` with the IP or host address of the each Gitaly node.
More Gitaly nodes can be added to the cluster to increase the number of
replicas. More clusters can also be added for very large GitLab instances.
+ NOTE:
+ When adding additional Gitaly nodes to a virtual storage, all storage names
+ within that virtual storage must be unique. Additionally, all Gitaly node
+ addresses referenced in the Praefect configuration must be unique.
+
```ruby
# Name of storage hash must match storage name in git_data_dirs on GitLab
- # server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
+ # server ('default') and in git_data_dirs on Gitaly nodes ('gitaly-1')
praefect['virtual_storages'] = {
'default' => {
- 'gitaly-1' => {
- 'address' => 'tcp://GITALY_HOST:8075',
- 'token' => 'PRAEFECT_INTERNAL_TOKEN',
- },
- 'gitaly-2' => {
- 'address' => 'tcp://GITALY_HOST:8075',
- 'token' => 'PRAEFECT_INTERNAL_TOKEN'
- },
- 'gitaly-3' => {
- 'address' => 'tcp://GITALY_HOST:8075',
- 'token' => 'PRAEFECT_INTERNAL_TOKEN'
+ 'nodes' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://GITALY_HOST_1:8075',
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN',
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://GITALY_HOST_2:8075',
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://GITALY_HOST_3:8075',
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
+ }
}
}
}
```
+ NOTE:
+ In [GitLab 13.8 and earlier](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4988),
+ Gitaly nodes were configured directly under the virtual storage, and not under the `nodes` key.
+
1. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2013) in GitLab 13.1 and later, enable [distribution of reads](#distributed-reads).
1. Save the changes to `/etc/gitlab/gitlab.rb` and [reconfigure
@@ -640,7 +692,7 @@ because we rely on Praefect to route operations correctly.
Particular attention should be shown to:
- The `gitaly['auth_token']` configured in this section must match the `token`
- value under `praefect['virtual_storages']` on the Praefect node. This was set
+ value under `praefect['virtual_storages']['nodes']` on the Praefect node. This was set
in the [previous section](#praefect). This document uses the placeholder
`PRAEFECT_INTERNAL_TOKEN` throughout.
- The storage names in `git_data_dirs` configured in this section must match the
@@ -774,7 +826,7 @@ configuration.
### Load Balancer
-In a highly available Gitaly configuration, a load balancer is needed to route
+In a fault-tolerant Gitaly configuration, a load balancer is needed to route
internal traffic from the GitLab application to the Praefect nodes. The
specifics on which load balancer to use or the exact configuration is beyond the
scope of the GitLab documentation.
@@ -786,7 +838,7 @@ addition to the GitLab nodes. Some requests handled by
process. `gitaly-ruby` uses the Gitaly address set in the GitLab server's
`git_data_dirs` setting to make this connection.
-We hope that if you’re managing HA systems like GitLab, you have a load balancer
+We hope that if you’re managing fault-tolerant systems like GitLab, you have a load balancer
of choice already. Some examples include [HAProxy](https://www.haproxy.org/)
(open-source), [Google Internal Load Balancer](https://cloud.google.com/load-balancing/docs/internal/),
[AWS Elastic Load Balancer](https://aws.amazon.com/elasticloadbalancing/), F5
@@ -878,7 +930,7 @@ Particular attention should be shown to:
You need to replace:
- `PRAEFECT_HOST` with the IP address or hostname of the Praefect node
- - `GITALY_HOST` with the IP address or hostname of each Gitaly node
+ - `GITALY_HOST_*` with the IP address or hostname of each Gitaly node
```ruby
prometheus['scrape_configs'] = [
@@ -896,9 +948,9 @@ Particular attention should be shown to:
'job_name' => 'praefect-gitaly',
'static_configs' => [
'targets' => [
- 'GITALY_HOST:9236', # gitaly-1
- 'GITALY_HOST:9236', # gitaly-2
- 'GITALY_HOST:9236', # gitaly-3
+ 'GITALY_HOST_1:9236', # gitaly-1
+ 'GITALY_HOST_2:9236', # gitaly-2
+ 'GITALY_HOST_3:9236', # gitaly-3
]
]
}
@@ -960,14 +1012,14 @@ To get started quickly:
gitlab-ctl reconfigure
```
-1. Set the Grafana admin password. This command prompts you to enter a new
+1. Set the Grafana administrator password. This command prompts you to enter a new
password:
```shell
gitlab-ctl set-grafana-password
```
-1. In your web browser, open `/-/grafana` (e.g.
+1. In your web browser, open `/-/grafana` (such as
`https://gitlab.example.com/-/grafana`) on your GitLab server.
Login using the password you set, and the username `admin`.
@@ -975,7 +1027,7 @@ To get started quickly:
1. Go to **Explore** and query `gitlab_build_info` to verify that you are
getting metrics from all your machines.
-Congratulations! You've configured an observable highly available Praefect
+Congratulations! You've configured an observable fault-tolerant Praefect
cluster.
## Distributed reads
@@ -983,18 +1035,12 @@ cluster.
> - 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.
> - [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.
Praefect supports distribution of read operations across Gitaly nodes that are
configured for the virtual node.
-The feature is disabled by default. To enable distributed reads, the `gitaly_distributed_reads`
-[feature flag](../feature_flags.md) must be enabled in a Ruby console:
-
-```ruby
-Feature.enable(:gitaly_distributed_reads)
-```
-
-If enabled, all RPCs marked with `ACCESSOR` option like
+All RPCs marked with `ACCESSOR` option like
[GetBlob](https://gitlab.com/gitlab-org/gitaly/-/blob/v12.10.6/proto/blob.proto#L16)
are redirected to an up to date and healthy Gitaly node.
@@ -1025,9 +1071,8 @@ Praefect guarantees eventual consistency by replicating all writes to secondary
after the write to the primary Gitaly node has happened.
Praefect can instead provide strong consistency by creating a transaction and writing
-changes to all Gitaly nodes at once. Strong consistency is currently in
-[alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga) and not enabled by
-default. If enabled, transactions are only available for a subset of RPCs. For more
+changes to all Gitaly nodes at once.
+If enabled, transactions are only available for a subset of RPCs. For more
information, see the [strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189).
To enable strong consistency:
@@ -1077,7 +1122,7 @@ replication factor offers better redundancy and distribution of read workload, b
in a higher storage cost. By default, Praefect replicates repositories to every storage in a
virtual storage.
-### Variable replication factor
+### Configure replication factors
WARNING:
The feature is not production ready yet. After you set a replication factor, you can't unset it
@@ -1088,36 +1133,46 @@ strategy is not production ready yet.
Praefect supports configuring a replication factor on a per-repository basis, by assigning
specific storage nodes to host a repository.
-[In an upcoming release](https://gitlab.com/gitlab-org/gitaly/-/issues/3362), we intend to
-support configuring a default replication factor for a virtual storage. The default replication factor
-is applied to every newly-created repository.
-
-Prafect does not store the actual replication factor, but assigns enough storages to host the repository
+Praefect does not store the actual replication factor, but assigns enough storages to host the repository
so the desired replication factor is met. If a storage node is later removed from the virtual storage,
the replication factor of repositories assigned to the storage is decreased accordingly.
-The only way to configure a repository's replication factor is the `set-replication-factor`
-sub-command. `set-replication-factor` automatically assigns or unassigns random storage nodes as necessary to
-reach the desired replication factor. The repository's primary node is always assigned
-first and is never unassigned.
+You can configure:
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -repository <relative-path> -replication-factor <replication-factor>
-```
+- A default replication factor for each virtual storage that is applied to newly-created repositories.
+ The configuration is added to the `/etc/gitlab/gitlab.rb` file:
-- `-virtual-storage` is the virtual storage the repository is located in.
-- `-repository` is the repository's relative path in the storage.
-- `-replication-factor` is the desired replication factor of the repository. The minimum value is
- `1`, as the primary needs a copy of the repository. The maximum replication factor is the number of
- storages in the virtual storage.
+ ```ruby
+ praefect['virtual_storages'] = {
+ 'default' => {
+ 'default_replication_factor' => 1,
+ # ...
+ }
+ }
+ ```
-On success, the assigned host storages are printed. For example:
+- A replication factor for an existing repository using the `set-replication-factor` sub-command.
+ `set-replication-factor` automatically assigns or unassigns random storage nodes as
+ necessary to reach the desired replication factor. The repository's primary node is
+ always assigned first and is never unassigned.
-```shell
-$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -repository @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2
+ ```shell
+ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -repository <relative-path> -replication-factor <replication-factor>
+ ```
-current assignments: gitaly-1, gitaly-2
-```
+ - `-virtual-storage` is the virtual storage the repository is located in.
+ - `-repository` is the repository's relative path in the storage.
+ - `-replication-factor` is the desired replication factor of the repository. The minimum value is
+ `1`, as the primary needs a copy of the repository. The maximum replication factor is the number of
+ storages in the virtual storage.
+
+ On success, the assigned host storages are printed. For example:
+
+ ```shell
+ $ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -repository @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2
+
+ current assignments: gitaly-1, gitaly-2
+ ```
## Automatic failover and leader election
@@ -1171,8 +1226,8 @@ To enable writes again, an administrator can:
### Check for data loss
-The Praefect `dataloss` sub-command identifies replicas that are likely to be outdated. This is
-useful for identifying potential data loss after a failover. The following parameters are
+The Praefect `dataloss` sub-command identifies replicas that are likely to be outdated. This can help
+identify potential data loss after a failover. The following parameters are
available:
- `-virtual-storage` that specifies which virtual storage to check. The default behavior is to
@@ -1196,7 +1251,7 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
```
Repositories which have assigned storage nodes that contain an outdated copy of the repository are listed
-in the output. A number of useful information is printed for each repository:
+in the output. This information is printed for each repository:
- A repository's relative path to the storage directory identifies each repository and groups the related
information.
@@ -1213,7 +1268,7 @@ in the output. A number of useful information is printed for each repository:
Whether a replica is assigned to host the repository is listed with each replica's status. `assigned host` is printed
next to replicas which are assigned to store the repository. The text is omitted if the replica contains a copy of
-the repository but is not assigned to store the repository. Such replicas won't be kept in-sync by Praefect but may
+the repository but is not assigned to store the repository. Such replicas aren't kept in-sync by Praefect, but may
act as replication sources to bring assigned replicas up to date.
Example output:
@@ -1282,7 +1337,7 @@ To check a project's repository checksums across on all Gitaly nodes, run the
### Enable writes or accept data loss
-Praefect provides the following subcommands to re-enable writes:
+Praefect provides the following sub-commands to re-enable writes:
- In GitLab 13.2 and earlier, `enable-writes` to re-enable virtual storage for writes after data
recovery attempts.
@@ -1324,7 +1379,7 @@ These tools reconcile the outdated repositories to bring them fully up to date a
Praefect automatically reconciles repositories that are not up to date. By default, this is done every
five minutes. For each outdated repository on a healthy Gitaly node, the Praefect picks a
-random, fully up to date replica of the repository on another healthy Gitaly node to replicate from. A
+random, fully up-to-date replica of the repository on another healthy Gitaly node to replicate from. A
replication job is scheduled only if there are no other replication jobs pending for the target
repository.
@@ -1363,10 +1418,10 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
If your GitLab instance already has repositories on single Gitaly nodes, these aren't migrated to
Gitaly Cluster automatically.
-Project repositories may be moved from one storage location using the [Project repository storage moves API](../../api/project_repository_storage_moves.md):
+Project repositories may be moved from one storage location using the [Project repository storage moves API](../../api/project_repository_storage_moves.md). Note that this API cannot move all repository types. For moving other repositories types, see:
-NOTE:
-The Project repository storage moves API [cannot move all repository types](../../api/project_repository_storage_moves.md#limitations).
+- [Snippet repository storage moves API](../../api/snippet_repository_storage_moves.md).
+- [Group repository storage moves API](../../api/group_repository_storage_moves.md).
To move repositories to Gitaly Cluster:
@@ -1383,11 +1438,13 @@ To move repositories to Gitaly Cluster:
- The moves are in progress. Re-query the repository move until it completes successfully.
- The moves have failed. Most failures are temporary and are solved by rescheduling the move.
-1. Once the moves are complete, [query projects](../../api/projects.md#list-all-projects)
+1. After the moves are complete, [query projects](../../api/projects.md#list-all-projects)
using the API to confirm that all projects have moved. No projects should be returned
with `repository_storage` field set to the old storage.
-In a similar way, you can move Snippet repositories using the [Snippet repository storage moves API](../../api/snippet_repository_storage_moves.md):
+In a similar way, you can move other repository types by using the
+[Snippet repository storage moves API](../../api/snippet_repository_storage_moves.md) **(FREE SELF)**
+or the [Groups repository storage moves API](../../api/group_repository_storage_moves.md) **(PREMIUM SELF)**.
## Debugging Praefect
diff --git a/doc/administration/gitaly/reference.md b/doc/administration/gitaly/reference.md
index 5a004d97220..5105b9ed0d4 100644
--- a/doc/administration/gitaly/reference.md
+++ b/doc/administration/gitaly/reference.md
@@ -95,13 +95,13 @@ key_path = '/home/git/key.pem'
### Storage
-GitLab repositories are grouped into directories known as "storages"
-(e.g., `/home/git/repositories`) containing bare repositories managed
-by GitLab with names (e.g., `default`).
+GitLab repositories are grouped into directories known as storages, such as
+`/home/git/repositories`. They contain bare repositories managed
+by GitLab with names, such as `default`.
These names and paths are also defined in the `gitlab.yml` configuration file of
-GitLab. When you run Gitaly on the same machine as GitLab, which is the default
-and recommended configuration, storage paths defined in Gitaly's `config.toml`
+GitLab. When you run Gitaly on the same machine as GitLab (the default
+and recommended configuration) storage paths defined in Gitaly's `config.toml`
must match those in `gitlab.yml`.
| Name | Type | Required | Description |
@@ -232,9 +232,9 @@ The following values configure logging in Gitaly under the `[logging]` section.
| ---- | ---- | -------- | ----------- |
| `format` | string | no | Log format: `text` or `json`. Default: `text`. |
| `level` | string | no | Log level: `debug`, `info`, `warn`, `error`, `fatal`, or `panic`. Default: `info`. |
-| `sentry_dsn` | string | no | Sentry DSN for exception monitoring. |
+| `sentry_dsn` | string | no | Sentry DSN (Data Source Name) for exception monitoring. |
| `sentry_environment` | string | no | [Sentry Environment](https://docs.sentry.io/product/sentry-basics/environments/) for exception monitoring. |
-| `ruby_sentry_dsn` | string | no | Sentry DSN for `gitaly-ruby` exception monitoring. |
+| `ruby_sentry_dsn` | string | no | Sentry DSN (Data Source Name) for `gitaly-ruby` exception monitoring. |
While the main Gitaly application logs go to `stdout`, there are some extra log
files that go to a configured directory, like the GitLab Shell logs.
diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md
index 178fc438df2..8f369a05fbf 100644
--- a/doc/administration/housekeeping.md
+++ b/doc/administration/housekeeping.md
@@ -49,7 +49,7 @@ It is ultimately performed by the Gitaly RPC `FetchIntoObjectPool`.
This is the current call stack by which it is invoked:
1. `Repositories::HousekeepingService#execute_gitlab_shell_gc`
-1. `GitGarbageCollectWorker#perform`
+1. `Projects::GitGarbageCollectWorker#perform`
1. `Projects::GitDeduplicationService#fetch_from_source`
1. `ObjectPool#fetch`
1. `ObjectPoolService#fetch`
diff --git a/doc/administration/img/impersonated_audit_events_v13_8.png b/doc/administration/img/impersonated_audit_events_v13_8.png
new file mode 100644
index 00000000000..0a8548d515d
--- /dev/null
+++ b/doc/administration/img/impersonated_audit_events_v13_8.png
Binary files differ
diff --git a/doc/administration/img/time_zone_settings.png b/doc/administration/img/time_zone_settings.png
new file mode 100644
index 00000000000..e735a8bc5ec
--- /dev/null
+++ b/doc/administration/img/time_zone_settings.png
Binary files differ
diff --git a/doc/administration/index.md b/doc/administration/index.md
index f071fde2faa..e5f20e3ba05 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
description: 'Learn how to install, configure, update, and maintain your GitLab instance.'
---
-# Administrator documentation **(CORE ONLY)**
+# Administrator documentation **(FREE SELF)**
Learn how to administer your self-managed GitLab instance.
@@ -17,7 +17,7 @@ GitLab has two product distributions available through [different subscriptions]
You can [install either GitLab CE or GitLab EE](https://about.gitlab.com/install/ce-or-ee/).
However, the features you have access to depend on your chosen [subscription](https://about.gitlab.com/pricing/).
-GitLab Community Edition installations have access only to Core features.
+GitLab Community Edition installations have access only to Free features.
Non-administrator users can't access GitLab administration tools and settings.
@@ -32,7 +32,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Installing GitLab
-- [Install](../install/README.md): Requirements, directory structures, and installation methods.
+- [Install](../install/index.md): Requirements, directory structures, and installation methods.
- [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers.
- [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only).
- [Reference architectures](reference_architectures/index.md): Add additional resources to support more users.
@@ -80,6 +80,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
emails with S/MIME.
- [Enabling and disabling features flags](feature_flags.md): how to enable and
disable GitLab features deployed behind feature flags.
+- [Application settings cache expiry interval](application_settings_cache.md)
#### Customizing GitLab appearance
@@ -91,7 +92,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Maintaining GitLab
-- [Rake tasks](../raketasks/README.md): Perform various tasks for maintenance, backups, automatic webhooks setup, and more.
+- [Rake tasks](../raketasks/index.md): Perform various tasks for maintenance, backups, automatic webhooks setup, and more.
- [Backup and restore](../raketasks/backup_restore.md): Backup and restore your GitLab instance.
- [Operations](operations/index.md): Keeping GitLab up and running (clean up Redis sessions, moving repositories, Sidekiq MemoryKiller, Puma).
- [Restart GitLab](restart_gitlab.md): Learn how to restart GitLab and its components.
@@ -101,14 +102,15 @@ Learn how to install, configure, update, and maintain your GitLab instance.
#### Updating GitLab
- [GitLab versions and maintenance policy](../policy/maintenance.md): Understand GitLab versions and releases (Major, Minor, Patch, Security), as well as update recommendations.
-- [Update GitLab](../update/README.md): Update guides to upgrade your installation to a new version.
-- [Upgrading without downtime](../update/README.md#upgrading-without-downtime): Upgrade to a newer major, minor, or patch version of GitLab without taking your GitLab instance offline.
+- [GitLab in maintenance mode](maintenance_mode/index.md): Put GitLab in maintenance mode.
+- [Update GitLab](../update/index.md): Update guides to upgrade your installation to a new version.
+- [Upgrading without downtime](../update/index.md#upgrading-without-downtime): Upgrade to a newer major, minor, or patch version of GitLab without taking your GitLab instance offline.
- [Migrate your GitLab CI/CD data to another version of GitLab](../migrate_ci_to_ce/README.md): If you have an old GitLab installation (older than 8.0), follow this guide to migrate your existing GitLab CI/CD data to another version of GitLab.
### Upgrading or downgrading GitLab
-- [Upgrade from GitLab CE to GitLab EE](../update/README.md#upgrading-between-editions): learn how to upgrade GitLab Community Edition to GitLab Enterprise Editions.
-- [Downgrade from GitLab EE to GitLab CE](../downgrade_ee_to_ce/README.md): Learn how to downgrade GitLab Enterprise Editions to Community Edition.
+- [Upgrade from GitLab CE to GitLab EE](../update/index.md#upgrading-between-editions): learn how to upgrade GitLab Community Edition to GitLab Enterprise Editions.
+- [Downgrade from GitLab EE to GitLab CE](../downgrade_ee_to_ce/index.md): Learn how to downgrade GitLab Enterprise Editions to Community Edition.
### GitLab platform integrations
@@ -152,8 +154,8 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Package Registry administration
-- [Container Registry](packages/container_registry.md): Configure Container Registry with GitLab.
-- [Package Registry](packages/index.md): Enable GitLab to act as an NPM Registry and a Maven Repository.
+- [Container Registry](packages/container_registry.md): Configure GitLab to act as a registry for containers.
+- [Package Registry](packages/index.md): Enable GitLab to act as a registry for packages.
- [Dependency Proxy](packages/dependency_proxy.md): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages.
### Repository settings
@@ -168,7 +170,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Continuous Integration settings
- [Enable/disable GitLab CI/CD](../ci/enable_or_disable_ci.md#site-wide-admin-setting): Enable or disable GitLab CI/CD for your instance.
-- [GitLab CI/CD admin settings](../user/admin_area/settings/continuous_integration.md): Enable or disable Auto DevOps site-wide and define the artifacts' max size and expiration time.
+- [GitLab CI/CD administration settings](../user/admin_area/settings/continuous_integration.md): Enable or disable Auto DevOps site-wide and define the artifacts' max size and expiration time.
- [External Pipeline Validation](external_pipeline_validation.md): Enable, disable and configure external pipeline validation.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job logs](job_logs.md): Information about the job logs.
@@ -186,7 +188,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Git configuration options
-- [Server hooks](server_hooks.md): Server hooks (on the filesystem) for when webhooks aren't enough.
+- [Server hooks](server_hooks.md): Server hooks (on the file system) for when webhooks aren't enough.
- [Git LFS configuration](lfs/index.md): Learn how to configure LFS for GitLab.
- [Housekeeping](housekeeping.md): Keep your Git repositories tidy and fast.
- [Configuring Git Protocol v2](git_protocol.md): Git protocol version 2 support.
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index a3452a1a605..27e8b13812f 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -134,6 +134,15 @@ It's possible that this limit will be changed to a lower number in the future.
- **Max size:** ~1 million characters / ~1 MB
+## Size of commit titles and descriptions
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292039) in GitLab 13.9
+
+Commits with arbitrarily large messages may be pushed to GitLab, but when
+displaying commits, titles (the first line of the commit message) will be
+limited to 1KiB, and descriptions (the rest of the message) will be limited to
+1MiB.
+
## Number of issues in the milestone overview
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39453) in GitLab 12.10.
@@ -156,8 +165,6 @@ Read more in the [CI documentation](../ci/yaml/README.md#processing-git-pushes).
## Retention of activity history
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21164) in GitLab 8.12.
-
Activity history for projects and individuals' profiles was limited to one year until [GitLab 11.4](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52246) when it was extended to two years, and in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/33840) to three years.
## Number of embedded metrics
@@ -258,9 +265,11 @@ each time a new pipeline is created. An active pipeline is any pipeline in one o
If a new pipeline would cause the total number of jobs to exceed the limit, the pipeline
will fail with a `job_activity_limit_exceeded` error.
-- On GitLab.com different [limits are defined per plan](../user/gitlab_com/index.md#gitlab-cicd) and they affect all projects under that plan.
-- On [GitLab Starter](https://about.gitlab.com/pricing/#self-managed) tier or higher self-managed installations, this limit is defined under a `default` plan that affects all projects.
- This limit is disabled (`0`) by default.
+- GitLab SaaS subscribers have different limits [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
+ and they affect all projects under that plan.
+- On [GitLab Premium](https://about.gitlab.com/pricing/) self-managed or
+ higher installations, this limit is defined under a `default` plan that affects all
+ projects. This limit is disabled (`0`) by default.
To set this limit on a self-managed installation, run the following in the
[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
@@ -283,7 +292,7 @@ any job with an [`environment`](../ci/environments/index.md) specified. The numb
of deployments in a pipeline is checked at pipeline creation. Pipelines that have
too many deployments fail with a `deployments_limit_exceeded` error.
-The default limit is 500 for all [self-managed and GitLab.com plans](https://about.gitlab.com/pricing/).
+The default limit is 500 for all [GitLab self-managed and SaaS plans](https://about.gitlab.com/pricing/).
To change the limit on a self-managed installation, change the `default` plan's limit with the following
[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session) command:
@@ -307,8 +316,11 @@ checked each time a new subscription is created.
If a new subscription would cause the total number of subscription to exceed the
limit, the subscription will be considered invalid.
-- On GitLab.com different [limits are defined per plan](../user/gitlab_com/index.md#gitlab-cicd) and they affect all projects under that plan.
-- On [GitLab Starter](https://about.gitlab.com/pricing/#self-managed) tier or higher self-managed installations, this limit is defined under a `default` plan that affects all projects. By default, there is a limit of `2` subscriptions.
+- GitLab SaaS subscribers have different limits [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
+ and they affect all projects under that plan.
+- On [GitLab Premium](https://about.gitlab.com/pricing/) self-managed
+ or higher installations, this limit is defined under a `default` plan that
+ affects all projects. By default, there is a limit of `2` subscriptions.
To set this limit on a self-managed installation, run the following in the
[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
@@ -328,11 +340,11 @@ checked each time a new pipeline schedule is created. If a new pipeline schedule
would cause the total number of pipeline schedules to exceed the limit, the
pipeline schedule will not be created.
-On GitLab.com, different limits are [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
+GitLab SaaS subscribers have different limits [defined per plan](../user/gitlab_com/index.md#gitlab-cicd),
and they affect all projects under that plan.
-On self-managed instances ([GitLab Starter](https://about.gitlab.com/pricing/#self-managed)
-or higher tiers), this limit is defined under a `default` plan that affects all
+On [GitLab Premium](https://about.gitlab.com/pricing/) self-managed or
+higher installations, this limit is defined under a `default` plan that affects all
projects. By default, there is a limit of `10` pipeline schedules.
To set this limit on a self-managed installation, run the following in the
@@ -406,7 +418,7 @@ setting is used:
| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) |
| `ci_max_artifact_size_trace` | 0 |
-For example, to set the `ci_max_artifact_size_junit` limit to 10MB on a self-managed
+For example, to set the `ci_max_artifact_size_junit` limit to 10 MB on a self-managed
installation, run the following in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
```ruby
@@ -577,7 +589,7 @@ On GitLab.com, the maximum file size for a package that's uploaded to the [GitLa
- Conan: 5GB
- Generic: 5GB
- Maven: 5GB
-- NPM: 5GB
+- npm: 5GB
- NuGet: 5GB
- PyPI: 5GB
@@ -590,7 +602,7 @@ To set this limit on a self-managed installation, run the following in the
# For Conan Packages
Plan.default.actual_limits.update!(conan_max_file_size: 100.megabytes)
-# For NPM Packages
+# For npm Packages
Plan.default.actual_limits.update!(npm_max_file_size: 100.megabytes)
# For NuGet Packages
@@ -610,3 +622,15 @@ Plan.default.actual_limits.update!(generic_packages_max_file_size: 100.megabytes
```
Set the limit to `0` to allow any file size.
+
+### Package versions returned
+
+When asking for versions of a given NuGet package name, the GitLab Package Registry returns a maximum of 300 versions.
+
+## Branch retargeting on merge **(FREE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
+
+If a branch is merged while open merge requests still point to it, GitLab can
+retarget merge requests pointing to the now-merged branch. To learn more, read
+[Branch retargeting on merge](../user/project/merge_requests/getting_started.md#branch-retargeting-on-merge).
diff --git a/doc/administration/instance_review.md b/doc/administration/instance_review.md
index 8f33ddf3ca5..56a305fa4da 100644
--- a/doc/administration/instance_review.md
+++ b/doc/administration/instance_review.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Instance Review
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6995) in [GitLab Core](https://about.gitlab.com/pricing/) 11.3.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6995) in [GitLab Free](https://about.gitlab.com/pricing/) 11.3.
If you run a medium-sized self-managed instance (50+ users) of a free version of GitLab,
[either Community Edition or unlicensed Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/),
diff --git a/doc/administration/integration/kroki.md b/doc/administration/integration/kroki.md
index dead5640873..5e458399773 100644
--- a/doc/administration/integration/kroki.md
+++ b/doc/administration/integration/kroki.md
@@ -1,4 +1,10 @@
-# Kroki diagrams **(CORE ONLY)**
+---
+stage: Create
+group: Ecosystem
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Kroki diagrams **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241744) in GitLab 13.7.
@@ -24,6 +30,8 @@ The **Kroki URL** is the hostname of the server running the container.
The [`yuzutech/kroki`](https://hub.docker.com/r/yuzutech/kroki) image contains the following diagrams libraries out-of-the-box:
+<!-- vale gitlab.Spelling = NO -->
+
- [Bytefield](https://bytefield-svg.deepsymmetry.org/)
- [Ditaa](http://ditaa.sourceforge.net)
- [Erd](https://github.com/BurntSushi/erd)
@@ -37,6 +45,8 @@ The [`yuzutech/kroki`](https://hub.docker.com/r/yuzutech/kroki) image contains t
- [Vega-Lite](https://github.com/vega/vega-lite)
- [WaveDrom](https://wavedrom.com/)
+<!-- vale gitlab.Spelling = YES -->
+
If you want to use additional diagram libraries,
read the [Kroki installation](https://docs.kroki.io/kroki/setup/install/#_images) to learn how to start Kroki companion containers.
@@ -138,8 +148,12 @@ Rel(banking_system, mainframe, "Uses")
![C4 PlantUML diagram](../img/kroki_c4_diagram.png)
+<!-- vale gitlab.Spelling = NO -->
+
**Nomnoml**
+<!-- vale gitlab.Spelling = YES -->
+
```plaintext
[nomnoml]
....
@@ -159,4 +173,4 @@ Rel(banking_system, mainframe, "Uses")
....
```
-![Nomnoml diagram](../img/kroki_nomnoml_diagram.png)
+![Diagram](../img/kroki_nomnoml_diagram.png)
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index cd61dc9a2bf..dbbe17cccc8 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -5,18 +5,18 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# PlantUML & GitLab
+# PlantUML & GitLab **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8537) in GitLab 8.16.
When [PlantUML](https://plantuml.com) integration is enabled and configured in
-GitLab we are able to create simple diagrams in AsciiDoc and Markdown documents
+GitLab you can create diagrams in AsciiDoc and Markdown documents
created in snippets, wikis, and repositories.
## PlantUML Server
-Before you can enable PlantUML in GitLab; you need to set up your own PlantUML
-server that will generate the diagrams.
+Before you can enable PlantUML in GitLab; set up your own PlantUML
+server to generate the diagrams.
### Docker
@@ -26,12 +26,11 @@ With Docker, you can just run a container like this:
docker run -d --name plantuml -p 8080:8080 plantuml/plantuml-server:tomcat
```
-The **PlantUML URL** will be the hostname of the server running the container.
+The **PlantUML URL** is the hostname of the server running the container.
-When running GitLab in Docker, it will need to have access to the PlantUML container.
-The easiest way to achieve that is by using [Docker Compose](https://docs.docker.com/compose/).
-
-A simple `docker-compose.yml` file would be:
+When running GitLab in Docker, it must have access to the PlantUML container.
+You can achieve that by using [Docker Compose](https://docs.docker.com/compose/).
+A basic `docker-compose.yml` file could contain:
```yaml
version: "3"
@@ -47,13 +46,12 @@ services:
container_name: plantuml
```
-In this scenario, PlantUML will be accessible for GitLab at the URL
+In this scenario, PlantUML is accessible to GitLab at the URL
`http://plantuml:8080/`.
### Debian/Ubuntu
-Installing and configuring your
-own PlantUML server is easy in Debian/Ubuntu distributions using Tomcat.
+You can also install and configure a PlantUML server in Debian/Ubuntu distributions using Tomcat.
First you need to create a `plantuml.war` file from the source code:
@@ -64,8 +62,7 @@ cd plantuml-server
mvn package
```
-The above sequence of commands will generate a WAR file that can be deployed
-using Tomcat:
+The above sequence of commands generates a `.war` file you can deploy with Tomcat:
```shell
sudo apt-get install tomcat8
@@ -74,17 +71,18 @@ sudo chown tomcat8:tomcat8 /var/lib/tomcat8/webapps/plantuml.war
sudo service tomcat8 restart
```
-Once the Tomcat service restarts the PlantUML service will be ready and
+After the Tomcat service restarts, the PlantUML service is ready and
listening for requests on port 8080:
```plaintext
http://localhost:8080/plantuml
```
-you can change these defaults by editing the `/etc/tomcat8/server.xml` file.
+To change these defaults, edit the `/etc/tomcat8/server.xml` file.
-Note that the default URL is different than when using the Docker-based image,
-where the service is available at the root of URL with no relative path. Adjust
+NOTE:
+The default URL is different when using this approach. The Docker-based image
+makes the service available at the root URL, with no relative path. Adjust
the configuration below accordingly.
### Making local PlantUML accessible using custom GitLab setup
@@ -112,7 +110,7 @@ To activate the changes, run the following command:
sudo gitlab-ctl reconfigure
```
-Note that the redirection through GitLab **must** be configured
+Note that the redirection through GitLab must be configured
when running [GitLab with TLS](https://docs.gitlab.com/omnibus/settings/ssl.html)
due to PlantUML's use of the insecure HTTP protocol. Newer browsers such
as [Google Chrome 86+](https://www.chromestatus.com/feature/4926989725073408)
@@ -120,7 +118,7 @@ do not load insecure HTTP resources on a page served over HTTPS.
### Security
-PlantUML has features that allows fetching network resources.
+PlantUML has features that allow fetching network resources.
```plaintext
@startuml
@@ -136,18 +134,18 @@ stop;
## GitLab
You need to enable PlantUML integration from Settings under Admin Area. To do
-that, login with an Admin account and do following:
+that, sign in with an Administrator account, and then do following:
-- In GitLab, go to **Admin Area > Settings > General**.
-- Expand the **PlantUML** section.
-- Check **Enable PlantUML** checkbox.
-- Set the PlantUML instance as `https://gitlab.example.com/-/plantuml/`.
+1. In GitLab, go to **Admin Area > Settings > General**.
+1. Expand the **PlantUML** section.
+1. Select the **Enable PlantUML** check box.
+1. Set the PlantUML instance as `https://gitlab.example.com/-/plantuml/`.
NOTE:
If you are using a PlantUML server running v1.2020.9 and
above (for example, [plantuml.com](https://plantuml.com)), set the `PLANTUML_ENCODING`
-environment variable to enable the `deflate` compression. On Omnibus,
-this can be done set in `/etc/gitlab.rb`:
+environment variable to enable the `deflate` compression. On Omnibus GitLab,
+this can be set in `/etc/gitlab.rb`:
```ruby
gitlab_rails['env'] = { 'PLANTUML_ENCODING' => 'deflate' }
@@ -191,9 +189,11 @@ our AsciiDoc snippets, wikis, and repositories using delimited blocks:
Alice -> Bob: hi
```
- You can also use the `uml::` directive for compatibility with [`sphinxcontrib-plantuml`](https://pypi.org/project/sphinxcontrib-plantuml/), but please note that we currently only support the `caption` option.
+ You can also use the `uml::` directive for compatibility with
+ [`sphinxcontrib-plantuml`](https://pypi.org/project/sphinxcontrib-plantuml/),
+ but GitLab only supports the `caption` option.
-The above blocks will be converted to an HTML image tag with source pointing to the
+The above blocks are converted to an HTML image tag with source pointing to the
PlantUML instance. If the PlantUML server is correctly configured, this should
render a nice diagram instead of the block:
@@ -202,12 +202,18 @@ Bob -> Alice : hello
Alice -> Bob : hi
```
-Inside the block you can add any of the supported diagrams by PlantUML such as
-[Sequence](https://plantuml.com/sequence-diagram), [Use Case](https://plantuml.com/use-case-diagram),
-[Class](https://plantuml.com/class-diagram), [Activity](https://plantuml.com/activity-diagram-legacy),
-[Component](https://plantuml.com/component-diagram), [State](https://plantuml.com/state-diagram),
-and [Object](https://plantuml.com/object-diagram) diagrams. You do not need to use the PlantUML
-diagram delimiters `@startuml`/`@enduml` as these are replaced by the AsciiDoc `plantuml` block.
+Inside the block you can add any of the diagrams PlantUML supports, such as:
+
+- [Sequence](https://plantuml.com/sequence-diagram)
+- [Use Case](https://plantuml.com/use-case-diagram)
+- [Class](https://plantuml.com/class-diagram)
+- [Activity](https://plantuml.com/activity-diagram-legacy)
+- [Component](https://plantuml.com/component-diagram)
+- [State](https://plantuml.com/state-diagram),
+- [Object](https://plantuml.com/object-diagram)
+
+You do not need to use the PlantUML
+diagram delimiters `@startuml`/`@enduml`, as these are replaced by the AsciiDoc `plantuml` block.
Some parameters can be added to the AsciiDoc block definition:
@@ -217,4 +223,4 @@ Some parameters can be added to the AsciiDoc block definition:
- `width`: Width attribute added to the image tag.
- `height`: Height attribute added to the image tag.
-Markdown does not support any parameters and will always use PNG format.
+Markdown does not support any parameters and always uses PNG format.
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index f4c242b6e72..0f26eb83d17 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -8,14 +8,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7690) in GitLab 8.15.
-NOTE:
-Only project maintainers and owners can access web terminals.
-
With the introduction of the [Kubernetes integration](../../user/project/clusters/index.md),
-GitLab gained the ability to store and use credentials for a Kubernetes cluster.
-One of the things it uses these credentials for is providing access to
+GitLab can store and use credentials for a Kubernetes cluster.
+GitLab uses these credentials to provide access to
[web terminals](../../ci/environments/index.md#web-terminals) for environments.
+NOTE:
+Only project maintainers and owners can access web terminals.
+
## How it works
A detailed overview of the architecture of web terminals and how they work
@@ -53,15 +53,13 @@ detail below.
NOTE:
AWS Elastic Load Balancers (ELBs) do not support web sockets.
-AWS Application Load Balancers (ALBs) must be used if you want web terminals
-to work. See [AWS Elastic Load Balancing Product Comparison](https://aws.amazon.com/elasticloadbalancing/features/#compare)
+If you want web terminals to work, use AWS Application Load Balancers (ALBs).
+Read [AWS Elastic Load Balancing Product Comparison](https://aws.amazon.com/elasticloadbalancing/features/#compare)
for more information.
As web terminals use WebSockets, every HTTP/HTTPS reverse proxy in front of
-Workhorse needs to be configured to pass the `Connection` and `Upgrade` headers
-through to the next one in the chain. If you installed GitLab using Omnibus, or
-from source, starting with GitLab 8.15, this should be done by the default
-configuration, so there's no need for you to do anything.
+Workhorse must be configured to pass the `Connection` and `Upgrade` headers
+to the next one in the chain. GitLab is configured by default to do so.
However, if you run a [load balancer](../load_balancer.md) in
front of GitLab, you may need to make some changes to your configuration. These
@@ -73,17 +71,17 @@ guides document the necessary steps for a selection of popular reverse proxies:
- [Varnish](https://varnish-cache.org/docs/4.1/users-guide/vcl-example-websockets.html)
Workhorse doesn't let WebSocket requests through to non-WebSocket endpoints, so
-it's safe to enable support for these headers globally. If you'd rather had a
-narrower set of rules, you can restrict it to URLs ending with `/terminal.ws`
-(although this may still have a few false positives).
+it's safe to enable support for these headers globally. If you prefer a
+narrower set of rules, you can restrict it to URLs ending with `/terminal.ws`.
+This approach may still result in a few false positives.
If you installed from source, or have made any configuration changes to your
Omnibus installation before upgrading to 8.15, you may need to make some changes
-to your configuration. See the [Upgrading Community Edition and Enterprise
-Edition from source](../../update/upgrading_from_source.md#nginx-configuration)
-document for more details.
+to your configuration. Read
+[Upgrading Community Edition and Enterprise Edition from source](../../update/upgrading_from_source.md#nginx-configuration)
+for more details.
-If you'd like to disable web terminal support in GitLab, just stop passing
+To disable web terminal support in GitLab, stop passing
the `Connection` and `Upgrade` hop-by-hop headers in the *first* HTTP reverse
proxy in the chain. For most users, this is the NGINX server bundled with
Omnibus GitLab, in which case, you need to:
@@ -104,4 +102,6 @@ they receive a `Connection failed` message.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8413) in GitLab 8.17.
Terminal sessions, by default, do not expire.
-You can limit terminal session lifetime in your GitLab instance. To do so, navigate to [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general), and set a `max session time`.
+You can limit terminal session lifetime in your GitLab instance. To do so,
+go to [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general),
+and set a `max session time`.
diff --git a/doc/administration/invalidate_markdown_cache.md b/doc/administration/invalidate_markdown_cache.md
index 75bee6e0c9a..211316534ee 100644
--- a/doc/administration/invalidate_markdown_cache.md
+++ b/doc/administration/invalidate_markdown_cache.md
@@ -5,13 +5,13 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Invalidate Markdown Cache
+# Invalidate Markdown Cache **(FREE)**
For performance reasons, GitLab caches the HTML version of Markdown text
-(e.g. issue and merge request descriptions, comments). It's possible
-that these cached versions become outdated, for example
-when the `external_url` configuration option is changed - causing links
-in the cached text to refer to the old URL.
+in fields like comments, issue descriptions, and merge request descriptions. These
+cached versions can become outdated, such as
+when the `external_url` configuration option is changed. Links
+in the cached text would still refer to the old URL.
To avoid this problem, the administrator can invalidate the existing cache by
increasing the `local_markdown_version` setting in application settings. This can
diff --git a/doc/administration/issue_closing_pattern.md b/doc/administration/issue_closing_pattern.md
index 6a5b90ae963..32d367bb15e 100644
--- a/doc/administration/issue_closing_pattern.md
+++ b/doc/administration/issue_closing_pattern.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Issue closing pattern **(CORE ONLY)**
+# Issue closing pattern **(FREE SELF)**
NOTE:
This is the administration documentation. There is a separate [user documentation](../user/project/issues/managing_issues.md#closing-issues-automatically)
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 5d07e7d1b26..3f8aca2f1ff 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -91,7 +91,7 @@ _The artifacts are stored by default in
> [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
> - Since version 9.5, artifacts are [browsable](../ci/pipelines/job_artifacts.md#browsing-artifacts),
> when object storage is enabled. 9.4 lacks this feature.
-> - Since version 10.6, available in [GitLab Core](https://about.gitlab.com/pricing/)
+> - Since version 10.6, available in [GitLab Free](https://about.gitlab.com/pricing/).
> - Since version 11.0, we support `direct_upload` to S3.
If you don't want to use the local disk where GitLab is installed to store the
@@ -339,7 +339,7 @@ an expiry for the artifacts, they are marked for deletion right after that date
Otherwise, they expire per the [default artifacts expiration setting](../user/admin_area/settings/continuous_integration.md).
Artifacts are cleaned up by the `expire_build_artifacts_worker` cron job which Sidekiq
-runs every hour at 50 minutes (`50 * * * *`).
+runs every 7 minutes (`*/7 * * * *`).
To change the default schedule on which the artifacts are expired, follow the
steps below.
@@ -350,7 +350,7 @@ steps below.
your schedule in cron syntax:
```ruby
- gitlab_rails['expire_build_artifacts_worker_cron'] = "50 * * * *"
+ gitlab_rails['expire_build_artifacts_worker_cron'] = "*/7 * * * *"
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -362,20 +362,20 @@ steps below.
```yaml
expire_build_artifacts_worker:
- cron: "50 * * * *"
+ cron: "*/7 * * * *"
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
If the `expire` directive is not set explicitly in your pipeline, artifacts expire per the
-default artifacts expiration setting, which you can find in the [CI/CD Admin settings](../user/admin_area/settings/continuous_integration.md).
+default artifacts expiration setting, which you can find in the [CI/CD Administration settings](../user/admin_area/settings/continuous_integration.md).
## Validation for dependencies
> Introduced in GitLab 10.3.
To disable [the dependencies validation](../ci/yaml/README.md#when-a-dependent-job-fails),
-you can enable the `ci_disable_validates_dependencies` feature flag from a Rails console.
+you can enable the `ci_validate_build_dependencies_override` feature flag from a Rails console.
**In Omnibus installations:**
@@ -388,7 +388,7 @@ you can enable the `ci_disable_validates_dependencies` feature flag from a Rails
1. Enable the feature flag to disable the validation:
```ruby
- Feature.enable(:ci_disable_validates_dependencies)
+ Feature.enable(:ci_validate_build_dependencies_override)
```
**In installations from source:**
@@ -403,7 +403,7 @@ you can enable the `ci_disable_validates_dependencies` feature flag from a Rails
1. Enable the feature flag to disable the validation:
```ruby
- Feature.enable(:ci_disable_validates_dependencies)
+ Feature.enable(:ci_validate_build_dependencies_override)
```
## Set the maximum file size of the artifacts
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index b2c6864e671..1afadcaf668 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -73,7 +73,7 @@ these steps to move the logs to a new location without losing any data.
```
Use `--ignore-existing` so you don't override new job logs with older versions of the same log.
-1. Unpause continuous integration data processing by editing `/etc/gitlab/gitlab.rb` and removing the `sidekiq` setting you updated earlier.
+1. Resume continuous integration data processing by editing `/etc/gitlab/gitlab.rb` and removing the `sidekiq` setting you updated earlier.
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the
changes to take effect.
1. Remove the old job logs storage location:
diff --git a/doc/administration/job_traces.md b/doc/administration/job_traces.md
deleted file mode 100644
index 2dbcf5d6705..00000000000
--- a/doc/administration/job_traces.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'job_logs.md'
----
-
-This document was moved to [another location](job_logs.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md
index bc349536a0c..862c26abac8 100644
--- a/doc/administration/lfs/index.md
+++ b/doc/administration/lfs/index.md
@@ -6,17 +6,17 @@ type: reference, howto
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/lfs/lfs_administration.html'
---
-# GitLab Git Large File Storage (LFS) Administration **(CORE ONLY)**
+# GitLab Git Large File Storage (LFS) Administration **(FREE SELF)**
> - Git LFS is supported in GitLab starting with version 8.2.
> - Support for object storage, such as AWS S3, was introduced in 10.0.
> - LFS is enabled in GitLab self-managed instances by default.
-Documentation on how to use Git LFS are under [Managing large binary files with Git LFS doc](../../topics/git/lfs/index.md).
+Documentation about how to use Git LFS are under [Managing large binary files with Git LFS doc](../../topics/git/lfs/index.md).
## Requirements
-- Users need to install [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up.
+- Users need to install [Git LFS client](https://git-lfs.github.com) version 1.0.1 or later.
## Configuration
@@ -25,9 +25,9 @@ GitLab is installed on.
There are various configuration options to help GitLab server administrators:
-- Enabling/disabling Git LFS support
-- Changing the location of LFS object storage
-- Setting up object storage supported by [Fog](http://fog.io/about/provider_documentation.html)
+- Enabling/disabling Git LFS support.
+- Changing the location of LFS object storage.
+- Setting up object storage supported by [Fog](http://fog.io/about/provider_documentation.html).
### Configuration for Omnibus installations
@@ -43,7 +43,7 @@ gitlab_rails['lfs_enabled'] = false
gitlab_rails['lfs_storage_path'] = "/mnt/storage/lfs-objects"
```
-After you update settings in `/etc/gitlab/gitlab.rb`, make sure to run [Omnibus GitLab reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+After you update settings in `/etc/gitlab/gitlab.rb`, run [Omnibus GitLab reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure).
### Configuration for installations from source
@@ -58,14 +58,12 @@ In `config/gitlab.yml`:
## Storing LFS objects in remote object storage
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2760) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0. Brought to GitLab Core in 10.7.
-
-It is possible to store LFS objects in remote object storage which allows you
-to offload local hard disk R/W operations, and free up disk space significantly.
+You can store LFS objects in remote object storage. This allows you
+to offload reads and writes to the local disk, and free up disk space significantly.
GitLab is tightly integrated with `Fog`, so you can refer to its [documentation](http://fog.io/about/provider_documentation.html)
to check which storage services can be integrated with GitLab.
You can also use external object storage in a private local network. For example,
-[MinIO](https://min.io/) is a standalone object storage service, is easy to set up, and works well with GitLab instances.
+[MinIO](https://min.io/) is a standalone object storage service that works with GitLab instances.
GitLab provides two different options for the uploading mechanism: "Direct upload" and "Background upload".
@@ -78,26 +76,26 @@ This section describes the earlier configuration format.
**Option 1. Direct upload**
-1. User pushes an `lfs` file to the GitLab instance
-1. GitLab-workhorse uploads the file directly to the external object storage
-1. GitLab-workhorse notifies GitLab-rails that the upload process is complete
+1. User pushes an `lfs` file to the GitLab instance.
+1. GitLab-workhorse uploads the file directly to the external object storage.
+1. GitLab-workhorse notifies GitLab-rails that the upload process is complete.
**Option 2. Background upload**
-1. User pushes an `lfs` file to the GitLab instance
-1. GitLab-rails stores the file in the local file storage
-1. GitLab-rails then uploads the file to the external object storage asynchronously
+1. User pushes an `lfs` file to the GitLab instance.
+1. GitLab-rails stores the file in the local file storage.
+1. GitLab-rails then uploads the file to the external object storage asynchronously.
The following general settings are supported.
-| Setting | Description | Default |
-|---------|-------------|---------|
-| `enabled` | Enable/disable object storage | `false` |
-| `remote_directory` | The bucket name where LFS objects will be stored| |
-| `direct_upload` | Set to true to enable direct upload of LFS without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
-| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
-| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
-| `connection` | Various connection options described below | |
+| Setting | Description | Default |
+|---------------------|-------------|---------|
+| `enabled` | Enable/disable object storage. | `false` |
+| `remote_directory` | The bucket name where LFS objects are stored. | |
+| `direct_upload` | Set to true to enable direct upload of LFS without the need of local shared storage. Option may be removed after we decide to support only single storage for all files. | `false` |
+| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3. | `true` |
+| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data. | `false` |
+| `connection` | Various connection options described below. | |
See [the available connection settings for different providers](../object_storage.md#connection-settings).
@@ -131,10 +129,9 @@ end
### S3 for Omnibus installations
-On Omnibus installations, the settings are prefixed by `lfs_object_store_`:
+On Omnibus GitLab installations, the settings are prefixed by `lfs_object_store_`:
-1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with
- the values you want:
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines, replacing values based on your needs:
```ruby
gitlab_rails['lfs_object_store_enabled'] = true
@@ -151,17 +148,17 @@ On Omnibus installations, the settings are prefixed by `lfs_object_store_`:
}
```
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local LFS objects to the object storage:
```shell
gitlab-rake gitlab:lfs:migrate
```
- This will migrate existing LFS objects to object storage. New LFS objects
- will be forwarded to object storage unless
+ This migrates existing LFS objects to object storage. New LFS objects
+ are forwarded to object storage unless
`gitlab_rails['lfs_object_store_background_upload']` and `gitlab_rails['lfs_object_store_direct_upload']` is set to `false`.
-1. Optional: Verify all files migrated properly.
+1. (Optional) Verify all files migrated properly.
From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
(`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
@@ -204,17 +201,17 @@ For source installations the settings are nested under `lfs:` and then
path_style: true
```
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
+1. Save the file, and then [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Migrate any existing local LFS objects to the object storage:
```shell
sudo -u git -H bundle exec rake gitlab:lfs:migrate RAILS_ENV=production
```
- This will migrate existing LFS objects to object storage. New LFS objects
- will be forwarded to object storage unless `background_upload` and `direct_upload` is set to
+ This migrates existing LFS objects to object storage. New LFS objects
+ are forwarded to object storage unless `background_upload` and `direct_upload` is set to
`false`.
-1. Optional: Verify all files migrated properly.
+1. (Optional) Verify all files migrated properly.
From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
```shell
@@ -233,7 +230,7 @@ For source installations the settings are nested under `lfs:` and then
### Migrating back to local storage
-In order to migrate back to local storage:
+To migrate back to local storage:
1. Set both `direct_upload` and `background_upload` to `false` under the LFS object storage settings. Don't forget to restart GitLab.
1. Run `rake gitlab:lfs:migrate_to_local` on your console.
@@ -241,17 +238,18 @@ In order to migrate back to local storage:
## Storage statistics
-You can see the total storage used for LFS objects on groups and projects
-in the administration area, as well as through the [groups](../../api/groups.md)
-and [projects APIs](../../api/projects.md).
+You can see the total storage used for LFS objects on groups and projects:
+
+- In the administration area.
+- In the [groups](../../api/groups.md) and [projects APIs](../../api/projects.md).
## Troubleshooting: `Google::Apis::TransmissionError: execution expired`
If LFS integration is configured with Google Cloud Storage and background uploads (`background_upload: true` and `direct_upload: false`),
Sidekiq workers may encounter this error. This is because the uploading timed out with very large files.
-LFS files up to 6Gb can be uploaded without any extra steps, otherwise you need to use the following workaround.
+LFS files up to 6 GB can be uploaded without any extra steps, otherwise you need to use the following workaround.
-Log into Rails console:
+Sign in to Rails console:
```shell
sudo gitlab-rails console
@@ -282,6 +280,6 @@ See more information in [!19581](https://gitlab.com/gitlab-org/gitlab-foss/-/mer
- Support for removing unreferenced LFS objects was added in 8.14 onward.
- LFS authentications via SSH was added with GitLab 8.12.
-- Only compatible with the Git LFS client versions 1.1.0 and up, or 1.0.2.
-- The storage statistics currently count each LFS object multiple times for
+- Only compatible with the Git LFS client versions 1.1.0 and later, or 1.0.2.
+- The storage statistics count each LFS object multiple times for
every project linking to it.
diff --git a/doc/administration/lfs/lfs_administration.md b/doc/administration/lfs/lfs_administration.md
deleted file mode 100644
index a275efce5bb..00000000000
--- a/doc/administration/lfs/lfs_administration.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'index.md'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/lfs/manage_large_binaries_with_git_lfs.md b/doc/administration/lfs/manage_large_binaries_with_git_lfs.md
deleted file mode 100644
index 69c401acb86..00000000000
--- a/doc/administration/lfs/manage_large_binaries_with_git_lfs.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../topics/git/lfs/index.md'
----
-
-This document was moved to [another location](../../topics/git/lfs/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/administration/lfs/migrate_from_git_annex_to_git_lfs.md
deleted file mode 100644
index 16095c1dbf6..00000000000
--- a/doc/administration/lfs/migrate_from_git_annex_to_git_lfs.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../topics/git/lfs/migrate_from_git_annex_to_git_lfs.md'
----
-
-This document was moved to [another location](../../topics/git/lfs/migrate_from_git_annex_to_git_lfs.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 3d5ba903941..17ecb324417 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Log system
+# Log system **(FREE SELF)**
GitLab has an advanced log system where everything is logged, so you
can analyze your instance using various system log files. In addition to
@@ -93,6 +93,8 @@ which correspond to:
1. `elasticsearch_calls`: total number of calls to Elasticsearch
1. `elasticsearch_duration_s`: total time taken by Elasticsearch calls
+1. `elasticsearch_timed_out_count`: total number of calls to Elasticsearch that
+ timed out and therefore returned partial results
ActionCable connection and subscription events are also logged to this file and they follow the same
format above. The `method`, `path`, and `format` fields are not applicable, and are always empty.
@@ -381,16 +383,18 @@ only. For example:
}
```
-## `audit_json.log`
+## `audit_json.log` **(FREE)**
NOTE:
-Most log entries only exist in [GitLab Starter](https://about.gitlab.com/pricing/), however a few exist in GitLab Core.
+GitLab Free tracks a small number of different audit events.
+[GitLab Premium](https://about.gitlab.com/pricing/) tracks many more.
This file lives in `/var/log/gitlab/gitlab-rails/audit_json.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/audit_json.log` for
installations from source.
-Changes to group or project settings are logged to this file. For example:
+Changes to group or project settings and memberships (`target_details`) are logged to this file.
+For example:
```json
{
@@ -411,11 +415,14 @@ Changes to group or project settings are logged to this file. For example:
## Sidekiq Logs
+NOTE:
+In Omnibus GitLab `12.10` or earlier, the Sidekiq log lives in `/var/log/gitlab/gitlab-rails/sidekiq.log`.
+
For Omnibus installations, some Sidekiq logs reside in `/var/log/gitlab/sidekiq/current` and as follows.
### `sidekiq.log`
-This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for
+This file lives in `/var/log/gitlab/sidekiq/current` for
Omnibus GitLab packages or in `/home/git/gitlab/log/sidekiq.log` for
installations from source.
@@ -772,7 +779,7 @@ are generated:
- For Omnibus GitLab packages, in `/var/log/gitlab/gitlab-rails/web_exporter.log`.
- For installations from source, in `/home/git/gitlab/log/web_exporter.log`.
-## `database_load_balancing.log` **(PREMIUM ONLY)**
+## `database_load_balancing.log` **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15442) in GitLab 12.3.
@@ -782,7 +789,7 @@ It's stored at:
- `/var/log/gitlab/gitlab-rails/database_load_balancing.log` for Omnibus GitLab packages.
- `/home/git/gitlab/log/database_load_balancing.log` for installations from source.
-## `elasticsearch.log` **(STARTER ONLY)**
+## `elasticsearch.log` **(PREMIUM SELF)**
> Introduced in GitLab 12.6.
@@ -856,7 +863,7 @@ For example:
{ "severity":"INFO", "time":"2020-04-22T16:04:50.691Z","correlation_id":"04f1366e-57a1-45b8-88c1-b00b23dc3616","class":"Projects::ImportExport::ExportService","current_user":"John Doe","project_full_path":"group1/test-export","file_path":"/path/to/archive","gc_stats":{"count":{"before":127,"after":127,"diff":0},"heap_allocated_pages":{"before":10369,"after":10369,"diff":0},"heap_sorted_length":{"before":10369,"after":10369,"diff":0},"heap_allocatable_pages":{"before":0,"after":0,"diff":0},"heap_available_slots":{"before":4226409,"after":4226409,"diff":0},"heap_live_slots":{"before":2542709,"after":2641420,"diff":98711},"heap_free_slots":{"before":1683700,"after":1584989,"diff":-98711},"heap_final_slots":{"before":0,"after":0,"diff":0},"heap_marked_slots":{"before":2542704,"after":2542704,"diff":0},"heap_eden_pages":{"before":10369,"after":10369,"diff":0},"heap_tomb_pages":{"before":0,"after":0,"diff":0},"total_allocated_pages":{"before":10369,"after":10369,"diff":0},"total_freed_pages":{"before":0,"after":0,"diff":0},"total_allocated_objects":{"before":24896308,"after":24995019,"diff":98711},"total_freed_objects":{"before":22353599,"after":22353599,"diff":0},"malloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"malloc_increase_bytes_limit":{"before":25804104,"after":25804104,"diff":0},"minor_gc_count":{"before":94,"after":94,"diff":0},"major_gc_count":{"before":33,"after":33,"diff":0},"remembered_wb_unprotected_objects":{"before":34284,"after":34284,"diff":0},"remembered_wb_unprotected_objects_limit":{"before":68568,"after":68568,"diff":0},"old_objects":{"before":2404725,"after":2404725,"diff":0},"old_objects_limit":{"before":4809450,"after":4809450,"diff":0},"oldmalloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"oldmalloc_increase_bytes_limit":{"before":68537556,"after":68537556,"diff":0}},"time_to_finish":0.12298400001600385,"number_of_sql_calls":70,"memory_usage":"0.0 MiB","label":"process_48616"}
```
-## `geo.log` **(PREMIUM ONLY)**
+## `geo.log` **(PREMIUM SELF)**
> Introduced in 9.5.
@@ -973,9 +980,13 @@ For Omnibus GitLab installations, Redis logs reside in `/var/log/gitlab/redis/`.
For Omnibus GitLab installations, Alertmanager logs reside in `/var/log/gitlab/alertmanager/`.
+<!-- vale gitlab.Spelling = NO -->
+
## Crond Logs
-For Omnibus GitLab installations, `crond` logs reside in `/var/log/gitlab/crond/`.
+For Omnibus GitLab installations, crond logs reside in `/var/log/gitlab/crond/`.
+
+<!-- vale gitlab.Spelling = YES -->
## Grafana Logs
@@ -983,7 +994,7 @@ For Omnibus GitLab installations, Grafana logs reside in `/var/log/gitlab/grafan
## LogRotate Logs
-For Omnibus GitLab installations, logrotate logs reside in `/var/log/gitlab/logrotate/`.
+For Omnibus GitLab installations, `logrotate` logs reside in `/var/log/gitlab/logrotate/`.
## GitLab Monitor Logs
@@ -1009,7 +1020,7 @@ installations from source.
Performance bar statistics (currently only duration of SQL queries) are recorded in that file. For example:
```json
-{"severity":"INFO","time":"2020-12-04T09:29:44.592Z","correlation_id":"33680b1490ccd35981b03639c406a697","filename":"app/models/ci/pipeline.rb","filenum":"395","method":"each_with_object","request_id":"rYHomD0VJS4","duration_ms":26.889,"type": "sql"}
+{"severity":"INFO","time":"2020-12-04T09:29:44.592Z","correlation_id":"33680b1490ccd35981b03639c406a697","filename":"app/models/ci/pipeline.rb","method_path":"app/models/ci/pipeline.rb:each_with_object","request_id":"rYHomD0VJS4","duration_ms":26.889,"count":2,"type": "sql"}
```
These statistics are logged on .com only, disabled on self-deployments.
@@ -1026,14 +1037,14 @@ GitLab Support often asks for one of these, and maintains the required tools.
### Briefly tail the main logs
If the bug or error is readily reproducible, save the main GitLab logs
-[to a file](troubleshooting/linux_cheat_sheet.md#files--dirs) while reproducing the
+[to a file](troubleshooting/linux_cheat_sheet.md#files-and-directories) while reproducing the
problem a few times:
```shell
sudo gitlab-ctl tail | tee /tmp/<case-ID-and-keywords>.log
```
-Conclude the log gathering with <kbd>Ctrl</kbd> + <kbd>C</kbd>.
+Conclude the log gathering with <kbd>Control</kbd> + <kbd>C</kbd>.
### GitLabSOS
diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md
new file mode 100644
index 00000000000..61d321f2176
--- /dev/null
+++ b/doc/administration/maintenance_mode/index.md
@@ -0,0 +1,206 @@
+---
+stage: Enablement
+group: Geo
+info: To 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 Maintenance Mode **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2149) in GitLab Premium 13.9.
+
+Maintenance Mode allows administrators to reduce write operations to a minimum while maintenance tasks are performed. The main goal is to block all external actions that change the internal state, including the PostgreSQL database, but especially files, Git repositories, Container repositories, etc.
+
+Once Maintenance Mode is enabled, in-progress actions will finish relatively quickly since no new actions are coming in, and internal state changes will be minimal.
+In that state, various maintenance tasks are easier, and services can be stopped completely or be
+further degraded for a much shorter period of time than might otherwise be needed, for example stopping cron jobs and draining queues should be fairly quick.
+
+Maintenance Mode allows most external actions that do not change internal state. On a high-level, HTTP POST, PUT, PATCH, and DELETE requests are blocked and a detailed overview of [how special cases are handled](#rest-api) is available.
+
+## Enable Maintenance Mode
+
+There are three ways to enable Maintenance Mode as an administrator:
+
+- **Web UI**:
+ 1. Go to **Admin Area > Settings > General**, expand **Maintenance Mode**, and toggle **Enable Maintenance Mode**.
+ You can optionally add a message for the banner as well.
+
+ 1. Click **Save** for the changes to take effect.
+
+- **API**:
+
+ ```shell
+ curl --request PUT --header "PRIVATE-TOKEN:$ADMIN_TOKEN" "<gitlab-url>/api/v4/application/settings?maintenance_mode=true"
+ ```
+
+- [**Rails console**](../operations/rails_console.md#starting-a-rails-console-session):
+
+ ```ruby
+ ::Gitlab::CurrentSettings.update_attributes!(maintenance_mode: true)
+ ::Gitlab::CurrentSettings.update_attributes!(maintenance_mode_message: "New message")
+ ```
+
+## Disable Maintenance Mode
+
+There are three ways to disable Maintenance Mode:
+
+- **Web UI**:
+ 1. Go to **Admin Area > Settings > General**, expand **Maintenance Mode**, and toggle **Enable Maintenance Mode**.
+
+ 1. Click **Save** for the changes to take effect.
+
+- **API**:
+
+ ```shell
+ curl --request PUT --header "PRIVATE-TOKEN:$ADMIN_TOKEN" "<gitlab-url>/api/v4/application/settings?maintenance_mode=false"
+ ```
+
+- [**Rails console**](../operations/rails_console.md#starting-a-rails-console-session):
+
+ ```ruby
+ ::Gitlab::CurrentSettings.update_attributes!(maintenance_mode: false)
+ ```
+
+## Behavior of GitLab features in Maintenance Mode
+
+When Maintenance Mode is enabled, a banner is displayed at the top of the page.
+The banner can be customized with a specific message.
+
+An error is displayed when a user tries to perform a write operation that isn't allowed.
+
+![Maintenance Mode banner and error message](maintenance_mode_error_message.png)
+
+NOTE:
+In some cases, the visual feedback from an action could be misleading, for example when starring a project, the **Star** button changes to show the **Unstar** action, however, this is only the frontend update, and it doesn't take into account the failed status of the POST request. These visual bugs are to be fixed [in follow-up iterations](https://gitlab.com/gitlab-org/gitlab/-/issues/295197).
+
+### Admin functions
+
+Systems administrators can edit the application settings. This will allow
+them to disable Maintenance Mode after it's been enabled.
+
+### Authentication
+
+All users can log in and out of the GitLab instance but no new users can be created.
+
+If there are [LDAP syncs](../auth/ldap/index.md) scheduled for that time, they will fail since user creation is disabled. Similarly, [user creations based on SAML](../../integration/saml.md#general-setup) will fail.
+
+### Git actions
+
+All read-only Git operations will continue to work, for example
+`git clone` and `git pull`. All write operations will fail, both through the CLI and Web IDE with the error message: `Git push is not allowed because this GitLab instance is currently in (read-only) maintenance mode.`
+
+If Geo is enabled, Git pushes to both primary and secondaries will fail.
+
+### Merge requests, issues, epics
+
+All write actions except those mentioned above will fail. For example, a user cannot update merge requests or issues.
+
+### Incoming email
+
+Creating new issue replies, issues (including new Service Desk issues), merge requests [by email](../incoming_email.md) will fail.
+
+### Outgoing email
+
+Notification emails will continue to arrive, but emails that require database writes, like resetting the password, will not arrive.
+
+### REST API
+
+For most JSON requests, POST, PUT, PATCH, and DELETE are blocked, and the API returns a 403 response with the error message: `You cannot perform write operations on a read-only instance`. Only the following requests are allowed:
+
+|HTTP request | Allowed routes | Notes |
+|:----:|:--------------------------------------:|:----:|
+| POST | `/admin/application_settings/general` | To allow updating application settings in the admin UI |
+| PUT | `/api/v4/application/settings` | To allow updating application settings with the API |
+| POST | `/users/sign_in` | To allow users to log in. |
+| POST | `/users/sign_out`| To allow users to log out. |
+| POST | `/oauth/token` | To allow users to log in to a Geo secondary for the first time. |
+| POST | `/admin/session`, `/admin/session/destroy` | To allow [Admin mode for GitLab administrators](https://gitlab.com/groups/gitlab-org/-/epics/2158) |
+| POST | Paths ending with `/compare`| Git revision routes. |
+| POST | `.git/git-upload-pack` | To allow Git pull/clone. |
+| POST | `/api/v4/internal` | [internal API routes](../../development/internal_api.md) |
+| POST | `/admin/sidekiq` | To allow management of background jobs in the admin UI |
+| POST | `/admin/geo` | To allow updating Geo Nodes in the admin UI |
+| POST | `/api/v4/geo_replication`| To allow certain Geo-specific admin UI actions on secondary sites |
+
+### GraphQL API
+
+`POST /api/graphql` requests are allowed but mutations are blocked with the error message `You cannot perform write operations on a read-only instance`.
+
+### Continuous Integration
+
+- No new jobs or pipelines start, scheduled or otherwise.
+- Jobs that were already running continue to have a `running` status in the GitLab UI,
+ even if they finish running on the GitLab Runner.
+- Jobs in the `running` state for longer than the project's time limit do not time out.
+- Pipelines cannot be started, retried or canceled. No new jobs can be created either.
+
+After Maintenance Mode is disabled, new jobs are picked up again. Jobs that were
+in the `running` state before enabling Maintenance Mode resume and their logs start
+updating again.
+
+NOTE:
+It is recommended that you restart previously `running` pipelines after Maintenance Mode
+is turned off.
+
+### Deployments
+
+Deployments won't go through because pipelines will be unfinished.
+
+It is recommended to disable auto deploys during Maintenance Mode, and enable them once it is disabled.
+
+#### Terraform integration
+
+Terraform integration depends on running CI pipelines, hence it will be blocked.
+
+### Container Registry
+
+`docker push` will fail with this error: `denied: requested access to the resource is denied`, but `docker pull` will work.
+
+### Package Registry
+
+Package Registry will allow you to install but not publish packages.
+
+### Background jobs
+
+Background jobs (cron jobs, Sidekiq) will continue running as is, because background jobs are not automatically disabled.
+
+[During a planned Geo failover](../geo/disaster_recovery/planned_failover.md#prevent-updates-to-the-primary-node),
+it is recommended that you disable all cron jobs except for those related to Geo.
+
+You can monitor queues and disable jobs in **Admin Area > Monitoring > Background Jobs**.
+
+### Incident management
+
+[Incident management](../../operations/incident_management/index.md) functions will be limited. The creation of [alerts](../../operations/incident_management/alerts.md) and [incidents](../../operations/incident_management/incidents.md#incident-creation) will be paused entirely. Notifications and paging on alerts and incidents will therefore be disabled.
+
+### Feature flags
+
+- [Development feature flags](../../development/feature_flags/index.md) cannot be turned on or off through the API, but can be toggled through the Rails console.
+- [The feature flag service](../../operations/feature_flags.md) will respond to feature flag checks but feature flags cannot be toggled
+
+### Geo secondaries
+
+When primary is in Maintenance Mode, secondary will also automatically go into Maintenance Mode.
+
+It is important that you do not disable replication before enabling Maintenance Mode.
+
+Replication and verification will continue to work but proxied Git pushes to primary will not work.
+
+### Secure features
+
+Features that depend on creating issues or creating or approving Merge Requests, will not work.
+
+Exporting a vulnerability list from a Vulnerability Report page will not work.
+
+Changing the status on a finding or vulnerability object will not work, even though no error is shown in the UI.
+
+SAST and Secret Detection cannot be initiated because they depend on passing CI jobs to create artifacts.
+
+## An example use case: a planned failover
+
+In the use case of [a planned failover](../geo/disaster_recovery/planned_failover.md), a few writes in the primary database are acceptable, since they will be replicated quickly and are not significant in number.
+
+For the same reason we don't automatically block background jobs when Maintenance Mode is enabled.
+
+The resulting database writes are acceptable. Here, the trade-off is between more service degradation and the completion of replication.
+
+However, during a planned failover, we [ask users to turn off cron jobs that are not related to Geo, manually](../geo/disaster_recovery/planned_failover.md#prevent-updates-to-the-primary-node). In the absence of new database writes and non-Geo cron jobs, new background jobs would either not be created at all or be minimal.
diff --git a/doc/administration/maintenance_mode/maintenance_mode_error_message.png b/doc/administration/maintenance_mode/maintenance_mode_error_message.png
new file mode 100644
index 00000000000..4b422a719ca
--- /dev/null
+++ b/doc/administration/maintenance_mode/maintenance_mode_error_message.png
Binary files differ
diff --git a/doc/administration/maven_packages.md b/doc/administration/maven_packages.md
deleted file mode 100644
index 690b6785941..00000000000
--- a/doc/administration/maven_packages.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'packages/index.md'
----
-
-This document was moved to [another location](packages/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/maven_repository.md b/doc/administration/maven_repository.md
deleted file mode 100644
index 690b6785941..00000000000
--- a/doc/administration/maven_repository.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'packages/index.md'
----
-
-This document was moved to [another location](packages/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/merge_request_diffs.md b/doc/administration/merge_request_diffs.md
index 92fdba6216c..1133bff204c 100644
--- a/doc/administration/merge_request_diffs.md
+++ b/doc/administration/merge_request_diffs.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Merge request diffs storage **(CORE ONLY)**
+# Merge request diffs storage **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52568) in GitLab 11.8.
@@ -31,8 +31,8 @@ that only [stores outdated diffs](#alternative-in-database-storage) outside of d
gitlab_rails['external_diffs_enabled'] = true
```
-1. _The external diffs will be stored in
- `/var/opt/gitlab/gitlab-rails/shared/external-diffs`._ To change the path,
+1. The external diffs are stored in
+ `/var/opt/gitlab/gitlab-rails/shared/external-diffs`. To change the path,
for example, to `/mnt/storage/external-diffs`, edit `/etc/gitlab/gitlab.rb`
and add the following line:
@@ -52,8 +52,8 @@ that only [stores outdated diffs](#alternative-in-database-storage) outside of d
enabled: true
```
-1. _The external diffs will be stored in
- `/home/git/gitlab/shared/external-diffs`._ To change the path, for example,
+1. The external diffs are stored in
+ `/home/git/gitlab/shared/external-diffs`. To change the path, for example,
to `/mnt/storage/external-diffs`, edit `/home/git/gitlab/config/gitlab.yml`
and add or amend the following lines:
@@ -68,7 +68,7 @@ that only [stores outdated diffs](#alternative-in-database-storage) outside of d
## Using object storage
WARNING:
-Currently migrating to object storage is **non-reversible**
+Migrating to object storage is not reversible.
Instead of storing the external diffs on disk, we recommended the use of an object
store like AWS S3 instead. This configuration relies on valid AWS credentials to
@@ -114,7 +114,7 @@ then `object_store:`. On Omnibus installations, they are prefixed by
| Setting | Description | Default |
|---------|-------------|---------|
| `enabled` | Enable/disable object storage | `false` |
-| `remote_directory` | The bucket name where external diffs will be stored| |
+| `remote_directory` | The bucket name where external diffs are stored| |
| `direct_upload` | Set to `true` to enable direct upload of external diffs without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
| `background_upload` | Set to `false` to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
| `proxy_download` | Set to `true` to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
@@ -141,7 +141,7 @@ See [the available connection settings for different providers](object_storage.m
}
```
- Note that, if you are using AWS IAM profiles, be sure to omit the
+ If you are using AWS IAM profiles, omit the
AWS access key and secret access key/value pairs. For example:
```ruby
@@ -206,8 +206,8 @@ To enable this feature, perform the following steps:
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-With this feature enabled, diffs will initially stored in the database, rather
-than externally. They will be moved to external storage once any of these
+With this feature enabled, diffs are initially stored in the database, rather
+than externally. They are moved to external storage after any of these
conditions become true:
- A newer version of the merge request diff exists
@@ -225,15 +225,15 @@ of some merge request diffs when [external diffs in object storage](#object-stor
were enabled. This mainly affected imported merge requests, and was resolved
with [this merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31005).
-If you are using object storage, have never used on-disk storage for external
-diffs, the "changes" tab for some merge requests fails to load with a 500 error,
+If you are using object storage, or have never used on-disk storage for external
+diffs, the **Changes** tab for some merge requests fails to load with a 500 error,
and the exception for that error is of this form:
```plain
Errno::ENOENT (No such file or directory @ rb_sysopen - /var/opt/gitlab/gitlab-rails/shared/external-diffs/merge_request_diffs/mr-6167082/diff-8199789)
```
-Then you are affected by this issue. Since it's not possible to safely determine
+Then you are affected by this issue. Because it's not possible to safely determine
all these conditions automatically, we've provided a Rake task in GitLab v13.2.0
that you can run manually to correct the data:
diff --git a/doc/administration/monitoring/github_imports.md b/doc/administration/monitoring/github_imports.md
index cf7c105e8cf..736ff299a86 100644
--- a/doc/administration/monitoring/github_imports.md
+++ b/doc/administration/monitoring/github_imports.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring GitHub imports
+# Monitoring GitHub imports **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14731) in GitLab 10.2.
diff --git a/doc/administration/monitoring/gitlab_instance_administration_project/index.md b/doc/administration/monitoring/gitlab_instance_administration_project/index.md
deleted file mode 100644
index 59837dcdb20..00000000000
--- a/doc/administration/monitoring/gitlab_instance_administration_project/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../gitlab_self_monitoring_project/index.md'
----
-
-This document was moved to [another location](../gitlab_self_monitoring_project/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index 13d42ca2ee6..1262c4192f6 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -4,7 +4,7 @@ group: Health
info: To 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 self monitoring project
+# GitLab self monitoring project **(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.
@@ -19,7 +19,7 @@ specifically created for visualizing and configuring the monitoring of your
GitLab instance.
All administrators at the time of creation of the project and group are
-added as maintainers of the group and project, and as an admin, you can
+added as maintainers of the group and project, and as an administrator, you can
add new members to the group to give them maintainer access to the project.
This project is used to self monitor your GitLab instance. The metrics dashboard
@@ -94,22 +94,22 @@ You can add custom metrics in the self monitoring project by:
There is [a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/208676) which causes
project creation to fail with the following error (which appears in the log file)
-when the first admin user is an
+when the first administrator user is an
[external user](../../../user/permissions.md#external-users):
```plaintext
Could not create instance administrators group. Errors: ["You don’t have permission to create groups."]
```
-Run the following in a Rails console to check if the first admin user is an external user:
+Run the following in a Rails console to check if the first administrator user is an external user:
```ruby
User.admins.active.first.external?
```
-If this returns true, the first admin user is an external user.
+If this returns true, the first administrator user is an external user.
If you face this issue, you can temporarily
-[make the admin user a non-external user](../../../user/permissions.md#external-users)
+[make the administrator user a non-external user](../../../user/permissions.md#external-users)
and then try to create the project.
-Once the project is created, the admin user can be changed back to an external user.
+Once the project is created, the administrator user can be changed back to an external user.
diff --git a/doc/administration/monitoring/index.md b/doc/administration/monitoring/index.md
index 68dbe9f3cf9..ac09acf2d2e 100644
--- a/doc/administration/monitoring/index.md
+++ b/doc/administration/monitoring/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring GitLab
+# Monitoring GitLab **(FREE SELF)**
Explore our features to monitor your GitLab instance:
diff --git a/doc/administration/monitoring/ip_whitelist.md b/doc/administration/monitoring/ip_whitelist.md
index 83fbec86f57..91f9c5d560f 100644
--- a/doc/administration/monitoring/ip_whitelist.md
+++ b/doc/administration/monitoring/ip_whitelist.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# IP whitelist
+# IP whitelist **(FREE SELF)**
> Introduced in GitLab 9.4.
diff --git a/doc/administration/monitoring/performance/gitlab_configuration.md b/doc/administration/monitoring/performance/gitlab_configuration.md
index dd4481434a6..03eba67292d 100644
--- a/doc/administration/monitoring/performance/gitlab_configuration.md
+++ b/doc/administration/monitoring/performance/gitlab_configuration.md
@@ -4,22 +4,24 @@ group: Health
info: To 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 Configuration
+# GitLab Configuration **(FREE SELF)**
GitLab Performance Monitoring is disabled by default. To enable it and change any of its
settings:
1. Navigate to **Admin Area > Settings > Metrics and profiling**
- (`/admin/application_settings/metrics_and_profiling`):
-
- ![GitLab Performance Monitoring Administration Settings](img/metrics_gitlab_configuration_settings.png)
-
-1. You must restart all GitLab processes for the changes to take effect:
+ (`/admin/application_settings/metrics_and_profiling`).
+1. Add the necessary configuration changes.
+1. Restart all GitLab for the changes to take effect:
- For Omnibus GitLab installations: `sudo gitlab-ctl restart`
- For installations from source: `sudo service gitlab restart`
-## Pending Migrations
+NOTE:
+Removed [in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30786). Use the
+[Prometheus integration](../prometheus/index.md) instead.
+
+## Pending migrations
When any migrations are pending, the metrics are disabled until the migrations
have been performed.
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index e76e81c6499..e6dda2ac87a 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Grafana Configuration
+# Grafana Configuration **(FREE SELF)**
[Grafana](https://grafana.com/) is a tool that enables you to visualize time
series metrics through graphs and dashboards. GitLab writes performance data to Prometheus,
@@ -17,42 +17,38 @@ or Grafana supplies package repositories (Yum/Apt) for easy installation.
See [Grafana installation documentation](https://grafana.com/docs/grafana/latest/installation/)
for detailed steps.
-Before starting Grafana for the first time, set the admin user
+Before starting Grafana for the first time, set the administration user
and password in `/etc/grafana/grafana.ini`. If you don't, the default password
is `admin`.
## Configuration
-1. Log in to Grafana as the admin user.
-1. Expand the menu by clicking the Grafana logo in the top left corner.
-1. Choose **Data Sources** from the menu.
-1. Click **Add new** in the top bar:
- ![Grafana empty data source page](img/grafana_data_source_empty.png)
-1. Edit the data source to fit your needs:
- ![Grafana data source configurations](img/grafana_data_source_configuration.png)
-1. Click **Save**.
+1. Log in to Grafana as the administration user.
+1. Select **Data Sources** from the **Configuration** menu.
+1. Select the **Add data source** button.
+1. Select the required data source type. For example, [Prometheus](../prometheus/index.md#prometheus-as-a-grafana-data-source).
+1. Complete the details for the data source and select the **Save & Test** button.
+
+Grafana should indicate the data source is working.
## Import Dashboards
You can now import a set of default dashboards to start displaying useful information.
GitLab has published a set of default
-[Grafana dashboards](https://gitlab.com/gitlab-org/grafana-dashboards) to get you started.
-Clone the repository, or download a ZIP file or tarball, then follow these steps to import each
-JSON file individually:
+[Grafana dashboards](https://gitlab.com/gitlab-org/grafana-dashboards) to get you started. To use
+them:
-1. Log in to Grafana as the admin user.
-1. Open the dashboard dropdown menu and click **Import**:
- ![Grafana dashboard dropdown](img/grafana_dashboard_dropdown.png)
-1. Click **Choose file**, and browse to the location where you downloaded or
- cloned the dashboard repository. Select a JSON file to import:
- ![Grafana dashboard import](img/grafana_dashboard_import.png)
-1. After the dashboard is imported, click the **Save dashboard** icon in the top bar:
- ![Grafana save icon](img/grafana_save_icon.png)
+1. Clone the repository, or download a ZIP file or tarball.
+1. Follow these steps to import each JSON file individually:
- If you don't save the dashboard after importing it, the dashboard is removed
- when you navigate away from the page.
+ 1. Log in to Grafana as the administration user.
+ 1. Select **Manage** from the **Dashboards** menu.
+ 1. Select the **Import** button, then the **Upload JSON file** button.
+ 1. Locate the JSON file to import and select **Choose for Upload**. Select the **Import** button.
+ 1. After the dashboard is imported, select the **Save dashboard** icon in the top bar.
-Repeat this process for each dashboard you wish to import.
+If you don't save the dashboard after importing it, the dashboard is removed
+when you navigate away from the page. Repeat this process for each dashboard you wish to import.
Alternatively, you can import all the dashboards into your Grafana
instance. For more information about this process, see the
@@ -103,7 +99,7 @@ sudo mv /var/opt/gitlab/grafana/data.bak.xxxx/ /var/opt/gitlab/grafana/data/
However, you should **not** reinstate your old data _except_ under one of the following conditions:
-1. If you're certain that you changed your default admin password when you enabled Grafana.
+1. If you're certain that you changed your default administration password when you enabled Grafana.
1. If you run GitLab in a private network, accessed only by trusted users, and your
Grafana login page has not been exposed to the internet.
@@ -121,8 +117,6 @@ existing data and dashboards.
For more information and further mitigation details, please refer to our
[blog post on the security release](https://about.gitlab.com/releases/2019/08/12/critical-security-release-gitlab-12-dot-1-dot-6-released/).
----
-
Read more on:
- [Introduction to GitLab Performance Monitoring](index.md)
diff --git a/doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.png b/doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.png
deleted file mode 100644
index 51eef90068d..00000000000
--- a/doc/administration/monitoring/performance/img/grafana_dashboard_dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_dashboard_import.png b/doc/administration/monitoring/performance/img/grafana_dashboard_import.png
deleted file mode 100644
index fd639ee0eb8..00000000000
--- a/doc/administration/monitoring/performance/img/grafana_dashboard_import.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_data_source_configuration.png b/doc/administration/monitoring/performance/img/grafana_data_source_configuration.png
deleted file mode 100644
index a98e0ed1e7d..00000000000
--- a/doc/administration/monitoring/performance/img/grafana_data_source_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_data_source_empty.png b/doc/administration/monitoring/performance/img/grafana_data_source_empty.png
deleted file mode 100644
index 549ada8343e..00000000000
--- a/doc/administration/monitoring/performance/img/grafana_data_source_empty.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/grafana_save_icon.png b/doc/administration/monitoring/performance/img/grafana_save_icon.png
deleted file mode 100644
index 68a071f5ae2..00000000000
--- a/doc/administration/monitoring/performance/img/grafana_save_icon.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.png b/doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.png
deleted file mode 100644
index 13bfd097b81..00000000000
--- a/doc/administration/monitoring/performance/img/metrics_gitlab_configuration_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/performance_bar_external_http_calls.png b/doc/administration/monitoring/performance/img/performance_bar_external_http_calls.png
new file mode 100644
index 00000000000..45f2b0956e9
--- /dev/null
+++ b/doc/administration/monitoring/performance/img/performance_bar_external_http_calls.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md
index 072baa16e29..cdf78811092 100644
--- a/doc/administration/monitoring/performance/index.md
+++ b/doc/administration/monitoring/performance/index.md
@@ -4,7 +4,7 @@ group: Health
info: To 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 Performance Monitoring
+# GitLab Performance Monitoring **(FREE SELF)**
GitLab comes with its own application performance measuring system as of GitLab
8.4, called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the
diff --git a/doc/administration/monitoring/performance/influxdb_configuration.md b/doc/administration/monitoring/performance/influxdb_configuration.md
deleted file mode 100644
index d793e014a18..00000000000
--- a/doc/administration/monitoring/performance/influxdb_configuration.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'prometheus.md'
----
-
-Support for InfluxDB was removed in GitLab 13.0. Use [Prometheus](prometheus.md) for performance monitoring.
diff --git a/doc/administration/monitoring/performance/influxdb_schema.md b/doc/administration/monitoring/performance/influxdb_schema.md
deleted file mode 100644
index d793e014a18..00000000000
--- a/doc/administration/monitoring/performance/influxdb_schema.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'prometheus.md'
----
-
-Support for InfluxDB was removed in GitLab 13.0. Use [Prometheus](prometheus.md) for performance monitoring.
diff --git a/doc/administration/monitoring/performance/introduction.md b/doc/administration/monitoring/performance/introduction.md
deleted file mode 100644
index a275efce5bb..00000000000
--- a/doc/administration/monitoring/performance/introduction.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'index.md'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index a214660bd5c..0516cbc2f8b 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Performance Bar
+# Performance Bar **(FREE SELF)**
You can display the GitLab Performance Bar to see statistics for the performance
of a page. When activated, it looks as follows:
@@ -31,6 +31,10 @@ From left to right, it displays:
![Redis profiling using the Performance Bar](img/performance_bar_redis_calls.png)
- **Elasticsearch calls**: the time taken (in milliseconds) and the total number of
Elasticsearch calls. Click to display a modal window with more details.
+- **External HTTP calls**: the time taken (in milliseconds) and the total
+ number of external calls to other systems. Click to display a modal window
+ with more details
+ ![External call details in the Performance Bar](img/performance_bar_external_http_calls.png)
- **Load timings** of the page: if your browser supports load timings (Chromium
and Chrome) several values in milliseconds, separated by slashes.
Click to display a modal window with more details. The values, from left to right:
@@ -67,7 +71,7 @@ Requests with warnings display `(!)` after their path in the **Request selector*
![Request selector showing dropdown](img/performance_bar_request_selector_warning_expanded.png)
-## Enable the Performance Bar via the Admin panel
+## Enable the Performance Bar via the Admin Area
The GitLab Performance Bar is disabled by default. To enable it for a given group:
diff --git a/doc/administration/monitoring/performance/prometheus.md b/doc/administration/monitoring/performance/prometheus.md
deleted file mode 100644
index 2978de865e2..00000000000
--- a/doc/administration/monitoring/performance/prometheus.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../prometheus/index.md'
----
-
-This document was moved to [another location](../prometheus/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index 23af50dec11..f0ac8f991d3 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -4,7 +4,7 @@ group: Health
info: To 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
+# Request Profiling **(FREE SELF)**
To profile a request:
diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md
index 5add842bccc..589fa799cca 100644
--- a/doc/administration/monitoring/prometheus/gitlab_exporter.md
+++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md
@@ -4,7 +4,7 @@ group: Health
info: To 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 exporter
+# GitLab exporter **(FREE SELF)**
>- Available since [Omnibus GitLab 8.17](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1132).
>- Renamed from `GitLab monitor exporter` to `GitLab exporter` in [GitLab 12.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16511).
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 4493c1677bc..38b26041901 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -4,7 +4,7 @@ group: Health
info: To 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 Prometheus metrics
+# GitLab Prometheus metrics **(FREE SELF)**
To enable the GitLab Prometheus metrics:
@@ -33,87 +33,95 @@ For enabling and viewing metrics from Sidekiq nodes, see [Sidekiq metrics](#side
The following metrics are available:
-| Metric | Type | Since | Description | Labels |
-|:---------------------------------------------------------------|:----------|-----------------------:|:----------------------------------------------------------------------------------------------------|:----------------------------------------------------|
-| `gitlab_banzai_cached_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output exists | `controller`, `action` |
-| `gitlab_banzai_cacheless_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output does not exist | `controller`, `action` |
-| `gitlab_cache_misses_total` | Counter | 10.2 | Cache read miss | `controller`, `action` |
-| `gitlab_cache_operation_duration_seconds` | Histogram | 10.2 | Cache access time | |
-| `gitlab_cache_operations_total` | Counter | 12.2 | Cache operations by controller or action | `controller`, `action`, `operation` |
-| `gitlab_ci_pipeline_creation_duration_seconds` | Histogram | 13.0 | Time in seconds it takes to create a CI/CD pipeline | |
-| `gitlab_ci_pipeline_size_builds` | Histogram | 13.1 | Total number of builds within a pipeline grouped by a pipeline source | `source` |
-| `job_waiter_started_total` | Counter | 12.9 | Number of batches of jobs started where a web request is waiting for the jobs to complete | `worker` |
-| `job_waiter_timeouts_total` | Counter | 12.9 | Number of batches of jobs that timed out where a web request is waiting for the jobs to complete | `worker` |
-| `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_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_ruby_threads_max_expected_threads` | Gauge | 13.3 | Maximum number of threads expected to be running and performing application work |
-| `gitlab_ruby_threads_running_threads` | Gauge | 13.3 | Number of running Ruby threads by name |
-| `gitlab_transaction_cache_<key>_count_total` | Counter | 10.2 | Counter for total Rails cache calls (per key) | |
-| `gitlab_transaction_cache_<key>_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (per key) | |
-| `gitlab_transaction_cache_count_total` | Counter | 10.2 | Counter for total Rails cache calls (aggregate) | |
-| `gitlab_transaction_cache_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (aggregate) | |
-| `gitlab_transaction_cache_read_hit_count_total` | Counter | 10.2 | Counter for cache hits for Rails cache calls | `controller`, `action` |
-| `gitlab_transaction_cache_read_miss_count_total` | Counter | 10.2 | Counter for cache misses for Rails cache calls | `controller`, `action` |
-| `gitlab_transaction_duration_seconds` | Histogram | 10.2 | Duration for all transactions (`gitlab_transaction_*` metrics) | `controller`, `action` |
-| `gitlab_transaction_event_build_found_total` | Counter | 9.4 | Counter for build found for API /jobs/request | |
-| `gitlab_transaction_event_build_invalid_total` | Counter | 9.4 | Counter for build invalid due to concurrency conflict for API /jobs/request | |
-| `gitlab_transaction_event_build_not_found_cached_total` | Counter | 9.4 | Counter for cached response of build not found for API /jobs/request | |
-| `gitlab_transaction_event_build_not_found_total` | Counter | 9.4 | Counter for build not found for API /jobs/request | |
-| `gitlab_transaction_event_change_default_branch_total` | Counter | 9.4 | Counter when default branch is changed for any repository | |
-| `gitlab_transaction_event_create_repository_total` | Counter | 9.4 | Counter when any repository is created | |
-| `gitlab_transaction_event_etag_caching_cache_hit_total` | Counter | 9.4 | Counter for ETag cache hit. | `endpoint` |
-| `gitlab_transaction_event_etag_caching_header_missing_total` | Counter | 9.4 | Counter for ETag cache miss - header missing | `endpoint` |
-| `gitlab_transaction_event_etag_caching_key_not_found_total` | Counter | 9.4 | Counter for ETag cache miss - key not found | `endpoint` |
-| `gitlab_transaction_event_etag_caching_middleware_used_total` | Counter | 9.4 | Counter for ETag middleware accessed | `endpoint` |
-| `gitlab_transaction_event_etag_caching_resource_changed_total` | Counter | 9.4 | Counter for ETag cache miss - resource changed | `endpoint` |
-| `gitlab_transaction_event_fork_repository_total` | Counter | 9.4 | Counter for repository forks (RepositoryForkWorker). Only incremented when source repository exists | |
-| `gitlab_transaction_event_import_repository_total` | Counter | 9.4 | Counter for repository imports (RepositoryImportWorker) | |
-| `gitlab_transaction_event_push_branch_total` | Counter | 9.4 | Counter for all branch pushes | |
-| `gitlab_transaction_event_push_commit_total` | Counter | 9.4 | Counter for commits | `branch` |
-| `gitlab_transaction_event_push_tag_total` | Counter | 9.4 | Counter for tag pushes | |
-| `gitlab_transaction_event_rails_exception_total` | Counter | 9.4 | Counter for number of rails exceptions | |
-| `gitlab_transaction_event_receive_email_total` | Counter | 9.4 | Counter for received emails | `handler` |
-| `gitlab_transaction_event_remote_mirrors_failed_total` | Counter | 10.8 | Counter for failed remote mirrors | |
-| `gitlab_transaction_event_remote_mirrors_finished_total` | Counter | 10.8 | Counter for finished remote mirrors | |
-| `gitlab_transaction_event_remote_mirrors_running_total` | Counter | 10.8 | Counter for running remote mirrors | |
-| `gitlab_transaction_event_remove_branch_total` | Counter | 9.4 | Counter when a branch is removed for any repository | |
-| `gitlab_transaction_event_remove_repository_total` | Counter | 9.4 | Counter when a repository is removed | |
-| `gitlab_transaction_event_remove_tag_total` | Counter | 9.4 | Counter when a tag is remove for any repository | |
-| `gitlab_transaction_event_sidekiq_exception_total` | Counter | 9.4 | Counter of Sidekiq exceptions | |
-| `gitlab_transaction_event_stuck_import_jobs_total` | Counter | 9.4 | Count of stuck import jobs | `projects_without_jid_count`, `projects_with_jid_count` |
-| `gitlab_transaction_event_update_build_total` | Counter | 9.4 | Counter for update build for API `/jobs/request/:id` | |
-| `gitlab_transaction_new_redis_connections_total` | Counter | 9.4 | Counter for new Redis connections | |
-| `gitlab_transaction_queue_duration_total` | Counter | 9.4 | Duration jobs were enqueued before processing | |
-| `gitlab_transaction_rails_queue_duration_total` | Counter | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | `controller`, `action` |
-| `gitlab_transaction_view_duration_total` | Counter | 9.4 | Duration for views | `controller`, `action`, `view` |
-| `gitlab_view_rendering_duration_seconds` | Histogram | 10.2 | Duration for views (histogram) | `controller`, `action`, `view` |
-| `http_requests_total` | Counter | 9.4 | Rack request count | `method`, `status` |
-| `http_request_duration_seconds` | Histogram | 9.4 | HTTP response time from rack middleware | `method` |
-| `gitlab_transaction_db_count_total` | Counter | 13.1 | Counter for total number of SQL calls | `controller`, `action` |
-| `gitlab_transaction_db_write_count_total` | Counter | 13.1 | Counter for total number of write SQL calls | `controller`, `action` |
-| `gitlab_transaction_db_cached_count_total` | Counter | 13.1 | Counter for total number of cached SQL calls | `controller`, `action` |
-| `http_elasticsearch_requests_duration_seconds` **(STARTER)** | Histogram | 13.1 | Elasticsearch requests duration during web transactions | `controller`, `action` |
-| `http_elasticsearch_requests_total` **(STARTER)** | Counter | 13.1 | Elasticsearch requests count during web transactions | `controller`, `action` |
-| `pipelines_created_total` | Counter | 9.4 | Counter of pipelines created | |
-| `rack_uncaught_errors_total` | Counter | 9.4 | Rack connections handling uncaught errors count | |
-| `user_session_logins_total` | Counter | 9.4 | Counter of how many users have logged in since GitLab was started or restarted | |
-| `upload_file_does_not_exist` | Counter | 10.7 in EE, 11.5 in CE | Number of times an upload record could not find its file | |
-| `failed_login_captcha_total` | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login | |
-| `successful_login_captcha_total` | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login | |
-| `auto_devops_pipelines_completed_total` | Counter | 12.7 | Counter of completed Auto DevOps pipelines, labeled by status | |
-| `gitlab_metrics_dashboard_processing_time_ms` | Summary | 12.10 | Metrics dashboard processing time in milliseconds | service, stages |
-| `action_cable_active_connections` | Gauge | 13.4 | Number of ActionCable WS clients currently connected | `server_mode` |
-| `action_cable_pool_min_size` | Gauge | 13.4 | Minimum number of worker threads in ActionCable thread pool | `server_mode` |
-| `action_cable_pool_max_size` | Gauge | 13.4 | Maximum number of worker threads in ActionCable thread pool | `server_mode` |
-| `action_cable_pool_current_size` | Gauge | 13.4 | Current number of worker threads in ActionCable thread pool | `server_mode` |
-| `action_cable_pool_largest_size` | Gauge | 13.4 | Largest number of worker threads observed so far in ActionCable thread pool | `server_mode` |
-| `action_cable_pool_pending_tasks` | Gauge | 13.4 | Number of tasks waiting to be executed in ActionCable thread pool | `server_mode` |
-| `action_cable_pool_tasks_total` | Gauge | 13.4 | Total number of tasks executed in ActionCable thread pool | `server_mode` |
-| `gitlab_issuable_fast_count_by_state_total` | Counter | 13.5 | Total number of row count operations on issue/merge request list pages | |
-| `gitlab_issuable_fast_count_by_state_failures_total` | Counter | 13.5 | Number of soft-failed row count operations on issue/merge request list pages | |
+| Metric | Type | Since | Description | Labels |
+|:---------------------------------------------------------------|:----------|------:|:------------------------------------------------------------------------------------------------------|:--------------------------------------------------------|
+| `gitlab_banzai_cached_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output exists | `controller`, `action` |
+| `gitlab_banzai_cacheless_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output does not exist | `controller`, `action` |
+| `gitlab_cache_misses_total` | Counter | 10.2 | Cache read miss | `controller`, `action` |
+| `gitlab_cache_operation_duration_seconds` | Histogram | 10.2 | Cache access time | |
+| `gitlab_cache_operations_total` | Counter | 12.2 | Cache operations by controller or action | `controller`, `action`, `operation` |
+| `gitlab_ci_pipeline_creation_duration_seconds` | Histogram | 13.0 | Time in seconds it takes to create a CI/CD pipeline | |
+| `gitlab_ci_pipeline_size_builds` | Histogram | 13.1 | Total number of builds within a pipeline grouped by a pipeline source | `source` |
+| `job_waiter_started_total` | Counter | 12.9 | Number of batches of jobs started where a web request is waiting for the jobs to complete | `worker` |
+| `job_waiter_timeouts_total` | Counter | 12.9 | Number of batches of jobs that timed out where a web request is waiting for the jobs to complete | `worker` |
+| `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_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_ruby_threads_max_expected_threads` | Gauge | 13.3 | Maximum number of threads expected to be running and performing application work | |
+| `gitlab_ruby_threads_running_threads` | Gauge | 13.3 | Number of running Ruby threads by name | |
+| `gitlab_transaction_cache_<key>_count_total` | Counter | 10.2 | Counter for total Rails cache calls (per key) | |
+| `gitlab_transaction_cache_<key>_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (per key) | |
+| `gitlab_transaction_cache_count_total` | Counter | 10.2 | Counter for total Rails cache calls (aggregate) | |
+| `gitlab_transaction_cache_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (aggregate) | |
+| `gitlab_transaction_cache_read_hit_count_total` | Counter | 10.2 | Counter for cache hits for Rails cache calls | `controller`, `action` |
+| `gitlab_transaction_cache_read_miss_count_total` | Counter | 10.2 | Counter for cache misses for Rails cache calls | `controller`, `action` |
+| `gitlab_transaction_duration_seconds` | Histogram | 10.2 | Duration for all transactions (`gitlab_transaction_*` metrics) | `controller`, `action` |
+| `gitlab_transaction_event_build_found_total` | Counter | 9.4 | Counter for build found for API /jobs/request | |
+| `gitlab_transaction_event_build_invalid_total` | Counter | 9.4 | Counter for build invalid due to concurrency conflict for API /jobs/request | |
+| `gitlab_transaction_event_build_not_found_cached_total` | Counter | 9.4 | Counter for cached response of build not found for API /jobs/request | |
+| `gitlab_transaction_event_build_not_found_total` | Counter | 9.4 | Counter for build not found for API /jobs/request | |
+| `gitlab_transaction_event_change_default_branch_total` | Counter | 9.4 | Counter when default branch is changed for any repository | |
+| `gitlab_transaction_event_create_repository_total` | Counter | 9.4 | Counter when any repository is created | |
+| `gitlab_transaction_event_etag_caching_cache_hit_total` | Counter | 9.4 | Counter for ETag cache hit. | `endpoint` |
+| `gitlab_transaction_event_etag_caching_header_missing_total` | Counter | 9.4 | Counter for ETag cache miss - header missing | `endpoint` |
+| `gitlab_transaction_event_etag_caching_key_not_found_total` | Counter | 9.4 | Counter for ETag cache miss - key not found | `endpoint` |
+| `gitlab_transaction_event_etag_caching_middleware_used_total` | Counter | 9.4 | Counter for ETag middleware accessed | `endpoint` |
+| `gitlab_transaction_event_etag_caching_resource_changed_total` | Counter | 9.4 | Counter for ETag cache miss - resource changed | `endpoint` |
+| `gitlab_transaction_event_fork_repository_total` | Counter | 9.4 | Counter for repository forks (RepositoryForkWorker). Only incremented when source repository exists | |
+| `gitlab_transaction_event_import_repository_total` | Counter | 9.4 | Counter for repository imports (RepositoryImportWorker) | |
+| `gitlab_transaction_event_patch_hard_limit_bytes_hit_total` | Counter | 13.9 | Counter for diff patch size limit hits | |
+| `gitlab_transaction_event_push_branch_total` | Counter | 9.4 | Counter for all branch pushes | |
+| `gitlab_transaction_event_push_commit_total` | Counter | 9.4 | Counter for commits | `branch` |
+| `gitlab_transaction_event_push_tag_total` | Counter | 9.4 | Counter for tag pushes | |
+| `gitlab_transaction_event_rails_exception_total` | Counter | 9.4 | Counter for number of rails exceptions | |
+| `gitlab_transaction_event_receive_email_total` | Counter | 9.4 | Counter for received emails | `handler` |
+| `gitlab_transaction_event_remote_mirrors_failed_total` | Counter | 10.8 | Counter for failed remote mirrors | |
+| `gitlab_transaction_event_remote_mirrors_finished_total` | Counter | 10.8 | Counter for finished remote mirrors | |
+| `gitlab_transaction_event_remote_mirrors_running_total` | Counter | 10.8 | Counter for running remote mirrors | |
+| `gitlab_transaction_event_remove_branch_total` | Counter | 9.4 | Counter when a branch is removed for any repository | |
+| `gitlab_transaction_event_remove_repository_total` | Counter | 9.4 | Counter when a repository is removed | |
+| `gitlab_transaction_event_remove_tag_total` | Counter | 9.4 | Counter when a tag is remove for any repository | |
+| `gitlab_transaction_event_sidekiq_exception_total` | Counter | 9.4 | Counter of Sidekiq exceptions | |
+| `gitlab_transaction_event_stuck_import_jobs_total` | Counter | 9.4 | Count of stuck import jobs | `projects_without_jid_count`, `projects_with_jid_count` |
+| `gitlab_transaction_event_update_build_total` | Counter | 9.4 | Counter for update build for API `/jobs/request/:id` | |
+| `gitlab_transaction_new_redis_connections_total` | Counter | 9.4 | Counter for new Redis connections | |
+| `gitlab_transaction_queue_duration_total` | Counter | 9.4 | Duration jobs were enqueued before processing | |
+| `gitlab_transaction_rails_queue_duration_total` | Counter | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | `controller`, `action` |
+| `gitlab_transaction_view_duration_total` | Counter | 9.4 | Duration for views | `controller`, `action`, `view` |
+| `gitlab_view_rendering_duration_seconds` | Histogram | 10.2 | Duration for views (histogram) | `controller`, `action`, `view` |
+| `http_requests_total` | Counter | 9.4 | Rack request count | `method`, `status` |
+| `http_request_duration_seconds` | Histogram | 9.4 | HTTP response time from rack middleware | `method` |
+| `gitlab_transaction_db_count_total` | Counter | 13.1 | Counter for total number of SQL calls | `controller`, `action` |
+| `gitlab_transaction_db_write_count_total` | Counter | 13.1 | Counter for total number of write SQL calls | `controller`, `action` |
+| `gitlab_transaction_db_cached_count_total` | Counter | 13.1 | Counter for total number of cached SQL calls | `controller`, `action` |
+| `http_elasticsearch_requests_duration_seconds` **(PREMIUM)** | Histogram | 13.1 | Elasticsearch requests duration during web transactions | `controller`, `action` |
+| `http_elasticsearch_requests_total` **(PREMIUM)** | Counter | 13.1 | Elasticsearch requests count during web transactions | `controller`, `action` |
+| `pipelines_created_total` | Counter | 9.4 | Counter of pipelines created | |
+| `rack_uncaught_errors_total` | Counter | 9.4 | Rack connections handling uncaught errors count | |
+| `user_session_logins_total` | Counter | 9.4 | Counter of how many users have logged in since GitLab was started or restarted | |
+| `upload_file_does_not_exist` | Counter | 10.7 | Number of times an upload record could not find its file. Made available in all tiers in GitLab 11.5. | |
+| `failed_login_captcha_total` | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login | |
+| `successful_login_captcha_total` | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login | |
+| `auto_devops_pipelines_completed_total` | Counter | 12.7 | Counter of completed Auto DevOps pipelines, labeled by status | |
+| `gitlab_metrics_dashboard_processing_time_ms` | Summary | 12.10 | Metrics dashboard processing time in milliseconds | service, stages |
+| `action_cable_active_connections` | Gauge | 13.4 | Number of ActionCable WS clients currently connected | `server_mode` |
+| `action_cable_pool_min_size` | Gauge | 13.4 | Minimum number of worker threads in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_max_size` | Gauge | 13.4 | Maximum number of worker threads in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_current_size` | Gauge | 13.4 | Current number of worker threads in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_largest_size` | Gauge | 13.4 | Largest number of worker threads observed so far in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_pending_tasks` | Gauge | 13.4 | Number of tasks waiting to be executed in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_tasks_total` | Gauge | 13.4 | Total number of tasks executed in ActionCable thread pool | `server_mode` |
+| `gitlab_issuable_fast_count_by_state_total` | Counter | 13.5 | Total number of row count operations on issue/merge request list pages | |
+| `gitlab_issuable_fast_count_by_state_failures_total` | Counter | 13.5 | Number of soft-failed row count operations on issue/merge request list pages | |
+| `gitlab_external_http_total` | Counter | 13.8 | Total number of HTTP calls to external systems | `controller`, `action` |
+| `gitlab_external_http_duration_seconds` | Counter | 13.8 | Duration in seconds spent on each HTTP call to external systems | |
+| `gitlab_external_http_exception_total` | Counter | 13.8 | Total number of exceptions raised when making external HTTP calls | |
+| `ci_report_parser_duration_seconds` | Histogram | 13.9 | Time to parse CI/CD report artifacts | `parser` |
+| `pipeline_graph_link_calculation_duration_seconds` | Histogram | 13.9 | Total time spent calculating links, in seconds | |
+| `pipeline_graph_links_total` | Histogram | 13.9 | Number of links per graph | |
+| `pipeline_graph_links_per_job_ratio` | Histogram | 13.9 | Ratio of links to job per graph | |
## Metrics controlled by a feature flag
@@ -212,7 +220,7 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `destroyed_job_artifacts_count_total` | Counter | 13.6 | Number of destroyed expired job artifacts | |
| `destroyed_pipeline_artifacts_count_total` | Counter | 13.8 | Number of destroyed expired pipeline artifacts | |
-## Database load balancing metrics **(PREMIUM ONLY)**
+## Database load balancing metrics **(PREMIUM SELF)**
The following metrics are available:
@@ -220,7 +228,7 @@ The following metrics are available:
|:--------------------------------- |:--------- |:------------------------------------------------------------- |:-------------------------------------- |
| `db_load_balancing_hosts` | Gauge | [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/13630) | Current number of load balancing hosts |
-## Database partitioning metrics **(PREMIUM ONLY)**
+## Database partitioning metrics **(PREMIUM SELF)**
The following metrics are available:
diff --git a/doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md b/doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md
deleted file mode 100644
index 8fa2e16dcd0..00000000000
--- a/doc/administration/monitoring/prometheus/gitlab_monitor_exporter.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'gitlab_exporter.md'
----
-
-This document was moved to [another location](gitlab_exporter.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index 80ddb87e727..23bffae99cf 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -4,7 +4,12 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring GitLab with Prometheus
+# Monitoring GitLab with Prometheus **(FREE SELF)**
+
+[Prometheus](https://prometheus.io) is a powerful time-series monitoring service, providing a flexible
+platform for monitoring GitLab and other software products.
+GitLab provides out-of-the-box monitoring with Prometheus, providing easy
+access to high quality time-series monitoring of GitLab services.
> **Notes:**
>
@@ -16,11 +21,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Prometheus and its exporters don't authenticate users, and are available
> to anyone who can access them.
-[Prometheus](https://prometheus.io) is a powerful time-series monitoring service, providing a flexible
-platform for monitoring GitLab and other software products.
-GitLab provides out of the box monitoring with Prometheus, providing easy
-access to high quality time-series monitoring of GitLab services.
-
## Overview
Prometheus works by periodically connecting to data sources and collecting their
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
index f27912d5806..6efc9d67e8d 100644
--- a/doc/administration/monitoring/prometheus/node_exporter.md
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Node exporter
+# Node exporter **(FREE SELF)**
The [node exporter](https://github.com/prometheus/node_exporter) enables you to measure
various machine resources such as memory, disk and CPU utilization.
diff --git a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
index 0dffad59793..df2aa08efaa 100644
--- a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# PgBouncer exporter
+# PgBouncer exporter **(FREE SELF)**
> Introduced in [Omnibus GitLab 11.0](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2493).
diff --git a/doc/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
index 8bc61ff53bb..8b6d3d82018 100644
--- a/doc/administration/monitoring/prometheus/postgres_exporter.md
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# PostgreSQL Server Exporter
+# PostgreSQL Server Exporter **(FREE SELF)**
The [PostgreSQL Server Exporter](https://github.com/wrouesnel/postgres_exporter) allows you to export various PostgreSQL metrics.
diff --git a/doc/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
index 03c215625ec..e9d656a6493 100644
--- a/doc/administration/monitoring/prometheus/redis_exporter.md
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Redis exporter
+# Redis exporter **(FREE SELF)**
The [Redis exporter](https://github.com/oliver006/redis_exporter) enables you to measure
various [Redis](https://redis.io) metrics. For more information on what is exported,
diff --git a/doc/administration/monitoring/prometheus/registry_exporter.md b/doc/administration/monitoring/prometheus/registry_exporter.md
index 009d94491f3..d2bd86aa908 100644
--- a/doc/administration/monitoring/prometheus/registry_exporter.md
+++ b/doc/administration/monitoring/prometheus/registry_exporter.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Registry exporter
+# Registry exporter **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2884) in GitLab 11.9.
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index bddf770180b..a7009b702ed 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -20,10 +20,10 @@ From GitLab 14.0, technical support for NFS for Git repositories
will no longer be provided. Upgrade to [Gitaly Cluster](gitaly/praefect.md)
as soon as possible.
-Filesystem performance can impact overall GitLab performance, especially for
+File system performance can impact overall GitLab performance, especially for
actions that read or write to Git repositories. For steps you can use to test
-filesystem performance, see
-[Filesystem Performance Benchmarking](operations/filesystem_benchmarking.md).
+file system performance, see
+[File system Performance Benchmarking](operations/filesystem_benchmarking.md).
## Known kernel version incompatibilities
@@ -408,7 +408,7 @@ For supported database architecture, see our documentation about
### Finding the requests that are being made to NFS
In case of NFS-related problems, it can be helpful to trace
-the filesystem requests that are being made by using `perf`:
+the file system requests that are being made by using `perf`:
```shell
sudo perf trace -e 'nfs4:*' -p $(pgrep -fd ',' puma && pgrep -fd ',' unicorn)
diff --git a/doc/administration/npm_registry.md b/doc/administration/npm_registry.md
deleted file mode 100644
index 690b6785941..00000000000
--- a/doc/administration/npm_registry.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'packages/index.md'
----
-
-This document was moved to [another location](packages/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 999d9b87363..3cad18dc497 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -75,8 +75,7 @@ types. If you want to use local storage for specific object types, you can
Most types of objects, such as CI artifacts, LFS files, upload
attachments, and so on can be saved in object storage by specifying a single
-credential for object storage with multiple buckets. A [different bucket
-for each type must be used](#use-separate-buckets).
+credential for object storage with multiple buckets.
When the consolidated form is:
@@ -551,19 +550,18 @@ supported by consolidated configuration form, refer to the following guides:
| [Merge request diffs](merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](packages/index.md#using-object-storage) (optional feature) | Yes |
-| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
-| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM SELF)** | Yes |
+| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](terraform_state.md#using-object-storage) | Yes |
| [GitLab Pages content](pages/index.md#using-object-storage) | Yes |
-### Other alternatives to filesystem storage
+### Other alternatives to file system storage
If you're working to [scale out](reference_architectures/index.md) your GitLab implementation,
or add fault tolerance and redundancy, you may be
-looking at removing dependencies on block or network filesystems.
-See the following additional guides and
-[note that Pages requires disk storage](#gitlab-pages-requires-nfs):
+looking at removing dependencies on block or network file systems.
+See the following additional guides:
1. Make sure the [`git` user home directory](https://docs.gitlab.com/omnibus/settings/configuration.html#moving-the-home-directory-for-a-user) is on local disk.
1. Configure [database lookup of SSH keys](operations/fast_ssh_key_lookup.md)
@@ -572,22 +570,13 @@ See the following additional guides and
## Warnings, limitations, and known issues
-### Use separate buckets
+### Separate buckets required when using Helm
-Using separate buckets for each data type is the recommended approach for GitLab.
+Generally, using the same bucket for your Object Storage is fine to do
+for convenience.
-A limitation of our configuration is that each use of object storage is separately configured.
-[We have an issue for improving this](https://gitlab.com/gitlab-org/gitlab/-/issues/23345)
-and easily using one bucket with separate folders is one improvement that this might bring.
-
-There is at least one specific issue with using the same bucket:
-when GitLab is deployed with the Helm chart restore from backup
-[will not properly function](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer)
-unless separate buckets are used.
-
-One risk of using a single bucket would be that if your organisation decided to
-migrate GitLab to the Helm deployment in the future. GitLab would run, but the situation with
-backups might not be realised until the organisation had a critical requirement for the backups to work.
+However, if you're using or planning to use Helm, separate buckets will
+be required as there is a [known limitation with restorations of Helm chart backups](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer).
### S3 API compatibility issues
@@ -598,17 +587,6 @@ with the Fog library that GitLab uses. Symptoms include an error in `production.
411 Length Required
```
-### GitLab Pages requires NFS
-
-If you're working to add more GitLab servers for [scaling or fault tolerance](reference_architectures/index.md)
-and one of your requirements is [GitLab Pages](../user/project/pages/index.md) this currently requires
-NFS. There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)
-to remove this dependency. In the future, GitLab Pages may use
-[object storage](https://gitlab.com/gitlab-org/gitlab/-/issues/208135).
-
-The dependency on disk storage also prevents Pages being deployed using the
-[GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37).
-
### Incremental logging is required for CI to use object storage
If you configure GitLab to use object storage for CI logs and artifacts,
diff --git a/doc/administration/operations.md b/doc/administration/operations.md
deleted file mode 100644
index cfabb5ec27d..00000000000
--- a/doc/administration/operations.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'operations/index.md'
----
-
-This document was moved to [another location](operations/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 1b7c0edab04..d07afb3bb14 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Run multiple Sidekiq processes **(CORE ONLY)**
+# Run multiple Sidekiq processes **(FREE SELF)**
GitLab allows you to start multiple Sidekiq processes.
These processes can be used to consume a dedicated set
@@ -27,7 +27,7 @@ can be started.
## Start multiple processes
> - [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4006) in GitLab 12.10, starting multiple processes with Sidekiq cluster.
-> - [Sidekiq cluster moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 12.10.
+> - [Sidekiq cluster moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
> - [Sidekiq cluster became default](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140) in GitLab 13.0.
To start multiple processes:
@@ -112,8 +112,8 @@ you list:
## Queue selector
-> - [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
-> - [Sidekiq cluster including queue selector moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 12.10.
+> - [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in GitLab 12.8.
+> - [Sidekiq cluster, including queue selector, moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
> - [Renamed from `experimental_queue_selector` to `queue_selector`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab 13.6.
In addition to selecting queues by name, as above, the `queue_selector`
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index b93af074795..330bd9a43da 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -224,5 +224,5 @@ the database. The following instructions can be used to build OpenSSH 7.5:
GitLab supports `authorized_keys` database lookups with [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux).
Because the SELinux policy is static, GitLab doesn't support the ability to change
-internal Unicorn ports at the moment. Admins would have to create a special `.te`
+internal Unicorn ports at the moment. Administrators would have to create a special `.te`
file for the environment, since it isn't generated dynamically.
diff --git a/doc/administration/operations/filesystem_benchmarking.md b/doc/administration/operations/filesystem_benchmarking.md
index 9072214eb02..6119fcdae45 100644
--- a/doc/administration/operations/filesystem_benchmarking.md
+++ b/doc/administration/operations/filesystem_benchmarking.md
@@ -4,15 +4,15 @@ 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
---
-# Filesystem Performance Benchmarking
+# File system Performance Benchmarking
-Filesystem performance has a big impact on overall GitLab performance,
+File system performance has a big impact on overall GitLab performance,
especially for actions that read or write to Git repositories. This information
-will help benchmark filesystem performance against known good and bad real-world
+will help benchmark file system performance against known good and bad real-world
systems.
-Normally when talking about filesystem performance the biggest concern is
-with Network Filesystems (NFS). However, even some local disks can have slow
+Normally when talking about file system performance the biggest concern is
+with Network File Systems (NFS). However, even some local disks can have slow
I/O. The information on this page can be used for either scenario.
## Executing benchmarks
@@ -77,7 +77,7 @@ available on the system. It's possible to receive good results on this
test but still have poor performance due to read speed and various other
factors.
-The following one-line commands provide a quick benchmark for filesystem write and read
+The following one-line commands provide a quick benchmark for file system write and read
performance. This will write 1,000 small files to the directory in which it is
executed, and then read the same 1,000 files.
@@ -125,4 +125,4 @@ sys 0m1.663s
```
From experience with multiple customers, this task should take under 10
-seconds to indicate good filesystem performance.
+seconds to indicate good file system performance.
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index b15417ea8d9..708861d8529 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -13,24 +13,24 @@ Keep your GitLab instance up and running smoothly.
you have been running a large GitLab server (thousands of users) since before
GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
database after you upgrade to GitLab 7.3.
-- [Rake tasks](../../raketasks/README.md): Tasks for common administration and operational processes such as
+- [Rake tasks](../../raketasks/index.md): Tasks for common administration and operational processes such as
[cleaning up unneeded items from GitLab instance](../../raketasks/cleanup.md), integrity checks,
and more.
- [Moving repositories](moving_repositories.md): Moving all repositories managed
by GitLab to another file system or another server.
- [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller
to restart Sidekiq.
-- [Multiple Sidekiq processes](extra_sidekiq_processes.md): Configure multiple Sidekiq processes to ensure certain queues always have dedicated workers, no matter the number of jobs that need to be processed. **(CORE ONLY)**
+- [Multiple Sidekiq processes](extra_sidekiq_processes.md): Configure multiple Sidekiq processes to ensure certain queues always have dedicated workers, no matter the number of jobs that need to be processed. **(FREE SELF)**
- [Puma](puma.md): Understand Puma and puma-worker-killer.
- [Unicorn](unicorn.md): Understand Unicorn and unicorn-worker-killer.
- Speed up SSH operations by [Authorizing SSH users via a fast,
indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
by [doing away with user SSH keys stored on GitLab entirely in favor
of SSH certificates](ssh_certificates.md).
-- [Filesystem Performance Benchmarking](filesystem_benchmarking.md): Filesystem
+- [File System Performance Benchmarking](filesystem_benchmarking.md): File system
performance can have a big impact on GitLab performance, especially for actions
that read or write Git repositories. This information will help benchmark
- filesystem performance against known good and bad real-world systems.
+ file system performance against known good and bad real-world systems.
- [The Rails Console](rails_console.md): Provides a way to interact with your GitLab instance from the command line.
Used for troubleshooting a problem or retrieving some data that can only be done through direct access to GitLab.
- [ChatOps Scripts](https://gitlab.com/gitlab-com/chatops): The GitLab.com Infrastructure team uses this repository to house
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 029f3bb01ed..da3b3dbbc15 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Moving repositories managed by GitLab **(CORE ONLY)**
+# Moving repositories managed by GitLab **(FREE SELF)**
Sometimes you need to move all repositories managed by GitLab to
another file system or another server.
@@ -20,25 +20,23 @@ The GitLab API is the recommended way to move Git repositories:
For more information, see:
-- [Configuring additional storage for Gitaly](../gitaly/index.md#network-architecture). Within this
- example, additional storage called `storage1` and `storage2` is configured.
+- [Configuring additional storage for Gitaly](../gitaly/index.md#network-architecture). This
+ example configures additional storage called `storage1` and `storage2`.
- [The API documentation](../../api/project_repository_storage_moves.md) details the endpoints for
querying and scheduling project repository moves.
- [The API documentation](../../api/snippet_repository_storage_moves.md) details the endpoints for
querying and scheduling snippet repository moves.
+- [The API documentation](../../api/group_repository_storage_moves.md) details the endpoints for
+ querying and scheduling group repository moves **(PREMIUM SELF)**.
- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
-### Limitations
-
-Read more in the [API documentation for projects](../../api/project_repository_storage_moves.md#limitations) and the [API documentation for snippets](../../api/snippet_repository_storage_moves.md#limitations).
-
## Migrating to another GitLab instance
[Using the API](#moving-data-within-a-gitlab-instance) isn't an option if you are migrating to a new
GitLab environment, for example:
- From a single-node GitLab to a scaled-out architecture.
-- From a GitLab instance in your private datacenter to a cloud provider.
+- From a GitLab instance in your private data center to a cloud provider.
The rest of the document looks
at some of the ways you can copy all your repositories from
@@ -103,8 +101,8 @@ Using `rsync` to migrate Git data can cause data loss and repository corruption.
If the target directory already contains a partial / outdated copy
of the repositories it may be wasteful to copy all the data again
with `tar`. In this scenario it is better to use `rsync`. This utility
-is either already installed on your system or easily installable
-via `apt`, `yum`, and so on.
+is either already installed on your system, or installable
+by using `apt` or `yum`.
```shell
sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
@@ -112,7 +110,7 @@ sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
```
The `/.` in the command above is very important, without it you can
-easily get the wrong directory structure in the target directory.
+get the wrong directory structure in the target directory.
If you want to see progress, replace `-a` with `-av`.
#### Single `rsync` to another server
@@ -135,20 +133,23 @@ WARNING:
Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
-Every time you start an `rsync` job it has to inspect all files in
-the source directory, all files in the target directory, and then
-decide what files to copy or not. If the source or target directory
-has many contents this startup phase of `rsync` can become a burden
-for your GitLab server. In cases like this you can make `rsync`'s
-life easier by dividing its work in smaller pieces, and sync one
-repository at a time.
+Every time you start an `rsync` job it must:
+
+- Inspect all files in the source directory.
+- Inspect all files in the target directory.
+- Decide whether or not to copy files.
+
+If the source or target directory
+has many contents, this startup phase of `rsync` can become a burden
+for your GitLab server. You can reduce the workload of `rsync` by dividing its
+work in smaller pieces, and sync one repository at a time.
In addition to `rsync` we use [GNU Parallel](http://www.gnu.org/software/parallel/).
-This utility is not included in GitLab so you need to install it yourself with `apt`
-or `yum`. Also note that the GitLab scripts we used below were added in GitLab 8.1.
+This utility is not included in GitLab, so you must install it yourself with `apt`
+or `yum`.
-**This process does not clean up repositories at the target location that no
-longer exist at the source.**
+This process does not clean up repositories at the target location that no
+longer exist at the source.
#### Parallel `rsync` for all repositories known to GitLab
@@ -218,8 +219,8 @@ Using `rsync` to migrate Git data can cause data loss and repository corruption.
[These instructions are being reviewed](https://gitlab.com/gitlab-org/gitlab/-/issues/270422).
Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
-Then you might only want to sync repositories that were changed via GitLab
-_after_ that time. You can use the `SINCE` variable to tell `rake
+Then you might only want to sync repositories that were changed by using GitLab
+after that time. You can use the `SINCE` variable to tell `rake
gitlab:list_repos` to only print repositories with recent activity.
```shell
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 44ac014650e..3b676010bfe 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -31,7 +31,7 @@ Unicorn in GitLab 14.0.
When switching to Puma, Unicorn server configuration
will _not_ carry over automatically, due to differences between the two application servers. For Omnibus-based
deployments, see [Configuring Puma Settings](https://docs.gitlab.com/omnibus/settings/puma.html#configuring-puma-settings).
-For Helm based deployments, see the [Webservice Chart documentation](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html).
+For Helm based deployments, see the [`webservice` chart documentation](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html).
Additionally we strongly recommend that multi-node deployments [configure their load balancers to use the readiness check](../load_balancer.md#readiness-check) due to a difference between Unicorn and Puma in how they handle connections during a restart of the service.
diff --git a/doc/administration/operations/speed_up_ssh.md b/doc/administration/operations/speed_up_ssh.md
deleted file mode 100644
index 2f3cf40a222..00000000000
--- a/doc/administration/operations/speed_up_ssh.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'fast_ssh_key_lookup.md'
----
-
-This document was moved to [another location](fast_ssh_key_lookup.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/packages.md b/doc/administration/packages.md
deleted file mode 100644
index 690b6785941..00000000000
--- a/doc/administration/packages.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'packages/index.md'
----
-
-This document was moved to [another location](packages/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index ab6202fef4c..63bb969afce 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -312,14 +312,14 @@ configuration.
The different supported drivers are:
-| Driver | Description |
-|------------|-------------------------------------|
-| filesystem | Uses a path on the local filesystem |
-| Azure | Microsoft Azure Blob Storage |
-| gcs | Google Cloud Storage |
-| s3 | Amazon Simple Storage Service. Be sure to configure your storage bucket with the correct [S3 Permission Scopes](https://docs.docker.com/registry/storage-drivers/s3/#s3-permission-scopes). |
-| swift | OpenStack Swift Object Storage |
-| oss | Aliyun OSS |
+| Driver | Description |
+|--------------|--------------------------------------|
+| `filesystem` | Uses a path on the local file system |
+| `Azure` | Microsoft Azure Blob Storage |
+| `gcs` | Google Cloud Storage |
+| `s3` | Amazon Simple Storage Service. Be sure to configure your storage bucket with the correct [S3 Permission Scopes](https://docs.docker.com/registry/storage-drivers/s3/#s3-permission-scopes). |
+| `swift` | OpenStack Swift Object Storage |
+| `oss` | Aliyun OSS |
Although most S3 compatible services (like [MinIO](https://min.io/)) should work with the Container Registry, we only guarantee support for AWS S3. Because we cannot assert the correctness of third-party S3 implementations, we can debug issues, but we cannot patch the registry unless an issue is reproducible against an AWS S3 bucket.
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
index 9e315722c24..16cfdc8c784 100644
--- a/doc/administration/packages/dependency_proxy.md
+++ b/doc/administration/packages/dependency_proxy.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Dependency Proxy administration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Core](https://about.gitlab.com/pricing/) in GitLab 13.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Free](https://about.gitlab.com/pricing/) in GitLab 13.6.
GitLab can be used as a dependency proxy for a variety of common package managers.
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 0f391371a6a..b1d2a82e31a 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -22,7 +22,7 @@ The Package Registry supports the following formats:
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/conan_repository/index.html">Conan</a></td><td>12.6+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/go_proxy/index.html">Go</a></td><td>13.1+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/maven_repository/index.html">Maven</a></td><td>11.3+</td></tr>
-<tr><td><a href="https://docs.gitlab.com/ee/user/packages/npm_registry/index.html">NPM</a></td><td>11.7+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/npm_registry/index.html">npm</a></td><td>11.7+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/nuget_repository/index.html">NuGet</a></td><td>12.8+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/pypi_repository/index.html">PyPI</a></td><td>12.10+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/generic_packages/index.html">Generic packages</a></td><td>13.5+</td></tr>
@@ -35,6 +35,8 @@ The Package Registry supports the following formats:
The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md)
guides you through the process.
+<!-- vale gitlab.Spelling = NO -->
+
| Format | Status |
| ------ | ------ |
| Chef | [#36889](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) |
@@ -51,6 +53,8 @@ guides you through the process.
| Terraform | [WIP: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
+<!-- vale gitlab.Spelling = YES -->
+
## Enabling the Packages feature
NOTE:
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 9e949468805..655e35c3e60 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -190,7 +190,7 @@ outside world.
### Additional configuration for Docker container
The GitLab Pages daemon doesn't have permissions to bind mounts when it runs
-in a Docker container. To overcome this issue, you must change the chroot
+in a Docker container. To overcome this issue, you must change the `chroot`
behavior:
1. Edit `/etc/gitlab/gitlab.rb`.
@@ -216,13 +216,13 @@ control over how the Pages daemon runs and serves content in your environment.
| Setting | Description |
| ------- | ----------- |
-| `pages_external_url` | The URL where GitLab Pages is accessible, including protocol (HTTP / HTTPS). If `https://` is used, you must also set `gitlab_pages['ssl_certificate']` and `gitlab_pages['ssl_certificate_key']`.
+| `pages_external_url` | The URL where GitLab Pages is accessible, including protocol (HTTP / HTTPS). If `https://` is used, additional configuration is required. See [Wildcard domains with TLS support](#wildcard-domains-with-tls-support) and [Custom domains with TLS support](#custom-domains-with-tls-support) for details.
| `gitlab_pages[]` | |
| `access_control` | Whether to enable [access control](index.md#access-control).
| `api_secret_key` | Full path to file with secret key used to authenticate with the GitLab API. Auto-generated when left unset.
| `artifacts_server` | Enable viewing [artifacts](../job_artifacts.md) in GitLab Pages.
| `artifacts_server_timeout` | Timeout (in seconds) for a proxied request to the artifacts server.
-| `artifacts_server_url` | API URL to proxy artifact requests to. Defaults to GitLab `external URL` + `/api/v4`, for example `https://gitlab.com/api/v4`.
+| `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.
| `dir` | Working directory for configuration and secrets files.
@@ -234,9 +234,10 @@ control over how the Pages daemon runs and serves content in your environment.
| `domain_config_source` | Domain configuration source (default: `auto`)
| `gitlab_id` | The OAuth application public ID. Leave blank to automatically fill when Pages authenticates with GitLab.
| `gitlab_secret` | The OAuth application secret. Leave blank to automatically fill when Pages authenticates with GitLab.
+| `auth_scope` | The OAuth application scope to use for authentication. Must match GitLab Pages OAuth application settings. Leave blank to use `api` scope by default.
| `gitlab_server` | Server to use for authentication when access control is enabled; defaults to GitLab `external_url`.
| `headers` | Specify any additional http headers that should be sent to the client with each response.
-| `inplace_chroot` | On [systems that don't support bind-mounts](index.md#additional-configuration-for-docker-container), this instructs GitLab Pages to chroot into its `pages_path` directory. Some caveats exist when using inplace chroot; refer to the GitLab Pages [README](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md#caveats) for more information.
+| `inplace_chroot` | On [systems that don't support bind-mounts](index.md#additional-configuration-for-docker-container), this instructs GitLab Pages to `chroot` into its `pages_path` directory. Some caveats exist when using in-place `chroot`; refer to the GitLab Pages [README](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md#caveats) for more information.
| `insecure_ciphers` | Use default list of cipher suites, may contain insecure ones like 3DES and RC4.
| `internal_gitlab_server` | Internal GitLab server address used exclusively for API requests. Useful if you want to send that traffic over an internal load balancer. Defaults to GitLab `external_url`.
| `listen_proxy` | The addresses to listen on for reverse-proxy requests. Pages binds to these addresses' network sockets and receives incoming requests from them. Sets the value of `proxy_pass` in `$nginx-dir/conf/gitlab-pages.conf`.
@@ -400,6 +401,25 @@ NOTE:
For this setting to be effective with multi-node setups, it has to be applied to
all the App nodes and Sidekiq nodes.
+#### Using Pages with reduced authentication scope
+
+By default, the Pages daemon uses the `api` scope to authenticate. You can configure this. For
+example, this reduces the scope to `read_api` in `/etc/gitlab/gitlab.rb`:
+
+```ruby
+gitlab_pages['auth_scope'] = 'read_api'
+```
+
+The scope to use for authentication must match the GitLab Pages OAuth application settings. Users of
+pre-existing applications must modify the GitLab Pages OAuth application. Follow these steps to do
+this:
+
+1. Navigate to your instance's **Admin Area > Settings > Applications** and expand **GitLab Pages**
+ settings.
+1. Clear the `api` scope's checkbox and select the desired scope's checkbox (for example,
+ `read_api`).
+1. Click **Save changes**.
+
#### Disabling public access to all Pages websites
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32095) in GitLab 12.7.
@@ -538,7 +558,7 @@ the below steps to do a no downtime transfer to a new storage location.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Verify Pages are still being served up as expected.
-1. Unpause Pages deployments by removing from `/etc/gitlab/gitlab.rb` the `sidekiq` setting set above.
+1. Resume Pages deployments by removing from `/etc/gitlab/gitlab.rb` the `sidekiq` setting set above.
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Trigger a new Pages deployment and verify it's working as expected.
1. Remove the old Pages storage location: `sudo rm -rf /var/opt/gitlab/gitlab-rails/shared/pages`
@@ -573,7 +593,7 @@ You can configure the maximum size of the unpacked archive per project in
**Admin Area > Settings > Preferences > Pages**, in **Maximum size of pages (MB)**.
The default is 100MB.
-### Override maximum pages size per project or group **(PREMIUM ONLY)**
+### Override maximum pages size per project or group **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16610) in GitLab 12.7.
@@ -629,7 +649,7 @@ database encryption. Proceed with caution.
on the **Pages server** and configure this share to
allow access from your main **GitLab server**.
Note that the example there is more general and
- shares several sub-directories from `/home` to several `/nfs/home` mountpoints.
+ shares several sub-directories from `/home` to several `/nfs/home` mount points.
For our Pages-specific example here, we instead share only the
default GitLab Pages folder `/var/opt/gitlab/gitlab-rails/shared/pages`
from the **Pages server** and we mount it to `/mnt/pages`
@@ -689,7 +709,7 @@ Pages server.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) in GitLab 13.3.
GitLab Pages can use different sources to get domain configuration.
-The default value is `nil`. However, GitLab Pages defaults to `auto`.
+The default value for Omnibus installations is `nil`.
```ruby
gitlab_pages['domain_config_source'] = nil
@@ -700,8 +720,33 @@ preferred source is `gitlab`, which uses [API-based configuration](#gitlab-api-b
For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/).
+### Deprecated domain_config_source
+
+WARNING:
+The flag `gitlab_pages['domain_config_source']` is deprecated for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913),
+and is planned for removal in GitLab 14.0.
+
+GitLab 13.0 introduced the special flag `domain_config_source` to support manual opt-in to
+[API-based configuration](#gitlab-api-based-configuration).
+GitLab 13.7 introduced the [`auto` value](https://gitlab.com/gitlab-org/gitlab/-/issues/218358)
+to support a smoother transition to API-based configuration.
+
+Starting with GitLab 14.0, GitLab Pages only supports API-based configuration, and
+[disk source configuration is removed](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382).
+Therefore, GitLab 14.0 also removes `domain_config_source`.
+
+GitLab Pages fails to start if it can't connect to the GitLab API. For other common issues, see the
+[troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api)
+or report an issue.
+
### GitLab API-based configuration
+WARNING:
+The flag `gitlab_pages['domain_config_source']` is deprecated for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913),
+and is planned for removal in GitLab 14.0. In GitLab 14.0 and later, GitLab Pages attempts to
+connect to the API automatically, without requiring the manual configuration steps shown here. Pages
+fails to start if this automatic connection fails.
+
GitLab Pages can use an API-based configuration. This replaces disk source configuration, which
was used prior to GitLab 13.0. Follow these steps to enable it:
@@ -730,6 +775,13 @@ or report an issue.
### Object storage settings
+WARNING:
+With the following settings, Pages uses both NFS and Object Storage locations when deploying the
+site. **Do not remove the existing NFS mount used by Pages** when applying these settings. For more
+information, see the epics
+[3901](https://gitlab.com/groups/gitlab-org/-/epics/3901#how-to-test-object-storage-integration-in-beta)
+and [3910](https://gitlab.com/groups/gitlab-org/-/epics/3910).
+
The following settings are:
- Nested under `pages:` and then `object_store:` on source installations.
@@ -818,7 +870,7 @@ but commented out to help encourage others to add to it in the future. -->
### `open /etc/ssl/ca-bundle.pem: permission denied`
-GitLab Pages runs inside a chroot jail, usually in a uniquely numbered directory like
+GitLab Pages runs inside a `chroot` jail, usually in a uniquely numbered directory like
`/tmp/gitlab-pages-*`.
Within the jail, a bundle of trusted certificates is
@@ -828,7 +880,7 @@ from `/opt/gitlab/embedded/ssl/certs/cacert.pem`
as part of starting up Pages.
If the permissions on the source file are incorrect (they should be `0644`), then
-the file inside the chroot jail is also wrong.
+the file inside the `chroot` jail is also wrong.
Pages logs errors in `/var/log/gitlab/gitlab-pages/current` like:
@@ -837,8 +889,8 @@ x509: failed to load system roots and no roots provided
open /etc/ssl/ca-bundle.pem: permission denied
```
-The use of a chroot jail makes this error misleading, as it is not
-referring to `/etc/ssl` on the root filesystem.
+The use of a `chroot` jail makes this error misleading, as it is not
+referring to `/etc/ssl` on the root file system.
The fix is to correct the source file permissions and restart Pages:
@@ -862,8 +914,8 @@ open /opt/gitlab/embedded/ssl/certs/cacert.pem: no such file or directory
x509: certificate signed by unknown authority
```
-The reason for those errors is that the files `resolv.conf` and `ca-bundle.pem` are missing inside the chroot.
-The fix is to copy the host's `/etc/resolv.conf` and the GitLab certificate bundle inside the chroot:
+The reason for those errors is that the files `resolv.conf` and `ca-bundle.pem` are missing inside the `chroot`.
+The fix is to copy the host's `/etc/resolv.conf` and the GitLab certificate bundle inside the `chroot`:
```shell
sudo mkdir -p /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl
@@ -895,7 +947,7 @@ gitlab_pages['listen_proxy'] = '127.0.0.1:8090'
### 404 error after transferring project to a different group or user
If you encounter a `404 Not Found` error a Pages site after transferring a project to
-another group or user, you must trigger adomain configuration update for Pages. To do
+another group or user, you must trigger a domain configuration update for Pages. To do
so, write something in the `.update` file. The Pages daemon monitors for changes to this
file, and reloads the configuration when changes occur.
@@ -928,11 +980,30 @@ For example, if there is a connection timeout:
error="failed to connect to internal Pages API: Get \"https://gitlab.example.com:3000/api/v4/internal/pages/status\": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)"
```
+### Pages cannot communicate with an instance of the GitLab API
+
+WARNING:
+The flag `gitlab_pages['domain_config_source']` is [deprecated](#deprecated-domain_config_source)
+for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913),
+and is planned for removal in GitLab 14.0.
+
+If you use the default value for `domain_config_source=auto` and run multiple instances of GitLab
+Pages, you may see intermittent 502 error responses while serving Pages content. You may also see
+the following warning in the Pages logs:
+
+```plaintext
+WARN[0010] Pages cannot communicate with an instance of the GitLab API. Please sync your gitlab-secrets.json file https://gitlab.com/gitlab-org/gitlab-pages/-/issues/535#workaround. error="pages endpoint unauthorized"
+```
+
+This can happen if your `gitlab-secrets.json` file is out of date between GitLab Rails and GitLab
+Pages. Follow steps 8-10 of [Running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server),
+in all of your GitLab Pages instances.
+
### 500 error with `securecookie: failed to generate random iv` and `Failed to save the session`
This problem most likely results from an [out-dated operating system](https://docs.gitlab.com/omnibus/package-information/deprecated_os.html).
-The [Pages daemon uses the `securecookie` library](https://gitlab.com/search?group_id=9970&project_id=734943&repository_ref=master&scope=blobs&search=securecookie&snippets=false) to get random strings via [crypto/rand in Go](https://golang.org/pkg/crypto/rand/#pkg-variables).
-This requires the `getrandom` syscall or `/dev/urandom` to be available on the host OS.
+The [Pages daemon uses the `securecookie` library](https://gitlab.com/search?group_id=9970&project_id=734943&repository_ref=master&scope=blobs&search=securecookie&snippets=false) to get random strings via [`crypto/rand` in Go](https://golang.org/pkg/crypto/rand/#pkg-variables).
+This requires the `getrandom` system call or `/dev/urandom` to be available on the host OS.
Upgrading to an [officially supported operating system](https://about.gitlab.com/install/) is recommended.
### The requested scope is invalid, malformed, or unknown
@@ -940,6 +1011,8 @@ Upgrading to an [officially supported operating system](https://about.gitlab.com
This problem comes from the permissions of the GitLab Pages OAuth application. To fix it, go to
**Admin > Applications > GitLab Pages** and edit the application. Under **Scopes**, ensure that the
`api` scope is selected and save your changes.
+When running a [separate Pages server](#running-gitlab-pages-on-a-separate-server),
+this setting needs to be configured on the main GitLab server.
### Workaround in case no wildcard DNS entry can be set
@@ -948,3 +1021,21 @@ If the wildcard DNS [prerequisite](#prerequisites) can't be met, you can still u
1. [Move](../../user/project/settings/index.md#transferring-an-existing-project-into-another-namespace)
all projects you need to use Pages with into a single group namespace, for example `pages`.
1. Configure a [DNS entry](#dns-configuration) without the `*.`-wildcard, for example `pages.example.io`.
+
+### Pages daemon fails with permission denied errors
+
+If `/tmp` is mounted with `noexec`, the Pages daemon fails to start with an error like:
+
+```plaintext
+{"error":"fork/exec /gitlab-pages: permission denied","level":"fatal","msg":"could not create pages daemon","time":"2021-02-02T21:54:34Z"}
+```
+
+In this case, change `TMPDIR` to a location that is not mounted with `noexec`. Add the following to
+`/etc/gitlab/gitlab.rb`:
+
+```ruby
+gitlab_pages['env'] = {'TMPDIR' => '<new_tmp_path>'}
+```
+
+Once added, reconfigure with `sudo gitlab-ctl reconfigure` and restart GitLab with
+`sudo gitlab-ctl restart`.
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 0aebeaf2ebe..d1a8b703860 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -407,7 +407,7 @@ Pages access control is disabled by default. To enable it:
```
1. [Restart GitLab](../restart_gitlab.md#installations-from-source).
-1. Create a new [system OAuth application](../../integration/oauth_provider.md#adding-an-application-through-the-profile).
+1. Create a new [system OAuth application](../../integration/oauth_provider.md#add-an-application-through-the-profile).
This should be called `GitLab Pages` and have a `Redirect URL` of
`https://projects.example.io/auth`. It does not need to be a "trusted"
application, but it does need the `api` scope.
diff --git a/doc/administration/plugins.md b/doc/administration/plugins.md
deleted file mode 100644
index f5d4b3aa2ff..00000000000
--- a/doc/administration/plugins.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'file_hooks.md'
----
-
-This document was moved to [File Hooks](file_hooks.md), after the Plugins feature was renamed to File Hooks.
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/postgresql/index.md b/doc/administration/postgresql/index.md
index 0e6fd757421..eabb396aeab 100644
--- a/doc/administration/postgresql/index.md
+++ b/doc/administration/postgresql/index.md
@@ -11,7 +11,7 @@ In this section, you'll be guided through configuring a PostgreSQL database to
be used with GitLab in one of our [reference architectures](../reference_architectures/index.md).
There are essentially three setups to choose from.
-## PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM ONLY)**
+## PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM SELF)**
This setup is for when you have installed GitLab using the
[Omnibus GitLab **Enterprise Edition** (EE) package](https://about.gitlab.com/install/?version=ee).
@@ -21,7 +21,7 @@ the package, so you can it to set up the whole PostgreSQL infrastructure (primar
[> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.md)
-## Standalone PostgreSQL using Omnibus GitLab **(CORE ONLY)**
+## Standalone PostgreSQL using Omnibus GitLab **(FREE SELF)**
This setup is for when you have installed the
[Omnibus GitLab packages](https://about.gitlab.com/install/) (CE or EE),
@@ -29,7 +29,7 @@ to use the bundled PostgreSQL having only its service enabled.
[> Read how to set up a standalone PostgreSQL instance using Omnibus GitLab](standalone.md)
-## Provide your own PostgreSQL instance **(CORE ONLY)**
+## Provide your own PostgreSQL instance **(FREE SELF)**
This setup is for when you have installed GitLab using the
[Omnibus GitLab packages](https://about.gitlab.com/install/) (CE or EE),
diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md
index 951edfeaec2..791ca64b001 100644
--- a/doc/administration/postgresql/pgbouncer.md
+++ b/doc/administration/postgresql/pgbouncer.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Working with the bundled PgBouncer service **(PREMIUM ONLY)**
+# Working with the bundled PgBouncer service **(PREMIUM SELF)**
[PgBouncer](http://www.pgbouncer.org/) is used to seamlessly migrate database
connections between servers in a failover scenario. Additionally, it can be used
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 75d0c558962..e80e38fe5d1 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -4,7 +4,7 @@ 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
---
-# PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM ONLY)**
+# PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM SELF)**
This document focuses on configuration supported with [GitLab Premium](https://about.gitlab.com/pricing/), using the Omnibus GitLab package.
If you're a Community Edition or Starter user, consider using a cloud hosted solution.
@@ -46,7 +46,7 @@ Each database node runs three services:
`PostgreSQL` - The database itself.
-`Patroni` - Communicates with other patroni services in the cluster and handles
+`Patroni` - Communicates with other Patroni services in the cluster and handles
failover when issues with the leader server occurs. The failover procedure
consists of:
diff --git a/doc/administration/postgresql/standalone.md b/doc/administration/postgresql/standalone.md
index 30495824cd2..cca46a2ea8c 100644
--- a/doc/administration/postgresql/standalone.md
+++ b/doc/administration/postgresql/standalone.md
@@ -4,7 +4,7 @@ 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
---
-# Standalone PostgreSQL using Omnibus GitLab **(CORE ONLY)**
+# Standalone PostgreSQL using Omnibus GitLab **(FREE SELF)**
If you wish to have your database service hosted separately from your GitLab
application servers, you can do this using the PostgreSQL binaries packaged
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index 41defd89df5..5ec268ac769 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Integrity check Rake task **(CORE ONLY)**
+# Integrity check Rake task **(FREE SELF)**
GitLab provides Rake tasks to check the integrity of various components.
diff --git a/doc/administration/raketasks/doctor.md b/doc/administration/raketasks/doctor.md
index c80f580cce6..ec3f7835b9c 100644
--- a/doc/administration/raketasks/doctor.md
+++ b/doc/administration/raketasks/doctor.md
@@ -4,7 +4,7 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Doctor Rake tasks **(CORE ONLY)**
+# Doctor Rake tasks **(FREE SELF)**
This is a collection of tasks to help investigate and repair
problems caused by data integrity issues.
diff --git a/doc/administration/raketasks/geo.md b/doc/administration/raketasks/geo.md
index 492fe4b52ca..3112e5f61b1 100644
--- a/doc/administration/raketasks/geo.md
+++ b/doc/administration/raketasks/geo.md
@@ -4,7 +4,7 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Geo Rake Tasks **(PREMIUM ONLY)**
+# Geo Rake Tasks **(PREMIUM SELF)**
The following Rake tasks are for [Geo installations](../geo/index.md).
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index 630570cb81f..c29865be56c 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitHub import **(CORE ONLY)**
+# GitHub import **(FREE SELF)**
> [Introduced]( https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10308) in GitLab 9.1.
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
index 7dafda89e3c..531e9e89020 100644
--- a/doc/administration/raketasks/ldap.md
+++ b/doc/administration/raketasks/ldap.md
@@ -4,7 +4,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# LDAP Rake tasks **(CORE ONLY)**
+# LDAP Rake tasks **(FREE SELF)**
The following are LDAP-related Rake tasks.
@@ -34,7 +34,7 @@ limit by passing a number to the check task:
rake gitlab:ldap:check[50]
```
-## Run a group sync **(STARTER ONLY)**
+## Run a group sync **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14735) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.2.
@@ -233,9 +233,9 @@ It can also be used as a receiving application for content encrypted with a KMS:
gcloud kms decrypt --key my-key --keyring my-test-kms --plaintext-file=- --ciphertext-file=my-file --location=us-west1 | sudo gitlab-rake gitlab:ldap:secret:write
```
-**gcloud secret integration example**
+**Google Cloud secret integration example**
-It can also be used as a receiving application for secrets out of gcloud:
+It can also be used as a receiving application for secrets out of Google Cloud:
```shell
gcloud secrets versions access latest --secret="my-test-secret" > $1 | sudo gitlab-rake gitlab:ldap:secret:write
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 26381434ad4..3494ceb701e 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Maintenance Rake tasks **(CORE ONLY)**
+# Maintenance Rake tasks **(FREE SELF)**
GitLab provides Rake tasks for general maintenance.
@@ -64,9 +64,10 @@ Repository storage paths:
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
```
-## Show GitLab license information **(STARTER ONLY)**
+## Show GitLab license information **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20501) in GitLab Starter 12.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20501) in GitLab 12.6.
+> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9.
This command shows information about your [GitLab license](../../user/admin_area/license.md) and
how many seats are used. It is only available on GitLab Enterprise
@@ -291,7 +292,7 @@ sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:4]
## Display status of database migrations
-See the [upgrade documentation](../../update/README.md#checking-for-background-migrations-before-upgrading)
+See the [upgrade documentation](../../update/index.md#checking-for-background-migrations-before-upgrading)
for how to check that migrations are complete when upgrading GitLab.
To check the status of specific migrations, you can use the following Rake task:
@@ -325,6 +326,39 @@ sudo gitlab-rake db:migrate
After the command completes, run `sudo gitlab-rake db:migrate:status` to check if all
migrations are completed (have an `up` status).
+## Rebuild database indexes
+
+WARNING:
+This is an experimental feature that isn't enabled by default.
+
+Database indexes can be rebuilt regularly to reclaim space and maintain healthy levels of index bloat over time.
+
+In order to rebuild the two indexes with the highest estimated bloat, use the following Rake task:
+
+```shell
+sudo gitlab-rake gitlab:db:reindex
+```
+
+In order to target a specific index, use the following Rake task:
+
+```shell
+sudo gitlab-rake gitlab:db:reindex['public.a_specific_index']
+```
+
+The following index types are not supported:
+
+1. Unique and primary key indexes
+1. Indexes used for constraint exclusion
+1. Partitioned indexes
+1. Expression indexes
+
+Optionally, this Rake task sends annotations to a Grafana (4.6 or later) endpoint. Use the following custom environment variables in order to enable annotations:
+
+1. `GRAFANA_API_URL` - Grafana's base URL, for example `http://some-host:3000`.
+1. `GRAFANA_API_KEY` - Grafana API key with at least `Editor role`.
+
+You can also [enable reindexing as a regular cron job](https://docs.gitlab.com/omnibus/settings/database.html#automatic-database-reindexing).
+
## Import common metrics
Sometimes you may need to re-import the common metrics that power the Metrics dashboards.
diff --git a/doc/administration/raketasks/praefect.md b/doc/administration/raketasks/praefect.md
index 17c3e44bb7e..5fe0546999b 100644
--- a/doc/administration/raketasks/praefect.md
+++ b/doc/administration/raketasks/praefect.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Praefect Rake tasks **(CORE ONLY)**
+# Praefect Rake tasks **(FREE SELF)**
> [Introduced]( https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28369) in GitLab 12.10.
diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md
index 0ea0bb3c28f..0fe15f2b5ba 100644
--- a/doc/administration/raketasks/project_import_export.md
+++ b/doc/administration/raketasks/project_import_export.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Project import/export administration **(CORE ONLY)**
+# Project import/export administration **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3050) in GitLab 8.9.
> - From GitLab 11.3, import/export can use object storage automatically.
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index 158b541b36b..7fedcbf3c1a 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Repository storage Rake tasks **(CORE ONLY)**
+# Repository storage Rake tasks **(FREE SELF)**
This is a collection of Rake tasks to help you list and migrate
existing projects and their attachments to the new
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index 2f51bf9357f..ab0a51ba8d6 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Uploads migrate Rake tasks **(CORE ONLY)**
+# Uploads migrate Rake tasks **(FREE SELF)**
There is a Rake task for migrating uploads between different storage types.
diff --git a/doc/administration/raketasks/uploads/sanitize.md b/doc/administration/raketasks/uploads/sanitize.md
index 637992d52ca..7dc813de14e 100644
--- a/doc/administration/raketasks/uploads/sanitize.md
+++ b/doc/administration/raketasks/uploads/sanitize.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Uploads sanitize Rake tasks **(CORE ONLY)**
+# Uploads sanitize Rake tasks **(FREE SELF)**
In GitLab 11.9 and later, EXIF data is automatically stripped from JPG or TIFF image uploads.
diff --git a/doc/administration/read_only_gitlab.md b/doc/administration/read_only_gitlab.md
index d1cb53d0090..cb7b621bf16 100644
--- a/doc/administration/read_only_gitlab.md
+++ b/doc/administration/read_only_gitlab.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Place GitLab into a read-only state **(CORE ONLY)**
+# Place GitLab into a read-only state **(FREE SELF)**
WARNING:
This document should be used as a temporary solution.
@@ -68,7 +68,7 @@ the database is read-only:
1. Take a [GitLab backup](../raketasks/backup_restore.md#back-up-gitlab)
in case things don't go as expected.
-1. Enter PostgreSQL on the console as an admin user:
+1. Enter PostgreSQL on the console as an administrator user:
```shell
sudo \
diff --git a/doc/administration/redis/replication_and_failover.md b/doc/administration/redis/replication_and_failover.md
index 1abc52b65cc..20a9fbd7d68 100644
--- a/doc/administration/redis/replication_and_failover.md
+++ b/doc/administration/redis/replication_and_failover.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Redis replication and failover with Omnibus GitLab **(PREMIUM ONLY)**
+# Redis replication and failover with Omnibus GitLab **(PREMIUM SELF)**
NOTE:
This is the documentation for the Omnibus GitLab packages. For using your own
diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md
index 3bcefe2ef13..1b2e93cccd9 100644
--- a/doc/administration/redis/replication_and_failover_external.md
+++ b/doc/administration/redis/replication_and_failover_external.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Redis replication and failover providing your own instance **(CORE ONLY)**
+# Redis replication and failover providing your own instance **(FREE SELF)**
If you’re hosting GitLab on a cloud provider, you can optionally use a managed
service for Redis. For example, AWS offers ElastiCache that runs Redis.
diff --git a/doc/administration/redis/standalone.md b/doc/administration/redis/standalone.md
index 0e7eca84d17..42482475d26 100644
--- a/doc/administration/redis/standalone.md
+++ b/doc/administration/redis/standalone.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Standalone Redis using Omnibus GitLab **(CORE ONLY)**
+# Standalone Redis using Omnibus GitLab **(FREE SELF)**
The Omnibus GitLab package can be used to configure a standalone Redis server.
In this configuration, Redis is not scaled, and represents a single
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index afa53b5efa8..d4d522ab1b8 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -5,107 +5,117 @@ 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
---
-# Reference architecture: up to 10,000 users **(PREMIUM ONLY)**
+# Reference architecture: up to 10,000 users **(PREMIUM SELF)**
This page describes GitLab reference architecture for up to 10,000 users. For a
full list of reference architectures, see
[Available reference architectures](index.md#available-reference-architectures).
> - **Supported users (approximate):** 10,000
-> - **High Availability:** Yes
-> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git: 20 RPS
+> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
+> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|-------------|----------|
| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
+| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Gitaly | 2 (minimum) | 16 vCPU, 60 GB memory | n1-standard-16 | m5.4xlarge | D16s v3 |
+| Gitaly Cluster | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | m5.4xlarge | D16s v3 |
+| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-```mermaid
-stateDiagram-v2
- [*] --> LoadBalancer
- LoadBalancer --> ApplicationServer
-
- ApplicationServer --> BackgroundJobs
- ApplicationServer --> Gitaly
- ApplicationServer --> Redis_Cache
- ApplicationServer --> Redis_Queues
- ApplicationServer --> PgBouncer
- PgBouncer --> Database
- ApplicationServer --> ObjectStorage
- BackgroundJobs --> ObjectStorage
-
- ApplicationMonitoring -->ApplicationServer
- ApplicationMonitoring -->PgBouncer
- ApplicationMonitoring -->Database
- ApplicationMonitoring -->BackgroundJobs
-
- ApplicationServer --> Consul
-
- Consul --> Database
- Consul --> PgBouncer
- Redis_Cache --> Consul
- Redis_Queues --> Consul
- BackgroundJobs --> Consul
-
- state Consul {
- "Consul_1..3"
- }
-
- state Database {
- "PG_Primary_Node"
- "PG_Secondary_Node_1..2"
- }
-
- state Redis_Cache {
- "R_Cache_Primary_Node"
- "R_Cache_Replica_Node_1..2"
- "R_Cache_Sentinel_1..3"
- }
-
- state Redis_Queues {
- "R_Queues_Primary_Node"
- "R_Queues_Replica_Node_1..2"
- "R_Queues_Sentinel_1..3"
- }
-
- state Gitaly {
- "Gitaly_1..2"
- }
-
- state BackgroundJobs {
- "Sidekiq_1..4"
- }
-
- state ApplicationServer {
- "GitLab_Rails_1..3"
- }
-
- state LoadBalancer {
- "LoadBalancer_1"
- }
-
- state ApplicationMonitoring {
- "Prometheus"
- "Grafana"
- }
-
- state PgBouncer {
- "Internal_Load_Balancer"
- "PgBouncer_1..3"
- }
+```plantuml
+@startuml 10k
+card "**External Load Balancer**" as elb #6a9be7
+card "**Internal Load Balancer**" as ilb #9370DB
+
+together {
+ collections "**GitLab Rails** x3" as gitlab #32CD32
+ collections "**Sidekiq** x4" as sidekiq #ff8dd1
+}
+
+together {
+ card "**Prometheus + Grafana**" as monitor #7FFFD4
+ collections "**Consul** x3" as consul #e76a9b
+}
+
+card "Gitaly Cluster" as gitaly_cluster {
+ collections "**Praefect** x3" as praefect #FF8C00
+ collections "**Gitaly** x3" as gitaly #FF8C00
+ card "**Praefect PostgreSQL***\n//Non fault-tolerant//" as praefect_postgres #FF8C00
+
+ praefect -[#FF8C00]-> gitaly
+ praefect -[#FF8C00]> praefect_postgres
+}
+
+card "Database" as database {
+ collections "**PGBouncer** x3" as pgbouncer #4EA7FF
+ card "**PostgreSQL** (Primary)" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** (Secondary) x2" as postgres_secondary #4EA7FF
+
+ pgbouncer -[#4EA7FF]-> postgres_primary
+ postgres_primary .[#4EA7FF]> postgres_secondary
+}
+
+card "redis" as redis {
+ collections "**Redis Persistent** x3" as redis_persistent #FF6347
+ collections "**Redis Cache** x3" as redis_cache #FF6347
+ collections "**Redis Persistent Sentinel** x3" as redis_persistent_sentinel #FF6347
+ collections "**Redis Cache Sentinel** x3"as redis_cache_sentinel #FF6347
+
+ redis_persistent <.[#FF6347]- redis_persistent_sentinel
+ redis_cache <.[#FF6347]- redis_cache_sentinel
+}
+
+cloud "**Object Storage**" as object_storage #white
+
+elb -[#6a9be7]-> gitlab
+elb -[#6a9be7]--> monitor
+
+gitlab -[#32CD32]> sidekiq
+gitlab -[#32CD32]--> ilb
+gitlab -[#32CD32]-> object_storage
+gitlab -[#32CD32]---> redis
+gitlab -[hidden]-> monitor
+gitlab -[hidden]-> consul
+
+sidekiq -[#ff8dd1]--> ilb
+sidekiq -[#ff8dd1]-> object_storage
+sidekiq -[#ff8dd1]---> redis
+sidekiq -[hidden]-> monitor
+sidekiq -[hidden]-> consul
+
+ilb -[#9370DB]-> gitaly_cluster
+ilb -[#9370DB]-> database
+
+consul .[#e76a9b]u-> gitlab
+consul .[#e76a9b]u-> sidekiq
+consul .[#e76a9b]> monitor
+consul .[#e76a9b]-> database
+consul .[#e76a9b]-> gitaly_cluster
+consul .[#e76a9b,norank]--> redis
+
+monitor .[#7FFFD4]u-> gitlab
+monitor .[#7FFFD4]u-> sidekiq
+monitor .[#7FFFD4]> consul
+monitor .[#7FFFD4]-> database
+monitor .[#7FFFD4]-> gitaly_cluster
+monitor .[#7FFFD4,norank]--> redis
+monitor .[#7FFFD4]> ilb
+monitor .[#7FFFD4,norank]u--> elb
+
+@enduml
```
The Google Cloud Platform (GCP) architectures were built and tested using the
@@ -120,19 +130,25 @@ uploads, or artifacts), using an [object storage service](#configure-the-object-
is recommended instead of using NFS. Using an object storage service also
doesn't require you to provision and maintain a node.
+It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
+that to achieve full High Availability a third party PostgreSQL database solution will be required.
+We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
+can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
+
## Setup components
To set up GitLab and its components to accommodate up to 10,000 users:
-1. [Configure the external load balancing node](#configure-the-external-load-balancer)
+1. [Configure the external load balancer](#configure-the-external-load-balancer)
to handle the load balancing of the GitLab application services nodes.
+1. [Configure the internal load balancer](#configure-the-internal-load-balancer).
+ to handle the load balancing of GitLab application internal connections.
1. [Configure Consul](#configure-consul).
1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab.
1. [Configure PgBouncer](#configure-pgbouncer).
-1. [Configure the internal load balancing node](#configure-the-internal-load-balancer).
1. [Configure Redis](#configure-redis).
-1. [Configure Gitaly](#configure-gitaly),
- which provides access to the Git repositories.
+1. [Configure Gitaly Cluster](#configure-gitaly-cluster),
+ provides access to the Git repositories.
1. [Configure Sidekiq](#configure-sidekiq).
1. [Configure the main GitLab Rails application](#configure-gitlab-rails)
to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend
@@ -178,6 +194,11 @@ The following list includes descriptions of each server and its assigned IP:
- `10.6.0.83`: Sentinel - Queues 3
- `10.6.0.91`: Gitaly 1
- `10.6.0.92`: Gitaly 2
+- `10.6.0.93`: Gitaly 3
+- `10.6.0.131`: Praefect 1
+- `10.6.0.132`: Praefect 2
+- `10.6.0.133`: Praefect 3
+- `10.6.0.141`: Praefect PostgreSQL 1 (non HA)
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
- `10.6.0.103`: Sidekiq 3
@@ -308,6 +329,71 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
</a>
</div>
+## Configure the internal load balancer
+
+The Internal Load Balancer is used to balance any internal connections the GitLab environment requires
+such as connections to [PgBouncer](#configure-pgbouncer) and [Praefect](#configure-praefect) (Gitaly Cluster).
+
+Note that it's a separate node from the External Load Balancer and shouldn't have any access externally.
+
+The following IP will be used as an example:
+
+- `10.6.0.40`: Internal Load Balancer
+
+Here's how you could do it with [HAProxy](https://www.haproxy.org/):
+
+```plaintext
+global
+ log /dev/log local0
+ log localhost local1 notice
+ log stdout format raw local0
+
+defaults
+ log global
+ default-server inter 10s fall 3 rise 2
+ balance leastconn
+
+frontend internal-pgbouncer-tcp-in
+ bind *:6432
+ mode tcp
+ option tcplog
+
+ default_backend pgbouncer
+
+frontend internal-praefect-tcp-in
+ bind *:2305
+ mode tcp
+ option tcplog
+ option clitcpka
+
+ default_backend praefect
+
+backend pgbouncer
+ mode tcp
+ option tcp-check
+
+ server pgbouncer1 10.6.0.21:6432 check
+ server pgbouncer2 10.6.0.22:6432 check
+ server pgbouncer3 10.6.0.23:6432 check
+
+backend praefect
+ mode tcp
+ option tcp-check
+ option srvtcpka
+
+ server praefect1 10.6.0.131:2305 check
+ server praefect2 10.6.0.132:2305 check
+ server praefect3 10.6.0.133:2305 check
+```
+
+Refer to your preferred Load Balancer's documentation for further guidance.
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
## Configure Consul
The following IPs will be used as an example:
@@ -662,52 +748,6 @@ The following IPs will be used as an example:
</a>
</div>
-### Configure the internal load balancer
-
-If you're running more than one PgBouncer node as recommended, then at this time you'll need to set
-up a TCP internal load balancer to serve each correctly.
-
-The following IP will be used as an example:
-
-- `10.6.0.40`: Internal Load Balancer
-
-Here's how you could do it with [HAProxy](https://www.haproxy.org/):
-
-```plaintext
-global
- log /dev/log local0
- log localhost local1 notice
- log stdout format raw local0
-
-defaults
- log global
- default-server inter 10s fall 3 rise 2
- balance leastconn
-
-frontend internal-pgbouncer-tcp-in
- bind *:6432
- mode tcp
- option tcplog
-
- default_backend pgbouncer
-
-backend pgbouncer
- mode tcp
- option tcp-check
-
- server pgbouncer1 10.6.0.21:6432 check
- server pgbouncer2 10.6.0.22:6432 check
- server pgbouncer3 10.6.0.23:6432 check
-```
-
-Refer to your preferred Load Balancer's documentation for further guidance.
-
-<div align="right">
- <a type="button" class="btn btn-default" href="#setup-components">
- Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
- </a>
-</div>
-
## Configure Redis
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
@@ -1302,19 +1342,283 @@ To configure the Sentinel Queues server:
</a>
</div>
-## Configure Gitaly
+## Configure Gitaly Cluster
-NOTE:
-[Gitaly Cluster](../gitaly/praefect.md) support
-for the Reference Architectures is being
-worked on as a [collaborative effort](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/1) between the Quality Engineering and Gitaly teams. When this component has been verified
-some Architecture specs will likely change as a result to support the new
-and improved designed.
+[Gitaly Cluster](../gitaly/praefect.md) is a GitLab provided and recommended fault tolerant solution for storing Git repositories.
+In this configuration, every Git repository is stored on every Gitaly node in the cluster, with one being designated the primary, and failover occurs automatically if the primary node goes down.
+
+The recommended cluster setup includes the following components:
+
+- 3 Gitaly nodes: Replicated storage of Git repositories.
+- 3 Praefect nodes: Router and transaction manager for Gitaly Cluster.
+- 1 Praefect PostgreSQL node: Database server for Praefect. A third-party solution
+ is required for Praefect database connections to be made highly available.
+- 1 load balancer: A load balancer is required for Praefect. The
+ [internal load balancer](#configure-the-internal-load-balancer) will be used.
+
+This section will detail how to configure the recommended standard setup in order.
+For more advanced setups refer to the [standalone Gitaly Cluster documentation](../gitaly/praefect.md).
+
+### Configure Praefect PostgreSQL
+
+Praefect, the routing and transaction manager for Gitaly Cluster, requires its own database server to store data on Gitaly Cluster status.
+
+If you want to have a highly available setup, Praefect requires a third-party PostgreSQL database.
+A built-in solution is being [worked on](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919).
+
+#### Praefect non-HA PostgreSQL standalone using Omnibus GitLab
+
+The following IPs will be used as an example:
+
+- `10.6.0.141`: Praefect PostgreSQL
+
+First, make sure to [install](https://about.gitlab.com/install/)
+the Linux GitLab package in the Praefect PostgreSQL node. Following the steps,
+install the necessary dependencies from step 1, and add the
+GitLab package repository from step 2. When installing GitLab
+in the second step, do not supply the `EXTERNAL_URL` value.
+
+1. SSH in to the Praefect PostgreSQL node.
+1. Create a strong password to be used for the Praefect PostgreSQL user. Take note of this password as `<praefect_postgresql_password>`.
+1. Generate the password hash for the Praefect PostgreSQL username/password pair. This assumes you will use the default
+ username of `praefect` (recommended). The command will request the password `<praefect_postgresql_password>`
+ and confirmation. Use the value that is output by this command in the next
+ step as the value of `<praefect_postgresql_password_hash>`:
+
+ ```shell
+ sudo gitlab-ctl pg-password-md5 praefect
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
+
+ ```ruby
+ # Disable all components except PostgreSQL and Consul
+ roles ['postgres_role']
+ repmgr['enable'] = false
+ patroni['enable'] = false
+
+ # PostgreSQL configuration
+ postgresql['listen_address'] = '0.0.0.0'
+ postgresql['max_connections'] = 200
+
+ gitlab_rails['auto_migrate'] = false
+
+ # Configure the Consul agent
+ consul['enable'] = true
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ #
+ # Replace PRAEFECT_POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = "<praefect_postgresql_password_hash>"
+
+ # Replace XXX.XXX.XXX.XXX/YY with Network Address
+ postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24)
+
+ # Set the network addresses that the exporters will listen on for monitoring
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ postgres_exporter['listen_address'] = '0.0.0.0:9187'
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+ #
+ # END user configuration
+ ```
+
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. Follow the [post configuration](#praefect-postgresql-post-configuration).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+#### Praefect HA PostgreSQL third-party solution
+
+[As noted](#configure-praefect-postgresql), a third-party PostgreSQL solution for
+Praefect's database is recommended if aiming for full High Availability.
+
+There are many third-party solutions for PostgreSQL HA. The solution selected must have the following to work with Praefect:
+
+- A static IP for all connections that doesn't change on failover.
+- [`LISTEN`](https://www.postgresql.org/docs/12/sql-listen.html) SQL functionality must be supported.
+
+Examples of the above could include [Google's Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) or [Amazon RDS](https://aws.amazon.com/rds/).
+
+Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
+
+#### Praefect PostgreSQL post-configuration
+
+After the Praefect PostgreSQL server has been set up, you'll then need to configure the user and database for Praefect to use.
+
+We recommend the user be named `praefect` and the database `praefect_production`, and these can be configured as standard in PostgreSQL.
+The password for the user is the same as the one you configured earlier as `<praefect_postgresql_password>`.
+
+This is how this would work with a Omnibus GitLab PostgreSQL setup:
+
+1. SSH in to the Praefect PostgreSQL node.
+1. Connect to the PostgreSQL server with administrative access.
+ The `gitlab-psql` user should be used here for this as it's added by default in Omnibus.
+ The database `template1` is used because it is created by default on all PostgreSQL servers.
+
+ ```shell
+ /opt/gitlab/embedded/bin/psql -U gitlab-psql -d template1 -h POSTGRESQL_SERVER_ADDRESS
+ ```
+
+1. Create the new user `praefect`, replacing `<praefect_postgresql_password>`:
+
+ ```shell
+ CREATE ROLE praefect WITH LOGIN CREATEDB PASSWORD <praefect_postgresql_password>;
+ ```
+
+1. Reconnect to the PostgreSQL server, this time as the `praefect` user:
+
+ ```shell
+ /opt/gitlab/embedded/bin/psql -U praefect -d template1 -h POSTGRESQL_SERVER_ADDRESS
+ ```
+
+1. Create a new database `praefect_production`:
+
+ ```shell
+ CREATE DATABASE praefect_production WITH ENCODING=UTF8;
+ ```
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#setup-components">
+ Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+### Configure Praefect
+
+Praefect is the router and transaction manager for Gitaly Cluster and all connections to Gitaly go through
+it. This section details how to configure it.
+
+Praefect requires several secret tokens to secure communications across the Cluster:
+
+- `<praefect_external_token>`: Used for repositories hosted on your Gitaly cluster and can only be accessed by Gitaly clients that carry this token.
+- `<praefect_internal_token>`: Used for replication traffic inside your Gitaly cluster. This is distinct from `praefect_external_token` because Gitaly clients must not be able to access internal nodes of the Praefect cluster directly; that could lead to data loss.
+- `<praefect_postgresql_password>`: The Praefect PostgreSQL password defined in the previous section is also required as part of this setup.
+
+Gitaly Cluster nodes are configured in Praefect via a `virtual storage`. Each storage contains
+the details of each Gitaly node that makes up the cluster. Each storage is also given a name
+and this name is used in several areas of the config. In this guide, the name of the storage will be
+`default`. Also, this guide is geared towards new installs, if upgrading an existing environment
+to use Gitaly Cluster, you may need to use a different name.
+Refer to the [Praefect documentation](../gitaly/praefect.md#praefect) for more info.
+
+The following IPs will be used as an example:
+
+- `10.6.0.131`: Praefect 1
+- `10.6.0.132`: Praefect 2
+- `10.6.0.133`: Praefect 3
+
+To configure the Praefect nodes, on each one:
+
+1. SSH in to the Praefect server.
+1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
+ package of your choice. Be sure to follow _only_ installation steps 1 and 2
+ on the page.
+1. Edit the `/etc/gitlab/gitlab.rb` file to configure Praefect:
+
+ ```ruby
+ # Avoid running unnecessary services on the Gitaly server
+ postgresql['enable'] = false
+ redis['enable'] = false
+ nginx['enable'] = false
+ puma['enable'] = false
+ unicorn['enable'] = false
+ sidekiq['enable'] = false
+ gitlab_workhorse['enable'] = false
+ grafana['enable'] = false
+
+ # If you run a separate monitoring node you can disable these services
+ alertmanager['enable'] = false
+ prometheus['enable'] = false
+
+ # Praefect Configuration
+ praefect['enable'] = true
+ praefect['listen_addr'] = '0.0.0.0:2305'
+
+ gitlab_rails['rake_cache_clear'] = false
+ gitlab_rails['auto_migrate'] = false
+
+ # Configure the Consul agent
+ consul['enable'] = true
+ ## Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
+
+ # START user configuration
+ # Please set the real values as explained in Required Information section
+ #
+
+ # Praefect External Token
+ # This is needed by clients outside the cluster (like GitLab Shell) to communicate with the Praefect cluster
+ praefect['auth_token'] = '<praefect_external_token>'
+
+ # Praefect Database Settings
+ praefect['database_host'] = '10.6.0.141'
+ praefect['database_port'] = 5432
+ # `no_proxy` settings must always be a direct connection for caching
+ praefect['database_host_no_proxy'] = '10.6.0.141'
+ praefect['database_port_no_proxy'] = 5432
+ praefect['database_dbname'] = 'praefect_production'
+ praefect['database_user'] = 'praefect'
+ praefect['database_password'] = '<praefect_postgresql_password>'
+
+ # Praefect Virtual Storage config
+ # Name of storage hash must match storage name in git_data_dirs on GitLab
+ # server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
+ praefect['virtual_storages'] = {
+ 'default' => {
+ 'gitaly-1' => {
+ 'address' => 'tcp://10.6.0.91:8075',
+ 'token' => '<praefect_internal_token>',
+ 'primary' => true
+ },
+ 'gitaly-2' => {
+ 'address' => 'tcp://10.6.0.92:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ 'gitaly-3' => {
+ 'address' => 'tcp://10.6.0.93:8075',
+ 'token' => '<praefect_internal_token>'
+ },
+ }
+ }
+
+ # Set the network addresses that the exporters will listen on for monitoring
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ praefect['prometheus_listen_addr'] = '0.0.0.0:9652'
+
+ ## The IPs of the Consul server nodes
+ ## You can also use FQDNs and intermix them with IPs
+ consul['configuration'] = {
+ retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13),
+ }
+ #
+ # END user configuration
+ ```
-[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
-specifically the number of projects and those projects' sizes. It's recommended
-that a Gitaly server node stores no more than 5 TB of data. Depending on your
-repository storage requirements, you may require additional Gitaly server nodes.
+ 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
+ then replace the file of the same name on this server. If that file isn't on
+ this server, add the file from your Consul server to this server.
+
+ 1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+### Configure Gitaly
+
+The [Gitaly](../gitaly/index.md) server nodes that make up the cluster have
+requirements that are dependent on data, specifically the number of projects
+and those projects' sizes. It's recommended that a Gitaly Cluster stores
+no more than 5 TB of data on each node. Depending on your
+repository storage requirements, you may require additional Gitaly Clusters.
Due to Gitaly having notable input and output requirements, we strongly
recommend that all Gitaly nodes use solid-state drives (SSDs). These SSDs
@@ -1325,36 +1629,21 @@ adjusted to greater or lesser values depending on the scale of your
environment's workload. If you're running the environment on a Cloud provider,
refer to their documentation about how to configure IOPS correctly.
-Be sure to note the following items:
+Gitaly servers must not be exposed to the public internet, as Gitaly's network
+traffic is unencrypted by default. The use of a firewall is highly recommended
+to restrict access to the Gitaly server. Another option is to
+[use TLS](#gitaly-cluster-tls-support).
-- The GitLab Rails application shards repositories into
- [repository storage paths](../repository_storage_paths.md).
-- A Gitaly server can host one or more storage paths.
-- A GitLab server can use one or more Gitaly server nodes.
-- Gitaly addresses must be specified to be correctly resolvable for all Gitaly
- clients.
-- Gitaly servers must not be exposed to the public internet, as Gitaly's network
- traffic is unencrypted by default. The use of a firewall is highly recommended
- to restrict access to the Gitaly server. Another option is to
- [use TLS](#gitaly-tls-support).
-
-NOTE:
-The token referred to throughout the Gitaly documentation is an arbitrary
-password selected by the administrator. This token is unrelated to tokens
-created for the GitLab API or other similar web API tokens.
+For configuring Gitaly you should note the following:
-This section describes how to configure two Gitaly servers, with the following
-IPs and domain names:
+- `git_data_dirs` should be configured to reflect the storage path for the specific Gitaly node
+- `auth_token` should be the same as `praefect_internal_token`
-- `10.6.0.91`: Gitaly 1 (`gitaly1.internal`)
-- `10.6.0.92`: Gitaly 2 (`gitaly2.internal`)
-
-Assumptions about your servers include having the secret token be `gitalysecret`,
-and that your GitLab installation has three repository storages:
+The following IPs will be used as an example:
-- `default` on Gitaly 1
-- `storage1` on Gitaly 1
-- `storage2` on Gitaly 2
+- `10.6.0.91`: Gitaly 1
+- `10.6.0.92`: Gitaly 2
+- `10.6.0.93`: Gitaly 3
On each node:
@@ -1364,21 +1653,9 @@ On each node:
1. Edit the Gitaly server node's `/etc/gitlab/gitlab.rb` file to configure
storage paths, enable the network listener, and to configure the token:
- <!--
- updates to following example must also be made at
- https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
- -->
-
```ruby
# /etc/gitlab/gitlab.rb
- # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests
- # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
- # The following two values must be the same as their respective values
- # of the GitLab Rails application setup
- gitaly['auth_token'] = 'gitalysecret'
- gitlab_shell['secret_token'] = 'shellsecret'
-
# Avoid running unnecessary services on the Gitaly server
postgresql['enable'] = false
redis['enable'] = false
@@ -1407,36 +1684,42 @@ On each node:
# firewalls to restrict access to this address/port.
# Comment out following line if you only want to support TLS connections
gitaly['listen_addr'] = "0.0.0.0:8075"
+
+ # Gitaly Auth Token
+ # Should be the same as praefect_internal_token
+ gitaly['auth_token'] = '<praefect_internal_token>'
```
1. Append the following to `/etc/gitlab/gitlab.rb` for each respective server:
- - On `gitaly1.internal`:
+ - On Gitaly node 1:
```ruby
git_data_dirs({
- 'default' => {
- 'path' => '/var/opt/gitlab/git-data'
- },
- 'storage1' => {
- 'path' => '/mnt/gitlab/git-data'
- },
+ "gitaly-1" => {
+ "path" => "/var/opt/gitlab/git-data"
+ }
})
```
- - On `gitaly2.internal`:
+ - On Gitaly node 2:
```ruby
git_data_dirs({
- 'storage2' => {
- 'path' => '/mnt/gitlab/git-data'
- },
+ "gitaly-2" => {
+ "path" => "/var/opt/gitlab/git-data"
+ }
})
```
- <!--
- updates to following example must also be made at
- https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
- -->
+ - On Gitaly node 3:
+
+ ```ruby
+ git_data_dirs({
+ "gitaly-3" => {
+ "path" => "/var/opt/gitlab/git-data"
+ }
+ })
+ ```
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and
then replace the file of the same name on this server. If that file isn't on
@@ -1444,34 +1727,44 @@ On each node:
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-### Gitaly TLS support
+### Gitaly Cluster TLS support
-Gitaly supports TLS encryption. To be able to communicate
-with a Gitaly instance that listens for secure connections you will need to use `tls://` URL
-scheme in the `gitaly_address` of the corresponding storage entry in the GitLab configuration.
+Praefect supports TLS encryption. To communicate with a Praefect instance that listens
+for secure connections, you must:
-You will need to bring your own certificates as this isn't provided automatically.
-The certificate, or its certificate authority, must be installed on all Gitaly
-nodes (including the Gitaly node using the certificate) and on all client nodes
-that communicate with it following the procedure described in
-[GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
+- 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.
-NOTE:
-The self-signed certificate must specify the address you use to access the
-Gitaly server. If you are addressing the Gitaly server by a hostname, you can
-either use the Common Name field for this, or add it as a Subject Alternative
-Name. If you are addressing the Gitaly server by its IP address, you must add it
-as a Subject Alternative Name to the certificate.
-[gRPC does not support using an IP address as Common Name in a certificate](https://github.com/grpc/grpc/issues/2691).
+Additionally the certificate, or its certificate authority, must be installed on all Gitaly servers
+and on all Praefect clients that communicate with it following the procedure described in
+[GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates) (and repeated below).
+
+Note the following:
+
+- The certificate must specify the address you use to access the Praefect server. If
+ addressing the Praefect server by:
+
+ - 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.
-It's possible to 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 do a gradual transition from unencrypted to
-encrypted traffic, if necessary.
+- 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.
+ This allows you to do a gradual transition from unencrypted to encrypted traffic, if
+ necessary.
-To configure Gitaly with TLS:
+- The Internal Load Balancer will also access to the certificates and need to be configured
+ to allow for TLS passthrough.
+ Refer to the load balancers documentation on how to configure this.
-1. Create the `/etc/gitlab/ssl` directory and copy your key and certificate there:
+To configure Praefect with TLS:
+
+1. Create certificates for Praefect servers.
+
+1. On the Praefect servers, create the `/etc/gitlab/ssl` directory and copy your key
+ and certificate there:
```shell
sudo mkdir -p /etc/gitlab/ssl
@@ -1480,27 +1773,34 @@ To configure Gitaly with TLS:
sudo chmod 644 key.pem cert.pem
```
-1. Copy the cert to `/etc/gitlab/trusted-certs` so Gitaly will trust the cert when
- calling into itself:
+1. Edit `/etc/gitlab/gitlab.rb` and add:
- ```shell
- sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/
+ ```ruby
+ praefect['tls_listen_addr'] = "0.0.0.0:3305"
+ praefect['certificate_path'] = "/etc/gitlab/ssl/cert.pem"
+ praefect['key_path'] = "/etc/gitlab/ssl/key.pem"
```
-1. Edit `/etc/gitlab/gitlab.rb` and add:
+1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure).
- <!--
- updates to following example must also be made at
- https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
- -->
+1. On the Praefect clients (including each Gitaly server), copy the certificates,
+ or their certificate authority, into `/etc/gitlab/trusted-certs`:
- ```ruby
- gitaly['tls_listen_addr'] = "0.0.0.0:9999"
- gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem"
- gitaly['key_path'] = "/etc/gitlab/ssl/key.pem"
+ ```shell
+ sudo cp cert.pem /etc/gitlab/trusted-certs/
```
-1. Delete `gitaly['listen_addr']` to allow only encrypted connections.
+1. On the Praefect clients (except Gitaly servers), edit `git_data_dirs` in
+ `/etc/gitlab/gitlab.rb` as follows:
+
+ ```ruby
+ git_data_dirs({
+ "default" => {
+ "gitaly_address" => 'tls://LOAD_BALANCER_SERVER_ADDRESS:2305',
+ "gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
+ }
+ })
+ ```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1512,8 +1812,9 @@ To configure Gitaly with TLS:
## Configure Sidekiq
-Sidekiq requires connections to the Redis, PostgreSQL and Gitaly instances.
-The following IPs will be used as an example:
+Sidekiq requires connection to the [Redis](#configure-redis),
+[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
+[Object storage](#configure-the-object-storage) is also required to be configured.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@@ -1586,17 +1887,20 @@ To configure the Sidekiq nodes, on each one:
### Gitaly ###
#######################################
+ # git_data_dirs get configured for the Praefect virtual storage
+ # Address is Internal Load Balancer for Praefect
+ # Token is praefect_external_token
git_data_dirs({
- 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
- 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
- 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
+ "default" => {
+ "gitaly_address" => "tcp://10.6.0.40:2305", # internal load balancer IP
+ "gitaly_token" => '<praefect_external_token>'
+ }
})
- gitlab_rails['gitaly_token'] = 'YOUR_TOKEN'
#######################################
### Postgres ###
#######################################
- gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
+ gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
gitlab_rails['db_adapter'] = 'postgresql'
@@ -1624,6 +1928,25 @@ To configure the Sidekiq nodes, on each one:
# Rails Status for prometheus
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
@@ -1644,6 +1967,7 @@ You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_proces
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
+[Object storage](#configure-the-object-storage) is also required to be configured.
The following IPs will be used as an example:
@@ -1669,17 +1993,14 @@ On each node perform the following:
```ruby
external_url 'https://gitlab.example.com'
- # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests
- # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
- # The following two values must be the same as their respective values
- # of the Gitaly setup
- gitlab_rails['gitaly_token'] = 'gitalysecret'
- gitlab_shell['secret_token'] = 'shellsecret'
-
+ # git_data_dirs get configured for the Praefect virtual storage
+ # Address is Interal Load Balancer for Praefect
+ # Token is praefect_external_token
git_data_dirs({
- 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
- 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
- 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
+ "default" => {
+ "gitaly_address" => "tcp://10.6.0.40:2305", # internal load balancer IP
+ "gitaly_token" => '<praefect_external_token>'
+ }
})
## Disable components that will not be on the GitLab application server
@@ -1736,17 +2057,37 @@ On each node perform the following:
# scrape the NGINX metrics
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8']
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-1. If you're using [Gitaly with TLS support](#gitaly-tls-support), make sure the
+1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the
`git_data_dirs` entry is configured with `tls` instead of `tcp`:
```ruby
git_data_dirs({
- 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' },
- 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' },
- 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' },
+ "default" => {
+ "gitaly_address" => "tls://10.6.0.40:2305", # internal load balancer IP
+ "gitaly_token" => '<praefect_external_token>'
+ }
})
```
@@ -1928,7 +2269,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
-- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -1957,7 +2298,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -1983,7 +2324,7 @@ work.
</a>
</div>
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
@@ -2028,3 +2369,56 @@ See the [troubleshooting documentation](troubleshooting.md).
Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>
</a>
</div>
+
+## Cloud Native Deployment (optional)
+
+Hybrid installations leverage the benefits of both cloud native and traditional
+deployments. We recommend shifting the Sidekiq and Webservice components into
+Kubernetes to reap cloud native workload management benefits while the others
+are deployed using the traditional server method already described.
+
+The following sections detail this hybrid approach.
+
+### Cluster topology
+
+The following table provides a starting point for hybrid
+deployment infrastructure. The recommendations use Google Cloud's Kubernetes Engine (GKE)
+and associated machine types, but the memory and CPU requirements should
+translate to most other providers.
+
+Machine count | Machine type | Allocatable vCPUs | Allocatable memory (GB) | Purpose
+-|-|-|-|-
+2 | `n1-standard-4` | 7.75 | 25 | Non-GitLab resources, including Grafana, NGINX, and Prometheus
+4 | `n1-standard-4` | 15.5 | 50 | GitLab Sidekiq pods
+4 | `n1-highcpu-32` | 127.5 | 118 | GitLab Webservice pods
+
+"Allocatable" in this table refers to the amount of resources available to workloads deployed in Kubernetes _after_ accounting for the overhead of running Kubernetes itself.
+
+### Resource usage settings
+
+The following formulas help when calculating how many pods may be deployed within resource constraints.
+The [10k reference architecture example values file](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/examples/ref/10k.yaml)
+documents how to apply the calculated configuration to the Helm Chart.
+
+#### Sidekiq
+
+Sidekiq pods should generally have 1 vCPU and 2 GB of memory.
+
+[The provided starting point](#cluster-topology) allows the deployment of up to
+16 Sidekiq pods. Expand available resources using the 1vCPU to 2GB memory
+ratio for each additional pod.
+
+For further information on resource usage, see the [Sidekiq resources](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/#resources).
+
+#### Webservice
+
+Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
+Each Webservice pod will consume roughly 2 vCPUs and 2.5 GB of memory using
+the [recommended topology](#cluster-topology) because two worker processes
+are created by default.
+
+The [provided recommendations](#cluster-topology) allow the deployment of up to 28
+Webservice pods. Expand available resources using the ratio of 1 vCPU to 1.25 GB of memory
+_per each worker process_ for each additional Webservice pod.
+
+For further information on resource usage, see the [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources).
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index 161964353f5..bed584e94bd 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Reference architecture: up to 1,000 users **(CORE ONLY)**
+# Reference architecture: up to 1,000 users **(FREE SELF)**
This page describes GitLab reference architecture for up to 1,000 users. For a
full list of reference architectures, see
@@ -18,11 +18,12 @@ many organizations .
> - **Supported users (approximate):** 1,000
> - **High Availability:** No. For a highly-available environment, you can
> follow the [3K reference architecture](3k_users.md).
+> - **Test requests per second (RPS) rates:** API: 20 RPS, Web: 2 RPS, Git (Pull): 2 RPS, Git (Push): 1 RPS
| Users | Configuration | GCP | AWS | Azure |
|--------------|-------------------------|----------------|-----------------|----------------|
-| Up to 500 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-| Up to 1,000 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
+| Up to 500 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+| Up to 1,000 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
The Google Cloud Platform (GCP) architectures were built and tested using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
@@ -41,13 +42,13 @@ the swap available when needed.
## Setup instructions
To install GitLab for this default reference architecture, use the standard
-[installation instructions](../../install/README.md).
+[installation instructions](../../install/index.md).
You can also optionally configure GitLab to use an [external PostgreSQL service](../postgresql/external.md)
or an [external object storage service](../object_storage.md) for added
-performance and reliability at a reduced complexity cost.
+performance and reliability at an increased complexity cost.
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index d96e93d4ab4..48c72bb930d 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Reference architecture: up to 25,000 users **(PREMIUM ONLY)**
+# Reference architecture: up to 25,000 users **(PREMIUM SELF)**
This page describes GitLab reference architecture for up to 25,000 users. For a
full list of reference architectures, see
@@ -13,25 +13,25 @@ full list of reference architectures, see
> - **Supported users (approximate):** 25,000
> - **High Availability:** Yes
-> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git: 50 RPS
+> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-----------------------------------------|-------------|-------------------------|-----------------|-------------|----------|
-| External load balancing node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.large | F2s v2 |
-| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Gitaly | 2 (minimum) | 32 vCPU, 120 GB memory | n1-standard-32 | m5.8xlarge | D32s v3 |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| External load balancing node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | `m5.2xlarge` | D8s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | `c5.large` | F2s v2 |
+| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Gitaly | 2 (minimum) | 32 vCPU, 120 GB memory | n1-standard-32 | `m5.8xlarge` | D32s v3 |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | `c5.9xlarge` | F32s v2 |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```mermaid
stateDiagram-v2
@@ -1512,8 +1512,9 @@ To configure Gitaly with TLS:
## Configure Sidekiq
-Sidekiq requires connections to the Redis, PostgreSQL and Gitaly instances.
-The following IPs will be used as an example:
+Sidekiq requires connection to the [Redis](#configure-redis),
+[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
+[Object storage](#configure-the-object-storage) is also required to be configured.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@@ -1624,6 +1625,25 @@ To configure the Sidekiq nodes, on each one:
# Rails Status for prometheus
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
@@ -1644,6 +1664,7 @@ You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_proces
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
+[Object storage](#configure-the-object-storage) is also required to be configured.
The following IPs will be used as an example:
@@ -1736,6 +1757,25 @@ On each node perform the following:
# scrape the NGINX metrics
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8']
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1928,7 +1968,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
-- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -1957,7 +1997,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -1983,7 +2023,7 @@ work.
</a>
</div>
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 3d38586fa62..9ad6054104a 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Reference architecture: up to 2,000 users **(CORE ONLY)**
+# Reference architecture: up to 2,000 users **(FREE SELF)**
This page describes GitLab reference architecture for up to 2,000 users.
For a full list of reference architectures, see
@@ -14,57 +14,45 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 2,000
> - **High Availability:** No. For a highly-available environment, you can
> follow the [3K reference architecture](3k_users.md).
-> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git: 4 RPS
+> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|--------|-------------------------|----------------|--------------|---------|
-| Load balancer | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 1 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| Redis | 1 | 1 vCPU, 3.75 GB memory | n1-standard-1 | m5.large | D2s v3 |
-| Gitaly | 1 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| GitLab Rails | 2 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| Load balancer | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 1 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| Redis | 1 | 1 vCPU, 3.75 GB memory | n1-standard-1 | `m5.large` | D2s v3 |
+| Gitaly | 1 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| GitLab Rails | 2 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
-
-```mermaid
-stateDiagram-v2
- [*] --> LoadBalancer
- LoadBalancer --> ApplicationServer
-
- ApplicationServer --> Gitaly
- ApplicationServer --> Redis
- ApplicationServer --> Database
- ApplicationServer --> ObjectStorage
-
- ApplicationMonitoring -->ApplicationServer
- ApplicationMonitoring -->Redis
- ApplicationMonitoring -->Database
-
-
- state Database {
- "PG_Node"
- }
- state Redis {
- "Redis_Node"
- }
-
- state Gitaly {
- "Gitaly"
- }
-
- state ApplicationServer {
- "AppServ_1..2"
- }
-
- state LoadBalancer {
- "LoadBalancer"
- }
-
- state ApplicationMonitoring {
- "Prometheus"
- "Grafana"
- }
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
+
+```plantuml
+@startuml 2k
+card "**External Load Balancer**" as elb #6a9be7
+
+collections "**GitLab Rails** x3" as gitlab #32CD32
+card "**Prometheus + Grafana**" as monitor #7FFFD4
+card "**Gitaly**" as gitaly #FF8C00
+card "**PostgreSQL**" as postgres #4EA7FF
+card "**Redis**" as redis #FF6347
+cloud "**Object Storage**" as object_storage #white
+
+elb -[#6a9be7]-> gitlab
+elb -[#6a9be7]--> monitor
+
+gitlab -[#32CD32]--> gitaly
+gitlab -[#32CD32]--> postgres
+gitlab -[#32CD32]-> object_storage
+gitlab -[#32CD32]--> redis
+
+monitor .[#7FFFD4]u-> gitlab
+monitor .[#7FFFD4]-> gitaly
+monitor .[#7FFFD4]-> postgres
+monitor .[#7FFFD4,norank]--> redis
+monitor .[#7FFFD4,norank]u--> elb
+
+@enduml
```
The Google Cloud Platform (GCP) architectures were built and tested using the
@@ -669,6 +657,25 @@ On each node perform the following:
gitlab_rails['monitoring_whitelist'] = ['<MONITOR NODE IP>/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['<MONITOR NODE IP>/32', '127.0.0.0/8']
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
+
## Uncomment and edit the following options if you have set up NFS
##
## Prevent GitLab from starting if NFS data mounts are not available
@@ -789,7 +796,7 @@ running [Prometheus](../monitoring/prometheus/index.md) and
gitlab_exporter['enable'] = false
```
-1. Prometheus also needs some scrape configs to pull all the data from the various
+1. Prometheus also needs some scrape configurations to pull all the data from the various
nodes where we configured exporters. Assuming that your nodes' IPs are:
```plaintext
@@ -879,7 +886,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
-- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -908,7 +915,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -932,7 +939,7 @@ functioning backups is encountered.
</a>
</div>
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 648fac8025f..175c4318d78 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Reference architecture: up to 3,000 users **(PREMIUM ONLY)**
+# Reference architecture: up to 3,000 users **(PREMIUM SELF)**
This page describes GitLab reference architecture for up to 3,000 users.
It is designed to help your organization achieve a
@@ -21,22 +21,22 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 3,000
> - **High Availability:** Yes
-> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git: 6 RPS
+> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-----------------------|----------------|-------------|---------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Gitaly | 2 (minimum) | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Gitaly | 2 (minimum) | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```mermaid
stateDiagram-v2
@@ -1212,7 +1212,10 @@ To configure Gitaly with TLS:
## Configure Sidekiq
-Sidekiq requires connection to the Redis, PostgreSQL and Gitaly instance.
+Sidekiq requires connection to the [Redis](#configure-redis),
+[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
+[Object storage](#configure-the-object-storage) is also required to be configured.
+
The following IPs will be used as an example:
- `10.6.0.71`: Sidekiq 1
@@ -1307,6 +1310,25 @@ To configure the Sidekiq nodes, one each one:
# Rails Status for prometheus
gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8']
gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1337,6 +1359,7 @@ You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_proces
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
+[Object storage](#configure-the-object-storage) is also required to be configured.
On each node perform the following:
@@ -1454,6 +1477,25 @@ On each node perform the following:
#web_server['gid'] = 9001
#registry['uid'] = 9002
#registry['gid'] = 9002
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. If you're using [Gitaly with TLS support](#gitaly-tls-support), make sure the
@@ -1621,7 +1663,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
-- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -1650,7 +1692,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -1676,7 +1718,7 @@ work.
</a>
</div>
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 093869d331b..0b22a2d3602 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Reference architecture: up to 50,000 users **(PREMIUM ONLY)**
+# Reference architecture: up to 50,000 users **(PREMIUM SELF)**
This page describes GitLab reference architecture for up to 50,000 users. For a
full list of reference architectures, see
@@ -13,25 +13,25 @@ full list of reference architectures, see
> - **Supported users (approximate):** 50,000
> - **High Availability:** Yes
-> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git: 100 RPS
+> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-----------------------------------------|-------------|-------------------------|-----------------|--------------|----------|
-| External load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | m5.4xlarge | D16s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 |
-| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | t3.small | B1MS |
-| Gitaly | 2 (minimum) | 64 vCPU, 240 GB memory | n1-standard-64 | m5.16xlarge | D64s v3 |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | m5.xlarge | D4s v3 |
-| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 |
-| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| External load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | `m5.4xlarge` | D16s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 8 vCPU, 7.2 GB memory | n1-highcpu-8 | `c5.2xlarge` | F8s v2 |
+| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
+| Gitaly | 2 (minimum) | 64 vCPU, 240 GB memory | n1-standard-64 | `m5.16xlarge` | D64s v3 |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
+| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | `c5.9xlarge` | F32s v2 |
+| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```mermaid
stateDiagram-v2
@@ -1512,8 +1512,9 @@ To configure Gitaly with TLS:
## Configure Sidekiq
-Sidekiq requires connections to the Redis, PostgreSQL and Gitaly instances.
-The following IPs will be used as an example:
+Sidekiq requires connection to the [Redis](#configure-redis),
+[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
+[Object storage](#configure-the-object-storage) is also required to be configured.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@@ -1624,6 +1625,25 @@ To configure the Sidekiq nodes, on each one:
# Rails Status for prometheus
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace
@@ -1644,6 +1664,7 @@ You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_proces
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
+[Object storage](#configure-the-object-storage) is also required to be configured.
The following IPs will be used as an example:
@@ -1736,6 +1757,25 @@ On each node perform the following:
# scrape the NGINX metrics
gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8']
nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8']
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1928,7 +1968,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
-- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -1957,7 +1997,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -1983,7 +2023,7 @@ work.
</a>
</div>
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 16ad866a108..37d35c299fa 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -5,7 +5,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Reference architecture: up to 5,000 users **(PREMIUM ONLY)**
+# Reference architecture: up to 5,000 users **(PREMIUM SELF)**
This page describes GitLab reference architecture for up to 5,000 users. For a
full list of reference architectures, see
@@ -20,22 +20,22 @@ costly-to-operate environment by using the
> - **Supported users (approximate):** 5,000
> - **High Availability:** Yes
-> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS
+> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|----------------|-------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| PostgreSQL | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
-| Gitaly | 2 (minimum) | 8 vCPU, 30 GB memory | n1-standard-8 | m5.2xlarge | D8s v3 |
-| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | m5.large | D2s v3 |
-| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | n1-highcpu-16 | c5.4xlarge | F16s v2 |
-| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | c5.large | F2s v2 |
+| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Redis | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| Consul + Sentinel | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| PostgreSQL | 3 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
+| Gitaly | 2 (minimum) | 8 vCPU, 30 GB memory | n1-standard-8 | `m5.2xlarge` | D8s v3 |
+| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | n1-standard-2 | `m5.large` | D2s v3 |
+| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | n1-highcpu-16 | `c5.4xlarge` | F16s v2 |
+| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
```mermaid
stateDiagram-v2
@@ -1211,8 +1211,9 @@ To configure Gitaly with TLS:
## Configure Sidekiq
-Sidekiq requires connection to the Redis, PostgreSQL and Gitaly instance.
-The following IPs will be used as an example:
+Sidekiq requires connection to the [Redis](#configure-redis),
+[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
+[Object storage](#configure-the-object-storage) is also required to be configured.
- `10.6.0.71`: Sidekiq 1
- `10.6.0.72`: Sidekiq 2
@@ -1306,6 +1307,25 @@ To configure the Sidekiq nodes, one each one:
# Rails Status for prometheus
gitlab_rails['monitoring_whitelist'] = ['10.6.0.81/32', '127.0.0.0/8']
gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
+
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1336,6 +1356,7 @@ You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_proces
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
+[Object storage](#configure-the-object-storage) is also required to be configured.
On each node perform the following:
@@ -1439,6 +1460,25 @@ On each node perform the following:
nginx['status']['options']['allow'] = ['10.6.0.81/32', '127.0.0.0/8']
gitlab_rails['prometheus_address'] = '10.6.0.81:9090'
+ #############################
+ ### Object storage ###
+ #############################
+
+ # This is an example for configuring Object Storage on GCP
+ # Replace this config with your chosen Object Storage provider as desired
+ gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'Google',
+ 'google_project' => '<gcp-project-name>',
+ 'google_json_key_location' => '<path-to-gcp-service-account-key>'
+ }
+ gitlab_rails['object_store']['objects']['artifacts']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['lfs']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['uploads']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['packages']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = "<gcp-bucket-name>"
+ gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = "<gcp-bucket-name>"
+
## Uncomment and edit the following options if you have set up NFS
##
## Prevent GitLab from starting if NFS data mounts are not available
@@ -1620,7 +1660,7 @@ GitLab has been tested on a number of object storage providers:
- [Google Cloud Storage](https://cloud.google.com/storage)
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
-- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [OpenStack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -1649,7 +1689,7 @@ on what features you intend to use:
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](../packages/index.md#using-object-storage) (optional feature) | Yes |
| [Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature) | Yes |
-| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
+| [Pseudonymizer](../pseudonymizer.md#configuration) (optional feature) **(ULTIMATE SELF)** | No |
| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
| [Terraform state files](../terraform_state.md#using-object-storage) | Yes |
@@ -1675,7 +1715,7 @@ work.
</a>
</div>
-## Configure Advanced Search **(STARTER ONLY)**
+## Configure Advanced Search **(PREMIUM SELF)**
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
for faster, more advanced code search across your entire GitLab instance.
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index b90b8d67b68..b149cbc6e9d 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -29,11 +29,12 @@ per 1,000 users:
- API: 20 RPS
- Web: 2 RPS
-- Git: 2 RPS
+- Git (Pull): 2 RPS
+- Git (Push): 0.4 RPS (rounded to nearest integer)
For GitLab instances with less than 2,000 users, it's recommended that you use
the [default setup](#automated-backups) by
-[installing GitLab](../../install/README.md) on a single machine to minimize
+[installing GitLab](../../install/index.md) on a single machine to minimize
maintenance and resource costs.
If your organization has more than 2,000 users, the recommendation is to scale the
@@ -91,7 +92,7 @@ Also, not implementing extra servers for GitLab doesn't necessarily mean that yo
more downtime. Depending on your needs and experience level, single servers can
have more actual perceived uptime for your users.
-### Automated backups **(CORE ONLY)**
+### Automated backups **(FREE SELF)**
> - Level of complexity: **Low**
> - Required domain knowledge: PostgreSQL, GitLab configurations, Git
@@ -102,7 +103,7 @@ this can be an optimal solution if you don't have strict requirements.
[Automated backups](../../raketasks/backup_restore.md#configuring-cron-to-make-daily-backups)
is the least complex to setup. This provides a point-in-time recovery of a predetermined schedule.
-### Traffic load balancer **(STARTER ONLY)**
+### Traffic load balancer **(PREMIUM SELF)**
> - Level of complexity: **Medium**
> - Required domain knowledge: HAProxy, shared storage, distributed systems
@@ -124,7 +125,7 @@ to the default installation:
For more details on how to configure a traffic load balancer with GitLab, you can refer
to any of the [available reference architectures](#available-reference-architectures) with more than 1,000 users.
-### Zero downtime updates **(STARTER ONLY)**
+### Zero downtime updates **(PREMIUM SELF)**
> - Level of complexity: **Medium**
> - Required domain knowledge: PostgreSQL, HAProxy, shared storage, distributed systems
@@ -134,7 +135,7 @@ Single GitLab nodes can be updated with only a [few minutes of downtime](https:/
To avoid this, we recommend to separate GitLab into several application nodes.
As long as at least one of each component is online and capable of handling the instance's usage load, your team's productivity will not be interrupted during the update.
-### Automated database failover **(PREMIUM ONLY)**
+### Automated database failover **(PREMIUM SELF)**
> - Level of complexity: **High**
> - Required domain knowledge: PgBouncer, Repmgr or Patroni, shared storage, distributed systems
@@ -145,7 +146,7 @@ cluster management and failover policies.
[PgBouncer in conjunction with Repmgr or Patroni](../postgresql/replication_and_failover.md)
is recommended.
-### Instance level replication with GitLab Geo **(PREMIUM ONLY)**
+### Instance level replication with GitLab Geo **(PREMIUM SELF)**
> - Level of complexity: **Very High**
> - Required domain knowledge: Storage replication
diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md
index 835231ac584..cab45a99ee4 100644
--- a/doc/administration/reference_architectures/troubleshooting.md
+++ b/doc/administration/reference_architectures/troubleshooting.md
@@ -298,7 +298,7 @@ Confirm the following are all true:
- When any user adds or modifies a file from the repository using the GitLab
UI, it immediately fails with a red `401 Unauthorized` banner.
-- Creating a new project and [initializing it with a README](../../gitlab-basics/create-project.md#blank-projects)
+- Creating a new project and [initializing it with a README](../../user/project/working_with_projects.md#blank-projects)
successfully creates the project but doesn't create the README.
- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server) on an app node and reproducing the error, you get `401` errors
when reaching the `/api/v4/internal/allowed` endpoint:
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index 6f7a72a0ef2..404a7bd77c1 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -12,37 +12,35 @@ type: reference
Git has a built-in mechanism, [`git fsck`](https://git-scm.com/docs/git-fsck), to verify the
integrity of all data committed to a repository. GitLab administrators
can trigger such a check for a project via the project page under the
-admin panel. The checks run asynchronously so it may take a few minutes
-before the check result is visible on the project admin page. If the
-checks failed you can see their output on in the [`repocheck.log`
-file.](logs.md#repochecklog)
+Admin Area. The checks run asynchronously so it may take a few minutes
+before the check result is visible on the project Admin Area. If the
+checks failed you can see their output on in the
+[`repocheck.log` file.](logs.md#repochecklog)
-NOTE:
-It is OFF by default because it still causes too many false alarms.
+This setting is off by default, because it can cause many false alarms.
## Periodic checks
When enabled, GitLab periodically runs a repository check on all project
repositories and wiki repositories in order to detect data corruption.
-A project will be checked no more than once per month. If any projects
-fail their repository checks all GitLab administrators will receive an email
+A project is checked no more than once per month. If any projects
+fail their repository checks all GitLab administrators receive an email
notification of the situation. This notification is sent out once a week,
by default, midnight at the start of Sunday. Repositories with known check
failures can be found at `/admin/projects?last_repository_check_failed=1`.
## Disabling periodic checks
-You can disable the periodic checks on the 'Settings' page of the admin
-panel.
+You can disable the periodic checks on the **Settings** page of the Admin Area.
## What to do if a check failed
If the repository check fails for some repository you should look up the error
in the [`repocheck.log` file](logs.md#repochecklog) on disk:
-- `/var/log/gitlab/gitlab-rails` for Omnibus installations
+- `/var/log/gitlab/gitlab-rails` for Omnibus GitLab installations
- `/home/git/gitlab/log` for installations from source
If the periodic repository check causes false alarms, you can clear all repository check states by
-navigating to **Admin Area > Settings > Repository**
+going to **Admin Area > Settings > Repository**
(`/admin/application_settings/repository`) and clicking **Clear all repository checks**.
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index c71d1a5714c..5884a8b3283 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -5,69 +5,100 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Repository storage paths
+# Repository storage **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4578) in GitLab 8.10.
-GitLab allows you to define multiple repository storage paths (sometimes called
-storage shards) to distribute the storage load between several mount points.
+GitLab stores [repositories](../user/project/repository/index.md) on repository storage. Repository
+storage is either:
-> **Notes:**
->
-> - You must have at least one storage path called `default`.
-> - The paths are defined in key-value pairs. The key is an arbitrary name you
-> can pick to name the file path.
-> - The target directories and any of its sub-paths must not be a symlink.
-> - No target directory may be a sub-directory of another; no nesting.
+- A `gitaly_address`, which points to a [Gitaly node](gitaly/index.md).
+- A `path`, which points directly a directory where the repository is stored.
-Example: this is OK:
+GitLab allows you to define multiple repository storages to distribute the storage load between
+several mount points. For example:
-```plaintext
-default:
- path: /mnt/git-storage-1
-storage2:
- path: /mnt/git-storage-2
-```
+- When using Gitaly (Omnibus GitLab-style configuration):
+
+ ```ruby
+ git_data_dirs({
+ 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
+ 'storage1' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
+ })
+ ```
-This is not OK because it nests storage paths:
+- When using direct repository storage (source install-style configuration):
-```plaintext
-default:
- path: /mnt/git-storage-1
-storage2:
- path: /mnt/git-storage-1/git-storage-2 # <- NOT OK because of nesting
-```
+ ```plaintext
+ default:
+ path: /mnt/git-storage-1
+ storage2:
+ path: /mnt/git-storage-2
+ ```
+
+For more information on
+
+- Configuring Gitaly, see [Configure Gitaly](gitaly/index.md#configure-gitaly).
+- Configuring direct repository access, see the following section below.
+
+## Configure repository storage paths
+
+To configure repository storage paths:
+
+1. Edit the necessary configuration files:
+ - `/etc/gitlab/gitlab.rb`, for Omnibus GitLab installations.
+ - `gitlab.yml`, for installations from source.
+1. Add the required repository storage paths.
+
+For repository storage paths:
+
+- You must have at least one storage path called `default`.
+- The paths are defined in key-value pairs. Apart from `default`, the key can be any name you choose
+ to name the file path.
+- The target directories and any of its sub paths must not be a symlink.
+- No target directory may be a sub-directory of another. That is, no nesting. For example, the
+ following configuration is invalid:
+
+ ```plaintext
+ default:
+ path: /mnt/git-storage-1
+ storage2:
+ path: /mnt/git-storage-1/git-storage-2 # <- NOT OK because of nesting
+ ```
+
+### Configure for backups
+
+For [backups](../raketasks/backup_restore.md) to work correctly:
-## Configure GitLab
-
-In order for [backups](../raketasks/backup_restore.md) to work correctly, the storage path must **not** be a
-mount point and the GitLab user should have correct permissions for the parent
-directory of the path. In Omnibus GitLab this is taken care of automatically,
-but for source installations you should be extra careful.
-
-The thing is that for compatibility reasons `gitlab.yml` has a different
-structure than Omnibus. In `gitlab.yml` you indicate the path for the
-repositories, for example `/home/git/repositories`, while in Omnibus you
-indicate `git_data_dirs`, which for the example above would be `/home/git`.
-Then, Omnibus creates a `repositories` directory under that path to use with
-`gitlab.yml`.
-
-This little detail matters because while restoring a backup, the current
-contents of `/home/git/repositories` [are moved to](https://gitlab.com/gitlab-org/gitlab/blob/033e5423a2594e08a7ebcd2379bd2331f4c39032/lib/backup/repository.rb#L54-56) `/home/git/repositories.old`,
-so if `/home/git/repositories` is the mount point, then `mv` would be moving
-things between mount points, and bad things could happen. Ideally,
-`/home/git` would be the mount point, so then things would be moving within the
-same mount point. This is guaranteed with Omnibus installations (because they
-don't specify the full repository path but the parent path), but not for source
-installations.
-
-Now that you've read that big fat warning above, let's edit the configuration
-files and add the full paths of the alternative repository storage paths. In
-the example below, we add two more mount points that are named `nfs_1` and `nfs_2`
-respectively.
+- The repository storage path cannot be a mount point.
+- The GitLab user must have correct permissions for the parent directory of the path.
+
+Omnibus GitLab takes care of these issues for you, but for source installations you should be extra
+careful.
+
+While restoring a backup, the current contents of `/home/git/repositories` are moved to
+`/home/git/repositories.old`. If `/home/git/repositories` is a mount point, then `mv` would be
+moving things between mount points, and problems can occur.
+
+Ideally, `/home/git` is the mount point, so things remain inside the same mount point. Omnibus
+GitLab installations guarantee this because they don't specify the full repository path but instead
+the parent path, but source installations do not.
+
+### Example configuration
+
+In the examples below, we add two additional repository storage paths configured to two additional
+mount points.
+
+For compatibility reasons `gitlab.yml` has a different structure than Omnibus GitLab configuration:
+
+- In `gitlab.yml`, you indicate the path for the repositories, for example `/home/git/repositories`
+- In Omnibus GitLab configuration you indicate `git_data_dirs`, which could be `/home/git` for
+ example. Then Omnibus GitLab creates a `repositories` directory under that path to use with
+ `gitlab.yml`.
NOTE:
-This example uses NFS. We do not recommend using EFS for storage as it may impact GitLab performance. See the [relevant documentation](nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
+This example uses NFS. We do not recommend using EFS for storage as it may impact GitLab performance.
+Read the [relevant documentation](nfs.md#avoid-using-awss-elastic-file-system-efs) for more details.
**For installations from source**
@@ -77,7 +108,7 @@ This example uses NFS. We do not recommend using EFS for storage as it may impac
repositories:
# Paths where repositories can be stored. Give the canonicalized absolute pathname.
# NOTE: REPOS PATHS MUST NOT CONTAIN ANY SYMLINK!!!
- storages: # You must have at least a 'default' storage path.
+ storages: # You must have at least a 'default' repository storage path.
default:
path: /home/git/repositories
nfs_1:
@@ -88,42 +119,39 @@ This example uses NFS. We do not recommend using EFS for storage as it may impac
1. [Restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-NOTE:
-We plan to replace [`gitlab_shell: repos_path` entry](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-9-stable/config/gitlab.yml.example#L457) in `gitlab.yml` with `repositories: storages`. If you
-are upgrading from a version prior to 8.10, make sure to add the configuration
-as described in the step above. After you make the changes and confirm they are
-working, you can remove the `repos_path` line.
-
**For Omnibus installations**
-1. Edit `/etc/gitlab/gitlab.rb` by appending the rest of the paths to the
- default one:
+Edit `/etc/gitlab/gitlab.rb` by appending the rest of the paths to the default one:
- ```ruby
- git_data_dirs({
- "default" => { "path" => "/var/opt/gitlab/git-data" },
- "nfs_1" => { "path" => "/mnt/nfs1/git-data" },
- "nfs_2" => { "path" => "/mnt/nfs2/git-data" }
- })
- ```
+```ruby
+git_data_dirs({
+ "default" => { "path" => "/var/opt/gitlab/git-data" },
+ "nfs_1" => { "path" => "/mnt/nfs1/git-data" },
+ "nfs_2" => { "path" => "/mnt/nfs2/git-data" }
+})
+```
+
+NOTE:
+Omnibus stores the repositories in a `repositories` subdirectory of the `git-data` directory.
- Note that Omnibus stores the repositories in a `repositories` subdirectory
- of the `git-data` directory.
+## Configure where new repositories are stored
-## Choose where new repositories are stored
+After you [configure](#configure-repository-storage-paths) multiple repository storage paths, you
+can choose where new repositories are stored:
-Once you set the multiple storage paths, you can choose where new repositories
-are stored in the Admin Area under **Settings > Repository > Repository storage > Storage nodes for new repositories**.
+1. Go to the Admin Area (**{admin}**).
+1. Go to **Settings > Repository** and expand the **Repository storage** section.
+1. Enter values in the **Storage nodes for new repositories** fields.
+1. Select **Save changes**.
-Each storage can be assigned a weight from 0-100. When a new project is created, these
-weights are used to determine the storage location the repository is created on.
+Each repository storage path can be assigned a weight from 0-100. When a new project is created,
+these weights are used to determine the storage location the repository is created on. The higher
+the weight of a given repository storage path relative to other repository storages paths, the more
+often it is chosen. That is, `(storage weight) / (sum of all weights) * 100 = chance %`.
![Choose repository storage path in Admin Area](img/repository_storages_admin_ui_v13_1.png)
-Beginning with GitLab 8.13.4, multiple paths can be chosen. New repositories
-are randomly placed on one of the selected paths.
-
-## Move a repository to a different repository path
+## Move repositories
To move a repository to a different repository path, use the
[Project repository storage moves](../api/project_repository_storage_moves.md) API. Use
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 6ec43a8ce06..a5c323be4ce 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Repository storage types **(CORE ONLY)**
+# Repository storage types **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28283) in GitLab 10.0.
> - Hashed storage became the default for new installations in GitLab 12.0
@@ -38,13 +38,13 @@ been disabled.
Hashed storage is the storage behavior we rolled out with 10.0. Instead
of coupling project URL and the folder structure where the repository is
-stored on disk, we are coupling a hash, based on the project's ID. This makes
+stored on disk, we couple a hash based on the project's ID. This makes
the folder structure immutable, and therefore eliminates any requirement to
synchronize state from URLs to disk structure. This means that renaming a group,
user, or project costs only the database transaction, and takes effect
immediately.
-The hash also helps to spread the repositories more evenly on the disk, so the
+The hash also helps spread the repositories more evenly on the disk. The
top-level directory contains fewer folders than the total number of top-level
namespaces.
@@ -122,7 +122,7 @@ Do not run `git prune` or `git gc` in pool repositories! This can
cause data loss in "real" repositories that depend on the pool in
question.
-Forks of public projects are deduplicated by creating a third repository, the
+Forks of public and internal projects are deduplicated by creating a third repository, the
object pool, containing the objects from the source project. Using
`objects/info/alternates`, the source project and forks use the object pool for
shared objects. Objects are moved from the source project to the object pool
@@ -136,8 +136,8 @@ when housekeeping is run on the source project.
### Hashed storage coverage migration
Files stored in an S3-compatible endpoint do not have the downsides
-mentioned earlier, if they are not prefixed with `#{namespace}/#{project_name}`,
-which is true for CI Cache and LFS Objects.
+mentioned earlier, if they are not prefixed with `#{namespace}/#{project_name}`.
+This is true for CI Cache and LFS Objects.
In the table below, you can find the coverage of the migration to the hashed storage.
@@ -161,7 +161,8 @@ When avatar is replaced, `Upload` model is destroyed and a new one takes place w
#### CI artifacts
-CI Artifacts are S3 compatible since **9.4** (GitLab Premium), and available in GitLab Core since **10.6**.
+CI Artifacts are S3 compatible since **9.4** (GitLab Premium), and available in GitLab Free since
+**10.6**.
#### LFS objects
@@ -194,10 +195,10 @@ reasons, GitLab replicated the same mapping structure from the projects URLs:
- Project's repository: `#{namespace}/#{project_name}.git`
- Project's wiki: `#{namespace}/#{project_name}.wiki.git`
-This structure made it simple to migrate from existing solutions to GitLab and
-easy for Administrators to find where the repository is stored.
+This structure enables you to migrate from existing solutions to GitLab, and
+for Administrators to find where the repository is stored.
-On the other hand this has some drawbacks:
+This approach also has some drawbacks:
Storage location concentrates a huge number of top-level namespaces. The
impact can be reduced by the introduction of
@@ -211,4 +212,4 @@ is at that same URL today.
Any change in the URL needs to be reflected on disk (when groups / users or
projects are renamed). This can add a lot of load in big installations,
-especially if using any type of network based filesystem.
+especially if using any type of network based file system.
diff --git a/doc/administration/repository_storages.md b/doc/administration/repository_storages.md
deleted file mode 100644
index 93d0ee3cac9..00000000000
--- a/doc/administration/repository_storages.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'repository_storage_paths.md'
----
-
-This document was moved to [another location](repository_storage_paths.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 4f104c6a63f..69b3ae5282f 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -140,7 +140,7 @@ your server in `/etc/init.d/gitlab`.
---
-If you are using other init systems, like systemd, you can check the
+If you are using other init systems, like `systemd`, you can check the
[GitLab Recipes](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/init) repository for some unofficial services. These are
**not** officially supported so use them at your own risk.
diff --git a/doc/administration/scaling/index.md b/doc/administration/scaling/index.md
deleted file mode 100644
index 4f934646ed6..00000000000
--- a/doc/administration/scaling/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: ../reference_architectures/index.md
----
-
-This document was moved to [another location](../reference_architectures/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index 645d3bc4e9f..93b899d5146 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -6,7 +6,7 @@ type: reference, howto
disqus_identifier: 'https://docs.gitlab.com/ee/administration/custom_hooks.html'
---
-# Server hooks **(CORE ONLY)**
+# Server hooks **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196051) in GitLab 12.8 replacing Custom Hooks.
diff --git a/doc/administration/snippets/index.md b/doc/administration/snippets/index.md
index 0bf0eb3b1ed..61d0b1ec50a 100644
--- a/doc/administration/snippets/index.md
+++ b/doc/administration/snippets/index.md
@@ -5,7 +5,7 @@ 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"
---
-# Snippets settings **(CORE ONLY)**
+# Snippets settings **(FREE SELF)**
Adjust the snippets' settings of your GitLab instance.
@@ -18,7 +18,7 @@ abuse of the feature. The default value is **52428800 Bytes** (50 MB).
### How does it work?
-The content size limit will be applied when a snippet is created or updated.
+The content size limit is applied when a snippet is created or updated.
This limit doesn't affect existing snippets until they're updated and their
content changes.
@@ -60,8 +60,8 @@ To retrieve the current value, start the Rails console and run:
#### Through the API
-The process to set the snippets size limit through the Application Settings API is
-exactly the same as you would do to [update any other setting](../../api/settings.md#change-application-settings).
+To set the snippets size limit through the Application Settings API (similar to
+[updating any other setting](../../api/settings.md#change-application-settings)), use this command:
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/application/settings?snippet_size_limit=52428800"
diff --git a/doc/administration/static_objects_external_storage.md b/doc/administration/static_objects_external_storage.md
index b10af12de67..0f3dab743e9 100644
--- a/doc/administration/static_objects_external_storage.md
+++ b/doc/administration/static_objects_external_storage.md
@@ -9,8 +9,8 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31025) in GitLab 12.3.
-GitLab can be configured to serve repository static objects (for example, archives or raw blobs) from an external
-storage, such as a Content Delivery Network (CDN).
+You can configure GitLab to serve repository static objects, like archives or raw blobs,
+from an external storage, such as a Content Delivery Network (CDN).
## Configuring
@@ -19,19 +19,22 @@ To configure external storage for static objects:
1. Navigate to **Admin Area > Settings > Repository**.
1. Expand the **Repository static objects** section.
1. Enter the base URL and an arbitrary token. When you [set up external storage](#set-up-external-storage),
-you'll use a script that uses these values as `ORIGIN_HOSTNAME` and `STORAGE_TOKEN`.
+ use a script that sets these values as `ORIGIN_HOSTNAME` and `STORAGE_TOKEN`.
The token is required to distinguish requests coming from the external storage, so users don't
-circumvent the external storage and go for the application directly. The token is expected to be
-set in the `X-Gitlab-External-Storage-Token` header in requests originating from the external
-storage.
+circumvent the external storage and access the application directly. GitLab expects
+this token to be set in the `X-Gitlab-External-Storage-Token` header in requests
+originating from the external storage.
## Serving private static objects
-GitLab will append a user-specific token for static object URLs that belong to private projects,
-so an external storage can be authenticated on behalf of the user. When processing requests originating
-from the external storage, GitLab will look for the token in the `token` query parameter or in
-the `X-Gitlab-Static-Object-Token` header to check the user's ability to access the requested object.
+GitLab appends a user-specific token for static object URLs belonging to private projects,
+so an external storage can be authenticated on the user's behalf. When processing requests originating
+from the external storage, GitLab checks the following places to confirm the user may
+access the requested object:
+
+- The `token` query parameter.
+- The `X-Gitlab-Static-Object-Token` header.
## Requests flow example
@@ -66,8 +69,8 @@ other CDNs or Function as a Service (FaaS) systems should work using the same pr
1. In the following script, set the following values for the first two constants:
- `ORIGIN_HOSTNAME`: the hostname of your GitLab installation.
- - `STORAGE_TOKEN`: any arbitrary secure token (e.g. you can get one by running
- `pwgen -cn1 64` on a UNIX machine). Save this token for the admin panel, as
+ - `STORAGE_TOKEN`: any arbitrary secure token. You can get a token by running
+ `pwgen -cn1 64` on a UNIX machine. Save this token for the Admin Area, as
described in the [configuring](#configuring) section.
```javascript
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index be5647aa133..6e5d6b274b6 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/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
---
-# Terraform state administration (alpha)
+# Terraform state administration (alpha) **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2673) in GitLab 12.10.
@@ -18,6 +18,8 @@ The storage location of these files defaults to:
These locations can be configured using the options described below.
+Use [external object storage](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer-terraform-state-dependency-proxy) configuration for [GitLab Helm chart](https://docs.gitlab.com/charts/) installations.
+
## Using local storage
The default configuration uses local storage. To change the location where
@@ -47,7 +49,7 @@ Terraform state files are stored locally, follow the steps below.
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-## Using object storage **(CORE ONLY)**
+## Using object storage **(FREE SELF)**
Instead of storing Terraform state files on disk, we recommend the use of [one of the supported object
storage options](object_storage.md#options). This configuration relies on valid credentials to
@@ -100,6 +102,11 @@ See [the available connection settings for different providers](object_storage.m
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+1. Migrate any existing local states to the object storage (GitLab 13.9 and later):
+
+ ```shell
+ gitlab-rake gitlab:terraform_states:migrate
+ ```
**In installations from source:**
@@ -120,3 +127,8 @@ See [the available connection settings for different providers](object_storage.m
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
+1. Migrate any existing local states to the object storage (GitLab 13.9 and later):
+
+ ```shell
+ sudo -u git -H bundle exec rake gitlab:terraform_states:migrate RAILS_ENV=production
+ ```
diff --git a/doc/administration/timezone.md b/doc/administration/timezone.md
index 798e7f5050c..6f460ed0ea8 100644
--- a/doc/administration/timezone.md
+++ b/doc/administration/timezone.md
@@ -41,3 +41,18 @@ After adding the configuration parameter, reconfigure and restart your GitLab in
gitlab-ctl reconfigure
gitlab-ctl restart
```
+
+## Changing time zone per user
+
+To allow users to change the time zone in their profile, the feature flag `user_time_settings` should be enabled:
+
+1. [Start a Rails console session](operations/rails_console.md).
+1. Enable the feature flag:
+
+ ```ruby
+ Feature.enable(:user_time_settings)
+ ```
+
+1. You should now be able to see the timezone dropdown in the users' **Settings > Profile** page.
+
+ ![User Time Zone Settings](img/time_zone_settings.png)
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index 8c8fa25aa5e..a6073e34d58 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -126,7 +126,7 @@ an SMTP server, but you're not seeing mail delivered. Here's how to check the se
For more advanced issues, `gdb` is a must-have tool for debugging issues.
-### The GNU Project Debugger (gdb)
+### The GNU Project Debugger (GDB)
To install on Ubuntu/Debian:
@@ -140,9 +140,13 @@ On CentOS:
sudo yum install gdb
```
+<!-- vale gitlab.Spelling = NO -->
+
### rbtrace
-GitLab 11.2 ships with [rbtrace](https://github.com/tmm1/rbtrace), which
+<!-- vale gitlab.Spelling = YES -->
+
+GitLab 11.2 ships with [`rbtrace`](https://github.com/tmm1/rbtrace), which
allows you to trace Ruby code, view all running threads, take memory dumps,
and more. However, this is not enabled by default. To enable it, define the
`ENABLE_RBTRACE` variable to the environment. For example, in Omnibus:
@@ -175,7 +179,7 @@ downtime. Otherwise skip to the next section.
1. Load the problematic URL
1. Run `sudo gdb -p <PID>` to attach to the Unicorn process.
-1. In the gdb window, type:
+1. In the GDB window, type:
```plaintext
call (void) rb_backtrace()
@@ -210,7 +214,7 @@ downtime. Otherwise skip to the next section.
```
Note that if the Unicorn process terminates before you are able to run these
-commands, gdb will report an error. To buy more time, you can always raise the
+commands, GDB will report an error. To buy more time, you can always raise the
Unicorn timeout. For omnibus users, you can edit `/etc/gitlab/gitlab.rb` and
increase it from 60 seconds to 300:
@@ -231,7 +235,7 @@ separate Rails process to debug the issue:
1. Log in to your GitLab account.
1. Copy the URL that is causing problems (e.g. `https://gitlab.com/ABC`).
-1. Create a Personal Access Token for your user (Profile Settings -> Access Tokens).
+1. Create a Personal Access Token for your user (User Settings -> Access Tokens).
1. Bring up the [GitLab Rails console.](../operations/rails_console.md#starting-a-rails-console-session)
1. At the Rails console, run:
@@ -246,7 +250,7 @@ separate Rails process to debug the issue:
```
1. In a new window, run `top`. It should show this Ruby process using 100% CPU. Write down the PID.
-1. Follow step 2 from the previous section on using gdb.
+1. Follow step 2 from the previous section on using GDB.
### GitLab: API is not accessible
@@ -279,4 +283,4 @@ The output in `/tmp/unicorn.txt` may help diagnose the root cause.
## More information
- [Debugging Stuck Ruby Processes](https://blog.newrelic.com/engineering/debugging-stuck-ruby-processes-what-to-do-before-you-kill-9/)
-- [Cheatsheet of using gdb and Ruby processes](gdb-stuck-ruby.txt)
+- [Cheat sheet of using GDB and Ruby processes](gdb-stuck-ruby.txt)
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index fb153adfeab..0f60c43ef9e 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -232,7 +232,7 @@ If the results:
### Troubleshooting indexing
Troubleshooting indexing issues can be tricky. It can pretty quickly go to either GitLab
-support or your Elasticsearch admin.
+support or your Elasticsearch administrator.
The best place to start is to determine if the issue is with creating an empty index.
If it is, check on the Elasticsearch side to determine if the `gitlab-production` (the
@@ -245,7 +245,7 @@ If you still encounter issues, try creating an index manually on the Elasticsear
instance. The details of the index aren't important here, as we want to test if indices
can be made. If the indices:
-- Cannot be made, speak with your Elasticsearch admin.
+- Cannot be made, speak with your Elasticsearch administrator.
- Can be made, Escalate this to GitLab support.
If the issue is not with creating an empty index, the next step is to check for errors
@@ -253,7 +253,7 @@ during the indexing of projects. If errors do occur, they will either stem from
- On the GitLab side. You need to rectify those. If they are not
something you are familiar with, contact GitLab support for guidance.
-- Within the Elasticsearch instance itself. See if the error is [documented and has a fix](../../integration/elasticsearch.md#troubleshooting). If not, speak with your Elasticsearch admin.
+- Within the Elasticsearch instance itself. See if the error is [documented and has a fix](../../integration/elasticsearch.md#troubleshooting). If not, speak with your Elasticsearch administrator.
If the indexing process does not present errors, you will want to check the status of the indexed projects. You can do this via the following Rake tasks:
@@ -271,7 +271,7 @@ If reindexing the project shows:
- Errors on the GitLab side, escalate those to GitLab support.
- Elasticsearch errors or doesn't present any errors at all, reach out to your
- Elasticsearch admin to check the instance.
+ Elasticsearch administrator to check the instance.
### Troubleshooting integration
@@ -284,7 +284,7 @@ If the issue is:
This is a required package so make sure you install it.
Go indexer was a beta indexer which can be optionally turned on/off, but in 12.3 it reached stable status and is now the default.
- Not concerning the Go indexer, it is almost always an
- Elasticsearch-side issue. This means you should reach out to your Elasticsearch admin
+ Elasticsearch-side issue. This means you should reach out to your Elasticsearch administrator
regarding the error(s) you are seeing. If you are unsure here, it never hurts to reach
out to GitLab support.
@@ -354,12 +354,12 @@ learn them, so it is best to escalate/pair with an Elasticsearch expert if you n
dig further into these.
Feel free to reach out to GitLab support, but this is likely to be something a skilled
-Elasticsearch admin has more experience with.
+Elasticsearch administrator has more experience with.
### Troubleshooting background migrations
Troubleshooting background migration failures can be difficult and may require contacting
-an Elasticsearch admin or GitLab Support.
+an Elasticsearch administrator or GitLab Support.
The best place to start while debugging issues with a background migration is the
[`elasticsearch.log` file](../logs.md#elasticsearchlog). Migrations will
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 4a112733bfa..55e707042ba 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -5,13 +5,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab Rails Console Cheat Sheet **(CORE ONLY)**
+# GitLab Rails Console Cheat Sheet **(FREE SELF)**
This is the GitLab Support Team's collection of information regarding the GitLab Rails
console, for use while troubleshooting. It is listed here for transparency,
and it may be useful for users with experience with these tools. If you are currently
-having an issue with GitLab, it is highly recommended that you check your
-[support options](https://about.gitlab.com/support/) first, before attempting to use
+having an issue with GitLab, it is highly recommended that you first check
+our guide on [navigating our Rails console](navigating_gitlab_via_rails_console.md),
+and your [support options](https://about.gitlab.com/support/), before attempting to use
this information.
WARNING:
@@ -562,7 +563,7 @@ service = ::Groups::TransferService.new(group, user)
service.execute(parent_group)
```
-### Count unique users in a group and sub-groups
+### Count unique users in a group and subgroups
```ruby
group = Group.find_by_path_or_name("groupname")
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index e9dbbfbde12..f0d44a578ff 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Troubleshooting Group SAML and SCIM **(SILVER ONLY)**
+# Troubleshooting Group SAML and SCIM **(PREMIUM SAAS)**
These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team’s collected knowledge.
diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md
index 67115ce31c0..63b056df8b7 100644
--- a/doc/administration/troubleshooting/index.md
+++ b/doc/administration/troubleshooting/index.md
@@ -13,7 +13,7 @@ in case something goes wrong:
- [Diagnostics tools](diagnostics_tools.md)
- [Elasticsearch](elasticsearch.md)
- [GitLab Rails console cheat sheet](gitlab_rails_cheat_sheet.md)
-- [Group SAML and SCIM troubleshooting](group_saml_scim.md) **(SILVER ONLY)**
+- [Group SAML and SCIM troubleshooting](group_saml_scim.md) **(PREMIUM SAAS)**
- [Kubernetes cheat sheet](kubernetes_cheat_sheet.md)
- [Linux cheat sheet](linux_cheat_sheet.md)
- [Parsing GitLab logs with `jq`](log_parsing.md)
diff --git a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
index 07a7baf338b..9766b2210ca 100644
--- a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
+++ b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md
@@ -70,7 +70,7 @@ and they will assist you with any issues you are having.
kubectl logs <pod-name> --previous
```
- No logs are kept in the containers/pods themselves. Everything is written to stdout.
+ No logs are kept in the containers/pods themselves. Everything is written to `stdout`.
This is the principle of Kubernetes, read [Twelve-factor app](https://12factor.net/)
for details.
@@ -88,7 +88,7 @@ and they will assist you with any issues you are having.
- Minimal configuration that can be used to [test a Kubernetes Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/620).
-- Tailing logs of a separate pod. An example for a Webservice pod:
+- Tailing logs of a separate pod. An example for a `webservice` pod:
```shell
kubectl logs gitlab-webservice-54fbf6698b-hpckq -c webservice
@@ -154,7 +154,7 @@ and they will assist you with any issues you are having.
- On the side of GitLab check Sidekiq log and Kubernetes log. When GitLab is installed
via Helm Chart, `kubernetes.log` can be found inside the Sidekiq pod.
-- How to get your initial admin password <https://docs.gitlab.com/charts/installation/deployment.html#initial-login>:
+- How to get your initial administrator password <https://docs.gitlab.com/charts/installation/deployment.html#initial-login>:
```shell
# find the name of the secret containing the password
diff --git a/doc/administration/troubleshooting/linux_cheat_sheet.md b/doc/administration/troubleshooting/linux_cheat_sheet.md
index c61a78624c3..c4e991ccc1b 100644
--- a/doc/administration/troubleshooting/linux_cheat_sheet.md
+++ b/doc/administration/troubleshooting/linux_cheat_sheet.md
@@ -55,7 +55,7 @@ chown root:git <file_or_dir>
chmod u+x <file>
```
-### Files & Dirs
+### Files and directories
```shell
# create a new directory and all subdirectories
@@ -202,7 +202,7 @@ or you can build it from source if you have the Rust compiler.
First run the tool with no arguments other than the strace output filename to get
a summary of the top processes sorted by time spent actively performing tasks. You
-can also sort based on total time, # of syscalls made, PID #, and # of child processes
+can also sort based on total time, # of system calls made, PID #, and # of child processes
using the `-S` or `--sort` flag. The number of results defaults to 25 processes, but
can be changed using the `-c`/`--count` option. See `--help` for full details.
@@ -220,7 +220,7 @@ Top 25 PIDs
...
```
-Based on the summary, you can then view the details of syscalls made by one or more
+Based on the summary, you can then view the details of system calls made by one or more
processes using the `-p`/`--pid` for a specific process, or `-s`/`--stats` flags for
a sorted list. `--stats` takes the same sorting and count options as summary.
@@ -266,7 +266,7 @@ Rough numbers for calls to `open` and `openat` (used to access files) on various
Slow storage can cause the dreaded `DeadlineExceeded` error in Gitaly.
Also [see this entry](../operations/filesystem_benchmarking.md)
-in the handbook for quick tests customers can perform to check their filesystem performance.
+in the handbook for quick tests customers can perform to check their file system performance.
Keep in mind that timing information from `strace` is often somewhat inaccurate, so
small differences should not be considered significant.
@@ -304,6 +304,24 @@ whois <ip_address> | grep -i "orgname\|netname"
# Curl headers with redirect
curl --head --location "https://example.com"
+
+# Test if a host is reachable on the network. `ping6` works on IPv6 networks.
+ping example.com
+
+# Show the route taken to a host. `traceroute6` works on IPv6 networks.
+traceroute example.com
+mtr example.com
+
+# List details of network interfaces
+ip address
+
+# Check local DNS settings
+cat /etc/hosts
+cat /etc/resolv.conf
+systemd-resolve --status
+
+# Capture traffic to/from a host
+sudo tcpdump host www.example.com
```
## Package Management
diff --git a/doc/administration/troubleshooting/log_parsing.md b/doc/administration/troubleshooting/log_parsing.md
index 144aa0f6d3b..25300d036ed 100644
--- a/doc/administration/troubleshooting/log_parsing.md
+++ b/doc/administration/troubleshooting/log_parsing.md
@@ -179,3 +179,11 @@ jq --raw-output --slurp '
663 106 ms, 96 ms, 94 ms 'groupABC/project123'
...
```
+
+#### Find all projects affected by a fatal Git problem
+
+```shell
+grep "fatal: " /var/log/gitlab/gitaly/current | \
+ jq '."grpc.request.glProjectPath"' | \
+ sort | uniq
+```
diff --git a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
index 68c12117222..481c95b925a 100644
--- a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
+++ b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
@@ -107,7 +107,7 @@ Up to now, we've been using `.find` or `.find_by`, which are designed to return
only a single object (notice the `LIMIT 1` in the generated SQL query?).
`.where` is used when it is desirable to get a collection of objects.
-Let's get a collection of non-admin users and see what we can do with it:
+Let's get a collection of non-administrator users and see what we can do with it:
```ruby
users = User.where.not(admin: true)
@@ -364,7 +364,7 @@ StateMachines::InvalidTransition (Cannot transition state via :block from :activ
We see that a validation error from what feels like a completely separate
attribute comes back to haunt us when we try to update the user in any way.
-In practical terms, we sometimes see this happen with GitLab admin settings --
+In practical terms, we sometimes see this happen with GitLab administration settings --
validations are sometimes added or changed in a GitLab update, resulting in
previously saved settings now failing validation. Because you can only update
a subset of settings at once through the UI, in this case the only way to get
@@ -388,7 +388,7 @@ User.find_by_any_email('user@example.com')
The `find_by_any_email` method is a custom method added by GitLab developers rather
than a Rails-provided default method.
-**Get a collection of admin users:**
+**Get a collection of administrator users:**
```ruby
User.admins
@@ -443,7 +443,7 @@ group = Group.find_by_full_path('group/subgroup')
# Get group's immediate child projects
group.projects
-# Get group's child projects, including those in sub-groups
+# Get group's child projects, including those in subgroups
group.all_projects
```
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index e4082f87c7d..147bf1123ad 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -221,7 +221,7 @@ It is possible to use [Sidekiq API](https://github.com/mperham/sidekiq/wiki/API)
to perform a number of troubleshooting steps on Sidekiq.
These are the administrative commands and it should only be used if currently
-admin interface is not suitable due to scale of installation.
+administration interface is not suitable due to scale of installation.
All these commands should be run using `gitlab-rails console`.
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index 49af8358e29..d3a9777775f 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Uploads administration **(CORE ONLY)**
+# Uploads administration **(FREE SELF)**
Uploads represent all user data that may be sent to GitLab as a single file. As an example, avatars and notes' attachments are uploads. Uploads are integral to GitLab functionality, and therefore cannot be disabled.
@@ -49,12 +49,12 @@ _The uploads are stored by default in
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-## Using object storage **(CORE ONLY)**
+## Using object storage **(FREE SELF)**
> **Notes:**
>
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3867) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.5.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17358) in [GitLab Core](https://about.gitlab.com/pricing/) 10.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17358) in [GitLab Free](https://about.gitlab.com/pricing/) 10.7.
> - Since version 11.1, we support direct_upload to S3.
If you don't want to use the local disk where GitLab is installed to store the
@@ -112,7 +112,24 @@ _The uploads are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
+1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.md).
+1. Optional: Verify all files migrated properly.
+ From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
+ (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `store=2`) has count of all artifacts:
+
+ ```shell
+ gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
+
+ total | filesystem | objectstg
+ ------+------------+-----------
+ 2409 | 0 | 2409
+ ```
+
+ Verify no files on disk in `artifacts` folder:
+
+ ```shell
+ sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
+ ```
**In installations from source:**
@@ -136,6 +153,22 @@ _The uploads are stored by default in
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
+1. Optional: Verify all files migrated properly.
+ From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
+
+ ```shell
+ gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
+
+ total | filesystem | objectstg
+ ------+------------+-----------
+ 2409 | 0 | 2409
+ ```
+
+ Verify no files on disk in `artifacts` folder:
+
+ ```shell
+ sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
+ ```
#### OpenStack example
@@ -162,6 +195,23 @@ _The uploads are stored by default in
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
+1. Optional: Verify all files migrated properly.
+ From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
+ (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `store=2`) has count of all artifacts:
+
+ ```shell
+ gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
+
+ total | filesystem | objectstg
+ ------+------------+-----------
+ 2409 | 0 | 2409
+ ```
+
+ Verify no files on disk in `artifacts` folder:
+
+ ```shell
+ sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
+ ```
---
@@ -193,3 +243,19 @@ _The uploads are stored by default in
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
+1. Optional: Verify all files migrated properly.
+ From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
+
+ ```shell
+ gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
+
+ total | filesystem | objectstg
+ ------+------------+-----------
+ 2409 | 0 | 2409
+ ```
+
+ Verify no files on disk in `artifacts` folder:
+
+ ```shell
+ sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
+ ```
diff --git a/doc/administration/user_settings.md b/doc/administration/user_settings.md
index 9892d2a0764..681ce87edb6 100644
--- a/doc/administration/user_settings.md
+++ b/doc/administration/user_settings.md
@@ -1,6 +1,6 @@
---
-stage: Enablement
-group: Distribution
+stage: Manage
+group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -10,7 +10,8 @@ GitLab administrators can modify user settings for the entire GitLab instance.
## Disallow users creating top-level groups
-By default, new users can create top-level groups. To disable this, modify the appropriate configuration file.
+By default, new users can create top-level groups. To disable this, modify the appropriate configuration file,
+and then [reconfigure and restart GitLab](restart_gitlab.md).
For Omnibus installations, add the following to `/etc/gitlab/gitlab.rb`:
@@ -26,7 +27,8 @@ For source installations, uncomment the following line in `config/gitlab.yml`:
## Disallow users changing usernames
-By default, new users can change their usernames. To disable this, modify the appropriate configuration file.
+By default, new users can change their usernames. To disable this, modify the appropriate configuration file,
+and then [reconfigure and restart GitLab](restart_gitlab.md).
For Omnibus installations, add the following to `/etc/gitlab/gitlab.rb`:
diff --git a/doc/administration/wikis/index.md b/doc/administration/wikis/index.md
index 026f9b6f471..57bbe913216 100644
--- a/doc/administration/wikis/index.md
+++ b/doc/administration/wikis/index.md
@@ -1,11 +1,11 @@
---
type: reference, howto
stage: Create
-group: Knowledge
+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
---
-# Wiki settings **(CORE ONLY)**
+# Wiki settings **(FREE SELF)**
Adjust the wiki settings of your GitLab instance.
@@ -18,24 +18,24 @@ abuse of the feature. The default value is **52428800 Bytes** (50 MB).
### How does it work?
-The content size limit will be applied when a wiki page is created or updated
-through the GitLab UI or API. Local changes pushed via Git will not be validated.
+The content size limit is applied when a wiki page is created or updated
+through the GitLab UI or API. Local changes pushed via Git are not validated.
-In order not to break any existing wiki pages, the limit doesn't have any
-effect on them until a wiki page is edited again and the content changes.
+To break any existing wiki pages, the limit doesn't take effect until a wiki page
+is edited again and the content changes.
### Wiki page content size limit configuration
This setting is not available through the [Admin Area settings](../../user/admin_area/settings/index.md).
-In order to configure this setting, use either the Rails console
+To configure this setting, use either the Rails console
or the [Application settings API](../../api/settings.md).
NOTE:
-The value of the limit **must** be in bytes. The minimum value is 1024 bytes.
+The value of the limit must be in bytes. The minimum value is 1024 bytes.
#### Through the Rails console
-The steps to configure this setting through the Rails console are:
+To configure this setting through the Rails console:
1. Start the Rails console:
@@ -61,14 +61,14 @@ To retrieve the current value, start the Rails console and run:
#### Through the API
-The process to set the wiki page size limit through the Application Settings API is
-exactly the same as you would do to [update any other setting](../../api/settings.md#change-application-settings).
+To set the wiki page size limit through the Application Settings API, use a command,
+as you would to [update any other setting](../../api/settings.md#change-application-settings):
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/application/settings?wiki_page_max_content_bytes=52428800"
```
-You can also use the API to [retrieve the current value](../../api/settings.md#get-current-application-settings).
+You can also use the API to [retrieve the current value](../../api/settings.md#get-current-application-settings):
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/application/settings"
diff --git a/doc/analytics/README.md b/doc/analytics/README.md
deleted file mode 100644
index 7c732f48ba8..00000000000
--- a/doc/analytics/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/group/index.md#user-contribution-analysis'
----
-
-This document was moved to [another location](../user/group/index.md#user-contribution-analysis)
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/analytics/contribution_analytics.md b/doc/analytics/contribution_analytics.md
deleted file mode 100644
index b9a52d9ca68..00000000000
--- a/doc/analytics/contribution_analytics.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/group/contribution_analytics/index.md'
----
-
-This document was moved to [another location](../user/group/contribution_analytics/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/README.md b/doc/api/README.md
index 8fb3269d28b..d6119fbfa43 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -21,7 +21,7 @@ Contributions are welcome.
For a list of the available resources and their endpoints, see
[API resources](api_resources.md).
-## SCIM **(SILVER ONLY)**
+## SCIM **(PREMIUM SAAS)**
GitLab provides an [SCIM API](scim.md) that both implements
[the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides the
@@ -124,7 +124,7 @@ There are several methods you can use to authenticate with the GitLab API:
- [GitLab CI/CD job token](#gitlab-ci-job-token) **(Specific endpoints only)**
NOTE:
-Project access tokens are supported for self-managed instances on Core and
+Project access tokens are supported for self-managed instances on Free and
higher. They're also supported on GitLab.com Bronze and higher.
For administrators who want to authenticate with the API as a specific user, or who want
@@ -200,16 +200,16 @@ With a few API endpoints you can use a [GitLab CI/CD job token](../user/project/
to authenticate with the API:
- Packages:
- - [Composer Repository](../user/packages/composer_repository/index.md)
- - [Conan Repository](../user/packages/conan_repository/index.md)
+ - [Package Registry for Composer](../user/packages/composer_repository/index.md)
+ - [Package Registry for Conan](../user/packages/conan_repository/index.md)
- [Container Registry](../user/packages/container_registry/index.md)
(`$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`)
- [Go Proxy](../user/packages/go_proxy/index.md)
- - [Maven Repository](../user/packages/maven_repository/index.md#authenticate-with-a-ci-job-token-in-maven)
- - [NPM Repository](../user/packages/npm_registry/index.md#authenticate-with-a-ci-job-token)
- - [Nuget Repository](../user/packages/nuget_repository/index.md)
- - [PyPI Repository](../user/packages/pypi_repository/index.md#authenticate-with-a-ci-job-token)
- - [Generic packages](../user/packages/generic_packages/index.md#publish-a-generic-package-by-using-cicd)
+ - [Package Registry for Maven](../user/packages/maven_repository/index.md#authenticate-with-a-ci-job-token-in-maven)
+ - [Package Registry for npm](../user/packages/npm_registry/index.md#authenticate-with-a-ci-job-token)
+ - [Package Registry for NuGet](../user/packages/nuget_repository/index.md)
+ - [Package Registry for PyPI](../user/packages/pypi_repository/index.md#authenticate-with-a-ci-job-token)
+ - [Package Registry for generic packages](../user/packages/generic_packages/index.md#publish-a-generic-package-by-using-cicd)
- [Get job artifacts](job_artifacts.md#get-job-artifacts)
- [Pipeline triggers](pipeline_triggers.md) (using the `token=` parameter)
- [Release creation](releases/index.md#create-a-release)
@@ -744,3 +744,15 @@ For administrator documentation on rate limit settings, see
[Rate limits](../security/rate_limits.md). To find the settings that are
specifically used by GitLab.com, see
[GitLab.com-specific rate limits](../user/gitlab_com/index.md#gitlabcom-specific-rate-limits).
+
+## Content type
+
+The GitLab API supports the `application/json` content type by default, though
+some API endpoints also support `text/plain`.
+
+In [GitLab 13.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/250342),
+API endpoints do not support `text/plain` by default, unless it's explicitly documented.
+
+This change is deployed behind the `:api_always_use_application_json` [feature flag](../user/feature_flags.md),
+enabled by default. On GitLab self-managed instances, GitLab administrators can choose
+to [disable it](../administration/feature_flags.md). **(FREE SELF)**
diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md
index 7f2f2b8668c..9cbdcb863d6 100644
--- a/doc/api/admin_sidekiq_queues.md
+++ b/doc/api/admin_sidekiq_queues.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
---
-# Sidekiq queues administration API **(CORE ONLY)**
+# Sidekiq queues administration API **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25998) in GitLab 12.9
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 029e434749f..ebe856715a6 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -25,6 +25,7 @@ The following API resources are available in the project context:
| Resource | Available endpoints |
|:--------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
+| [Access tokens](resource_access_tokens.md) | `/projects/:id/access_tokens` |
| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
@@ -76,7 +77,7 @@ The following API resources are available in the project context:
| [Remote mirrors](remote_mirrors.md) | `/projects/:id/remote_mirrors` |
| [Repositories](repositories.md) | `/projects/:id/repository` |
| [Repository files](repository_files.md) | `/projects/:id/repository/files` |
-| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
+| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
| [Resource label events](resource_label_events.md) | `/projects/:id/issues/.../resource_label_events`, `/projects/:id/merge_requests/.../resource_label_events` (also available for groups) |
| [Runners](runners.md) | `/projects/:id/runners` (also available standalone) |
| [Search](search.md) | `/projects/:id/search` (also available for groups and standalone) |
@@ -127,10 +128,10 @@ The following API resources are available outside of project and group contexts
| Resource | Available endpoints |
|:---------------------------------------------------|:------------------------------------------------------------------------|
| [Instance-level CI/CD variables](instance_level_ci_variables.md) | `/admin/ci/variables` |
-| [Sidekiq queues administration](admin_sidekiq_queues.md) **(CORE ONLY)** | `/admin/sidekiq/queues/:queue_name` |
-| [Appearance](appearance.md) **(CORE ONLY)** | `/application/appearance` |
+| [Sidekiq queues administration](admin_sidekiq_queues.md) **(FREE SELF)** | `/admin/sidekiq/queues/:queue_name` |
+| [Appearance](appearance.md) **(FREE SELF)** | `/application/appearance` |
| [Applications](applications.md) | `/applications` |
-| [Audit Events](audit_events.md) **(PREMIUM ONLY)** | `/audit_events` |
+| [Audit Events](audit_events.md) **(PREMIUM SELF)** | `/audit_events` |
| [Avatar](avatar.md) | `/avatar` |
| [Broadcast messages](broadcast_messages.md) | `/broadcast_messages` |
| [Code snippets](snippets.md) | `/snippets` |
@@ -138,14 +139,15 @@ The following API resources are available outside of project and group contexts
| [Deploy keys](deploy_keys.md) | `/deploy_keys` (also available for projects) |
| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
| [Feature flags](features.md) | `/features` |
-| [Geo Nodes](geo_nodes.md) **(PREMIUM ONLY)** | `/geo_nodes` |
+| [Geo Nodes](geo_nodes.md) **(PREMIUM SELF)** | `/geo_nodes` |
| [Group Activity Analytics](group_activity_analytics.md) **(STARTER)** | `/analytics/group_activity/{issues_count | merge_requests_count | new_members_count }` |
+| [Group repository storage moves](group_repository_storage_moves.md) **(PREMIUM SELF)** | `/group_repository_storage_moves` |
| [Import repository from GitHub](import.md) | `/import/github` |
| [Instance clusters](instance_clusters.md) | `/admin/clusters` |
| [Issues](issues.md) | `/issues` (also available for groups and projects) |
| [Issues Statistics](issues_statistics.md) | `/issues_statistics` (also available for groups and projects) |
| [Keys](keys.md) | `/keys` |
-| [License](license.md) **(CORE ONLY)** | `/license` |
+| [License](license.md) **(FREE SELF)** | `/license` |
| [Markdown](markdown.md) | `/markdown` |
| [Merge requests](merge_requests.md) | `/merge_requests` (also available for groups and projects) |
| [Metrics dashboard annotations](metrics_dashboard_annotations.md) | `/environments/:id/metrics_dashboard/annotations`, `/clusters/:id/metrics_dashboard/annotations` |
@@ -154,13 +156,13 @@ The following API resources are available outside of project and group contexts
| [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) |
| [Personal access tokens](personal_access_tokens.md) | `/personal_access_tokens` |
| [Projects](projects.md) | `/users/:id/projects` (also available for projects) |
-| [Project repository storage moves](project_repository_storage_moves.md) **(CORE ONLY)** | `/project_repository_storage_moves` |
+| [Project repository storage moves](project_repository_storage_moves.md) **(FREE SELF)** | `/project_repository_storage_moves` |
| [Runners](runners.md) | `/runners` (also available for projects) |
| [Search](search.md) | `/search` (also available for groups and projects) |
-| [Settings](settings.md) **(CORE ONLY)** | `/application/settings` |
-| [Snippet repository storage moves](snippet_repository_storage_moves.md) **(CORE ONLY)** | `/snippet_repository_storage_moves` |
+| [Settings](settings.md) **(FREE SELF)** | `/application/settings` |
+| [Snippet repository storage moves](snippet_repository_storage_moves.md) **(FREE SELF)** | `/snippet_repository_storage_moves` |
| [Statistics](statistics.md) | `/application/statistics` |
-| [Sidekiq metrics](sidekiq_metrics.md) **(CORE ONLY)** | `/sidekiq` |
+| [Sidekiq metrics](sidekiq_metrics.md) **(FREE SELF)** | `/sidekiq` |
| [Suggestions](suggestions.md) | `/suggestions` |
| [System hooks](system_hooks.md) | `/hooks` |
| [To-dos](todos.md) | `/todos` |
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index d03fc94cfcf..5689cacd9ce 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -4,7 +4,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Appearance API **(CORE ONLY)**
+# Appearance API **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16647) in GitLab 12.7.
diff --git a/doc/api/applications.md b/doc/api/applications.md
index eb4930c8721..19a80685b6f 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -14,7 +14,7 @@ Applications API operates on OAuth applications for:
- [Allowing access to GitLab resources on a user's behalf](oauth2.md).
NOTE:
-Only admin users can use the Applications API.
+Only administrator users can use the Applications API.
## Create an application
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 5017c8defaf..78bf292a3d7 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Audit Events API
-## Instance Audit Events **(PREMIUM ONLY)**
+## Instance Audit Events **(PREMIUM SELF)**
The Audit Events API allows you to retrieve [instance audit events](../administration/audit_events.md#instance-events).
@@ -126,7 +126,7 @@ Example response:
}
```
-## Group Audit Events **(STARTER)**
+## Group Audit Events **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) in GitLab 12.5.
@@ -233,7 +233,7 @@ Example response:
}
```
-## Project Audit Events **(STARTER)**
+## Project Audit Events **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219238) in GitLab 13.1.
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index ccaa50eedd8..14fdc5e8afd 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Get a single avatar URL
-Get a single [avatar](../user/profile/index.md#profile-settings) URL for a user with the given email address.
+Get a single [avatar](../user/profile/index.md#user-settings) URL for a user with the given email address.
If:
diff --git a/doc/api/boards.md b/doc/api/boards.md
index e86f0d846ed..021e4103228 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -8,8 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Every API call to boards must be authenticated.
-If a user is not a member of a project and the project is private, a `GET`
-request on that project will result to a `404` status code.
+If a user is not a member of a private project,
+a `GET` request on that project results in a `404` status code.
## List project issue boards
@@ -488,7 +488,7 @@ Example response:
## Delete a board list from a board
-Only for admins and project owners. Deletes the board list in question.
+Only for administrators and project owners. Deletes a board list.
```plaintext
DELETE /projects/:id/boards/:board_id/lists/:list_id
diff --git a/doc/api/branches.md b/doc/api/branches.md
index 74383841272..e9e27a358f0 100644
--- a/doc/api/branches.md
+++ b/doc/api/branches.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Branches API
+# Branches API **(FREE)**
This API operates on [repository branches](../user/project/repository/branches/index.md).
diff --git a/doc/api/build_triggers.md b/doc/api/build_triggers.md
deleted file mode 100644
index 13adf949981..00000000000
--- a/doc/api/build_triggers.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'pipeline_triggers.md'
----
-
-This document was moved to [another location](pipeline_triggers.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/builds.md b/doc/api/builds.md
deleted file mode 100644
index b7b61e853a8..00000000000
--- a/doc/api/builds.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'jobs.md'
----
-
-This document was moved to [another location](jobs.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 81014956fc5..f4896f75c93 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -5,7 +5,9 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Commits API
+# Commits API **(FREE)**
+
+This API operates on [repository commits](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository). Read more about [GitLab-specific information](../user/project/repository/index.md#commits) for commits.
## List repository commits
diff --git a/doc/api/dependency_proxy.md b/doc/api/dependency_proxy.md
index ab691aaecea..8448edef9c5 100644
--- a/doc/api/dependency_proxy.md
+++ b/doc/api/dependency_proxy.md
@@ -9,9 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Purge the dependency proxy for a group
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11631) in GitLab 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Core](https://about.gitlab.com/pricing/) in GitLab 13.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/273655) to [GitLab Free](https://about.gitlab.com/pricing/) in GitLab 13.6.
-Deletes the cached manifests and blobs for a group. This endpoint requires group admin access.
+Deletes the cached manifests and blobs for a group. This endpoint requires group owner access.
WARNING:
[A bug exists](https://gitlab.com/gitlab-org/gitlab/-/issues/277161) for this API.
diff --git a/doc/api/deploy_key_multiple_projects.md b/doc/api/deploy_key_multiple_projects.md
deleted file mode 100644
index 16ce201c1c0..00000000000
--- a/doc/api/deploy_key_multiple_projects.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: deploy_keys.md#adding-deploy-keys-to-multiple-projects
----
-
-This document was moved to [another location](deploy_keys.md#adding-deploy-keys-to-multiple-projects).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md
index 91046717c1d..30a56e6253b 100644
--- a/doc/api/deploy_keys.md
+++ b/doc/api/deploy_keys.md
@@ -4,11 +4,11 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Deploy Keys API
+# Deploy keys API
## List all deploy keys
-Get a list of all deploy keys across all projects of the GitLab instance. This endpoint requires admin access and is not available on GitLab.com.
+Get a list of all deploy keys across all projects of the GitLab instance. This 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 2bdec4a0688..eae46d5f2f5 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 admin access.
+Get a list of all deploy tokens across the GitLab instance. This endpoint requires administrator access.
```plaintext
GET /deploy_tokens
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index a7a53987fe9..d88d4780e65 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, api
---
-# Discussions API
+# Discussions API **(FREE)**
Discussions are a set of related notes on:
@@ -156,7 +156,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `issue_iid` | integer | yes | The IID of an issue |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment"
@@ -182,7 +182,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -365,7 +365,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `snippet_id` | integer | yes | The ID of an snippet |
| `body` | string | yes | The content of a discussion |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment"
@@ -388,7 +388,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -572,7 +572,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions?body=comment"
@@ -596,7 +596,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -847,7 +847,7 @@ Parameters:
| `merge_request_iid` | integer | yes | The IID of a merge request |
| `body` | string | yes | The content of the thread |
| `commit_id` | string | no | SHA referencing commit to start this thread on |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
| `position` | hash | no | Position when creating a diff note |
| `position[base_sha]` | string | yes | Base commit SHA in the source branch |
| `position[start_sha]` | string | yes | SHA referencing commit in target branch |
@@ -912,7 +912,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -1147,7 +1147,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `commit_id` | integer | yes | The ID of a commit |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
| `position` | hash | no | Position when creating a diff note |
| `position[base_sha]` | string | yes | Base commit SHA in the source branch |
| `position[start_sha]` | string | yes | SHA referencing commit in target branch |
@@ -1183,7 +1183,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
diff --git a/doc/api/dora4_group_analytics.md b/doc/api/dora4_group_analytics.md
new file mode 100644
index 00000000000..7a7260f40e8
--- /dev/null
+++ b/doc/api/dora4_group_analytics.md
@@ -0,0 +1,84 @@
+---
+stage: Release
+group: Release
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, api
+---
+
+# DORA4 Analytics Group API **(ULTIMATE ONLY)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291747) in GitLab 13.9.
+> - 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-dora4-analytics-group-api). **(ULTIMATE ONLY)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+All methods require reporter authorization.
+
+## List group deployment frequencies
+
+Get a list of all group deployment frequencies:
+
+```plaintext
+GET /groups/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval
+```
+
+Attributes:
+
+| Attribute | Type | Required | Description |
+|--------------|--------|----------|-----------------------|
+| `id` | string | yes | The ID of the group. |
+
+Parameters:
+
+| Parameter | Type | Required | Description |
+|--------------|--------|----------|-----------------------|
+| `environment`| string | yes | The name of the environment to filter by. |
+| `from` | string | yes | Datetime range to start from. Inclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`). |
+| `to` | string | no | Datetime range to end at. Exclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`). |
+| `interval` | string | no | The bucketing interval (`all`, `monthly`, `daily`). |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval"
+```
+
+Example response:
+
+```json
+[
+ {
+ "from": "2017-01-01",
+ "to": "2017-01-02",
+ "value": 106
+ },
+ {
+ "from": "2017-01-02",
+ "to": "2017-01-03",
+ "value": 55
+ }
+]
+```
+
+## Enable or disable DORA4 Analytics Group API **(ULTIMATE ONLY)**
+
+DORA4 Analytics Group API 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(:dora4_group_deployment_frequency_api)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:dora4_group_deployment_frequency_api)
+```
diff --git a/doc/api/dora4_project_analytics.md b/doc/api/dora4_project_analytics.md
new file mode 100644
index 00000000000..a1becb056bf
--- /dev/null
+++ b/doc/api/dora4_project_analytics.md
@@ -0,0 +1,54 @@
+---
+stage: Release
+group: Release
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, api
+---
+
+# DORA4 Analytics Project API **(ULTIMATE ONLY)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.
+
+All methods require reporter authorization.
+
+## List project deployment frequencies
+
+Get a list of all project deployment frequencies, sorted by date:
+
+```plaintext
+GET /projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval
+```
+
+| Attribute | Type | Required | Description |
+|--------------|--------|----------|-----------------------|
+| `id` | string | yes | The ID of the project |
+
+| Parameter | Type | Required | Description |
+|--------------|--------|----------|-----------------------|
+| `environment`| string | yes | The name of the environment to filter by |
+| `from` | string | yes | Datetime range to start from, inclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
+| `to` | string | no | Datetime range to end at, exclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
+| `interval` | string | no | The bucketing interval (`all`, `monthly`, `daily`) |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval"
+```
+
+Example response:
+
+```json
+[
+ {
+ "from": "2017-01-01",
+ "to": "2017-01-02",
+ "value": 106
+ },
+ {
+ "from": "2017-01-02",
+ "to": "2017-01-03",
+ "value": 55
+ }
+]
+```
diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md
index cabab18ed71..228f68531fd 100644
--- a/doc/api/epic_links.md
+++ b/doc/api/epic_links.md
@@ -12,9 +12,10 @@ Manages parent-child [epic relationships](../user/group/epics/index.md#multi-lev
Every API call to `epic_links` must be authenticated.
-If a user makes a `GET` request to a private group they are not a member of, the result is a `404` status code.
+If a user is not a member of a private group, a `GET` request on that
+group results in a `404` status code.
-Multi-level Epics are available only in GitLab [Ultimate/Gold](https://about.gitlab.com/pricing/).
+Multi-level Epics are available only in GitLab [Ultimate](https://about.gitlab.com/pricing/).
If the Multi-level Epics feature is not available, a `403` status code is returned.
## List epics related to a given epic
diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md
index 12ff0148661..c737edbdc44 100644
--- a/doc/api/error_tracking.md
+++ b/doc/api/error_tracking.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Error Tracking settings API
+# Error Tracking settings API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34940) in GitLab 12.7.
diff --git a/doc/api/events.md b/doc/api/events.md
index d073e7ed633..e2ff779f3bf 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -25,7 +25,7 @@ Available action types for the `action` parameter are:
- `destroyed`
- `expired`
-Note that these options are downcased.
+Note that these options are in lower case.
### Target Types
@@ -39,7 +39,7 @@ Available target types for the `target_type` parameter are:
- `snippet`
- `user`
-Note that these options are downcased.
+Note that these options are in lower case.
### Date formatting
diff --git a/doc/api/feature_flag_user_lists.md b/doc/api/feature_flag_user_lists.md
index ba03b81ebfd..e0a5fe99663 100644
--- a/doc/api/feature_flag_user_lists.md
+++ b/doc/api/feature_flag_user_lists.md
@@ -4,10 +4,10 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Feature flag user lists API **(CORE)**
+# Feature flag user lists API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205409) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Core in 13.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
API for accessing GitLab Feature Flag User Lists.
diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md
index e8d6911463d..77d30475555 100644
--- a/doc/api/feature_flags.md
+++ b/doc/api/feature_flags.md
@@ -4,11 +4,11 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Feature Flags API **(CORE)**
+# Feature Flags API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md
index 8a5af39a37f..33ea2727fb9 100644
--- a/doc/api/feature_flags_legacy.md
+++ b/doc/api/feature_flags_legacy.md
@@ -4,11 +4,11 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Legacy Feature Flags API **(CORE)**
+# Legacy Feature Flags API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
WARNING:
This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). Use [this API](feature_flags.md) instead.
diff --git a/doc/api/features.md b/doc/api/features.md
index 0ed0dec1b6d..cb3ee04d076 100644
--- a/doc/api/features.md
+++ b/doc/api/features.md
@@ -128,7 +128,7 @@ POST /features/:name
| `user` | string | no | A GitLab username |
| `group` | string | no | A GitLab group's path, for example `gitlab-org` |
| `project` | string | no | A projects path, for example `gitlab-org/gitlab-foss` |
-| `force` | boolean | no | Skip feature flag validation checks, ie. YAML definition |
+| `force` | boolean | no | Skip feature flag validation checks, such as a YAML definition |
Note that you can enable or disable a feature for a `feature_group`, a `user`,
a `group`, and a `project` in a single API call.
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index 280d02ced32..a2417af5285 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -4,10 +4,10 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Geo Nodes API **(PREMIUM ONLY)**
+# Geo Nodes API **(PREMIUM SELF)**
To interact with Geo node endpoints, you need to authenticate yourself as an
-admin.
+administrator.
## Create a new Geo node
@@ -307,37 +307,37 @@ Example response:
"health_status": "Healthy",
"missing_oauth_application": false,
"attachments_count": 1,
- "attachments_synced_count": nil,
- "attachments_failed_count": nil,
+ "attachments_synced_count": null,
+ "attachments_failed_count": null,
"attachments_synced_missing_on_primary_count": 0,
"attachments_synced_in_percentage": "0.00%",
- "db_replication_lag_seconds": nil,
+ "db_replication_lag_seconds": null,
"lfs_objects_count": 0,
- "lfs_objects_synced_count": nil,
- "lfs_objects_failed_count": nil,
+ "lfs_objects_synced_count": null,
+ "lfs_objects_failed_count": null,
"lfs_objects_synced_missing_on_primary_count": 0,
"lfs_objects_synced_in_percentage": "0.00%",
"job_artifacts_count": 2,
- "job_artifacts_synced_count": nil,
- "job_artifacts_failed_count": nil,
+ "job_artifacts_synced_count": null,
+ "job_artifacts_failed_count": null,
"job_artifacts_synced_missing_on_primary_count": 0,
"job_artifacts_synced_in_percentage": "0.00%",
"container_repositories_count": 3,
- "container_repositories_synced_count": nil,
- "container_repositories_failed_count": nil,
+ "container_repositories_synced_count": null,
+ "container_repositories_failed_count": null,
"container_repositories_synced_in_percentage": "0.00%",
"design_repositories_count": 3,
- "design_repositories_synced_count": nil,
- "design_repositories_failed_count": nil,
+ "design_repositories_synced_count": null,
+ "design_repositories_failed_count": null,
"design_repositories_synced_in_percentage": "0.00%",
"projects_count": 41,
"repositories_count": 41,
- "repositories_failed_count": nil,
- "repositories_synced_count": nil,
+ "repositories_failed_count": null,
+ "repositories_synced_count": null,
"repositories_synced_in_percentage": "0.00%",
"wikis_count": 41,
- "wikis_failed_count": nil,
- "wikis_synced_count": nil,
+ "wikis_failed_count": null,
+ "wikis_synced_count": null,
"wikis_synced_in_percentage": "0.00%",
"replication_slots_count": 1,
"replication_slots_used_count": 1,
@@ -367,7 +367,7 @@ Example response:
"repositories_checked_in_percentage": "17.07%",
"last_event_id": 23,
"last_event_timestamp": 1509681166,
- "cursor_last_event_id": nil,
+ "cursor_last_event_id": null,
"cursor_last_event_timestamp": 0,
"last_successful_status_check_timestamp": 1510125024,
"version": "10.3.0",
@@ -408,12 +408,12 @@ Example response:
"job_artifacts_synced_missing_on_primary_count": 0,
"job_artifacts_synced_in_percentage": "50.00%",
"container_repositories_count": 3,
- "container_repositories_synced_count": nil,
- "container_repositories_failed_count": nil,
+ "container_repositories_synced_count": null,
+ "container_repositories_failed_count": null,
"container_repositories_synced_in_percentage": "0.00%",
"design_repositories_count": 3,
- "design_repositories_synced_count": nil,
- "design_repositories_failed_count": nil,
+ "design_repositories_synced_count": null,
+ "design_repositories_failed_count": null,
"design_repositories_synced_in_percentage": "0.00%",
"projects_count": 41,
"repositories_count": 41,
@@ -424,10 +424,10 @@ Example response:
"wikis_failed_count": 0,
"wikis_synced_count": 41,
"wikis_synced_in_percentage": "100.00%",
- "replication_slots_count": nil,
- "replication_slots_used_count": nil,
+ "replication_slots_count": null,
+ "replication_slots_used_count": null,
"replication_slots_used_in_percentage": "0.00%",
- "replication_slots_max_retained_wal_bytes": nil,
+ "replication_slots_max_retained_wal_bytes": null,
"repositories_checksummed_count": 20,
"repositories_checksum_failed_count": 5,
"repositories_checksummed_in_percentage": "48.78%",
@@ -518,12 +518,12 @@ Example response:
"job_artifacts_synced_missing_on_primary_count": 0,
"job_artifacts_synced_in_percentage": "50.00%",
"container_repositories_count": 3,
- "container_repositories_synced_count": nil,
- "container_repositories_failed_count": nil,
+ "container_repositories_synced_count": null,
+ "container_repositories_failed_count": null,
"container_repositories_synced_in_percentage": "0.00%",
"design_repositories_count": 3,
- "design_repositories_synced_count": nil,
- "design_repositories_failed_count": nil,
+ "design_repositories_synced_count": null,
+ "design_repositories_failed_count": null,
"design_repositories_synced_in_percentage": "0.00%",
"projects_count": 41,
"repositories_count": 41,
@@ -534,10 +534,10 @@ Example response:
"wikis_failed_count": 0,
"wikis_synced_count": 41,
"wikis_synced_in_percentage": "100.00%",
- "replication_slots_count": nil,
- "replication_slots_used_count": nil,
+ "replication_slots_count": null,
+ "replication_slots_used_count": null,
"replication_slots_used_in_percentage": "0.00%",
- "replication_slots_max_retained_wal_bytes": nil,
+ "replication_slots_max_retained_wal_bytes": null,
"last_event_id": 23,
"last_event_timestamp": 1509681166,
"cursor_last_event_id": 23,
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index ca2b7989700..1b7e273f7a1 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -314,9 +314,10 @@ Pagination is a way of only asking for a subset of the records (say, the first 1
If we want more of them, we can make another request for the next 10 from the server
(in the form of something like "please give me the next 10 records").
-By default, the GitLab GraphQL API returns only the first 100 records of any collection.
+By default, the GitLab GraphQL API returns 100 records per page.
This can be changed by using `first` or `last` arguments. Both arguments take a value,
so `first: 10` returns the first 10 records, and `last: 10` the last 10 records.
+There is a limit on how many records will be returned per page, which is generally `100`.
Example: Retrieve only the first 2 issues (slicing). The `cursor` field gives us a position from which
we can retrieve further records relative to that one.
diff --git a/doc/api/graphql/img/users_query_example_v13_8.png b/doc/api/graphql/img/users_query_example_v13_8.png
index b4c2b4e999a..155824cad6e 100644
--- a/doc/api/graphql/img/users_query_example_v13_8.png
+++ b/doc/api/graphql/img/users_query_example_v13_8.png
Binary files differ
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 45a327d323b..7a68b1cdf16 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -48,7 +48,7 @@ libraries](https://graphql.org/code/#graphql-clients) to consume the
API and avoid manual parsing.
Since there's no fixed endpoints and data model, new abilities can be
-added to the API without creating breaking changes. This allows us to
+added to the API without creating [breaking changes](../../development/contributing/#breaking-changes). This allows us to
have a versionless API as described in [the GraphQL
documentation](https://graphql.org/learn/best-practices/#versioning).
@@ -117,6 +117,43 @@ information about multiplexed queries is also available for
[GraphQL Ruby](https://graphql-ruby.org/queries/multiplex.html), the
library GitLab uses on the backend.
+## Limits
+
+The following limits apply to the GitLab GraphQL API.
+
+### Max page size
+
+By default, connections return at most `100` records ("nodes") per page,
+and this limit applies to most connections in the API. Particular connections
+may have different max page size limits that are higher or lower.
+
+### Max query complexity
+
+The GitLab GraphQL API scores the _complexity_ of a query. Generally, larger
+queries will have a higher complexity score. This limit is designed to protect
+the API from performing queries that could negatively impact its overall performance.
+
+The complexity of a single query is limited to a maximum of:
+
+- `200` for unauthenticated requests.
+- `250` for authenticated requests.
+
+There is no way to discover the complexity of a query except by exceeding the limit.
+
+If a query exceeds the complexity limit an error message response will
+be returned.
+
+In general, each field in a query will add `1` to the complexity score, although
+this can be higher or lower for particular fields. Sometimes the addition of
+certain arguments may also increase the complexity of a query.
+
+The complexity limits may be revised in future, and additionally, the complexity
+of a query may be altered.
+
+### Request timeout
+
+Requests time out at 30 seconds.
+
## Reference
The GitLab GraphQL reference [is available](reference/index.md).
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 94792a49933..4e89f663efc 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -3,12 +3,12 @@ Represents the access level of a relationship between a User and object that it
"""
type AccessLevel {
"""
- Integer representation of access level
+ Integer representation of access level.
"""
integerValue: Int
"""
- String representation of access level
+ String representation of access level.
"""
stringValue: AccessLevelEnum
}
@@ -40,7 +40,7 @@ input AddAwardEmojiInput {
clientMutationId: String
"""
- The emoji name
+ The emoji name.
"""
name: String!
}
@@ -180,7 +180,7 @@ Describes an alert from the project's Alert Management
"""
type AlertManagementAlert implements Noteable {
"""
- Assignees of the alert
+ Assignees of the alert.
"""
assignees(
"""
@@ -205,27 +205,27 @@ type AlertManagementAlert implements Noteable {
): UserConnection
"""
- Timestamp the alert was created
+ Timestamp the alert was created.
"""
createdAt: Time
"""
- Description of the alert
+ Description of the alert.
"""
description: String
"""
- Alert details
+ Alert details.
"""
details: JSON
"""
- The URL of the alert detail page
+ The URL of the alert detail page.
"""
detailsUrl: String!
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -250,47 +250,47 @@ type AlertManagementAlert implements Noteable {
): DiscussionConnection!
"""
- Timestamp the alert ended
+ Timestamp the alert ended.
"""
endedAt: Time
"""
- Environment for the alert
+ Environment for the alert.
"""
environment: Environment
"""
- Number of events of this alert
+ Number of events of this alert.
"""
eventCount: Int
"""
- List of hosts the alert came from
+ List of hosts the alert came from.
"""
hosts: [String!]
"""
- Internal ID of the alert
+ Internal ID of the alert.
"""
iid: ID!
"""
- Internal ID of the GitLab issue attached to the alert
+ Internal ID of the GitLab issue attached to the alert.
"""
issueIid: ID
"""
- URL for metrics embed for the alert
+ URL for metrics embed for the alert.
"""
metricsDashboardUrl: String
"""
- Monitoring tool the alert came from
+ Monitoring tool the alert came from.
"""
monitoringTool: String
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -315,42 +315,42 @@ type AlertManagementAlert implements Noteable {
): NoteConnection!
"""
- The alert condition for Prometheus
+ The alert condition for Prometheus.
"""
prometheusAlert: PrometheusAlert
"""
- Runbook for the alert as defined in alert details
+ Runbook for the alert as defined in alert details.
"""
runbook: String
"""
- Service the alert came from
+ Service the alert came from.
"""
service: String
"""
- Severity of the alert
+ Severity of the alert.
"""
severity: AlertManagementSeverity
"""
- Timestamp the alert was raised
+ Timestamp the alert was raised.
"""
startedAt: Time
"""
- Status of the alert
+ Status of the alert.
"""
status: AlertManagementStatus
"""
- Title of the alert
+ Title of the alert.
"""
title: String
"""
- Todos of the current user for the alert
+ To-do items of the current user for the alert.
"""
todos(
"""
@@ -405,7 +405,7 @@ type AlertManagementAlert implements Noteable {
): TodoConnection
"""
- Timestamp the alert was last updated
+ Timestamp the alert was last updated.
"""
updatedAt: Time
}
@@ -570,7 +570,7 @@ type AlertManagementAlertStatusCountsType {
acknowledged: Int
"""
- Total number of alerts for the project
+ Total number of alerts for the project.
"""
all: Int
@@ -580,7 +580,7 @@ type AlertManagementAlertStatusCountsType {
ignored: Int
"""
- Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project
+ Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project.
"""
open: Int
@@ -615,79 +615,79 @@ An endpoint and credentials used to accept alerts for a project
"""
type AlertManagementHttpIntegration implements AlertManagementIntegration {
"""
- Whether the endpoint is currently accepting alerts
+ Whether the endpoint is currently accepting alerts.
"""
active: Boolean
"""
- URL at which Prometheus metrics can be queried to populate the metrics dashboard
+ URL at which Prometheus metrics can be queried to populate the metrics dashboard.
"""
apiUrl: String
"""
- ID of the integration
+ ID of the integration.
"""
id: ID!
"""
- Name of the integration
+ Name of the integration.
"""
name: String
"""
- Token used to authenticate alert notification requests
+ Token used to authenticate alert notification requests.
"""
token: String
"""
- Type of integration
+ Type of integration.
"""
type: AlertManagementIntegrationType!
"""
- Endpoint which accepts alert notifications
+ Endpoint which accepts alert notifications.
"""
url: String
}
"""
-Identifier of AlertManagement::HttpIntegration
+Identifier of AlertManagement::HttpIntegration.
"""
scalar AlertManagementHttpIntegrationID
interface AlertManagementIntegration {
"""
- Whether the endpoint is currently accepting alerts
+ Whether the endpoint is currently accepting alerts.
"""
active: Boolean
"""
- URL at which Prometheus metrics can be queried to populate the metrics dashboard
+ URL at which Prometheus metrics can be queried to populate the metrics dashboard.
"""
apiUrl: String
"""
- ID of the integration
+ ID of the integration.
"""
id: ID!
"""
- Name of the integration
+ Name of the integration.
"""
name: String
"""
- Token used to authenticate alert notification requests
+ Token used to authenticate alert notification requests.
"""
token: String
"""
- Type of integration
+ Type of integration.
"""
type: AlertManagementIntegrationType!
"""
- Endpoint which accepts alert notifications
+ Endpoint which accepts alert notifications.
"""
url: String
}
@@ -743,6 +743,26 @@ enum AlertManagementIntegrationType {
}
"""
+Parsed field from an alert used for custom mappings
+"""
+type AlertManagementPayloadAlertField {
+ """
+ Human-readable label of the payload path.
+ """
+ label: String
+
+ """
+ Path to value inside payload JSON.
+ """
+ path: [String!]
+
+ """
+ Type of the parsed value.
+ """
+ type: AlertManagementPayloadAlertFieldType
+}
+
+"""
Field that are available while modifying the custom mapping attributes for an HTTP integration
"""
input AlertManagementPayloadAlertFieldInput {
@@ -847,37 +867,37 @@ An endpoint and credentials used to accept Prometheus alerts for a project
"""
type AlertManagementPrometheusIntegration implements AlertManagementIntegration {
"""
- Whether the endpoint is currently accepting alerts
+ Whether the endpoint is currently accepting alerts.
"""
active: Boolean
"""
- URL at which Prometheus metrics can be queried to populate the metrics dashboard
+ URL at which Prometheus metrics can be queried to populate the metrics dashboard.
"""
apiUrl: String
"""
- ID of the integration
+ ID of the integration.
"""
id: ID!
"""
- Name of the integration
+ Name of the integration.
"""
name: String
"""
- Token used to authenticate alert notification requests
+ Token used to authenticate alert notification requests.
"""
token: String
"""
- Type of integration
+ Type of integration.
"""
type: AlertManagementIntegrationType!
"""
- Endpoint which accepts alert notifications
+ Endpoint which accepts alert notifications.
"""
url: String
}
@@ -997,7 +1017,7 @@ type AlertSetAssigneesPayload {
issue: Issue
"""
- The todo after mutation.
+ The to-do item after mutation.
"""
todo: Todo
}
@@ -1047,17 +1067,138 @@ type AlertTodoCreatePayload {
issue: Issue
"""
- The todo after mutation.
+ The to-do item after mutation.
"""
todo: Todo
}
"""
-Identifier of Analytics::DevopsAdoption::Segment
+Identifier of Analytics::DevopsAdoption::Segment.
"""
scalar AnalyticsDevopsAdoptionSegmentID
"""
+Data associated with configuring API fuzzing scans in GitLab CI
+"""
+type ApiFuzzingCiConfiguration {
+ """
+ All available scan modes.
+ """
+ scanModes: [ApiFuzzingScanMode!]
+
+ """
+ All default scan profiles.
+ """
+ scanProfiles: [ApiFuzzingScanProfile!]
+}
+
+"""
+Autogenerated input type of ApiFuzzingCiConfigurationCreate
+"""
+input ApiFuzzingCiConfigurationCreateInput {
+ """
+ File path or URL to the file that defines the API surface for scanning. Must
+ be in the format specified by the `scanMode` argument.
+ """
+ apiSpecificationFile: String!
+
+ """
+ CI variable containing the password for authenticating with the target API.
+ """
+ authPassword: String
+
+ """
+ CI variable containing the username for authenticating with the target API.
+ """
+ authUsername: String
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Full path of the project.
+ """
+ projectPath: ID!
+
+ """
+ The mode for API fuzzing scans.
+ """
+ scanMode: ApiFuzzingScanMode!
+
+ """
+ Name of a default profile to use for scanning. Ex: Quick-10.
+ """
+ scanProfile: String
+
+ """
+ URL for the target of API fuzzing scans.
+ """
+ target: String!
+}
+
+"""
+Autogenerated return type of ApiFuzzingCiConfigurationCreate
+"""
+type ApiFuzzingCiConfigurationCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ A YAML snippet that can be inserted into the project's `.gitlab-ci.yml` to set up API fuzzing scans.
+ """
+ configurationYaml: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The location at which the project's `.gitlab-ci.yml` file can be edited in the browser.
+ """
+ gitlabCiYamlEditPath: String
+}
+
+"""
+All possible ways to specify the API surface for an API fuzzing scan
+"""
+enum ApiFuzzingScanMode {
+ """
+ The API surface is specified by a HAR file.
+ """
+ HAR
+
+ """
+ The API surface is specified by a OPENAPI file.
+ """
+ OPENAPI
+}
+
+"""
+An API Fuzzing scan profile.
+"""
+type ApiFuzzingScanProfile {
+ """
+ A short description of the profile.
+ """
+ description: String
+
+ """
+ The unique name of the profile.
+ """
+ name: String
+
+ """
+ A syntax highlit HTML representation of the YAML.
+ """
+ yaml: String
+}
+
+"""
User availability status
"""
enum AvailabilityEnum {
@@ -1077,32 +1218,32 @@ An emoji awarded by a user
"""
type AwardEmoji {
"""
- The emoji description
+ The emoji description.
"""
description: String!
"""
- The emoji as an icon
+ The emoji as an icon.
"""
emoji: String!
"""
- The emoji name
+ The emoji name.
"""
name: String!
"""
- The emoji in unicode
+ The emoji in Unicode.
"""
unicode: String!
"""
- The unicode version for this emoji
+ The Unicode version for this emoji.
"""
unicodeVersion: String!
"""
- The user who awarded the emoji
+ The user who awarded the emoji.
"""
user: User!
}
@@ -1122,7 +1263,7 @@ input AwardEmojiAddInput {
clientMutationId: String
"""
- The emoji name
+ The emoji name.
"""
name: String!
}
@@ -1148,6 +1289,41 @@ type AwardEmojiAddPayload {
}
"""
+The connection type for AwardEmoji.
+"""
+type AwardEmojiConnection {
+ """
+ A list of edges.
+ """
+ edges: [AwardEmojiEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [AwardEmoji]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type AwardEmojiEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: AwardEmoji
+}
+
+"""
Autogenerated input type of AwardEmojiRemove
"""
input AwardEmojiRemoveInput {
@@ -1162,7 +1338,7 @@ input AwardEmojiRemoveInput {
clientMutationId: String
"""
- The emoji name
+ The emoji name.
"""
name: String!
}
@@ -1202,7 +1378,7 @@ input AwardEmojiToggleInput {
clientMutationId: String
"""
- The emoji name
+ The emoji name.
"""
name: String!
}
@@ -1233,18 +1409,18 @@ type AwardEmojiTogglePayload {
}
"""
-Identifier of Awardable
+Identifier of Awardable.
"""
scalar AwardableID
type BaseService implements Service {
"""
- Indicates if the service is active
+ Indicates if the service is active.
"""
active: Boolean
"""
- Class name of the service
+ Class name of the service.
"""
type: String
}
@@ -1257,52 +1433,52 @@ scalar BigInt
type Blob implements Entry {
"""
- Flat path of the entry
+ Flat path of the entry.
"""
flatPath: String!
"""
- ID of the entry
+ ID of the entry.
"""
id: ID!
"""
- LFS ID of the blob
+ LFS ID of the blob.
"""
lfsOid: String
"""
- Blob mode in numeric format
+ Blob mode in numeric format.
"""
mode: String
"""
- Name of the entry
+ Name of the entry.
"""
name: String!
"""
- Path of the entry
+ Path of the entry.
"""
path: String!
"""
- Last commit sha for the entry
+ Last commit SHA for the entry.
"""
sha: String!
"""
- Type of tree entry
+ Type of tree entry.
"""
type: EntryType!
"""
- Web path of the blob
+ Web path of the blob.
"""
webPath: String
"""
- Web URL of the blob
+ Web URL of the blob.
"""
webUrl: String
}
@@ -1356,12 +1532,12 @@ Represents a project or group board
"""
type Board {
"""
- The board assignee
+ The board assignee.
"""
assignee: User
"""
- Epics associated with board issues
+ Epics associated with board issues.
"""
epics(
"""
@@ -1391,17 +1567,17 @@ type Board {
): BoardEpicConnection
"""
- Whether or not backlog list is hidden
+ Whether or not backlog list is hidden.
"""
hideBacklogList: Boolean
"""
- Whether or not closed list is hidden
+ Whether or not closed list is hidden.
"""
hideClosedList: Boolean
"""
- ID (global ID) of the board
+ ID (global ID) of the board.
"""
id: ID!
@@ -1411,7 +1587,7 @@ type Board {
iteration: Iteration
"""
- Labels of the board
+ Labels of the board.
"""
labels(
"""
@@ -1436,7 +1612,7 @@ type Board {
): LabelConnection
"""
- Lists of the board
+ Lists of the board.
"""
lists(
"""
@@ -1471,12 +1647,12 @@ type Board {
): BoardListConnection
"""
- The board milestone
+ The board milestone.
"""
milestone: Milestone
"""
- Name of the board
+ Name of the board.
"""
name: String
@@ -1491,7 +1667,7 @@ type Board {
webUrl: String!
"""
- Weight of the board
+ Weight of the board.
"""
weight: Int
}
@@ -1534,14 +1710,39 @@ type BoardEdge {
"""
Represents an epic on an issue board
"""
-type BoardEpic implements CurrentUserTodos & Noteable {
+type BoardEpic implements CurrentUserTodos & Eventable & Noteable {
"""
- Author of the epic
+ Author of the epic.
"""
author: User!
"""
- Children (sub-epics) of the epic
+ A list of award emojis associated with the epic.
+ """
+ awardEmoji(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): AwardEmojiConnection
+
+ """
+ Children (sub-epics) of the epic.
"""
children(
"""
@@ -1639,22 +1840,22 @@ type BoardEpic implements CurrentUserTodos & Noteable {
): EpicConnection
"""
- Timestamp of when the epic was closed
+ Timestamp of when the epic was closed.
"""
closedAt: Time
"""
- Indicates if the epic is confidential
+ Indicates if the epic is confidential.
"""
confidential: Boolean
"""
- Timestamp of when the epic was created
+ Timestamp of when the epic was created.
"""
createdAt: Time
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -1678,28 +1879,28 @@ type BoardEpic implements CurrentUserTodos & Noteable {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
"""
- Number of open and closed descendant epics and issues
+ Number of open and closed descendant epics and issues.
"""
descendantCounts: EpicDescendantCount
"""
- Total weight of open and closed issues in the epic and its descendants
+ Total weight of open and closed issues in the epic and its descendants.
"""
descendantWeightSum: EpicDescendantWeights
"""
- Description of the epic
+ Description of the epic.
"""
description: String
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -1724,67 +1925,92 @@ type BoardEpic implements CurrentUserTodos & Noteable {
): DiscussionConnection!
"""
- Number of downvotes the epic has received
+ Number of downvotes the epic has received.
"""
downvotes: Int!
"""
- Due date of the epic
+ Due date of the epic.
"""
dueDate: Time
"""
- Fixed due date of the epic
+ Fixed due date of the epic.
"""
dueDateFixed: Time
"""
- Inherited due date of the epic from milestones
+ Inherited due date of the epic from milestones.
"""
dueDateFromMilestones: Time
"""
- Indicates if the due date has been manually set
+ Indicates if the due date has been manually set.
"""
dueDateIsFixed: Boolean
"""
- Group to which the epic belongs
+ A list of events associated with the object.
+ """
+ events(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EventConnection
+
+ """
+ Group to which the epic belongs.
"""
group: Group!
"""
- Indicates if the epic has children
+ Indicates if the epic has children.
"""
hasChildren: Boolean!
"""
- Indicates if the epic has direct issues
+ Indicates if the epic has direct issues.
"""
hasIssues: Boolean!
"""
- Indicates if the epic has a parent epic
+ Indicates if the epic has a parent epic.
"""
hasParent: Boolean!
"""
- Current health status of the epic
+ Current health status of the epic.
"""
healthStatus: EpicHealthStatus
"""
- ID of the epic
+ ID of the epic.
"""
id: ID!
"""
- Internal ID of the epic
+ Internal ID of the epic.
"""
iid: ID!
"""
- A list of issues associated with the epic
+ A list of issues associated with the epic.
"""
issues(
"""
@@ -1809,7 +2035,7 @@ type BoardEpic implements CurrentUserTodos & Noteable {
): EpicIssueConnection
"""
- Labels assigned to the epic
+ Labels assigned to the epic.
"""
labels(
"""
@@ -1834,7 +2060,7 @@ type BoardEpic implements CurrentUserTodos & Noteable {
): LabelConnection
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -1859,12 +2085,12 @@ type BoardEpic implements CurrentUserTodos & Noteable {
): NoteConnection!
"""
- Parent epic of the epic
+ Parent epic of the epic.
"""
parent: Epic
"""
- List of participants for the epic
+ List of participants for the epic.
"""
participants(
"""
@@ -1889,77 +2115,77 @@ type BoardEpic implements CurrentUserTodos & Noteable {
): UserConnection
"""
- Internal reference of the epic. Returned in shortened format by default
+ Internal reference of the epic. Returned in shortened format by default.
"""
reference(
"""
- Indicates if the reference should be returned in full
+ Indicates if the reference should be returned in full.
"""
full: Boolean = false
): String!
"""
- URI path of the epic-issue relationship
+ URI path of the epic-issue relationship.
"""
relationPath: String
"""
- The relative position of the epic in the epic tree
+ The relative position of the epic in the epic tree.
"""
relativePosition: Int
"""
- Start date of the epic
+ Start date of the epic.
"""
startDate: Time
"""
- Fixed start date of the epic
+ Fixed start date of the epic.
"""
startDateFixed: Time
"""
- Inherited start date of the epic from milestones
+ Inherited start date of the epic from milestones.
"""
startDateFromMilestones: Time
"""
- Indicates if the start date has been manually set
+ Indicates if the start date has been manually set.
"""
startDateIsFixed: Boolean
"""
- State of the epic
+ State of the epic.
"""
state: EpicState!
"""
- Indicates the currently logged in user is subscribed to the epic
+ Indicates the currently logged in user is subscribed to the epic.
"""
subscribed: Boolean!
"""
- Title of the epic
+ Title of the epic.
"""
title: String
"""
- Timestamp of when the epic was updated
+ Timestamp of when the epic was updated.
"""
updatedAt: Time
"""
- Number of upvotes the epic has received
+ Number of upvotes the epic has received.
"""
upvotes: Int!
"""
- Number of user discussions in the epic
+ Number of user discussions in the epic.
"""
userDiscussionsCount: Int!
"""
- Number of user notes of the epic
+ Number of user notes of the epic.
"""
userNotesCount: Int!
@@ -1969,17 +2195,17 @@ type BoardEpic implements CurrentUserTodos & Noteable {
userPermissions: EpicPermissions!
"""
- User preferences for the epic on the issue board
+ User preferences for the epic on the issue board.
"""
userPreferences: BoardEpicUserPreferences
"""
- Web path of the epic
+ Web path of the epic.
"""
webPath: String!
"""
- Web URL of the epic
+ Web URL of the epic.
"""
webUrl: String!
}
@@ -2024,79 +2250,79 @@ Represents user preferences for a board epic
"""
type BoardEpicUserPreferences {
"""
- Indicates epic should be displayed as collapsed
+ Indicates epic should be displayed as collapsed.
"""
collapsed: Boolean!
}
"""
-Identifier of Board
+Identifier of Board.
"""
scalar BoardID
input BoardIssueInput {
"""
- Filter by assignee username
+ Filter by assignee username.
"""
assigneeUsername: [String]
"""
- Filter by author username
+ Filter by author username.
"""
authorUsername: String
"""
- Filter by epic ID. Incompatible with epicWildcardId
+ Filter by epic ID. Incompatible with epicWildcardId.
"""
epicId: EpicID
"""
- Filter by epic ID wildcard. Incompatible with epicId
+ Filter by epic ID wildcard. Incompatible with epicId.
"""
epicWildcardId: EpicWildcardId
"""
- Filter by iteration title
+ Filter by iteration title.
"""
iterationTitle: String
"""
- Filter by iteration ID wildcard
+ Filter by iteration ID wildcard.
"""
iterationWildcardId: IterationWildcardId
"""
- Filter by label name
+ Filter by label name.
"""
labelName: [String]
"""
- Filter by milestone title
+ Filter by milestone title.
"""
milestoneTitle: String
"""
- Filter by reaction emoji
+ Filter by reaction emoji.
"""
myReactionEmoji: String
"""
- List of negated params. Warning: this argument is experimental and a subject to change in future
+ List of negated params. Warning: this argument is experimental and a subject to change in future.
"""
not: NegatedBoardIssueInput
"""
- Filter by release tag
+ Filter by release tag.
"""
releaseTag: String
"""
- Search query for issue title or description
+ Search query for issue title or description.
"""
search: String
"""
- Filter by weight
+ Filter by weight.
"""
weight: String
}
@@ -2106,22 +2332,22 @@ Represents a list for an issue board
"""
type BoardList {
"""
- Assignee in the list
+ Assignee in the list.
"""
assignee: User
"""
- Indicates if list is collapsed for this user
+ Indicates if list is collapsed for this user.
"""
collapsed: Boolean
"""
- ID (global ID) of the list
+ ID (global ID) of the list.
"""
id: ID!
"""
- Board issues
+ Board issues.
"""
issues(
"""
@@ -2151,57 +2377,57 @@ type BoardList {
): IssueConnection
"""
- Count of issues in the list
+ Count of issues in the list.
"""
issuesCount: Int
"""
- Iteration of the list
+ Iteration of the list.
"""
iteration: Iteration
"""
- Label of the list
+ Label of the list.
"""
label: Label
"""
- The current limit metric for the list
+ The current limit metric for the list.
"""
limitMetric: ListLimitMetric
"""
- Type of the list
+ Type of the list.
"""
listType: String!
"""
- Maximum number of issues in the list
+ Maximum number of issues in the list.
"""
maxIssueCount: Int
"""
- Maximum weight of issues in the list
+ Maximum weight of issues in the list.
"""
maxIssueWeight: Int
"""
- Milestone of the list
+ Milestone of the list.
"""
milestone: Milestone
"""
- Position of list within the board
+ Position of list within the board.
"""
position: Int
"""
- Title of the list
+ Title of the list.
"""
title: String!
"""
- Total weight of all issues in the list
+ Total weight of all issues in the list.
"""
totalWeight: Int
}
@@ -2281,7 +2507,7 @@ type BoardListCreatePayload {
errors: [String!]!
"""
- List of the issue board.
+ Issue list in the issue board.
"""
list: BoardList
}
@@ -2352,23 +2578,23 @@ type BoardListUpdateLimitMetricsPayload {
}
"""
-Identifier of Boards::EpicBoard
+Identifier of Boards::EpicBoard.
"""
scalar BoardsEpicBoardID
"""
-Identifier of Boards::EpicList
+Identifier of Boards::EpicList.
"""
scalar BoardsEpicListID
type Branch {
"""
- Commit for the branch
+ Commit for the branch.
"""
commit: Commit
"""
- Name of the branch
+ Name of the branch.
"""
name: String!
}
@@ -2378,31 +2604,38 @@ Represents the total number of issues and their weights for a particular day
"""
type BurnupChartDailyTotals {
"""
- Number of closed issues as of this day
+ Number of closed issues as of this day.
"""
completedCount: Int!
"""
- Total weight of closed issues as of this day
+ Total weight of closed issues as of this day.
"""
completedWeight: Int!
"""
- Date for burnup totals
+ Date for burnup totals.
"""
date: ISO8601Date!
"""
- Number of issues as of this day
+ Number of issues as of this day.
"""
scopeCount: Int!
"""
- Total weight of issues as of this day
+ Total weight of issues as of this day.
"""
scopeWeight: Int!
}
+type CiApplicationSettings {
+ """
+ Whether to keep the latest jobs artifacts.
+ """
+ keepLatestArtifact: Boolean
+}
+
type CiBuildNeed {
"""
Name of the job we need to complete.
@@ -2482,17 +2715,17 @@ type CiCdSettingsUpdatePayload {
type CiConfig {
"""
- Linting errors
+ Linting errors.
"""
errors: [String!]
"""
- Merged CI config YAML
+ Merged CI configuration YAML.
"""
mergedYaml: String
"""
- Stages of the pipeline
+ Stages of the pipeline.
"""
stages(
"""
@@ -2517,14 +2750,14 @@ type CiConfig {
): CiConfigStageConnection
"""
- Status of linting, can be either valid or invalid
+ Status of linting, can be either valid or invalid.
"""
status: CiConfigStatus
}
type CiConfigGroup {
"""
- Jobs in group
+ Jobs in group.
"""
jobs(
"""
@@ -2549,12 +2782,12 @@ type CiConfigGroup {
): CiConfigJobConnection
"""
- Name of the job group
+ Name of the job group.
"""
name: String
"""
- Size of the job group
+ Size of the job group.
"""
size: Int
}
@@ -2725,7 +2958,7 @@ type CiConfigJobRestriction {
type CiConfigNeed {
"""
- Name of the need
+ Name of the need.
"""
name: String
}
@@ -2767,7 +3000,7 @@ type CiConfigNeedEdge {
type CiConfigStage {
"""
- Groups of jobs for the stage
+ Groups of jobs for the stage.
"""
groups(
"""
@@ -2792,7 +3025,7 @@ type CiConfigStage {
): CiConfigGroupConnection
"""
- Name of the stage
+ Name of the stage.
"""
name: String
}
@@ -2849,12 +3082,12 @@ enum CiConfigStatus {
type CiGroup {
"""
- Detailed status of the group
+ Detailed status of the group.
"""
detailedStatus: DetailedStatus
"""
- Jobs in group
+ Jobs in group.
"""
jobs(
"""
@@ -2879,12 +3112,12 @@ type CiGroup {
): CiJobConnection
"""
- Name of the job group
+ Name of the job group.
"""
name: String
"""
- Size of the group
+ Size of the group.
"""
size: Int
}
@@ -2926,7 +3159,7 @@ type CiGroupEdge {
type CiJob {
"""
- Artifacts generated by the job
+ Artifacts generated by the job.
"""
artifacts(
"""
@@ -2951,17 +3184,17 @@ type CiJob {
): CiJobArtifactConnection
"""
- Detailed status of the job
+ Detailed status of the job.
"""
detailedStatus: DetailedStatus
"""
- Name of the job
+ Name of the job.
"""
name: String
"""
- References to builds that must complete before the jobs run
+ References to builds that must complete before the jobs run.
"""
needs(
"""
@@ -2986,24 +3219,24 @@ type CiJob {
): CiBuildNeedConnection
"""
- Pipeline the job belongs to
+ Pipeline the job belongs to.
"""
pipeline: Pipeline
"""
- Schedule for the build
+ Schedule for the build.
"""
scheduledAt: Time
}
type CiJobArtifact {
"""
- URL for downloading the artifact's file
+ URL for downloading the artifact's file.
"""
downloadPath: String
"""
- File type of the artifact
+ File type of the artifact.
"""
fileType: JobArtifactFileType
}
@@ -3079,18 +3312,18 @@ type CiJobEdge {
}
"""
-Identifier of Ci::Pipeline
+Identifier of Ci::Pipeline.
"""
scalar CiPipelineID
type CiStage {
"""
- Detailed status of the stage
+ Detailed status of the stage.
"""
detailedStatus: DetailedStatus
"""
- Group of jobs for the stage
+ Group of jobs for the stage.
"""
groups(
"""
@@ -3115,7 +3348,7 @@ type CiStage {
): CiGroupConnection
"""
- Name of the stage
+ Name of the stage.
"""
name: String
}
@@ -3157,27 +3390,32 @@ type CiStageEdge {
type ClusterAgent {
"""
- Timestamp the cluster agent was created
+ Timestamp the cluster agent was created.
"""
createdAt: Time
"""
- ID of the cluster agent
+ User object, containing information about the person who created the agent.
+ """
+ createdByUser: User
+
+ """
+ ID of the cluster agent.
"""
id: ID!
"""
- Name of the cluster agent
+ Name of the cluster agent.
"""
name: String
"""
- The project this cluster agent is associated with
+ The project this cluster agent is associated with.
"""
project: Project
"""
- Tokens associated with the cluster agent
+ Tokens associated with the cluster agent.
"""
tokens(
"""
@@ -3202,7 +3440,7 @@ type ClusterAgent {
): ClusterAgentTokenConnection
"""
- Timestamp the cluster agent was updated
+ Timestamp the cluster agent was updated.
"""
updatedAt: Time
}
@@ -3212,7 +3450,7 @@ The connection type for ClusterAgent.
"""
type ClusterAgentConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -3279,17 +3517,22 @@ type ClusterAgentEdge {
type ClusterAgentToken {
"""
- Cluster agent this token is associated with
+ Cluster agent this token is associated with.
"""
clusterAgent: ClusterAgent
"""
- Timestamp the token was created
+ Timestamp the token was created.
"""
createdAt: Time
"""
- Global ID of the token
+ The user who created the token.
+ """
+ createdByUser: User
+
+ """
+ Global ID of the token.
"""
id: ClustersAgentTokenID!
}
@@ -3299,7 +3542,7 @@ The connection type for ClusterAgentToken.
"""
type ClusterAgentTokenConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -3405,17 +3648,17 @@ type ClusterAgentTokenEdge {
}
"""
-Identifier of Clusters::Agent
+Identifier of Clusters::Agent.
"""
scalar ClustersAgentID
"""
-Identifier of Clusters::AgentToken
+Identifier of Clusters::AgentToken.
"""
scalar ClustersAgentTokenID
"""
-Identifier of Clusters::Cluster
+Identifier of Clusters::Cluster.
"""
scalar ClustersClusterID
@@ -3501,27 +3744,27 @@ type CodeCoverageSummary {
type Commit {
"""
- Author of the commit
+ Author of the commit.
"""
author: User
"""
- Commit authors gravatar
+ Commit authors gravatar.
"""
authorGravatar: String
"""
- Commit authors name
+ Commit authors name.
"""
authorName: String
"""
- Timestamp of when the commit was authored
+ Timestamp of when the commit was authored.
"""
authoredDate: Time
"""
- Description of the commit message
+ Description of the commit message.
"""
description: String
@@ -3531,17 +3774,17 @@ type Commit {
descriptionHtml: String
"""
- ID (global ID) of the commit
+ ID (global ID) of the commit.
"""
id: ID!
"""
- Raw commit message
+ Raw commit message.
"""
message: String
"""
- Pipelines of the commit ordered latest first
+ Pipelines of the commit ordered latest first.
"""
pipelines(
"""
@@ -3581,22 +3824,22 @@ type Commit {
): PipelineConnection
"""
- SHA1 ID of the commit
+ SHA1 ID of the commit.
"""
sha: String!
"""
- Short SHA1 ID of the commit
+ Short SHA1 ID of the commit.
"""
shortId: String!
"""
- Rendered HTML of the commit signature
+ Rendered HTML of the commit signature.
"""
signatureHtml: String
"""
- Title of the commit message
+ Title of the commit message.
"""
title: String
@@ -3606,49 +3849,49 @@ type Commit {
titleHtml: String
"""
- Web path of the commit
+ Web path of the commit.
"""
webPath: String!
"""
- Web URL of the commit
+ Web URL of the commit.
"""
webUrl: String!
}
input CommitAction {
"""
- The action to perform, create, delete, move, update, chmod
+ The action to perform, create, delete, move, update, chmod.
"""
action: CommitActionMode!
"""
- Content of the file
+ Content of the file.
"""
content: String
"""
- Encoding of the file. Default is text
+ Encoding of the file. Default is text.
"""
encoding: CommitEncoding
"""
- Enables/disables the execute flag on the file
+ Enables/disables the execute flag on the file.
"""
executeFilemode: Boolean
"""
- Full path to the file
+ Full path to the file.
"""
filePath: String!
"""
- Last known file commit ID
+ Last known file commit ID.
"""
lastCommitId: String
"""
- Original full path to the file being moved
+ Original full path to the file being moved.
"""
previousPath: String
}
@@ -3723,7 +3966,7 @@ input CommitCreateInput {
clientMutationId: String
"""
- Raw commit message
+ Raw commit message.
"""
message: String!
@@ -3790,24 +4033,30 @@ Represents a ComplianceFramework associated with a Project
"""
type ComplianceFramework {
"""
- Hexadecimal representation of compliance framework's label color
+ Hexadecimal representation of compliance framework's label color.
"""
color: String!
"""
- Description of the compliance framework
+ Description of the compliance framework.
"""
description: String!
"""
- Compliance framework ID
+ Compliance framework ID.
"""
id: ID!
"""
- Name of the compliance framework
+ Name of the compliance framework.
"""
name: String!
+
+ """
+ Full path of the compliance pipeline configuration stored in a project
+ repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hippa`.
+ """
+ pipelineConfigurationFullPath: String
}
"""
@@ -3860,14 +4109,35 @@ input ComplianceFrameworkInput {
New name for the compliance framework.
"""
name: String
+
+ """
+ Full path of the compliance pipeline configuration stored in a project
+ repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hippa`.
+ """
+ pipelineConfigurationFullPath: String
}
"""
-Identifier of ComplianceManagement::Framework
+Identifier of ComplianceManagement::Framework.
"""
scalar ComplianceManagementFrameworkID
"""
+Composer metadata
+"""
+type ComposerMetadata {
+ """
+ Data of the Composer JSON file.
+ """
+ composerJson: PackageComposerJsonType!
+
+ """
+ Target SHA of the package.
+ """
+ targetSha: String!
+}
+
+"""
Autogenerated input type of ConfigureSast
"""
input ConfigureSastInput {
@@ -3917,47 +4187,47 @@ A tag expiration policy designed to keep only the images that matter most
"""
type ContainerExpirationPolicy {
"""
- This container expiration policy schedule
+ This container expiration policy schedule.
"""
cadence: ContainerExpirationPolicyCadenceEnum!
"""
- Timestamp of when the container expiration policy was created
+ Timestamp of when the container expiration policy was created.
"""
createdAt: Time!
"""
- Indicates whether this container expiration policy is enabled
+ Indicates whether this container expiration policy is enabled.
"""
enabled: Boolean!
"""
- Number of tags to retain
+ Number of tags to retain.
"""
keepN: ContainerExpirationPolicyKeepEnum
"""
- Tags with names matching this regex pattern will expire
+ Tags with names matching this regex pattern will expire.
"""
nameRegex: UntrustedRegexp
"""
- Tags with names matching this regex pattern will be preserved
+ Tags with names matching this regex pattern will be preserved.
"""
nameRegexKeep: UntrustedRegexp
"""
- Next time that this container expiration policy will get executed
+ Next time that this container expiration policy will get executed.
"""
nextRunAt: Time
"""
- Tags older that this will expire
+ Tags older that this will expire.
"""
olderThan: ContainerExpirationPolicyOlderThanEnum
"""
- Timestamp of when the container expiration policy was updated
+ Timestamp of when the container expiration policy was updated.
"""
updatedAt: Time!
}
@@ -4088,7 +4358,7 @@ type ContainerRepository {
path: String!
"""
- Project of the container registry
+ Project of the container registry.
"""
project: Project!
@@ -4198,7 +4468,7 @@ type ContainerRepositoryDetails {
path: String!
"""
- Project of the container registry
+ Project of the container registry.
"""
project: Project!
@@ -4208,7 +4478,7 @@ type ContainerRepositoryDetails {
status: ContainerRepositoryStatus
"""
- Tags of the container repository
+ Tags of the container repository.
"""
tags(
"""
@@ -4259,11 +4529,66 @@ type ContainerRepositoryEdge {
}
"""
-Identifier of ContainerRepository
+Identifier of ContainerRepository.
"""
scalar ContainerRepositoryID
"""
+Values for sorting container repositories
+"""
+enum ContainerRepositorySort {
+ """
+ Created at ascending order
+ """
+ CREATED_ASC
+
+ """
+ Created at descending order
+ """
+ CREATED_DESC
+
+ """
+ Name by ascending order
+ """
+ NAME_ASC
+
+ """
+ Name by descending order
+ """
+ NAME_DESC
+
+ """
+ Updated at ascending order
+ """
+ UPDATED_ASC
+
+ """
+ Updated at descending order
+ """
+ UPDATED_DESC
+
+ """
+ Created at ascending order
+ """
+ created_asc @deprecated(reason: "Use CREATED_ASC. Deprecated in 13.5.")
+
+ """
+ Created at descending order
+ """
+ created_desc @deprecated(reason: "Use CREATED_DESC. Deprecated in 13.5.")
+
+ """
+ Updated at ascending order
+ """
+ updated_asc @deprecated(reason: "Use UPDATED_ASC. Deprecated in 13.5.")
+
+ """
+ Updated at descending order
+ """
+ updated_desc @deprecated(reason: "Use UPDATED_DESC. Deprecated in 13.5.")
+}
+
+"""
Status of a container repository
"""
enum ContainerRepositoryStatus {
@@ -4408,7 +4733,7 @@ type CreateAlertIssuePayload {
issue: Issue
"""
- The todo after mutation.
+ The to-do item after mutation.
"""
todo: Todo
}
@@ -4488,17 +4813,17 @@ input CreateBoardInput {
clientMutationId: String
"""
- The group full path the resource is associated with.
+ Full path of the group with which the resource is associated.
"""
groupPath: ID
"""
- Whether or not backlog list is hidden
+ Whether or not backlog list is hidden.
"""
hideBacklogList: Boolean
"""
- Whether or not closed list is hidden
+ Whether or not closed list is hidden.
"""
hideClosedList: Boolean
@@ -4513,7 +4838,7 @@ input CreateBoardInput {
labelIds: [LabelID!]
"""
- Labels of the issue
+ Labels of the issue.
"""
labels: [String!]
@@ -4528,7 +4853,7 @@ input CreateBoardInput {
name: String
"""
- The project full path the resource is associated with.
+ Full path of the project with which the resource is associated.
"""
projectPath: ID
@@ -4738,14 +5063,9 @@ input CreateDevopsAdoptionSegmentInput {
clientMutationId: String
"""
- The array of group IDs to set for the segment.
+ Namespace ID to set for the segment.
"""
- groupIds: [GroupID!]
-
- """
- Name of the segment.
- """
- name: String!
+ namespaceId: NamespaceID!
}
"""
@@ -4773,7 +5093,7 @@ Autogenerated input type of CreateDiffNote
"""
input CreateDiffNoteInput {
"""
- Content of the note
+ Content of the note.
"""
body: String!
@@ -4793,7 +5113,7 @@ input CreateDiffNoteInput {
noteableId: NoteableID!
"""
- The position of this note on a diff
+ The position of this note on a diff.
"""
position: DiffPositionInput!
}
@@ -4903,7 +5223,7 @@ Autogenerated input type of CreateImageDiffNote
"""
input CreateImageDiffNoteInput {
"""
- Content of the note
+ Content of the note.
"""
body: String!
@@ -4923,7 +5243,7 @@ input CreateImageDiffNoteInput {
noteableId: NoteableID!
"""
- The position of this note on a diff
+ The position of this note on a diff.
"""
position: DiffImagePositionInput!
}
@@ -4963,7 +5283,7 @@ input CreateIssueInput {
clientMutationId: String
"""
- Indicates the issue is confidential
+ Indicates the issue is confidential.
"""
confidential: Boolean
@@ -4973,7 +5293,7 @@ input CreateIssueInput {
createdAt: Time
"""
- Description of the issue
+ Description of the issue.
"""
description: String
@@ -4983,7 +5303,7 @@ input CreateIssueInput {
discussionToResolve: String
"""
- Due date of the issue
+ Due date of the issue.
"""
dueDate: ISO8601Date
@@ -5008,12 +5328,12 @@ input CreateIssueInput {
labelIds: [LabelID!]
"""
- Labels of the issue
+ Labels of the issue.
"""
labels: [String!]
"""
- Indicates discussion is locked on the issue
+ Indicates discussion is locked on the issue.
"""
locked: Boolean
@@ -5033,7 +5353,7 @@ input CreateIssueInput {
projectPath: ID!
"""
- Title of the issue
+ Title of the issue.
"""
title: String!
@@ -5083,12 +5403,12 @@ input CreateIterationInput {
dueDate: String
"""
- The target group for the iteration.
+ Full path of the group with which the resource is associated.
"""
groupPath: ID
"""
- The target project for the iteration.
+ Full path of the project with which the resource is associated.
"""
projectPath: ID
@@ -5128,7 +5448,7 @@ Autogenerated input type of CreateNote
"""
input CreateNoteInput {
"""
- Content of the note
+ Content of the note.
"""
body: String!
@@ -5228,6 +5548,13 @@ input CreateSnippetInput {
blobActions: [SnippetBlobActionInputType!]
"""
+ A 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".
+ """
+ captchaResponse: String
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -5243,6 +5570,13 @@ input CreateSnippetInput {
projectPath: ID
"""
+ The 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".
+ """
+ spamLogId: Int
+
+ """
Title of the snippet.
"""
title: String!
@@ -5263,6 +5597,13 @@ Autogenerated return type of CreateSnippet
"""
type CreateSnippetPayload {
"""
+ The 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.
+ """
+ captchaSiteKey: String
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -5273,14 +5614,31 @@ type CreateSnippetPayload {
errors: [String!]!
"""
+ 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.
+ """
+ needsCaptchaResponse: Boolean
+
+ """
The snippet after mutation.
"""
snippet: Snippet
"""
- Indicates whether the operation returns a record detected as spam.
+ Indicates whether the operation was detected as definite spam. There is no
+ option to resubmit the request with a CAPTCHA response.
"""
spam: Boolean
+
+ """
+ The 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.
+ """
+ spamLogId: Int
}
"""
@@ -5335,7 +5693,7 @@ type CreateTestCasePayload {
interface CurrentUserTodos {
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -5359,7 +5717,7 @@ interface CurrentUserTodos {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
@@ -5370,22 +5728,22 @@ A custom emoji uploaded by user
"""
type CustomEmoji {
"""
- Whether the emoji is an external link
+ Whether the emoji is an external link.
"""
external: Boolean!
"""
- The ID of the emoji
+ The ID of the emoji.
"""
id: CustomEmojiID!
"""
- The name of the emoji
+ The name of the emoji.
"""
name: String!
"""
- The link to file of the emoji
+ The link to file of the emoji.
"""
url: String!
}
@@ -5426,7 +5784,7 @@ type CustomEmojiEdge {
}
"""
-Identifier of CustomEmoji
+Identifier of CustomEmoji.
"""
scalar CustomEmojiID
@@ -5475,6 +5833,288 @@ type DastOnDemandScanCreatePayload {
pipelineUrl: String
}
+"""
+Represents a DAST Profile
+"""
+type DastProfile {
+ """
+ The associated scanner profile.
+ """
+ dastScannerProfile: DastScannerProfile
+
+ """
+ The associated site profile.
+ """
+ dastSiteProfile: DastSiteProfile
+
+ """
+ The description of the scan.
+ """
+ description: String
+
+ """
+ Relative web path to the edit page of a profile.
+ """
+ editPath: String
+
+ """
+ ID of the profile.
+ """
+ id: DastProfileID!
+
+ """
+ The name of the profile.
+ """
+ name: String
+}
+
+"""
+The connection type for DastProfile.
+"""
+type DastProfileConnection {
+ """
+ A list of edges.
+ """
+ edges: [DastProfileEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [DastProfile]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+Autogenerated input type of DastProfileCreate
+"""
+input DastProfileCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the scanner profile to be associated.
+ """
+ dastScannerProfileId: DastScannerProfileID!
+
+ """
+ ID of the site profile to be associated.
+ """
+ dastSiteProfileId: DastSiteProfileID!
+
+ """
+ The description of the profile. Defaults to an empty string.
+ """
+ description: String = ""
+
+ """
+ The project the profile belongs to.
+ """
+ fullPath: ID!
+
+ """
+ The name of the profile.
+ """
+ name: String!
+
+ """
+ Run scan using profile after creation. Defaults to false.
+ """
+ runAfterCreate: Boolean = false
+}
+
+"""
+Autogenerated return type of DastProfileCreate
+"""
+type DastProfileCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The created profile.
+ """
+ dastProfile: DastProfile
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The URL of the pipeline that was created. Requires `runAfterCreate` to be set to `true`.
+ """
+ pipelineUrl: String
+}
+
+"""
+Autogenerated input type of DastProfileDelete
+"""
+input DastProfileDeleteInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the profile to be deleted.
+ """
+ id: DastProfileID!
+}
+
+"""
+Autogenerated return type of DastProfileDelete
+"""
+type DastProfileDeletePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
+An edge in a connection.
+"""
+type DastProfileEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: DastProfile
+}
+
+"""
+Identifier of Dast::Profile.
+"""
+scalar DastProfileID
+
+"""
+Autogenerated input type of DastProfileRun
+"""
+input DastProfileRunInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Full path for the project the scanner profile belongs to.
+ """
+ fullPath: ID!
+
+ """
+ ID of the profile to be used for the scan.
+ """
+ id: DastProfileID!
+}
+
+"""
+Autogenerated return type of DastProfileRun
+"""
+type DastProfileRunPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ URL of the pipeline that was created.
+ """
+ pipelineUrl: String
+}
+
+"""
+Autogenerated input type of DastProfileUpdate
+"""
+input DastProfileUpdateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the scanner profile to be associated.
+ """
+ dastScannerProfileId: DastScannerProfileID
+
+ """
+ ID of the site profile to be associated.
+ """
+ dastSiteProfileId: DastSiteProfileID
+
+ """
+ The description of the profile. Defaults to an empty string.
+ """
+ description: String = ""
+
+ """
+ The project the profile belongs to.
+ """
+ fullPath: ID!
+
+ """
+ ID of the profile to be deleted.
+ """
+ id: DastProfileID!
+
+ """
+ The name of the profile.
+ """
+ name: String
+
+ """
+ Run scan using profile after update. Defaults to false.
+ """
+ runAfterUpdate: Boolean = false
+}
+
+"""
+Autogenerated return type of DastProfileUpdate
+"""
+type DastProfileUpdatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The updated profile.
+ """
+ dastProfile: DastProfile
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The URL of the pipeline that was created. Requires the input argument
+ `runAfterUpdate` to be set to `true` when calling the mutation, otherwise no
+ pipeline will be created.
+ """
+ pipelineUrl: String
+}
+
enum DastScanTypeEnum {
"""
Active DAST scan. This scan will make active attacks against the target site.
@@ -5492,22 +6132,22 @@ Represents a DAST scanner profile
"""
type DastScannerProfile {
"""
- Relative web path to the edit page of a scanner profile
+ Relative web path to the edit page of a scanner profile.
"""
editPath: String
"""
- ID of the DAST scanner profile Deprecated in 13.6: Use `id`.
+ ID of the DAST scanner profile. Deprecated in 13.6: Use `id`.
"""
globalId: DastScannerProfileID! @deprecated(reason: "Use `id`. Deprecated in 13.6.")
"""
- ID of the DAST scanner profile
+ ID of the DAST scanner profile.
"""
id: DastScannerProfileID!
"""
- Name of the DAST scanner profile
+ Name of the DAST scanner profile.
"""
profileName: String
@@ -5522,12 +6162,12 @@ type DastScannerProfile {
showDebugMessages: Boolean!
"""
- The maximum number of minutes allowed for the spider to traverse the site
+ The maximum number of minutes allowed for the spider to traverse the site.
"""
spiderTimeout: Int
"""
- The maximum number of seconds allowed for the site under test to respond to a request
+ The maximum number of seconds allowed for the site under test to respond to a request.
"""
targetTimeout: Int
@@ -5682,7 +6322,7 @@ type DastScannerProfileEdge {
}
"""
-Identifier of DastScannerProfile
+Identifier of DastScannerProfile.
"""
scalar DastScannerProfileID
@@ -5763,27 +6403,27 @@ Represents a DAST Site Profile
"""
type DastSiteProfile {
"""
- Relative web path to the edit page of a site profile
+ Relative web path to the edit page of a site profile.
"""
editPath: String
"""
- ID of the site profile
+ ID of the site profile.
"""
id: DastSiteProfileID!
"""
- Normalized URL of the target to be scanned
+ Normalized URL of the target to be scanned.
"""
normalizedTargetUrl: String
"""
- The name of the site profile
+ The name of the site profile.
"""
profileName: String
"""
- The URL of the target to be scanned
+ The URL of the target to be scanned.
"""
targetUrl: String
@@ -5793,7 +6433,7 @@ type DastSiteProfile {
userPermissions: DastSiteProfilePermissions!
"""
- The current validation status of the site profile
+ The current validation status of the site profile.
"""
validationStatus: DastSiteProfileValidationStatusEnum
}
@@ -5914,7 +6554,7 @@ type DastSiteProfileEdge {
}
"""
-Identifier of DastSiteProfile
+Identifier of DastSiteProfile.
"""
scalar DastSiteProfileID
@@ -6056,7 +6696,7 @@ type DastSiteTokenCreatePayload {
}
"""
-Identifier of DastSiteToken
+Identifier of DastSiteToken.
"""
scalar DastSiteTokenID
@@ -6065,17 +6705,17 @@ Represents a DAST Site Validation
"""
type DastSiteValidation {
"""
- Global ID of the site validation
+ Global ID of the site validation.
"""
id: DastSiteValidationID!
"""
- Normalized URL of the target to be validated
+ Normalized URL of the target to be validated.
"""
normalizedTargetUrl: String
"""
- Status of the site validation
+ Status of the site validation.
"""
status: DastSiteProfileValidationStatusEnum!
}
@@ -6171,10 +6811,45 @@ type DastSiteValidationEdge {
}
"""
-Identifier of DastSiteValidation
+Identifier of DastSiteValidation.
"""
scalar DastSiteValidationID
+"""
+Autogenerated input type of DastSiteValidationRevoke
+"""
+input DastSiteValidationRevokeInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The project the site validation belongs to.
+ """
+ fullPath: ID!
+
+ """
+ Normalized URL of the target to be revoked.
+ """
+ normalizedTargetUrl: String!
+}
+
+"""
+Autogenerated return type of DastSiteValidationRevoke
+"""
+type DastSiteValidationRevokePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
enum DastSiteValidationStrategyEnum {
"""
Header validation
@@ -6347,17 +7022,17 @@ The response from the AdminSidekiqQueuesDeleteJobs mutation
"""
type DeleteJobsResponse {
"""
- Whether or not the entire queue was processed in time; if not, retrying the same request is safe
+ Whether or not the entire queue was processed in time; if not, retrying the same request is safe.
"""
completed: Boolean
"""
- The number of matching jobs deleted
+ The number of matching jobs deleted.
"""
deletedJobs: Int
"""
- The queue size after processing
+ The queue size after processing.
"""
queueSize: Int
}
@@ -6367,7 +7042,7 @@ A single design
"""
type Design implements CurrentUserTodos & DesignFields & Noteable {
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -6391,18 +7066,18 @@ type Design implements CurrentUserTodos & DesignFields & Noteable {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
"""
- The diff refs for this design
+ The diff refs for this design.
"""
diffRefs: DiffRefs!
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -6427,27 +7102,27 @@ type Design implements CurrentUserTodos & DesignFields & Noteable {
): DiscussionConnection!
"""
- How this design was changed in the current version
+ How this design was changed in the current version.
"""
event: DesignVersionEvent!
"""
- The filename of the design
+ The filename of the design.
"""
filename: String!
"""
- The full path to the design file
+ The full path to the design file.
"""
fullPath: String!
"""
- The ID of this design
+ The ID of this design.
"""
id: ID!
"""
- The URL of the full-sized image
+ The URL of the full-sized image.
"""
image: String!
@@ -6457,12 +7132,12 @@ type Design implements CurrentUserTodos & DesignFields & Noteable {
imageV432x230: String
"""
- The issue the design belongs to
+ The issue the design belongs to.
"""
issue: Issue!
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -6487,17 +7162,17 @@ type Design implements CurrentUserTodos & DesignFields & Noteable {
): NoteConnection!
"""
- The total count of user-created notes for this design
+ The total count of user-created notes for this design.
"""
notesCount: Int!
"""
- The project the design belongs to
+ The project the design belongs to.
"""
project: Project!
"""
- All versions related to this design ordered newest first
+ All versions related to this design ordered newest first.
"""
versions(
"""
@@ -6537,37 +7212,37 @@ A design pinned to a specific version. The image field reflects the design as of
"""
type DesignAtVersion implements DesignFields {
"""
- The underlying design
+ The underlying design.
"""
design: Design!
"""
- The diff refs for this design
+ The diff refs for this design.
"""
diffRefs: DiffRefs!
"""
- How this design was changed in the current version
+ How this design was changed in the current version.
"""
event: DesignVersionEvent!
"""
- The filename of the design
+ The filename of the design.
"""
filename: String!
"""
- The full path to the design file
+ The full path to the design file.
"""
fullPath: String!
"""
- The ID of this design
+ The ID of this design.
"""
id: ID!
"""
- The URL of the full-sized image
+ The URL of the full-sized image.
"""
image: String!
@@ -6577,22 +7252,22 @@ type DesignAtVersion implements DesignFields {
imageV432x230: String
"""
- The issue the design belongs to
+ The issue the design belongs to.
"""
issue: Issue!
"""
- The total count of user-created notes for this design
+ The total count of user-created notes for this design.
"""
notesCount: Int!
"""
- The project the design belongs to
+ The project the design belongs to.
"""
project: Project!
"""
- The version this design-at-versions is pinned to
+ The version this design-at-versions is pinned to.
"""
version: DesignVersion!
}
@@ -6637,12 +7312,12 @@ A collection of designs
"""
type DesignCollection {
"""
- Copy state of the design collection
+ Copy state of the design collection.
"""
copyState: DesignCollectionCopyState
"""
- Find a specific design
+ Find a specific design.
"""
design(
"""
@@ -6657,7 +7332,7 @@ type DesignCollection {
): Design
"""
- Find a design as of a version
+ Find a design as of a version.
"""
designAtVersion(
"""
@@ -6667,7 +7342,7 @@ type DesignCollection {
): DesignAtVersion
"""
- All designs for the design collection
+ All designs for the design collection.
"""
designs(
"""
@@ -6708,17 +7383,17 @@ type DesignCollection {
): DesignConnection!
"""
- Issue associated with the design collection
+ Issue associated with the design collection.
"""
issue: Issue!
"""
- Project associated with the design collection
+ Project associated with the design collection.
"""
project: Project!
"""
- A specific version
+ A specific version.
"""
version(
"""
@@ -6733,7 +7408,7 @@ type DesignCollection {
): DesignVersion
"""
- All versions related to all designs, ordered newest first
+ All versions related to all designs, ordered newest first.
"""
versions(
"""
@@ -6825,32 +7500,32 @@ type DesignEdge {
interface DesignFields {
"""
- The diff refs for this design
+ The diff refs for this design.
"""
diffRefs: DiffRefs!
"""
- How this design was changed in the current version
+ How this design was changed in the current version.
"""
event: DesignVersionEvent!
"""
- The filename of the design
+ The filename of the design.
"""
filename: String!
"""
- The full path to the design file
+ The full path to the design file.
"""
fullPath: String!
"""
- The ID of this design
+ The ID of this design.
"""
id: ID!
"""
- The URL of the full-sized image
+ The URL of the full-sized image.
"""
image: String!
@@ -6860,24 +7535,24 @@ interface DesignFields {
imageV432x230: String
"""
- The issue the design belongs to
+ The issue the design belongs to.
"""
issue: Issue!
"""
- The total count of user-created notes for this design
+ The total count of user-created notes for this design.
"""
notesCount: Int!
"""
- The project the design belongs to
+ The project the design belongs to.
"""
project: Project!
}
type DesignManagement {
"""
- Find a design as of a version
+ Find a design as of a version.
"""
designAtVersion(
"""
@@ -6887,7 +7562,7 @@ type DesignManagement {
): DesignAtVersion
"""
- Find a version
+ Find a version.
"""
version(
"""
@@ -6943,12 +7618,12 @@ type DesignManagementDeletePayload {
}
"""
-Identifier of DesignManagement::DesignAtVersion
+Identifier of DesignManagement::DesignAtVersion.
"""
scalar DesignManagementDesignAtVersionID
"""
-Identifier of DesignManagement::Design
+Identifier of DesignManagement::Design.
"""
scalar DesignManagementDesignID
@@ -7048,7 +7723,7 @@ type DesignManagementUploadPayload {
}
"""
-Identifier of DesignManagement::Version
+Identifier of DesignManagement::Version.
"""
scalar DesignManagementVersionID
@@ -7057,7 +7732,7 @@ A specific version in which designs were added, modified or deleted
"""
type DesignVersion {
"""
- A particular design as of this version, provided it is visible at this version
+ A particular design as of this version, provided it is visible at this version.
"""
designAtVersion(
"""
@@ -7077,7 +7752,7 @@ type DesignVersion {
): DesignAtVersion!
"""
- All designs that were changed in the version
+ All designs that were changed in the version.
"""
designs(
"""
@@ -7102,7 +7777,7 @@ type DesignVersion {
): DesignConnection!
"""
- All designs that are visible at this version, as of this version
+ All designs that are visible at this version, as of this version.
"""
designsAtVersion(
"""
@@ -7137,12 +7812,12 @@ type DesignVersion {
): DesignAtVersionConnection!
"""
- ID of the design version
+ ID of the design version.
"""
id: ID!
"""
- SHA of the design version
+ SHA of the design version.
"""
sha: ID!
}
@@ -7454,47 +8129,47 @@ type DestroySnippetPayload {
type DetailedStatus {
"""
- Action information for the status. This includes method, button title, icon, path, and title
+ Action information for the status. This includes method, button title, icon, path, and title.
"""
action: StatusAction
"""
- Path of the details for the status
+ Path of the details for the status.
"""
detailsPath: String
"""
- Favicon of the status
+ Favicon of the status.
"""
favicon: String
"""
- Group of the status
+ Group of the status.
"""
group: String
"""
- Indicates if the status has further details
+ Indicates if the status has further details.
"""
hasDetails: Boolean
"""
- Icon of the status
+ Icon of the status.
"""
icon: String
"""
- Label of the status
+ Label of the status.
"""
label: String
"""
- Text of the status
+ Text of the status.
"""
text: String
"""
- Tooltip associated with the status
+ Tooltip associated with the status.
"""
tooltip: String
}
@@ -7504,24 +8179,19 @@ Segment
"""
type DevopsAdoptionSegment {
"""
- Assigned groups
- """
- groups: [Group!]
-
- """
- ID of the segment
+ ID of the segment.
"""
id: ID!
"""
- The latest adoption metrics for the segment
+ The latest adoption metrics for the segment.
"""
latestSnapshot: DevopsAdoptionSnapshot
"""
- Name of the segment
+ Segment namespace.
"""
- name: String!
+ namespace: Namespace
}
"""
@@ -7564,69 +8234,69 @@ Snapshot
"""
type DevopsAdoptionSnapshot {
"""
- At least one deployment succeeded
+ At least one deployment succeeded.
"""
deploySucceeded: Boolean!
"""
- The end time for the snapshot where the data points were collected
+ The end time for the snapshot where the data points were collected.
"""
endTime: Time!
"""
- At least one issue was opened
+ At least one issue was opened.
"""
issueOpened: Boolean!
"""
- At least one merge request was approved
+ At least one merge request was approved.
"""
mergeRequestApproved: Boolean!
"""
- At least one merge request was opened
+ At least one merge request was opened.
"""
mergeRequestOpened: Boolean!
"""
- At least one pipeline succeeded
+ At least one pipeline succeeded.
"""
pipelineSucceeded: Boolean!
"""
- The time the snapshot was recorded
+ The time the snapshot was recorded.
"""
recordedAt: Time!
"""
- At least one runner was used
+ At least one runner was used.
"""
runnerConfigured: Boolean!
"""
- At least one security scan succeeded
+ At least one security scan succeeded.
"""
securityScanSucceeded: Boolean!
"""
- The start time for the snapshot where the data points were collected
+ The start time for the snapshot where the data points were collected.
"""
startTime: Time!
}
input DiffImagePositionInput {
"""
- Merge base of the branch the comment was made on
+ Merge base of the branch the comment was made on.
"""
baseSha: String
"""
- SHA of the HEAD at the time the comment was made
+ SHA of the HEAD at the time the comment was made.
"""
headSha: String!
"""
- Total height of the image
+ Total height of the image.
"""
height: Int!
@@ -7637,118 +8307,118 @@ input DiffImagePositionInput {
paths: DiffPathsInput!
"""
- SHA of the branch being compared against
+ SHA of the branch being compared against.
"""
startSha: String!
"""
- Total width of the image
+ Total width of the image.
"""
width: Int!
"""
- X position of the note
+ X position of the note.
"""
x: Int!
"""
- Y position of the note
+ Y position of the note.
"""
y: Int!
}
"""
-Identifier of DiffNote
+Identifier of DiffNote.
"""
scalar DiffNoteID
input DiffPathsInput {
"""
- The path of the file on the head sha
+ The path of the file on the head sha.
"""
newPath: String
"""
- The path of the file on the start sha
+ The path of the file on the start sha.
"""
oldPath: String
}
type DiffPosition {
"""
- Information about the branch, HEAD, and base at the time of commenting
+ Information about the branch, HEAD, and base at the time of commenting.
"""
diffRefs: DiffRefs!
"""
- Path of the file that was changed
+ Path of the file that was changed.
"""
filePath: String!
"""
- Total height of the image
+ Total height of the image.
"""
height: Int
"""
- Line on HEAD SHA that was changed
+ Line on HEAD SHA that was changed.
"""
newLine: Int
"""
- Path of the file on the HEAD SHA
+ Path of the file on the HEAD SHA.
"""
newPath: String
"""
- Line on start SHA that was changed
+ Line on start SHA that was changed.
"""
oldLine: Int
"""
- Path of the file on the start SHA
+ Path of the file on the start SHA.
"""
oldPath: String
"""
- Type of file the position refers to
+ Type of file the position refers to.
"""
positionType: DiffPositionType!
"""
- Total width of the image
+ Total width of the image.
"""
width: Int
"""
- X position of the note
+ X position of the note.
"""
x: Int
"""
- Y position of the note
+ Y position of the note.
"""
y: Int
}
input DiffPositionInput {
"""
- Merge base of the branch the comment was made on
+ Merge base of the branch the comment was made on.
"""
baseSha: String
"""
- SHA of the HEAD at the time the comment was made
+ SHA of the HEAD at the time the comment was made.
"""
headSha: String!
"""
- Line on HEAD SHA that was changed
+ Line on HEAD SHA that was changed.
"""
newLine: Int!
"""
- Line on start SHA that was changed
+ Line on start SHA that was changed.
"""
oldLine: Int
@@ -7759,7 +8429,7 @@ input DiffPositionInput {
paths: DiffPathsInput!
"""
- SHA of the branch being compared against
+ SHA of the branch being compared against.
"""
startSha: String!
}
@@ -7774,17 +8444,17 @@ enum DiffPositionType {
type DiffRefs {
"""
- Merge base of the branch the comment was made on
+ Merge base of the branch the comment was made on.
"""
baseSha: String
"""
- SHA of the HEAD at the time the comment was made
+ SHA of the HEAD at the time the comment was made.
"""
headSha: String!
"""
- SHA of the branch being compared against
+ SHA of the branch being compared against.
"""
startSha: String!
}
@@ -7794,17 +8464,17 @@ Changes to a single file
"""
type DiffStats {
"""
- Number of lines added to this file
+ Number of lines added to this file.
"""
additions: Int!
"""
- Number of lines deleted from this file
+ Number of lines deleted from this file.
"""
deletions: Int!
"""
- File path, relative to repository root
+ File path, relative to repository root.
"""
path: String!
}
@@ -7814,39 +8484,39 @@ Aggregated summary of changes
"""
type DiffStatsSummary {
"""
- Number of lines added
+ Number of lines added.
"""
additions: Int!
"""
- Number of lines changed
+ Number of lines changed.
"""
changes: Int!
"""
- Number of lines deleted
+ Number of lines deleted.
"""
deletions: Int!
"""
- Number of files changed
+ Number of files changed.
"""
fileCount: Int!
}
type Discussion implements ResolvableInterface {
"""
- Timestamp of the discussion's creation
+ Timestamp of the discussion's creation.
"""
createdAt: Time!
"""
- ID of this discussion
+ ID of this discussion.
"""
- id: ID!
+ id: DiscussionID!
"""
- All notes in the discussion
+ All notes in the discussion.
"""
notes(
"""
@@ -7871,27 +8541,27 @@ type Discussion implements ResolvableInterface {
): NoteConnection!
"""
- ID used to reply to this discussion
+ ID used to reply to this discussion.
"""
- replyId: ID!
+ replyId: DiscussionID!
"""
- Indicates if the object can be resolved
+ Indicates if the object can be resolved.
"""
resolvable: Boolean!
"""
- Indicates if the object is resolved
+ Indicates if the object is resolved.
"""
resolved: Boolean!
"""
- Timestamp of when the object was resolved
+ Timestamp of when the object was resolved.
"""
resolvedAt: Time
"""
- User who resolved the object
+ User who resolved the object.
"""
resolvedBy: User
}
@@ -7932,7 +8602,7 @@ type DiscussionEdge {
}
"""
-Identifier of Discussion
+Identifier of Discussion.
"""
scalar DiscussionID
@@ -8023,32 +8693,32 @@ type DismissVulnerabilityPayload {
interface Entry {
"""
- Flat path of the entry
+ Flat path of the entry.
"""
flatPath: String!
"""
- ID of the entry
+ ID of the entry.
"""
id: ID!
"""
- Name of the entry
+ Name of the entry.
"""
name: String!
"""
- Path of the entry
+ Path of the entry.
"""
path: String!
"""
- Last commit sha for the entry
+ Last commit SHA for the entry.
"""
sha: String!
"""
- Type of tree entry
+ Type of tree entry.
"""
type: EntryType!
}
@@ -8067,17 +8737,17 @@ Describes where code is deployed for a project
"""
type Environment {
"""
- ID of the environment
+ ID of the environment.
"""
id: ID!
"""
- The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned
+ The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned.
"""
latestOpenedMostSevereAlert: AlertManagementAlert
"""
- Metrics dashboard schema for the environment
+ Metrics dashboard schema for the environment.
"""
metricsDashboard(
"""
@@ -8087,7 +8757,7 @@ type Environment {
): MetricsDashboard
"""
- Human-readable name of the environment
+ Human-readable name of the environment.
"""
name: String!
@@ -8097,7 +8767,7 @@ type Environment {
path: String!
"""
- State of the environment, for example: available/stopped
+ State of the environment, for example: available/stopped.
"""
state: String!
}
@@ -8138,7 +8808,7 @@ type EnvironmentEdge {
}
"""
-Identifier of Environment
+Identifier of Environment.
"""
scalar EnvironmentID
@@ -8180,14 +8850,39 @@ type EnvironmentsCanaryIngressUpdatePayload {
"""
Represents an epic
"""
-type Epic implements CurrentUserTodos & Noteable {
+type Epic implements CurrentUserTodos & Eventable & Noteable {
"""
- Author of the epic
+ Author of the epic.
"""
author: User!
"""
- Children (sub-epics) of the epic
+ A list of award emojis associated with the epic.
+ """
+ awardEmoji(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): AwardEmojiConnection
+
+ """
+ Children (sub-epics) of the epic.
"""
children(
"""
@@ -8285,22 +8980,22 @@ type Epic implements CurrentUserTodos & Noteable {
): EpicConnection
"""
- Timestamp of when the epic was closed
+ Timestamp of when the epic was closed.
"""
closedAt: Time
"""
- Indicates if the epic is confidential
+ Indicates if the epic is confidential.
"""
confidential: Boolean
"""
- Timestamp of when the epic was created
+ Timestamp of when the epic was created.
"""
createdAt: Time
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -8324,28 +9019,28 @@ type Epic implements CurrentUserTodos & Noteable {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
"""
- Number of open and closed descendant epics and issues
+ Number of open and closed descendant epics and issues.
"""
descendantCounts: EpicDescendantCount
"""
- Total weight of open and closed issues in the epic and its descendants
+ Total weight of open and closed issues in the epic and its descendants.
"""
descendantWeightSum: EpicDescendantWeights
"""
- Description of the epic
+ Description of the epic.
"""
description: String
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -8370,67 +9065,92 @@ type Epic implements CurrentUserTodos & Noteable {
): DiscussionConnection!
"""
- Number of downvotes the epic has received
+ Number of downvotes the epic has received.
"""
downvotes: Int!
"""
- Due date of the epic
+ Due date of the epic.
"""
dueDate: Time
"""
- Fixed due date of the epic
+ Fixed due date of the epic.
"""
dueDateFixed: Time
"""
- Inherited due date of the epic from milestones
+ Inherited due date of the epic from milestones.
"""
dueDateFromMilestones: Time
"""
- Indicates if the due date has been manually set
+ Indicates if the due date has been manually set.
"""
dueDateIsFixed: Boolean
"""
- Group to which the epic belongs
+ A list of events associated with the object.
+ """
+ events(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EventConnection
+
+ """
+ Group to which the epic belongs.
"""
group: Group!
"""
- Indicates if the epic has children
+ Indicates if the epic has children.
"""
hasChildren: Boolean!
"""
- Indicates if the epic has direct issues
+ Indicates if the epic has direct issues.
"""
hasIssues: Boolean!
"""
- Indicates if the epic has a parent epic
+ Indicates if the epic has a parent epic.
"""
hasParent: Boolean!
"""
- Current health status of the epic
+ Current health status of the epic.
"""
healthStatus: EpicHealthStatus
"""
- ID of the epic
+ ID of the epic.
"""
id: ID!
"""
- Internal ID of the epic
+ Internal ID of the epic.
"""
iid: ID!
"""
- A list of issues associated with the epic
+ A list of issues associated with the epic.
"""
issues(
"""
@@ -8455,7 +9175,7 @@ type Epic implements CurrentUserTodos & Noteable {
): EpicIssueConnection
"""
- Labels assigned to the epic
+ Labels assigned to the epic.
"""
labels(
"""
@@ -8480,7 +9200,7 @@ type Epic implements CurrentUserTodos & Noteable {
): LabelConnection
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -8505,12 +9225,12 @@ type Epic implements CurrentUserTodos & Noteable {
): NoteConnection!
"""
- Parent epic of the epic
+ Parent epic of the epic.
"""
parent: Epic
"""
- List of participants for the epic
+ List of participants for the epic.
"""
participants(
"""
@@ -8535,77 +9255,77 @@ type Epic implements CurrentUserTodos & Noteable {
): UserConnection
"""
- Internal reference of the epic. Returned in shortened format by default
+ Internal reference of the epic. Returned in shortened format by default.
"""
reference(
"""
- Indicates if the reference should be returned in full
+ Indicates if the reference should be returned in full.
"""
full: Boolean = false
): String!
"""
- URI path of the epic-issue relationship
+ URI path of the epic-issue relationship.
"""
relationPath: String
"""
- The relative position of the epic in the epic tree
+ The relative position of the epic in the epic tree.
"""
relativePosition: Int
"""
- Start date of the epic
+ Start date of the epic.
"""
startDate: Time
"""
- Fixed start date of the epic
+ Fixed start date of the epic.
"""
startDateFixed: Time
"""
- Inherited start date of the epic from milestones
+ Inherited start date of the epic from milestones.
"""
startDateFromMilestones: Time
"""
- Indicates if the start date has been manually set
+ Indicates if the start date has been manually set.
"""
startDateIsFixed: Boolean
"""
- State of the epic
+ State of the epic.
"""
state: EpicState!
"""
- Indicates the currently logged in user is subscribed to the epic
+ Indicates the currently logged in user is subscribed to the epic.
"""
subscribed: Boolean!
"""
- Title of the epic
+ Title of the epic.
"""
title: String
"""
- Timestamp of when the epic was updated
+ Timestamp of when the epic was updated.
"""
updatedAt: Time
"""
- Number of upvotes the epic has received
+ Number of upvotes the epic has received.
"""
upvotes: Int!
"""
- Number of user discussions in the epic
+ Number of user discussions in the epic.
"""
userDiscussionsCount: Int!
"""
- Number of user notes of the epic
+ Number of user notes of the epic.
"""
userNotesCount: Int!
@@ -8615,12 +9335,12 @@ type Epic implements CurrentUserTodos & Noteable {
userPermissions: EpicPermissions!
"""
- Web path of the epic
+ Web path of the epic.
"""
webPath: String!
"""
- Web URL of the epic
+ Web URL of the epic.
"""
webUrl: String!
}
@@ -8746,6 +9466,56 @@ type EpicBoardConnection {
}
"""
+Autogenerated input type of EpicBoardCreate
+"""
+input EpicBoardCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Full path of the group with which the resource is associated.
+ """
+ groupPath: ID
+
+ """
+ Whether or not backlog list is hidden.
+ """
+ hideBacklogList: Boolean
+
+ """
+ Whether or not closed list is hidden.
+ """
+ hideClosedList: Boolean
+
+ """
+ The board name.
+ """
+ name: String
+}
+
+"""
+Autogenerated return type of EpicBoardCreate
+"""
+type EpicBoardCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The created epic board.
+ """
+ epicBoard: EpicBoard
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
An edge in a connection.
"""
type EpicBoardEdge {
@@ -8761,6 +9531,51 @@ type EpicBoardEdge {
}
"""
+Autogenerated input type of EpicBoardListCreate
+"""
+input EpicBoardListCreateInput {
+ """
+ Create the backlog list.
+ """
+ backlog: Boolean
+
+ """
+ Global ID of the issue board to mutate.
+ """
+ boardId: BoardsEpicBoardID!
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global ID of an existing label.
+ """
+ labelId: LabelID
+}
+
+"""
+Autogenerated return type of EpicBoardListCreate
+"""
+type EpicBoardListCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ Epic list in the epic board.
+ """
+ list: EpicList
+}
+
+"""
The connection type for Epic.
"""
type EpicConnection {
@@ -8785,22 +9600,22 @@ Counts of descendent epics
"""
type EpicDescendantCount {
"""
- Number of closed child epics
+ Number of closed child epics.
"""
closedEpics: Int
"""
- Number of closed epic issues
+ Number of closed epic issues.
"""
closedIssues: Int
"""
- Number of opened child epics
+ Number of opened child epics.
"""
openedEpics: Int
"""
- Number of opened epic issues
+ Number of opened epic issues.
"""
openedIssues: Int
}
@@ -8810,12 +9625,12 @@ Total weight of open and closed descendant issues
"""
type EpicDescendantWeights {
"""
- Total weight of completed (closed) issues in this epic, including epic descendants
+ Total weight of completed (closed) issues in this epic, including epic descendants.
"""
closedIssues: Int
"""
- Total weight of opened issues in this epic, including epic descendants
+ Total weight of opened issues in this epic, including epic descendants.
"""
openedIssues: Int
}
@@ -8840,23 +9655,23 @@ Health status of child issues
"""
type EpicHealthStatus {
"""
- Number of issues at risk
+ Number of issues at risk.
"""
issuesAtRisk: Int
"""
- Number of issues that need attention
+ Number of issues that need attention.
"""
issuesNeedingAttention: Int
"""
- Number of issues on track
+ Number of issues on track.
"""
issuesOnTrack: Int
}
"""
-Identifier of Epic
+Identifier of Epic.
"""
scalar EpicID
@@ -8865,12 +9680,12 @@ Relationship between an epic and an issue
"""
type EpicIssue implements CurrentUserTodos & Noteable {
"""
- Alert associated to this issue
+ Alert associated to this issue.
"""
alertManagementAlert: AlertManagementAlert
"""
- Assignees of the issue
+ Assignees of the issue.
"""
assignees(
"""
@@ -8895,7 +9710,7 @@ type EpicIssue implements CurrentUserTodos & Noteable {
): UserConnection
"""
- User that created the issue
+ User that created the issue.
"""
author: User!
@@ -8910,27 +9725,27 @@ type EpicIssue implements CurrentUserTodos & Noteable {
blockedByCount: Int
"""
- Timestamp of when the issue was closed
+ Timestamp of when the issue was closed.
"""
closedAt: Time
"""
- Indicates the issue is confidential
+ Indicates the issue is confidential.
"""
confidential: Boolean!
"""
- User specific email address for the issue
+ User specific email address for the issue.
"""
createNoteEmail: String
"""
- Timestamp of when the issue was created
+ Timestamp of when the issue was created.
"""
createdAt: Time!
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -8954,13 +9769,13 @@ type EpicIssue implements CurrentUserTodos & Noteable {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
"""
- Description of the issue
+ Description of the issue.
"""
description: String
@@ -8970,17 +9785,17 @@ type EpicIssue implements CurrentUserTodos & Noteable {
descriptionHtml: String
"""
- Collection of design images associated with this issue
+ Collection of design images associated with this issue.
"""
designCollection: DesignCollection
"""
- Indicates discussion is locked on the issue
+ Indicates discussion is locked on the issue.
"""
discussionLocked: Boolean!
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -9005,17 +9820,17 @@ type EpicIssue implements CurrentUserTodos & Noteable {
): DiscussionConnection!
"""
- Number of downvotes the issue has received
+ Number of downvotes the issue has received.
"""
downvotes: Int!
"""
- Due date of the issue
+ Due date of the issue.
"""
dueDate: Time
"""
- Indicates if a project has email notifications disabled: `true` if email notifications are disabled
+ Indicates if a project has email notifications disabled: `true` if email notifications are disabled.
"""
emailsDisabled: Boolean!
@@ -9025,7 +9840,7 @@ type EpicIssue implements CurrentUserTodos & Noteable {
epic: Epic
"""
- ID of the epic-issue relation
+ ID of the epic-issue relation.
"""
epicIssueId: ID!
@@ -9035,22 +9850,22 @@ type EpicIssue implements CurrentUserTodos & Noteable {
healthStatus: HealthStatus
"""
- Human-readable time estimate of the issue
+ Human-readable time estimate of the issue.
"""
humanTimeEstimate: String
"""
- Human-readable total time reported as spent on the issue
+ Human-readable total time reported as spent on the issue.
"""
humanTotalTimeSpent: String
"""
- Global ID of the epic-issue relation
+ Global ID of the epic-issue relation.
"""
id: ID
"""
- Internal ID of the issue
+ Internal ID of the issue.
"""
iid: ID!
@@ -9060,7 +9875,7 @@ type EpicIssue implements CurrentUserTodos & Noteable {
iteration: Iteration
"""
- Labels of the issue
+ Labels of the issue.
"""
labels(
"""
@@ -9090,22 +9905,22 @@ type EpicIssue implements CurrentUserTodos & Noteable {
metricImages: [MetricImage!]
"""
- Milestone of the issue
+ Milestone of the issue.
"""
milestone: Milestone
"""
- Indicates if issue got moved from other project
+ Indicates if issue got moved from other project.
"""
moved: Boolean
"""
- Updated Issue after it got moved to another project
+ Updated Issue after it got moved to another project.
"""
movedTo: Issue
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -9130,7 +9945,7 @@ type EpicIssue implements CurrentUserTodos & Noteable {
): NoteConnection!
"""
- List of participants in the issue
+ List of participants in the issue.
"""
participants(
"""
@@ -9155,27 +9970,27 @@ type EpicIssue implements CurrentUserTodos & Noteable {
): UserConnection
"""
- Internal reference of the issue. Returned in shortened format by default
+ Internal reference of the issue. Returned in shortened format by default.
"""
reference(
"""
- Boolean option specifying whether the reference should be returned in full
+ Boolean option specifying whether the reference should be returned in full.
"""
full: Boolean = false
): String!
"""
- URI path of the epic-issue relation
+ URI path of the epic-issue relation.
"""
relationPath: String
"""
- Relative position of the issue (used for positioning in epic tree and issue boards)
+ Relative position of the issue (used for positioning in epic tree and issue boards).
"""
relativePosition: Int
"""
- Severity level of the incident
+ Severity level of the incident.
"""
severity: IssuableSeverity
@@ -9185,7 +10000,7 @@ type EpicIssue implements CurrentUserTodos & Noteable {
slaDueAt: Time
"""
- State of the issue
+ State of the issue.
"""
state: IssueState!
@@ -9195,22 +10010,22 @@ type EpicIssue implements CurrentUserTodos & Noteable {
statusPagePublishedIncident: Boolean
"""
- Indicates the currently logged in user is subscribed to the issue
+ Indicates the currently logged in user is subscribed to the issue.
"""
subscribed: Boolean!
"""
- Task completion status of the issue
+ Task completion status of the issue.
"""
taskCompletionStatus: TaskCompletionStatus!
"""
- Time estimate of the issue
+ Time estimate of the issue.
"""
timeEstimate: Int!
"""
- Title of the issue
+ Title of the issue.
"""
title: String!
@@ -9220,37 +10035,37 @@ type EpicIssue implements CurrentUserTodos & Noteable {
titleHtml: String
"""
- Total time reported as spent on the issue
+ Total time reported as spent on the issue.
"""
totalTimeSpent: Int!
"""
- Type of the issue
+ Type of the issue.
"""
type: IssueType
"""
- Timestamp of when the issue was last updated
+ Timestamp of when the issue was last updated.
"""
updatedAt: Time!
"""
- User that last updated the issue
+ User that last updated the issue.
"""
updatedBy: User
"""
- Number of upvotes the issue has received
+ Number of upvotes the issue has received.
"""
upvotes: Int!
"""
- Number of user discussions in the issue
+ Number of user discussions in the issue.
"""
userDiscussionsCount: Int!
"""
- Number of user notes of the issue
+ Number of user notes of the issue.
"""
userNotesCount: Int!
@@ -9260,12 +10075,12 @@ type EpicIssue implements CurrentUserTodos & Noteable {
userPermissions: IssuePermissions!
"""
- Web path of the issue
+ Web path of the issue.
"""
webPath: String!
"""
- Web URL of the issue
+ Web URL of the issue.
"""
webUrl: String!
@@ -9280,7 +10095,7 @@ The connection type for EpicIssue.
"""
type EpicIssueConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -9300,7 +10115,7 @@ type EpicIssueConnection {
pageInfo: PageInfo!
"""
- Total weight of issues collection
+ Total weight of issues collection.
"""
weight: Int!
}
@@ -9554,22 +10369,22 @@ A node of an epic tree.
"""
input EpicTreeNodeFieldsInputType {
"""
- The ID of the epic_issue or issue that the actual epic or issue is switched with
+ The ID of the epic_issue or issue that the actual epic or issue is switched with.
"""
adjacentReferenceId: EpicTreeSortingID
"""
- The ID of the epic_issue or epic that is being moved
+ The ID of the epic_issue or epic that is being moved.
"""
id: EpicTreeSortingID!
"""
- ID of the new parent epic
+ ID of the new parent epic.
"""
newParentId: EpicID
"""
- The type of the switch, after or before allowed
+ The type of the switch, after or before allowed.
"""
relativePosition: MoveType
}
@@ -9610,7 +10425,7 @@ type EpicTreeReorderPayload {
}
"""
-Identifier of EpicTreeSorting
+Identifier of EpicTreeSorting.
"""
scalar EpicTreeSortingID
@@ -9630,6 +10445,168 @@ enum EpicWildcardId {
}
"""
+Representing an event
+"""
+type Event {
+ """
+ Action of the event.
+ """
+ action: EventAction!
+
+ """
+ Author of this event.
+ """
+ author: User!
+
+ """
+ When this event was created.
+ """
+ createdAt: Time!
+
+ """
+ ID of the event.
+ """
+ id: ID!
+
+ """
+ When this event was updated.
+ """
+ updatedAt: Time!
+}
+
+"""
+Event action
+"""
+enum EventAction {
+ """
+ Approved action
+ """
+ APPROVED
+
+ """
+ Archived action
+ """
+ ARCHIVED
+
+ """
+ Closed action
+ """
+ CLOSED
+
+ """
+ Commented action
+ """
+ COMMENTED
+
+ """
+ Created action
+ """
+ CREATED
+
+ """
+ Destroyed action
+ """
+ DESTROYED
+
+ """
+ Expired action
+ """
+ EXPIRED
+
+ """
+ Joined action
+ """
+ JOINED
+
+ """
+ Left action
+ """
+ LEFT
+
+ """
+ Merged action
+ """
+ MERGED
+
+ """
+ Pushed action
+ """
+ PUSHED
+
+ """
+ Reopened action
+ """
+ REOPENED
+
+ """
+ Updated action
+ """
+ UPDATED
+}
+
+"""
+The connection type for Event.
+"""
+type EventConnection {
+ """
+ A list of edges.
+ """
+ edges: [EventEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [Event]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type EventEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: Event
+}
+
+interface Eventable {
+ """
+ A list of events associated with the object.
+ """
+ events(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EventConnection
+}
+
+"""
Autogenerated input type of ExportRequirements
"""
input ExportRequirementsInput {
@@ -9654,6 +10631,11 @@ input ExportRequirementsInput {
search: String
"""
+ List of selected requirements fields to be exported.
+ """
+ selectedFields: [String!]
+
+ """
List requirements by sort order.
"""
sort: Sort
@@ -9684,69 +10666,69 @@ Represents an external issue
"""
type ExternalIssue {
"""
- Timestamp of when the issue was created
+ Timestamp of when the issue was created.
"""
createdAt: Time
"""
- Type of external tracker
+ Type of external tracker.
"""
externalTracker: String
"""
- Relative reference of the issue in the external tracker
+ Relative reference of the issue in the external tracker.
"""
relativeReference: String
"""
- Status of the issue in the external tracker
+ Status of the issue in the external tracker.
"""
status: String
"""
- Title of the issue in the external tracker
+ Title of the issue in the external tracker.
"""
title: String
"""
- Timestamp of when the issue was updated
+ Timestamp of when the issue was updated.
"""
updatedAt: Time
"""
- URL to the issue in the external tracker
+ URL to the issue in the external tracker.
"""
webUrl: String
}
type GeoNode {
"""
- The maximum concurrency of container repository sync for this secondary node
+ The maximum concurrency of container repository sync for this secondary node.
"""
containerRepositoriesMaxCapacity: Int
"""
- Indicates whether this Geo node is enabled
+ Indicates whether this Geo node is enabled.
"""
enabled: Boolean
"""
- The maximum concurrency of LFS/attachment backfill for this secondary node
+ The maximum concurrency of LFS/attachment backfill for this secondary node.
"""
filesMaxCapacity: Int
"""
- ID of this GeoNode
+ ID of this GeoNode.
"""
id: ID!
"""
- The URL defined on the primary node that secondary nodes should use to contact it
+ The URL defined on the primary node that secondary nodes should use to contact it.
"""
internalUrl: String
"""
- Find merge request diff registries on this Geo node
+ Find merge request diff registries on this Geo node.
"""
mergeRequestDiffRegistries(
"""
@@ -9776,17 +10758,17 @@ type GeoNode {
): MergeRequestDiffRegistryConnection
"""
- The interval (in days) in which the repository verification is valid. Once expired, it will be reverified
+ The interval (in days) in which the repository verification is valid. Once expired, it will be reverified.
"""
minimumReverificationInterval: Int
"""
- The unique identifier for this Geo node
+ The unique identifier for this Geo node.
"""
name: String
"""
- Package file registries of the GeoNode
+ Package file registries of the GeoNode.
"""
packageFileRegistries(
"""
@@ -9816,17 +10798,17 @@ type GeoNode {
): PackageFileRegistryConnection
"""
- Indicates whether this Geo node is the primary
+ Indicates whether this Geo node is the primary.
"""
primary: Boolean
"""
- The maximum concurrency of repository backfill for this secondary node
+ The maximum concurrency of repository backfill for this secondary node.
"""
reposMaxCapacity: Int
"""
- The namespaces that should be synced, if `selective_sync_type` == `namespaces`
+ The namespaces that should be synced, if `selective_sync_type` == `namespaces`.
"""
selectiveSyncNamespaces(
"""
@@ -9851,17 +10833,17 @@ type GeoNode {
): NamespaceConnection
"""
- The repository storages whose projects should be synced, if `selective_sync_type` == `shards`
+ The repository storages whose projects should be synced, if `selective_sync_type` == `shards`.
"""
selectiveSyncShards: [String!]
"""
- Indicates if syncing is limited to only specific groups, or shards
+ Indicates if syncing is limited to only specific groups, or shards.
"""
selectiveSyncType: String
"""
- Find snippet repository registries on this Geo node
+ Find snippet repository registries on this Geo node.
"""
snippetRepositoryRegistries(
"""
@@ -9891,12 +10873,12 @@ type GeoNode {
): SnippetRepositoryRegistryConnection
"""
- Indicates if this secondary node will replicate blobs in Object Storage
+ Indicates if this secondary node will replicate blobs in Object Storage.
"""
syncObjectStorage: Boolean
"""
- Find terraform state version registries on this Geo node
+ Find terraform state version registries on this Geo node.
"""
terraformStateVersionRegistries(
"""
@@ -9926,71 +10908,101 @@ type GeoNode {
): TerraformStateVersionRegistryConnection
"""
- The user-facing URL for this Geo node
+ The user-facing URL for this Geo node.
"""
url: String
"""
- The maximum concurrency of repository verification for this secondary node
+ The maximum concurrency of repository verification for this secondary node.
"""
verificationMaxCapacity: Int
}
"""
-Identifier of Gitlab::ErrorTracking::DetailedError
+Identifier of Gitlab::ErrorTracking::DetailedError.
"""
scalar GitlabErrorTrackingDetailedErrorID
+"""
+Autogenerated input type of GitlabSubscriptionActivate
+"""
+input GitlabSubscriptionActivateInput {
+ """
+ Activation code received after purchasing a GitLab subscription.
+ """
+ activationCode: String!
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+}
+
+"""
+Autogenerated return type of GitlabSubscriptionActivate
+"""
+type GitlabSubscriptionActivatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
type GrafanaIntegration {
"""
- Timestamp of the issue's creation
+ Timestamp of the issue's creation.
"""
createdAt: Time!
"""
- Indicates whether Grafana integration is enabled
+ Indicates whether Grafana integration is enabled.
"""
enabled: Boolean!
"""
- URL for the Grafana host for the Grafana integration
+ URL for the Grafana host for the Grafana integration.
"""
grafanaUrl: String!
"""
- Internal ID of the Grafana integration
+ Internal ID of the Grafana integration.
"""
id: ID!
"""
- Timestamp of the issue's last activity
+ Timestamp of the issue's last activity.
"""
updatedAt: Time!
}
type Group {
"""
- Size limit for repositories in the namespace in bytes
+ Size limit for repositories in the namespace in bytes.
"""
actualRepositorySizeLimit: Float
"""
- Additional storage purchased for the root namespace in bytes
+ Additional storage purchased for the root namespace in bytes.
"""
additionalPurchasedStorageSize: Float
"""
- Indicates whether Auto DevOps is enabled for all projects within this group
+ Indicates whether Auto DevOps is enabled for all projects within this group.
"""
autoDevopsEnabled: Boolean
"""
- Avatar URL of the group
+ Avatar URL of the group.
"""
avatarUrl: String
"""
- A single board of the group
+ A single board of the group.
"""
board(
"""
@@ -10000,7 +11012,7 @@ type Group {
): Board
"""
- Boards of the group
+ Boards of the group.
"""
boards(
"""
@@ -10030,7 +11042,7 @@ type Group {
): BoardConnection
"""
- Represents the code coverage activity for this group
+ Represents the code coverage activity for this group.
"""
codeCoverageActivities(
"""
@@ -10091,7 +11103,7 @@ type Group {
): ComplianceFrameworkConnection
"""
- Container repositories of the group
+ Container repositories of the group.
"""
containerRepositories(
"""
@@ -10118,20 +11130,25 @@ type Group {
Filter the container repositories by their name.
"""
name: String
+
+ """
+ Sort container repositories by this criteria.
+ """
+ sort: ContainerRepositorySort = created_desc
): ContainerRepositoryConnection
"""
- Number of container repositories in the group
+ Number of container repositories in the group.
"""
containerRepositoriesCount: Int!
"""
- Includes at least one project where the repository size exceeds the limit
+ Includes at least one project where the repository size exceeds the limit.
"""
containsLockedProjects: Boolean!
"""
- Custom emoji within this namespace Available only when feature flag `custom_emoji` is enabled.
+ Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled.
"""
customEmoji(
"""
@@ -10156,7 +11173,7 @@ type Group {
): CustomEmojiConnection
"""
- Description of the namespace
+ Description of the namespace.
"""
description: String
@@ -10166,12 +11183,12 @@ type Group {
descriptionHtml: String
"""
- Indicates if a group has email notifications disabled
+ Indicates if a group has email notifications disabled.
"""
emailsDisabled: Boolean
"""
- Find a single epic
+ Find a single epic.
"""
epic(
"""
@@ -10249,7 +11266,7 @@ type Group {
): Epic
"""
- Find a single epic board
+ Find a single epic board.
"""
epicBoard(
"""
@@ -10259,7 +11276,7 @@ type Group {
): EpicBoard
"""
- Find epic boards
+ Find epic boards.
"""
epicBoards(
"""
@@ -10284,7 +11301,7 @@ type Group {
): EpicBoardConnection
"""
- Find epics
+ Find epics.
"""
epics(
"""
@@ -10387,17 +11404,17 @@ type Group {
epicsEnabled: Boolean
"""
- Full name of the namespace
+ Full name of the namespace.
"""
fullName: String!
"""
- Full path of the namespace
+ Full path of the namespace.
"""
fullPath: ID!
"""
- A membership of a user within this group
+ A membership of a user within this group.
"""
groupMembers(
"""
@@ -10437,17 +11454,17 @@ type Group {
groupTimelogsEnabled: Boolean
"""
- ID of the namespace
+ ID of the namespace.
"""
id: ID!
"""
- Status of the temporary storage increase
+ Status of the temporary storage increase.
"""
isTemporaryStorageIncreaseEnabled: Boolean!
"""
- Issues for projects in this group
+ Issues for projects in this group.
"""
issues(
"""
@@ -10577,7 +11594,7 @@ type Group {
): IssueConnection
"""
- Find iterations
+ Find iterations.
"""
iterations(
"""
@@ -10645,17 +11662,17 @@ type Group {
): IterationConnection
"""
- A label available on this group
+ A label available on this group.
"""
label(
"""
- Title of the label
+ Title of the label.
"""
title: String!
): Label
"""
- Labels available on this group
+ Labels available on this group.
"""
labels(
"""
@@ -10674,28 +11691,43 @@ type Group {
first: Int
"""
+ Include labels from ancestor groups.
+ """
+ includeAncestorGroups: Boolean = false
+
+ """
+ Include labels from descendant groups.
+ """
+ includeDescendantGroups: Boolean = false
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
"""
- A search term to find labels with
+ Include only group level labels.
+ """
+ onlyGroupLabels: Boolean = false
+
+ """
+ A search term to find labels with.
"""
searchTerm: String
): LabelConnection
"""
- Indicates if Large File Storage (LFS) is enabled for namespace
+ Indicates if Large File Storage (LFS) is enabled for namespace.
"""
lfsEnabled: Boolean
"""
- Indicates if a group is disabled from getting mentioned
+ Indicates if a group is disabled from getting mentioned.
"""
mentionsDisabled: Boolean
"""
- Merge requests for projects in this group
+ Merge requests for projects in this group.
"""
mergeRequests(
"""
@@ -10780,7 +11812,7 @@ type Group {
): MergeRequestConnection
"""
- Milestones of the group
+ Milestones of the group.
"""
milestones(
"""
@@ -10853,32 +11885,32 @@ type Group {
): MilestoneConnection
"""
- Name of the namespace
+ Name of the namespace.
"""
name: String!
"""
- The package settings for the namespace
+ The package settings for the namespace.
"""
packageSettings: PackageSettings
"""
- Parent group
+ Parent group.
"""
parent: Group
"""
- Path of the namespace
+ Path of the namespace.
"""
path: String!
"""
- The permission level required to create projects in the group
+ The permission level required to create projects in the group.
"""
projectCreationLevel: String
"""
- Projects within this namespace
+ Projects within this namespace.
"""
projects(
"""
@@ -10923,52 +11955,52 @@ type Group {
): ProjectConnection!
"""
- Number of projects in the root namespace where the repository size exceeds the limit
+ Number of projects in the root namespace where the repository size exceeds the limit.
"""
repositorySizeExcessProjectCount: Int!
"""
- Indicates if users can request access to namespace
+ Indicates if users can request access to namespace.
"""
requestAccessEnabled: Boolean
"""
- Indicates if all users in this group are required to set up two-factor authentication
+ Indicates if all users in this group are required to set up two-factor authentication.
"""
requireTwoFactorAuthentication: Boolean
"""
- Aggregated storage statistics of the namespace. Only available for root namespaces
+ Aggregated storage statistics of the namespace. Only available for root namespaces.
"""
rootStorageStatistics: RootStorageStatistics
"""
- Indicates if sharing a project with another group within this group is prevented
+ Indicates if sharing a project with another group within this group is prevented.
"""
shareWithGroupLock: Boolean
"""
- Group statistics
+ Group statistics.
"""
stats: GroupStats
"""
- Total storage limit of the root namespace in bytes
+ Total storage limit of the root namespace in bytes.
"""
storageSizeLimit: Float
"""
- The permission level required to create subgroups within the group
+ The permission level required to create subgroups within the group.
"""
subgroupCreationLevel: String
"""
- Date until the temporary storage increase is active
+ Date until the temporary storage increase is active.
"""
temporaryStorageIncreaseEndsOn: Time
"""
- Time logged in issues by group members
+ Time logged in issues by group members.
"""
timelogs(
"""
@@ -11013,17 +12045,17 @@ type Group {
): TimelogConnection!
"""
- Total repository size of all projects in the root namespace in bytes
+ Total repository size of all projects in the root namespace in bytes.
"""
totalRepositorySize: Float
"""
- Total excess repository size of all projects in the root namespace in bytes
+ Total excess repository size of all projects in the root namespace in bytes.
"""
totalRepositorySizeExcess: Float
"""
- Time before two-factor authentication is enforced
+ Time before two-factor authentication is enforced.
"""
twoFactorGracePeriod: Int
@@ -11033,12 +12065,12 @@ type Group {
userPermissions: GroupPermissions!
"""
- Visibility of the namespace
+ Visibility of the namespace.
"""
visibility: String
"""
- Vulnerabilities reported on the projects in the group and its subgroups
+ Vulnerabilities reported on the projects in the group and its subgroups.
"""
vulnerabilities(
"""
@@ -11103,7 +12135,7 @@ type Group {
): VulnerabilityConnection
"""
- Number of vulnerabilities per day for the projects in the group and its subgroups
+ Number of vulnerabilities per day for the projects in the group and its subgroups.
"""
vulnerabilitiesCountByDay(
"""
@@ -11139,7 +12171,7 @@ type Group {
"""
Number of vulnerabilities per severity level, per day, for the projects in the
- group and its subgroups Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.
+ group and its subgroups. Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.
"""
vulnerabilitiesCountByDayAndSeverity(
"""
@@ -11174,7 +12206,7 @@ type Group {
): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3.")
"""
- Represents vulnerable project counts for each grade
+ Represents vulnerable project counts for each grade.
"""
vulnerabilityGrades(
"""
@@ -11184,7 +12216,7 @@ type Group {
): [VulnerableProjectsByGrade!]!
"""
- Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups
+ Vulnerability scanners reported on the project vulnerabilities of the group and its subgroups.
"""
vulnerabilityScanners(
"""
@@ -11209,7 +12241,7 @@ type Group {
): VulnerabilityScannerConnection
"""
- Counts for each vulnerability severity in the group and its subgroups
+ Counts for each vulnerability severity in the group and its subgroups.
"""
vulnerabilitySeveritiesCount(
"""
@@ -11239,13 +12271,13 @@ type Group {
): VulnerabilitySeveritiesCount
"""
- Web URL of the group
+ Web URL of the group.
"""
webUrl: String!
}
"""
-Identifier of Group
+Identifier of Group.
"""
scalar GroupID
@@ -11254,42 +12286,42 @@ Represents a Group Membership
"""
type GroupMember implements MemberInterface {
"""
- GitLab::Access level
+ GitLab::Access level.
"""
accessLevel: AccessLevel
"""
- Date and time the membership was created
+ Date and time the membership was created.
"""
createdAt: Time
"""
- User that authorized membership
+ User that authorized membership.
"""
createdBy: User
"""
- Date and time the membership expires
+ Date and time the membership expires.
"""
expiresAt: Time
"""
- Group that a User is a member of
+ Group that a User is a member of.
"""
group: Group
"""
- ID of the member
+ ID of the member.
"""
id: ID!
"""
- Date and time the membership was last updated
+ Date and time the membership was last updated.
"""
updatedAt: Time
"""
- User that is associated with the member object
+ User that is associated with the member object.
"""
user: User!
@@ -11383,7 +12415,7 @@ Contains statistics about a group
"""
type GroupStats {
"""
- Statistics related to releases within the group
+ Statistics related to releases within the group.
"""
releaseStats: GroupReleaseStats
}
@@ -11545,6 +12577,16 @@ input HttpIntegrationUpdateInput {
The name of the integration.
"""
name: String
+
+ """
+ The custom mapping of GitLab alert attributes to fields from the payload_example.
+ """
+ payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!]
+
+ """
+ The example of an alert payload.
+ """
+ payloadExample: JsonString
}
"""
@@ -11573,7 +12615,7 @@ An ISO 8601-encoded date
scalar ISO8601Date
"""
-Identifier of IncidentManagement::OncallParticipant
+Identifier of IncidentManagement::OncallParticipant.
"""
scalar IncidentManagementOncallParticipantID
@@ -11627,6 +12669,41 @@ type IncidentManagementOncallRotation {
): OncallParticipantTypeConnection
"""
+ Blocks of time for which a participant is on-call within a given time frame. Time frame cannot exceed one month.
+ """
+ shifts(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ End of timeframe to include shifts for. Cannot exceed one month after start.
+ """
+ endTime: Time!
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+
+ """
+ Start of timeframe to include shifts for.
+ """
+ startTime: Time!
+ ): IncidentManagementOncallShiftConnection
+
+ """
Start date of the on-call rotation.
"""
startsAt: Time
@@ -11668,7 +12745,7 @@ type IncidentManagementOncallRotationEdge {
}
"""
-Identifier of IncidentManagement::OncallRotation
+Identifier of IncidentManagement::OncallRotation.
"""
scalar IncidentManagementOncallRotationID
@@ -11677,22 +12754,22 @@ Describes an incident management on-call schedule
"""
type IncidentManagementOncallSchedule {
"""
- Description of the on-call schedule
+ Description of the on-call schedule.
"""
description: String
"""
- Internal ID of the on-call schedule
+ Internal ID of the on-call schedule.
"""
iid: ID!
"""
- Name of the on-call schedule
+ Name of the on-call schedule.
"""
name: String!
"""
- On-call rotations for the on-call schedule
+ On-call rotations for the on-call schedule.
"""
rotations(
"""
@@ -11717,7 +12794,7 @@ type IncidentManagementOncallSchedule {
): IncidentManagementOncallRotationConnection!
"""
- Time zone of the on-call schedule
+ Time zone of the on-call schedule.
"""
timezone: String!
}
@@ -11757,9 +12834,64 @@ type IncidentManagementOncallScheduleEdge {
node: IncidentManagementOncallSchedule
}
+"""
+A block of time for which a participant is on-call.
+"""
+type IncidentManagementOncallShift {
+ """
+ End time of the on-call shift.
+ """
+ endsAt: Time
+
+ """
+ Participant assigned to the on-call shift.
+ """
+ participant: OncallParticipantType
+
+ """
+ Start time of the on-call shift.
+ """
+ startsAt: Time
+}
+
+"""
+The connection type for IncidentManagementOncallShift.
+"""
+type IncidentManagementOncallShiftConnection {
+ """
+ A list of edges.
+ """
+ edges: [IncidentManagementOncallShiftEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [IncidentManagementOncallShift]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type IncidentManagementOncallShiftEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: IncidentManagementOncallShift
+}
+
type InstanceSecurityDashboard {
"""
- Projects selected in Instance Security Dashboard
+ Projects selected in Instance Security Dashboard.
"""
projects(
"""
@@ -11784,12 +12916,12 @@ type InstanceSecurityDashboard {
): ProjectConnection!
"""
- Represents vulnerable project counts for each grade
+ Represents vulnerable project counts for each grade.
"""
vulnerabilityGrades: [VulnerableProjectsByGrade!]!
"""
- Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard
+ Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard.
"""
vulnerabilityScanners(
"""
@@ -11814,7 +12946,7 @@ type InstanceSecurityDashboard {
): VulnerabilityScannerConnection
"""
- Counts for each vulnerability severity from projects selected in Instance Security Dashboard
+ Counts for each vulnerability severity from projects selected in Instance Security Dashboard.
"""
vulnerabilitySeveritiesCount(
"""
@@ -11849,17 +12981,17 @@ Represents a recorded measurement (object count) for the Admins
"""
type InstanceStatisticsMeasurement {
"""
- Object count
+ Object count.
"""
count: Int!
"""
- The type of objects being measured
+ The type of objects being measured.
"""
identifier: MeasurementIdentifier!
"""
- The time the measurement was recorded
+ The time the measurement was recorded.
"""
recordedAt: Time
}
@@ -11941,12 +13073,12 @@ enum IssuableState {
type Issue implements CurrentUserTodos & Noteable {
"""
- Alert associated to this issue
+ Alert associated to this issue.
"""
alertManagementAlert: AlertManagementAlert
"""
- Assignees of the issue
+ Assignees of the issue.
"""
assignees(
"""
@@ -11971,7 +13103,7 @@ type Issue implements CurrentUserTodos & Noteable {
): UserConnection
"""
- User that created the issue
+ User that created the issue.
"""
author: User!
@@ -11986,27 +13118,27 @@ type Issue implements CurrentUserTodos & Noteable {
blockedByCount: Int
"""
- Timestamp of when the issue was closed
+ Timestamp of when the issue was closed.
"""
closedAt: Time
"""
- Indicates the issue is confidential
+ Indicates the issue is confidential.
"""
confidential: Boolean!
"""
- User specific email address for the issue
+ User specific email address for the issue.
"""
createNoteEmail: String
"""
- Timestamp of when the issue was created
+ Timestamp of when the issue was created.
"""
createdAt: Time!
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -12030,13 +13162,13 @@ type Issue implements CurrentUserTodos & Noteable {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
"""
- Description of the issue
+ Description of the issue.
"""
description: String
@@ -12046,17 +13178,17 @@ type Issue implements CurrentUserTodos & Noteable {
descriptionHtml: String
"""
- Collection of design images associated with this issue
+ Collection of design images associated with this issue.
"""
designCollection: DesignCollection
"""
- Indicates discussion is locked on the issue
+ Indicates discussion is locked on the issue.
"""
discussionLocked: Boolean!
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -12081,17 +13213,17 @@ type Issue implements CurrentUserTodos & Noteable {
): DiscussionConnection!
"""
- Number of downvotes the issue has received
+ Number of downvotes the issue has received.
"""
downvotes: Int!
"""
- Due date of the issue
+ Due date of the issue.
"""
dueDate: Time
"""
- Indicates if a project has email notifications disabled: `true` if email notifications are disabled
+ Indicates if a project has email notifications disabled: `true` if email notifications are disabled.
"""
emailsDisabled: Boolean!
@@ -12106,22 +13238,22 @@ type Issue implements CurrentUserTodos & Noteable {
healthStatus: HealthStatus
"""
- Human-readable time estimate of the issue
+ Human-readable time estimate of the issue.
"""
humanTimeEstimate: String
"""
- Human-readable total time reported as spent on the issue
+ Human-readable total time reported as spent on the issue.
"""
humanTotalTimeSpent: String
"""
- ID of the issue
+ ID of the issue.
"""
id: ID!
"""
- Internal ID of the issue
+ Internal ID of the issue.
"""
iid: ID!
@@ -12131,7 +13263,7 @@ type Issue implements CurrentUserTodos & Noteable {
iteration: Iteration
"""
- Labels of the issue
+ Labels of the issue.
"""
labels(
"""
@@ -12161,22 +13293,22 @@ type Issue implements CurrentUserTodos & Noteable {
metricImages: [MetricImage!]
"""
- Milestone of the issue
+ Milestone of the issue.
"""
milestone: Milestone
"""
- Indicates if issue got moved from other project
+ Indicates if issue got moved from other project.
"""
moved: Boolean
"""
- Updated Issue after it got moved to another project
+ Updated Issue after it got moved to another project.
"""
movedTo: Issue
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -12201,7 +13333,7 @@ type Issue implements CurrentUserTodos & Noteable {
): NoteConnection!
"""
- List of participants in the issue
+ List of participants in the issue.
"""
participants(
"""
@@ -12226,22 +13358,22 @@ type Issue implements CurrentUserTodos & Noteable {
): UserConnection
"""
- Internal reference of the issue. Returned in shortened format by default
+ Internal reference of the issue. Returned in shortened format by default.
"""
reference(
"""
- Boolean option specifying whether the reference should be returned in full
+ Boolean option specifying whether the reference should be returned in full.
"""
full: Boolean = false
): String!
"""
- Relative position of the issue (used for positioning in epic tree and issue boards)
+ Relative position of the issue (used for positioning in epic tree and issue boards).
"""
relativePosition: Int
"""
- Severity level of the incident
+ Severity level of the incident.
"""
severity: IssuableSeverity
@@ -12251,7 +13383,7 @@ type Issue implements CurrentUserTodos & Noteable {
slaDueAt: Time
"""
- State of the issue
+ State of the issue.
"""
state: IssueState!
@@ -12261,22 +13393,22 @@ type Issue implements CurrentUserTodos & Noteable {
statusPagePublishedIncident: Boolean
"""
- Indicates the currently logged in user is subscribed to the issue
+ Indicates the currently logged in user is subscribed to the issue.
"""
subscribed: Boolean!
"""
- Task completion status of the issue
+ Task completion status of the issue.
"""
taskCompletionStatus: TaskCompletionStatus!
"""
- Time estimate of the issue
+ Time estimate of the issue.
"""
timeEstimate: Int!
"""
- Title of the issue
+ Title of the issue.
"""
title: String!
@@ -12286,37 +13418,37 @@ type Issue implements CurrentUserTodos & Noteable {
titleHtml: String
"""
- Total time reported as spent on the issue
+ Total time reported as spent on the issue.
"""
totalTimeSpent: Int!
"""
- Type of the issue
+ Type of the issue.
"""
type: IssueType
"""
- Timestamp of when the issue was last updated
+ Timestamp of when the issue was last updated.
"""
updatedAt: Time!
"""
- User that last updated the issue
+ User that last updated the issue.
"""
updatedBy: User
"""
- Number of upvotes the issue has received
+ Number of upvotes the issue has received.
"""
upvotes: Int!
"""
- Number of user discussions in the issue
+ Number of user discussions in the issue.
"""
userDiscussionsCount: Int!
"""
- Number of user notes of the issue
+ Number of user notes of the issue.
"""
userNotesCount: Int!
@@ -12326,12 +13458,12 @@ type Issue implements CurrentUserTodos & Noteable {
userPermissions: IssuePermissions!
"""
- Web path of the issue
+ Web path of the issue.
"""
webPath: String!
"""
- Web URL of the issue
+ Web URL of the issue.
"""
webUrl: String!
@@ -12346,7 +13478,7 @@ The connection type for Issue.
"""
type IssueConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -12366,7 +13498,7 @@ type IssueConnection {
pageInfo: PageInfo!
"""
- Total weight of issues collection
+ Total weight of issues collection.
"""
weight: Int!
}
@@ -12387,7 +13519,7 @@ type IssueEdge {
}
"""
-Identifier of Issue
+Identifier of Issue.
"""
scalar IssueID
@@ -13161,12 +14293,12 @@ Represents an iteration object
"""
type Iteration implements TimeboxReportInterface {
"""
- Timestamp of iteration creation
+ Timestamp of iteration creation.
"""
createdAt: Time!
"""
- Description of the iteration
+ Description of the iteration.
"""
description: String
@@ -13176,62 +14308,62 @@ type Iteration implements TimeboxReportInterface {
descriptionHtml: String
"""
- Timestamp of the iteration due date
+ Timestamp of the iteration due date.
"""
dueDate: Time
"""
- ID of the iteration
+ ID of the iteration.
"""
id: ID!
"""
- Internal ID of the iteration
+ Internal ID of the iteration.
"""
iid: ID!
"""
- Historically accurate report about the timebox
+ Historically accurate report about the timebox.
"""
report: TimeboxReport
"""
- Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts
+ Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts.
"""
scopedPath: String
"""
- Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts
+ Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts.
"""
scopedUrl: String
"""
- Timestamp of the iteration start date
+ Timestamp of the iteration start date.
"""
startDate: Time
"""
- State of the iteration
+ State of the iteration.
"""
state: IterationState!
"""
- Title of the iteration
+ Title of the iteration.
"""
title: String!
"""
- Timestamp of last iteration update
+ Timestamp of last iteration update.
"""
updatedAt: Time!
"""
- Web path of the iteration
+ Web path of the iteration.
"""
webPath: String!
"""
- Web URL of the iteration
+ Web URL of the iteration.
"""
webUrl: String!
}
@@ -13272,7 +14404,7 @@ type IterationEdge {
}
"""
-Identifier of Iteration
+Identifier of Iteration.
"""
scalar IterationID
@@ -13314,37 +14446,37 @@ scalar JSON
type JiraImport {
"""
- Timestamp of when the Jira import was created
+ Timestamp of when the Jira import was created.
"""
createdAt: Time
"""
- Count of issues that failed to import
+ Count of issues that failed to import.
"""
failedToImportCount: Int!
"""
- Count of issues that were successfully imported
+ Count of issues that were successfully imported.
"""
importedIssuesCount: Int!
"""
- Project key for the imported Jira project
+ Project key for the imported Jira project.
"""
jiraProjectKey: String!
"""
- Timestamp of when the Jira import was scheduled
+ Timestamp of when the Jira import was scheduled.
"""
scheduledAt: Time
"""
- User that started the Jira import
+ User that started the Jira import.
"""
scheduledBy: User
"""
- Total count of issues that were attempted to import
+ Total count of issues that were attempted to import.
"""
totalIssueCount: Int!
}
@@ -13476,17 +14608,17 @@ type JiraImportUsersPayload {
type JiraProject {
"""
- Key of the Jira project
+ Key of the Jira project.
"""
key: String!
"""
- Name of the Jira project
+ Name of the Jira project.
"""
name: String
"""
- ID of the Jira project
+ ID of the Jira project.
"""
projectId: Int!
}
@@ -13528,12 +14660,12 @@ type JiraProjectEdge {
type JiraService implements Service {
"""
- Indicates if the service is active
+ Indicates if the service is active.
"""
active: Boolean
"""
- List of all Jira projects fetched through Jira REST API
+ List of all Jira projects fetched through Jira REST API.
"""
projects(
"""
@@ -13563,51 +14695,51 @@ type JiraService implements Service {
): JiraProjectConnection
"""
- Class name of the service
+ Class name of the service.
"""
type: String
}
type JiraUser {
"""
- ID of the matched GitLab user
+ ID of the matched GitLab user.
"""
gitlabId: Int
"""
- Name of the matched GitLab user
+ Name of the matched GitLab user.
"""
gitlabName: String
"""
- Username of the matched GitLab user
+ Username of the matched GitLab user.
"""
gitlabUsername: String
"""
- Account ID of the Jira user
+ Account ID of the Jira user.
"""
jiraAccountId: String!
"""
- Display name of the Jira user
+ Display name of the Jira user.
"""
jiraDisplayName: String!
"""
- Email of the Jira user, returned only for users with public emails
+ Email of the Jira user, returned only for users with public emails.
"""
jiraEmail: String
}
input JiraUsersMappingInputType {
"""
- Id of the GitLab user
+ Id of the GitLab user.
"""
gitlabId: Int
"""
- Jira account ID of the user
+ Jira account ID of the user.
"""
jiraAccountId: String!
}
@@ -13649,12 +14781,12 @@ scalar JsonString
type Label {
"""
- Background color of the label
+ Background color of the label.
"""
color: String!
"""
- Description of the label (Markdown rendered as HTML for caching)
+ Description of the label (Markdown rendered as HTML for caching).
"""
description: String
@@ -13664,17 +14796,17 @@ type Label {
descriptionHtml: String
"""
- Label ID
+ Label ID.
"""
id: ID!
"""
- Text color of the label
+ Text color of the label.
"""
textColor: String!
"""
- Content of the label
+ Content of the label.
"""
title: String!
}
@@ -13684,7 +14816,7 @@ The connection type for Label.
"""
type LabelConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -13718,7 +14850,7 @@ input LabelCreateInput {
(e.g. #FFAABB) or one of the CSS color names in
https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords.
"""
- color: String = "#428BCA"
+ color: String = "#6699cc"
"""
Description of the label.
@@ -13726,12 +14858,12 @@ input LabelCreateInput {
description: String
"""
- The group full path the resource is associated with.
+ Full path of the group with which the resource is associated.
"""
groupPath: ID
"""
- The project full path the resource is associated with.
+ Full path of the project with which the resource is associated.
"""
projectPath: ID
@@ -13777,12 +14909,12 @@ type LabelEdge {
}
"""
-Identifier of Label
+Identifier of Label.
"""
scalar LabelID
"""
-Identifier of List
+Identifier of List.
"""
scalar ListID
@@ -13887,37 +15019,37 @@ enum MeasurementIdentifier {
interface MemberInterface {
"""
- GitLab::Access level
+ GitLab::Access level.
"""
accessLevel: AccessLevel
"""
- Date and time the membership was created
+ Date and time the membership was created.
"""
createdAt: Time
"""
- User that authorized membership
+ User that authorized membership.
"""
createdBy: User
"""
- Date and time the membership expires
+ Date and time the membership expires.
"""
expiresAt: Time
"""
- ID of the member
+ ID of the member.
"""
id: ID!
"""
- Date and time the membership was last updated
+ Date and time the membership was last updated.
"""
updatedAt: Time
"""
- User that is associated with the member object
+ User that is associated with the member object.
"""
user: User!
}
@@ -13959,17 +15091,17 @@ type MemberInterfaceEdge {
type MergeRequest implements CurrentUserTodos & Noteable {
"""
- Indicates if members of the target project can push to the fork
+ Indicates if members of the target project can push to the fork.
"""
allowCollaboration: Boolean
"""
- Number of approvals left
+ Number of approvals left.
"""
approvalsLeft: Int
"""
- Number of approvals required
+ Number of approvals required.
"""
approvalsRequired: Int
@@ -13979,7 +15111,7 @@ type MergeRequest implements CurrentUserTodos & Noteable {
approved: Boolean!
"""
- Users who approved the merge request
+ Users who approved the merge request.
"""
approvedBy(
"""
@@ -14004,7 +15136,7 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): UserConnection
"""
- Assignees of the merge request
+ Assignees of the merge request.
"""
assignees(
"""
@@ -14029,32 +15161,32 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): UserConnection
"""
- User who created this merge request
+ User who created this merge request.
"""
author: User
"""
- Indicates if auto merge is enabled for the merge request
+ Indicates if auto merge is enabled for the merge request.
"""
autoMergeEnabled: Boolean!
"""
- Selected auto merge strategy
+ Selected auto merge strategy.
"""
autoMergeStrategy: String
"""
- Array of available auto merge strategies
+ Array of available auto merge strategies.
"""
availableAutoMergeStrategies: [String!]
"""
- Number of commits in the merge request
+ Number of commits in the merge request.
"""
commitCount: Int
"""
- Merge request commits excluding merge commits
+ Merge request commits excluding merge commits.
"""
commitsWithoutMergeCommits(
"""
@@ -14079,17 +15211,17 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): CommitConnection
"""
- Indicates if the merge request has conflicts
+ Indicates if the merge request has conflicts.
"""
conflicts: Boolean!
"""
- Timestamp of when the merge request was created
+ Timestamp of when the merge request was created.
"""
createdAt: Time!
"""
- Todos for the current user
+ To-do items for the current user.
"""
currentUserTodos(
"""
@@ -14113,28 +15245,28 @@ type MergeRequest implements CurrentUserTodos & Noteable {
last: Int
"""
- State of the todos
+ State of the to-do items.
"""
state: TodoStateEnum
): TodoConnection!
"""
- Default merge commit message of the merge request
+ Default merge commit message of the merge request.
"""
defaultMergeCommitMessage: String
"""
- Default merge commit message of the merge request with description
+ Default merge commit message of the merge request with description.
"""
defaultMergeCommitMessageWithDescription: String
"""
- Default squash commit message of the merge request
+ Default squash commit message of the merge request.
"""
defaultSquashCommitMessage: String
"""
- Description of the merge request (Markdown rendered as HTML for caching)
+ Description of the merge request (Markdown rendered as HTML for caching).
"""
description: String
@@ -14144,37 +15276,37 @@ type MergeRequest implements CurrentUserTodos & Noteable {
descriptionHtml: String
"""
- Diff head SHA of the merge request
+ Diff head SHA of the merge request.
"""
diffHeadSha: String
"""
- References of the base SHA, the head SHA, and the start SHA for this merge request
+ References of the base SHA, the head SHA, and the start SHA for this merge request.
"""
diffRefs: DiffRefs
"""
- Details about which files were changed in this merge request
+ Details about which files were changed in this merge request.
"""
diffStats(
"""
- A specific file-path
+ A specific file-path.
"""
path: String
): [DiffStats!]
"""
- Summary of which files were changed in this merge request
+ Summary of which files were changed in this merge request.
"""
diffStatsSummary: DiffStatsSummary
"""
- Indicates if comments on the merge request are locked to members only
+ Indicates if comments on the merge request are locked to members only.
"""
discussionLocked: Boolean!
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -14199,42 +15331,47 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): DiscussionConnection!
"""
- Number of downvotes for the merge request
+ Number of downvotes for the merge request.
"""
downvotes: Int!
"""
- Indicates if the project settings will lead to source branch deletion after merge
+ Indicates if the project settings will lead to source branch deletion after merge.
"""
forceRemoveSourceBranch: Boolean
"""
- Indicates if the merge request has CI
+ Indicates if the merge request has CI.
"""
hasCi: Boolean!
"""
- The pipeline running on the branch HEAD of the merge request
+ Indicates if the source branch has any security reports.
+ """
+ hasSecurityReports: Boolean!
+
+ """
+ The pipeline running on the branch HEAD of the merge request.
"""
headPipeline: Pipeline
"""
- ID of the merge request
+ ID of the merge request.
"""
id: ID!
"""
- Internal ID of the merge request
+ Internal ID of the merge request.
"""
iid: String!
"""
- Commit SHA of the merge request if merge is in progress
+ Commit SHA of the merge request if merge is in progress.
"""
inProgressMergeCommitSha: String
"""
- Labels of the merge request
+ Labels of the merge request.
"""
labels(
"""
@@ -14259,61 +15396,62 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): LabelConnection
"""
- SHA of the merge request commit (set once merged)
+ SHA of the merge request commit (set once merged).
"""
mergeCommitSha: String
"""
- Error message due to a merge error
+ Error message due to a merge error.
"""
mergeError: String
"""
- Indicates if a merge is currently occurring
+ Indicates if a merge is currently occurring.
"""
mergeOngoing: Boolean!
"""
- Status of the merge request
+ Status of the merge request.
"""
mergeStatus: String
"""
+ Number of merge requests in the merge train.
"""
mergeTrainsCount: Int
"""
- User who merged this merge request
+ User who merged this merge request.
"""
mergeUser: User
"""
- Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS)
+ Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).
"""
mergeWhenPipelineSucceeds: Boolean
"""
- Indicates if the merge request is mergeable
+ Indicates if the merge request is mergeable.
"""
mergeable: Boolean!
"""
- Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged
+ Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.
"""
mergeableDiscussionsState: Boolean
"""
- Timestamp of when the merge request was merged, null if not merged
+ Timestamp of when the merge request was merged, null if not merged.
"""
mergedAt: Time
"""
- The milestone of the merge request
+ The milestone of the merge request.
"""
milestone: Milestone
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -14404,31 +15542,31 @@ type MergeRequest implements CurrentUserTodos & Noteable {
): PipelineConnection
"""
- Alias for target_project
+ Alias for target_project.
"""
project: Project!
"""
- ID of the merge request project
+ ID of the merge request project.
"""
projectId: Int!
"""
- Rebase commit SHA of the merge request
+ Rebase commit SHA of the merge request.
"""
rebaseCommitSha: String
"""
- Indicates if there is a rebase currently in progress for the merge request
+ Indicates if there is a rebase currently in progress for the merge request.
"""
rebaseInProgress: Boolean!
"""
- Internal reference of the merge request. Returned in shortened format by default
+ Internal reference of the merge request. Returned in shortened format by default.
"""
reference(
"""
- Boolean option specifying whether the reference should be returned in full
+ Boolean option specifying whether the reference should be returned in full.
"""
full: Boolean = false
): String!
@@ -14464,77 +15602,77 @@ type MergeRequest implements CurrentUserTodos & Noteable {
securityAutoFix: Boolean
"""
- Indicates if the merge request will be rebased
+ Indicates if the merge request will be rebased.
"""
shouldBeRebased: Boolean!
"""
- Indicates if the source branch of the merge request will be deleted after merge
+ Indicates if the source branch of the merge request will be deleted after merge.
"""
shouldRemoveSourceBranch: Boolean
"""
- Source branch of the merge request
+ Source branch of the merge request.
"""
sourceBranch: String!
"""
- Indicates if the source branch of the merge request exists
+ Indicates if the source branch of the merge request exists.
"""
sourceBranchExists: Boolean!
"""
- Indicates if the source branch is protected
+ Indicates if the source branch is protected.
"""
sourceBranchProtected: Boolean!
"""
- Source project of the merge request
+ Source project of the merge request.
"""
sourceProject: Project
"""
- ID of the merge request source project
+ ID of the merge request source project.
"""
sourceProjectId: Int
"""
- Indicates if squash on merge is enabled
+ Indicates if squash on merge is enabled.
"""
squash: Boolean!
"""
- Indicates if squash on merge is enabled
+ Indicates if squash on merge is enabled.
"""
squashOnMerge: Boolean!
"""
- State of the merge request
+ State of the merge request.
"""
state: MergeRequestState!
"""
- Indicates if the currently logged in user is subscribed to this merge request
+ Indicates if the currently logged in user is subscribed to this merge request.
"""
subscribed: Boolean!
"""
- Target branch of the merge request
+ Target branch of the merge request.
"""
targetBranch: String!
"""
- Indicates if the target branch of the merge request exists
+ Indicates if the target branch of the merge request exists.
"""
targetBranchExists: Boolean!
"""
- Target project of the merge request
+ Target project of the merge request.
"""
targetProject: Project!
"""
- ID of the merge request target project
+ ID of the merge request target project.
"""
targetProjectId: Int!
@@ -14544,12 +15682,12 @@ type MergeRequest implements CurrentUserTodos & Noteable {
taskCompletionStatus: TaskCompletionStatus!
"""
- Time estimate of the merge request
+ Time estimate of the merge request.
"""
timeEstimate: Int!
"""
- Title of the merge request
+ Title of the merge request.
"""
title: String!
@@ -14559,27 +15697,27 @@ type MergeRequest implements CurrentUserTodos & Noteable {
titleHtml: String
"""
- Total time reported as spent on the merge request
+ Total time reported as spent on the merge request.
"""
totalTimeSpent: Int!
"""
- Timestamp of when the merge request was last updated
+ Timestamp of when the merge request was last updated.
"""
updatedAt: Time!
"""
- Number of upvotes for the merge request
+ Number of upvotes for the merge request.
"""
upvotes: Int!
"""
- Number of user discussions in the merge request
+ Number of user discussions in the merge request.
"""
userDiscussionsCount: Int
"""
- User notes count of the merge request
+ User notes count of the merge request.
"""
userNotesCount: Int
@@ -14589,12 +15727,12 @@ type MergeRequest implements CurrentUserTodos & Noteable {
userPermissions: MergeRequestPermissions!
"""
- Web URL of the merge request
+ Web URL of the merge request.
"""
webUrl: String
"""
- Indicates if the merge request is a work in progress (WIP)
+ Indicates if the merge request is a work in progress (WIP).
"""
workInProgress: Boolean!
}
@@ -14604,7 +15742,7 @@ The connection type for MergeRequest.
"""
type MergeRequestConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -14624,7 +15762,7 @@ type MergeRequestConnection {
pageInfo: PageInfo!
"""
- Total sum of time to merge, in seconds, for the collection of merge requests
+ Total sum of time to merge, in seconds, for the collection of merge requests.
"""
totalTimeToMerge: Float
}
@@ -14639,12 +15777,12 @@ input MergeRequestCreateInput {
clientMutationId: String
"""
- Description of the merge request (Markdown rendered as HTML for caching)
+ Description of the merge request (Markdown rendered as HTML for caching).
"""
description: String
"""
- Labels of the merge request
+ Labels of the merge request.
"""
labels: [String!]
@@ -14654,17 +15792,17 @@ input MergeRequestCreateInput {
projectPath: ID!
"""
- Source branch of the merge request
+ Source branch of the merge request.
"""
sourceBranch: String!
"""
- Target branch of the merge request
+ Target branch of the merge request.
"""
targetBranch: String!
"""
- Title of the merge request
+ Title of the merge request.
"""
title: String!
}
@@ -14714,7 +15852,7 @@ type MergeRequestDiffRegistry {
lastSyncedAt: Time
"""
- ID of the Merge Request diff
+ ID of the Merge Request diff.
"""
mergeRequestDiffId: ID!
@@ -14785,11 +15923,26 @@ type MergeRequestEdge {
}
"""
-Identifier of MergeRequest
+Identifier of MergeRequest.
"""
scalar MergeRequestID
"""
+New state to apply to a merge request.
+"""
+enum MergeRequestNewState {
+ """
+ Close the merge request if it is open.
+ """
+ CLOSED
+
+ """
+ Open the merge request if it is closed.
+ """
+ OPEN
+}
+
+"""
Check permissions for the current user on a merge request
"""
type MergeRequestPermissions {
@@ -14840,6 +15993,51 @@ type MergeRequestPermissions {
}
"""
+Autogenerated input type of MergeRequestReviewerRereview
+"""
+input MergeRequestReviewerRereviewInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The IID of the merge request to mutate.
+ """
+ iid: String!
+
+ """
+ The project the merge request to mutate is in.
+ """
+ projectPath: ID!
+
+ """
+ The user ID for the user that has been requested for a new review.
+ """
+ userId: UserID!
+}
+
+"""
+Autogenerated return type of MergeRequestReviewerRereview
+"""
+type MergeRequestReviewerRereviewPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The merge request after mutation.
+ """
+ mergeRequest: MergeRequest
+}
+
+"""
Autogenerated input type of MergeRequestSetAssignees
"""
input MergeRequestSetAssigneesInput {
@@ -15211,6 +16409,10 @@ enum MergeRequestState {
all
closed
locked
+
+ """
+ Merge Request has been merged
+ """
merged
opened
}
@@ -15225,7 +16427,7 @@ input MergeRequestUpdateInput {
clientMutationId: String
"""
- Description of the merge request (Markdown rendered as HTML for caching)
+ Description of the merge request (Markdown rendered as HTML for caching).
"""
description: String
@@ -15240,12 +16442,17 @@ input MergeRequestUpdateInput {
projectPath: ID!
"""
- Target branch of the merge request
+ The action to perform to change the state.
+ """
+ state: MergeRequestNewState
+
+ """
+ Target branch of the merge request.
"""
targetBranch: String
"""
- Title of the merge request
+ Title of the merge request.
"""
title: String
}
@@ -15272,12 +16479,12 @@ type MergeRequestUpdatePayload {
type Metadata {
"""
- Revision
+ Revision.
"""
revision: String!
"""
- Version
+ Version.
"""
version: String!
}
@@ -15287,34 +16494,34 @@ Represents a metric image upload
"""
type MetricImage {
"""
- File name of the metric image
+ File name of the metric image.
"""
fileName: String
"""
- File path of the metric image
+ File path of the metric image.
"""
filePath: String
"""
- ID of the metric upload
+ ID of the metric upload.
"""
id: ID!
"""
- Internal ID of the metric upload
+ Internal ID of the metric upload.
"""
iid: ID!
"""
- URL of the metric source
+ URL of the metric source.
"""
url: String!
}
type MetricsDashboard {
"""
- Annotations added to the dashboard
+ Annotations added to the dashboard.
"""
annotations(
"""
@@ -15349,39 +16556,39 @@ type MetricsDashboard {
): MetricsDashboardAnnotationConnection
"""
- Path to a file with the dashboard definition
+ Path to a file with the dashboard definition.
"""
path: String
"""
- Dashboard schema validation warnings
+ Dashboard schema validation warnings.
"""
schemaValidationWarnings: [String!]
}
type MetricsDashboardAnnotation {
"""
- Description of the annotation
+ Description of the annotation.
"""
description: String
"""
- Timestamp marking end of annotated time span
+ Timestamp marking end of annotated time span.
"""
endingAt: Time
"""
- ID of the annotation
+ ID of the annotation.
"""
id: ID!
"""
- ID of a dashboard panel to which the annotation should be scoped
+ ID of a dashboard panel to which the annotation should be scoped.
"""
panelId: String
"""
- Timestamp marking start of annotated time span
+ Timestamp marking start of annotated time span.
"""
startingAt: Time
}
@@ -15422,7 +16629,7 @@ type MetricsDashboardAnnotationEdge {
}
"""
-Identifier of Metrics::Dashboard::Annotation
+Identifier of Metrics::Dashboard::Annotation.
"""
scalar MetricsDashboardAnnotationID
@@ -15431,72 +16638,72 @@ Represents a milestone
"""
type Milestone implements TimeboxReportInterface {
"""
- Timestamp of milestone creation
+ Timestamp of milestone creation.
"""
createdAt: Time!
"""
- Description of the milestone
+ Description of the milestone.
"""
description: String
"""
- Timestamp of the milestone due date
+ Timestamp of the milestone due date.
"""
dueDate: Time
"""
- Indicates if milestone is at group level
+ Indicates if milestone is at group level.
"""
groupMilestone: Boolean!
"""
- ID of the milestone
+ ID of the milestone.
"""
id: ID!
"""
- Indicates if milestone is at project level
+ Indicates if milestone is at project level.
"""
projectMilestone: Boolean!
"""
- Historically accurate report about the timebox
+ Historically accurate report about the timebox.
"""
report: TimeboxReport
"""
- Timestamp of the milestone start date
+ Timestamp of the milestone start date.
"""
startDate: Time
"""
- State of the milestone
+ State of the milestone.
"""
state: MilestoneStateEnum!
"""
- Milestone statistics
+ Milestone statistics.
"""
stats: MilestoneStats
"""
- Indicates if milestone is at subgroup level
+ Indicates if milestone is at subgroup level.
"""
subgroupMilestone: Boolean!
"""
- Title of the milestone
+ Title of the milestone.
"""
title: String!
"""
- Timestamp of last milestone update
+ Timestamp of last milestone update.
"""
updatedAt: Time!
"""
- Web path of the milestone
+ Web path of the milestone.
"""
webPath: String!
}
@@ -15537,12 +16744,22 @@ type MilestoneEdge {
}
"""
-Identifier of Milestone
+Identifier of Milestone.
"""
scalar MilestoneID
+"""
+Current state of milestone
+"""
enum MilestoneStateEnum {
+ """
+ Milestone is currently active
+ """
active
+
+ """
+ Milestone is closed
+ """
closed
}
@@ -15551,12 +16768,12 @@ Contains statistics about a milestone
"""
type MilestoneStats {
"""
- Number of closed issues associated with the milestone
+ Number of closed issues associated with the milestone.
"""
closedIssuesCount: Int
"""
- Total number of issues associated with the milestone
+ Total number of issues associated with the milestone.
"""
totalIssuesCount: Int
}
@@ -15582,6 +16799,7 @@ type Mutation {
adminSidekiqQueuesDeleteJobs(input: AdminSidekiqQueuesDeleteJobsInput!): AdminSidekiqQueuesDeleteJobsPayload
alertSetAssignees(input: AlertSetAssigneesInput!): AlertSetAssigneesPayload
alertTodoCreate(input: AlertTodoCreateInput!): AlertTodoCreatePayload
+ apiFuzzingCiConfigurationCreate(input: ApiFuzzingCiConfigurationCreateInput!): ApiFuzzingCiConfigurationCreatePayload
awardEmojiAdd(input: AwardEmojiAddInput!): AwardEmojiAddPayload
awardEmojiRemove(input: AwardEmojiRemoveInput!): AwardEmojiRemovePayload
awardEmojiToggle(input: AwardEmojiToggleInput!): AwardEmojiTogglePayload
@@ -15615,6 +16833,10 @@ type Mutation {
createSnippet(input: CreateSnippetInput!): CreateSnippetPayload
createTestCase(input: CreateTestCaseInput!): CreateTestCasePayload
dastOnDemandScanCreate(input: DastOnDemandScanCreateInput!): DastOnDemandScanCreatePayload
+ dastProfileCreate(input: DastProfileCreateInput!): DastProfileCreatePayload
+ dastProfileDelete(input: DastProfileDeleteInput!): DastProfileDeletePayload
+ dastProfileRun(input: DastProfileRunInput!): DastProfileRunPayload
+ dastProfileUpdate(input: DastProfileUpdateInput!): DastProfileUpdatePayload
dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload
dastScannerProfileDelete(input: DastScannerProfileDeleteInput!): DastScannerProfileDeletePayload
dastScannerProfileUpdate(input: DastScannerProfileUpdateInput!): DastScannerProfileUpdatePayload
@@ -15623,6 +16845,7 @@ type Mutation {
dastSiteProfileUpdate(input: DastSiteProfileUpdateInput!): DastSiteProfileUpdatePayload
dastSiteTokenCreate(input: DastSiteTokenCreateInput!): DastSiteTokenCreatePayload
dastSiteValidationCreate(input: DastSiteValidationCreateInput!): DastSiteValidationCreatePayload
+ dastSiteValidationRevoke(input: DastSiteValidationRevokeInput!): DastSiteValidationRevokePayload
deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload
deleteDevopsAdoptionSegment(input: DeleteDevopsAdoptionSegmentInput!): DeleteDevopsAdoptionSegmentPayload
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
@@ -15643,9 +16866,12 @@ type Mutation {
dismissVulnerability(input: DismissVulnerabilityInput!): DismissVulnerabilityPayload @deprecated(reason: "Use vulnerabilityDismiss. Deprecated in 13.5.")
environmentsCanaryIngressUpdate(input: EnvironmentsCanaryIngressUpdateInput!): EnvironmentsCanaryIngressUpdatePayload
epicAddIssue(input: EpicAddIssueInput!): EpicAddIssuePayload
+ epicBoardCreate(input: EpicBoardCreateInput!): EpicBoardCreatePayload
+ epicBoardListCreate(input: EpicBoardListCreateInput!): EpicBoardListCreatePayload
epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload
epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload
exportRequirements(input: ExportRequirementsInput!): ExportRequirementsPayload
+ gitlabSubscriptionActivate(input: GitlabSubscriptionActivateInput!): GitlabSubscriptionActivatePayload
httpIntegrationCreate(input: HttpIntegrationCreateInput!): HttpIntegrationCreatePayload
httpIntegrationDestroy(input: HttpIntegrationDestroyInput!): HttpIntegrationDestroyPayload
httpIntegrationResetToken(input: HttpIntegrationResetTokenInput!): HttpIntegrationResetTokenPayload
@@ -15666,6 +16892,7 @@ type Mutation {
labelCreate(input: LabelCreateInput!): LabelCreatePayload
markAsSpamSnippet(input: MarkAsSpamSnippetInput!): MarkAsSpamSnippetPayload
mergeRequestCreate(input: MergeRequestCreateInput!): MergeRequestCreatePayload
+ mergeRequestReviewerRereview(input: MergeRequestReviewerRereviewInput!): MergeRequestReviewerRereviewPayload
mergeRequestSetAssignees(input: MergeRequestSetAssigneesInput!): MergeRequestSetAssigneesPayload
mergeRequestSetLabels(input: MergeRequestSetLabelsInput!): MergeRequestSetLabelsPayload
mergeRequestSetLocked(input: MergeRequestSetLockedInput!): MergeRequestSetLockedPayload
@@ -15679,6 +16906,7 @@ type Mutation {
mergeRequestUpdate(input: MergeRequestUpdateInput!): MergeRequestUpdatePayload
namespaceIncreaseStorageTemporarily(input: NamespaceIncreaseStorageTemporarilyInput!): NamespaceIncreaseStorageTemporarilyPayload
oncallRotationCreate(input: OncallRotationCreateInput!): OncallRotationCreatePayload
+ oncallRotationDestroy(input: OncallRotationDestroyInput!): OncallRotationDestroyPayload
oncallScheduleCreate(input: OncallScheduleCreateInput!): OncallScheduleCreatePayload
oncallScheduleDestroy(input: OncallScheduleDestroyInput!): OncallScheduleDestroyPayload
oncallScheduleUpdate(input: OncallScheduleUpdateInput!): OncallScheduleUpdatePayload
@@ -15716,7 +16944,6 @@ type Mutation {
updateBoardList(input: UpdateBoardListInput!): UpdateBoardListPayload
updateComplianceFramework(input: UpdateComplianceFrameworkInput!): UpdateComplianceFrameworkPayload
updateContainerExpirationPolicy(input: UpdateContainerExpirationPolicyInput!): UpdateContainerExpirationPolicyPayload
- updateDevopsAdoptionSegment(input: UpdateDevopsAdoptionSegmentInput!): UpdateDevopsAdoptionSegmentPayload
updateEpic(input: UpdateEpicInput!): UpdateEpicPayload
"""
@@ -15766,12 +16993,12 @@ enum MutationOperationMode {
type Namespace {
"""
- Size limit for repositories in the namespace in bytes
+ Size limit for repositories in the namespace in bytes.
"""
actualRepositorySizeLimit: Float
"""
- Additional storage purchased for the root namespace in bytes
+ Additional storage purchased for the root namespace in bytes.
"""
additionalPurchasedStorageSize: Float
@@ -15807,12 +17034,12 @@ type Namespace {
): ComplianceFrameworkConnection
"""
- Includes at least one project where the repository size exceeds the limit
+ Includes at least one project where the repository size exceeds the limit.
"""
containsLockedProjects: Boolean!
"""
- Description of the namespace
+ Description of the namespace.
"""
description: String
@@ -15822,47 +17049,47 @@ type Namespace {
descriptionHtml: String
"""
- Full name of the namespace
+ Full name of the namespace.
"""
fullName: String!
"""
- Full path of the namespace
+ Full path of the namespace.
"""
fullPath: ID!
"""
- ID of the namespace
+ ID of the namespace.
"""
id: ID!
"""
- Status of the temporary storage increase
+ Status of the temporary storage increase.
"""
isTemporaryStorageIncreaseEnabled: Boolean!
"""
- Indicates if Large File Storage (LFS) is enabled for namespace
+ Indicates if Large File Storage (LFS) is enabled for namespace.
"""
lfsEnabled: Boolean
"""
- Name of the namespace
+ Name of the namespace.
"""
name: String!
"""
- The package settings for the namespace
+ The package settings for the namespace.
"""
packageSettings: PackageSettings
"""
- Path of the namespace
+ Path of the namespace.
"""
path: String!
"""
- Projects within this namespace
+ Projects within this namespace.
"""
projects(
"""
@@ -15907,42 +17134,42 @@ type Namespace {
): ProjectConnection!
"""
- Number of projects in the root namespace where the repository size exceeds the limit
+ Number of projects in the root namespace where the repository size exceeds the limit.
"""
repositorySizeExcessProjectCount: Int!
"""
- Indicates if users can request access to namespace
+ Indicates if users can request access to namespace.
"""
requestAccessEnabled: Boolean
"""
- Aggregated storage statistics of the namespace. Only available for root namespaces
+ Aggregated storage statistics of the namespace. Only available for root namespaces.
"""
rootStorageStatistics: RootStorageStatistics
"""
- Total storage limit of the root namespace in bytes
+ Total storage limit of the root namespace in bytes.
"""
storageSizeLimit: Float
"""
- Date until the temporary storage increase is active
+ Date until the temporary storage increase is active.
"""
temporaryStorageIncreaseEndsOn: Time
"""
- Total repository size of all projects in the root namespace in bytes
+ Total repository size of all projects in the root namespace in bytes.
"""
totalRepositorySize: Float
"""
- Total excess repository size of all projects in the root namespace in bytes
+ Total excess repository size of all projects in the root namespace in bytes.
"""
totalRepositorySizeExcess: Float
"""
- Visibility of the namespace
+ Visibility of the namespace.
"""
visibility: String
}
@@ -15983,7 +17210,7 @@ type NamespaceEdge {
}
"""
-Identifier of Namespace
+Identifier of Namespace.
"""
scalar NamespaceID
@@ -16039,59 +17266,59 @@ enum NamespaceProjectSort {
input NegatedBoardIssueInput {
"""
- Filter by assignee username
+ Filter by assignee username.
"""
assigneeUsername: [String]
"""
- Filter by author username
+ Filter by author username.
"""
authorUsername: String
"""
- Filter by epic ID. Incompatible with epicWildcardId
+ Filter by epic ID. Incompatible with epicWildcardId.
"""
epicId: EpicID
"""
- Filter by iteration title
+ Filter by iteration title.
"""
iterationTitle: String
"""
- Filter by label name
+ Filter by label name.
"""
labelName: [String]
"""
- Filter by milestone title
+ Filter by milestone title.
"""
milestoneTitle: String
"""
- Filter by reaction emoji
+ Filter by reaction emoji.
"""
myReactionEmoji: String
"""
- Filter by release tag
+ Filter by release tag.
"""
releaseTag: String
"""
- Filter by weight
+ Filter by weight.
"""
weight: String
}
type Note implements ResolvableInterface {
"""
- User who wrote this note
+ User who wrote this note.
"""
author: User!
"""
- Content of the note
+ Content of the note.
"""
body: String!
@@ -16101,72 +17328,72 @@ type Note implements ResolvableInterface {
bodyHtml: String
"""
- Indicates if this note is confidential
+ Indicates if this note is confidential.
"""
confidential: Boolean
"""
- Timestamp of the note creation
+ Timestamp of the note creation.
"""
createdAt: Time!
"""
- The discussion this note is a part of
+ The discussion this note is a part of.
"""
discussion: Discussion
"""
- ID of the note
+ ID of the note.
"""
- id: ID!
+ id: NoteID!
"""
- The position of this note on a diff
+ The position of this note on a diff.
"""
position: DiffPosition
"""
- Project associated with the note
+ Project associated with the note.
"""
project: Project
"""
- Indicates if the object can be resolved
+ Indicates if the object can be resolved.
"""
resolvable: Boolean!
"""
- Indicates if the object is resolved
+ Indicates if the object is resolved.
"""
resolved: Boolean!
"""
- Timestamp of when the object was resolved
+ Timestamp of when the object was resolved.
"""
resolvedAt: Time
"""
- User who resolved the object
+ User who resolved the object.
"""
resolvedBy: User
"""
- Indicates whether this note was created by the system or by a user
+ Indicates whether this note was created by the system or by a user.
"""
system: Boolean!
"""
- Name of the icon corresponding to a system note
+ Name of the icon corresponding to a system note.
"""
systemNoteIconName: String
"""
- Timestamp of the note's last activity
+ Timestamp of the note's last activity.
"""
updatedAt: Time!
"""
- URL to view this Note in the Web UI
+ URL to view this Note in the Web UI.
"""
url: String
@@ -16212,7 +17439,7 @@ type NoteEdge {
}
"""
-Identifier of Note
+Identifier of Note.
"""
scalar NoteID
@@ -16250,7 +17477,7 @@ type NotePermissions {
interface Noteable {
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -16275,7 +17502,7 @@ interface Noteable {
): DiscussionConnection!
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -16301,7 +17528,7 @@ interface Noteable {
}
"""
-Identifier of Noteable
+Identifier of Noteable.
"""
scalar NoteableID
@@ -16441,6 +17668,51 @@ input OncallRotationDateInputType {
}
"""
+Autogenerated input type of OncallRotationDestroy
+"""
+input OncallRotationDestroyInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The ID of the on-call rotation to remove.
+ """
+ id: IncidentManagementOncallRotationID!
+
+ """
+ The project to remove the on-call schedule from.
+ """
+ projectPath: ID!
+
+ """
+ The IID of the on-call schedule to the on-call rotation belongs to.
+ """
+ scheduleIid: String!
+}
+
+"""
+Autogenerated return type of OncallRotationDestroy
+"""
+type OncallRotationDestroyPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The on-call rotation.
+ """
+ oncallRotation: IncidentManagementOncallRotation
+}
+
+"""
The rotation length of the on-call rotation
"""
input OncallRotationLengthInputType {
@@ -16645,142 +17917,27 @@ Represents a package in the Package Registry
"""
type Package {
"""
- The created date.
+ Date of creation.
"""
createdAt: Time!
"""
- The ID of the package.
- """
- id: ID!
-
- """
- The name of the package.
- """
- name: String!
-
- """
- The type of the package.
- """
- packageType: PackageTypeEnum!
-
- """
- Pipelines that built the package.
- """
- pipelines(
- """
- Returns the elements in the list that come after the specified cursor.
- """
- after: String
-
- """
- Returns the elements in the list that come before the specified cursor.
- """
- before: String
-
- """
- Returns the first _n_ elements from the list.
- """
- first: Int
-
- """
- Returns the last _n_ elements from the list.
- """
- last: Int
- ): PipelineConnection
-
- """
- Project where the package is stored.
- """
- project: Project!
-
- """
- The package tags.
- """
- tags(
- """
- Returns the elements in the list that come after the specified cursor.
- """
- after: String
-
- """
- Returns the elements in the list that come before the specified cursor.
- """
- before: String
-
- """
- Returns the first _n_ elements from the list.
- """
- first: Int
-
- """
- Returns the last _n_ elements from the list.
- """
- last: Int
- ): PackageTagConnection
-
- """
- The updated date.
- """
- updatedAt: Time!
-
- """
- The version of the package.
- """
- version: String
-
- """
- The other versions of the package.
- """
- versions(
- """
- Returns the elements in the list that come after the specified cursor.
- """
- after: String
-
- """
- Returns the elements in the list that come before the specified cursor.
- """
- before: String
-
- """
- Returns the first _n_ elements from the list.
- """
- first: Int
-
- """
- Returns the last _n_ elements from the list.
- """
- last: Int
- ): PackageConnection
-}
-
-"""
-Details of a Composer package
-"""
-type PackageComposerDetails {
- """
- The Composer metadatum.
- """
- composerMetadatum: PackageComposerMetadatumType!
-
- """
- The created date.
+ ID of the package.
"""
- createdAt: Time!
+ id: PackagesPackageID!
"""
- The ID of the package.
+ Package metadata.
"""
- id: ID!
+ metadata: PackageMetadata
"""
- The name of the package.
+ Name of the package.
"""
name: String!
"""
- The type of the package.
+ Package type.
"""
packageType: PackageTypeEnum!
@@ -16815,7 +17972,7 @@ type PackageComposerDetails {
project: Project!
"""
- The package tags.
+ Package tags.
"""
tags(
"""
@@ -16840,12 +17997,12 @@ type PackageComposerDetails {
): PackageTagConnection
"""
- The updated date.
+ Date of most recent update.
"""
updatedAt: Time!
"""
- The version of the package.
+ Version string.
"""
version: String
@@ -16872,7 +18029,7 @@ type PackageComposerDetails {
Returns the last _n_ elements from the list.
"""
last: Int
- ): PackageConnection
+ ): PackageWithoutVersionsConnection
}
"""
@@ -16901,21 +18058,6 @@ type PackageComposerJsonType {
}
"""
-Composer metadatum
-"""
-type PackageComposerMetadatumType {
- """
- Data of the Composer JSON file.
- """
- composerJson: PackageComposerJsonType!
-
- """
- Target SHA of the package.
- """
- targetSha: String!
-}
-
-"""
The connection type for Package.
"""
type PackageConnection {
@@ -16975,7 +18117,7 @@ type PackageFileRegistry {
lastSyncedAt: Time
"""
- ID of the PackageFile
+ ID of the PackageFile.
"""
packageFileId: ID!
@@ -17031,6 +18173,11 @@ type PackageFileRegistryEdge {
}
"""
+Represents metadata associated with a Package
+"""
+union PackageMetadata = ComposerMetadata
+
+"""
Namespace-level Package Registry settings
"""
type PackageSettings {
@@ -17138,7 +18285,7 @@ enum PackageTypeEnum {
MAVEN
"""
- Packages from the NPM package manager
+ Packages from the npm package manager
"""
NPM
@@ -17151,10 +18298,145 @@ enum PackageTypeEnum {
Packages from the PyPI package manager
"""
PYPI
+
+ """
+ Packages from the Rubygems package manager
+ """
+ RUBYGEMS
+}
+
+"""
+Represents a version of a package in the Package Registry
+"""
+type PackageWithoutVersions {
+ """
+ Date of creation.
+ """
+ createdAt: Time!
+
+ """
+ ID of the package.
+ """
+ id: PackagesPackageID!
+
+ """
+ Package metadata.
+ """
+ metadata: PackageMetadata
+
+ """
+ Name of the package.
+ """
+ name: String!
+
+ """
+ Package type.
+ """
+ packageType: PackageTypeEnum!
+
+ """
+ Pipelines that built the package.
+ """
+ pipelines(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): PipelineConnection
+
+ """
+ Project where the package is stored.
+ """
+ project: Project!
+
+ """
+ Package tags.
+ """
+ tags(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): PackageTagConnection
+
+ """
+ Date of most recent update.
+ """
+ updatedAt: Time!
+
+ """
+ Version string.
+ """
+ version: String
}
"""
-Identifier of Packages::Package
+The connection type for PackageWithoutVersions.
+"""
+type PackageWithoutVersionsConnection {
+ """
+ A list of edges.
+ """
+ edges: [PackageWithoutVersionsEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [PackageWithoutVersions]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type PackageWithoutVersionsEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: PackageWithoutVersions
+}
+
+"""
+Identifier of Packages::Package.
"""
scalar PackagesPackageID
@@ -17185,49 +18467,49 @@ type PageInfo {
type Pipeline {
"""
- Indicates if the pipeline is active
+ Indicates if the pipeline is active.
"""
active: Boolean!
"""
- Base SHA of the source branch
+ Base SHA of the source branch.
"""
beforeSha: String
"""
- Specifies if a pipeline can be canceled
+ Specifies if a pipeline can be canceled.
"""
cancelable: Boolean!
"""
- Timestamp of the pipeline's commit
+ Timestamp of the pipeline's commit.
"""
committedAt: Time
"""
- Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE,
+ Configuration source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE,
AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE,
- BRIDGE_SOURCE, PARAMETER_SOURCE)
+ BRIDGE_SOURCE, PARAMETER_SOURCE, COMPLIANCE_SOURCE)
"""
configSource: PipelineConfigSourceEnum
"""
- Coverage percentage
+ Coverage percentage.
"""
coverage: Float
"""
- Timestamp of the pipeline's creation
+ Timestamp of the pipeline's creation.
"""
createdAt: Time!
"""
- Detailed status of the pipeline
+ Detailed status of the pipeline.
"""
detailedStatus: DetailedStatus!
"""
- Pipelines this pipeline will trigger
+ Pipelines this pipeline will trigger.
"""
downstream(
"""
@@ -17252,27 +18534,27 @@ type Pipeline {
): PipelineConnection
"""
- Duration of the pipeline in seconds
+ Duration of the pipeline in seconds.
"""
duration: Int
"""
- Timestamp of the pipeline's completion
+ Timestamp of the pipeline's completion.
"""
finishedAt: Time
"""
- ID of the pipeline
+ ID of the pipeline.
"""
id: ID!
"""
- Internal ID of the pipeline
+ Internal ID of the pipeline.
"""
iid: String!
"""
- Jobs belonging to the pipeline
+ Jobs belonging to the pipeline.
"""
jobs(
"""
@@ -17302,37 +18584,37 @@ type Pipeline {
): CiJobConnection
"""
- Relative path to the pipeline's page
+ Relative path to the pipeline's page.
"""
path: String
"""
- Project the pipeline belongs to
+ Project the pipeline belongs to.
"""
project: Project
"""
- Specifies if a pipeline can be retried
+ Specifies if a pipeline can be retried.
"""
retryable: Boolean!
"""
- Vulnerability and scanned resource counts for each security scanner of the pipeline
+ Vulnerability and scanned resource counts for each security scanner of the pipeline.
"""
securityReportSummary: SecurityReportSummary
"""
- SHA of the pipeline's commit
+ SHA of the pipeline's commit.
"""
sha: String!
"""
- Job where pipeline was triggered from
+ Job where pipeline was triggered from.
"""
sourceJob: CiJob
"""
- Stages of the pipeline
+ Stages of the pipeline.
"""
stages(
"""
@@ -17357,7 +18639,7 @@ type Pipeline {
): CiStageConnection
"""
- Timestamp when the pipeline was started
+ Timestamp when the pipeline was started.
"""
startedAt: Time
@@ -17368,17 +18650,17 @@ type Pipeline {
status: PipelineStatusEnum!
"""
- Timestamp of the pipeline's last activity
+ Timestamp of the pipeline's last activity.
"""
updatedAt: Time!
"""
- Pipeline that triggered the pipeline
+ Pipeline that triggered the pipeline.
"""
upstream: Pipeline
"""
- Pipeline user
+ Pipeline user.
"""
user: User
@@ -17386,61 +18668,66 @@ type Pipeline {
Permissions for the current user on the resource
"""
userPermissions: PipelinePermissions!
+
+ """
+ Indicates if a pipeline has warnings.
+ """
+ warnings: Boolean!
}
type PipelineAnalytics {
"""
- Labels for the monthly pipeline count
+ Labels for the monthly pipeline count.
"""
monthPipelinesLabels: [String!]
"""
- Total monthly successful pipeline count
+ Total monthly successful pipeline count.
"""
monthPipelinesSuccessful: [Int!]
"""
- Total monthly pipeline count
+ Total monthly pipeline count.
"""
monthPipelinesTotals: [Int!]
"""
- Pipeline times labels
+ Pipeline times labels.
"""
pipelineTimesLabels: [String!]
"""
- Pipeline times
+ Pipeline times.
"""
pipelineTimesValues: [Int!]
"""
- Labels for the weekly pipeline count
+ Labels for the weekly pipeline count.
"""
weekPipelinesLabels: [String!]
"""
- Total weekly successful pipeline count
+ Total weekly successful pipeline count.
"""
weekPipelinesSuccessful: [Int!]
"""
- Total weekly pipeline count
+ Total weekly pipeline count.
"""
weekPipelinesTotals: [Int!]
"""
- Labels for the yearly pipeline count
+ Labels for the yearly pipeline count.
"""
yearPipelinesLabels: [String!]
"""
- Total yearly successful pipeline count
+ Total yearly successful pipeline count.
"""
yearPipelinesSuccessful: [Int!]
"""
- Total yearly pipeline count
+ Total yearly pipeline count.
"""
yearPipelinesTotals: [Int!]
}
@@ -17478,6 +18765,7 @@ type PipelineCancelPayload {
enum PipelineConfigSourceEnum {
AUTO_DEVOPS_SOURCE
BRIDGE_SOURCE
+ COMPLIANCE_SOURCE
EXTERNAL_PROJECT_SOURCE
PARAMETER_SOURCE
REMOTE_SOURCE
@@ -17491,7 +18779,7 @@ The connection type for Pipeline.
"""
type PipelineConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -17624,12 +18912,12 @@ enum PipelineStatusEnum {
type Project {
"""
- Size limit for the repository in bytes
+ Size limit for the repository in bytes.
"""
actualRepositorySizeLimit: Float
"""
- A single Alert Management alert of the project
+ A single Alert Management alert of the project.
"""
alertManagementAlert(
"""
@@ -17664,7 +18952,7 @@ type Project {
): AlertManagementAlert
"""
- Counts of alerts by status for the project
+ Counts of alerts by status for the project.
"""
alertManagementAlertStatusCounts(
"""
@@ -17679,7 +18967,7 @@ type Project {
): AlertManagementAlertStatusCountsType
"""
- Alert Management alerts of the project
+ Alert Management alerts of the project.
"""
alertManagementAlerts(
"""
@@ -17734,7 +19022,7 @@ type Project {
): AlertManagementAlertConnection
"""
- Integrations which can receive alerts for the project
+ Integrations which can receive alerts for the project.
"""
alertManagementIntegrations(
"""
@@ -17759,28 +19047,43 @@ type Project {
): AlertManagementIntegrationConnection
"""
+ Extract alert fields from payload for custom mapping.
+ """
+ alertManagementPayloadFields(
+ """
+ Sample payload for extracting alert fields for custom mappings.
+ """
+ payloadExample: String!
+ ): [AlertManagementPayloadAlertField!]
+
+ """
If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge
- requests of the project can also be merged with skipped jobs
+ requests of the project can also be merged with skipped jobs.
"""
allowMergeOnSkippedPipeline: Boolean
"""
- Indicates the archived status of the project
+ API fuzzing configuration for the project. Available only when feature flag `api_fuzzing_configuration_ui` is enabled.
+ """
+ apiFuzzingCiConfiguration: ApiFuzzingCiConfiguration
+
+ """
+ Indicates the archived status of the project.
"""
archived: Boolean
"""
- Indicates if issues referenced by merge requests and commits within the default branch are closed automatically
+ Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.
"""
autocloseReferencedIssues: Boolean
"""
- URL to avatar image file of the project
+ URL to avatar image file of the project.
"""
avatarUrl: String
"""
- A single board of the project
+ A single board of the project.
"""
board(
"""
@@ -17790,7 +19093,7 @@ type Project {
): Board
"""
- Boards of the project
+ Boards of the project.
"""
boards(
"""
@@ -17820,12 +19123,12 @@ type Project {
): BoardConnection
"""
- CI/CD settings for the project
+ CI/CD settings for the project.
"""
ciCdSettings: ProjectCiCdSetting
"""
- Find a single cluster agent by name
+ Find a single cluster agent by name.
"""
clusterAgent(
"""
@@ -17835,7 +19138,7 @@ type Project {
): ClusterAgent
"""
- Cluster agents associated with the project
+ Cluster agents associated with the project.
"""
clusterAgents(
"""
@@ -17860,12 +19163,12 @@ type Project {
): ClusterAgentConnection
"""
- Code coverage summary associated with the project
+ Code coverage summary associated with the project.
"""
codeCoverageSummary: CodeCoverageSummary
"""
- Compliance frameworks associated with the project
+ Compliance frameworks associated with the project.
"""
complianceFrameworks(
"""
@@ -17890,17 +19193,17 @@ type Project {
): ComplianceFrameworkConnection
"""
- The container expiration policy of the project
+ The container expiration policy of the project.
"""
containerExpirationPolicy: ContainerExpirationPolicy
"""
- Indicates if the project stores Docker container images in a container registry
+ Indicates if the project stores Docker container images in a container registry.
"""
containerRegistryEnabled: Boolean
"""
- Container repositories of the project
+ Container repositories of the project.
"""
containerRepositories(
"""
@@ -17927,20 +19230,50 @@ type Project {
Filter the container repositories by their name.
"""
name: String
+
+ """
+ Sort container repositories by this criteria.
+ """
+ sort: ContainerRepositorySort = created_desc
): ContainerRepositoryConnection
"""
- Number of container repositories in the project
+ Number of container repositories in the project.
"""
containerRepositoriesCount: Int!
"""
- Timestamp of the project creation
+ Timestamp of the project creation.
"""
createdAt: Time
"""
- The DAST scanner profiles associated with the project
+ DAST Profiles associated with the project. Always returns no nodes if `dast_saved_scans` is disabled.
+ """
+ dastProfiles(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): DastProfileConnection
+
+ """
+ The DAST scanner profiles associated with the project.
"""
dastScannerProfiles(
"""
@@ -17965,7 +19298,7 @@ type Project {
): DastScannerProfileConnection
"""
- DAST Site Profile associated with the project
+ DAST Site Profile associated with the project.
"""
dastSiteProfile(
"""
@@ -17975,7 +19308,7 @@ type Project {
): DastSiteProfile
"""
- DAST Site Profiles associated with the project
+ DAST Site Profiles associated with the project.
"""
dastSiteProfiles(
"""
@@ -18000,8 +19333,8 @@ type Project {
): DastSiteProfileConnection
"""
- DAST Site Validations associated with the project. Will always return no nodes
- if `security_on_demand_scans_site_validation` is disabled
+ DAST Site Validations associated with the project. Always returns no nodes if
+ `security_on_demand_scans_site_validation` is disabled.
"""
dastSiteValidations(
"""
@@ -18031,7 +19364,7 @@ type Project {
): DastSiteValidationConnection
"""
- Short description of the project
+ Short description of the project.
"""
description: String
@@ -18041,7 +19374,7 @@ type Project {
descriptionHtml: String
"""
- A single environment of the project
+ A single environment of the project.
"""
environment(
"""
@@ -18061,7 +19394,7 @@ type Project {
): Environment
"""
- Environments of the project
+ Environments of the project.
"""
environments(
"""
@@ -18101,42 +19434,42 @@ type Project {
): EnvironmentConnection
"""
- Number of times the project has been forked
+ Number of times the project has been forked.
"""
forksCount: Int!
"""
- Full path of the project
+ Full path of the project.
"""
fullPath: ID!
"""
- Grafana integration details for the project
+ Grafana integration details for the project.
"""
grafanaIntegration: GrafanaIntegration
"""
- Group of the project
+ Group of the project.
"""
group: Group
"""
- URL to connect to the project via HTTPS
+ URL to connect to the project via HTTPS.
"""
httpUrlToRepo: String
"""
- ID of the project
+ ID of the project.
"""
id: ID!
"""
- Status of import background job of the project
+ Status of import background job of the project.
"""
importStatus: String
"""
- Incident Management On-call schedules of the project
+ Incident Management On-call schedules of the project.
"""
incidentManagementOncallSchedules(
"""
@@ -18161,7 +19494,7 @@ type Project {
): IncidentManagementOncallScheduleConnection
"""
- A single issue of the project
+ A single issue of the project.
"""
issue(
"""
@@ -18266,7 +19599,7 @@ type Project {
): Issue
"""
- Counts of issues by status for the project
+ Counts of issues by status for the project.
"""
issueStatusCounts(
"""
@@ -18351,7 +19684,7 @@ type Project {
): IssueStatusCountsType
"""
- Issues of the project
+ Issues of the project.
"""
issues(
"""
@@ -18481,7 +19814,7 @@ type Project {
issuesEnabled: Boolean
"""
- Find iterations
+ Find iterations.
"""
iterations(
"""
@@ -18549,12 +19882,12 @@ type Project {
): IterationConnection
"""
- Status of Jira import background job of the project
+ Status of Jira import background job of the project.
"""
jiraImportStatus: String
"""
- Jira imports into the project
+ Jira imports into the project.
"""
jiraImports(
"""
@@ -18579,22 +19912,22 @@ type Project {
): JiraImportConnection
"""
- Indicates if CI/CD pipeline jobs are enabled for the current user
+ Indicates if CI/CD pipeline jobs are enabled for the current user.
"""
jobsEnabled: Boolean
"""
- A label available on this project
+ A label available on this project.
"""
label(
"""
- Title of the label
+ Title of the label.
"""
title: String!
): Label
"""
- Labels available on this project
+ Labels available on this project.
"""
labels(
"""
@@ -18613,28 +19946,33 @@ type Project {
first: Int
"""
+ Include labels from ancestor groups.
+ """
+ includeAncestorGroups: Boolean = false
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
"""
- A search term to find labels with
+ A search term to find labels with.
"""
searchTerm: String
): LabelConnection
"""
- Timestamp of the project last activity
+ Timestamp of the project last activity.
"""
lastActivityAt: Time
"""
- Indicates if the project has Large File Storage (LFS) enabled
+ Indicates if the project has Large File Storage (LFS) enabled.
"""
lfsEnabled: Boolean
"""
- A single merge request of the project
+ A single merge request of the project.
"""
mergeRequest(
"""
@@ -18644,7 +19982,7 @@ type Project {
): MergeRequest
"""
- Merge requests of the project
+ Merge requests of the project.
"""
mergeRequests(
"""
@@ -18741,7 +20079,7 @@ type Project {
mergeRequestsFfOnlyEnabled: Boolean
"""
- Milestones of the project
+ Milestones of the project.
"""
milestones(
"""
@@ -18814,37 +20152,37 @@ type Project {
): MilestoneConnection
"""
- Name of the project (without namespace)
+ Name of the project (without namespace).
"""
name: String!
"""
- Full name of the project with its namespace
+ Full name of the project with its namespace.
"""
nameWithNamespace: String!
"""
- Namespace of the project
+ Namespace of the project.
"""
namespace: Namespace
"""
- Indicates if merge requests of the project can only be merged when all the discussions are resolved
+ Indicates if merge requests of the project can only be merged when all the discussions are resolved.
"""
onlyAllowMergeIfAllDiscussionsAreResolved: Boolean
"""
- Indicates if merge requests of the project can only be merged with successful jobs
+ Indicates if merge requests of the project can only be merged with successful jobs.
"""
onlyAllowMergeIfPipelineSucceeds: Boolean
"""
- Number of open issues for the project
+ Number of open issues for the project.
"""
openIssuesCount: Int
"""
- Packages of the project
+ Packages of the project.
"""
packages(
"""
@@ -18869,12 +20207,12 @@ type Project {
): PackageConnection
"""
- Path of the project
+ Path of the project.
"""
path: String!
"""
- Build pipeline of the project
+ Build pipeline of the project.
"""
pipeline(
"""
@@ -18884,12 +20222,12 @@ type Project {
): Pipeline
"""
- Pipeline analytics
+ Pipeline analytics.
"""
pipelineAnalytics: PipelineAnalytics
"""
- Build pipelines of the project
+ Build pipelines of the project.
"""
pipelines(
"""
@@ -18930,12 +20268,12 @@ type Project {
"""
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
+ push to Git repositories of the project from the command line.
"""
printingMergeRequestLinkEnabled: Boolean
"""
- Members of the project
+ Members of the project.
"""
projectMembers(
"""
@@ -18970,12 +20308,12 @@ type Project {
): MemberInterfaceConnection
"""
- Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts
+ Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.
"""
publicJobs: Boolean
"""
- A single release of the project
+ A single release of the project.
"""
release(
"""
@@ -18985,7 +20323,7 @@ type Project {
): Release
"""
- Releases of the project
+ Releases of the project.
"""
releases(
"""
@@ -19015,27 +20353,27 @@ type Project {
): ReleaseConnection
"""
- Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project
+ Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.
"""
removeSourceBranchAfterMerge: Boolean
"""
- Git repository of the project
+ Git repository of the project.
"""
repository: Repository
"""
- Size of repository that exceeds the limit in bytes
+ Size of repository that exceeds the limit in bytes.
"""
repositorySizeExcess: Float
"""
- Indicates if users can request member access to the project
+ Indicates if users can request member access to the project.
"""
requestAccessEnabled: Boolean
"""
- Find a single requirement
+ Find a single requirement.
"""
requirement(
"""
@@ -19054,6 +20392,11 @@ type Project {
iids: [ID!]
"""
+ The state of latest requirement test report.
+ """
+ lastTestReportState: TestReportState
+
+ """
Search query for requirement title.
"""
search: String
@@ -19070,12 +20413,12 @@ type Project {
): Requirement
"""
- Number of requirements for the project by their state
+ Number of requirements for the project by their state.
"""
requirementStatesCount: RequirementStatesCount
"""
- Find requirements
+ Find requirements.
"""
requirements(
"""
@@ -19114,6 +20457,11 @@ type Project {
last: Int
"""
+ The state of latest requirement test report.
+ """
+ lastTestReportState: TestReportState
+
+ """
Search query for requirement title.
"""
search: String
@@ -19130,22 +20478,22 @@ type Project {
): RequirementConnection
"""
- SAST CI configuration for the project
+ SAST CI configuration for the project.
"""
sastCiConfiguration: SastCiConfiguration
"""
- Path to project's security dashboard
+ Path to project's security dashboard.
"""
securityDashboardPath: String
"""
- Information about security analyzers used in the project
+ Information about security analyzers used in the project.
"""
securityScanners: SecurityScanners
"""
- Detailed version of a Sentry error on the project
+ Detailed version of a Sentry error on the project.
"""
sentryDetailedError(
"""
@@ -19155,7 +20503,7 @@ type Project {
): SentryDetailedError
"""
- Paginated collection of Sentry errors on the project
+ Paginated collection of Sentry errors on the project.
"""
sentryErrors: SentryErrorCollection
@@ -19170,7 +20518,7 @@ type Project {
serviceDeskEnabled: Boolean
"""
- Project services
+ Project services.
"""
services(
"""
@@ -19205,12 +20553,12 @@ type Project {
): ServiceConnection
"""
- Indicates if shared runners are enabled for the project
+ Indicates if shared runners are enabled for the project.
"""
sharedRunnersEnabled: Boolean
"""
- Snippets of the project
+ Snippets of the project.
"""
snippets(
"""
@@ -19250,37 +20598,47 @@ type Project {
snippetsEnabled: Boolean
"""
- Indicates if squash readonly is enabled
+ Indicates if `squashReadOnly` is enabled.
"""
squashReadOnly: Boolean!
"""
- URL to connect to the project via SSH
+ URL to connect to the project via SSH.
"""
sshUrlToRepo: String
"""
- Number of times the project has been starred
+ Number of times the project has been starred.
"""
starCount: Int!
"""
- Statistics of the project
+ Statistics of the project.
"""
statistics: ProjectStatistics
"""
- The commit message used to apply merge request suggestions
+ The commit message used to apply merge request suggestions.
"""
suggestionCommitMessage: String
"""
- List of project topics (not Git tags)
+ List of project topics (not Git tags).
"""
tagList: String
"""
- Terraform states associated with the project
+ Find a single Terraform state by name.
+ """
+ terraformState(
+ """
+ Name of the Terraform state.
+ """
+ name: String!
+ ): TerraformState
+
+ """
+ Terraform states associated with the project.
"""
terraformStates(
"""
@@ -19310,12 +20668,12 @@ type Project {
userPermissions: ProjectPermissions!
"""
- Visibility of the project
+ Visibility of the project.
"""
visibility: String
"""
- Vulnerabilities reported on the project
+ Vulnerabilities reported on the project.
"""
vulnerabilities(
"""
@@ -19380,7 +20738,7 @@ type Project {
): VulnerabilityConnection
"""
- Number of vulnerabilities per day for the project
+ Number of vulnerabilities per day for the project.
"""
vulnerabilitiesCountByDay(
"""
@@ -19415,7 +20773,7 @@ type Project {
): VulnerabilitiesCountByDayConnection
"""
- Vulnerability scanners reported on the project vulnerabilties
+ Vulnerability scanners reported on the project vulnerabilities.
"""
vulnerabilityScanners(
"""
@@ -19440,7 +20798,7 @@ type Project {
): VulnerabilityScannerConnection
"""
- Counts for each vulnerability severity in the project
+ Counts for each vulnerability severity in the project.
"""
vulnerabilitySeveritiesCount(
"""
@@ -19470,7 +20828,7 @@ type Project {
): VulnerabilitySeveritiesCount
"""
- Web URL of the project
+ Web URL of the project.
"""
webUrl: String
@@ -19538,7 +20896,7 @@ type ProjectEdge {
}
"""
-Identifier of Project
+Identifier of Project.
"""
scalar ProjectID
@@ -19547,42 +20905,42 @@ Represents a Project Membership
"""
type ProjectMember implements MemberInterface {
"""
- GitLab::Access level
+ GitLab::Access level.
"""
accessLevel: AccessLevel
"""
- Date and time the membership was created
+ Date and time the membership was created.
"""
createdAt: Time
"""
- User that authorized membership
+ User that authorized membership.
"""
createdBy: User
"""
- Date and time the membership expires
+ Date and time the membership expires.
"""
expiresAt: Time
"""
- ID of the member
+ ID of the member.
"""
id: ID!
"""
- Project that User is a member of
+ Project that User is a member of.
"""
project: Project
"""
- Date and time the membership was last updated
+ Date and time the membership was last updated.
"""
updatedAt: Time
"""
- User that is associated with the member object
+ User that is associated with the member object.
"""
user: User!
@@ -19866,47 +21224,47 @@ type ProjectPermissions {
type ProjectStatistics {
"""
- Build artifacts size of the project in bytes
+ Build artifacts size of the project in bytes.
"""
buildArtifactsSize: Float!
"""
- Commit count of the project
+ Commit count of the project.
"""
commitCount: Float!
"""
- Large File Storage (LFS) object size of the project in bytes
+ Large File Storage (LFS) object size of the project in bytes.
"""
lfsObjectsSize: Float!
"""
- Packages size of the project in bytes
+ Packages size of the project in bytes.
"""
packagesSize: Float!
"""
- Repository size of the project in bytes
+ Repository size of the project in bytes.
"""
repositorySize: Float!
"""
- Snippets size of the project in bytes
+ Snippets size of the project in bytes.
"""
snippetsSize: Float
"""
- Storage size of the project in bytes
+ Storage size of the project in bytes.
"""
storageSize: Float!
"""
- Uploads size of the project in bytes
+ Uploads size of the project in bytes.
"""
uploadsSize: Float
"""
- Wiki size of the project in bytes
+ Wiki size of the project in bytes.
"""
wikiSize: Float
}
@@ -19916,12 +21274,12 @@ The alert condition for Prometheus
"""
type PrometheusAlert {
"""
- The human-readable text of the alert condition
+ The human-readable text of the alert condition.
"""
humanizedText: String!
"""
- ID of the alert condition
+ ID of the alert condition.
"""
id: ID!
}
@@ -20052,7 +21410,7 @@ type PrometheusIntegrationUpdatePayload {
}
"""
-Identifier of PrometheusService
+Identifier of PrometheusService.
"""
scalar PrometheusServiceID
@@ -20108,6 +21466,11 @@ type PromoteToEpicPayload {
type Query {
"""
+ CI related settings that apply to the entire instance.
+ """
+ ciApplicationSettings: CiApplicationSettings
+
+ """
Get linted and processed contents of a CI config. Should not be requested more than once per request.
"""
ciConfig(
@@ -20128,27 +21491,27 @@ type Query {
): CiConfig
"""
- Find a container repository
+ Find a container repository.
"""
containerRepository(
"""
- The global ID of the container repository
+ The global ID of the container repository.
"""
id: ContainerRepositoryID!
): ContainerRepositoryDetails
"""
- Get information about current user
+ Get information about current user.
"""
currentUser: User
"""
- Fields related to design management
+ Fields related to design management.
"""
designManagement: DesignManagement!
"""
- Get configured DevOps adoption segments on the instance
+ Get configured DevOps adoption segments on the instance.
"""
devopsAdoptionSegments(
"""
@@ -20173,7 +21536,7 @@ type Query {
): DevopsAdoptionSegmentConnection
"""
- Text to echo back
+ Text to echo back.
"""
echo(
"""
@@ -20183,7 +21546,7 @@ type Query {
): String!
"""
- Find a Geo node
+ Find a Geo node.
"""
geoNode(
"""
@@ -20193,7 +21556,7 @@ type Query {
): GeoNode
"""
- Find a group
+ Find a group.
"""
group(
"""
@@ -20203,12 +21566,12 @@ type Query {
): Group
"""
- Fields related to Instance Security Dashboard
+ Fields related to Instance Security Dashboard.
"""
instanceSecurityDashboard: InstanceSecurityDashboard
"""
- Get statistics on the instance
+ Get statistics on the instance.
"""
instanceStatisticsMeasurements(
"""
@@ -20248,42 +21611,42 @@ type Query {
): InstanceStatisticsMeasurementConnection
"""
- Find an issue
+ Find an issue.
"""
issue(
"""
- The global ID of the Issue
+ The global ID of the Issue.
"""
id: IssueID!
): Issue
"""
- Find an iteration
+ Find an iteration.
"""
iteration(
"""
- Find an iteration by its ID
+ Find an iteration by its ID.
"""
id: IterationID!
): Iteration
"""
- Metadata about GitLab
+ Metadata about GitLab.
"""
metadata: Metadata
"""
- Find a milestone
+ Find a milestone.
"""
milestone(
"""
- Find a milestone by its ID
+ Find a milestone by its ID.
"""
id: MilestoneID!
): Milestone
"""
- Find a namespace
+ Find a namespace.
"""
namespace(
"""
@@ -20293,17 +21656,17 @@ type Query {
): Namespace
"""
- Find a composer package
+ Find a package.
"""
- packageComposerDetails(
+ package(
"""
The global ID of the package.
"""
id: PackagesPackageID!
- ): PackageComposerDetails
+ ): Package
"""
- Find a project
+ Find a project.
"""
project(
"""
@@ -20313,7 +21676,7 @@ type Query {
): Project
"""
- Find projects visible to the current user
+ Find projects visible to the current user.
"""
projects(
"""
@@ -20363,7 +21726,7 @@ type Query {
): ProjectConnection
"""
- Supported runner platforms
+ Supported runner platforms.
"""
runnerPlatforms(
"""
@@ -20388,7 +21751,7 @@ type Query {
): RunnerPlatformConnection
"""
- Get runner setup instructions
+ Get runner setup instructions.
"""
runnerSetup(
"""
@@ -20413,7 +21776,7 @@ type Query {
): RunnerSetup
"""
- Find Snippets visible to the current user
+ Find Snippets visible to the current user.
"""
snippets(
"""
@@ -20468,7 +21831,7 @@ type Query {
): SnippetConnection
"""
- Find a user
+ Find a user.
"""
user(
"""
@@ -20483,7 +21846,7 @@ type Query {
): User
"""
- Find users
+ Find users.
"""
users(
"""
@@ -20533,7 +21896,7 @@ type Query {
): UserConnection
"""
- Vulnerabilities reported on projects on the current user's instance security dashboard
+ Vulnerabilities reported on projects on the current user's instance security dashboard.
"""
vulnerabilities(
"""
@@ -20598,7 +21961,7 @@ type Query {
): VulnerabilityConnection
"""
- Number of vulnerabilities per day for the projects on the current user's instance security dashboard
+ Number of vulnerabilities per day for the projects on the current user's instance security dashboard.
"""
vulnerabilitiesCountByDay(
"""
@@ -20634,7 +21997,7 @@ type Query {
"""
Number of vulnerabilities per severity level, per day, for the projects on the
- current user's instance security dashboard Deprecated in 13.3: Use
+ current user's instance security dashboard. Deprecated in 13.3: Use
`vulnerabilitiesCountByDay`.
"""
vulnerabilitiesCountByDayAndSeverity(
@@ -20670,11 +22033,11 @@ type Query {
): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3.")
"""
- Find a vulnerability
+ Find a vulnerability.
"""
vulnerability(
"""
- The Global ID of the Vulnerability
+ The Global ID of the Vulnerability.
"""
id: VulnerabilityID!
): Vulnerability
@@ -20710,27 +22073,27 @@ Represents a release
"""
type Release {
"""
- Assets of the release
+ Assets of the release.
"""
assets: ReleaseAssets
"""
- User that created the release
+ User that created the release.
"""
author: User
"""
- The commit associated with the release
+ The commit associated with the release.
"""
commit: Commit
"""
- Timestamp of when the release was created
+ Timestamp of when the release was created.
"""
createdAt: Time
"""
- Description (also known as "release notes") of the release
+ Description (also known as "release notes") of the release.
"""
description: String
@@ -20740,7 +22103,7 @@ type Release {
descriptionHtml: String
"""
- Evidence for the release
+ Evidence for the release.
"""
evidences(
"""
@@ -20765,12 +22128,12 @@ type Release {
): ReleaseEvidenceConnection
"""
- Links of the release
+ Links of the release.
"""
links: ReleaseLinks
"""
- Milestones associated to the release
+ Milestones associated to the release.
"""
milestones(
"""
@@ -20795,27 +22158,27 @@ type Release {
): MilestoneConnection
"""
- Name of the release
+ Name of the release.
"""
name: String
"""
- Timestamp of when the release was released
+ Timestamp of when the release was released.
"""
releasedAt: Time
"""
- Name of the tag associated with the release
+ Name of the tag associated with the release.
"""
tagName: String
"""
- Relative web path to the tag associated with the release
+ Relative web path to the tag associated with the release.
"""
tagPath: String
"""
- Indicates the release is an upcoming release
+ Indicates the release is an upcoming release.
"""
upcomingRelease: Boolean
}
@@ -20825,32 +22188,32 @@ Represents an asset link associated with a release
"""
type ReleaseAssetLink {
"""
- Direct asset URL of the link
+ Direct asset URL of the link.
"""
directAssetUrl: String
"""
- Indicates the link points to an external resource
+ Indicates the link points to an external resource.
"""
external: Boolean
"""
- ID of the link
+ ID of the link.
"""
id: ID!
"""
- Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`
+ Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.
"""
linkType: ReleaseAssetLinkType
"""
- Name of the link
+ Name of the link.
"""
name: String
"""
- URL of the link
+ URL of the link.
"""
url: String
}
@@ -20895,22 +22258,22 @@ Fields that are available when modifying a release asset link
"""
input ReleaseAssetLinkInput {
"""
- Relative path for a direct asset link
+ Relative path for a direct asset link.
"""
directAssetPath: String
"""
- The type of the asset link
+ The type of the asset link.
"""
linkType: ReleaseAssetLinkType = OTHER
"""
- Name of the asset link
+ Name of the asset link.
"""
name: String!
"""
- URL of the asset link
+ URL of the asset link.
"""
url: String!
}
@@ -20945,12 +22308,12 @@ A container for all assets associated with a release
"""
type ReleaseAssets {
"""
- Number of assets of the release
+ Number of assets of the release.
"""
count: Int
"""
- Asset links of the release
+ Asset links of the release.
"""
links(
"""
@@ -20975,7 +22338,7 @@ type ReleaseAssets {
): ReleaseAssetLinkConnection
"""
- Sources of the release
+ Sources of the release.
"""
sources(
"""
@@ -21005,7 +22368,7 @@ Fields that are available when modifying release assets
"""
input ReleaseAssetsInput {
"""
- A list of asset links to associate to the release
+ A list of asset links to associate to the release.
"""
links: [ReleaseAssetLinkInput!]
}
@@ -21015,7 +22378,7 @@ The connection type for Release.
"""
type ReleaseConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -21165,22 +22528,22 @@ Evidence for a release
"""
type ReleaseEvidence {
"""
- Timestamp when the evidence was collected
+ Timestamp when the evidence was collected.
"""
collectedAt: Time
"""
- URL from where the evidence can be downloaded
+ URL from where the evidence can be downloaded.
"""
filepath: String
"""
- ID of the evidence
+ ID of the evidence.
"""
id: ID!
"""
- SHA1 ID of the evidence hash
+ SHA1 ID of the evidence hash.
"""
sha: String
}
@@ -21222,37 +22585,37 @@ type ReleaseEvidenceEdge {
type ReleaseLinks {
"""
- HTTP URL of the issues page, filtered by this release and `state=closed`
+ HTTP URL of the issues page, filtered by this release and `state=closed`.
"""
closedIssuesUrl: String
"""
- HTTP URL of the merge request page , filtered by this release and `state=closed`
+ HTTP URL of the merge request page , filtered by this release and `state=closed`.
"""
closedMergeRequestsUrl: String
"""
- HTTP URL of the release's edit page
+ HTTP URL of the release's edit page.
"""
editUrl: String
"""
- HTTP URL of the merge request page , filtered by this release and `state=merged`
+ HTTP URL of the merge request page , filtered by this release and `state=merged`.
"""
mergedMergeRequestsUrl: String
"""
- HTTP URL of the issues page, filtered by this release and `state=open`
+ HTTP URL of the issues page, filtered by this release and `state=open`.
"""
openedIssuesUrl: String
"""
- HTTP URL of the merge request page, filtered by this release and `state=open`
+ HTTP URL of the merge request page, filtered by this release and `state=open`.
"""
openedMergeRequestsUrl: String
"""
- HTTP URL of the release
+ HTTP URL of the release.
"""
selfUrl: String
}
@@ -21287,12 +22650,12 @@ Represents the source code attached to a release in a particular format
"""
type ReleaseSource {
"""
- Format of the source
+ Format of the source.
"""
format: String
"""
- Download URL of the source
+ Download URL of the source.
"""
url: String
}
@@ -21407,7 +22770,7 @@ input RemoveAwardEmojiInput {
clientMutationId: String
"""
- The emoji name
+ The emoji name.
"""
name: String!
}
@@ -21477,7 +22840,7 @@ input RepositionImageDiffNoteInput {
id: DiffNoteID!
"""
- The position of this note on a diff
+ The position of this note on a diff.
"""
position: UpdateDiffImagePositionInput!
}
@@ -21504,22 +22867,22 @@ type RepositionImageDiffNotePayload {
type Repository {
"""
- Indicates repository has no visible content
+ Indicates repository has no visible content.
"""
empty: Boolean!
"""
- Indicates a corresponding Git repository exists on disk
+ Indicates a corresponding Git repository exists on disk.
"""
exists: Boolean!
"""
- Default branch of the repository
+ Default branch of the repository.
"""
rootRef: String
"""
- Tree of the repository
+ Tree of the repository.
"""
tree(
"""
@@ -21544,17 +22907,17 @@ Represents a requirement
"""
type Requirement {
"""
- Author of the requirement
+ Author of the requirement.
"""
author: User!
"""
- Timestamp of when the requirement was created
+ Timestamp of when the requirement was created.
"""
createdAt: Time!
"""
- Description of the requirement
+ Description of the requirement.
"""
description: String
@@ -21564,37 +22927,37 @@ type Requirement {
descriptionHtml: String
"""
- ID of the requirement
+ ID of the requirement.
"""
id: ID!
"""
- Internal ID of the requirement
+ Internal ID of the requirement.
"""
iid: ID!
"""
- Indicates if latest test report was created by user
+ Indicates if latest test report was created by user.
"""
lastTestReportManuallyCreated: Boolean
"""
- Latest requirement test report state
+ Latest requirement test report state.
"""
lastTestReportState: TestReportState
"""
- Project to which the requirement belongs
+ Project to which the requirement belongs.
"""
project: Project!
"""
- State of the requirement
+ State of the requirement.
"""
state: RequirementState!
"""
- Test reports of the requirement
+ Test reports of the requirement.
"""
testReports(
"""
@@ -21624,7 +22987,7 @@ type Requirement {
): TestReportConnection
"""
- Title of the requirement
+ Title of the requirement.
"""
title: String
@@ -21634,7 +22997,7 @@ type Requirement {
titleHtml: String
"""
- Timestamp of when the requirement was last updated
+ Timestamp of when the requirement was last updated.
"""
updatedAt: Time!
@@ -21722,34 +23085,34 @@ Counts of requirements by their state
"""
type RequirementStatesCount {
"""
- Number of archived requirements
+ Number of archived requirements.
"""
archived: Int
"""
- Number of opened requirements
+ Number of opened requirements.
"""
opened: Int
}
interface ResolvableInterface {
"""
- Indicates if the object can be resolved
+ Indicates if the object can be resolved.
"""
resolvable: Boolean!
"""
- Indicates if the object is resolved
+ Indicates if the object is resolved.
"""
resolved: Boolean!
"""
- Timestamp of when the object was resolved
+ Timestamp of when the object was resolved.
"""
resolvedAt: Time
"""
- User who resolved the object
+ User who resolved the object.
"""
resolvedBy: User
}
@@ -21791,47 +23154,47 @@ type RevertVulnerabilityToDetectedPayload {
type RootStorageStatistics {
"""
- The CI artifacts size in bytes
+ The CI artifacts size in bytes.
"""
buildArtifactsSize: Float!
"""
- The LFS objects size in bytes
+ The LFS objects size in bytes.
"""
lfsObjectsSize: Float!
"""
- The packages size in bytes
+ The packages size in bytes.
"""
packagesSize: Float!
"""
- The CI pipeline artifacts size in bytes
+ The CI pipeline artifacts size in bytes.
"""
pipelineArtifactsSize: Float!
"""
- The Git repository size in bytes
+ The Git repository size in bytes.
"""
repositorySize: Float!
"""
- The snippets size in bytes
+ The snippets size in bytes.
"""
snippetsSize: Float!
"""
- The total storage in bytes
+ The total storage in bytes.
"""
storageSize: Float!
"""
- The uploads size in bytes
+ The uploads size in bytes.
"""
uploadsSize: Float!
"""
- The wiki size in bytes
+ The wiki size in bytes.
"""
wikiSize: Float!
}
@@ -21888,12 +23251,12 @@ type RunDASTScanPayload {
type RunnerArchitecture {
"""
- Download location for the runner for the platform architecture
+ Download location for the runner for the platform architecture.
"""
downloadLocation: String!
"""
- Name of the runner platform architecture
+ Name of the runner platform architecture.
"""
name: String!
}
@@ -21935,7 +23298,7 @@ type RunnerArchitectureEdge {
type RunnerPlatform {
"""
- Runner architectures supported for the platform
+ Runner architectures supported for the platform.
"""
architectures(
"""
@@ -21960,12 +23323,12 @@ type RunnerPlatform {
): RunnerArchitectureConnection
"""
- Human readable name of the runner platform
+ Human readable name of the runner platform.
"""
humanReadableName: String!
"""
- Name slug of the runner platform
+ Name slug of the runner platform.
"""
name: String!
}
@@ -22007,12 +23370,12 @@ type RunnerPlatformEdge {
type RunnerSetup {
"""
- Instructions for installing the runner on the specified architecture
+ Instructions for installing the runner on the specified architecture.
"""
installInstructions: String!
"""
- Instructions for registering the runner
+ Instructions for registering the runner.
"""
registerInstructions: String
}
@@ -22102,27 +23465,27 @@ Represents an analyzer entity in SAST CI configuration
"""
type SastCiConfigurationAnalyzersEntity {
"""
- Analyzer description that is displayed on the form
+ Analyzer description that is displayed on the form.
"""
description: String
"""
- Indicates whether an analyzer is enabled
+ Indicates whether an analyzer is enabled.
"""
enabled: Boolean
"""
- Analyzer label used in the config UI
+ Analyzer label used in the config UI.
"""
label: String
"""
- Name of the analyzer
+ Name of the analyzer.
"""
name: String
"""
- List of supported variables
+ List of supported variables.
"""
variables(
"""
@@ -22187,17 +23550,17 @@ Represents the analyzers entity in SAST CI configuration
"""
input SastCiConfigurationAnalyzersEntityInput {
"""
- State of the analyzer
+ State of the analyzer.
"""
enabled: Boolean!
"""
- Name of analyzer
+ Name of analyzer.
"""
name: String!
"""
- List of variables for the analyzer
+ List of variables for the analyzer.
"""
variables: [SastCiConfigurationEntityInput!]
}
@@ -22307,17 +23670,17 @@ Represents an entity in SAST CI configuration
"""
input SastCiConfigurationEntityInput {
"""
- Default value that is used if value is empty
+ Default value that is used if value is empty.
"""
defaultValue: String!
"""
- CI keyword of entity
+ CI keyword of entity.
"""
field: String!
"""
- Current value of the entity
+ Current value of the entity.
"""
value: String!
}
@@ -22327,17 +23690,17 @@ Represents a CI configuration of SAST
"""
input SastCiConfigurationInput {
"""
- List of analyzers and related variables for the SAST configuration
+ List of analyzers and related variables for the SAST configuration.
"""
analyzers: [SastCiConfigurationAnalyzersEntityInput!]
"""
- List of global entities related to SAST configuration
+ List of global entities related to SAST configuration.
"""
global: [SastCiConfigurationEntityInput!]
"""
- List of pipeline entities related to SAST configuration
+ List of pipeline entities related to SAST configuration.
"""
pipeline: [SastCiConfigurationEntityInput!]
}
@@ -22406,12 +23769,12 @@ Represents a resource scanned by a security scan
"""
type ScannedResource {
"""
- The HTTP request method used to access the URL
+ The HTTP request method used to access the URL.
"""
requestMethod: String
"""
- The URL scanned by the scanner
+ The URL scanned by the scanner.
"""
url: String
}
@@ -22456,37 +23819,37 @@ Represents summary of a security report
"""
type SecurityReportSummary {
"""
- Aggregated counts for the api_fuzzing scan
+ Aggregated counts for the `api_fuzzing` scan
"""
apiFuzzing: SecurityReportSummarySection
"""
- Aggregated counts for the container_scanning scan
+ Aggregated counts for the `container_scanning` scan
"""
containerScanning: SecurityReportSummarySection
"""
- Aggregated counts for the coverage_fuzzing scan
+ Aggregated counts for the `coverage_fuzzing` scan
"""
coverageFuzzing: SecurityReportSummarySection
"""
- Aggregated counts for the dast scan
+ Aggregated counts for the `dast` scan
"""
dast: SecurityReportSummarySection
"""
- Aggregated counts for the dependency_scanning scan
+ Aggregated counts for the `dependency_scanning` scan
"""
dependencyScanning: SecurityReportSummarySection
"""
- Aggregated counts for the sast scan
+ Aggregated counts for the `sast` scan
"""
sast: SecurityReportSummarySection
"""
- Aggregated counts for the secret_detection scan
+ Aggregated counts for the `secret_detection` scan
"""
secretDetection: SecurityReportSummarySection
}
@@ -22496,7 +23859,7 @@ Represents a section of a summary of a security report
"""
type SecurityReportSummarySection {
"""
- A list of the first 20 scanned resources
+ A list of the first 20 scanned resources.
"""
scannedResources(
"""
@@ -22521,17 +23884,17 @@ type SecurityReportSummarySection {
): ScannedResourceConnection
"""
- Total number of scanned resources
+ Total number of scanned resources.
"""
scannedResourcesCount: Int
"""
- Path to download all the scanned resources in CSV format
+ Path to download all the scanned resources in CSV format.
"""
scannedResourcesCsvPath: String
"""
- Total number of vulnerabilities
+ Total number of vulnerabilities.
"""
vulnerabilitiesCount: Int
}
@@ -22611,142 +23974,142 @@ A Sentry error
"""
type SentryDetailedError {
"""
- Count of occurrences
+ Count of occurrences.
"""
count: Int!
"""
- Culprit of the error
+ Culprit of the error.
"""
culprit: String!
"""
- External Base URL of the Sentry Instance
+ External Base URL of the Sentry Instance.
"""
externalBaseUrl: String!
"""
- External URL of the error
+ External URL of the error.
"""
externalUrl: String!
"""
- Commit the error was first seen
+ Commit the error was first seen.
"""
firstReleaseLastCommit: String
"""
- Release short version the error was first seen
+ Release short version the error was first seen.
"""
firstReleaseShortVersion: String
"""
- Release version the error was first seen
+ Release version the error was first seen.
"""
firstReleaseVersion: String
"""
- Timestamp when the error was first seen
+ Timestamp when the error was first seen.
"""
firstSeen: Time!
"""
- Last 24hr stats of the error
+ Last 24hr stats of the error.
"""
frequency: [SentryErrorFrequency!]!
"""
- GitLab commit SHA attributed to the Error based on the release version
+ GitLab commit SHA attributed to the Error based on the release version.
"""
gitlabCommit: String
"""
- Path to the GitLab page for the GitLab commit attributed to the error
+ Path to the GitLab page for the GitLab commit attributed to the error.
"""
gitlabCommitPath: String
"""
- URL of GitLab Issue
+ URL of GitLab Issue.
"""
gitlabIssuePath: String
"""
- ID (global ID) of the error
+ ID (global ID) of the error.
"""
id: ID!
"""
- Commit the error was last seen
+ Commit the error was last seen.
"""
lastReleaseLastCommit: String
"""
- Release short version the error was last seen
+ Release short version the error was last seen.
"""
lastReleaseShortVersion: String
"""
- Release version the error was last seen
+ Release version the error was last seen.
"""
lastReleaseVersion: String
"""
- Timestamp when the error was last seen
+ Timestamp when the error was last seen.
"""
lastSeen: Time!
"""
- Sentry metadata message of the error
+ Sentry metadata message of the error.
"""
message: String
"""
- ID (Sentry ID) of the error
+ ID (Sentry ID) of the error.
"""
sentryId: String!
"""
- ID of the project (Sentry project)
+ ID of the project (Sentry project).
"""
sentryProjectId: ID!
"""
- Name of the project affected by the error
+ Name of the project affected by the error.
"""
sentryProjectName: String!
"""
- Slug of the project affected by the error
+ Slug of the project affected by the error.
"""
sentryProjectSlug: String!
"""
- Short ID (Sentry ID) of the error
+ Short ID (Sentry ID) of the error.
"""
shortId: String!
"""
- Status of the error
+ Status of the error.
"""
status: SentryErrorStatus!
"""
- Tags associated with the Sentry Error
+ Tags associated with the Sentry Error.
"""
tags: SentryErrorTags!
"""
- Title of the error
+ Title of the error.
"""
title: String!
"""
- Type of the error
+ Type of the error.
"""
type: String!
"""
- Count of users affected by the error
+ Count of users affected by the error.
"""
userCount: Int!
}
@@ -22756,87 +24119,87 @@ A Sentry error. A simplified version of SentryDetailedError
"""
type SentryError {
"""
- Count of occurrences
+ Count of occurrences.
"""
count: Int!
"""
- Culprit of the error
+ Culprit of the error.
"""
culprit: String!
"""
- External URL of the error
+ External URL of the error.
"""
externalUrl: String!
"""
- Timestamp when the error was first seen
+ Timestamp when the error was first seen.
"""
firstSeen: Time!
"""
- Last 24hr stats of the error
+ Last 24hr stats of the error.
"""
frequency: [SentryErrorFrequency!]!
"""
- ID (global ID) of the error
+ ID (global ID) of the error.
"""
id: ID!
"""
- Timestamp when the error was last seen
+ Timestamp when the error was last seen.
"""
lastSeen: Time!
"""
- Sentry metadata message of the error
+ Sentry metadata message of the error.
"""
message: String
"""
- ID (Sentry ID) of the error
+ ID (Sentry ID) of the error.
"""
sentryId: String!
"""
- ID of the project (Sentry project)
+ ID of the project (Sentry project).
"""
sentryProjectId: ID!
"""
- Name of the project affected by the error
+ Name of the project affected by the error.
"""
sentryProjectName: String!
"""
- Slug of the project affected by the error
+ Slug of the project affected by the error.
"""
sentryProjectSlug: String!
"""
- Short ID (Sentry ID) of the error
+ Short ID (Sentry ID) of the error.
"""
shortId: String!
"""
- Status of the error
+ Status of the error.
"""
status: SentryErrorStatus!
"""
- Title of the error
+ Title of the error.
"""
title: String!
"""
- Type of the error
+ Type of the error.
"""
type: String!
"""
- Count of users affected by the error
+ Count of users affected by the error.
"""
userCount: Int!
}
@@ -22846,7 +24209,7 @@ An object containing a collection of Sentry errors, and a detailed error
"""
type SentryErrorCollection {
"""
- Detailed version of a Sentry error on the project
+ Detailed version of a Sentry error on the project.
"""
detailedError(
"""
@@ -22856,7 +24219,7 @@ type SentryErrorCollection {
): SentryDetailedError
"""
- Stack Trace of Sentry Error
+ Stack Trace of Sentry Error.
"""
errorStackTrace(
"""
@@ -22866,7 +24229,7 @@ type SentryErrorCollection {
): SentryErrorStackTrace
"""
- Collection of Sentry Errors
+ Collection of Sentry Errors.
"""
errors(
"""
@@ -22901,7 +24264,7 @@ type SentryErrorCollection {
): SentryErrorConnection
"""
- External URL for Sentry
+ External URL for Sentry.
"""
externalUrl: String
}
@@ -22943,12 +24306,12 @@ type SentryErrorEdge {
type SentryErrorFrequency {
"""
- Count of errors received since the previously recorded time
+ Count of errors received since the previously recorded time.
"""
count: Int!
"""
- Time the error frequency stats were recorded
+ Time the error frequency stats were recorded.
"""
time: Time!
}
@@ -22958,17 +24321,17 @@ An object containing a stack trace entry for a Sentry error
"""
type SentryErrorStackTrace {
"""
- Time the stack trace was received by Sentry
+ Time the stack trace was received by Sentry.
"""
dateReceived: String!
"""
- ID of the Sentry error
+ ID of the Sentry error.
"""
issueId: String!
"""
- Stack trace entries for the Sentry error
+ Stack trace entries for the Sentry error.
"""
stackTraceEntries: [SentryErrorStackTraceEntry!]!
}
@@ -22978,12 +24341,12 @@ An object context for a Sentry error stack trace
"""
type SentryErrorStackTraceContext {
"""
- Code number of the context
+ Code number of the context.
"""
code: String!
"""
- Line number of the context
+ Line number of the context.
"""
line: Int!
}
@@ -22993,27 +24356,27 @@ An object containing a stack trace entry for a Sentry error
"""
type SentryErrorStackTraceEntry {
"""
- Function in which the Sentry error occurred
+ Function in which the Sentry error occurred.
"""
col: String
"""
- File in which the Sentry error occurred
+ File in which the Sentry error occurred.
"""
fileName: String
"""
- Function in which the Sentry error occurred
+ Function in which the Sentry error occurred.
"""
function: String
"""
- Function in which the Sentry error occurred
+ Function in which the Sentry error occurred.
"""
line: String
"""
- Context of the Sentry error
+ Context of the Sentry error.
"""
traceContext: [SentryErrorStackTraceContext!]
}
@@ -23048,24 +24411,24 @@ State of a Sentry error
"""
type SentryErrorTags {
"""
- Severity level of the Sentry Error
+ Severity level of the Sentry Error.
"""
level: String
"""
- Logger of the Sentry Error
+ Logger of the Sentry Error.
"""
logger: String
}
interface Service {
"""
- Indicates if the service is active
+ Indicates if the service is active.
"""
active: Boolean
"""
- Class name of the service
+ Class name of the service.
"""
type: String
}
@@ -23106,41 +24469,184 @@ type ServiceEdge {
}
enum ServiceType {
+ """
+ AsanaService type
+ """
ASANA_SERVICE
+
+ """
+ AssemblaService type
+ """
ASSEMBLA_SERVICE
+
+ """
+ BambooService type
+ """
BAMBOO_SERVICE
+
+ """
+ BugzillaService type
+ """
BUGZILLA_SERVICE
+
+ """
+ BuildkiteService type
+ """
BUILDKITE_SERVICE
+
+ """
+ CampfireService type
+ """
CAMPFIRE_SERVICE
+
+ """
+ ConfluenceService type
+ """
CONFLUENCE_SERVICE
+
+ """
+ CustomIssueTrackerService type
+ """
CUSTOM_ISSUE_TRACKER_SERVICE
+
+ """
+ DatadogService type
+ """
DATADOG_SERVICE
+
+ """
+ DiscordService type
+ """
DISCORD_SERVICE
+
+ """
+ DroneCiService type
+ """
DRONE_CI_SERVICE
+
+ """
+ EmailsOnPushService type
+ """
EMAILS_ON_PUSH_SERVICE
+
+ """
+ EwmService type
+ """
EWM_SERVICE
+
+ """
+ ExternalWikiService type
+ """
EXTERNAL_WIKI_SERVICE
+
+ """
+ FlowdockService type
+ """
FLOWDOCK_SERVICE
+
+ """
+ GithubService type
+ """
GITHUB_SERVICE
+
+ """
+ HangoutsChatService type
+ """
HANGOUTS_CHAT_SERVICE
+
+ """
+ HipchatService type
+ """
HIPCHAT_SERVICE
+
+ """
+ IrkerService type
+ """
IRKER_SERVICE
+
+ """
+ JenkinsService type
+ """
JENKINS_SERVICE
+
+ """
+ JiraService type
+ """
JIRA_SERVICE
+
+ """
+ MattermostService type
+ """
MATTERMOST_SERVICE
+
+ """
+ MattermostSlashCommandsService type
+ """
MATTERMOST_SLASH_COMMANDS_SERVICE
+
+ """
+ MicrosoftTeamsService type
+ """
MICROSOFT_TEAMS_SERVICE
+
+ """
+ PackagistService type
+ """
PACKAGIST_SERVICE
+
+ """
+ PipelinesEmailService type
+ """
PIPELINES_EMAIL_SERVICE
+
+ """
+ PivotaltrackerService type
+ """
PIVOTALTRACKER_SERVICE
+
+ """
+ PrometheusService type
+ """
PROMETHEUS_SERVICE
+
+ """
+ PushoverService type
+ """
PUSHOVER_SERVICE
+
+ """
+ RedmineService type
+ """
REDMINE_SERVICE
+
+ """
+ SlackService type
+ """
SLACK_SERVICE
+
+ """
+ SlackSlashCommandsService type
+ """
SLACK_SLASH_COMMANDS_SERVICE
+
+ """
+ TeamcityService type
+ """
TEAMCITY_SERVICE
+
+ """
+ UnifyCircuitService type
+ """
UNIFY_CIRCUIT_SERVICE
+
+ """
+ WebexTeamsService type
+ """
WEBEX_TEAMS_SERVICE
+
+ """
+ YoutrackService type
+ """
YOUTRACK_SERVICE
}
@@ -23149,17 +24655,17 @@ Represents a snippet entry
"""
type Snippet implements Noteable {
"""
- The owner of the snippet
+ The owner of the snippet.
"""
author: User
"""
- Snippet blob Deprecated in 13.3: Use `blobs`.
+ Snippet blob. Deprecated in 13.3: Use `blobs`.
"""
blob: SnippetBlob! @deprecated(reason: "Use `blobs`. Deprecated in 13.3.")
"""
- Snippet blobs
+ Snippet blobs.
"""
blobs(
"""
@@ -23189,12 +24695,12 @@ type Snippet implements Noteable {
): SnippetBlobConnection
"""
- Timestamp this snippet was created
+ Timestamp this snippet was created.
"""
createdAt: Time!
"""
- Description of the snippet
+ Description of the snippet.
"""
description: String
@@ -23204,7 +24710,7 @@ type Snippet implements Noteable {
descriptionHtml: String
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -23229,22 +24735,22 @@ type Snippet implements Noteable {
): DiscussionConnection!
"""
- File Name of the snippet
+ File Name of the snippet.
"""
fileName: String
"""
- HTTP URL to the snippet repository
+ HTTP URL to the snippet repository.
"""
httpUrlToRepo: String
"""
- ID of the snippet
+ ID of the snippet.
"""
id: SnippetID!
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -23269,27 +24775,27 @@ type Snippet implements Noteable {
): NoteConnection!
"""
- The project the snippet is associated with
+ The project the snippet is associated with.
"""
project: Project
"""
- Raw URL of the snippet
+ Raw URL of the snippet.
"""
rawUrl: String!
"""
- SSH URL to the snippet repository
+ SSH URL to the snippet repository.
"""
sshUrlToRepo: String
"""
- Title of the snippet
+ Title of the snippet.
"""
title: String!
"""
- Timestamp this snippet was updated
+ Timestamp this snippet was updated.
"""
updatedAt: Time!
@@ -23299,12 +24805,12 @@ type Snippet implements Noteable {
userPermissions: SnippetPermissions!
"""
- Visibility Level of the snippet
+ Visibility Level of the snippet.
"""
visibilityLevel: VisibilityLevelsEnum!
"""
- Web URL of the snippet
+ Web URL of the snippet.
"""
webUrl: String!
}
@@ -23314,62 +24820,62 @@ Represents the snippet blob
"""
type SnippetBlob {
"""
- Shows whether the blob is binary
+ Shows whether the blob is binary.
"""
binary: Boolean!
"""
- Blob external storage
+ Blob external storage.
"""
externalStorage: String
"""
- Blob mode
+ Blob mode.
"""
mode: String
"""
- Blob name
+ Blob name.
"""
name: String
"""
- Blob path
+ Blob path.
"""
path: String
"""
- Blob plain highlighted data
+ Blob plain highlighted data.
"""
plainData: String
"""
- Blob raw content endpoint path
+ Blob raw content endpoint path.
"""
rawPath: String!
"""
- Shows whether the blob is rendered as text
+ Shows whether the blob is rendered as text.
"""
renderedAsText: Boolean!
"""
- Blob highlighted data
+ Blob highlighted data.
"""
richData: String
"""
- Blob content rich viewer
+ Blob content rich viewer.
"""
richViewer: SnippetBlobViewer
"""
- Blob content simple viewer
+ Blob content simple viewer.
"""
simpleViewer: SnippetBlobViewer!
"""
- Blob size
+ Blob size.
"""
size: Int!
}
@@ -23389,22 +24895,22 @@ Represents an action to perform over a snippet file
"""
input SnippetBlobActionInputType {
"""
- Type of input action
+ Type of input action.
"""
action: SnippetBlobActionEnum!
"""
- Snippet file content
+ Snippet file content.
"""
content: String
"""
- Path of the snippet file
+ Path of the snippet file.
"""
filePath: String!
"""
- Previous path of the snippet file
+ Previous path of the snippet file.
"""
previousPath: String
}
@@ -23449,37 +24955,37 @@ Represents how the blob content should be displayed
"""
type SnippetBlobViewer {
"""
- Shows whether the blob should be displayed collapsed
+ Shows whether the blob should be displayed collapsed.
"""
collapsed: Boolean!
"""
- Content file type
+ Content file type.
"""
fileType: String!
"""
- Shows whether the blob content is loaded async
+ Shows whether the blob content is loaded asynchronously.
"""
loadAsync: Boolean!
"""
- Loading partial name
+ Loading partial name.
"""
loadingPartialName: String!
"""
- Error rendering the blob content
+ Error rendering the blob content.
"""
renderError: String
"""
- Shows whether the blob too large to be displayed
+ Shows whether the blob too large to be displayed.
"""
tooLarge: Boolean!
"""
- Type of blob viewer
+ Type of blob viewer.
"""
type: BlobViewersType!
}
@@ -23520,7 +25026,7 @@ type SnippetEdge {
}
"""
-Identifier of Snippet
+Identifier of Snippet.
"""
scalar SnippetID
@@ -23591,7 +25097,7 @@ type SnippetRepositoryRegistry {
retryCount: Int
"""
- ID of the Snippet Repository
+ ID of the Snippet Repository.
"""
snippetRepositoryId: ID!
@@ -23683,69 +25189,69 @@ enum Sort {
type StatusAction {
"""
- Title for the button, for example: Retry this job
+ Title for the button, for example: Retry this job.
"""
buttonTitle: String
"""
- Icon used in the action button
+ Icon used in the action button.
"""
icon: String
"""
- Method for the action, for example: :post
+ Method for the action, for example: :post.
"""
method: String
"""
- Path for the action
+ Path for the action.
"""
path: String
"""
- Title for the action, for example: Retry
+ Title for the action, for example: Retry.
"""
title: String
}
type Submodule implements Entry {
"""
- Flat path of the entry
+ Flat path of the entry.
"""
flatPath: String!
"""
- ID of the entry
+ ID of the entry.
"""
id: ID!
"""
- Name of the entry
+ Name of the entry.
"""
name: String!
"""
- Path of the entry
+ Path of the entry.
"""
path: String!
"""
- Last commit sha for the entry
+ Last commit SHA for the entry.
"""
sha: String!
"""
- Tree URL for the sub-module
+ Tree URL for the sub-module.
"""
treeUrl: String
"""
- Type of tree entry
+ Type of tree entry.
"""
type: EntryType!
"""
- Web URL for the sub-module
+ Web URL for the sub-module.
"""
webUrl: String
}
@@ -23790,49 +25296,49 @@ Completion status of tasks
"""
type TaskCompletionStatus {
"""
- Number of completed tasks
+ Number of completed tasks.
"""
completedCount: Int!
"""
- Number of total tasks
+ Number of total tasks.
"""
count: Int!
}
type TerraformState {
"""
- Timestamp the Terraform state was created
+ Timestamp the Terraform state was created.
"""
createdAt: Time!
"""
- ID of the Terraform state
+ ID of the Terraform state.
"""
id: ID!
"""
- The latest version of the Terraform state
+ The latest version of the Terraform state.
"""
latestVersion: TerraformStateVersion
"""
- Timestamp the Terraform state was locked
+ Timestamp the Terraform state was locked.
"""
lockedAt: Time
"""
- The user currently holding a lock on the Terraform state
+ The user currently holding a lock on the Terraform state.
"""
lockedByUser: User
"""
- Name of the Terraform state
+ Name of the Terraform state.
"""
name: String!
"""
- Timestamp the Terraform state was updated
+ Timestamp the Terraform state was updated.
"""
updatedAt: Time!
}
@@ -23842,7 +25348,7 @@ The connection type for TerraformState.
"""
type TerraformStateConnection {
"""
- Total count of collection
+ Total count of collection.
"""
count: Int!
@@ -23908,7 +25414,7 @@ type TerraformStateEdge {
}
"""
-Identifier of Terraform::State
+Identifier of Terraform::State.
"""
scalar TerraformStateID
@@ -23974,37 +25480,37 @@ type TerraformStateUnlockPayload {
type TerraformStateVersion {
"""
- Timestamp the version was created
+ Timestamp the version was created.
"""
createdAt: Time!
"""
- The user that created this version
+ The user that created this version.
"""
createdByUser: User
"""
- URL for downloading the version's JSON file
+ URL for downloading the version's JSON file.
"""
downloadPath: String
"""
- ID of the Terraform state version
+ ID of the Terraform state version.
"""
id: ID!
"""
- The job that created this version
+ The job that created this version.
"""
job: CiJob
"""
- Serial number of the version
+ Serial number of the version.
"""
serial: Int
"""
- Timestamp the version was updated
+ Timestamp the version was updated.
"""
updatedAt: Time!
}
@@ -24049,7 +25555,7 @@ type TerraformStateVersionRegistry {
state: RegistryState
"""
- ID of the terraform state version
+ ID of the terraform state version.
"""
terraformStateVersionId: ID!
}
@@ -24094,22 +25600,22 @@ Represents a requirement test report
"""
type TestReport {
"""
- Author of the test report
+ Author of the test report.
"""
author: User
"""
- Timestamp of when the test report was created
+ Timestamp of when the test report was created.
"""
createdAt: Time!
"""
- ID of the test report
+ ID of the test report.
"""
id: ID!
"""
- State of the test report
+ State of the test report.
"""
state: TestReportState!
}
@@ -24167,17 +25673,17 @@ Represents the time report stats for timeboxes
"""
type TimeReportStats {
"""
- Completed issues metrics
+ Completed issues metrics.
"""
complete: TimeboxMetrics
"""
- Incomplete issues metrics
+ Incomplete issues metrics.
"""
incomplete: TimeboxMetrics
"""
- Total issues metrics
+ Total issues metrics.
"""
total: TimeboxMetrics
}
@@ -24187,12 +25693,12 @@ Represents measured stats metrics for timeboxes
"""
type TimeboxMetrics {
"""
- The count metric
+ The count metric.
"""
count: Int!
"""
- The weight metric
+ The weight metric.
"""
weight: Int!
}
@@ -24202,19 +25708,19 @@ Represents a historically accurate report about the timebox
"""
type TimeboxReport {
"""
- Daily scope and completed totals for burnup charts
+ Daily scope and completed totals for burnup charts.
"""
burnupTimeSeries: [BurnupChartDailyTotals!]
"""
- Represents the time report stats for the timebox
+ Represents the time report stats for the timebox.
"""
stats: TimeReportStats
}
interface TimeboxReportInterface {
"""
- Historically accurate report about the timebox
+ Historically accurate report about the timebox.
"""
report: TimeboxReport
}
@@ -24224,39 +25730,39 @@ A time-frame defined as a closed inclusive range of two dates
"""
input Timeframe {
"""
- The end of the range
+ The end of the range.
"""
end: Date!
"""
- The start of the range
+ The start of the range.
"""
start: Date!
}
type Timelog {
"""
- The issue that logged time was added to
+ The issue that logged time was added to.
"""
issue: Issue
"""
- The note where the quick action to add the logged time was executed
+ The note where the quick action to add the logged time was executed.
"""
note: Note
"""
- Timestamp of when the time tracked was spent at
+ Timestamp of when the time tracked was spent at.
"""
spentAt: Time
"""
- The time spent displayed in seconds
+ The time spent displayed in seconds.
"""
timeSpent: Int!
"""
- The user that logged the time
+ The user that logged the time.
"""
user: User!
}
@@ -24297,51 +25803,51 @@ type TimelogEdge {
}
"""
-Representing a todo entry
+Representing a to-do entry
"""
type Todo {
"""
- Action of the todo
+ Action of the to-do item.
"""
action: TodoActionEnum!
"""
- The author of this todo
+ The author of this to-do item.
"""
author: User!
"""
- Body of the todo
+ Body of the to-do item.
"""
body: String!
"""
- Timestamp this todo was created
+ Timestamp this to-do item was created.
"""
createdAt: Time!
"""
- Group this todo is associated with
+ Group this to-do item is associated with.
"""
group: Group
"""
- ID of the todo
+ ID of the to-do item.
"""
id: ID!
"""
- The project this todo is associated with
+ The project this to-do item is associated with.
"""
project: Project
"""
- State of the todo
+ State of the to-do item.
"""
state: TodoStateEnum!
"""
- Target type of the todo
+ Target type of the to-do item.
"""
targetType: TodoTargetEnum!
}
@@ -24406,7 +25912,7 @@ type TodoCreatePayload {
errors: [String!]!
"""
- The to-do created.
+ The to-do item created.
"""
todo: Todo
}
@@ -24427,7 +25933,7 @@ type TodoEdge {
}
"""
-Identifier of Todo
+Identifier of Todo.
"""
scalar TodoID
@@ -24441,7 +25947,7 @@ input TodoMarkDoneInput {
clientMutationId: String
"""
- The global ID of the todo to mark as done.
+ The global ID of the to-do item to mark as done.
"""
id: TodoID!
}
@@ -24461,7 +25967,7 @@ type TodoMarkDonePayload {
errors: [String!]!
"""
- The requested todo.
+ The requested to-do item.
"""
todo: Todo!
}
@@ -24476,7 +25982,7 @@ input TodoRestoreInput {
clientMutationId: String
"""
- The global ID of the todo to restore.
+ The global ID of the to-do item to restore.
"""
id: TodoID!
}
@@ -24491,7 +25997,7 @@ input TodoRestoreManyInput {
clientMutationId: String
"""
- The global IDs of the todos to restore (a maximum of 50 is supported at once).
+ The global IDs of the to-do items to restore (a maximum of 50 is supported at once).
"""
ids: [TodoID!]!
}
@@ -24511,14 +26017,14 @@ type TodoRestoreManyPayload {
errors: [String!]!
"""
- Updated todos.
+ Updated to-do items.
"""
todos: [Todo!]!
"""
- The IDs of the updated todo items. Deprecated in 13.2: Use todos.
+ The IDs of the updated to-do items. Deprecated in 13.2: Use to-do items.
"""
- updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2.")
+ updatedIds: [TodoID!]! @deprecated(reason: "Use to-do items. Deprecated in 13.2.")
}
"""
@@ -24536,7 +26042,7 @@ type TodoRestorePayload {
errors: [String!]!
"""
- The requested todo.
+ The requested to-do item.
"""
todo: Todo!
}
@@ -24579,7 +26085,7 @@ enum TodoTargetEnum {
}
"""
-Identifier of Todoable
+Identifier of Todoable.
"""
scalar TodoableID
@@ -24608,14 +26114,14 @@ type TodosMarkAllDonePayload {
errors: [String!]!
"""
- Updated todos.
+ Updated to-do items.
"""
todos: [Todo!]!
"""
- Ids of the updated todos. Deprecated in 13.2: Use todos.
+ IDs of the updated to-do items. Deprecated in 13.2: Use to-do items.
"""
- updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2.")
+ updatedIds: [TodoID!]! @deprecated(reason: "Use to-do items. Deprecated in 13.2.")
}
"""
@@ -24633,7 +26139,7 @@ input ToggleAwardEmojiInput {
clientMutationId: String
"""
- The emoji name
+ The emoji name.
"""
name: String!
}
@@ -24665,7 +26171,7 @@ type ToggleAwardEmojiPayload {
type Tree {
"""
- Blobs of the tree
+ Blobs of the tree.
"""
blobs(
"""
@@ -24690,12 +26196,12 @@ type Tree {
): BlobConnection!
"""
- Last commit for the tree
+ Last commit for the tree.
"""
lastCommit: Commit
"""
- Sub-modules of the tree
+ Sub-modules of the tree.
"""
submodules(
"""
@@ -24720,7 +26226,7 @@ type Tree {
): SubmoduleConnection!
"""
- Trees of the tree
+ Trees of the tree.
"""
trees(
"""
@@ -24750,42 +26256,42 @@ Represents a directory
"""
type TreeEntry implements Entry {
"""
- Flat path of the entry
+ Flat path of the entry.
"""
flatPath: String!
"""
- ID of the entry
+ ID of the entry.
"""
id: ID!
"""
- Name of the entry
+ Name of the entry.
"""
name: String!
"""
- Path of the entry
+ Path of the entry.
"""
path: String!
"""
- Last commit sha for the entry
+ Last commit SHA for the entry.
"""
sha: String!
"""
- Type of tree entry
+ Type of tree entry.
"""
type: EntryType!
"""
- Web path for the tree entry (directory)
+ Web path for the tree entry (directory).
"""
webPath: String
"""
- Web URL for the tree entry (directory)
+ Web URL for the tree entry (directory).
"""
webUrl: String
}
@@ -24885,7 +26391,7 @@ type UpdateAlertStatusPayload {
issue: Issue
"""
- The todo after mutation.
+ The to-do item after mutation.
"""
todo: Todo
}
@@ -24950,12 +26456,12 @@ input UpdateBoardInput {
clientMutationId: String
"""
- Whether or not backlog list is hidden
+ Whether or not backlog list is hidden.
"""
hideBacklogList: Boolean
"""
- Whether or not closed list is hidden
+ Whether or not closed list is hidden.
"""
hideClosedList: Boolean
@@ -24975,7 +26481,7 @@ input UpdateBoardInput {
labelIds: [LabelID!]
"""
- Labels of the issue
+ Labels of the issue.
"""
labels: [String!]
@@ -25105,7 +26611,7 @@ Autogenerated input type of UpdateContainerExpirationPolicy
"""
input UpdateContainerExpirationPolicyInput {
"""
- This container expiration policy schedule
+ This container expiration policy schedule.
"""
cadence: ContainerExpirationPolicyCadenceEnum
@@ -25115,27 +26621,27 @@ input UpdateContainerExpirationPolicyInput {
clientMutationId: String
"""
- Indicates whether this container expiration policy is enabled
+ Indicates whether this container expiration policy is enabled.
"""
enabled: Boolean
"""
- Number of tags to retain
+ Number of tags to retain.
"""
keepN: ContainerExpirationPolicyKeepEnum
"""
- Tags with names matching this regex pattern will expire
+ Tags with names matching this regex pattern will expire.
"""
nameRegex: UntrustedRegexp
"""
- Tags with names matching this regex pattern will be preserved
+ Tags with names matching this regex pattern will be preserved.
"""
nameRegexKeep: UntrustedRegexp
"""
- Tags older that this will expire
+ Tags older that this will expire.
"""
olderThan: ContainerExpirationPolicyOlderThanEnum
@@ -25165,69 +26671,24 @@ type UpdateContainerExpirationPolicyPayload {
errors: [String!]!
}
-"""
-Autogenerated input type of UpdateDevopsAdoptionSegment
-"""
-input UpdateDevopsAdoptionSegmentInput {
- """
- A unique identifier for the client performing the mutation.
- """
- clientMutationId: String
-
- """
- The array of group IDs to set for the segment.
- """
- groupIds: [GroupID!]
-
- """
- ID of the segment.
- """
- id: AnalyticsDevopsAdoptionSegmentID!
-
- """
- Name of the segment.
- """
- name: String!
-}
-
-"""
-Autogenerated return type of UpdateDevopsAdoptionSegment
-"""
-type UpdateDevopsAdoptionSegmentPayload {
- """
- A unique identifier for the client performing the mutation.
- """
- clientMutationId: String
-
- """
- Errors encountered during execution of the mutation.
- """
- errors: [String!]!
-
- """
- The segment after mutation.
- """
- segment: DevopsAdoptionSegment
-}
-
input UpdateDiffImagePositionInput {
"""
- Total height of the image
+ Total height of the image.
"""
height: Int
"""
- Total width of the image
+ Total width of the image.
"""
width: Int
"""
- X position of the note
+ X position of the note.
"""
x: Int
"""
- Y position of the note
+ Y position of the note.
"""
y: Int
}
@@ -25327,7 +26788,7 @@ Autogenerated input type of UpdateImageDiffNote
"""
input UpdateImageDiffNoteInput {
"""
- Content of the note
+ Content of the note.
"""
body: String
@@ -25342,7 +26803,7 @@ input UpdateImageDiffNoteInput {
id: NoteID!
"""
- The position of this note on a diff
+ The position of this note on a diff.
"""
position: UpdateDiffImagePositionInput
}
@@ -25382,17 +26843,17 @@ input UpdateIssueInput {
clientMutationId: String
"""
- Indicates the issue is confidential
+ Indicates the issue is confidential.
"""
confidential: Boolean
"""
- Description of the issue
+ Description of the issue.
"""
description: String
"""
- Due date of the issue
+ Due date of the issue.
"""
dueDate: ISO8601Date
@@ -25412,7 +26873,7 @@ input UpdateIssueInput {
iid: String!
"""
- Indicates discussion is locked on the issue
+ Indicates discussion is locked on the issue.
"""
locked: Boolean
@@ -25437,7 +26898,7 @@ input UpdateIssueInput {
stateEvent: IssueStateEvent
"""
- Title of the issue
+ Title of the issue.
"""
title: String
@@ -25578,7 +27039,7 @@ Autogenerated input type of UpdateNote
"""
input UpdateNoteInput {
"""
- Content of the note
+ Content of the note.
"""
body: String
@@ -25688,6 +27149,13 @@ input UpdateSnippetInput {
blobActions: [SnippetBlobActionInputType!]
"""
+ A 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".
+ """
+ captchaResponse: String
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -25703,6 +27171,13 @@ input UpdateSnippetInput {
id: SnippetID!
"""
+ The 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".
+ """
+ spamLogId: Int
+
+ """
Title of the snippet.
"""
title: String
@@ -25718,6 +27193,13 @@ Autogenerated return type of UpdateSnippet
"""
type UpdateSnippetPayload {
"""
+ The 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.
+ """
+ captchaSiteKey: String
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -25728,21 +27210,38 @@ type UpdateSnippetPayload {
errors: [String!]!
"""
+ 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.
+ """
+ needsCaptchaResponse: Boolean
+
+ """
The snippet after mutation.
"""
snippet: Snippet
"""
- Indicates whether the operation returns a record detected as spam.
+ Indicates whether the operation was detected as definite spam. There is no
+ option to resubmit the request with a CAPTCHA response.
"""
spam: Boolean
+
+ """
+ The 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.
+ """
+ spamLogId: Int
}
scalar Upload
type User {
"""
- Merge Requests assigned to the user
+ Merge Requests assigned to the user.
"""
assignedMergeRequests(
"""
@@ -25832,7 +27331,7 @@ type User {
): MergeRequestConnection
"""
- Merge Requests authored by the user
+ Merge Requests authored by the user.
"""
authoredMergeRequests(
"""
@@ -25922,22 +27421,27 @@ type User {
): MergeRequestConnection
"""
- URL of the user's avatar
+ URL of the user's avatar.
"""
avatarUrl: String
"""
- User email Deprecated in 13.7: Use public_email.
+ Indicates if the user is a bot.
+ """
+ bot: Boolean!
+
+ """
+ User email. Deprecated in 13.7: Use public_email.
"""
email: String @deprecated(reason: "Use public_email. Deprecated in 13.7.")
"""
- Group count for the user Available only when feature flag `user_group_counts` is enabled.
+ Group count for the user. Available only when feature flag `user_group_counts` is enabled.
"""
groupCount: Int
"""
- Group memberships of the user
+ Group memberships of the user.
"""
groupMemberships(
"""
@@ -25962,7 +27466,7 @@ type User {
): GroupMemberConnection
"""
- ID of the user
+ ID of the user.
"""
id: ID!
@@ -25972,12 +27476,12 @@ type User {
location: String
"""
- Human-readable name of the user
+ Human-readable name of the user.
"""
name: String!
"""
- Project memberships of the user
+ Project memberships of the user.
"""
projectMemberships(
"""
@@ -26002,12 +27506,12 @@ type User {
): ProjectMemberConnection
"""
- User's public email
+ User's public email.
"""
publicEmail: String
"""
- Merge Requests assigned to the user for review
+ Merge Requests assigned to the user for review.
"""
reviewRequestedMergeRequests(
"""
@@ -26097,7 +27601,7 @@ type User {
): MergeRequestConnection
"""
- Snippets authored by the user
+ Snippets authored by the user.
"""
snippets(
"""
@@ -26137,7 +27641,7 @@ type User {
): SnippetConnection
"""
- Projects starred by the user
+ Projects starred by the user.
"""
starredProjects(
"""
@@ -26167,17 +27671,17 @@ type User {
): ProjectConnection
"""
- State of the user
+ State of the user.
"""
state: UserState!
"""
- User status
+ User status.
"""
status: UserStatus
"""
- Todos of the user
+ To-do items of the user.
"""
todos(
"""
@@ -26237,17 +27741,17 @@ type User {
userPermissions: UserPermissions!
"""
- Username of the user. Unique within this instance of GitLab
+ Username of the user. Unique within this instance of GitLab.
"""
username: String!
"""
- Web path of the user
+ Web path of the user.
"""
webPath: String!
"""
- Web URL of the user
+ Web URL of the user.
"""
webUrl: String!
}
@@ -26288,7 +27792,7 @@ type UserEdge {
}
"""
-Identifier of User
+Identifier of User.
"""
scalar UserID
@@ -26321,17 +27825,17 @@ enum UserState {
type UserStatus {
"""
- User availability status
+ User availability status.
"""
availability: AvailabilityEnum!
"""
- String representation of emoji
+ String representation of emoji.
"""
emoji: String
"""
- User status message
+ User status message.
"""
message: String
@@ -26363,7 +27867,7 @@ type VulnerabilitiesCountByDay {
critical: Int!
"""
- Date for the count
+ Date for the count.
"""
date: ISO8601Date!
@@ -26388,7 +27892,7 @@ type VulnerabilitiesCountByDay {
medium: Int!
"""
- Total number of vulnerabilities on a particular day
+ Total number of vulnerabilities on a particular day.
"""
total: Int!
@@ -26403,17 +27907,17 @@ Represents the number of vulnerabilities for a particular severity on a particul
"""
type VulnerabilitiesCountByDayAndSeverity {
"""
- Number of vulnerabilities
+ Number of vulnerabilities.
"""
count: Int
"""
- Date for the count
+ Date for the count.
"""
day: ISO8601Date
"""
- Severity of the counted vulnerabilities
+ Severity of the counted vulnerabilities.
"""
severity: VulnerabilitySeverity
}
@@ -26489,7 +27993,7 @@ type VulnerabilitiesCountByDayEdge {
}
"""
-Identifier of Vulnerabilities::ExternalIssueLink
+Identifier of Vulnerabilities::ExternalIssueLink.
"""
scalar VulnerabilitiesExternalIssueLinkID
@@ -26498,7 +28002,7 @@ Represents a vulnerability
"""
type Vulnerability implements Noteable {
"""
- Timestamp of when the vulnerability state was changed to confirmed
+ Timestamp of when the vulnerability state was changed to confirmed.
"""
confirmedAt: Time
@@ -26508,17 +28012,22 @@ type Vulnerability implements Noteable {
confirmedBy: User
"""
- Description of the vulnerability
+ Description of the vulnerability.
"""
description: String
"""
- Timestamp of when the vulnerability was first detected
+ Details of the vulnerability.
+ """
+ details: [VulnerabilityDetail!]!
+
+ """
+ Timestamp of when the vulnerability was first detected.
"""
detectedAt: Time!
"""
- All discussions on this noteable
+ All discussions on this noteable.
"""
discussions(
"""
@@ -26543,7 +28052,7 @@ type Vulnerability implements Noteable {
): DiscussionConnection!
"""
- Timestamp of when the vulnerability state was changed to dismissed
+ Timestamp of when the vulnerability state was changed to dismissed.
"""
dismissedAt: Time
@@ -26553,7 +28062,7 @@ type Vulnerability implements Noteable {
dismissedBy: User
"""
- List of external issue links related to the vulnerability
+ List of external issue links related to the vulnerability.
"""
externalIssueLinks(
"""
@@ -26583,7 +28092,7 @@ type Vulnerability implements Noteable {
hasSolutions: Boolean
"""
- GraphQL ID of the vulnerability
+ GraphQL ID of the vulnerability.
"""
id: ID!
@@ -26593,7 +28102,7 @@ type Vulnerability implements Noteable {
identifiers: [VulnerabilityIdentifier!]!
"""
- List of issue links related to the vulnerability
+ List of issue links related to the vulnerability.
"""
issueLinks(
"""
@@ -26623,7 +28132,7 @@ type Vulnerability implements Noteable {
): VulnerabilityIssueLinkConnection!
"""
- Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability
+ Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability.
"""
location: VulnerabilityLocation
@@ -26633,7 +28142,7 @@ type Vulnerability implements Noteable {
mergeRequest: MergeRequest
"""
- All notes on this noteable
+ All notes on this noteable.
"""
notes(
"""
@@ -26663,7 +28172,7 @@ type Vulnerability implements Noteable {
primaryIdentifier: VulnerabilityIdentifier
"""
- The project on which the vulnerability was found
+ The project on which the vulnerability was found.
"""
project: Project
@@ -26675,7 +28184,7 @@ type Vulnerability implements Noteable {
reportType: VulnerabilityReportType
"""
- Timestamp of when the vulnerability state was changed to resolved
+ Timestamp of when the vulnerability state was changed to resolved.
"""
resolvedAt: Time
@@ -26685,7 +28194,7 @@ type Vulnerability implements Noteable {
resolvedBy: User
"""
- Indicates whether the vulnerability is fixed on the default branch or not
+ Indicates whether the vulnerability is fixed on the default branch or not.
"""
resolvedOnDefaultBranch: Boolean!
@@ -26705,12 +28214,12 @@ type Vulnerability implements Noteable {
state: VulnerabilityState
"""
- Title of the vulnerability
+ Title of the vulnerability.
"""
title: String
"""
- Number of user notes attached to the vulnerability
+ Number of user notes attached to the vulnerability.
"""
userNotesCount: Int!
@@ -26720,7 +28229,7 @@ type Vulnerability implements Noteable {
userPermissions: VulnerabilityPermissions!
"""
- URL to the vulnerability's details page
+ URL to the vulnerability's details page.
"""
vulnerabilityPath: String
}
@@ -26781,6 +28290,366 @@ type VulnerabilityConnection {
}
"""
+Represents a vulnerability detail field. The fields with data will depend on the vulnerability detail type
+"""
+union VulnerabilityDetail = VulnerabilityDetailBase | VulnerabilityDetailBoolean | VulnerabilityDetailCode | VulnerabilityDetailCommit | VulnerabilityDetailDiff | VulnerabilityDetailFileLocation | VulnerabilityDetailInt | VulnerabilityDetailList | VulnerabilityDetailMarkdown | VulnerabilityDetailModuleLocation | VulnerabilityDetailTable | VulnerabilityDetailText | VulnerabilityDetailUrl
+
+"""
+Represents the vulnerability details base
+"""
+type VulnerabilityDetailBase {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+}
+
+"""
+Represents the vulnerability details boolean value
+"""
+type VulnerabilityDetailBoolean {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Value of the field.
+ """
+ value: Boolean!
+}
+
+"""
+Represents the vulnerability details code field
+"""
+type VulnerabilityDetailCode {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Language of the code.
+ """
+ lang: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Source code.
+ """
+ value: String!
+}
+
+"""
+Represents the vulnerability details commit field
+"""
+type VulnerabilityDetailCommit {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ The commit SHA value.
+ """
+ value: String!
+}
+
+"""
+Represents the vulnerability details diff field
+"""
+type VulnerabilityDetailDiff {
+ """
+ Value of the field after the change.
+ """
+ after: String!
+
+ """
+ Value of the field before the change.
+ """
+ before: String!
+
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+}
+
+"""
+Represents the vulnerability details location within a file in the project
+"""
+type VulnerabilityDetailFileLocation {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ File name.
+ """
+ fileName: String!
+
+ """
+ End line number of the file location.
+ """
+ lineEnd: Int!
+
+ """
+ Start line number of the file location.
+ """
+ lineStart: Int!
+
+ """
+ Name of the field.
+ """
+ name: String!
+}
+
+"""
+Represents the vulnerability details integer value
+"""
+type VulnerabilityDetailInt {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Value of the field.
+ """
+ value: Int!
+}
+
+"""
+Represents the vulnerability details list value
+"""
+type VulnerabilityDetailList {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ List of details.
+ """
+ items: [VulnerabilityDetail!]!
+
+ """
+ Name of the field.
+ """
+ name: String!
+}
+
+"""
+Represents the vulnerability details Markdown field
+"""
+type VulnerabilityDetailMarkdown {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Value of the Markdown field.
+ """
+ value: String!
+}
+
+"""
+Represents the vulnerability details location within a file in the project
+"""
+type VulnerabilityDetailModuleLocation {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Module name.
+ """
+ moduleName: String!
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Offset of the module location.
+ """
+ offset: Int!
+}
+
+"""
+Represents the vulnerability details table value
+"""
+type VulnerabilityDetailTable {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Table headers.
+ """
+ headers: [VulnerabilityDetail!]!
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Table rows.
+ """
+ rows: [VulnerabilityDetail!]!
+}
+
+"""
+Represents the vulnerability details text field
+"""
+type VulnerabilityDetailText {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Value of the text field.
+ """
+ value: String!
+}
+
+"""
+Represents the vulnerability details URL field
+"""
+type VulnerabilityDetailUrl {
+ """
+ Description of the field.
+ """
+ description: String!
+
+ """
+ Name of the field.
+ """
+ fieldName: String
+
+ """
+ Href of the URL.
+ """
+ href: String!
+
+ """
+ Name of the field.
+ """
+ name: String!
+
+ """
+ Text of the URL.
+ """
+ text: String
+}
+
+"""
Autogenerated input type of VulnerabilityDismiss
"""
input VulnerabilityDismissInput {
@@ -26875,17 +28744,17 @@ Represents an external issue link of a vulnerability
"""
type VulnerabilityExternalIssueLink {
"""
- The external issue attached to the issue link
+ The external issue attached to the issue link.
"""
externalIssue: ExternalIssue
"""
- GraphQL ID of the external issue link
+ GraphQL ID of the external issue link.
"""
id: VulnerabilitiesExternalIssueLinkID!
"""
- Type of the external issue link
+ Type of the external issue link.
"""
linkType: VulnerabilityExternalIssueLinkType!
}
@@ -27032,7 +28901,7 @@ enum VulnerabilityGrade {
}
"""
-Identifier of Vulnerability
+Identifier of Vulnerability.
"""
scalar VulnerabilityID
@@ -27041,22 +28910,22 @@ Represents a vulnerability identifier
"""
type VulnerabilityIdentifier {
"""
- External ID of the vulnerability identifier
+ External ID of the vulnerability identifier.
"""
externalId: String
"""
- External type of the vulnerability identifier
+ External type of the vulnerability identifier.
"""
externalType: String
"""
- Name of the vulnerability identifier
+ Name of the vulnerability identifier.
"""
name: String
"""
- URL of the vulnerability identifier
+ URL of the vulnerability identifier.
"""
url: String
}
@@ -27066,17 +28935,17 @@ Represents an issue link of a vulnerability
"""
type VulnerabilityIssueLink {
"""
- GraphQL ID of the vulnerability
+ GraphQL ID of the vulnerability.
"""
id: ID!
"""
- The issue attached to issue link
+ The issue attached to issue link.
"""
issue: Issue!
"""
- Type of the issue link
+ Type of the issue link.
"""
linkType: VulnerabilityIssueLinkType!
}
@@ -27134,17 +29003,17 @@ Represents the location of a vulnerability found by a container security scan
"""
type VulnerabilityLocationContainerScanning {
"""
- Dependency containing the vulnerability
+ Dependency containing the vulnerability.
"""
dependency: VulnerableDependency
"""
- Name of the vulnerable container image
+ Name of the vulnerable container image.
"""
image: String
"""
- Operating system that runs on the vulnerable container image
+ Operating system that runs on the vulnerable container image.
"""
operatingSystem: String
}
@@ -27154,27 +29023,32 @@ Represents the location of a vulnerability found by a Coverage Fuzzing scan
"""
type VulnerabilityLocationCoverageFuzzing {
"""
- Number of the last relevant line in the vulnerable file
+ Blob path to the vulnerable file.
+ """
+ blobPath: String
+
+ """
+ Number of the last relevant line in the vulnerable file.
"""
endLine: String
"""
- Path to the vulnerable file
+ Path to the vulnerable file.
"""
file: String
"""
- Number of the first relevant line in the vulnerable file
+ Number of the first relevant line in the vulnerable file.
"""
startLine: String
"""
- Class containing the vulnerability
+ Class containing the vulnerability.
"""
vulnerableClass: String
"""
- Method containing the vulnerability
+ Method containing the vulnerability.
"""
vulnerableMethod: String
}
@@ -27184,22 +29058,22 @@ Represents the location of a vulnerability found by a DAST scan
"""
type VulnerabilityLocationDast {
"""
- Domain name of the vulnerable request
+ Domain name of the vulnerable request.
"""
hostname: String
"""
- Query parameter for the URL on which the vulnerability occurred
+ Query parameter for the URL on which the vulnerability occurred.
"""
param: String
"""
- URL path and query string of the vulnerable request
+ URL path and query string of the vulnerable request.
"""
path: String
"""
- HTTP method of the vulnerable request
+ HTTP method of the vulnerable request.
"""
requestMethod: String
}
@@ -27209,12 +29083,17 @@ Represents the location of a vulnerability found by a dependency security scan
"""
type VulnerabilityLocationDependencyScanning {
"""
- Dependency containing the vulnerability
+ Blob path to the vulnerable file.
+ """
+ blobPath: String
+
+ """
+ Dependency containing the vulnerability.
"""
dependency: VulnerableDependency
"""
- Path to the vulnerable file
+ Path to the vulnerable file.
"""
file: String
}
@@ -27224,27 +29103,32 @@ Represents the location of a vulnerability found by a SAST scan
"""
type VulnerabilityLocationSast {
"""
- Number of the last relevant line in the vulnerable file
+ Blob path to the vulnerable file.
+ """
+ blobPath: String
+
+ """
+ Number of the last relevant line in the vulnerable file.
"""
endLine: String
"""
- Path to the vulnerable file
+ Path to the vulnerable file.
"""
file: String
"""
- Number of the first relevant line in the vulnerable file
+ Number of the first relevant line in the vulnerable file.
"""
startLine: String
"""
- Class containing the vulnerability
+ Class containing the vulnerability.
"""
vulnerableClass: String
"""
- Method containing the vulnerability
+ Method containing the vulnerability.
"""
vulnerableMethod: String
}
@@ -27254,27 +29138,32 @@ Represents the location of a vulnerability found by a secret detection scan
"""
type VulnerabilityLocationSecretDetection {
"""
- Number of the last relevant line in the vulnerable file
+ Blob path to the vulnerable file.
+ """
+ blobPath: String
+
+ """
+ Number of the last relevant line in the vulnerable file.
"""
endLine: String
"""
- Path to the vulnerable file
+ Path to the vulnerable file.
"""
file: String
"""
- Number of the first relevant line in the vulnerable file
+ Number of the first relevant line in the vulnerable file.
"""
startLine: String
"""
- Class containing the vulnerability
+ Class containing the vulnerability.
"""
vulnerableClass: String
"""
- Method containing the vulnerability
+ Method containing the vulnerability.
"""
vulnerableMethod: String
}
@@ -27417,22 +29306,22 @@ Represents a vulnerability scanner
"""
type VulnerabilityScanner {
"""
- External ID of the vulnerability scanner
+ External ID of the vulnerability scanner.
"""
externalId: String
"""
- Name of the vulnerability scanner
+ Name of the vulnerability scanner.
"""
name: String
"""
- Type of the vulnerability report
+ Type of the vulnerability report.
"""
reportType: VulnerabilityReportType
"""
- Vendor of the vulnerability scanner
+ Vendor of the vulnerability scanner.
"""
vendor: String
}
@@ -27589,12 +29478,12 @@ Represents a vulnerable dependency. Used in vulnerability location data
"""
type VulnerableDependency {
"""
- The package associated with the vulnerable dependency
+ The package associated with the vulnerable dependency.
"""
package: VulnerablePackage
"""
- The version of the vulnerable dependency
+ The version of the vulnerable dependency.
"""
version: String
}
@@ -27604,7 +29493,7 @@ Represents a vulnerable package. Used in vulnerability dependency data
"""
type VulnerablePackage {
"""
- The name of the vulnerable package
+ The name of the vulnerable package.
"""
name: String
}
@@ -27614,17 +29503,17 @@ Represents vulnerability letter grades with associated projects
"""
type VulnerableProjectsByGrade {
"""
- Number of projects within this grade
+ Number of projects within this grade.
"""
count: Int!
"""
- Grade based on the highest severity vulnerability present
+ Grade based on the highest severity vulnerability present.
"""
grade: VulnerabilityGrade!
"""
- Projects within this grade
+ Projects within this grade.
"""
projects(
"""
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 138530abb17..492682d2e54 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -16,7 +16,7 @@
"fields": [
{
"name": "integerValue",
- "description": "Integer representation of access level",
+ "description": "Integer representation of access level.",
"args": [
],
@@ -30,7 +30,7 @@
},
{
"name": "stringValue",
- "description": "String representation of access level",
+ "description": "String representation of access level.",
"args": [
],
@@ -119,7 +119,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -504,7 +504,7 @@
"fields": [
{
"name": "assignees",
- "description": "Assignees of the alert",
+ "description": "Assignees of the alert.",
"args": [
{
"name": "after",
@@ -557,7 +557,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp the alert was created",
+ "description": "Timestamp the alert was created.",
"args": [
],
@@ -571,7 +571,7 @@
},
{
"name": "description",
- "description": "Description of the alert",
+ "description": "Description of the alert.",
"args": [
],
@@ -585,7 +585,7 @@
},
{
"name": "details",
- "description": "Alert details",
+ "description": "Alert details.",
"args": [
],
@@ -599,7 +599,7 @@
},
{
"name": "detailsUrl",
- "description": "The URL of the alert detail page",
+ "description": "The URL of the alert detail page.",
"args": [
],
@@ -617,7 +617,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -674,7 +674,7 @@
},
{
"name": "endedAt",
- "description": "Timestamp the alert ended",
+ "description": "Timestamp the alert ended.",
"args": [
],
@@ -688,7 +688,7 @@
},
{
"name": "environment",
- "description": "Environment for the alert",
+ "description": "Environment for the alert.",
"args": [
],
@@ -702,7 +702,7 @@
},
{
"name": "eventCount",
- "description": "Number of events of this alert",
+ "description": "Number of events of this alert.",
"args": [
],
@@ -716,7 +716,7 @@
},
{
"name": "hosts",
- "description": "List of hosts the alert came from",
+ "description": "List of hosts the alert came from.",
"args": [
],
@@ -738,7 +738,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the alert",
+ "description": "Internal ID of the alert.",
"args": [
],
@@ -756,7 +756,7 @@
},
{
"name": "issueIid",
- "description": "Internal ID of the GitLab issue attached to the alert",
+ "description": "Internal ID of the GitLab issue attached to the alert.",
"args": [
],
@@ -770,7 +770,7 @@
},
{
"name": "metricsDashboardUrl",
- "description": "URL for metrics embed for the alert",
+ "description": "URL for metrics embed for the alert.",
"args": [
],
@@ -784,7 +784,7 @@
},
{
"name": "monitoringTool",
- "description": "Monitoring tool the alert came from",
+ "description": "Monitoring tool the alert came from.",
"args": [
],
@@ -798,7 +798,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -855,7 +855,7 @@
},
{
"name": "prometheusAlert",
- "description": "The alert condition for Prometheus",
+ "description": "The alert condition for Prometheus.",
"args": [
],
@@ -869,7 +869,7 @@
},
{
"name": "runbook",
- "description": "Runbook for the alert as defined in alert details",
+ "description": "Runbook for the alert as defined in alert details.",
"args": [
],
@@ -883,7 +883,7 @@
},
{
"name": "service",
- "description": "Service the alert came from",
+ "description": "Service the alert came from.",
"args": [
],
@@ -897,7 +897,7 @@
},
{
"name": "severity",
- "description": "Severity of the alert",
+ "description": "Severity of the alert.",
"args": [
],
@@ -911,7 +911,7 @@
},
{
"name": "startedAt",
- "description": "Timestamp the alert was raised",
+ "description": "Timestamp the alert was raised.",
"args": [
],
@@ -925,7 +925,7 @@
},
{
"name": "status",
- "description": "Status of the alert",
+ "description": "Status of the alert.",
"args": [
],
@@ -939,7 +939,7 @@
},
{
"name": "title",
- "description": "Title of the alert",
+ "description": "Title of the alert.",
"args": [
],
@@ -953,7 +953,7 @@
},
{
"name": "todos",
- "description": "Todos of the current user for the alert",
+ "description": "To-do items of the current user for the alert.",
"args": [
{
"name": "action",
@@ -1114,7 +1114,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp the alert was last updated",
+ "description": "Timestamp the alert was last updated.",
"args": [
],
@@ -1414,7 +1414,7 @@
},
{
"name": "all",
- "description": "Total number of alerts for the project",
+ "description": "Total number of alerts for the project.",
"args": [
],
@@ -1442,7 +1442,7 @@
},
{
"name": "open",
- "description": "Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project",
+ "description": "Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project.",
"args": [
],
@@ -1520,7 +1520,7 @@
"fields": [
{
"name": "active",
- "description": "Whether the endpoint is currently accepting alerts",
+ "description": "Whether the endpoint is currently accepting alerts.",
"args": [
],
@@ -1534,7 +1534,7 @@
},
{
"name": "apiUrl",
- "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
+ "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard.",
"args": [
],
@@ -1548,7 +1548,7 @@
},
{
"name": "id",
- "description": "ID of the integration",
+ "description": "ID of the integration.",
"args": [
],
@@ -1566,7 +1566,7 @@
},
{
"name": "name",
- "description": "Name of the integration",
+ "description": "Name of the integration.",
"args": [
],
@@ -1580,7 +1580,7 @@
},
{
"name": "token",
- "description": "Token used to authenticate alert notification requests",
+ "description": "Token used to authenticate alert notification requests.",
"args": [
],
@@ -1594,7 +1594,7 @@
},
{
"name": "type",
- "description": "Type of integration",
+ "description": "Type of integration.",
"args": [
],
@@ -1612,7 +1612,7 @@
},
{
"name": "url",
- "description": "Endpoint which accepts alert notifications",
+ "description": "Endpoint which accepts alert notifications.",
"args": [
],
@@ -1639,7 +1639,7 @@
{
"kind": "SCALAR",
"name": "AlertManagementHttpIntegrationID",
- "description": "Identifier of AlertManagement::HttpIntegration",
+ "description": "Identifier of AlertManagement::HttpIntegration.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -1653,7 +1653,7 @@
"fields": [
{
"name": "active",
- "description": "Whether the endpoint is currently accepting alerts",
+ "description": "Whether the endpoint is currently accepting alerts.",
"args": [
],
@@ -1667,7 +1667,7 @@
},
{
"name": "apiUrl",
- "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
+ "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard.",
"args": [
],
@@ -1681,7 +1681,7 @@
},
{
"name": "id",
- "description": "ID of the integration",
+ "description": "ID of the integration.",
"args": [
],
@@ -1699,7 +1699,7 @@
},
{
"name": "name",
- "description": "Name of the integration",
+ "description": "Name of the integration.",
"args": [
],
@@ -1713,7 +1713,7 @@
},
{
"name": "token",
- "description": "Token used to authenticate alert notification requests",
+ "description": "Token used to authenticate alert notification requests.",
"args": [
],
@@ -1727,7 +1727,7 @@
},
{
"name": "type",
- "description": "Type of integration",
+ "description": "Type of integration.",
"args": [
],
@@ -1745,7 +1745,7 @@
},
{
"name": "url",
- "description": "Endpoint which accepts alert notifications",
+ "description": "Endpoint which accepts alert notifications.",
"args": [
],
@@ -1910,6 +1910,69 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "AlertManagementPayloadAlertField",
+ "description": "Parsed field from an alert used for custom mappings",
+ "fields": [
+ {
+ "name": "label",
+ "description": "Human-readable label of the payload path.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "path",
+ "description": "Path to value inside payload JSON.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "type",
+ "description": "Type of the parsed value.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "AlertManagementPayloadAlertFieldType",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "AlertManagementPayloadAlertFieldInput",
"description": "Field that are available while modifying the custom mapping attributes for an HTTP integration",
@@ -2087,7 +2150,7 @@
"fields": [
{
"name": "active",
- "description": "Whether the endpoint is currently accepting alerts",
+ "description": "Whether the endpoint is currently accepting alerts.",
"args": [
],
@@ -2101,7 +2164,7 @@
},
{
"name": "apiUrl",
- "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
+ "description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard.",
"args": [
],
@@ -2115,7 +2178,7 @@
},
{
"name": "id",
- "description": "ID of the integration",
+ "description": "ID of the integration.",
"args": [
],
@@ -2133,7 +2196,7 @@
},
{
"name": "name",
- "description": "Name of the integration",
+ "description": "Name of the integration.",
"args": [
],
@@ -2147,7 +2210,7 @@
},
{
"name": "token",
- "description": "Token used to authenticate alert notification requests",
+ "description": "Token used to authenticate alert notification requests.",
"args": [
],
@@ -2161,7 +2224,7 @@
},
{
"name": "type",
- "description": "Type of integration",
+ "description": "Type of integration.",
"args": [
],
@@ -2179,7 +2242,7 @@
},
{
"name": "url",
- "description": "Endpoint which accepts alert notifications",
+ "description": "Endpoint which accepts alert notifications.",
"args": [
],
@@ -2441,7 +2504,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation.",
+ "description": "The to-do item after mutation.",
"args": [
],
@@ -2585,7 +2648,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation.",
+ "description": "The to-do item after mutation.",
"args": [
],
@@ -2608,10 +2671,333 @@
{
"kind": "SCALAR",
"name": "AnalyticsDevopsAdoptionSegmentID",
- "description": "Identifier of Analytics::DevopsAdoption::Segment",
+ "description": "Identifier of Analytics::DevopsAdoption::Segment.",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ApiFuzzingCiConfiguration",
+ "description": "Data associated with configuring API fuzzing scans in GitLab CI",
+ "fields": [
+ {
+ "name": "scanModes",
+ "description": "All available scan modes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "ApiFuzzingScanMode",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "scanProfiles",
+ "description": "All default scan profiles.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ApiFuzzingScanProfile",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "ApiFuzzingCiConfigurationCreateInput",
+ "description": "Autogenerated input type of ApiFuzzingCiConfigurationCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "Full path of the project.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "apiSpecificationFile",
+ "description": "File path or URL to the file that defines the API surface for scanning. Must be in the format specified by the `scanMode` argument.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "authPassword",
+ "description": "CI variable containing the password for authenticating with the target API.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "authUsername",
+ "description": "CI variable containing the username for authenticating with the target API.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "scanMode",
+ "description": "The mode for API fuzzing scans.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "ApiFuzzingScanMode",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "scanProfile",
+ "description": "Name of a default profile to use for scanning. Ex: Quick-10.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "target",
+ "description": "URL for the target of API fuzzing scans.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ApiFuzzingCiConfigurationCreatePayload",
+ "description": "Autogenerated return type of ApiFuzzingCiConfigurationCreate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "configurationYaml",
+ "description": "A YAML snippet that can be inserted into the project's `.gitlab-ci.yml` to set up API fuzzing scans.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "gitlabCiYamlEditPath",
+ "description": "The location at which the project's `.gitlab-ci.yml` file can be edited in the browser.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "ApiFuzzingScanMode",
+ "description": "All possible ways to specify the API surface for an API fuzzing scan",
"fields": null,
"inputFields": null,
"interfaces": null,
+ "enumValues": [
+ {
+ "name": "HAR",
+ "description": "The API surface is specified by a HAR file.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "OPENAPI",
+ "description": "The API surface is specified by a OPENAPI file.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ApiFuzzingScanProfile",
+ "description": "An API Fuzzing scan profile.",
+ "fields": [
+ {
+ "name": "description",
+ "description": "A short description of the profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "The unique name of the profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "yaml",
+ "description": "A syntax highlit HTML representation of the YAML.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
"enumValues": null,
"possibleTypes": null
},
@@ -2645,7 +3031,7 @@
"fields": [
{
"name": "description",
- "description": "The emoji description",
+ "description": "The emoji description.",
"args": [
],
@@ -2663,7 +3049,7 @@
},
{
"name": "emoji",
- "description": "The emoji as an icon",
+ "description": "The emoji as an icon.",
"args": [
],
@@ -2681,7 +3067,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"args": [
],
@@ -2699,7 +3085,7 @@
},
{
"name": "unicode",
- "description": "The emoji in unicode",
+ "description": "The emoji in Unicode.",
"args": [
],
@@ -2717,7 +3103,7 @@
},
{
"name": "unicodeVersion",
- "description": "The unicode version for this emoji",
+ "description": "The Unicode version for this emoji.",
"args": [
],
@@ -2735,7 +3121,7 @@
},
{
"name": "user",
- "description": "The user who awarded the emoji",
+ "description": "The user who awarded the emoji.",
"args": [
],
@@ -2781,7 +3167,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -2876,6 +3262,118 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "AwardEmojiConnection",
+ "description": "The connection type for AwardEmoji.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "AwardEmojiEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "AwardEmoji",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "AwardEmojiEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AwardEmoji",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "AwardEmojiRemoveInput",
"description": "Autogenerated input type of AwardEmojiRemove",
@@ -2897,7 +3395,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -3013,7 +3511,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -3128,7 +3626,7 @@
{
"kind": "SCALAR",
"name": "AwardableID",
- "description": "Identifier of Awardable",
+ "description": "Identifier of Awardable.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -3142,7 +3640,7 @@
"fields": [
{
"name": "active",
- "description": "Indicates if the service is active",
+ "description": "Indicates if the service is active.",
"args": [
],
@@ -3156,7 +3654,7 @@
},
{
"name": "type",
- "description": "Class name of the service",
+ "description": "Class name of the service.",
"args": [
],
@@ -3197,7 +3695,7 @@
"fields": [
{
"name": "flatPath",
- "description": "Flat path of the entry",
+ "description": "Flat path of the entry.",
"args": [
],
@@ -3215,7 +3713,7 @@
},
{
"name": "id",
- "description": "ID of the entry",
+ "description": "ID of the entry.",
"args": [
],
@@ -3233,7 +3731,7 @@
},
{
"name": "lfsOid",
- "description": "LFS ID of the blob",
+ "description": "LFS ID of the blob.",
"args": [
],
@@ -3247,7 +3745,7 @@
},
{
"name": "mode",
- "description": "Blob mode in numeric format",
+ "description": "Blob mode in numeric format.",
"args": [
],
@@ -3261,7 +3759,7 @@
},
{
"name": "name",
- "description": "Name of the entry",
+ "description": "Name of the entry.",
"args": [
],
@@ -3279,7 +3777,7 @@
},
{
"name": "path",
- "description": "Path of the entry",
+ "description": "Path of the entry.",
"args": [
],
@@ -3297,7 +3795,7 @@
},
{
"name": "sha",
- "description": "Last commit sha for the entry",
+ "description": "Last commit SHA for the entry.",
"args": [
],
@@ -3315,7 +3813,7 @@
},
{
"name": "type",
- "description": "Type of tree entry",
+ "description": "Type of tree entry.",
"args": [
],
@@ -3333,7 +3831,7 @@
},
{
"name": "webPath",
- "description": "Web path of the blob",
+ "description": "Web path of the blob.",
"args": [
],
@@ -3347,7 +3845,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the blob",
+ "description": "Web URL of the blob.",
"args": [
],
@@ -3519,7 +4017,7 @@
"fields": [
{
"name": "assignee",
- "description": "The board assignee",
+ "description": "The board assignee.",
"args": [
],
@@ -3533,7 +4031,7 @@
},
{
"name": "epics",
- "description": "Epics associated with board issues",
+ "description": "Epics associated with board issues.",
"args": [
{
"name": "issueFilters",
@@ -3596,7 +4094,7 @@
},
{
"name": "hideBacklogList",
- "description": "Whether or not backlog list is hidden",
+ "description": "Whether or not backlog list is hidden.",
"args": [
],
@@ -3610,7 +4108,7 @@
},
{
"name": "hideClosedList",
- "description": "Whether or not closed list is hidden",
+ "description": "Whether or not closed list is hidden.",
"args": [
],
@@ -3624,7 +4122,7 @@
},
{
"name": "id",
- "description": "ID (global ID) of the board",
+ "description": "ID (global ID) of the board.",
"args": [
],
@@ -3656,7 +4154,7 @@
},
{
"name": "labels",
- "description": "Labels of the board",
+ "description": "Labels of the board.",
"args": [
{
"name": "after",
@@ -3709,7 +4207,7 @@
},
{
"name": "lists",
- "description": "Lists of the board",
+ "description": "Lists of the board.",
"args": [
{
"name": "id",
@@ -3782,7 +4280,7 @@
},
{
"name": "milestone",
- "description": "The board milestone",
+ "description": "The board milestone.",
"args": [
],
@@ -3796,7 +4294,7 @@
},
{
"name": "name",
- "description": "Name of the board",
+ "description": "Name of the board.",
"args": [
],
@@ -3846,7 +4344,7 @@
},
{
"name": "weight",
- "description": "Weight of the board",
+ "description": "Weight of the board.",
"args": [
],
@@ -3985,7 +4483,7 @@
"fields": [
{
"name": "author",
- "description": "Author of the epic",
+ "description": "Author of the epic.",
"args": [
],
@@ -4002,8 +4500,61 @@
"deprecationReason": null
},
{
+ "name": "awardEmoji",
+ "description": "A list of award emojis associated with the epic.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AwardEmojiConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "children",
- "description": "Children (sub-epics) of the epic",
+ "description": "Children (sub-epics) of the epic.",
"args": [
{
"name": "startDate",
@@ -4212,7 +4763,7 @@
},
{
"name": "closedAt",
- "description": "Timestamp of when the epic was closed",
+ "description": "Timestamp of when the epic was closed.",
"args": [
],
@@ -4226,7 +4777,7 @@
},
{
"name": "confidential",
- "description": "Indicates if the epic is confidential",
+ "description": "Indicates if the epic is confidential.",
"args": [
],
@@ -4240,7 +4791,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the epic was created",
+ "description": "Timestamp of when the epic was created.",
"args": [
],
@@ -4254,7 +4805,7 @@
},
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -4298,7 +4849,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -4321,7 +4872,7 @@
},
{
"name": "descendantCounts",
- "description": "Number of open and closed descendant epics and issues",
+ "description": "Number of open and closed descendant epics and issues.",
"args": [
],
@@ -4335,7 +4886,7 @@
},
{
"name": "descendantWeightSum",
- "description": "Total weight of open and closed issues in the epic and its descendants",
+ "description": "Total weight of open and closed issues in the epic and its descendants.",
"args": [
],
@@ -4349,7 +4900,7 @@
},
{
"name": "description",
- "description": "Description of the epic",
+ "description": "Description of the epic.",
"args": [
],
@@ -4363,7 +4914,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -4420,7 +4971,7 @@
},
{
"name": "downvotes",
- "description": "Number of downvotes the epic has received",
+ "description": "Number of downvotes the epic has received.",
"args": [
],
@@ -4438,7 +4989,7 @@
},
{
"name": "dueDate",
- "description": "Due date of the epic",
+ "description": "Due date of the epic.",
"args": [
],
@@ -4452,7 +5003,7 @@
},
{
"name": "dueDateFixed",
- "description": "Fixed due date of the epic",
+ "description": "Fixed due date of the epic.",
"args": [
],
@@ -4466,7 +5017,7 @@
},
{
"name": "dueDateFromMilestones",
- "description": "Inherited due date of the epic from milestones",
+ "description": "Inherited due date of the epic from milestones.",
"args": [
],
@@ -4480,7 +5031,7 @@
},
{
"name": "dueDateIsFixed",
- "description": "Indicates if the due date has been manually set",
+ "description": "Indicates if the due date has been manually set.",
"args": [
],
@@ -4493,8 +5044,61 @@
"deprecationReason": null
},
{
+ "name": "events",
+ "description": "A list of events associated with the object.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EventConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "group",
- "description": "Group to which the epic belongs",
+ "description": "Group to which the epic belongs.",
"args": [
],
@@ -4512,7 +5116,7 @@
},
{
"name": "hasChildren",
- "description": "Indicates if the epic has children",
+ "description": "Indicates if the epic has children.",
"args": [
],
@@ -4530,7 +5134,7 @@
},
{
"name": "hasIssues",
- "description": "Indicates if the epic has direct issues",
+ "description": "Indicates if the epic has direct issues.",
"args": [
],
@@ -4548,7 +5152,7 @@
},
{
"name": "hasParent",
- "description": "Indicates if the epic has a parent epic",
+ "description": "Indicates if the epic has a parent epic.",
"args": [
],
@@ -4566,7 +5170,7 @@
},
{
"name": "healthStatus",
- "description": "Current health status of the epic",
+ "description": "Current health status of the epic.",
"args": [
],
@@ -4580,7 +5184,7 @@
},
{
"name": "id",
- "description": "ID of the epic",
+ "description": "ID of the epic.",
"args": [
],
@@ -4598,7 +5202,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the epic",
+ "description": "Internal ID of the epic.",
"args": [
],
@@ -4616,7 +5220,7 @@
},
{
"name": "issues",
- "description": "A list of issues associated with the epic",
+ "description": "A list of issues associated with the epic.",
"args": [
{
"name": "after",
@@ -4669,7 +5273,7 @@
},
{
"name": "labels",
- "description": "Labels assigned to the epic",
+ "description": "Labels assigned to the epic.",
"args": [
{
"name": "after",
@@ -4722,7 +5326,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -4779,7 +5383,7 @@
},
{
"name": "parent",
- "description": "Parent epic of the epic",
+ "description": "Parent epic of the epic.",
"args": [
],
@@ -4793,7 +5397,7 @@
},
{
"name": "participants",
- "description": "List of participants for the epic",
+ "description": "List of participants for the epic.",
"args": [
{
"name": "after",
@@ -4846,11 +5450,11 @@
},
{
"name": "reference",
- "description": "Internal reference of the epic. Returned in shortened format by default",
+ "description": "Internal reference of the epic. Returned in shortened format by default.",
"args": [
{
"name": "full",
- "description": "Indicates if the reference should be returned in full",
+ "description": "Indicates if the reference should be returned in full.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -4873,7 +5477,7 @@
},
{
"name": "relationPath",
- "description": "URI path of the epic-issue relationship",
+ "description": "URI path of the epic-issue relationship.",
"args": [
],
@@ -4887,7 +5491,7 @@
},
{
"name": "relativePosition",
- "description": "The relative position of the epic in the epic tree",
+ "description": "The relative position of the epic in the epic tree.",
"args": [
],
@@ -4901,7 +5505,7 @@
},
{
"name": "startDate",
- "description": "Start date of the epic",
+ "description": "Start date of the epic.",
"args": [
],
@@ -4915,7 +5519,7 @@
},
{
"name": "startDateFixed",
- "description": "Fixed start date of the epic",
+ "description": "Fixed start date of the epic.",
"args": [
],
@@ -4929,7 +5533,7 @@
},
{
"name": "startDateFromMilestones",
- "description": "Inherited start date of the epic from milestones",
+ "description": "Inherited start date of the epic from milestones.",
"args": [
],
@@ -4943,7 +5547,7 @@
},
{
"name": "startDateIsFixed",
- "description": "Indicates if the start date has been manually set",
+ "description": "Indicates if the start date has been manually set.",
"args": [
],
@@ -4957,7 +5561,7 @@
},
{
"name": "state",
- "description": "State of the epic",
+ "description": "State of the epic.",
"args": [
],
@@ -4975,7 +5579,7 @@
},
{
"name": "subscribed",
- "description": "Indicates the currently logged in user is subscribed to the epic",
+ "description": "Indicates the currently logged in user is subscribed to the epic.",
"args": [
],
@@ -4993,7 +5597,7 @@
},
{
"name": "title",
- "description": "Title of the epic",
+ "description": "Title of the epic.",
"args": [
],
@@ -5007,7 +5611,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the epic was updated",
+ "description": "Timestamp of when the epic was updated.",
"args": [
],
@@ -5021,7 +5625,7 @@
},
{
"name": "upvotes",
- "description": "Number of upvotes the epic has received",
+ "description": "Number of upvotes the epic has received.",
"args": [
],
@@ -5039,7 +5643,7 @@
},
{
"name": "userDiscussionsCount",
- "description": "Number of user discussions in the epic",
+ "description": "Number of user discussions in the epic.",
"args": [
],
@@ -5057,7 +5661,7 @@
},
{
"name": "userNotesCount",
- "description": "Number of user notes of the epic",
+ "description": "Number of user notes of the epic.",
"args": [
],
@@ -5093,7 +5697,7 @@
},
{
"name": "userPreferences",
- "description": "User preferences for the epic on the issue board",
+ "description": "User preferences for the epic on the issue board.",
"args": [
],
@@ -5107,7 +5711,7 @@
},
{
"name": "webPath",
- "description": "Web path of the epic",
+ "description": "Web path of the epic.",
"args": [
],
@@ -5125,7 +5729,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the epic",
+ "description": "Web URL of the epic.",
"args": [
],
@@ -5153,6 +5757,11 @@
"kind": "INTERFACE",
"name": "CurrentUserTodos",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "Eventable",
+ "ofType": null
}
],
"enumValues": null,
@@ -5277,7 +5886,7 @@
"fields": [
{
"name": "collapsed",
- "description": "Indicates epic should be displayed as collapsed",
+ "description": "Indicates epic should be displayed as collapsed.",
"args": [
],
@@ -5304,7 +5913,7 @@
{
"kind": "SCALAR",
"name": "BoardID",
- "description": "Identifier of Board",
+ "description": "Identifier of Board.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -5319,7 +5928,7 @@
"inputFields": [
{
"name": "labelName",
- "description": "Filter by label name",
+ "description": "Filter by label name.",
"type": {
"kind": "LIST",
"name": null,
@@ -5333,7 +5942,7 @@
},
{
"name": "milestoneTitle",
- "description": "Filter by milestone title",
+ "description": "Filter by milestone title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5343,7 +5952,7 @@
},
{
"name": "assigneeUsername",
- "description": "Filter by assignee username",
+ "description": "Filter by assignee username.",
"type": {
"kind": "LIST",
"name": null,
@@ -5357,7 +5966,7 @@
},
{
"name": "authorUsername",
- "description": "Filter by author username",
+ "description": "Filter by author username.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5367,7 +5976,7 @@
},
{
"name": "releaseTag",
- "description": "Filter by release tag",
+ "description": "Filter by release tag.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5377,7 +5986,7 @@
},
{
"name": "myReactionEmoji",
- "description": "Filter by reaction emoji",
+ "description": "Filter by reaction emoji.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5387,7 +5996,7 @@
},
{
"name": "epicId",
- "description": "Filter by epic ID. Incompatible with epicWildcardId",
+ "description": "Filter by epic ID. Incompatible with epicWildcardId.",
"type": {
"kind": "SCALAR",
"name": "EpicID",
@@ -5397,7 +6006,7 @@
},
{
"name": "iterationTitle",
- "description": "Filter by iteration title",
+ "description": "Filter by iteration title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5407,7 +6016,7 @@
},
{
"name": "weight",
- "description": "Filter by weight",
+ "description": "Filter by weight.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5417,7 +6026,7 @@
},
{
"name": "not",
- "description": "List of negated params. Warning: this argument is experimental and a subject to change in future",
+ "description": "List of negated params. Warning: this argument is experimental and a subject to change in future.",
"type": {
"kind": "INPUT_OBJECT",
"name": "NegatedBoardIssueInput",
@@ -5427,7 +6036,7 @@
},
{
"name": "search",
- "description": "Search query for issue title or description",
+ "description": "Search query for issue title or description.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -5437,7 +6046,7 @@
},
{
"name": "epicWildcardId",
- "description": "Filter by epic ID wildcard. Incompatible with epicId",
+ "description": "Filter by epic ID wildcard. Incompatible with epicId.",
"type": {
"kind": "ENUM",
"name": "EpicWildcardId",
@@ -5447,7 +6056,7 @@
},
{
"name": "iterationWildcardId",
- "description": "Filter by iteration ID wildcard",
+ "description": "Filter by iteration ID wildcard.",
"type": {
"kind": "ENUM",
"name": "IterationWildcardId",
@@ -5467,7 +6076,7 @@
"fields": [
{
"name": "assignee",
- "description": "Assignee in the list",
+ "description": "Assignee in the list.",
"args": [
],
@@ -5481,7 +6090,7 @@
},
{
"name": "collapsed",
- "description": "Indicates if list is collapsed for this user",
+ "description": "Indicates if list is collapsed for this user.",
"args": [
],
@@ -5495,7 +6104,7 @@
},
{
"name": "id",
- "description": "ID (global ID) of the list",
+ "description": "ID (global ID) of the list.",
"args": [
],
@@ -5513,7 +6122,7 @@
},
{
"name": "issues",
- "description": "Board issues",
+ "description": "Board issues.",
"args": [
{
"name": "filters",
@@ -5576,7 +6185,7 @@
},
{
"name": "issuesCount",
- "description": "Count of issues in the list",
+ "description": "Count of issues in the list.",
"args": [
],
@@ -5590,7 +6199,7 @@
},
{
"name": "iteration",
- "description": "Iteration of the list",
+ "description": "Iteration of the list.",
"args": [
],
@@ -5604,7 +6213,7 @@
},
{
"name": "label",
- "description": "Label of the list",
+ "description": "Label of the list.",
"args": [
],
@@ -5618,7 +6227,7 @@
},
{
"name": "limitMetric",
- "description": "The current limit metric for the list",
+ "description": "The current limit metric for the list.",
"args": [
],
@@ -5632,7 +6241,7 @@
},
{
"name": "listType",
- "description": "Type of the list",
+ "description": "Type of the list.",
"args": [
],
@@ -5650,7 +6259,7 @@
},
{
"name": "maxIssueCount",
- "description": "Maximum number of issues in the list",
+ "description": "Maximum number of issues in the list.",
"args": [
],
@@ -5664,7 +6273,7 @@
},
{
"name": "maxIssueWeight",
- "description": "Maximum weight of issues in the list",
+ "description": "Maximum weight of issues in the list.",
"args": [
],
@@ -5678,7 +6287,7 @@
},
{
"name": "milestone",
- "description": "Milestone of the list",
+ "description": "Milestone of the list.",
"args": [
],
@@ -5692,7 +6301,7 @@
},
{
"name": "position",
- "description": "Position of list within the board",
+ "description": "Position of list within the board.",
"args": [
],
@@ -5706,7 +6315,7 @@
},
{
"name": "title",
- "description": "Title of the list",
+ "description": "Title of the list.",
"args": [
],
@@ -5724,7 +6333,7 @@
},
{
"name": "totalWeight",
- "description": "Total weight of all issues in the list",
+ "description": "Total weight of all issues in the list.",
"args": [
],
@@ -5818,20 +6427,6 @@
"fields": null,
"inputFields": [
{
- "name": "boardId",
- "description": "Global ID of the issue board to mutate.",
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "BoardID",
- "ofType": null
- }
- },
- "defaultValue": null
- },
- {
"name": "backlog",
"description": "Create the backlog list.",
"type": {
@@ -5852,6 +6447,20 @@
"defaultValue": null
},
{
+ "name": "boardId",
+ "description": "Global ID of the issue board to mutate.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BoardID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "milestoneId",
"description": "Global ID of an existing milestone.",
"type": {
@@ -5943,7 +6552,7 @@
},
{
"name": "list",
- "description": "List of the issue board.",
+ "description": "Issue list in the issue board.",
"args": [
],
@@ -6143,7 +6752,7 @@
{
"kind": "SCALAR",
"name": "BoardsEpicBoardID",
- "description": "Identifier of Boards::EpicBoard",
+ "description": "Identifier of Boards::EpicBoard.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -6153,7 +6762,7 @@
{
"kind": "SCALAR",
"name": "BoardsEpicListID",
- "description": "Identifier of Boards::EpicList",
+ "description": "Identifier of Boards::EpicList.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -6177,7 +6786,7 @@
"fields": [
{
"name": "commit",
- "description": "Commit for the branch",
+ "description": "Commit for the branch.",
"args": [
],
@@ -6191,7 +6800,7 @@
},
{
"name": "name",
- "description": "Name of the branch",
+ "description": "Name of the branch.",
"args": [
],
@@ -6222,7 +6831,7 @@
"fields": [
{
"name": "completedCount",
- "description": "Number of closed issues as of this day",
+ "description": "Number of closed issues as of this day.",
"args": [
],
@@ -6240,7 +6849,7 @@
},
{
"name": "completedWeight",
- "description": "Total weight of closed issues as of this day",
+ "description": "Total weight of closed issues as of this day.",
"args": [
],
@@ -6258,7 +6867,7 @@
},
{
"name": "date",
- "description": "Date for burnup totals",
+ "description": "Date for burnup totals.",
"args": [
],
@@ -6276,7 +6885,7 @@
},
{
"name": "scopeCount",
- "description": "Number of issues as of this day",
+ "description": "Number of issues as of this day.",
"args": [
],
@@ -6294,7 +6903,7 @@
},
{
"name": "scopeWeight",
- "description": "Total weight of issues as of this day",
+ "description": "Total weight of issues as of this day.",
"args": [
],
@@ -6320,6 +6929,33 @@
},
{
"kind": "OBJECT",
+ "name": "CiApplicationSettings",
+ "description": null,
+ "fields": [
+ {
+ "name": "keepLatestArtifact",
+ "description": "Whether to keep the latest jobs artifacts.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "CiBuildNeed",
"description": null,
"fields": [
@@ -6562,7 +7198,7 @@
"fields": [
{
"name": "errors",
- "description": "Linting errors",
+ "description": "Linting errors.",
"args": [
],
@@ -6584,7 +7220,7 @@
},
{
"name": "mergedYaml",
- "description": "Merged CI config YAML",
+ "description": "Merged CI configuration YAML.",
"args": [
],
@@ -6598,7 +7234,7 @@
},
{
"name": "stages",
- "description": "Stages of the pipeline",
+ "description": "Stages of the pipeline.",
"args": [
{
"name": "after",
@@ -6651,7 +7287,7 @@
},
{
"name": "status",
- "description": "Status of linting, can be either valid or invalid",
+ "description": "Status of linting, can be either valid or invalid.",
"args": [
],
@@ -6678,7 +7314,7 @@
"fields": [
{
"name": "jobs",
- "description": "Jobs in group",
+ "description": "Jobs in group.",
"args": [
{
"name": "after",
@@ -6731,7 +7367,7 @@
},
{
"name": "name",
- "description": "Name of the job group",
+ "description": "Name of the job group.",
"args": [
],
@@ -6745,7 +7381,7 @@
},
{
"name": "size",
- "description": "Size of the job group",
+ "description": "Size of the job group.",
"args": [
],
@@ -7297,7 +7933,7 @@
"fields": [
{
"name": "name",
- "description": "Name of the need",
+ "description": "Name of the need.",
"args": [
],
@@ -7436,7 +8072,7 @@
"fields": [
{
"name": "groups",
- "description": "Groups of jobs for the stage",
+ "description": "Groups of jobs for the stage.",
"args": [
{
"name": "after",
@@ -7489,7 +8125,7 @@
},
{
"name": "name",
- "description": "Name of the stage",
+ "description": "Name of the stage.",
"args": [
],
@@ -7651,7 +8287,7 @@
"fields": [
{
"name": "detailedStatus",
- "description": "Detailed status of the group",
+ "description": "Detailed status of the group.",
"args": [
],
@@ -7665,7 +8301,7 @@
},
{
"name": "jobs",
- "description": "Jobs in group",
+ "description": "Jobs in group.",
"args": [
{
"name": "after",
@@ -7718,7 +8354,7 @@
},
{
"name": "name",
- "description": "Name of the job group",
+ "description": "Name of the job group.",
"args": [
],
@@ -7732,7 +8368,7 @@
},
{
"name": "size",
- "description": "Size of the group",
+ "description": "Size of the group.",
"args": [
],
@@ -7871,7 +8507,7 @@
"fields": [
{
"name": "artifacts",
- "description": "Artifacts generated by the job",
+ "description": "Artifacts generated by the job.",
"args": [
{
"name": "after",
@@ -7924,7 +8560,7 @@
},
{
"name": "detailedStatus",
- "description": "Detailed status of the job",
+ "description": "Detailed status of the job.",
"args": [
],
@@ -7938,7 +8574,7 @@
},
{
"name": "name",
- "description": "Name of the job",
+ "description": "Name of the job.",
"args": [
],
@@ -7952,7 +8588,7 @@
},
{
"name": "needs",
- "description": "References to builds that must complete before the jobs run",
+ "description": "References to builds that must complete before the jobs run.",
"args": [
{
"name": "after",
@@ -8005,7 +8641,7 @@
},
{
"name": "pipeline",
- "description": "Pipeline the job belongs to",
+ "description": "Pipeline the job belongs to.",
"args": [
],
@@ -8019,7 +8655,7 @@
},
{
"name": "scheduledAt",
- "description": "Schedule for the build",
+ "description": "Schedule for the build.",
"args": [
],
@@ -8046,7 +8682,7 @@
"fields": [
{
"name": "downloadPath",
- "description": "URL for downloading the artifact's file",
+ "description": "URL for downloading the artifact's file.",
"args": [
],
@@ -8060,7 +8696,7 @@
},
{
"name": "fileType",
- "description": "File type of the artifact",
+ "description": "File type of the artifact.",
"args": [
],
@@ -8307,7 +8943,7 @@
{
"kind": "SCALAR",
"name": "CiPipelineID",
- "description": "Identifier of Ci::Pipeline",
+ "description": "Identifier of Ci::Pipeline.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -8321,7 +8957,7 @@
"fields": [
{
"name": "detailedStatus",
- "description": "Detailed status of the stage",
+ "description": "Detailed status of the stage.",
"args": [
],
@@ -8335,7 +8971,7 @@
},
{
"name": "groups",
- "description": "Group of jobs for the stage",
+ "description": "Group of jobs for the stage.",
"args": [
{
"name": "after",
@@ -8388,7 +9024,7 @@
},
{
"name": "name",
- "description": "Name of the stage",
+ "description": "Name of the stage.",
"args": [
],
@@ -8527,7 +9163,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp the cluster agent was created",
+ "description": "Timestamp the cluster agent was created.",
"args": [
],
@@ -8540,8 +9176,22 @@
"deprecationReason": null
},
{
+ "name": "createdByUser",
+ "description": "User object, containing information about the person who created the agent.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "id",
- "description": "ID of the cluster agent",
+ "description": "ID of the cluster agent.",
"args": [
],
@@ -8559,7 +9209,7 @@
},
{
"name": "name",
- "description": "Name of the cluster agent",
+ "description": "Name of the cluster agent.",
"args": [
],
@@ -8573,7 +9223,7 @@
},
{
"name": "project",
- "description": "The project this cluster agent is associated with",
+ "description": "The project this cluster agent is associated with.",
"args": [
],
@@ -8587,7 +9237,7 @@
},
{
"name": "tokens",
- "description": "Tokens associated with the cluster agent",
+ "description": "Tokens associated with the cluster agent.",
"args": [
{
"name": "after",
@@ -8640,7 +9290,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp the cluster agent was updated",
+ "description": "Timestamp the cluster agent was updated.",
"args": [
],
@@ -8667,7 +9317,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -8885,7 +9535,7 @@
"fields": [
{
"name": "clusterAgent",
- "description": "Cluster agent this token is associated with",
+ "description": "Cluster agent this token is associated with.",
"args": [
],
@@ -8899,7 +9549,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp the token was created",
+ "description": "Timestamp the token was created.",
"args": [
],
@@ -8912,8 +9562,22 @@
"deprecationReason": null
},
{
+ "name": "createdByUser",
+ "description": "The user who created the token.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "id",
- "description": "Global ID of the token",
+ "description": "Global ID of the token.",
"args": [
],
@@ -8944,7 +9608,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -9274,7 +9938,7 @@
{
"kind": "SCALAR",
"name": "ClustersAgentID",
- "description": "Identifier of Clusters::Agent",
+ "description": "Identifier of Clusters::Agent.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -9284,7 +9948,7 @@
{
"kind": "SCALAR",
"name": "ClustersAgentTokenID",
- "description": "Identifier of Clusters::AgentToken",
+ "description": "Identifier of Clusters::AgentToken.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -9294,7 +9958,7 @@
{
"kind": "SCALAR",
"name": "ClustersClusterID",
- "description": "Identifier of Clusters::Cluster",
+ "description": "Identifier of Clusters::Cluster.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -9548,7 +10212,7 @@
"fields": [
{
"name": "author",
- "description": "Author of the commit",
+ "description": "Author of the commit.",
"args": [
],
@@ -9562,7 +10226,7 @@
},
{
"name": "authorGravatar",
- "description": "Commit authors gravatar",
+ "description": "Commit authors gravatar.",
"args": [
],
@@ -9576,7 +10240,7 @@
},
{
"name": "authorName",
- "description": "Commit authors name",
+ "description": "Commit authors name.",
"args": [
],
@@ -9590,7 +10254,7 @@
},
{
"name": "authoredDate",
- "description": "Timestamp of when the commit was authored",
+ "description": "Timestamp of when the commit was authored.",
"args": [
],
@@ -9604,7 +10268,7 @@
},
{
"name": "description",
- "description": "Description of the commit message",
+ "description": "Description of the commit message.",
"args": [
],
@@ -9632,7 +10296,7 @@
},
{
"name": "id",
- "description": "ID (global ID) of the commit",
+ "description": "ID (global ID) of the commit.",
"args": [
],
@@ -9650,7 +10314,7 @@
},
{
"name": "message",
- "description": "Raw commit message",
+ "description": "Raw commit message.",
"args": [
],
@@ -9664,7 +10328,7 @@
},
{
"name": "pipelines",
- "description": "Pipelines of the commit ordered latest first",
+ "description": "Pipelines of the commit ordered latest first.",
"args": [
{
"name": "status",
@@ -9747,7 +10411,7 @@
},
{
"name": "sha",
- "description": "SHA1 ID of the commit",
+ "description": "SHA1 ID of the commit.",
"args": [
],
@@ -9765,7 +10429,7 @@
},
{
"name": "shortId",
- "description": "Short SHA1 ID of the commit",
+ "description": "Short SHA1 ID of the commit.",
"args": [
],
@@ -9783,7 +10447,7 @@
},
{
"name": "signatureHtml",
- "description": "Rendered HTML of the commit signature",
+ "description": "Rendered HTML of the commit signature.",
"args": [
],
@@ -9797,7 +10461,7 @@
},
{
"name": "title",
- "description": "Title of the commit message",
+ "description": "Title of the commit message.",
"args": [
],
@@ -9825,7 +10489,7 @@
},
{
"name": "webPath",
- "description": "Web path of the commit",
+ "description": "Web path of the commit.",
"args": [
],
@@ -9843,7 +10507,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the commit",
+ "description": "Web URL of the commit.",
"args": [
],
@@ -9875,7 +10539,7 @@
"inputFields": [
{
"name": "action",
- "description": "The action to perform, create, delete, move, update, chmod",
+ "description": "The action to perform, create, delete, move, update, chmod.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -9889,7 +10553,7 @@
},
{
"name": "filePath",
- "description": "Full path to the file",
+ "description": "Full path to the file.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -9903,7 +10567,7 @@
},
{
"name": "content",
- "description": "Content of the file",
+ "description": "Content of the file.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -9913,7 +10577,7 @@
},
{
"name": "previousPath",
- "description": "Original full path to the file being moved",
+ "description": "Original full path to the file being moved.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -9923,7 +10587,7 @@
},
{
"name": "lastCommitId",
- "description": "Last known file commit ID",
+ "description": "Last known file commit ID.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -9933,7 +10597,7 @@
},
{
"name": "executeFilemode",
- "description": "Enables/disables the execute flag on the file",
+ "description": "Enables/disables the execute flag on the file.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -9943,7 +10607,7 @@
},
{
"name": "encoding",
- "description": "Encoding of the file. Default is text",
+ "description": "Encoding of the file. Default is text.",
"type": {
"kind": "ENUM",
"name": "CommitEncoding",
@@ -10110,7 +10774,7 @@
},
{
"name": "message",
- "description": "Raw commit message",
+ "description": "Raw commit message.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -10301,7 +10965,7 @@
"fields": [
{
"name": "color",
- "description": "Hexadecimal representation of compliance framework's label color",
+ "description": "Hexadecimal representation of compliance framework's label color.",
"args": [
],
@@ -10319,7 +10983,7 @@
},
{
"name": "description",
- "description": "Description of the compliance framework",
+ "description": "Description of the compliance framework.",
"args": [
],
@@ -10337,7 +11001,7 @@
},
{
"name": "id",
- "description": "Compliance framework ID",
+ "description": "Compliance framework ID.",
"args": [
],
@@ -10355,7 +11019,7 @@
},
{
"name": "name",
- "description": "Name of the compliance framework",
+ "description": "Name of the compliance framework.",
"args": [
],
@@ -10370,6 +11034,20 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "pipelineConfigurationFullPath",
+ "description": "Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hippa`.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -10526,6 +11204,16 @@
"ofType": null
},
"defaultValue": null
+ },
+ {
+ "name": "pipelineConfigurationFullPath",
+ "description": "Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hippa`.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"interfaces": null,
@@ -10535,7 +11223,7 @@
{
"kind": "SCALAR",
"name": "ComplianceManagementFrameworkID",
- "description": "Identifier of ComplianceManagement::Framework",
+ "description": "Identifier of ComplianceManagement::Framework.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -10543,6 +11231,55 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "ComposerMetadata",
+ "description": "Composer metadata",
+ "fields": [
+ {
+ "name": "composerJson",
+ "description": "Data of the Composer JSON file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PackageComposerJsonType",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "targetSha",
+ "description": "Target SHA of the package.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "ConfigureSastInput",
"description": "Autogenerated input type of ConfigureSast",
@@ -10683,7 +11420,7 @@
"fields": [
{
"name": "cadence",
- "description": "This container expiration policy schedule",
+ "description": "This container expiration policy schedule.",
"args": [
],
@@ -10701,7 +11438,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the container expiration policy was created",
+ "description": "Timestamp of when the container expiration policy was created.",
"args": [
],
@@ -10719,7 +11456,7 @@
},
{
"name": "enabled",
- "description": "Indicates whether this container expiration policy is enabled",
+ "description": "Indicates whether this container expiration policy is enabled.",
"args": [
],
@@ -10737,7 +11474,7 @@
},
{
"name": "keepN",
- "description": "Number of tags to retain",
+ "description": "Number of tags to retain.",
"args": [
],
@@ -10751,7 +11488,7 @@
},
{
"name": "nameRegex",
- "description": "Tags with names matching this regex pattern will expire",
+ "description": "Tags with names matching this regex pattern will expire.",
"args": [
],
@@ -10765,7 +11502,7 @@
},
{
"name": "nameRegexKeep",
- "description": "Tags with names matching this regex pattern will be preserved",
+ "description": "Tags with names matching this regex pattern will be preserved.",
"args": [
],
@@ -10779,7 +11516,7 @@
},
{
"name": "nextRunAt",
- "description": "Next time that this container expiration policy will get executed",
+ "description": "Next time that this container expiration policy will get executed.",
"args": [
],
@@ -10793,7 +11530,7 @@
},
{
"name": "olderThan",
- "description": "Tags older that this will expire",
+ "description": "Tags older that this will expire.",
"args": [
],
@@ -10807,7 +11544,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the container expiration policy was updated",
+ "description": "Timestamp of when the container expiration policy was updated.",
"args": [
],
@@ -11097,7 +11834,7 @@
},
{
"name": "project",
- "description": "Project of the container registry",
+ "description": "Project of the container registry.",
"args": [
],
@@ -11416,7 +12153,7 @@
},
{
"name": "project",
- "description": "Project of the container registry",
+ "description": "Project of the container registry.",
"args": [
],
@@ -11448,7 +12185,7 @@
},
{
"name": "tags",
- "description": "Tags of the container repository",
+ "description": "Tags of the container repository.",
"args": [
{
"name": "after",
@@ -11591,7 +12328,7 @@
{
"kind": "SCALAR",
"name": "ContainerRepositoryID",
- "description": "Identifier of ContainerRepository",
+ "description": "Identifier of ContainerRepository.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -11600,6 +12337,77 @@
},
{
"kind": "ENUM",
+ "name": "ContainerRepositorySort",
+ "description": "Values for sorting container repositories",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "updated_desc",
+ "description": "Updated at descending order",
+ "isDeprecated": true,
+ "deprecationReason": "Use UPDATED_DESC. Deprecated in 13.5."
+ },
+ {
+ "name": "updated_asc",
+ "description": "Updated at ascending order",
+ "isDeprecated": true,
+ "deprecationReason": "Use UPDATED_ASC. Deprecated in 13.5."
+ },
+ {
+ "name": "created_desc",
+ "description": "Created at descending order",
+ "isDeprecated": true,
+ "deprecationReason": "Use CREATED_DESC. Deprecated in 13.5."
+ },
+ {
+ "name": "created_asc",
+ "description": "Created at ascending order",
+ "isDeprecated": true,
+ "deprecationReason": "Use CREATED_ASC. Deprecated in 13.5."
+ },
+ {
+ "name": "UPDATED_DESC",
+ "description": "Updated at descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "UPDATED_ASC",
+ "description": "Updated at ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "CREATED_DESC",
+ "description": "Created at descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "CREATED_ASC",
+ "description": "Created at ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "NAME_ASC",
+ "description": "Name by ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "NAME_DESC",
+ "description": "Name by descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
"name": "ContainerRepositoryStatus",
"description": "Status of a container repository",
"fields": null,
@@ -12012,7 +12820,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation.",
+ "description": "The to-do item after mutation.",
"args": [
],
@@ -12200,7 +13008,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project full path the resource is associated with.",
+ "description": "Full path of the project with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -12210,7 +13018,7 @@
},
{
"name": "groupPath",
- "description": "The group full path the resource is associated with.",
+ "description": "Full path of the group with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -12230,7 +13038,7 @@
},
{
"name": "hideBacklogList",
- "description": "Whether or not backlog list is hidden",
+ "description": "Whether or not backlog list is hidden.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -12240,7 +13048,7 @@
},
{
"name": "hideClosedList",
- "description": "Whether or not closed list is hidden",
+ "description": "Whether or not closed list is hidden.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -12290,7 +13098,7 @@
},
{
"name": "labels",
- "description": "Labels of the issue",
+ "description": "Labels of the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -12905,38 +13713,20 @@
"fields": null,
"inputFields": [
{
- "name": "name",
- "description": "Name of the segment.",
+ "name": "namespaceId",
+ "description": "Namespace ID to set for the segment.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "String",
+ "name": "NamespaceID",
"ofType": null
}
},
"defaultValue": null
},
{
- "name": "groupIds",
- "description": "The array of group IDs to set for the segment.",
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "GroupID",
- "ofType": null
- }
- }
- },
- "defaultValue": null
- },
- {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -13040,7 +13830,7 @@
},
{
"name": "body",
- "description": "Content of the note",
+ "description": "Content of the note.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13064,7 +13854,7 @@
},
{
"name": "position",
- "description": "The position of this note on a diff",
+ "description": "The position of this note on a diff.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13388,7 +14178,7 @@
},
{
"name": "body",
- "description": "Content of the note",
+ "description": "Content of the note.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13412,7 +14202,7 @@
},
{
"name": "position",
- "description": "The position of this note on a diff",
+ "description": "The position of this note on a diff.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13514,7 +14304,7 @@
"inputFields": [
{
"name": "description",
- "description": "Description of the issue",
+ "description": "Description of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -13524,7 +14314,7 @@
},
{
"name": "dueDate",
- "description": "Due date of the issue",
+ "description": "Due date of the issue.",
"type": {
"kind": "SCALAR",
"name": "ISO8601Date",
@@ -13534,7 +14324,7 @@
},
{
"name": "confidential",
- "description": "Indicates the issue is confidential",
+ "description": "Indicates the issue is confidential.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -13544,7 +14334,7 @@
},
{
"name": "locked",
- "description": "Indicates discussion is locked on the issue",
+ "description": "Indicates discussion is locked on the issue.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -13578,7 +14368,7 @@
},
{
"name": "title",
- "description": "Title of the issue",
+ "description": "Title of the issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -13602,7 +14392,7 @@
},
{
"name": "labels",
- "description": "Labels of the issue",
+ "description": "Labels of the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -13803,8 +14593,8 @@
"fields": null,
"inputFields": [
{
- "name": "groupPath",
- "description": "The target group for the iteration.",
+ "name": "projectPath",
+ "description": "Full path of the project with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -13813,8 +14603,8 @@
"defaultValue": null
},
{
- "name": "projectPath",
- "description": "The target project for the iteration.",
+ "name": "groupPath",
+ "description": "Full path of the group with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -13966,7 +14756,7 @@
},
{
"name": "body",
- "description": "Content of the note",
+ "description": "Content of the note.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -14209,6 +14999,26 @@
"fields": null,
"inputFields": [
{
+ "name": "captchaResponse",
+ "description": "A 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\".",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "spamLogId",
+ "description": "The 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\".",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "title",
"description": "Title of the snippet.",
"type": {
@@ -14313,6 +15123,20 @@
"description": "Autogenerated return type of CreateSnippet",
"fields": [
{
+ "name": "captchaSiteKey",
+ "description": "The 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.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
@@ -14353,6 +15177,20 @@
"deprecationReason": null
},
{
+ "name": "needsCaptchaResponse",
+ "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.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "snippet",
"description": "The snippet after mutation.",
"args": [
@@ -14368,7 +15206,7 @@
},
{
"name": "spam",
- "description": "Indicates whether the operation returns a record detected as spam.",
+ "description": "Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response.",
"args": [
],
@@ -14379,6 +15217,20 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "spamLogId",
+ "description": "The 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.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -14539,7 +15391,7 @@
"fields": [
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -14583,7 +15435,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -14648,7 +15500,7 @@
"fields": [
{
"name": "external",
- "description": "Whether the emoji is an external link",
+ "description": "Whether the emoji is an external link.",
"args": [
],
@@ -14666,7 +15518,7 @@
},
{
"name": "id",
- "description": "The ID of the emoji",
+ "description": "The ID of the emoji.",
"args": [
],
@@ -14684,7 +15536,7 @@
},
{
"name": "name",
- "description": "The name of the emoji",
+ "description": "The name of the emoji.",
"args": [
],
@@ -14702,7 +15554,7 @@
},
{
"name": "url",
- "description": "The link to file of the emoji",
+ "description": "The link to file of the emoji.",
"args": [
],
@@ -14841,7 +15693,7 @@
{
"kind": "SCALAR",
"name": "CustomEmojiID",
- "description": "Identifier of CustomEmoji",
+ "description": "Identifier of CustomEmoji.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -14975,6 +15827,791 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "DastProfile",
+ "description": "Represents a DAST Profile",
+ "fields": [
+ {
+ "name": "dastScannerProfile",
+ "description": "The associated scanner profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastScannerProfile",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastSiteProfile",
+ "description": "The associated site profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastSiteProfile",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "description",
+ "description": "The description of the scan.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "editPath",
+ "description": "Relative web path to the edit page of a profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastProfileID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastProfileConnection",
+ "description": "The connection type for DastProfile.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "DastProfileEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "DastProfile",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileCreateInput",
+ "description": "Autogenerated input type of DastProfileCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "The project the profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the profile.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "description",
+ "description": "The description of the profile. Defaults to an empty string.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": "\"\""
+ },
+ {
+ "name": "dastSiteProfileId",
+ "description": "ID of the site profile to be associated.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastSiteProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "dastScannerProfileId",
+ "description": "ID of the scanner profile to be associated.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "runAfterCreate",
+ "description": "Run scan using profile after creation. Defaults to false.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastProfileCreatePayload",
+ "description": "Autogenerated return type of DastProfileCreate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastProfile",
+ "description": "The created profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfile",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineUrl",
+ "description": "The URL of the pipeline that was created. Requires `runAfterCreate` to be set to `true`.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileDeleteInput",
+ "description": "Autogenerated input type of DastProfileDelete",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "ID of the profile to be deleted.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastProfileDeletePayload",
+ "description": "Autogenerated return type of DastProfileDelete",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastProfileEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfile",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "DastProfileID",
+ "description": "Identifier of Dast::Profile.",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileRunInput",
+ "description": "Autogenerated input type of DastProfileRun",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "Full path for the project the scanner profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the profile to be used for the scan.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastProfileRunPayload",
+ "description": "Autogenerated return type of DastProfileRun",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineUrl",
+ "description": "URL of the pipeline that was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileUpdateInput",
+ "description": "Autogenerated input type of DastProfileUpdate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "ID of the profile to be deleted.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "fullPath",
+ "description": "The project the profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "name",
+ "description": "The name of the profile.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "description",
+ "description": "The description of the profile. Defaults to an empty string.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": "\"\""
+ },
+ {
+ "name": "dastSiteProfileId",
+ "description": "ID of the site profile to be associated.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "DastSiteProfileID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "dastScannerProfileId",
+ "description": "ID of the scanner profile to be associated.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "runAfterUpdate",
+ "description": "Run scan using profile after update. Defaults to false.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastProfileUpdatePayload",
+ "description": "Autogenerated return type of DastProfileUpdate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastProfile",
+ "description": "The updated profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfile",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineUrl",
+ "description": "The URL of the pipeline that was created. Requires the input argument `runAfterUpdate` to be set to `true` when calling the mutation, otherwise no pipeline will be created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "DastScanTypeEnum",
"description": null,
@@ -15004,7 +16641,7 @@
"fields": [
{
"name": "editPath",
- "description": "Relative web path to the edit page of a scanner profile",
+ "description": "Relative web path to the edit page of a scanner profile.",
"args": [
],
@@ -15018,7 +16655,7 @@
},
{
"name": "globalId",
- "description": "ID of the DAST scanner profile Deprecated in 13.6: Use `id`.",
+ "description": "ID of the DAST scanner profile. Deprecated in 13.6: Use `id`.",
"args": [
],
@@ -15036,7 +16673,7 @@
},
{
"name": "id",
- "description": "ID of the DAST scanner profile",
+ "description": "ID of the DAST scanner profile.",
"args": [
],
@@ -15054,7 +16691,7 @@
},
{
"name": "profileName",
- "description": "Name of the DAST scanner profile",
+ "description": "Name of the DAST scanner profile.",
"args": [
],
@@ -15100,7 +16737,7 @@
},
{
"name": "spiderTimeout",
- "description": "The maximum number of minutes allowed for the spider to traverse the site",
+ "description": "The maximum number of minutes allowed for the spider to traverse the site.",
"args": [
],
@@ -15114,7 +16751,7 @@
},
{
"name": "targetTimeout",
- "description": "The maximum number of seconds allowed for the site under test to respond to a request",
+ "description": "The maximum number of seconds allowed for the site under test to respond to a request.",
"args": [
],
@@ -15549,7 +17186,7 @@
{
"kind": "SCALAR",
"name": "DastScannerProfileID",
- "description": "Identifier of DastScannerProfile",
+ "description": "Identifier of DastScannerProfile.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -15751,7 +17388,7 @@
"fields": [
{
"name": "editPath",
- "description": "Relative web path to the edit page of a site profile",
+ "description": "Relative web path to the edit page of a site profile.",
"args": [
],
@@ -15765,7 +17402,7 @@
},
{
"name": "id",
- "description": "ID of the site profile",
+ "description": "ID of the site profile.",
"args": [
],
@@ -15783,7 +17420,7 @@
},
{
"name": "normalizedTargetUrl",
- "description": "Normalized URL of the target to be scanned",
+ "description": "Normalized URL of the target to be scanned.",
"args": [
],
@@ -15797,7 +17434,7 @@
},
{
"name": "profileName",
- "description": "The name of the site profile",
+ "description": "The name of the site profile.",
"args": [
],
@@ -15811,7 +17448,7 @@
},
{
"name": "targetUrl",
- "description": "The URL of the target to be scanned",
+ "description": "The URL of the target to be scanned.",
"args": [
],
@@ -15843,7 +17480,7 @@
},
{
"name": "validationStatus",
- "description": "The current validation status of the site profile",
+ "description": "The current validation status of the site profile.",
"args": [
],
@@ -16206,7 +17843,7 @@
{
"kind": "SCALAR",
"name": "DastSiteProfileID",
- "description": "Identifier of DastSiteProfile",
+ "description": "Identifier of DastSiteProfile.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -16568,7 +18205,7 @@
{
"kind": "SCALAR",
"name": "DastSiteTokenID",
- "description": "Identifier of DastSiteToken",
+ "description": "Identifier of DastSiteToken.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -16582,7 +18219,7 @@
"fields": [
{
"name": "id",
- "description": "Global ID of the site validation",
+ "description": "Global ID of the site validation.",
"args": [
],
@@ -16600,7 +18237,7 @@
},
{
"name": "normalizedTargetUrl",
- "description": "Normalized URL of the target to be validated",
+ "description": "Normalized URL of the target to be validated.",
"args": [
],
@@ -16614,7 +18251,7 @@
},
{
"name": "status",
- "description": "Status of the site validation",
+ "description": "Status of the site validation.",
"args": [
],
@@ -16907,7 +18544,7 @@
{
"kind": "SCALAR",
"name": "DastSiteValidationID",
- "description": "Identifier of DastSiteValidation",
+ "description": "Identifier of DastSiteValidation.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -16915,6 +18552,108 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "DastSiteValidationRevokeInput",
+ "description": "Autogenerated input type of DastSiteValidationRevoke",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "The project the site validation belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "normalizedTargetUrl",
+ "description": "Normalized URL of the target to be revoked.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DastSiteValidationRevokePayload",
+ "description": "Autogenerated return type of DastSiteValidationRevoke",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "DastSiteValidationStrategyEnum",
"description": null,
@@ -17248,7 +18987,7 @@
"fields": [
{
"name": "completed",
- "description": "Whether or not the entire queue was processed in time; if not, retrying the same request is safe",
+ "description": "Whether or not the entire queue was processed in time; if not, retrying the same request is safe.",
"args": [
],
@@ -17262,7 +19001,7 @@
},
{
"name": "deletedJobs",
- "description": "The number of matching jobs deleted",
+ "description": "The number of matching jobs deleted.",
"args": [
],
@@ -17276,7 +19015,7 @@
},
{
"name": "queueSize",
- "description": "The queue size after processing",
+ "description": "The queue size after processing.",
"args": [
],
@@ -17303,7 +19042,7 @@
"fields": [
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -17347,7 +19086,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -17370,7 +19109,7 @@
},
{
"name": "diffRefs",
- "description": "The diff refs for this design",
+ "description": "The diff refs for this design.",
"args": [
],
@@ -17388,7 +19127,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -17445,7 +19184,7 @@
},
{
"name": "event",
- "description": "How this design was changed in the current version",
+ "description": "How this design was changed in the current version.",
"args": [
],
@@ -17463,7 +19202,7 @@
},
{
"name": "filename",
- "description": "The filename of the design",
+ "description": "The filename of the design.",
"args": [
],
@@ -17481,7 +19220,7 @@
},
{
"name": "fullPath",
- "description": "The full path to the design file",
+ "description": "The full path to the design file.",
"args": [
],
@@ -17499,7 +19238,7 @@
},
{
"name": "id",
- "description": "The ID of this design",
+ "description": "The ID of this design.",
"args": [
],
@@ -17517,7 +19256,7 @@
},
{
"name": "image",
- "description": "The URL of the full-sized image",
+ "description": "The URL of the full-sized image.",
"args": [
],
@@ -17549,7 +19288,7 @@
},
{
"name": "issue",
- "description": "The issue the design belongs to",
+ "description": "The issue the design belongs to.",
"args": [
],
@@ -17567,7 +19306,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -17624,7 +19363,7 @@
},
{
"name": "notesCount",
- "description": "The total count of user-created notes for this design",
+ "description": "The total count of user-created notes for this design.",
"args": [
],
@@ -17642,7 +19381,7 @@
},
{
"name": "project",
- "description": "The project the design belongs to",
+ "description": "The project the design belongs to.",
"args": [
],
@@ -17660,7 +19399,7 @@
},
{
"name": "versions",
- "description": "All versions related to this design ordered newest first",
+ "description": "All versions related to this design ordered newest first.",
"args": [
{
"name": "earlierOrEqualToSha",
@@ -17764,7 +19503,7 @@
"fields": [
{
"name": "design",
- "description": "The underlying design",
+ "description": "The underlying design.",
"args": [
],
@@ -17782,7 +19521,7 @@
},
{
"name": "diffRefs",
- "description": "The diff refs for this design",
+ "description": "The diff refs for this design.",
"args": [
],
@@ -17800,7 +19539,7 @@
},
{
"name": "event",
- "description": "How this design was changed in the current version",
+ "description": "How this design was changed in the current version.",
"args": [
],
@@ -17818,7 +19557,7 @@
},
{
"name": "filename",
- "description": "The filename of the design",
+ "description": "The filename of the design.",
"args": [
],
@@ -17836,7 +19575,7 @@
},
{
"name": "fullPath",
- "description": "The full path to the design file",
+ "description": "The full path to the design file.",
"args": [
],
@@ -17854,7 +19593,7 @@
},
{
"name": "id",
- "description": "The ID of this design",
+ "description": "The ID of this design.",
"args": [
],
@@ -17872,7 +19611,7 @@
},
{
"name": "image",
- "description": "The URL of the full-sized image",
+ "description": "The URL of the full-sized image.",
"args": [
],
@@ -17904,7 +19643,7 @@
},
{
"name": "issue",
- "description": "The issue the design belongs to",
+ "description": "The issue the design belongs to.",
"args": [
],
@@ -17922,7 +19661,7 @@
},
{
"name": "notesCount",
- "description": "The total count of user-created notes for this design",
+ "description": "The total count of user-created notes for this design.",
"args": [
],
@@ -17940,7 +19679,7 @@
},
{
"name": "project",
- "description": "The project the design belongs to",
+ "description": "The project the design belongs to.",
"args": [
],
@@ -17958,7 +19697,7 @@
},
{
"name": "version",
- "description": "The version this design-at-versions is pinned to",
+ "description": "The version this design-at-versions is pinned to.",
"args": [
],
@@ -18105,7 +19844,7 @@
"fields": [
{
"name": "copyState",
- "description": "Copy state of the design collection",
+ "description": "Copy state of the design collection.",
"args": [
],
@@ -18119,7 +19858,7 @@
},
{
"name": "design",
- "description": "Find a specific design",
+ "description": "Find a specific design.",
"args": [
{
"name": "id",
@@ -18152,7 +19891,7 @@
},
{
"name": "designAtVersion",
- "description": "Find a design as of a version",
+ "description": "Find a design as of a version.",
"args": [
{
"name": "id",
@@ -18179,7 +19918,7 @@
},
{
"name": "designs",
- "description": "All designs for the design collection",
+ "description": "All designs for the design collection.",
"args": [
{
"name": "ids",
@@ -18282,7 +20021,7 @@
},
{
"name": "issue",
- "description": "Issue associated with the design collection",
+ "description": "Issue associated with the design collection.",
"args": [
],
@@ -18300,7 +20039,7 @@
},
{
"name": "project",
- "description": "Project associated with the design collection",
+ "description": "Project associated with the design collection.",
"args": [
],
@@ -18318,7 +20057,7 @@
},
{
"name": "version",
- "description": "A specific version",
+ "description": "A specific version.",
"args": [
{
"name": "sha",
@@ -18351,7 +20090,7 @@
},
{
"name": "versions",
- "description": "All versions related to all designs, ordered newest first",
+ "description": "All versions related to all designs, ordered newest first.",
"args": [
{
"name": "earlierOrEqualToSha",
@@ -18582,7 +20321,7 @@
"fields": [
{
"name": "diffRefs",
- "description": "The diff refs for this design",
+ "description": "The diff refs for this design.",
"args": [
],
@@ -18600,7 +20339,7 @@
},
{
"name": "event",
- "description": "How this design was changed in the current version",
+ "description": "How this design was changed in the current version.",
"args": [
],
@@ -18618,7 +20357,7 @@
},
{
"name": "filename",
- "description": "The filename of the design",
+ "description": "The filename of the design.",
"args": [
],
@@ -18636,7 +20375,7 @@
},
{
"name": "fullPath",
- "description": "The full path to the design file",
+ "description": "The full path to the design file.",
"args": [
],
@@ -18654,7 +20393,7 @@
},
{
"name": "id",
- "description": "The ID of this design",
+ "description": "The ID of this design.",
"args": [
],
@@ -18672,7 +20411,7 @@
},
{
"name": "image",
- "description": "The URL of the full-sized image",
+ "description": "The URL of the full-sized image.",
"args": [
],
@@ -18704,7 +20443,7 @@
},
{
"name": "issue",
- "description": "The issue the design belongs to",
+ "description": "The issue the design belongs to.",
"args": [
],
@@ -18722,7 +20461,7 @@
},
{
"name": "notesCount",
- "description": "The total count of user-created notes for this design",
+ "description": "The total count of user-created notes for this design.",
"args": [
],
@@ -18740,7 +20479,7 @@
},
{
"name": "project",
- "description": "The project the design belongs to",
+ "description": "The project the design belongs to.",
"args": [
],
@@ -18780,7 +20519,7 @@
"fields": [
{
"name": "designAtVersion",
- "description": "Find a design as of a version",
+ "description": "Find a design as of a version.",
"args": [
{
"name": "id",
@@ -18807,7 +20546,7 @@
},
{
"name": "version",
- "description": "Find a version",
+ "description": "Find a version.",
"args": [
{
"name": "id",
@@ -18981,7 +20720,7 @@
{
"kind": "SCALAR",
"name": "DesignManagementDesignAtVersionID",
- "description": "Identifier of DesignManagement::DesignAtVersion",
+ "description": "Identifier of DesignManagement::DesignAtVersion.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -18991,7 +20730,7 @@
{
"kind": "SCALAR",
"name": "DesignManagementDesignID",
- "description": "Identifier of DesignManagement::Design",
+ "description": "Identifier of DesignManagement::Design.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -19299,7 +21038,7 @@
{
"kind": "SCALAR",
"name": "DesignManagementVersionID",
- "description": "Identifier of DesignManagement::Version",
+ "description": "Identifier of DesignManagement::Version.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -19313,7 +21052,7 @@
"fields": [
{
"name": "designAtVersion",
- "description": "A particular design as of this version, provided it is visible at this version",
+ "description": "A particular design as of this version, provided it is visible at this version.",
"args": [
{
"name": "id",
@@ -19360,7 +21099,7 @@
},
{
"name": "designs",
- "description": "All designs that were changed in the version",
+ "description": "All designs that were changed in the version.",
"args": [
{
"name": "after",
@@ -19417,7 +21156,7 @@
},
{
"name": "designsAtVersion",
- "description": "All designs that are visible at this version, as of this version",
+ "description": "All designs that are visible at this version, as of this version.",
"args": [
{
"name": "ids",
@@ -19510,7 +21249,7 @@
},
{
"name": "id",
- "description": "ID of the design version",
+ "description": "ID of the design version.",
"args": [
],
@@ -19528,7 +21267,7 @@
},
{
"name": "sha",
- "description": "SHA of the design version",
+ "description": "SHA of the design version.",
"args": [
],
@@ -20444,7 +22183,7 @@
"fields": [
{
"name": "action",
- "description": "Action information for the status. This includes method, button title, icon, path, and title",
+ "description": "Action information for the status. This includes method, button title, icon, path, and title.",
"args": [
],
@@ -20458,7 +22197,7 @@
},
{
"name": "detailsPath",
- "description": "Path of the details for the status",
+ "description": "Path of the details for the status.",
"args": [
],
@@ -20472,7 +22211,7 @@
},
{
"name": "favicon",
- "description": "Favicon of the status",
+ "description": "Favicon of the status.",
"args": [
],
@@ -20486,7 +22225,7 @@
},
{
"name": "group",
- "description": "Group of the status",
+ "description": "Group of the status.",
"args": [
],
@@ -20500,7 +22239,7 @@
},
{
"name": "hasDetails",
- "description": "Indicates if the status has further details",
+ "description": "Indicates if the status has further details.",
"args": [
],
@@ -20514,7 +22253,7 @@
},
{
"name": "icon",
- "description": "Icon of the status",
+ "description": "Icon of the status.",
"args": [
],
@@ -20528,7 +22267,7 @@
},
{
"name": "label",
- "description": "Label of the status",
+ "description": "Label of the status.",
"args": [
],
@@ -20542,7 +22281,7 @@
},
{
"name": "text",
- "description": "Text of the status",
+ "description": "Text of the status.",
"args": [
],
@@ -20556,7 +22295,7 @@
},
{
"name": "tooltip",
- "description": "Tooltip associated with the status",
+ "description": "Tooltip associated with the status.",
"args": [
],
@@ -20582,30 +22321,8 @@
"description": "Segment",
"fields": [
{
- "name": "groups",
- "description": "Assigned groups",
- "args": [
-
- ],
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "Group",
- "ofType": null
- }
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
"name": "id",
- "description": "ID of the segment",
+ "description": "ID of the segment.",
"args": [
],
@@ -20623,7 +22340,7 @@
},
{
"name": "latestSnapshot",
- "description": "The latest adoption metrics for the segment",
+ "description": "The latest adoption metrics for the segment.",
"args": [
],
@@ -20636,19 +22353,15 @@
"deprecationReason": null
},
{
- "name": "name",
- "description": "Name of the segment",
+ "name": "namespace",
+ "description": "Segment namespace.",
"args": [
],
"type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
+ "kind": "OBJECT",
+ "name": "Namespace",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
@@ -20780,7 +22493,7 @@
"fields": [
{
"name": "deploySucceeded",
- "description": "At least one deployment succeeded",
+ "description": "At least one deployment succeeded.",
"args": [
],
@@ -20798,7 +22511,7 @@
},
{
"name": "endTime",
- "description": "The end time for the snapshot where the data points were collected",
+ "description": "The end time for the snapshot where the data points were collected.",
"args": [
],
@@ -20816,7 +22529,7 @@
},
{
"name": "issueOpened",
- "description": "At least one issue was opened",
+ "description": "At least one issue was opened.",
"args": [
],
@@ -20834,7 +22547,7 @@
},
{
"name": "mergeRequestApproved",
- "description": "At least one merge request was approved",
+ "description": "At least one merge request was approved.",
"args": [
],
@@ -20852,7 +22565,7 @@
},
{
"name": "mergeRequestOpened",
- "description": "At least one merge request was opened",
+ "description": "At least one merge request was opened.",
"args": [
],
@@ -20870,7 +22583,7 @@
},
{
"name": "pipelineSucceeded",
- "description": "At least one pipeline succeeded",
+ "description": "At least one pipeline succeeded.",
"args": [
],
@@ -20888,7 +22601,7 @@
},
{
"name": "recordedAt",
- "description": "The time the snapshot was recorded",
+ "description": "The time the snapshot was recorded.",
"args": [
],
@@ -20906,7 +22619,7 @@
},
{
"name": "runnerConfigured",
- "description": "At least one runner was used",
+ "description": "At least one runner was used.",
"args": [
],
@@ -20924,7 +22637,7 @@
},
{
"name": "securityScanSucceeded",
- "description": "At least one security scan succeeded",
+ "description": "At least one security scan succeeded.",
"args": [
],
@@ -20942,7 +22655,7 @@
},
{
"name": "startTime",
- "description": "The start time for the snapshot where the data points were collected",
+ "description": "The start time for the snapshot where the data points were collected.",
"args": [
],
@@ -20974,7 +22687,7 @@
"inputFields": [
{
"name": "headSha",
- "description": "SHA of the HEAD at the time the comment was made",
+ "description": "SHA of the HEAD at the time the comment was made.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -20988,7 +22701,7 @@
},
{
"name": "baseSha",
- "description": "Merge base of the branch the comment was made on",
+ "description": "Merge base of the branch the comment was made on.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -20998,7 +22711,7 @@
},
{
"name": "startSha",
- "description": "SHA of the branch being compared against",
+ "description": "SHA of the branch being compared against.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21026,7 +22739,7 @@
},
{
"name": "x",
- "description": "X position of the note",
+ "description": "X position of the note.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21040,7 +22753,7 @@
},
{
"name": "y",
- "description": "Y position of the note",
+ "description": "Y position of the note.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21054,7 +22767,7 @@
},
{
"name": "width",
- "description": "Total width of the image",
+ "description": "Total width of the image.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21068,7 +22781,7 @@
},
{
"name": "height",
- "description": "Total height of the image",
+ "description": "Total height of the image.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21088,7 +22801,7 @@
{
"kind": "SCALAR",
"name": "DiffNoteID",
- "description": "Identifier of DiffNote",
+ "description": "Identifier of DiffNote.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -21103,7 +22816,7 @@
"inputFields": [
{
"name": "oldPath",
- "description": "The path of the file on the start sha",
+ "description": "The path of the file on the start sha.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21113,7 +22826,7 @@
},
{
"name": "newPath",
- "description": "The path of the file on the head sha",
+ "description": "The path of the file on the head sha.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21133,7 +22846,7 @@
"fields": [
{
"name": "diffRefs",
- "description": "Information about the branch, HEAD, and base at the time of commenting",
+ "description": "Information about the branch, HEAD, and base at the time of commenting.",
"args": [
],
@@ -21151,7 +22864,7 @@
},
{
"name": "filePath",
- "description": "Path of the file that was changed",
+ "description": "Path of the file that was changed.",
"args": [
],
@@ -21169,7 +22882,7 @@
},
{
"name": "height",
- "description": "Total height of the image",
+ "description": "Total height of the image.",
"args": [
],
@@ -21183,7 +22896,7 @@
},
{
"name": "newLine",
- "description": "Line on HEAD SHA that was changed",
+ "description": "Line on HEAD SHA that was changed.",
"args": [
],
@@ -21197,7 +22910,7 @@
},
{
"name": "newPath",
- "description": "Path of the file on the HEAD SHA",
+ "description": "Path of the file on the HEAD SHA.",
"args": [
],
@@ -21211,7 +22924,7 @@
},
{
"name": "oldLine",
- "description": "Line on start SHA that was changed",
+ "description": "Line on start SHA that was changed.",
"args": [
],
@@ -21225,7 +22938,7 @@
},
{
"name": "oldPath",
- "description": "Path of the file on the start SHA",
+ "description": "Path of the file on the start SHA.",
"args": [
],
@@ -21239,7 +22952,7 @@
},
{
"name": "positionType",
- "description": "Type of file the position refers to",
+ "description": "Type of file the position refers to.",
"args": [
],
@@ -21257,7 +22970,7 @@
},
{
"name": "width",
- "description": "Total width of the image",
+ "description": "Total width of the image.",
"args": [
],
@@ -21271,7 +22984,7 @@
},
{
"name": "x",
- "description": "X position of the note",
+ "description": "X position of the note.",
"args": [
],
@@ -21285,7 +22998,7 @@
},
{
"name": "y",
- "description": "Y position of the note",
+ "description": "Y position of the note.",
"args": [
],
@@ -21313,7 +23026,7 @@
"inputFields": [
{
"name": "headSha",
- "description": "SHA of the HEAD at the time the comment was made",
+ "description": "SHA of the HEAD at the time the comment was made.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21327,7 +23040,7 @@
},
{
"name": "baseSha",
- "description": "Merge base of the branch the comment was made on",
+ "description": "Merge base of the branch the comment was made on.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -21337,7 +23050,7 @@
},
{
"name": "startSha",
- "description": "SHA of the branch being compared against",
+ "description": "SHA of the branch being compared against.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21365,7 +23078,7 @@
},
{
"name": "oldLine",
- "description": "Line on start SHA that was changed",
+ "description": "Line on start SHA that was changed.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -21375,7 +23088,7 @@
},
{
"name": "newLine",
- "description": "Line on HEAD SHA that was changed",
+ "description": "Line on HEAD SHA that was changed.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -21422,7 +23135,7 @@
"fields": [
{
"name": "baseSha",
- "description": "Merge base of the branch the comment was made on",
+ "description": "Merge base of the branch the comment was made on.",
"args": [
],
@@ -21436,7 +23149,7 @@
},
{
"name": "headSha",
- "description": "SHA of the HEAD at the time the comment was made",
+ "description": "SHA of the HEAD at the time the comment was made.",
"args": [
],
@@ -21454,7 +23167,7 @@
},
{
"name": "startSha",
- "description": "SHA of the branch being compared against",
+ "description": "SHA of the branch being compared against.",
"args": [
],
@@ -21485,7 +23198,7 @@
"fields": [
{
"name": "additions",
- "description": "Number of lines added to this file",
+ "description": "Number of lines added to this file.",
"args": [
],
@@ -21503,7 +23216,7 @@
},
{
"name": "deletions",
- "description": "Number of lines deleted from this file",
+ "description": "Number of lines deleted from this file.",
"args": [
],
@@ -21521,7 +23234,7 @@
},
{
"name": "path",
- "description": "File path, relative to repository root",
+ "description": "File path, relative to repository root.",
"args": [
],
@@ -21552,7 +23265,7 @@
"fields": [
{
"name": "additions",
- "description": "Number of lines added",
+ "description": "Number of lines added.",
"args": [
],
@@ -21570,7 +23283,7 @@
},
{
"name": "changes",
- "description": "Number of lines changed",
+ "description": "Number of lines changed.",
"args": [
],
@@ -21588,7 +23301,7 @@
},
{
"name": "deletions",
- "description": "Number of lines deleted",
+ "description": "Number of lines deleted.",
"args": [
],
@@ -21606,7 +23319,7 @@
},
{
"name": "fileCount",
- "description": "Number of files changed",
+ "description": "Number of files changed.",
"args": [
],
@@ -21637,7 +23350,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp of the discussion's creation",
+ "description": "Timestamp of the discussion's creation.",
"args": [
],
@@ -21655,7 +23368,7 @@
},
{
"name": "id",
- "description": "ID of this discussion",
+ "description": "ID of this discussion.",
"args": [
],
@@ -21664,7 +23377,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DiscussionID",
"ofType": null
}
},
@@ -21673,7 +23386,7 @@
},
{
"name": "notes",
- "description": "All notes in the discussion",
+ "description": "All notes in the discussion.",
"args": [
{
"name": "after",
@@ -21730,7 +23443,7 @@
},
{
"name": "replyId",
- "description": "ID used to reply to this discussion",
+ "description": "ID used to reply to this discussion.",
"args": [
],
@@ -21739,7 +23452,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DiscussionID",
"ofType": null
}
},
@@ -21748,7 +23461,7 @@
},
{
"name": "resolvable",
- "description": "Indicates if the object can be resolved",
+ "description": "Indicates if the object can be resolved.",
"args": [
],
@@ -21766,7 +23479,7 @@
},
{
"name": "resolved",
- "description": "Indicates if the object is resolved",
+ "description": "Indicates if the object is resolved.",
"args": [
],
@@ -21784,7 +23497,7 @@
},
{
"name": "resolvedAt",
- "description": "Timestamp of when the object was resolved",
+ "description": "Timestamp of when the object was resolved.",
"args": [
],
@@ -21798,7 +23511,7 @@
},
{
"name": "resolvedBy",
- "description": "User who resolved the object",
+ "description": "User who resolved the object.",
"args": [
],
@@ -21937,7 +23650,7 @@
{
"kind": "SCALAR",
"name": "DiscussionID",
- "description": "Identifier of Discussion",
+ "description": "Identifier of Discussion.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -22189,7 +23902,7 @@
"fields": [
{
"name": "flatPath",
- "description": "Flat path of the entry",
+ "description": "Flat path of the entry.",
"args": [
],
@@ -22207,7 +23920,7 @@
},
{
"name": "id",
- "description": "ID of the entry",
+ "description": "ID of the entry.",
"args": [
],
@@ -22225,7 +23938,7 @@
},
{
"name": "name",
- "description": "Name of the entry",
+ "description": "Name of the entry.",
"args": [
],
@@ -22243,7 +23956,7 @@
},
{
"name": "path",
- "description": "Path of the entry",
+ "description": "Path of the entry.",
"args": [
],
@@ -22261,7 +23974,7 @@
},
{
"name": "sha",
- "description": "Last commit sha for the entry",
+ "description": "Last commit SHA for the entry.",
"args": [
],
@@ -22279,7 +23992,7 @@
},
{
"name": "type",
- "description": "Type of tree entry",
+ "description": "Type of tree entry.",
"args": [
],
@@ -22353,7 +24066,7 @@
"fields": [
{
"name": "id",
- "description": "ID of the environment",
+ "description": "ID of the environment.",
"args": [
],
@@ -22371,7 +24084,7 @@
},
{
"name": "latestOpenedMostSevereAlert",
- "description": "The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned",
+ "description": "The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned.",
"args": [
],
@@ -22385,7 +24098,7 @@
},
{
"name": "metricsDashboard",
- "description": "Metrics dashboard schema for the environment",
+ "description": "Metrics dashboard schema for the environment.",
"args": [
{
"name": "path",
@@ -22412,7 +24125,7 @@
},
{
"name": "name",
- "description": "Human-readable name of the environment",
+ "description": "Human-readable name of the environment.",
"args": [
],
@@ -22448,7 +24161,7 @@
},
{
"name": "state",
- "description": "State of the environment, for example: available/stopped",
+ "description": "State of the environment, for example: available/stopped.",
"args": [
],
@@ -22587,7 +24300,7 @@
{
"kind": "SCALAR",
"name": "EnvironmentID",
- "description": "Identifier of Environment",
+ "description": "Identifier of Environment.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -22703,7 +24416,7 @@
"fields": [
{
"name": "author",
- "description": "Author of the epic",
+ "description": "Author of the epic.",
"args": [
],
@@ -22720,8 +24433,61 @@
"deprecationReason": null
},
{
+ "name": "awardEmoji",
+ "description": "A list of award emojis associated with the epic.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AwardEmojiConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "children",
- "description": "Children (sub-epics) of the epic",
+ "description": "Children (sub-epics) of the epic.",
"args": [
{
"name": "startDate",
@@ -22930,7 +24696,7 @@
},
{
"name": "closedAt",
- "description": "Timestamp of when the epic was closed",
+ "description": "Timestamp of when the epic was closed.",
"args": [
],
@@ -22944,7 +24710,7 @@
},
{
"name": "confidential",
- "description": "Indicates if the epic is confidential",
+ "description": "Indicates if the epic is confidential.",
"args": [
],
@@ -22958,7 +24724,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the epic was created",
+ "description": "Timestamp of when the epic was created.",
"args": [
],
@@ -22972,7 +24738,7 @@
},
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -23016,7 +24782,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -23039,7 +24805,7 @@
},
{
"name": "descendantCounts",
- "description": "Number of open and closed descendant epics and issues",
+ "description": "Number of open and closed descendant epics and issues.",
"args": [
],
@@ -23053,7 +24819,7 @@
},
{
"name": "descendantWeightSum",
- "description": "Total weight of open and closed issues in the epic and its descendants",
+ "description": "Total weight of open and closed issues in the epic and its descendants.",
"args": [
],
@@ -23067,7 +24833,7 @@
},
{
"name": "description",
- "description": "Description of the epic",
+ "description": "Description of the epic.",
"args": [
],
@@ -23081,7 +24847,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -23138,7 +24904,7 @@
},
{
"name": "downvotes",
- "description": "Number of downvotes the epic has received",
+ "description": "Number of downvotes the epic has received.",
"args": [
],
@@ -23156,7 +24922,7 @@
},
{
"name": "dueDate",
- "description": "Due date of the epic",
+ "description": "Due date of the epic.",
"args": [
],
@@ -23170,7 +24936,7 @@
},
{
"name": "dueDateFixed",
- "description": "Fixed due date of the epic",
+ "description": "Fixed due date of the epic.",
"args": [
],
@@ -23184,7 +24950,7 @@
},
{
"name": "dueDateFromMilestones",
- "description": "Inherited due date of the epic from milestones",
+ "description": "Inherited due date of the epic from milestones.",
"args": [
],
@@ -23198,7 +24964,7 @@
},
{
"name": "dueDateIsFixed",
- "description": "Indicates if the due date has been manually set",
+ "description": "Indicates if the due date has been manually set.",
"args": [
],
@@ -23211,8 +24977,61 @@
"deprecationReason": null
},
{
+ "name": "events",
+ "description": "A list of events associated with the object.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EventConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "group",
- "description": "Group to which the epic belongs",
+ "description": "Group to which the epic belongs.",
"args": [
],
@@ -23230,7 +25049,7 @@
},
{
"name": "hasChildren",
- "description": "Indicates if the epic has children",
+ "description": "Indicates if the epic has children.",
"args": [
],
@@ -23248,7 +25067,7 @@
},
{
"name": "hasIssues",
- "description": "Indicates if the epic has direct issues",
+ "description": "Indicates if the epic has direct issues.",
"args": [
],
@@ -23266,7 +25085,7 @@
},
{
"name": "hasParent",
- "description": "Indicates if the epic has a parent epic",
+ "description": "Indicates if the epic has a parent epic.",
"args": [
],
@@ -23284,7 +25103,7 @@
},
{
"name": "healthStatus",
- "description": "Current health status of the epic",
+ "description": "Current health status of the epic.",
"args": [
],
@@ -23298,7 +25117,7 @@
},
{
"name": "id",
- "description": "ID of the epic",
+ "description": "ID of the epic.",
"args": [
],
@@ -23316,7 +25135,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the epic",
+ "description": "Internal ID of the epic.",
"args": [
],
@@ -23334,7 +25153,7 @@
},
{
"name": "issues",
- "description": "A list of issues associated with the epic",
+ "description": "A list of issues associated with the epic.",
"args": [
{
"name": "after",
@@ -23387,7 +25206,7 @@
},
{
"name": "labels",
- "description": "Labels assigned to the epic",
+ "description": "Labels assigned to the epic.",
"args": [
{
"name": "after",
@@ -23440,7 +25259,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -23497,7 +25316,7 @@
},
{
"name": "parent",
- "description": "Parent epic of the epic",
+ "description": "Parent epic of the epic.",
"args": [
],
@@ -23511,7 +25330,7 @@
},
{
"name": "participants",
- "description": "List of participants for the epic",
+ "description": "List of participants for the epic.",
"args": [
{
"name": "after",
@@ -23564,11 +25383,11 @@
},
{
"name": "reference",
- "description": "Internal reference of the epic. Returned in shortened format by default",
+ "description": "Internal reference of the epic. Returned in shortened format by default.",
"args": [
{
"name": "full",
- "description": "Indicates if the reference should be returned in full",
+ "description": "Indicates if the reference should be returned in full.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -23591,7 +25410,7 @@
},
{
"name": "relationPath",
- "description": "URI path of the epic-issue relationship",
+ "description": "URI path of the epic-issue relationship.",
"args": [
],
@@ -23605,7 +25424,7 @@
},
{
"name": "relativePosition",
- "description": "The relative position of the epic in the epic tree",
+ "description": "The relative position of the epic in the epic tree.",
"args": [
],
@@ -23619,7 +25438,7 @@
},
{
"name": "startDate",
- "description": "Start date of the epic",
+ "description": "Start date of the epic.",
"args": [
],
@@ -23633,7 +25452,7 @@
},
{
"name": "startDateFixed",
- "description": "Fixed start date of the epic",
+ "description": "Fixed start date of the epic.",
"args": [
],
@@ -23647,7 +25466,7 @@
},
{
"name": "startDateFromMilestones",
- "description": "Inherited start date of the epic from milestones",
+ "description": "Inherited start date of the epic from milestones.",
"args": [
],
@@ -23661,7 +25480,7 @@
},
{
"name": "startDateIsFixed",
- "description": "Indicates if the start date has been manually set",
+ "description": "Indicates if the start date has been manually set.",
"args": [
],
@@ -23675,7 +25494,7 @@
},
{
"name": "state",
- "description": "State of the epic",
+ "description": "State of the epic.",
"args": [
],
@@ -23693,7 +25512,7 @@
},
{
"name": "subscribed",
- "description": "Indicates the currently logged in user is subscribed to the epic",
+ "description": "Indicates the currently logged in user is subscribed to the epic.",
"args": [
],
@@ -23711,7 +25530,7 @@
},
{
"name": "title",
- "description": "Title of the epic",
+ "description": "Title of the epic.",
"args": [
],
@@ -23725,7 +25544,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the epic was updated",
+ "description": "Timestamp of when the epic was updated.",
"args": [
],
@@ -23739,7 +25558,7 @@
},
{
"name": "upvotes",
- "description": "Number of upvotes the epic has received",
+ "description": "Number of upvotes the epic has received.",
"args": [
],
@@ -23757,7 +25576,7 @@
},
{
"name": "userDiscussionsCount",
- "description": "Number of user discussions in the epic",
+ "description": "Number of user discussions in the epic.",
"args": [
],
@@ -23775,7 +25594,7 @@
},
{
"name": "userNotesCount",
- "description": "Number of user notes of the epic",
+ "description": "Number of user notes of the epic.",
"args": [
],
@@ -23811,7 +25630,7 @@
},
{
"name": "webPath",
- "description": "Web path of the epic",
+ "description": "Web path of the epic.",
"args": [
],
@@ -23829,7 +25648,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the epic",
+ "description": "Web URL of the epic.",
"args": [
],
@@ -23857,6 +25676,11 @@
"kind": "INTERFACE",
"name": "CurrentUserTodos",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "Eventable",
+ "ofType": null
}
],
"enumValues": null,
@@ -24196,6 +26020,134 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "EpicBoardCreateInput",
+ "description": "Autogenerated input type of EpicBoardCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "name",
+ "description": "The board name.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "hideBacklogList",
+ "description": "Whether or not backlog list is hidden.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "hideClosedList",
+ "description": "Whether or not closed list is hidden.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "groupPath",
+ "description": "Full path of the group with which the resource is associated.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EpicBoardCreatePayload",
+ "description": "Autogenerated return type of EpicBoardCreate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "epicBoard",
+ "description": "The created epic board.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicBoard",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "EpicBoardEdge",
"description": "An edge in a connection.",
@@ -24241,6 +26193,128 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "EpicBoardListCreateInput",
+ "description": "Autogenerated input type of EpicBoardListCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "backlog",
+ "description": "Create the backlog list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labelId",
+ "description": "Global ID of an existing label.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "LabelID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "boardId",
+ "description": "Global ID of the issue board to mutate.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BoardsEpicBoardID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EpicBoardListCreatePayload",
+ "description": "Autogenerated return type of EpicBoardListCreate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "list",
+ "description": "Epic list in the epic board.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicList",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "EpicConnection",
"description": "The connection type for Epic.",
@@ -24314,7 +26388,7 @@
"fields": [
{
"name": "closedEpics",
- "description": "Number of closed child epics",
+ "description": "Number of closed child epics.",
"args": [
],
@@ -24328,7 +26402,7 @@
},
{
"name": "closedIssues",
- "description": "Number of closed epic issues",
+ "description": "Number of closed epic issues.",
"args": [
],
@@ -24342,7 +26416,7 @@
},
{
"name": "openedEpics",
- "description": "Number of opened child epics",
+ "description": "Number of opened child epics.",
"args": [
],
@@ -24356,7 +26430,7 @@
},
{
"name": "openedIssues",
- "description": "Number of opened epic issues",
+ "description": "Number of opened epic issues.",
"args": [
],
@@ -24383,7 +26457,7 @@
"fields": [
{
"name": "closedIssues",
- "description": "Total weight of completed (closed) issues in this epic, including epic descendants",
+ "description": "Total weight of completed (closed) issues in this epic, including epic descendants.",
"args": [
],
@@ -24397,7 +26471,7 @@
},
{
"name": "openedIssues",
- "description": "Total weight of opened issues in this epic, including epic descendants",
+ "description": "Total weight of opened issues in this epic, including epic descendants.",
"args": [
],
@@ -24469,7 +26543,7 @@
"fields": [
{
"name": "issuesAtRisk",
- "description": "Number of issues at risk",
+ "description": "Number of issues at risk.",
"args": [
],
@@ -24483,7 +26557,7 @@
},
{
"name": "issuesNeedingAttention",
- "description": "Number of issues that need attention",
+ "description": "Number of issues that need attention.",
"args": [
],
@@ -24497,7 +26571,7 @@
},
{
"name": "issuesOnTrack",
- "description": "Number of issues on track",
+ "description": "Number of issues on track.",
"args": [
],
@@ -24520,7 +26594,7 @@
{
"kind": "SCALAR",
"name": "EpicID",
- "description": "Identifier of Epic",
+ "description": "Identifier of Epic.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -24534,7 +26608,7 @@
"fields": [
{
"name": "alertManagementAlert",
- "description": "Alert associated to this issue",
+ "description": "Alert associated to this issue.",
"args": [
],
@@ -24548,7 +26622,7 @@
},
{
"name": "assignees",
- "description": "Assignees of the issue",
+ "description": "Assignees of the issue.",
"args": [
{
"name": "after",
@@ -24601,7 +26675,7 @@
},
{
"name": "author",
- "description": "User that created the issue",
+ "description": "User that created the issue.",
"args": [
],
@@ -24651,7 +26725,7 @@
},
{
"name": "closedAt",
- "description": "Timestamp of when the issue was closed",
+ "description": "Timestamp of when the issue was closed.",
"args": [
],
@@ -24665,7 +26739,7 @@
},
{
"name": "confidential",
- "description": "Indicates the issue is confidential",
+ "description": "Indicates the issue is confidential.",
"args": [
],
@@ -24683,7 +26757,7 @@
},
{
"name": "createNoteEmail",
- "description": "User specific email address for the issue",
+ "description": "User specific email address for the issue.",
"args": [
],
@@ -24697,7 +26771,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the issue was created",
+ "description": "Timestamp of when the issue was created.",
"args": [
],
@@ -24715,7 +26789,7 @@
},
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -24759,7 +26833,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -24782,7 +26856,7 @@
},
{
"name": "description",
- "description": "Description of the issue",
+ "description": "Description of the issue.",
"args": [
],
@@ -24810,7 +26884,7 @@
},
{
"name": "designCollection",
- "description": "Collection of design images associated with this issue",
+ "description": "Collection of design images associated with this issue.",
"args": [
],
@@ -24824,7 +26898,7 @@
},
{
"name": "discussionLocked",
- "description": "Indicates discussion is locked on the issue",
+ "description": "Indicates discussion is locked on the issue.",
"args": [
],
@@ -24842,7 +26916,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -24899,7 +26973,7 @@
},
{
"name": "downvotes",
- "description": "Number of downvotes the issue has received",
+ "description": "Number of downvotes the issue has received.",
"args": [
],
@@ -24917,7 +26991,7 @@
},
{
"name": "dueDate",
- "description": "Due date of the issue",
+ "description": "Due date of the issue.",
"args": [
],
@@ -24931,7 +27005,7 @@
},
{
"name": "emailsDisabled",
- "description": "Indicates if a project has email notifications disabled: `true` if email notifications are disabled",
+ "description": "Indicates if a project has email notifications disabled: `true` if email notifications are disabled.",
"args": [
],
@@ -24963,7 +27037,7 @@
},
{
"name": "epicIssueId",
- "description": "ID of the epic-issue relation",
+ "description": "ID of the epic-issue relation.",
"args": [
],
@@ -24995,7 +27069,7 @@
},
{
"name": "humanTimeEstimate",
- "description": "Human-readable time estimate of the issue",
+ "description": "Human-readable time estimate of the issue.",
"args": [
],
@@ -25009,7 +27083,7 @@
},
{
"name": "humanTotalTimeSpent",
- "description": "Human-readable total time reported as spent on the issue",
+ "description": "Human-readable total time reported as spent on the issue.",
"args": [
],
@@ -25023,7 +27097,7 @@
},
{
"name": "id",
- "description": "Global ID of the epic-issue relation",
+ "description": "Global ID of the epic-issue relation.",
"args": [
],
@@ -25037,7 +27111,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the issue",
+ "description": "Internal ID of the issue.",
"args": [
],
@@ -25069,7 +27143,7 @@
},
{
"name": "labels",
- "description": "Labels of the issue",
+ "description": "Labels of the issue.",
"args": [
{
"name": "after",
@@ -25144,7 +27218,7 @@
},
{
"name": "milestone",
- "description": "Milestone of the issue",
+ "description": "Milestone of the issue.",
"args": [
],
@@ -25158,7 +27232,7 @@
},
{
"name": "moved",
- "description": "Indicates if issue got moved from other project",
+ "description": "Indicates if issue got moved from other project.",
"args": [
],
@@ -25172,7 +27246,7 @@
},
{
"name": "movedTo",
- "description": "Updated Issue after it got moved to another project",
+ "description": "Updated Issue after it got moved to another project.",
"args": [
],
@@ -25186,7 +27260,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -25243,7 +27317,7 @@
},
{
"name": "participants",
- "description": "List of participants in the issue",
+ "description": "List of participants in the issue.",
"args": [
{
"name": "after",
@@ -25296,11 +27370,11 @@
},
{
"name": "reference",
- "description": "Internal reference of the issue. Returned in shortened format by default",
+ "description": "Internal reference of the issue. Returned in shortened format by default.",
"args": [
{
"name": "full",
- "description": "Boolean option specifying whether the reference should be returned in full",
+ "description": "Boolean option specifying whether the reference should be returned in full.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -25323,7 +27397,7 @@
},
{
"name": "relationPath",
- "description": "URI path of the epic-issue relation",
+ "description": "URI path of the epic-issue relation.",
"args": [
],
@@ -25337,7 +27411,7 @@
},
{
"name": "relativePosition",
- "description": "Relative position of the issue (used for positioning in epic tree and issue boards)",
+ "description": "Relative position of the issue (used for positioning in epic tree and issue boards).",
"args": [
],
@@ -25351,7 +27425,7 @@
},
{
"name": "severity",
- "description": "Severity level of the incident",
+ "description": "Severity level of the incident.",
"args": [
],
@@ -25379,7 +27453,7 @@
},
{
"name": "state",
- "description": "State of the issue",
+ "description": "State of the issue.",
"args": [
],
@@ -25411,7 +27485,7 @@
},
{
"name": "subscribed",
- "description": "Indicates the currently logged in user is subscribed to the issue",
+ "description": "Indicates the currently logged in user is subscribed to the issue.",
"args": [
],
@@ -25429,7 +27503,7 @@
},
{
"name": "taskCompletionStatus",
- "description": "Task completion status of the issue",
+ "description": "Task completion status of the issue.",
"args": [
],
@@ -25447,7 +27521,7 @@
},
{
"name": "timeEstimate",
- "description": "Time estimate of the issue",
+ "description": "Time estimate of the issue.",
"args": [
],
@@ -25465,7 +27539,7 @@
},
{
"name": "title",
- "description": "Title of the issue",
+ "description": "Title of the issue.",
"args": [
],
@@ -25497,7 +27571,7 @@
},
{
"name": "totalTimeSpent",
- "description": "Total time reported as spent on the issue",
+ "description": "Total time reported as spent on the issue.",
"args": [
],
@@ -25515,7 +27589,7 @@
},
{
"name": "type",
- "description": "Type of the issue",
+ "description": "Type of the issue.",
"args": [
],
@@ -25529,7 +27603,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the issue was last updated",
+ "description": "Timestamp of when the issue was last updated.",
"args": [
],
@@ -25547,7 +27621,7 @@
},
{
"name": "updatedBy",
- "description": "User that last updated the issue",
+ "description": "User that last updated the issue.",
"args": [
],
@@ -25561,7 +27635,7 @@
},
{
"name": "upvotes",
- "description": "Number of upvotes the issue has received",
+ "description": "Number of upvotes the issue has received.",
"args": [
],
@@ -25579,7 +27653,7 @@
},
{
"name": "userDiscussionsCount",
- "description": "Number of user discussions in the issue",
+ "description": "Number of user discussions in the issue.",
"args": [
],
@@ -25597,7 +27671,7 @@
},
{
"name": "userNotesCount",
- "description": "Number of user notes of the issue",
+ "description": "Number of user notes of the issue.",
"args": [
],
@@ -25633,7 +27707,7 @@
},
{
"name": "webPath",
- "description": "Web path of the issue",
+ "description": "Web path of the issue.",
"args": [
],
@@ -25651,7 +27725,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the issue",
+ "description": "Web URL of the issue.",
"args": [
],
@@ -25705,7 +27779,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -25777,7 +27851,7 @@
},
{
"name": "weight",
- "description": "Total weight of issues collection",
+ "description": "Total weight of issues collection.",
"args": [
],
@@ -26488,7 +28562,7 @@
"inputFields": [
{
"name": "id",
- "description": "The ID of the epic_issue or epic that is being moved",
+ "description": "The ID of the epic_issue or epic that is being moved.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -26502,7 +28576,7 @@
},
{
"name": "adjacentReferenceId",
- "description": "The ID of the epic_issue or issue that the actual epic or issue is switched with",
+ "description": "The ID of the epic_issue or issue that the actual epic or issue is switched with.",
"type": {
"kind": "SCALAR",
"name": "EpicTreeSortingID",
@@ -26512,7 +28586,7 @@
},
{
"name": "relativePosition",
- "description": "The type of the switch, after or before allowed",
+ "description": "The type of the switch, after or before allowed.",
"type": {
"kind": "ENUM",
"name": "MoveType",
@@ -26522,7 +28596,7 @@
},
{
"name": "newParentId",
- "description": "ID of the new parent epic",
+ "description": "ID of the new parent epic.",
"type": {
"kind": "SCALAR",
"name": "EpicID",
@@ -26640,7 +28714,7 @@
{
"kind": "SCALAR",
"name": "EpicTreeSortingID",
- "description": "Identifier of EpicTreeSorting",
+ "description": "Identifier of EpicTreeSorting.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -26671,6 +28745,385 @@
"possibleTypes": null
},
{
+ "kind": "OBJECT",
+ "name": "Event",
+ "description": "Representing an event",
+ "fields": [
+ {
+ "name": "action",
+ "description": "Action of the event.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "EventAction",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "author",
+ "description": "Author of this event.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": "When this event was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the event.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": "When this event was updated.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
+ "name": "EventAction",
+ "description": "Event action",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "CREATED",
+ "description": "Created action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "UPDATED",
+ "description": "Updated action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "CLOSED",
+ "description": "Closed action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "REOPENED",
+ "description": "Reopened action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "PUSHED",
+ "description": "Pushed action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "COMMENTED",
+ "description": "Commented action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MERGED",
+ "description": "Merged action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "JOINED",
+ "description": "Joined action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "LEFT",
+ "description": "Left action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "DESTROYED",
+ "description": "Destroyed action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "EXPIRED",
+ "description": "Expired action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "APPROVED",
+ "description": "Approved action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "ARCHIVED",
+ "description": "Archived action",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EventConnection",
+ "description": "The connection type for Event.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "EventEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Event",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EventEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Event",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "Eventable",
+ "description": null,
+ "fields": [
+ {
+ "name": "events",
+ "description": "A list of events associated with the object.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EventConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "BoardEpic",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "Epic",
+ "ofType": null
+ }
+ ]
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "ExportRequirementsInput",
"description": "Autogenerated input type of ExportRequirements",
@@ -26739,6 +29192,24 @@
"defaultValue": null
},
{
+ "name": "selectedFields",
+ "description": "List of selected requirements fields to be exported.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -26813,7 +29284,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp of when the issue was created",
+ "description": "Timestamp of when the issue was created.",
"args": [
],
@@ -26827,7 +29298,7 @@
},
{
"name": "externalTracker",
- "description": "Type of external tracker",
+ "description": "Type of external tracker.",
"args": [
],
@@ -26841,7 +29312,7 @@
},
{
"name": "relativeReference",
- "description": "Relative reference of the issue in the external tracker",
+ "description": "Relative reference of the issue in the external tracker.",
"args": [
],
@@ -26855,7 +29326,7 @@
},
{
"name": "status",
- "description": "Status of the issue in the external tracker",
+ "description": "Status of the issue in the external tracker.",
"args": [
],
@@ -26869,7 +29340,7 @@
},
{
"name": "title",
- "description": "Title of the issue in the external tracker",
+ "description": "Title of the issue in the external tracker.",
"args": [
],
@@ -26883,7 +29354,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the issue was updated",
+ "description": "Timestamp of when the issue was updated.",
"args": [
],
@@ -26897,7 +29368,7 @@
},
{
"name": "webUrl",
- "description": "URL to the issue in the external tracker",
+ "description": "URL to the issue in the external tracker.",
"args": [
],
@@ -26934,7 +29405,7 @@
"fields": [
{
"name": "containerRepositoriesMaxCapacity",
- "description": "The maximum concurrency of container repository sync for this secondary node",
+ "description": "The maximum concurrency of container repository sync for this secondary node.",
"args": [
],
@@ -26948,7 +29419,7 @@
},
{
"name": "enabled",
- "description": "Indicates whether this Geo node is enabled",
+ "description": "Indicates whether this Geo node is enabled.",
"args": [
],
@@ -26962,7 +29433,7 @@
},
{
"name": "filesMaxCapacity",
- "description": "The maximum concurrency of LFS/attachment backfill for this secondary node",
+ "description": "The maximum concurrency of LFS/attachment backfill for this secondary node.",
"args": [
],
@@ -26976,7 +29447,7 @@
},
{
"name": "id",
- "description": "ID of this GeoNode",
+ "description": "ID of this GeoNode.",
"args": [
],
@@ -26994,7 +29465,7 @@
},
{
"name": "internalUrl",
- "description": "The URL defined on the primary node that secondary nodes should use to contact it",
+ "description": "The URL defined on the primary node that secondary nodes should use to contact it.",
"args": [
],
@@ -27008,7 +29479,7 @@
},
{
"name": "mergeRequestDiffRegistries",
- "description": "Find merge request diff registries on this Geo node",
+ "description": "Find merge request diff registries on this Geo node.",
"args": [
{
"name": "ids",
@@ -27079,7 +29550,7 @@
},
{
"name": "minimumReverificationInterval",
- "description": "The interval (in days) in which the repository verification is valid. Once expired, it will be reverified",
+ "description": "The interval (in days) in which the repository verification is valid. Once expired, it will be reverified.",
"args": [
],
@@ -27093,7 +29564,7 @@
},
{
"name": "name",
- "description": "The unique identifier for this Geo node",
+ "description": "The unique identifier for this Geo node.",
"args": [
],
@@ -27107,7 +29578,7 @@
},
{
"name": "packageFileRegistries",
- "description": "Package file registries of the GeoNode",
+ "description": "Package file registries of the GeoNode.",
"args": [
{
"name": "ids",
@@ -27178,7 +29649,7 @@
},
{
"name": "primary",
- "description": "Indicates whether this Geo node is the primary",
+ "description": "Indicates whether this Geo node is the primary.",
"args": [
],
@@ -27192,7 +29663,7 @@
},
{
"name": "reposMaxCapacity",
- "description": "The maximum concurrency of repository backfill for this secondary node",
+ "description": "The maximum concurrency of repository backfill for this secondary node.",
"args": [
],
@@ -27206,7 +29677,7 @@
},
{
"name": "selectiveSyncNamespaces",
- "description": "The namespaces that should be synced, if `selective_sync_type` == `namespaces`",
+ "description": "The namespaces that should be synced, if `selective_sync_type` == `namespaces`.",
"args": [
{
"name": "after",
@@ -27259,7 +29730,7 @@
},
{
"name": "selectiveSyncShards",
- "description": "The repository storages whose projects should be synced, if `selective_sync_type` == `shards`",
+ "description": "The repository storages whose projects should be synced, if `selective_sync_type` == `shards`.",
"args": [
],
@@ -27281,7 +29752,7 @@
},
{
"name": "selectiveSyncType",
- "description": "Indicates if syncing is limited to only specific groups, or shards",
+ "description": "Indicates if syncing is limited to only specific groups, or shards.",
"args": [
],
@@ -27295,7 +29766,7 @@
},
{
"name": "snippetRepositoryRegistries",
- "description": "Find snippet repository registries on this Geo node",
+ "description": "Find snippet repository registries on this Geo node.",
"args": [
{
"name": "ids",
@@ -27366,7 +29837,7 @@
},
{
"name": "syncObjectStorage",
- "description": "Indicates if this secondary node will replicate blobs in Object Storage",
+ "description": "Indicates if this secondary node will replicate blobs in Object Storage.",
"args": [
],
@@ -27380,7 +29851,7 @@
},
{
"name": "terraformStateVersionRegistries",
- "description": "Find terraform state version registries on this Geo node",
+ "description": "Find terraform state version registries on this Geo node.",
"args": [
{
"name": "ids",
@@ -27451,7 +29922,7 @@
},
{
"name": "url",
- "description": "The user-facing URL for this Geo node",
+ "description": "The user-facing URL for this Geo node.",
"args": [
],
@@ -27465,7 +29936,7 @@
},
{
"name": "verificationMaxCapacity",
- "description": "The maximum concurrency of repository verification for this secondary node",
+ "description": "The maximum concurrency of repository verification for this secondary node.",
"args": [
],
@@ -27488,7 +29959,7 @@
{
"kind": "SCALAR",
"name": "GitlabErrorTrackingDetailedErrorID",
- "description": "Identifier of Gitlab::ErrorTracking::DetailedError",
+ "description": "Identifier of Gitlab::ErrorTracking::DetailedError.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -27496,13 +29967,101 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "GitlabSubscriptionActivateInput",
+ "description": "Autogenerated input type of GitlabSubscriptionActivate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "activationCode",
+ "description": "Activation code received after purchasing a GitLab subscription.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "GitlabSubscriptionActivatePayload",
+ "description": "Autogenerated return type of GitlabSubscriptionActivate",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "GrafanaIntegration",
"description": null,
"fields": [
{
"name": "createdAt",
- "description": "Timestamp of the issue's creation",
+ "description": "Timestamp of the issue's creation.",
"args": [
],
@@ -27520,7 +30079,7 @@
},
{
"name": "enabled",
- "description": "Indicates whether Grafana integration is enabled",
+ "description": "Indicates whether Grafana integration is enabled.",
"args": [
],
@@ -27538,7 +30097,7 @@
},
{
"name": "grafanaUrl",
- "description": "URL for the Grafana host for the Grafana integration",
+ "description": "URL for the Grafana host for the Grafana integration.",
"args": [
],
@@ -27556,7 +30115,7 @@
},
{
"name": "id",
- "description": "Internal ID of the Grafana integration",
+ "description": "Internal ID of the Grafana integration.",
"args": [
],
@@ -27574,7 +30133,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of the issue's last activity",
+ "description": "Timestamp of the issue's last activity.",
"args": [
],
@@ -27605,7 +30164,7 @@
"fields": [
{
"name": "actualRepositorySizeLimit",
- "description": "Size limit for repositories in the namespace in bytes",
+ "description": "Size limit for repositories in the namespace in bytes.",
"args": [
],
@@ -27619,7 +30178,7 @@
},
{
"name": "additionalPurchasedStorageSize",
- "description": "Additional storage purchased for the root namespace in bytes",
+ "description": "Additional storage purchased for the root namespace in bytes.",
"args": [
],
@@ -27633,7 +30192,7 @@
},
{
"name": "autoDevopsEnabled",
- "description": "Indicates whether Auto DevOps is enabled for all projects within this group",
+ "description": "Indicates whether Auto DevOps is enabled for all projects within this group.",
"args": [
],
@@ -27647,7 +30206,7 @@
},
{
"name": "avatarUrl",
- "description": "Avatar URL of the group",
+ "description": "Avatar URL of the group.",
"args": [
],
@@ -27661,7 +30220,7 @@
},
{
"name": "board",
- "description": "A single board of the group",
+ "description": "A single board of the group.",
"args": [
{
"name": "id",
@@ -27688,7 +30247,7 @@
},
{
"name": "boards",
- "description": "Boards of the group",
+ "description": "Boards of the group.",
"args": [
{
"name": "id",
@@ -27751,7 +30310,7 @@
},
{
"name": "codeCoverageActivities",
- "description": "Represents the code coverage activity for this group",
+ "description": "Represents the code coverage activity for this group.",
"args": [
{
"name": "startDate",
@@ -27881,7 +30440,7 @@
},
{
"name": "containerRepositories",
- "description": "Container repositories of the group",
+ "description": "Container repositories of the group.",
"args": [
{
"name": "name",
@@ -27894,6 +30453,16 @@
"defaultValue": null
},
{
+ "name": "sort",
+ "description": "Sort container repositories by this criteria.",
+ "type": {
+ "kind": "ENUM",
+ "name": "ContainerRepositorySort",
+ "ofType": null
+ },
+ "defaultValue": "created_desc"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -27944,7 +30513,7 @@
},
{
"name": "containerRepositoriesCount",
- "description": "Number of container repositories in the group",
+ "description": "Number of container repositories in the group.",
"args": [
],
@@ -27962,7 +30531,7 @@
},
{
"name": "containsLockedProjects",
- "description": "Includes at least one project where the repository size exceeds the limit",
+ "description": "Includes at least one project where the repository size exceeds the limit.",
"args": [
],
@@ -27980,7 +30549,7 @@
},
{
"name": "customEmoji",
- "description": "Custom emoji within this namespace Available only when feature flag `custom_emoji` is enabled.",
+ "description": "Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled.",
"args": [
{
"name": "after",
@@ -28033,7 +30602,7 @@
},
{
"name": "description",
- "description": "Description of the namespace",
+ "description": "Description of the namespace.",
"args": [
],
@@ -28061,7 +30630,7 @@
},
{
"name": "emailsDisabled",
- "description": "Indicates if a group has email notifications disabled",
+ "description": "Indicates if a group has email notifications disabled.",
"args": [
],
@@ -28075,7 +30644,7 @@
},
{
"name": "epic",
- "description": "Find a single epic",
+ "description": "Find a single epic.",
"args": [
{
"name": "startDate",
@@ -28244,7 +30813,7 @@
},
{
"name": "epicBoard",
- "description": "Find a single epic board",
+ "description": "Find a single epic board.",
"args": [
{
"name": "id",
@@ -28271,7 +30840,7 @@
},
{
"name": "epicBoards",
- "description": "Find epic boards",
+ "description": "Find epic boards.",
"args": [
{
"name": "after",
@@ -28324,7 +30893,7 @@
},
{
"name": "epics",
- "description": "Find epics",
+ "description": "Find epics.",
"args": [
{
"name": "startDate",
@@ -28547,7 +31116,7 @@
},
{
"name": "fullName",
- "description": "Full name of the namespace",
+ "description": "Full name of the namespace.",
"args": [
],
@@ -28565,7 +31134,7 @@
},
{
"name": "fullPath",
- "description": "Full path of the namespace",
+ "description": "Full path of the namespace.",
"args": [
],
@@ -28583,7 +31152,7 @@
},
{
"name": "groupMembers",
- "description": "A membership of a user within this group",
+ "description": "A membership of a user within this group.",
"args": [
{
"name": "search",
@@ -28678,7 +31247,7 @@
},
{
"name": "id",
- "description": "ID of the namespace",
+ "description": "ID of the namespace.",
"args": [
],
@@ -28696,7 +31265,7 @@
},
{
"name": "isTemporaryStorageIncreaseEnabled",
- "description": "Status of the temporary storage increase",
+ "description": "Status of the temporary storage increase.",
"args": [
],
@@ -28714,7 +31283,7 @@
},
{
"name": "issues",
- "description": "Issues for projects in this group",
+ "description": "Issues for projects in this group.",
"args": [
{
"name": "iid",
@@ -29013,7 +31582,7 @@
},
{
"name": "iterations",
- "description": "Find iterations",
+ "description": "Find iterations.",
"args": [
{
"name": "startDate",
@@ -29146,11 +31715,11 @@
},
{
"name": "label",
- "description": "A label available on this group",
+ "description": "A label available on this group.",
"args": [
{
"name": "title",
- "description": "Title of the label",
+ "description": "Title of the label.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -29173,9 +31742,49 @@
},
{
"name": "labels",
- "description": "Labels available on this group",
+ "description": "Labels available on this group.",
"args": [
{
+ "name": "searchTerm",
+ "description": "A search term to find labels with.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "includeAncestorGroups",
+ "description": "Include labels from ancestor groups.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ },
+ {
+ "name": "includeDescendantGroups",
+ "description": "Include labels from descendant groups.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ },
+ {
+ "name": "onlyGroupLabels",
+ "description": "Include only group level labels.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -29214,16 +31823,6 @@
"ofType": null
},
"defaultValue": null
- },
- {
- "name": "searchTerm",
- "description": "A search term to find labels with",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
}
],
"type": {
@@ -29236,7 +31835,7 @@
},
{
"name": "lfsEnabled",
- "description": "Indicates if Large File Storage (LFS) is enabled for namespace",
+ "description": "Indicates if Large File Storage (LFS) is enabled for namespace.",
"args": [
],
@@ -29250,7 +31849,7 @@
},
{
"name": "mentionsDisabled",
- "description": "Indicates if a group is disabled from getting mentioned",
+ "description": "Indicates if a group is disabled from getting mentioned.",
"args": [
],
@@ -29264,7 +31863,7 @@
},
{
"name": "mergeRequests",
- "description": "Merge requests for projects in this group",
+ "description": "Merge requests for projects in this group.",
"args": [
{
"name": "iids",
@@ -29469,7 +32068,7 @@
},
{
"name": "milestones",
- "description": "Milestones of the group",
+ "description": "Milestones of the group.",
"args": [
{
"name": "startDate",
@@ -29620,7 +32219,7 @@
},
{
"name": "name",
- "description": "Name of the namespace",
+ "description": "Name of the namespace.",
"args": [
],
@@ -29638,7 +32237,7 @@
},
{
"name": "packageSettings",
- "description": "The package settings for the namespace",
+ "description": "The package settings for the namespace.",
"args": [
],
@@ -29652,7 +32251,7 @@
},
{
"name": "parent",
- "description": "Parent group",
+ "description": "Parent group.",
"args": [
],
@@ -29666,7 +32265,7 @@
},
{
"name": "path",
- "description": "Path of the namespace",
+ "description": "Path of the namespace.",
"args": [
],
@@ -29684,7 +32283,7 @@
},
{
"name": "projectCreationLevel",
- "description": "The permission level required to create projects in the group",
+ "description": "The permission level required to create projects in the group.",
"args": [
],
@@ -29698,7 +32297,7 @@
},
{
"name": "projects",
- "description": "Projects within this namespace",
+ "description": "Projects within this namespace.",
"args": [
{
"name": "includeSubgroups",
@@ -29795,7 +32394,7 @@
},
{
"name": "repositorySizeExcessProjectCount",
- "description": "Number of projects in the root namespace where the repository size exceeds the limit",
+ "description": "Number of projects in the root namespace where the repository size exceeds the limit.",
"args": [
],
@@ -29813,7 +32412,7 @@
},
{
"name": "requestAccessEnabled",
- "description": "Indicates if users can request access to namespace",
+ "description": "Indicates if users can request access to namespace.",
"args": [
],
@@ -29827,7 +32426,7 @@
},
{
"name": "requireTwoFactorAuthentication",
- "description": "Indicates if all users in this group are required to set up two-factor authentication",
+ "description": "Indicates if all users in this group are required to set up two-factor authentication.",
"args": [
],
@@ -29841,7 +32440,7 @@
},
{
"name": "rootStorageStatistics",
- "description": "Aggregated storage statistics of the namespace. Only available for root namespaces",
+ "description": "Aggregated storage statistics of the namespace. Only available for root namespaces.",
"args": [
],
@@ -29855,7 +32454,7 @@
},
{
"name": "shareWithGroupLock",
- "description": "Indicates if sharing a project with another group within this group is prevented",
+ "description": "Indicates if sharing a project with another group within this group is prevented.",
"args": [
],
@@ -29869,7 +32468,7 @@
},
{
"name": "stats",
- "description": "Group statistics",
+ "description": "Group statistics.",
"args": [
],
@@ -29883,7 +32482,7 @@
},
{
"name": "storageSizeLimit",
- "description": "Total storage limit of the root namespace in bytes",
+ "description": "Total storage limit of the root namespace in bytes.",
"args": [
],
@@ -29897,7 +32496,7 @@
},
{
"name": "subgroupCreationLevel",
- "description": "The permission level required to create subgroups within the group",
+ "description": "The permission level required to create subgroups within the group.",
"args": [
],
@@ -29911,7 +32510,7 @@
},
{
"name": "temporaryStorageIncreaseEndsOn",
- "description": "Date until the temporary storage increase is active",
+ "description": "Date until the temporary storage increase is active.",
"args": [
],
@@ -29925,7 +32524,7 @@
},
{
"name": "timelogs",
- "description": "Time logged in issues by group members",
+ "description": "Time logged in issues by group members.",
"args": [
{
"name": "startDate",
@@ -30022,7 +32621,7 @@
},
{
"name": "totalRepositorySize",
- "description": "Total repository size of all projects in the root namespace in bytes",
+ "description": "Total repository size of all projects in the root namespace in bytes.",
"args": [
],
@@ -30036,7 +32635,7 @@
},
{
"name": "totalRepositorySizeExcess",
- "description": "Total excess repository size of all projects in the root namespace in bytes",
+ "description": "Total excess repository size of all projects in the root namespace in bytes.",
"args": [
],
@@ -30050,7 +32649,7 @@
},
{
"name": "twoFactorGracePeriod",
- "description": "Time before two-factor authentication is enforced",
+ "description": "Time before two-factor authentication is enforced.",
"args": [
],
@@ -30082,7 +32681,7 @@
},
{
"name": "visibility",
- "description": "Visibility of the namespace",
+ "description": "Visibility of the namespace.",
"args": [
],
@@ -30096,7 +32695,7 @@
},
{
"name": "vulnerabilities",
- "description": "Vulnerabilities reported on the projects in the group and its subgroups",
+ "description": "Vulnerabilities reported on the projects in the group and its subgroups.",
"args": [
{
"name": "projectId",
@@ -30269,7 +32868,7 @@
},
{
"name": "vulnerabilitiesCountByDay",
- "description": "Number of vulnerabilities per day for the projects in the group and its subgroups",
+ "description": "Number of vulnerabilities per day for the projects in the group and its subgroups.",
"args": [
{
"name": "startDate",
@@ -30350,7 +32949,7 @@
},
{
"name": "vulnerabilitiesCountByDayAndSeverity",
- "description": "Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.",
+ "description": "Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups. Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.",
"args": [
{
"name": "startDate",
@@ -30431,7 +33030,7 @@
},
{
"name": "vulnerabilityGrades",
- "description": "Represents vulnerable project counts for each grade",
+ "description": "Represents vulnerable project counts for each grade.",
"args": [
{
"name": "includeSubgroups",
@@ -30466,7 +33065,7 @@
},
{
"name": "vulnerabilityScanners",
- "description": "Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups",
+ "description": "Vulnerability scanners reported on the project vulnerabilities of the group and its subgroups.",
"args": [
{
"name": "after",
@@ -30519,7 +33118,7 @@
},
{
"name": "vulnerabilitySeveritiesCount",
- "description": "Counts for each vulnerability severity in the group and its subgroups",
+ "description": "Counts for each vulnerability severity in the group and its subgroups.",
"args": [
{
"name": "projectId",
@@ -30622,7 +33221,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the group",
+ "description": "Web URL of the group.",
"args": [
],
@@ -30649,7 +33248,7 @@
{
"kind": "SCALAR",
"name": "GroupID",
- "description": "Identifier of Group",
+ "description": "Identifier of Group.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -30663,7 +33262,7 @@
"fields": [
{
"name": "accessLevel",
- "description": "GitLab::Access level",
+ "description": "GitLab::Access level.",
"args": [
],
@@ -30677,7 +33276,7 @@
},
{
"name": "createdAt",
- "description": "Date and time the membership was created",
+ "description": "Date and time the membership was created.",
"args": [
],
@@ -30691,7 +33290,7 @@
},
{
"name": "createdBy",
- "description": "User that authorized membership",
+ "description": "User that authorized membership.",
"args": [
],
@@ -30705,7 +33304,7 @@
},
{
"name": "expiresAt",
- "description": "Date and time the membership expires",
+ "description": "Date and time the membership expires.",
"args": [
],
@@ -30719,7 +33318,7 @@
},
{
"name": "group",
- "description": "Group that a User is a member of",
+ "description": "Group that a User is a member of.",
"args": [
],
@@ -30733,7 +33332,7 @@
},
{
"name": "id",
- "description": "ID of the member",
+ "description": "ID of the member.",
"args": [
],
@@ -30751,7 +33350,7 @@
},
{
"name": "updatedAt",
- "description": "Date and time the membership was last updated",
+ "description": "Date and time the membership was last updated.",
"args": [
],
@@ -30765,7 +33364,7 @@
},
{
"name": "user",
- "description": "User that is associated with the member object",
+ "description": "User that is associated with the member object.",
"args": [
],
@@ -31031,7 +33630,7 @@
"fields": [
{
"name": "releaseStats",
- "description": "Statistics related to releases within the group",
+ "description": "Statistics related to releases within the group.",
"args": [
],
@@ -31483,6 +34082,34 @@
"defaultValue": null
},
{
+ "name": "payloadExample",
+ "description": "The example of an alert payload.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "JsonString",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "payloadAttributeMappings",
+ "description": "The custom mapping of GitLab alert attributes to fields from the payload_example.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "AlertManagementPayloadAlertFieldInput",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -31587,7 +34214,7 @@
{
"kind": "SCALAR",
"name": "IncidentManagementOncallParticipantID",
- "description": "Identifier of IncidentManagement::OncallParticipant",
+ "description": "Identifier of IncidentManagement::OncallParticipant.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -31717,6 +34344,87 @@
"deprecationReason": null
},
{
+ "name": "shifts",
+ "description": "Blocks of time for which a participant is on-call within a given time frame. Time frame cannot exceed one month.",
+ "args": [
+ {
+ "name": "startTime",
+ "description": "Start of timeframe to include shifts for.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "endTime",
+ "description": "End of timeframe to include shifts for. Cannot exceed one month after start.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallShiftConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "startsAt",
"description": "Start date of the on-call rotation.",
"args": [
@@ -31853,7 +34561,7 @@
{
"kind": "SCALAR",
"name": "IncidentManagementOncallRotationID",
- "description": "Identifier of IncidentManagement::OncallRotation",
+ "description": "Identifier of IncidentManagement::OncallRotation.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -31867,7 +34575,7 @@
"fields": [
{
"name": "description",
- "description": "Description of the on-call schedule",
+ "description": "Description of the on-call schedule.",
"args": [
],
@@ -31881,7 +34589,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the on-call schedule",
+ "description": "Internal ID of the on-call schedule.",
"args": [
],
@@ -31899,7 +34607,7 @@
},
{
"name": "name",
- "description": "Name of the on-call schedule",
+ "description": "Name of the on-call schedule.",
"args": [
],
@@ -31917,7 +34625,7 @@
},
{
"name": "rotations",
- "description": "On-call rotations for the on-call schedule",
+ "description": "On-call rotations for the on-call schedule.",
"args": [
{
"name": "after",
@@ -31974,7 +34682,7 @@
},
{
"name": "timezone",
- "description": "Time zone of the on-call schedule",
+ "description": "Time zone of the on-call schedule.",
"args": [
],
@@ -32112,12 +34820,179 @@
},
{
"kind": "OBJECT",
+ "name": "IncidentManagementOncallShift",
+ "description": "A block of time for which a participant is on-call.",
+ "fields": [
+ {
+ "name": "endsAt",
+ "description": "End time of the on-call shift.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "participant",
+ "description": "Participant assigned to the on-call shift.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "OncallParticipantType",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "startsAt",
+ "description": "Start time of the on-call shift.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallShiftConnection",
+ "description": "The connection type for IncidentManagementOncallShift.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallShiftEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallShift",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallShiftEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallShift",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "InstanceSecurityDashboard",
"description": null,
"fields": [
{
"name": "projects",
- "description": "Projects selected in Instance Security Dashboard",
+ "description": "Projects selected in Instance Security Dashboard.",
"args": [
{
"name": "after",
@@ -32174,7 +35049,7 @@
},
{
"name": "vulnerabilityGrades",
- "description": "Represents vulnerable project counts for each grade",
+ "description": "Represents vulnerable project counts for each grade.",
"args": [
],
@@ -32200,7 +35075,7 @@
},
{
"name": "vulnerabilityScanners",
- "description": "Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard",
+ "description": "Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard.",
"args": [
{
"name": "after",
@@ -32253,7 +35128,7 @@
},
{
"name": "vulnerabilitySeveritiesCount",
- "description": "Counts for each vulnerability severity from projects selected in Instance Security Dashboard",
+ "description": "Counts for each vulnerability severity from projects selected in Instance Security Dashboard.",
"args": [
{
"name": "projectId",
@@ -32369,7 +35244,7 @@
"fields": [
{
"name": "count",
- "description": "Object count",
+ "description": "Object count.",
"args": [
],
@@ -32387,7 +35262,7 @@
},
{
"name": "identifier",
- "description": "The type of objects being measured",
+ "description": "The type of objects being measured.",
"args": [
],
@@ -32405,7 +35280,7 @@
},
{
"name": "recordedAt",
- "description": "The time the measurement was recorded",
+ "description": "The time the measurement was recorded.",
"args": [
],
@@ -32630,7 +35505,7 @@
"fields": [
{
"name": "alertManagementAlert",
- "description": "Alert associated to this issue",
+ "description": "Alert associated to this issue.",
"args": [
],
@@ -32644,7 +35519,7 @@
},
{
"name": "assignees",
- "description": "Assignees of the issue",
+ "description": "Assignees of the issue.",
"args": [
{
"name": "after",
@@ -32697,7 +35572,7 @@
},
{
"name": "author",
- "description": "User that created the issue",
+ "description": "User that created the issue.",
"args": [
],
@@ -32747,7 +35622,7 @@
},
{
"name": "closedAt",
- "description": "Timestamp of when the issue was closed",
+ "description": "Timestamp of when the issue was closed.",
"args": [
],
@@ -32761,7 +35636,7 @@
},
{
"name": "confidential",
- "description": "Indicates the issue is confidential",
+ "description": "Indicates the issue is confidential.",
"args": [
],
@@ -32779,7 +35654,7 @@
},
{
"name": "createNoteEmail",
- "description": "User specific email address for the issue",
+ "description": "User specific email address for the issue.",
"args": [
],
@@ -32793,7 +35668,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the issue was created",
+ "description": "Timestamp of when the issue was created.",
"args": [
],
@@ -32811,7 +35686,7 @@
},
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -32855,7 +35730,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -32878,7 +35753,7 @@
},
{
"name": "description",
- "description": "Description of the issue",
+ "description": "Description of the issue.",
"args": [
],
@@ -32906,7 +35781,7 @@
},
{
"name": "designCollection",
- "description": "Collection of design images associated with this issue",
+ "description": "Collection of design images associated with this issue.",
"args": [
],
@@ -32920,7 +35795,7 @@
},
{
"name": "discussionLocked",
- "description": "Indicates discussion is locked on the issue",
+ "description": "Indicates discussion is locked on the issue.",
"args": [
],
@@ -32938,7 +35813,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -32995,7 +35870,7 @@
},
{
"name": "downvotes",
- "description": "Number of downvotes the issue has received",
+ "description": "Number of downvotes the issue has received.",
"args": [
],
@@ -33013,7 +35888,7 @@
},
{
"name": "dueDate",
- "description": "Due date of the issue",
+ "description": "Due date of the issue.",
"args": [
],
@@ -33027,7 +35902,7 @@
},
{
"name": "emailsDisabled",
- "description": "Indicates if a project has email notifications disabled: `true` if email notifications are disabled",
+ "description": "Indicates if a project has email notifications disabled: `true` if email notifications are disabled.",
"args": [
],
@@ -33073,7 +35948,7 @@
},
{
"name": "humanTimeEstimate",
- "description": "Human-readable time estimate of the issue",
+ "description": "Human-readable time estimate of the issue.",
"args": [
],
@@ -33087,7 +35962,7 @@
},
{
"name": "humanTotalTimeSpent",
- "description": "Human-readable total time reported as spent on the issue",
+ "description": "Human-readable total time reported as spent on the issue.",
"args": [
],
@@ -33101,7 +35976,7 @@
},
{
"name": "id",
- "description": "ID of the issue",
+ "description": "ID of the issue.",
"args": [
],
@@ -33119,7 +35994,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the issue",
+ "description": "Internal ID of the issue.",
"args": [
],
@@ -33151,7 +36026,7 @@
},
{
"name": "labels",
- "description": "Labels of the issue",
+ "description": "Labels of the issue.",
"args": [
{
"name": "after",
@@ -33226,7 +36101,7 @@
},
{
"name": "milestone",
- "description": "Milestone of the issue",
+ "description": "Milestone of the issue.",
"args": [
],
@@ -33240,7 +36115,7 @@
},
{
"name": "moved",
- "description": "Indicates if issue got moved from other project",
+ "description": "Indicates if issue got moved from other project.",
"args": [
],
@@ -33254,7 +36129,7 @@
},
{
"name": "movedTo",
- "description": "Updated Issue after it got moved to another project",
+ "description": "Updated Issue after it got moved to another project.",
"args": [
],
@@ -33268,7 +36143,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -33325,7 +36200,7 @@
},
{
"name": "participants",
- "description": "List of participants in the issue",
+ "description": "List of participants in the issue.",
"args": [
{
"name": "after",
@@ -33378,11 +36253,11 @@
},
{
"name": "reference",
- "description": "Internal reference of the issue. Returned in shortened format by default",
+ "description": "Internal reference of the issue. Returned in shortened format by default.",
"args": [
{
"name": "full",
- "description": "Boolean option specifying whether the reference should be returned in full",
+ "description": "Boolean option specifying whether the reference should be returned in full.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -33405,7 +36280,7 @@
},
{
"name": "relativePosition",
- "description": "Relative position of the issue (used for positioning in epic tree and issue boards)",
+ "description": "Relative position of the issue (used for positioning in epic tree and issue boards).",
"args": [
],
@@ -33419,7 +36294,7 @@
},
{
"name": "severity",
- "description": "Severity level of the incident",
+ "description": "Severity level of the incident.",
"args": [
],
@@ -33447,7 +36322,7 @@
},
{
"name": "state",
- "description": "State of the issue",
+ "description": "State of the issue.",
"args": [
],
@@ -33479,7 +36354,7 @@
},
{
"name": "subscribed",
- "description": "Indicates the currently logged in user is subscribed to the issue",
+ "description": "Indicates the currently logged in user is subscribed to the issue.",
"args": [
],
@@ -33497,7 +36372,7 @@
},
{
"name": "taskCompletionStatus",
- "description": "Task completion status of the issue",
+ "description": "Task completion status of the issue.",
"args": [
],
@@ -33515,7 +36390,7 @@
},
{
"name": "timeEstimate",
- "description": "Time estimate of the issue",
+ "description": "Time estimate of the issue.",
"args": [
],
@@ -33533,7 +36408,7 @@
},
{
"name": "title",
- "description": "Title of the issue",
+ "description": "Title of the issue.",
"args": [
],
@@ -33565,7 +36440,7 @@
},
{
"name": "totalTimeSpent",
- "description": "Total time reported as spent on the issue",
+ "description": "Total time reported as spent on the issue.",
"args": [
],
@@ -33583,7 +36458,7 @@
},
{
"name": "type",
- "description": "Type of the issue",
+ "description": "Type of the issue.",
"args": [
],
@@ -33597,7 +36472,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the issue was last updated",
+ "description": "Timestamp of when the issue was last updated.",
"args": [
],
@@ -33615,7 +36490,7 @@
},
{
"name": "updatedBy",
- "description": "User that last updated the issue",
+ "description": "User that last updated the issue.",
"args": [
],
@@ -33629,7 +36504,7 @@
},
{
"name": "upvotes",
- "description": "Number of upvotes the issue has received",
+ "description": "Number of upvotes the issue has received.",
"args": [
],
@@ -33647,7 +36522,7 @@
},
{
"name": "userDiscussionsCount",
- "description": "Number of user discussions in the issue",
+ "description": "Number of user discussions in the issue.",
"args": [
],
@@ -33665,7 +36540,7 @@
},
{
"name": "userNotesCount",
- "description": "Number of user notes of the issue",
+ "description": "Number of user notes of the issue.",
"args": [
],
@@ -33701,7 +36576,7 @@
},
{
"name": "webPath",
- "description": "Web path of the issue",
+ "description": "Web path of the issue.",
"args": [
],
@@ -33719,7 +36594,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the issue",
+ "description": "Web URL of the issue.",
"args": [
],
@@ -33773,7 +36648,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -33845,7 +36720,7 @@
},
{
"name": "weight",
- "description": "Total weight of issues collection",
+ "description": "Total weight of issues collection.",
"args": [
],
@@ -33917,7 +36792,7 @@
{
"kind": "SCALAR",
"name": "IssueID",
- "description": "Identifier of Issue",
+ "description": "Identifier of Issue.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -35881,7 +38756,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp of iteration creation",
+ "description": "Timestamp of iteration creation.",
"args": [
],
@@ -35899,7 +38774,7 @@
},
{
"name": "description",
- "description": "Description of the iteration",
+ "description": "Description of the iteration.",
"args": [
],
@@ -35927,7 +38802,7 @@
},
{
"name": "dueDate",
- "description": "Timestamp of the iteration due date",
+ "description": "Timestamp of the iteration due date.",
"args": [
],
@@ -35941,7 +38816,7 @@
},
{
"name": "id",
- "description": "ID of the iteration",
+ "description": "ID of the iteration.",
"args": [
],
@@ -35959,7 +38834,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the iteration",
+ "description": "Internal ID of the iteration.",
"args": [
],
@@ -35977,7 +38852,7 @@
},
{
"name": "report",
- "description": "Historically accurate report about the timebox",
+ "description": "Historically accurate report about the timebox.",
"args": [
],
@@ -35991,7 +38866,7 @@
},
{
"name": "scopedPath",
- "description": "Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts",
+ "description": "Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts.",
"args": [
],
@@ -36005,7 +38880,7 @@
},
{
"name": "scopedUrl",
- "description": "Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts",
+ "description": "Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts.",
"args": [
],
@@ -36019,7 +38894,7 @@
},
{
"name": "startDate",
- "description": "Timestamp of the iteration start date",
+ "description": "Timestamp of the iteration start date.",
"args": [
],
@@ -36033,7 +38908,7 @@
},
{
"name": "state",
- "description": "State of the iteration",
+ "description": "State of the iteration.",
"args": [
],
@@ -36051,7 +38926,7 @@
},
{
"name": "title",
- "description": "Title of the iteration",
+ "description": "Title of the iteration.",
"args": [
],
@@ -36069,7 +38944,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of last iteration update",
+ "description": "Timestamp of last iteration update.",
"args": [
],
@@ -36087,7 +38962,7 @@
},
{
"name": "webPath",
- "description": "Web path of the iteration",
+ "description": "Web path of the iteration.",
"args": [
],
@@ -36105,7 +38980,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the iteration",
+ "description": "Web URL of the iteration.",
"args": [
],
@@ -36248,7 +39123,7 @@
{
"kind": "SCALAR",
"name": "IterationID",
- "description": "Identifier of Iteration",
+ "description": "Identifier of Iteration.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -36342,7 +39217,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp of when the Jira import was created",
+ "description": "Timestamp of when the Jira import was created.",
"args": [
],
@@ -36356,7 +39231,7 @@
},
{
"name": "failedToImportCount",
- "description": "Count of issues that failed to import",
+ "description": "Count of issues that failed to import.",
"args": [
],
@@ -36374,7 +39249,7 @@
},
{
"name": "importedIssuesCount",
- "description": "Count of issues that were successfully imported",
+ "description": "Count of issues that were successfully imported.",
"args": [
],
@@ -36392,7 +39267,7 @@
},
{
"name": "jiraProjectKey",
- "description": "Project key for the imported Jira project",
+ "description": "Project key for the imported Jira project.",
"args": [
],
@@ -36410,7 +39285,7 @@
},
{
"name": "scheduledAt",
- "description": "Timestamp of when the Jira import was scheduled",
+ "description": "Timestamp of when the Jira import was scheduled.",
"args": [
],
@@ -36424,7 +39299,7 @@
},
{
"name": "scheduledBy",
- "description": "User that started the Jira import",
+ "description": "User that started the Jira import.",
"args": [
],
@@ -36438,7 +39313,7 @@
},
{
"name": "totalIssueCount",
- "description": "Total count of issues that were attempted to import",
+ "description": "Total count of issues that were attempted to import.",
"args": [
],
@@ -36845,7 +39720,7 @@
"fields": [
{
"name": "key",
- "description": "Key of the Jira project",
+ "description": "Key of the Jira project.",
"args": [
],
@@ -36863,7 +39738,7 @@
},
{
"name": "name",
- "description": "Name of the Jira project",
+ "description": "Name of the Jira project.",
"args": [
],
@@ -36877,7 +39752,7 @@
},
{
"name": "projectId",
- "description": "ID of the Jira project",
+ "description": "ID of the Jira project.",
"args": [
],
@@ -37020,7 +39895,7 @@
"fields": [
{
"name": "active",
- "description": "Indicates if the service is active",
+ "description": "Indicates if the service is active.",
"args": [
],
@@ -37034,7 +39909,7 @@
},
{
"name": "projects",
- "description": "List of all Jira projects fetched through Jira REST API",
+ "description": "List of all Jira projects fetched through Jira REST API.",
"args": [
{
"name": "name",
@@ -37097,7 +39972,7 @@
},
{
"name": "type",
- "description": "Class name of the service",
+ "description": "Class name of the service.",
"args": [
],
@@ -37128,7 +40003,7 @@
"fields": [
{
"name": "gitlabId",
- "description": "ID of the matched GitLab user",
+ "description": "ID of the matched GitLab user.",
"args": [
],
@@ -37142,7 +40017,7 @@
},
{
"name": "gitlabName",
- "description": "Name of the matched GitLab user",
+ "description": "Name of the matched GitLab user.",
"args": [
],
@@ -37156,7 +40031,7 @@
},
{
"name": "gitlabUsername",
- "description": "Username of the matched GitLab user",
+ "description": "Username of the matched GitLab user.",
"args": [
],
@@ -37170,7 +40045,7 @@
},
{
"name": "jiraAccountId",
- "description": "Account ID of the Jira user",
+ "description": "Account ID of the Jira user.",
"args": [
],
@@ -37188,7 +40063,7 @@
},
{
"name": "jiraDisplayName",
- "description": "Display name of the Jira user",
+ "description": "Display name of the Jira user.",
"args": [
],
@@ -37206,7 +40081,7 @@
},
{
"name": "jiraEmail",
- "description": "Email of the Jira user, returned only for users with public emails",
+ "description": "Email of the Jira user, returned only for users with public emails.",
"args": [
],
@@ -37234,7 +40109,7 @@
"inputFields": [
{
"name": "jiraAccountId",
- "description": "Jira account ID of the user",
+ "description": "Jira account ID of the user.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -37248,7 +40123,7 @@
},
{
"name": "gitlabId",
- "description": "Id of the GitLab user",
+ "description": "Id of the GitLab user.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -37451,7 +40326,7 @@
"fields": [
{
"name": "color",
- "description": "Background color of the label",
+ "description": "Background color of the label.",
"args": [
],
@@ -37469,7 +40344,7 @@
},
{
"name": "description",
- "description": "Description of the label (Markdown rendered as HTML for caching)",
+ "description": "Description of the label (Markdown rendered as HTML for caching).",
"args": [
],
@@ -37497,7 +40372,7 @@
},
{
"name": "id",
- "description": "Label ID",
+ "description": "Label ID.",
"args": [
],
@@ -37515,7 +40390,7 @@
},
{
"name": "textColor",
- "description": "Text color of the label",
+ "description": "Text color of the label.",
"args": [
],
@@ -37533,7 +40408,7 @@
},
{
"name": "title",
- "description": "Content of the label",
+ "description": "Content of the label.",
"args": [
],
@@ -37564,7 +40439,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -37650,7 +40525,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "The project full path the resource is associated with.",
+ "description": "Full path of the project with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -37660,7 +40535,7 @@
},
{
"name": "groupPath",
- "description": "The group full path the resource is associated with.",
+ "description": "Full path of the group with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -37700,7 +40575,7 @@
"name": "String",
"ofType": null
},
- "defaultValue": "\"#428BCA\""
+ "defaultValue": "\"#6699cc\""
},
{
"name": "clientMutationId",
@@ -37832,7 +40707,7 @@
{
"kind": "SCALAR",
"name": "LabelID",
- "description": "Identifier of Label",
+ "description": "Identifier of Label.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -37842,7 +40717,7 @@
{
"kind": "SCALAR",
"name": "ListID",
- "description": "Identifier of List",
+ "description": "Identifier of List.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -38058,7 +40933,7 @@
"fields": [
{
"name": "accessLevel",
- "description": "GitLab::Access level",
+ "description": "GitLab::Access level.",
"args": [
],
@@ -38072,7 +40947,7 @@
},
{
"name": "createdAt",
- "description": "Date and time the membership was created",
+ "description": "Date and time the membership was created.",
"args": [
],
@@ -38086,7 +40961,7 @@
},
{
"name": "createdBy",
- "description": "User that authorized membership",
+ "description": "User that authorized membership.",
"args": [
],
@@ -38100,7 +40975,7 @@
},
{
"name": "expiresAt",
- "description": "Date and time the membership expires",
+ "description": "Date and time the membership expires.",
"args": [
],
@@ -38114,7 +40989,7 @@
},
{
"name": "id",
- "description": "ID of the member",
+ "description": "ID of the member.",
"args": [
],
@@ -38132,7 +41007,7 @@
},
{
"name": "updatedAt",
- "description": "Date and time the membership was last updated",
+ "description": "Date and time the membership was last updated.",
"args": [
],
@@ -38146,7 +41021,7 @@
},
{
"name": "user",
- "description": "User that is associated with the member object",
+ "description": "User that is associated with the member object.",
"args": [
],
@@ -38298,7 +41173,7 @@
"fields": [
{
"name": "allowCollaboration",
- "description": "Indicates if members of the target project can push to the fork",
+ "description": "Indicates if members of the target project can push to the fork.",
"args": [
],
@@ -38312,7 +41187,7 @@
},
{
"name": "approvalsLeft",
- "description": "Number of approvals left",
+ "description": "Number of approvals left.",
"args": [
],
@@ -38326,7 +41201,7 @@
},
{
"name": "approvalsRequired",
- "description": "Number of approvals required",
+ "description": "Number of approvals required.",
"args": [
],
@@ -38358,7 +41233,7 @@
},
{
"name": "approvedBy",
- "description": "Users who approved the merge request",
+ "description": "Users who approved the merge request.",
"args": [
{
"name": "after",
@@ -38411,7 +41286,7 @@
},
{
"name": "assignees",
- "description": "Assignees of the merge request",
+ "description": "Assignees of the merge request.",
"args": [
{
"name": "after",
@@ -38464,7 +41339,7 @@
},
{
"name": "author",
- "description": "User who created this merge request",
+ "description": "User who created this merge request.",
"args": [
],
@@ -38478,7 +41353,7 @@
},
{
"name": "autoMergeEnabled",
- "description": "Indicates if auto merge is enabled for the merge request",
+ "description": "Indicates if auto merge is enabled for the merge request.",
"args": [
],
@@ -38496,7 +41371,7 @@
},
{
"name": "autoMergeStrategy",
- "description": "Selected auto merge strategy",
+ "description": "Selected auto merge strategy.",
"args": [
],
@@ -38510,7 +41385,7 @@
},
{
"name": "availableAutoMergeStrategies",
- "description": "Array of available auto merge strategies",
+ "description": "Array of available auto merge strategies.",
"args": [
],
@@ -38532,7 +41407,7 @@
},
{
"name": "commitCount",
- "description": "Number of commits in the merge request",
+ "description": "Number of commits in the merge request.",
"args": [
],
@@ -38546,7 +41421,7 @@
},
{
"name": "commitsWithoutMergeCommits",
- "description": "Merge request commits excluding merge commits",
+ "description": "Merge request commits excluding merge commits.",
"args": [
{
"name": "after",
@@ -38599,7 +41474,7 @@
},
{
"name": "conflicts",
- "description": "Indicates if the merge request has conflicts",
+ "description": "Indicates if the merge request has conflicts.",
"args": [
],
@@ -38617,7 +41492,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the merge request was created",
+ "description": "Timestamp of when the merge request was created.",
"args": [
],
@@ -38635,7 +41510,7 @@
},
{
"name": "currentUserTodos",
- "description": "Todos for the current user",
+ "description": "To-do items for the current user.",
"args": [
{
"name": "after",
@@ -38679,7 +41554,7 @@
},
{
"name": "state",
- "description": "State of the todos",
+ "description": "State of the to-do items.",
"type": {
"kind": "ENUM",
"name": "TodoStateEnum",
@@ -38702,7 +41577,7 @@
},
{
"name": "defaultMergeCommitMessage",
- "description": "Default merge commit message of the merge request",
+ "description": "Default merge commit message of the merge request.",
"args": [
],
@@ -38716,7 +41591,7 @@
},
{
"name": "defaultMergeCommitMessageWithDescription",
- "description": "Default merge commit message of the merge request with description",
+ "description": "Default merge commit message of the merge request with description.",
"args": [
],
@@ -38730,7 +41605,7 @@
},
{
"name": "defaultSquashCommitMessage",
- "description": "Default squash commit message of the merge request",
+ "description": "Default squash commit message of the merge request.",
"args": [
],
@@ -38744,7 +41619,7 @@
},
{
"name": "description",
- "description": "Description of the merge request (Markdown rendered as HTML for caching)",
+ "description": "Description of the merge request (Markdown rendered as HTML for caching).",
"args": [
],
@@ -38772,7 +41647,7 @@
},
{
"name": "diffHeadSha",
- "description": "Diff head SHA of the merge request",
+ "description": "Diff head SHA of the merge request.",
"args": [
],
@@ -38786,7 +41661,7 @@
},
{
"name": "diffRefs",
- "description": "References of the base SHA, the head SHA, and the start SHA for this merge request",
+ "description": "References of the base SHA, the head SHA, and the start SHA for this merge request.",
"args": [
],
@@ -38800,11 +41675,11 @@
},
{
"name": "diffStats",
- "description": "Details about which files were changed in this merge request",
+ "description": "Details about which files were changed in this merge request.",
"args": [
{
"name": "path",
- "description": "A specific file-path",
+ "description": "A specific file-path.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -38831,7 +41706,7 @@
},
{
"name": "diffStatsSummary",
- "description": "Summary of which files were changed in this merge request",
+ "description": "Summary of which files were changed in this merge request.",
"args": [
],
@@ -38845,7 +41720,7 @@
},
{
"name": "discussionLocked",
- "description": "Indicates if comments on the merge request are locked to members only",
+ "description": "Indicates if comments on the merge request are locked to members only.",
"args": [
],
@@ -38863,7 +41738,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -38920,7 +41795,7 @@
},
{
"name": "downvotes",
- "description": "Number of downvotes for the merge request",
+ "description": "Number of downvotes for the merge request.",
"args": [
],
@@ -38938,7 +41813,7 @@
},
{
"name": "forceRemoveSourceBranch",
- "description": "Indicates if the project settings will lead to source branch deletion after merge",
+ "description": "Indicates if the project settings will lead to source branch deletion after merge.",
"args": [
],
@@ -38952,7 +41827,25 @@
},
{
"name": "hasCi",
- "description": "Indicates if the merge request has CI",
+ "description": "Indicates if the merge request has CI.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "hasSecurityReports",
+ "description": "Indicates if the source branch has any security reports.",
"args": [
],
@@ -38970,7 +41863,7 @@
},
{
"name": "headPipeline",
- "description": "The pipeline running on the branch HEAD of the merge request",
+ "description": "The pipeline running on the branch HEAD of the merge request.",
"args": [
],
@@ -38984,7 +41877,7 @@
},
{
"name": "id",
- "description": "ID of the merge request",
+ "description": "ID of the merge request.",
"args": [
],
@@ -39002,7 +41895,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the merge request",
+ "description": "Internal ID of the merge request.",
"args": [
],
@@ -39020,7 +41913,7 @@
},
{
"name": "inProgressMergeCommitSha",
- "description": "Commit SHA of the merge request if merge is in progress",
+ "description": "Commit SHA of the merge request if merge is in progress.",
"args": [
],
@@ -39034,7 +41927,7 @@
},
{
"name": "labels",
- "description": "Labels of the merge request",
+ "description": "Labels of the merge request.",
"args": [
{
"name": "after",
@@ -39087,7 +41980,7 @@
},
{
"name": "mergeCommitSha",
- "description": "SHA of the merge request commit (set once merged)",
+ "description": "SHA of the merge request commit (set once merged).",
"args": [
],
@@ -39101,7 +41994,7 @@
},
{
"name": "mergeError",
- "description": "Error message due to a merge error",
+ "description": "Error message due to a merge error.",
"args": [
],
@@ -39115,7 +42008,7 @@
},
{
"name": "mergeOngoing",
- "description": "Indicates if a merge is currently occurring",
+ "description": "Indicates if a merge is currently occurring.",
"args": [
],
@@ -39133,7 +42026,7 @@
},
{
"name": "mergeStatus",
- "description": "Status of the merge request",
+ "description": "Status of the merge request.",
"args": [
],
@@ -39147,7 +42040,7 @@
},
{
"name": "mergeTrainsCount",
- "description": "",
+ "description": "Number of merge requests in the merge train.",
"args": [
],
@@ -39161,7 +42054,7 @@
},
{
"name": "mergeUser",
- "description": "User who merged this merge request",
+ "description": "User who merged this merge request.",
"args": [
],
@@ -39175,7 +42068,7 @@
},
{
"name": "mergeWhenPipelineSucceeds",
- "description": "Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS)",
+ "description": "Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).",
"args": [
],
@@ -39189,7 +42082,7 @@
},
{
"name": "mergeable",
- "description": "Indicates if the merge request is mergeable",
+ "description": "Indicates if the merge request is mergeable.",
"args": [
],
@@ -39207,7 +42100,7 @@
},
{
"name": "mergeableDiscussionsState",
- "description": "Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged",
+ "description": "Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.",
"args": [
],
@@ -39221,7 +42114,7 @@
},
{
"name": "mergedAt",
- "description": "Timestamp of when the merge request was merged, null if not merged",
+ "description": "Timestamp of when the merge request was merged, null if not merged.",
"args": [
],
@@ -39235,7 +42128,7 @@
},
{
"name": "milestone",
- "description": "The milestone of the merge request",
+ "description": "The milestone of the merge request.",
"args": [
],
@@ -39249,7 +42142,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -39442,7 +42335,7 @@
},
{
"name": "project",
- "description": "Alias for target_project",
+ "description": "Alias for target_project.",
"args": [
],
@@ -39460,7 +42353,7 @@
},
{
"name": "projectId",
- "description": "ID of the merge request project",
+ "description": "ID of the merge request project.",
"args": [
],
@@ -39478,7 +42371,7 @@
},
{
"name": "rebaseCommitSha",
- "description": "Rebase commit SHA of the merge request",
+ "description": "Rebase commit SHA of the merge request.",
"args": [
],
@@ -39492,7 +42385,7 @@
},
{
"name": "rebaseInProgress",
- "description": "Indicates if there is a rebase currently in progress for the merge request",
+ "description": "Indicates if there is a rebase currently in progress for the merge request.",
"args": [
],
@@ -39510,11 +42403,11 @@
},
{
"name": "reference",
- "description": "Internal reference of the merge request. Returned in shortened format by default",
+ "description": "Internal reference of the merge request. Returned in shortened format by default.",
"args": [
{
"name": "full",
- "description": "Boolean option specifying whether the reference should be returned in full",
+ "description": "Boolean option specifying whether the reference should be returned in full.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -39604,7 +42497,7 @@
},
{
"name": "shouldBeRebased",
- "description": "Indicates if the merge request will be rebased",
+ "description": "Indicates if the merge request will be rebased.",
"args": [
],
@@ -39622,7 +42515,7 @@
},
{
"name": "shouldRemoveSourceBranch",
- "description": "Indicates if the source branch of the merge request will be deleted after merge",
+ "description": "Indicates if the source branch of the merge request will be deleted after merge.",
"args": [
],
@@ -39636,7 +42529,7 @@
},
{
"name": "sourceBranch",
- "description": "Source branch of the merge request",
+ "description": "Source branch of the merge request.",
"args": [
],
@@ -39654,7 +42547,7 @@
},
{
"name": "sourceBranchExists",
- "description": "Indicates if the source branch of the merge request exists",
+ "description": "Indicates if the source branch of the merge request exists.",
"args": [
],
@@ -39672,7 +42565,7 @@
},
{
"name": "sourceBranchProtected",
- "description": "Indicates if the source branch is protected",
+ "description": "Indicates if the source branch is protected.",
"args": [
],
@@ -39690,7 +42583,7 @@
},
{
"name": "sourceProject",
- "description": "Source project of the merge request",
+ "description": "Source project of the merge request.",
"args": [
],
@@ -39704,7 +42597,7 @@
},
{
"name": "sourceProjectId",
- "description": "ID of the merge request source project",
+ "description": "ID of the merge request source project.",
"args": [
],
@@ -39718,7 +42611,7 @@
},
{
"name": "squash",
- "description": "Indicates if squash on merge is enabled",
+ "description": "Indicates if squash on merge is enabled.",
"args": [
],
@@ -39736,7 +42629,7 @@
},
{
"name": "squashOnMerge",
- "description": "Indicates if squash on merge is enabled",
+ "description": "Indicates if squash on merge is enabled.",
"args": [
],
@@ -39754,7 +42647,7 @@
},
{
"name": "state",
- "description": "State of the merge request",
+ "description": "State of the merge request.",
"args": [
],
@@ -39772,7 +42665,7 @@
},
{
"name": "subscribed",
- "description": "Indicates if the currently logged in user is subscribed to this merge request",
+ "description": "Indicates if the currently logged in user is subscribed to this merge request.",
"args": [
],
@@ -39790,7 +42683,7 @@
},
{
"name": "targetBranch",
- "description": "Target branch of the merge request",
+ "description": "Target branch of the merge request.",
"args": [
],
@@ -39808,7 +42701,7 @@
},
{
"name": "targetBranchExists",
- "description": "Indicates if the target branch of the merge request exists",
+ "description": "Indicates if the target branch of the merge request exists.",
"args": [
],
@@ -39826,7 +42719,7 @@
},
{
"name": "targetProject",
- "description": "Target project of the merge request",
+ "description": "Target project of the merge request.",
"args": [
],
@@ -39844,7 +42737,7 @@
},
{
"name": "targetProjectId",
- "description": "ID of the merge request target project",
+ "description": "ID of the merge request target project.",
"args": [
],
@@ -39880,7 +42773,7 @@
},
{
"name": "timeEstimate",
- "description": "Time estimate of the merge request",
+ "description": "Time estimate of the merge request.",
"args": [
],
@@ -39898,7 +42791,7 @@
},
{
"name": "title",
- "description": "Title of the merge request",
+ "description": "Title of the merge request.",
"args": [
],
@@ -39930,7 +42823,7 @@
},
{
"name": "totalTimeSpent",
- "description": "Total time reported as spent on the merge request",
+ "description": "Total time reported as spent on the merge request.",
"args": [
],
@@ -39948,7 +42841,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the merge request was last updated",
+ "description": "Timestamp of when the merge request was last updated.",
"args": [
],
@@ -39966,7 +42859,7 @@
},
{
"name": "upvotes",
- "description": "Number of upvotes for the merge request",
+ "description": "Number of upvotes for the merge request.",
"args": [
],
@@ -39984,7 +42877,7 @@
},
{
"name": "userDiscussionsCount",
- "description": "Number of user discussions in the merge request",
+ "description": "Number of user discussions in the merge request.",
"args": [
],
@@ -39998,7 +42891,7 @@
},
{
"name": "userNotesCount",
- "description": "User notes count of the merge request",
+ "description": "User notes count of the merge request.",
"args": [
],
@@ -40030,7 +42923,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the merge request",
+ "description": "Web URL of the merge request.",
"args": [
],
@@ -40044,7 +42937,7 @@
},
{
"name": "workInProgress",
- "description": "Indicates if the merge request is a work in progress (WIP)",
+ "description": "Indicates if the merge request is a work in progress (WIP).",
"args": [
],
@@ -40084,7 +42977,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -40156,7 +43049,7 @@
},
{
"name": "totalTimeToMerge",
- "description": "Total sum of time to merge, in seconds, for the collection of merge requests",
+ "description": "Total sum of time to merge, in seconds, for the collection of merge requests.",
"args": [
],
@@ -40198,7 +43091,7 @@
},
{
"name": "title",
- "description": "Title of the merge request",
+ "description": "Title of the merge request.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -40212,7 +43105,7 @@
},
{
"name": "sourceBranch",
- "description": "Source branch of the merge request",
+ "description": "Source branch of the merge request.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -40226,7 +43119,7 @@
},
{
"name": "targetBranch",
- "description": "Target branch of the merge request",
+ "description": "Target branch of the merge request.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -40240,7 +43133,7 @@
},
{
"name": "description",
- "description": "Description of the merge request (Markdown rendered as HTML for caching)",
+ "description": "Description of the merge request (Markdown rendered as HTML for caching).",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -40250,7 +43143,7 @@
},
{
"name": "labels",
- "description": "Labels of the merge request",
+ "description": "Labels of the merge request.",
"type": {
"kind": "LIST",
"name": null,
@@ -40415,7 +43308,7 @@
},
{
"name": "mergeRequestDiffId",
- "description": "ID of the Merge Request diff",
+ "description": "ID of the Merge Request diff.",
"args": [
],
@@ -40641,7 +43534,7 @@
{
"kind": "SCALAR",
"name": "MergeRequestID",
- "description": "Identifier of MergeRequest",
+ "description": "Identifier of MergeRequest.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -40649,6 +43542,29 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "MergeRequestNewState",
+ "description": "New state to apply to a merge request.",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "OPEN",
+ "description": "Open the merge request if it is closed.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "CLOSED",
+ "description": "Close the merge request if it is open.",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "MergeRequestPermissions",
"description": "Check permissions for the current user on a merge request",
@@ -40825,6 +43741,136 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "MergeRequestReviewerRereviewInput",
+ "description": "Autogenerated input type of MergeRequestReviewerRereview",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project the merge request to mutate is in.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iid",
+ "description": "The IID of the merge request to mutate.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "userId",
+ "description": "The user ID for the user that has been requested for a new review.\n",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "UserID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "MergeRequestReviewerRereviewPayload",
+ "description": "Autogenerated return type of MergeRequestReviewerRereview",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "mergeRequest",
+ "description": "The merge request after mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "MergeRequest",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
"name": "MergeRequestSetAssigneesInput",
"description": "Autogenerated input type of MergeRequestSetAssignees",
"fields": null,
@@ -41776,7 +44822,7 @@
},
{
"name": "merged",
- "description": null,
+ "description": "Merge Request has been merged",
"isDeprecated": false,
"deprecationReason": null
}
@@ -41819,7 +44865,7 @@
},
{
"name": "title",
- "description": "Title of the merge request",
+ "description": "Title of the merge request.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -41829,7 +44875,7 @@
},
{
"name": "targetBranch",
- "description": "Target branch of the merge request",
+ "description": "Target branch of the merge request.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -41839,7 +44885,7 @@
},
{
"name": "description",
- "description": "Description of the merge request (Markdown rendered as HTML for caching)",
+ "description": "Description of the merge request (Markdown rendered as HTML for caching).",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -41848,6 +44894,16 @@
"defaultValue": null
},
{
+ "name": "state",
+ "description": "The action to perform to change the state.",
+ "type": {
+ "kind": "ENUM",
+ "name": "MergeRequestNewState",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -41936,7 +44992,7 @@
"fields": [
{
"name": "revision",
- "description": "Revision",
+ "description": "Revision.",
"args": [
],
@@ -41954,7 +45010,7 @@
},
{
"name": "version",
- "description": "Version",
+ "description": "Version.",
"args": [
],
@@ -41985,7 +45041,7 @@
"fields": [
{
"name": "fileName",
- "description": "File name of the metric image",
+ "description": "File name of the metric image.",
"args": [
],
@@ -41999,7 +45055,7 @@
},
{
"name": "filePath",
- "description": "File path of the metric image",
+ "description": "File path of the metric image.",
"args": [
],
@@ -42013,7 +45069,7 @@
},
{
"name": "id",
- "description": "ID of the metric upload",
+ "description": "ID of the metric upload.",
"args": [
],
@@ -42031,7 +45087,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the metric upload",
+ "description": "Internal ID of the metric upload.",
"args": [
],
@@ -42049,7 +45105,7 @@
},
{
"name": "url",
- "description": "URL of the metric source",
+ "description": "URL of the metric source.",
"args": [
],
@@ -42080,7 +45136,7 @@
"fields": [
{
"name": "annotations",
- "description": "Annotations added to the dashboard",
+ "description": "Annotations added to the dashboard.",
"args": [
{
"name": "from",
@@ -42157,7 +45213,7 @@
},
{
"name": "path",
- "description": "Path to a file with the dashboard definition",
+ "description": "Path to a file with the dashboard definition.",
"args": [
],
@@ -42171,7 +45227,7 @@
},
{
"name": "schemaValidationWarnings",
- "description": "Dashboard schema validation warnings",
+ "description": "Dashboard schema validation warnings.",
"args": [
],
@@ -42206,7 +45262,7 @@
"fields": [
{
"name": "description",
- "description": "Description of the annotation",
+ "description": "Description of the annotation.",
"args": [
],
@@ -42220,7 +45276,7 @@
},
{
"name": "endingAt",
- "description": "Timestamp marking end of annotated time span",
+ "description": "Timestamp marking end of annotated time span.",
"args": [
],
@@ -42234,7 +45290,7 @@
},
{
"name": "id",
- "description": "ID of the annotation",
+ "description": "ID of the annotation.",
"args": [
],
@@ -42252,7 +45308,7 @@
},
{
"name": "panelId",
- "description": "ID of a dashboard panel to which the annotation should be scoped",
+ "description": "ID of a dashboard panel to which the annotation should be scoped.",
"args": [
],
@@ -42266,7 +45322,7 @@
},
{
"name": "startingAt",
- "description": "Timestamp marking start of annotated time span",
+ "description": "Timestamp marking start of annotated time span.",
"args": [
],
@@ -42401,7 +45457,7 @@
{
"kind": "SCALAR",
"name": "MetricsDashboardAnnotationID",
- "description": "Identifier of Metrics::Dashboard::Annotation",
+ "description": "Identifier of Metrics::Dashboard::Annotation.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -42415,7 +45471,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp of milestone creation",
+ "description": "Timestamp of milestone creation.",
"args": [
],
@@ -42433,7 +45489,7 @@
},
{
"name": "description",
- "description": "Description of the milestone",
+ "description": "Description of the milestone.",
"args": [
],
@@ -42447,7 +45503,7 @@
},
{
"name": "dueDate",
- "description": "Timestamp of the milestone due date",
+ "description": "Timestamp of the milestone due date.",
"args": [
],
@@ -42461,7 +45517,7 @@
},
{
"name": "groupMilestone",
- "description": "Indicates if milestone is at group level",
+ "description": "Indicates if milestone is at group level.",
"args": [
],
@@ -42479,7 +45535,7 @@
},
{
"name": "id",
- "description": "ID of the milestone",
+ "description": "ID of the milestone.",
"args": [
],
@@ -42497,7 +45553,7 @@
},
{
"name": "projectMilestone",
- "description": "Indicates if milestone is at project level",
+ "description": "Indicates if milestone is at project level.",
"args": [
],
@@ -42515,7 +45571,7 @@
},
{
"name": "report",
- "description": "Historically accurate report about the timebox",
+ "description": "Historically accurate report about the timebox.",
"args": [
],
@@ -42529,7 +45585,7 @@
},
{
"name": "startDate",
- "description": "Timestamp of the milestone start date",
+ "description": "Timestamp of the milestone start date.",
"args": [
],
@@ -42543,7 +45599,7 @@
},
{
"name": "state",
- "description": "State of the milestone",
+ "description": "State of the milestone.",
"args": [
],
@@ -42561,7 +45617,7 @@
},
{
"name": "stats",
- "description": "Milestone statistics",
+ "description": "Milestone statistics.",
"args": [
],
@@ -42575,7 +45631,7 @@
},
{
"name": "subgroupMilestone",
- "description": "Indicates if milestone is at subgroup level",
+ "description": "Indicates if milestone is at subgroup level.",
"args": [
],
@@ -42593,7 +45649,7 @@
},
{
"name": "title",
- "description": "Title of the milestone",
+ "description": "Title of the milestone.",
"args": [
],
@@ -42611,7 +45667,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of last milestone update",
+ "description": "Timestamp of last milestone update.",
"args": [
],
@@ -42629,7 +45685,7 @@
},
{
"name": "webPath",
- "description": "Web path of the milestone",
+ "description": "Web path of the milestone.",
"args": [
],
@@ -42772,7 +45828,7 @@
{
"kind": "SCALAR",
"name": "MilestoneID",
- "description": "Identifier of Milestone",
+ "description": "Identifier of Milestone.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -42782,20 +45838,20 @@
{
"kind": "ENUM",
"name": "MilestoneStateEnum",
- "description": null,
+ "description": "Current state of milestone",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "active",
- "description": null,
+ "description": "Milestone is currently active",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "closed",
- "description": null,
+ "description": "Milestone is closed",
"isDeprecated": false,
"deprecationReason": null
}
@@ -42809,7 +45865,7 @@
"fields": [
{
"name": "closedIssuesCount",
- "description": "Number of closed issues associated with the milestone",
+ "description": "Number of closed issues associated with the milestone.",
"args": [
],
@@ -42823,7 +45879,7 @@
},
{
"name": "totalIssuesCount",
- "description": "Total number of issues associated with the milestone",
+ "description": "Total number of issues associated with the milestone.",
"args": [
],
@@ -43007,6 +46063,33 @@
"deprecationReason": null
},
{
+ "name": "apiFuzzingCiConfigurationCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ApiFuzzingCiConfigurationCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ApiFuzzingCiConfigurationCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "awardEmojiAdd",
"description": null,
"args": [
@@ -43790,6 +46873,114 @@
"deprecationReason": null
},
{
+ "name": "dastProfileCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfileCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastProfileDelete",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileDeleteInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfileDeletePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastProfileRun",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileRunInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfileRunPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastProfileUpdate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastProfileUpdateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfileUpdatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dastScannerProfileCreate",
"description": null,
"args": [
@@ -44006,6 +47197,33 @@
"deprecationReason": null
},
{
+ "name": "dastSiteValidationRevoke",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastSiteValidationRevokeInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastSiteValidationRevokePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "deleteAnnotation",
"description": null,
"args": [
@@ -44438,6 +47656,60 @@
"deprecationReason": null
},
{
+ "name": "epicBoardCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "EpicBoardCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicBoardCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "epicBoardListCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "EpicBoardListCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicBoardListCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "epicSetSubscription",
"description": null,
"args": [
@@ -44519,6 +47791,33 @@
"deprecationReason": null
},
{
+ "name": "gitlabSubscriptionActivate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "GitlabSubscriptionActivateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "GitlabSubscriptionActivatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "httpIntegrationCreate",
"description": null,
"args": [
@@ -45059,6 +48358,33 @@
"deprecationReason": null
},
{
+ "name": "mergeRequestReviewerRereview",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "MergeRequestReviewerRereviewInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "MergeRequestReviewerRereviewPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "mergeRequestSetAssignees",
"description": null,
"args": [
@@ -45302,6 +48628,33 @@
"deprecationReason": null
},
{
+ "name": "oncallRotationDestroy",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "OncallRotationDestroyInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "OncallRotationDestroyPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "oncallScheduleCreate",
"description": null,
"args": [
@@ -46193,33 +49546,6 @@
"deprecationReason": null
},
{
- "name": "updateDevopsAdoptionSegment",
- "description": null,
- "args": [
- {
- "name": "input",
- "description": null,
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "INPUT_OBJECT",
- "name": "UpdateDevopsAdoptionSegmentInput",
- "ofType": null
- }
- },
- "defaultValue": null
- }
- ],
- "type": {
- "kind": "OBJECT",
- "name": "UpdateDevopsAdoptionSegmentPayload",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
"name": "updateEpic",
"description": null,
"args": [
@@ -46641,7 +49967,7 @@
"fields": [
{
"name": "actualRepositorySizeLimit",
- "description": "Size limit for repositories in the namespace in bytes",
+ "description": "Size limit for repositories in the namespace in bytes.",
"args": [
],
@@ -46655,7 +49981,7 @@
},
{
"name": "additionalPurchasedStorageSize",
- "description": "Additional storage purchased for the root namespace in bytes",
+ "description": "Additional storage purchased for the root namespace in bytes.",
"args": [
],
@@ -46732,7 +50058,7 @@
},
{
"name": "containsLockedProjects",
- "description": "Includes at least one project where the repository size exceeds the limit",
+ "description": "Includes at least one project where the repository size exceeds the limit.",
"args": [
],
@@ -46750,7 +50076,7 @@
},
{
"name": "description",
- "description": "Description of the namespace",
+ "description": "Description of the namespace.",
"args": [
],
@@ -46778,7 +50104,7 @@
},
{
"name": "fullName",
- "description": "Full name of the namespace",
+ "description": "Full name of the namespace.",
"args": [
],
@@ -46796,7 +50122,7 @@
},
{
"name": "fullPath",
- "description": "Full path of the namespace",
+ "description": "Full path of the namespace.",
"args": [
],
@@ -46814,7 +50140,7 @@
},
{
"name": "id",
- "description": "ID of the namespace",
+ "description": "ID of the namespace.",
"args": [
],
@@ -46832,7 +50158,7 @@
},
{
"name": "isTemporaryStorageIncreaseEnabled",
- "description": "Status of the temporary storage increase",
+ "description": "Status of the temporary storage increase.",
"args": [
],
@@ -46850,7 +50176,7 @@
},
{
"name": "lfsEnabled",
- "description": "Indicates if Large File Storage (LFS) is enabled for namespace",
+ "description": "Indicates if Large File Storage (LFS) is enabled for namespace.",
"args": [
],
@@ -46864,7 +50190,7 @@
},
{
"name": "name",
- "description": "Name of the namespace",
+ "description": "Name of the namespace.",
"args": [
],
@@ -46882,7 +50208,7 @@
},
{
"name": "packageSettings",
- "description": "The package settings for the namespace",
+ "description": "The package settings for the namespace.",
"args": [
],
@@ -46896,7 +50222,7 @@
},
{
"name": "path",
- "description": "Path of the namespace",
+ "description": "Path of the namespace.",
"args": [
],
@@ -46914,7 +50240,7 @@
},
{
"name": "projects",
- "description": "Projects within this namespace",
+ "description": "Projects within this namespace.",
"args": [
{
"name": "includeSubgroups",
@@ -47011,7 +50337,7 @@
},
{
"name": "repositorySizeExcessProjectCount",
- "description": "Number of projects in the root namespace where the repository size exceeds the limit",
+ "description": "Number of projects in the root namespace where the repository size exceeds the limit.",
"args": [
],
@@ -47029,7 +50355,7 @@
},
{
"name": "requestAccessEnabled",
- "description": "Indicates if users can request access to namespace",
+ "description": "Indicates if users can request access to namespace.",
"args": [
],
@@ -47043,7 +50369,7 @@
},
{
"name": "rootStorageStatistics",
- "description": "Aggregated storage statistics of the namespace. Only available for root namespaces",
+ "description": "Aggregated storage statistics of the namespace. Only available for root namespaces.",
"args": [
],
@@ -47057,7 +50383,7 @@
},
{
"name": "storageSizeLimit",
- "description": "Total storage limit of the root namespace in bytes",
+ "description": "Total storage limit of the root namespace in bytes.",
"args": [
],
@@ -47071,7 +50397,7 @@
},
{
"name": "temporaryStorageIncreaseEndsOn",
- "description": "Date until the temporary storage increase is active",
+ "description": "Date until the temporary storage increase is active.",
"args": [
],
@@ -47085,7 +50411,7 @@
},
{
"name": "totalRepositorySize",
- "description": "Total repository size of all projects in the root namespace in bytes",
+ "description": "Total repository size of all projects in the root namespace in bytes.",
"args": [
],
@@ -47099,7 +50425,7 @@
},
{
"name": "totalRepositorySizeExcess",
- "description": "Total excess repository size of all projects in the root namespace in bytes",
+ "description": "Total excess repository size of all projects in the root namespace in bytes.",
"args": [
],
@@ -47113,7 +50439,7 @@
},
{
"name": "visibility",
- "description": "Visibility of the namespace",
+ "description": "Visibility of the namespace.",
"args": [
],
@@ -47248,7 +50574,7 @@
{
"kind": "SCALAR",
"name": "NamespaceID",
- "description": "Identifier of Namespace",
+ "description": "Identifier of Namespace.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -47388,7 +50714,7 @@
"inputFields": [
{
"name": "labelName",
- "description": "Filter by label name",
+ "description": "Filter by label name.",
"type": {
"kind": "LIST",
"name": null,
@@ -47402,7 +50728,7 @@
},
{
"name": "milestoneTitle",
- "description": "Filter by milestone title",
+ "description": "Filter by milestone title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -47412,7 +50738,7 @@
},
{
"name": "assigneeUsername",
- "description": "Filter by assignee username",
+ "description": "Filter by assignee username.",
"type": {
"kind": "LIST",
"name": null,
@@ -47426,7 +50752,7 @@
},
{
"name": "authorUsername",
- "description": "Filter by author username",
+ "description": "Filter by author username.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -47436,7 +50762,7 @@
},
{
"name": "releaseTag",
- "description": "Filter by release tag",
+ "description": "Filter by release tag.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -47446,7 +50772,7 @@
},
{
"name": "myReactionEmoji",
- "description": "Filter by reaction emoji",
+ "description": "Filter by reaction emoji.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -47456,7 +50782,7 @@
},
{
"name": "epicId",
- "description": "Filter by epic ID. Incompatible with epicWildcardId",
+ "description": "Filter by epic ID. Incompatible with epicWildcardId.",
"type": {
"kind": "SCALAR",
"name": "EpicID",
@@ -47466,7 +50792,7 @@
},
{
"name": "iterationTitle",
- "description": "Filter by iteration title",
+ "description": "Filter by iteration title.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -47476,7 +50802,7 @@
},
{
"name": "weight",
- "description": "Filter by weight",
+ "description": "Filter by weight.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -47496,7 +50822,7 @@
"fields": [
{
"name": "author",
- "description": "User who wrote this note",
+ "description": "User who wrote this note.",
"args": [
],
@@ -47514,7 +50840,7 @@
},
{
"name": "body",
- "description": "Content of the note",
+ "description": "Content of the note.",
"args": [
],
@@ -47546,7 +50872,7 @@
},
{
"name": "confidential",
- "description": "Indicates if this note is confidential",
+ "description": "Indicates if this note is confidential.",
"args": [
],
@@ -47560,7 +50886,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of the note creation",
+ "description": "Timestamp of the note creation.",
"args": [
],
@@ -47578,7 +50904,7 @@
},
{
"name": "discussion",
- "description": "The discussion this note is a part of",
+ "description": "The discussion this note is a part of.",
"args": [
],
@@ -47592,7 +50918,7 @@
},
{
"name": "id",
- "description": "ID of the note",
+ "description": "ID of the note.",
"args": [
],
@@ -47601,7 +50927,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "NoteID",
"ofType": null
}
},
@@ -47610,7 +50936,7 @@
},
{
"name": "position",
- "description": "The position of this note on a diff",
+ "description": "The position of this note on a diff.",
"args": [
],
@@ -47624,7 +50950,7 @@
},
{
"name": "project",
- "description": "Project associated with the note",
+ "description": "Project associated with the note.",
"args": [
],
@@ -47638,7 +50964,7 @@
},
{
"name": "resolvable",
- "description": "Indicates if the object can be resolved",
+ "description": "Indicates if the object can be resolved.",
"args": [
],
@@ -47656,7 +50982,7 @@
},
{
"name": "resolved",
- "description": "Indicates if the object is resolved",
+ "description": "Indicates if the object is resolved.",
"args": [
],
@@ -47674,7 +51000,7 @@
},
{
"name": "resolvedAt",
- "description": "Timestamp of when the object was resolved",
+ "description": "Timestamp of when the object was resolved.",
"args": [
],
@@ -47688,7 +51014,7 @@
},
{
"name": "resolvedBy",
- "description": "User who resolved the object",
+ "description": "User who resolved the object.",
"args": [
],
@@ -47702,7 +51028,7 @@
},
{
"name": "system",
- "description": "Indicates whether this note was created by the system or by a user",
+ "description": "Indicates whether this note was created by the system or by a user.",
"args": [
],
@@ -47720,7 +51046,7 @@
},
{
"name": "systemNoteIconName",
- "description": "Name of the icon corresponding to a system note",
+ "description": "Name of the icon corresponding to a system note.",
"args": [
],
@@ -47734,7 +51060,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of the note's last activity",
+ "description": "Timestamp of the note's last activity.",
"args": [
],
@@ -47752,7 +51078,7 @@
},
{
"name": "url",
- "description": "URL to view this Note in the Web UI",
+ "description": "URL to view this Note in the Web UI.",
"args": [
],
@@ -47909,7 +51235,7 @@
{
"kind": "SCALAR",
"name": "NoteID",
- "description": "Identifier of Note",
+ "description": "Identifier of Note.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -48044,7 +51370,7 @@
"fields": [
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -48101,7 +51427,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -48211,7 +51537,7 @@
{
"kind": "SCALAR",
"name": "NoteableID",
- "description": "Identifier of Noteable",
+ "description": "Identifier of Noteable.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -48628,6 +51954,136 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "OncallRotationDestroyInput",
+ "description": "Autogenerated input type of OncallRotationDestroy",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project to remove the on-call schedule from.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "scheduleIid",
+ "description": "The IID of the on-call schedule to the on-call rotation belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "id",
+ "description": "The ID of the on-call rotation to remove.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "IncidentManagementOncallRotationID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "OncallRotationDestroyPayload",
+ "description": "Autogenerated return type of OncallRotationDestroy",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "oncallRotation",
+ "description": "The on-call rotation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "IncidentManagementOncallRotation",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
"name": "OncallRotationLengthInputType",
"description": "The rotation length of the on-call rotation",
"fields": null,
@@ -49148,7 +52604,7 @@
"fields": [
{
"name": "createdAt",
- "description": "The created date.",
+ "description": "Date of creation.",
"args": [
],
@@ -49166,7 +52622,7 @@
},
{
"name": "id",
- "description": "The ID of the package.",
+ "description": "ID of the package.",
"args": [
],
@@ -49175,7 +52631,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "PackagesPackageID",
"ofType": null
}
},
@@ -49183,320 +52639,22 @@
"deprecationReason": null
},
{
- "name": "name",
- "description": "The name of the package.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "packageType",
- "description": "The type of the package.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "ENUM",
- "name": "PackageTypeEnum",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "pipelines",
- "description": "Pipelines that built the package.",
- "args": [
- {
- "name": "after",
- "description": "Returns the elements in the list that come after the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "before",
- "description": "Returns the elements in the list that come before the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "first",
- "description": "Returns the first _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "last",
- "description": "Returns the last _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- }
- ],
- "type": {
- "kind": "OBJECT",
- "name": "PipelineConnection",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "project",
- "description": "Project where the package is stored.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "Project",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "tags",
- "description": "The package tags.",
- "args": [
- {
- "name": "after",
- "description": "Returns the elements in the list that come after the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "before",
- "description": "Returns the elements in the list that come before the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "first",
- "description": "Returns the first _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "last",
- "description": "Returns the last _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- }
- ],
- "type": {
- "kind": "OBJECT",
- "name": "PackageTagConnection",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "updatedAt",
- "description": "The updated date.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "Time",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "version",
- "description": "The version of the package.",
+ "name": "metadata",
+ "description": "Package metadata.",
"args": [
],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "versions",
- "description": "The other versions of the package.",
- "args": [
- {
- "name": "after",
- "description": "Returns the elements in the list that come after the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "before",
- "description": "Returns the elements in the list that come before the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "first",
- "description": "Returns the first _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "last",
- "description": "Returns the last _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- }
- ],
- "type": {
- "kind": "OBJECT",
- "name": "PackageConnection",
+ "kind": "UNION",
+ "name": "PackageMetadata",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
- }
- ],
- "inputFields": null,
- "interfaces": [
-
- ],
- "enumValues": null,
- "possibleTypes": null
- },
- {
- "kind": "OBJECT",
- "name": "PackageComposerDetails",
- "description": "Details of a Composer package",
- "fields": [
- {
- "name": "composerMetadatum",
- "description": "The Composer metadatum.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "PackageComposerMetadatumType",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "createdAt",
- "description": "The created date.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "Time",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "id",
- "description": "The ID of the package.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
},
{
"name": "name",
- "description": "The name of the package.",
+ "description": "Name of the package.",
"args": [
],
@@ -49514,7 +52672,7 @@
},
{
"name": "packageType",
- "description": "The type of the package.",
+ "description": "Package type.",
"args": [
],
@@ -49603,7 +52761,7 @@
},
{
"name": "tags",
- "description": "The package tags.",
+ "description": "Package tags.",
"args": [
{
"name": "after",
@@ -49656,7 +52814,7 @@
},
{
"name": "updatedAt",
- "description": "The updated date.",
+ "description": "Date of most recent update.",
"args": [
],
@@ -49674,7 +52832,7 @@
},
{
"name": "version",
- "description": "The version of the package.",
+ "description": "Version string.",
"args": [
],
@@ -49733,7 +52891,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "PackageConnection",
+ "name": "PackageWithoutVersionsConnection",
"ofType": null
},
"isDeprecated": false,
@@ -49818,55 +52976,6 @@
},
{
"kind": "OBJECT",
- "name": "PackageComposerMetadatumType",
- "description": "Composer metadatum",
- "fields": [
- {
- "name": "composerJson",
- "description": "Data of the Composer JSON file.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "PackageComposerJsonType",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "targetSha",
- "description": "Target SHA of the package.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- }
- ],
- "inputFields": null,
- "interfaces": [
-
- ],
- "enumValues": null,
- "possibleTypes": null
- },
- {
- "kind": "OBJECT",
"name": "PackageConnection",
"description": "The connection type for Package.",
"fields": [
@@ -50044,7 +53153,7 @@
},
{
"name": "packageFileId",
- "description": "ID of the PackageFile",
+ "description": "ID of the PackageFile.",
"args": [
],
@@ -50223,6 +53332,22 @@
"possibleTypes": null
},
{
+ "kind": "UNION",
+ "name": "PackageMetadata",
+ "description": "Represents metadata associated with a Package",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "ComposerMetadata",
+ "ofType": null
+ }
+ ]
+ },
+ {
"kind": "OBJECT",
"name": "PackageSettings",
"description": "Namespace-level Package Registry settings",
@@ -50480,7 +53605,7 @@
},
{
"name": "NPM",
- "description": "Packages from the NPM package manager",
+ "description": "Packages from the npm package manager",
"isDeprecated": false,
"deprecationReason": null
},
@@ -50525,14 +53650,387 @@
"description": "Packages from the Debian package manager",
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "RUBYGEMS",
+ "description": "Packages from the Rubygems package manager",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PackageWithoutVersions",
+ "description": "Represents a version of a package in the Package Registry",
+ "fields": [
+ {
+ "name": "createdAt",
+ "description": "Date of creation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the package.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "PackagesPackageID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "metadata",
+ "description": "Package metadata.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "UNION",
+ "name": "PackageMetadata",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the package.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "packageType",
+ "description": "Package type.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "PackageTypeEnum",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelines",
+ "description": "Pipelines that built the package.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PipelineConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "project",
+ "description": "Project where the package is stored.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Project",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "tags",
+ "description": "Package tags.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PackageTagConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": "Date of most recent update.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "version",
+ "description": "Version string.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PackageWithoutVersionsConnection",
+ "description": "The connection type for PackageWithoutVersions.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PackageWithoutVersionsEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PackageWithoutVersions",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "PackageWithoutVersionsEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PackageWithoutVersions",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "PackagesPackageID",
- "description": "Identifier of Packages::Package",
+ "description": "Identifier of Packages::Package.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -50623,7 +54121,7 @@
"fields": [
{
"name": "active",
- "description": "Indicates if the pipeline is active",
+ "description": "Indicates if the pipeline is active.",
"args": [
],
@@ -50641,7 +54139,7 @@
},
{
"name": "beforeSha",
- "description": "Base SHA of the source branch",
+ "description": "Base SHA of the source branch.",
"args": [
],
@@ -50655,7 +54153,7 @@
},
{
"name": "cancelable",
- "description": "Specifies if a pipeline can be canceled",
+ "description": "Specifies if a pipeline can be canceled.",
"args": [
],
@@ -50673,7 +54171,7 @@
},
{
"name": "committedAt",
- "description": "Timestamp of the pipeline's commit",
+ "description": "Timestamp of the pipeline's commit.",
"args": [
],
@@ -50687,7 +54185,7 @@
},
{
"name": "configSource",
- "description": "Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE)",
+ "description": "Configuration source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE, COMPLIANCE_SOURCE)",
"args": [
],
@@ -50701,7 +54199,7 @@
},
{
"name": "coverage",
- "description": "Coverage percentage",
+ "description": "Coverage percentage.",
"args": [
],
@@ -50715,7 +54213,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of the pipeline's creation",
+ "description": "Timestamp of the pipeline's creation.",
"args": [
],
@@ -50733,7 +54231,7 @@
},
{
"name": "detailedStatus",
- "description": "Detailed status of the pipeline",
+ "description": "Detailed status of the pipeline.",
"args": [
],
@@ -50751,7 +54249,7 @@
},
{
"name": "downstream",
- "description": "Pipelines this pipeline will trigger",
+ "description": "Pipelines this pipeline will trigger.",
"args": [
{
"name": "after",
@@ -50804,7 +54302,7 @@
},
{
"name": "duration",
- "description": "Duration of the pipeline in seconds",
+ "description": "Duration of the pipeline in seconds.",
"args": [
],
@@ -50818,7 +54316,7 @@
},
{
"name": "finishedAt",
- "description": "Timestamp of the pipeline's completion",
+ "description": "Timestamp of the pipeline's completion.",
"args": [
],
@@ -50832,7 +54330,7 @@
},
{
"name": "id",
- "description": "ID of the pipeline",
+ "description": "ID of the pipeline.",
"args": [
],
@@ -50850,7 +54348,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the pipeline",
+ "description": "Internal ID of the pipeline.",
"args": [
],
@@ -50868,7 +54366,7 @@
},
{
"name": "jobs",
- "description": "Jobs belonging to the pipeline",
+ "description": "Jobs belonging to the pipeline.",
"args": [
{
"name": "securityReportTypes",
@@ -50939,7 +54437,7 @@
},
{
"name": "path",
- "description": "Relative path to the pipeline's page",
+ "description": "Relative path to the pipeline's page.",
"args": [
],
@@ -50953,7 +54451,7 @@
},
{
"name": "project",
- "description": "Project the pipeline belongs to",
+ "description": "Project the pipeline belongs to.",
"args": [
],
@@ -50967,7 +54465,7 @@
},
{
"name": "retryable",
- "description": "Specifies if a pipeline can be retried",
+ "description": "Specifies if a pipeline can be retried.",
"args": [
],
@@ -50985,7 +54483,7 @@
},
{
"name": "securityReportSummary",
- "description": "Vulnerability and scanned resource counts for each security scanner of the pipeline",
+ "description": "Vulnerability and scanned resource counts for each security scanner of the pipeline.",
"args": [
],
@@ -50999,7 +54497,7 @@
},
{
"name": "sha",
- "description": "SHA of the pipeline's commit",
+ "description": "SHA of the pipeline's commit.",
"args": [
],
@@ -51017,7 +54515,7 @@
},
{
"name": "sourceJob",
- "description": "Job where pipeline was triggered from",
+ "description": "Job where pipeline was triggered from.",
"args": [
],
@@ -51031,7 +54529,7 @@
},
{
"name": "stages",
- "description": "Stages of the pipeline",
+ "description": "Stages of the pipeline.",
"args": [
{
"name": "after",
@@ -51084,7 +54582,7 @@
},
{
"name": "startedAt",
- "description": "Timestamp when the pipeline was started",
+ "description": "Timestamp when the pipeline was started.",
"args": [
],
@@ -51116,7 +54614,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of the pipeline's last activity",
+ "description": "Timestamp of the pipeline's last activity.",
"args": [
],
@@ -51134,7 +54632,7 @@
},
{
"name": "upstream",
- "description": "Pipeline that triggered the pipeline",
+ "description": "Pipeline that triggered the pipeline.",
"args": [
],
@@ -51148,7 +54646,7 @@
},
{
"name": "user",
- "description": "Pipeline user",
+ "description": "Pipeline user.",
"args": [
],
@@ -51177,6 +54675,24 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "warnings",
+ "description": "Indicates if a pipeline has warnings.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -51193,7 +54709,7 @@
"fields": [
{
"name": "monthPipelinesLabels",
- "description": "Labels for the monthly pipeline count",
+ "description": "Labels for the monthly pipeline count.",
"args": [
],
@@ -51215,7 +54731,7 @@
},
{
"name": "monthPipelinesSuccessful",
- "description": "Total monthly successful pipeline count",
+ "description": "Total monthly successful pipeline count.",
"args": [
],
@@ -51237,7 +54753,7 @@
},
{
"name": "monthPipelinesTotals",
- "description": "Total monthly pipeline count",
+ "description": "Total monthly pipeline count.",
"args": [
],
@@ -51259,7 +54775,7 @@
},
{
"name": "pipelineTimesLabels",
- "description": "Pipeline times labels",
+ "description": "Pipeline times labels.",
"args": [
],
@@ -51281,7 +54797,7 @@
},
{
"name": "pipelineTimesValues",
- "description": "Pipeline times",
+ "description": "Pipeline times.",
"args": [
],
@@ -51303,7 +54819,7 @@
},
{
"name": "weekPipelinesLabels",
- "description": "Labels for the weekly pipeline count",
+ "description": "Labels for the weekly pipeline count.",
"args": [
],
@@ -51325,7 +54841,7 @@
},
{
"name": "weekPipelinesSuccessful",
- "description": "Total weekly successful pipeline count",
+ "description": "Total weekly successful pipeline count.",
"args": [
],
@@ -51347,7 +54863,7 @@
},
{
"name": "weekPipelinesTotals",
- "description": "Total weekly pipeline count",
+ "description": "Total weekly pipeline count.",
"args": [
],
@@ -51369,7 +54885,7 @@
},
{
"name": "yearPipelinesLabels",
- "description": "Labels for the yearly pipeline count",
+ "description": "Labels for the yearly pipeline count.",
"args": [
],
@@ -51391,7 +54907,7 @@
},
{
"name": "yearPipelinesSuccessful",
- "description": "Total yearly successful pipeline count",
+ "description": "Total yearly successful pipeline count.",
"args": [
],
@@ -51413,7 +54929,7 @@
},
{
"name": "yearPipelinesTotals",
- "description": "Total yearly pipeline count",
+ "description": "Total yearly pipeline count.",
"args": [
],
@@ -51584,6 +55100,12 @@
"description": null,
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "COMPLIANCE_SOURCE",
+ "description": null,
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"possibleTypes": null
@@ -51595,7 +55117,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -52059,7 +55581,7 @@
"fields": [
{
"name": "actualRepositorySizeLimit",
- "description": "Size limit for the repository in bytes",
+ "description": "Size limit for the repository in bytes.",
"args": [
],
@@ -52073,7 +55595,7 @@
},
{
"name": "alertManagementAlert",
- "description": "A single Alert Management alert of the project",
+ "description": "A single Alert Management alert of the project.",
"args": [
{
"name": "iid",
@@ -52158,7 +55680,7 @@
},
{
"name": "alertManagementAlertStatusCounts",
- "description": "Counts of alerts by status for the project",
+ "description": "Counts of alerts by status for the project.",
"args": [
{
"name": "search",
@@ -52191,7 +55713,7 @@
},
{
"name": "alertManagementAlerts",
- "description": "Alert Management alerts of the project",
+ "description": "Alert Management alerts of the project.",
"args": [
{
"name": "iid",
@@ -52316,7 +55838,7 @@
},
{
"name": "alertManagementIntegrations",
- "description": "Integrations which can receive alerts for the project",
+ "description": "Integrations which can receive alerts for the project.",
"args": [
{
"name": "after",
@@ -52368,8 +55890,43 @@
"deprecationReason": null
},
{
+ "name": "alertManagementPayloadFields",
+ "description": "Extract alert fields from payload for custom mapping.",
+ "args": [
+ {
+ "name": "payloadExample",
+ "description": "Sample payload for extracting alert fields for custom mappings.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "AlertManagementPayloadAlertField",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "allowMergeOnSkippedPipeline",
- "description": "If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs",
+ "description": "If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs.",
"args": [
],
@@ -52382,8 +55939,22 @@
"deprecationReason": null
},
{
+ "name": "apiFuzzingCiConfiguration",
+ "description": "API fuzzing configuration for the project. Available only when feature flag `api_fuzzing_configuration_ui` is enabled.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ApiFuzzingCiConfiguration",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "archived",
- "description": "Indicates the archived status of the project",
+ "description": "Indicates the archived status of the project.",
"args": [
],
@@ -52397,7 +55968,7 @@
},
{
"name": "autocloseReferencedIssues",
- "description": "Indicates if issues referenced by merge requests and commits within the default branch are closed automatically",
+ "description": "Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.",
"args": [
],
@@ -52411,7 +55982,7 @@
},
{
"name": "avatarUrl",
- "description": "URL to avatar image file of the project",
+ "description": "URL to avatar image file of the project.",
"args": [
],
@@ -52425,7 +55996,7 @@
},
{
"name": "board",
- "description": "A single board of the project",
+ "description": "A single board of the project.",
"args": [
{
"name": "id",
@@ -52452,7 +56023,7 @@
},
{
"name": "boards",
- "description": "Boards of the project",
+ "description": "Boards of the project.",
"args": [
{
"name": "id",
@@ -52515,7 +56086,7 @@
},
{
"name": "ciCdSettings",
- "description": "CI/CD settings for the project",
+ "description": "CI/CD settings for the project.",
"args": [
],
@@ -52529,7 +56100,7 @@
},
{
"name": "clusterAgent",
- "description": "Find a single cluster agent by name",
+ "description": "Find a single cluster agent by name.",
"args": [
{
"name": "name",
@@ -52556,7 +56127,7 @@
},
{
"name": "clusterAgents",
- "description": "Cluster agents associated with the project",
+ "description": "Cluster agents associated with the project.",
"args": [
{
"name": "after",
@@ -52609,7 +56180,7 @@
},
{
"name": "codeCoverageSummary",
- "description": "Code coverage summary associated with the project",
+ "description": "Code coverage summary associated with the project.",
"args": [
],
@@ -52623,7 +56194,7 @@
},
{
"name": "complianceFrameworks",
- "description": "Compliance frameworks associated with the project",
+ "description": "Compliance frameworks associated with the project.",
"args": [
{
"name": "after",
@@ -52676,7 +56247,7 @@
},
{
"name": "containerExpirationPolicy",
- "description": "The container expiration policy of the project",
+ "description": "The container expiration policy of the project.",
"args": [
],
@@ -52690,7 +56261,7 @@
},
{
"name": "containerRegistryEnabled",
- "description": "Indicates if the project stores Docker container images in a container registry",
+ "description": "Indicates if the project stores Docker container images in a container registry.",
"args": [
],
@@ -52704,7 +56275,7 @@
},
{
"name": "containerRepositories",
- "description": "Container repositories of the project",
+ "description": "Container repositories of the project.",
"args": [
{
"name": "name",
@@ -52717,6 +56288,16 @@
"defaultValue": null
},
{
+ "name": "sort",
+ "description": "Sort container repositories by this criteria.",
+ "type": {
+ "kind": "ENUM",
+ "name": "ContainerRepositorySort",
+ "ofType": null
+ },
+ "defaultValue": "created_desc"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -52767,7 +56348,7 @@
},
{
"name": "containerRepositoriesCount",
- "description": "Number of container repositories in the project",
+ "description": "Number of container repositories in the project.",
"args": [
],
@@ -52785,7 +56366,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of the project creation",
+ "description": "Timestamp of the project creation.",
"args": [
],
@@ -52798,8 +56379,61 @@
"deprecationReason": null
},
{
+ "name": "dastProfiles",
+ "description": "DAST Profiles associated with the project. Always returns no nodes if `dast_saved_scans` is disabled.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastProfileConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dastScannerProfiles",
- "description": "The DAST scanner profiles associated with the project",
+ "description": "The DAST scanner profiles associated with the project.",
"args": [
{
"name": "after",
@@ -52852,7 +56486,7 @@
},
{
"name": "dastSiteProfile",
- "description": "DAST Site Profile associated with the project",
+ "description": "DAST Site Profile associated with the project.",
"args": [
{
"name": "id",
@@ -52879,7 +56513,7 @@
},
{
"name": "dastSiteProfiles",
- "description": "DAST Site Profiles associated with the project",
+ "description": "DAST Site Profiles associated with the project.",
"args": [
{
"name": "after",
@@ -52932,7 +56566,7 @@
},
{
"name": "dastSiteValidations",
- "description": "DAST Site Validations associated with the project. Will always return no nodes if `security_on_demand_scans_site_validation` is disabled",
+ "description": "DAST Site Validations associated with the project. Always returns no nodes if `security_on_demand_scans_site_validation` is disabled.",
"args": [
{
"name": "normalizedTargetUrls",
@@ -53003,7 +56637,7 @@
},
{
"name": "description",
- "description": "Short description of the project",
+ "description": "Short description of the project.",
"args": [
],
@@ -53031,7 +56665,7 @@
},
{
"name": "environment",
- "description": "A single environment of the project",
+ "description": "A single environment of the project.",
"args": [
{
"name": "name",
@@ -53082,7 +56716,7 @@
},
{
"name": "environments",
- "description": "Environments of the project",
+ "description": "Environments of the project.",
"args": [
{
"name": "name",
@@ -53173,7 +56807,7 @@
},
{
"name": "forksCount",
- "description": "Number of times the project has been forked",
+ "description": "Number of times the project has been forked.",
"args": [
],
@@ -53191,7 +56825,7 @@
},
{
"name": "fullPath",
- "description": "Full path of the project",
+ "description": "Full path of the project.",
"args": [
],
@@ -53209,7 +56843,7 @@
},
{
"name": "grafanaIntegration",
- "description": "Grafana integration details for the project",
+ "description": "Grafana integration details for the project.",
"args": [
],
@@ -53223,7 +56857,7 @@
},
{
"name": "group",
- "description": "Group of the project",
+ "description": "Group of the project.",
"args": [
],
@@ -53237,7 +56871,7 @@
},
{
"name": "httpUrlToRepo",
- "description": "URL to connect to the project via HTTPS",
+ "description": "URL to connect to the project via HTTPS.",
"args": [
],
@@ -53251,7 +56885,7 @@
},
{
"name": "id",
- "description": "ID of the project",
+ "description": "ID of the project.",
"args": [
],
@@ -53269,7 +56903,7 @@
},
{
"name": "importStatus",
- "description": "Status of import background job of the project",
+ "description": "Status of import background job of the project.",
"args": [
],
@@ -53283,7 +56917,7 @@
},
{
"name": "incidentManagementOncallSchedules",
- "description": "Incident Management On-call schedules of the project",
+ "description": "Incident Management On-call schedules of the project.",
"args": [
{
"name": "after",
@@ -53336,7 +56970,7 @@
},
{
"name": "issue",
- "description": "A single issue of the project",
+ "description": "A single issue of the project.",
"args": [
{
"name": "iid",
@@ -53585,7 +57219,7 @@
},
{
"name": "issueStatusCounts",
- "description": "Counts of issues by status for the project",
+ "description": "Counts of issues by status for the project.",
"args": [
{
"name": "iid",
@@ -53790,7 +57424,7 @@
},
{
"name": "issues",
- "description": "Issues of the project",
+ "description": "Issues of the project.",
"args": [
{
"name": "iid",
@@ -54093,7 +57727,7 @@
},
{
"name": "iterations",
- "description": "Find iterations",
+ "description": "Find iterations.",
"args": [
{
"name": "startDate",
@@ -54226,7 +57860,7 @@
},
{
"name": "jiraImportStatus",
- "description": "Status of Jira import background job of the project",
+ "description": "Status of Jira import background job of the project.",
"args": [
],
@@ -54240,7 +57874,7 @@
},
{
"name": "jiraImports",
- "description": "Jira imports into the project",
+ "description": "Jira imports into the project.",
"args": [
{
"name": "after",
@@ -54293,7 +57927,7 @@
},
{
"name": "jobsEnabled",
- "description": "Indicates if CI/CD pipeline jobs are enabled for the current user",
+ "description": "Indicates if CI/CD pipeline jobs are enabled for the current user.",
"args": [
],
@@ -54307,11 +57941,11 @@
},
{
"name": "label",
- "description": "A label available on this project",
+ "description": "A label available on this project.",
"args": [
{
"name": "title",
- "description": "Title of the label",
+ "description": "Title of the label.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -54334,9 +57968,29 @@
},
{
"name": "labels",
- "description": "Labels available on this project",
+ "description": "Labels available on this project.",
"args": [
{
+ "name": "searchTerm",
+ "description": "A search term to find labels with.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "includeAncestorGroups",
+ "description": "Include labels from ancestor groups.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false"
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -54375,16 +58029,6 @@
"ofType": null
},
"defaultValue": null
- },
- {
- "name": "searchTerm",
- "description": "A search term to find labels with",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
}
],
"type": {
@@ -54397,7 +58041,7 @@
},
{
"name": "lastActivityAt",
- "description": "Timestamp of the project last activity",
+ "description": "Timestamp of the project last activity.",
"args": [
],
@@ -54411,7 +58055,7 @@
},
{
"name": "lfsEnabled",
- "description": "Indicates if the project has Large File Storage (LFS) enabled",
+ "description": "Indicates if the project has Large File Storage (LFS) enabled.",
"args": [
],
@@ -54425,7 +58069,7 @@
},
{
"name": "mergeRequest",
- "description": "A single merge request of the project",
+ "description": "A single merge request of the project.",
"args": [
{
"name": "iid",
@@ -54452,7 +58096,7 @@
},
{
"name": "mergeRequests",
- "description": "Merge requests of the project",
+ "description": "Merge requests of the project.",
"args": [
{
"name": "iids",
@@ -54685,7 +58329,7 @@
},
{
"name": "milestones",
- "description": "Milestones of the project",
+ "description": "Milestones of the project.",
"args": [
{
"name": "startDate",
@@ -54836,7 +58480,7 @@
},
{
"name": "name",
- "description": "Name of the project (without namespace)",
+ "description": "Name of the project (without namespace).",
"args": [
],
@@ -54854,7 +58498,7 @@
},
{
"name": "nameWithNamespace",
- "description": "Full name of the project with its namespace",
+ "description": "Full name of the project with its namespace.",
"args": [
],
@@ -54872,7 +58516,7 @@
},
{
"name": "namespace",
- "description": "Namespace of the project",
+ "description": "Namespace of the project.",
"args": [
],
@@ -54886,7 +58530,7 @@
},
{
"name": "onlyAllowMergeIfAllDiscussionsAreResolved",
- "description": "Indicates if merge requests of the project can only be merged when all the discussions are resolved",
+ "description": "Indicates if merge requests of the project can only be merged when all the discussions are resolved.",
"args": [
],
@@ -54900,7 +58544,7 @@
},
{
"name": "onlyAllowMergeIfPipelineSucceeds",
- "description": "Indicates if merge requests of the project can only be merged with successful jobs",
+ "description": "Indicates if merge requests of the project can only be merged with successful jobs.",
"args": [
],
@@ -54914,7 +58558,7 @@
},
{
"name": "openIssuesCount",
- "description": "Number of open issues for the project",
+ "description": "Number of open issues for the project.",
"args": [
],
@@ -54928,7 +58572,7 @@
},
{
"name": "packages",
- "description": "Packages of the project",
+ "description": "Packages of the project.",
"args": [
{
"name": "after",
@@ -54981,7 +58625,7 @@
},
{
"name": "path",
- "description": "Path of the project",
+ "description": "Path of the project.",
"args": [
],
@@ -54999,7 +58643,7 @@
},
{
"name": "pipeline",
- "description": "Build pipeline of the project",
+ "description": "Build pipeline of the project.",
"args": [
{
"name": "iid",
@@ -55026,7 +58670,7 @@
},
{
"name": "pipelineAnalytics",
- "description": "Pipeline analytics",
+ "description": "Pipeline analytics.",
"args": [
],
@@ -55040,7 +58684,7 @@
},
{
"name": "pipelines",
- "description": "Build pipelines of the project",
+ "description": "Build pipelines of the project.",
"args": [
{
"name": "status",
@@ -55123,7 +58767,7 @@
},
{
"name": "printingMergeRequestLinkEnabled",
- "description": "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",
+ "description": "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.",
"args": [
],
@@ -55137,7 +58781,7 @@
},
{
"name": "projectMembers",
- "description": "Members of the project",
+ "description": "Members of the project.",
"args": [
{
"name": "search",
@@ -55218,7 +58862,7 @@
},
{
"name": "publicJobs",
- "description": "Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts",
+ "description": "Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.",
"args": [
],
@@ -55232,7 +58876,7 @@
},
{
"name": "release",
- "description": "A single release of the project",
+ "description": "A single release of the project.",
"args": [
{
"name": "tagName",
@@ -55259,7 +58903,7 @@
},
{
"name": "releases",
- "description": "Releases of the project",
+ "description": "Releases of the project.",
"args": [
{
"name": "sort",
@@ -55322,7 +58966,7 @@
},
{
"name": "removeSourceBranchAfterMerge",
- "description": "Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project",
+ "description": "Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.",
"args": [
],
@@ -55336,7 +58980,7 @@
},
{
"name": "repository",
- "description": "Git repository of the project",
+ "description": "Git repository of the project.",
"args": [
],
@@ -55350,7 +58994,7 @@
},
{
"name": "repositorySizeExcess",
- "description": "Size of repository that exceeds the limit in bytes",
+ "description": "Size of repository that exceeds the limit in bytes.",
"args": [
],
@@ -55364,7 +59008,7 @@
},
{
"name": "requestAccessEnabled",
- "description": "Indicates if users can request member access to the project",
+ "description": "Indicates if users can request member access to the project.",
"args": [
],
@@ -55378,7 +59022,7 @@
},
{
"name": "requirement",
- "description": "Find a single requirement",
+ "description": "Find a single requirement.",
"args": [
{
"name": "sort",
@@ -55455,6 +59099,16 @@
}
},
"defaultValue": null
+ },
+ {
+ "name": "lastTestReportState",
+ "description": "The state of latest requirement test report.",
+ "type": {
+ "kind": "ENUM",
+ "name": "TestReportState",
+ "ofType": null
+ },
+ "defaultValue": null
}
],
"type": {
@@ -55467,7 +59121,7 @@
},
{
"name": "requirementStatesCount",
- "description": "Number of requirements for the project by their state",
+ "description": "Number of requirements for the project by their state.",
"args": [
],
@@ -55481,7 +59135,7 @@
},
{
"name": "requirements",
- "description": "Find requirements",
+ "description": "Find requirements.",
"args": [
{
"name": "sort",
@@ -55560,6 +59214,16 @@
"defaultValue": null
},
{
+ "name": "lastTestReportState",
+ "description": "The state of latest requirement test report.",
+ "type": {
+ "kind": "ENUM",
+ "name": "TestReportState",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -55610,7 +59274,7 @@
},
{
"name": "sastCiConfiguration",
- "description": "SAST CI configuration for the project",
+ "description": "SAST CI configuration for the project.",
"args": [
],
@@ -55624,7 +59288,7 @@
},
{
"name": "securityDashboardPath",
- "description": "Path to project's security dashboard",
+ "description": "Path to project's security dashboard.",
"args": [
],
@@ -55638,7 +59302,7 @@
},
{
"name": "securityScanners",
- "description": "Information about security analyzers used in the project",
+ "description": "Information about security analyzers used in the project.",
"args": [
],
@@ -55652,7 +59316,7 @@
},
{
"name": "sentryDetailedError",
- "description": "Detailed version of a Sentry error on the project",
+ "description": "Detailed version of a Sentry error on the project.",
"args": [
{
"name": "id",
@@ -55679,7 +59343,7 @@
},
{
"name": "sentryErrors",
- "description": "Paginated collection of Sentry errors on the project",
+ "description": "Paginated collection of Sentry errors on the project.",
"args": [
],
@@ -55721,7 +59385,7 @@
},
{
"name": "services",
- "description": "Project services",
+ "description": "Project services.",
"args": [
{
"name": "active",
@@ -55794,7 +59458,7 @@
},
{
"name": "sharedRunnersEnabled",
- "description": "Indicates if shared runners are enabled for the project",
+ "description": "Indicates if shared runners are enabled for the project.",
"args": [
],
@@ -55808,7 +59472,7 @@
},
{
"name": "snippets",
- "description": "Snippets of the project",
+ "description": "Snippets of the project.",
"args": [
{
"name": "ids",
@@ -55903,7 +59567,7 @@
},
{
"name": "squashReadOnly",
- "description": "Indicates if squash readonly is enabled",
+ "description": "Indicates if `squashReadOnly` is enabled.",
"args": [
],
@@ -55921,7 +59585,7 @@
},
{
"name": "sshUrlToRepo",
- "description": "URL to connect to the project via SSH",
+ "description": "URL to connect to the project via SSH.",
"args": [
],
@@ -55935,7 +59599,7 @@
},
{
"name": "starCount",
- "description": "Number of times the project has been starred",
+ "description": "Number of times the project has been starred.",
"args": [
],
@@ -55953,7 +59617,7 @@
},
{
"name": "statistics",
- "description": "Statistics of the project",
+ "description": "Statistics of the project.",
"args": [
],
@@ -55967,7 +59631,7 @@
},
{
"name": "suggestionCommitMessage",
- "description": "The commit message used to apply merge request suggestions",
+ "description": "The commit message used to apply merge request suggestions.",
"args": [
],
@@ -55981,7 +59645,7 @@
},
{
"name": "tagList",
- "description": "List of project topics (not Git tags)",
+ "description": "List of project topics (not Git tags).",
"args": [
],
@@ -55994,8 +59658,35 @@
"deprecationReason": null
},
{
+ "name": "terraformState",
+ "description": "Find a single Terraform state by name.",
+ "args": [
+ {
+ "name": "name",
+ "description": "Name of the Terraform state.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "TerraformState",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "terraformStates",
- "description": "Terraform states associated with the project",
+ "description": "Terraform states associated with the project.",
"args": [
{
"name": "after",
@@ -56066,7 +59757,7 @@
},
{
"name": "visibility",
- "description": "Visibility of the project",
+ "description": "Visibility of the project.",
"args": [
],
@@ -56080,7 +59771,7 @@
},
{
"name": "vulnerabilities",
- "description": "Vulnerabilities reported on the project",
+ "description": "Vulnerabilities reported on the project.",
"args": [
{
"name": "projectId",
@@ -56253,7 +59944,7 @@
},
{
"name": "vulnerabilitiesCountByDay",
- "description": "Number of vulnerabilities per day for the project",
+ "description": "Number of vulnerabilities per day for the project.",
"args": [
{
"name": "startDate",
@@ -56334,7 +60025,7 @@
},
{
"name": "vulnerabilityScanners",
- "description": "Vulnerability scanners reported on the project vulnerabilties",
+ "description": "Vulnerability scanners reported on the project vulnerabilities.",
"args": [
{
"name": "after",
@@ -56387,7 +60078,7 @@
},
{
"name": "vulnerabilitySeveritiesCount",
- "description": "Counts for each vulnerability severity in the project",
+ "description": "Counts for each vulnerability severity in the project.",
"args": [
{
"name": "projectId",
@@ -56490,7 +60181,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the project",
+ "description": "Web URL of the project.",
"args": [
],
@@ -56708,7 +60399,7 @@
{
"kind": "SCALAR",
"name": "ProjectID",
- "description": "Identifier of Project",
+ "description": "Identifier of Project.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -56722,7 +60413,7 @@
"fields": [
{
"name": "accessLevel",
- "description": "GitLab::Access level",
+ "description": "GitLab::Access level.",
"args": [
],
@@ -56736,7 +60427,7 @@
},
{
"name": "createdAt",
- "description": "Date and time the membership was created",
+ "description": "Date and time the membership was created.",
"args": [
],
@@ -56750,7 +60441,7 @@
},
{
"name": "createdBy",
- "description": "User that authorized membership",
+ "description": "User that authorized membership.",
"args": [
],
@@ -56764,7 +60455,7 @@
},
{
"name": "expiresAt",
- "description": "Date and time the membership expires",
+ "description": "Date and time the membership expires.",
"args": [
],
@@ -56778,7 +60469,7 @@
},
{
"name": "id",
- "description": "ID of the member",
+ "description": "ID of the member.",
"args": [
],
@@ -56796,7 +60487,7 @@
},
{
"name": "project",
- "description": "Project that User is a member of",
+ "description": "Project that User is a member of.",
"args": [
],
@@ -56810,7 +60501,7 @@
},
{
"name": "updatedAt",
- "description": "Date and time the membership was last updated",
+ "description": "Date and time the membership was last updated.",
"args": [
],
@@ -56824,7 +60515,7 @@
},
{
"name": "user",
- "description": "User that is associated with the member object",
+ "description": "User that is associated with the member object.",
"args": [
],
@@ -57793,7 +61484,7 @@
"fields": [
{
"name": "buildArtifactsSize",
- "description": "Build artifacts size of the project in bytes",
+ "description": "Build artifacts size of the project in bytes.",
"args": [
],
@@ -57811,7 +61502,7 @@
},
{
"name": "commitCount",
- "description": "Commit count of the project",
+ "description": "Commit count of the project.",
"args": [
],
@@ -57829,7 +61520,7 @@
},
{
"name": "lfsObjectsSize",
- "description": "Large File Storage (LFS) object size of the project in bytes",
+ "description": "Large File Storage (LFS) object size of the project in bytes.",
"args": [
],
@@ -57847,7 +61538,7 @@
},
{
"name": "packagesSize",
- "description": "Packages size of the project in bytes",
+ "description": "Packages size of the project in bytes.",
"args": [
],
@@ -57865,7 +61556,7 @@
},
{
"name": "repositorySize",
- "description": "Repository size of the project in bytes",
+ "description": "Repository size of the project in bytes.",
"args": [
],
@@ -57883,7 +61574,7 @@
},
{
"name": "snippetsSize",
- "description": "Snippets size of the project in bytes",
+ "description": "Snippets size of the project in bytes.",
"args": [
],
@@ -57897,7 +61588,7 @@
},
{
"name": "storageSize",
- "description": "Storage size of the project in bytes",
+ "description": "Storage size of the project in bytes.",
"args": [
],
@@ -57915,7 +61606,7 @@
},
{
"name": "uploadsSize",
- "description": "Uploads size of the project in bytes",
+ "description": "Uploads size of the project in bytes.",
"args": [
],
@@ -57929,7 +61620,7 @@
},
{
"name": "wikiSize",
- "description": "Wiki size of the project in bytes",
+ "description": "Wiki size of the project in bytes.",
"args": [
],
@@ -57956,7 +61647,7 @@
"fields": [
{
"name": "humanizedText",
- "description": "The human-readable text of the alert condition",
+ "description": "The human-readable text of the alert condition.",
"args": [
],
@@ -57974,7 +61665,7 @@
},
{
"name": "id",
- "description": "ID of the alert condition",
+ "description": "ID of the alert condition.",
"args": [
],
@@ -58355,7 +62046,7 @@
{
"kind": "SCALAR",
"name": "PrometheusServiceID",
- "description": "Identifier of PrometheusService",
+ "description": "Identifier of PrometheusService.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -58508,6 +62199,20 @@
"description": null,
"fields": [
{
+ "name": "ciApplicationSettings",
+ "description": "CI related settings that apply to the entire instance.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CiApplicationSettings",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "ciConfig",
"description": "Get linted and processed contents of a CI config. Should not be requested more than once per request.",
"args": [
@@ -58560,11 +62265,11 @@
},
{
"name": "containerRepository",
- "description": "Find a container repository",
+ "description": "Find a container repository.",
"args": [
{
"name": "id",
- "description": "The global ID of the container repository",
+ "description": "The global ID of the container repository.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -58587,7 +62292,7 @@
},
{
"name": "currentUser",
- "description": "Get information about current user",
+ "description": "Get information about current user.",
"args": [
],
@@ -58601,7 +62306,7 @@
},
{
"name": "designManagement",
- "description": "Fields related to design management",
+ "description": "Fields related to design management.",
"args": [
],
@@ -58619,7 +62324,7 @@
},
{
"name": "devopsAdoptionSegments",
- "description": "Get configured DevOps adoption segments on the instance",
+ "description": "Get configured DevOps adoption segments on the instance.",
"args": [
{
"name": "after",
@@ -58672,7 +62377,7 @@
},
{
"name": "echo",
- "description": "Text to echo back",
+ "description": "Text to echo back.",
"args": [
{
"name": "text",
@@ -58703,7 +62408,7 @@
},
{
"name": "geoNode",
- "description": "Find a Geo node",
+ "description": "Find a Geo node.",
"args": [
{
"name": "name",
@@ -58726,7 +62431,7 @@
},
{
"name": "group",
- "description": "Find a group",
+ "description": "Find a group.",
"args": [
{
"name": "fullPath",
@@ -58753,7 +62458,7 @@
},
{
"name": "instanceSecurityDashboard",
- "description": "Fields related to Instance Security Dashboard",
+ "description": "Fields related to Instance Security Dashboard.",
"args": [
],
@@ -58767,7 +62472,7 @@
},
{
"name": "instanceStatisticsMeasurements",
- "description": "Get statistics on the instance",
+ "description": "Get statistics on the instance.",
"args": [
{
"name": "identifier",
@@ -58854,11 +62559,11 @@
},
{
"name": "issue",
- "description": "Find an issue",
+ "description": "Find an issue.",
"args": [
{
"name": "id",
- "description": "The global ID of the Issue",
+ "description": "The global ID of the Issue.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -58881,11 +62586,11 @@
},
{
"name": "iteration",
- "description": "Find an iteration",
+ "description": "Find an iteration.",
"args": [
{
"name": "id",
- "description": "Find an iteration by its ID",
+ "description": "Find an iteration by its ID.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -58908,7 +62613,7 @@
},
{
"name": "metadata",
- "description": "Metadata about GitLab",
+ "description": "Metadata about GitLab.",
"args": [
],
@@ -58922,11 +62627,11 @@
},
{
"name": "milestone",
- "description": "Find a milestone",
+ "description": "Find a milestone.",
"args": [
{
"name": "id",
- "description": "Find a milestone by its ID",
+ "description": "Find a milestone by its ID.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -58949,7 +62654,7 @@
},
{
"name": "namespace",
- "description": "Find a namespace",
+ "description": "Find a namespace.",
"args": [
{
"name": "fullPath",
@@ -58975,8 +62680,8 @@
"deprecationReason": null
},
{
- "name": "packageComposerDetails",
- "description": "Find a composer package",
+ "name": "package",
+ "description": "Find a package.",
"args": [
{
"name": "id",
@@ -58995,7 +62700,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "PackageComposerDetails",
+ "name": "Package",
"ofType": null
},
"isDeprecated": false,
@@ -59003,7 +62708,7 @@
},
{
"name": "project",
- "description": "Find a project",
+ "description": "Find a project.",
"args": [
{
"name": "fullPath",
@@ -59030,7 +62735,7 @@
},
{
"name": "projects",
- "description": "Find projects visible to the current user",
+ "description": "Find projects visible to the current user.",
"args": [
{
"name": "membership",
@@ -59141,7 +62846,7 @@
},
{
"name": "runnerPlatforms",
- "description": "Supported runner platforms",
+ "description": "Supported runner platforms.",
"args": [
{
"name": "after",
@@ -59194,7 +62899,7 @@
},
{
"name": "runnerSetup",
- "description": "Get runner setup instructions",
+ "description": "Get runner setup instructions.",
"args": [
{
"name": "platform",
@@ -59255,7 +62960,7 @@
},
{
"name": "snippets",
- "description": "Find Snippets visible to the current user",
+ "description": "Find Snippets visible to the current user.",
"args": [
{
"name": "ids",
@@ -59376,7 +63081,7 @@
},
{
"name": "user",
- "description": "Find a user",
+ "description": "Find a user.",
"args": [
{
"name": "id",
@@ -59409,7 +63114,7 @@
},
{
"name": "users",
- "description": "Find users",
+ "description": "Find users.",
"args": [
{
"name": "ids",
@@ -59528,7 +63233,7 @@
},
{
"name": "vulnerabilities",
- "description": "Vulnerabilities reported on projects on the current user's instance security dashboard",
+ "description": "Vulnerabilities reported on projects on the current user's instance security dashboard.",
"args": [
{
"name": "projectId",
@@ -59701,7 +63406,7 @@
},
{
"name": "vulnerabilitiesCountByDay",
- "description": "Number of vulnerabilities per day for the projects on the current user's instance security dashboard",
+ "description": "Number of vulnerabilities per day for the projects on the current user's instance security dashboard.",
"args": [
{
"name": "startDate",
@@ -59782,7 +63487,7 @@
},
{
"name": "vulnerabilitiesCountByDayAndSeverity",
- "description": "Number of vulnerabilities per severity level, per day, for the projects on the current user's instance security dashboard Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.",
+ "description": "Number of vulnerabilities per severity level, per day, for the projects on the current user's instance security dashboard. Deprecated in 13.3: Use `vulnerabilitiesCountByDay`.",
"args": [
{
"name": "startDate",
@@ -59863,11 +63568,11 @@
},
{
"name": "vulnerability",
- "description": "Find a vulnerability",
+ "description": "Find a vulnerability.",
"args": [
{
"name": "id",
- "description": "The Global ID of the Vulnerability",
+ "description": "The Global ID of the Vulnerability.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -59938,7 +63643,7 @@
"fields": [
{
"name": "assets",
- "description": "Assets of the release",
+ "description": "Assets of the release.",
"args": [
],
@@ -59952,7 +63657,7 @@
},
{
"name": "author",
- "description": "User that created the release",
+ "description": "User that created the release.",
"args": [
],
@@ -59966,7 +63671,7 @@
},
{
"name": "commit",
- "description": "The commit associated with the release",
+ "description": "The commit associated with the release.",
"args": [
],
@@ -59980,7 +63685,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the release was created",
+ "description": "Timestamp of when the release was created.",
"args": [
],
@@ -59994,7 +63699,7 @@
},
{
"name": "description",
- "description": "Description (also known as \"release notes\") of the release",
+ "description": "Description (also known as \"release notes\") of the release.",
"args": [
],
@@ -60022,7 +63727,7 @@
},
{
"name": "evidences",
- "description": "Evidence for the release",
+ "description": "Evidence for the release.",
"args": [
{
"name": "after",
@@ -60075,7 +63780,7 @@
},
{
"name": "links",
- "description": "Links of the release",
+ "description": "Links of the release.",
"args": [
],
@@ -60089,7 +63794,7 @@
},
{
"name": "milestones",
- "description": "Milestones associated to the release",
+ "description": "Milestones associated to the release.",
"args": [
{
"name": "after",
@@ -60142,7 +63847,7 @@
},
{
"name": "name",
- "description": "Name of the release",
+ "description": "Name of the release.",
"args": [
],
@@ -60156,7 +63861,7 @@
},
{
"name": "releasedAt",
- "description": "Timestamp of when the release was released",
+ "description": "Timestamp of when the release was released.",
"args": [
],
@@ -60170,7 +63875,7 @@
},
{
"name": "tagName",
- "description": "Name of the tag associated with the release",
+ "description": "Name of the tag associated with the release.",
"args": [
],
@@ -60184,7 +63889,7 @@
},
{
"name": "tagPath",
- "description": "Relative web path to the tag associated with the release",
+ "description": "Relative web path to the tag associated with the release.",
"args": [
],
@@ -60198,7 +63903,7 @@
},
{
"name": "upcomingRelease",
- "description": "Indicates the release is an upcoming release",
+ "description": "Indicates the release is an upcoming release.",
"args": [
],
@@ -60225,7 +63930,7 @@
"fields": [
{
"name": "directAssetUrl",
- "description": "Direct asset URL of the link",
+ "description": "Direct asset URL of the link.",
"args": [
],
@@ -60239,7 +63944,7 @@
},
{
"name": "external",
- "description": "Indicates the link points to an external resource",
+ "description": "Indicates the link points to an external resource.",
"args": [
],
@@ -60253,7 +63958,7 @@
},
{
"name": "id",
- "description": "ID of the link",
+ "description": "ID of the link.",
"args": [
],
@@ -60271,7 +63976,7 @@
},
{
"name": "linkType",
- "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`",
+ "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.",
"args": [
],
@@ -60285,7 +63990,7 @@
},
{
"name": "name",
- "description": "Name of the link",
+ "description": "Name of the link.",
"args": [
],
@@ -60299,7 +64004,7 @@
},
{
"name": "url",
- "description": "URL of the link",
+ "description": "URL of the link.",
"args": [
],
@@ -60439,7 +64144,7 @@
"inputFields": [
{
"name": "name",
- "description": "Name of the asset link",
+ "description": "Name of the asset link.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -60453,7 +64158,7 @@
},
{
"name": "url",
- "description": "URL of the asset link",
+ "description": "URL of the asset link.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -60467,7 +64172,7 @@
},
{
"name": "directAssetPath",
- "description": "Relative path for a direct asset link",
+ "description": "Relative path for a direct asset link.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -60477,7 +64182,7 @@
},
{
"name": "linkType",
- "description": "The type of the asset link",
+ "description": "The type of the asset link.",
"type": {
"kind": "ENUM",
"name": "ReleaseAssetLinkType",
@@ -60532,7 +64237,7 @@
"fields": [
{
"name": "count",
- "description": "Number of assets of the release",
+ "description": "Number of assets of the release.",
"args": [
],
@@ -60546,7 +64251,7 @@
},
{
"name": "links",
- "description": "Asset links of the release",
+ "description": "Asset links of the release.",
"args": [
{
"name": "after",
@@ -60599,7 +64304,7 @@
},
{
"name": "sources",
- "description": "Sources of the release",
+ "description": "Sources of the release.",
"args": [
{
"name": "after",
@@ -60666,7 +64371,7 @@
"inputFields": [
{
"name": "links",
- "description": "A list of asset links to associate to the release",
+ "description": "A list of asset links to associate to the release.",
"type": {
"kind": "LIST",
"name": null,
@@ -60694,7 +64399,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -61124,7 +64829,7 @@
"fields": [
{
"name": "collectedAt",
- "description": "Timestamp when the evidence was collected",
+ "description": "Timestamp when the evidence was collected.",
"args": [
],
@@ -61138,7 +64843,7 @@
},
{
"name": "filepath",
- "description": "URL from where the evidence can be downloaded",
+ "description": "URL from where the evidence can be downloaded.",
"args": [
],
@@ -61152,7 +64857,7 @@
},
{
"name": "id",
- "description": "ID of the evidence",
+ "description": "ID of the evidence.",
"args": [
],
@@ -61170,7 +64875,7 @@
},
{
"name": "sha",
- "description": "SHA1 ID of the evidence hash",
+ "description": "SHA1 ID of the evidence hash.",
"args": [
],
@@ -61309,7 +65014,7 @@
"fields": [
{
"name": "closedIssuesUrl",
- "description": "HTTP URL of the issues page, filtered by this release and `state=closed`",
+ "description": "HTTP URL of the issues page, filtered by this release and `state=closed`.",
"args": [
],
@@ -61323,7 +65028,7 @@
},
{
"name": "closedMergeRequestsUrl",
- "description": "HTTP URL of the merge request page , filtered by this release and `state=closed`",
+ "description": "HTTP URL of the merge request page , filtered by this release and `state=closed`.",
"args": [
],
@@ -61337,7 +65042,7 @@
},
{
"name": "editUrl",
- "description": "HTTP URL of the release's edit page",
+ "description": "HTTP URL of the release's edit page.",
"args": [
],
@@ -61351,7 +65056,7 @@
},
{
"name": "mergedMergeRequestsUrl",
- "description": "HTTP URL of the merge request page , filtered by this release and `state=merged`",
+ "description": "HTTP URL of the merge request page , filtered by this release and `state=merged`.",
"args": [
],
@@ -61365,7 +65070,7 @@
},
{
"name": "openedIssuesUrl",
- "description": "HTTP URL of the issues page, filtered by this release and `state=open`",
+ "description": "HTTP URL of the issues page, filtered by this release and `state=open`.",
"args": [
],
@@ -61379,7 +65084,7 @@
},
{
"name": "openedMergeRequestsUrl",
- "description": "HTTP URL of the merge request page, filtered by this release and `state=open`",
+ "description": "HTTP URL of the merge request page, filtered by this release and `state=open`.",
"args": [
],
@@ -61393,7 +65098,7 @@
},
{
"name": "selfUrl",
- "description": "HTTP URL of the release",
+ "description": "HTTP URL of the release.",
"args": [
],
@@ -61455,7 +65160,7 @@
"fields": [
{
"name": "format",
- "description": "Format of the source",
+ "description": "Format of the source.",
"args": [
],
@@ -61469,7 +65174,7 @@
},
{
"name": "url",
- "description": "Download URL of the source",
+ "description": "Download URL of the source.",
"args": [
],
@@ -61787,7 +65492,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -61991,7 +65696,7 @@
},
{
"name": "position",
- "description": "The position of this note on a diff",
+ "description": "The position of this note on a diff.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -62092,7 +65797,7 @@
"fields": [
{
"name": "empty",
- "description": "Indicates repository has no visible content",
+ "description": "Indicates repository has no visible content.",
"args": [
],
@@ -62110,7 +65815,7 @@
},
{
"name": "exists",
- "description": "Indicates a corresponding Git repository exists on disk",
+ "description": "Indicates a corresponding Git repository exists on disk.",
"args": [
],
@@ -62128,7 +65833,7 @@
},
{
"name": "rootRef",
- "description": "Default branch of the repository",
+ "description": "Default branch of the repository.",
"args": [
],
@@ -62142,7 +65847,7 @@
},
{
"name": "tree",
- "description": "Tree of the repository",
+ "description": "Tree of the repository.",
"args": [
{
"name": "path",
@@ -62198,7 +65903,7 @@
"fields": [
{
"name": "author",
- "description": "Author of the requirement",
+ "description": "Author of the requirement.",
"args": [
],
@@ -62216,7 +65921,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the requirement was created",
+ "description": "Timestamp of when the requirement was created.",
"args": [
],
@@ -62234,7 +65939,7 @@
},
{
"name": "description",
- "description": "Description of the requirement",
+ "description": "Description of the requirement.",
"args": [
],
@@ -62262,7 +65967,7 @@
},
{
"name": "id",
- "description": "ID of the requirement",
+ "description": "ID of the requirement.",
"args": [
],
@@ -62280,7 +65985,7 @@
},
{
"name": "iid",
- "description": "Internal ID of the requirement",
+ "description": "Internal ID of the requirement.",
"args": [
],
@@ -62298,7 +66003,7 @@
},
{
"name": "lastTestReportManuallyCreated",
- "description": "Indicates if latest test report was created by user",
+ "description": "Indicates if latest test report was created by user.",
"args": [
],
@@ -62312,7 +66017,7 @@
},
{
"name": "lastTestReportState",
- "description": "Latest requirement test report state",
+ "description": "Latest requirement test report state.",
"args": [
],
@@ -62326,7 +66031,7 @@
},
{
"name": "project",
- "description": "Project to which the requirement belongs",
+ "description": "Project to which the requirement belongs.",
"args": [
],
@@ -62344,7 +66049,7 @@
},
{
"name": "state",
- "description": "State of the requirement",
+ "description": "State of the requirement.",
"args": [
],
@@ -62362,7 +66067,7 @@
},
{
"name": "testReports",
- "description": "Test reports of the requirement",
+ "description": "Test reports of the requirement.",
"args": [
{
"name": "sort",
@@ -62425,7 +66130,7 @@
},
{
"name": "title",
- "description": "Title of the requirement",
+ "description": "Title of the requirement.",
"args": [
],
@@ -62453,7 +66158,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp of when the requirement was last updated",
+ "description": "Timestamp of when the requirement was last updated.",
"args": [
],
@@ -62740,7 +66445,7 @@
"fields": [
{
"name": "archived",
- "description": "Number of archived requirements",
+ "description": "Number of archived requirements.",
"args": [
],
@@ -62754,7 +66459,7 @@
},
{
"name": "opened",
- "description": "Number of opened requirements",
+ "description": "Number of opened requirements.",
"args": [
],
@@ -62781,7 +66486,7 @@
"fields": [
{
"name": "resolvable",
- "description": "Indicates if the object can be resolved",
+ "description": "Indicates if the object can be resolved.",
"args": [
],
@@ -62799,7 +66504,7 @@
},
{
"name": "resolved",
- "description": "Indicates if the object is resolved",
+ "description": "Indicates if the object is resolved.",
"args": [
],
@@ -62817,7 +66522,7 @@
},
{
"name": "resolvedAt",
- "description": "Timestamp of when the object was resolved",
+ "description": "Timestamp of when the object was resolved.",
"args": [
],
@@ -62831,7 +66536,7 @@
},
{
"name": "resolvedBy",
- "description": "User who resolved the object",
+ "description": "User who resolved the object.",
"args": [
],
@@ -62969,7 +66674,7 @@
"fields": [
{
"name": "buildArtifactsSize",
- "description": "The CI artifacts size in bytes",
+ "description": "The CI artifacts size in bytes.",
"args": [
],
@@ -62987,7 +66692,7 @@
},
{
"name": "lfsObjectsSize",
- "description": "The LFS objects size in bytes",
+ "description": "The LFS objects size in bytes.",
"args": [
],
@@ -63005,7 +66710,7 @@
},
{
"name": "packagesSize",
- "description": "The packages size in bytes",
+ "description": "The packages size in bytes.",
"args": [
],
@@ -63023,7 +66728,7 @@
},
{
"name": "pipelineArtifactsSize",
- "description": "The CI pipeline artifacts size in bytes",
+ "description": "The CI pipeline artifacts size in bytes.",
"args": [
],
@@ -63041,7 +66746,7 @@
},
{
"name": "repositorySize",
- "description": "The Git repository size in bytes",
+ "description": "The Git repository size in bytes.",
"args": [
],
@@ -63059,7 +66764,7 @@
},
{
"name": "snippetsSize",
- "description": "The snippets size in bytes",
+ "description": "The snippets size in bytes.",
"args": [
],
@@ -63077,7 +66782,7 @@
},
{
"name": "storageSize",
- "description": "The total storage in bytes",
+ "description": "The total storage in bytes.",
"args": [
],
@@ -63095,7 +66800,7 @@
},
{
"name": "uploadsSize",
- "description": "The uploads size in bytes",
+ "description": "The uploads size in bytes.",
"args": [
],
@@ -63113,7 +66818,7 @@
},
{
"name": "wikiSize",
- "description": "The wiki size in bytes",
+ "description": "The wiki size in bytes.",
"args": [
],
@@ -63288,7 +66993,7 @@
"fields": [
{
"name": "downloadLocation",
- "description": "Download location for the runner for the platform architecture",
+ "description": "Download location for the runner for the platform architecture.",
"args": [
],
@@ -63306,7 +67011,7 @@
},
{
"name": "name",
- "description": "Name of the runner platform architecture",
+ "description": "Name of the runner platform architecture.",
"args": [
],
@@ -63449,7 +67154,7 @@
"fields": [
{
"name": "architectures",
- "description": "Runner architectures supported for the platform",
+ "description": "Runner architectures supported for the platform.",
"args": [
{
"name": "after",
@@ -63502,7 +67207,7 @@
},
{
"name": "humanReadableName",
- "description": "Human readable name of the runner platform",
+ "description": "Human readable name of the runner platform.",
"args": [
],
@@ -63520,7 +67225,7 @@
},
{
"name": "name",
- "description": "Name slug of the runner platform",
+ "description": "Name slug of the runner platform.",
"args": [
],
@@ -63663,7 +67368,7 @@
"fields": [
{
"name": "installInstructions",
- "description": "Instructions for installing the runner on the specified architecture",
+ "description": "Instructions for installing the runner on the specified architecture.",
"args": [
],
@@ -63681,7 +67386,7 @@
},
{
"name": "registerInstructions",
- "description": "Instructions for registering the runner",
+ "description": "Instructions for registering the runner.",
"args": [
],
@@ -63880,7 +67585,7 @@
"fields": [
{
"name": "description",
- "description": "Analyzer description that is displayed on the form",
+ "description": "Analyzer description that is displayed on the form.",
"args": [
],
@@ -63894,7 +67599,7 @@
},
{
"name": "enabled",
- "description": "Indicates whether an analyzer is enabled",
+ "description": "Indicates whether an analyzer is enabled.",
"args": [
],
@@ -63908,7 +67613,7 @@
},
{
"name": "label",
- "description": "Analyzer label used in the config UI",
+ "description": "Analyzer label used in the config UI.",
"args": [
],
@@ -63922,7 +67627,7 @@
},
{
"name": "name",
- "description": "Name of the analyzer",
+ "description": "Name of the analyzer.",
"args": [
],
@@ -63936,7 +67641,7 @@
},
{
"name": "variables",
- "description": "List of supported variables",
+ "description": "List of supported variables.",
"args": [
{
"name": "after",
@@ -64115,7 +67820,7 @@
"inputFields": [
{
"name": "name",
- "description": "Name of analyzer",
+ "description": "Name of analyzer.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -64129,7 +67834,7 @@
},
{
"name": "enabled",
- "description": "State of the analyzer",
+ "description": "State of the analyzer.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -64143,7 +67848,7 @@
},
{
"name": "variables",
- "description": "List of variables for the analyzer",
+ "description": "List of variables for the analyzer.",
"type": {
"kind": "LIST",
"name": null,
@@ -64448,7 +68153,7 @@
"inputFields": [
{
"name": "field",
- "description": "CI keyword of entity",
+ "description": "CI keyword of entity.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -64462,7 +68167,7 @@
},
{
"name": "defaultValue",
- "description": "Default value that is used if value is empty",
+ "description": "Default value that is used if value is empty.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -64476,7 +68181,7 @@
},
{
"name": "value",
- "description": "Current value of the entity",
+ "description": "Current value of the entity.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -64501,7 +68206,7 @@
"inputFields": [
{
"name": "global",
- "description": "List of global entities related to SAST configuration",
+ "description": "List of global entities related to SAST configuration.",
"type": {
"kind": "LIST",
"name": null,
@@ -64519,7 +68224,7 @@
},
{
"name": "pipeline",
- "description": "List of pipeline entities related to SAST configuration",
+ "description": "List of pipeline entities related to SAST configuration.",
"type": {
"kind": "LIST",
"name": null,
@@ -64537,7 +68242,7 @@
},
{
"name": "analyzers",
- "description": "List of analyzers and related variables for the SAST configuration",
+ "description": "List of analyzers and related variables for the SAST configuration.",
"type": {
"kind": "LIST",
"name": null,
@@ -64747,7 +68452,7 @@
"fields": [
{
"name": "requestMethod",
- "description": "The HTTP request method used to access the URL",
+ "description": "The HTTP request method used to access the URL.",
"args": [
],
@@ -64761,7 +68466,7 @@
},
{
"name": "url",
- "description": "The URL scanned by the scanner",
+ "description": "The URL scanned by the scanner.",
"args": [
],
@@ -64900,7 +68605,7 @@
"fields": [
{
"name": "apiFuzzing",
- "description": "Aggregated counts for the api_fuzzing scan",
+ "description": "Aggregated counts for the `api_fuzzing` scan",
"args": [
],
@@ -64914,7 +68619,7 @@
},
{
"name": "containerScanning",
- "description": "Aggregated counts for the container_scanning scan",
+ "description": "Aggregated counts for the `container_scanning` scan",
"args": [
],
@@ -64928,7 +68633,7 @@
},
{
"name": "coverageFuzzing",
- "description": "Aggregated counts for the coverage_fuzzing scan",
+ "description": "Aggregated counts for the `coverage_fuzzing` scan",
"args": [
],
@@ -64942,7 +68647,7 @@
},
{
"name": "dast",
- "description": "Aggregated counts for the dast scan",
+ "description": "Aggregated counts for the `dast` scan",
"args": [
],
@@ -64956,7 +68661,7 @@
},
{
"name": "dependencyScanning",
- "description": "Aggregated counts for the dependency_scanning scan",
+ "description": "Aggregated counts for the `dependency_scanning` scan",
"args": [
],
@@ -64970,7 +68675,7 @@
},
{
"name": "sast",
- "description": "Aggregated counts for the sast scan",
+ "description": "Aggregated counts for the `sast` scan",
"args": [
],
@@ -64984,7 +68689,7 @@
},
{
"name": "secretDetection",
- "description": "Aggregated counts for the secret_detection scan",
+ "description": "Aggregated counts for the `secret_detection` scan",
"args": [
],
@@ -65011,7 +68716,7 @@
"fields": [
{
"name": "scannedResources",
- "description": "A list of the first 20 scanned resources",
+ "description": "A list of the first 20 scanned resources.",
"args": [
{
"name": "after",
@@ -65064,7 +68769,7 @@
},
{
"name": "scannedResourcesCount",
- "description": "Total number of scanned resources",
+ "description": "Total number of scanned resources.",
"args": [
],
@@ -65078,7 +68783,7 @@
},
{
"name": "scannedResourcesCsvPath",
- "description": "Path to download all the scanned resources in CSV format",
+ "description": "Path to download all the scanned resources in CSV format.",
"args": [
],
@@ -65092,7 +68797,7 @@
},
{
"name": "vulnerabilitiesCount",
- "description": "Total number of vulnerabilities",
+ "description": "Total number of vulnerabilities.",
"args": [
],
@@ -65304,7 +69009,7 @@
"fields": [
{
"name": "count",
- "description": "Count of occurrences",
+ "description": "Count of occurrences.",
"args": [
],
@@ -65322,7 +69027,7 @@
},
{
"name": "culprit",
- "description": "Culprit of the error",
+ "description": "Culprit of the error.",
"args": [
],
@@ -65340,7 +69045,7 @@
},
{
"name": "externalBaseUrl",
- "description": "External Base URL of the Sentry Instance",
+ "description": "External Base URL of the Sentry Instance.",
"args": [
],
@@ -65358,7 +69063,7 @@
},
{
"name": "externalUrl",
- "description": "External URL of the error",
+ "description": "External URL of the error.",
"args": [
],
@@ -65376,7 +69081,7 @@
},
{
"name": "firstReleaseLastCommit",
- "description": "Commit the error was first seen",
+ "description": "Commit the error was first seen.",
"args": [
],
@@ -65390,7 +69095,7 @@
},
{
"name": "firstReleaseShortVersion",
- "description": "Release short version the error was first seen",
+ "description": "Release short version the error was first seen.",
"args": [
],
@@ -65404,7 +69109,7 @@
},
{
"name": "firstReleaseVersion",
- "description": "Release version the error was first seen",
+ "description": "Release version the error was first seen.",
"args": [
],
@@ -65418,7 +69123,7 @@
},
{
"name": "firstSeen",
- "description": "Timestamp when the error was first seen",
+ "description": "Timestamp when the error was first seen.",
"args": [
],
@@ -65436,7 +69141,7 @@
},
{
"name": "frequency",
- "description": "Last 24hr stats of the error",
+ "description": "Last 24hr stats of the error.",
"args": [
],
@@ -65462,7 +69167,7 @@
},
{
"name": "gitlabCommit",
- "description": "GitLab commit SHA attributed to the Error based on the release version",
+ "description": "GitLab commit SHA attributed to the Error based on the release version.",
"args": [
],
@@ -65476,7 +69181,7 @@
},
{
"name": "gitlabCommitPath",
- "description": "Path to the GitLab page for the GitLab commit attributed to the error",
+ "description": "Path to the GitLab page for the GitLab commit attributed to the error.",
"args": [
],
@@ -65490,7 +69195,7 @@
},
{
"name": "gitlabIssuePath",
- "description": "URL of GitLab Issue",
+ "description": "URL of GitLab Issue.",
"args": [
],
@@ -65504,7 +69209,7 @@
},
{
"name": "id",
- "description": "ID (global ID) of the error",
+ "description": "ID (global ID) of the error.",
"args": [
],
@@ -65522,7 +69227,7 @@
},
{
"name": "lastReleaseLastCommit",
- "description": "Commit the error was last seen",
+ "description": "Commit the error was last seen.",
"args": [
],
@@ -65536,7 +69241,7 @@
},
{
"name": "lastReleaseShortVersion",
- "description": "Release short version the error was last seen",
+ "description": "Release short version the error was last seen.",
"args": [
],
@@ -65550,7 +69255,7 @@
},
{
"name": "lastReleaseVersion",
- "description": "Release version the error was last seen",
+ "description": "Release version the error was last seen.",
"args": [
],
@@ -65564,7 +69269,7 @@
},
{
"name": "lastSeen",
- "description": "Timestamp when the error was last seen",
+ "description": "Timestamp when the error was last seen.",
"args": [
],
@@ -65582,7 +69287,7 @@
},
{
"name": "message",
- "description": "Sentry metadata message of the error",
+ "description": "Sentry metadata message of the error.",
"args": [
],
@@ -65596,7 +69301,7 @@
},
{
"name": "sentryId",
- "description": "ID (Sentry ID) of the error",
+ "description": "ID (Sentry ID) of the error.",
"args": [
],
@@ -65614,7 +69319,7 @@
},
{
"name": "sentryProjectId",
- "description": "ID of the project (Sentry project)",
+ "description": "ID of the project (Sentry project).",
"args": [
],
@@ -65632,7 +69337,7 @@
},
{
"name": "sentryProjectName",
- "description": "Name of the project affected by the error",
+ "description": "Name of the project affected by the error.",
"args": [
],
@@ -65650,7 +69355,7 @@
},
{
"name": "sentryProjectSlug",
- "description": "Slug of the project affected by the error",
+ "description": "Slug of the project affected by the error.",
"args": [
],
@@ -65668,7 +69373,7 @@
},
{
"name": "shortId",
- "description": "Short ID (Sentry ID) of the error",
+ "description": "Short ID (Sentry ID) of the error.",
"args": [
],
@@ -65686,7 +69391,7 @@
},
{
"name": "status",
- "description": "Status of the error",
+ "description": "Status of the error.",
"args": [
],
@@ -65704,7 +69409,7 @@
},
{
"name": "tags",
- "description": "Tags associated with the Sentry Error",
+ "description": "Tags associated with the Sentry Error.",
"args": [
],
@@ -65722,7 +69427,7 @@
},
{
"name": "title",
- "description": "Title of the error",
+ "description": "Title of the error.",
"args": [
],
@@ -65740,7 +69445,7 @@
},
{
"name": "type",
- "description": "Type of the error",
+ "description": "Type of the error.",
"args": [
],
@@ -65758,7 +69463,7 @@
},
{
"name": "userCount",
- "description": "Count of users affected by the error",
+ "description": "Count of users affected by the error.",
"args": [
],
@@ -65789,7 +69494,7 @@
"fields": [
{
"name": "count",
- "description": "Count of occurrences",
+ "description": "Count of occurrences.",
"args": [
],
@@ -65807,7 +69512,7 @@
},
{
"name": "culprit",
- "description": "Culprit of the error",
+ "description": "Culprit of the error.",
"args": [
],
@@ -65825,7 +69530,7 @@
},
{
"name": "externalUrl",
- "description": "External URL of the error",
+ "description": "External URL of the error.",
"args": [
],
@@ -65843,7 +69548,7 @@
},
{
"name": "firstSeen",
- "description": "Timestamp when the error was first seen",
+ "description": "Timestamp when the error was first seen.",
"args": [
],
@@ -65861,7 +69566,7 @@
},
{
"name": "frequency",
- "description": "Last 24hr stats of the error",
+ "description": "Last 24hr stats of the error.",
"args": [
],
@@ -65887,7 +69592,7 @@
},
{
"name": "id",
- "description": "ID (global ID) of the error",
+ "description": "ID (global ID) of the error.",
"args": [
],
@@ -65905,7 +69610,7 @@
},
{
"name": "lastSeen",
- "description": "Timestamp when the error was last seen",
+ "description": "Timestamp when the error was last seen.",
"args": [
],
@@ -65923,7 +69628,7 @@
},
{
"name": "message",
- "description": "Sentry metadata message of the error",
+ "description": "Sentry metadata message of the error.",
"args": [
],
@@ -65937,7 +69642,7 @@
},
{
"name": "sentryId",
- "description": "ID (Sentry ID) of the error",
+ "description": "ID (Sentry ID) of the error.",
"args": [
],
@@ -65955,7 +69660,7 @@
},
{
"name": "sentryProjectId",
- "description": "ID of the project (Sentry project)",
+ "description": "ID of the project (Sentry project).",
"args": [
],
@@ -65973,7 +69678,7 @@
},
{
"name": "sentryProjectName",
- "description": "Name of the project affected by the error",
+ "description": "Name of the project affected by the error.",
"args": [
],
@@ -65991,7 +69696,7 @@
},
{
"name": "sentryProjectSlug",
- "description": "Slug of the project affected by the error",
+ "description": "Slug of the project affected by the error.",
"args": [
],
@@ -66009,7 +69714,7 @@
},
{
"name": "shortId",
- "description": "Short ID (Sentry ID) of the error",
+ "description": "Short ID (Sentry ID) of the error.",
"args": [
],
@@ -66027,7 +69732,7 @@
},
{
"name": "status",
- "description": "Status of the error",
+ "description": "Status of the error.",
"args": [
],
@@ -66045,7 +69750,7 @@
},
{
"name": "title",
- "description": "Title of the error",
+ "description": "Title of the error.",
"args": [
],
@@ -66063,7 +69768,7 @@
},
{
"name": "type",
- "description": "Type of the error",
+ "description": "Type of the error.",
"args": [
],
@@ -66081,7 +69786,7 @@
},
{
"name": "userCount",
- "description": "Count of users affected by the error",
+ "description": "Count of users affected by the error.",
"args": [
],
@@ -66112,7 +69817,7 @@
"fields": [
{
"name": "detailedError",
- "description": "Detailed version of a Sentry error on the project",
+ "description": "Detailed version of a Sentry error on the project.",
"args": [
{
"name": "id",
@@ -66139,7 +69844,7 @@
},
{
"name": "errorStackTrace",
- "description": "Stack Trace of Sentry Error",
+ "description": "Stack Trace of Sentry Error.",
"args": [
{
"name": "id",
@@ -66166,7 +69871,7 @@
},
{
"name": "errors",
- "description": "Collection of Sentry Errors",
+ "description": "Collection of Sentry Errors.",
"args": [
{
"name": "searchTerm",
@@ -66239,7 +69944,7 @@
},
{
"name": "externalUrl",
- "description": "External URL for Sentry",
+ "description": "External URL for Sentry.",
"args": [
],
@@ -66378,7 +70083,7 @@
"fields": [
{
"name": "count",
- "description": "Count of errors received since the previously recorded time",
+ "description": "Count of errors received since the previously recorded time.",
"args": [
],
@@ -66396,7 +70101,7 @@
},
{
"name": "time",
- "description": "Time the error frequency stats were recorded",
+ "description": "Time the error frequency stats were recorded.",
"args": [
],
@@ -66427,7 +70132,7 @@
"fields": [
{
"name": "dateReceived",
- "description": "Time the stack trace was received by Sentry",
+ "description": "Time the stack trace was received by Sentry.",
"args": [
],
@@ -66445,7 +70150,7 @@
},
{
"name": "issueId",
- "description": "ID of the Sentry error",
+ "description": "ID of the Sentry error.",
"args": [
],
@@ -66463,7 +70168,7 @@
},
{
"name": "stackTraceEntries",
- "description": "Stack trace entries for the Sentry error",
+ "description": "Stack trace entries for the Sentry error.",
"args": [
],
@@ -66502,7 +70207,7 @@
"fields": [
{
"name": "code",
- "description": "Code number of the context",
+ "description": "Code number of the context.",
"args": [
],
@@ -66520,7 +70225,7 @@
},
{
"name": "line",
- "description": "Line number of the context",
+ "description": "Line number of the context.",
"args": [
],
@@ -66551,7 +70256,7 @@
"fields": [
{
"name": "col",
- "description": "Function in which the Sentry error occurred",
+ "description": "Function in which the Sentry error occurred.",
"args": [
],
@@ -66565,7 +70270,7 @@
},
{
"name": "fileName",
- "description": "File in which the Sentry error occurred",
+ "description": "File in which the Sentry error occurred.",
"args": [
],
@@ -66579,7 +70284,7 @@
},
{
"name": "function",
- "description": "Function in which the Sentry error occurred",
+ "description": "Function in which the Sentry error occurred.",
"args": [
],
@@ -66593,7 +70298,7 @@
},
{
"name": "line",
- "description": "Function in which the Sentry error occurred",
+ "description": "Function in which the Sentry error occurred.",
"args": [
],
@@ -66607,7 +70312,7 @@
},
{
"name": "traceContext",
- "description": "Context of the Sentry error",
+ "description": "Context of the Sentry error.",
"args": [
],
@@ -66677,7 +70382,7 @@
"fields": [
{
"name": "level",
- "description": "Severity level of the Sentry Error",
+ "description": "Severity level of the Sentry Error.",
"args": [
],
@@ -66691,7 +70396,7 @@
},
{
"name": "logger",
- "description": "Logger of the Sentry Error",
+ "description": "Logger of the Sentry Error.",
"args": [
],
@@ -66718,7 +70423,7 @@
"fields": [
{
"name": "active",
- "description": "Indicates if the service is active",
+ "description": "Indicates if the service is active.",
"args": [
],
@@ -66732,7 +70437,7 @@
},
{
"name": "type",
- "description": "Class name of the service",
+ "description": "Class name of the service.",
"args": [
],
@@ -66883,217 +70588,217 @@
"enumValues": [
{
"name": "ASANA_SERVICE",
- "description": null,
+ "description": "AsanaService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ASSEMBLA_SERVICE",
- "description": null,
+ "description": "AssemblaService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BAMBOO_SERVICE",
- "description": null,
+ "description": "BambooService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUGZILLA_SERVICE",
- "description": null,
+ "description": "BugzillaService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BUILDKITE_SERVICE",
- "description": null,
+ "description": "BuildkiteService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "CAMPFIRE_SERVICE",
- "description": null,
+ "description": "CampfireService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "CONFLUENCE_SERVICE",
- "description": null,
+ "description": "ConfluenceService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "CUSTOM_ISSUE_TRACKER_SERVICE",
- "description": null,
+ "description": "CustomIssueTrackerService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DATADOG_SERVICE",
- "description": null,
+ "description": "DatadogService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DISCORD_SERVICE",
- "description": null,
+ "description": "DiscordService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DRONE_CI_SERVICE",
- "description": null,
+ "description": "DroneCiService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "EMAILS_ON_PUSH_SERVICE",
- "description": null,
+ "description": "EmailsOnPushService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "EWM_SERVICE",
- "description": null,
+ "description": "EwmService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "EXTERNAL_WIKI_SERVICE",
- "description": null,
+ "description": "ExternalWikiService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "FLOWDOCK_SERVICE",
- "description": null,
+ "description": "FlowdockService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "GITHUB_SERVICE",
- "description": null,
+ "description": "GithubService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "HANGOUTS_CHAT_SERVICE",
- "description": null,
+ "description": "HangoutsChatService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "HIPCHAT_SERVICE",
- "description": null,
+ "description": "HipchatService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "IRKER_SERVICE",
- "description": null,
+ "description": "IrkerService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "JENKINS_SERVICE",
- "description": null,
+ "description": "JenkinsService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "JIRA_SERVICE",
- "description": null,
+ "description": "JiraService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MATTERMOST_SERVICE",
- "description": null,
+ "description": "MattermostService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MATTERMOST_SLASH_COMMANDS_SERVICE",
- "description": null,
+ "description": "MattermostSlashCommandsService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MICROSOFT_TEAMS_SERVICE",
- "description": null,
+ "description": "MicrosoftTeamsService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PACKAGIST_SERVICE",
- "description": null,
+ "description": "PackagistService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PIPELINES_EMAIL_SERVICE",
- "description": null,
+ "description": "PipelinesEmailService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PIVOTALTRACKER_SERVICE",
- "description": null,
+ "description": "PivotaltrackerService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PROMETHEUS_SERVICE",
- "description": null,
+ "description": "PrometheusService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PUSHOVER_SERVICE",
- "description": null,
+ "description": "PushoverService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "REDMINE_SERVICE",
- "description": null,
+ "description": "RedmineService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "SLACK_SERVICE",
- "description": null,
+ "description": "SlackService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "SLACK_SLASH_COMMANDS_SERVICE",
- "description": null,
+ "description": "SlackSlashCommandsService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "TEAMCITY_SERVICE",
- "description": null,
+ "description": "TeamcityService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "UNIFY_CIRCUIT_SERVICE",
- "description": null,
+ "description": "UnifyCircuitService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "WEBEX_TEAMS_SERVICE",
- "description": null,
+ "description": "WebexTeamsService type",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "YOUTRACK_SERVICE",
- "description": null,
+ "description": "YoutrackService type",
"isDeprecated": false,
"deprecationReason": null
}
@@ -67107,7 +70812,7 @@
"fields": [
{
"name": "author",
- "description": "The owner of the snippet",
+ "description": "The owner of the snippet.",
"args": [
],
@@ -67121,7 +70826,7 @@
},
{
"name": "blob",
- "description": "Snippet blob Deprecated in 13.3: Use `blobs`.",
+ "description": "Snippet blob. Deprecated in 13.3: Use `blobs`.",
"args": [
],
@@ -67139,7 +70844,7 @@
},
{
"name": "blobs",
- "description": "Snippet blobs",
+ "description": "Snippet blobs.",
"args": [
{
"name": "paths",
@@ -67210,7 +70915,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp this snippet was created",
+ "description": "Timestamp this snippet was created.",
"args": [
],
@@ -67228,7 +70933,7 @@
},
{
"name": "description",
- "description": "Description of the snippet",
+ "description": "Description of the snippet.",
"args": [
],
@@ -67256,7 +70961,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -67313,7 +71018,7 @@
},
{
"name": "fileName",
- "description": "File Name of the snippet",
+ "description": "File Name of the snippet.",
"args": [
],
@@ -67327,7 +71032,7 @@
},
{
"name": "httpUrlToRepo",
- "description": "HTTP URL to the snippet repository",
+ "description": "HTTP URL to the snippet repository.",
"args": [
],
@@ -67341,7 +71046,7 @@
},
{
"name": "id",
- "description": "ID of the snippet",
+ "description": "ID of the snippet.",
"args": [
],
@@ -67359,7 +71064,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -67416,7 +71121,7 @@
},
{
"name": "project",
- "description": "The project the snippet is associated with",
+ "description": "The project the snippet is associated with.",
"args": [
],
@@ -67430,7 +71135,7 @@
},
{
"name": "rawUrl",
- "description": "Raw URL of the snippet",
+ "description": "Raw URL of the snippet.",
"args": [
],
@@ -67448,7 +71153,7 @@
},
{
"name": "sshUrlToRepo",
- "description": "SSH URL to the snippet repository",
+ "description": "SSH URL to the snippet repository.",
"args": [
],
@@ -67462,7 +71167,7 @@
},
{
"name": "title",
- "description": "Title of the snippet",
+ "description": "Title of the snippet.",
"args": [
],
@@ -67480,7 +71185,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp this snippet was updated",
+ "description": "Timestamp this snippet was updated.",
"args": [
],
@@ -67516,7 +71221,7 @@
},
{
"name": "visibilityLevel",
- "description": "Visibility Level of the snippet",
+ "description": "Visibility Level of the snippet.",
"args": [
],
@@ -67534,7 +71239,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the snippet",
+ "description": "Web URL of the snippet.",
"args": [
],
@@ -67569,7 +71274,7 @@
"fields": [
{
"name": "binary",
- "description": "Shows whether the blob is binary",
+ "description": "Shows whether the blob is binary.",
"args": [
],
@@ -67587,7 +71292,7 @@
},
{
"name": "externalStorage",
- "description": "Blob external storage",
+ "description": "Blob external storage.",
"args": [
],
@@ -67601,7 +71306,7 @@
},
{
"name": "mode",
- "description": "Blob mode",
+ "description": "Blob mode.",
"args": [
],
@@ -67615,7 +71320,7 @@
},
{
"name": "name",
- "description": "Blob name",
+ "description": "Blob name.",
"args": [
],
@@ -67629,7 +71334,7 @@
},
{
"name": "path",
- "description": "Blob path",
+ "description": "Blob path.",
"args": [
],
@@ -67643,7 +71348,7 @@
},
{
"name": "plainData",
- "description": "Blob plain highlighted data",
+ "description": "Blob plain highlighted data.",
"args": [
],
@@ -67657,7 +71362,7 @@
},
{
"name": "rawPath",
- "description": "Blob raw content endpoint path",
+ "description": "Blob raw content endpoint path.",
"args": [
],
@@ -67675,7 +71380,7 @@
},
{
"name": "renderedAsText",
- "description": "Shows whether the blob is rendered as text",
+ "description": "Shows whether the blob is rendered as text.",
"args": [
],
@@ -67693,7 +71398,7 @@
},
{
"name": "richData",
- "description": "Blob highlighted data",
+ "description": "Blob highlighted data.",
"args": [
],
@@ -67707,7 +71412,7 @@
},
{
"name": "richViewer",
- "description": "Blob content rich viewer",
+ "description": "Blob content rich viewer.",
"args": [
],
@@ -67721,7 +71426,7 @@
},
{
"name": "simpleViewer",
- "description": "Blob content simple viewer",
+ "description": "Blob content simple viewer.",
"args": [
],
@@ -67739,7 +71444,7 @@
},
{
"name": "size",
- "description": "Blob size",
+ "description": "Blob size.",
"args": [
],
@@ -67806,7 +71511,7 @@
"inputFields": [
{
"name": "action",
- "description": "Type of input action",
+ "description": "Type of input action.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -67820,7 +71525,7 @@
},
{
"name": "previousPath",
- "description": "Previous path of the snippet file",
+ "description": "Previous path of the snippet file.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -67830,7 +71535,7 @@
},
{
"name": "filePath",
- "description": "Path of the snippet file",
+ "description": "Path of the snippet file.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -67844,7 +71549,7 @@
},
{
"name": "content",
- "description": "Snippet file content",
+ "description": "Snippet file content.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -67976,7 +71681,7 @@
"fields": [
{
"name": "collapsed",
- "description": "Shows whether the blob should be displayed collapsed",
+ "description": "Shows whether the blob should be displayed collapsed.",
"args": [
],
@@ -67994,7 +71699,7 @@
},
{
"name": "fileType",
- "description": "Content file type",
+ "description": "Content file type.",
"args": [
],
@@ -68012,7 +71717,7 @@
},
{
"name": "loadAsync",
- "description": "Shows whether the blob content is loaded async",
+ "description": "Shows whether the blob content is loaded asynchronously.",
"args": [
],
@@ -68030,7 +71735,7 @@
},
{
"name": "loadingPartialName",
- "description": "Loading partial name",
+ "description": "Loading partial name.",
"args": [
],
@@ -68048,7 +71753,7 @@
},
{
"name": "renderError",
- "description": "Error rendering the blob content",
+ "description": "Error rendering the blob content.",
"args": [
],
@@ -68062,7 +71767,7 @@
},
{
"name": "tooLarge",
- "description": "Shows whether the blob too large to be displayed",
+ "description": "Shows whether the blob too large to be displayed.",
"args": [
],
@@ -68080,7 +71785,7 @@
},
{
"name": "type",
- "description": "Type of blob viewer",
+ "description": "Type of blob viewer.",
"args": [
],
@@ -68219,7 +71924,7 @@
{
"kind": "SCALAR",
"name": "SnippetID",
- "description": "Identifier of Snippet",
+ "description": "Identifier of Snippet.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -68442,7 +72147,7 @@
},
{
"name": "snippetRepositoryId",
- "description": "ID of the Snippet Repository",
+ "description": "ID of the Snippet Repository.",
"args": [
],
@@ -68658,7 +72363,7 @@
"fields": [
{
"name": "buttonTitle",
- "description": "Title for the button, for example: Retry this job",
+ "description": "Title for the button, for example: Retry this job.",
"args": [
],
@@ -68672,7 +72377,7 @@
},
{
"name": "icon",
- "description": "Icon used in the action button",
+ "description": "Icon used in the action button.",
"args": [
],
@@ -68686,7 +72391,7 @@
},
{
"name": "method",
- "description": "Method for the action, for example: :post",
+ "description": "Method for the action, for example: :post.",
"args": [
],
@@ -68700,7 +72405,7 @@
},
{
"name": "path",
- "description": "Path for the action",
+ "description": "Path for the action.",
"args": [
],
@@ -68714,7 +72419,7 @@
},
{
"name": "title",
- "description": "Title for the action, for example: Retry",
+ "description": "Title for the action, for example: Retry.",
"args": [
],
@@ -68751,7 +72456,7 @@
"fields": [
{
"name": "flatPath",
- "description": "Flat path of the entry",
+ "description": "Flat path of the entry.",
"args": [
],
@@ -68769,7 +72474,7 @@
},
{
"name": "id",
- "description": "ID of the entry",
+ "description": "ID of the entry.",
"args": [
],
@@ -68787,7 +72492,7 @@
},
{
"name": "name",
- "description": "Name of the entry",
+ "description": "Name of the entry.",
"args": [
],
@@ -68805,7 +72510,7 @@
},
{
"name": "path",
- "description": "Path of the entry",
+ "description": "Path of the entry.",
"args": [
],
@@ -68823,7 +72528,7 @@
},
{
"name": "sha",
- "description": "Last commit sha for the entry",
+ "description": "Last commit SHA for the entry.",
"args": [
],
@@ -68841,7 +72546,7 @@
},
{
"name": "treeUrl",
- "description": "Tree URL for the sub-module",
+ "description": "Tree URL for the sub-module.",
"args": [
],
@@ -68855,7 +72560,7 @@
},
{
"name": "type",
- "description": "Type of tree entry",
+ "description": "Type of tree entry.",
"args": [
],
@@ -68873,7 +72578,7 @@
},
{
"name": "webUrl",
- "description": "Web URL for the sub-module",
+ "description": "Web URL for the sub-module.",
"args": [
],
@@ -69016,7 +72721,7 @@
"fields": [
{
"name": "completedCount",
- "description": "Number of completed tasks",
+ "description": "Number of completed tasks.",
"args": [
],
@@ -69034,7 +72739,7 @@
},
{
"name": "count",
- "description": "Number of total tasks",
+ "description": "Number of total tasks.",
"args": [
],
@@ -69065,7 +72770,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp the Terraform state was created",
+ "description": "Timestamp the Terraform state was created.",
"args": [
],
@@ -69083,7 +72788,7 @@
},
{
"name": "id",
- "description": "ID of the Terraform state",
+ "description": "ID of the Terraform state.",
"args": [
],
@@ -69101,7 +72806,7 @@
},
{
"name": "latestVersion",
- "description": "The latest version of the Terraform state",
+ "description": "The latest version of the Terraform state.",
"args": [
],
@@ -69115,7 +72820,7 @@
},
{
"name": "lockedAt",
- "description": "Timestamp the Terraform state was locked",
+ "description": "Timestamp the Terraform state was locked.",
"args": [
],
@@ -69129,7 +72834,7 @@
},
{
"name": "lockedByUser",
- "description": "The user currently holding a lock on the Terraform state",
+ "description": "The user currently holding a lock on the Terraform state.",
"args": [
],
@@ -69143,7 +72848,7 @@
},
{
"name": "name",
- "description": "Name of the Terraform state",
+ "description": "Name of the Terraform state.",
"args": [
],
@@ -69161,7 +72866,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp the Terraform state was updated",
+ "description": "Timestamp the Terraform state was updated.",
"args": [
],
@@ -69192,7 +72897,7 @@
"fields": [
{
"name": "count",
- "description": "Total count of collection",
+ "description": "Total count of collection.",
"args": [
],
@@ -69406,7 +73111,7 @@
{
"kind": "SCALAR",
"name": "TerraformStateID",
- "description": "Identifier of Terraform::State",
+ "description": "Identifier of Terraform::State.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -69596,7 +73301,7 @@
"fields": [
{
"name": "createdAt",
- "description": "Timestamp the version was created",
+ "description": "Timestamp the version was created.",
"args": [
],
@@ -69614,7 +73319,7 @@
},
{
"name": "createdByUser",
- "description": "The user that created this version",
+ "description": "The user that created this version.",
"args": [
],
@@ -69628,7 +73333,7 @@
},
{
"name": "downloadPath",
- "description": "URL for downloading the version's JSON file",
+ "description": "URL for downloading the version's JSON file.",
"args": [
],
@@ -69642,7 +73347,7 @@
},
{
"name": "id",
- "description": "ID of the Terraform state version",
+ "description": "ID of the Terraform state version.",
"args": [
],
@@ -69660,7 +73365,7 @@
},
{
"name": "job",
- "description": "The job that created this version",
+ "description": "The job that created this version.",
"args": [
],
@@ -69674,7 +73379,7 @@
},
{
"name": "serial",
- "description": "Serial number of the version",
+ "description": "Serial number of the version.",
"args": [
],
@@ -69688,7 +73393,7 @@
},
{
"name": "updatedAt",
- "description": "Timestamp the version was updated",
+ "description": "Timestamp the version was updated.",
"args": [
],
@@ -69821,7 +73526,7 @@
},
{
"name": "terraformStateVersionId",
- "description": "ID of the terraform state version",
+ "description": "ID of the terraform state version.",
"args": [
],
@@ -69964,7 +73669,7 @@
"fields": [
{
"name": "author",
- "description": "Author of the test report",
+ "description": "Author of the test report.",
"args": [
],
@@ -69978,7 +73683,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp of when the test report was created",
+ "description": "Timestamp of when the test report was created.",
"args": [
],
@@ -69996,7 +73701,7 @@
},
{
"name": "id",
- "description": "ID of the test report",
+ "description": "ID of the test report.",
"args": [
],
@@ -70014,7 +73719,7 @@
},
{
"name": "state",
- "description": "State of the test report",
+ "description": "State of the test report.",
"args": [
],
@@ -70190,7 +73895,7 @@
"fields": [
{
"name": "complete",
- "description": "Completed issues metrics",
+ "description": "Completed issues metrics.",
"args": [
],
@@ -70204,7 +73909,7 @@
},
{
"name": "incomplete",
- "description": "Incomplete issues metrics",
+ "description": "Incomplete issues metrics.",
"args": [
],
@@ -70218,7 +73923,7 @@
},
{
"name": "total",
- "description": "Total issues metrics",
+ "description": "Total issues metrics.",
"args": [
],
@@ -70245,7 +73950,7 @@
"fields": [
{
"name": "count",
- "description": "The count metric",
+ "description": "The count metric.",
"args": [
],
@@ -70263,7 +73968,7 @@
},
{
"name": "weight",
- "description": "The weight metric",
+ "description": "The weight metric.",
"args": [
],
@@ -70294,7 +73999,7 @@
"fields": [
{
"name": "burnupTimeSeries",
- "description": "Daily scope and completed totals for burnup charts",
+ "description": "Daily scope and completed totals for burnup charts.",
"args": [
],
@@ -70316,7 +74021,7 @@
},
{
"name": "stats",
- "description": "Represents the time report stats for the timebox",
+ "description": "Represents the time report stats for the timebox.",
"args": [
],
@@ -70343,7 +74048,7 @@
"fields": [
{
"name": "report",
- "description": "Historically accurate report about the timebox",
+ "description": "Historically accurate report about the timebox.",
"args": [
],
@@ -70380,7 +74085,7 @@
"inputFields": [
{
"name": "start",
- "description": "The start of the range",
+ "description": "The start of the range.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -70394,7 +74099,7 @@
},
{
"name": "end",
- "description": "The end of the range",
+ "description": "The end of the range.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -70418,7 +74123,7 @@
"fields": [
{
"name": "issue",
- "description": "The issue that logged time was added to",
+ "description": "The issue that logged time was added to.",
"args": [
],
@@ -70432,7 +74137,7 @@
},
{
"name": "note",
- "description": "The note where the quick action to add the logged time was executed",
+ "description": "The note where the quick action to add the logged time was executed.",
"args": [
],
@@ -70446,7 +74151,7 @@
},
{
"name": "spentAt",
- "description": "Timestamp of when the time tracked was spent at",
+ "description": "Timestamp of when the time tracked was spent at.",
"args": [
],
@@ -70460,7 +74165,7 @@
},
{
"name": "timeSpent",
- "description": "The time spent displayed in seconds",
+ "description": "The time spent displayed in seconds.",
"args": [
],
@@ -70478,7 +74183,7 @@
},
{
"name": "user",
- "description": "The user that logged the time",
+ "description": "The user that logged the time.",
"args": [
],
@@ -70617,11 +74322,11 @@
{
"kind": "OBJECT",
"name": "Todo",
- "description": "Representing a todo entry",
+ "description": "Representing a to-do entry",
"fields": [
{
"name": "action",
- "description": "Action of the todo",
+ "description": "Action of the to-do item.",
"args": [
],
@@ -70639,7 +74344,7 @@
},
{
"name": "author",
- "description": "The author of this todo",
+ "description": "The author of this to-do item.",
"args": [
],
@@ -70657,7 +74362,7 @@
},
{
"name": "body",
- "description": "Body of the todo",
+ "description": "Body of the to-do item.",
"args": [
],
@@ -70675,7 +74380,7 @@
},
{
"name": "createdAt",
- "description": "Timestamp this todo was created",
+ "description": "Timestamp this to-do item was created.",
"args": [
],
@@ -70693,7 +74398,7 @@
},
{
"name": "group",
- "description": "Group this todo is associated with",
+ "description": "Group this to-do item is associated with.",
"args": [
],
@@ -70707,7 +74412,7 @@
},
{
"name": "id",
- "description": "ID of the todo",
+ "description": "ID of the to-do item.",
"args": [
],
@@ -70725,7 +74430,7 @@
},
{
"name": "project",
- "description": "The project this todo is associated with",
+ "description": "The project this to-do item is associated with.",
"args": [
],
@@ -70739,7 +74444,7 @@
},
{
"name": "state",
- "description": "State of the todo",
+ "description": "State of the to-do item.",
"args": [
],
@@ -70757,7 +74462,7 @@
},
{
"name": "targetType",
- "description": "Target type of the todo",
+ "description": "Target type of the to-do item.",
"args": [
],
@@ -70983,7 +74688,7 @@
},
{
"name": "todo",
- "description": "The to-do created.",
+ "description": "The to-do item created.",
"args": [
],
@@ -71051,7 +74756,7 @@
{
"kind": "SCALAR",
"name": "TodoID",
- "description": "Identifier of Todo",
+ "description": "Identifier of Todo.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -71066,7 +74771,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the todo to mark as done.",
+ "description": "The global ID of the to-do item to mark as done.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -71140,7 +74845,7 @@
},
{
"name": "todo",
- "description": "The requested todo.",
+ "description": "The requested to-do item.",
"args": [
],
@@ -71172,7 +74877,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global ID of the todo to restore.",
+ "description": "The global ID of the to-do item to restore.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -71207,7 +74912,7 @@
"inputFields": [
{
"name": "ids",
- "description": "The global IDs of the todos to restore (a maximum of 50 is supported at once).",
+ "description": "The global IDs of the to-do items to restore (a maximum of 50 is supported at once).",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -71289,7 +74994,7 @@
},
{
"name": "todos",
- "description": "Updated todos.",
+ "description": "Updated to-do items.",
"args": [
],
@@ -71315,7 +75020,7 @@
},
{
"name": "updatedIds",
- "description": "The IDs of the updated todo items. Deprecated in 13.2: Use todos.",
+ "description": "The IDs of the updated to-do items. Deprecated in 13.2: Use to-do items.",
"args": [
],
@@ -71337,7 +75042,7 @@
}
},
"isDeprecated": true,
- "deprecationReason": "Use todos. Deprecated in 13.2."
+ "deprecationReason": "Use to-do items. Deprecated in 13.2."
}
],
"inputFields": null,
@@ -71394,7 +75099,7 @@
},
{
"name": "todo",
- "description": "The requested todo.",
+ "description": "The requested to-do item.",
"args": [
],
@@ -71491,7 +75196,7 @@
{
"kind": "SCALAR",
"name": "TodoableID",
- "description": "Identifier of Todoable",
+ "description": "Identifier of Todoable.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -71566,7 +75271,7 @@
},
{
"name": "todos",
- "description": "Updated todos.",
+ "description": "Updated to-do items.",
"args": [
],
@@ -71592,7 +75297,7 @@
},
{
"name": "updatedIds",
- "description": "Ids of the updated todos. Deprecated in 13.2: Use todos.",
+ "description": "IDs of the updated to-do items. Deprecated in 13.2: Use to-do items.",
"args": [
],
@@ -71614,7 +75319,7 @@
}
},
"isDeprecated": true,
- "deprecationReason": "Use todos. Deprecated in 13.2."
+ "deprecationReason": "Use to-do items. Deprecated in 13.2."
}
],
"inputFields": null,
@@ -71646,7 +75351,7 @@
},
{
"name": "name",
- "description": "The emoji name",
+ "description": "The emoji name.",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -71765,7 +75470,7 @@
"fields": [
{
"name": "blobs",
- "description": "Blobs of the tree",
+ "description": "Blobs of the tree.",
"args": [
{
"name": "after",
@@ -71822,7 +75527,7 @@
},
{
"name": "lastCommit",
- "description": "Last commit for the tree",
+ "description": "Last commit for the tree.",
"args": [
],
@@ -71836,7 +75541,7 @@
},
{
"name": "submodules",
- "description": "Sub-modules of the tree",
+ "description": "Sub-modules of the tree.",
"args": [
{
"name": "after",
@@ -71893,7 +75598,7 @@
},
{
"name": "trees",
- "description": "Trees of the tree",
+ "description": "Trees of the tree.",
"args": [
{
"name": "after",
@@ -71963,7 +75668,7 @@
"fields": [
{
"name": "flatPath",
- "description": "Flat path of the entry",
+ "description": "Flat path of the entry.",
"args": [
],
@@ -71981,7 +75686,7 @@
},
{
"name": "id",
- "description": "ID of the entry",
+ "description": "ID of the entry.",
"args": [
],
@@ -71999,7 +75704,7 @@
},
{
"name": "name",
- "description": "Name of the entry",
+ "description": "Name of the entry.",
"args": [
],
@@ -72017,7 +75722,7 @@
},
{
"name": "path",
- "description": "Path of the entry",
+ "description": "Path of the entry.",
"args": [
],
@@ -72035,7 +75740,7 @@
},
{
"name": "sha",
- "description": "Last commit sha for the entry",
+ "description": "Last commit SHA for the entry.",
"args": [
],
@@ -72053,7 +75758,7 @@
},
{
"name": "type",
- "description": "Type of tree entry",
+ "description": "Type of tree entry.",
"args": [
],
@@ -72071,7 +75776,7 @@
},
{
"name": "webPath",
- "description": "Web path for the tree entry (directory)",
+ "description": "Web path for the tree entry (directory).",
"args": [
],
@@ -72085,7 +75790,7 @@
},
{
"name": "webUrl",
- "description": "Web URL for the tree entry (directory)",
+ "description": "Web URL for the tree entry (directory).",
"args": [
],
@@ -72392,7 +76097,7 @@
},
{
"name": "todo",
- "description": "The todo after mutation.",
+ "description": "The to-do item after mutation.",
"args": [
],
@@ -72560,7 +76265,7 @@
},
{
"name": "hideBacklogList",
- "description": "Whether or not backlog list is hidden",
+ "description": "Whether or not backlog list is hidden.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -72570,7 +76275,7 @@
},
{
"name": "hideClosedList",
- "description": "Whether or not closed list is hidden",
+ "description": "Whether or not closed list is hidden.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -72634,7 +76339,7 @@
},
{
"name": "labels",
- "description": "Labels of the issue",
+ "description": "Labels of the issue.",
"type": {
"kind": "LIST",
"name": null,
@@ -73010,7 +76715,7 @@
},
{
"name": "enabled",
- "description": "Indicates whether this container expiration policy is enabled",
+ "description": "Indicates whether this container expiration policy is enabled.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -73020,7 +76725,7 @@
},
{
"name": "cadence",
- "description": "This container expiration policy schedule",
+ "description": "This container expiration policy schedule.",
"type": {
"kind": "ENUM",
"name": "ContainerExpirationPolicyCadenceEnum",
@@ -73030,7 +76735,7 @@
},
{
"name": "olderThan",
- "description": "Tags older that this will expire",
+ "description": "Tags older that this will expire.",
"type": {
"kind": "ENUM",
"name": "ContainerExpirationPolicyOlderThanEnum",
@@ -73040,7 +76745,7 @@
},
{
"name": "keepN",
- "description": "Number of tags to retain",
+ "description": "Number of tags to retain.",
"type": {
"kind": "ENUM",
"name": "ContainerExpirationPolicyKeepEnum",
@@ -73050,7 +76755,7 @@
},
{
"name": "nameRegex",
- "description": "Tags with names matching this regex pattern will expire",
+ "description": "Tags with names matching this regex pattern will expire.",
"type": {
"kind": "SCALAR",
"name": "UntrustedRegexp",
@@ -73060,7 +76765,7 @@
},
{
"name": "nameRegexKeep",
- "description": "Tags with names matching this regex pattern will be preserved",
+ "description": "Tags with names matching this regex pattern will be preserved.",
"type": {
"kind": "SCALAR",
"name": "UntrustedRegexp",
@@ -73152,147 +76857,13 @@
},
{
"kind": "INPUT_OBJECT",
- "name": "UpdateDevopsAdoptionSegmentInput",
- "description": "Autogenerated input type of UpdateDevopsAdoptionSegment",
- "fields": null,
- "inputFields": [
- {
- "name": "name",
- "description": "Name of the segment.",
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- },
- "defaultValue": null
- },
- {
- "name": "groupIds",
- "description": "The array of group IDs to set for the segment.",
- "type": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "GroupID",
- "ofType": null
- }
- }
- },
- "defaultValue": null
- },
- {
- "name": "id",
- "description": "ID of the segment.",
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "AnalyticsDevopsAdoptionSegmentID",
- "ofType": null
- }
- },
- "defaultValue": null
- },
- {
- "name": "clientMutationId",
- "description": "A unique identifier for the client performing the mutation.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- }
- ],
- "interfaces": null,
- "enumValues": null,
- "possibleTypes": null
- },
- {
- "kind": "OBJECT",
- "name": "UpdateDevopsAdoptionSegmentPayload",
- "description": "Autogenerated return type of UpdateDevopsAdoptionSegment",
- "fields": [
- {
- "name": "clientMutationId",
- "description": "A unique identifier for the client performing the mutation.",
- "args": [
-
- ],
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "errors",
- "description": "Errors encountered during execution of the mutation.",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "LIST",
- "name": null,
- "ofType": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- }
- }
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "segment",
- "description": "The segment after mutation.",
- "args": [
-
- ],
- "type": {
- "kind": "OBJECT",
- "name": "DevopsAdoptionSegment",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- }
- ],
- "inputFields": null,
- "interfaces": [
-
- ],
- "enumValues": null,
- "possibleTypes": null
- },
- {
- "kind": "INPUT_OBJECT",
"name": "UpdateDiffImagePositionInput",
"description": null,
"fields": null,
"inputFields": [
{
"name": "x",
- "description": "X position of the note",
+ "description": "X position of the note.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -73302,7 +76873,7 @@
},
{
"name": "y",
- "description": "Y position of the note",
+ "description": "Y position of the note.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -73312,7 +76883,7 @@
},
{
"name": "width",
- "description": "Total width of the image",
+ "description": "Total width of the image.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -73322,7 +76893,7 @@
},
{
"name": "height",
- "description": "Total height of the image",
+ "description": "Total height of the image.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -73589,7 +77160,7 @@
},
{
"name": "body",
- "description": "Content of the note",
+ "description": "Content of the note.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -73599,7 +77170,7 @@
},
{
"name": "position",
- "description": "The position of this note on a diff",
+ "description": "The position of this note on a diff.",
"type": {
"kind": "INPUT_OBJECT",
"name": "UpdateDiffImagePositionInput",
@@ -73725,7 +77296,7 @@
},
{
"name": "description",
- "description": "Description of the issue",
+ "description": "Description of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -73735,7 +77306,7 @@
},
{
"name": "dueDate",
- "description": "Due date of the issue",
+ "description": "Due date of the issue.",
"type": {
"kind": "SCALAR",
"name": "ISO8601Date",
@@ -73745,7 +77316,7 @@
},
{
"name": "confidential",
- "description": "Indicates the issue is confidential",
+ "description": "Indicates the issue is confidential.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -73755,7 +77326,7 @@
},
{
"name": "locked",
- "description": "Indicates discussion is locked on the issue",
+ "description": "Indicates discussion is locked on the issue.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -73765,7 +77336,7 @@
},
{
"name": "title",
- "description": "Title of the issue",
+ "description": "Title of the issue.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -74241,7 +77812,7 @@
},
{
"name": "body",
- "description": "Content of the note",
+ "description": "Content of the note.",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -74504,6 +78075,26 @@
"fields": null,
"inputFields": [
{
+ "name": "captchaResponse",
+ "description": "A 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\".",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "spamLogId",
+ "description": "The 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\".",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "id",
"description": "The global ID of the snippet to update.",
"type": {
@@ -74586,6 +78177,20 @@
"description": "Autogenerated return type of UpdateSnippet",
"fields": [
{
+ "name": "captchaSiteKey",
+ "description": "The 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.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
@@ -74626,6 +78231,20 @@
"deprecationReason": null
},
{
+ "name": "needsCaptchaResponse",
+ "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.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "snippet",
"description": "The snippet after mutation.",
"args": [
@@ -74641,7 +78260,7 @@
},
{
"name": "spam",
- "description": "Indicates whether the operation returns a record detected as spam.",
+ "description": "Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response.",
"args": [
],
@@ -74652,6 +78271,20 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "spamLogId",
+ "description": "The 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.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -74678,7 +78311,7 @@
"fields": [
{
"name": "assignedMergeRequests",
- "description": "Merge Requests assigned to the user",
+ "description": "Merge Requests assigned to the user.",
"args": [
{
"name": "iids",
@@ -74893,7 +78526,7 @@
},
{
"name": "authoredMergeRequests",
- "description": "Merge Requests authored by the user",
+ "description": "Merge Requests authored by the user.",
"args": [
{
"name": "iids",
@@ -75108,7 +78741,7 @@
},
{
"name": "avatarUrl",
- "description": "URL of the user's avatar",
+ "description": "URL of the user's avatar.",
"args": [
],
@@ -75121,8 +78754,26 @@
"deprecationReason": null
},
{
+ "name": "bot",
+ "description": "Indicates if the user is a bot.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "email",
- "description": "User email Deprecated in 13.7: Use public_email.",
+ "description": "User email. Deprecated in 13.7: Use public_email.",
"args": [
],
@@ -75136,7 +78787,7 @@
},
{
"name": "groupCount",
- "description": "Group count for the user Available only when feature flag `user_group_counts` is enabled.",
+ "description": "Group count for the user. Available only when feature flag `user_group_counts` is enabled.",
"args": [
],
@@ -75150,7 +78801,7 @@
},
{
"name": "groupMemberships",
- "description": "Group memberships of the user",
+ "description": "Group memberships of the user.",
"args": [
{
"name": "after",
@@ -75203,7 +78854,7 @@
},
{
"name": "id",
- "description": "ID of the user",
+ "description": "ID of the user.",
"args": [
],
@@ -75235,7 +78886,7 @@
},
{
"name": "name",
- "description": "Human-readable name of the user",
+ "description": "Human-readable name of the user.",
"args": [
],
@@ -75253,7 +78904,7 @@
},
{
"name": "projectMemberships",
- "description": "Project memberships of the user",
+ "description": "Project memberships of the user.",
"args": [
{
"name": "after",
@@ -75306,7 +78957,7 @@
},
{
"name": "publicEmail",
- "description": "User's public email",
+ "description": "User's public email.",
"args": [
],
@@ -75320,7 +78971,7 @@
},
{
"name": "reviewRequestedMergeRequests",
- "description": "Merge Requests assigned to the user for review",
+ "description": "Merge Requests assigned to the user for review.",
"args": [
{
"name": "iids",
@@ -75535,7 +79186,7 @@
},
{
"name": "snippets",
- "description": "Snippets authored by the user",
+ "description": "Snippets authored by the user.",
"args": [
{
"name": "ids",
@@ -75626,7 +79277,7 @@
},
{
"name": "starredProjects",
- "description": "Projects starred by the user",
+ "description": "Projects starred by the user.",
"args": [
{
"name": "search",
@@ -75689,7 +79340,7 @@
},
{
"name": "state",
- "description": "State of the user",
+ "description": "State of the user.",
"args": [
],
@@ -75707,7 +79358,7 @@
},
{
"name": "status",
- "description": "User status",
+ "description": "User status.",
"args": [
],
@@ -75721,7 +79372,7 @@
},
{
"name": "todos",
- "description": "Todos of the user",
+ "description": "To-do items of the user.",
"args": [
{
"name": "action",
@@ -75904,7 +79555,7 @@
},
{
"name": "username",
- "description": "Username of the user. Unique within this instance of GitLab",
+ "description": "Username of the user. Unique within this instance of GitLab.",
"args": [
],
@@ -75922,7 +79573,7 @@
},
{
"name": "webPath",
- "description": "Web path of the user",
+ "description": "Web path of the user.",
"args": [
],
@@ -75940,7 +79591,7 @@
},
{
"name": "webUrl",
- "description": "Web URL of the user",
+ "description": "Web URL of the user.",
"args": [
],
@@ -76079,7 +79730,7 @@
{
"kind": "SCALAR",
"name": "UserID",
- "description": "Identifier of User",
+ "description": "Identifier of User.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -76153,7 +79804,7 @@
"fields": [
{
"name": "availability",
- "description": "User availability status",
+ "description": "User availability status.",
"args": [
],
@@ -76171,7 +79822,7 @@
},
{
"name": "emoji",
- "description": "String representation of emoji",
+ "description": "String representation of emoji.",
"args": [
],
@@ -76185,7 +79836,7 @@
},
{
"name": "message",
- "description": "User status message",
+ "description": "User status message.",
"args": [
],
@@ -76302,7 +79953,7 @@
},
{
"name": "date",
- "description": "Date for the count",
+ "description": "Date for the count.",
"args": [
],
@@ -76392,7 +80043,7 @@
},
{
"name": "total",
- "description": "Total number of vulnerabilities on a particular day",
+ "description": "Total number of vulnerabilities on a particular day.",
"args": [
],
@@ -76441,7 +80092,7 @@
"fields": [
{
"name": "count",
- "description": "Number of vulnerabilities",
+ "description": "Number of vulnerabilities.",
"args": [
],
@@ -76455,7 +80106,7 @@
},
{
"name": "day",
- "description": "Date for the count",
+ "description": "Date for the count.",
"args": [
],
@@ -76469,7 +80120,7 @@
},
{
"name": "severity",
- "description": "Severity of the counted vulnerabilities",
+ "description": "Severity of the counted vulnerabilities.",
"args": [
],
@@ -76716,7 +80367,7 @@
{
"kind": "SCALAR",
"name": "VulnerabilitiesExternalIssueLinkID",
- "description": "Identifier of Vulnerabilities::ExternalIssueLink",
+ "description": "Identifier of Vulnerabilities::ExternalIssueLink.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -76730,7 +80381,7 @@
"fields": [
{
"name": "confirmedAt",
- "description": "Timestamp of when the vulnerability state was changed to confirmed",
+ "description": "Timestamp of when the vulnerability state was changed to confirmed.",
"args": [
],
@@ -76758,7 +80409,7 @@
},
{
"name": "description",
- "description": "Description of the vulnerability",
+ "description": "Description of the vulnerability.",
"args": [
],
@@ -76771,8 +80422,34 @@
"deprecationReason": null
},
{
+ "name": "details",
+ "description": "Details of the vulnerability.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "UNION",
+ "name": "VulnerabilityDetail",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "detectedAt",
- "description": "Timestamp of when the vulnerability was first detected",
+ "description": "Timestamp of when the vulnerability was first detected.",
"args": [
],
@@ -76790,7 +80467,7 @@
},
{
"name": "discussions",
- "description": "All discussions on this noteable",
+ "description": "All discussions on this noteable.",
"args": [
{
"name": "after",
@@ -76847,7 +80524,7 @@
},
{
"name": "dismissedAt",
- "description": "Timestamp of when the vulnerability state was changed to dismissed",
+ "description": "Timestamp of when the vulnerability state was changed to dismissed.",
"args": [
],
@@ -76875,7 +80552,7 @@
},
{
"name": "externalIssueLinks",
- "description": "List of external issue links related to the vulnerability",
+ "description": "List of external issue links related to the vulnerability.",
"args": [
{
"name": "after",
@@ -76946,7 +80623,7 @@
},
{
"name": "id",
- "description": "GraphQL ID of the vulnerability",
+ "description": "GraphQL ID of the vulnerability.",
"args": [
],
@@ -76990,7 +80667,7 @@
},
{
"name": "issueLinks",
- "description": "List of issue links related to the vulnerability",
+ "description": "List of issue links related to the vulnerability.",
"args": [
{
"name": "linkType",
@@ -77057,7 +80734,7 @@
},
{
"name": "location",
- "description": "Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability",
+ "description": "Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability.",
"args": [
],
@@ -77085,7 +80762,7 @@
},
{
"name": "notes",
- "description": "All notes on this noteable",
+ "description": "All notes on this noteable.",
"args": [
{
"name": "after",
@@ -77156,7 +80833,7 @@
},
{
"name": "project",
- "description": "The project on which the vulnerability was found",
+ "description": "The project on which the vulnerability was found.",
"args": [
],
@@ -77184,7 +80861,7 @@
},
{
"name": "resolvedAt",
- "description": "Timestamp of when the vulnerability state was changed to resolved",
+ "description": "Timestamp of when the vulnerability state was changed to resolved.",
"args": [
],
@@ -77212,7 +80889,7 @@
},
{
"name": "resolvedOnDefaultBranch",
- "description": "Indicates whether the vulnerability is fixed on the default branch or not",
+ "description": "Indicates whether the vulnerability is fixed on the default branch or not.",
"args": [
],
@@ -77272,7 +80949,7 @@
},
{
"name": "title",
- "description": "Title of the vulnerability",
+ "description": "Title of the vulnerability.",
"args": [
],
@@ -77286,7 +80963,7 @@
},
{
"name": "userNotesCount",
- "description": "Number of user notes attached to the vulnerability",
+ "description": "Number of user notes attached to the vulnerability.",
"args": [
],
@@ -77322,7 +80999,7 @@
},
{
"name": "vulnerabilityPath",
- "description": "URL to the vulnerability's details page",
+ "description": "URL to the vulnerability's details page.",
"args": [
],
@@ -77516,6 +81193,1259 @@
"possibleTypes": null
},
{
+ "kind": "UNION",
+ "name": "VulnerabilityDetail",
+ "description": "Represents a vulnerability detail field. The fields with data will depend on the vulnerability detail type",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailBase",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailBoolean",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailCode",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailCommit",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailDiff",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailFileLocation",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailInt",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailList",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailMarkdown",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailModuleLocation",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailTable",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailText",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailUrl",
+ "ofType": null
+ }
+ ]
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailBase",
+ "description": "Represents the vulnerability details base",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailBoolean",
+ "description": "Represents the vulnerability details boolean value",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "value",
+ "description": "Value of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailCode",
+ "description": "Represents the vulnerability details code field",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lang",
+ "description": "Language of the code.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "value",
+ "description": "Source code.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailCommit",
+ "description": "Represents the vulnerability details commit field",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "value",
+ "description": "The commit SHA value.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailDiff",
+ "description": "Represents the vulnerability details diff field",
+ "fields": [
+ {
+ "name": "after",
+ "description": "Value of the field after the change.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "before",
+ "description": "Value of the field before the change.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailFileLocation",
+ "description": "Represents the vulnerability details location within a file in the project",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fileName",
+ "description": "File name.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lineEnd",
+ "description": "End line number of the file location.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lineStart",
+ "description": "Start line number of the file location.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailInt",
+ "description": "Represents the vulnerability details integer value",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "value",
+ "description": "Value of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailList",
+ "description": "Represents the vulnerability details list value",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "items",
+ "description": "List of details.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "UNION",
+ "name": "VulnerabilityDetail",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailMarkdown",
+ "description": "Represents the vulnerability details Markdown field",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "value",
+ "description": "Value of the Markdown field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailModuleLocation",
+ "description": "Represents the vulnerability details location within a file in the project",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "moduleName",
+ "description": "Module name.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "offset",
+ "description": "Offset of the module location.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailTable",
+ "description": "Represents the vulnerability details table value",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "headers",
+ "description": "Table headers.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "UNION",
+ "name": "VulnerabilityDetail",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "rows",
+ "description": "Table rows.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "UNION",
+ "name": "VulnerabilityDetail",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailText",
+ "description": "Represents the vulnerability details text field",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "value",
+ "description": "Value of the text field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "VulnerabilityDetailUrl",
+ "description": "Represents the vulnerability details URL field",
+ "fields": [
+ {
+ "name": "description",
+ "description": "Description of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "fieldName",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "href",
+ "description": "Href of the URL.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "name",
+ "description": "Name of the field.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "text",
+ "description": "Text of the URL.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "VulnerabilityDismissInput",
"description": "Autogenerated input type of VulnerabilityDismiss",
@@ -77730,7 +82660,7 @@
"fields": [
{
"name": "externalIssue",
- "description": "The external issue attached to the issue link",
+ "description": "The external issue attached to the issue link.",
"args": [
],
@@ -77744,7 +82674,7 @@
},
{
"name": "id",
- "description": "GraphQL ID of the external issue link",
+ "description": "GraphQL ID of the external issue link.",
"args": [
],
@@ -77762,7 +82692,7 @@
},
{
"name": "linkType",
- "description": "Type of the external issue link",
+ "description": "Type of the external issue link.",
"args": [
],
@@ -78194,7 +83124,7 @@
{
"kind": "SCALAR",
"name": "VulnerabilityID",
- "description": "Identifier of Vulnerability",
+ "description": "Identifier of Vulnerability.",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -78208,7 +83138,7 @@
"fields": [
{
"name": "externalId",
- "description": "External ID of the vulnerability identifier",
+ "description": "External ID of the vulnerability identifier.",
"args": [
],
@@ -78222,7 +83152,7 @@
},
{
"name": "externalType",
- "description": "External type of the vulnerability identifier",
+ "description": "External type of the vulnerability identifier.",
"args": [
],
@@ -78236,7 +83166,7 @@
},
{
"name": "name",
- "description": "Name of the vulnerability identifier",
+ "description": "Name of the vulnerability identifier.",
"args": [
],
@@ -78250,7 +83180,7 @@
},
{
"name": "url",
- "description": "URL of the vulnerability identifier",
+ "description": "URL of the vulnerability identifier.",
"args": [
],
@@ -78277,7 +83207,7 @@
"fields": [
{
"name": "id",
- "description": "GraphQL ID of the vulnerability",
+ "description": "GraphQL ID of the vulnerability.",
"args": [
],
@@ -78295,7 +83225,7 @@
},
{
"name": "issue",
- "description": "The issue attached to issue link",
+ "description": "The issue attached to issue link.",
"args": [
],
@@ -78313,7 +83243,7 @@
},
{
"name": "linkType",
- "description": "Type of the issue link",
+ "description": "Type of the issue link.",
"args": [
],
@@ -78520,7 +83450,7 @@
"fields": [
{
"name": "dependency",
- "description": "Dependency containing the vulnerability",
+ "description": "Dependency containing the vulnerability.",
"args": [
],
@@ -78534,7 +83464,7 @@
},
{
"name": "image",
- "description": "Name of the vulnerable container image",
+ "description": "Name of the vulnerable container image.",
"args": [
],
@@ -78548,7 +83478,7 @@
},
{
"name": "operatingSystem",
- "description": "Operating system that runs on the vulnerable container image",
+ "description": "Operating system that runs on the vulnerable container image.",
"args": [
],
@@ -78574,8 +83504,22 @@
"description": "Represents the location of a vulnerability found by a Coverage Fuzzing scan",
"fields": [
{
+ "name": "blobPath",
+ "description": "Blob path to the vulnerable file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "endLine",
- "description": "Number of the last relevant line in the vulnerable file",
+ "description": "Number of the last relevant line in the vulnerable file.",
"args": [
],
@@ -78589,7 +83533,7 @@
},
{
"name": "file",
- "description": "Path to the vulnerable file",
+ "description": "Path to the vulnerable file.",
"args": [
],
@@ -78603,7 +83547,7 @@
},
{
"name": "startLine",
- "description": "Number of the first relevant line in the vulnerable file",
+ "description": "Number of the first relevant line in the vulnerable file.",
"args": [
],
@@ -78617,7 +83561,7 @@
},
{
"name": "vulnerableClass",
- "description": "Class containing the vulnerability",
+ "description": "Class containing the vulnerability.",
"args": [
],
@@ -78631,7 +83575,7 @@
},
{
"name": "vulnerableMethod",
- "description": "Method containing the vulnerability",
+ "description": "Method containing the vulnerability.",
"args": [
],
@@ -78658,7 +83602,7 @@
"fields": [
{
"name": "hostname",
- "description": "Domain name of the vulnerable request",
+ "description": "Domain name of the vulnerable request.",
"args": [
],
@@ -78672,7 +83616,7 @@
},
{
"name": "param",
- "description": "Query parameter for the URL on which the vulnerability occurred",
+ "description": "Query parameter for the URL on which the vulnerability occurred.",
"args": [
],
@@ -78686,7 +83630,7 @@
},
{
"name": "path",
- "description": "URL path and query string of the vulnerable request",
+ "description": "URL path and query string of the vulnerable request.",
"args": [
],
@@ -78700,7 +83644,7 @@
},
{
"name": "requestMethod",
- "description": "HTTP method of the vulnerable request",
+ "description": "HTTP method of the vulnerable request.",
"args": [
],
@@ -78726,8 +83670,22 @@
"description": "Represents the location of a vulnerability found by a dependency security scan",
"fields": [
{
+ "name": "blobPath",
+ "description": "Blob path to the vulnerable file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dependency",
- "description": "Dependency containing the vulnerability",
+ "description": "Dependency containing the vulnerability.",
"args": [
],
@@ -78741,7 +83699,7 @@
},
{
"name": "file",
- "description": "Path to the vulnerable file",
+ "description": "Path to the vulnerable file.",
"args": [
],
@@ -78767,8 +83725,22 @@
"description": "Represents the location of a vulnerability found by a SAST scan",
"fields": [
{
+ "name": "blobPath",
+ "description": "Blob path to the vulnerable file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "endLine",
- "description": "Number of the last relevant line in the vulnerable file",
+ "description": "Number of the last relevant line in the vulnerable file.",
"args": [
],
@@ -78782,7 +83754,7 @@
},
{
"name": "file",
- "description": "Path to the vulnerable file",
+ "description": "Path to the vulnerable file.",
"args": [
],
@@ -78796,7 +83768,7 @@
},
{
"name": "startLine",
- "description": "Number of the first relevant line in the vulnerable file",
+ "description": "Number of the first relevant line in the vulnerable file.",
"args": [
],
@@ -78810,7 +83782,7 @@
},
{
"name": "vulnerableClass",
- "description": "Class containing the vulnerability",
+ "description": "Class containing the vulnerability.",
"args": [
],
@@ -78824,7 +83796,7 @@
},
{
"name": "vulnerableMethod",
- "description": "Method containing the vulnerability",
+ "description": "Method containing the vulnerability.",
"args": [
],
@@ -78850,8 +83822,22 @@
"description": "Represents the location of a vulnerability found by a secret detection scan",
"fields": [
{
+ "name": "blobPath",
+ "description": "Blob path to the vulnerable file.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "endLine",
- "description": "Number of the last relevant line in the vulnerable file",
+ "description": "Number of the last relevant line in the vulnerable file.",
"args": [
],
@@ -78865,7 +83851,7 @@
},
{
"name": "file",
- "description": "Path to the vulnerable file",
+ "description": "Path to the vulnerable file.",
"args": [
],
@@ -78879,7 +83865,7 @@
},
{
"name": "startLine",
- "description": "Number of the first relevant line in the vulnerable file",
+ "description": "Number of the first relevant line in the vulnerable file.",
"args": [
],
@@ -78893,7 +83879,7 @@
},
{
"name": "vulnerableClass",
- "description": "Class containing the vulnerability",
+ "description": "Class containing the vulnerability.",
"args": [
],
@@ -78907,7 +83893,7 @@
},
{
"name": "vulnerableMethod",
- "description": "Method containing the vulnerability",
+ "description": "Method containing the vulnerability.",
"args": [
],
@@ -79366,7 +84352,7 @@
"fields": [
{
"name": "externalId",
- "description": "External ID of the vulnerability scanner",
+ "description": "External ID of the vulnerability scanner.",
"args": [
],
@@ -79380,7 +84366,7 @@
},
{
"name": "name",
- "description": "Name of the vulnerability scanner",
+ "description": "Name of the vulnerability scanner.",
"args": [
],
@@ -79394,7 +84380,7 @@
},
{
"name": "reportType",
- "description": "Type of the vulnerability report",
+ "description": "Type of the vulnerability report.",
"args": [
],
@@ -79408,7 +84394,7 @@
},
{
"name": "vendor",
- "description": "Vendor of the vulnerability scanner",
+ "description": "Vendor of the vulnerability scanner.",
"args": [
],
@@ -79797,7 +84783,7 @@
"fields": [
{
"name": "package",
- "description": "The package associated with the vulnerable dependency",
+ "description": "The package associated with the vulnerable dependency.",
"args": [
],
@@ -79811,7 +84797,7 @@
},
{
"name": "version",
- "description": "The version of the vulnerable dependency",
+ "description": "The version of the vulnerable dependency.",
"args": [
],
@@ -79838,7 +84824,7 @@
"fields": [
{
"name": "name",
- "description": "The name of the vulnerable package",
+ "description": "The name of the vulnerable package.",
"args": [
],
@@ -79865,7 +84851,7 @@
"fields": [
{
"name": "count",
- "description": "Number of projects within this grade",
+ "description": "Number of projects within this grade.",
"args": [
],
@@ -79883,7 +84869,7 @@
},
{
"name": "grade",
- "description": "Grade based on the highest severity vulnerability present",
+ "description": "Grade based on the highest severity vulnerability present.",
"args": [
],
@@ -79901,7 +84887,7 @@
},
{
"name": "projects",
- "description": "Projects within this grade",
+ "description": "Projects within this grade.",
"args": [
{
"name": "after",
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index c098de16ef6..f49a12568ed 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -24,6 +24,8 @@ Fields that are deprecated are marked with **{warning-solid}**.
Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
in [Removed Items](../removed_items.md).
+<!-- vale gitlab.Spelling = NO -->
+
## Object types
Object types represent the resources that the GitLab GraphQL API can return.
@@ -41,8 +43,8 @@ Represents the access level of a relationship between a User and object that it
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `integerValue` | Int | Integer representation of access level |
-| `stringValue` | AccessLevelEnum | String representation of access level |
+| `integerValue` | Int | Integer representation of access level. |
+| `stringValue` | AccessLevelEnum | String representation of access level. |
### AddAwardEmojiPayload
@@ -80,30 +82,30 @@ Describes an alert from the project's Alert Management.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `assignees` | UserConnection | Assignees of the alert |
-| `createdAt` | Time | Timestamp the alert was created |
-| `description` | String | Description of the alert |
-| `details` | JSON | Alert details |
-| `detailsUrl` | String! | The URL of the alert detail page |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `endedAt` | Time | Timestamp the alert ended |
-| `environment` | Environment | Environment for the alert |
-| `eventCount` | Int | Number of events of this alert |
-| `hosts` | String! => Array | List of hosts the alert came from |
-| `iid` | ID! | Internal ID of the alert |
-| `issueIid` | ID | Internal ID of the GitLab issue attached to the alert |
-| `metricsDashboardUrl` | String | URL for metrics embed for the alert |
-| `monitoringTool` | String | Monitoring tool the alert came from |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `prometheusAlert` | PrometheusAlert | The alert condition for Prometheus |
-| `runbook` | String | Runbook for the alert as defined in alert details |
-| `service` | String | Service the alert came from |
-| `severity` | AlertManagementSeverity | Severity of the alert |
-| `startedAt` | Time | Timestamp the alert was raised |
-| `status` | AlertManagementStatus | Status of the alert |
-| `title` | String | Title of the alert |
-| `todos` | TodoConnection | Todos of the current user for the alert |
-| `updatedAt` | Time | Timestamp the alert was last updated |
+| `assignees` | UserConnection | Assignees of the alert. |
+| `createdAt` | Time | Timestamp the alert was created. |
+| `description` | String | Description of the alert. |
+| `details` | JSON | Alert details. |
+| `detailsUrl` | String! | The URL of the alert detail page. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `endedAt` | Time | Timestamp the alert ended. |
+| `environment` | Environment | Environment for the alert. |
+| `eventCount` | Int | Number of events of this alert. |
+| `hosts` | String! => Array | List of hosts the alert came from. |
+| `iid` | ID! | Internal ID of the alert. |
+| `issueIid` | ID | Internal ID of the GitLab issue attached to the alert. |
+| `metricsDashboardUrl` | String | URL for metrics embed for the alert. |
+| `monitoringTool` | String | Monitoring tool the alert came from. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `prometheusAlert` | PrometheusAlert | The alert condition for Prometheus. |
+| `runbook` | String | Runbook for the alert as defined in alert details. |
+| `service` | String | Service the alert came from. |
+| `severity` | AlertManagementSeverity | Severity of the alert. |
+| `startedAt` | Time | Timestamp the alert was raised. |
+| `status` | AlertManagementStatus | Status of the alert. |
+| `title` | String | Title of the alert. |
+| `todos` | TodoConnection | To-do items of the current user for the alert. |
+| `updatedAt` | Time | Timestamp the alert was last updated. |
### AlertManagementAlertStatusCountsType
@@ -112,9 +114,9 @@ Represents total number of alerts for the represented categories.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `acknowledged` | Int | Number of alerts with status ACKNOWLEDGED for the project |
-| `all` | Int | Total number of alerts for the project |
+| `all` | Int | Total number of alerts for the project. |
| `ignored` | Int | Number of alerts with status IGNORED for the project |
-| `open` | Int | Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project |
+| `open` | Int | Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project. |
| `resolved` | Int | Number of alerts with status RESOLVED for the project |
| `triggered` | Int | Number of alerts with status TRIGGERED for the project |
@@ -124,13 +126,23 @@ An endpoint and credentials used to accept alerts for a project.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `active` | Boolean | Whether the endpoint is currently accepting alerts |
-| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard |
-| `id` | ID! | ID of the integration |
-| `name` | String | Name of the integration |
-| `token` | String | Token used to authenticate alert notification requests |
-| `type` | AlertManagementIntegrationType! | Type of integration |
-| `url` | String | Endpoint which accepts alert notifications |
+| `active` | Boolean | Whether the endpoint is currently accepting alerts. |
+| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard. |
+| `id` | ID! | ID of the integration. |
+| `name` | String | Name of the integration. |
+| `token` | String | Token used to authenticate alert notification requests. |
+| `type` | AlertManagementIntegrationType! | Type of integration. |
+| `url` | String | Endpoint which accepts alert notifications. |
+
+### AlertManagementPayloadAlertField
+
+Parsed field from an alert used for custom mappings.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `label` | String | Human-readable label of the payload path. |
+| `path` | String! => Array | Path to value inside payload JSON. |
+| `type` | AlertManagementPayloadAlertFieldType | Type of the parsed value. |
### AlertManagementPrometheusIntegration
@@ -138,13 +150,13 @@ An endpoint and credentials used to accept Prometheus alerts for a project.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `active` | Boolean | Whether the endpoint is currently accepting alerts |
-| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard |
-| `id` | ID! | ID of the integration |
-| `name` | String | Name of the integration |
-| `token` | String | Token used to authenticate alert notification requests |
-| `type` | AlertManagementIntegrationType! | Type of integration |
-| `url` | String | Endpoint which accepts alert notifications |
+| `active` | Boolean | Whether the endpoint is currently accepting alerts. |
+| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard. |
+| `id` | ID! | ID of the integration. |
+| `name` | String | Name of the integration. |
+| `token` | String | Token used to authenticate alert notification requests. |
+| `type` | AlertManagementIntegrationType! | Type of integration. |
+| `url` | String | Endpoint which accepts alert notifications. |
### AlertSetAssigneesPayload
@@ -156,7 +168,7 @@ Autogenerated return type of AlertSetAssignees.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `issue` | Issue | The issue created after mutation. |
-| `todo` | Todo | The todo after mutation. |
+| `todo` | Todo | The to-do item after mutation. |
### AlertTodoCreatePayload
@@ -168,7 +180,37 @@ Autogenerated return type of AlertTodoCreate.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `issue` | Issue | The issue created after mutation. |
-| `todo` | Todo | The todo after mutation. |
+| `todo` | Todo | The to-do item after mutation. |
+
+### ApiFuzzingCiConfiguration
+
+Data associated with configuring API fuzzing scans in GitLab CI.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `scanModes` | ApiFuzzingScanMode! => Array | All available scan modes. |
+| `scanProfiles` | ApiFuzzingScanProfile! => Array | All default scan profiles. |
+
+### ApiFuzzingCiConfigurationCreatePayload
+
+Autogenerated return type of ApiFuzzingCiConfigurationCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `configurationYaml` | String | A YAML snippet that can be inserted into the project's `.gitlab-ci.yml` to set up API fuzzing scans. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `gitlabCiYamlEditPath` | String | The location at which the project's `.gitlab-ci.yml` file can be edited in the browser. |
+
+### ApiFuzzingScanProfile
+
+An API Fuzzing scan profile..
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String | A short description of the profile. |
+| `name` | String | The unique name of the profile. |
+| `yaml` | String | A syntax highlit HTML representation of the YAML. |
### AwardEmoji
@@ -176,12 +218,12 @@ An emoji awarded by a user.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `description` | String! | The emoji description |
-| `emoji` | String! | The emoji as an icon |
-| `name` | String! | The emoji name |
-| `unicode` | String! | The emoji in unicode |
-| `unicodeVersion` | String! | The unicode version for this emoji |
-| `user` | User! | The user who awarded the emoji |
+| `description` | String! | The emoji description. |
+| `emoji` | String! | The emoji as an icon. |
+| `name` | String! | The emoji name. |
+| `unicode` | String! | The emoji in Unicode. |
+| `unicodeVersion` | String! | The Unicode version for this emoji. |
+| `user` | User! | The user who awarded the emoji. |
### AwardEmojiAddPayload
@@ -218,23 +260,23 @@ Autogenerated return type of AwardEmojiToggle.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `active` | Boolean | Indicates if the service is active |
-| `type` | String | Class name of the service |
+| `active` | Boolean | Indicates if the service is active. |
+| `type` | String | Class name of the service. |
### Blob
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `flatPath` | String! | Flat path of the entry |
-| `id` | ID! | ID of the entry |
-| `lfsOid` | String | LFS ID of the blob |
-| `mode` | String | Blob mode in numeric format |
-| `name` | String! | Name of the entry |
-| `path` | String! | Path of the entry |
-| `sha` | String! | Last commit sha for the entry |
-| `type` | EntryType! | Type of tree entry |
-| `webPath` | String | Web path of the blob |
-| `webUrl` | String | Web URL of the blob |
+| `flatPath` | String! | Flat path of the entry. |
+| `id` | ID! | ID of the entry. |
+| `lfsOid` | String | LFS ID of the blob. |
+| `mode` | String | Blob mode in numeric format. |
+| `name` | String! | Name of the entry. |
+| `path` | String! | Path of the entry. |
+| `sha` | String! | Last commit SHA for the entry. |
+| `type` | EntryType! | Type of tree entry. |
+| `webPath` | String | Web path of the blob. |
+| `webUrl` | String | Web URL of the blob. |
### Board
@@ -242,19 +284,19 @@ Represents a project or group board.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `assignee` | User | The board assignee |
-| `epics` | BoardEpicConnection | Epics associated with board issues |
-| `hideBacklogList` | Boolean | Whether or not backlog list is hidden |
-| `hideClosedList` | Boolean | Whether or not closed list is hidden |
-| `id` | ID! | ID (global ID) of the board |
+| `assignee` | User | The board assignee. |
+| `epics` | BoardEpicConnection | Epics associated with board issues. |
+| `hideBacklogList` | Boolean | Whether or not backlog list is hidden. |
+| `hideClosedList` | Boolean | Whether or not closed list is hidden. |
+| `id` | ID! | ID (global ID) of the board. |
| `iteration` | Iteration | The board iteration. |
-| `labels` | LabelConnection | Labels of the board |
-| `lists` | BoardListConnection | Lists of the board |
-| `milestone` | Milestone | The board milestone |
-| `name` | String | Name of the board |
+| `labels` | LabelConnection | Labels of the board. |
+| `lists` | BoardListConnection | Lists of the board. |
+| `milestone` | Milestone | The board milestone. |
+| `name` | String | Name of the board. |
| `webPath` | String! | Web path of the board. |
| `webUrl` | String! | Web URL of the board. |
-| `weight` | Int | Weight of the board |
+| `weight` | Int | Weight of the board. |
### BoardEpic
@@ -262,51 +304,53 @@ Represents an epic on an issue board.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User! | Author of the epic |
-| `children` | EpicConnection | Children (sub-epics) of the epic |
-| `closedAt` | Time | Timestamp of when the epic was closed |
-| `confidential` | Boolean | Indicates if the epic is confidential |
-| `createdAt` | Time | Timestamp of when the epic was created |
-| `currentUserTodos` | TodoConnection! | Todos for the current user |
-| `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues |
-| `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants |
-| `description` | String | Description of the epic |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `downvotes` | Int! | Number of downvotes the epic has received |
-| `dueDate` | Time | Due date of the epic |
-| `dueDateFixed` | Time | Fixed due date of the epic |
-| `dueDateFromMilestones` | Time | Inherited due date of the epic from milestones |
-| `dueDateIsFixed` | Boolean | Indicates if the due date has been manually set |
-| `group` | Group! | Group to which the epic belongs |
-| `hasChildren` | Boolean! | Indicates if the epic has children |
-| `hasIssues` | Boolean! | Indicates if the epic has direct issues |
-| `hasParent` | Boolean! | Indicates if the epic has a parent epic |
-| `healthStatus` | EpicHealthStatus | Current health status of the epic |
-| `id` | ID! | ID of the epic |
-| `iid` | ID! | Internal ID of the epic |
-| `issues` | EpicIssueConnection | A list of issues associated with the epic |
-| `labels` | LabelConnection | Labels assigned to the epic |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `parent` | Epic | Parent epic of the epic |
-| `participants` | UserConnection | List of participants for the epic |
-| `reference` | String! | Internal reference of the epic. Returned in shortened format by default |
-| `relationPath` | String | URI path of the epic-issue relationship |
-| `relativePosition` | Int | The relative position of the epic in the epic tree |
-| `startDate` | Time | Start date of the epic |
-| `startDateFixed` | Time | Fixed start date of the epic |
-| `startDateFromMilestones` | Time | Inherited start date of the epic from milestones |
-| `startDateIsFixed` | Boolean | Indicates if the start date has been manually set |
-| `state` | EpicState! | State of the epic |
-| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the epic |
-| `title` | String | Title of the epic |
-| `updatedAt` | Time | Timestamp of when the epic was updated |
-| `upvotes` | Int! | Number of upvotes the epic has received |
-| `userDiscussionsCount` | Int! | Number of user discussions in the epic |
-| `userNotesCount` | Int! | Number of user notes of the epic |
+| `author` | User! | Author of the epic. |
+| `awardEmoji` | AwardEmojiConnection | A list of award emojis associated with the epic. |
+| `children` | EpicConnection | Children (sub-epics) of the epic. |
+| `closedAt` | Time | Timestamp of when the epic was closed. |
+| `confidential` | Boolean | Indicates if the epic is confidential. |
+| `createdAt` | Time | Timestamp of when the epic was created. |
+| `currentUserTodos` | TodoConnection! | To-do items for the current user. |
+| `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues. |
+| `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants. |
+| `description` | String | Description of the epic. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `downvotes` | Int! | Number of downvotes the epic has received. |
+| `dueDate` | Time | Due date of the epic. |
+| `dueDateFixed` | Time | Fixed due date of the epic. |
+| `dueDateFromMilestones` | Time | Inherited due date of the epic from milestones. |
+| `dueDateIsFixed` | Boolean | Indicates if the due date has been manually set. |
+| `events` | EventConnection | A list of events associated with the object. |
+| `group` | Group! | Group to which the epic belongs. |
+| `hasChildren` | Boolean! | Indicates if the epic has children. |
+| `hasIssues` | Boolean! | Indicates if the epic has direct issues. |
+| `hasParent` | Boolean! | Indicates if the epic has a parent epic. |
+| `healthStatus` | EpicHealthStatus | Current health status of the epic. |
+| `id` | ID! | ID of the epic. |
+| `iid` | ID! | Internal ID of the epic. |
+| `issues` | EpicIssueConnection | A list of issues associated with the epic. |
+| `labels` | LabelConnection | Labels assigned to the epic. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `parent` | Epic | Parent epic of the epic. |
+| `participants` | UserConnection | List of participants for the epic. |
+| `reference` | String! | Internal reference of the epic. Returned in shortened format by default. |
+| `relationPath` | String | URI path of the epic-issue relationship. |
+| `relativePosition` | Int | The relative position of the epic in the epic tree. |
+| `startDate` | Time | Start date of the epic. |
+| `startDateFixed` | Time | Fixed start date of the epic. |
+| `startDateFromMilestones` | Time | Inherited start date of the epic from milestones. |
+| `startDateIsFixed` | Boolean | Indicates if the start date has been manually set. |
+| `state` | EpicState! | State of the epic. |
+| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the epic. |
+| `title` | String | Title of the epic. |
+| `updatedAt` | Time | Timestamp of when the epic was updated. |
+| `upvotes` | Int! | Number of upvotes the epic has received. |
+| `userDiscussionsCount` | Int! | Number of user discussions in the epic. |
+| `userNotesCount` | Int! | Number of user notes of the epic. |
| `userPermissions` | EpicPermissions! | Permissions for the current user on the resource |
-| `userPreferences` | BoardEpicUserPreferences | User preferences for the epic on the issue board |
-| `webPath` | String! | Web path of the epic |
-| `webUrl` | String! | Web URL of the epic |
+| `userPreferences` | BoardEpicUserPreferences | User preferences for the epic on the issue board. |
+| `webPath` | String! | Web path of the epic. |
+| `webUrl` | String! | Web URL of the epic. |
### BoardEpicUserPreferences
@@ -314,7 +358,7 @@ Represents user preferences for a board epic.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `collapsed` | Boolean! | Indicates epic should be displayed as collapsed |
+| `collapsed` | Boolean! | Indicates epic should be displayed as collapsed. |
### BoardList
@@ -322,21 +366,21 @@ Represents a list for an issue board.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `assignee` | User | Assignee in the list |
-| `collapsed` | Boolean | Indicates if list is collapsed for this user |
-| `id` | ID! | ID (global ID) of the list |
-| `issues` | IssueConnection | Board issues |
-| `issuesCount` | Int | Count of issues in the list |
-| `iteration` | Iteration | Iteration of the list |
-| `label` | Label | Label of the list |
-| `limitMetric` | ListLimitMetric | The current limit metric for the list |
-| `listType` | String! | Type of the list |
-| `maxIssueCount` | Int | Maximum number of issues in the list |
-| `maxIssueWeight` | Int | Maximum weight of issues in the list |
-| `milestone` | Milestone | Milestone of the list |
-| `position` | Int | Position of list within the board |
-| `title` | String! | Title of the list |
-| `totalWeight` | Int | Total weight of all issues in the list |
+| `assignee` | User | Assignee in the list. |
+| `collapsed` | Boolean | Indicates if list is collapsed for this user. |
+| `id` | ID! | ID (global ID) of the list. |
+| `issues` | IssueConnection | Board issues. |
+| `issuesCount` | Int | Count of issues in the list. |
+| `iteration` | Iteration | Iteration of the list. |
+| `label` | Label | Label of the list. |
+| `limitMetric` | ListLimitMetric | The current limit metric for the list. |
+| `listType` | String! | Type of the list. |
+| `maxIssueCount` | Int | Maximum number of issues in the list. |
+| `maxIssueWeight` | Int | Maximum weight of issues in the list. |
+| `milestone` | Milestone | Milestone of the list. |
+| `position` | Int | Position of list within the board. |
+| `title` | String! | Title of the list. |
+| `totalWeight` | Int | Total weight of all issues in the list. |
### BoardListCreatePayload
@@ -346,7 +390,7 @@ Autogenerated return type of BoardListCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `list` | BoardList | List of the issue board. |
+| `list` | BoardList | Issue list in the issue board. |
### BoardListUpdateLimitMetricsPayload
@@ -362,8 +406,8 @@ Autogenerated return type of BoardListUpdateLimitMetrics.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `commit` | Commit | Commit for the branch |
-| `name` | String! | Name of the branch |
+| `commit` | Commit | Commit for the branch. |
+| `name` | String! | Name of the branch. |
### BurnupChartDailyTotals
@@ -371,11 +415,17 @@ Represents the total number of issues and their weights for a particular day.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `completedCount` | Int! | Number of closed issues as of this day |
-| `completedWeight` | Int! | Total weight of closed issues as of this day |
-| `date` | ISO8601Date! | Date for burnup totals |
-| `scopeCount` | Int! | Number of issues as of this day |
-| `scopeWeight` | Int! | Total weight of issues as of this day |
+| `completedCount` | Int! | Number of closed issues as of this day. |
+| `completedWeight` | Int! | Total weight of closed issues as of this day. |
+| `date` | ISO8601Date! | Date for burnup totals. |
+| `scopeCount` | Int! | Number of issues as of this day. |
+| `scopeWeight` | Int! | Total weight of issues as of this day. |
+
+### CiApplicationSettings
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `keepLatestArtifact` | Boolean | Whether to keep the latest jobs artifacts. |
### CiBuildNeed
@@ -396,18 +446,18 @@ Autogenerated return type of CiCdSettingsUpdate.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `errors` | String! => Array | Linting errors |
-| `mergedYaml` | String | Merged CI config YAML |
-| `stages` | CiConfigStageConnection | Stages of the pipeline |
-| `status` | CiConfigStatus | Status of linting, can be either valid or invalid |
+| `errors` | String! => Array | Linting errors. |
+| `mergedYaml` | String | Merged CI configuration YAML. |
+| `stages` | CiConfigStageConnection | Stages of the pipeline. |
+| `status` | CiConfigStatus | Status of linting, can be either valid or invalid. |
### CiConfigGroup
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `jobs` | CiConfigJobConnection | Jobs in group |
-| `name` | String | Name of the job group |
-| `size` | Int | Size of the job group |
+| `jobs` | CiConfigJobConnection | Jobs in group. |
+| `name` | String | Name of the job group. |
+| `size` | Int | Size of the job group. |
### CiConfigJob
@@ -437,60 +487,61 @@ Autogenerated return type of CiCdSettingsUpdate.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `name` | String | Name of the need |
+| `name` | String | Name of the need. |
### CiConfigStage
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `groups` | CiConfigGroupConnection | Groups of jobs for the stage |
-| `name` | String | Name of the stage |
+| `groups` | CiConfigGroupConnection | Groups of jobs for the stage. |
+| `name` | String | Name of the stage. |
### CiGroup
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `detailedStatus` | DetailedStatus | Detailed status of the group |
-| `jobs` | CiJobConnection | Jobs in group |
-| `name` | String | Name of the job group |
-| `size` | Int | Size of the group |
+| `detailedStatus` | DetailedStatus | Detailed status of the group. |
+| `jobs` | CiJobConnection | Jobs in group. |
+| `name` | String | Name of the job group. |
+| `size` | Int | Size of the group. |
### CiJob
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `artifacts` | CiJobArtifactConnection | Artifacts generated by the job |
-| `detailedStatus` | DetailedStatus | Detailed status of the job |
-| `name` | String | Name of the job |
-| `needs` | CiBuildNeedConnection | References to builds that must complete before the jobs run |
-| `pipeline` | Pipeline | Pipeline the job belongs to |
-| `scheduledAt` | Time | Schedule for the build |
+| `artifacts` | CiJobArtifactConnection | Artifacts generated by the job. |
+| `detailedStatus` | DetailedStatus | Detailed status of the job. |
+| `name` | String | Name of the job. |
+| `needs` | CiBuildNeedConnection | References to builds that must complete before the jobs run. |
+| `pipeline` | Pipeline | Pipeline the job belongs to. |
+| `scheduledAt` | Time | Schedule for the build. |
### CiJobArtifact
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `downloadPath` | String | URL for downloading the artifact's file |
-| `fileType` | JobArtifactFileType | File type of the artifact |
+| `downloadPath` | String | URL for downloading the artifact's file. |
+| `fileType` | JobArtifactFileType | File type of the artifact. |
### CiStage
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `detailedStatus` | DetailedStatus | Detailed status of the stage |
-| `groups` | CiGroupConnection | Group of jobs for the stage |
-| `name` | String | Name of the stage |
+| `detailedStatus` | DetailedStatus | Detailed status of the stage. |
+| `groups` | CiGroupConnection | Group of jobs for the stage. |
+| `name` | String | Name of the stage. |
### ClusterAgent
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time | Timestamp the cluster agent was created |
-| `id` | ID! | ID of the cluster agent |
-| `name` | String | Name of the cluster agent |
-| `project` | Project | The project this cluster agent is associated with |
-| `tokens` | ClusterAgentTokenConnection | Tokens associated with the cluster agent |
-| `updatedAt` | Time | Timestamp the cluster agent was updated |
+| `createdAt` | Time | Timestamp the cluster agent was created. |
+| `createdByUser` | User | User object, containing information about the person who created the agent. |
+| `id` | ID! | ID of the cluster agent. |
+| `name` | String | Name of the cluster agent. |
+| `project` | Project | The project this cluster agent is associated with. |
+| `tokens` | ClusterAgentTokenConnection | Tokens associated with the cluster agent. |
+| `updatedAt` | Time | Timestamp the cluster agent was updated. |
### ClusterAgentDeletePayload
@@ -505,9 +556,10 @@ Autogenerated return type of ClusterAgentDelete.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `clusterAgent` | ClusterAgent | Cluster agent this token is associated with |
-| `createdAt` | Time | Timestamp the token was created |
-| `id` | ClustersAgentTokenID! | Global ID of the token |
+| `clusterAgent` | ClusterAgent | Cluster agent this token is associated with. |
+| `createdAt` | Time | Timestamp the token was created. |
+| `createdByUser` | User | The user who created the token. |
+| `id` | ClustersAgentTokenID! | Global ID of the token. |
### ClusterAgentTokenCreatePayload
@@ -554,22 +606,22 @@ Represents the code coverage summary for a project.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User | Author of the commit |
-| `authorGravatar` | String | Commit authors gravatar |
-| `authorName` | String | Commit authors name |
-| `authoredDate` | Time | Timestamp of when the commit was authored |
-| `description` | String | Description of the commit message |
+| `author` | User | Author of the commit. |
+| `authorGravatar` | String | Commit authors gravatar. |
+| `authorName` | String | Commit authors name. |
+| `authoredDate` | Time | Timestamp of when the commit was authored. |
+| `description` | String | Description of the commit message. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `id` | ID! | ID (global ID) of the commit |
-| `message` | String | Raw commit message |
-| `pipelines` | PipelineConnection | Pipelines of the commit ordered latest first |
-| `sha` | String! | SHA1 ID of the commit |
-| `shortId` | String! | Short SHA1 ID of the commit |
-| `signatureHtml` | String | Rendered HTML of the commit signature |
-| `title` | String | Title of the commit message |
+| `id` | ID! | ID (global ID) of the commit. |
+| `message` | String | Raw commit message. |
+| `pipelines` | PipelineConnection | Pipelines of the commit ordered latest first. |
+| `sha` | String! | SHA1 ID of the commit. |
+| `shortId` | String! | Short SHA1 ID of the commit. |
+| `signatureHtml` | String | Rendered HTML of the commit signature. |
+| `title` | String | Title of the commit message. |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
-| `webPath` | String! | Web path of the commit |
-| `webUrl` | String! | Web URL of the commit |
+| `webPath` | String! | Web path of the commit. |
+| `webUrl` | String! | Web URL of the commit. |
### CommitCreatePayload
@@ -587,10 +639,20 @@ Represents a ComplianceFramework associated with a Project.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `color` | String! | Hexadecimal representation of compliance framework's label color |
-| `description` | String! | Description of the compliance framework |
-| `id` | ID! | Compliance framework ID |
-| `name` | String! | Name of the compliance framework |
+| `color` | String! | Hexadecimal representation of compliance framework's label color. |
+| `description` | String! | Description of the compliance framework. |
+| `id` | ID! | Compliance framework ID. |
+| `name` | String! | Name of the compliance framework. |
+| `pipelineConfigurationFullPath` | String | Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hippa`. |
+
+### ComposerMetadata
+
+Composer metadata.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `composerJson` | PackageComposerJsonType! | Data of the Composer JSON file. |
+| `targetSha` | String! | Target SHA of the package. |
### ConfigureSastPayload
@@ -609,15 +671,15 @@ A tag expiration policy designed to keep only the images that matter most.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `cadence` | ContainerExpirationPolicyCadenceEnum! | This container expiration policy schedule |
-| `createdAt` | Time! | Timestamp of when the container expiration policy was created |
-| `enabled` | Boolean! | Indicates whether this container expiration policy is enabled |
-| `keepN` | ContainerExpirationPolicyKeepEnum | Number of tags to retain |
-| `nameRegex` | UntrustedRegexp | Tags with names matching this regex pattern will expire |
-| `nameRegexKeep` | UntrustedRegexp | Tags with names matching this regex pattern will be preserved |
-| `nextRunAt` | Time | Next time that this container expiration policy will get executed |
-| `olderThan` | ContainerExpirationPolicyOlderThanEnum | Tags older that this will expire |
-| `updatedAt` | Time! | Timestamp of when the container expiration policy was updated |
+| `cadence` | ContainerExpirationPolicyCadenceEnum! | This container expiration policy schedule. |
+| `createdAt` | Time! | Timestamp of when the container expiration policy was created. |
+| `enabled` | Boolean! | Indicates whether this container expiration policy is enabled. |
+| `keepN` | ContainerExpirationPolicyKeepEnum | Number of tags to retain. |
+| `nameRegex` | UntrustedRegexp | Tags with names matching this regex pattern will expire. |
+| `nameRegexKeep` | UntrustedRegexp | Tags with names matching this regex pattern will be preserved. |
+| `nextRunAt` | Time | Next time that this container expiration policy will get executed. |
+| `olderThan` | ContainerExpirationPolicyOlderThanEnum | Tags older that this will expire. |
+| `updatedAt` | Time! | Timestamp of when the container expiration policy was updated. |
### ContainerRepository
@@ -633,7 +695,7 @@ A container repository.
| `location` | String! | URL of the container repository. |
| `name` | String! | Name of the container repository. |
| `path` | String! | Path of the container repository. |
-| `project` | Project! | Project of the container registry |
+| `project` | Project! | Project of the container registry. |
| `status` | ContainerRepositoryStatus | Status of the container repository. |
| `tagsCount` | Int! | Number of tags associated with this image. |
| `updatedAt` | Time! | Timestamp when the container repository was updated. |
@@ -652,9 +714,9 @@ Details of a container repository.
| `location` | String! | URL of the container repository. |
| `name` | String! | Name of the container repository. |
| `path` | String! | Path of the container repository. |
-| `project` | Project! | Project of the container registry |
+| `project` | Project! | Project of the container registry. |
| `status` | ContainerRepositoryStatus | Status of the container repository. |
-| `tags` | ContainerRepositoryTagConnection | Tags of the container repository |
+| `tags` | ContainerRepositoryTagConnection | Tags of the container repository. |
| `tagsCount` | Int! | Number of tags associated with this image. |
| `updatedAt` | Time! | Timestamp when the container repository was updated. |
@@ -684,7 +746,7 @@ Autogenerated return type of CreateAlertIssue.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `issue` | Issue | The issue created after mutation. |
-| `todo` | Todo | The todo after mutation. |
+| `todo` | Todo | The to-do item after mutation. |
### CreateAnnotationPayload
@@ -832,10 +894,13 @@ Autogenerated return type of CreateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `captchaSiteKey` | String | The 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. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `needsCaptchaResponse` | Boolean | 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. |
| `snippet` | Snippet | The snippet after mutation. |
-| `spam` | Boolean | Indicates whether the operation returns a record detected as spam. |
+| `spam` | Boolean | Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response. |
+| `spamLogId` | Int | The 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. |
### CreateTestCasePayload
@@ -853,10 +918,10 @@ A custom emoji uploaded by user.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `external` | Boolean! | Whether the emoji is an external link |
-| `id` | CustomEmojiID! | The ID of the emoji |
-| `name` | String! | The name of the emoji |
-| `url` | String! | The link to file of the emoji |
+| `external` | Boolean! | Whether the emoji is an external link. |
+| `id` | CustomEmojiID! | The ID of the emoji. |
+| `name` | String! | The name of the emoji. |
+| `url` | String! | The link to file of the emoji. |
### DastOnDemandScanCreatePayload
@@ -868,20 +933,74 @@ Autogenerated return type of DastOnDemandScanCreate.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `pipelineUrl` | String | URL of the pipeline that was created. |
+### DastProfile
+
+Represents a DAST Profile.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `dastScannerProfile` | DastScannerProfile | The associated scanner profile. |
+| `dastSiteProfile` | DastSiteProfile | The associated site profile. |
+| `description` | String | The description of the scan. |
+| `editPath` | String | Relative web path to the edit page of a profile. |
+| `id` | DastProfileID! | ID of the profile. |
+| `name` | String | The name of the profile. |
+
+### DastProfileCreatePayload
+
+Autogenerated return type of DastProfileCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `dastProfile` | DastProfile | The created profile. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `pipelineUrl` | String | The URL of the pipeline that was created. Requires `runAfterCreate` to be set to `true`. |
+
+### DastProfileDeletePayload
+
+Autogenerated return type of DastProfileDelete.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### DastProfileRunPayload
+
+Autogenerated return type of DastProfileRun.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `pipelineUrl` | String | URL of the pipeline that was created. |
+
+### DastProfileUpdatePayload
+
+Autogenerated return type of DastProfileUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `dastProfile` | DastProfile | The updated profile. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `pipelineUrl` | String | The URL of the pipeline that was created. Requires the input argument `runAfterUpdate` to be set to `true` when calling the mutation, otherwise no pipeline will be created. |
+
### DastScannerProfile
Represents a DAST scanner profile.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `editPath` | String | Relative web path to the edit page of a scanner profile |
+| `editPath` | String | Relative web path to the edit page of a scanner profile. |
| `globalId` **{warning-solid}** | DastScannerProfileID! | **Deprecated:** Use `id`. Deprecated in 13.6. |
-| `id` | DastScannerProfileID! | ID of the DAST scanner profile |
-| `profileName` | String | Name of the DAST scanner profile |
+| `id` | DastScannerProfileID! | ID of the DAST scanner profile. |
+| `profileName` | String | Name of the DAST scanner profile. |
| `scanType` | DastScanTypeEnum | Indicates the type of DAST scan that will run. Either a Passive Scan or an Active Scan. |
| `showDebugMessages` | Boolean! | Indicates if debug messages should be included in DAST console output. True to include the debug messages. |
-| `spiderTimeout` | Int | The maximum number of minutes allowed for the spider to traverse the site |
-| `targetTimeout` | Int | The maximum number of seconds allowed for the site under test to respond to a request |
+| `spiderTimeout` | Int | The maximum number of minutes allowed for the spider to traverse the site. |
+| `targetTimeout` | Int | The maximum number of seconds allowed for the site under test to respond to a request. |
| `useAjaxSpider` | Boolean! | Indicates if the AJAX spider should be used to crawl the target site. True to run the AJAX spider in addition to the traditional spider, and false to run only the traditional spider. |
### DastScannerProfileCreatePayload
@@ -920,13 +1039,13 @@ Represents a DAST Site Profile.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `editPath` | String | Relative web path to the edit page of a site profile |
-| `id` | DastSiteProfileID! | ID of the site profile |
-| `normalizedTargetUrl` | String | Normalized URL of the target to be scanned |
-| `profileName` | String | The name of the site profile |
-| `targetUrl` | String | The URL of the target to be scanned |
+| `editPath` | String | Relative web path to the edit page of a site profile. |
+| `id` | DastSiteProfileID! | ID of the site profile. |
+| `normalizedTargetUrl` | String | Normalized URL of the target to be scanned. |
+| `profileName` | String | The name of the site profile. |
+| `targetUrl` | String | The URL of the target to be scanned. |
| `userPermissions` | DastSiteProfilePermissions! | Permissions for the current user on the resource |
-| `validationStatus` | DastSiteProfileValidationStatusEnum | The current validation status of the site profile |
+| `validationStatus` | DastSiteProfileValidationStatusEnum | The current validation status of the site profile. |
### DastSiteProfileCreatePayload
@@ -983,9 +1102,9 @@ Represents a DAST Site Validation.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `id` | DastSiteValidationID! | Global ID of the site validation |
-| `normalizedTargetUrl` | String | Normalized URL of the target to be validated |
-| `status` | DastSiteProfileValidationStatusEnum! | Status of the site validation |
+| `id` | DastSiteValidationID! | Global ID of the site validation. |
+| `normalizedTargetUrl` | String | Normalized URL of the target to be validated. |
+| `status` | DastSiteProfileValidationStatusEnum! | Status of the site validation. |
### DastSiteValidationCreatePayload
@@ -998,6 +1117,15 @@ Autogenerated return type of DastSiteValidationCreate.
| `id` | DastSiteValidationID | ID of the site validation. |
| `status` | DastSiteProfileValidationStatusEnum | The current validation status. |
+### DastSiteValidationRevokePayload
+
+Autogenerated return type of DastSiteValidationRevoke.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
### DeleteAnnotationPayload
Autogenerated return type of DeleteAnnotation.
@@ -1022,9 +1150,9 @@ The response from the AdminSidekiqQueuesDeleteJobs mutation.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `completed` | Boolean | Whether or not the entire queue was processed in time; if not, retrying the same request is safe |
-| `deletedJobs` | Int | The number of matching jobs deleted |
-| `queueSize` | Int | The queue size after processing |
+| `completed` | Boolean | Whether or not the entire queue was processed in time; if not, retrying the same request is safe. |
+| `deletedJobs` | Int | The number of matching jobs deleted. |
+| `queueSize` | Int | The queue size after processing. |
### Design
@@ -1032,20 +1160,20 @@ A single design.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `currentUserTodos` | TodoConnection! | Todos for the current user |
-| `diffRefs` | DiffRefs! | The diff refs for this design |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `event` | DesignVersionEvent! | How this design was changed in the current version |
-| `filename` | String! | The filename of the design |
-| `fullPath` | String! | The full path to the design file |
-| `id` | ID! | The ID of this design |
-| `image` | String! | The URL of the full-sized image |
+| `currentUserTodos` | TodoConnection! | To-do items for the current user. |
+| `diffRefs` | DiffRefs! | The diff refs for this design. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `event` | DesignVersionEvent! | How this design was changed in the current version. |
+| `filename` | String! | The filename of the design. |
+| `fullPath` | String! | The full path to the design file. |
+| `id` | ID! | The ID of this design. |
+| `image` | String! | The URL of the full-sized image. |
| `imageV432x230` | String | The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated |
-| `issue` | Issue! | The issue the design belongs to |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `notesCount` | Int! | The total count of user-created notes for this design |
-| `project` | Project! | The project the design belongs to |
-| `versions` | DesignVersionConnection! | All versions related to this design ordered newest first |
+| `issue` | Issue! | The issue the design belongs to. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `notesCount` | Int! | The total count of user-created notes for this design. |
+| `project` | Project! | The project the design belongs to. |
+| `versions` | DesignVersionConnection! | All versions related to this design ordered newest first. |
### DesignAtVersion
@@ -1053,18 +1181,18 @@ A design pinned to a specific version. The image field reflects the design as of
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `design` | Design! | The underlying design |
-| `diffRefs` | DiffRefs! | The diff refs for this design |
-| `event` | DesignVersionEvent! | How this design was changed in the current version |
-| `filename` | String! | The filename of the design |
-| `fullPath` | String! | The full path to the design file |
-| `id` | ID! | The ID of this design |
-| `image` | String! | The URL of the full-sized image |
+| `design` | Design! | The underlying design. |
+| `diffRefs` | DiffRefs! | The diff refs for this design. |
+| `event` | DesignVersionEvent! | How this design was changed in the current version. |
+| `filename` | String! | The filename of the design. |
+| `fullPath` | String! | The full path to the design file. |
+| `id` | ID! | The ID of this design. |
+| `image` | String! | The URL of the full-sized image. |
| `imageV432x230` | String | The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated |
-| `issue` | Issue! | The issue the design belongs to |
-| `notesCount` | Int! | The total count of user-created notes for this design |
-| `project` | Project! | The project the design belongs to |
-| `version` | DesignVersion! | The version this design-at-versions is pinned to |
+| `issue` | Issue! | The issue the design belongs to. |
+| `notesCount` | Int! | The total count of user-created notes for this design. |
+| `project` | Project! | The project the design belongs to. |
+| `version` | DesignVersion! | The version this design-at-versions is pinned to. |
### DesignCollection
@@ -1072,21 +1200,21 @@ A collection of designs.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `copyState` | DesignCollectionCopyState | Copy state of the design collection |
-| `design` | Design | Find a specific design |
-| `designAtVersion` | DesignAtVersion | Find a design as of a version |
-| `designs` | DesignConnection! | All designs for the design collection |
-| `issue` | Issue! | Issue associated with the design collection |
-| `project` | Project! | Project associated with the design collection |
-| `version` | DesignVersion | A specific version |
-| `versions` | DesignVersionConnection! | All versions related to all designs, ordered newest first |
+| `copyState` | DesignCollectionCopyState | Copy state of the design collection. |
+| `design` | Design | Find a specific design. |
+| `designAtVersion` | DesignAtVersion | Find a design as of a version. |
+| `designs` | DesignConnection! | All designs for the design collection. |
+| `issue` | Issue! | Issue associated with the design collection. |
+| `project` | Project! | Project associated with the design collection. |
+| `version` | DesignVersion | A specific version. |
+| `versions` | DesignVersionConnection! | All versions related to all designs, ordered newest first. |
### DesignManagement
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `designAtVersion` | DesignAtVersion | Find a design as of a version |
-| `version` | DesignVersion | Find a version |
+| `designAtVersion` | DesignAtVersion | Find a design as of a version. |
+| `version` | DesignVersion | Find a version. |
### DesignManagementDeletePayload
@@ -1125,11 +1253,11 @@ A specific version in which designs were added, modified or deleted.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `designAtVersion` | DesignAtVersion! | A particular design as of this version, provided it is visible at this version |
-| `designs` | DesignConnection! | All designs that were changed in the version |
-| `designsAtVersion` | DesignAtVersionConnection! | All designs that are visible at this version, as of this version |
-| `id` | ID! | ID of the design version |
-| `sha` | ID! | SHA of the design version |
+| `designAtVersion` | DesignAtVersion! | A particular design as of this version, provided it is visible at this version. |
+| `designs` | DesignConnection! | All designs that were changed in the version. |
+| `designsAtVersion` | DesignAtVersionConnection! | All designs that are visible at this version, as of this version. |
+| `id` | ID! | ID of the design version. |
+| `sha` | ID! | SHA of the design version. |
### DestroyBoardListPayload
@@ -1204,15 +1332,15 @@ Autogenerated return type of DestroySnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `action` | StatusAction | Action information for the status. This includes method, button title, icon, path, and title |
-| `detailsPath` | String | Path of the details for the status |
-| `favicon` | String | Favicon of the status |
-| `group` | String | Group of the status |
-| `hasDetails` | Boolean | Indicates if the status has further details |
-| `icon` | String | Icon of the status |
-| `label` | String | Label of the status |
-| `text` | String | Text of the status |
-| `tooltip` | String | Tooltip associated with the status |
+| `action` | StatusAction | Action information for the status. This includes method, button title, icon, path, and title. |
+| `detailsPath` | String | Path of the details for the status. |
+| `favicon` | String | Favicon of the status. |
+| `group` | String | Group of the status. |
+| `hasDetails` | Boolean | Indicates if the status has further details. |
+| `icon` | String | Icon of the status. |
+| `label` | String | Label of the status. |
+| `text` | String | Text of the status. |
+| `tooltip` | String | Tooltip associated with the status. |
### DevopsAdoptionSegment
@@ -1220,10 +1348,9 @@ Segment.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `groups` | Group! => Array | Assigned groups |
-| `id` | ID! | ID of the segment |
-| `latestSnapshot` | DevopsAdoptionSnapshot | The latest adoption metrics for the segment |
-| `name` | String! | Name of the segment |
+| `id` | ID! | ID of the segment. |
+| `latestSnapshot` | DevopsAdoptionSnapshot | The latest adoption metrics for the segment. |
+| `namespace` | Namespace | Segment namespace. |
### DevopsAdoptionSnapshot
@@ -1231,40 +1358,40 @@ Snapshot.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `deploySucceeded` | Boolean! | At least one deployment succeeded |
-| `endTime` | Time! | The end time for the snapshot where the data points were collected |
-| `issueOpened` | Boolean! | At least one issue was opened |
-| `mergeRequestApproved` | Boolean! | At least one merge request was approved |
-| `mergeRequestOpened` | Boolean! | At least one merge request was opened |
-| `pipelineSucceeded` | Boolean! | At least one pipeline succeeded |
-| `recordedAt` | Time! | The time the snapshot was recorded |
-| `runnerConfigured` | Boolean! | At least one runner was used |
-| `securityScanSucceeded` | Boolean! | At least one security scan succeeded |
-| `startTime` | Time! | The start time for the snapshot where the data points were collected |
+| `deploySucceeded` | Boolean! | At least one deployment succeeded. |
+| `endTime` | Time! | The end time for the snapshot where the data points were collected. |
+| `issueOpened` | Boolean! | At least one issue was opened. |
+| `mergeRequestApproved` | Boolean! | At least one merge request was approved. |
+| `mergeRequestOpened` | Boolean! | At least one merge request was opened. |
+| `pipelineSucceeded` | Boolean! | At least one pipeline succeeded. |
+| `recordedAt` | Time! | The time the snapshot was recorded. |
+| `runnerConfigured` | Boolean! | At least one runner was used. |
+| `securityScanSucceeded` | Boolean! | At least one security scan succeeded. |
+| `startTime` | Time! | The start time for the snapshot where the data points were collected. |
### DiffPosition
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `diffRefs` | DiffRefs! | Information about the branch, HEAD, and base at the time of commenting |
-| `filePath` | String! | Path of the file that was changed |
-| `height` | Int | Total height of the image |
-| `newLine` | Int | Line on HEAD SHA that was changed |
-| `newPath` | String | Path of the file on the HEAD SHA |
-| `oldLine` | Int | Line on start SHA that was changed |
-| `oldPath` | String | Path of the file on the start SHA |
-| `positionType` | DiffPositionType! | Type of file the position refers to |
-| `width` | Int | Total width of the image |
-| `x` | Int | X position of the note |
-| `y` | Int | Y position of the note |
+| `diffRefs` | DiffRefs! | Information about the branch, HEAD, and base at the time of commenting. |
+| `filePath` | String! | Path of the file that was changed. |
+| `height` | Int | Total height of the image. |
+| `newLine` | Int | Line on HEAD SHA that was changed. |
+| `newPath` | String | Path of the file on the HEAD SHA. |
+| `oldLine` | Int | Line on start SHA that was changed. |
+| `oldPath` | String | Path of the file on the start SHA. |
+| `positionType` | DiffPositionType! | Type of file the position refers to. |
+| `width` | Int | Total width of the image. |
+| `x` | Int | X position of the note. |
+| `y` | Int | Y position of the note. |
### DiffRefs
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `baseSha` | String | Merge base of the branch the comment was made on |
-| `headSha` | String! | SHA of the HEAD at the time the comment was made |
-| `startSha` | String! | SHA of the branch being compared against |
+| `baseSha` | String | Merge base of the branch the comment was made on. |
+| `headSha` | String! | SHA of the HEAD at the time the comment was made. |
+| `startSha` | String! | SHA of the branch being compared against. |
### DiffStats
@@ -1272,9 +1399,9 @@ Changes to a single file.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `additions` | Int! | Number of lines added to this file |
-| `deletions` | Int! | Number of lines deleted from this file |
-| `path` | String! | File path, relative to repository root |
+| `additions` | Int! | Number of lines added to this file. |
+| `deletions` | Int! | Number of lines deleted from this file. |
+| `path` | String! | File path, relative to repository root. |
### DiffStatsSummary
@@ -1282,23 +1409,23 @@ Aggregated summary of changes.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `additions` | Int! | Number of lines added |
-| `changes` | Int! | Number of lines changed |
-| `deletions` | Int! | Number of lines deleted |
-| `fileCount` | Int! | Number of files changed |
+| `additions` | Int! | Number of lines added. |
+| `changes` | Int! | Number of lines changed. |
+| `deletions` | Int! | Number of lines deleted. |
+| `fileCount` | Int! | Number of files changed. |
### Discussion
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | Timestamp of the discussion's creation |
-| `id` | ID! | ID of this discussion |
-| `notes` | NoteConnection! | All notes in the discussion |
-| `replyId` | ID! | ID used to reply to this discussion |
-| `resolvable` | Boolean! | Indicates if the object can be resolved |
-| `resolved` | Boolean! | Indicates if the object is resolved |
-| `resolvedAt` | Time | Timestamp of when the object was resolved |
-| `resolvedBy` | User | User who resolved the object |
+| `createdAt` | Time! | Timestamp of the discussion's creation. |
+| `id` | DiscussionID! | ID of this discussion. |
+| `notes` | NoteConnection! | All notes in the discussion. |
+| `replyId` | DiscussionID! | ID used to reply to this discussion. |
+| `resolvable` | Boolean! | Indicates if the object can be resolved. |
+| `resolved` | Boolean! | Indicates if the object is resolved. |
+| `resolvedAt` | Time | Timestamp of when the object was resolved. |
+| `resolvedBy` | User | User who resolved the object. |
### DiscussionToggleResolvePayload
@@ -1326,12 +1453,12 @@ Describes where code is deployed for a project.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `id` | ID! | ID of the environment |
-| `latestOpenedMostSevereAlert` | AlertManagementAlert | The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned |
-| `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment |
-| `name` | String! | Human-readable name of the environment |
+| `id` | ID! | ID of the environment. |
+| `latestOpenedMostSevereAlert` | AlertManagementAlert | The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. |
+| `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment. |
+| `name` | String! | Human-readable name of the environment. |
| `path` | String! | The path to the environment. |
-| `state` | String! | State of the environment, for example: available/stopped |
+| `state` | String! | State of the environment, for example: available/stopped. |
### EnvironmentsCanaryIngressUpdatePayload
@@ -1348,50 +1475,52 @@ Represents an epic.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User! | Author of the epic |
-| `children` | EpicConnection | Children (sub-epics) of the epic |
-| `closedAt` | Time | Timestamp of when the epic was closed |
-| `confidential` | Boolean | Indicates if the epic is confidential |
-| `createdAt` | Time | Timestamp of when the epic was created |
-| `currentUserTodos` | TodoConnection! | Todos for the current user |
-| `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues |
-| `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants |
-| `description` | String | Description of the epic |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `downvotes` | Int! | Number of downvotes the epic has received |
-| `dueDate` | Time | Due date of the epic |
-| `dueDateFixed` | Time | Fixed due date of the epic |
-| `dueDateFromMilestones` | Time | Inherited due date of the epic from milestones |
-| `dueDateIsFixed` | Boolean | Indicates if the due date has been manually set |
-| `group` | Group! | Group to which the epic belongs |
-| `hasChildren` | Boolean! | Indicates if the epic has children |
-| `hasIssues` | Boolean! | Indicates if the epic has direct issues |
-| `hasParent` | Boolean! | Indicates if the epic has a parent epic |
-| `healthStatus` | EpicHealthStatus | Current health status of the epic |
-| `id` | ID! | ID of the epic |
-| `iid` | ID! | Internal ID of the epic |
-| `issues` | EpicIssueConnection | A list of issues associated with the epic |
-| `labels` | LabelConnection | Labels assigned to the epic |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `parent` | Epic | Parent epic of the epic |
-| `participants` | UserConnection | List of participants for the epic |
-| `reference` | String! | Internal reference of the epic. Returned in shortened format by default |
-| `relationPath` | String | URI path of the epic-issue relationship |
-| `relativePosition` | Int | The relative position of the epic in the epic tree |
-| `startDate` | Time | Start date of the epic |
-| `startDateFixed` | Time | Fixed start date of the epic |
-| `startDateFromMilestones` | Time | Inherited start date of the epic from milestones |
-| `startDateIsFixed` | Boolean | Indicates if the start date has been manually set |
-| `state` | EpicState! | State of the epic |
-| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the epic |
-| `title` | String | Title of the epic |
-| `updatedAt` | Time | Timestamp of when the epic was updated |
-| `upvotes` | Int! | Number of upvotes the epic has received |
-| `userDiscussionsCount` | Int! | Number of user discussions in the epic |
-| `userNotesCount` | Int! | Number of user notes of the epic |
+| `author` | User! | Author of the epic. |
+| `awardEmoji` | AwardEmojiConnection | A list of award emojis associated with the epic. |
+| `children` | EpicConnection | Children (sub-epics) of the epic. |
+| `closedAt` | Time | Timestamp of when the epic was closed. |
+| `confidential` | Boolean | Indicates if the epic is confidential. |
+| `createdAt` | Time | Timestamp of when the epic was created. |
+| `currentUserTodos` | TodoConnection! | To-do items for the current user. |
+| `descendantCounts` | EpicDescendantCount | Number of open and closed descendant epics and issues. |
+| `descendantWeightSum` | EpicDescendantWeights | Total weight of open and closed issues in the epic and its descendants. |
+| `description` | String | Description of the epic. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `downvotes` | Int! | Number of downvotes the epic has received. |
+| `dueDate` | Time | Due date of the epic. |
+| `dueDateFixed` | Time | Fixed due date of the epic. |
+| `dueDateFromMilestones` | Time | Inherited due date of the epic from milestones. |
+| `dueDateIsFixed` | Boolean | Indicates if the due date has been manually set. |
+| `events` | EventConnection | A list of events associated with the object. |
+| `group` | Group! | Group to which the epic belongs. |
+| `hasChildren` | Boolean! | Indicates if the epic has children. |
+| `hasIssues` | Boolean! | Indicates if the epic has direct issues. |
+| `hasParent` | Boolean! | Indicates if the epic has a parent epic. |
+| `healthStatus` | EpicHealthStatus | Current health status of the epic. |
+| `id` | ID! | ID of the epic. |
+| `iid` | ID! | Internal ID of the epic. |
+| `issues` | EpicIssueConnection | A list of issues associated with the epic. |
+| `labels` | LabelConnection | Labels assigned to the epic. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `parent` | Epic | Parent epic of the epic. |
+| `participants` | UserConnection | List of participants for the epic. |
+| `reference` | String! | Internal reference of the epic. Returned in shortened format by default. |
+| `relationPath` | String | URI path of the epic-issue relationship. |
+| `relativePosition` | Int | The relative position of the epic in the epic tree. |
+| `startDate` | Time | Start date of the epic. |
+| `startDateFixed` | Time | Fixed start date of the epic. |
+| `startDateFromMilestones` | Time | Inherited start date of the epic from milestones. |
+| `startDateIsFixed` | Boolean | Indicates if the start date has been manually set. |
+| `state` | EpicState! | State of the epic. |
+| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the epic. |
+| `title` | String | Title of the epic. |
+| `updatedAt` | Time | Timestamp of when the epic was updated. |
+| `upvotes` | Int! | Number of upvotes the epic has received. |
+| `userDiscussionsCount` | Int! | Number of user discussions in the epic. |
+| `userNotesCount` | Int! | Number of user notes of the epic. |
| `userPermissions` | EpicPermissions! | Permissions for the current user on the resource |
-| `webPath` | String! | Web path of the epic |
-| `webUrl` | String! | Web URL of the epic |
+| `webPath` | String! | Web path of the epic. |
+| `webUrl` | String! | Web URL of the epic. |
### EpicAddIssuePayload
@@ -1414,16 +1543,36 @@ Represents an epic board.
| `lists` | EpicListConnection | Epic board lists. |
| `name` | String | Name of the board. |
+### EpicBoardCreatePayload
+
+Autogenerated return type of EpicBoardCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `epicBoard` | EpicBoard | The created epic board. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### EpicBoardListCreatePayload
+
+Autogenerated return type of EpicBoardListCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `list` | EpicList | Epic list in the epic board. |
+
### EpicDescendantCount
Counts of descendent epics.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `closedEpics` | Int | Number of closed child epics |
-| `closedIssues` | Int | Number of closed epic issues |
-| `openedEpics` | Int | Number of opened child epics |
-| `openedIssues` | Int | Number of opened epic issues |
+| `closedEpics` | Int | Number of closed child epics. |
+| `closedIssues` | Int | Number of closed epic issues. |
+| `openedEpics` | Int | Number of opened child epics. |
+| `openedIssues` | Int | Number of opened epic issues. |
### EpicDescendantWeights
@@ -1431,8 +1580,8 @@ Total weight of open and closed descendant issues.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `closedIssues` | Int | Total weight of completed (closed) issues in this epic, including epic descendants |
-| `openedIssues` | Int | Total weight of opened issues in this epic, including epic descendants |
+| `closedIssues` | Int | Total weight of completed (closed) issues in this epic, including epic descendants. |
+| `openedIssues` | Int | Total weight of opened issues in this epic, including epic descendants. |
### EpicHealthStatus
@@ -1440,9 +1589,9 @@ Health status of child issues.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `issuesAtRisk` | Int | Number of issues at risk |
-| `issuesNeedingAttention` | Int | Number of issues that need attention |
-| `issuesOnTrack` | Int | Number of issues on track |
+| `issuesAtRisk` | Int | Number of issues at risk. |
+| `issuesNeedingAttention` | Int | Number of issues that need attention. |
+| `issuesOnTrack` | Int | Number of issues on track. |
### EpicIssue
@@ -1450,61 +1599,61 @@ Relationship between an epic and an issue.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
-| `assignees` | UserConnection | Assignees of the issue |
-| `author` | User! | User that created the issue |
+| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue. |
+| `assignees` | UserConnection | Assignees of the issue. |
+| `author` | User! | User that created the issue. |
| `blocked` | Boolean! | Indicates the issue is blocked. |
| `blockedByCount` | Int | Count of issues blocking this issue. |
-| `closedAt` | Time | Timestamp of when the issue was closed |
-| `confidential` | Boolean! | Indicates the issue is confidential |
-| `createNoteEmail` | String | User specific email address for the issue |
-| `createdAt` | Time! | Timestamp of when the issue was created |
-| `currentUserTodos` | TodoConnection! | Todos for the current user |
-| `description` | String | Description of the issue |
+| `closedAt` | Time | Timestamp of when the issue was closed. |
+| `confidential` | Boolean! | Indicates the issue is confidential. |
+| `createNoteEmail` | String | User specific email address for the issue. |
+| `createdAt` | Time! | Timestamp of when the issue was created. |
+| `currentUserTodos` | TodoConnection! | To-do items for the current user. |
+| `description` | String | Description of the issue. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `designCollection` | DesignCollection | Collection of design images associated with this issue |
-| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `downvotes` | Int! | Number of downvotes the issue has received |
-| `dueDate` | Time | Due date of the issue |
-| `emailsDisabled` | Boolean! | Indicates if a project has email notifications disabled: `true` if email notifications are disabled |
+| `designCollection` | DesignCollection | Collection of design images associated with this issue. |
+| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `downvotes` | Int! | Number of downvotes the issue has received. |
+| `dueDate` | Time | Due date of the issue. |
+| `emailsDisabled` | Boolean! | Indicates if a project has email notifications disabled: `true` if email notifications are disabled. |
| `epic` | Epic | Epic to which this issue belongs. |
-| `epicIssueId` | ID! | ID of the epic-issue relation |
+| `epicIssueId` | ID! | ID of the epic-issue relation. |
| `healthStatus` | HealthStatus | Current health status. |
-| `humanTimeEstimate` | String | Human-readable time estimate of the issue |
-| `humanTotalTimeSpent` | String | Human-readable total time reported as spent on the issue |
-| `id` | ID | Global ID of the epic-issue relation |
-| `iid` | ID! | Internal ID of the issue |
+| `humanTimeEstimate` | String | Human-readable time estimate of the issue. |
+| `humanTotalTimeSpent` | String | Human-readable total time reported as spent on the issue. |
+| `id` | ID | Global ID of the epic-issue relation. |
+| `iid` | ID! | Internal ID of the issue. |
| `iteration` | Iteration | Iteration of the issue. |
-| `labels` | LabelConnection | Labels of the issue |
+| `labels` | LabelConnection | Labels of the issue. |
| `metricImages` | MetricImage! => Array | Metric images associated to the issue. |
-| `milestone` | Milestone | Milestone of the issue |
-| `moved` | Boolean | Indicates if issue got moved from other project |
-| `movedTo` | Issue | Updated Issue after it got moved to another project |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `participants` | UserConnection | List of participants in the issue |
-| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
-| `relationPath` | String | URI path of the epic-issue relation |
-| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
-| `severity` | IssuableSeverity | Severity level of the incident |
+| `milestone` | Milestone | Milestone of the issue. |
+| `moved` | Boolean | Indicates if issue got moved from other project. |
+| `movedTo` | Issue | Updated Issue after it got moved to another project. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `participants` | UserConnection | List of participants in the issue. |
+| `reference` | String! | Internal reference of the issue. Returned in shortened format by default. |
+| `relationPath` | String | URI path of the epic-issue relation. |
+| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards). |
+| `severity` | IssuableSeverity | Severity level of the incident. |
| `slaDueAt` | Time | Timestamp of when the issue SLA expires. |
-| `state` | IssueState! | State of the issue |
+| `state` | IssueState! | State of the issue. |
| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page. |
-| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue |
-| `taskCompletionStatus` | TaskCompletionStatus! | Task completion status of the issue |
-| `timeEstimate` | Int! | Time estimate of the issue |
-| `title` | String! | Title of the issue |
+| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue. |
+| `taskCompletionStatus` | TaskCompletionStatus! | Task completion status of the issue. |
+| `timeEstimate` | Int! | Time estimate of the issue. |
+| `title` | String! | Title of the issue. |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
-| `totalTimeSpent` | Int! | Total time reported as spent on the issue |
-| `type` | IssueType | Type of the issue |
-| `updatedAt` | Time! | Timestamp of when the issue was last updated |
-| `updatedBy` | User | User that last updated the issue |
-| `upvotes` | Int! | Number of upvotes the issue has received |
-| `userDiscussionsCount` | Int! | Number of user discussions in the issue |
-| `userNotesCount` | Int! | Number of user notes of the issue |
+| `totalTimeSpent` | Int! | Total time reported as spent on the issue. |
+| `type` | IssueType | Type of the issue. |
+| `updatedAt` | Time! | Timestamp of when the issue was last updated. |
+| `updatedBy` | User | User that last updated the issue. |
+| `upvotes` | Int! | Number of upvotes the issue has received. |
+| `userDiscussionsCount` | Int! | Number of user discussions in the issue. |
+| `userNotesCount` | Int! | Number of user notes of the issue. |
| `userPermissions` | IssuePermissions! | Permissions for the current user on the resource |
-| `webPath` | String! | Web path of the issue |
-| `webUrl` | String! | Web URL of the issue |
+| `webPath` | String! | Web path of the issue. |
+| `webUrl` | String! | Web URL of the issue. |
| `weight` | Int | Weight of the issue. |
### EpicList
@@ -1554,6 +1703,18 @@ Autogenerated return type of EpicTreeReorder.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### Event
+
+Representing an event.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `action` | EventAction! | Action of the event. |
+| `author` | User! | Author of this event. |
+| `createdAt` | Time! | When this event was created. |
+| `id` | ID! | ID of the event. |
+| `updatedAt` | Time! | When this event was updated. |
+
### ExportRequirementsPayload
Autogenerated return type of ExportRequirements.
@@ -1569,114 +1730,123 @@ Represents an external issue.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time | Timestamp of when the issue was created |
-| `externalTracker` | String | Type of external tracker |
-| `relativeReference` | String | Relative reference of the issue in the external tracker |
-| `status` | String | Status of the issue in the external tracker |
-| `title` | String | Title of the issue in the external tracker |
-| `updatedAt` | Time | Timestamp of when the issue was updated |
-| `webUrl` | String | URL to the issue in the external tracker |
+| `createdAt` | Time | Timestamp of when the issue was created. |
+| `externalTracker` | String | Type of external tracker. |
+| `relativeReference` | String | Relative reference of the issue in the external tracker. |
+| `status` | String | Status of the issue in the external tracker. |
+| `title` | String | Title of the issue in the external tracker. |
+| `updatedAt` | Time | Timestamp of when the issue was updated. |
+| `webUrl` | String | URL to the issue in the external tracker. |
### GeoNode
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node |
-| `enabled` | Boolean | Indicates whether this Geo node is enabled |
-| `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node |
-| `id` | ID! | ID of this GeoNode |
-| `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it |
-| `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node |
-| `minimumReverificationInterval` | Int | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified |
-| `name` | String | The unique identifier for this Geo node |
-| `packageFileRegistries` | PackageFileRegistryConnection | Package file registries of the GeoNode |
-| `primary` | Boolean | Indicates whether this Geo node is the primary |
-| `reposMaxCapacity` | Int | The maximum concurrency of repository backfill for this secondary node |
-| `selectiveSyncNamespaces` | NamespaceConnection | The namespaces that should be synced, if `selective_sync_type` == `namespaces` |
-| `selectiveSyncShards` | String! => Array | The repository storages whose projects should be synced, if `selective_sync_type` == `shards` |
-| `selectiveSyncType` | String | Indicates if syncing is limited to only specific groups, or shards |
-| `snippetRepositoryRegistries` | SnippetRepositoryRegistryConnection | Find snippet repository registries on this Geo node |
-| `syncObjectStorage` | Boolean | Indicates if this secondary node will replicate blobs in Object Storage |
-| `terraformStateVersionRegistries` | TerraformStateVersionRegistryConnection | Find terraform state version registries on this Geo node |
-| `url` | String | The user-facing URL for this Geo node |
-| `verificationMaxCapacity` | Int | The maximum concurrency of repository verification for this secondary node |
+| `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node. |
+| `enabled` | Boolean | Indicates whether this Geo node is enabled. |
+| `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node. |
+| `id` | ID! | ID of this GeoNode. |
+| `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it. |
+| `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node. |
+| `minimumReverificationInterval` | Int | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified. |
+| `name` | String | The unique identifier for this Geo node. |
+| `packageFileRegistries` | PackageFileRegistryConnection | Package file registries of the GeoNode. |
+| `primary` | Boolean | Indicates whether this Geo node is the primary. |
+| `reposMaxCapacity` | Int | The maximum concurrency of repository backfill for this secondary node. |
+| `selectiveSyncNamespaces` | NamespaceConnection | The namespaces that should be synced, if `selective_sync_type` == `namespaces`. |
+| `selectiveSyncShards` | String! => Array | The repository storages whose projects should be synced, if `selective_sync_type` == `shards`. |
+| `selectiveSyncType` | String | Indicates if syncing is limited to only specific groups, or shards. |
+| `snippetRepositoryRegistries` | SnippetRepositoryRegistryConnection | Find snippet repository registries on this Geo node. |
+| `syncObjectStorage` | Boolean | Indicates if this secondary node will replicate blobs in Object Storage. |
+| `terraformStateVersionRegistries` | TerraformStateVersionRegistryConnection | Find terraform state version registries on this Geo node. |
+| `url` | String | The user-facing URL for this Geo node. |
+| `verificationMaxCapacity` | Int | The maximum concurrency of repository verification for this secondary node. |
+
+### GitlabSubscriptionActivatePayload
+
+Autogenerated return type of GitlabSubscriptionActivate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### GrafanaIntegration
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | Timestamp of the issue's creation |
-| `enabled` | Boolean! | Indicates whether Grafana integration is enabled |
-| `grafanaUrl` | String! | URL for the Grafana host for the Grafana integration |
-| `id` | ID! | Internal ID of the Grafana integration |
-| `updatedAt` | Time! | Timestamp of the issue's last activity |
+| `createdAt` | Time! | Timestamp of the issue's creation. |
+| `enabled` | Boolean! | Indicates whether Grafana integration is enabled. |
+| `grafanaUrl` | String! | URL for the Grafana host for the Grafana integration. |
+| `id` | ID! | Internal ID of the Grafana integration. |
+| `updatedAt` | Time! | Timestamp of the issue's last activity. |
### Group
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `actualRepositorySizeLimit` | Float | Size limit for repositories in the namespace in bytes |
-| `additionalPurchasedStorageSize` | Float | Additional storage purchased for the root namespace in bytes |
-| `autoDevopsEnabled` | Boolean | Indicates whether Auto DevOps is enabled for all projects within this group |
-| `avatarUrl` | String | Avatar URL of the group |
-| `board` | Board | A single board of the group |
-| `boards` | BoardConnection | Boards of the group |
-| `codeCoverageActivities` | CodeCoverageActivityConnection | Represents the code coverage activity for this group |
+| `actualRepositorySizeLimit` | Float | Size limit for repositories in the namespace in bytes. |
+| `additionalPurchasedStorageSize` | Float | Additional storage purchased for the root namespace in bytes. |
+| `autoDevopsEnabled` | Boolean | Indicates whether Auto DevOps is enabled for all projects within this group. |
+| `avatarUrl` | String | Avatar URL of the group. |
+| `board` | Board | A single board of the group. |
+| `boards` | BoardConnection | Boards of the group. |
+| `codeCoverageActivities` | CodeCoverageActivityConnection | Represents the code coverage activity for this group. |
| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. |
-| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the group |
-| `containerRepositoriesCount` | Int! | Number of container repositories in the group |
-| `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit |
-| `customEmoji` | CustomEmojiConnection | Custom emoji within this namespace Available only when feature flag `custom_emoji` is enabled. |
-| `description` | String | Description of the namespace |
+| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the group. |
+| `containerRepositoriesCount` | Int! | Number of container repositories in the group. |
+| `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit. |
+| `customEmoji` | CustomEmojiConnection | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. |
+| `description` | String | Description of the namespace. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `emailsDisabled` | Boolean | Indicates if a group has email notifications disabled |
-| `epic` | Epic | Find a single epic |
-| `epicBoard` | EpicBoard | Find a single epic board |
-| `epicBoards` | EpicBoardConnection | Find epic boards |
-| `epics` | EpicConnection | Find epics |
+| `emailsDisabled` | Boolean | Indicates if a group has email notifications disabled. |
+| `epic` | Epic | Find a single epic. |
+| `epicBoard` | EpicBoard | Find a single epic board. |
+| `epicBoards` | EpicBoardConnection | Find epic boards. |
+| `epics` | EpicConnection | Find epics. |
| `epicsEnabled` | Boolean | Indicates if Epics are enabled for namespace |
-| `fullName` | String! | Full name of the namespace |
-| `fullPath` | ID! | Full path of the namespace |
-| `groupMembers` | GroupMemberConnection | A membership of a user within this group |
+| `fullName` | String! | Full name of the namespace. |
+| `fullPath` | ID! | Full path of the namespace. |
+| `groupMembers` | GroupMemberConnection | A membership of a user within this group. |
| `groupTimelogsEnabled` | Boolean | Indicates if Group timelogs are enabled for namespace |
-| `id` | ID! | ID of the namespace |
-| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase |
-| `issues` | IssueConnection | Issues for projects in this group |
-| `iterations` | IterationConnection | Find iterations |
-| `label` | Label | A label available on this group |
-| `labels` | LabelConnection | Labels available on this group |
-| `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace |
-| `mentionsDisabled` | Boolean | Indicates if a group is disabled from getting mentioned |
-| `mergeRequests` | MergeRequestConnection | Merge requests for projects in this group |
-| `milestones` | MilestoneConnection | Milestones of the group |
-| `name` | String! | Name of the namespace |
-| `packageSettings` | PackageSettings | The package settings for the namespace |
-| `parent` | Group | Parent group |
-| `path` | String! | Path of the namespace |
-| `projectCreationLevel` | String | The permission level required to create projects in the group |
-| `projects` | ProjectConnection! | Projects within this namespace |
-| `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit |
-| `requestAccessEnabled` | Boolean | Indicates if users can request access to namespace |
-| `requireTwoFactorAuthentication` | Boolean | Indicates if all users in this group are required to set up two-factor authentication |
-| `rootStorageStatistics` | RootStorageStatistics | Aggregated storage statistics of the namespace. Only available for root namespaces |
-| `shareWithGroupLock` | Boolean | Indicates if sharing a project with another group within this group is prevented |
-| `stats` | GroupStats | Group statistics |
-| `storageSizeLimit` | Float | Total storage limit of the root namespace in bytes |
-| `subgroupCreationLevel` | String | The permission level required to create subgroups within the group |
-| `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active |
-| `timelogs` | TimelogConnection! | Time logged in issues by group members |
-| `totalRepositorySize` | Float | Total repository size of all projects in the root namespace in bytes |
-| `totalRepositorySizeExcess` | Float | Total excess repository size of all projects in the root namespace in bytes |
-| `twoFactorGracePeriod` | Int | Time before two-factor authentication is enforced |
+| `id` | ID! | ID of the namespace. |
+| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase. |
+| `issues` | IssueConnection | Issues for projects in this group. |
+| `iterations` | IterationConnection | Find iterations. |
+| `label` | Label | A label available on this group. |
+| `labels` | LabelConnection | Labels available on this group. |
+| `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace. |
+| `mentionsDisabled` | Boolean | Indicates if a group is disabled from getting mentioned. |
+| `mergeRequests` | MergeRequestConnection | Merge requests for projects in this group. |
+| `milestones` | MilestoneConnection | Milestones of the group. |
+| `name` | String! | Name of the namespace. |
+| `packageSettings` | PackageSettings | The package settings for the namespace. |
+| `parent` | Group | Parent group. |
+| `path` | String! | Path of the namespace. |
+| `projectCreationLevel` | String | The permission level required to create projects in the group. |
+| `projects` | ProjectConnection! | Projects within this namespace. |
+| `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit. |
+| `requestAccessEnabled` | Boolean | Indicates if users can request access to namespace. |
+| `requireTwoFactorAuthentication` | Boolean | Indicates if all users in this group are required to set up two-factor authentication. |
+| `rootStorageStatistics` | RootStorageStatistics | Aggregated storage statistics of the namespace. Only available for root namespaces. |
+| `shareWithGroupLock` | Boolean | Indicates if sharing a project with another group within this group is prevented. |
+| `stats` | GroupStats | Group statistics. |
+| `storageSizeLimit` | Float | Total storage limit of the root namespace in bytes. |
+| `subgroupCreationLevel` | String | The permission level required to create subgroups within the group. |
+| `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active. |
+| `timelogs` | TimelogConnection! | Time logged in issues by group members. |
+| `totalRepositorySize` | Float | Total repository size of all projects in the root namespace in bytes. |
+| `totalRepositorySizeExcess` | Float | Total excess repository size of all projects in the root namespace in bytes. |
+| `twoFactorGracePeriod` | Int | Time before two-factor authentication is enforced. |
| `userPermissions` | GroupPermissions! | Permissions for the current user on the resource |
-| `visibility` | String | Visibility of the namespace |
-| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the projects in the group and its subgroups |
-| `vulnerabilitiesCountByDay` | VulnerabilitiesCountByDayConnection | Number of vulnerabilities per day for the projects in the group and its subgroups |
+| `visibility` | String | Visibility of the namespace. |
+| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the projects in the group and its subgroups. |
+| `vulnerabilitiesCountByDay` | VulnerabilitiesCountByDayConnection | Number of vulnerabilities per day for the projects in the group and its subgroups. |
| `vulnerabilitiesCountByDayAndSeverity` **{warning-solid}** | VulnerabilitiesCountByDayAndSeverityConnection | **Deprecated:** Use `vulnerabilitiesCountByDay`. Deprecated in 13.3. |
-| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade |
-| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups |
-| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the group and its subgroups |
-| `webUrl` | String! | Web URL of the group |
+| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade. |
+| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the project vulnerabilities of the group and its subgroups. |
+| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the group and its subgroups. |
+| `webUrl` | String! | Web URL of the group. |
### GroupMember
@@ -1684,14 +1854,14 @@ Represents a Group Membership.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `accessLevel` | AccessLevel | GitLab::Access level |
-| `createdAt` | Time | Date and time the membership was created |
-| `createdBy` | User | User that authorized membership |
-| `expiresAt` | Time | Date and time the membership expires |
-| `group` | Group | Group that a User is a member of |
-| `id` | ID! | ID of the member |
-| `updatedAt` | Time | Date and time the membership was last updated |
-| `user` | User! | User that is associated with the member object |
+| `accessLevel` | AccessLevel | GitLab::Access level. |
+| `createdAt` | Time | Date and time the membership was created. |
+| `createdBy` | User | User that authorized membership. |
+| `expiresAt` | Time | Date and time the membership expires. |
+| `group` | Group | Group that a User is a member of. |
+| `id` | ID! | ID of the member. |
+| `updatedAt` | Time | Date and time the membership was last updated. |
+| `user` | User! | User that is associated with the member object. |
| `userPermissions` | GroupPermissions! | Permissions for the current user on the resource |
### GroupPermissions
@@ -1715,7 +1885,7 @@ Contains statistics about a group.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `releaseStats` | GroupReleaseStats | Statistics related to releases within the group |
+| `releaseStats` | GroupReleaseStats | Statistics related to releases within the group. |
### HttpIntegrationCreatePayload
@@ -1768,6 +1938,7 @@ Describes an incident management on-call rotation.
| `lengthUnit` | OncallRotationUnitEnum | Unit of the on-call rotation length. |
| `name` | String! | Name of the on-call rotation. |
| `participants` | OncallParticipantTypeConnection | Participants of the on-call rotation. |
+| `shifts` | IncidentManagementOncallShiftConnection | Blocks of time for which a participant is on-call within a given time frame. Time frame cannot exceed one month. |
| `startsAt` | Time | Start date of the on-call rotation. |
### IncidentManagementOncallSchedule
@@ -1776,20 +1947,30 @@ Describes an incident management on-call schedule.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `description` | String | Description of the on-call schedule |
-| `iid` | ID! | Internal ID of the on-call schedule |
-| `name` | String! | Name of the on-call schedule |
-| `rotations` | IncidentManagementOncallRotationConnection! | On-call rotations for the on-call schedule |
-| `timezone` | String! | Time zone of the on-call schedule |
+| `description` | String | Description of the on-call schedule. |
+| `iid` | ID! | Internal ID of the on-call schedule. |
+| `name` | String! | Name of the on-call schedule. |
+| `rotations` | IncidentManagementOncallRotationConnection! | On-call rotations for the on-call schedule. |
+| `timezone` | String! | Time zone of the on-call schedule. |
+
+### IncidentManagementOncallShift
+
+A block of time for which a participant is on-call..
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `endsAt` | Time | End time of the on-call shift. |
+| `participant` | OncallParticipantType | Participant assigned to the on-call shift. |
+| `startsAt` | Time | Start time of the on-call shift. |
### InstanceSecurityDashboard
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `projects` | ProjectConnection! | Projects selected in Instance Security Dashboard |
-| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade |
-| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard |
-| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity from projects selected in Instance Security Dashboard |
+| `projects` | ProjectConnection! | Projects selected in Instance Security Dashboard. |
+| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade. |
+| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard. |
+| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity from projects selected in Instance Security Dashboard. |
### InstanceStatisticsMeasurement
@@ -1797,67 +1978,67 @@ Represents a recorded measurement (object count) for the Admins.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int! | Object count |
-| `identifier` | MeasurementIdentifier! | The type of objects being measured |
-| `recordedAt` | Time | The time the measurement was recorded |
+| `count` | Int! | Object count. |
+| `identifier` | MeasurementIdentifier! | The type of objects being measured. |
+| `recordedAt` | Time | The time the measurement was recorded. |
### Issue
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
-| `assignees` | UserConnection | Assignees of the issue |
-| `author` | User! | User that created the issue |
+| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue. |
+| `assignees` | UserConnection | Assignees of the issue. |
+| `author` | User! | User that created the issue. |
| `blocked` | Boolean! | Indicates the issue is blocked. |
| `blockedByCount` | Int | Count of issues blocking this issue. |
-| `closedAt` | Time | Timestamp of when the issue was closed |
-| `confidential` | Boolean! | Indicates the issue is confidential |
-| `createNoteEmail` | String | User specific email address for the issue |
-| `createdAt` | Time! | Timestamp of when the issue was created |
-| `currentUserTodos` | TodoConnection! | Todos for the current user |
-| `description` | String | Description of the issue |
+| `closedAt` | Time | Timestamp of when the issue was closed. |
+| `confidential` | Boolean! | Indicates the issue is confidential. |
+| `createNoteEmail` | String | User specific email address for the issue. |
+| `createdAt` | Time! | Timestamp of when the issue was created. |
+| `currentUserTodos` | TodoConnection! | To-do items for the current user. |
+| `description` | String | Description of the issue. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `designCollection` | DesignCollection | Collection of design images associated with this issue |
-| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `downvotes` | Int! | Number of downvotes the issue has received |
-| `dueDate` | Time | Due date of the issue |
-| `emailsDisabled` | Boolean! | Indicates if a project has email notifications disabled: `true` if email notifications are disabled |
+| `designCollection` | DesignCollection | Collection of design images associated with this issue. |
+| `discussionLocked` | Boolean! | Indicates discussion is locked on the issue. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `downvotes` | Int! | Number of downvotes the issue has received. |
+| `dueDate` | Time | Due date of the issue. |
+| `emailsDisabled` | Boolean! | Indicates if a project has email notifications disabled: `true` if email notifications are disabled. |
| `epic` | Epic | Epic to which this issue belongs. |
| `healthStatus` | HealthStatus | Current health status. |
-| `humanTimeEstimate` | String | Human-readable time estimate of the issue |
-| `humanTotalTimeSpent` | String | Human-readable total time reported as spent on the issue |
-| `id` | ID! | ID of the issue |
-| `iid` | ID! | Internal ID of the issue |
+| `humanTimeEstimate` | String | Human-readable time estimate of the issue. |
+| `humanTotalTimeSpent` | String | Human-readable total time reported as spent on the issue. |
+| `id` | ID! | ID of the issue. |
+| `iid` | ID! | Internal ID of the issue. |
| `iteration` | Iteration | Iteration of the issue. |
-| `labels` | LabelConnection | Labels of the issue |
+| `labels` | LabelConnection | Labels of the issue. |
| `metricImages` | MetricImage! => Array | Metric images associated to the issue. |
-| `milestone` | Milestone | Milestone of the issue |
-| `moved` | Boolean | Indicates if issue got moved from other project |
-| `movedTo` | Issue | Updated Issue after it got moved to another project |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `participants` | UserConnection | List of participants in the issue |
-| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
-| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
-| `severity` | IssuableSeverity | Severity level of the incident |
+| `milestone` | Milestone | Milestone of the issue. |
+| `moved` | Boolean | Indicates if issue got moved from other project. |
+| `movedTo` | Issue | Updated Issue after it got moved to another project. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `participants` | UserConnection | List of participants in the issue. |
+| `reference` | String! | Internal reference of the issue. Returned in shortened format by default. |
+| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards). |
+| `severity` | IssuableSeverity | Severity level of the incident. |
| `slaDueAt` | Time | Timestamp of when the issue SLA expires. |
-| `state` | IssueState! | State of the issue |
+| `state` | IssueState! | State of the issue. |
| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page. |
-| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue |
-| `taskCompletionStatus` | TaskCompletionStatus! | Task completion status of the issue |
-| `timeEstimate` | Int! | Time estimate of the issue |
-| `title` | String! | Title of the issue |
+| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue. |
+| `taskCompletionStatus` | TaskCompletionStatus! | Task completion status of the issue. |
+| `timeEstimate` | Int! | Time estimate of the issue. |
+| `title` | String! | Title of the issue. |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
-| `totalTimeSpent` | Int! | Total time reported as spent on the issue |
-| `type` | IssueType | Type of the issue |
-| `updatedAt` | Time! | Timestamp of when the issue was last updated |
-| `updatedBy` | User | User that last updated the issue |
-| `upvotes` | Int! | Number of upvotes the issue has received |
-| `userDiscussionsCount` | Int! | Number of user discussions in the issue |
-| `userNotesCount` | Int! | Number of user notes of the issue |
+| `totalTimeSpent` | Int! | Total time reported as spent on the issue. |
+| `type` | IssueType | Type of the issue. |
+| `updatedAt` | Time! | Timestamp of when the issue was last updated. |
+| `updatedBy` | User | User that last updated the issue. |
+| `upvotes` | Int! | Number of upvotes the issue has received. |
+| `userDiscussionsCount` | Int! | Number of user discussions in the issue. |
+| `userNotesCount` | Int! | Number of user notes of the issue. |
| `userPermissions` | IssuePermissions! | Permissions for the current user on the resource |
-| `webPath` | String! | Web path of the issue |
-| `webUrl` | String! | Web URL of the issue |
+| `webPath` | String! | Web path of the issue. |
+| `webUrl` | String! | Web URL of the issue. |
| `weight` | Int | Weight of the issue. |
### IssueMoveListPayload
@@ -2001,33 +2182,33 @@ Represents an iteration object.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | Timestamp of iteration creation |
-| `description` | String | Description of the iteration |
+| `createdAt` | Time! | Timestamp of iteration creation. |
+| `description` | String | Description of the iteration. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `dueDate` | Time | Timestamp of the iteration due date |
-| `id` | ID! | ID of the iteration |
-| `iid` | ID! | Internal ID of the iteration |
-| `report` | TimeboxReport | Historically accurate report about the timebox |
-| `scopedPath` | String | Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts |
-| `scopedUrl` | String | Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts |
-| `startDate` | Time | Timestamp of the iteration start date |
-| `state` | IterationState! | State of the iteration |
-| `title` | String! | Title of the iteration |
-| `updatedAt` | Time! | Timestamp of last iteration update |
-| `webPath` | String! | Web path of the iteration |
-| `webUrl` | String! | Web URL of the iteration |
+| `dueDate` | Time | Timestamp of the iteration due date. |
+| `id` | ID! | ID of the iteration. |
+| `iid` | ID! | Internal ID of the iteration. |
+| `report` | TimeboxReport | Historically accurate report about the timebox. |
+| `scopedPath` | String | Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts. |
+| `scopedUrl` | String | Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts. |
+| `startDate` | Time | Timestamp of the iteration start date. |
+| `state` | IterationState! | State of the iteration. |
+| `title` | String! | Title of the iteration. |
+| `updatedAt` | Time! | Timestamp of last iteration update. |
+| `webPath` | String! | Web path of the iteration. |
+| `webUrl` | String! | Web URL of the iteration. |
### JiraImport
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time | Timestamp of when the Jira import was created |
-| `failedToImportCount` | Int! | Count of issues that failed to import |
-| `importedIssuesCount` | Int! | Count of issues that were successfully imported |
-| `jiraProjectKey` | String! | Project key for the imported Jira project |
-| `scheduledAt` | Time | Timestamp of when the Jira import was scheduled |
-| `scheduledBy` | User | User that started the Jira import |
-| `totalIssueCount` | Int! | Total count of issues that were attempted to import |
+| `createdAt` | Time | Timestamp of when the Jira import was created. |
+| `failedToImportCount` | Int! | Count of issues that failed to import. |
+| `importedIssuesCount` | Int! | Count of issues that were successfully imported. |
+| `jiraProjectKey` | String! | Project key for the imported Jira project. |
+| `scheduledAt` | Time | Timestamp of when the Jira import was scheduled. |
+| `scheduledBy` | User | User that started the Jira import. |
+| `totalIssueCount` | Int! | Total count of issues that were attempted to import. |
### JiraImportStartPayload
@@ -2053,39 +2234,39 @@ Autogenerated return type of JiraImportUsers.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `key` | String! | Key of the Jira project |
-| `name` | String | Name of the Jira project |
-| `projectId` | Int! | ID of the Jira project |
+| `key` | String! | Key of the Jira project. |
+| `name` | String | Name of the Jira project. |
+| `projectId` | Int! | ID of the Jira project. |
### JiraService
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `active` | Boolean | Indicates if the service is active |
-| `projects` | JiraProjectConnection | List of all Jira projects fetched through Jira REST API |
-| `type` | String | Class name of the service |
+| `active` | Boolean | Indicates if the service is active. |
+| `projects` | JiraProjectConnection | List of all Jira projects fetched through Jira REST API. |
+| `type` | String | Class name of the service. |
### JiraUser
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `gitlabId` | Int | ID of the matched GitLab user |
-| `gitlabName` | String | Name of the matched GitLab user |
-| `gitlabUsername` | String | Username of the matched GitLab user |
-| `jiraAccountId` | String! | Account ID of the Jira user |
-| `jiraDisplayName` | String! | Display name of the Jira user |
-| `jiraEmail` | String | Email of the Jira user, returned only for users with public emails |
+| `gitlabId` | Int | ID of the matched GitLab user. |
+| `gitlabName` | String | Name of the matched GitLab user. |
+| `gitlabUsername` | String | Username of the matched GitLab user. |
+| `jiraAccountId` | String! | Account ID of the Jira user. |
+| `jiraDisplayName` | String! | Display name of the Jira user. |
+| `jiraEmail` | String | Email of the Jira user, returned only for users with public emails. |
### Label
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `color` | String! | Background color of the label |
-| `description` | String | Description of the label (Markdown rendered as HTML for caching) |
+| `color` | String! | Background color of the label. |
+| `description` | String | Description of the label (Markdown rendered as HTML for caching). |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `id` | ID! | Label ID |
-| `textColor` | String! | Text color of the label |
-| `title` | String! | Content of the label |
+| `id` | ID! | Label ID. |
+| `textColor` | String! | Text color of the label. |
+| `title` | String! | Content of the label. |
### LabelCreatePayload
@@ -2111,88 +2292,89 @@ Autogenerated return type of MarkAsSpamSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `allowCollaboration` | Boolean | Indicates if members of the target project can push to the fork |
-| `approvalsLeft` | Int | Number of approvals left |
-| `approvalsRequired` | Int | Number of approvals required |
+| `allowCollaboration` | Boolean | Indicates if members of the target project can push to the fork. |
+| `approvalsLeft` | Int | Number of approvals left. |
+| `approvalsRequired` | Int | Number of approvals required. |
| `approved` | Boolean! | Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured. |
-| `approvedBy` | UserConnection | Users who approved the merge request |
-| `assignees` | UserConnection | Assignees of the merge request |
-| `author` | User | User who created this merge request |
-| `autoMergeEnabled` | Boolean! | Indicates if auto merge is enabled for the merge request |
-| `autoMergeStrategy` | String | Selected auto merge strategy |
-| `availableAutoMergeStrategies` | String! => Array | Array of available auto merge strategies |
-| `commitCount` | Int | Number of commits in the merge request |
-| `commitsWithoutMergeCommits` | CommitConnection | Merge request commits excluding merge commits |
-| `conflicts` | Boolean! | Indicates if the merge request has conflicts |
-| `createdAt` | Time! | Timestamp of when the merge request was created |
-| `currentUserTodos` | TodoConnection! | Todos for the current user |
-| `defaultMergeCommitMessage` | String | Default merge commit message of the merge request |
-| `defaultMergeCommitMessageWithDescription` | String | Default merge commit message of the merge request with description |
-| `defaultSquashCommitMessage` | String | Default squash commit message of the merge request |
-| `description` | String | Description of the merge request (Markdown rendered as HTML for caching) |
+| `approvedBy` | UserConnection | Users who approved the merge request. |
+| `assignees` | UserConnection | Assignees of the merge request. |
+| `author` | User | User who created this merge request. |
+| `autoMergeEnabled` | Boolean! | Indicates if auto merge is enabled for the merge request. |
+| `autoMergeStrategy` | String | Selected auto merge strategy. |
+| `availableAutoMergeStrategies` | String! => Array | Array of available auto merge strategies. |
+| `commitCount` | Int | Number of commits in the merge request. |
+| `commitsWithoutMergeCommits` | CommitConnection | Merge request commits excluding merge commits. |
+| `conflicts` | Boolean! | Indicates if the merge request has conflicts. |
+| `createdAt` | Time! | Timestamp of when the merge request was created. |
+| `currentUserTodos` | TodoConnection! | To-do items for the current user. |
+| `defaultMergeCommitMessage` | String | Default merge commit message of the merge request. |
+| `defaultMergeCommitMessageWithDescription` | String | Default merge commit message of the merge request with description. |
+| `defaultSquashCommitMessage` | String | Default squash commit message of the merge request. |
+| `description` | String | Description of the merge request (Markdown rendered as HTML for caching). |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `diffHeadSha` | String | Diff head SHA of the merge request |
-| `diffRefs` | DiffRefs | References of the base SHA, the head SHA, and the start SHA for this merge request |
-| `diffStats` | DiffStats! => Array | Details about which files were changed in this merge request |
-| `diffStatsSummary` | DiffStatsSummary | Summary of which files were changed in this merge request |
-| `discussionLocked` | Boolean! | Indicates if comments on the merge request are locked to members only |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `downvotes` | Int! | Number of downvotes for the merge request |
-| `forceRemoveSourceBranch` | Boolean | Indicates if the project settings will lead to source branch deletion after merge |
-| `hasCi` | Boolean! | Indicates if the merge request has CI |
-| `headPipeline` | Pipeline | The pipeline running on the branch HEAD of the merge request |
-| `id` | ID! | ID of the merge request |
-| `iid` | String! | Internal ID of the merge request |
-| `inProgressMergeCommitSha` | String | Commit SHA of the merge request if merge is in progress |
-| `labels` | LabelConnection | Labels of the merge request |
-| `mergeCommitSha` | String | SHA of the merge request commit (set once merged) |
-| `mergeError` | String | Error message due to a merge error |
-| `mergeOngoing` | Boolean! | Indicates if a merge is currently occurring |
-| `mergeStatus` | String | Status of the merge request |
-| `mergeTrainsCount` | Int | |
-| `mergeUser` | User | User who merged this merge request |
-| `mergeWhenPipelineSucceeds` | Boolean | Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS) |
-| `mergeable` | Boolean! | Indicates if the merge request is mergeable |
-| `mergeableDiscussionsState` | Boolean | Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged |
-| `mergedAt` | Time | Timestamp of when the merge request was merged, null if not merged |
-| `milestone` | Milestone | The milestone of the merge request |
-| `notes` | NoteConnection! | All notes on this noteable |
+| `diffHeadSha` | String | Diff head SHA of the merge request. |
+| `diffRefs` | DiffRefs | References of the base SHA, the head SHA, and the start SHA for this merge request. |
+| `diffStats` | DiffStats! => Array | Details about which files were changed in this merge request. |
+| `diffStatsSummary` | DiffStatsSummary | Summary of which files were changed in this merge request. |
+| `discussionLocked` | Boolean! | Indicates if comments on the merge request are locked to members only. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `downvotes` | Int! | Number of downvotes for the merge request. |
+| `forceRemoveSourceBranch` | Boolean | Indicates if the project settings will lead to source branch deletion after merge. |
+| `hasCi` | Boolean! | Indicates if the merge request has CI. |
+| `hasSecurityReports` | Boolean! | Indicates if the source branch has any security reports. |
+| `headPipeline` | Pipeline | The pipeline running on the branch HEAD of the merge request. |
+| `id` | ID! | ID of the merge request. |
+| `iid` | String! | Internal ID of the merge request. |
+| `inProgressMergeCommitSha` | String | Commit SHA of the merge request if merge is in progress. |
+| `labels` | LabelConnection | Labels of the merge request. |
+| `mergeCommitSha` | String | SHA of the merge request commit (set once merged). |
+| `mergeError` | String | Error message due to a merge error. |
+| `mergeOngoing` | Boolean! | Indicates if a merge is currently occurring. |
+| `mergeStatus` | String | Status of the merge request. |
+| `mergeTrainsCount` | Int | Number of merge requests in the merge train. |
+| `mergeUser` | User | User who merged this merge request. |
+| `mergeWhenPipelineSucceeds` | Boolean | Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS). |
+| `mergeable` | Boolean! | Indicates if the merge request is mergeable. |
+| `mergeableDiscussionsState` | Boolean | Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged. |
+| `mergedAt` | Time | Timestamp of when the merge request was merged, null if not merged. |
+| `milestone` | Milestone | The milestone of the merge request. |
+| `notes` | NoteConnection! | All notes on this noteable. |
| `participants` | UserConnection | Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes. |
| `pipelines` | PipelineConnection | Pipelines for the merge request. Note: for performance reasons, no more than the most recent 500 pipelines will be returned. |
-| `project` | Project! | Alias for target_project |
-| `projectId` | Int! | ID of the merge request project |
-| `rebaseCommitSha` | String | Rebase commit SHA of the merge request |
-| `rebaseInProgress` | Boolean! | Indicates if there is a rebase currently in progress for the merge request |
-| `reference` | String! | Internal reference of the merge request. Returned in shortened format by default |
+| `project` | Project! | Alias for target_project. |
+| `projectId` | Int! | ID of the merge request project. |
+| `rebaseCommitSha` | String | Rebase commit SHA of the merge request. |
+| `rebaseInProgress` | Boolean! | Indicates if there is a rebase currently in progress for the merge request. |
+| `reference` | String! | Internal reference of the merge request. Returned in shortened format by default. |
| `reviewers` | UserConnection | Users from whom a review has been requested. |
| `securityAutoFix` | Boolean | Indicates if the merge request is created by @GitLab-Security-Bot. |
-| `shouldBeRebased` | Boolean! | Indicates if the merge request will be rebased |
-| `shouldRemoveSourceBranch` | Boolean | Indicates if the source branch of the merge request will be deleted after merge |
-| `sourceBranch` | String! | Source branch of the merge request |
-| `sourceBranchExists` | Boolean! | Indicates if the source branch of the merge request exists |
-| `sourceBranchProtected` | Boolean! | Indicates if the source branch is protected |
-| `sourceProject` | Project | Source project of the merge request |
-| `sourceProjectId` | Int | ID of the merge request source project |
-| `squash` | Boolean! | Indicates if squash on merge is enabled |
-| `squashOnMerge` | Boolean! | Indicates if squash on merge is enabled |
-| `state` | MergeRequestState! | State of the merge request |
-| `subscribed` | Boolean! | Indicates if the currently logged in user is subscribed to this merge request |
-| `targetBranch` | String! | Target branch of the merge request |
-| `targetBranchExists` | Boolean! | Indicates if the target branch of the merge request exists |
-| `targetProject` | Project! | Target project of the merge request |
-| `targetProjectId` | Int! | ID of the merge request target project |
+| `shouldBeRebased` | Boolean! | Indicates if the merge request will be rebased. |
+| `shouldRemoveSourceBranch` | Boolean | Indicates if the source branch of the merge request will be deleted after merge. |
+| `sourceBranch` | String! | Source branch of the merge request. |
+| `sourceBranchExists` | Boolean! | Indicates if the source branch of the merge request exists. |
+| `sourceBranchProtected` | Boolean! | Indicates if the source branch is protected. |
+| `sourceProject` | Project | Source project of the merge request. |
+| `sourceProjectId` | Int | ID of the merge request source project. |
+| `squash` | Boolean! | Indicates if squash on merge is enabled. |
+| `squashOnMerge` | Boolean! | Indicates if squash on merge is enabled. |
+| `state` | MergeRequestState! | State of the merge request. |
+| `subscribed` | Boolean! | Indicates if the currently logged in user is subscribed to this merge request. |
+| `targetBranch` | String! | Target branch of the merge request. |
+| `targetBranchExists` | Boolean! | Indicates if the target branch of the merge request exists. |
+| `targetProject` | Project! | Target project of the merge request. |
+| `targetProjectId` | Int! | ID of the merge request target project. |
| `taskCompletionStatus` | TaskCompletionStatus! | Completion status of tasks |
-| `timeEstimate` | Int! | Time estimate of the merge request |
-| `title` | String! | Title of the merge request |
+| `timeEstimate` | Int! | Time estimate of the merge request. |
+| `title` | String! | Title of the merge request. |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
-| `totalTimeSpent` | Int! | Total time reported as spent on the merge request |
-| `updatedAt` | Time! | Timestamp of when the merge request was last updated |
-| `upvotes` | Int! | Number of upvotes for the merge request |
-| `userDiscussionsCount` | Int | Number of user discussions in the merge request |
-| `userNotesCount` | Int | User notes count of the merge request |
+| `totalTimeSpent` | Int! | Total time reported as spent on the merge request. |
+| `updatedAt` | Time! | Timestamp of when the merge request was last updated. |
+| `upvotes` | Int! | Number of upvotes for the merge request. |
+| `userDiscussionsCount` | Int | Number of user discussions in the merge request. |
+| `userNotesCount` | Int | User notes count of the merge request. |
| `userPermissions` | MergeRequestPermissions! | Permissions for the current user on the resource |
-| `webUrl` | String | Web URL of the merge request |
-| `workInProgress` | Boolean! | Indicates if the merge request is a work in progress (WIP) |
+| `webUrl` | String | Web URL of the merge request. |
+| `workInProgress` | Boolean! | Indicates if the merge request is a work in progress (WIP). |
### MergeRequestCreatePayload
@@ -2214,7 +2396,7 @@ Represents the Geo sync and verification state of a Merge Request diff.
| `id` | ID! | ID of the MergeRequestDiffRegistry |
| `lastSyncFailure` | String | Error message during sync of the MergeRequestDiffRegistry |
| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the MergeRequestDiffRegistry |
-| `mergeRequestDiffId` | ID! | ID of the Merge Request diff |
+| `mergeRequestDiffId` | ID! | ID of the Merge Request diff. |
| `retryAt` | Time | Timestamp after which the MergeRequestDiffRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the MergeRequestDiffRegistry |
| `state` | RegistryState | Sync state of the MergeRequestDiffRegistry |
@@ -2235,6 +2417,16 @@ Check permissions for the current user on a merge request.
| `revertOnCurrentMergeRequest` | Boolean! | Indicates the user can perform `revert_on_current_merge_request` on this resource |
| `updateMergeRequest` | Boolean! | Indicates the user can perform `update_merge_request` on this resource |
+### MergeRequestReviewerRereviewPayload
+
+Autogenerated return type of MergeRequestReviewerRereview.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `mergeRequest` | MergeRequest | The merge request after mutation. |
+
### MergeRequestSetAssigneesPayload
Autogenerated return type of MergeRequestSetAssignees.
@@ -2309,8 +2501,8 @@ Autogenerated return type of MergeRequestUpdate.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `revision` | String! | Revision |
-| `version` | String! | Version |
+| `revision` | String! | Revision. |
+| `version` | String! | Version. |
### MetricImage
@@ -2318,29 +2510,29 @@ Represents a metric image upload.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `fileName` | String | File name of the metric image |
-| `filePath` | String | File path of the metric image |
-| `id` | ID! | ID of the metric upload |
-| `iid` | ID! | Internal ID of the metric upload |
-| `url` | String! | URL of the metric source |
+| `fileName` | String | File name of the metric image. |
+| `filePath` | String | File path of the metric image. |
+| `id` | ID! | ID of the metric upload. |
+| `iid` | ID! | Internal ID of the metric upload. |
+| `url` | String! | URL of the metric source. |
### MetricsDashboard
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `annotations` | MetricsDashboardAnnotationConnection | Annotations added to the dashboard |
-| `path` | String | Path to a file with the dashboard definition |
-| `schemaValidationWarnings` | String! => Array | Dashboard schema validation warnings |
+| `annotations` | MetricsDashboardAnnotationConnection | Annotations added to the dashboard. |
+| `path` | String | Path to a file with the dashboard definition. |
+| `schemaValidationWarnings` | String! => Array | Dashboard schema validation warnings. |
### MetricsDashboardAnnotation
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `description` | String | Description of the annotation |
-| `endingAt` | Time | Timestamp marking end of annotated time span |
-| `id` | ID! | ID of the annotation |
-| `panelId` | String | ID of a dashboard panel to which the annotation should be scoped |
-| `startingAt` | Time | Timestamp marking start of annotated time span |
+| `description` | String | Description of the annotation. |
+| `endingAt` | Time | Timestamp marking end of annotated time span. |
+| `id` | ID! | ID of the annotation. |
+| `panelId` | String | ID of a dashboard panel to which the annotation should be scoped. |
+| `startingAt` | Time | Timestamp marking start of annotated time span. |
### Milestone
@@ -2348,20 +2540,20 @@ Represents a milestone.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | Timestamp of milestone creation |
-| `description` | String | Description of the milestone |
-| `dueDate` | Time | Timestamp of the milestone due date |
-| `groupMilestone` | Boolean! | Indicates if milestone is at group level |
-| `id` | ID! | ID of the milestone |
-| `projectMilestone` | Boolean! | Indicates if milestone is at project level |
-| `report` | TimeboxReport | Historically accurate report about the timebox |
-| `startDate` | Time | Timestamp of the milestone start date |
-| `state` | MilestoneStateEnum! | State of the milestone |
-| `stats` | MilestoneStats | Milestone statistics |
-| `subgroupMilestone` | Boolean! | Indicates if milestone is at subgroup level |
-| `title` | String! | Title of the milestone |
-| `updatedAt` | Time! | Timestamp of last milestone update |
-| `webPath` | String! | Web path of the milestone |
+| `createdAt` | Time! | Timestamp of milestone creation. |
+| `description` | String | Description of the milestone. |
+| `dueDate` | Time | Timestamp of the milestone due date. |
+| `groupMilestone` | Boolean! | Indicates if milestone is at group level. |
+| `id` | ID! | ID of the milestone. |
+| `projectMilestone` | Boolean! | Indicates if milestone is at project level. |
+| `report` | TimeboxReport | Historically accurate report about the timebox. |
+| `startDate` | Time | Timestamp of the milestone start date. |
+| `state` | MilestoneStateEnum! | State of the milestone. |
+| `stats` | MilestoneStats | Milestone statistics. |
+| `subgroupMilestone` | Boolean! | Indicates if milestone is at subgroup level. |
+| `title` | String! | Title of the milestone. |
+| `updatedAt` | Time! | Timestamp of last milestone update. |
+| `webPath` | String! | Web path of the milestone. |
### MilestoneStats
@@ -2369,36 +2561,36 @@ Contains statistics about a milestone.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `closedIssuesCount` | Int | Number of closed issues associated with the milestone |
-| `totalIssuesCount` | Int | Total number of issues associated with the milestone |
+| `closedIssuesCount` | Int | Number of closed issues associated with the milestone. |
+| `totalIssuesCount` | Int | Total number of issues associated with the milestone. |
### Namespace
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `actualRepositorySizeLimit` | Float | Size limit for repositories in the namespace in bytes |
-| `additionalPurchasedStorageSize` | Float | Additional storage purchased for the root namespace in bytes |
+| `actualRepositorySizeLimit` | Float | Size limit for repositories in the namespace in bytes. |
+| `additionalPurchasedStorageSize` | Float | Additional storage purchased for the root namespace in bytes. |
| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. |
-| `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit |
-| `description` | String | Description of the namespace |
+| `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit. |
+| `description` | String | Description of the namespace. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `fullName` | String! | Full name of the namespace |
-| `fullPath` | ID! | Full path of the namespace |
-| `id` | ID! | ID of the namespace |
-| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase |
-| `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace |
-| `name` | String! | Name of the namespace |
-| `packageSettings` | PackageSettings | The package settings for the namespace |
-| `path` | String! | Path of the namespace |
-| `projects` | ProjectConnection! | Projects within this namespace |
-| `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit |
-| `requestAccessEnabled` | Boolean | Indicates if users can request access to namespace |
-| `rootStorageStatistics` | RootStorageStatistics | Aggregated storage statistics of the namespace. Only available for root namespaces |
-| `storageSizeLimit` | Float | Total storage limit of the root namespace in bytes |
-| `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active |
-| `totalRepositorySize` | Float | Total repository size of all projects in the root namespace in bytes |
-| `totalRepositorySizeExcess` | Float | Total excess repository size of all projects in the root namespace in bytes |
-| `visibility` | String | Visibility of the namespace |
+| `fullName` | String! | Full name of the namespace. |
+| `fullPath` | ID! | Full path of the namespace. |
+| `id` | ID! | ID of the namespace. |
+| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase. |
+| `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace. |
+| `name` | String! | Name of the namespace. |
+| `packageSettings` | PackageSettings | The package settings for the namespace. |
+| `path` | String! | Path of the namespace. |
+| `projects` | ProjectConnection! | Projects within this namespace. |
+| `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit. |
+| `requestAccessEnabled` | Boolean | Indicates if users can request access to namespace. |
+| `rootStorageStatistics` | RootStorageStatistics | Aggregated storage statistics of the namespace. Only available for root namespaces. |
+| `storageSizeLimit` | Float | Total storage limit of the root namespace in bytes. |
+| `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active. |
+| `totalRepositorySize` | Float | Total repository size of all projects in the root namespace in bytes. |
+| `totalRepositorySizeExcess` | Float | Total excess repository size of all projects in the root namespace in bytes. |
+| `visibility` | String | Visibility of the namespace. |
### NamespaceIncreaseStorageTemporarilyPayload
@@ -2414,23 +2606,23 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User! | User who wrote this note |
-| `body` | String! | Content of the note |
+| `author` | User! | User who wrote this note. |
+| `body` | String! | Content of the note. |
| `bodyHtml` | String | The GitLab Flavored Markdown rendering of `note` |
-| `confidential` | Boolean | Indicates if this note is confidential |
-| `createdAt` | Time! | Timestamp of the note creation |
-| `discussion` | Discussion | The discussion this note is a part of |
-| `id` | ID! | ID of the note |
-| `position` | DiffPosition | The position of this note on a diff |
-| `project` | Project | Project associated with the note |
-| `resolvable` | Boolean! | Indicates if the object can be resolved |
-| `resolved` | Boolean! | Indicates if the object is resolved |
-| `resolvedAt` | Time | Timestamp of when the object was resolved |
-| `resolvedBy` | User | User who resolved the object |
-| `system` | Boolean! | Indicates whether this note was created by the system or by a user |
-| `systemNoteIconName` | String | Name of the icon corresponding to a system note |
-| `updatedAt` | Time! | Timestamp of the note's last activity |
-| `url` | String | URL to view this Note in the Web UI |
+| `confidential` | Boolean | Indicates if this note is confidential. |
+| `createdAt` | Time! | Timestamp of the note creation. |
+| `discussion` | Discussion | The discussion this note is a part of. |
+| `id` | NoteID! | ID of the note. |
+| `position` | DiffPosition | The position of this note on a diff. |
+| `project` | Project | Project associated with the note. |
+| `resolvable` | Boolean! | Indicates if the object can be resolved. |
+| `resolved` | Boolean! | Indicates if the object is resolved. |
+| `resolvedAt` | Time | Timestamp of when the object was resolved. |
+| `resolvedBy` | User | User who resolved the object. |
+| `system` | Boolean! | Indicates whether this note was created by the system or by a user. |
+| `systemNoteIconName` | String | Name of the icon corresponding to a system note. |
+| `updatedAt` | Time! | Timestamp of the note's last activity. |
+| `url` | String | URL to view this Note in the Web UI. |
| `userPermissions` | NotePermissions! | Permissions for the current user on the resource |
### NotePermissions
@@ -2465,6 +2657,16 @@ Autogenerated return type of OncallRotationCreate.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `oncallRotation` | IncidentManagementOncallRotation | The on-call rotation. |
+### OncallRotationDestroyPayload
+
+Autogenerated return type of OncallRotationDestroy.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `oncallRotation` | IncidentManagementOncallRotation | The on-call rotation. |
+
### OncallScheduleCreatePayload
Autogenerated return type of OncallScheduleCreate.
@@ -2501,34 +2703,17 @@ Represents a package in the Package Registry.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | The created date. |
-| `id` | ID! | The ID of the package. |
-| `name` | String! | The name of the package. |
-| `packageType` | PackageTypeEnum! | The type of the package. |
+| `createdAt` | Time! | Date of creation. |
+| `id` | PackagesPackageID! | ID of the package. |
+| `metadata` | PackageMetadata | Package metadata. |
+| `name` | String! | Name of the package. |
+| `packageType` | PackageTypeEnum! | Package type. |
| `pipelines` | PipelineConnection | Pipelines that built the package. |
| `project` | Project! | Project where the package is stored. |
-| `tags` | PackageTagConnection | The package tags. |
-| `updatedAt` | Time! | The updated date. |
-| `version` | String | The version of the package. |
-| `versions` | PackageConnection | The other versions of the package. |
-
-### PackageComposerDetails
-
-Details of a Composer package.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `composerMetadatum` | PackageComposerMetadatumType! | The Composer metadatum. |
-| `createdAt` | Time! | The created date. |
-| `id` | ID! | The ID of the package. |
-| `name` | String! | The name of the package. |
-| `packageType` | PackageTypeEnum! | The type of the package. |
-| `pipelines` | PipelineConnection | Pipelines that built the package. |
-| `project` | Project! | Project where the package is stored. |
-| `tags` | PackageTagConnection | The package tags. |
-| `updatedAt` | Time! | The updated date. |
-| `version` | String | The version of the package. |
-| `versions` | PackageConnection | The other versions of the package. |
+| `tags` | PackageTagConnection | Package tags. |
+| `updatedAt` | Time! | Date of most recent update. |
+| `version` | String | Version string. |
+| `versions` | PackageWithoutVersionsConnection | The other versions of the package. |
### PackageComposerJsonType
@@ -2541,15 +2726,6 @@ Represents a composer JSON file.
| `type` | String | The type set in the Composer JSON file. |
| `version` | String | The version set in the Composer JSON file. |
-### PackageComposerMetadatumType
-
-Composer metadatum.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `composerJson` | PackageComposerJsonType! | Data of the Composer JSON file. |
-| `targetSha` | String! | Target SHA of the package. |
-
### PackageFileRegistry
Represents the Geo sync and verification state of a package file.
@@ -2560,7 +2736,7 @@ Represents the Geo sync and verification state of a package file.
| `id` | ID! | ID of the PackageFileRegistry |
| `lastSyncFailure` | String | Error message during sync of the PackageFileRegistry |
| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the PackageFileRegistry |
-| `packageFileId` | ID! | ID of the PackageFile |
+| `packageFileId` | ID! | ID of the PackageFile. |
| `retryAt` | Time | Timestamp after which the PackageFileRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the PackageFileRegistry |
| `state` | RegistryState | Sync state of the PackageFileRegistry |
@@ -2585,6 +2761,23 @@ Represents a package tag.
| `name` | String! | The name of the tag. |
| `updatedAt` | Time! | The updated date. |
+### PackageWithoutVersions
+
+Represents a version of a package in the Package Registry.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | Time! | Date of creation. |
+| `id` | PackagesPackageID! | ID of the package. |
+| `metadata` | PackageMetadata | Package metadata. |
+| `name` | String! | Name of the package. |
+| `packageType` | PackageTypeEnum! | Package type. |
+| `pipelines` | PipelineConnection | Pipelines that built the package. |
+| `project` | Project! | Project where the package is stored. |
+| `tags` | PackageTagConnection | Package tags. |
+| `updatedAt` | Time! | Date of most recent update. |
+| `version` | String | Version string. |
+
### PageInfo
Information about pagination in a connection..
@@ -2600,49 +2793,50 @@ Information about pagination in a connection..
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `active` | Boolean! | Indicates if the pipeline is active |
-| `beforeSha` | String | Base SHA of the source branch |
-| `cancelable` | Boolean! | Specifies if a pipeline can be canceled |
-| `committedAt` | Time | Timestamp of the pipeline's commit |
-| `configSource` | PipelineConfigSourceEnum | Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE) |
-| `coverage` | Float | Coverage percentage |
-| `createdAt` | Time! | Timestamp of the pipeline's creation |
-| `detailedStatus` | DetailedStatus! | Detailed status of the pipeline |
-| `downstream` | PipelineConnection | Pipelines this pipeline will trigger |
-| `duration` | Int | Duration of the pipeline in seconds |
-| `finishedAt` | Time | Timestamp of the pipeline's completion |
-| `id` | ID! | ID of the pipeline |
-| `iid` | String! | Internal ID of the pipeline |
-| `jobs` | CiJobConnection | Jobs belonging to the pipeline |
-| `path` | String | Relative path to the pipeline's page |
-| `project` | Project | Project the pipeline belongs to |
-| `retryable` | Boolean! | Specifies if a pipeline can be retried |
-| `securityReportSummary` | SecurityReportSummary | Vulnerability and scanned resource counts for each security scanner of the pipeline |
-| `sha` | String! | SHA of the pipeline's commit |
-| `sourceJob` | CiJob | Job where pipeline was triggered from |
-| `stages` | CiStageConnection | Stages of the pipeline |
-| `startedAt` | Time | Timestamp when the pipeline was started |
+| `active` | Boolean! | Indicates if the pipeline is active. |
+| `beforeSha` | String | Base SHA of the source branch. |
+| `cancelable` | Boolean! | Specifies if a pipeline can be canceled. |
+| `committedAt` | Time | Timestamp of the pipeline's commit. |
+| `configSource` | PipelineConfigSourceEnum | Configuration source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE, COMPLIANCE_SOURCE) |
+| `coverage` | Float | Coverage percentage. |
+| `createdAt` | Time! | Timestamp of the pipeline's creation. |
+| `detailedStatus` | DetailedStatus! | Detailed status of the pipeline. |
+| `downstream` | PipelineConnection | Pipelines this pipeline will trigger. |
+| `duration` | Int | Duration of the pipeline in seconds. |
+| `finishedAt` | Time | Timestamp of the pipeline's completion. |
+| `id` | ID! | ID of the pipeline. |
+| `iid` | String! | Internal ID of the pipeline. |
+| `jobs` | CiJobConnection | Jobs belonging to the pipeline. |
+| `path` | String | Relative path to the pipeline's page. |
+| `project` | Project | Project the pipeline belongs to. |
+| `retryable` | Boolean! | Specifies if a pipeline can be retried. |
+| `securityReportSummary` | SecurityReportSummary | Vulnerability and scanned resource counts for each security scanner of the pipeline. |
+| `sha` | String! | SHA of the pipeline's commit. |
+| `sourceJob` | CiJob | Job where pipeline was triggered from. |
+| `stages` | CiStageConnection | Stages of the pipeline. |
+| `startedAt` | Time | Timestamp when the pipeline was started. |
| `status` | PipelineStatusEnum! | Status of the pipeline (CREATED, WAITING_FOR_RESOURCE, PREPARING, PENDING, RUNNING, FAILED, SUCCESS, CANCELED, SKIPPED, MANUAL, SCHEDULED) |
-| `updatedAt` | Time! | Timestamp of the pipeline's last activity |
-| `upstream` | Pipeline | Pipeline that triggered the pipeline |
-| `user` | User | Pipeline user |
+| `updatedAt` | Time! | Timestamp of the pipeline's last activity. |
+| `upstream` | Pipeline | Pipeline that triggered the pipeline. |
+| `user` | User | Pipeline user. |
| `userPermissions` | PipelinePermissions! | Permissions for the current user on the resource |
+| `warnings` | Boolean! | Indicates if a pipeline has warnings. |
### PipelineAnalytics
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `monthPipelinesLabels` | String! => Array | Labels for the monthly pipeline count |
-| `monthPipelinesSuccessful` | Int! => Array | Total monthly successful pipeline count |
-| `monthPipelinesTotals` | Int! => Array | Total monthly pipeline count |
-| `pipelineTimesLabels` | String! => Array | Pipeline times labels |
-| `pipelineTimesValues` | Int! => Array | Pipeline times |
-| `weekPipelinesLabels` | String! => Array | Labels for the weekly pipeline count |
-| `weekPipelinesSuccessful` | Int! => Array | Total weekly successful pipeline count |
-| `weekPipelinesTotals` | Int! => Array | Total weekly pipeline count |
-| `yearPipelinesLabels` | String! => Array | Labels for the yearly pipeline count |
-| `yearPipelinesSuccessful` | Int! => Array | Total yearly successful pipeline count |
-| `yearPipelinesTotals` | Int! => Array | Total yearly pipeline count |
+| `monthPipelinesLabels` | String! => Array | Labels for the monthly pipeline count. |
+| `monthPipelinesSuccessful` | Int! => Array | Total monthly successful pipeline count. |
+| `monthPipelinesTotals` | Int! => Array | Total monthly pipeline count. |
+| `pipelineTimesLabels` | String! => Array | Pipeline times labels. |
+| `pipelineTimesValues` | Int! => Array | Pipeline times. |
+| `weekPipelinesLabels` | String! => Array | Labels for the weekly pipeline count. |
+| `weekPipelinesSuccessful` | Int! => Array | Total weekly successful pipeline count. |
+| `weekPipelinesTotals` | Int! => Array | Total weekly pipeline count. |
+| `yearPipelinesLabels` | String! => Array | Labels for the yearly pipeline count. |
+| `yearPipelinesSuccessful` | Int! => Array | Total yearly successful pipeline count. |
+| `yearPipelinesTotals` | Int! => Array | Total yearly pipeline count. |
### PipelineCancelPayload
@@ -2684,108 +2878,112 @@ Autogenerated return type of PipelineRetry.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `actualRepositorySizeLimit` | Float | Size limit for the repository in bytes |
-| `alertManagementAlert` | AlertManagementAlert | A single Alert Management alert of the project |
-| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | Counts of alerts by status for the project |
-| `alertManagementAlerts` | AlertManagementAlertConnection | Alert Management alerts of the project |
-| `alertManagementIntegrations` | AlertManagementIntegrationConnection | Integrations which can receive alerts for the project |
-| `allowMergeOnSkippedPipeline` | Boolean | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs |
-| `archived` | Boolean | Indicates the archived status of the project |
-| `autocloseReferencedIssues` | Boolean | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically |
-| `avatarUrl` | String | URL to avatar image file of the project |
-| `board` | Board | A single board of the project |
-| `boards` | BoardConnection | Boards of the project |
-| `ciCdSettings` | ProjectCiCdSetting | CI/CD settings for the project |
-| `clusterAgent` | ClusterAgent | Find a single cluster agent by name |
-| `clusterAgents` | ClusterAgentConnection | Cluster agents associated with the project |
-| `codeCoverageSummary` | CodeCoverageSummary | Code coverage summary associated with the project |
-| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks associated with the project |
-| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy of the project |
-| `containerRegistryEnabled` | Boolean | Indicates if the project stores Docker container images in a container registry |
-| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the project |
-| `containerRepositoriesCount` | Int! | Number of container repositories in the project |
-| `createdAt` | Time | Timestamp of the project creation |
-| `dastScannerProfiles` | DastScannerProfileConnection | The DAST scanner profiles associated with the project |
-| `dastSiteProfile` | DastSiteProfile | DAST Site Profile associated with the project |
-| `dastSiteProfiles` | DastSiteProfileConnection | DAST Site Profiles associated with the project |
-| `dastSiteValidations` | DastSiteValidationConnection | DAST Site Validations associated with the project. Will always return no nodes if `security_on_demand_scans_site_validation` is disabled |
-| `description` | String | Short description of the project |
+| `actualRepositorySizeLimit` | Float | Size limit for the repository in bytes. |
+| `alertManagementAlert` | AlertManagementAlert | A single Alert Management alert of the project. |
+| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | Counts of alerts by status for the project. |
+| `alertManagementAlerts` | AlertManagementAlertConnection | Alert Management alerts of the project. |
+| `alertManagementIntegrations` | AlertManagementIntegrationConnection | Integrations which can receive alerts for the project. |
+| `alertManagementPayloadFields` | AlertManagementPayloadAlertField! => Array | Extract alert fields from payload for custom mapping. |
+| `allowMergeOnSkippedPipeline` | Boolean | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs. |
+| `apiFuzzingCiConfiguration` | ApiFuzzingCiConfiguration | API fuzzing configuration for the project. Available only when feature flag `api_fuzzing_configuration_ui` is enabled. |
+| `archived` | Boolean | Indicates the archived status of the project. |
+| `autocloseReferencedIssues` | Boolean | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically. |
+| `avatarUrl` | String | URL to avatar image file of the project. |
+| `board` | Board | A single board of the project. |
+| `boards` | BoardConnection | Boards of the project. |
+| `ciCdSettings` | ProjectCiCdSetting | CI/CD settings for the project. |
+| `clusterAgent` | ClusterAgent | Find a single cluster agent by name. |
+| `clusterAgents` | ClusterAgentConnection | Cluster agents associated with the project. |
+| `codeCoverageSummary` | CodeCoverageSummary | Code coverage summary associated with the project. |
+| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks associated with the project. |
+| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy of the project. |
+| `containerRegistryEnabled` | Boolean | Indicates if the project stores Docker container images in a container registry. |
+| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the project. |
+| `containerRepositoriesCount` | Int! | Number of container repositories in the project. |
+| `createdAt` | Time | Timestamp of the project creation. |
+| `dastProfiles` | DastProfileConnection | DAST Profiles associated with the project. Always returns no nodes if `dast_saved_scans` is disabled. |
+| `dastScannerProfiles` | DastScannerProfileConnection | The DAST scanner profiles associated with the project. |
+| `dastSiteProfile` | DastSiteProfile | DAST Site Profile associated with the project. |
+| `dastSiteProfiles` | DastSiteProfileConnection | DAST Site Profiles associated with the project. |
+| `dastSiteValidations` | DastSiteValidationConnection | DAST Site Validations associated with the project. Always returns no nodes if `security_on_demand_scans_site_validation` is disabled. |
+| `description` | String | Short description of the project. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `environment` | Environment | A single environment of the project |
-| `environments` | EnvironmentConnection | Environments of the project |
-| `forksCount` | Int! | Number of times the project has been forked |
-| `fullPath` | ID! | Full path of the project |
-| `grafanaIntegration` | GrafanaIntegration | Grafana integration details for the project |
-| `group` | Group | Group of the project |
-| `httpUrlToRepo` | String | URL to connect to the project via HTTPS |
-| `id` | ID! | ID of the project |
-| `importStatus` | String | Status of import background job of the project |
-| `incidentManagementOncallSchedules` | IncidentManagementOncallScheduleConnection | Incident Management On-call schedules of the project |
-| `issue` | Issue | A single issue of the project |
-| `issueStatusCounts` | IssueStatusCountsType | Counts of issues by status for the project |
-| `issues` | IssueConnection | Issues of the project |
+| `environment` | Environment | A single environment of the project. |
+| `environments` | EnvironmentConnection | Environments of the project. |
+| `forksCount` | Int! | Number of times the project has been forked. |
+| `fullPath` | ID! | Full path of the project. |
+| `grafanaIntegration` | GrafanaIntegration | Grafana integration details for the project. |
+| `group` | Group | Group of the project. |
+| `httpUrlToRepo` | String | URL to connect to the project via HTTPS. |
+| `id` | ID! | ID of the project. |
+| `importStatus` | String | Status of import background job of the project. |
+| `incidentManagementOncallSchedules` | IncidentManagementOncallScheduleConnection | Incident Management On-call schedules of the project. |
+| `issue` | Issue | A single issue of the project. |
+| `issueStatusCounts` | IssueStatusCountsType | Counts of issues by status for the project. |
+| `issues` | IssueConnection | Issues of the project. |
| `issuesEnabled` | Boolean | Indicates if Issues are enabled for the current user |
-| `iterations` | IterationConnection | Find iterations |
-| `jiraImportStatus` | String | Status of Jira import background job of the project |
-| `jiraImports` | JiraImportConnection | Jira imports into the project |
-| `jobsEnabled` | Boolean | Indicates if CI/CD pipeline jobs are enabled for the current user |
-| `label` | Label | A label available on this project |
-| `labels` | LabelConnection | Labels available on this project |
-| `lastActivityAt` | Time | Timestamp of the project last activity |
-| `lfsEnabled` | Boolean | Indicates if the project has Large File Storage (LFS) enabled |
-| `mergeRequest` | MergeRequest | A single merge request of the project |
-| `mergeRequests` | MergeRequestConnection | Merge requests of the project |
+| `iterations` | IterationConnection | Find iterations. |
+| `jiraImportStatus` | String | Status of Jira import background job of the project. |
+| `jiraImports` | JiraImportConnection | Jira imports into the project. |
+| `jobsEnabled` | Boolean | Indicates if CI/CD pipeline jobs are enabled for the current user. |
+| `label` | Label | A label available on this project. |
+| `labels` | LabelConnection | Labels available on this project. |
+| `lastActivityAt` | Time | Timestamp of the project last activity. |
+| `lfsEnabled` | Boolean | Indicates if the project has Large File Storage (LFS) enabled. |
+| `mergeRequest` | MergeRequest | A single merge request of the project. |
+| `mergeRequests` | MergeRequestConnection | Merge requests of the project. |
| `mergeRequestsEnabled` | Boolean | Indicates if Merge Requests are enabled for the current user |
| `mergeRequestsFfOnlyEnabled` | Boolean | Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded. |
-| `milestones` | MilestoneConnection | Milestones of the project |
-| `name` | String! | Name of the project (without namespace) |
-| `nameWithNamespace` | String! | Full name of the project with its namespace |
-| `namespace` | Namespace | Namespace of the project |
-| `onlyAllowMergeIfAllDiscussionsAreResolved` | Boolean | Indicates if merge requests of the project can only be merged when all the discussions are resolved |
-| `onlyAllowMergeIfPipelineSucceeds` | Boolean | Indicates if merge requests of the project can only be merged with successful jobs |
-| `openIssuesCount` | Int | Number of open issues for the project |
-| `packages` | PackageConnection | Packages of the project |
-| `path` | String! | Path of the project |
-| `pipeline` | Pipeline | Build pipeline of the project |
-| `pipelineAnalytics` | PipelineAnalytics | Pipeline analytics |
-| `pipelines` | PipelineConnection | Build pipelines of the project |
-| `printingMergeRequestLinkEnabled` | 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 |
-| `projectMembers` | MemberInterfaceConnection | Members of the project |
-| `publicJobs` | Boolean | Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts |
-| `release` | Release | A single release of the project |
-| `releases` | ReleaseConnection | Releases of the project |
-| `removeSourceBranchAfterMerge` | Boolean | Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project |
-| `repository` | Repository | Git repository of the project |
-| `repositorySizeExcess` | Float | Size of repository that exceeds the limit in bytes |
-| `requestAccessEnabled` | Boolean | Indicates if users can request member access to the project |
-| `requirement` | Requirement | Find a single requirement |
-| `requirementStatesCount` | RequirementStatesCount | Number of requirements for the project by their state |
-| `requirements` | RequirementConnection | Find requirements |
-| `sastCiConfiguration` | SastCiConfiguration | SAST CI configuration for the project |
-| `securityDashboardPath` | String | Path to project's security dashboard |
-| `securityScanners` | SecurityScanners | Information about security analyzers used in the project |
-| `sentryDetailedError` | SentryDetailedError | Detailed version of a Sentry error on the project |
-| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project |
+| `milestones` | MilestoneConnection | Milestones of the project. |
+| `name` | String! | Name of the project (without namespace). |
+| `nameWithNamespace` | String! | Full name of the project with its namespace. |
+| `namespace` | Namespace | Namespace of the project. |
+| `onlyAllowMergeIfAllDiscussionsAreResolved` | Boolean | Indicates if merge requests of the project can only be merged when all the discussions are resolved. |
+| `onlyAllowMergeIfPipelineSucceeds` | Boolean | Indicates if merge requests of the project can only be merged with successful jobs. |
+| `openIssuesCount` | Int | Number of open issues for the project. |
+| `packages` | PackageConnection | Packages of the project. |
+| `path` | String! | Path of the project. |
+| `pipeline` | Pipeline | Build pipeline of the project. |
+| `pipelineAnalytics` | PipelineAnalytics | Pipeline analytics. |
+| `pipelines` | PipelineConnection | Build pipelines of the project. |
+| `printingMergeRequestLinkEnabled` | 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. |
+| `projectMembers` | MemberInterfaceConnection | Members of the project. |
+| `publicJobs` | Boolean | Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts. |
+| `release` | Release | A single release of the project. |
+| `releases` | ReleaseConnection | Releases of the project. |
+| `removeSourceBranchAfterMerge` | Boolean | Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project. |
+| `repository` | Repository | Git repository of the project. |
+| `repositorySizeExcess` | Float | Size of repository that exceeds the limit in bytes. |
+| `requestAccessEnabled` | Boolean | Indicates if users can request member access to the project. |
+| `requirement` | Requirement | Find a single requirement. |
+| `requirementStatesCount` | RequirementStatesCount | Number of requirements for the project by their state. |
+| `requirements` | RequirementConnection | Find requirements. |
+| `sastCiConfiguration` | SastCiConfiguration | SAST CI configuration for the project. |
+| `securityDashboardPath` | String | Path to project's security dashboard. |
+| `securityScanners` | SecurityScanners | Information about security analyzers used in the project. |
+| `sentryDetailedError` | SentryDetailedError | Detailed version of a Sentry error on the project. |
+| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project. |
| `serviceDeskAddress` | String | E-mail address of the service desk. |
| `serviceDeskEnabled` | Boolean | Indicates if the project has service desk enabled. |
-| `services` | ServiceConnection | Project services |
-| `sharedRunnersEnabled` | Boolean | Indicates if shared runners are enabled for the project |
-| `snippets` | SnippetConnection | Snippets of the project |
+| `services` | ServiceConnection | Project services. |
+| `sharedRunnersEnabled` | Boolean | Indicates if shared runners are enabled for the project. |
+| `snippets` | SnippetConnection | Snippets of the project. |
| `snippetsEnabled` | Boolean | Indicates if Snippets are enabled for the current user |
-| `squashReadOnly` | Boolean! | Indicates if squash readonly is enabled |
-| `sshUrlToRepo` | String | URL to connect to the project via SSH |
-| `starCount` | Int! | Number of times the project has been starred |
-| `statistics` | ProjectStatistics | Statistics of the project |
-| `suggestionCommitMessage` | String | The commit message used to apply merge request suggestions |
-| `tagList` | String | List of project topics (not Git tags) |
-| `terraformStates` | TerraformStateConnection | Terraform states associated with the project |
+| `squashReadOnly` | Boolean! | Indicates if `squashReadOnly` is enabled. |
+| `sshUrlToRepo` | String | URL to connect to the project via SSH. |
+| `starCount` | Int! | Number of times the project has been starred. |
+| `statistics` | ProjectStatistics | Statistics of the project. |
+| `suggestionCommitMessage` | String | The commit message used to apply merge request suggestions. |
+| `tagList` | String | List of project topics (not Git tags). |
+| `terraformState` | TerraformState | Find a single Terraform state by name. |
+| `terraformStates` | TerraformStateConnection | Terraform states associated with the project. |
| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource |
-| `visibility` | String | Visibility of the project |
-| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the project |
-| `vulnerabilitiesCountByDay` | VulnerabilitiesCountByDayConnection | Number of vulnerabilities per day for the project |
-| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the project vulnerabilties |
-| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the project |
-| `webUrl` | String | Web URL of the project |
+| `visibility` | String | Visibility of the project. |
+| `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the project. |
+| `vulnerabilitiesCountByDay` | VulnerabilitiesCountByDayConnection | Number of vulnerabilities per day for the project. |
+| `vulnerabilityScanners` | VulnerabilityScannerConnection | Vulnerability scanners reported on the project vulnerabilities. |
+| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the project. |
+| `webUrl` | String | Web URL of the project. |
| `wikiEnabled` | Boolean | Indicates if Wikis are enabled for the current user |
### ProjectCiCdSetting
@@ -2803,14 +3001,14 @@ Represents a Project Membership.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `accessLevel` | AccessLevel | GitLab::Access level |
-| `createdAt` | Time | Date and time the membership was created |
-| `createdBy` | User | User that authorized membership |
-| `expiresAt` | Time | Date and time the membership expires |
-| `id` | ID! | ID of the member |
-| `project` | Project | Project that User is a member of |
-| `updatedAt` | Time | Date and time the membership was last updated |
-| `user` | User! | User that is associated with the member object |
+| `accessLevel` | AccessLevel | GitLab::Access level. |
+| `createdAt` | Time | Date and time the membership was created. |
+| `createdBy` | User | User that authorized membership. |
+| `expiresAt` | Time | Date and time the membership expires. |
+| `id` | ID! | ID of the member. |
+| `project` | Project | Project that User is a member of. |
+| `updatedAt` | Time | Date and time the membership was last updated. |
+| `user` | User! | User that is associated with the member object. |
| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource |
### ProjectPermissions
@@ -2864,15 +3062,15 @@ Represents a Project Membership.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `buildArtifactsSize` | Float! | Build artifacts size of the project in bytes |
-| `commitCount` | Float! | Commit count of the project |
-| `lfsObjectsSize` | Float! | Large File Storage (LFS) object size of the project in bytes |
-| `packagesSize` | Float! | Packages size of the project in bytes |
-| `repositorySize` | Float! | Repository size of the project in bytes |
-| `snippetsSize` | Float | Snippets size of the project in bytes |
-| `storageSize` | Float! | Storage size of the project in bytes |
-| `uploadsSize` | Float | Uploads size of the project in bytes |
-| `wikiSize` | Float | Wiki size of the project in bytes |
+| `buildArtifactsSize` | Float! | Build artifacts size of the project in bytes. |
+| `commitCount` | Float! | Commit count of the project. |
+| `lfsObjectsSize` | Float! | Large File Storage (LFS) object size of the project in bytes. |
+| `packagesSize` | Float! | Packages size of the project in bytes. |
+| `repositorySize` | Float! | Repository size of the project in bytes. |
+| `snippetsSize` | Float | Snippets size of the project in bytes. |
+| `storageSize` | Float! | Storage size of the project in bytes. |
+| `uploadsSize` | Float | Uploads size of the project in bytes. |
+| `wikiSize` | Float | Wiki size of the project in bytes. |
### PrometheusAlert
@@ -2880,8 +3078,8 @@ The alert condition for Prometheus.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `humanizedText` | String! | The human-readable text of the alert condition |
-| `id` | ID! | ID of the alert condition |
+| `humanizedText` | String! | The human-readable text of the alert condition. |
+| `id` | ID! | ID of the alert condition. |
### PrometheusIntegrationCreatePayload
@@ -2930,20 +3128,20 @@ Represents a release.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `assets` | ReleaseAssets | Assets of the release |
-| `author` | User | User that created the release |
-| `commit` | Commit | The commit associated with the release |
-| `createdAt` | Time | Timestamp of when the release was created |
-| `description` | String | Description (also known as "release notes") of the release |
+| `assets` | ReleaseAssets | Assets of the release. |
+| `author` | User | User that created the release. |
+| `commit` | Commit | The commit associated with the release. |
+| `createdAt` | Time | Timestamp of when the release was created. |
+| `description` | String | Description (also known as "release notes") of the release. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `evidences` | ReleaseEvidenceConnection | Evidence for the release |
-| `links` | ReleaseLinks | Links of the release |
-| `milestones` | MilestoneConnection | Milestones associated to the release |
-| `name` | String | Name of the release |
-| `releasedAt` | Time | Timestamp of when the release was released |
-| `tagName` | String | Name of the tag associated with the release |
-| `tagPath` | String | Relative web path to the tag associated with the release |
-| `upcomingRelease` | Boolean | Indicates the release is an upcoming release |
+| `evidences` | ReleaseEvidenceConnection | Evidence for the release. |
+| `links` | ReleaseLinks | Links of the release. |
+| `milestones` | MilestoneConnection | Milestones associated to the release. |
+| `name` | String | Name of the release. |
+| `releasedAt` | Time | Timestamp of when the release was released. |
+| `tagName` | String | Name of the tag associated with the release. |
+| `tagPath` | String | Relative web path to the tag associated with the release. |
+| `upcomingRelease` | Boolean | Indicates the release is an upcoming release. |
### ReleaseAssetLink
@@ -2951,12 +3149,12 @@ Represents an asset link associated with a release.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `directAssetUrl` | String | Direct asset URL of the link |
-| `external` | Boolean | Indicates the link points to an external resource |
-| `id` | ID! | ID of the link |
-| `linkType` | ReleaseAssetLinkType | Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other` |
-| `name` | String | Name of the link |
-| `url` | String | URL of the link |
+| `directAssetUrl` | String | Direct asset URL of the link. |
+| `external` | Boolean | Indicates the link points to an external resource. |
+| `id` | ID! | ID of the link. |
+| `linkType` | ReleaseAssetLinkType | Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`. |
+| `name` | String | Name of the link. |
+| `url` | String | URL of the link. |
### ReleaseAssets
@@ -2964,9 +3162,9 @@ A container for all assets associated with a release.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int | Number of assets of the release |
-| `links` | ReleaseAssetLinkConnection | Asset links of the release |
-| `sources` | ReleaseSourceConnection | Sources of the release |
+| `count` | Int | Number of assets of the release. |
+| `links` | ReleaseAssetLinkConnection | Asset links of the release. |
+| `sources` | ReleaseSourceConnection | Sources of the release. |
### ReleaseCreatePayload
@@ -2994,22 +3192,22 @@ Evidence for a release.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `collectedAt` | Time | Timestamp when the evidence was collected |
-| `filepath` | String | URL from where the evidence can be downloaded |
-| `id` | ID! | ID of the evidence |
-| `sha` | String | SHA1 ID of the evidence hash |
+| `collectedAt` | Time | Timestamp when the evidence was collected. |
+| `filepath` | String | URL from where the evidence can be downloaded. |
+| `id` | ID! | ID of the evidence. |
+| `sha` | String | SHA1 ID of the evidence hash. |
### ReleaseLinks
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `closedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=closed` |
-| `closedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=closed` |
-| `editUrl` | String | HTTP URL of the release's edit page |
-| `mergedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=merged` |
-| `openedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=open` |
-| `openedMergeRequestsUrl` | String | HTTP URL of the merge request page, filtered by this release and `state=open` |
-| `selfUrl` | String | HTTP URL of the release |
+| `closedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=closed`. |
+| `closedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=closed`. |
+| `editUrl` | String | HTTP URL of the release's edit page. |
+| `mergedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=merged`. |
+| `openedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=open`. |
+| `openedMergeRequestsUrl` | String | HTTP URL of the merge request page, filtered by this release and `state=open`. |
+| `selfUrl` | String | HTTP URL of the release. |
### ReleaseSource
@@ -3017,8 +3215,8 @@ Represents the source code attached to a release in a particular format.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `format` | String | Format of the source |
-| `url` | String | Download URL of the source |
+| `format` | String | Format of the source. |
+| `url` | String | Download URL of the source. |
### ReleaseUpdatePayload
@@ -3063,10 +3261,10 @@ Autogenerated return type of RepositionImageDiffNote.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `empty` | Boolean! | Indicates repository has no visible content |
-| `exists` | Boolean! | Indicates a corresponding Git repository exists on disk |
-| `rootRef` | String | Default branch of the repository |
-| `tree` | Tree | Tree of the repository |
+| `empty` | Boolean! | Indicates repository has no visible content. |
+| `exists` | Boolean! | Indicates a corresponding Git repository exists on disk. |
+| `rootRef` | String | Default branch of the repository. |
+| `tree` | Tree | Tree of the repository. |
### Requirement
@@ -3074,20 +3272,20 @@ Represents a requirement.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User! | Author of the requirement |
-| `createdAt` | Time! | Timestamp of when the requirement was created |
-| `description` | String | Description of the requirement |
+| `author` | User! | Author of the requirement. |
+| `createdAt` | Time! | Timestamp of when the requirement was created. |
+| `description` | String | Description of the requirement. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `id` | ID! | ID of the requirement |
-| `iid` | ID! | Internal ID of the requirement |
-| `lastTestReportManuallyCreated` | Boolean | Indicates if latest test report was created by user |
-| `lastTestReportState` | TestReportState | Latest requirement test report state |
-| `project` | Project! | Project to which the requirement belongs |
-| `state` | RequirementState! | State of the requirement |
-| `testReports` | TestReportConnection | Test reports of the requirement |
-| `title` | String | Title of the requirement |
+| `id` | ID! | ID of the requirement. |
+| `iid` | ID! | Internal ID of the requirement. |
+| `lastTestReportManuallyCreated` | Boolean | Indicates if latest test report was created by user. |
+| `lastTestReportState` | TestReportState | Latest requirement test report state. |
+| `project` | Project! | Project to which the requirement belongs. |
+| `state` | RequirementState! | State of the requirement. |
+| `testReports` | TestReportConnection | Test reports of the requirement. |
+| `title` | String | Title of the requirement. |
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
-| `updatedAt` | Time! | Timestamp of when the requirement was last updated |
+| `updatedAt` | Time! | Timestamp of when the requirement was last updated. |
| `userPermissions` | RequirementPermissions! | Permissions for the current user on the resource |
### RequirementPermissions
@@ -3108,8 +3306,8 @@ Counts of requirements by their state.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `archived` | Int | Number of archived requirements |
-| `opened` | Int | Number of opened requirements |
+| `archived` | Int | Number of archived requirements. |
+| `opened` | Int | Number of opened requirements. |
### RevertVulnerabilityToDetectedPayload
@@ -3125,15 +3323,15 @@ Autogenerated return type of RevertVulnerabilityToDetected.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `buildArtifactsSize` | Float! | The CI artifacts size in bytes |
-| `lfsObjectsSize` | Float! | The LFS objects size in bytes |
-| `packagesSize` | Float! | The packages size in bytes |
-| `pipelineArtifactsSize` | Float! | The CI pipeline artifacts size in bytes |
-| `repositorySize` | Float! | The Git repository size in bytes |
-| `snippetsSize` | Float! | The snippets size in bytes |
-| `storageSize` | Float! | The total storage in bytes |
-| `uploadsSize` | Float! | The uploads size in bytes |
-| `wikiSize` | Float! | The wiki size in bytes |
+| `buildArtifactsSize` | Float! | The CI artifacts size in bytes. |
+| `lfsObjectsSize` | Float! | The LFS objects size in bytes. |
+| `packagesSize` | Float! | The packages size in bytes. |
+| `pipelineArtifactsSize` | Float! | The CI pipeline artifacts size in bytes. |
+| `repositorySize` | Float! | The Git repository size in bytes. |
+| `snippetsSize` | Float! | The snippets size in bytes. |
+| `storageSize` | Float! | The total storage in bytes. |
+| `uploadsSize` | Float! | The uploads size in bytes. |
+| `wikiSize` | Float! | The wiki size in bytes. |
### RunDASTScanPayload
@@ -3149,23 +3347,23 @@ Autogenerated return type of RunDASTScan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `downloadLocation` | String! | Download location for the runner for the platform architecture |
-| `name` | String! | Name of the runner platform architecture |
+| `downloadLocation` | String! | Download location for the runner for the platform architecture. |
+| `name` | String! | Name of the runner platform architecture. |
### RunnerPlatform
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `architectures` | RunnerArchitectureConnection | Runner architectures supported for the platform |
-| `humanReadableName` | String! | Human readable name of the runner platform |
-| `name` | String! | Name slug of the runner platform |
+| `architectures` | RunnerArchitectureConnection | Runner architectures supported for the platform. |
+| `humanReadableName` | String! | Human readable name of the runner platform. |
+| `name` | String! | Name slug of the runner platform. |
### RunnerSetup
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `installInstructions` | String! | Instructions for installing the runner on the specified architecture |
-| `registerInstructions` | String | Instructions for registering the runner |
+| `installInstructions` | String! | Instructions for installing the runner on the specified architecture. |
+| `registerInstructions` | String | Instructions for registering the runner. |
### SastCiConfiguration
@@ -3183,11 +3381,11 @@ Represents an analyzer entity in SAST CI configuration.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `description` | String | Analyzer description that is displayed on the form |
-| `enabled` | Boolean | Indicates whether an analyzer is enabled |
-| `label` | String | Analyzer label used in the config UI |
-| `name` | String | Name of the analyzer |
-| `variables` | SastCiConfigurationEntityConnection | List of supported variables |
+| `description` | String | Analyzer description that is displayed on the form. |
+| `enabled` | Boolean | Indicates whether an analyzer is enabled. |
+| `label` | String | Analyzer label used in the config UI. |
+| `name` | String | Name of the analyzer. |
+| `variables` | SastCiConfigurationEntityConnection | List of supported variables. |
### SastCiConfigurationEntity
@@ -3219,8 +3417,8 @@ Represents a resource scanned by a security scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `requestMethod` | String | The HTTP request method used to access the URL |
-| `url` | String | The URL scanned by the scanner |
+| `requestMethod` | String | The HTTP request method used to access the URL. |
+| `url` | String | The URL scanned by the scanner. |
### SecurityReportSummary
@@ -3228,13 +3426,13 @@ Represents summary of a security report.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `apiFuzzing` | SecurityReportSummarySection | Aggregated counts for the api_fuzzing scan |
-| `containerScanning` | SecurityReportSummarySection | Aggregated counts for the container_scanning scan |
-| `coverageFuzzing` | SecurityReportSummarySection | Aggregated counts for the coverage_fuzzing scan |
-| `dast` | SecurityReportSummarySection | Aggregated counts for the dast scan |
-| `dependencyScanning` | SecurityReportSummarySection | Aggregated counts for the dependency_scanning scan |
-| `sast` | SecurityReportSummarySection | Aggregated counts for the sast scan |
-| `secretDetection` | SecurityReportSummarySection | Aggregated counts for the secret_detection scan |
+| `apiFuzzing` | SecurityReportSummarySection | Aggregated counts for the `api_fuzzing` scan |
+| `containerScanning` | SecurityReportSummarySection | Aggregated counts for the `container_scanning` scan |
+| `coverageFuzzing` | SecurityReportSummarySection | Aggregated counts for the `coverage_fuzzing` scan |
+| `dast` | SecurityReportSummarySection | Aggregated counts for the `dast` scan |
+| `dependencyScanning` | SecurityReportSummarySection | Aggregated counts for the `dependency_scanning` scan |
+| `sast` | SecurityReportSummarySection | Aggregated counts for the `sast` scan |
+| `secretDetection` | SecurityReportSummarySection | Aggregated counts for the `secret_detection` scan |
### SecurityReportSummarySection
@@ -3242,10 +3440,10 @@ Represents a section of a summary of a security report.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `scannedResources` | ScannedResourceConnection | A list of the first 20 scanned resources |
-| `scannedResourcesCount` | Int | Total number of scanned resources |
-| `scannedResourcesCsvPath` | String | Path to download all the scanned resources in CSV format |
-| `vulnerabilitiesCount` | Int | Total number of vulnerabilities |
+| `scannedResources` | ScannedResourceConnection | A list of the first 20 scanned resources. |
+| `scannedResourcesCount` | Int | Total number of scanned resources. |
+| `scannedResourcesCsvPath` | String | Path to download all the scanned resources in CSV format. |
+| `vulnerabilitiesCount` | Int | Total number of vulnerabilities. |
### SecurityScanners
@@ -3263,34 +3461,34 @@ A Sentry error.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int! | Count of occurrences |
-| `culprit` | String! | Culprit of the error |
-| `externalBaseUrl` | String! | External Base URL of the Sentry Instance |
-| `externalUrl` | String! | External URL of the error |
-| `firstReleaseLastCommit` | String | Commit the error was first seen |
-| `firstReleaseShortVersion` | String | Release short version the error was first seen |
-| `firstReleaseVersion` | String | Release version the error was first seen |
-| `firstSeen` | Time! | Timestamp when the error was first seen |
-| `frequency` | SentryErrorFrequency! => Array | Last 24hr stats of the error |
-| `gitlabCommit` | String | GitLab commit SHA attributed to the Error based on the release version |
-| `gitlabCommitPath` | String | Path to the GitLab page for the GitLab commit attributed to the error |
-| `gitlabIssuePath` | String | URL of GitLab Issue |
-| `id` | ID! | ID (global ID) of the error |
-| `lastReleaseLastCommit` | String | Commit the error was last seen |
-| `lastReleaseShortVersion` | String | Release short version the error was last seen |
-| `lastReleaseVersion` | String | Release version the error was last seen |
-| `lastSeen` | Time! | Timestamp when the error was last seen |
-| `message` | String | Sentry metadata message of the error |
-| `sentryId` | String! | ID (Sentry ID) of the error |
-| `sentryProjectId` | ID! | ID of the project (Sentry project) |
-| `sentryProjectName` | String! | Name of the project affected by the error |
-| `sentryProjectSlug` | String! | Slug of the project affected by the error |
-| `shortId` | String! | Short ID (Sentry ID) of the error |
-| `status` | SentryErrorStatus! | Status of the error |
-| `tags` | SentryErrorTags! | Tags associated with the Sentry Error |
-| `title` | String! | Title of the error |
-| `type` | String! | Type of the error |
-| `userCount` | Int! | Count of users affected by the error |
+| `count` | Int! | Count of occurrences. |
+| `culprit` | String! | Culprit of the error. |
+| `externalBaseUrl` | String! | External Base URL of the Sentry Instance. |
+| `externalUrl` | String! | External URL of the error. |
+| `firstReleaseLastCommit` | String | Commit the error was first seen. |
+| `firstReleaseShortVersion` | String | Release short version the error was first seen. |
+| `firstReleaseVersion` | String | Release version the error was first seen. |
+| `firstSeen` | Time! | Timestamp when the error was first seen. |
+| `frequency` | SentryErrorFrequency! => Array | Last 24hr stats of the error. |
+| `gitlabCommit` | String | GitLab commit SHA attributed to the Error based on the release version. |
+| `gitlabCommitPath` | String | Path to the GitLab page for the GitLab commit attributed to the error. |
+| `gitlabIssuePath` | String | URL of GitLab Issue. |
+| `id` | ID! | ID (global ID) of the error. |
+| `lastReleaseLastCommit` | String | Commit the error was last seen. |
+| `lastReleaseShortVersion` | String | Release short version the error was last seen. |
+| `lastReleaseVersion` | String | Release version the error was last seen. |
+| `lastSeen` | Time! | Timestamp when the error was last seen. |
+| `message` | String | Sentry metadata message of the error. |
+| `sentryId` | String! | ID (Sentry ID) of the error. |
+| `sentryProjectId` | ID! | ID of the project (Sentry project). |
+| `sentryProjectName` | String! | Name of the project affected by the error. |
+| `sentryProjectSlug` | String! | Slug of the project affected by the error. |
+| `shortId` | String! | Short ID (Sentry ID) of the error. |
+| `status` | SentryErrorStatus! | Status of the error. |
+| `tags` | SentryErrorTags! | Tags associated with the Sentry Error. |
+| `title` | String! | Title of the error. |
+| `type` | String! | Type of the error. |
+| `userCount` | Int! | Count of users affected by the error. |
### SentryError
@@ -3298,23 +3496,23 @@ A Sentry error. A simplified version of SentryDetailedError.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int! | Count of occurrences |
-| `culprit` | String! | Culprit of the error |
-| `externalUrl` | String! | External URL of the error |
-| `firstSeen` | Time! | Timestamp when the error was first seen |
-| `frequency` | SentryErrorFrequency! => Array | Last 24hr stats of the error |
-| `id` | ID! | ID (global ID) of the error |
-| `lastSeen` | Time! | Timestamp when the error was last seen |
-| `message` | String | Sentry metadata message of the error |
-| `sentryId` | String! | ID (Sentry ID) of the error |
-| `sentryProjectId` | ID! | ID of the project (Sentry project) |
-| `sentryProjectName` | String! | Name of the project affected by the error |
-| `sentryProjectSlug` | String! | Slug of the project affected by the error |
-| `shortId` | String! | Short ID (Sentry ID) of the error |
-| `status` | SentryErrorStatus! | Status of the error |
-| `title` | String! | Title of the error |
-| `type` | String! | Type of the error |
-| `userCount` | Int! | Count of users affected by the error |
+| `count` | Int! | Count of occurrences. |
+| `culprit` | String! | Culprit of the error. |
+| `externalUrl` | String! | External URL of the error. |
+| `firstSeen` | Time! | Timestamp when the error was first seen. |
+| `frequency` | SentryErrorFrequency! => Array | Last 24hr stats of the error. |
+| `id` | ID! | ID (global ID) of the error. |
+| `lastSeen` | Time! | Timestamp when the error was last seen. |
+| `message` | String | Sentry metadata message of the error. |
+| `sentryId` | String! | ID (Sentry ID) of the error. |
+| `sentryProjectId` | ID! | ID of the project (Sentry project). |
+| `sentryProjectName` | String! | Name of the project affected by the error. |
+| `sentryProjectSlug` | String! | Slug of the project affected by the error. |
+| `shortId` | String! | Short ID (Sentry ID) of the error. |
+| `status` | SentryErrorStatus! | Status of the error. |
+| `title` | String! | Title of the error. |
+| `type` | String! | Type of the error. |
+| `userCount` | Int! | Count of users affected by the error. |
### SentryErrorCollection
@@ -3322,17 +3520,17 @@ An object containing a collection of Sentry errors, and a detailed error.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `detailedError` | SentryDetailedError | Detailed version of a Sentry error on the project |
-| `errorStackTrace` | SentryErrorStackTrace | Stack Trace of Sentry Error |
-| `errors` | SentryErrorConnection | Collection of Sentry Errors |
-| `externalUrl` | String | External URL for Sentry |
+| `detailedError` | SentryDetailedError | Detailed version of a Sentry error on the project. |
+| `errorStackTrace` | SentryErrorStackTrace | Stack Trace of Sentry Error. |
+| `errors` | SentryErrorConnection | Collection of Sentry Errors. |
+| `externalUrl` | String | External URL for Sentry. |
### SentryErrorFrequency
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int! | Count of errors received since the previously recorded time |
-| `time` | Time! | Time the error frequency stats were recorded |
+| `count` | Int! | Count of errors received since the previously recorded time. |
+| `time` | Time! | Time the error frequency stats were recorded. |
### SentryErrorStackTrace
@@ -3340,9 +3538,9 @@ An object containing a stack trace entry for a Sentry error.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `dateReceived` | String! | Time the stack trace was received by Sentry |
-| `issueId` | String! | ID of the Sentry error |
-| `stackTraceEntries` | SentryErrorStackTraceEntry! => Array | Stack trace entries for the Sentry error |
+| `dateReceived` | String! | Time the stack trace was received by Sentry. |
+| `issueId` | String! | ID of the Sentry error. |
+| `stackTraceEntries` | SentryErrorStackTraceEntry! => Array | Stack trace entries for the Sentry error. |
### SentryErrorStackTraceContext
@@ -3350,8 +3548,8 @@ An object context for a Sentry error stack trace.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `code` | String! | Code number of the context |
-| `line` | Int! | Line number of the context |
+| `code` | String! | Code number of the context. |
+| `line` | Int! | Line number of the context. |
### SentryErrorStackTraceEntry
@@ -3359,11 +3557,11 @@ An object containing a stack trace entry for a Sentry error.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `col` | String | Function in which the Sentry error occurred |
-| `fileName` | String | File in which the Sentry error occurred |
-| `function` | String | Function in which the Sentry error occurred |
-| `line` | String | Function in which the Sentry error occurred |
-| `traceContext` | SentryErrorStackTraceContext! => Array | Context of the Sentry error |
+| `col` | String | Function in which the Sentry error occurred. |
+| `fileName` | String | File in which the Sentry error occurred. |
+| `function` | String | Function in which the Sentry error occurred. |
+| `line` | String | Function in which the Sentry error occurred. |
+| `traceContext` | SentryErrorStackTraceContext! => Array | Context of the Sentry error. |
### SentryErrorTags
@@ -3371,8 +3569,8 @@ State of a Sentry error.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `level` | String | Severity level of the Sentry Error |
-| `logger` | String | Logger of the Sentry Error |
+| `level` | String | Severity level of the Sentry Error. |
+| `logger` | String | Logger of the Sentry Error. |
### Snippet
@@ -3380,25 +3578,25 @@ Represents a snippet entry.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User | The owner of the snippet |
+| `author` | User | The owner of the snippet. |
| `blob` **{warning-solid}** | SnippetBlob! | **Deprecated:** Use `blobs`. Deprecated in 13.3. |
-| `blobs` | SnippetBlobConnection | Snippet blobs |
-| `createdAt` | Time! | Timestamp this snippet was created |
-| `description` | String | Description of the snippet |
+| `blobs` | SnippetBlobConnection | Snippet blobs. |
+| `createdAt` | Time! | Timestamp this snippet was created. |
+| `description` | String | Description of the snippet. |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `fileName` | String | File Name of the snippet |
-| `httpUrlToRepo` | String | HTTP URL to the snippet repository |
-| `id` | SnippetID! | ID of the snippet |
-| `notes` | NoteConnection! | All notes on this noteable |
-| `project` | Project | The project the snippet is associated with |
-| `rawUrl` | String! | Raw URL of the snippet |
-| `sshUrlToRepo` | String | SSH URL to the snippet repository |
-| `title` | String! | Title of the snippet |
-| `updatedAt` | Time! | Timestamp this snippet was updated |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `fileName` | String | File Name of the snippet. |
+| `httpUrlToRepo` | String | HTTP URL to the snippet repository. |
+| `id` | SnippetID! | ID of the snippet. |
+| `notes` | NoteConnection! | All notes on this noteable. |
+| `project` | Project | The project the snippet is associated with. |
+| `rawUrl` | String! | Raw URL of the snippet. |
+| `sshUrlToRepo` | String | SSH URL to the snippet repository. |
+| `title` | String! | Title of the snippet. |
+| `updatedAt` | Time! | Timestamp this snippet was updated. |
| `userPermissions` | SnippetPermissions! | Permissions for the current user on the resource |
-| `visibilityLevel` | VisibilityLevelsEnum! | Visibility Level of the snippet |
-| `webUrl` | String! | Web URL of the snippet |
+| `visibilityLevel` | VisibilityLevelsEnum! | Visibility Level of the snippet. |
+| `webUrl` | String! | Web URL of the snippet. |
### SnippetBlob
@@ -3406,18 +3604,18 @@ Represents the snippet blob.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `binary` | Boolean! | Shows whether the blob is binary |
-| `externalStorage` | String | Blob external storage |
-| `mode` | String | Blob mode |
-| `name` | String | Blob name |
-| `path` | String | Blob path |
-| `plainData` | String | Blob plain highlighted data |
-| `rawPath` | String! | Blob raw content endpoint path |
-| `renderedAsText` | Boolean! | Shows whether the blob is rendered as text |
-| `richData` | String | Blob highlighted data |
-| `richViewer` | SnippetBlobViewer | Blob content rich viewer |
-| `simpleViewer` | SnippetBlobViewer! | Blob content simple viewer |
-| `size` | Int! | Blob size |
+| `binary` | Boolean! | Shows whether the blob is binary. |
+| `externalStorage` | String | Blob external storage. |
+| `mode` | String | Blob mode. |
+| `name` | String | Blob name. |
+| `path` | String | Blob path. |
+| `plainData` | String | Blob plain highlighted data. |
+| `rawPath` | String! | Blob raw content endpoint path. |
+| `renderedAsText` | Boolean! | Shows whether the blob is rendered as text. |
+| `richData` | String | Blob highlighted data. |
+| `richViewer` | SnippetBlobViewer | Blob content rich viewer. |
+| `simpleViewer` | SnippetBlobViewer! | Blob content simple viewer. |
+| `size` | Int! | Blob size. |
### SnippetBlobViewer
@@ -3425,13 +3623,13 @@ Represents how the blob content should be displayed.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `collapsed` | Boolean! | Shows whether the blob should be displayed collapsed |
-| `fileType` | String! | Content file type |
-| `loadAsync` | Boolean! | Shows whether the blob content is loaded async |
-| `loadingPartialName` | String! | Loading partial name |
-| `renderError` | String | Error rendering the blob content |
-| `tooLarge` | Boolean! | Shows whether the blob too large to be displayed |
-| `type` | BlobViewersType! | Type of blob viewer |
+| `collapsed` | Boolean! | Shows whether the blob should be displayed collapsed. |
+| `fileType` | String! | Content file type. |
+| `loadAsync` | Boolean! | Shows whether the blob content is loaded asynchronously. |
+| `loadingPartialName` | String! | Loading partial name. |
+| `renderError` | String | Error rendering the blob content. |
+| `tooLarge` | Boolean! | Shows whether the blob too large to be displayed. |
+| `type` | BlobViewersType! | Type of blob viewer. |
### SnippetPermissions
@@ -3456,31 +3654,31 @@ Represents the Geo sync and verification state of a snippet repository.
| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the SnippetRepositoryRegistry |
| `retryAt` | Time | Timestamp after which the SnippetRepositoryRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the SnippetRepositoryRegistry |
-| `snippetRepositoryId` | ID! | ID of the Snippet Repository |
+| `snippetRepositoryId` | ID! | ID of the Snippet Repository. |
| `state` | RegistryState | Sync state of the SnippetRepositoryRegistry |
### StatusAction
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `buttonTitle` | String | Title for the button, for example: Retry this job |
-| `icon` | String | Icon used in the action button |
-| `method` | String | Method for the action, for example: :post |
-| `path` | String | Path for the action |
-| `title` | String | Title for the action, for example: Retry |
+| `buttonTitle` | String | Title for the button, for example: Retry this job. |
+| `icon` | String | Icon used in the action button. |
+| `method` | String | Method for the action, for example: :post. |
+| `path` | String | Path for the action. |
+| `title` | String | Title for the action, for example: Retry. |
### Submodule
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `flatPath` | String! | Flat path of the entry |
-| `id` | ID! | ID of the entry |
-| `name` | String! | Name of the entry |
-| `path` | String! | Path of the entry |
-| `sha` | String! | Last commit sha for the entry |
-| `treeUrl` | String | Tree URL for the sub-module |
-| `type` | EntryType! | Type of tree entry |
-| `webUrl` | String | Web URL for the sub-module |
+| `flatPath` | String! | Flat path of the entry. |
+| `id` | ID! | ID of the entry. |
+| `name` | String! | Name of the entry. |
+| `path` | String! | Path of the entry. |
+| `sha` | String! | Last commit SHA for the entry. |
+| `treeUrl` | String | Tree URL for the sub-module. |
+| `type` | EntryType! | Type of tree entry. |
+| `webUrl` | String | Web URL for the sub-module. |
### TaskCompletionStatus
@@ -3488,20 +3686,20 @@ Completion status of tasks.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `completedCount` | Int! | Number of completed tasks |
-| `count` | Int! | Number of total tasks |
+| `completedCount` | Int! | Number of completed tasks. |
+| `count` | Int! | Number of total tasks. |
### TerraformState
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | Timestamp the Terraform state was created |
-| `id` | ID! | ID of the Terraform state |
-| `latestVersion` | TerraformStateVersion | The latest version of the Terraform state |
-| `lockedAt` | Time | Timestamp the Terraform state was locked |
-| `lockedByUser` | User | The user currently holding a lock on the Terraform state |
-| `name` | String! | Name of the Terraform state |
-| `updatedAt` | Time! | Timestamp the Terraform state was updated |
+| `createdAt` | Time! | Timestamp the Terraform state was created. |
+| `id` | ID! | ID of the Terraform state. |
+| `latestVersion` | TerraformStateVersion | The latest version of the Terraform state. |
+| `lockedAt` | Time | Timestamp the Terraform state was locked. |
+| `lockedByUser` | User | The user currently holding a lock on the Terraform state. |
+| `name` | String! | Name of the Terraform state. |
+| `updatedAt` | Time! | Timestamp the Terraform state was updated. |
### TerraformStateDeletePayload
@@ -3534,13 +3732,13 @@ Autogenerated return type of TerraformStateUnlock.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `createdAt` | Time! | Timestamp the version was created |
-| `createdByUser` | User | The user that created this version |
-| `downloadPath` | String | URL for downloading the version's JSON file |
-| `id` | ID! | ID of the Terraform state version |
-| `job` | CiJob | The job that created this version |
-| `serial` | Int | Serial number of the version |
-| `updatedAt` | Time! | Timestamp the version was updated |
+| `createdAt` | Time! | Timestamp the version was created. |
+| `createdByUser` | User | The user that created this version. |
+| `downloadPath` | String | URL for downloading the version's JSON file. |
+| `id` | ID! | ID of the Terraform state version. |
+| `job` | CiJob | The job that created this version. |
+| `serial` | Int | Serial number of the version. |
+| `updatedAt` | Time! | Timestamp the version was updated. |
### TerraformStateVersionRegistry
@@ -3555,7 +3753,7 @@ Represents the Geo sync and verification state of a terraform state version.
| `retryAt` | Time | Timestamp after which the TerraformStateVersionRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the TerraformStateVersionRegistry |
| `state` | RegistryState | Sync state of the TerraformStateVersionRegistry |
-| `terraformStateVersionId` | ID! | ID of the terraform state version |
+| `terraformStateVersionId` | ID! | ID of the terraform state version. |
### TestReport
@@ -3563,10 +3761,10 @@ Represents a requirement test report.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `author` | User | Author of the test report |
-| `createdAt` | Time! | Timestamp of when the test report was created |
-| `id` | ID! | ID of the test report |
-| `state` | TestReportState! | State of the test report |
+| `author` | User | Author of the test report. |
+| `createdAt` | Time! | Timestamp of when the test report was created. |
+| `id` | ID! | ID of the test report. |
+| `state` | TestReportState! | State of the test report. |
### TimeReportStats
@@ -3574,9 +3772,9 @@ Represents the time report stats for timeboxes.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `complete` | TimeboxMetrics | Completed issues metrics |
-| `incomplete` | TimeboxMetrics | Incomplete issues metrics |
-| `total` | TimeboxMetrics | Total issues metrics |
+| `complete` | TimeboxMetrics | Completed issues metrics. |
+| `incomplete` | TimeboxMetrics | Incomplete issues metrics. |
+| `total` | TimeboxMetrics | Total issues metrics. |
### TimeboxMetrics
@@ -3584,8 +3782,8 @@ Represents measured stats metrics for timeboxes.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int! | The count metric |
-| `weight` | Int! | The weight metric |
+| `count` | Int! | The count metric. |
+| `weight` | Int! | The weight metric. |
### TimeboxReport
@@ -3593,34 +3791,34 @@ Represents a historically accurate report about the timebox.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `burnupTimeSeries` | BurnupChartDailyTotals! => Array | Daily scope and completed totals for burnup charts |
-| `stats` | TimeReportStats | Represents the time report stats for the timebox |
+| `burnupTimeSeries` | BurnupChartDailyTotals! => Array | Daily scope and completed totals for burnup charts. |
+| `stats` | TimeReportStats | Represents the time report stats for the timebox. |
### Timelog
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `issue` | Issue | The issue that logged time was added to |
-| `note` | Note | The note where the quick action to add the logged time was executed |
-| `spentAt` | Time | Timestamp of when the time tracked was spent at |
-| `timeSpent` | Int! | The time spent displayed in seconds |
-| `user` | User! | The user that logged the time |
+| `issue` | Issue | The issue that logged time was added to. |
+| `note` | Note | The note where the quick action to add the logged time was executed. |
+| `spentAt` | Time | Timestamp of when the time tracked was spent at. |
+| `timeSpent` | Int! | The time spent displayed in seconds. |
+| `user` | User! | The user that logged the time. |
### Todo
-Representing a todo entry.
+Representing a to-do entry.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `action` | TodoActionEnum! | Action of the todo |
-| `author` | User! | The author of this todo |
-| `body` | String! | Body of the todo |
-| `createdAt` | Time! | Timestamp this todo was created |
-| `group` | Group | Group this todo is associated with |
-| `id` | ID! | ID of the todo |
-| `project` | Project | The project this todo is associated with |
-| `state` | TodoStateEnum! | State of the todo |
-| `targetType` | TodoTargetEnum! | Target type of the todo |
+| `action` | TodoActionEnum! | Action of the to-do item. |
+| `author` | User! | The author of this to-do item. |
+| `body` | String! | Body of the to-do item. |
+| `createdAt` | Time! | Timestamp this to-do item was created. |
+| `group` | Group | Group this to-do item is associated with. |
+| `id` | ID! | ID of the to-do item. |
+| `project` | Project | The project this to-do item is associated with. |
+| `state` | TodoStateEnum! | State of the to-do item. |
+| `targetType` | TodoTargetEnum! | Target type of the to-do item. |
### TodoCreatePayload
@@ -3630,7 +3828,7 @@ Autogenerated return type of TodoCreate.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `todo` | Todo | The to-do created. |
+| `todo` | Todo | The to-do item created. |
### TodoMarkDonePayload
@@ -3640,7 +3838,7 @@ Autogenerated return type of TodoMarkDone.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `todo` | Todo! | The requested todo. |
+| `todo` | Todo! | The requested to-do item. |
### TodoRestoreManyPayload
@@ -3650,8 +3848,8 @@ Autogenerated return type of TodoRestoreMany.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `todos` | Todo! => Array | Updated todos. |
-| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2. |
+| `todos` | Todo! => Array | Updated to-do items. |
+| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use to-do items. Deprecated in 13.2. |
### TodoRestorePayload
@@ -3661,7 +3859,7 @@ Autogenerated return type of TodoRestore.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `todo` | Todo! | The requested todo. |
+| `todo` | Todo! | The requested to-do item. |
### TodosMarkAllDonePayload
@@ -3671,8 +3869,8 @@ Autogenerated return type of TodosMarkAllDone.
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `todos` | Todo! => Array | Updated todos. |
-| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2. |
+| `todos` | Todo! => Array | Updated to-do items. |
+| `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use to-do items. Deprecated in 13.2. |
### ToggleAwardEmojiPayload
@@ -3689,10 +3887,10 @@ Autogenerated return type of ToggleAwardEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `blobs` | BlobConnection! | Blobs of the tree |
-| `lastCommit` | Commit | Last commit for the tree |
-| `submodules` | SubmoduleConnection! | Sub-modules of the tree |
-| `trees` | TreeEntryConnection! | Trees of the tree |
+| `blobs` | BlobConnection! | Blobs of the tree. |
+| `lastCommit` | Commit | Last commit for the tree. |
+| `submodules` | SubmoduleConnection! | Sub-modules of the tree. |
+| `trees` | TreeEntryConnection! | Trees of the tree. |
### TreeEntry
@@ -3700,14 +3898,14 @@ Represents a directory.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `flatPath` | String! | Flat path of the entry |
-| `id` | ID! | ID of the entry |
-| `name` | String! | Name of the entry |
-| `path` | String! | Path of the entry |
-| `sha` | String! | Last commit sha for the entry |
-| `type` | EntryType! | Type of tree entry |
-| `webPath` | String | Web path for the tree entry (directory) |
-| `webUrl` | String | Web URL for the tree entry (directory) |
+| `flatPath` | String! | Flat path of the entry. |
+| `id` | ID! | ID of the entry. |
+| `name` | String! | Name of the entry. |
+| `path` | String! | Path of the entry. |
+| `sha` | String! | Last commit SHA for the entry. |
+| `type` | EntryType! | Type of tree entry. |
+| `webPath` | String | Web path for the tree entry (directory). |
+| `webUrl` | String | Web URL for the tree entry (directory). |
### UpdateAlertStatusPayload
@@ -3719,7 +3917,7 @@ Autogenerated return type of UpdateAlertStatus.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `issue` | Issue | The issue created after mutation. |
-| `todo` | Todo | The todo after mutation. |
+| `todo` | Todo | The to-do item after mutation. |
### UpdateBoardEpicUserPreferencesPayload
@@ -3771,16 +3969,6 @@ Autogenerated return type of UpdateContainerExpirationPolicy.
| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy after mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-### UpdateDevopsAdoptionSegmentPayload
-
-Autogenerated return type of UpdateDevopsAdoptionSegment.
-
-| Field | Type | Description |
-| ----- | ---- | ----------- |
-| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
-| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `segment` | DevopsAdoptionSegment | The segment after mutation. |
-
### UpdateEpicPayload
Autogenerated return type of UpdateEpic.
@@ -3857,36 +4045,40 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
+| `captchaSiteKey` | String | The 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. |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `needsCaptchaResponse` | Boolean | 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. |
| `snippet` | Snippet | The snippet after mutation. |
-| `spam` | Boolean | Indicates whether the operation returns a record detected as spam. |
+| `spam` | Boolean | Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response. |
+| `spamLogId` | Int | The 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. |
### User
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `assignedMergeRequests` | MergeRequestConnection | Merge Requests assigned to the user |
-| `authoredMergeRequests` | MergeRequestConnection | Merge Requests authored by the user |
-| `avatarUrl` | String | URL of the user's avatar |
+| `assignedMergeRequests` | MergeRequestConnection | Merge Requests assigned to the user. |
+| `authoredMergeRequests` | MergeRequestConnection | Merge Requests authored by the user. |
+| `avatarUrl` | String | URL of the user's avatar. |
+| `bot` | Boolean! | Indicates if the user is a bot. |
| `email` **{warning-solid}** | String | **Deprecated:** Use public_email. Deprecated in 13.7. |
-| `groupCount` | Int | Group count for the user Available only when feature flag `user_group_counts` is enabled. |
-| `groupMemberships` | GroupMemberConnection | Group memberships of the user |
-| `id` | ID! | ID of the user |
+| `groupCount` | Int | Group count for the user. Available only when feature flag `user_group_counts` is enabled. |
+| `groupMemberships` | GroupMemberConnection | Group memberships of the user. |
+| `id` | ID! | ID of the user. |
| `location` | String | The location of the user. |
-| `name` | String! | Human-readable name of the user |
-| `projectMemberships` | ProjectMemberConnection | Project memberships of the user |
-| `publicEmail` | String | User's public email |
-| `reviewRequestedMergeRequests` | MergeRequestConnection | Merge Requests assigned to the user for review |
-| `snippets` | SnippetConnection | Snippets authored by the user |
-| `starredProjects` | ProjectConnection | Projects starred by the user |
-| `state` | UserState! | State of the user |
-| `status` | UserStatus | User status |
-| `todos` | TodoConnection! | Todos of the user |
+| `name` | String! | Human-readable name of the user. |
+| `projectMemberships` | ProjectMemberConnection | Project memberships of the user. |
+| `publicEmail` | String | User's public email. |
+| `reviewRequestedMergeRequests` | MergeRequestConnection | Merge Requests assigned to the user for review. |
+| `snippets` | SnippetConnection | Snippets authored by the user. |
+| `starredProjects` | ProjectConnection | Projects starred by the user. |
+| `state` | UserState! | State of the user. |
+| `status` | UserStatus | User status. |
+| `todos` | TodoConnection! | To-do items of the user. |
| `userPermissions` | UserPermissions! | Permissions for the current user on the resource |
-| `username` | String! | Username of the user. Unique within this instance of GitLab |
-| `webPath` | String! | Web path of the user |
-| `webUrl` | String! | Web URL of the user |
+| `username` | String! | Username of the user. Unique within this instance of GitLab. |
+| `webPath` | String! | Web path of the user. |
+| `webUrl` | String! | Web URL of the user. |
### UserPermissions
@@ -3898,9 +4090,9 @@ Autogenerated return type of UpdateSnippet.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `availability` | AvailabilityEnum! | User availability status |
-| `emoji` | String | String representation of emoji |
-| `message` | String | User status message |
+| `availability` | AvailabilityEnum! | User availability status. |
+| `emoji` | String | String representation of emoji. |
+| `message` | String | User status message. |
| `messageHtml` | String | HTML of the user status message |
### VulnerabilitiesCountByDay
@@ -3910,12 +4102,12 @@ Represents the count of vulnerabilities by severity on a particular day. This da
| Field | Type | Description |
| ----- | ---- | ----------- |
| `critical` | Int! | Total number of vulnerabilities on a particular day with critical severity |
-| `date` | ISO8601Date! | Date for the count |
+| `date` | ISO8601Date! | Date for the count. |
| `high` | Int! | Total number of vulnerabilities on a particular day with high severity |
| `info` | Int! | Total number of vulnerabilities on a particular day with info severity |
| `low` | Int! | Total number of vulnerabilities on a particular day with low severity |
| `medium` | Int! | Total number of vulnerabilities on a particular day with medium severity |
-| `total` | Int! | Total number of vulnerabilities on a particular day |
+| `total` | Int! | Total number of vulnerabilities on a particular day. |
| `unknown` | Int! | Total number of vulnerabilities on a particular day with unknown severity |
### VulnerabilitiesCountByDayAndSeverity
@@ -3924,9 +4116,9 @@ Represents the number of vulnerabilities for a particular severity on a particul
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int | Number of vulnerabilities |
-| `day` | ISO8601Date | Date for the count |
-| `severity` | VulnerabilitySeverity | Severity of the counted vulnerabilities |
+| `count` | Int | Number of vulnerabilities. |
+| `day` | ISO8601Date | Date for the count. |
+| `severity` | VulnerabilitySeverity | Severity of the counted vulnerabilities. |
### Vulnerability
@@ -3934,34 +4126,35 @@ Represents a vulnerability.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `confirmedAt` | Time | Timestamp of when the vulnerability state was changed to confirmed |
+| `confirmedAt` | Time | Timestamp of when the vulnerability state was changed to confirmed. |
| `confirmedBy` | User | The user that confirmed the vulnerability. |
-| `description` | String | Description of the vulnerability |
-| `detectedAt` | Time! | Timestamp of when the vulnerability was first detected |
-| `discussions` | DiscussionConnection! | All discussions on this noteable |
-| `dismissedAt` | Time | Timestamp of when the vulnerability state was changed to dismissed |
+| `description` | String | Description of the vulnerability. |
+| `details` | VulnerabilityDetail! => Array | Details of the vulnerability. |
+| `detectedAt` | Time! | Timestamp of when the vulnerability was first detected. |
+| `discussions` | DiscussionConnection! | All discussions on this noteable. |
+| `dismissedAt` | Time | Timestamp of when the vulnerability state was changed to dismissed. |
| `dismissedBy` | User | The user that dismissed the vulnerability. |
-| `externalIssueLinks` | VulnerabilityExternalIssueLinkConnection! | List of external issue links related to the vulnerability |
+| `externalIssueLinks` | VulnerabilityExternalIssueLinkConnection! | List of external issue links related to the vulnerability. |
| `hasSolutions` | Boolean | Indicates whether there is a solution available for this vulnerability. |
-| `id` | ID! | GraphQL ID of the vulnerability |
+| `id` | ID! | GraphQL ID of the vulnerability. |
| `identifiers` | VulnerabilityIdentifier! => Array | Identifiers of the vulnerability. |
-| `issueLinks` | VulnerabilityIssueLinkConnection! | List of issue links related to the vulnerability |
-| `location` | VulnerabilityLocation | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability |
+| `issueLinks` | VulnerabilityIssueLinkConnection! | List of issue links related to the vulnerability. |
+| `location` | VulnerabilityLocation | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. |
| `mergeRequest` | MergeRequest | Merge request that fixes the vulnerability. |
-| `notes` | NoteConnection! | All notes on this noteable |
+| `notes` | NoteConnection! | All notes on this noteable. |
| `primaryIdentifier` | VulnerabilityIdentifier | Primary identifier of the vulnerability. |
-| `project` | Project | The project on which the vulnerability was found |
+| `project` | Project | The project on which the vulnerability was found. |
| `reportType` | VulnerabilityReportType | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING, API_FUZZING) |
-| `resolvedAt` | Time | Timestamp of when the vulnerability state was changed to resolved |
+| `resolvedAt` | Time | Timestamp of when the vulnerability state was changed to resolved. |
| `resolvedBy` | User | The user that resolved the vulnerability. |
-| `resolvedOnDefaultBranch` | Boolean! | Indicates whether the vulnerability is fixed on the default branch or not |
+| `resolvedOnDefaultBranch` | Boolean! | Indicates whether the vulnerability is fixed on the default branch or not. |
| `scanner` | VulnerabilityScanner | Scanner metadata for the vulnerability. |
| `severity` | VulnerabilitySeverity | Severity of the vulnerability (INFO, UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL) |
| `state` | VulnerabilityState | State of the vulnerability (DETECTED, CONFIRMED, RESOLVED, DISMISSED) |
-| `title` | String | Title of the vulnerability |
-| `userNotesCount` | Int! | Number of user notes attached to the vulnerability |
+| `title` | String | Title of the vulnerability. |
+| `userNotesCount` | Int! | Number of user notes attached to the vulnerability. |
| `userPermissions` | VulnerabilityPermissions! | Permissions for the current user on the resource |
-| `vulnerabilityPath` | String | URL to the vulnerability's details page |
+| `vulnerabilityPath` | String | URL to the vulnerability's details page. |
### VulnerabilityConfirmPayload
@@ -3973,6 +4166,155 @@ Autogenerated return type of VulnerabilityConfirm.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `vulnerability` | Vulnerability | The vulnerability after state change. |
+### VulnerabilityDetailBase
+
+Represents the vulnerability details base.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+
+### VulnerabilityDetailBoolean
+
+Represents the vulnerability details boolean value.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+| `value` | Boolean! | Value of the field. |
+
+### VulnerabilityDetailCode
+
+Represents the vulnerability details code field.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `lang` | String | Language of the code. |
+| `name` | String! | Name of the field. |
+| `value` | String! | Source code. |
+
+### VulnerabilityDetailCommit
+
+Represents the vulnerability details commit field.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+| `value` | String! | The commit SHA value. |
+
+### VulnerabilityDetailDiff
+
+Represents the vulnerability details diff field.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `after` | String! | Value of the field after the change. |
+| `before` | String! | Value of the field before the change. |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+
+### VulnerabilityDetailFileLocation
+
+Represents the vulnerability details location within a file in the project.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `fileName` | String! | File name. |
+| `lineEnd` | Int! | End line number of the file location. |
+| `lineStart` | Int! | Start line number of the file location. |
+| `name` | String! | Name of the field. |
+
+### VulnerabilityDetailInt
+
+Represents the vulnerability details integer value.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+| `value` | Int! | Value of the field. |
+
+### VulnerabilityDetailList
+
+Represents the vulnerability details list value.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `items` | VulnerabilityDetail! => Array | List of details. |
+| `name` | String! | Name of the field. |
+
+### VulnerabilityDetailMarkdown
+
+Represents the vulnerability details Markdown field.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+| `value` | String! | Value of the Markdown field. |
+
+### VulnerabilityDetailModuleLocation
+
+Represents the vulnerability details location within a file in the project.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `moduleName` | String! | Module name. |
+| `name` | String! | Name of the field. |
+| `offset` | Int! | Offset of the module location. |
+
+### VulnerabilityDetailTable
+
+Represents the vulnerability details table value.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `headers` | VulnerabilityDetail! => Array | Table headers. |
+| `name` | String! | Name of the field. |
+| `rows` | VulnerabilityDetail! => Array | Table rows. |
+
+### VulnerabilityDetailText
+
+Represents the vulnerability details text field.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `name` | String! | Name of the field. |
+| `value` | String! | Value of the text field. |
+
+### VulnerabilityDetailUrl
+
+Represents the vulnerability details URL field.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String! | Description of the field. |
+| `fieldName` | String | Name of the field. |
+| `href` | String! | Href of the URL. |
+| `name` | String! | Name of the field. |
+| `text` | String | Text of the URL. |
+
### VulnerabilityDismissPayload
Autogenerated return type of VulnerabilityDismiss.
@@ -3989,9 +4331,9 @@ Represents an external issue link of a vulnerability.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `externalIssue` | ExternalIssue | The external issue attached to the issue link |
-| `id` | VulnerabilitiesExternalIssueLinkID! | GraphQL ID of the external issue link |
-| `linkType` | VulnerabilityExternalIssueLinkType! | Type of the external issue link |
+| `externalIssue` | ExternalIssue | The external issue attached to the issue link. |
+| `id` | VulnerabilitiesExternalIssueLinkID! | GraphQL ID of the external issue link. |
+| `linkType` | VulnerabilityExternalIssueLinkType! | Type of the external issue link. |
### VulnerabilityExternalIssueLinkCreatePayload
@@ -4018,10 +4360,10 @@ Represents a vulnerability identifier.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `externalId` | String | External ID of the vulnerability identifier |
-| `externalType` | String | External type of the vulnerability identifier |
-| `name` | String | Name of the vulnerability identifier |
-| `url` | String | URL of the vulnerability identifier |
+| `externalId` | String | External ID of the vulnerability identifier. |
+| `externalType` | String | External type of the vulnerability identifier. |
+| `name` | String | Name of the vulnerability identifier. |
+| `url` | String | URL of the vulnerability identifier. |
### VulnerabilityIssueLink
@@ -4029,9 +4371,9 @@ Represents an issue link of a vulnerability.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `id` | ID! | GraphQL ID of the vulnerability |
-| `issue` | Issue! | The issue attached to issue link |
-| `linkType` | VulnerabilityIssueLinkType! | Type of the issue link |
+| `id` | ID! | GraphQL ID of the vulnerability. |
+| `issue` | Issue! | The issue attached to issue link. |
+| `linkType` | VulnerabilityIssueLinkType! | Type of the issue link. |
### VulnerabilityLocationContainerScanning
@@ -4039,9 +4381,9 @@ Represents the location of a vulnerability found by a container security scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `dependency` | VulnerableDependency | Dependency containing the vulnerability |
-| `image` | String | Name of the vulnerable container image |
-| `operatingSystem` | String | Operating system that runs on the vulnerable container image |
+| `dependency` | VulnerableDependency | Dependency containing the vulnerability. |
+| `image` | String | Name of the vulnerable container image. |
+| `operatingSystem` | String | Operating system that runs on the vulnerable container image. |
### VulnerabilityLocationCoverageFuzzing
@@ -4049,11 +4391,12 @@ Represents the location of a vulnerability found by a Coverage Fuzzing scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `endLine` | String | Number of the last relevant line in the vulnerable file |
-| `file` | String | Path to the vulnerable file |
-| `startLine` | String | Number of the first relevant line in the vulnerable file |
-| `vulnerableClass` | String | Class containing the vulnerability |
-| `vulnerableMethod` | String | Method containing the vulnerability |
+| `blobPath` | String | Blob path to the vulnerable file. |
+| `endLine` | String | Number of the last relevant line in the vulnerable file. |
+| `file` | String | Path to the vulnerable file. |
+| `startLine` | String | Number of the first relevant line in the vulnerable file. |
+| `vulnerableClass` | String | Class containing the vulnerability. |
+| `vulnerableMethod` | String | Method containing the vulnerability. |
### VulnerabilityLocationDast
@@ -4061,10 +4404,10 @@ Represents the location of a vulnerability found by a DAST scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `hostname` | String | Domain name of the vulnerable request |
-| `param` | String | Query parameter for the URL on which the vulnerability occurred |
-| `path` | String | URL path and query string of the vulnerable request |
-| `requestMethod` | String | HTTP method of the vulnerable request |
+| `hostname` | String | Domain name of the vulnerable request. |
+| `param` | String | Query parameter for the URL on which the vulnerability occurred. |
+| `path` | String | URL path and query string of the vulnerable request. |
+| `requestMethod` | String | HTTP method of the vulnerable request. |
### VulnerabilityLocationDependencyScanning
@@ -4072,8 +4415,9 @@ Represents the location of a vulnerability found by a dependency security scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `dependency` | VulnerableDependency | Dependency containing the vulnerability |
-| `file` | String | Path to the vulnerable file |
+| `blobPath` | String | Blob path to the vulnerable file. |
+| `dependency` | VulnerableDependency | Dependency containing the vulnerability. |
+| `file` | String | Path to the vulnerable file. |
### VulnerabilityLocationSast
@@ -4081,11 +4425,12 @@ Represents the location of a vulnerability found by a SAST scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `endLine` | String | Number of the last relevant line in the vulnerable file |
-| `file` | String | Path to the vulnerable file |
-| `startLine` | String | Number of the first relevant line in the vulnerable file |
-| `vulnerableClass` | String | Class containing the vulnerability |
-| `vulnerableMethod` | String | Method containing the vulnerability |
+| `blobPath` | String | Blob path to the vulnerable file. |
+| `endLine` | String | Number of the last relevant line in the vulnerable file. |
+| `file` | String | Path to the vulnerable file. |
+| `startLine` | String | Number of the first relevant line in the vulnerable file. |
+| `vulnerableClass` | String | Class containing the vulnerability. |
+| `vulnerableMethod` | String | Method containing the vulnerability. |
### VulnerabilityLocationSecretDetection
@@ -4093,11 +4438,12 @@ Represents the location of a vulnerability found by a secret detection scan.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `endLine` | String | Number of the last relevant line in the vulnerable file |
-| `file` | String | Path to the vulnerable file |
-| `startLine` | String | Number of the first relevant line in the vulnerable file |
-| `vulnerableClass` | String | Class containing the vulnerability |
-| `vulnerableMethod` | String | Method containing the vulnerability |
+| `blobPath` | String | Blob path to the vulnerable file. |
+| `endLine` | String | Number of the last relevant line in the vulnerable file. |
+| `file` | String | Path to the vulnerable file. |
+| `startLine` | String | Number of the first relevant line in the vulnerable file. |
+| `vulnerableClass` | String | Class containing the vulnerability. |
+| `vulnerableMethod` | String | Method containing the vulnerability. |
### VulnerabilityPermissions
@@ -4141,10 +4487,10 @@ Represents a vulnerability scanner.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `externalId` | String | External ID of the vulnerability scanner |
-| `name` | String | Name of the vulnerability scanner |
-| `reportType` | VulnerabilityReportType | Type of the vulnerability report |
-| `vendor` | String | Vendor of the vulnerability scanner |
+| `externalId` | String | External ID of the vulnerability scanner. |
+| `name` | String | Name of the vulnerability scanner. |
+| `reportType` | VulnerabilityReportType | Type of the vulnerability report. |
+| `vendor` | String | Vendor of the vulnerability scanner. |
### VulnerabilitySeveritiesCount
@@ -4165,8 +4511,8 @@ Represents a vulnerable dependency. Used in vulnerability location data.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `package` | VulnerablePackage | The package associated with the vulnerable dependency |
-| `version` | String | The version of the vulnerable dependency |
+| `package` | VulnerablePackage | The package associated with the vulnerable dependency. |
+| `version` | String | The version of the vulnerable dependency. |
### VulnerablePackage
@@ -4174,7 +4520,7 @@ Represents a vulnerable package. Used in vulnerability dependency data.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `name` | String | The name of the vulnerable package |
+| `name` | String | The name of the vulnerable package. |
### VulnerableProjectsByGrade
@@ -4182,9 +4528,9 @@ Represents vulnerability letter grades with associated projects.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `count` | Int! | Number of projects within this grade |
-| `grade` | VulnerabilityGrade! | Grade based on the highest severity vulnerability present |
-| `projects` | ProjectConnection! | Projects within this grade |
+| `count` | Int! | Number of projects within this grade. |
+| `grade` | VulnerabilityGrade! | Grade based on the highest severity vulnerability present. |
+| `projects` | ProjectConnection! | Projects within this grade. |
## Enumeration types
@@ -4306,6 +4652,15 @@ Alert status values.
| `RESOLVED` | Resolved status |
| `TRIGGERED` | Triggered status |
+### ApiFuzzingScanMode
+
+All possible ways to specify the API surface for an API fuzzing scan.
+
+| Value | Description |
+| ----- | ----------- |
+| `HAR` | The API surface is specified by a HAR file. |
+| `OPENAPI` | The API surface is specified by a OPENAPI file. |
+
### AvailabilityEnum
User availability status.
@@ -4394,6 +4749,23 @@ Status of the tags cleanup of a container repository.
| `UNFINISHED` | The tags cleanup has been partially executed. There are still remaining tags to delete. |
| `UNSCHEDULED` | The tags cleanup is not scheduled. This is the default state. |
+### ContainerRepositorySort
+
+Values for sorting container repositories.
+
+| Value | Description |
+| ----- | ----------- |
+| `CREATED_ASC` | Created at ascending order |
+| `CREATED_DESC` | Created at descending order |
+| `NAME_ASC` | Name by ascending order |
+| `NAME_DESC` | Name by descending order |
+| `UPDATED_ASC` | Updated at ascending order |
+| `UPDATED_DESC` | Updated at descending order |
+| `created_asc` **{warning-solid}** | **Deprecated:** Use CREATED_ASC. Deprecated in 13.5. |
+| `created_desc` **{warning-solid}** | **Deprecated:** Use CREATED_DESC. Deprecated in 13.5. |
+| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5. |
+| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5. |
+
### ContainerRepositoryStatus
Status of a container repository.
@@ -4536,6 +4908,26 @@ Epic ID wildcard values.
| `ANY` | Any epic is assigned |
| `NONE` | No epic is assigned |
+### EventAction
+
+Event action.
+
+| Value | Description |
+| ----- | ----------- |
+| `APPROVED` | Approved action |
+| `ARCHIVED` | Archived action |
+| `CLOSED` | Closed action |
+| `COMMENTED` | Commented action |
+| `CREATED` | Created action |
+| `DESTROYED` | Destroyed action |
+| `EXPIRED` | Expired action |
+| `JOINED` | Joined action |
+| `LEFT` | Left action |
+| `MERGED` | Merged action |
+| `PUSHED` | Pushed action |
+| `REOPENED` | Reopened action |
+| `UPDATED` | Updated action |
+
### GroupMemberRelation
Group member relation.
@@ -4722,6 +5114,15 @@ Possible identifier types for a measurement.
| `PROJECTS` | Project count |
| `USERS` | User count |
+### MergeRequestNewState
+
+New state to apply to a merge request..
+
+| Value | Description |
+| ----- | ----------- |
+| `CLOSED` | Close the merge request if it is open. |
+| `OPEN` | Open the merge request if it is closed. |
+
### MergeRequestSort
Values for sorting merge requests.
@@ -4754,15 +5155,17 @@ State of a GitLab merge request.
| `all` | |
| `closed` | |
| `locked` | |
-| `merged` | |
+| `merged` | Merge Request has been merged |
| `opened` | |
### MilestoneStateEnum
+Current state of milestone.
+
| Value | Description |
| ----- | ----------- |
-| `active` | |
-| `closed` | |
+| `active` | Milestone is currently active |
+| `closed` | Milestone is closed |
### MoveType
@@ -4812,9 +5215,10 @@ Rotation length unit of an on-call rotation.
| `GENERIC` | Packages from the Generic package manager |
| `GOLANG` | Packages from the Golang package manager |
| `MAVEN` | Packages from the Maven package manager |
-| `NPM` | Packages from the NPM package manager |
+| `NPM` | Packages from the npm package manager |
| `NUGET` | Packages from the Nuget package manager |
| `PYPI` | Packages from the PyPI package manager |
+| `RUBYGEMS` | Packages from the Rubygems package manager |
### PipelineConfigSourceEnum
@@ -4822,6 +5226,7 @@ Rotation length unit of an on-call rotation.
| ----- | ----------- |
| `AUTO_DEVOPS_SOURCE` | |
| `BRIDGE_SOURCE` | |
+| `COMPLIANCE_SOURCE` | |
| `EXTERNAL_PROJECT_SOURCE` | |
| `PARAMETER_SOURCE` | |
| `REMOTE_SOURCE` | |
@@ -4949,42 +5354,42 @@ State of a Sentry error.
| Value | Description |
| ----- | ----------- |
-| `ASANA_SERVICE` | |
-| `ASSEMBLA_SERVICE` | |
-| `BAMBOO_SERVICE` | |
-| `BUGZILLA_SERVICE` | |
-| `BUILDKITE_SERVICE` | |
-| `CAMPFIRE_SERVICE` | |
-| `CONFLUENCE_SERVICE` | |
-| `CUSTOM_ISSUE_TRACKER_SERVICE` | |
-| `DATADOG_SERVICE` | |
-| `DISCORD_SERVICE` | |
-| `DRONE_CI_SERVICE` | |
-| `EMAILS_ON_PUSH_SERVICE` | |
-| `EWM_SERVICE` | |
-| `EXTERNAL_WIKI_SERVICE` | |
-| `FLOWDOCK_SERVICE` | |
-| `GITHUB_SERVICE` | |
-| `HANGOUTS_CHAT_SERVICE` | |
-| `HIPCHAT_SERVICE` | |
-| `IRKER_SERVICE` | |
-| `JENKINS_SERVICE` | |
-| `JIRA_SERVICE` | |
-| `MATTERMOST_SERVICE` | |
-| `MATTERMOST_SLASH_COMMANDS_SERVICE` | |
-| `MICROSOFT_TEAMS_SERVICE` | |
-| `PACKAGIST_SERVICE` | |
-| `PIPELINES_EMAIL_SERVICE` | |
-| `PIVOTALTRACKER_SERVICE` | |
-| `PROMETHEUS_SERVICE` | |
-| `PUSHOVER_SERVICE` | |
-| `REDMINE_SERVICE` | |
-| `SLACK_SERVICE` | |
-| `SLACK_SLASH_COMMANDS_SERVICE` | |
-| `TEAMCITY_SERVICE` | |
-| `UNIFY_CIRCUIT_SERVICE` | |
-| `WEBEX_TEAMS_SERVICE` | |
-| `YOUTRACK_SERVICE` | |
+| `ASANA_SERVICE` | AsanaService type |
+| `ASSEMBLA_SERVICE` | AssemblaService type |
+| `BAMBOO_SERVICE` | BambooService type |
+| `BUGZILLA_SERVICE` | BugzillaService type |
+| `BUILDKITE_SERVICE` | BuildkiteService type |
+| `CAMPFIRE_SERVICE` | CampfireService type |
+| `CONFLUENCE_SERVICE` | ConfluenceService type |
+| `CUSTOM_ISSUE_TRACKER_SERVICE` | CustomIssueTrackerService type |
+| `DATADOG_SERVICE` | DatadogService type |
+| `DISCORD_SERVICE` | DiscordService type |
+| `DRONE_CI_SERVICE` | DroneCiService type |
+| `EMAILS_ON_PUSH_SERVICE` | EmailsOnPushService type |
+| `EWM_SERVICE` | EwmService type |
+| `EXTERNAL_WIKI_SERVICE` | ExternalWikiService type |
+| `FLOWDOCK_SERVICE` | FlowdockService type |
+| `GITHUB_SERVICE` | GithubService type |
+| `HANGOUTS_CHAT_SERVICE` | HangoutsChatService type |
+| `HIPCHAT_SERVICE` | HipchatService type |
+| `IRKER_SERVICE` | IrkerService type |
+| `JENKINS_SERVICE` | JenkinsService type |
+| `JIRA_SERVICE` | JiraService type |
+| `MATTERMOST_SERVICE` | MattermostService type |
+| `MATTERMOST_SLASH_COMMANDS_SERVICE` | MattermostSlashCommandsService type |
+| `MICROSOFT_TEAMS_SERVICE` | MicrosoftTeamsService type |
+| `PACKAGIST_SERVICE` | PackagistService type |
+| `PIPELINES_EMAIL_SERVICE` | PipelinesEmailService type |
+| `PIVOTALTRACKER_SERVICE` | PivotaltrackerService type |
+| `PROMETHEUS_SERVICE` | PrometheusService type |
+| `PUSHOVER_SERVICE` | PushoverService type |
+| `REDMINE_SERVICE` | RedmineService type |
+| `SLACK_SERVICE` | SlackService type |
+| `SLACK_SLASH_COMMANDS_SERVICE` | SlackSlashCommandsService type |
+| `TEAMCITY_SERVICE` | TeamcityService type |
+| `UNIFY_CIRCUIT_SERVICE` | UnifyCircuitService type |
+| `WEBEX_TEAMS_SERVICE` | WebexTeamsService type |
+| `YOUTRACK_SERVICE` | YoutrackService type |
### SnippetBlobActionEnum
diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md
index f05b23495bb..2761c1a1c84 100644
--- a/doc/api/graphql/removed_items.md
+++ b/doc/api/graphql/removed_items.md
@@ -1,3 +1,9 @@
+---
+stage: Plan
+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
+---
+
# GraphQL API removed items
GraphQL is a versionless API, unlike the REST API.
diff --git a/doc/api/group_badges.md b/doc/api/group_badges.md
index 7698fa9ba5f..e3fcaa3db37 100644
--- a/doc/api/group_badges.md
+++ b/doc/api/group_badges.md
@@ -12,11 +12,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Badges support placeholders that are replaced in real time in both the link and image URL. The allowed placeholders are:
+<!-- vale gitlab.Spelling = NO -->
+
- **%{project_path}**: replaced by the project path.
- **%{project_id}**: replaced by the project ID.
- **%{default_branch}**: replaced by the project default branch.
- **%{commit_sha}**: replaced by the last project's commit SHA.
+<!-- vale gitlab.Spelling = YES -->
+
Because these endpoints aren't inside a project's context, the information used to replace the placeholders comes
from the first group's project by creation date. If the group hasn't got any project the original URL with the placeholders is returned.
diff --git a/doc/api/group_boards.md b/doc/api/group_boards.md
index 722f3a76267..16ab81af1fe 100644
--- a/doc/api/group_boards.md
+++ b/doc/api/group_boards.md
@@ -76,7 +76,7 @@ Example response:
]
```
-Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) see
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) see
different parameters, due to the ability to have multiple group boards.
Example response:
@@ -192,7 +192,7 @@ Example response:
}
```
-Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) see
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) see
different parameters, due to the ability to have multiple group issue boards.
Example response:
@@ -526,7 +526,7 @@ Example response:
## Delete a group issue board list
-Only for admins and group owners. Deletes the board list in question.
+Only for administrators and group owners. Deletes the board list in question.
```plaintext
DELETE /groups/:id/boards/:board_id/lists/:list_id
diff --git a/doc/api/group_clusters.md b/doc/api/group_clusters.md
index f169c1829be..69b54591d0a 100644
--- a/doc/api/group_clusters.md
+++ b/doc/api/group_clusters.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
---
-# Group clusters API
+# Group clusters API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30213) in GitLab 12.1.
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index 57670eff1ea..79338df4f7a 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -19,7 +19,8 @@ Group exports include the following:
- Group labels
- Group badges
- Group members
-- Sub-groups. Each sub-group includes all data above
+- Subgroups. Each subgroup includes all data above
+- Group wikis **(PREMIUM SELF)**
## Schedule new export
@@ -94,7 +95,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "name=i
NOTE:
The maximum import file size can be set by the Administrator, default is `0` (unlimited).
-As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](settings.md#change-application-settings) or the [Admin UI](../user/admin_area/settings/account_and_limit_settings.md).
+As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](settings.md#change-application-settings) or the [Admin Area](../user/admin_area/settings/account_and_limit_settings.md). Default [modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8.
## Important notes
diff --git a/doc/api/group_iterations.md b/doc/api/group_iterations.md
index d96f0881088..3d72e035383 100644
--- a/doc/api/group_iterations.md
+++ b/doc/api/group_iterations.md
@@ -4,9 +4,10 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Group iterations API **(STARTER)**
+# Group iterations API **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.5.
+> - Moved to GitLab Premium in 13.9.
This page describes the group iterations API.
There's a separate [project iterations API](iterations.md) page.
@@ -49,7 +50,8 @@ Example response:
"created_at": "2020-01-27T05:07:12.573Z",
"updated_at": "2020-01-27T05:07:12.573Z",
"due_date": "2020-02-01",
- "start_date": "2020-02-14"
+ "start_date": "2020-02-14",
+ "web_url": "http://gitlab.example.com/groups/my-group/-/iterations/13"
}
]
```
diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md
index 2c56b2c501d..cf542a9da0b 100644
--- a/doc/api/group_milestones.md
+++ b/doc/api/group_milestones.md
@@ -159,9 +159,10 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `milestone_id` | integer | yes | The ID of a group milestone |
-## Get all burndown chart events for a single milestone **(STARTER)**
+## Get all burndown chart events for a single milestone **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) in GitLab 12.1
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) in GitLab 12.1
+> - Moved to GitLab Premium in 13.9.
Get all burndown chart events for a single milestone.
diff --git a/doc/api/group_repository_storage_moves.md b/doc/api/group_repository_storage_moves.md
new file mode 100644
index 00000000000..8a19a43d31f
--- /dev/null
+++ b/doc/api/group_repository_storage_moves.md
@@ -0,0 +1,254 @@
+---
+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
+---
+
+# Group repository storage moves API **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53016) in GitLab 13.9.
+
+Group repositories can be moved between storages. This can be useful when
+[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster),
+for example, or to migrate a Group Wiki.
+
+As group repository storage moves are processed, they transition through different states. Values
+of `state` are:
+
+- `initial`
+- `scheduled`
+- `started`
+- `finished`
+- `failed`
+- `replicated`
+- `cleanup failed`
+
+To ensure data integrity, groups are put in a temporary read-only state for the
+duration of the move. During this time, users receive a `The repository is temporarily
+read-only. Please try again later.` message if they try to push new commits.
+
+This API requires you to [authenticate yourself](README.md#authentication) as an administrator.
+
+For other type of repositories you can read:
+
+- [Project repository storage moves API](project_repository_storage_moves.md)
+- [Snippet repository storage moves API](snippet_repository_storage_moves.md)
+
+## Retrieve all group repository storage moves
+
+```plaintext
+GET /group_repository_storage_moves
+```
+
+By default, `GET` requests return 20 results at a time because the API results
+are [paginated](README.md#pagination).
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/group_repository_storage_moves"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "created_at": "2020-05-07T04:27:17.234Z",
+ "state": "scheduled",
+ "source_storage_name": "default",
+ "destination_storage_name": "storage2",
+ "group": {
+ "id": 283,
+ "web_url": "https://gitlab.example.com/groups/testgroup",
+ "name": "testgroup"
+ }
+ }
+]
+```
+
+## Retrieve all repository storage moves for a single group
+
+In order to retrieve all the repository storage moves for a single group you can use the following endpoint:
+
+```plaintext
+GET /groups/:group_id/repository_storage_moves
+```
+
+By default, `GET` requests return 20 results at a time because the API results
+are [paginated](README.md#pagination).
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `group_id` | integer | yes | ID of the group. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/repository_storage_moves"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "created_at": "2020-05-07T04:27:17.234Z",
+ "state": "scheduled",
+ "source_storage_name": "default",
+ "destination_storage_name": "storage2",
+ "group": {
+ "id": 283,
+ "web_url": "https://gitlab.example.com/groups/testgroup",
+ "name": "testgroup"
+ }
+ }
+]
+```
+
+## Get a single group repository storage move
+
+In order to retrieve a single repository storage move throughout all the existing repository storage moves, you can use the following endpoint:
+
+```plaintext
+GET /group_repository_storage_moves/:repository_storage_id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `repository_storage_id` | integer | yes | ID of the group repository storage move. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/group_repository_storage_moves/1"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "created_at": "2020-05-07T04:27:17.234Z",
+ "state": "scheduled",
+ "source_storage_name": "default",
+ "destination_storage_name": "storage2",
+ "group": {
+ "id": 283,
+ "web_url": "https://gitlab.example.com/groups/testgroup",
+ "name": "testgroup"
+ }
+}
+```
+
+## Get a single repository storage move for a group
+
+Given a group, you can retrieve a specific repository storage move for that group, through the following endpoint:
+
+```plaintext
+GET /groups/:group_id/repository_storage_moves/:repository_storage_id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `group_id` | integer | yes | ID of the group. |
+| `repository_storage_id` | integer | yes | ID of the group repository storage move. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/repository_storage_moves/1"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "created_at": "2020-05-07T04:27:17.234Z",
+ "state": "scheduled",
+ "source_storage_name": "default",
+ "destination_storage_name": "storage2",
+ "group": {
+ "id": 283,
+ "web_url": "https://gitlab.example.com/groups/testgroup",
+ "name": "testgroup"
+ }
+}
+```
+
+## Schedule a repository storage move for a group
+
+```plaintext
+POST /groups/:group_id/repository_storage_moves
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `group_id` | integer | yes | ID of the group. |
+| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected automatically if not provided. |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+--data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/groups/1/repository_storage_moves"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "created_at": "2020-05-07T04:27:17.234Z",
+ "state": "scheduled",
+ "source_storage_name": "default",
+ "destination_storage_name": "storage2",
+ "group": {
+ "id": 283,
+ "web_url": "https://gitlab.example.com/groups/testgroup",
+ "name": "testgroup"
+ }
+}
+```
+
+## Schedule repository storage moves for all groups on a storage shard
+
+Schedules repository storage moves for each group repository stored on the source storage shard.
+
+```plaintext
+POST /group_repository_storage_moves
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `source_storage_name` | string | yes | Name of the source storage shard. |
+| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected automatically if not provided. |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \
+--data '{"source_storage_name":"default"}' "https://gitlab.example.com/api/v4/group_repository_storage_moves"
+```
+
+Example response:
+
+```json
+{
+ "message": "202 Accepted"
+}
+```
diff --git a/doc/api/group_wikis.md b/doc/api/group_wikis.md
index f8804d1eadc..6c5e2b77f93 100644
--- a/doc/api/group_wikis.md
+++ b/doc/api/group_wikis.md
@@ -1,6 +1,6 @@
---
stage: Create
-group: Knowledge
+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, api
---
@@ -179,9 +179,9 @@ POST /groups/:id/wikis/attachments
| `file` | string | yes | The attachment to be uploaded |
| `branch` | string | no | The name of the branch. Defaults to the wiki repository default branch |
-To upload a file from your filesystem, use the `--form` argument. This causes
+To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`.
-The `file=` parameter must point to a file on your filesystem and be preceded
+The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
diff --git a/doc/api/groups.md b/doc/api/groups.md
index eb255f8de00..6031d780436 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -18,12 +18,12 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------------ | ----------------- | -------- | ---------- |
| `skip_groups` | array of integers | no | Skip the group IDs passed |
-| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin); Attributes `owned` and `min_access_level` have precedence |
+| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for administrators); Attributes `owned` and `min_access_level` have precedence |
| `search` | string | no | Return the list of authorized groups matching the search criteria |
| `order_by` | string | no | Order groups by `name`, `path` or `id`. Default is `name` |
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
-| `statistics` | boolean | no | Include group statistics (admins only) |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| `statistics` | boolean | no | Include group statistics (administrators only) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
| `min_access_level` | integer | no | Limit to groups where current user has at least this [access level](members.md#valid-access-levels) |
| `top_level_only` | boolean | no | Limit to top level groups, excluding all subgroups |
@@ -62,7 +62,7 @@ GET /groups
]
```
-When adding the parameter `statistics=true` and the authenticated user is an admin, additional group statistics are returned.
+When adding the parameter `statistics=true` and the authenticated user is an administrator, additional group statistics are returned.
```plaintext
GET /groups?statistics=true
@@ -130,12 +130,12 @@ Parameters:
| ------------------------ | ----------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) of the immediate parent group |
| `skip_groups` | array of integers | no | Skip the group IDs passed |
-| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin); Attributes `owned` and `min_access_level` have precedence |
+| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for administrators); Attributes `owned` and `min_access_level` have precedence |
| `search` | string | no | Return the list of authorized groups matching the search criteria |
| `order_by` | string | no | Order groups by `name`, `path` or `id`. Default is `name` |
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
-| `statistics` | boolean | no | Include group statistics (admins only) |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| `statistics` | boolean | no | Include group statistics (administrators only) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
| `min_access_level` | integer | no | Limit to groups where current user has at least this [access level](members.md#valid-access-levels) |
@@ -188,12 +188,12 @@ Parameters:
| ------------------------ | ----------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) of the immediate parent group |
| `skip_groups` | array of integers | no | Skip the group IDs passed |
-| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin). Attributes `owned` and `min_access_level` have precedence |
+| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for administrators). Attributes `owned` and `min_access_level` have precedence |
| `search` | string | no | Return the list of authorized groups matching the search criteria |
| `order_by` | string | no | Order groups by `name`, `path`, or `id`. Default is `name` |
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
-| `statistics` | boolean | no | Include group statistics (admins only) |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| `statistics` | boolean | no | Include group statistics (administrators only) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
| `min_access_level` | integer | no | Limit to groups where current user has at least this [access level](members.md#valid-access-levels) |
@@ -284,7 +284,7 @@ Parameters:
| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
| `min_access_level` | integer | no | Limit to projects where current user has at least this [access level](members.md#valid-access-levels) |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
| `with_security_reports` | boolean | no | **(ULTIMATE)** Return only projects that have security reports artifacts present in any of their builds. This means "projects with security reports enabled". Default is `false` |
1. Order by similarity: Orders the results by a similarity score calculated from the provided `search`
@@ -366,7 +366,7 @@ Parameters:
| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
| `min_access_level` | integer | no | Limit to projects where current user has at least this [access level](members.md#valid-access-levels) |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
Example response:
@@ -479,7 +479,7 @@ Example response:
## Details of a group
Get all details of a group. This endpoint can be accessed without authentication
-if the group is publicly accessible. In case the user that requests is admin of the group, it returns the `runners_token` for the group too.
+if the group is publicly accessible. In case the user that requests is administrator of the group, it returns the `runners_token` for the group too.
```plaintext
GET /groups/:id
@@ -490,7 +490,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------------ | -------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only). |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only). |
| `with_projects` | boolean | no | Include details from projects that belong to the specified group (defaults to `true`). (Deprecated, [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797). To get the details of all projects within a group, use the [list a group's projects endpoint](#list-a-groups-projects).) |
NOTE:
@@ -670,7 +670,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see
the `shared_runners_minutes_limit` and `extra_shared_runners_minutes_limit` parameters:
Additional response parameters:
@@ -685,7 +685,7 @@ Additional response parameters:
}
```
-Users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see
the `marked_for_deletion_on` attribute:
```json
@@ -764,8 +764,8 @@ Parameters:
| `request_access_enabled` | boolean | no | Allow users to request member access. |
| `parent_id` | integer | no | The parent group ID for creating nested group. |
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). Default to the global level default branch protection setting. |
-| `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
-| `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
+| `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
+| `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
### Options for `default_branch_protection`
@@ -838,8 +838,8 @@ PUT /groups/:id
| `request_access_enabled` | boolean | no | Allow users to request member access. |
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). |
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
-| `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
-| `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
+| `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
+| `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
| `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces
| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. |
@@ -941,6 +941,19 @@ The `shared_runners_setting` attribute determines whether shared runners are ena
| `disabled_with_override` | Disables shared runners for all projects and subgroups in this group, but allows subgroups to override this setting. |
| `disabled_and_unoverridable` | Disables shared runners for all projects and subgroups in this group, and prevents subgroups from overriding this setting. |
+### Upload a group avatar
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) in GitLab 12.9.
+
+To upload an avatar file from your file system, use the `--form` argument. This causes
+curl to post data using the header `Content-Type: multipart/form-data`. The
+`file=` parameter must point to a file on your file system and be preceded by
+`@`. For example:
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/22" --form "avatar=@/tmp/example.png"
+```
+
## Remove group
Only available to group owners and administrators.
@@ -948,7 +961,7 @@ Only available to group owners and administrators.
This endpoint either:
- Removes group, and queues a background job to delete all projects in the group as well.
-- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, marks a group for deletion. The deletion happens 7 days later by default, but this can be changed in the [instance settings](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
+- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium](https://about.gitlab.com/pricing/) or higher tiers, marks a group for deletion. The deletion happens 7 days later by default, but this can be changed in the [instance settings](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
```plaintext
DELETE /groups/:id
@@ -997,7 +1010,7 @@ GET /groups?search=foobar
]
```
-## Hooks
+## Hooks **(PREMIUM)**
Also called Group Hooks and Webhooks.
These are different from [System Hooks](system_hooks.md) that are system wide and [Project Hooks](projects.md#hooks) that are limited to one project.
@@ -1044,6 +1057,7 @@ GET /groups/:id/hooks/:hook_id
"wiki_page_events": true,
"deployment_events": true,
"releases_events": true,
+ "subgroup_events": true,
"enable_ssl_verification": true,
"created_at": "2012-10-12T17:04:47Z"
}
@@ -1073,6 +1087,7 @@ POST /groups/:id/hooks
| `wiki_page_events` | boolean | no | Trigger hook on wiki events |
| `deployment_events` | boolean | no | Trigger hook on deployment events |
| `releases_events` | boolean | no | Trigger hook on release events |
+| `subgroup_events` | boolean | no | Trigger hook on subgroup events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
| `token` | string | no | Secret token to validate received payloads; not returned in the response |
@@ -1101,6 +1116,7 @@ PUT /groups/:id/hooks/:hook_id
| `wiki_events` | boolean | no | Trigger hook on wiki events |
| `deployment_events` | boolean | no | Trigger hook on deployment events |
| `releases_events` | boolean | no | Trigger hook on release events |
+| `subgroup_events` | boolean | no | Trigger hook on subgroup events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
| `token` | string | no | Secret token to validate received payloads; not returned in the response |
@@ -1122,7 +1138,7 @@ DELETE /groups/:id/hooks/:hook_id
Group audit events can be accessed via the [Group Audit Events API](audit_events.md#group-audit-events)
-## Sync group with LDAP **(STARTER ONLY)**
+## Sync group with LDAP **(PREMIUM SELF)**
Syncs the group with its linked LDAP group. Only available to group owners and administrators.
@@ -1142,7 +1158,7 @@ Please consult the [Group Members](members.md) documentation.
List, add, and delete LDAP group links.
-### List LDAP group links **(STARTER ONLY)**
+### List LDAP group links **(PREMIUM SELF)**
Lists LDAP group links.
@@ -1154,7 +1170,7 @@ GET /groups/:id/ldap_group_links
| --------- | -------------- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
-### Add LDAP group link with CN or filter **(STARTER ONLY)**
+### Add LDAP group link with CN or filter **(PREMIUM SELF)**
Adds an LDAP group link using a CN or filter. Adding a group link by filter is only supported in the Premium tier and above.
@@ -1173,7 +1189,7 @@ POST /groups/:id/ldap_group_links
NOTE:
To define the LDAP group link, provide either a `cn` or a `filter`, but not both.
-### Delete LDAP group link **(STARTER ONLY)**
+### Delete LDAP group link **(PREMIUM SELF)**
Deletes an LDAP group link. Deprecated. Scheduled for removal in a future release.
@@ -1198,7 +1214,7 @@ DELETE /groups/:id/ldap_group_links/:provider/:cn
| `cn` | string | yes | The CN of an LDAP group |
| `provider` | string | yes | LDAP provider for the LDAP group link |
-### Delete LDAP group link with CN or filter **(STARTER ONLY)**
+### Delete LDAP group link with CN or filter **(PREMIUM SELF)**
Deletes an LDAP group link using a CN or filter. Deleting by filter is only supported in the Premium tier and above.
@@ -1306,7 +1322,7 @@ GET /groups/:id/push_rule
}
```
-Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see
the `commit_committer_check` and `reject_unsigned_commits` parameters:
```json
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index d5c033563d6..99717ba939d 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -4,14 +4,14 @@ 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
---
-# Instance clusters API
+# Instance clusters API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36001) in GitLab 13.2.
Instance-level Kubernetes clusters allow you to connect a Kubernetes cluster to the GitLab instance, which enables you to use the same cluster across multiple projects. [More information](../user/instance/clusters/index.md)
NOTE:
-Users need admin access to use these endpoints.
+Users need administrator access to use these endpoints.
## List instance clusters
diff --git a/doc/api/issue_links.md b/doc/api/issue_links.md
index b94207f8e16..0d55b77df0e 100644
--- a/doc/api/issue_links.md
+++ b/doc/api/issue_links.md
@@ -4,9 +4,9 @@ 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
---
-# Issue links API **(CORE)**
+# Issue links API **(FREE)**
-> The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.4.
+> 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.
## List issue relations
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 1abb4fe3b4a..c333967b36c 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -60,8 +60,8 @@ GET /issues?state=opened
| `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 in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ |
| `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` |
-| `iteration_id` **(STARTER)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)_ |
-| `iteration_title` **(STARTER)** | string | no | Return issues assigned to the iteration with the given title. Similar to `iteration_id` and mutually exclusive with `iteration_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)_ |
+| `iteration_id` **(PREMIUM)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
+| `iteration_title` **(PREMIUM)** | string | no | Return issues assigned to the iteration with the given title. Similar to `iteration_id` and mutually exclusive with `iteration_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)_ |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
@@ -169,7 +169,7 @@ Example response:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -183,7 +183,7 @@ the `weight` parameter:
]
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -347,7 +347,7 @@ Example response:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -361,7 +361,7 @@ the `weight` parameter:
]
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -530,7 +530,7 @@ Example response:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -544,7 +544,7 @@ the `weight` parameter:
]
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -684,7 +684,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -696,7 +696,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `epic` property:
```javascript
@@ -833,7 +833,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -845,7 +845,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Premium](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium](https://about.gitlab.com/pricing/) can also see
the `epic` property:
```javascript
@@ -864,7 +864,7 @@ the `epic` property:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see the `health_status`
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see the `health_status`
property:
```json
@@ -980,7 +980,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -992,7 +992,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -1133,7 +1133,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -1145,7 +1145,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -1298,7 +1298,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
@@ -1310,7 +1310,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -1421,7 +1421,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see
the `weight` parameter:
```json
diff --git a/doc/api/iterations.md b/doc/api/iterations.md
index 1ee489e4cf1..be52ef0ea47 100644
--- a/doc/api/iterations.md
+++ b/doc/api/iterations.md
@@ -4,9 +4,10 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Project iterations API **(STARTER)**
+# Project iterations API **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.5.
+> - Moved to GitLab Premium in 13.9.
This page describes the project iterations API.
There's a separate [group iterations API](group_iterations.md) page.
@@ -51,7 +52,8 @@ Example response:
"created_at": "2020-01-27T05:07:12.573Z",
"updated_at": "2020-01-27T05:07:12.573Z",
"due_date": "2020-02-01",
- "start_date": "2020-02-14"
+ "start_date": "2020-02-14",
+ "web_url": "http://gitlab.example.com/groups/my-group/-/iterations/13"
}
]
```
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index b7b742ebe66..18d2e5ec3df 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -54,6 +54,9 @@ Example of response
{"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"}
],
"artifacts_expire_at": "2016-01-23T17:54:27.895Z",
+ "tag_list": [
+ "docker runner", "ubuntu18"
+ ],
"id": 7,
"name": "teaspoon",
"pipeline": {
@@ -104,6 +107,9 @@ Example of response
"finished_at": "2015-12-24T17:54:24.921Z",
"duration": 0.192,
"artifacts_expire_at": "2016-01-23T17:54:24.921Z",
+ "tag_list": [
+ "docker runner", "win10-2004"
+ ],
"id": 6,
"name": "rspec:other",
"pipeline": {
@@ -148,11 +154,12 @@ Get a list of jobs for a pipeline.
GET /projects/:id/pipelines/:pipeline_id/jobs
```
-| Attribute | Type | Required | Description |
-|---------------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.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 | yes | ID or [URL-encoded path of the project](README.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. |
+| `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. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running"
@@ -179,6 +186,9 @@ Example of response
"finished_at": "2015-12-24T17:54:24.921Z",
"duration": 0.192,
"artifacts_expire_at": "2016-01-23T17:54:24.921Z",
+ "tag_list": [
+ "docker runner", "ubuntu18"
+ ],
"id": 6,
"name": "rspec:other",
"pipeline": {
@@ -239,6 +249,9 @@ Example of response
{"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"}
],
"artifacts_expire_at": "2016-01-23T17:54:27.895Z",
+ "tag_list": [
+ "docker runner", "ubuntu18"
+ ],
"id": 7,
"name": "teaspoon",
"pipeline": {
@@ -248,7 +261,6 @@ Example of response
"status": "pending"
},
"ref": "master",
- "artifacts": [],
"runner": null,
"stage": "test",
"status": "failed",
@@ -278,6 +290,12 @@ Example of response
In GitLab 13.3 and later, this endpoint [returns data for any pipeline](pipelines.md#single-pipeline-requests)
including [child pipelines](../ci/parent_child_pipelines.md).
+In GitLab 13.5 and later, this endpoint does not return retried jobs in the response
+by default.
+
+In GitLab 13.9 and later, this endpoint can include retried jobs in the response
+with `include_retried` set to `true`.
+
## List pipeline bridges
Get a list of bridge jobs for a pipeline.
@@ -399,6 +417,9 @@ Example of response
"finished_at": "2015-12-24T17:54:31.198Z",
"duration": 0.465,
"artifacts_expire_at": "2016-01-23T17:54:31.198Z",
+ "tag_list": [
+ "docker runner", "macos-10.15"
+ ],
"id": 8,
"name": "rubocop",
"pipeline": {
diff --git a/doc/api/keys.md b/doc/api/keys.md
index dccea1f0e0a..98159bcf027 100644
--- a/doc/api/keys.md
+++ b/doc/api/keys.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Keys API
+# Keys API **(FREE)**
## Get SSH key with user by ID of an SSH key
diff --git a/doc/api/license.md b/doc/api/license.md
index 9aaf68d5b89..7aa00335933 100644
--- a/doc/api/license.md
+++ b/doc/api/license.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
---
-# License **(CORE ONLY)**
+# License **(FREE SELF)**
To interact with license endpoints, you need to authenticate yourself as an
administrator.
diff --git a/doc/api/license_templates.md b/doc/api/license_templates.md
deleted file mode 100644
index 7587721968b..00000000000
--- a/doc/api/license_templates.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'templates/licenses.md'
----
-
-This document was moved to [another location](templates/licenses.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/lint.md b/doc/api/lint.md
index 48a7be13a28..867a5e54663 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -13,6 +13,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Checks if CI/CD YAML configuration is valid. This endpoint validates basic CI/CD
configuration syntax. It doesn't have any namespace specific context.
+Access to this endpoint requires authentication.
+
```plaintext
POST /ci/lint
```
@@ -23,7 +25,7 @@ POST /ci/lint
| `include_merged_yaml` | boolean | no | If the [expanded CI/CD configuration](#yaml-expansion) should be included in the response. |
```shell
-curl --header "Content-Type: application/json" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
+curl --header "Content-Type: application/json" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
```
Be sure to paste the exact contents of your GitLab CI/CD YAML configuration because YAML
diff --git a/doc/api/markdown.md b/doc/api/markdown.md
index c7908f02b6e..157714c2791 100644
--- a/doc/api/markdown.md
+++ b/doc/api/markdown.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Markdown API
+# Markdown API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18926) in GitLab 11.0.
diff --git a/doc/api/members.md b/doc/api/members.md
index 47b686d9275..bf2bf8c1220 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -284,6 +284,7 @@ Example response:
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
+ "last_activity_on": "2021-01-27"
},
{
"id": 2,
@@ -292,7 +293,8 @@ Example response:
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
- "email": "john@example.com"
+ "email": "john@example.com",
+ "last_activity_on": "2021-01-25"
},
{
"id": 3,
@@ -300,7 +302,8 @@ Example response:
"name": "Foo bar",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
- "web_url": "http://192.168.1.8:3000/root"
+ "web_url": "http://192.168.1.8:3000/root",
+ "last_activity_on": "2021-01-20"
}
]
```
@@ -319,7 +322,7 @@ POST /projects/:id/members
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer/string | yes | The user ID of the new member or multiple IDs separated by commas |
| `access_level` | integer | yes | A valid access level |
-| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
+| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=1&access_level=30" "https://gitlab.example.com/api/v4/groups/:id/members"
@@ -357,7 +360,7 @@ PUT /projects/:id/members/:user_id
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the member |
| `access_level` | integer | yes | A valid access level |
-| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
+| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id?access_level=40"
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index e3ebb61768e..5b8bad1d685 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Merge request approvals API **(STARTER)**
+# Merge request approvals API **(PREMIUM)**
Configuration for approvals on all Merge Requests (MR) in the project. Must be authenticated for all endpoints.
@@ -13,7 +13,8 @@ Configuration for approvals on all Merge Requests (MR) in the project. Must be a
### Get Configuration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
+> - Moved to GitLab Premium in 13.9.
You can request information about a project's approval configuration using the
following endpoint:
@@ -41,7 +42,8 @@ GET /projects/:id/approvals
### Change configuration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
+> - Moved to GitLab Premium in 13.9.
If you are allowed to, you can change approval configuration using the following
endpoint:
@@ -75,7 +77,8 @@ POST /projects/:id/approvals
### Get project-level rules
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
> - `protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7.
You can request information about a project's approval rules using the following endpoint:
@@ -273,7 +276,8 @@ GET /projects/:id/approval_rules/:approval_rule_id
### Create project-level rule
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can create project approval rules using the following endpoint:
@@ -375,7 +379,8 @@ POST /projects/:id/approval_rules
### Update project-level rule
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can update project approval rules using the following endpoint:
@@ -480,7 +485,8 @@ PUT /projects/:id/approval_rules/:approval_rule_id
### Delete project-level rule
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can delete project approval rules using the following endpoint:
@@ -497,7 +503,8 @@ DELETE /projects/:id/approval_rules/:approval_rule_id
### Change allowed approvers
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
+> - Moved to GitLab Premium in 13.9.
NOTE:
This API endpoint has been deprecated. Please use Approval Rule API instead.
@@ -566,7 +573,8 @@ Configuration for approvals on a specific Merge Request. Must be authenticated f
### Get Configuration
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 8.9.
+> - Introduced in GitLab 8.9.
+> - Moved to GitLab Premium in 13.9.
You can request information about a merge request's approval status using the
following endpoint:
@@ -612,7 +620,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/approvals
### Change approval configuration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
+> - Moved to GitLab Premium in 13.9.
If you are allowed to, you can change `approvals_required` using the following
endpoint:
@@ -648,7 +657,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/approvals
### Change allowed approvers for Merge Request
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in GitLab 10.6.
+> - Moved to GitLab Premium in 13.9.
NOTE:
This API endpoint has been deprecated. Please use Approval Rule API instead.
@@ -722,7 +732,8 @@ PUT /projects/:id/merge_requests/:merge_request_iid/approvers
### Get the approval state of merge requests
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can request information about a merge request's approval state by using the following endpoint:
@@ -794,7 +805,8 @@ This includes additional information about the users who have already approved
### Get merge request level rules
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can request information about a merge request's approval rules using the following endpoint:
@@ -871,7 +883,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/approval_rules
### Create merge request level rule
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can create merge request approval rules using the following endpoint:
@@ -955,7 +968,8 @@ will be used.
### Update merge request level rule
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can update merge request approval rules using the following endpoint:
@@ -1040,7 +1054,8 @@ These are system generated rules.
### Delete merge request level rule
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
+> - Moved to GitLab Premium in 13.9.
You can delete merge request approval rules using the following endpoint:
@@ -1061,7 +1076,8 @@ These are system generated rules.
## Approve Merge Request
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 8.9.
+> - Introduced in GitLab 8.9.
+> - Moved to GitLab Premium in 13.9.
If you are allowed to, you can approve a merge request using the following
endpoint:
@@ -1077,7 +1093,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/approve
| `id` | integer | yes | The ID of a project |
| `merge_request_iid` | integer | yes | The IID of MR |
| `sha` | string | no | The HEAD of the MR |
-| `approval_password` **(STARTER)** | string | no | Current user's password. Required if [**Require user password to approve**](../user/project/merge_requests/merge_request_approvals.md#require-authentication-when-approving-a-merge-request) is enabled in the project settings. |
+| `approval_password` **(PREMIUM)** | string | no | Current user's password. Required if [**Require user password to approve**](../user/project/merge_requests/merge_request_approvals.md#require-authentication-when-approving-a-merge-request) 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
@@ -1124,7 +1140,8 @@ does not match, the response code will be `409`.
## Unapprove Merge Request
->Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 9.0.
+> - Introduced in GitLab 9.0.
+> - Moved to GitLab Premium in 13.9.
If you did approve a merge request, you can unapprove it using the following
endpoint:
diff --git a/doc/api/merge_request_context_commits.md b/doc/api/merge_request_context_commits.md
index 3873cb00033..0b4b96b889b 100644
--- a/doc/api/merge_request_context_commits.md
+++ b/doc/api/merge_request_context_commits.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Merge request context commits API
+# Merge request context commits API **(FREE)**
## List MR context commits
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index c43ac96a42f..d9bcba96fdc 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Merge requests API
+# Merge requests API **(FREE)**
> - `author_id`, `author_username`, and `assignee_id` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5.
> - `my_reaction_emoji` was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0.
@@ -15,6 +15,7 @@ type: reference, api
> - `reference` was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) in GitLab 12.10 in favour of `references`.
> - `with_merge_status_recheck` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0.
> - `reviewer_username` and `reviewer_id` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8.
+> - `reviewer_ids` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51186) in GitLab 13.8.
Every API call to merge requests must be authenticated.
@@ -30,7 +31,7 @@ If you need the value of these fields from this endpoint, set the `with_merge_st
`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` **(STARTER)** is not provided, it inherits the value from the target project. If provided, the following conditions must hold for it to take effect:
+- 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.
@@ -91,8 +92,8 @@ Parameters:
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. |
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. |
| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. |
-| `approver_ids` **(STARTER)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
-| `approved_by_ids` **(STARTER)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
+| `approver_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
+| `approved_by_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. |
| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. |
| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
@@ -216,7 +217,7 @@ Parameters:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
```json
@@ -277,8 +278,8 @@ Parameters:
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. |
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`.|
| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. |
-| `approver_ids` **(STARTER)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
-| `approved_by_ids` **(STARTER)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
+| `approver_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
+| `approved_by_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. |
| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. |
@@ -401,7 +402,7 @@ Parameters:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
```json
@@ -453,10 +454,10 @@ Parameters:
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_. |
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_. |
| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_. |
-| `approver_ids` **(STARTER)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
-| `approved_by_ids` **(STARTER)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
-| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#enable-or-disable-merge-request-reviewers) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. |
-| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#enable-or-disable-merge-request-reviewers) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. |
+| `approver_ids` **(PREMIUM))** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
+| `approved_by_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
+| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. |
+| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. |
| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_. |
| `source_branch` | string | no | Return merge requests with the given source branch. |
| `target_branch` | string | no | Return merge requests with the given target branch. |
@@ -574,7 +575,7 @@ Parameters:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
```json
@@ -745,7 +746,7 @@ Parameters:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium also see
the `approvals_before_merge` parameter:
```json
@@ -884,6 +885,14 @@ Parameters:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 4,
"target_project_id": 4,
"labels": [ ],
@@ -1051,7 +1060,8 @@ POST /projects/:id/merge_requests
| `target_branch` | string | yes | The target branch. |
| `title` | string | yes | Title of MR. |
| `assignee_id` | integer | no | Assignee user ID. |
-| `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
+| `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
+| `reviewer_ids` | integer array | no | The ID of the user(s) added as a reviewer to the MR. If set to `0` or left empty, there will be no reviewers added. |
| `description` | string | no | Description of MR. Limited to 1,048,576 characters. |
| `target_project_id` | integer | no | The target project (numeric ID). |
| `labels` | string | no | Labels for MR as a comma-separated list. |
@@ -1172,7 +1182,7 @@ POST /projects/:id/merge_requests
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see
the `approvals_before_merge` parameter:
```json
@@ -1200,6 +1210,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `title` | string | no | Title of MR. |
| `assignee_id` | integer | no | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. |
| `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
+| `reviewer_ids` | integer array | no | The ID of the user(s) set as a reviewer to the MR. Set the value to `0` or provide an empty value to unset all reviewers. |
| `milestone_id` | integer | no | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.|
| `labels` | string | no | Comma-separated label names for a merge request. Set to an empty string to unassign all labels. |
| `add_labels` | string | no | Comma-separated label names to add to a merge request. |
@@ -1252,6 +1263,14 @@ Must include at least one non-required attribute from above.
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1333,7 +1352,7 @@ Must include at least one non-required attribute from above.
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
```json
@@ -1386,7 +1405,7 @@ Parameters:
| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
| `merge_commit_message` | string | no | Custom merge commit message. |
| `squash_commit_message` | string | no | Custom squash commit message. |
-| `squash` | boolean | no | If `true` the commits the commits are squashed into a single commit on merge. |
+| `squash` | boolean | no | If `true` the commits are squashed into a single commit on merge. |
| `should_remove_source_branch` | boolean | no | If `true` removes the source branch. |
| `merge_when_pipeline_succeeds` | boolean | no | If `true` the MR is merged when the pipeline succeeds. |
| `sha` | string | no | If present, then this SHA must match the HEAD of the source branch, otherwise the merge fails. |
@@ -1429,6 +1448,14 @@ Parameters:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1510,7 +1537,7 @@ Parameters:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium also see
the `approvals_before_merge` parameter:
```json
@@ -1609,6 +1636,14 @@ Parameters:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1690,7 +1725,7 @@ Parameters:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
```json
@@ -1902,6 +1937,14 @@ Example response:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -1982,7 +2025,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium also see
the `approvals_before_merge` parameter:
```json
@@ -2053,6 +2096,14 @@ Example response:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 2,
"target_project_id": 3,
"labels": [
@@ -2133,7 +2184,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab Premium or higher also see
the `approvals_before_merge` parameter:
```json
@@ -2224,6 +2275,14 @@ Example response:
"avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
"web_url": "https://gitlab.example.com/axel.block"
}],
+ "reviewers": [{
+ "name": "Miss Monserrate Beier",
+ "username": "axel.block",
+ "id": 12,
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/axel.block"
+ }],
"source_project_id": 3,
"target_project_id": 3,
"labels": [],
@@ -2513,7 +2572,7 @@ Example response:
}
```
-## Approvals **(STARTER)**
+## Approvals
For approvals, please see [Merge Request Approvals](merge_request_approvals.md)
diff --git a/doc/api/metrics_dashboard_annotations.md b/doc/api/metrics_dashboard_annotations.md
index b92e26b03fb..896420ed0fb 100644
--- a/doc/api/metrics_dashboard_annotations.md
+++ b/doc/api/metrics_dashboard_annotations.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
-# Dashboard annotations API
+# Dashboard annotations API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29089) in GitLab 12.10 behind a disabled feature flag.
diff --git a/doc/api/metrics_user_starred_dashboards.md b/doc/api/metrics_user_starred_dashboards.md
index 79040333148..9178291181e 100644
--- a/doc/api/metrics_user_starred_dashboards.md
+++ b/doc/api/metrics_user_starred_dashboards.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
-# User-starred metrics dashboards API
+# User-starred metrics dashboards API **(FREE)**
The starred dashboard feature makes navigating to frequently-used dashboards easier
by displaying favorited dashboards at the top of the select list.
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 93b867c0286..15927ad852e 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -159,9 +159,10 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `milestone_id` (required) - The ID of a project milestone
-## Get all burndown chart events for a single milestone **(STARTER)**
+## Get all burndown chart events for a single milestone **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) in GitLab 12.1
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4737) in GitLab 12.1
+> - Moved to GitLab Premium in 13.9.
Gets all burndown chart events for a single milestone.
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 4e5a418be7a..a89e91f82e5 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Namespaces API
-Usernames and groupnames fall under a special category called namespaces.
+Usernames and group names fall under a special category called namespaces.
For users and groups supported API calls see the [users](users.md) and
[groups](groups.md) documentation respectively.
diff --git a/doc/api/notes.md b/doc/api/notes.md
index fe20d5ab353..8a443d57682 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -36,6 +36,11 @@ are paginated.
Read more on [pagination](README.md#pagination).
+## Rate limits
+
+To help avoid abuse, you can limit your users to a specific number of `Create` request per minute.
+See [Notes rate limits](../user/admin_area/settings/rate_limit_on_notes_creation.md).
+
## Issues
### List project issue notes
diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md
index 74746f60d7e..a85c6475331 100644
--- a/doc/api/notification_settings.md
+++ b/doc/api/notification_settings.md
@@ -196,7 +196,7 @@ Example responses:
}
```
-Users on GitLab [Ultimate or Gold](https://about.gitlab.com/pricing/) also see the `new_epic`
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) also see the `new_epic`
parameter:
```json
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index a80a97890ba..92d109cac5f 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -21,7 +21,7 @@ GitLab currently supports the following authorization flows:
- **Authorization code with [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636):**
Most secure. Without PKCE, you'd have to include client secrets on mobile clients,
- and is recommended for both client and server aoos.
+ and is recommended for both client and server apps.
- **Authorization code:** Secure and common flow. Recommended option for secure
server-side apps.
- **Implicit grant:** Originally designed for user-agent only apps, such as
@@ -89,7 +89,7 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD
`/oauth/authorize` page with the following query parameters:
```plaintext
- https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=YOUR_UNIQUE_STATE_HASH&scope=REQUESTED_SCOPES&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
+ https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
```
This page asks the user to approve the request from the app to access their
@@ -100,7 +100,7 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD
The redirect includes the authorization `code`, for example:
```plaintext
- https://example.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH
+ https://example.com/oauth/redirect?code=1234567890&state=STATE
```
1. With the authorization `code` returned from the previous request (denoted as
@@ -139,29 +139,31 @@ detailed flow description.
The authorization code flow is essentially the same as
[authorization code flow with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce),
+Before starting the flow, generate the `STATE`. It is a value that can't be predicted
+used by the client to maintain state between the request and callback. It should also
+be used as a CSRF token.
+
1. Request authorization code. To do that, you should redirect the user to the
- `/oauth/authorize` endpoint with the following GET parameters:
+ `/oauth/authorize` page with the following query parameters:
```plaintext
https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES
```
- This will ask the user to approve the applications access to their account
- based on the scopes specified in `REQUESTED_SCOPES` and then redirect back to
- the `REDIRECT_URI` you provided. The [scope parameter](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#requesting-particular-scopes)
- is a space separated list of scopes you want to have access to (e.g. `scope=read_user+profile`
- would request `read_user` and `profile` scopes). The redirect will
- include the GET `code` parameter, for example:
+ This page asks the user to approve the request from the app to access their
+ account based on the scopes specified in `REQUESTED_SCOPES`. The user is then
+ redirected back to the specified `REDIRECT_URI`. The [scope parameter](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#requesting-particular-scopes)
+ is a space separated list of scopes associated with the user.
+ For example,`scope=read_user+profile` requests the `read_user` and `profile` scopes.
+ The redirect includes the authorization `code`, for example:
```plaintext
https://example.com/oauth/redirect?code=1234567890&state=STATE
```
- You should then use `code` to request an access token.
-
-1. After you have the authorization code you can request an `access_token` using the
- code. You can do that by using any HTTP client. In the following example,
- we are using Ruby's `rest-client`:
+1. With the authorization `code` returned from the previous request (shown as
+ `RETURNED_CODE` in the following example), you can request an `access_token`, with
+ 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'
diff --git a/doc/api/openapi/img/apiviewer01-fs8.png b/doc/api/openapi/img/apiviewer01-fs8.png
new file mode 100644
index 00000000000..0a2f7062cc8
--- /dev/null
+++ b/doc/api/openapi/img/apiviewer01-fs8.png
Binary files differ
diff --git a/doc/api/openapi/img/apiviewer03-fs8.png b/doc/api/openapi/img/apiviewer03-fs8.png
new file mode 100644
index 00000000000..9fa00e830e7
--- /dev/null
+++ b/doc/api/openapi/img/apiviewer03-fs8.png
Binary files differ
diff --git a/doc/api/openapi/img/apiviewer04-fs8.png b/doc/api/openapi/img/apiviewer04-fs8.png
new file mode 100644
index 00000000000..bd878ba809b
--- /dev/null
+++ b/doc/api/openapi/img/apiviewer04-fs8.png
Binary files differ
diff --git a/doc/api/openapi/openapi_interactive.md b/doc/api/openapi/openapi_interactive.md
new file mode 100644
index 00000000000..0f1544b139d
--- /dev/null
+++ b/doc/api/openapi/openapi_interactive.md
@@ -0,0 +1,42 @@
+---
+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
+---
+
+# Interactive API documentation
+
+Introduces the interactive documentation tool for the GitLab API.
+
+## About the OpenAPI specification
+
+The [OpenAPI specification](https://swagger.io/specification/) (formerly called Swagger) defines a standard, language-agnostic interface to RESTful APIs. OpenAPI definition files are written in the YAML format, which is automatically rendered by the GitLab browser into a more human-readable interface. For general information about the GitLab APIs, see [API Docs](../README.md).
+
+## Overview
+
+The [interactive API documentation tool](openapi.yaml) allows API testing directly on the GitLab.com
+website. Only a few of the available endpoints are documented with the OpenAPI spec, but the current
+list demonstrates the functionality of the tool.
+
+![API viewer screenshot](img/apiviewer01-fs8.png)
+
+## Endpoint parameters
+
+When you expand an endpoint listing, you'll see a description, input parameters (if required),
+and example server responses. Some parameters include a default or a list of allowed values.
+
+![API viewer screenshot](img/apiviewer04-fs8.png)
+
+## Starting an interactive sesssion
+
+A [Personal access token](../../user/profile/personal_access_tokens.md) (PAT) is one way to
+start an interactive session. To do this, select **Authorize** from the main page, and a
+dialog box prompts you to enter your PAT, which is valid for the current web session.
+
+To test the endpoint, first select **Try it out** on the endpoint definition page. Input the parameters
+as required, then select **Execute**. In the following example, we executed a request for the `version`
+endpoint (no parameters required). The tool shows the `curl` command and URL of the request, followed
+by the server responses that are returned. You can create new responses by editing the relevant parameters
+and then select **Execute** once again.
+
+![API viewer screenshot](img/apiviewer03-fs8.png)
diff --git a/doc/api/packages.md b/doc/api/packages.md
index a0d966fdd88..112c7ef2e61 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -29,6 +29,7 @@ GET /projects/:id/packages
| `package_type` | string | no | Filter the returned packages by type. One of `conan`, `maven`, `npm`, `pypi`, `composer`, `nuget`, or `golang`. (_Introduced in GitLab 12.9_)
| `package_name` | string | no | Filter the project packages with a fuzzy search by name. (_Introduced in GitLab 12.9_)
| `include_versionless` | boolean | no | When set to true, versionless packages are included in the response. (_Introduced in GitLab 13.8_)
+| `status` | string | no | Filter the returned packages by status. One of `default` (default), `hidden`, or `processing`. (_Introduced in GitLab 13.9_)
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages"
@@ -70,6 +71,9 @@ Example response:
By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination).
+Although you can filter packages by status, working with packages that have a `processing` status
+can result in malformed data or broken packages.
+
### Within a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18871) in GitLab 12.5.
@@ -90,9 +94,10 @@ GET /groups/:id/packages
| `package_type` | string | no | Filter the returned packages by type. One of `conan`, `maven`, `npm`, `pypi`, `composer`, `nuget`, or `golang`. (_Introduced in GitLab 12.9_) |
| `package_name` | string | no | Filter the project packages with a fuzzy search by name. (_[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30980) in GitLab 13.0_)
| `include_versionless` | boolean | no | When set to true, versionless packages are included in the response. (_Introduced in GitLab 13.8_)
+| `status` | string | no | Filter the returned packages by status. One of `default` (default), `hidden`, or `processing`. (_Introduced in GitLab 13.9_)
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=false"
```
> **Deprecation:**
@@ -166,6 +171,9 @@ The `_links` object contains the following properties:
- `web_path`: The path which you can visit in GitLab and see the details of the package.
- `delete_api_path`: The API path to delete the package. Only available if the request user has permission to do so.
+Although you can filter packages by status, working with packages that have a `processing` status
+can result in malformed data or broken packages.
+
## Get a project package
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9667) in GitLab 11.9.
@@ -264,7 +272,7 @@ GET /projects/:id/packages/:package_id/package_files
| `package_id` | integer | yes | ID of a package. |
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/packages/4/package_files"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages/4/package_files"
```
Example response:
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index ca0ac3522c3..4949bf504fa 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -11,7 +11,7 @@ You can read more about [personal access tokens](../user/profile/personal_access
## List personal access tokens
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227264) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.6.
Get a list of personal access tokens.
@@ -71,7 +71,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
## Revoke a personal access token
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216004) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.6.
Revoke a personal access token.
diff --git a/doc/api/project_aliases.md b/doc/api/project_aliases.md
index 270c88ca661..439f34ad93b 100644
--- a/doc/api/project_aliases.md
+++ b/doc/api/project_aliases.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Project Aliases API **(PREMIUM ONLY)**
+# Project Aliases API **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1.
diff --git a/doc/api/project_analytics.md b/doc/api/project_analytics.md
index 97b15cc2c88..d89c173dd3e 100644
--- a/doc/api/project_analytics.md
+++ b/doc/api/project_analytics.md
@@ -1,52 +1,8 @@
---
-stage: Release
-group: Release
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference, api
+redirect_to: 'dora4_project_analytics.md'
---
-# Project Analytics API **(ULTIMATE ONLY)**
+This document was moved to [another location](dora4_project_analytics.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.
-
-All methods require reporter authorization.
-
-## List project deployment frequencies
-
-Get a list of all project aliases:
-
-```plaintext
-GET /projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval
-```
-
-| Attribute | Type | Required | Description |
-|--------------|--------|----------|-----------------------|
-| `id` | string | yes | The ID of the project |
-
-| Parameter | Type | Required | Description |
-|--------------|--------|----------|-----------------------|
-| `environment`| string | yes | The name of the environment to filter by |
-| `from` | string | yes | Datetime range to start from, inclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
-| `to` | string | no | Datetime range to end at, exclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
-| `interval` | string | no | The bucketing interval (`all`, `monthly`, `daily`) |
-
-```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/analytics/deployment_frequency?from=:from&to=:to&interval=:interval"
-```
-
-Example response:
-
-```json
-[
- {
- "from": "2017-01-01",
- "to": "2017-01-02",
- "value": 106
- },
- {
- "from": "2017-01-02",
- "to": "2017-01-03",
- "value": 55
- }
-]
-```
+<!-- This redirect file can be deleted after <2021-04-25>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md
index 2ca22baf654..041f67157f7 100644
--- a/doc/api/project_badges.md
+++ b/doc/api/project_badges.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Project badges API
+# Project badges API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) in GitLab 10.6.
@@ -13,11 +13,14 @@ type: reference, api
Badges support placeholders that will be replaced in real time in both the link and image URL. The allowed placeholders are:
+<!-- vale gitlab.Spelling = NO -->
+
- **%{project_path}**: will be replaced by the project path.
- **%{project_id}**: will be replaced by the project ID.
- **%{default_branch}**: will be replaced by the project default branch.
- **%{commit_sha}**: will be replaced by the last project's commit SHA.
+<!-- vale gitlab.Spelling = YES -->
## List all badges of a project
Gets a list of a project's badges and its group badges.
@@ -103,9 +106,10 @@ POST /projects/:id/badges
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `link_url` | string | yes | URL of the badge link |
| `image_url` | string | yes | URL of the badge image |
+| `name` | string | no | Name of the badge |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&position=0" "https://gitlab.example.com/api/v4/projects/:id/badges"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "link_url=https://gitlab.com/gitlab-org/gitlab-foss/commits/master&image_url=https://shields.io/my/badge1&name=mybadge" "https://gitlab.example.com/api/v4/projects/:id/badges"
```
Example response:
@@ -113,6 +117,7 @@ Example response:
```json
{
"id": 1,
+ "name": "mybadge",
"link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master",
"image_url": "https://shields.io/my/badge1",
"rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master",
@@ -135,6 +140,7 @@ PUT /projects/:id/badges/:badge_id
| `badge_id` | integer | yes | The badge ID |
| `link_url` | string | no | URL of the badge link |
| `image_url` | string | no | URL of the badge image |
+| `name` | string | no | Name of the badge |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/badges/:badge_id"
@@ -145,6 +151,7 @@ Example response:
```json
{
"id": 1,
+ "name": "mybadge",
"link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master",
"image_url": "https://shields.io/my/badge",
"rendered_link_url": "https://gitlab.com/gitlab-org/gitlab-foss/commits/master",
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index 3cc8cd07923..a431e754774 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.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
---
-# Project clusters API
+# Project clusters API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) in GitLab 11.7.
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 0711cc8abd6..cd8adf49f1d 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -5,14 +5,14 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Project import/export API
+# Project import/export API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41899) in GitLab 10.6.
See also:
- [Project import/export documentation](../user/project/settings/import_export.md).
-- [Project import/export administration Rake tasks](../administration/raketasks/project_import_export.md). **(CORE ONLY)**
+- [Project import/export administration Rake tasks](../administration/raketasks/project_import_export.md). **(FREE SELF)**
## Schedule an export
@@ -194,7 +194,7 @@ requests.post(url, headers=headers, data=data, files=files)
NOTE:
The maximum import file size can be set by the Administrator, default is `0` (unlimited)..
-As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](settings.md#change-application-settings) or the [Admin UI](../user/admin_area/settings/account_and_limit_settings.md).
+As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](settings.md#change-application-settings) or the [Admin UI](../user/admin_area/settings/account_and_limit_settings.md). Default [modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8.
## Import status
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 413d89950cd..8ef887675e9 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -17,7 +17,7 @@ GET /projects/:id/variables
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables"
@@ -48,7 +48,7 @@ GET /projects/:id/variables/:key
| Attribute | Type | required | Description |
|-----------|---------|----------|-----------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
| `filter` | hash | no | Available filters: `[environment_scope]`. See the [`filter` parameter details](#the-filter-parameter). |
@@ -76,7 +76,7 @@ POST /projects/:id/variables
| Attribute | Type | required | Description |
|---------------------|---------|----------|-----------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
| `value` | string | yes | The `value` of a variable |
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
@@ -109,7 +109,7 @@ PUT /projects/:id/variables/:key
| Attribute | Type | required | Description |
|---------------------|---------|----------|-------------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
| `value` | string | yes | The `value` of a variable |
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
@@ -143,7 +143,7 @@ DELETE /projects/:id/variables/:key
| Attribute | Type | required | Description |
|-----------|---------|----------|-------------------------|
-| `id` | integer/string | yes | The ID of a project or [urlencoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
| `filter` | hash | no | Available filters: `[environment_scope]`. See the [`filter` parameter details](#the-filter-parameter). |
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index 52c357ca32a..be922b441d6 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Project repository storage moves API **(CORE ONLY)**
+# Project repository storage moves API **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0.
@@ -30,11 +30,10 @@ read-only. Please try again later.` message if they try to push new commits.
This API requires you to [authenticate yourself](README.md#authentication) as an administrator.
-Snippet repositories can be moved using the [Snippet repository storage moves API](snippet_repository_storage_moves.md).
+For other repository types see:
-## Limitations
-
-- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
+- [Snippet repository storage moves API](snippet_repository_storage_moves.md).
+- [Group repository storage moves API](group_repository_storage_moves.md).
## Retrieve all project repository storage moves
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index d264e68e96a..c5adf361fb6 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -225,8 +225,8 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
-- `ref` (required) - The name of a branch, tag or commit e.g. master
-- `file_path` (required) - The URL-encoded path to the file, e.g. snippet%2Erb
+- `ref` (required) - The name of a branch, tag or commit, such as `master`
+- `file_path` (required) - The URL-encoded path to the file, such as `snippet%2Erb`
Example request:
@@ -239,7 +239,7 @@ curl "https://gitlab.com/api/v4/projects/1/snippets/2/files/master/snippet%2Erb/
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29508) in GitLab 9.4.
-Available only for admins.
+Available only for users with Administrator [permissions](../user/permissions.md).
```plaintext
GET /projects/:id/snippets/:snippet_id/user_agent_detail
diff --git a/doc/api/project_statistics.md b/doc/api/project_statistics.md
index 984720ed56f..6a987b60f64 100644
--- a/doc/api/project_statistics.md
+++ b/doc/api/project_statistics.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Project statistics API
+# Project statistics API **(FREE)**
Every API call to [project](../user/project/index.md) statistics must be authenticated.
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index d75047d6cb3..6251d31660c 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Project templates API
+# Project templates API **(FREE)**
This API is a project-specific version of these endpoints:
@@ -34,7 +34,7 @@ GET /projects/:id/templates/:type
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
| `id` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template |
+| `type` | string | yes | The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template |
Example response (licenses):
@@ -94,14 +94,15 @@ Example response (licenses):
## Get one template of a particular type
```plaintext
-GET /projects/:id/templates/:type/:key
+GET /projects/:id/templates/:type/:name
```
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
| `id` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template |
-| `key` | string | yes | The key of the template, as obtained from the collection endpoint |
+| `name` | string | yes | The key of the template, as obtained from the collection endpoint |
+| `source_template_project_id` | integer | no | The project ID where a given template is being stored. This is useful when multiple templates from different projects have the same name. If multiple templates have the same name, the match from `closest ancestor` is returned if `source_template_project_id` is not specified |
| `project` | string | no | The project name to use when expanding placeholders in the template. Only affects licenses |
| `fullname` | string | no | The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses |
diff --git a/doc/api/projects.md b/doc/api/projects.md
index f9a4b3ba55e..321a95af8b5 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -298,11 +298,11 @@ When the user is authenticated and `simple` is not set this returns something li
```
NOTE:
-For users of GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/),
+For users of [GitLab Premium or higher](https://about.gitlab.com/pricing/),
the `marked_for_deletion_at` attribute has been deprecated, and is removed
in API v5 in favor of the `marked_for_deletion_on` attribute.
-Users of GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/)
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/)
can also see the `approvals_before_merge` parameter:
```json
@@ -933,7 +933,7 @@ GET /projects/:id
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/)
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/)
can also see the `approvals_before_merge` parameter:
```json
@@ -1053,7 +1053,7 @@ POST /projects
|-------------------------------------------------------------|---------|------------------------|-------------|
| `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 | no | One of `disabled`, `private` or `enabled` |
-| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
+| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
@@ -1081,8 +1081,8 @@ POST /projects
| `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` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
-| `mirror` **(STARTER)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
+| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
| `name` | string | **{check-circle}** Yes (if path isn't provided) | The name of the new project. Equals path if not provided. |
| `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`. |
@@ -1104,7 +1104,7 @@ POST /projects
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
-| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
| `template_project_id` **(PREMIUM)** | integer | **{dotted-circle}** No | When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. |
| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
@@ -1127,7 +1127,7 @@ POST /projects/user/:user_id
|-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
+| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
@@ -1153,8 +1153,8 @@ POST /projects/user/:user_id
| `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` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
-| `mirror` **(STARTER)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
+| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
| `name` | string | **{check-circle}** Yes | The name of the new 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`. |
@@ -1177,7 +1177,7 @@ POST /projects/user/:user_id
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
| `tag_list` | array | **{dotted-circle}** No | The list of tags for a project; put array of tags, that should be finally assigned to a project. |
-| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
| `user_id` | integer | **{check-circle}** Yes | The user ID of the project owner. |
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
@@ -1200,7 +1200,7 @@ PUT /projects/:id
|-------------------------------------------------------------|----------------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
-| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
+| `approvals_before_merge` **(PREMIUM)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). |
| `auto_devops_enabled` | boolean | **{dotted-circle}** No | Enable Auto DevOps for this project. |
@@ -1229,15 +1229,15 @@ PUT /projects/:id
| `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_overwrites_diverged_branches` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirror overwrites diverged branches. |
-| `mirror_trigger_builds` **(STARTER)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
-| `mirror_user_id` **(STARTER)** | integer | **{dotted-circle}** No | User responsible for all the activity surrounding a pull mirror event. _(admins only)_ |
-| `mirror` **(STARTER)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
+| `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. _(admins only)_ |
+| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a 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` **(STARTER)** | boolean | **{dotted-circle}** No | Only mirror protected branches. |
+| `only_mirror_protected_branches` **(PREMIUM)** | boolean | **{dotted-circle}** No | Only mirror protected branches. |
| `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` |
@@ -1280,6 +1280,8 @@ POST /projects/:id/fork
| `namespace_path` | string | **{dotted-circle}** No | The path of the namespace that the project is forked to. |
| `namespace` | integer/string | **{dotted-circle}** No | _(Deprecated)_ The ID or path of the namespace that the project is forked to. |
| `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. |
## List Forks of a project
@@ -1875,7 +1877,7 @@ This endpoint:
- Deletes a project including all associated resources (including issues and
merge requests).
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on
- [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, group
+ [Premium or higher](https://about.gitlab.com/pricing/) tiers, group
admins can [configure](../user/group/index.md#enabling-delayed-project-removal)
projects within a group to be deleted after a delayed period. When enabled,
actual deletion happens after the number of days specified in the
@@ -2185,8 +2187,6 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
## Start the Housekeeping task for a project
-> Introduced in GitLab 9.0.
-
```plaintext
POST /projects/:id/housekeeping
```
@@ -2195,9 +2195,9 @@ POST /projects/:id/housekeeping
|-----------|----------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. |
-## Push Rules **(STARTER)**
+## Push Rules **(PREMIUM)**
-### Get project push rules **(STARTER)**
+### Get project push rules **(PREMIUM)**
Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a
project.
@@ -2229,7 +2229,7 @@ GET /projects/:id/push_rule
}
```
-Users of GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/)
+Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/)
can also see the `commit_committer_check` and `reject_unsigned_commits`
parameters:
@@ -2243,7 +2243,7 @@ parameters:
}
```
-### Add project push rule **(STARTER)**
+### Add project push rule **(PREMIUM)**
Adds a push rule to a specified project.
@@ -2266,7 +2266,7 @@ POST /projects/:id/push_rule
| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. |
| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commit when it's not signed through GPG. |
-### Edit project push rule **(STARTER)**
+### Edit project push rule **(PREMIUM)**
Edits a push rule for a specified project.
@@ -2291,7 +2291,7 @@ PUT /projects/:id/push_rule
### Delete project push rule
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 9.0.
+> - Moved to GitLab Premium in 13.9.
Removes a push rule from a project. This is an idempotent method and can be
called multiple times. Either the push rule is available or not.
@@ -2438,9 +2438,10 @@ Read more in the [Project import/export](project_import_export.md) documentation
Read more in the [Project members](members.md) documentation.
-## Configure pull mirroring for a project **(STARTER)**
+## Configure pull mirroring for a project **(PREMIUM)**
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 11.2.
+> - Introduced in GitLab 11.
+> - 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 if the remote repository is publicly accessible or via `username/password` authentication. In case your HTTP repository is not publicly accessible, you can add the authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`, where password is a [personal access token](../user/profile/personal_access_tokens.md) with the API scope enabled.
@@ -2450,9 +2451,9 @@ The relevant API parameters to update are:
- `mirror`: Enables pull mirroring on project when set to `true`.
- `only_mirror_protected_branches`: Set to `true` for protected branches.
-## Start the pull mirroring process for a Project **(STARTER)**
+## Start the pull mirroring process for a Project **(PREMIUM)**
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
+> - Moved to GitLab Premium in 13.9.
```plaintext
POST /projects/:id/mirror/pull
diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md
index 1dd15231dd8..12ba40d5df5 100644
--- a/doc/api/protected_branches.md
+++ b/doc/api/protected_branches.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Protected branches API
+# Protected branches API **(FREE)**
> Introduced in GitLab 9.5.
@@ -62,7 +62,7 @@ Example response:
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab Premium or higher also see
the `user_id` and `group_id` parameters:
Example response:
@@ -133,7 +133,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab Premium or higher also see
the `user_id` and `group_id` parameters:
Example response:
@@ -182,9 +182,9 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
| `push_access_level` | string | no | Access levels allowed to push (defaults: `40`, maintainer access level) |
| `merge_access_level` | string | no | Access levels allowed to merge (defaults: `40`, maintainer access level) |
| `unprotect_access_level` | string | no | Access levels allowed to unprotect (defaults: `40`, maintainer access level) |
-| `allowed_to_push` | array | no | **(STARTER)** Array of access levels allowed to push, with each described by a hash |
-| `allowed_to_merge` | array | no | **(STARTER)** Array of access levels allowed to merge, with each described by a hash |
-| `allowed_to_unprotect` | array | no | **(STARTER)** Array of access levels allowed to unprotect, with each described by a hash |
+| `allowed_to_push` | array | no | **(PREMIUM)** Array of access levels allowed to push, with each described by a hash |
+| `allowed_to_merge` | array | no | **(PREMIUM)** Array of access levels allowed to merge, with each described by a hash |
+| `allowed_to_unprotect` | array | no | **(PREMIUM)** Array of access levels allowed to unprotect, with each described by a hash |
| `code_owner_approval_required` | boolean | no | **(PREMIUM)** Prevent pushes to this branch if it matches an item in the [`CODEOWNERS` file](../user/project/code_owners.md). (defaults: false) |
Example response:
@@ -215,7 +215,7 @@ Example response:
}
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab Premium or higher also see
the `user_id` and `group_id` parameters:
Example response:
@@ -252,7 +252,7 @@ Example response:
}
```
-### Example with user / group level access **(STARTER)**
+### Example with user / group level access **(PREMIUM)**
Elements in the `allowed_to_push` / `allowed_to_merge` / `allowed_to_unprotect` array should take the
form `{user_id: integer}`, `{group_id: integer}` or `{access_level: integer}`. Each user must have access to the project and each group must [have this project shared](../user/project/members/share_project_with_groups.md). These access levels allow [more granular control over protected branch access](../user/project/protected_branches.md#restricting-push-and-merge-access-to-certain-users) and were [added to the API](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3516) in GitLab 10.3 EE.
@@ -295,7 +295,9 @@ Example response:
}
```
-### Example with allow to push and allow to merge access **(STARTER)**
+### Example with allow to push and allow to merge access **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
Example request:
@@ -375,7 +377,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## Require code owner approvals for a single branch
-Update the "code owner approval required" option for the given protected branch protected branch.
+Update the "code owner approval required" option for the given protected branch.
```plaintext
PATCH /projects/:id/protected_branches/:name
diff --git a/doc/api/protected_tags.md b/doc/api/protected_tags.md
index 87bd7043121..63fa7183aab 100644
--- a/doc/api/protected_tags.md
+++ b/doc/api/protected_tags.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Protected tags API
+# Protected tags API **(FREE)**
> Introduced in GitLab 11.3.
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index a58d6246a63..be9512ed0e0 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -486,7 +486,7 @@ Example response:
}
```
-### Group milestones **(PREMIUM ONLY)**
+### Group milestones **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235391) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
@@ -495,7 +495,7 @@ array for [Create a release](#create-a-release) and [Update a release](#update-a
API calls. Only milestones associated with the project's group may be specified, and
adding milestones for ancestor groups raises an error.
-## Collect release evidence **(PREMIUM ONLY)**
+## Collect release evidence **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
diff --git a/doc/api/remote_mirrors.md b/doc/api/remote_mirrors.md
index c40aed534d5..638d4a3b917 100644
--- a/doc/api/remote_mirrors.md
+++ b/doc/api/remote_mirrors.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Project remote mirrors API
+# Project remote mirrors API **(FREE)**
[Push mirrors](../user/project/repository/repository_mirroring.md#pushing-to-a-remote-repository)
defined on a project's repository settings are called "remote mirrors", and the
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index efdf010e072..b0b3160e075 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Repositories API
+# Repositories API **(FREE)**
## List repository tree
@@ -18,14 +18,15 @@ This command provides essentially the same functionality as the `git ls-tree` co
GET /projects/:id/repository/tree
```
-Parameters:
+Supported attributes:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `path` (optional) - The path inside repository. Used to get content of subdirectories
-- `ref` (optional) - The name of a repository branch or tag or if not given the default branch
-- `recursive` (optional) - Boolean value used to get a recursive tree (false by default)
-- `per_page` (optional) - Number of results to show per page. If not specified, defaults to `20`.
- Read more on [pagination](README.md#pagination).
+| Attribute | Type | Required | Description |
+| :---------- | :------------- | :------- | :---------- |
+| `id` | integer/string | no | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `path` | string | yes | The path inside repository. Used to get content of subdirectories. |
+| `ref` | string | yes | The name of a repository branch or tag or if not given the default branch. |
+| `recursive` | boolean | yes | Boolean value used to get a recursive tree (false by default). |
+| `per_page` | integer | yes | Number of results to show per page. If not specified, defaults to `20`. [Learn more on pagination](README.md#pagination). |
```json
[
@@ -91,10 +92,12 @@ without authentication if the repository is publicly accessible.
GET /projects/:id/repository/blobs/:sha
```
-Parameters:
+Supported attributes:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `sha` (required) - The blob SHA
+| Attribute | Type | Required | Description |
+| :-------- | :------------- | :------- | :---------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `sha` | string | yes | The blob SHA. |
## Raw blob content
@@ -105,10 +108,12 @@ without authentication if the repository is publicly accessible.
GET /projects/:id/repository/blobs/:sha/raw
```
-Parameters:
+Supported attributes:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `sha` (required) - The blob SHA
+| Attribute | Type | Required | Description |
+| :-------- | :------- | :------- | :---------- |
+| `id` | datatype | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `sha` | datatype | yes | The blob SHA. |
## Get file archive
@@ -128,10 +133,14 @@ GET /projects/:id/repository/archive[.format]
`bz2`, `tar`, and `zip`. For example, specifying `archive.zip`
would send an archive in ZIP format.
-Parameters:
+Supported attributes:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `sha` (optional) - The commit SHA to download. A tag, branch reference, or SHA can be used. This defaults to the tip of the default branch if not specified. For example:
+| Attribute | Type | Required | Description |
+|:------------|:---------------|:---------|:----------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `sha` | string | no | The commit SHA to download. A tag, branch reference, or SHA can be used. This defaults to the tip of the default branch if not specified. |
+
+Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/<project_id>/repository/archive?sha=<commit_sha>"
@@ -146,21 +155,22 @@ publicly accessible. Note that diffs could have an empty diff string if [diff li
GET /projects/:id/repository/compare
```
-Parameters:
+Supported attributes:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `from` (required) - the commit SHA or branch name
-- `to` (required) - the commit SHA or branch name
-- `straight` (optional) - comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)'. Default is `false`.
+| Attribute | Type | Required | Description |
+| :--------- | :------------- | :------- | :---------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `from` | string | yes | The commit SHA or branch name. |
+| `to` | string | yes | The commit SHA or branch name. |
+| `straight` | boolean | no | Comparison method, `true` for direct comparison between `from` and `to` (`from`..`to`), `false` to compare using merge base (`from`...`to`)'. Default is `false`. |
```plaintext
GET /projects/:id/repository/compare?from=master&to=feature
```
-Response:
+Example response:
```json
-
{
"commit": {
"id": "12d65c8dd2b2676fa3ac47d955accc085a37a9c1",
@@ -203,15 +213,17 @@ GET /projects/:id/repository/contributors
```
WARNING:
-The `additions` and `deletions` attributes are deprecated [as of GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39653) because they [always return `0`](https://gitlab.com/gitlab-org/gitlab/-/issues/233119).
+The `additions` and `deletions` attributes are deprecated [as of GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39653), because they [always return `0`](https://gitlab.com/gitlab-org/gitlab/-/issues/233119).
-Parameters:
+Supported attributes:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `order_by` (optional) - Return contributors ordered by `name`, `email`, or `commits` (orders by commit date) fields. Default is `commits`
-- `sort` (optional) - Return contributors sorted in `asc` or `desc` order. Default is `asc`
+| Attribute | Type | Required | Description |
+| :--------- | :------------- | :------- | :---------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `order_by` | string | no | Return contributors ordered by `name`, `email`, or `commits` (orders by commit date) fields. Default is `commits`. |
+| `sort` | string | no | Return contributors sorted in `asc` or `desc` order. Default is `asc`. |
-Response:
+Example response:
```json
[{
@@ -237,10 +249,12 @@ Get the common ancestor for 2 or more refs (commit SHAs, branch names or tags).
GET /projects/:id/repository/merge_base
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed |
+| Attribute | Type | Required | Description |
+| --------- | -------------- | -------- | ------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed |
+
+Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209"
@@ -264,3 +278,283 @@ Example response:
"committed_date": "2014-02-27T08:03:18.000Z"
}
```
+
+## Generate changelog data
+
+> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/351) in GitLab 13.9.
+
+Generate changelog data based on commits in a repository.
+
+Given a version (using semantic versioning) and a range of commits,
+GitLab generates a changelog for all commits that use a particular
+[Git trailer](https://git-scm.com/docs/git-interpret-trailers).
+
+The output of this process is a new section in a changelog file in the Git
+repository of the given project. The output format is in Markdown, and can be
+customized.
+
+```plaintext
+POST /projects/:id/repository/changelog
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| :-------- | :------- | :--------- | :---------- |
+| `version` | string | yes | The version to generate the changelog for. The format must follow [semantic versioning](https://semver.org/). |
+| `from` | string | no | The start of the range of commits (as a SHA) to use for generating the changelog. This commit itself isn't included in the list. |
+| `to` | string | yes | The end of the range of commits (as a SHA) to use for the changelog. This commit _is_ included in the list. |
+| `date` | datetime | no | The date and time of the release, defaults to the current time. |
+| `branch` | string | no | The branch to commit the changelog changes to, defaults to the project's default branch. |
+| `trailer` | string | no | The Git trailer to use for including commits, defaults to `Changelog`. |
+| `file` | string | no | The file to commit the changes to, defaults to `CHANGELOG.md`. |
+| `message` | string | no | The commit message to produce when committing the changes, defaults to `Add changelog for version X` where X is the value of the `version` argument. |
+
+If the `from` attribute is unspecified, GitLab uses the Git tag of the last
+version that came before the version specified in the `version` attribute. For
+this to work, your project must create Git tags for versions using the
+following format:
+
+```plaintext
+vX.Y.Z
+```
+
+Where `X.Y.Z` is a version that follows semantic versioning. For example,
+consider a project with the following tags:
+
+- v1.0.0
+- v1.1.0
+- v2.0.0
+
+If the `version` attribute is `2.1.0`, GitLab uses tag v2.0.0. And when the
+version is `1.1.1`, or `1.2.0`, GitLab uses tag v1.1.0.
+
+If `from` is unspecified and no tag to use is found, the API produces an error.
+To solve such an error, you must explicitly specify a value for the `from`
+attribute.
+
+### How it works
+
+Changelogs are generated based on commit titles. Commits are only included if
+they contain a specific Git trailer. GitLab uses the value of this trailer to
+categorize the changes.
+
+GitLab uses Git trailers, because Git trailers are
+supported by Git out of the box. We use commits as input, as this is the only
+source of data every project uses. In addition, commits can be retrieved when
+operating on a mirror. This is important for GitLab itself, because during a security
+release we might need to include changes from both public projects and private
+security mirrors.
+
+Changelogs are generated by taking the title of the commits to include and using
+these as the changelog entries. You can enrich entries with additional data,
+such as a link to the merge request or details about the commit author. You can
+[customize the format of a changelog](#customize-the-changelog-output) section with a template.
+
+### Customize the changelog output
+
+The output is customized using a YAML configuration file stored in your
+project's Git repository. This file must reside in
+`.gitlab/changelog_config.yml`.
+
+You can set the following variables in this file:
+
+- `date_format`: the date format to use in the title of the newly added
+ changelog data. This uses regular `strftime` formatting.
+- `template`: a custom template to use for generating the changelog data.
+- `categories`: a hash that maps raw category names to the names to use in the
+ changelog.
+
+Using the default settings, generating a changelog results in a section along
+the lines of the following:
+
+```markdown
+## 1.0.0 (2021-01-05)
+
+### Features (4 changes)
+
+- [Feature 1](gitlab-org/gitlab@123abc) by @alice ([merge request](gitlab-org/gitlab!123))
+- [Feature 2](gitlab-org/gitlab@456abc) ([merge request](gitlab-org/gitlab!456))
+- [Feature 3](gitlab-org/gitlab@234abc) by @steve
+- [Feature 4](gitlab-org/gitlab@456)
+```
+
+Each section starts with a title that contains the version and release date.
+While the format of the date can be customized, the rest of the title can't be
+changed. When adding a new section, GitLab parses these titles to determine
+where in the file the new section should be placed. GitLab sorts sections
+according to their versions, not their dates.
+
+Each section can have categories, each with their
+corresponding changes. In the above example, "Features" is one such category.
+You can customize the format of these sections.
+
+The section names are derived from the values of the Git trailer used to include
+or exclude commits.
+
+For example, if the trailer to use is called `Changelog`,
+and its value is `feature`, then the commit is grouped in the `feature`
+category. The names of these raw values might differ from what you want to
+show in a changelog, you can remap them. Let's say we use the `Changelog`
+trailer and developers use the following values: `feature`, `bug`, and
+`performance`.
+
+You can remap these using the following YAML configuration file:
+
+```yaml
+---
+categories:
+ feature: Features
+ bug: Bug fixes
+ performance: Performance improvements
+```
+
+When generating the changelog data, the category titles are then `### Features`,
+`### Bug fixes`, and `### Performance improvements`.
+
+### Custom templates
+
+The category sections are generated using a template. The default template is as
+follows:
+
+```plaintext
+{% if categories %}
+{% each categories %}
+### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})
+
+{% each entries %}
+- [{{ title }}]({{ commit.reference }})\
+{% if author.contributor %} by {{ author.reference }}{% end %}\
+{% if merge_request %} ([merge request]({{ merge_request.reference }})){% end %}
+
+{% end %}
+
+{% end %}
+{% else %}
+No changes.
+{% end %}
+```
+
+The `{% ... %}` tags are for statements, and `{{ ... }}` is used for printing
+data. Statements must be terminated using a `{% end %}` tag. Both the `if` and
+`each` statements require a single argument.
+
+For example, if we have a variable `valid`, and we want to display "yes"
+when this value is true, and display "nope" otherwise. We can do so as follows:
+
+```plaintext
+{% if valid %}
+yes
+{% else %}
+nope
+{% end %}
+```
+
+The use of `else` is optional. A value is considered true when it's a non-empty
+value or boolean `true`. Empty arrays and hashes are considered false.
+
+Looping is done using `each`, and variables inside a loop are scoped to it.
+Referring to the current value in a loop is done using the variable tag `{{ it
+}}`. Other variables read their value from the current loop value. Take
+this template for example:
+
+```plaintext
+{% each users %}
+{{name}}
+{% end %}
+```
+
+Assuming `users` is an array of objects, each with a `name` field, this would
+then print the name of every user.
+
+Using variable tags, you can access nested objects. For example, `{{
+users.0.name }}` prints the name of the first user in the `users` variable.
+
+If a line ends in a backslash, the next newline is ignored. This allows you to
+wrap code across multiple lines, without introducing unnecessary newlines in the
+Markdown output.
+
+Tags that use `{%` and `%}` (known as expression tags) consume the newline that
+directly follows them, if any. This means that this:
+
+```plaintext
+---
+{% if foo %}
+bar
+{% end %}
+---
+```
+
+Compiles into this:
+
+```plaintext
+---
+bar
+---
+```
+
+Instead of this:
+
+```plaintext
+---
+
+bar
+
+---
+```
+
+You can specify a custom template in your configuration like so:
+
+```yaml
+---
+template: |
+ {% if categories %}
+ {% each categories %}
+ ### {{ title }}
+
+ {% each entries %}
+ - [{{ title }}]({{ commit.reference }})\
+ {% if author.contributor %} by {{ author.reference }}{% end %}
+
+ {% end %}
+
+ {% end %}
+ {% else %}
+ No changes.
+ {% end %}
+```
+
+Note that when specifying the template you should use `template: |` and not
+`template: >`, as the latter doesn't preserve newlines in the template.
+
+### Template data
+
+At the top level, the following variable is available:
+
+- `categories`: an array of objects, one for every changelog category.
+
+In a category, the following variables are available:
+
+- `title`: the title of the category (after it has been remapped).
+- `count`: the number of entries in this category.
+- `single_change`: a boolean that indicates if there is only one change (`true`),
+ or multiple changes (`false`).
+- `entries`: the entries that belong to this category.
+
+In an entry, the following variables are available (here `foo.bar` means that
+`bar` is a sub-field of `foo`):
+
+- `title`: the title of the changelog entry (this is the commit title).
+- `commit.reference`: a reference to the commit, for example,
+ `gitlab-org/gitlab@0a4cdd86ab31748ba6dac0f69a8653f206e5cfc7`.
+- `commit.trailers`: an object containing all the Git trailers that were present
+ in the commit body.
+- `author.reference`: a reference to the commit author (for example, `@alice`).
+- `author.contributor`: a boolean set to `true` when the author is an external
+ contributor, otherwise this is set to `false`.
+- `merge_request.reference`: a reference to the merge request that first
+ introduced the change (for example, `gitlab-org/gitlab!50063`).
+
+The `author` and `merge_request` objects might not be present if the data
+couldn't be determined. For example, when a commit is created without a
+corresponding merge request, no merge request is displayed.
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index ce11e5a38b7..19684b4ac0e 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Repository files API
+# Repository files API **(FREE)**
**CRUD for repository files**
diff --git a/doc/api/repository_submodules.md b/doc/api/repository_submodules.md
index 9c59920df77..c014bb44861 100644
--- a/doc/api/repository_submodules.md
+++ b/doc/api/repository_submodules.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Repository submodules API
+# Repository submodules API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41213) in GitLab 11.5
diff --git a/doc/api/resource_access_tokens.md b/doc/api/resource_access_tokens.md
new file mode 100644
index 00000000000..50f5ea73634
--- /dev/null
+++ b/doc/api/resource_access_tokens.md
@@ -0,0 +1,107 @@
+---
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Project access tokens API
+
+You can read more about [project access tokens](../user/project/settings/project_access_tokens.md).
+
+## List project access tokens
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
+
+Get a list of project access tokens.
+
+```plaintext
+GET projects/:id/access_tokens
+```
+
+| Attribute | Type | required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID of the project |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
+```
+
+```json
+[
+ {
+ "user_id" : 141,
+ "scopes" : [
+ "api"
+ ],
+ "name" : "token",
+ "expires_at" : "2021-01-31",
+ "id" : 42,
+ "active" : true,
+ "created_at" : "2021-01-20T22:11:48.151Z",
+ "revoked" : false
+ }
+]
+```
+
+## Create a project access token
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
+
+Create a project access token.
+
+```plaintext
+POST projects/:id/access_tokens
+```
+
+| Attribute | Type | required | Description |
+|-----------|---------|----------|---------------------|
+| `name` | String | yes | The name of the project access token |
+| `scopes` | Array\[String] | yes | [List of scopes](../user/project/settings/project_access_tokens.md#limiting-scopes-of-a-project-access-token) |
+| `expires_at` | Date | no | The token expires at midnight UTC on that date |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+--header "Content-Type:application/json" \
+--data '{ "name":"test_token", "scopes":["api", "read_repository"], "expires_at":"2021-01-31" }' \
+"https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
+```
+
+```json
+{
+ "scopes" : [
+ "api",
+ "read_repository"
+ ],
+ "active" : true,
+ "name" : "test",
+ "revoked" : false,
+ "created_at" : "2021-01-21T19:35:37.921Z",
+ "user_id" : 166,
+ "id" : 58,
+ "expires_at" : "2021-01-31"
+}
+```
+
+## Revoke a project access token
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
+
+Revoke a project access token.
+
+```plaintext
+DELETE projects/:id/access_tokens/:token_id
+```
+
+| Attribute | Type | required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID of the project |
+| `token_id` | integer/string | yes | The ID of the project access token |
+
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>"
+```
+
+### Responses
+
+- `204: No Content` if successfully revoked.
+- `400 Bad Request` or `404 Not Found` if not revoked successfully.
diff --git a/doc/api/resource_iteration_events.md b/doc/api/resource_iteration_events.md
index 4c351308ae1..91c7a1b07ea 100644
--- a/doc/api/resource_iteration_events.md
+++ b/doc/api/resource_iteration_events.md
@@ -4,10 +4,11 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Resource iteration events API **(STARTER)**
+# Resource iteration events API **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229463) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229463) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229463) in GitLab 13.4.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229463) in GitLab 13.5.
+> - Moved to GitLab Premium in 13.9.
Resource iteration events keep track of what happens to GitLab [issues](../user/project/issues/).
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 131418de725..1782e236c36 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -575,7 +575,7 @@ Example response:
```json
{
- "id": "12345",
+ "id": 12345,
"token": "6337ff461c94fd3fa32ba3b1ff4125"
}
```
diff --git a/doc/api/scim.md b/doc/api/scim.md
index 6e67b6fbc2d..d00a0988d2b 100644
--- a/doc/api/scim.md
+++ b/doc/api/scim.md
@@ -5,9 +5,9 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# SCIM API (SYSTEM ONLY) **(SILVER ONLY)**
+# SCIM API (SYSTEM ONLY) **(PREMIUM SAAS)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab Premium 11.10.
The SCIM API implements the [RFC7644 protocol](https://tools.ietf.org/html/rfc7644). As this API is for
**system** use for SCIM provider integration, it is subject to change without notice.
diff --git a/doc/api/search.md b/doc/api/search.md
index 584b2cbb837..9e1407fdffd 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Search API
+# Search API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41763) in GitLab 10.5.
> - [Feature flag `search_filter_by_confidential` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/244923) in GitLab 13.6.
@@ -31,7 +31,7 @@ GET /search
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, snippet_titles, users.
-If Elasticsearch is enabled additional scopes available are blobs, wiki_blobs, notes, and commits. Find more about [the feature](../integration/elasticsearch.md). **(STARTER)**
+If Elasticsearch is enabled additional scopes available are blobs, wiki_blobs, notes, and commits. Find more about [the feature](../integration/elasticsearch.md). **(PREMIUM)**
The response depends on the requested scope.
@@ -266,7 +266,9 @@ Example response:
]
```
-### Scope: wiki_blobs **(STARTER)**
+### Scope: wiki_blobs **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -295,7 +297,9 @@ Example response:
NOTE:
`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the filename and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521).
-### Scope: commits **(STARTER)**
+### Scope: commits **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -328,7 +332,9 @@ Example response:
]
```
-### Scope: blobs **(STARTER)**
+### Scope: blobs **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -367,7 +373,9 @@ Example response:
NOTE:
`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521).
-### Scope: notes **(STARTER)**
+### Scope: notes **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -444,7 +452,7 @@ GET /groups/:id/search
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users.
-If Elasticsearch is enabled additional scopes available are blobs, wiki_blobs, notes, and commits. Find more about [the feature](../integration/elasticsearch.md). **(STARTER)**
+If Elasticsearch is enabled additional scopes available are blobs, wiki_blobs, notes, and commits. Find more about [the feature](../integration/elasticsearch.md). **(PREMIUM)**
The response depends on the requested scope.
@@ -648,7 +656,9 @@ Example response:
]
```
-### Scope: wiki_blobs **(STARTER)**
+### Scope: wiki_blobs **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -677,7 +687,9 @@ Example response:
NOTE:
`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the filename and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521).
-### Scope: commits **(STARTER)**
+### Scope: commits **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -710,7 +722,9 @@ Example response:
]
```
-### Scope: blobs **(STARTER)**
+### Scope: blobs **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -749,7 +763,9 @@ Example response:
NOTE:
`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521).
-### Scope: notes **(STARTER)**
+### Scope: notes **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -998,7 +1014,9 @@ Example response:
]
```
-### Scope: notes **(STARTER)**
+### Scope: notes **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -1032,7 +1050,9 @@ Example response:
]
```
-### Scope: wiki_blobs **(STARTER)**
+### Scope: wiki_blobs **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -1078,7 +1098,9 @@ Example response:
NOTE:
`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the filename and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521).
-### Scope: commits **(STARTER)**
+### Scope: commits **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
@@ -1111,7 +1133,9 @@ Example response:
]
```
-### Scope: blobs **(STARTER)**
+### Scope: blobs **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
diff --git a/doc/api/services.md b/doc/api/services.md
index d00ddb07a05..16431937c7a 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -748,7 +748,7 @@ Send IRC messages, on update, to a list of recipients through an Irker gateway.
Set Irker (IRC gateway) service for a project.
NOTE:
-Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read: <http://www.catb.org/~esr/irker/security.html>.
+Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read [Security analysis of `irker`](http://www.catb.org/~esr/irker/security.html).
```plaintext
PUT /projects/:id/services/irker
@@ -1358,7 +1358,7 @@ Get JetBrains TeamCity CI service settings for a project.
GET /projects/:id/services/teamcity
```
-## Jenkins CI **(STARTER)**
+## Jenkins CI
A continuous integration and build server
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 264021b3a2d..2fd58917aad 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.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
---
-# Application settings API **(CORE ONLY)**
+# Application settings API **(FREE SELF)**
These API calls allow you to read and modify GitLab instance
[application settings](#list-of-settings-that-can-be-accessed-via-api-calls)
@@ -77,6 +77,7 @@ Example response:
"asset_proxy_enabled": true,
"asset_proxy_url": "https://assets.example.com",
"asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"],
+ "asset_proxy_allowlist": ["example.com", "*.example.com", "your-instance.com"],
"npm_package_requests_forwarding": true,
"snippet_size_limit": 52428800,
"issues_create_limit": 300,
@@ -84,7 +85,8 @@ Example response:
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
"personal_access_token_prefix": "GL-",
- "rate_limiting_response_text": null
+ "rate_limiting_response_text": null,
+ "keep_latest_artifact": true
}
```
@@ -166,7 +168,7 @@ Example response:
"local_markdown_version": 0,
"asset_proxy_enabled": true,
"asset_proxy_url": "https://assets.example.com",
- "asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"],
+ "asset_proxy_allowlist": ["example.com", "*.example.com", "your-instance.com"],
"geo_node_allowed_ips": "0.0.0.0/0, ::/0",
"allow_local_requests_from_hooks_and_services": true,
"allow_local_requests_from_web_hooks_and_services": true,
@@ -178,7 +180,8 @@ Example response:
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
"personal_access_token_prefix": "GL-",
- "rate_limiting_response_text": null
+ "rate_limiting_response_text": null,
+ "keep_latest_artifact": true
}
```
@@ -190,7 +193,7 @@ these parameters:
- `geo_status_timeout`
- `deletion_adjourned_period`
-Example responses: **(PREMIUM ONLY)**
+Example responses: **(PREMIUM SELF)**
```json
"file_template_project_id": 1,
@@ -219,7 +222,8 @@ listed in the descriptions of the relevant settings.
| `asset_proxy_enabled` | boolean | no | (**If enabled, requires:** `asset_proxy_url`) Enable proxying of assets. GitLab restart is required to apply changes. |
| `asset_proxy_secret_key` | string | no | Shared secret with the asset proxy server. GitLab restart is required to apply changes. |
| `asset_proxy_url` | string | no | URL of the asset proxy server. GitLab restart is required to apply changes. |
-| `asset_proxy_whitelist` | string or array of strings | no | Assets that match these domain(s) are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
+| `asset_proxy_whitelist` | string or array of strings | no | (Deprecated: Use `asset_proxy_allowlist` instead) Assets that match these domain(s) are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
+| `asset_proxy_allowlist` | string or array of strings | no | Assets that match these domain(s) are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
| `authorized_keys_enabled` | boolean | no | By default, we write to the `authorized_keys` file to support Git over SSH without additional configuration. GitLab can be optimized to authenticate SSH keys via the database file. Only disable this if you have configured your OpenSSH server to use the AuthorizedKeysCommand. |
| `auto_devops_domain` | string | no | Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages. |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for projects by default. It automatically builds, tests, and deploys applications based on a predefined CI/CD configuration. |
@@ -235,7 +239,7 @@ listed in the descriptions of the relevant settings.
| `default_project_visibility` | string | no | What visibility level new projects receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
| `default_projects_limit` | integer | no | Project limit per user. Default is `100000`. |
| `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
-| `deletion_adjourned_period` | integer | no | **(PREMIUM ONLY)** The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90.
+| `deletion_adjourned_period` | integer | no | **(PREMIUM SELF)** The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90.
| `diff_max_patch_bytes` | integer | no | Maximum diff patch size (Bytes). |
| `disable_feed_token` | boolean | no | Disable display of RSS/Atom and calendar feed tokens ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/231493) in GitLab 13.7) |
| `disabled_oauth_sign_in_sources` | array of strings | no | Disabled OAuth sign-in sources. |
@@ -280,6 +284,7 @@ listed in the descriptions of the relevant settings.
| `first_day_of_week` | integer | no | Start day of the week for calendar views and date pickers. Valid values are `0` (default) for Sunday, `1` for Monday, and `6` for Saturday. |
| `geo_node_allowed_ips` | string | yes | **(PREMIUM)** Comma-separated list of IPs and CIDRs of allowed secondary nodes. For example, `1.1.1.1, 2.2.2.0/24`. |
| `geo_status_timeout` | integer | no | **(PREMIUM)** The amount of seconds after which a request to get a secondary node status times out. |
+| `git_two_factor_session_expiry` | integer | no | **(PREMIUM)** Maximum duration (in minutes) of a session for Git operations when 2FA is enabled. |
| `gitaly_timeout_default` | integer | no | Default Gitaly timeout, in seconds. This timeout is not enforced for Git fetch/push operations or Sidekiq jobs. Set to `0` to disable timeouts. |
| `gitaly_timeout_fast` | integer | no | Gitaly fast operation timeout, in seconds. Some Gitaly operations are expected to be fast. If they exceed this threshold, there may be a problem with a storage shard and 'failing fast' can help maintain the stability of the GitLab instance. Set to `0` to disable timeouts. |
| `gitaly_timeout_medium` | integer | no | Medium Gitaly timeout, in seconds. This should be a value between the Fast and the Default timeout. Set to `0` to disable timeouts. |
@@ -300,22 +305,22 @@ listed in the descriptions of the relevant settings.
| `housekeeping_incremental_repack_period` | integer | required by: `housekeeping_enabled` | Number of Git pushes after which an incremental `git repack` is run. |
| `html_emails_enabled` | boolean | no | Enable HTML emails. |
| `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. |
-| `invisible_captcha_enabled` | boolean | no | Enable Invisible Captcha spam detection during signup. Disabled by default. |
+| `invisible_captcha_enabled` | boolean | no | <!-- vale gitlab.Spelling = NO --> Enable Invisible Captcha <!-- vale gitlab.Spelling = YES --> spam detection during sign-up. Disabled by default. |
| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.|
| `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. |
| `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode |
-| `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-admin users can sign in with read-only access and make read-only API requests |
+| `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-administrative users can sign in with read-only access and make read-only API requests |
| `max_artifacts_size` | integer | no | Maximum artifacts size in MB |
| `max_attachment_size` | integer | no | Limit attachment size in MB |
-| `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 0 (unlimited) |
+| `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 0 (unlimited) [Modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8. |
| `max_pages_size` | integer | no | Maximum size of pages repositories in MB |
-| `max_personal_access_token_lifetime` | integer | no | **(ULTIMATE ONLY)** Maximum allowable lifetime for personal access tokens in days |
+| `max_personal_access_token_lifetime` | integer | no | **(ULTIMATE SELF)** Maximum allowable lifetime for personal access tokens in days |
| `metrics_method_call_threshold` | integer | no | A method call is only tracked when it takes longer than the given amount of milliseconds. |
| `mirror_available` | boolean | no | Allow repository mirroring to configured by project Maintainers. If disabled, only Admins can configure repository mirroring. |
| `mirror_capacity_threshold` | integer | no | **(PREMIUM)** Minimum capacity to be available before scheduling more mirrors preemptively |
| `mirror_max_capacity` | integer | no | **(PREMIUM)** Maximum number of mirrors that can be synchronizing at the same time. |
| `mirror_max_delay` | integer | no | **(PREMIUM)** Maximum time (in minutes) between updates that a mirror can have when scheduled to synchronize. |
-| `npm_package_requests_forwarding` | boolean | no | **(PREMIUM)** Use npmjs.org as a default remote repository when the package is not found in the GitLab NPM Registry |
+| `npm_package_requests_forwarding` | boolean | no | **(PREMIUM)** Use npmjs.org as a default remote repository when the package is not found in the GitLab Package Registry for npm |
| `outbound_local_requests_whitelist` | array of strings | no | Define a list of trusted domains or IP addresses to which local requests are allowed when local requests for hooks and services are disabled.
| `pages_domain_verification_enabled` | boolean | no | Require users to prove ownership of custom domains. Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. |
| `password_authentication_enabled_for_git` | boolean | no | Enable authentication for Git over HTTP(S) via a GitLab account password. Default is `true`. |
@@ -341,7 +346,7 @@ listed in the descriptions of the relevant settings.
| `receive_max_input_size` | integer | no | Maximum push size (MB). |
| `repository_checks_enabled` | boolean | no | GitLab periodically runs `git fsck` in all project and wiki repositories to look for silent disk corruption issues. |
| `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) |
-| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to [weights](../administration/repository_storage_paths.md#choose-where-new-repositories-are-stored). New projects are created in one of these stores, chosen by a weighted random selection. |
+| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to [weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored). New projects are created in one of these stores, chosen by a weighted random selection. |
| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. |
| `require_admin_approval_after_user_signup` | boolean | no | When enabled, any user that signs up for an account using the registration form is placed under a **Pending approval** state and has to be explicitly [approved](../user/admin_area/approving_users.md) by an administrator. |
| `require_two_factor_authentication` | boolean | no | (**If enabled, requires:** `two_factor_grace_period`) Require all users to set up Two-factor authentication. |
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index 2f018e67628..4791f066cd2 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.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
---
-# Sidekiq Metrics API **(CORE ONLY)**
+# Sidekiq Metrics API **(FREE SELF)**
> Introduced in GitLab 8.9.
diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md
index f60b1dfb449..393ca30c28d 100644
--- a/doc/api/snippet_repository_storage_moves.md
+++ b/doc/api/snippet_repository_storage_moves.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Snippet repository storage moves API **(CORE ONLY)**
+# Snippet repository storage moves API **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8.
@@ -30,11 +30,10 @@ read-only. Please try again later.` message if they try to push new commits.
This API requires you to [authenticate yourself](README.md#authentication) as an administrator.
-Project repositories can be moved using the [Project repository storage moves API](project_repository_storage_moves.md).
+For other repository types see:
-## Limitations
-
-- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
+- [Project repository storage moves API](project_repository_storage_moves.md).
+- [Group repository storage moves API](group_repository_storage_moves.md).
## Retrieve all snippet repository storage moves
diff --git a/doc/api/suggestions.md b/doc/api/suggestions.md
index 9f878cd029a..0fcb6122505 100644
--- a/doc/api/suggestions.md
+++ b/doc/api/suggestions.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Suggest Changes API
+# Suggest Changes API **(FREE)**
Every API call to suggestions must be authenticated.
@@ -21,6 +21,7 @@ PUT /suggestions/:id/apply
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID of a suggestion |
+| `commit_message` | string | no | A custom commit message to use instead of the default generated message or the project's default message |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/suggestions/5/apply"
diff --git a/doc/api/tags.md b/doc/api/tags.md
index 126bc010022..eef4504aa5b 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Tags API
+# Tags API **(FREE)**
## List project repository tags
@@ -123,7 +123,7 @@ Parameters:
| `tag_name` | string | yes | The name of a tag |
| `ref` | string | yes | Create tag using commit SHA, another tag name, or branch name |
| `message` | string | no | Creates annotated tag |
-| `release_description` | string | no | Add release notes to the Git tag and store it in the GitLab database |
+| `release_description` | string | no | This parameter is [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) for use in GitLab 11.7, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/290311) in GitLab 14.0. Use the [Releases API](../api/releases/index.md) instead. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/tags?tag_name=test&ref=master"
@@ -186,6 +186,11 @@ Parameters:
## Create a new release
+WARNING:
+This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766)
+for use in GitLab 11.7, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/290311)
+in GitLab 14.0. Use the [Releases API](../api/releases/index.md) instead.
+
Add release notes to the existing Git tag. If there
already exists a release for the given tag, status code `409` is returned.
@@ -221,6 +226,11 @@ Response:
## Update a release
+WARNING:
+This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766)
+for use in GitLab 11.7, and is planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/290311)
+in GitLab 14.0. Use the [Releases API](../api/releases/index.md) instead.
+
Updates the release notes of a given release.
```plaintext
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 203d1bc6f03..3b2e3acb38b 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -10,8 +10,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Get a list of to dos
-Returns a list of to dos. When no filter is applied, it returns all pending to dos
-for the current user. Different filters allow the user to precise the request.
+Returns a list of [to-do items](../user/todos.md). When no filter is applied, it
+returns all pending to-do items for the current user. Different filters allow the
+user to refine the request.
```plaintext
GET /todos
diff --git a/doc/api/users.md b/doc/api/users.md
index ecfd8e26626..76b0bb3491c 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -65,7 +65,7 @@ GET /users?active=true
GET /users?blocked=true
```
-GitLab supports bot users such as the [alert bot](../operations/incident_management/alert_integrations.md)
+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).
To exclude these users from the users' list, you can use the parameter `exclude_internal=true`
([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241144) in GitLab 13.4).
@@ -88,7 +88,7 @@ GET /users
| `order_by` | string | no | Return users ordered by `id`, `name`, `username`, `created_at`, or `updated_at` fields. Default is `id` |
| `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` |
+| `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` |
```json
@@ -171,7 +171,7 @@ GET /users
]
```
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `shared_runners_minutes_limit`, `extra_shared_runners_minutes_limit`, and `using_license_seat` parameters.
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see the `shared_runners_minutes_limit`, `extra_shared_runners_minutes_limit`, and `using_license_seat` parameters.
```json
[
@@ -186,7 +186,7 @@ Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/)
]
```
-Users on GitLab [Silver or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see
the `group_saml` provider option:
```json
@@ -217,7 +217,9 @@ For example:
GET /users?extern_uid=1234567&provider=github
```
-You can search for users who are external with: `/users?external=true`
+Instance administrators can search for users who are external with: `/users?external=true`
+
+You cannot search for external users if you are not an instance administrator.
You can search users by creation date time range with:
@@ -264,6 +266,7 @@ Parameters:
"created_at": "2012-05-23T08:00:58Z",
"bio": "",
"bio_html": "",
+ "bot": false,
"location": null,
"public_email": "john@example.com",
"skype": "",
@@ -271,7 +274,9 @@ Parameters:
"twitter": "",
"website_url": "",
"organization": "",
- "job_title": "Operations Specialist"
+ "job_title": "Operations Specialist",
+ "followers": 1,
+ "following": 1
}
```
@@ -337,7 +342,7 @@ Example Responses:
NOTE:
The `plan` and `trial` parameters are only available on GitLab Enterprise Edition.
-Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see
+Users on GitLab [Premium or higher](https://about.gitlab.com/pricing/) also see
the `shared_runners_minutes_limit`, and `extra_shared_runners_minutes_limit` parameters.
```json
@@ -350,7 +355,7 @@ the `shared_runners_minutes_limit`, and `extra_shared_runners_minutes_limit` par
}
```
-Users on GitLab.com [Silver, or higher](https://about.gitlab.com/pricing/) also
+Users on GitLab.com [Premium or higher](https://about.gitlab.com/pricing/) also
see the `group_saml` option:
```json
@@ -623,7 +628,8 @@ Example response:
{
"emoji":"coffee",
"message":"I crave coffee :coffee:",
- "message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>"
+ "message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>",
+ "clear_status_at": null
}
```
@@ -649,7 +655,8 @@ Example response:
{
"emoji":"coffee",
"message":"I crave coffee :coffee:",
- "message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>"
+ "message_html": "I crave coffee <gl-emoji title=\"hot beverage\" data-name=\"coffee\" data-unicode-version=\"4.0\">☕</gl-emoji>",
+ "clear_status_at": null
}
```
@@ -661,15 +668,16 @@ Set the status of the current user.
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. |
+| 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 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 "emoji=coffee" --data "message=I crave coffee" "https://gitlab.example.com/api/v4/user/status"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "clear_status_after=1_day" --data "emoji=coffee" --data "message=I crave coffee" "https://gitlab.example.com/api/v4/user/status"
```
Example responses
@@ -678,10 +686,93 @@ Example responses
{
"emoji":"coffee",
"message":"I crave coffee",
- "message_html": "I crave coffee"
+ "message_html": "I crave coffee",
+ "clear_status_at":"2021-02-15T10:49:01.311Z"
+}
+```
+
+## User Follow
+
+### Follow and unfollow users
+
+Follow a user.
+
+```plaintext
+POST /users/:id/follow
+```
+
+Unfollow a user.
+
+```plaintext
+POST /users/:id/unfollow
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | ---------------------------- |
+| `id` | integer | yes | The ID of the user to follow |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/users/3/follow"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "username": "john_smith",
+ "name": "John Smith",
+ "state": "active",
+ "avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
+ "web_url": "http://localhost:3000/john_smith"
}
```
+### Followers and following
+
+Get the followers of a user.
+
+```plaintext
+GET /users/:id/followers
+```
+
+Get the list of users being followed.
+
+```plaintext
+GET /users/:id/following
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ------- | -------- | ---------------------------- |
+| `id` | integer | yes | The ID of the user to follow |
+
+```shell
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/users/3/followers"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 2,
+ "name": "Lennie Donnelly",
+ "username": "evette.kilback",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/7955171a55ac4997ed81e5976287890a?s=80&d=identicon",
+ "web_url": "http://127.0.0.1:3000/evette.kilback"
+ },
+ {
+ "id": 4,
+ "name": "Serena Bradtke",
+ "username": "cammy",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/a2daad869a7b60d3090b7b9bef4baf57?s=80&d=identicon",
+ "web_url": "http://127.0.0.1:3000/cammy"
+ }
+]
+```
+
## User counts
Get the counts (same as in top right menu) of the currently signed in user.
@@ -1374,7 +1465,7 @@ Example Responses:
```
```json
-{ "message": "The user you are trying to approve is not pending an approval" }
+{ "message": "The user you are trying to approve is not pending approval" }
```
## Get an impersonation token of a user
@@ -1481,7 +1572,7 @@ Parameters:
| `user_id` | integer | yes | The ID of the user |
| `impersonation_token_id` | integer | yes | The ID of the impersonation token |
-## Create a personal access token **(CORE ONLY)**
+## Create a personal access token **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17176) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267553) in GitLab 13.8.
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index 00e70d34db6..c63a04228a5 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -71,7 +71,7 @@ Below are the changes made between V3 and V4.
- Notes do not return deprecated field `upvote` and `downvote` [!9384](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9384)
- Return HTTP status code `400` for all validation errors when creating or updating a member instead of sometimes `422` error. [!9523](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9523)
- Remove `GET /groups/owned`. Use `GET /groups?owned=true` instead [!9505](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9505)
-- Return 202 with JSON body on async removals on V4 API (`DELETE /projects/:id/repository/merged_branches` and `DELETE /projects/:id`) [!9449](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9449)
+- Return 202 with JSON body on asynchronous removals on V4 API (`DELETE /projects/:id/repository/merged_branches` and `DELETE /projects/:id`) [!9449](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9449)
- `GET /projects/:id/milestones?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!9096](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9096)
- Return basic information about pipeline in `GET /projects/:id/pipelines` [!8875](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8875)
- Renamed all `build` references to `job` [!9463](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9463)
diff --git a/doc/api/visual_review_discussions.md b/doc/api/visual_review_discussions.md
index 67d9c523862..c3414a4e9ec 100644
--- a/doc/api/visual_review_discussions.md
+++ b/doc/api/visual_review_discussions.md
@@ -5,9 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, api
---
-# Visual Review discussions API **(STARTER)**
+# Visual Review discussions API **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18710) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.5.
+> - [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
feedback from [Visual Reviews](../ci/review_apps/index.md#visual-reviews).
diff --git a/doc/api/vulnerability_exports.md b/doc/api/vulnerability_exports.md
index e4853920cab..f70662c7c61 100644
--- a/doc/api/vulnerability_exports.md
+++ b/doc/api/vulnerability_exports.md
@@ -37,7 +37,7 @@ POST /security/projects/:id/vulnerability_exports
| `id` | integer or string | yes | The ID or [URL-encoded path](README.md#namespaced-path-encoding) of the project which the authenticated user is a member of |
```shell
-curl --header POST "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/vulnerability_exports"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/security/projects/1/vulnerability_exports"
```
The created vulnerability export is automatically deleted after 1 hour.
@@ -83,7 +83,7 @@ POST /security/groups/:id/vulnerability_exports
| `id` | integer or string | yes | The ID or [URL-encoded path](README.md#namespaced-path-encoding) of the group which the authenticated user is a member of |
```shell
-curl --header POST "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/security/groups/1/vulnerability_exports"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/security/groups/1/vulnerability_exports"
```
The created vulnerability export is automatically deleted after 1 hour.
@@ -116,7 +116,7 @@ POST /security/vulnerability_exports
```
```shell
-curl --header POST "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/security/vulnerability_exports"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/security/vulnerability_exports"
```
The created vulnerability export is automatically deleted after one hour.
diff --git a/doc/api/wikis.md b/doc/api/wikis.md
index dfbedc9bfd1..43587da9473 100644
--- a/doc/api/wikis.md
+++ b/doc/api/wikis.md
@@ -1,6 +1,6 @@
---
stage: Create
-group: Knowledge
+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, api
---
@@ -175,9 +175,9 @@ POST /projects/:id/wikis/attachments
| `file` | string | yes | The attachment to be uploaded |
| `branch` | string | no | The name of the branch. Defaults to the wiki repository default branch |
-To upload a file from your filesystem, use the `--form` argument. This causes
+To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`.
-The `file=` parameter must point to a file on your filesystem and be preceded
+The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
diff --git a/doc/architecture/blueprints/database_testing/index.md b/doc/architecture/blueprints/database_testing/index.md
new file mode 100644
index 00000000000..a333ac12ef3
--- /dev/null
+++ b/doc/architecture/blueprints/database_testing/index.md
@@ -0,0 +1,145 @@
+---
+comments: false
+description: 'Database Testing'
+---
+
+# Database Testing
+
+We have identified [common themes of reverted migrations](https://gitlab.com/gitlab-org/gitlab/-/issues/233391) and discovered failed migrations breaking in both production and staging even when successfully tested in a developer environment. We have also experienced production incidents even with successful testing in staging. These failures are quite expensive: they can have a significant effect on availability, block deployments, and generate incident escalations. These escalations must be triaged and either reverted or fixed forward. Often, this can take place without the original author's involvement due to time zones and/or the criticality of the escalation. With our increased deployment speeds and stricter uptime requirements, the need for improving database testing is critical, particularly earlier in the development process (shift left).
+
+From a developer's perspective, it is hard, if not unfeasible, to validate a migration on a large enough dataset before it goes into production.
+
+Our primary goal is to **provide developers with immediate feedback for new migrations and other database-related changes tested on a full copy of the production database**, and to do so with high levels of efficiency (particularly in terms of infrastructure costs) and security.
+
+## Current day
+
+Developers are expected to test database migrations prior to deploying to any environment, but we lack the ability to perform testing against large environments such as GitLab.com. The [developer database migration style guide](../../../development/migration_style_guide.md) provides guidelines on migrations, and we focus on validating migrations during code review and testing in CI and staging.
+
+The [code review phase](../../../development/database_review.md) involves Database Reviewers and Maintainers to manually check the migrations committed. This often involves knowing and spotting problematic patterns and their particular behavior on GitLab.com from experience. There is no large-scale environment available that allows us to test database migrations before they are being merged.
+
+Testing in CI is done on a very small database. We mainly check forward/backward migration consistency, evaluate Rubocop rules to detect well-known problematic behaviors (static code checking) and have a few other, rather technical checks in place (adding the right files etc). That is, we typically find code or other rather simple errors, but cannot surface any data related errors - which are also typically not covered by unit tests either.
+
+Once merged, migrations are being deployed to the staging environment. Its database size is less than 5% of the production database size as of January 2021 and its recent data distribution does not resemble the production site. Oftentimes, we see migrations succeed in staging but then fail in production due to query timeouts or other unexpected problems. Even if we caught problems in staging, this is still expensive to reconcile and ideally we want to catch those problems as early as possible in the development cycle.
+
+Today, we have gained experience with working on a thin-cloned production database (more on this below) and already use it to provide developers with access to production query plans, automated query feedback and suggestions with optimizations. This is built around [Database Lab](https://gitlab.com/postgres-ai/database-lab) and [Joe](https://gitlab.com/postgres-ai/joe), both available through Slack (using ChatOps) and [postgres.ai](https://postgres.ai/).
+
+## Vision
+
+As a developer:
+
+1. I am working on a GitLab code change that includes a data migration and changes a heavy database query.
+1. I push my code, create a merge request, and provide an example query in the description.
+1. The pipeline executes the data migration and examines the query in a large-scale environment (a copy of GitLab.com).
+1. Once the pipeline finishes, the merge request gets detailed feedback and information about the migration and the query I provided. This is based on a full clone of the production database with a state that is very close to production (minutes).
+
+For database migrations, the information gathered from execution on the clone includes:
+
+- Overall runtime.
+- Detailed statistics for queries being executed in the migration (normalizing queries and showing their frequencies and execution times as plots).
+- Dangerous locks held during the migration (which would cause blocking situations in production).
+
+For database queries, we can automatically gather:
+
+- Query plans along with visualization.
+- Execution times and predictions for production.
+- Suggestions on optimizations from Joe.
+- Memory and IO statistics.
+
+After having gotten that feedback:
+
+1. I can go back and investigate a performance problem with the data migration.
+1. Once I have a fix pushed, I can repeat the above cycle and eventually send my merge request for database review. During the database review, the database reviewer and maintainer have all the additional generated information available to them to make an informed decision on the performance of the introduced changes.
+
+This information gathering is done in a protected and safe environment, making sure that there is no unauthorized access to production data and we can safely execute code in this environment.
+
+The intended benefits include:
+
+- Shifting left: Allow developers to understand large-scale database performance and what to expect to happen on GitLab.com in a self-service manner
+- Identify errors that are only generated when working against a production scale dataset with real data (with inconsistencies or unexpected patterns)
+- Automate the information gathering phase to make it easier for everybody involved in code review (developer, reviewer, maintainer) by providing relevant details automatically and upfront.
+
+## Technology and next steps
+
+We already use Database Lab from [postgres.ai](https://postgres.ai/), which is a thin-cloning technology. We maintain a PostgreSQL replica which is up to date with production data but does not serve any production traffic. This runs Database Lab which allows us to quickly create a full clone of the production dataset (in the order of seconds).
+
+Internally, this is based on ZFS and implements a "thin-cloning technology". That is, ZFS snapshots are being used to clone the data and it exposes a full read/write PostgreSQL cluster based on the cloned data. This is called a *thin clone*. It is rather short lived and is going to be destroyed again shortly after we are finished using it.
+
+It is important to note that a thin clone is fully read/write. This allows us to execute migrations on top of it.
+
+Database Lab provides an API we can interact with to manage thin clones. In order to automate the migration and query testing, we add steps to the `gitlab/gitlab-org` CI pipeline. This triggers automation that performs the following steps for a given merge request:
+
+1. Create a thin-clone with production data for this testing session.
+1. Pull GitLab code from the merge request.
+1. Execute migrations and gather all necessary information from it.
+1. Execute query testing and gather all necessary information from it.
+1. Post back the results of the migration and query testing to the merge request.
+1. Destroy the thin-clone.
+
+### Short-term
+
+The short-term focus is on testing regular migrations (typically schema changes) and using the existing Database Lab instance from postgres.ai for it.
+
+In order to secure this process and meet compliance goals, the runner environment will be treated as a *production* environment and similarly locked down, monitored and audited. Only Database Maintainers will have access to the CI pipeline and its job output. Everyone else will only be able to see the results and statistics posted back on the merge request.
+
+We implement a secured CI pipeline on <https://ops.gitlab.net> that adds the execution steps outlined above. The goal is to secure this pipeline in order to solve the following problem:
+
+Make sure we strongly protect production data, even though we allow everyone (GitLab team/developers) to execute arbitrary code on the thin-clone which contains production data.
+
+This is in principle achieved by locking down the GitLab Runner instance executing the code and its containers on a network level, such that no data can escape over the network. We make sure no communication can happen to the outside world from within the container executing the GitLab Rails code (and its database migrations).
+
+Furthermore, we limit the ability to view the results of the jobs (including the output printed from code) to Maintainer and Owner level on the <https://ops.gitlab.net> pipeline and provide only a high level summary back to the original MR. If there are issues or errors in one of the jobs run, the database Maintainer assigned to review the MR can check the original job for more details.
+
+With this step implemented, we already have the ability to execute database migrations on the thin-cloned GitLab.com database automatically from GitLab CI and provide feedback back to the merge request and the developer. The content of that feedback is expected to evolve over time and we can continuously add to this.
+
+We already have an [MVC-style implementation for the pipeline](https://gitlab.com/gitlab-org/database-team/gitlab-com-migrations) for reference and an [example merge request with feedback](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50793#note_477815261) from the pipeline.
+
+The short-term goal is detailed in [this epic](https://gitlab.com/groups/gitlab-org/database-team/-/epics/6).
+
+### 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 etc.) 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:
+
+1. Scheduling phase - query statistics (for example a histogram of query execution times), job statistics (how many jobs, overall duration etc.), batch sizes.
+1. Execution phase - using a few instances of a job as examples, we execute those to gather query and runtime statistics.
+
+### 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.
+
+## An alternative discussed: Anonymization
+
+At the core of this problem lies the concern about executing (potentially arbitrary) code on a production dataset and making sure the production data is well protected. The approach discussed above solves this by strongly limiting access to the output of said code.
+
+An alternative approach we have discussed and abandoned is to "scrub" and anonymize production data. The idea is to remove any sensitive data from the database and use the resulting dataset for database testing. This has a lot of downsides which led us to abandon the idea:
+
+- Anonymization is complex by nature - it is a hard problem to call a "scrubbed clone" actually safe to work with in public. Different data types may require different anonymization techniques (e.g. anonymizing sensitive information inside a JSON field) and only focusing on one attribute at a time does not guarantee that a dataset is fully anonymized (for example join attacks or using timestamps in conjunction to public profiles/projects to de-anonymize users by there activity).
+- Anonymization requires an additional process to keep track and update the set of attributes considered as sensitive, ongoing maintenance and security reviews every time the database schema changes.
+- Annotating data as "sensitive" is error prone, with the wrong anonymization approach used for a data type or one sensitive attribute accidentally not marked as such possibly leading to a data breach.
+- Scrubbing not only removes sensitive data, but also changes data distribution, which greatly affects performance of migrations and queries.
+- Scrubbing heavily changes the database contents, potentially updating a lot of data, which leads to different data storage details (think MVC bloat), affecting performance of migrations and queries.
+
+## Who
+
+<!-- vale gitlab.Spelling = NO -->
+
+This effort is owned and driven by the [GitLab Database Team](https://about.gitlab.com/handbook/engineering/development/enablement/database/) with support from the [GitLab.com Reliability Datastores](https://about.gitlab.com/handbook/engineering/infrastructure/team/reliability/datastores/) team.
+
+| Role | Who
+|------------------------------|-------------------------|
+| Author | Andreas Brandl |
+| Architecture Evolution Coach | Gerardo Lopez-Fernandez |
+| Engineering Leader | Craig Gomes |
+| Domain Expert | Yannis Roussos |
+| Domain Expert | Pat Bair |
+
+DRIs:
+
+| Role | Who
+|------------------------------|------------------------|
+| Product | Fabian Zimmer |
+| Leadership | Craig Gomes |
+| Engineering | Andreas Brandl |
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index 6be582bb8af..a5e46d25921 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -91,7 +91,7 @@ allow us to have:
name: ci_disallow_to_create_merge_request_pipelines_in_target_project
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40724
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235119
-group: group::progressive delivery
+group: group::release
type: development
default_enabled: false
```
@@ -105,7 +105,7 @@ These are reason why these changes are needed:
- we have ambiguous usage of feature flag with different `default_enabled:` and
different `actors` used
- we lack a clear indication who owns what feature flag and where to find
- relevant informations
+ relevant information
- we do not emphasise the desire to create feature flag rollout issue to
indicate that feature flag is in fact a ~"technical debt"
- we don't know exactly what feature flags we have in our codebase
diff --git a/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md b/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
index 6c27ecca284..fb71707c146 100644
--- a/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
+++ b/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
@@ -1,12 +1,12 @@
---
-stage: configure
-group: configure
+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/#designated-technical-writers
comments: false
description: 'GitLab to Kubernetes communication'
---
-# GitLab to Kubernetes communication
+# GitLab to Kubernetes communication **(FREE)**
The goal of this document is to define how GitLab can communicate with Kubernetes
and in-cluster services through the GitLab Kubernetes Agent.
diff --git a/doc/architecture/blueprints/graphql_api/index.md b/doc/architecture/blueprints/graphql_api/index.md
new file mode 100644
index 00000000000..40d02168b3b
--- /dev/null
+++ b/doc/architecture/blueprints/graphql_api/index.md
@@ -0,0 +1,183 @@
+---
+stage: none
+group: unassigned
+comments: false
+description: 'GraphQL API architecture foundation'
+---
+
+# GraphQL API
+
+[GraphQL](https://graphql.org/) is a data query and manipulation language for
+APIs, and a runtime for fulfilling queries with existing data.
+
+At GitLab we want to adopt GraphQL to make it easier for the wider community to
+interact with GitLab in a reliable way, but also to advance our own product by
+modeling communication between backend and frontend components using GraphQL.
+
+We've recently increased the pace of the adoption by defining quarterly OKRs
+related to GraphQL migration. This resulted in us spending more time on the
+GraphQL development and helped to surface the need of improving tooling we use
+to extend the new API.
+
+This document describes the work that is needed to build a stable foundation that
+will support our development efforts and a large-scale usage of the [GraphQL
+API](https://docs.gitlab.com/ee/api/graphql/index.html).
+
+## Summary
+
+The GraphQL initiative at GitLab [started around three years ago](https://gitlab.com/gitlab-org/gitlab/-/commit/9c6c17cbcdb8bf8185fc1b873dcfd08f723e4df5).
+Most of the work around the GraphQL ecosystem has been done by volunteers that are
+[GraphQL experts](https://gitlab.com/groups/gitlab-org/graphql-experts/-/group_members?with_inherited_permissions=exclude).
+
+The [retrospective on our progress](https://gitlab.com/gitlab-org/gitlab/-/issues/235659)
+surfaced a few opportunities to streamline our GraphQL development efforts and
+to reduce the risk of performance degradations and possible outages that may
+be related to the gaps in the essential mechanisms needed to make the GraphQL
+API observable and operable at scale.
+
+Amongst small improvements to the GraphQL engine itself we want to build a
+comprehensive monitoring dashboard, that will enable team members to make sense
+of what is happening inside our GraphQL API. We want to make it possible to define
+SLOs, triage breached SLIs and to be able to zoom into relevant details using
+Grafana and Elastic. We want to see historical data and predict future usage.
+
+It is an opportunity to learn from our experience in evolving the REST API, for
+the scale, and to apply this knowledge onto the GraphQL development efforts. We
+can do that by building query-to-feature correlation mechanisms, adding
+scalable state synchronization support and aligning GraphQL with other
+architectural initiatives being executed in parallel, like [the support for
+direct uploads](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
+
+GraphQL should be secure by default. We can avoid common security mistakes by
+building mechanisms that will help us to enforce [OWASP GraphQL
+recommendations](https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html)
+that are relevant to us.
+
+Understanding what are the needs of the wider community will also allow us to
+plan deprecation policies better and to design parity between GraphQL and REST
+API that suits their needs.
+
+## Challenges
+
+### Make sense of what is happening in GraphQL
+
+Being able to see how GraphQL performs in a production environment is a
+prerequisite for improving performance and reliability of that service.
+
+We do not yet have tools that would make it possible for us to answer a
+question of how GraphQL performs and what the bottlenecks we should optimize
+are. This, combined with a pace of GraphQL adoption and the scale in which we
+expect it operate, imposes a risk of an increased rate of production incidents
+what will be difficult to resolve.
+
+We want to build a comprehensive Grafana dashboard that will focus on
+delivering insights of how GraphQL endpoint performs, while still empowering
+team members with capability of zooming in into details. We want to improve
+logging to make it possible to better correlate GraphQL queries with feature
+using Elastic and to index them in a way that performance problems can be
+detected early.
+
+- Build a comprehensive Grafana dashboard for GraphQL
+- Build a GraphQL query-to-feature correlation mechanisms
+- Improve logging GraphQL queries in Elastic
+- Redesign error handling on frontend to surface warnings
+
+### Manage volatile GraphQL data structures
+
+Our GraphQL API will evolve with time. GraphQL has been designed to make such
+evolution easier. GraphQL APIs are easier to extend because of how composable
+GraphQL is. On the other hand this is also a reason why versioning of GraphQL
+APIs is considered unnecessary. Instead of versioning the API we want to mark
+some fields as deprecated, but we need to have a way to understand what is the
+usage of deprecated fields, types and a way to visualize it in a way that is
+easy to understand. We might want to detect usage of deprecated fields and
+notify users that we plan to remove them.
+
+- Define a data-informed deprecation policy that will serve our users better
+- Build a dashboard showing usage frequency of deprecated GraphQL fields
+- Build mechanisms required to send deprecated fields usage in usage ping
+
+### Ensure consistency with the rest of the codebase
+
+GraphQL is not the only thing we work on, but it cuts across the entire
+application. It is being used to expose data collected and processed in almost
+every part of our product. It makes it tightly coupled with our monolithic
+codebase.
+
+We need to ensure that how we use GraphQL is consistent with other mechanisms
+we've designed to improve performance and reliability of GitLab.
+
+We have extensive experience with evolving our REST API. We want to apply
+this knowledge onto GraphQL and make it performant and secure by default.
+
+- Design direct uploads for GraphQL
+- Build GraphQL query depth and complexity histograms
+- Visualize the amount of GraphQL queries reaching limits
+- Add support for GraphQL ETags for existing features
+
+### Design GraphQL interoperability with REST API
+
+We do not plan to deprecate our REST API. It is a simple way to interact with
+GitLab, and GraphQL might never become a full replacement of a traditional REST
+API. The two APIs will need to coexist together. We will need to remove
+duplication between them to make their codebases maintainable. This symbiosis,
+however, is not only a technical challenge we need to resolve on the backend.
+Users might want to use the two APIs interchangeably or even at the same time.
+Making it interoperable by exposing a common scheme for resource identifiers is
+a prerequisite for interoperability.
+
+- Make GraphQL and REST API interoperable
+- Design common resource identifiers for both APIs
+
+### Design scalable state synchronization mechanisms
+
+One of the most important goals related to GraphQL adoption at GitLab is using
+it to model interactions between GitLab backend and frontend components. This
+is an ongoing process that has already surfaced the need of building better
+state synchronization mechanisms and hooking into existing ones.
+
+- Design a scalable state synchronization mechanism
+- Evaluate state synchronization through pub/sub and websockets
+- Build a generic support for GraphQL feature correlation and feature ETags
+- Redesign frontend code responsible for managing shared global state
+
+## Iterations
+
+1. [Build comprehensive Grafana dashboard for GraphQL](https://gitlab.com/groups/gitlab-com/-/epics/1343)
+1. [Improve logging of GraphQL requests in Elastic](https://gitlab.com/groups/gitlab-org/-/epics/4646)
+1. [Build a scalable state synchronization for GraphQL](https://gitlab.com/groups/gitlab-org/-/epics/5319)
+1. [Build GraphQL feature-to-query correlation mechanisms](https://gitlab.com/groups/gitlab-org/-/epics/5320)
+1. [Design a better data-informed deprecation policy](https://gitlab.com/groups/gitlab-org/-/epics/5321)
+1. [Add support for direct uploads for GraphQL](https://gitlab.com/gitlab-org/gitlab/-/issues/280819)
+1. [Review GraphQL design choices related to security](https://gitlab.com/gitlab-org/security/gitlab/-/issues/339)
+
+## Status
+
+Current status: in progress.
+
+## Who
+
+Proposal:
+
+<!-- vale gitlab.Spelling = NO -->
+
+| Role | Who
+|------------------------------|-------------------------|
+| Author | Grzegorz Bizon |
+| Architecture Evolution Coach | Kamil Trzciński |
+| Engineering Leader | Darva Satcher |
+| Product Manager | Patrick Deuley |
+| Domain Expert / GraphQL | Charlie Ablett |
+| Domain Expert / GraphQL | Alex Kalderimis |
+| Domain Expert / GraphQL | Natalia Tepluhina |
+| Domain Expert / Scalability | Bob Van Landuyt |
+
+DRIs:
+
+| Role | Who
+|------------------------------|------------------------|
+| Leadership | Darva Satcher |
+| Product | Patrick Deuley |
+| Engineering | |
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/image_resizing/index.md b/doc/architecture/blueprints/image_resizing/index.md
index 9e5c45a715d..686a2f9c8f5 100644
--- a/doc/architecture/blueprints/image_resizing/index.md
+++ b/doc/architecture/blueprints/image_resizing/index.md
@@ -59,6 +59,8 @@ The MVC Avatar resizing implementation is integrated into Workhorse. With the ex
Proposal:
+<!-- vale gitlab.Spelling = NO -->
+
| Role | Who
|------------------------------|-------------------------|
| Author | Craig Gomes |
@@ -67,10 +69,16 @@ Proposal:
| Domain Expert | Matthias Kaeppler |
| Domain Expert | Aleksei Lipniagov |
+<!-- vale gitlab.Spelling = YES -->
+
DRIs:
+<!-- vale gitlab.Spelling = NO -->
+
| Role | Who
|------------------------------|------------------------|
| Product | Josh Lambert |
| Leadership | Craig Gomes |
| Engineering | Matthias Kaeppler |
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 740be7d1dbd..9b555c0ee68 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -7,10 +7,10 @@ description: "Learn how to use GitLab CI/CD, the GitLab built-in Continuous Inte
type: index
---
-# GitLab CI/CD
+# GitLab CI/CD **(FREE)**
GitLab CI/CD is a tool built into GitLab for software development
-through the [continuous methodologies](introduction/index.md#introduction-to-cicd-methodologies):
+through the [continuous methodologies](introduction/index.md):
- Continuous Integration (CI)
- Continuous Delivery (CD)
@@ -55,9 +55,9 @@ at the repository's root. This file creates a [pipeline](pipelines/index.md), wh
To get started with GitLab CI/CD, we recommend you read through
the following documents:
-- [Get started with GitLab CI/CD](quick_start/README.md).
+- [Get started with GitLab CI/CD](quick_start/index.md).
- [Fundamental pipeline architectures](pipelines/pipeline_architectures.md).
-- [GitLab CI/CD basic workflow](introduction/index.md#basic-cicd-workflow).
+- [GitLab CI/CD basic workflow](introduction/index.md#gitlab-cicd-workflow).
- [Step-by-step guide for writing `.gitlab-ci.yml` for the first time](../user/project/pages/getting_started/pages_from_scratch.md).
If you're migrating from another CI/CD tool, check out our handy references:
@@ -71,11 +71,11 @@ available through the UI. You can use them by creating a new file,
choosing a template that suits your application, and adjusting it
to your needs:
-![Use a `.gitlab-ci.yml` template](img/add_file_template_11_10.png)
+![Use a YAML template](img/add_file_template_11_10.png)
While building your `.gitlab-ci.yml`, you can use the [CI/CD configuration visualization](pipeline_editor/index.md#visualize-ci-configuration) to facilitate your writing experience.
-For a broader overview, see the [CI/CD getting started](quick_start/README.md) guide.
+For a broader overview, see the [CI/CD getting started](quick_start/index.md) guide.
After you're familiar with how GitLab CI/CD works, see the
[`.gitlab-ci.yml` full reference](yaml/README.md)
@@ -90,7 +90,7 @@ GitLab CI/CD uses a number of concepts to describe and run your build and deploy
| Concept | Description |
|:--------------------------------------------------------|:-------------------------------------------------------------------------------|
| [Pipelines](pipelines/index.md) | Structure your CI/CD process through pipelines. |
-| [Environment variables](variables/README.md) | Reuse values based on a variable/value key pair. |
+| [CI/CD variables](variables/README.md) | Reuse values based on a variable/value key pair. |
| [Environments](environments/index.md) | Deploy your application to different environments (e.g., staging, production). |
| [Job artifacts](pipelines/job_artifacts.md) | Output, use, and reuse job artifacts. |
| [Cache dependencies](caching/index.md) | Cache your dependencies for a faster execution. |
@@ -105,9 +105,9 @@ GitLab CI/CD supports numerous configuration options:
| Configuration | Description |
|:----------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
| [Schedule pipelines](pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
-| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-ci-configuration-path) | Define a custom path for the CI/CD configuration file. |
+| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-cicd-configuration-path) | Define a custom path for the CI/CD configuration file. |
| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules. |
-| [SSH keys for CI/CD](ssh_keys/README.md) | Using SSH keys in your CI pipelines. |
+| [SSH keys for CI/CD](ssh_keys/index.md) | Using SSH keys in your CI pipelines. |
| [Pipeline triggers](triggers/README.md) | Trigger pipelines through the API. |
| [Pipelines for Merge Requests](merge_request_pipelines/index.md) | Design a pipeline structure for running a pipeline in merge requests. |
| [Integrate with Kubernetes clusters](../user/project/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
@@ -126,15 +126,15 @@ Its feature set is listed on the table below according to DevOps stages.
|:------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|
| **Configure** | |
| [Auto DevOps](../topics/autodevops/index.md) | Set up your app's entire lifecycle. |
-| [ChatOps](chatops/README.md) | Trigger CI jobs from chat, with results sent back to the channel. |
+| [ChatOps](chatops/index.md) | Trigger CI jobs from chat, with results sent back to the channel. |
|-------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------|
| **Verify** | |
| [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. |
| [Load Performance Testing](../user/project/merge_requests/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. |
-| [CI services](services/README.md) | Link Docker containers with your base image. |
+| [CI services](services/index.md) | Link Docker containers with your base image. |
| [Code Quality](../user/project/merge_requests/code_quality.md) | Analyze your source code quality. |
| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) **(PREMIUM)** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and Bitbucket Cloud. |
-| [Interactive Web Terminals](interactive_web_terminal/index.md) **(CORE ONLY)** | Open an interactive web terminal to debug the running jobs. |
+| [Interactive Web Terminals](interactive_web_terminal/index.md) **(FREE SELF)** | Open an interactive web terminal to debug the running jobs. |
| [Unit test reports](unit_test_reports.md) | Identify script failures directly on merge requests. |
| [Using Docker images](docker/using_docker_images.md) | Use GitLab and GitLab Runner with Docker to build and test applications. |
|-------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------|
@@ -160,9 +160,7 @@ Its feature set is listed on the table below according to DevOps stages.
Find example project code and tutorials for using GitLab CI/CD with a variety of app frameworks, languages, and platforms
on the [CI Examples](examples/README.md) page.
-GitLab also provides [example projects](https://gitlab.com/gitlab-examples) pre-configured to use GitLab CI/CD.
-
-## Administration **(CORE ONLY)**
+## Administration **(FREE SELF)**
As a GitLab administrator, you can change the default behavior
of GitLab CI/CD for:
@@ -206,7 +204,7 @@ been necessary. These are:
#### 12.0
-- [Use refspec to clone/fetch Git repository](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4069).
+- [Use `refspec` to clone/fetch Git repository](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4069).
- [Old cache configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4070).
- [Old metrics server configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4072).
- [Remove `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4073).
diff --git a/doc/ci/autodeploy/index.md b/doc/ci/autodeploy/index.md
deleted file mode 100644
index 8c7d9c1da64..00000000000
--- a/doc/ci/autodeploy/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../topics/autodevops/stages.md#auto-deploy'
----
-
-This document was moved to [another location](../../topics/autodevops/stages.md#auto-deploy).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/autodeploy/quick_start_guide.md b/doc/ci/autodeploy/quick_start_guide.md
deleted file mode 100644
index 8c7d9c1da64..00000000000
--- a/doc/ci/autodeploy/quick_start_guide.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../topics/autodevops/stages.md#auto-deploy'
----
-
-This document was moved to [another location](../../topics/autodevops/stages.md#auto-deploy).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/build_artifacts/README.md b/doc/ci/build_artifacts/README.md
deleted file mode 100644
index 4344a544798..00000000000
--- a/doc/ci/build_artifacts/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/project/pipelines/job_artifacts.md'
----
-
-This document was moved to [pipelines/job_artifacts.md](../../user/project/pipelines/job_artifacts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index 08a45714de3..bfc332e35b1 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -87,7 +87,7 @@ use one or more of the following:
that are only available to a particular project.
- [Use a `key`](../yaml/README.md#cachekey) that fits your workflow (for example,
different caches on each branch). For that, you can take advantage of the
- [CI/CD predefined variables](../variables/README.md#predefined-environment-variables).
+ [predefined CI/CD variables](../variables/README.md#predefined-cicd-variables).
For runners to work with caches efficiently, you must do one of the following:
diff --git a/doc/ci/chatops/README.md b/doc/ci/chatops/README.md
index 5d6af0b78db..c94d6e3ea80 100644
--- a/doc/ci/chatops/README.md
+++ b/doc/ci/chatops/README.md
@@ -1,116 +1,8 @@
---
-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
-type: index, concepts, howto
+redirect_to: 'index.md'
---
-# GitLab ChatOps
+This document was moved to [another location](index.md).
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
-
-GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
-like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
-place in chat services. Having a method to run CI/CD jobs with output
-posted back to the channel can significantly augment your team's workflow.
-
-## How GitLab ChatOps works
-
-GitLab ChatOps is built upon [GitLab CI/CD](../README.md) and
-[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.md).
-ChatOps provides a `run` action for [slash commands](../../integration/slash_commands.md)
-with the following arguments:
-
-- A `<job name>` to execute.
-- The `<job arguments>`.
-
-ChatOps passes the following [CI/CD variables](../variables/README.md#predefined-environment-variables)
-to the job:
-
-- `CHAT_INPUT` contains any additional arguments.
-- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
-
-When executed, ChatOps looks up the specified job name and attempts to match it
-to a corresponding job in [`.gitlab-ci.yml`](../yaml/README.md). If a matching job
-is found on `master`, a pipeline containing only that job is scheduled. After the
-job completes:
-
-- If the job completes in *less than 30 minutes*, the ChatOps sends the job's output to Slack.
-- If the job completes in *more than 30 minutes*, the job must use the
- [Slack API](https://api.slack.com/) to send data to the channel.
-
-To use the `run` command, you must have
-[Developer access or above](../../user/permissions.md#project-members-permissions).
-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
-
-Since ChatOps is built upon GitLab CI/CD, the job has all the same features and
-functions available. Consider these best practices when creating ChatOps jobs:
-
-- GitLab strongly recommends you set `only: [chat]` so the job does not run as part
- 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 [Developer access or above](../../user/permissions.md#project-members-permissions)
- in the project, the job runs. The job itself can use existing
- [CI/CD variables](../variables/README.md#predefined-environment-variables) like
- `GITLAB_USER_ID` to perform additional rights validation, but
- these variables can be [overridden](../variables/README.md#priority-of-environment-variables).
-
-### Controlling the ChatOps reply
-
-The output for jobs with a single command is sent to the channel as a reply. For
-example, the chat reply of the following job is `Hello World` in the channel:
-
-```yaml
-hello-world:
- stage: chatops
- only: [chat]
- script:
- - echo "Hello World"
-```
-
-Jobs that contain multiple commands (or `before_script`) return additional
-content in the chat reply. In these cases, both the commands and their output are
-included, with the commands wrapped in ANSI color codes.
-
-To selectively reply with the output of one command, its output must be bounded by
-the `chat_reply` section. For example, the following job lists the files in the
-current directory:
-
-```yaml
-ls:
- stage: chatops
- only: [chat]
- script:
- - echo "This command will not be shown."
- - echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K"
-```
-
-## GitLab ChatOps examples
-
-The GitLab.com team created a repository of [common ChatOps scripts](https://gitlab.com/gitlab-com/chatops)
-they use to interact with our Production instance of GitLab. Administrators of
-other GitLab instances may find them useful. They can serve as inspiration for ChatOps
-scripts you can write to interact with your own applications.
-
-## GitLab ChatOps icon
-
-The [official GitLab ChatOps icon](img/gitlab-chatops-icon.png) is available for download.
-You can find and download the official GitLab ChatOps icon here.
-
-![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
-
-<!-- ## 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 2021-05-01. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
new file mode 100644
index 00000000000..48f8e595df6
--- /dev/null
+++ b/doc/ci/chatops/index.md
@@ -0,0 +1,116 @@
+---
+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
+type: index, concepts, howto
+---
+
+# GitLab ChatOps **(FREE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Free](https://about.gitlab.com/pricing/) in 11.9.
+
+GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
+like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
+place in chat services. Having a method to run CI/CD jobs with output
+posted back to the channel can significantly augment your team's workflow.
+
+## How GitLab ChatOps works
+
+GitLab ChatOps is built upon [GitLab CI/CD](../README.md) and
+[Slack Slash Commands](../../user/project/integrations/slack_slash_commands.md).
+ChatOps provides a `run` action for [slash commands](../../integration/slash_commands.md)
+with the following arguments:
+
+- A `<job name>` to execute.
+- The `<job arguments>`.
+
+ChatOps passes the following [CI/CD variables](../variables/README.md#predefined-cicd-variables)
+to the job:
+
+- `CHAT_INPUT` contains any additional arguments.
+- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
+
+When executed, ChatOps looks up the specified job name and attempts to match it
+to a corresponding job in [`.gitlab-ci.yml`](../yaml/README.md). If a matching job
+is found on `master`, a pipeline containing only that job is scheduled. After the
+job completes:
+
+- If the job completes in *less than 30 minutes*, the ChatOps sends the job's output to Slack.
+- If the job completes in *more than 30 minutes*, the job must use the
+ [Slack API](https://api.slack.com/) to send data to the channel.
+
+To use the `run` command, you must have
+[Developer access or above](../../user/permissions.md#project-members-permissions).
+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
+
+Since ChatOps is built upon GitLab CI/CD, the job has all the same features and
+functions available. Consider these best practices when creating ChatOps jobs:
+
+- GitLab strongly recommends you set `only: [chat]` so the job does not run as part
+ 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 [Developer access or above](../../user/permissions.md#project-members-permissions)
+ in the project, the job runs. The job itself can use existing
+ [CI/CD variables](../variables/README.md#predefined-cicd-variables) like
+ `GITLAB_USER_ID` to perform additional rights validation, but
+ these variables can be [overridden](../variables/README.md#priority-of-cicd-variables).
+
+### Controlling the ChatOps reply
+
+The output for jobs with a single command is sent to the channel as a reply. For
+example, the chat reply of the following job is `Hello World` in the channel:
+
+```yaml
+hello-world:
+ stage: chatops
+ only: [chat]
+ script:
+ - echo "Hello World"
+```
+
+Jobs that contain multiple commands (or `before_script`) return additional
+content in the chat reply. In these cases, both the commands and their output are
+included, with the commands wrapped in ANSI color codes.
+
+To selectively reply with the output of one command, its output must be bounded by
+the `chat_reply` section. For example, the following job lists the files in the
+current directory:
+
+```yaml
+ls:
+ stage: chatops
+ only: [chat]
+ script:
+ - echo "This command will not be shown."
+ - echo -e "section_start:$( date +%s ):chat_reply\r\033[0K\n$( ls -la )\nsection_end:$( date +%s ):chat_reply\r\033[0K"
+```
+
+## GitLab ChatOps examples
+
+The GitLab.com team created a repository of [common ChatOps scripts](https://gitlab.com/gitlab-com/chatops)
+they use to interact with our Production instance of GitLab. Administrators of
+other GitLab instances may find them useful. They can serve as inspiration for ChatOps
+scripts you can write to interact with your own applications.
+
+## GitLab ChatOps icon
+
+The [official GitLab ChatOps icon](img/gitlab-chatops-icon.png) is available for download.
+You can find and download the official GitLab ChatOps icon here.
+
+![GitLab ChatOps bot icon](img/gitlab-chatops-icon-small.png)
+
+<!-- ## 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/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
index a466214374b..38930eb60ad 100644
--- a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -14,8 +14,9 @@ GitLab CI/CD can be used with Bitbucket Cloud by:
To use GitLab CI/CD with a Bitbucket Cloud repository:
-1. In GitLab create a **CI/CD for external repository**, select **Repo by URL** and
- create the project.
+1. <!-- vale gitlab.Spelling = NO --> In GitLab create a **CI/CD for external repository**, select
+ **Repo by URL** and create the project.
+ <!-- vale gitlab.Spelling = YES -->
![Create project](img/external_repository.png)
@@ -49,7 +50,7 @@ To use GitLab CI/CD with a Bitbucket Cloud repository:
![Bitbucket Cloud webhook](img/bitbucket_app_password.png)
-1. In GitLab, from **Settings > CI/CD > Environment variables**, add variables to allow
+1. In GitLab, from **Settings > CI/CD > Variables**, add variables to allow
communication with Bitbucket via the Bitbucket API:
`BITBUCKET_ACCESS_TOKEN`: the Bitbucket app password created above.
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 8e3d609b5dc..2a8b050b224 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -35,13 +35,13 @@ repositories:
your project, update commit statuses, and create a web hook to notify
GitLab of new commits.
-1. In GitLab, go to the [new project page](../../gitlab-basics/create-project.md#create-a-project-in-gitlab), select the **CI/CD for external repository** tab, and then click
+1. In GitLab, go to the [new project page](../../user/project/working_with_projects.md#create-a-project), select the **CI/CD for external repository** tab, and then click
**GitHub**.
1. Paste the token into the **Personal access token** field and click **List
Repositories**. Click **Connect** to select the repository.
-1. In GitHub, add a `.gitlab-ci.yml` to [configure GitLab CI/CD](../quick_start/README.md).
+1. In GitHub, add a `.gitlab-ci.yml` to [configure GitLab CI/CD](../quick_start/index.md).
GitLab:
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
index 44534ddf793..cc6c629fb47 100644
--- a/doc/ci/ci_cd_for_external_repos/index.md
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -25,11 +25,15 @@ snippets disabled. These features
To connect to an external repository:
+<!-- vale gitlab.Spelling = NO -->
+
1. From your GitLab dashboard, click **New project**.
1. Switch to the **CI/CD for external repository** tab.
1. Choose **GitHub** or **Repo by URL**.
1. The next steps are similar to the [import flow](../../user/project/import/index.md).
+<!-- vale gitlab.Spelling = YES -->
+
![CI/CD for external repository project creation](img/ci_cd_for_external_repo.png)
## Pipelines for external pull requests
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index 0be86527cb5..ccacb3c61d3 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -38,7 +38,7 @@ Some credentials are required to be able to run `aws` commands:
A new **Access key ID** and **Secret access key** are generated. Please take a note of them right away.
1. In your GitLab project, go to **Settings > CI / CD**. Set the following as
- [environment variables](../variables/README.md#gitlab-cicd-environment-variables)
+ [CI/CD variables](../variables/README.md)
(see table below):
- Access key ID.
@@ -47,11 +47,11 @@ Some credentials are required to be able to run `aws` commands:
You might want to check if the AWS service you intend to use is
[available in the chosen region](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/).
- | Env. variable name | Value |
- |:------------------------|:-----------------------|
- | `AWS_ACCESS_KEY_ID` | Your Access key ID |
- | `AWS_SECRET_ACCESS_KEY` | Your Secret access key |
- | `AWS_DEFAULT_REGION` | Your region code |
+ | Environment variable name | Value |
+ |:-------------------------------|:-----------------------|
+ | `AWS_ACCESS_KEY_ID` | Your Access key ID |
+ | `AWS_SECRET_ACCESS_KEY` | Your Secret access key |
+ | `AWS_DEFAULT_REGION` | Your region code |
1. You can now use `aws` commands in the `.gitlab-ci.yml` file of this project:
@@ -109,7 +109,7 @@ The ECS task definition can be:
After you have these prerequisites ready, follow these steps:
-1. Make sure your AWS credentials are set up as environment variables for your
+1. Make sure your AWS credentials are set up as CI/CD variables for your
project. You can follow [the steps above](#run-aws-commands-from-gitlab-cicd) to complete this setup.
1. Add these variables to your project's `.gitlab-ci.yml` file, or in the project's
[CI/CD settings](../variables/README.md#create-a-custom-variable-in-the-ui):
@@ -141,15 +141,15 @@ After you have these prerequisites ready, follow these steps:
```
You can create your `CI_AWS_ECS_TASK_DEFINITION_FILE` variable as a
- [file-typed environment variable](../variables/README.md#custom-environment-variables-of-type-file) instead of a
- regular environment variable. If you choose to do so, set the variable value to be the full contents of
+ [file-typed CI/CD variable](../variables/README.md#custom-cicd-variables-of-type-file) instead of a
+ regular CI/CD variable. If you choose to do so, set the variable value to be the full contents of
the JSON task definition. You can then remove the JSON file from your project.
In both cases, make sure that the value for the `containerDefinitions[].name` attribute is
the same as the `Container name` defined in your targeted ECS service.
WARNING:
- `CI_AWS_ECS_TASK_DEFINITION_FILE` takes precedence over `CI_AWS_ECS_TASK_DEFINITION` if both these environment
+ `CI_AWS_ECS_TASK_DEFINITION_FILE` takes precedence over `CI_AWS_ECS_TASK_DEFINITION` if both these
variables are defined within your project.
NOTE:
@@ -242,7 +242,7 @@ pass three JSON input objects, based on existing templates:
have two ways to pass in these JSON objects:
- They can be three actual files located in your project. You must specify their path relative to
- your project root in your `.gitlab-ci.yml` file, using the following variables. For example, if
+ your project root in your `.gitlab-ci.yml` file, using the following CI/CD variables. For example, if
your files are in a `<project_root>/aws` folder:
```yaml
@@ -252,12 +252,12 @@ pass three JSON input objects, based on existing templates:
CI_AWS_EC2_DEPLOYMENT_FILE: 'aws/create_deployment.json'
```
- - Alternatively, you can provide these JSON objects as [file-typed environment variables](../variables/README.md#custom-environment-variables-of-type-file).
- In your project, go to **Settings > CI / CD > Variables** and add
- the three variables listed above as file-typed environment variables.
- For each variable, set the value to its corresponding JSON object.
+ - Alternatively, you can provide these JSON objects as [file-typed CI/CD variables](../variables/README.md#custom-cicd-variables-of-type-file).
+ In your project, go to **Settings > CI/CD > Variables** and add
+ the three variables listed above as file-typed CI/CD variables.
+ For each variable, set the value to its corresponding JSON object.
-1. Provide the name of the stack you're creating and/or targeting, as an environment variable:
+1. Provide the name of the stack you're creating and/or targeting, as a CI/CD variable:
```yaml
variables:
@@ -286,7 +286,7 @@ When running your project pipeline at this point:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216008) in GitLab 13.6.
To leverage [Auto DevOps](../../topics/autodevops/index.md) for your project when deploying to
-AWS EC2, first you must define [your AWS credentials as environment variables](#run-aws-commands-from-gitlab-cicd).
+AWS EC2, first you must define [your AWS credentials as CI/CD variables](#run-aws-commands-from-gitlab-cicd).
Next, define a job for the `build` stage. To do so, you must reference the
`Auto-DevOps.gitlab-ci.yml` template and include a job named `build_artifact` in your
@@ -299,7 +299,7 @@ include:
- template: Auto-DevOps.gitlab-ci.yml
variables:
- - AUTO_DEVOPS_PLATFORM_TARGET: EC2
+ AUTO_DEVOPS_PLATFORM_TARGET: EC2
build_artifact:
stage: build
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index a8ce46b9845..5089aa6c9a5 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -82,11 +82,8 @@ are certain use cases that you may need to work around. For more information:
## Needs Visualization
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215517) in GitLab 13.1 as a [Beta feature](https://about.gitlab.com/handbook/product/#beta).
-> - It was deployed behind a feature flag, disabled by default.
-> - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802) in 13.2.
> - It became a [standard feature](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38517) in 13.3.
-> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-needs-visualization).
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52208) in GitLab 13.9.
The needs visualization makes it easier to visualize the relationships between dependent jobs in a DAG. This graph displays all the jobs in a pipeline that need or are needed by other jobs. Jobs with no relationships are not displayed in this view.
@@ -97,16 +94,3 @@ To see the needs visualization, click on the **Needs** tab when viewing a pipeli
Clicking a node highlights all the job paths it depends on.
![Needs visualization with path highlight](img/dag_graph_example_clicked_v13_1.png)
-
-### Enable or disable Needs Visualization **(CORE ONLY)**
-
-The needs visualization is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it for your instance:
-
-```ruby
-# Instance-wide
-Feature.disable(:dag_pipeline_tab)
-# or by project
-Feature.disable(:dag_pipeline_tab, Project.find(<project ID>))
-```
diff --git a/doc/ci/docker/README.md b/doc/ci/docker/README.md
index 2b97f317fc1..c94d6e3ea80 100644
--- a/doc/ci/docker/README.md
+++ b/doc/ci/docker/README.md
@@ -1,18 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To 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
+redirect_to: 'index.md'
---
-# Docker integration
+This document was moved to [another location](index.md).
-GitLab CI/CD can be combined with [Docker](https://www.docker.com) to enable
-integration between the two.
-
-The following documentation is available for using GitLab CI/CD with Docker:
-
-- [Using Docker images](using_docker_images.md).
-- [Building Docker images with GitLab CI/CD](using_docker_build.md).
-- [Building images with kaniko and GitLab CI/CD](using_kaniko.md).
+<!-- This redirect file can be deleted after 2021-05-01. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/docker/index.md b/doc/ci/docker/index.md
new file mode 100644
index 00000000000..18a9d63b694
--- /dev/null
+++ b/doc/ci/docker/index.md
@@ -0,0 +1,18 @@
+---
+stage: Verify
+group: Continuous Integration
+info: To 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
+---
+
+# Docker integration
+
+GitLab CI/CD can be combined with [Docker](https://www.docker.com) to enable
+integration between the two.
+
+The following documentation is available for using GitLab CI/CD with Docker:
+
+- [Building Docker images with GitLab CI/CD](using_docker_build.md).
+- [Using Docker images](using_docker_images.md).
+- [Building images with kaniko and GitLab CI/CD](using_kaniko.md).
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index af88a006156..46ced9b4d6d 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -126,7 +126,7 @@ not without its own challenges:
instance of Docker engine so they don't conflict with each other. But this
also means that jobs can be slower because there's no caching of layers.
- By default, Docker 17.09 and higher uses `--storage-driver overlay2` which is
- the recommended storage driver. See [Using the overlayfs driver](#use-the-overlayfs-driver)
+ the recommended storage driver. See [Using the OverlayFS driver](#use-the-overlayfs-driver)
for details.
- Since the `docker:19.03.12-dind` container and the runner container don't share their
root file system, the job's working directory can be used as a mount point for
@@ -801,7 +801,7 @@ NOTE:
The shared runners on GitLab.com use the `overlay2` driver by default.
By default, when using `docker:dind`, Docker uses the `vfs` storage driver which
-copies the filesystem on every run. This is a disk-intensive operation
+copies the file system on every run. This is a disk-intensive operation
which can be avoided if a different driver is used, for example `overlay2`.
### Requirements
@@ -830,7 +830,7 @@ which can be avoided if a different driver is used, for example `overlay2`.
### Use the OverlayFS driver per project
You can enable the driver for each project individually by using the `DOCKER_DRIVER`
-environment [variable](../yaml/README.md#variables) in `.gitlab-ci.yml`:
+[CI/CD variable](../yaml/README.md#variables) in `.gitlab-ci.yml`:
```yaml
variables:
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 630e106b72c..67450d442a9 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -91,7 +91,7 @@ Services inherit the same DNS servers, search domains, and additional hosts as
the CI container itself.
You can see some widely used services examples in the relevant documentation of
-[CI services examples](../services/README.md).
+[CI services examples](../services/index.md).
### How services are linked to the job
@@ -272,11 +272,11 @@ test:
- bundle exec rake spec
```
-## Passing environment variables to services
+## Passing CI/CD variables to services
-You can also pass custom environment [variables](../variables/README.md)
+You can also pass custom CI/CD [variables](../variables/README.md)
to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml` file.
-For more information, read [custom environment variables](../variables/README.md#gitlab-ciyml-defined-variables)
+For more information, read about [`.gitlab-ci.yml` defined variables](../variables/README.md#gitlab-ciyml-defined-variables).
```yaml
# The following variables are automatically passed down to the Postgres container
@@ -528,7 +528,7 @@ To access private container registries, the GitLab Runner process can use:
To define which should be used, the GitLab Runner process reads the configuration in the following order:
- `DOCKER_AUTH_CONFIG` variable provided as either:
- - A [variable](../variables/README.md#gitlab-cicd-environment-variables) in `.gitlab-ci.yml`.
+ - A [CI/CD variable](../variables/README.md) in `.gitlab-ci.yml`.
- A project's variables stored on the projects **Settings > CI/CD** page.
- `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the runner.
- `config.json` file placed in `$HOME/.docker` directory of the user running GitLab Runner process.
@@ -627,7 +627,7 @@ Use one of the following methods to determine the value of `DOCKER_AUTH_CONFIG`:
To configure a single job with access for `registry.example.com:5000`,
follow these steps:
-1. Create a [variable](../variables/README.md#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` with the content of the
+1. Create a [CI/CD variable](../variables/README.md) `DOCKER_AUTH_CONFIG` with the content of the
Docker configuration file as the value:
```json
@@ -702,7 +702,7 @@ To configure credentials store, follow these steps:
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
- Create a
- [variable](../variables/README.md#gitlab-cicd-environment-variables)
+ [CI/CD variable](../variables/README.md)
`DOCKER_AUTH_CONFIG` with the content of the
Docker configuration file as the value:
@@ -734,7 +734,7 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
Make sure that GitLab Runner can access the credentials.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
- - Create a [variable](../variables/README.md#gitlab-cicd-environment-variables)
+ - Create a [CI/CD variable](../variables/README.md)
`DOCKER_AUTH_CONFIG` with the content of the
Docker configuration file as the value:
@@ -781,13 +781,13 @@ registries to the `"credHelpers"` hash as described above.
Many services accept environment variables, which you can use to change
database names or set account names, depending on the environment.
-GitLab Runner 0.5.0 and up passes all YAML-defined variables to the created
+GitLab Runner 0.5.0 and up passes all YAML-defined CI/CD variables to the created
service containers.
For all possible configuration variables, check the documentation of each image
provided in their corresponding Docker hub page.
-All variables are passed to all services containers. It's not
+All CI/CD variables are passed to all services containers. It's not
designed to distinguish which variable should go where.
### PostgreSQL service example
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 7eb2a8286c7..2122cf2bf16 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -49,7 +49,7 @@ In the following example, kaniko is used to:
The job runs only when a tag is pushed. A `config.json` file is created under
`/kaniko/.docker` with the needed GitLab Container Registry credentials taken from the
-[environment variables](../variables/README.md#predefined-environment-variables)
+[predefined CI/CD variables](../variables/README.md#predefined-cicd-variables)
GitLab CI/CD provides.
In the last step, kaniko uses the `Dockerfile` under the
@@ -76,7 +76,7 @@ If you use a custom GitLab Runner behind an http(s) proxy, kaniko needs to be se
up accordingly. This means:
- Adding the proxy to `/kaniko/.docker/config.json`
-- Passing the `http_proxy` environment variables as build args so the Dockerfile
+- Passing the `http_proxy` environment variables as build arguments so the Dockerfile
instructions can use the proxy when building the image.
The previous example can be extended as follows:
diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md
index f59e32fb46d..72fd9833df1 100644
--- a/doc/ci/enable_or_disable_ci.md
+++ b/doc/ci/enable_or_disable_ci.md
@@ -13,7 +13,7 @@ To effectively use GitLab CI/CD, you need:
of your project.
- A [runner](runners/README.md) properly set up.
-You can read our [quick start guide](quick_start/README.md) to get you started.
+You can read our [quick start guide](quick_start/index.md) to get you started.
If you are using an external CI/CD server like Jenkins or Drone CI, it is advised
to disable GitLab CI/CD in order to not have any conflicts with the commits status
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
deleted file mode 100644
index 2ce0618c8e7..00000000000
--- a/doc/ci/environments.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'environments/index.md'
----
-
-This document was moved to [another location](environments/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 4dac076ffb7..eecc8ffd18f 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -110,7 +110,7 @@ for an explanation of these roles and the permissions of each.
Production secrets are needed to deploy successfully. For example, when deploying to the cloud,
cloud providers require these secrets to connect to their services. In the project settings, you can
-define and protect environment variables for these secrets. [Protected variables](../variables/README.md#protect-a-custom-variable)
+define and protect CI/CD variables for these secrets. [Protected variables](../variables/README.md#protect-a-custom-variable)
are only passed to pipelines running on [protected branches](../../user/project/protected_branches.md)
or [protected tags](../../user/project/protected_tags.md).
The other pipelines don't get the protected variable. You can also
@@ -141,7 +141,7 @@ reference a file in another project with a completely different set of permissio
In this scenario, the `gitlab-ci.yml` is publicly accessible, but can only be edited by users with
appropriate permissions in the other project.
-For more information, see [Custom CI configuration path](../pipelines/settings.md#custom-ci-configuration-path).
+For more information, see [Custom CI/CD configuration path](../pipelines/settings.md#custom-cicd-configuration-path).
## Troubleshooting
diff --git a/doc/ci/environments/environments_dashboard.md b/doc/ci/environments/environments_dashboard.md
index 84f8b1b1dbf..ef222ba5779 100644
--- a/doc/ci/environments/environments_dashboard.md
+++ b/doc/ci/environments/environments_dashboard.md
@@ -36,7 +36,7 @@ environments are not displayed.
To add a project to the dashboard:
-1. Click the **Add projects** button in the homescreen of the dashboard.
+1. Click the **Add projects** button in the home screen of the dashboard.
1. Search and add one or more projects using the **Search your projects** field.
1. Click the **Add projects** button.
@@ -53,4 +53,4 @@ You can add up to 150 projects for GitLab to display on this dashboard.
GitLab.com users can add public projects to the Environments
Dashboard for free. If your project is private, the group it belongs
-to must have a [GitLab Silver](https://about.gitlab.com/pricing/) plan.
+to must have a [GitLab Premium](https://about.gitlab.com/pricing/) plan.
diff --git a/doc/ci/environments/incremental_rollouts.md b/doc/ci/environments/incremental_rollouts.md
index 15eb4d2c526..39e3dd1ca75 100644
--- a/doc/ci/environments/incremental_rollouts.md
+++ b/doc/ci/environments/incremental_rollouts.md
@@ -117,6 +117,10 @@ available, [demonstrating configuration of timed rollouts](https://gitlab.com/gl
## Blue-Green Deployment
+NOTE:
+As of GitLab 13.7, teams can leverage an Ingress annotation and [set traffic weight](../../user/project/canary_deployments.md#how-to-change-the-traffic-weight-on-a-canary-ingress)
+as an alternative approach to the blue-green deployment strategy documented here.
+
Also sometimes known as A/B deployment or red-black deployment, this technique is used to reduce
downtime and risk during a deployment. When combined with incremental rollouts, you can
minimize the impact of a deployment causing an issue.
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 7bf30ef1b95..b49fcd72172 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -57,7 +57,7 @@ Configuring environments involves:
The rest of this section illustrates how to configure environments and deployments using
an example scenario. It assumes you have already:
-- Created a [project](../../gitlab-basics/create-project.md) in GitLab.
+- Created a [project](../../user/project/working_with_projects.md#create-a-project) in GitLab.
- Set up [a runner](../runners/README.md).
In the scenario:
@@ -135,12 +135,12 @@ In summary, with the above `.gitlab-ci.yml` we have achieved the following:
job deploys our code to a staging server while the deployment
is recorded in an environment named `staging`.
-#### Environment variables and runners
+#### CI/CD variables and runners
Starting with GitLab 8.15, the environment name is exposed to the runner in
two forms:
-- `$CI_ENVIRONMENT_NAME`. The name given in `.gitlab-ci.yml` (with any variables
+- `$CI_ENVIRONMENT_NAME`. The name given in `.gitlab-ci.yml` (with any CI/CD variables
expanded).
- `$CI_ENVIRONMENT_SLUG`. A "cleaned-up" version of the name, suitable for use in URLs,
DNS, etc.
@@ -221,7 +221,7 @@ The assigned URL for the `review/your-branch-name` environment is [visible in th
Note the following:
- `stop_review` doesn't generate a dotenv report artifact, so it doesn't recognize the
- `DYNAMIC_ENVIRONMENT_URL` variable. Therefore you shouldn't set `environment:url:` in the
+ `DYNAMIC_ENVIRONMENT_URL` environment variable. Therefore you shouldn't set `environment:url:` in the
`stop_review` job.
- If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update
the environment URL.
@@ -313,9 +313,9 @@ Dynamic environments are a fundamental part of [Review apps](../review_apps/inde
The `name` and `url` keywords for dynamic environments can use most available CI/CD variables,
including:
-- [Predefined environment variables](../variables/README.md#predefined-environment-variables)
-- [Project and group variables](../variables/README.md#gitlab-cicd-environment-variables)
-- [`.gitlab-ci.yml` variables](../yaml/README.md#variables)
+- [Predefined CI/CD variables](../variables/README.md#predefined-cicd-variables)
+- [Project and group CI/CD variables](../variables/README.md)
+- [`.gitlab-ci.yml` CI/CD variables](../yaml/README.md#variables)
However, you cannot use variables defined:
@@ -327,7 +327,7 @@ For more information, see [Where variables can be used](../variables/where_varia
#### Example configuration
-Runners expose various [environment variables](../variables/README.md) when a job runs, so
+Runners expose various [predefined CI/CD variables](../variables/predefined_variables.md) when a job runs, so
you can use them as environment names.
In the following example, the job deploys to all branches except `master`:
@@ -825,7 +825,7 @@ build with the specified environment runs. Newer deployments can also
You may want to specify an environment keyword to
[protect builds from unauthorized access](protected_environments.md), or to get
-access to [scoped variables](#scoping-environments-with-specs). In these cases,
+access to [environment-scoped variables](#scoping-environments-with-specs). In these cases,
you can use the `action: prepare` keyword to ensure deployments aren't created,
and no builds are canceled:
@@ -846,7 +846,7 @@ build:
As documented in [Configuring dynamic environments](#configuring-dynamic-environments), you can
prepend environment name with a word, followed by a `/`, and finally the branch
-name, which is automatically defined by the `CI_COMMIT_REF_NAME` variable.
+name, which is automatically defined by the `CI_COMMIT_REF_NAME` predefined CI/CD variable.
In short, environments that are named like `type/foo` are all presented under the same
group, named `type`.
@@ -1009,9 +1009,9 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
### Scoping environments with specs
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2112) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
-> - [Scoping for environment variables was moved to Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30779) in GitLab 12.2.
+> - [Environment scoping for CI/CD variables was moved to all tiers](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30779) in GitLab 12.2.
-You can limit the environment scope of a variable by
+You can limit the environment scope of a CI/CD variable by
defining which environments it can be available for.
Wildcards can be used and the default environment scope is `*`. This means that
@@ -1025,7 +1025,7 @@ with `review/` would have that particular variable.
Some GitLab features can behave differently for each environment.
For example, you can
-[create a secret variable to be injected only into a production environment](../variables/README.md#limit-the-environment-scopes-of-environment-variables).
+[create a secret variable to be injected only into a production environment](../variables/README.md#limit-the-environment-scopes-of-cicd-variables).
In most cases, these features use the _environment specs_ mechanism, which offers
an efficient way to implement scoping within each environment group.
@@ -1061,7 +1061,7 @@ environment's operational health.
## Limitations
-In the `environment: name`, you are limited to only the [predefined environment variables](../variables/predefined_variables.md).
+In the `environment: name`, you are limited to only the [predefined CI/CD variables](../variables/predefined_variables.md).
Re-using variables defined inside `script` as part of the environment name doesn't work.
## Further reading
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 0e4ad1df65f..2636e59723a 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
-# Protected Environments **(PREMIUM)**
+# Protected environments **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6303) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
@@ -31,7 +31,7 @@ To protect, update, or unprotect an environment, you need to have at least
To protect an environment:
1. Navigate to your project's **Settings > CI/CD**.
-1. Expand the **Protected Environments** section.
+1. Expand the **Protected environments** section.
1. From the **Environment** dropdown menu, select the environment you want to protect.
1. In the **Allowed to Deploy** dropdown menu, select the role, users, or groups you
want to give deploy access to. Keep in mind that:
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 9fa0bb080ac..b48dd561a66 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -23,31 +23,35 @@ Examples are available in several forms. As a collection of:
The following table lists examples with step-by-step tutorials that are contained in this section:
| Use case | Resource |
-|:------------------------------|:---------|
+|-------------------------------|----------|
| Browser performance testing | [Browser Performance Testing with the Sitespeed.io container](../../user/project/merge_requests/browser_performance_testing.md). |
| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.md). |
| Deployment with Dpl | [Using `dpl` as deployment tool](deployment/README.md). |
| GitLab Pages | See the [GitLab Pages](../../user/project/pages/index.md) documentation for a complete example of deploying a static site. |
| End-to-end testing | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md). |
-| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.md). |
-| Java with Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md). |
-| Java with Spring Boot | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.md). |
| Load performance testing | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_performance_testing.md). |
| Multi project pipeline | [Build, test deploy using multi project pipeline](https://gitlab.com/gitlab-examples/upstream-project). |
-| NPM with semantic-release | [Publish NPM packages to the GitLab Package Registry using semantic-release](semantic-release.md). |
+| npm with semantic-release | [Publish npm packages to the GitLab Package Registry using semantic-release](semantic-release.md). |
| PHP with Laravel, Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.md). |
-| PHP with NPM, SCP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.md). |
-| PHP with PHPunit, atoum | [Testing PHP projects](php.md). |
-| Parallel testing Ruby & JS | [GitLab CI/CD parallel jobs testing for Ruby & JavaScript projects](https://docs.knapsackpro.com/2019/how-to-run-parallel-jobs-for-rspec-tests-on-gitlab-ci-pipeline-and-speed-up-ruby-javascript-testing). |
+| PHP with npm, SCP | [Running Composer and npm scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.md). |
+| PHP with PHPunit, `atoum` | [Testing PHP projects](php.md). |
| Python on Heroku | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.md). |
| Ruby on Heroku | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.md). |
-| Scala on Heroku | [Test and deploy a Scala application to Heroku](test-scala-application.md). |
-| Secrets management with Vault | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.md). |
+| Secrets management with Vault | [Authenticating and Reading Secrets With HashiCorp Vault](authenticating-with-hashicorp-vault/index.md). |
+
+### Contributed examples
-### How to contributing examples
+You can help people that use your favorite programming language by submitting a link
+to a guide for that language. These contributed guides are hosted externally or in
+separate example projects:
-Contributions are welcome! You can help your favorite programming
-language users and GitLab by sending a merge request with a guide for that language.
+| Use case | Resource |
+|-------------------------------|----------|
+| Game development | [DevOps and Game Development with GitLab CI/CD](https://gitlab.com/gitlab-examples/gitlab-game-demo/). |
+| Java with Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](https://gitlab.com/gitlab-examples/maven/simple-maven-example). |
+| Java with Spring Boot | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](https://gitlab.com/gitlab-examples/spring-gitlab-cf-deploy-demo). |
+| Parallel testing Ruby & JS | [GitLab CI/CD parallel jobs testing for Ruby & JavaScript projects](https://docs.knapsackpro.com/2019/how-to-run-parallel-jobs-for-rspec-tests-on-gitlab-ci-pipeline-and-speed-up-ruby-javascript-testing). |
+| Scala on Heroku | [Test and deploy a Scala application to Heroku](https://gitlab.com/gitlab-examples/scala-sbt). |
## CI/CD templates
@@ -81,7 +85,7 @@ choose one of these templates:
- [LaTeX (`LaTeX.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml)
- [Maven (`Maven.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Maven.gitlab-ci.yml)
- [Mono (`Mono.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Mono.gitlab-ci.yml)
-- [NPM (`npm.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml)
+- [npm (`npm.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml)
- [Node.js (`Nodejs.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml)
- [OpenShift (`OpenShift.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml)
- [Packer (`Packer.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Packer.gitlab-ci.yml)
@@ -95,9 +99,9 @@ choose one of these templates:
If a programming language or framework template is not in this list, you can contribute
one. To create a template, submit a merge request
-to <https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates>.
+to [the templates list](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).
-### Adding templates to your GitLab installation **(PREMIUM ONLY)**
+### Adding templates to your GitLab installation **(PREMIUM SELF)**
You can add custom examples and templates to your self-managed GitLab instance.
Your GitLab administrator can [designate an instance template repository](../../user/admin_area/settings/instance_template_repository.md)
@@ -127,7 +131,7 @@ See also the following video overviews:
For some customer experiences with GitLab CI/CD, see:
-- [How Verizon Connect reduced datacenter deploys from 30 days to under 8 hours with GitLab](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)
+- [How Verizon Connect reduced data center deploys from 30 days to under 8 hours with GitLab](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)
- [How Wag! cut their release process from 40 minutes to just 6](https://about.gitlab.com/blog/2019/01/16/wag-labs-blog-post/)
- [How Jaguar Land Rover embraced CI to speed up their software lifecycle](https://about.gitlab.com/blog/2018/07/23/chris-hill-devops-enterprise-summit-talk/)
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index c1df21297e3..a1a7de26cf2 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -1,289 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-disqus_identifier: 'https://docs.gitlab.com/ee/articles/artifactory_and_gitlab/index.html'
-author: Fabio Busatto
-author_gitlab: bikebilly
-type: tutorial
-date: 2017-08-15
+redirect_to: '../README.md#contributed-examples'
---
-<!-- vale off -->
+This document was moved to [another location](../README.md#contributed-examples).
-# How to deploy Maven projects to Artifactory with GitLab CI/CD
-
-## Introduction
-
-In this article, we show how you can leverage the power of [GitLab CI/CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)
-to build a [Maven](https://maven.apache.org/) project, deploy it to [Artifactory](https://jfrog.com/artifactory/), and then use it from another Maven application as a dependency.
-
-You'll create two different projects:
-
-- `simple-maven-dep`: the app built and deployed to Artifactory (see the [simple-maven-dep](https://gitlab.com/gitlab-examples/maven/simple-maven-dep) example project)
-- `simple-maven-app`: the app using the previous one as a dependency (see the [simple-maven-app](https://gitlab.com/gitlab-examples/maven/simple-maven-app) example project)
-
-We assume that you already have a GitLab account on [GitLab.com](https://gitlab.com/), and that you know the basic usage of Git and [GitLab CI/CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/).
-We also assume that an Artifactory instance is available and reachable from the internet, and that you have valid credentials to deploy on it.
-
-## Create the simple Maven dependency
-
-First, you need an application to work with: in this specific case we'll use a
-simple one, but it could be any Maven application. This will be the dependency
-you want to package and deploy to Artifactory, to be available to other
-projects.
-
-### Prepare the dependency application
-
-For this article you'll use a Maven app that can be cloned from our example
-project:
-
-1. Log in to your GitLab account
-1. Create a new project by selecting **Import project from > Repo by URL**
-1. Add the following URL:
-
- ```plaintext
- https://gitlab.com/gitlab-examples/maven/simple-maven-dep.git
- ```
-
-1. Click **Create project**
-
-This application is nothing more than a basic class with a stub for a JUnit based test suite.
-It exposes a method called `hello` that accepts a string as input, and prints a hello message on the screen.
-
-The project structure is really simple, and you should consider these two resources:
-
-- `pom.xml`: project object model (POM) configuration file
-- `src/main/java/com/example/dep/Dep.java`: source of our application
-
-### Configure the Artifactory deployment
-
-The application is ready to use, but you need some additional steps to deploy it to Artifactory:
-
-1. Log in to Artifactory with your user's credentials.
-1. From the main screen, click on the `libs-release-local` item in the **Set Me Up** panel.
-1. Copy to clipboard the configuration snippet under the **Deploy** paragraph.
-1. Change the `url` value to have it configurable by using variables.
-1. Copy the snippet in the `pom.xml` file for your project, just after the
- `dependencies` section. The snippet should look like this:
-
- ```xml
- <distributionManagement>
- <repository>
- <id>central</id>
- <name>83d43b5afeb5-releases</name>
- <url>${env.MAVEN_REPO_URL}/libs-release-local</url>
- </repository>
- </distributionManagement>
- ```
-
-Another step you need to do before you can deploy the dependency to Artifactory
-is to configure the authentication data. It is a simple task, but Maven requires
-it to stay in a file called `settings.xml` that has to be in the `.m2` subdirectory
-in the user's homedir.
-
-Since you want to use a runner to automatically deploy the application, you
-should create the file in the project's home directory and set a command line
-parameter in `.gitlab-ci.yml` to use the custom location instead of the default one:
-
-1. Create a folder called `.m2` in the root of your repository
-1. Create a file called `settings.xml` in the `.m2` folder
-1. Copy the following content into a `settings.xml` file:
-
- ```xml
- <settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd"
- xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <servers>
- <server>
- <id>central</id>
- <username>${env.MAVEN_REPO_USER}</username>
- <password>${env.MAVEN_REPO_PASS}</password>
- </server>
- </servers>
- </settings>
- ```
-
- Username and password will be replaced by the correct values using variables.
-
-### Configure GitLab CI/CD for `simple-maven-dep`
-
-Now it's time we set up [GitLab CI/CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) to automatically build, test and deploy the dependency!
-
-GitLab CI/CD uses a file in the root of the repository, named `.gitlab-ci.yml`, to read the definitions for jobs
-that will be executed by the configured runners. You can read more about this file in the [GitLab Documentation](../../yaml/README.md).
-
-First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Environment variables** page
-and add the following ones (replace them with your current values, of course):
-
-- **MAVEN_REPO_URL**: `http://artifactory.example.com:8081/artifactory` (your Artifactory URL)
-- **MAVEN_REPO_USER**: `gitlab` (your Artifactory username)
-- **MAVEN_REPO_PASS**: `AKCp2WXr3G61Xjz1PLmYa3arm3yfBozPxSta4taP3SeNu2HPXYa7FhNYosnndFNNgoEds8BCS` (your Artifactory Encrypted Password)
-
-Now it's time to define jobs in `.gitlab-ci.yml` and push it to the repository:
-
-```yaml
-image: maven:latest
-
-variables:
- MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
- MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
-
-cache:
- paths:
- - .m2/repository/
- - target/
-
-build:
- stage: build
- script:
- - mvn $MAVEN_CLI_OPTS compile
-
-test:
- stage: test
- script:
- - mvn $MAVEN_CLI_OPTS test
-
-deploy:
- stage: deploy
- script:
- - mvn $MAVEN_CLI_OPTS deploy
- only:
- - master
-```
-
-The runner uses the latest [Maven Docker image](https://hub.docker.com/_/maven/),
-which contains all of the tools and dependencies needed to manage the project
-and to run the jobs.
-
-Environment variables are set to instruct Maven to use the `homedir` of the repository instead of the user's home when searching for configuration and dependencies.
-
-Caching the `.m2/repository folder` (where all the Maven files are stored), and the `target` folder (where our application will be created), is useful for speeding up the process
-by running all Maven phases in a sequential order, therefore, executing `mvn test` will automatically run `mvn compile` if necessary.
-
-Both `build` and `test` jobs leverage the `mvn` command to compile the application and to test it as defined in the test suite that is part of the application.
-
-Deploy to Artifactory is done as defined by the variables we have just set up.
-The deployment occurs only if we're pushing or merging to `master` branch, so that the development versions are tested but not published.
-
-Done! Now you have all the changes in the GitLab repository, and a pipeline has already been started for this commit. In the **Pipelines** tab you can see what's happening.
-If the deployment has been successful, the deploy job log will output:
-
-```plaintext
-[INFO] ------------------------------------------------------------------------
-[INFO] BUILD SUCCESS
-[INFO] ------------------------------------------------------------------------
-[INFO] Total time: 1.983 s
-```
-
->**Note**:
-the `mvn` command downloads a lot of files from the internet, so you'll see a lot of extra activity in the log the first time you run it.
-
-Yay! You did it! Checking in Artifactory will confirm that you have a new artifact available in the `libs-release-local` repository.
-
-## Create the main Maven application
-
-Now that you have the dependency available on Artifactory, it's time to use it!
-Let's see how we can have it as a dependency to our main application.
-
-### Prepare the main application
-
-We'll use again a Maven app that can be cloned from our example project:
-
-1. Create a new project by selecting **Import project from âž” Repo by URL**
-1. Add the following URL:
-
- ```plaintext
- https://gitlab.com/gitlab-examples/maven/simple-maven-app.git
- ```
-
-1. Click **Create project**
-
-This one is a simple app as well. If you look at the `src/main/java/com/example/app/App.java`
-file you can see that it imports the `com.example.dep.Dep` class and calls the `hello` method passing `GitLab` as a parameter.
-
-Since Maven doesn't know how to resolve the dependency, you need to modify the configuration:
-
-1. Go back to Artifactory
-1. Browse the `libs-release-local` repository
-1. Select the `simple-maven-dep-1.0.jar` file
-1. Find the configuration snippet from the **Dependency Declaration** section of the main panel
-1. Copy the snippet in the `dependencies` section of the `pom.xml` file.
- The snippet should look like this:
-
- ```xml
- <dependency>
- <groupId>com.example.dep</groupId>
- <artifactId>simple-maven-dep</artifactId>
- <version>1.0</version>
- </dependency>
- ```
-
-### Configure the Artifactory repository location
-
-At this point you defined the dependency for the application, but you still miss where you can find the required files.
-You need to create a `.m2/settings.xml` file as you did for the dependency project, and let Maven know the location using environment variables.
-
-Here is how you can get the content of the file directly from Artifactory:
-
-1. From the main screen, click on the `libs-release-local` item in the **Set Me Up** panel
-1. Click on **Generate Maven Settings**
-1. Click on **Generate Settings**
-1. Copy to clipboard the configuration file
-1. Save the file as `.m2/settings.xml` in your repository
-
-Now you are ready to use the Artifactory repository to resolve dependencies and use `simple-maven-dep` in your main application!
-
-### Configure GitLab CI/CD for `simple-maven-app`
-
-You need a last step to have everything in place: configure the `.gitlab-ci.yml` file for this project, as you already did for `simple-maven-dep`.
-
-You want to leverage [GitLab CI/CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) to automatically build, test and run your awesome application,
-and see if you can get the greeting as expected!
-
-All you need to do is to add the following `.gitlab-ci.yml` to the repository:
-
-```yaml
-image: maven:latest
-
-stages:
- - build
- - test
- - run
-
-variables:
- MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
- MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
-
-cache:
- paths:
- - .m2/repository/
- - target/
-
-build:
- stage: build
- script:
- - mvn $MAVEN_CLI_OPTS compile
-
-test:
- stage: test
- script:
- - mvn $MAVEN_CLI_OPTS test
-
-run:
- stage: run
- script:
- - mvn $MAVEN_CLI_OPTS package
- - mvn $MAVEN_CLI_OPTS exec:java -Dexec.mainClass="com.example.app.App"
-```
-
-It is very similar to the configuration used for `simple-maven-dep`, but instead of the `deploy` job there is a `run` job.
-Probably something that you don't want to use in real projects, but here it is useful to see the application executed automatically.
-
-And that's it! In the `run` job output log you will find a friendly hello to GitLab!
-
-## Conclusion
-
-In this article we covered the basic steps to use an Artifactory Maven repository to automatically publish and consume artifacts.
-
-A similar approach could be used to interact with any other Maven compatible Binary Repository Manager.
-Obviously, you can improve these examples, optimizing the `.gitlab-ci.yml` file to better suit your needs, and adapting to your workflow.
+<!-- This redirect file can be deleted after 2021-04-18. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index fccc62a4ca0..2d8c92a1a74 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -5,13 +5,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: tutorial
---
-# Authenticating and Reading Secrets With Hashicorp Vault
+# Authenticating and Reading Secrets With HashiCorp Vault
This tutorial demonstrates how to authenticate, configure, and read secrets with HashiCorp's Vault from GitLab CI/CD.
NOTE:
[GitLab Premium](https://about.gitlab.com/pricing/) supports read access to a
-Hashicorp Vault, and enables you to
+HashiCorp Vault, and enables you to
[use Vault secrets in a CI job](../../secrets/index.md#use-vault-secrets-in-a-ci-job).
To learn more, read [Using external secrets in CI](../../secrets/index.md).
@@ -30,7 +30,7 @@ You must replace the `vault.example.com` URL below with the URL of your Vault se
## How it works
-Each job has JSON Web Token (JWT) provided as environment variable named `CI_JOB_JWT`. This JWT can be used to authenticate with Vault using the [JWT Auth](https://www.vaultproject.io/docs/auth/jwt#jwt-authentication) method.
+Each job has JSON Web Token (JWT) provided as CI/CD variable named `CI_JOB_JWT`. This JWT can be used to authenticate with Vault using the [JWT Auth](https://www.vaultproject.io/docs/auth/jwt#jwt-authentication) method.
The JWT's payload looks like this:
@@ -155,11 +155,11 @@ This example uses [bound_claims](https://www.vaultproject.io/api/auth/jwt#bound_
Combined with [protected branches](../../../user/project/protected_branches.md), you can restrict who is able to authenticate and read the secrets.
-[token_explicit_max_ttl](https://www.vaultproject.io/api/auth/jwt#token_explicit_max_ttl) specifies that the token issued by Vault, upon successful authentication, has a hard lifetime limit of 60 seconds.
+[`token_explicit_max_ttl`](https://www.vaultproject.io/api/auth/jwt#token_explicit_max_ttl) specifies that the token issued by Vault, upon successful authentication, has a hard lifetime limit of 60 seconds.
-[user_claim](https://www.vaultproject.io/api/auth/jwt#user_claim) specifies the name for the Identity alias created by Vault upon a successful login.
+[`user_claim`](https://www.vaultproject.io/api/auth/jwt#user_claim) specifies the name for the Identity alias created by Vault upon a successful login.
-[bound_claims_type](https://www.vaultproject.io/api-docs/auth/jwt#bound_claims_type) configures the interpretation of the `bound_claims` values. If set to `glob`, the values are interpreted as globs, with `*` matching any number of characters.
+[`bound_claims_type`](https://www.vaultproject.io/api-docs/auth/jwt#bound_claims_type) configures the interpretation of the `bound_claims` values. If set to `glob`, the values are interpreted as globs, with `*` matching any number of characters.
For the full list of options, see Vault's [Create Role documentation](https://www.vaultproject.io/api/auth/jwt#create-role).
@@ -187,7 +187,7 @@ read_secrets:
- echo $CI_COMMIT_REF_NAME
# and is this ref protected
- echo $CI_COMMIT_REF_PROTECTED
- # Vault's address can be provided here or as CI variable
+ # Vault's address can be provided here or as CI/CD variable
- export VAULT_ADDR=http://vault.example.com:8200
# Authenticate and get token. Token expiry time and other properties can be configured
# when configuring JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
@@ -211,7 +211,7 @@ read_secrets:
- echo $CI_COMMIT_REF_NAME
# and is this ref protected
- echo $CI_COMMIT_REF_PROTECTED
- # Vault's address can be provided here or as CI variable
+ # Vault's address can be provided here or as CI/CD variable
- export VAULT_ADDR=http://vault.example.com:8200
# Authenticate and get token. Token expiry time and other properties can be configured
# when configuring JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
diff --git a/doc/ci/examples/browser_performance.md b/doc/ci/examples/browser_performance.md
deleted file mode 100644
index 131a539499d..00000000000
--- a/doc/ci/examples/browser_performance.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/project/merge_requests/browser_performance_testing.md#configuring-browser-performance-testing'
----
-
-This document was moved to [another location](../../user/project/merge_requests/browser_performance_testing.md#configuring-browser-performance-testing).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/code_climate.md b/doc/ci/examples/code_climate.md
deleted file mode 100644
index 2b7b2574ef7..00000000000
--- a/doc/ci/examples/code_climate.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'code_quality.md'
----
-
-This document was moved to [another location](code_quality.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/code_quality.md b/doc/ci/examples/code_quality.md
deleted file mode 100644
index 808ad6d8fef..00000000000
--- a/doc/ci/examples/code_quality.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/project/merge_requests/code_quality.md#example-configuration'
----
-
-This document was moved to [another location](../../user/project/merge_requests/code_quality.md#example-configuration).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/container_scanning.md b/doc/ci/examples/container_scanning.md
deleted file mode 100644
index eecf939d959..00000000000
--- a/doc/ci/examples/container_scanning.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/application_security/container_scanning/index.md'
----
-
-This document was moved to [another location](../../user/application_security/container_scanning/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/dast.md b/doc/ci/examples/dast.md
deleted file mode 100644
index 97c5cafae95..00000000000
--- a/doc/ci/examples/dast.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/application_security/dast/index.md'
----
-
-This document was moved to [another location](../../user/application_security/dast/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/dependency_scanning.md b/doc/ci/examples/dependency_scanning.md
deleted file mode 100644
index dc4b7bd764a..00000000000
--- a/doc/ci/examples/dependency_scanning.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/application_security/dependency_scanning/index.md'
----
-
-This document was moved to [another location](../../user/application_security/dependency_scanning/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.png b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.png
deleted file mode 100644
index e76767741ce..00000000000
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/create_from_template.png b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/create_from_template.png
deleted file mode 100644
index f3761632556..00000000000
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/create_from_template.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
index 9c145677f6e..a1a7de26cf2 100644
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
+++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
@@ -1,145 +1,8 @@
---
-stage: Release
-group: Release
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-author: Dylan Griffith
-author_gitlab: DylanGriffith
-type: tutorial
-date: 2018-06-07
-description: "Continuous Deployment of a Spring Boot application to Cloud Foundry with GitLab CI/CD"
+redirect_to: '../README.md#contributed-examples'
---
-<!-- vale off -->
+This document was moved to [another location](../README.md#contributed-examples).
-# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD
-
-## Introduction
-
-This article demonstrates how to use the [Continuous Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment)
-method to deploy a [Spring Boot](https://projects.spring.io/spring-boot/) application to
-[Cloud Foundry (CF)](https://www.cloudfoundry.org/)
-with GitLab CI/CD.
-
-All the code for this project can be found in this [GitLab
-repository](https://gitlab.com/gitlab-examples/spring-gitlab-cf-deploy-demo).
-
-In case you're interested in deploying Spring Boot applications to Kubernetes
-using GitLab CI/CD, read through the blog post [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/blog/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/).
-
-## Requirements
-
-This tutorial assumes you are familiar with Java, GitLab, Cloud Foundry, and GitLab CI/CD.
-
-To follow along, you need:
-
-- An account on [Pivotal Web Services (PWS)](https://run.pivotal.io/) or any
- other Cloud Foundry (CF) instance.
-- An account on GitLab.
-
-NOTE:
-If you're not deploying to PWS, you must replace the `api.run.pivotal.io` URL in all the below
-commands with the [API URL](https://docs.cloudfoundry.org/running/cf-api-endpoint.html)
-of your CF instance.
-
-## Create your project
-
-To create your Spring Boot application you can use the Spring template in
-GitLab when creating a new project:
-
-![New Project From Template](img/create_from_template.png)
-
-## Configure the deployment to Cloud Foundry
-
-To deploy to Cloud Foundry you must add a `manifest.yml` file. This
-is the configuration for the CF CLI you must use to deploy the application.
-Create this in the root directory of your project with the following
-content:
-
-```yaml
----
-applications:
- - name: gitlab-hello-world
- random-route: true
- memory: 1G
- path: target/demo-0.0.1-SNAPSHOT.jar
-```
-
-## Configure GitLab CI/CD to deploy your application
-
-Now you must add the GitLab CI/CD configuration file
-([`.gitlab-ci.yml`](../../yaml/README.md))
-to your project's root. This is how GitLab figures out what commands must run whenever
-code is pushed to your repository. Add the following `.gitlab-ci.yml`
-file to the root directory of the repository. GitLab detects it
-automatically and runs the defined steps once you push your code:
-
-```yaml
-image: java:8
-
-stages:
- - build
- - deploy
-
-before_script:
- - chmod +x mvnw
-
-build:
- stage: build
- script: ./mvnw package
- artifacts:
- paths:
- - target/demo-0.0.1-SNAPSHOT.jar
-
-production:
- stage: deploy
- script:
- - curl --location "https://cli.run.pivotal.io/stable?release=linux64-binary&source=github" | tar zx
- - ./cf login -u $CF_USERNAME -p $CF_PASSWORD -a api.run.pivotal.io
- - ./cf push
- only:
- - master
-```
-
-This uses the `java:8` [Docker image](../../docker/using_docker_images.md)
-to build your application, as it provides the up-to-date Java 8 JDK on [Docker Hub](https://hub.docker.com/).
-You also added the [`only` clause](../../yaml/README.md#onlyexcept-basic)
-to ensure your deployments only happen when you push to the master branch.
-
-Because the steps defined in `.gitlab-ci.yml` require credentials to sign in to
-CF, you must add your CF credentials as
-[environment variables](../../variables/README.md#predefined-environment-variables)
-in GitLab CI/CD. To set the environment variables, navigate to your project's
-**Settings > CI/CD**, and then expand **Variables**. Name the variables
-`CF_USERNAME` and `CF_PASSWORD` and set them to the correct values.
-
-![Variable Settings in GitLab](img/cloud_foundry_variables.png)
-
-After set up, GitLab CI/CD deploys your app to CF at every push to your
-repository's default branch. To review the build logs or watch your builds
-running live, navigate to **CI/CD > Pipelines**.
-
-WARNING:
-It's considered best practice for security to create a separate deploy user for
-your application and add its credentials to GitLab instead of using a
-developer's credentials.
-
-To start a manual deployment in GitLab go to **CI/CD > Pipelines** then click
-**Run Pipeline**. After the app is finished deploying, it displays the
-URL of your application in the logs for the `production` job:
-
-```shell
-requested state: started
-instances: 1/1
-usage: 1G x 1 instances
-urls: gitlab-hello-world-undissembling-hotchpot.cfapps.io
-last uploaded: Mon Nov 6 10:02:25 UTC 2017
-stack: cflinuxfs2
-buildpack: client-certificate-mapper=1.2.0_RELEASE container-security-provider=1.8.0_RELEASE java-buildpack=v4.5-offline-https://github.com/cloudfoundry/java-buildpack.git#ffeefb9 java-main java-opts jvmkill-agent=1.10.0_RELEASE open-jdk-like-jre=1.8.0_1...
-
- state since cpu memory disk details
-#0 running 2017-11-06 09:03:22 PM 120.4% 291.9M of 1G 137.6M of 1G
-```
-
-You can then visit your deployed application (for this example,
-`https://gitlab-hello-world-undissembling-hotchpot.cfapps.io/`) and you should
-see the "Spring is here!" message.
+<!-- This redirect file can be deleted after 2021-04-18. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index 958093364af..779ca98084f 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -38,15 +38,15 @@ apt-get install ruby-dev
The Dpl provides support for vast number of services, including: Heroku, Cloud Foundry, AWS/S3, and more.
To use it simply define provider and any additional parameters required by the provider.
-For example if you want to use it to deploy your application to Heroku, you need to specify `heroku` as provider, specify `api-key` and `app`.
-All possible parameters can be found here: <https://github.com/travis-ci/dpl#heroku-api>.
+For example if you want to use it to deploy your application to Heroku, you need to specify `heroku` as provider, specify `api_key` and `app`.
+All possible parameters can be found in the [Heroku API section](https://github.com/travis-ci/dpl#heroku-api).
```yaml
staging:
stage: deploy
script:
- gem install dpl
- - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY
+ - dpl --provider=heroku --app=my-app-staging --api_key=$HEROKU_STAGING_API_KEY
```
In the above example we use Dpl to deploy `my-app-staging` to Heroku server with API key stored in `HEROKU_STAGING_API_KEY` secure variable.
@@ -67,7 +67,7 @@ staging:
- apt-get update -yq
- apt-get install -y ruby-dev
- gem install dpl
- - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY
+ - dpl --provider=heroku --app=my-app-staging --api_key=$HEROKU_STAGING_API_KEY
only:
- master
```
@@ -90,7 +90,7 @@ staging:
stage: deploy
script:
- gem install dpl
- - dpl --provider=heroku --app=my-app-staging --api-key=$HEROKU_STAGING_API_KEY
+ - dpl --provider=heroku --app=my-app-staging --api_key=$HEROKU_STAGING_API_KEY
only:
- master
@@ -98,7 +98,7 @@ production:
stage: deploy
script:
- gem install dpl
- - dpl --provider=heroku --app=my-app-production --api-key=$HEROKU_PRODUCTION_API_KEY
+ - dpl --provider=heroku --app=my-app-production --api_key=$HEROKU_PRODUCTION_API_KEY
only:
- tags
```
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index 6bc96ae6c30..2d7ba2bc759 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -5,9 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: tutorial
---
-# Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD
+# Running Composer and npm scripts with deployment via SCP in GitLab CI/CD
-This guide covers the building of dependencies of a PHP project while compiling assets via an NPM script using [GitLab CI/CD](../../README.md).
+This guide covers the building of dependencies of a PHP project while compiling assets via an npm script using [GitLab CI/CD](../../README.md).
While it is possible to create your own image with custom PHP and Node.js versions, for brevity we use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and Node.js installed.
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/aws_config_window.png b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/aws_config_window.png
deleted file mode 100644
index 09eef98202f..00000000000
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/aws_config_window.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/gitlab_config.png b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/gitlab_config.png
deleted file mode 100644
index 71ffcdea289..00000000000
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/gitlab_config.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/test_pipeline_pass.png b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/test_pipeline_pass.png
deleted file mode 100644
index a9452577a42..00000000000
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/test_pipeline_pass.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
index 298ffff568a..9408c26f06f 100644
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
@@ -1,534 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To 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: Ryan Hall
-author_gitlab: blitzgren
-type: tutorial
-date: 2018-03-07
+redirect_to: '../README.md#contributed-examples'
---
-<!-- vale off -->
+This document was moved to [another location](../README.md#contributed-examples).
-# DevOps and Game Dev with GitLab CI/CD
-
-With advances in WebGL and WebSockets, browsers are extremely viable as game development
-platforms without the use of plugins like Adobe Flash. Furthermore, by using GitLab and [AWS](https://aws.amazon.com/),
-single game developers, as well as game dev teams, can easily host browser-based games online.
-
-In this tutorial, we'll focus on DevOps, as well as testing and hosting games with Continuous
-Integration/Deployment methods using [GitLab CI/CD](../../README.md). We assume you are familiar with GitLab, JavaScript,
-and the basics of game development.
-
-## The game
-
-Our [demo game](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/) consists of a simple spaceship traveling in space that shoots by clicking the mouse in a given direction.
-
-Creating a strong CI/CD pipeline at the beginning of developing another game, [Dark Nova](https://www.darknova.io),
-was essential for the fast pace the team worked at. This tutorial will build upon my
-[previous introductory article](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/) and go through the following steps:
-
-1. Using code from the previous article to start with a bare-bones [Phaser](https://phaser.io) game built by a gulp file
-1. Adding and running unit tests
-1. Creating a `Weapon` class that can be triggered to spawn a `Bullet` in a given direction
-1. Adding a `Player` class that uses this weapon and moves around the screen
-1. Adding the sprites we will use for the `Player` and `Weapon`
-1. Testing and deploying with Continuous Integration and Continuous Deployment methods
-
-By the end, we'll have the core of a [playable game](http://gitlab-game-demo.s3-website-us-east-1.amazonaws.com/)
-that's tested and deployed on every push to the `master` branch of the [codebase](https://gitlab.com/blitzgren/gitlab-game-demo).
-This will also provide
-boilerplate code for starting a browser-based game with the following components:
-
-- Written in [TypeScript](https://www.typescriptlang.org/) and [PhaserJs](https://phaser.io)
-- Building, running, and testing with [Gulp](https://gulpjs.com)
-- Unit tests with [Chai](https://www.chaijs.com) and [Mocha](https://mochajs.org/)
-- CI/CD with GitLab
-- Hosting the codebase on GitLab.com
-- Hosting the game on AWS
-- Deploying to AWS
-
-## Requirements and setup
-
-Please refer to my previous article [DevOps and Game Dev](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/) to learn the foundational
-development tools, running a Hello World-like game, and building this game using GitLab
-CI/CD from every new push to master. The `master` branch for this game's [repository](https://gitlab.com/blitzgren/gitlab-game-demo)
-contains a completed version with all configurations. If you would like to follow along
-with this article, you can clone and work from the `devops-article` branch:
-
-```shell
-git clone git@gitlab.com:blitzgren/gitlab-game-demo.git
-git checkout devops-article
-```
-
-Next, we'll create a small subset of tests that exemplify most of the states I expect
-this `Weapon` class to go through. To get started, create a folder called `lib/tests`
-and add the following code to a new file `weaponTests.ts`:
-
-```typescript
-import { expect } from 'chai';
-import { Weapon, BulletFactory } from '../lib/weapon';
-
-describe('Weapon', () => {
- var subject: Weapon;
- var shotsFired: number = 0;
- // Mocked bullet factory
- var bulletFactory: BulletFactory = <BulletFactory>{
- generate: function(px, py, vx, vy, rot) {
- shotsFired++;
- }
- };
- var parent: any = { x: 0, y: 0 };
-
- beforeEach(() => {
- shotsFired = 0;
- subject = new Weapon(bulletFactory, parent, 0.25, 1);
- });
-
- it('should shoot if not in cooldown', () => {
- subject.trigger(true);
- subject.update(0.1);
- expect(shotsFired).to.equal(1);
- });
-
- it('should not shoot during cooldown', () => {
- subject.trigger(true);
- subject.update(0.1);
- subject.update(0.1);
- expect(shotsFired).to.equal(1);
- });
-
- it('should shoot after cooldown ends', () => {
- subject.trigger(true);
- subject.update(0.1);
- subject.update(0.3); // longer than timeout
- expect(shotsFired).to.equal(2);
- });
-
- it('should not shoot if not triggered', () => {
- subject.update(0.1);
- subject.update(0.1);
- expect(shotsFired).to.equal(0);
- });
-});
-```
-
-To build and run these tests using gulp, let's also add the following gulp functions
-to the existing `gulpfile.js` file:
-
-```typescript
-gulp.task('build-test', function () {
- return gulp.src('src/tests/**/*.ts', { read: false })
- .pipe(tap(function (file) {
- // replace file contents with browserify's bundle stream
- file.contents = browserify(file.path, { debug: true })
- .plugin(tsify, { project: "./tsconfig.test.json" })
- .bundle();
- }))
- .pipe(buffer())
- .pipe(sourcemaps.init({loadMaps: true}) )
- .pipe(gulp.dest('built/tests'));
-});
-
-gulp.task('run-test', function() {
- gulp.src(['./built/tests/**/*.ts']).pipe(mocha());
-});
-```
-
-We will start implementing the first part of our game and get these `Weapon` tests to pass.
-The `Weapon` class will expose a method to trigger the generation of a bullet at a given
-direction and speed. Later we will implement a `Player` class that ties together the user input
-to trigger the weapon. In the `src/lib` folder create a `weapon.ts` file. We'll add two classes
-to it: `Weapon` and `BulletFactory` which will encapsulate Phaser's **sprite** and
-**group** objects, and the logic specific to our game.
-
-```typescript
-export class Weapon {
- private isTriggered: boolean = false;
- private currentTimer: number = 0;
-
- constructor(private bulletFactory: BulletFactory, private parent: Phaser.Sprite, private cooldown: number, private bulletSpeed: number) {
- }
-
- public trigger(on: boolean): void {
- this.isTriggered = on;
- }
-
- public update(delta: number): void {
- this.currentTimer -= delta;
-
- if (this.isTriggered && this.currentTimer <= 0) {
- this.shoot();
- }
- }
-
- private shoot(): void {
- // Reset timer
- this.currentTimer = this.cooldown;
-
- // Get velocity direction from player rotation
- var parentRotation = this.parent.rotation + Math.PI / 2;
- var velx = Math.cos(parentRotation);
- var vely = Math.sin(parentRotation);
-
- // Apply a small forward offset so bullet shoots from head of ship instead of the middle
- var posx = this.parent.x - velx * 10
- var posy = this.parent.y - vely * 10;
-
- this.bulletFactory.generate(posx, posy, -velx * this.bulletSpeed, -vely * this.bulletSpeed, this.parent.rotation);
- }
-}
-
-export class BulletFactory {
-
- constructor(private bullets: Phaser.Group, private poolSize: number) {
- // Set all the defaults for this BulletFactory's bullet object
- this.bullets.enableBody = true;
- this.bullets.physicsBodyType = Phaser.Physics.ARCADE;
- this.bullets.createMultiple(30, 'bullet');
- this.bullets.setAll('anchor.x', 0.5);
- this.bullets.setAll('anchor.y', 0.5);
- this.bullets.setAll('outOfBoundsKill', true);
- this.bullets.setAll('checkWorldBounds', true);
- }
-
- public generate(posx: number, posy: number, velx: number, vely: number, rot: number): Phaser.Sprite {
- // Pull a bullet from Phaser's Group pool
- var bullet = this.bullets.getFirstExists(false);
-
- // Set the few unique properties about this bullet: rotation, position, and velocity
- if (bullet) {
- bullet.reset(posx, posy);
- bullet.rotation = rot;
- bullet.body.velocity.x = velx;
- bullet.body.velocity.y = vely;
- }
-
- return bullet;
- }
-}
-```
-
-Lastly, we'll redo our entry point, `game.ts`, to tie together both `Player` and `Weapon` objects
-as well as add them to the update loop. Here is what the updated `game.ts` file looks like:
-
-```typescript
-import { Player } from "./player";
-import { Weapon, BulletFactory } from "./weapon";
-
-window.onload = function() {
- var game = new Phaser.Game(800, 600, Phaser.AUTO, 'gameCanvas', { preload: preload, create: create, update: update });
- var player: Player;
- var weapon: Weapon;
-
- // Import all assets prior to loading the game
- function preload () {
- game.load.image('player', 'assets/player.png');
- game.load.image('bullet', 'assets/bullet.png');
- }
-
- // Create all entities in the game, after Phaser loads
- function create () {
- // Create and position the player
- var playerSprite = game.add.sprite(400, 550, 'player');
- playerSprite.anchor.setTo(0.5);
- player = new Player(game.input, playerSprite, 150);
-
- var bulletFactory = new BulletFactory(game.add.group(), 30);
- weapon = new Weapon(bulletFactory, player.sprite, 0.25, 1000);
-
- player.loadWeapon(weapon);
- }
-
- // This function is called once every tick, default is 60fps
- function update() {
- var deltaSeconds = game.time.elapsedMS / 1000; // convert to seconds
- player.update(deltaSeconds);
- weapon.update(deltaSeconds);
- }
-}
-```
-
-Run `gulp serve` and you can run around and shoot. Wonderful! Let's update our CI
-pipeline to include running the tests along with the existing build job.
-
-## Continuous Integration
-
-To ensure our changes don't break the build and all tests still pass, we use
-Continuous Integration (CI) to run these checks automatically for every push.
-Read through this article to understand [Continuous Integration, Continuous Delivery, and Continuous Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/),
-and how these methods are leveraged by GitLab.
-From the [last tutorial](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/) we already have a `.gitlab-ci.yml` file set up for building our app from
-every push. We need to set up a new CI job for testing, which GitLab CI/CD will run after the build job using our generated artifacts from gulp.
-
-Please read through the [documentation on CI/CD configuration](../../../ci/yaml/README.md) file to explore its contents and adjust it to your needs.
-
-### Build your game with GitLab CI/CD
-
-We need to update our build job to ensure tests get run as well. Add `gulp build-test`
-to the end of the `script` array for the existing `build` job. After these commands run,
-we know we will need to access everything in the `built` folder, given by GitLab CI/CD's `artifacts`.
-We'll also cache `node_modules` to avoid having to do a full re-pull of those dependencies:
-just pack them up in the cache. Here is the full `build` job:
-
-```yaml
-build:
- stage: build
- script:
- - npm i gulp -g
- - npm i
- - gulp
- - gulp build-test
- cache:
- policy: push
- paths:
- - node_modules
- artifacts:
- paths:
- - built
-```
-
-### Test your game with GitLab CI/CD
-
-For testing locally, we simply run `gulp run-tests`, which requires gulp to be installed
-globally like in the `build` job. We pull `node_modules` from the cache, so the `npm i`
-command won't have to do much. In preparation for deployment, we know we will still need
-the `built` folder in the artifacts, which will be brought over as default behavior from
-the previous job. Lastly, by convention, we let GitLab CI/CD know this needs to be run after
-the `build` job by giving it a `test` [stage](../../../ci/yaml/README.md#stages).
-Following the YAML structure, the `test` job should look like this:
-
-```yaml
-test:
- stage: test
- script:
- - npm i gulp -g
- - npm i
- - gulp run-test
- cache:
- policy: push
- paths:
- - node_modules/
- artifacts:
- paths:
- - built/
-```
-
-We have added unit tests for a `Weapon` class that shoots on a specified interval.
-The `Player` class implements `Weapon` along with the ability to move around and shoot. Also,
-we've added test artifacts and a test stage to our GitLab CI/CD pipeline using `.gitlab-ci.yml`,
-allowing us to run our tests by every push.
-Our entire `.gitlab-ci.yml` file should now look like this:
-
-```yaml
-image: node:10
-
-build:
- stage: build
- script:
- - npm i gulp -g
- - npm i
- - gulp
- - gulp build-test
- cache:
- policy: push
- paths:
- - node_modules/
- artifacts:
- paths:
- - built/
-
-test:
- stage: test
- script:
- - npm i gulp -g
- - npm i
- - gulp run-test
- cache:
- policy: pull
- paths:
- - node_modules/
- artifacts:
- paths:
- - built/
-```
-
-### Run your CI/CD pipeline
-
-That's it! Add all your new files, commit, and push. For a reference of what our repository should
-look like at this point, please refer to the [final commit related to this article on my sample repository](https://gitlab.com/blitzgren/gitlab-game-demo/commit/8b36ef0ecebcf569aeb251be4ee13743337fcfe2).
-By applying both build and test stages, GitLab will run them sequentially at every push to
-our repository. If all goes well you'll end up with a green check mark on each job for the pipeline:
-
-![Passing Pipeline](img/test_pipeline_pass.png)
-
-You can confirm that the tests passed by clicking on the `test` job to enter the full build logs.
-Scroll to the bottom and observe, in all its passing glory:
-
-```shell
-$ gulp run-test
-[18:37:24] Using gulpfile /builds/blitzgren/gitlab-game-demo/gulpfile.js
-[18:37:24] Starting 'run-test'...
-[18:37:24] Finished 'run-test' after 21 ms
-
-
- Weapon
- ✓ should shoot if not in cooldown
- ✓ should not shoot during cooldown
- ✓ should shoot after cooldown ends
- ✓ should not shoot if not triggered
-
-
- 4 passing (18ms)
-
-Uploading artifacts...
-built/: found 17 matching files
-Uploading artifacts to coordinator... ok id=17095874 responseStatus=201 Created token=aaaaaaaa Job succeeded
-```
-
-## Continuous Deployment
-
-We have our codebase built and tested on every push. To complete the full pipeline with Continuous Deployment,
-let's set up [free web hosting with AWS S3](https://aws.amazon.com/free/) and a job through which our build artifacts get
-deployed. GitLab also has a free static site hosting service we can use, [GitLab Pages](https://about.gitlab.com/stages-devops-lifecycle/pages/),
-however Dark Nova specifically uses other AWS tools that necessitates using `AWS S3`.
-Read through this article that describes [deploying to both S3 and GitLab Pages](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)
-and further delves into the principles of GitLab CI/CD than discussed in this article.
-
-### Set up S3 Bucket
-
-1. Log into your AWS account and go to [S3](https://console.aws.amazon.com/s3/home)
-1. Click the **Create Bucket** link at the top
-1. Enter a name of your choosing and click next
-1. Keep the default **Properties** and click next
-1. Click the **Manage group permissions** and allow **Read** for the **Everyone** group, click next
-1. Create the bucket, and select it in your S3 bucket list
-1. On the right side, click **Properties** and enable the **Static website hosting** category
-1. Update the radio button to the **Use this bucket to host a website** selection. Fill in `index.html` and `error.html` respectively
-
-### Set up AWS Secrets
-
-We need to be able to deploy to AWS with our AWS account credentials, but we certainly
-don't want to put secrets into source code. Luckily GitLab provides a solution for this
-with [Variables](../../../ci/variables/README.md). This can get complicated
-due to [IAM](https://aws.amazon.com/iam/) management. As a best practice, you shouldn't
-use root security credentials. Proper IAM credential management is beyond the scope of this
-article, but AWS will remind you that using root credentials is unadvised and against their
-best practices, as they should. Feel free to follow best practices and use a custom IAM user's
-credentials, which will be the same two credentials (Key ID and Secret). It's a good idea to
-fully understand [IAM Best Practices in AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html). We need to add these credentials to GitLab:
-
-1. Log into your AWS account and go to the [Security Credentials page](https://console.aws.amazon.com/iam/home#/security_credential)
-1. Click the **Access Keys** section and **Create New Access Key**. Create the key and keep the ID and secret around, you'll need them later
-
- ![AWS Access Key Configuration](img/aws_config_window.png)
-
-1. Go to your GitLab project, click **Settings > CI/CD** on the left sidebar
-1. Expand the **Variables** section
-
- ![GitLab Secret Configuration](img/gitlab_config.png)
-
-1. Add a key named `AWS_KEY_ID` and copy the key ID from Step 2 into the **Value** field
-1. Add a key named `AWS_KEY_SECRET` and copy the key secret from Step 2 into the **Value** field
-
-### Deploy your game with GitLab CI/CD
-
-To deploy our build artifacts, we need to install the [AWS CLI](https://aws.amazon.com/cli/) on
-the shared runner. The shared runner also needs to be able to authenticate with your AWS
-account to deploy the artifacts. By convention, AWS CLI will look for `AWS_ACCESS_KEY_ID`
-and `AWS_SECRET_ACCESS_KEY`. GitLab CI/CD gives us a way to pass the variables we
-set up in the prior section using the `variables` portion of the `deploy` job. At the end,
-we add directives to ensure deployment `only` happens on pushes to `master`. This way, every
-single branch still runs through CI, and only merging (or committing directly) to master will
-trigger the `deploy` job of our pipeline. Put these together to get the following:
-
-```yaml
-deploy:
- stage: deploy
- variables:
- AWS_ACCESS_KEY_ID: "$AWS_KEY_ID"
- AWS_SECRET_ACCESS_KEY: "$AWS_KEY_SECRET"
- script:
- - apt-get update
- - apt-get install -y python3-dev python3-pip
- - easy_install3 -U pip
- - pip3 install --upgrade awscli
- - aws s3 sync ./built s3://gitlab-game-demo --region "us-east-1" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --cache-control "no-cache, no-store, must-revalidate" --delete
- only:
- - master
-```
-
-Be sure to update the region and S3 URL in that last script command to fit your setup.
-Our final configuration file `.gitlab-ci.yml` looks like:
-
-```yaml
-image: node:10
-
-build:
- stage: build
- script:
- - npm i gulp -g
- - npm i
- - gulp
- - gulp build-test
- cache:
- policy: push
- paths:
- - node_modules/
- artifacts:
- paths:
- - built/
-
-test:
- stage: test
- script:
- - npm i gulp -g
- - gulp run-test
- cache:
- policy: pull
- paths:
- - node_modules/
- artifacts:
- paths:
- - built/
-
-deploy:
- stage: deploy
- variables:
- AWS_ACCESS_KEY_ID: "$AWS_KEY_ID"
- AWS_SECRET_ACCESS_KEY: "$AWS_KEY_SECRET"
- script:
- - apt-get update
- - apt-get install -y python3-dev python3-pip
- - easy_install3 -U pip
- - pip3 install --upgrade awscli
- - aws s3 sync ./built s3://gitlab-game-demo --region "us-east-1" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --cache-control "no-cache, no-store, must-revalidate" --delete
- only:
- - master
-```
-
-## Conclusion
-
-Within the [demo repository](https://gitlab.com/blitzgren/gitlab-game-demo) you can also find a handful of boilerplate code to get
-[TypeScript](https://www.typescriptlang.org/), [Mocha](https://mochajs.org/), [Gulp](https://gulpjs.com/) and [Phaser](https://phaser.io) all playing
-together nicely with GitLab CI/CD, which is the result of lessons learned while making [Dark Nova](https://www.darknova.io).
-Using a combination of free and open source software, we have a full CI/CD pipeline, a game foundation,
-and unit tests, all running and deployed at every push to master - with shockingly little code.
-Errors can be easily debugged through GitLab build logs, and within minutes of a successful commit,
-you can see the changes live on your game.
-
-Setting up Continuous Integration and Continuous Deployment from the start with Dark Nova enables
-rapid but stable development. We can easily test changes in a separate [environment](../../environments/index.md),
-or multiple environments if needed. Balancing and updating a multiplayer game can be ongoing
-and tedious, but having faith in a stable deployment with GitLab CI/CD allows
-a lot of breathing room in quickly getting changes to players.
-
-## Further settings
-
-Here are some ideas to further investigate that can speed up or improve your pipeline:
-
-- [Yarn](https://yarnpkg.com) instead of npm
-- Set up a custom [Docker](../../../ci/docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml) image that can pre-load dependencies and tools (like AWS CLI)
-- Forward a [custom domain](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html) to your game's S3 static website
-- Combine jobs if you find it unnecessary for a small project
-- Avoid the queues and set up your own [custom GitLab CI/CD runner](https://about.gitlab.com/blog/2016/03/01/gitlab-runner-with-docker/)
+<!-- This redirect file can be deleted after 2021-04-19. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
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 4521c2ed52e..e20e86e8936 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -191,7 +191,7 @@ option as an argument to `npm run confidence-check` on the command line.
However, we still need to tell WebdriverIO which browser is available for it to use.
[GitLab CI/CD makes
-a number of variables available](../../variables/README.md#predefined-environment-variables)
+a number of variables available](../../variables/README.md#predefined-cicd-variables)
with information about the current CI job. We can use this information to dynamically set
up our WebdriverIO configuration according to the job that is running. More specifically, we can
tell WebdriverIO what browser to execute the test on depending on the name of the currently running
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 c6ddeefb916..a02a5347734 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -69,7 +69,7 @@ This test will be used later for continuously testing our app with GitLab CI/CD.
### Push to GitLab
Since we have our app up and running locally, it's time to push the codebase to our remote repository.
-Let's create [a new project](../../../gitlab-basics/create-project.md) in GitLab named `laravel-sample`.
+Let's create [a new project](../../../user/project/working_with_projects.md#create-a-project) in GitLab named `laravel-sample`.
After that, follow the command line instructions displayed on the project's homepage to initiate the repository on our machine and push the first commit.
```shell
@@ -119,8 +119,8 @@ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
cat ~/.ssh/id_rsa
```
-Now, let's add it to your GitLab project as a [variable](../../variables/README.md#gitlab-cicd-environment-variables).
-Variables are user-defined variables and are stored out of `.gitlab-ci.yml`, for security purposes.
+Now, let's add it to your GitLab project as a [CI/CD variable](../../variables/README.md).
+Project CI/CD variables are user-defined variables and are stored out of `.gitlab-ci.yml`, for security purposes.
They can be added per project by navigating to the project's **Settings** > **CI/CD**.
To the field **KEY**, add the name `SSH_PRIVATE_KEY`, and to the **VALUE** field, paste the private key you've copied earlier.
@@ -544,11 +544,11 @@ services:
...
```
-If you wish to test your app with different PHP versions and [database management systems](../../services/README.md), you can define different `image` and `services` keywords for each test job.
+If you wish to test your app with different PHP versions and [database management systems](../../services/index.md), you can define different `image` and `services` keywords for each test job.
-#### Variables
+#### CI/CD variables
-GitLab CI/CD allows us to use [environment variables](../../yaml/README.md#variables) in our jobs.
+GitLab CI/CD allows us to use [CI/CD variables](../../yaml/README.md#variables) in our jobs.
We defined MySQL as our database management system, which comes with a superuser root created by default.
So we should adjust the configuration of MySQL instance by defining `MYSQL_DATABASE` variable as our database name and `MYSQL_ROOT_PASSWORD` variable as the password of `root`.
@@ -567,7 +567,7 @@ variables:
#### Unit Test as the first job
-We defined the required shell scripts as an array of the [script](../../yaml/README.md#script) variable to be executed when running `unit_test` job.
+We defined the required shell scripts as an array of the [script](../../yaml/README.md#script) keyword to be executed when running `unit_test` job.
These scripts are some Artisan commands to prepare the Laravel, and, at the end of the script, we'll run the tests by `PHPUnit`.
@@ -589,7 +589,7 @@ unit_test:
#### Deploy to production
The job `deploy_production` will deploy the app to the production server.
-To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/README.md#ssh-keys-when-using-the-docker-executor).
+To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/index.md#ssh-keys-when-using-the-docker-executor).
If the SSH keys have added successfully, we can run Envoy.
As mentioned before, GitLab supports [Continuous Delivery](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery) methods as well.
diff --git a/doc/ci/examples/license_management.md b/doc/ci/examples/license_management.md
deleted file mode 100644
index 46be93c9676..00000000000
--- a/doc/ci/examples/license_management.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/compliance/license_compliance/index.md'
----
-
-This document was moved to [another location](../../user/compliance/license_compliance/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index 31f0cc76023..53014585f2e 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -66,8 +66,7 @@ docker-php-ext-install pdo_mysql
You might wonder what `docker-php-ext-install` is. In short, it is a script
provided by the official PHP Docker image that you can use to easily install
-extensions. For more information read the documentation at
-<https://hub.docker.com/_/php>.
+extensions. For more information read [the documentation](https://hub.docker.com/_/php).
Now that we created the script that contains all prerequisites for our build
environment, let's add it in `.gitlab-ci.yml`:
@@ -179,8 +178,8 @@ phpenv config-add my_config.ini
*__Important note:__ It seems `phpenv/phpenv`
[is abandoned](https://github.com/phpenv/phpenv/issues/57). There is a fork
- at [madumlao/phpenv](https://github.com/madumlao/phpenv) that tries to bring
- the project back to life. [CHH/phpenv](https://github.com/CHH/phpenv) also
+ at [`madumlao/phpenv`](https://github.com/madumlao/phpenv) that tries to bring
+ the project back to life. [`CHH/phpenv`](https://github.com/CHH/phpenv) also
seems like a good alternative. Picking any of the mentioned tools works
with the basic phpenv commands. Guiding you to choose the right phpenv is out
of the scope of this tutorial.*
@@ -201,10 +200,10 @@ command once, only to set up the build environment.
## Extend your tests
-### Using atoum
+### Using `atoum`
Instead of PHPUnit, you can use any other tool to run unit tests. For example
-you can use [atoum](https://github.com/atoum/atoum):
+you can use [`atoum`](https://github.com/atoum/atoum):
```yaml
before_script:
@@ -242,7 +241,7 @@ before_script:
## Access private packages or dependencies
If your test suite needs to access a private repository, you need to configure
-the [SSH keys](../ssh_keys/README.md) to be able to clone it.
+the [SSH keys](../ssh_keys/index.md) to be able to clone it.
## Use databases or other services
@@ -251,7 +250,7 @@ run. If you're using the Docker executor, you can leverage Docker's ability to
link to other containers. With GitLab Runner, this can be achieved by defining
a `service`.
-This functionality is covered in [the CI services](../services/README.md)
+This functionality is covered in [the CI services](../services/index.md)
documentation.
## Testing things locally
diff --git a/doc/ci/examples/sast.md b/doc/ci/examples/sast.md
deleted file mode 100644
index ebb3c1f66c1..00000000000
--- a/doc/ci/examples/sast.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/application_security/sast/index.md'
----
-
-This document was moved to [another location](../../user/application_security/sast/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/sast_docker.md b/doc/ci/examples/sast_docker.md
deleted file mode 100644
index eecf939d959..00000000000
--- a/doc/ci/examples/sast_docker.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/application_security/container_scanning/index.md'
----
-
-This document was moved to [another location](../../user/application_security/container_scanning/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/examples/semantic-release.md b/doc/ci/examples/semantic-release.md
index 037faaf66a2..c0fc93fe1b3 100644
--- a/doc/ci/examples/semantic-release.md
+++ b/doc/ci/examples/semantic-release.md
@@ -4,9 +4,9 @@ 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
---
-# Publish NPM packages to the GitLab Package Registry using semantic-release
+# Publish npm packages to the GitLab Package Registry using semantic-release
-This guide demonstrates how to automatically publish NPM packages to the [GitLab Package Registry](../../user/packages/npm_registry/index.md) by using [semantic-release](https://github.com/semantic-release/semantic-release).
+This guide demonstrates how to automatically publish npm packages to the [GitLab Package Registry](../../user/packages/npm_registry/index.md) by using [semantic-release](https://github.com/semantic-release/semantic-release).
You can also view or fork the complete [example source](https://gitlab.com/gitlab-examples/semantic-release-npm).
@@ -15,7 +15,7 @@ You can also view or fork the complete [example source](https://gitlab.com/gitla
1. Open a terminal and navigate to the project's repository
1. Run `npm init`. Name the module according to [the Package Registry's naming conventions](../../user/packages/npm_registry/index.md#package-naming-convention). For example, if the project's path is `gitlab-examples/semantic-release-npm`, name the module `@gitlab-examples/semantic-release-npm`.
-1. Install the following NPM packages:
+1. Install the following npm packages:
```shell
npm install semantic-release @semantic-release/git @semantic-release/gitlab @semantic-release/npm --save-dev
@@ -35,7 +35,7 @@ You can also view or fork the complete [example source](https://gitlab.com/gitla
}
```
-1. Update the `files` key with glob pattern(s) that selects all files that should be included in the published module. More information about `files` can be found [in NPM's documentation](https://docs.npmjs.com/cli/v6/configuring-npm/package-json/#files).
+1. Update the `files` key with glob pattern(s) that selects all files that should be included in the published module. More information about `files` can be found [in npm's documentation](https://docs.npmjs.com/cli/v6/configuring-npm/package-json/#files).
1. Add a `.gitignore` file to the project to avoid committing `node_modules`:
@@ -80,13 +80,13 @@ publish:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
-This example configures the pipeline with a single job, `publish`, which runs `semantic-release`. The semantic-release library publishes new versions of the NPM package and creates new GitLab releases (if necessary).
+This example configures the pipeline with a single job, `publish`, which runs `semantic-release`. The semantic-release library publishes new versions of the npm package and creates new GitLab releases (if necessary).
The default `before_script` generates a temporary `.npmrc` that is used to authenticate to the Package Registry during the `publish` job.
-## Set up environment variables
+## Set up CI/CD variables
-As part of publishing a package, semantic-release increases the version number in `package.json`. For semantic-release to commit this change and push it back to GitLab, the pipeline requires a custom environment variable named `GITLAB_TOKEN`. To create this variable:
+As part of publishing a package, semantic-release increases the version number in `package.json`. For semantic-release to commit this change and push it back to GitLab, the pipeline requires a custom CI/CD variable named `GITLAB_TOKEN`. To create this variable:
1. Navigate to **Project > Settings > Access Tokens**.
1. Give the token a name, and select the `api` scope.
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index 87291f4e8b8..28d00362309 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -59,7 +59,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in **Settings > CI/CD > Environment variables** in your GitLab project:
+You'll need to create two variables in **Settings > CI/CD > Variables** in your GitLab project:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 1204a1ae837..5bf0b3d01be 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -50,7 +50,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in your project's **Settings > CI/CD > Environment variables** and do not check **Protect variable** and **Mask variable**:
+You'll need to create two CI/CD variables in your project's **Settings > CI/CD > Variables** and do not check **Protect variable** or **Mask variable**:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/examples/test-phoenix-application.md b/doc/ci/examples/test-phoenix-application.md
deleted file mode 100644
index 52db5740c34..00000000000
--- a/doc/ci/examples/test-phoenix-application.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: '../../ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md'
----
-
-The content of this page was incorporated in [this document](../../ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md).
diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md
index 5c499d6a855..057b950289d 100644
--- a/doc/ci/examples/test-scala-application.md
+++ b/doc/ci/examples/test-scala-application.md
@@ -1,81 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To 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
+redirect_to: 'README.md#contributed-examples'
---
-# Test and deploy a Scala application to Heroku
+This document was moved to [another location](README.md#contributed-examples).
-This example demonstrates the integration of GitLab CI/CD with Scala
-applications using SBT. You can view or fork the [example project](https://gitlab.com/gitlab-examples/scala-sbt)
-and view the logs of its past [CI jobs](https://gitlab.com/gitlab-examples/scala-sbt/-/jobs?scope=finished).
-
-## Add `.gitlab-ci.yml` file to project
-
-The following `.gitlab-ci.yml` should be added in the root of your
-repository to trigger CI:
-
-``` yaml
-image: openjdk:8
-
-stages:
- - test
- - deploy
-
-before_script:
- - apt-get update -y
- - apt-get install apt-transport-https -y
- ## Install SBT
- - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
- - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
- - apt-get update -y
- - apt-get install sbt -y
- - sbt sbtVersion
-
-test:
- stage: test
- script:
- - sbt clean coverage test coverageReport
-
-deploy:
- stage: deploy
- script:
- - apt-get update -yq
- - apt-get install rubygems ruby-dev -y
- - gem install dpl
- - dpl --provider=heroku --app=gitlab-play-sample-app --api-key=$HEROKU_API_KEY
-```
-
-In the above configuration:
-
-- The `before_script` installs [SBT](https://www.scala-sbt.org/) and
- displays the version that is being used.
-- The `test` stage executes SBT to compile and test the project.
- - [sbt-scoverage](https://github.com/scoverage/sbt-scoverage) is used as an SBT
- plugin to measure test coverage.
-- The `deploy` stage automatically deploys the project to Heroku using dpl.
-
-You can use other versions of Scala and SBT by defining them in
-`build.sbt`.
-
-## Display test coverage in job
-
-Add the `Coverage was \[\d+.\d+\%\]` regular expression in the
-**Settings > Pipelines > Coverage report** project setting to
-retrieve the [test coverage](../pipelines/settings.md#test-coverage-report-badge)
-rate from the build trace and have it displayed with your jobs.
-
-**Pipelines** must be enabled for this option to appear.
-
-## Heroku application
-
-A Heroku application is required. You can create one through the
-[Dashboard](https://dashboard.heroku.com/). Substitute `gitlab-play-sample-app`
-in the `.gitlab-ci.yml` file with your application's name.
-
-## Heroku API key
-
-You can look up your Heroku API key in your
-[account](https://dashboard.heroku.com/account). Add a [protected variable](../variables/README.md#protect-a-custom-variable) with
-this value in **Project âž” Variables** with key `HEROKU_API_KEY`.
+<!-- This redirect file can be deleted after 2021-04-18. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index fb42ed64e78..d9a40c1feb6 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -13,7 +13,7 @@ type: reference
> are encouraged to upgrade your GitLab instance if you haven't done already.
> If you are **not** using GitLab 8.12 or higher, you would need to work your way
> around submodules in order to access the sources of e.g., `gitlab.com/group/project`
-> with the use of [SSH keys](ssh_keys/README.md).
+> with the use of [SSH keys](ssh_keys/index.md).
> - With GitLab 8.12 onward, your permissions are used to evaluate what a CI job
> can access. More information about how this system works can be found in the
> [Jobs permissions model](../user/permissions.md#job-permissions).
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index c04bcd6f549..307dcdf258c 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -6,162 +6,114 @@ description: "An overview of Continuous Integration, Continuous Delivery, and Co
type: concepts
---
-# Introduction to CI/CD with GitLab
+# CI/CD concepts **(FREE)**
-This document presents an overview of the concepts of Continuous Integration,
-Continuous Delivery, and Continuous Deployment, as well as an introduction to
-GitLab CI/CD.
+With the continuous method of software development, you continuously build,
+test, and deploy iterative code changes. This iterative process helps reduce
+the chance that you develop new code based on buggy or failed previous versions.
+With this method, you strive to have less human intervention or even no intervention at all,
+from the development of new code until its deployment.
+
+The three primary approaches for the continuous method are:
+
+- [Continuous Integration](#continuous-integration)
+- [Continuous Delivery](#continuous-delivery)
+- [Continuous Deployment](#continuous-deployment)
NOTE:
Out-of-the-box management systems can decrease hours spent on maintaining toolchains by 10% or more.
Watch our ["Mastering continuous software development"](https://about.gitlab.com/webcast/mastering-ci-cd/)
-webcast to learn about continuous methods and how the GitLab built-in CI can help you simplify and scale software development.
+webcast to learn about continuous methods and how built-in GitLab CI/CD can help you simplify and scale software development.
-> For some additional information about GitLab CI/CD:
->
-> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Watch the [CI/CD Ease of configuration](https://www.youtube.com/embed/opdLqwz6tcE) video.
-> - Watch the [Making the case for CI/CD in your organization](https://about.gitlab.com/compare/github-actions-alternative/)
-> webcast to learn the benefits of CI/CD and how to measure the results of CI/CD automation.
+> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn how to [configure CI/CD](https://www.youtube.com/embed/opdLqwz6tcE).
+> - [Make the case for CI/CD in your organization](https://about.gitlab.com/compare/github-actions-alternative/).
> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn how [Verizon reduced rebuilds](https://about.gitlab.com/blog/2019/02/14/verizon-customer-story/)
> from 30 days to under 8 hours with GitLab.
-## Introduction to CI/CD methodologies
-
-The continuous methodologies of software development are based on
-automating the execution of scripts to minimize the chance of
-introducing errors while developing applications. They require
-less human intervention or even no intervention at all, from the
-development of new code until its deployment.
-
-It involves continuously building, testing, and deploying code
-changes at every small iteration, reducing the chance of developing
-new code based on bugged or failed previous versions.
-
-There are three main approaches to this methodology, each of them
-to be applied according to what best suits your strategy.
-
-### Continuous Integration
+## Continuous Integration
Consider an application that has its code stored in a Git
repository in GitLab. Developers push code changes every day,
multiple times a day. For every push to the repository, you
can create a set of scripts to build and test your application
-automatically, decreasing the chance of introducing errors to your app.
+automatically. These scripts help decrease the chances that you introduce errors in your application.
-This practice is known as [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration);
-for every change submitted to an application - even to development branches -
-it's built and tested automatically and continuously, ensuring the
-introduced changes pass all tests, guidelines, and code compliance
-standards you established for your app.
+This practice is known as [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration).
+Each change submitted to an application, even to development branches,
+is built and tested automatically and continuously. These tests ensure the
+changes pass all tests, guidelines, and code compliance
+standards you established for your application.
-[GitLab itself](https://gitlab.com/gitlab-org/gitlab-foss) is an
-example of using Continuous Integration as a software
-development method. For every push to the project, there's a set
-of scripts the code is checked against.
+[GitLab itself](https://gitlab.com/gitlab-org/gitlab) is an
+example of a project that uses Continuous Integration as a software
+development method. For every push to the project, a set
+of checks run against the code.
-### Continuous Delivery
+## Continuous Delivery
[Continuous Delivery](https://continuousdelivery.com/) is a step
-beyond Continuous Integration. Your application is not only
-built and tested at every code change pushed to the codebase,
-but, as an additional step, it's also deployed continuously, though
-the deployments are triggered manually.
+beyond Continuous Integration. Not only is your application
+built and tested each time a code change is pushed to the codebase,
+the application is also deployed continuously. However, with continuous
+delivery, you trigger the deployments manually.
-This method ensures the code is checked automatically but requires
+Continuous Delivery checks the code automatically, but it requires
human intervention to manually and strategically trigger the deployment
of the changes.
-### Continuous Deployment
+## Continuous Deployment
[Continuous Deployment](https://www.airpair.com/continuous-deployment/posts/continuous-deployment-for-practical-people)
-is also a further step beyond Continuous Integration, similar to
+is another step beyond Continuous Integration, similar to
Continuous Delivery. The difference is that instead of deploying your
-application manually, you set it to be deployed automatically. It does
-not require human intervention at all to have your application
-deployed.
+application manually, you set it to be deployed automatically.
+Human intervention is not required.
-## Introduction to GitLab CI/CD
+## GitLab CI/CD
-GitLab CI/CD is a powerful tool built into GitLab that allows you
-to apply all the continuous methods (Continuous Integration,
-Delivery, and Deployment) to your software with no third-party
-application or integration needed.
+[GitLab CI/CD](../quick_start/index.md) is the part of GitLab that you use
+for all of the continuous methods (Continuous Integration,
+Delivery, and Deployment). With GitLab CI/CD, you can test, build,
+and publish your software with no third-party application or integration needed.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Introduction to GitLab CI](https://www.youtube.com/watch?v=l5705U8s_nQ&t=397) from a recent GitLab meetup.
+For an overview, see [Introduction to GitLab CI/CD](https://www.youtube.com/watch?v=l5705U8s_nQ&t=397) from an April 2020 GitLab meetup.
-### Basic CI/CD workflow
+### GitLab CI/CD workflow
-Consider the following example for how GitLab CI/CD fits in a
-common development workflow.
+GitLab CI/CD fits in a common development workflow.
-Assume that you have discussed a code implementation in an issue
-and worked locally on your proposed changes. After you push your
-commits to a feature branch in a remote repository in GitLab,
-the CI/CD pipeline set for your project is triggered. By doing
-so, GitLab CI/CD:
+You can start by discussing a code implementation in an issue
+and working locally on your proposed changes. Then you can push your
+commits to a feature branch in a remote repository that's hosted in GitLab.
+The push triggers the CI/CD pipeline for your project. Then, GitLab CI/CD:
- Runs automated scripts (sequentially or in parallel) to:
- - Build and test your app.
- - Preview the changes per merge request with Review Apps, as you
- would see in your `localhost`.
+ - Build and test your application.
+ - Preview the changes in a Review App, the same as you
+ would see on your `localhost`.
-After you're happy with your implementation:
+After the implementation works as expected:
- Get your code reviewed and approved.
- Merge the feature branch into the default branch.
- GitLab CI/CD deploys your changes automatically to a production environment.
-- And finally, you and your team can easily roll it back if something goes wrong.
+
+If something goes wrong, you can roll back your changes.
![GitLab workflow example](img/gitlab_workflow_example_11_9.png)
-GitLab CI/CD is capable of doing a lot more, but this workflow
-exemplifies the ability of GitLab to track the entire process,
-without the need for an external tool to deliver your software.
-And, most usefully, you can visualize all the steps through
-the GitLab UI.
+This workflow shows the major steps in the GitLab process.
+You don't need any external tools to deliver your software and
+you can visualize all the steps in the GitLab UI.
-#### A deeper look into the CI/CD basic workflow
+### A deeper look into the CI/CD workflow
-If we take a deeper look into the basic workflow, we can see
+If you look deeper into the workflow, you can see
the features available in GitLab at each stage of the DevOps
-lifecycle, as shown in the illustration below.
+lifecycle.
![Deeper look into the basic CI/CD workflow](img/gitlab_workflow_example_extended_v12_3.png)
-If you look at the image from the left to the right,
-you can see some of the features available in GitLab
-according to each stage (Verify, Package, Release).
-
-1. **Verify**:
- - Automatically build and test your application with Continuous Integration.
- - Analyze your source code quality with [GitLab Code Quality](../../user/project/merge_requests/code_quality.md).
- - Determine the browser performance impact of code changes with [Browser Performance Testing](../../user/project/merge_requests/browser_performance_testing.md). **(PREMIUM)**
- - Determine the server performance impact of code changes with [Load Performance Testing](../../user/project/merge_requests/load_performance_testing.md). **(PREMIUM)**
- - Perform a series of tests, such as [Container Scanning](../../user/application_security/container_scanning/index.md) **(ULTIMATE)**, [Dependency Scanning](../../user/application_security/dependency_scanning/index.md) **(ULTIMATE)**, and [Unit tests](../unit_test_reports.md).
- - Deploy your changes with [Review Apps](../review_apps/index.md) to preview the app changes on every branch.
-1. **Package**:
- - Store Docker images with the [Container Registry](../../user/packages/container_registry/index.md).
- - Store packages with the [Package Registry](../../user/packages/package_registry/index.md).
-1. **Release**:
- - Continuous Deployment, automatically deploying your app to production.
- - Continuous Delivery, manually click to deploy your app to production.
- - Deploy static websites with [GitLab Pages](../../user/project/pages/index.md).
- - Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature with [Canary Deployments](../../user/project/canary_deployments.md).
- - Deploy your features behind [Feature Flags](../../operations/feature_flags.md).
- - Add release notes to any Git tag with [GitLab Releases](../../user/project/releases/index.md).
- - View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](../../user/project/deploy_boards.md).
- - Deploy your application to a production environment in a Kubernetes cluster with [Auto Deploy](../../topics/autodevops/stages.md#auto-deploy).
-
-With GitLab CI/CD you can also:
-
-- Easily set up your app's entire lifecycle with [Auto DevOps](../../topics/autodevops/index.md).
-- Deploy your app to different [environments](../environments/index.md).
-- Install your own [GitLab Runner](https://docs.gitlab.com/runner/).
-- [Schedule pipelines](../pipelines/schedules.md).
-- Check for app vulnerabilities with [Security Test reports](../../user/application_security/index.md). **(ULTIMATE)**
-
-To see all CI/CD features, navigate back to the [CI/CD index](../README.md).
-
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-Watch the video [GitLab CI Live Demo](https://youtu.be/l5705U8s_nQ?t=369) with a deeper overview of GitLab CI/CD.
+[Get a deeper look at GitLab CI/CD](https://youtu.be/l5705U8s_nQ?t=369).
diff --git a/doc/ci/jenkins/index.md b/doc/ci/jenkins/index.md
deleted file mode 100644
index 3f720ef959e..00000000000
--- a/doc/ci/jenkins/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../migration/jenkins.md'
----
-
-This document was moved to [another location](../migration/jenkins.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md
index c985a5b00ef..d1fe6db3ee4 100644
--- a/doc/ci/jobs/index.md
+++ b/doc/ci/jobs/index.md
@@ -133,12 +133,29 @@ In the pipeline, the result is a group named `build ruby` with three jobs:
![Job group](img/job_group_v12_10.png)
-The jobs are be ordered by comparing the numbers from left to right. You
+The jobs are ordered by comparing the numbers from left to right. You
usually want the first number to be the index and the second number to be the total.
[This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99)
evaluates the job names: `\d+[\s:\/\\]+\d+\s*`.
+### Improved job grouping
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52644) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](../../administration/feature_flags.md). **(FREE SELF)**
+
+Job grouping is evaluated with an improved regular expression to group jobs by name:
+
+- `([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z`.
+
+The new implementation removes one or more `: [...]`, `X Y`, `X/Y`, or `X\Y` sequences
+from the **end** of job names only.
+
+Matching substrings occuring at the beginning or in the middle of build names are
+no longer removed.
+
## Specifying variables when running manual jobs
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30485) in GitLab 12.2.
@@ -150,9 +167,9 @@ additional variables. To access this page, click on the **name** of the manual j
the pipeline view, *not* the play (**{play}**) button.
This is useful when you want to alter the execution of a job that uses
-[custom environment variables](../variables/README.md#custom-environment-variables).
+[custom CI/CD variables](../variables/README.md#custom-cicd-variables).
Add a variable name (key) and value here to override the value defined in
-[the UI or `.gitlab-ci.yml`](../variables/README.md#custom-environment-variables),
+[the UI or `.gitlab-ci.yml`](../variables/README.md#custom-cicd-variables),
for a single run of the manual job.
![Manual job variables](img/manual_job_variables.png)
@@ -196,8 +213,8 @@ You can create [collapsible sections in job logs](#expand-and-collapse-job-log-s
by manually outputting special codes
that GitLab uses to determine what sections to collapse:
-- Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER`
-- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
+- Section start marker: `\e[0Ksection_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER`
+- Section end marker: `\e[0Ksection_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
You must add these codes to the script section of the CI configuration. For example,
using `echo`:
@@ -205,9 +222,9 @@ using `echo`:
```yaml
job1:
script:
- - echo -e "section_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section"
+ - echo -e "\e[0Ksection_start:`date +%s`:my_first_section\r\e[0KHeader of the 1st collapsible section"
- echo 'this line should be hidden when collapsed'
- - echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
+ - echo -e "\e[0Ksection_end:`date +%s`:my_first_section\r\e[0K"
```
In the example above:
@@ -223,9 +240,9 @@ In the example above:
Sample raw job log:
```plaintext
-section_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section
+\e[0Ksection_start:1560896352:my_first_section\r\e[0KHeader of the 1st collapsible section
this line should be hidden when collapsed
-section_end:1560896353:my_first_section\r\e[0K
+\e[0Ksection_end:1560896353:my_first_section\r\e[0K
```
### Pre-collapse sections
@@ -236,7 +253,7 @@ You can make the job log automatically collapse collapsible sections by adding t
Add `[collapsed=true]` after the section name and before the `\r`. The section end marker
remains unchanged:
-- Section start marker with `[collapsed=true]`: `section_start:UNIX_TIMESTAMP:SECTION_NAME[collapsed=true]\r\e[0K` + `TEXT_OF_SECTION_HEADER`
+- Section start marker with `[collapsed=true]`: `\e[0Ksection_start:UNIX_TIMESTAMP:SECTION_NAME[collapsed=true]\r\e[0K` + `TEXT_OF_SECTION_HEADER`
- Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K`
Add the updated section start text to the CI configuration. For example,
@@ -245,7 +262,7 @@ using `echo`:
```yaml
job1:
script:
- - echo -e "section_start:`date +%s`:my_first_section[collapsed=true]\r\e[0KHeader of the 1st collapsible section"
+ - echo -e "\e[0Ksection_start:`date +%s`:my_first_section[collapsed=true]\r\e[0KHeader of the 1st collapsible section"
- echo 'this line should be hidden automatically after loading the job log'
- - echo -e "section_end:`date +%s`:my_first_section\r\e[0K"
+ - echo -e "\e[0Ksection_end:`date +%s`:my_first_section\r\e[0K"
```
diff --git a/doc/ci/junit_test_reports.md b/doc/ci/junit_test_reports.md
deleted file mode 100644
index 2ae17df0933..00000000000
--- a/doc/ci/junit_test_reports.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'unit_test_reports.md'
----
-
-This document was moved to [unit_test_reports](unit_test_reports.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 35b4a2de8f8..aff18b0889f 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -114,6 +114,11 @@ For example, if your project contains a large number of tags that your CI jobs d
you could add [`--no-tags`](https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---no-tags)
to the extra flags to make your fetches faster and more compact.
+Also in the case where you repository does _not_ contain a lot of
+tags, `--no-tags` can [make a big difference in some
+cases](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746).
+If your CI builds do not depend on Git tags it is worth trying.
+
See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../runners/README.md#git-fetch-extra-flags)
for more information.
diff --git a/doc/ci/lint.md b/doc/ci/lint.md
index ec3c128f076..3888a750d6a 100644
--- a/doc/ci/lint.md
+++ b/doc/ci/lint.md
@@ -1,11 +1,13 @@
---
-stage: none
-group: unassigned
+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
---
<!-- markdownlint-disable MD044 -->
+<!-- vale gitlab.Spelling = NO -->
# Validate .gitlab-ci.yml syntax with the CI Lint tool
<!-- markdownlint-enable MD044 -->
+<!-- vale gitlab.Spelling = YES -->
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
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index 999d15eac24..5c3cf6ec02e 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -166,9 +166,10 @@ Read the [documentation on Pipelines for Merged Results](pipelines_for_merged_re
Read the [documentation on Merge Trains](pipelines_for_merged_results/merge_trains/index.md).
-## Run pipelines in the parent project for merge requests from a forked project **(STARTER)**
+## Run pipelines in the parent project for merge requests from a forked project **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217451) in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217451) in GitLab 13.3.
+> - [Moved](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) to GitLab Premium in 13.9.
By default, external contributors working from forks can't create pipelines in the
parent project. When a pipeline for merge requests is triggered by a merge request
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
index e5b9ad030d0..edfedbc2527 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md
@@ -84,9 +84,10 @@ To enable merge trains for your project:
1. If you are on a self-managed GitLab instance, ensure the [feature flag](#merge-trains-feature-flag) is set correctly.
1. [Configure your CI/CD configuration file](../../index.md#configuring-pipelines-for-merge-requests)
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.** (if not enabled)
-1. Check **Enable merge trains.**
+1. Visit your project's **Settings > General** and expand **Merge requests**.
+1. In the **Merge method** section, verify that **Merge commit** is selected.
+ You cannot use **Merge commit with semi-linear history** or **Fast-forward merge** with merge trains.
+1. In the **Merge options** section, select **Enable merged results pipelines.** (if not already selected) and **Enable merge trains.**
1. Click **Save changes**
In GitLab 13.5 and earlier, there is only one checkbox, named
@@ -209,7 +210,7 @@ Trains, create a new pipeline for merged results when this error occurs:
See [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/35135)
for more information.
-### Merge Trains feature flag **(PREMIUM ONLY)**
+### Merge Trains feature flag **(PREMIUM SELF)**
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).
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index 5d217466f5c..0a44232efd3 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -15,7 +15,7 @@ comparison to see what's different.
We have collected several resources that you may find useful before starting to migrate.
-The [Quick Start Guide](../quick_start/README.md) is a good overview of how GitLab CI/CD works. You may also be interested in [Auto DevOps](../../topics/autodevops/index.md) which can be used to build, test, and deploy your applications with little to no configuration needed at all.
+The [Quick Start Guide](../quick_start/index.md) is a good overview of how GitLab CI/CD works. You may also be interested in [Auto DevOps](../../topics/autodevops/index.md) which can be used to build, test, and deploy your applications with little to no configuration needed at all.
For advanced CI/CD teams, [custom project templates](../../user/admin_area/custom_project_templates.md) can enable the reuse of pipeline configurations.
@@ -265,14 +265,14 @@ test_async:
## Contexts and variables
-CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [variables](../variables/README.md#group-level-environment-variables) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
+CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/README.md#group-level-cicd-variables) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
## Orbs
There are two GitLab issues open addressing CircleCI Orbs and how GitLab can achieve similar functionality.
-- <https://gitlab.com/gitlab-com/Product/-/issues/1151>
-- <https://gitlab.com/gitlab-org/gitlab/-/issues/195173>
+- [issue #1151](https://gitlab.com/gitlab-com/Product/-/issues/1151)
+- [issue #195173](https://gitlab.com/gitlab-org/gitlab/-/issues/195173)
## Build environments
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index 71d5e6eb859..1424868401e 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -15,11 +15,11 @@ before diving in. Think of this page as a "GitLab CI/CD for Jenkins Users" guide
The following list of recommended steps was created after observing organizations
that were able to quickly complete this migration:
-1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/README.md) and [important product differences](#important-product-differences).
+1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/index.md) and [important product differences](#important-product-differences).
1. Learn the importance of [managing the organizational transition](#managing-the-organizational-transition).
1. [Add runners](../runners/README.md) to your GitLab instance.
1. Educate and enable your developers to independently perform the following steps in their projects:
- 1. Review the [Quick Start Guide](../quick_start/README.md) and [Pipeline Configuration Reference](../yaml/README.md).
+ 1. Review the [Quick Start Guide](../quick_start/index.md) and [Pipeline Configuration Reference](../yaml/README.md).
1. Use the [Jenkins Wrapper](#jenkinsfile-wrapper) to temporarily maintain fragile Jenkins jobs.
1. Migrate the build and CI jobs and configure them to show results directly in your merge requests. They can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point, and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#using-components-of-auto-devops) the configuration as needed.
1. Add [Review Apps](../review_apps/index.md).
@@ -79,7 +79,7 @@ There are some high level differences between the products worth mentioning:
- from the [GitLab UI](../pipelines/index.md#run-a-pipeline-manually)
- by [API call](../triggers/README.md)
- by [webhook](../triggers/README.md#triggering-a-pipeline-from-a-webhook)
- - by [ChatOps](../chatops/README.md)
+ - by [ChatOps](../chatops/index.md)
- You can control which jobs run in which cases, depending on how they are triggered,
with the [`rules` syntax](../yaml/README.md#rules).
@@ -188,7 +188,7 @@ pdf:
expire_in: 1 week
```
-Additionally, we have package management features like a built-in container, NPM, and Maven registry that you
+Additionally, we have package management features like built-in container and package registries that you
can leverage. You can see the complete list of packaging features in the
[Packages & Registries](../../user/packages/index.md) documentation.
@@ -209,7 +209,7 @@ as well as encourage inner sourcing.
In self-managed GitLab instances, you can build an [Instance Template Repository](../../user/admin_area/settings/instance_template_repository.md).
Development teams across the whole organization can select templates from a dropdown menu.
-A group administrator is able to set a group to use as the source for the
+A group maintainer or a group owner is able to set a group to use as the source for the
[custom project templates](../../user/admin_area/custom_project_templates.md), which can
be used by all projects in the group. An instance administrator can set a group as
the source for [instance project templates](../../user/group/custom_project_templates.md),
diff --git a/doc/ci/multi_project_pipeline_graphs.md b/doc/ci/multi_project_pipeline_graphs.md
deleted file mode 100644
index 66efa0a7c35..00000000000
--- a/doc/ci/multi_project_pipeline_graphs.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'multi_project_pipelines.md'
----
-
-This document was moved to [another location](multi_project_pipelines.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index 006d6bda0e0..4c186b8a64e 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -68,7 +68,7 @@ outbound connections for upstream and downstream pipeline dependencies.
When using:
-- Variables or [`rules`](yaml/README.md#rulesif) to control job behavior, the value of
+- CI/CD Variables or [`rules`](yaml/README.md#rulesif) to control job behavior, the value of
the [`$CI_PIPELINE_SOURCE` predefined variable](variables/predefined_variables.md) is
`pipeline` for multi-project pipeline triggered through the API with `CI_JOB_TOKEN`.
- [`only/except`](yaml/README.md#onlyexcept-basic) to control job behavior, use the
@@ -114,7 +114,7 @@ the `staging` job is marked as _failed_.
When using:
-- Variables or [`rules`](yaml/README.md#rulesif) to control job behavior, the value of
+- CI/CD variables or [`rules`](yaml/README.md#rulesif) to control job behavior, the value of
the [`$CI_PIPELINE_SOURCE` predefined variable](variables/predefined_variables.md) is
`pipeline` for multi-project pipelines triggered with a bridge job (using the
[`trigger:`](yaml/README.md#trigger) keyword).
@@ -162,11 +162,11 @@ of the user that ran the trigger job in the upstream project. If the user does n
have permission to run CI/CD pipelines against the protected branch, the pipeline fails. See
[pipeline security for protected branches](pipelines/index.md#pipeline-security-on-protected-branches).
-### Passing variables to a downstream pipeline
+### Passing CI/CD variables to a downstream pipeline
#### With the `variables` keyword
-Sometimes you might want to pass variables to a downstream pipeline.
+Sometimes you might want to pass CI/CD variables to a downstream pipeline.
You can do that using the `variables` keyword, just like you would when
defining a regular job.
@@ -183,7 +183,7 @@ staging:
```
The `ENVIRONMENT` variable is passed to every job defined in a downstream
-pipeline. It is available as an environment variable when GitLab Runner picks a job.
+pipeline. It is available as a variable when GitLab Runner picks a job.
In the following configuration, the `MY_VARIABLE` variable is passed to the downstream pipeline
that is created when the `trigger-downstream` job is queued. This is because `trigger-downstream`
@@ -220,7 +220,7 @@ the ones defined in the upstream project take precedence.
#### With variable inheritance
-You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](variables/README.md#inherit-environment-variables) and [cross project artifact downloads](yaml/README.md#cross-project-artifact-downloads-with-needs).
+You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](variables/README.md#inherit-cicd-variables) and [cross project artifact downloads](yaml/README.md#cross-project-artifact-downloads-with-needs).
In the upstream pipeline:
@@ -261,7 +261,7 @@ test:
### Mirroring status from triggered pipeline
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11238) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Core in 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
You can mirror the pipeline status from the triggered pipeline to the source
bridge job by using `strategy: depend`. For example:
diff --git a/doc/ci/parent_child_pipelines.md b/doc/ci/parent_child_pipelines.md
index d088d0d7e4d..bc1c02bc48c 100644
--- a/doc/ci/parent_child_pipelines.md
+++ b/doc/ci/parent_child_pipelines.md
@@ -156,7 +156,11 @@ build a matrix of targets and architectures.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM).
-We also have an [example project using Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet) which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime. You could use a similar process for other templating languages like [Dhall](https://dhall-lang.org/) or [`ytt`](https://get-ytt.io/).
+<!-- vale gitlab.Spelling = NO -->
+We also have an example project using
+[Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet)
+which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime. You could use a similar process for other templating languages like [Dhall](https://dhall-lang.org/) or [`ytt`](https://get-ytt.io/).
+<!-- vale gitlab.Spelling = NO -->
The artifact path is parsed by GitLab, not the runner, so the path must match the
syntax for the OS running GitLab. If GitLab is running on Linux but using a Windows
@@ -176,7 +180,10 @@ pipelines, which was later increased to two. A parent pipeline can trigger many
pipelines, and these child pipelines can trigger their own child pipelines. It's not
possible to trigger another level of child pipelines.
-## Pass variables to a child pipeline
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview, see [Nested Dynamic Pipelines](https://youtu.be/C5j3ju9je2M).
+
+## Pass CI/CD variables to a child pipeline
-You can [pass variables to a downstream pipeline](multi_project_pipelines.md#passing-variables-to-a-downstream-pipeline)
+You can [pass CI/CD variables to a downstream pipeline](multi_project_pipelines.md#passing-cicd-variables-to-a-downstream-pipeline)
the same way as for multi-project pipelines.
diff --git a/doc/ci/permissions/README.md b/doc/ci/permissions/README.md
deleted file mode 100644
index 897d7b6ce51..00000000000
--- a/doc/ci/permissions/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../user/permissions.md#gitlab-cicd-permissions'
----
-
-This document was moved to [user/permissions.md](../../user/permissions.md#gitlab-cicd-permissions).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png b/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png
index cc1f666f319..fcafc984ce4 100644
--- a/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png
+++ b/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png
Binary files differ
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
index 61b8e289509..9f4a1afe2f9 100644
--- a/doc/ci/pipeline_editor/index.md
+++ b/doc/ci/pipeline_editor/index.md
@@ -5,13 +5,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Pipeline Editor **(CORE)**
+# Pipeline Editor **(FREE)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4540) in GitLab 13.8.
> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
> - It's enabled 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-pipeline-editor). **(CORE ONLY)**
+> - It's recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-pipeline-editor). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -25,11 +25,12 @@ From the pipeline editor page you can:
- Do a deeper [lint](#lint-ci-configuration) of your configuration, that verifies it with any configuration
added with the [`include`](../yaml/README.md#include) keyword.
- See a [visualization](#visualize-ci-configuration) of the current configuration.
+- View an [expanded](#view-expanded-configuration) version of your configuration.
- [Commit](#commit-changes-to-ci-configuration) the changes to a specific branch.
NOTE:
-You must have already [created a CI/CD configuration file](../quick_start/README.md#create-a-gitlab-ciyml-file)
-to use the editor.
+You must already have [a `.gitlab-ci.yml` file](../quick_start/index.md#create-a-gitlab-ciyml-file)
+on the default branch (usually `master`) of your project to use the editor.
## Validate CI configuration
@@ -62,26 +63,29 @@ reflected in the CI lint. It displays the same results as the existing [CI Lint
> - It was [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/290117) in GitLab 13.8.
> - It's enabled 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-cicd-configuration-visualization). **(CORE ONLY)**
+> - It's recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cicd-configuration-visualization). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
+It is not accessible if the [pipeline editor is disabled](#enable-or-disable-pipeline-editor).
-To see a visualization of your `gitlab-ci.yml` configuration, navigate to **CI/CD > Editor**
-and select the `visualization` tab. The visualization shows all stages and jobs.
-[`needs`](../yaml/README.md#needs) relationships are displayed as lines connecting jobs together, showing the hierarchy of execution:
+To view a visualization of your `gitlab-ci.yml` configuration, in your project,
+go to **CI/CD > Editor**, and then select the **Visualize** tab. The
+visualization shows all stages and jobs. Any [`needs`](../yaml/README.md#needs)
+relationships are displayed as lines connecting jobs together, showing the
+hierarchy of execution:
![CI configuration Visualization](img/ci_config_visualization_v13_7.png)
-Hovering on a job highlights its `needs` relationships:
+Hover over a job to highlight its `needs` relationships:
![CI configuration visualization on hover](img/ci_config_visualization_hover_v13_7.png)
If the configuration does not have any `needs` relationships, then no lines are drawn because
each job depends only on the previous stage being completed successfully.
-### Enable or disable CI/CD configuration visualization **(CORE ONLY)**
+### Enable or disable CI/CD configuration visualization **(FREE SELF)**
CI/CD configuration visualization is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
@@ -100,6 +104,40 @@ To enable it:
Feature.enable(:ci_config_visualization_tab)
```
+## View expanded configuration
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/246801) in GitLab 13.9.
+> - It is [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-expanded-configuration). **(FREE SELF)**
+
+To view the fully expanded CI/CD configuration as one combined file, go to the
+pipeline editor's **View merged YAML** tab. This tab displays an expanded configuration
+where:
+
+- Configuration imported with [`include`](../yaml/README.md#include) is copied into the view.
+- Jobs that use [`extends`](../yaml/README.md#extends) display with the
+ [extended configuration merged into the job](../yaml/README.md#merge-details).
+- YAML anchors are [replaced with the linked configuration](../yaml/README.md#anchors).
+
+### Enable or disable expanded configuration **(FREE SELF)**
+
+Expanded CI/CD configuration 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 opt to enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_config_visualization_tab)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_config_visualization_tab)
+```
+
## Commit changes to CI configuration
The commit form appears at the bottom of each tab in the editor so you can commit
@@ -113,9 +151,9 @@ checkbox appears. Select it to start a new merge request after you commit the ch
![The commit form with a new branch](img/pipeline_editor_commit_v13_8.png)
-## Enable or disable pipeline editor **(CORE ONLY)**
+## Enable or disable pipeline editor **(FREE SELF)**
-The pipeline editor is under development and not ready for production use. It is
+The pipeline editor is under development but ready for production use. It is
deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can disable it.
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
deleted file mode 100644
index 090dbd3d347..00000000000
--- a/doc/ci/pipelines.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'pipelines/index.md'
----
-
-This document was moved to [another location](pipelines/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/pipelines/img/job_artifacts_merge_request.png b/doc/ci/pipelines/img/job_artifacts_merge_request.png
index fa1ed9acbf8..e87839ceeca 100644
--- a/doc/ci/pipelines/img/job_artifacts_merge_request.png
+++ b/doc/ci/pipelines/img/job_artifacts_merge_request.png
Binary files differ
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index 7920a3bf7f3..6bc0d9bddd9 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -77,7 +77,7 @@ You can also configure specific aspects of your pipelines through the GitLab UI.
- [Pipeline settings](settings.md) for each project.
- [Pipeline schedules](schedules.md).
-- [Custom CI/CD variables](../variables/README.md#custom-environment-variables).
+- [Custom CI/CD variables](../variables/README.md#custom-cicd-variables).
### Ref Specs for Runners
@@ -132,10 +132,6 @@ Pipelines can be manually executed, with predefined or manually-specified [varia
You might do this if the results of a pipeline (for example, a code build) are required outside the normal
operation of the pipeline.
-[In GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30101),
-all global variables with descriptions defined in the `.gitlab-ci.yml` file are
-displayed in the variable fields.
-
To execute a pipeline manually:
1. Navigate to your project's **CI/CD > Pipelines**.
@@ -143,10 +139,33 @@ To execute a pipeline manually:
1. On the **Run Pipeline** page:
1. Select the branch to run the pipeline for in the **Create for** field.
1. Enter any [environment variables](../variables/README.md) required for the pipeline run.
+ You can set specific variables to have their [values prefilled in the form](#prefill-variables-in-manual-pipelines).
1. Click the **Create pipeline** button.
The pipeline now executes the jobs as configured.
+#### Prefill variables in manual pipelines
+
+> [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) GitLab 13.7.
+
+You can use the [`value` and `description`](../yaml/README.md#prefill-variables-in-manual-pipelines)
+keywords to define [variables](../variables/README.md) that are prefilled when running
+a pipeline manually.
+
+In pipelines triggered manually, the **Run pipelines** page displays all variables
+with a `description` and `value` defined in the `.gitlab-ci.yml` file. The values
+can then be modified if needed, which overrides the value for that single pipeline run.
+
+The description is displayed below the variable. It can be used to explain what
+the variable is used for, what the acceptable values are, and so on:
+
+```yaml
+variables:
+ DEPLOY_ENVIRONMENT:
+ value: "staging" # Deploy to staging by default
+ description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
+```
+
### Run a pipeline by using a URL query string
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24146) in GitLab 12.5.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index 4c77a578aa4..cf8e4e71534 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -150,7 +150,7 @@ in merge requests. For more information, see
> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in GitLab 13.2.
> - Requires GitLab Runner 11.5 and above.
-The `codequality` report collects [CodeQuality issues](../../user/project/merge_requests/code_quality.md)
+The `codequality` report collects [Code Quality issues](../../user/project/merge_requests/code_quality.md)
as artifacts.
The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests.
@@ -168,9 +168,11 @@ The collected SAST report uploads to GitLab as an artifact and is summarized
in merge requests and the pipeline view. It's also used to provide data for security
dashboards.
-#### `artifacts:reports:secret_detection` **(ULTIMATE)**
+#### `artifacts:reports:secret_detection`
> - Introduced in GitLab 13.1.
+> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) in GitLab
+ 13.3.
> - Requires GitLab Runner 11.5 and above.
The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md)
@@ -482,6 +484,12 @@ a project, you can disable this behavior to save space:
1. Navigate to **Settings > CI/CD > Artifacts**.
1. Uncheck **Keep artifacts from most recent successful jobs**.
+You can disable this behavior for all projects on a self-managed instance in the
+[instance's CI/CD settings](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines). **(CORE ONLY)**
+
+When you disable the feature, the latest artifacts do not immediately expire.
+A new pipeline must run before the latest artifacts can expire and be deleted.
+
## Troubleshooting
### Error message `No files to upload`
@@ -490,7 +498,7 @@ This is often preceded by other errors or warnings that specify the filename and
generated in the first place. Please check the entire job log for such messages.
If you find no helpful messages, please retry the failed job after activating
-[CI debug logging](../variables/README.md#debug-logging).
+[CI/CD debug logging](../variables/README.md#debug-logging).
This provides useful information to investigate further.
<!-- ## Troubleshooting
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
index de78b8558c4..faebf40462e 100644
--- a/doc/ci/pipelines/pipeline_efficiency.md
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -20,7 +20,7 @@ to use pipeline features that improve efficiency right away, and get a faster so
development lifecycle earlier.
First ensure you are familiar with [GitLab CI/CD fundamentals](../introduction/index.md)
-and understand the [quick start guide](../quick_start/README.md).
+and understand the [quick start guide](../quick_start/index.md).
## Identify bottlenecks and common failures
@@ -161,7 +161,7 @@ Try to find which jobs don't need to run in all situations, and use pipeline con
to stop them from running:
- Use the [`interruptible`](../yaml/README.md#interruptible) keyword to stop old pipelines
- when they are superceded by a newer pipeline.
+ when they are superseded by a newer pipeline.
- Use [`rules`](../yaml/README.md#rules) to skip tests that aren't needed. For example,
skip backend tests when only the frontend code is changed.
- Run non-essential [scheduled pipelines](schedules.md) less frequently.
@@ -235,7 +235,7 @@ Methods to reduce Docker image size:
to analyze and shrink images.
To simplify Docker image management, you can create a dedicated group for managing
-[Docker images](../docker/README.md) and test, build and publish them with CI/CD pipelines.
+[Docker images](../docker/index.md) and test, build and publish them with CI/CD pipelines.
## Test, document, and learn
diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md
index cddfcb754ec..a8e310c1f0d 100644
--- a/doc/ci/pipelines/schedules.md
+++ b/doc/ci/pipelines/schedules.md
@@ -6,7 +6,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pipelines/schedules.
type: reference, howto
---
-# Pipeline schedules
+# Pipeline schedules **(FREE)**
> - Introduced in GitLab 9.1 as [Trigger Schedule](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10533).
> - [Renamed to Pipeline Schedule](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10853) in GitLab 9.2.
@@ -83,7 +83,7 @@ job:
- make build
```
-### Advanced configuration
+### Advanced configuration **(FREE SELF)**
The pipelines are not executed exactly on schedule because schedules are handled by
Sidekiq, which runs according to its interval.
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index 5a758bccd62..32221b78039 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -63,12 +63,12 @@ if the job surpasses the threshold, it is marked as failed.
Project defined timeout (either specific timeout set by user or the default
60 minutes timeout) may be [overridden for runners](../runners/README.md#set-maximum-job-timeout-for-a-runner).
-## Maximum artifacts size **(CORE ONLY)**
+## Maximum artifacts size **(FREE SELF)**
For information about setting a maximum artifact size for a project, see
[Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
-## Custom CI configuration path
+## Custom CI/CD configuration path
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12509) in GitLab 9.4.
> - [Support for external `.gitlab-ci.yml` locations](https://gitlab.com/gitlab-org/gitlab/-/issues/14376) introduced in GitLab 12.6.
@@ -80,7 +80,7 @@ To customize the path:
1. Go to the project's **Settings > CI / CD**.
1. Expand the **General pipelines** section.
-1. Provide a value in the **Custom CI configuration path** field.
+1. Provide a value in the **CI/CD configuration file** field.
1. Click **Save changes**.
If the CI configuration is stored within the repository in a non-default
@@ -131,8 +131,23 @@ averaged.
![Build status coverage](img/pipelines_test_coverage_build.png)
-A few examples of known coverage tools for a variety of languages can be found
-in the pipelines settings page.
+<!-- vale gitlab.Spelling = NO -->
+
+| Coverage Tool | Sample regular expression |
+|------------------------------------------------|---------------------------|
+| Simplecov (Ruby) | `\(\d+.\d+\%\) covered` |
+| pytest-cov (Python) | `^TOTAL.+?(\d+\%)$` |
+| Scoverage (Scala) | `Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)` |
+| `phpunit --coverage-text --colors=never` (PHP) | `^\s*Lines:\s*\d+.\d+\%` |
+| gcovr (C/C++) | `^TOTAL.*\s+(\d+\%)$` |
+| `tap --coverage-report=text-summary` (NodeJS) | `^Statements\s*:\s*([^%]+)` |
+| `nyc npm test` (NodeJS) | `All files[^|]*\|[^|]*\s+([\d\.]+)` |
+| excoveralls (Elixir) | `\[TOTAL\]\s+(\d+\.\d+)%` |
+| `mix test --cover` (Elixir) | `\d+.\d+\%\s+\|\s+Total` |
+| JaCoCo (Java/Kotlin) | `Total.*?([0-9]{1,3})%` |
+| `go test -cover` (Go) | `coverage: \d+.\d+% of statements` |
+
+<!-- vale gitlab.Spelling = YES -->
### Code Coverage history
@@ -143,7 +158,7 @@ To see the evolution of your project code coverage over time,
you can view a graph or download a CSV file with this data. From your project:
1. Go to **{chart}** **Project Analytics > Repository** to see the historic data for each job listed in the dropdown above the graph.
-1. If you want a CSV file of that data, click **Download raw data (.csv)**
+1. If you want a CSV file of that data, click **Download raw data (`.csv`)**
![Code coverage graph of a project over time](img/code_coverage_graph_v13_1.png)
@@ -198,7 +213,7 @@ If **Public pipelines** is disabled:
- For **private** projects, only project members (reporter or higher)
can view the pipelines or access the related features.
-## Auto-cancel pending pipelines
+## Auto-cancel redundant pipelines
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9362) in GitLab 9.1.
@@ -206,7 +221,7 @@ You can set pending or running pipelines to cancel automatically when a new pipe
1. Go to **Settings > CI / CD**.
1. Expand **General Pipelines**.
-1. Check the **Auto-cancel redundant, pending pipelines** checkbox.
+1. Check the **Auto-cancel redundant pipelines** checkbox.
1. Click **Save changes**.
Use the [`interruptible`](../yaml/README.md#interruptible) keyword to indicate if a
@@ -336,9 +351,9 @@ https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_te
![Badge with custom text and width](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=130)
-## Environment Variables
+## CI/CD Variables
-[Environment variables](../variables/README.md#gitlab-cicd-environment-variables) can be set in an environment to be available to a runner.
+[CI/CD variables](../variables/README.md) can be set to be available to a runner.
<!-- ## Troubleshooting
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index e9c85353db3..c94d6e3ea80 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -1,157 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To 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
+redirect_to: 'index.md'
---
-# Get started with GitLab CI/CD
+This document was moved to [another location](index.md).
-Use this document to get started with
-GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/).
-
-Before you start, make sure you have:
-
-- A project in GitLab that you would like to use CI/CD for.
-- Maintainer or owner access for the project.
-
-If you are migrating from another CI/CD tool, view this documentation:
-
-- [Migrate from CircleCI](../migration/circleci.md).
-- [Migrate from Jenkins](../migration/jenkins.md).
-
-## CI/CD process overview
-
-To use GitLab CI/CD:
-
-1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs.
- If you don't have a runner, [install GitLab Runner](https://docs.gitlab.com/runner/install/)
- and [register a runner](https://docs.gitlab.com/runner/register/) for your instance, project, or group.
-1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file)
- at the root of your repository. This file is where you define your CI/CD jobs.
-
-When you commit the file to your repository, the runner runs your jobs.
-The job results [are displayed in a pipeline](#view-the-status-of-your-pipeline-and-jobs).
-
-### Ensure you have runners available
-
-In GitLab, runners are agents that run your CI/CD jobs.
-
-You might already have runners available for your project, including
-[shared runners](../runners/README.md#shared-runners), which are
-available to all projects in your GitLab instance.
-
-To view available runners:
-
-- Go to **Settings > CI/CD** and expand **Runners**.
-
-As long as you have at least one runner that's active, with a green circle next to it,
-you have a runner available to process your jobs.
-
-If no runners are listed on the **Runners** page in the UI, you or an administrator
-must [install GitLab Runner](https://docs.gitlab.com/runner/install/) and
-[register](https://docs.gitlab.com/runner/register/) at least one runner.
-
-If you are testing CI/CD, you can install GitLab Runner and register runners on your local machine.
-When your CI/CD jobs run, they run on your local machine.
-
-### Create a `.gitlab-ci.yml` file
-
-The `.gitlab-ci.yml` file is a [YAML](https://en.wikipedia.org/wiki/YAML) file where
-you configure specific instructions for GitLab CI/CD.
-
-In this file, you define:
-
-- The structure and order of jobs that the runner should execute.
-- The decisions the runner should make when specific conditions are encountered.
-
-For example, you might want to run a suite of tests when you commit to
-any branch except `master`. When you commit to `master`, you want
-to run the same suite, but also publish your application.
-
-All of this is defined in the `.gitlab-ci.yml` file.
-
-To create a `.gitlab-ci.yml` file:
-
-1. Go to **Project overview > Details**.
-1. Above the file list, select the branch you want to commit to,
- click the plus icon, then select **New file**:
-
- ![New file](img/new_file_v13_6.png)
-
-1. For the **Filename**, type `.gitlab-ci.yml` and in the larger window,
- paste this sample code:
-
- ```yaml
- build-job:
- stage: build
- script:
- - echo "Hello, $GITLAB_USER_LOGIN!"
-
- test-job1:
- stage: test
- script:
- - echo "This job tests something"
-
- test-job2:
- stage: test
- script:
- - echo "This job tests something, but takes more time than test-job1."
- - echo "After the echo commands complete, it runs the sleep command for 20 seconds"
- - echo "which simulates a test that runs 20 seconds longer than test-job1"
- - sleep 20
-
- deploy-prod:
- stage: deploy
- script:
- - echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
- ```
-
- `$GITLAB_USER_LOGIN` and `$CI_COMMIT_BRANCH` are
- [predefined variables](../variables/predefined_variables.md)
- that populate when the job runs.
-
-1. Click **Commit changes**.
-
-The pipeline starts when the commit is committed.
-
-#### `.gitlab-ci.yml` tips
-
-- If you want the runner to use a Docker image to run the jobs, edit the `.gitlab-ci.yml` file
- to include your image name:
-
- ```yaml
- default:
- image: ruby:2.7.2
- ```
-
- This command tells the runner to use a Ruby image from Docker Hub.
-
-- To validate your `.gitlab-ci.yml` file, use the
- [CI Lint tool](../lint.md), which is available in every project.
-- You can also use [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration) to
- view a graphical representation of your `.gitlab-ci.yml` file.
-- For the complete `.gitlab-ci.yml` syntax, see
- [the `.gitlab-ci.yml` reference topic](../yaml/README.md).
-
-### View the status of your pipeline and jobs
-
-When you committed your changes, a pipeline started.
-
-To view your pipeline:
-
-- Go **CI/CD > Pipelines**.
-
- A pipeline with three stages should be displayed:
-
- ![Three stages](img/three_stages_v13_6.png)
-
-- To view a visual representation of your pipeline, click the pipeline ID.
-
- ![Pipeline graph](img/pipeline_graph_v13_6.png)
-
-- To view details of a job, click the job name, for example, `deploy-prod`.
-
- ![Job details](img/job_details_v13_6.png)
-
-If the job status is `stuck`, check to ensure a runner is probably configured for the project.
+<!-- This redirect file can be deleted after 2021-05-01. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md
new file mode 100644
index 00000000000..711bf0c0e7a
--- /dev/null
+++ b/doc/ci/quick_start/index.md
@@ -0,0 +1,157 @@
+---
+stage: Verify
+group: Continuous Integration
+info: To 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
+---
+
+# Get started with GitLab CI/CD **(FREE)**
+
+Use this document to get started with
+GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/).
+
+Before you start, make sure you have:
+
+- A project in GitLab that you would like to use CI/CD for.
+- Maintainer or owner access for the project.
+
+If you are migrating from another CI/CD tool, view this documentation:
+
+- [Migrate from CircleCI](../migration/circleci.md).
+- [Migrate from Jenkins](../migration/jenkins.md).
+
+## CI/CD process overview
+
+To use GitLab CI/CD:
+
+1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs.
+ If you don't have a runner, [install GitLab Runner](https://docs.gitlab.com/runner/install/)
+ and [register a runner](https://docs.gitlab.com/runner/register/) for your instance, project, or group.
+1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file)
+ at the root of your repository. This file is where you define your CI/CD jobs.
+
+When you commit the file to your repository, the runner runs your jobs.
+The job results [are displayed in a pipeline](#view-the-status-of-your-pipeline-and-jobs).
+
+### Ensure you have runners available
+
+In GitLab, runners are agents that run your CI/CD jobs.
+
+You might already have runners available for your project, including
+[shared runners](../runners/README.md#shared-runners), which are
+available to all projects in your GitLab instance.
+
+To view available runners:
+
+- Go to **Settings > CI/CD** and expand **Runners**.
+
+As long as you have at least one runner that's active, with a green circle next to it,
+you have a runner available to process your jobs.
+
+If no runners are listed on the **Runners** page in the UI, you or an administrator
+must [install GitLab Runner](https://docs.gitlab.com/runner/install/) and
+[register](https://docs.gitlab.com/runner/register/) at least one runner.
+
+If you are testing CI/CD, you can install GitLab Runner and register runners on your local machine.
+When your CI/CD jobs run, they run on your local machine.
+
+### Create a `.gitlab-ci.yml` file
+
+The `.gitlab-ci.yml` file is a [YAML](https://en.wikipedia.org/wiki/YAML) file where
+you configure specific instructions for GitLab CI/CD.
+
+In this file, you define:
+
+- The structure and order of jobs that the runner should execute.
+- The decisions the runner should make when specific conditions are encountered.
+
+For example, you might want to run a suite of tests when you commit to
+any branch except `master`. When you commit to `master`, you want
+to run the same suite, but also publish your application.
+
+All of this is defined in the `.gitlab-ci.yml` file.
+
+To create a `.gitlab-ci.yml` file:
+
+1. Go to **Project overview > Details**.
+1. Above the file list, select the branch you want to commit to,
+ click the plus icon, then select **New file**:
+
+ ![New file](img/new_file_v13_6.png)
+
+1. For the **Filename**, type `.gitlab-ci.yml` and in the larger window,
+ paste this sample code:
+
+ ```yaml
+ build-job:
+ stage: build
+ script:
+ - echo "Hello, $GITLAB_USER_LOGIN!"
+
+ test-job1:
+ stage: test
+ script:
+ - echo "This job tests something"
+
+ test-job2:
+ stage: test
+ script:
+ - echo "This job tests something, but takes more time than test-job1."
+ - echo "After the echo commands complete, it runs the sleep command for 20 seconds"
+ - echo "which simulates a test that runs 20 seconds longer than test-job1"
+ - sleep 20
+
+ deploy-prod:
+ stage: deploy
+ script:
+ - echo "This job deploys something from the $CI_COMMIT_BRANCH branch."
+ ```
+
+ `$GITLAB_USER_LOGIN` and `$CI_COMMIT_BRANCH` are
+ [predefined variables](../variables/predefined_variables.md)
+ that populate when the job runs.
+
+1. Click **Commit changes**.
+
+The pipeline starts when the commit is committed.
+
+#### `.gitlab-ci.yml` tips
+
+- If you want the runner to use a Docker image to run the jobs, edit the `.gitlab-ci.yml` file
+ to include your image name:
+
+ ```yaml
+ default:
+ image: ruby:2.7.2
+ ```
+
+ This command tells the runner to use a Ruby image from Docker Hub.
+
+- To validate your `.gitlab-ci.yml` file, use the
+ [CI Lint tool](../lint.md), which is available in every project.
+- You can also use [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration) to
+ view a graphical representation of your `.gitlab-ci.yml` file.
+- For the complete `.gitlab-ci.yml` syntax, see
+ [the `.gitlab-ci.yml` reference topic](../yaml/README.md).
+
+### View the status of your pipeline and jobs
+
+When you committed your changes, a pipeline started.
+
+To view your pipeline:
+
+- Go **CI/CD > Pipelines**.
+
+ A pipeline with three stages should be displayed:
+
+ ![Three stages](img/three_stages_v13_6.png)
+
+- To view a visual representation of your pipeline, click the pipeline ID.
+
+ ![Pipeline graph](img/pipeline_graph_v13_6.png)
+
+- To view details of a job, click the job name, for example, `deploy-prod`.
+
+ ![Job details](img/job_details_v13_6.png)
+
+If the job status is `stuck`, check to ensure a runner is probably configured for the project.
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 3512b77e4e2..9de6a1162bd 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -58,7 +58,7 @@ The process of configuring Review Apps is as follows:
1. Set up the infrastructure to host and deploy the Review Apps (check the [examples](#review-apps-examples) below).
1. [Install](https://docs.gitlab.com/runner/install/) and [configure](https://docs.gitlab.com/runner/commands/) a runner to do deployment.
-1. Set up a job in `.gitlab-ci.yml` that uses the [predefined CI environment variable](../variables/README.md) `${CI_COMMIT_REF_NAME}`
+1. Set up a job in `.gitlab-ci.yml` that uses the [predefined CI/CD variable](../variables/README.md) `${CI_COMMIT_REF_NAME}`
to create dynamic environments and restrict it to run only on branches.
Alternatively, you can get a YML template for this job by [enabling review apps](#enable-review-apps-button) for your project.
1. Optionally, set a job that [manually stops](../environments/index.md#stopping-an-environment) the Review Apps.
@@ -180,18 +180,19 @@ After you have the route mapping set up, it takes effect in the following locati
- In the diff for a merge request, comparison, or commit.
- !["View on env" button in merge request diff](img/view_on_env_mr.png)
+ ![View on environment button in merge request diff](img/view_on_env_mr.png)
- In the blob file view.
- !["View on env" button in file view](img/view_on_env_blob.png)
+ ![View on environment button in file view](img/view_on_env_blob.png)
-## Visual Reviews **(STARTER)**
+## Visual Reviews **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10761) in GitLab Starter 12.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10761) in GitLab 12.0.
+> - [Moved](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) to GitLab Premium in 13.9.
> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-visual-reviews). **(STARTER ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-visual-reviews). **(PREMIUM SELF)**
With Visual Reviews, members of any team (Product, Design, Quality, and so on) can provide feedback comments through a form in your review apps. The comments are added to the merge request that triggered the review app.
@@ -242,7 +243,7 @@ looks for a project with code hosted in a project on GitLab.com:
</script>
```
-Ideally, you should use [environment variables](../variables/predefined_variables.md)
+Ideally, you should use [CI/CD variables](../variables/predefined_variables.md)
to replace those values at runtime when each review app is created:
- `data-project-id` is the project ID, which can be found by the `CI_PROJECT_ID`
@@ -288,7 +289,7 @@ can supply the ID by either:​​
- Dynamically adding the `data-merge-request-id` value during the build of the app.
- Supplying it manually through the visual review form in the app.
-### Enable or disable Visual Reviews **(STARTER ONLY)**
+### Enable or disable Visual Reviews **(PREMIUM SELF)**
Visual Reviews is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index d6ea4d83825..bf7552ad609 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -37,10 +37,10 @@ multiple projects.
If you are using a self-managed instance of GitLab:
-- Your administrator can install and register shared runners by [following the documentation](https://docs.gitlab.com/runner/install/index.html).
- <!-- going to your project's-->
- <!-- **Settings > CI / CD**, expanding the **Runners** section, and clicking **Show runner installation instructions**.-->
- <!-- These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).-->
+- Your administrator can install and register shared runners by
+ going to your project's **Settings > CI / CD**, expanding the **Runners** section,
+ and clicking **Show runner installation instructions**.
+ These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).
- The administrator can also configure a maximum number of shared runner [pipeline minutes for
each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota).
@@ -136,10 +136,16 @@ Shared runners are automatically disabled for a project:
To disable shared runners for a group:
1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared runners** area, click **Enable shared runners for this group**.
+1. In the **Shared runners** area, turn off the **Enable shared runners for this group** toggle.
1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
click **Allow projects and subgroups to override the group setting**.
+NOTE:
+To re-enable the shared runners for a group, turn on the
+**Enable shared runners for this group** toggle.
+Then, an owner or maintainer must explicitly change this setting
+for each project subgroup or project.
+
### Group runners
Use *Group runners* when you want all projects in a group
@@ -274,7 +280,7 @@ On GitLab.com, you cannot override the job timeout for shared runners and must u
To set the maximum job timeout:
1. In a project, go to **Settings > CI/CD > Runners**.
-1. Select your specific runner to edit the settings.
+1. Select your specific runner to edit the settings.
1. Enter a value under **Maximum job timeout**.
1. Select **Save changes**.
@@ -805,3 +811,38 @@ You can set them globally or per-job in the [`variables`](../yaml/README.md#vari
## System calls not available on GitLab.com shared runners
GitLab.com shared runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library.
+
+## Artifact and cache settings
+
+> Introduced in GitLab Runner 13.9.
+
+Artifact and cache settings control the compression ratio of artifacts and caches.
+Use these settings to specify the size of the archive produced by a job.
+
+- On a slow network, uploads might be faster for smaller archives.
+- On a fast network where bandwidth and storage are not a concern, uploads might be faster using the fastest compression ratio, despite the archive produced being larger.
+
+For [GitLab Pages](../../user/project/pages/index.md) to serve
+[HTTP Range requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests), artifacts
+should use the `ARTIFACT_COMPRESSION_LEVEL: fastest` setting, as only uncompressed zip archives
+support this feature.
+
+A meter can also be enabled to provide the rate of transfer for uploads and downloads.
+
+```yaml
+variables:
+ # output upload and download progress every 2 seconds
+ TRANSFER_METER_FREQUENCY: "2s"
+
+ # Use fast compression for artifacts, resulting in larger archives
+ ARTIFACT_COMPRESSION_LEVEL: "fast"
+
+ # Use no compression for caches
+ CACHE_COMPRESSION_LEVEL: "fastest"
+```
+
+| Variable | Description |
+|---------------------------------|--------------------------------------------------------|
+| `TRANSFER_METER_FREQUENCY` | Specify how often to print the meter's transfer rate. It can be set to a duration (for example, `1s` or `1m30s`). A duration of `0` disables the meter (default). When a value is set, the pipeline shows a progress meter for artifact and cache uploads and downloads. |
+| `ARTIFACT_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
+| `CACHE_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
index f05812f77f7..eac72bc7351 100644
--- a/doc/ci/secrets/index.md
+++ b/doc/ci/secrets/index.md
@@ -13,7 +13,7 @@ Secrets represent sensitive information your CI job needs to complete work. This
sensitive information can be items like API tokens, database credentials, or private keys.
Secrets are sourced from your secrets provider.
-Unlike CI variables, which are always presented to a job, secrets must be explicitly
+Unlike CI/CD variables, which are always presented to a job, secrets must be explicitly
required by a job. Read [GitLab CI/CD pipeline configuration reference](../yaml/README.md#secrets)
for more information about the syntax.
@@ -80,7 +80,7 @@ To configure your Vault server:
1. Configure roles on your Vault server, restricting roles to a project or namespace,
as described in [Configure Vault server roles](#configure-vault-server-roles) on this page.
-1. [Create the following CI variables](../variables/README.md#custom-environment-variables)
+1. [Create the following CI/CD variables](../variables/README.md#custom-cicd-variables)
to provide details about your Vault server:
- `VAULT_SERVER_URL` - The URL of your Vault server, such as `https://vault.example.com:8200`.
Required.
@@ -113,8 +113,8 @@ In this example:
- `ops` - The path where the secrets engine is mounted.
After GitLab fetches the secret from Vault, the value is saved in a temporary file.
-The path to this file is stored in environment variable named `DATABASE_PASSWORD`,
-similar to [CI variables of type `file`](../variables/README.md#custom-environment-variables-of-type-file).
+The path to this file is stored in a CI/CD variable named `DATABASE_PASSWORD`,
+similar to [variables of type `file`](../variables/README.md#custom-cicd-variables-of-type-file).
For more information about the supported syntax, read the
[`.gitlab-ci.yml` reference](../yaml/README.md#secretsvault).
diff --git a/doc/ci/services/README.md b/doc/ci/services/README.md
index 71c2be70de3..c94d6e3ea80 100644
--- a/doc/ci/services/README.md
+++ b/doc/ci/services/README.md
@@ -1,21 +1,8 @@
---
-stage: Verify
-group: Runner
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-comments: false
-type: index
+redirect_to: 'index.md'
---
-# GitLab CI services examples
+This document was moved to [another location](index.md).
-The [`services`](../docker/using_docker_images.md#what-is-a-service)
-keyword defines a Docker image that runs during a `job` linked to the
-Docker image that the image keyword defines. This allows you to access
-the service image during build time.
-
-The service image can run any application, but the most common use
-case is to run a database container, for example:
-
-- [Using MySQL](mysql.md)
-- [Using PostgreSQL](postgres.md)
-- [Using Redis](redis.md)
+<!-- This redirect file can be deleted after 2021-05-01. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/services/docker-services.md b/doc/ci/services/docker-services.md
deleted file mode 100644
index e4653cdc9e2..00000000000
--- a/doc/ci/services/docker-services.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'README.md'
----
-
-This document was moved to [another location](README.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md
new file mode 100644
index 00000000000..71c2be70de3
--- /dev/null
+++ b/doc/ci/services/index.md
@@ -0,0 +1,21 @@
+---
+stage: Verify
+group: Runner
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+comments: false
+type: index
+---
+
+# GitLab CI services examples
+
+The [`services`](../docker/using_docker_images.md#what-is-a-service)
+keyword defines a Docker image that runs during a `job` linked to the
+Docker image that the image keyword defines. This allows you to access
+the service image during build time.
+
+The service image can run any application, but the most common use
+case is to run a database container, for example:
+
+- [Using MySQL](mysql.md)
+- [Using PostgreSQL](postgres.md)
+- [Using Redis](redis.md)
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index 1595907184e..5bd034cbf97 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -14,7 +14,7 @@ need it for your tests to run.
If you want to use a MySQL container, you can use [GitLab Runner](../runners/README.md) with the Docker executor.
-1. [Create variables](../variables/README.md#create-a-custom-variable-in-the-ui) for your
+1. [Create CI/CD variables](../variables/README.md#create-a-custom-variable-in-the-ui) for your
MySQL database and password by going to **Settings > CI/CD**, expanding **Variables**,
and clicking **Add Variable**.
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index d37875e1e05..16576069583 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -31,7 +31,7 @@ variables:
To set values for the `POSTGRES_DB`, `POSTGRES_USER`,
`POSTGRES_PASSWORD` and `POSTGRES_HOST_AUTH_METHOD`,
-[assign them to a variable in the user interface](../variables/README.md#create-a-custom-variable-in-the-ui),
+[assign them to a CI/CD variable in the user interface](../variables/README.md#create-a-custom-variable-in-the-ui),
then assign that variable to the corresponding variable in your
`.gitlab-ci.yml` file.
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index a5410d53a95..c94d6e3ea80 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -1,212 +1,8 @@
---
-stage: Verify
-group: Continuous Integration
-info: To 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
+redirect_to: 'index.md'
---
-# Using SSH keys with GitLab CI/CD
+This document was moved to [another location](index.md).
-GitLab currently doesn't have built-in support for managing SSH keys in a build
-environment (where the GitLab Runner runs).
-
-The SSH keys can be useful when:
-
-1. You want to checkout internal submodules
-1. You want to download private packages using your package manager (e.g., Bundler)
-1. You want to deploy your application to your own server, or, for example, Heroku
-1. You want to execute SSH commands from the build environment to a remote server
-1. You want to rsync files from the build environment to a remote server
-
-If anything of the above rings a bell, then you most likely need an SSH key.
-
-The most widely supported method is to inject an SSH key into your build
-environment by extending your `.gitlab-ci.yml`, and it's a solution which works
-with any type of [executor](https://docs.gitlab.com/runner/executors/)
-(Docker, shell, etc.).
-
-## How it works
-
-1. Create a new SSH key pair locally with [`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)
-1. Add the private key as a [variable](../variables/README.md) to
- your project
-1. Run the [`ssh-agent`](https://linux.die.net/man/1/ssh-agent) during job to load
- the private key.
-1. Copy the public key to the servers you want to have access to (usually in
- `~/.ssh/authorized_keys`) or add it as a [deploy key](../../ssh/README.md#deploy-keys)
- if you are accessing a private GitLab repository.
-
-The private key is displayed in the job log, unless you enable
-[debug logging](../variables/README.md#debug-logging). You might also want to
-check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
-
-## SSH keys when using the Docker executor
-
-When your CI/CD jobs run inside Docker containers (meaning the environment is
-contained) and you want to deploy your code in a private server, you need a way
-to access it. This is where an SSH key pair comes in handy.
-
-1. You first need to create an SSH key pair. For more information, follow
- the instructions to [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
- **Do not** add a passphrase to the SSH key, or the `before_script` will
- prompt for it.
-
-1. Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables).
- As **Key** enter the name `SSH_PRIVATE_KEY` and in the **Value** field paste
- the content of your _private_ key that you created earlier.
-
-1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following
- example, a Debian based image is assumed. Edit to your needs:
-
- ```yaml
- before_script:
- ##
- ## Install ssh-agent if not already installed, it is required by Docker.
- ## (change apt-get to yum if you use an RPM-based image)
- ##
- - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
-
- ##
- ## Run ssh-agent (inside the build environment)
- ##
- - eval $(ssh-agent -s)
-
- ##
- ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
- ## We're using tr to fix line endings which makes ed25519 keys work
- ## without extra base64 encoding.
- ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
- ##
- - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
-
- ##
- ## Create the SSH directory and give it the right permissions
- ##
- - mkdir -p ~/.ssh
- - chmod 700 ~/.ssh
-
- ##
- ## Optionally, if you will be using any Git commands, set the user name and
- ## and email.
- ##
- # - git config --global user.email "user@example.com"
- # - git config --global user.name "User name"
- ```
-
- The [`before_script`](../yaml/README.md#before_script) can be set globally
- or per-job.
-
-1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
-
-1. As a final step, add the _public_ key from the one you created in the first
- step to the services that you want to have an access to from within the build
- environment. If you are accessing a private GitLab repository you need to add
- it as a [deploy key](../../ssh/README.md#deploy-keys).
-
-That's it! You can now have access to private servers or repositories in your
-build environment.
-
-## SSH keys when using the Shell executor
-
-If you are using the Shell executor and not Docker, it is easier to set up an
-SSH key.
-
-You can generate the SSH key from the machine that GitLab Runner is installed
-on, and use that key for all projects that are run on this machine.
-
-1. First, log in to the server that runs your jobs.
-
-1. Then, from the terminal, log in as the `gitlab-runner` user:
-
- ```shell
- sudo su - gitlab-runner
- ```
-
-1. Generate the SSH key pair as described in the instructions to
- [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
- **Do not** add a passphrase to the SSH key, or the `before_script` will
- prompt for it.
-
-1. As a final step, add the _public_ key from the one you created earlier to the
- services that you want to have an access to from within the build environment.
- If you are accessing a private GitLab repository you need to add it as a
- [deploy key](../../ssh/README.md#deploy-keys).
-
-After generating the key, try to sign in to the remote server to accept the
-fingerprint:
-
-```shell
-ssh example.com
-```
-
-For accessing repositories on GitLab.com, you would use `git@gitlab.com`.
-
-## Verifying the SSH host keys
-
-It is a good practice to check the private server's own public key to make sure
-you are not being targeted by a man-in-the-middle attack. If anything
-suspicious happens, you notice it because the job fails (the SSH
-connection fails when the public keys don't match).
-
-To find out the host keys of your server, run the `ssh-keyscan` command from a
-trusted network (ideally, from the private server itself):
-
-```shell
-## Use the domain name
-ssh-keyscan example.com
-
-## Or use an IP
-ssh-keyscan 1.2.3.4
-```
-
-Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables) with
-`SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan`.
-
-If you need to connect to multiple servers, all the server host keys
-need to be collected in the **Value** of the variable, one key per line.
-
-NOTE:
-By using a variable instead of `ssh-keyscan` directly inside
-`.gitlab-ci.yml`, it has the benefit that you don't have to change `.gitlab-ci.yml`
-if the host domain name changes for some reason. Also, the values are predefined
-by you, meaning that if the host keys suddenly change, the CI/CD job doesn't fail,
-so there's something wrong with the server or the network.
-
-Now that the `SSH_KNOWN_HOSTS` variable is created, in addition to the
-[content of `.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)
-above, here's what more you need to add:
-
-```yaml
-before_script:
- ##
- ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
- ## following two lines.
- ##
- - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- - chmod 644 ~/.ssh/known_hosts
-
- ##
- ## Alternatively, use ssh-keyscan to scan the keys of your private server.
- ## Replace example.com with your private server's domain name. Repeat that
- ## command if you have more than one server to connect to.
- ##
- # - ssh-keyscan example.com >> ~/.ssh/known_hosts
- # - chmod 644 ~/.ssh/known_hosts
-
- ##
- ## You can optionally disable host key checking. Be aware that by adding that
- ## you are susceptible to man-in-the-middle attacks.
- ## WARNING: Use this only with the Docker executor, if you use it with shell
- ## you will overwrite your user's SSH config.
- ##
- # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'
-```
-
-## Example project
-
-We have set up an [Example SSH Project](https://gitlab.com/gitlab-examples/ssh-private-key/) for your convenience
-that runs on [GitLab.com](https://gitlab.com) using our publicly available
-[shared runners](../runners/README.md).
-
-Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes is picked by a public runner and the job starts.
+<!-- This redirect file can be deleted after 2021-05-01. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/ssh_keys/index.md b/doc/ci/ssh_keys/index.md
new file mode 100644
index 00000000000..2cdef176a22
--- /dev/null
+++ b/doc/ci/ssh_keys/index.md
@@ -0,0 +1,212 @@
+---
+stage: Verify
+group: Continuous Integration
+info: To 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
+---
+
+# Using SSH keys with GitLab CI/CD
+
+GitLab currently doesn't have built-in support for managing SSH keys in a build
+environment (where the GitLab Runner runs).
+
+The SSH keys can be useful when:
+
+1. You want to checkout internal submodules
+1. You want to download private packages using your package manager (e.g., Bundler)
+1. You want to deploy your application to your own server, or, for example, Heroku
+1. You want to execute SSH commands from the build environment to a remote server
+1. You want to rsync files from the build environment to a remote server
+
+If anything of the above rings a bell, then you most likely need an SSH key.
+
+The most widely supported method is to inject an SSH key into your build
+environment by extending your `.gitlab-ci.yml`, and it's a solution which works
+with any type of [executor](https://docs.gitlab.com/runner/executors/)
+(Docker, shell, etc.).
+
+## How it works
+
+1. Create a new SSH key pair locally with [`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)
+1. Add the private key as a [variable](../variables/README.md) to
+ your project
+1. Run the [`ssh-agent`](https://linux.die.net/man/1/ssh-agent) during job to load
+ the private key.
+1. Copy the public key to the servers you want to have access to (usually in
+ `~/.ssh/authorized_keys`) or add it as a [deploy key](../../ssh/README.md#deploy-keys)
+ if you are accessing a private GitLab repository.
+
+The private key is displayed in the job log, unless you enable
+[debug logging](../variables/README.md#debug-logging). You might also want to
+check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
+
+## SSH keys when using the Docker executor
+
+When your CI/CD jobs run inside Docker containers (meaning the environment is
+contained) and you want to deploy your code in a private server, you need a way
+to access it. This is where an SSH key pair comes in handy.
+
+1. You first need to create an SSH key pair. For more information, follow
+ the instructions to [generate an SSH key](../../ssh/README.md#generate-an-ssh-key-pair).
+ **Do not** add a passphrase to the SSH key, or the `before_script` will
+ prompt for it.
+
+1. Create a new [CI/CD variable](../variables/README.md).
+ As **Key** enter the name `SSH_PRIVATE_KEY` and in the **Value** field paste
+ the content of your _private_ key that you created earlier.
+
+1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following
+ example, a Debian based image is assumed. Edit to your needs:
+
+ ```yaml
+ before_script:
+ ##
+ ## Install ssh-agent if not already installed, it is required by Docker.
+ ## (change apt-get to yum if you use an RPM-based image)
+ ##
+ - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
+
+ ##
+ ## Run ssh-agent (inside the build environment)
+ ##
+ - eval $(ssh-agent -s)
+
+ ##
+ ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
+ ## We're using tr to fix line endings which makes ed25519 keys work
+ ## without extra base64 encoding.
+ ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
+ ##
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
+
+ ##
+ ## Create the SSH directory and give it the right permissions
+ ##
+ - mkdir -p ~/.ssh
+ - chmod 700 ~/.ssh
+
+ ##
+ ## Optionally, if you will be using any Git commands, set the user name and
+ ## and email.
+ ##
+ # - git config --global user.email "user@example.com"
+ # - git config --global user.name "User name"
+ ```
+
+ The [`before_script`](../yaml/README.md#before_script) can be set globally
+ or per-job.
+
+1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
+
+1. As a final step, add the _public_ key from the one you created in the first
+ step to the services that you want to have an access to from within the build
+ environment. If you are accessing a private GitLab repository you need to add
+ it as a [deploy key](../../ssh/README.md#deploy-keys).
+
+That's it! You can now have access to private servers or repositories in your
+build environment.
+
+## SSH keys when using the Shell executor
+
+If you are using the Shell executor and not Docker, it is easier to set up an
+SSH key.
+
+You can generate the SSH key from the machine that GitLab Runner is installed
+on, and use that key for all projects that are run on this machine.
+
+1. First, log in to the server that runs your jobs.
+
+1. Then, from the terminal, log in as the `gitlab-runner` user:
+
+ ```shell
+ sudo su - gitlab-runner
+ ```
+
+1. Generate the SSH key pair as described in the instructions to
+ [generate an SSH key](../../ssh/README.md#generate-an-ssh-key-pair).
+ **Do not** add a passphrase to the SSH key, or the `before_script` will
+ prompt for it.
+
+1. As a final step, add the _public_ key from the one you created earlier to the
+ services that you want to have an access to from within the build environment.
+ If you are accessing a private GitLab repository you need to add it as a
+ [deploy key](../../ssh/README.md#deploy-keys).
+
+After generating the key, try to sign in to the remote server to accept the
+fingerprint:
+
+```shell
+ssh example.com
+```
+
+For accessing repositories on GitLab.com, you would use `git@gitlab.com`.
+
+## Verifying the SSH host keys
+
+It is a good practice to check the private server's own public key to make sure
+you are not being targeted by a man-in-the-middle attack. If anything
+suspicious happens, you notice it because the job fails (the SSH
+connection fails when the public keys don't match).
+
+To find out the host keys of your server, run the `ssh-keyscan` command from a
+trusted network (ideally, from the private server itself):
+
+```shell
+## Use the domain name
+ssh-keyscan example.com
+
+## Or use an IP
+ssh-keyscan 1.2.3.4
+```
+
+Create a new [CI/CD variable](../variables/README.md) with
+`SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan`.
+
+If you need to connect to multiple servers, all the server host keys
+need to be collected in the **Value** of the variable, one key per line.
+
+NOTE:
+By using a variable instead of `ssh-keyscan` directly inside
+`.gitlab-ci.yml`, it has the benefit that you don't have to change `.gitlab-ci.yml`
+if the host domain name changes for some reason. Also, the values are predefined
+by you, meaning that if the host keys suddenly change, the CI/CD job doesn't fail,
+so there's something wrong with the server or the network.
+
+Now that the `SSH_KNOWN_HOSTS` variable is created, in addition to the
+[content of `.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)
+above, here's what more you need to add:
+
+```yaml
+before_script:
+ ##
+ ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
+ ## following two lines.
+ ##
+ - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
+ - chmod 644 ~/.ssh/known_hosts
+
+ ##
+ ## Alternatively, use ssh-keyscan to scan the keys of your private server.
+ ## Replace example.com with your private server's domain name. Repeat that
+ ## command if you have more than one server to connect to.
+ ##
+ # - ssh-keyscan example.com >> ~/.ssh/known_hosts
+ # - chmod 644 ~/.ssh/known_hosts
+
+ ##
+ ## You can optionally disable host key checking. Be aware that by adding that
+ ## you are susceptible to man-in-the-middle attacks.
+ ## WARNING: Use this only with the Docker executor, if you use it with shell
+ ## you will overwrite your user's SSH config.
+ ##
+ # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'
+```
+
+## Example project
+
+We have set up an [Example SSH Project](https://gitlab.com/gitlab-examples/ssh-private-key/) for your convenience
+that runs on [GitLab.com](https://gitlab.com) using our publicly available
+[shared runners](../runners/README.md).
+
+Want to hack on it? Simply fork it, commit and push your changes. Within a few
+moments the changes is picked by a public runner and the job starts.
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 2e7ec58f048..b4cea48a362 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: tutorial
---
-# Triggering pipelines through the API **(CORE)**
+# Triggering pipelines through the API **(FREE)**
Triggers can be used to force a pipeline rerun of a specific `ref` (branch or
tag) with an API call.
@@ -17,7 +17,7 @@ The following methods of authentication are supported:
- [Trigger token](#trigger-token)
- [CI job token](#ci-job-token)
-If using the `$CI_PIPELINE_SOURCE` [predefined environment variable](../variables/predefined_variables.md)
+If using the `$CI_PIPELINE_SOURCE` [predefined CI/CD variable](../variables/predefined_variables.md)
to limit which jobs run in a pipeline, the value could be either `pipeline` or `trigger`,
depending on which trigger method is used.
@@ -35,12 +35,12 @@ A unique trigger token can be obtained when [adding a new trigger](#adding-a-new
WARNING:
Passing plain text tokens in public projects is a security issue. Potential
attackers can impersonate the user that exposed their trigger token publicly in
-their `.gitlab-ci.yml` file. Use [variables](../variables/README.md#gitlab-cicd-environment-variables)
+their `.gitlab-ci.yml` file. Use [CI/CD variables](../variables/README.md)
to protect trigger tokens.
### CI job token
-You can use the `CI_JOB_TOKEN` [variable](../variables/README.md#predefined-environment-variables) (used to authenticate
+You can use the `CI_JOB_TOKEN` [CI/CD variable](../variables/README.md#predefined-cicd-variables) (used to authenticate
with the [GitLab Container Registry](../../user/packages/container_registry/index.md)) in the following cases.
#### When used with multi-project pipelines
@@ -53,7 +53,7 @@ and it creates a dependent pipeline relation visible on the
[pipeline graph](../multi_project_pipelines.md). For example:
```yaml
-build_docs:
+trigger_pipeline:
stage: deploy
script:
- curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
@@ -126,16 +126,14 @@ branches or tags. The `:id` of a project can be found by
[querying the API](../../api/projects.md) or by visiting the **CI/CD**
settings page which provides self-explanatory examples.
-When a rerun of a pipeline is triggered, the information is exposed in the GitLab
-UI under the **Jobs** page and the jobs are marked as triggered 'by API'.
+When a rerun of a pipeline is triggered, jobs are marked as triggered `by API` in
+**CI/CD > Jobs**.
-![Marked rebuilds as on jobs page](img/builds_page.png)
-
-You can see which trigger caused the rebuild by visiting the single job page.
+You can see which trigger caused a job to run by visiting the single job page.
A part of the trigger's token is exposed in the UI as you can see from the image
below.
-![Marked rebuilds as triggered on a single job page](img/trigger_single_build.png)
+![Marked as triggered on a single job page](img/trigger_single_job.png)
By using cURL you can trigger a pipeline rerun with minimal effort, for example:
@@ -146,7 +144,7 @@ curl --request POST \
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
```
-In this case, the project with ID `9` gets rebuilt on `master` branch.
+In this case, the pipeline for the project with ID `9` runs on the `master` branch.
Alternatively, you can pass the `token` and `ref` arguments in the query string:
@@ -156,12 +154,12 @@ curl --request POST \
```
You can also benefit by using triggers in your `.gitlab-ci.yml`. Let's say that
-you have two projects, A and B, and you want to trigger a rebuild on the `master`
+you have two projects, A and B, and you want to trigger a pipeline on the `master`
branch of project B whenever a tag on project A is created. This is the job you
need to add in project A's `.gitlab-ci.yml`:
```yaml
-build_docs:
+trigger_pipeline:
stage: deploy
script:
- 'curl --request POST --form token=TOKEN --form ref=master "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"'
@@ -170,7 +168,7 @@ build_docs:
```
This means that whenever a new tag is pushed on project A, the job runs and the
-`build_docs` job is executed, triggering a rebuild of project B. The
+`trigger_pipeline` job is executed, triggering the pipeline for project B. The
`stage: deploy` ensures that this job runs only after all jobs with
`stage: test` complete successfully.
@@ -187,6 +185,41 @@ You should pass `ref` as part of the URL, to take precedence over `ref` from
the webhook body that designates the branch ref that fired the trigger in the
source repository. Be sure to URL-encode `ref` if it contains slashes.
+### Using webhook payload in the triggered pipeline
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31197) in GitLab 13.9.
+> - 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-trigger_payload-variable). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+If you trigger a pipeline by using a webhook, you can access the webhook payload with
+the `TRIGGER_PAYLOAD` [predefined CI/CD variable](../variables/predefined_variables.md).
+The payload is exposed as a [file-type variable](../variables/README.md#custom-cicd-variables-of-type-file),
+so you can access the data with `cat $TRIGGER_PAYLOAD` or a similar command.
+
+#### Enable or disable the `TRIGGER_PAYLOAD` variable
+
+The `TRIGGER_PAYLOAD` CI/CD variable 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(:ci_trigger_payload_into_pipeline)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_trigger_payload_into_pipeline)
+```
+
## Making use of trigger variables
You can pass any number of arbitrary variables in the trigger API call and they
@@ -204,7 +237,7 @@ This information is also exposed in the UI. Please note that _values_ are only v
Using trigger variables can be proven useful for a variety of reasons:
- Identifiable jobs. Since the variable is exposed in the UI you can know
- why the rebuild was triggered if you pass a variable that explains the
+ why the pipeline was triggered if you pass a variable that explains the
purpose.
- Conditional job processing. You can have conditional jobs that run whenever
a certain variable is present.
@@ -236,7 +269,7 @@ upload_package:
- if [ -n "${UPLOAD_TO_S3}" ]; then make upload; fi
```
-You can then trigger a rebuild while you pass the `UPLOAD_TO_S3` variable
+You can then trigger a pipeline while you pass the `UPLOAD_TO_S3` variable
and the script of the `upload_package` job is run:
```shell
@@ -247,7 +280,7 @@ curl --request POST \
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
```
-Trigger variables have the [highest priority](../variables/README.md#priority-of-environment-variables)
+Trigger variables have the [highest priority](../variables/README.md#priority-of-cicd-variables)
of all types of variables.
## Using cron to trigger nightly pipelines
diff --git a/doc/ci/triggers/img/builds_page.png b/doc/ci/triggers/img/builds_page.png
deleted file mode 100644
index 14d73b140f4..00000000000
--- a/doc/ci/triggers/img/builds_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/triggers/img/trigger_single_build.png b/doc/ci/triggers/img/trigger_single_job.png
index b760782afdc..b760782afdc 100644
--- a/doc/ci/triggers/img/trigger_single_build.png
+++ b/doc/ci/triggers/img/trigger_single_job.png
Binary files differ
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 9cda1f14b01..cddcf76236a 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -222,6 +222,29 @@ 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
+
+This message is shown if the [merge request pipeline](merge_request_pipelines/index.md),
+[merged results pipeline](merge_request_pipelines/pipelines_for_merged_results/index.md),
+or [merge train pipeline](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md)
+has failed or been canceled.
+
+If a merge request pipeline or merged result pipeline was canceled or failed, you can:
+
+- Re-run the entire pipeline by clicking **Run pipeline** in the pipeline tab in the merge request.
+- [Retry only the jobs that failed](pipelines/index.md#view-pipelines). If you re-run the entire pipeline, this is not necessary.
+- Push a new commit to fix the failure.
+
+If the merge train pipeline has failed, you can:
+
+- Check the failure and determine if you can use the [`/merge` quick action](../user/project/quick_actions.md) to immediately add the merge request to the train again.
+- Re-run the entire pipeline by clicking **Run pipeline** in the pipeline tab in the merge request, then add the merge request to the train again.
+- Push a commit to fix the failure, then add the merge request to the train again.
+
+If the merge train pipeline was canceled before the merge request was merged, without a failure, you can:
+
+- Add it to the train again.
+
## Pipeline warnings
Pipeline configuration warnings are shown when you:
@@ -239,6 +262,23 @@ To [prevent duplicate pipelines](yaml/README.md#prevent-duplicate-pipelines), us
[`workflow: rules`](yaml/README.md#workflowrules) or rewrite your rules to control
which pipelines can run.
+### Console workaround if job using resource_group gets stuck
+
+```ruby
+# find resource group by name
+resource_group = Project.find_by_full_path('...').resource_groups.find_by(key: 'the-group-name')
+busy_resources = resource_group.resources.where('build_id IS NOT NULL')
+
+# identify which builds are occupying the resource
+# (I think it should be 1 as of today)
+busy_resources.pluck(:build_id)
+
+# it's good to check why this build is holding the resource.
+# Is it stuck? Has it been forcefully dropped by the system?
+# free up busy resources
+busy_resources.update_all(build_id: nil)
+```
+
## How to get help
If you are unable to resolve pipeline issues, you can get help from:
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index 1fec1f77bc3..ee060f33d01 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -67,8 +67,9 @@ execution time and the error output.
### Number of recent failures
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in GitLab 13.7.
+> - [Introduced in Merge Requests](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in GitLab 13.7.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268249) in GitLab 13.8.
+> - [Introduced in Test Reports](https://gitlab.com/gitlab-org/gitlab/-/issues/235525) in GitLab 13.9.
If a test failed in the project's default branch in the last 14 days, a message like
`Failed {n} time(s) in {default_branch} in the last 14 days` is displayed for that test.
@@ -290,6 +291,22 @@ javascript:
- junit.xml
```
+### Flutter / Dart example
+
+This example `.gitlab-ci.yml` file uses the [JUnit Report](https://pub.dev/packages/junitreport) package to convert the `flutter test` output into JUnit report XML format:
+
+```yaml
+test:
+ stage: test
+ script:
+ - flutter test --machine | tojunit -o report.xml
+ artifacts:
+ when: always
+ reports:
+ junit:
+ - report.xml
+```
+
## Viewing Unit test reports on GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default.
@@ -310,7 +327,12 @@ You can also retrieve the reports via the [GitLab API](../api/pipelines.md#get-a
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0.
> - It's deployed behind a feature flag, disabled by default.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-junit-screenshots-feature). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-junit-screenshots-feature). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+When [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/6061) is complete, the attached file will be visible on the pipeline details page.
If JUnit report format XML files contain an `attachment` tag, GitLab parses the attachment.
@@ -322,9 +344,7 @@ Upload your screenshots as [artifacts](pipelines/job_artifacts.md#artifactsrepor
</testcase>
```
-When [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/6061) is complete, the attached file will be visible on the pipeline details page.
-
-### Enabling the JUnit screenshots feature **(CORE ONLY)**
+### Enabling the JUnit screenshots feature **(FREE SELF)**
This feature comes with the `:junit_pipeline_screenshots_view` feature flag disabled by default.
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 5fca8e8c2b7..b6228e26175 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -5,20 +5,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab CI/CD environment variables
+# GitLab CI/CD variables
-An environment variable is a dynamically-named value that can
-affect the way running processes behave on an operating
-system.
+CI/CD variables are part of the environment in which [pipelines](../pipelines/index.md)
+and jobs run. For example, you could:
-Environment variables are part of the environment in which a process runs.
-For example, a running process could:
-
-- Use the value of a `TEMP` environment variable to know the correct location
- to store temporary files.
+- Use the value of a `TEMP` variable to know the correct location to store temporary files.
- Use a `DATABASE_URL` variable for the URL to a database that can be reused in different scripts.
-Variables are useful for customizing your jobs in GitLab CI/CD.
+Variables can be used to customize your jobs in [GitLab CI/CD](../README.md).
When you use variables, you don't have to hard-code values.
> For more information about advanced use of GitLab CI/CD:
@@ -28,28 +23,27 @@ When you use variables, you don't have to hard-code values.
> - <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>&nbsp;Learn how the Cloud Native Computing Foundation (CNCF) [eliminates the complexity](https://about.gitlab.com/customers/cncf/)
> of managing projects across many cloud providers with GitLab CI/CD.
-## Predefined environment variables
+## Predefined CI/CD variables
-GitLab CI/CD has a [default set of predefined variables](predefined_variables.md)
+GitLab CI/CD has a [default set of predefined CI/CD variables](predefined_variables.md)
that you can use without any additional specification.
You can call issue numbers, user names, branch names,
pipeline and commit IDs, and much more.
-Predefined environment variables are provided by GitLab
-for the local environment of the runner.
+Predefined variables are provided by GitLab for the local environment of the runner.
GitLab reads the `.gitlab-ci.yml` file and sends the information
to the runner, where the variables are exposed. The runner then runs the script commands.
-### Use predefined environment variables
+### Use predefined CI/CD variables
-You can choose one of the existing predefined variables
+You can choose one of the existing predefined CI/CD variables
to be output by the runner.
This example shows how to output a job's stage by using the predefined variable `CI_JOB_STAGE`.
In your `.gitlab-ci.yml` file, call the variable from your script. Ensure
-you use the correct [syntax](#syntax-of-environment-variables-in-job-scripts).
+you use the correct [syntax](#syntax-of-cicd-variables-in-job-scripts).
```yaml
test_variable:
@@ -63,14 +57,15 @@ job `test_variable`, which is `test`:
![Output `$CI_JOB_STAGE`](img/ci_job_stage_output_example.png)
-## Custom environment variables
+## Custom CI/CD variables
-When you need a specific custom environment variable, you can
+When you need a specific custom variable, you can
[set it up in the UI](#create-a-custom-variable-in-the-ui), in [the API](../../api/project_level_variables.md),
or directly [in the `.gitlab-ci.yml` file](#create-a-custom-variable-in-gitlab-ciyml).
The variables are used by the runner any time the pipeline runs.
-You can also [override variable values manually for a specific pipeline](../jobs/index.md#specifying-variables-when-running-manual-jobs).
+You can also [override variable values manually for a specific pipeline](../jobs/index.md#specifying-variables-when-running-manual-jobs),
+or have them [prefilled in manual pipelines](../pipelines/index.md#prefill-variables-in-manual-pipelines).
There are two types of variables: **Variable** and **File**. You cannot set types in
the `.gitlab-ci.yml` file, but you can set them in the UI and API.
@@ -96,7 +91,7 @@ For more details, see [`.gitlab-ci.yml` defined variables](#gitlab-ciyml-defined
### Create a custom variable in the UI
-From within the UI, you can add or update custom environment variables:
+From the UI, you can add or update custom variables:
1. Go to your project's **Settings > CI/CD** and expand the **Variables** section.
1. Click the **Add Variable** button. In the **Add variable** modal, fill in the details:
@@ -104,7 +99,7 @@ From within the UI, you can add or update custom environment variables:
- **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`.
- **Value**: No limitations.
- **Type**: `File` or `Variable`.
- - **Environment scope**: `All`, or specific environments.
+ - **Environment scope**: `All`, or specific [environments](../environments/index.md).
- **Protect variable** (Optional): If selected, the variable is only available in pipelines that run on protected branches or tags.
- **Mask variable** (Optional): If selected, the variable's **Value** is masked in job logs. The variable fails to save if the value does not meet the [masking requirements](#masked-variable-requirements).
@@ -145,7 +140,7 @@ build:
- curl --request POST --data "secret_variable=$SECRET_VARIABLE" "https://maliciouswebsite.abcd/"
```
-### Custom environment variables of type Variable
+### Custom CI/CD variables of type Variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) in GitLab 11.11.
@@ -155,7 +150,7 @@ that uses the key for the name and the value for the value.
There are [some predefined variables](#custom-variables-validated-by-gitlab) of this type,
which may be further validated. They appear when you add or update a variable in the UI.
-### Custom environment variables of type File
+### Custom CI/CD variables of type File
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) in GitLab 11.11.
@@ -207,10 +202,11 @@ The value of the variable must:
- Be in a single line.
- Be at least 8 characters long.
-- Not be a predefined or custom environment variable.
-- Consist only of characters from the Base64 alphabet (RFC4648).
- [In GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63043)
- and newer, `@` and `:` are also valid values.
+- Not be a predefined or custom CI/CD variable.
+- Consist only of:
+ - Characters from the Base64 alphabet (RFC4648).
+ - The `@` and `:` characters ([In GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/63043) and later).
+ - The `.` character ([In GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29022) and later).
You can't mask variables that don't meet these requirements.
@@ -247,7 +243,7 @@ WARNING:
When you store credentials, there are security implications. If you are using AWS keys,
for example, follow their [best practices](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html).
-## Syntax of environment variables in job scripts
+## Syntax of CI/CD variables in job scripts
All variables are set as environment variables in the build environment, and
they are accessible with normal methods that are used to access such variables.
@@ -263,7 +259,7 @@ To access environment variables, use the syntax for your runner's [shell](https:
### Bash
-To access environment variables in **bash**, prefix the variable name with (`$`):
+To access environment variables in **bash**, prefix the CI/CD variable name with (`$`):
```yaml
job_name:
@@ -274,8 +270,8 @@ job_name:
### PowerShell
To access variables in a **Windows PowerShell** environment, including system set
-environment variables, prefix the variable name with (`$env:`). Environment variables
-set by GitLab CI can also be accessed by prefixing the variable name with (`$`) with
+environment variables, prefix the variable name with (`$env:`). GitLab CI/CD variables
+can also be accessed by prefixing the variable name with (`$`) with
[GitLab Runner 1.0.0](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/68)
and later.
@@ -371,9 +367,8 @@ export GITLAB_USER_ID="42"
## `.gitlab-ci.yml` defined variables
-You can add variables that are set in the build environment to `.gitlab-ci.yml`.
-These variables are saved in the repository, and they
-are meant to store non-sensitive project configuration, like `RAILS_ENV` or
+You can add CI/CD variables to `.gitlab-ci.yml`. These variables are saved in the repository,
+and they are meant to store non-sensitive project configuration, like `RAILS_ENV` or
`DATABASE_URL`.
For example, if you set the variable below globally (not inside a job), it is
@@ -406,13 +401,20 @@ script:
- 'eval $LS_CMD' # will execute 'ls -al $TMP_DIR'
```
-## Group-level environment variables
+Use the [`value` and `description`](../yaml/README.md#prefill-variables-in-manual-pipelines)
+keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
+when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually):
+
+## Group-level CI/CD variables
> Introduced in GitLab 9.4.
-You can define per-project or per-group variables that are set in the pipeline environment. Group-level variables are stored out of the repository (not in `.gitlab-ci.yml`). They are securely passed to GitLab Runner, which makes them available during a pipeline run.
+You can define per-project or per-group variables that are set in the pipeline environment.
+Group-level variables are stored out of the repository (not in `.gitlab-ci.yml`).
+They are securely passed to GitLab Runner, which makes them available during a pipeline run.
-We recommend using group environment variables to store secrets (like passwords, SSH keys, and credentials) for Premium users who:
+We recommend using group variables to store secrets (like passwords, SSH keys, and
+credentials) for users who:
- Do **not** use an external key store.
- Use the GitLab [integration with HashiCorp Vault](../secrets/index.md).
@@ -430,7 +432,7 @@ After you set them, they are available for all subsequent pipelines. Any group-l
![CI/CD settings - inherited variables](img/inherited_group_variables_v12_5.png)
-## Instance-level CI/CD environment variables
+## Instance-level CI/CD variables
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) in GitLab 13.0.
@@ -471,12 +473,12 @@ To enable it:
Feature.enable(:instance_variables_ui)
```
-## Inherit environment variables
+## Inherit CI/CD variables
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22638) in GitLab 13.0 behind a disabled [feature flag](../../administration/feature_flags.md): `ci_dependency_variables`.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) in GitLab 13.1.
-You can inherit environment variables from dependent jobs.
+You can inherit CI/CD variables from dependent jobs.
This feature makes use of the [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) report feature.
@@ -519,7 +521,7 @@ deploy:
artifacts: true
```
-## Priority of environment variables
+## Priority of CI/CD variables
Variables of different types can take precedence over other
variables, depending on where they are defined.
@@ -528,14 +530,14 @@ The order of precedence for variables is (from highest to lowest):
1. [Trigger variables](../triggers/README.md#making-use-of-trigger-variables), [scheduled pipeline variables](../pipelines/schedules.md#using-variables),
and [manual pipeline run variables](#override-a-variable-by-manually-running-a-pipeline).
-1. Project-level [variables](#custom-environment-variables) or [protected variables](#protect-a-custom-variable).
-1. Group-level [variables](#group-level-environment-variables) or [protected variables](#protect-a-custom-variable).
-1. Instance-level [variables](#instance-level-cicd-environment-variables) or [protected variables](#protect-a-custom-variable).
-1. [Inherited environment variables](#inherit-environment-variables).
+1. Project-level [variables](#custom-cicd-variables) or [protected variables](#protect-a-custom-variable).
+1. Group-level [variables](#group-level-cicd-variables) or [protected variables](#protect-a-custom-variable).
+1. Instance-level [variables](#instance-level-cicd-variables) or [protected variables](#protect-a-custom-variable).
+1. [Inherited CI/CD variables](#inherit-cicd-variables).
1. YAML-defined [job-level variables](../yaml/README.md#variables).
1. YAML-defined [global variables](../yaml/README.md#variables).
-1. [Deployment variables](#deployment-environment-variables).
-1. [Predefined environment variables](predefined_variables.md).
+1. [Deployment variables](#deployment-variables).
+1. [Predefined CI/CD variables](predefined_variables.md).
For example, if you define:
@@ -549,7 +551,7 @@ variables take precedence over those defined in `.gitlab-ci.yml`.
Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html).
Each shell has its own unique set of reserved variable names.
-Keep in mind the [scope of environment variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope in which you wish to use it.
+Keep in mind the [scope of CI/CD variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope in which you wish to use it.
## Where variables can be used
@@ -557,14 +559,14 @@ Keep in mind the [scope of environment variables](where_variables_can_be_used.md
## Advanced use
-### Limit the environment scopes of environment variables
+### Limit the environment scopes of CI/CD variables
You can limit the environment scope of a variable by
[defining which environments](../environments/index.md) it can be available for.
To learn more about scoping environments, see [Scoping environments with specs](../environments/index.md#scoping-environments-with-specs).
-### Deployment environment variables
+### Deployment variables
> Introduced in GitLab 8.15.
@@ -582,11 +584,10 @@ An example integration that defines deployment variables is the
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) in GitLab 11.7.
You can configure [Auto DevOps](../../topics/autodevops/index.md) to
-pass CI variables to the running application by prefixing the key of the
+pass CI/CD variables to the running application by prefixing the key of the
variable with `K8S_SECRET_`.
-These [prefixed
-variables](../../topics/autodevops/customize.md#application-secret-variables) are
+These [prefixed variables](../../topics/autodevops/customize.md#application-secret-variables) are
then available as environment variables on the running application
container.
@@ -603,9 +604,9 @@ You can override the value of a variable when:
1. Manually playing a job via the UI.
1. Using [push options](../../user/project/push_options.md#push-options-for-gitlab-cicd).
1. Manually triggering pipelines with [the API](../triggers/README.md#making-use-of-trigger-variables).
-1. Passing variables to a [downstream pipeline](../multi_project_pipelines.md#passing-variables-to-a-downstream-pipeline).
+1. Passing variables to a [downstream pipeline](../multi_project_pipelines.md#passing-cicd-variables-to-a-downstream-pipeline).
-These pipeline variables declared in these events take [priority over other variables](#priority-of-environment-variables).
+These pipeline variables declared in these events take [priority over other variables](#priority-of-cicd-variables).
#### Restrict who can override variables
@@ -618,7 +619,7 @@ variables, an `Insufficient permissions to set pipeline variables` error occurs.
The setting is `disabled` by default.
-If you [store your CI configurations in a different repository](../../ci/pipelines/settings.md#custom-ci-configuration-path),
+If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-path),
use this setting for strict control over all aspects of the environment
the pipeline runs in.
@@ -642,7 +643,7 @@ value for this specific pipeline.
![Manually overridden variable output](img/override_value_via_manual_pipeline_output.png)
-## Environment variables expressions
+## CI/CD variable expressions
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37397) in GitLab 10.7 for [the `only` and `except` CI keywords](../yaml/README.md#onlyexcept-advanced)
> - [Expanded](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3 with [the `rules` keyword](../yaml/README.md#rules)
@@ -676,7 +677,7 @@ when `except` is being used, a job is not created.
This follows the usual rules for [`only` / `except` policies](../yaml/README.md#onlyexcept-advanced).
-### Syntax of environment variable expressions
+### Syntax of CI/CD variable expressions
Below you can find supported syntax reference.
@@ -777,7 +778,7 @@ so `&&` is evaluated before `||`.
> - It's deployed behind a feature flag, enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables). **(FREE SELF)**
It is possible to use parentheses to group conditions. Parentheses have the highest
precedence of all operators. Expressions enclosed in parentheses are evaluated first,
@@ -793,7 +794,7 @@ Examples:
- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3`
- `$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)`
-##### Enable or disable parenthesis support for variables **(CORE ONLY)**
+##### Enable or disable parenthesis support for variables **(FREE SELF)**
The feature is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
@@ -1076,7 +1077,7 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
## Video walkthrough of a working example
-The [Managing the Complex Configuration Data Management Monster Using GitLab](https://www.youtube.com/watch?v=v4ZOJ96hAck) video is a walkthrough of the [Complex Config Data Monorepo](https://gitlab.com/guided-explorations/config-data-top-scope/config-data-subscope/config-data-monorepo) working example project. It explains how multiple levels of group CI/CD variables can be combined with environment-scoped project variables for complex configuration of application builds or deployments.
+The [Managing the Complex Configuration Data Management Monster Using GitLab](https://www.youtube.com/watch?v=v4ZOJ96hAck) video is a walkthrough of the [Complex Configuration Data Monorepo](https://gitlab.com/guided-explorations/config-data-top-scope/config-data-subscope/config-data-monorepo) working example project. It explains how multiple levels of group CI/CD variables can be combined with environment-scoped project variables for complex configuration of application builds or deployments.
The example can be copied to your own group or instance for testing. More details
on what other GitLab CI patterns are demonstrated are available at the project page.
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 701fe33b53f..8d2df82a212 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -5,25 +5,25 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Predefined environment variables reference
+# Predefined variables reference
For an introduction on this subject, read through the
-[getting started with environment variables](README.md) document.
+[CI/CD variables](README.md) document.
-Some of the predefined environment variables are available only if a minimum
+Some of the predefined variables are available only if a minimum
version of [GitLab Runner](https://docs.gitlab.com/runner/) is used. Consult the table below to find the
version of GitLab Runner that's required.
You can add a command to your `.gitlab-ci.yml` file to
[output the values of all variables available for a job](README.md#list-all-environment-variables).
-Kubernetes-specific environment variables are detailed in the
+Kubernetes-specific variables are detailed in the
[Kubernetes deployment variables](../../user/project/clusters/index.md#deployment-variables) section.
| Variable | GitLab | Runner | Description |
|-----------------------------------------------|--------|--------|-------------|
-| `CHAT_CHANNEL` | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/README.md) command. |
-| `CHAT_INPUT` | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/README.md) command. |
+| `CHAT_CHANNEL` | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/index.md) command. |
+| `CHAT_INPUT` | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/index.md) command. |
| `CI` | all | 0.4 | Mark that job is executed in CI environment. |
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
| `CI_BUILDS_DIR` | all | 11.10 | Top-level directory where builds are executed. |
@@ -145,3 +145,4 @@ Kubernetes-specific environment variables are detailed in the
| `GITLAB_USER_ID` | 8.12 | all | The ID of the user who started the job. |
| `GITLAB_USER_LOGIN` | 10.0 | all | The login username of the user who started the job. |
| `GITLAB_USER_NAME` | 10.0 | all | The real name of the user who started the job. |
+| `TRIGGER_PAYLOAD` | 13.9 | all | This variable is available when a pipeline is [triggered with a webhook](../triggers/README.md#using-webhook-payload-in-the-triggered-pipeline) |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index e84714f2a46..d057fe9c4cc 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -124,7 +124,7 @@ They are:
- Script execution shell.
- Not supported:
- For definitions where the ["Expansion place"](#gitlab-ciyml-file) is GitLab.
- - In the `only` and `except` [variables expressions](README.md#environment-variables-expressions).
+ - In the `only` and `except` [variables expressions](README.md#cicd-variable-expressions).
Some of the persisted variables contain tokens and cannot be used by some definitions
due to security reasons.
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 19b8f0f1c89..2abfbd3a5b4 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -5,11 +5,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab CI/CD pipeline configuration reference
+<!-- markdownlint-disable MD044 -->
+<!-- vale gitlab.Spelling = NO -->
+# Keyword reference for the .gitlab-ci.yml file
+<!-- vale gitlab.Spelling = YES -->
+<!-- markdownlint-enable MD044 -->
This document lists the configuration options for your GitLab `.gitlab-ci.yml` file.
-- For a quick introduction to GitLab CI/CD, follow the [quick start guide](../quick_start/README.md).
+- For a quick introduction to GitLab CI/CD, follow the [quick start guide](../quick_start/index.md).
- For a collection of examples, see [GitLab CI/CD Examples](../examples/README.md).
- To view a large `.gitlab-ci.yml` file used in an enterprise, see the [`.gitlab-ci.yml` file for `gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
@@ -26,7 +30,7 @@ The keywords available for jobs are:
|:---------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`script`](#script) | Shell script that is executed by a runner. |
| [`after_script`](#after_script) | Override a set of commands that are executed after job. |
-| [`allow_failure`](#allow_failure) | Allow job to fail. A failed job does not cause the pipeline to fail. |
+| [`allow_failure`](#allow_failure) | Allow job to fail. A failed job does not cause the pipeline to fail. |
| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:exclude`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, and `artifacts:reports`. |
| [`before_script`](#before_script) | Override a set of commands that are executed before job. |
| [`cache`](#cache) | List of files that should be cached between subsequent runs. Also available: `cache:paths`, `cache:key`, `cache:untracked`, `cache:when`, and `cache:policy`. |
@@ -44,7 +48,7 @@ The keywords available for jobs are:
| [`release`](#release) | Instructs the runner to generate a [Release](../../user/project/releases/index.md) object. |
| [`resource_group`](#resource_group) | Limit job concurrency. |
| [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
-| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it's created. May not be used alongside `only`/`except`. |
+| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it's created. |
| [`services`](#services) | Use Docker services images. Also available: `services:name`, `services:alias`, `services:entrypoint`, and `services:command`. |
| [`stage`](#stage) | Defines a job stage (default: `test`). |
| [`tags`](#tags) | List of tags that are used to select a runner. |
@@ -55,8 +59,8 @@ The keywords available for jobs are:
### Unavailable names for jobs
-Each job must have a unique name, but there are a few **reserved `keywords` that
-can't be used as job names**:
+Each job must have a unique name, but there are a few reserved `keywords` that
+can't be used as job names:
- `image`
- `services`
@@ -70,7 +74,7 @@ can't be used as job names**:
### Reserved keywords
-If you get a validation error when using specific values (for example, `true` or `false`), try to:
+If you get a validation error when you use specific values (for example, `true` or `false`), try to:
- Quote them.
- Change them to a different form. For example, `/bin/true`.
@@ -223,7 +227,7 @@ stages:
If any job fails, the pipeline is marked as `failed` and jobs in later stages do not
start. Jobs in the current stage are not stopped and continue to run.
-If no `stages` are defined in `.gitlab-ci.yml`, then `build`, `test` and `deploy`
+If no `stages` are defined in the `.gitlab-ci.yml` file, then `build`, `test` and `deploy`
are the default pipeline stages.
If a job does not specify a [`stage`](#stage), the job is assigned the `test` stage.
@@ -339,10 +343,10 @@ include:
> - Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.5.
> - Available for Starter, Premium, and Ultimate in GitLab 10.6 and later.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/42861) to GitLab Core in 11.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/42861) to GitLab Free in 11.4.
Use the `include` keyword to include external YAML files in your CI/CD configuration.
-You can break down one long `gitlab-ci.yml` into multiple files to increase readability,
+You can break down one long `gitlab-ci.yml` file into multiple files to increase readability,
or reduce duplication of the same configuration in multiple places.
You can also store template files in a central repository and `include` them in projects.
@@ -363,33 +367,27 @@ use the [`extends` keyword](#extends).
| [`remote`](#includeremote) | Include a file from a remote URL. Must be publicly accessible. |
| [`template`](#includetemplate) | Include templates that are provided by GitLab. |
-`.gitlab-ci.yml` configuration included by all methods is evaluated at pipeline creation.
+The `.gitlab-ci.yml` file configuration included by all methods is evaluated when the pipeline is created.
The configuration is a snapshot in time and persisted in the database. Any changes to
-referenced `.gitlab-ci.yml` configuration is not reflected in GitLab until the next pipeline is created.
+the referenced `.gitlab-ci.yml` file configuration is not reflected in GitLab until the next pipeline is created.
The files defined by `include` are:
-- Deep merged with those in `.gitlab-ci.yml`.
-- Always evaluated first and merged with the content of `.gitlab-ci.yml`,
+- Deep merged with those in the `.gitlab-ci.yml` file.
+- Always evaluated first and merged with the content of the `.gitlab-ci.yml` file,
regardless of the position of the `include` keyword.
NOTE:
Use merging to customize and override included CI/CD configurations with local
-definitions. Local definitions in `.gitlab-ci.yml` override included definitions.
+configurations. Local configurations in the `.gitlab-ci.yml` file override included configurations.
-#### Variables with `include`
+#### Variables with `include` **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/284883) in GitLab 13.8.
-> - 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-includepredefined-project-variables). **(CORE ONLY)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/294294) in GitLab 13.9.
You can [use some predefined variables in `include` sections](../variables/where_variables_can_be_used.md#gitlab-ciyml-file)
-in your `.gitlab-ci.yml`:
+in your `.gitlab-ci.yml` file:
```yaml
include:
@@ -398,35 +396,15 @@ include:
```
For an example of how you can include these predefined variables, and their impact on CI jobs,
-see the following [CI variable demo](https://youtu.be/4XR8gw3Pkos).
-
-##### Enable or disable include:predefined-project-variables **(CORE ONLY)**
-
-Use of predefined project variables in `include` section of `.gitlab-ci.yml` 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(:variables_in_include_section_ci)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:variables_in_include_section_ci)
-```
+see the following [CI/CD variable demo](https://youtu.be/4XR8gw3Pkos).
#### `include:local`
-`include:local` includes a file from the same repository as `.gitlab-ci.yml`.
+`include:local` includes a file that is in the same repository as the `.gitlab-ci.yml` file.
It's referenced with full paths relative to the root directory (`/`).
-You can only use files that are tracked by Git on the same branch
-your configuration file is on. If you `include:local`, make
-sure that both `.gitlab-ci.yml` and the local file are on the same branch.
+If you use `include:local`, make sure that both the `.gitlab-ci.yml` file and the local file
+are on the same branch.
You can't include local files through Git submodules paths.
@@ -440,14 +418,14 @@ include:
- local: '/templates/.gitlab-ci-template.yml'
```
-Local includes can be used as a replacement for symbolic links that are not followed.
-
This can be defined as a short local include:
```yaml
include: '.gitlab-ci-production.yml'
```
+Use local includes instead of symbolic links.
+
#### `include:file`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) in GitLab 11.7.
@@ -501,24 +479,23 @@ include:
#### `include:remote`
-`include:remote` can be used to include a file from a different location,
-using HTTP/HTTPS, referenced by the full URL. The remote file must be
-publicly accessible by a GET request, because authentication schemas
-in the remote URL are not supported. For example:
+Use `include:remote` with a full URL to include a file from a different location.
+The remote file must be publicly accessible by an HTTP/HTTPS `GET` request, because
+authentication in the remote URL is not supported. For example:
```yaml
include:
- - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml'
+ - remote: 'https://gitlab.com/example-project/-/raw/master/.gitlab-ci.yml'
```
-All [nested includes](#nested-includes) are executed without context as a public user,
+All [nested includes](#nested-includes) execute without context as a public user,
so you can only `include` public projects or templates.
#### `include:template`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53445) in GitLab 11.7.
-`include:template` can be used to include `.gitlab-ci.yml` templates that are
+Use `include:template` to include `.gitlab-ci.yml` templates that are
[shipped with GitLab](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates).
For example:
@@ -566,7 +543,7 @@ Used to specify [a Docker image](../docker/using_docker_images.md#what-is-an-ima
For:
- Usage examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
-- Detailed usage information, refer to [Docker integration](../docker/README.md) documentation.
+- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
#### `image:name`
@@ -587,8 +564,8 @@ Used to specify a [service Docker image](../docker/using_docker_images.md#what-i
For:
- Usage examples, see [Define `image` and `services` from `.gitlab-ci.yml`](../docker/using_docker_images.md#define-image-and-services-from-gitlab-ciyml).
-- Detailed usage information, refer to [Docker integration](../docker/README.md) documentation.
-- For example services, see [GitLab CI/CD Services](../services/README.md).
+- Detailed usage information, refer to [Docker integration](../docker/index.md) documentation.
+- For example services, see [GitLab CI/CD Services](../services/index.md).
##### `services:name`
@@ -677,7 +654,7 @@ job:
#### `before_script`
-`before_script` is used to define an array of commands that should run before each job,
+Use `before_script` to define an array of commands that should run before each job,
but after [artifacts](#artifacts) are restored.
Scripts specified in `before_script` are concatenated with any scripts specified
@@ -705,7 +682,7 @@ You can use [YAML anchors with `before_script`](#yaml-anchors-for-scripts).
#### `after_script`
-`after_script` is used to define an array of commands that run after each job,
+Use `after_script` to define an array of commands that run after each job,
including failed jobs.
If a job times out or is cancelled, the `after_script` commands are not executed.
@@ -756,7 +733,7 @@ You can use special syntax in [`script`](README.md#script) sections to:
`stage` is defined per-job and relies on [`stages`](#stages), which is defined
globally. Use `stage` to define which stage a job runs in, and jobs of the same
-`stage` are executed in parallel (subject to [certain conditions](#using-your-own-runners)). For example:
+`stage` are executed in parallel (subject to [certain conditions](#use-your-own-runners)). For example:
```yaml
stages:
@@ -789,7 +766,7 @@ job 5:
script: make something useful at the end of pipeline
```
-#### Using your own runners
+#### Use your own runners
When you use your own runners, each runner runs only one job at a time by default.
Jobs can run in parallel if they run on different runners.
@@ -811,7 +788,7 @@ User-defined stages are executed after `.pre` and before `.post`.
A pipeline is not created if all jobs are in `.pre` or `.post` stages.
-The order of `.pre` and `.post` can't be changed, even if defined out of order in `.gitlab-ci.yml`.
+The order of `.pre` and `.post` can't be changed, even if defined out of order in the `.gitlab-ci.yml` file.
For example, the following are equivalent configuration:
- Configured in order:
@@ -846,11 +823,16 @@ For example, the following are equivalent configuration:
> Introduced in GitLab 11.3.
-`extends` defines entry names that a job that uses `extends`
-inherits from.
+Use `extends` to reuse configuration sections. It's an alternative to [YAML anchors](#anchors)
+and is a little more flexible and readable. You can use `extends` to reuse configuration
+from [included configuration files](#use-extends-and-include-together).
+
+In this example, the `rspec` job uses the configuration from the `.tests` template job.
+GitLab:
-It's an alternative to using [YAML anchors](#anchors) and is a little
-more flexible and readable:
+- Performs a reverse deep merge based on the keys.
+- Merges the `.tests` content with the `rspec` job.
+- Doesn't merge the values of the keys.
```yaml
.tests:
@@ -868,13 +850,7 @@ rspec:
- $RSPEC
```
-In the example above, the `rspec` job inherits from the `.tests` template job.
-GitLab performs a reverse deep merge based on the keys. GitLab:
-
-- Merges the `rspec` contents into `.tests` recursively.
-- Doesn't merge the values of the keys.
-
-The result is this `rspec` job, where `script: rake test` is overwritten by `script: rake rspec`:
+The result is this `rspec` job:
```yaml
rspec:
@@ -887,10 +863,8 @@ rspec:
- $RSPEC
```
-If you do want to include the `rake test`, see [`before_script`](#before_script) or [`after_script`](#after_script).
-
`.tests` in this example is a [hidden job](#hide-jobs), but it's
-possible to inherit from regular jobs as well.
+possible to extend configuration from regular jobs as well.
`extends` supports multi-level inheritance. You should avoid using more than three levels,
but you can use as many as eleven. The following example has two levels of inheritance:
@@ -979,51 +953,51 @@ rspec:
Note that in the example above:
-- `variables` sections have been merged but that `URL: "http://my-url.internal"`
-has been overwritten by `URL: "http://docker-url.internal"`.
-- `tags: ['production']` has been overwritten by `tags: ['docker']`.
-- `script` has not been merged but rather `script: ['echo "Hello world!"']` has
- been overwritten by `script: ['rake rspec']`. Arrays can be
- merged using [YAML anchors](#anchors).
+- The `variables` sections merge, but `URL: "http://docker-url.internal"` overwrites `URL: "http://my-url.internal"`.
+- `tags: ['docker']` overwrites `tags: ['production']`.
+- `script` does not merge, but `script: ['rake rspec']` overwrites
+ `script: ['echo "Hello world!"']`. You can use [YAML anchors](#anchors) to merge arrays.
-#### Using `extends` and `include` together
+#### Use `extends` and `include` together
-`extends` works across configuration files combined with `include`.
+To reuse configuration from different configuration files,
+combine `extends` and [`include`](#include).
-For example, if you have a local `included.yml` file:
+In this example, a `script` is defined in the `included.yml` file.
+Then, in the `.gitlab-ci.yml` file, you use `extends` to refer
+to the contents of the `script`:
-```yaml
-.template:
- script:
- - echo Hello!
-```
+- `included.yml`:
-Then, in `.gitlab-ci.yml`:
+ ```yaml
+ .template:
+ script:
+ - echo Hello!
+ ```
-```yaml
-include: included.yml
+- `.gitlab-ci.yml`:
-useTemplate:
- image: alpine
- extends: .template
-```
+ ```yaml
+ include: included.yml
-This example runs a job called `useTemplate` that runs `echo Hello!` as defined in
-the `.template` job, and uses the `alpine` Docker image as defined in the local job.
+ useTemplate:
+ image: alpine
+ extends: .template
+ ```
### `rules`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3.
-The `rules` keyword can be used to include or exclude jobs in pipelines.
+Use the `rules` keyword to include or exclude jobs in pipelines.
Rules are evaluated *in order* until the first match. When matched, the job
is either included or excluded from the pipeline, depending on the configuration.
If included, the job also has [certain attributes](#rules-attributes)
added to it.
-`rules` replaces [`only/except`](#onlyexcept-basic) and can't be used in conjunction with it.
-If you attempt to use both keywords in the same job, the linter returns a
+`rules` replaces [`only/except`](#onlyexcept-basic) and they can't be used together
+in the same job. If you configure one job to use both keywords, the linter returns a
`key may not be used with rules` error.
#### Rules attributes
@@ -1078,7 +1052,7 @@ The job is not added to the pipeline:
`when: always`.
- If a rule matches, and has `when: never` as the attribute.
-For example, using `if` clauses to strictly limit when jobs run:
+This example uses `if` to strictly limit when jobs run:
```yaml
job:
@@ -1090,8 +1064,6 @@ job:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
```
-In this example:
-
- If the pipeline is for a merge request, the first rule matches, and the job
is added to the [merge request pipeline](../merge_request_pipelines/index.md)
with attributes of:
@@ -1165,7 +1137,7 @@ There are multiple ways to avoid duplicate pipelines:
or push (branch) pipelines only.
- Rewrite the rules to run the job only in very specific cases,
- and avoid using a final `when:` rule:
+ and avoid a final `when:` rule:
```yaml
job:
@@ -1240,13 +1212,13 @@ or excluded from a pipeline. In plain English, `if` rules can be interpreted as
`rules:if` differs slightly from `only:variables` by accepting only a single
expression string per rule, rather than an array of them. Any set of expressions to be
evaluated can be [conjoined into a single expression](../variables/README.md#conjunction--disjunction)
-by using `&&` or `||`, and the [variable matching operators (`==`, `!=`, `=~` and `!~`)](../variables/README.md#syntax-of-environment-variable-expressions).
+by using `&&` or `||`, and the [variable matching operators (`==`, `!=`, `=~` and `!~`)](../variables/README.md#syntax-of-cicd-variable-expressions).
-Unlike variables in [`script`](../variables/README.md#syntax-of-environment-variables-in-job-scripts)
+Unlike variables in [`script`](../variables/README.md#syntax-of-cicd-variables-in-job-scripts)
sections, variables in rules expressions are always formatted as `$VARIABLE`.
-`if:` clauses are evaluated based on the values of [predefined environment variables](../variables/predefined_variables.md)
-or [custom environment variables](../variables/README.md#custom-environment-variables).
+`if:` clauses are evaluated based on the values of [predefined CI/CD variables](../variables/predefined_variables.md)
+or [custom CI/CD variables](../variables/README.md#custom-cicd-variables).
For example:
@@ -1281,8 +1253,8 @@ check the value of the `$CI_PIPELINE_SOURCE` variable:
| Value | Description |
|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
-| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. |
-| `external` | When using CI services other than GitLab. |
+| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
+| `external` | When you use CI services other than GitLab. |
| `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). |
| `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). |
| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../parent_child_pipelines.md) with `rules`. Use this pipeline source in the child pipeline configuration so that it can be triggered by the parent pipeline. |
@@ -1331,7 +1303,7 @@ Other commonly used variables for `if` clauses:
branch (usually `master`). Use when you want to have the same configuration in multiple
projects with different default branches.
- `if: '$CI_COMMIT_BRANCH =~ /regex-expression/'`: If the commit branch matches a regular expression.
-- `if: '$CUSTOM_VARIABLE !~ /regex-expression/'`: If the [custom variable](../variables/README.md#custom-environment-variables)
+- `if: '$CUSTOM_VARIABLE !~ /regex-expression/'`: If the [custom variable](../variables/README.md#custom-cicd-variables)
`CUSTOM_VARIABLE` does **not** match a regular expression.
- `if: '$CUSTOM_VARIABLE == "value1"'`: If the custom variable `CUSTOM_VARIABLE` is
exactly `value1`.
@@ -1387,7 +1359,7 @@ if there is no `if:` statement that limits the job to branch or merge request pi
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34272) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267192) in GitLab 13.7.
-Environment variables can be used in `rules:changes` expressions to determine when
+CI/CD variables can be used in `rules:changes` expressions to determine when
to add jobs to a pipeline:
```yaml
@@ -1400,7 +1372,7 @@ docker build:
- $DOCKERFILES_DIR/*
```
-The `$` character can be used for both variables and paths. For example, if the
+You can use The `$` character for both variables and paths. For example, if the
`$DOCKERFILES_DIR` variable exists, its value is used. If it does not exist, the
`$` is interpreted as being part of a path.
@@ -1409,7 +1381,9 @@ The `$` character can be used for both variables and paths. For example, if the
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4.
`exists` accepts an array of paths and matches if any of these paths exist
-as files in the repository:
+as files in the repository.
+
+In this example, `job` runs if a `Dockerfile` exists anywhere in the repository:
```yaml
job:
@@ -1419,7 +1393,9 @@ job:
- Dockerfile
```
-You can also use glob patterns to match multiple files in any directory in the repository:
+Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly link outside it.
+
+You can use glob patterns to match multiple files in any directory in the repository:
```yaml
job:
@@ -1429,15 +1405,17 @@ job:
- spec/**.rb
```
-For performance reasons, using `exists` with patterns is limited to 10,000
-checks. After the 10,000th check, rules with patterned globs always match.
+Glob patterns are interpreted with Ruby [`File.fnmatch`](https://docs.ruby-lang.org/en/2.7.0/File.html#method-c-fnmatch)
+with the flags `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB`.
+
+For performance reasons, GitLab matches a maximum of 10,000 `exists` patterns. After the 10,000th check, rules with patterned globs always match.
#### `rules:allow_failure`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) in GitLab 12.8.
You can use [`allow_failure: true`](#allow_failure) in `rules:` to allow a job to fail, or a manual job to
-wait for action, without stopping the pipeline itself. All jobs using `rules:` default to `allow_failure: false`
+wait for action, without stopping the pipeline itself. All jobs that use `rules:` default to `allow_failure: false`
if `allow_failure:` is not defined.
The rule-level `rules:allow_failure` option overrides the job-level
@@ -1462,7 +1440,7 @@ In this example, if the first rule matches, then the job has `when: manual` and
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/289803) on GitLab 13.8.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-rulesvariables). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-rulesvariables). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -1487,7 +1465,7 @@ job:
- echo "Run another script if $IS_A_FEATURE exists"
```
-##### Enable or disable rules:variables **(CORE ONLY)**
+##### Enable or disable rules:variables **(FREE SELF)**
rules:variables is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
@@ -1553,12 +1531,10 @@ rules that use both `||` and `&&` may evaluate with an unexpected order of opera
### `only`/`except` (basic)
NOTE:
-The [`rules`](#rules) syntax is an improved, more powerful solution for defining
-when jobs should run or not. Consider using `rules` instead of `only/except` to get
-the most out of your pipelines.
+`only` and `except` are not being actively developed. To define when
+to add jobs to pipelines, use [`rules`](#rules).
-`only` and `except` are two keywords that set a job policy to limit when
-jobs are created:
+`only` and `except` are two keywords that determine when to add jobs to pipelines:
1. `only` defines the names of branches and tags the job runs for.
1. `except` defines the names of branches and tags the job does
@@ -1577,8 +1553,8 @@ In addition, `only` and `except` can use special keywords:
|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
| `branches` | When the Git reference for a pipeline is a branch. |
-| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. |
-| `external` | When using CI services other than GitLab. |
+| `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](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). |
| `pipelines` | For [multi-project pipelines](../multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../multi_project_pipelines.md#triggering-multi-project-pipelines-through-api), or the [`trigger`](#trigger) keyword. |
@@ -1630,7 +1606,7 @@ job:
- schedules
```
-The repository path can be used to have jobs executed only for the parent
+Use the repository path to have jobs executed only for the parent
repository and not forks:
```yaml
@@ -1648,17 +1624,13 @@ except `master` and those with names prefixed with `release/`.
If a job does not have an `only` rule, `only: ['branches', 'tags']` is set by
default. If it does not have an `except` rule, it's empty.
-For example,
+For example, `job1` and `job2` are essentially the same:
```yaml
-job:
+job1:
script: echo 'test'
-```
-
-is translated to:
-```yaml
-job:
+job2:
script: echo 'test'
only: ['branches', 'tags']
```
@@ -1728,7 +1700,7 @@ the pipeline if the following is true:
In the example below, the `test` job is `only` created when **all** of the following are true:
-- The pipeline has been [scheduled](../pipelines/schedules.md) **or** runs for `master`.
+- The pipeline is [scheduled](../pipelines/schedules.md) **or** runs for `master`.
- The `variables` keyword matches.
- The `kubernetes` service is active on the project.
@@ -1805,7 +1777,7 @@ The `variables` keyword defines variable expressions.
These expressions determine whether or not a job should be created.
-Examples of using variable expressions:
+Examples of variable expressions:
```yaml
deploy:
@@ -1844,15 +1816,14 @@ job1:
> `changes` policy [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19232) in GitLab 11.4.
-Using the `changes` keyword with `only` or `except` makes it possible to define if
-a job should be created based on files modified by a Git push event.
+Use the `changes` keyword with `only` to run a job, or with `except` to skip a job,
+when a Git push event modifies a file.
-Use the `only:changes` policy for pipelines triggered by the following
-refs only:
+Use `only:changes` with pipelines triggered by the following refs only:
- `branches`
- `external_pull_requests`
-- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](#using-onlychanges-with-pipelines-for-merge-requests))
+- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](#use-onlychanges-with-pipelines-for-merge-requests))
WARNING:
In pipelines with [sources other than the three above](../variables/predefined_variables.md)
@@ -1860,7 +1831,13 @@ In pipelines with [sources other than the three above](../variables/predefined_v
You can configure jobs to use `only: changes` with other `only: refs` keywords. However,
those jobs ignore the changes and always run.
-A basic example of using `only: changes`:
+In this example, when you push commits to an existing branch, the `docker build` job
+runs only if any of these files change:
+
+- The `Dockerfile` file.
+- Files in the `docker/scripts/` directory.
+- Files and subdirectories in the `dockerfiles` directory.
+- Files with `rb`, `py`, `sh` extensions in the `more_scripts` directory.
```yaml
docker build:
@@ -1875,21 +1852,13 @@ docker build:
- more_scripts/*.{rb,py,sh}
```
-When you push commits to an existing branch,
-the `docker build` job is created, but only if changes were made to any of the following:
-
-- The `Dockerfile` file.
-- Any of the files in the `docker/scripts/` directory.
-- Any of the files and subdirectories in the `dockerfiles` directory.
-- Any of the files with `rb`, `py`, `sh` extensions in the `more_scripts` directory.
-
WARNING:
If you use `only: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`](#using-onlychanges-with-pipelines-for-merge-requests). Otherwise it may not work as expected.
+you should [also use `only:merge_requests`](#use-onlychanges-with-pipelines-for-merge-requests). Otherwise it may not work as expected.
You can also use glob patterns to match multiple files in either the root directory
of the repository, or in _any_ directory in the repository. However, they must be wrapped
-in double quotes or GitLab can't parse them. For example:
+in double quotes or GitLab can't parse them:
```yaml
test:
@@ -1918,10 +1887,10 @@ the `build` job is still skipped. The job does not run for any of the files.
Read more about how to use this feature with:
-- [New branches or tags *without* pipelines for merge requests](#using-onlychanges-without-pipelines-for-merge-requests).
-- [Scheduled pipelines](#using-onlychanges-with-scheduled-pipelines).
+- [New branches or tags *without* pipelines for merge requests](#use-onlychanges-without-pipelines-for-merge-requests).
+- [Scheduled pipelines](#use-onlychanges-with-scheduled-pipelines).
-##### Using `only:changes` with pipelines for merge requests
+##### Use `only:changes` with pipelines for merge requests
With [pipelines for merge requests](../merge_request_pipelines/index.md),
it's possible to define a job to be created based on files modified
@@ -1971,7 +1940,7 @@ it doesn't matter that an earlier pipeline failed because of a change that has n
When you use this configuration, ensure that the most recent pipeline
properly corrects any failures from previous pipelines.
-##### Using `only:changes` without pipelines for merge requests
+##### Use `only:changes` without pipelines for merge requests
Without [pipelines for merge requests](../merge_request_pipelines/index.md), pipelines
run on branches or tags that don't have an explicit association with a merge request.
@@ -1979,14 +1948,13 @@ In this case, a previous SHA is used to calculate the diff, which is equivalent
This can result in some unexpected behavior, including:
- When pushing a new branch or a new tag to GitLab, the policy always evaluates to true.
-- When pushing a new commit, the changed files are calculated using the previous commit
+- When pushing a new commit, the changed files are calculated by using the previous commit
as the base SHA.
-##### Using `only:changes` with scheduled pipelines
+##### Use `only:changes` with scheduled pipelines
-`only:changes` always evaluates as "true" in [Scheduled pipelines](../pipelines/schedules.md).
-All files are considered to have "changed" when a scheduled pipeline
-runs.
+`only:changes` always evaluates as true in [Scheduled pipelines](../pipelines/schedules.md).
+All files are considered to have changed when a scheduled pipeline runs.
### `needs`
@@ -2056,15 +2024,17 @@ This example creates four paths of execution:
- For GitLab.com, the limit is 50. For more information, see our
[infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541).
- For self-managed instances, the limit is: 50. This limit [can be changed](#changing-the-needs-job-limit).
-- If `needs:` refers to a job that is marked as `parallel:`.
- the current job depends on all parallel jobs being created.
+- If `needs:` refers to a job that uses the [`parallel`](#parallel) keyword,
+ it depends on all jobs created in parallel, not just one job. It also downloads
+ artifacts from all the parallel jobs by default. If the artifacts have the same
+ name, they overwrite each other and only the last one downloaded is saved.
- `needs:` is similar to `dependencies:` in that it must use jobs from prior stages,
meaning it's impossible to create circular dependencies. Depending on jobs in the
current stage is not possible either, but support [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/30632).
- Related to the above, stages must be explicitly defined for all jobs
that have the keyword `needs:` or are referred to by one.
-##### Changing the `needs:` job limit **(CORE ONLY)**
+##### Changing the `needs:` job limit **(FREE SELF)**
The maximum number of jobs that can be defined in `needs:` defaults to 50.
@@ -2081,14 +2051,11 @@ To disable directed acyclic graphs (DAG), set the limit to `0`.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab v12.6.
-When using `needs`, artifact downloads are controlled with `artifacts: true` (default) or `artifacts: false`.
+Use `artifacts: true` (default) or `artifacts: false` to control when artifacts are
+downloaded in jobs that use `needs`.
-In GitLab 12.6 and later, you can't combine the [`dependencies`](#dependencies) keyword
-with `needs` to control artifact downloads in jobs. `dependencies` is still valid
-in jobs that do not use `needs`.
-
-In the example below, the `rspec` job downloads the `build_job` artifacts, while the
-`rubocop` job doesn't:
+In this example, the `rspec` job downloads the `build_job` artifacts, but the
+`rubocop` job does not:
```yaml
build_job:
@@ -2110,9 +2077,11 @@ rubocop:
artifacts: false
```
-Additionally, in the three syntax examples below, the `rspec` job downloads the artifacts
-from all three `build_jobs`. `artifacts` is true for `build_job_1` and
-**defaults** to true for both `build_job_2` and `build_job_3`.
+In this example, the `rspec` job downloads the artifacts from all three `build_jobs`.
+`artifacts` is:
+
+- Set to true for `build_job_1`.
+- Defaults to true for both `build_job_2` and `build_job_3`.
```yaml
rspec:
@@ -2123,6 +2092,9 @@ rspec:
- build_job_3
```
+In GitLab 12.6 and later, you can't combine the [`dependencies`](#dependencies) keyword
+with `needs`.
+
#### Cross project artifact downloads with `needs` **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab v12.7.
@@ -2146,7 +2118,7 @@ build_job:
`build_job` downloads the artifacts from the latest successful `build-1` job
on the `master` branch in the `group/project-name` project. If the project is in the
-same group or namespace, you can omit them from the `project:` key. For example,
+same group or namespace, you can omit them from the `project:` keyword. For example,
`project: group/project-name` or `project: project-name`.
The user running the pipeline must have at least `reporter` access to the group or project, or the group/project must have public visibility.
@@ -2171,7 +2143,7 @@ build_job:
artifacts: true
```
-Environment variables support for `project:`, `job:`, and `ref` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093)
+CI/CD variable support for `project:`, `job:`, and `ref` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093)
in GitLab 13.3. [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235761) in GitLab 13.4.
For example:
@@ -2280,10 +2252,11 @@ osx job:
### `allow_failure`
Use `allow_failure` when you want to let a job fail without impacting the rest of the CI
-suite.
-The default value is `false`, except for [manual](#whenmanual) jobs using the
-`when: manual` syntax, unless using [`rules:`](#rules) syntax, where all jobs
-default to false, *including* `when: manual` jobs.
+suite. The default value is `false`, except for [manual](#whenmanual) jobs that use
+the `when: manual` syntax.
+
+In jobs that use [`rules:`](#rules), all jobs default to `allow_failure: false`,
+*including* `when: manual` jobs.
When `allow_failure` is set to `true` and the job fails, the job shows an orange warning in the UI.
However, the logical flow of the pipeline considers the job a
@@ -2318,13 +2291,7 @@ job3:
#### `allow_failure:exit_codes`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273157) in GitLab 13.8.
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-allow_failureexit_codes). **(CORE ONLY)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292024) in GitLab 13.9.
Use `allow_failure:exit_codes` to dynamically control if a job should be allowed
to fail. You can list which exit codes are not considered failures. The job fails
@@ -2348,31 +2315,12 @@ test_job_2:
- 255
```
-##### Enable or disable `allow_failure:exit_codes` **(CORE ONLY)**
-
-`allow_failure:exit_codes` is under development but ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_allow_failure_with_exit_codes)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:ci_allow_failure_with_exit_codes)
-```
-
### `when`
-`when` is used to implement jobs that are run in case of failure or despite the
+Use `when` to implement jobs that run in case of failure or despite the
failure.
-`when` can be set to one of the following values:
+The valid values of `when` are:
1. `on_success` (default) - Execute job only when all jobs in earlier stages succeed,
or are considered successful because they have `allow_failure: true`.
@@ -2510,8 +2458,8 @@ by authorized users.
Use `when: delayed` to execute scripts after a waiting period, or if you want to avoid
jobs immediately entering the `pending` state.
-You can set the period with `start_in` key. The value of `start_in` key is an elapsed time in seconds, unless a unit is
-provided. `start_in` key must be less than or equal to one week. Examples of valid values include:
+You can set the period with `start_in` keyword. The value of `start_in` is an elapsed time in seconds, unless a unit is
+provided. `start_in` must be less than or equal to one week. Examples of valid values include:
- `'5'`
- `5 seconds`
@@ -2519,13 +2467,13 @@ provided. `start_in` key must be less than or equal to one week. Examples of val
- `1 day`
- `1 week`
-When there is a delayed job in a stage, the pipeline doesn't progress until the delayed job has finished.
-This keyword can also be used for inserting delays between different stages.
+When a stage includes a delayed job, the pipeline doesn't progress until the delayed job finishes.
+You can use this keyword to insert delays between different stages.
-The timer of a delayed job starts immediately after the previous stage has completed.
-Similar to other types of jobs, a delayed job's timer doesn't start unless the previous stage passed.
+The timer of a delayed job starts immediately after the previous stage completes.
+Similar to other types of jobs, a delayed job's timer doesn't start unless the previous stage passes.
-The following example creates a job named `timed rollout 10%` that is executed 30 minutes after the previous stage has completed:
+The following example creates a job named `timed rollout 10%` that is executed 30 minutes after the previous stage completes:
```yaml
timed rollout 10%:
@@ -2535,7 +2483,7 @@ timed rollout 10%:
start_in: 30 minutes
```
-You can stop the active timer of a delayed job by clicking the **{time-out}** (**Unschedule**) button.
+To stop the active timer of a delayed job, click the **{time-out}** (**Unschedule**) button.
This job can no longer be scheduled to run automatically. You can, however, execute the job manually.
To start a delayed job immediately, click the **Play** button.
@@ -2561,8 +2509,8 @@ deployment to the `production` environment.
#### `environment:name`
-The `environment: name` keyword can use any of the defined CI variables,
-including predefined, secure, or `.gitlab-ci.yml` [`variables`](#variables).
+The `environment: name` keyword can use any of the defined CI/CD [variables](#variables),
+including predefined, secure, or variables defined in the `.gitlab-ci.yml` file.
You can't use variables defined in a `script` section.
@@ -2595,8 +2543,8 @@ deploy to production:
#### `environment:url`
-The `url` keyword can use any of the defined CI variables,
-including predefined, secure, or `.gitlab-ci.yml` [`variables`](#variables).
+The `environment:url` keyword can use any of the defined CI/CD [variables](#variables),
+including predefined, secure, or variables defined in the `.gitlab-ci.yml` file.
You can't use variables defined in a `script` section.
@@ -2632,7 +2580,7 @@ Read the `environment:action` section for an example.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22191) in GitLab 8.13.
-The `action` keyword can be used to specify jobs that prepare, start, or stop environments.
+Use the `action` keyword to specify jobs that prepare, start, or stop environments.
| **Value** | **Description** |
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -2718,7 +2666,7 @@ For more information, see
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) in GitLab 12.6.
-The `kubernetes` block is used to configure deployments to a
+Use the `kubernetes` keyword to configure deployments to a
[Kubernetes cluster](../../user/project/clusters/index.md) that is associated with your project.
For example:
@@ -2763,7 +2711,7 @@ deploy as review app:
The `deploy as review app` job is marked as a deployment to dynamically
create the `review/$CI_COMMIT_REF_NAME` environment. `$CI_COMMIT_REF_NAME`
-is an [environment variable](../variables/README.md) set by the runner. The
+is a [CI/CD variable](../variables/README.md) set by the runner. The
`$CI_ENVIRONMENT_SLUG` variable is based on the environment name, but suitable
for inclusion in URLs. If the `deploy as review app` job runs in a branch named
`pow`, this environment would be accessible with a URL like `https://review-pow.example.com/`.
@@ -2774,11 +2722,11 @@ as Review Apps. You can see an example that uses Review Apps at
### `cache`
-`cache` is used to specify a list of files and directories that should be
-cached between jobs. You can only use paths that are in the local working copy.
+Use the `cache` keyword to specify a list of files and directories to
+cache between jobs. You can only use paths that are in the local working copy.
-If `cache` is defined outside the scope of jobs, it means it's set
-globally and all jobs use that definition.
+If `cache` is defined outside the scope of jobs, it's set
+globally and all jobs use that configuration.
Caching is shared between pipelines and jobs. Caches are restored before [artifacts](#artifacts).
@@ -2789,7 +2737,7 @@ Read how caching works and find out some good practices in the
Use the `paths` directive to choose which files or directories to cache. Paths
are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly link outside it.
-Wildcards can be used that follow the [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+You can use Wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
patterns and:
- In [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620) and later,
@@ -2864,7 +2812,7 @@ URI-encoded `%2F`. A value made only of dots (`.`, `%2E`) is also forbidden.
You can specify a [fallback cache key](#fallback-cache-key) to use if the specified `cache:key` is not found.
-#### Fallback cache key
+##### Fallback cache key
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1534) in GitLab Runner 13.4.
@@ -2875,7 +2823,8 @@ to download cache that's tagged with `test`.
If a cache with this tag is not found, you can use `CACHE_FALLBACK_KEY` to
specify a cache to use when none exists.
-For example:
+In this example, if the `$CI_COMMIT_REF_SLUG` is not found, the job uses the key defined
+by the `CACHE_FALLBACK_KEY` variable:
```yaml
variables:
@@ -2887,9 +2836,6 @@ cache:
- binaries/
```
-In this example, if the `$CI_COMMIT_REF_SLUG` is not found, the job uses the key defined
-by the `CACHE_FALLBACK_KEY` variable.
-
##### `cache:key:files`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab v12.5.
@@ -2900,7 +2846,7 @@ runs.
When you include `cache:key:files`, you must also list the project files that are used to generate the key, up to a maximum of two files.
The cache `key` is a SHA checksum computed from the most recent commits (up to two, if two files are listed)
-that changed the given files. If neither file was changed in any commits,
+that changed the given files. If neither file is changed in any commits,
the fallback key is `default`.
```yaml
@@ -2927,7 +2873,7 @@ use the new cache, instead of rebuilding the dependencies.
When you want to combine a prefix with the SHA computed for `cache:key:files`,
use the `prefix` keyword with `key:files`.
For example, if you add a `prefix` of `test`, the resulting key is: `test-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5`.
-If neither file was changed in any commits, the prefix is added to `default`, so the
+If neither file is changed in any commits, the prefix is added to `default`, so the
key in the example would be `test-default`.
Like `cache:key`, `prefix` can use any of the [predefined variables](../variables/README.md),
@@ -3039,8 +2985,8 @@ rspec:
- bundle exec rspec ...
```
-The `pull` policy speeds up job execution and reduces load on the cache server. It
-can be used when you have many jobs that use caches executing in parallel.
+Use the `pull` policy when you have many jobs executing in parallel that use caches. This
+policy speeds up job execution and reduces load on the cache server.
If you have a job that unconditionally recreates the cache without
referring to its previous contents, you can skip the download step.
@@ -3048,7 +2994,7 @@ To do so, add `policy: push` to the job.
### `artifacts`
-`artifacts` is used to specify a list of files and directories that are
+Use the `artifacts` keyword to specify a list of files and directories that are
attached to the job when it [succeeds, fails, or always](#artifactswhen).
The artifacts are sent to GitLab after the job finishes. They are
@@ -3063,7 +3009,7 @@ artifacts are restored after [caches](#cache).
#### `artifacts:paths`
Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly
-link outside it. Wildcards can be used that follow the [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+link outside it. You can use Wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
patterns and:
- In [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620) and later,
@@ -3122,6 +3068,32 @@ job:
- path/*xyz/*
```
+#### `artifacts:public`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49775) in GitLab 13.8
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+
+Use `artifacts:public` to determine whether the job artifacts should be
+publicly available.
+
+The default for `artifacts:public` is `true` which means that the artifacts in
+public pipelines are available for download by anonymous and guest users:
+
+```yaml
+artifacts:
+ public: true
+```
+
+To deny read access for anonymous and guest users to artifacts in public
+pipelines, set `artifacts:public` to `false`:
+
+```yaml
+artifacts:
+ public: false
+```
+
#### `artifacts:exclude`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) in GitLab 13.1
@@ -3131,9 +3103,9 @@ job:
archive.
Similar to [`artifacts:paths`](#artifactspaths), `exclude` paths are relative
-to the project directory. Wildcards can be used that follow the
-[glob](https://en.wikipedia.org/wiki/Glob_(programming)) patterns and
-[`filepath.Match`](https://golang.org/pkg/path/filepath/#Match).
+to the project directory. You can use Wildcards that use
+[glob](https://en.wikipedia.org/wiki/Glob_(programming)) or
+[`filepath.Match`](https://golang.org/pkg/path/filepath/#Match) patterns.
For example, to store all files in `binaries/`, but not `*.o` files located in
subdirectories of `binaries/`:
@@ -3153,7 +3125,7 @@ Files matched by [`artifacts:untracked`](#artifactsuntracked) can be excluded us
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15018) in GitLab 12.5.
-The `expose_as` keyword can be used to expose [job artifacts](../pipelines/job_artifacts.md)
+Use the `expose_as` keyword to expose [job artifacts](../pipelines/job_artifacts.md)
in the [merge request](../../user/project/merge_requests/index.md) UI.
For example, to match a single file:
@@ -3270,8 +3242,8 @@ job:
#### `artifacts:untracked`
-`artifacts:untracked` is used to add all Git untracked files as artifacts (along
-to the paths defined in `artifacts:paths`). `artifacts:untracked` ignores configuration
+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.
Send all Git untracked files:
@@ -3301,7 +3273,7 @@ artifacts:
#### `artifacts:when`
-`artifacts:when` is used to upload artifacts on job failure or despite the
+Use `artifacts:when` to upload artifacts on job failure or despite the
failure.
`artifacts:when` can be set to one of the following values:
@@ -3361,12 +3333,14 @@ job:
The latest artifacts for refs are locked against deletion, and kept regardless of
the expiry time. [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/16267)
GitLab 13.0 behind a disabled feature flag, and [made the default behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/229936)
-in GitLab 13.4. In [GitLab 13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/241026), you can [disable this behavior in the CI/CD settings](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
+in GitLab 13.4.
+
+In [GitLab 13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/241026), you can [disable this behavior at the project level in the CI/CD settings](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs). In [GitLab 13.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/276583), you can [disable this behavior instance-wide](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
#### `artifacts:reports`
-The [`artifacts:reports` keyword](../pipelines/job_artifacts.md#artifactsreports)
-is used for collecting test reports, code quality reports, and security reports from jobs.
+Use [`artifacts:reports`](../pipelines/job_artifacts.md#artifactsreports)
+to collect test reports, code quality reports, and security reports from jobs.
It also exposes these reports in the GitLab UI (merge requests, pipeline views, and security dashboards).
These are the available report types:
@@ -3374,7 +3348,7 @@ These are the available report types:
| Keyword | Description |
|-----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
| [`artifacts:reports:cobertura`](../pipelines/job_artifacts.md#artifactsreportscobertura) | The `cobertura` report collects Cobertura coverage XML files. |
-| [`artifacts:reports:codequality`](../pipelines/job_artifacts.md#artifactsreportscodequality) | The `codequality` report collects CodeQuality issues. |
+| [`artifacts:reports:codequality`](../pipelines/job_artifacts.md#artifactsreportscodequality) | The `codequality` report collects Code Quality issues. |
| [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.md#artifactsreportscontainer_scanning) **(ULTIMATE)** | The `container_scanning` report collects Container Scanning vulnerabilities. |
| [`artifacts:reports:dast`](../pipelines/job_artifacts.md#artifactsreportsdast) **(ULTIMATE)** | The `dast` report collects Dynamic Application Security Testing vulnerabilities. |
| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.md#artifactsreportsdependency_scanning) **(ULTIMATE)** | The `dependency_scanning` report collects Dependency Scanning vulnerabilities. |
@@ -3385,7 +3359,7 @@ These are the available report types:
| [`artifacts:reports:load_performance`](../pipelines/job_artifacts.md#artifactsreportsload_performance) **(PREMIUM)** | The `load_performance` report collects load performance metrics. |
| [`artifacts:reports:metrics`](../pipelines/job_artifacts.md#artifactsreportsmetrics) **(PREMIUM)** | The `metrics` report collects Metrics. |
| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. |
-| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast) **(ULTIMATE)** | The `sast` report collects Static Application Security Testing vulnerabilities. |
+| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast) | The `sast` report collects Static Application Security Testing vulnerabilities. |
| [`artifacts:reports:terraform`](../pipelines/job_artifacts.md#artifactsreportsterraform) | The `terraform` report collects Terraform `tfplan.json` files. |
#### `dependencies`
@@ -3403,7 +3377,7 @@ An error occurs if you define jobs from the current or an upcoming stage.
To prevent a job from downloading artifacts, define an empty array.
When you use `dependencies`, the status of the previous job is not considered.
-If a job fails or it's a manual job that was not run, no error occurs.
+If a job fails or it's a manual job that isn't triggered, no error occurs.
The following example defines two jobs with artifacts: `build:osx` and
`build:linux`. When the `test:osx` is executed, the artifacts from `build:osx`
@@ -3449,7 +3423,7 @@ deploy:
> Introduced in GitLab 10.3.
-If the artifacts of the job that is set as a dependency have been
+If the artifacts of the job that is set as a dependency are
[expired](#artifactsexpire_in) or
[erased](../pipelines/job_artifacts.md#erasing-artifacts), then
the dependent job fails.
@@ -3478,7 +3452,7 @@ job1:
The coverage is shown in the UI if at least one line in the job output matches the regular expression.
If there is more than one matched line in the job output, the last line is used.
-For the matched line, the first occurence of `\d+(\.\d+)?` is the code coverage.
+For the matched line, the first occurrence of `\d+(\.\d+)?` is the code coverage.
Leading zeros are removed.
Coverage output from [child pipelines](../parent_child_pipelines.md) is not recorded
@@ -3554,15 +3528,15 @@ Possible values for `when` are:
- `script_failure`: Retry when the script failed.
- `api_failure`: Retry on API failure.
- `stuck_or_timeout_failure`: Retry when the job got stuck or timed out.
-- `runner_system_failure`: Retry if there was a runner system failure (for example, job setup failed).
-- `missing_dependency_failure`: Retry if a dependency was missing.
-- `runner_unsupported`: Retry if the runner was unsupported.
+- `runner_system_failure`: Retry if there is a runner system failure (for example, job setup failed).
+- `missing_dependency_failure`: Retry if a dependency is missing.
+- `runner_unsupported`: Retry if the runner is unsupported.
- `stale_schedule`: Retry if a delayed job could not be executed.
- `job_execution_timeout`: Retry if the script exceeded the maximum execution time set for the job.
- `archived_failure`: Retry if the job is archived and can't be run.
- `unmet_prerequisites`: Retry if the job failed to complete prerequisite tasks.
- `scheduler_failure`: Retry if the scheduler failed to assign the job to a runner.
-- `data_integrity_failure`: Retry if there was a structural integrity problem detected.
+- `data_integrity_failure`: Retry if there is a structural integrity problem detected.
You can specify the number of [retry attempts for certain stages of job execution](../runners/README.md#job-stages-attempts) using variables.
@@ -3603,7 +3577,7 @@ test:
```
Every parallel job has a `CI_NODE_INDEX` and `CI_NODE_TOTAL`
-[environment variable](../variables/README.md#predefined-environment-variables) set.
+[predefined CI/CD variable](../variables/README.md#predefined-cicd-variables) set.
Different languages and test suites have different methods to enable parallelization.
For example, use [Semaphore Test Boosters](https://github.com/renderedtext/test-boosters)
@@ -3640,9 +3614,9 @@ but with different variable values for each instance of the job.
There can be from 2 to 50 jobs.
Jobs can only run in parallel if there are multiple runners, or a single runner is
-[configured to run multiple jobs concurrently](#using-your-own-runners).
+[configured to run multiple jobs concurrently](#use-your-own-runners).
-Every job gets the same `CI_NODE_TOTAL` [environment variable](../variables/README.md#predefined-environment-variables) value, and a unique `CI_NODE_INDEX` value.
+Every job gets the same `CI_NODE_TOTAL` [CI/CD variable](../variables/README.md#predefined-cicd-variables) value, and a unique `CI_NODE_INDEX` value.
```yaml
deploystacks:
@@ -3699,10 +3673,10 @@ deploystacks:
### `trigger`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Core in 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
-Use `trigger` to define a downstream pipeline trigger. When GitLab starts a job created
-with a `trigger` definition, a downstream pipeline is created.
+Use `trigger` to define a downstream pipeline trigger. When GitLab starts a `trigger` job,
+a downstream pipeline is created.
Jobs with `trigger` can only use a [limited set of keywords](../multi_project_pipelines.md#limitations).
For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
@@ -3777,7 +3751,7 @@ upstream_bridge:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) in GitLab 12.7.
To create a [child pipeline](../parent_child_pipelines.md), specify the path to the
-YAML file containing the CI config of the child pipeline:
+YAML file that contains the configuration of the child pipeline:
```yaml
trigger_job:
@@ -3871,10 +3845,10 @@ The trigger token is different than the [`trigger`](#trigger) keyword.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32022) in GitLab 12.3.
-`interruptible` is used to indicate that a running job should be canceled if made redundant by a newer pipeline run.
+Use `interruptible` to indicate that a running job should be canceled if made redundant by a newer pipeline run.
Defaults to `false` (uninterruptible). Jobs that have not started yet (pending) are considered interruptible
and safe to be cancelled.
-This value is used only if the [automatic cancellation of redundant pipelines feature](../pipelines/settings.md#auto-cancel-pending-pipelines)
+This value is used only if the [automatic cancellation of redundant pipelines feature](../pipelines/settings.md#auto-cancel-redundant-pipelines)
is enabled.
When enabled, a pipeline is immediately canceled when a new pipeline starts on the same branch if either of the following is true:
@@ -3924,11 +3898,11 @@ When an uninterruptible job is running, the pipeline cannot be canceled, regardl
Sometimes running multiple jobs or pipelines at the same time in an environment
can lead to errors during the deployment.
-To avoid these errors, the `resource_group` attribute can be used to ensure that
+To avoid these errors, use the `resource_group` attribute to make sure that
the runner doesn't run certain jobs simultaneously. Resource groups behave similar
to semaphores in other programming languages.
-When the `resource_group` key is defined for a job in `.gitlab-ci.yml`,
+When the `resource_group` keyword is defined for a job in the `.gitlab-ci.yml` file,
job executions are mutually exclusive across different pipelines for the same project.
If multiple jobs belonging to the same resource group are enqueued simultaneously,
only one of the jobs is picked by the runner. The other jobs wait until the
@@ -3954,13 +3928,67 @@ It can't start or end with `/`.
For more information, see [Deployments Safety](../environments/deployment_safety.md).
+#### Pipeline-level concurrency control with Cross-Project/Parent-Child pipelines
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39057) in GitLab 13.9.
+
+You can define `resource_group` for downstream pipelines that are sensitive to concurrent
+executions. The [`trigger` keyword](#trigger) can trigger downstream pipelines. The
+[`resource_group` keyword](#resource_group) can co-exist with it. This is useful to control the
+concurrency for deployment pipelines, while running non-sensitive jobs concurrently.
+
+This example has two pipeline configurations in a project. When a pipeline starts running,
+non-sensitive jobs are executed first and aren't affected by concurrent executions in other
+pipelines. However, GitLab ensures that there are no other deployment pipelines running before
+triggering a deployment (child) pipeline. If other deployment pipelines are running, GitLab waits
+until those pipelines finish before running another one.
+
+```yaml
+# .gitlab-ci.yml (parent pipeline)
+
+build:
+ stage: build
+ script: echo "Building..."
+
+test:
+ stage: test
+ script: echo "Testing..."
+
+deploy:
+ stage: deploy
+ trigger:
+ include: deploy.gitlab-ci.yml
+ strategy: depend
+ resource_group: AWS-production
+```
+
+```yaml
+# deploy.gitlab-ci.yml (child pipeline)
+
+stages:
+ - provision
+ - deploy
+
+provision:
+ stage: provision
+ script: echo "Provisioning..."
+
+deployment:
+ stage: deploy
+ script: echo "Deploying..."
+```
+
+Note that you must define [`strategy: depend`](#linking-pipelines-with-triggerstrategy)
+with the `trigger` keyword. This ensures that the lock isn't released until the downstream pipeline
+finishes.
+
### `release`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) in GitLab 13.2.
`release` indicates that the job creates a [Release](../../user/project/releases/index.md).
-These methods are supported:
+These keywords are supported:
- [`tag_name`](#releasetag_name)
- [`description`](#releasedescription)
@@ -3983,7 +4011,7 @@ image: registry.gitlab.com/gitlab-org/release-cli:latest
#### Script
All jobs except [trigger](#trigger) jobs must have the `script` keyword. A `release`
-job can use the output from script commands, but a placeholder script can be used if
+job can use the output from script commands, but you can use a placeholder script if
the script is not needed:
```yaml
@@ -4055,7 +4083,7 @@ description.
You can specify a file in `$CI_PROJECT_DIR` that contains the description. The file must be relative
to the project directory (`$CI_PROJECT_DIR`), and if the file is a symbolic link it can't reside
-outside of `$CI_PROJECT_DIR`. The `./path/to/file` and file name can't contain spaces.
+outside of `$CI_PROJECT_DIR`. The `./path/to/file` and filename can't contain spaces.
```yaml
job:
@@ -4086,7 +4114,7 @@ released_at: '2021-03-15T08:00:00Z'
Combining the individual examples given above for `release` results in the following
code snippets. There are two options, depending on how you generate the
-tags. These options cannot be used together, so choose one:
+tags. You can't use these options together, so choose one:
- To create a release when you push a Git tag, or when you add a Git tag
in the UI by going to **Repository > Tags**:
@@ -4179,10 +4207,10 @@ release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33014) in GitLab 13.4.
-`secrets` indicates the [CI Secrets](../secrets/index.md) this job needs. It should be a hash,
-and the keys should be the names of the environment variables that are made available to the job.
+`secrets` indicates the [CI/CD Secrets](../secrets/index.md) this job needs. It should be a hash,
+and the keys should be the names of the variables that are made available to the job.
The value of each secret is saved in a temporary file. This file's path is stored in these
-environment variables.
+variables.
#### `secrets:vault` **(PREMIUM)**
@@ -4226,8 +4254,8 @@ job:
### `pages`
-`pages` is a special job that is used to upload static content to GitLab that
-can be used to serve your website. It has a special syntax, so the two
+`pages` is a special job that uploads static content to GitLab that
+is then published as a website. It has a special syntax, so the two
requirements below must be met:
- Any static content must be placed under a `public/` directory.
@@ -4262,9 +4290,10 @@ They can be set globally and per-job.
There are two types of variables.
-- [Custom variables](../variables/README.md#custom-environment-variables):
+- [Custom variables](../variables/README.md#custom-cicd-variables):
You can define their values in the `.gitlab-ci.yml` file, in the GitLab UI,
- or by using the API.
+ or by using the API. You can also input variables in the GitLab UI when
+ [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
- [Predefined variables](../variables/predefined_variables.md):
These values are set by the runner itself.
One example is `CI_COMMIT_REF_NAME`, which is the branch or tag the project is built for.
@@ -4297,13 +4326,27 @@ meaning it applies to all jobs. If you define a variable in a job, it's availabl
to that job only.
If a variable of the same name is defined globally and for a specific job, the
-[job-specific variable is used](../variables/README.md#priority-of-environment-variables).
+[job-specific variable overrides the global variable](../variables/README.md#priority-of-cicd-variables).
All YAML-defined variables are also set to any linked
[Docker service containers](../docker/using_docker_images.md#what-is-a-service).
You can use [YAML anchors for variables](#yaml-anchors-for-variables).
+### Prefill variables in manual pipelines
+
+> [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) GitLab 13.7.
+
+You can use the `value` and `description` keywords to define [variables that are prefilled](../pipelines/index.md#prefill-variables-in-manual-pipelines)
+when [running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually):
+
+```yaml
+variables:
+ DEPLOY_ENVIRONMENT:
+ value: "staging" # Deploy to staging by default
+ description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
+```
+
### Configure runner behavior with variables
You can use [CI/CD variables](../variables/README.md) to configure runner Git behavior:
@@ -4315,6 +4358,9 @@ You can use [CI/CD variables](../variables/README.md) to configure runner Git be
- [`GIT_FETCH_EXTRA_FLAGS`](../runners/README.md#git-fetch-extra-flags)
- [`GIT_DEPTH`](../runners/README.md#shallow-cloning) (shallow cloning)
- [`GIT_CLONE_PATH`](../runners/README.md#custom-build-directories) (custom build directories)
+- [`TRANSFER_METER_FREQUENCY`](../runners/README.md#artifact-and-cache-settings) (artifact/cache meter update frequency)
+- [`ARTIFACT_COMPRESSION_LEVEL`](../runners/README.md#artifact-and-cache-settings) (artifact archiver compression level)
+- [`CACHE_COMPRESSION_LEVEL`](../runners/README.md#artifact-and-cache-settings) (cache archiver compression level)
You can also use variables to configure how many times a runner
[attempts certain stages of job execution](../runners/README.md#job-stages-attempts).
@@ -4323,13 +4369,14 @@ You can also use variables to configure how many times a runner
It's possible to use special YAML features like anchors (`&`), aliases (`*`)
and map merging (`<<`). Use these features to reduce the complexity
-of `.gitlab-ci.yml`.
+of the code in the `.gitlab-ci.yml` file.
Read more about the various [YAML features](https://learnxinyminutes.com/docs/yaml/).
In most cases, the [`extends` keyword](#extends) is more user friendly and should
-be used over these special YAML features. YAML anchors may still
-need to be used to merge arrays.
+be used over these special YAML features.
+
+You can use YAML anchors to merge YAML arrays.
### Anchors
@@ -4349,26 +4396,26 @@ The following example uses anchors and map merging. It creates two jobs,
with their own custom `script` defined:
```yaml
-.job_template: &job_definition # Hidden key that defines an anchor named 'job_definition'
+.job_template: &job_configuration # Hidden yaml configuration that defines an anchor named 'job_configuration'
image: ruby:2.6
services:
- postgres
- redis
test1:
- <<: *job_definition # Merge the contents of the 'job_definition' alias
+ <<: *job_configuration # Merge the contents of the 'job_configuration' alias
script:
- test1 project
test2:
- <<: *job_definition # Merge the contents of the 'job_definition' alias
+ <<: *job_configuration # Merge the contents of the 'job_configuration' alias
script:
- test2 project
```
-`&` sets up the name of the anchor (`job_definition`), `<<` means "merge the
+`&` sets up the name of the anchor (`job_configuration`), `<<` means "merge the
given hash into the current one", and `*` includes the named anchor
-(`job_definition` again). The expanded version of the example above is:
+(`job_configuration` again). The expanded version of the example above is:
```yaml
.job_template:
@@ -4399,31 +4446,31 @@ and `test:mysql` share the `script` defined in `.job_template`, but use differen
`services`, defined in `.postgres_services` and `.mysql_services`:
```yaml
-.job_template: &job_definition
+.job_template: &job_configuration
script:
- test project
tags:
- dev
.postgres_services:
- services: &postgres_definition
+ services: &postgres_configuration
- postgres
- ruby
.mysql_services:
- services: &mysql_definition
+ services: &mysql_configuration
- mysql
- ruby
test:postgres:
- <<: *job_definition
- services: *postgres_definition
+ <<: *job_configuration
+ services: *postgres_configuration
tags:
- postgres
test:mysql:
- <<: *job_definition
- services: *mysql_definition
+ <<: *job_configuration
+ services: *mysql_configuration
```
The expanded version is:
@@ -4465,7 +4512,7 @@ test:mysql:
```
You can see that the hidden jobs are conveniently used as templates, and
-`tags: [dev]` has been overwritten by `tags: [postgres]`.
+`tags: [postgres]` overwrites `tags: [dev]`.
#### YAML anchors for scripts
@@ -4475,28 +4522,37 @@ You can use [YAML anchors](#anchors) with [script](#script), [`before_script`](#
and [`after_script`](#after_script) to use predefined commands in multiple jobs:
```yaml
-.some-script: &some-script
- - echo "Execute this script in `before_script` sections"
-
.some-script-before: &some-script-before
- - echo "Execute this script in `script` sections"
+ - echo "Execute this script first"
+
+.some-script: &some-script
+ - echo "Execute this script second"
+ - echo "Execute this script too"
.some-script-after: &some-script-after
- - echo "Execute this script in `after_script` sections"
+ - echo "Execute this script last"
-job_name:
+job1:
before_script:
- *some-script-before
script:
- *some-script
+ - echo "Execute something, for this job only"
after_script:
- *some-script-after
+
+job2:
+ script:
+ - *some-script-before
+ - *some-script
+ - echo "Execute something else, for this job only"
+ - *some-script-after
```
#### YAML anchors for variables
-[YAML anchors](#anchors) can be used with `variables`, to repeat assignment
-of variables across multiple jobs. Use can also use YAML anchors when a job
+Use [YAML anchors](#anchors) with `variables` to repeat assignment
+of variables across multiple jobs. You can also use YAML anchors when a job
requires a specific `variables` block that would otherwise override the global variables.
In the example below, we override the `GIT_STRATEGY` variable without affecting
@@ -4541,6 +4597,68 @@ Use this feature to ignore jobs, or use the
[special YAML features](#special-yaml-features) and transform the hidden jobs
into templates.
+### `!reference` tags
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/266173) in GitLab 13.9.
+
+Use the `!reference` custom YAML tag to select keyword configuration from other job
+sections and reuse it in the current section. Unlike [YAML anchors](#anchors), you can
+use `!reference` tags to reuse configuration from [included](#include) configuration
+files as well.
+
+In this example, a `script` and an `after_script` from two different locations are
+reused in the `test` job:
+
+- `setup.yml`:
+
+ ```yaml
+ .setup:
+ script:
+ - echo creating environment
+ ```
+
+- `.gitlab-ci.yml`:
+
+ ```yaml
+ include:
+ - local: setup.yml
+
+ .teardown:
+ after_script:
+ - echo deleting environment
+
+ test:
+ script:
+ - !reference [.setup, script]
+ - echo running my own command
+ after_script:
+ - !reference [.teardown, after_script]
+ ```
+
+In this example, `test-vars-1` reuses the all the variables in `.vars`, while `test-vars-2`
+selects a specific variable and reuses it as a new `MY_VAR` variable.
+
+```yaml
+.vars:
+ variables:
+ URL: "http://my-url.internal"
+ IMPORTANT_VAR: "the details"
+
+test-vars-1:
+ variables: !reference [.vars, variables]
+ script:
+ - printenv
+
+test-vars-2:
+ variables:
+ MY_VAR: !reference [.vars, variables, IMPORTANT_VAR]
+ script:
+ - printenv
+```
+
+You can't reuse a section that already includes a `!reference` tag. Only one level
+of nesting is supported.
+
## Skip Pipeline
To push a commit without triggering a pipeline, add `[ci skip]` or `[skip ci]`, using any
diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md
index e4ede9cf699..765b982dbeb 100644
--- a/doc/ci/yaml/gitlab_ci_yaml.md
+++ b/doc/ci/yaml/gitlab_ci_yaml.md
@@ -5,7 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
<!-- markdownlint-disable MD044 -->
+<!-- vale gitlab.Spelling = NO -->
# The .gitlab-ci.yml file
+<!-- vale gitlab.Spelling = YES -->
<!-- markdownlint-enable MD044 -->
To use GitLab CI/CD, you need:
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index 2d26d9f8922..5750fe1ba61 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -121,7 +121,7 @@ job:
- echo -e "\e[31mThis text is red,\e[0m but this text isn't\e[31m however this text is red again."
```
-You can define the color codes in Shell variables, or even [custom environment variables](../variables/README.md#custom-environment-variables),
+You can define the color codes in Shell variables, or even [custom environment variables](../variables/README.md#custom-cicd-variables),
which makes the commands easier to read and reusable.
For example, using the same example as above and variables defined in a `before_script`:
diff --git a/doc/customization/branded_login_page.md b/doc/customization/branded_login_page.md
deleted file mode 100644
index cf593f360c8..00000000000
--- a/doc/customization/branded_login_page.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md#sign-in--sign-up-pages'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md#sign-in--sign-up-pages).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/branded_page_and_email_header.md b/doc/customization/branded_page_and_email_header.md
deleted file mode 100644
index 21a69178b6d..00000000000
--- a/doc/customization/branded_page_and_email_header.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md#navigation-bar'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md#navigation-bar).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/favicon.md b/doc/customization/favicon.md
deleted file mode 100644
index 3d6c2f62b25..00000000000
--- a/doc/customization/favicon.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md#favicon'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md#favicon).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/help_message.md b/doc/customization/help_message.md
deleted file mode 100644
index 3f13e4efdbd..00000000000
--- a/doc/customization/help_message.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/settings/help_page.md'
----
-
-This document was moved to [another location](../user/admin_area/settings/help_page.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/index.md b/doc/customization/index.md
deleted file mode 100644
index 3c88ad8106b..00000000000
--- a/doc/customization/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/issue_and_merge_request_template.md b/doc/customization/issue_and_merge_request_template.md
deleted file mode 100644
index 0b4ca009080..00000000000
--- a/doc/customization/issue_and_merge_request_template.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/project/description_templates.md'
----
-
-This document was moved to [description_templates](../user/project/description_templates.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/issue_closing.md b/doc/customization/issue_closing.md
deleted file mode 100644
index c860f51dc2f..00000000000
--- a/doc/customization/issue_closing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/project/issues/managing_issues.md#closing-issues-automatically'
----
-
-This document was moved to [another location](../user/project/issues/managing_issues.md#closing-issues-automatically).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md
deleted file mode 100644
index affb6211377..00000000000
--- a/doc/customization/libravatar.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/libravatar.md'
----
-
-This document was moved to [another location](../administration/libravatar.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/new_project_page.md b/doc/customization/new_project_page.md
deleted file mode 100644
index 82549d62960..00000000000
--- a/doc/customization/new_project_page.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md#new-project-pages'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md#new-project-pages).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/system_header_and_footer_messages.md b/doc/customization/system_header_and_footer_messages.md
deleted file mode 100644
index 03dccfb35c9..00000000000
--- a/doc/customization/system_header_and_footer_messages.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md#system-header-and-footer-messages'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md#system-header-and-footer-messages).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/customization/welcome_message.md b/doc/customization/welcome_message.md
deleted file mode 100644
index cf593f360c8..00000000000
--- a/doc/customization/welcome_message.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/appearance.md#sign-in--sign-up-pages'
----
-
-This document was moved to [another location](../user/admin_area/appearance.md#sign-in--sign-up-pages).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/README.md b/doc/development/README.md
index 0d3c1b3cbe9..3d5335feb11 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -121,6 +121,7 @@ In these cases, use the following workflow:
- [User Experience (UX)](https://about.gitlab.com/handbook/engineering/ux/)
- [Security](https://about.gitlab.com/handbook/engineering/security/)
- [Quality](https://about.gitlab.com/handbook/engineering/quality/)
+ - [Engineering Productivity](https://about.gitlab.com/handbook/engineering/quality/engineering-productivity-team/)
- [Infrastructure](https://about.gitlab.com/handbook/engineering/infrastructure/)
- [Technical Writing](https://about.gitlab.com/handbook/engineering/ux/technical-writing/)
@@ -151,6 +152,7 @@ In these cases, use the following workflow:
## Backend guides
+- [Directory structure](directory_structure.md)
- [GitLab utilities](utilities.md)
- [Issuable-like Rails models](issuable-like-models.md)
- [Logging](logging.md)
@@ -229,7 +231,7 @@ See [database guidelines](database/index.md).
- [Security Scanners](integrations/secure.md)
- [Secure Partner Integration](integrations/secure_partner_integration.md)
- [How to run Jenkins in development environment](integrations/jenkins.md)
-- [How to run local Codesandbox integration for Web IDE Live Preview](integrations/codesandbox.md)
+- [How to run local `Codesandbox` integration for Web IDE Live Preview](integrations/codesandbox.md)
## Testing guides
@@ -293,6 +295,7 @@ See [database guidelines](database/index.md).
- [Compatibility with multiple versions of the application running at the same time](multi_version_compatibility.md)
- [Features inside `.gitlab/`](features_inside_dot_gitlab.md)
- [Dashboards for stage groups](stage_group_dashboards.md)
+- [Preventing transient bugs](transient/prevention-patterns.md)
## Other GitLab Development Kit (GDK) guides
diff --git a/doc/development/adding_service_component.md b/doc/development/adding_service_component.md
index 7e2add2c91f..f3e23906ac6 100644
--- a/doc/development/adding_service_component.md
+++ b/doc/development/adding_service_component.md
@@ -65,7 +65,7 @@ Notify the [Distribution team](https://about.gitlab.com/handbook/engineering/dev
New services to be bundled with GitLab need to be available in the following environments.
-**Dev environment**
+**Development environment**
The first step of bundling a new service is to provide it in the development environment to engage in collaboration and feedback.
diff --git a/doc/development/agent/gitops.md b/doc/development/agent/gitops.md
index 8c8586326fa..f183ba86aa1 100644
--- a/doc/development/agent/gitops.md
+++ b/doc/development/agent/gitops.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/#designated-technical-writers
---
-# GitOps with the Kubernetes Agent **(PREMIUM ONLY)**
+# GitOps with the Kubernetes Agent **(PREMIUM SELF)**
The [GitLab Kubernetes Agent](../../user/clusters/agent/index.md) supports the
[pull-based version](https://www.gitops.tech/#pull-based-deployments) of
diff --git a/doc/development/agent/identity.md b/doc/development/agent/identity.md
index 884ce015a02..49d20d2fd87 100644
--- a/doc/development/agent/identity.md
+++ b/doc/development/agent/identity.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/#designated-technical-writers
---
-# Kubernetes Agent identity and authentication **(PREMIUM ONLY)**
+# Kubernetes Agent identity and authentication **(PREMIUM SELF)**
This page uses the word `agent` to describe the concept of the
GitLab Kubernetes Agent. The program that implements the concept is called `agentk`.
diff --git a/doc/development/agent/index.md b/doc/development/agent/index.md
index 95661c8ddbd..112162f8f90 100644
--- a/doc/development/agent/index.md
+++ b/doc/development/agent/index.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/#designated-technical-writers
---
-# Kubernetes Agent development **(PREMIUM ONLY)**
+# Kubernetes Agent development **(PREMIUM SELF)**
This page contains developer-specific information about the GitLab Kubernetes Agent.
[End-user documentation about the GitLab Kubernetes Agent](../../user/clusters/agent/index.md)
diff --git a/doc/development/agent/local.md b/doc/development/agent/local.md
index 47246a6a6d3..603364567bf 100644
--- a/doc/development/agent/local.md
+++ b/doc/development/agent/local.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/#designated-technical-writers
---
-# Run the Kubernetes Agent locally **(PREMIUM ONLY)**
+# Run the Kubernetes Agent locally **(PREMIUM SELF)**
You can run `kas` and `agentk` locally to test the [Kubernetes Agent](index.md) yourself.
diff --git a/doc/development/agent/repository_overview.md b/doc/development/agent/repository_overview.md
new file mode 100644
index 00000000000..b9eea286a3e
--- /dev/null
+++ b/doc/development/agent/repository_overview.md
@@ -0,0 +1,98 @@
+---
+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/#designated-technical-writers
+---
+
+# Kubernetes Agent repository overview **(PREMIUM SELF)**
+
+This page describes the subfolders of the Kubernetes Agent repository.
+[Development information](index.md) and
+[end-user documentation](../../user/clusters/agent/index.md) are both available.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a video overview, see
+[GitLab Kubernetes Agent repository overview](https://www.youtube.com/watch?v=j8CyaCWroUY).
+
+## `build`
+
+Various files for the build process.
+
+### `build/deployment`
+
+A [`kpt`](https://googlecontainertools.github.io/kpt/) package that bundles some
+[Kustomize](https://kustomize.io/) layers and components. Can be used as-is, or
+to create a custom package to install `agentk`.
+
+## `cmd`
+
+Commands are binaries that this repository produces. They are:
+
+- `kas` is the GitLab Kubernetes Agent Server binary.
+- `agentk` is the GitLab Kubernetes Agent binary.
+
+Each of these directories contain application bootstrap code for:
+
+- Reading configuration.
+- Applying defaults to it.
+- Constructing the dependency graph of objects that constitute the program.
+- Running it.
+
+### `cmd/agentk`
+
+- `agentk` initialization logic.
+- Implementation of the agent modules API.
+
+### `cmd/kas`
+
+- `kas` initialization logic.
+- Implementation of the server modules API.
+
+## `examples`
+
+Git submodules for the example projects.
+
+## `internal`
+
+The main code of both `gitlab-kas` and `agentk`, and various supporting building blocks.
+
+### `internal/api`
+
+Structs that represent some important pieces of data.
+
+### `internal/gitaly`
+
+Items to work with [Gitaly](../../administration/gitaly/index.md).
+
+### `internal/gitlab`
+
+GitLab REST client.
+
+### `internal/module`
+
+Modules that implement server and agent-side functionality.
+
+### `internal/tool`
+
+Various building blocks. `internal/tool/testing` contains mocks and helpers
+for testing. Mocks are generated with [`gomock`](https://pkg.go.dev/github.com/golang/mock).
+
+## `it`
+
+Contains scaffolding for integration tests. Unused at the moment.
+
+## `pkg`
+
+Contains exported packages.
+
+### `pkg/agentcfg`
+
+Contains protobuf definitions of the `agentk` configuration file. Used to configure
+the agent through a configuration repository.
+
+### `pkg/kascfg`
+
+Contains protobuf definitions of the `gitlab-kas` configuration file. Contains an
+example of that configuration file along with the test for it. The test ensures
+the configuration file example is in sync with the protobuf definitions of the
+file and defaults, which are applied when the file is loaded.
diff --git a/doc/development/agent/routing.md b/doc/development/agent/routing.md
index 43cc78ccdfb..9a7d6422d47 100644
--- a/doc/development/agent/routing.md
+++ b/doc/development/agent/routing.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/#designated-technical-writers
---
-# Routing `kas` requests in the Kubernetes Agent **(PREMIUM ONLY)**
+# Routing `kas` requests in the Kubernetes Agent **(PREMIUM SELF)**
This document describes how `kas` routes requests to concrete `agentk` instances.
GitLab must talk to GitLab Kubernetes Agent Server (`kas`) to:
@@ -134,90 +134,97 @@ of the `kas` receiving the request from the _external_ endpoint to retry and re-
requests. This method ensures a single central component for each request can determine
how a request is routed, rather than distributing the decision across several `kas` instances.
-### API definitions
+### Reverse gRPC tunnel
+
+This section explains how the `agentk` -> `kas` reverse gRPC tunnel is implemented.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a video overview of how some of the blocks map to code, see
+[GitLab Kubernetes Agent reverse gRPC tunnel architecture and code overview
+](https://www.youtube.com/watch?v=9pnQF76hyZc).
+
+#### High level schema
+
+In this example, `Server side of module A` exposes its API to get the `Pod` list
+on the `Public API gRPC server`. When it receives a request, it must determine
+the agent ID from it, then call the proxying code which forwards the request to
+a suitable `agentk` that can handle it.
+
+The `Agent side of module A` exposes the same API on the `Internal gRPC server`.
+When it receives the request, it needs to handle it (such as retrieving and returning
+the `Pod` list).
+
+This schema describes how reverse tunneling is handled fully transparently
+for modules, so you can add new features:
+
+```mermaid
+graph TB
+ subgraph kas
+ server-internal-grpc-server[Internal gRPC server]
+ server-api-grpc-server[Public API gRPC server]
+ server-module-a[Server side of module A]
+ server-module-b[Server side of module B]
+ end
+ subgraph agentk
+ agent-internal-grpc-server[Internal gRPC server]
+ agent-module-a[Agent side of module A]
+ agent-module-b[Agent side of module B]
+ end
+
+ agent-internal-grpc-server -- request --> agent-module-a
+ agent-internal-grpc-server -- request --> agent-module-b
+
+ server-module-a-. expose API on .-> server-internal-grpc-server
+ server-module-b-. expose API on .-> server-api-grpc-server
+
+ server-internal-grpc-server -- proxy request --> agent-internal-grpc-server
+ server-api-grpc-server -- proxy request --> agent-internal-grpc-server
+```
+
+#### Implementation schema
+
+`HandleTunnelConnection()` is called with the server-side interface of the reverse
+tunnel. It registers the connection and blocks, waiting for a request to proxy
+through the connection.
+
+`HandleIncomingConnection()` is called with the server-side interface of the incoming
+connection. It registers the connection and blocks, waiting for a matching tunnel
+to proxy the connection through.
+
+After it has two connections that match, `Connection registry` starts bi-directional
+data streaming:
-```proto
-syntax = "proto3";
-
-import "google/protobuf/timestamp.proto";
-
-message KasAddress {
- string ip = 1;
- uint32 port = 2;
-}
-
-message ConnectedAgentInfo {
- // Agent id.
- int64 id = 1;
- // Identifies a particular agentk->kas connection. Randomly generated when agent connects.
- int64 connection_id = 2;
- string version = 3;
- string commit = 4;
- // Pod namespace.
- string pod_namespace = 5;
- // Pod name.
- string pod_name = 6;
- // When the connection was established.
- google.protobuf.Timestamp connected_at = 7;
- KasAddress kas_address = 8;
- // What else do we need?
-}
-
-message KasInstanceInfo {
- string version = 1;
- string commit = 2;
- KasAddress address = 3;
- // What else do we need?
-}
-
-message ConnectedAgentsForProjectRequest {
- int64 project_id = 1;
-}
-
-message ConnectedAgentsForProjectResponse {
- // There may 0 or more agents with the same id, depending on the number of running Pods.
- repeated ConnectedAgentInfo agents = 1;
-}
-
-message ConnectedAgentsByIdRequest {
- int64 agent_id = 1;
-}
-
-message ConnectedAgentsByIdResponse {
- repeated ConnectedAgentInfo agents = 1;
-}
-
-// API for use by GitLab.
-service KasApi {
- // Connected agents for a particular configuration project.
- rpc ConnectedAgentsForProject (ConnectedAgentsForProjectRequest) returns (ConnectedAgentsForProjectResponse) {
- }
- // Connected agents for a particular agent id.
- rpc ConnectedAgentsById (ConnectedAgentsByIdRequest) returns (ConnectedAgentsByIdResponse) {
- }
- // Depends on the need, but here is the call from the example above.
- rpc GetPods (GetPodsRequest) returns (GetPodsResponse) {
- }
-}
-
-message Pod {
- string namespace = 1;
- string name = 2;
-}
-
-message GetPodsRequest {
- int64 agent_id = 1;
- int64 connection_id = 2;
-}
-
-message GetPodsResponse {
- repeated Pod pods = 1;
-}
-
-// Internal API for use by kas for kas -> kas calls.
-service KasInternal {
- // Depends on the need, but here is the call from the example above.
- rpc GetPods (GetPodsRequest) returns (GetPodsResponse) {
- }
-}
+```mermaid
+graph TB
+ subgraph kas
+ server-tunnel-module[Server tunnel module]
+ connection-registry[Connection registry]
+ server-internal-grpc-server[Internal gRPC server]
+ server-api-grpc-server[Public API gRPC server]
+ server-module-a[Server side of module A]
+ server-module-b[Server side of module B]
+ end
+ subgraph agentk
+ agent-internal-grpc-server[Internal gRPC server]
+ agent-tunnel-module[Agent tunnel module]
+ agent-module-a[Agent side of module A]
+ agent-module-b[Agent side of module B]
+ end
+
+ server-tunnel-module -- "HandleTunnelConnection()" --> connection-registry
+ server-internal-grpc-server -- "HandleIncomingConnection()" --> connection-registry
+ server-api-grpc-server -- "HandleIncomingConnection()" --> connection-registry
+ server-module-a-. expose API on .-> server-internal-grpc-server
+ server-module-b-. expose API on .-> server-api-grpc-server
+
+ agent-tunnel-module -- "establish tunnel, receive request" --> server-tunnel-module
+ agent-tunnel-module -- make request --> agent-internal-grpc-server
+ agent-internal-grpc-server -- request --> agent-module-a
+ agent-internal-grpc-server -- request --> agent-module-b
```
+
+### API definitions
+
+- [`agent_tracker/agent_tracker.proto`](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/agent_tracker/agent_tracker.proto)
+- [`agent_tracker/rpc/rpc.proto`](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/agent_tracker/rpc/rpc.proto)
+- [`reverse_tunnel/rpc/rpc.proto`](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/reverse_tunnel/rpc/rpc.proto)
diff --git a/doc/development/agent/user_stories.md b/doc/development/agent/user_stories.md
index 2929573ffd3..609be47a3cb 100644
--- a/doc/development/agent/user_stories.md
+++ b/doc/development/agent/user_stories.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/#designated-technical-writers
---
-# Kubernetes Agent user stories **(PREMIUM ONLY)**
+# Kubernetes Agent user stories **(PREMIUM SELF)**
The [personas in action](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#user-personas)
for the Kubernetes Agent are:
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index d73c3a8d6f6..85098689392 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -10,7 +10,10 @@ This document outlines the style guide for the GitLab [GraphQL API](../api/graph
## How GitLab implements GraphQL
+<!-- vale gitlab.Spelling = NO -->
We use the [GraphQL Ruby gem](https://graphql-ruby.org/) written by [Robert Mosolgo](https://github.com/rmosolgo/).
+<!-- vale gitlab.Spelling = YES -->
+In addition, we have a subscription to [GraphQL Pro](https://www.graphql.pro). For details see [GraphQL Pro subscription](graphql_guide/graphql_pro.md).
All GraphQL queries are directed to a single endpoint
([`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/blob/master/app%2Fcontrollers%2Fgraphql_controller.rb)),
@@ -21,6 +24,7 @@ which is exposed as an API endpoint at `/api/graphql`.
In March 2019, Nick Thomas hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
on the GitLab [GraphQL API](../api/graphql/index.md) to share his domain specific knowledge
with anyone who may work in this part of the codebase in the future. You can find the
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
[recording on YouTube](https://www.youtube.com/watch?v=-9L_1MWrjkg), and the slides on
[Google Slides](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit)
and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/8e78ea7f326b2ef649e7d7d569c26d56/GraphQL_Deep_Dive__Create_.pdf).
@@ -42,6 +46,36 @@ can be shared.
It's also possible to add a `private_token` to the query string, or
add a `HTTP_PRIVATE_TOKEN` header.
+## Limits
+
+Several limits apply to the GraphQL API and some of these can be overridden
+by developers.
+
+### Max page size
+
+By default, [connections](#connection-types) can only return
+at most a maximum number of records defined in
+[`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb)
+per page.
+
+Developers can [specify a custom max page size](#page-size-limit) when defining
+a connection.
+
+### Max complexity
+
+Complexity is explained [on our client-facing API page](../api/graphql/index.md#max-query-complexity).
+
+Fields default to adding `1` to a query's complexity score, but developers can
+[specify a custom complexity](#field-complexity) when defining a field.
+
+To estimate the complexity of a query, you can run the
+[`gitlab:graphql:analyze`](rake_tasks.md#analyze-graphql-queries)
+Rake task.
+
+### Request timeout
+
+Requests time out at 30 seconds.
+
## Global IDs
The GitLab GraphQL API uses Global IDs (i.e: `"gid://gitlab/MyObject/123"`)
@@ -281,6 +315,61 @@ Use the functionality the framework provides unless there is a compelling reason
For example, instead of `latest_pipeline`, use `pipelines(last: 1)`.
+#### Page size limit
+
+By default, the API returns at most a maximum number of records defined in
+[`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb)
+per page within a connection and this will also be the default number of records
+returned per page if no limiting arguments (`first:` or `last:`) are provided by a client.
+
+The `max_page_size` argument can be used to specify a different page size limit
+for a connection.
+
+WARNING:
+It's better to change the frontend client, or product requirements, to not need large amounts of
+records per page than it is to raise the `max_page_size`, as the default is set to ensure
+the GraphQL API remains performant.
+
+For example:
+
+```ruby
+field :tags,
+ Types::ContainerRepositoryTagType.connection_type,
+ null: true,
+ description: 'Tags of the container repository',
+ max_page_size: 20
+```
+
+### Field complexity
+
+The GitLab GraphQL API uses a _complexity_ score to limit performing overly complex queries.
+Complexity is described in [our client documentation](../api/graphql/index.md#max-query-complexity) on the topic.
+
+Complexity limits are defined in [`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb).
+
+By default, fields will add `1` to a query's complexity score. This can be overridden by
+[providing a custom `complexity`](https://graphql-ruby.org/queries/complexity_and_depth.html) value for a field.
+
+Developers should specify higher complexity for fields that cause more _work_ to be performed
+by the server in order to return data. Fields that represent data that can be returned
+with little-to-no _work_, for example in most cases; `id` or `title`, can be given a complexity of `0`.
+
+### `calls_gitaly`
+
+Fields that have the potential to perform a [Gitaly](../administration/gitaly/index.md) call when resolving _must_ be marked as
+such by passing `calls_gitaly: true` to `field` when defining it.
+
+For example:
+
+```ruby
+field :blob, type: Types::Snippets::BlobType,
+ description: 'Snippet blob',
+ null: false,
+ calls_gitaly: true
+```
+
+This will increment the [`complexity` score](#field-complexity) of the field by `1`.
+
### Exposing permissions for a type
To expose permissions the current user has on a resource, you can call
@@ -1599,7 +1688,7 @@ full stack:
- An argument or scalar's [`prepare`](#validating-arguments) applies correctly.
- Logic in a resolver or mutation's [`#ready?` method](#correct-use-of-resolverready) applies correctly.
- An [argument's `default_value`](https://graphql-ruby.org/fields/arguments.html) applies correctly.
-- Objects resolve performantly and there are no N+1 issues.
+- Objects resolve successfully, and there are no N+1 issues.
When adding a query, you can use the `a working graphql query` shared example to test if the query
renders valid results.
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index b2c93f16770..dd43281da6d 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -28,7 +28,7 @@ See the [Documentation Style Guide RESTful API page](documentation/restful_api_s
## Methods and parameters description
Every method must be described using the [Grape DSL](https://github.com/ruby-grape/grape#describing-methods)
-(see <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb>
+(see [`environments.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/environments.rb)
for a good example):
- `desc` for the method summary. You should pass it a block for additional
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index c661ff3f617..3608636dd55 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+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
---
diff --git a/doc/development/approval_rules.md b/doc/development/approval_rules.md
index 542bce1cb97..368987eb85f 100644
--- a/doc/development/approval_rules.md
+++ b/doc/development/approval_rules.md
@@ -4,7 +4,7 @@ group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Approval Rules **(STARTER)**
+# Approval Rules development guide **(FREE)**
This document explains the backend design and flow of all related functionality
about [merge request approval rules](../user/project/merge_requests/merge_request_approvals.md).
@@ -44,8 +44,8 @@ erDiagram
### `Project` and `MergeRequest`
`Project` and `MergeRequest` models are defined in `ee/app/models/ee/project.rb`
-and `ee/app/models/ee/merge_request.rb`. They extend the non-EE versions since
-approval rules is an EE only feature. Associations and other related stuff to
+and `ee/app/models/ee/merge_request.rb`. They extend the non-EE versions, because
+approval rules are an EE-only feature. Associations and other related stuff to
merge request approvals are defined here.
### `ApprovalState`
@@ -265,8 +265,8 @@ graph LR
ApprovalWrappedRule --> Approval
```
-This flow gets initiated by the frontend component. The data returned will
-then be used to display information on the MR widget.
+This flow gets initiated by the frontend component. The data returned is
+used to display information on the MR widget.
### Approving a merge request
@@ -282,5 +282,5 @@ is executed instead.
## TODO
-1. Add information related to other rule types (e.g. `code_owner` and `report_approver`).
+1. Add information related to other rule types, such as `code_owner` and `report_approver`.
1. Add information about side effects of approving/unapproving merge request.
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index f8ab97de848..69055131ae8 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -91,6 +91,8 @@ The simplest way to ensure this, is to add support for your feature or service t
[the official GitLab Helm chart](https://docs.gitlab.com/charts/) or reach out to
[the Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution).
+Refer to the [process for adding new service components](adding_service_component.md) for more details.
+
### Simplified component overview
This is a simplified architecture diagram that can be used to
@@ -225,52 +227,54 @@ Component statuses are linked to configuration documentation for each component.
Table description links:
- [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)
-| Component | Description | Omnibus GitLab | GitLab chart | Minikube Minimal | GitLab.com | Source | GDK | CE/EE |
-|-------------------------------------------------------|----------------------------------------------------------------------|:--------------:|:------------:|:----------------:|:----------:|:------:|:---:|:-------:|
-| [Certificate Management](#certificate-management) | TLS Settings, Let's Encrypt | ✅ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE & EE |
-| [Consul](#consul) | Database node discovery, failover | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
-| [Database Migrations](#database-migrations) | Database migrations | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
-| [Elasticsearch](#elasticsearch) | Improved search within GitLab | ⤓ | ⤓ | ⤓ | ✅ | ⤓ | ⤓ | EE Only |
-| [Gitaly](#gitaly) | Git RPC service for handling all Git calls made by GitLab | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
-| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
-| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ⌠| ✅ | ⌠| ⚙ | EE Only |
-| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy Helm, Ingress, Cert-Manager, Prometheus, GitLab Runner, JupyterHub, or Knative to a cluster | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
-| [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⌠| ⌠| ✅ | ⚙ | ⚙ | CE & EE |
-| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
-| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
-| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | ✅ | ⚙ | ⤓ | ✅ | ⌠| ⌠| CE & EE |
-| [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | ⌠| ⚙ | ⌠| ⌠| ⤓ | ⚙ | CE & EE |
-| [GitLab self-monitoring: Prometheus](#prometheus) | Time-series database, metrics collection, and query service | ✅ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
-| [GitLab self-monitoring: Sentry](#sentry) | Track errors generated by the GitLab instance | ⤓ | ⤓ | ⌠| ✅ | ⤓ | ⤓ | CE & EE |
-| [GitLab Shell](#gitlab-shell) | Handles `git` over SSH sessions | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
-| [GitLab Workhorse](#gitlab-workhorse) | Smart reverse proxy, handles large HTTP requests | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
-| [Inbound email (SMTP)](#inbound-email) | Receive messages to update issues | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE & EE |
-| [Jaeger integration](#jaeger) | Distributed tracing for deployed apps | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | EE Only |
-| [LDAP Authentication](#ldap-authentication) | Authenticate users against centralized LDAP directory | ⤓ | ⤓ | ⤓ | ⌠| ⤓ | ⤓ | CE & EE |
-| [Mattermost](#mattermost) | Open-source Slack alternative | ⚙ | ⤓ | ⤓ | ⤓ | ⌠| ⌠| CE & EE |
-| [MinIO](#minio) | Object storage service | ⤓ | ✅ | ✅ | ✅ | ⌠| ⚙ | CE & EE |
-| [NGINX](#nginx) | Routes requests to appropriate components, terminates SSL | ✅ | ✅ | ⚙ | ✅ | ⤓ | ⌠| CE & EE |
-| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | ✅ | N/A | N/A | ✅ | ⌠| ⌠| CE & EE |
-| [Outbound email (SMTP)](#outbound-email) | Send email messages to users | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE & EE |
-| [Patroni](#patroni) | Manage PostgreSQL HA cluster leader selection and replication | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
-| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| CE & EE |
-| [PgBouncer](#pgbouncer) | Database connection pooling, failover | ⚙ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
-| [PostgreSQL Exporter](#postgresql-exporter) | Prometheus endpoint with PostgreSQL metrics | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
-| [PostgreSQL](#postgresql) | Database | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE & EE |
-| [Praefect](#praefect) | A transparent proxy between any Git client and Gitaly storage nodes. | ✅ | ⚙ | ⌠| ✅ | ⚙ | ✅ | CE & EE |
-| [Redis Exporter](#redis-exporter) | Prometheus endpoint with Redis metrics | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
-| [Redis](#redis) | Caching service | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE & EE |
-| [Registry](#registry) | Container registry, allows pushing and pulling of images | ⚙ | ✅ | ✅ | ✅ | ⤓ | ⚙ | CE & EE |
-| [Runner](#gitlab-runner) | Executes GitLab CI/CD jobs | ⤓ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE & EE |
-| [Sentry integration](#sentry) | Error tracking for deployed apps | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
-| [Sidekiq](#sidekiq) | Background jobs processor | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | CE & EE |
-| [Puma (GitLab Rails)](#puma) | Handles requests for the web interface and API | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
+| Component | Description | Omnibus GitLab | GitLab Environment Toolkit (GET) | GitLab chart | Minikube Minimal | GitLab.com | Source | GDK | CE/EE |
+|-------------------------------------------------------|----------------------------------------------------------------------|:--------------:|:--------------:|:------------:|:----------------:|:----------:|:------:|:---:|:-------:|
+| [Certificate Management](#certificate-management) | TLS Settings, Let's Encrypt | ✅ | ✅ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE & EE |
+| [Consul](#consul) | Database node discovery, failover | ⚙ | ✅ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
+| [Database Migrations](#database-migrations) | Database migrations | ✅ | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
+| [Elasticsearch](#elasticsearch) | Improved search within GitLab | ⤓ | ⚙ | ⤓ | ⤓ | ✅ | ⤓ | ⤓ | EE Only |
+| [Gitaly](#gitaly) | Git RPC service for handling all Git calls made by GitLab | ✅ | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
+| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
+| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⌠| ⚙ | EE Only |
+| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
+| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy Helm, Ingress, Cert-Manager, Prometheus, GitLab Runner, JupyterHub, or Knative to a cluster | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
+| [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⚙ | ⚙ | CE & EE |
+| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
+| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ⚙ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
+| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | ✅ | ✅ | ⚙ | ⤓ | ✅ | ⌠| ⌠| CE & EE |
+| [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | ⌠| ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | CE & EE |
+| [GitLab self-monitoring: Prometheus](#prometheus) | Time-series database, metrics collection, and query service | ✅ | ✅ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
+| [GitLab self-monitoring: Sentry](#sentry) | Track errors generated by the GitLab instance | ⤓ | ⤓ | ⤓ | ⌠| ✅ | ⤓ | ⤓ | CE & EE |
+| [GitLab Shell](#gitlab-shell) | Handles `git` over SSH sessions | ✅ | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
+| [GitLab Workhorse](#gitlab-workhorse) | Smart reverse proxy, handles large HTTP requests | ✅ | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
+| [Inbound email (SMTP)](#inbound-email) | Receive messages to update issues | ⤓ | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE & EE |
+| [Jaeger integration](#jaeger) | Distributed tracing for deployed apps | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | EE Only |
+| [LDAP Authentication](#ldap-authentication) | Authenticate users against centralized LDAP directory | ⤓ | ⤓ | ⤓ | ⤓ | ⌠| ⤓ | ⤓ | CE & EE |
+| [Mattermost](#mattermost) | Open-source Slack alternative | ⚙ | ⚙ | ⤓ | ⤓ | ⤓ | ⌠| ⌠| CE & EE |
+| [MinIO](#minio) | Object storage service | ⤓ | ⤓ | ✅ | ✅ | ✅ | ⌠| ⚙ | CE & EE |
+| [NGINX](#nginx) | Routes requests to appropriate components, terminates SSL | ✅ | ✅ | ✅ | ⚙ | ✅ | ⤓ | ⌠| CE & EE |
+| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | ✅ | ✅ | N/A | N/A | ✅ | ⌠| ⌠| CE & EE |
+| [Outbound email (SMTP)](#outbound-email) | Send email messages to users | ⤓ | ⤓ | ⚙ | ⤓ | ✅ | ⤓ | ⤓ | CE & EE |
+| [Patroni](#patroni) | Manage PostgreSQL HA cluster leader selection and replication | ⚙ | ✅ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
+| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | ⚙ | ✅ | ⌠| ⌠| ✅ | ⌠| ⌠| CE & EE |
+| [PgBouncer](#pgbouncer) | Database connection pooling, failover | ⚙ | ✅ | ⌠| ⌠| ✅ | ⌠| ⌠| EE Only |
+| [PostgreSQL Exporter](#postgresql-exporter) | Prometheus endpoint with PostgreSQL metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
+| [PostgreSQL](#postgresql) | Database | ✅ | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE & EE |
+| [Praefect](#praefect) | A transparent proxy between any Git client and Gitaly storage nodes. | ✅ | ✅ | ⚙ | ⌠| ✅ | ⚙ | ✅ | CE & EE |
+| [Puma (GitLab Rails)](#puma) | Handles requests for the web interface and API | ✅ | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
+| [Redis Exporter](#redis-exporter) | Prometheus endpoint with Redis metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
+| [Redis](#redis) | Caching service | ✅ | ✅ | ✅ | ✅ | ✅ | ⤓ | ✅ | CE & EE |
+| [Registry](#registry) | Container registry, allows pushing and pulling of images | ⚙ | ⚙ | ✅ | ✅ | ✅ | ⤓ | ⚙ | CE & EE |
+| [Runner](#gitlab-runner) | Executes GitLab CI/CD jobs | ⤓ | ⤓ | ✅ | ⚙ | ✅ | ⚙ | ⚙ | CE & EE |
+| [Sentry integration](#sentry) | Error tracking for deployed apps | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
+| [Sidekiq](#sidekiq) | Background jobs processor | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | CE & EE |
### Component details
@@ -934,7 +938,7 @@ ps aux | grep '^git'
```
GitLab has several components to operate. It requires a persistent database
-(PostgreSQL) and Redis database, and uses Apache `httpd` or NGINX to proxypass
+(PostgreSQL) and Redis database, and uses Apache `httpd` or NGINX to `proxypass`
Puma. All these components should run as different system users to GitLab
(for example, `postgres`, `redis`, and `www-data`, instead of `git`).
diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md
index c457573b87a..eaf1d712f17 100644
--- a/doc/development/auto_devops.md
+++ b/doc/development/auto_devops.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
---
-# Auto DevOps development guide
+# Auto DevOps development guide **(FREE)**
This document provides a development guide for contributors to
[Auto DevOps](../topics/autodevops/index.md).
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 8fad32ed163..f2c8aa4db62 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -45,7 +45,7 @@ the `author` field. GitLab team members **should not**.
**must** have a changelog entry, without `merge_request` value
and with `type` set to `security`.
- Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content.
-- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry.
+- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. This includes modifying complexity of GraphQL fields.
- Performance improvements **should** have a changelog entry.
- Changes that need to be documented in the Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary)
also require a changelog entry.
@@ -168,6 +168,7 @@ type:
| [`--dry-run`](#--dry-run-or--n) | `-n` | Don't actually write anything, just print |
| [`--git-username`](#--git-username-or--u) | `-u` | Use Git user.name configuration as the author |
| [`--type`](#--type-or--t) | `-t` | The category of the change, valid options are: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`, `performance`, `other` |
+| [`--ee`](#how-to-generate-a-changelog-entry) | | Create an EE changelog
| `--help` | `-h` | Print help message |
#### `--amend`
@@ -274,6 +275,20 @@ author:
type: added
```
+#### `--ee`
+
+Use the **`--ee`** argument to create an EE changelog:
+
+```plaintext
+$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -ee
+create ee/changelogs/unreleased/feature-hey-dz.yml
+---
+title: Hey DZ, I added a feature to GitLab!
+merge_request:
+author:
+type: added
+```
+
### History and Reasoning
Our `CHANGELOG` file was previously updated manually by each contributor that
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
index 9104c01c980..85c93f521ac 100644
--- a/doc/development/chaos_endpoints.md
+++ b/doc/development/chaos_endpoints.md
@@ -6,8 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Generating chaos in a test GitLab instance
+<!-- vale gitlab.Spelling = NO -->
+
As [Werner Vogels](https://twitter.com/Werner), the CTO at Amazon Web Services, famously put it, **Everything fails, all the time**.
+<!-- vale gitlab.Spelling = NO -->
+
As a developer, it's as important to consider the failure modes in which your software may operate as much as normal operation. Doing so can mean the difference between a minor hiccup leading to a scattering of `500` errors experienced by a tiny fraction of users, and a full site outage that affects all users for an extended period.
To paraphrase [Tolstoy](https://en.wikipedia.org/wiki/Anna_Karenina_principle), _all happy servers are alike, but all failing servers are failing in their own way_. Luckily, there are ways we can attempt to simulate these failure modes, and the chaos endpoints are tools for assisting in this process.
@@ -160,3 +164,58 @@ GET /-/chaos/kill?async=true
curl "http://localhost:3000/-/chaos/kill" --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/kill?token=secret"
```
+
+## Run garbage collector
+
+This endpoint triggers a GC run on the worker handling the request and returns its worker ID
+plus GC stats as JSON. This is mostly useful when running Puma in standalone mode, since
+otherwise the worker handling the request will not be known upfront.
+
+Endpoint:
+
+```plaintext
+POST /-/chaos/gc
+```
+
+Example request:
+
+```shell
+curl --request POST "http://localhost:3000/-/chaos/gc" --header 'X-Chaos-Secret: secret'
+curl --request POST "http://localhost:3000/-/chaos/gc?token=secret"
+```
+
+Example response:
+
+```json
+{
+ "worker_id": "puma_1",
+ "gc_stat": {
+ "count": 94,
+ "heap_allocated_pages": 9077,
+ "heap_sorted_length": 9077,
+ "heap_allocatable_pages": 0,
+ "heap_available_slots": 3699720,
+ "heap_live_slots": 2827510,
+ "heap_free_slots": 872210,
+ "heap_final_slots": 0,
+ "heap_marked_slots": 2827509,
+ "heap_eden_pages": 9077,
+ "heap_tomb_pages": 0,
+ "total_allocated_pages": 9077,
+ "total_freed_pages": 0,
+ "total_allocated_objects": 14229357,
+ "total_freed_objects": 11401847,
+ "malloc_increase_bytes": 8192,
+ "malloc_increase_bytes_limit": 30949538,
+ "minor_gc_count": 71,
+ "major_gc_count": 23,
+ "compact_count": 0,
+ "remembered_wb_unprotected_objects": 41685,
+ "remembered_wb_unprotected_objects_limit": 83370,
+ "old_objects": 2617806,
+ "old_objects_limit": 5235612,
+ "oldmalloc_increase_bytes": 8192,
+ "oldmalloc_increase_bytes_limit": 122713697
+ }
+}
+```
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
index a2a0005f7cb..0341abf5eeb 100644
--- a/doc/development/chatops_on_gitlabcom.md
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -35,14 +35,12 @@ To request access to ChatOps on GitLab.com:
in the `#chat-ops-test` Slack channel, replacing `<username>` with your username:
`/chatops run member add <username> gitlab-com/chatops --ops`
- <!-- vale gitlab.FirstPerson = NO -->
-
- > Hi `__BUDDY_HANDLE__` and `__MANAGER_HANDLE__`, could you please add me to
- > the ChatOps project in Ops by running this command:
- > `/chatops run member add <username> gitlab-com/chatops --ops` in the
- > `#chat-ops-test` Slack channel? Thanks in advance.
-
- <!-- vale gitlab.FirstPerson = YES -->
+ ```plaintext
+ Hi <__BUDDY_HANDLE__> and <__MANAGER_HANDLE__>, could you please add me to
+ the ChatOps project in Ops by running this command:
+ `/chatops run member add <username> gitlab-com/chatops --ops` in the
+ `#chat-ops-test` Slack channel? Thanks in advance.
+ ```
1. Ensure you've set up two-factor authentication.
1. After you're added to the ChatOps project, run this command to check your user
@@ -61,6 +59,6 @@ To request access to ChatOps on GitLab.com:
## See also
-- [ChatOps Usage](../ci/chatops/README.md)
+- [ChatOps Usage](../ci/chatops/index.md)
- [Understanding EXPLAIN plans](understanding_explain_plans.md)
- [Feature Groups](feature_flags/development.md#feature-groups)
diff --git a/doc/development/cicd/img/ci_minutes.png b/doc/development/cicd/img/ci_minutes.png
new file mode 100644
index 00000000000..d47406fb445
--- /dev/null
+++ b/doc/development/cicd/img/ci_minutes.png
Binary files differ
diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md
index eede1d691a9..eb2224d710a 100644
--- a/doc/development/cicd/index.md
+++ b/doc/development/cicd/index.md
@@ -143,3 +143,42 @@ Finally if the runner can only pick jobs that are tagged, all untagged jobs are
At this point we loop through remaining `pending` jobs and we try to assign the first job that the runner "can pick" based on additional policies. For example, runners marked as `protected` can only pick jobs that run against protected branches (such as production deployments).
As we increase the number of runners in the pool we also increase the chances of conflicts which would arise if assigning the same job to different runners. To prevent that we gracefully rescue conflict errors and assign the next job in the list.
+
+## The definition of "Job" in GitLab CI/CD
+
+"Job" in GitLab CI context refers a task to drive Continuous Integration, Delivery and Deployment.
+Typically, a pipeline contains multiple stages, and a stage contains multiple jobs.
+
+In Active Record modeling, Job is defined as `CommitStatus` class.
+On top of that, we have the following types of jobs:
+
+- `Ci::Build` ... The job to be executed by runners.
+- `Ci::Bridge` ... The job to trigger a downstream pipeline.
+- `GenericCommitStatus` ... The job to be executed in an external CI/CD system e.g. Jenkins.
+
+Please note that, when you use the "Job" terminology in codebase, readers would
+assume that the class/object is any type of above.
+If you specifically refer `Ci::Build` class, you should not name the object/class
+as "job" as this could cause some confusions. In documentation,
+we should use "Job" in general, instead of "Build".
+
+We have a few inconsistencies in our codebase that should be refactored.
+For example, `CommitStatus` should be `Ci::Job` and `Ci::JobArtifact` should be `Ci::BuildArtifact`.
+See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/16111) for the full refactoring plan.
+
+## CI Minutes
+
+This diagram shows how the [CI minutes](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes)
+feature and its components work.
+
+![CI Minutes architecture](img/ci_minutes.png)
+<!-- Editable diagram available at https://app.diagrams.net/?libs=general;flowchart#G1XjLPvJXbzMofrC3eKRyDEk95clV6ypOb -->
+
+Watch a walkthrough of this feature in details in the video below.
+
+<div class="video-fallback">
+ See the video: <a href="https://www.youtube.com/watch?v=NmdWRGT8kZg">CI Minutes - architectural overview</a>.
+</div>
+<figure class="video-container">
+ <iframe src="https://www.youtube.com/embed/NmdWRGT8kZg" frameborder="0" allowfullscreen="true"> </iframe>
+</figure>
diff --git a/doc/development/code_intelligence/index.md b/doc/development/code_intelligence/index.md
index c5673f6eee2..ac962e3ae3e 100644
--- a/doc/development/code_intelligence/index.md
+++ b/doc/development/code_intelligence/index.md
@@ -4,7 +4,7 @@ group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Code Intelligence
+# Code Intelligence **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/1576) in GitLab 13.1.
@@ -45,7 +45,7 @@ sequenceDiagram
GitLab Rails to authorize the upload.
1. GitLab Rails validates whether the artifact can be uploaded and sends
- `ProcessLsif: true` header if the lsif artifact can be processed.
+ `ProcessLsif: true` header if the LSIF artifact can be processed.
1. Workhorse reads the LSIF document line by line and generates code intelligence
data for each file in the project. The output is a zipped directory of JSON
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index fe395dc2304..dada6adcce7 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -24,7 +24,7 @@ uncovered edge cases.
The default approach is to choose a reviewer from your group or team for the first review.
This is only a recommendation and the reviewer may be from a different team.
However, it is recommended to pick someone who is a [domain expert](#domain-experts).
-If your merge request touches more than one domain (for example, Dynamic Analysis and GraphQL), ask for reviews from an expert from each domain.
+If your merge request touches more than one domain (for example, Dynamic Analysis and GraphQL), ask for reviews from an expert from each domain.
You can read more about the importance of involving reviewer(s) in the section on the responsibility of the author below.
@@ -107,11 +107,11 @@ with [domain expertise](#domain-experts).
be **approved by a [frontend foundations member](https://about.gitlab.com/direction/create/ecosystem/frontend-ux-foundations/)**.
- If the license used by the new library hasn't been approved for use in
GitLab, the license must be **approved by a [legal department member](https://about.gitlab.com/handbook/legal/)**.
- More information about license compatiblity can be found in our
+ More information about license compatibility can be found in our
[GitLab Licensing and Compatibility documentation](licensing.md).
1. If your merge request includes adding a new UI/UX paradigm (*1*), it must be
**approved by a [UX lead](https://about.gitlab.com/company/team/)**.
-1. If your merge request includes a new dependency or a filesystem change, it must be
+1. If your merge request includes a new dependency or a file system change, it must be
**approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
1. If your merge request includes documentation changes, it must be **approved
by a [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)**, based on
@@ -121,6 +121,8 @@ with [domain expertise](#domain-experts).
1. If your merge request only includes end-to-end changes (*3*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)**
1. If your merge request includes a new or updated [application limit](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits), it must be **approved by a [product manager](https://about.gitlab.com/company/team/)**.
1. If your merge request includes Product Intelligence (telemetry or analytics) changes, it should be reviewed and approved by a [Product Intelligence engineer](https://gitlab.com/gitlab-org/growth/product_intelligence/engineers).
+1. If your merge request includes an addition of, or changes to a [Feature spec](testing_guide/testing_levels.md#frontend-feature-tests), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa) or [Quality reviewer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_qa)**.
+1. If your merge request introduces a new service to GitLab (Puma, Sidekiq, Gitaly are examples), it must be **approved by a [product manager](https://about.gitlab.com/company/team/)**. See the [process for adding a service component to GitLab](adding_service_component.md) for details.
- (*1*): Please note that specs other than JavaScript specs are considered backend code.
- (*2*): We encourage you to seek guidance from a database maintainer if your merge
@@ -177,8 +179,11 @@ warrant a comment could be:
Avoid:
-- Adding comments (referenced above, or TODO items) directly to the source code unless the reviewer requires you to do so. If the comments are added due to an actionable task,
-a link to an issue must be included.
+- Adding TODO comments (referenced above) directly to the source code unless the reviewer requires
+ you to do so. If TODO comments are added due to an actionable task,
+ [include a link to the relevant issue](code_comments.md).
+- Adding comments which only explain what the code is doing. If non-TODO comments are added, they should
+ [_explain why, not what_](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/).
- Assigning merge requests with failed tests to maintainers. If the tests are failing and you have to assign, ensure you leave a comment with an explanation.
- Excessively mentioning maintainers through email or Slack (if the maintainer is reachable
through Slack). If you can't assign a merge request, `@` mentioning a maintainer in a comment is acceptable and in all other cases assigning the merge request is sufficient.
@@ -276,10 +281,9 @@ first time.
of your shiny new branch, read through the entire diff. Does it make sense?
Did you include something unrelated to the overall purpose of the changes? Did
you forget to remove any debugging code?
-<!-- vale gitlab.FutureTense = NO -->
-- Be grateful for the reviewer's suggestions. ("Good call. I'll make that
- change.")
-<!-- vale gitlab.FutureTense = YES -->
+- Consider providing instructions on how to test the merge request. This can be
+ helpful for reviewers not familiar with the product feature or area of the codebase.
+- Be grateful for the reviewer's suggestions. (`Good call. I'll make that change.`)
- Don't take it personally. The review is of the code, not of you.
- Explain why the code exists. ("It's like that because of these reasons. Would
it be more clear if I rename this class/file/method/variable?")
@@ -340,7 +344,7 @@ experience, refactors the existing code). Then:
convey your intent.
- For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can
optionally resolve within the merge request or follow-up at a later stage.
- - There's a [Chrome/Firefox addon](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes.
+ - There's a [Chrome/Firefox add-on](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes.
- After a round of line notes, it can be helpful to post a summary note such as
"Looks good to me", or "Just a couple things to address."
- Assign the merge request to the author if changes are required following your
@@ -378,9 +382,12 @@ When ready to merge:
- Consider using the [Squash and
merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
feature when the merge request has a lot of commits.
- When merging code a maintainer should only use the squash feature if the
- author has already set this option or if the merge request clearly contains a
- messy commit history that is intended to be squashed.
+ When merging code, a maintainer should only use the squash feature if the
+ author has already set this option, or if the merge request clearly contains a
+ messy commit history, it will be more efficient to squash commits instead of
+ circling back with the author about that. Otherwise, if the MR only has a few commits, we'll
+ be respecting the author's setting by not squashing them.
+
- **Start a new merge request pipeline with the `Run Pipeline` button in the merge
request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).** Note that:
- If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you
@@ -565,7 +572,7 @@ A good example of collaboration on an MR touching multiple parts of the codebase
### Credits
-Largely based on the [thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
+Largely based on the [`thoughtbot` code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
---
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 329303558b0..7a1c189e087 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -181,11 +181,21 @@ reasons for including it.
`@mention` a maintainer in merge requests that contain:
- More than 500 changes.
-- Any major breaking changes.
+- Any major [breaking changes](#breaking-changes).
- External libraries.
If you are not sure who to mention, the reviewer will do this for you early in the merge request process.
+#### Breaking changes
+
+A "breaking change" is any change that requires users to make a corresponding change to their code, settings, or workflow. "Users" might be humans, API clients, or even code classes that "use" another class. Examples of breaking changes include:
+
+- Removing a user-facing feature without a replacement/workaround.
+- Changing the definition of an existing API (by re-naming query parameters, changing routes, etc.).
+- Removing a public method from a code class.
+
+A breaking change can be considered "major" if it affects many users, or represents a significant change in behavior.
+
#### Issues workflow
This [documentation](issue_workflow.md) outlines the current issue workflow:
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 7859af4e88b..166f7b350bf 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -65,9 +65,9 @@ request is as follows:
template already provided in the "Description" field.
1. If you are contributing documentation, choose `Documentation` from the
"Choose a template" menu and fill in the description according to the template.
- 1. Mention the issue(s) your merge request solves, using the `Solves #XXX` or
- `Closes #XXX` syntax to [auto-close](../../user/project/issues/managing_issues.md#closing-issues-automatically)
- the issue(s) once the merge request is merged.
+ 1. Use the syntax `Solves #XXX`, `Closes #XXX`, or `Refs #XXX` to mention the issue(s) your merge
+ request addresses. Referenced issues do not [close automatically](../../user/project/issues/managing_issues.md#closing-issues-automatically).
+ You must close them manually once the merge request is merged.
1. If you're allowed to, set a relevant milestone and [labels](issue_workflow.md).
1. UI changes should use available components from the GitLab Design System,
[Pajamas](https://design.gitlab.com/). The MR must include *Before* and
@@ -150,7 +150,7 @@ Commit messages should follow the guidelines below, for reasons explained by Chr
#### Why these standards matter
1. Consistent commit messages that follow these guidelines make the history more readable.
-1. Concise standard commit messages helps to identify breaking changes for a deployment or ~"master:broken" quicker when
+1. Concise standard commit messages helps to identify [breaking changes](index.md#breaking-changes) for a deployment or ~"master:broken" quicker when
reviewing commits between two points in time.
#### Commit message template
@@ -212,7 +212,7 @@ the contribution acceptance criteria below:
1. Changes do not degrade performance:
- Avoid repeated polling of endpoints that require a significant amount of overhead.
- Check for N+1 queries via the SQL log or [`QueryRecorder`](../merge_request_performance_guidelines.md).
- - Avoid repeated access of the filesystem.
+ - Avoid repeated access of the file system.
- Use [polling with ETag caching](../polling.md) if needed to support real-time features.
1. If the merge request adds any new libraries (gems, JavaScript libraries, etc.),
they should conform to our [Licensing guidelines](../licensing.md). See those
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index c316d50c88c..2a2cfebe964 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -15,52 +15,83 @@ settings automatically by default. If your editor/IDE does not automatically sup
we suggest investigating to see if a plugin exists. For instance here is the
[plugin for vim](https://github.com/editorconfig/editorconfig-vim).
-## Pre-push static analysis
+## Pre-push static analysis with Lefthook
-We strongly recommend installing [Lefthook](https://github.com/Arkweid/lefthook) to automatically check
-for static analysis offenses before pushing your changes.
+[Lefthook](https://github.com/Arkweid/lefthook) is a Git hooks manager that allows
+custom logic to be executed prior to Git committing or pushing. GitLab comes with
+Lefthook configuration (`lefthook.yml`), but it must be installed.
-To install `lefthook`, run the following in your GitLab source directory:
+We have a `lefthook.yml` checked in but it is ignored until Lefthook is installed.
-```shell
-# 1. Make sure to uninstall Overcommit first
-overcommit --uninstall
+### Uninstall Overcommit
+
+We were using Overcommit prior to Lefthook, so you may want to uninstall it first with `overcommit --uninstall`.
+
+### Install Lefthook
+
+1. Install the `lefthook` Ruby gem:
+
+ ```shell
+ bundle install
+ ```
+
+1. Install Lefthook managed Git hooks:
+
+ ```shell
+ bundle exec lefthook install
+ ```
+
+1. Test Lefthook is working by running the Lefthook `prepare-commit-msg` Git hook:
+
+ ```shell
+ bundle exec lefthook run prepare-commit-msg
+ ```
+
+This should return a fully qualified path command with no other output.
+
+### Lefthook configuration
-# If using rbenv, at this point you may need to do: rbenv rehash
+The current Lefthook configuration can be found in [`lefthook.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lefthook.yml).
-# 2. Install lefthook...
+Before you push your changes, Lefthook automatically runs the following checks:
-## With Homebrew (macOS)
-brew install Arkweid/lefthook/lefthook
+- Danger: Runs a subset of checks that `danger-review` runs on your merge requests.
+- ES lint: Run `yarn 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 `bundle exec scss-lint` checks (with the [`.scss-lint.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.scss-lint.yml) 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`.
-## Or with Go
-go get github.com/Arkweid/lefthook
+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).
-## Or with Rubygems
-gem install lefthook
+### Disable Lefthook temporarily
-### You may need to run the following if you're using rbenv
-rbenv rehash
+To disable Lefthook temporarily, you can set the `LEFTHOOK` environment variable to `0`. For instance:
-# 3. Install the Git hooks
-lefthook install -f
+```shell
+LEFTHOOK=0 git push ...
```
-Before you push your changes, Lefthook then automatically run Danger checks, and other checks
-for changed files. This saves you time as you don't have to wait for the same errors to be detected
-by CI/CD.
+### Run Lefthook hooks manually
+
+To run the `pre-push` Git hook, run:
+
+```shell
+bundle exec lefthook run pre-push
+```
-Lefthook relies on a pre-push hook to prevent commits that violate its ruleset.
-To override this behavior, pass the environment variable `LEFTHOOK=0`. That is,
-`LEFTHOOK=0 git push`.
+For more information, check out [Lefthook documentation](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#run-githook-group-directly).
-You can also:
+### Skip Lefthook checks per tag
-- Define [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
-- Skip [checks per tag on the fly](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#skip-some-tags-on-the-fly).
- For example, `LEFTHOOK_EXCLUDE=frontend git push origin`.
-- Run [hooks manually](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#run-githook-group-directly).
- For example, `lefthook run pre-push`.
+To skip some checks based on tags when pushing, you can set the `LEFTHOOK_EXCLUDE` environment variable. For instance:
+
+```shell
+LEFTHOOK_EXCLUDE=frontend,documentation git push ...
+```
+
+For more information, check out [Lefthook documentation](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#skip-some-tags-on-the-fly).
## Ruby, Rails, RSpec
@@ -111,7 +142,7 @@ This ensures that our list isn't mistakenly removed by another auto generation o
the `.rubocop_todo.yml`. This also allows us greater visibility into the exceptions
which are currently being resolved.
-One way to generate the initial list is to run the todo auto generation,
+One way to generate the initial list is to run the `todo` auto generation,
with `exclude limit` set to a high number.
```shell
@@ -149,8 +180,12 @@ See the dedicated [Shell scripting standards and style guidelines](../shell_scri
## Markdown
+<!-- vale gitlab.Spelling = NO -->
+
We're following [Ciro Santilli's Markdown Style Guide](https://cirosantilli.com/markdown-style-guide/).
+<!-- vale gitlab.Spelling = YES -->
+
## Documentation
See the dedicated [Documentation Style Guide](../documentation/styleguide/index.md).
diff --git a/doc/development/cycle_analytics.md b/doc/development/cycle_analytics.md
deleted file mode 100644
index 1619f3dcb10..00000000000
--- a/doc/development/cycle_analytics.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'value_stream_analytics.md'
----
-
-This document was moved to [another location](value_stream_analytics.md)
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index 59b31437161..413c0a31eec 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -105,9 +105,9 @@ minimize the number of lines of code in `danger/`. A non-trivial `Dangerfile`
should mostly call plugin code with arguments derived from the methods provided
by Danger. The plugin code itself should have unit tests.
-At present, we do this by putting the code in a module in `lib/gitlab/danger/...`,
+At present, we do this by putting the code in a module in `tooling/danger/...`,
and including it in the matching `danger/plugins/...` file. Specs can then be
-added in `spec/lib/gitlab/danger/...`.
+added in `spec/tooling/danger/...`.
To determine if your `Dangerfile` works, push the branch that contains it to
GitLab. This can be quite frustrating, as it significantly increases the cycle
diff --git a/doc/development/database/database_reviewer_guidelines.md b/doc/development/database/database_reviewer_guidelines.md
index 26083183d6d..a242a3d5fd0 100644
--- a/doc/development/database/database_reviewer_guidelines.md
+++ b/doc/development/database/database_reviewer_guidelines.md
@@ -50,17 +50,17 @@ European/US and APAC friendly hours. You can join the office hours call and brin
that require a more in-depth discussion between the database reviewers and maintainers:
- [Database Office Hours Agenda](https://docs.google.com/document/d/1wgfmVL30F8SdMg-9yY6Y8djPSxWNvKmhR5XmsvYX1EI/edit).
-- [Youtube playlist with past recordings](https://www.youtube.com/playlist?list=PL05JrBw4t0Kp-kqXeiF7fF7cFYaKtdqXM).
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [YouTube playlist with past recordings](https://www.youtube.com/playlist?list=PL05JrBw4t0Kp-kqXeiF7fF7cFYaKtdqXM).
You should also join the [#database-labs](../understanding_explain_plans.md#database-lab)
-Slack channel and get familiar with how to use Joe, the slackbot that provides developers
+Slack channel and get familiar with how to use Joe, the Slackbot that provides developers
with their own clone of the production database.
Understanding and efficiently using `EXPLAIN` plans is at the core of the database review process.
The following guides provide a quick introduction and links to follow on more advanced topics:
- Guide on [understanding EXPLAIN plans](../understanding_explain_plans.md).
-- [Explaining the unexplainable series in depesz](https://www.depesz.com/tag/unexplainable/).
+- [Explaining the unexplainable series in `depesz`](https://www.depesz.com/tag/unexplainable/).
Finally, you can find various guides in the [Database guides](index.md) page that cover more specific
topics and use cases. The most frequently required during database reviewing are the following:
diff --git a/doc/development/database/strings_and_the_text_data_type.md b/doc/development/database/strings_and_the_text_data_type.md
index 33a0fd2ebb7..f338520c6ca 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -34,6 +34,12 @@ but only for updating the declaration of the columns. We can then validate it at
`VALIDATE CONSTRAINT`, which requires only a `SHARE UPDATE EXCLUSIVE LOCK` (only conflicts with other
validations and index creation while it allows reads and writes).
+### Exceptions
+
+Text columns used by `attr_encrypted` are not required to have a limit, because the length of the
+text after encryption may be longer than the text itself. Instead, you can use an Active Record
+length validation on the attribute.
+
## Create a new table with text columns
When adding a new table, the limits for all text columns should be added in the same migration as
diff --git a/doc/development/database/table_partitioning.md b/doc/development/database/table_partitioning.md
index 358b9bb42b0..207d5a733ce 100644
--- a/doc/development/database/table_partitioning.md
+++ b/doc/development/database/table_partitioning.md
@@ -60,7 +60,7 @@ was the first table to be partitioned in the application database
(scheduled for deployment with the GitLab 13.5 release). This
table tracks audit entries of security events that happen in the
application. In almost all cases, users want to see audit activity that
-occurs in a certain timeframe. As a result, date-range partitioning
+occurs in a certain time frame. As a result, date-range partitioning
was a natural fit for how the data would be accessed.
To look at this in more detail, imagine a simplified `audit_events` schema:
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index f4558189000..dc64b59018b 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -69,16 +69,14 @@ bundle exec rails db -e development
Use these instructions for exploring the GitLab database while developing with the GDK:
1. Install or open [Visual Studio Code](https://code.visualstudio.com/download).
-1. Install the [PostgreSQL VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres) by Chris Kolkman.
+1. Install the [PostgreSQL VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres).
1. In Visual Studio Code click on the PostgreSQL Explorer button in the left toolbar.
1. In the top bar of the new window, click on the `+` to **Add Database Connection**, and follow the prompts to fill in the details:
1. **Hostname**: the path to the PostgreSQL folder in your GDK directory (for example `/dev/gitlab-development-kit/postgresql`).
1. **PostgreSQL user to authenticate as**: usually your local username, unless otherwise specified during PostgreSQL installation.
1. **Password of the PostgreSQL user**: the password you set when installing PostgreSQL.
1. **Port number to connect to**: `5432` (default).
- 1. <!-- vale gitlab.Spelling = NO -->
- **Use an ssl connection?**
- <!-- vale gitlab.Spelling = YES --> This depends on your installation. Options are:
+ 1. **Use an SSL connection?** This depends on your installation. Options are:
- **Use Secure Connection**
- **Standard Connection** (default)
1. **(Optional) The database to connect to**: `gitlabhq_development`.
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index da2c93cc1fd..a19f46b2198 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -144,10 +144,13 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
##### Query Plans
- The query plan for each raw SQL query included in the merge request along with the link to the query plan following each raw SQL snippet.
-- Provide the link to the plan at: [explain.depesz.com](https://explain.depesz.com). Paste both the plan and the query used in the form.
+- Provide a public link to the plan from either:
+ - [postgres.ai](https://postgres.ai/): Follow the link in `#database-lab` and generate a shareable, public link
+ by clicking the **Share** button in the upper right corner.
+ - [explain.depesz.com](https://explain.depesz.com): Paste both the plan and the query used in the form.
- When providing query plans, make sure it hits enough data:
- You can use a GitLab production replica to test your queries on a large scale,
- through the `#database-lab` Slack channel or through [chatops](understanding_explain_plans.md#chatops).
+ through the `#database-lab` Slack channel or through [ChatOps](understanding_explain_plans.md#chatops).
- Usually, the `gitlab-org` namespace (`namespace_id = 9970`) and the
`gitlab-org/gitlab-foss` (`project_id = 13083`) or the `gitlab-org/gitlab` (`project_id = 278964`)
projects provide enough data to serve as a good example.
@@ -220,13 +223,13 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac
- Check for any obviously complex queries and queries the author specifically
points out for review (if any)
- If not present yet, ask the author to provide SQL queries and query plans
- (for example, by using [chatops](understanding_explain_plans.md#chatops) or direct
+ (for example, by using [ChatOps](understanding_explain_plans.md#chatops) or direct
database access)
- For given queries, review parameters regarding data distribution
- [Check query plans](understanding_explain_plans.md) and suggest improvements
to queries (changing the query, schema or adding indexes and similar)
- General guideline is for queries to come in below [100ms execution time](query_performance.md#timing-guidelines-for-queries)
- - Avoid N+1 problems and minimalize the [query count](merge_request_performance_guidelines.md#query-counts).
+ - Avoid N+1 problems and minimize the [query count](merge_request_performance_guidelines.md#query-counts).
### Timing guidelines for migrations
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index fba8eda0408..52ba89a4d6e 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -14,12 +14,20 @@ We rely on different sources to present diffs. These include:
## Deep Dive
+<!-- vale gitlab.Spelling = NO -->
+
In January 2019, Oswaldo Ferreira hosted a Deep Dive (GitLab team members only:
`https://gitlab.com/gitlab-org/create-stage/issues/1`) on GitLab Diffs and Commenting on Diffs
-functionality to share his domain specific knowledge with anyone who may work in this part of the
-codebase in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=K6G3gMcFyek),
-and the slides on [Google Slides](https://docs.google.com/presentation/d/1bGutFH2AT3bxOPZuLMGl1ANWHqFnrxwQwjiwAZkF-TU/edit)
-and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/b5ad2f336e0afcfe0f99db0af0ccc71a/).
+functionality to share domain-specific knowledge with anyone who may work in this part of the
+codebase in the future:
+
+<!-- vale gitlab.Spelling = YES -->
+
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+ [Recording on YouTube](https://www.youtube.com/watch?v=K6G3gMcFyek)
+- Slides on [Google Slides](https://docs.google.com/presentation/d/1bGutFH2AT3bxOPZuLMGl1ANWHqFnrxwQwjiwAZkF-TU/edit)
+- [PDF slides](https://gitlab.com/gitlab-org/create-stage/uploads/b5ad2f336e0afcfe0f99db0af0ccc71a/)
+
Everything covered in this deep dive was accurate as of GitLab 11.7, and while specific details may
have changed since then, it should still serve as a good introduction.
@@ -125,7 +133,7 @@ Gitaly only returns `Diff.Collapsed` (RPC) when surpassing collection limits.
#### Not expandable patches (too large)
The patch not be rendered if it's larger than `ApplicationSettings#diff_max_patch_bytes`.
-Users see a `This source diff could not be displayed because it is too large` message.
+Users see a `Changes are too large to be shown.` message and a button to view only that file in that commit.
```ruby
Commit::DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines] = 5000
@@ -180,8 +188,8 @@ has been introduced.
One of the key challenges to deal with when working on merge ref diffs are merge
conflicts. If the target and source branch contains a merge conflict, the branches
-cannot be automatically merged. The [recording on
-YouTube](https://www.youtube.com/watch?v=GFXIFA4ZuZw&feature=youtu.be&ab_channel=GitLabUnfiltered)
+cannot be automatically merged. The
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=GFXIFA4ZuZw&feature=youtu.be&ab_channel=GitLabUnfiltered)
is a quick introduction to the problem and the motivation behind the [epic](https://gitlab.com/groups/gitlab-org/-/epics/854).
In 13.5 a solution for both-modified merge
diff --git a/doc/development/directory_structure.md b/doc/development/directory_structure.md
new file mode 100644
index 00000000000..c2329feb941
--- /dev/null
+++ b/doc/development/directory_structure.md
@@ -0,0 +1,36 @@
+---
+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
+---
+
+# Backend directory structure
+
+## Use namespaces to define bounded contexts
+
+A healthy application is divided into macro and sub components that represent the contexts at play,
+whether they are related to business domain or infrastructure code.
+
+As GitLab code has so many features and components it's hard to see what contexts are involved.
+We should expect any class to be defined inside a module/namespace that represents the contexts where it operates.
+
+When we namespace classes inside their domain:
+
+- Similar terminology becomes unambiguous as the domain clarifies the meaning:
+ For example, `MergeRequests::Diff` and `Notes::Diff`.
+- Top-level namespaces could be associated to one or more groups identified as domain experts.
+- We can better identify the interactions and coupling between components.
+ For example, several classes inside `MergeRequests::` domain interact more with `Ci::`
+ domain and less with `ImportExport::`.
+
+```ruby
+# bad
+class MyClass
+end
+
+# good
+module MyDomain
+ class MyClass
+ end
+end
+```
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 9228609aae9..eb20e721e46 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Distributed Tracing - development guidelines
+# Distributed Tracing - development guidelines **(FREE)**
GitLab is instrumented for distributed tracing. Distributed Tracing in GitLab is currently considered **experimental**, as it has not yet been tested at scale on GitLab.com.
diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md
deleted file mode 100644
index 1595a841ade..00000000000
--- a/doc/development/doc_styleguide.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'documentation/styleguide.md'
----
-
-This document was moved to [another location](documentation/styleguide.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/documentation/feature-change-workflow.md b/doc/development/documentation/feature-change-workflow.md
deleted file mode 100644
index 78e5510ffca..00000000000
--- a/doc/development/documentation/feature-change-workflow.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'workflow.md'
----
-
-This document was moved to [another location](workflow.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index 7547ec59fb2..c9c291abd2c 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -30,7 +30,7 @@ See how to document them below, according to the state of the flag:
- [Features that can be enabled or disabled for a single project](#features-enabled-by-project).
- [Features with the feature flag removed](#features-with-flag-removed).
-The [`**(CORE ONLY)**`](styleguide/index.md#product-tier-badges) badge or equivalent for
+The [`**(FREE SELF)**`](styleguide/index.md#product-tier-badges) badge or equivalent for
the feature's tier should be added to the line and heading that refers to
enabling/disabling feature flags as Admin access is required to do so,
therefore, it indicates that it cannot be done by regular users of GitLab.com.
@@ -61,7 +61,7 @@ be enabled for a single project, and is not ready for production use:
> - It's [deployed behind a feature flag](<replace with path to>/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](#anchor-to-section). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -70,7 +70,7 @@ This feature might not be available to you. Check the **version history** note a
<!-- Add this at the end of the file -->
-### Enable or disable <Feature Name> **(CORE ONLY)**
+### Enable or disable <Feature Name> **(FREE SELF)**
<Feature Name> is under development and not ready for production use. It is
deployed behind a feature flag that is **disabled by default**.
@@ -91,7 +91,7 @@ Feature.disable(:<feature flag>)
````
Adjust the blurb according to the state of the feature you're documenting.
-Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`, and
+Replace `<Feature name>`, `**(FREE SELF)**`, `<feature flag>`, and
`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features that became enabled by default
@@ -120,7 +120,7 @@ use:
> - [Became enabled by default](link-to-issue) on GitLab 12.1.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -129,7 +129,7 @@ This feature might not be available to you. Check the **version history** note a
<!-- Add this at the end of the file -->
-### Enable or disable <Feature Name> **(CORE ONLY)**
+### Enable or disable <Feature Name> **(FREE SELF)**
<Feature Name> is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
@@ -150,7 +150,7 @@ Feature.disable(:<feature flag>)
````
Adjust the blurb according to the state of the feature you're documenting.
-Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`,
+Replace `<Feature name>`, `**(FREE SELF)**`, `<feature flag>`,
`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features directly enabled by default
@@ -176,7 +176,7 @@ cannot be enabled for a single project, and is ready for production use:
> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -185,7 +185,7 @@ This feature might not be available to you. Check the **version history** note a
<!-- Add this at the end of the file -->
-### Enable or disable <Feature Name> **(CORE ONLY)**
+### Enable or disable <Feature Name> **(FREE SELF)**
<Feature Name> is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
@@ -206,7 +206,7 @@ Feature.disable(:<feature flag>)
````
Adjust the blurb according to the state of the feature you're documenting.
-Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`,
+Replace `<Feature name>`, `**(FREE SELF)**`, `<feature flag>`,
`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features enabled by project
@@ -249,7 +249,7 @@ be enabled by project, and is ready for production use:
> - It's enabled on GitLab.com.
> - It can be enabled or disabled for a single project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -258,14 +258,14 @@ This feature might not be available to you. Check the **version history** note a
<!-- Add this at the end of the file -->
-### Enable or disable <Feature Name> **(CORE ONLY)**
+### Enable or disable <Feature Name> **(FREE SELF)**
<Feature Name> is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](<replace with path to>/administration/feature_flags.md)
can opt to disable it.
-To enabled it:
+To enable it:
```ruby
# For the instance
@@ -285,7 +285,7 @@ Feature.disable(:<feature flag>, Project.find(<project id>))
````
Adjust the blurb according to the state of the feature you're documenting.
-Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`,
+Replace `<Feature name>`, `**(FREE SELF)**`, `<feature flag>`,
`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features with flag removed
diff --git a/doc/development/documentation/improvement-workflow.md b/doc/development/documentation/improvement-workflow.md
deleted file mode 100644
index 78e5510ffca..00000000000
--- a/doc/development/documentation/improvement-workflow.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'workflow.md'
----
-
-This document was moved to [another location](workflow.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 55f5d43b175..53e7ba35831 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -12,7 +12,7 @@ The GitLab documentation is [intended as the single source of truth (SSOT)](http
In addition to this page, the following resources can help you craft and contribute to documentation:
- [Style Guide](styleguide/index.md) - What belongs in the docs, language guidelines, Markdown standards to follow, links, and more.
-- [Structure and template](structure.md) - Learn the typical parts of a doc page and how to write each one.
+- [Topic type template](structure.md) - Learn about the different types of topics.
- [Documentation process](workflow.md).
- [Markdown Guide](../../user/markdown.md) - A reference for all Markdown syntax supported by GitLab.
- [Site architecture](site_architecture/index.md) - How <https://docs.gitlab.com> is built.
@@ -96,18 +96,18 @@ belongs to, as well as an information block as described below:
https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
```
-For example, the following metadata would be at the beginning of a product
-documentation page whose content is primarily associated with the Audit Events
-feature:
+For example:
```yaml
---
-stage: Monitor
-group: APM
+stage: Example Stage
+group: Example Group
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
```
+If you need help determining the correct stage, read [Ask for help](workflow.md#ask-for-help).
+
### Document type metadata
Originally discussed in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/1280),
@@ -161,73 +161,69 @@ Nanoc layout), which is displayed at the top of the page if defined:
## Move or rename a page
-Moving or renaming a document is the same as changing its location.
-Be sure to assign a technical writer to any MR that renames or moves a page. Technical
-Writers can help with any questions and can review your change.
+Moving or renaming a document is the same as changing its location. Be sure to
+assign a technical writer to any merge request that renames or moves a page.
+Technical Writers can help with any questions and can review your change.
-When moving or renaming a page, you must redirect browsers to the new page. This
-ensures users find the new page, and have the opportunity to update their bookmarks.
+When moving or renaming a page, you must redirect browsers to the new page.
+This ensures users find the new page, and have the opportunity to update their
+bookmarks.
There are two types of redirects:
-- Redirect files added into the docs themselves, for users who view the docs in `/help`
- on self-managed instances. For example, [`/help` on GitLab.com](https://gitlab.com/help).
-- Redirects in a [`_redirects`](../../user/project/pages/redirects.md) file, for users
- who view the docs on <https://docs.gitlab.com>.
-
-To add a redirect:
-
-1. In an MR in one of the internal docs projects (`gitlab`, `gitlab-runner`, `omnibus-gitlab`
- or `charts`):
- 1. Move or rename the doc, but do not delete the old doc.
- 1. In the old doc, add the redirect code for `/help`. Use the following template exactly,
- and only change the links and date. Use relative paths and `.md` for a redirect
- to another docs page. Use the full URL to redirect to a different project or site:
-
- ```markdown
- ---
- redirect_to: '../path/to/file/index.md'
- ---
-
- This document was moved to [another location](../path/to/file/index.md).
-
- <!-- This redirect file can be deleted after <YYYY-MM-DD>. -->
- <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
- ```
+- Redirect codes added into the documentation files themselves, for users who
+ view the docs in `/help` on self-managed instances. For example,
+ [`/help` on GitLab.com](https://gitlab.com/help).
+- [GitLab Pages redirects](../../user/project/pages/redirects.md),
+ for users who view the docs on [`docs.gitlab.com`](https://docs.gitlab.com).
- Redirect files linking to docs in any of the 4 internal docs projects can be
- removed after 3 months. Redirect files linking to external sites can be removed
- after 1 year.
+The Technical Writing team manages the [process](https://gitlab.com/gitlab-org/technical-writing/-/blob/master/.gitlab/issue_templates/tw-monthly-tasks.md)
+to regularly update the [`redirects.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/content/_data/redirects.yaml)
+file.
- 1. If the document being moved has any Disqus comments on it, follow the steps
- described in [Redirections for pages with Disqus comments](#redirections-for-pages-with-disqus-comments).
- 1. If a documentation page you're removing includes images that aren't used
- with any other documentation pages, be sure to use your MR to delete
- those images from the repository.
- 1. Assign the MR to a technical writer for review and merge.
-1. If the redirect is to one of the 4 internal docs projects (not an external URL),
- create an MR in [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs):
- 1. Update [`_redirects`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/content/_redirects)
- with one redirect entry for each renamed or moved file. This code works for
- <https://docs.gitlab.com> links only:
-
- ```plaintext
- /ee/path/to/old_file.html /ee/path/to/new_file 302 # To be removed after YYYY-MM-DD
- ```
+To add a redirect:
- The path must start with the internal project directory `/ee` for `gitlab`,
- `/gitlab-runner`, `/omnibus-gitlab` or `charts`, and must end with `.html`.
+1. Create a merge request in one of the internal docs projects (`gitlab`,
+ `gitlab-runner`, `omnibus-gitlab`, or `charts`), depending on the location of
+ the file that's being moved, renamed, or removed.
+1. To move or rename the documentation file, create a new file with the new
+ name or location, but don't delete the existing documentation file.
+1. In the original documentation file, add the redirect code for
+ `/help`. Use the following template exactly, and change only the links and
+ date. Use relative paths and `.md` for a redirect to another documentation
+ page. Use the full URL (with `https://`) to redirect to a different project or
+ site:
+
+ ```markdown
+ ---
+ redirect_to: '../path/to/file/index.md'
+ ---
+
+ This document was moved to [another location](../path/to/file/index.md).
+
+ <!-- This redirect file can be deleted after <YYYY-MM-DD>. -->
+ <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
+ ```
- `_redirects` entries can be removed after one year.
+ Redirect files linking to docs in any of the internal documentations projects
+ are removed after three months. Redirect files linking to external sites are
+ removed after one year.
-1. Search for links to the old file. You must find and update all links to the old file:
+1. If the documentation page being moved has any Disqus comments, follow the steps
+ described in [Redirections for pages with Disqus comments](#redirections-for-pages-with-disqus-comments).
+1. If a documentation page you're removing includes images that aren't used
+ with any other documentation pages, be sure to use your merge request to delete
+ those images from the repository.
+1. Assign the merge request to a technical writer for review and merge.
+1. Search for links to the original documentation file. You must find and update all
+ links that point to the original documentation file:
- In <https://gitlab.com/gitlab-com/www-gitlab-com>, search for full URLs:
`grep -r "docs.gitlab.com/ee/path/to/file.html" .`
- In <https://gitlab.com/gitlab-org/gitlab-docs/-/tree/master/content/_data>,
search the navigation bar configuration files for the path with `.html`:
`grep -r "path/to/file.html" .`
- - In any of the 4 internal projects. This includes searching for links in the docs
+ - In any of the four internal projects. This includes searching for links in the docs
and codebase. Search for all variations, including full URL and just the path.
In macOS for example, go to the root directory of the `gitlab` project and run:
@@ -238,8 +234,8 @@ To add a redirect:
grep -r "path/to/file" .
```
- You may need to try variations of relative links as well, such as `../path/to/file`
- or even `../file` to find every case.
+ You may need to try variations of relative links, such as `../path/to/file` or
+ `../file` to find every case.
### Redirections for pages with Disqus comments
@@ -306,68 +302,51 @@ with GitLab 11.4. Meaning, it's available only with `/help` from GitLab
### Linking to `/help`
-When you're building a new feature, you may need to link the documentation
-from GitLab, the application. This is normally done in files inside the
-`app/views/` directory with the help of the `help_page_path` helper method.
-
-In its simplest form, the HAML code to generate a link to the `/help` page is:
-
-```haml
-= link_to 'Help page', help_page_path('user/permissions')
-```
-
-The `help_page_path` contains the path to the document you want to link to with
-the following conventions:
-
-- it is relative to the `doc/` directory in the GitLab repository
-- the `.md` extension must be omitted
-- it must not end with a slash (`/`)
+When you're building a new feature, you may need to link to the documentation
+from the GitLab application. This is normally done in files inside the
+`app/views/` directory, with the help of the `help_page_path` helper method.
-Below are some special cases where should be used depending on the context.
-You can combine one or more of the following:
+The `help_page_path` contains the path to the document you want to link to,
+with the following conventions:
-1. **Linking to an anchor link.** Use `anchor` as part of the `help_page_path`
- method:
+- It's relative to the `doc/` directory in the GitLab repository.
+- It omits the `.md` extension.
+- It doesn't end with a slash (`/`).
- ```haml
- = link_to 'Help page', help_page_path('user/permissions', anchor: 'anchor-link')
- ```
+The help text follows the [Pajamas guidelines](https://design.gitlab.com/usability/helping-users/#formatting-help-content).
-1. **Opening links in a new tab.** This should be the default behavior:
+Use the following special cases depending on the context, ensuring all links
+are inside `_()` so they can be translated:
- ```haml
- = link_to 'Help page', help_page_path('user/permissions'), target: '_blank'
- ```
+- Linking to a doc page. In its most basic form, the HAML code to generate a
+ link to the `/help` page is:
-1. **Using a question icon.** Usually used in settings where a long
- description cannot be used, like near checkboxes. You can basically use
- any GitLab SVG icon, but prefer the `question-o`:
-
- ```haml
- = link_to sprite_icon('question-o'), help_page_path('user/permissions')
- ```
+ ```haml
+ = link_to _('Learn more.'), help_page_path('user/permissions'), target: '_blank', rel: 'noopener noreferrer'
+ ```
-1. **Using a button link.** Useful in places where text would be out of context
- with the rest of the page layout:
+- Linking to an anchor link. Use `anchor` as part of the `help_page_path`
+ method:
- ```haml
- = link_to 'Help page', help_page_path('user/permissions'), class: 'btn btn-info'
- ```
+ ```haml
+ = link_to _('Learn more.'), help_page_path('user/permissions', anchor: 'anchor-link'), target: '_blank', rel: 'noopener noreferrer'
+ ```
-1. **Using links inline of some text.**
+- Using links inline of some text. First, define the link, and then use it. In
+ this example, `link_start` is the name of the variable that contains the
+ link:
- ```haml
- Description to #{link_to 'Help page', help_page_path('user/permissions')}.
- ```
+ ```haml
+ - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/permissions') }
+ %p= _("This is a text describing the option/feature in a sentence. %{link_start}Learn more.%{link_end}").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ ```
-1. **Adding a period at the end of the sentence.** Useful when you don't want
- the period to be part of the link:
+- Using a button link. Useful in places where text would be out of context with
+ the rest of the page layout:
- ```haml
- = succeed '.' do
- Learn more in the
- = link_to 'Help page', help_page_path('user/permissions')
- ```
+ ```haml
+ = link_to _('Learn more.'), help_page_path('user/permissions'), class: 'btn btn-info', target: '_blank', rel: 'noopener noreferrer'
+ ```
#### Linking to `/help` in JavaScript
@@ -514,7 +493,7 @@ To run the tool on an existing screenshot generator, take the following steps:
1. Set up the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
1. Navigate to the subdirectory with your cloned GitLab repository, typically `gdk/gitlab`.
1. Make sure that your GDK database is fully migrated: `bin/rake db:migrate RAILS_ENV=development`.
-1. Install pngquant, see the tool website for more information: [`pngquant`](https://pngquant.org/)
+1. Install `pngquant`, see the tool website for more information: [`pngquant`](https://pngquant.org/)
1. Run `scripts/docs_screenshots.rb spec/docs_screenshots/<name_of_screenshot_generator>.rb <milestone-version>`.
1. Identify the location of the screenshots, based on the `gitlab/doc` location defined by the `it` parameter in your script.
1. Commit the newly created screenshots.
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index c8c48e71b48..e05f6760ff1 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -165,7 +165,7 @@ curl --request POST \
### Post data using form-data
-Instead of using JSON or urlencode you can use multipart/form-data which
+Instead of using JSON or URL-encoding data, you can use `multipart/form-data` which
properly handles data encoding:
```shell
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index fcf4662502f..f66b0543ad1 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -283,8 +283,8 @@ and the following syntax rules.
- As convention, always wrap URLs in single quotes `'url'`.
- Always use relative paths against the home of CE and EE. Examples:
- For `https://docs.gitlab.com/ee/README.html`, the relative URL is `README.html`.
- - For `https://docs.gitlab.com/ee/user/project/cycle_analytics.html`, the relative
- URL is `user/project/cycle_analytics.html`.
+ - For `https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.md`, the relative
+ URL is `user/analytics/value_stream_analytics.html`.
- For `README.html` files, add the complete path `path/to/README.html`.
- For `index.html` files, use the clean (canonical) URL: `path/to/`.
- For EE-only docs, use the same relative path, but add the attribute `ee_only: true` below
@@ -328,7 +328,7 @@ There are three main considerations on the logic built for the nav:
- `https://docs.gitlab.com/*`
- [EE-only](#ee-only-docs): documentation only available in `/ee/`, not on `/ce/`, e.g.:
- `https://docs.gitlab.com/ee/user/group/epics/`
- - `https://docs.gitlab.com/ee/user/project/security_dashboard.html`
+ - `https://docs.gitlab.com/ee/user/application_security/security_dashboard/index.html`
- [Default URL](#default-url): between CE and EE docs, the default is `ee`, therefore, all docs
should link to `/ee/` unless if on `/ce/` linking internally to `ce`.
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index be25a083948..92fd17f9d3e 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -114,7 +114,7 @@ located in the [Dockerfiles directory](https://gitlab.com/gitlab-org/gitlab-docs
If you need to rebuild the Docker images immediately (must have maintainer level permissions):
WARNING:
-If you change the dockerfile configuration and rebuild the images, you can break the master
+If you change the Dockerfile configuration and rebuild the images, you can break the master
pipeline in the main `gitlab` repository as well as in `gitlab-docs`. Create an image with
a different name first and test it to ensure you do not break the pipelines.
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index fd0c29f0fc1..65949d5b5f5 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -5,167 +5,165 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: What to include in GitLab documentation pages.
---
-# Documentation structure and template
+# Documentation topic types
-Use these standards to contribute content to the GitLab documentation.
+At GitLab, we have not traditionally used topic types. However, we are starting to
+move in this direction, and we now use four topic types:
-Before getting started, familiarize yourself with [Documentation guidelines for GitLab](index.md)
-and the [Documentation Style Guide](styleguide/index.md).
+- [Concept](#concept)
+- [Task](#task)
+- [Reference](#reference)
+- [Troubleshooting](#troubleshooting)
-## Components of a documentation page
+Each page contains multiple topic types. For example,
+a page with the title `Pipelines`, which is generated from a file called `index.md`,
+can include a concept and multiple task and reference topics.
-Most pages are dedicated to a specific GitLab feature or to a use case that
-involves one or more features, potentially in conjunction with third-party tools.
+GitLab also uses high-level landing pages.
-In general, each topic should include the following content, in this sequence:
+## Landing pages
-- *Metadata*: Information about the stage, group, and how to find the technical
- writer for the topic. This information isn't visible in the published help.
-- *Title*: A top-level heading with the feature or use case name. Choose a term
- that defines the functionality and use the same term in all the resources
- where the feature is mentioned.
-- *Introduction*: In a few sentences beneath the title, describe what the
- feature or topic is, what it does, and in what context it should be used.
-- *Use cases*: Describe real user scenarios.
-- *Prerequisites*: Describe the software, configuration, account, permissions,
- or knowledge required to use this functionality.
-- *Tasks*: Present detailed step-by-step instructions on how to use the feature.
-- *Troubleshooting*: List errors and how to address them. Recommended but not
- required.
+Landing pages are topics that group other topics and help a user to navigate a section.
-You can include additional subsections, as appropriate, such as *How it Works*,
-or *Architecture*. You can also include other logical divisions, such as
-pre-deployment and post-deployment tasks.
+Users who are using the in-product help do not have a left nav,
+and need these topics to navigate the documentation.
-## Template for new docs
+These topics can also help other users find the most important topics
+in a section.
-Follow the [folder structure and filename guidelines](styleguide/index.md#folder-structure-overview)
-and create a new topic by using this template:
+Landing page topics should be in this format:
```markdown
-<!--Follow the Style Guide when working on this document.
-https://docs.gitlab.com/ee/development/documentation/styleguide.html
-When done, remove all of this commented-out text, except a commented-out
-Troubleshooting section, which, if empty, can be left in place to encourage future use.-->
----
-description: "Short document description." # Up to ~200 chars long. This information is displayed
-in Google Search snippets. It may help to write the page intro first, and then reuse it here.
-stage: Add the stage name here
-group: Add the group name here
-info: To determine the technical writer assigned to the Stage/Group associated with this page,
-see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
+# Title (a noun, like "CI/CD or "Analytics")
-# Feature or Use Case Name **[TIER]** (1)
-<!--If you are writing about a use case, start with a verb,
-for example, "Configure", "Implement", + the goal/scenario-->
+Brief introduction to the concept or product area.
+Include the reason why someone would use this thing.
+
+- Bulleted list of important related topics.
+- These links are needed because users of in-product help do not have left navigation.
+```
-<!--For pages on newly-introduced features, add the following line.
-If only some aspects of the feature have been introduced, specify which parts of the feature.-->
-> [Introduced](link_to_issue_or_mr) in GitLab (Tier) X.Y (2).
+## Concept
-Write a description of the feature or use case. This introduction should answer
-these questions:
+A concept topic introduces a single feature or concept.
-- What is this feature or use case?
-- Who is it for?
-- What is the context in which it is used and are there any prerequisites or
- requirements?
-- What can the audience do with this? (Be sure to consider all applicable
- audiences, such as GitLab admin and developer-user.)
-- What are the benefits of using this over any existing alternatives?
+A concept should answer the questions:
-You can reuse this content, or part of it, for the front matter's `description`
-at the top of this file.
+- What is this?
+- Why would I use it?
-## Use cases
+Think of everything someone might want to know if they’ve never heard of this topic before.
-Describe common use cases, typically in bulleted form. Include real-life examples
-for each.
+Don’t tell them **how** to do this thing. Tell them **what it is**.
-If the page itself is dedicated to a use case, this section usually includes more
-specific scenarios for use (for example, variations on the main use case), but if
-that's not applicable, you can omit this section.
+If you start describing another topic, start a new concept and link to it.
+
+Concept topics should be in this format:
+
+```markdown
+# Title (a noun, like "Widgets")
-Examples of use cases on feature pages:
+A paragraph that explains what this thing is.
-- CE and EE: [Issues](../../user/project/issues/index.md#use-cases)
-- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md)
-- EE-only: [Geo](../../administration/geo/index.md)
-- EE-only: [Jenkins integration](../../integration/jenkins.md)
+Another paragraph that explains what this thing is.
-## Prerequisites
+Remember, if you start to describe about another concept, stop yourself.
+Each concept topic should be about one concept only.
+```
-State any prerequisites for using the feature. These might include:
+## Task
-- Technical prereqs (for example, an account on a third-party service, an amount
- of storage space, or prior configuration of another feature)
-- Prerequisite knowledge (for example, familiarity with certain GitLab features
- or other products and technologies).
+A task topic gives instructions for how to complete a procedure.
-Link each one to an appropriate place for more information.
+Task topics should be in this format:
-## Tasks
+```markdown
+# Title (starts with an active verb, like "Create a widget" or "Delete a widget")
-Each topic should help users accomplish a specific task.
+Do this task when you want to...
-The heading should:
+Prerequisites (optional):
-- Describe the task and start with a verb. For example, `Create a package` or
- `Configure a pipeline`.
-- Be short and descriptive (up to ~50 chars).
-- Start from an `h2` (`##`), then go over `h3`, `h4`, `h5`, and `h6` as needed.
- Never skip a hierarchy level (like `h2` > `h4`). It breaks the table of
- contents and can affect the breadcrumbs.
+- Thing 1
+- Thing 2
+- Thing 3
-Bigger tasks can have subsections that explain specific phases of the process.
+To do this task:
-Include example code or configurations when needed. Use Markdown to wrap code
-blocks with [syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting).
+1. Location then action. (Go to this menu, then select this item.)
+1. Another step.
+1. Another step.
-Example topic:
+Task result (optional). Next steps (optional).
+```
-## Create a teddy bear
+Here is an example.
-Create a teddy bear when you need something to hug. (Include the reason why you
-might do the task.)
+```markdown
+# Create an issue
-To create a teddy bear:
+Create an issue when you want to track bugs or future work.
-1. Go to **Settings > CI/CD**.
-1. Expand **This** and click **This**.
-1. Do another step.
+Prerequisites:
-The teddy bear is now in the kitchen, in the cupboard above the sink. _(This is the result.)_
+- A minimum of Contributor access to a project in GitLab.
-You can retrieve the teddy bear and put it on the couch with the other animals. _(These are next steps.)_
+To create an issue:
-Screenshots are not necessary. They are difficult to keep up-to-date and can
-clutter the page.
+1. Go to **Issues > List**.
+1. In the top right, click **New issue**.
+1. Complete the fields. (If you have a reference topic that lists each field, link to it here.)
+1. Click **Submit issue**.
-<!-- ## Troubleshooting
+The issue is created. You can view it by going to **Issues > List**.
+```
-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 documentation comments with questions that you know
-someone might ask.
+## Reference
-Each scenario can be a third-level heading, for example, `### 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. -->
+A reference topic provides information in an easily-scannable format,
+like a table or list. It's similar to a dictionary or encyclopedia entry.
----
+```markdown
+# Title (a noun, like "Pipeline settings" or "Administrator options")
-Notes:
+Introductory sentence.
-- (1): Apply the [tier badges](styleguide/index.md#product-badges) accordingly.
-- (2): Apply the correct format for the
- [GitLab version that introduces the feature](styleguide/index.md#gitlab-versions-and-tiers).
+| Setting | Description |
+|---------|-------------|
+| **Name** | Descriptive sentence about the setting. |
```
-## Help and feedback section
+## Troubleshooting
+
+Troubleshooting topics can be one of two categories:
+
+- **Troubleshooting task.** This topic is written the same as a [standard task topic](#task).
+ For example, "Run debug tools" or "Verify syntax."
+- **Troubleshooting reference.** This topic has a specific format.
+
+Troubleshooting reference topics should be in this format:
+
+```markdown
+# Title (the error message or a description of it)
+
+You might get an error that states <error message>.
+
+This issue occurs when...
+
+The workaround is...
+```
+
+## Other information on a topic
+
+Topics include other information.
+
+For example:
+
+- Each topic must have a [tier badge](styleguide/index.md#product-tier-badges).
+- New topics must have information about the
+ [GitLab version where the feature was introduced](styleguide/index.md#where-to-put-version-text).
+
+### Help and feedback section
This section ([introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/319) in GitLab 11.4)
is displayed at the end of each document and can be omitted by adding a key into
@@ -180,7 +178,7 @@ feedback: false
The default is to leave it there. If you want to omit it from a document, you
must check with a technical writer before doing so.
-### Disqus
+#### Disqus
We also have integrated the docs site with Disqus (introduced by
[!151](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/151)),
@@ -206,7 +204,7 @@ The click events in the feedback section are tracked with Google Tag Manager.
The conversions can be viewed on Google Analytics by navigating to
**Behavior > Events > Top events > docs**.
-## Guidelines for good practices
+### Guidelines for good practices
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36576/) in GitLab 13.2 as GitLab Development documentation.
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index a12c2740083..ade0b89a92c 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -3,3 +3,6 @@ redirect_to: 'styleguide/index.md'
---
This document was moved to [another location](styleguide/index.md).
+
+<!-- This redirect file can be deleted after <2022-02-13>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/documentation/styleguide/img/tier_badge.png b/doc/development/documentation/styleguide/img/tier_badge.png
index 674d869da9b..5fc38e08172 100644
--- a/doc/development/documentation/styleguide/img/tier_badge.png
+++ b/doc/development/documentation/styleguide/img/tier_badge.png
Binary files differ
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index bba94c7de7e..7737aa58506 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -7,34 +7,25 @@ description: 'Writing styles, markup, formatting, and other standards for GitLab
# Documentation Style Guide
-This document defines the standards for GitLab documentation.
+This document defines the standards for GitLab documentation, including grammar, formatting, word use, and more.
-For broader information about the documentation, see the [Documentation guidelines](../index.md).
+For style questions, mention `@tw-style` in an issue or merge request. If you have access to the GitLab Slack workspace,
+use the `#docs-processes` channel.
-For guidelines specific to text in the GitLab interface, see the Pajamas [Content](https://design.gitlab.com/content/error-messages/) section.
+In addition to this page, the following resources can help you craft and contribute to documentation:
-For information on how to validate styles locally or by using GitLab CI/CD, see [Testing](../testing.md).
-
-Use this guide for standards on grammar, formatting, word usage, and more.
-
-You can also view a list of [recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix).
-
-If you can't find what you need:
-
-- View the GitLab Handbook for [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) that apply to all GitLab content.
-- Refer to:
-
- - [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/).
- - [Google Developer Documentation Style Guide](https://developers.google.com/style).
-
-If you have questions about style, mention `@tw-style` in an issue or merge request, or, if you have access to the GitLab Slack workspace, use `#docs-process`.
+- [Doc contribution guidelines](../index.md)
+- [Doc style and consistency testing](../testing.md)
+- [UI text guidelines](https://design.gitlab.com/content/error-messages/)
+- [GitLab Handbook style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines)
+- [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/)
+- [Google Developer Documentation Style Guide](https://developers.google.com/style)
+- [Recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix)
## Documentation is the single source of truth (SSOT)
-### Why a single source of truth
-
-The documentation of GitLab products and features is the SSOT for all
-information related to implementation, usage, and troubleshooting. It evolves
+The GitLab documentation is the SSOT for all
+information related to GitLab implementation, usage, and troubleshooting. It evolves
continuously, in keeping with new products and features, and with improvements
for clarity, accuracy, and completeness.
@@ -44,7 +35,7 @@ about GitLab products.
It also informs decisions about the kinds of content we include in our
documentation.
-### All information
+### The documentation includes all information
Include problem-solving actions that may address rare cases or be considered
_risky_, but provide proper context through fully-detailed
@@ -54,10 +45,13 @@ If you think you have found an exception to this rule, contact the
Technical Writing team.
GitLab adds all troubleshooting information to the documentation, no matter how
-unlikely a user is to encounter a situation. For the [Troubleshooting sections](#troubleshooting),
-people in GitLab Support can merge additions themselves.
+unlikely a user is to encounter a situation.
+
+GitLab Support maintains their own
+[troubleshooting content](../../../administration/index.md#support-team-docs)
+in the GitLab documentation.
-### All media types
+### The documentation includes all media types
Include any media types/sources if the content is relevant to readers. You can
freely include or link presentations, diagrams, and videos. No matter who
@@ -71,48 +65,33 @@ include it.
quotation with the source cited. Typically it is better to either rephrase
relevant information in your own words or link out to the other source.
-### No special types
+### Topic types
In the software industry, it is a best practice to organize documentation in
-different types. For example, [Divio recommends](https://www.divio.com/blog/documentation/):
+different types. For example:
-- Tutorials
-- How-to guides
-- Explanation
-- Reference (for example, a glossary)
+- Concepts
+- Tasks
+- Reference
+- Troubleshooting
-At GitLab, we have so many product changes in our monthly releases that we can't
-afford to continuously update multiple types of information. If we have multiple
-types, the information becomes outdated. Therefore, we have a
-[single template](../structure.md) for documentation.
+At GitLab, we have not traditionally used topic types. However, we are starting to
+move in this direction, so we can address these issues:
-GitLab documentation does not distinguish specific document types. We are open to
-reconsidering this policy after the documentation has reached a future stage of
-maturity and quality. If you are reading this, then despite our continuous
-improvement efforts, that point hasn't been reached.
+- **Content is hard to find.** Our docs are comprehensive and include a large amount of
+ useful information. Topic types create repeatable patterns that make our content easier
+ to scan and parse.
+- **Content is often written from the contributor's point of view.** Our docs
+ are written by contributors. Topic types (tasks specifically) help put
+ information into a format that is geared toward helping others, rather than
+ documenting how a feature was implemented.
-### Link instead of summarize
+GitLab uses these [topic type templates](../structure.md).
-There is a temptation to summarize the information on another page, which
-causes the information to live in two places. Instead, link to the single source
-of truth and explain why it is important to consume the information.
+### Link instead of repeating text
-### Organize by topic, not by type
-
-We organize content by topic, not by type, so it can be located in the
-single-source-of-truth (SSOT) section for the subject matter. Top-level audience-type
-folders, like `administration`, are exceptions.
-
-For example, do not create groupings of similar media types. For example:
-
-- Glossaries.
-- FAQs.
-- Sets of all articles or videos.
-
-Such grouping of content by type makes it difficult to browse for the information
-you need and difficult to maintain up-to-date content. Instead, organize content
-by its subject (for example, everything related to CI goes together) and
-cross-link between any related content.
+Rather than repeating information from another topic, link to the single source
+of truth and explain why it is important.
### Docs-first methodology
@@ -127,14 +106,9 @@ of GitLab more efficient.
should be to create a merge request (MR) to add this information to the
documentation. You can then share the MR to communicate this information.
-New information about the future usage or troubleshooting
-of GitLab should not be written directly in a forum or other messaging system.
-Instead, add it to a documentation merge request, then reference it. Note
-that among any other documentation changes, you can either:
-
-- Add a [Troubleshooting section](#troubleshooting) to a doc if none exists.
-- Un-comment and use the placeholder Troubleshooting section included as part of
- our [documentation template](../structure.md#template-for-new-docs), if present.
+New information that would be useful toward the future usage or troubleshooting
+of GitLab should not be written directly in a forum or other messaging system,
+but added to a documentation MR and then referenced, as described above.
The more we reflexively add information to the documentation, the more
the documentation helps others efficiently accomplish tasks and solve problems.
@@ -217,8 +191,11 @@ included in backticks. For example:
## Structure
-Because we want documentation to be a SSOT, we should [organize by topic, not by
-type](#organize-by-topic-not-by-type).
+We include concept and task topic types in the same larger topic.
+
+In general, we have one topic that's a [landing page](../structure.md#landing-pages).
+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
@@ -299,7 +276,7 @@ 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-summarize)
+[Link to a single source of truth instead.](#link-instead-of-repeating-text)
### References across documents
@@ -389,7 +366,7 @@ by default.
Capitalize names of:
- GitLab [product tiers](https://about.gitlab.com/pricing/). For example,
- GitLab Core and GitLab Ultimate. (Tested in [`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml).)
+ GitLab Free and GitLab Ultimate. (Tested in [`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml).)
- Third-party organizations, software, and products. For example, Prometheus,
Kubernetes, Git, and The Linux Foundation.
- Methods or methodologies. For example, Continuous Integration,
@@ -549,6 +526,7 @@ You can use these fake tokens as examples:
| scalability | Do not use when talking about increasing GitLab performance for additional users. The words scale or scaling are sometimes acceptable, but references to increasing GitLab performance for additional users should direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md) page. |
| simply | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
| slashes | Instead of **and/or**, use **or** or another sensible construction. This rule also applies to other slashes, like **follow/unfollow**. Some exceptions (like **CI/CD**) are allowed. |
+| subgroup | Use instead of `sub-group`. |
| that | Do not use. Example: `the file that you save` can be `the file you save`. |
| useful | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
| utilize | Do not use. Use **use** instead. It's more succinct and easier for non-native English speakers to understand. |
@@ -765,8 +743,6 @@ Items nested in lists should always align with the first character of the list
item. In unordered lists (using `-`), this means two spaces for each level of
indentation:
-<!-- vale off -->
-
````markdown
- Unordered list item 1
@@ -788,12 +764,8 @@ indentation:
![an image that will nest inside list item 4](image.png)
````
-<!-- vale on -->
-
For ordered lists, use three spaces for each level of indentation:
-<!-- vale off -->
-
````markdown
1. Ordered list item 1
@@ -815,8 +787,6 @@ For ordered lists, use three spaces for each level of indentation:
![an image that will nest inside list item 4](image.png)
````
-<!-- vale on -->
-
You can nest full lists inside other lists using the same rules as above. If you
want to mix types, that's also possible, if you don't mix items at the same
level:
@@ -942,7 +912,7 @@ NOTE:
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39717) in
GitLab 13.4, [product badges](#product-tier-badges) used in headings aren't
included in the generated anchor links. For example, when you link to
-`## This is an example **(CORE)**`, use the anchor `#this-is-an-example`.
+`## This is an example **(FREE)**`, use the anchor `#this-is-an-example`.
Keep in mind that the GitLab user interface links to many documentation pages
and anchor links to take the user to the right spot. When you change
@@ -966,8 +936,8 @@ this option.
## Links
-Links are important in GitLab documentation. They allow you to [link instead of
-summarizing](#link-instead-of-summarize) to help preserve a [single source of truth](#why-a-single-source-of-truth)
+Links are important in GitLab documentation. Use links instead of
+summarizing to help preserve a [single source of truth](#documentation-is-the-single-source-of-truth-ssot)
in GitLab documentation.
We include guidance for links in these categories:
@@ -1020,7 +990,8 @@ To link to internal documentation:
- Use relative links to Markdown files in the same repository.
- Do not use absolute URLs or URLs from `docs.gitlab.com`.
- Use `../` to navigate to higher-level directories.
-- Don't prepend `./` to links to files or directories.
+- Don't prepend `./` to links to files or directories. To link to a file in the
+ same directory or one of its sub-directories, use the syntax `path/to/file.md`.
- Don't link relative to root. For example, `/ee/user/gitlab_com/index.md`.
Don't:
@@ -1045,6 +1016,7 @@ To link to internal documentation:
- `../../merge_requests/index.md`
- `../../issues/tags.md`
- `../../issues/tags.md#stages`
+ - `issues/tags.md`
NOTE:
Using the Markdown extension is necessary for the [`/help`](../index.md#gitlab-help)
@@ -1345,8 +1317,6 @@ hidden on the documentation site, but is displayed by `/help`.
- For regular fenced code blocks, always use a highlighting class corresponding to
the language for better readability. Examples:
- <!-- vale off -->
-
````markdown
```ruby
Ruby code
@@ -1365,8 +1335,6 @@ hidden on the documentation site, but is displayed by `/help`.
```
````
- <!-- vale on -->
-
Syntax highlighting is required for fenced code blocks added to the GitLab
documentation. Refer to this table for the most common language classes,
or check the [complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
@@ -1671,8 +1639,8 @@ the blockquote to use a bulleted list:
If a feature is moved to another tier:
```markdown
-> - [Moved](<link-to-issue>) from GitLab Premium to GitLab Starter in 11.8.
-> - [Moved](<link-to-issue>) from GitLab Starter to GitLab Core in 12.0.
+> - [Moved](<link-to-issue>) from GitLab Ultimate to GitLab Premium in 11.8.
+> - [Moved](<link-to-issue>) from GitLab Premium to GitLab Free in 12.0.
```
If a feature is deprecated, include a link to a replacement (when available):
@@ -1779,7 +1747,7 @@ To add a tier badge to a heading, add the relevant [tier badge](#available-produ
after the heading text. For example:
```markdown
-# Heading title `**(CORE)**`
+# Heading title **(FREE)**
```
#### Product tier badges on other content
@@ -1787,30 +1755,26 @@ after the heading text. For example:
In paragraphs, list names, and table cells, an information icon displays when you
add a tier badge. More verbose information displays when a user points to the icon:
-- `**(STARTER)**` displays as **(STARTER)**
-- `**(STARTER ONLY)**` displays as **(STARTER ONLY)**
-- `**(SILVER ONLY)**` displays as **(SILVER ONLY)**
+- `**(FREE)**` displays as **(FREE)**
+- `**(FREE SELF)**` displays as **(FREE SELF)**
+- `**(FREE SAAS)**` displays as **(FREE SAAS)**
-The `**(STARTER)**` generates a `span` element to trigger the
-badges and tooltips (`<span class="badge-trigger starter">`). When the keyword
-_only_ is added, the corresponding GitLab.com badge isn't displayed.
+The `**(FREE)**` generates a `span` element to trigger the
+badges and tooltips (`<span class="badge-trigger free">`).
#### Available product tier badges
-| Tier in which feature is available | Tier badge |
-|:-----------------------------------------------------------------------|:----------------------|
-| GitLab Core and GitLab.com Free, and their higher tiers | `**(CORE)**` |
-| GitLab Starter and GitLab.com Bronze, and their higher tiers | `**(STARTER)**` |
-| GitLab Premium and GitLab.com Silver, and their higher tiers | `**(PREMIUM)**` |
-| GitLab Ultimate and GitLab.com Gold | `**(ULTIMATE)**` |
-| _Only_ GitLab Core and higher tiers (no GitLab.com-based tiers) | `**(CORE ONLY)**` |
-| _Only_ GitLab Starter and higher tiers (no GitLab.com-based tiers) | `**(STARTER ONLY)**` |
-| _Only_ GitLab Premium and higher tiers (no GitLab.com-based tiers) | `**(PREMIUM ONLY)**` |
-| _Only_ GitLab Ultimate (no GitLab.com-based tiers) | `**(ULTIMATE ONLY)**` |
-| _Only_ GitLab.com Free and higher tiers (no self-managed instances) | `**(FREE ONLY)**` |
-| _Only_ GitLab.com Bronze and higher tiers (no self-managed instances) | `**(BRONZE ONLY)**` |
-| _Only_ GitLab.com Silver and higher tiers (no self-managed instances) | `**(SILVER ONLY)**` |
-| _Only_ GitLab.com Gold (no self-managed instances) | `**(GOLD ONLY)**` |
+| Tier in which feature is available | Tier badge |
+|:--------------------------------------------------------------------------|:----------------------|
+| GitLab Free self-managed and SaaS, and higher tiers | `**(FREE)**` |
+| GitLab Premium self-managed and SaaS, and their higher tiers | `**(PREMIUM)**` |
+| GitLab Ultimate self-managed and SaaS | `**(ULTIMATE)**` |
+| _Only_ GitLab Free self-managed and higher tiers (no SaaS-based tiers) | `**(FREE SELF)**` |
+| _Only_ GitLab Premium self-managed and higher tiers (no SaaS-based tiers) | `**(PREMIUM SELF)**` |
+| _Only_ GitLab Ultimate self-managed (no SaaS-based tiers) | `**(ULTIMATE SELF)**` |
+| _Only_ GitLab Free SaaS and higher tiers (no self-managed instances) | `**(FREE SAAS)**` |
+| _Only_ GitLab Premium SaaS and higher tiers (no self-managed instances) | `**(PREMIUM SAAS)**` |
+| _Only_ GitLab Ultimate SaaS (no self-managed instances) | `**(ULTIMATE SAAS)**` |
Topics that mention the `gitlab.rb` file are referring to
self-managed instances of GitLab. To prevent confusion, include the relevant `TIER ONLY`
@@ -1859,8 +1823,6 @@ Configuration procedures can require users to edit configuration files, reconfig
GitLab, or restart GitLab. Use these styles to document these steps, replacing
`PATH/TO` with the appropriate path:
-<!-- vale off -->
-
````markdown
**For Omnibus installations**
@@ -1888,8 +1850,6 @@ GitLab, or restart GitLab. Use these styles to document these steps, replacing
GitLab for the changes to take effect.
````
-<!-- vale on -->
-
In this case:
- Bold the installation method's name.
@@ -1899,21 +1859,6 @@ In this case:
- Use the [GitLab Restart](#gitlab-restart) section to explain any required
restart or reconfigure of GitLab.
-### Troubleshooting
-
-For troubleshooting sections, provide as much context as possible so
-users can identify their problem and resolve it on their own. You
-can facilitate this by making sure the troubleshooting content addresses:
-
-1. The problem the user needs to solve.
-1. How the user can confirm they have the problem.
-1. Steps the user can take towards resolution of the problem.
-
-If the contents of each category can be summarized in one line and a list of
-steps aren't required, consider setting up a [table](#tables). Create headers of
-_Problem_ \| _Cause_ \| _Solution_ (or _Workaround_ if the fix is temporary), or
-_Error message_ \| _Solution_.
-
## Feature flags
Learn how to [document features deployed behind flags](../feature_flags.md). For
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index 561727648f0..f3d6e0a5c71 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -93,8 +93,8 @@ To execute documentation link tests locally:
### UI link tests
-The `ui-docs-links lint` job uses `haml-lint` to test that all links to docs from
-UI elements (`app/views` files, for example) are linking to valid docs and anchors.
+The `ui-docs-links lint` job uses `haml-lint` to test that all documentation links from
+UI elements (`app/views` files, for example) are linking to valid pages and anchors.
To run the `ui-docs-links` test locally:
@@ -156,12 +156,12 @@ markdownlint configuration is found in the following projects:
- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.markdownlint.json)
- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/.markdownlint.json)
-This configuration is also used within build pipelines.
+This configuration is also used in build pipelines.
You can use markdownlint:
- [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--).
-- [Within a code editor](#configure-editors).
+- [In a code editor](#configure-editors).
- [In a `pre-push` hook](#configure-pre-push-hooks).
### Vale
@@ -172,10 +172,10 @@ English language. Vale's configuration is stored in the
directory of projects.
Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/) that extend any of
-several types of checks, which we store in the `.linting/vale/styles/gitlab` directory within the
+several types of checks, which we store in the `.linting/vale/styles/gitlab` directory in the
documentation directory of projects.
-Vale configuration is found in the following projects:
+You can find Vale configuration in the following projects:
- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab)
- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab)
@@ -183,13 +183,13 @@ Vale configuration is found in the following projects:
- [`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)
-This configuration is also used within build pipelines, where
+This configuration is also used in build pipelines, where
[error-level rules](#vale-result-types) are enforced.
You can use Vale:
- [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage).
-- [Within a code editor](#configure-editors).
+- [In a code editor](#configure-editors).
- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same
configuration as the CI/CD pipelines), and does not report suggestions or warnings.
@@ -243,32 +243,40 @@ To match the versions of `markdownlint-cli` and `vale` used in the GitLab projec
[versions used](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L447)
when building the `image:docs-lint-markdown` Docker image containing these tools for CI/CD.
-| Tool | Version | Command | Additional information |
-|--------------------|----------|-------------------------------------------|------------------------|
-| `markdownlint-cli` | Latest | `yarn global add markdownlint-cli` | n/a |
-| `markdownlint-cli` | Specfic | `yarn global add markdownlint-cli@0.23.2` | The `@` indicates a specific version, and this example updates the tool to version `0.23.2`. |
-| Vale | Latest | `brew update && brew upgrade vale` | This command is for macOS only. |
-| Vale | Specific | n/a | Not possible using `brew`, but can be [directly downloaded](https://github.com/errata-ai/vale/releases). |
+| Tool | Version | Command | Additional information |
+|--------------------|-----------|-------------------------------------------|------------------------|
+| `markdownlint-cli` | Latest | `yarn global add markdownlint-cli` | n/a |
+| `markdownlint-cli` | Specific | `yarn global add markdownlint-cli@0.23.2` | The `@` indicates a specific version, and this example updates the tool to version `0.23.2`. |
+| Vale | Latest | `brew update && brew upgrade vale` | This command is for macOS only. |
+| Vale | Specific | n/a | Not possible using `brew`, but can be [directly downloaded](https://github.com/errata-ai/vale/releases). |
### Configure editors
Using linters in your editor is more convenient than having to run the commands from the
command line.
-To configure markdownlint within your editor, install one of the following as appropriate:
+To configure markdownlint in your editor, install one of the following as appropriate:
-- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
-- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
-- [Atom](https://atom.io/packages/linter-node-markdownlint)
-- [Vim](https://github.com/dense-analysis/ale)
+- Sublime Text [`SublimeLinter-contrib-markdownlint` package](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint).
+- Visual Studio Code [`DavidAnson.vscode-markdownlint` extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint).
+- Atom [`linter-node-markdownlint` package](https://atom.io/packages/linter-node-markdownlint).
+- Vim [ALE plugin](https://github.com/dense-analysis/ale).
-To configure Vale within your editor, install one of the following as appropriate:
+To configure Vale in your editor, install one of the following as appropriate:
-- The Sublime Text [`SublimeLinter-contrib-vale` plugin](https://packagecontrol.io/packages/SublimeLinter-contrib-vale).
-- The Visual Studio Code [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server).
- You don't need Vale Server to use the plugin. You can configure the plugin to
+- 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).
-- [Vim](https://github.com/dense-analysis/ale).
+
+ In the extension's settings:
+
+ - 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.
+ - 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.
+
+- Vim [ALE plugin](https://github.com/dense-analysis/ale).
We don't use [Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application).
@@ -286,7 +294,7 @@ Configuration for `lefthook` is available in the [`lefthook.yml`](https://gitlab
file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project.
To set up `lefthook` for documentation linting, see
-[Pre-push static analysis](../contributing/style_guides.md#pre-push-static-analysis).
+[Pre-push static analysis](../contributing/style_guides.md#pre-push-static-analysis-with-lefthook).
### Show subset of Vale alerts
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index e809ca84707..8e2028532e4 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -65,13 +65,15 @@ To update GitLab documentation:
NOTE:
Work in a fork if you do not have Developer access to the GitLab project.
-Request help from the Technical Writing team if you:
+### Ask for help
+
+Ask for help from the Technical Writing team if you:
- Need help to choose the correct place for documentation.
- Want to discuss a documentation idea or outline.
- Want to request any other help.
-To request help:
+To identify someone who can help you:
1. Locate the Technical Writer for the relevant
[DevOps stage group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 5be601187ca..81014b7624c 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -92,12 +92,36 @@ class User < ActiveRecord::Base
# ... lots of code here ...
end
-User.prepend_if_ee('EE::User')
+User.prepend_ee_mod
```
Do not use methods such as `prepend`, `extend`, and `include`. Instead, use
-`prepend_if_ee`, `extend_if_ee`, or `include_if_ee`. These methods take a
-_String_ containing the full module name as the argument, not the module itself.
+`prepend_ee_mod`, `extend_ee_mod`, or `include_ee_mod`. These methods will try to
+find the relevant EE module by the name of the receiver module, for example;
+
+```ruby
+module Vulnerabilities
+ class Finding
+ #...
+ end
+end
+
+Vulnerabilities::Finding.prepend_ee_mod
+```
+
+will prepend the module named `::EE::Vulnerabilities::Finding`.
+
+If the extending module does not follow this naming convention, you can also provide the module name
+by using `prepend_if_ee`, `extend_if_ee`, or `include_if_ee`. These methods take a
+_String_ containing the full module name as the argument, not the module itself, like so;
+
+```ruby
+class User
+ #...
+end
+
+User.prepend_if_ee('::EE::UserExtension')
+```
Since the module would require an `EE` namespace, the file should also be
put in an `ee/` sub-directory. For example, we want to extend the user model
@@ -142,9 +166,9 @@ still having access the class's implementation with `super`.
There are a few gotchas with it:
- you should always [`extend ::Gitlab::Utils::Override`](utilities.md#override) and use `override` to
- guard the "overrider" method to ensure that if the method gets renamed in
+ guard the `overrider` method to ensure that if the method gets renamed in
CE, the EE override isn't silently forgotten.
-- when the "overrider" would add a line in the middle of the CE
+- when the `overrider` would add a line in the middle of the CE
implementation, you should refactor the CE method and split it in
smaller methods. Or create a "hook" method that is empty in CE,
and with the EE-specific implementation in EE.
@@ -947,7 +971,7 @@ information on managing page-specific JavaScript within EE.
#### Child Component only used in EE
-To separate Vue template differences we should [async import the components](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
+To separate Vue template differences we should [import the components asynchronously](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
Doing this allows for us to load the correct component in EE while in CE
we can load a empty component that renders nothing. This code **should**
@@ -1044,7 +1068,7 @@ export default {
**For EE components that need different results for the same computed values, we can pass in props to the CE wrapper as seen in the example.**
- **EE Child components**
- - Since we are using the async loading to check which component to load, we'd still use the component's name, check [this example](#child-component-only-used-in-ee).
+ - Since we are using the asynchronous loading to check which component to load, we'd still use the component's name, check [this example](#child-component-only-used-in-ee).
- **EE extra HTML**
- For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` dynamic import
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 8bf8a5fccb8..3392bd1fbf6 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -4,7 +4,7 @@ group: Global Search
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Elasticsearch knowledge **(STARTER ONLY)**
+# Elasticsearch knowledge **(PREMIUM SELF)**
This area is to maintain a compendium of useful information when working with Elasticsearch.
@@ -13,9 +13,9 @@ the [Elasticsearch integration documentation](../integration/elasticsearch.md#en
## Deep Dive
-In June 2019, Mario de la Ossa hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`) on the GitLab [Elasticsearch integration](../integration/elasticsearch.md) to share his domain specific knowledge with anyone who may work in this part of the codebase in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=vrvl-tN2EaA), and the slides on [Google Slides](https://docs.google.com/presentation/d/1H-pCzI_LNrgrL5pJAIQgvLX8Ji0-jIKOg1QeJQzChug/edit) and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/c5aa32b6b07476fa8b597004899ec538/Elasticsearch_Deep_Dive.pdf). Everything covered in this deep dive was accurate as of GitLab 12.0, and while specific details may have changed since then, it should still serve as a good introduction.
+In June 2019, Mario de la Ossa hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`) on the GitLab [Elasticsearch integration](../integration/elasticsearch.md) to share his domain specific knowledge with anyone who may work in this part of the codebase in the future. You can find the <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=vrvl-tN2EaA), and the slides on [Google Slides](https://docs.google.com/presentation/d/1H-pCzI_LNrgrL5pJAIQgvLX8Ji0-jIKOg1QeJQzChug/edit) and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/c5aa32b6b07476fa8b597004899ec538/Elasticsearch_Deep_Dive.pdf). Everything covered in this deep dive was accurate as of GitLab 12.0, and while specific details may have changed since then, it should still serve as a good introduction.
-In August 2020, a second Deep Dive was hosted, focusing on [GitLab-specific architecture for multi-indices support](#zero-downtime-reindexing-with-multiple-indices). The [recording on YouTube](https://www.youtube.com/watch?v=0WdPR9oB2fg) and the [slides](https://lulalala.gitlab.io/gitlab-elasticsearch-deepdive/) are available. Everything covered in this deep dive was accurate as of GitLab 13.3.
+In August 2020, a second Deep Dive was hosted, focusing on [GitLab-specific architecture for multi-indices support](#zero-downtime-reindexing-with-multiple-indices). The <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=0WdPR9oB2fg) and the [slides](https://lulalala.gitlab.io/gitlab-elasticsearch-deepdive/) are available. Everything covered in this deep dive was accurate as of GitLab 13.3.
## Supported Versions
@@ -69,7 +69,7 @@ The `whitespace` tokenizer was selected in order to have more control over how t
Please see the `code` filter for an explanation on how tokens are split.
NOTE:
-Currently the [Elasticsearch code_analyzer doesn't account for all code cases](../integration/elasticsearch.md#known-issues).
+The [Elasticsearch code_analyzer doesn't account for all code cases](../integration/elasticsearch.md#elasticsearch-code_analyzer-doesnt-account-for-all-code-cases).
#### `code_search_analyzer`
@@ -210,7 +210,7 @@ class MigrationName < Elastic::Migration
end
```
-Applied migrations are stored in `gitlab-#{RAILS_ENV}-migrations` index. All unexecuted migrations
+Applied migrations are stored in `gitlab-#{RAILS_ENV}-migrations` index. All migrations not executed
are applied by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb)
cron worker sequentially.
@@ -337,7 +337,7 @@ cluster.routing.allocation.disk.watermark.low: 15gb
cluster.routing.allocation.disk.watermark.high: 10gb
```
-Restart Elasticsearch, and the `read_only_allow_delete` will clear on it's own.
+Restart Elasticsearch, and the `read_only_allow_delete` will clear on its own.
_from "Disk-based Shard Allocation | Elasticsearch Reference" [5.6](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/disk-allocator.html#disk-allocator) and [6.x](https://www.elastic.co/guide/en/elasticsearch/reference/6.7/disk-allocator.html)_
@@ -351,7 +351,7 @@ simply reindex everything from scratch.
If your Elasticsearch index is incredibly large it may be too time consuming or
cause too much downtime to reindex from scratch. There aren't any built in
-mechanisms for automatically finding discrepencies and resyncing an
+mechanisms for automatically finding discrepancies and resyncing an
Elasticsearch index if it gets out of sync but one tool that may be useful is
looking at the logs for all the updates that occurred in a time range you
believe may have been missed. This information is very low level and only
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index a1899ab5f18..21c61324dc1 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -12,7 +12,7 @@ Experiments are run as an A/B test and are behind a feature flag to turn the tes
## Experiment tracking issue
-Each experiment should have an [Experiment tracking](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=growth%20experiment&search=%22Experiment+tracking%22) issue to track the experiment from roll-out through to cleanup/removal. Immediately after an experiment is deployed, the due date of the issue should be set (this depends on the experiment but can be up to a few weeks in the future).
+Each experiment should have an [Experiment tracking](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=growth%20experiment&search=%22Experiment+tracking%22) issue to track the experiment from roll-out through to cleanup/removal. The tracking issue is similar to a feature flag rollout issue, and is also used to track the status of an experiment. Immediately after an experiment is deployed, the due date of the issue should be set (this depends on the experiment but can be up to a few weeks in the future).
After the deadline, the issue needs to be resolved and either:
- It was successful and the experiment becomes the new default.
@@ -36,7 +36,17 @@ and link to the issue that resolves the experiment. If the experiment is
successful and becomes part of the product, any follow up issues should be
addressed.
-## How to create an A/B test
+## Experiments using `gitlab-experiment`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300383) in GitLab 13.7.
+> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - It's enabled on GitLab.com.
+> - It is not yet intended for use in GitLab self-managed instances.
+
+[GitLab Experiment](https://gitlab.com/gitlab-org/gitlab-experiment/) is a gem included
+in GitLab that can be used for running experiments.
+
+## How to create an A/B test using `experimentation.rb`
### Implement the experiment
@@ -315,7 +325,7 @@ Note that the use of this method requires that we have first [recorded the user
### Enable the experiment
-After all merge requests have been merged, use [`chatops`](../../ci/chatops/README.md) in the
+After all merge requests have been merged, use [`chatops`](../../ci/chatops/index.md) in the
[appropriate channel](../feature_flags/controls.md#communicate-the-change) to start the experiment for 10% of the users.
The feature flag should have the name of the experiment with the `_experiment_percentage` suffix appended.
For visibility, please also share any commands run against production in the `#s_growth` channel:
@@ -358,7 +368,7 @@ Use a comma to list more than one experiment to be forced:
document.cookie = "force_experiment=<EXPERIMENT_KEY>,<ANOTHER_EXPERIMENT_KEY>; path=/";
```
-Clear the experiments by unsetting the `force_experiment` cookie:
+To clear the experiments, unset the `force_experiment` cookie:
```javascript
document.cookie = "force_experiment=; path=/";
diff --git a/doc/development/export_csv.md b/doc/development/export_csv.md
index 99b6062736d..0bf12149779 100644
--- a/doc/development/export_csv.md
+++ b/doc/development/export_csv.md
@@ -14,7 +14,7 @@ This document lists the different implementations of CSV export in GitLab codeba
| 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_dashboard/#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) |
| 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/security_dashboard/#export-vulnerabilities) |
+| 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-vulnerabilities) |
| 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) |
NOTE:
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index 92730e8139f..5ad1a701fac 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -9,11 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Resources
[Chrome Accessibility Developer Tools](https://github.com/GoogleChrome/accessibility-developer-tools)
-are useful for testing for potential accessibility problems in GitLab.
+assist with testing for potential accessibility problems in GitLab.
-The [axe](https://www.deque.com/axe/) browser extension (available for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/) and [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd)) is
-also a handy tool for running audits and getting feedback on markup, CSS and even potentially problematic color usages.
+The [axe](https://www.deque.com/axe/) browser extension (available for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/) and [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd)) provides running audits and feedback on markup, CSS, and even potentially problematic color usages.
Accessibility best-practices and more in-depth information are available on
-[the Audit Rules page](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules) for the Chrome Accessibility Developer Tools. The [Awesome Accessibility](https://github.com/brunopulis/awesome-a11y) list is also a
-useful compilation of accessibility-related material.
+[the Audit Rules page](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules) for the Chrome Accessibility Developer Tools. The [Awesome Accessibility](https://github.com/brunopulis/awesome-a11y) list is a compilation of accessibility-related material.
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
index 964837dc5f7..c51f99ca9d2 100644
--- a/doc/development/fe_guide/architecture.md
+++ b/doc/development/fe_guide/architecture.md
@@ -6,9 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Architecture
-When you are developing a new feature that requires architectural design, or if
-you are changing the fundamental design of an existing feature, make sure it is
-discussed with one of the Frontend Architecture Experts.
+When developing a feature that requires architectural design, or changing the fundamental design of an existing feature, discuss it with a Frontend Architecture Expert.
A Frontend Architect is an expert who makes high-level Frontend design decisions
and decides on technical standards, including coding standards and frameworks.
diff --git a/doc/development/fe_guide/axios.md b/doc/development/fe_guide/axios.md
index cf5a4970c04..2d699b305ce 100644
--- a/doc/development/fe_guide/axios.md
+++ b/doc/development/fe_guide/axios.md
@@ -44,7 +44,7 @@ Advantages over [`spyOn()`](https://jasmine.github.io/api/edge/global.html#spyOn
- no need to create response objects
- does not allow call through (which we want to avoid)
-- simple API to test error cases
+- clear API to test error cases
- provides `replyOnce()` to allow for different responses
We have also decided against using [Axios interceptors](https://github.com/axios/axios#interceptors) because they are not suitable for mocking.
diff --git a/doc/development/fe_guide/components.md b/doc/development/fe_guide/components.md
deleted file mode 100644
index 6b6274a6480..00000000000
--- a/doc/development/fe_guide/components.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/components/status/'
----
diff --git a/doc/development/fe_guide/dark_mode.md b/doc/development/fe_guide/dark_mode.md
new file mode 100644
index 00000000000..dd7ffd1ee6c
--- /dev/null
+++ b/doc/development/fe_guide/dark_mode.md
@@ -0,0 +1,77 @@
+---
+type: reference, dev
+stage: none
+group: Development
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+This page is about developing dark mode for GitLab. We also have documentation on how
+[to enable dark mode](../../user/profile/preferences.md#dark-mode).
+
+# How dark mode works
+
+Short version: Reverse the color palette and override a few Bootstrap variables.
+
+Note the following:
+
+- The dark mode palette is defined in `app/assets/stylesheets/themes/_dark.scss`.
+ This is loaded _before_ application.scss to generate `application_dark.css`
+ - We define two types of variables in `_dark.scss`:
+ - SCSS variables are used in framework, components, and utitlity classes.
+ - CSS variables are used for any colors within the `app/assets/stylesheets/page_bundles` directory.
+- `app/views/layouts/_head.html.haml` then loads application or application_dark based on the user's theme preference.
+
+As we do not want to generate separate `_dark.css` variants of every page_bundle file,
+we use CSS variables with SCSS variables as fallbacks. This is because when we generate the `page_bundles`
+CSS, we get the variable values from `_variables.scss`, so any SCSS variables have light mode values.
+
+As the CSS variables defined in `_dark.scss` are available in the browser, they have the
+correct colors for dark mode.
+
+```scss
+color: var(--gray-500, $gray-500);
+```
+
+## Utility classes
+
+We generate a separate `utilities_dark.css` file for utility classes containing the inverted values. So a class
+such as `gl-text-white` specifies a text color of `#333` in dark mode. This means you do not have to
+add multiple classes every time you want to add a color.
+
+Currently, we cannot set up a utility class only in dark mode. We hope to address that
+[issue](https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1141) soon.
+
+## Using different values in light and dark mode
+
+In most cases, we can use the same values for light and dark mode. If that is not possible, you
+can add an override using the `.gl-dark` class that dark mode adds to `body`:
+
+```scss
+color: $gray-700;
+.gl-dark & {
+ color: var(--gray-500);
+}
+```
+
+NOTE:
+Avoid using a different value for the SCSS fallback
+
+```scss
+// avoid where possible
+// --gray-500 (#999) in dark mode
+// $gray-700 (#525252) in light mode
+color: var(--gray-500, $gray-700);
+```
+
+We [plan to add](https://gitlab.com/gitlab-org/gitlab/-/issues/301147) the CSS variables to light mode. When that happens, different values for the SCSS fallback will no longer work.
+
+## When to use SCSS variables
+
+There are a few things we do in SCSS that we cannot (easily) do with CSS, such as the following
+functions:
+
+- `lighten`
+- `darken`
+- `color-yiq` (color contrast)
+
+If those are needed then SCSS variables should be used.
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md
index b036819cde1..8fe03544f85 100644
--- a/doc/development/fe_guide/dependencies.md
+++ b/doc/development/fe_guide/dependencies.md
@@ -6,28 +6,75 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Frontend dependencies
-## Package manager
+We use [yarn@1](https://classic.yarnpkg.com/lang/en/) to manage frontend dependencies.
-We use [Yarn](https://yarnpkg.com/) to manage frontend dependencies. There are a few exceptions, stored in `vendor/assets/`.
+There are a few exceptions in the GitLab repository, stored in `vendor/assets/`.
-## Updating dependencies
+## What are production and development dependencies?
+
+These dependencies are defined in two groups within `package.json`, `dependencies` and `devDependencies`.
+For our purposes, we consider anything that is required to compile our production assets a "production" dependency.
+That is, anything required to run the `webpack` script with `NODE_ENV=production`.
+Tools like `eslint`, `jest`, and various plugins and tools used in development are considered `devDependencies`.
+This distinction is used by omnibus to determine which dependencies it requires when building GitLab.
-### Renovate GitLab Bot
+Exceptions are made for some tools that we require in the
+`compile-production-assets` CI job such as `webpack-bundle-analyzer` to analyze our
+production assets post-compile.
+
+## Updating dependencies
We use the [Renovate GitLab Bot](https://gitlab.com/gitlab-org/frontend/renovate-gitlab-bot) to
-automatically create merge requests for updating dependencies of several projects. You can find the
-up-to-date list of projects managed by the renovate bot in the project’s README. Some key dependencies
-updated using renovate are:
+automatically create merge requests for updating dependencies of several projects.
+You can find the up-to-date list of projects managed by the renovate bot in the project’s README.
+
+Some key dependencies updated using renovate are:
- [`@gitlab/ui`](https://gitlab.com/gitlab-org/gitlab-ui)
- [`@gitlab/svgs`](https://gitlab.com/gitlab-org/gitlab-svgs)
- [`@gitlab/eslint-plugin`](https://gitlab.com/gitlab-org/frontend/eslint-plugin)
+- And any other package in the `@gitlab/` scope
+
+We have the goal of updating [_all_ dependencies with renovate](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/21).
+
+Updating dependencies automatically has several benefits, have a look at this [example MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53613).
+
+- MRs will be created automatically when new versions are released
+- MRs can easily be rebased and updated with just checking a checkbox in the MR description
+- MRs contain changelog summaries and links to compare the different package versions
+- MRs can be assigned to people directly responsible for the dependencies
+
+### Community contributions updating dependencies
+
+It is okay to reject Community Contributions that solely bump dependencies.
+Simple dependency updates are better done automatically for the reasons provided above.
+If a community contribution needs to be rebased, runs into conflicts, or goes stale, the effort required
+to instruct the contributor to correct it often outweighs the benefits.
+
+If a dependency update is accompanied with significant migration efforts, due to major version updates,
+a community contribution is acceptable.
+
+Here is a message you can use to explain to community contributors as to why we reject simple updates:
+
+```markdown
+Hello CONTRIBUTOR!
+
+Thank you very much for this contribution. It seems like you are doing a "simple" dependency update.
+
+If a dependency update is as simple as increasing the version number, we'd like a Bot to do this to save you and ourselves some time.
+
+This has certain benefits as outlined in our <a href="https://docs.gitlab.com/ee/development/fe_guide/dependencies.html#updating-dependencies">Frontend development guidelines</a>.
+
+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.
+/close
+```
### Blocked dependencies
-We discourage installing some dependencies in [GitLab repository](https://gitlab.com/gitlab-org/gitlab)
-because they can create conflicts in the dependency tree. Blocked dependencies are declared in the
-`blockDependencies` property of the GitLab [`package.json` file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/package.json).
+We discourage installing some dependencies in [GitLab repository](https://gitlab.com/gitlab-org/gitlab) because they can create conflicts in the dependency tree.
+Blocked dependencies are declared in the `blockDependencies` property of the GitLab [`package.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/package.json).
## Dependency notes
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
new file mode 100644
index 00000000000..d230e413879
--- /dev/null
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -0,0 +1,219 @@
+---
+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
+---
+
+# Design Anti-patterns
+
+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)
+when figuring out whether or not to refactor, when touching code that uses one of these legacy patterns.
+
+**Please note:** For new features, anti-patterns are not necessarily prohibited, but it is **strongly suggested** to find another approach.
+
+## Shared Global Object (Anti-pattern)
+
+A shared global object is an instance of something that can be accessed from anywhere and therefore has no clear owner.
+
+Here's an example of this pattern applied to a Vuex Store:
+
+```javascript
+const createStore = () => new Vuex.Store({
+ actions,
+ state,
+ mutations
+});
+
+// Notice that we are forcing all references to this module to use the same single instance of the store.
+// We are also creating the store at import-time and there is nothing which can automatically dispose of it.
+//
+// As an alternative, we should simply export the `createStore` and let the client manage the
+// lifecycle and instance of the store.
+export default createStore();
+```
+
+### What problems do Shared Global Objects cause?
+
+Shared Global Objects are convenient because they can be accessed from anywhere. However,
+the convenience does not always outweigh their heavy cost:
+
+- **No ownership.** There is no clear owner to these objects and therefore they assume a non-deterministic
+ and permanent lifecycle. This can be especially problematic for tests.
+- **No access control.** When Shared Global Objects manage some state, this can create some very buggy and difficult
+ coupling situations because there is no access control to this object.
+- **Possible circular references.** Shared Global Objects can also create some circular referencing situations since submodules
+ of the Shared Global Object can reference modules that reference itself (see
+ [this MR for an example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33366)).
+
+Here are some historic examples where this pattern was identified to be problematic:
+
+- [Reference to global Vuex store in IDE](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36401)
+- [Docs update to discourage singleton Vuex store](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36952)
+
+### When could the Shared Global Object pattern be actually appropriate?
+
+Shared Global Object's solve the problem of making something globally accessible. This pattern
+could be appropriate:
+
+- When a responsibility is truly global and should be referenced across the application
+ (e.g., an application-wide Event Bus).
+
+Even in these scenarios, please consider avoiding the Shared Global Object pattern because the
+side-effects can be notoriously difficult to reason with.
+
+### References
+
+To read more on this topic, check out the following references:
+
+- [GlobalVariablesAreBad from C2 wiki](https://wiki.c2.com/?GlobalVariablesAreBad)
+
+## Singleton (Anti-pattern)
+
+The classic [Singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern) is an approach to ensure that only one
+instance of a thing exists.
+
+Here's an example of this pattern:
+
+```javascript
+class MyThing {
+ constructor() {
+ // ...
+ }
+
+ // ...
+}
+
+MyThing.instance = null;
+
+export const getThingInstance = () => {
+ if (MyThing.instance) {
+ return MyThing.instance;
+ }
+
+ const instance = new MyThing();
+ MyThing.instance = instance;
+ return instance;
+};
+```
+
+### What problems do Singletons cause?
+
+It is a big assumption that only one instance of a thing should exist. More often than not,
+a Singleton is misused and causes very tight coupling amongst itself and the modules that reference it.
+
+Here are some historic examples where this pattern was identified to be problematic:
+
+- [Test issues caused by singleton class in IDE](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30398#note_331174190)
+- [Implicit Singleton created by module's shared variables](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/97#note_417515776)
+- [Complexity caused by Singletons](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29461#note_324585814)
+
+Here are some ills that Singletons often produce:
+
+1. **Non-deterministic tests.** Singletons encourage non-deterministic tests because the single instance is shared across
+ individual tests, often causing the state of one test to bleed into another.
+1. **High coupling.** Under the hood, clients of a singleton class all share a single specific
+ instance of an object, which means this pattern inherits all the [problems of Shared Global Object](#what-problems-do-shared-global-objects-cause)
+ such as no clear ownership and no access control. These leads to high coupling situations that can
+ be buggy and difficult to untangle.
+1. **Infectious.** Singletons are infectious, especially when they manage state. Consider the component
+ [RepoEditor](https://gitlab.com/gitlab-org/gitlab/blob/27ad6cb7b76430fbcbaf850df68c338d6719ed2b/app%2Fassets%2Fjavascripts%2Fide%2Fcomponents%2Frepo_editor.vue#L0-1)
+ used in the Web IDE. This component interfaces with a Singleton [Editor](https://gitlab.com/gitlab-org/gitlab/blob/862ad57c44ec758ef3942ac2e7a2bd40a37a9c59/app%2Fassets%2Fjavascripts%2Fide%2Flib%2Feditor.js#L21)
+ which manages some state for working with Monaco. Because of the Singleton nature of the Editor class,
+ the component `RepoEditor` is now forced to be a Singleton as well. Multiple instances of this component
+ would cause production issues because no one truly owns the instance of `Editor`.
+
+### Why is the Singleton pattern popular in other languages like Java?
+
+This is because of the limitations of languages like Java where everything has to be wrapped
+in a class. In JavaScript we have things like object and function literals where we can solve
+many problems with a module that simply exports utility functions.
+
+### When could the Singleton pattern be actually appropriate?**
+
+Singletons solve the problem of enforcing there to be only 1 instance of a thing. It's possible
+that a Singleton could be appropriate in the following rare cases:
+
+- We need to manage some resource that **MUST** have just 1 instance (i.e. some hardware restriction).
+- There is a real [cross-cutting concern](https://en.wikipedia.org/wiki/Cross-cutting_concern) (e.g., logging) and a Singleton provides the simplest API.
+
+Even in these scenarios, please consider avoiding the Singleton pattern.
+
+### What alternatives are there to the Singleton pattern?
+
+#### Utility Functions
+
+When no state needs to be managed, we can simply export utility functions from a module without
+messing with any class instantiation.
+
+```javascript
+// bad - Singleton
+export class ThingUtils {
+ static create() {
+ if(this.instance) {
+ return this.instance;
+ }
+
+ this.instance = new ThingUtils();
+ return this.instance;
+ }
+
+ bar() { /* ... */ }
+
+ fuzzify(id) { /* ... */ }
+}
+
+// good - Utility functions
+export const bar = () => { /* ... */ };
+
+export const fuzzify = (id) => { /* ... */ };
+```
+
+#### Dependency Injection
+
+[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) is an approach which breaks
+coupling by declaring a module's dependencies to be injected from outside the module (e.g., through constructor parameters, a bona-fide Dependency Injection framework, and even Vue's `provide/inject`).
+
+```javascript
+// bad - Vue component coupled to Singleton
+export default {
+ created() {
+ this.mediator = MyFooMediator.getInstance();
+ },
+};
+
+// good - Vue component declares dependency
+export default {
+ inject: ['mediator']
+};
+```
+
+```javascript
+// bad - We're not sure where the singleton is in it's lifecycle so we init it here.
+export class Foo {
+ constructor() {
+ Bar.getInstance().init();
+ }
+
+ stuff() {
+ return Bar.getInstance().doStuff();
+ }
+}
+
+// good - Lets receive this dependency as a constructor argument.
+// It's also not our responsibility to manage the lifecycle.
+export class Foo {
+ constructor(bar) {
+ this.bar = bar;
+ }
+
+ stuff() {
+ return this.bar.doStuff();
+ }
+}
+```
+
+In this example, the lifecycle and implementation details of `mediator` are all managed
+**outside** the component (most likely the page entrypoint).
diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md
index 784612682f8..c769d0767e7 100644
--- a/doc/development/fe_guide/design_patterns.md
+++ b/doc/development/fe_guide/design_patterns.md
@@ -6,79 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Design Patterns
-## Singletons
+The following design patterns are suggested approaches for solving common problems. Use discretion when evaluating
+if a certain pattern makes sense in your situation. Just because it is a pattern, doesn't mean it is a good one for your problem.
-When exactly one object is needed for a given task, prefer to define it as a
-`class` rather than as an object literal. Prefer also to explicitly restrict
-instantiation, unless flexibility is important (e.g. for testing).
+**Please note:** When adding a design pattern to this document, be sure to clearly state the **problem it solves**.
-```javascript
-// bad
+## TBD
-const MyThing = {
- prop1: 'hello',
- method1: () => {}
-};
-
-export default MyThing;
-
-// good
-
-class MyThing {
- constructor() {
- this.prop1 = 'hello';
- }
- method1() {}
-}
-
-export default new MyThing();
-
-// best
-
-export default class MyThing {
- constructor() {
- if (!MyThing.prototype.singleton) {
- this.init();
- MyThing.prototype.singleton = this;
- }
- return MyThing.prototype.singleton;
- }
-
- init() {
- this.prop1 = 'hello';
- }
-
- method1() {}
-}
-
-```
-
-## Manipulating the DOM in a JS Class
-
-When writing a class that needs to manipulate the DOM guarantee a container option is provided.
-This is useful when we need that class to be instantiated more than once in the same page.
-
-Bad:
-
-```javascript
-class Foo {
- constructor() {
- document.querySelector('.bar');
- }
-}
-new Foo();
-```
-
-Good:
-
-```javascript
-class Foo {
- constructor(opts) {
- document.querySelector(`${opts.container} .bar`);
- }
-}
-
-new Foo({ container: '.my-element' });
-```
-
-You can find an example of the above in this [class](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/mini_pipeline_graph_dropdown.js);
+Stay tuned!
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index d122459f51c..b85ed4da442 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -12,9 +12,9 @@ You can find more about the organization of the frontend team in the [handbook](
The idea is to remind us about specific topics during the time we build a new feature or start something. This is a common practice in other industries (like pilots) that also use standardized checklists to reduce problems early on.
-Copy the content over to your issue or merge request and if something doesn't apply simply remove it from your current list.
+Copy the content over to your issue or merge request and if something doesn't apply, remove it from your current list.
-This checklist is intended to help us during development of bigger features/refactorings, it's not a "use it always and every point always matches" list.
+This checklist is intended to help us during development of bigger features/refactorings. It is not a "use it always and every point always matches" list.
Please use your best judgment when to use it and please contribute new points through merge requests if something comes to your mind.
@@ -77,7 +77,7 @@ With the purpose of being [respectful of others' time](https://about.gitlab.com/
- includes tests
- includes a changelog entry (when necessary)
- Before assigning to a maintainer, assign to a reviewer.
-- If you assigned a merge request or pinged someone directly, be patient because we work in different timezones and asynchronously. Unless the merge request is urgent (like fixing a broken master), please don't DM or reassign the merge request before waiting for a 24-hour window.
+- If you assigned a merge request or pinged someone directly, be patient because we work in different timezones and asynchronously. Unless the merge request is urgent (like fixing a broken default branch), please don't DM or reassign the merge request before waiting for a 24-hour window.
- If you have a question regarding your merge request/issue, make it on the merge request/issue. When we DM each other, we no longer have a SSOT and [no one else is able to contribute](https://about.gitlab.com/handbook/values/#public-by-default).
- When you have a big **Draft** merge request with many changes, you're advised to get the review started before adding/removing significant code. Make sure it is assigned well before the release cut-off, as the reviewer(s)/maintainer(s) would always prioritize reviewing finished MRs before the **Draft** ones.
- Make sure to remove the `Draft:` title before the last round of review.
diff --git a/doc/development/fe_guide/dropdowns.md b/doc/development/fe_guide/dropdowns.md
deleted file mode 100644
index bd2dae13c5b..00000000000
--- a/doc/development/fe_guide/dropdowns.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/components/dropdown/'
----
diff --git a/doc/development/fe_guide/editor_lite.md b/doc/development/fe_guide/editor_lite.md
index 47ef85d8737..f783a97fbd3 100644
--- a/doc/development/fe_guide/editor_lite.md
+++ b/doc/development/fe_guide/editor_lite.md
@@ -8,13 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Background
-**Editor Lite** is a technological product driving [Web Editor](../../user/project/repository/web_editor.md), [Snippets](../../user/snippets.md), [CI Linter](../../ci/lint.md), etc. Editor Lite is the driving technology for any single-file editing experience across the product.
+**Editor Lite** is a technological product driving features like [Web Editor](../../user/project/repository/web_editor.md), [Snippets](../../user/snippets.md), and [CI Linter](../../ci/lint.md). Editor Lite is the driving technology for any single-file editing experience across the product.
Editor Lite is a thin wrapper around [the Monaco editor](https://microsoft.github.io/monaco-editor/index.html) that provides the necessary helpers and abstractions and extends Monaco using extensions.
## How to use Editor Lite
-Editor Lite is framework-agnostic and can be used in any application, whether it's Rails or Vue. For the convenience of integration, we have [the dedicated `<editor-lite>` Vue component](#vue-component), but in general, the integration of Editor Lite is pretty straightforward:
+Editor Lite is framework-agnostic and can be used in any application, whether it's Rails or Vue. For the convenience of integration, we have the dedicated `<editor-lite>` Vue component, but in general, the integration of Editor Lite is pretty straightforward:
1. Import Editor Lite:
@@ -65,7 +65,7 @@ The editor follows the same public API as [provided by Monaco editor](https://mi
1. Editor's loading state.
-Editor Lite comes with the loading state built-in, making spinners and loaders rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading` property on the HTML element that is supposed to contain the editor. Editor Lite will show the loader automatically while it's bootstrapping.
+Editor Lite comes with the loading state built-in, making spinners and loaders rarely needed in HTML. To benefit the built-in loading state, set the `data-editor-loading` property on the HTML element that is supposed to contain the editor. Editor Lite shows the loader automatically while it's bootstrapping.
![Editor Lite: loading state](img/editor_lite_loading.png)
1. Update syntax highlighting if the filename changes.
@@ -89,7 +89,7 @@ form.addEventListener('submit', () => {
1. Performance
-Even though Editor Lite itself is extremely slim, it still depends on Monaco editor. Monaco is not an easily tree-shakeable module. Hence, every time you add Editor Lite to a view, the JavaScript bundle's size significantly increases, affecting your view's loading performance. To avoid that, it is recommended to import the editor on demand on those views where it is not 100% certain that the editor will be used. Or if the editor is a secondary element of the view. Loading Editor Lite on demand is no different from loading any other module:
+Even though Editor Lite itself is extremely slim, it still depends on Monaco editor. Monaco is not an easily tree-shakeable module. Hence, every time you add Editor Lite to a view, the JavaScript bundle's size significantly increases, affecting your view's loading performance. It is recommended to import the editor on demand on those views where it is not 100% certain that the editor is needed. Or if the editor is a secondary element of the view. Loading Editor Lite on demand is no different from loading any other module:
```javascript
someActionFunction() {
@@ -109,8 +109,8 @@ which would not depend on any particular group. Even though the Editor Lite's co
[Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor/),
the main functional elements — extensions — can be owned by any group. Editor Lite extensions' main idea
is that the core of the editor remains very slim and stable. At the same time, whatever new functionality
-is needed can be added as an extension to this core, without touching the core itself. It allows any group
-to build and own any new editing functionality without being afraid of it being broken or overridden with
+is needed can be added as an extension to this core, without touching the core itself. Any group is allowed
+to build and own new editing functionality without being afraid of it being broken or overridden with
the Editor Lite changes.
Structurally, the complete implementation of Editor Lite could be presented as the following diagram:
@@ -145,7 +145,7 @@ Important things to note here:
### Using an existing extension
-Adding an extension to Editor Lite's instance is simple:
+Adding an extension to Editor Lite's instance requires the following steps:
```javascript
import EditorLite from '~/editor/editor_lite';
@@ -159,7 +159,7 @@ editor.use(MyExtension);
### Creating an extension
-Let's create our first Editor Lite extension. As aforementioned, extensions are ES6 modules exporting the simple `Object` that is used to extend Editor Lite's functionality. As the most straightforward test, let's create an extension that extends Editor Lite with a new function that, when called, will output editor's content in `alert`.
+Let's create our first Editor Lite extension. Extensions are ES6 modules exporting a basic `Object` that is used to extend Editor Lite's functionality. As a test, let's create an extension that extends Editor Lite with a new function that, when called, outputs editor's content in `alert`.
`~/my_folder/my_fancy_extension.js:`
@@ -225,7 +225,3 @@ Just pass the array of extensions to your `use` method:
```javascript
editor.use([FileTemplateExtension, MyFancyExtension]);
```
-
-## <a id="vue-component"></a>`<editor-lite>` Vue component
-
-TBD
diff --git a/doc/development/fe_guide/emojis.md b/doc/development/fe_guide/emojis.md
index 7151e2ffeee..2dedbc8f19d 100644
--- a/doc/development/fe_guide/emojis.md
+++ b/doc/development/fe_guide/emojis.md
@@ -25,7 +25,7 @@ when your platform does not support it.
- `app/assets/images/emoji.png`
- `app/assets/images/emoji@2x.png`
1. Ensure you see new individual images copied into `app/assets/images/emoji/`
- 1. Ensure you can see the new emojis and their aliases in the GFM Autocomplete
+ 1. Ensure you can see the new emojis and their aliases in the GitLab Flavored Markdown (GFM) Autocomplete
1. Ensure you can see the new emojis and their aliases in the award emoji menu
1. You might need to add new emoji Unicode support checks and rules for platforms
that do not support a certain emoji and we need to fallback to an image.
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
index 9612f604b56..bf1dae6e7bd 100644
--- a/doc/development/fe_guide/frontend_faq.md
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -21,7 +21,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## FAQ
-### 1. How do I find the Rails route for a page?
+### 1. How does one find the Rails route for a page?
#### Check the 'page' data attribute
@@ -36,7 +36,7 @@ Find here the [source code setting the attribute](https://gitlab.com/gitlab-org/
#### Rails routes
-The `rake routes` command can be used to list all the routes available in the application, piping the output into `grep`, we can perform a search through the list of available routes.
+The `rake routes` command can be used to list all the routes available in the application. Piping the output into `grep`, we can perform a search through the list of available routes.
The output includes the request types available, route parameters and the relevant controller.
```shell
@@ -46,13 +46,13 @@ bundle exec rake routes | grep "issues"
### 2. `modal_copy_button` vs `clipboard_button`
The `clipboard_button` uses the `copy_to_clipboard.js` behavior, which is
-initialized on page load, so if there are vue-based clipboard buttons that
-don't exist at page load (such as ones in a `GlModal`), they do not have the
+initialized on page load. Vue clipboard buttons that
+don't exist at page load (such as ones in a `GlModal`) do not have
click handlers associated with the clipboard package.
-`modal_copy_button` was added that manages an instance of the
+`modal_copy_button` manages an instance of the
[`clipboard` plugin](https://www.npmjs.com/package/clipboard) specific to
-the instance of that component, which means that clipboard events are
+the instance of that component. This means that clipboard events are
bound on mounting and destroyed when the button is, mitigating the above
issue. It also has bindings to a particular container or modal ID
available, to work with the focus trap created by our GlModal.
@@ -60,7 +60,7 @@ available, to work with the focus trap created by our GlModal.
### 3. A `gitlab-ui` component not conforming to [Pajamas Design System](https://design.gitlab.com/)
Some [Pajamas Design System](https://design.gitlab.com/) components implemented in
-`gitlab-ui` do not conform with the design system specs because they lack some
+`gitlab-ui` do not conform with the design system specs. This is because they lack some
planned features or are not correctly styled yet. In the Pajamas website, a
banner on top of the component examples indicates that:
@@ -77,18 +77,17 @@ It makes codebase unified and more comfortable to maintain/refactor in the futur
Ensure a [Product Designer](https://about.gitlab.com/company/team/?department=ux-department)
reviews the use of the non-conforming component as part of the MR review. Make a
-follow up issue and attach it to the component implementation epic found within the
+follow up issue and attach it to the component implementation epic found in the
[Components of Pajamas Design System epic](https://gitlab.com/groups/gitlab-org/-/epics/973).
### 4. My submit form button becomes disabled after submitting
-If you are using a submit button inside a form and you attach an `onSubmit` event listener on the form element, [this piece of code](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225) adds a `disabled` class selector to the submit button when the form is submitted.
-To avoid this behavior, add the class `js-no-auto-disable` to the button.
+A Submit button inside of a form attaches an `onSubmit` event listener on the form element. [This code](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225) adds a `disabled` class selector to the submit button when the form is submitted. To avoid this behavior, add the class `js-no-auto-disable` to the button.
-### 5. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?
+### 5. Should one use a full URL (for example `gon.gitlab_url`) or a full path (for example `gon.relative_url_root`) when referencing backend endpoints?
-It's preferred to use a **full path** over a **full URL** because the URL uses the hostname configured with
-GitLab which may not match the request. This causes [CORS issues like this Web IDE one](https://gitlab.com/gitlab-org/gitlab/-/issues/36810).
+It's preferred to use a **full path** over a **full URL**. This is because the URL uses the hostname configured with
+GitLab which may not match the request. This causes [cross-origin resource sharing issues like this Web IDE example](https://gitlab.com/gitlab-org/gitlab/-/issues/36810).
Example:
@@ -117,7 +116,7 @@ Example:
### 6. How should the Frontend reference Backend paths?
-We prefer not to add extra coupling by hardcoding paths. If possible,
+We prefer not to add extra coupling by hard-coding paths. If possible,
add these paths as data attributes to the DOM element being referenced in the JavaScript.
Example:
@@ -153,7 +152,7 @@ export const fetchFoos = ({ state }) => {
};
```
-### 7. How can I test the production build locally?
+### 7. How can one test the production build locally?
Sometimes it's necessary to test locally what the frontend production build would produce, to do so the steps are:
@@ -161,7 +160,7 @@ Sometimes it's necessary to test locally what the frontend production build woul
1. Open `gitlab.yaml` located in your `gitlab` installation folder, scroll down to the `webpack` section and change `dev_server` to `enabled: false`.
1. Run `yarn webpack-prod && gdk restart rails-web`.
-The production build takes a few minutes to be completed; any code changes at this point are
+The production build takes a few minutes to be completed. Any code changes at this point are
displayed only after executing the item 3 above again.
To return to the normal development mode:
@@ -176,8 +175,8 @@ To return to the normal development mode:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/28837) in GitLab 12.8.
GitLab has enabled the Babel `preset-env` option
-[`useBuiltIns: 'usage'`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins-usage),
-which adds the appropriate `core-js` polyfills once for each JavaScript feature
+[`useBuiltIns: 'usage'`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins-usage).
+This adds the appropriate `core-js` polyfills once for each JavaScript feature
we're using that our target browsers don't support. You don't need to add `core-js`
polyfills manually.
@@ -199,3 +198,7 @@ To see what polyfills are being used:
which polyfills are being loaded and where:
![Image of webpack report](img/webpack_report_v12_8.png)
+
+### 9. Why is my page broken in dark mode?
+
+See [dark mode docs](dark_mode.md)
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index cbaa648570c..a53d9fee029 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -18,34 +18,46 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
**GraphQL at GitLab**:
-- [🎬 GitLab Unfiltered GraphQL playlist](https://www.youtube.com/watch?v=wHPKZBDMfxE&list=PL05JrBw4t0KpcjeHjaRMB7IGB2oDWyJzv)
-- [🎬 GraphQL at GitLab: Deep Dive](../api_graphql_styleguide.md#deep-dive) (video) by Nick Thomas
+<!-- vale gitlab.Spelling = NO -->
+
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [GitLab Unfiltered GraphQL playlist](https://www.youtube.com/watch?v=wHPKZBDMfxE&list=PL05JrBw4t0KpcjeHjaRMB7IGB2oDWyJzv)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [GraphQL at GitLab: Deep Dive](../api_graphql_styleguide.md#deep-dive) (video) by Nick Thomas
- An overview of the history of GraphQL at GitLab (not frontend-specific)
-- [🎬 GitLab Feature Walkthrough with GraphQL and Vue Apollo](https://www.youtube.com/watch?v=6yYp2zB7FrM) (video) by Natalia Tepluhina
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [GitLab Feature Walkthrough with GraphQL and Vue Apollo](https://www.youtube.com/watch?v=6yYp2zB7FrM) (video) by Natalia Tepluhina
- A real-life example of implementing a frontend feature in GitLab using GraphQL
-- [🎬 History of client-side GraphQL at GitLab](https://www.youtube.com/watch?v=mCKRJxvMnf0) (video) Illya Klymov and Natalia Tepluhina
-- [🎬 From Vuex to Apollo](https://www.youtube.com/watch?v=9knwu87IfU8) (video) by Natalia Tepluhina
- - A useful overview of when Apollo might be a better choice than Vuex, and how one could go about the transition
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [History of client-side GraphQL at GitLab](https://www.youtube.com/watch?v=mCKRJxvMnf0) (video) Illya Klymov and Natalia Tepluhina
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [From Vuex to Apollo](https://www.youtube.com/watch?v=9knwu87IfU8) (video) by Natalia Tepluhina
+ - An overview of when Apollo might be a better choice than Vuex, and how one could go about the transition
- [🛠 Vuex -> Apollo Migration: a proof-of-concept project](https://gitlab.com/ntepluhina/vuex-to-apollo/blob/master/README.md)
- A collection of examples that show the possible approaches for state management with Vue+GraphQL+(Vuex or Apollo) apps
+<!-- vale gitlab.Spelling = YES -->
+
### Libraries
We use [Apollo](https://www.apollographql.com/) (specifically [Apollo Client](https://www.apollographql.com/docs/react/)) and [Vue Apollo](https://github.com/vuejs/vue-apollo)
when using GraphQL for frontend development.
-If you are using GraphQL within a Vue application, the [Usage in Vue](#usage-in-vue) section
+If you are using GraphQL in a Vue application, the [Usage in Vue](#usage-in-vue) section
can help you learn how to integrate Vue Apollo.
For other use cases, check out the [Usage outside of Vue](#usage-outside-of-vue) section.
+<!-- vale gitlab.Spelling = NO -->
+
We use [Immer](https://immerjs.github.io/immer/docs/introduction) for immutable cache updates;
see [Immutability and cache updates](#immutability-and-cache-updates) for more information.
+<!-- vale gitlab.Spelling = YES -->
+
### Tooling
+<!-- vale gitlab.Spelling = NO -->
+
- [Apollo Client Devtools](https://github.com/apollographql/apollo-client-devtools)
+<!-- vale gitlab.Spelling = YES -->
+
#### [Apollo GraphQL VS Code extension](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo)
If you use VS Code, the Apollo GraphQL extension supports autocompletion in `.graphql` files. To set up
@@ -76,7 +88,7 @@ Our GraphQL API can be explored via GraphiQL at your instance's
where needed.
You can check all existing queries and mutations on the right side
-of GraphiQL in its **Documentation explorer**. It's also possible to
+of GraphiQL in its **Documentation explorer**. You can also
write queries and mutations directly on the left tab and check
their execution by clicking **Execute query** button on the top left:
@@ -93,8 +105,8 @@ Default client accepts two parameters: `resolvers` and `config`.
- `resolvers` parameter is created to accept an object of resolvers for [local state management](#local-state-with-apollo) queries and mutations
- `config` parameter takes an object of configuration settings:
- `cacheConfig` field accepts an optional object of settings to [customize Apollo cache](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache)
- - `baseUrl` allows us to pass a URL for GraphQL endpoint different from our main endpoint (i.e.`${gon.relative_url_root}/api/graphql`)
- - `assumeImmutableResults` (set to `false` by default) - this setting, when set to `true`, will assume that every single operation on updating Apollo Cache is immutable. It also sets `freezeResults` to `true`, so any attempt on mutating Apollo Cache will throw a console warning in development environment. Please ensure you're following the immutability pattern on cache update operations before setting this option to `true`.
+ - `baseUrl` allows us to pass a URL for GraphQL endpoint different from our main endpoint (for example, `${gon.relative_url_root}/api/graphql`)
+ - `assumeImmutableResults` (set to `false` by default) - this setting, when set to `true`, assumes that every single operation on updating Apollo Cache is immutable. It also sets `freezeResults` to `true`, so any attempt on mutating Apollo Cache throws a console warning in development environment. Please ensure you're following the immutability pattern on cache update operations before setting this option to `true`.
- `fetchPolicy` determines how you want your component to interact with the Apollo cache. Defaults to "cache-first".
## GraphQL Queries
@@ -139,7 +151,7 @@ fragment DesignItem on Design {
```
More about fragments:
-[GraphQL Docs](https://graphql.org/learn/queries/#fragments)
+[GraphQL documentation](https://graphql.org/learn/queries/#fragments)
## Global IDs
@@ -157,12 +169,17 @@ const primaryKeyId = getIdFromGraphQLId(data.id);
## Immutability and cache updates
-From Apollo version 3.0.0 all the cache updates need to be immutable; it needs to be replaced entirely
+From Apollo version 3.0.0 all the cache updates need to be immutable. It needs to be replaced entirely
with a **new and updated** object.
-To facilitate the process of updating the cache and returning the new object we use the library [Immer](https://immerjs.github.io/immer/docs/introduction).
+<!-- vale gitlab.Spelling = NO -->
+
+To facilitate the process of updating the cache and returning the new object we
+use the library [Immer](https://immerjs.github.io/immer/docs/introduction).
When possible, follow these conventions:
+<!-- vale gitlab.Spelling = YES -->
+
- The updated cache is named `data`.
- The original cache data is named `sourceData`.
@@ -184,10 +201,10 @@ client.writeQuery({
```
As shown in the code example by using `produce`, we can perform any kind of direct manipulation of the
-`draftState`. Besides, `immer` guarantees that a new state which includes the changes to `draftState` will be generated.
+`draftState`. Besides, `immer` guarantees that a new state which includes the changes to `draftState` is generated.
Finally, to verify whether the immutable cache update is working properly, we need to change
-`assumeImmutableResults` to `true` in the default client configuration (see [Apollo Client](#apollo-client) for more information).
+`assumeImmutableResults` to `true` in the default client configuration. See [Apollo Client](#apollo-client) for more information.
If everything is working properly `assumeImmutableResults` should remain set to `true`.
@@ -259,11 +276,11 @@ query User {
}
```
-Along with creating local data, we can also extend existing GraphQL types with `@client` fields. This is extremely useful when we need to mock an API responses for fields not yet added to our GraphQL API.
+Along with creating local data, we can also extend existing GraphQL types with `@client` fields. This is extremely helpful when we need to mock an API response for fields not yet added to our GraphQL API.
#### Mocking API response with local Apollo cache
-Using local Apollo Cache is handy when we have a need to mock some GraphQL API responses, queries or mutations locally (e.g. when they're still not added to our actual API).
+Using local Apollo Cache is helpful when we have a need to mock some GraphQL API responses, queries, or mutations locally (such as when they're still not added to our actual API).
For example, we have a [fragment](#fragments) on `DesignVersion` used in our queries:
@@ -274,7 +291,7 @@ fragment VersionListItem on DesignVersion {
}
```
-We need to fetch also version author and the 'created at' property to display them in the versions dropdown but these changes are still not implemented in our API. We can change the existing fragment to get a mocked response for these new fields:
+We also need to fetch the version author and the `created at` property to display in the versions dropdown. But, these changes are still not implemented in our API. We can change the existing fragment to get a mocked response for these new fields:
```javascript
fragment VersionListItem on DesignVersion {
@@ -288,7 +305,7 @@ fragment VersionListItem on DesignVersion {
}
```
-Now Apollo will try to find a _resolver_ for every field marked with `@client` directive. Let's create a resolver for `DesignVersion` type (why `DesignVersion`? because our fragment was created on this type).
+Now Apollo tries to find a _resolver_ for every field marked with `@client` directive. Let's create a resolver for `DesignVersion` type (why `DesignVersion`? because our fragment was created on this type).
```javascript
// resolvers.js
@@ -319,13 +336,13 @@ import resolvers from './graphql/resolvers';
const defaultClient = createDefaultClient(resolvers);
```
-For each attempt to fetch a version, our client will fetch `id` and `sha` from the remote API endpoint and will assign our hardcoded values to the `author` and `createdAt` version properties. With this data, frontend developers are able to work on their UI without being blocked by backend. When the actual response is added to the API, our custom local resolver can be removed and the only change to the query/fragment is to remove the `@client` directive.
+For each attempt to fetch a version, our client fetches `id` and `sha` from the remote API endpoint. It then assigns our hardcoded values to the `author` and `createdAt` version properties. With this data, frontend developers are able to work on their UI without being blocked by backend. When the response is added to the API, our custom local resolver can be removed. The only change to the query/fragment is to remove the `@client` directive.
Read more about local state management with Apollo in the [Vue Apollo documentation](https://vue-apollo.netlify.app/guide/local-state.html#local-state).
### Using with Vuex
-When Apollo Client is used within Vuex and fetched data is stored in the Vuex store, there is no need to keep Apollo Client cache enabled. Otherwise we would have data from the API stored in two places - Vuex store and Apollo Client cache. With Apollo's default settings, a subsequent fetch from the GraphQL API could result in fetching data from Apollo cache (in the case where we have the same query and variables). To prevent this behavior, we need to disable Apollo Client cache by passing a valid `fetchPolicy` option to its constructor:
+When the Apollo Client is used in Vuex and fetched data is stored in the Vuex store, the Apollo Client cache does not need to be enabled. Otherwise we would have data from the API stored in two places - Vuex store and Apollo Client cache. With Apollo's default settings, a subsequent fetch from the GraphQL API could result in fetching data from Apollo cache (in the case where we have the same query and variables). To prevent this behavior, we need to disable Apollo Client cache by passing a valid `fetchPolicy` option to its constructor:
```javascript
import fetchPolicies from '~/graphql_shared/fetch_policy_constants';
@@ -338,11 +355,61 @@ export const gqClient = createGqClient(
);
```
-### Feature flags in queries
+### Working on GraphQL-based features when frontend and backend are not in sync
+
+Any feature that requires GraphQL queries/mutations to be created or updated should be carefully
+planned. Frontend and backend counterparts should agree on a schema that satisfies both client-side and
+server-side requirements. This enables both departments to start implementing their parts without
+blocking each other.
+
+Ideally, the backend implementation should be done prior to the frontend so that the client can
+immediately start querying the API with minimal back and forth between departments. However, we
+recognize that priorities don't always align. For the sake of iteration and
+delivering work we're committed to, it might be necessary for the frontend to be implemented ahead
+of the backend.
+
+#### Implementing frontend queries and mutations ahead of the backend
-Sometimes it may be useful to have an entity in the GraphQL query behind a feature flag.
-For example, when working on a feature where the backend has already been merged but the frontend
-hasn't you might want to put the GraphQL entity behind a feature flag to allow for smaller
+In such case, the frontend will define GraphQL schemas or fields that do not correspond to any
+backend resolver yet. This is fine as long as the implementation is properly feature-flagged so it
+does not translate to public-facing errors in the product. However, we do validate client-side
+queries/mutations against the backend GraphQL schema with the `graphql-verify` CI job.
+You must confirm your changes pass the validation if they are to be merged before the
+backend actually supports them. Below are a few suggestions to go about this.
+
+##### Using the `@client` directive
+
+The preferred approach is to use the `@client` directive on any new query, mutation, or field that
+isn't yet supported by the backend. Any entity with the directive is skipped by the
+`graphql-verify` validation job.
+
+Additionally Apollo will attempt to resolve them client-side, which can be used in conjunction with
+[Mocking API response with local Apollo cache](#mocking-api-response-with-local-apollo-cache). This
+provides a convenient way of testing your feature with fake data defined client-side.
+When opening a merge request for your changes, it can be a good idea to provide local resolvers as a
+patch that reviewers can apply in their GDK to easily smoke-test your work.
+
+Make sure to track the removal of the directive in a follow-up issue, or as part of the backend
+implementation plan.
+
+##### Adding an exception to the list of known failures
+
+GraphQL queries/mutations validation can be completely turned off for specific files by adding their
+paths to the
+[`config/known_invalid_graphql_queries.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/known_invalid_graphql_queries.yml)
+file, much like you would disable ESLint for some files via an `.eslintignore` file.
+Bear in mind that any file listed in here will not be validated at all. So if you're only adding
+fields to an existing query, use the `@client` directive approach so that the rest of the query
+is still validated.
+
+Again, make sure that those overrides are as short-lived as possible by tracking their removal in
+the appropriate issue.
+
+#### Feature flags in queries
+
+Sometimes it may be helpful to have an entity in the GraphQL query behind a feature flag.
+One example is working on a feature where the backend has already been merged but the frontend
+has not. In this case, you may consider putting the GraphQL entity behind a feature flag to allow smaller
merge requests to be created and merged.
To do this we can use the `@include` directive to exclude an entity if the `if` statement passes.
@@ -355,7 +422,7 @@ query getAuthorData($authorNameEnabled: Boolean = false) {
```
Then in the Vue (or JavaScript) call to the query we can pass in our feature flag. This feature
-flag will need to be already setup correctly. See the [feature flag documentation](../feature_flags/development.md)
+flag needs to be already set up correctly. See the [feature flag documentation](../feature_flags/development.md)
for the correct way to do this.
```javascript
@@ -469,7 +536,7 @@ Note that we are using the [`pageInfo.fragment.graphql`](https://gitlab.com/gitl
#### Using `fetchMore` method in components
-This approach makes sense to use with user-handled pagination (e.g. when the scrolls to fetch more data or explicitly clicks a "Next Page"-button).
+This approach makes sense to use with user-handled pagination. For example, when the scrolling to fetch more data or explicitly clicking a **Next Page** button.
When we need to fetch all the data initially, it is recommended to use [a (non-smart) query, instead](#using-a-recursive-query-in-components).
When making an initial fetch, we usually want to start a pagination from the beginning.
@@ -479,7 +546,7 @@ In this case, we can either:
- Pass `null` explicitly to `after`.
After data is fetched, we can use the `update`-hook as an opportunity [to customize
-the data that is set in the Vue component property](https://apollo.vuejs.org/api/smart-query.html#options), getting a hold of the `pageInfo` object among other data.
+the data that is set in the Vue component property](https://apollo.vuejs.org/api/smart-query.html#options). This allows us to get a hold of the `pageInfo` object among other data.
In the `result`-hook, we can inspect the `pageInfo` object to see if we need to fetch
the next page. Note that we also keep a `requestCount` to ensure that the application
@@ -561,8 +628,8 @@ fetchNextPage(endCursor) {
When it is necessary to fetch all paginated data initially an Apollo query can do the trick for us.
If we need to fetch the next page based on user interactions, it is recommend to use a [`smartQuery`](https://apollo.vuejs.org/api/smart-query.html) along with the [`fetchMore`-hook](#using-fetchmore-method-in-components).
-When the query resolves we can update the component data and inspect the `pageInfo` object
-to see if we need to fetch the next page, i.e. call the method recursively.
+When the query resolves we can update the component data and inspect the `pageInfo` object. This allows us
+to see if we need to fetch the next page, calling the method recursively.
Note that we also keep a `requestCount` to ensure that the application does not keep
requesting the next page, indefinitely.
@@ -634,7 +701,7 @@ or [`.writeQuery()`](https://www.apollographql.com/docs/react/v2/api/apollo-clie
This can be tedious and counter-intuitive.
To make it easier to deal with cached paginated queries, Apollo provides the `@connection` directive.
-The directive accepts a `key` parameter that will be used as a static key when caching the data.
+The directive accepts a `key` parameter that is used as a static key when caching the data.
You'd then be able to retrieve the data without providing any pagination-specific variables.
Here's an example of a query using the `@connection` directive:
@@ -661,7 +728,7 @@ query DastSiteProfiles($fullPath: ID!, $after: String, $before: String, $first:
}
```
-In this example, Apollo will store the data with the stable `dastSiteProfiles` cache key.
+In this example, Apollo stores the data with the stable `dastSiteProfiles` cache key.
To retrieve that data from the cache, you'd then only need to provide the `$fullPath` variable,
omitting pagination-specific variables like `after` or `before`:
@@ -679,9 +746,9 @@ Read more about the `@connection` directive in [Apollo's documentation](https://
### Managing performance
-The Apollo client will batch queries by default. This means that if you have 3 queries defined,
-Apollo will group them into one request, send the single request off to the server and only
-respond once all 3 queries have completed.
+The Apollo client batches queries by default. Given 3 deferred queries,
+Apollo groups them into one request, sends the single request to the server, and
+responds after all 3 queries have completed.
If you need to have queries sent as individual requests, additional context can be provided
to tell Apollo to do this.
@@ -703,9 +770,13 @@ export default {
#### Mocking response as component data
-With [Vue test utils](https://vue-test-utils.vuejs.org/) it is easy to quickly test components that
+<!-- 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
+the data on the component:
+
+<!-- vale gitlab.Spelling = YES -->
```javascript
it('tests apollo component', () => {
@@ -719,7 +790,7 @@ it('tests apollo component', () => {
#### Testing loading state
-If we need to test how our component renders when results from the GraphQL API are still loading, we can mock a loading state into respective Apollo queries/mutations:
+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({
@@ -817,9 +888,9 @@ it('calls mutation on submitting form ', () => {
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.
-To separate tests with mocked client from 'usual' unit tests, it's recommended to 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 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.
-We need to inject `VueApollo` to the Vue local instance and, likewise, it is recommended to call `localVue.use()` within `createMockApolloProvider()` to only load it when it is necessary.
+We need to inject `VueApollo` to the Vue local instance and, likewise, it is recommended to call `localVue.use()` in `createMockApolloProvider()` to only load it when it is necessary.
```javascript
import VueApollo from 'vue-apollo';
@@ -861,7 +932,7 @@ describe('Some component', () => {
});
```
-Within `createMockApolloProvider`-factory, we need to define an array of _handlers_ for every query or mutation:
+In the `createMockApolloProvider`-factory, we need to define an array of _handlers_ for every query or mutation:
```javascript
import getDesignListQuery from '~/design_management/graphql/queries/get_design_list.query.graphql';
@@ -1251,9 +1322,9 @@ describe('My Index test with `createMockApollo`', () => {
## Handling errors
-The GitLab GraphQL mutations currently have two distinct error modes: [Top-level](#top-level-errors) and [errors-as-data](#errors-as-data).
+The GitLab GraphQL mutations have two distinct error modes: [Top-level](#top-level-errors) and [errors-as-data](#errors-as-data).
-When utilising a GraphQL mutation, we must consider handling **both of these error modes** to ensure that the user receives the appropriate feedback when an error occurs.
+When utilising a GraphQL mutation, consider handling **both of these error modes** to ensure that the user receives the appropriate feedback when an error occurs.
### Top-level errors
@@ -1261,13 +1332,13 @@ These errors are located at the "top level" of a GraphQL response. These are non
#### Handling top-level errors
-Apollo is aware of top-level errors, so we are able to leverage Apollo's various error-handling mechanisms to handle these errors (e.g. handling Promise rejections after invoking the [`mutate`](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.mutate) method, or handling the `error` event emitted from the [`ApolloMutation`](https://apollo.vuejs.org/api/apollo-mutation.html#events) component).
+Apollo is aware of top-level errors, so we are able to leverage Apollo's various error-handling mechanisms to handle these errors. For example, handling Promise rejections after invoking the [`mutate`](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.mutate) method, or handling the `error` event emitted from the [`ApolloMutation`](https://apollo.vuejs.org/api/apollo-mutation.html#events) component.
Because these errors are not intended for users, error messages for top-level errors should be defined client-side.
### Errors-as-data
-These errors are nested within the `data` object of a GraphQL response. These are recoverable errors that, ideally, can be presented directly to the user.
+These errors are nested in the `data` object of a GraphQL response. These are recoverable errors that, ideally, can be presented directly to the user.
#### Handling errors-as-data
@@ -1283,7 +1354,7 @@ mutation createNoteMutation($input: String!) {
}
```
-Now, when we commit this mutation and errors occur, the response will include `errors` for us to handle:
+Now, when we commit this mutation and errors occur, the response includes `errors` for us to handle:
```javascript
{
@@ -1316,7 +1387,7 @@ When [using Vuex](#using-with-vuex), disable the cache when:
- The data is being cached elsewhere
- The use case does not need caching
-if the data is being cached elsewhere, or if there is simply no need for it for the given use case.
+if the data is being cached elsewhere, or if there is no need for it for the given use case.
```javascript
import createDefaultClient from '~/lib/graphql';
@@ -1416,7 +1487,7 @@ for your application. To add GraphQL startup calls, we use
`add_page_startup_graphql_call` helper where the first parameter is a path to the
query, the second one is an object containing query variables. Path to the query is
relative to `app/graphql/queries` folder: for example, if we need a
-`app/graphql/queries/repository/files.query.graphql` query, the path will be
+`app/graphql/queries/repository/files.query.graphql` query, the path is
`repository/files`.
```yaml
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index af587a31bbb..a7b62fbb267 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -26,11 +26,11 @@ To use a sprite Icon in HAML or Rails we use a specific helper function:
sprite_icon(icon_name, size: nil, css_class: '')
```
-- **icon_name**: Use the icon_name for the SVG sprite in the list of
+- **`icon_name`**: Use the `icon_name` for the SVG sprite in the list of
([GitLab SVGs](https://gitlab-org.gitlab.io/gitlab-svgs)).
-- **size (optional)**: Use one of the following sizes : 16, 24, 32, 48, 72 (this
+- **`size` (optional)**: Use one of the following sizes : 16, 24, 32, 48, 72 (this
is translated into a `s16` class)
-- **css_class (optional)**: If you want to add additional CSS classes.
+- **`css_class` (optional)**: If you want to add additional CSS classes.
**Example**
@@ -100,7 +100,7 @@ by the examples that follow:
- `container` (optional): wraps the loading icon in a container, which centers the loading icon using the `text-center` CSS property.
- `color` (optional): either `orange` (default), `light`, or `dark`.
- `size` (optional): either `sm` (default), `md`, `lg`, or `xl`.
-- `css_class` (optional): defaults to an empty string, but can be useful for utility classes to fine-tune alignment or spacing.
+- `css_class` (optional): defaults to an empty string, but can be used for utility classes to fine-tune alignment or spacing.
**Example 1:**
@@ -164,8 +164,8 @@ export default {
## SVG Illustrations
-Please use from now on for any SVG based illustrations simple `img` tags to show an illustration by simply using either `image_tag` or `image_path` helpers.
-Please use the class `svg-content` around it to ensure nice rendering.
+From now on, use `img` tags to display any SVG based illustrations with either `image_tag` or `image_path` helpers.
+Using the class `svg-content` around it ensures nice rendering.
### Usage in HAML/Rails
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index 84c1623f8c0..711c6a5f875 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -11,8 +11,11 @@ across the GitLab frontend team.
## Overview
-GitLab is built on top of [Ruby on Rails](https://rubyonrails.org) using [Haml](https://haml.info/) and also a JavaScript based Frontend with [Vue.js](https://vuejs.org).
-Be wary of [the limitations that come with using Hamlit](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations). We also use [SCSS](https://sass-lang.com) and plain JavaScript with
+GitLab is built on top of [Ruby on Rails](https://rubyonrails.org). It uses [Haml](https://haml.info/) and a JavaScript0based frontend with [Vue.js](https://vuejs.org).
+<!-- vale gitlab.Spelling = NO -->
+Be wary of [the limitations that come with using Hamlit](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations).
+<!-- vale gitlab.Spelling = YES -->
+We also use [SCSS](https://sass-lang.com) and plain JavaScript with
modern ECMAScript standards supported through [Babel](https://babeljs.io/) and ES module support through [webpack](https://webpack.js.org/).
Working with our frontend assets requires Node (v10.13.0 or greater) and Yarn
@@ -21,7 +24,7 @@ Working with our frontend assets requires Node (v10.13.0 or greater) and Yarn
### Browser Support
-For our currently-supported browsers, see our [requirements](../../install/requirements.md#supported-web-browsers).
+For supported browsers, see our [requirements](../../install/requirements.md#supported-web-browsers).
Use [BrowserStack](https://www.browserstack.com/) to test with our supported browsers.
Sign in to BrowserStack with the credentials saved in the **Engineering** vault of the GitLab
@@ -56,7 +59,11 @@ Reusable components with technical and usage guidelines can be found in our
## Design Patterns
-Common JavaScript [design patterns](design_patterns.md) in the GitLab codebase.
+JavaScript [design patterns](design_patterns.md) in the GitLab codebase.
+
+## Design Anti-patterns
+
+JavaScript [design anti-patterns](design_anti_patterns.md) we try to avoid.
## Vue.js Best Practices
@@ -121,3 +128,7 @@ Our accessibility standards and resources.
Frontend internationalization support is described in [this document](../i18n/).
The [externalization part of the guide](../i18n/externalization.md) explains the helpers/methods available.
+
+## [Troubleshooting](troubleshooting.md)
+
+Running into a Frontend development problem? Check out [this guide](troubleshooting.md) to help resolve your issue.
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index aac2258f3a3..795de87d309 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -202,15 +202,15 @@ help identify marks and measures coming from the different apps on the same page
## Best Practices
-### Realtime Components
+### Real-time Components
-When writing code for realtime features we have to keep a couple of things in mind:
+When writing code for real-time features we have to keep a couple of things in mind:
1. Do not overload the server with requests.
-1. It should feel realtime.
+1. It should feel real-time.
-Thus, we must strike a balance between sending requests and the feeling of realtime.
-Use the following rules when creating realtime solutions.
+Thus, we must strike a balance between sending requests and the feeling of real-time.
+Use the following rules when creating real-time solutions.
1. The server tells you how much to poll by sending `Poll-Interval` in the header.
Use that as your polling interval. This enables system administrators to change the
@@ -219,9 +219,9 @@ Use the following rules when creating realtime solutions.
1. A response with HTTP status different from 2XX should disable polling as well.
1. Use a common library for polling.
1. Poll on active tabs only. Please use [Visibility](https://github.com/ai/visibilityjs).
-1. Use regular polling intervals, do not use backoff polling, or jitter, as the interval is
+1. Use regular polling intervals, do not use <!-- vale gitlab.Spelling = NO --> backoff polling <!-- vale gitlab.Spelling = YES --> or jitter, as the interval is
controlled by the server.
-1. The backend code is likely to be using etags. You do not and should not check for status
+1. The backend code is likely to be using ETags. You do not and should not check for status
`304 Not Modified`. The browser transforms it for you.
### Lazy Loading Images
@@ -230,12 +230,12 @@ To improve the time to first render we are using lazy loading for images. This w
the actual image source on the `data-src` attribute. After the HTML is rendered and JavaScript is loaded,
the value of `data-src` is moved to `src` automatically if the image is in the current viewport.
-- Prepare images in HTML for lazy loading by renaming the `src` attribute to `data-src` AND adding the class `lazy`.
+- Prepare images in HTML for lazy loading by renaming the `src` attribute to `data-src` and adding the class `lazy`.
- If you are using the Rails `image_tag` helper, all images are lazy-loaded by default unless `lazy: false` is provided.
-If you are asynchronously adding content which contains lazy images then you need to call the function
+When asynchronously adding content which contains lazy images, call the function
`gl.lazyLoader.searchLazyImages()` which searches for lazy images and loads them if needed.
-But in general it should be handled automatically through a `MutationObserver` in the lazy loading function.
+In general, it should be handled automatically through a `MutationObserver` in the lazy loading function.
### Animations
@@ -243,7 +243,7 @@ Only animate `opacity` & `transform` properties. Other properties (such as `top`
Layout to be recalculated, which is much more expensive. For details on this, see "Styles that Affect Layout" in
[High Performance Animations](https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/).
-If you _do_ need to change layout (for example, a sidebar that pushes main content over), prefer [FLIP](https://aerotwist.com/blog/flip-your-animations/) to change expensive
+If you _do_ need to change layout (for example, a sidebar that pushes main content over), prefer [FLIP](https://aerotwist.com/blog/flip-your-animations/). FLIP allows you to change expensive
properties once, and handle the actual animation with transforms.
## Reducing Asset Footprint
@@ -251,7 +251,7 @@ properties once, and handle the actual animation with transforms.
### Universal code
Code that is contained in `main.js` and `commons/index.js` is loaded and
-run on _all_ pages. **DO NOT ADD** anything to these files unless it is truly
+run on _all_ pages. **Do not add** anything to these files unless it is truly
needed _everywhere_. These bundles include ubiquitous libraries like `vue`,
`axios`, and `jQuery`, as well as code for the main navigation and sidebar.
Where possible we should aim to remove modules from these bundles to reduce our
@@ -277,9 +277,9 @@ manually generated webpack bundles. However under this new system you should
not ever need to manually add an entry point to the `webpack.config.js` file.
NOTE:
-If you are unsure what controller and action corresponds to a given page, you
-can find this out by inspecting `document.body.dataset.page` in your
-browser's developer console while on any page in GitLab.
+When unsure what controller and action corresponds to a page,
+inspect `document.body.dataset.page` in your
+browser's developer console from any page in GitLab.
#### Important Considerations
@@ -294,7 +294,7 @@ browser's developer console while on any page in GitLab.
All GitLab JavaScript files are added with the `defer` attribute.
According to the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer),
this implies that "the script is meant to be executed after the document has
- been parsed, but before firing `DOMContentLoaded`". Since the document is already
+ been parsed, but before firing `DOMContentLoaded`". Because the document is already
parsed, `DOMContentLoaded` is not needed to bootstrap applications because all
the DOM nodes are already at our disposal.
@@ -333,7 +333,7 @@ browser's developer console while on any page in GitLab.
action();
```
- For example, see how we use this in [app/assets/javascripts/pages/projects/graphs/charts/index.js](https://gitlab.com/gitlab-org/gitlab/-/commit/5e90885d6afd4497002df55bf015b338efcfc3c5#02e81de37f5b1716a3ef3222fa7f7edf22c40969_9_8):
+ For example, see how we use this in [`app/assets/javascripts/pages/projects/graphs/charts/index.js`](https://gitlab.com/gitlab-org/gitlab/-/commit/5e90885d6afd4497002df55bf015b338efcfc3c5#02e81de37f5b1716a3ef3222fa7f7edf22c40969_9_8):
```javascript
waitForCSSLoaded(() => {
@@ -366,9 +366,9 @@ browser's developer console while on any page in GitLab.
### Code Splitting
-For any code that does not need to be run immediately upon page load, (for example,
-modals, dropdowns, and other behaviors that can be lazy-loaded), you can split
-your module into asynchronous chunks with dynamic import statements. These
+Code that does not need to be run immediately upon page load (for example,
+modals, dropdowns, and other behaviors that can be lazy-loaded) should be split
+into asynchronous chunks with dynamic import statements. These
imports return a Promise which is resolved after the script has loaded:
```javascript
@@ -377,16 +377,16 @@ import(/* webpackChunkName: 'emoji' */ '~/emoji')
.catch(/* report error */)
```
-Please try to use `webpackChunkName` when generating these dynamic imports as
+Use `webpackChunkName` when generating dynamic imports as
it provides a deterministic filename for the chunk which can then be cached
-the browser across GitLab versions.
+in the browser across GitLab versions.
More information is available in [webpack's code splitting documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports).
### Minimizing page size
-A smaller page size means the page loads faster (especially important on mobile
-and poor connections), the page is parsed more quickly by the browser, and less
+A smaller page size means the page loads faster, especially on mobile
+and poor connections. The page is parsed more quickly by the browser, and less
data is used for users with capped data plans.
General tips:
diff --git a/doc/development/fe_guide/security.md b/doc/development/fe_guide/security.md
index 627c5f4d12f..df4613d521d 100644
--- a/doc/development/fe_guide/security.md
+++ b/doc/development/fe_guide/security.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Resources
-[Mozilla’s HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli) and the
+[Mozilla’s HTTP Observatory CLI](https://github.com/mozilla/http-observatory-cli) and
[Qualys SSL Labs Server Test](https://www.ssllabs.com/ssltest/analyze.html) are good resources for finding
potential problems and ensuring compliance with security best practices.
@@ -76,7 +76,7 @@ such as with reCAPTCHA, which cannot be used without an `iframe`.
In order to protect users from [XSS vulnerabilities](https://en.wikipedia.org/wiki/Cross-site_scripting), we intend to disable
inline scripts in the future using Content Security Policy.
-While inline scripts can be useful, they're also a security concern. If
+While inline scripts can make something easier, they're also a security concern. If
user-supplied content is unintentionally left un-sanitized, malicious users can
inject scripts into the web app.
diff --git a/doc/development/fe_guide/style/html.md b/doc/development/fe_guide/style/html.md
index 7fedbc6ce0d..e53686de1a0 100644
--- a/doc/development/fe_guide/style/html.md
+++ b/doc/development/fe_guide/style/html.md
@@ -6,6 +6,38 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# HTML style guide
+## Semantic elements
+
+[Semantic elements](https://developer.mozilla.org/en-US/docs/Glossary/Semantics) are HTML tags that
+give semantic (rather than presentational) meaning to the data they contain. For example:
+
+- [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
+- [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
+- [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
+
+Prefer using semantic tags, but only if the intention is truly accurate with the semantic meaning
+of the tag itself. View the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element)
+for a description on what each tag semantically means.
+
+```html
+<!-- bad - could use semantic tags instead of div's. -->
+<div class="...">
+ <p>
+ <!-- bad - this isn't what "strong" is meant for. -->
+ Simply visit your <strong>Settings</strong> to say hello to the world.
+ </p>
+ <div class="...">...</div>
+</div>
+
+<!-- good - prefer semantic classes used accurately -->
+<section class="...">
+ <p>
+ Simply visit your <span class="gl-font-weight-bold">Settings</span> to say hello to the world.
+ </p>
+ <footer class="...">...</footer>
+</section>
+```
+
## Buttons
### Button type
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index faf03a03101..5c35b880eab 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -14,7 +14,7 @@ In addition to the style guidelines set by Airbnb, we also have a few specific r
listed below.
NOTE:
-You can run eslint locally by running `yarn eslint`
+You can run ESLint locally by running `yarn eslint`
## Avoid forEach
diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md
index a4cae12c4f3..1d0b3c2b7fc 100644
--- a/doc/development/fe_guide/style/scss.md
+++ b/doc/development/fe_guide/style/scss.md
@@ -12,7 +12,7 @@ easy to maintain, and performant for the end-user.
## Rules
-Our CSS is a mixture of current and legacy approaches. That means sometimes it may be difficult to follow this guide to the letter; it means you are likely to run into exceptions, where following the guide is difficult to impossible without outsized effort. In those cases, you may work with your reviewers and maintainers to identify an approach that does not fit these rules. Please endeavor to limit these cases.
+Our CSS is a mixture of current and legacy approaches. That means sometimes it may be difficult to follow this guide to the letter; it means you are likely to run into exceptions, where following the guide is difficult to impossible without major effort. In those cases, you may work with your reviewers and maintainers to identify an approach that does not fit these rules. Please endeavor to limit these cases.
### Utility Classes
@@ -20,15 +20,19 @@ In order to reduce the generation of more CSS as our site grows, prefer the use
#### Where are utility classes defined?
-Prefer the use of [utility classes defined in GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md#utilities). An easy list of classes can also be [seen on Unpkg](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss).
+Prefer the use of [utility classes defined in GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/css.md#utilities).
+<!-- vale gitlab.Spelling = NO -->
+An easy list of classes can also be [seen on Unpkg](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss).
+<!-- vale gitlab.Spelling = YES -->
-Classes in [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/utilities.scss) and [`common.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/framework/common.scss) are being deprecated. Classes in [`common.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/framework/common.scss) that use non-design system values should be avoided in favor of conformant values.
+Classes in [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/utilities.scss) and [`common.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/framework/common.scss) are being deprecated.
+Classes in [`common.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/framework/common.scss) that use non-design-system values should be avoided. Use classes with conforming values instead.
Avoid [Bootstrap's Utility Classes](https://getbootstrap.com/docs/4.3/utilities/).
NOTE:
While migrating [Bootstrap's Utility Classes](https://getbootstrap.com/docs/4.3/utilities/)
-to the [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/css.md#utilities)
+to the [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/css.md#utilities)
utility classes, note both the classes for margin and padding differ. The size scale used at
GitLab differs from the scale used in the Bootstrap library. For a Bootstrap padding or margin
utility, you may need to double the size of the applied utility to achieve the same visual
@@ -36,9 +40,9 @@ result (such as `ml-1` becoming `gl-ml-2`).
#### Where should I put new utility classes?
-If a class you need has not been added to GitLab UI, you get to add it! Follow the naming patterns documented in the [utility files](https://gitlab.com/gitlab-org/gitlab-ui/-/tree/master/src/scss/utility-mixins) and refer to [GitLab UI's CSS documentation](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/master/doc/contributing/adding_css.md#adding-utility-mixins) for more details, especially about adding responsive and stateful rules.
+If a class you need has not been added to GitLab UI, you get to add it! Follow the naming patterns documented in the [utility files](https://gitlab.com/gitlab-org/gitlab-ui/-/tree/main/src/scss/utility-mixins) and refer to [GitLab UI's CSS documentation](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/contributing/adding_css.md#adding-utility-mixins) for more details, especially about adding responsive and stateful rules.
-If it is not possible to wait for a GitLab UI update (generally one day), add the class to [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/stylesheets/utilities.scss) following the same naming conventions documented in GitLab UI. A follow—up issue to backport the class to GitLab UI and delete it from GitLab should be opened.
+If it is not possible to wait for a GitLab UI update (generally one day), add the class to [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/utilities.scss) following the same naming conventions documented in GitLab UI. A follow—up issue to backport the class to GitLab UI and delete it from GitLab should be opened.
#### When should I create component classes?
@@ -47,7 +51,7 @@ We recommend a "utility-first" approach.
1. Start with utility classes.
1. If composing utility classes into a component class removes code duplication and encapsulates a clear responsibility, do it.
-This encourages an organic growth of component classes and prevents the creation of one-off unreusable classes. Also, the kind of classes that emerge from "utility-first" tend to be design-centered (e.g. `.button`, `.alert`, `.card`) rather than domain-centered (e.g. `.security-report-widget`, `.commit-header-icon`).
+This encourages an organic growth of component classes and prevents the creation of one-off non-reusable classes. Also, the kind of classes that emerge from "utility-first" tend to be design-centered (e.g. `.button`, `.alert`, `.card`) rather than domain-centered (e.g. `.security-report-widget`, `.commit-header-icon`).
Inspiration:
@@ -143,7 +147,7 @@ documentation includes [a full list of their linters](https://github.com/sds/scs
If you want to automate changing a large portion of the codebase to conform to
the SCSS style guide, you can use [CSSComb](https://github.com/csscomb/csscomb.js). First install
-[Node](https://github.com/nodejs/node) and [NPM](https://www.npmjs.com/), then run `npm install csscomb -g` to install
+[Node](https://github.com/nodejs/node) and [npm](https://www.npmjs.com/), then run `npm install csscomb -g` to install
CSSComb globally (system-wide). Run it in the GitLab directory with
`csscomb app/assets/stylesheets` to automatically fix issues with CSS/SCSS.
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
deleted file mode 100644
index 73a5bea189d..00000000000
--- a/doc/development/fe_guide/style_guide_js.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'style/javascript.md'
----
-
-This document was moved to [another location](style/javascript.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/fe_guide/style_guide_scss.md b/doc/development/fe_guide/style_guide_scss.md
deleted file mode 100644
index eaa6d33fb43..00000000000
--- a/doc/development/fe_guide/style_guide_scss.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'style/scss.md'
----
-
-This document was moved to [another location](style/scss.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/fe_guide/testing.md b/doc/development/fe_guide/testing.md
deleted file mode 100644
index 457d15235ae..00000000000
--- a/doc/development/fe_guide/testing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../testing_guide/frontend_testing.md'
----
-
-This document was moved to [another location](../testing_guide/frontend_testing.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/fe_guide/tooling.md b/doc/development/fe_guide/tooling.md
index d33022b9355..7a2d8fccdbf 100644
--- a/doc/development/fe_guide/tooling.md
+++ b/doc/development/fe_guide/tooling.md
@@ -111,7 +111,7 @@ preferred editor (all major editors are supported) accordingly. We suggest
setting up Prettier to run when each file is saved. For instructions about using
Prettier in your preferred editor, see the [Prettier documentation](https://prettier.io/docs/en/editors.html).
-Please take care that you only let Prettier format the same file types as the global Yarn script does (`.js`, `.vue`, `.graphql`, and `.scss`). In VSCode by example you can easily exclude file formats in your settings file:
+Please take care that you only let Prettier format the same file types as the global Yarn script does (`.js`, `.vue`, `.graphql`, and `.scss`). For example, you can exclude file formats in your Visual Studio Code settings file:
```json
"prettier.disableLanguages": [
@@ -128,13 +128,13 @@ The following yarn scripts are available to do global formatting:
yarn prettier-staged-save
```
-Updates all currently staged files (based on `git diff`) with Prettier and saves the needed changes.
+Updates all staged files (based on `git diff`) with Prettier and saves the needed changes.
```shell
yarn prettier-staged
```
-Checks all currently staged files (based on `git diff`) with Prettier and log which files would need manual updating to the console.
+Checks all staged files (based on `git diff`) with Prettier and log which files would need manual updating to the console.
```shell
yarn prettier-all
diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md
new file mode 100644
index 00000000000..abaf9cd68c7
--- /dev/null
+++ b/doc/development/fe_guide/troubleshooting.md
@@ -0,0 +1,41 @@
+---
+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
+---
+
+# Troubleshooting
+
+Running into a problem? Maybe this will help ¯\_(ツ)_/¯.
+
+## Troubleshooting issues
+
+### This guide doesn't contain the issue I ran into
+
+If you run into a Frontend development issue that is not in this guide, please consider updating this guide with your issue and possible remedies. This way future adventurers can face these dragons with more success, being armed with your experience and knowledge.
+
+## Testing issues
+
+### ``Property or method `nodeType` is not defined`` but I'm not using `nodeType` anywhere
+
+This issue can happen in Vue component tests, when an expectation fails, but there is an error thrown when
+Jest tries to pretty print the diff in the console. It's been noted that using `toEqual` with an array as a
+property might also be a contributing factor.
+
+See [this video](https://youtu.be/-BkEhghP-kM) for an in-depth overview and investigation.
+
+**Remedy - Try cloning the object that has Vue watchers**
+
+```patch
+- expect(wrapper.find(ChildComponent).props()).toEqual(...);
++ expect(cloneDeep(wrapper.find(ChildComponent).props())).toEqual(...)
+```
+
+**Remedy - Try using `toMatchObject` instead of `toEqual`**
+
+```patch
+- expect(wrapper.find(ChildComponent).props()).toEqual(...);
++ expect(wrapper.find(ChildComponent).props()).toMatchObject(...);
+```
+
+Please note that `toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation.
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index b3fbb9556a9..5b902e1b16e 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -20,9 +20,9 @@ What is described in the following sections can be found in these examples:
All new features built with Vue.js must follow a [Flux architecture](https://facebook.github.io/flux/).
The main goal we are trying to achieve is to have only one data flow and only one data entry.
-In order to achieve this goal we use [vuex](#vuex).
+In order to achieve this goal we use [Vuex](#vuex).
-You can also read about this architecture in Vue docs about
+You can also read about this architecture in Vue documentation about
[state management](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch)
and about [one way data flow](https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow).
@@ -70,7 +70,7 @@ The advantage of providing data from the DOM to the Vue instance through `props`
function instead of querying the DOM inside the main Vue component is avoiding the need to create a
fixture or an HTML element in the unit test, which makes the tests easier.
-See the following example, also, please refer to our [Vue style guide](style/vue.md#basic-rules) for
+See the following example. Also, please refer to our [Vue style guide](style/vue.md#basic-rules) for
additional information on why we explicitly declare the data being passed into the Vue app;
```javascript
@@ -101,8 +101,8 @@ across the codebase.
#### Accessing the `gl` object
-When we need to query the `gl` object for data that doesn't change during the application's life
-cycle, we should do it in the same place where we query the DOM. By following this practice, we can
+We query the `gl` object for data that doesn't change during the application's life
+cycle in the same place we query the DOM. By following this practice, we can
avoid the need to mock the `gl` object, which makes tests easier. It should be done while
initializing our Vue instance, and the data should be provided as `props` to the main component:
@@ -148,8 +148,8 @@ This approach has a few benefits:
- Arbitrarily deeply nested components can opt-in and access the flag without
intermediate components being aware of it (c.f. passing the flag down via
props).
-- Good testability, since the flag can be provided to `mount`/`shallowMount`
- from `vue-test-utils` simply as a prop.
+- Good testability, because the flag can be provided to `mount`/`shallowMount`
+ from `vue-test-utils` as a prop.
```javascript
import { shallowMount } from '@vue/test-utils';
@@ -207,20 +207,20 @@ Based on the Vue guidance:
such as `user: new User()`.
- **Do not** add new JavaScript class implementations.
- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if
-cannot use simple primitives or objects.
+cannot use primitives or objects.
- **Do** maintain existing implementations using such approaches.
- **Do** Migrate components to a pure object model when there are substantial changes to it.
-- **Do** add business logic to helpers or utils, so you can test them separately from your component.
+- **Do** add business logic to helpers or utilities, so you can test them separately from your component.
#### Why
There are additional reasons why having a JavaScript class presents maintainability issues on a huge codebase:
-- Once a class is created, it is easy to extend it in a way that can infringe Vue reactivity and best practices.
+- After a class is created, it can be extended in a way that can infringe Vue reactivity and best practices.
- A class adds a layer of abstraction, which makes the component API and its inner workings less clear.
-- It makes it harder to test. Since the class is instantiated by the component data function, it is
+- It makes it harder to test. Because the class is instantiated by the component data function, it is
harder to 'manage' component and class separately.
-- Adding OOP to a functional codebase adds yet another way of writing code, reducing consistency and clarity.
+- Adding Object Oriented Principles (OOP) to a functional codebase adds yet another way of writing code, reducing consistency and clarity.
## Style guide
@@ -234,8 +234,8 @@ for guidelines and best practices for testing your Vue components.
Each Vue component has a unique output. This output is always present in the render function.
-Although we can test each method of a Vue component individually, our goal must be to test the output
-of the render/template function, which represents the state at all times.
+Although each method of a Vue component can be tested individually, our goal is to test the output
+of the render function, which represents the state at all times.
Here's an example of a well structured unit test for [this Vue component](#appendix---vue-component-subject-under-test):
@@ -345,12 +345,12 @@ component under test, with the `computed` property, for example). Remember to us
```javascript
const checkbox = wrapper.findByTestId('checkboxTestId');
-
+
expect(checkbox.attributes('disabled')).not.toBeDefined();
-
+
findChildComponent().vm.$emit('primary');
await nextTick();
-
+
expect(checkbox.attributes('disabled')).toBeDefined();
```
@@ -359,14 +359,14 @@ component under test, with the `computed` property, for example). Remember to us
```javascript
// bad
expect(findChildComponent().find('.error-alert').exists()).toBe(false);
-
+
// good
expect(findChildComponent().props('withAlertContainer')).toBe(false);
```
### Events
-We should test for events emitted in response to an action within our component, this is useful to
+We should test for events emitted in response to an action in our component. This is used to
verify the correct events are being fired with the correct arguments.
For any DOM events we should use [`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger)
@@ -416,7 +416,7 @@ You should only apply to be a Vue.js expert when your own merge requests and you
> This section is added temporarily to support the efforts to migrate the codebase from Vue 2.x to Vue 3.x
-Currently, we recommend to minimize adding certain features to the codebase to prevent increasing
+We recommend to minimize adding certain features to the codebase to prevent increasing
the tech debt for the eventual migration:
- filters;
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md
index 9d2f3b27968..ee25e97ab6e 100644
--- a/doc/development/fe_guide/vue3_migration.md
+++ b/doc/development/fe_guide/vue3_migration.md
@@ -26,7 +26,7 @@ Component's computed properties / methods or external helpers.
**What to use instead**
-Vue docs recommend using [mitt](https://github.com/developit/mitt) library. It's relatively small (200 bytes gzipped) and has a simple API:
+Vue documentation recommends using the [mitt](https://github.com/developit/mitt) library. It's relatively small (200 bytes, compressed) and has a clear API:
```javascript
import mitt from 'mitt'
@@ -51,9 +51,9 @@ emitter.off('foo', onFoo) // unlisten
**Event hub factory**
-To make it easier for you to migrate existing event hubs to the new recommended approach, or simply
-to create new ones, we have created a factory that you can use to instantiate a new mitt-based
-event hub.
+We have created a factory that you can use to instantiate a new mitt-based event hub.
+This makes it easier to migrate existing event hubs to the new recommended approach, or
+to create new ones.
```javascript
import createEventHub from '~/helpers/event_hub_factory';
@@ -88,7 +88,7 @@ It is not recommended to replace stateful components with functional components
**Why?**
-In Vue 2.6 `slot` attribute was already deprecated in favor of `v-slot` directive but its usage is still allowed and sometimes we prefer using them because it simplifies unit tests (with old syntax, slots are rendered on `shallowMount`). However, in Vue 3 we can't use old syntax anymore.
+In Vue 2.6 `slot` attribute was already deprecated in favor of `v-slot` directive. The `slot` attribute usage is still allowed and sometimes we prefer using it because it simplifies unit tests (with old syntax, slots are rendered on `shallowMount`). However, in Vue 3 we can't use old syntax anymore.
**What to use instead**
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 1d83335291a..cc1d9ccab77 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -146,7 +146,7 @@ The only way to change state in a Vuex store is by committing a mutation.
Most mutations are committed from an action using `commit`. If you don't have any
asynchronous operations, you can call mutations from a component using the `mapMutations` helper.
-See the Vuex docs for examples of [committing mutations from components](https://vuex.vuejs.org/guide/mutations.html#committing-mutations-in-components).
+See the Vuex documentation for examples of [committing mutations from components](https://vuex.vuejs.org/guide/mutations.html#committing-mutations-in-components).
#### Naming Pattern: `REQUEST` and `RECEIVE` namespaces
@@ -271,7 +271,7 @@ import { mapGetters } from 'vuex';
### `mutation_types.js`
-From [vuex mutations docs](https://vuex.vuejs.org/guide/mutations.html):
+From [Vuex mutations documentation](https://vuex.vuejs.org/guide/mutations.html):
> It is a commonly seen pattern to use constants for mutation types in various Flux implementations.
> This allows the code to take advantage of tooling like linters, and putting all constants in a
> single file allows your collaborators to get an at-a-glance view of what mutations are possible
@@ -429,7 +429,7 @@ export default {
#### Testing Vuex concerns
-Refer to [Vuex docs](https://vuex.vuejs.org/guide/testing.html) regarding testing Actions, Getters and Mutations.
+Refer to [Vuex documentation](https://vuex.vuejs.org/guide/testing.html) regarding testing Actions, Getters and Mutations.
#### Testing components that need a store
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
deleted file mode 100644
index 7456e8df8d9..00000000000
--- a/doc/development/feature_flags.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'feature_flags/index.md'
----
-
-This document was moved to [another location](feature_flags/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index adcf3175c45..21ac152c469 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -11,12 +11,12 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
To be able to turn on/off features behind feature flags in any of the
GitLab Inc. provided environments such as staging and production, you need to
-have access to the [Chatops](../chatops_on_gitlabcom.md) bot. The Chatops bot
+have access to the [ChatOps](../chatops_on_gitlabcom.md) bot. The ChatOps bot
is currently running on the ops instance, which is different from <https://gitlab.com> or <https://dev.gitlab.org>.
-Follow the Chatops document to [request access](../chatops_on_gitlabcom.md#requesting-access).
+Follow the ChatOps document to [request access](../chatops_on_gitlabcom.md#requesting-access).
-Once you are added to the project test if your access propagated,
+After you are added to the project test if your access propagated,
run:
```shell
@@ -37,7 +37,7 @@ easier to measure the impact of both separately.
The GitLab feature library (using
[Flipper](https://github.com/jnunemaker/flipper), and covered in the [Feature
Flags process](process.md) guide) supports rolling out changes to a percentage of
-time to users. This in turn can be controlled using [GitLab Chatops](../../ci/chatops/README.md).
+time to users. This in turn can be controlled using [GitLab ChatOps](../../ci/chatops/index.md).
For an up to date list of feature flag commands please see [the source
code](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb).
@@ -48,7 +48,7 @@ If you get an error "Whoops! This action is not allowed. This incident
will be reported." that means your Slack account is not allowed to
change feature flags or you do not [have access](#access).
-### Enabling a feature for preproduction testing
+### Enabling a feature for pre-production testing
As a first step in a feature rollout, you should enable the feature on <https://about.staging.gitlab.com>
and <https://dev.gitlab.org>.
@@ -62,7 +62,7 @@ a (very) rough estimate of how your feature will look/behave on GitLab.com.
Both of these instances are connected to Sentry so make sure you check the projects
there for any exceptions while testing your feature after enabling the feature flag.
-For these preproduction environments, the commands should be run in a
+For these pre-production environments, the commands should be run in a
Slack channel for the stage the feature is relevant to. For example, use the
`#s_monitor` channel for features developed by the Monitor stage, Health
group.
@@ -77,7 +77,7 @@ To enable a feature for 25% of all users, run the following in Slack:
### Enabling a feature for GitLab.com
When a feature has successfully been
-[enabled on a preproduction](#enabling-a-feature-for-preproduction-testing)
+[enabled on a pre-production](#enabling-a-feature-for-pre-production-testing)
environment and verified as safe and working, you can roll out the
change to GitLab.com (production).
@@ -226,11 +226,27 @@ you should fully roll out the feature by enabling the flag **globally** by runni
This changes the feature flag state to be **enabled** always, which overrides the
existing gates (e.g. `--group=gitlab-org`) in the above processes.
+##### Disabling feature flags
+
+To disable a feature flag that has been globally enabled you can run:
+
+```shell
+/chatops run feature set some_feature false
+```
+
+To disable a feature flag that has been enabled for a specific project you can run:
+
+```shell
+/chatops run feature set --group=gitlab-org some_feature false
+```
+
+You cannot selectively disable feature flags for a specific project/group/user without applying a [specific method of implementing](development.md#selectively-disable-by-actor) the feature flags.
+
### Feature flag change logging
-#### Chatops level
+#### ChatOps level
-Any feature flag change that affects GitLab.com (production) via [Chatops](https://gitlab.com/gitlab-com/chatops)
+Any feature flag change that affects GitLab.com (production) via [ChatOps](https://gitlab.com/gitlab-com/chatops)
is automatically logged in an issue.
The issue is created in the
@@ -243,7 +259,7 @@ The issue is then also posted to the GitLab internal
marker to make the change even more visible.
Changes to the issue format can be submitted in the
-[Chatops project](https://gitlab.com/gitlab-com/chatops).
+[ChatOps project](https://gitlab.com/gitlab-com/chatops).
#### Instance level
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index dd732a08c72..0cdfa3e68d7 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -66,6 +66,13 @@ Feature.disabled?(:my_ops_flag, project, type: :ops)
push_frontend_feature_flag(:my_ops_flag, project, type: :ops)
```
+### `experiment` type
+
+`experiment` feature flags are used for A/B testing on GitLab.com.
+
+An `experiment` feature flag should conform to the same standards as a `development` feature flag,
+although the interface has some differences. More information can be found in the [experiment guide](../experiment_guide/index.md).
+
## Feature flag definition and validation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229161) in GitLab 13.3.
@@ -321,6 +328,28 @@ Feature.enabled?(:feature_flag, group)
Feature.enabled?(:feature_flag, user)
```
+#### Selectively disable by actor
+
+By default you cannot selectively disable a feature flag by actor.
+
+```shell
+# This will not work how you would expect.
+/chatops run feature set some_feature true
+/chatops run feature set --project=gitlab-org/gitlab some_feature false
+```
+
+However, if you add two feature flags, you can write your conditional statement in such a way that the equivalent selective disable is possible.
+
+```ruby
+Feature.enabled?(:a_feature, project) && Feature.disabled?(:a_feature_override, project)
+```
+
+```shell
+# This will enable a feature flag globally, except for gitlab-org/gitlab
+/chatops run feature set a_feature true
+/chatops run feature set --project=gitlab-org/gitlab a_feature_override true
+```
+
### Enable additional objects as actors
To use feature gates based on actors, the model needs to respond to
@@ -398,6 +427,9 @@ to ensure the feature works properly.
When using the testing environment, all feature flags are enabled by default.
+WARNING:
+This does not apply to end-to-end (QA) tests, which [do not disable feature flags by default](#end-to-end-qa-tests). There is a different [process for using feature flags in end-to-end tests](../testing_guide/end_to_end/feature_flags.md).
+
To disable a feature flag in a test, use the `stub_feature_flags`
helper. For example, to globally disable the `ci_live_trace` feature
flag in a test:
@@ -545,3 +577,17 @@ a mode that is used by `production` and `development`.
You should use this mode only when you really want to tests aspects of Flipper
with how it interacts with `ActiveRecord`.
+
+### End-to-end (QA) tests
+
+Toggling feature flags works differently in end-to-end (QA) tests. The end-to-end test framework does not have direct access to
+Rails or the database, so it can't use Flipper. Instead, it uses [the public API](../../api/features.md#set-or-create-a-feature). Each end-to-end test can [enable or disable a feature flag during the test](../testing_guide/end_to_end/feature_flags.md). Alternatively, you can enable or disable a feature flag before one or more tests when you [run them from your GitLab repository's `qa` directory](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled-or-disabled), or if you [run the tests via GitLab QA](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#running-tests-with-a-feature-flag-enabled).
+
+[As noted above, feature flags are not enabled by default in end-to-end tests.](#feature-flags-in-tests)
+This means that end-to-end tests will run with feature flags in the default state implemented in the source
+code, or with the feature flag in its current state on the GitLab instance under test, unless the
+test is written to enable/disable a feature flag explicitly.
+
+When a feature flag is changed on Staging or on GitLab.com, a Slack message will be posted to the `#qa-staging` or `#qa-production` channels to inform
+the pipeline triage DRI so that they can more easily determine if any failures are related to a feature flag change. However, if you are working on a change you can
+help to avoid unexpected failures by [confirming that the end-to-end tests pass with a feature flag enabled.](../testing_guide/end_to_end/feature_flags.md#confirming-that-end-to-end-tests-pass-with-a-feature-flag-enabled)
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index e93a5b3de1b..4890cc5da35 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -31,7 +31,8 @@ In all cases, those working on the changes should ask themselves:
> Why do I need to add a feature flag? If I don't add one, what options do I have to control the impact on application reliability, and user experience?
-For perspective on why we limit our use of feature flags please see the following [video](https://www.youtube.com/watch?v=DQaGqyolOd8).
+For perspective on why we limit our use of feature flags please see
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Feature flags only when needed](https://www.youtube.com/watch?v=DQaGqyolOd8).
In case you are uncertain if a feature flag is necessary, simply ask about this in an early merge request, and those reviewing the changes will likely provide you with an answer.
diff --git a/doc/development/feature_flags/process.md b/doc/development/feature_flags/process.md
index 7e6299c193c..65a6d01e0a2 100644
--- a/doc/development/feature_flags/process.md
+++ b/doc/development/feature_flags/process.md
@@ -155,7 +155,7 @@ It may seem like feature flags are configuration, which goes against our [conven
principle. However, configuration is by definition something that is user-manageable.
Feature flags are not intended to be user-editable. Instead, they are intended as a tool for Engineers
and Site Reliability Engineers to use to de-risk their changes. Feature flags are the shim that gets us
-to Continuous Delivery with our mono repo and without having to deploy the entire codebase on every change.
+to Continuous Delivery with our monorepo and without having to deploy the entire codebase on every change.
Feature flags are created to ensure that we can safely rollout our work on our terms.
If we use Feature Flags as a configuration, we are doing it wrong and are indeed in violation of our
principles. If something needs to be configured, we should intentionally make it configuration from the
@@ -173,5 +173,5 @@ Some of the benefits of using development-type feature flags are:
1. Improved throughput: when a change is less risky because a flag exists, theoretical tests about
scalability can potentially become unnecessary or less important. This allows an engineer to
potentially test a feature on a small project, monitor the impact, and proceed. The alternative might
- be to build complex benchmarks locally, or on staging, or on another GitLab deployment, which has an
- outsized impact on the time it can take to build and release a feature.
+ be to build complex benchmarks locally, or on staging, or on another GitLab deployment, which has a
+ large impact on the time it can take to build and release a feature.
diff --git a/doc/development/filtering_by_label.md b/doc/development/filtering_by_label.md
index b10e2f6e082..2b9c7efc087 100644
--- a/doc/development/filtering_by_label.md
+++ b/doc/development/filtering_by_label.md
@@ -137,7 +137,7 @@ object, so the number of combinations would balloon further.
### Attempt B2: store label titles for each object
-From the perspective of updating the labelable object, this is the worst
+From the perspective of updating the object, this is the worst
option. We have to bulk update the objects when:
1. The objects are moved from one project to another.
@@ -159,7 +159,7 @@ However, at present, the disadvantages outweigh the advantages.
## Conclusion
-We have yet to find a method that is demonstratably better than the current
+We have yet to find a method that is demonstrably better than the current
method, when considering:
1. Query performance.
diff --git a/doc/development/foreign_keys.md b/doc/development/foreign_keys.md
index 37764a12f97..abe191ace5e 100644
--- a/doc/development/foreign_keys.md
+++ b/doc/development/foreign_keys.md
@@ -75,7 +75,7 @@ your models _unless_ absolutely required and only when approved by database
specialists. For example, if each row in a table has a corresponding file on a
file system it may be tempting to add a `after_destroy` hook. This however
introduces non database logic to a model, and means we can no longer rely on
-foreign keys to remove the data as this would result in the filesystem data
+foreign keys to remove the data as this would result in the file system data
being left behind. In such a case you should use a service class instead that
takes care of removing non database data.
diff --git a/doc/development/frontend.md b/doc/development/frontend.md
deleted file mode 100644
index 040004a6917..00000000000
--- a/doc/development/frontend.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'fe_guide/index.md'
----
-
-This document was moved to [another location](fe_guide/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
index c4a9ec4c454..0be772db12e 100644
--- a/doc/development/gemfile.md
+++ b/doc/development/gemfile.md
@@ -18,3 +18,16 @@ dependencies and build times.
## License compliance
Refer to [licensing guidelines](licensing.md) for ensuring license compliance.
+
+## Upgrade Rails
+
+When upgrading the Rails gem and its dependencies, you also should update the following:
+
+- The [`Gemfile` in the `qa` directory](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/Gemfile).
+- The [`Gemfile` in Gitaly Ruby](https://gitlab.com/gitlab-org/gitaly/-/blob/master/ruby/Gemfile),
+ to ensure that we ship only one version of these gems.
+
+You should also update npm packages that follow the current version of Rails:
+
+- `@rails/ujs`
+- `@rails/actioncable`
diff --git a/doc/development/geo.md b/doc/development/geo.md
index ed1837f9564..05fadcad08a 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -4,7 +4,7 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Geo (development) **(PREMIUM ONLY)**
+# Geo (development) **(PREMIUM SELF)**
Geo connects GitLab instances together. One GitLab instance is
designated as a **primary** node and can be run with multiple
@@ -305,7 +305,7 @@ events include:
- Repositories Changed event
- Repository Created event
- Hashed Storage Migrated event
-- Lfs Object Deleted event
+- LFS Object Deleted event
- Hashed Storage Attachments event
- Job Artifact Deleted event
- Upload Deleted event
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 148953dc418..e615fbc87a9 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -189,11 +189,6 @@ For example, to add support for files referenced by a `Widget` model with a
mount_uploader :file, WidgetUploader
- def local?
- # Must to be implemented, Check the uploader's storage types
- file_store == ObjectStorage::Store::LOCAL
- end
-
# @param primary_key_in [Range, Widget] arg to pass to primary_key_in scope
# @return [ActiveRecord::Relation<Widget>] everything that should be synced to this node, restricted by primary key
def self.replicables_for_current_secondary(primary_key_in)
@@ -279,17 +274,32 @@ For example, to add support for files referenced by a `Widget` model with a
unless table_exists?(:widget_registry)
ActiveRecord::Base.transaction do
create_table :widget_registry, id: :bigserial, force: :cascade do |t|
- t.integer :widget_id, null: false
+ t.bigint :widget_id, null: false
+ t.datetime_with_timezone :created_at, null: false
+ t.datetime_with_timezone :last_synced_at
+ t.datetime_with_timezone :retry_at
+ t.datetime_with_timezone :verified_at
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
t.integer :state, default: 0, null: false, limit: 2
+ t.integer :verification_state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2
- t.datetime_with_timezone :retry_at
- t.datetime_with_timezone :last_synced_at
- t.datetime_with_timezone :created_at, null: false
+ t.integer :verification_retry_count, default: 0, limit: 2
+ t.boolean :checksum_mismatch
+ t.binary :verification_checksum
+ t.binary :verification_checksum_mismatched
+ t.string :verification_failure, limit: 255
t.text :last_sync_failure
t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true
t.index :retry_at
t.index :state
+ # To optimize performance of WidgetRegistry.verification_failed_batch
+ t.index :verification_retry_at, name: :widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
+ # To optimize performance of WidgetRegistry.needs_verification_count
+ t.index :verification_state, name: :widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
+ # To optimize performance of WidgetRegistry.verification_pending_batch
+ t.index :verified_at, name: :widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
end
end
end
@@ -310,6 +320,10 @@ For example, to add support for files referenced by a `Widget` model with a
class Geo::WidgetRegistry < Geo::BaseRegistry
include Geo::ReplicableRegistry
+ # TODO: Include VerificationState in VerifiableRegistry
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/298811
+ include ::Gitlab::Geo::VerificationState
+ include ::Geo::VerifiableRegistry
MODEL_CLASS = ::Widget
MODEL_FOREIGN_KEY = :widget_id
@@ -366,6 +380,7 @@ For example, to add support for files referenced by a `Widget` model with a
end
include_examples 'a Geo framework registry'
+ include_examples 'a Geo verifiable registry'
describe '.find_registry_differences' do
... # To be implemented
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 5d062d7404e..87b9d35f99b 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -12,17 +12,18 @@ Workhorse and GitLab Shell.
## Deep Dive
-In May 2019, Bob Van Landuyt hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
-on the [Gitaly project](https://gitlab.com/gitlab-org/gitaly) and how to contribute to it as a
-Ruby developer, to share his domain specific knowledge with anyone who may work in this part of the
+In May 2019, <!-- vale gitlab.Spelling = NO --> Bob Van Landuyt <!-- vale gitlab.Spelling = YES -->
+hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
+on the [Gitaly project](https://gitlab.com/gitlab-org/gitaly). It included how to contribute to it as a
+Ruby developer, and shared domain-specific knowledge with anyone who may work in this part of the
codebase in the future.
-You can find the [recording on YouTube](https://www.youtube.com/watch?v=BmlEWFS8ORo), and the slides
+You can find the <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=BmlEWFS8ORo), and the slides
on [Google Slides](https://docs.google.com/presentation/d/1VgRbiYih9ODhcPnL8dS0W98EwFYpJ7GXMPpX-1TM6YE/edit)
and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/a4fdb1026278bda5c1c5bb574379cf80/Create_Deep_Dive__Gitaly_for_Create_Ruby_Devs.pdf).
Everything covered in this deep dive was accurate as of GitLab 11.11, and while specific details may
-have changed since then, it should still serve as a good introduction.
+have changed, it should still serve as a good introduction.
## Beginner's guide
@@ -43,7 +44,7 @@ needs direct access to the Git repository *must* be implemented in Gitaly, and
exposed via an RPC.
It's often easier to develop a new feature in Gitaly if you make the changes to
-GitLab that will use the new feature in a separate merge request, to be merged
+GitLab that intends to use the new feature in a separate merge request, to be merged
immediately after the Gitaly one. This allows you to test your changes before
they are merged.
@@ -107,9 +108,9 @@ bundle exec rake gitlab:features:disable_rugged
Most of this code exists in the `lib/gitlab/git/rugged_impl` directory.
NOTE:
-You should NOT need to add or modify code related to
-Rugged unless explicitly discussed with the [Gitaly
-Team](https://gitlab.com/groups/gl-gitaly/group_members). This code does
+You should *not* need to add or modify code related to
+Rugged unless explicitly discussed with the
+[Gitaly Team](https://gitlab.com/groups/gl-gitaly/group_members). This code does
NOT work on GitLab.com or other GitLab instances that do not use NFS.
## `TooManyInvocationsError` errors
@@ -129,7 +130,7 @@ Isolate the source of the n+1 problem. This is normally a loop that results in G
element in an array. If you are unable to isolate the problem, please contact a member
of the [Gitaly Team](https://gitlab.com/groups/gl-gitaly/group_members) for assistance.
-Once the source has been found, wrap it in an `allow_n_plus_1_calls` block, as follows:
+After the source has been found, wrap it in an `allow_n_plus_1_calls` block, as follows:
```ruby
# n+1: link to n+1 issue
@@ -139,7 +140,7 @@ Gitlab::GitalyClient.allow_n_plus_1_calls do
end
```
-Once the code is wrapped in this block, this code path is excluded from n+1 detection.
+After the code is wrapped in this block, this code path is excluded from n+1 detection.
## Request counts
@@ -164,13 +165,13 @@ end
Normally, GitLab CE/EE tests use a local clone of Gitaly in
`tmp/tests/gitaly` pinned at the version specified in
`GITALY_SERVER_VERSION`. The `GITALY_SERVER_VERSION` file supports also
-branches and SHA to use a custom commit in <https://gitlab.com/gitlab-org/gitaly>.
+branches and SHA to use a custom commit in [the repository](https://gitlab.com/gitlab-org/gitaly).
NOTE:
With the introduction of auto-deploy for Gitaly, the format of
`GITALY_SERVER_VERSION` was aligned with Omnibus syntax.
It no longer supports `=revision`, it evaluates the file content as a Git
-reference (branch or SHA). Only if it matches a semver does it prepend a `v`.
+reference (branch or SHA). Only if it matches a semantic version does it prepend a `v`.
If you want to run tests locally against a modified version of Gitaly you
can replace `tmp/tests/gitaly` with a symlink. This is much faster
@@ -195,7 +196,7 @@ Note that CI tests do not use your locally modified version of
Gitaly. To use a custom Gitaly version in CI you need to update
GITALY_SERVER_VERSION as described at the beginning of this section.
-To use a different Gitaly repository, e.g., if your changes are present
+To use a different Gitaly repository, such as if your changes are present
on a fork, you can specify a `GITALY_REPO_URL` environment variable when
running tests:
@@ -210,15 +211,15 @@ and specify it in the URL:
GITALY_REPO_URL=https://gitlab+deploy-token-1000:token-here@gitlab.com/nick.thomas/gitaly bundle exec rspec spec/lib/gitlab/git/repository_spec.rb
```
-To use a custom Gitaly repository in CI, for instance if you want your
+To use a custom Gitaly repository in CI/CD, for instance if you want your
GitLab fork to always use your own Gitaly fork, set `GITALY_REPO_URL`
-as a [CI environment variable](../ci/variables/README.md#gitlab-cicd-environment-variables).
+as a [CI/CD variable](../ci/variables/README.md).
### Use a locally modified version of Gitaly RPC client
If you are making changes to the RPC client, such as adding a new endpoint or adding a new
parameter to an existing endpoint, follow the guide for
-[Gitaly proto](https://gitlab.com/gitlab-org/gitaly/blob/master/proto/README.md). After pushing
+[Gitaly protobuf specifications](https://gitlab.com/gitlab-org/gitaly/blob/master/proto/README.md). After pushing
the branch with the changes (`new-feature-branch`, for example):
1. Change the `gitaly` line in the Rails' `Gemfile` to:
@@ -328,15 +329,15 @@ the integration by using GDK:
1. Uncomment `prometheus_listen_addr` in the configuration file and run `gdk restart gitaly`.
1. Make sure that the flag is not enabled yet:
- 1. Perform whatever action is required to trigger your changes (project creation,
- submitting commit, observing history, etc.).
+ 1. Perform whatever action is required to trigger your changes, such as project creation,
+ submitting commit, or observing history.
1. Check that the list of current metrics has the new counter for the feature flag:
```shell
curl --silent "http://localhost:9236/metrics" | grep go_find_all_tags
```
-1. Once you observe the metrics for the new feature flag and it increments, you
+1. After you observe the metrics for the new feature flag and it increments, you
can enable the new feature:
1. Navigate to GDK's root directory.
1. Start a Rails console:
@@ -359,7 +360,7 @@ the integration by using GDK:
```
1. Exit the Rails console and perform whatever action is required to trigger
- your changes (project creation, submitting commit, observing history, etc.).
+ your changes, such as project creation, submitting commit, or observing history.
1. Verify the feature is on by observing the metrics for it:
```shell
diff --git a/doc/development/go_guide/dependencies.md b/doc/development/go_guide/dependencies.md
index 72b3f82d86f..c5af21d0772 100644
--- a/doc/development/go_guide/dependencies.md
+++ b/doc/development/go_guide/dependencies.md
@@ -178,4 +178,4 @@ authenticate requests made over HTTP. Go rejects HTTP-only entries in
`GOPROXY` that have embedded credentials.
In a future version, Go may add support for arbitrary authentication headers.
-Follow [golang/go#26232](https://github.com/golang/go/issues/26232) for details.
+Follow [`golang/go#26232`](https://github.com/golang/go/issues/26232) for details.
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 68210c08a00..f352db918ed 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -63,10 +63,9 @@ of possible security breaches in our code:
Remember to run
[SAST](../../user/application_security/sast/index.md) and [Dependency Scanning](../../user/application_security/dependency_scanning/index.md)
-**(ULTIMATE)** on your project (or at least the [gosec
-analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/gosec)),
-and to follow our [Security
-requirements](../code_review.md#security-requirements).
+**(ULTIMATE)** on your project (or at least the
+[`gosec` analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/gosec)),
+and to follow our [Security requirements](../code_review.md#security-requirements).
Web servers can take advantages of middlewares like [Secure](https://github.com/unrolled/secure).
@@ -92,9 +91,9 @@ projects:
- Avoid global variables, even in packages. By doing so you introduce side
effects if the package is included multiple times.
- Use `goimports` before committing.
- [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports)
+ [`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports)
is a tool that automatically formats Go source code using
- [Gofmt](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
+ [`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
adding missing ones and removing unreferenced ones.
Most editors/IDEs allow you to run commands before/after saving a file, you can set it
@@ -162,8 +161,8 @@ be downloaded repeatedly, which can lead to intermittent problems due to rate
limiting or network failures. In these circumstances, you should [cache the
downloaded code between](../../ci/caching/index.md#caching-go-dependencies).
-There was a [bug on modules
-checksums](https://github.com/golang/go/issues/29278) in Go < v1.11.4, so make
+There was a
+[bug on modules checksums](https://github.com/golang/go/issues/29278) in Go versions earlier than v1.11.4, so make
sure to use at least this version to avoid `checksum mismatch` errors.
### ORM
@@ -171,7 +170,7 @@ sure to use at least this version to avoid `checksum mismatch` errors.
We don't use object-relational mapping libraries (ORMs) at GitLab (except
[ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) in
Ruby on Rails). Projects can be structured with services to avoid them.
-[pgx](https://github.com/jackc/pgx) should be enough to interact with PostgreSQL
+[`pgx`](https://github.com/jackc/pgx) should be enough to interact with PostgreSQL
databases.
### Migrations
@@ -193,7 +192,7 @@ external dependencies might be worth considering in case we decide to use a spec
library or framework:
- [Testify](https://github.com/stretchr/testify)
-- [httpexpect](https://github.com/gavv/httpexpect)
+- [`httpexpect`](https://github.com/gavv/httpexpect)
### Subtests
@@ -329,8 +328,8 @@ A few things to keep in mind when adding context:
## CLIs
Every Go program is launched from the command line.
-[cli](https://github.com/urfave/cli) is a convenient package to create command
-line apps. It should be used whether the project is a daemon or a simple cli
+[`cli`](https://github.com/urfave/cli) is a convenient package to create command
+line apps. It should be used whether the project is a daemon or a simple CLI
tool. Flags can be mapped to [environment
variables](https://github.com/urfave/cli#values-from-the-environment) directly,
which documents and centralizes at the same time all the possible command line
@@ -389,7 +388,7 @@ functionality:
This gives us a thin abstraction over underlying implementations that is
consistent across Workhorse, Gitaly, and, in future, other Go servers. For
example, in the case of `gitlab.com/gitlab-org/labkit/tracing` we can switch
-from using Opentracing directly to using Zipkin or Gokit's own tracing wrapper
+from using `Opentracing` directly to using `Zipkin` or Gokit's own tracing wrapper
without changes to the application code, while still keeping the same
consistent configuration mechanism (i.e. the `GITLAB_TRACING` environment
variable).
@@ -489,9 +488,9 @@ The following are some style guidelines that are specific to the Secure Team.
### Code style and format
Use `goimports -local gitlab.com/gitlab-org` before committing.
-[goimports](https://godoc.org/golang.org/x/tools/cmd/goimports)
+[`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports)
is a tool that automatically formats Go source code using
-[Gofmt](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
+[`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
adding missing ones and removing unreferenced ones.
By using the `-local gitlab.com/gitlab-org` option, `goimports` groups locally referenced
packages separately from external ones. See
diff --git a/doc/development/graphql_guide/batchloader.md b/doc/development/graphql_guide/batchloader.md
index e965e678aba..1869c6e6f80 100644
--- a/doc/development/graphql_guide/batchloader.md
+++ b/doc/development/graphql_guide/batchloader.md
@@ -20,7 +20,7 @@ When implementing a new endpoint we should aim to minimise the number of SQL que
Batch loading is useful when a series of queries for inputs `Qα, Qβ, ... Qω` can be combined to a single query for `Q[α, β, ... ω]`. An example of this is lookups by ID, where we can find two users by usernames as cheaply as one, but real-world examples can be more complex.
-Batchloading is not suitable when the result sets have different sort-orders, grouping, aggregation or other non-composable features.
+Batch loading is not suitable when the result sets have different sort-orders, grouping, aggregation or other non-composable features.
There are two ways to use the batch-loader in your code. For simple ID lookups, use `::Gitlab::Graphql::Loaders::BatchModelLoader.new(model, id).find`. For more complex cases, you can use the batch API directly.
diff --git a/doc/development/graphql_guide/graphql_pro.md b/doc/development/graphql_guide/graphql_pro.md
new file mode 100644
index 00000000000..6f62d86af40
--- /dev/null
+++ b/doc/development/graphql_guide/graphql_pro.md
@@ -0,0 +1,21 @@
+---
+stage: Plan
+group: Project Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GraphQL Pro
+
+GraphQL has become a key technology in GitLab and is implemented using the
+[GraphQL Ruby gem](https://graphql-ruby.org). As such, we've purchased a subscription to
+[GraphQL Pro](https://graphql.pro).
+
+The main purpose is for support. Per the website:
+
+> As a GraphQL::Pro customer, you get direct access to the GraphQL Ruby gem
+> creator and maintainer. Get prioritized support for issues and requests.
+
+Note that we **cannot** use the Pro version directly in our product, since we are
+an Open Core product - we can not require customers to purchase the Pro version, nor can we ship it.
+
+Details on the billing account and gem licensing can be found in the Engineering 1Password vault.
diff --git a/doc/development/graphql_guide/index.md b/doc/development/graphql_guide/index.md
index 658bba96f33..fd6d8992f94 100644
--- a/doc/development/graphql_guide/index.md
+++ b/doc/development/graphql_guide/index.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Plan
+group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -17,3 +17,6 @@ feedback, and suggestions.
- [GraphQL API documentation style guide](../documentation/graphql_styleguide.md): documentation
style guide for GraphQL.
- [GraphQL API](../../api/graphql/index.md): user documentation for the GitLab GraphQL API.
+- [GraphQL BatchLoader](batchloader.md): development documentation on the batchloader.
+- [GraphQL pagination](pagination.md): development documentation on pagination.
+- [GraphQL Pro](graphql_pro.md): information on our GraphQL Pro subscription.
diff --git a/doc/development/graphql_guide/pagination.md b/doc/development/graphql_guide/pagination.md
index 130ed5721f3..55ff7942418 100644
--- a/doc/development/graphql_guide/pagination.md
+++ b/doc/development/graphql_guide/pagination.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Plan
+group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index 582c1428bdd..e7d25942143 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -66,12 +66,14 @@ have been fixed on master.
NOTE:
These instructions work only for GitLab Team Members.
-If for some reason the GitLab integration in CrowdIn does not exist, it can be
-recreated by the following steps:
-
-1. Sign in to GitLab as `gitlab-crowdin-bot` (If you're a GitLab Team Member, find credentials in the GitLab shared [1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams)
-1. Sign in to Crowdin with the GitLab integration
-1. Navigate to Settings > Integrations > GitLab > Set Up Integration
-1. Select `gitlab-org/gitlab` repository
-1. On `Select Branches for Translation`, select `master`
-1. Ensure the `Service Branch Name` is `master-i18n`
+If for some reason the GitLab integration in CrowdIn doesn't exist, you can
+recreate it with the following steps:
+
+1. Sign in to GitLab as `gitlab-crowdin-bot`. (If you're a GitLab Team Member,
+ find credentials in the GitLab shared
+ [1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).)
+1. Sign in to CrowdIn with the GitLab integration.
+1. Go to **Settings > Integrations > GitLab > Set Up Integration**.
+1. Select the `gitlab-org/gitlab` repository.
+1. In `Select Branches for Translation`, select `master`.
+1. Ensure the `Service Branch Name` is `master-i18n`.
diff --git a/doc/development/i18n_guide.md b/doc/development/i18n_guide.md
deleted file mode 100644
index ddc91f9308e..00000000000
--- a/doc/development/i18n_guide.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'i18n/index.md'
----
-
-This document was moved to [another location](i18n/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index dfe6153ad45..a4917cc0c3d 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -170,7 +170,7 @@ The last option is to import a project using a Rails console:
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path,
shared: shared,
- project: project).restore
+ importable: project).restore
```
We are storing all import failures in the `import_failures` data table.
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index 94b56e10d9e..338ad76d414 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Instrumenting Ruby code
+# Instrumenting Ruby code **(FREE)**
[GitLab Performance Monitoring](../administration/monitoring/performance/index.md) allows instrumenting of both methods and custom
blocks of Ruby code. Method instrumentation is the primary form of
diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md
index faa1ec0ee3f..62acdda6d0d 100644
--- a/doc/development/integrations/codesandbox.md
+++ b/doc/development/integrations/codesandbox.md
@@ -1,14 +1,20 @@
-# Set up local Codesandbox development environment
+---
+stage: none
+group: Development
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
-This guide walks through setting up a local [Codesandbox repository](https://github.com/codesandbox/codesandbox-client) and integrating it with a local GitLab instance. Codesandbox
-is used to power the Web IDE's [Live Preview feature](../../user/project/web_ide/index.md#live-preview). Having a local Codesandbox setup is useful for debugging upstream issues or
+# Set up local CodeSandbox development environment
+
+This guide walks through setting up a local [CodeSandbox repository](https://github.com/codesandbox/codesandbox-client) and integrating it with a local GitLab instance. CodeSandbox
+is used to power the Web IDE's [Live Preview feature](../../user/project/web_ide/index.md#live-preview). Having a local CodeSandbox setup is useful for debugging upstream issues or
creating upstream contributions like [this one](https://github.com/codesandbox/codesandbox-client/pull/5137).
## Initial setup
-Before using Codesandbox with your local GitLab instance, you must:
+Before using CodeSandbox with your local GitLab instance, you must:
-1. Enable HTTPS on your GDK. Codesandbox uses Service Workers that require `https`.
+1. Enable HTTPS on your GDK. CodeSandbox uses Service Workers that require `https`.
Follow the GDK [NGINX configuration instructions](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/nginx.md) to enable HTTPS for GDK.
1. Clone the [`codesandbox-client` project](https://github.com/codesandbox/codesandbox-client)
locally. If you plan on contributing upstream, you might want to fork and clone first.
@@ -32,16 +38,16 @@ Before using Codesandbox with your local GitLab instance, you must:
You can run `yarn build:clean` to clean up the build assets.
-## Use local GitLab instance with local Codesandbox
+## Use local GitLab instance with local CodeSandbox
-GitLab integrates with two parts of Codesandbox:
+GitLab integrates with two parts of CodeSandbox:
-- An NPM package called `smooshpack` (called `sandpack` in the `codesandbox-client` project).
+- An npm package called `smooshpack` (called `sandpack` in the `codesandbox-client` project).
This exposes an entrypoint for us to kick off Codesandbox's bundler.
-- A server that houses Codesandbox assets for bundling and previewing. This is hosted
+- A server that houses CodeSandbox assets for bundling and previewing. This is hosted
on a separate server for security.
-Each time you want to run GitLab and Codesandbox together, you need to perform the
+Each time you want to run GitLab and CodeSandbox together, you need to perform the
steps in the following sections.
### Use local `smooshpack` for GitLab
@@ -88,7 +94,7 @@ mkdir node_modules
ln -s $PATH_TO_LOCAL_GITLAB/node_modules/core-js ./node_modules/core-js
```
-### Start building codesandbox app assets
+### Start building CodeSandbox app assets
In the `codesandbox-client` project directory:
@@ -98,7 +104,7 @@ cd packages/app
yarn start:sandpack-sandbox
```
-### Create HTTPS proxy for Codesandbox `sandpack` assets
+### Create HTTPS proxy for CodeSandbox `sandpack` assets
Because we need `https`, we need to create a proxy to the webpack server. We can use
[`http-server`](https://www.npmjs.com/package/http-server), which can do this proxying
@@ -111,7 +117,7 @@ npx http-server --proxy http://localhost:3000 -S -C $PATH_TO_CERT_PEM -K $PATH_T
### Update `bundler_url` setting in GitLab
We need to update our `application_setting_implementation.rb` to point to the server that hosts the
-Codesandbox `sandpack` assets. For instance, if these assets are hosted by a server at `https://sandpack.local:8044`:
+CodeSandbox `sandpack` assets. For instance, if these assets are hosted by a server at `https://sandpack.local:8044`:
```patch
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
@@ -133,7 +139,7 @@ index 6eed627b502..1824669e881 100644
NOTE:
You can apply this patch by copying it to your clipboard and running `pbpaste | git apply`.
-You'll might want to restart the GitLab Rails server after making this change:
+You may want to restart the GitLab Rails server after making this change:
```shell
gdk restart rails-web
diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md
index a9a1026f1a8..16aba023fab 100644
--- a/doc/development/integrations/jenkins.md
+++ b/doc/development/integrations/jenkins.md
@@ -21,7 +21,7 @@ brew services start jenkins
GitLab does not allow requests to localhost or the local network by default. When running Jenkins on your local machine, you need to enable local access.
-1. Log into your GitLab instance as an admin.
+1. Log into your GitLab instance as an administrator.
1. Go to **Admin Area > Settings > Network**.
1. Expand **Outbound requests** and check the following checkboxes:
@@ -32,7 +32,7 @@ GitLab does not allow requests to localhost or the local network by default. Whe
Jenkins uses the GitLab API and needs an access token.
-1. Log in to your GitLab instance.
+1. Sign in to your GitLab instance.
1. Click on your profile picture, then click **Settings**.
1. Click **Access Tokens**.
1. Create a new Access Token with the **API** scope enabled. Note the value of the token.
diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md
index 48beb526774..bfe523ee390 100644
--- a/doc/development/integrations/jira_connect.md
+++ b/doc/development/integrations/jira_connect.md
@@ -19,10 +19,12 @@ The following are required to install and test the app:
- [GDK with Gitpod](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/gitpod.md)
documentation.
- You **must not** use tunneling tools such as Serveo or `ngrok`. These are
+ You **must not** use tunneling tools such as
+ <!-- vale gitlab.Spelling = NO --> Serveo <!-- vale gitlab.Spelling = YES -->
+ or `ngrok`. These are
security risks, and must not be run on developer laptops.
- Jira requires all connections to the app host to be over SSL, so if you set up
+ Jira requires all connections to the app host to be over SSL. If you set up
your own environment, remember to enable SSL and an appropriate certificate.
## Install the app in Jira
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index fb9d894d203..1d5aced5869 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -260,6 +260,8 @@ When executing command lines, scanners should use the `debug` level to log the c
For instance, the [bundler-audit](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit) scanner
uses the `debug` level to log the command line `bundle audit check --quiet`,
and what `bundle audit` writes to the standard output.
+If the command line fails, then it should be logged with the `error` log level;
+this makes it possible to debug the problem without having to change the log level to `debug` and rerun the scanning job.
#### common logutil package
diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md
index 80f632639ca..364e18ad015 100644
--- a/doc/development/integrations/secure_partner_integration.md
+++ b/doc/development/integrations/secure_partner_integration.md
@@ -19,7 +19,7 @@ integration as well as linking to more detailed resources for how to do so.
## Integration Tiers
-The security offerings in GitLab are designed for GitLab Gold and GitLab Ultimate users, and the
+The security offerings in GitLab are designed for GitLab Ultimate users, and the
[DevSecOps](https://about.gitlab.com/handbook/use-cases/#4-devsecops-shift-left-security)
use case. All the features are in those tiers. This includes the APIs and standard reporting
framework needed to provide a consistent experience for users to easily bring their preferred
@@ -75,7 +75,7 @@ and complete an integration with the Secure stage.
1. [Create an issue](https://gitlab.com/gitlab-com/alliances/alliances/-/issues/new?issuable_template=new_partner)
using our new partner issue template to begin the discussion.
1. Get a test account to begin developing your integration. You can
- request a [GitLab.com Gold Subscription Sandbox](https://about.gitlab.com/partners/integrate/#gitlabcom-gold-subscription-sandbox-request)
+ request a [GitLab.com Subscription Sandbox](https://about.gitlab.com/partners/integrate/#gitlabcom-subscription-sandbox-request)
or an [EE Developer License](https://about.gitlab.com/partners/integrate/#requesting-ee-dev-license-for-rd).
1. Provide a [pipeline job](../../development/pipelines.md)
template that users could integrate into their own GitLab pipelines.
@@ -114,7 +114,7 @@ and complete an integration with the Secure stage.
doing an [Unfiltered blog post](https://about.gitlab.com/handbook/marketing/blog/unfiltered/),
doing a co-branded webinar, or producing a co-branded white paper.
-We have a [video playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KpMqYxJiOLz-uBIr5w-yP4A)
+We have a <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [video playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KpMqYxJiOLz-uBIr5w-yP4A)
that may be helpful as part of this process. This covers various topics related to integrating your
tool.
diff --git a/doc/development/interacting_components.md b/doc/development/interacting_components.md
index 50751dcc539..4c2d0580428 100644
--- a/doc/development/interacting_components.md
+++ b/doc/development/interacting_components.md
@@ -29,5 +29,5 @@ See also [File Storage in GitLab](file_storage.md).
### Forks
GitLab supports a great amount of features for [merge requests](../user/project/merge_requests/index.md). One
-of them is the ability to create merge requests from and to [forks](../gitlab-basics/fork-project.md),
+of them is the ability to create merge requests from and to [forks](../user/project/working_with_projects.md#fork-a-project),
which should also be highly considered and tested upon development phase.
diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md
index 43655c37048..dce0877b1b7 100644
--- a/doc/development/internal_api.md
+++ b/doc/development/internal_api.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
-# Internal API
+# Internal API **(FREE)**
The internal API is used by different GitLab components, it can not be
used by other consumers. This documentation is intended for people
@@ -26,7 +26,7 @@ file, and include the token Base64 encoded in a `secret_token` parameter
or in the `Gitlab-Shared-Secret` header.
NOTE:
-The internal API used by GitLab Pages, and GitLab Kubernetes Agent Server (kas) uses JSON Web Token (JWT)
+The internal API used by GitLab Pages, and GitLab Kubernetes Agent Server (`kas`) uses JSON Web Token (JWT)
authentication, which is different from GitLab Shell.
## Git Authentication
@@ -51,7 +51,7 @@ POST /internal/allowed
| `key_id` | string | no | ID of the SSH-key used to connect to GitLab Shell |
| `username` | string | no | Username from the certificate used to connect to GitLab Shell |
| `project` | string | no (if `gl_repository` is passed) | Path to the project |
-| `gl_repository` | string | no (if `project` is passed) | Repository identifier (e.g. `project-7`) |
+| `gl_repository` | string | no (if `project` is passed) | Repository identifier, such as `project-7` |
| `protocol` | string | yes | SSH when called from GitLab Shell, HTTP or SSH when called from Gitaly |
| `action` | string | yes | Git command being run (`git-upload-pack`, `git-receive-pack`, `git-upload-archive`) |
| `changes` | string | yes | `<oldrev> <newrev> <refname>` when called from Gitaly, the magic string `_any` when called from GitLab Shell |
@@ -378,7 +378,7 @@ Example response:
> - This feature is not deployed on GitLab.com
> - It's not recommended for production use.
-The following endpoints are used by the GitLab Kubernetes Agent Server (kas)
+The following endpoints are used by the GitLab Kubernetes Agent Server (`kas`)
for various purposes.
These endpoints are all authenticated using JWT. The JWT secret is stored in a file
@@ -390,9 +390,9 @@ The Kubernetes agent is under development and is not recommended for production
### Kubernetes agent information
-Called from GitLab Kubernetes Agent Server (kas) to retrieve agent
+Called from GitLab Kubernetes Agent Server (`kas`) to retrieve agent
information for the given agent token. This returns the Gitaly connection
-information for the agent's project in order for kas to fetch and update
+information for the agent's project in order for `kas` to fetch and update
the agent's configuration.
```plaintext
@@ -407,13 +407,13 @@ curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Auth
### Kubernetes agent project information
-Called from GitLab Kubernetes Agent Server (kas) to retrieve project
+Called from GitLab Kubernetes Agent Server (`kas`) to retrieve project
information for the given agent token. This returns the Gitaly
-connection for the requested project. GitLab kas uses this to configure
+connection for the requested project. GitLab `kas` uses this to configure
the agent to fetch Kubernetes resources from the project repository to
sync.
-Only public projects are currently supported. For private projects, the ability for the
+Only public projects are supported. For private projects, the ability for the
agent to be authorized is [not yet implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
| Attribute | Type | Required | Description |
@@ -432,7 +432,7 @@ curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Auth
### Kubernetes agent usage metrics
-Called from GitLab Kubernetes Agent Server (kas) to increase the usage
+Called from GitLab Kubernetes Agent Server (`kas`) to increase the usage
metric counters.
| Attribute | Type | Required | Description |
@@ -456,7 +456,7 @@ Cluster.
| Attribute | Type | Required | Description |
|:----------|:-------|:---------|:------------|
-| `alert` | Hash | yes | Alerts detail. Currently same format as [3rd party alert](../operations/incident_management/alert_integrations.md#customize-the-alert-payload-outside-of-gitlab). |
+| `alert` | Hash | yes | Alerts detail. Same format as [3rd party alert](../operations/incident_management/integrations.md#customize-the-alert-payload-outside-of-gitlab). |
```plaintext
POST internal/kubernetes/modules/cilium_alert
@@ -467,3 +467,153 @@ Example Request:
```shell
curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
```
+
+## Subscriptions
+
+The subscriptions endpoint is used by `[customers.gitlab.com](https://gitlab.com/gitlab-org/customers-gitlab-com)` (CustomersDot)
+in order to apply subscriptions including trials, and add-on purchases, for personal namespaces or top-level groups within GitLab.com.
+
+### Creating a subscription
+
+Use a POST to create a subscription.
+
+```plaintext
+POST /namespaces/:id/gitlab_subscription
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:--------|:---------|:------------|
+| `start_date` | date | yes | Start date of subscription |
+| `end_date` | date | no | End date of subscription |
+| `plan_code` | string | no | Subscription tier code |
+| `seats` | integer | no | Number of seats in subscription |
+| `max_seats_used` | integer | no | Highest number of active users in the last month |
+| `auto_renew` | boolean | no | Whether subscription will auto renew on end date |
+| `trial` | boolean | no | Whether subscription is a trial |
+| `trial_starts_on` | date | no | Start date of trial |
+| `trial_ends_on` | date | no | End date of trial |
+
+Example request:
+
+```shell
+curl --request POST --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?start_date="2020-07-15"&plan="silver"&seats=10"
+```
+
+Example response:
+
+```json
+{
+ "plan": {
+ "code":"silver",
+ "name":"Silver",
+ "trial":false,
+ "auto_renew":null,
+ "upgradable":false
+ },
+ "usage": {
+ "seats_in_subscription":10,
+ "seats_in_use":1,
+ "max_seats_used":0,
+ "seats_owed":0
+ },
+ "billing": {
+ "subscription_start_date":"2020-07-15",
+ "subscription_end_date":null,
+ "trial_ends_on":null
+ }
+}
+```
+
+### Updating a subscription
+
+Use a PUT command to update an existing subscription.
+
+```plaintext
+PUT /namespaces/:id/gitlab_subscription
+```
+
+| Attribute | Type | Required | Description |
+|:------------|:--------|:---------|:------------|
+| `start_date` | date | no | Start date of subscription |
+| `end_date` | date | no | End date of subscription |
+| `plan_code` | string | no | Subscription tier code |
+| `seats` | integer | no | Number of seats in subscription |
+| `max_seats_used` | integer | no | Highest number of active users in the last month |
+| `auto_renew` | boolean | no | Whether subscription will auto renew on end date |
+| `trial` | boolean | no | Whether subscription is a trial |
+| `trial_starts_on` | date | no | Start date of trial. Required if trial is true. |
+| `trial_ends_on` | date | no | End date of trial |
+
+Example request:
+
+```shell
+curl --request PUT --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription?max_seats_used=0"
+```
+
+Example response:
+
+```json
+{
+ "plan": {
+ "code":"silver",
+ "name":"Silver",
+ "trial":false,
+ "auto_renew":null,
+ "upgradable":false
+ },
+ "usage": {
+ "seats_in_subscription":80,
+ "seats_in_use":82,
+ "max_seats_used":0,
+ "seats_owed":2
+ },
+ "billing": {
+ "subscription_start_date":"2020-07-15",
+ "subscription_end_date":"2021-07-15",
+ "trial_ends_on":null
+ }
+}
+```
+
+### Retrieving a subscription
+
+Use a GET command to view an existing subscription.
+
+```plaintext
+GET /namespaces/:id/gitlab_subscription
+```
+
+Example request:
+
+```shell
+curl --header "TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/namespaces/1234/gitlab_subscription"
+```
+
+Example response:
+
+```json
+{
+ "plan": {
+ "code":"silver",
+ "name":"Silver",
+ "trial":false,
+ "auto_renew":null,
+ "upgradable":false
+ },
+ "usage": {
+ "seats_in_subscription":80,
+ "seats_in_use":82,
+ "max_seats_used":82,
+ "seats_owed":2
+ },
+ "billing": {
+ "subscription_start_date":"2020-07-15",
+ "subscription_end_date":"2021-07-15",
+ "trial_ends_on":null
+ }
+}
+```
+
+### Known consumers
+
+- CustomersDot
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index 43d7f32ad7f..bae55bccf7c 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -46,7 +46,7 @@ all of the arguments that `in_batches` supports. You should always use
One should proceed with extra caution, and possibly avoid iterating over a column that can contain duplicate values.
When you iterate over an attribute that is not unique, even with the applied max batch size, there is no guarantee that the resulting batches will not surpass it.
-The following snippet demonstrates this situation, whe one attempt to select `Ci::Build` entries for users with `id` between `1` and `10,s000`, database returns `1 215 178`
+The following snippet demonstrates this situation, when one attempt to select `Ci::Build` entries for users with `id` between `1` and `10,s000`, database returns `1 215 178`
matching rows
```ruby
diff --git a/doc/development/kubernetes.md b/doc/development/kubernetes.md
index a56a0bd48be..5be2080eb64 100644
--- a/doc/development/kubernetes.md
+++ b/doc/development/kubernetes.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
---
-# Kubernetes integration - development guidelines
+# Kubernetes integration - development guidelines **(FREE)**
This document provides various guidelines when developing for the GitLab
[Kubernetes integration](../user/project/clusters/index.md).
diff --git a/doc/development/lfs.md b/doc/development/lfs.md
index 9df1f659654..9b78c8869b1 100644
--- a/doc/development/lfs.md
+++ b/doc/development/lfs.md
@@ -4,18 +4,18 @@ 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
---
-# Git LFS
+# Git LFS **(FREE)**
## Deep Dive
In April 2019, Francisco Javier López hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
-on the GitLab [Git LFS](../topics/git/lfs/index.md) implementation to share his domain
-specific knowledge with anyone who may work in this part of the codebase in the future.
-You can find the [recording on YouTube](https://www.youtube.com/watch?v=Yyxwcksr0Qc),
+on the GitLab [Git LFS](../topics/git/lfs/index.md) implementation to share domain-specific
+knowledge with anyone who may work in this part of the codebase in the future.
+You can find the <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=Yyxwcksr0Qc),
and the slides on [Google Slides](https://docs.google.com/presentation/d/1E-aw6-z0rYd0346YhIWE7E9A65zISL9iIMAOq2zaw9E/edit)
and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/07a89257a140db067bdfb484aecd35e1/Git_LFS_Deep_Dive__Create_.pdf).
-Everything covered in this deep dive was accurate as of GitLab 11.10, and while specific
-details may have changed since then, it should still serve as a good introduction.
+This deep dive was accurate as of GitLab 11.10, and while specific
+details may have changed, it should still serve as a good introduction.
## Including LFS blobs in project archives
@@ -52,7 +52,7 @@ JSON payload prefaced with `git-archive`. This payload includes the
archive already exists in the archive cache, Workhorse sends that
file. Otherwise, Workhorse sends the `SendArchiveRequest` to the
appropriate Gitaly server.
-1. The Gitaly server will call `git archive <ref>` to begin generating
+1. The Gitaly server calls `git archive <ref>` to begin generating
the Git archive on-the-fly. If the `include_lfs_blobs` flag is enabled,
Gitaly enables a custom LFS smudge filter via the `-c
filter.lfs.smudge=/path/to/gitaly-lfs-smudge` Git option.
@@ -76,7 +76,7 @@ process, which writes the contents to the standard output.
1. The archive data is sent back to the client.
In step 7, the `gitaly-lfs-smudge` filter must talk to Workhorse, not to
-Rails, or an invalid LFS blob will be saved. To support this, GitLab
+Rails, or an invalid LFS blob is saved. To support this, GitLab
13.5 [changed the default Omnibus configuration to have Gitaly talk to
the Workhorse](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4592)
instead of Rails.
@@ -84,6 +84,6 @@ instead of Rails.
One side effect of this change: the correlation ID of the original
request is not preserved for the internal API requests made by Gitaly
(or `gitaly-lfs-smudge`), such as the one made in step 8. The
-correlation IDs for those API requests will be random values until [this
+correlation IDs for those API requests are random values until [this
Workhorse issue](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/309) is
resolved.
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
index 3a6bdbc973f..377e31f6ab7 100644
--- a/doc/development/licensed_feature_availability.md
+++ b/doc/development/licensed_feature_availability.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Fulfillment
+group: License
info: To 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/licensing.md b/doc/development/licensing.md
index d7c2c764883..c467fe81755 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
In order to comply with the terms the libraries we use are licensed under, we have to make sure to check new gems for compatible licenses whenever they're added. To automate this process, we use the [license_finder](https://github.com/pivotal/LicenseFinder) gem by Pivotal. It runs every time a new commit is pushed and verifies that all gems and node modules in the bundle use a license that doesn't conflict with the licensing of either GitLab Community Edition or GitLab Enterprise Edition.
-There are some limitations with the automated testing, however. CSS, JavaScript, or Ruby libraries which are not included by way of Bundler, NPM, or Yarn (for instance those manually copied into our source tree in the `vendor` directory), must be verified manually and independently. Take care whenever one such library is used, as automated tests don't catch problematic licenses from them.
+There are some limitations with the automated testing, however. CSS, JavaScript, or Ruby libraries which are not included by way of Bundler, npm, or Yarn (for instance those manually copied into our source tree in the `vendor` directory), must be verified manually and independently. Take care whenever one such library is used, as automated tests don't catch problematic licenses from them.
Some gems may not include their license information in their `gemspec` file, and some node modules may not include their license information in their `package.json` file. These aren't detected by License Finder, and must be verified manually.
diff --git a/doc/development/logging.md b/doc/development/logging.md
index 07ec9d53145..30398eb87a1 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -4,7 +4,7 @@ group: Health
info: To 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 Developers Guide to Logging
+# GitLab Developers Guide to Logging **(FREE)**
[GitLab Logs](../administration/logs.md) play a critical role for both
administrators and GitLab team members to diagnose problems in the field.
@@ -291,7 +291,7 @@ method or variable shouldn't be evaluated right away)
- Change `Gitlab::ApplicationContext` to accept these new values
- Make sure the new attributes are accepted at [`Labkit::Context`](https://gitlab.com/gitlab-org/labkit-ruby/blob/master/lib/labkit/context.rb)
-See our [HOWTO: Use Sidekiq metadata logs](https://www.youtube.com/watch?v=_wDllvO_IY0) for further knowledge on
+See our <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [HOWTO: Use Sidekiq metadata logs](https://www.youtube.com/watch?v=_wDllvO_IY0) for further knowledge on
creating visualizations in Kibana.
The fields of the context are currently only logged for Sidekiq jobs triggered
@@ -299,6 +299,28 @@ through web requests. See the
[follow-up work](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/68)
for more information.
+### Logging context metadata (through workers)
+
+Additional metadata can be attached to a worker through the use of the [`ApplicationWorker#log_extra_metadata_on_done`](https://gitlab.com/gitlab-org/gitlab/-/blob/16ecc33341a3f6b6bebdf78d863c5bce76b040d3/app/workers/concerns/application_worker.rb#L31-34)
+method. Using this method adds metadata that is later logged to Kibana with the done job payload.
+
+```ruby
+class MyExampleWorker
+ include ApplicationWorker
+
+ def perform(*args)
+ # Worker performs work
+ # ...
+
+ # The contents of value will appear in Kibana under `json.extra.my_example_worker.my_key`
+ log_extra_metadata_on_done(:my_key, value)
+ end
+end
+```
+
+Please see [this example](https://gitlab.com/gitlab-org/gitlab/-/blob/16ecc33341a3f6b6bebdf78d863c5bce76b040d3/app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb#L20-21)
+which logs a count of how many artifacts are destroyed per run of the `ExpireArtifactsWorker`.
+
## Exception Handling
It often happens that you catch the exception and want to track it.
diff --git a/doc/development/maintenance_mode.md b/doc/development/maintenance_mode.md
new file mode 100644
index 00000000000..6b5a6045bb9
--- /dev/null
+++ b/doc/development/maintenance_mode.md
@@ -0,0 +1,19 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Internal workings of GitLab Maintenance Mode **(PREMIUM SELF)**
+
+## Where is Maintenance Mode enforced?
+
+GitLab Maintenance Mode **only** blocks writes from HTTP and SSH requests at the application level in a few key places within the rails application.
+[Search the codebase for `maintenance_mode?`.](https://gitlab.com/search?utf8=%E2%9C%93&search=maintenance_mode%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
+
+- [the read-only database method](https://gitlab.com/gitlab-org/gitlab/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?utf8=%E2%9C%93&search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=)
+- [the read-only middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/middleware/read_only/controller.rb), where HTTP requests that cause database writes are blocked, unless explicitly allowed.
+- [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to `/internal/allowed` to [check if access is allowed](internal_api.md#git-authentication).
+- [Container registry authentication service](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/app/services/ee/auth/container_registry_authentication_service.rb#L12), where updates to the container registry are blocked.
+
+The database itself is not in read-only mode (except in a Geo secondary site) and can be written by sources other than the ones blocked.
diff --git a/doc/development/module_with_instance_variables.md b/doc/development/module_with_instance_variables.md
index 75575105178..16c7a807053 100644
--- a/doc/development/module_with_instance_variables.md
+++ b/doc/development/module_with_instance_variables.md
@@ -121,71 +121,7 @@ module Gitlab
end
```
-Now the cop doesn't complain. Here's a bad example which we could rewrite:
-
-``` ruby
-module SpamCheckService
- def filter_spam_check_params
- @request = params.delete(:request)
- @api = params.delete(:api)
- @recaptcha_verified = params.delete(:recaptcha_verified)
- @spam_log_id = params.delete(:spam_log_id)
- end
-
- def spam_check(spammable, user)
- spam_service = SpamService.new(spammable, @request)
-
- spam_service.when_recaptcha_verified(@recaptcha_verified, @api) do
- user.spam_logs.find_by(id: @spam_log_id)&.update!(recaptcha_verified: true)
- end
- end
-end
-```
-
-There are several implicit dependencies here. First, `params` should be
-defined before use. Second, `filter_spam_check_params` should be called
-before `spam_check`. These are all implicit and the includer could be using
-those instance variables without awareness.
-
-This should be rewritten like:
-
-``` ruby
-class SpamCheckService
- def initialize(request:, api:, recaptcha_verified:, spam_log_id:)
- @request = request
- @api = api
- @recaptcha_verified = recaptcha_verified
- @spam_log_id = spam_log_id
- end
-
- def spam_check(spammable, user)
- spam_service = SpamService.new(spammable, @request)
-
- spam_service.when_recaptcha_verified(@recaptcha_verified, @api) do
- user.spam_logs.find_by(id: @spam_log_id)&.update!(recaptcha_verified: true)
- end
- end
-end
-```
-
-And use it like:
-
-``` ruby
-class UpdateSnippetService < BaseService
- def execute
- # ...
- spam = SpamCheckService.new(params.slice!(:request, :api, :recaptcha_verified, :spam_log_id))
-
- spam.check(snippet, current_user)
- # ...
- end
-end
-```
-
-This way, all those instance variables are isolated in `SpamCheckService`
-rather than whatever includes the module, and those modules which were also
-included, making it much easier to track down any issues,
-and reducing the chance of having name conflicts.
+Now the cop doesn't complain.
## How to disable this cop
diff --git a/doc/development/new_fe_guide/dependencies.md b/doc/development/new_fe_guide/dependencies.md
index 6db3b401025..b58319c15ca 100644
--- a/doc/development/new_fe_guide/dependencies.md
+++ b/doc/development/new_fe_guide/dependencies.md
@@ -1,38 +1,8 @@
---
-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: '../fe_guide/dependencies.md'
---
-# Dependencies
+This document was moved to [another location](../fe_guide/dependencies.md).
-## Adding Dependencies
-
-GitLab uses `yarn` to manage dependencies. These dependencies are defined in
-two groups within `package.json`, `dependencies` and `devDependencies`. For
-our purposes, we consider anything that is required to compile our production
-assets a "production" dependency. That is, anything required to run the
-`webpack` script with `NODE_ENV=production`. Tools like `eslint`, `karma`, and
-various plugins and tools used in development are considered `devDependencies`.
-This distinction is used by omnibus to determine which dependencies it requires
-when building GitLab.
-
-Exceptions are made for some tools that we require in the
-`gitlab:assets:compile` CI job such as `webpack-bundle-analyzer` to analyze our
-production assets post-compile.
-
-To add or upgrade a dependency, run:
-
-```shell
-yarn add <your dependency here>
-```
-
-This may introduce duplicate dependencies. To de-duplicate `yarn.lock`, run:
-
-```shell
-node_modules/.bin/yarn-deduplicate --list --strategy fewer yarn.lock && yarn install
-```
-
----
-
-> TODO: Add Dependencies
+<!-- This redirect file can be deleted after <2021-05-14>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/new_fe_guide/development/testing.md b/doc/development/new_fe_guide/development/testing.md
deleted file mode 100644
index 034324989ef..00000000000
--- a/doc/development/new_fe_guide/development/testing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../testing_guide/frontend_testing.md'
----
-
-This document was moved to [another location](../../testing_guide/frontend_testing.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/new_fe_guide/index.md b/doc/development/new_fe_guide/index.md
index a62ea53de9f..4d4098844b2 100644
--- a/doc/development/new_fe_guide/index.md
+++ b/doc/development/new_fe_guide/index.md
@@ -13,10 +13,6 @@ This is a living document, and we welcome contributions, feedback, and suggestio
Guidance on topics related to development.
-## [Dependencies](dependencies.md)
-
-Learn about all the dependencies that make up our frontend, including some of our own custom built libraries.
-
## [Modules](modules/index.md)
Learn about all the internal JavaScript modules that make up our frontend.
diff --git a/doc/development/new_fe_guide/modules/widget_extensions.md b/doc/development/new_fe_guide/modules/widget_extensions.md
index ffcd736511a..d1f6099e908 100644
--- a/doc/development/new_fe_guide/modules/widget_extensions.md
+++ b/doc/development/new_fe_guide/modules/widget_extensions.md
@@ -4,19 +4,19 @@ 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
---
-# Merge request widget extensions
+# Merge request widget extensions **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44616) in GitLab 13.6.
## Summary
-Extensions in the merge request widget allow for others team to quickly and easily add new features
-into the widget that will match the existing design and interaction as other extensions.
+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.
## Usage
-To use extensions you need to first create a new extension object that will be used to fetch the
-data that will be rendered in the extension. See the example file in
+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.
The basic object structure is as below:
@@ -36,8 +36,8 @@ export default {
};
```
-Following the same data structure allows each extension to follow the same registering structure
-but allows for each extension to manage where it gets its own data from.
+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.
diff --git a/doc/development/new_fe_guide/style/html.md b/doc/development/new_fe_guide/style/html.md
deleted file mode 100644
index afbfbdcf834..00000000000
--- a/doc/development/new_fe_guide/style/html.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../fe_guide/style/html.md'
----
-
-This document was moved to [another location](../../fe_guide/style/html.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/new_fe_guide/style/index.md b/doc/development/new_fe_guide/style/index.md
deleted file mode 100644
index 77700441aa3..00000000000
--- a/doc/development/new_fe_guide/style/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../fe_guide/style/index.md'
----
-
-This document was moved to [another location](../../fe_guide/style/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/new_fe_guide/style/javascript.md b/doc/development/new_fe_guide/style/javascript.md
deleted file mode 100644
index 17722d2c41b..00000000000
--- a/doc/development/new_fe_guide/style/javascript.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../fe_guide/style/javascript.md'
----
-
-This document was moved to [another location](../../fe_guide/style/javascript.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/new_fe_guide/style/prettier.md b/doc/development/new_fe_guide/style/prettier.md
deleted file mode 100644
index 6c0f3b77505..00000000000
--- a/doc/development/new_fe_guide/style/prettier.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../fe_guide/tooling.md#formatting-with-prettier'
----
-
-This document was moved to [another location](../../fe_guide/tooling.md#formatting-with-prettier).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/ordering_table_columns.md b/doc/development/ordering_table_columns.md
index a0a38acd816..00ce15fcc10 100644
--- a/doc/development/ordering_table_columns.md
+++ b/doc/development/ordering_table_columns.md
@@ -63,17 +63,17 @@ bits platform and 8 bytes for a 64 bits platform.
| Type | Size | Alignment needed |
|:-----------------|:-------------------------------------|:-----------|
-| smallint | 2 bytes | 1 word |
-| integer | 4 bytes | 1 word |
-| bigint | 8 bytes | 8 bytes |
-| real | 4 bytes | 1 word |
-| double precision | 8 bytes | 8 bytes |
-| boolean | 1 byte | not needed |
-| text / string | variable, 1 byte plus the data | 1 word |
-| bytea | variable, 1 or 4 bytes plus the data | 1 word |
-| timestamp | 8 bytes | 8 bytes |
-| timestamptz | 8 bytes | 8 bytes |
-| date | 4 bytes | 1 word |
+| `smallint` | 2 bytes | 1 word |
+| `integer` | 4 bytes | 1 word |
+| `bigint` | 8 bytes | 8 bytes |
+| `real` | 4 bytes | 1 word |
+| `double precision` | 8 bytes | 8 bytes |
+| `boolean` | 1 byte | not needed |
+| `text` / `string` | variable, 1 byte plus the data | 1 word |
+| `bytea` | variable, 1 or 4 bytes plus the data | 1 word |
+| `timestamp` | 8 bytes | 8 bytes |
+| `timestamptz` | 8 bytes | 8 bytes |
+| `date` | 4 bytes | 1 word |
A "variable" size means the actual size depends on the value being stored. If
PostgreSQL determines this can be embedded directly into a row it may do so, but
diff --git a/doc/development/packages.md b/doc/development/packages.md
index aadd71c9ffa..2476c876b77 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -15,7 +15,7 @@ package system support with solely backend changes. This guide is superficial an
not cover the way the code should be written. However, you can find a good example
by looking at the following merge requests:
-- [NPM registry support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8673).
+- [npm registry support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8673).
- [Maven repository](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6607).
- [Composer repository for PHP dependencies](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22415).
- [Terraform modules registry](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834).
@@ -33,7 +33,7 @@ The existing database model requires the following:
### API endpoints
Package systems work with GitLab via API. For example `lib/api/npm_packages.rb`
-implements API endpoints to work with NPM clients. So, the first thing to do is to
+implements API endpoints to work with npm clients. So, the first thing to do is to
add a new `lib/api/your_name_packages.rb` file with API endpoints that are
necessary to make the package system client to work. Usually that means having
endpoints like:
@@ -69,15 +69,15 @@ The current state of existing package registries availability is:
|------------------|---------------|-------------|----------------|
| Maven | Yes | Yes | Yes |
| Conan | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) | Yes |
-| NPM | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) |
-| NuGet | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36423) | No |
+| npm | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) |
+| NuGet | Yes | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36425) |
| PyPI | Yes | No | No |
| Go | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/213900) | No - [open-issue](https://gitlab.com/gitlab-org/gitlab/-/issues/213902) |
| Composer | Yes | Yes | No |
| Generic | Yes | No | No |
NOTE:
-NPM is currently a hybrid of the instance level and group level.
+npm is currently a hybrid of the instance level and group level.
It is using the top-level group or namespace as the defining portion of the name
(for example, `@my-group-name/my-package-name`).
@@ -124,7 +124,7 @@ The way new package systems are integrated in GitLab is using an [MVC](https://a
Required actions are all the additional requests that GitLab needs to handle so the corresponding package manager CLI can work properly. It could be a search feature or an endpoint providing meta information about a package. For example:
- For NuGet, the search request was implemented during the first MVC iteration, to support Visual Studio.
-- For NPM, there is a metadata endpoint used by `npm` to get the tarball URL.
+- For npm, there is a metadata endpoint used by `npm` to get the tarball URL.
For the first MVC iteration, it's recommended to stay at the project level of the [remote hierarchy](#remote-hierarchy). Other levels can be tackled with [future Merge Requests](#future-work).
@@ -191,7 +191,7 @@ support is done by overriding a specific function in the API helpers, like
For this authentication mechanism, keep in mind that some clients can send an unauthenticated
request first, wait for the 401 Unauthorized response with the [`WWW-Authenticate`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate)
field, then send an updated (authenticated) request. This case is more involved as
-GitLab needs to handle the 401 Unauthorized response. The [Nuget API](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/nuget_packages.rb)
+GitLab needs to handle the 401 Unauthorized response. The [NuGet API](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/nuget_packages.rb)
supports this case.
#### Authorization
@@ -245,8 +245,8 @@ in your local development environment.
#### Rate Limits on GitLab.com
Package manager clients can make rapid requests that exceed the
-[GitLab.com standard API rate limits](../user/gitlab_com/index.md#gitlabcom-specific-rate-limits).
-This results in a `429 Too Many Requests` error.
+[GitLab.com standard API rate limits](../user/gitlab_com/index.md#gitlabcom-specific-rate-limits).
+This results in a `429 Too Many Requests` error.
We have opened a set of paths to allow higher rate limits. Unless it is not possible,
new package managers should follow these conventions so they can take advantage of the
diff --git a/doc/development/performance.md b/doc/development/performance.md
index f3ce924de38..3b4525dc8ee 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -50,7 +50,7 @@ GitLab provides built-in tools to help improve performance and availability:
- [Service measurement](service_measurement.md) for measuring and logging service execution.
GitLab team members can use [GitLab.com's performance monitoring systems](https://about.gitlab.com/handbook/engineering/monitoring/) located at
-<https://dashboards.gitlab.net>, this requires you to log in using your
+[`dashboards.gitlab.net`](https://dashboards.gitlab.net), this requires you to log in using your
`@gitlab.com` email address. Non-GitLab team-members are advised to set up their
own Prometheus and Grafana stack.
@@ -176,7 +176,7 @@ stackprof tmp/project_policy_spec.rb.dump --graphviz > project_policy_spec.dot
dot -Tsvg project_policy_spec.dot > project_policy_spec.svg
```
-To load the profile in [kcachegrind](https://kcachegrind.github.io/):
+To load the profile in [KCachegrind](https://kcachegrind.github.io/):
```shell
stackprof tmp/project_policy_spec.rb.dump --callgrind > project_policy_spec.callgrind
@@ -184,7 +184,7 @@ kcachegrind project_policy_spec.callgrind # Linux
qcachegrind project_policy_spec.callgrind # Mac
```
-For flamegraphs, enable raw collection first. Note that raw
+For flame graphs, enable raw collection first. Note that raw
collection can generate a very large file, so increase the `INTERVAL`, or
run on a smaller number of specs for smaller file size:
@@ -192,7 +192,7 @@ run on a smaller number of specs for smaller file size:
RAW=true bin/rspec-stackprof spec/policies/group_member_policy_spec.rb
```
-You can then generate, and view the resultant flamegraph. It might take a
+You can then generate, and view the resultant flame graph. It might take a
while to generate based on the output file size:
```shell
@@ -251,7 +251,7 @@ In order to enable production profiling for Ruby processes, you can set the `STA
The following configuration options can be configured:
-- `STACKPROF_ENABLED`: Enables stackprof signal handler on SIGUSR2 signal.
+- `STACKPROF_ENABLED`: Enables Stackprof signal handler on SIGUSR2 signal.
Defaults to `false`.
- `STACKPROF_MODE`: See [sampling modes](https://github.com/tmm1/stackprof#sampling).
Defaults to `cpu`.
@@ -264,7 +264,7 @@ The following configuration options can be configured:
- `STACKPROF_TIMEOUT_S`: Profiling timeout in seconds. Profiling will
automatically stop after this time has elapsed. Defaults to `30`.
- `STACKPROF_RAW`: Whether to collect raw samples or only aggregates. Raw
- samples are needed to generate flamegraphs, but they do have a higher memory
+ samples are needed to generate flame graphs, but they do have a higher memory
and disk overhead. Defaults to `true`.
Once enabled, profiling can be triggered by sending a `SIGUSR2` signal to the
@@ -287,7 +287,7 @@ The Puma master process is not supported. Neither is Unicorn.
Sending SIGUSR2 to either of those triggers restarts. In the case of Puma,
take care to only send the signal to Puma workers.
-This can be done via `pkill -USR2 puma:`. The `:` disambiguates between `puma
+This can be done via `pkill -USR2 puma:`. The `:` distinguishes between `puma
4.3.3.gitlab.2 ...` (the master process) from `puma: cluster worker 0: ...` (the
worker processes), selecting the latter.
@@ -296,7 +296,7 @@ For Sidekiq, the signal can be sent to the `sidekiq-cluster` process via `pkill
children. Alternatively, you can also select a specific pid of interest.
Production profiles can be especially noisy. It can be helpful to visualize them
-as a [flamegraph](https://github.com/brendangregg/FlameGraph). This can be done
+as a [flame graph](https://github.com/brendangregg/FlameGraph). This can be done
via:
```shell
@@ -543,6 +543,88 @@ test += " world"
When adding new Ruby files, please check that you can add the above header,
as omitting it may lead to style check failures.
+## Banzai pipelines and filters
+
+When writing or updating [Banzai filters and pipelines](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/banzai),
+it can be difficult to understand what the performance of the filter is, and what effect it might
+have on the overall pipeline performance.
+
+To perform benchmarks run:
+
+```shell
+bin/rake benchmark:banzai
+```
+
+This command generates output like this:
+
+```plaintext
+--> Benchmarking Full, Wiki, and Plain pipelines
+Calculating -------------------------------------
+ Full pipeline 1.000 i/100ms
+ Wiki pipeline 1.000 i/100ms
+ Plain pipeline 1.000 i/100ms
+-------------------------------------------------
+ Full pipeline 3.357 (±29.8%) i/s - 31.000
+ Wiki pipeline 2.893 (±34.6%) i/s - 25.000 in 10.677014s
+ Plain pipeline 15.447 (±32.4%) i/s - 119.000
+
+Comparison:
+ Plain pipeline: 15.4 i/s
+ Full pipeline: 3.4 i/s - 4.60x slower
+ Wiki pipeline: 2.9 i/s - 5.34x slower
+
+.
+--> Benchmarking FullPipeline filters
+Calculating -------------------------------------
+ Markdown 24.000 i/100ms
+ Plantuml 8.000 i/100ms
+ SpacedLink 22.000 i/100ms
+
+...
+
+ TaskList 49.000 i/100ms
+ InlineDiff 9.000 i/100ms
+ SetDirection 369.000 i/100ms
+-------------------------------------------------
+ Markdown 237.796 (±16.4%) i/s - 2.304k
+ Plantuml 80.415 (±36.1%) i/s - 520.000
+ SpacedLink 168.188 (±10.1%) i/s - 1.672k
+
+...
+
+ TaskList 101.145 (± 6.9%) i/s - 1.029k
+ InlineDiff 52.925 (±15.1%) i/s - 522.000
+ SetDirection 3.728k (±17.2%) i/s - 34.317k in 10.617882s
+
+Comparison:
+ Suggestion: 739616.9 i/s
+ Kroki: 306449.0 i/s - 2.41x slower
+InlineGrafanaMetrics: 156535.6 i/s - 4.72x slower
+ SetDirection: 3728.3 i/s - 198.38x slower
+
+...
+
+ UserReference: 2.1 i/s - 360365.80x slower
+ ExternalLink: 1.6 i/s - 470400.67x slower
+ ProjectReference: 0.7 i/s - 1128756.09x slower
+
+.
+--> Benchmarking PlainMarkdownPipeline filters
+Calculating -------------------------------------
+ Markdown 19.000 i/100ms
+-------------------------------------------------
+ Markdown 241.476 (±15.3%) i/s - 2.356k
+
+```
+
+This can give you an idea how various filters perform, and which ones might be performing the slowest.
+
+The test data has a lot to do with how well a filter performs. If there is nothing in the test data
+that specifically triggers the filter, it might look like it's running incredibly fast.
+Make sure that you have relevant test data for your filter in the
+[`spec/fixtures/markdown.md.erb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/fixtures/markdown.md.erb)
+file.
+
## Reading from files and other data sources
Ruby offers several convenience functions that deal with file contents specifically
@@ -665,5 +747,4 @@ Assuming you are working with ActiveRecord models, you might also find these lin
### Examples
-You may find some useful examples in this snippet:
-<https://gitlab.com/gitlab-org/gitlab-foss/snippets/33946>
+You may find some useful examples in [this snippet](https://gitlab.com/gitlab-org/gitlab-foss/snippets/33946).
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 0354e703357..4d931899da6 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -1,12 +1,12 @@
---
stage: none
-group: unassigned
+group: Engineering Productivity
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Pipelines for the GitLab project
-Pipelines for <https://gitlab.com/gitlab-org/gitlab> and <https://gitlab.com/gitlab-org/gitlab-foss> (as well as the
+Pipelines for [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) and [`gitlab-org/gitlab-foss`](https://gitlab.com/gitlab-org/gitlab-foss) (as well as the
`dev` instance's mirrors) are configured in the usual
[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml)
which itself includes files under
@@ -37,14 +37,14 @@ Pipeline creation is also affected by the following CI variables:
No pipeline is created in any other cases (for example, when pushing a branch with no
MR for it).
-The source of truth for these workflow rules is defined in <https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml>.
+The source of truth for these workflow rules is defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
### Pipelines for Merge Requests
In general, pipelines for an MR fall into one or more of the following types,
depending on the changes made in the MR:
-- [Docs-only MR pipeline](#docs-only-mr-pipeline): This is typically created for an MR that only changes documentation.
+- [Documentation only MR pipeline](#documentation-only-mr-pipeline): This is typically created for an MR that only changes documentation.
- [Code-only MR pipeline](#code-only-mr-pipeline): This is typically created for an MR that only changes code, either backend or frontend.
- [Frontend-only MR pipeline](#frontend-only-mr-pipeline): This is typically created for an MR that only changes frontend code.
- [QA-only MR pipeline](#qa-only-mr-pipeline): This is typically created for an MR that only changes end to end tests related code.
@@ -53,23 +53,27 @@ We use the [`rules:`](../ci/yaml/README.md#rules) and [`needs:`](../ci/yaml/READ
to determine the jobs that need to be run in a pipeline. Note that an MR that includes multiple types of changes would
have a pipelines that include jobs from multiple types (e.g. a combination of docs-only and code-only pipelines).
-#### Docs-only MR pipeline
+#### Documentation only MR pipeline
-Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/135236627>
+[Reference pipeline](https://gitlab.com/gitlab-org/gitlab/-/pipelines/250546928):
```mermaid
graph LR
subgraph "No needed jobs";
1-1["danger-review (2.3 minutes)"];
click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0"
- 1-50["docs lint (9 minutes)"];
- click 1-50 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356757&udv=0"
- end
+ 1-2["docs-lint markdown (1.5 minutes)"];
+ click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=10224335&udv=0"
+ 1-3["docs-lint links (6 minutes)"];
+ click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356757&udv=0"
+ 1-4["ui-docs-links lint (2.5 minutes)"];
+ click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=10823717&udv=1020379"
+ end
```
#### Code-only MR pipeline
-Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/136295694>
+[Reference pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/136295694)
```mermaid
graph RL;
@@ -107,7 +111,7 @@ graph RL;
class 1-6 criticalPath;
end
- 2_1-1["graphql-reference-verify (5 minutes)"];
+ 2_1-1["graphql-verify (4 minutes)"];
click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0"
2_1-2["memory-static (4.75 minutes)"];
click 2_1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356721&udv=0"
@@ -173,7 +177,7 @@ graph RL;
#### Frontend-only MR pipeline
-Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/134661039>
+[Reference pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/134661039):
```mermaid
graph RL;
@@ -212,7 +216,7 @@ graph RL;
class 1-6 criticalPath;
end
- 2_1-1["graphql-reference-verify (5 minutes)"];
+ 2_1-1["graphql-verify (4 minutes)"];
click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0"
2_1-2["memory-static (4.75 minutes)"];
click 2_1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356721&udv=0"
@@ -304,7 +308,7 @@ graph RL;
#### QA-only MR pipeline
-Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/134645109>
+[Reference pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/134645109):
```mermaid
graph RL;
@@ -341,7 +345,7 @@ graph RL;
class 1-5 criticalPath;
end
- 2_1-1["graphql-reference-verify (5 minutes)"];
+ 2_1-1["graphql-verify (4 minutes)"];
click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0"
subgraph "Needs `setup-test-env`";
2_1-1 --> 1-6;
@@ -493,6 +497,7 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
1. We currently have several different caches defined in
[`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml),
with fixed keys:
+ - `.setup-test-env-cache`.
- `.rails-cache`.
- `.static-analysis-cache`.
- `.coverage-cache`
@@ -500,6 +505,7 @@ request, be sure to start the `dont-interrupt-me` job before pushing.
- `.yarn-cache`.
- `.assets-compile-cache` (the key includes `${NODE_ENV}` so it's actually two different caches).
1. Only 6 specific jobs, running in 2-hourly scheduled pipelines, are pushing (i.e. updating) to the caches:
+ - `update-setup-test-env-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-rails-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-static-analysis-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
- `update-coverage-cache`, defined in [`.gitlab/ci/rails.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/rails.gitlab-ci.yml).
@@ -584,8 +590,8 @@ runner, or [you can incur network egress charges](https://cloud.google.com/stora
The current stages are:
-- `sync`: This stage is used to synchronize changes from <https://gitlab.com/gitlab-org/gitlab> to
- <https://gitlab.com/gitlab-org/gitlab-foss>.
+- `sync`: This stage is used to synchronize changes from [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) to
+ [`gitlab-org/gitlab-foss`](https://gitlab.com/gitlab-org/gitlab-foss).
- `prepare`: This stage includes jobs that prepare artifacts that are needed by
jobs in subsequent stages.
- `build-images`: This stage includes jobs that prepare Docker images
@@ -614,7 +620,9 @@ that is deployed in stage `review`.
The default image is defined in [`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
+<!-- vale gitlab.Spelling = NO -->
It includes Ruby, Go, Git, Git LFS, Chrome, Node, Yarn, PostgreSQL, and Graphics Magick.
+<!-- vale gitlab.Spelling = YES -->
The images used in our pipelines are configured in the
[`gitlab-org/gitlab-build-images`](https://gitlab.com/gitlab-org/gitlab-build-images)
@@ -624,11 +632,30 @@ for redundancy.
The current version of the build images can be found in the
["Used by GitLab section"](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/.gitlab-ci.yml).
+### Dependency Proxy
+
+Some of the jobs are using images from Docker Hub, where we also use
+`${GITLAB_DEPENDENCY_PROXY}` as a prefix to the image path, so that we pull
+images from our [Dependency Proxy](../user/packages/dependency_proxy/index.md).
+
+`${GITLAB_DEPENDENCY_PROXY}` is a group variable defined in
+[`gitlab-org`](https://gitlab.com/gitlab-org) as
+`${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/`. This means when we use an image
+defined as:
+
+```yaml
+image: ${GITLAB_DEPENDENCY_PROXY}alpine:edge
+```
+
+Projects in the `gitlab-org` group pull from the Dependency Proxy, while
+forks that reside on any other personal namespaces or groups fall back to
+Docker Hub unless `${GITLAB_DEPENDENCY_PROXY}` is also defined there.
+
### Default variables
In addition to the [predefined variables](../ci/variables/predefined_variables.md),
each pipeline includes default variables defined in
-<https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml>.
+[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml).
### Common job definitions
@@ -640,6 +667,7 @@ that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-key
|------------------|-------------|
| `.default-retry` | Allows a job to [retry](../ci/yaml/README.md#retry) upon `unknown_failure`, `api_failure`, `runner_system_failure`, `job_execution_timeout`, or `stuck_or_timeout_failure`. |
| `.default-before_script` | Allows a job to use a default `before_script` definition suitable for Ruby/Rails tasks that may need a database running (e.g. tests). |
+| `.setup-test-env-cache` | Allows a job to use a default `cache` definition suitable for setting up test environment for subsequent Ruby/Rails tasks. |
| `.rails-cache` | Allows a job to use a default `cache` definition suitable for Ruby/Rails tasks. |
| `.static-analysis-cache` | Allows a job to use a default `cache` definition suitable for static analysis tasks. |
| `.coverage-cache` | Allows a job to use a default `cache` definition suitable for coverage tasks. |
@@ -659,7 +687,7 @@ that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-key
We're using the [`rules` keyword](../ci/yaml/README.md#rules) extensively.
All `rules` definitions are defined in
-<https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rules.gitlab-ci.yml>,
+[`rules.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/rules.gitlab-ci.yml),
then included in individual jobs via [`extends`](../ci/yaml/README.md#extends).
The `rules` definitions are composed of `if:` conditions and `changes:` patterns,
diff --git a/doc/development/polling.md b/doc/development/polling.md
index 18f9fb954dd..f854891a528 100644
--- a/doc/development/polling.md
+++ b/doc/development/polling.md
@@ -60,6 +60,6 @@ route matching easier.
For more information see:
-- [`Poll-Interval` header](fe_guide/performance.md#realtime-components)
+- [`Poll-Interval` header](fe_guide/performance.md#real-time-components)
- [RFC 7232](https://tools.ietf.org/html/rfc7232)
- [ETag proposal](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26926)
diff --git a/doc/development/product_analytics/index.md b/doc/development/product_analytics/index.md
index 4d2168cf304..e8b8e0c4885 100644
--- a/doc/development/product_analytics/index.md
+++ b/doc/development/product_analytics/index.md
@@ -4,10 +4,5 @@ redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-gui
This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-<!-- Needed by the Product Intelligence group
-
-Since our new standard for redirects otherwise lies within the gitlab-docs repo,
-as long as we need a redirect to the handbook, we need to retain this file.
- -->
<!-- This redirect file can be deleted after December 1, 2021. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/product_analytics/snowplow.md b/doc/development/product_analytics/snowplow.md
index bb056ffddfe..ff91e450e1e 100644
--- a/doc/development/product_analytics/snowplow.md
+++ b/doc/development/product_analytics/snowplow.md
@@ -4,5 +4,5 @@ redirect_to: '../snowplow.md'
This document was moved to [another location](../snowplow.md).
-<!-- This redirect file can be deleted after February 1, 2021. -->
+<!-- This redirect file can be deleted after April 1, 2021. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md
index 5fbdb508bb1..79075157ce4 100644
--- a/doc/development/product_analytics/usage_ping.md
+++ b/doc/development/product_analytics/usage_ping.md
@@ -4,5 +4,5 @@ redirect_to: '../usage_ping.md'
This document was moved to [another location](../usage_ping.md).
-<!-- This redirect file can be deleted after February 1, 2021. -->
+<!-- This redirect file can be deleted after April 1, 2021. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index ce9c1191648..5c5ad5f9c39 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -106,6 +106,8 @@ environment variable `ENABLE_SHERLOCK` to a non empty value. For example:
ENABLE_SHERLOCK=1 bundle exec rails s
```
+Sherlock is also [available though the GitLab GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/sherlock.md).
+
Recorded transactions can be found by navigating to `/sherlock/transactions`.
## Bullet
@@ -227,5 +229,5 @@ The following table lists these variables along with their default values.
GitLab may decide to change these settings in order to speed up application performance, lower memory requirements, or both.
You can see how each of these settings affect GC performance, memory use and application start-up time for an idle instance of
-GitLab by runnning the `scripts/perf/gc/collect_gc_stats.rb` script. It will output GC stats and general timing data to standard
+GitLab by running the `scripts/perf/gc/collect_gc_stats.rb` script. It will output GC stats and general timing data to standard
out as CSV.
diff --git a/doc/development/projections.md b/doc/development/projections.md
index e62f13981c9..c112ec6f119 100644
--- a/doc/development/projections.md
+++ b/doc/development/projections.md
@@ -27,7 +27,7 @@ You can find a basic list of projection options in
- VSCode
- [Alternate File](https://marketplace.visualstudio.com/items?itemName=will-wow.vscode-alternate-file)
- [projectionist](https://github.com/jarsen/projectionist)
- - [jumpto](https://github.com/gmdayley/jumpto)
+ - [`jumpto`](https://github.com/gmdayley/jumpto)
- Atom
- [projectionist-atom](https://atom.io/packages/projectionist-atom)
- Command-line
@@ -35,6 +35,8 @@ You can find a basic list of projection options in
## History
+<!-- vale gitlab.Spelling = NO -->
This started as a
[plugin for vim by tpope](https://github.com/tpope/vim-projectionist)
It has since become editor-agnostic and ported to most modern editors.
+<!-- vale gitlab.Spelling = YES --> \ No newline at end of file
diff --git a/doc/development/prometheus_metrics.md b/doc/development/prometheus_metrics.md
index df13cb7d56c..05a623448bf 100644
--- a/doc/development/prometheus_metrics.md
+++ b/doc/development/prometheus_metrics.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Working with Prometheus Metrics
+# Working with Prometheus Metrics **(FREE)**
## Adding to the library
@@ -75,5 +75,10 @@ This section describes how to add new metrics for self-monitoring
1. Select the appropriate name for your metric. Refer to the guidelines
for [Prometheus metric names](https://prometheus.io/docs/practices/naming/#metric-names).
1. Update the list of [GitLab Prometheus metrics](../administration/monitoring/prometheus/gitlab_metrics.md).
+1. Carefully choose what labels you want to add to your metric. Values with high cardinality,
+like `project_path`, or `project_id` are strongly discouraged because they can affect our services
+availability due to the fact that each set of labels is exposed as a new entry in the `/metrics` endpoint.
+For example, a histogram with 10 buckets and a label with 100 values would generate 1000
+entries in the export endpoint.
1. Trigger the relevant page or code that records the new metric.
1. Check that the new metric appears at `/-/metrics`.
diff --git a/doc/development/pry_debugging.md b/doc/development/pry_debugging.md
index f29e0d403cd..d662e6bbc54 100644
--- a/doc/development/pry_debugging.md
+++ b/doc/development/pry_debugging.md
@@ -10,7 +10,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To invoke the debugger, place `binding.pry` somewhere in your
code. When the Ruby interpreter hits that code, execution stops,
-and you can type in commands to debug the state of the program
+and you can type in commands to debug the state of the program.
+
+When debugging code in another process like Puma or Sidekiq, you can use `binding.remote_pry`.
+You can then connect to this session by running `pry-remote` from your terminal.
## `byebug` vs `binding.pry`
@@ -79,7 +82,7 @@ Similar to source browsing, is [Documentation browsing](https://github.com/pry/p
### Command history
-With **Ctrl+R** you can search your [command history](https://github.com/pry/pry/wiki/History).
+With <kbd>Control</kbd> + <kbd>R</kbd> you can search your [command history](https://github.com/pry/pry/wiki/History).
## Stepping
diff --git a/doc/development/python_guide/index.md b/doc/development/python_guide/index.md
index 3291b6c31a9..fe5492c3bd8 100644
--- a/doc/development/python_guide/index.md
+++ b/doc/development/python_guide/index.md
@@ -14,8 +14,8 @@ As of GitLab 11.10, we require Python 3.
## Installation
There are several ways of installing Python on your system. To be able to use the same version we use in production,
-we suggest you use [pyenv](https://github.com/pyenv/pyenv). It works and behaves similarly to its counterpart in the
-Ruby world: [rbenv](https://github.com/rbenv/rbenv).
+we suggest you use [`pyenv`](https://github.com/pyenv/pyenv). It works and behaves similarly to its counterpart in the
+Ruby world: [`rbenv`](https://github.com/rbenv/rbenv).
### macOS
@@ -35,11 +35,11 @@ curl "https://pyenv.run" | bash
Alternatively, you may find `pyenv` available as a system package via your distribution's package manager.
-You can read more about it in: <https://github.com/pyenv/pyenv-installer#prerequisites>.
+You can read more about it in [the `pyenv` prerequisites](https://github.com/pyenv/pyenv-installer#prerequisites).
### Shell integration
-Pyenv installation adds required changes to Bash. If you use a different shell,
+`Pyenv` installation adds required changes to Bash. If you use a different shell,
check for any additional steps required for it.
For Fish, you can install a plugin for [Fisher](https://github.com/jorgebucaran/fisher):
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index 226d21b2ecd..13bb39a4a6c 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -64,9 +64,9 @@ By default, this seeds an average of 10 issues per week for the last 52 weeks
per project. All issues are also randomly labeled with team, type, severity,
and priority.
-#### Seeding groups with sub-groups
+#### Seeding groups with subgroups
-You can seed groups with sub-groups that contain milestones/projects/issues
+You can seed groups with subgroups that contain milestones/projects/issues
with the `gitlab:seed:group_seed` task:
```shell
@@ -261,6 +261,48 @@ bundle exec rake db:obsolete_ignored_columns
Feel free to remove their definitions from their `ignored_columns` definitions.
+## Validate GraphQL queries
+
+To check the validity of one or more of our front-end GraphQL queries,
+run:
+
+```shell
+# Validate all queries
+bundle exec rake gitlab::graphql:validate
+# Validate one query
+bundle exec rake gitlab::graphql:validate[path/to/query.graphql]
+# Validate a directory
+bundle exec rake gitlab::graphql:validate[path/to/queries]
+```
+
+This prints out a report with an entry for each query, explaining why
+each query is invalid if it fails to pass validation.
+
+We strip out `@client` fields during validation so it is important to mark
+client fields with the `@client` directive to avoid false positives.
+
+## Analyze GraphQL queries
+
+Analogous to `ANALYZE` in SQL, we can run `gitlab:graphql:analyze` to
+estimate the of the cost of running a query.
+
+Usage:
+
+```shell
+# Analyze all queries
+bundle exec rake gitlab::graphql:analyze
+# Analyze one query
+bundle exec rake gitlab::graphql:analyze[path/to/query.graphql]
+# Analyze a directory
+bundle exec rake gitlab::graphql:analyze[path/to/queries]
+```
+
+This prints out a report for each query, including the complexity
+of the query if it is valid.
+
+The complexity depends on the arguments in some cases, so the reported
+complexity is a best-effort assessment of the upper bound.
+
## Update GraphQL documentation and schema definitions
To generate GraphQL documentation based on the GitLab schema, run:
diff --git a/doc/development/reactive_caching.md b/doc/development/reactive_caching.md
index 5d514ffbfc9..0223f5d91d6 100644
--- a/doc/development/reactive_caching.md
+++ b/doc/development/reactive_caching.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# `ReactiveCaching`
-> This doc refers to <https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/reactive_caching.rb>.
+> This doc refers to [`reactive_caching.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/models/concerns/reactive_caching.rb).
The `ReactiveCaching` concern is used for fetching some data in the background and storing it
in the Rails cache, keeping it up-to-date for as long as it is being requested. If the
@@ -103,7 +103,7 @@ not wait until the background worker completes.
- An API that calls a model or service method that uses `ReactiveCaching` should return
`202 accepted` when the cache is being calculated (when `#with_reactive_cache` returns `nil`).
- It should also
- [set the polling interval header](fe_guide/performance.md#realtime-components) with
+ [set the polling interval header](fe_guide/performance.md#real-time-components) with
`Gitlab::PollingInterval.set_header`.
- The consumer of the API is expected to poll the API.
- You can also consider implementing [ETag caching](polling.md) to reduce the server
diff --git a/doc/development/redis.md b/doc/development/redis.md
index bb725e3c321..9f90c5ee760 100644
--- a/doc/development/redis.md
+++ b/doc/development/redis.md
@@ -74,8 +74,10 @@ which is enabled for the `cache` and `shared_state`
## Redis in structured logging
-For GitLab Team Members: There are [basic](https://www.youtube.com/watch?v=Uhdj19Dc6vU) and
-[advanced](https://youtu.be/jw1Wv2IJxzs) videos that show how you can work with the Redis
+For GitLab Team Members: There are <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+[basic](https://www.youtube.com/watch?v=Uhdj19Dc6vU) and
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [advanced](https://youtu.be/jw1Wv2IJxzs)
+videos that show how you can work with the Redis
structured logging fields on GitLab.com.
Our [structured logging](logging.md#use-structured-json-logging) for web
@@ -183,9 +185,8 @@ The Redis [`PFCOUNT`](https://redis.io/commands/pfcount),
[`PFMERGE`](https://redis.io/commands/pfmergge) commands operate on
HyperLogLogs, a data structure that allows estimating the number of unique
elements with low memory usage. (In addition to the `PFCOUNT` documentation,
-Thoughtbot's article on [HyperLogLogs in
-Redis](https://thoughtbot.com/blog/hyperloglogs-in-redis) provides a good
-background here.)
+Thoughtbot's article on [HyperLogLogs in Redis](https://thoughtbot.com/blog/hyperloglogs-in-redis)
+provides a good background here.)
[`Gitlab::Redis::HLL`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/hll.rb)
provides a convenient interface for adding and counting values in HyperLogLogs.
diff --git a/doc/development/refactoring_guide/index.md b/doc/development/refactoring_guide/index.md
index 224b6bf9b38..a25000589c0 100644
--- a/doc/development/refactoring_guide/index.md
+++ b/doc/development/refactoring_guide/index.md
@@ -80,4 +80,4 @@ expect(cleanForSnapshot(wrapper.element)).toMatchSnapshot();
- [Pinning test in refactoring dropdown](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28173)
- [Pinning test in refactoring vulnerability_details.vue](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25830/commits)
- [Pinning test in refactoring notes_award_list.vue](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29528#pinning-test)
-- [Video of pair programming session on pinning tests](https://youtu.be/LrakPcspBK4)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Video of pair programming session on pinning tests](https://youtu.be/LrakPcspBK4)
diff --git a/doc/development/repository_mirroring.md b/doc/development/repository_mirroring.md
index 4153bcf77a5..61157c88618 100644
--- a/doc/development/repository_mirroring.md
+++ b/doc/development/repository_mirroring.md
@@ -8,10 +8,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Deep Dive
+<!-- vale gitlab.Spelling = NO -->
+
In December 2018, Tiago Botelho hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
on the GitLab [Pull Repository Mirroring functionality](../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository)
to share his domain specific knowledge with anyone who may work in this part of the
-codebase in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=sSZq0fpdY-Y),
+codebase in the future. You can find the <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=sSZq0fpdY-Y),
and the slides in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/8693404888a941fd851f8a8ecdec9675/Gitlab_Create_-_Pull_Mirroring_Deep_Dive.pdf).
Everything covered in this deep dive was accurate as of GitLab 11.6, and while specific
details may have changed since then, it should still serve as a good introduction.
+
+<!-- vale gitlab.Spelling = YES --> \ No newline at end of file
diff --git a/doc/development/rolling_out_changes_using_feature_flags.md b/doc/development/rolling_out_changes_using_feature_flags.md
deleted file mode 100644
index 7456e8df8d9..00000000000
--- a/doc/development/rolling_out_changes_using_feature_flags.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'feature_flags/index.md'
----
-
-This document was moved to [another location](feature_flags/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index bd98ea170e5..41a7defbc26 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -180,7 +180,7 @@ For other regular expressions, here are a few guidelines:
- If there's a clean non-regex solution, such as `String#start_with?`, consider using it
- Ruby supports some advanced regex features like [atomic groups](https://www.regular-expressions.info/atomic.html)
-and [possessive quantifiers](https://www.regular-expressions.info/possessive.html) that eleminate backtracking
+and [possessive quantifiers](https://www.regular-expressions.info/possessive.html) that eliminate backtracking
- 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_`
@@ -288,9 +288,9 @@ XSS issues are commonly classified in three categories, by their delivery method
The injected client-side code is executed on the victim's browser in the context of their current session. This means the attacker could perform any same action the victim would normally be able to do through a browser. The attacker would also have the ability to:
-- [log victim keystrokes](https://youtu.be/2VFavqfDS6w?t=1367)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [log victim keystrokes](https://youtu.be/2VFavqfDS6w?t=1367)
- launch a network scan from the victim's browser
-- potentially [obtain the victim's session tokens](https://youtu.be/2VFavqfDS6w?t=739)
+- potentially <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [obtain the victim's session tokens](https://youtu.be/2VFavqfDS6w?t=739)
- perform actions that lead to data loss/theft or account takeover
Much of the impact is contingent upon the function of the application and the capabilities of the victim's session. For further impact possibilities, please check out [the beef project](https://beefproject.com/).
@@ -309,14 +309,14 @@ In most situations, a two-step solution can be used: input validation and output
##### Setting expectations
-For any and all input fields, ensure to define expectations on the type/format of input, the contents, [size limits](https://youtu.be/2VFavqfDS6w?t=7582), the context in which it will be output. It's important to work with both security and product teams to determine what is considered acceptable input.
+For any and all input fields, ensure to define expectations on the type/format of input, the contents, <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [size limits](https://youtu.be/2VFavqfDS6w?t=7582), the context in which it will be output. It's important to work with both security and product teams to determine what is considered acceptable input.
##### Validate input
- Treat all user input as untrusted.
- Based on the expectations you [defined above](#setting-expectations):
- - Validate the [input size limits](https://youtu.be/2VFavqfDS6w?t=7582).
- - Validate the input using an [allowlist approach](https://youtu.be/2VFavqfDS6w?t=7816) to only allow characters through which you are expecting to receive for the field.
+ - Validate the <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [input size limits](https://youtu.be/2VFavqfDS6w?t=7582).
+ - Validate the input using an <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [allowlist approach](https://youtu.be/2VFavqfDS6w?t=7816) to only allow characters through which you are expecting to receive for the field.
- Input which fails validation should be **rejected**, and not sanitized.
- When adding redirects or links to a user-controlled URL, ensure that the scheme is HTTP or HTTPS. Allowing other schemes like `javascript://` can lead to XSS and other security issues.
@@ -328,8 +328,8 @@ Once you've [determined when and where](#setting-expectations) the user submitte
- Content placed inside HTML elements need to be [HTML entity encoded](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-1---html-escape-before-inserting-untrusted-data-into-html-element-content).
- Content placed into a JSON response needs to be [JSON encoded](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-31---html-escape-json-values-in-an-html-context-and-read-the-data-with-jsonparse).
-- Content placed inside [HTML URL GET parameters](https://youtu.be/2VFavqfDS6w?t=3494) need to be [URL-encoded](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-5---url-escape-before-inserting-untrusted-data-into-html-url-parameter-values)
-- [Additional contexts may require context-specific encoding](https://youtu.be/2VFavqfDS6w?t=2341).
+- Content placed inside <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [HTML URL GET parameters](https://youtu.be/2VFavqfDS6w?t=3494) need to be [URL-encoded](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-5---url-escape-before-inserting-untrusted-data-into-html-url-parameter-values)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Additional contexts may require context-specific encoding](https://youtu.be/2VFavqfDS6w?t=2341).
### Additional information
@@ -352,10 +352,10 @@ Do also sanitize and validate URL schemes.
References:
-- [XSS Defense in Rails](https://youtu.be/2VFavqfDS6w?t=2442)
-- [XSS Defense with HAML](https://youtu.be/2VFavqfDS6w?t=2796)
-- [Validating Untrusted URLs in Ruby](https://youtu.be/2VFavqfDS6w?t=3936)
-- [RoR Model Validators](https://youtu.be/2VFavqfDS6w?t=7636)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [XSS Defense in Rails](https://youtu.be/2VFavqfDS6w?t=2442)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [XSS Defense with HAML](https://youtu.be/2VFavqfDS6w?t=2796)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Validating Untrusted URLs in Ruby](https://youtu.be/2VFavqfDS6w?t=3936)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [RoR Model Validators](https://youtu.be/2VFavqfDS6w?t=7636)
#### XSS mitigation and prevention in JavaScript and Vue
@@ -376,7 +376,7 @@ References:
#### Content Security Policy
-- [Content Security Policy](https://www.youtube.com/watch?v=2VFavqfDS6w&t=12991s)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Content Security Policy](https://www.youtube.com/watch?v=2VFavqfDS6w&t=12991s)
- [Use nonce-based Content Security Policy for inline JavaScript](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/65330)
#### Free form input field
@@ -390,26 +390,26 @@ References:
### Internal Developer Training
-- [Introduction to XSS](https://www.youtube.com/watch?v=PXR8PTojHmc&t=7785s)
-- [Reflected XSS](https://youtu.be/2VFavqfDS6w?t=603s)
-- [Persistent XSS](https://youtu.be/2VFavqfDS6w?t=643)
-- [DOM XSS](https://youtu.be/2VFavqfDS6w?t=5871)
-- [XSS in depth](https://www.youtube.com/watch?v=2VFavqfDS6w&t=111s)
-- [XSS Defense](https://youtu.be/2VFavqfDS6w?t=1685)
-- [XSS Defense in Rails](https://youtu.be/2VFavqfDS6w?t=2442)
-- [XSS Defense with HAML](https://youtu.be/2VFavqfDS6w?t=2796)
-- [JavaScript URLs](https://youtu.be/2VFavqfDS6w?t=3274)
-- [URL encoding context](https://youtu.be/2VFavqfDS6w?t=3494)
-- [Validating Untrusted URLs in Ruby](https://youtu.be/2VFavqfDS6w?t=3936)
-- [HTML Sanitization](https://youtu.be/2VFavqfDS6w?t=5075)
-- [DOMPurify](https://youtu.be/2VFavqfDS6w?t=5381)
-- [Safe Client-side JSON Handling](https://youtu.be/2VFavqfDS6w?t=6334)
-- [iframe sandboxing](https://youtu.be/2VFavqfDS6w?t=7043)
-- [Input Validation](https://youtu.be/2VFavqfDS6w?t=7489)
-- [Validate size limits](https://youtu.be/2VFavqfDS6w?t=7582)
-- [RoR model validators](https://youtu.be/2VFavqfDS6w?t=7636)
-- [Allowlist input validation](https://youtu.be/2VFavqfDS6w?t=7816)
-- [Content Security Policy](https://www.youtube.com/watch?v=2VFavqfDS6w&t=12991s)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Introduction to XSS](https://www.youtube.com/watch?v=PXR8PTojHmc&t=7785s)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Reflected XSS](https://youtu.be/2VFavqfDS6w?t=603s)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Persistent XSS](https://youtu.be/2VFavqfDS6w?t=643)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [DOM XSS](https://youtu.be/2VFavqfDS6w?t=5871)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [XSS in depth](https://www.youtube.com/watch?v=2VFavqfDS6w&t=111s)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [XSS Defense](https://youtu.be/2VFavqfDS6w?t=1685)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [XSS Defense in Rails](https://youtu.be/2VFavqfDS6w?t=2442)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [XSS Defense with HAML](https://youtu.be/2VFavqfDS6w?t=2796)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [JavaScript URLs](https://youtu.be/2VFavqfDS6w?t=3274)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [URL encoding context](https://youtu.be/2VFavqfDS6w?t=3494)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Validating Untrusted URLs in Ruby](https://youtu.be/2VFavqfDS6w?t=3936)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [HTML Sanitization](https://youtu.be/2VFavqfDS6w?t=5075)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [DOMPurify](https://youtu.be/2VFavqfDS6w?t=5381)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Safe Client-side JSON Handling](https://youtu.be/2VFavqfDS6w?t=6334)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [iframe sandboxing](https://youtu.be/2VFavqfDS6w?t=7043)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Input Validation](https://youtu.be/2VFavqfDS6w?t=7489)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Validate size limits](https://youtu.be/2VFavqfDS6w?t=7582)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [RoR model validators](https://youtu.be/2VFavqfDS6w?t=7636)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Allowlist input validation](https://youtu.be/2VFavqfDS6w?t=7816)
+- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Content Security Policy](https://www.youtube.com/watch?v=2VFavqfDS6w&t=12991s)
## Path Traversal guidelines
@@ -423,14 +423,14 @@ Path Traversal attacks can lead to multiple critical and high severity issues, l
### When to consider
-When working with user-controlled filenames/paths and filesystem APIs.
+When working with user-controlled filenames/paths and file system APIs.
### Mitigation and prevention
In order to prevent Path Traversal vulnerabilities, user-controlled filenames or paths should be validated before being processed.
- Comparing user input against an allowlist of allowed values or verifying that it only contains allowed characters.
-- After validating the user supplied input, it should be appended to the base directory and the path should be canonicalized using the filesystem API.
+- After validating the user supplied input, it should be appended to the base directory and the path should be canonicalized using the file system API.
#### GitLab specific validations
diff --git a/doc/development/shared_files.md b/doc/development/shared_files.md
index 859650c2e6c..6c273f2899d 100644
--- a/doc/development/shared_files.md
+++ b/doc/development/shared_files.md
@@ -32,7 +32,7 @@ disk in a temporary file so you can perform some checks on it. When the checks
pass, you make the file official. In scenarios like this please follow these
rules:
-- Store the temporary file under `shared/tmp`, i.e. on the same filesystem you
+- Store the temporary file under `shared/tmp`, i.e. on the same file system you
want the official file to be on.
- Use move/rename operations when operating on the file instead of copy
operations where possible, because renaming a file is much faster than
diff --git a/doc/development/shell_commands.md b/doc/development/shell_commands.md
index db72454b482..f28828c2e4e 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -202,7 +202,7 @@ When using regular expressions to validate user input that is passed as an argum
If you don't, an attacker could use this to execute commands with potentially harmful effect.
-For example, when a project's `import_url` is validated like below, the user could trick GitLab into cloning from a Git repository on the local filesystem.
+For example, when a project's `import_url` is validated like below, the user could trick GitLab into cloning from a Git repository on the local file system.
```ruby
validates :import_url, format: { with: URI.regexp(%w(ssh git http https)) }
diff --git a/doc/development/sidekiq_debugging.md b/doc/development/sidekiq_debugging.md
deleted file mode 100644
index a9b6e246861..00000000000
--- a/doc/development/sidekiq_debugging.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/troubleshooting/sidekiq.md'
----
-
-This document was moved to [another location](../administration/troubleshooting/sidekiq.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index e290eaee7c2..ce00934b35c 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -550,7 +550,7 @@ in the default execution mode - using
does not account for weights.
As we are [moving towards using `sidekiq-cluster` in
-Core](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
+Free](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
workers do not need to have weights specified. They can simply use the
default weight, which is 1.
diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md
index 6b37936cd93..a56e85ba50d 100644
--- a/doc/development/snowplow.md
+++ b/doc/development/snowplow.md
@@ -104,9 +104,9 @@ The current method provides several attributes that are sent on each click event
| attribute | type | required | description |
| --------- | ------- | -------- | ----------- |
-| category | text | true | The page or backend area of the application. Unless infeasible, please use the Rails page attribute by default in the frontend, and namespace + classname on the backend. |
+| category | text | true | The page or backend area of the application. Unless infeasible, please use the Rails page attribute by default in the frontend, and namespace + class name on the backend. |
| action | text | true | The action the user is taking, or aspect that's being instrumented. The first word should always describe the action or aspect: clicks should be `click`, activations should be `activate`, creations should be `create`, etc. Use underscores to describe what was acted on; for example, activating a form field would be `activate_form_input`. An interface action like clicking on a dropdown would be `click_dropdown`, while a behavior like creating a project record from the backend would be `create_project` |
-| label | text | false | The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navbar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created. |
+| label | text | false | The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navigation bar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created. |
| property | text | false | Any additional property of the element, or object being acted on. |
| value | decimal | false | Describes a numeric value or something directly related to the event. This could be the value of an input (e.g. `10` when clicking `internal` visibility). |
@@ -120,9 +120,9 @@ GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tra
| field | type | default value | description |
|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `category` | string | document.body.dataset.page | Page or subsection of a page that events are being captured within. |
+| `category` | string | `document.body.dataset.page` | Page or subsection of a page that events are being captured within. |
| `action` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
-| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
+| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). |
### Tracking in HAML (or Vue Templates)
@@ -303,11 +303,17 @@ GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby T
Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments:
-| argument | type | default value | description |
-|:-----------|:-------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `category` | string | 'application' | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. |
-| `action` | string | 'generic' | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. |
-| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in [Structured event taxonomy](#structured-event-taxonomy). These are set as empty strings if you don't provide them. |
+| argument | type | default value | description |
+|------------|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------|
+| `category` | String | | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. |
+| `action` | String | | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. |
+| `label` | String | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
+| `property` | String | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
+| `value` | Numeric | nil | As described in [Structured event taxonomy](#structured-event-taxonomy). |
+| `context` | Array\[SelfDescribingJSON\] | nil | An array of custom contexts to send with this event. Most events should not have any custom contexts. |
+| `project` | Project | nil | The project associated with the event. |
+| `user` | User | nil | The user associated with the event. |
+| `namespace` | Namespace | nil | The namespace associated with the event. |
Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code.
@@ -318,10 +324,8 @@ class Projects::CreateService < BaseService
def execute
project = Project.create(params)
- Gitlab::Tracking.event('Projects::CreateService', 'create_project',
- label: project.errors.full_messages.to_sentence,
- value: project.valid?
- )
+ Gitlab::Tracking.event('Projects::CreateService', 'create_project', label: project.errors.full_messages.to_sentence,
+ property: project.valid?.to_s, project: project, user: current_user, namespace: namespace)
end
end
```
@@ -379,7 +383,7 @@ Snowplow Micro is a Docker-based solution for testing frontend and backend event
- Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/)
- Look at the [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro)
-- Watch our [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag)
+- Watch our <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag)
1. Ensure Docker is installed and running.
@@ -478,146 +482,152 @@ For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.c
## Snowplow Schemas
-### [gitlab_standard](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/1-0-0) Schema
+### `gitlab_standard`
-| Field Name | Required | Type | Description |
-|--------------|---------------------|---------|--------------------------------|
-| project_id | **{dotted-circle}** | integer | ID of the associated project |
-| namespace_id | **{dotted-circle}** | integer | ID of the associated namespace |
+We are currently working towards 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.
+
+| Field Name | Required | Type | Description |
+|----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------|
+| `project_id` | **{dotted-circle}** | integer | |
+| `namespace_id` | **{dotted-circle}** | integer | |
+| `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` |
### Default Schema
| Field Name | Required | Type | Description |
|--------------------------|---------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------|
-| app_id | **{check-circle}** | string | Unique identifier for website / application |
-| base_currency | **{dotted-circle}** | string | Reporting currency |
-| br_colordepth | **{dotted-circle}** | integer | Browser color depth |
-| br_cookies | **{dotted-circle}** | boolean | Does the browser permit cookies? |
-| br_family | **{dotted-circle}** | string | Browser family |
-| br_features_director | **{dotted-circle}** | boolean | Director plugin installed? |
-| br_features_flash | **{dotted-circle}** | boolean | Flash plugin installed? |
-| br_features_gears | **{dotted-circle}** | boolean | Google gears installed? |
-| br_features_java | **{dotted-circle}** | boolean | Java plugin installed? |
-| br_features_pdf | **{dotted-circle}** | boolean | Adobe PDF plugin installed? |
-| br_features_quicktime | **{dotted-circle}** | boolean | Quicktime plugin installed? |
-| br_features_realplayer | **{dotted-circle}** | boolean | Realplayer plugin installed? |
-| br_features_silverlight | **{dotted-circle}** | boolean | Silverlight plugin installed? |
-| br_features_windowsmedia | **{dotted-circle}** | boolean | Windows media plugin installed? |
-| br_lang | **{dotted-circle}** | string | Language the browser is set to |
-| br_name | **{dotted-circle}** | string | Browser name |
-| br_renderengine | **{dotted-circle}** | string | Browser rendering engine |
-| br_type | **{dotted-circle}** | string | Browser type |
-| br_version | **{dotted-circle}** | string | Browser version |
-| br_viewheight | **{dotted-circle}** | string | Browser viewport height |
-| br_viewwidth | **{dotted-circle}** | string | Browser viewport width |
-| collector_tstamp | **{dotted-circle}** | timestamp | Time stamp for the event recorded by the collector |
-| contexts | **{dotted-circle}** | | |
-| derived_contexts | **{dotted-circle}** | | Contexts derived in the Enrich process |
-| derived_tstamp | **{dotted-circle}** | timestamp | Timestamp making allowance for innaccurate device clock |
-| doc_charset | **{dotted-circle}** | string | Web page’s character encoding |
-| doc_height | **{dotted-circle}** | string | Web page height |
-| doc_width | **{dotted-circle}** | string | Web page width |
-| domain_sessionid | **{dotted-circle}** | string | Unique identifier (UUID) for this visit of this user_id to this domain |
-| domain_sessionidx | **{dotted-circle}** | integer | Index of number of visits that this user_id has made to this domain (The first visit is `1`) |
-| domain_userid | **{dotted-circle}** | string | Unique identifier for a user, based on a first party cookie (so domain specific) |
-| dvce_created_tstamp | **{dotted-circle}** | timestamp | Timestamp when event occurred, as recorded by client device |
-| dvce_ismobile | **{dotted-circle}** | boolean | Indicates whether device is mobile |
-| dvce_screenheight | **{dotted-circle}** | string | Screen / monitor resolution |
-| dvce_screenwidth | **{dotted-circle}** | string | Screen / monitor resolution |
-| dvce_sent_tstamp | **{dotted-circle}** | timestamp | Timestamp when event was sent by client device to collector |
-| dvce_type | **{dotted-circle}** | string | Type of device |
-| etl_tags | **{dotted-circle}** | string | JSON of tags for this ETL run |
-| etl_tstamp | **{dotted-circle}** | timestamp | Timestamp event began ETL |
-| event | **{dotted-circle}** | string | Event type |
-| event_fingerprint | **{dotted-circle}** | string | Hash client-set event fields |
-| event_format | **{dotted-circle}** | string | Format for event |
-| event_id | **{dotted-circle}** | string | Event UUID |
-| event_name | **{dotted-circle}** | string | Event name |
-| event_vendor | **{dotted-circle}** | string | The company who developed the event model |
-| event_version | **{dotted-circle}** | string | Version of event schema |
-| geo_city | **{dotted-circle}** | string | City of IP origin |
-| geo_country | **{dotted-circle}** | string | Country of IP origin |
-| geo_latitude | **{dotted-circle}** | string | An approximate latitude |
-| geo_longitude | **{dotted-circle}** | string | An approximate longitude |
-| geo_region | **{dotted-circle}** | string | Region of IP origin |
-| geo_region_name | **{dotted-circle}** | string | Region of IP origin |
-| geo_timezone | **{dotted-circle}** | string | Timezone of IP origin |
-| geo_zipcode | **{dotted-circle}** | string | Zip (postal) code of IP origin |
-| ip_domain | **{dotted-circle}** | string | Second level domain name associated with the visitor’s IP address |
-| ip_isp | **{dotted-circle}** | string | Visitor’s ISP |
-| ip_netspeed | **{dotted-circle}** | string | Visitor’s connection type |
-| ip_organization | **{dotted-circle}** | string | Organization associated with the visitor’s IP address – defaults to ISP name if none is found |
-| mkt_campaign | **{dotted-circle}** | string | The campaign ID |
-| mkt_clickid | **{dotted-circle}** | string | The click ID |
-| mkt_content | **{dotted-circle}** | string | The content or ID of the ad. |
-| mkt_medium | **{dotted-circle}** | string | Type of traffic source |
-| mkt_network | **{dotted-circle}** | string | The ad network to which the click ID belongs |
-| mkt_source | **{dotted-circle}** | string | The company / website where the traffic came from |
-| mkt_term | **{dotted-circle}** | string | Keywords associated with the referrer |
-| name_tracker | **{dotted-circle}** | string | The tracker namespace |
-| network_userid | **{dotted-circle}** | string | Unique identifier for a user, based on a cookie from the collector (so set at a network level and shouldn’t be set by a tracker) |
-| os_family | **{dotted-circle}** | string | Operating system family |
-| os_manufacturer | **{dotted-circle}** | string | Manufacturers of operating system |
-| os_name | **{dotted-circle}** | string | Name of operating system |
-| os_timezone | **{dotted-circle}** | string | Client operating system timezone |
-| page_referrer | **{dotted-circle}** | string | Referrer URL |
-| page_title | **{dotted-circle}** | string | Page title |
-| page_url | **{dotted-circle}** | string | Page URL |
-| page_urlfragment | **{dotted-circle}** | string | Fragment aka anchor |
-| page_urlhost | **{dotted-circle}** | string | Host aka domain |
-| page_urlpath | **{dotted-circle}** | string | Path to page |
-| page_urlport | **{dotted-circle}** | integer | Port if specified, 80 if not |
-| page_urlquery | **{dotted-circle}** | string | Query string |
-| page_urlscheme | **{dotted-circle}** | string | Scheme (protocol name) |
-| platform | **{dotted-circle}** | string | The platform the app runs on |
-| pp_xoffset_max | **{dotted-circle}** | integer | Maximum page x offset seen in the last ping period |
-| pp_xoffset_min | **{dotted-circle}** | integer | Minimum page x offset seen in the last ping period |
-| pp_yoffset_max | **{dotted-circle}** | integer | Maximum page y offset seen in the last ping period |
-| pp_yoffset_min | **{dotted-circle}** | integer | Minimum page y offset seen in the last ping period |
-| refr_domain_userid | **{dotted-circle}** | string | The Snowplow domain_userid of the referring website |
-| refr_dvce_tstamp | **{dotted-circle}** | timestamp | The time of attaching the domain_userid to the inbound link |
-| refr_medium | **{dotted-circle}** | string | Type of referer |
-| refr_source | **{dotted-circle}** | string | Name of referer if recognised |
-| refr_term | **{dotted-circle}** | string | Keywords if source is a search engine |
-| refr_urlfragment | **{dotted-circle}** | string | Referer URL fragment |
-| refr_urlhost | **{dotted-circle}** | string | Referer host |
-| refr_urlpath | **{dotted-circle}** | string | Referer page path |
-| refr_urlport | **{dotted-circle}** | integer | Referer port |
-| refr_urlquery | **{dotted-circle}** | string | Referer URL querystring |
-| refr_urlscheme | **{dotted-circle}** | string | Referer scheme |
-| se_action | **{dotted-circle}** | string | The action / event itself |
-| se_category | **{dotted-circle}** | string | The category of event |
-| se_label | **{dotted-circle}** | string | A label often used to refer to the ‘object’ the action is performed on |
-| se_property | **{dotted-circle}** | string | A property associated with either the action or the object |
-| se_value | **{dotted-circle}** | decimal | A value associated with the user action |
-| ti_category | **{dotted-circle}** | string | Item category |
-| ti_currency | **{dotted-circle}** | string | Currency |
-| ti_name | **{dotted-circle}** | string | Item name |
-| ti_orderid | **{dotted-circle}** | string | Order ID |
-| ti_price | **{dotted-circle}** | decimal | Item price |
-| ti_price_base | **{dotted-circle}** | decimal | Item price in base currency |
-| ti_quantity | **{dotted-circle}** | integer | Item quantity |
-| ti_sku | **{dotted-circle}** | string | Item SKU |
-| tr_affiliation | **{dotted-circle}** | string | Transaction affiliation (such as channel) |
-| tr_city | **{dotted-circle}** | string | Delivery address: city |
-| tr_country | **{dotted-circle}** | string | Delivery address: country |
-| tr_currency | **{dotted-circle}** | string | Transaction Currency |
-| tr_orderid | **{dotted-circle}** | string | Order ID |
-| tr_shipping | **{dotted-circle}** | decimal | Delivery cost charged |
-| tr_shipping_base | **{dotted-circle}** | decimal | Shipping cost in base currency |
-| tr_state | **{dotted-circle}** | string | Delivery address: state |
-| tr_tax | **{dotted-circle}** | decimal | Transaction tax value (such as amount of VAT included) |
-| tr_tax_base | **{dotted-circle}** | decimal | Tax applied in base currency |
-| tr_total | **{dotted-circle}** | decimal | Transaction total value |
-| tr_total_base | **{dotted-circle}** | decimal | Total amount of transaction in base currency |
-| true_tstamp | **{dotted-circle}** | timestamp | User-set exact timestamp |
-| txn_id | **{dotted-circle}** | string | Transaction ID |
-| unstruct_event | **{dotted-circle}** | JSON | The properties of the event |
-| uploaded_at | **{dotted-circle}** | | |
-| user_fingerprint | **{dotted-circle}** | integer | User identifier based on (hopefully unique) browser features |
-| user_id | **{dotted-circle}** | string | Unique identifier for user, set by the business using setUserId |
-| user_ipaddress | **{dotted-circle}** | string | IP address |
-| useragent | **{dotted-circle}** | string | User agent (expressed as a browser string) |
-| v_collector | **{dotted-circle}** | string | Collector version |
-| v_etl | **{dotted-circle}** | string | ETL version |
-| v_tracker | **{dotted-circle}** | string | Identifier for Snowplow tracker |
+| `app_id` | **{check-circle}** | string | Unique identifier for website / application |
+| `base_currency` | **{dotted-circle}** | string | Reporting currency |
+| `br_colordepth` | **{dotted-circle}** | integer | Browser color depth |
+| `br_cookies` | **{dotted-circle}** | boolean | Does the browser permit cookies? |
+| `br_family` | **{dotted-circle}** | string | Browser family |
+| `br_features_director` | **{dotted-circle}** | boolean | Director plugin installed? |
+| `br_features_flash` | **{dotted-circle}** | boolean | Flash plugin installed? |
+| `br_features_gears` | **{dotted-circle}** | boolean | Google gears installed? |
+| `br_features_java` | **{dotted-circle}** | boolean | Java plugin installed? |
+| `br_features_pdf` | **{dotted-circle}** | boolean | Adobe PDF plugin installed? |
+| `br_features_quicktime` | **{dotted-circle}** | boolean | Quicktime plugin installed? |
+| `br_features_realplayer` | **{dotted-circle}** | boolean | RealPlayer plugin installed? |
+| `br_features_silverlight` | **{dotted-circle}** | boolean | Silverlight plugin installed? |
+| `br_features_windowsmedia` | **{dotted-circle}** | boolean | Windows media plugin installed? |
+| `br_lang` | **{dotted-circle}** | string | Language the browser is set to |
+| `br_name` | **{dotted-circle}** | string | Browser name |
+| `br_renderengine` | **{dotted-circle}** | string | Browser rendering engine |
+| `br_type` | **{dotted-circle}** | string | Browser type |
+| `br_version` | **{dotted-circle}** | string | Browser version |
+| `br_viewheight` | **{dotted-circle}** | string | Browser viewport height |
+| `br_viewwidth` | **{dotted-circle}** | string | Browser viewport width |
+| `collector_tstamp` | **{dotted-circle}** | timestamp | Time stamp for the event recorded by the collector |
+| `contexts` | **{dotted-circle}** | | |
+| `derived_contexts` | **{dotted-circle}** | | Contexts derived in the Enrich process |
+| `derived_tstamp` | **{dotted-circle}** | timestamp | Timestamp making allowance for inaccurate device clock |
+| `doc_charset` | **{dotted-circle}** | string | Web page’s character encoding |
+| `doc_height` | **{dotted-circle}** | string | Web page height |
+| `doc_width` | **{dotted-circle}** | string | Web page width |
+| `domain_sessionid` | **{dotted-circle}** | string | Unique identifier (UUID) for this visit of this user_id to this domain |
+| `domain_sessionidx` | **{dotted-circle}** | integer | Index of number of visits that this user_id has made to this domain (The first visit is `1`) |
+| `domain_userid` | **{dotted-circle}** | string | Unique identifier for a user, based on a first party cookie (so domain specific) |
+| `dvce_created_tstamp` | **{dotted-circle}** | timestamp | Timestamp when event occurred, as recorded by client device |
+| `dvce_ismobile` | **{dotted-circle}** | boolean | Indicates whether device is mobile |
+| `dvce_screenheight` | **{dotted-circle}** | string | Screen / monitor resolution |
+| `dvce_screenwidth` | **{dotted-circle}** | string | Screen / monitor resolution |
+| `dvce_sent_tstamp` | **{dotted-circle}** | timestamp | Timestamp when event was sent by client device to collector |
+| `dvce_type` | **{dotted-circle}** | string | Type of device |
+| `etl_tags` | **{dotted-circle}** | string | JSON of tags for this ETL run |
+| `etl_tstamp` | **{dotted-circle}** | timestamp | Timestamp event began ETL |
+| `event` | **{dotted-circle}** | string | Event type |
+| `event_fingerprint` | **{dotted-circle}** | string | Hash client-set event fields |
+| `event_format` | **{dotted-circle}** | string | Format for event |
+| `event_id` | **{dotted-circle}** | string | Event UUID |
+| `event_name` | **{dotted-circle}** | string | Event name |
+| `event_vendor` | **{dotted-circle}** | string | The company who developed the event model |
+| `event_version` | **{dotted-circle}** | string | Version of event schema |
+| `geo_city` | **{dotted-circle}** | string | City of IP origin |
+| `geo_country` | **{dotted-circle}** | string | Country of IP origin |
+| `geo_latitude` | **{dotted-circle}** | string | An approximate latitude |
+| `geo_longitude` | **{dotted-circle}** | string | An approximate longitude |
+| `geo_region` | **{dotted-circle}** | string | Region of IP origin |
+| `geo_region_name` | **{dotted-circle}** | string | Region of IP origin |
+| `geo_timezone` | **{dotted-circle}** | string | Timezone of IP origin |
+| `geo_zipcode` | **{dotted-circle}** | string | Zip (postal) code of IP origin |
+| `ip_domain` | **{dotted-circle}** | string | Second level domain name associated with the visitor’s IP address |
+| `ip_isp` | **{dotted-circle}** | string | Visitor’s ISP |
+| `ip_netspeed` | **{dotted-circle}** | string | Visitor’s connection type |
+| `ip_organization` | **{dotted-circle}** | string | Organization associated with the visitor’s IP address – defaults to ISP name if none is found |
+| `mkt_campaign` | **{dotted-circle}** | string | The campaign ID |
+| `mkt_clickid` | **{dotted-circle}** | string | The click ID |
+| `mkt_content` | **{dotted-circle}** | string | The content or ID of the ad. |
+| `mkt_medium` | **{dotted-circle}** | string | Type of traffic source |
+| `mkt_network` | **{dotted-circle}** | string | The ad network to which the click ID belongs |
+| `mkt_source` | **{dotted-circle}** | string | The company / website where the traffic came from |
+| `mkt_term` | **{dotted-circle}** | string | Keywords associated with the referrer |
+| `name_tracker` | **{dotted-circle}** | string | The tracker namespace |
+| `network_userid` | **{dotted-circle}** | string | Unique identifier for a user, based on a cookie from the collector (so set at a network level and shouldn’t be set by a tracker) |
+| `os_family` | **{dotted-circle}** | string | Operating system family |
+| `os_manufacturer` | **{dotted-circle}** | string | Manufacturers of operating system |
+| `os_name` | **{dotted-circle}** | string | Name of operating system |
+| `os_timezone` | **{dotted-circle}** | string | Client operating system timezone |
+| `page_referrer` | **{dotted-circle}** | string | Referrer URL |
+| `page_title` | **{dotted-circle}** | string | Page title |
+| `page_url` | **{dotted-circle}** | string | Page URL |
+| `page_urlfragment` | **{dotted-circle}** | string | Fragment aka anchor |
+| `page_urlhost` | **{dotted-circle}** | string | Host aka domain |
+| `page_urlpath` | **{dotted-circle}** | string | Path to page |
+| `page_urlport` | **{dotted-circle}** | integer | Port if specified, 80 if not |
+| `page_urlquery` | **{dotted-circle}** | string | Query string |
+| `page_urlscheme` | **{dotted-circle}** | string | Scheme (protocol name) |
+| `platform` | **{dotted-circle}** | string | The platform the app runs on |
+| `pp_xoffset_max` | **{dotted-circle}** | integer | Maximum page x offset seen in the last ping period |
+| `pp_xoffset_min` | **{dotted-circle}** | integer | Minimum page x offset seen in the last ping period |
+| `pp_yoffset_max` | **{dotted-circle}** | integer | Maximum page y offset seen in the last ping period |
+| `pp_yoffset_min` | **{dotted-circle}** | integer | Minimum page y offset seen in the last ping period |
+| `refr_domain_userid` | **{dotted-circle}** | string | The Snowplow `domain_userid` of the referring website |
+| `refr_dvce_tstamp` | **{dotted-circle}** | timestamp | The time of attaching the `domain_userid` to the inbound link |
+| `refr_medium` | **{dotted-circle}** | string | Type of referer |
+| `refr_source` | **{dotted-circle}** | string | Name of referer if recognised |
+| `refr_term` | **{dotted-circle}** | string | Keywords if source is a search engine |
+| `refr_urlfragment` | **{dotted-circle}** | string | Referer URL fragment |
+| `refr_urlhost` | **{dotted-circle}** | string | Referer host |
+| `refr_urlpath` | **{dotted-circle}** | string | Referer page path |
+| `refr_urlport` | **{dotted-circle}** | integer | Referer port |
+| `refr_urlquery` | **{dotted-circle}** | string | Referer URL query string |
+| `refr_urlscheme` | **{dotted-circle}** | string | Referer scheme |
+| `se_action` | **{dotted-circle}** | string | The action / event itself |
+| `se_category` | **{dotted-circle}** | string | The category of event |
+| `se_label` | **{dotted-circle}** | string | A label often used to refer to the ‘object’ the action is performed on |
+| `se_property` | **{dotted-circle}** | string | A property associated with either the action or the object |
+| `se_value` | **{dotted-circle}** | decimal | A value associated with the user action |
+| `ti_category` | **{dotted-circle}** | string | Item category |
+| `ti_currency` | **{dotted-circle}** | string | Currency |
+| `ti_name` | **{dotted-circle}** | string | Item name |
+| `ti_orderid` | **{dotted-circle}** | string | Order ID |
+| `ti_price` | **{dotted-circle}** | decimal | Item price |
+| `ti_price_base` | **{dotted-circle}** | decimal | Item price in base currency |
+| `ti_quantity` | **{dotted-circle}** | integer | Item quantity |
+| `ti_sku` | **{dotted-circle}** | string | Item SKU |
+| `tr_affiliation` | **{dotted-circle}** | string | Transaction affiliation (such as channel) |
+| `tr_city` | **{dotted-circle}** | string | Delivery address: city |
+| `tr_country` | **{dotted-circle}** | string | Delivery address: country |
+| `tr_currency` | **{dotted-circle}** | string | Transaction Currency |
+| `tr_orderid` | **{dotted-circle}** | string | Order ID |
+| `tr_shipping` | **{dotted-circle}** | decimal | Delivery cost charged |
+| `tr_shipping_base` | **{dotted-circle}** | decimal | Shipping cost in base currency |
+| `tr_state` | **{dotted-circle}** | string | Delivery address: state |
+| `tr_tax` | **{dotted-circle}** | decimal | Transaction tax value (such as amount of VAT included) |
+| `tr_tax_base` | **{dotted-circle}** | decimal | Tax applied in base currency |
+| `tr_total` | **{dotted-circle}** | decimal | Transaction total value |
+| `tr_total_base` | **{dotted-circle}** | decimal | Total amount of transaction in base currency |
+| `true_tstamp` | **{dotted-circle}** | timestamp | User-set exact timestamp |
+| `txn_id` | **{dotted-circle}** | string | Transaction ID |
+| `unstruct_event` | **{dotted-circle}** | JSON | The properties of the event |
+| `uploaded_at` | **{dotted-circle}** | | |
+| `user_fingerprint` | **{dotted-circle}** | integer | User identifier based on (hopefully unique) browser features |
+| `user_id` | **{dotted-circle}** | string | Unique identifier for user, set by the business using setUserId |
+| `user_ipaddress` | **{dotted-circle}** | string | IP address |
+| `useragent` | **{dotted-circle}** | string | User agent (expressed as a browser string) |
+| `v_collector` | **{dotted-circle}** | string | Collector version |
+| `v_etl` | **{dotted-circle}** | string | ETL version |
+| `v_tracker` | **{dotted-circle}** | string | Identifier for Snowplow tracker |
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
index 453d71411c3..e75237869ba 100644
--- a/doc/development/stage_group_dashboards.md
+++ b/doc/development/stage_group_dashboards.md
@@ -61,7 +61,7 @@ Although most of the metrics displayed in the panels are self-explanatory in the
To inspect the raw data of the panel for further calculation, click on the Inspect button from the dropdown menu of a panel. Queries, raw data, and panel JSON structure are available. Read more at [Grafana panel inspection](https://grafana.com/docs/grafana/latest/panels/inspect-panel/).
-All the dashboards are powered by [Grafana](https://grafana.com/), a frontend for displaying metrics. Grafana consumes the data returned from queries to backend Prometheus data source, then presents them under different visualizations. The stage group dashboards are built to serve the most common use cases with a limited set of filters, and pre-built queries. Grafana provides a way to explore and visualize the metrics data with [Grafana Explore](https://grafana.com/docs/grafana/latest/explore/). This would require some knowledge about [Prometheus Promql query language](https://prometheus.io/docs/prometheus/latest/querying/basics/).
+All the dashboards are powered by [Grafana](https://grafana.com/), a frontend for displaying metrics. Grafana consumes the data returned from queries to backend Prometheus data source, then presents them under different visualizations. The stage group dashboards are built to serve the most common use cases with a limited set of filters, and pre-built queries. Grafana provides a way to explore and visualize the metrics data with [Grafana Explore](https://grafana.com/docs/grafana/latest/explore/). This would require some knowledge about [Prometheus PromQL query language](https://prometheus.io/docs/prometheus/latest/querying/basics/).
## How to debug with the dashboards
@@ -83,7 +83,7 @@ All the dashboards are powered by [Grafana](https://grafana.com/), a frontend fo
## How to customize the dashboard
-All Grafana dashboards at GitLab are generated from the [Jsonnet files](https://github.com/grafana/grafonnet-lib) stored in [the runbook project](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards). Particularly, the stage group dashboards definitions are stored in [/dashboards/stage-groups](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards/stage-groups) subfolder in the Runbook. By convention, each group has a corresponding jsonnet file. The dashboards are synced with GitLab [stage group data](https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml) every month. Expansion and customization are one of the key principles used when we designed this system. To customize your group's dashboard, you need to edit the corresponding file and follow the [Runbook workflow](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards#dashboard-source). The dashboard is updated after the MR is merged. Looking at an autogenerated file, for example, [`product_planning.dashboard.jsonnet`](https://gitlab.com/gitlab-com/runbooks/-/blob/master/dashboards/stage-groups/product_planning.dashboard.jsonnet):
+All Grafana dashboards at GitLab are generated from the [Jsonnet files](https://github.com/grafana/grafonnet-lib) stored in [the runbook project](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards). Particularly, the stage group dashboards definitions are stored in [/dashboards/stage-groups](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards/stage-groups) subfolder in the Runbook. By convention, each group has a corresponding Jsonnet file. The dashboards are synced with GitLab [stage group data](https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml) every month. Expansion and customization are one of the key principles used when we designed this system. To customize your group's dashboard, you need to edit the corresponding file and follow the [Runbook workflow](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards#dashboard-source). The dashboard is updated after the MR is merged. Looking at an autogenerated file, for example, [`product_planning.dashboard.jsonnet`](https://gitlab.com/gitlab-com/runbooks/-/blob/master/dashboards/stage-groups/product_planning.dashboard.jsonnet):
```jsonnet
// This file is autogenerated using scripts/update_stage_groups_dashboards.rb
@@ -145,4 +145,8 @@ stageGroupDashboards.dashboard('source_code')
![Stage Group Dashboard Customization](img/stage_group_dashboards_time_customization.png)
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+If you want to see the workflow in action, we've recorded a pairing session on customizing a dashboard,
+available on [GitLab Unfiltered](https://youtu.be/shEd_eiUjdI).
+
For deeper customization and more complicated metrics, visit the [Grafonnet lib](https://github.com/grafana/grafonnet-lib) project and the [GitLab Prometheus Metrics](../administration/monitoring/prometheus/gitlab_metrics.md#gitlab-prometheus-metrics) documentation.
diff --git a/doc/development/telemetry/event_dictionary.md b/doc/development/telemetry/event_dictionary.md
deleted file mode 100644
index b3b3b0b4fdd..00000000000
--- a/doc/development/telemetry/event_dictionary.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/telemetry/index.md b/doc/development/telemetry/index.md
deleted file mode 100644
index b3b3b0b4fdd..00000000000
--- a/doc/development/telemetry/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/telemetry/snowplow.md b/doc/development/telemetry/snowplow.md
deleted file mode 100644
index bb056ffddfe..00000000000
--- a/doc/development/telemetry/snowplow.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../snowplow.md'
----
-
-This document was moved to [another location](../snowplow.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md
deleted file mode 100644
index 5fbdb508bb1..00000000000
--- a/doc/development/telemetry/usage_ping.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../usage_ping.md'
----
-
-This document was moved to [another location](../usage_ping.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/testing.md b/doc/development/testing.md
deleted file mode 100644
index a0130bfb4ac..00000000000
--- a/doc/development/testing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'testing_guide/index.md'
----
-
-This document was moved to [another location](testing_guide/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index ac5f1a47f9b..79ff46ae352 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -13,13 +13,13 @@ description: "GitLab development guidelines - testing best practices."
Testing at GitLab is a first class citizen, not an afterthought. It's important we consider the design of our tests
as we do the design of our features.
-When implementing a feature, we think about developing the right capabilities the right way, which helps us
+When implementing a feature, we think about developing the right capabilities the right way. This helps us
narrow our scope to a manageable level. When implementing tests for a feature, we must think about developing
-the right tests, but then cover _all_ the important ways the test may fail, which can quickly widen our scope to
+the right tests, but then cover _all_ the important ways the test may fail. This can quickly widen our scope to
a level that is difficult to manage.
Test heuristics can help solve this problem. They concisely address many of the common ways bugs
-manifest themselves within our code. When designing our tests, take time to review known test heuristics to inform
+manifest themselves in our code. When designing our tests, take time to review known test heuristics to inform
our test design. We can find some helpful heuristics documented in the Handbook in the
[Test Engineering](https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-heuristics) section.
@@ -90,7 +90,7 @@ Obviously we should reduce test dependencies, and avoiding
capabilities also reduces the amount of set-up needed.
`:js` is particularly important to avoid. This must only be used if the feature
-test requires JavaScript reactivity in the browser, since using a headless
+test requires JavaScript reactivity in the browser. Using a headless
browser is much slower than parsing the HTML response from the app.
#### Optimize factory usage
@@ -108,8 +108,8 @@ To avoid creation, it is worth bearing in mind that:
- `instance_double` and `spy` are faster than `FactoryBot.build(...)`.
- `FactoryBot.build(...)` and `.build_stubbed` are faster than `.create`.
-- Don't `create` an object when `build`, `build_stubbed`, `attributes_for`,
- `spy`, or `instance_double` will do. Database persistence is slow!
+- Don't `create` an object when you can use `build`, `build_stubbed`, `attributes_for`,
+ `spy`, or `instance_double`. Database persistence is slow!
Use [Factory Doctor](https://test-prof.evilmartians.io/#/profilers/factory_doctor) to find cases where database persistence is not needed in a given test.
@@ -171,14 +171,14 @@ RSpec.describe API::Search, factory_default: :keep do
let_it_be(:namespace) { create_default(:namespace) }
```
-Then every project we create will use this `namespace`, without us having to pass
+Then every project we create uses this `namespace`, without us having to pass
it as `namespace: namespace`. In order to make it work along with `let_it_be`, `factory_default: :keep`
-must be explicitly specified. That will keep the default factory for every example in a suite instead of
+must be explicitly specified. That keeps the default factory for every example in a suite instead of
recreating it for each example.
Maybe we don't need to create 208 different projects - we
can create one and reuse it. In addition, we can see that only about 1/3 of the
-projects we create are ones we ask for (76/208), so there is benefit in setting
+projects we create are ones we ask for (76/208). There is benefit in setting
a default value for projects as well:
```ruby
@@ -233,8 +233,8 @@ Finished in 2 minutes 19 seconds (files took 1 minute 4.42 seconds to load)
```
From this result, we can see the most expensive examples in our spec, giving us
-a place to start. The fact that the most expensive examples here are in
-shared examples means that any reductions are likely to have a larger impact as
+a place to start. The most expensive examples here are in
+shared examples; any reductions generally have a larger impact as
they are called in multiple places.
#### Avoid repeating expensive actions
@@ -287,7 +287,7 @@ results are available, and not just the first failure.
- Use `.method` to describe class methods and `#method` to describe instance
methods.
- Use `context` to test branching logic.
-- Try to match the ordering of tests to the ordering within the class.
+- Try to match the ordering of tests to the ordering in the class.
- Try to follow the [Four-Phase Test](https://thoughtbot.com/blog/four-phase-test) pattern, using newlines
to separate phases.
- Use `Gitlab.config.gitlab.host` rather than hard coding `'localhost'`
@@ -295,10 +295,10 @@ results are available, and not just the first failure.
[Gotchas](../gotchas.md#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
- Avoid using `expect_any_instance_of` or `allow_any_instance_of` (see
[Gotchas](../gotchas.md#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute)).
-- Don't supply the `:each` argument to hooks since it's the default.
+- Don't supply the `:each` argument to hooks because it's the default.
- On `before` and `after` hooks, prefer it scoped to `:context` over `:all`
- When using `evaluate_script("$('.js-foo').testSomething()")` (or `execute_script`) which acts on a given element,
- use a Capybara matcher beforehand (e.g. `find('.js-foo')`) to ensure the element actually exists.
+ use a Capybara matcher beforehand (such as `find('.js-foo')`) to ensure the element actually exists.
- Use `focus: true` to isolate parts of the specs you want to run.
- Use [`:aggregate_failures`](https://relishapp.com/rspec/rspec-core/docs/expectation-framework-integration/aggregating-failures) when there is more than one expectation in a test.
- For [empty test description blocks](https://github.com/rubocop-hq/rspec-style-guide#it-and-specify), use `specify` rather than `it do` if the test is self-explanatory.
@@ -343,7 +343,7 @@ writing one](testing_levels.md#consider-not-writing-a-system-test)!
For instance, if you want to verify that a record was created, add
expectations that its attributes are displayed on the page, not that
`Model.count` increased by one.
-- It's ok to look for DOM elements but don't abuse it since it makes the tests
+- It's ok to look for DOM elements, but don't abuse it, because it makes the tests
more brittle
#### Debugging Capybara
@@ -353,7 +353,7 @@ Sometimes you may need to debug Capybara tests by observing browser behavior.
#### Live debug
You can pause Capybara and view the website on the browser by using the
-`live_debug` method in your spec. The current page will be automatically opened
+`live_debug` method in your spec. The current page is automatically opened
in your default browser.
You may need to sign in first (the current user's credentials are displayed in
the terminal).
@@ -381,13 +381,13 @@ Finished in 34.51 seconds (files took 0.76702 seconds to load)
#### Run `:js` spec in a visible browser
-Run the spec with `CHROME_HEADLESS=0`, e.g.:
+Run the spec with `CHROME_HEADLESS=0`, like this:
```shell
CHROME_HEADLESS=0 bin/rspec some_spec.rb
```
-The test will go by quickly, but this will give you an idea of what's happening.
+The test completes quickly, but this gives you an idea of what's happening.
Using `live_debug` with `CHROME_HEADLESS=0` pauses the open browser, and does not
open the page again. This can be used to debug and inspect elements.
@@ -416,20 +416,20 @@ There is a [small hack](https://gitlab.com/gitlab-org/gitlab-foss/snippets/17184
### Fast unit tests
-Some classes are well-isolated from Rails and you should be able to test them
+Some classes are well-isolated from Rails. You should be able to test them
without the overhead added by the Rails environment and Bundler's `:default`
group's gem loading. In these cases, you can `require 'fast_spec_helper'`
instead of `require 'spec_helper'` in your test file, and your test should run
-really fast since:
+really fast because:
-- Gems loading is skipped
+- Gem loading is skipped
- Rails app boot is skipped
- GitLab Shell and Gitaly setup are skipped
- Test repositories setup are skipped
`fast_spec_helper` also support autoloading classes that are located inside the
-`lib/` directory. It means that as long as your class / module is using only
-code from the `lib/` directory you will not need to explicitly load any
+`lib/` directory. If your class or module is using only
+code from the `lib/` directory, you don't need to explicitly load any
dependencies. `fast_spec_helper` also loads all ActiveSupport extensions,
including core extensions that are commonly used in the Rails environment.
@@ -439,9 +439,11 @@ in `lib/`.
For example, if you want to test your code that is calling the
`Gitlab::UntrustedRegexp` class, which under the hood uses `re2` library, you
-should either add `require_dependency 're2'` to files in your library that
-need `re2` gem, to make this requirement explicit, or you can add it to the
-spec itself, but the former is preferred.
+should either:
+
+- Add `require_dependency 're2'` to files in your library that need `re2` gem,
+ to make this requirement explicit. This approach is preferred.
+- Add it to the spec itself.
It takes around one second to load tests that are using `fast_spec_helper`
instead of 30+ seconds in case of a regular `spec_helper`.
@@ -465,7 +467,7 @@ so we need to set some guidelines for their use going forward:
- Don't define a `let` variable that's only used by the definition of another.
Use a helper method instead.
- `let!` variables should be used only in case if strict evaluation with defined
- order is required, otherwise `let` will suffice. Remember that `let` is lazy and won't
+ order is required, otherwise `let` suffices. Remember that `let` is lazy and won't
be evaluated until it is referenced.
- Avoid referencing `subject` in examples. Use a named subject `subject(:name)`, or a `let` variable instead, so
the variable has a contextual name.
@@ -475,7 +477,7 @@ so we need to set some guidelines for their use going forward:
In some cases, there is no need to recreate the same object for tests
again for each example. For example, a project and a guest of that project
-is needed to test issues on the same project, one project and user will do for the entire file.
+are needed to test issues on the same project, so one project and user are enough for the entire file.
As much as possible, do not implement this using `before(:all)` or `before(:context)`. If you do,
you would need to manually clean up the data as those hooks run outside a database transaction.
@@ -494,9 +496,9 @@ before_all do
end
```
-This will result in only one `Project`, `User`, and `ProjectMember` created for this context.
+This results in only one `Project`, `User`, and `ProjectMember` created for this context.
-`let_it_be` and `before_all` are also available within nested contexts. Cleanup after the context
+`let_it_be` and `before_all` are also available in nested contexts. Cleanup after the context
is handled automatically using a transaction rollback.
Note that if you modify an object defined inside a `let_it_be` block,
@@ -545,14 +547,14 @@ This section was moved to [developing with feature flags](../feature_flags/devel
The code exercised by a single GitLab test may access and modify many items of
data. Without careful preparation before a test runs, and cleanup afterward,
-data can be changed by a test in such a way that it affects the behavior of
+a test can change data in a way that affects the behavior of
following tests. This should be avoided at all costs! Fortunately, the existing
test framework handles most cases already.
When the test environment does get polluted, a common outcome is
-[flaky tests](flaky_tests.md). Pollution will often manifest as an order
-dependency: running spec A followed by spec B will reliably fail, but running
-spec B followed by spec A will reliably succeed. In these cases, you can use
+[flaky tests](flaky_tests.md). Pollution often manifests as an order
+dependency: running spec A followed by spec B reliably fails, but running
+spec B followed by spec A reliably succeeds. In these cases, you can use
`rspec --bisect` (or a manual pairwise bisect of spec files) to determine which
spec is at fault. Fixing the problem requires some understanding of how the test
suite ensures the environment is pristine. Read on to discover more about each
@@ -561,15 +563,15 @@ data store!
#### SQL database
This is managed for us by the `database_cleaner` gem. Each spec is surrounded in
-a transaction, which is rolled back once the test completes. Certain specs will
-instead issue `DELETE FROM` queries against every table after completion; this
+a transaction, which is rolled back after the test completes. Certain specs
+instead issue `DELETE FROM` queries against every table after completion. This
allows the created rows to be viewed from multiple database connections, which
is important for specs that run in a browser, or migration specs, among others.
One consequence of using these strategies, instead of the well-known
`TRUNCATE TABLES` approach, is that primary keys and other sequences are **not**
reset across specs. So if you create a project in spec A, then create a project
-in spec B, the first will have `id=1`, while the second will have `id=2`.
+in spec B, the first has `id=1`, while the second has `id=2`.
This means that specs should **never** rely on the value of an ID, or any other
sequence-generated column. To avoid accidental conflicts, specs should also
@@ -610,7 +612,7 @@ DNS requests are stubbed universally in the test suite
(as of [!22368](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22368)), as DNS can
cause issues depending on the developer's local network. There are RSpec labels
available in `spec/support/dns.rb` which you can apply to tests if you need to
-bypass the DNS stubbing, e.g.:
+bypass the DNS stubbing, like this:
```ruby
it "really connects to Prometheus", :permit_dns do
@@ -625,8 +627,8 @@ In the situations where you need to
[stub](https://relishapp.com/rspec/rspec-mocks/v/3-9/docs/basics/allowing-messages)
methods such as `File.read`, make sure to:
-1. Stub `File.read` for only the filepath you are interested in.
-1. Call the original implementation for other filepaths.
+1. Stub `File.read` for only the file path you are interested in.
+1. Call the original implementation for other file paths.
Otherwise `File.read` calls from other parts of the codebase get
stubbed incorrectly. You should use the `stub_file_read`, and
@@ -645,19 +647,19 @@ allow(File).to receive(:read).and_call_original
allow(File).to receive(:read).with(my_filepath)
```
-#### Filesystem
+#### File system
-Filesystem data can be roughly split into "repositories", and "everything else".
+File system data can be roughly split into "repositories", and "everything else".
Repositories are stored in `tmp/tests/repositories`. This directory is emptied
before a test run starts, and after the test run ends. It is not emptied between
-specs, so created repositories accumulate within this directory over the
+specs, so created repositories accumulate in this directory over the
lifetime of the process. Deleting them is expensive, but this could lead to
pollution unless carefully managed.
To avoid this, [hashed storage](../../administration/repository_storage_types.md)
is enabled in the test suite. This means that repositories are given a unique
-path that depends on their project's ID. Since the project IDs are not reset
-between specs, this guarantees that each spec gets its own repository on disk,
+path that depends on their project's ID. Because the project IDs are not reset
+between specs, each spec gets its own repository on disk,
and prevents changes from being visible between specs.
If a spec manually specifies a project ID, or inspects the state of the
@@ -671,9 +673,9 @@ written to disk in locations determined by ID, so conflicts should not occur.
Some specs disable hashed storage by passing the `:legacy_storage` trait to the
`projects` factory. Specs that do this must **never** override the `path` of the
-project, or any of its groups. The default path includes the project ID, so will
-not conflict; but if two specs create a `:legacy_storage` project with the same
-path, they will use the same repository on disk and lead to test environment
+project, or any of its groups. The default path includes the project ID, so it
+does not conflict. If two specs create a `:legacy_storage` project with the same
+path, they use the same repository on disk and lead to test environment
pollution.
Other files must be managed manually by the spec. If you run code that creates a
@@ -712,21 +714,20 @@ If you need to modify the contents of the `ENV` constant, you can use the
While most Ruby **instances** are not shared between specs, **classes**
and **modules** generally are. Class and module instance variables, accessors,
class variables, and other stateful idioms, should be treated in the same way as
-global variables - don't modify them unless you have to! In particular, prefer
+global variables. Don't modify them unless you have to! In particular, prefer
using expectations, or dependency injection along with stubs, to avoid the need
-for modifications. If you have no other choice, an `around` block similar to the
-example for global variables, above, can be used, but this should be avoided if
-at all possible.
+for modifications. If you have no other choice, an `around` block like the global
+variables example can be used, but avoid this if at all possible.
#### Test Snowplow events
WARNING:
Snowplow performs **runtime type checks** by using the [contracts gem](https://rubygems.org/gems/contracts).
-Since Snowplow is **by default disabled in tests and development**, it can be hard to
+Because Snowplow is **by default disabled in tests and development**, it can be hard to
**catch exceptions** when mocking `Gitlab::Tracking`.
-To catch runtime errors due to type checks, you can enable Snowplow in tests by marking the spec with
-`:snowplow` and use the `expect_snowplow_event` helper which will check for
+To catch runtime errors due to type checks, you can enable Snowplow in tests. Mark the spec with
+`:snowplow` and use the `expect_snowplow_event` helper, which checks for
calls to `Gitlab::Tracking#event`.
```ruby
@@ -737,12 +738,14 @@ describe '#show', :snowplow do
expect_snowplow_event(
category: 'Experiment',
action: 'start',
+ standard_context: { namespace: group, project: project }
)
expect_snowplow_event(
category: 'Experiment',
action: 'sent',
property: 'property',
- label: 'label'
+ label: 'label',
+ standard_context: { namespace: group, project: project }
)
end
end
@@ -794,7 +797,7 @@ end
WARNING:
Only use simple values as input in the `where` block. Using procs, stateful
-objects, FactoryBot-created objects etc. can lead to
+objects, FactoryBot-created objects, and similar items can lead to
[unexpected results](https://github.com/tomykaira/rspec-parameterized/issues/8).
### Prometheus tests
@@ -807,7 +810,7 @@ reset before each example, add the `:prometheus` tag to the RSpec test.
Custom matchers should be created to clarify the intent and/or hide the
complexity of RSpec expectations. They should be placed under
`spec/support/matchers/`. Matchers can be placed in subfolder if they apply to
-a certain type of specs only (e.g. features, requests etc.) but shouldn't be if
+a certain type of specs only (such as features or requests) but shouldn't be if
they apply to multiple type of specs.
#### `be_like_time`
@@ -881,13 +884,13 @@ expect(json_string).to be_valid_json.and match_schema(schema)
Testing query performance allows us to:
-- Assert that N+1 problems do not exist within a block of code.
-- Ensure that the number of queries within a block of code does not increase unnoticed.
+- Assert that N+1 problems do not exist in a block of code.
+- Ensure that the number of queries in a block of code does not increase unnoticed.
#### QueryRecorder
`QueryRecorder` allows profiling and testing of the number of database queries
-performed within a given block of code.
+performed in a given block of code.
See the [`QueryRecorder`](../query_recorder.md) section for more details.
@@ -905,9 +908,9 @@ Any shared contexts used by more than one spec file:
- Should be placed under `spec/support/shared_contexts/`.
- Can be placed in subfolder if they apply to a certain type of specs only
- (e.g. features, requests etc.) but shouldn't be if they apply to multiple type of specs.
+ (such as features or requests) but shouldn't be if they apply to multiple type of specs.
-Each file should include only one context and have a descriptive name, e.g.
+Each file should include only one context and have a descriptive name, such as
`spec/support/shared_contexts/controllers/githubish_import_controller_shared_context.rb`.
### Shared examples
@@ -917,9 +920,9 @@ Any shared examples used by more than one spec file:
- Should be placed under `spec/support/shared_examples/`.
- Can be placed in subfolder if they apply to a certain type of specs only
- (e.g. features, requests etc.) but shouldn't be if they apply to multiple type of specs.
+ (such as features or requests) but shouldn't be if they apply to multiple type of specs.
-Each file should include only one context and have a descriptive name, e.g.
+Each file should include only one context and have a descriptive name, such as
`spec/support/shared_examples/controllers/githubish_import_controller_shared_example.rb`.
### Helpers
@@ -927,8 +930,8 @@ Each file should include only one context and have a descriptive name, e.g.
Helpers are usually modules that provide some methods to hide the complexity of
specific RSpec examples. You can define helpers in RSpec files if they're not
intended to be shared with other specs. Otherwise, they should be placed
-under `spec/support/helpers/`. Helpers can be placed in subfolder if they apply
-to a certain type of specs only (e.g. features, requests etc.) but shouldn't be
+under `spec/support/helpers/`. Helpers can be placed in a subfolder if they apply
+to a certain type of specs only (such as features or requests) but shouldn't be
if they apply to multiple type of specs.
Helpers should follow the Rails naming / namespacing convention. For instance
@@ -985,7 +988,7 @@ All fixtures should be placed under `spec/fixtures/`.
### Repositories
-Testing some functionality, e.g., merging a merge request, requires a Git
+Testing some functionality, such as merging a merge request, requires a Git
repository with a certain state to be present in the test environment. GitLab
maintains the [`gitlab-test`](https://gitlab.com/gitlab-org/gitlab-test)
repository for certain common cases - you can ensure a copy of the repository is
@@ -996,7 +999,7 @@ let(:project) { create(:project, :repository) }
```
Where you can, consider using the `:custom_repo` trait instead of `:repository`.
-This allows you to specify exactly what files will appear in the `master` branch
+This allows you to specify exactly what files appear in the `master` branch
of the project's repository. For example:
```ruby
@@ -1011,17 +1014,17 @@ let(:project) do
end
```
-This will create a repository containing two files, with default permissions and
+This creates a repository containing two files, with default permissions and
the specified content.
### Configuration
-RSpec configuration files are files that change the RSpec configuration (i.e.
+RSpec configuration files are files that change the RSpec configuration (like
`RSpec.configure do |config|` blocks). They should be placed under
`spec/support/`.
-Each file should be related to a specific domain, e.g.
-`spec/support/capybara.rb`, `spec/support/carrierwave.rb`, etc.
+Each file should be related to a specific domain, such as
+`spec/support/capybara.rb` or `spec/support/carrierwave.rb`.
If a helpers module applies only to a certain kind of specs, it should add
modifiers to the `config.include` call. For instance if
@@ -1047,7 +1050,7 @@ file which is used by the `spec/fast_spec_helper.rb` file. See
Services for the test environment are automatically configured and started when
tests are run, including Gitaly, Workhorse, Elasticsearch, and Capybara. When run in CI, or
-if the service needs to be installed, the test environment will log information
+if the service needs to be installed, the test environment logs information
about set-up time, producing log messages like the following:
```plaintext
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 b761e33367f..a5a2d2a1113 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -10,7 +10,7 @@ This is a tailored extension of the Best Practices [found in the testing guide](
## Link a test to its test-case issue
-Every test should have a corresponding issue in the [Quality Testcases project](https://gitlab.com/gitlab-org/quality/testcases/).
+Every test should have a corresponding issue in the [Quality Test Cases project](https://gitlab.com/gitlab-org/quality/testcases/).
It's recommended that you reuse the issue created to plan the test. If one does not already exist you
can create the issue yourself. Alternatively, you can run the test in a pipeline that has reporting
enabled and the test-case issue reporter will automatically create a new issue.
@@ -244,7 +244,7 @@ point of failure and so the screenshot would not be captured at the right moment
All tests expect to be able to log in at the start of the test.
-For an example see: <https://gitlab.com/gitlab-org/gitlab/-/issues/34736>
+For an example see [issue #34736](https://gitlab.com/gitlab-org/gitlab/-/issues/34736).
Ideally, actions performed in an `after(:context)` (or
[`before(:context)`](#limit-the-use-of-the-ui-in-beforecontext-and-after-hooks))
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 1e0eda6491a..1bc33b79c7c 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -74,3 +74,16 @@ existing tests or write new ones.
Please see the [QA README](https://gitlab.com/gitlab-org/gitlab/tree/master/qa#running-tests-with-a-feature-flag-enabled)
for details.
+
+## Confirming that end-to-end tests pass with a feature flag enabled
+
+End-to-end tests should pass with a feature flag enabled before it is enabled on Staging or on GitLab.com. Tests that need to be updated should be identified as part of [quad-planning](https://about.gitlab.com/handbook/engineering/quality/quad-planning/). The relevant [counterpart Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) is responsible for updating the tests or assisting another engineer to do so. However, if a change does not go through quad-planning and a required test update is not made, test failures could block deployment.
+
+If a test enables a feature flag as describe above, it is sufficient to run the `package-and-qa` job in a merge request containing the relevant changes.
+Or, if the feature flag and relevant changes have already been merged, you can confirm that the tests
+pass on `master`. The end-to-end tests run on `master` every two hours, and the results are posted to a [Test
+Session Report, which is available in the testcase-sessions project](https://gitlab.com/gitlab-org/quality/testcase-sessions/-/issues?label_name%5B%5D=found%3Amaster).
+
+If the relevant tests do not enable the feature flag themselves, you can check if the tests will need
+to be updated by opening a draft merge request that enables the flag by default and then running the `package-and-qa` job.
+The merge request can be closed once the tests pass. If you need assistance to update the tests, please contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), or any Software Engineer in Test if there is no stable counterpart for your group.
diff --git a/doc/development/testing_guide/end_to_end/page_objects.md b/doc/development/testing_guide/end_to_end/page_objects.md
index 939e44cedd9..d9309f74e0e 100644
--- a/doc/development/testing_guide/end_to_end/page_objects.md
+++ b/doc/development/testing_guide/end_to_end/page_objects.md
@@ -145,7 +145,7 @@ for each element defined.
In our case, `data-qa-selector="login_field"`, `data-qa-selector="password_field"` and `data-qa-selector="sign_in_button"`
-**app/views/my/view.html.haml**
+`app/views/my/view.html.haml`
```haml
= f.text_field :login, class: "form-control top", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required.", data: { qa_selector: 'login_field' }
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 6d6f7fbcf8d..8a929737ebe 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
@@ -14,31 +14,32 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| Tag | Description |
|-----|-------------|
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
+| `:geo` | The test requires two GitLab Geo instances - a primary and a secondary - to be spun up. |
| `:gitaly_cluster` | The test runs against a GitLab instance where repositories are stored on redundant Gitaly nodes behind a Praefect node. All nodes are [separate containers](../../../administration/gitaly/praefect.md#requirements-for-configuring-a-gitaly-cluster). Tests that use this tag have a longer setup time since there are three additional containers that need to be started. |
+| `: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. |
| `: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`._ |
+| `:ldap_no_server` | The test requires a GitLab instance to be configured to use LDAP. To be used with the `:orchestrated` tag. It does not spin up an LDAP server at orchestration time. Instead, it creates the LDAP server at runtime. |
+| `:ldap_no_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS not enabled. |
+| `:ldap_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS enabled. |
+| `:mattermost` | The test requires a GitLab Mattermost service on the GitLab instance. |
+| `:object_storage` | The test requires a GitLab instance to be configured to use multiple [object storage types](../../../administration/object_storage.md). Uses MinIO as the object storage server. |
| `:only` | The test is only to be run against specific environments or pipelines. See [Environment selection](environment_selection.md) for more information. |
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate Docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify the GitLab configuration (for example, Staging). |
+| `:packages` | The test requires a GitLab instance that has the [Package Registry](../../../administration/packages/#gitlab-package-registry-administration) enabled. |
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), runs in a separate job that only includes quarantined tests, and is allowed to fail. The test is skipped in its regular job so that if it fails it doesn't hold up the pipeline. Note that you can also [quarantine a test only when it runs against specific environment](environment_selection.md#quarantining-a-test-for-a-specific-environment). |
+| `:relative_url` | The test requires a GitLab instance to be installed under a [relative URL](../../../install/relative_url.md). |
| `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/guidelines/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. |
+| `:repository_storage` | The test requires a GitLab instance to be configured to use multiple [repository storage paths](../../../administration/repository_storage_paths.md). Paired with the `:orchestrated` tag. |
| `:requires_admin` | The test requires an admin account. Tests with the tag are excluded when run against Canary and Production environments. |
+| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
+| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage . It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
| `:runner` | The test depends on and sets up a GitLab Runner instance, typically to run a pipeline. |
| `:skip_live_env` | The test is excluded when run against live deployed environments such as Staging, Canary, and Production. |
-| `:testcase` | The link to the test case issue in the [Quality Testcases project](https://gitlab.com/gitlab-org/quality/testcases/). |
-| `:mattermost` | The test requires a GitLab Mattermost service on the GitLab instance. |
-| `:ldap_no_server` | The test requires a GitLab instance to be configured to use LDAP. To be used with the `:orchestrated` tag. It does not spin up an LDAP server at orchestration time. Instead, it creates the LDAP server at runtime. |
-| `:ldap_no_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS not enabled. |
-| `:ldap_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS enabled. |
-| `:object_storage` | The test requires a GitLab instance to be configured to use multiple [object storage types](../../../administration/object_storage.md). Uses MinIO as the object storage server. |
-| `:smtp` | The test requires a GitLab instance to be configured to use an SMTP server. Tests SMTP notification email delivery from GitLab by using MailHog. |
-| `: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. |
| `:skip_signup_disabled` | The test uses UI to sign up a new user and is skipped in any environment that does not allow new user registration via the UI. |
| `:smoke` | The test belongs to the test suite which verifies basic functionality of a GitLab instance.|
-| `:github` | The test requires a GitHub personal access token. |
-| `:repository_storage` | The test requires a GitLab instance to be configured to use multiple [repository storage paths](../../../administration/repository_storage_paths.md). Paired with the `:orchestrated` tag. |
-| `:geo` | The test requires two GitLab Geo instances - a primary and a secondary - to be spun up. |
-| `:relative_url` | The test requires a GitLab instance to be installed under a [relative URL](../../../install/relative_url.md). |
-| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
-| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage . It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
-| `:packages` | The test requires a GitLab instance that has the [Package Registry](../../../administration/packages/#gitlab-package-registry-administration) enabled. |
+| `:smtp` | The test requires a GitLab instance to be configured to use an SMTP server. Tests SMTP notification email delivery from GitLab by using MailHog. |
+| `:testcase` | The link to the test case issue in the [Quality Test Cases project](https://gitlab.com/gitlab-org/quality/testcases/). |
+| `:transient` | The test tests transient bugs. It is excluded by default. |
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 cd429a74a2a..b6293ec41b8 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
@@ -75,17 +75,17 @@ When all the containers are running, the output of the `docker ps` command shows
```plaintext
CONTAINER ID ... PORTS NAMES
-d15d3386a0a8 ... 22/tcp, 443/tcp, 0.0.0.0:32772->80/tcp gitlab-gitaly-ha
+d15d3386a0a8 ... 22/tcp, 443/tcp, 0.0.0.0:32772->80/tcp gitlab-gitaly-cluster
```
-That shows that the GitLab instance running in the `gitlab-gitaly-ha` container can be reached via `http://localhost:32772`. However, Git operations like cloning and pushing are performed against the URL revealed via the UI as the clone URL. It uses the hostname configured for the GitLab instance, which in this case matches the Docker container name and network, `gitlab-gitaly-ha.test`. Before you can run the tests you need to configure your computer to access the container via that address. One option is to [use caddyserver as described for running tests against GDK](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/run_qa_against_gdk.md#workarounds).
+That shows that the GitLab instance running in the `gitlab-gitaly-cluster` container can be reached via `http://localhost:32772`. However, Git operations like cloning and pushing are performed against the URL revealed via the UI as the clone URL. It uses the hostname configured for the GitLab instance, which in this case matches the Docker container name and network, `gitlab-gitaly-cluster.test`. Before you can run the tests you need to configure your computer to access the container via that address. One option is to [use Caddy server as described for running tests against GDK](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/run_qa_against_gdk.md#workarounds).
Another option is to use NGINX.
-In both cases you must configure your machine to translate `gitlab-gitlab-ha.test` into an appropriate IP address:
+In both cases you must configure your machine to translate `gitlab-gitaly-cluster.test` into an appropriate IP address:
```shell
-echo '127.0.0.1 gitlab-gitaly-ha.test' | sudo tee -a /etc/hosts
+echo '127.0.0.1 gitlab-gitaly-cluster.test' | sudo tee -a /etc/hosts
```
Then install NGINX:
@@ -101,19 +101,19 @@ apt install nginx
yum install nginx
```
-Finally, configure NGINX to pass requests for `gitlab-gitaly-ha.test` to the GitLab instance:
+Finally, configure NGINX to pass requests for `gitlab-gitaly-cluster.test` to the GitLab instance:
```plaintext
# On Debian/Ubuntu, in /etc/nginx/sites-enabled/gitlab-cluster
# On macOS, in /usr/local/etc/nginx/nginx.conf
server {
- server_name gitlab-gitaly-ha.test;
+ server_name gitlab-gitaly-cluster.test;
client_max_body_size 500m;
location / {
proxy_pass http://127.0.0.1:32772;
- proxy_set_header Host gitlab-gitaly-ha.test;
+ proxy_set_header Host gitlab-gitaly-cluster.test;
}
}
```
@@ -131,14 +131,14 @@ sudo nginx -s reload
You could then run the tests from the `/qa` directory:
```shell
-CHROME_HEADLESS=false bin/qa Test::Instance::All http://gitlab-gitaly-ha.test -- --tag gitaly_ha
+CHROME_HEADLESS=false bin/qa Test::Instance::All http://gitlab-gitaly-cluster.test -- --tag gitaly_cluster
```
Once you have finished testing you can stop and remove the Docker containers:
```shell
-docker stop gitlab-gitaly-ha praefect postgres gitaly3 gitaly2 gitaly1
-docker rm gitlab-gitaly-ha praefect postgres gitaly3 gitaly2 gitaly1
+docker stop gitlab-gitaly-cluster praefect postgres gitaly3 gitaly2 gitaly1
+docker rm gitlab-gitaly-cluster praefect postgres gitaly3 gitaly2 gitaly1
```
## Guide to run and debug Monitor tests
@@ -177,7 +177,7 @@ The following includes more information on the command:
At the moment of this writing, there are two specs which run monitor tests:
--`qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - has the specs of features in GitLab Core
+-`qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - has the specs of features in GitLab Free
-`qa/specs/features/ee/browser_ui/8_monitor/all_monitor_features_spec.rb` - has the specs of features for paid GitLab (Enterprise Edition)
### How to debug
@@ -408,15 +408,15 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r
Tests that are tagged with `:ldap_tls` and `:ldap_no_tls` meta are orchestrated tests where the sign-in happens via LDAP.
-These tests spin up a Docker container [(osixia/openldap)](https://hub.docker.com/r/osixia/openldap) running an instance of [OpenLDAP](https://www.openldap.org/).
-The container uses fixtures [checked into the GitLab-QA repo](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap) to create
+These tests spin up a Docker container [(`osixia/openldap`)](https://hub.docker.com/r/osixia/openldap) running an instance of [OpenLDAP](https://www.openldap.org/).
+The container uses fixtures [checked into the GitLab-QA repository](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap) to create
base data such as users and groups including the admin group. The password for [all users](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap/2_add_users.ldif) including [the `tanuki` user](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap/tanuki.ldif) is `password`.
A GitLab instance is also created in a Docker container based on our [General LDAP setup](../../../administration/auth/ldap/index.md#general-ldap-setup) documentation.
-Tests that are tagged `:ldap_tls` enable TLS on GitLab using the certificate [checked into the GitLab-QA repo](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab).
+Tests that are tagged `:ldap_tls` enable TLS on GitLab using the certificate [checked into the GitLab-QA repository](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab).
-The certificate was generated with openssl using this command:
+The certificate was generated with OpenSSL using this command:
```shell
openssl req -x509 -newkey rsa:4096 -keyout gitlab.test.key -out gitlab.test.crt -days 3650 -nodes -subj "/C=US/ST=CA/L=San Francisco/O=GitLab/OU=Org/CN=gitlab.test"
@@ -432,7 +432,7 @@ To run the LDAP tests on your local with TLS enabled, follow these steps:
`127.0.0.1 gitlab.test`
- You can then run tests against GitLab in a Docker container on `https://gitlab.test`. Please note that the TLS certificate [checked into the GitLab-QA repo](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab) is configured for this domain.
+ You can then run tests against GitLab in a Docker container on `https://gitlab.test`. Please note that the TLS certificate [checked into the GitLab-QA repository](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab) is configured for this domain.
1. Run the OpenLDAP container with TLS enabled. Change the path to [`gitlab-qa/fixtures/ldap`](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap) directory to your local checkout path:
```shell
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 94bc80abcdb..73fce3a38d7 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -31,7 +31,7 @@ Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE.
## Karma test suite
While GitLab has switched over to [Jest](https://jestjs.io), Karma tests still exist in our
-application because some of our specs require a browser and can't be easiliy migrated to Jest.
+application because some of our specs require a browser and can't be easily migrated to Jest.
Those specs intend to eventually drop Karma in favor of either Jest or RSpec. You can track this migration
in the [related epic](https://gitlab.com/groups/gitlab-org/-/epics/4900).
@@ -258,7 +258,7 @@ it('exists', () => {
### Naming unit tests
When writing describe test blocks to test specific functions/methods,
-please use the method name as the describe block name.
+use the method name as the describe block name.
**Bad**:
@@ -439,7 +439,7 @@ it('waits for an Ajax call', done => {
});
```
-If you are not able to register handlers to the `Promise`, for example because it is executed in a synchronous Vue life cycle hook, please take a look at the [waitFor](#wait-until-axios-requests-finish) helpers or you can flush all pending `Promise`s:
+If you are not able to register handlers to the `Promise`, for example because it is executed in a synchronous Vue life cycle hook, take a look at the [waitFor](#wait-until-axios-requests-finish) helpers or you can flush all pending `Promise`s:
**in Jest:**
@@ -548,8 +548,12 @@ In order to ensure that a clean wrapper object and DOM are being used in each te
});
```
+<!-- vale gitlab.Spelling = NO -->
+
See also the [Vue Test Utils documentation on `destroy`](https://vue-test-utils.vuejs.org/api/wrapper/#destroy).
+<!-- vale gitlab.Spelling = YES -->
+
### Jest best practices
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34209) in GitLab 13.2.
@@ -646,20 +650,46 @@ The latter is useful when you have `setInterval` in the code. **Remember:** our
Non-determinism is the breeding ground for flaky and brittle specs. Such specs end up breaking the CI pipeline, interrupting the work flow of other contributors.
-1. Make sure your test subject's collaborators (e.g., axios, apollo, lodash helpers) and test environment (e.g., Date) behave consistently across systems and over time.
+1. Make sure your test subject's collaborators (e.g., Axios, apollo, Lodash helpers) and test environment (e.g., Date) behave consistently across systems and over time.
1. Make sure tests are focused and not doing "extra work" (e.g., needlessly creating the test subject more than once in an individual test)
### Faking `Date` for determinism
-Consider using `useFakeDate` to ensure a consistent value is returned with every `new Date()` or `Date.now()`.
+`Date` is faked by default in our Jest environment. This means every call to `Date()` or `Date.now()` returns a fixed deterministic value.
+
+If you really need to change the default fake date, you can call `useFakeDate` within any `describe` block, and
+the date will be replaced for that specs within that `describe` context only:
```javascript
import { useFakeDate } from 'helpers/fake_date';
describe('cool/component', () => {
- useFakeDate();
+ // Default fake `Date`
+ const TODAY = new Date();
- // ...
+ // NOTE: `useFakeDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.).
+ describe("on Ada Lovelace's Birthday", () => {
+ useFakeDate(1815, 11, 10)
+
+ it('Date is no longer default', () => {
+ expect(new Date()).not.toEqual(TODAY);
+ });
+ });
+
+ it('Date is still default in this scope', () => {
+ expect(new Date()).toEqual(TODAY)
+ });
+})
+```
+
+Similarly, if you really need to use the real `Date` class, then you can import and call `useRealDate` within any `describe` block:
+
+```javascript
+import { useRealDate } from 'helpers/fake_date';
+
+// NOTE: `useRealDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.).
+describe('with real date', () => {
+ useRealDate();
});
```
@@ -702,10 +732,10 @@ unit testing by mocking out modules which cannot be easily consumed in our test
Jest supports [manual module mocks](https://jestjs.io/docs/en/manual-mocks) by placing a mock in a `__mocks__/` directory next to the source module
(e.g. `app/assets/javascripts/ide/__mocks__`). **Don't do this.** We want to keep all of our test-related code in one place (the `spec/` folder).
-If a manual mock is needed for a `node_modules` package, please use the `spec/frontend/__mocks__` folder. Here's an example of
+If a manual mock is needed for a `node_modules` package, use the `spec/frontend/__mocks__` folder. Here's an example of
a [Jest mock for the package `monaco-editor`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1).
-If a manual mock is needed for a CE module, please place it in `spec/frontend/mocks/ce`.
+If a manual mock is needed for a CE module, place it in `spec/frontend/mocks/ce`.
- Files in `spec/frontend/mocks/ce` mocks the corresponding CE module from `app/assets/javascripts`, mirroring the source module's path.
- Example: `spec/frontend/mocks/ce/lib/utils/axios_utils` mocks the module `~/lib/utils/axios_utils`.
@@ -728,11 +758,11 @@ If a manual mock is needed for a CE module, please place it in `spec/frontend/mo
Global mocks introduce magic and technically can reduce test coverage. When mocking is deemed profitable:
- Keep the mock short and focused.
-- Please leave a top-level comment in the mock on why it is necessary.
+- Leave a top-level comment in the mock on why it is necessary.
### Additional mocking techniques
-Please consult the [official Jest docs](https://jestjs.io/docs/en/jest-object#mock-modules) for a full overview of the available mocking features.
+Consult the [official Jest docs](https://jestjs.io/docs/en/jest-object#mock-modules) for a full overview of the available mocking features.
## Running Frontend Tests
@@ -807,7 +837,7 @@ yarn karma -f 'spec/javascripts/ide/**/file_spec.js'
## Frontend test fixtures
Frontend fixtures are files containing responses from backend controllers. These responses can be either HTML
-generated from haml templates or JSON payloads. Frontend tests that rely on these responses are
+generated from HAML templates or JSON payloads. Frontend tests that rely on these responses are
often using fixtures to validate correct integration with the backend code.
### Generate fixtures
@@ -865,7 +895,7 @@ end
This will create a new fixture located at
`tmp/tests/frontend/fixtures-ee/graphql/releases/queries/all_releases.query.graphql.json`.
-Note that you will need to provide the paths to all fragments used by the query.
+You will need to provide the paths to all fragments used by the query.
`get_graphql_query_as_string` reads all of the provided file paths and returns
the result as a single, concatenated string.
@@ -929,7 +959,8 @@ it.each([
);
```
-**Note**: only use template literal block if pretty print is **not** needed for spec output. For example, empty strings, nested objects etc.
+NOTE:
+Only use template literal block if pretty print is not needed for spec output. For example, empty strings, nested objects etc.
For example, when testing the difference between an empty search string and a non-empty search string, the use of the array block syntax with the pretty print option would be preferred. That way the differences between an empty string e.g. `''` and a non-empty string e.g. `'search string'` would be visible in the spec output. Whereas with a template literal block, the empty string would be shown as a space, which could lead to a confusing developer experience
@@ -1038,9 +1069,10 @@ import Subject from '~/feature/the_subject.vue';
import _Thing from '~/feature/path/to/thing.vue';
```
-**PLEASE NOTE:** Do not simply disregard test timeouts. This could be a sign that there's
+NOTE:
+Do not disregard test timeouts. This could be a sign that there's
actually a production problem. Use this opportunity to analyze the production webpack bundles and
-chunks and confirm that there is not a production issue with the async imports.
+chunks and confirm that there is not a production issue with the asynchronous imports.
## Overview of Frontend Testing Levels
@@ -1063,7 +1095,7 @@ See also [Notes on testing Vue components](../fe_guide/vue.md#testing-vue-compon
## Test helpers
Test helpers can be found in [`spec/frontend/__helpers__`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/__helpers__).
-If you introduce new helpers, please place them in that directory.
+If you introduce new helpers, place them in that directory.
### Vuex Helper: `testAction`
@@ -1090,9 +1122,13 @@ Check an example in [`spec/frontend/ide/stores/actions_spec.js`](https://gitlab.
### Wait until Axios requests finish
+<!-- vale gitlab.Spelling = NO -->
+
The Axios Utils mock module located in `spec/frontend/mocks/ce/lib/utils/axios_utils.js` contains two helper methods for Jest tests that spawn HTTP requests.
These are very useful if you don't have a handle to the request's Promise, for example when a Vue component does a request as part of its life cycle.
+<!-- vale gitlab.Spelling = YES -->
+
- `waitFor(url, callback)`: Runs `callback` after a request to `url` finishes (either successfully or unsuccessfully).
- `waitForAll(callback)`: Runs `callback` once all pending requests have finished. If no requests are pending, runs `callback` on the next tick.
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index 68326879dd0..c22a4e0b3ad 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -9,9 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
This document describes various guidelines and best practices for automated
testing of the GitLab project.
-It is meant to be an _extension_ of the [thoughtbot testing
+It is meant to be an _extension_ of the [Thoughtbot testing
style guide](https://github.com/thoughtbot/guides/tree/master/testing-rspec). If
-this guide defines a rule that contradicts the thoughtbot guide, this guide
+this guide defines a rule that contradicts the Thoughtbot guide, this guide
takes precedence. Some guidelines may be repeated verbatim to stress their
importance.
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index a5294be40a9..f1c74f990cb 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -186,9 +186,9 @@ the GitLab handbook information for the [shared 1Password account](https://about
### Find my Review App slug
1. Open the `review-deploy` job.
-1. Look for `Checking for previous deployment of review-*`.
-1. For instance for `Checking for previous deployment of review-qa-raise-e-12chm0`,
- your Review App slug would be `review-qa-raise-e-12chm0` in this case.
+1. Look for `** Deploying review-*`.
+1. For instance for `** Deploying review-1234-abc-defg... **`,
+ your Review App slug would be `review-1234-abc-defg` in this case.
### Run a Rails console
@@ -357,7 +357,7 @@ using `v232`.
For the record, the debugging steps to find out this issue were:
-1. Switch kubectl context to review-apps-ce (we recommend using [kubectx](https://github.com/ahmetb/kubectx/))
+1. Switch kubectl context to `review-apps-ce` (we recommend using [`kubectx`](https://github.com/ahmetb/kubectx/))
1. `kubectl get pods | grep dns`
1. `kubectl describe pod <pod name>` & confirm exact error message
1. Web search for exact error message, following rabbit hole to [a relevant Kubernetes bug report](https://github.com/kubernetes/kubernetes/issues/57345)
diff --git a/doc/development/testing_guide/testing_migrations_guide.md b/doc/development/testing_guide/testing_migrations_guide.md
index 31054d0ffb2..d54ca0d3c64 100644
--- a/doc/development/testing_guide/testing_migrations_guide.md
+++ b/doc/development/testing_guide/testing_migrations_guide.md
@@ -32,7 +32,7 @@ migrate the database **down** to the previous migration version.
With this approach you can test a migration against a database schema.
-An `after` hook migrates the database **up** and reinstitutes the latest
+An `after` hook migrates the database **up** and restores the latest
schema version, so that the process does not affect subsequent specs and
ensures proper isolation.
diff --git a/doc/development/transient/prevention-patterns.md b/doc/development/transient/prevention-patterns.md
new file mode 100644
index 00000000000..4c1e4d373e7
--- /dev/null
+++ b/doc/development/transient/prevention-patterns.md
@@ -0,0 +1,141 @@
+---
+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
+---
+
+# Preventing Transient Bugs
+
+This page will cover architectural patterns and tips for developers to follow to prevent [transient bugs.](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#transient-bugs)
+
+## Common root causes
+
+We've noticed a few root causes that come up frequently when addressing transient bugs.
+
+- Needs better state management in the backend or frontend.
+- Frontend code needs improvements.
+- Lack of test coverage.
+- Race conditions.
+
+## Frontend
+
+### Don't rely on response order
+
+When working with multiple requests, it's easy to assume the order of the responses will match the order in which they are triggered.
+
+That's not always the case and can cause bugs that only happen if the order is switched.
+
+**Example:**
+
+- `diffs_metadata.json` (lighter)
+- `diffs_batch.json` (heavier)
+
+If your feature requires data from both, ensure that the two have finished loading before working on it.
+
+### Simulate slower connections when testing manually
+
+Add a network condition template to your browser's developer tools to enable you to toggle between a slow and a fast connection.
+
+**Example:**
+
+- Turtle:
+ - Down: 50kb/s
+ - Up: 20kb/s
+ - Latency: 10000ms
+
+### Collapsed elements
+
+When setting event listeners, if not possible to use event delegation, ensure all relevant event listeners are set for expanded content.
+
+Including when that expanded content is:
+
+- **Invisible** (`display: none;`). Some JavaScript requires the element to be visible to work properly, such as when taking measurements.
+- **Dynamic content** (AJAX/DOM manipulation).
+
+### Using assertions to detect transient bugs caused by unmet conditions
+
+Transient bugs happen in the context of code that executes under the assumption
+that the application’s state meets one or more conditions. We may write a feature
+that assumes a server-side API response always include a group of attributes or that
+an operation only executes when the application has successfully transitioned to a new
+state.
+
+Transient bugs are difficult to debug because there isn’t any mechanism that alerts
+the user or the developer about unsatisfied conditions. These conditions are usually
+not expressed explicitly in the code. A useful debugging technique for such situations
+is placing assertions to make any assumption explicit. They can help detect the cause
+which unmet condition causes the bug.
+
+#### Asserting pre-conditions on state mutations
+
+A common scenario that leads to transient bugs is when there is a polling service
+that should mutate state only if a user operation is completed. We can use
+assertions to make this pre-condition explicit:
+
+```javascript
+// This action is called by a polling service. It assumes that all pre-conditions
+// are satisfied by the time the action is dispatched.
+export const updateMergeableStatus = ({ commit }, payload) => {
+ commit(types.SET_MERGEABLE_STATUS, payload);
+};
+
+// We can make any pre-condition explicit by adding an assertion
+export const updateMergeableStatus = ({ state, commit }, payload) => {
+ console.assert(
+ state.isResolvingDiscussion === true,
+ 'Resolve discussion request must be completed before updating mergeable status'
+ );
+ commit(types.SET_MERGEABLE_STATUS, payload);
+};
+```
+
+#### Asserting API contracts
+
+Another useful way of using assertions is to detect if the response payload returned
+by the server-side endpoint satisfies the API contract.
+
+#### Related reading
+
+[Debug it!](https://pragprog.com/titles/pbdp/debug-it/) explores techniques to diagnose
+and fix non-determinstic bugs and write software that is easier to debug.
+
+## Backend
+
+### Sidekiq jobs with locks
+
+When dealing with asynchronous work via Sidekiq, it is possible to have 2 jobs with the same arguments
+getting worked on at the same time. If not handled correctly, this can result in an outdated or inaccurate state.
+
+For instance, consider a worker that updates a state of an object. Before the worker updates the state
+(for example, `#update_state`) of the object, it needs to check what the appropriate state should be
+(for example, `#check_state`).
+
+When there are 2 jobs being worked on at the same time, it is possible that the order of operations will go like:
+
+1. (Worker A) Calls `#check_state`
+1. (Worker B) Calls `#check_state`
+1. (Worker B) Calls `#update_state`
+1. (Worker A) Calls `#update_state`
+
+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).
+
+### Retry mechanism handling
+
+There are times that an object/record will be on a failed state which can be rechecked.
+
+If an object is in a state that can be rechecked, ensure that appropriate messaging is shown to the user
+so they know what to do. Also, make sure that the retry functionality will be able to reset the state
+correctly when triggered.
+
+### Error Logging
+
+Error logging doesn't necessarily directly prevents transient bugs but it can help to debug them.
+
+When coding, sometimes we expect some exceptions to be raised and we rescue them.
+
+Logging whenever we rescue an error helps in case it's causing transient bugs that a user may see.
+While investigating a bug report, it may require the engineer to look into logs of when it happened.
+Seeing an error being logged can be a signal of something that went wrong which can be handled differently.
diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ui_guide.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/usage_ping.md b/doc/development/usage_ping.md
index 10c3de2f0a1..3618d18b1bb 100644
--- a/doc/development/usage_ping.md
+++ b/doc/development/usage_ping.md
@@ -6,10 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Usage Ping Guide
-> - Introduced in GitLab Enterprise Edition 8.10.
-> - More statistics were added in GitLab Enterprise Edition 8.12.
-> - Moved to GitLab Core in 9.1.
-> - More statistics were added in GitLab Ultimate 11.2.
+> Introduced in GitLab Ultimate 11.2, more statistics.
This guide describes Usage Ping's purpose and how it's implemented.
@@ -122,6 +119,60 @@ sequenceDiagram
the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`,
the required URL is <https://version.gitlab.com/>.
+## Usage Ping Metric Life cycle
+
+### 1. New metrics addition
+
+Please follow the [Implementing Usage Ping](#implementing-usage-ping) guide.
+
+### 2. Existing metric change
+
+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.
+If there is a problem with an existing metric, it's best to deprecate the existing metric,
+and use it, side by side, with the desired new metric.
+
+Example:
+Consider following change. Before GitLab 12.6, the `example_metric` was implemented as:
+
+```ruby
+{
+ ...
+ example_metric: distinct_count(Project, :creator_id)
+}
+```
+
+For GitLab 12.6, the metric was changed to filter out archived projects:
+
+```ruby
+{
+ ...
+ example_metric: distinct_count(Project.non_archived, :creator_id)
+}
+```
+
+In this scenario all instances running up to GitLab 12.5 continue to report `example_metric`,
+including all archived projects, while all instances running GitLab 12.6 and higher filters
+out such projects. As Usage Ping data is collected from all reporting instances, the
+resulting dataset includes mixed data, which distorts any following business analysis.
+
+The correct approach is to add a new metric for GitLab 12.6 release with updated logic:
+
+```ruby
+{
+ ...
+ example_metric_without_archived: distinct_count(Project.non_archived, :creator_id)
+}
+```
+
+and update existing business analysis artefacts to use `example_metric_without_archived` instead of `example_metric`
+
+### 3. Metrics deprecation and removal
+
+The process for deprecating and removing metrics is currently under development. For
+more information, see the following [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284637).
+
## Implementing Usage Ping
Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event
@@ -175,9 +226,9 @@ Arguments:
- `relation` the ActiveRecord_Relation to perform the count
- `column` the column to perform the count on, by default is the primary key
-- `batch`: default `true` in order to use batch counting
-- `start`: custom start of the batch counting in order to avoid complex min calculations
-- `end`: custom end of the batch counting in order to avoid complex min calculations
+- `batch`: default `true` to use batch counting
+- `start`: custom start of the batch counting to avoid complex min calculations
+- `end`: custom end of the batch counting to avoid complex min calculations
Examples:
@@ -199,10 +250,10 @@ Arguments:
- `relation` the ActiveRecord_Relation to perform the count
- `column` the column to perform the distinct count, by default is the primary key
-- `batch`: default `true` in order to use batch counting
+- `batch`: default `true` to use batch counting
- `batch_size`: if none set it uses default value 10000 from `Gitlab::Database::BatchCounter`
-- `start`: custom start of the batch counting in order to avoid complex min calculations
-- `end`: custom end of the batch counting in order to avoid complex min calculations
+- `start`: custom start of the batch counting to avoid complex min calculations
+- `end`: custom end of the batch counting to avoid complex min calculations
WARNING:
Counting over non-unique columns can lead to performance issues. Take a look at the [iterating tables in batches](iterating_tables_in_batches.md) guide for more details.
@@ -228,8 +279,8 @@ Arguments:
- `relation` the ActiveRecord_Relation to perform the operation
- `column` the column to sum on
- `batch_size`: if none set it uses default value 1000 from `Gitlab::Database::BatchCounter`
-- `start`: custom start of the batch counting in order to avoid complex min calculations
-- `end`: custom end of the batch counting in order to avoid complex min calculations
+- `start`: custom start of the batch counting to avoid complex min calculations
+- `end`: custom end of the batch counting to avoid complex min calculations
Examples:
@@ -281,7 +332,7 @@ The method includes the following arguments:
- `column`: The column to perform the distinct count. The default is the primary key.
- `batch_size`: The default is 10,000, from `Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE`.
- `start`: The custom start of the batch count, to avoid complex minimum calculations.
-- `finish`: The custom end of the batch count in order to avoid complex maximum calculations.
+- `finish`: The custom end of the batch count to avoid complex maximum calculations.
The method includes the following prerequisites:
@@ -364,7 +415,7 @@ Examples of implementation:
API requests are protected by checking for a valid CSRF token.
- In order to be able to increment the values the related feature `usage_data_<event_name>` should be enabled.
+ To be able to increment the values, the related feature `usage_data_<event_name>` should be enabled.
```plaintext
POST /usage_data/increment_counter
@@ -383,7 +434,7 @@ Examples of implementation:
1. Track events using JavaScript/Vue API helper which calls the API above
- Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled in order to be able to track events
+ Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled to be able to track events
```javascript
import api from '~/api';
@@ -429,7 +480,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
- `a_` for events encompassing all `g_`, `p_`, `i_`.
- `o_` for other.
- Consider including in the event's name the Redis slot in order to be able to count totals for a specific category.
+ Consider including in the event's name the Redis slot to be able to count totals for a specific category.
Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`.
@@ -444,16 +495,17 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
aggregation.
- `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis.
Aggregation on a `daily` basis does not pull more fine grained data.
- - `feature_flag`: optional. For details, see our [GitLab internal Feature flags](feature_flags/) documentation.
+ - `feature_flag`: optional `default_enabled: :yaml`. If no feature flag is set then the tracking is enabled. For details, see our [GitLab internal Feature flags](feature_flags/) documentation. The feature flags are owned by the group adding the event tracking.
+
+Use one of the following methods to track events:
-1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`.
+1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, if: nil)`.
Arguments:
- `controller_actions`: controller actions we want to track.
- `name`: event name.
- - `feature`: feature name, all metrics we track should be under feature flag.
- - `feature_default_enabled`: feature flag is disabled by default, set to `true` for it to be enabled by default.
+ - `if`: optional custom conditions, using the same format as with Rails callbacks.
Example usage:
@@ -463,7 +515,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
include RedisTracking
skip_before_action :authenticate_user!, only: :show
- track_redis_hll_event :index, :show, name: 'g_compliance_example_feature_visitors', feature: :compliance_example_feature, feature_default_enabled: true
+ track_redis_hll_event :index, :show, name: 'g_compliance_example_feature_visitors'
def index
render html: 'index'
@@ -481,7 +533,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
1. Track event in API using `increment_unique_values(event_name, values)` helper method.
- In order to be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled.
+ To be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled.
Arguments:
@@ -508,9 +560,9 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
Example:
- [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/issues/update_service.rb)
+ [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/app/services/issues/update_service.rb#L66)
- [Track usage event for incident created in GraphQL](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/alert_management/update_alert_status.rb)
+ [Track usage event for incident created in GraphQL](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/app/graphql/mutations/alert_management/update_alert_status.rb#L16)
```ruby
track_usage_event(:incident_management_incident_created, current_user.id)
@@ -526,7 +578,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
API requests are protected by checking for a valid CSRF token.
- In order to increment the values, the related feature `usage_data_<event_name>` should be
+ To increment the values, the related feature `usage_data_<event_name>` should be
set to `default_enabled: true`. For more information, see
[Feature flags in development of GitLab](feature_flags/index.md).
@@ -562,21 +614,6 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
api.trackRedisHllUserEvent('my_already_defined_event_name'),
```
-1. Track event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values:)`.
-
- Arguments:
-
- - `event_name`: event name.
- - `values`: One value or array of values we count. For example: user_id, visitor_id, user_ids.
-
-1. Track event on context level using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event_in_context(event_name, values:, context:)`.
-
- Arguments:
-
- - `event_name`: event name.
- - `values`: values we count. For example: user_id, visitor_id.
- - `context`: context value. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`
-
1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date:, context: '')`.
Arguments:
@@ -600,7 +637,7 @@ Next, get the unique events for the current week.
```ruby
# Get unique events for metric for current_week
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_audit_events',
- start_date: Date.current.beginning_of_week, end_date: Date.current.end_of_week)
+ start_date: Date.current.beginning_of_week, end_date: Date.current.next_week)
```
##### Recommendations
@@ -780,7 +817,7 @@ Paste the SQL query into `#database-lab` to see how the query performs at scale.
- Any single query must stay below [1 second execution time](query_performance.md#timing-guidelines-for-queries) with cold caches.
- Add a specialized index on columns involved to reduce the execution time.
-In order to have an understanding of the query's execution we add in the MR description the following information:
+To have an understanding of the query's execution we add in the MR description the following information:
- For counters that have a `time_period` test we add information for both cases:
- `time_period = {}` for all time periods
@@ -839,16 +876,16 @@ There are currently three kinds of components that may export data to Prometheus
This is the recommended approach to test Prometheus based Usage Ping.
-The easiest way to verify your changes is to build a new Omnibus image from your code branch via CI, then download the image
+The easiest way to verify your changes is to build a new Omnibus image from your code branch by using CI, then download the image
and run a local container instance:
1. From your merge request, click on the `qa` stage, then trigger the `package-and-qa` job. This job triggers an Omnibus
build in a [downstream pipeline of the `omnibus-gitlab-mirror` project](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines).
1. In the downstream pipeline, wait for the `gitlab-docker` job to finish.
1. Open the job logs and locate the full container name including the version. It takes the following form: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`.
-1. On your local machine, make sure you are logged in to the GitLab Docker registry. You can find the instructions for this in
+1. On your local machine, make sure you are signed in to the GitLab Docker registry. You can find the instructions for this in
[Authenticate to the GitLab Container Registry](../user/packages/container_registry/index.md#authenticate-with-the-container-registry).
-1. Once logged in, download the new image via `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`
+1. Once signed in, download the new image by using `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`
1. For more information about working with and running Omnibus GitLab containers in Docker, please refer to [GitLab Docker images](https://docs.gitlab.com/omnibus/docker/README.html) in the Omnibus documentation.
#### Test with GitLab development toolkits
@@ -875,7 +912,7 @@ appear to be associated to any of the services running, since they all appear to
WARNING:
This feature is intended solely for internal GitLab use.
-In order to add data for aggregated metrics into Usage Ping payload you should add corresponding definition in [`aggregated_metrics`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/). Each aggregate definition includes following parts:
+To add data for aggregated metrics into Usage Ping payload you should add corresponding definition in [`aggregated_metrics`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/). Each aggregate definition includes following parts:
- name: unique name under which aggregate metric is added to Usage Ping payload
- operator: operator that defines how aggregated metric data is counted. Available operators are:
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
new file mode 100644
index 00000000000..ca3e0f1aae6
--- /dev/null
+++ b/doc/development/usage_ping/dictionary.md
@@ -0,0 +1,887 @@
+---
+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/#designated-technical-writers
+---
+
+<!---
+ This documentation is auto generated by a script.
+
+ Please do not edit this file directly, check generate_metrics_dictionary task on lib/tasks/gitlab/usage_data.rake.
+--->
+
+<!-- vale gitlab.Spelling = NO -->
+
+# Metrics Dictionary
+
+This file is autogenerated, please do not edit directly.
+
+To generate these files from the GitLab repository, run:
+
+```shell
+bundle exec rake gitlab:usage_data:generate_metrics_dictionary
+```
+
+The Metrics Dictionary is based on the following metrics definition YAML files:
+
+- [`config/metrics`]('https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics')
+- [`ee/config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/metrics)
+Each table includes a `milestone`, which corresponds to the GitLab version when the metric
+was released.
+
+## `active_user_count`
+
+This is named the instance_user_count in the Versions application.
+
+| field | value |
+| --- | --- |
+| `key_path` | **`active_user_count`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | Database |
+| `distribution` | ce, ee |
+| `tier` | free, premium, ultimate |
+| `skip_validation` | true |
+
+## `container_registry_enabled`
+
+Whether container registry is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`container_registry_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `counts.deployments`
+
+Total deployments count
+
+| field | value |
+| --- | --- |
+| `key_path` | **`counts.deployments`** |
+| `product_section` | ops |
+| `product_stage` | release |
+| `product_group` | `group::ops release` |
+| `value_type` | number |
+| `status` | data_available |
+| `milestone` | 8.12 |
+| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/735) |
+| `time_frame` | all |
+| `data_source` | Database |
+| `distribution` | ee, ce |
+| `tier` | free, premium, ultimate |
+
+## `counts.geo_nodes`
+
+Total number of sites in a Geo deployment
+
+| field | value |
+| --- | --- |
+| `key_path` | **`counts.geo_nodes`** |
+| `product_section` | enablement |
+| `product_stage` | enablement |
+| `product_group` | `group::geo` |
+| `product_category` | disaster_recovery |
+| `value_type` | integer |
+| `status` | data_available |
+| `milestone` | 11.2 |
+| `time_frame` | all |
+| `data_source` | Database |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+
+## `counts.license_management_jobs`
+
+Name on the GitLab license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`counts.license_management_jobs`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | number |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | Database |
+| `distribution` | |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `counts_monthly.deployments`
+
+Total deployments count for recent 28 days
+
+| field | value |
+| --- | --- |
+| `key_path` | **`counts_monthly.deployments`** |
+| `product_section` | ops |
+| `product_stage` | release |
+| `product_group` | `group::ops release` |
+| `product_category` | |
+| `value_type` | number |
+| `status` | data_available |
+| `milestone` | 13.2 |
+| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35493) |
+| `time_frame` | 28d |
+| `data_source` | Database |
+| `distribution` | ee, ce |
+| `tier` | free, premium, ultimate |
+
+## `database.adapter`
+
+This metric only returns a value of PostgreSQL in supported versions of GitLab. It could be removed from the usage ping. Historically MySQL was also supported.
+
+| field | value |
+| --- | --- |
+| `key_path` | **`database.adapter`** |
+| `product_section` | enablement |
+| `product_stage` | enablement |
+| `product_group` | `group::enablement distribution` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | Database |
+| `distribution` | ee, ce |
+| `tier` | free, premium, ultimate |
+
+## `dependency_proxy_enabled`
+
+Whether dependency proxy is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`dependency_proxy_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `elasticsearch_enabled`
+
+Whether Elasticsearch is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`elasticsearch_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gitaly.clusters`
+
+Total GitLab Managed clusters both enabled and disabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gitaly.clusters`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | number |
+| `status` | data_available |
+| `time_frame` | all |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gitaly.servers`
+
+Total Gitalty Servers
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gitaly.servers`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | number |
+| `status` | data_available |
+| `time_frame` | all |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gitaly.version`
+
+Version of Gitaly
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gitaly.version`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gitlab_pages.enabled`
+
+Whether GitLab Pages is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gitlab_pages.enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gitlab_pages.version`
+
+The version number of GitLab Pages
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gitlab_pages.version`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gitlab_shared_runners_enabled`
+
+Whether shared runners is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gitlab_shared_runners_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `grafana_link_enabled`
+
+Whether Grafana is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`grafana_link_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `gravatar_enabled`
+
+Whether gravatar is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`gravatar_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `historical_max_users`
+
+The maximum active user count. Active is defined in UsersStatistics model.
+
+| field | value |
+| --- | --- |
+| `key_path` | **`historical_max_users`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `hostname`
+
+Host name of GitLab instance
+
+| field | value |
+| --- | --- |
+| `key_path` | **`hostname`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ce, ee |
+| `tier` | free, premium, ultimate |
+| `skip_validation` | true |
+
+## `instance_auto_devops_enabled`
+
+Whether auto DevOps is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`instance_auto_devops_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `ldap_enabled`
+
+Whether LDAP is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`ldap_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `license_expires_at`
+
+The date the license ends
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_expires_at`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `license_id`
+
+The ID of the license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_id`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `license_md5`
+
+The license key of the GitLab instance
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_md5`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | free, premium, ultimate |
+| `skip_validation` | true |
+
+## `license_plan`
+
+The plan of the GitLab license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_plan`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `license_starts_at`
+
+The date the license starts
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_starts_at`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `license_subscription_id`
+
+Licese zuora_subscription_id
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_subscription_id`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `license_trial`
+
+Whether this is a trial license or not
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_trial`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `license_trial_ends_on`
+
+Date the license ends on
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_trial_ends_on`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `license_user_count`
+
+The number of users included in the license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`license_user_count`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | Database |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `licensee.Company`
+
+Company on the GitLab license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`licensee.Company`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `licensee.Email`
+
+Email on the GitLab license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`licensee.Email`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `licensee.Name`
+
+Name on the GitLab license
+
+| field | value |
+| --- | --- |
+| `key_path` | **`licensee.Name`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | premium, ultimate |
+| `skip_validation` | true |
+
+## `mattermost_enabled`
+
+Whether Mattermost is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`mattermost_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `omniauth_enabled`
+
+Whether OmniAuth is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`omniauth_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `prometheus_enabled`
+
+Whether the bundled Prometheus is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`prometheus_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `prometheus_metrics_enabled`
+
+Whether Prometheus Metrics endpoint is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`prometheus_metrics_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `recorded_at`
+
+When the Usage Ping computation was started
+
+| field | value |
+| --- | --- |
+| `key_path` | **`recorded_at`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `milestone` | 8.1 |
+| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/557) |
+| `time_frame` | none |
+| `data_source` | Ruby |
+| `distribution` | ee, ce |
+| `tier` | free, premium, ultimate |
+
+## `recording_ce_finished_at`
+
+When the core features were computed
+
+| field | value |
+| --- | --- |
+| `key_path` | **`recording_ce_finished_at`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ce, ee |
+| `tier` | |
+| `skip_validation` | true |
+
+## `recording_ee_finished_at`
+
+When the EE-specific features were computed
+
+| field | value |
+| --- | --- |
+| `key_path` | **`recording_ee_finished_at`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | ee |
+| `tier` | |
+| `skip_validation` | true |
+
+## `redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly`
+
+Distinct users count that changed issue title in a group for last recent week
+
+| field | value |
+| --- | --- |
+| `key_path` | **`redis_hll_counters.issues_edit.g_project_management_issue_title_changed_weekly`** |
+| `product_stage` | plan |
+| `product_group` | `group::project management` |
+| `product_category` | issue_tracking |
+| `value_type` | number |
+| `status` | data_available |
+| `milestone` | 13.6 |
+| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/issues/229918) |
+| `time_frame` | 7d |
+| `data_source` | Redis_hll |
+| `distribution` | ee, ce |
+| `tier` | free, premium, ultimate |
+
+## `reply_by_email_enabled`
+
+Whether incoming email is setup
+
+| field | value |
+| --- | --- |
+| `key_path` | **`reply_by_email_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `signup_enabled`
+
+Whether public signup is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`signup_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
+
+## `uuid`
+
+GitLab instance unique identifier
+
+| field | value |
+| --- | --- |
+| `key_path` | **`uuid`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | string |
+| `status` | data_available |
+| `milestone` | 9.1 |
+| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521) |
+| `time_frame` | none |
+| `data_source` | Database |
+| `distribution` | ee, ce |
+| `tier` | free, premium, ultimate |
+
+## `web_ide_clientside_preview_enabled`
+
+Whether web ide clientside preview is enabled
+
+| field | value |
+| --- | --- |
+| `key_path` | **`web_ide_clientside_preview_enabled`** |
+| `product_section` | growth |
+| `product_stage` | growth |
+| `product_group` | `group::product intelligence` |
+| `product_category` | collection |
+| `value_type` | boolean |
+| `status` | data_available |
+| `time_frame` | none |
+| `data_source` | |
+| `distribution` | |
+| `tier` | |
+| `skip_validation` | true |
diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md
index bae79689f3b..406a223b204 100644
--- a/doc/development/usage_ping/metrics_dictionary.md
+++ b/doc/development/usage_ping/metrics_dictionary.md
@@ -14,38 +14,33 @@ We are using [JSON Schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/co
This process is meant to ensure consistent and valid metrics defined for Usage Ping. All metrics *must*:
-- Comply with the definied [JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/schema.json).
-- Have a unique `full_path` .
+- Comply with the defined [JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/schema.json).
+- Have a unique `key_path` .
- Have an owner.
All metrics are stored in YAML files:
- [`config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics)
-Each metric is definied in a separate YAML file consisting of a number of fields:
+Each metric is defined in a separate YAML file consisting of a number of fields:
| Field | Required | Additional information |
|---------------------|----------|----------------------------------------------------------------|
-| `name` | yes | |
+| `key_path` | yes | JSON key path for the metric, location in Usage Ping payload. |
| `description` | yes | |
| `value_type` | yes | |
| `status` | yes | |
-| `default_generation`| yes | Default generation path of the metric. One full_path value. (1) |
-| `full_path` | yes | Full path of the metric for one or multiple generations. Path of the metric in Usage Ping payload. (1) |
-| `group` | yes | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the metric. |
+| `product_group` | yes | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the metric. |
| `time_frame` | yes | `string`; may be set to a value like "7d" |
| `data_source` | yes | `string`: may be set to a value like `database` or `redis_hll`. |
| `distribution` | yes | The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the metric applies. |
| `tier` | yes | The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the metric applies. |
| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. |
-| `stage` | no | The [stage](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) for the metric. |
+| `product_stage` | no | The [stage](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) for the metric. |
| `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. |
-1. The default generation path is the location of the metric in the Usage Ping payload.
- The `full_path` is the list locations for multiple Usage Ping generaations.
-
### Example metric definition
The linked [`uuid`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/uuid.yml)
@@ -53,21 +48,46 @@ YAML file includes an example metric definition, where the `uuid` metric is the
instance unique identifier.
```yaml
-name: uuid
+key_path: uuid
description: GitLab instance unique identifier
value_type: string
product_category: collection
-stage: growth
+product_stage: growth
status: data_available
-default_generation: generation_1
-full_path:
- generation_1: uuid
- generation_2: license.uuid
milestone: 9.1
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521
-group: group::product intelligence
+product_group: group::product intelligence
time_frame: none
data_source: database
-distribution: [ee, ce]
-tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
+distribution:
+- ee
+- ce
+tier:
+- free
+- premium
+- ultimate
+```
+
+## 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.
+
+For uniqueness, the generated file includes a timestamp prefix, in ISO 8601 format.
+
+The generator takes the key path argument and 2 options and creates the metric YAML definition in corresponding location:
+
+- `--ee`, `--no-ee` Indicates if metric is for EE.
+- `--dir=DIR` indicates the metric directory. It must be one of: `counts_7d`, `7d`, `counts_28d`, `28d`, `counts_all`, `all`, `settings`, `license`.
+
+```shell
+bundle exec rails generate gitlab:usage_metric_definition counts.issues --dir=7d
+create config/metrics/counts_7d/issues.yml
+```
+
+NOTE:
+To create a metric definition used in EE, add the `--ee` flag.
+
+```shell
+bundle exec rails generate gitlab:usage_metric_definition counts.issues --ee --dir=7d
+create ee/config/metrics/counts_7d/issues.yml
```
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index 2d347df0559..d7baa6b23a5 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -10,7 +10,7 @@ We have developed a number of utilities to help ease development:
## `MergeHash`
-Refer to: <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/merge_hash.rb>:
+Refer to [`merge_hash.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/merge_hash.rb):
- Deep merges an array of hashes:
@@ -109,9 +109,50 @@ Refer to [`override.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gi
Because only a class or prepended module can actually override a method.
Including or extending a module into another cannot override anything.
+### Interactions with `ActiveSupport::Concern`, `prepend`, and `class_methods`
+
+When you use `ActiveSupport::Concern` that includes class methods, you do not
+get expected results because `ActiveSupport::Concern` doesn't work like a
+regular Ruby module.
+
+Since we already have `Prependable` as a patch for `ActiveSupport::Concern`
+to enable `prepend`, it has consequences with how it would interact with
+`override` and `class_methods`. As a workaround, `extend` `ClassMethods`
+into the defining `Prependable` module.
+
+This allows us to use `override` to verify `class_methods` used in the
+context mentioned above. This workaround only applies when we run the
+verification, not when running the application itself.
+
+Here are example code blocks that demonstrate the effect of this workaround:
+following codes:
+
+```ruby
+module Base
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def f
+ end
+ end
+end
+
+module Derived
+ include Base
+end
+
+# Without the workaround
+Base.f # => NoMethodError
+Derived.f # => nil
+
+# With the workaround
+Base.f # => nil
+Derived.f # => nil
+```
+
## `StrongMemoize`
-Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/strong_memoize.rb>:
+Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/strong_memoize.rb):
- Memoize the value even if it is `nil` or `false`.
diff --git a/doc/development/ux_guide/animation.md b/doc/development/ux_guide/animation.md
deleted file mode 100644
index 0f7a24042bb..00000000000
--- a/doc/development/ux_guide/animation.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/product-foundations/motion/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/product-foundations/motion/).
diff --git a/doc/development/ux_guide/basics.md b/doc/development/ux_guide/basics.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/basics.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/components.md b/doc/development/ux_guide/components.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/components.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/copy.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/features.md b/doc/development/ux_guide/features.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/features.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/illustrations.md b/doc/development/ux_guide/illustrations.md
deleted file mode 100644
index 815f870f8c5..00000000000
--- a/doc/development/ux_guide/illustrations.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/product-foundations/illustration/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/product-foundations/illustration/).
diff --git a/doc/development/ux_guide/index.md b/doc/development/ux_guide/index.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/index.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/principles.md b/doc/development/ux_guide/principles.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/principles.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/resources.md b/doc/development/ux_guide/resources.md
deleted file mode 100644
index ae092246d05..00000000000
--- a/doc/development/ux_guide/resources.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/resources/design-resources/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/resources/design-resources/).
diff --git a/doc/development/ux_guide/surfaces.md b/doc/development/ux_guide/surfaces.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/surfaces.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/tips.md b/doc/development/ux_guide/tips.md
deleted file mode 100644
index 1e84bf608f4..00000000000
--- a/doc/development/ux_guide/tips.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://design.gitlab.com/'
----
-
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/users.md b/doc/development/ux_guide/users.md
deleted file mode 100644
index a01aa4bcf35..00000000000
--- a/doc/development/ux_guide/users.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/wikis.md b/doc/development/wikis.md
index a2da4843eac..7995afb1e17 100644
--- a/doc/development/wikis.md
+++ b/doc/development/wikis.md
@@ -1,7 +1,7 @@
---
type: reference, dev
stage: Create
-group: Knowledge
+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
description: "GitLab's development guidelines for Wikis"
---
@@ -12,8 +12,8 @@ description: "GitLab's development guidelines for Wikis"
## Overview
-The wiki functionality in GitLab is based on [Gollum 4.x](https://github.com/gollum/gollum/),
-which is used in [Gitaly's](gitaly.md) Ruby service and accessed from the Rails app through Gitaly RPC calls.
+The wiki functionality in GitLab is based on [Gollum 4.x](https://github.com/gollum/gollum/).
+It's used in [Gitaly's](gitaly.md) Ruby service, and accessed from the Rails app through Gitaly RPC calls.
Wikis use Git repositories as storage backend, and can be accessed through:
@@ -43,7 +43,7 @@ When rendering wiki pages, we don't use Gollum at all and instead go through a
[custom Banzai pipeline](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/banzai/pipeline/wiki_pipeline.rb).
This adds some [wiki-specific markup](../user/markdown.md#wiki-specific-markdown), such as Gollum's `[[link]]` syntax.
-Since we do not make use of most of Gollum's features, we plan to move away from it entirely at some point.
+Because we do not make use of most of Gollum's features, we plan to move away from it entirely at some point.
[See this epic](https://gitlab.com/groups/gitlab-org/-/epics/2381) for reference.
## Model classes
diff --git a/doc/development/windows.md b/doc/development/windows.md
index 08ff29a4e58..07f8a80e95f 100644
--- a/doc/development/windows.md
+++ b/doc/development/windows.md
@@ -63,7 +63,7 @@ Build a Google Cloud image with the above shared runners repository by doing the
## How to use a Windows image in GCP
-1. In a web browser, go to <https://console.cloud.google.com/compute/images>.
+1. In a web browser, go to the [Google Cloud Platform console](https://console.cloud.google.com/compute/images).
1. Filter images by the name you used when creating image, `windows` is likely all you need to filter by.
1. Click the image's name.
1. Click the **CREATE INSTANCE** link.
@@ -81,7 +81,7 @@ Build a Google Cloud image with the above shared runners repository by doing the
1. Click **Continue** to accept the certificate.
1. Enter the password and click **Next**.
-You should now be remoted into a Windows machine with a command prompt.
+You should now be connected into a Windows machine with a command prompt.
### Optional: Use GCP VM Instance as a runner
diff --git a/doc/development/writing_documentation.md b/doc/development/writing_documentation.md
deleted file mode 100644
index 038a4b1e6ea..00000000000
--- a/doc/development/writing_documentation.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-redirect_to: 'documentation/index.md'
----
diff --git a/doc/downgrade_ee_to_ce/README.md b/doc/downgrade_ee_to_ce/README.md
index 3cbc68d61ed..c815842480c 100644
--- a/doc/downgrade_ee_to_ce/README.md
+++ b/doc/downgrade_ee_to_ce/README.md
@@ -1,97 +1,8 @@
---
-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: 'index.md'
---
-# Downgrading from EE to CE
+This document was moved to [another location](index.md).
-If you ever decide to downgrade your Enterprise Edition back to the Community
-Edition, there are a few steps you need take before installing the CE package
-on top of the current EE package, or, if you are in an installation from source,
-before you change remotes and fetch the latest CE code.
-
-## Disable Enterprise-only features
-
-First thing to do is to disable the following features.
-
-### Authentication mechanisms
-
-Kerberos and Atlassian Crowd are only available on the Enterprise Edition, so
-you should disable these mechanisms before downgrading and you should provide
-alternative authentication methods to your users.
-
-### Remove Service Integration entries from the database
-
-The `GithubService` class is only available in the Enterprise Edition codebase,
-so if you downgrade to the Community Edition, the following error displays:
-
-```plaintext
-Completed 500 Internal Server Error in 497ms (ActiveRecord: 32.2ms)
-
-ActionView::Template::Error (The single-table inheritance mechanism failed to locate the subclass: 'GithubService'. This
-error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this
-column if you didn't intend it to be used for storing the inheritance class or overwrite Service.inheritance_column to
-use another column for that information.)
-```
-
-All services are created automatically for every project you have, so in order
-to avoid getting this error, you need to remove all instances of the
-`GithubService` from your database:
-
-**Omnibus Installation**
-
-```shell
-sudo gitlab-rails runner "Service.where(type: ['GithubService']).delete_all"
-```
-
-**Source Installation**
-
-```shell
-bundle exec rails runner "Service.where(type: ['GithubService']).delete_all" production
-```
-
-NOTE:
-If you are running `GitLab =< v13.0` you need to also remove `JenkinsDeprecatedService` records
-and if you are running `GitLab =< v13.6` you need to also remove `JenkinsService` records.
-
-### Variables environment scopes
-
-If you're using this feature and there are variables sharing the same
-key, but they have different scopes in a project, then you might want to
-revisit the environment scope setting for those variables.
-
-In CE, environment scopes are completely ignored, therefore you could
-accidentally get a variable which you're not expecting for a particular
-environment. Make sure that you have the right variables in this case.
-
-Data is completely preserved, so you could always upgrade back to EE and
-restore the behavior if you leave it alone.
-
-## Downgrade to CE
-
-After performing the above mentioned steps, you are now ready to downgrade your
-GitLab installation to the Community Edition.
-
-**Omnibus Installation**
-
-To downgrade an Omnibus installation, it is sufficient to install the Community
-Edition package on top of the currently installed one. You can do this manually,
-by directly [downloading the package](https://packages.gitlab.com/gitlab/gitlab-ce)
-you need, or by adding our CE package repository and following the
-[CE installation instructions](https://about.gitlab.com/install/?version=ce).
-
-**Source Installation**
-
-To downgrade a source installation, you need to replace the current remote of
-your GitLab installation with the Community Edition's remote, fetch the latest
-changes, and checkout the latest stable branch:
-
-```shell
-git remote set-url origin git@gitlab.com:gitlab-org/gitlab-foss.git
-git fetch --all
-git checkout 8-x-stable
-```
-
-Remember to follow the correct [update guides](../update/README.md) to make
-sure all dependencies are up to date.
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/downgrade_ee_to_ce/index.md b/doc/downgrade_ee_to_ce/index.md
new file mode 100644
index 00000000000..ab95c5f3b09
--- /dev/null
+++ b/doc/downgrade_ee_to_ce/index.md
@@ -0,0 +1,97 @@
+---
+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
+---
+
+# Downgrading from EE to CE
+
+If you ever decide to downgrade your Enterprise Edition back to the Community
+Edition, there are a few steps you need take before installing the CE package
+on top of the current EE package, or, if you are in an installation from source,
+before you change remotes and fetch the latest CE code.
+
+## Disable Enterprise-only features
+
+First thing to do is to disable the following features.
+
+### Authentication mechanisms
+
+Kerberos and Atlassian Crowd are only available on the Enterprise Edition, so
+you should disable these mechanisms before downgrading and you should provide
+alternative authentication methods to your users.
+
+### Remove Service Integration entries from the database
+
+The `GithubService` class is only available in the Enterprise Edition codebase,
+so if you downgrade to the Community Edition, the following error displays:
+
+```plaintext
+Completed 500 Internal Server Error in 497ms (ActiveRecord: 32.2ms)
+
+ActionView::Template::Error (The single-table inheritance mechanism failed to locate the subclass: 'GithubService'. This
+error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this
+column if you didn't intend it to be used for storing the inheritance class or overwrite Service.inheritance_column to
+use another column for that information.)
+```
+
+All services are created automatically for every project you have, so in order
+to avoid getting this error, you need to remove all instances of the
+`GithubService` from your database:
+
+**Omnibus Installation**
+
+```shell
+sudo gitlab-rails runner "Service.where(type: ['GithubService']).delete_all"
+```
+
+**Source Installation**
+
+```shell
+bundle exec rails runner "Service.where(type: ['GithubService']).delete_all" production
+```
+
+NOTE:
+If you are running `GitLab =< v13.0` you need to also remove `JenkinsDeprecatedService` records
+and if you are running `GitLab =< v13.6` you need to also remove `JenkinsService` records.
+
+### Variables environment scopes
+
+If you're using this feature and there are variables sharing the same
+key, but they have different scopes in a project, then you might want to
+revisit the environment scope setting for those variables.
+
+In CE, environment scopes are completely ignored, therefore you could
+accidentally get a variable which you're not expecting for a particular
+environment. Make sure that you have the right variables in this case.
+
+Data is completely preserved, so you could always upgrade back to EE and
+restore the behavior if you leave it alone.
+
+## Downgrade to CE
+
+After performing the above mentioned steps, you are now ready to downgrade your
+GitLab installation to the Community Edition.
+
+**Omnibus Installation**
+
+To downgrade an Omnibus installation, it is sufficient to install the Community
+Edition package on top of the currently installed one. You can do this manually,
+by directly [downloading the package](https://packages.gitlab.com/gitlab/gitlab-ce)
+you need, or by adding our CE package repository and following the
+[CE installation instructions](https://about.gitlab.com/install/?version=ce).
+
+**Source Installation**
+
+To downgrade a source installation, you need to replace the current remote of
+your GitLab installation with the Community Edition's remote, fetch the latest
+changes, and checkout the latest stable branch:
+
+```shell
+git remote set-url origin git@gitlab.com:gitlab-org/gitlab-foss.git
+git fetch --all
+git checkout 8-x-stable
+```
+
+Remember to follow the correct [update guides](../update/index.md) to make
+sure all dependencies are up to date.
diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md
index b933cb873c8..c815842480c 100644
--- a/doc/gitlab-basics/README.md
+++ b/doc/gitlab-basics/README.md
@@ -1,49 +1,8 @@
---
-stage: Create
-group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
-comments: false
-type: index
+redirect_to: 'index.md'
---
-# GitLab basics guides
+This document was moved to [another location](index.md).
-This section provides resources to help you start working with GitLab and Git by focusing
-on the basic features that you will need to use.
-
-This documentation is split into the following groups:
-
-- [GitLab-specific functionality](#gitlab-basics), for basic GitLab features.
-- [General Git functionality](#working-with-git-from-the-command-line), for working
- with Git in conjunction with GitLab.
-
-## GitLab basics
-
-The following are guides to basic GitLab functionality:
-
-- [Create and add your SSH public key](create-your-ssh-keys.md), for enabling Git over SSH.
-- [Create a project](create-project.md), to start using GitLab.
-- [Create a group](../user/group/index.md#create-a-new-group), to combine and administer
- projects together.
-- [Create a branch](create-branch.md), to make changes to files stored in a project's repository.
-- [Feature branch workflow](feature_branch_workflow.md).
-- [Fork a project](fork-project.md), to duplicate projects so they can be worked on in parallel.
-- [Add a file](add-file.md), to add new files to a project's repository.
-- [Create an issue](../user/project/issues/managing_issues.md#create-a-new-issue),
- to start collaborating within a project.
-- [Create a merge request](../user/project/merge_requests/creating_merge_requests.md), to request changes made in a branch
- be merged into a project's repository.
-- See how these features come together in the [GitLab Flow introduction video](https://youtu.be/InKNIvky2KE)
- and [GitLab Flow page](../topics/gitlab_flow.md).
-
-## Working with Git from the command line
-
-If you're familiar with Git on the command line, you can interact with your GitLab
-projects just as you would with any other Git repository.
-
-These resources will help you get further acclimated to working on the command line.
-
-- [Start using Git on the command line](start-using-git.md), for some simple Git commands.
-- [Command line basics](command-line-commands.md), to create and edit files using the command line.
-
-More Git resources are available in the GitLab [Git documentation](../topics/git/index.md).
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md
index 4afeb5ce83b..33db7d74949 100644
--- a/doc/gitlab-basics/add-file.md
+++ b/doc/gitlab-basics/add-file.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: howto
---
-# Add a file to a repository
+# Add a file to a repository **(FREE)**
Adding files to a repository is a small, but key task. Bringing files in to a repository,
such as code, images, or documents, allows them to be tracked by Git, even though they
diff --git a/doc/gitlab-basics/add-image.md b/doc/gitlab-basics/add-image.md
deleted file mode 100644
index 8eb60f03877..00000000000
--- a/doc/gitlab-basics/add-image.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'add-file.md'
----
-
-This document was moved to [another location](add-file.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md
deleted file mode 100644
index a04bc5704e5..00000000000
--- a/doc/gitlab-basics/add-merge-request.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/project/merge_requests/creating_merge_requests.md'
----
-
-This document was moved to [another location](../user/project/merge_requests/creating_merge_requests.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/gitlab-basics/basic-git-commands.md b/doc/gitlab-basics/basic-git-commands.md
deleted file mode 100644
index 506fe89fc18..00000000000
--- a/doc/gitlab-basics/basic-git-commands.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'start-using-git.md'
----
-
-This document was moved to [another location](start-using-git.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md
index d237fa940e3..52facc7bd1a 100644
--- a/doc/gitlab-basics/command-line-commands.md
+++ b/doc/gitlab-basics/command-line-commands.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: howto, reference
---
-# Edit files through the command line
+# Edit files through the command line **(FREE)**
When [working with Git from the command line](start-using-git.md), you need to
use more than just the Git commands. There are several basic commands that you should
@@ -106,9 +106,9 @@ WARNING:
Be careful of the commands you run with `sudo`. Certain commands may cause
damage to your data or system.
-## Sample Git taskflow
+## Sample Git task flow
-If you're completely new to Git, looking through some [sample taskflows](https://rogerdudler.github.io/git-guide/)
+If you're completely new to Git, looking through some [sample task flows](https://rogerdudler.github.io/git-guide/)
may help you understand the best practices for using these commands as you work.
<!-- ## Troubleshooting
diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md
index 3697ae34bf9..9f4f46e5bd3 100644
--- a/doc/gitlab-basics/create-branch.md
+++ b/doc/gitlab-basics/create-branch.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: howto
---
-# How to create a branch
+# How to create a branch **(FREE)**
A branch is an independent line of development in a [project](../user/project/index.md).
diff --git a/doc/gitlab-basics/create-group.md b/doc/gitlab-basics/create-group.md
deleted file mode 100644
index f683b92af89..00000000000
--- a/doc/gitlab-basics/create-group.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/group/index.md#create-a-new-group'
----
-
-This document was moved to [another location](../user/group/index.md#create-a-new-group).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/gitlab-basics/create-issue.md b/doc/gitlab-basics/create-issue.md
deleted file mode 100644
index 39e47690264..00000000000
--- a/doc/gitlab-basics/create-issue.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/project/issues/index.md#viewing-and-managing-issues'
----
-
-This document was moved to [another location](../user/project/issues/index.md#viewing-and-managing-issues).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index c4fe522e6a2..18886120c63 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -1,175 +1,8 @@
---
-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: howto
+redirect_to: '../user/project/working_with_projects.md'
---
-# Create a project
+This document was moved to [another location](../user/project/working_with_projects.md).
-Most work in GitLab is done within a [Project](../user/project/index.md). Files and
-code are saved in projects, and most features are used within the scope of projects.
-
-## Create a project in GitLab
-
-To create a project in GitLab:
-
-1. In your dashboard, click the green **New project** button or use the plus
- icon in the navigation bar. This opens the **New project** page.
-1. On the **New project** page, choose if you want to:
- - Create a [blank project](#blank-projects).
- - Create a project using one of the available [project templates](#project-templates).
- - [Import a project](../user/project/import/index.md) from a different repository,
- if enabled on your GitLab instance. Contact your GitLab administrator if this is unavailable.
- - Run [CI/CD pipelines for external repositories](../ci/ci_cd_for_external_repos/index.md). **(PREMIUM)**
-
-NOTE:
-For a list of words that can't be used as project names see
-[Reserved project and group names](../user/reserved_names.md).
-
-### Blank projects
-
-To create a new blank project on the **New project** page:
-
-1. On the **Blank project** tab, provide the following information:
- - The name of your project in the **Project name** field. You can't use
- special characters, but you can use spaces, hyphens, underscores, or even
- emoji. When adding the name, the **Project slug** auto populates.
- The slug is what the GitLab instance uses as the URL path to the project.
- If you want a different slug, input the project name first,
- then change the slug after.
- - The path to your project in the **Project slug** field. This is the URL
- path for your project that the GitLab instance uses. If the
- **Project name** is blank, it auto populates when you fill in
- the **Project slug**.
- - The **Project description (optional)** field enables you to enter a
- description for your project's dashboard, which helps others
- understand what your project is about. Though it's not required, it's a good
- idea to fill this in.
- - Changing the **Visibility Level** modifies the project's
- [viewing and access rights](../public_access/public_access.md) for users.
- - Selecting the **Initialize repository with a README** option creates a
- README file so that the Git repository is initialized, has a default branch, and
- can be cloned.
-1. Click **Create project**.
-
-### Project templates
-
-Project templates can pre-populate a new project with the necessary files to get you
-started quickly.
-
-There are two main types of project templates:
-
-- [Built-in templates](#built-in-templates), sourced from the following groups:
- - [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
- - [`pages`](https://gitlab.com/pages)
-- [Custom project templates](#custom-project-templates), for custom templates
- configured by GitLab administrators and users.
-
-#### Built-in templates
-
-Built-in templates are project templates that are:
-
-- Developed and maintained in the [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
- and [`pages`](https://gitlab.com/pages) groups.
-- Released with GitLab.
-
-To use a built-in template on the **New project** page:
-
-1. On the **Create from template** tab, select the **Built-in** tab.
-1. From the list of available built-in templates, click the:
- - **Preview** button to look at the template source itself.
- - **Use template** button to start creating the project.
-1. Finish creating the project by filling out the project's details. The process is
- the same as creating a [blank project](#blank-projects).
-
-##### Enterprise templates **(ULTIMATE)**
-
-GitLab is developing Enterprise templates to help you streamline audit management with selected regulatory standards. These templates automatically import issues that correspond to each regulatory requirement.
-
-To create a new project with an Enterprise template, on the **New project** page:
-
-1. On the **Create from template** tab, select the **Built-in** tab.
-1. From the list of available built-in Enterprise templates, click the:
- - **Preview** button to look at the template source itself.
- - **Use template** button to start creating the project.
-1. Finish creating the project by filling out the project's details. The process is the same as creating a [blank project](#blank-projects).
-
-Available Enterprise templates include:
-
-- HIPAA Audit Protocol template ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) in GitLab 12.10)
-
-NOTE:
-You can improve the existing built-in templates or contribute new ones in the
-[`project-templates`](https://gitlab.com/gitlab-org/project-templates) and
-[`pages`](https://gitlab.com/pages) groups by following [these steps](https://gitlab.com/gitlab-org/project-templates/contributing).
-
-#### Custom project templates **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2.
-
-Creating new projects based on custom project templates is a convenient option for
-quickly starting projects.
-
-Custom projects are available at the [instance-level](../user/admin_area/custom_project_templates.md)
-from the **Instance** tab, or at the [group-level](../user/group/custom_project_templates.md)
-from the **Group** tab, under the **Create from template** tab.
-
-To use a custom project template on the **New project** page:
-
-1. On the **Create from template** tab, select the **Instance** tab or the **Group** tab.
-1. From the list of available custom templates, click the:
- - **Preview** button to look at the template source itself.
- - **Use template** button to start creating the project.
-1. Finish creating the project by filling out the project's details. The process is
- the same as creating a [blank project](#blank-projects).
-
-## Push to create a new project
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) in GitLab 10.5.
-
-When you create a new repository locally, instead of manually creating a new project in GitLab
-and then [cloning the repository](start-using-git.md#clone-a-repository)
-locally, you can directly push it to GitLab to create the new project, all without leaving
-your terminal. If you have access rights to the associated namespace, GitLab
-automatically creates a new project under that GitLab namespace with its visibility
-set to Private by default (you can later change it in the [project's settings](../public_access/public_access.md#how-to-change-project-visibility)).
-
-This can be done by using either SSH or HTTPS:
-
-```shell
-## Git push using SSH
-git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git master
-
-## Git push using HTTPS
-git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master
-```
-
-You can pass the flag `--tags` to the `git push` command to export existing repository tags.
-
-Once the push finishes successfully, a remote message indicates
-the command to set the remote and the URL to the new project:
-
-```plaintext
-remote:
-remote: The private project namespace/nonexistent-project was created.
-remote:
-remote: To configure the remote, run:
-remote: git remote add origin https://gitlab.example.com/namespace/nonexistent-project.git
-remote:
-remote: To view the project, visit:
-remote: https://gitlab.example.com/namespace/nonexistent-project
-remote:
-```
-
-<!-- ## 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 <2021-05-05>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> \ No newline at end of file
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index 98e01df7252..9cbaca91f7d 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -1,30 +1,8 @@
---
-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: howto
+redirect_to: '../ssh/README.md'
---
-# Create and add your SSH key pair
+This document was moved to [another location](../ssh/README.md).
-It's best practice to use [Git over SSH instead of Git over HTTP](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols).
-In order to use SSH, you need to:
-
-1. Create an SSH key pair
-1. Add your SSH public key to GitLab
-
-## Creating your SSH key pair
-
-1. Go to your [command line](start-using-git.md#command-shell).
-1. Follow the [instructions](../ssh/README.md#generating-a-new-ssh-key-pair) to generate
- your SSH key pair.
-
-## Adding your SSH public key to GitLab
-
-To add the SSH public key to GitLab, see
-[Adding an SSH key to your GitLab account](../ssh/README.md#adding-an-ssh-key-to-your-gitlab-account).
-
-NOTE:
-Once you add a key, you can't edit it. If it did not paste properly, it
-[will not work](../ssh/README.md#testing-that-everything-is-set-up-correctly), and
-you need to remove the key from GitLab and try adding it again.
+<!-- This redirect file can be deleted after <2021-07-04>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> \ No newline at end of file
diff --git a/doc/gitlab-basics/feature_branch_workflow.md b/doc/gitlab-basics/feature_branch_workflow.md
index e02be390ab8..682bc1aec0b 100644
--- a/doc/gitlab-basics/feature_branch_workflow.md
+++ b/doc/gitlab-basics/feature_branch_workflow.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/workflow.html'
---
-# Feature branch workflow
+# Feature branch workflow **(FREE)**
1. Clone project:
diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md
index 2f8cde2e1b7..adb49c6970f 100644
--- a/doc/gitlab-basics/fork-project.md
+++ b/doc/gitlab-basics/fork-project.md
@@ -1,14 +1,8 @@
---
-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: howto
+redirect_to: '../user/project/working_with_projects.md'
---
-# How to fork a project
+This document was moved to [another location](../user/project/working_with_projects.md).
-A fork is a copy of an original repository that you put in another namespace
-where you can experiment and apply changes that you can later decide whether or
-not to share, without affecting the original project.
-
-It takes just a few steps to [fork a project in GitLab](../user/project/repository/forking_workflow.md#creating-a-fork).
+<!-- This redirect file can be deleted after <2021-05-04>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> \ No newline at end of file
diff --git a/doc/gitlab-basics/index.md b/doc/gitlab-basics/index.md
new file mode 100644
index 00000000000..8052fd27bb3
--- /dev/null
+++ b/doc/gitlab-basics/index.md
@@ -0,0 +1,49 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+comments: false
+type: index
+---
+
+# GitLab basics guides **(FREE)**
+
+This section provides resources to help you start working with GitLab and Git by focusing
+on the basic features that you will need to use.
+
+This documentation is split into the following groups:
+
+- [GitLab-specific functionality](#gitlab-basics), for basic GitLab features.
+- [General Git functionality](#working-with-git-from-the-command-line), for working
+ with Git in conjunction with GitLab.
+
+## GitLab basics
+
+The following are guides to basic GitLab functionality:
+
+- [Create and add your SSH public key](../ssh/README.md), for enabling Git over SSH.
+- [Create a project](../user/project/working_with_projects.md#create-a-project), to start using GitLab.
+- [Create a group](../user/group/index.md#create-a-new-group), to combine and administer
+ projects together.
+- [Create a branch](create-branch.md), to make changes to files stored in a project's repository.
+- [Feature branch workflow](feature_branch_workflow.md).
+- [Fork a project](../user/project/working_with_projects.md#fork-a-project), to duplicate projects so they can be worked on in parallel.
+- [Add a file](add-file.md), to add new files to a project's repository.
+- [Create an issue](../user/project/issues/managing_issues.md#create-a-new-issue),
+ to start collaborating within a project.
+- [Create a merge request](../user/project/merge_requests/creating_merge_requests.md), to request changes made in a branch
+ be merged into a project's repository.
+- See how these features come together in the [GitLab Flow introduction video](https://youtu.be/InKNIvky2KE)
+ and [GitLab Flow page](../topics/gitlab_flow.md).
+
+## Working with Git from the command line
+
+If you're familiar with Git on the command line, you can interact with your GitLab
+projects just as you would with any other Git repository.
+
+These resources will help you get further acclimated to working on the command line.
+
+- [Start using Git on the command line](start-using-git.md), for some simple Git commands.
+- [Command line basics](command-line-commands.md), to create and edit files using the command line.
+
+More Git resources are available in the GitLab [Git documentation](../topics/git/index.md).
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 7f3e90dc6bd..a2d286379d2 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -6,7 +6,7 @@ type: howto, tutorial
description: "Introduction to using Git through the command line."
---
-# Start using Git on the command line
+# Start using Git on the command line **(FREE)**
[Git](https://git-scm.com/) is an open-source distributed version control system designed to
handle everything from small to very large projects with speed and efficiency. GitLab is built
@@ -51,7 +51,7 @@ prompt, terminal, and command line) of your preference. Here are some suggestion
- Built-in: [Terminal](https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line). Press <kbd>⌘ command</kbd> + <kbd>space</kbd> and type "terminal" to find it.
- [iTerm2](https://iterm2.com/), which you can integrate with [zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [oh my zsh](https://ohmyz.sh/) for color highlighting, among other handy features for Git users.
- For Windows users:
- - Built-in: **cmd**. Click the search icon on the bottom navbar on Windows and type "cmd" to find it.
+ - Built-in: `cmd`. Click the search icon on the bottom navigation bar on Windows and type `cmd` to find it.
- [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7): a Windows "powered up" shell, from which you can execute a greater number of commands.
- Git Bash: it comes built into [Git for Windows](https://gitforwindows.org/).
- For Linux users:
@@ -152,8 +152,12 @@ Your files in GitLab live in a **repository**, similar to how you have them in a
directory in your computer. **Remote** repository refers to the files in
GitLab and the copy in your computer is called **local** copy.
A **project** in GitLab is what holds a repository, which holds your files.
-Often, the word "repository" is shortened to "repo".
+<!-- vale gitlab.Spelling = NO -->
+<!-- vale gitlab.SubstitutionWarning = NO -->
+Often, the word "repository" is shortened to "repo".
+<!-- vale gitlab.Spelling = YES -->
+<!-- vale gitlab.SubstitutionWarning = YES -->
### Fork
When you want to copy someone else's repository, you [**fork**](../user/project/repository/forking_workflow.md#creating-a-fork)
@@ -274,7 +278,7 @@ identified by Git as the local content for that specific remote project.
To add a remote repository to your local copy:
-1. In GitLab, [create a new project](../gitlab-basics/create-project.md#push-to-create-a-new-project) to hold your files.
+1. In GitLab, [create a new project](../user/project/working_with_projects.md#create-a-project) to hold your files.
1. Visit this project's homepage, scroll down to **Push an existing folder**, and copy the command that starts with `git remote add`.
1. On your computer, open the terminal in the directory you've initialized, paste the command you copied, and press <kbd>enter</kbd>:
diff --git a/doc/install/README.md b/doc/install/README.md
index 7ed478439e0..c815842480c 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -1,143 +1,8 @@
---
-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
-comments: false
-description: Read through the GitLab installation methods.
-type: index
+redirect_to: 'index.md'
---
-# Installation **(CORE ONLY)**
+This document was moved to [another location](index.md).
-GitLab can be installed in most GNU/Linux distributions and with several
-cloud providers. To get the best experience from GitLab, you must balance
-performance, reliability, ease of administration (backups, upgrades, and
-troubleshooting), and the cost of hosting.
-
-Depending on your platform, select from the following available methods to
-install GitLab:
-
-- [_Omnibus GitLab_](#installing-gitlab-on-linux-using-the-omnibus-gitlab-package-recommended):
- The official deb/rpm packages that contain a bundle of GitLab and the
- components it depends on, including PostgreSQL, Redis, and Sidekiq.
-- [_GitLab Helm chart_](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts):
- The cloud native Helm chart for installing GitLab and all of its components
- on Kubernetes.
-- [_Docker_](#installing-gitlab-with-docker): The Omnibus GitLab packages,
- dockerized.
-- [_Source_](#installing-gitlab-from-source): Install GitLab and all of its
- components from scratch.
-- [_Cloud provider_](#installing-gitlab-on-cloud-providers): Install directly
- from platforms like AWS, Azure, and GCP.
-
-If you're not sure which installation method to use, we recommend you use
-Omnibus GitLab. The Omnibus GitLab packages are mature,
-[scalable](../administration/reference_architectures/index.md), and are used
-today on GitLab.com. The Helm charts are recommended for those who are familiar
-with Kubernetes.
-
-## Requirements
-
-Before you install GitLab, be sure to review the [system requirements](requirements.md).
-The system requirements include details about the minimum hardware, software,
-database, and additional requirements to support GitLab.
-
-## Installing GitLab on Linux using the Omnibus GitLab package (recommended)
-
-The Omnibus GitLab package uses our official deb/rpm repositories, and is
-recommended for most users.
-
-If you need additional scale or resilience, we recommend deploying
-GitLab as described in our [reference architecture documentation](../administration/reference_architectures/index.md).
-
-[**> Install GitLab using the Omnibus GitLab package.**](https://about.gitlab.com/install/)
-
-### GitLab Environment Toolkit (alpha)
-
-The [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) provides a set of automation tools to easily deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers.
-
-It is currently in alpha, and is not recommended for production use.
-
-[**> Install a GitLab reference architecture using the GitLab Environment Toolkit.**](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#documentation)
-
-## Installing GitLab on Kubernetes via the GitLab Helm charts
-
-When installing GitLab on Kubernetes, there are some trade-offs that you
-need to be aware of:
-
-- Administration and troubleshooting requires Kubernetes knowledge.
-- It can be more expensive for smaller installations. The default installation
- requires more resources than a single node Omnibus deployment, as most services
- are deployed in a redundant fashion.
-- There are some feature [limitations to be aware of](https://docs.gitlab.com/charts/#limitations).
-
-Due to these trade-offs, having Kubernetes experience is a requirement for
-using this method. We recommend being familiar with Kubernetes before using it
-to deploy GitLab in production. The methods for management, observability, and
-some concepts are different than traditional deployments.
-
-[**> Install GitLab on Kubernetes using the GitLab Helm charts.**](https://docs.gitlab.com/charts/)
-
-## Installing GitLab with Docker
-
-GitLab maintains a set of official Docker images based on the Omnibus GitLab
-package.
-
-[**> Install GitLab using the official GitLab Docker images.**](docker.md)
-
-## Installing GitLab from source
-
-If the Omnibus GitLab package isn't available for your distribution, you can
-install GitLab from source. This can be useful with unsupported systems, like
-\*BSD. For an overview of the directory structure, see the
-[structure documentation](installation.md#gitlab-directory-structure).
-
-[**> Install GitLab from source.**](installation.md)
-
-## Installing GitLab on cloud providers
-
-GitLab can be installed on a variety of cloud providers by using any of
-the above methods, provided the cloud provider supports it.
-
-- [Install on AWS](aws/index.md): Install Omnibus GitLab on AWS using the community AMIs that GitLab provides.
-- [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md): Install Omnibus GitLab on a VM in GCP.
-- [Install GitLab on Azure](azure/index.md): Install Omnibus GitLab from Azure Marketplace.
-- [Install GitLab on OpenShift](https://docs.gitlab.com/charts/installation/cloud/openshift.html): Install GitLab on OpenShift by using the GitLab Helm charts.
-- [Install GitLab on DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-gitlab-on-ubuntu-18-04): Install Omnibus GitLab on DigitalOcean.
-- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md):
- Quickly test any version of GitLab on DigitalOcean using Docker Machine.
-
-## Next steps
-
-Here are a few resources you might want to check out after completing the
-installation:
-
-- [Upload a license](../user/admin_area/license.md) or [start a free trial](https://about.gitlab.com/free-trial/):
- Activate all GitLab Enterprise Edition functionality with a license.
-- [Set up runners](https://docs.gitlab.com/runner/): Set up one or more GitLab
- Runners, the agents that are responsible for all of the GitLab CI/CD features.
-- [GitLab Pages](../administration/pages/index.md): Configure GitLab Pages to
- allow hosting of static sites.
-- [GitLab Registry](../administration/packages/container_registry.md): With the
- GitLab Container Registry, every project can have its own space to store Docker
- images.
-- [Secure GitLab](../security/README.md#securing-your-gitlab-installation):
- Recommended practices to secure your GitLab instance.
-- [SMTP](https://docs.gitlab.com/omnibus/settings/smtp.html): Configure SMTP
- for proper email notifications support.
-- [LDAP](../administration/auth/ldap/index.md): Configure LDAP to be used as
- an authentication mechanism for GitLab.
-- [Back up and restore GitLab](../raketasks/backup_restore.md): Learn the different
- ways you can back up or restore GitLab.
-- [Upgrade GitLab](../update/README.md): Every 22nd of the month, a new feature-rich GitLab version
- is released. Learn how to upgrade to it, or to an interim release that contains a security fix.
-- [Scaling GitLab](../administration/reference_architectures/index.md):
- GitLab supports several different types of clustering.
-- [Advanced Search](../integration/elasticsearch.md): Leverage Elasticsearch for
- faster, more advanced code search across your entire GitLab instance.
-- [Geo replication](../administration/geo/index.md):
- Geo is the solution for widely distributed development teams.
-- [Release and maintenance policy](../policy/maintenance.md): Learn about GitLab
- policies governing version naming, as well as release pace for major, minor, patch,
- and security releases.
-- [Pricing](https://about.gitlab.com/pricing/): Pricing for the different tiers.
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 8a8e3a053b6..8fa1883da59 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -122,7 +122,7 @@ Internet Gateway.
We'll now create a VPC, a virtual networking environment that you'll control:
-1. Navigate to <https://console.aws.amazon.com/vpc/home>.
+1. Sign in to [Amazon Web Services](https://console.aws.amazon.com/vpc/home).
1. Select **Your VPCs** from the left menu and then click **Create VPC**.
At the "Name tag" enter `gitlab-vpc` and at the "IPv4 CIDR block" enter
`10.0.0.0/16`. If you don't require dedicated hardware, you can leave
@@ -277,7 +277,7 @@ On the Route 53 dashboard, click **Hosted zones** in the left navigation bar:
1. Click **Create**.
1. If you registered your domain through Route 53, you're done. If you used a different domain registrar, you need to update your DNS records with your domain registrar. You'll need to:
1. Click on **Hosted zones** and select the domain you added above.
- 1. You'll see a list of `NS` records. From your domain registrar's admin panel, add each of these as `NS` records to your domain's DNS records. These steps may vary between domain registrars. If you're stuck, Google **"name of your registrar" add dns records** and you should find a help article specific to your domain registrar.
+ 1. You'll see a list of `NS` records. From your domain registrar's admin panel, add each of these as `NS` records to your domain's DNS records. These steps may vary between domain registrars. If you're stuck, Google **"name of your registrar" add DNS records** and you should find a help article specific to your domain registrar.
The steps for doing this vary depending on which registrar you use and is beyond the scope of this guide.
@@ -568,7 +568,7 @@ Let's create an EC2 instance where we'll install Gitaly:
1. From the EC2 dashboard, click **Launch instance**.
1. Choose an AMI. In this example, we'll select the **Ubuntu Server 18.04 LTS (HVM), SSD Volume Type**.
-1. Choose an instance type. We'll pick a **c5.xlarge**.
+1. Choose an instance type. We'll pick a `c5.xlarge`.
1. Click **Configure Instance Details**.
1. In the **Network** dropdown, select `gitlab-vpc`, the VPC we created earlier.
1. In the **Subnet** dropdown, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.
diff --git a/doc/install/google-protobuf.md b/doc/install/google-protobuf.md
deleted file mode 100644
index ae7b0548d51..00000000000
--- a/doc/install/google-protobuf.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'installation.md#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found'
----
-
-This document was moved to [another location](installation.md#google-protobuf-loaderror-libx86_64-linux-gnulibcso6-version-glibc_214-not-found).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index d579e214efc..7f38970a2b1 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -36,7 +36,7 @@ To deploy GitLab on GCP you first need to create a virtual machine:
![Search for GitLab](img/launch_vm.png)
1. On the next page, you can select the type of VM as well as the
- estimated costs. Provide the name of the instance, desired datacenter, and machine type.
+ estimated costs. Provide the name of the instance, desired data center, and machine type.
Note our [hardware requirements for different user base sizes](../requirements.md#hardware-requirements).
![Launch on Compute Engine](img/vm_details.png)
diff --git a/doc/install/index.md b/doc/install/index.md
new file mode 100644
index 00000000000..948365ce548
--- /dev/null
+++ b/doc/install/index.md
@@ -0,0 +1,143 @@
+---
+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
+comments: false
+description: Read through the GitLab installation methods.
+type: index
+---
+
+# Installation **(FREE SELF)**
+
+GitLab can be installed in most GNU/Linux distributions and with several
+cloud providers. To get the best experience from GitLab, you must balance
+performance, reliability, ease of administration (backups, upgrades, and
+troubleshooting), and the cost of hosting.
+
+Depending on your platform, select from the following available methods to
+install GitLab:
+
+- [_Omnibus GitLab_](#installing-gitlab-on-linux-using-the-omnibus-gitlab-package-recommended):
+ The official deb/rpm packages that contain a bundle of GitLab and the
+ components it depends on, including PostgreSQL, Redis, and Sidekiq.
+- [_GitLab Helm chart_](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts):
+ The cloud native Helm chart for installing GitLab and all of its components
+ on Kubernetes.
+- [_Docker_](#installing-gitlab-with-docker): The Omnibus GitLab packages,
+ Dockerized.
+- [_Source_](#installing-gitlab-from-source): Install GitLab and all of its
+ components from scratch.
+- [_Cloud provider_](#installing-gitlab-on-cloud-providers): Install directly
+ from platforms like AWS, Azure, and GCP.
+
+If you're not sure which installation method to use, we recommend you use
+Omnibus GitLab. The Omnibus GitLab packages are mature,
+[scalable](../administration/reference_architectures/index.md), and are used
+today on GitLab.com. The Helm charts are recommended for those who are familiar
+with Kubernetes.
+
+## Requirements
+
+Before you install GitLab, be sure to review the [system requirements](requirements.md).
+The system requirements include details about the minimum hardware, software,
+database, and additional requirements to support GitLab.
+
+## Installing GitLab on Linux using the Omnibus GitLab package (recommended)
+
+The Omnibus GitLab package uses our official deb/rpm repositories, and is
+recommended for most users.
+
+If you need additional scale or resilience, we recommend deploying
+GitLab as described in our [reference architecture documentation](../administration/reference_architectures/index.md).
+
+[**> Install GitLab using the Omnibus GitLab package.**](https://about.gitlab.com/install/)
+
+### GitLab Environment Toolkit (alpha)
+
+The [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) provides a set of automation tools to easily deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers.
+
+It is currently in alpha, and is not recommended for production use.
+
+[**> Install a GitLab reference architecture using the GitLab Environment Toolkit.**](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#documentation)
+
+## Installing GitLab on Kubernetes via the GitLab Helm charts
+
+When installing GitLab on Kubernetes, there are some trade-offs that you
+need to be aware of:
+
+- Administration and troubleshooting requires Kubernetes knowledge.
+- It can be more expensive for smaller installations. The default installation
+ requires more resources than a single node Omnibus deployment, as most services
+ are deployed in a redundant fashion.
+- There are some feature [limitations to be aware of](https://docs.gitlab.com/charts/#limitations).
+
+Due to these trade-offs, having Kubernetes experience is a requirement for
+using this method. We recommend being familiar with Kubernetes before using it
+to deploy GitLab in production. The methods for management, observability, and
+some concepts are different than traditional deployments.
+
+[**> Install GitLab on Kubernetes using the GitLab Helm charts.**](https://docs.gitlab.com/charts/)
+
+## Installing GitLab with Docker
+
+GitLab maintains a set of official Docker images based on the Omnibus GitLab
+package.
+
+[**> Install GitLab using the official GitLab Docker images.**](docker.md)
+
+## Installing GitLab from source
+
+If the Omnibus GitLab package isn't available for your distribution, you can
+install GitLab from source. This can be useful with unsupported systems, like
+\*BSD. For an overview of the directory structure, see the
+[structure documentation](installation.md#gitlab-directory-structure).
+
+[**> Install GitLab from source.**](installation.md)
+
+## Installing GitLab on cloud providers
+
+GitLab can be installed on a variety of cloud providers by using any of
+the above methods, provided the cloud provider supports it.
+
+- [Install on AWS](aws/index.md): Install Omnibus GitLab on AWS using the community AMIs that GitLab provides.
+- [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md): Install Omnibus GitLab on a VM in GCP.
+- [Install GitLab on Azure](azure/index.md): Install Omnibus GitLab from Azure Marketplace.
+- [Install GitLab on OpenShift](https://docs.gitlab.com/charts/installation/cloud/openshift.html): Install GitLab on OpenShift by using the GitLab Helm charts.
+- [Install GitLab on DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-gitlab-on-ubuntu-18-04): Install Omnibus GitLab on DigitalOcean.
+- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md):
+ Quickly test any version of GitLab on DigitalOcean using Docker Machine.
+
+## Next steps
+
+Here are a few resources you might want to check out after completing the
+installation:
+
+- [Upload a license](../user/admin_area/license.md) or [start a free trial](https://about.gitlab.com/free-trial/):
+ Activate all GitLab Enterprise Edition functionality with a license.
+- [Set up runners](https://docs.gitlab.com/runner/): Set up one or more GitLab
+ Runners, the agents that are responsible for all of the GitLab CI/CD features.
+- [GitLab Pages](../administration/pages/index.md): Configure GitLab Pages to
+ allow hosting of static sites.
+- [GitLab Registry](../administration/packages/container_registry.md): With the
+ GitLab Container Registry, every project can have its own space to store Docker
+ images.
+- [Secure GitLab](../security/README.md#securing-your-gitlab-installation):
+ Recommended practices to secure your GitLab instance.
+- [SMTP](https://docs.gitlab.com/omnibus/settings/smtp.html): Configure SMTP
+ for proper email notifications support.
+- [LDAP](../administration/auth/ldap/index.md): Configure LDAP to be used as
+ an authentication mechanism for GitLab.
+- [Back up and restore GitLab](../raketasks/backup_restore.md): Learn the different
+ ways you can back up or restore GitLab.
+- [Upgrade GitLab](../update/index.md): Every 22nd of the month, a new feature-rich GitLab version
+ is released. Learn how to upgrade to it, or to an interim release that contains a security fix.
+- [Scaling GitLab](../administration/reference_architectures/index.md):
+ GitLab supports several different types of clustering.
+- [Advanced Search](../integration/elasticsearch.md): Leverage Elasticsearch for
+ faster, more advanced code search across your entire GitLab instance.
+- [Geo replication](../administration/geo/index.md):
+ Geo is the solution for widely distributed development teams.
+- [Release and maintenance policy](../policy/maintenance.md): Learn about GitLab
+ policies governing version naming, as well as release pace for major, minor, patch,
+ and security releases.
+- [Pricing](https://about.gitlab.com/pricing/): Pricing for the different tiers.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 80f3f6ab092..f246f975acf 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -9,7 +9,7 @@ type: howto
This is the official installation guide to set up a production GitLab server
using the source files. To set up a **development installation** or for many
-other installation options, see the [main installation page](README.md).
+other installation options, see the [main installation page](index.md).
It was created for and tested on **Debian/Ubuntu** operating systems.
Read [requirements.md](requirements.md) for hardware and operating system requirements.
If you want to install on RHEL/CentOS, we recommend using the
@@ -110,7 +110,7 @@ Install the required packages (needed to compile Ruby and native extensions to R
sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev \
libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev \
libxslt-dev libcurl4-openssl-dev libicu-dev logrotate rsync python-docutils pkg-config cmake \
- runit
+ runit-systemd
```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
@@ -172,8 +172,12 @@ sudo apt-get install -y postfix
Then select 'Internet Site' and press enter to confirm the hostname.
+<!-- vale gitlab.Spelling = NO -->
+
### Exiftool
+<!-- vale gitlab.Spelling = YES -->
+
[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse#dependencies)
requires `exiftool` to remove EXIF data from uploaded images.
@@ -187,7 +191,7 @@ The Ruby interpreter is required to run GitLab.
See the [requirements page](requirements.md#ruby-versions) for the minimum
Ruby requirements.
-The use of Ruby version managers such as [RVM](https://rvm.io/), [rbenv](https://github.com/rbenv/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab
+The use of Ruby version managers such as [`RVM`](https://rvm.io/), [`rbenv`](https://github.com/rbenv/rbenv) or [`chruby`](https://github.com/postmodern/chruby) with GitLab
in production, frequently leads to hard to diagnose problems. Version managers
are not supported and we strongly advise everyone to follow the instructions
below to use a system Ruby.
@@ -205,7 +209,7 @@ Download Ruby and compile it:
```shell
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.gz"
+curl --remote-name --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.gz"
echo 'cb9731a17487e0ad84037490a6baf8bfa31a09e8 ruby-2.7.2.tar.gz' | shasum -c - && tar xzf ruby-2.7.2.tar.gz
cd ruby-2.7.2
@@ -225,7 +229,7 @@ page](https://golang.org/dl).
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress "https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz"
+curl --remote-name --progress-bar "https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz"
echo '512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569 go1.13.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.13.5.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
@@ -238,16 +242,16 @@ In GitLab 8.17 and later, GitLab requires the use of Node to compile JavaScript
assets, and Yarn to manage JavaScript dependencies. The current minimum
requirements for these are:
-- `node` >= v10.13.0. (We recommend node 12.x as it is faster)
+- `node` >= v10.14.2. (We recommend node 14.x as it is faster)
- `yarn` >= v1.10.0.
-In many distros,
+In many distributions,
the versions provided by the official package repositories are out of date, so
we need to install through the following commands:
```shell
-# install node v12.x
-curl --location "https://deb.nodesource.com/setup_12.x" | sudo bash -
+# install node v14.x
+curl --location "https://deb.nodesource.com/setup_14.x" | sudo bash -
sudo apt-get install -y nodejs
curl --silent --show-error "https://dl.yarnpkg.com/debian/pubkey.gpg" | sudo apt-key add -
@@ -603,7 +607,7 @@ You can specify a different Git repository by providing it as an extra parameter
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
```
-### Install GitLab-Elasticsearch-indexer on Enterprise Edition **(STARTER ONLY)**
+### Install GitLab-Elasticsearch-indexer on Enterprise Edition **(PREMIUM SELF)**
GitLab-Elasticsearch-Indexer uses [GNU Make](https://www.gnu.org/software/make/). The
following command-line installs GitLab-Elasticsearch-Indexer in `/home/git/gitlab-elasticsearch-indexer`
@@ -935,7 +939,7 @@ production:
url: redis://redis.example.tld:6379
```
-If you want to connect the Redis server via socket, use the "unix:" URL scheme and the path to the Redis socket file in the `config/resque.yml` file.
+If you want to connect the Redis server via socket, use the `unix:` URL scheme and the path to the Redis socket file in the `config/resque.yml` file.
```yaml
# example
diff --git a/doc/install/ldap.md b/doc/install/ldap.md
deleted file mode 100644
index e88363f81b1..00000000000
--- a/doc/install/ldap.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/auth/ldap/index.md'
----
-
-This document was moved to [another location](../administration/auth/ldap/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 21fe87a71b1..3ee899958af 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -15,7 +15,7 @@ for details.
## Introduction
-[OpenShift Origin](https://www.okd.io/) (**Note:** renamed to OKD in Aug 2018) is an open source container application
+[OpenShift Origin](https://www.okd.io/) (**Note:** renamed to OKD in August 2018) is an open source container application
platform created by [RedHat](https://www.redhat.com/en), based on [Kubernetes](https://kubernetes.io/) and [Docker](https://www.docker.com). That means
you can host your own PaaS for free and almost with no hassle.
@@ -44,7 +44,7 @@ test OpenShift easily:
It is also important to mention that for the purposes of this tutorial, the
latest Origin release is used:
-- **oc** `v1.3.0` (must be [installed](https://github.com/openshift/origin/releases/tag/v1.3.0) locally on your computer)
+- **`oc`** `v1.3.0` (must be [installed](https://github.com/openshift/origin/releases/tag/v1.3.0) locally on your computer)
- **OpenShift** `v1.3.0` (is pre-installed in the [VM image](https://app.vagrantup.com/openshift/boxes/origin-all-in-one))
- **Kubernetes** `v1.3.0` (is pre-installed in the [VM image](https://app.vagrantup.com/openshift/boxes/origin-all-in-one))
@@ -59,8 +59,8 @@ on your computer.
## Getting familiar with OpenShift Origin
-The environment we are about to use is based on CentOS 7 which comes with all
-the tools needed pre-installed: Docker, Kubernetes, OpenShift, etcd.
+The environment we are about to use is based on CentOS 7, which comes with all
+the tools needed pre-installed, including Docker, Kubernetes, and OpenShift.
### Test OpenShift using Vagrant
@@ -100,14 +100,14 @@ order to proceed.
Let's login as admin with username/password `admin/admin`. This is what the
landing page looks like:
-![openshift web console](img/web-console.png)
+![OpenShift web console](img/web-console.png)
You can see that a number of [projects](https://docs.okd.io/3.11/dev_guide/projects.html) are already created for testing purposes.
If you head over the `openshift-infra` project, a number of services with their
respective pods are there to explore.
-![openshift web console](img/openshift-infra-project.png)
+![OpenShift web console](img/openshift-infra-project.png)
We are not going to explore the whole interface, but if you want to learn about
the key concepts of OpenShift, read the [core concepts reference](https://docs.okd.io/3.11/architecture/core_concepts/index.html)
@@ -318,7 +318,7 @@ NOTE:
The `gitlab.apps.10.2.2.2.nip.io` hostname that is used by default will
resolve to the host with IP `10.2.2.2` which is the IP our VM uses. It is a
trick to have distinct FQDNs pointing to services that are on our local network.
-Read more on how this works in <https://nip.io>.
+Read more on how this works at [nip.io](https://nip.io).
Now that we configured this, let's see how to manage and scale GitLab.
@@ -343,7 +343,7 @@ created the GitLab app? This is where you can see them in action.
![Running pods](img/running-pods.png)
-You can see GitLab being reconfigured by taking look at the logs in realtime.
+You can see GitLab being reconfigured by taking look at the logs in real time.
Click on `gitlab-ce-2-j7ioe` (your ID will be different) and go to the **Logs**
tab.
@@ -464,7 +464,7 @@ OpenShift's website about [autoscaling](https://docs.okd.io/3.11/dev_guide/pod_a
As stated in the [all-in-one VM](https://www.okd.io/minishift/) page:
> By default, OpenShift will not allow a container to run as root or even a
-non-random container assigned userid. Most Docker images in Docker Hub do not
+non-random container assigned user ID. Most Docker images in Docker Hub do not
follow this best practice and instead run as root.
The all-in-one VM we are using has this security turned off so it will not
diff --git a/doc/install/pivotal/index.md b/doc/install/pivotal/index.md
index 1ac667898ab..eee70c2c578 100644
--- a/doc/install/pivotal/index.md
+++ b/doc/install/pivotal/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
---
-# GitLab Pivotal Tile **(PREMIUM ONLY)**
+# GitLab Pivotal Tile **(PREMIUM SELF)**
WARNING:
As of September 13, 2017, the GitLab Enterprise Plus for Pivotal Cloud Foundry
diff --git a/doc/install/redis.md b/doc/install/redis.md
deleted file mode 100644
index 9048f777a0d..00000000000
--- a/doc/install/redis.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: installation.md#7-redis
----
-
-This document was moved to [another location](installation.md#7-redis).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 69983edc383..da07453c2ce 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -22,7 +22,7 @@ as the hardware requirements that are needed to install and use GitLab.
- Scientific Linux (please use the CentOS packages and instructions)
- Oracle Linux (please use the CentOS packages and instructions)
-For the installation options, see [the main installation page](README.md).
+For the installation options, see [the main installation page](index.md).
### Unsupported Linux distributions and Unix-like operating systems
@@ -179,7 +179,7 @@ Omnibus GitLab defaults to the recommended Puma settings. Regardless of installa
tune the Puma settings.
If you're using Omnibus GitLab, see [Puma settings](https://docs.gitlab.com/omnibus/settings/puma.html)
-for instructions on changing the Puma settings. If you're using the GitLab Helm chart, see the [Webservice chart](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html).
+for instructions on changing the Puma settings. If you're using the GitLab Helm chart, see the [`webservice` chart](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html).
### Puma workers
@@ -227,7 +227,7 @@ recommendation above) please see [the Unicorn settings in the Omnibus GitLab doc
Redis stores all user sessions and the background task queue.
The storage requirements for Redis are minimal, about 25kB per user.
-Sidekiq processes the background jobs with a multithreaded process.
+Sidekiq processes the background jobs with a multi-threaded process.
This process starts with the entire Rails stack (200MB+) but it can grow over time due to memory leaks.
On a very active server (10,000 billable users) the Sidekiq process can use 1GB+ of memory.
diff --git a/doc/install/structure.md b/doc/install/structure.md
deleted file mode 100644
index ca90a3de1b8..00000000000
--- a/doc/install/structure.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: installation.md#gitlab-directory-structure
----
-
-This page was moved to [another location](installation.md#gitlab-directory-structure).
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 227e2eec53c..7d38dd6222a 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -25,7 +25,7 @@ GitLab can be configured to authenticate access requests with the following auth
- Enable sign in via [LDAP](../administration/auth/ldap/index.md).
- Enable [OAuth2 provider](oauth_provider.md) application creation.
- Use [OmniAuth](omniauth.md) to enable sign in via Twitter, GitHub, GitLab.com, Google,
- Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure or Authentiq ID.
+ Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure, or Authentiq ID.
- Use GitLab as an [OpenID Connect](openid_connect_provider.md) identity provider.
- Authenticate to [Vault](vault.md) through GitLab OpenID Connect.
- Configure GitLab as a [SAML](saml.md) 2.0 Service Provider.
@@ -39,6 +39,11 @@ GitLab can be integrated with the following external services to enhance securit
GitLab also provides features to improve the security of your own application. For more details see [GitLab Secure](../user/application_security/index.md).
+## Security partners
+
+GitLab has integrated with several security partners. For more information, see
+[Security partners integration](security_partners/index.md).
+
## Continuous integration
GitLab can be integrated with the following external service for continuous integration:
@@ -65,7 +70,9 @@ Integration with services such as Campfire, Flowdock, HipChat, Pivotal Tracker,
### SSL certificate errors
-When trying to integrate GitLab with services that are using self-signed certificates, it is very likely that SSL certificate errors occur in different parts of the application, most likely Sidekiq.
+When trying to integrate GitLab with services using self-signed certificates,
+SSL certificate errors can occur in different parts of the application. Sidekiq
+is a common culprit.
There are two approaches you can take to solve this:
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index f22a94a01c7..c83ef650f54 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -6,6 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Microsoft Azure OAuth2 OmniAuth Provider
+NOTE:
+Per Microsoft, this provider uses the [older Azure Active Directory v1.0 endpoint](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-protocols-oauth-code).
+Microsoft documentation suggests that you should use the [OpenID Connect protocol to use the v2 endpoints](../administration/auth/oidc.md#microsoft-azure) for new projects.
+
To enable the Microsoft Azure OAuth2 OmniAuth provider, you must register your application with Azure. Azure generates a client ID and secret key for you to use.
Sign in to the [Azure Portal](https://portal.azure.com), and follow the instructions in
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index 4bc9d39ae3f..8999f4da9a2 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -10,8 +10,8 @@ NOTE:
Starting from GitLab 11.4, OmniAuth is enabled by default. If you're using an
earlier version, you must explicitly enable it.
-You can set up Bitbucket.org as an OAuth2 provider so that you can use your
-Bitbucket.org account credentials to sign into GitLab or import your projects from
+You can set up Bitbucket.org as an OAuth2 provider to use your
+Bitbucket.org account credentials to sign in to GitLab, or import your projects from
Bitbucket.org.
- To use Bitbucket.org as an OmniAuth provider, follow the
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index 5a198e85f5c..b444143b03e 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# CAS OmniAuth Provider
-To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab supplies to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for backchannel logout.
+To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab supplies to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for back-channel logout.
1. On your GitLab server, open the configuration file.
@@ -57,7 +57,7 @@ To enable the CAS OmniAuth provider you must register your application with your
logout_url: '/CAS_PATH/logout' } }
```
-1. Change 'CAS_PATH' to the root of your CAS instance (ie. `cas`).
+1. Change 'CAS_PATH' to the root of your CAS instance (such as `cas`).
1. If your CAS instance does not use default TGC lifetimes, update the `cas3.session_duration` to at least the current TGC maximum lifetime. To explicitly disable SLO, regardless of CAS settings, set this to 0.
diff --git a/doc/integration/chat_commands.md b/doc/integration/chat_commands.md
deleted file mode 100644
index a0361064d87..00000000000
--- a/doc/integration/chat_commands.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'slash_commands.md'
----
-
-This document was moved to [integration/slash_commands.md](slash_commands.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/crowd.md b/doc/integration/crowd.md
deleted file mode 100644
index e07e3435baf..00000000000
--- a/doc/integration/crowd.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/auth/crowd.md'
----
-
-This document was moved to [`administration/auth/crowd`](../administration/auth/crowd.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index b1fc2573bb0..389c7aabdf5 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -5,10 +5,9 @@ group: Global Search
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Elasticsearch integration **(STARTER ONLY)**
+# Elasticsearch integration **(PREMIUM SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109 "Elasticsearch Merge Request") in GitLab [Starter](https://about.gitlab.com/pricing/) 8.4.
-> - Support for [Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1305) in GitLab [Starter](https://about.gitlab.com/pricing/) 9.0.
+> Moved to GitLab Premium in 13.9.
This document describes how to enable Advanced Search. After
Advanced Search is enabled, you'll have the benefit of fast search response times
@@ -87,7 +86,7 @@ updated automatically.
Since Elasticsearch can read and use indices created in the previous major version, you don't need to change anything in the GitLab configuration when upgrading Elasticsearch.
-The only thing worth noting is that if you have created your current index before GitLab 13.0, you might want to [reclaim the production index name](#reclaiming-the-gitlab-production-index-name) or reindex from scratch (which will implicitly create an alias). The latter might be faster depending on the GitLab instance size. Once you do that, you'll be able to perform zero-downtime reindexing and you will benefit from any future features that will make use of the alias.
+The only thing worth noting is that if you have created your current index before GitLab 13.0, you might want to reindex from scratch (which will implicitly create an alias) in order to use some features, for example [Zero downtime reindexing](#zero-downtime-reindexing). Once you do that, you'll be able to perform zero-downtime reindexing and will benefit from any future features that make use of the alias.
## Elasticsearch repository indexer
@@ -152,7 +151,7 @@ cd $indexer_path && sudo make install
The `gitlab-elasticsearch-indexer` will be installed to `/usr/local/bin`.
-You can change the installation path with the `PREFIX` env variable.
+You can change the installation path with the `PREFIX` environment variable.
Please remember to pass the `-E` flag to `sudo` if you do so.
Example:
@@ -175,18 +174,17 @@ instances](#indexing-large-instances) below.
To enable Advanced Search, you need to have admin access to GitLab:
-1. Navigate to **Admin Area**, then **Settings > General**
- and expand the **Advanced Search** section.
+1. Navigate to **Admin Area**, then **Settings > Advanced Search**.
NOTE:
- To see the Advanced Search section, you need an active Starter
+ To see the Advanced Search section, you need an active GitLab Premium
[license](../user/admin_area/license.md).
1. Configure the [Advanced Search settings](#advanced-search-configuration) for
your Elasticsearch cluster. Do not enable **Search with Elasticsearch enabled**
yet.
1. Now enable **Elasticsearch indexing** in **Admin Area > Settings >
- General > Advanced Search** and click **Save changes**. This will create
+ Advanced Search** and click **Save changes**. This will create
an empty index if one does not already exist.
1. Click **Index all projects**.
1. Click **Check progress** in the confirmation message to see the status of
@@ -202,7 +200,7 @@ To enable Advanced Search, you need to have admin access to GitLab:
```
1. After the indexing has completed, enable **Search with Elasticsearch enabled** in
- **Admin Area > Settings > General > Advanced Search** and click **Save
+ **Admin Area > Settings > Advanced Search** and click **Save
changes**.
NOTE:
@@ -218,7 +216,7 @@ The following Elasticsearch settings are available:
| Parameter | Description |
|-------------------------------------------------------|-------------|
| `Elasticsearch indexing` | Enables or disables Elasticsearch indexing and creates an empty index if one does not already exist. You may want to enable indexing but disable search in order to give the index time to be fully completed, for example. Also, keep in mind that this option doesn't have any impact on existing data, this only enables/disables the background indexer which tracks data changes and ensures new data is indexed. |
-| `Pause Elasticsearch indexing` | Enables or disables temporary indexing pause. This is useful for cluster migration/reindexing. All changes are still tracked, but they are not committed to the Elasticsearch index until unpaused. |
+| `Pause Elasticsearch indexing` | Enables or disables temporary indexing pause. This is useful for cluster migration/reindexing. All changes are still tracked, but they are not committed to the Elasticsearch index until resumed. |
| `Search with Elasticsearch enabled` | Enables or disables using Elasticsearch in search. |
| `URL` | The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., `http://host1, https://host2:9200`). If your Elasticsearch instance is password protected, pass the `username:password` in the URL (e.g., `http://<username>:<password>@<elastic_host>:9200/`). |
| `Number of Elasticsearch shards` | Elasticsearch indexes are split into multiple shards for performance reasons. In general, larger indexes need to have more shards. Changes to this value do not take effect until the index is recreated. You can read more about tradeoffs in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html). |
@@ -241,7 +239,7 @@ If you select `Limit namespaces and projects that can be indexed`, more options
![limit namespaces and projects options](img/limit_namespaces_projects_options.png)
You can select namespaces and projects to index exclusively. Note that if the namespace is a group it will include
-any sub-groups and projects belonging to those sub-groups to be indexed as well.
+any subgroups and projects belonging to those subgroups to be indexed as well.
Advanced Search only provides cross-group code/commit search (global) if all name-spaces are indexed. In this particular scenario where only a subset of namespaces are indexed, a global search will not provide a code or commit scope. This will be possible only in the scope of an indexed namespace. Currently there is no way to code/commit search in multiple indexed namespaces (when only a subset of namespaces has been indexed). For example if two groups are indexed, there is no way to run a single code search on both. You can only run a code search on the first group and then on the second.
@@ -260,13 +258,13 @@ from the Elasticsearch index as expected.
## Enabling custom language analyzers
-You can improve the language support for Chinese and Japanese languages by utilizing [smartcn](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) and/or [kuromoji](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) analysis plugins from Elastic.
+You can improve the language support for Chinese and Japanese languages by utilizing [`smartcn`](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) and/or [`kuromoji`](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) analysis plugins from Elastic.
To enable language(s) support:
1. Install the desired plugin(s), please refer to [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/plugins/7.9/installation.html) for plugins installation instructions. The plugin(s) must be installed on every node in the cluster, and each node must be restarted after installation. For a list of plugins, see the table later in this section.
-1. Navigate to the **Admin Area**, then **Settings > General**..
-1. Expand the **Advanced Search** section and locate **Custom analyzers: language support**.
+1. Navigate to the **Admin Area**, then **Settings > Advanced Search**..
+1. Locate **Custom analyzers: language support**.
1. Enable plugin(s) support for **Indexing**.
1. Click **Save changes** for the changes to take effect.
1. Trigger [Zero downtime reindexing](#zero-downtime-reindexing) or reindex everything from scratch to create a new index with updated mappings.
@@ -276,18 +274,17 @@ For guidance on what to install, see the following Elasticsearch language plugin
| Parameter | Description |
|-------------------------------------------------------|-------------|
-| `Enable Chinese (smartcn) custom analyzer: Indexing` | Enables or disables Chinese language support using [smartcn](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) custom analyzer for newly created indices.|
-| `Enable Chinese (smartcn) custom analyzer: Search` | Enables or disables using [smartcn](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) fields for Advanced Search. Please only enable this after [installing the plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html), enabling custom analyzer indexing and recreating the index.|
-| `Enable Japanese (kuromoji) custom analyzer: Indexing` | Enables or disables Japanese language support using [kuromoji](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) custom analyzer for newly created indices.|
-| `Enable Japanese (kuromoji) custom analyzer: Search` | Enables or disables using [kuromoji](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) fields for Advanced Search. Please only enable this after [installing the plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html), enabling custom analyzer indexing and recreating the index.|
+| `Enable Chinese (smartcn) custom analyzer: Indexing` | Enables or disables Chinese language support using [`smartcn`](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) custom analyzer for newly created indices.|
+| `Enable Chinese (smartcn) custom analyzer: Search` | Enables or disables using [`smartcn`](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html) fields for Advanced Search. Please only enable this after [installing the plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html), enabling custom analyzer indexing and recreating the index.|
+| `Enable Japanese (kuromoji) custom analyzer: Indexing` | Enables or disables Japanese language support using [`kuromoji`](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) custom analyzer for newly created indices.|
+| `Enable Japanese (kuromoji) custom analyzer: Search` | Enables or disables using [`kuromoji`](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html) fields for Advanced Search. Please only enable this after [installing the plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html), enabling custom analyzer indexing and recreating the index.|
## Disabling Advanced Search
To disable the Elasticsearch integration:
-1. Navigate to the **Admin Area**, then **Settings > General**.
-1. Expand the **Advanced Search** section and uncheck **Elasticsearch indexing**
- and **Search with Elasticsearch enabled**.
+1. Navigate to the **Admin Area**, then **Settings > Advanced Search**.
+1. Uncheck **Elasticsearch indexing** and **Search with Elasticsearch enabled**.
1. Click **Save changes** for the changes to take effect.
1. (Optional) Delete the existing indexes:
@@ -301,146 +298,19 @@ To disable the Elasticsearch integration:
## Zero downtime reindexing
-The idea behind this reindexing method is to leverage Elasticsearch index alias
-feature to atomically swap between two indices. We'll refer to each index as
-`primary` (online and used by GitLab for read/writes) and `secondary`
-(offline, for reindexing purpose).
-
-Instead of connecting directly to the `primary` index, we'll setup an index
-alias such as we can change the underlying index at will.
-
-NOTE:
-Any index attached to the production alias is deemed a `primary` and will be
-used by the GitLab Advanced Search integration.
-
-### Pause the indexing
-
-In the **Admin Area > Settings > General > Advanced Search** section, select the
-**Pause Elasticsearch Indexing** setting, and then save your change.
-With this, all updates that should happen on your Elasticsearch index will be
-buffered and caught up once unpaused.
-
-The indexing will also be automatically paused when the [**Trigger cluster reindexing**](#trigger-the-reindex-via-the-advanced-search-administration) button is used, and unpaused when the reindexing completes or aborts.
-
-### Setup
-
-NOTE:
-If your index was created with GitLab 13.0 or greater, you can directly
-[trigger the reindex](#trigger-the-reindex-via-the-advanced-search-administration).
-
-This process involves several shell commands and curl invocations, so a good
-initial setup will help for later:
-
-```shell
-# You can find this value under Admin Area > Settings > General > Advanced Search > URL
-export CLUSTER_URL="http://localhost:9200"
-export PRIMARY_INDEX="gitlab-production"
-export SECONDARY_INDEX="gitlab-production-$(date +%s)"
-```
-
-### Reclaiming the `gitlab-production` index name
-
-WARNING:
-It is highly recommended that you take a snapshot of your cluster to ensure
-there is a recovery path if anything goes wrong.
-
-Due to a technical limitation, there will be a slight downtime because of the
-fact that we need to reclaim the current `primary` index to be used as the alias.
-
-To reclaim the `gitlab-production` index name, you need to first create a `secondary` index and then trigger the re-index from `primary`.
-
-#### Creating a secondary index
-
-To create a secondary index, run the following Rake task. The `SKIP_ALIAS`
-environment variable will disable the automatic creation of the Elasticsearch
-alias, which would conflict with the existing index under `$PRIMARY_INDEX`, and will
-not create a separate Issue index:
-
-```shell
-# Omnibus installation
-sudo SKIP_ALIAS=1 gitlab-rake "gitlab:elastic:create_empty_index[$SECONDARY_INDEX]"
-
-# Source installation
-SKIP_ALIAS=1 bundle exec rake "gitlab:elastic:create_empty_index[$SECONDARY_INDEX]"
-```
-
-The index should be created successfully, with the latest index options and
-mappings.
-
-#### Trigger the re-index from `primary`
-
-To trigger the re-index from `primary` index:
-
-1. Use the Elasticsearch [Reindex API](https://www.elastic.co/guide/en/elasticsearch/reference/7.6/docs-reindex.html):
-
- ```shell
- curl --request POST \
- --header 'Content-Type: application/json' \
- --data "{ \"source\": { \"index\": \"$PRIMARY_INDEX\" }, \"dest\": { \"index\": \"$SECONDARY_INDEX\" } }" \
- "$CLUSTER_URL/_reindex?slices=auto&wait_for_completion=false"
- ```
-
- There will be an output like:
-
- ```plaintext
- {"task":"3qw_Tr0YQLq7PF16Xek8YA:1012"}
- ```
-
- Note the `task` value, as it will be useful to follow the reindex progress.
-
-1. Wait for the reindex process to complete by checking the `completed` value.
- Using the `task` value form the previous step:
-
- ```shell
- export TASK_ID=3qw_Tr0YQLq7PF16Xek8YA:1012
- curl "$CLUSTER_URL/_tasks/$TASK_ID?pretty"
- ```
-
- The output will be like:
-
- ```plaintext
- {"completed":false, …}
- ```
-
- After the returned value is `true`, continue to the next step.
-
-1. Ensure that the secondary index has data in it. You can use the
- Elasticsearch API to look for the index size and compare our two indices:
-
- ```shell
- curl $CLUSTER_URL/$PRIMARY_INDEX/_count => 123123
- curl $CLUSTER_URL/$SECONDARY_INDEX/_count => 123123
- ```
-
- NOTE:
- Comparing the document count is more accurate than using the index size, as improvements to the storage might cause the new index to be smaller than the original one.
-
-1. After you are confident your `secondary` index is valid, you can process to
- the creation of the alias.
-
- ```shell
- # Delete the original index
- curl --request DELETE $CLUSTER_URL/$PRIMARY_INDEX
-
- # Create the alias and add the `secondary` index to it
- curl --request POST \
- --header 'Content-Type: application/json' \
- --data "{\"actions\":[{\"add\":{\"index\":\"$SECONDARY_INDEX\",\"alias\":\"$PRIMARY_INDEX\"}}]}}" \
- $CLUSTER_URL/_aliases
- ```
-
- The reindexing is now completed. Your GitLab instance is now ready to use the [automated in-cluster reindexing](#trigger-the-reindex-via-the-advanced-search-administration) feature for future reindexing.
-
-1. Unpause the indexing
-
- Under **Admin Area > Settings > General > Advanced Search**, uncheck the **Pause Elasticsearch Indexing** setting and save.
+The idea behind this reindexing method is to leverage the [Elasticsearch reindex API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html)
+and Elasticsearch index alias feature to perform the operation. We set up an index alias which connects to a
+`primary` index which is used by GitLab for reads/writes. When reindexing process starts, we temporarily pause
+the writes to the `primary` index. Then, we create another index and invoke the Reindex API which migrates the
+index data onto the new index. Once the reindexing job is complete, we switch to the new index by connecting the
+index alias to it which becomes the new `primary` index. At the end, we resume the writes and normal operation resumes.
### Trigger the reindex via the Advanced Search administration
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34069) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
-> - A scheduled index deletion and the ability to cancel it was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38914) in GitLab Starter 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34069) in GitLab 13.2.
+> - A scheduled index deletion and the ability to cancel it was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38914) in GitLab 13.3.
-Under **Admin Area > Settings > General > Advanced Search > Elasticsearch zero-downtime reindexing**, click on **Trigger cluster reindexing**.
+Under **Admin Area > Settings > Advanced Search > Elasticsearch zero-downtime reindexing**, click on **Trigger cluster reindexing**.
Reindexing can be a lengthy process depending on the size of your Elasticsearch cluster.
@@ -449,9 +319,9 @@ After the reindexing is completed, the original index will be scheduled to be de
While the reindexing is running, you will be able to follow its progress under that same section.
-### Mark the most recent reindex job as failed and unpause the indexing
+### Mark the most recent reindex job as failed and resume the indexing
-Sometimes, you might want to abandon the unfinished reindex job and unpause the indexing. You can achieve this via the following steps:
+Sometimes, you might want to abandon the unfinished reindex job and resume the indexing. You can achieve this via the following steps:
1. Mark the most recent reindex job as failed:
@@ -463,7 +333,7 @@ Sometimes, you might want to abandon the unfinished reindex job and unpause the
bundle exec rake gitlab:elastic:mark_reindex_failed RAILS_ENV=production
```
-1. Uncheck the "Pause Elasticsearch indexing" checkbox in **Admin Area > Settings > General > Advanced Search**.
+1. Uncheck the "Pause Elasticsearch indexing" checkbox in **Admin Area > Settings > Advanced Search**.
## Background migrations
@@ -519,8 +389,8 @@ In order to debug issues with the migrations you can check the [`elasticsearch.l
Some migrations are built with a retry limit. If the migration cannot finish within the retry limit,
it will be halted and a notification will be displayed in the Advanced Search integration settings.
It is recommended to check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog) to
-debug why the migration was halted and make any changes before retrying the migration. Once you believe you've
-fixed the cause of the failure, click "Retry migration", and the migration will be scheduled to be retried
+debug why the migration was halted and make any changes before retrying the migration. Once you believe you've
+fixed the cause of the failure, click "Retry migration", and the migration will be scheduled to be retried
in the background.
## GitLab Advanced Search Rake tasks
@@ -539,17 +409,14 @@ The following are some available Rake tasks:
| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects and queues Sidekiq jobs to index them in the background. |
| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100. |
| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. Note that this command will result in a complete wipe of the index, and it should be used with caution. |
-| [`sudo gitlab-rake gitlab:elastic:create_empty_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indexes (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. |
-| [`sudo gitlab-rake gitlab:elastic:delete_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indexes and aliases (if they exist) on the Elasticsearch instance. |
-| [`sudo gitlab-rake gitlab:elastic:recreate_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index[<TARGET_NAME>]` and `gitlab:elastic:create_empty_index[<TARGET_NAME>]`. |
+| [`sudo gitlab-rake gitlab:elastic:create_empty_index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indexes (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. |
+| [`sudo gitlab-rake gitlab:elastic:delete_index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indexes and aliases (if they exist) on the Elasticsearch instance. |
+| [`sudo gitlab-rake gitlab:elastic:recreate_index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index` and `gitlab:elastic:create_empty_index`. |
| [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Performs an Elasticsearch import that indexes the snippets data. |
| [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Displays which projects are not indexed. |
| [`sudo gitlab-rake gitlab:elastic:reindex_cluster`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Schedules a zero-downtime cluster reindexing task. This feature should be used with an index that was created after GitLab 13.0. |
| [`sudo gitlab-rake gitlab:elastic:mark_reindex_failed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake)`] | Mark the most recent re-index job as failed. |
-NOTE:
-The `TARGET_NAME` parameter is optional and will use the default index/alias name from the current `RAILS_ENV` if not set.
-
### Environment variables
In addition to the Rake tasks, there are some environment variables that can be used to modify the process:
@@ -599,7 +466,7 @@ For basic guidance on choosing a cluster configuration you may refer to [Elastic
- Number of CPUs (CPU cores) per node usually corresponds to the `Number of Elasticsearch shards` setting described below.
- A good guideline is to ensure you keep the number of shards per node below 20 per GB heap it has configured. A node with a 30GB heap should therefore have a maximum of 600 shards, but the further below this limit you can keep it the better. This will generally help the cluster stay in good health.
- Small shards result in small segments, which increases overhead. Aim to keep the average shard size between at least a few GB and a few tens of GB. Another consideration is the number of documents, you should aim for this simple formula for the number of shards: `number of expected documents / 5M +1`.
-- `refresh_interval` is a per index setting. You may want to adjust that from default `1s` to a bigger value if you don't need data in realtime. This will change how soon you will see fresh results. If that's important for you, you should leave it as close as possible to the default value.
+- `refresh_interval` is a per index setting. You may want to adjust that from default `1s` to a bigger value if you don't need data in real-time. This will change how soon you will see fresh results. If that's important for you, you should leave it as close as possible to the default value.
- You might want to raise [`indices.memory.index_buffer_size`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indexing-buffer.html) to 30% or 40% if you have a lot of heavy indexing operations.
### Advanced Search integration settings guidance
@@ -799,6 +666,23 @@ 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.
+## Reverting to Basic Search
+
+Sometimes there may be issues with your Elasticsearch index data and as such
+GitLab will allow you to revert to "basic search" when there are no search
+results and assuming that basic search is supported in that scope. This "basic
+search" will behave as though you don't have Advanced Search enabled at all for
+your instance and search using other data sources (such as PostgreSQL data and Git
+data).
+
+## Data recovery: Elasticsearch is a secondary data store only
+
+The use of Elasticsearch in GitLab is only ever as a secondary data store.
+This means that all of the data stored in Elasticsearch can always be derived
+again from other data sources, specifically PostgreSQL and Gitaly. Therefore, if
+the Elasticsearch data store is ever corrupted for whatever reason, you can
+simply reindex everything from scratch.
+
## Troubleshooting
One of the most valuable tools for identifying issues with the Elasticsearch
@@ -823,7 +707,7 @@ There are a couple of ways to achieve that:
This is always correctly identifying whether the current project/namespace
being searched is using Elasticsearch.
-- From the admin area under **Settings > General > Advanced Search** check that the
+- From the admin area under **Settings > Advanced Search** check that the
Advanced Search settings are checked.
Those same settings there can be obtained from the Rails console if necessary:
@@ -980,27 +864,12 @@ problem.
There is a [more structured, lower-level troubleshooting document](../administration/troubleshooting/elasticsearch.md) for when you experience other issues, including poor performance.
-### Known issues
-
-[Elasticsearch `code_analyzer` doesn't account for all code cases](https://gitlab.com/groups/gitlab-org/-/epics/3621).
+### Elasticsearch `code_analyzer` doesn't account for all code cases
The `code_analyzer` pattern and filter configuration is being evaluated for improvement. We have fixed [most edge cases](https://gitlab.com/groups/gitlab-org/-/epics/3621#note_363429094) that were not returning expected search results due to our pattern and filter configuration.
Improvements to the `code_analyzer` pattern and filters are being discussed in [epic 3621](https://gitlab.com/groups/gitlab-org/-/epics/3621).
-### Reverting to Basic Search
-
-Sometimes there may be issues with your Elasticsearch index data and as such
-GitLab will allow you to revert to "basic search" when there are no search
-results and assuming that basic search is supported in that scope. This "basic
-search" will behave as though you don't have Advanced Search enabled at all for
-your instance and search using other data sources (ie. PostgreSQL data and Git
-data).
-
-### Data recovery: Elasticsearch is a secondary data store only
+### Some binary files may not be searchable by name
-The use of Elasticsearch in GitLab is only ever as a secondary data store.
-This means that all of the data stored in Elasticsearch can always be derived
-again from other data sources, specifically PostgreSQL and Gitaly. Therefore, if
-the Elasticsearch data store is ever corrupted for whatever reason, you can
-simply reindex everything from scratch.
+In GitLab 13.9, a change was made where [binary file names are being indexed](https://gitlab.com/gitlab-org/gitlab/-/issues/301083). However, without indexing all projects' data from scratch, only binary files that are added or updated after the GitLab 13.9 release are searchable.
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 858614a0571..0239ba0e818 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Integrate your GitLab instance with GitHub
-You can integrate your GitLab instance with GitHub.com and GitHub Enterprise to
-enable users to import projects from GitHub or sign in to your GitLab instance
-with your GitHub account.
+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.
## Enabling GitHub OAuth
@@ -24,7 +24,7 @@ To prevent an [OAuth2 covert redirect](https://oauth.net/advisories/2014-1-cover
See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
-After you have configured the GitHub provider, you need the following information, which you must substitute in the GitLab configuration file, in the steps shown next.
+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.
| Setting from GitHub | Substitute in the GitLab configuration file | Description |
|:---------------------|:---------------------------------------------|:------------|
@@ -179,7 +179,9 @@ If you're getting the message `Signing in using your GitHub account without a pr
GitLab account is not allowed. Create a GitLab account first, and then connect it to your
GitHub account` when signing in, in GitLab:
-1. Go to your **Profile > Account**.
-1. Under the "Social sign-in" section, click **Connect** near the GitHub icon.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In 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 3bd3099e390..97c5332c438 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -11,12 +11,10 @@ Import projects from GitLab.com and login to your GitLab instance with your GitL
To enable the GitLab.com OmniAuth provider you must register your application with GitLab.com.
GitLab.com generates an application ID and secret key for you to use.
-1. Sign in to GitLab.com
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
-1. Select **Applications** in the left menu.
-
+1. Sign in to GitLab.com.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Applications**.
1. Provide the required details for **Add new application**.
- Name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive.
- Redirect URI:
@@ -29,10 +27,8 @@ GitLab.com generates an application ID and secret key for you to use.
The first link is required for the importer and second for the authorization.
1. Select **Save application**.
-
1. You should now see an **Application ID** and **Secret**. Keep this page open as you continue
configuration.
-
1. On your GitLab server, open the configuration file.
For Omnibus package:
@@ -50,10 +46,9 @@ GitLab.com generates an application ID and secret key for you to use.
```
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
-
1. Add the provider configuration:
- For Omnibus package:
+ For Omnibus installations:
```ruby
gitlab_rails['omniauth_providers'] = [
@@ -76,16 +71,13 @@ GitLab.com generates an application ID and secret key for you to use.
```
1. Change `'YOUR_APP_ID'` to the Application ID from the GitLab.com application page.
-
1. Change `'YOUR_APP_SECRET'` to the secret from the GitLab.com application page.
-
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).
+ - Omnibus GitLab: [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - Source: [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
On the sign-in page, there should now be a GitLab.com icon following the
regular sign-in form. Select the icon to begin the authentication process.
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index 05f129e6049..7dc710615fb 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -10,45 +10,57 @@ info: "To determine the technical writer assigned to the Stage/Group associated
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228893) in GitLab 13.4.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/258206) in GitLab 13.8
-With [Gitpod](https://gitpod.io/) you can describe your dev environment as code to get fully set
-up, compiled, and tested dev environments for any GitLab project. The dev environments are not only
-automated but also prebuilt which means that Gitpod continuously builds your Git branches like a CI
-server. By that you don’t have to wait for dependencies to be downloaded and builds to finish, but
-you can start coding immediately.
+With [Gitpod](https://gitpod.io/) you can describe your development environment as code to get fully
+set up, compiled, and tested development environments for any GitLab project. The development
+environments are not only automated but also prebuilt which means that Gitpod continuously builds
+your Git branches like a CI/CD server.
-In short: With Gitpod you can start coding instantly on any project, branch, and merge request from
-any device, at any time.
+This means you don't have to wait for dependencies to be downloaded and builds to finish, you can start
+coding immediately. With Gitpod you can start coding instantly on any project, branch, and merge
+request from any device, at any time.
-![Gitpod interface](img/gitpod_web_interface_v13_4.png)
+To use the GitLab Gitpod integration, it must be enabled for your GitLab instance. Users of:
-You can launch Gitpod directly from GitLab by clicking the **Gitpod** button from the **Web IDE**
-dropdown on the project page:
-
-![Gitpod Button on Project Page](img/gitpod_button_project_page_v13_4.png)
+- GitLab.com can use it immediately after it's [enabled in their user settings](#enable-gitpod-in-your-user-settings).
+- GitLab self-managed instances can use it after:
+ 1. It's [enabled and configured by a GitLab administrator](#configure-a-self-managed-instance).
+ 1. It's [enabled in their user settings](#enable-gitpod-in-your-user-settings).
To learn more about Gitpod, see their [features](https://www.gitpod.io/features/) and
[documentation](https://www.gitpod.io/docs/).
-To use the GitLab-Gitpod integration, you need to enable it from your user preferences:
+## Enable Gitpod in your user settings
+
+With the Gitpod integration enabled for your GitLab instance, to enable it for yourself:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Account**.
+1. Under **Integrations**, locate the **Gitpod** section.
+1. Check the **Enable Gitpod integration** checkbox and select the **Save changes** button.
-1. From the GitLab UI, click your avatar in the top-right corner, then click **Settings**.
-1. On the left-hand nav, click **Preferences**.
-1. Under **Integrations**, find the **Gitpod** section.
-1. Check **Enable Gitpod**.
+## Configure a self-managed instance **(FREE SELF)**
-Users of GitLab.com can enable it and start using straightaway. Users of GitLab self-managed instances
-can follow the same steps once the integration has been enabled and configured by a GitLab administrator.
+For GitLab self-managed instances, a GitLab administrator needs to:
-## Configure your GitLab instance with Gitpod **(CORE ONLY)**
+1. Set up a Gitpod instance to integrate with GitLab. Refer to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/)
+ to get your instance up and running.
+1. Enable it in GitLab:
+ 1. Go to **Admin Area > Settings > General**.
+ 1. Expand the **Gitpod** configuration section.
+ 1. Check the **Enable Gitpod integration** checkbox.
+ 1. Add your Gitpod instance URL (for example, `https://gitpod.example.com`).
+ 1. Select the **Save changes** button.
-The integration of Gitpod with GitLab is enabled on GitLab.com and available to all users.
-For GitLab self-managed instances, a GitLab administrator needs to enable it through the admin settings.
+Your users then need to [enable it for themselves](#enable-gitpod-in-your-user-settings).
-First, you (GitLab admin) need to set up a Gitpod instance to integrate with GitLab.
-Head over to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/) to
-get your instance up and running. Once done:
+## Launch Gitpod in GitLab
-1. In GitLab, go to **Admin Area > Settings > General**.
-1. Expand the **Gitpod** configuration section.
-1. Check **Enable Gitpod**.
-1. Add your Gitpod instance URL (for example, `https://gitpod.example.com`).
+You can launch Gitpod directly from GitLab by clicking the **Gitpod** button from the **Web IDE**
+dropdown on the project page:
+
+![Gitpod Button on Project Page](img/gitpod_button_project_page_v13_4.png)
+
+A project launched in GitLab looks like:
+
+![Gitpod interface](img/gitpod_web_interface_v13_4.png)
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index 1158d6c9bc8..af9972e825e 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -10,20 +10,29 @@ GitLab supports [Google actions in email](https://developers.google.com/gmail/ma
If correctly set up, emails that require an action are marked in Gmail.
-![gmail_actions_button.png](img/gmail_action_buttons_for_gitlab.png)
+![GMail actions button](img/gmail_action_buttons_for_gitlab.png)
To get this functioning, you need to be registered with Google. For instructions, see
[Register with Google](https://developers.google.com/gmail/markup/registering-with-google).
-*This process has a lot of steps so make sure that you fulfill all requirements set by Google to avoid your application being rejected by Google.*
+This process has many steps. Make sure that you fulfill all requirements set by Google to avoid your application being rejected by Google.
In particular, note:
+<!-- vale gitlab.InclusionCultural = NO -->
+
- The email account used by GitLab to send notification emails must:
- Have a "Consistent history of sending a high volume of mail from your domain
(order of hundred emails a day minimum to Gmail) for a few weeks at least".
- Have a very low rate of spam complaints from users.
- Emails must be authenticated via DKIM or SPF.
-- Before sending the final form ("Gmail Schema Whitelist Request"), you must send a real email from your production server. This means that you must find a way to send this email from the email address you are registering. You can do this by, for example, forwarding the real email from the email address you are registering or going into the rails console on the GitLab server and triggering the email sending from there.
+- Before sending the final form (**Gmail Schema Whitelist Request**), you must
+ send a real email from your production server. This means that you must find
+ a way to send this email from the email address you are registering. You can
+ do this by forwarding the real email from the email address you are
+ registering. You can also go into the Rails console on the GitLab server and
+ trigger sending the email from there.
+
+<!-- vale gitlab.InclusionCultural = YES -->
You can check how it looks going through all the steps laid out in the "Registering with Google" doc in [this GitLab.com issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/1517).
diff --git a/doc/integration/google_workspace_saml.md b/doc/integration/google_workspace_saml.md
new file mode 100644
index 00000000000..7b561750b0f
--- /dev/null
+++ b/doc/integration/google_workspace_saml.md
@@ -0,0 +1,163 @@
+---
+type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Google Workspace SSO provider
+
+Google Workspace (formerly G Suite) is a [Single Sign-on provider](https://support.google.com/a/answer/60224?hl=en) that can be used to authenticate
+with GitLab.
+
+The following documentation enables Google Workspace as a SAML provider for GitLab.
+
+## Configure the Google Workspace SAML app
+
+The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en):
+
+Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account.
+ Follow the instructions in the linked Google Workspace article, where you'll need the following information:
+
+| | Typical value | Description |
+|------------------|--------------------------------------------------|----------------------------------------------------------|
+| Name of SAML App | GitLab | Other names OK. |
+| ACS URL | `https://<GITLAB_DOMAIN>/users/auth/saml/callback` | ACS is short for Assertion Consumer Service. |
+| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. |
+| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, you'll set it to the `issuer` in your GitLab configuration. |
+| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` |
+| Name ID | Primary email address | Make sure someone receives content sent to that address |
+| First name | `first_name` | Required value to communicate with GitLab. |
+| Last name | `last_name` | Required value to communicate with GitLab. |
+
+You will also need to setup the following SAML attribute mappings:
+
+| Google Directory attributes | App attributes |
+|-----------------------------------|----------------|
+| Basic information > Email | `email` |
+| Basic Information > First name | `first_name` |
+| Basic Information > Last name | `last_name` |
+
+You may also use some of this information when you [Configure GitLab](#configure-gitlab).
+
+When configuring the Google Workspace SAML app, be sure to record the following information:
+
+| | Value | Description |
+|-------------|--------------|-----------------------------------------------------------------------------------|
+| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. |
+| Certificate | Downloadable | Run `openssl x509 -in <your_certificate.crt> -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. |
+
+While the Google Workspace Admin provides IDP metadata, Entity ID and SHA-256 fingerprint,
+GitLab does not need that information to connect to the Google Workspace SAML app.
+
+---
+
+Now that the Google Workspace SAML app is configured, it's time to enable it in GitLab.
+
+## Configure GitLab
+
+1. See [Initial OmniAuth Configuration](../integration/omniauth.md#initial-omniauth-configuration)
+ for initial settings.
+
+1. To allow people to register for GitLab, through their Google accounts, add the following
+ values to your configuration:
+
+ **For Omnibus GitLab installations**
+
+ Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
+ gitlab_rails['omniauth_block_auto_created_users'] = false
+ ```
+
+ ---
+
+ **For installations from source**
+
+ Edit `config/gitlab.yml`:
+
+ ```yaml
+ allow_single_sign_on: ["saml"]
+ block_auto_created_users: false
+ ```
+
+1. If an existing GitLab user has the same email address as a Google Workspace user, the registration
+ process automatically links their accounts, if you add the following setting:
+ their email addresses match by adding the following setting:
+
+ **For Omnibus GitLab installations**
+
+ Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['omniauth_auto_link_saml_user'] = true
+ ```
+
+ ---
+
+ **For installations from source**
+
+ Edit `config/gitlab.yml`:
+
+ ```yaml
+ auto_link_saml_user: true
+ ```
+
+1. Add the provider configuration.
+
+For guidance on how to set up these values, see the [SAML General Setup steps](saml.md#general-setup).
+Pay particular attention to the values for:
+
+- `assertion_consumer_service_url`
+- `idp_cert_fingerprint`
+- `idp_sso_target_url`
+- `issuer`
+- `name_identifier_format`
+
+ **For Omnibus GitLab installations**
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://<GITLAB_DOMAIN>/users/auth/saml/callback',
+ idp_cert_fingerprint: '00:00:00:00:00:00:0:00:00:00:00:00:00:00:00:00',
+ idp_sso_target_url: 'https://accounts.google.com/o/saml2/idp?idpid=00000000',
+ issuer: 'https://<GITLAB_DOMAIN>',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress'
+ },
+ label: 'Google Workspace' # optional label for SAML log in button, defaults to "Saml"
+ }
+ ]
+ ```
+
+ **For installations from source**
+
+ ```yaml
+ - {
+ name: 'saml',
+ args: {
+ assertion_consumer_service_url: 'https://<GITLAB_DOMAIN>/users/auth/saml/callback',
+ idp_cert_fingerprint: '00:00:00:00:00:00:0:00:00:00:00:00:00:00:00:00',
+ idp_sso_target_url: 'https://accounts.google.com/o/saml2/idp?idpid=00000000',
+ issuer: 'https://<GITLAB_DOMAIN>',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress'
+ },
+ label: 'Google Workspace' # optional label for SAML log in button, defaults to "Saml"
+ }
+ ```
+
+1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for Omnibus and installations
+ from source respectively for the changes to take effect.
+
+To avoid caching issues, test the result on an incognito or private browser window.
+
+## Troubleshooting
+
+The Google Workspace documentation on [SAML app error messages](https://support.google.com/a/answer/6301076?hl=en) is helpful for debugging if you are seeing an error from Google while signing in.
+Pay particular attention to the following 403 errors:
+
+- `app_not_configured`
+- `app_not_configured_for_user`
diff --git a/doc/integration/img/jira_dev_panel_setup_com_3.png b/doc/integration/img/jira_dev_panel_setup_com_3.png
deleted file mode 100644
index eb3c573a4bb..00000000000
--- a/doc/integration/img/jira_dev_panel_setup_com_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_setup_com_3_v13_9.png b/doc/integration/img/jira_dev_panel_setup_com_3_v13_9.png
new file mode 100644
index 00000000000..fe791637d31
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_setup_com_3_v13_9.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_setup_com_4_v13_9.png b/doc/integration/img/jira_dev_panel_setup_com_4_v13_9.png
new file mode 100644
index 00000000000..08787f12b67
--- /dev/null
+++ b/doc/integration/img/jira_dev_panel_setup_com_4_v13_9.png
Binary files differ
diff --git a/doc/integration/img/oauth_provider_application_form.png b/doc/integration/img/oauth_provider_application_form.png
deleted file mode 100644
index c4546d8b3f5..00000000000
--- a/doc/integration/img/oauth_provider_application_form.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/oauth_provider_application_id_secret.png b/doc/integration/img/oauth_provider_application_id_secret.png
deleted file mode 100644
index 21e442b5d04..00000000000
--- a/doc/integration/img/oauth_provider_application_id_secret.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/oauth_provider_authorized_application.png b/doc/integration/img/oauth_provider_authorized_application.png
deleted file mode 100644
index ebff8529b4e..00000000000
--- a/doc/integration/img/oauth_provider_authorized_application.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/oauth_provider_user_wide_applications.png b/doc/integration/img/oauth_provider_user_wide_applications.png
deleted file mode 100644
index 9cc12555574..00000000000
--- a/doc/integration/img/oauth_provider_user_wide_applications.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 7be2a6efd71..b51ce5de8d7 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -4,9 +4,9 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Jenkins CI service **(CORE)**
+# Jenkins CI service **(FREE)**
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/246756) to Core in GitLab 13.7.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/246756) to GitLab Free in 13.7.
From GitLab, you can trigger a Jenkins build when you push code to a repository, or when a merge
request is created. In return, the Jenkins pipeline status is shown on merge requests widgets and
@@ -64,15 +64,16 @@ Grant a GitLab user access to the select GitLab projects.
1. Grant the user permission to the GitLab projects.
If you're integrating Jenkins with many GitLab projects, consider granting the user global
- Admin permission. Otherwise, add the user to each project, and grant Developer permission.
+ Administrator permission. Otherwise, add the user to each project, and grant Developer permission.
## Configure GitLab API access
Create a personal access token to authorize Jenkins' access to GitLab.
-1. Log in to GitLab as the user to be used with Jenkins.
-1. Click your avatar, then **Settings**.
-1. Click **Access Tokens** in the sidebar.
+1. Sign in to GitLab as the user to be used with Jenkins.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Access Tokens**.
1. Create a personal access token with the **API** scope checkbox checked. For more details, see
[Personal access tokens](../user/profile/personal_access_tokens.md).
1. Record the personal access token's value, because it's required in [Configure the Jenkins server](#configure-the-jenkins-server) section.
@@ -166,7 +167,7 @@ to integrate GitLab and Jenkins.
1. In the configuration of your Jenkins job, in the GitLab configuration section, click **Advanced**.
1. Click the **Generate** button under the **Secret Token** field.
1. Copy the resulting token, and save the job configuration.
-1. In GitLab, create a webhook for your project, enter the trigger URL (e.g. `https://JENKINS_URL/project/YOUR_JOB`) and paste the token in the **Secret Token** field.
+1. In GitLab, create a webhook for your project, enter the trigger URL (such as `https://JENKINS_URL/project/YOUR_JOB`) and paste the token in the **Secret Token** field.
1. After you add the webhook, click the **Test** button, and it should succeed.
## Troubleshooting
@@ -205,8 +206,8 @@ which is set to 10 seconds by default.
To fix this the `gitlab_rails['webhook_timeout']` value must be increased
in the `gitlab.rb` configuration file, followed by the [`gitlab-ctl reconfigure` command](../administration/restart_gitlab.md).
-If you don't find the errors above, but do find *duplicate* entries like below (in `/var/log/gitlab/gitlab-rail`), this
-could also indicate that [webhook requests are timing out](../user/project/integrations/webhooks.md#webhook-fails-or-multiple-webhook-requests-are-triggered):
+If you don't find the errors above, but do find *duplicate* entries like below (in `/var/log/gitlab/gitlab-rail`),
+[webhook requests may be timing out](../user/project/integrations/webhooks.md#webhook-fails-or-multiple-webhook-requests-are-triggered):
```plaintext
2019-10-25_04:22:41.25630 2019-10-25T04:22:41.256Z 1584 TID-ovowh4tek WebHookWorker JID-941fb7f40b69dff3d833c99b INFO: start
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
index b5d68e3183f..2ed87456ea1 100644
--- a/doc/integration/jenkins_deprecated.md
+++ b/doc/integration/jenkins_deprecated.md
@@ -50,7 +50,7 @@ Now navigate to GitLab services page and activate Jenkins
![screen](img/jenkins_gitlab_service.png)
-Done! Now when you push to GitLab - it creates a build for Jenkins, and you can view the merge request build status with a link to the Jenkins build.
+Done! When you push to GitLab, it creates a build for Jenkins. You can view the merge request build status with a link to the Jenkins build.
### Multi-project Configuration
diff --git a/doc/integration/jira.md b/doc/integration/jira.md
deleted file mode 100644
index 0e22bedd1cc..00000000000
--- a/doc/integration/jira.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/project/integrations/jira.md'
----
-
-This document was moved to [another location](../user/project/integrations/jira.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index 1c0b2bdc85e..59a96970d75 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -4,12 +4,11 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Jira Development Panel integration **(CORE)**
+# GitLab Jira Development Panel integration **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2381) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) to GitLab Free in 13.4.
-The Jira Development Panel integration allows you to reference Jira issues within GitLab, displaying
+The Jira Development Panel integration allows you to reference Jira issues in GitLab, displaying
activity in the [Development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/)
in the issue.
@@ -19,8 +18,8 @@ to configure both integrations to take advantage of both sets of features. See a
Depending on your environment, you can enable this integration by either:
-- Configuring the Jira DVCS connector.
-- Using the GitLab for Jira app in the Atlassian Marketplace.
+- Configuring [the Jira DVCS connector](#jira-dvcs-configuration).
+- Using the [GitLab for Jira app](#gitlab-for-jira-app) in the Atlassian Marketplace.
See the [Configuration](#configuration) section for details.
@@ -35,7 +34,7 @@ See the [Configuration](#configuration) section for details.
With this integration, you can access related GitLab merge requests, branches, and commits directly from a Jira issue, reflecting your work in GitLab. From the Development panel, you can open a detailed view and take actions including creating a new merge request from a branch. For more information, see [Usage](#usage).
-This integration connects all GitLab projects to projects in the Jira instance within either:
+This integration connects all GitLab projects to projects in the Jira instance in either:
- A top-level group. A top-level GitLab group is one that does not have any parent group itself. All
the projects of that top-level group, as well as projects of the top-level group's subgroups nesting
@@ -57,13 +56,13 @@ If you're using:
- Self-managed GitLab, self-managed Jira, or both, configure the integration using
[Jira's DVCS Connector](#jira-dvcs-configuration), which syncs data hourly.
-We recommend that a GitLab group administrator or instance administrator (in the case of
+We recommend that a GitLab group maintainer or group owner, or instance administrator (in the case of
self-managed GitLab) set up the integration to simplify administration.
### Jira DVCS configuration
-If you're using GitLab.com and Jira Cloud, we recommend you use the
-[GitLab for Jira app](#gitlab-for-jira-app), unless you have a specific need for the DVCS Connector.
+If you're using GitLab.com and Jira Cloud, use the
+[GitLab for Jira app](#gitlab-for-jira-app) unless you have a specific need for the DVCS Connector.
When configuring Jira DVCS Connector:
@@ -78,14 +77,12 @@ To ensure that regular user account maintenance doesn't impact your integration,
create and use a single-purpose `jira` user in GitLab.
1. In GitLab, create a new application to allow Jira to connect with your GitLab account.
-
- While signed in to the GitLab account that you want Jira to use to connect to GitLab,
- click your profile avatar at the top right, and then click **Settings > Applications**.
- Use the form to create a new application.
-
- In the **Name** field, enter a descriptive name for the integration, such as `Jira`.
-
- For the **Redirect URI** field, enter `https://<gitlab.example.com>/login/oauth/callback`,
+1. Sign in to the GitLab account that you want Jira to use to connect to GitLab.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Applications**.
+1. In the **Name** field, enter a descriptive name for the integration, such as `Jira`.
+1. In the **Redirect URI** field, enter `https://<gitlab.example.com>/login/oauth/callback`,
replacing `<gitlab.example.com>` with your GitLab instance domain. For example, if you are using GitLab.com,
this would be `https://gitlab.com/login/oauth/callback`.
@@ -97,15 +94,14 @@ create and use a single-purpose `jira` user in GitLab.
![GitLab application setup](img/jira_dev_panel_gl_setup_1.png)
- - Check **API** in the Scopes section and uncheck any other checkboxes.
-
+1. Check **API** in the **Scopes** section, and clear any other checkboxes.
1. Click **Save application**. GitLab displays the generated **Application ID**
and **Secret** values. Copy these values, which you use in Jira.
#### Jira DVCS Connector setup
-If you're using GitLab.com and Jira Cloud, we recommend you use the
-[GitLab for Jira app](#gitlab-for-jira-app), unless you have a specific need for the DVCS Connector.
+If you're using GitLab.com and Jira Cloud, use the
+[GitLab for Jira app](#gitlab-for-jira-app) unless you have a specific need for the DVCS Connector.
1. Ensure you have completed the [GitLab configuration](#gitlab-account-configuration-for-dvcs).
1. If you're using Jira Server, go to **Settings (gear) > Applications > DVCS accounts**.
@@ -114,37 +110,39 @@ If you're using GitLab.com and Jira Cloud, we recommend you use the
(We're pretending to be GitHub in this integration, until there's additional platform support in Jira.)
1. Complete the form:
- Select **GitHub Enterprise** for the **Host** field.
+1. Select **GitHub Enterprise** for the **Host** field.
+
+1. In the **Team or User Account** field, enter either:
- In the **Team or User Account** field, enter the relative path of a top-level GitLab group that you have access to,
- or the relative path of your personal namespace.
+ - The relative path of a top-level GitLab group that you have access to.
+ - The relative path of your personal namespace.
![Creation of Jira DVCS integration](img/jira_dev_panel_jira_setup_2.png)
- In the **Host URL** field, enter `https://<gitlab.example.com>/`,
+1. In the **Host URL** field, enter `https://<gitlab.example.com>/`,
replacing `<gitlab.example.com>` with your GitLab instance domain. For example, if you are using GitLab.com,
this would be `https://gitlab.com/`.
NOTE:
If using a GitLab version earlier than 11.3 the **Host URL** value should be `https://<gitlab.example.com>/-/jira`
- For the **Client ID** field, use the **Application ID** value from the previous section.
+1. For the **Client ID** field, use the **Application ID** value from the previous section.
- For the **Client Secret** field, use the **Secret** value from the previous section.
+1. For the **Client Secret** field, use the **Secret** value from the previous section.
- Ensure that the rest of the checkboxes are checked.
+1. Ensure that the rest of the checkboxes are checked.
1. Click **Add** to complete and create the integration.
- Jira takes up to a few minutes to know about (import behind the scenes) all the commits and branches
- for all the projects in the GitLab group you specified in the previous step. These are refreshed
- every 60 minutes.
+ Jira takes up to a few minutes to know about (import behind the scenes) all the commits and branches
+ for all the projects in the GitLab group you specified in the previous step. These are refreshed
+ every 60 minutes.
- In the future, we plan on implementing real-time integration. If you need
- to refresh the data manually, you can do this from the `Applications -> DVCS
- accounts` screen where you initially set up the integration:
+ In the future, we plan on implementing real-time integration. If you need
+ to refresh the data manually, you can do this from the `Applications -> DVCS
+ accounts` screen where you initially set up the integration:
- ![Refresh GitLab information in Jira](img/jira_dev_panel_manual_refresh.png)
+ ![Refresh GitLab information in Jira](img/jira_dev_panel_manual_refresh.png)
To connect additional GitLab projects from other GitLab top-level groups (or personal namespaces), repeat the previous
steps with additional Jira DVCS accounts.
@@ -173,26 +171,26 @@ If there was an issue with SSL/TLS, this error message is generated.
as GitLab is the TLS client.
- The Jira Development Panel integration requires Jira to connect to GitLab, which
causes Jira to be the TLS client. If your GitLab server's certificate is not
- issued by a public certificate authority, the Java truststore on Jira's server
+ issued by a public certificate authority, the Java Truststore on Jira's server
needs to have the appropriate certificate added to it (such as your organization's
root certificate).
Refer to Atlassian's documentation and Atlassian Support for assistance setting up Jira correctly:
- [Adding a certificate to the trust store](https://confluence.atlassian.com/kb/how-to-import-a-public-ssl-certificate-into-a-jvm-867025849.html).
- - Simplest approach is to use [keytool](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html).
- - Add additional roots to Java's default truststore (`cacerts`) to allow Jira to
+ - Simplest approach is to use [`keytool`](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html).
+ - Add additional roots to Java's default Truststore (`cacerts`) to allow Jira to
also trust public certificate authorities.
- If the integration stops working after upgrading Jira's Java runtime, this
- might be because the `cacerts` truststore got replaced.
+ might be because the `cacerts` Truststore got replaced.
- [Troubleshooting connectivity up to and including TLS handshaking](https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html),
using the a java class called `SSLPoke`.
-- Download the class from Atlassian's knowledgebase to Jira's server, for example to `/tmp`.
+- Download the class from Atlassian's knowledge base to Jira's server, for example to `/tmp`.
- Use the same Java runtime as Jira.
- Pass all networking-related parameters that Jira is called with, such as proxy
- settings or an alternative root truststore (`-Djavax.net.ssl.trustStore`):
+ settings or an alternative root Truststore (`-Djavax.net.ssl.trustStore`):
```shell
${JAVA_HOME}/bin/java -Djavax.net.ssl.trustStore=/var/atlassian/application-data/jira/cacerts -classpath /tmp SSLPoke gitlab.example.com 443
@@ -211,7 +209,7 @@ The requested scope is invalid, unknown, or malformed.
Potential resolutions:
-- Verify the URL shown in the browser after being redirected from Jira in step 5 of [Jira DVCS Connector Setp](#jira-dvcs-connector-setup) includes `scope=api` within the query string.
+- Verify the URL shown in the browser after being redirected from Jira in step 5 of [Jira DVCS Connector Setup](#jira-dvcs-connector-setup) includes `scope=api` in the query string.
- If `scope=api` is missing from the URL, return to [GitLab account configuration](#gitlab-account-configuration-for-dvcs) and ensure the application you created in step 1 has the `api` box checked under scopes.
##### Jira error adding account and no repositories listed
@@ -230,7 +228,7 @@ Potential resolutions:
- If you're using GitLab versions 11.10-12.7, upgrade to GitLab 12.8.10 or later
to resolve an identified [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/37012).
-- If you're using GitLab Core or GitLab Starter, be sure you're using
+- If you're using GitLab Free or GitLab Starter, be sure you're using
GitLab 13.4 or later.
[Contact GitLab Support](https://about.gitlab.com/support/) if none of these reasons apply.
@@ -248,30 +246,40 @@ resynchronize the information. To do so:
the button. For more information, see
[Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
-### GitLab for Jira app
+### GitLab for Jira app **(FREE SAAS)**
-You can integrate GitLab.com and Jira Cloud using the [GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) app in the Atlassian Marketplace.
+You can integrate GitLab.com and Jira Cloud using the
+[GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
+app in the Atlassian Marketplace. The user configuring GitLab for Jira must have
+[Maintainer](../user/permissions.md) permissions in the GitLab namespace.
-This method is recommended when using GitLab.com and Jira Cloud because data is synchronized in realtime, while the DVCS connector updates data only once per hour. If you are not using both of these environments, use the [Jira DVCS Connector](#jira-dvcs-configuration) method.
+This method is recommended when using GitLab.com and Jira Cloud because data is synchronized in real-time. The DVCS connector updates data only once per hour. If you are not using both of these environments, use the [Jira DVCS Connector](#jira-dvcs-configuration) method.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For a walkthrough of the integration with GitLab for Jira, watch [Configure GitLab Jira Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
-1. Click **GitLab for Jira**, then click **Get it now**. Or go the [App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
+1. Click **GitLab for Jira**, then click **Get it now**, or go to the
+ [App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud).
![Install GitLab App on Jira](img/jira_dev_panel_setup_com_1.png)
-1. After installing, click **Get started** to go to the configurations page. This page is always available under **Jira Settings > Apps > Manage apps**.
+1. After installing, click **Get started** to go to the configurations page.
+ This page is always available under **Jira Settings > Apps > Manage apps**.
![Start GitLab App configuration on Jira](img/jira_dev_panel_setup_com_2.png)
-1. In **Namespace**, enter the group or personal namespace, and then click
- **Link namespace to Jira**. The user setting up *GitLab for Jira* must have
- *Maintainer* access to the GitLab namespace.
+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.
-NOTE:
-The GitLab user only needs access when adding a new namespace. For syncing with Jira, we do not depend on the user's token.
+ ![Sign in to GitLab.com in GitLab Jira App](img/jira_dev_panel_setup_com_3_v13_9.png)
+1. Select **Add namespace** to open the list of available namespaces.
+
+1. Identify the namespace you want to link, and select **Link**.
- ![Configure namespace on GitLab Jira App](img/jira_dev_panel_setup_com_3.png)
+ ![Link namespace in GitLab Jira App](img/jira_dev_panel_setup_com_4_v13_9.png)
+
+NOTE:
+The GitLab user only needs access when adding a new namespace. For syncing with
+Jira, we do not depend on the user's token.
After a namespace is added:
@@ -285,11 +293,11 @@ For more information, see [Usage](#usage).
#### Troubleshooting GitLab for Jira
-The GitLab for Jira App uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies which can lead to a message saying that the user needs to log in on GitLab.com even though the user is already logged in.
+The GitLab for Jira App uses an iframe to add namespaces on the settings page. Some browsers block cross-site cookies. This can lead to a message saying that the user needs to log in on GitLab.com even though the user is already logged in.
> "You need to sign in or sign up before continuing."
-In this case, use [Firefox](https://www.mozilla.org/en-US/firefox/), [Google Chrome](https://www.google.com/chrome/index.html) or enable cross-site cookies in your browser.
+In this case, use [Firefox](https://www.mozilla.org/en-US/firefox/) or enable cross-site cookies in your browser.
## Usage
@@ -314,6 +322,6 @@ For more information on using Jira Smart Commits to track time against an issue,
## Limitations
-This integration is currently not supported on GitLab instances under a
+This integration is not supported on GitLab instances under a
[relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab).
For example, `http://example.com/gitlab`.
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 390c3ae3e7c..5be076464d8 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, how-to
---
-# Kerberos integration **(STARTER ONLY)**
+# Kerberos integration **(PREMIUM SELF)**
GitLab can integrate with [Kerberos](https://web.mit.edu/kerberos/) as an authentication mechanism.
@@ -109,15 +109,16 @@ existing GitLab account. To do so:
1. Navigate to **Admin Area > Overview > Users > Example User**.
1. Select the Identities tab.
-1. Select 'Kerberos Spnego' in the 'Provider' dropdown box.
+1. Select 'Kerberos SPNEGO' in the 'Provider' dropdown box.
1. Make sure the **Identifier** corresponds to the Kerberos username.
1. Select **Save changes**.
If you're not an administrator:
-1. Select your avatar in the upper-right corner, and select **Settings**.
-1. Select Account. In the **Social sign-in** section, select
- **Connect Kerberos Spnego**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Account**.
+1. In the **Social sign-in** section, select **Connect Kerberos SPNEGO**.
If you don't see a **Social sign-in** Kerberos option, follow the
requirements in [Enable single sign-on](#enable-single-sign-on).
@@ -291,10 +292,10 @@ remove support for password-based Kerberos sign-ins in a future
release, so we recommend that you upgrade to ticket-based sign-ins.
Depending on your existing GitLab configuration, the 'Sign in with:
-Kerberos Spnego' button may already be visible on your GitLab sign-in
+Kerberos SPNEGO' button may already be visible on your GitLab sign-in
page. If not, then add the settings [described above](#configuration).
-Once you have verified that the 'Kerberos Spnego' button works
+Once you have verified that the 'Kerberos SPNEGO' button works
without entering any passwords, you can proceed to disable
password-based Kerberos sign-ins. To do this you need only need to
remove the OmniAuth provider named `kerberos` from your `gitlab.yml` /
diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md
deleted file mode 100644
index 55c169bca80..00000000000
--- a/doc/integration/ldap.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/auth/ldap/index.md'
----
-
-This document was moved to [`administration/auth/ldap`](../administration/auth/ldap/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
index 88e9e3ef05c..41656bd2216 100644
--- a/doc/integration/oauth2_generic.md
+++ b/doc/integration/oauth2_generic.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Sign into GitLab with (almost) any OAuth2 provider
-The `omniauth-oauth2-generic` gem allows Single Sign On between GitLab and your own OAuth2 provider
+The `omniauth-oauth2-generic` gem allows Single Sign-On between GitLab and your own OAuth2 provider
(or any OAuth2 provider compatible with this gem)
This strategy is designed to allow configuration of the simple OmniAuth SSO process outlined below:
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index 82cb409c560..377c8ec82d0 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -1,83 +1,88 @@
---
-stage: Create
-group: Ecosystem
+stage: Manage
+group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# GitLab as OAuth2 authentication service provider
-This document is about using GitLab as an OAuth authentication service provider
-to sign in to other services.
+This document describes how you can use GitLab as an OAuth 2
+authentication service provider.
If you want to use:
- The [OAuth2](https://oauth.net/2/) protocol to access GitLab resources on user's behalf,
- see [OAuth2 provider](../api/oauth2.md)
-- Other OAuth authentication service providers to sign in to
+ see [OAuth2 provider](../api/oauth2.md).
+- Other OAuth 2 authentication service providers to sign in to
GitLab, see the [OAuth2 client documentation](omniauth.md).
- The related API, see [Applications API](../api/applications.md).
## Introduction to OAuth
-[OAuth](https://oauth.net/2/) provides to client applications a 'secure delegated access' to server
-resources on behalf of a resource owner. In fact, OAuth allows an authorization
-server to issue access tokens to third-party clients with the approval of the
-resource owner, or the end-user.
+[OAuth 2](https://oauth.net/2/) provides to client applications a 'secure delegated
+access' to server resources on behalf of a resource owner. OAuth 2 allows
+authorization servers to issue access tokens to third-party clients with the approval
+of the resource owner or the end-user.
-OAuth is mostly used as a Single Sign-On service (SSO), but you can find a
-lot of different uses for this functionality. For example, you can allow users
-to sign in to your application with their GitLab.com account, or GitLab.com
-can be used for authentication to your GitLab instance
+OAuth 2 can be used:
+
+- To allow users to sign in to your application with their GitLab.com account.
+- To set up GitLab.com for authentication to your GitLab instance.
(see [GitLab OmniAuth](gitlab.md)).
-The 'GitLab Importer' feature is also using the OAuth protocol to give access
+The 'GitLab Importer' feature also uses OAuth 2 to give access
to repositories without sharing user credentials to your GitLab.com account.
-GitLab supports two ways of adding a new OAuth2 application to an instance. You
-can either add an application as a regular user or add it in the Admin Area.
-What this means is that GitLab can actually have instance-wide and a user-wide
-applications. There is no difference between them except for the different
-permission levels they are set (user/admin). The default callback URL is
-`http://your-gitlab.example.com/users/auth/gitlab/callback`
-
-## Adding an application through the profile
+GitLab supports two ways of adding a new OAuth 2 application to an instance:
-In order to add a new application via your profile, navigate to
-**Profile Settings > Applications** and select **New Application**.
+- As a regular user, for applications owned by an individual.
+- Through the Admin Area menu for instance-wide apps.
-![New OAuth application](img/oauth_provider_user_wide_applications.png)
+The only difference between these two methods is the [permission](../user/permissions.md)
+levels. The default callback URL is `http://your-gitlab.example.com/users/auth/gitlab/callback`.
-In the application form, enter a **Name** (arbitrary), and make sure to set up
-correctly the **Redirect URI** which is the URL where users are sent after
-they authorize with GitLab.
+## Add an application through the profile
-![New OAuth application form](img/oauth_provider_application_form.png)
+To add a new application via your profile:
-When you click **Submit** you are provided with the application ID and
-the application secret which you can then use with your application that
-connects to GitLab.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Applications**.
+1. Enter a **Name**, **Redirect URI** and OAuth 2 scopes as defined in [Authorized Applications](#authorized-applications).
+ The **Redirect URI** is the URL where users are sent after they authorize with GitLab.
+1. Select **Save application**. GitLab displays:
-![OAuth application ID and secret](img/oauth_provider_application_id_secret.png)
+ - Application ID: OAuth 2 Client ID.
+ - Secret: OAuth 2 Client Secret.
## OAuth applications in the Admin Area
-To create an application that does not belong to a certain user, you can create
-it from the Admin Area.
-
-![OAuth admin_applications](img/oauth_provider_admin_application.png)
+To create an application for your GitLab instance, select
+**Admin Area > Applications > New application**.
-You're also able to mark an application as _trusted_ when creating it through the Admin Area. By doing that,
-the user authorization step is automatically skipped for this application.
+When creating an **Admin Area** application, you can mark it as _trusted_.
+The user authorization step is automatically skipped for this application.
## Authorized applications
-Every application you authorized to use your GitLab credentials is shown
-in the **Authorized applications** section under **Profile Settings > Applications**.
-
-![Authorized_applications](img/oauth_provider_authorized_application.png)
-
-The GitLab OAuth applications support scopes, which allow various actions that any given
-application can perform such as `read_user` and `api`. There are many more scopes
-available.
-
-At any time you can revoke any access by just clicking **Revoke**.
+Every application you authorize with your GitLab credentials is shown
+in the **Authorized applications** section under **Settings > Applications**.
+
+The GitLab OAuth 2 applications support scopes, which allow various actions that any given
+application can perform. Available scopes are depicted in the following table.
+
+| Scope | Description |
+| ------------------ | ----------- |
+| `api` | Grants complete read/write access to the API, including all groups and projects, the container registry, and the package registry. |
+| `read_user` | Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users. |
+| `read_api` | Grants read access to the API, including all groups and projects, the container registry, and the package registry. |
+| `read_repository` | Grants read-only access to repositories on private projects using Git-over-HTTP or the Repository Files API. |
+| `write_repository` | Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API). |
+| `read_registry` | Grants read-only access to container registry images on private projects. |
+| `write_registry` | Grants read-only access to container registry images on private projects. |
+| `sudo` | Grants permission to perform API actions as any user in the system, when authenticated as an administrator user. |
+| `openid` | Grants permission to authenticate with GitLab using [OpenID Connect](openid_connect_provider.md). Also gives read-only access to the user's profile and group memberships. |
+| `profile` | Grants read-only access to the user's profile data using [OpenID Connect](openid_connect_provider.md). |
+| `email` | Grants read-only access to the user's primary email address using [OpenID Connect](openid_connect_provider.md). |
+
+At any time you can revoke any access by clicking **Revoke**.
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 53c19ddfdb1..cf033018e17 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -55,7 +55,7 @@ earlier version, you must explicitly enable it.
- `allow_single_sign_on` allows you to specify the providers you want to allow to
automatically create an account. It defaults to `false`. If `false` users must
- be created manually or they can't sign in via OmniAuth.
+ be created manually or they can't sign in by using OmniAuth.
- `auto_link_ldap_user` can be used if you have [LDAP / ActiveDirectory](../administration/auth/ldap/index.md)
integration enabled. It defaults to `false`. When enabled, users automatically
created through an OmniAuth provider have their LDAP identity created in GitLab as well.
@@ -66,7 +66,7 @@ earlier version, you must explicitly enable it.
NOTE:
If you set `block_auto_created_users` to `false`, make sure to only
define providers under `allow_single_sign_on` that you are able to control, like
-SAML, Shibboleth, Crowd or Google, or set it to `false` otherwise any user on
+SAML, Shibboleth, Crowd, or Google. Otherwise, set it to `false`, or any user on
the Internet can successfully sign in to your GitLab without
administrative approval.
@@ -138,9 +138,10 @@ provider such as Twitter can be enabled. Follow the steps below to enable an
OmniAuth provider for an existing user.
1. Sign in normally - whether standard sign in, LDAP, or another OmniAuth provider.
-1. Go to profile settings (the silhouette icon in the top right corner).
-1. Select the "Account" tab.
-1. Under "Connected Accounts" select the desired OmniAuth provider, such as Twitter.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Account**.
+1. In the **Connected Accounts** section, select the desired OmniAuth provider, such as Twitter.
1. The user is redirected to the provider. After the user authorizes GitLab,
they are redirected back to GitLab.
@@ -168,10 +169,8 @@ omniauth:
## Configure OmniAuth Providers as External
-> Introduced in GitLab 8.7.
-
-You can define which OmniAuth providers you want to be `external` so that all users
-**creating accounts, or logging in via these providers** can't have
+You can define which OmniAuth providers you want to be `external`. Users
+creating accounts, or logging in by using these `external` providers cannot have
access to internal projects. You must use the full name of the provider,
like `google_oauth2` for Google. Refer to the examples for the full names of the
supported providers.
@@ -200,9 +199,9 @@ NOTE:
The following information only applies for installations from source.
GitLab uses [OmniAuth](https://github.com/omniauth/omniauth) for authentication and already ships
-with a few providers pre-installed (e.g. LDAP, GitHub, Twitter). But sometimes that
-is not enough and you need to integrate with other authentication solutions. For
-these cases you can use the OmniAuth provider.
+with a few providers pre-installed, such as LDAP, GitHub, and Twitter. You may also
+need to integrate with other authentication solutions. For
+these cases, you can use the OmniAuth provider.
### Steps
@@ -215,7 +214,7 @@ from the OmniAuth provider's documentation.
sudo service gitlab stop
```
-- Add the gem to your [Gemfile](https://gitlab.com/gitlab-org/gitlab/blob/master/Gemfile):
+- Add the gem to your [`Gemfile`](https://gitlab.com/gitlab-org/gitlab/blob/master/Gemfile):
```shell
gem "omniauth-your-auth-provider"
@@ -240,25 +239,28 @@ from the OmniAuth provider's documentation.
If you have successfully set up a provider that is not shipped with GitLab itself,
please let us know.
+Share your experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Custom-omniauth-provider-configurations).
You can help others by reporting successful configurations and probably share a
-few insights or provide warnings for common errors or pitfalls by sharing your
-experience [in the public Wiki](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Custom-omniauth-provider-configurations).
+few insights or provide warnings for common errors or pitfalls.
While we can't officially support every possible authentication mechanism out there,
we'd like to at least help those with specific needs.
## Enable or disable Sign In with an OmniAuth provider without disabling import sources
-> Introduced in GitLab 8.8.
-
-Administrators are able to enable or disable Sign In via some OmniAuth providers.
+Administrators are able to enable or disable **Sign In** by using some OmniAuth providers.
NOTE:
-By default Sign In is enabled via all the OAuth Providers that have been configured in `config/gitlab.yml`.
+By default, **Sign In** is enabled by using all the OAuth Providers that have been configured in `config/gitlab.yml`.
+
+To enable/disable an OmniAuth provider:
-In order to enable/disable an OmniAuth provider, go to Admin Area -> Settings -> Sign-in Restrictions section -> Enabled OAuth Sign-In sources and select the providers you want to enable or disable.
+1. In the top navigation bar, go to **Admin Area**.
+1. In the left sidebar, go to **Settings**.
+1. Scroll to the **Sign-in Restrictions** section, and click **Expand**.
+1. Next to **Enabled OAuth Sign-In sources**, select the check box for each provider you want to enable or disable.
-![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png)
+ ![Enabled OAuth Sign-In sources](img/enabled-oauth-sign-in-sources.png)
## Disabling OmniAuth
@@ -325,7 +327,7 @@ omniauth:
You can add the `auto_sign_in_with_provider` setting to your GitLab
configuration to redirect login requests to your OmniAuth provider for
-authentication, removing the need to click a button before actually signing in.
+authentication. This removes the need to click a button before actually signing in.
For example, when using the Azure integration, set the following to enable auto
sign-in:
@@ -345,7 +347,7 @@ omniauth:
Keep in mind that every sign-in attempt is redirected to the OmniAuth
provider; you can't sign in using local credentials. Ensure at least
-one of the OmniAuth users has admin permissions.
+one of the OmniAuth users has administrator permissions.
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/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
index 5bf079df800..4455ace3e1f 100644
--- a/doc/integration/openid_connect_provider.md
+++ b/doc/integration/openid_connect_provider.md
@@ -12,11 +12,12 @@ to sign in to other services.
## Introduction to OpenID Connect
[OpenID Connect](https://openid.net/connect/) \(OIDC) is a simple identity layer on top of the
-OAuth 2.0 protocol. It allows clients to verify the identity of the end-user
-based on the authentication performed by GitLab, as well as to obtain
-basic profile information about the end-user in an interoperable and
-REST-like manner. OIDC performs many of the same tasks as OpenID 2.0,
-but does so in a way that is API-friendly, and usable by native and
+OAuth 2.0 protocol. It allows clients to:
+
+- Verify the identity of the end-user based on the authentication performed by GitLab.
+- Obtain basic profile information about the end-user in an interoperable and REST-like manner.
+
+OIDC performs many of the same tasks as OpenID 2.0, but is API-friendly and usable by native and
mobile applications.
On the client side, you can use [OmniAuth::OpenIDConnect](https://github.com/jjbohn/omniauth-openid-connect/) for Rails
@@ -34,7 +35,7 @@ is select the `openid` scope in the application settings.
## Shared information
-Currently the following user information is shared with clients:
+The following user information is shared with clients:
| Claim | Type | Description |
|:-----------------|:----------|:------------|
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index bb5425187c1..8f090dfc588 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -14,7 +14,7 @@ to confirm that a real user, not a bot, is attempting to create an account.
To use reCAPTCHA, first you must create a site and private key.
-1. Go to the URL: <https://www.google.com/recaptcha/admin>.
+1. Go to the [Google reCAPTCHA page](https://www.google.com/recaptcha/admin).
1. Fill out the form necessary to obtain reCAPTCHA v2 keys.
1. Log in to your GitLab server, with administrator credentials.
1. Go to Reporting Applications Settings in the Admin Area (`admin/application_settings/reporting`).
@@ -26,7 +26,7 @@ To use reCAPTCHA, first you must create a site and private key.
return `recaptcha_html`.
NOTE:
-Make sure you are viewing an issuable in a project that is public, and if you're working with an issue, the issue is public.
+Make sure you are viewing an issuable in a project that is public. If you're working with an issue, the issue is public.
## Enabling reCAPTCHA for user logins via passwords
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index 1aca3b04eee..156109518a6 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -86,4 +86,6 @@ Click the icon to begin the authentication process. Salesforce asks the user to
If everything goes well, the user is returned to GitLab and is signed in.
NOTE:
-GitLab requires the email address of each new user. Once the user is logged in using Salesforce, GitLab redirects the user to the profile page where they must provide the email and verify the email.
+GitLab requires the email address of each new user. After the user is signed in
+using Salesforce, GitLab redirects the user to the profile page where they must
+provide the email and verify the email.
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index af0a58eab59..9b6ad3f2755 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -5,7 +5,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# SAML OmniAuth Provider **(CORE ONLY)**
+# SAML OmniAuth Provider **(FREE SELF)**
This page describes instance-wide SAML for self-managed GitLab instances. For SAML on GitLab.com, see [SAML SSO for GitLab.com groups](../user/group/saml_sso/index.md).
@@ -17,7 +17,7 @@ You should also reference the [OmniAuth documentation](omniauth.md) for general
|------|-------------|
| Identity Provider (IdP) | The service which manages your user identities such as ADFS, Okta, Onelogin, or Ping Identity. |
| Service Provider (SP) | SAML considers GitLab to be a service provider. |
-| Assertion | A piece of information about a user's identity, such as their name or role. Also know as claims or attributes. |
+| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. |
| SSO | Single Sign-On. |
| Assertion consumer service URL | The callback on GitLab where users will be redirected after successfully authenticating with the identity provider. |
| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
@@ -163,9 +163,21 @@ will be returned to GitLab and will be signed in.
## SAML Groups
-You can require users to be members of a certain group, or assign users `external`, `admin` or `auditor` roles based on group membership. This feature **does not** allow you to
+You can require users to be members of a certain group, or assign users [external](../user/permissions.md#external-users), admin or [auditor](../user/permissions.md#auditor-users) roles based on group membership.
+These groups are checked on each SAML login and user attributes updated as necessary.
+This feature **does not** allow you to
automatically add users to GitLab [Groups](../user/group/index.md).
+Support for these groups depends on your [subscription](https://about.gitlab.com/pricing/)
+and whether you've installed [GitLab Enterprise Edition (EE)](https://about.gitlab.com/install/).
+
+| Group | Tier | GitLab Enterprise Edition (EE) Only? |
+|------------------------------|--------------------|--------------------------------------|
+| [Required](#required-groups) | **(FREE SELF)** | Yes |
+| [External](#external-groups) | **(FREE SELF)** | No |
+| [Admin](#admin-groups) | **(FREE SELF)** | Yes |
+| [Auditor](#auditor-groups) | **(PREMIUM SELF)** | Yes |
+
### Requirements
First you need to tell GitLab where to look for group information. For this you
@@ -187,7 +199,7 @@ The name of the attribute can be anything you like, but it must contain the grou
to which a user belongs. In order to tell GitLab where to find these groups, you need
to add a `groups_attribute:` element to your SAML settings.
-### Required groups **(STARTER ONLY)**
+### Required groups **(FREE SELF)**
Your IdP passes Group Information to the SP (GitLab) in the SAML Response. You need to configure GitLab to identify:
@@ -213,9 +225,9 @@ Example:
} }
```
-### External Groups **(STARTER ONLY)**
+### External groups **(FREE SELF)**
-SAML login supports automatic identification on whether a user should be considered an [external](../user/permissions.md) user. This is based on the user's group membership in the SAML identity provider.
+SAML login supports automatic identification on whether a user should be considered an [external user](../user/permissions.md#external-users). This is based on the user's group membership in the SAML identity provider.
```yaml
{ name: 'saml',
@@ -231,7 +243,7 @@ SAML login supports automatic identification on whether a user should be conside
} }
```
-### Admin Groups **(STARTER ONLY)**
+### Admin groups **(FREE SELF)**
The requirements are the same as the previous settings, your IdP needs to pass Group information to GitLab, you need to tell
GitLab where to look for the groups in the SAML response, and which group(s) should be
@@ -251,13 +263,13 @@ considered admin users.
} }
```
-### Auditor Groups **(STARTER ONLY)**
+### Auditor groups **(PREMIUM SELF)**
> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 11.4.
The requirements are the same as the previous settings, your IdP needs to pass Group information to GitLab, you need to tell
GitLab where to look for the groups in the SAML response, and which group(s) should be
-considered auditor users.
+considered [auditor users](../user/permissions.md#auditor-users).
```yaml
{ name: 'saml',
@@ -385,7 +397,7 @@ This setting should be used only to map attributes that are part of the OmniAuth
`attribute_statements` is used to map Attribute Names in a SAMLResponse to entries
in the OmniAuth [`info` hash](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later).
-For example, if your SAMLResponse contains an Attribute called 'EmailAddress',
+For example, if your SAMLResponse contains an Attribute called `EmailAddress`,
specify `{ email: ['EmailAddress'] }` to map the Attribute to the
corresponding key in the `info` hash. URI-named Attributes are also supported, e.g.
`{ email: ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'] }`.
@@ -582,8 +594,8 @@ GitLab will sign the request with the provided private key. GitLab will include
Avoid user control of the following attributes:
-- [`*NameID*`](../user/group/saml_sso/index.md#nameid)
-- *Email* when used with `omniauth_auto_link_saml_user`
+- [`NameID`](../user/group/saml_sso/index.md#nameid)
+- `Email` when used with `omniauth_auto_link_saml_user`
These attributes define the SAML user. If users can change these attributes, they can impersonate others.
@@ -593,7 +605,7 @@ Refer to the documentation for your SAML Identity Provider for information on ho
The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML.
-## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM ONLY)**
+## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM SELF)**
For information on the GitLab.com implementation, please see the [SAML SSO for GitLab.com groups page](../user/group/saml_sso).
diff --git a/doc/integration/security_partners/index.md b/doc/integration/security_partners/index.md
new file mode 100644
index 00000000000..1cd14947e74
--- /dev/null
+++ b/doc/integration/security_partners/index.md
@@ -0,0 +1,23 @@
+---
+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/#designated-technical-writers
+type: index
+---
+
+# Security partner integrations
+
+You can integrate GitLab with its security partners. This page has information on how do this with
+each security partner:
+
+<!-- vale gitlab.Spelling = NO -->
+
+- [Anchore](https://docs.anchore.com/current/docs/using/integration/ci_cd/gitlab/)
+- [Bridgecrew](https://docs.bridgecrew.io/docs/integrate-with-gitlab-self-managed)
+- [Checkmarx](https://checkmarx.atlassian.net/wiki/spaces/SD/pages/1929937052/GitLab+Integration)
+- [Indeni](https://indeni.com/doc-indeni-cloudrail/integrate-with-ci-cd/gitlab-instructions/)
+- [JScrambler](https://docs.jscrambler.com/code-integrity/documentation/gitlab-ci-integration)
+- [StackHawk](https://docs.stackhawk.com/continuous-integration/gitlab.html)
+- [WhiteSource](https://www.whitesourcesoftware.com/gitlab/)
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index e811cac4f0b..3b92f2858ac 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -10,17 +10,17 @@ NOTE:
The preferred approach for integrating a Shibboleth authentication system
with GitLab 10 or newer is to use the [GitLab SAML integration](saml.md). This documentation is for Omnibus GitLab 9.x installs or older.
-In order to enable Shibboleth support in GitLab we need to use Apache instead of NGINX (It may be possible to use NGINX, however this is difficult to configure using the bundled NGINX provided in the Omnibus GitLab package). Apache uses mod_shib2 module for Shibboleth authentication and can pass attributes as headers to OmniAuth Shibboleth provider.
+To enable Shibboleth support in GitLab we need to use Apache instead of NGINX. (It may be possible to use NGINX, however this is difficult to configure using the bundled NGINX provided in the Omnibus GitLab package.) Apache uses `mod_shib2` module for Shibboleth authentication and can pass attributes as headers to OmniAuth Shibboleth provider.
To enable the Shibboleth OmniAuth provider you must configure Apache Shibboleth module.
The installation and configuration of the module itself is out of the scope of this document.
-Check <https://wiki.shibboleth.net/confluence/display/SP3/Apache> for more information.
+Check [the Shibboleth documentation](https://wiki.shibboleth.net/confluence/display/SP3/Apache) for more information.
You can find Apache configuration in [GitLab Recipes](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache).
The following changes are needed to enable Shibboleth:
-1. Protect OmniAuth Shibboleth callback URL:
+1. Protect the OmniAuth Shibboleth callback URL:
```apache
<Location /users/auth/shibboleth/callback>
@@ -53,7 +53,7 @@ The following changes are needed to enable Shibboleth:
```
NOTE:
- Starting from GitLab 11.4, OmniAuth is enabled by default. If you're using an
+ In GitLab versions 11.4 and later, OmniAuth is enabled by default. If you're using an
earlier version, you must explicitly enable it in `/etc/gitlab/gitlab.rb`.
1. In addition, add Shibboleth to `/etc/gitlab/gitlab.rb` as an OmniAuth provider.
@@ -100,7 +100,7 @@ The following changes are needed to enable Shibboleth:
1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect if you
installed GitLab via Omnibus or from source respectively.
-On the sign in page, there should now be a "Sign in with: Shibboleth" icon below the regular sign in form. Click the icon to begin the authentication process. You are redirected to IdP server (depends on your Shibboleth module configuration). If everything goes well the user is returned to GitLab and is signed in.
+On the sign in page, there should now be a **Sign in with: Shibboleth** icon below the regular sign in form. Click the icon to begin the authentication process. You are redirected to IdP server (depends on your Shibboleth module configuration). If everything goes well the user is returned to GitLab and is signed in.
## Apache 2.4 / GitLab 8.6 update
diff --git a/doc/integration/slack.md b/doc/integration/slack.md
deleted file mode 100644
index fbea9d3035c..00000000000
--- a/doc/integration/slack.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/project/integrations/slack.md'
----
-
-This document was moved to [another location](../user/project/integrations/slack.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index 6820ff8a0aa..0dcf86cc46d 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Slash Commands
-> The `run` command was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6. [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to GitLab Free in 11.9.
-Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires an [integration configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it.
+Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires an [integration configuration](../user/project/integrations/slack_slash_commands.md). Type the command as a message in your chat client to activate it.
Commands are scoped to a project, with a trigger term that is specified during configuration.
@@ -26,22 +26,22 @@ Taking the trigger term as `project-name`, the commands are:
| `/project-name issue move <id> to <project>` | Moves issue ID `<id>` to `<project>` |
| `/project-name issue comment <id> <shift+return> <comment>` | Adds a new comment to an issue with ID `<id>` and comment body `<comment>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
-| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/README.md) job `<job name>` on `master` |
+| `/project-name run <job name> <arguments>` | Execute [ChatOps](../ci/chatops/index.md) job `<job name>` on `master` |
-Note that if you are using the [GitLab Slack application](../user/project/integrations/gitlab_slack_application.md) for
-your GitLab.com projects, you need to [add the `gitlab` keyword at the beginning of the command](../user/project/integrations/gitlab_slack_application.md#usage).
+If you are using the [GitLab Slack application](../user/project/integrations/gitlab_slack_application.md) for
+your GitLab.com projects, [add the `gitlab` keyword at the beginning of the command](../user/project/integrations/gitlab_slack_application.md#usage).
## Issue commands
-It is possible to create new issue, display issue details and search up to 5 issues.
+It's possible to create new issue, display issue details and search up to 5 issues.
## Deploy command
-In order to deploy to an environment, GitLab tries to find a deployment
+To deploy to an environment, GitLab tries to find a deployment
manual action in the pipeline.
-If there is only one action for a given environment, it is triggered.
-If there is more than one action defined, GitLab tries to find an action
+If there's only one action for a given environment, it is triggered.
+If more than one action is defined, GitLab tries to find an action
which name equals the environment name we want to deploy to.
The command returns an error when no matching action has been found.
diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md
index 8e1a6cdcfd1..d068aabed41 100644
--- a/doc/integration/sourcegraph.md
+++ b/doc/integration/sourcegraph.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, how-to
---
-# Sourcegraph integration
+# Sourcegraph integration **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16556) in GitLab 12.5.
> - Note that this integration is in BETA and deployed [behind a feature flag](#enable-the-sourcegraph-feature-flag) disabled by default. Self-managed instances can opt to enable it.
@@ -23,9 +23,9 @@ NOTE:
This feature requires user opt-in. After Sourcegraph has been enabled for your GitLab instance,
you can choose to enable Sourcegraph [through your user preferences](#enable-sourcegraph-in-user-preferences).
-## Set up for self-managed GitLab instances **(CORE ONLY)**
+## Set up for self-managed GitLab instances **(FREE SELF)**
-Before you can enable Sourcegraph code intelligence in GitLab you will need to:
+Before you can enable Sourcegraph code intelligence in GitLab you must:
- Enable the `sourcegraph` feature flag for your GitLab instance.
- Configure a Sourcegraph instance with your GitLab instance as an external service.
@@ -33,7 +33,7 @@ Before you can enable Sourcegraph code intelligence in GitLab you will need to:
### Enable the Sourcegraph feature flag
NOTE:
-If you are running a self-managed instance, the Sourcegraph integration will not be available
+If you are running a self-managed instance, the Sourcegraph integration is unavailable
unless the feature flag `sourcegraph` is enabled. This can be done from the Rails console
by instance administrators.
@@ -64,7 +64,7 @@ Feature.enable(:sourcegraph, Project.find_by_full_path('my_group/my_project'))
If you are new to Sourcegraph, head over to the [Sourcegraph installation documentation](https://docs.sourcegraph.com/admin) and get your instance up and running.
-If you are using an HTTPS connection to GitLab, you will need to [configure HTTPS](https://docs.sourcegraph.com/admin/http_https_configuration) for your Sourcegraph instance.
+If you are using an HTTPS connection to GitLab, you must [configure HTTPS](https://docs.sourcegraph.com/admin/http_https_configuration) for your Sourcegraph instance.
### Connect your Sourcegraph instance to your GitLab instance
@@ -79,23 +79,26 @@ You can skip this step if you already have your GitLab repositories searchable i
1. In GitLab, go to **Admin Area > Settings > General**.
1. Expand the **Sourcegraph** configuration section.
1. Check **Enable Sourcegraph**.
-1. Set the Sourcegraph URL to your Sourcegraph instance, e.g., `https://sourcegraph.example.com`.
+1. Set the Sourcegraph URL to your Sourcegraph instance, such as `https://sourcegraph.example.com`.
-![Sourcegraph admin settings](img/sourcegraph_admin_v12_5.png)
+![Sourcegraph administration settings](img/sourcegraph_admin_v12_5.png)
## Enable Sourcegraph in user preferences
If a GitLab administrator has enabled Sourcegraph, you can enable this feature in your user preferences.
-1. In GitLab, click your avatar in the top-right corner, then click **Settings**. On the left-hand nav, click **Preferences**.
-1. Under **Integrations**, find the **Sourcegraph** section.
-1. Check **Enable Sourcegraph**.
+In GitLab:
+
+1. In the top-right corner, select your avatar.
+1. Select **Preferences**.
+1. In the **Integrations** section, select the checkbox under **Sourcegraph**.
+1. Select **Save changes**.
![Sourcegraph user preferences](img/sourcegraph_user_preferences_v12_5.png)
## Using Sourcegraph code intelligence
-Once enabled, participating projects will have a code intelligence popover available in
+Once enabled, participating projects display a code intelligence popover available in
the following code views:
- Merge request diffs
@@ -114,7 +117,7 @@ When visiting one of these views, you can now hover over a code reference to see
Sourcegraph powered code intelligence is available for all public projects on GitLab.com.
-Support for private projects is currently not available for GitLab.com;
+Support for private projects is not yet available for GitLab.com;
follow the epic [&2201](https://gitlab.com/groups/gitlab-org/-/epics/2201)
for updates.
@@ -122,7 +125,7 @@ for updates.
### Sourcegraph isn't working
-If you enabled Sourcegraph for your project but still it doesn't look like it's working, it might be because Sourcegraph has not indexed the project yet. You can check for Sourcegraph's availability of your project by visiting `https://sourcegraph.com/gitlab.com/<project-path>`replacing `<project-path>` with the path to your GitLab project.
+If you enabled Sourcegraph for your project but it isn't working, Sourcegraph may not have indexed the project yet. You can check for Sourcegraph's availability of your project by visiting `https://sourcegraph.com/gitlab.com/<project-path>`replacing `<project-path>` with the path to your GitLab project.
## Sourcegraph and Privacy
@@ -130,5 +133,5 @@ From Sourcegraph's [extension documentation](https://docs.sourcegraph.com/integr
engine behind the native GitLab integration:
> Sourcegraph integrations never send any logs, pings, usage statistics, or telemetry to Sourcegraph.com.
-> They will only connect to Sourcegraph.com as required to provide code intelligence or other functionality on public code.
+> They connect only to Sourcegraph.com as required to provide code intelligence or other functionality on public code.
> As a result, no private code, private repository names, usernames, or any other specific data is sent to Sourcegraph.com.
diff --git a/doc/integration/trello_power_up.md b/doc/integration/trello_power_up.md
index d30308cea7a..1a1b6cd101f 100644
--- a/doc/integration/trello_power_up.md
+++ b/doc/integration/trello_power_up.md
@@ -38,8 +38,11 @@ If your instance's URL is `https://example.com`, your API URL is `https://exampl
Your GitLab personal access token enables your GitLab account to be accessed
from Trello.
-> Find it in GitLab by clicking on your avatar (upright corner), from which you access
-your user **Settings** > **Access Tokens**.
+To find it in GitLab:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In 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).
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index 3c49cd47509..362ae36389b 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -18,12 +18,15 @@ The following assumes you already have Vault installed and running.
1. **Get the OpenID Connect client ID and secret from GitLab:**
- First you must create a GitLab application to obtain an application ID and secret for authenticating into Vault. To do this, sign in to GitLab and follow these steps:
-
- 1. On GitLab, click your avatar on the top-right corner, and select your user **Settings > Applications**.
- 1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris),
- making sure to select the **OpenID** scope.
- 1. Save application.
+ First you must create a GitLab application to obtain an application ID and secret for authenticating into Vault.
+ To do this, sign in to GitLab and follow these steps:
+
+ 1. In the top-right corner, select your avatar.
+ 1. Select **Edit profile**.
+ 1. In the left sidebar, select **Applications**.
+ 1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris).
+ 1. Select the **OpenID** scope.
+ 1. Select **Save application**.
1. Copy client ID and secret, or keep the page open for reference.
![GitLab OAuth provider](img/gitlab_oauth_vault_v12_6.png)
@@ -44,7 +47,7 @@ The following assumes you already have Vault installed and running.
Success! Enabled oidc auth method at: oidc/
```
-1. **Write the OIDC config:**
+1. **Write the OIDC configuration:**
Next, Vault needs to be given the application ID and secret generated by GitLab.
@@ -67,7 +70,7 @@ The following assumes you already have Vault installed and running.
Success! Data written to: auth/oidc/config
```
-1. **Write the OIDC Role Config:**
+1. **Write the OIDC Role Configuration:**
Now that Vault has a GitLab application ID and secret, it needs to know the [**Redirect URIs**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris) and scopes given to GitLab during the application creation process. The redirect URIs need to match where your Vault instance is running. The `oidc_scopes` field needs to include the `openid`. Similarly to the previous step, replace `your_application_id` with the generated application ID from GitLab:
@@ -108,7 +111,7 @@ The following assumes you already have Vault installed and running.
Here's a short explanation of what this command does:
- 1. In the **Write the OIDC Role Config** (step 4), we created a role called
+ 1. In the **Write the OIDC Role Configuration** (step 4), we created a role called
`demo`. We set `role=demo` so Vault knows which configuration we'd like to
sign in with.
1. To set Vault to use the `OIDC` sign-in method, we set `-method=oidc`.
diff --git a/doc/intro/README.md b/doc/intro/README.md
index 5df4efe5307..c815842480c 100644
--- a/doc/intro/README.md
+++ b/doc/intro/README.md
@@ -1,49 +1,8 @@
---
-stage: Create
-group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
-comments: false
+redirect_to: 'index.md'
---
-# Get started with GitLab
+This document was moved to [another location](index.md).
-## Organize
-
-Create projects and groups.
-
-- [Create a new project](../gitlab-basics/create-project.md)
-- [Create a new group](../user/group/index.md#create-a-new-group)
-
-## Prioritize
-
-Create issues, labels, milestones, cast your vote, and review issues.
-
-- [Create an issue](../user/project/issues/managing_issues.md#create-a-new-issue)
-- [Assign labels to issues](../user/project/labels.md)
-- [Use milestones as an overview of your project's tracker](../user/project/milestones/index.md)
-- [Use voting to express your like/dislike to issues and merge requests](../user/award_emojis.md)
-
-## Collaborate
-
-Create merge requests and review code.
-
-- [Fork a project and contribute to it](../user/project/repository/forking_workflow.md)
-- [Create a new merge request](../user/project/merge_requests/creating_merge_requests.md)
-- [Automatically close issues from merge requests](../user/project/issues/managing_issues.md#closing-issues-automatically)
-- [Automatically merge when pipeline succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md)
-- [Revert any commit](../user/project/merge_requests/revert_changes.md)
-- [Cherry-pick any commit](../user/project/merge_requests/cherry_pick_changes.md)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [Get started with GitLab CI/CD](../ci/quick_start/README.md)
-
-## Install and Update
-
-Install and update your GitLab installation.
-
-- [Install GitLab](https://about.gitlab.com/install/)
-- [Update GitLab](https://about.gitlab.com/update/)
-- [Explore Omnibus GitLab configuration options](https://docs.gitlab.com/omnibus/settings/configuration.html)
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/intro/index.md b/doc/intro/index.md
new file mode 100644
index 00000000000..1ab7553d3a8
--- /dev/null
+++ b/doc/intro/index.md
@@ -0,0 +1,49 @@
+---
+stage: Create
+group: Source Code
+info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
+comments: false
+---
+
+# Get started with GitLab **(FREE)**
+
+## Organize
+
+Create projects and groups.
+
+- [Create a new project](../user/project/working_with_projects.md#create-a-project)
+- [Create a new group](../user/group/index.md#create-a-new-group)
+
+## Prioritize
+
+Create issues, labels, milestones, cast your vote, and review issues.
+
+- [Create an issue](../user/project/issues/managing_issues.md#create-a-new-issue)
+- [Assign labels to issues](../user/project/labels.md)
+- [Use milestones as an overview of your project's tracker](../user/project/milestones/index.md)
+- [Use voting to express your like/dislike to issues and merge requests](../user/award_emojis.md)
+
+## Collaborate
+
+Create merge requests and review code.
+
+- [Fork a project and contribute to it](../user/project/repository/forking_workflow.md)
+- [Create a new merge request](../user/project/merge_requests/creating_merge_requests.md)
+- [Automatically close issues from merge requests](../user/project/issues/managing_issues.md#closing-issues-automatically)
+- [Automatically merge when pipeline succeeds](../user/project/merge_requests/merge_when_pipeline_succeeds.md)
+- [Revert any commit](../user/project/merge_requests/revert_changes.md)
+- [Cherry-pick any commit](../user/project/merge_requests/cherry_pick_changes.md)
+
+## Test and Deploy
+
+Use the built-in continuous integration in GitLab.
+
+- [Get started with GitLab CI/CD](../ci/quick_start/index.md)
+
+## Install and Update
+
+Install and update your GitLab installation.
+
+- [Install GitLab](https://about.gitlab.com/install/)
+- [Update GitLab](https://about.gitlab.com/update/)
+- [Explore Omnibus GitLab configuration options](https://docs.gitlab.com/omnibus/settings/configuration.html)
diff --git a/doc/legal/README.md b/doc/legal/README.md
index 371ea53046c..c815842480c 100644
--- a/doc/legal/README.md
+++ b/doc/legal/README.md
@@ -1,10 +1,8 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-comments: false
+redirect_to: 'index.md'
---
-# Legal
+This document was moved to [another location](index.md).
-Please read through the [GitLab License Agreement](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md).
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/legal/index.md b/doc/legal/index.md
new file mode 100644
index 00000000000..371ea53046c
--- /dev/null
+++ b/doc/legal/index.md
@@ -0,0 +1,10 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+comments: false
+---
+
+# Legal
+
+Please read through the [GitLab License Agreement](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md).
diff --git a/doc/license/README.md b/doc/license/README.md
deleted file mode 100644
index f0ff27c315e..00000000000
--- a/doc/license/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/license.md'
----
-
-This document was moved to [another location](../user/admin_area/license.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md
deleted file mode 100644
index e68f9c217d5..00000000000
--- a/doc/markdown/markdown.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/markdown.md'
----
-
-This document was moved to [another location](../user/markdown.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/monitoring/health_check.md b/doc/monitoring/health_check.md
deleted file mode 100644
index d607ea03d5a..00000000000
--- a/doc/monitoring/health_check.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../user/admin_area/monitoring/health_check.md'
----
-
-This document was moved to [user/admin_area/monitoring/health_check](../user/admin_area/monitoring/health_check.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/monitoring/performance/gitlab_configuration.md b/doc/monitoring/performance/gitlab_configuration.md
deleted file mode 100644
index 6a6f297f674..00000000000
--- a/doc/monitoring/performance/gitlab_configuration.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../administration/monitoring/performance/gitlab_configuration.md'
----
-
-This document was moved to [administration/monitoring/performance/gitlab_configuration](../../administration/monitoring/performance/gitlab_configuration.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/monitoring/performance/grafana_configuration.md b/doc/monitoring/performance/grafana_configuration.md
deleted file mode 100644
index 98dfe51ae04..00000000000
--- a/doc/monitoring/performance/grafana_configuration.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../administration/monitoring/performance/grafana_configuration.md'
----
-
-This document was moved to [administration/monitoring/performance/grafana_configuration](../../administration/monitoring/performance/grafana_configuration.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/monitoring/performance/influxdb_configuration.md b/doc/monitoring/performance/influxdb_configuration.md
deleted file mode 100644
index 0bcb18bdfe7..00000000000
--- a/doc/monitoring/performance/influxdb_configuration.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: '../../administration/monitoring/performance/prometheus.md'
----
-
-Support for InfluxDB was removed in GitLab 13.0. Use [Prometheus](../../administration/monitoring/performance/prometheus.md) for performance monitoring.
diff --git a/doc/monitoring/performance/influxdb_schema.md b/doc/monitoring/performance/influxdb_schema.md
deleted file mode 100644
index 0bcb18bdfe7..00000000000
--- a/doc/monitoring/performance/influxdb_schema.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: '../../administration/monitoring/performance/prometheus.md'
----
-
-Support for InfluxDB was removed in GitLab 13.0. Use [Prometheus](../../administration/monitoring/performance/prometheus.md) for performance monitoring.
diff --git a/doc/monitoring/performance/introduction.md b/doc/monitoring/performance/introduction.md
deleted file mode 100644
index 71ecd24c743..00000000000
--- a/doc/monitoring/performance/introduction.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../administration/monitoring/performance/index.md'
----
-
-This document was moved to [administration/monitoring/performance/introduction](../../administration/monitoring/performance/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/cleaning_up_redis_sessions.md b/doc/operations/cleaning_up_redis_sessions.md
deleted file mode 100644
index 96f72099f8f..00000000000
--- a/doc/operations/cleaning_up_redis_sessions.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/operations/cleaning_up_redis_sessions.md'
----
-
-This document was moved to [another location](../administration/operations/cleaning_up_redis_sessions.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 6fa67c375c9..8bf0e56c989 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Error Tracking
+# Error Tracking **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/169) in GitLab 11.8.
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 9ce7eb0ede2..f23880554a6 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -4,11 +4,10 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Feature Flags **(CORE)**
+# Feature Flags **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) in GitLab 11.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
With Feature Flags, you can deploy your application's new features to production in smaller batches.
You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery.
@@ -61,14 +60,13 @@ next to any feature flag in the list.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254379) in GitLab 13.5.
The maximum number of feature flags per project on self-managed GitLab instances
-is 200. On GitLab.com, the maximum number is determined by [GitLab.com tier](https://about.gitlab.com/pricing/):
+is 200. For GitLab SaaS, the maximum number is determined by [tier](https://about.gitlab.com/pricing/):
| Tier | Number of feature flags per project |
|----------|-------------------------------------|
| Free | 50 |
-| Bronze | 100 |
-| Silver | 150 |
-| Gold | 200 |
+| Premium | 150 |
+| Ultimate | 200 |
## Feature flag strategies
@@ -238,6 +236,18 @@ It can be set to:
of specific users IDs to enable the feature for.
- [User IDs](#user-ids)
+## Legacy feature flag migration
+
+Legacy feature flags became read-only in GitLab 13.4. GitLab 14.0 removes support for legacy feature
+flags. You must migrate your legacy feature flags to the new version. To do so, follow these steps:
+
+1. Take a screenshot of the legacy flag for tracking.
+1. Delete the flag through the API or UI (you don't need to alter the code).
+1. Create a new feature flag with the same name as the legacy flag you deleted. Make sure the
+ strategies and environments match the deleted flag.
+
+See [this video tutorial](https://www.youtube.com/watch?v=CAJY2IGep7Y) for help with this migration.
+
## Disable a feature flag for a specific environment
In [GitLab 13.0 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/8621),
diff --git a/doc/operations/incident_management/alert_details.md b/doc/operations/incident_management/alert_details.md
deleted file mode 100644
index cd73e9e7e1f..00000000000
--- a/doc/operations/incident_management/alert_details.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: alerts.md
----
-
-This document was moved to [another location](alerts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/incident_management/alert_integrations.md b/doc/operations/incident_management/alert_integrations.md
index 0f695e7a6c9..bec0653d464 100644
--- a/doc/operations/incident_management/alert_integrations.md
+++ b/doc/operations/incident_management/alert_integrations.md
@@ -1,199 +1,8 @@
---
-stage: Monitor
-group: Health
-info: To 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: 'integrations.md'
---
-# Alert integrations
+This document was moved to [another location](integrations.md).
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.8.
-
-GitLab can accept alerts from any source via a webhook receiver. This can be configured
-generically or, in GitLab versions 13.1 and greater, you can configure
-[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
-to use this endpoint.
-
-## Integrations list
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in [GitLab Core](https://about.gitlab.com/pricing/) 13.5.
-
-With Maintainer or higher [permissions](../../user/permissions.md), you can view
-the list of configured alerts integrations by navigating to
-**Settings > Operations** in your project's sidebar menu, and expanding **Alerts** section.
-The list displays the integration name, type, and status (enabled or disabled):
-
-![Current Integrations](img/integrations_list_v13_5.png)
-
-## Configuration
-
-GitLab can receive alerts via a HTTP endpoint that you configure,
-or the [Prometheus integration](#external-prometheus-integration).
-
-### Single HTTP Endpoint **CORE**
-
-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 maintainer [permissions](../../user/permissions.md)
- for a project.
-1. Navigate to **Settings > Operations** in your project.
-1. Expand the **Alerts** section, and in the **Integration** dropdown menu, select **Generic**.
-1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
- for the webhook configuration.
-
-### HTTP Endpoints **PREMIUM**
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4442) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
-
-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 maintainer [permissions](../../user/permissions.md)
- for a project.
-1. Navigate to **Settings > Operations** in your project.
-1. Expand the **Alerts** section.
-1. For each endpoint you want to create:
-
- 1. In the **Integration** dropdown menu, select **HTTP Endpoint**.
- 1. Name the integration.
- 1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
- for the webhook configuration. You must also input the URL and Authorization Key
- in your external service.
- 1. _(Optional)_ To generate a test alert to test the new integration, enter a
- sample payload, then click **Save and test alert payload**. Valid JSON is required.
- 1. Click **Save Integration**.
-
-The new HTTP Endpoint displays in the [integrations list](#integrations-list).
-You can edit the integration by selecting the **{pencil}** pencil icon on the right
-side of the integrations list.
-
-### External Prometheus integration
-
-For GitLab versions 13.1 and greater, please read
-[External Prometheus Instances](../metrics/alerts.md#external-prometheus-instances)
-to configure alerts for this integration.
-
-## Customize the alert payload outside of GitLab
-
-For all integration types, you can customize the payload by sending the following
-parameters. All fields are optional. If the incoming alert does not contain a value for the `Title` field, a default value of `New: Incident` will be applied.
-
-| Property | Type | Description |
-| ------------------------- | --------------- | ----------- |
-| `title` | String | The title of the incident. |
-| `description` | String | A high-level summary of the problem. |
-| `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue is used. |
-| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. |
-| `service` | String | The affected service. |
-| `monitoring_tool` | String | The name of the associated monitoring tool. |
-| `hosts` | String or Array | One or more hosts, as to where this incident occurred. |
-| `severity` | String | The severity of the alert. Must be one of `critical`, `high`, `medium`, `low`, `info`, `unknown`. Default is `critical`. |
-| `fingerprint` | String or Array | The unique identifier of the alert. This can be used to group occurrences of the same alert. |
-| `gitlab_environment_name` | String | The name of the associated GitLab [environment](../../ci/environments/index.md). This can be used to associate your alert to your environment. |
-
-You can also add custom fields to the alert's payload. The values of extra
-parameters aren't limited to primitive types (such as strings or numbers), but
-can be a nested JSON object. For example:
-
-```json
-{ "foo": { "bar": { "baz": 42 } } }
-```
-
-NOTE:
-Ensure your requests are smaller than the
-[payload application limits](../../administration/instance_limits.md#generic-alert-json-payloads).
-
-Example request:
-
-```shell
-curl --request POST \
- --data '{"title": "Incident title"}' \
- --header "Authorization: Bearer <authorization_key>" \
- --header "Content-Type: application/json" \
- <url>
-```
-
-The `<authorization_key>` and `<url>` values can be found when configuring an alert integration.
-
-Example payload:
-
-```json
-{
- "title": "Incident title",
- "description": "Short description of the incident",
- "start_time": "2019-09-12T06:00:55Z",
- "service": "service affected",
- "monitoring_tool": "value",
- "hosts": "value",
- "severity": "high",
- "fingerprint": "d19381d4e8ebca87b55cda6e8eee7385",
- "foo": {
- "bar": {
- "baz": 42
- }
- }
-}
-```
-
-## Triggering test alerts
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Core in 13.2.
-
-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 Developer or greater [permissions](../../user/permissions.md).
-1. Navigate to **Settings > Operations** in your project.
-1. Click **Alerts endpoint** to expand the section.
-1. Enter a sample payload in **Alert test payload** (valid JSON is required).
-1. Click **Test alert payload**.
-
-GitLab displays an error or success message, depending on the outcome of your test.
-
-## Automatic grouping of identical alerts **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214557) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-
-In GitLab versions 13.2 and greater, GitLab groups alerts based on their
-payload. When an incoming alert contains the same payload as another alert
-(excluding the `start_time` and `hosts` attributes), GitLab groups these alerts
-together and displays a counter on the [Alert Management List](incidents.md)
-and details pages.
-
-If the existing alert is already `resolved`, GitLab creates a new alert instead.
-
-![Alert Management List](img/alert_list_v13_1.png)
-
-## Link to your Opsgenie Alerts
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-
-WARNING:
-We are building deeper integration with Opsgenie and other alerting tools through
-[HTTP endpoint integrations](#single-http-endpoint) so you can see alerts in
-the GitLab interface. As a result, the previous direct link to Opsgenie Alerts from
-the GitLab alerts list is deprecated in
-GitLab versions [13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/273657).
-
-You can monitor alerts using a GitLab integration with [Opsgenie](https://www.atlassian.com/software/opsgenie).
-
-If you enable the Opsgenie integration, you can't have other GitLab alert
-services
-active at the same time.
-
-To enable Opsgenie integration:
-
-1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md).
-1. Navigate to **Operations > Alerts**.
-1. In the **Integrations** select box, select **Opsgenie**.
-1. Select the **Active** toggle.
-1. In the **API URL** field, enter the base URL for your Opsgenie integration,
- such as `https://app.opsgenie.com/alert/list`.
-1. Select **Save changes**.
-
-After you enable the integration, navigate to the Alerts list page at
-**Operations > Alerts**, and then select **View alerts in Opsgenie**.
+<!-- This redirect file can be deleted after <2021-05-03>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/incident_management/alert_notifications.md b/doc/operations/incident_management/alert_notifications.md
index eaf606105d6..4f46c2bec71 100644
--- a/doc/operations/incident_management/alert_notifications.md
+++ b/doc/operations/incident_management/alert_notifications.md
@@ -1,36 +1,8 @@
---
-stage: Monitor
-group: Health
-info: To 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: 'paging.md'
---
-# Paging and notifications
+This document was moved to [another location](paging.md).
-When there is a new alert or incident, it is important for a responder to be notified
-immediately so they can triage and respond to the problem. Responders can receive
-notifications using the methods described on this page.
-
-## Slack notifications
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216326) in GitLab 13.1.
-
-Responders can be paged via Slack using the
-[Slack Notifications Service](../../user/project/integrations/slack.md), which you
-can configure for new alerts and new incidents. After configuring, responders
-receive a **single** page via Slack. To set up Slack notifications on your mobile
-device, make sure to enable notifications for the Slack app on your phone so
-you never miss a page.
-
-## Email notifications
-
-Email notifications are available in projects that have been
-[configured to create incidents automatically](incidents.md#create-incidents-automatically)
-for triggered alerts. Project members with the **Owner** or **Maintainer** roles are
-sent an email notification automatically. (This is not configurable.) To optionally
-send additional email notifications to project members with the **Developer** role:
-
-1. Navigate to **Settings > Operations**.
-1. Expand the **Incidents** section.
-1. In the **Alert Integration** tab, select the **Send a separate email notification to Developers**
- check box.
-1. Select **Save changes**.
+<!-- This redirect file can be deleted after 2021-04-21 -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index a8852a02f2b..3c60c737309 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Alerts
+# Alerts **(FREE)**
Alerts are a critical entity in your incident management workflow. They represent a notable event that might indicate a service outage or disruption. GitLab provides a list view for triage and detail view for deeper investigation of what happened.
@@ -102,8 +102,9 @@ To view the metrics for an alert:
#### View an alert's logs
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) in GitLab Ultimate 12.8. and [improved](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) in GitLab Ultimate 12.8.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to GitLab Free 12.9.
Viewing logs from a metrics panel can be useful if you're triaging an
application incident and need to [explore logs](../metrics/dashboards/index.md#chart-context-menu)
@@ -196,9 +197,9 @@ add a to-do item:
1. To display the list of current alerts, navigate to **Operations > Alerts**.
1. Select your desired alert to display its **Alert Management Details View**.
-1. Select the **Add a To-Do** button in the right sidebar:
+1. Select the **Add a to do** button in the right sidebar:
- ![Alert Details Add a To-Do](img/alert_detail_add_todo_v13_1.png)
+ ![Alert Details Add a to do](img/alert_detail_add_todo_v13_9.png)
Select the **To-Do List** **{todo-done}** in the navigation bar to view your current to-do list.
diff --git a/doc/operations/incident_management/generic_alerts.md b/doc/operations/incident_management/generic_alerts.md
deleted file mode 100644
index 44b1f4b088a..00000000000
--- a/doc/operations/incident_management/generic_alerts.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: alert_integrations.md
----
-
-This document was moved to [another location](alert_integrations.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/incident_management/img/alert_detail_add_todo_v13_1.png b/doc/operations/incident_management/img/alert_detail_add_todo_v13_1.png
deleted file mode 100644
index 39aa9e33728..00000000000
--- a/doc/operations/incident_management/img/alert_detail_add_todo_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/alert_detail_add_todo_v13_9.png b/doc/operations/incident_management/img/alert_detail_add_todo_v13_9.png
new file mode 100644
index 00000000000..5beb1cd0bfb
--- /dev/null
+++ b/doc/operations/incident_management/img/alert_detail_add_todo_v13_9.png
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 3f6522b3f90..f0bb9a8e950 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Incidents
+# Incidents **(FREE)**
Incidents are critical entities in incident management workflows. They represent
a service disruption or outage that needs to be restored urgently. GitLab provides
@@ -24,7 +24,7 @@ Incident, you have two options to do this manually.
**From the Incidents List:**
-> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab core in 13.3.
+> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab Free in 13.3.
- Navigate to **Operations > Incidents** and click **Create Incident**.
- Create a new issue using the `incident` template available when creating it.
@@ -36,9 +36,11 @@ Incident, you have two options to do this manually.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230857) in GitLab 13.4.
-- Navigate to **Issues > List** and click **Create Issue**.
-- Create a new issue using the `type` drop-down and select `Incident`.
-- The page refreshes and the page only displays fields relevant to Incidents.
+1. Go to **Issues > List**, and select **New issue**.
+1. In the **Type** dropdown, select **Incident**. Only fields relevant to
+ incidents are displayed on the page.
+1. Create the incident as needed, and select **Submit issue** to save the
+ incident.
![Incident List Create](img/new_incident_create_v13_4.png)
@@ -53,7 +55,7 @@ With Maintainer or higher [permissions](../../user/permissions.md), you can enab
1. Check the **Create an incident** checkbox.
1. To customize the incident, select an
[issue template](../../user/project/description_templates.md#creating-issue-templates).
-1. To send [an email notification](alert_notifications.md#email-notifications) to users
+1. To send [an email notification](paging.md#email-notifications) to users
with [Developer permissions](../../user/permissions.md), select
**Send a separate email notification to Developers**. Email notifications are
also sent to users with **Maintainer** and **Owner** permissions.
@@ -115,7 +117,7 @@ in your project's sidebar. The list contains the following metrics:
to a [Status Page](status_page.md). **(ULTIMATE)**
The Incident list displays incidents sorted by incident created date.
-([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229534) to GitLab core in 13.3.)
+([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229534) to GitLab Free in 13.3.)
To see if a column is sortable, point your mouse at the header. Sortable columns
display an arrow next to the column name.
@@ -185,7 +187,7 @@ field populated.
![Incident alert details](img/incident_alert_details_v13_4.png)
-### Timeline view
+### Timeline view **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227836) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
@@ -195,7 +197,7 @@ un-threaded and ordered chronologically, newest to oldest:
![Timeline view toggle](img/timeline_view_toggle_v13_5.png)
-### Service Level Agreement countdown timer
+### Service Level Agreement countdown timer **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241663) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5.
@@ -225,6 +227,10 @@ There are different actions available to help triage and respond to incidents.
Assign incidents to users that are actively responding. Select **Edit** in the
right-hand side bar to select or deselect assignees.
+### Associate a milestone
+
+Associate an incident to a milestone by selecting **Edit** next to the milestone feature in the right-hand side bar.
+
### Change severity
See [Incident List](#incident-list) for a full description of the severity levels available.
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index b0274537941..6e285300b12 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Incident management
+# Incident management **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2877) in GitLab 13.0.
@@ -12,7 +12,7 @@ Incident Management enables developers to easily triage and view the alerts and
generated by their application. By surfacing alerts and incidents where the code is
being developed, efficiency and awareness can be increased. Check out the following sections for more information:
-- [Integrate your monitoring tools](alert_integrations.md).
-- Receive [notifications](alert_notifications.md) for triggered alerts.
+- [Integrate your monitoring tools](integrations.md).
+- Receive [notifications](paging.md) for triggered alerts.
- Triage [Alerts](alerts.md) and [Incidents](incidents.md).
- Inform stakeholders with [Status Page](status_page.md).
diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index 8c2159c130b..b3e7d9c544d 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -4,9 +4,19 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Integrations
+# Alert integrations **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in [GitLab Core](https://about.gitlab.com/pricing/) 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in GitLab Ultimate 12.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to GitLab Free in 12.8.
+
+GitLab can accept alerts from any source via a webhook receiver. This can be configured
+generically or, in GitLab versions 13.1 and greater, you can configure
+[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
+to use this endpoint.
+
+## Integrations list
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/245331) in GitLab Free 13.5.
With Maintainer or higher [permissions](../../user/permissions.md), you can view
the list of configured alerts integrations by navigating to
@@ -14,3 +24,176 @@ the list of configured alerts integrations by navigating to
The list displays the integration name, type, and status (enabled or disabled):
![Current Integrations](img/integrations_list_v13_5.png)
+
+## Configuration
+
+GitLab can receive alerts via a HTTP endpoint that you configure,
+or the [Prometheus integration](#external-prometheus-integration).
+
+### Single HTTP Endpoint **(FREE)**
+
+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 maintainer [permissions](../../user/permissions.md)
+ for a project.
+1. Navigate to **Settings > Operations** in your project.
+1. Expand the **Alerts** section, and in the **Integration** dropdown menu, select **Generic**.
+1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
+ for the webhook configuration.
+
+### HTTP Endpoints **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4442) in GitLab Premium 13.6.
+
+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 maintainer [permissions](../../user/permissions.md)
+ for a project.
+1. Navigate to **Settings > Operations** in your project.
+1. Expand the **Alerts** section.
+1. For each endpoint you want to create:
+
+ 1. In the **Integration** dropdown menu, select **HTTP Endpoint**.
+ 1. Name the integration.
+ 1. Toggle the **Active** alert setting to display the **URL** and **Authorization Key**
+ for the webhook configuration. You must also input the URL and Authorization Key
+ in your external service.
+ 1. _(Optional)_ To generate a test alert to test the new integration, enter a
+ sample payload, then click **Save and test alert payload**. Valid JSON is required.
+ 1. Click **Save Integration**.
+
+The new HTTP Endpoint displays in the [integrations list](#integrations-list).
+You can edit the integration by selecting the **{pencil}** pencil icon on the right
+side of the integrations list.
+
+### External Prometheus integration
+
+For GitLab versions 13.1 and greater, read
+[External Prometheus Instances](../metrics/alerts.md#external-prometheus-instances)
+to configure alerts for this integration.
+
+## Customize the alert payload outside of GitLab
+
+For all integration types, you can customize the payload by sending the following
+parameters. All fields are optional. If the incoming alert does not contain a value for the `Title` field, a default value of `New: Incident` will be applied.
+
+| Property | Type | Description |
+| ------------------------- | --------------- | ----------- |
+| `title` | String | The title of the incident. |
+| `description` | String | A high-level summary of the problem. |
+| `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue is used. |
+| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. |
+| `service` | String | The affected service. |
+| `monitoring_tool` | String | The name of the associated monitoring tool. |
+| `hosts` | String or Array | One or more hosts, as to where this incident occurred. |
+| `severity` | String | The severity of the alert. Case-insensitive. Can be one of: `critical`, `high`, `medium`, `low`, `info`, `unknown`. Defaults to `critical` if missing or value is not in this list. |
+| `fingerprint` | String or Array | The unique identifier of the alert. This can be used to group occurrences of the same alert. |
+| `gitlab_environment_name` | String | The name of the associated GitLab [environment](../../ci/environments/index.md). Required to [display alerts on a dashboard](../../user/operations_dashboard/index.md#adding-a-project-to-the-dashboard). |
+
+You can also add custom fields to the alert's payload. The values of extra
+parameters aren't limited to primitive types (such as strings or numbers), but
+can be a nested JSON object. For example:
+
+```json
+{ "foo": { "bar": { "baz": 42 } } }
+```
+
+NOTE:
+Ensure your requests are smaller than the
+[payload application limits](../../administration/instance_limits.md#generic-alert-json-payloads).
+
+Example request:
+
+```shell
+curl --request POST \
+ --data '{"title": "Incident title"}' \
+ --header "Authorization: Bearer <authorization_key>" \
+ --header "Content-Type: application/json" \
+ <url>
+```
+
+The `<authorization_key>` and `<url>` values can be found when configuring an alert integration.
+
+Example payload:
+
+```json
+{
+ "title": "Incident title",
+ "description": "Short description of the incident",
+ "start_time": "2019-09-12T06:00:55Z",
+ "service": "service affected",
+ "monitoring_tool": "value",
+ "hosts": "value",
+ "severity": "high",
+ "fingerprint": "d19381d4e8ebca87b55cda6e8eee7385",
+ "foo": {
+ "bar": {
+ "baz": 42
+ }
+ }
+}
+```
+
+## Triggering test alerts
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Free in 13.2.
+
+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 Developer or greater [permissions](../../user/permissions.md).
+1. Navigate to **Settings > Operations** in your project.
+1. Click **Alerts endpoint** to expand the section.
+1. Enter a sample payload in **Alert test payload** (valid JSON is required).
+1. Click **Test alert payload**.
+
+GitLab displays an error or success message, depending on the outcome of your test.
+
+## Automatic grouping of identical alerts **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214557) in GitLab Premium 13.2.
+
+In GitLab versions 13.2 and greater, GitLab groups alerts based on their
+payload. When an incoming alert contains the same payload as another alert
+(excluding the `start_time` and `hosts` attributes), GitLab groups these alerts
+together and displays a counter on the [Alert Management List](incidents.md)
+and details pages.
+
+If the existing alert is already `resolved`, GitLab creates a new alert instead.
+
+![Alert Management List](img/alert_list_v13_1.png)
+
+## Link to your Opsgenie Alerts
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Premium 13.2.
+
+WARNING:
+We are building deeper integration with Opsgenie and other alerting tools through
+[HTTP endpoint integrations](#single-http-endpoint) so you can see alerts in
+the GitLab interface. As a result, the previous direct link to Opsgenie Alerts from
+the GitLab alerts list is deprecated in
+GitLab versions [13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/273657).
+
+You can monitor alerts using a GitLab integration with [Opsgenie](https://www.atlassian.com/software/opsgenie).
+
+If you enable the Opsgenie integration, you can't have other GitLab alert
+services
+active at the same time.
+
+To enable Opsgenie integration:
+
+1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md).
+1. Navigate to **Operations > Alerts**.
+1. In the **Integrations** select box, select **Opsgenie**.
+1. Select the **Active** toggle.
+1. In the **API URL** field, enter the base URL for your Opsgenie integration,
+ such as `https://app.opsgenie.com/alert/list`.
+1. Select **Save changes**.
+
+After you enable the integration, navigate to the Alerts list page at
+**Operations > Alerts**, and then select **View alerts in Opsgenie**.
diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md
new file mode 100644
index 00000000000..dd04cd63a54
--- /dev/null
+++ b/doc/operations/incident_management/paging.md
@@ -0,0 +1,36 @@
+---
+stage: Monitor
+group: Health
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Paging and notifications **(FREE)**
+
+When there is a new alert or incident, it is important for a responder to be notified
+immediately so they can triage and respond to the problem. Responders can receive
+notifications using the methods described on this page.
+
+## Slack notifications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216326) in GitLab 13.1.
+
+Responders can be paged via Slack using the
+[Slack Notifications Service](../../user/project/integrations/slack.md), which you
+can configure for new alerts and new incidents. After configuring, responders
+receive a **single** page via Slack. To set up Slack notifications on your mobile
+device, make sure to enable notifications for the Slack app on your phone so
+you never miss a page.
+
+## Email notifications
+
+Email notifications are available in projects that have been
+[configured to create incidents automatically](incidents.md#create-incidents-automatically)
+for triggered alerts. Project members with the **Owner** or **Maintainer** roles are
+sent an email notification automatically. (This is not configurable.) To optionally
+send additional email notifications to project members with the **Developer** role:
+
+1. Navigate to **Settings > Operations**.
+1. Expand the **Incidents** section.
+1. In the **Alert Integration** tab, select the **Send a separate email notification to Developers**
+ check box.
+1. Select **Save changes**.
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index 6514a80a32b..fe0bfa3318b 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Status Page
+# Status Page **(ULTIMATE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2479) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
diff --git a/doc/operations/index.md b/doc/operations/index.md
index 1d738768531..4427dd66f3d 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Project operations **(CORE)**
+# Project operations **(FREE)**
GitLab provides a variety of tools to help operate and maintain
your applications:
diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md
index 36a73d66609..98beb8d6773 100644
--- a/doc/operations/metrics/alerts.md
+++ b/doc/operations/metrics/alerts.md
@@ -4,9 +4,9 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Set up alerts for Prometheus metrics **(CORE)**
+# Set up alerts for Prometheus metrics **(FREE)**
-> [Moved from Ultimate to Core](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) in GitLab 12.10.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to GitLab Free in 12.10.
After [configuring metrics for your CI/CD environment](index.md), you can set up
alerting for Prometheus metrics depending on the location of your instances, and
@@ -47,8 +47,8 @@ as soon as the alert fires:
## External Prometheus instances
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) in GitLab Ultimate 11.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to GitLab Free in 12.10.
For manually configured Prometheus servers, GitLab provides a notify endpoint for
use with Prometheus webhooks. If you have manual configuration enabled, an
@@ -78,9 +78,12 @@ For GitLab to associate your alerts with an [environment](../../ci/environments/
you must configure a `gitlab_environment_name` label on the alerts you set up in
Prometheus. The value of this should match the name of your environment in GitLab.
+You can display alerts with a `gitlab_environment_name` of `production`
+[on a dashboard](../../user/operations_dashboard/index.md#adding-a-project-to-the-dashboard).
+
In GitLab versions 13.1 and greater, you can configure your manually configured
Prometheus server to use the
-[Generic alerts integration](../incident_management/alert_integrations.md).
+[Generic alerts integration](../incident_management/integrations.md).
## Trigger actions from alerts **(ULTIMATE)**
@@ -101,11 +104,20 @@ values extracted from the [`alerts` field in webhook payload](https://prometheus
- Issue author: `GitLab Alert Bot`
- Issue title: Extracted from the alert payload fields `annotations/title`, `annotations/summary`, or `labels/alertname`.
+- Issue description: Extracted from alert payload field `annotations/description`.
- Alert `Summary`: A list of properties from the alert's payload.
- `starts_at`: Alert start time from the payload's `startsAt` field
- `full_query`: Alert query extracted from the payload's `generatorURL` field
- Optional list of attached annotations extracted from `annotations/*`
- Alert [GFM](../../user/markdown.md): GitLab Flavored Markdown from the payload's `annotations/gitlab_incident_markdown` field.
+- Alert Severity (introduced in GitLab version [13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50871):
+ Extracted from the alert payload field `labels/severity`. Maps case-insensitive
+ value to [Alert's severity](../incident_management/alerts.md#alert-severity):
+ - **Critical**: `critical`, `s1`, `p1`, `emergency`, `fatal`, or any value not in this list
+ - **High**: `high`, `s2`, `p2`, `major`, `page`
+ - **Medium**: `medium`, `s3`, `p3`, `error`, `alert`
+ - **Low**: `low`, `s4`, `p4`, `warn`, `warning`
+ - **Info**: `info`, `s5`, `p5`, `debug`, `information`, `notice`
When GitLab receives a **Recovery Alert**, it closes the associated issue.
This action is recorded as a system message on the issue indicating that it
diff --git a/doc/operations/metrics/dashboards/default.md b/doc/operations/metrics/dashboards/default.md
index 5c6187565dd..3c151586f12 100644
--- a/doc/operations/metrics/dashboards/default.md
+++ b/doc/operations/metrics/dashboards/default.md
@@ -4,7 +4,7 @@ group: Health
info: To 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-defined metrics dashboards **(CORE)**
+# GitLab-defined metrics dashboards **(FREE)**
GitLab provides some dashboards out-of-the-box for any project with
[Prometheus available](../../../user/project/integrations/prometheus.md). You can
diff --git a/doc/operations/metrics/dashboards/develop.md b/doc/operations/metrics/dashboards/develop.md
index 800ed401efb..76ad609870c 100644
--- a/doc/operations/metrics/dashboards/develop.md
+++ b/doc/operations/metrics/dashboards/develop.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Developing templates for custom dashboards **(CORE)**
+# Developing templates for custom dashboards **(FREE)**
GitLab provides a template to make it easier for you to create templates for
[custom dashboards](index.md). Templates provide helpful guidance and
@@ -27,7 +27,7 @@ Navigate to the browser-based editor of your choice:
1. Click **{doc-new}** **New file**, then click **Choose a template** to see a list of available templates:
![Metrics dashboard template selection WebIDE](img/metrics_dashboard_template_selection_web_ide_v13_3.png)
-## Custom dashboard templates **(PREMIUM ONLY)**
+## Custom dashboard templates **(PREMIUM SELF)**
To enable and use a custom dashboard templates on your GitLab instance, read the
[guide for creating custom templates](../../../user/admin_area/settings/instance_template_repository.md).
diff --git a/doc/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md
index f875c4a87c5..a0ac4fe6226 100644
--- a/doc/operations/metrics/dashboards/index.md
+++ b/doc/operations/metrics/dashboards/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Custom dashboards **(CORE)**
+# Custom dashboards **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59974) in GitLab 12.1.
@@ -94,7 +94,7 @@ with the **Add Panel** page:
## Duplicate a GitLab-defined dashboard
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/37238) in GitLab 12.7.
-> - From [GitLab 12.8 onwards](https://gitlab.com/gitlab-org/gitlab/-/issues/39505), custom metrics are also duplicated when you duplicate a dashboard.
+> - [GitLab versions 12.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/39505), custom metrics are also duplicated when you duplicate a dashboard.
You can save a complete copy of a GitLab-defined dashboard along with all custom metrics added to it.
The resulting `.yml` file can be customized and adapted to your project.
@@ -128,7 +128,7 @@ any chart on a dashboard:
The options are:
- **Expand panel** - Displays a larger version of a visualization. To return to
- the dashboard, click the **Back** button in your browser, or press the <kbd>Esc</kbd> key.
+ the dashboard, click the **Back** button in your browser, or press the <kbd>Escape</kbd> key.
([Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3100) in GitLab 13.0.)
- **View logs** **(ULTIMATE)** - Displays [Logs](../../../user/project/clusters/kubernetes_pod_logs.md),
if they are enabled. If used in conjunction with the [timeline zoom](#timeline-zoom-and-url-sharing)
@@ -147,7 +147,7 @@ The options are:
You can use the **Timeline zoom** function at the bottom of a chart to zoom in
on a date and time of your choice. When you click and drag the sliders to select
a different beginning or end date of data to display, GitLab adds your selected start
-and end times to the URL, enabling you to share specific timeframes more easily.
+and end times to the URL, enabling you to share specific time frames more easily.
## Dashboard Annotations
diff --git a/doc/operations/metrics/dashboards/panel_types.md b/doc/operations/metrics/dashboards/panel_types.md
index 86f6776e273..4b942ffcf4f 100644
--- a/doc/operations/metrics/dashboards/panel_types.md
+++ b/doc/operations/metrics/dashboards/panel_types.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Panel types for dashboards **(CORE)**
+# Panel types for dashboards **(FREE)**
The below panel types are supported in monitoring dashboards.
diff --git a/doc/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md
index 92f3a14aab9..18cfd6c53b8 100644
--- a/doc/operations/metrics/dashboards/settings.md
+++ b/doc/operations/metrics/dashboards/settings.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Dashboard settings
+# Dashboard settings **(FREE)**
You can configure your [Monitoring dashboard](../index.md) to
display the time zone of your choice, and the links of your choice.
diff --git a/doc/operations/metrics/dashboards/templating_variables.md b/doc/operations/metrics/dashboards/templating_variables.md
index db02cc3bf98..72541f7ced5 100644
--- a/doc/operations/metrics/dashboards/templating_variables.md
+++ b/doc/operations/metrics/dashboards/templating_variables.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Templating variables for metrics dashboards **(CORE)**
+# Templating variables for metrics dashboards **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214539) in GitLab 13.0.
diff --git a/doc/operations/metrics/dashboards/variables.md b/doc/operations/metrics/dashboards/variables.md
index 9c5ff3bd13b..c0d0f65cc65 100644
--- a/doc/operations/metrics/dashboards/variables.md
+++ b/doc/operations/metrics/dashboards/variables.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Using variables **(CORE)**
+# Using variables **(FREE)**
## Query variables
diff --git a/doc/operations/metrics/dashboards/yaml.md b/doc/operations/metrics/dashboards/yaml.md
index db49de7e800..138d9b28c76 100644
--- a/doc/operations/metrics/dashboards/yaml.md
+++ b/doc/operations/metrics/dashboards/yaml.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Dashboard YAML properties **(CORE)**
+# Dashboard YAML properties **(FREE)**
Dashboards have several components:
@@ -133,7 +133,7 @@ metrics:
unit: 'count'
```
-This works by lowercasing the value of `label` and, if there are more words separated by spaces, replacing those spaces with an underscore (`_`). The transformed value is then checked against the labels of the time series returned by the Prometheus query. If a time series label is found that is equal to the transformed value, then the label value renders in the legend like this:
+This works by converting the value of `label` to lower-case and, if there are more words separated by spaces, replacing those spaces with an underscore (`_`). The transformed value is then checked against the labels of the time series returned by the Prometheus query. If a time series label is found that is equal to the transformed value, then the label value renders in the legend like this:
![legend with label shorthand variable](img/prometheus_dashboard_label_variable_shorthand.png)
diff --git a/doc/operations/metrics/dashboards/yaml_number_format.md b/doc/operations/metrics/dashboards/yaml_number_format.md
index 27e4b905597..dd652a0cc2b 100644
--- a/doc/operations/metrics/dashboards/yaml_number_format.md
+++ b/doc/operations/metrics/dashboards/yaml_number_format.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Unit formats reference **(CORE)**
+# Unit formats reference **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201999) in GitLab 12.9.
diff --git a/doc/operations/metrics/embed.md b/doc/operations/metrics/embed.md
index 9a9a0b4cff2..e5ab391afe5 100644
--- a/doc/operations/metrics/embed.md
+++ b/doc/operations/metrics/embed.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Embedding metric charts within GitLab-flavored Markdown **(CORE)**
+# Embedding metric charts within GitLab-flavored Markdown **(FREE)**
You can display metrics charts within
[GitLab Flavored Markdown](../../user/markdown.md#gitlab-flavored-markdown-gfm)
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index 21950354ae9..f9db3750bb9 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Embedding Grafana charts **(CORE)**
+# Embedding Grafana charts **(FREE)**
Grafana metrics can be embedded in [GitLab Flavored Markdown](../../user/markdown.md).
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index 7cd18e5606b..ca7bce347d3 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitor your environment's metrics **(CORE)**
+# Monitor your environment's metrics **(FREE)**
GitLab helps your team monitor the health and performance of your applications
and infrastructure by turning statistics and log files into charts and graphs
@@ -131,8 +131,7 @@ dashboard is visible to authenticated and non-authenticated users.
## Adding custom metrics
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3799) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28527) to [GitLab Core](https://about.gitlab.com/pricing/) 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28527) to GitLab Free in 12.10.
Custom metrics can be monitored by adding them on the monitoring dashboard page.
After saving them, they display on the environment metrics dashboard provided that either:
diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md
deleted file mode 100644
index 07df1607d37..00000000000
--- a/doc/operations/moving_repositories.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/operations/moving_repositories.md'
----
-
-This document was moved to [another location](../administration/operations/moving_repositories.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/product_analytics.md b/doc/operations/product_analytics.md
index e6e887b9738..db6dc13607b 100644
--- a/doc/operations/product_analytics.md
+++ b/doc/operations/product_analytics.md
@@ -1,10 +1,10 @@
---
stage: Growth
-group: Product Analytics
+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
---
-# Product Analytics **(CORE)**
+# Product Analytics **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225167) in GitLab 13.3.
> - It's deployed behind a feature flag, disabled by default.
diff --git a/doc/operations/sidekiq_memory_killer.md b/doc/operations/sidekiq_memory_killer.md
deleted file mode 100644
index b98e4abb4d0..00000000000
--- a/doc/operations/sidekiq_memory_killer.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/operations/sidekiq_memory_killer.md'
----
-
-This document was moved to [another location](../administration/operations/sidekiq_memory_killer.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/operations/tracing.md b/doc/operations/tracing.md
index c08651560e0..a4aae05c46d 100644
--- a/doc/operations/tracing.md
+++ b/doc/operations/tracing.md
@@ -4,10 +4,10 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Tracing
+# Tracing **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7903) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
-> - [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab/-/issues/42645) in 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7903) in GitLab Ultimate 11.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42645) to GitLab Free in 13.5.
Tracing provides insight into the performance and health of a deployed application,
tracking each function or microservice which handles a given request.
diff --git a/doc/operations/unicorn.md b/doc/operations/unicorn.md
deleted file mode 100644
index d10b7f8bbb9..00000000000
--- a/doc/operations/unicorn.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/operations/unicorn.md'
----
-
-This document was moved to [another location](../administration/operations/unicorn.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md
deleted file mode 100644
index 38b68ff9e42..00000000000
--- a/doc/permissions/permissions.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-redirect_to: '../user/permissions.md'
----
-
-# Permissions
-
-This document was moved to [user/permissions.md](../user/permissions.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index e097d2c24a8..0df0ef06d19 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -74,7 +74,7 @@ A step-by-step guide to [upgrading the Omnibus-bundled PostgreSQL is documented
## Upgrading major versions
-Backward-incompatible changes and migrations are reserved for major versions. See the [upgrade guide](../update/README.md#upgrading-to-a-new-major-version).
+Backward-incompatible changes and migrations are reserved for major versions. See the [upgrade guide](../update/index.md#upgrading-to-a-new-major-version).
## Patch releases
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 4f902382fd5..9be76416ba7 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -5,21 +5,21 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Push Rules **(STARTER)**
+# 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.
-## Overview
-
GitLab already offers [protected branches](../user/project/protected_branches.md), but there are
-cases when you need some specific rules like preventing Git tag removal or
+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 essentially [pre-receive Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that are easy to
-enable in a user-friendly interface. They are defined globally if you are an
-admin or per project so you can have different rules applied to different
-projects depending on your needs.
+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
@@ -32,24 +32,24 @@ 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`
-All you need to do is write a simple regular expression that requires the mention
+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 will
-be declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
-will be accepted.
+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
-Let's assume there's a strict policy for branch names in your company, and
-you want the branches to start with a certain name because you have different
-GitLab CI/CD jobs (`feature`, `hotfix`, `docker`, `android`, etc.) that rely on the
+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, however, don't always remember that policy, so they might push to
+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.
-Any branch name that doesn't match your push rule will get rejected.
+Any branch name that doesn't match your push rule is 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
@@ -64,9 +64,9 @@ which already limits users from pushing directly.
> Introduced in GitLab 12.10.
By default, GitLab restricts certain formats of branch names for security purposes.
-Currently 40-character hexadecimal names, similar to Git commit hashes, are prohibited.
+40-character hexadecimal names, similar to Git commit hashes, are prohibited.
-### Custom Push Rules **(CORE ONLY)**
+### Custom Push Rules **(FREE 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.
@@ -77,10 +77,10 @@ See [server hooks](../administration/server_hooks.md) for more information.
NOTE:
GitLab administrators can set push rules globally under
-**Admin Area > Push Rules** that all new projects will inherit. You can later
+**Admin Area > Push Rules** that all new projects inherit. You can later
override them in a project's settings. They can be also set on a [group level](../user/group/index.md#group-push-rules).
-1. Navigate to your project's **Settings > Repository** and expand **Push Rules**
+1. Navigate to your project's **Settings > Repository** and expand **Push rules**
1. Set the rule you want
1. Click **Save Push Rules** for the changes to take effect
@@ -88,13 +88,13 @@ The following options are available:
| Push rule | Description |
|---------------------------------|-------------|
-| Removal of tags with `git push` | Forbid users to remove Git tags with `git push`. Tags will still be able to be deleted through the web UI. |
-| Check whether author is a GitLab user | Restrict commits by author (email) to existing GitLab users. |
-| Committer restriction **(PREMIUM)** | GitLab will reject any commit that was not committed by the current authenticated user. |
+| 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). |
+| Reject unverified users **(PREMIUM)** | GitLab rejects any commit that was not committed by an authenticated user. |
| Check whether commit is signed through GPG **(PREMIUM)** | Reject commit when it is not signed through GPG. Read [signing commits with GPG](../user/project/repository/gpg_signed_commits/index.md). |
-| Prevent committing secrets to Git | GitLab will reject any files that are likely to contain secrets. Read [what files are forbidden](#prevent-pushing-secrets-to-the-repository). |
-| Restrict by commit message | Only commit messages that match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
-| Restrict by commit message (negative match) | Only commit messages that do not match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| 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. 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. 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. Leave empty to allow any branch name. |
| Restrict by commit author's email | Only commit author's email that match this regular expression are allowed to be pushed. 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. Leave empty to allow any filenames. See [common examples](#prohibited-file-names). |
@@ -105,11 +105,12 @@ GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular
## Prevent pushing secrets to the repository
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.12.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385) in GitLab 8.12.
+> - Moved to GitLab Premium in 13.9.
Secrets such as credential files, SSH private keys, and other files containing secrets should never be committed to source control.
-GitLab allows you to turn on a predefined denylist of files which won't be allowed to be
-pushed to a repository, stopping those commits from reaching the remote repository.
+GitLab enables you to turn on a predefined denylist of files which can't be
+pushed to a repository. The list stops those commits from reaching the remote repository.
By selecting the checkbox *Prevent committing secrets to Git*, GitLab prevents
pushes to the repository when a file matches a regular expression as read from
@@ -117,9 +118,9 @@ pushes to the repository when a file matches a regular expression as read from
as your GitLab version when viewing this file).
NOTE:
-Files already committed won't get restricted by this push rule.
+Files already committed aren't restricted by this push rule.
-Below is an example list of what will be rejected by these regular expressions:
+Below is an example list of what GitLab rejects with these regular expressions:
```shell
#####################
@@ -180,7 +181,8 @@ id_ecdsa
## Prohibited file names
-> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 7.10.
+> - Introduced in GitLab 7.10.
+> - 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.
@@ -204,13 +206,17 @@ Example: prevent a specific configuration file in a known directory from being p
^directory-name\/config\.yml$
```
-Example: prevent the specific file named `install.exe` from being pushed to any location in the repository. Note that the parenthesized expression `(^|\/)` will match either a file following a directory separator or a file in the root directory of the repository:
+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. Note that all of the preceding expressions rely on the end of string character `$`, so we can move that part of each expression to the end of the grouped collection of match conditions where it will be appended to all matches:
+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)$
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index e119563fd25..c815842480c 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -1,48 +1,8 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-comments: false
+redirect_to: 'index.md'
---
-# Rake tasks **(CORE ONLY)**
+This document was moved to [another location](index.md).
-GitLab provides [Rake](https://ruby.github.io/rake/) tasks for common administration and operational processes.
-
-GitLab Rake tasks are performed using:
-
-- `gitlab-rake <raketask>` for [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) installations.
-- `bundle exec rake <raketask>` for [source](../install/installation.md) installations.
-
-## Available Rake tasks
-
-The following are available Rake tasks:
-
-| Tasks | Description |
-|:----------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
-| [Back up and restore](backup_restore.md) | Back up, restore, and migrate GitLab instances between servers. |
-| [Clean up](cleanup.md) | Clean up unneeded items from GitLab instances. |
-| [Development](../development/rake_tasks.md) | Tasks for GitLab contributors. |
-| [Doctor tasks](../administration/raketasks/doctor.md) | Checks for data integrity issues. |
-| [Elasticsearch](../integration/elasticsearch.md#gitlab-advanced-search-rake-tasks) **(STARTER ONLY)** | Maintain Elasticsearch in a GitLab instance. |
-| [Enable namespaces](features.md) | Enable usernames and namespaces for user projects. |
-| [General maintenance](../administration/raketasks/maintenance.md) | General maintenance and self-check tasks. |
-| [Geo maintenance](../administration/raketasks/geo.md) **(PREMIUM ONLY)** | [Geo](../administration/geo/index.md)-related maintenance. |
-| [GitHub import](../administration/raketasks/github_import.md) | Retrieve and import repositories from GitHub. |
-| [Import repositories](import.md) | Import bare repositories into your GitLab instance. |
-| [Import large project exports](../development/import_project.md#importing-via-a-rake-task) | Import large GitLab [project exports](../user/project/settings/import_export.md). |
-| [Integrity checks](../administration/raketasks/check.md) | Check the integrity of repositories, files, and LDAP. |
-| [LDAP maintenance](../administration/raketasks/ldap.md) | [LDAP](../administration/auth/ldap/index.md)-related tasks. |
-| [List repositories](list_repos.md) | List of all GitLab-managed Git repositories on disk. |
-| [Migrate Snippets to Git](migrate_snippets.md) | Migrate GitLab Snippets to Git repositories and show migration status |
-| [Praefect Rake tasks](../administration/raketasks/praefect.md) | [Praefect](../administration/gitaly/praefect.md)-related tasks. |
-| [Project import/export](../administration/raketasks/project_import_export.md) | Prepare for [project exports and imports](../user/project/settings/import_export.md). |
-| [Sample Prometheus data](generate_sample_prometheus_data.md) | Generate sample Prometheus data. |
-| [SPDX license list import](spdx.md) **(PREMIUM ONLY)** | Import a local copy of the [SPDX license list](https://spdx.org/licenses/) for matching [License Compliance policies](../user/compliance/license_compliance/index.md).| |
-| [Repository storage](../administration/raketasks/storage.md) | List and migrate existing projects and attachments from legacy storage to hashed storage. |
-| [Uploads migrate](../administration/raketasks/uploads/migrate.md) | Migrate uploads between storage local and object storage. |
-| [Uploads sanitize](../administration/raketasks/uploads/sanitize.md) | Remove EXIF data from images uploaded to earlier versions of GitLab. |
-| [Usage data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping) | Generate and troubleshoot [Usage Ping](../development/usage_ping.md).|
-| [User management](user_management.md) | Perform user management tasks. |
-| [Webhooks administration](web_hooks.md) | Maintain project Webhooks. |
-| [X.509 signatures](x509_signatures.md) | Update X.509 commit signatures, useful if certificate store has changed. |
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- 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 8a01975f771..20131a795c5 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# Back up and restore GitLab **(CORE ONLY)**
+# Back up and restore GitLab **(FREE SELF)**
GitLab provides Rake tasks for backing up and restoring GitLab instances.
@@ -16,7 +16,7 @@ of GitLab on which it was created. The best way to migrate your repositories
from one server to another is through backup restore.
WARNING:
-GitLab doesn't back up items that aren't stored in the filesystem. If you're
+GitLab doesn't back up items that aren't stored in the file system. If you're
using [object storage](../administration/object_storage.md), be sure to enable
backups with your object storage provider, if desired.
@@ -100,7 +100,7 @@ the host, based on your installed version of GitLab:
- GitLab 12.1 and earlier:
```shell
- gitlab-rake gitlab:backup:create
+ docker exec -t <container name> gitlab-rake gitlab:backup:create
```
If you're using the [GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab)
@@ -240,7 +240,7 @@ The resulting file is named `dump_gitlab_backup.tar`. This is useful for
systems that make use of rsync and incremental backups, and results in
considerably faster transfer speeds.
-#### Rsyncable
+#### Confirm archive can be transferred
To ensure the generated archive is transferable by rsync, you can set the `GZIP_RSYNCABLE=yes`
option. This sets the `--rsyncable` option to `gzip`, which is useful only in
@@ -810,7 +810,7 @@ data into (`gitlabhq_production`). All existing data is either erased
To restore a backup, you must restore `/etc/gitlab/gitlab-secrets.json`
(for Omnibus packages) or `/home/git/gitlab/.secret` (for installations from
source). This file contains the database encryption key,
-[CI/CD variables](../ci/variables/README.md#gitlab-cicd-environment-variables), and
+[CI/CD variables](../ci/variables/README.md), and
variables used for [two-factor authentication](../user/profile/account/two_factor_authentication.md).
If you fail to restore this encryption key file along with the application data
backup, users with two-factor authentication enabled and GitLab Runner
@@ -1024,7 +1024,7 @@ restoring a single project or group, you can use a workaround by restoring
your backup to a separate, temporary GitLab instance, and then export your
project or group from there:
-1. [Install a new GitLab](../install/README.md) instance at the same version as
+1. [Install a new GitLab](../install/index.md) instance at the same version as
the backed-up instance from which you want to restore.
1. [Restore the backup](#restore-gitlab) into this new instance, then
export your [project](../user/project/settings/import_export.md)
@@ -1042,12 +1042,12 @@ is being discussed in [issue #17517](https://gitlab.com/gitlab-org/gitlab/-/issu
If your GitLab server contains a lot of Git repository data, you may find the
GitLab backup script to be too slow. In this case you can consider using
-filesystem snapshots as part of your backup strategy.
+file system snapshots as part of your backup strategy.
Example: Amazon EBS
> A GitLab server using Omnibus GitLab hosted on Amazon AWS.
-> An EBS drive containing an ext4 filesystem is mounted at `/var/opt/gitlab`.
+> An EBS drive containing an ext4 file system is mounted at `/var/opt/gitlab`.
> In this case you could make an application backup by taking an EBS snapshot.
> The backup includes all repositories, uploads and PostgreSQL data.
@@ -1055,7 +1055,7 @@ Example: LVM snapshots + rsync
> A GitLab server using Omnibus GitLab, with an LVM logical volume mounted at `/var/opt/gitlab`.
> Replicating the `/var/opt/gitlab` directory using rsync would not be reliable because too many files would change while rsync is running.
-> Instead of rsync-ing `/var/opt/gitlab`, we create a temporary LVM snapshot, which we mount as a read-only filesystem at `/mnt/gitlab_backup`.
+> Instead of rsync-ing `/var/opt/gitlab`, we create a temporary LVM snapshot, which we mount as a read-only file system at `/mnt/gitlab_backup`.
> Now we can have a longer running rsync job which creates a consistent replica on the remote server.
> The replica includes all repositories, uploads and PostgreSQL data.
@@ -1204,9 +1204,9 @@ and the jobs begin running again.
Use the information in the following sections at your own risk.
-#### Check for undecryptable values
+#### Verify that all values can be decrypted
-You can determine if you have undecryptable values in the database by using the
+You can determine if your database contains values that can't be decrypted by using the
[Secrets Doctor Rake task](../administration/raketasks/doctor.md).
#### Take a backup
@@ -1285,6 +1285,7 @@ You may need to reconfigure or restart GitLab for the changes to take effect.
UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
-- Clear instance tokens
UPDATE application_settings SET runners_registration_token_encrypted = null;
+ UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
-- Clear runner tokens
UPDATE ci_runners SET token = null, token_encrypted = null;
```
@@ -1370,7 +1371,7 @@ To get your registry working again:
sudo chown -R registry:registry /var/opt/gitlab/gitlab-rails/shared/registry/docker
```
-If you changed the default filesystem location for the registry, run `chown`
+If you changed the default file system location for the registry, run `chown`
against your custom location, instead of `/var/opt/gitlab/gitlab-rails/shared/registry/docker`.
### Backup fails to complete with Gzip error
diff --git a/doc/raketasks/check.md b/doc/raketasks/check.md
deleted file mode 100644
index 1a8149ca04a..00000000000
--- a/doc/raketasks/check.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/raketasks/check.md'
----
-
-This document was moved to [another location](../administration/raketasks/check.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index 0c184aa0075..9f79d3cc675 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# Clean up **(CORE ONLY)**
+# Clean up **(FREE SELF)**
GitLab provides Rake tasks for cleaning up GitLab instances.
@@ -74,7 +74,7 @@ I, [2020-01-08T20:51:17.148765 #43765] INFO -- : Removed unreferenced LFS files
Clean up project upload files if they don't exist in GitLab database.
-### Clean up project upload files from filesystem
+### Clean up project upload files from file system
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20863) in GitLab 11.2.
@@ -173,7 +173,7 @@ delete the files:
sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files DRY_RUN=false
```
-You can also limit the number of files to delete with `LIMIT`:
+You can also limit the number of files to delete with `LIMIT` (default `100`):
```shell
sudo gitlab-rake gitlab:cleanup:orphan_job_artifact_files LIMIT=100
diff --git a/doc/raketasks/features.md b/doc/raketasks/features.md
index bf67522c256..ba14293a9fd 100644
--- a/doc/raketasks/features.md
+++ b/doc/raketasks/features.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# Namespaces **(CORE ONLY)**
+# Namespaces **(FREE SELF)**
This Rake task enables [namespaces](../user/group/index.md#namespaces) for projects.
@@ -15,7 +15,13 @@ This command enables the namespaces feature introduced in GitLab 4.0. It moves e
The **repository location changes as part of this task**, so you must **update all your Git URLs** to
point to the new location.
-The username can be changed at **Profile > Account**.
+To change your username:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Account**.
+1. In the **Change username** section, type the new username.
+1. Select **Update username**.
For example:
diff --git a/doc/raketasks/generate_sample_prometheus_data.md b/doc/raketasks/generate_sample_prometheus_data.md
index 9dbdf053693..41e31c0b817 100644
--- a/doc/raketasks/generate_sample_prometheus_data.md
+++ b/doc/raketasks/generate_sample_prometheus_data.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Generate sample Prometheus data **(CORE ONLY)**
+# Generate sample Prometheus data **(FREE SELF)**
This command runs Prometheus queries for each of the metrics of a specific environment
for a series of time intervals to now:
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index 648cd784c1b..b18413987a3 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# Import bare repositories **(CORE ONLY)**
+# Import bare repositories **(FREE SELF)**
Rake tasks are available to import bare repositories into a GitLab instance.
When migrating from an existing GitLab instance,
diff --git a/doc/raketasks/index.md b/doc/raketasks/index.md
new file mode 100644
index 00000000000..be7e55cba9b
--- /dev/null
+++ b/doc/raketasks/index.md
@@ -0,0 +1,48 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+comments: false
+---
+
+# Rake tasks **(FREE SELF)**
+
+GitLab provides [Rake](https://ruby.github.io/rake/) tasks for common administration and operational processes.
+
+GitLab Rake tasks are performed using:
+
+- `gitlab-rake <raketask>` for [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) installations.
+- `bundle exec rake <raketask>` for [source](../install/installation.md) installations.
+
+## Available Rake tasks
+
+The following are available Rake tasks:
+
+| Tasks | Description |
+|:----------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
+| [Back up and restore](backup_restore.md) | Back up, restore, and migrate GitLab instances between servers. |
+| [Clean up](cleanup.md) | Clean up unneeded items from GitLab instances. |
+| [Development](../development/rake_tasks.md) | Tasks for GitLab contributors. |
+| [Doctor tasks](../administration/raketasks/doctor.md) | Checks for data integrity issues. |
+| [Elasticsearch](../integration/elasticsearch.md#gitlab-advanced-search-rake-tasks) **(PREMIUM SELF)** | Maintain Elasticsearch in a GitLab instance. |
+| [Enable namespaces](features.md) | Enable usernames and namespaces for user projects. |
+| [General maintenance](../administration/raketasks/maintenance.md) | General maintenance and self-check tasks. |
+| [Geo maintenance](../administration/raketasks/geo.md) **(PREMIUM SELF)** | [Geo](../administration/geo/index.md)-related maintenance. |
+| [GitHub import](../administration/raketasks/github_import.md) | Retrieve and import repositories from GitHub. |
+| [Import repositories](import.md) | Import bare repositories into your GitLab instance. |
+| [Import large project exports](../development/import_project.md#importing-via-a-rake-task) | Import large GitLab [project exports](../user/project/settings/import_export.md). |
+| [Integrity checks](../administration/raketasks/check.md) | Check the integrity of repositories, files, and LDAP. |
+| [LDAP maintenance](../administration/raketasks/ldap.md) | [LDAP](../administration/auth/ldap/index.md)-related tasks. |
+| [List repositories](list_repos.md) | List of all GitLab-managed Git repositories on disk. |
+| [Migrate Snippets to Git](migrate_snippets.md) | Migrate GitLab Snippets to Git repositories and show migration status |
+| [Praefect Rake tasks](../administration/raketasks/praefect.md) | [Praefect](../administration/gitaly/praefect.md)-related tasks. |
+| [Project import/export](../administration/raketasks/project_import_export.md) | Prepare for [project exports and imports](../user/project/settings/import_export.md). |
+| [Sample Prometheus data](generate_sample_prometheus_data.md) | Generate sample Prometheus data. |
+| [SPDX license list import](spdx.md) **(PREMIUM SELF)** | Import a local copy of the [SPDX license list](https://spdx.org/licenses/) for matching [License Compliance policies](../user/compliance/license_compliance/index.md).| |
+| [Repository storage](../administration/raketasks/storage.md) | List and migrate existing projects and attachments from legacy storage to hashed storage. |
+| [Uploads migrate](../administration/raketasks/uploads/migrate.md) | Migrate uploads between storage local and object storage. |
+| [Uploads sanitize](../administration/raketasks/uploads/sanitize.md) | Remove EXIF data from images uploaded to earlier versions of GitLab. |
+| [Usage data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping) | Generate and troubleshoot [Usage Ping](../development/usage_ping.md).|
+| [User management](user_management.md) | Perform user management tasks. |
+| [Webhooks administration](web_hooks.md) | Maintain project Webhooks. |
+| [X.509 signatures](x509_signatures.md) | Update X.509 commit signatures, useful if certificate store has changed. |
diff --git a/doc/raketasks/list_repos.md b/doc/raketasks/list_repos.md
index e2442df3418..35c5e1e3357 100644
--- a/doc/raketasks/list_repos.md
+++ b/doc/raketasks/list_repos.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# Listing repository directories **(CORE ONLY)**
+# Listing repository directories **(FREE SELF)**
You can print a list of all Git repositories on disk managed by GitLab.
diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md
deleted file mode 100644
index b6d530256a7..00000000000
--- a/doc/raketasks/maintenance.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../administration/raketasks/maintenance.md'
----
-
-This document was moved to [another location](../administration/raketasks/maintenance.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/raketasks/migrate_snippets.md b/doc/raketasks/migrate_snippets.md
index 244ff4f2b56..0d2c4edb01f 100644
--- a/doc/raketasks/migrate_snippets.md
+++ b/doc/raketasks/migrate_snippets.md
@@ -4,25 +4,24 @@ 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
---
-# Migration to Versioned Snippets **(CORE ONLY)**
+# Migration to versioned snippets **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215861) in GitLab 13.0.
In GitLab 13.0, [GitLab Snippets are backed by Git repositories](../user/snippets.md#versioned-snippets).
-This means that the snippet content will be stored in the repository
-and users can update it directly through Git.
+Snippet content is stored in the repository, and users can update it directly through Git.
-Nevertheless, existing GitLab Snippets have to be migrated to this new functionality.
-For each snippet, a new repository is created and the snippet content is committed
-to the repository inside a file whose name is the filename used in the snippet
-as well.
+Nevertheless, existing GitLab Snippets must be migrated to this new feature.
+For each snippet:
-GitLab performs this migration through a [Background Migration](../development/background_migrations.md)
-automatically when the GitLab instance is upgrade to 13.0 or a higher version.
-However, if the migration fails for any of the snippets, they still need
-to be migrated individually.
+- A new repository is created.
+- A file is created in the repository, using the snippet filename.
+- The snippet is committed to the repository.
-The following Rake tasks will help with that process.
+GitLab performs this migration through a [Background Migration](../development/background_migrations.md)
+when the GitLab instance is upgraded to 13.0 or a higher version.
+However, if the migration fails for any of the snippets, they must be migrated individually.
+The following Rake tasks help with that process.
## Migrate specific snippets to Git
diff --git a/doc/raketasks/spdx.md b/doc/raketasks/spdx.md
index fe7ac13c463..f330698daba 100644
--- a/doc/raketasks/spdx.md
+++ b/doc/raketasks/spdx.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+stage: Secure
+group: Composition 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
---
-# SPDX license list import **(PREMIUM ONLY)**
+# SPDX license list import **(PREMIUM SELF)**
GitLab provides a Rake task for uploading a fresh copy of the [SPDX license list](https://spdx.org/licenses/)
to a GitLab instance. This list is needed for matching the names of [License Compliance policies](../user/compliance/license_compliance/index.md).
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 6df978b2efd..08f0005883b 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# User management **(CORE ONLY)**
+# User management **(FREE SELF)**
GitLab provides Rake tasks for user management.
diff --git a/doc/raketasks/web_hooks.md b/doc/raketasks/web_hooks.md
index 1f40c60e23d..e48a03f6883 100644
--- a/doc/raketasks/web_hooks.md
+++ b/doc/raketasks/web_hooks.md
@@ -1,10 +1,10 @@
---
-stage: none
-group: unassigned
+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
---
-# Webhooks administration **(CORE ONLY)**
+# Webhooks administration **(FREE SELF)**
GitLab provides Rake tasks for webhooks management.
diff --git a/doc/raketasks/x509_signatures.md b/doc/raketasks/x509_signatures.md
index a98f0af8cd8..5090fc285cc 100644
--- a/doc/raketasks/x509_signatures.md
+++ b/doc/raketasks/x509_signatures.md
@@ -4,7 +4,7 @@ group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# X.509 signatures **(CORE ONLY)**
+# X.509 signatures **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/122159) in GitLab 12.10.
diff --git a/doc/security/README.md b/doc/security/README.md
index 3b64d0229ed..b009fe5c8da 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -23,7 +23,7 @@ type: index
- [Send email confirmation on sign-up](user_email_confirmation.md)
- [Security of running jobs](https://docs.gitlab.com/runner/security/)
- [Proxying images](asset_proxy.md)
-- [CI/CD environment variables](cicd_environment_variables.md)
+- [CI/CD variables](cicd_variables.md)
## Securing your GitLab installation
diff --git a/doc/security/asset_proxy.md b/doc/security/asset_proxy.md
index 613743143d3..7774f5e0635 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -51,7 +51,8 @@ To install a Camo server as an asset proxy:
| `asset_proxy_enabled` | Enable proxying of assets. If enabled, requires: `asset_proxy_url`). |
| `asset_proxy_secret_key` | Shared secret with the asset proxy server. |
| `asset_proxy_url` | URL of the asset proxy server. |
- | `asset_proxy_whitelist` | Assets that match these domain(s) are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted. |
+ | `asset_proxy_whitelist` | (Deprecated: Use `asset_proxy_allowlist` instead) Assets that match these domain(s) are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed. |
+ | `asset_proxy_allowlist` | Assets that match these domain(s) are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed. |
1. Restart the server for the changes to take effect. Each time you change any values for the asset
proxy, you need to restart the server.
diff --git a/doc/security/cicd_environment_variables.md b/doc/security/cicd_environment_variables.md
index 4d60df8e531..7de2e17c0f9 100644
--- a/doc/security/cicd_environment_variables.md
+++ b/doc/security/cicd_environment_variables.md
@@ -1,13 +1,8 @@
---
-stage: Release
-group: Release
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'cicd_variables.md'
---
-# CI/CD Environment Variables
+This document was moved to [another location](cicd_variables.md).
-Environment variables are applied to environments via the runner and can be set from the project's **Settings > CI/CD** page.
-
-The values are encrypted using [aes-256-cbc](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and stored in the database.
-
-This data can only be decrypted with a valid [secrets file](../raketasks/backup_restore.md#when-the-secrets-file-is-lost).
+<!-- This redirect file can be deleted after 2021-05-15. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/security/cicd_variables.md b/doc/security/cicd_variables.md
new file mode 100644
index 00000000000..4ef8129da2a
--- /dev/null
+++ b/doc/security/cicd_variables.md
@@ -0,0 +1,13 @@
+---
+stage: Secure
+group: None
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# CI/CD Variables
+
+CI/CD variables are applied to environments via the runner and can be set from the project's **Settings > CI/CD** page.
+
+The values are encrypted using [`aes-256-cbc`](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and stored in the database.
+
+This data can only be decrypted with a valid [secrets file](../raketasks/backup_restore.md#when-the-secrets-file-is-lost).
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index c5f8afe36ad..9a43f5dfca8 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -58,7 +58,7 @@ vulnerability.
## References
-- NGINX ["Module ngx_http_spdy_module"](http://nginx.org/en/docs/http/ngx_http_spdy_module.html)
+- NGINX ["Module `ngx_http_spdy_module`"](http://nginx.org/en/docs/http/ngx_http_spdy_module.html)
- Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"](https://www.tenable.com/plugins/index.php?view=single&id=62565)
- Wikipedia contributors, ["CRIME"](https://en.wikipedia.org/wiki/CRIME) Wikipedia, The Free Encyclopedia
diff --git a/doc/security/password_storage.md b/doc/security/password_storage.md
index ca39defe6b9..af4b57e342a 100644
--- a/doc/security/password_storage.md
+++ b/doc/security/password_storage.md
@@ -11,6 +11,6 @@ GitLab stores user passwords in a hashed format, to prevent passwords from being
GitLab uses the [Devise](https://github.com/heartcombo/devise) authentication library, which handles the hashing of user passwords. Password hashes are created with the following attributes:
-- **Hashing**: the [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) hashing function is used to generate the hash of the provided password. This is a strong, industry-standard cryptographic hashing function.
+- **Hashing**: the [`bcrypt`](https://en.wikipedia.org/wiki/Bcrypt) hashing function is used to generate the hash of the provided password. This is a strong, industry-standard cryptographic hashing function.
- **Stretching**: Password hashes are [stretched](https://en.wikipedia.org/wiki/Key_stretching) to harden against brute-force attacks. GitLab uses a stretching factor of 10 by default.
- **Salting**: A [cryptographic salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) is added to each password to harden against pre-computed hash and dictionary attacks. Each salt is randomly generated for each password, so that no two passwords share a salt, to further increase security.
diff --git a/doc/security/rate_limits.md b/doc/security/rate_limits.md
index 500ec057102..1609607ea5c 100644
--- a/doc/security/rate_limits.md
+++ b/doc/security/rate_limits.md
@@ -25,11 +25,14 @@ similarly mitigated by a rate limit.
## Admin Area settings
-- [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md).
-- [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md).
-- [Raw endpoints rate limits](../user/admin_area/settings/rate_limits_on_raw_endpoints.md).
-- [Protected paths](../user/admin_area/settings/protected_paths.md).
-- [Import/Export rate limits](../user/admin_area/settings/import_export_rate_limits.md).
+These are rate limits you can set in the Admin Area of your instance:
+
+- [Import/Export rate limits](../user/admin_area/settings/import_export_rate_limits.md)
+- [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md)
+- [Notes rate limits](../user/admin_area/settings/rate_limit_on_notes_creation.md)
+- [Protected paths](../user/admin_area/settings/protected_paths.md)
+- [Raw endpoints rate limits](../user/admin_area/settings/rate_limits_on_raw_endpoints.md)
+- [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md)
## Non-configurable limits
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index fc808452736..ed7b9f89616 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -7,70 +7,91 @@ type: howto
# How to reset user password
-To reset the password of a user, first log into your server with root privileges.
+There are a few ways to reset the password of a user.
-Start a Ruby on Rails console with this command:
+## Rake Task
+
+GitLab provides a Rake Task to reset passwords of users using their usernames,
+which can be invoked by the following command:
```shell
-gitlab-rails console -e production
+sudo gitlab-rake "gitlab:password:reset"
```
-Wait until the console has loaded.
-
-## Find the user
+You will be asked for username, password, and password confirmation. Upon giving
+proper values for them, the password of the specified user will be updated.
-There are multiple ways to find your user. You can search by email or user ID number.
+The Rake task also takes the username as an argument, as shown in the example
+below:
```shell
-user = User.where(id: 7).first
+sudo gitlab-rake "gitlab:password:reset[johndoe]"
```
-or
+NOTE:
+To reset the default admin password, run this Rake task with the username
+`root`, which is the default username of that admin account.
-```shell
-user = User.find_by(email: 'user@example.com')
-```
+## Rails console
-## Reset the password
+The Rake task is capable of finding users via their usernames. However, if only
+user ID or email ID of the user is known, Rails console can be used to find user
+using user ID and then change password of the user manually.
-Now you can change your password:
+1. Start a Rails console
-```shell
-user.password = 'secret_pass'
-user.password_confirmation = 'secret_pass'
-```
+ ```shell
+ sudo gitlab-rails console -e production
+ ```
-It's important that you change both password and password_confirmation to make it work.
+1. Find the user either by user ID or email ID:
-When using this method instead of the [Users API](../api/users.md#user-modification), GitLab sends an email to the user stating that the user changed their password.
+ ```ruby
+ user = User.find(123)
-If the password was changed by an administrator, execute the following command to notify the user by email:
+ #or
-```shell
-user.send_only_admin_changed_your_password_notification!
-```
+ user = User.find_by(email: 'user@example.com')
+ ```
-Don't forget to save the changes.
+1. Reset the password
-```shell
-user.save!
-```
+ ```ruby
+ user.password = 'secret_pass'
+ user.password_confirmation = 'secret_pass'
+ ```
+
+1. When using this method instead of the [Users API](../api/users.md#user-modification),
+ GitLab sends an email to the user stating that the user changed their
+ password. If the password was changed by an administrator, execute the
+ following command to notify the user by email:
+
+ ```ruby
+ user.send_only_admin_changed_your_password_notification!
+ ```
-Exit the console, and then try to sign in with your new password.
+1. Save the changes:
+
+ ```ruby
+ user.save!
+ ```
+
+1. Exit the console, and then try to sign in with your new password.
NOTE:
You can also reset passwords by using the [Users API](../api/users.md#user-modification).
-### Reset your root password
+## Reset your root password
-The previously described steps can also be used to reset the root password. First,
-identify the root user, with an `id` of `1`. To do so, run the following command:
+The previously described steps can also be used to reset the root password.
-```shell
-user = User.where(id: 1).first
-```
+In normal installations where the username of root account hasn't been changed
+manually, the Rake task can be used with username `root` to reset the root
+password.
-After finding the user, follow the steps mentioned in the [Reset the password](#reset-the-password) section to reset the password of the root user.
+If the username was changed to something else and has been forgotten, one
+possible way is to reset the password using Rails console with user ID `1` (in
+almost all the cases, the first user will be the default admin account).
<!-- ## Troubleshooting
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index 4911cf63489..7a9ed9d435d 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -110,9 +110,10 @@ Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
-## Two-factor Authentication (2FA) for Git over SSH operations
+## Two-factor Authentication (2FA) for Git over SSH operations **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/270554) in GitLab 13.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/299088) from GitLab Free to GitLab Premium in 13.9.
> - 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.
@@ -149,3 +150,8 @@ To disable it:
```ruby
Feature.disable(:two_factor_for_cli)
```
+
+The feature flag affects these features:
+
+- [Two-factor Authentication (2FA) for Git over SSH operations](#two-factor-authentication-2fa-for-git-over-ssh-operations).
+- [Customize session duration for Git Operations when 2FA is enabled](../user/admin_area/settings/account_and_limit_settings.md#customize-session-duration-for-git-operations-when-2fa-is-enabled).
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index 2a26b71071b..45da283f33e 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -40,7 +40,7 @@ To unlock a locked user:
user.unlock_access!
```
-1. Exit the console with <kbd>Ctrl</kbd>+<kbd>d</kbd>
+1. Exit the console with <kbd>Control</kbd>+<kbd>d</kbd>
The user should now be able to log in.
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index f34e38fb7ca..815d8c13c43 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -17,179 +17,145 @@ GitLab remote server without supplying your username or password each time.
This page can help you configure secure SSH keys which you can use to help secure
connections to GitLab repositories.
-- If you need information on creating SSH keys, start with our [options for SSH keys](#options-for-ssh-keys).
+- If you need information on creating SSH keys, start with our [options for SSH keys](#supported-ssh-key-types).
- If you have SSH keys dedicated for your GitLab account, you may be interested in [Working with non-default SSH key pair paths](#working-with-non-default-ssh-key-pair-paths).
-- If you already have an SSH key pair, you can go to how you can [add an SSH key to your GitLab account](#adding-an-ssh-key-to-your-gitlab-account).
+- If you already have an SSH key pair, you can go to how you can [add an SSH key to your GitLab account](#add-an-ssh-key-to-your-gitlab-account).
-## Requirements
+## Prerequisites
-To support SSH, GitLab requires the installation of the OpenSSH client, which
-comes pre-installed on GNU/Linux and macOS, as well as on Windows 10.
+To use SSH to communicate with GitLab, you need:
-Make sure that your system includes SSH version 6.5 or newer, as that excludes
-the now insecure MD5 signature scheme. The following command returns the version of
-SSH installed on your system:
+- The OpenSSH client, which comes pre-installed on GNU/Linux, macOS, and Windows 10.
+- SSH version 6.5 or later. Earlier versions used an MD5 signature, which is not secure.
-```shell
-ssh -V
-```
-
-While GitLab does [not support installation on Microsoft Windows](../install/requirements.md#microsoft-windows),
-you can set up SSH keys to set up Windows [as a client](#options-for-microsoft-windows).
-
-## Options for SSH keys
-
-GitLab supports the use of RSA, DSA, ECDSA, and ED25519 keys.
-
-- GitLab has [deprecated](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) DSA keys in GitLab 11.0.
-- 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.
-
-NOTE:
-Available documentation suggests that ED25519 is more secure. If you use an RSA key, the US National Institute of Science and Technology in [Publication 800-57 Part 3 (PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf) recommends a key size of at least 2048 bits.
-
-Therefore, our documentation focuses on the use of ED25519 and RSA keys.
-
-Administrators can [restrict which keys should be permitted and their minimum lengths](../security/ssh_keys_restrictions.md).
-
-## Review existing SSH keys
-
-If you have existing SSH keys, you may be able to use them to help secure connections with GitLab
-repositories. By default, SSH keys on Linux and macOS systems are stored in the user's home directory,
-in the `.ssh/` subdirectory. The following table includes default filenames for each SSH key algorithm:
+To view the version of SSH installed on your system, run `ssh -V`.
-| Algorithm | Public key | Private key |
-| --------- | ---------- | ----------- |
-| ED25519 (preferred) | `id_ed25519.pub` | `id_ed25519` |
-| 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` |
+GitLab does [not support installation on Microsoft Windows](../install/requirements.md#microsoft-windows),
+but you can set up SSH keys on the Windows [client](#options-for-microsoft-windows).
-For recommendations, see [options for SSH keys](#options-for-ssh-keys).
+## Supported SSH key types
-## Generating a new SSH key pair
+To communicate with GitLab, you can use the following SSH key types:
-If you want to create:
+- [ED25519](#ed25519-ssh-keys)
+- [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.)
-- An ED25519 key, read [ED25519 SSH keys](#ed25519-ssh-keys).
-- An RSA key, read [RSA SSH keys](#rsa-ssh-keys).
+Administrators can [restrict which keys are permitted and their minimum lengths](../security/ssh_keys_restrictions.md).
### ED25519 SSH keys
The book [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-chapter-5-digital-signatures)
suggests that [ED25519](https://ed25519.cr.yp.to/) keys are more secure and performant than RSA keys.
-As OpenSSH 6.5 introduced ED25519 SSH keys in 2014, they should be available on any current
-operating system.
+OpenSSH 6.5 introduced ED25519 SSH keys in 2014 and they should be available on most
+operating systems.
-You can create and configure an ED25519 key with the following command:
+### RSA SSH keys
-```shell
-ssh-keygen -t ed25519 -C "<comment>"
-```
+Available documentation suggests that ED25519 is more secure than RSA.
-The `-C` flag, with a quoted comment such as an email address, is an optional way to label your SSH keys.
+If you use an RSA key, the US National Institute of Science and Technology in
+[Publication 800-57 Part 3 (PDF)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf)
+recommends a key size of at least 2048 bits. The default key size depends on your version of `ssh-keygen`.
+Review the `man` page for your installed `ssh-keygen` command for details.
-You'll see a response similar to:
+## See if you have an existing SSH key pair
-```plaintext
-Generating public/private ed25519 key pair.
-Enter file in which to save the key (/home/user/.ssh/id_ed25519):
-```
+Before you create a key pair, see if a key pair already exists.
-For guidance, proceed to the [common steps](#common-steps-for-generating-an-ssh-key-pair).
+1. On Linux or macOS, go to your home directory.
+1. Go to the `.ssh/` subdirectory.
+1. See if a file with one of the following formats exists:
-### RSA SSH keys
+ | Algorithm | Public key | Private key |
+ | --------- | ---------- | ----------- |
+ | ED25519 (preferred) | `id_ed25519.pub` | `id_ed25519` |
+ | 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` |
-If you use RSA keys for SSH, the US National Institute of Standards and Technology recommends
-that you use a key size of [at least 2048 bits](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57Pt3r1.pdf).
-By default, the `ssh-keygen` command creates an 1024-bit RSA key.
+## Generate an SSH key pair
-You can create and configure an RSA key with the following command, substituting if desired for the minimum recommended key size of `2048`:
+If you do not have an existing SSH key pair, generate a new one.
-```shell
-ssh-keygen -t rsa -b 2048 -C "email@example.com"
-```
+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:
-The `-C` flag, with a quoted comment such as an email address, is an optional way to label your SSH keys.
+ ```shell
+ ssh-keygen -t ed25519 -C "<comment>"
+ ```
-You'll see a response similar to:
+ For 2048-bit RSA:
-```plaintext
-Generating public/private rsa key pair.
-Enter file in which to save the key (/home/user/.ssh/id_rsa):
-```
+ ```shell
+ ssh-keygen -t rsa -b 2048 -C "<comment>"
+ ```
-For guidance, proceed to the [common steps](#common-steps-for-generating-an-ssh-key-pair).
+1. Press Enter. Output similar to the following is displayed:
-NOTE:
-If you have OpenSSH version 7.8 or below, consider the problems associated
-with [encoding](#rsa-keys-and-openssh-from-versions-65-to-78).
+ ```plaintext
+ Generating public/private ed25519 key pair.
+ Enter file in which to save the key (/home/user/.ssh/id_ed25519):
+ ```
-### Common steps for generating an SSH key pair
+1. Accept the suggested filename and directory, unless you are generating a [deploy key](#deploy-keys)
+ or want to save in a specific directory where you store other keys.
-Whether you're creating a [ED25519](#ed25519-ssh-keys) or an [RSA](#rsa-ssh-keys) key, you've started with the `ssh-keygen` command.
-At this point, you'll see the following message in the command line (for ED25519 keys):
+ You can also dedicate the SSH key pair to a [specific host](#working-with-non-default-ssh-key-pair-paths).
-```plaintext
-Generating public/private ed25519 key pair.
-Enter file in which to save the key (/home/user/.ssh/id_ed25519):
-```
+1. Specify a [passphrase](https://www.ssh.com/ssh/passphrase/):
-If you don't already have an SSH key pair and are not generating a [deploy key](#deploy-keys),
-accept the suggested file and directory. Your SSH client uses
-the resulting SSH key pair with no additional configuration.
+ ```plaintext
+ Enter passphrase (empty for no passphrase):
+ Enter same passphrase again:
+ ```
-Alternatively, you can save the new SSH key pair in a different location.
-You can assign the directory and filename of your choice.
-You can also dedicate that SSH key pair to a [specific host](#working-with-non-default-ssh-key-pair-paths).
+1. A confirmation is displayed, including information about where your files are stored.
-After assigning a file to save your SSH key, you can set up
-a [passphrase](https://www.ssh.com/ssh/passphrase/) for your SSH key:
+A public and private key are generated.
+[Add the public SSH key to your GitLab account](#add-an-ssh-key-to-your-gitlab-account) and keep
+the private key secure.
-```plaintext
-Enter passphrase (empty for no passphrase):
-Enter same passphrase again:
-```
+### Update your SSH key passphrase
-If successful, you'll see confirmation of where the `ssh-keygen` command
-saved your identification and private key.
+You can update the passphrase for your SSH key.
-When needed, you can update the passphrase with the following command:
+1. Open a terminal and type this command:
-```shell
-ssh-keygen -p -f /path/to/ssh_key
-```
+ ```shell
+ ssh-keygen -p -f /path/to/ssh_key
+ ```
-### RSA keys and OpenSSH from versions 6.5 to 7.8
+1. At the prompts, type the passphrase and press Enter.
-Before OpenSSH 7.8, the default public key fingerprint for RSA keys was based on MD5,
-and is therefore insecure.
+### Upgrade your RSA key pair to a more secure format
-If your version of OpenSSH lies between version 6.5 to version 7.8 (inclusive),
-run `ssh-keygen` with the `-o` option to save your private SSH keys in the more secure
+If your version of OpenSSH is between 6.5 and 7.8,
+you can save your private RSA SSH keys in a more secure
OpenSSH format.
-If you already have an RSA SSH key pair to use with GitLab, consider upgrading it
-to use the more secure password encryption format. You can do so with the following command:
-
-```shell
-ssh-keygen -o -f ~/.ssh/id_rsa
-```
+1. Open a terminal and type this command:
-Alternatively, you can generate a new RSA key with the more secure encryption format with
-the following command:
+ ```shell
+ ssh-keygen -o -f ~/.ssh/id_rsa
+ ```
-```shell
-ssh-keygen -o -t rsa -b 4096 -C "email@example.com"
-```
+ Alternatively, you can generate a new RSA key with the more secure encryption format with
+ the following command:
-NOTE:
-As noted in the `ssh-keygen` man page, ED25519 already encrypts keys to the more secure
-OpenSSH format.
+ ```shell
+ ssh-keygen -o -t rsa -b 4096 -C "<comment>"
+ ```
-## Adding an SSH key to your GitLab account
+## Add an SSH key to your GitLab account
-Now you can copy the SSH key you created to your GitLab account. To do so, follow these steps:
+Now you can copy the SSH key you created to your GitLab account.
1. Copy your **public** SSH key to a location that saves information in text format.
The following options saves information for ED25519 keys to the clipboard
@@ -201,7 +167,7 @@ Now you can copy the SSH key you created to your GitLab account. To do so, follo
pbcopy < ~/.ssh/id_ed25519.pub
```
- **Linux (requires the xclip package):**
+ **Linux (requires the `xclip` package):**
```shell
xclip -sel clip < ~/.ssh/id_ed25519.pub
@@ -216,8 +182,9 @@ Now you can copy the SSH key you created to your GitLab account. To do so, follo
If you're using an RSA key, substitute accordingly.
1. Navigate to `https://gitlab.com` or your local GitLab instance URL and sign in.
-1. Select your avatar in the upper right corner, and click **Settings**
-1. Click **SSH Keys**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **SSH Keys**.
1. Paste the public key that you copied into the **Key** text box.
1. Make sure your key includes a descriptive name in the **Title** text box, such as _Work Laptop_ or
_Home Workstation_.
@@ -379,7 +346,7 @@ git remote set-url origin git@<user_1.gitlab.com>:gitlab-org/gitlab.git
## Deploy keys
-Read the [documentation on Deploy Keys](../user/project/deploy_keys/index.md).
+Read the [documentation on deploy keys](../user/project/deploy_keys/index.md).
## Applications
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
new file mode 100644
index 00000000000..8b223953007
--- /dev/null
+++ b/doc/subscriptions/bronze_starter.md
@@ -0,0 +1,139 @@
+---
+stage: Fulfillment
+group: Purchase
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Features available to Starter and Bronze subscribers
+
+Although GitLab has discontinued selling the Bronze and Starter tiers, GitLab
+continues to honor the entitlements of existing Bronze and Starter tier GitLab
+customers for the duration of their contracts at that level.
+
+These features remain available to Bronze and Starter customers, even though
+the tiers are no longer mentioned in GitLab documentation:
+
+- [Activate GitLab EE with a license](../user/admin_area/license.md)
+- [Adding a help message to the login page](../user/admin_area/settings/help_page.md#adding-a-help-message-to-the-login-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)
+- [Code owners](../user/project/code_owners.md)
+- Description templates:
+ - [Setting a default template for merge requests and issues](../user/project/description_templates.md#setting-a-default-template-for-merge-requests-and-issues)
+- [Email from GitLab](../tools/email.md)
+- Groups:
+ - [Creating group memberships via CN](../user/group/index.md#creating-group-links-via-cn)
+ - [Group push rules](../user/group/index.md#group-push-rules)
+ - [Managing group memberships via LDAP](../user/group/index.md#manage-group-memberships-via-ldap)
+ - [Member locking](../user/group/index.md#member-lock)
+ - [Overriding user permissions](../user/group/index.md#overriding-user-permissions)
+ - [User contribution analysis](../user/group/index.md#user-contribution-analysis)
+ - [Kerberos integration](../integration/kerberos.md)
+- Issue Boards:
+ - [Configurable issue boards](../user/project/issue_board.md#configurable-issue-boards)
+ - [Sum of issue weights](../user/project/issue_board.md#sum-of-issue-weights)
+ - [Work In Progress limits](../user/project/issue_board.md#work-in-progress-limits)
+- Issues:
+ - [Multiple assignees for issues](../user/project/issues/multiple_assignees_for_issues.md)
+ - [Issue weights](../user/project/issues/issue_weight.md)
+ - [Issue histories](../user/project/issues/issue_data_and_actions.md#issue-history) contain changes to issue description
+ - [Adding an issue to an iteration](../user/project/issues/managing_issues.md#add-an-issue-to-an-iteration)
+- [Iterations](../user/group/iterations/index.md)
+- [Kerberos integration](../integration/kerberos.md)
+- LDAP:
+ - Querying LDAP [from the Rails console](../administration/auth/ldap/ldap-troubleshooting.md#query-ldap), or
+ [querying a single group](../administration/auth/ldap/ldap-troubleshooting.md#query-a-group-in-ldap)
+ - [Sync all users](../administration/auth/ldap/ldap-troubleshooting.md#sync-all-users)
+ - [Group management through LDAP](../administration/auth/ldap/ldap-troubleshooting.md#group-memberships)
+ - Syncing information through LDAP:
+ - Groups: [one group](../administration/auth/ldap/ldap-troubleshooting.md#sync-one-group),
+ [all groups programmatically](../administration/auth/ldap/index.md#group-sync),
+ [group sync schedule](../administration/auth/ldap/index.md#adjusting-ldap-group-sync-schedule), and
+ [all groups manually](../administration/auth/ldap/ldap-troubleshooting.md#sync-all-groups)
+ - [Configuration settings](../administration/auth/ldap/index.md#ldap-sync-configuration-settings)
+ - Users: [all users](../administration/auth/ldap/index.md#user-sync),
+ [administrators](../administration/auth/ldap/index.md#administrator-sync),
+ [user sync schedule](../administration/auth/ldap/index.md#adjusting-ldap-user-sync-schedule)
+ - [Adding group links](../administration/auth/ldap/index.md#adding-group-links)
+ - [Lock memberships to LDAP synchronization](../administration/auth/ldap/index.md#global-group-memberships-lock)
+ - Rake tasks for [LDAP tasks](../administration/raketasks/ldap.md), including
+ [syncing groups](../administration/raketasks/ldap.md#run-a-group-sync)
+- Logging:
+ - [`audit_json.log`](../administration/logs.md#audit_jsonlog) (specific entries)
+ - [`elasticsearch.log`](../administration/logs.md#elasticsearchlog)
+- Merge requests:
+ - [Full code quality reports in the code quality tab](../user/project/merge_requests/code_quality.md#code-quality-reports)
+ - [Merge request approvals](../user/project/merge_requests/merge_request_approvals.md)
+ - [Multiple assignees](../user/project/merge_requests/getting_started.md#multiple-assignees)
+ - [Approval Rule information for Reviewers](../user/project/merge_requests/getting_started.md#approval-rule-information-for-reviewers) **(PREMIUM)**
+ - [Required Approvals](../user/project/merge_requests/merge_request_approvals.md#required-approvals)
+ - [Code Owners as eligible approvers](../user/project/merge_requests/merge_request_approvals.md#code-owners-as-eligible-approvers)
+ - All [Approval rules](../user/project/merge_requests/merge_request_approvals.md#approval-rules) features
+ - [Restricting push and merge access to certain users](../user/project/protected_branches.md#restricting-push-and-merge-access-to-certain-users)
+ - [Visual Reviews](../ci/review_apps/index.md#visual-reviews)
+- Metrics and analytics:
+ - [Contribution Analytics](../user/group/contribution_analytics/index.md)
+ - [Merge Request Analytics](../user/analytics/merge_request_analytics.md)
+ - [Code Review Analytics](../user/analytics/code_review_analytics.md)
+ - [Audit Events](../administration/audit_events.md), including
+ [Group events](../administration/audit_events.md#group-events) and
+ [Project events](../administration/audit_events.md#project-events)
+- Rake tasks:
+ - [Displaying GitLab license information](../administration/raketasks/maintenance.md#show-gitlab-license-information)
+- Reference Architecture information:
+ - [Traffic load balancers](../administration/reference_architectures/index.md#traffic-load-balancer)
+ - [Zero downtime updates](../administration/reference_architectures/index.md#zero-downtime-updates)
+- Repositories:
+ - [Repository size limit](../user/admin_area/settings/account_and_limit_settings.md#repository-size-limit)
+ - Repository mirroring:
+ - [Pull mirroring](../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository) outside repositories in a GitLab repository
+ - [Overwrite diverged branches](../user/project/repository/repository_mirroring.md#overwrite-diverged-branches)
+ - [Trigger pipelines for mirror updates](../user/project/repository/repository_mirroring.md#trigger-pipelines-for-mirror-updates)
+ - [Hard failures](../user/project/repository/repository_mirroring.md#hard-failure) when mirroring fails
+ - [Trigger pull mirroring from the API](../user/project/repository/repository_mirroring.md#trigger-an-update-using-the-api)
+ - [Mirror only protected branches](../user/project/repository/repository_mirroring.md#mirror-only-protected-branches)
+ - [Bidirectional mirroring](../user/project/repository/repository_mirroring.md#bidirectional-mirroring)
+ - [Mirroring with Perforce Helix via Git Fusion](../user/project/repository/repository_mirroring.md#mirroring-with-perforce-helix-via-git-fusion)
+- Runners:
+ - Run pipelines in the parent project [for merge requests from a forked project](../ci/merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project)
+ - [Shared runners pipeline minutes quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+- [Push rules](../push_rules/push_rules.md)
+- SAML for self-managed GitLab instance:
+ - [Administrator groups](../integration/saml.md#admin-groups)
+ - [Auditor groups](../integration/saml.md#auditor-groups)
+ - [External groups](../integration/saml.md#external-groups)
+ - [Required groups](../integration/saml.md#required-groups)
+- Search:
+ - [Filtering merge requests by approvers](../user/search/index.md#filtering-merge-requests-by-approvers)
+ - [Filtering merge requests by "approved by"](../user/search/index.md#filtering-merge-requests-by-approved-by)
+ - [Advanced Global Search (Elasticsearch)](../user/search/advanced_global_search.md)
+ - [Advanced Search Syntax](../user/search/advanced_search_syntax.md)
+- [Service Desk](../user/project/service_desk.md)
+- [Storage usage statistics](../user/usage_quotas.md#storage-usage-statistics)
+
+The following developer features continue to be available to Starter and
+Bronze-level subscribers:
+
+- APIs:
+ - LDAP synchronization:
+ - Certain fields in the [group details API](../api/groups.md#details-of-a-group)
+ - [syncing groups](../api/groups.md#sync-group-with-ldap)
+ - Listing, adding, and deleting [group links](../api/groups.md#list-ldap-group-links)
+ - [Push rules](../api/groups.md#push-rules)
+ - [Audit events](../api/audit_events.md), including
+ [group audit events](../api/groups.md#group-audit-events) and
+ [project audit events](../api/audit_events.md#project-audit-events)
+ - Projects API: certain fields in the [Create project API](../api/projects.md)
+ - [Resource iteration events API](../api/resource_iteration_events.md)
+ - Group milestones API: [Get all burndown chart events for a single milestone](../api/group_milestones.md#get-all-burndown-chart-events-for-a-single-milestone)
+ - [Group iterations API](../api/group_iterations.md)
+ - Project milestones API: [Get all burndown chart events for a single milestone](../api/milestones.md#get-all-burndown-chart-events-for-a-single-milestone)
+ - [Project iterations API](../api/iterations.md)
+ - Fields in the [Search API](../api/search.md) available only to [Advanced Global Search (Elasticsearch)](../integration/elasticsearch.md) users
+ - Fields in the [Merge requests API](../api/merge_requests.md) for [merge request approvals](../user/project/merge_requests/merge_request_approvals.md)
+ - Fields in the [Protected branches API](../api/protected_branches.md) that specify users or groups allowed to merge
+ - [Merge request approvals API](../api/merge_request_approvals.md)
+ - [Visual review discussions API](../api/visual_review_discussions.md)
+- Development information:
+ - [Run Jenkins in a macOS development environment](../development/integrations/jenkins.md)
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index aef1c1127c5..b7a1243be72 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -5,115 +5,83 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# GitLab.com subscription **(BRONZE ONLY)**
+# GitLab SaaS subscription **(PREMIUM SAAS)**
-GitLab.com is GitLab Inc.'s software-as-a-service offering. You don't need to
-install anything to use GitLab.com, you only need to
+GitLab SaaS is GitLab Inc.'s software-as-a-service offering. You don't need to
+install anything to use GitLab SaaS, you only need to
[sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away.
-This page reviews the details of your GitLab.com subscription.
+This page reviews the details of your GitLab SaaS subscription.
-## Choose a GitLab.com group or personal subscription
-
-On GitLab.com you can apply a subscription to either a group or a personal namespace.
-
-When applied to:
-
-- A **group**, the group, all subgroups, and all projects under the selected
- group on GitLab.com contains the features of the associated tier. GitLab recommends
- choosing a group plan when managing an organization's projects and users.
-- A **personal userspace**, all projects contain features with the
- subscription applied, but as it's not a group, group features aren't available.
-
-You can read more about [common misconceptions](https://about.gitlab.com/handbook/marketing/strategic-marketing/enablement/dotcom-subscriptions/#common-misconceptions) regarding a GitLab.com subscription to help avoid issues.
-
-## Choose a GitLab.com tier
+## Choose a GitLab SaaS tier
Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
the features which fit your budget. For information on what features are available
at each tier, see the
-[GitLab.com feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/).
+[GitLab SaaS feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/).
## Choose the number of users
NOTE:
Applied only to groups.
-A GitLab.com subscription uses a concurrent (_seat_) model. You pay for a
+A GitLab SaaS subscription uses a concurrent (_seat_) model. You pay for a
subscription according to the maximum number of users enabled at once. You can
add and remove users during the subscription period, as long as the total users
at any given time doesn't exceed the subscription count.
Every occupied seat is counted in the subscription, with the following exception:
-- Members with Guest permissions on a Gold subscription.
+- Members with Guest permissions on an Ultimate subscription.
NOTE:
To support the open source community and encourage the development of open
-source projects, GitLab grants access to **Gold** features for all GitLab.com
+source projects, GitLab grants access to **Ultimate** features for all GitLab SaaS
**public** projects, regardless of the subscription.
-## Obtain a GitLab.com subscription
-
-To subscribe to GitLab.com:
-
-- **For individuals**:
- 1. Create a user account for yourself using our
- [sign up page](https://gitlab.com/users/sign_up).
- 1. Visit the [billing page](https://gitlab.com/profile/billings)
- under your profile.
- 1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the
- [Customers Portal](https://customers.gitlab.com/).
- 1. Link your GitLab.com account with your Customers Portal account.
- Once a plan has been selected, if your account is not
- already linked, GitLab prompts you to link your account with a
- **Sign in to GitLab.com** button.
- 1. Select the namespace from the drop-down list to associate the subscription.
- 1. Proceed to checkout.
-- **For groups**:
- 1. Create a user account for yourself using our
- [sign up page](https://gitlab.com/users/sign_up).
- 1. Create a [group](../../user/group/index.md). GitLab groups help assemble related
- projects together allowing you to grant members access to several projects
- at once. A group is not required if you plan on having projects inside a personal
- namespace.
- 1. Create additional users and
- [add them to the group](../../user/group/index.md#add-users-to-a-group).
- 1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the
- [Customers Portal](https://customers.gitlab.com/).
- 1. Link your GitLab.com account with your Customers Portal account.
- Once a plan has been selected, if your account is not
- already linked, GitLab prompts you to link your account with a
- **Sign in to GitLab.com** button.
- 1. Select the namespace from the drop-down list to associate the subscription.
- 1. Proceed to checkout.
+## Obtain a GitLab SaaS subscription
+
+To subscribe to GitLab SaaS:
+
+1. Create a user account for yourself using our
+ [sign up page](https://gitlab.com/users/sign_up).
+1. Create a [group](../../user/group/index.md). GitLab groups help assemble related
+ projects together allowing you to grant members access to several projects
+ at once. A group is not required if you plan on having projects inside a personal
+ namespace.
+1. Create additional users and
+ [add them to the group](../../user/group/index.md#add-users-to-a-group).
+1. Select the GitLab SaaS plan through the
+ [Customers Portal](https://customers.gitlab.com/).
+1. Link your GitLab SaaS account with your Customers Portal account.
+ Once a plan has been selected, if your account is not
+ already linked, GitLab prompts you to link your account with a
+ **Sign in to GitLab.com** button.
+1. Select the namespace from the drop-down list to associate the subscription.
+1. Proceed to checkout.
NOTE:
You can also go to the [**My Account**](https://customers.gitlab.com/customers/edit)
-page to add or change the GitLab.com account link.
-
-## View your GitLab.com subscription
+page to add or change the GitLab SaaS account link.
-To see the status of your GitLab.com subscription, log in to GitLab.com and go
-to the **Billing** section of the relevant namespace:
+## View your GitLab SaaS subscription
-- **For individuals**: Visit the [billing page](https://gitlab.com/profile/billings)
- under your profile.
-- **For groups**: From the group page (*not* from a project in the group), go to **Settings > Billing**.
+To see the status of your GitLab SaaS subscription, log in to GitLab SaaS and go
+to the **Billing** section:
- NOTE:
- You must have Owner level [permissions](../../user/permissions.md) to view a group's billing page.
+NOTE:
+You must have Owner level [permissions](../../user/permissions.md) to view the billing page.
- The following table describes details of your subscription for groups:
+The following table describes details of your subscription:
- | Field | Description |
- |-----------------------------|-------------|
- | **Seats in subscription** | If this is a paid plan, represents the number of seats you've bought for this group. |
- | **Seats currently in use** | Number of seats in use. Select **See usage** to see a list of the users using these seats. For more details, see [Seat usage](#seat-usage). |
- | **Max seats used** | Highest number of seats you've used. |
- | **Seats owed** | _Seats owed_ = _Max seats used_ - _Seats in subscription_. |
- | **Subscription start date** | Date your subscription started. If this is for a Free plan, it's the date you transitioned off your group's paid plan. |
- | **Subscription end date** | Date your current subscription ends. Does not apply to Free plans. |
+| Field | Description |
+|:----------------------------|:------------|
+| **Seats in subscription** | If this is a paid plan, represents the number of seats you've bought for this group. |
+| **Seats currently in use** | Number of seats in use. Select **See usage** to see a list of the users using these seats. For more details, see [Seat usage](#seat-usage). |
+| **Max seats used** | Highest number of seats you've used. |
+| **Seats owed** | _Seats owed_ = _Max seats used_ - _Seats in subscription_. |
+| **Subscription start date** | Date your subscription started. If this is for a Free plan, it's the date you transitioned off your group's paid plan. |
+| **Subscription end date** | Date your current subscription ends. Does not apply to Free plans. |
## Seat usage
@@ -125,7 +93,7 @@ The **Seat usage** page lists all users occupying seats. Details for each user i
- Full name
- Username
-- Public email address (if they have provided one in their [profile settings](../../user/profile/index.md#profile-settings))
+- Public email address (if they have provided one in their [user settings](../../user/profile/index.md#user-settings))
The Seat usage listing is updated live, but the usage statistics on the billing page are updated
only once per day. For this reason there can be a minor difference between the seat usage listing
@@ -147,12 +115,12 @@ For example:
| Amir | `ami` | Yes |
| Amir | `amr` | No |
-## Renew your GitLab.com subscription
+## Renew your GitLab SaaS subscription
To renew your subscription:
-1. [Prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account)
-1. [Renew your GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription)
+1. [Prepare for renewal by reviewing your account.](#prepare-for-renewal-by-reviewing-your-account)
+1. [Renew your GitLab SaaS subscription.](#renew-or-change-a-gitlab-saas-subscription)
### Prepare for renewal by reviewing your account
@@ -180,21 +148,21 @@ It's important to regularly review your user accounts, because:
A GitLab subscription is valid for a specific number of users. For details, see
[Choose the number of users](#choose-the-number-of-users).
-If the number of [billable users](#view-your-gitlabcom-subscription) exceeds the number included in the subscription, known
+If the number of [billable users](#view-your-gitlab-saas-subscription) exceeds the number included in the subscription, known
as the number of _users over license_, you must pay for the excess number of
users either before renewal, or at the time of renewal. This is also known the
_true up_ process.
-### Renew or change a GitLab.com subscription
+### Renew or change a GitLab SaaS subscription
-You can adjust the number of users before renewing your GitLab.com subscription.
+You can adjust the number of users before renewing your GitLab SaaS subscription.
-- To renew for more users than are currently included in your GitLab.com plan, [add users to your subscription](#add-users-to-your-subscription).
-- To renew for fewer users than are currently included in your GitLab.com plan,
+- To renew for more users than are currently included in your GitLab SaaS plan, [add users to your subscription](#add-users-to-your-subscription).
+- To renew for fewer users than are currently included in your GitLab SaaS plan,
either [disable](../../user/admin_area/activating_deactivating_users.md#deactivating-a-user) or [block](../../user/admin_area/blocking_unblocking_users.md#blocking-a-user) the user accounts you no longer need.
For details on upgrading your subscription tier, see
-[Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier).
+[Upgrade your GitLab SaaS subscription tier](#upgrade-your-gitlab-saas-subscription-tier).
#### Automatic renewal
@@ -235,7 +203,7 @@ The following is emailed to you:
- A payment receipt. You can also access this information in the Customers Portal under
[**View invoices**](https://customers.gitlab.com/receipts).
-## Upgrade your GitLab.com subscription tier
+## Upgrade your GitLab SaaS subscription tier
To upgrade your [GitLab tier](https://about.gitlab.com/pricing/):
@@ -266,13 +234,12 @@ If you renew or upgrade, your data is accessible again.
CI pipeline minutes are the execution time for your
[pipelines](../../ci/pipelines/index.md) on GitLab shared runners. Each
-[GitLab.com tier](https://about.gitlab.com/pricing/) includes a monthly quota
+[GitLab SaaS tier](https://about.gitlab.com/pricing/) includes a monthly quota
of CI pipeline minutes:
- Free: 400 minutes
-- Bronze: 2,000 minutes
-- Silver: 10,000 minutes
-- Gold: 50,000 minutes
+- Premium: 10,000 minutes
+- Ultimate: 50,000 minutes
Quotas apply to:
@@ -280,22 +247,25 @@ Quotas apply to:
subgroups, and nested projects. To view the group's usage, navigate to the group,
then **Settings > Usage Quotas**.
- Your personal account, where the minutes are available for your personal projects.
- To view and buy personal minutes, click your avatar, then
- **Settings > [Usage Quotas](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)**.
+ To view and buy personal minutes:
+
+ 1. In the top-right corner, select your avatar.
+ 1. Select **Edit profile**.
+ 1. In the left sidebar, select **[Usage Quotas](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)**.
Only pipeline minutes for GitLab shared runners are restricted. If you have a
-specific runner set up for your projects, there is no limit to your build time on GitLab.com.
+specific runner set up for your projects, there is no limit to your build time on GitLab SaaS.
The available quota is reset on the first of each calendar month at midnight UTC.
When the CI minutes are depleted, an email is sent automatically to notify the owner(s)
of the namespace. You can [purchase additional CI minutes](#purchase-additional-ci-minutes),
-or upgrade your account to [Silver or Gold](https://about.gitlab.com/pricing/).
+or upgrade your account to a higher [plan](https://about.gitlab.com/pricing/).
Your own runners can still be used even if you reach your limits.
### Purchase additional CI minutes
-If you're using GitLab.com, you can purchase additional CI minutes so your
+If you're using GitLab SaaS, you can purchase additional CI minutes so your
pipelines aren't blocked after you have used all your CI minutes from your
main quota. You can find pricing for additional CI/CD minutes in the
[GitLab Customers Portal](https://customers.gitlab.com/plans). Additional minutes:
@@ -303,11 +273,11 @@ main quota. You can find pricing for additional CI/CD minutes in the
- Are only used after the shared quota included in your subscription runs out.
- Roll over month to month.
-To purchase additional minutes for your group on GitLab.com:
+To purchase additional minutes for your group on GitLab SaaS:
1. From your group, go to **Settings > Usage Quotas**.
1. Select **Buy additional minutes** and GitLab directs you to the Customers Portal.
-1. Locate the subscription card that's linked to your group on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction.
+1. Locate the subscription card that's linked to your group on GitLab SaaS, click **Buy more CI minutes**, and complete the details about the transaction.
1. Once we have processed your payment, the extra CI minutes are synced to your group namespace.
1. To confirm the available CI minutes, go to your group, then **Settings > Usage Quotas**.
@@ -315,10 +285,12 @@ To purchase additional minutes for your group on GitLab.com:
To purchase additional minutes for your personal namespace:
-1. Click your avatar, then go to **Settings > Usage Quotas**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Usage Quotas**.
1. Select **Buy additional minutes** and GitLab redirects you to the Customers Portal.
-1. Locate the subscription card that's linked to your personal namespace on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction. Once we have processed your payment, the extra CI minutes are synced to your personal namespace.
-1. To confirm the available CI minutes for your personal projects, click your avatar, then go to **Settings > Usage Quotas**.
+1. Locate the subscription card that's linked to your personal namespace on GitLab SaaS, click **Buy more CI minutes**, and complete the details about the transaction. Once we have processed your payment, the extra CI minutes are synced to your personal namespace.
+1. To confirm the available CI minutes for your personal projects, go to the **Usage Quotas** settings again.
The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
@@ -348,7 +320,7 @@ locked. Projects can only be unlocked by purchasing more storage subscription un
To purchase more storage for either a personal or group namespace:
-1. Sign in to GitLab.com.
+1. Sign in to GitLab SaaS.
1. From either your personal homepage or the group's page, go to **Settings > Usage Quotas**.
1. For each locked project, total by how much its **Usage** exceeds the free quota and purchased
storage. You must purchase the storage increment that exceeds this total.
@@ -361,7 +333,7 @@ To purchase more storage for either a personal or group namespace:
1. Select the **Privacy Policy** and **Terms of Service** checkbox.
1. Select **Buy subscription**.
1. Sign out of the Customers Portal.
-1. Switch back to the GitLab.com tab and refresh the page.
+1. Switch back to the GitLab SaaS tab and refresh the page.
The **Purchased storage available** total is incremented by the amount purchased. All locked
projects are unlocked and their excess usage is deducted from the additional storage.
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 383ba471df4..aff392f61ff 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# GitLab subscription **(STARTER)**
+# GitLab subscription **(PREMIUM)**
GitLab offers tiers of features. Your subscription determines which tier you
have access to. Subscriptions are valid for 12 months.
@@ -19,26 +19,26 @@ GitLab provides special subscriptions to participants in:
When choosing a subscription, there are two factors to consider:
-- [GitLab.com or self-managed](#choose-between-gitlabcom-or-self-managed)
+- [GitLab SaaS or GitLab self-managed](#choose-between-gitlab-saas-or-gitlab-self-managed)
- [GitLab tier](#choose-a-gitlab-tier)
-### Choose between GitLab.com or self-managed
+### Choose between GitLab SaaS or GitLab self-managed
There are some differences in how a subscription applies, depending if you use
-GitLab.com or a self-managed instance:
+GitLab SaaS or GitLab self-managed:
-- [GitLab.com](gitlab_com/index.md): The GitLab software-as-a-service offering.
- You don't need to install anything to use GitLab.com, you only need to
+- [GitLab SaaS](gitlab_com/index.md): The GitLab software-as-a-service offering.
+ You don't need to install anything to use GitLab SaaS, you only need to
[sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away.
- [GitLab self-managed](self_managed/index.md): Install, administer, and maintain
your own GitLab instance.
-On a self-managed instance, a GitLab subscription provides the same set of
-features for _all_ users. On GitLab.com, you can apply a subscription to either
+On a GitLab self-managed instance, a GitLab subscription provides the same set of
+features for _all_ users. On GitLab SaaS, you can apply a subscription to either
a group or a personal namespace.
NOTE:
-Subscriptions cannot be transferred between GitLab.com and GitLab self-managed.
+Subscriptions cannot be transferred between GitLab SaaS and GitLab self-managed.
A new subscription must be purchased and applied as needed.
### Choose a GitLab tier
@@ -47,8 +47,8 @@ Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choo
the features which fit your budget. For information on what features are available
at each tier for each product, see:
-- [GitLab.com feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)
-- [Self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/)
+- [GitLab SaaS feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)
+- [GitLab self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/)
## Find your subscription
@@ -76,7 +76,7 @@ With the [Customers Portal](https://customers.gitlab.com/) you can:
- [Change your company details](#change-your-company-details)
- [Change your payment method](#change-your-payment-method)
- [Change the linked account](#change-the-linked-account)
-- [Change the associated namespace](#change-the-associated-namespace)
+- [Change the namespace the subscription is linked to](#change-the-linked-namespace)
- [Change customers portal account password](#change-customers-portal-account-password)
### Change your personal details
@@ -130,27 +130,27 @@ method as the default:
### Change the linked account
-To change the GitLab.com account associated with your Customers Portal
-account:
+To change the GitLab.com account linked to your Customers Portal account:
1. Log in to the
[Customers Portal](https://customers.gitlab.com/customers/sign_in).
-1. In a separate browser tab, go to [GitLab.com](https://gitlab.com) and ensure you
+1. In a separate browser tab, go to [GitLab SaaS](https://gitlab.com) and ensure you
are not logged in.
1. On the Customers Portal page, click **My account > Account details**.
1. Under **Your GitLab.com account**, click **Change linked account**.
-1. Log in to the [GitLab.com](https://gitlab.com) account you want to link to the Customers Portal
+1. Log in to the [GitLab SaaS](https://gitlab.com) account you want to link to the Customers Portal
account.
-### Change the associated namespace
+### Change the linked namespace
-With a linked GitLab.com account:
+To change the namespace linked to a subscription:
-1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
+1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) with a
+ [linked](#change-the-linked-account) GitLab SaaS account.
1. Navigate to the **Manage Purchases** page.
-1. Click **Change linked namespace**.
+1. Select **Change linked namespace**.
1. Select the desired group from the **This subscription is for** dropdown.
-1. Click **Proceed to checkout**.
+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.
@@ -173,7 +173,7 @@ Find more information how to apply and renew at
## GitLab for Open Source subscriptions
-All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/join/)
+All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/)
requests, including subscription renewals, must be made by using the application process.
If you have any questions, send an email to `opensource@gitlab.com` for assistance.
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index a9c0337509a..dc98a9415d7 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# GitLab self-managed subscription **(STARTER ONLY)**
+# GitLab self-managed subscription **(PREMIUM SELF)**
You can install, administer, and maintain your own GitLab instance.
@@ -37,10 +37,10 @@ at each tier, see the
## Subscription seats
-A self-managed subscription uses a hybrid model. You pay for a subscription
+A GitLab self-managed subscription uses a hybrid model. You pay for a subscription
according to the maximum number of users enabled during the subscription period.
For instances that aren't offline or on a closed network, the maximum number of
-simultaneous users in the self-managed installation is checked each quarter,
+simultaneous users in the GitLab self-managed installation is checked each quarter,
using [Seat Link](#seat-link).
### Billable users
@@ -76,15 +76,14 @@ GitLab has several features which can help you manage the number of users:
## Obtain a subscription
-To subscribe to GitLab through a self-managed installation:
+To subscribe to GitLab through a GitLab self-managed installation:
-1. Go to the [Customers Portal](https://customers.gitlab.com/) and purchase a
- **Starter**, **Premium**, or **Ultimate** self-managed plan.
+1. Go to the [Customers Portal](https://customers.gitlab.com/) and purchase a GitLab self-managed plan.
1. After purchase, a license file is sent to the email address associated to the Customers Portal account,
which must be [uploaded to your GitLab instance](../../user/admin_area/license.md#uploading-your-license).
NOTE:
-If you're purchasing a subscription for an existing **Core** self-managed
+If you're purchasing a subscription for an existing **Free** GitLab self-managed
instance, ensure you're purchasing enough seats to
[cover your users](../../user/admin_area/index.md#administering-users).
@@ -114,7 +113,7 @@ It also displays the following important statistics:
To renew your subscription,
[prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account),
-then [renew your self-managed subscription](#renew-a-subscription).
+then [renew your GitLab self-managed subscription](#renew-a-subscription).
### Prepare for renewal by reviewing your account
@@ -203,9 +202,9 @@ An invoice is generated for the renewal and available for viewing or download on
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9.
-Seat Link allows GitLab Inc. to provide our self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process.
+Seat Link allows GitLab Inc. to provide our GitLab self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process.
-Seat Link daily sends a count of all users in connected self-managed instances to GitLab. That information is used to automate prorated reconciliations. The data is sent securely through an encrypted HTTPS connection to `customers.gitlab.com` on port `443`.
+Seat Link daily sends a count of all users in connected GitLab self-managed instances to GitLab. That information is used to automate prorated reconciliations. The data is sent securely through an encrypted HTTPS connection to `customers.gitlab.com` on port `443`.
Seat Link provides **only** the following information to GitLab:
@@ -325,11 +324,11 @@ behave as expected if you're not prepared for the expiry. For example,
[environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab/-/issues/24759).
If you renew or upgrade, your data is again accessible.
-For self-managed customers, there is a 14-day grace period when your features
+For GitLab self-managed customers, there is a 14-day grace period when your features
continue to work as-is, after which the entire instance becomes read
only.
-However, if you remove the license, you immediately revert to Core
+However, if you remove the license, you immediately revert to Free
features, and the instance become read / write again.
## Contact Support
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index 7e4d274f21b..ea588fb32a5 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -48,6 +48,17 @@ NOTE:
We follow the same structure and deprecations as [Webhooks](../user/project/integrations/webhooks.md)
for Push and Tag events, but we never display commits.
+## Create a system hook
+
+To create a system hook:
+
+1. In the top navigation bar, go to **{admin}** **Admin Area**.
+1. In the left sidebar, select **System Hooks**.
+1. Provide the **URL** and **Secret Token**.
+1. Select the check box next to each **Trigger** you want to enable.
+1. Select **Enable SSL verification**, if desired.
+1. Click **Add system hook**.
+
## Hooks request example
**Request header**:
@@ -300,15 +311,11 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`.
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "group_create",
"name": "StoreCloud",
- "owner_email": null,
- "owner_name": null,
"path": "storecloud",
"group_id": 78
}
```
-`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab/-/issues/20011>.
-
**Group removed:**
```json
@@ -317,15 +324,11 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`.
"updated_at": "2012-07-21T07:38:22Z",
"event_name": "group_destroy",
"name": "StoreCloud",
- "owner_email": null,
- "owner_name": null,
"path": "storecloud",
"group_id": 78
}
```
-`owner_name` and `owner_email` are always `null`. Please see [issue #20011](https://gitlab.com/gitlab-org/gitlab/-/issues/20011).
-
**Group renamed:**
```json
@@ -337,15 +340,11 @@ If the user is blocked via LDAP, `state` is `ldap_blocked`.
"path": "better-name",
"full_path": "parent-group/better-name",
"group_id": 64,
- "owner_name": null,
- "owner_email": null,
"old_path": "old-name",
"old_full_path": "parent-group/old-name"
}
```
-`owner_name` and `owner_email` are always `null`. Please see <https://gitlab.com/gitlab-org/gitlab/-/issues/20011>.
-
**New Group Member:**
```json
diff --git a/doc/telemetry/index.md b/doc/telemetry/index.md
deleted file mode 100644
index b3b3b0b4fdd..00000000000
--- a/doc/telemetry/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/telemetry/snowplow.md b/doc/telemetry/snowplow.md
deleted file mode 100644
index 709c61b9e64..00000000000
--- a/doc/telemetry/snowplow.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../development/snowplow.md'
----
-
-This document was moved to [another location](../development/snowplow.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/topics/airgap/index.md b/doc/topics/airgap/index.md
deleted file mode 100644
index 3866ec50253..00000000000
--- a/doc/topics/airgap/index.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-redirect_to: '../offline/index.md'
----
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 0e51042193c..1988e3e2890 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -33,8 +33,8 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Atlassian Crowd OmniAuth Provider](../../administration/auth/crowd.md)
- [CAS OmniAuth Provider](../../integration/cas.md)
- [SAML OmniAuth Provider](../../integration/saml.md)
- - [SAML for GitLab.com Groups](../../user/group/saml_sso/index.md) **(SILVER ONLY)**
- - [SCIM user provisioning for GitLab.com Groups](../../user/group/saml_sso/scim_setup.md) **(SILVER ONLY)**
+ - [SAML for GitLab.com Groups](../../user/group/saml_sso/index.md) **(PREMIUM SAAS)**
+ - [SCIM user provisioning for GitLab.com Groups](../../user/group/saml_sso/scim_setup.md) **(PREMIUM SAAS)**
- [Okta SSO provider](../../administration/auth/okta.md)
- [Kerberos integration (GitLab EE)](../../integration/kerberos.md) **(STARTER)**
@@ -42,12 +42,16 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [OAuth 2 Tokens](../../api/README.md#oauth2-tokens)
- [Personal access tokens](../../api/README.md#personalproject-access-tokens)
-- [Project access tokens](../../api/README.md#personalproject-access-tokens) **(CORE ONLY)**
+- [Project access tokens](../../api/README.md#personalproject-access-tokens) **(FREE SELF)**
- [Impersonation tokens](../../api/README.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
## Third-party resources
+<!-- vale gitlab.Spelling = NO -->
+
- [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth)
- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin)
- [OKD - Configuring Authentication and User Agent](https://docs.okd.io/3.11/install_config/configuring_authentication.html#GitLab)
+
+<!-- vale gitlab.Spelling = YES --> \ No newline at end of file
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 0d4f86f1284..b7f2a0768ef 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.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
---
-# Customizing Auto DevOps
+# Customizing Auto DevOps **(FREE)**
While [Auto DevOps](index.md) provides great defaults to get you started, you can customize
almost everything to fit your needs. Auto DevOps offers everything from custom
@@ -136,7 +136,7 @@ repository or by specifying a project variable:
file in it, Auto DevOps detects the chart and uses it instead of the
[default chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app), enabling
you to control exactly how your application is deployed.
-- **Project variable** - Create a [project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables)
+- **Project variable** - Create a [project CI/CD variable](../../ci/variables/README.md)
`AUTO_DEVOPS_CHART` with the URL of a custom chart to use, or create two project
variables: `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository,
and `AUTO_DEVOPS_CHART` with the path to the chart.
@@ -163,7 +163,7 @@ to override the default chart values by setting `HELM_UPGRADE_EXTRA_ARGS` to `--
You can customize the `helm upgrade` command used in the [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image)
by passing options to the command with the `HELM_UPGRADE_EXTRA_ARGS` variable.
For example, set the value of `HELM_UPGRADE_EXTRA_ARGS` to `--no-hooks` to disable
-pre and post upgrade hooks when the command is executed.
+pre-upgrade and post-upgrade hooks when the command is executed.
See [the official documentation](https://helm.sh/docs/helm/helm_upgrade/) for the full
list of options.
@@ -171,7 +171,7 @@ list of options.
## Custom Helm chart per environment
You can specify the use of a custom Helm chart per environment by scoping the environment variable
-to the desired environment. See [Limiting environment scopes of variables](../../ci/variables/README.md#limit-the-environment-scopes-of-environment-variables).
+to the desired environment. See [Limiting environment scopes of variables](../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables).
## Customizing `.gitlab-ci.yml`
@@ -357,7 +357,7 @@ applications.
NOTE:
After you set up your replica variables using a
-[project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables),
+[project CI/CD variable](../../ci/variables/README.md),
you can scale your application by redeploying it.
WARNING:
@@ -376,7 +376,7 @@ The following table lists variables related to the database.
| `POSTGRES_ENABLED` | Whether PostgreSQL is enabled. Defaults to `true`. Set to `false` to disable the automatic deployment of PostgreSQL. |
| `POSTGRES_USER` | The PostgreSQL user. Defaults to `user`. Set it to use a custom username. |
| `POSTGRES_PASSWORD` | The PostgreSQL password. Defaults to `testing-password`. Set it to use a custom password. |
-| `POSTGRES_DB` | The PostgreSQL database name. Defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.md#predefined-environment-variables). Set it to use a custom database name. |
+| `POSTGRES_DB` | The PostgreSQL database name. Defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.md#predefined-cicd-variables). Set it to use a custom database name. |
| `POSTGRES_VERSION` | Tag for the [`postgres` Docker image](https://hub.docker.com/_/postgres) to use. Defaults to `9.6.16` for tests and deployments as of GitLab 13.0 (previously `9.6.2`). If `AUTO_DEVOPS_POSTGRES_CHANNEL` is set to `1`, deployments uses the default version `9.6.2`. |
### Disable jobs
diff --git a/doc/topics/autodevops/img/alexj_autodevops_min_v13_8.png b/doc/topics/autodevops/img/alexj_autodevops_min_v13_8.png
new file mode 100644
index 00000000000..7dc37737835
--- /dev/null
+++ b/doc/topics/autodevops/img/alexj_autodevops_min_v13_8.png
Binary files differ
diff --git a/doc/topics/autodevops/img/kai_autodevops_min_v13_8.png b/doc/topics/autodevops/img/kai_autodevops_min_v13_8.png
new file mode 100644
index 00000000000..fa3ab4c1820
--- /dev/null
+++ b/doc/topics/autodevops/img/kai_autodevops_min_v13_8.png
Binary files differ
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 78be67a5196..d95e5568e0b 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.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
---
-# Auto DevOps
+# Auto DevOps **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37115) in GitLab 10.0.
> - Generally available on GitLab 11.0.
@@ -37,6 +37,19 @@ For requirements, read [Requirements for Auto DevOps](requirements.md) for more
For a developer's guide, read [Auto DevOps development guide](../../development/auto_devops.md).
+### Share your feedback
+
+As Auto DevOps continues to gain popularity, and lowers the barrier to entry for
+getting started with DevOps and CI/CD, see what our wider community is saying:
+
+From [AlexJonesax](https://twitter.com/AlexJonesax) and [KaiPMDH](https://twitter.com/KaiPMDH) on Twitter:
+
+![Alex on Twitter: Auto DevOps in GitLab doesn't just lower the bar to entry, it removes the bar and holds your hand.](img/alexj_autodevops_min_v13_8.png)
+
+![Kai on Twitter: When I saw this on the Auto DevOps stuff, my mind was blown...](img/kai_autodevops_min_v13_8.png)
+
+We welcome everyone to [share your experience by tagging GitLab on Twitter](https://twitter.com/gitlab).
+
## Enabled by default
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41729) in GitLab 11.3.
@@ -153,20 +166,10 @@ any of the following places:
**Continuous Integration and Delivery** section
The base domain variable `KUBE_INGRESS_BASE_DOMAIN` follows the same order of precedence
-as other environment [variables](../../ci/variables/README.md#priority-of-environment-variables).
+as other environment [variables](../../ci/variables/README.md#priority-of-cicd-variables).
If the CI/CD variable is not set and the cluster setting is left blank, the instance-wide **Auto DevOps domain**
setting is used if set.
-NOTE:
-If you use the [GitLab managed app for Ingress](../../user/clusters/applications.md#ingress),
-the URL endpoint should be automatically configured for you. All you must do
-is use its value for the `KUBE_INGRESS_BASE_DOMAIN` variable.
-
-NOTE:
-`AUTO_DEVOPS_DOMAIN` was [deprecated in GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52363)
-and replaced with `KUBE_INGRESS_BASE_DOMAIN`, and removed in
-[GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/56959).
-
Auto DevOps requires a wildcard DNS A record matching the base domain(s). For
a base domain of `example.com`, you'd need a DNS entry like:
@@ -283,7 +286,7 @@ used by Auto DevOps currently defines 3 environment names:
Those environments are tied to jobs using [Auto Deploy](stages.md#auto-deploy), so
except for the environment scope, they must have a different deployment domain.
You must define a separate `KUBE_INGRESS_BASE_DOMAIN` variable for each of the above
-[based on the environment](../../ci/variables/README.md#limit-the-environment-scopes-of-environment-variables).
+[based on the environment](../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables).
The following table is an example of how to configure the three different clusters:
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index effdb4d7b75..cd951e53bd1 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.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
---
-# Getting started with Auto DevOps
+# Getting started with Auto DevOps **(FREE)**
This step-by-step guide helps you use [Auto DevOps](index.md) to
deploy a project hosted on GitLab.com to Google Kubernetes Engine.
@@ -51,7 +51,7 @@ those projects provide a bare-bones application built on some well-known framewo
1. Give your project a name, optionally a description, and make it public so that
you can take advantage of the features available in the
- [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com).
+ [GitLab Ultimate plan](https://about.gitlab.com/pricing/).
![Create project](img/guide_create_project_v12_3.png)
@@ -177,7 +177,7 @@ The jobs are separated into stages:
- The `test` job runs unit and integration tests by detecting the language and
framework ([Auto Test](stages.md#auto-test))
- The `code_quality` job checks the code quality and is allowed to fail
- ([Auto Code Quality](stages.md#auto-code-quality)) **(STARTER)**
+ ([Auto Code Quality](stages.md#auto-code-quality))
- The `container_scanning` job checks the Docker container if it has any
vulnerabilities and is allowed to fail ([Auto Container Scanning](stages.md#auto-container-scanning))
- The `dependency_scanning` job checks if the application has any dependencies
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index 824874ed4d4..930938b7571 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.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
---
-# Requirements for Auto DevOps
+# Requirements for Auto DevOps **(FREE)**
You can set up Auto DevOps for [Kubernetes](#auto-devops-requirements-for-kubernetes),
[Amazon Elastic Container Service (ECS)](#auto-devops-requirements-for-amazon-ecs),
@@ -46,12 +46,9 @@ To make full use of Auto DevOps with Kubernetes, you need:
- **Base domain** (for [Auto Review Apps](stages.md#auto-review-apps),
[Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring))
- You need a domain configured with wildcard DNS, which all of your Auto DevOps
- applications use. If you're using the
- [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
- the URL endpoint is automatically configured for you.
-
- You must also [specify the Auto DevOps base domain](index.md#auto-devops-base-domain).
+ You must [specify the Auto DevOps base domain](index.md#auto-devops-base-domain),
+ which all of your Auto DevOps applications use. This domain must be configured
+ with wildcard DNS.
- **GitLab Runner** (for all stages)
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 23ba6ad3356..f1244a1ad1b 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.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
---
-# Stages of Auto DevOps
+# Stages of Auto DevOps **(FREE)**
The following sections describe the stages of [Auto DevOps](index.md).
Read them carefully to understand how each one works.
@@ -135,7 +135,7 @@ might want to use a [custom buildpack](customize.md#custom-buildpacks).
## Auto Code Quality
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab](https://about.gitlab.com/pricing/) 9.3.
> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in GitLab 13.2.
Auto Code Quality uses the
@@ -378,6 +378,12 @@ deploys with Auto DevOps can undo your changes. Also, if you change something
and want to undo it by deploying again, Helm may not detect that anything changed
in the first place, and thus not realize that it needs to re-apply the old configuration.
+WARNING:
+GitLab 14.0 [renews the Auto Deploy template](https://gitlab.com/gitlab-org/gitlab/-/issues/232788).
+This might cause an unexpected failure on your Auto DevOps project due to the breaking changes on
+the v2 `auto-deploy-image`. Follow [the upgrade guide](upgrading_auto_deploy_dependencies.md#upgrade-guide)
+to upgrade your environments before upgrading to GitLab 14.0.
+
### GitLab deploy tokens
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19507) in GitLab 11.0.
diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
index 663060bf59d..5f8dfcdfc05 100644
--- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
+++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
@@ -153,7 +153,7 @@ steps to upgrade to v2:
### Use a specific version of Auto Deploy dependencies
-To use a specifc version of Auto Deploy dependencies, specify the previous Auto Deploy
+To use a specific version of Auto Deploy dependencies, specify the previous Auto Deploy
stable template that contains the [desired version of `auto-deploy-image` and `auto-deploy-app`](#verify-dependency-versions).
For example, if the template is bundled in GitLab v13.3, change your `.gitlab-ci.yml` to:
@@ -181,7 +181,7 @@ the latest Auto Deploy template into your `.gitlab-ci.yml`:
```yaml
include:
- template: Auto-DevOps.gitlab-ci.yml
- - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/master/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+ - template: Jobs/Deploy.latest.gitlab-ci.yml
```
WARNING:
diff --git a/doc/topics/autodevops/upgrading_chart.md b/doc/topics/autodevops/upgrading_chart.md
deleted file mode 100644
index 2162969b53e..00000000000
--- a/doc/topics/autodevops/upgrading_chart.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'upgrading_auto_deploy_dependencies.md'
----
-
-This document was moved to [another location](upgrading_auto_deploy_dependencies.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/topics/autodevops/upgrading_postgresql.md b/doc/topics/autodevops/upgrading_postgresql.md
index 55432ad61fa..a0c4a41f90d 100644
--- a/doc/topics/autodevops/upgrading_postgresql.md
+++ b/doc/topics/autodevops/upgrading_postgresql.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
---
-# Upgrading PostgreSQL for Auto DevOps
+# Upgrading PostgreSQL for Auto DevOps **(FREE)**
Auto DevOps provides an [in-cluster PostgreSQL database](customize.md#postgresql-database-support)
for your application.
diff --git a/doc/topics/cron/index.md b/doc/topics/cron/index.md
index 5abcc5e1eb1..88f8bd1858f 100644
--- a/doc/topics/cron/index.md
+++ b/doc/topics/cron/index.md
@@ -64,6 +64,6 @@ More examples of how to write a cron schedule can be found at
## How GitLab parses cron syntax strings
-GitLab uses [fugit](https://github.com/floraison/fugit) to parse cron syntax
+GitLab uses [`fugit`](https://github.com/floraison/fugit) to parse cron syntax
strings on the server and [cron-validate](https://github.com/Airfooox/cron-validate)
to validate cron syntax in the browser.
diff --git a/doc/topics/git/feature_branch_development.md b/doc/topics/git/feature_branch_development.md
index c9fb81600d4..842c39f0bfd 100644
--- a/doc/topics/git/feature_branch_development.md
+++ b/doc/topics/git/feature_branch_development.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: how-tos
---
-# Develop on a feature branch
+# Develop on a feature branch **(FREE)**
GitLab values encourage the use of [Minimal Viable Change (MVC)](https://about.gitlab.com/handbook/values/#minimal-viable-change-mvc).
However, viable changes are not always small. In such cases, it can help to set up a dedicated feature branch.
diff --git a/doc/topics/git/git_rebase.md b/doc/topics/git/git_rebase.md
index 6a4608223b4..bf77ba3272c 100644
--- a/doc/topics/git/git_rebase.md
+++ b/doc/topics/git/git_rebase.md
@@ -6,7 +6,7 @@ type: concepts, howto
description: "Introduction to Git rebase, force-push, and resolving merge conflicts through the command line."
---
-# Introduction to Git rebase, force-push, and merge conflicts
+# Introduction to Git rebase, force-push, and merge conflicts **(FREE)**
This guide helps you to get started with rebasing, force-pushing, and fixing
merge conflicts locally.
@@ -69,7 +69,7 @@ changes by resetting `my-feature-branch` against `my-feature-branch-backup`:
```
Note that if you added changes to `my-feature-branch` after creating the backup branch,
-you will lose them when resetting.
+you lose them when resetting.
### Regular rebase
@@ -116,7 +116,7 @@ example, `release-10-3`. You can also replace `origin` with other remote
repositories, for example, `upstream`. To check what remotes you have linked to your local
repository, you can run `git remote -v`.
-If there are [merge conflicts](#merge-conflicts), Git will prompt you to fix
+If there are [merge conflicts](#merge-conflicts), Git prompts you to fix
them before continuing the rebase.
To learn more, check Git's documentation on [rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
@@ -126,13 +126,13 @@ and [rebasing strategies](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
You can use interactive rebase to modify commits. For example, amend a commit
message, squash (join multiple commits into one), edit, or delete
-commits. It is handy for changing past commit messages,
-as well as for organizing the commit history of your branch to keep it clean.
+commits. Use a rebase for changing past commit messages,
+and organizing the commit history of your branch to keep it clean.
NOTE:
If you want to keep the default branch commit history clean, you don't need to
-manually squash all your commits before merging every merge request;
-with [Squash and Merge](../../user/project/merge_requests/squash_and_merge.md)
+manually squash all your commits before merging every merge request.
+With [Squash and Merge](../../user/project/merge_requests/squash_and_merge.md),
GitLab does it automatically.
When you want to change anything in recent commits, use interactive
@@ -155,16 +155,17 @@ For example, if you're using [Vim](https://www.vim.org/) as the text editor in
a macOS's `ZSH` shell, and you want to **squash** all the three commits
(join them into one):
-1. Press <kbd>i</kbd> on your keyboard to switch to Vim's editing mode.
+1. Press <!-- vale gitlab.FirstPerson = NO --> <kbd>i</kbd> <!-- vale gitlab.FirstPerson = YES -->
+ on your keyboard to switch to Vim's editing mode.
1. Navigate with your keyboard arrows to edit the **second** commit keyword
from `pick` to `squash` (or `s`). Do the same to the **third** commit.
The first commit should be left **unchanged** (`pick`) as we want to squash
the second and third into the first.
-1. Press <kbd>Esc</kbd> to leave the editing mode.
+1. Press <kbd>Escape</kbd> to leave the editing mode.
1. Type `:wq` to "write" (save) and "quit".
1. Git outputs the commit message so you have a chance to edit it:
- - All lines starting with `#` will be ignored and not included in the commit
- message. Everything else will be included.
+ - All lines starting with `#` are ignored and not included in the commit
+ message. Everything else is included.
- To leave it as it is, type `:wq`. To edit the commit message: switch to the
editing mode, edit the commit message, and save it as you just did.
1. If you haven't pushed your commits to the remote branch before rebasing,
@@ -180,8 +181,8 @@ for a deeper look into interactive rebase.
## Force-push
When you perform more complex operations, for example, squash commits, reset or
-rebase your branch, you'll have to _force_ an update to the remote branch,
-since these operations imply rewriting the commit history of the branch.
+rebase your branch, you must _force_ an update to the remote branch.
+These operations imply rewriting the commit history of the branch.
To force an update, pass the flag `--force` or `-f` to the `push` command. For
example:
@@ -267,6 +268,6 @@ To fix conflicts locally, you can use the following method:
Up to this point, you can run `git rebase --abort` to stop the process.
Git aborts the rebase and rolls back the branch to the state you had before
running `git rebase`.
- Once you run `git rebase --continue` the rebase **cannot** be aborted.
+ After you run `git rebase --continue` the rebase **cannot** be aborted.
1. [Force-push](#force-push) to your remote branch.
diff --git a/doc/topics/git/how_to_install_git/index.md b/doc/topics/git/how_to_install_git/index.md
index 5979cad1c0e..17c5f31705f 100644
--- a/doc/topics/git/how_to_install_git/index.md
+++ b/doc/topics/git/how_to_install_git/index.md
@@ -6,7 +6,7 @@ description: 'This article describes how to install Git on macOS, Ubuntu Linux a
type: howto
---
-# Installing Git
+# Installing Git **(FREE)**
To begin contributing to GitLab projects,
you will need to install the Git client on your computer.
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
index cc4e546a244..52e8a42de76 100644
--- a/doc/topics/git/index.md
+++ b/doc/topics/git/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: index
---
-# Git
+# Git **(FREE)**
Git is a [free and open source](https://git-scm.com/about/free-and-open-source)
distributed version control system designed to handle everything from small to
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 6179175b4cd..14bb28d2477 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -6,7 +6,7 @@ type: reference, howto
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/lfs/lfs/index.html'
---
-# Git Large File Storage (LFS)
+# Git Large File Storage (LFS) **(FREE)**
Managing large files such as audio, video and graphics files has always been one
of the shortcomings of Git. The general recommendation is to not have Git repositories
@@ -14,13 +14,13 @@ larger than 1GB to preserve performance.
![Git LFS tracking status](img/lfs-icon.png)
-An LFS icon is shown on files tracked by Git LFS to denote if a file is stored
-as a blob or as an LFS pointer.
+Files tracked by Git LFS display an icon to indicate if the file is stored as a
+blob or an LFS pointer.
## How it works
Git LFS client talks with the GitLab server over HTTPS. It uses HTTP Basic Authentication
-to authorize client requests. Once the request is authorized, Git LFS client receives
+to authorize client requests. After the request is authorized, Git LFS client receives
instructions from where to fetch or where to push the large file.
## GitLab server configuration
@@ -35,18 +35,18 @@ Documentation for GitLab instance administrators is under [LFS administration do
## Known limitations
-- Git LFS v1 original API is not supported since it was deprecated early in LFS
- development
-- When SSH is set as a remote, Git LFS objects still go through HTTPS
-- Any Git LFS request will ask for HTTPS credentials to be provided so a good Git
- credentials store is recommended
-- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
- to add the URL to Git configuration manually (see [troubleshooting](#troubleshooting))
+- Git LFS v1 original API is not supported, because it was deprecated early in LFS
+ development.
+- When SSH is set as a remote, Git LFS objects still go through HTTPS.
+- Any Git LFS request asks for HTTPS credentials to be provided so a good Git
+ credentials store is recommended.
+- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you must
+ [add the URL to Git configuration manually](#troubleshooting).
NOTE:
With 8.12 GitLab added LFS support to SSH. The Git LFS communication
still goes over HTTP, but now the SSH client passes the correct credentials
-to the Git LFS client, so no action is required by the user.
+to the Git LFS client. No action is required by the user.
## Using Git LFS
@@ -60,8 +60,8 @@ git lfs install # initialize the Git LFS project
git lfs track "*.iso" # select the file extensions that you want to treat as large files
```
-Once a certain file extension is marked for tracking as a LFS object you can use
-Git as usual without having to redo the command to track a file with the same extension:
+After you mark a file extension for tracking as a LFS object you can use
+Git as usual without redoing the command to track a file with the same extension:
```shell
cp ~/tmp/debian.iso ./ # copy a large file into the current directory
@@ -71,7 +71,7 @@ git push origin master # sync the git repo and large file to the
```
**Make sure** that `.gitattributes` is tracked by Git. Otherwise Git
-LFS will not be working properly for people cloning the project:
+LFS doesn't work properly for people cloning the project:
```shell
git add .gitattributes
@@ -93,8 +93,8 @@ that are on the remote repository, such as for a branch from origin:
git lfs fetch origin master
```
-Make sure your files aren't listed in `.gitignore`, otherwise, they will be ignored by Git thus will not
-be pushed to the remote repository.
+Make sure your files aren't listed in `.gitignore`, otherwise, they are ignored by Git
+and are not pushed to the remote repository.
### Migrate an existing repository to Git LFS
@@ -178,7 +178,7 @@ available to the project anymore. Probably the object was removed from the serve
### Invalid status for `<url>` : 501
-Git LFS will log the failures into a log file.
+Git LFS logs the failures into a log file.
To view this log file, while in project directory:
```shell
@@ -201,12 +201,19 @@ If the status `error 501` is shown, it is because:
remove the line and try to update your Git LFS client. Only version 1.0.1 and
newer are supported.
+<!-- vale gitlab.Spelling = NO -->
+
### getsockopt: connection refused
-If you push a LFS object to a project and you receive an error similar to:
-`Post <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused`,
+<!-- vale gitlab.Spelling = YES -->
+
+If you push an LFS object to a project and receive an error like this,
the LFS client is trying to reach GitLab through HTTPS. However, your GitLab
-instance is being served on HTTP.
+instance is being served on HTTP:
+
+```plaintext
+Post <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused
+```
This behavior is caused by Git LFS using HTTPS connections by default when a
`lfsurl` is not set in the Git configuration.
@@ -222,10 +229,10 @@ git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"
NOTE:
With 8.12 GitLab added LFS support to SSH. The Git LFS communication
still goes over HTTP, but now the SSH client passes the correct credentials
-to the Git LFS client, so no action is required by the user.
+to the Git LFS client. No action is required by the user.
-Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing
-the LFS object on every push for every object, user HTTPS credentials are required.
+Git LFS authenticates the user with HTTP Basic Authentication on every push for
+every object, so user HTTPS credentials are required.
By default, Git has support for remembering the credentials for each repository
you use. This is described in [Git credentials man pages](https://git-scm.com/docs/gitcredentials).
@@ -237,7 +244,7 @@ which you expect to push the objects:
git config --global credential.helper 'cache --timeout=3600'
```
-This will remember the credentials for an hour after which Git operations will
+This remembers the credentials for an hour, after which Git operations
require re-authentication.
If you are using OS X you can use `osxkeychain` to store and encrypt your credentials.
@@ -258,7 +265,7 @@ If you are storing LFS files outside of GitLab you can disable LFS on the projec
It is possible to host LFS objects externally by setting a custom LFS URL with `git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs`.
-You might choose to do this if you are using an appliance like a Sonatype Nexus to store LFS data. If you choose to use an external LFS store,
-GitLab will not be able to verify LFS objects which means that pushes will fail if you have GitLab LFS support enabled.
+You might choose to do this if you are using an appliance like a <!-- vale gitlab.Spelling = NO --> Sonatype Nexus <!-- vale gitlab.Spelling = YES --> to store LFS data. If you choose to use an external LFS store,
+GitLab can't verify LFS objects. Pushes then fail if you have GitLab LFS support enabled.
-To stop push failure, LFS support can be disabled in the [Project settings](../../../user/project/settings/index.md). This means you will lose GitLab LFS value-adds (Verifying LFS objects, UI integration for LFS).
+To stop push failure, LFS support can be disabled in the [Project settings](../../../user/project/settings/index.md), which also disables GitLab LFS value-adds (Verifying LFS objects, UI integration for LFS).
diff --git a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
index 3bd754aabfb..3b3f1c0b46f 100644
--- a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Migration guide from Git Annex to Git LFS
+# Migration guide from Git Annex to Git LFS **(FREE)**
WARNING:
Git Annex support [has been removed](https://gitlab.com/gitlab-org/gitlab/-/issues/1648) in GitLab Enterprise
@@ -37,9 +37,9 @@ ones that GitLab developed.
## Migration steps
-Since Git Annex files are stored in a sub-directory of the normal repositories
-(`.git/annex/objects`) and LFS files are stored outside of the repositories,
-they are not compatible as they are using a different scheme. Therefore, the
+Git Annex files are stored in a sub-directory of the normal repositories
+(`.git/annex/objects`) and LFS files are stored outside of the repositories.
+The two aren't compatible as they are using a different scheme. Therefore, the
migration has to be done manually per repository.
There are basically two steps you need to take in order to migrate from Git
@@ -74,17 +74,17 @@ Fire up a terminal, navigate to your Git repository and:
### Disabling Git Annex in your repository
Before changing anything, make sure you have a backup of your repository first.
-There are a couple of ways to do that, but you can simply clone it to another
+There are a couple of ways to do that, but you can clone it to another
local path and maybe push it to GitLab if you want a remote backup as well.
-Here you'll find a guide on
-[how to back up a **git-annex** repository to an external hard drive](https://www.thomas-krenn.com/en/wiki/Git-annex_Repository_on_an_External_Hard_Drive).
+A guide on
+[how to back up a **git-annex** repository to an external hard drive](https://www.thomas-krenn.com/en/wiki/Git-annex_Repository_on_an_External_Hard_Drive) is also available.
-Since Annex files are stored as objects with symlinks and cannot be directly
+Because Annex files are stored as objects with symlinks and cannot be directly
modified, we need to first remove those symlinks.
NOTE:
Make sure the you read about the [`direct` mode](https://git-annex.branchable.com/direct_mode/) as it contains
-useful information that may fit in your use case. Note that `annex direct` is
+information that may fit in your use case. The `annex direct` command is
deprecated in Git Annex version 6, so you may need to upgrade your repository
if the server also has Git Annex 6 installed. Read more in the
[Git Annex troubleshooting tips](../../../administration/git_annex.md#troubleshooting-tips) section.
@@ -133,7 +133,7 @@ if the server also has Git Annex 6 installed. Read more in the
Deleted branch git-annex (was 2534d2c).
```
- This will `unannex` every file in the repository, leaving the original files.
+ This command runs `unannex` on every file in the repository, leaving the original files.
1. Switch back to `indirect` mode:
@@ -161,7 +161,7 @@ if the server also has Git Annex 6 installed. Read more in the
---
At this point, you have two options. Either add, commit and push the files
-directly back to GitLab or switch to Git LFS. We will tackle the LFS switch in
+directly back to GitLab or switch to Git LFS. The LFS switch is described in
the next section.
### Enabling Git LFS in your repository
@@ -194,7 +194,7 @@ GitLab.com), therefore, you don't need to do anything server-side.
git lfs track images/ # per directory
```
- Once you do that, run `git status` and you'll see `.gitattributes` added
+ After this, run `git status` to see the `.gitattributes` added
to your repository. It collects all file patterns that you chose to track via
`git-lfs`.
@@ -206,7 +206,7 @@ GitLab.com), therefore, you don't need to do anything server-side.
git push
```
- If your remote is set up with HTTP, you will be asked to enter your login
+ If your remote is set up with HTTP, you are asked to enter your login
credentials. If you have [2FA enabled](../../../user/profile/account/two_factor_authentication.md), make sure to use a
[personal access token](../../../user/profile/account/two_factor_authentication.md#personal-access-tokens)
instead of your password.
@@ -244,5 +244,5 @@ git annex uninit
- (Blog Post) [Getting Started with Git FLS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/)
- (Blog Post) [Announcing LFS Support in GitLab](https://about.gitlab.com/blog/2015/11/23/announcing-git-lfs-support-in-gitlab/)
- (Blog Post) [GitLab Annex Solves the Problem of Versioning Large Binaries with Git](https://about.gitlab.com/blog/2015/02/17/gitlab-annex-solves-the-problem-of-versioning-large-binaries-with-git/)
-- (GitLab Docs) [Git Annex](../../../administration/git_annex.md)
-- (GitLab Docs) [Git LFS](index.md)
+- [Git Annex](../../../administration/git_annex.md)
+- [Git LFS](index.md)
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index ef2675db6d4..98c7e59154e 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -115,7 +115,7 @@ Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs-
so that we can force-push the rewritten repository:
1. Navigate to your project's **Settings > Repository** and
- expand **Protected Branches**.
+ expand **Protected branches**.
1. Scroll down to locate the protected branches and click
**Unprotect** the default branch.
@@ -153,7 +153,7 @@ Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs-
1. [Re-protect the default branch](../../../user/project/protected_branches.md):
1. Navigate to your project's **Settings > Repository** and
- expand **Protected Branches**.
+ expand **Protected branches**.
1. Select the default branch from the **Branch** dropdown menu,
and set up the
**Allowed to push** and **Allowed to merge** rules.
diff --git a/doc/topics/git/migrate_to_git_lfs/index.md b/doc/topics/git/migrate_to_git_lfs/index.md
deleted file mode 100644
index c530fa1dcb1..00000000000
--- a/doc/topics/git/migrate_to_git_lfs/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../lfs/migrate_to_git_lfs.md'
----
-
-This document was moved to [another location](../lfs/migrate_to_git_lfs.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
index f6571c7b277..c263609125f 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -5,23 +5,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Numerous undo possibilities in Git
+# Numerous undo possibilities in Git **(FREE)**
-In this tutorial, we will show you different ways of undoing your work in Git, for which
-we will assume you have a basic working knowledge of. Check the GitLab
+This tutorial shows you different ways of undoing your work in Git.
+We assume you have a basic working knowledge of Git. Check the GitLab
[Git documentation](../index.md) for reference.
-Also, we will only provide some general information of the commands, which is enough
-to get you started for the easy cases/examples, but for anything more advanced
-please refer to the [Git book](https://git-scm.com/book/en/v2).
+We only provide some general information about the commands to get you started.
+For more advanced examples, refer to the [Git book](https://git-scm.com/book/en/v2).
-We will explain a few different techniques to undo your changes based on the stage
-of the change in your current development. Also, keep in mind that [nothing in
-Git is really deleted](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery).
-
-This means that until Git automatically cleans detached commits (which cannot be
-accessed by branch or tag) it will be possible to view them with `git reflog` command
-and access them with direct commit ID. Read more about _[redoing the undo](#redoing-the-undo)_ in the section below.
+A few different techniques exist to undo your changes, based on the stage
+of the change in your current development. Remember that
+[nothing in Git is really deleted](https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery).
+Until Git cleans detached commits - commits that cannot be accessed by branch or tag -
+you can view them with `git reflog` command, and access them with direct commit ID.
+Read more about [redoing the undo](#redoing-the-undo) in the section below.
> For more information about working with Git and GitLab:
>
@@ -30,13 +28,16 @@ and access them with direct commit ID. Read more about _[redoing the undo](#redo
## Introduction
-This guide is organized depending on the [stage of development](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository)
-where you want to undo your changes from and if they were shared with other developers
-or not. Because Git is tracking changes a created or edited file is in the unstaged state
+This guide is organized depending on the [stage of development](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository):
+
+- Where do you want to undo your changes from?
+- Were they shared with other developers?
+
+Because Git tracks changes, a created or edited file is in the unstaged state
(if created it is untracked by Git). After you add it to a repository (`git add`) you put
a file into the **staged** state, which is then committed (`git commit`) to your
local repository. After that, file can be shared with other developers (`git push`).
-Here's what we'll cover in this tutorial:
+This tutorial covers:
- [Undo local changes](#undo-local-changes) which were not pushed to a remote repository:
@@ -54,38 +55,38 @@ Here's what we'll cover in this tutorial:
### Branching strategy
-[Git](https://git-scm.com/) is a de-centralized version control system, which means that beside regular
+[Git](https://git-scm.com/) is a de-centralized version control system. Beside regular
versioning of the whole repository, it has possibilities to exchange changes
with other repositories.
To avoid chaos with
[multiple sources of truth](https://git-scm.com/about/distributed), various
-development workflows have to be followed, and it depends on your internal
+development workflows have to be followed. It depends on your internal
workflow how certain changes or commits can be undone or changed.
[GitLab Flow](https://about.gitlab.com/blog/2014/09/29/gitlab-flow/) provides a good
balance between developers clashing with each other while
-developing the same feature and cooperating seamlessly, but it does not enable
+developing the same feature and cooperating seamlessly. However, it does not enable
joined development of the same feature by multiple developers by default.
When multiple developers develop the same feature on the same branch, clashing
-with every synchronization is unavoidable, but a proper or chosen Git Workflow will
-prevent that anything is lost or out of sync when the feature is complete.
+with every synchronization is unavoidable. However, a proper or chosen Git Workflow
+prevents lost or out-of-sync data when the feature is complete.
You can also
read through this blog post on [Git Tips & Tricks](https://about.gitlab.com/blog/2016/12/08/git-tips-and-tricks/)
-to learn how to easily **do** things in Git.
+to learn how to do things in Git.
## Undo local changes
-Until you push your changes to any remote repository, they will only affect you.
+Until you push your changes to any remote repository, they only affect you.
That broadens your options on how to handle undoing them. Still, local changes
can be on various stages and each stage has a different approach on how to tackle them.
### Unstaged local changes (before you commit)
-When a change is made, but it is not added to the staged tree, Git itself
-proposes a solution to discard changes to a certain file.
+When a change is made, but not added to the staged tree, Git
+proposes a solution to discard changes to the file.
Suppose you edited a file to change the content using your favorite editor:
@@ -93,7 +94,7 @@ Suppose you edited a file to change the content using your favorite editor:
vim <file>
```
-Since you did not `git add <file>` to staging, it should be under unstaged files (or
+Because you did not `git add <file>` to staging, it should be under unstaged files (or
untracked if file was created). You can confirm that with:
```shell
@@ -136,32 +137,37 @@ you would like to apply them at some later time. You can read more about it in
### Quickly save local changes
-You are working on a feature when a boss drops by with an urgent task. Since your
+You are working on a feature when a boss drops by with an urgent task. Because your
feature is not complete, but you need to swap to another branch, you can use
-`git stash` to save what you had done, swap to another branch, commit, push,
-test, then get back to previous feature branch, do `git stash pop` and continue
-where you left.
+`git stash` to:
+
+- Save what you have done.
+- Swap to another branch.
+- Commit, push, and test.
+- Return to the feature branch.
+- Run `git stash pop`.
+- Resume your work.
-The example above shows that discarding all changes is not always a preferred option,
-but Git provides a way to save them for later, while resetting the repository to state without
+The example above shows that discarding all changes is not always a preferred option.
+However, Git provides a way to save them for later, while resetting the repository to state without
them. This is achieved by Git stashing command `git stash`, which in fact saves your
current work and runs `git reset --hard`, but it also has various
additional options like:
-- `git stash save`, which enables including temporary commit message, which will help you identify changes, among with other options
+- `git stash save`, which enables including temporary commit message, which helps you identify changes, among with other options
- `git stash list`, which lists all previously stashed commits (yes, there can be more) that were not `pop`ed
- `git stash pop`, which redoes previously stashed changes and removes them from stashed list
- `git stash apply`, which redoes previously stashed changes, but keeps them on stashed list
### Staged local changes (before you commit)
-Let's say you have added some files to staging, but you want to remove them from the
-current commit, yet you want to retain those changes - just move them outside
-of the staging tree. You also have an option to discard all changes with
+If you add some files to staging, but you want to remove them from the
+current commit while retaining those changes, move them outside
+of the staging tree. You can also discard all changes with
`git reset --hard` or think about `git stash` [as described earlier.](#quickly-save-local-changes)
-Lets start the example by editing a file, with your favorite editor, to change the
-content and add it to staging
+Lets start the example by editing a file with your favorite editor to change the
+content and add it to staging:
```shell
vim <file>
@@ -208,17 +214,17 @@ Now you have 4 options to undo your changes:
## Committed local changes
-Once you commit, your changes are recorded by the version control system.
+After you commit, your changes are recorded by the version control system.
Because you haven't pushed to your remote repository yet, your changes are
still not public (or shared with other developers). At this point, undoing
-things is a lot easier, we have quite some workaround options. Once you push
-your code, you'll have less options to troubleshoot your work.
+things is a lot easier, we have quite some workaround options. After you push
+your code, you have fewer options to troubleshoot your work.
### Without modifying history
Through the development process some of the previously committed changes do not
-fit anymore in the end solution, or are source of the bugs. Once you find the
-commit which triggered bug, or once you have a faulty commit, you can simply
+fit anymore in the end solution, or are source of the bugs. After you find the
+commit which triggered bug, or identify a faulty commit, you can
revert it with `git revert commit-id`.
This command inverts (swaps) the additions and
@@ -226,19 +232,19 @@ deletions in that commit, so that it does not modify history. Retaining history
can be helpful in future to notice that some changes have been tried
unsuccessfully in the past.
-In our example we will assume there are commits `A`,`B`,`C`,`D`,`E` committed in this order: `A-B-C-D-E`,
+In our example we assume there are commits `A`,`B`,`C`,`D`,`E` committed in this order: `A-B-C-D-E`,
and `B` is the commit you want to undo. There are many different ways to identify commit
-`B` as bad, one of them is to pass a range to `git bisect` command. The provided range includes
-last known good commit (we assume `A`) and first known bad commit (where bug was detected - we will assume `E`).
+`B` as bad. One of them is to pass a range to `git bisect` command. The provided range includes
+last known good commit (we assume `A`) and first known bad commit where the bug was detected (we assume `E`).
```shell
git bisect A..E
```
-Bisect will provide us with commit ID of the middle commit to test, and then guide us
-through simple bisection process. You can read more about it [in official Git Tools](https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git)
-In our example we will end up with commit `B`, that introduced the bug/error. We have
-4 options on how to remove it (or part of it) from our repository.
+Bisect provides us with commit ID of the middle commit to test, and then guide us
+through the bisection process. You can read more about it [in official Git Tools](https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git)
+Our example results in commit `B`, which introduced the bug/error. We have
+these options to remove all or part of it from our repository:
- Undo (swap additions and deletions) changes introduced by commit `B`:
@@ -260,13 +266,13 @@ In our example we will end up with commit `B`, that introduced the bug/error. We
- There is one command we also must not forget: **creating a new branch**
from the point where changes are not applicable or where the development has hit a
- dead end. For example you have done commits `A-B-C-D` on your feature-branch
+ dead end. For example you have done commits `A-B-C-D` on your feature branch
and then you figure `C` and `D` are wrong.
At this point you either reset to `B`
- and do commit `F` (which will cause problems with pushing and if forced pushed also with other developers)
- since branch now looks `A-B-F`, which clashes with what other developers have locally (you will
- [change history](#with-history-modification)), or you simply checkout commit `B` create
+ and do commit `F` (which causes problems with pushing and if forced pushed also with other developers)
+ because the branch now looks `A-B-F`, which clashes with what other developers have locally (you will
+ [change history](#with-history-modification)), or you checkout commit `B` create
a new branch and do commit `F`. In the last case, everyone else can still do their work while you
have your new way to get it right and merge it back in later. Alternatively, with GitLab,
you can [cherry-pick](../../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
@@ -291,7 +297,7 @@ provides interactive mode (`-i` flag) which enables you to:
- **edit** the commit content (changes introduced by commit) and message.
- **squash** multiple commits into a single one, and have a custom or aggregated
commit message.
-- **drop** commits - simply delete them.
+- **drop** commits - delete them.
- and few more options.
Let us check few examples. Again there are commits `A-B-C-D` where you want to
@@ -326,8 +332,8 @@ In case you want to modify something introduced in commit `B`.
git commit -a
```
-You can find some more examples in [below section where we explain how to modify
-history](#how-modifying-history-is-done)
+You can find some more examples in the section explaining
+[how to modify history](#how-modifying-history-is-done).
### Redoing the Undo
@@ -391,12 +397,12 @@ git checkout -b new-path-of-feature
## Undo remote changes with modifying history
This is useful when you want to *hide* certain things - like secret keys,
-passwords, SSH keys, etc. It is and should not be used to hide mistakes, as
-it will make it harder to debug in case there are some other bugs. The main
-reason for this is that you loose the real development progress. **Also keep in
+passwords, and SSH keys. It is and should not be used to hide mistakes, as
+it makes it harder to debug in case there are some other bugs. The main
+reason for this is that you loose the real development progress. Keep in
mind that, even with modified history, commits are just detached and can still be
-accessed through commit ID** - at least until all repositories perform
-the cleanup of detached commits (happens automatically).
+accessed through commit ID - at least until all repositories perform
+the automated cleanup of detached commits.
![Modifying history causes problems on remote branch](img/rebase_reset.png)
@@ -404,16 +410,16 @@ the cleanup of detached commits (happens automatically).
Modified history breaks the development chain of other developers, as changed
history does not have matching commit IDs. For that reason it should not be
-used on any public branch or on branch that *might* be used by other developers.
+used on any public branch or on branch that might be used by other developers.
When contributing to big open source repositories (for example, [GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md#contribution-acceptance-criteria)
-itself), it is acceptable to *squash* commits into a single one, to present a
+itself), it is acceptable to squash commits into a single one, to present a
nicer history of your contribution.
Keep in mind that this also removes the comments attached to certain commits
in merge requests, so if you need to retain traceability in GitLab, then
modifying history is not acceptable.
-A feature-branch of a merge request is a public branch and might be used by
+A feature branch of a merge request is a public branch and might be used by
other developers, but project process and rules might allow or require
you to use `git rebase` (command that changes history) to reduce number of
displayed commits on target branch after reviews are done (for example
@@ -427,7 +433,7 @@ Never modify the commit history of `master` or shared branch.
### How modifying history is done
After you know what you want to modify (how far in history or how which range of
-old commits), use `git rebase -i commit-id`. This command will then display all the commits from
+old commits), use `git rebase -i commit-id`. This command displays all the commits from
current version to chosen commit ID and allow modification, squashing, deletion
of that commits.
@@ -458,12 +464,12 @@ pick <commit3-id> <commit3-commit-message>
```
NOTE:
-It is important to notice that comment from the output clearly states that, if
-you decide to abort, then do not just close your editor (as that will in-fact
-modify history), but remove all uncommented lines and save.
+The comment from the output clearly states that, if
+you decide to abort, don't just close your editor (as that
+modifies history), but remove all uncommented lines and save.
-That is one of the reasons why `git rebase` should be used carefully on
-shared and remote branches. But don't worry, there will be nothing broken until
+Use `git rebase` carefully on
+shared and remote branches, but rest assured: nothing is broken until
you push back to the remote repository (so you can freely explore the
different outcomes locally).
@@ -486,7 +492,7 @@ file from history altogether use:
git filter-branch --tree-filter 'rm filename' HEAD
```
-Since `git filter-branch` command might be slow on big repositories, there are
+Because `git filter-branch` command might be slow on big repositories, there are
tools that can use some of Git specifics to enable faster execution of common
tasks (which is exactly what removing sensitive information file is about).
An alternative is the open source community-maintained tool [BFG](https://rtyley.github.io/bfg-repo-cleaner/).
@@ -497,8 +503,8 @@ Refer [Reduce repository size](../../../user/project/repository/reducing_the_rep
## Conclusion
-There are various options of undoing your work with any version control system, but
-because of de-centralized nature of Git, these options are multiplied (or limited)
+Various options exist for undoing your work with any version control system, but
+because of the de-centralized nature of Git, these options are multiplied (or limited)
depending on the stage of your process. Git also enables rewriting history, but that
should be avoided as it might cause problems when multiple developers are
contributing to the same codebase.
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index fa42cfd6e5b..d9c239486f5 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Partial Clone
+# Partial Clone **(FREE)**
As Git repositories grow in size, they can become cumbersome to work with
because of the large amount of history that must be downloaded, and the large
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index aace979004f..528a9a4ba00 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: howto
---
-# Troubleshooting Git
+# Troubleshooting Git **(FREE)**
Sometimes things don't work the way they should or as you might expect when
you're using Git. Here are some tips on troubleshooting and resolving issues
@@ -14,7 +14,7 @@ with Git.
## Broken pipe errors on `git push`
'Broken pipe' errors can occur when attempting to push to a remote repository.
-When pushing you will usually see:
+When pushing you usually see:
```plaintext
Write failed: Broken pipe
@@ -45,14 +45,13 @@ set to 50MB. The default is 1MB.
**If pushing over SSH**, first check your SSH configuration as 'Broken pipe'
errors can sometimes be caused by underlying issues with SSH (such as
authentication). Make sure that SSH is correctly configured by following the
-instructions in the [SSH troubleshooting](../../ssh/README.md#troubleshooting) docs.
+instructions in the [SSH troubleshooting](../../ssh/README.md#troubleshooting) documentation.
-There's another option where you can prevent session timeouts by configuring
-SSH 'keep alive' either on the client or on the server (if you are a GitLab
-admin and have access to the server).
+If you're a GitLab administrator and have access to the server, you can also prevent
+session timeouts by configuring SSH `keep alive` either on the client or on the server.
NOTE:
-Configuring *both* the client and the server is unnecessary.
+Configuring both the client and the server is unnecessary.
**To configure SSH on the client side**:
@@ -67,7 +66,7 @@ Configuring *both* the client and the server is unnecessary.
- On Windows, if you are using PuTTY, go to your session properties, then
navigate to "Connection" and under "Sending of null packets to keep
- session active", set "Seconds between keepalives (0 to turn off)" to `60`.
+ session active", set `Seconds between keepalives (0 to turn off)` to `60`.
**To configure SSH on the server side**, edit `/etc/ssh/sshd_config` and add:
@@ -125,7 +124,7 @@ MaxStartups 100:30:200
```
`100:30:200` means up to 100 SSH sessions are allowed without restriction,
-after which 30% of connections will be dropped until reaching an absolute maximum of 200.
+after which 30% of connections are dropped until reaching an absolute maximum of 200.
Once configured, restart the SSH daemon for the change to take effect.
@@ -140,7 +139,7 @@ sudo service sshd restart
## Timeout during `git push` / `git pull`
If pulling/pushing from/to your repository ends up taking more than 50 seconds,
-a timeout will be issued with a log of the number of operations performed
+a timeout is issued. It contains a log of the number of operations performed
and their respective timings, like the example below:
```plaintext
@@ -154,7 +153,7 @@ and provide GitLab with more information on how to improve the service.
## `git clone` over HTTP fails with `transfer closed with outstanding read data remaining` error
-If the buffer size is lower than what is allowed in the request, the action will fail with an error similar to the one below:
+If the buffer size is lower than what is allowed in the request, the action fails with an error similar to the one below:
```plaintext
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
@@ -163,7 +162,7 @@ fatal: early EOF
fatal: index-pack failed
```
-This can be fixed by increasing the existing `http.postBuffer` value to one greater than the repository size. For example, if `git clone` fails when cloning a 500M repository, the solution will be to set `http.postBuffer` to `524288000` so that the request only starts buffering after the first 524288000 bytes.
+This can be fixed by increasing the existing `http.postBuffer` value to one greater than the repository size. For example, if `git clone` fails when cloning a 500M repository, you should set `http.postBuffer` to `524288000`. That setting ensures the request only starts buffering after the first 524288000 bytes.
NOTE:
The default value of `http.postBuffer`, 1 MiB, is applied if the setting is not configured.
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 6b4d1e06c2c..94279e521b6 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -5,10 +5,10 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Useful Git commands
+# Useful Git commands **(FREE)**
-Here are some useful Git commands collected by the GitLab support team. You may not
-need to use often, but they can come in handy when needed.
+The GitLab support team has collected these commands to help you. You may not
+need to use them often.
## Remotes
@@ -182,7 +182,7 @@ Git includes a complete set of [traces for debugging Git commands](https://git-s
### Rebase your branch onto master
-The -i flag stands for 'interactive':
+The `-i` flag stands for 'interactive':
```shell
git rebase -i master
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 87d8129dc7f..d02573a0e06 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/gitlab_flow.html'
---
-# Introduction to GitLab Flow
+# Introduction to GitLab Flow **(FREE)**
![GitLab Flow](img/gitlab_flow.png)
@@ -16,7 +16,7 @@ It combines [feature-driven development](https://en.wikipedia.org/wiki/Feature-d
Organizations coming to Git from other version control systems frequently find it hard to develop a productive workflow.
This article describes GitLab flow, which integrates the Git workflow with an issue tracking system.
-It offers a simple, transparent, and effective way to work with Git.
+It offers a transparent and effective way to work with Git.
![Four stages (working copy, index, local repository, remote repository) and three steps between them](img/gitlab_flow_four_stages.png)
@@ -28,7 +28,7 @@ After getting used to these three steps, the next challenge is the branching mod
![Multiple long-running branches and merging in all directions](img/gitlab_flow_messy_flow.png)
-Since many organizations new to Git have no conventions for how to work with it, their repositories can quickly become messy.
+Because many organizations new to Git have no conventions for how to work with it, their repositories can quickly become messy.
The biggest problem is that many long-running branches emerge that all contain part of the changes.
People have a hard time figuring out which branch has the latest code, or which branch to deploy to production.
Frequently, the reaction to this problem is to adopt a standardized pattern such as [Git flow](https://nvie.com/posts/a-successful-git-branching-model/) and [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html).
@@ -38,8 +38,12 @@ For a video introduction of how this works in GitLab, see [GitLab Flow](https://
## Git flow and its problems
+<!-- vale gitlab.Spelling = NO -->
+
![Git Flow timeline by Vincent Driessen, used with permission](img/gitlab_flow_gitdashflow.png)
+<!-- vale gitlab.Spelling = YES -->
+
Git flow was one of the first proposals to use Git branches, and it has received a lot of attention.
It suggests a `master` branch and a separate `develop` branch, as well as supporting branches for features, releases, and hotfixes.
The development happens on the `develop` branch, moves to a release branch, and is finally merged into the `master` branch.
@@ -47,7 +51,7 @@ The development happens on the `develop` branch, moves to a release branch, and
Git flow is a well-defined standard, but its complexity introduces two problems.
The first problem is that developers must use the `develop` branch and not `master`. `master` is reserved for code that is released to production.
It is a convention to call your default branch `master` and to mostly branch from and merge to this.
-Since most tools automatically use the `master` branch as the default, it is annoying to have to switch to another branch.
+Because most tools automatically use the `master` branch as the default, it is annoying to have to switch to another branch.
The second problem of Git flow is the complexity introduced by the hotfix and release branches.
These branches can be a good idea for some organizations but are overkill for the vast majority of them.
@@ -61,28 +65,32 @@ For example, many projects do releases but don't need to do hotfixes.
## GitHub flow as a simpler alternative
-![Master branch with feature branches merged in](img/gitlab_flow_github_flow.png)
+![Branch with feature branches merged in](img/gitlab_flow_github_flow.png)
In reaction to Git flow, GitHub created a simpler alternative.
[GitHub flow](https://guides.github.com/introduction/flow/index.html) has only feature branches and a `master` branch.
This flow is clean and straightforward, and many organizations have adopted it with great success.
Atlassian recommends [a similar strategy](https://www.atlassian.com/blog/git/simple-git-workflow-is-simple), although they rebase feature branches.
-Merging everything into the `master` branch and frequently deploying means you minimize the amount of unreleased code, which is in line with lean and continuous delivery best practices.
+Merging everything into the `master` branch and frequently deploying means you minimize the amount of unreleased code. This approach is in line with lean and continuous delivery best practices.
However, this flow still leaves a lot of questions unanswered regarding deployments, environments, releases, and integrations with issues.
With GitLab flow, we offer additional guidance for these questions.
## Production branch with GitLab flow
-![Master branch and production branch with an arrow that indicates a deployment](img/gitlab_flow_production_branch.png)
+![Branches with an arrow that indicates a deployment](img/gitlab_flow_production_branch.png)
GitHub flow assumes you can deploy to production every time you merge a feature branch.
-While this is possible in some cases, such as SaaS applications, there are many cases where this is not possible.
-One case is where you don't control the timing of a release, for example, an iOS application that is released when it passes App Store validation.
-Another case is when you have deployment windows &mdash; for example, workdays from 10&nbsp;AM to 4&nbsp;PM when the operations team is at full capacity &mdash; but you also merge code at other times.
+While this is possible in some cases, such as SaaS applications, there are some cases where this is not possible, such as:
+
+- You don't control the timing of a release. For example, an iOS application that
+ is released when it passes App Store validation.
+- You have deployment windows - for example, workdays from 10 AM to 4 PM when the
+ operations team is at full capacity - but you also merge code at other times.
+
In these cases, you can make a production branch that reflects the deployed code.
You can deploy a new version by merging `master` into the production branch.
-If you need to know what code is in production, you can just checkout the production branch to see.
-The approximate time of deployment is easily visible as the merge commit in the version control system.
+If you need to know what code is in production, you can check out the production branch to see.
+The approximate time of deployment is visible as the merge commit in the version control system.
This time is pretty accurate if you automatically deploy your production branch.
If you need a more exact time, you can have your deployment script create a tag on each deployment.
This flow prevents the overhead of releasing, tagging, and merging that happens with Git flow.
@@ -105,10 +113,10 @@ If this is not possible because more manual testing is required, you can send me
## Release branches with GitLab flow
-![Master and multiple release branches that vary in length with cherry-picks from master](img/gitlab_flow_release_branches.png)
+![Multiple release branches that vary in length with cherry-picks](img/gitlab_flow_release_branches.png)
You only need to work with release branches if you need to release software to the outside world.
-In this case, each branch contains a minor version, for example, 2-3-stable, 2-4-stable, etc.
+In this case, each branch contains a minor version, such as `2-3-stable` or `2-4-stable`.
Create stable branches using `master` as a starting point, and branch as late as possible.
By doing this, you minimize the length of time during which you have to apply bug fixes to multiple branches.
After announcing a release branch, only add serious bug fixes to the branch.
@@ -124,11 +132,11 @@ In this flow, it is not common to have a production branch (or Git flow `master`
![Merge request with inline comments](img/gitlab_flow_mr_inline_comments.png)
Merge or pull requests are created in a Git management application. They ask an assigned person to merge two branches.
-Tools such as GitHub and Bitbucket choose the name "pull request" since the first manual action is to pull the feature branch.
-Tools such as GitLab and others choose the name "merge request" since the final action is to merge the feature branch.
-In this article, we'll refer to them as merge requests.
+Tools such as GitHub and Bitbucket choose the name "pull request", because the first manual action is to pull the feature branch.
+Tools such as GitLab and others choose the name "merge request", because the final action is to merge the feature branch.
+This article refers to them as merge requests.
-If you work on a feature branch for more than a few hours, it is good to share the intermediate result with the rest of the team.
+If you work on a feature branch for more than a few hours, share the intermediate result with the rest of your team.
To do this, create a merge request without assigning it to anyone.
Instead, mention people in the description or a comment, for example, "/cc @mark @susan."
This indicates that the merge request is not ready to be merged yet, but feedback is welcome.
@@ -143,7 +151,7 @@ Also, mention any other people from whom you would like feedback.
After the assigned person feels comfortable with the result, they can merge the branch.
If the assigned person does not feel comfortable, they can request more changes or close the merge request without merging.
-In GitLab, it is common to protect the long-lived branches, e.g., the `master` branch, so that [most developers can't modify them](../user/permissions.md).
+In GitLab, it is common to protect the long-lived branches, such as the `master` branch, so [most developers can't modify them](../user/permissions.md).
So, if you want to merge into a protected branch, assign your merge request to someone with maintainer permissions.
After you merge a feature branch, you should remove it from the source control software.
@@ -165,10 +173,10 @@ GitLab flow is a way to make the relation between the code and the issue tracker
Any significant change to the code should start with an issue that describes the goal.
Having a reason for every code change helps to inform the rest of the team and to keep the scope of a feature branch small.
In GitLab, each change to the codebase starts with an issue in the issue tracking system.
-If there is no issue yet, create the issue, as long as the change will take a significant amount of work, i.e., more than 1 hour.
+If there is no issue yet, create the issue if the change requires more than an hour's work.
In many organizations, raising an issue is part of the development process because they are used in sprint planning.
The issue title should describe the desired state of the system.
-For example, the issue title "As an administrator, I want to remove users without receiving an error" is better than "Admin can't remove users."
+For example, the issue title "As an administrator, I want to remove users without receiving an error" is better than "Administrators can't remove users."
When you are ready to code, create a branch for the issue from the `master` branch.
This branch is the place for any work related to this change.
@@ -185,20 +193,20 @@ Start the title of the merge request with `[Draft]`, `Draft:` or `(Draft)` to pr
When you think the code is ready, assign the merge request to a reviewer.
The reviewer can merge the changes when they think the code is ready for inclusion in the `master` branch.
-When they press the merge button, GitLab merges the code and creates a merge commit that makes this event easily visible later on.
+When they press the merge button, GitLab merges the code and creates a merge commit that makes this event visible later on.
Merge requests always create a merge commit, even when the branch could be merged without one.
This merge strategy is called "no fast-forward" in Git.
-After the merge, delete the feature branch since it is no longer needed.
+After the merge, delete the feature branch, because it is no longer needed.
In GitLab, this deletion is an option when merging.
Suppose that a branch is merged but a problem occurs and the issue is reopened.
-In this case, it is no problem to reuse the same branch name since the first branch was deleted when it was merged.
+In this case, it is no problem to reuse the same branch name, because the first branch was deleted when it was merged.
At any time, there is at most one branch for every issue.
It is possible that one feature branch solves more than one issue.
## Linking and closing issues from merge requests
-![Merge request showing the linked issues that will be closed](img/gitlab_flow_close_issue_mr.png)
+![Merge request showing the linked issues to close](img/gitlab_flow_close_issue_mr.png)
Link to issues by mentioning them in commit messages or the description of a merge request, for example, "Fixes #16" or "Duck typing is preferred. See #12."
GitLab then creates links to the mentioned issues and creates comments in the issues linking back to the merge request.
@@ -212,12 +220,12 @@ If you have an issue that spans across multiple repositories, create an issue fo
![Vim screen showing the rebase view](img/gitlab_flow_rebase.png)
With Git, you can use an interactive rebase (`rebase -i`) to squash multiple commits into one or reorder them.
-This functionality is useful if you want to replace a couple of small commits with a single commit, or if you want to make the order more logical.
+This feature helps you replace a couple of small commits with a single commit, or if you want to make the order more logical.
However, you should avoid rebasing commits you have pushed to a remote server if you have other active contributors in the same branch.
-Since rebasing creates new commits for all your changes, it can cause confusion because the same change would have multiple identifiers.
+Because rebasing creates new commits for all your changes, it can cause confusion because the same change would have multiple identifiers.
It would cause merge errors for anyone working on the same branch because their history would not match with yours. It can be really troublesome for the author or other contributors.
-Also, if someone has already reviewed your code, rebasing makes it hard to tell what changed since the last review.
+Also, if someone has already reviewed your code, rebasing makes it hard to tell what changed after the last review.
You should never rebase commits authored by other people unless you've agreed otherwise.
Not only does this rewrite history, but it also loses authorship information.
@@ -225,7 +233,7 @@ Rebasing prevents the other authors from being attributed and sharing part of th
If a merge involves many commits, it may seem more difficult to undo.
You might consider solving this by squashing all the changes into one commit just before merging by using the GitLab [Squash-and-Merge](../user/project/merge_requests/squash_and_merge.md) feature.
-Fortunately, there is an easy way to undo a merge with all its commits.
+Fortunately, you can undo a merge with all its commits.
The way to do this is by reverting the merge commit.
Preserving this ability to revert a merge is a good reason to always use the "no fast-forward" (`--no-ff`) strategy when you merge manually.
@@ -243,8 +251,8 @@ Often, people avoid merge commits by just using rebase to reorder their commits
Using rebase prevents a merge commit when merging `master` into your feature branch, and it creates a neat linear history.
However, as discussed in [the section about rebasing](#squashing-commits-with-rebase), you should avoid rebasing commits in a feature branch that you're sharing with others.
-Rebasing could create more work, since every time you rebase, you may need to resolve the same conflicts.
-Sometimes you can reuse recorded resolutions (`rerere`), but merging is better since you only have to resolve conflicts once.
+Rebasing could create more work, as every time you rebase, you may need to resolve the same conflicts.
+Sometimes you can reuse recorded resolutions (`rerere`), but merging is better, because you only have to resolve conflicts once.
Atlassian has a more thorough explanation of the tradeoffs between merging and rebasing [on their blog](https://www.atlassian.com/blog/git/git-team-workflows-merge-or-rebase).
A good way to prevent creating many merge commits is to not frequently merge `master` into the feature branch.
@@ -270,8 +278,8 @@ You could also use [feature toggles](https://martinfowler.com/bliki/FeatureToggl
NOTE:
Don't confuse automatic branch testing with continuous integration.
-Martin Fowler makes this distinction in [his article about feature branches](https://martinfowler.com/bliki/FeatureBranch.html):
-"I've heard people say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit.
+Martin Fowler makes this distinction in [an article about feature branches](https://martinfowler.com/bliki/FeatureBranch.html):
+"\[People\] say they are doing CI because they are running builds, perhaps using a CI server, on every branch with every commit.
That's continuous building, and a Good Thing, but there's no *integration*, so it's not CI."
In conclusion, you should try to prevent merge commits, but not eliminate them.
@@ -285,24 +293,36 @@ If you rebase code, the history is incorrect, and there is no way for tools to r
Another way to make your development work easier is to commit often.
Every time you have a working set of tests and code, you should make a commit.
Splitting up work into individual commits provides context for developers looking at your code later.
-Smaller commits make it clear how a feature was developed, and they make it easy to roll back to a specific good point in time or to revert one code change without reverting several unrelated changes.
+Smaller commits make it clear how a feature was developed. They help you roll back to a specific good point in time, or to revert one code change without reverting several unrelated changes.
-Committing often also makes it easy to share your work, which is important so that everyone is aware of what you are working on.
+Committing often also helps you share your work, which is important so that everyone is aware of what you are working on.
You should push your feature branch frequently, even when it is not yet ready for review.
By sharing your work in a feature branch or [a merge request](#mergepull-requests-with-gitlab-flow), you prevent your team members from duplicating work.
-Sharing your work before it's complete also allows for discussion and feedback about the changes, which can help improve the code before it gets to review.
+Sharing your work before it's complete also allows for discussion and feedback about the changes. This feedback can help improve the code before it gets to review.
## How to write a good commit message
![Good and bad commit message](img/gitlab_flow_good_commit.png)
A commit message should reflect your intention, not just the contents of the commit.
-It is easy to see the changes in a commit, so the commit message should explain why you made those changes.
+You can see the changes in a commit, so the commit message should explain why you made those changes.
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 example, "Improve XML generation" could be better written as "Properly escape special characters in XML generation."
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).
+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,
+containing more information for users who need in-depth context about the change.
+
+For example:
+
+```plaintext
+Properly escape special characters in XML generation.
+
+Issue: gitlab.com/gitlab-org/gitlab/-/issues/1
+```
+
## Testing before merging
![Merge requests showing the test states: red, yellow, and green](img/gitlab_flow_ci_mr.png)
@@ -311,12 +331,12 @@ In old workflows, the continuous integration (CI) server commonly ran tests on t
Developers had to ensure their code did not break the `master` branch.
When using GitLab flow, developers create their branches from this `master` branch, so it is essential that it never breaks.
Therefore, each merge request must be tested before it is accepted.
-CI software like Travis CI and GitLab CI/CD show the build results right in the merge request itself to make this easy.
+CI software like Travis CI and GitLab CI/CD show the build results right in the merge request itself to simplify the process.
There is one drawback to testing merge requests: the CI server only tests the feature branch itself, not the merged result.
Ideally, the server could also test the `master` branch after each change.
However, retesting on every commit to `master` is computationally expensive and means you are more frequently waiting for test results.
-Since feature branches should be short-lived, testing just the branch is an acceptable risk.
+Because feature branches should be short-lived, testing just the branch is an acceptable risk.
If new commits in `master` cause merge conflicts with the feature branch, merge `master` back into the branch to make the CI server re-run the tests.
As said before, if you often have feature branches that last for more than a few days, you should make your issues smaller.
diff --git a/doc/topics/index.md b/doc/topics/index.md
index 276cb07c250..565b436c0b0 100644
--- a/doc/topics/index.md
+++ b/doc/topics/index.md
@@ -19,6 +19,6 @@ tutorials, technical overviews, blog posts) and videos.
- [Cron](cron/index.md)
- [Git](git/index.md)
- [GitLab Flow](gitlab_flow.md)
-- [GitLab Installation](../install/README.md)
+- [GitLab Installation](../install/index.md)
- [GitLab Pages](../user/project/pages/index.md)
- [Offline GitLab](offline/index.md)
diff --git a/doc/university/README.md b/doc/university/README.md
index 7d6ecb536a6..c815842480c 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -1,212 +1,8 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-comments: false
-type: index
+redirect_to: 'index.md'
---
-# GitLab University
+This document was moved to [another location](index.md).
-GitLab University is a great place to start when learning about version control with Git and GitLab, as well as other GitLab features.
-
-If you're looking for a GitLab subscription for _your university_, see our [GitLab for Education](https://about.gitlab.com/solutions/education/) page.
-
-WARNING:
-Some of the content in GitLab University may be out of date and we plan to
-[evaluate](https://gitlab.com/gitlab-org/gitlab/-/issues/20403) it.
-
-The GitLab University curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections:
-
-1. [GitLab Beginner](#1-gitlab-beginner).
-1. [GitLab Intermediate](#2-gitlab-intermediate).
-1. [GitLab Advanced](#3-gitlab-advanced).
-1. [External Articles](#4-external-articles).
-1. [Resources for GitLab Team Members](#5-resources-for-gitlab-team-members).
-
-## 1. GitLab Beginner
-
-### 1.1. Version Control and Git
-
-1. [Version Control Systems](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.g72f2e4906_2_29)
-1. [Katacoda: Learn Git Version Control using Interactive Browser-Based Scenarios](https://www.katacoda.com/courses/git)
-
-### 1.2. GitLab Basics
-
-1. [An Overview of GitLab.com - Video](https://www.youtube.com/watch?v=WaiL5DGEMR4)
-1. [Why Use Git and GitLab - Slides](https://docs.google.com/a/gitlab.com/presentation/d/1RcZhFmn5VPvoFu6UMxhMOy7lAsToeBZRjLRn0LIdaNc/edit?usp=drive_web)
-1. [GitLab Basics - Article](../gitlab-basics/README.md)
-1. [Git and GitLab Basics - Video](https://www.youtube.com/watch?v=03wb9FvO4Ak&index=5&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [Git and GitLab Basics - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2475-part-233-2/)
-1. [Comparison of GitLab Versions](https://about.gitlab.com/features/#compare)
-
-### 1.3. Your GitLab Account
-
-1. [Create a GitLab Account - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2434-create-an-account-on-gitlab/)
-1. [Create and Add your SSH key to GitLab - Video](https://www.youtube.com/watch?v=54mxyLo3Mqk)
-
-### 1.4. GitLab Projects
-
-1. [Repositories, Projects and Groups - Video](https://www.youtube.com/watch?v=4TWfh1aKHHw&index=1&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [Creating a Project in GitLab - Video](https://www.youtube.com/watch?v=7p0hrpNaJ14)
-1. [How to Create Files and Directories](https://about.gitlab.com/blog/2016/02/10/feature-highlight-create-files-and-directories-from-files-page/)
-1. [GitLab To-Do List](https://about.gitlab.com/blog/2016/03/02/gitlab-todos-feature-highlight/)
-1. [GitLab Work in Progress (WIP) Flag](https://about.gitlab.com/blog/2016/01/08/feature-highlight-wip/)
-
-### 1.5. Migrating from other Source Control
-
-1. [Migrating from Bitbucket/Stash](../user/project/import/bitbucket.md)
-1. [Migrating from GitHub](../user/project/import/github.md)
-1. [Migrating from SVN](../user/project/import/svn.md)
-1. [Migrating from Fogbugz](../user/project/import/fogbugz.md)
-
-### 1.6. The GitLab team
-
-1. [About GitLab](https://about.gitlab.com/company/)
-1. [GitLab Direction](https://about.gitlab.com/direction/)
-1. [GitLab Master Plan](https://about.gitlab.com/blog/2016/09/13/gitlab-master-plan/)
-1. [Making GitLab Great for Everyone - Video](https://www.youtube.com/watch?v=GGC40y4vMx0) - Response to "Dear GitHub" letter
-1. [Using Innersourcing to Improve Collaboration](https://about.gitlab.com/blog/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/)
-1. [The Software Development Market and GitLab - Video](https://www.youtube.com/watch?v=sXlhgPK1NTY&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=6) - [Slides](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit)
-1. [GitLab Resources](https://about.gitlab.com/resources/)
-
-### 1.7 Community and Support
-
-1. [Getting Help](https://about.gitlab.com/get-help/)
- - Proposing Features and Reporting and Tracking bugs for GitLab
- - The GitLab IRC channel, Gitter Chat Room, Community Forum, and Mailing List
- - Getting Technical Support
- - Being part of our Great Community and Contributing to GitLab
-1. [Getting Started with the GitLab Development Kit (GDK)](https://about.gitlab.com/blog/2016/06/08/getting-started-with-gitlab-development-kit/)
-1. [GitLab Professional Services](https://about.gitlab.com/services/)
-
-### 1.8 GitLab Training Material
-
-1. [Git and GitLab Workshop - Slides](https://docs.google.com/presentation/d/1JzTYD8ij9slejV2-TO-NzjCvlvj6mVn9BORePXNJoMI/edit?usp=drive_web)
-
-## 2. GitLab Intermediate
-
-### 2.1 GitLab Pages
-
-1. [Using any Static Site Generator with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
-1. [Securing GitLab Pages with SSL](https://about.gitlab.com/blog/2016/06/24/secure-gitlab-pages-with-startssl/)
-1. [GitLab Pages Documentation](../user/project/pages/index.md)
-
-### 2.2. GitLab Issues
-
-1. [Markdown in GitLab](../user/markdown.md)
-1. [Issues and Merge Requests - Video](https://www.youtube.com/watch?v=raXvuwet78M)
-1. [Due Dates and Milestones for GitLab Issues](https://about.gitlab.com/blog/2016/08/05/feature-highlight-set-dates-for-issues/)
-1. [How to Use GitLab Labels](https://about.gitlab.com/blog/2016/08/17/using-gitlab-labels/)
-1. [Applying GitLab Labels Automatically](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/)
-1. [GitLab Issue Board - Product Page](https://about.gitlab.com/stages-devops-lifecycle/issueboard/)
-1. [An Overview of GitLab Issue Board](https://about.gitlab.com/blog/2016/08/22/announcing-the-gitlab-issue-board/)
-1. [Designing GitLab Issue Board](https://about.gitlab.com/blog/2016/08/31/designing-issue-boards/)
-1. [From Idea to Production with GitLab - Video](https://www.youtube.com/watch?v=25pHyknRgEo&index=14&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-
-### 2.3. Continuous Integration
-
-1. [Operating Systems, Servers, VMs, Containers and Unix - Video](https://www.youtube.com/watch?v=V61kL6IC-zY&index=8&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [GitLab CI/CD - Product Page](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)
-1. [Getting started with GitLab and GitLab CI](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
-1. [GitLab Container Registry](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/)
-1. [GitLab and Docker - Video](https://www.youtube.com/watch?v=ugOrCcbdHko&index=12&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [How we scale GitLab with built in Docker](https://about.gitlab.com/blog/2016/06/21/how-we-scale-gitlab-by-having-docker-built-in/)
-1. [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
-1. [Deployments and Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)
-1. [Sequential, Parallel or Custom Pipelines](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/)
-1. [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/blog/2016/03/01/gitlab-runner-with-docker/)
-1. [Setting up GitLab Runner on DigitalOcean](https://about.gitlab.com/blog/2016/04/19/how-to-set-up-gitlab-runner-on-digitalocean/)
-1. [Setting up GitLab CI for iOS projects](https://about.gitlab.com/blog/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
-1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw)
-1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc)
-1. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/devops/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
-1. See **[Integrations](#39-integrations)** for integrations with other CI services.
-
-### 2.4. Workflow
-
-1. [GitLab Flow - Video](https://youtu.be/enMumwvLAug?list=PLFGfElNsQthZnwMUFi6rqkyUZkI00OxIV)
-1. [GitLab Flow vs Forking in GitLab - Video](https://www.youtube.com/watch?v=UGotqAUACZA)
-1. [GitLab Flow Overview](https://about.gitlab.com/blog/2014/09/29/gitlab-flow/)
-1. [Always Start with an Issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/)
-1. [GitLab Flow Documentation](../topics/gitlab_flow.md)
-
-### 2.5. GitLab Comparisons
-
-1. [GitLab Compared to Other Tools](https://about.gitlab.com/devops-tools/)
-1. [Comparing GitLab Terminology](https://about.gitlab.com/blog/2016/01/27/comparing-terms-gitlab-github-bitbucket/)
-1. [GitLab Compared to Atlassian (Recording 2016-03-03)](https://youtu.be/Nbzp1t45ERo)
-1. [GitLab Position FAQ](https://about.gitlab.com/handbook/positioning-faq/)
-1. [Customer review of GitLab with points on why they prefer GitLab](https://www.enovate.co.uk/blog/2015/11/25/gitlab-review)
-
-## 3. GitLab Advanced
-
-### 3.1. DevOps
-
-1. [XebiaLabs: DevOps Terminology](https://digital.ai/glossary)
-1. [XebiaLabs: Periodic Table of DevOps Tools](https://digital.ai/periodic-table-of-devops-tools)
-1. [Puppet Labs: State of DevOps 2016 - Book](https://puppet.com/resources/report/2016-state-devops-report/)
-
-### 3.2. Installing GitLab with Omnibus
-
-1. [What is Omnibus - Video](https://www.youtube.com/watch?v=XTmpKudd-Oo)
-1. [How to Install GitLab with Omnibus - Video](https://www.youtube.com/watch?v=Q69YaOjqNhg)
-1. [Installing GitLab - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2476-part-0/)
-1. [Using a Non-Packaged PostgreSQL Database](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#using-a-non-packaged-postgresql-database-management-server)
-1. [Installing GitLab on Microsoft Azure](https://about.gitlab.com/blog/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/)
-1. [Installing GitLab on Digital Ocean](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/)
-
-### 3.3. Permissions
-
-1. [How to Manage Permissions in GitLab EE - Video](https://www.youtube.com/watch?v=DjUoIrkiNuM)
-
-### 3.4. Large Files
-
-1. [Big files in Git (Git LFS) - Video](https://www.youtube.com/watch?v=DawznUxYDe4)
-
-### 3.5. LDAP and Active Directory
-
-1. [How to Manage LDAP, Active Directory in GitLab - Video](https://www.youtube.com/watch?v=HPMjM-14qa8)
-
-### 3.6 Custom Languages
-
-1. [How to add Syntax Highlighting Support for Custom Languages to GitLab - Video](https://youtu.be/6WxTMqatrrA)
-
-### 3.7. Scalability and High Availability
-
-1. [Scalability and High Availability - Video](https://www.youtube.com/watch?v=cXRMJJb6sp4&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=2)
-1. [High Availability - Video](https://www.youtube.com/watch?v=36KS808u6bE&index=15&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [High Availability Documentation](https://about.gitlab.com/solutions/reference-architectures/)
-
-### 3.8 Value Stream Analytics
-
-1. [GitLab Value Stream Analytics Overview (as of 2016)](https://about.gitlab.com/blog/2016/09/21/cycle-analytics-feature-highlight/)
-1. [GitLab Value Stream Analytics - Product Page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/)
-
-### 3.9. Integrations
-
-1. [How to Integrate Jira and Jenkins with GitLab - Video](https://gitlabmeetings.webex.com/gitlabmeetings/ldr.php?RCID=44b548147a67ab4d8a62274047146415)
-1. [How to Integrate Jira with GitLab](../user/project/integrations/jira.md)
-1. [How to Integrate Jenkins with GitLab](../integration/jenkins.md)
-1. [How to Integrate Bamboo with GitLab](../user/project/integrations/bamboo.md)
-1. [How to Integrate Slack with GitLab](../user/project/integrations/slack.md)
-1. [How to Integrate Convox with GitLab](https://about.gitlab.com/blog/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
-1. [Getting Started with GitLab and Shippable CI](https://about.gitlab.com/blog/2016/05/05/getting-started-gitlab-and-shippable/)
-
-## 4. External Articles
-
-1. [2011 WSJ article by Marc Andreessen - Software is Eating the World](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
-1. [2014 Blog post by Chris Dixon - Software eats software development](https://cdixon.org/2014/04/13/software-eats-software-development/)
-1. [2015 Venture Beat article - Actually, Open Source is Eating the World](https://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/)
-
-## 5. Resources for GitLab Team Members
-
-NOTE:
-Some content can only be accessed by GitLab team members.
-
-1. [Sales Path](https://about.gitlab.com/handbook/sales/onboarding/)
-1. [User Training](training/user_training.md)
-1. [GitLab Flow Training](training/gitlab_flow.md)
-1. [Training Topics](training/index.md)
-1. [GitLab architecture](../development/architecture.md)
-1. [Client Assessment of GitLab versus GitHub](https://docs.google.com/a/gitlab.com/spreadsheets/d/18cRF9Y5I6I7Z_ab6qhBEW55YpEMyU4PitZYjomVHM-M/edit?usp=sharing)
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md
deleted file mode 100644
index c0251229916..00000000000
--- a/doc/university/bookclub/booklist.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com'
----
-
-Visit our [documentation page](https://docs.gitlab.com) for information about GitLab.
diff --git a/doc/university/bookclub/index.md b/doc/university/bookclub/index.md
deleted file mode 100644
index c0251229916..00000000000
--- a/doc/university/bookclub/index.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com'
----
-
-Visit our [documentation page](https://docs.gitlab.com) for information about GitLab.
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
deleted file mode 100644
index c0251229916..00000000000
--- a/doc/university/glossary/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com'
----
-
-Visit our [documentation page](https://docs.gitlab.com) for information about GitLab.
diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md
deleted file mode 100644
index cfaeea8f5c2..00000000000
--- a/doc/university/high-availability/aws/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../install/aws/index.md'
----
-
-This document was moved to [another location](../../../install/aws/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/index.md b/doc/university/index.md
new file mode 100644
index 00000000000..8b6c2d834f9
--- /dev/null
+++ b/doc/university/index.md
@@ -0,0 +1,223 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+comments: false
+type: index
+---
+
+# GitLab University
+
+GitLab University is a great place to start when learning about version control with Git and GitLab, as well as other GitLab features.
+
+If you're looking for a GitLab subscription for _your university_, see our [GitLab for Education](https://about.gitlab.com/solutions/education/) page.
+
+WARNING:
+Some of the content in GitLab University may be out of date and we plan to
+[evaluate](https://gitlab.com/gitlab-org/gitlab/-/issues/20403) it.
+
+The GitLab University curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections:
+
+1. [GitLab Beginner](#1-gitlab-beginner).
+1. [GitLab Intermediate](#2-gitlab-intermediate).
+1. [GitLab Advanced](#3-gitlab-advanced).
+1. [External Articles](#4-external-articles).
+1. [Resources for GitLab Team Members](#5-resources-for-gitlab-team-members).
+
+## 1. GitLab Beginner
+
+### 1.1. Version Control and Git
+
+<!-- vale gitlab.Spelling = NO -->
+
+1. [Version Control Systems](https://docs.google.com/presentation/d/16sX7hUrCZyOFbpvnrAFrg6tVO5_yT98IgdAqOmXwBho/edit#slide=id.g72f2e4906_2_29)
+1. [Katacoda: Learn Git Version Control using Interactive Browser-Based Scenarios](https://www.katacoda.com/courses/git)
+
+<!-- vale gitlab.Spelling = YES -->
+
+### 1.2. GitLab Basics
+
+1. [An Overview of GitLab.com - Video](https://www.youtube.com/watch?v=WaiL5DGEMR4)
+1. [Why Use Git and GitLab - Slides](https://docs.google.com/a/gitlab.com/presentation/d/1RcZhFmn5VPvoFu6UMxhMOy7lAsToeBZRjLRn0LIdaNc/edit?usp=drive_web)
+1. [GitLab Basics - Article](../gitlab-basics/index.md)
+1. [Git and GitLab Basics - Video](https://www.youtube.com/watch?v=03wb9FvO4Ak&index=5&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
+1. [Git and GitLab Basics - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2475-part-233-2/)
+1. [Comparison of GitLab Versions](https://about.gitlab.com/features/#compare)
+
+### 1.3. Your GitLab Account
+
+1. [Create a GitLab Account - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2434-create-an-account-on-gitlab/)
+1. [Create and Add your SSH key to GitLab - Video](https://www.youtube.com/watch?v=54mxyLo3Mqk)
+
+### 1.4. GitLab Projects
+
+1. [Repositories, Projects and Groups - Video](https://www.youtube.com/watch?v=4TWfh1aKHHw&index=1&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
+1. [Creating a Project in GitLab - Video](https://www.youtube.com/watch?v=7p0hrpNaJ14)
+1. [How to Create Files and Directories](https://about.gitlab.com/blog/2016/02/10/feature-highlight-create-files-and-directories-from-files-page/)
+1. [GitLab To-Do List](https://about.gitlab.com/blog/2016/03/02/gitlab-todos-feature-highlight/)
+1. [GitLab Work in Progress (WIP) Flag](https://about.gitlab.com/blog/2016/01/08/feature-highlight-wip/)
+
+### 1.5. Migrating from other Source Control
+
+<!-- vale gitlab.Spelling = NO -->
+
+1. [Migrating from Bitbucket/Stash](../user/project/import/bitbucket.md)
+1. [Migrating from GitHub](../user/project/import/github.md)
+1. [Migrating from SVN](../user/project/import/svn.md)
+1. [Migrating from Fogbugz](../user/project/import/fogbugz.md)
+
+<!-- vale gitlab.Spelling = YES -->
+### 1.6. The GitLab team
+
+1. [About GitLab](https://about.gitlab.com/company/)
+1. [GitLab Direction](https://about.gitlab.com/direction/)
+1. [GitLab Master Plan](https://about.gitlab.com/blog/2016/09/13/gitlab-master-plan/)
+1. [Making GitLab Great for Everyone - Video](https://www.youtube.com/watch?v=GGC40y4vMx0) - Response to "Dear GitHub" letter
+1. [Using Innersourcing to Improve Collaboration](https://about.gitlab.com/blog/2014/09/05/innersourcing-using-the-open-source-workflow-to-improve-collaboration-within-an-organization/)
+1. [The Software Development Market and GitLab - Video](https://www.youtube.com/watch?v=sXlhgPK1NTY&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=6) - [Slides](https://docs.google.com/presentation/d/1vCU-NbZWz8NTNK8Vu3y4zGMAHb5DpC8PE5mHtw1PWfI/edit)
+1. [GitLab Resources](https://about.gitlab.com/resources/)
+
+### 1.7 Community and Support
+
+1. [Getting Help](https://about.gitlab.com/get-help/)
+ - Proposing Features and Reporting and Tracking bugs for GitLab
+ - The GitLab IRC channel, Gitter Chat Room, Community Forum, and Mailing List
+ - Getting Technical Support
+ - Being part of our Great Community and Contributing to GitLab
+1. [Getting Started with the GitLab Development Kit (GDK)](https://about.gitlab.com/blog/2016/06/08/getting-started-with-gitlab-development-kit/)
+1. [GitLab Professional Services](https://about.gitlab.com/services/)
+
+### 1.8 GitLab Training Material
+
+1. [Git and GitLab Workshop - Slides](https://docs.google.com/presentation/d/1JzTYD8ij9slejV2-TO-NzjCvlvj6mVn9BORePXNJoMI/edit?usp=drive_web)
+
+## 2. GitLab Intermediate
+
+### 2.1 GitLab Pages
+
+1. [Using any Static Site Generator with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
+1. [Securing GitLab Pages with SSL](https://about.gitlab.com/blog/2016/06/24/secure-gitlab-pages-with-startssl/)
+1. [GitLab Pages Documentation](../user/project/pages/index.md)
+
+### 2.2. GitLab Issues
+
+1. [Markdown in GitLab](../user/markdown.md)
+1. [Issues and Merge Requests - Video](https://www.youtube.com/watch?v=raXvuwet78M)
+1. [Due Dates and Milestones for GitLab Issues](https://about.gitlab.com/blog/2016/08/05/feature-highlight-set-dates-for-issues/)
+1. [How to Use GitLab Labels](https://about.gitlab.com/blog/2016/08/17/using-gitlab-labels/)
+1. [Applying GitLab Labels Automatically](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/)
+1. [GitLab Issue Board - Product Page](https://about.gitlab.com/stages-devops-lifecycle/issueboard/)
+1. [An Overview of GitLab Issue Board](https://about.gitlab.com/blog/2016/08/22/announcing-the-gitlab-issue-board/)
+1. [Designing GitLab Issue Board](https://about.gitlab.com/blog/2016/08/31/designing-issue-boards/)
+1. [From Idea to Production with GitLab - Video](https://www.youtube.com/watch?v=25pHyknRgEo&index=14&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
+
+### 2.3. Continuous Integration
+
+1. [Operating Systems, Servers, VMs, Containers and Unix - Video](https://www.youtube.com/watch?v=V61kL6IC-zY&index=8&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
+1. [GitLab CI/CD - Product Page](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/)
+1. [Getting started with GitLab and GitLab CI](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
+1. [GitLab Container Registry](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/)
+1. [GitLab and Docker - Video](https://www.youtube.com/watch?v=ugOrCcbdHko&index=12&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
+1. [How we scale GitLab with built in Docker](https://about.gitlab.com/blog/2016/06/21/how-we-scale-gitlab-by-having-docker-built-in/)
+1. [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
+1. [Deployments and Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/)
+1. [Sequential, Parallel or Custom Pipelines](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/)
+1. [Setting up GitLab Runner For Continuous Integration](https://about.gitlab.com/blog/2016/03/01/gitlab-runner-with-docker/)
+1. [Setting up GitLab Runner on DigitalOcean](https://about.gitlab.com/blog/2016/04/19/how-to-set-up-gitlab-runner-on-digitalocean/)
+1. [Setting up GitLab CI for iOS projects](https://about.gitlab.com/blog/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
+1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw)
+1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc)
+1. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/devops/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
+1. See **[Integrations](#39-integrations)** for integrations with other CI services.
+
+### 2.4. Workflow
+
+1. [GitLab Flow - Video](https://youtu.be/enMumwvLAug?list=PLFGfElNsQthZnwMUFi6rqkyUZkI00OxIV)
+1. [GitLab Flow vs Forking in GitLab - Video](https://www.youtube.com/watch?v=UGotqAUACZA)
+1. [GitLab Flow Overview](https://about.gitlab.com/blog/2014/09/29/gitlab-flow/)
+1. [Always Start with an Issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/)
+1. [GitLab Flow Documentation](../topics/gitlab_flow.md)
+
+### 2.5. GitLab Comparisons
+
+1. [GitLab Compared to Other Tools](https://about.gitlab.com/devops-tools/)
+1. [Comparing GitLab Terminology](https://about.gitlab.com/blog/2016/01/27/comparing-terms-gitlab-github-bitbucket/)
+1. [GitLab Compared to Atlassian (Recording 2016-03-03)](https://youtu.be/Nbzp1t45ERo)
+1. [GitLab Position FAQ](https://about.gitlab.com/handbook/positioning-faq/)
+1. [Customer review of GitLab with points on why they prefer GitLab](https://www.enovate.co.uk/blog/2015/11/25/gitlab-review)
+
+## 3. GitLab Advanced
+
+### 3.1. DevOps
+
+1. [XebiaLabs: DevOps Terminology](https://digital.ai/glossary)
+1. [XebiaLabs: Periodic Table of DevOps Tools](https://digital.ai/periodic-table-of-devops-tools)
+1. [Puppet Labs: State of DevOps 2016 - Book](https://puppet.com/resources/report/2016-state-devops-report/)
+
+### 3.2. Installing GitLab with Omnibus
+
+1. [What is Omnibus - Video](https://www.youtube.com/watch?v=XTmpKudd-Oo)
+1. [How to Install GitLab with Omnibus - Video](https://www.youtube.com/watch?v=Q69YaOjqNhg)
+1. [Installing GitLab - Online Course](https://courses.platzi.com/classes/57-git-gitlab/2476-part-0/)
+1. [Using a Non-Packaged PostgreSQL Database](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#using-a-non-packaged-postgresql-database-management-server)
+1. [Installing GitLab on Microsoft Azure](https://about.gitlab.com/blog/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/)
+1. [Installing GitLab on Digital Ocean](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/)
+
+### 3.3. Permissions
+
+1. [How to Manage Permissions in GitLab EE - Video](https://www.youtube.com/watch?v=DjUoIrkiNuM)
+
+### 3.4. Large Files
+
+1. [Big files in Git (Git LFS) - Video](https://www.youtube.com/watch?v=DawznUxYDe4)
+
+### 3.5. LDAP and Active Directory
+
+1. [How to Manage LDAP, Active Directory in GitLab - Video](https://www.youtube.com/watch?v=HPMjM-14qa8)
+
+### 3.6 Custom Languages
+
+1. [How to add Syntax Highlighting Support for Custom Languages to GitLab - Video](https://youtu.be/6WxTMqatrrA)
+
+### 3.7. Scalability and High Availability
+
+1. [Scalability and High Availability - Video](https://www.youtube.com/watch?v=cXRMJJb6sp4&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=2)
+1. [High Availability - Video](https://www.youtube.com/watch?v=36KS808u6bE&index=15&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
+1. [High Availability Documentation](https://about.gitlab.com/solutions/reference-architectures/)
+
+### 3.8 Value Stream Analytics
+
+1. [GitLab Value Stream Analytics Overview (as of 2016)](https://about.gitlab.com/blog/2016/09/21/cycle-analytics-feature-highlight/)
+1. [GitLab Value Stream Analytics - Product Page](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/)
+
+### 3.9. Integrations
+
+<!-- vale gitlab.Spelling = NO -->
+
+1. [How to Integrate Jira and Jenkins with GitLab - Video](https://gitlabmeetings.webex.com/gitlabmeetings/ldr.php?RCID=44b548147a67ab4d8a62274047146415)
+1. [How to Integrate Jira with GitLab](../user/project/integrations/jira.md)
+1. [How to Integrate Jenkins with GitLab](../integration/jenkins.md)
+1. [How to Integrate Bamboo with GitLab](../user/project/integrations/bamboo.md)
+1. [How to Integrate Slack with GitLab](../user/project/integrations/slack.md)
+1. [How to Integrate Convox with GitLab](https://about.gitlab.com/blog/2016/06/09/continuous-delivery-with-gitlab-and-convox/)
+1. [Getting Started with GitLab and Shippable CI](https://about.gitlab.com/blog/2016/05/05/getting-started-gitlab-and-shippable/)
+
+<!-- vale gitlab.Spelling = YES -->
+
+## 4. External Articles
+
+1. [2011 Wall Street Journal article - Software is Eating the World](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
+1. [2014 Blog post by Chris Dixon - Software eats software development](https://cdixon.org/2014/04/13/software-eats-software-development/)
+1. [2015 Venture Beat article - Actually, Open Source is Eating the World](https://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/)
+
+## 5. Resources for GitLab Team Members
+
+NOTE:
+Some content can only be accessed by GitLab team members.
+
+1. [Sales Path](https://about.gitlab.com/handbook/sales/onboarding/)
+1. [User Training](training/user_training.md)
+1. [GitLab Flow Training](training/gitlab_flow.md)
+1. [Training Topics](training/index.md)
+1. [GitLab architecture](../development/architecture.md)
+1. [Client Assessment of GitLab versus GitHub](https://docs.google.com/a/gitlab.com/spreadsheets/d/18cRF9Y5I6I7Z_ab6qhBEW55YpEMyU4PitZYjomVHM-M/edit?usp=sharing)
diff --git a/doc/university/process/README.md b/doc/university/process/README.md
deleted file mode 100644
index c0251229916..00000000000
--- a/doc/university/process/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com'
----
-
-Visit our [documentation page](https://docs.gitlab.com) for information about GitLab.
diff --git a/doc/university/training/end-user/README.md b/doc/university/training/end-user/README.md
deleted file mode 100644
index c0251229916..00000000000
--- a/doc/university/training/end-user/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: 'https://docs.gitlab.com'
----
-
-Visit our [documentation page](https://docs.gitlab.com) for information about GitLab.
diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md
index f25bff03926..bdc97ff8d28 100644
--- a/doc/university/training/gitlab_flow.md
+++ b/doc/university/training/gitlab_flow.md
@@ -1,57 +1,8 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-comments: false
-type: reference
+redirect_to: '../../topics/gitlab_flow.md'
---
-# What is the GitLab Flow
+This document was moved to [another location](../../topics/gitlab_flow.md).
-- A simplified branching strategy
-- All features and fixes first go to master
-- Allows for 'production' or 'stable' branches
-- Bug fixes/hot fix patches are cherry-picked from master
-
-## Feature branches
-
-- Create a feature/bugfix branch to do all work
-- Use merge requests to merge to master
-
-![inline](gitlab_flow/feature_branches.png)
-
-## Production branch
-
-- One, long-running production release branch
- as opposed to individual stable branches
-- Consider creating a tag for each version that gets deployed
-
-![inline](gitlab_flow/production_branch.png)
-
-## Release branch
-
-- Useful if you release software to customers
-- When preparing a new release, create stable branch
- from master
-- Consider creating a tag for each version
-- Cherry-pick critical bug fixes to stable branch for patch release
-- Never commit bug fixes directly to stable branch
-
-![inline](gitlab_flow/release_branches.png)
-
-## More details
-
-For more information, read through the [GitLab Flow](../../topics/gitlab_flow.md)
-documentation.
-
-<!-- ## 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 <2021-05-16>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
index deae79e51b0..13cf4184560 100644
--- a/doc/university/training/index.md
+++ b/doc/university/training/index.md
@@ -8,8 +8,10 @@ type: index
# GitLab Training Material
+<!-- vale gitlab.Spelling = NO -->
All GitLab training material is stored in Markdown format. Slides are
-generated using [Deskset](https://www.deckset.com/).
+generated using [Deckset](https://www.deckset.com/).
+<!-- vale gitlab.Spelling = YES -->
All training material is open to public contribution.
@@ -20,7 +22,7 @@ This section contains the following topics:
- [Cherry pick](topics/cherry_picking.md).
- [Code review and collaboration with Merge Requests](topics/merge_requests.md).
- [Configure your environment](topics/env_setup.md).
-- [Explore GitLab](../../gitlab-basics/README.md).
+- [Explore GitLab](../../gitlab-basics/index.md).
- [Feature branching](topics/feature_branching.md).
- [Getting started](topics/getting_started.md).
- [GitLab flow](gitlab_flow.md).
@@ -40,6 +42,6 @@ This section contains the following topics:
1. [GitLab Documentation](https://docs.gitlab.com)
1. [GUI Clients](https://git-scm.com/downloads/guis)
1. [Pro Git book](https://git-scm.com/book/en/v2)
-1. [Platzi Course](https://courses.platzi.com/courses/git-gitlab/)
+1. <!-- vale gitlab.Spelling = NO --> [Platzi Course](https://courses.platzi.com/courses/git-gitlab/) <!-- vale gitlab.Spelling = NO -->
1. [Code School tutorial](http://try.github.io/)
1. Contact us at `subscribers@gitlab.com`
diff --git a/doc/university/training/topics/explore_gitlab.md b/doc/university/training/topics/explore_gitlab.md
deleted file mode 100644
index 584069aa7b0..00000000000
--- a/doc/university/training/topics/explore_gitlab.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../gitlab-basics/README.md'
----
-
-This document was moved to [another location](../../../gitlab-basics/README.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
index fd600624a25..2c3d5fe15de 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -21,7 +21,7 @@ comments: false
git clone <url>
```
-## Central Repos
+## Central Repositories
- To instantiate a central repository a `--bare` flag is required.
- Bare repositories don't allow file editing or committing changes.
@@ -34,7 +34,7 @@ comments: false
## Instantiate workflow with clone
1. Create a project in your user namespace.
- - Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>.
+ - Choose to import from **Any Repository by URL** and use <https://gitlab.com/gitlab-org/training-examples.git>.
1. Create a '`Workspace`' directory in your home directory.
1. Clone the '`training-examples`' project.
diff --git a/doc/university/training/topics/gitlab_flow.md b/doc/university/training/topics/gitlab_flow.md
deleted file mode 100644
index f6006ce0a60..00000000000
--- a/doc/university/training/topics/gitlab_flow.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-redirect_to: '../gitlab_flow.md'
----
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index ad8f094d185..75c4fe25842 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -102,7 +102,7 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.
## Create a project
- Create a project in your user namespace.
- - Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>.
+ - Choose to import from **Any Repository by URL** and use <https://gitlab.com/gitlab-org/training-examples.git>.
- Create a '`development`' or '`workspace`' directory in your home directory.
- Clone the '`training-examples`' project.
@@ -214,9 +214,13 @@ Create your first merge request:
## Feedback and Collaboration resources
+<!-- vale gitlab.Spelling = NO -->
+
Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
<https://github.com/thoughtbot/guides/tree/master/code-review>.
+<!-- vale gitlab.Spelling = YES -->
+
See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests>.
## Explore GitLab projects
diff --git a/doc/update/README.md b/doc/update/README.md
index 958beeeb321..c815842480c 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -1,423 +1,8 @@
---
-stage: Enablement
-group: Distribution
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'index.md'
---
-# Upgrading GitLab
+This document was moved to [another location](index.md).
-Upgrading GitLab is a relatively straightforward process, but the complexity
-can increase based on the installation method you have used, how old your
-GitLab version is, if you're upgrading to a major version, and so on.
-
-Make sure to read the whole page as it contains information related to every upgrade method.
-
-The [maintenance policy documentation](../policy/maintenance.md)
-has additional information about upgrading, including:
-
-- How to interpret GitLab product versioning.
-- Recommendations on the what release to run.
-- How we use patch and security patch releases.
-- When we backport code changes.
-
-## Upgrade based on installation method
-
-Depending on the installation method and your GitLab version, there are multiple
-official ways to update GitLab:
-
-- [Linux packages (Omnibus GitLab)](#linux-packages-omnibus-gitlab)
-- [Source installations](#installation-from-source)
-- [Docker installations](#installation-using-docker)
-- [Kubernetes (Helm) installations](#installation-using-helm)
-
-### Linux packages (Omnibus GitLab)
-
-The [Omnibus update guide](https://docs.gitlab.com/omnibus/update/)
-contains the steps needed to update a package installed by official GitLab
-repositories.
-
-There are also instructions when you want to
-[update to a specific version](https://docs.gitlab.com/omnibus/update/#multi-step-upgrade-using-the-official-repositories).
-
-### Installation from source
-
-- [Upgrading Community Edition and Enterprise Edition from
- source](upgrading_from_source.md) - The guidelines for upgrading Community
- Edition and Enterprise Edition from source.
-- [Patch versions](patch_versions.md) guide includes the steps needed for a
- patch version, such as 13.2.0 to 13.2.1, and apply to both Community and Enterprise
- Editions.
-
-In the past we used separate documents for the upgrading instructions, but we
-have since switched to using a single document. The old upgrading guidelines
-can still be found in the Git repository:
-
-- [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update)
-- [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update)
-
-### Installation using Docker
-
-GitLab provides official Docker images for both Community and Enterprise
-editions. They are based on the Omnibus package and instructions on how to
-update them are in [a separate document](https://docs.gitlab.com/omnibus/docker/README.html).
-
-### Installation using Helm
-
-GitLab can be deployed into a Kubernetes cluster using Helm.
-Instructions on how to update a cloud-native deployment are in
-[a separate document](https://docs.gitlab.com/charts/installation/upgrade.html).
-
-Use the [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html)
-from the chart version to GitLab version to determine the [upgrade path](#upgrade-paths).
-
-## Checking for background migrations before upgrading
-
-Certain major/minor releases may require a set of background migrations to be
-finished. The number of remaining migrations jobs can be found by running the
-following command:
-
-**For Omnibus installations**
-
-If using GitLab 12.9 and newer, run:
-
-```shell
-sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
-```
-
-If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
-
-```ruby
-puts Sidekiq::Queue.new("background_migration").size
-Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
-```
-
-**For installations from source**
-
-If using GitLab 12.9 and newer, run:
-
-```shell
-cd /home/git/gitlab
-sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
-```
-
-If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
-
-```ruby
-puts Sidekiq::Queue.new("background_migration").size
-Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
-```
-
-### What do I do if my background migrations are stuck?
-
-WARNING:
-The following operations can disrupt your GitLab performance.
-
-It is safe to re-execute these commands, especially if you have 1000+ pending jobs which would likely overflow your runtime memory.
-
-**For Omnibus installations**
-
-```shell
-# Start the rails console
-sudo gitlab-rails c
-
-# Execute the following in the rails console
-scheduled_queue = Sidekiq::ScheduledSet.new
-pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
-pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
-```
-
-**For installations from source**
-
-```shell
-# Start the rails console
-sudo -u git -H bundle exec rails RAILS_ENV=production
-
-# Execute the following in the rails console
-scheduled_queue = Sidekiq::ScheduledSet.new
-pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
-pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
-```
-
-## Upgrade paths
-
-Although you can generally upgrade through multiple GitLab versions in one go,
-sometimes this can cause issues.
-
-Find where your version sits in the upgrade path below, and upgrade GitLab
-accordingly, while also consulting the
-[version-specific upgrade instructions](#version-specific-upgrading-instructions):
-
-`8.11.x` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` - > `13.5.3`
-
-The following table, while not exhaustive, shows some examples of the supported
-upgrade paths.
-
-| Target version | Your version | Supported upgrade path | Note |
-| --------------------- | ------------ | ------------------------ | ---- |
-| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
-| `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.2.10` | Five intermediate versions are required: the final `11.11`, `12.0`, `12.1` and `12.10` releases, plus `13.0`. |
-| `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: the final `11.11` and `12.0` releases, plus `12.1` |
-| `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` |
-| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2`. |
-| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
-
-## Upgrading to a new major version
-
-Upgrading the *major* version requires more attention.
-Backward-incompatible changes and migrations are reserved for major versions.
-We cannot guarantee that upgrading between major versions will be seamless.
-It is suggested to upgrade to the latest available *minor* version within
-your major version before proceeding to the next major version.
-Doing this will address any backward-incompatible changes or deprecations
-to help ensure a successful upgrade to the next major release.
-Identify a [supported upgrade path](#upgrade-paths).
-
-More significant migrations may occur during major release upgrades. To ensure these are successful:
-
-1. Increment to the first minor version (`x.0.x`) during the major version jump.
-1. Proceed with upgrading to a newer release.
-
-It's also important to ensure that any background migrations have been fully completed
-before upgrading to a new major version. To see the current size of the `background_migration` queue,
-[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
-
-If your GitLab instance has any runners associated with it, it is very
-important to upgrade GitLab Runner to match the GitLab minor version that was
-upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
-
-## Upgrading without downtime
-
-Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
-patch version of GitLab without having to take your GitLab instance offline.
-However, for this to work there are the following requirements:
-
-- You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
- 9.3.
-- You have to use [post-deployment
- migrations](../development/post_deployment_migrations.md) (included in
- [zero downtime update steps below](#steps)).
-- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
-- Multi-node GitLab instance. Single-node instances may experience brief interruptions
- [as services restart (Puma in particular)](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
-
-Most of the time you can safely upgrade from a patch release to the next minor
-release if the patch release is not the latest. For example, upgrading from
-9.1.1 to 9.2.0 should be safe even if 9.1.2 has been released. We do recommend
-you check the release posts of any releases between your current and target
-version just in case they include any migrations that may require you to upgrade
-1 release at a time.
-
-Some releases may also include so called "background migrations". These
-migrations are performed in the background by Sidekiq and are often used for
-migrating data. Background migrations are only added in the monthly releases.
-
-Certain major/minor releases may require a set of background migrations to be
-finished. To guarantee this such a release will process any remaining jobs
-before continuing the upgrading procedure. While this won't require downtime
-(if the above conditions are met) we recommend users to keep at least 1 week
-between upgrading major/minor releases, allowing the background migrations to
-finish. The time necessary to complete these migrations can be reduced by
-increasing the number of Sidekiq workers that can process jobs in the
-`background_migration` queue. To see the size of this queue,
-[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
-
-As a rule of thumb, any database smaller than 10 GB won't take too much time to
-upgrade; perhaps an hour at most per minor release. Larger databases however may
-require more time, but this is highly dependent on the size of the database and
-the migrations that are being performed.
-
-### Examples
-
-To help explain this, let's look at some examples.
-
-**Example 1:** You are running a large GitLab installation using version 9.4.2,
-which is the latest patch release of 9.4. When GitLab 9.5.0 is released this
-installation can be safely upgraded to 9.5.0 without requiring downtime if the
-requirements mentioned above are met. You can also skip 9.5.0 and upgrade to
-9.5.1 after it's released, but you **can not** upgrade straight to 9.6.0; you
-_have_ to first upgrade to a 9.5.x release.
-
-**Example 2:** You are running a large GitLab installation using version 9.4.2,
-which is the latest patch release of 9.4. GitLab 9.5 includes some background
-migrations, and 10.0 will require these to be completed (processing any
-remaining jobs for you). Skipping 9.5 is not possible without downtime, and due
-to the background migrations would require potentially hours of downtime
-depending on how long it takes for the background migrations to complete. To
-work around this you will have to upgrade to 9.5.x first, then wait at least a
-week before upgrading to 10.0.
-
-**Example 3:** You use MySQL as the database for GitLab. Any upgrade to a new
-major/minor release will require downtime. If a release includes any background
-migrations this could potentially lead to hours of downtime, depending on the
-size of your database. To work around this you will have to use PostgreSQL and
-meet the other online upgrade requirements mentioned above.
-
-### Steps
-
-Steps to [upgrade without downtime](https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates).
-
-## Upgrading between editions
-
-GitLab comes in two flavors: [Community Edition](https://about.gitlab.com/features/#community) which is MIT licensed,
-and [Enterprise Edition](https://about.gitlab.com/features/#enterprise) which builds on top of the Community Edition and
-includes extra features mainly aimed at organizations with more than 100 users.
-
-Below you can find some guides to help you change GitLab editions.
-
-### Community to Enterprise Edition
-
-NOTE:
-The following guides are for subscribers of the Enterprise Edition only.
-
-If you wish to upgrade your GitLab installation from Community to Enterprise
-Edition, follow the guides below based on the installation method:
-
-- [Source CE to EE update guides](upgrading_from_ce_to_ee.md) - The steps are very similar
- to a version upgrade: stop the server, get the code, update configuration files for
- the new functionality, install libraries and do migrations, update the init
- script, start the application and check its status.
-- [Omnibus CE to EE](https://docs.gitlab.com/omnibus/update/README.html#update-community-edition-to-enterprise-edition) - Follow this guide to update your Omnibus
- GitLab Community Edition to the Enterprise Edition.
-
-### Enterprise to Community Edition
-
-If you need to downgrade your Enterprise Edition installation back to Community
-Edition, you can follow [this guide](../downgrade_ee_to_ce/README.md) to make the process as smooth as
-possible.
-
-## Version-specific upgrading instructions
-
-Each month, a major or minor release of GitLab is published along with a
-[release post](https://about.gitlab.com/releases/categories/releases/).
-You should check all the major and minor versions you're passing over.
-At the end of those release posts, there are three sections to look for:
-
-- Deprecations
-- Removals
-- Important notes on upgrading
-
-These will include:
-
-- Steps you need to perform as part of an upgrade.
- For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
- required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
-- Changes to the versions of software we support such as
- [ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
-
-Apart from the instructions in this section, you should also check the
-installation-specific upgrade instructions, based on how you installed GitLab:
-
-- [Linux packages (Omnibus GitLab)](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes)
-- [Helm charts](https://docs.gitlab.com/charts/installation/upgrade.html)
-
-NOTE:
-Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
-and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
-
-### 13.6.0
-
-Ruby 2.7.2 is required. GitLab will not start with Ruby 2.6.6 or older versions.
-
-The required Git version is Git v2.29 or higher.
-
-### 13.3.0
-
-The recommended Git version is Git v2.28. The minimum required version of Git
-v2.24 remains the same.
-
-### 13.2.0
-
-GitLab installations that have multiple web nodes will need to be
-[upgraded to 13.1](#1310) before upgrading to 13.2 (and later) due to a
-breaking change in Rails that can result in authorization issues.
-
-GitLab 13.2.0 [remediates](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35492) an [email verification bypass](https://about.gitlab.com/releases/2020/05/27/security-release-13-0-1-released/).
-After upgrading, if some of your users are unexpectedly encountering 404 or 422 errors when signing in,
-or "blocked" messages when using the command line,
-their accounts may have been un-confirmed.
-In that case, please ask them to check their email for a re-confirmation link.
-For more information, see our discussion of [Email confirmation issues](../user/upgrade_email_bypass.md).
-
-GitLab 13.2.0 relies on the `btree_gist` extension for PostgreSQL. For installations with an externally managed PostgreSQL setup, please make sure to
-[install the extension manually](https://www.postgresql.org/docs/11/sql-createextension.html) before upgrading GitLab if the database user for GitLab
-is not a superuser. This is not necessary for installations using a GitLab managed PostgreSQL database.
-
-### 13.1.0
-
-In 13.1.0, you must upgrade to either:
-
-- At least Git v2.24 (previously, the minimum required version was Git v2.22).
-- The recommended Git v2.26.
-
-Failure to do so will result in internal errors in the Gitaly service in some RPCs due
-to the use of the new `--end-of-options` Git flag.
-
-Additionally, in GitLab 13.1.0, the version of [Rails was upgraded from 6.0.3 to
-6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454).
-The Rails upgrade included a change to CSRF token generation which is
-not backwards-compatible - GitLab servers with the new Rails version
-will generate CSRF tokens that are not recognizable by GitLab servers
-with the older Rails version - which could cause non-GET requests to
-fail for [multi-node GitLab installations](https://docs.gitlab.com/omnibus/update/#multi-node--ha-deployment).
-
-So, if you are using multiple Rails servers and specifically upgrading from 13.0,
-all servers must first be upgraded to 13.1.X before upgrading to 13.2.0 or later:
-
-1. Ensure all GitLab web nodes are on GitLab 13.1.X.
-1. Optionally, enable the `global_csrf_token` feature flag to enable new
- method of CSRF token generation:
-
- ```ruby
- Feature.enable(:global_csrf_token)
- ```
-
-1. Only then, continue to upgrade to later versions of GitLab.
-
-### 12.2.0
-
-In 12.2.0, we enabled Rails' authenticated cookie encryption. Old sessions are
-automatically upgraded.
-
-However, session cookie downgrades are not supported. So after upgrading to 12.2.0,
-any downgrades would result to all sessions being invalidated and users are logged out.
-
-### 12.1.0
-
-If you are planning to upgrade from `12.0.x` to `12.10.x`, it is necessary to
-perform an intermediary upgrade to `12.1.x` before upgrading to `12.10.x` to
-avoid issues like [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
-
-### 12.0.0
-
-In 12.0.0 we made various database related changes. These changes require that
-users first upgrade to the latest 11.11 patch release. After upgraded to 11.11.x,
-users can upgrade to 12.0.x. Failure to do so may result in database migrations
-not being applied, which could lead to application errors.
-
-It is also required that you upgrade to 12.0.x before moving to a later version
-of 12.x.
-
-Example 1: you are currently using GitLab 11.11.8, which is the latest patch
-release for 11.11.x. You can upgrade as usual to 12.0.x.
-
-Example 2: you are currently using a version of GitLab 10.x. To upgrade, first
-upgrade to the last 10.x release (10.8.7) then the last 11.x release (11.11.8).
-After upgraded to 11.11.8 you can safely upgrade to 12.0.x.
-
-See our [documentation on upgrade paths](../policy/maintenance.md#upgrade-recommendations)
-for more information.
-
-### Upgrades from versions earlier than 8.12
-
-- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
-- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
- when it was merged into GitLab.
-
-## Miscellaneous
-
-- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating
- your database from MySQL to PostgreSQL.
-- [Restoring from backup after a failed upgrade](restore_after_failure.md)
-- [Upgrading PostgreSQL Using Slony](upgrading_postgresql_using_slony.md), for
- upgrading a PostgreSQL database with minimal downtime.
-- [Managing PostgreSQL extensions](../install/postgresql_extensions.md)
+<!-- This redirect file can be deleted after 2021-05-11. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/update/index.md b/doc/update/index.md
new file mode 100644
index 00000000000..a07a6f4b0b7
--- /dev/null
+++ b/doc/update/index.md
@@ -0,0 +1,423 @@
+---
+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
+---
+
+# Upgrading GitLab
+
+Upgrading GitLab is a relatively straightforward process, but the complexity
+can increase based on the installation method you have used, how old your
+GitLab version is, if you're upgrading to a major version, and so on.
+
+Make sure to read the whole page as it contains information related to every upgrade method.
+
+The [maintenance policy documentation](../policy/maintenance.md)
+has additional information about upgrading, including:
+
+- How to interpret GitLab product versioning.
+- Recommendations on the what release to run.
+- How we use patch and security patch releases.
+- When we backport code changes.
+
+## Upgrade based on installation method
+
+Depending on the installation method and your GitLab version, there are multiple
+official ways to update GitLab:
+
+- [Linux packages (Omnibus GitLab)](#linux-packages-omnibus-gitlab)
+- [Source installations](#installation-from-source)
+- [Docker installations](#installation-using-docker)
+- [Kubernetes (Helm) installations](#installation-using-helm)
+
+### Linux packages (Omnibus GitLab)
+
+The [Omnibus update guide](https://docs.gitlab.com/omnibus/update/)
+contains the steps needed to update a package installed by official GitLab
+repositories.
+
+There are also instructions when you want to
+[update to a specific version](https://docs.gitlab.com/omnibus/update/#multi-step-upgrade-using-the-official-repositories).
+
+### Installation from source
+
+- [Upgrading Community Edition and Enterprise Edition from
+ source](upgrading_from_source.md) - The guidelines for upgrading Community
+ Edition and Enterprise Edition from source.
+- [Patch versions](patch_versions.md) guide includes the steps needed for a
+ patch version, such as 13.2.0 to 13.2.1, and apply to both Community and Enterprise
+ Editions.
+
+In the past we used separate documents for the upgrading instructions, but we
+have since switched to using a single document. The old upgrading guidelines
+can still be found in the Git repository:
+
+- [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update)
+- [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update)
+
+### Installation using Docker
+
+GitLab provides official Docker images for both Community and Enterprise
+editions. They are based on the Omnibus package and instructions on how to
+update them are in [a separate document](https://docs.gitlab.com/omnibus/docker/README.html).
+
+### Installation using Helm
+
+GitLab can be deployed into a Kubernetes cluster using Helm.
+Instructions on how to update a cloud-native deployment are in
+[a separate document](https://docs.gitlab.com/charts/installation/upgrade.html).
+
+Use the [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html)
+from the chart version to GitLab version to determine the [upgrade path](#upgrade-paths).
+
+## Checking for background migrations before upgrading
+
+Certain major/minor releases may require a set of background migrations to be
+finished. The number of remaining migrations jobs can be found by running the
+following command:
+
+**For Omnibus installations**
+
+If using GitLab 12.9 and newer, run:
+
+```shell
+sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+```
+
+If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+puts Sidekiq::Queue.new("background_migration").size
+Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
+```
+
+**For installations from source**
+
+If using GitLab 12.9 and newer, run:
+
+```shell
+cd /home/git/gitlab
+sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+```
+
+If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+```ruby
+Sidekiq::Queue.new("background_migration").size
+Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
+```
+
+### What do I do if my background migrations are stuck?
+
+WARNING:
+The following operations can disrupt your GitLab performance.
+
+It is safe to re-execute these commands, especially if you have 1000+ pending jobs which would likely overflow your runtime memory.
+
+**For Omnibus installations**
+
+```shell
+# Start the rails console
+sudo gitlab-rails c
+
+# Execute the following in the rails console
+scheduled_queue = Sidekiq::ScheduledSet.new
+pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
+pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
+```
+
+**For installations from source**
+
+```shell
+# Start the rails console
+sudo -u git -H bundle exec rails RAILS_ENV=production
+
+# Execute the following in the rails console
+scheduled_queue = Sidekiq::ScheduledSet.new
+pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
+pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
+```
+
+## Upgrade paths
+
+Although you can generally upgrade through multiple GitLab versions in one go,
+sometimes this can cause issues.
+
+Find where your version sits in the upgrade path below, and upgrade GitLab
+accordingly, while also consulting the
+[version-specific upgrade instructions](#version-specific-upgrading-instructions):
+
+`8.11.x` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` - > `13.x (latest)`
+
+The following table, while not exhaustive, shows some examples of the supported
+upgrade paths.
+
+| Target version | Your version | Supported upgrade path | Note |
+| --------------------- | ------------ | ------------------------ | ---- |
+| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
+| `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.2.10` | Five intermediate versions are required: the final `11.11`, `12.0`, `12.1` and `12.10` releases, plus `13.0`. |
+| `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: the final `11.11` and `12.0` releases, plus `12.1` |
+| `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` |
+| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2`. |
+| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
+
+## Upgrading to a new major version
+
+Upgrading the *major* version requires more attention.
+Backward-incompatible changes and migrations are reserved for major versions.
+We cannot guarantee that upgrading between major versions will be seamless.
+It is suggested to upgrade to the latest available *minor* version within
+your major version before proceeding to the next major version.
+Doing this will address any backward-incompatible changes or deprecations
+to help ensure a successful upgrade to the next major release.
+Identify a [supported upgrade path](#upgrade-paths).
+
+More significant migrations may occur during major release upgrades. To ensure these are successful:
+
+1. Increment to the first minor version (`x.0.x`) during the major version jump.
+1. Proceed with upgrading to a newer release.
+
+It's also important to ensure that any background migrations have been fully completed
+before upgrading to a new major version. To see the current size of the `background_migration` queue,
+[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
+
+If your GitLab instance has any runners associated with it, it is very
+important to upgrade GitLab Runner to match the GitLab minor version that was
+upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
+
+## Upgrading without downtime
+
+Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
+patch version of GitLab without having to take your GitLab instance offline.
+However, for this to work there are the following requirements:
+
+- You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
+ 9.3.
+- You have to use [post-deployment
+ migrations](../development/post_deployment_migrations.md) (included in
+ [zero downtime update steps below](#steps)).
+- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
+- Multi-node GitLab instance. Single-node instances may experience brief interruptions
+ [as services restart (Puma in particular)](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment).
+
+Most of the time you can safely upgrade from a patch release to the next minor
+release if the patch release is not the latest. For example, upgrading from
+9.1.1 to 9.2.0 should be safe even if 9.1.2 has been released. We do recommend
+you check the release posts of any releases between your current and target
+version just in case they include any migrations that may require you to upgrade
+1 release at a time.
+
+Some releases may also include so called "background migrations". These
+migrations are performed in the background by Sidekiq and are often used for
+migrating data. Background migrations are only added in the monthly releases.
+
+Certain major/minor releases may require a set of background migrations to be
+finished. To guarantee this such a release will process any remaining jobs
+before continuing the upgrading procedure. While this won't require downtime
+(if the above conditions are met) we recommend users to keep at least 1 week
+between upgrading major/minor releases, allowing the background migrations to
+finish. The time necessary to complete these migrations can be reduced by
+increasing the number of Sidekiq workers that can process jobs in the
+`background_migration` queue. To see the size of this queue,
+[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
+
+As a rule of thumb, any database smaller than 10 GB won't take too much time to
+upgrade; perhaps an hour at most per minor release. Larger databases however may
+require more time, but this is highly dependent on the size of the database and
+the migrations that are being performed.
+
+### Examples
+
+To help explain this, let's look at some examples.
+
+**Example 1:** You are running a large GitLab installation using version 9.4.2,
+which is the latest patch release of 9.4. When GitLab 9.5.0 is released this
+installation can be safely upgraded to 9.5.0 without requiring downtime if the
+requirements mentioned above are met. You can also skip 9.5.0 and upgrade to
+9.5.1 after it's released, but you **can not** upgrade straight to 9.6.0; you
+_have_ to first upgrade to a 9.5.x release.
+
+**Example 2:** You are running a large GitLab installation using version 9.4.2,
+which is the latest patch release of 9.4. GitLab 9.5 includes some background
+migrations, and 10.0 will require these to be completed (processing any
+remaining jobs for you). Skipping 9.5 is not possible without downtime, and due
+to the background migrations would require potentially hours of downtime
+depending on how long it takes for the background migrations to complete. To
+work around this you will have to upgrade to 9.5.x first, then wait at least a
+week before upgrading to 10.0.
+
+**Example 3:** You use MySQL as the database for GitLab. Any upgrade to a new
+major/minor release will require downtime. If a release includes any background
+migrations this could potentially lead to hours of downtime, depending on the
+size of your database. To work around this you will have to use PostgreSQL and
+meet the other online upgrade requirements mentioned above.
+
+### Steps
+
+Steps to [upgrade without downtime](https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates).
+
+## Upgrading between editions
+
+GitLab comes in two flavors: [Community Edition](https://about.gitlab.com/features/#community) which is MIT licensed,
+and [Enterprise Edition](https://about.gitlab.com/features/#enterprise) which builds on top of the Community Edition and
+includes extra features mainly aimed at organizations with more than 100 users.
+
+Below you can find some guides to help you change GitLab editions.
+
+### Community to Enterprise Edition
+
+NOTE:
+The following guides are for subscribers of the Enterprise Edition only.
+
+If you wish to upgrade your GitLab installation from Community to Enterprise
+Edition, follow the guides below based on the installation method:
+
+- [Source CE to EE update guides](upgrading_from_ce_to_ee.md) - The steps are very similar
+ to a version upgrade: stop the server, get the code, update configuration files for
+ the new functionality, install libraries and do migrations, update the init
+ script, start the application and check its status.
+- [Omnibus CE to EE](https://docs.gitlab.com/omnibus/update/README.html#update-community-edition-to-enterprise-edition) - Follow this guide to update your Omnibus
+ GitLab Community Edition to the Enterprise Edition.
+
+### Enterprise to Community Edition
+
+If you need to downgrade your Enterprise Edition installation back to Community
+Edition, you can follow [this guide](../downgrade_ee_to_ce/index.md) to make the process as smooth as
+possible.
+
+## Version-specific upgrading instructions
+
+Each month, a major or minor release of GitLab is published along with a
+[release post](https://about.gitlab.com/releases/categories/releases/).
+You should check all the major and minor versions you're passing over.
+At the end of those release posts, there are three sections to look for:
+
+- Deprecations
+- Removals
+- Important notes on upgrading
+
+These will include:
+
+- Steps you need to perform as part of an upgrade.
+ For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
+ required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
+- Changes to the versions of software we support such as
+ [ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
+
+Apart from the instructions in this section, you should also check the
+installation-specific upgrade instructions, based on how you installed GitLab:
+
+- [Linux packages (Omnibus GitLab)](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes)
+- [Helm charts](https://docs.gitlab.com/charts/installation/upgrade.html)
+
+NOTE:
+Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
+and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
+
+### 13.6.0
+
+Ruby 2.7.2 is required. GitLab will not start with Ruby 2.6.6 or older versions.
+
+The required Git version is Git v2.29 or higher.
+
+### 13.3.0
+
+The recommended Git version is Git v2.28. The minimum required version of Git
+v2.24 remains the same.
+
+### 13.2.0
+
+GitLab installations that have multiple web nodes will need to be
+[upgraded to 13.1](#1310) before upgrading to 13.2 (and later) due to a
+breaking change in Rails that can result in authorization issues.
+
+GitLab 13.2.0 [remediates](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35492) an [email verification bypass](https://about.gitlab.com/releases/2020/05/27/security-release-13-0-1-released/).
+After upgrading, if some of your users are unexpectedly encountering 404 or 422 errors when signing in,
+or "blocked" messages when using the command line,
+their accounts may have been un-confirmed.
+In that case, please ask them to check their email for a re-confirmation link.
+For more information, see our discussion of [Email confirmation issues](../user/upgrade_email_bypass.md).
+
+GitLab 13.2.0 relies on the `btree_gist` extension for PostgreSQL. For installations with an externally managed PostgreSQL setup, please make sure to
+[install the extension manually](https://www.postgresql.org/docs/11/sql-createextension.html) before upgrading GitLab if the database user for GitLab
+is not a superuser. This is not necessary for installations using a GitLab managed PostgreSQL database.
+
+### 13.1.0
+
+In 13.1.0, you must upgrade to either:
+
+- At least Git v2.24 (previously, the minimum required version was Git v2.22).
+- The recommended Git v2.26.
+
+Failure to do so will result in internal errors in the Gitaly service in some RPCs due
+to the use of the new `--end-of-options` Git flag.
+
+Additionally, in GitLab 13.1.0, the version of [Rails was upgraded from 6.0.3 to
+6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454).
+The Rails upgrade included a change to CSRF token generation which is
+not backwards-compatible - GitLab servers with the new Rails version
+will generate CSRF tokens that are not recognizable by GitLab servers
+with the older Rails version - which could cause non-GET requests to
+fail for [multi-node GitLab installations](https://docs.gitlab.com/omnibus/update/#multi-node--ha-deployment).
+
+So, if you are using multiple Rails servers and specifically upgrading from 13.0,
+all servers must first be upgraded to 13.1.X before upgrading to 13.2.0 or later:
+
+1. Ensure all GitLab web nodes are on GitLab 13.1.X.
+1. Optionally, enable the `global_csrf_token` feature flag to enable new
+ method of CSRF token generation:
+
+ ```ruby
+ Feature.enable(:global_csrf_token)
+ ```
+
+1. Only then, continue to upgrade to later versions of GitLab.
+
+### 12.2.0
+
+In 12.2.0, we enabled Rails' authenticated cookie encryption. Old sessions are
+automatically upgraded.
+
+However, session cookie downgrades are not supported. So after upgrading to 12.2.0,
+any downgrades would result to all sessions being invalidated and users are logged out.
+
+### 12.1.0
+
+If you are planning to upgrade from `12.0.x` to `12.10.x`, it is necessary to
+perform an intermediary upgrade to `12.1.x` before upgrading to `12.10.x` to
+avoid issues like [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
+
+### 12.0.0
+
+In 12.0.0 we made various database related changes. These changes require that
+users first upgrade to the latest 11.11 patch release. After upgraded to 11.11.x,
+users can upgrade to 12.0.x. Failure to do so may result in database migrations
+not being applied, which could lead to application errors.
+
+It is also required that you upgrade to 12.0.x before moving to a later version
+of 12.x.
+
+Example 1: you are currently using GitLab 11.11.8, which is the latest patch
+release for 11.11.x. You can upgrade as usual to 12.0.x.
+
+Example 2: you are currently using a version of GitLab 10.x. To upgrade, first
+upgrade to the last 10.x release (10.8.7) then the last 11.x release (11.11.8).
+After upgraded to 11.11.8 you can safely upgrade to 12.0.x.
+
+See our [documentation on upgrade paths](../policy/maintenance.md#upgrade-recommendations)
+for more information.
+
+### Upgrades from versions earlier than 8.12
+
+- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
+- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
+ when it was merged into GitLab.
+
+## Miscellaneous
+
+- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating
+ your database from MySQL to PostgreSQL.
+- [Restoring from backup after a failed upgrade](restore_after_failure.md)
+- [Upgrading PostgreSQL Using Slony](upgrading_postgresql_using_slony.md), for
+ upgrading a PostgreSQL database with minimal downtime.
+- [Managing PostgreSQL extensions](../install/postgresql_extensions.md)
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index fb1335acd7d..9a367d218f0 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -15,7 +15,7 @@ NOTE:
Support for MySQL was removed in GitLab 12.1. This procedure should be performed
**before** installing GitLab 12.1.
-[pgloader](https://pgloader.io/) 3.4.1+ is required, confirm with `pgloader -V`.
+[pgLoader](https://pgloader.io/) 3.4.1+ is required, confirm with `pgloader -V`.
You can install it directly from your distribution, for example in
Debian/Ubuntu:
@@ -52,7 +52,7 @@ For other distributions, follow the instructions in PostgreSQL's
and then install `pgloader`.
If you are migrating to a Docker based installation, you must install
-pgloader within the container as it is not included in the container image.
+pgLoader within the container as it is not included in the container image.
1. Start a shell session in the context of the running container:
@@ -60,7 +60,7 @@ pgloader within the container as it is not included in the container image.
docker exec -it gitlab bash
```
-1. Install pgloader:
+1. Install pgLoader:
```shell
apt-get update
@@ -142,7 +142,7 @@ new PostgreSQL one:
sudo -u gitlab-psql pgloader commands.load
```
-1. Once the migration finishes, you should see a summary table that looks like
+1. After the migration finishes, you should see a summary table that looks like
the following:
```plaintext
@@ -243,7 +243,7 @@ new PostgreSQL one:
sudo -u postgres pgloader commands.load
```
-1. Once the migration finishes, you should see a summary table that looks like
+1. After the migration finishes, you should see a summary table that looks like
the following:
```plaintext
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index 71c8c701775..b4c80c4f877 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
comments: false
---
-# Universal update guide for patch versions
+# Universal update guide for patch versions of source installations
## Select Version to Install
@@ -96,7 +96,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
sudo -u git -H make
```
-### 8. Install/Update `gitlab-elasticsearch-indexer` **(STARTER ONLY)**
+### 8. Install/Update `gitlab-elasticsearch-indexer` **(PREMIUM SELF)**
Please follow the [install instruction](../integration/elasticsearch.md#installing-elasticsearch).
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index 7f190a310b0..36f0078a4f7 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -81,7 +81,7 @@ sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:c
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
```
-### 4. Install `gitlab-elasticsearch-indexer` **(STARTER ONLY)**
+### 4. Install `gitlab-elasticsearch-indexer` **(PREMIUM SELF)**
Please follow the [install instruction](../integration/elasticsearch.md#installing-elasticsearch).
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 93aefb60f61..a76e9fb4504 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -35,7 +35,7 @@ to identify the ideal upgrade path.
Before upgrading to a new major version, you should ensure that any background
migration jobs from previous releases have been completed. To see the current size of the `background_migration` queue,
-[Check for background migrations before upgrading](README.md#checking-for-background-migrations-before-upgrading).
+[Check for background migrations before upgrading](index.md#checking-for-background-migrations-before-upgrading).
## Guidelines for all versions
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index c5dd6cf16b7..c9f8f83749c 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -40,7 +40,7 @@ If you're not using the Omnibus GitLab package you may have to adjust the paths
`pg_dump` and the PostgreSQL installation directory to match the paths of your
configuration.
-Once the structure dump is generated we also need to generate a dump for the
+After the structure dump is generated we also need to generate a dump for the
`schema_migrations` table. This table doesn't have any primary keys and as such
can't be replicated easily by Slony. To generate this dump run the following
command on your active database server:
@@ -210,7 +210,7 @@ this output, don't just append it below it. The result looks like this:
]
```
-Once you have the configuration file generated you must install it on both the
+After you have the configuration file generated you must install it on both the
old and new database. To do so, place it in
`/var/opt/gitlab/postgresql/slony/slon_tools.conf` (for which we created the
directory earlier on).
@@ -218,7 +218,7 @@ directory earlier on).
Now that the configuration file is in place we can _finally_ start replicating
our database. First we must set up the schema in our new database. To do so make
sure that the SQL files we generated earlier can be found in the `/tmp`
-directory of the new server. Once these files are in place start a `psql`
+directory of the new server. After these files are in place start a `psql`
session on this server:
```shell
diff --git a/doc/user/account/security.md b/doc/user/account/security.md
deleted file mode 100644
index d9db3a25c00..00000000000
--- a/doc/user/account/security.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../profile/account/index.md'
----
-
-This document was moved to [profile](../profile/account/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/account/two_factor_authentication.md b/doc/user/account/two_factor_authentication.md
deleted file mode 100644
index b085611f747..00000000000
--- a/doc/user/account/two_factor_authentication.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../profile/account/two_factor_authentication.md'
----
-
-This document was moved to [profile/account/two_factor_authentication](../profile/account/two_factor_authentication.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/admin_area/abuse_reports.md b/doc/user/admin_area/abuse_reports.md
index 62f3bd3625c..653c67ed197 100644
--- a/doc/user/admin_area/abuse_reports.md
+++ b/doc/user/admin_area/abuse_reports.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Abuse reports **(CORE ONLY)**
+# Abuse reports **(FREE SELF)**
View and resolve abuse reports from GitLab users.
diff --git a/doc/user/admin_area/analytics/convdev.md b/doc/user/admin_area/analytics/convdev.md
deleted file mode 100644
index d0f3a34e15e..00000000000
--- a/doc/user/admin_area/analytics/convdev.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'dev_ops_report.md'
----
-
-This document was moved to [another location](dev_ops_report.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index 80108fba060..a8f6e8ec8fa 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.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
---
-# DevOps Report **(CORE)**
+# DevOps Report
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30469) in GitLab 9.3.
> - [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
@@ -15,7 +15,7 @@ from planning to monitoring.
To see DevOps Report, go to **Admin Area > Analytics > DevOps Report**.
-## DevOps Score **(CORE)**
+## DevOps Score **(FREE)**
NOTE:
Your GitLab instance's [usage ping](../settings/usage_statistics.md#usage-ping) must be activated in order to use this feature.
@@ -40,7 +40,7 @@ collected before this feature is available.
[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).
-The DevOps Adoption tab shows you which segments of your organization are using the most essential features of GitLab:
+The DevOps Adoption tab shows you which groups within your organization are using the most essential features of GitLab:
- Issues
- Merge Requests
@@ -50,9 +50,7 @@ The DevOps Adoption tab shows you which segments of your organization are using
- Deploys
- Scanning
-Segments are arbitrary collections of GitLab groups that you define. You might define a segment to represent a small team, a large department, or a whole organization.
-You are limited to creating a maximum of 20 segments, and each segment is limited to a maximum of 20 groups.
-Buttons to manage your segments appear in the DevOps Adoption section of the page.
+Buttons to manage your groups appear in the DevOps Adoption section of the page.
DevOps Adoption allows you to:
@@ -60,7 +58,7 @@ DevOps Adoption allows you to:
- Identify specific groups that are lagging in their adoption of GitLab so you can help them along in their DevOps journey.
- Find the groups that have adopted certain features and can provide guidance to other groups on how to use those features.
-![DevOps Report](img/dev_ops_adoption_v13_7.png)
+![DevOps Report](img/dev_ops_adoption_v13_9.png)
### Disable or enable DevOps Adoption
diff --git a/doc/user/admin_area/analytics/img/cohorts_v13_4.png b/doc/user/admin_area/analytics/img/cohorts_v13_4.png
deleted file mode 100644
index 6f7dd5101f2..00000000000
--- a/doc/user/admin_area/analytics/img/cohorts_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/analytics/img/cohorts_v13_9.png b/doc/user/admin_area/analytics/img/cohorts_v13_9.png
new file mode 100644
index 00000000000..6a616b201c9
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/cohorts_v13_9.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.png b/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.png
deleted file mode 100644
index 0f1f16bead6..00000000000
--- a/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_9.png b/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_9.png
new file mode 100644
index 00000000000..a295179dda3
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/dev_ops_adoption_v13_9.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md
index 098d758e42a..5cf5e33f2d2 100644
--- a/doc/user/admin_area/analytics/index.md
+++ b/doc/user/admin_area/analytics/index.md
@@ -12,6 +12,6 @@ Administrators have access to instance-wide analytics, as shown in **Admin Area
There are several kinds of statistics:
-- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage. **(CORE)**
-- [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing. **(CORE)**
-- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time. **(CORE)**
+- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage. **(FREE)**
+- [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing. **(FREE)**
+- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time. **(FREE)**
diff --git a/doc/user/admin_area/analytics/instance_statistics.md b/doc/user/admin_area/analytics/instance_statistics.md
index 44fd04198b1..e44dd891029 100644
--- a/doc/user/admin_area/analytics/instance_statistics.md
+++ b/doc/user/admin_area/analytics/instance_statistics.md
@@ -3,3 +3,6 @@ redirect_to: 'usage_trends.md'
---
This document was moved to [another location](usage_trends.md).
+
+<!-- This redirect file can be deleted after <2022-03-20>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/admin_area/analytics/usage_trends.md b/doc/user/admin_area/analytics/usage_trends.md
index aeb577b8183..0c0cae09c16 100644
--- a/doc/user/admin_area/analytics/usage_trends.md
+++ b/doc/user/admin_area/analytics/usage_trends.md
@@ -4,7 +4,7 @@ group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Usage Trends **(CORE)**
+# Usage Trends **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235754) in GitLab 13.5 behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46962) in GitLab 13.6.
diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md
index 7adc9ad59a5..a7c93160b69 100644
--- a/doc/user/admin_area/analytics/user_cohorts.md
+++ b/doc/user/admin_area/analytics/user_cohorts.md
@@ -4,19 +4,19 @@ 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
---
-# Cohorts **(CORE)**
+# Cohorts **(FREE)**
As a benefit of having the [usage ping active](../settings/usage_statistics.md),
you can analyze your users' GitLab activities over time.
-To see user cohorts, go to **Admin Area > Analytics > Cohorts**.
+To see user cohorts, go to **Admin Area > Overview > Users**.
## Overview
How do you interpret the user cohorts table? Let's review an example with the
following user cohorts:
-![User cohort example](img/cohorts_v13_4.png)
+![User cohort example](img/cohorts_v13_9.png)
For the cohort of March 2020, three users were added to this server and have
been active since this month. One month later (April 2020), two users are still
diff --git a/doc/user/admin_area/appearance.md b/doc/user/admin_area/appearance.md
index b7f5afe7b70..e2e96f980f5 100644
--- a/doc/user/admin_area/appearance.md
+++ b/doc/user/admin_area/appearance.md
@@ -6,7 +6,7 @@ type: howto
disqus_identifier: 'https://docs.gitlab.com/ee/customization/branded_login_page.html'
---
-# GitLab Appearance **(CORE ONLY)**
+# GitLab Appearance **(FREE SELF)**
There are several options for customizing the appearance of a self-managed instance
of GitLab. These settings are accessed from the **Admin Area** in the **Appearance**
@@ -20,7 +20,7 @@ used (less than 1MB) and it is automatically resized.
![Navigation bar header logo screenshot](img/appearance_header_logo_v12_3.png)
-Once you select and upload an image, click **Update appearance settings** at the bottom
+After you select and upload an image, click **Update appearance settings** at the bottom
of the page to activate it in the GitLab instance.
NOTE:
@@ -41,8 +41,7 @@ of the page to activate it in the GitLab instance.
## System header and footer messages
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5023) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.7.
-> - [Added](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55057) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55057) to GitLab Free in 11.9.
You can add a small header message, a small footer message, or both, to the interface
of your GitLab instance. These messages appear on all projects and pages of the
diff --git a/doc/user/admin_area/broadcast_messages.md b/doc/user/admin_area/broadcast_messages.md
index c96c57a99eb..6f6aed68620 100644
--- a/doc/user/admin_area/broadcast_messages.md
+++ b/doc/user/admin_area/broadcast_messages.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Broadcast Messages **(CORE ONLY)**
+# Broadcast Messages **(FREE SELF)**
GitLab can display broadcast messages to all users of a GitLab instance. There are two types of broadcast messages:
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index 70bb070b13e..02659276b53 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Credentials inventory **(ULTIMATE ONLY)**
+# Credentials inventory **(ULTIMATE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20912) in GitLab 12.6.
diff --git a/doc/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
index a9bc2ecf324..26551d828bf 100644
--- a/doc/user/admin_area/custom_project_templates.md
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Custom instance-level project templates **(PREMIUM ONLY)**
+# Custom instance-level project templates **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2.
diff --git a/doc/user/admin_area/diff_limits.md b/doc/user/admin_area/diff_limits.md
index b5fcab58535..83b1869c7f2 100644
--- a/doc/user/admin_area/diff_limits.md
+++ b/doc/user/admin_area/diff_limits.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Diff limits administration **(CORE ONLY)**
+# Diff limits administration **(FREE SELF)**
You can set a maximum size for display of diff files (patches).
@@ -13,25 +13,25 @@ For details about diff files, [View changes between files](../project/merge_requ
## Maximum diff patch size
-Diff files which exceed this value will be presented as 'too large' and won't
-be expandable. Instead of an expandable view, a link to the blob view will be
+Diff files which exceed this value are presented as 'too large' and cannot
+be expandable. Instead of an expandable view, a link to the blob view is
shown.
-Patches greater than 10% of this size will be automatically collapsed, and a
-link to expand the diff will be presented.
+Patches greater than 10% of this size are automatically collapsed, and a
+link to expand the diff is presented.
+This affects merge requests and branch comparison views.
-NOTE:
-Merge requests and branch comparison views will be affected.
-
-WARNING:
-This setting is experimental. An increased maximum will increase resource
-consumption of your instance. Keep this in mind when adjusting the maximum.
+To set the maximum diff patch size:
1. Go to **Admin Area > Settings > General**.
1. Expand **Diff limits**.
1. Enter a value for **Maximum diff patch size**, measured in bytes.
1. Click on **Save changes**.
+WARNING:
+This setting is experimental. An increased maximum increases resource
+consumption of your instance. Keep this in mind when adjusting the maximum.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/admin_area/geo_nodes.md b/doc/user/admin_area/geo_nodes.md
index 81e987d25d6..f41170da975 100644
--- a/doc/user/admin_area/geo_nodes.md
+++ b/doc/user/admin_area/geo_nodes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo nodes Admin Area **(PREMIUM ONLY)**
+# Geo nodes Admin Area **(PREMIUM SELF)**
You can configure various settings for GitLab Geo nodes. For more information, see
[Geo documentation](../../administration/geo/index.md).
diff --git a/doc/user/admin_area/img/impersonate_user_button_v13_8.png b/doc/user/admin_area/img/impersonate_user_button_v13_8.png
new file mode 100644
index 00000000000..475315a0c0f
--- /dev/null
+++ b/doc/user/admin_area/img/impersonate_user_button_v13_8.png
Binary files differ
diff --git a/doc/user/admin_area/img/license_details.png b/doc/user/admin_area/img/license_details.png
deleted file mode 100644
index 3e980d9316d..00000000000
--- a/doc/user/admin_area/img/license_details.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/license_details_v13_8.png b/doc/user/admin_area/img/license_details_v13_8.png
new file mode 100644
index 00000000000..00421d8a41d
--- /dev/null
+++ b/doc/user/admin_area/img/license_details_v13_8.png
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 40cb6bd0853..b5e51e8d4c0 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab Admin Area **(CORE ONLY)**
+# GitLab Admin Area **(FREE SELF)**
The Admin Area provides a web UI for administering some features of GitLab self-managed instances.
@@ -24,20 +24,20 @@ The Admin Area is made up of the following sections:
| Section | Description |
|:-----------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **{overview}** [Overview](#overview-section) | View your GitLab [Dashboard](#admin-dashboard), and administer [projects](#administering-projects), [users](#administering-users), [groups](#administering-groups), [jobs](#administering-jobs), [runners](#administering-runners), and [Gitaly servers](#administering-gitaly-servers). |
-| **{monitor}** Monitoring | View GitLab [system information](#system-info), and information on [background jobs](#background-jobs), [logs](#logs), [health checks](monitoring/health_check.md), [requests profiles](#requests-profiles), and [audit events](#audit-events). |
+| **{monitor}** Monitoring | View GitLab [system information](#system-information), and information on [background jobs](#background-jobs), [logs](#logs), [health checks](monitoring/health_check.md), [requests profiles](#requests-profiles), and [audit events](#audit-events). |
| **{messages}** Messages | Send and manage [broadcast messages](broadcast_messages.md) for your users. |
| **{hook}** System Hooks | Configure [system hooks](../../system_hooks/system_hooks.md) for many events. |
| **{applications}** Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. |
| **{slight-frown}** Abuse Reports | Manage [abuse reports](abuse_reports.md) submitted by your users. |
| **{license}** License **(STARTER ONLY)** | 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 **(STARTER ONLY)** | Configure pre-defined Git [push rules](../../push_rules/push_rules.md) for projects. Also, configure [merge requests approvers rules](merge_requests_approvals.md). **(PREMIUM ONLY)** |
-| **{location-dot}** Geo **(PREMIUM ONLY)** | Configure and maintain [Geo nodes](geo_nodes.md). |
-| **{key}** Deploy Keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). |
-| **{lock}** Credentials **(ULTIMATE ONLY)** | View [credentials](credentials_inventory.md) that can be used to access your instance. |
+| **{push-rules}** Push rules **(STARTER ONLY)** | Configure pre-defined Git [push rules](../../push_rules/push_rules.md) for projects. Also, configure [merge requests approvers rules](merge_requests_approvals.md). **(PREMIUM SELF)** |
+| **{location-dot}** Geo **(PREMIUM SELF)** | Configure and maintain [Geo nodes](geo_nodes.md). |
+| **{key}** Deploy keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). |
+| **{lock}** Credentials **(ULTIMATE SELF)** | View [credentials](credentials_inventory.md) that can be used to access your instance. |
| **{template}** Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
| **{labels}** Labels | Create and maintain [labels](labels.md) for your GitLab instance. |
-| **{appearance}** Appearance | Customize [GitLab appearance](appearance.md). |
+| **{appearance}** Appearance | Customize [GitLab appearance](appearance.md). |
| **{settings}** Settings | Modify the [settings](settings/index.md) for your GitLab instance. |
## Admin Dashboard
@@ -144,6 +144,19 @@ To search for users, enter your criteria in the search field. The user search is
insensitive, and applies partial matching to name and username. To search for an email address,
you must provide the complete email address.
+#### User impersonation
+
+An administrator can "impersonate" any other user, including other administrator users.
+This allows the administrator to "see what the user sees," and take actions on behalf of the user.
+You can impersonate a user in the following ways:
+
+- Through the UI, by selecting **Admin Area > Overview > Users > Select a user > Impersonate**.
+- With the API, using [impersonation tokens](../../api/README.md#impersonation-tokens).
+
+All impersonation activities are [captured with audit events](../../administration/audit_events.md#impersonation-data).
+
+![user impersonation button](img/impersonate_user_button_v13_8.png)
+
#### Users statistics
The **Users statistics** page provides an overview of user accounts by role. These statistics are
@@ -242,7 +255,7 @@ For each runner, the following attributes are listed:
| Projects | Projects to which the runner is assigned |
| Jobs | Total of jobs run by the runner |
| Tags | Tags associated with the runner |
-| Last contact | Timestamp indicating when the GitLab instance last contacted the runner |
+| Last contact | Timestamp indicating when the runner last contacted the GitLab instance |
You can also edit, pause, or remove each runner.
@@ -267,7 +280,7 @@ For each Gitaly server, the following details are listed:
The following topics document the **Monitoring** section of the Admin Area.
-### System Info
+### System Information
The **System Info** page provides the following statistics:
@@ -300,7 +313,9 @@ The Sidekiq dashboard consists of the following elements:
### Logs
-The **Logs** page provides access to the following log files:
+Since GitLab 13.0, **Log** view has been removed from the admin dashboard since the logging does not work in multi-node setups and could cause confusion for administrators by displaying partial information.
+
+For multi-node systems we recommend ingesting the logs into services like Elasticsearch and Splunk.
| Log file | Contents |
| :---------------------- | :------- |
@@ -312,7 +327,7 @@ The **Logs** page provides access to the following log files:
| `integrations_json.log` | Activity between GitLab and integrated systems |
| `kubernetes.log` | Kubernetes activity |
-The contents of these log files can be useful when troubleshooting a problem. Access is available to GitLab admins, without requiring direct access to the log files.
+The contents of these log files can be useful when troubleshooting a problem.
For details of these log files and their contents, see [Log system](../../administration/logs.md).
@@ -322,6 +337,6 @@ The content of each log file is listed in chronological order. To minimize perfo
The **Requests Profiles** page contains the token required for profiling. For more details, see [Request Profiling](../../administration/monitoring/performance/request_profiling.md).
-### Audit Events **(PREMIUM ONLY)**
+### Audit Events **(PREMIUM SELF)**
The **Audit Events** page lists changes made within the GitLab server. With this information you can control, analyze, and track every change.
diff --git a/doc/user/admin_area/labels.md b/doc/user/admin_area/labels.md
index cc9735df9d6..b5dbf835d70 100644
--- a/doc/user/admin_area/labels.md
+++ b/doc/user/admin_area/labels.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Labels administration **(CORE ONLY)**
+# Labels administration **(FREE SELF)**
In the Admin Area, you can manage labels for the GitLab instance. For more details, see [Labels](../project/labels.md).
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index d06b0c844ec..505f54e9ae9 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -13,7 +13,7 @@ you are running. To verify, sign in to GitLab and browse to `/help`. The GitLab
are listed at the top of the **Help** page.
If you are running GitLab Community Edition (CE), upgrade your installation to
-GitLab Enterprise Edition (EE). For more details, see [Upgrading between editions](../../update/README.md#upgrading-between-editions).
+GitLab Enterprise Edition (EE). For more details, see [Upgrading between editions](../../update/index.md#upgrading-between-editions).
If you have questions or need assistance upgrading from GitLab CE to EE please [contact GitLab Support](https://about.gitlab.com/support/#contact-support).
The license is a base64-encoded ASCII text file with a `.gitlab-license`
@@ -25,7 +25,7 @@ by **signing into your GitLab instance as an admin** or adding it at
installation time.
As of GitLab Enterprise Edition 9.4.0, a newly-installed instance without an
-uploaded license only has the Core features active. A trial license
+uploaded license only has the Free features active. A trial license
activates all Ultimate features, but after
[the trial expires](#what-happens-when-your-license-expires), some functionality
is locked.
@@ -86,13 +86,13 @@ These methods only add a license at the time of installation. Use the
After the license is uploaded, all GitLab Enterprise Edition functionality
is active until the end of the license period. When that period ends, the
-instance will [fall back](#what-happens-when-your-license-expires) to Core-only
+instance will [fall back](#what-happens-when-your-license-expires) to Free-only
functionality.
You can review the license details at any time in the **License** section of the
**Admin Area**.
-![License details](img/license_details.png)
+![License details](img/license_details_v13_8.png)
## Notification before the license expires
@@ -106,7 +106,7 @@ In case your license expires, GitLab locks down some features like Git pushes,
and issue creation, and displays a message to all administrators to inform of the expired license.
To get back all the previous functionality, you must upload a new license.
-To fall back to having only the Core features active, you must delete the
+To fall back to having only the Free features active, you must delete the
expired license(s).
### Remove a license
@@ -133,7 +133,7 @@ The banner disappears after the new license becomes active.
### There is no License tab in the Admin Area
If you originally installed Community Edition rather than Enterprise Edition you must
-[upgrade to Enterprise Edition](../../update/README.md#community-to-enterprise-edition)
+[upgrade to Enterprise Edition](../../update/index.md#community-to-enterprise-edition)
before uploading your license.
GitLab.com users can't upload and use a self-managed license. If you
diff --git a/doc/user/admin_area/merge_requests_approvals.md b/doc/user/admin_area/merge_requests_approvals.md
index 5264f3b770b..d6ffde7be95 100644
--- a/doc/user/admin_area/merge_requests_approvals.md
+++ b/doc/user/admin_area/merge_requests_approvals.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Merge request approval rules **(PREMIUM ONLY)**
+# Merge request approval rules **(PREMIUM SELF)**
> Introduced in [GitLab Premium](https://gitlab.com/gitlab-org/gitlab/-/issues/39060) 12.8.
diff --git a/doc/user/admin_area/monitoring/convdev.md b/doc/user/admin_area/monitoring/convdev.md
deleted file mode 100644
index d9c3950f2e4..00000000000
--- a/doc/user/admin_area/monitoring/convdev.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: '../analytics/dev_ops_report.md'
----
-
-Conversational Development Index was renamed to [DevOps Report](../analytics/dev_ops_report.md) in GitLab 12.6.
diff --git a/doc/user/admin_area/monitoring/dev_ops_report.md b/doc/user/admin_area/monitoring/dev_ops_report.md
deleted file mode 100644
index 2cc9f153de3..00000000000
--- a/doc/user/admin_area/monitoring/dev_ops_report.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../analytics/dev_ops_report.md'
----
-
-This document was moved to [another location](../analytics/dev_ops_report.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 3c08a330b13..2d4683911fb 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
-# Health Check **(CORE ONLY)**
+# Health Check **(FREE SELF)**
> - Liveness and readiness probes were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10416) in GitLab 9.1.
> - The `health_check` endpoint was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3888) in GitLab 8.8 and was
@@ -15,7 +15,7 @@ type: concepts, howto
GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the
-database connection, Redis connection, and access to the filesystem. These
+database connection, Redis connection, and access to the file system. These
endpoints [can be provided to schedulers like Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) to hold
traffic until the system is ready or restart the container as needed.
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 028858c96f6..70416c224c7 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Account and limit settings **(CORE ONLY)**
+# Account and limit settings **(FREE SELF)**
## Default projects limit
@@ -13,7 +13,8 @@ You can change the default maximum number of projects that users can create in t
Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**.
You can increase or decrease that `Default projects limit` value.
-- If you set `Default projects limit` to 0, users are not allowed to create projects in their users personal namespace. However, projects can still be created within a group.
+- If you set `Default projects limit` to 0, users are not allowed to create projects
+ in their users personal namespace. However, projects can still be created in a group.
## Max attachment size
@@ -22,8 +23,8 @@ Navigate to **Admin Area > Settings > General**, then expand **Account and Limit
From here, you can increase or decrease by changing the value in `Maximum attachment size (MB)`.
NOTE:
-If you choose a size larger than what is currently configured for the web server,
-you will likely get errors. See the [troubleshooting section](#troubleshooting) for more
+If you choose a size larger than the configured value for the web server,
+you may receive errors. See the [troubleshooting section](#troubleshooting) for more
details.
## Max push size
@@ -39,8 +40,8 @@ Navigate to **Admin Area > Settings > General**, then expand **Account and Limit
From here, you can increase or decrease by changing the value in `Maximum import size (MB)`.
NOTE:
-If you choose a size larger than what is currently configured for the web server,
-you will likely get errors. See the [troubleshooting section](#troubleshooting) for more
+If you choose a size larger than the configured value for the web server,
+you may receive errors. See the [troubleshooting section](#troubleshooting) for more
details.
## Personal Access Token prefix
@@ -62,14 +63,11 @@ to any PAT generated in the system by any user:
It is also possible to configure the prefix via the [settings API](../../../api/settings.md)
using the `personal_access_token_prefix` field.
-## Repository size limit **(STARTER ONLY)**
+## Repository size limit **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/740) in [GitLab Enterprise Edition 8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#limit-project-size-ee).
-
-Repositories within your GitLab instance can grow quickly, especially if you are
+Repositories in your GitLab instance can grow quickly, especially if you are
using LFS. Their size can grow exponentially, rapidly consuming available storage.
-
-To avoid this from happening, you can set a hard limit for your repositories' size.
+To prevent this from happening, you can set a hard limit for your repositories' size.
This limit can be set globally, per group, or per project, with per project limits
taking the highest priority.
@@ -88,7 +86,7 @@ For instance, consider the following workflow:
Only a GitLab administrator can set those limits. Setting the limit to `0` means
there are no restrictions.
-These settings can be found within:
+These settings can be found in:
- Each project's settings:
1. From the Project's homepage, navigate to **Settings > General**.
@@ -104,9 +102,9 @@ These settings can be found within:
1. Fill in the **Size limit per repository (MB)** field.
1. Click **Save changes**.
-The first push of a new project, including LFS objects, will be checked for size
-and **will** be rejected if the sum of their sizes exceeds the maximum allowed
-repository size.
+The first push of a new project, including LFS objects, is checked for size.
+If the sum of their sizes exceeds the maximum allowed repository size, the push
+is rejected.
NOTE:
The repository size limit includes repository files and LFS, but does not include artifacts, uploads,
@@ -121,29 +119,46 @@ For GitLab.com repository size limits, see [accounts and limit settings](../../g
### 413 Request Entity Too Large
-If you are attaching a file to a comment or reply in GitLab and receive the `413 Request Entity Too Large`
-error, it is likely caused by having a [max attachment size](#max-attachment-size)
-larger than what the web server is configured to allow.
+When attaching a file to a comment or reply in GitLab displays a `413 Request Entity Too Large`
+error, the [max attachment size](#max-attachment-size)
+is probably larger than the web server's allowed value.
-If you wanted to increase the max attachment size to 200m in a GitLab
-[Omnibus](https://docs.gitlab.com/omnibus/) install, for example, you might need to
+To increase the max attachment size to 200 MB in a
+[Omnibus GitLab](https://docs.gitlab.com/omnibus/) install, you may need to
add the line below to `/etc/gitlab/gitlab.rb` before increasing the max attachment size:
```ruby
nginx['client_max_body_size'] = "200m"
```
-## Limiting lifetime of personal access tokens **(ULTIMATE ONLY)**
+## Customize session duration for Git Operations when 2FA is enabled **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296669) in GitLab 13.9.
+> - It's deployed behind a feature flag, 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](../../../security/two_factor_authentication.md#enable-or-disable-two-factor-authentication-2fa-for-git-operations)
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
+GitLab administrators can choose to customize the session duration (in minutes) for Git operations when 2FA is enabled. The default is 15 and this can be set to a value between 1 and 10080.
+
+To set a limit on how long these sessions are valid:
+
+1. Navigate to **Admin Area > Settings > General**.
+1. Expand the **Account and limit** section.
+1. Fill in the **Session duration for Git operations when 2FA is enabled (minutes)** field.
+1. Click **Save changes**.
+
+## Limiting lifetime of personal access tokens **(ULTIMATE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab Ultimate 12.6.
Users can optionally specify an expiration date for
[personal access tokens](../../profile/personal_access_tokens.md).
This expiration date is not a requirement, and can be set to any arbitrary date.
-Since personal access tokens are the only token needed for programmatic access to GitLab,
-organizations with security requirements may want to enforce more protection to require
-regular rotation of these tokens.
+Personal access tokens are the only tokens needed for programmatic access to GitLab.
+However, organizations with security requirements may want to enforce more protection by
+requiring the regular rotation of these tokens.
### Setting a limit
@@ -157,48 +172,40 @@ To set a limit on how long personal access tokens are valid:
1. Fill in the **Maximum allowable lifetime for personal access tokens (days)** field.
1. Click **Save changes**.
-Once a lifetime for personal access tokens is set, GitLab will:
+Once a lifetime for personal access tokens is set, GitLab:
-- Apply the lifetime for new personal access tokens, and require users to set an expiration date
+- Applies the lifetime for new personal access tokens, and require users to set an expiration date
and a date no later than the allowed lifetime.
- After three hours, revoke old tokens with no expiration date or with a lifetime longer than the
allowed lifetime. Three hours is given to allow administrators to change the allowed lifetime,
or remove it, before revocation takes place.
-## Optional enforcement of Personal Access Token expiry **(ULTIMATE ONLY)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
-> - It is deployed behind a feature flag, disabled by default.
-> - It is disabled on GitLab.com.
-> - It is not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature). **(CORE ONLY)**
+## Enforcement of SSH key expiration **(ULTIMATE SELF)**
-GitLab administrators can choose to prevent personal access tokens from expiring automatically. The tokens will be usable after the expiry date, unless they are revoked explicitly.
+GitLab administrators can choose to enforce the expiration of SSH keys after their expiration dates.
+If you enable this feature, this disables all _expired_ SSH keys.
To do this:
1. Navigate to **Admin Area > Settings > General**.
1. Expand the **Account and limit** section.
-1. Uncheck the **Enforce personal access token expiration** checkbox.
+1. Select the **Enforce SSH key expiration** checkbox.
-### Enable or disable optional enforcement of Personal Access Token expiry Feature **(CORE ONLY)**
+## Optional enforcement of Personal Access Token expiry **(ULTIMATE SELF)**
-Optional Enforcement of Personal Access Token Expiry is deployed behind a feature flag and is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can enable it for your instance from the [rails console](../../../administration/feature_flags.md#start-the-gitlab-rails-console).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) in GitLab Ultimate 13.1.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/296881) in GitLab 13.9.
-To enable it:
+GitLab administrators can choose to prevent personal access tokens from expiring
+automatically. The tokens are usable after the expiry date, unless they are revoked explicitly.
-```ruby
-Feature.enable(:enforce_pat_expiration)
-```
-
-To disable it:
+To do this:
-```ruby
-Feature.disable(:enforce_pat_expiration)
-```
+1. Navigate to **Admin Area > Settings > General**.
+1. Expand the **Account and limit** section.
+1. Uncheck the **Enforce personal access token expiration** checkbox.
-## Disabling user profile name changes **(PREMIUM ONLY)**
+## Disabling user profile name changes **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24605) in GitLab 12.7.
@@ -210,4 +217,6 @@ To do this:
1. Check the **Prevent users from changing their profile name** checkbox.
NOTE:
-When this ability is disabled, GitLab administrators will still be able to update the name of any user in their instance via the [Admin UI](../index.md#administering-users) or the [API](../../../api/users.md#user-modification)
+When this ability is disabled, GitLab administrators can still use the
+[Admin UI](../index.md#administering-users) or the
+[API](../../../api/users.md#user-modification) to update usernames.
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 6418be13ee9..761fc6477d6 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -5,14 +5,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Continuous Integration and Deployment Admin settings **(CORE ONLY)**
+# Continuous Integration and Deployment Admin settings **(FREE SELF)**
In this area, you will find settings for Auto DevOps, runners, and job artifacts.
You can find it in the **Admin Area > Settings > CI/CD**.
![Admin Area settings button](../img/admin_area_settings_button.png)
-## Auto DevOps **(CORE ONLY)**
+## Auto DevOps **(FREE SELF)**
To enable (or disable) [Auto DevOps](../../../topics/autodevops/index.md)
for all projects:
@@ -29,7 +29,7 @@ From now on, every existing project and newly created ones that don't have a
If you want to disable it for a specific project, you can do so in
[its settings](../../../topics/autodevops/index.md#enablingdisabling-auto-devops).
-## Maximum artifacts size **(CORE ONLY)**
+## Maximum artifacts size **(FREE SELF)**
The maximum size of the [job artifacts](../../../administration/job_artifacts.md)
can be set at:
@@ -65,7 +65,7 @@ To change it at the:
NOTE:
The setting at all levels is only available to GitLab administrators.
-## Default artifacts expiration **(CORE ONLY)**
+## Default artifacts expiration **(FREE SELF)**
The default expiration time of the [job artifacts](../../../administration/job_artifacts.md)
can be set in the Admin Area of your GitLab instance. The syntax of duration is
@@ -86,9 +86,28 @@ be updated for artifacts created before this setting was changed.
The administrator may need to manually search for and expire previously-created
artifacts, as described in the [troubleshooting documentation](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#remove-artifacts-more-than-a-week-old).
-## Shared runners pipeline minutes quota **(STARTER ONLY)**
+## Keep the latest artifacts for all jobs in the latest successful pipelines **(CORE ONLY)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1078) in GitLab Starter 8.16.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50889) in GitLab Core 13.9.
+
+When enabled (default), the artifacts for the most recent pipeline for a ref are
+locked against deletion and kept regardless of the expiry time.
+
+When disabled, the latest artifacts for any **new** successful or fixed pipelines
+are allowed to expire.
+
+This setting takes precedence over the [project level setting](../../../ci/pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
+If disabled at the instance level, you cannot enable this per-project.
+
+When you disable the feature, the latest artifacts do not immediately expire.
+A new pipeline must run before the latest artifacts can expire and be deleted.
+
+NOTE:
+All application settings have a [customizable cache expiry interval](../../../administration/application_settings_cache.md) which can delay the settings affect.
+
+## Shared runners pipeline minutes quota **(PREMIUM SELF)**
+
+> [Moved](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) to GitLab Premium in 13.9.
If you have enabled shared runners for your GitLab instance, you can limit their
usage by setting a maximum number of pipeline minutes that a group can use on
@@ -126,7 +145,7 @@ a group in the **Usage Quotas** page available to the group page settings list.
![Group pipelines quota](img/group_pipelines_quota.png)
-## Archive jobs **(CORE ONLY)**
+## Archive jobs **(FREE SELF)**
Archiving jobs is useful for reducing the CI/CD footprint on the system by
removing some of the capabilities of the jobs (metadata needed to run the job),
@@ -156,21 +175,9 @@ Area of your GitLab instance (`.gitlab-ci.yml` if not set):
1. Input the new path in the **Default CI configuration path** field.
1. Hit **Save changes** for the changes to take effect.
-It is also possible to specify a [custom CI configuration path for a specific project](../../../ci/pipelines/settings.md#custom-ci-configuration-path).
+It is also possible to specify a [custom CI/CD configuration path for a specific project](../../../ci/pipelines/settings.md#custom-cicd-configuration-path).
-<!-- ## 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. -->
-
-## Required pipeline configuration **(PREMIUM ONLY)**
+## Required pipeline configuration **(PREMIUM SELF)**
WARNING:
This feature is being re-evaluated in favor of a different
@@ -204,18 +211,18 @@ To set required pipeline configuration:
## Package Registry configuration
-### NPM Forwarding **(PREMIUM ONLY)**
+### npm Forwarding **(PREMIUM SELF)**
-GitLab administrators can disable the forwarding of NPM requests to [npmjs.com](https://www.npmjs.com/).
+GitLab administrators can disable the forwarding of npm requests to [npmjs.com](https://www.npmjs.com/).
To disable it:
1. Go to **Admin Area > Settings > CI/CD**.
1. Expand the **Package Registry** section.
-1. Uncheck **Enable forwarding of NPM package requests to npmjs.org**.
+1. Uncheck **Enable forwarding of npm package requests to npmjs.org**.
1. Click **Save changes**.
-![NPM package requests forwarding](img/admin_package_registry_npm_package_requests_forward.png)
+![npm package requests forwarding](img/admin_package_registry_npm_package_requests_forward.png)
### Package file size limits
@@ -228,3 +235,14 @@ To set the maximum file size:
1. Find the package type you would like to adjust.
1. Enter the maximum file size, in bytes.
1. Click **Save size limits**.
+
+## Troubleshooting
+
+### 413 Request Entity Too Large
+
+When build jobs fail with the following error,
+increase the [maximum artifacts size](#maximum-artifacts-size).
+
+```plaintext
+Uploading artifacts as "archive" to coordinator... too large archive <job-id> responseStatus=413 Request Entity Too Large status=413" at end of a build job on pipeline when trying to store artifacts to <object-storage>.
+```
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 4ebfac57715..2eaff417ba3 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -5,7 +5,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Email **(CORE ONLY)**
+# Email **(FREE SELF)**
You can customize some of the content in emails sent from your GitLab instance.
@@ -13,7 +13,7 @@ You can customize some of the content in emails sent from your GitLab instance.
The logo in the header of some emails can be customized, see the [logo customization section](../appearance.md#navigation-bar).
-## Custom additional text **(PREMIUM ONLY)**
+## Custom additional text **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5031) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.7.
@@ -40,7 +40,7 @@ In order to change this option:
1. Select **Save changes**.
NOTE:
-Once the hostname gets configured, every private commit email using the previous hostname, will not get
+After the hostname gets 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
`Check whether author is a GitLab user` and `Check whether committer is the current authenticated user`.
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index 18ae7e6f05a..0975b93f98f 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -5,10 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# External authorization control **(CORE ONLY)**
+# External authorization control **(FREE SELF)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4216) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27056) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27056) to GitLab Free in 11.10.
In highly controlled environments, it may be necessary for access policy to be
controlled by an external service that permits access based on project
diff --git a/doc/user/admin_area/settings/gitaly_timeouts.md b/doc/user/admin_area/settings/gitaly_timeouts.md
index d196dc1730e..3570634b9ba 100644
--- a/doc/user/admin_area/settings/gitaly_timeouts.md
+++ b/doc/user/admin_area/settings/gitaly_timeouts.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Gitaly timeouts **(CORE ONLY)**
+# Gitaly timeouts **(FREE SELF)**
[Gitaly](../../../administration/gitaly/index.md) timeouts are configurable. The timeouts can be
configured to make sure that long running Gitaly calls don't needlessly take up resources.
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 9a661fa9716..3377b1674db 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index
---
-# Admin Area settings **(CORE ONLY)**
+# Admin Area settings **(FREE SELF)**
As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. To do so, select **Admin Area > Settings**.
@@ -36,7 +36,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [Elasticsearch](../../../integration/elasticsearch.md#enabling-advanced-search) | Elasticsearch integration. Elasticsearch AWS IAM. |
| [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) | Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). |
| [PlantUML](../../../administration/integration/plantuml.md#gitlab) | Allow rendering of PlantUML diagrams in AsciiDoc and Markdown documents. |
-| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE ONLY)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
+| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE SAAS)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
| [Third party offers](third_party_offers.md) | Control the display of third party offers. |
| [Snowplow](../../../development/snowplow.md) | Configure the Snowplow integration. |
| [Google GKE](../../project/clusters/add_gke_clusters.md) | Google GKE integration allows you to provision GKE clusters from GitLab. |
@@ -52,7 +52,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. |
| [Repository static objects](../../../administration/static_objects_external_storage.md) | Serve repository static objects (for example, archives, blobs, ...) from an external storage (for example, a CDN). |
-## Templates **(PREMIUM ONLY)**
+## Templates **(PREMIUM SELF)**
| Option | Description |
| ------ | ----------- |
@@ -64,7 +64,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| Option | Description |
| ------ | ----------- |
| [Continuous Integration and Deployment](continuous_integration.md) | Auto DevOps, runners and job artifacts. |
-| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) **(PREMIUM ONLY)** | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/README.md). This pipeline configuration is run after the project's own configuration. |
+| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) **(PREMIUM SELF)** | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/README.md). This pipeline configuration is run after the project's own configuration. |
| [Package Registry](continuous_integration.md#package-registry-configuration) | Settings related to the use and experience of using the GitLab Package Registry. Note there are [risks involved](../../packages/container_registry/index.md#use-with-external-container-registries) in enabling some of these settings. |
## Reporting
@@ -80,7 +80,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| ------ | ----------- |
| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) | Enable and configure Prometheus metrics. |
| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) | Enable and configure Grafana. |
-| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-via-the-admin-panel) | Enable access to the Performance Bar for a given group. |
+| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-via-the-admin-area) | Enable access to the Performance Bar for a given group. |
| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#creating-the-self-monitoring-project) | Enable or disable instance self monitoring. |
| [Usage statistics](usage_statistics.md) | Enable or disable version check and usage ping. |
| [Pseudonymizer data collection](../../../administration/pseudonymizer.md) **(ULTIMATE)** | Enable or disable the Pseudonymizer data collection. |
@@ -94,6 +94,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [Outbound requests](../../../security/webhooks.md) | Allow requests to the local network from hooks and services. |
| [Protected Paths](protected_paths.md) | Configure paths to be protected by Rack Attack. |
| [Incident Management](../../../operations/incident_management/index.md) Limits | Configure limits on the number of inbound alerts able to be sent to a project. |
+| [Notes creation limit](rate_limit_on_notes_creation.md)| Set a rate limit on the note creation requests. |
## Geo
diff --git a/doc/user/admin_area/settings/instance_template_repository.md b/doc/user/admin_area/settings/instance_template_repository.md
index 42fa7fe6f54..7630f0c2fbd 100644
--- a/doc/user/admin_area/settings/instance_template_repository.md
+++ b/doc/user/admin_area/settings/instance_template_repository.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Instance template repository **(PREMIUM ONLY)**
+# Instance template repository **(PREMIUM SELF)** **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5986) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
@@ -22,10 +22,9 @@ select the project to serve as the custom template repository.
![File templates in the Admin Area](img/file_template_admin_area.png)
-Once a project has been selected, you can add custom templates to the repository,
-and they will appear in the appropriate places in the
-[frontend](../../project/repository/web_editor.md#template-dropdowns) and
-[API](../../../api/settings.md).
+After that, you can add custom templates to the selected repository and use them for the entire instance.
+They will be available on the [Web Editor's dropdown](../../project/repository/web_editor.md#template-dropdowns)
+and through the [API settings](../../../api/settings.md).
Templates must be added to a specific subdirectory in the repository,
corresponding to the kind of template. The following types of custom templates
@@ -61,9 +60,7 @@ extension and not be empty. So, the hierarchy should look like this:
|-- another_metrics-dashboard.yml
```
-Once this is established, the list of custom templates will be included when
-creating a new file and the template type is selected. These will appear at the
-top of the list.
+Your custom templates will be displayed on the dropdown menu when a new file is added through the GitLab UI:
![Custom template dropdown menu](img/file_template_user_dropdown.png)
diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md
index adb192f5b4a..18491f92650 100644
--- a/doc/user/admin_area/settings/project_integration_management.md
+++ b/doc/user/admin_area/settings/project_integration_management.md
@@ -17,7 +17,7 @@ for all projects that didn't have it already enabled.
Only the complete settings for an integration can be inherited. Per-field inheritance is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137).
-## Manage instance-level default settings for a project integration **(CORE ONLY)**
+## Manage instance-level default settings for a project integration **(FREE SELF)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2137) in GitLab 13.3 for project-level integrations.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level integrations.
diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md
index a03156511e2..061e9fa05d3 100644
--- a/doc/user/admin_area/settings/protected_paths.md
+++ b/doc/user/admin_area/settings/protected_paths.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Protected paths **(CORE ONLY)**
+# Protected paths **(FREE SELF)**
Rate limiting is a common technique used to improve the security and durability
of a web application. For more details, see
diff --git a/doc/user/admin_area/settings/push_event_activities_limit.md b/doc/user/admin_area/settings/push_event_activities_limit.md
index 484bb7b0a14..1d6424face0 100644
--- a/doc/user/admin_area/settings/push_event_activities_limit.md
+++ b/doc/user/admin_area/settings/push_event_activities_limit.md
@@ -5,21 +5,21 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Push event activities limit and bulk push events
+# Push event activities limit and bulk push events **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31007) in GitLab 12.4.
-This allows you to set the number of changes (branches or tags) in a single push
-to determine whether individual push events or bulk push event will be created.
-Bulk push events will be created if it surpasses that value.
+Set the number of branches or tags to limit the number of single push events
+allowed at once. If the number of events is greater than this, GitLab creates
+bulk push event instead.
For example, if 4 branches are pushed and the limit is currently set to 3,
you'll see the following in the activity feed:
![Bulk push event](img/bulk_push_event_v12_4.png)
-With this feature, when a single push includes a lot of changes (e.g. 1,000
-branches), only 1 bulk push event will be created instead of creating 1,000 push
+With this feature, when a single push includes a lot of changes (for example, 1,000
+branches), only 1 bulk push event is created instead of 1,000 push
events. This helps in maintaining good system performance and preventing spam on
the activity feed.
diff --git a/doc/user/admin_area/settings/rate_limit_on_notes_creation.md b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
new file mode 100644
index 00000000000..54b5da35dac
--- /dev/null
+++ b/doc/user/admin_area/settings/rate_limit_on_notes_creation.md
@@ -0,0 +1,32 @@
+---
+type: reference
+stage: Plan
+group: Project Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Rate limits on note creation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53637) in GitLab 13.9.
+
+This setting allows you to rate limit the requests to the note creation endpoint.
+
+To change the note creation rate limit:
+
+1. Go to **Admin Area > Settings > Network**.
+1. Expand the **Notes Rate Limits** section.
+1. Enter the new value.
+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 using the
+[Projects::NotesController#create](https://gitlab.com/gitlab-org/gitlab/blob/master/app/controllers/projects/notes_controller.rb)
+action exceeding a rate of 300 per minute are blocked. Access to the endpoint is allowed after one minute.
diff --git a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
index 9ffd46e9ba6..a9b23b3dc50 100644
--- a/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
+++ b/doc/user/admin_area/settings/rate_limits_on_raw_endpoints.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Rate limits on raw endpoints **(CORE ONLY)**
+# Rate limits on raw endpoints **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30829) in GitLab 12.2.
diff --git a/doc/user/admin_area/settings/sign_in_restrictions.md b/doc/user/admin_area/settings/sign_in_restrictions.md
index 92ad8eced95..a34a63f4543 100644
--- a/doc/user/admin_area/settings/sign_in_restrictions.md
+++ b/doc/user/admin_area/settings/sign_in_restrictions.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Sign-in restrictions **(CORE ONLY)**
+# Sign-in restrictions **(FREE SELF)**
You can use **Sign-in restrictions** to customize authentication restrictions for web interfaces as well as Git over HTTP(S).
@@ -27,7 +27,7 @@ You can restrict the password authentication for web interface and Git over HTTP
When this feature enabled, all users must use the [two-factor authentication](../../profile/account/two_factor_authentication.md).
-Once the two-factor authentication is configured as mandatory, the users are allowed
+After the two-factor authentication is configured as mandatory, users are allowed
to skip forced configuration of two-factor authentication for the configurable grace
period in hours.
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index ddd3dbda9cc..0945471b11b 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Sign-up restrictions **(CORE ONLY)**
+# Sign-up restrictions **(FREE SELF)**
You can enforce the following restrictions on sign ups:
@@ -50,12 +50,10 @@ To enforce confirmation of the email address used for new sign ups:
1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
1. Select the **Enable email restrictions for sign ups** checkbox, then select **Save changes**.
-## User cap **(CORE ONLY)**
+## User cap **(FREE SELF)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4315) in GitLab 13.7.
-> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-user-cap). **(CORE ONLY)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292600) in GitLab 13.9.
When the number of billable users reaches the user cap, any user who is added or requests access must be
[approved](../approving_users.md#approving-a-user) by an administrator before they can start using
@@ -64,29 +62,10 @@ their account.
If an administrator increases or removes the user cap, the users in pending approval state are
automatically approved in a background job.
-### Enable or disable User cap **(CORE ONLY)**
-
-User cap is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To disable it:
-
-```ruby
-Feature.disable(:admin_new_user_signups_cap)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:admin_new_user_signups_cap)
-```
-
## Soft email confirmation
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47003) in GitLab 12.2.
-> - It's [deployed behind a feature flag](../../..//user/feature_flags.md), disabled by default.
+> - It's [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-soft-email-confirmation).
@@ -94,7 +73,7 @@ Feature.enable(:admin_new_user_signups_cap)
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-The soft email confirmation improves the signup experience for new users by allowing
+The soft email confirmation improves the sign-up experience for new users by allowing
them to sign in without an immediate confirmation when an email confirmation is required.
GitLab shows the user a reminder to confirm their email address, and the user can't
create or update pipelines until their email address is confirmed.
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index b6826035116..3e0636ef7ac 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -5,9 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Enforce accepting Terms of Service **(CORE ONLY)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18570) in [GitLab Core](https://about.gitlab.com/pricing/) 10.8.
+# Enforce accepting Terms of Service **(FREE SELF)**
An admin can enforce acceptance of a terms of service and privacy policy. When this option is enabled, new and existing users must accept the terms.
diff --git a/doc/user/admin_area/settings/third_party_offers.md b/doc/user/admin_area/settings/third_party_offers.md
index 84511339842..59845a8d0d8 100644
--- a/doc/user/admin_area/settings/third_party_offers.md
+++ b/doc/user/admin_area/settings/third_party_offers.md
@@ -5,9 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Third party offers **(CORE ONLY)**
+# Third party offers **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20379) in [GitLab Core](https://about.gitlab.com/pricing/) 11.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20379) in GitLab Free 11.1.
Within GitLab, we inform users of available third-party offers they might find valuable in order
to enhance the development of their projects. An example is the Google Cloud Platform free credit
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 06b39d67228..2bb6adbc32b 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Usage statistics **(CORE ONLY)**
+# Usage statistics **(FREE SELF)**
GitLab Inc. periodically collects information about your instance in order
to perform various actions.
@@ -20,7 +20,7 @@ usage statistics to GitLab Inc.
If your GitLab instance is behind a proxy, set the appropriate [proxy configuration variables](https://docs.gitlab.com/omnibus/settings/environment-variables.html).
-## Version Check **(CORE ONLY)**
+## Version Check **(FREE SELF)**
If enabled, version check informs you if a new version is available and the
importance of it through a status. This is shown on the help page (i.e. `/help`)
@@ -59,7 +59,7 @@ sequenceDiagram
Version Application->>GitLab instance: Response (PNG/SVG)
```
-## Usage Ping **(CORE ONLY)**
+## Usage Ping **(FREE SELF)**
See [Usage Ping guide](../../../development/usage_ping.md).
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 e2040ef19d6..ba4ef890caa 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
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# User and IP rate limits **(CORE ONLY)**
+# User and IP rate limits **(FREE SELF)**
Rate limiting is a common technique used to improve the security and durability
of a web application. For more details, see
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 fe1841e7020..0fcdbf3ca90 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -5,22 +5,22 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Visibility and access controls **(CORE ONLY)**
+# Visibility and access controls **(FREE SELF)**
GitLab allows administrators to enforce specific controls.
To access the visibility and access control options:
-1. Log in to GitLab as an admin.
+1. Sign in to GitLab as a user with Administrator [permissions](../../permissions.md).
1. Go to **Admin Area > Settings > General**.
1. Expand the **Visibility and access controls** section.
## Default branch protection
This global option defines the branch protection that applies to every repository's default branch. [Branch protection](../../project/protected_branches.md) specifies which roles can push to branches and which roles can delete
-branches. In this case _Default_ refers to a repository's default branch, which in most cases is _master_.
+branches. In this case _Default_ refers to a repository's default branch, which in most cases is `master`.
-This setting applies only to each repositories' default branch. To protect other branches, you must configure branch protection in repository. For details, see [Protected Branches](../../project/protected_branches.md).
+This setting applies only to each repositories' default branch. To protect other branches, you must configure branch protection in repository. For details, see [protected branches](../../project/protected_branches.md).
To change the default branch protection:
@@ -31,7 +31,7 @@ For more details, see [Protected branches](../../project/protected_branches.md).
To change this setting for a specific group, see [Default branch protection for groups](../../group/index.md#changing-the-default-branch-protection-of-a-group)
-### Disable group owners from updating default branch protection **(PREMIUM ONLY)**
+### Disable group owners from updating default branch protection **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211944) in GitLab 13.0.
@@ -57,30 +57,30 @@ To change the default project creation protection:
For more details, see [Default project-creation level](../../group/index.md#default-project-creation-level).
-## Default project deletion protection **(PREMIUM ONLY)**
+## Default project deletion protection **(PREMIUM SELF)**
By default, a project can be deleted by anyone with the **Owner** role, either at the project or
group level.
-To ensure only admin users can delete projects:
+To ensure only Administrator users can delete projects:
1. Check the **Default project deletion protection** checkbox.
1. Click **Save changes**.
-## Default deletion delay **(PREMIUM ONLY)**
+## Default deletion delay **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6.
-By default, a project marked for deletion will be permanently removed with immediate effect.
-By default, a group marked for deletion will be permanently removed after 7 days.
+By default, a project marked for deletion is permanently removed with immediate effect.
+By default, a group marked for deletion is permanently removed after seven days.
WARNING:
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
-Projects within a group (but not a personal namespace) can be deleted after a delayed period, by [configuring in Group Settings](../../group/index.md#enabling-delayed-project-removal).
-
-The default period is 7 days, and can be changed. Setting this period to 0 will enable immediate removal
+Projects in a group (but not a personal namespace) can be deleted after a delayed period, by
+[configuring in Group Settings](../../group/index.md#enabling-delayed-project-removal).
+The default period is seven days, and can be changed. Setting this period to `0` enables immediate removal
of projects or groups.
To change this period:
@@ -124,10 +124,10 @@ For more details on group visibility, see [Public access](../../../public_access
## Restricted visibility levels
-To set the available visibility levels for projects, snippets, and selected pages:
+To set the restricted visibility levels for projects, snippets, and selected pages:
-1. Check the desired visibility levels.
-1. Click **Save changes**.
+1. Select the desired visibility levels to restrict.
+1. Select **Save changes**.
For more details on project visibility, see [Public access](../../../public_access/public_access.md).
@@ -149,13 +149,11 @@ For more details, see [Exporting a project and its data](../../../user/project/s
## Enabled Git access protocols
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4696) in GitLab 8.10.
-
With GitLab access restrictions, you can select with which protocols users can communicate with
GitLab.
-Disabling an access protocol does not block access to the server itself via those ports. The ports
-used for the protocol, SSH or HTTP(S), will still be accessible. The GitLab restrictions apply at the
+Disabling an access protocol does not block access to the server itself by using those ports. The ports
+used for the protocol, SSH or HTTP(S), are still accessible. The GitLab restrictions apply at the
application level.
To specify the enabled Git access protocols:
@@ -170,26 +168,26 @@ When both SSH and HTTP(S) are enabled, users can choose either protocol.
When only one protocol is enabled:
-- The project page will only show the allowed protocol's URL, with no option to
+- The project page shows only the allowed protocol's URL, with no option to
change it.
-- A tooltip will be shown when you hover over the URL's protocol, if an action
- on the user's part is required, e.g. adding an SSH key, or setting a password.
+- A tooltip is shown when you hover over the URL's protocol, if an action
+ on the user's part is required. For example, adding an SSH key or setting a password.
![Project URL with SSH only access](img/restricted_url.png)
-On top of these UI restrictions, GitLab will deny all Git actions on the protocol
+On top of these UI restrictions, GitLab denies all Git actions on the protocol
not selected.
WARNING:
-Starting with [GitLab 10.7](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18021),
-HTTP(S) protocol will be allowed for Git clone or fetch requests done by GitLab Runner
-from CI/CD jobs, even if _Only SSH_ was selected.
+GitLab versions [10.7 and later](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18021),
+allow the HTTP(S) protocol for Git clone or fetch requests done by GitLab Runner
+from CI/CD jobs, even if **Only SSH** was selected.
## Custom Git clone URL for HTTP(S)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18422) in GitLab 12.4.
-You can customize project Git clone URLs for HTTP(S). This will affect the clone
+You can customize project Git clone URLs for HTTP(S), which affects the clone
panel:
![Clone panel](img/clone_panel_v12_4.png)
@@ -225,10 +223,9 @@ For more details, see [SSH key restrictions](../../../security/ssh_keys_restrict
## Allow mirrors to be set up for projects
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3586) in GitLab 10.3.
-
-This option is enabled by default. By disabling it, both [pull and push mirroring](../../project/repository/repository_mirroring.md) will no longer
-work in every repository and can only be re-enabled by an admin on a per-project basis.
+This option is enabled by default. By disabling it, both
+[pull and push mirroring](../../project/repository/repository_mirroring.md) no longer
+work in every repository. They can only be re-enabled by an administrator user on a per-project basis.
![Mirror settings](img/mirror_settings.png)
diff --git a/doc/user/admin_area/user_cohorts.md b/doc/user/admin_area/user_cohorts.md
deleted file mode 100644
index a95501c0bde..00000000000
--- a/doc/user/admin_area/user_cohorts.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'analytics/user_cohorts.md'
----
-
-This document was moved to [another location](analytics/user_cohorts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
index beb2cbfdc58..0f19998749d 100644
--- a/doc/user/analytics/ci_cd_analytics.md
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# CI/CD Analytics
-## Pipeline success and duration charts **(CORE)**
+## Pipeline success and duration charts **(FREE)**
> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI/CD Analytics in GitLab 12.8.
@@ -22,6 +22,29 @@ View pipeline duration history:
![Pipeline duration](img/pipelines_duration_chart.png)
+## DORA4 Metrics
+
+Customer experience is a key metric. Users want to measure platform stability and other
+post-deployment performance KPIs, and set targets for customer behavior, experience, and financial
+impact. Tracking and measuring these indicators solves an important pain point. Similarly, creating
+views that manage products, not projects or repositories, provides users with a more relevant data set.
+Since GitLab is a tool for the entire DevOps life-cycle, information from different workflows is
+integrated and can be used to measure the success of the teams.
+
+The DevOps Research and Assessment ([DORA](https://cloud.google.com/blog/products/devops-sre/the-2019-accelerate-state-of-devops-elite-performance-productivity-and-scaling))
+team developed four key metrics that the industry has widely adopted. You can use these metrics as
+performance indicators for software development teams:
+
+- Deployment frequency: How often an organization successfully releases to production.
+- Lead time for changes: The amount of time it takes for code to reach production.
+- Change failure rate: The percentage of deployments that cause a failure in production.
+- Time to restore service: How long it takes an organization to recover from a failure in
+ production.
+
+GitLab plans to add support for all the DORA4 metrics at the project and group levels. GitLab added
+the first metric, deployment frequency, at the project and group scopes for [CI/CD charts](ci_cd_analytics.md#deployment-frequency-charts),
+the [Project API]( ../../api/dora4_project_analytics.md), and the [Group API]( ../../api/dora4_group_analytics.md).
+
## Deployment frequency charts **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.8.
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 745774480b0..19016c3aa26 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -6,22 +6,23 @@ info: To determine the technical writer assigned to the Stage/Group associated w
---
-# Code Review Analytics **(STARTER)**
+# Code Review Analytics **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38062) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38062) in GitLab 12.7.
+> - Moved to GitLab Premium in 13.9.
-Code Review Analytics makes it easy to view the longest-running reviews among open merge requests and
-enables you to:
+Use Code Review Analytics to view the longest-running reviews among open merge
+requests, and:
-1. Take action on individual merge requests.
-1. Reduce overall cycle time.
+- Take action on individual merge requests.
+- Reduce overall cycle time.
NOTE:
Initially, no data appears. Data is populated as users comment on open merge requests.
## Overview
-Code Review Analytics 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 Reporter access and above, 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.
To access Code Review Analytics, from your project's menu, go to **Project Analytics > Code Review**.
@@ -53,8 +54,3 @@ For example:
- Lots of comments or commits? Maybe the code is too complex.
- A particular author is involved? Maybe more training is required.
- Few comments and approvers? Maybe your team is understaffed.
-
-## Permissions
-
-- On [Starter or Bronze tier](https://about.gitlab.com/pricing/) and above.
-- By users with Reporter access and above.
diff --git a/doc/user/analytics/cycle_analytics.md b/doc/user/analytics/cycle_analytics.md
deleted file mode 100644
index 5c235f6708b..00000000000
--- a/doc/user/analytics/cycle_analytics.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../analytics/value_stream_analytics.md'
----
-
-This document was moved to [another location](../analytics/value_stream_analytics.md)
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index caa8972b220..f5da373ee6d 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -6,6 +6,28 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Analytics
+## Definitions
+
+When we describe GitLab analytics, we use the following terms:
+
+- Cycle time: The duration of your value stream, from start to finish. Often displayed in combination with "lead time." GitLab measures cycle time from issue creation to issue close. GitLab displays cycle time in [Value Stream Analytics](value_stream_analytics.md).
+- DORA (DevOps Research and Assessment) ["Four Keys"](https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance):
+ - Speed
+ - Deployment Frequency: How often an organization successfully releases to production.
+ - Lead Time for Changes: The time it takes for a commit to get into production. This differs from ordinary "lead time" as it "focuses on measuring only the time to deliver a feature once it has been developed",
+as described in ([Measuring DevOps Performance](https://devops.com/measuring-devops-performance/)).
+ - Stability
+ - Change Failure Rate: The percentage of deployments causing a failure in production.
+ - Time to Restore Service: How long it takes an organization to recover from a failure in production.
+- MTTC (Mean Time to Change): The average duration between idea and delivery. GitLab measures MTTC from issue creation to the issue's latest related merge request's deployment to production.
+- MTTD (Mean Time to Detect): The average duration that a bug goes undetected in production. GitLab measures MTTD from deployment of bug to issue creation.
+- MTTM (Mean Time To Merge): The average lifespan of a merge request. GitLab measures MTTM from merge request creation to merge request merge (and closed/un-merged merge requests are excluded). For more information, see [Merge Request Analytics](merge_request_analytics.md).
+- MTTR (Mean Time to Recover/Repair/Resolution/Resolve/Restore): The average duration that a bug is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
+- Lead time: The duration of the work itself. Often displayed in combination with "cycle time." GitLab measures from issue first merge request creation to issue close. Note: Obviously work started before the creation of the first merge request. We plan to start measuring from "issue first commit" as a better proxy, although still imperfect. GitLab displays lead time in [Value Stream Analytics](value_stream_analytics.md).
+- Throughput: The number of issues closed or merge requests merged (not closed) in some period of time. Often measured per sprint. GitLab displays merge request throughput in [Merge Request Analytics](merge_request_analytics.md).
+- Value Stream: The entire work process that is followed to deliver value to customers. For example, the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts with "plan" and ends with "monitor". GitLab helps you track your value stream using [Value Stream Analytics](value_stream_analytics.md).
+- Velocity: The total issue burden completed in some period of time. The burden is usually measured in points or weight, often per sprint. For example, your velocity may be "30 points per sprint". GitLab measures velocity as the total points/weight of issues closed in a given period of time.
+
## Instance-level analytics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in GitLab 12.2.
@@ -18,26 +40,27 @@ in one place.
## Group-level analytics
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195979) in GitLab 12.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195979) in GitLab 12.8.
+> - Moved to [GitLab Premium](https://about.gitlab.com/pricing/) due to Starter/Bronze being [discontinued](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) in 13.9.
The following analytics features are available at the group level:
-- [Contribution](../group/contribution_analytics/index.md). **(STARTER)**
+- [Contribution](../group/contribution_analytics/index.md). **(PREMIUM)**
- [Insights](../group/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
- [Productivity](productivity_analytics.md) **(PREMIUM)**
- [Repositories](../group/repositories_analytics/index.md) **(PREMIUM)**
-- [Value Stream](value_stream_analytics.md). **(PREMIUM)**
+- [Value Stream](../group/value_stream_analytics/index.md). **(PREMIUM)**
## Project-level analytics
The following analytics features are available at the project level:
-- [CI/CD](ci_cd_analytics.md). **(CORE)**
-- [Code Review](code_review_analytics.md). **(STARTER)**
+- [CI/CD](ci_cd_analytics.md). **(FREE)**
+- [Code Review](code_review_analytics.md). **(PREMIUM)**
- [Insights](../project/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
- [Merge Request](merge_request_analytics.md), enabled with the `project_merge_request_analytics`
- [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-locally-in-development). **(STARTER)**
-- [Repository](repository_analytics.md). **(CORE)**
-- [Value Stream](value_stream_analytics.md). **(CORE)**
+ [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-locally-in-development). **(PREMIUM)**
+- [Repository](repository_analytics.md). **(FREE)**
+- [Value Stream](value_stream_analytics.md). **(FREE)**
diff --git a/doc/user/analytics/issue_analytics.md b/doc/user/analytics/issue_analytics.md
index 0aa135ab88d..6c6911ff4f4 100644
--- a/doc/user/analytics/issue_analytics.md
+++ b/doc/user/analytics/issue_analytics.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/196561) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.9.
Issue Analytics is a bar graph which illustrates the number of issues created each month.
-The default timespan is 13 months, which includes the current month, and the 12 months
+The default time span is 13 months, which includes the current month, and the 12 months
prior.
To access the chart, navigate to your project sidebar and select **{chart}** **Analytics > Issue Analytics**.
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index c0fe19f1f16..3edbe3e8aa4 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -5,9 +5,10 @@ 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 **(STARTER)**
+# Merge Request Analytics **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229045) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229045) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.3.
+> - Moved to [GitLab Premium](https://about.gitlab.com/pricing/) due to Starter/Bronze being [discontinued](https://about.gitlab.com/blog/2021/01/26/new-gitlab-product-subscription-model/) in 13.9.
Merge Request Analytics helps you understand the efficiency of your code review process, and the productivity of your team.
@@ -102,5 +103,5 @@ bookmark for those preferred settings in your browser.
The **Merge Request Analytics** feature can be accessed only:
-- On [Starter](https://about.gitlab.com/pricing/) and above.
+- On [Premium](https://about.gitlab.com/pricing/) and above.
- By users with [Reporter access](../permissions.md) and above.
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index 633d7b35087..a06d94caf69 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -16,7 +16,7 @@ long, on average, it takes to deliver features is an enormous endeavor.
While [Value Stream Analytics](../analytics/value_stream_analytics.md) focuses on the entire
Software Development Life Cycle (SDLC) process, Productivity Analytics provides a way for Engineering Management to drill down in a systematic way to uncover patterns and causes for success or failure at an individual, project, or group level.
-Productivity can slow down for many reasons ranging from degrading code base to quickly growing teams. In order to investigate, department or team leaders can start by visualizing the time it takes for merge requests to be merged.
+Productivity can slow down for many reasons ranging from degrading codebase to quickly growing teams. In order to investigate, department or team leaders can start by visualizing the time it takes for merge requests to be merged.
## Supported features
@@ -60,5 +60,5 @@ GitLab has the ability to filter analytics based on a date range. To filter resu
The **Productivity Analytics** dashboard can be accessed only:
-- On [Premium or Silver tier](https://about.gitlab.com/pricing/) and above.
+- On the [Premium tier](https://about.gitlab.com/pricing/) and above.
- By users with [Reporter access](../permissions.md) and above.
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index b5aecff5180..6c41d93d51f 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -4,7 +4,7 @@ group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Value Stream Analytics **(CORE)**
+# Value Stream Analytics **(FREE)**
> - Introduced as Cycle Analytics prior to GitLab 12.3 at the project level.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3 at the group level.
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 674afcb29ee..49311ccc7cd 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -69,7 +69,7 @@ Examples of both configurations can be found here:
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 by using
an OpenAPI specification to provide information about the target API to test. OpenAPI specifications
-are provided as a filesystem resource or URL.
+are provided as a file system resource or URL.
Follow these steps to configure API fuzzing in GitLab with an OpenAPI specification:
@@ -89,7 +89,7 @@ Follow these steps to configure API fuzzing in GitLab with an OpenAPI specificat
amounts of fuzzing. We recommend that you start with the `Quick-10` profile. Testing with this
profile completes quickly, allowing for easier configuration validation.
- Provide the profile by adding the `FUZZAPI_PROFILE` variable to your `.gitlab-ci.yml` file,
+ Provide the profile by adding the `FUZZAPI_PROFILE` CI/CD variable to your `.gitlab-ci.yml` file,
substituting `Quick-10` for the profile you choose:
```yaml
@@ -182,7 +182,7 @@ target API to test:
amounts of fuzzing. We recommend that you start with the `Quick-10` profile. Testing with this
profile completes quickly, allowing for easier configuration validation.
- Provide the profile by adding the `FUZZAPI_PROFILE` variable to your `.gitlab-ci.yml` file,
+ Provide the profile by adding the `FUZZAPI_PROFILE` CI/CD variable to your `.gitlab-ci.yml` file,
substituting `Quick-10` for the profile you choose:
```yaml
@@ -273,7 +273,7 @@ information about the target API to test:
amounts of fuzzing. We recommend that you start with the `Quick-10` profile. Testing with this
profile completes quickly, allowing for easier configuration validation.
- Provide the profile by adding the `FUZZAPI_PROFILE` variable to your `.gitlab-ci.yml` file,
+ Provide the profile by adding the `FUZZAPI_PROFILE` CI/CD variable to your `.gitlab-ci.yml` file,
substituting `Quick-10` for the profile you choose:
```yaml
@@ -335,16 +335,17 @@ provide a script that performs an authentication flow or calculates the token.
#### HTTP Basic Authentication
[HTTP basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication)
-is an authentication method built into the HTTP protocol and used in-conjunction with
+is an authentication method built in to the HTTP protocol and used in conjunction with
[transport layer security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security).
-To use HTTP basic authentication, two variables are added to your `.gitlab-ci.yml` file:
+To use HTTP basic authentication, two CI/CD variables are added to your `.gitlab-ci.yml` file:
- `FUZZAPI_HTTP_USERNAME`: The username for authentication.
- `FUZZAPI_HTTP_PASSWORD`: The password for authentication.
For the password, we recommended that you [create a CI/CD variable](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui)
(for example, `TEST_API_PASSWORD`) set to the password. You can create CI/CD variables from the
-GitLab projects page at **Settings > CI/CD**, in the **Variables** section.
+GitLab projects page at **Settings > CI/CD**, in the **Variables** section. Use that variable
+as the value for `FUZZAPI_HTTP_PASSWORD`:
```yaml
include:
@@ -356,7 +357,6 @@ variables:
FUZZAPI_TARGET_URL: http://test-deployment/
FUZZAPI_HTTP_USERNAME: testuser
FUZZAPI_HTTP_PASSWORD: $TEST_API_PASSWORD
-
```
#### Bearer Tokens
@@ -371,36 +371,39 @@ tokens with API fuzzing, you need one of the following:
##### Token doesn't expire
-If the bearer token doesn't expire, you can provide it using the `FUZZAPI_OVERRIDES_ENV` variable.
-The `FUZZAPI_OVERRIDES_ENV` content is a JSON snippet that provides headers and cookies that should
-be added to outgoing HTTP requests made by API fuzzing.
+If the bearer token doesn't expire, use the `FUZZAPI_OVERRIDES_ENV` variable to provide it. This
+variable's content is a JSON snippet that provides headers and cookies to add to API fuzzing's
+outgoing HTTP requests.
-Create a CI/CD variable, for example `TEST_API_BEARERAUTH`, with the value
-`{"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.
+Follow these steps to provide the bearer token with `FUZZAPI_OVERRIDES_ENV`:
-Set `FUZZAPI_OVERRIDES_ENV` in your `.gitlab-ci.yml` file:
+1. [Create a CI/CD variable](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui),
+ for example `TEST_API_BEARERAUTH`, with the value
+ `{"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.
-```yaml
-include:
- - template: API-Fuzzing.gitlab-ci.yml
+1. In your `.gitlab-ci.yml` file, set `FUZZAPI_OVERRIDES_ENV` to the variable you just created:
-variables:
- FUZZAPI_PROFILE: Quick-10
- FUZZAPI_OPENAPI: test-api-specification.json
- FUZZAPI_TARGET_URL: http://test-deployment/
- FUZZAPI_OVERRIDES_ENV: $TEST_API_BEARERAUTH
-```
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
-To validate that authentication is working, run an API fuzzing test and review the fuzzing logs and
-the test API's application logs.
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_ENV: $TEST_API_BEARERAUTH
+ ```
+
+1. To validate that authentication is working, run an API fuzzing test and review the fuzzing logs
+ and the test API's application logs.
-##### Token generated at test-runtime
+##### Token generated at test runtime
-If the bearer token must be generated, and the resulting token doesn't expire during testing, you
-can provide to API fuzzing a file containing the token. This file can be generated by a prior stage
-and job, or as part of the API fuzzing job.
+If the bearer token must be generated and doesn't expire during testing, you can provide to API
+fuzzing a file containing the token. A prior stage and job, or part of the API fuzzing job, can
+generate this file.
API fuzzing expects to receive a JSON file with the following structure:
@@ -413,7 +416,7 @@ API fuzzing expects to receive a JSON file with the following structure:
```
This file can be generated by a prior stage and provided to API fuzzing through the
-`FUZZAPI_OVERRIDES_FILE` variable.
+`FUZZAPI_OVERRIDES_FILE` CI/CD variable.
Set `FUZZAPI_OVERRIDES_FILE` in your `.gitlab-ci.yml` file:
@@ -448,11 +451,13 @@ The script must create a JSON file containing the bearer token in a specific for
}
```
-You must provide three variables, each set for correct operation:
+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_INTERVAL`: Interval in seconds to run command.
+- `FUZZAPI_OVERRIDES_FILE`: JSON file the provided command generates.
+- `FUZZAPI_OVERRIDES_CMD`: Command that generates the JSON file.
+- `FUZZAPI_OVERRIDES_INTERVAL`: Interval (in seconds) to run command.
+
+For example:
```yaml
include:
@@ -472,35 +477,35 @@ the test API's application logs.
### Configuration files
-To get started quickly, GitLab provides you with the configuration file
+To get you started quickly, GitLab provides the configuration file
[`gitlab-api-fuzzing-config.yml`](https://gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing/-/blob/master/gitlab-api-fuzzing-config.yml).
-This file has several testing profiles that perform various amounts of testing. The run time of each
-increases as the numbers go up. To use a configuration file, add it to your repository's root as
-`.gitlab-api-fuzzing.yml`.
+This file has several testing profiles that perform various numbers of tests. The run time of each
+profile increases as the test numbers go up. To use a configuration file, add it to your
+repository's root as `.gitlab-api-fuzzing.yml`.
-| Profile | Scan Type |
+| Profile | Fuzz Tests (per parameter) |
|:---------|:-----------|
-|Quick-10 |Fuzzing 10 times per parameter |
-|Medium-20 |Fuzzing 20 times per parameter |
-|Medium-50 |Fuzzing 50 times per parameter |
-|Long-100 |Fuzzing 100 times per parameter |
-
-### Available variables
-
-| Environment variable | Description |
-|-----------------------------|--------------------|
-| `FUZZAPI_VERSION` | Specify API Fuzzing container version. Defaults to `latest`. |
-| `FUZZAPI_TARGET_URL` | Base URL of API testing target. |
-|[`FUZZAPI_CONFIG`](#configuration-files) | API Fuzzing configuration file. Defaults to `.gitlab-apifuzzer.yml`. |
-|[`FUZZAPI_PROFILE`](#configuration-files) | Configuration profile to use during testing. Defaults to `Quick`. |
-| `FUZZAPI_REPORT` | Scan report filename. Defaults to `gl-api_fuzzing-report.xml`. |
-|[`FUZZAPI_OPENAPI`](#openapi-specification) | OpenAPI specification file or URL. |
-|[`FUZZAPI_HAR`](#http-archive-har) | HTTP Archive (HAR) file. |
-|[`FUZZAPI_POSTMAN_COLLECTION`](#postman-collection) | Postman Collection file. |
-|[`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_INTERVAL`](#overrides) | How often to run overrides command in seconds. Defaults to `0` (once). |
+| Quick-10 | 10 |
+| Medium-20 | 20 |
+| Medium-50 | 50 |
+| Long-100 | 100 |
+
+### Available CI/CD variables
+
+| CI/CD variable | Description |
+|------------------------------------------------------|--------------------|
+| `FUZZAPI_VERSION` | Specify API Fuzzing container version. Defaults to `latest`. |
+| `FUZZAPI_TARGET_URL` | Base URL of API testing target. |
+|[`FUZZAPI_CONFIG`](#configuration-files) | API Fuzzing configuration file. Defaults to `.gitlab-apifuzzer.yml`. |
+|[`FUZZAPI_PROFILE`](#configuration-files) | Configuration profile to use during testing. Defaults to `Quick`. |
+| `FUZZAPI_REPORT` | Scan report filename. Defaults to `gl-api_fuzzing-report.xml`. |
+|[`FUZZAPI_OPENAPI`](#openapi-specification) | OpenAPI specification file or URL. |
+|[`FUZZAPI_HAR`](#http-archive-har) | HTTP Archive (HAR) file. |
+|[`FUZZAPI_POSTMAN_COLLECTION`](#postman-collection) | Postman Collection file. |
+|[`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_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. |
@@ -518,11 +523,11 @@ increases as the numbers go up. To use a configuration file, add it to your repo
### Overrides
-API Fuzzing provides a method to add or override headers and cookies for all outbound HTTP requests
-made. You can use this to inject semver headers, authentication, and so on. The
+API Fuzzing provides a method to add or override headers and cookies for all outbound HTTP requests.
+You can use this to inject semantic version headers, authentication, and so on. The
[authentication section](#authentication) includes examples of using overrides for that purpose.
-Overrides uses a JSON document to define the headers and cookies:
+Overrides use a JSON document to define the headers and cookies:
```json
{
@@ -537,7 +542,7 @@ Overrides uses a JSON document to define the headers and cookies:
}
```
-Example usage for setting a single header:
+Example of setting a single header:
```json
{
@@ -547,7 +552,7 @@ Example usage for setting a single header:
}
```
-Example usage for setting both a header and cookie:
+Example of setting both a header and cookie:
```json
{
@@ -560,14 +565,14 @@ Example usage for setting both a header and cookie:
}
```
-You can provide this JSON document as a file or environment variable. You may also provide a command
+You can provide this JSON document as a file or CI/CD variable. You may also provide a command
to generate the JSON document. The command can run at intervals to support values that expire.
#### Using a file
-To provide the overrides JSON as a file, the `FUZZAPI_OVERRIDES_FILE` environment variable is set. The path is relative to the job current working directory.
+To provide the overrides JSON as a file, the `FUZZAPI_OVERRIDES_FILE` CI/CD variable is set. The path is relative to the job current working directory.
-Example `.gitlab-ci.yml`:
+Here's an example `.gitlab-ci.yml`:
```yaml
include:
@@ -580,12 +585,12 @@ variables:
FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
```
-#### Using an environment variable
+#### Using a CI/CD variable
-To provide the overrides JSON as an environment variable, use the `FUZZAPI_OVERRIDES_ENV` variable.
-This allows you to place the JSON as CI/CD variables that can be masked and protected.
+To provide the overrides JSON as a CI/CD variable, use the `FUZZAPI_OVERRIDES_ENV` variable.
+This allows you to place the JSON as variables that can be masked and protected.
-In this example `.gitlab-ci.yml`, the JSON is provided directly:
+In this example `.gitlab-ci.yml`, the `FUZZAPI_OVERRIDES_ENV` variable is set directly to the JSON:
```yaml
include:
@@ -598,8 +603,8 @@ variables:
FUZZAPI_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'
```
-In this example `.gitlab-ci.yml`, the CI/CD variable `SECRET_OVERRIDES` provides the JSON. This is a
-[group or instance level environment variable defined in the UI](../../../ci/variables/README.md#instance-level-cicd-environment-variables):
+In this example `.gitlab-ci.yml`, the `SECRET_OVERRIDES` variable provides the JSON. This is a
+[group or instance level CI/CD variable defined in the UI](../../../ci/variables/README.md#instance-level-cicd-variables):
```yaml
include:
@@ -620,7 +625,7 @@ container that has Python 3 and Bash installed. If the Python script requires ad
it must detect this and install the packages at runtime. The script creates the overrides JSON file
as defined above.
-You must provide three variables, each set for correct operation:
+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.
@@ -689,9 +694,9 @@ for off. To turn header fuzzing on, change this setting to `true`:
Headers:
```
-`Headers` is a list of headers to fuzz. Only headers listed are fuzzed. For example, to fuzz a
-custom header `X-Custom` used by your APIs, add an entry for it using the syntax
-`- Name: HeaderName`, substituting `HeaderName` with the header to fuzz:
+`Headers` is a list of headers to fuzz. Only headers listed are fuzzed. To fuzz a header used by
+your APIs, add an entry for it using the syntax `- Name: HeaderName`. For example, to fuzz a
+custom header `X-Custom`, add `- Name: X-Custom`:
```yaml
- Name: GeneralFuzzingCheck
diff --git a/doc/user/application_security/compliance_dashboard/index.md b/doc/user/application_security/compliance_dashboard/index.md
deleted file mode 100644
index 383d2bf2df7..00000000000
--- a/doc/user/application_security/compliance_dashboard/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../compliance/compliance_dashboard/index.md'
----
-
-This document was moved to [another location](../../compliance/compliance_dashboard/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 9bde2c28972..6eec1418ef0 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -9,6 +9,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+WARNING:
+GitLab 14.0 will replace its container scanning engine with Trivy. Currently, GitLab uses the open
+source Clair engine for container scanning. GitLab 13.9 deprecates Clair. This is not a hard
+breaking change, as customers who wish to continue to use Clair can do so by setting the
+`CS_MAJOR_VERSION` CI/CD variable to version 3 (or earlier) in their `gitlab-ci.yaml` file. Since Clair is
+deprecated, however, note that GitLab will no longer update or maintain that scanning engine
+beginning in the 14.0 release. We advise customers to use the new default of Trivy beginning in
+GitLab 14.0 for regular updates and the latest features.
+
Your application's Docker image may itself be based on Docker images that contain known
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
displays them in a merge request, you can use GitLab to audit your Docker-based apps.
@@ -46,7 +55,7 @@ To enable container scanning in your pipeline, you need the following:
- An image matching [Clair's list of supported distributions](https://quay.github.io/claircore/).
- [Build and push](../../packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
your Docker image to your project's container registry. The name of the Docker image should use
- the following [predefined environment variables](../../../ci/variables/predefined_variables.md):
+ the following [predefined CI/CD variables](../../../ci/variables/predefined_variables.md):
```plaintext
$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
@@ -131,12 +140,12 @@ include:
There may be cases where you want to customize how GitLab scans your containers. For example, you
may want to enable more verbose output from Clair or Klar, access a Docker registry that requires
authentication, and more. To change such settings, use the [`variables`](../../../ci/yaml/README.md#variables)
-parameter in your `.gitlab-ci.yml` to set [environment variables](#available-variables).
-The environment variables you set in your `.gitlab-ci.yml` overwrite those in
+parameter in your `.gitlab-ci.yml` to set [CI/CD variables](#available-variables).
+The variables you set in your `.gitlab-ci.yml` overwrite those in
`Container-Scanning.gitlab-ci.yml`.
This example [includes](../../../ci/yaml/README.md#include) the container scanning template and
-enables verbose output from Clair by setting the `CLAIR_OUTPUT` environment variable to `High`:
+enables verbose output from Clair by setting the `CLAIR_OUTPUT` variable to `High`:
```yaml
include:
@@ -173,26 +182,26 @@ variables:
#### Available variables
You can [configure](#customizing-the-container-scanning-settings) container
-scanning by using the following environment variables:
+scanning by using the following CI/CD variables:
-| Environment Variable | Default | Description |
+| CI/CD Variable | Default | Description |
| ------------------------------ | ------------- | ----------- |
-| `ADDITIONAL_CA_CERT_BUNDLE` | `""` | Bundle of CA certs that you want to trust. |
+| `ADDITIONAL_CA_CERT_BUNDLE` | `""` | Bundle of CA certs that you want to trust. See [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority) for more details. |
| `CLAIR_DB_CONNECTION_STRING` | `postgresql://postgres:password@clair-vulnerabilities-db:5432/postgres?sslmode=disable&statement_timeout=60000` | This variable represents the [connection string](https://www.postgresql.org/docs/9.3/libpq-connect.html#AEN39692) to the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) database and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool) section. The host value for the connection string must match the [alias](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) value of the `Container-Scanning.gitlab-ci.yml` template file, which defaults to `clair-vulnerabilities-db`. |
| `CLAIR_DB_IMAGE` | `arminc/clair-db:latest` | The Docker image name and tag for the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes, or to refer to a locally hosted vulnerabilities database for an on-premise offline installation. |
| `CLAIR_DB_IMAGE_TAG` | `latest` | (**DEPRECATED - use `CLAIR_DB_IMAGE` instead**) The Docker image tag for the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes. |
| `CLAIR_OUTPUT` | `Unknown` | Severity level threshold. Vulnerabilities with severity level higher than or equal to this threshold are outputted. Supported levels are `Unknown`, `Negligible`, `Low`, `Medium`, `High`, `Critical` and `Defcon1`. |
-| `CLAIR_TRACE` | `"false"` | Set to true to enable more verbose output from the clair server process. |
+| `CLAIR_TRACE` | `"false"` | Set to true to enable more verbose output from the Clair server process. |
| `CLAIR_VULNERABILITIES_DB_URL` | `clair-vulnerabilities-db` | (**DEPRECATED - use `CLAIR_DB_CONNECTION_STRING` instead**) This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) is running on and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool) section. |
| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. |
| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. |
-| `CS_MAJOR_VERSION` | `3` | The major version of the Docker image tag. |
+| `CS_MAJOR_VERSION` | `3` | The major version of the Docker image tag. |
| `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. |
| `DOCKER_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access secure Docker registries using HTTPS with bad (or self-signed) SSL certificates. |
| `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | Password for accessing a Docker registry requiring authentication. |
| `DOCKER_USER` | `$CI_REGISTRY_USER` | Username for accessing a Docker registry requiring authentication. |
| `DOCKERFILE_PATH` | `Dockerfile` | The path to the `Dockerfile` to be used for generating remediations. By default, the scanner looks for a file named `Dockerfile` in the root directory of the project, so this variable should only be configured if your `Dockerfile` is in a non-standard location, such as a subdirectory. See [Solutions for vulnerabilities](#solutions-for-vulnerabilities-auto-remediation) for more details. |
-| `KLAR_TRACE` | `"false"` | Set to true to enable more verbose output from klar. |
+| `KLAR_TRACE` | `"false"` | Set to true to enable more verbose output from Klar. |
| `REGISTRY_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access insecure registries (HTTP only). Should only be set to `true` when testing the image locally. |
| `SECURE_ANALYZERS_PREFIX` | `"registry.gitlab.com/gitlab-org/security-products/analyzers"` | Set the Docker registry base address from which to download the analyzer. |
| `SECURE_LOG_LEVEL` | `info` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. |
@@ -217,6 +226,23 @@ GitLab 13.0 and later doesn't support [`only` and `except`](../../../ci/yaml/REA
When overriding the template, you must use [`rules`](../../../ci/yaml/README.md#rules)
instead.
+### Using a custom SSL CA certificate authority
+
+You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority, which is used to verify the peer when fetching Docker images from a registry which uses HTTPS. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
+
+```yaml
+container_scanning:
+ variables:
+ ADDITIONAL_CA_CERT_BUNDLE: |
+ -----BEGIN CERTIFICATE-----
+ MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
+ ...
+ jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
+ -----END CERTIFICATE-----
+```
+
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
+
### Vulnerability allowlisting
To allowlist specific vulnerabilities, follow these steps:
@@ -277,7 +303,7 @@ For details on saving and transporting Docker images as a file, see Docker's doc
[`docker save`](https://docs.docker.com/engine/reference/commandline/save/), [`docker load`](https://docs.docker.com/engine/reference/commandline/load/),
[`docker export`](https://docs.docker.com/engine/reference/commandline/export/), and [`docker import`](https://docs.docker.com/engine/reference/commandline/import/).
-#### Set container scanning CI job variables to use local container scanner analyzers
+#### Set container scanning CI/CD variables to use local container scanner analyzers
1. [Override the container scanning template](#overriding-the-container-scanning-template) in your `.gitlab-ci.yml` file to refer to the Docker images hosted on your local Docker container registry:
@@ -334,13 +360,13 @@ image directly, follow these steps:
docker run -p 5432:5432 -d --name clair-db arminc/clair-db:latest
```
-1. Configure an environment variable to point to your local machine's IP address (or insert your IP address instead of the `LOCAL_MACHINE_IP_ADDRESS` variable in the `CLAIR_DB_CONNECTION_STRING` in the next step):
+1. Configure a CI/CD variable to point to your local machine's IP address (or insert your IP address instead of the `LOCAL_MACHINE_IP_ADDRESS` variable in the `CLAIR_DB_CONNECTION_STRING` in the next step):
```shell
export LOCAL_MACHINE_IP_ADDRESS=your.local.ip.address
```
-1. Run the analyzer's Docker image, passing the image and tag you want to analyze in the `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG` environment variables:
+1. Run the analyzer's Docker image, passing the image and tag you want to analyze in the `CI_APPLICATION_REPOSITORY` and `CI_APPLICATION_TAG` variables:
```shell
docker run \
@@ -437,7 +463,7 @@ Some vulnerabilities can be fixed by applying the solution that GitLab
automatically generates.
To enable remediation support, the scanning tool _must_ have access to the `Dockerfile` specified by
-the [`DOCKERFILE_PATH`](#available-variables) environment variable. To ensure that the scanning tool
+the [`DOCKERFILE_PATH`](#available-variables) CI/CD variable. To ensure that the scanning tool
has access to this
file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/runners/README.md#git-strategy) in
your `.gitlab-ci.yml` file by following the instructions described in this document's
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 469945246c1..9e42b3e403a 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -27,12 +27,13 @@ Docker image with the fuzz engine to run your app.
|----------|----------------|---------|
| C/C++ | [libFuzzer](https://llvm.org/docs/LibFuzzer.html) | [c-cpp-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/c-cpp-fuzzing-example) |
| GoLang | [go-fuzz (libFuzzer support)](https://github.com/dvyukov/go-fuzz) | [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example) |
-| Swift | [libfuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.md) | [swift-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/swift-fuzzing-example) |
+| Swift | [libFuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.md) | [swift-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/swift-fuzzing-example) |
| Rust | [cargo-fuzz (libFuzzer support)](https://github.com/rust-fuzz/cargo-fuzz) | [rust-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example) |
-| Java | [javafuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/javafuzz) (recommended) | [javafuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/javafuzz-fuzzing-example) |
+| Java | [Javafuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/javafuzz) (recommended) | [javafuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/javafuzz-fuzzing-example) |
| Java | [JQF](https://github.com/rohanpadhye/JQF) (not preferred) | [jqf-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/java-fuzzing-example) |
-| JavaScript | [jsfuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/jsfuzz)| [jsfuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/jsfuzz-fuzzing-example) |
-| 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) |
+| JavaScript | [`jsfuzz`](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/jsfuzz)| [jsfuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/jsfuzz-fuzzing-example) |
+| 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
@@ -44,8 +45,18 @@ provided as part of your GitLab installation.
To do so, add the following to your `.gitlab-ci.yml` file:
```yaml
+stages:
+ - fuzz
+
include:
- template: Coverage-Fuzzing.gitlab-ci.yml
+
+my_fuzz_target:
+ extends: .fuzz_base
+ script:
+ # Build your fuzz target binary in these steps, then run it with gitlab-cov-fuzz>
+ # See our example repos for how you could do this with any of our supported languages
+ - ./gitlab-cov-fuzz run --regression=$REGRESSION -- <your fuzz target>
```
The included template makes available the [hidden job](../../../ci/yaml/README.md#hide-jobs)
@@ -97,7 +108,7 @@ There are two types of jobs:
Here's our current suggestion for configuring your fuzz target's timeout:
-- Set `COVFUZZ_BRANCH` to the branch where you want to run long-running (async) fuzzing
+- Set `COVFUZZ_BRANCH` to the branch where you want to run long-running (asynchronous) fuzzing
jobs. This is `master` by default.
- Use regression or short-running fuzzing jobs for other branches or merge requests.
@@ -108,13 +119,13 @@ You can configure this by passing `--regression=false/true` to `gitlab-cov-fuzz`
shows. Also note that `gitlab-cov-fuzz` is a wrapper, so you can pass those arguments to configure
any option available in the underlying fuzzing engine.
-### Available variables
+### Available CI/CD variables
-| Environment variable | Description |
-|---------------------------|--------------------------------------------------------------------|
-| `COVFUZZ_BRANCH` | The branch for long-running fuzzing jobs. The default is `master`. |
-| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. The default is empty. |
-| `COVFUZZ_URL_PREFIX` | Path to the `gitlab-cov-fuzz` repository cloned for use with an offline environment. You should only change this when using an offline environment. The default value is `https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw`. |
+| CI/CD variable | Description |
+|-----------------------|--------------------------------------------------------------------|
+| `COVFUZZ_BRANCH` | The branch for long-running fuzzing jobs. The default is `master`. |
+| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. The default is empty. |
+| `COVFUZZ_URL_PREFIX` | Path to the `gitlab-cov-fuzz` repository cloned for use with an offline environment. You should only change this when using an offline environment. The default value is `https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw`. |
The files in the seed corpus (`COVFUZZ_SEED_CORPUS`), if provided, aren't updated unless you commit new
files to your Git repository. There's usually no need to frequently update the seed corpus. As part
@@ -178,20 +189,20 @@ To use coverage fuzzing in an offline environment, follow these steps:
`NEW_URL_GITLAB_COV_FUZ` is the URL of the private `gitlab-cov-fuzz` clone that you set up in the
first step.
-### Continuous fuzzing (long-running async fuzzing jobs)
+### Continuous fuzzing (long-running asynchronous fuzzing jobs)
It's also possible to run the fuzzing jobs longer and without blocking your main pipeline. This
configuration uses the GitLab [parent-child pipelines](../../../ci/parent_child_pipelines.md).
The full example is available in the [repository](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/-/tree/continuous_fuzzing#running-go-fuzz-from-ci).
This example uses Go, but is applicable for any other supported languages.
-The suggested workflow in this scenario is to have long-running, async fuzzing jobs on a
+The suggested workflow in this scenario is to have long-running, asynchronous fuzzing jobs on a
main/development branch, and short, blocking sync fuzzing jobs on all other branches and MRs. This
is a good way to balance the needs of letting a developer's per-commit pipeline complete quickly,
and also giving the fuzzer a large amount of time to fully explore and test the app.
Long-running fuzzing jobs are usually necessary for the coverage guided fuzzer to find deeper bugs
-in your latest code base. THe following is an example of what `.gitlab-ci.yml` looks like in this
+in your latest codebase. THe following is an example of what `.gitlab-ci.yml` looks like in this
workflow (for the full example, see the [repository](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/-/tree/continuous_fuzzing)):
```yaml
@@ -207,7 +218,7 @@ sync_fuzzing:
async_fuzzing:
variables:
- COVFUZZ_ADDITIONAL_ARGS: '-max_total_time=3600'
+ COVFUZZ_ADDITIONAL_ARGS: '-max_total_time=3600'
trigger:
include: .covfuzz-ci.yml
rules:
@@ -242,9 +253,9 @@ vulnerability:
vulnerability can be Detected, Confirmed, Dismissed, or Resolved.
- Project: The project in which the vulnerability exists.
- Crash type: The type of crash or weakness in the code. This typically maps to a [CWE](https://cwe.mitre.org/).
-- Crash state: A normalized version of the stacktrace, containing the last three functions of the
+- Crash state: A normalized version of the stack trace, containing the last three functions of the
crash (without random addresses).
-- Stacktrace snippet: The last few lines of the stacktrace, which shows details about the crash.
+- Stack trace snippet: The last few lines of the stack trace, which shows details about the crash.
- Identifier: The vulnerability's identifier. This maps to either a [CVE](https://cve.mitre.org/)
or [CWE](https://cwe.mitre.org/).
- Severity: The vulnerability's severity. This can be Critical, High, Medium, Low, Info, or Unknown.
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 395a8702d1b..3950c856b40 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -92,7 +92,7 @@ variables:
To use the latest version of the DAST template, include
`DAST.latest.gitlab-ci.yml` instead of `DAST.gitlab-ci.yml`.
-See the CI [docs](../../../development/cicd/templates.md#latest-version)
+See the CI/CD [documentation](../../../development/cicd/templates.md#latest-version)
on template versioning for more information.
Please note that the latest version may include breaking changes. Check the
@@ -102,7 +102,7 @@ Please note that the latest version may include breaking changes. Check the
There are two ways to define the URL to be scanned by DAST:
-1. Set the `DAST_WEBSITE` [variable](../../../ci/yaml/README.md#variables).
+1. Set the `DAST_WEBSITE` [CI/CD variable](../../../ci/yaml/README.md#variables).
1. Add it in an `environment_url.txt` file at the root of your project.
This is useful for testing in dynamic environments. To run DAST against an application
@@ -177,7 +177,7 @@ authorization credentials. By default, the following headers are masked:
- `Set-Cookie` (values only).
- `Cookie` (values only).
-Using the [`DAST_MASK_HTTP_HEADERS` variable](#available-variables), you can list the
+Using the [`DAST_MASK_HTTP_HEADERS` CI/CD variable](#available-variables), you can list the
headers whose values you want masked. For details on how to mask headers, see
[Customizing the DAST settings](#customizing-the-dast-settings).
@@ -192,7 +192,7 @@ of your application is likely not accessible without authentication. It is also
that you periodically confirm the scanner's authentication is still working as this tends to break over
time due to authentication changes to the application.
-Create masked variables to pass the credentials that DAST uses.
+Create masked CI/CD variables to pass the credentials that DAST uses.
To create masked variables for the username and password, see [Create a custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui).
Note that the key of the username variable must be `DAST_USERNAME`
and the key of the password variable must be `DAST_PASSWORD`.
@@ -252,7 +252,7 @@ and potentially damage them. You could even take down your production environmen
For that reason, you should use domain validation.
Domain validation is not required by default. It can be required by setting the
-[environment variable](#available-variables) `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` to `"true"`.
+[CI/CD variable](#available-variables) `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` to `"true"`.
```yaml
include:
@@ -406,14 +406,14 @@ dast:
#### Full API scan
API scans support full scanning, which can be enabled by using the `DAST_FULL_SCAN_ENABLED`
-environment variable. Domain validation is not supported for full API scans.
+CI/CD variable. Domain validation is not supported for full API scans.
#### Host override
Specifications often define a host, which contains a domain name and a port. The
host referenced may be different than the host of the API's review instance.
This can cause incorrect URLs to be imported, or a scan on an incorrect host.
-Use the `DAST_API_HOST_OVERRIDE` environment variable to override these values.
+Use the `DAST_API_HOST_OVERRIDE` CI/CD variable to override these values.
For example, with a OpenAPI V3 specification containing:
@@ -441,7 +441,7 @@ limitation in the ZAP OpenAPI extension.
#### Authentication using headers
Tokens in request headers are often used as a way to authenticate API requests.
-You can achieve this by using the `DAST_REQUEST_HEADERS` environment variable.
+You can achieve this by using the `DAST_REQUEST_HEADERS` CI/CD variable.
Headers are applied to every request DAST makes.
```yaml
@@ -463,10 +463,10 @@ A URL scan allows you to specify which parts of a website are scanned by DAST.
URLs to scan can be specified by either of the following methods:
-- Use `DAST_PATHS_FILE` environment variable to specify the name of a file containing the paths.
-- Use `DAST_PATHS` environment variable to list the paths.
+- Use `DAST_PATHS_FILE` CI/CD variable to specify the name of a file containing the paths.
+- Use `DAST_PATHS` variable to list the paths.
-##### Use DAST_PATHS_FILE environment variable
+##### Use `DAST_PATHS_FILE` CI/CD variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6.
@@ -478,7 +478,7 @@ page1.html
category/shoes/page1.html
```
-To scan the URLs in that file, set the environment variable `DAST_PATHS_FILE` to the path of that file.
+To scan the URLs in that file, set the CI/CD variable `DAST_PATHS_FILE` to the path of that file.
```yaml
include:
@@ -501,12 +501,12 @@ dast:
DAST_PATHS_FILE: url_file.txt
```
-##### Use DAST_PATHS environment variable
+##### Use `DAST_PATHS` CI/CD variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4.
-To specify the paths to scan in an environment variable, add a comma-separated list of the paths to the `DAST_PATHS`
-environment variable. Note that you can only scan paths of a single host.
+To specify the paths to scan in a CI/CD variable, add a comma-separated list of the paths to the `DAST_PATHS`
+variable. Note that you can only scan paths of a single host.
```yaml
include:
@@ -521,12 +521,12 @@ When using `DAST_PATHS` and `DAST_PATHS_FILE`, note the following:
- `DAST_WEBSITE` must be defined when using either `DAST_PATHS_FILE` or `DAST_PATHS`. The paths listed in either use `DAST_WEBSITE` to build the URLs to scan
- Spidering is disabled when `DAST_PATHS` or `DAST_PATHS_FILE` are defined
- `DAST_PATHS_FILE` and `DAST_PATHS` can not be used together
-- The `DAST_PATHS` environment variable has a limit of about 130kb. If you have a list or paths
+- The `DAST_PATHS` variable has a limit of about 130kb. If you have a list or paths
greater than this, use `DAST_PATHS_FILE`.
#### Full Scan
-To perform a [full scan](#full-scan) on the listed paths, use the `DAST_FULL_SCAN_ENABLED` environment variable.
+To perform a [full scan](#full-scan) on the listed paths, use the `DAST_FULL_SCAN_ENABLED` CI/CD variable.
### Customizing the DAST settings
@@ -534,7 +534,7 @@ WARNING:
Beginning in GitLab 13.0, the use of [`only` and `except`](../../../ci/yaml/README.md#onlyexcept-basic)
is no longer supported. When overriding the template, you must use [`rules`](../../../ci/yaml/README.md#rules) instead.
-The DAST settings can be changed through environment variables by using the
+The DAST settings can be changed through CI/CD variables by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
These variables are documented in [available variables](#available-variables).
@@ -554,46 +554,47 @@ configuration, the last mention of the variable takes precedence.
### Available variables
-DAST can be [configured](#customizing-the-dast-settings) using environment variables.
+DAST can be [configured](#customizing-the-dast-settings) using CI/CD variables.
-| Environment variable | Type | Description |
-|-----------------------------| -----------|--------------------------------------------------------------------------------|
-| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
-| `DAST_WEBSITE` | URL | The URL of the website to scan. `DAST_API_SPECIFICATION` must be specified if this is omitted. |
-| `DAST_API_SPECIFICATION` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
+| CI/CD variable | Type | Description |
+|------------------------------| --------|-------------|
+| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
+| `DAST_WEBSITE` | URL | The URL of the website to scan. `DAST_API_SPECIFICATION` must be specified if this is omitted. |
+| `DAST_API_SPECIFICATION` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. |
| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
-| `DAST_AUTH_URL` | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. |
-| `DAST_AUTH_VALIDATION_URL` | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST will exit if it cannot access the URL. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8.
-| `DAST_USERNAME` | string | The username to authenticate to in the website. |
-| `DAST_PASSWORD` | string | The password to authenticate to in the website. |
-| `DAST_USERNAME_FIELD` | string | The name of username field at the sign-in HTML form. |
-| `DAST_PASSWORD_FIELD` | string | The name of password field at the sign-in HTML form. |
-| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
-| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
-| `DAST_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. In [GitLab 13.7 and earlier](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/367), was `DAST_AUTH_EXCLUDE_URLS` (which we plan to support until GitLab 14.0). |
-| `DAST_FULL_SCAN_ENABLED` | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
+| `DAST_AUTH_URL` | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. |
+| `DAST_AUTH_VALIDATION_URL` | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST will exit if it cannot access the URL. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8.
+| `DAST_USERNAME` | string | The username to authenticate to in the website. |
+| `DAST_PASSWORD` | string | The password to authenticate to in the website. |
+| `DAST_USERNAME_FIELD` | string | The name of username field at the sign-in HTML form. |
+| `DAST_PASSWORD_FIELD` | string | The name of password field at the sign-in HTML form. |
+| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
+| `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). |
+| `DAST_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
+| `DAST_FULL_SCAN_ENABLED` | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | Set to `true` to require [domain validation](#domain-validation) when running DAST full scans. Not supported for API scans. Default: `false` |
-| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` |
-| `DAST_API_HOST_OVERRIDE` | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080` |
-| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). For example, `HTTP Parameter Override` has a rule ID of `10026`. **Note:** In earlier versions of GitLab the excluded rules were executed but alerts they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
-| `DAST_REQUEST_HEADERS` | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
-| `DAST_DEBUG` | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_SPIDER_MINS` | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1.|
-| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` |
+| `DAST_API_HOST_OVERRIDE` | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080` |
+| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). For example, `HTTP Parameter Override` has a rule ID of `10026`. **Note:** In earlier versions of GitLab the excluded rules were executed but alerts they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
+| `DAST_REQUEST_HEADERS` | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
+| `DAST_DEBUG` | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_SPIDER_MINS` | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_MARKDOWN_REPORT` | string | The filename of the Markdown report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1.|
+| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
-| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line and be in `/zap/wrk`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
-| `DAST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
-| `DAST_FIRST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
-| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
+| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in GitLab 13.4. |
+| `DAST_PATHS_FILE` | string | The file path containing the paths within `DAST_WEBSITE` to scan. The file must be plain text with one path per line and be in `/zap/wrk`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258825) in GitLab 13.6. |
+| `DAST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
+| `DAST_FIRST_SUBMIT_FIELD` | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
+| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
+| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
+| `DAST_AUTH_EXCLUDE_URLS` | URLs | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/289959) in GitLab 13.8, to be removed in 14.0, and replaced by `DAST_EXCLUDE_URLS`. The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
### DAST command-line options
-Not all DAST configuration is available via environment variables. To find out all
+Not all DAST configuration is available via CI/CD variables. To find out all
possible options, run the following configuration.
Available command-line options are printed to the job log:
@@ -648,11 +649,11 @@ A DAST job has two executing processes:
- The ZAP server.
- A series of scripts that start, control and stop the ZAP server.
-Debug mode of the scripts can be enabled by using the `DAST_DEBUG` environment variable. This can help when troubleshooting the job,
+Debug mode of the scripts can be enabled by using the `DAST_DEBUG` CI/CD variable. This can help when troubleshooting the job,
and outputs statements indicating what percentage of the scan is complete.
For details on using variables, see [Overriding the DAST template](#customizing-the-dast-settings).
-Debug mode of the ZAP server can be enabled using the `DAST_ZAP_LOG_CONFIGURATION` environment variable.
+Debug mode of the ZAP server can be enabled using the `DAST_ZAP_LOG_CONFIGURATION` variable.
The following table outlines examples of values that can be set and the effect that they have on the output that is logged.
Multiple values can be specified, separated by semicolons.
@@ -705,7 +706,7 @@ For details on saving and transporting Docker images as a file, see Docker's doc
[`docker export`](https://docs.docker.com/engine/reference/commandline/export/), and
[`docker import`](https://docs.docker.com/engine/reference/commandline/import/).
-### Set DAST CI job variables to use local DAST analyzers
+### Set DAST CI/CD job variables to use local DAST analyzers
Add the following configuration to your `.gitlab-ci.yml` file. You must replace `image` to refer to
the DAST Docker image hosted on your local Docker container registry:
@@ -720,21 +721,24 @@ dast:
The DAST job should now use local copies of the DAST analyzers to scan your code and generate
security reports without requiring internet access.
-Alternatively, you can use the variable `SECURE_ANALYZERS_PREFIX` to override the base registry address of the `dast` image.
+Alternatively, you can use the CI/CD variable `SECURE_ANALYZERS_PREFIX` to override the base registry address of the `dast` image.
## On-demand scans
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.3.
+> - The saved scans feature was [added](https://gitlab.com/groups/gitlab-org/-/epics/5100) in
+> GitLab 13.9.
An on-demand DAST scan runs outside the DevOps life cycle. Changes in your repository don't trigger
the scan. You must start it manually.
An on-demand DAST scan:
-- Uses settings in the site profile and scanner profile you select when you run the scan,
- instead of those in the `.gitlab-ci.yml` file.
+- Can run a specific combination of a [site profile](#site-profile) and a
+ [scanner profile](#scanner-profile).
- Is associated with your project's default branch.
+- Is saved on creation so it can be run later.
### On-demand scan modes
@@ -742,8 +746,8 @@ An on-demand scan can be run in active or passive mode:
- _Passive mode_ is the default and runs a ZAP Baseline Scan.
- _Active mode_ runs a ZAP Full Scan which is potentially harmful to the site being scanned. To
- minimize the risk of accidental damage, running an active scan requires a [validated site
- profile](#site-profile-validation).
+ minimize the risk of accidental damage, running an active scan requires a [validated site
+ profile](#site-profile-validation).
### Run an on-demand DAST scan
@@ -752,19 +756,81 @@ You must have permission to run an on-demand DAST scan against a protected branc
The default branch is automatically protected. For more information, see
[Pipeline security on protected branches](../../../ci/pipelines/index.md#pipeline-security-on-protected-branches).
-To run an on-demand DAST scan, you need:
+Prerequisites:
- A [scanner profile](#create-a-scanner-profile).
- A [site profile](#create-a-site-profile).
- If you are running an active scan the site profile must be [validated](#validate-a-site-profile).
-1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left sidebar.
+To run an on-demand scan, either:
+
+- [Create and run an on-demand scan](#create-and-run-an-on-demand-scan).
+- [Run a previously saved on-demand scan](#run-a-saved-on-demand-scan).
+
+#### Create and run an on-demand scan
+
+1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left
+ sidebar.
+1. Complete the **Scan name** and **Description** fields.
1. In **Scanner profile**, select a scanner profile from the dropdown.
1. In **Site profile**, select a site profile from the dropdown.
-1. Click **Run scan**.
+1. To run the on-demand scan now, select **Save and run scan**. Otherwise select **Save scan** to
+ [run](#run-a-saved-on-demand-scan) it later.
The on-demand DAST scan runs and the project's dashboard shows the results.
+### List saved on-demand scans
+
+To list saved on-demand scans:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Select the **Saved Scans** tab.
+
+### View details of an on-demand scan
+
+To view details of an on-demand scan:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Select **Manage DAST scans**.
+1. Select **Manage** in the **DAST Profiles** row.
+1. Select the **Saved Scans** tab.
+1. In the saved scan's row select **More actions** (**{ellipsis_v}**), then select **Edit**.
+
+### Run a saved on-demand scan
+
+To run a saved on-demand scan:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Select **Manage DAST scans**.
+1. Select **Manage** in the **DAST Profiles** row.
+1. Select the **Saved Scans** tab.
+1. In the scan's row select **Run scan**.
+
+The on-demand DAST scan runs and the project's dashboard shows the results.
+
+### Edit an on-demand scan
+
+To edit an on-demand scan:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Select **Manage DAST scans**.
+1. Select **Manage** in the **DAST Profiles** row.
+1. Select the **Saved Scans** tab.
+1. In the saved scan's row select **More actions** (**{ellipsis_v}**), then select **Edit**.
+1. Edit the form.
+1. Select **Save scan**.
+
+### Delete an on-demand scan
+
+To delete an on-demand scan:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Select **Manage DAST scans**.
+1. Select **Manage** in the **DAST Profiles** row.
+1. Select the **Saved Scans** tab.
+1. In the saved scan's row select **More actions** (**{ellipsis_v}**), then select **Delete**.
+1. Select **Delete** to confirm the deletion.
+
## Site profile
A site profile describes the attributes of a web site to scan on demand with DAST. A site profile is
@@ -775,7 +841,7 @@ A site profile contains the following:
- **Profile name**: A name you assign to the site to be scanned.
- **Target URL**: The URL that DAST runs against.
-## Site profile validation
+### Site profile validation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233020) in GitLab 13.8.
@@ -798,37 +864,51 @@ To create a site profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
1. Select **Manage** in the **DAST Profiles** row.
-1. Select **New Profile > Site Profile**.
-1. Type in a unique **Profile name** and **Target URL** then select **Save profile**.
+1. Select **New > Site Profile**.
+1. Complete the fields then select **Save profile**.
+
+The site profile is created.
### Edit a site profile
To edit an existing site profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
-1. Select **Manage** in the **DAST Profiles** row.
-1. Select **Edit** in the row of the profile to edit.
-1. Edit the **Profile name** and **Target URL**, then select **Save profile**.
+1. In the **DAST Profiles** row select **Manage**.
+1. Select the **Site Profiles** tab.
+1. In the profile's row select the **More actions** (**{ellipsis_v}**) menu, then select **Edit**.
+1. Edit the fields then select **Save profile**.
+
+The site profile is updated with the edited details.
### Delete a site profile
To delete an existing site profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
-1. Select **Manage** in the **DAST Profiles** row.
-1. Select **{remove}** (Delete profile) in the row of the profile to delete.
+1. In the **DAST Profiles** row select **Manage**.
+1. Select the **Site Profiles** tab.
+1. In the profile's row select the **More actions** (**{ellipsis_v}**) menu, then select **Delete**.
+1. Select **Delete** to confirm the deletion.
+
+The site profile is deleted.
### Validate a site profile
+Prerequisites:
+
+- A site profile.
+
To validate a site profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
-1. Select **Manage** in the **DAST Profiles** row.
-1. Select **Validate target site** beside the profile to validate.
+1. In the **DAST Profiles** row select **Manage**.
+1. Select the **Site Profiles** tab.
+1. In the profile's row select **Validate** or **Retry validation**.
1. Select the validation method.
1. For **Text file validation**:
1. Download the validation file listed in **Step 2**.
- 1. Upload the validation file to the host. You can upload the file to the location in
+ 1. Upload the validation file to the host. Upload the file to the location in
**Step 3** or any location you prefer.
1. Select **Validate**.
1. For **Header validation**:
@@ -839,11 +919,23 @@ To validate a site profile:
The site is validated and an active scan can run against it.
-If a validated site profile's target URL is edited, the site is no longer validated.
+If a validated site profile's target URL is edited, the site's validation status is revoked.
+
+### Revoke a site profile's validation status
+
+Note that all site profiles with the same URL have their validation status revoked.
+
+To revoke a site profile's validation status:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. In the **DAST Profiles** row select **Manage**.
+1. Select **Revoke validation** beside the validated profile.
+
+The site profile's validation status is revoked.
#### Validated site profile headers
-The following are code samples of how you could provide the required site profile header in your
+The following are code samples of how you can provide the required site profile header in your
application.
##### Ruby on Rails example for on-demand scan
@@ -888,27 +980,26 @@ app.get('/dast-website-target', function(req, res) {
## Scanner profile
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222767) in GitLab 13.4.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/225804) in GitLab 13.5: scan mode, AJAX spider, debug messages.
A scanner profile defines the scanner settings used to run an on-demand scan:
- **Profile name:** A name you give the scanner profile. For example, "Spider_15".
+- **Scan mode:** A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities.
- **Spider timeout:** The maximum number of minutes allowed for the spider to traverse the site.
- **Target timeout:** The maximum number of seconds DAST waits for the site to be available before
starting the scan.
-- **Scan mode:** A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities.
- **AJAX spider:** Run the AJAX spider, in addition to the traditional spider, to crawl the target site.
- **Debug messages:** Include debug messages in the DAST console output.
-Scan mode, AJAX spider, Debug messages are [added in GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/225804)
-
### Create a scanner profile
To create a scanner profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
-1. Click **Manage** in the **DAST Profiles** row.
-1. Click **New Profile > Scanner Profile**.
-1. Enter a unique **Profile name**, the desired **Spider timeout**, and the **Target timeout**.
+1. In the **DAST Profiles** row select **Manage**.
+1. Select **New > Scanner Profile**.
+1. Complete the form. For details of each field, see [Scanner profile](#scanner-profile).
1. Click **Save profile**.
### Edit a scanner profile
@@ -917,7 +1008,12 @@ To edit a scanner profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
1. Click **Manage** in the **DAST Profiles** row.
-1. Click **Edit** in the scanner profile's row.
+1. Select the **Scanner Profiles** tab.
+1. In the scanner's row select the **More actions** (**{ellipsis_v}**) menu, then select **Edit**.
+1. Edit the form.
+1. Select **Save profile**.
+
+The scanner profile is updated with the edited details.
### Delete a scanner profile
@@ -925,7 +1021,11 @@ To delete a scanner profile:
1. From your project's home page, go to **Security & Compliance > Configuration**.
1. Click **Manage** in the **DAST Profiles** row.
-1. Click **{remove}** (Delete profile) in the scanner profile's row.
+1. Select the **Scanner Profiles** tab.
+1. In the scanner's row select the **More actions** (**{ellipsis_v}**) menu, then select **Delete**.
+1. Select **Delete**.
+
+The scanner profile is deleted.
## Reports
@@ -985,7 +1085,7 @@ vulnerabilities in your groups, projects and pipelines. Read more about the
ZAP first creates rules in the `alpha` class. After a testing period with
the community, they are promoted to `beta`. DAST uses `beta` definitions by
default. To request `alpha` definitions, use the
-`DAST_INCLUDE_ALPHA_VULNERABILITIES` environment variable as shown in the
+`DAST_INCLUDE_ALPHA_VULNERABILITIES` CI/CD variable as shown in the
following configuration:
```yaml
@@ -1033,7 +1133,7 @@ This results in the following error:
```
Fortunately, it's straightforward to increase the amount of memory available
-for DAST by using the `DAST_ZAP_CLI_OPTIONS` environment variable:
+for DAST by using the `DAST_ZAP_CLI_OPTIONS` CI/CD variable:
```yaml
include:
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index 1079a75e32f..53d91bfcd78 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -34,8 +34,8 @@ maintained by GitLab, but users can also integrate their own **custom images**.
## Official default analyzers
-Any custom change to the official analyzers can be achieved by using an
-[environment variable in your `.gitlab-ci.yml`](index.md#customizing-the-dependency-scanning-settings).
+Any custom change to the official analyzers can be achieved by using a
+[CI/CD variable in your `.gitlab-ci.yml`](index.md#customizing-the-dependency-scanning-settings).
### Using a custom Docker mirror
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index cecf818edfc..11d27140e42 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -65,20 +65,19 @@ The following languages and dependency managers are supported:
| [Golang](https://golang.org/) | Go | `go.sum` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) | Java | `build.gradle`, `build.gradle.kts`, `pom.xml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
-| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package.json` | [Retire.js](https://retirejs.github.io/retire.js/) |
+| [npm](https://www.npmjs.com/) (7 and earlier), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package.json` | [Retire.js](https://retirejs.github.io/retire.js/) |
| [NuGet](https://www.nuget.org/) 4.9+ | .NET, C# | [`packages.lock.json`](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-lock-file) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
-| [setuptools](https://setuptools.readthedocs.io/en/latest/), [pip](https://pip.pypa.io/en/stable/), [Pipenv](https://pipenv.pypa.io/en/latest/) (*1*) | Python | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile`, `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
-| [sbt](https://www.scala-sbt.org/) 1.2 and below ([Ivy](http://ant.apache.org/ivy/)) | Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
+| [`setuptools`](https://setuptools.readthedocs.io/en/latest/), [pip](https://pip.pypa.io/en/stable/), [Pipenv](https://pipenv.pypa.io/en/latest/) (*1*) | Python | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile`, `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
+| [sbt](https://www.scala-sbt.org/) (*2*) | Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
1. [Pipenv](https://pipenv.pypa.io/en/latest/) projects are scanned when a `Pipfile` is present.
- Gemnasium scans the exact package versions listed in `Pipfile.lock` when this file is also present.
+1. Support for [sbt](https://www.scala-sbt.org/) 1.3 and above was added in GitLab 13.9.
Plans are underway for supporting the following languages, dependency managers, and dependency files. For details, see the issue link for each.
| Package Managers | Languages | Supported files | Scan tools | Issue |
| ------------------- | --------- | --------------- | ---------- | ----- |
| [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) |
-| [sbt](https://www.scala-sbt.org/) 1.3+ ([Coursier](https://get-coursier.io/))| Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#271345](https://gitlab.com/gitlab-org/gitlab/-/issues/271345) |
## Contribute your scanner
@@ -109,7 +108,7 @@ always take the latest dependency scanning artifact available.
### Customizing the dependency scanning settings
-The dependency scanning settings can be changed through [environment variables](#available-variables) by using the
+The dependency scanning settings can be changed through [CI/CD variables](#available-variables) by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
For example:
@@ -163,47 +162,63 @@ using environment variables.
The following variables allow configuration of global dependency scanning settings.
-| Environment variable | Description |
-| --------------------------------------- |------------ |
-| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
-| `DS_DEFAULT_ANALYZERS` | Override the names of the official default images. Read more about [customizing analyzers](analyzers.md). |
-| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. The bundle of certificates provided here is also used by other tools during the scanning process, such as `git`, `yarn`, or `npm`. |
-| `DS_EXCLUDED_PATHS` | Exclude vulnerabilities from output based on the paths. A comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"` |
-| `SECURE_LOG_LEVEL` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. Default: `info` |
+| CI/CD variables | Description |
+| ----------------------------|------------ |
+| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. The bundle of certificates provided here is also used by other tools during the scanning process, such as `git`, `yarn`, or `npm`. See [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority) for more details. |
+| `DS_DEFAULT_ANALYZERS` | Override the names of the official default images. Read more about [customizing analyzers](analyzers.md). |
+| `DS_EXCLUDED_PATHS` | Exclude vulnerabilities from output based on the paths. A comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. |
+| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
+| `SECURE_LOG_LEVEL` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. Default: `info`. |
#### Configuring specific analyzers used by dependency scanning
The following variables are used for configuring specific analyzers (used for a specific language/framework).
-| Environment variable | Analyzer | Default | Description |
-| --------------------------------------- | ------------------ | ---------------------------- |------------ |
-| `GEMNASIUM_DB_LOCAL_PATH` | `gemnasium` | `/gemnasium-db` | Path to local Gemnasium database. |
-| `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. |
-| `PIP_INDEX_URL` | `gemnasium-python` | `https://pypi.org/simple` | Base URL of Python Package Index. |
-| `PIP_EXTRA_INDEX_URL` | `gemnasium-python` | | Array of [extra URLs](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url) of package indexes to use in addition to `PIP_INDEX_URL`. Comma-separated. |
-| `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)|
-| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`. Maven and Gradle use the Java version specified by this value. |
-| `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-repos). |
-| `GRADLE_CLI_OPTS` | `gemnasium-maven` | | List of command line arguments that are passed to `gradle` by the analyzer. |
-| `SBT_CLI_OPTS` | `gemnasium-maven` | | List of command-line arguments that the analyzer passes to `sbt`. |
-| `BUNDLER_AUDIT_UPDATE_DISABLED` | `bundler-audit` | `"false"` | Disable automatic updates for the `bundler-audit` analyzer. Useful 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`. |
-| `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` environment 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` environment 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. |
-
-### Using private Maven repos
+| 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`. |
+| `GEMNASIUM_DB_LOCAL_PATH` | `gemnasium` | `/gemnasium-db` | Path to local Gemnasium database. |
+| `GEMNASIUM_DB_REMOTE_URL` | `gemnasium` | `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` | Repository URL for fetching the Gemnasium database. |
+| `GEMNASIUM_DB_REF_NAME` | `gemnasium` | `master` | Branch name for remote repository database. `GEMNASIUM_DB_REMOTE_URL` is required. |
+| `DS_REMEDIATE` | `gemnasium` | `"true"` | Enable automatic remediation of vulnerable dependencies. |
+| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`. Maven and Gradle use the Java version specified by this value. |
+| `MAVEN_CLI_OPTS` | `gemnasium-maven` | `"-DskipTests --batch-mode"` | List of command line arguments that are passed to `maven` by the analyzer. See an example for [using private repositories](../index.md#using-private-maven-repositories). |
+| `GRADLE_CLI_OPTS` | `gemnasium-maven` | | List of command line arguments that are passed to `gradle` by the analyzer. |
+| `SBT_CLI_OPTS` | `gemnasium-maven` | | List of command-line arguments that the analyzer passes to `sbt`. |
+| `PIP_INDEX_URL` | `gemnasium-python` | `https://pypi.org/simple` | Base URL of Python Package Index. |
+| `PIP_EXTRA_INDEX_URL` | `gemnasium-python` | | Array of [extra URLs](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url) of package indexes to use in addition to `PIP_INDEX_URL`. Comma-separated. |
+| `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. |
+
+### 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:
+
+```yaml
+variables:
+ ADDITIONAL_CA_CERT_BUNDLE: |
+ -----BEGIN CERTIFICATE-----
+ MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
+ ...
+ jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
+ -----END CERTIFICATE-----
+```
+
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
+
+### Using private Maven repositories
If your private Maven repository requires login credentials,
-you can use the `MAVEN_CLI_OPTS` environment variable.
+you can use the `MAVEN_CLI_OPTS` CI/CD variable.
-Read more on [how to use private Maven repositories](../index.md#using-private-maven-repos).
+Read more on [how to use private Maven repositories](../index.md#using-private-maven-repositories).
## Interacting with the vulnerabilities
@@ -370,12 +385,12 @@ Here are the requirements for using dependency scanning in an offline environmen
- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
- Docker Container Registry with locally available copies of dependency scanning [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers) images.
- If you have a limited access environment you need to allow access, such as using a proxy, to the advisory database: `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git`.
- If you are unable to permit access to `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` you must host an offline copy of this `git` repository and set the `GEMNASIUM_DB_REMOTE_URL` variable to the URL of this repository. For more information on configuration variables, see [Dependency Scanning](#configuring-dependency-scanning).
+ If you are unable to permit access to `https://gitlab.com/gitlab-org/security-products/gemnasium-db.git` you must host an offline copy of this `git` repository and set the `GEMNASIUM_DB_REMOTE_URL` CI/CD variable to the URL of this repository. For more information on configuration variables, see [Dependency Scanning](#configuring-dependency-scanning).
This advisory database is constantly being updated, so you must periodically sync your local copy with GitLab.
- _Only if scanning Ruby projects_: Host an offline Git copy of the [advisory database](https://github.com/rubysec/ruby-advisory-db).
-- _Only if scanning npm/yarn projects_: Host an offline copy of the [retire.js](https://github.com/RetireJS/retire.js/) [node](https://github.com/RetireJS/retire.js/blob/master/repository/npmrepository.json) and [js](https://github.com/RetireJS/retire.js/blob/master/repository/jsrepository.json) advisory databases.
+- _Only if scanning npm/yarn projects_: Host an offline copy of the [`retire.js`](https://github.com/RetireJS/retire.js/) [node](https://github.com/RetireJS/retire.js/blob/master/repository/npmrepository.json) and [`js`](https://github.com/RetireJS/retire.js/blob/master/repository/jsrepository.json) advisory databases.
Note that GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
meaning the runner tries to pull Docker images from the GitLab container registry even if a local
@@ -420,7 +435,7 @@ Support for custom certificate authorities was introduced in the following versi
| `retire.js` | [v2.4.0](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js/-/releases/v2.4.0) |
| `bundler-audit` | [v2.4.0](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit/-/releases/v2.4.0) |
-### Set dependency scanning CI job variables to use local dependency scanning analyzers
+### Set dependency scanning CI/CD job variables to use local dependency scanning analyzers
Add the following configuration to your `.gitlab-ci.yml` file. You must change the value of
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry. You must also change the
@@ -460,7 +475,7 @@ BUNDLER_AUDIT_ADVISORY_DB_REF_NAME: "master"
BUNDLER_AUDIT_ADVISORY_DB_URL: "gitlab.example.com/ruby-advisory-db.git"
```
-#### Python (setuptools)
+#### Python (setup tools)
When using self-signed certificates for your private PyPi repository, no extra job configuration (aside
from the template `.gitlab-ci.yml` above) is needed. However, you must update your `setup.py` to
@@ -526,5 +541,9 @@ scanning job might be triggered even if the scanner doesn't support your project
### Issues building projects with npm or yarn packages relying on Python 2
-Python 2 was removed (see: [Python 2 sunsetting](https://www.python.org/doc/sunset-python-2/)) from the `retire.js` analyzer in GitLab 13.7 (analyzer version 2.10.1). Projects using packages
+[Python 2 was removed](https://www.python.org/doc/sunset-python-2/) from the `retire.js` analyzer in GitLab 13.7 (analyzer version 2.10.1). Projects using packages
with a dependency on this version of Python should use `retire.js` version 2.10.0 or lower (for example, `registry.gitlab.com/gitlab-org/security-products/analyzers/retire.js:2.10.0`).
+
+### Error: `dependency_scanning is used for configuration only, and its script should not be executed`
+
+For information on this, see the [GitLab Secure troubleshooting section](../index.md#error-job-is-used-for-configuration-only-and-its-script-should-not-be-executed).
diff --git a/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png b/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png
deleted file mode 100644
index b792fbc9af1..00000000000
--- a/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/issue.png b/doc/user/application_security/img/issue.png
deleted file mode 100644
index 6467201df3f..00000000000
--- a/doc/user/application_security/img/issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 417ce70665c..4a23cd874be 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -57,7 +57,7 @@ see [configure SAST in the UI](sast/index.md#configure-sast-in-the-ui).
### Override the default registry base address
By default, GitLab security scanners use `registry.gitlab.com/gitlab-org/security-products/analyzers` as the
-base address for Docker images. You can override this globally by setting the variable
+base address for Docker images. You can override this globally by setting the CI/CD variable
`SECURE_ANALYZERS_PREFIX` to another location. Note that this affects all scanners at once.
## Security scanning tools
@@ -110,7 +110,7 @@ The scanning tools and vulnerabilities database are updated regularly.
| Secure scanning tool | Vulnerabilities database updates |
|:-------------------------------------------------------------|-------------------------------------------|
| [Container Scanning](container_scanning/index.md) | Uses `clair`. The latest `clair-db` version is used for each job by running the [`latest` Docker image tag](https://gitlab.com/gitlab-org/gitlab/blob/438a0a56dc0882f22bdd82e700554525f552d91b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L37). The `clair-db` database [is updated daily according to the author](https://github.com/arminc/clair-local-scan#clair-server-or-local). |
-| [Dependency Scanning](dependency_scanning/index.md) | Relies on `bundler-audit` (for Ruby gems), `retire.js` (for NPM packages), and `gemnasium` (the GitLab tool for all libraries). Both `bundler-audit` and `retire.js` fetch their vulnerabilities data from GitHub repositories, so vulnerabilities added to `ruby-advisory-db` and `retire.js` are immediately available. The tools themselves are updated once per month if there's a new version. The [Gemnasium DB](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is updated at least once a week. See our [current measurement of time from CVE being issued to our product being updated](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update). |
+| [Dependency Scanning](dependency_scanning/index.md) | Relies on `bundler-audit` (for Ruby gems), `retire.js` (for npm packages), and `gemnasium` (the GitLab tool for all libraries). Both `bundler-audit` and `retire.js` fetch their vulnerabilities data from GitHub repositories, so vulnerabilities added to `ruby-advisory-db` and `retire.js` are immediately available. The tools themselves are updated once per month if there's a new version. The [Gemnasium DB](https://gitlab.com/gitlab-org/security-products/gemnasium-db) is updated at least once a week. See our [current measurement of time from CVE being issued to our product being updated](https://about.gitlab.com/handbook/engineering/development/performance-indicators/#cve-issue-to-update). |
| [Dynamic Application Security Testing (DAST)](dast/index.md) | The scanning engine is updated on a periodic basis. See the [version of the underlying tool `zaproxy`](https://gitlab.com/gitlab-org/security-products/dast/blob/master/Dockerfile#L1). The scanning rules are downloaded at scan runtime. |
| [Static Application Security Testing (SAST)](sast/index.md) | Relies exclusively on [the tools GitLab wraps](sast/index.md#supported-languages-and-frameworks). The underlying analyzers are updated at least once per month if a relevant update is available. The vulnerabilities database is updated by the upstream tools. |
@@ -123,19 +123,12 @@ latest versions of the scanning tools without having to do anything. There are s
with this approach, however, and there is a
[plan to resolve them](https://gitlab.com/gitlab-org/gitlab/-/issues/9725).
-## Viewing security scan information in merge requests **(CORE)**
+## Viewing security scan information in merge requests **(FREE)**
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4393) in GitLab Core 13.5.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4393) in GitLab Free 13.5.
> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/273205) in 13.6.
> - Report download dropdown [added](https://gitlab.com/gitlab-org/gitlab/-/issues/273418) in 13.7.
-> - It's [deployed behind a feature flag](../feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
-> - It can be enabled or disabled for a single project.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-the-basic-security-widget). **(CORE ONLY)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/249550) in GitLab 13.9.
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
@@ -148,12 +141,12 @@ reports are available to download. To download a report, click on the
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.8.
Each security vulnerability in the merge request report or the
-[Security Dashboard](security_dashboard/index.md) is actionable. Click an entry to view detailed
+[Vulnerability Report](vulnerability_report/index.md) is actionable. Click an entry to view detailed
information with several options:
- [Dismiss vulnerability](#dismissing-a-vulnerability): Dismissing a vulnerability styles it in
strikethrough.
-- [Create issue](#creating-an-issue-for-a-vulnerability): Create a new issue with the title and
+- [Create issue](vulnerabilities/index.md#create-a-gitlab-issue-for-a-vulnerability): Create a new issue with the title and
description pre-populated with information from the vulnerability report. By default, such issues
are [confidential](../project/issues/confidential_issues.md).
- [Automatic Remediation](#automatic-remediation-for-vulnerabilities): For some vulnerabilities,
@@ -261,40 +254,29 @@ vulnerability as you learn more over time.
#### Dismissing multiple vulnerabilities
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35816) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
You can dismiss multiple vulnerabilities at once, providing an optional reason.
Selecting the checkboxes on the side of each vulnerability in the list selects that individual vulnerability.
Alternatively, you can select all the vulnerabilities in the list by selecting the checkbox in the table header.
Deselecting the checkbox in the header deselects all the vulnerabilities in the list.
-Once you have selected some vulnerabilities, a menu appears at the top of the table that allows you to select a dismissal reason.
+After you have selected some vulnerabilities, a menu appears at the top of the table that allows you to select a dismissal reason.
Pressing the "Dismiss Selected" button dismisses all the selected vulnerabilities at once, with the reason you chose.
![Multiple vulnerability dismissal](img/multi_select_v12_9.png)
-### Creating an issue for a vulnerability
-
-You can create an issue for a vulnerability by visiting the vulnerability's page and clicking
-**Create issue**, which you can find in the **Related issues** section.
-
-![Create issue from vulnerability](img/create_issue_from_vulnerability_v13_3.png)
-
-This creates a [confidential issue](../project/issues/confidential_issues.md) in the project the
-vulnerability came from, and pre-populates it with some useful information taken from the vulnerability
-report. Once the issue is created, you are redirected to it so you can edit, assign, or comment on
-it.
+### Create an issue for a vulnerability
-Upon returning to the group security dashboard, the vulnerability now has an associated issue next
-to the name.
-
-![Linked issue in the group security dashboard](img/issue.png)
+You can create a GitLab issue, or a Jira issue (if it's enabled) for a vulnerability. For more
+details, see [Vulnerability Pages](vulnerabilities/index.md).
### Automatic remediation for vulnerabilities
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5656) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.7.
-Some vulnerabilities can be fixed by applying the solution that GitLab
-automatically generates. Although the feature name is Automatic Remediation, this feature is also commonly called Auto-Remediation, Auto Remediation, or Suggested Solutions. The following scanners are supported:
+Some vulnerabilities can be fixed by applying the solution that GitLab automatically generates.
+Although the feature name is Automatic Remediation, this feature is also commonly called
+Auto-Remediation, Auto Remediation, or Suggested Solutions. The following scanners are supported:
- [Dependency Scanning](dependency_scanning/index.md):
Automatic Patch creation is only available for Node.js projects managed with
@@ -395,11 +377,11 @@ must be created. A [security scanner job](#security-scanning-tools) must be enab
job must be enabled for `License-Check`. When the proper jobs aren't configured, the following
appears:
-![Unconfigured Approval Rules](img/unconfigured_security_approval_rules_and_jobs_v13_4.png)
+![Un-configured Approval Rules](img/unconfigured_security_approval_rules_and_jobs_v13_4.png)
If at least one security scanner is enabled, you can enable the `Vulnerability-Check` approval rule. If a license scanning job is enabled, you can enable the `License-Check` rule.
-![Unconfigured Approval Rules with valid pipeline jobs](img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png)
+![Un-configured Approval Rules with valid pipeline jobs](img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png)
For this approval group, you must set the number of approvals required to greater than zero. You
must have Maintainer or Owner [permissions](../permissions.md#project-members-permissions)
@@ -446,10 +428,10 @@ environment.
Read how to [operate the Secure scanners in an offline environment](offline_deployments/index.md).
-## Using private Maven repos
+## Using private Maven repositories
If you have a private Apache Maven repository that requires login credentials,
-you can use the `MAVEN_CLI_OPTS` environment variable
+you can use the `MAVEN_CLI_OPTS` CI/CD variable
to pass a username and password. You can set it under your project's settings
so that your credentials aren't exposed in `.gitlab-ci.yml`.
@@ -457,8 +439,8 @@ If the username is `myuser` and the password is `verysecret` then you would
[set the following variable](../../ci/variables/README.md#create-a-custom-variable-in-the-ui)
under your project's settings:
-| Type | Key | Value |
-| ---- | --- | ----- |
+| Type | Key | Value |
+| -------- | ---------------- | ----- |
| Variable | `MAVEN_CLI_OPTS` | `--settings mysettings.xml -Drepository.password=verysecret -Drepository.user=myuser` |
```xml
@@ -522,13 +504,28 @@ This error appears when the included job's stage (named `test`) isn't declared i
To fix this issue, you can either:
- Add a `test` stage in your `.gitlab-ci.yml`.
-- Change the default stage of the included security jobs. For example, with SpotBugs (SAST):
+- Override the default stage of each security job. For example, to use a pre-defined stage name `unit-tests`:
```yaml
include:
- template: Security/SAST.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/License-Scanning.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml
+
+ stages:
+ - unit-tests
+
+ dependency_scanning:
+ stage: unit-tests
- spotbugs-sast:
+ license_scanning:
+ stage: unit-tests
+
+ sast:
+ stage: unit-tests
+
+ .secret-analyzer:
stage: unit-tests
```
@@ -541,7 +538,7 @@ This is often followed by the [error `No files to upload`](../../ci/pipelines/jo
and preceded by other errors or warnings that indicate why the JSON report wasn't generated. Please
check the entire job log for such messages. If you don't find these messages, retry the failed job
after setting `SECURE_LOG_LEVEL: "debug"` as a
-[custom environment variable](../../ci/variables/README.md#custom-environment-variables).
+[custom CI/CD variable](../../ci/variables/README.md#custom-cicd-variables).
This provides useful information to investigate further.
### Getting error message `sast job: config key may not be used with 'rules': only/except`
@@ -652,27 +649,16 @@ Analyzer results are displayed in the [job logs](../../ci/jobs/index.md#expand-a
or [Security Dashboard](security_dashboard/index.md).
There is [an open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/235772) in which changes to this behavior are being discussed.
-### Enable or disable the basic security widget **(CORE ONLY)**
+### Error: job `is used for configuration only, and its script should not be executed`
-The basic security widget is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../feature_flags.md)
-can opt to disable it.
+[Changes made in GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41260)
+to the `Security/Dependency-Scanning.gitlab-ci.yml` and `Security/SAST.gitlab-ci.yml`
+templates mean that if you enable the `sast` or `dependency_scanning` jobs by setting the `rules` attribute,
+they will fail with the error `(job) is used for configuration only, and its script should not be executed`.
-To enable it:
+The `sast` or `dependency_scanning` stanzas can be used to make changes to all SAST or Dependency Scanning,
+such as changing `variables` or the `stage`, but they cannot be used to define shared `rules`.
-```ruby
-# For the instance
-Feature.enable(:core_security_mr_widget)
-# For a single project
-Feature.enable(:core_security_mr_widget, Project.find(<project id>))
-```
-
-To disable it:
-
-```ruby
-# For the instance
-Feature.disable(:core_security_mr_widget)
-# For a single project
-Feature.disable(:core_security_mr_widget, Project.find(<project id>))
-```
+There [is an issue open to improve extendability](https://gitlab.com/gitlab-org/gitlab/-/issues/218444).
+Please upvote the issue to help with prioritization, and
+[contributions are welcomed](https://about.gitlab.com/community/contribute/).
diff --git a/doc/user/application_security/license_compliance/index.md b/doc/user/application_security/license_compliance/index.md
deleted file mode 100644
index 4c598d851a9..00000000000
--- a/doc/user/application_security/license_compliance/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../compliance/license_compliance/index.md'
----
-
-This document was moved to [another location](../../compliance/license_compliance/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/application_security/license_management/index.md b/doc/user/application_security/license_management/index.md
deleted file mode 100644
index bd67fca529f..00000000000
--- a/doc/user/application_security/license_management/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: ../../compliance/license_compliance/index.md
----
-
-This document was moved to [another location](../../compliance/license_compliance/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index 14ca27cdabe..9d16fb75410 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -53,7 +53,7 @@ internally-hosted registry or provide access to the individual scanner images.
You must also ensure that your app has access to common package repositories
that are not hosted on GitLab.com, such as npm, yarn, or Ruby gems. Packages
-from these repos can be obtained by temporarily connecting to a network or by
+from these repositories can be obtained by temporarily connecting to a network or by
mirroring the packages inside your own offline network.
### Interacting with the vulnerabilities
@@ -132,7 +132,7 @@ a bastion, and used only for this specific project.
#### Scheduling the updates
By default, this project's pipeline runs only once, when the `.gitlab-ci.yml` is added to the
-repo. To update the GitLab security scanners and signatures, it's necessary to run this pipeline
+repository. To update the GitLab security scanners and signatures, it's necessary to run this pipeline
regularly. GitLab provides a way to [schedule pipelines](../../../ci/pipelines/schedules.md). For
example, you can set this up to download and store the Docker images every week.
@@ -148,19 +148,19 @@ The project using the `Secure-Binaries.gitlab-ci.yml` template should now host a
images and resources needed to run GitLab Security features.
Next, you must tell the offline instance to use these resources instead of the default ones on
-GitLab.com. To do so, set the environment variable `SECURE_ANALYZERS_PREFIX` with the URL of the
+GitLab.com. To do so, set the CI/CD variable `SECURE_ANALYZERS_PREFIX` with the URL of the
project [container registry](../../packages/container_registry/index.md).
You can set this variable in the projects' `.gitlab-ci.yml`, or
-in the GitLab UI at the project or group level. See the [GitLab CI/CD environment variables page](../../../ci/variables/README.md#custom-environment-variables)
+in the GitLab UI at the project or group level. See the [GitLab CI/CD variables page](../../../ci/variables/README.md#custom-cicd-variables)
for more information.
#### Variables
-The following table shows which variables you can use with the `Secure-Binaries.gitlab-ci.yml`
+The following table shows which CI/CD variables you can use with the `Secure-Binaries.gitlab-ci.yml`
template:
-| VARIABLE | Description | Default value |
+| CI/CD variable | Description | Default value |
|-------------------------------------------|-----------------------------------------------|-----------------------------------|
| `SECURE_BINARIES_ANALYZERS` | Comma-separated list of analyzers to download | `"bandit, brakeman, gosec, and so on..."` |
| `SECURE_BINARIES_DOWNLOAD_IMAGES` | Used to disable jobs | `"true"` |
@@ -224,11 +224,11 @@ these steps:
Before running AutoDevOps, follow the [above steps](#using-the-official-gitlab-template)
to load those container images into the local container registry.
-1. Set the pipeline variable to ensure that AutoDevOps looks in the right place for those images.
+1. Set the CI/CD variable to ensure that AutoDevOps looks in the right place for those images.
The AutoDevOps templates leverage the `SECURE_ANALYZERS_PREFIX` variable to identify the location
of analyzer images. This variable is discussed above in [Using the secure bundle created](#using-the-secure-bundle-created).
Ensure that you set this variable to the correct value for where you loaded the analyzer images.
- You could consider doing this with a pipeline variable or by [modifying](../../../topics/autodevops/customize.md#customizing-gitlab-ciyml)
+ You could consider doing this with a project CI/CD variable or by [modifying](../../../topics/autodevops/customize.md#customizing-gitlab-ciyml)
the `.gitlab-ci.yml` file directly.
Once these steps are complete, GitLab has local copies of the Secure analyzers and is set up to use
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 1f0b461c91b..83f85951388 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -4,10 +4,10 @@ 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
---
-# SAST Analyzers **(CORE)**
+# SAST Analyzers **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3.
-> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to GitLab Free in 13.3.
SAST relies on underlying third party tools that are wrapped into what we call
"Analyzers". An analyzer is a
@@ -33,6 +33,7 @@ SAST supports the following official analyzers:
- [`phpcs-security-audit`](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit) (PHP CS security-audit)
- [`pmd-apex`](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex) (PMD (Apex only))
- [`security-code-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) (Security Code Scan (.NET))
+- [`semgrep`](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep) (Semgrep)
- [`sobelow`](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow) (Sobelow (Elixir Phoenix))
- [`spotbugs`](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) (SpotBugs with the Find Sec Bugs plugin (Ant, Gradle and wrapper, Grails, Maven and wrapper, SBT))
@@ -44,8 +45,8 @@ GitLab, but users can also integrate their own **custom images**.
## Official default analyzers
-Any custom change to the official analyzers can be achieved by using an
-[environment variable in your `.gitlab-ci.yml`](index.md#customizing-the-sast-settings).
+Any custom change to the official analyzers can be achieved by using a
+[CI/CD variable in your `.gitlab-ci.yml`](index.md#customizing-the-sast-settings).
### Using a custom Docker mirror
@@ -116,6 +117,19 @@ variables:
SAST_EXCLUDED_ANALYZERS: "eslint"
```
+## Post Analyzers **(ULTIMATE)**
+
+While analyzers are thin wrappers for executing scanners, post analyzers work to
+enrich the data generated within our reports.
+
+GitLab SAST post analyzers never modify report contents directly but work by
+augmenting results with additional properties (such as CWEs), location tracking fields,
+and a means of identifying false positives or insignificant findings.
+
+The implementation of post analyzers is determined by feature availability tiers, where
+simple data enrichment may occur within our free tier and most advanced processing is split
+into separate binaries or pipeline jobs.
+
## Custom Analyzers
You can provide your own analyzers by
@@ -140,28 +154,28 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
## Analyzers Data
-| Property / Tool | Apex | Bandit | Brakeman | ESLint security | SpotBugs | Flawfinder | Gosec | Kubesec Scanner | MobSF | NodeJsScan | PHP CS Security Audit | Security code Scan (.NET) | Sobelow |
-| --------------------------------------- | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :---------------------: | :-------------------------: | :----------------: |
-| Severity | ✓ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ |
-| Title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Description | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ |
-| File | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Start line | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| End line | ✓ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Start column | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ |
-| End column | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| External ID (for example, CVE) | ð„‚ | ð„‚ | âš  | ð„‚ | âš  | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| URLs | ✓ | ð„‚ | ✓ | ð„‚ | âš  | ð„‚ | âš  | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Internal doc/explanation | ✓ | âš  | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ✓ |
-| Solution | ✓ | ð„‚ | ð„‚ | ð„‚ | âš  | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Affected item (for example, class or package) | ✓ | ð„‚ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Confidence | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | x | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ✓ |
-| Source code extract | ð„‚ | ✓ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Internal ID | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ |
+| Property / Tool | Apex | Bandit | Brakeman | ESLint security | SpotBugs | Flawfinder | Gosec | Kubesec Scanner | MobSF | NodeJsScan | PHP CS Security Audit | Security code Scan (.NET) | Semgrep | Sobelow |
+|--------------------------------|------|--------|----------|-----------------|----------|------------|-------|-----------------|-------|------------|-----------------------|---------------------------|---------|---------|
+| Affected item (for example, class or package) | ✓ | ✗ | ✓ | ✗ | ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
+| Confidence | ✗ | ✓ | ✓ | ✗ | ✓ | x | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ⚠ | ✓ |
+| Description | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ |
+| End column | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
+| End line | ✓ | ✓ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
+| External ID (for example, CVE) | ✗ | ✗ | ⚠ | ✗ | ⚠ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ⚠ | ✗ |
+| File | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Internal doc/explanation | ✓ | ⚠ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ |
+| Internal ID | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ |
+| Severity | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ⚠ | ✗ |
+| Solution | ✓ | ✗ | ✗ | ✗ | ⚠ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ⚠ | ✗ |
+| Source code extract | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
+| Start column | ✓ | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ |
+| Start line | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| URLs | ✓ | ✗ | ✓ | ✗ | ⚠ | ✗ | ⚠ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
- ✓ => we have that data
- âš  => we have that data but it's partially reliable, or we need to extract it from unstructured content
-- ð„‚ => we don't have that data or it would need to develop specific or inefficient/unreliable logic to obtain it.
+- ✗ => we don't have that data or it would need to develop specific or inefficient/unreliable logic to obtain it.
The values provided by these tools are heterogeneous so they are sometimes
normalized into common values (for example, `severity`, `confidence`, and so on).
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index 59887c95c67..880edebfeda 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -8,7 +8,7 @@ type: reference, howto
# Static Application Security Testing (SAST)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.3.
-> - All open source (OSS) analyzers were moved to GitLab Core in GitLab 13.3.
+> - All open source (OSS) analyzers were moved to GitLab Free in GitLab 13.3.
NOTE:
The whitepaper ["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
@@ -83,6 +83,7 @@ You can also [view our language roadmap](https://about.gitlab.com/direction/secu
| Objective-C (iOS) | [MobSF (beta)](https://github.com/MobSF/Mobile-Security-Framework-MobSF) | 13.5 |
| PHP | [phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit) | 10.8 |
| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
+| Python | [semgrep](https://semgrep.dev) | 13.9 |
| React | [ESLint react plugin](https://github.com/yannickcr/eslint-plugin-react) | 12.5 |
| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3 |
| Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/), and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) |
@@ -111,24 +112,25 @@ The following analyzers have multi-project support:
- MobSF
- PMD
- Security Code Scan
+- Semgrep
- SpotBugs
- Sobelow
#### Enable multi-project support for Security Code Scan
Multi-project support in the Security Code Scan requires a Solution (`.sln`) file in the root of
-the repository. For details on the Solution format, see the Microsoft reference [Solution (.sln) file](https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/solution-dot-sln-file?view=vs-2019).
+the repository. For details on the Solution format, see the Microsoft reference [Solution (`.sln`) file](https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/solution-dot-sln-file?view=vs-2019).
### Making SAST analyzers available to all GitLab tiers
-All open source (OSS) analyzers have been moved to the GitLab Core tier as of GitLab 13.3.
+All open source (OSS) analyzers have been moved to the GitLab Free tier as of GitLab 13.3.
#### Summary of features per tier
Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
as shown in the following table:
-| Capability | In Core | In Ultimate |
+| Capability | In Free | In Ultimate |
|:-----------------------------------------------------------------------------------|:--------------------|:-------------------|
| [Configure SAST Scanners](#configuration) | **{check-circle}** | **{check-circle}** |
| [Customize SAST Settings](#customizing-the-sast-settings) | **{check-circle}** | **{check-circle}** |
@@ -188,14 +190,15 @@ page:
1. If the project does not have a `.gitlab-ci.yml` file, click **Enable** in the Static Application Security Testing (SAST) row, otherwise click **Configure**.
1. Enter the custom SAST values.
- Custom values are stored in the `.gitlab-ci.yml` file. For variables not in the SAST Configuration page, their values are left unchanged. Default values are inherited from the GitLab SAST template.
+ Custom values are stored in the `.gitlab-ci.yml` file. For CI/CD variables not in the SAST Configuration page, their values are left unchanged. Default values are inherited from the GitLab SAST template.
+
1. Optionally, expand the **SAST analyzers** section, select individual [SAST analyzers](analyzers.md) and enter custom analyzer values.
1. Click **Create Merge Request**.
1. Review and merge the merge request.
### Customizing the SAST settings
-The SAST settings can be changed through [environment variables](#available-variables)
+The SAST settings can be changed through [CI/CD variables](#available-variables)
by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
In the following example, we include the SAST template and at the same time we
@@ -254,8 +257,8 @@ To create a custom ruleset:
1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory.
1. In the `sast-ruleset.toml` file, do one of the following:
- - Disable predefined rules belonging to SAST analyzers. In this example, the disabled rules
- belong to `eslint` and `sobelow` and have the corresponding identifiers `type` and `value`:
+ - Disable predefined rules belonging to SAST analyzers. In this example, the three disabled rules
+ belong to `eslint` and `sobelow` by matching the corresponding identifiers' `type` and `value`:
```toml
[eslint]
@@ -265,6 +268,12 @@ To create a custom ruleset:
type = "eslint_rule_id"
value = "security/detect-object-injection"
+ [[eslint.ruleset]]
+ disable = true
+ [eslint.ruleset.identifier]
+ type = "cwe"
+ value = "185"
+
[sobelow]
[[sobelow.ruleset]]
disable = true
@@ -322,20 +331,20 @@ To create a custom ruleset:
value = "gosec-config.json"
```
-### Using environment variables to pass credentials for private repositories
+### Using CI/CD variables to pass credentials for private repositories
Some analyzers require downloading the project's dependencies in order to
perform the analysis. In turn, such dependencies may live in private Git
repositories and thus require credentials like username and password to download them.
Depending on the analyzer, such credentials can be provided to
-it via [custom environment variables](#custom-environment-variables).
+it via [custom CI/CD variables](#custom-cicd-variables).
-#### Using a variable to pass username and password to a private Maven repository
+#### Using a CI/CD variable to pass username and password to a private Maven repository
If your private Maven repository requires login credentials,
-you can use the `MAVEN_CLI_OPTS` environment variable.
+you can use the `MAVEN_CLI_OPTS` CI/CD variable.
-Read more on [how to use private Maven repositories](../index.md#using-private-maven-repos).
+Read more on [how to use private Maven repositories](../index.md#using-private-maven-repositories).
### Enabling Kubesec analyzer
@@ -361,7 +370,7 @@ a `before_script` execution to prepare your scan job.
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` variable can be provided to the
+If all dependencies are present, the `COMPILE=false` CI/CD variable can be provided to the
analyzer and compilation is skipped:
```yaml
@@ -401,7 +410,7 @@ can use `MAVEN_REPO_PATH`. See
### Available variables
-SAST can be [configured](#customizing-the-sast-settings) using environment variables.
+SAST can be [configured](#customizing-the-sast-settings) using CI/CD variables.
#### Logging level
@@ -421,63 +430,75 @@ From highest to lowest severity, the logging levels are:
#### Custom Certificate Authority
To trust a custom Certificate Authority, set the `ADDITIONAL_CA_CERT_BUNDLE` variable to the bundle
-of CA certs that you want to trust in the SAST environment.
+of CA certs that you want to trust in the SAST environment. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
+
+```yaml
+variables:
+ ADDITIONAL_CA_CERT_BUNDLE: |
+ -----BEGIN CERTIFICATE-----
+ MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
+ ...
+ jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
+ -----END CERTIFICATE-----
+```
+
+The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a [custom variable in the UI](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui), either as a `file`, which requires the path to the certificate, or as a variable, which requires the text representation of the certificate.
#### Docker images
-The following are Docker image-related variables.
+The following are Docker image-related CI/CD variables.
-| Environment variable | Description |
+| CI/CD variable | Description |
|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the default images (proxy). Read more about [customizing analyzers](analyzers.md). |
| `SAST_ANALYZER_IMAGE_TAG` | **DEPRECATED:** Override the Docker tag of the default images. Read more about [customizing analyzers](analyzers.md). |
-| `SAST_DEFAULT_ANALYZERS` | **DEPRECATED:** Override the names of default images. Scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777). |
+| `SAST_DEFAULT_ANALYZERS` | **DEPRECATED:** Override the names of default images. Scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777). |
| `SAST_EXCLUDED_ANALYZERS` | Names of default images that should never run. Read more about [customizing analyzers](analyzers.md). |
#### Vulnerability filters
Some analyzers make it possible to filter out vulnerabilities under a given threshold.
-| Environment variable | Default value | Description |
-|-------------------------------|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `SAST_EXCLUDED_PATHS` | `spec, test, tests, tmp` | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. You might need to exclude temporary directories used by your build tool as these can generate false positives. |
-| `SEARCH_MAX_DEPTH` | 4 | SAST searches the repository to detect the programming languages used, and selects the matching analyzers. Set the value of `SEARCH_MAX_DEPTH` to specify how many directory levels the search phase should span. After the analyzers have been selected, the _entire_ repository is analyzed. |
-| `SAST_BANDIT_EXCLUDED_PATHS` | | Comma-separated list of paths to exclude from scan. Uses Python's [`fnmatch` syntax](https://docs.python.org/2/library/fnmatch.html); For example: `'*/tests/*, */venv/*'` |
-| `SAST_BRAKEMAN_LEVEL` | 1 | Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low 3=High. |
-| `SAST_FLAWFINDER_LEVEL` | 1 | Ignore Flawfinder vulnerabilities under given risk level. Integer, 0=No risk, 5=High risk. |
-| `SAST_GOSEC_LEVEL` | 0 | Ignore Gosec vulnerabilities under given confidence level. Integer, 0=Undefined, 1=Low, 2=Medium, 3=High. |
+| CI/CD variable | Default value | Description |
+|------------------------------|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `SAST_EXCLUDED_PATHS` | `spec, test, tests, tmp` | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. You might need to exclude temporary directories used by your build tool as these can generate false positives. |
+| `SEARCH_MAX_DEPTH` | 4 | SAST searches the repository to detect the programming languages used, and selects the matching analyzers. Set the value of `SEARCH_MAX_DEPTH` to specify how many directory levels the search phase should span. After the analyzers have been selected, the _entire_ repository is analyzed. |
+| `SAST_BANDIT_EXCLUDED_PATHS` | | Comma-separated list of paths to exclude from scan. Uses Python's [`fnmatch` syntax](https://docs.python.org/2/library/fnmatch.html); For example: `'*/tests/*, */venv/*'` |
+| `SAST_BRAKEMAN_LEVEL` | 1 | Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low 3=High. |
+| `SAST_FLAWFINDER_LEVEL` | 1 | Ignore Flawfinder vulnerabilities under given risk level. Integer, 0=No risk, 5=High risk. |
+| `SAST_GOSEC_LEVEL` | 0 | Ignore Gosec vulnerabilities under given confidence level. Integer, 0=Undefined, 1=Low, 2=Medium, 3=High. |
#### Analyzer settings
-Some analyzers can be customized with environment variables.
-
-| Environment variable | Analyzer | Description |
-|---------------------------------------|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `SCAN_KUBERNETES_MANIFESTS` | Kubesec | Set to `"true"` to scan Kubernetes manifests. |
-| `KUBESEC_HELM_CHARTS_PATH` | Kubesec | Optional path to Helm charts that `helm` uses to generate a Kubernetes manifest that `kubesec` scans. If dependencies are defined, `helm dependency build` should be ran in a `before_script` to fetch the necessary dependencies. |
-| `KUBESEC_HELM_OPTIONS` | Kubesec | Additional arguments for the `helm` executable. |
-| `COMPILE` | SpotBugs | Set to `false` to disable project compilation and dependency fetching. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195252) in GitLab 13.1. |
-| `ANT_HOME` | SpotBugs | The `ANT_HOME` environment variable. |
-| `ANT_PATH` | SpotBugs | Path to the `ant` executable. |
-| `GRADLE_PATH` | SpotBugs | Path to the `gradle` executable. |
-| `JAVA_OPTS` | SpotBugs | Additional arguments for the `java` executable. |
-| `JAVA_PATH` | SpotBugs | Path to the `java` executable. |
-| `SAST_JAVA_VERSION` | SpotBugs | Which Java version to use. Supported versions are `8` and `11`. Defaults to `8`. |
-| `MAVEN_CLI_OPTS` | SpotBugs | Additional arguments for the `mvn` or `mvnw` executable. |
-| `MAVEN_PATH` | SpotBugs | Path to the `mvn` executable. |
-| `MAVEN_REPO_PATH` | SpotBugs | Path to the Maven local repository (shortcut for the `maven.repo.local` property). |
-| `SBT_PATH` | SpotBugs | Path to the `sbt` executable. |
-| `FAIL_NEVER` | SpotBugs | Set to `1` to ignore compilation failure. |
-| `SAST_GOSEC_CONFIG` | Gosec | Path to configuration for Gosec (optional). |
-| `PHPCS_SECURITY_AUDIT_PHP_EXTENSIONS` | phpcs-security-audit | Comma separated list of additional PHP Extensions. |
-| `SAST_DISABLE_BABEL` | NodeJsScan | Disable Babel processing for the NodeJsScan scanner. Set to `true` to disable Babel processing. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33065) in GitLab 13.2. |
-
-#### Custom environment variables
+Some analyzers can be customized with CI/CD variables.
+
+| CI/CD variable | Analyzer | Description |
+|-----------------------------|------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `SCAN_KUBERNETES_MANIFESTS` | Kubesec | Set to `"true"` to scan Kubernetes manifests. |
+| `KUBESEC_HELM_CHARTS_PATH` | Kubesec | Optional path to Helm charts that `helm` uses to generate a Kubernetes manifest that `kubesec` scans. If dependencies are defined, `helm dependency build` should be ran in a `before_script` to fetch the necessary dependencies. |
+| `KUBESEC_HELM_OPTIONS` | Kubesec | Additional arguments for the `helm` executable. |
+| `COMPILE` | SpotBugs | Set to `false` to disable project compilation and dependency fetching. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195252) in GitLab 13.1. |
+| `ANT_HOME` | SpotBugs | The `ANT_HOME` variable. |
+| `ANT_PATH` | SpotBugs | Path to the `ant` executable. |
+| `GRADLE_PATH` | SpotBugs | Path to the `gradle` executable. |
+| `JAVA_OPTS` | SpotBugs | Additional arguments for the `java` executable. |
+| `JAVA_PATH` | SpotBugs | Path to the `java` executable. |
+| `SAST_JAVA_VERSION` | SpotBugs | Which Java version to use. Supported versions are `8` and `11`. Defaults to `8`. |
+| `MAVEN_CLI_OPTS` | SpotBugs | Additional arguments for the `mvn` or `mvnw` executable. |
+| `MAVEN_PATH` | SpotBugs | Path to the `mvn` executable. |
+| `MAVEN_REPO_PATH` | SpotBugs | Path to the Maven local repository (shortcut for the `maven.repo.local` property). |
+| `SBT_PATH` | SpotBugs | Path to the `sbt` executable. |
+| `FAIL_NEVER` | SpotBugs | Set to `1` to ignore compilation failure. |
+| `SAST_GOSEC_CONFIG` | Gosec | Path to configuration for Gosec (optional). |
+| `PHPCS_SECURITY_AUDIT_PHP_EXTENSIONS` | phpcs-security-audit | Comma separated list of additional PHP Extensions. |
+| `SAST_DISABLE_BABEL` | NodeJsScan | Disable Babel processing for the NodeJsScan scanner. Set to `true` to disable Babel processing. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33065) in GitLab 13.2. |
+
+#### Custom CI/CD variables
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18193) in GitLab Ultimate 12.5.
-In addition to the aforementioned SAST configuration variables,
-all [custom environment variables](../../../ci/variables/README.md#custom-environment-variables) are propagated
+In addition to the aforementioned SAST configuration CI/CD variables,
+all [custom variables](../../../ci/variables/README.md#custom-cicd-variables) are propagated
to the underlying SAST analyzer images if
[the SAST vendored template](#configuration) is used.
@@ -669,22 +690,23 @@ For details on saving and transporting Docker images as a file, see Docker's doc
Support for custom certificate authorities was introduced in the following versions.
-| Analyzer | Version |
-| -------- | ------- |
-| `bandit` | [v2.3.0](https://gitlab.com/gitlab-org/security-products/analyzers/bandit/-/releases/v2.3.0) |
-| `brakeman` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman/-/releases/v2.1.0) |
-| `eslint` | [v2.9.2](https://gitlab.com/gitlab-org/security-products/analyzers/eslint/-/releases/v2.9.2) |
-| `flawfinder` | [v2.3.0](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder/-/releases/v2.3.0) |
-| `gosec` | [v2.5.0](https://gitlab.com/gitlab-org/security-products/analyzers/gosec/-/releases/v2.5.0) |
-| `kubesec` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/kubesec/-/releases/v2.1.0) |
-| `nodejs-scan` | [v2.9.5](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan/-/releases/v2.9.5) |
+| Analyzer | Version |
+| -------- | ------- |
+| `bandit` | [v2.3.0](https://gitlab.com/gitlab-org/security-products/analyzers/bandit/-/releases/v2.3.0) |
+| `brakeman` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman/-/releases/v2.1.0) |
+| `eslint` | [v2.9.2](https://gitlab.com/gitlab-org/security-products/analyzers/eslint/-/releases/v2.9.2) |
+| `flawfinder` | [v2.3.0](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder/-/releases/v2.3.0) |
+| `gosec` | [v2.5.0](https://gitlab.com/gitlab-org/security-products/analyzers/gosec/-/releases/v2.5.0) |
+| `kubesec` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/kubesec/-/releases/v2.1.0) |
+| `nodejs-scan` | [v2.9.5](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan/-/releases/v2.9.5) |
| `phpcs-security-audit` | [v2.8.2](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit/-/releases/v2.8.2) |
-| `pmd-apex` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex/-/releases/v2.1.0) |
-| `security-code-scan` | [v2.7.3](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/releases/v2.7.3) |
-| `sobelow` | [v2.2.0](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow/-/releases/v2.2.0) |
-| `spotbugs` | [v2.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs/-/releases/v2.7.1) |
+| `pmd-apex` | [v2.1.0](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex/-/releases/v2.1.0) |
+| `security-code-scan` | [v2.7.3](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/releases/v2.7.3) |
+| `semgrep` | [v0.0.1](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan/-/releases/v0.0.1) |
+| `sobelow` | [v2.2.0](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow/-/releases/v2.2.0) |
+| `spotbugs` | [v2.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs/-/releases/v2.7.1) |
-### Set SAST CI job variables to use local SAST analyzers
+### Set SAST CI/CD variables to use local SAST analyzers
Add the following configuration to your `.gitlab-ci.yml` file. You must replace
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
@@ -720,6 +742,10 @@ affected. Read more in
For information on this, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload).
+### Error: `sast is used for configuration only, and its script should not be executed`
+
+For information on this, see the [GitLab Secure troubleshooting section](../index.md#error-job-is-used-for-configuration-only-and-its-script-should-not-be-executed).
+
### Limitation when using rules:exists
The [SAST CI template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml)
@@ -750,3 +776,7 @@ For Maven builds, add the following to your `pom.xml` file:
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
```
+
+### Flawfinder encoding error
+
+This occurs when Flawfinder encounters an invalid UTF-8 character. To fix this, convert all source code in your project to UTF-8 character encoding. This can be done with [`cvt2utf`](https://github.com/x1angli/cvt2utf) or [`iconv`](https://www.gnu.org/software/libiconv/documentation/libiconv-1.13/iconv.1.html) either over the entire project or per job using the [`before_script`](../../../ci/yaml/README.md#before_script) feature.
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 0ae038924ec..98177e804f3 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -86,14 +86,14 @@ However not all features are available on every tier. See the breakdown below fo
Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
as shown in the following table:
-| Capability | In Core | In Ultimate |
-|:--------------------------------------------------------------------------|:--------------------|:-------------------|
-| [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}** |
+| Capability | In Free | In Ultimate |
+|:----------------------------------------------------------------|:--------------------|:-------------------|
+| [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}** |
| [Interaction with Vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
-| [Access to Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
+| [Access to Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
## Configuration
@@ -148,7 +148,7 @@ Third party cloud and SaaS providers can [express integration interest by fillin
### Customizing settings
-The Secret Detection scan settings can be changed through [environment variables](#available-variables)
+The Secret Detection scan settings can be changed through [CI/CD variables](#available-variables)
by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
@@ -156,8 +156,21 @@ To override a job definition, (for example, change properties like `variables` o
declare a job with the same name as the SAST job to override. Place this new job after the template
inclusion and specify any additional keys under it.
+WARNING:
+Beginning in GitLab 13.0, the use of [`only` and `except`](../../../ci/yaml/README.md#onlyexcept-basic)
+is no longer supported. When overriding the template, you must use [`rules`](../../../ci/yaml/README.md#rules) instead.
+
+#### GIT_DEPTH
+
+The [`GIT_DEPTH` CI/CD variable](../../../ci/runners/README.md#shallow-cloning) affects Secret Detection.
+The Secret Detection analyzer relies on generating patches between commits to scan content for
+secrets. If you override the default, ensure the value is greater than 1. If the number of commits
+in an MR is greater than the GIT_DEPTH value, Secret Detection will [fail to detect secrets](#error-couldnt-run-the-gitleaks-command-exit-status-2).
+
+#### Custom settings example
+
In the following example, we include the Secret Detection template and at the same time we
-override the `secret_detection` job with the `SECRET_DETECTION_HISTORIC_SCAN` variable to `true`:
+override the `secret_detection` job with the `SECRET_DETECTION_HISTORIC_SCAN` CI/CD variable to `true`:
```yaml
include:
@@ -171,20 +184,16 @@ secret_detection:
Because the template is [evaluated before](../../../ci/yaml/README.md#include)
the pipeline configuration, the last mention of the variable takes precedence.
-WARNING:
-Beginning in GitLab 13.0, the use of [`only` and `except`](../../../ci/yaml/README.md#onlyexcept-basic)
-is no longer supported. When overriding the template, you must use [`rules`](../../../ci/yaml/README.md#rules) instead.
-
#### Available variables
-Secret Detection can be customized by defining available variables:
+Secret Detection can be customized by defining available CI/CD variables:
-| Environment variable | Default value | Description |
-|-------------------------|---------------|-------------|
-| `SECRET_DETECTION_COMMIT_FROM` | - | The commit a Gitleaks scan starts at. |
-| `SECRET_DETECTION_COMMIT_TO` | - | The commit a Gitleaks scan ends at. |
-| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. |
-| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. |
+| CI/CD variable | Default value | Description |
+|-----------------------------------|---------------|-------------|
+| `SECRET_DETECTION_COMMIT_FROM` | - | The commit a Gitleaks scan starts at. |
+| `SECRET_DETECTION_COMMIT_TO` | - | The commit a Gitleaks scan ends at. |
+| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. |
+| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. |
### Custom rulesets **(ULTIMATE)**
@@ -231,7 +240,7 @@ To create a custom ruleset:
### Logging level
-To control the verbosity of logs set the `SECURE_LOG_LEVEL` environment variable. Messages of this logging level or higher are output. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1.
+To control the verbosity of logs set the `SECURE_LOG_LEVEL` CI/CD variable. Messages of this logging level or higher are output. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1.
From highest to lowest severity, the logging levels are:
@@ -246,7 +255,7 @@ From highest to lowest severity, the logging levels are:
GitLab 12.11 introduced support for scanning the full history of a repository. This new functionality
is particularly useful when you are enabling Secret Detection in a repository for the first time and you
want to perform a full secret scan. Running a secret scan on the full history can take a long time,
-especially for larger repositories with lengthy Git histories. We recommend not setting this variable
+especially for larger repositories with lengthy Git histories. We recommend not setting this CI/CD variable
as part of your normal job definition.
A new configuration variable ([`SECRET_DETECTION_HISTORIC_SCAN`](../sast/#vulnerability-filters))
@@ -307,7 +316,7 @@ Support for custom certificate authorities was introduced in the following versi
| -------- | ------- |
| secrets | [v3.0.0](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/releases/v3.0.0) |
-### Set Secret Detection CI job variables to use local Secret Detection analyzer
+### Set Secret Detection CI/CD variables to use local Secret Detection analyzer
Add the following configuration to your `.gitlab-ci.yml` file. You must replace
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
@@ -331,11 +340,15 @@ For information on this, see the [general Application Security troubleshooting s
### Error: `Couldn't run the gitleaks command: exit status 2`
-This error is usually caused by the `GIT_DEPTH` value of 50 that is set for all [projects by default](../../../ci/pipelines/settings.md#git-shallow-clone).
-
-For example, if a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` is set to 50, the Secret Detection job fails as the clone is not deep enough to contain all of the relevant commits.
+If a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` variable
+is set to 50 (a [project default](../../../ci/pipelines/settings.md#git-shallow-clone)),
+the Secret Detection job fails as the clone is not deep enough to contain all of the
+relevant commits.
-You can confirm this to be the cause of the error by implementing a [logging level](../../application_security/secret_detection/index.md#logging-level) of `debug`. Once implemented, the logs should look similar to the following example, wherein an "object not found" error can be seen:
+To confirm this as the cause of the error, set the
+[logging level](../../application_security/secret_detection/index.md#logging-level) to `debug`, then
+rerun the pipeline. The logs should look similar to the following example. The text "object not
+found" is a symptom of this error.
```plaintext
ERRO[2020-11-18T18:05:52Z] object not found
@@ -343,7 +356,9 @@ ERRO[2020-11-18T18:05:52Z] object not found
[ERRO] [secrets] [2020-11-18T18:05:52Z] â–¶ Gitleaks analysis failed: exit status 2
```
-If this is the case, we can resolve the issue by setting the [`GIT_DEPTH` variable](../../../ci/runners/README.md#shallow-cloning) to a higher value. In order to apply this only to the Secret Detection job, the following can be added to your `.gitlab-ci.yml`:
+To resolve the issue, set the [`GIT_DEPTH` CI/CD variable](../../../ci/runners/README.md#shallow-cloning)
+to a higher value. To apply this only to the Secret Detection job, the following can be added to
+your `.gitlab-ci.yml` file:
```yaml
secret_detection:
diff --git a/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_7.png b/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_7.png
deleted file mode 100644
index cd8dbed48fc..00000000000
--- a/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.png
deleted file mode 100644
index 9ade24be16f..00000000000
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard_dismissal_v13_4.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard_dismissal_v13_4.png
deleted file mode 100644
index eb1dfe6c6f4..00000000000
--- a/doc/user/application_security/security_dashboard/img/project_security_dashboard_dismissal_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_5.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_5.png
deleted file mode 100644
index c46a8295a53..00000000000
--- a/doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.png b/doc/user/application_security/security_dashboard/img/security_center_dashboard_empty_v13_4.png
index 5edceb32e5c..5edceb32e5c 100644
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.png
+++ b/doc/user/application_security/security_dashboard/img/security_center_dashboard_empty_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_link_v12_4.png b/doc/user/application_security/security_dashboard/img/security_center_dashboard_link_v12_4.png
index e0e80810b08..e0e80810b08 100644
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_link_v12_4.png
+++ b/doc/user/application_security/security_dashboard/img/security_center_dashboard_link_v12_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.png b/doc/user/application_security/security_dashboard/img/security_center_dashboard_v13_4.png
index 5379b5c6e5d..5379b5c6e5d 100644
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.png
+++ b/doc/user/application_security/security_dashboard/img/security_center_dashboard_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_center_settings_v13_4.png b/doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png
index 4223494c294..4223494c294 100644
--- a/doc/user/application_security/security_dashboard/img/instance_security_center_settings_v13_4.png
+++ b/doc/user/application_security/security_dashboard/img/security_center_settings_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.png b/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.png
deleted file mode 100644
index 760942c3239..00000000000
--- a/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 10bf6202a92..b08c19bee47 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -5,15 +5,15 @@ 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
---
-# GitLab Security Dashboard, Security Center, and Vulnerability Reports **(ULTIMATE)**
+# GitLab Security Dashboards and Security Center **(ULTIMATE)**
GitLab provides a comprehensive set of features for viewing and managing vulnerabilities:
-- Security dashboards: An overview of the security status in your instance, [groups](#group-security-dashboard), and
+- Security dashboards: An overview of the security status in your personal [Security Center](#security-center), [groups](#group-security-dashboard), and
[projects](#project-security-dashboard).
-- [Vulnerability reports](#vulnerability-report): Detailed lists of all vulnerabilities for the instance, group, project, or
+- [Vulnerability reports](../vulnerability_report/index.md): Detailed lists of all vulnerabilities for the Security Center, group, project, or
pipeline. This is where you triage and manage vulnerabilities.
-- [Security Center](#instance-security-center): A dedicated area for vulnerability management at the instance level. This
+- [Security Center](#security-center): A dedicated area for personalized vulnerability management. This
includes a security dashboard, vulnerability report, and settings.
You can also drill down into a vulnerability and get extra information on the
@@ -27,7 +27,7 @@ To benefit from these features, you must first configure one of the
## Supported reports
-The vulnerability report displays vulnerabilities detected by scanners such as:
+The security dashboard and vulnerability report displays information about vulnerabilities detected by scanners such as:
- [Container Scanning](../container_scanning/index.md)
- [Dynamic Application Security Testing](../dast/index.md)
@@ -68,7 +68,7 @@ the analyzer outputs an
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235558) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6.
At the project level, the Security Dashboard displays a chart with the number of vulnerabilities over time.
-Access it by navigating to **Security & Compliance > Security Dashboard**. Currently, we display historical
+Access it by navigating to **Security & Compliance > Security Dashboard**. We display historical
data up to 365 days.
![Project Security Dashboard](img/project_security_dashboard_chart_v13_6.png)
@@ -76,43 +76,6 @@ data up to 365 days.
Filter the historical data by clicking on the corresponding legend name. The image above, for example, shows
only the graph for vulnerabilities with **high** severity.
-### Vulnerability Report
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1.
-
-The vulnerabilities that exist in your project's
-[default branch](../../project/repository/branches/index.md#default-branch) are accessed by navigating to
-**Security & Compliance > Vulnerability Report**. By default, the Vulnerability Report is filtered to
-display all detected and confirmed vulnerabilities.
-
-The Vulnerability Report first displays the time at which the last pipeline completed on the project's
-default branch. There's also a link to view this in more detail. In the case of any pipeline failures,
-the number of failures is indicated. The failure notification takes you directly to
-the **Failed jobs** tab of the pipeline page.
-
-The Vulnerability Report next displays the total number of vulnerabilities by severity (for example,
-Critical, High, Medium, Low, Info, Unknown). Below this, a table shows each vulnerability's status, severity,
-description and if there is a Merge Request related to it. Clicking a vulnerability takes you to its
-[Vulnerability Details](../vulnerabilities)
-page to view more information about that vulnerability.
-
-![Project Vulnerability Report](img/project_security_dashboard_v13_5.png)
-
-You can filter the vulnerabilities by one or more of the following:
-
-| Filter | Available Options |
-| --- | --- |
-| Status | Detected, Confirmed, Dismissed, Resolved |
-| Severity | Critical, High, Medium, Low, Info, Unknown |
-| Scanner | [Available Scanners](../index.md#security-scanning-tools) |
-
-You can also dismiss vulnerabilities in the table:
-
-1. Select the checkbox for each vulnerability you want to dismiss.
-1. In the menu that appears, select the reason for dismissal and click **Dismiss Selected**.
-
-![Project Vulnerability Report](img/project_security_dashboard_dismissal_v13_4.png)
-
## Group Security Dashboard
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
@@ -146,30 +109,30 @@ Next to the timeline chart is a list of projects, grouped and sorted by the seve
Projects with no vulnerability tests configured don't appear in the list. Additionally, dismissed
vulnerabilities are excluded.
-Navigate to the group's [vulnerability report](#vulnerability-report-1) to view the vulnerabilities found.
+Navigate to the group's [vulnerability report](../vulnerability_report/index.md) to view the vulnerabilities found.
-## Instance Security Center
+## Security Center
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3426) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
-The Security Center is where you manage vulnerabilities for your instance. It displays the
-vulnerabilities present in the default branches of all the projects you configure. It includes the
-following:
+The Security Center is personal space where you manage vulnerabilities across all your projects. It
+displays the vulnerabilities present in the default branches of all the projects you configure. It includes
+the following:
- The [group security dashboard's](#group-security-dashboard) features.
-- A [vulnerability report](#vulnerability-report).
+- A [vulnerability report](../vulnerability_report/index.md).
- A dedicated settings area to configure which projects to display.
-![Instance Security Dashboard with projects](img/instance_security_dashboard_v13_4.png)
+![Security Center Dashboard with projects](img/security_center_dashboard_v13_4.png)
-You can access the Instance Security Center from the menu
+You can access the Security Center from the menu
bar at the top of the page. Under **More**, select **Security**.
-![Instance Security Center navigation link](img/instance_security_dashboard_link_v12_4.png)
+![Security Center navigation link](img/security_center_dashboard_link_v12_4.png)
The dashboard and vulnerability report are empty before you add projects.
-![Uninitialized Instance Security Center](img/instance_security_dashboard_empty_v13_4.png)
+![Uninitialized Security Center](img/security_center_dashboard_empty_v13_4.png)
### Adding projects to the Security Center
@@ -179,41 +142,11 @@ To add projects to the Security Center:
1. Search for and add one or more projects using the **Search your projects** field.
1. Click the **Add projects** button.
-![Adding projects to Instance Security Center](img/instance_security_center_settings_v13_4.png)
+![Adding projects to Security Center](img/security_center_settings_v13_4.png)
After you add projects, the security dashboard and vulnerability report display the vulnerabilities
found in those projects' default branches.
-## Export vulnerabilities
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
-
-You can export all your vulnerabilities in CSV (comma separated values) format by clicking the
-**{upload}** **Export** button located at top right of the Security Dashboard. When the report is
-ready, the CSV report downloads to your local machine. The report contains all vulnerabilities for
-the projects defined in the Security Dashboard, as filters don't apply to the export function.
-
-NOTE:
-It may take several minutes for the download to start if your project contains
-thousands of vulnerabilities. Don't close the page until the download finishes.
-
-The fields in the export include:
-
-- Group Name
-- Project Name
-- Scanner Type
-- Scanner Name
-- Status
-- Vulnerability
-- Details
-- Additional Info
-- Severity
-- [CVE](https://cve.mitre.org/) (Common Vulnerabilities and Exposures)
-- [CWE](https://cwe.mitre.org/) (Common Weakness Enumeration)
-- Other Identifiers
-
-![Export vulnerabilities](img/instance_security_dashboard_export_csv_v13_4.png)
-
## Keeping the dashboards up to date
The Security Dashboard displays information from the results of the most recent
@@ -245,35 +178,6 @@ When using [Auto DevOps](../../../topics/autodevops/index.md), use
[special environment variables](../../../topics/autodevops/customize.md#environment-variables)
to configure daily security scans.
-## Vulnerability report
-
-Each vulnerability report contains vulnerabilities from the latest scans that were merged
-into the default branch.
-
-![Vulnerability Report](img/group_vulnerability_report_v13_7.png)
-
-You can filter which vulnerabilities the vulnerability report displays by:
-
-| Filter | Available Options |
-| --- | --- |
-| Status | Detected, Confirmed, Dismissed, Resolved |
-| Severity | Critical, High, Medium, Low, Info, Unknown |
-| Scanner | [Available Scanners](../index.md#security-scanning-tools) |
-| Project | Projects configured in the Security Center settings |
-
-Clicking any vulnerability in the table takes you to its
-[Vulnerability Details](../vulnerabilities) page to see more information on that vulnerability.
-To create an issue associated with the vulnerability, click the **Create Issue** button.
-
-![Create an issue for the vulnerability](img/vulnerability_details_create_issue_v13_7.png)
-
-Once you create the issue, the linked issue icon in the vulnerability list:
-
-- Indicates that an issue has been created for that vulnerability.
-- Shows a tooltip that contains a link to the issue.
-
-![Display attached issues](img/vulnerability_list_table_v13_4.png)
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.png b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.png
new file mode 100644
index 00000000000..a668ce1a3b8
--- /dev/null
+++ b/doc/user/application_security/threat_monitoring/img/threat_monitoring_policy_alert_list_v13_9.png
Binary files differ
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index f7bd201aba9..13bde2ed38b 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -126,14 +126,13 @@ any pods. The policy itself is still deployed to the corresponding deployment na
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
-The policy editor allows you to create, edit, and delete policies. To
-create a new policy click the **New policy** button located in the
-**Policy** tab's header. To edit an existing policy, click**Edit
-policy** in the selected policy drawer.
-
-Note that the policy editor only supports the
-[CiliumNetworkPolicy](https://docs.cilium.io/en/v1.8/policy/)specification. Regular Kubernetes
-[NetworkPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#networkpolicy-v1-networking-k8s-io)
+You can use the policy editor to create, edit, and delete policies.
+
+- To create a new policy, click the **New policy** button located in the **Policy** tab's header.
+- To edit an existing policy, click **Edit policy** in the selected policy drawer.
+
+The policy editor only supports the [CiliumNetworkPolicy](https://docs.cilium.io/en/v1.8/policy/)
+specification. Regular Kubernetes [NetworkPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#networkpolicy-v1-networking-k8s-io)
resources aren't supported.
The policy editor has two modes:
@@ -163,3 +162,65 @@ Once your policy is complete, save it by pressing the **Save policy**
button at the bottom of the editor. Existing policies can also be
removed from the editor interface by clicking the **Delete policy**
button at the bottom of the editor.
+
+### Configuring Network Policy Alerts
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
+
+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/index.md#create-an-agent-record-in-gitlab)
+a Kubernetes Agent for this project.
+
+There are two ways to create policy alerts:
+
+- In the [policy editor UI](#container-network-policy-editor),
+ by clicking **Add alert**.
+- In the policy editor's YAML mode, through the `metadata.annotations` property:
+
+ ```yaml
+ metadata:
+ annotations:
+ app.gitlab.com/alert: 'true'
+ ```
+
+Once added, the UI updates and displays a warning about the dangers of too many alerts.
+
+#### Enable or disable Policy Alerts **(FREE SELF)**
+
+Policy Alerts is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:threat_monitoring_alerts)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:threat_monitoring_alerts)
+```
+
+### Container Network Policy Alert list
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
+
+The policy alert list displays your policy's alert activity. You can sort the list by the
+**Date and time** column, and the **Status** column. Use the selector menu in the **Status** column
+to set the status for each alert:
+
+- Unreviewed
+- In review
+- Resolved
+- Dismissed
+
+By default, the list doesn't display resolved or dismissed alerts. To show these alerts, clear the
+checkbox **Hide dismissed alerts**.
+
+![Policy Alert List](img/threat_monitoring_policy_alert_list_v13_9.png)
+
+For information on work in progress for the alerts dashboard, see [this epic](https://gitlab.com/groups/gitlab-org/-/epics/5041).
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index 705964dba66..50f05b687f7 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -5,60 +5,107 @@ group: Threat Insights
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Vulnerability Pages
+# Vulnerability Pages **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
-Each security vulnerability in a project's [Security Dashboard](../security_dashboard/index.md#project-security-dashboard) has an individual page which includes:
+Each security vulnerability in a project's [Vulnerability Report](../vulnerability_report/index.md) has an individual page which includes:
-- Details for the vulnerability.
+- Details of the vulnerability.
- The status of the vulnerability within the project.
- Available actions for the vulnerability.
- Any issues related to the vulnerability.
-On the vulnerability page, you can interact with the vulnerability in
-several different ways:
+On the vulnerability's page, you can:
-- [Change the Vulnerability Status](#changing-vulnerability-status) - You can change the
- status of a vulnerability to **Detected**, **Confirmed**, **Dismissed**, or **Resolved**.
-- [Create issue](#creating-an-issue-for-a-vulnerability) - Create a new issue with the
- title and description pre-populated with information from the vulnerability report.
- By default, such issues are [confidential](../../project/issues/confidential_issues.md).
-- [Link issues](#link-issues-to-the-vulnerability) - Link existing issues to vulnerability.
-- [Automatic remediation](#automatic-remediation-for-vulnerabilities) - For some vulnerabilities,
- a solution is provided for how to fix the vulnerability automatically.
+- [Change the vulnerability's status](#change-vulnerability-status).
+- [Create a GitLab issue](#create-a-gitlab-issue-for-a-vulnerability).
+- [Create a Jira issue](#create-a-jira-issue-for-a-vulnerability).
+- [Link issues to the vulnerability](#link-gitlab-issues-to-the-vulnerability).
+- [Automatically remediate the vulnerability](#automatically-remediate-the-vulnerability), if an
+ automatic solution is available.
-## Changing vulnerability status
+## Change vulnerability status
-You can switch the status of a vulnerability using the **Status** dropdown to one of
+You can change the status of a vulnerability using the **Status** dropdown to one of
the following values:
-| Status | Description |
-|-----------|------------------------------------------------------------------------------------------------------------------|
-| Detected | The default state for a newly discovered vulnerability |
-| Confirmed | A user has seen this vulnerability and confirmed it to be accurate |
+| Status | Description |
+|-----------|----------------------------------------------------------------------------------------------------------------|
+| Detected | The default state for a newly discovered vulnerability |
+| Confirmed | A user has seen this vulnerability and confirmed it to be accurate |
| Dismissed | A user has seen this vulnerability and dismissed it because it is not accurate or otherwise not to be resolved |
-| Resolved | The vulnerability has been fixed and is no longer valid |
+| Resolved | The vulnerability has been fixed and is no longer valid |
A timeline shows you when the vulnerability status has changed
and allows you to comment on a change.
-## Creating an issue for a vulnerability
+## Create a GitLab issue for a vulnerability
-You can create an issue for a vulnerability by selecting the **Create issue** button.
+To create a GitLab issue for a vulnerability:
-This allows the user to create a [confidential issue](../../project/issues/confidential_issues.md)
-in the project the vulnerability came from. Fields are pre-populated with pertinent information
-from the vulnerability report. After the issue is created, GitLab redirects you to the
-issue page so you can edit, assign, or comment on the issue.
+1. In GitLab, go to the vulnerability's page.
+1. Select **Create issue**.
-## Link issues to the vulnerability
+An issue is created in the project, prepopulated with information from the vulnerability report.
+The issue is then opened so you can take further action.
-You can link one or more existing issues to the vulnerability. This allows you to
+## Create a Jira issue for a vulnerability
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4677) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../../user/feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to
+> [disable it](#enable-or-disable-jira-integration-for-vulnerabilities).
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+Prerequisites:
+
+- [Enable Jira integration for vulnerabilities](../../project/integrations/jira.md). Select
+ **Enable Jira issues creation from vulnerabilities** when configuring the integration.
+
+To create a Jira issue for a vulnerability:
+
+1. Go to the vulnerability's page.
+1. Select **Create Jira issue**.
+
+An issue is created in the linked Jira project, with the **Summary** and **Description** fields
+pre-populated. The Jira issue is then opened in a new browser tab.
+
+### Enable or disable Jira integration for vulnerabilities **(ULTIMATE SELF)**
+
+The option to create a Jira issue for a vulnerability is under development but ready for production
+use. It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:jira_for_vulnerabilities)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:jira_for_vulnerabilities)
+```
+
+## Link GitLab issues to the vulnerability
+
+NOTE:
+If Jira issue support is enabled, GitLab issues are disabled so this feature is not available.
+
+You can link one or more existing GitLab issues to the vulnerability. This allows you to
indicate that this vulnerability affects multiple issues. It also allows you to indicate
that the resolution of one issue would resolve multiple vulnerabilities.
-## Automatic remediation for vulnerabilities
+Linked issues are shown in the Vulnerability Report and the vulnerability's page.
+
+## Automatically remediate the vulnerability
You can fix some vulnerabilities by applying the solution that GitLab automatically
generates for you. [Read more about the automatic remediation for vulnerabilities feature](../index.md#automatic-remediation-for-vulnerabilities).
diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md
index ce2297f7a1a..40b8f418737 100644
--- a/doc/user/application_security/vulnerabilities/severities.md
+++ b/doc/user/application_security/vulnerabilities/severities.md
@@ -37,33 +37,33 @@ the following tables:
| 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 |
-| [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` |
-| [eslint](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Unknown` |
-| [SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) | **{check-circle}** Yes | Integer | `1`, `2`, `3`, `11`, `12`, `18` |
-| [gosec](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` |
-| [bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` |
-| [phpcs-security-audit](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit) | **{check-circle}** Yes | String | `ERROR`, `WARNING` |
-| [pmd-apex](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex) | **{check-circle}** Yes | Integer | `1`, `2`, `3`, `4`, `5` |
-| [kubesec](https://gitlab.com/gitlab-org/security-products/analyzers/kubesec) | **{check-circle}** Yes | String | `CriticalSeverity`, `InfoSeverity` |
-| [secrets](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Critical` |
+| [`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 |
+| [`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` |
+| [`eslint`](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Unknown` |
+| [`SpotBugs`](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) | **{check-circle}** Yes | Integer | `1`, `2`, `3`, `11`, `12`, `18` |
+| [`gosec`](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` |
+| [`bandit`](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` |
+| [`phpcs-security-audit`](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit) | **{check-circle}** Yes | String | `ERROR`, `WARNING` |
+| [`pmd-apex`](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex) | **{check-circle}** Yes | Integer | `1`, `2`, `3`, `4`, `5` |
+| [`kubesec`](https://gitlab.com/gitlab-org/security-products/analyzers/kubesec) | **{check-circle}** Yes | String | `CriticalSeverity`, `InfoSeverity` |
+| [`secrets`](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Critical` |
## Dependency Scanning
| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
|------------------------------------------------------------------------------------------|------------------------------|----------------------------|-------------------------------------|
-| [bundler-audit](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit) | **{check-circle}** Yes | String | `low`, `medium`, `high`, `critical` |
-| [retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js) | **{check-circle}** Yes | String | `low`, `medium`, `high`, `critical` |
-| [gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | **{check-circle}** Yes | CVSS v2.0 Rating and CVSS v3.1 Qualitative Severity Rating | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)`, `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` |
+| [`bundler-audit`](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit) | **{check-circle}** Yes | String | `low`, `medium`, `high`, `critical` |
+| [`retire.js`](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js) | **{check-circle}** Yes | String | `low`, `medium`, `high`, `critical` |
+| [`gemnasium`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | **{check-circle}** Yes | CVSS v2.0 Rating and CVSS v3.1 Qualitative Severity Rating | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)`, `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` |
## Container Scanning
| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example |
|------------------------------------------------------------------------|--------------------------|----------------------------|--------------------------------------------------------------|
-| [klar](https://gitlab.com/gitlab-org/security-products/analyzers/klar) | **{check-circle}** Yes | String | `Negligible`, `Low`, `Medium`, `High`, `Critical`, `Defcon1` |
+| [`klar`](https://gitlab.com/gitlab-org/security-products/analyzers/klar) | **{check-circle}** Yes | String | `Negligible`, `Low`, `Medium`, `High`, `Critical`, `Defcon1` |
## Fuzz Testing
diff --git a/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v13_9.png b/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v13_9.png
new file mode 100644
index 00000000000..72443180e09
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/img/group_vulnerability_report_v13_9.png
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/img/project_security_dashboard_dismissal_v13_9.png b/doc/user/application_security/vulnerability_report/img/project_security_dashboard_dismissal_v13_9.png
new file mode 100644
index 00000000000..ef96cf31fa4
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/img/project_security_dashboard_dismissal_v13_9.png
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/img/project_security_dashboard_v13_9.png b/doc/user/application_security/vulnerability_report/img/project_security_dashboard_v13_9.png
new file mode 100644
index 00000000000..83e67a24b78
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/img/project_security_dashboard_v13_9.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png b/doc/user/application_security/vulnerability_report/img/vulnerability_details_create_issue_v13_7.png
index 5184ad85fa9..5184ad85fa9 100644
--- a/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png
+++ b/doc/user/application_security/vulnerability_report/img/vulnerability_details_create_issue_v13_7.png
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/img/vulnerability_list_table_v13_9.png b/doc/user/application_security/vulnerability_report/img/vulnerability_list_table_v13_9.png
new file mode 100644
index 00000000000..bfde7cd6c80
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/img/vulnerability_list_table_v13_9.png
Binary files differ
diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md
new file mode 100644
index 00000000000..28083e09f1c
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -0,0 +1,95 @@
+---
+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
+---
+
+# GitLab Vulnerability Reports **(ULTIMATE)**
+
+Each vulnerability report contains vulnerabilities from the scans of the most recent branch merged into the default branch.
+
+The vulnerability reports display the total number of vulnerabilities by severity (for example,
+Critical, High, Medium, Low, Info, Unknown). Below this, a table shows each vulnerability's detected date, status, severity, description, identifier, the scanner where it was detected, and activity (including related issues or available solutions). By default, the vulnerability report is filtered to display all detected and confirmed vulnerabilities.
+
+![Vulnerability Report](img/group_vulnerability_report_v13_9.png)
+
+You can filter which vulnerabilities display by:
+
+| Filter | Available Options |
+| --- | --- |
+| Status | Detected, Confirmed, Dismissed, Resolved |
+| Severity | Critical, High, Medium, Low, Info, Unknown |
+| Scanner | [Available Scanners](../index.md#security-scanning-tools) |
+| Project | Projects configured in the Security Center settings, or all projects in the group for the group level report. This filter is not displayed on the project level vulnerability report |
+| Activity | Vulnerabilities with issues and vulnerabilities that are no longer detected in the default branch |
+
+The Activity filter behaves differently from the other Vulnerability Report filters. The other filter options all OR together to show results from any vulnerability matching one of the filter criteria. With the Activity filter, the selected values form mutually exclusive sets to allow for precisely locating the desired vulnerability records. Additionally, not all options can be selected in combination. Selection behavior when using the Activity filter:
+
+| Activity Selection | Results Displayed |
+| --- | --- |
+| All | Vulnerabilities with any Activity status (same as ignoring this filter). Selecting this will deselect any other Activity filter options. |
+| No activity | Only vulnerabilities without either an associated Issue or that are no longer detected. Selecting this will deselect any other Activity filter options. |
+| With issues | Only vulnerabilities with one or more associated issues. Does not include vulnerabilities that also are no longer detected. |
+| No longer detected | Only vulnerabilities that are no longer detected in the latest pipeline scan of the `default` branch. Does not include vulnerabilities with one or more associated issues. |
+| With issues and No longer detected | Only vulnerabilities that have one or more associated issues and also are no longer detected in the latest pipeline scan of the `default` branch. |
+
+Clicking any vulnerability in the table takes you to its
+[vulnerability details](../vulnerabilities) page to see more information on that vulnerability.
+
+The **Activity** column indicates the number of issues that have been created for the vulnerability.
+Hover over an **Activity** entry and select a link go to that issue.
+
+![Display attached issues](img/vulnerability_list_table_v13_9.png)
+
+Contents of the unfiltered vulnerability report can be exported using our [export feature](#export-vulnerabilities).
+
+You can also dismiss vulnerabilities in the table:
+
+1. Select the checkbox for each vulnerability you want to dismiss.
+1. In the menu that appears, select the reason for dismissal and click **Dismiss Selected**.
+
+![Project Vulnerability Report](img/project_security_dashboard_dismissal_v13_9.png)
+
+## Project Vulnerability Report
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1.
+
+The vulnerabilities that exist in your project's
+[default branch](../../project/repository/branches/index.md#default-branch) are accessed by navigating to
+**Security & Compliance > Vulnerability Report**.
+
+The project vulnerability report first displays the time at which the last pipeline completed on the project's
+default branch. There's also a link to view this in more detail. In the case of any pipeline failures,
+the number of failures is indicated. The failure notification takes you directly to
+the **Failed jobs** tab of the pipeline page.
+
+![Project Vulnerability Report](img/project_security_dashboard_v13_9.png)
+
+## Export vulnerabilities
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
+
+You can export all your vulnerabilities in CSV (comma separated values) format by clicking the
+**{upload}** **Export** button located at top right of the Security Dashboard. When the report is
+ready, the CSV report downloads to your local machine. The report contains all vulnerabilities for
+the projects defined in the Security Dashboard, as filters don't apply to the export function.
+
+NOTE:
+It may take several minutes for the download to start if your project contains
+thousands of vulnerabilities. Don't close the page until the download finishes.
+
+The fields in the export include:
+
+- Group Name
+- Project Name
+- Scanner Type
+- Scanner Name
+- Status
+- Vulnerability
+- Details
+- Additional Information
+- Severity
+- [CVE](https://cve.mitre.org/) (Common Vulnerabilities and Exposures)
+- [CWE](https://cwe.mitre.org/) (Common Weakness Enumeration)
+- Other Identifiers
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index 546746af535..07593c98da9 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# AsciiDoc
+# AsciiDoc **(FREE)**
GitLab uses the [Asciidoctor](https://asciidoctor.org) gem to convert AsciiDoc content to HTML5.
Consult the [Asciidoctor User Manual](https://asciidoctor.org/docs/user-manual/) for a complete Asciidoctor reference.
@@ -40,7 +40,7 @@ Notice how line breaks are now preserved.
An indented (literal) paragraph disables text formatting,
preserves spaces and line breaks, and is displayed in a
-monospaced font:
+fixed-width font:
```plaintext
This literal paragraph is indented with one space.
@@ -186,8 +186,12 @@ Attach a block or paragraph to a list item using a list continuation (which you
* [ ] not checked
```
+<!-- vale gitlab.Spelling = NO -->
+
#### Callout
+<!-- vale gitlab.Spelling = YES -->
+
```plaintext
// enable callout bubbles by adding `:icons: font` to the document header
[,ruby]
diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md
index 4ece94447bc..de250bc5fb4 100644
--- a/doc/user/award_emojis.md
+++ b/doc/user/award_emojis.md
@@ -4,7 +4,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Award emoji **(CORE)**
+# Award emoji **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/1825) in GitLab 8.2.
> - GitLab 9.0 [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9570) the usage of native emoji if the platform
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 2c0d9b6c9ce..6f3d1e197f5 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.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 Kubernetes Agent **(PREMIUM ONLY)**
+# GitLab Kubernetes Agent **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
> - It's disabled on GitLab.com. Rolling this feature out to GitLab.com is [planned](https://gitlab.com/groups/gitlab-org/-/epics/3834).
@@ -190,7 +190,7 @@ the Agent in subsequent steps. You can create an Agent record either:
For full details, read [Starting a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
-- Through GraphQL: **(PREMIUM ONLY)**
+- Through GraphQL: **(PREMIUM SELF)**
```graphql
mutation createAgent {
@@ -439,49 +439,23 @@ The following example projects can help you get started with the Kubernetes Agen
- [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)
-- [Install GitLab Runner](runner.md)
### Deploying GitLab Runner with the Agent
-These instructions assume that the Agent is already set up as described in the
-[Get started with GitOps](#get-started-with-gitops-and-the-gitlab-agent):
+You can use the Kubernetes Agent to
+[deploy GitLab Runner in a Kubernetes cluster](http://docs.gitlab.com/runner/install/kubernetes-agent.html).
-1. Check the possible
- [Runner chart YAML values](https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/master/values.yaml)
- on the Runner chart documentation, and create a `runner-chart-values.yaml` file
- with the configuration that fits your needs, such as:
+## Management interfaces
- ```yaml
- ## The GitLab Server URL (with protocol) that want to register the runner against
- ## ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register
- ##
- gitlabUrl: https://gitlab.my.domain.com/
+Users with at least the [Developer](../../permissions.md) can access the user interface
+for the GitLab Kubernetes agent at **Operations > Kubernetes** and selecting the
+**GitLab Agent managed clusters** tab. This page lists all registered agents for
+the current project, and the configuration directory for each agent:
- ## The Registration Token for adding new Runners to the GitLab Server. This must
- ## be retrieved from your GitLab Instance.
- ## ref: https://docs.gitlab.com/ce/ci/runners/README.html
- ##
- runnerRegistrationToken: "XXXXXXYYYYYYZZZZZZ"
+![GitLab Kubernetes Agent list UI](../img/kubernetes-agent-ui-list_v13_8.png)
- ## For RBAC support:
- rbac:
- create: true
-
- ## Run all containers with the privileged flag enabled
- ## This will allow the docker:dind image to run if you need to run Docker
- ## commands. Please read the docs before turning this on:
- ## ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-dockerdind
- runners:
- privileged: true
- ```
-
-1. Create a single manifest file to install the Runner chart with your cluster agent:
-
- ```shell
- helm template --namespace gitlab gitlab-runner -f runner-chart-values.yaml gitlab/gitlab-runner > manifest.yaml
- ```
-
-1. Push your `manifest.yaml` to your manifest repository.
+Additional management interfaces are planned for the GitLab Kubernetes Agent.
+[Provide more feedback in the related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
## Troubleshooting
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index b71bbc29ef9..60d8cd352fc 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.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/#designated-technical-writers
---
-# Kubernetes Agent configuration repository **(PREMIUM ONLY)**
+# Kubernetes Agent configuration repository **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
> - It's disabled on GitLab.com. Rolling this feature out to GitLab.com is [planned](https://gitlab.com/groups/gitlab-org/-/epics/3834).
diff --git a/doc/user/clusters/agent/runner.md b/doc/user/clusters/agent/runner.md
index 715b27f951a..bbf07d4ea84 100644
--- a/doc/user/clusters/agent/runner.md
+++ b/doc/user/clusters/agent/runner.md
@@ -1,452 +1,8 @@
---
-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
+redirect_to: 'https://docs.gitlab.com/runner/install/kubernetes-agent.html'
---
-# Install GitLab Runner with Kubernetes Agent **(PREMIUM ONLY)**
+This document was moved to [another location](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
-These instructions to install the GitLab Runner assume the
-[GitLab Kubernetes Agent](index.md) is already configured.
-
-1. Review the possible [Runner chart YAML values](https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/master/values.yaml) in the Runner chart documentation,
- and create a `runner-chart-values.yaml` file with the configuration that fits
- your needs, such as:
-
- ```yaml
- # The GitLab Server URL (with protocol) that want to register the runner against
- # ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register
- #
- gitlabUrl: https://gitlab.my.domain.example.com/
-
- # The Registration Token for adding new Runners to the GitLab Server. This must
- # be retrieved from your GitLab Instance.
- # ref: https://docs.gitlab.com/ce/ci/runners/README.html
- #
- runnerRegistrationToken: "yrnZW46BrtBFqM7xDzE7dddd"
-
- # For RBAC support:
- rbac:
- create: true
-
- # Run all containers with the privileged flag enabled
- # This will allow the docker:dind image to run if you need to run Docker
- # commands. Please read the docs before turning this on:
- # ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-dockerdind
- runners:
- privileged: true
- ```
-
-1. Create a single manifest file to install the Runner chart with your cluster agent,
- replacing `GITLAB GITLAB-RUNNER` with your namespace:
-
- ```shell
- helm template --namespace GITLAB GITLAB-RUNNER -f runner-chart-values.yaml gitlab/gitlab-runner > runner-manifest.yaml
- ```
-
- An [example file is available](#example-runner-manifest).
-
-1. Push your `runner-manifest.yaml` to your manifest repository.
-
-## Example Runner manifest
-
-```yaml
-# This code is an example of a runner manifest looks like.
-# Create your own manifest.yaml file to meet your project's needs.
-
----
-# Source: gitlab-runner/templates/service-account.yaml
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- annotations:
- name: gitlab-runner-gitlab-runner
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
----
-# Source: gitlab-runner/templates/secrets.yaml
-apiVersion: v1
-kind: Secret
-metadata:
- name: "gitlab-runner-gitlab-runner"
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
-type: Opaque
-data:
- runner-registration-token: "FAKE-TOKEN"
- runner-token: ""
----
-# Source: gitlab-runner/templates/configmap.yaml
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: gitlab-runner-gitlab-runner
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
-data:
- entrypoint: |
- #!/bin/bash
- set -e
- mkdir -p /home/gitlab-runner/.gitlab-runner/
- cp /scripts/config.toml /home/gitlab-runner/.gitlab-runner/
-
- # Register the runner
- if [[ -f /secrets/accesskey && -f /secrets/secretkey ]]; then
- export CACHE_S3_ACCESS_KEY=$(cat /secrets/accesskey)
- export CACHE_S3_SECRET_KEY=$(cat /secrets/secretkey)
- fi
-
- if [[ -f /secrets/gcs-applicaton-credentials-file ]]; then
- export GOOGLE_APPLICATION_CREDENTIALS="/secrets/gcs-applicaton-credentials-file"
- elif [[ -f /secrets/gcs-application-credentials-file ]]; then
- export GOOGLE_APPLICATION_CREDENTIALS="/secrets/gcs-application-credentials-file"
- else
- if [[ -f /secrets/gcs-access-id && -f /secrets/gcs-private-key ]]; then
- export CACHE_GCS_ACCESS_ID=$(cat /secrets/gcs-access-id)
- # echo -e used to make private key multiline (in google json auth key private key is oneline with \n)
- export CACHE_GCS_PRIVATE_KEY=$(echo -e $(cat /secrets/gcs-private-key))
- fi
- fi
-
- if [[ -f /secrets/runner-registration-token ]]; then
- export REGISTRATION_TOKEN=$(cat /secrets/runner-registration-token)
- fi
-
- if [[ -f /secrets/runner-token ]]; then
- export CI_SERVER_TOKEN=$(cat /secrets/runner-token)
- fi
-
- if ! sh /scripts/register-the-runner; then
- exit 1
- fi
-
- # Run pre-entrypoint-script
- if ! bash /scripts/pre-entrypoint-script; then
- exit 1
- fi
-
- # Start the runner
- exec /entrypoint run --user=gitlab-runner \
- --working-directory=/home/gitlab-runner
-
- config.toml: |
- concurrent = 10
- check_interval = 30
- log_level = "info"
- listen_address = ':9252'
- configure: |
- set -e
- cp /init-secrets/* /secrets
- register-the-runner: |
- #!/bin/bash
- MAX_REGISTER_ATTEMPTS=30
-
- for i in $(seq 1 "${MAX_REGISTER_ATTEMPTS}"); do
- echo "Registration attempt ${i} of ${MAX_REGISTER_ATTEMPTS}"
- /entrypoint register \
- --non-interactive
-
- retval=$?
-
- if [ ${retval} = 0 ]; then
- break
- elif [ ${i} = ${MAX_REGISTER_ATTEMPTS} ]; then
- exit 1
- fi
-
- sleep 5
- done
-
- exit 0
-
- check-live: |
- #!/bin/bash
- if /usr/bin/pgrep -f .*register-the-runner; then
- exit 0
- elif /usr/bin/pgrep gitlab.*runner; then
- exit 0
- else
- exit 1
- fi
-
- pre-entrypoint-script: |
----
-# Source: gitlab-runner/templates/role.yaml
-apiVersion: rbac.authorization.k8s.io/v1
-kind: "Role"
-metadata:
- name: gitlab-runner-gitlab-runner
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
-rules:
-- apiGroups: [""]
- resources: ["*"]
- verbs: ["*"]
----
-# Source: gitlab-runner/templates/role-binding.yaml
-apiVersion: rbac.authorization.k8s.io/v1
-kind: "RoleBinding"
-metadata:
- name: gitlab-runner-gitlab-runner
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: "Role"
- name: gitlab-runner-gitlab-runner
-subjects:
-- kind: ServiceAccount
- name: gitlab-runner-gitlab-runner
- namespace: "gitlab"
----
-# Source: gitlab-runner/templates/deployment.yaml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: gitlab-runner-gitlab-runner
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: gitlab-runner-gitlab-runner
- template:
- metadata:
- labels:
- app: gitlab-runner-gitlab-runner
- chart: gitlab-runner-0.21.1
- release: "gitlab-runner"
- heritage: "Helm"
- annotations:
- checksum/configmap: a6623303f6fcc3a043e87ea937bb8399d2d0068a901aa9c3419ed5c7a5afa9db
- checksum/secrets: 32c7d2c16918961b7b84a005680f748e774f61c6f4e4da30650d400d781bbb30
- prometheus.io/scrape: 'true'
- prometheus.io/port: '9252'
- spec:
- securityContext:
- runAsUser: 100
- fsGroup: 65533
- terminationGracePeriodSeconds: 3600
- initContainers:
- - name: configure
- command: ['sh', '/config/configure']
- image: gitlab/gitlab-runner:alpine-v13.4.1
- imagePullPolicy: "IfNotPresent"
- env:
-
- - name: CI_SERVER_URL
- value: "https://gitlab.qa.joaocunha.eu/"
- - name: CLONE_URL
- value: ""
- - name: RUNNER_REQUEST_CONCURRENCY
- value: "1"
- - name: RUNNER_EXECUTOR
- value: "kubernetes"
- - name: REGISTER_LOCKED
- value: "true"
- - name: RUNNER_TAG_LIST
- value: ""
- - name: RUNNER_OUTPUT_LIMIT
- value: "4096"
- - name: KUBERNETES_IMAGE
- value: "ubuntu:16.04"
-
- - name: KUBERNETES_PRIVILEGED
- value: "true"
-
- - name: KUBERNETES_NAMESPACE
- value: "gitlab"
- - name: KUBERNETES_POLL_TIMEOUT
- value: "180"
- - name: KUBERNETES_CPU_LIMIT
- value: ""
- - name: KUBERNETES_CPU_LIMIT_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_MEMORY_LIMIT
- value: ""
- - name: KUBERNETES_MEMORY_LIMIT_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_CPU_REQUEST
- value: ""
- - name: KUBERNETES_CPU_REQUEST_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_MEMORY_REQUEST
- value: ""
- - name: KUBERNETES_MEMORY_REQUEST_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_SERVICE_ACCOUNT
- value: ""
- - name: KUBERNETES_SERVICE_CPU_LIMIT
- value: ""
- - name: KUBERNETES_SERVICE_MEMORY_LIMIT
- value: ""
- - name: KUBERNETES_SERVICE_CPU_REQUEST
- value: ""
- - name: KUBERNETES_SERVICE_MEMORY_REQUEST
- value: ""
- - name: KUBERNETES_HELPER_CPU_LIMIT
- value: ""
- - name: KUBERNETES_HELPER_MEMORY_LIMIT
- value: ""
- - name: KUBERNETES_HELPER_CPU_REQUEST
- value: ""
- - name: KUBERNETES_HELPER_MEMORY_REQUEST
- value: ""
- - name: KUBERNETES_HELPER_IMAGE
- value: ""
- - name: KUBERNETES_PULL_POLICY
- value: ""
- volumeMounts:
- - name: runner-secrets
- mountPath: /secrets
- readOnly: false
- - name: scripts
- mountPath: /config
- readOnly: true
- - name: init-runner-secrets
- mountPath: /init-secrets
- readOnly: true
- resources:
- {}
- serviceAccountName: gitlab-runner-gitlab-runner
- containers:
- - name: gitlab-runner-gitlab-runner
- image: gitlab/gitlab-runner:alpine-v13.4.1
- imagePullPolicy: "IfNotPresent"
- lifecycle:
- preStop:
- exec:
- command: ["/entrypoint", "unregister", "--all-runners"]
- command: ["/bin/bash", "/scripts/entrypoint"]
- env:
-
- - name: CI_SERVER_URL
- value: "https://gitlab.qa.joaocunha.eu/"
- - name: CLONE_URL
- value: ""
- - name: RUNNER_REQUEST_CONCURRENCY
- value: "1"
- - name: RUNNER_EXECUTOR
- value: "kubernetes"
- - name: REGISTER_LOCKED
- value: "true"
- - name: RUNNER_TAG_LIST
- value: ""
- - name: RUNNER_OUTPUT_LIMIT
- value: "4096"
- - name: KUBERNETES_IMAGE
- value: "ubuntu:16.04"
-
- - name: KUBERNETES_PRIVILEGED
- value: "true"
-
- - name: KUBERNETES_NAMESPACE
- value: "gitlab"
- - name: KUBERNETES_POLL_TIMEOUT
- value: "180"
- - name: KUBERNETES_CPU_LIMIT
- value: ""
- - name: KUBERNETES_CPU_LIMIT_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_MEMORY_LIMIT
- value: ""
- - name: KUBERNETES_MEMORY_LIMIT_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_CPU_REQUEST
- value: ""
- - name: KUBERNETES_CPU_REQUEST_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_MEMORY_REQUEST
- value: ""
- - name: KUBERNETES_MEMORY_REQUEST_OVERWRITE_MAX_ALLOWED
- value: ""
- - name: KUBERNETES_SERVICE_ACCOUNT
- value: ""
- - name: KUBERNETES_SERVICE_CPU_LIMIT
- value: ""
- - name: KUBERNETES_SERVICE_MEMORY_LIMIT
- value: ""
- - name: KUBERNETES_SERVICE_CPU_REQUEST
- value: ""
- - name: KUBERNETES_SERVICE_MEMORY_REQUEST
- value: ""
- - name: KUBERNETES_HELPER_CPU_LIMIT
- value: ""
- - name: KUBERNETES_HELPER_MEMORY_LIMIT
- value: ""
- - name: KUBERNETES_HELPER_CPU_REQUEST
- value: ""
- - name: KUBERNETES_HELPER_MEMORY_REQUEST
- value: ""
- - name: KUBERNETES_HELPER_IMAGE
- value: ""
- - name: KUBERNETES_PULL_POLICY
- value: ""
- livenessProbe:
- exec:
- command: ["/bin/bash", "/scripts/check-live"]
- initialDelaySeconds: 60
- timeoutSeconds: 1
- periodSeconds: 10
- successThreshold: 1
- failureThreshold: 3
- readinessProbe:
- exec:
- command: ["/usr/bin/pgrep","gitlab.*runner"]
- initialDelaySeconds: 10
- timeoutSeconds: 1
- periodSeconds: 10
- successThreshold: 1
- failureThreshold: 3
- ports:
- - name: metrics
- containerPort: 9252
- volumeMounts:
- - name: runner-secrets
- mountPath: /secrets
- - name: etc-gitlab-runner
- mountPath: /home/gitlab-runner/.gitlab-runner
- - name: scripts
- mountPath: /scripts
- resources:
- {}
- volumes:
- - name: runner-secrets
- emptyDir:
- medium: "Memory"
- - name: etc-gitlab-runner
- emptyDir:
- medium: "Memory"
- - name: init-runner-secrets
- projected:
- sources:
- - secret:
- name: "gitlab-runner-gitlab-runner"
- items:
- - key: runner-registration-token
- path: runner-registration-token
- - key: runner-token
- path: runner-token
- - name: scripts
- configMap:
- name: gitlab-runner-gitlab-runner
-```
+<!-- 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 --> \ No newline at end of file
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index b03dfb79ae0..ad92cf9b4ed 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.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 Apps
+# GitLab Managed Apps **(FREE)**
GitLab provides **GitLab Managed Apps** for various
applications which can be added directly to your configured cluster. These
@@ -20,10 +20,9 @@ have been deprecated, and are scheduled for removal in GitLab 14.0.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20822) in GitLab 12.6.
WARNING:
-This is an _alpha_ feature, and is subject to change at any time without
-prior notice.
+This is a _beta_ feature, and some applications might miss features to provide full integration with GitLab.
-This alternative method allows users to install GitLab-managed
+This primary method for installing applications to clusters allows users to install GitLab-managed
applications using GitLab CI/CD. It also allows customization of the
install using Helm `values.yaml` files.
@@ -418,6 +417,8 @@ You can check the recommended variables for each cluster type in the official do
- [Google GKE](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#deploy-cilium)
- [AWS EKS](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-eks/#deploy-cilium)
+Do not use `clusterType` for sandbox environments like [Minikube](https://minikube.sigs.k8s.io/docs/).
+
You can customize Cilium's Helm variables by defining the
`.gitlab/managed-apps/cilium/values.yaml` file in your cluster
management project. Refer to the
@@ -1199,53 +1200,8 @@ determine the endpoint of your Ingress or Knative application, you can
#### Determining the external endpoint manually
-If the cluster is on GKE, click the **Google Kubernetes Engine** link in the
-**Advanced settings**, or go directly to the
-[Google Kubernetes Engine dashboard](https://console.cloud.google.com/kubernetes/)
-and select the proper project and cluster. Then click **Connect** and execute
-the `gcloud` command in a local terminal or using the **Cloud Shell**.
-
-If the cluster is not on GKE, follow the specific instructions for your
-Kubernetes provider to configure `kubectl` with the right credentials.
-The output of the following examples show the external endpoint of your
-cluster. This information can then be used to set up DNS entries and forwarding
-rules that allow external access to your deployed applications.
-
-- If you installed Ingress using the **Applications**, run the following
- command:
-
- ```shell
- kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
- ```
-
-- Some Kubernetes clusters return a hostname instead, like
- [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
-
- ```shell
- kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
- ```
-
- If EKS is used, an [Elastic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/)
- is also created, which incurs additional AWS costs.
-
-- For Istio/Knative, the command is different:
-
- ```shell
- kubectl get svc --namespace=istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
- ```
-
-- Otherwise, you can list the IP addresses of all load balancers:
-
- ```shell
- kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
- ```
-
-You may see a trailing `%` on some Kubernetes versions. Do not include it.
-
-The Ingress is now available at this address, and routes incoming requests to
-the proper service based on the DNS name in the request. To support this, create
-a wildcard DNS CNAME record for the desired domain name. For example,
-`*.myekscluster.com` would point to the Ingress hostname obtained earlier.
+See the [Base domain section](../project/clusters/index.md#base-domain) for a
+guide on how to determine the external endpoint manually.
#### Using a static IP
diff --git a/doc/user/clusters/crossplane.md b/doc/user/clusters/crossplane.md
index c1ef798f5a8..bdf9d582b93 100644
--- a/doc/user/clusters/crossplane.md
+++ b/doc/user/clusters/crossplane.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
---
-# Crossplane configuration
+# Crossplane configuration **(FREE)**
After [installing](applications.md#crossplane) Crossplane, you must configure it for use.
The process of configuring Crossplane includes:
diff --git a/doc/user/clusters/environments.md b/doc/user/clusters/environments.md
index be4ac8151e4..cb721115e76 100644
--- a/doc/user/clusters/environments.md
+++ b/doc/user/clusters/environments.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Cluster Environments **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) for group-level clusters in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) for instance-level clusters in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3 for group-level clusters.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4 for instance-level clusters.
Cluster environments provide a consolidated view of which CI [environments](../../ci/environments/index.md) are
deployed to the Kubernetes cluster and it:
@@ -38,7 +38,7 @@ In order to:
- Show pod usage correctly, you must
[enable Deploy Boards](../project/deploy_boards.md#enabling-deploy-boards).
-Once you have successful deployments to your group-level or instance-level cluster:
+After you have successful deployments to your group-level or instance-level cluster:
1. Navigate to your group's **Kubernetes** page.
1. Click on the **Environments** tab.
diff --git a/doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.png b/doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.png
new file mode 100644
index 00000000000..3f9cc41838a
--- /dev/null
+++ b/doc/user/clusters/img/kubernetes-agent-ui-list_v13_8.png
Binary files differ
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index 55f507fb318..ef1b3ce44f2 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.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
---
-# Cluster management project
+# Cluster management project **(FREE)**
WARNING:
This is an _alpha_ feature, and it is subject to change at any time without
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 1428a0d4e80..74c608fcc38 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -58,7 +58,7 @@ Java 8 and Gradle 1.x projects are not supported. The minimum supported version
| JavaScript | [Bower](https://bower.io/), [npm](https://www.npmjs.com/) | |
| Go | [Godep](https://github.com/tools/godep), [go mod](https://github.com/golang/go/wiki/Modules) | |
| Java | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) | |
-| .NET | [Nuget](https://www.nuget.org/) | The .NET Framework is supported via the [mono project](https://www.mono-project.com/). There are, however, some limitations. The scanner doesn't support Windows-specific dependencies and doesn't report dependencies of your project's listed dependencies. Also, the scanner always marks detected licenses for all dependencies as `unknown`. |
+| .NET | [NuGet](https://www.nuget.org/) | The .NET Framework is supported via the [mono project](https://www.mono-project.com/). There are, however, some limitations. The scanner doesn't support Windows-specific dependencies and doesn't report dependencies of your project's listed dependencies. Also, the scanner always marks detected licenses for all dependencies as `unknown`. |
| Python | [pip](https://pip.pypa.io/en/stable/) | Python is supported through [requirements.txt](https://pip.pypa.io/en/stable/user_guide/#requirements-files) and [Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock). |
| Ruby | [gem](https://rubygems.org/) | |
@@ -70,7 +70,7 @@ The reported licenses might be incomplete or inaccurate.
| Language | Package managers |
|------------|---------------------------------------------------------------------------------------------------------------|
| JavaScript | [Yarn](https://yarnpkg.com/) |
-| Go | go get, gvt, glide, dep, trash, govendor |
+| Go | `go get`, `gvt`, `glide`, `dep`, `trash`, `govendor` |
| Erlang | [Rebar](https://www.rebar3.org/) |
| Objective-C, Swift | [Carthage](https://github.com/Carthage/Carthage), [CocoaPods](https://cocoapods.org/) v0.39 and below |
| Elixir | [Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) |
@@ -118,7 +118,7 @@ always take the latest License Compliance artifact available. Behind the scenes,
[GitLab License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/license-finder)
is used to detect the languages/frameworks and in turn analyzes the licenses.
-The License Compliance settings can be changed through [environment variables](#available-variables) by using the
+The License Compliance settings can be changed through [CI/CD variables](#available-variables) by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
### When License Compliance runs
@@ -128,20 +128,20 @@ wait for other stages to complete.
### Available variables
-License Compliance can be configured using environment variables.
+License Compliance can be configured using CI/CD variables.
-| Environment variable | Required | Description |
+| CI/CD variable | Required | Description |
|-----------------------------|----------|-------------|
-| `ADDITIONAL_CA_CERT_BUNDLE` | no | Bundle of trusted CA certificates (currently supported in Pip, Pipenv, Maven, Gradle, Yarn, and NPM projects). |
+| `ADDITIONAL_CA_CERT_BUNDLE` | no | Bundle of trusted CA certificates (currently supported in Pip, Pipenv, Maven, Gradle, Yarn, and npm projects). |
| `ASDF_JAVA_VERSION` | no | Version of Java to use for the scan. |
| `ASDF_NODEJS_VERSION` | no | Version of Node.js to use for the scan. |
| `ASDF_PYTHON_VERSION` | no | Version of Python to use for the scan. |
| `ASDF_RUBY_VERSION` | no | Version of Ruby to use for the scan. |
-| `GRADLE_CLI_OPTS` | no | Additional arguments for the gradle executable. If not supplied, defaults to `--exclude-task=test`. |
+| `GRADLE_CLI_OPTS` | no | Additional arguments for the Gradle executable. If not supplied, defaults to `--exclude-task=test`. |
| `LICENSE_FINDER_CLI_OPTS` | no | Additional arguments for the `license_finder` executable. For example, if you have multiple projects in nested directories, you can update your `.gitlab-ci-yml` template to specify a recursive scan, like `LICENSE_FINDER_CLI_OPTS: '--recursive'`. |
| `LM_JAVA_VERSION` | no | Version of Java. If set to `11`, Maven and Gradle use Java 11 instead of Java 8. |
| `LM_PYTHON_VERSION` | no | Version of Python. If set to `3`, dependencies are installed using Python 3 instead of Python 2.7. |
-| `MAVEN_CLI_OPTS` | no | Additional arguments for the mvn executable. If not supplied, defaults to `-DskipTests`. |
+| `MAVEN_CLI_OPTS` | no | Additional arguments for the `mvn` executable. If not supplied, defaults to `-DskipTests`. |
| `PIP_INDEX_URL` | no | Base URL of Python Package Index (default: `https://pypi.org/simple/`). |
| `SECURE_ANALYZERS_PREFIX` | no | Set the Docker registry base address to download the analyzer from. |
| `SETUP_CMD` | no | Custom setup for the dependency installation (experimental). |
@@ -154,7 +154,7 @@ The `license_management` image already embeds many auto-detection scripts, langu
and packages. Nevertheless, it's almost impossible to cover all cases for all projects.
That's why sometimes it's necessary to install extra packages, or to have extra steps
in the project automated setup, like the download and installation of a certificate.
-For that, a `LICENSE_MANAGEMENT_SETUP_CMD` environment variable can be passed to the container,
+For that, a `LICENSE_MANAGEMENT_SETUP_CMD` CI/CD variable can be passed to the container,
with the required commands to run before the license detection.
If present, this variable overrides the setup step necessary to install all the packages
@@ -195,7 +195,7 @@ license_scanning:
### Configuring Maven projects
-The License Compliance tool provides a `MAVEN_CLI_OPTS` environment variable which can hold
+The License Compliance tool provides a `MAVEN_CLI_OPTS` CI/CD variable which can hold
the command line arguments to pass to the `mvn install` command which is executed under the hood.
Feel free to use it for the customization of Maven execution. For example:
@@ -217,12 +217,12 @@ to explicitly add `-DskipTests` to your options.
If you still need to run tests during `mvn install`, add `-DskipTests=false` to
`MAVEN_CLI_OPTS`.
-#### Using private Maven repos
+#### Using private Maven repositories
If you have a private Maven repository which requires login credentials,
-you can use the `MAVEN_CLI_OPTS` environment variable.
+you can use the `MAVEN_CLI_OPTS` CI/CD variable.
-Read more on [how to use private Maven repos](../../application_security/index.md#using-private-maven-repos).
+Read more on [how to use private Maven repositories](../../application_security/index.md#using-private-maven-repositories).
You can also use `MAVEN_CLI_OPTS` to connect to a trusted Maven repository that uses a self-signed
or internally trusted certificate. For example:
@@ -248,7 +248,7 @@ generate a key store file, see the
License Compliance uses Python 3.8 and pip 19.1 by default.
If your project requires Python 2, you can switch to Python 2.7 and pip 10.0
-by setting the `LM_PYTHON_VERSION` environment variable to `2`.
+by setting the `LM_PYTHON_VERSION` CI/CD variable to `2`.
```yaml
include:
@@ -262,21 +262,21 @@ license_scanning:
### Custom root certificates for Python
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
-#### Using private Python repos
+#### Using private Python repositories
-If you have a private Python repository you can use the `PIP_INDEX_URL` [environment variable](#available-variables)
+If you have a private Python repository you can use the `PIP_INDEX_URL` [CI/CD variable](#available-variables)
to specify its location.
-### Configuring NPM projects
+### Configuring npm projects
-You can configure NPM projects by using an [`.npmrc`](https://docs.npmjs.com/configuring-npm/npmrc.html/)
+You can configure npm projects by using an [`.npmrc`](https://docs.npmjs.com/configuring-npm/npmrc.html/)
file.
-#### Using private NPM registries
+#### Using private npm registries
-If you have a private NPM registry you can use the
+If you have a private npm registry you can use the
[`registry`](https://docs.npmjs.com/using-npm/config/#registry)
setting to specify its location.
@@ -286,10 +286,10 @@ For example:
registry = https://npm.example.com
```
-#### Custom root certificates for NPM
+#### Custom root certificates for npm
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
To disable TLS verification you can provide the [`strict-ssl`](https://docs.npmjs.com/using-npm/config/#strict-ssl)
setting.
@@ -320,7 +320,7 @@ npmRegistryServer: "https://npm.example.com"
#### Custom root certificates for Yarn
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
### Configuring Bower projects
@@ -344,7 +344,7 @@ For example:
#### Custom root certificates for Bower
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables), or by
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), or by
specifying a `ca` setting in a [`.bowerrc`](https://bower.io/docs/config/#bowerrc-specification)
file.
@@ -365,9 +365,9 @@ source "https://gems.example.com"
#### Custom root certificates for Bundler
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables), or by
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), or by
specifying a [`BUNDLE_SSL_CA_CERT`](https://bundler.io/v2.0/man/bundle-config.1.html)
-[environment variable](../../../ci/variables/README.md#custom-environment-variables)
+[variable](../../../ci/variables/README.md#custom-cicd-variables)
in the job definition.
### Configuring Cargo projects
@@ -389,9 +389,9 @@ my-registry = { index = "https://my-intranet:8080/git/index" }
To supply a custom root certificate to complete TLS verification, do one of the following:
-- Use the `ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
+- Use the `ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
- Specify a [`CARGO_HTTP_CAINFO`](https://doc.rust-lang.org/cargo/reference/environment-variables.html)
- [environment variable](../../../ci/variables/README.md#custom-environment-variables)
+ [variable](../../../ci/variables/README.md#custom-cicd-variables)
in the job definition.
### Configuring Composer projects
@@ -422,9 +422,9 @@ For example:
#### Custom root certificates for Composer
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables), or by
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), or by
specifying a [`COMPOSER_CAFILE`](https://getcomposer.org/doc/03-cli.md#composer-cafile)
-[environment variable](../../../ci/variables/README.md#custom-environment-variables)
+[variable](../../../ci/variables/README.md#custom-cicd-variables)
in the job definition.
### Configuring Conan projects
@@ -487,7 +487,7 @@ example:
}
```
-If credentials are required to authenticate then you can configure a [protected variable](../../../ci/variables/README.md#protect-a-custom-variable)
+If credentials are required to authenticate then you can configure a [protected CI/CD variable](../../../ci/variables/README.md#protect-a-custom-variable)
following the naming convention described in the [`CONAN_LOGIN_USERNAME` documentation](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name).
#### Custom root certificates for Conan
@@ -496,14 +496,14 @@ You can provide custom certificates by adding a `.conan/cacert.pem` file to the
setting [`CA_CERT_PATH`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-cacert-path)
to `.conan/cacert.pem`.
-If you specify the `ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables), this
+If you specify the `ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables), this
variable's X.509 certificates are installed in the Docker image's default trust store and Conan is
configured to use this as the default `CA_CERT_PATH`.
### Configuring Go projects
To configure [Go modules](https://github.com/golang/go/wiki/Modules)
-based projects, specify [environment variables](https://golang.org/pkg/cmd/go/#hdr-Environment_variables)
+based projects, specify [CI/CD variables](https://golang.org/pkg/cmd/go/#hdr-Environment_variables)
in the `license_scanning` job's [variables](#available-variables) section in `.gitlab-ci.yml`.
If a project has [vendored](https://golang.org/pkg/cmd/go/#hdr-Vendor_Directories) its modules,
@@ -553,18 +553,18 @@ For example:
#### Custom root certificates for NuGet
You can supply a custom root certificate to complete TLS verification by using the
-`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
+`ADDITIONAL_CA_CERT_BUNDLE` [CI/CD variable](#available-variables).
### Migration from `license_management` to `license_scanning`
In GitLab 12.8 a new name for `license_management` job was introduced. This change was made to improve clarity around the purpose of the scan, which is to scan and collect the types of licenses present in a projects dependencies.
GitLab 13.0 drops support for `license_management`.
If you're using a custom setup for License Compliance, you're required
-to update your CI config accordingly:
+to update your CI configuration accordingly:
1. Change the CI template to `License-Scanning.gitlab-ci.yml`.
1. Change the job name to `license_scanning` (if you mention it in `.gitlab-ci.yml`).
-1. Change the artifact name to `license_scanning`, and the file name to `gl-license-scanning-report.json` (if you mention it in `.gitlab-ci.yml`).
+1. Change the artifact name to `license_scanning`, and the filename to `gl-license-scanning-report.json` (if you mention it in `.gitlab-ci.yml`).
For example, the following `.gitlab-ci.yml`:
@@ -640,7 +640,7 @@ For details on saving and transporting Docker images as a file, see Docker's doc
[`docker save`](https://docs.docker.com/engine/reference/commandline/save/), [`docker load`](https://docs.docker.com/engine/reference/commandline/load/),
[`docker export`](https://docs.docker.com/engine/reference/commandline/export/), and [`docker import`](https://docs.docker.com/engine/reference/commandline/import/).
-### Set License Compliance CI job variables to use local License Compliance analyzers
+### Set License Compliance CI/CD variables to use local License Compliance analyzers
Add the following configuration to your `.gitlab-ci.yml` file. You must replace `image` to refer to
the License Compliance Docker image hosted on your local Docker container registry:
@@ -657,15 +657,16 @@ license_scanning:
The License Compliance job should now use local copies of the License Compliance analyzers to scan
your code and generate security reports, without requiring internet access.
-Additional configuration may be needed for connecting to
-[private Bower registries](#using-private-bower-registries),
-[private Bundler registries](#using-private-bundler-registries),
-[private Conan registries](#using-private-bower-registries),
-[private Go registries](#using-private-go-registries),
-[private Maven repositories](#using-private-maven-repos),
-[private NPM registries](#using-private-npm-registries),
-[private Python repositories](#using-private-python-repos),
-and [private Yarn registries](#using-private-yarn-registries).
+Additional configuration may be needed for connecting to private registries for:
+
+- [Bower](#using-private-bower-registries),
+- [Bundler](#using-private-bundler-registries),
+- [Conan](#using-private-bower-registries),
+- [Go](#using-private-go-registries),
+- [Maven repositories](#using-private-maven-repositories),
+- [npm](#using-private-npm-registries),
+- [Python repositories](#using-private-python-repositories),
+- [Yarn](#using-private-yarn-registries).
### SPDX license list name matching
@@ -776,7 +777,7 @@ nodejs 12.16.3
ruby 2.7.2
```
-The next example shows how to activate the same versions of the tools mentioned above by using environment variables defined in your
+The next example shows how to activate the same versions of the tools mentioned above by using CI/CD variables defined in your
project's `.gitlab-ci.yml` file.
```yaml
@@ -789,7 +790,7 @@ license_scanning:
ASDF_RUBY_VERSION: '2.7.2'
```
-A full list of variables can be found in [environment variables](#available-variables).
+A full list of variables can be found in [CI/CD variables](#available-variables).
To find out what tools are pre-installed in the `license_scanning` Docker image use the following command:
diff --git a/doc/user/discussions/img/apply_suggestion_v12_7.png b/doc/user/discussions/img/apply_suggestion_v12_7.png
deleted file mode 100644
index c8c44149fd0..00000000000
--- a/doc/user/discussions/img/apply_suggestion_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/apply_suggestion_v13_9.png b/doc/user/discussions/img/apply_suggestion_v13_9.png
new file mode 100644
index 00000000000..e27fa629672
--- /dev/null
+++ b/doc/user/discussions/img/apply_suggestion_v13_9.png
Binary files differ
diff --git a/doc/user/discussions/img/confidential_comments_v13_9.png b/doc/user/discussions/img/confidential_comments_v13_9.png
new file mode 100644
index 00000000000..b5be5a622a9
--- /dev/null
+++ b/doc/user/discussions/img/confidential_comments_v13_9.png
Binary files differ
diff --git a/doc/user/discussions/img/custom_commit_v13_9.png b/doc/user/discussions/img/custom_commit_v13_9.png
new file mode 100644
index 00000000000..170c04542dd
--- /dev/null
+++ b/doc/user/discussions/img/custom_commit_v13_9.png
Binary files differ
diff --git a/doc/user/discussions/img/make_suggestion_v12_7.png b/doc/user/discussions/img/make_suggestion_v12_7.png
deleted file mode 100644
index 7eb84186b0a..00000000000
--- a/doc/user/discussions/img/make_suggestion_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/make_suggestion_v13_9.png b/doc/user/discussions/img/make_suggestion_v13_9.png
new file mode 100644
index 00000000000..92d5ba5ddda
--- /dev/null
+++ b/doc/user/discussions/img/make_suggestion_v13_9.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_thread_open_issue.png b/doc/user/discussions/img/resolve_thread_open_issue.png
deleted file mode 100644
index 2dd4ea3cb1b..00000000000
--- a/doc/user/discussions/img/resolve_thread_open_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/resolve_thread_open_issue_v13_9.png b/doc/user/discussions/img/resolve_thread_open_issue_v13_9.png
new file mode 100644
index 00000000000..8ff0f5e84dd
--- /dev/null
+++ b/doc/user/discussions/img/resolve_thread_open_issue_v13_9.png
Binary files differ
diff --git a/doc/user/discussions/img/suggestion_button_v12_7.png b/doc/user/discussions/img/suggestion_button_v12_7.png
deleted file mode 100644
index 3b7a4d625a3..00000000000
--- a/doc/user/discussions/img/suggestion_button_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/discussions/img/suggestion_button_v13_9.png b/doc/user/discussions/img/suggestion_button_v13_9.png
new file mode 100644
index 00000000000..58e0508d8cf
--- /dev/null
+++ b/doc/user/discussions/img/suggestion_button_v13_9.png
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index bf3e907bd24..9320dbba1b8 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -5,14 +5,14 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Threads
+# Threads **(FREE)**
-The ability to contribute conversationally is offered throughout GitLab.
+GitLab encourages communication through comments, threads, and suggestions.
-You can leave a comment in the following places:
+For example, you can create a comment in the following places:
- Issues
-- Epics **(ULTIMATE)**
+- Epics
- Merge requests
- Snippets
- Commits
@@ -44,7 +44,7 @@ Thread resolution helps keep track of progress during planning or code review.
Every standard comment or thread in merge requests, commits, commit diffs, and
snippets is initially displayed as unresolved. They can then be individually resolved by anyone
with at least Developer access to the project or by the author of the change being reviewed.
-If the thread has been resolved and a non-member unresolves their own response,
+If the thread has been resolved and a non-member un-resolves their own response,
this will also unresolve the discussion thread.
If the non-member then resolves this same response, this will resolve the discussion thread.
@@ -115,7 +115,7 @@ are resolved](#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolve
there will be an **open an issue to resolve them later** link in the merge
request widget.
-![Link in merge request widget](img/resolve_thread_open_issue.png)
+![Link in merge request widget](img/resolve_thread_open_issue_v13_9.png)
This will prepare an issue with its content referring to the merge request and
the unresolved threads.
@@ -161,7 +161,7 @@ box and hit **Save** for the changes to take effect.
From now on, you will not be able to merge from the UI until all threads
are resolved.
-![Only allow merge if all the threads are resolved message](img/resolve_thread_open_issue.png)
+![Only allow merge if all the threads are resolved message](img/resolve_thread_open_issue_v13_9.png)
### Automatically resolve merge request diff threads when they become outdated
@@ -281,10 +281,27 @@ edit existing comments. Non-team members are restricted from adding or editing c
Additionally, locked issues and merge requests can not be reopened.
+## Confidential Comments
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207473) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to enable it. **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+When creating a comment, you can decide to make it visible only to the project members (users with Reporter and higher permissions).
+
+To create a confidential comment, select the **Make this comment confidential** checkbox before you submit it.
+
+![Confidential comments](img/confidential_comments_v13_9.png)
+
## Merge Request Reviews
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) to GitLab Core in 13.1.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/28154) to GitLab Free in 13.1.
When looking at a Merge Request diff, you are able to start a review.
This allows you to create comments inside a Merge Request that are **only visible to you** until published,
@@ -370,13 +387,18 @@ From a merge request's **Discussion** tab, or from an epic/issue overview, find
![Notes filters dropdown options](img/index_notes_filters.png)
-Once you select one of the filters in a given issue or MR, GitLab will save
+After you select one of the filters in a given issue or MR, GitLab will save
your preference, so that it will persist when you visit the same page again
from any device you're logged into.
## Suggest Changes
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18008) in GitLab 11.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18008) in GitLab 11.6.
+> - Custom commit messages for suggestions was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25381) in GitLab 13.9.
+> - Custom commit messages for suggestions was deployed behind a [feature flag](../feature_flags.md), disabled by default.
+> - Custom commit messages for suggestions became enabled by default on GitLab 13.9.
+> - Custom commit messages for suggestions is enabled on GitLab.com and is recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disabled it](#enable-or-disable-custom-commit-messages-for-suggestions). **(FREE SELF)**
As a reviewer, you're able to suggest code changes with a simple
Markdown syntax in Merge Request Diff threads. Then, the
@@ -388,20 +410,27 @@ the merge request authored by the user that applied them.
1. Choose a line of code to be changed, add a new comment, then click
on the **Insert suggestion** icon in the toolbar:
- ![Add a new comment](img/suggestion_button_v12_7.png)
+ ![Add a new comment](img/suggestion_button_v13_9.png)
1. In the comment, add your suggestion to the pre-populated code block:
- ![Add a suggestion into a code block tagged properly](img/make_suggestion_v12_7.png)
+ ![Add a suggestion into a code block tagged properly](img/make_suggestion_v13_9.png)
1. Click either **Start a review** or **Add to review** to add your comment to a [review](#merge-request-reviews), or **Add comment now** to add the comment to the thread immediately.
The Suggestion in the comment can be applied by the merge request author
directly from the merge request:
- ![Apply suggestions](img/apply_suggestion_v12_7.png)
+ ![Apply suggestions](img/apply_suggestion_v13_9.png)
+
+1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25381) in GitLab 13.9,
+ you can opt to add a custom commit message to describe your change. If you don't
+ specify it, the default commit message will be used. Note that [this feature may not be available to you](#enable-or-disable-custom-commit-messages-for-suggestions).
+ Also, it is not supported for [batch suggestions](#batch-suggestions).
-Once the author applies a Suggestion, it will be marked with the **Applied** label,
+ ![Custom commit](img/custom_commit_v13_9.png)
+
+After the author applies a Suggestion, it will be marked with the **Applied** label,
the thread will be automatically resolved, and GitLab will create a new commit
and push the suggested change directly into the codebase in the merge request's
branch. [Developer permission](../permissions.md) is required to do so.
@@ -501,27 +530,6 @@ to your branch to address your reviewers' requests.
![A code change suggestion displayed, with the button to apply the batch of suggestions highlighted.](img/apply_batch_of_suggestions_v13_1.jpg "Apply a batch of suggestions")
-#### Enable or disable Batch Suggestions **(CORE ONLY)**
-
-Batch Suggestions is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can opt to disable it for your instance.
-
-To enable it:
-
-```ruby
-# Instance-wide
-Feature.enable(:batch_suggestions)
-```
-
-To disable it:
-
-```ruby
-# Instance-wide
-Feature.disable(:batch_suggestions)
-```
-
## Start a thread by replying to a standard comment
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30299) in GitLab 11.9
@@ -537,7 +545,7 @@ Clicking on the **Reply to comment** button will bring the reply area into focus
![Reply to comment feature](img/reply_to_comment.gif)
Replying to a non-thread comment will convert the non-thread comment to a
-thread once the reply is submitted. This conversion is considered an edit
+thread after the reply is submitted. This conversion is considered an edit
to the original comment, so a note about when it was last edited will appear underneath it.
This feature only exists for Issues, Merge requests, and Epics. Commits, Snippets and Merge request diff threads are
@@ -554,3 +562,62 @@ In the comment, click the **More Actions** menu and click **Assign to commenting
Click the button again to unassign the commenter.
![Assign to commenting user](img/quickly_assign_commenter_v13_1.png)
+
+## Enable or disable Confidential Comments **(FREE SELF)**
+
+Confidential Comments 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(:confidential_notes)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:confidential_notes)
+```
+
+## Enable or disable Custom commit messages for suggestions **(FREE SELF)**
+
+Custom commit messages for suggestions is under development but ready for production use. It is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can opt to disable it.
+
+To disable custom commit messages for suggestions:
+
+```ruby
+Feature.disable(:suggestions_custom_commit)
+```
+
+To enable custom commit messages for suggestions:
+
+```ruby
+Feature.enable(:suggestions_custom_commit)
+```
+
+## Enable or disable Batch Suggestions **(FREE SELF)**
+
+Batch Suggestions is
+deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can opt to disable it for your instance.
+
+To enable it:
+
+```ruby
+# Instance-wide
+Feature.enable(:batch_suggestions)
+```
+
+To disable it:
+
+```ruby
+# Instance-wide
+Feature.disable(:batch_suggestions)
+```
diff --git a/doc/user/feature_flags.md b/doc/user/feature_flags.md
index 9a601871349..a6be4c69f81 100644
--- a/doc/user/feature_flags.md
+++ b/doc/user/feature_flags.md
@@ -29,11 +29,11 @@ GitLab.com. To see the full notes:
1. Click the three-dots icon (ellipsis) to expand version history notes:
- ![Version history note with FF info](img/version_history_notes_collapsed_v13_2.png)
+ ![Version history note with FF information](img/version_history_notes_collapsed_v13_2.png)
1. Read the version history information:
- ![Version history note with FF info](img/feature_flags_history_note_info_v13_2.png)
+ ![Version history note with FF information](img/feature_flags_history_note_info_v13_2.png)
If you're a user of a GitLab self-managed instance and you want to try to use a
disabled feature, you can ask a [GitLab administrator to enable it](../administration/feature_flags.md),
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 611c1105961..f988d825c9f 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -97,7 +97,7 @@ Any settings or feature limits not listed here are using the defaults listed in
| ----------- | ----------------- | ------------- |
| Artifacts maximum size (compressed) | 1G | 100M |
| Artifacts [expiry time](../../ci/yaml/README.md#artifactsexpire_in) | From June 22, 2020, deleted after 30 days unless otherwise specified (artifacts created before that date have no expiry). | deleted after 30 days unless otherwise specified |
-| Scheduled Pipeline Cron | `*/5 * * * *` | `19 * * * *` |
+| Scheduled Pipeline Cron | `*/5 * * * *` | `3-59/10 * * * *` |
| [Max jobs in active pipelines](../../administration/instance_limits.md#number-of-jobs-in-active-pipelines) | `500` for Free tier, unlimited otherwise | Unlimited
| [Max CI/CD subscriptions to a project](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project) | `2` | Unlimited |
| [Max pipeline schedules in projects](../../administration/instance_limits.md#number-of-pipeline-schedules) | `10` for Free tier, `50` for all paid tiers | Unlimited |
@@ -114,7 +114,7 @@ or over the repository size limit, you can [reduce your repository size with Git
| Setting | GitLab.com | Default |
| ----------- | ----------- | ------------- |
| [Repository size including LFS](../admin_area/settings/account_and_limit_settings.md) | 10 GB | Unlimited |
-| Maximum import size | 5 GB | Unlimited |
+| Maximum import size | 5 GB | Unlimited ([Modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to unlimited in GitLab 13.8. |
NOTE:
`git push` and GitLab project imports are limited to 5 GB per request through Cloudflare. Git LFS and imports other than a file upload are not affected by this limit.
@@ -130,7 +130,7 @@ GitLab.com is fronted by Cloudflare. For incoming connections to GitLab.com you
For outgoing connections from CI/CD runners we are not providing static IP addresses.
All our runners are deployed into Google Cloud Platform (GCP) - any IP based
firewall can be configured by looking up all
-[IP address ranges or CIDR blocks for GCP](https://cloud.google.com/compute/docs/faq#where_can_i_find_product_name_short_ip_ranges).
+[IP address ranges or CIDR blocks for GCP](https://cloud.google.com/compute/docs/faq#find_ip_range).
## Hostname list
@@ -170,7 +170,7 @@ Linux shared runners on GitLab.com run in autoscale mode and are powered by Goog
Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each project, thus maximizing security. These shared runners are available for users and customers on GitLab.com.
-GitLab offers Gold tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
+GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, CoreOS and the latest Docker Engine
installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
@@ -534,14 +534,16 @@ 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 |
-|:--------------------------------------------------------------------------|:----------------------------|:------------------------------|
-| **Protected paths** (for a given **IP address**) | **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 |
-| **Unauthenticated** traffic (from a given **IP address**) | No specific limit | **500** requests per minute |
-| **Authenticated** API traffic (for a given **user**) | No specific limit | **2,000** requests per minute |
-| **Authenticated** non-API HTTP traffic (for a given **user**) | No specific limit | **1,000** requests per minute |
-| **All** traffic (from a given **IP address**) | **600** requests per minute | **2,000** requests per minute |
+| 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 |
More details are available on the rate limits for [protected
paths](#protected-paths-throttle) and [raw
@@ -622,13 +624,6 @@ dropped and users get
To help avoid abuse, project and group imports, exports, and export downloads are rate limited. See [Project import/export rate limits](../../user/project/settings/import_export.md#rate-limits) and [Group import/export rate limits](../../user/group/settings/import_export.md#rate-limits) for details.
-GitLab.com Import/Export Rate Limits are set to the default except:
-
-| Setting | GitLab.com | Default |
-|:-------------------------------------------------|:-----------|:--------|
-| Max Project Export requests per minute per user | 1 | 6 |
-| Max Group Export requests per minute per user | 1 | 6 |
-
### Non-configurable limits
See [non-configurable limits](../../security/rate_limits.md#non-configurable-limits) for information on
@@ -639,7 +634,7 @@ rate limits that are not configurable, and therefore also used on GitLab.com.
We use [Fluentd](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#fluentd) to parse our logs. Fluentd sends our logs to
[Stackdriver Logging](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#stackdriver) and [Cloud Pub/Sub](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#cloud-pubsub).
Stackdriver is used for storing logs long-term in Google Cold Storage (GCS). Cloud Pub/Sub
-is used to forward logs to an [Elastic cluster](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#elastic) using [pubsubbeat](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#pubsubbeat-vms).
+is used to forward logs to an [Elastic cluster](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#elastic) using [`pubsubbeat`](https://gitlab.com/gitlab-com/runbooks/tree/master/logging/doc#pubsubbeat-vms).
You can view more information in our runbooks such as:
diff --git a/doc/user/group/bulk_editing/index.md b/doc/user/group/bulk_editing/index.md
index 8db9c7fd76c..651bb7c055e 100644
--- a/doc/user/group/bulk_editing/index.md
+++ b/doc/user/group/bulk_editing/index.md
@@ -13,26 +13,26 @@ For more details, see [Bulk editing issues and merge requests at the project lev
If you want to update attributes across multiple issues, epics, or merge requests in a group, you
can do it by bulk editing them, that is, editing them together.
-NOTE:
Only the items visible on the current page are selected for bulk editing (up to 20).
![Bulk editing](img/bulk-editing_v13_2.png)
## Bulk edit issues at the group level
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7249) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7249) in GitLab 12.1.
+> - Assigning epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in GitLab 13.2.
+> - Editing health status [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) in GitLab 13.2.
+> - Editing iteration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196806) in GitLab 13.9.
-NOTE:
-You need a permission level of [Reporter or higher](../../permissions.md) to manage issues.
+Users with permission level of [Reporter or higher](../../permissions.md) can manage issues.
When bulk editing issues in a group, you can edit the following attributes:
-- Epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in
- [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.) **(PREMIUM)**
-- Milestone
-- Labels
-- Health status ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) in
- [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2.) **(ULTIMATE)**
+- [Epic](../epics/index.md)
+- [Milestone](../../project/milestones/index.md)
+- [Labels](../../project/labels.md)
+- [Health status](../../project/issues/index.md#health-status)
+- [Iteration](../iterations/index.md)
To update multiple project issues at the same time:
@@ -46,8 +46,7 @@ To update multiple project issues at the same time:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7250) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
-NOTE:
-You need a permission level of [Reporter or higher](../../permissions.md) to manage epics.
+Users with permission level of [Reporter or higher](../../permissions.md) can manage epics.
When bulk editing epics in a group, you can edit their labels.
@@ -63,8 +62,7 @@ To update multiple epics at the same time:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12719) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
-NOTE:
-You need a permission level of [Developer or higher](../../permissions.md) to manage merge requests.
+Users with permission level of [Developer or higher](../../permissions.md) can manage merge requests.
When bulk editing merge requests in a group, you can edit the following attributes:
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index ea7629d1f10..d9167388e66 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -5,7 +5,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
---
-# Group-level Kubernetes clusters
+# Group-level Kubernetes clusters **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) in GitLab 11.6.
@@ -38,12 +38,12 @@ in the project namespace.
If the project's cluster is available and not disabled, GitLab uses the
project's cluster before using any cluster belonging to the group containing
the project.
-In the case of sub-groups, GitLab uses the cluster of the closest ancestor group
+In the case of subgroups, GitLab uses the cluster of the closest ancestor group
to the project, provided the cluster is not disabled.
## Multiple Kubernetes clusters
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) to GitLab Core in 13.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) in GitLab Free 13.2.
You can associate more than one Kubernetes cluster to your group, and maintain different clusters
for different environments, such as development, staging, and production.
@@ -107,7 +107,7 @@ The domain should have a wildcard DNS configured to the Ingress IP address.
When adding more than one Kubernetes cluster to your project, you need to differentiate
them with an environment scope. The environment scope associates clusters with
[environments](../../../ci/environments/index.md) similar to how the
-[environment-specific variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-environment-variables)
+[environment-specific variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables)
work.
While evaluating which environment matches the environment scope of a
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index 0dbd7af1214..09e899a61ba 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -4,7 +4,7 @@ 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
---
-# Contribution Analytics **(STARTER)**
+# Contribution Analytics **(PREMIUM)**
> - Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3090) for subgroups in GitLab 12.2.
diff --git a/doc/user/group/dependency_proxy/index.md b/doc/user/group/dependency_proxy/index.md
deleted file mode 100644
index c4feed24132..00000000000
--- a/doc/user/group/dependency_proxy/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../packages/dependency_proxy/index.md'
----
-
-This document was moved to [another location](../../packages/dependency_proxy/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index 9cc7a35bc32..d4c1a5fc768 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -16,13 +16,15 @@ to them.
> - The New Epic form [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211533) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
> - In [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/229621) and later, the New Epic button on the Epics list opens the New Epic form.
+> - In [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45948) and later, you can create a new epic from an empty Roadmap.
To create an epic in the group you're in:
1. Get to the New Epic form:
- - From the **Epics** list in your group, select the **New Epic** button.
- - From an epic in your group, select the **New Epic** button.
+ - From the **Epics** list in your group, select **New epic**.
+ - From an epic in your group, select **New epic**.
- From anywhere, in the top menu, select **New...** (**{plus-square}**) **> New epic**.
+ - In an empty [roadmap](../roadmap/index.md), select **New epic**.
![New epic from an open epic](img/new_epic_from_groups_v13.7.png)
@@ -39,7 +41,7 @@ To create an epic in the group you're in:
## Edit an epic
-After you create an epic, you can edit change the following details:
+After you create an epic, you can edit the following details:
- Title
- Description
@@ -152,6 +154,9 @@ To make an epic confidential:
## Manage issues assigned to an epic
+This section collects instructions for all the things you can do with [issues](../../project/issues/index.md)
+in relation to epics.
+
### Add a new issue to an epic
You can add an existing issue to an epic, or create a new issue that's
@@ -176,7 +181,7 @@ To add a new issue to an epic:
- Search for the desired issue by entering part of the issue's title, then selecting the desired
match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
- If there are multiple issues to be added, press <kbd>Spacebar</kbd> and repeat this step.
+ If there are multiple issues to be added, press <kbd>Space</kbd> and repeat this step.
1. Select **Add**.
#### Create an issue from an epic
@@ -278,7 +283,7 @@ To add a child epic to an epic:
- Search for the desired issue by entering part of the epic's title, then selecting the desired
match (introduced in [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/9126)).
- If there are multiple epics to be added, press <kbd>Spacebar</kbd> and repeat this step.
+ If there are multiple epics to be added, press <kbd>Space</kbd> and repeat this step.
1. Select **Add**.
### Move child epics between epics
diff --git a/doc/user/group/img/group_code_coverage_analytics_v13_7.png b/doc/user/group/img/group_code_coverage_analytics_v13_7.png
deleted file mode 100644
index 769953b1355..00000000000
--- a/doc/user/group/img/group_code_coverage_analytics_v13_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/img/group_code_coverage_analytics_v13_9.png b/doc/user/group/img/group_code_coverage_analytics_v13_9.png
new file mode 100644
index 00000000000..8cd71396381
--- /dev/null
+++ b/doc/user/group/img/group_code_coverage_analytics_v13_9.png
Binary files differ
diff --git a/doc/user/group/import/img/bulk_imports_v13_8.png b/doc/user/group/import/img/bulk_imports_v13_8.png
index 31234f9fcea..ae4d8567d80 100644
--- a/doc/user/group/import/img/bulk_imports_v13_8.png
+++ b/doc/user/group/import/img/bulk_imports_v13_8.png
Binary files differ
diff --git a/doc/user/group/import/img/import_panel_v13_8.png b/doc/user/group/import/img/import_panel_v13_8.png
index 1fb7fbad291..28d61785098 100644
--- a/doc/user/group/import/img/import_panel_v13_8.png
+++ b/doc/user/group/import/img/import_panel_v13_8.png
Binary files differ
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index d051a134af1..f4d15dce1cd 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -5,7 +5,7 @@ group: Import
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Import groups from another instance of GitLab **(CORE)**
+# Import groups from another instance of GitLab **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7.
> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
@@ -16,7 +16,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature is [under construction](https://gitlab.com/groups/gitlab-org/-/epics/2771) and currently migrates only some of the Group data. Please see below for the full list of what is included in the migration at this time.
-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 sub-group of any existing top-level group.
+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.
The following resources are migrated to the target instance:
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 069dea40ba5..4c63bae7e44 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -288,7 +288,7 @@ In [GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab adminis
There are two different ways to add a new project to a group:
-- Select a group, and then click **New project**. You can then continue [creating your project](../../gitlab-basics/create-project.md).
+- Select a group, and then click **New project**. You can then continue [creating your project](../../user/project/working_with_projects.md#create-a-project).
![New project](img/create_new_project_from_group_v13_6.png)
@@ -301,7 +301,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 Premium](https://about.gitlab.com/pricing/) 10.5.
> - Brought to [GitLab Starter](https://about.gitlab.com/pricing/) in 10.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) to [GitLab Free](https://about.gitlab.com/pricing/) in 11.10.
By default, [Developers and Maintainers](../permissions.md#group-members-permissions) can create projects under a group.
@@ -327,7 +327,7 @@ A group's **Details** page includes tabs for:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) in GitLab [Starter](https://about.gitlab.com/pricing/) 12.10 as
a [beta feature](https://about.gitlab.com/handbook/product/#beta)
-The group details view also shows the number of the following items created in the last 90 days: **(STARTER)**
+The group details view also shows the number of the following items created in the last 90 days: **(PREMIUM)**
- Merge requests.
- Issues.
@@ -389,7 +389,7 @@ To share a given group, for example, 'Frontend' with another group, for example,
All the members of the 'Engineering' group will have been added to 'Frontend'.
-## Manage group memberships via LDAP **(STARTER ONLY)**
+## 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.
@@ -400,10 +400,12 @@ For more information on the administration of LDAP and group sync, refer to the
NOTE:
If an LDAP user is a group member when LDAP Synchronization is added, and they are not part of the LDAP group, they will be removed from the group.
-### Creating group links via CN **(STARTER ONLY)**
+### Creating group links via CN **(PREMIUM SELF)**
To create group links via CN:
+<!-- vale gitlab.Spelling = NO -->
+
1. Select the **LDAP Server** for the link.
1. Select `LDAP Group cn` as the **Sync method**.
1. In the **LDAP Group cn** text input box, begin typing the CN of the group. There will be a dropdown menu with matching CNs within the configured `group_base`. Select your CN from this list.
@@ -412,7 +414,9 @@ To create group links via CN:
![Creating group links via CN](img/ldap_sync_cn_v13_1.png)
-### Creating group links via filter **(PREMIUM ONLY)**
+<!-- vale gitlab.Spelling = YES -->
+
+### Creating group links via filter **(PREMIUM SELF)**
To create group links via filter:
@@ -424,7 +428,7 @@ To create group links via filter:
![Creating group links via filter](img/ldap_sync_filter_v13_1.png)
-### Overriding user permissions **(STARTER ONLY)**
+### Overriding user permissions **(PREMIUM SELF)**
In GitLab [8.15](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/822) and later, LDAP user permissions can now be manually overridden by an admin user. To override a user's permissions:
@@ -455,20 +459,19 @@ Group wikis work the same way as [project wikis](../project/wiki/index.md), plea
Group wikis can be edited by members with [Developer permissions](../../user/permissions.md#group-members-permissions)
and above.
+Group wiki repositories can be moved through the [Group repository storage moves API](../../api/group_repository_storage_moves.md).
+
### Group wikis limitations
There are a few limitations compared to project wikis:
- Git LFS is not supported.
-- Group wikis are not included in global search, group exports, and Geo replication.
+- Group wikis are not included in global search and Geo replication.
- Changes to group wikis don't show up in the group's activity feed.
-- Group wikis [can't be moved](../../api/project_repository_storage_moves.md#limitations) using the project
- repository moves API.
For updates, you can follow:
- [The epic tracking feature parity with project wikis](https://gitlab.com/groups/gitlab-org/-/epics/2782).
-- [The issue for adding the ability to move group wikis using the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003).
## Group Security Dashboard **(ULTIMATE)**
@@ -500,7 +503,7 @@ From GitLab 10.5, you can transfer groups in the following ways:
When transferring groups, note:
-- Changing a group's parent can have unintended side effects. See [Redirects when changing repository paths](../project/index.md#redirects-when-changing-repository-paths).
+- Changing a group's parent can have unintended side effects. See [Redirects when changing repository paths](../project/repository/index.md#redirects-when-changing-repository-paths).
- You can only transfer groups to groups you manage.
- You must update your local repositories to point to the new location.
- If the immediate parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will change to match the new parent group's visibility.
@@ -523,7 +526,7 @@ access further configurations for your group.
#### Changing a group's path
Changing a group's path (group URL) can have unintended side effects. Read
-[how redirects will behave](../project/index.md#redirects-when-changing-repository-paths)
+[how redirects will behave](../project/repository/index.md#redirects-when-changing-repository-paths)
before proceeding.
If you are vacating the path so it can be claimed by another group or user,
@@ -551,12 +554,12 @@ username, you can create a new group and transfer projects to it.
You can change settings that are specific to repositories in your group.
-#### Custom initial branch name **(CORE ONLY)**
+#### Custom initial branch name **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43290) in GitLab 13.6.
By default, when you create a new project in GitLab, the initial branch is called `master`.
-For groups, a group administrator can customize the initial branch name to something
+For groups, a group owner can customize the initial branch name to something
else. This way, every new project created under that group from then on will start from the custom branch name rather than `master`. To do so:
1. Go to the **Group page > Settings > Repository** and expand **Default initial
@@ -576,7 +579,7 @@ To remove a group and its contents:
This action either:
- Removes the group, and also queues a background job to delete all projects in that group.
-- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
+- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
Since [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/issues/39504), if the user who sets up the deletion leaves or is otherwise removed from the group before the
actual deletion happens, the job is cancelled, and the group is no longer scheduled for deletion.
@@ -612,7 +615,7 @@ To enable this feature, navigate to the group settings page. Select
![Checkbox for share with group lock](img/share_with_group_lock.png)
-#### Member Lock **(STARTER)**
+#### Member Lock **(PREMIUM)**
Member lock lets a group owner prevent any new project membership to all of the
projects within a group, allowing tighter control over project membership.
@@ -634,8 +637,8 @@ request to add a new user to a project through API will not be possible.
#### IP access restriction **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in [GitLab Ultimate and Gold](https://about.gitlab.com/pricing/) 12.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) to [GitLab Premium and Silver](https://about.gitlab.com/pricing/) in 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) to [GitLab Premium](https://about.gitlab.com/pricing/) in 13.1.
NOTE:
IP Access Restrictions are currently not functioning as expected on GitLab.com. Some users
@@ -645,9 +648,9 @@ more information.
To make sure only people from within your organization can access particular
resources, you have the option to restrict access to groups and their
-underlying projects, issues, etc, by IP address. This can help ensure that
+underlying subgroups, projects, issues, and so on, by IP address. This can help ensure that
particular content doesn't leave the premises, while not blocking off access to
-the entire instance.
+the entire instance. IP access restrictions can only be configured at the group level.
Add one or more allowed IP subnets using CIDR notation to the group settings and anyone
coming from a different IP address won't be able to access the restricted
@@ -672,7 +675,7 @@ To enable this feature:
#### Allowed domain restriction **(PREMIUM)**
->- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in [GitLab Premium and Silver](https://about.gitlab.com/pricing/) 12.2.
+>- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
>- Support for specifying multiple email domains [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33143) in GitLab 13.1
You can restrict access to groups by allowing only users with email addresses in particular domains to be added to the group.
@@ -702,6 +705,9 @@ To enable this feature:
This will enable the domain-checking for all new users added to the group from this moment on.
+NOTE:
+Domain restrictions only apply to groups and do not prevent users from being added as members of projects owned by the restricted group.
+
#### Group file templates **(PREMIUM)**
Group file templates allow you to share a set of templates for common file
@@ -726,6 +732,9 @@ To enable this feature, navigate to the group settings page, expand the
![Group file template settings](img/group_file_template_settings.png)
+To learn how to create templates for issues and merge requests, visit
+[Description templates](../project/description_templates.md).
+
#### Group-level project templates **(PREMIUM)**
Define project templates at a group level by setting a group as the template source.
@@ -765,7 +774,7 @@ To enable this feature:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
By default, projects within a group are deleted immediately.
-Optionally, on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
+Optionally, on [Premium](https://about.gitlab.com/pricing/) or higher tiers,
you can configure the projects within a group to be deleted after a delayed interval.
During this interval period, the projects will be in a read-only state and can be restored, if required.
@@ -778,14 +787,14 @@ To enable delayed deletion of projects:
1. Click **Save changes**.
NOTE:
-The group setting for delayed deletion is not inherited by sub-groups and has to be individually defined for each group.
+The group setting for delayed deletion is not inherited by subgroups and has to be individually defined for each group.
#### Prevent project forking outside group **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
By default, projects within a group can be forked.
-Optionally, on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
+Optionally, on [Premium](https://about.gitlab.com/pricing/) or higher tiers,
you can prevent the projects within a group from being forked outside of the current top-level group.
Previously this setting was available only for groups enforcing group managed account. This setting will be
@@ -804,11 +813,11 @@ To enable prevent project forking:
- **Webhooks**: Configure [webhooks](../project/integrations/webhooks.md) for your group.
- **Kubernetes cluster integration**: Connect your GitLab group with [Kubernetes clusters](clusters/index.md).
- **Audit Events**: View [Audit Events](../../administration/audit_events.md)
- for the group. **(STARTER ONLY)**
+ for the group. **(PREMIUM SELF)**
- **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
- **Integrations**: Configure [integrations](../admin_area/settings/project_integration_management.md) for your group.
-#### Group push rules **(STARTER)**
+#### Group push rules **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
@@ -824,12 +833,12 @@ When set, new subgroups have push rules set for them based on either:
- The closest parent group with push rules defined.
- Push rules set at the instance level, if no parent groups have push rules defined.
-### Maximum artifacts size **(CORE ONLY)**
+### Maximum artifacts size **(FREE SELF)**
For information about setting a maximum artifact size for a group, see
[Maximum artifacts size](../admin_area/settings/continuous_integration.md#maximum-artifacts-size).
-## User contribution analysis **(STARTER)**
+## User contribution analysis **(PREMIUM)**
With [GitLab Contribution Analytics](contribution_analytics/index.md),
you have an overview of the contributions (pushes, merge requests,
@@ -844,17 +853,7 @@ With [GitLab Issue Analytics](issues_analytics/index.md), you can see a bar char
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263478) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/276003) in GitLab 13.7.
-With [GitLab Repositories Analytics](repositories_analytics/index.md), you can download a CSV of the latest coverage data for all the projects in your group.
-
-### Check code coverage for all projects
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263478) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
-
-See the overall activity of all projects with code coverage with [GitLab Repositories Analytics](repositories_analytics/index.md).
-
-It displays the current code coverage data available for your projects:
-
-![Group repositories analytics](img/group_code_coverage_analytics_v13_7.png)
+With [GitLab Repositories Analytics](repositories_analytics/index.md), you can view overall activity of all projects with code coverage.
## Dependency Proxy
@@ -871,3 +870,13 @@ 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. -->
+
+## DORA4 analytics overview **(ULTIMATE ONLY)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291747) in GitLab [Ultimate](https://about.gitlab.com/pricing/) 13.9 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+
+Group details include the following analytics:
+
+- Deployment Frequency
+
+For more information, see [DORA4 Project Analytics API](../../api/dora4_group_analytics.md).
diff --git a/doc/user/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md
index 269be19f759..97f62becdb6 100644
--- a/doc/user/group/issues_analytics/index.md
+++ b/doc/user/group/issues_analytics/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/-/issues/7478) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5.
Issue Analytics is a bar graph which illustrates the number of issues created each month.
-The default timespan is 13 months, which includes the current month, and the 12 months
+The default time span is 13 months, which includes the current month, and the 12 months
prior.
To access the chart, navigate to your group sidebar and select **{chart}** **Analytics > Issue Analytics**.
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 65d3129a825..8e125a0cc6e 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -5,15 +5,16 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Iterations **(STARTER)**
+# Iterations **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214713) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214713) in GitLab 13.1.
> - It was deployed behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) on GitLab 13.2.
> - It's enabled on GitLab.com.
> - It's able to be enabled or disabled per-group.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-iterations). **(STARTER ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-iterations). **(PREMIUM ONLY)**
+> - Moved to GitLab Premium in 13.9.
Iterations are a way to track issues over a period of time. This allows teams
to track velocity and volatility metrics. Iterations can be used with [milestones](../../project/milestones/index.md)
@@ -50,7 +51,7 @@ To create an iteration:
## Edit an iteration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218277) in GitLab 13.2.
NOTE:
You need Developer [permissions](../../permissions.md) or higher to edit an iteration.
@@ -59,14 +60,14 @@ To edit an iteration, click the three-dot menu (**{ellipsis_v}**) > **Edit itera
## Add an issue to an iteration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in GitLab 13.2.
To learn how to add an issue to an iteration, see the steps in
[Managing issues](../../project/issues/managing_issues.md#add-an-issue-to-an-iteration).
## View an iteration report
-> Viewing iteration reports in projects [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222763) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
+> Viewing iteration reports in projects [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222763) in GitLab 13.5.
You can track the progress of an iteration by reviewing iteration reports.
An iteration report displays a list of all the issues assigned to an iteration and their status.
@@ -79,8 +80,8 @@ To view an iteration report, go to the iterations list page and click an iterati
### Iteration burndown and burnup charts
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222750) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.5.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/269972) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222750) in GitLab 13.5.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/269972) in GitLab 13.7.
The iteration report includes [burndown and burnup charts](../../project/milestones/burndown_and_burnup_charts.md),
similar to how they appear when viewing a [milestone](../../project/milestones/index.md).
@@ -104,7 +105,7 @@ To group issues by label:
You can also search for labels by typing in the search input.
1. Click or tap outside of the label dropdown. The page is now grouped by the selected labels.
-## Disable iterations **(STARTER ONLY)**
+## Disable iterations **(PREMIUM SELF)**
GitLab Iterations feature is deployed with a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
index fc4fb0236de..1cb7c05bb5f 100644
--- a/doc/user/group/repositories_analytics/index.md
+++ b/doc/user/group/repositories_analytics/index.md
@@ -12,6 +12,25 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
+![Group repositories analytics](../img/group_code_coverage_analytics_v13_9.png)
+
+## Current group code coverage
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263478) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
+
+The **Analytics > Repositories** group page displays the overall test coverage of all your projects in your group.
+In the **Overall activity** section, you can see:
+
+- The number of projects with coverage reports.
+- The average percentage of coverage across all your projects.
+- The total number of pipeline jobs that produce coverage reports.
+
+## Average group test coverage from the last 30 days
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215140) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.9.
+
+The **Analytics > Repositories** group page displays the average test coverage of all your projects in your group in a graph for the last 30 days.
+
## Latest project test coverage list
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267624) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
@@ -30,10 +49,10 @@ You can get a CSV of the code coverage data for all of the projects in your grou
To get the report:
1. Go to your group's **Analytics > Repositories** page
-1. Click **Download historic test coverage data (.csv)**,
+1. Click **Download historic test coverage data (`.csv`)**,
1. In the popup, select the projects you want to include in the report.
1. Select the date range for the report from the preset options.
-1. Click **Download test coverage data (.csv)**.
+1. Click **Download test coverage data (`.csv`)**.
The projects dropdown shows up to 100 projects from your group. If the project you want to check is not in the dropdown list, you can select **All projects** to download the report for all projects in your group, including any projects that are not listed. There is a plan to improve this behavior in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/250684).
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index f3b7be536ae..e2c01987e36 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -40,7 +40,8 @@ toggle the list of the milestone bars.
> - Filtering roadmaps by milestone is [deployed behind a feature flag](../../feature_flags.md), enabled by default.
> - Filtering roadmaps by milestone is enabled on GitLab.com.
> - Filtering roadmaps by milestone is recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-filtering-roadmaps-by-milestone). **(PREMIUM ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-filtering-roadmaps-by-milestone). **(PREMIUM SELF)**
+> - Filtering by epic confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218624) in GitLab 13.8.
WARNING:
Filtering roadmaps by milestone might not be available to you. Check the **version history** note above for details.
@@ -62,18 +63,18 @@ You can sort epics in the Roadmap view by:
Each option contains a button that toggles the sort order between **ascending** and **descending**.
The sort option and order persist when browsing Epics, including the [epics list view](../epics/index.md).
-You can also filter epics in the Roadmap view by:
+You can also filter epics in the Roadmap view by the epics':
- Author
- Label
- Milestone
-- Confidentiality of epics
+- Confidentiality
![roadmap date range in weeks](img/roadmap_filters_v13_8.png)
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
-### Enable or disable filtering roadmaps by milestone **(PREMIUM ONLY)**
+### Enable or disable filtering roadmaps by milestone **(PREMIUM SELF)**
Filtering roadmaps by milestone is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md
index 7158b7bc86b..dd0888a610f 100644
--- a/doc/user/group/saml_sso/group_managed_accounts.md
+++ b/doc/user/group/saml_sso/group_managed_accounts.md
@@ -9,9 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This [Closed Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#sts=Closed%20Beta) feature is being re-evaluated in favor of a different
-[identity model](https://gitlab.com/groups/gitlab-org/-/epics/4345) that does not require separate accounts.
-We recommend that group administrators who haven't yet implemented this feature wait for
-the new solution.
+[approach](https://gitlab.com/groups/gitlab-org/-/epics/4786) that aligns more closely with our [Subscription Agreement](https://about.gitlab.com/handbook/legal/subscription-agreement/).
+We recommend that group owners who haven't yet implemented this feature wait for the new solution.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/709) in GitLab 12.1.
> - It's deployed behind a feature flag, disabled by default.
@@ -50,7 +49,7 @@ assertions to be able to create a user.
| First Name | `first_name`, `firstname`, `firstName` |
| Last Name | `last_name`, `lastname`, `lastName` |
-## Feature flag **(PREMIUM ONLY)**
+## Feature flag **(PREMIUM SELF)**
The group-managed accounts feature is behind these feature flags: `group_managed_accounts`, `sign_up_on_sso` and `convert_user_to_group_managed_accounts`. The flags are disabled by default.
To activate the feature, ask a GitLab administrator with Rails console access to run:
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 0ce92eac1a3..d1c490b0769 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -5,7 +5,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# SAML SSO for GitLab.com groups **(SILVER ONLY)**
+# SAML SSO for GitLab.com groups **(PREMIUM SAAS)**
> Introduced in GitLab 11.0.
@@ -18,14 +18,15 @@ If you follow our guidance to automate user provisioning using [SCIM](scim_setup
User synchronization of SAML SSO groups is supported through [SCIM](scim_setup.md). SCIM supports adding and removing users from the GitLab group.
For example, if you remove a user from the SCIM app, SCIM removes that same user from the GitLab group.
-SAML SSO is not supported at the subgroup level.
+SAML SSO is only configurable at the top-level group.
## Configuring your Identity Provider
-1. Navigate to the group and click **Settings > SAML SSO**.
+1. Navigate to the group and select **Settings > SAML SSO**.
1. Configure your SAML server using the **Assertion consumer service URL**, **Identifier**, and **GitLab single sign-on URL**. Alternatively GitLab provides [metadata XML configuration](#metadata-configuration). See [specific identity provider documentation](#providers) for more details.
1. Configure the SAML response to include a NameID that uniquely identifies each user.
1. Configure [required assertions](group_managed_accounts.md#assertions) if using [Group Managed Accounts](group_managed_accounts.md).
+1. While the default is enabled for most SAML providers, please ensure the app is set to have [Service Provider](#glossary) initiated calls in order to link existing GitLab accounts.
1. Once the identity provider is set up, move on to [configuring GitLab](#configuring-gitlab).
![Issuer and callback for configuring SAML identity provider with GitLab.com](img/group_saml_configuration_information.png)
@@ -56,7 +57,7 @@ We recommend setting the NameID format to `Persistent` unless using a field (suc
GitLab provides metadata XML that can be used to configure your Identity Provider.
-1. Navigate to the group and click **Settings > SAML SSO**.
+1. Navigate to the group and select **Settings > SAML SSO**.
1. Copy the provided **GitLab metadata URL**.
1. Follow your Identity Provider's documentation and paste the metadata URL when it's requested.
@@ -68,8 +69,8 @@ After you set up your identity provider to work with GitLab, you must configure
1. Find the SSO URL from your Identity Provider and enter it the **Identity provider single sign-on URL** field.
1. Find and enter the fingerprint for the SAML token signing certificate in the **Certificate** field.
1. Select the access level to be applied to newly added users in the **Default membership role** field. The default access level is 'Guest'.
-1. Click the **Enable SAML authentication for this group** toggle switch.
-1. Click the **Save changes** button.
+1. Select the **Enable SAML authentication for this group** toggle switch.
+1. Select the **Save changes** button.
![Group SAML Settings for GitLab.com](img/group_saml_settings_v13_3.png)
@@ -110,7 +111,8 @@ When [configuring your identify provider](#configuring-your-identity-provider),
### Azure setup notes
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU). Please note that the video is outdated in regards to objectID mapping and the [SCIM documentation should be followed](scim_setup.md#azure-configuration-steps).
+For a demo of the Azure SAML setup including SCIM, see [SCIM Provisioning on Azure Using SAML SSO for Groups Demo](https://youtu.be/24-ZxmTeEBU). Please note that the video is outdated in regard to
+objectID mapping and the [SCIM documentation should be followed](scim_setup.md#azure-configuration-steps).
| GitLab Setting | Azure Field |
|--------------|----------------|
@@ -214,7 +216,7 @@ To link SAML to your existing GitLab.com account:
1. Sign in to your GitLab.com account.
1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group owner can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the Identity Provider.
-1. Click **Authorize**.
+1. Select **Authorize**.
1. Enter your credentials on the Identity Provider if prompted.
1. You are then redirected back to GitLab.com and should now have access to the group. In the future, you can use SAML to sign in to GitLab.com.
@@ -223,7 +225,7 @@ On subsequent visits, you should be able to go [sign in to GitLab.com with SAML]
### Signing in to GitLab.com with SAML
1. Sign in to your identity provider.
-1. From the list of apps, click on the "GitLab.com" app (The name is set by the administrator of the identity provider).
+1. From the list of apps, select the "GitLab.com" app. (The name is set by the administrator of the identity provider.)
1. You are then signed in to GitLab.com and redirected to the group.
### Configure user settings from SAML response
@@ -280,7 +282,7 @@ If a user is already a member of the group, linking the SAML identity does not c
To rescind access to the group, perform the following steps, in order:
-1. Remove the user from the user datastore on the identity provider or the list of users on the specific app.
+1. Remove the user from the user data store on the identity provider or the list of users on the specific app.
1. Remove the user from the GitLab.com group.
### Unlinking accounts
@@ -291,10 +293,19 @@ Users can unlink SAML for a group from their profile page. This can be helpful i
- Your SAML NameID has changed and so GitLab can no longer find your user.
WARNING:
-Unlinking an account removes all roles assigned to that user within the group.
-If a user relinks their account, roles need to be reassigned.
+Unlinking an account removes all roles assigned to that user in the group.
+If a user re-links their account, roles need to be reassigned.
-For example, to unlink the `MyOrg` account, the following **Disconnect** button is available under **Profile > Accounts**:
+Groups require at least one owner. If your account is the only owner in the
+group, you are not allowed to unlink the account. In that case, set up another user as a
+group owner, and then you can unlink the account.
+
+For example, to unlink the `MyOrg` account:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Account**.
+1. In the **Social sign-in** section, select **Disconnect** next to the connected account.
![Unlink Group SAML](img/unlink_group_saml.png)
@@ -341,9 +352,9 @@ access.
| Term | Description |
|------|-------------|
-| Identity Provider | The service which manages your user identities such as ADFS, Okta, Onelogin, or Ping Identity. |
+| Identity Provider | The service which manages your user identities such as ADFS, Okta, OneLogin, or Ping Identity. |
| Service Provider | SAML considers GitLab to be a service provider. |
-| Assertion | A piece of information about a user's identity, such as their name or role. Also know as claims or attributes. |
+| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. |
| SSO | Single Sign On. |
| Assertion consumer service URL | The callback on GitLab where users are redirected after successfully authenticating with the identity provider. |
| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
@@ -376,7 +387,7 @@ For convenience, we've included some [example resources](../../../administration
### Verifying NameID
-In troubleshooting the Group SAML setup, any authenticated user can use the API to verify the NameID GitLab already has linked to the user by visiting [https://gitlab.com/api/v4/user](https://gitlab.com/api/v4/user) and checking the `extern_uid` under identities.
+In troubleshooting the Group SAML setup, any authenticated user can use the API to verify the NameID GitLab already has linked to the user by visiting [`https://gitlab.com/api/v4/user`](https://gitlab.com/api/v4/user) and checking the `extern_uid` under identities.
Similarly, group members of a role with the appropriate permissions can make use of the [members API](../../../api/members.md) to view group SAML identity information for members of the group.
@@ -387,7 +398,7 @@ This can then be compared to the [NameID](#nameid) being sent by the Identity Pr
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.
As outlined in the [user access section](#linking-saml-to-your-existing-gitlabcom-account), a group Owner will need to provide the URL to users.
-### Message: "SAML authentication failed: Extern uid has already been taken"
+### Message: "SAML authentication failed: Extern UID has already been taken"
This error suggests you are signed in as a GitLab user but have already linked your SAML identity to a different GitLab user. Sign out and then try to sign in again using the SSO SAML link, which should log you into GitLab with the linked user account.
@@ -408,7 +419,7 @@ Here are possible causes and solutions:
|------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
| When a user account with the email address already exists in GitLab, but the user does not have the SAML identity tied to their account. | The user will need to [link their account](#user-access-and-management). |
-### Message: "SAML authentication failed: Extern uid has already been taken, User has already been taken"
+### Message: "SAML authentication failed: Extern UID has already been taken, User has already been taken"
Getting both of these errors at the same time suggests the NameID capitalization provided by the Identity Provider didn't exactly match the previous value for that user.
@@ -418,6 +429,11 @@ This can be prevented by configuring the [NameID](#nameid) to return a consisten
Ensure that the user who is trying to link their GitLab account has been added as a user within the identity provider's SAML app.
+Alternatively, the SAML response may be missing the `InResponseTo` attribute in the
+`samlp:Response` tag, which is [expected by the SAML gem](https://github.com/onelogin/ruby-saml/blob/9f710c5028b069bfab4b9e2b66891e0549765af5/lib/onelogin/ruby-saml/response.rb#L307-L316).
+The [Identity Provider](#glossary) administrator should ensure that the login is
+initiated by the Service Provider (typically GitLab) and not the Identity Provider.
+
### Stuck in a login "loop"
Ensure that the **GitLab single sign-on URL** has been configured as "Login URL" (or similarly named field) in the identity provider's SAML app.
@@ -446,3 +462,25 @@ However, self-managed GitLab instances use a configuration file that supports mo
Internally that uses the [`ruby-saml` library](https://github.com/onelogin/ruby-saml), so we sometimes check there to verify low level details of less commonly used options.
It can also help to compare the XML response from your provider with our [example XML used for internal testing](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/spec/fixtures/saml/response.xml).
+
+### Searching Rails log
+
+With access to the rails log or `production_json.log` (available only to GitLab team members for GitLab.com),
+you should be able to find the base64 encoded SAML response by searching with the following filters:
+
+- `json.meta.caller_id`: `Groups::OmniauthCallbacksController#group_saml`
+- `json.meta.user` or `json.username`: `username`
+- `json.method`: `POST`
+- `json.path`: `/groups/GROUP-PATH/-/saml/callback`
+
+In a relevant log entry, the `json.params` should provide a valid response with:
+
+- `"key": "SAMLResponse"` and the `"value": (full SAML response)`,
+- `"key": "RelayState"` with `"value": "/group-path"`, and
+- `"key": "group_id"` with `"value": "group-path"`.
+
+In some cases, if the SAML response is lengthy, you may receive a `"key": "truncated"` with `"value":"..."`.
+In these cases, please ask a group owner for a copy of the SAML response from when they select
+the "Verify SAML Configuration" button on the group SSO Settings page.
+
+Use a base64 decoder to see a human-readable version of the SAML response.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index cd3e99ae541..3a34a4b0599 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -5,9 +5,9 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# SCIM provisioning using SAML SSO for GitLab.com groups **(SILVER ONLY)**
+# SCIM provisioning using SAML SSO for GitLab.com groups **(PREMIUM SAAS)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in [GitLab.com Silver](https://about.gitlab.com/pricing/) 11.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab Premium 11.10.
System for Cross-domain Identity Management (SCIM), is an open standard that enables the
automation of user provisioning. When SCIM is provisioned for a GitLab group, membership of
@@ -260,7 +260,7 @@ It is important not to update these to incorrect values, since this will cause u
Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](index.md#i-need-to-change-my-saml-app) section.
-Alternatively, users can be removed from the SCIM app which will delink all removed users. Sync can then be turned on for the new SCIM app to [link existing users](#user-access-and-linking-setup).
+Alternatively, users can be removed from the SCIM app which de-links all removed users. Sync can then be turned on for the new SCIM app to [link existing users](#user-access-and-linking-setup).
### The SCIM app is throwing `"User has already been taken","status":409` error message
diff --git a/doc/user/group/security_dashboard/index.md b/doc/user/group/security_dashboard/index.md
deleted file mode 100644
index 3feccf2e342..00000000000
--- a/doc/user/group/security_dashboard/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../application_security/security_dashboard/index.md'
----
-
-This document was moved to [another location](../../application_security/security_dashboard/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 6b95388bf2e..bb7c1e26544 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -48,6 +48,7 @@ The following items are exported:
- Subgroups (including all the aforementioned data)
- Epics
- Events
+- Wikis **(PREMIUM SELF)** (Introduced in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53247))
The following items are **not** exported:
@@ -69,7 +70,7 @@ For more details on the specific data persisted in a group export, see the
![Export group panel](img/export_panel_v13_0.png)
-1. Once the export is generated, you should receive an e-mail with a link to the [exported contents](#exported-contents)
+1. After the export is generated, you should receive an e-mail with a link to the [exported contents](#exported-contents)
in a compressed tar archive, with contents in JSON format.
1. Alternatively, you can come back to the project settings and download the
@@ -77,7 +78,7 @@ For more details on the specific data persisted in a group export, see the
NOTE:
The maximum import file size can be set by the Administrator, default is `0` (unlimited).
-As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin UI](../../admin_area/settings/account_and_limit_settings.md).
+As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin UI](../../admin_area/settings/account_and_limit_settings.md). Default [modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8.
### Between CE and EE
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 438769872c0..4fcef07a04e 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -324,7 +324,7 @@ To delete a custom value stream:
This chart visually depicts the total number of days it takes for cycles to be completed. (Totals are being replaced with averages in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/262070).)
This chart uses the global page filters for displaying data based on the selected
-group, projects, and timeframe. In addition, specific stages can be selected
+group, projects, and time frame. In addition, specific stages can be selected
from within the chart itself.
The chart data is limited to the last 500 items.
@@ -345,7 +345,7 @@ Feature.disable(:cycle_analytics_scatterplot_enabled)
This chart shows a cumulative count of issues and merge requests per day.
This chart uses the global page filters for displaying data based on the selected
-group, projects, and timeframe. The chart defaults to showing counts for issues but can be
+group, projects, and time frame. The chart defaults to showing counts for issues but can be
toggled to show data for merge requests and further refined for specific group-level labels.
By default the top group-level labels (max. 10) are pre-selected, with the ability to
diff --git a/doc/user/img/activity_followed_users_v13_9.png b/doc/user/img/activity_followed_users_v13_9.png
new file mode 100644
index 00000000000..3c0a9de74b4
--- /dev/null
+++ b/doc/user/img/activity_followed_users_v13_9.png
Binary files differ
diff --git a/doc/user/incident_management/index.md b/doc/user/incident_management/index.md
deleted file mode 100644
index ed3516df168..00000000000
--- a/doc/user/incident_management/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../operations/incident_management/index.md'
----
-
-This document was moved to [../../operations/incident_management/index.md](../../operations/incident_management/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/index.md b/doc/user/index.md
index 3b2acfab34c..a678038507f 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -43,7 +43,7 @@ GitLab is a Git-based platform that integrates a great number of essential tools
- Hosting code in repositories with version control.
- Tracking proposals for new implementations, bug reports, and feedback with a
fully featured [Issue Tracker](project/issues/index.md#issues-list).
-- Organizing and prioritizing with [Issue Boards](project/issues/index.md#issue-boards).
+- 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
branch with [Review Apps](../ci/review_apps/index.md).
- Building, testing, and deploying with built-in [Continuous Integration](../ci/README.md).
@@ -83,6 +83,14 @@ There are several types of users in GitLab:
self-managed instances' features and settings.
- [Internal users](../development/internal_users.md).
+## User activity
+
+You can follow or unfollow other users from their [user profiles](profile/index.md#user-profile).
+To see their activity in the top-level Activity view, select Follow or Unfollow, and select
+the Followed Users tab:
+
+![Follow users](img/activity_followed_users_v13_9.png)
+
## Projects
In GitLab, you can create [projects](project/index.md) to host
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index 60453b007ba..6ba5e49d553 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.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
---
-# Infrastructure as code with Terraform and GitLab
+# Infrastructure as code with Terraform and GitLab **(FREE)**
## Motivation
@@ -26,6 +26,8 @@ variables:
# If not using GitLab's 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 uses `.latest.`, instead of stable, and may include breaking changes.
@@ -39,6 +41,15 @@ This template also includes some opinionated decisions, which you can override:
[run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
`init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
+This video from January 2021 walks you through all the GitLab Terraform integration features:
+
+<div class="video-fallback">
+ See the video: <a href="https://www.youtube.com/watch?v=iGXjUrkkzDI">Terraform with GitLab</a>.
+</div>
+<figure class="video-container">
+ <iframe src="https://www.youtube.com/embed/iGXjUrkkzDI" frameborder="0" allowfullscreen="true"> </iframe>
+</figure>
+
## GitLab Managed Terraform state
[Terraform remote backends](https://www.terraform.io/docs/backends/index.html)
diff --git a/doc/user/infrastructure/mr_integration.md b/doc/user/infrastructure/mr_integration.md
index 2704e7b7c8d..927552b90be 100644
--- a/doc/user/infrastructure/mr_integration.md
+++ b/doc/user/infrastructure/mr_integration.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
---
-# Terraform integration in Merge Requests
+# 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.
diff --git a/doc/user/infrastructure/terraform_state.md b/doc/user/infrastructure/terraform_state.md
index 30838b1cabd..ae35ebce0dc 100644
--- a/doc/user/infrastructure/terraform_state.md
+++ b/doc/user/infrastructure/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
+# GitLab managed Terraform State **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2673) in GitLab 13.0.
@@ -18,10 +18,14 @@ The GitLab managed Terraform state backend can store your Terraform state easily
securely, and spares you from setting up additional remote resources like
Amazon S3 or Google Cloud Storage. Its features include:
+- Versioning of Terraform state files.
- Supporting encryption of the state file both in transit and at rest.
- Locking and unlocking state.
- Remote Terraform plan and apply execution.
+A GitLab **administrator** must [setup the Terraform state storage configuration](../../administration/terraform_state.md)
+before using this feature.
+
## Permissions for using Terraform
In GitLab version 13.1, [Maintainer access](../permissions.md) was required to use a
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index be6e483aa54..5f974d75522 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# GitLab Markdown
+# GitLab Markdown **(FREE)**
This Markdown guide is **valid only for the GitLab internal Markdown rendering system for entries and files**.
It is **not** valid for the [GitLab documentation website](https://docs.gitlab.com)
@@ -21,7 +21,7 @@ We encourage you to view this document as [rendered by GitLab itself](https://gi
## GitLab Flavored Markdown (GFM)
GitLab uses "GitLab Flavored Markdown" (GFM). It extends the [CommonMark specification](https://spec.commonmark.org/current/)
-(which is based on standard Markdown) in several ways to add additional useful functionality.
+(which is based on standard Markdown) in several ways to add more features.
It was inspired by [GitHub Flavored Markdown](https://docs.github.com/en/free-pro-team@latest/github/writing-on-github/basic-writing-and-formatting-syntax).
You can use GFM in the following areas:
@@ -41,20 +41,23 @@ for more information.
### Transition from Redcarpet to CommonMark
-Since 11.1, GitLab uses the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker)
-for Markdown processing of all new issues, merge requests, comments, and other Markdown
-content in the GitLab system. Since 11.3, wiki pages and Markdown files (`*.md`) in
-repositories are also processed with CommonMark. As of 11.8, the [Redcarpet Ruby library](https://github.com/vmg/redcarpet)
-has been removed and all issues and comments, including those from pre-11.1, are now processed
-using the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker).
-
-The documentation website had its [Markdown engine migrated from Redcarpet to Kramdown](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108)
+- In GitLab version 11.8, the [Redcarpet Ruby library](https://github.com/vmg/redcarpet)
+ was removed. All issues and comments, including those from pre-11.1, are now processed
+ using the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker).
+- GitLab versions 11.3 and greater use CommonMark to process wiki pages and Markdown
+ files (`*.md`) in repositories.
+- GitLab versions 11.1 and greater use the [CommonMark Ruby Library](https://github.com/gjtorikian/commonmarker)
+ for Markdown processing of all new issues, merge requests, comments, and other Markdown
+ content in the GitLab system.
+
+The documentation website migrated its Markdown engine
+[from Redcarpet to Kramdown](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/108)
in October 2018.
You may have older issues, merge requests, or Markdown documents in your
-repository that were written using some of the nuances of the GitLab RedCarpet version
-of Markdown. Since CommonMark uses slightly stricter syntax, these documents
-might now appear a little differently since we have transitioned to CommonMark.
+repository that relied upon nuances of the GitLab RedCarpet version
+of Markdown. Because CommonMark uses slightly stricter syntax, these documents
+may now appear differently after the transition to CommonMark.
For example, numbered lists with nested lists may
render incorrectly:
@@ -80,23 +83,24 @@ character of the top list item (`C` in this case):
We flag any significant differences between Redcarpet and CommonMark Markdown in this document.
-If you have a large volume of Markdown files, it can be tedious to determine
+If you have many Markdown files, it can be tedious to determine
if they display correctly or not. You can use the
[`diff_redcarpet_cmark`](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
-tool (not an officially supported product) to generate a list of files and the
-differences between how RedCarpet and CommonMark render the files. It gives
-an indication if anything needs to be changed - often nothing needs
-to change.
+tool to generate a list of files and the
+differences between how RedCarpet and CommonMark render the files. It indicates
+if any changes are needed.
+
+`diff_redcarpet_cmark` is not an officially supported product.
### GFM extends standard Markdown
-GitLab makes full use of the standard (CommonMark) formatting, but also includes additional
-functionality useful for GitLab users.
+GitLab makes full use of the standard (CommonMark) formatting, but also includes more
+helpful features for GitLab users.
It makes use of [new Markdown features](#new-gfm-markdown-extensions),
not found in standard Markdown:
-- [Color "chips" written in HEX, RGB or HSL](#colors)
+- [Color chips written in HEX, RGB or HSL](#colors)
- [Diagrams and flowcharts](#diagrams-and-flowcharts)
- [Emoji](#emoji)
- [Front matter](#front-matter)
@@ -124,7 +128,7 @@ changing how standard Markdown is used:
### Colors
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colors).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colors).
It's possible to have color written in HEX, RGB, or HSL format rendered with a color
indicator.
@@ -168,9 +172,12 @@ It's also possible to use [Kroki](https://kroki.io) to create a wide variety of
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15107) in GitLab 10.3.
-Visit the [official page](https://mermaidjs.github.io/) for more details. If you're new to using Mermaid or need help identifying issues in your Mermaid code, the [Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/) is a helpful tool for creating and resolving issues within Mermaid diagrams.
+Visit the [official page](https://mermaidjs.github.io/) for more details. The
+[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/) helps you
+learn Mermaid and debug issues in your Mermaid code. Use it to identify and resolve
+issues in your diagrams.
-In order to generate a diagram or flowchart, you should write your text inside the `mermaid` block:
+To generate a diagram or flowchart, write your text inside the `mermaid` block:
````markdown
```mermaid
@@ -239,42 +246,46 @@ Read more in the [Kroki integration](../administration/integration/kroki.md) pag
### Emoji
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#emoji).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#emoji).
```markdown
Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
:zap: You can use emoji anywhere GFM is supported. :v:
-You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that.
+You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People :heart: you for that.
If you're new to this, don't be :fearful:. You can join the emoji :family:. All you need to do is to look up one of the supported codes.
Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup:
```
-Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/monkey.png" width="20px" height="20px" style="display:inline;margin:0"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/star2.png" width="20px" height="20px" style="display:inline;margin:0"> to your <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/speech_balloon.png" width="20px" height="20px" style="display:inline;margin:0">. Well we have a gift for you:
+Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/monkey.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/star2.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> to your <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/speech_balloon.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. Well we have a gift for you:
-<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/zap.png" width="20px" height="20px" style="display:inline;margin:0">You can use emoji anywhere GFM is supported. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/v.png" width="20px" height="20px" style="display:inline;margin:0">
+<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/zap.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">You can use emoji anywhere GFM is supported. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/v.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
-You can use it to point out a <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/bug.png" width="20px" height="20px" style="display:inline;margin:0"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/speak_no_evil.png" width="20px" height="20px" style="display:inline;margin:0"> patches. And if someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/snail.png" width="20px" height="20px" style="display:inline;margin:0"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/birthday.png" width="20px" height="20px" style="display:inline;margin:0">. People will <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/heart.png" width="20px" height="20px" style="display:inline;margin:0"> you for that.
+You can use it to point out a<img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/bug.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/speak_no_evil.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> patches. If someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/snail.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/birthday.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. People <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/heart.png" width="20px" height="20px" style="display:inline;margin:0;border: 0"> you for that.
-If you're new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/fearful.png" width="20px" height="20px" style="display:inline;margin:0">. You can join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/family.png" width="20px" height="20px" style="display:inline;margin:0">. All you need to do is to look up one of the supported codes.
+If you're new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/fearful.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. You can join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/family.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">. All you need to do is to look up one of the supported codes.
-Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0">
+Consult the [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px" style="display:inline;margin:0;border: 0">
#### Emoji and your OS
-The emoji example above uses hard-coded images for this documentation. The emoji,
-when rendered within GitLab, may appear different depending on the OS and browser used.
+The emoji example above uses hard-coded images for this documentation. Rendered emoji
+in GitLab may appear different depending on the OS and browser used.
Most emoji are natively supported on macOS, Windows, iOS, Android, and fall back on image-based
emoji where there is no support.
+<!-- vale gitlab.Spelling = NO -->
+
On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/)
to get full native emoji support. Ubuntu 18.04 (like many modern Linux distributions) has
this font installed by default.
+<!-- vale gitlab.Spelling = YES -->
+
### Front matter
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23331) in GitLab 11.6.
@@ -284,8 +295,9 @@ its content. This data can be used by static site generators such as [Jekyll](ht
[Hugo](https://gohugo.io/content-management/front-matter/), and many other applications.
When you view a Markdown file rendered by GitLab, any front matter is displayed as-is,
-in a box at the top of the document, before the rendered HTML content. To view an example,
-you can toggle between the source and rendered version of a [GitLab documentation file](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/README.md).
+in a box at the top of the document. The HTML content displays after the front matter. To view an example,
+you can toggle between the source and rendered version of a
+[GitLab documentation file](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/README.md).
In GitLab, front matter is only used in Markdown files and wiki pages, not the other
places where Markdown formatting is supported. It must be at the very top of the document
@@ -340,7 +352,7 @@ $example = array(
### Inline diff
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-diff).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-diff).
With inline diff tags you can display `{+ additions +}` or `[- deletions -]`.
@@ -413,7 +425,7 @@ the [Asciidoctor user manual](https://asciidoctor.org/docs/user-manual/#activati
### Special GitLab references
GFM recognizes special GitLab related references. For example, you can reference
-an issue, a commit, a team member, or even the whole team within a project. GFM turns
+an issue, a commit, a team member, or even an entire project team. GFM turns
that reference into a link so you can navigate between them.
Additionally, GFM recognizes certain cross-project references and also has a shorthand
@@ -421,7 +433,7 @@ version to reference other projects from the same namespace.
GFM recognizes the following:
-| references | input | cross-project reference | shortcut within same namespace |
+| references | input | cross-project reference | shortcut inside same namespace |
| :------------------------------ | :------------------------- | :-------------------------------------- | :----------------------------- |
| specific user | `@user_name` | | |
| specific group | `@group_name` | | |
@@ -432,6 +444,7 @@ GFM recognizes the following:
| snippet | `$123` | `namespace/project$123` | `project$123` |
| epic **(ULTIMATE)** | `&123` | `group1/subgroup&123` | |
| vulnerability **(ULTIMATE)** (1)| `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
+| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
| label by ID | `~123` | `namespace/project~123` | `project~123` |
| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
@@ -447,8 +460,8 @@ GFM recognizes the following:
1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
-For example, referencing an issue by using `#123` will format the output as a link
-to issue number 123 with text `#123`. Likewise, a link to issue number 123 will be
+For example, referencing an issue by using `#123` formats the output as a link
+to issue number 123 with text `#123`. Likewise, a link to issue number 123 is
recognized and formatted with text `#123`.
In addition to this, links to some objects are also recognized and formatted. Some examples of these are:
@@ -459,12 +472,12 @@ In addition to this, links to some objects are also recognized and formatted. So
### Task lists
-If this section is not rendered correctly, [view it in GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#task-lists).
+If this section isn't rendered correctly, [view it in GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#task-lists).
-You can add task lists anywhere Markdown is supported, but you can only "click"
-to toggle the boxes if they are in issues, merge requests, or comments. In other
-places you must edit the Markdown manually to change the status by adding or
-removing an `x` within the square brackets.
+You can add task lists anywhere Markdown is supported, but only issues, merge requests, and
+comments support clicking to toggle the boxes. In other
+places, you must edit the Markdown manually to change the status by adding or
+removing an `x` inside the square brackets.
To create a task list, add a specially-formatted Markdown list. You can use either
unordered or ordered lists:
@@ -482,13 +495,13 @@ unordered or ordered lists:
1. [x] Sub-task 2
```
-![A task list as rendered by the GitLab interface](img/completed_tasks_v13_3.png)
+![Task list as rendered by the GitLab interface](img/completed_tasks_v13_3.png)
### Table of contents
-You can add a table of contents to a Markdown file, wiki page, or issue/merge request
-description, by adding the tag `[[_TOC_]]` on its own line.
-It appears as an unordered list that links to the various headers.
+Add a table of contents to a Markdown file, wiki page, issue request, or merge request
+description by adding the tag `[[_TOC_]]` on its own line.
+It displays an unordered list that links to subheadings in the document.
```markdown
This is an intro sentence to my Wiki page.
@@ -504,7 +517,7 @@ First section content.
Second section content.
```
-![Preview of an auto-generated TOC in a Wiki](img/markdown_toc_preview_v12_9.png)
+![Preview of an auto-generated table of contents in a Wiki](img/markdown_toc_preview_v12_9.png)
### Wiki-specific Markdown
@@ -583,38 +596,39 @@ This snippet links to `<wiki_root>/miscellaneous.md`:
### Embedding metrics in GitLab Flavored Markdown
-Metric charts can be embedded within GitLab Flavored Markdown. See [Embedding Metrics within GitLab flavored Markdown](../operations/metrics/embed.md) for more details.
+Metric charts can be embedded in GitLab Flavored Markdown. Read
+[Embedding Metrics in GitLab flavored Markdown](../operations/metrics/embed.md) for more details.
## Standard Markdown and extensions in GitLab
-All standard Markdown formatting should work as expected within GitLab. Some standard
+All standard Markdown formatting should work as expected in GitLab. Some standard
functionality is extended with additional features, without affecting the standard usage.
If a functionality is extended, the new option is listed as a sub-section.
### Blockquotes
-Blockquotes are useful to highlight information, such as a side-note. It's generated
+Use a blockquote to highlight information, such as a side note. It's generated
by starting the lines of the blockquote with `>`:
```markdown
-> Blockquotes are very handy to emulate reply text.
+> Blockquotes help you emulate reply text.
> This line is part of the same quote.
Quote break.
-> This is a very long line that is still quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.
+> This is a very long line that is still quoted properly when it wraps. Keep writing to make sure this line is long enough to actually wrap for everyone. You can also *add* **Markdown** into a blockquote.
```
-> Blockquotes are very handy to emulate reply text.
+> Blockquotes help you emulate reply text.
> This line is part of the same quote.
Quote break.
-> This is a very long line that is still quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.
+> This is a very long line that is still quoted properly when it wraps. Keep writing to make sure this line is long enough to actually wrap for everyone. You can also *add* **Markdown** into a blockquote.
#### Multiline blockquote
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiline-blockquote).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiline-blockquote).
GFM extends the standard Markdown by also supporting multi-line blockquotes
fenced by `>>>`:
@@ -639,9 +653,9 @@ you can quote that without having to manually prepend `>` to every line!
### Code spans and blocks
-You can highlight anything that should be viewed as code and not simple text.
+You can highlight anything that should be viewed as code and not standard text.
-Simple inline code is highlighted with single backticks `` ` ``:
+Inline code is highlighted with single backticks `` ` ``:
```markdown
Inline `code` has `back-ticks around` it.
@@ -651,9 +665,11 @@ Inline `code` has `back-ticks around` it.
---
-Similarly, a whole block of code can be fenced with triple backticks (```` ``` ````),
-triple tildes (`~~~`), or indented 4 or more spaces to achieve a similar effect for
-a larger body of code.
+To achieve a similar effect for a larger code example, you can:
+
+- Fence an entire block of code with triple backticks (```` ``` ````).
+- Fence an entire block of code with triple tildes (`~~~`).
+- Indent it four or more spaces.
````markdown
```python
@@ -695,16 +711,16 @@ Tildes are OK too.
#### Colored code and syntax highlighting
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting).
+If this section isn't rendered correctly,
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting).
GitLab uses the [Rouge Ruby library](http://rouge.jneen.net/) for more colorful syntax
highlighting in code blocks. For a list of supported languages visit the
[Rouge project wiki](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers).
-Syntax highlighting is only supported in code blocks, so it's not possible to highlight
-code when it's inline.
+Syntax highlighting is supported only in code blocks, so you can't highlight inline code.
-Blocks of code are fenced by lines with three back-ticks (```` ``` ````) or three tildes (`~~~`), and have
-the language identified at the end of the first fence:
+To fence and apply syntax highlighting to a block of code, append the code language
+to the opening code declaration, three back-ticks (```` ``` ````) or three tildes (`~~~`):
````markdown
```javascript
@@ -761,7 +777,7 @@ But let's throw in a <b>tag</b>.
### Emphasis
There are multiple ways to emphasize text in Markdown. You can italicize, bold, strikethrough,
-as well as combine these emphasis styles together.
+and combine these emphasis styles together.
Strikethrough is not part of the core Markdown standard, but is part of GFM.
Examples:
@@ -786,10 +802,11 @@ Strikethrough uses two tildes. ~~Scratch this.~~
#### Multiple underscores in words and mid-word emphasis
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiple-underscores-in-words).
+If this section isn't rendered correctly,
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#multiple-underscores-in-words).
-It's not usually useful to italicize just _part_ of a word, especially when you're
-dealing with code and names that often appear with multiple underscores. As a result,
+Avoid italicizing a portion of a word, especially when you're
+dealing with code and names that often appear with multiple underscores.
GFM extends the standard Markdown standard by ignoring multiple underlines in words,
to allow better rendering of Markdown documents discussing code:
@@ -922,8 +939,7 @@ emoji is converted to an image which is then removed from the ID.
### Horizontal Rule
-It's very simple to create a horizontal rule, by using three or more hyphens, asterisks,
-or underscores:
+Create a horizontal rule by using three or more hyphens, asterisks, or underscores:
```markdown
Three or more hyphens,
@@ -978,7 +994,7 @@ Do not change to a reference style link.
#### Videos
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#videos).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#videos).
Image tags that link to files with a video extension are automatically converted to
a video player. The valid video extensions are `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`:
@@ -995,7 +1011,7 @@ Here's a sample video:
#### Audio
-If this section is not rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#audio).
+If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#audio).
Similar to videos, link tags for files with an audio extension are automatically converted to
an audio player. The valid audio extensions are `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`:
@@ -1012,7 +1028,8 @@ Here's a sample audio clip:
### Inline HTML
-To see the Markdown rendered within HTML in the second example, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html).
+To see the second example of Markdown rendered in HTML,
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#inline-html).
You can also use raw HTML in your Markdown, and it usually works pretty well.
@@ -1076,11 +1093,12 @@ Markdown is fine in GitLab.
#### Details and summary
-To see the Markdown rendered within HTML in the second example, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary).
+To see the second Markdown example rendered in HTML,
+[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#details-and-summary).
Content can be collapsed using HTML's [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
and [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
-tags. This is especially useful for collapsing long logs so they take up less screen space.
+tags. For example, collapse a long log file so it takes up less screen space.
```html
<p>
@@ -1108,7 +1126,7 @@ These details <em>remain</em> <strong>hidden</strong> until expanded.
---
-Markdown inside these tags is supported as well.
+Markdown inside these tags is also supported.
NOTE:
If your Markdown isn't rendering correctly, try adding
@@ -1150,7 +1168,7 @@ These details <em>remain</em> <b>hidden</b> until expanded.
A line break is inserted (a new paragraph starts) if the previous text is
ended with two newlines, like when you hit <kbd>Enter</kbd> twice in a row. If you only
use one newline (hit <kbd>Enter</kbd> once), the next sentence remains part of the
-same paragraph. This is useful if you want to keep long lines from wrapping, and keep
+same paragraph. Use this approach if you want to keep long lines from wrapping, and keep
them editable:
```markdown
@@ -1180,7 +1198,7 @@ GFM adheres to the Markdown specification in how [paragraphs and line breaks are
A paragraph is one or more consecutive lines of text, separated by one or
more blank lines (two newlines at the end of the first paragraph), as [explained above](#line-breaks).
-If you need more control over line breaks or soft returns, you can add a single line break
+Need more control over line breaks or soft returns? Add a single line break
by ending a line with a backslash, or two or more spaces. Two newlines in a row create a new
paragraph, with a blank line in between:
@@ -1268,6 +1286,8 @@ GFM auto-links almost any URL you put into your text:
- http://localhost:3000
```
+<!-- vale gitlab.Spelling = NO -->
+
- <https://www.google.com>
- <https://www.google.com>
- <ftp://ftp.us.debian.org/debian/>
@@ -1275,6 +1295,7 @@ GFM auto-links almost any URL you put into your text:
- <irc://irc.freenode.net/>
- <http://localhost:3000>
+<!-- vale gitlab.Spelling = YES -->
### Lists
Ordered and unordered lists can be created.
@@ -1397,17 +1418,21 @@ Example:
### Superscripts / Subscripts
-Currently, CommonMark and GFM don't support the superscript syntax ( `x^2` ) that
-Redcarpet does. You can use the standard HTML syntax for superscripts and subscripts:
+CommonMark and GFM don't support the Redcarpet superscript syntax ( `x^2` ).
+Use the standard HTML syntax for superscripts and subscripts:
```html
The formula for water is H<sub>2</sub>O
while the equation for the theory of relativity is E = mc<sup>2</sup>.
```
+<!-- vale gitlab.Spelling = NO -->
+
The formula for water is H<sub>2</sub>O
while the equation for the theory of relativity is E = mc<sup>2</sup>.
+<!-- vale gitlab.Spelling = YES -->
+
### Tables
Tables are not part of the core Markdown spec, but they are part of GFM.
@@ -1437,7 +1462,7 @@ Example:
| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It eventually wraps the text when the cell is too large for the display size. |
| cell 7 | | cell 9 |
-Additionally, you can choose the alignment of text within columns by adding colons (`:`)
+Additionally, you can choose the alignment of text in columns by adding colons (`:`)
to the sides of the "dash" lines in the second row. This affects every cell in the column:
```markdown
@@ -1452,7 +1477,7 @@ to the sides of the "dash" lines in the second row. This affects every cell in t
| Cell 1 | Cell 2 | Cell 3 | Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 | Cell 10 | Cell 11 | Cell 12 |
-[Within GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#tables),
+[In GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#tables),
the headers are always left-aligned in Chrome and Firefox, and centered in Safari.
You can use HTML formatting to adjust the rendering of tables. For example, you can
@@ -1470,7 +1495,7 @@ use `<br>` tags to force a cell to have multiple lines:
| Item1 | This is on one line |
| Item2 | This item has:<br>- Multiple items<br>- That we want listed separately |
-You can use HTML formatting within GitLab itself to add [task lists](#task-lists) with checkboxes,
+You can use HTML formatting in GitLab itself to add [task lists](#task-lists) with checkboxes,
but they do not render properly on `docs.gitlab.com`:
```markdown
@@ -1485,8 +1510,8 @@ but they do not render properly on `docs.gitlab.com`:
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27205) in GitLab 12.7.
If you're working in spreadsheet software (for example, Microsoft Excel, Google
-Sheets, or Apple Numbers), you can copy from a spreadsheet, and GitLab
-pastes it as a Markdown table. For example, suppose you have the
+Sheets, or Apple Numbers), GitLab creates a Markdown table when you copy-and-paste
+from a spreadsheet. For example, suppose you have the
following spreadsheet:
![Copy from spreadsheet](img/markdown_copy_from_spreadsheet_v12_7.png)
@@ -1502,4 +1527,4 @@ entry and paste the spreadsheet:
- The original [Markdown Syntax Guide](https://daringfireball.net/projects/markdown/syntax)
at Daring Fireball is an excellent resource for a detailed explanation of standard Markdown.
- You can find the detailed specification for CommonMark in the [CommonMark Spec](https://spec.commonmark.org/current/).
-- The [CommonMark Dingus](https://spec.commonmark.org/dingus/) is a handy tool for testing CommonMark syntax.
+- The [CommonMark Dingus](https://spec.commonmark.org/dingus/) helps you test CommonMark syntax.
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
index bef768cad4e..be3454dbd02 100644
--- a/doc/user/operations_dashboard/index.md
+++ b/doc/user/operations_dashboard/index.md
@@ -6,23 +6,27 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Operations Dashboard **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5781) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5. [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/9218) to [GitLab Premium](https://about.gitlab.com/pricing/) in 11.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5781) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/9218) to [GitLab Premium](https://about.gitlab.com/pricing/) in 11.10.
The Operations Dashboard provides a summary of each project's operational health,
including pipeline and alert status.
-The dashboard can be accessed via the top bar, by clicking **More > Operations**.
+The dashboard can be accessed from the top bar, by clicking **More > Operations**.
## Adding a project to the dashboard
NOTE:
For GitLab.com, you can add your project to the Operations Dashboard for free if
your project is public. If your project is private, the group it belongs to must
-have a [Silver](https://about.gitlab.com/pricing/) plan.
+have a [GitLab Premium](https://about.gitlab.com/pricing/) plan.
To add a project to the dashboard:
-1. Click the **Add projects** button in the homescreen of the dashboard.
+1. Ensure your alerts
+ [populate the `gitlab_environment_name` field](../../operations/metrics/alerts.md#external-prometheus-instances).
+ In GitLab 13.9, you can display alerts for the `production` environment only.
+1. Click the **Add projects** button in the home screen of the dashboard.
1. Search and add one or more projects using the **Search your projects** field.
1. Click the **Add projects** button.
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 6159ea395fa..f935fa87d68 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -4,10 +4,10 @@ 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
---
-# Composer packages in the Package Registry
+# Composer packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in GitLab Premium 13.2.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
Publish [Composer](https://getcomposer.org/) packages in your project's Package Registry.
Then, install the packages whenever you need to use them as a dependency.
@@ -273,5 +273,5 @@ Output indicates that the package has been successfully installed.
WARNING:
Never commit the `auth.json` file to your repository. To install packages from a CI/CD job,
consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages.md#satis) tool with your personal access token
-stored in a [GitLab CI/CD environment variable](../../../ci/variables/README.md) or in
+stored in a [GitLab CI/CD variable](../../../ci/variables/README.md) or in
[HashiCorp Vault](../../../ci/secrets/index.md).
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index f90c220a622..c115f94b964 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -4,12 +4,12 @@ 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
---
-# Conan packages in the Package Registry
+# Conan packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8248) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8248) in GitLab Premium 12.6.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-Publish Conan packages in your project’s Package Registry. Then install the
+Publish Conan packages in your project's Package Registry. Then install the
packages whenever you need to use them as a dependency.
To publish Conan packages to the Package Registry, add the Package Registry as a
@@ -98,7 +98,8 @@ For more details about creating and managing Conan packages, see the
## Add the Package Registry as a Conan remote
To run `conan` commands, you must add the Package Registry as a Conan remote for
-your project or instance.
+your project or instance. Then you can publish packages to
+and install packages from the Package Registry.
### Add a remote for your project
@@ -170,13 +171,13 @@ convention.
## Authenticate to the Package Registry
-To authenticate to the Package Registry, you need either a personal access token
-or deploy token.
+To authenticate to the Package Registry, you need one of the following:
-- If you use a [personal access token](../../../user/profile/personal_access_tokens.md),
- set the scope to `api`.
-- If you use a [deploy token](../../project/deploy_tokens/index.md), set the
- scope to `read_package_registry`, `write_package_registry`, or both.
+- A [personal access token](../../../user/profile/personal_access_tokens.md)
+ with the scope set to `api`.
+- A [deploy token](../../project/deploy_tokens/index.md) with the
+ scope set to `read_package_registry`, `write_package_registry`, or both.
+- A [CI job token](#publish-a-conan-package-by-using-cicd).
### Add your credentials to the GitLab remote
@@ -278,10 +279,19 @@ create_package:
Additional Conan images to use as the basis of your CI file are available in the
[Conan docs](https://docs.conan.io/en/latest/howtos/run_conan_in_docker.html#available-docker-images).
+### Re-publishing a package with the same recipe
+
+When you publish a package that has the same recipe (`package-name/version@user/channel`)
+as an existing package, the duplicate files are uploaded successfully and
+are accessible through the UI. However, when the package is installed,
+only the most recently-published package is returned.
+
## Install a Conan package
Install a Conan package from the Package Registry so you can use it as a
-dependency.
+dependency. You can install a package from the scope of your instance or your project.
+If multiple packages have the same recipe, when you install
+a package, the most recently-published package is retrieved.
WARNING:
Project-level packages [cannot be downloaded currently](https://gitlab.com/gitlab-org/gitlab/-/issues/270129).
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 8c284ccb9a3..e3a469c4b6c 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -144,7 +144,7 @@ Before you can build and push images by using GitLab CI/CD, you must authenticat
To use CI/CD to authenticate, you can use:
-- The `CI_REGISTRY_USER` variable.
+- The `CI_REGISTRY_USER` CI/CD variable.
This variable has read-write access to the Container Registry and is valid for
one job only. Its password is also automatically created and assigned to `CI_REGISTRY_PASSWORD`.
@@ -209,7 +209,7 @@ build:
- docker push $CI_REGISTRY/group/project/image:latest
```
-You can also make use of [other variables](../../../ci/variables/README.md) to avoid hard-coding:
+You can also make use of [other CI/CD variables](../../../ci/variables/README.md) to avoid hard-coding:
```yaml
build:
@@ -382,7 +382,7 @@ The following example defines two stages: `build`, and `clean`. The
`build_image` job builds the Docker image for the branch, and the
`delete_image` job deletes it. The `reg` executable is downloaded and used to
remove the image matching the `$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG`
-[environment variable](../../../ci/variables/predefined_variables.md).
+[predefined CI/CD variable](../../../ci/variables/predefined_variables.md).
To use this example, change the `IMAGE_TAG` variable to match your needs:
@@ -559,18 +559,70 @@ Here are examples of regex patterns you may want to use:
v.+
```
-- Match tags that contain `master`:
+- Match only the tag named `master`:
```plaintext
master
```
-- Match tags that either start with `v`, contain `master`, or contain `release`:
+- Match tags that are either named or start with `release`:
```plaintext
- (?:v.+|master|release)
+ release.*
```
+- Match tags that either start with `v`, are named `master`, or begin with `release`:
+
+ ```plaintext
+ (?:v.+|master|release.*)
+ ```
+
+### Set cleanup limits to conserve resources
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/288812) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's enabled 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-cleanup-policy-limits).
+
+Cleanup policies are executed as a background process. This process is complex, and depending on the number of tags to delete,
+the process can take time to finish.
+
+To prevent server resource starvation, the following application settings are available:
+
+- `container_registry_expiration_policies_worker_capacity`. The maximum number of cleanup workers running concurrently. This must be greater than `1`.
+ We recommend starting with a low number and increasing it after monitoring the resources used by the background workers.
+- `container_registry_delete_tags_service_timeout`. The maximum time, in seconds, that the cleanup process can take to delete a batch of tags.
+- `container_registry_cleanup_tags_service_max_list_size`. The maximum number of tags that can be deleted in a single execution. Additional tags must be deleted in another execution.
+ We recommend starting with a low number, like `100`, and increasing it after monitoring that container images are properly deleted.
+
+For self-managed instances, those settings can be updated in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
+
+ ```ruby
+ ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
+ ```
+
+Alternatively, once the limits are [enabled](#enable-or-disable-cleanup-policy-limits), they are available in the [admin area](../../admin_area/index.md) **Settings > CI/CD > Container Registry**.
+
+#### Enable or disable cleanup policy limits
+
+The cleanup policies limits are under development and not ready for production use. They are
+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(:container_registry_expiration_policies_throttling)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:container_registry_expiration_policies_throttling)
+```
+
### Use the cleanup policy API
You can set, update, and disable the cleanup policies using the GitLab API.
@@ -603,7 +655,7 @@ If you see the following message:
Check the regex patterns to ensure they are valid.
-You can use [Rubular](https://rubular.com/) to check your regex.
+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).
## Use the Container Registry to store Helm Charts
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 5e5aadfae2b..fdf0caba090 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -35,7 +35,7 @@ The following images and packages are supported.
| Docker | 11.11+ |
For a list of planned additions, view the
-[direction page](https://about.gitlab.com/direction/package/dependency_proxy/#top-vision-items).
+[direction page](https://about.gitlab.com/direction/package/#dependency-proxy).
## Enable the Dependency Proxy
@@ -64,7 +64,7 @@ Prerequisites:
> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](../../../administration/packages/dependency_proxy.md#disabling-authentication). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](../../../administration/packages/dependency_proxy.md#disabling-authentication). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -91,94 +91,35 @@ You can authenticate using:
#### Authenticate within CI/CD
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/280582) in GitLab 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/280582) in GitLab 13.7.
+> - Automatic runner authentication [added](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27302) in GitLab 13.9.
-To work with the Dependency Proxy in [GitLab CI/CD](../../../ci/README.md), you can use:
-
-- `CI_DEPENDENCY_PROXY_USER`: A CI user for logging in to the Dependency Proxy.
-- `CI_DEPENDENCY_PROXY_PASSWORD`: A CI password for logging in to the Dependency Proxy.
-- `CI_DEPENDENCY_PROXY_SERVER`: The server for logging in to the Dependency Proxy.
-- `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`: The image prefix for pulling images through the Dependency Proxy.
-
-This script shows how to use these variables to log in and pull an image from the Dependency Proxy:
+Runners log in to the Dependency Proxy automatically. To pull through
+the Dependency Proxy, use the `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`
+[predefined CI/CD variable](../../../ci/variables/predefined_variables.md):
```yaml
# .gitlab-ci.yml
-
-dependency-proxy-pull-master:
- # Official docker image.
- image: docker:latest
- stage: build
- services:
- - docker:dind
- before_script:
- - docker login -u "$CI_DEPENDENCY_PROXY_USER" -p "$CI_DEPENDENCY_PROXY_PASSWORD" "$CI_DEPENDENCY_PROXY_SERVER"
- script:
- - docker pull "$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX"/alpine:latest
+image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:latest
```
-`CI_DEPENDENCY_PROXY_SERVER` and `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` include the server port. So if you use `CI_DEPENDENCY_PROXY_SERVER` to log in, for example, you must explicitly include the port in your pull command and vice-versa:
+There are other additional predefined CI/CD variables you can also use:
+
+- `CI_DEPENDENCY_PROXY_USER`: A CI/CD user for logging in to the Dependency Proxy.
+- `CI_DEPENDENCY_PROXY_PASSWORD`: A CI/CD password for logging in to the Dependency Proxy.
+- `CI_DEPENDENCY_PROXY_SERVER`: The server for logging in to the Dependency Proxy.
+- `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`: The image prefix for pulling images through the Dependency Proxy.
+
+`CI_DEPENDENCY_PROXY_SERVER` and `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`
+include the server port. If you explicitly include the Dependency Proxy
+path, the port must be included, unless you have logged into the Dependency
+Proxy manually without including the port:
```shell
docker pull gitlab.example.com:443/my-group/dependency_proxy/containers/alpine:latest
```
-You can also use [custom environment variables](../../../ci/variables/README.md#custom-environment-variables) to store and access your personal access token or other valid credentials.
-
-##### Authenticate with `DOCKER_AUTH_CONFIG`
-
-You can use the Dependency Proxy to pull your base image.
-
-1. [Create a `DOCKER_AUTH_CONFIG` environment variable](../../../ci/docker/using_docker_images.md#define-an-image-from-a-private-container-registry).
-1. Get credentials that allow you to log into the Dependency Proxy.
-1. Generate the version of these credentials that will be used by Docker:
-
- ```shell
- # The use of "-n" - prevents encoding a newline in the password.
- echo -n "my_username:my_password" | base64
-
- # Example output to copy
- bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
- ```
-
- This can also be a [personal access token](../../../user/profile/personal_access_tokens.md) such as:
-
- ```shell
- echo -n "my_username:personal_access_token" | base64
- ```
-
-1. Create a [custom environment variables](../../../ci/variables/README.md#custom-environment-variables)
-named `DOCKER_AUTH_CONFIG` with a value of:
-
- ```json
- {
- "auths": {
- "https://gitlab.example.com": {
- "auth": "(Base64 content from above)"
- }
- }
- }
- ```
-
- To use `$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` when referencing images, you must explicitly include the port in your `DOCKER_AUTH_CONFIG` value:
-
- ```json
- {
- "auths": {
- "https://gitlab.example.com:443": {
- "auth": "(Base64 content from above)"
- }
- }
- }
- ```
-
-1. Now reference the Dependency Proxy in your base image:
-
- ```yaml
- # .gitlab-ci.yml
- image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/node:latest
- ...
- ```
+You can also use [custom CI/CD variables](../../../ci/variables/README.md#custom-cicd-variables) to store and access your personal access token or other valid credentials.
### Store a Docker image in Dependency Proxy cache
@@ -284,3 +225,19 @@ RateLimit-Remaining: 98;w=21600
```
This example shows the total limit of 100 pulls in six hours, with 98 pulls remaining.
+
+#### Check the rate limit in a CI/CD job
+
+This example shows a GitLab CI/CD job that uses an image with `jq` and `curl` installed:
+
+```yaml
+hub_docker_quota_check:
+ stage: build
+ image: alpine:latest
+ tags:
+ - <optional_runner_tag>
+ before_script: apk add curl jq
+ script:
+ - |
+ TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token) && curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1
+```
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 82c72481984..73b84c04b6d 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -4,7 +4,7 @@ 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
---
-# GitLab Generic Packages Repository **(CORE)**
+# GitLab Generic Packages Repository **(FREE)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4209) in GitLab 13.5.
> - It's [deployed behind a feature flag](../../../user/feature_flags.md), enabled by default.
@@ -48,7 +48,8 @@ PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../../api/README.md#namespaced-path-encoding). |
| `package_name` | string | yes | The package name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), dots (`.`), hyphens (`-`), or underscores (`_`).
| `package_version` | string | yes | The package version. It can contain only numbers (`0-9`), and dots (`.`). Must be in the format of `X.Y.Z`, i.e. should match `/\A\d+\.\d+\.\d+\z/` regular expression.
-| `file_name` | string | yes | The file name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), dots (`.`), hyphens (`-`), or underscores (`_`).
+| `file_name` | string | yes | The filename. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), dots (`.`), hyphens (`-`), or underscores (`_`).
+| `status` | string | no | The package status. It can be `default` (default) or `hidden`. Hidden packages do not appear in the UI or [package API list endpoints](../../../api/packages.md).
Provide the file context in the request body.
@@ -87,7 +88,7 @@ GET /projects/:id/packages/generic/:package_name/:package_version/:file_name
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../../api/README.md#namespaced-path-encoding). |
| `package_name` | string | yes | The package name. |
| `package_version` | string | yes | The package version. |
-| `file_name` | string | yes | The file name. |
+| `file_name` | string | yes | The filename. |
The file context is served in the response body. The response content type is `application/octet-stream`.
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index 87cd4a4a9a6..c9397f8d9f6 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -4,14 +4,14 @@ 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
---
-# Go proxy for GitLab
+# Go proxy for GitLab **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27376) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27376) in GitLab Premium 13.1.
> - It's deployed behind a feature flag, disabled by default.
> - It's disabled for 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-the-go-proxy).
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
With the Go proxy for GitLab, every project in GitLab can be fetched with the
[Go proxy protocol](https://proxy.golang.org/).
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
index 9da14842845..d2bd9ef5646 100644
--- a/doc/user/packages/index.md
+++ b/doc/user/packages/index.md
@@ -20,7 +20,7 @@ The Package Registry supports the following formats:
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/conan_repository/index.html">Conan</a></td><td>12.6+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/go_proxy/index.html">Go</a></td><td>13.1+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/maven_repository/index.html">Maven</a></td><td>11.3+</td></tr>
-<tr><td><a href="https://docs.gitlab.com/ee/user/packages/npm_registry/index.html">NPM</a></td><td>11.7+</td></tr>
+<tr><td><a href="https://docs.gitlab.com/ee/user/packages/npm_registry/index.html">npm</a></td><td>11.7+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/nuget_repository/index.html">NuGet</a></td><td>12.8+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/pypi_repository/index.html">PyPI</a></td><td>12.10+</td></tr>
<tr><td><a href="https://docs.gitlab.com/ee/user/packages/generic_packages/index.html">Generic packages</a></td><td>13.5+</td></tr>
@@ -35,6 +35,8 @@ You can also use the [API](../../api/packages.md) to administer the Package Regi
The below table lists formats that are not supported, but are accepting Community contributions for. Consider contributing to GitLab. This [development documentation](../../development/packages.md)
guides you through the process.
+<!-- vale gitlab.Spelling = NO -->
+
| Format | Status |
| ------ | ------ |
| Chef | [#36889](https://gitlab.com/gitlab-org/gitlab/-/issues/36889) |
@@ -51,6 +53,7 @@ guides you through the process.
| Terraform | [WIP: Merge Request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18834) |
| Vagrant | [#36899](https://gitlab.com/gitlab-org/gitlab/-/issues/36899) |
+<!-- vale gitlab.Spelling = YES -->
## Container Registry
The GitLab [Container Registry](container_registry/index.md) is a secure and private registry for container images. It's built on open source software and completely integrated within GitLab. Use GitLab CI/CD to create and publish images. Use the GitLab [API](../../api/container_registry.md) to manage the registry across groups and projects.
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index e0f5a400977..828eec812fa 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -4,10 +4,10 @@ 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
---
-# Maven packages in the Package Repository
+# Maven packages in the Package Repository **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5811) in GitLab Premium 11.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
Publish [Maven](https://maven.apache.org) artifacts in your project’s Package Registry.
Then, install the packages whenever you need to use them as a dependency.
@@ -186,10 +186,11 @@ published to the GitLab Package Registry.
## Authenticate to the Package Registry with Maven
-To authenticate to the Package Registry, you need either a personal access token or deploy token.
+To authenticate to the Package Registry, you need one of the following:
-- If you use a [personal access token](../../../user/profile/personal_access_tokens.md), set the scope to `api`.
-- If you use a [deploy token](../../project/deploy_tokens/index.md), set the scope to `read_package_registry`, `write_package_registry`, or both.
+- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `api`.
+- A [deploy token](../../project/deploy_tokens/index.md) with the scope set to `read_package_registry`, `write_package_registry`, or both.
+- A [CI_JOB_TOKEN](#authenticate-with-a-ci-job-token-in-maven).
### Authenticate with a personal access token in Maven
@@ -219,7 +220,7 @@ The `name` must be `Private-Token`.
### Authenticate with a deploy token in Maven
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) deploy token authentication in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
To use a deploy token, add this section to your
[`settings.xml`](https://maven.apache.org/settings.html) file.
@@ -354,12 +355,13 @@ repositories {
To use the GitLab endpoint for Maven packages, choose an option:
-- **Project-level**: Use when you have few Maven packages and they are not in
- the same GitLab group.
-- **Group-level**: Use when you have many Maven packages in the same GitLab
- group.
-- **Instance-level**: Use when you have many Maven packages in different
- GitLab groups or in their own namespace.
+- **Project-level**: To publish Maven packages to a project, use a project-level endpoint.
+ To install Maven packages, use a project-level endpoint when you have few Maven packages
+ and they are not in the same GitLab group.
+- **Group-level**: Use a group-level endpoint when you want to install packages from
+ many different projects in the same GitLab group.
+- **Instance-level**: Use an instance-level endpoint when you want to install many
+ packages from different GitLab groups or in their own namespace.
The option you choose determines the settings you add to your `pom.xml` file.
@@ -414,7 +416,7 @@ repositories {
### Group-level Maven endpoint
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8798) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
If you rely on many packages, it might be inefficient to include the `repository` section
with a unique URL for each package. Instead, you can use the group-level endpoint for
@@ -462,7 +464,7 @@ repositories {
```
- For the `id`, use what you [defined in `settings.xml`](#authenticate-to-the-package-registry-with-maven).
-- For `my-group`, use your group name.
+- For `GROUP_ID`, use your group ID, which you can view on your group's home page.
- For `PROJECT_ID`, use your project ID, which you can view on your project's home page.
- Replace `gitlab.example.com` with your domain name.
- For retrieving artifacts, use either the
@@ -472,7 +474,7 @@ repositories {
### Instance-level Maven endpoint
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/8274) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
If you rely on many packages, it might be inefficient to include the `repository` section
with a unique URL for each package. Instead, you can use the instance-level endpoint for
@@ -533,7 +535,7 @@ repositories {
After you have set up the [remote and authentication](#authenticate-to-the-package-registry-with-maven)
and [configured your project](#use-the-gitlab-endpoint-for-maven-packages),
-publish a Maven artifact from your project.
+publish a Maven package to your project.
### Publish by using Maven
@@ -604,11 +606,35 @@ To publish a package by using Gradle:
Now navigate to your project's **Packages & Registries** page and view the published artifacts.
+### Publishing a package with the same name or version
+
+When you publish a package with the same name or version as an existing package,
+the existing package is overwritten.
+
+#### Do not allow duplicate Maven packages
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296895) in GitLab Free 13.9.
+
+To prevent users from publishing duplicate Maven packages, you can use the [GraphQl API](../../../api/graphql/reference/index.md#packagesettings) or the UI.
+
+In the UI:
+
+1. For your group, go to **Settings > Packages & Registries**.
+1. Expand the **Package Registry** section.
+1. Turn on the **Reject duplicates** toggle.
+1. Optional. To allow some duplicate packages, in the **Exceptions** box, enter a regex pattern that matches the names of packages you want to allow.
+
+Your changes are automatically saved.
+
## Install a package
To install a package from the GitLab Package Registry, you must configure
the [remote and authenticate](#authenticate-to-the-package-registry-with-maven).
-When this is completed, there are two ways to install a package.
+When this is completed, you can install a package from a project,
+group, or namespace.
+
+If multiple packages have the same name and version, when you install
+a package, the most recently-published package is retrieved.
### Use Maven with `mvn install`
@@ -706,7 +732,7 @@ You can create a new package each time the `master` branch is updated.
```
1. Make sure your `pom.xml` file includes the following.
- You can either let Maven use the CI environment variables, as shown in this example,
+ You can either let Maven use the [predefined CI/CD variables](../../../ci/variables/predefined_variables.md), as shown in this example,
or you can hard code your server's hostname and project's ID.
```xml
@@ -745,7 +771,7 @@ The next time the `deploy` job runs, it copies `ci_settings.xml` to the
user's home location. In this example:
- The user is `root`, because the job runs in a Docker container.
-- Maven uses the configured CI [environment variables](../../../ci/variables/README.md#predefined-environment-variables).
+- Maven uses the configured CI/CD variables.
### Create Maven packages with GitLab CI/CD by using Gradle
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index c16fea1d00a..b1075e19b7b 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -4,37 +4,37 @@ 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
---
-# NPM packages in the Package Registry
+# npm packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5934) in GitLab Premium 11.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-Publish NPM packages in your project's Package Registry. Then install the
+Publish npm packages in your project's Package Registry. Then install the
packages whenever you need to use them as a dependency.
Only [scoped](https://docs.npmjs.com/misc/scope/) packages are supported.
-## Build an NPM package
+## Build an npm package
-This section covers how to install NPM or Yarn and build a package for your
+This section covers how to install npm or Yarn and build a package for your
JavaScript project.
-If you already use NPM and know how to build your own packages, go to
+If you already use npm and know how to build your own packages, go to
the [next section](#authenticate-to-the-package-registry).
-### Install NPM
+### Install npm
-Install Node.js and NPM in your local development environment by following
+Install Node.js and npm in your local development environment by following
the instructions at [npmjs.com](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm/).
-When installation is complete, verify you can use NPM in your terminal by
+When installation is complete, verify you can use npm in your terminal by
running:
```shell
npm --version
```
-The NPM version is shown in the output:
+The npm version is shown in the output:
```plaintext
6.10.3
@@ -42,7 +42,7 @@ The NPM version is shown in the output:
### Install Yarn
-As an alternative to NPM, you can install Yarn in your local environment by following the
+As an alternative to npm, you can install Yarn in your local environment by following the
instructions at [yarnpkg.com](https://classic.yarnpkg.com/en/docs/install).
When installation is complete, verify you can use Yarn in your terminal by
@@ -81,13 +81,13 @@ To create a project:
A `package.json` file is created.
-## Use the GitLab endpoint for NPM packages
+## Use the GitLab endpoint for npm packages
-To use the GitLab endpoint for NPM packages, choose an option:
+To use the GitLab endpoint for npm packages, choose an option:
-- **Project-level**: Use when you have few NPM packages and they are not in
+- **Project-level**: Use when you have few npm packages and they are not in
the same GitLab group.
-- **Instance-level**: Use when you have many NPM packages in different
+- **Instance-level**: Use when you have many npm packages in different
GitLab groups or in their own namespace. Be sure to comply with the [package naming convention](#package-naming-convention).
Some features such as [publishing](#publish-an-npm-package) a package is only available on the project-level endpoint.
@@ -103,17 +103,17 @@ To authenticate, use one of the following:
(required for two-factor authentication (2FA)), with the scope set to `api`.
- A [deploy token](../../project/deploy_tokens/index.md), with the scope set to `read_package_registry`, `write_package_registry`, or both.
- It's not recommended, but you can use [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow).
- Standard OAuth tokens cannot authenticate to the GitLab NPM Registry. You must use a personal access token with OAuth headers.
+ Standard OAuth tokens cannot authenticate to the GitLab npm Registry. You must use a personal access token with OAuth headers.
- A [CI job token](#authenticate-with-a-ci-job-token).
-- Your NPM package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case.
+- Your npm package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case.
### Authenticate with a personal access token or deploy token
To authenticate with the Package Registry, you need a [personal access token](../../profile/personal_access_tokens.md) or [deploy token](../../project/deploy_tokens/index.md).
-#### Project-level NPM endpoint
+#### Project-level npm endpoint
-To use the [project-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, set your NPM configuration:
+To use the [project-level](#use-the-gitlab-endpoint-for-npm-packages) npm endpoint, set your npm configuration:
```shell
# Set URL for your scoped packages.
@@ -129,14 +129,14 @@ npm config set '//gitlab.example.com/api/v4/projects/<your_project_id>/packages/
- `<your_token>` is your personal access token or deploy token.
- Replace `gitlab.example.com` with your domain name.
-You should now be able to publish and install NPM packages in your project.
+You should now be able to publish and install npm packages in your project.
If you encounter an error with [Yarn](https://classic.yarnpkg.com/en/), view
[troubleshooting steps](#troubleshooting).
-#### Instance-level NPM endpoint
+#### Instance-level npm endpoint
-To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, set your NPM configuration:
+To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) npm endpoint, set your npm configuration:
```shell
# Set URL for your scoped packages.
@@ -151,7 +151,7 @@ npm config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "<your_tok
- `<your_token>` is your personal access token or deploy token.
- Replace `gitlab.example.com` with your domain name.
-You should now be able to publish and install NPM packages in your project.
+You should now be able to publish and install npm packages in your project.
If you encounter an error with [Yarn](https://classic.yarnpkg.com/en/), view
[troubleshooting steps](#troubleshooting).
@@ -159,23 +159,23 @@ If you encounter an error with [Yarn](https://classic.yarnpkg.com/en/), view
### Authenticate with a CI job token
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9104) in GitLab Premium 12.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-If you're using NPM with GitLab CI/CD, a CI job token can be used instead of a personal access token or deploy token.
+If you're using npm with GitLab CI/CD, a CI job token can be used instead of a personal access token or deploy token.
The token inherits the permissions of the user that generates the pipeline.
-#### Project-level NPM endpoint
+#### Project-level npm endpoint
-To use the [project-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, add a corresponding section to your `.npmrc` file:
+To use the [project-level](#use-the-gitlab-endpoint-for-npm-packages) npm endpoint, add a corresponding section to your `.npmrc` file:
```ini
@foo:registry=https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/
//gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
```
-#### Instance-level NPM endpoint
+#### Instance-level npm endpoint
-To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) NPM endpoint, add a corresponding section to your `.npmrc` file:
+To use the [instance-level](#use-the-gitlab-endpoint-for-npm-packages) npm endpoint, add a corresponding section to your `.npmrc` file:
```ini
@foo:registry=https://gitlab.example.com/api/v4/packages/npm/
@@ -199,12 +199,12 @@ Then, you can run `npm publish` either locally or by using GitLab CI/CD.
NPM_TOKEN=<your_token> npm publish
```
-- **GitLab CI/CD:** Set an `NPM_TOKEN` [variable](../../../ci/variables/README.md)
+- **GitLab CI/CD:** Set an `NPM_TOKEN` [CI/CD variable](../../../ci/variables/README.md)
under your project's **Settings > CI/CD > Variables**.
## Package naming convention
-Your NPM package name must be in the format of `@scope/package-name`.
+Your npm package name must be in the format of `@scope/package-name`.
- The `@scope` is the root namespace of the GitLab project. It must match exactly, including the case.
- The `package-name` can be whatever you want.
@@ -227,26 +227,28 @@ In GitLab, this regex validates all package names from all package managers:
/\A\@?(([\w\-\.\+]*)\/)*([\w\-\.]+)@?(([\w\-\.\+]*)\/)*([\w\-\.]*)\z/
```
-This regex allows almost all of the characters that NPM allows, with a few exceptions (for example, `~` is not allowed).
+This regex allows almost all of the characters that npm allows, with a few exceptions (for example, `~` is not allowed).
-The regex also allows for capital letters, while NPM does not. Capital letters are needed because the scope must be
+The regex also allows for capital letters, while npm does not. Capital letters are needed because the scope must be
identical to the root namespace of the project.
WARNING:
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
+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
the naming convention and run `npm publish` if necessary.
-## Publish an NPM package
+## Publish an npm package
Prerequisites:
- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
-- Set a [project-level NPM endpoint](#use-the-gitlab-endpoint-for-npm-packages).
-- Your NPM package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case.
+- Set a [project-level npm endpoint](#use-the-gitlab-endpoint-for-npm-packages).
+- Your npm package name must be in the format of [@scope/package-name](#package-naming-convention).
+ It must match exactly, including the case. This is different than the
+ npm naming convention, but it is required to work with the GitLab Package Registry.
-To upload an NPM package to your project, run this command:
+To upload an npm package to your project, run this command:
```shell
npm publish
@@ -257,17 +259,20 @@ To view the package, go to your project's **Packages & Registries**.
If you try to publish a package [with a name that already exists](#publishing-packages-with-the-same-name-or-version) within
a given scope, you get a `403 Forbidden!` error.
-## Publish an NPM package by using CI/CD
+## Publish an npm package by using CI/CD
Prerequisites:
- [Authenticate](#authenticate-to-the-package-registry) to the Package Registry.
-- Set a [project-level NPM endpoint](#use-the-gitlab-endpoint-for-npm-packages).
+- Set a [project-level npm endpoint](#use-the-gitlab-endpoint-for-npm-packages).
+- Your npm package name must be in the format of [@scope/package-name](#package-naming-convention).
+ It must match exactly, including the case. This is different than the
+ npm naming convention, but it is required to work with the GitLab Package Registry.
-To work with NPM commands within [GitLab CI/CD](../../../ci/README.md), you can use
+To work with npm commands within [GitLab CI/CD](../../../ci/README.md), you can use
`CI_JOB_TOKEN` in place of the personal access token or deploy token in your commands.
-An example `.gitlab-ci.yml` file for publishing NPM packages:
+An example `.gitlab-ci.yml` file for publishing npm packages:
```yaml
image: node:latest
@@ -283,7 +288,7 @@ deploy:
```
See the
-[Publish NPM packages to the GitLab Package Registry using semantic-release](../../../ci/examples/semantic-release.md)
+[Publish npm packages to the GitLab Package Registry using semantic-release](../../../ci/examples/semantic-release.md)
step-by-step guide and demo project for a complete example.
## Publishing packages with the same name or version
@@ -296,8 +301,9 @@ the same version more than once, even if it has been deleted.
## Install a package
-NPM packages are commonly-installed by using the `npm` or `yarn` commands
-in a JavaScript project.
+npm packages are commonly-installed by using the `npm` or `yarn` commands
+in a JavaScript project. You can install a package from the scope of a project, group,
+or instance.
1. Set the URL for scoped packages by running:
@@ -309,24 +315,24 @@ in a JavaScript project.
1. Ensure [authentication](#authenticate-to-the-package-registry) is configured.
-1. In your project, to install a package, run:
+1. To install a package in your project, run:
```shell
- npm install @my-project-scope/my-package
+ npm install @my-scope/my-package
```
Or if you're using Yarn:
```shell
- yarn add @my-project-scope/my-package
+ yarn add @my-scope/my-package
```
In [GitLab 12.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/55344),
-when an NPM package is not found in the Package Registry, the request is forwarded to [npmjs.com](https://www.npmjs.com/).
+when an npm package is not found in the Package Registry, the request is forwarded to [npmjs.com](https://www.npmjs.com/).
Administrators can disable this behavior in the [Continuous Integration settings](../../admin_area/settings/continuous_integration.md).
-### Install NPM packages from other organizations
+### Install npm packages from other organizations
You can route package requests to organizations and users outside of GitLab.
@@ -343,12 +349,12 @@ and use your organization's URL. The name is case-sensitive and must match the n
//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
```
-### NPM dependencies metadata
+### npm dependencies metadata
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11867) in GitLab Premium 12.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
-In GitLab 12.6 and later, packages published to the Package Registry expose the following attributes to the NPM client:
+In GitLab 12.6 and later, packages published to the Package Registry expose the following attributes to the npm client:
- name
- version
@@ -360,10 +366,10 @@ In GitLab 12.6 and later, packages published to the Package Registry expose the
- peerDependencies
- deprecated
-## Add NPM distribution tags
+## Add npm distribution tags
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9425) in GitLab Premium 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
You can add [distribution tags](https://docs.npmjs.com/cli/dist-tag/) to newly-published packages.
Tags are optional and can be assigned to only one package at a time.
@@ -384,13 +390,13 @@ npm install @scope/package@my-tag # Install a specific tag
You cannot use your `CI_JOB_TOKEN` or deploy token with the `npm dist-tag` commands.
View [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/258835) for details.
-Due to a bug in NPM 6.9.0, deleting distribution tags fails. Make sure your NPM version is 6.9.1 or later.
+Due to a bug in npm 6.9.0, deleting distribution tags fails. Make sure your npm version is 6.9.1 or later.
## Troubleshooting
-### Error running Yarn with NPM registry
+### Error running Yarn with the Package Registry for npm registry
-If you are using [Yarn](https://classic.yarnpkg.com/en/) with the NPM registry, you may get
+If you are using [Yarn](https://classic.yarnpkg.com/en/) with the npm registry, you may get
an error message like:
```shell
@@ -419,7 +425,7 @@ yarn config set '//gitlab.example.com/api/v4/projects/<your_project_id>/packages
yarn config set '//gitlab.example.com/api/v4/packages/npm/:_authToken' "<your_token>"
```
-### `npm publish` targets default NPM registry (`registry.npmjs.org`)
+### `npm publish` targets default npm registry (`registry.npmjs.org`)
Ensure that your package scope is set consistently in your `package.json` and `.npmrc` files.
@@ -430,7 +436,7 @@ should look like:
{
"name": "@foo/my-package",
"version": "1.0.0",
- "description": "Example package for GitLab NPM registry",
+ "description": "Example package for GitLab npm registry",
}
```
@@ -442,9 +448,9 @@ And the `.npmrc` file should look like:
@foo:registry=https://gitlab.example.com/api/v4/packages/npm/
```
-### `npm install` returns `Error: Failed to replace env in config: ${NPM_TOKEN}`
+### `npm install` returns `Error: Failed to replace env in config: ${npm_TOKEN}`
-You do not need a token to run `npm install` unless your project is private. The token is only required to publish. If the `.npmrc` file was checked in with a reference to `$NPM_TOKEN`, you can remove it. If you prefer to leave the reference in, you must set a value prior to running `npm install` or set the value by using [GitLab environment variables](../../../ci/variables/README.md):
+You do not need a token to run `npm install` unless your project is private. The token is only required to publish. If the `.npmrc` file was checked in with a reference to `$npm_TOKEN`, you can remove it. If you prefer to leave the reference in, you must set a value prior to running `npm install` or set the value by using [GitLab CI/CD variables](../../../ci/variables/README.md):
```shell
NPM_TOKEN=<your_token> npm install
@@ -456,7 +462,7 @@ If you get this error, ensure that:
- Your token is not expired and has appropriate permissions.
- [Your token does not begin with `-`](https://gitlab.com/gitlab-org/gitlab/-/issues/235473).
-- A package with the same name doesn't already exist within the given scope.
+- A package with the same name or version doesn't already exist within the given scope.
- The scoped packages URL includes a trailing slash:
- Correct: `//gitlab.example.com/api/v4/packages/npm/`
- Incorrect: `//gitlab.example.com/api/v4/packages/npm`
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 35172663cc1..101bb810a0e 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -4,10 +4,10 @@ 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
---
-# NuGet packages in the Package Registry
+# NuGet packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20050) in GitLab Premium 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
Publish NuGet packages in your project’s Package Registry. Then, install the
packages whenever you need to use them as a dependency.
@@ -62,11 +62,13 @@ NuGet CLI.
## Use the GitLab endpoint for NuGet Packages
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36423) group-level endpoint in GitLab 13.8.
+
To use the GitLab endpoint for NuGet Packages, choose an option:
- **Project-level**: Use when you have few NuGet packages and they are not in
the same GitLab group.
-- **Group-level**: Use when you have many NuGet packages in different within the
+- **Group-level**: Use when you have many NuGet packages in different projects within the
same GitLab group.
Some features such as [publishing](#publish-a-nuget-package) a package are only available on the project-level endpoint.
@@ -104,6 +106,9 @@ You can now add a new source to NuGet with:
#### Project-level endpoint
+A project-level endpoint is required to publish NuGet packages to the Package Registry.
+A project-level endpoint is also required to install NuGet packages from a project.
+
To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with `nuget`:
```shell
@@ -120,6 +125,8 @@ nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/proje
#### Group-level endpoint
+To install a NuGet package from a group, use a group-level endpoint.
+
To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with `nuget`:
```shell
@@ -138,6 +145,9 @@ nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/group
#### Project-level endpoint
+A project-level endpoint is required to publish NuGet packages to the Package Registry.
+A project-level endpoint is also required to install NuGet packages from a project.
+
To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with Visual Studio:
1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/).
@@ -165,6 +175,8 @@ If you get a warning, ensure that the **Location**, **Username**, and
#### Group-level endpoint
+To install a package from a group, use a group-level endpoint.
+
To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with Visual Studio:
1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/).
@@ -194,6 +206,9 @@ If you get a warning, ensure that the **Location**, **Username**, and
#### Project-level endpoint
+A project-level endpoint is required to publish NuGet packages to the Package Registry.
+A project-level endpoint is also required to install NuGet packages from a project.
+
To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) Package Registry as a source for .NET:
1. In the root of your project, create a file named `nuget.config`.
@@ -217,6 +232,8 @@ To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) Package
#### Group-level endpoint
+To install a package from a group, use a group-level endpoint.
+
To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) Package Registry as a source for .NET:
1. In the root of your project, create a file named `nuget.config`.
@@ -246,7 +263,7 @@ Prerequisite:
When publishing packages:
-- The Package Registry on GitLab.com can store up to 500 MB of content.
+- The Package Registry on GitLab.com can store up to 5 GB of content.
This limit is [configurable for self-managed GitLab instances](../../../administration/instance_limits.md#package-registry-limits).
- If you publish the same package with the same version multiple times, each
consecutive upload is saved as a separate file. When installing a package,
@@ -324,8 +341,19 @@ updated:
1. Commit the changes and push it to your GitLab repository to trigger a new CI/CD build.
+### Publishing a package with the same name or version
+
+When you publish a package with the same name or version as an existing package,
+the existing package is overwritten.
+
## Install packages
+To install a NuGet package from the Package Registry, you must first
+[add a project-level or group-level endpoint](#add-the-package-registry-as-a-source-for-nuget-packages).
+
+If multiple packages have the same name and version, when you install
+a package, the most recently-published package is retrieved.
+
### Install a package with the NuGet CLI
WARNING:
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index 5876ef19ad9..19796de0f51 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Package Registry
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
With the GitLab Package Registry, you can use GitLab as a private or public registry
for a variety of common package managers. You can publish and share
@@ -21,15 +21,21 @@ You can view packages for your project or group.
You can search, sort, and filter packages on this page.
+When you view packages in a group:
+
+- All projects published to the group and its projects are displayed.
+- Only the projects you can access are displayed.
+- If a project is private, or you are not a member of the project, it is not displayed.
+
For information on how to create and upload a package, view the GitLab documentation for your package type.
## Use GitLab CI/CD to build packages
You can use [GitLab CI/CD](../../../ci/README.md) to build packages.
-For Maven, NuGet, NPM, Conan, and PyPI packages, and Composer dependencies, you can
+For Maven, NuGet, npm, Conan, and PyPI packages, and Composer dependencies, you can
authenticate with GitLab by using the `CI_JOB_TOKEN`.
-CI/CD templates, which you can use to get started, are in [this repo](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+CI/CD templates, which you can use to get started, are in [this repository](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
Learn more about using CI/CD to build:
@@ -37,7 +43,7 @@ Learn more about using CI/CD to build:
- [Conan packages](../conan_repository/index.md#publish-a-conan-package-by-using-cicd)
- [Generic packages](../generic_packages/index.md#publish-a-generic-package-by-using-cicd)
- [Maven packages](../maven_repository/index.md#create-maven-packages-with-gitlab-cicd)
-- [NPM packages](../npm_registry/index.md#publish-an-npm-package-by-using-cicd)
+- [npm packages](../npm_registry/index.md#publish-an-npm-package-by-using-cicd)
- [NuGet packages](../nuget_repository/index.md#publish-a-nuget-package-by-using-cicd)
If you use CI/CD to build a package, extended activity information is displayed
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 376c0439f32..763dbee3a82 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -4,10 +4,10 @@ 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
---
-# PyPI packages in the Package Registry
+# PyPI packages in the Package Registry **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Core in 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208747) in GitLab Premium 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) to GitLab Free in 13.3.
Publish PyPI packages in your project’s Package Registry. Then install the
packages whenever you need to use them as a dependency.
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index d20c75e2d7a..9b99b126996 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -13,7 +13,7 @@ Then you can configure your remote repositories to point to the project in GitLa
You might want to do this because:
- You want to publish your packages in GitLab, but to a different project from where your code is stored.
-- You want to group packages together in one project. For example, you might want to put all NPM packages,
+- You want to group packages together in one project. For example, you might want to put all npm packages,
or all packages for a specific department, or all private packages in the same project.
- When you install packages for other projects, you want to use one remote.
- You want to migrate your packages from a third-party package registry to a single place in GitLab and do not
@@ -27,7 +27,7 @@ No functionality is specific to this feature. Instead, we're taking advantage of
of each package management system to publish different package types to the same place.
- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
- Watch a video of how to add Maven, NPM, and Conan packages to [the same project](https://youtu.be/ui2nNBwN35c).
+ Watch a video of how to add Maven, npm, and Conan packages to [the same project](https://youtu.be/ui2nNBwN35c).
- [View an example project](https://gitlab.com/sabrams/my-package-registry/-/packages).
## Store different package types in one GitLab project
@@ -44,14 +44,14 @@ Let's take a look at how you might create a public place to hold all of your pub
You can upload all types of packages to the same project, or
split things up based on package type or package visibility level.
-### NPM
+### npm
-If you're using NPM, create an `.npmrc` file. Add the appropriate URL for publishing
+If you're using npm, create an `.npmrc` file. Add the appropriate URL for publishing
packages to your project. Finally, add a section to your `package.json` file.
Follow the instructions in the
-[GitLab NPM Registry documentation](../npm_registry/index.md#authenticate-to-the-package-registry). After
-you do this, you can publish your NPM package to your project using `npm publish`, as described in the
+[GitLab Package Registry npm documentation](../npm_registry/index.md#authenticate-to-the-package-registry). After
+you do this, you can publish your npm package to your project using `npm publish`, as described in the
[publishing packages](../npm_registry/index.md#publish-an-npm-package) section.
### Maven
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 3dbae78ccc4..68a68ed65ad 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -142,13 +142,13 @@ The following table depicts the various user permission levels in a project.
| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
| Run CI/CD pipeline against a protected branch | | | ✓ (*5*) | ✓ | ✓ |
| Delete [packages](packages/index.md) | | | | ✓ | ✓ |
-| Request a CVE ID **(FREE ONLY)** | | | | ✓ | ✓ |
+| Request a CVE ID **(FREE SAAS)** | | | | ✓ | ✓ |
| Use environment terminals | | | | ✓ | ✓ |
-| Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ |
+| Run Web IDE's Interactive Web Terminals **(ULTIMATE SELF)** | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
| Enable/disable branch protection | | | | ✓ | ✓ |
| Push to protected branches | | | | ✓ | ✓ |
-| Turn on/off protected branch push for devs | | | | ✓ | ✓ |
+| Turn on/off protected branch push for developers | | | | ✓ | ✓ |
| Enable/disable tag protections | | | | ✓ | ✓ |
| Edit project settings | | | | ✓ | ✓ |
| Edit project badges | | | | ✓ | ✓ |
@@ -172,7 +172,7 @@ The following table depicts the various user permission levels in a project.
| Delete wiki pages | | | | ✓ | ✓ |
| View project Audit Events | | | ✓ (*12*) | ✓ | ✓ |
| Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ |
-| Manage [project access tokens](project/settings/project_access_tokens.md) **(CORE ONLY)** | | | | ✓ | ✓ |
+| Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
| Rename project | | | | | ✓ |
@@ -183,13 +183,14 @@ The following table depicts the various user permission levels in a project.
| Delete pipelines | | | | | ✓ |
| Delete merge request | | | | | ✓ |
| Disable notification emails | | | | | ✓ |
+| Administer project compliance frameworks | | | | | ✓ |
| Force push to protected branches (*4*) | | | | | |
| Remove protected branches (*4*) | | | | | |
1. Guest users are able to perform this action on public and internal projects, but not private projects. This doesn't apply to [external users](#external-users) where explicit access must be given even if the project is internal.
1. Guest users can only view the confidential issues 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. 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#using-the-allowed-to-merge-and-allowed-to-push-settings), 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 tags and commits.
1. Actions are limited only to records owned (referenced) by user.
@@ -282,7 +283,7 @@ group.
| Manage group members | | | | | ✓ |
| Delete group | | | | | ✓ |
| Delete group epic **(PREMIUM)** | | | | | ✓ |
-| Edit SAML SSO Billing **(SILVER ONLY)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
+| Edit SAML SSO Billing **(PREMIUM SAAS)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
| Disable notification emails | | | | | ✓ |
| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -290,9 +291,10 @@ group.
| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Productivity analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Billing **(FREE ONLY)** | | | | | ✓ (4) |
-| View Usage Quotas **(FREE ONLY)** | | | | | ✓ (4) |
+| View Billing **(FREE SAAS)** | | | | | ✓ (4) |
+| View Usage Quotas **(FREE SAAS)** | | | | | ✓ (4) |
| Filter members by 2FA status | | | | | ✓ |
+| Administer project compliance frameworks | | | | | ✓ |
1. Groups can be set to [allow either Owners or Owners and
Maintainers to create subgroups](group/subgroups/index.md#creating-a-subgroup)
@@ -314,7 +316,7 @@ nested groups if you have membership in one of its parents.
To learn more, read through the documentation on
[subgroups memberships](group/subgroups/index.md#membership).
-## External users **(CORE ONLY)**
+## External users **(FREE SELF)**
In cases where it is desired that a user has access only to some internal or
private projects, there is the option of creating **External Users**. This
@@ -352,6 +354,9 @@ An administrator can flag a user as external by either of the following methods:
or edit an existing one. There, you can find the option to flag the user as
external.
+Additionally users can be set as external users using [SAML groups](../integration/saml.md#external-groups)
+and [LDAP groups](../administration/auth/ldap/index.md#external-groups).
+
### Setting new users to external
By default, new users are not set as external users. This behavior can be changed
@@ -396,7 +401,7 @@ Beware though that even if a user is external, if they already have Reporter or
higher permissions in any project or group, they are **not** counted as a
free guest user.
-## Auditor users **(PREMIUM ONLY)**
+## Auditor users **(PREMIUM SELF)**
>[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/998) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.17.
@@ -421,7 +426,8 @@ details such as projects or subgroups. They do not have access to the group's pa
### Minimal access users take license seats
Users with even a "minimal access" role are counted against your number of license seats. This
-requirement does not apply for [GitLab Gold/Ultimate](https://about.gitlab.com/pricing/) subscriptions.
+requirement does not apply for [GitLab Ultimate](https://about.gitlab.com/pricing/)
+subscriptions.
## Project features
@@ -518,4 +524,4 @@ Read through the documentation on [LDAP users permissions](group/index.md#manage
## Project aliases
Project aliases can only be read, created and deleted by a GitLab administrator.
-Read through the documentation on [Project aliases](../user/project/index.md#project-aliases) to learn more.
+Read through the documentation on [Project aliases](../user/project/import/index.md#project-aliases) to learn more.
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index cdf80f722f7..91688989e55 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -5,7 +5,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Creating users **(CORE ONLY)**
+# Creating users **(FREE SELF)**
You can create users:
@@ -37,3 +37,5 @@ Users will be:
- Automatically created upon first sign in with the [LDAP integration](../../../administration/auth/ldap/index.md).
- Created when first signing in via an [OmniAuth provider](../../../integration/omniauth.md) if the `allow_single_sign_on` setting is present.
+- Created when first signing with [Group SAML](../../group/saml_sso/index.md)
+- Automatically created by [SCIM](../../group/saml_sso/scim_setup.md) when the user is created in the identity provider.
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index e347221bd66..a33b6742d61 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -17,20 +17,21 @@ Deleting a user will delete all projects in that user namespace.
## As a user
-As a user, you can delete your own account by:
+As a user, to delete your own account:
-1. Clicking on your avatar.
-1. Navigating to **Settings > Account**.
-1. Selecting **Delete account**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Account**.
+1. Select **Delete account**.
## As an administrator
-As an administrator, you can delete a user account by:
+As an administrator, to delete a user account:
-1. Navigating to **Admin Area > Overview > Users**.
-1. Selecting a user.
-1. Under the **Account** tab, clicking:
- - **Delete user** to delete only the user but maintaining their
+1. Go to **Admin Area > Overview > Users**.
+1. Select a user.
+1. Under the **Account** tab, select:
+ - **Delete user** to delete only the user but maintain their
[associated records](#associated-records).
- **Delete user and contributions** to delete the user and
their associated records.
diff --git a/doc/user/profile/account/index.md b/doc/user/profile/account/index.md
deleted file mode 100644
index b10cc778f45..00000000000
--- a/doc/user/profile/account/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../index.md#profile-settings'
----
-
-This document was moved to [../index.md#profile-settings](../index.md#profile-settings).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 6cdd2d6f161..44bf97bdd42 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -44,7 +44,7 @@ To enable 2FA:
1. **In GitLab:**
1. Sign in to your GitLab account.
- 1. Go to your [**Profile settings**](../index.md#profile-settings).
+ 1. Go to your [**User settings**](../index.md#user-settings).
1. Go to **Account**.
1. Select **Enable Two-factor Authentication**.
1. **On your device (usually your phone):**
@@ -240,13 +240,13 @@ following desktop browsers:
NOTE:
For Firefox 47-66, you can enable the FIDO U2F API in
-[about:config](https://support.mozilla.org/en-US/kb/about-config-editor-firefox).
+[`about:config`](https://support.mozilla.org/en-US/kb/about-config-editor-firefox).
Search for `security.webauth.u2f` and double click on it to toggle to `true`.
To set up 2FA with a U2F device:
1. Sign in to your GitLab account.
-1. Go to your [**Profile settings**](../index.md#profile-settings).
+1. Go to your [**User settings**](../index.md#user-settings).
1. Go to **Account**.
1. Click **Enable Two-Factor Authentication**.
1. Connect your U2F device.
@@ -262,7 +262,7 @@ Click on **Register U2F Device** to complete the process.
> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
> - It's disabled on GitLab.com.
> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-webauthn). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-webauthn). **(FREE SELF)**
The WebAuthn workflow is [supported by](https://caniuse.com/#search=webauthn) the
following desktop browsers:
@@ -282,7 +282,7 @@ and the following mobile browsers:
To set up 2FA with a WebAuthn compatible device:
1. Sign in to your GitLab account.
-1. Go to your [**Profile settings**](../index.md#profile-settings).
+1. Go to your [**User settings**](../index.md#user-settings).
1. Go to **Account**.
1. Select **Enable Two-Factor Authentication**.
1. Plug in your WebAuthn device.
@@ -349,7 +349,7 @@ request and you're automatically signed in.
If you ever need to disable 2FA:
1. Sign in to your GitLab account.
-1. Go to your [**Profile settings**](../index.md#profile-settings).
+1. Go to your [**User settings**](../index.md#user-settings).
1. Go to **Account**.
1. Click **Disable**, under **Two-Factor Authentication**.
@@ -384,7 +384,7 @@ codes. If you saved these codes, you can use one of them to sign in.
To use a recovery code, enter your username/email and password on the GitLab
sign-in page. When prompted for a two-factor code, enter the recovery code.
-Once you use a recovery code, you cannot re-use it. You can still use the other
+After you use a recovery code, you cannot re-use it. You can still use the other
recovery codes you saved.
### Generate new recovery codes using SSH
@@ -434,7 +434,7 @@ a new set of recovery codes with SSH:
When prompted for a two-factor code, enter one of the recovery codes obtained
from the command-line output.
-After signing in, visit your **Profile settings > Account** immediately to set
+After signing in, visit your **User settings > Account** immediately to set
up two-factor authentication with a new device.
### Regenerate 2FA recovery codes
@@ -443,8 +443,8 @@ To regenerate 2FA recovery codes, you need access to a desktop browser:
1. Navigate to GitLab.
1. Sign in to your GitLab account.
-1. Go to your [**Profile settings**](../index.md#profile-settings).
-1. Select **{account}** **Account > Two-Factor Authentication (2FA)**.
+1. Go to your [**User settings**](../index.md#user-settings).
+1. Select **Account > Two-Factor Authentication (2FA)**.
1. If you've already configured 2FA, click **Manage two-factor authentication**.
1. In the **Register Two-Factor Authenticator** pane, click **Regenerate recovery codes**.
@@ -479,7 +479,7 @@ Sign in and re-enable two-factor authentication as soon as possible.
- To enforce 2FA at the system or group levels see [Enforce Two-factor Authentication](../../../security/two_factor_authentication.md).
-## Enable or disable WebAuthn **(CORE ONLY)**
+## Enable or disable WebAuthn **(FREE SELF)**
Support for WebAuthn is under development and not ready for production use. It is
deployed behind a feature flag that is **disabled by default**.
diff --git a/doc/user/profile/active_sessions.md b/doc/user/profile/active_sessions.md
index 381015f17c3..e55b92378bd 100644
--- a/doc/user/profile/active_sessions.md
+++ b/doc/user/profile/active_sessions.md
@@ -14,9 +14,11 @@ review the sessions, and revoke any you don't recognize.
## Listing all active sessions
-1. Click your avatar.
-1. Select **Settings**.
-1. Click **Active Sessions** in the sidebar.
+To list all active sessions:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Active Sessions**.
![Active sessions list](img/active_sessions_list.png)
@@ -29,8 +31,12 @@ exceeds 100, the oldest ones are deleted.
## Revoking a session
-1. Use the previous steps to navigate to **Active Sessions**.
-1. Click on **Revoke** besides a session. The current session cannot be revoked, as this would sign you out of GitLab.
+To revoke an active session:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Active Sessions**.
+1. Select **Revoke** next to a session. The current session cannot be revoked, as this would sign you out of GitLab.
NOTE:
When any session is revoked all **Remember me** tokens for all
diff --git a/doc/user/profile/img/profil-preferences-navigation-theme.png b/doc/user/profile/img/profil-preferences-navigation-theme.png
deleted file mode 100644
index 335a19ac290..00000000000
--- a/doc/user/profile/img/profil-preferences-navigation-theme.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/profile/img/profile_following_v13_9.png b/doc/user/profile/img/profile_following_v13_9.png
new file mode 100644
index 00000000000..878dce83997
--- /dev/null
+++ b/doc/user/profile/img/profile_following_v13_9.png
Binary files differ
diff --git a/doc/user/profile/img/profile_settings_dropdown.png b/doc/user/profile/img/profile_settings_dropdown.png
deleted file mode 100644
index 99b06a1bf58..00000000000
--- a/doc/user/profile/img/profile_settings_dropdown.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index a96975fea92..d2cbf9e4acd 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# User account
Each GitLab account has a user profile, and settings. Your [profile](#user-profile)
-contains information about you, and your GitLab activity. Your [settings](#profile-settings)
+contains information about you, and your GitLab activity. Your [settings](#user-settings)
allow you to customize some aspects of GitLab to suit yourself.
## Creating users
@@ -29,8 +29,8 @@ See [Unknown Sign-In Notification](unknown_sign_in_notification.md) for more det
To access your profile:
-1. Click on your avatar.
-1. Select **Profile**.
+1. In the top-right corner, select your avatar.
+1. Select your name or username.
On your profile page, you can see the following information:
@@ -41,13 +41,19 @@ On your profile page, you can see the following information:
- Personal projects: your personal projects (respecting the project's visibility level)
- Starred projects: projects you starred
- Snippets: your personal code [snippets](../snippets.md#personal-snippets)
+- Followers: people following you
+- Following: people you are following
-## Profile settings
+Profile page with active Following view:
-To access your profile settings:
+![Follow users](img/profile_following_v13_9.png)
-1. Click on your avatar.
-1. Select **Settings**.
+## User settings
+
+To access your user settings:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
From there, you can:
@@ -78,11 +84,12 @@ From there, you can:
## Changing your password
-1. Navigate to your [profile's](#profile-settings) **Settings > Password**.
-1. Enter your current password in the 'Current password' field.
-1. Enter your desired new password twice, once in the 'New password' field and
- once in the 'Password confirmation' field.
-1. Click the 'Save password' button.
+1. Go to your [user settings](#user-settings).
+1. In the left sidebar, select **Password**.
+1. Enter your current password in the **Current password** field.
+1. Enter your desired new password twice, once in the **New password** field and
+ once in the **Password confirmation** field.
+1. Select **Save password**.
If you don't know your current password, select the 'I forgot my password' link.
@@ -92,17 +99,18 @@ If you don't know your current password, select the 'I forgot my password' link.
Your `username` is a unique [`namespace`](../group/index.md#namespaces)
related to your user ID. Changing it can have unintended side effects, read
-[how redirects behave](../project/index.md#redirects-when-changing-repository-paths)
+[how redirects behave](../project/repository/index.md#redirects-when-changing-repository-paths)
before proceeding.
To change your `username`:
-1. Navigate to your [profile's](#profile-settings) **Settings > Account**.
+1. Navigate to your [user settings](#user-settings).
+1. In the left sidebar, select **Account**.
1. Enter a new username under **Change username**.
-1. Click **Update username**.
+1. Select **Update username**.
WARNING:
-It is currently not possible to change your username if it contains a
+It is not possible to change your username if it contains a
project with [Container Registry](../packages/container_registry/index.md) tags,
because the project cannot be moved.
@@ -127,33 +135,31 @@ The following information is hidden from the user profile page (`https://gitlab.
- Starred projects tab
- Snippets tab
-To enable private profile:
+To make your profile private:
-1. Click your avatar.
-1. Select **Profile**.
-1. Click **Edit profile** (pencil icon).
-1. Check the **Private profile** option in the **Main settings** section.
-1. Click **Update profile settings**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. Select the **Private profile** checkbox.
+1. Select **Update profile settings**.
NOTE:
-All your profile information can be seen by yourself, and GitLab admins, even if
+All your profile information can be seen by yourself and GitLab administrators even if
the **Private profile** option is enabled.
## Add details of external accounts
-GitLab allows you to add links to certain other external accounts you might have, like Skype and Twitter. They can help other users connect with you on other platforms.
+You can add links to certain other external accounts you might have, like Skype and Twitter.
+They can help other users connect with you on other platforms.
To add links to other accounts:
-1. Click your avatar.
-1. Select **Profile**.
-1. Click **Edit profile** (pencil icon).
-1. Complete the desired fields for external accounts, in the **Main settings**
- section:
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. Edit the desired fields for external accounts:
- Skype
- - Twitter
- LinkedIn
-1. Click **Update profile settings**.
+ - Twitter
+1. Select **Update profile settings**.
## Private contributions
@@ -163,11 +169,10 @@ Enabling private contributions includes contributions to private projects, in th
To enable private contributions:
-1. Click on your avatar.
-1. Select **Profile**.
-1. Click **Edit profile** (pencil icon).
-1. Check the **Private contributions** option.
-1. Click **Update profile settings**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. Select the **Private contributions** checkbox.
+1. Select **Update profile settings**.
## Current status
@@ -183,23 +188,23 @@ They may however contain emoji codes such as `I'm on vacation :palm_tree:`.
To set your current status:
-1. Click your avatar.
-1. Click **Set status**, or **Edit status** if you have already set a status.
-1. Set the desired emoji and/or status message.
-1. Click **Set status**. Alternatively, you can click **Remove status** to remove your user status entirely.
+1. In the top-right corner, select your avatar.
+1. Select **Set status**, or **Edit status** if you have already set a status.
+1. Set the desired emoji and status message.
+1. Select **Set status**. Alternatively, you can select **Remove status** to remove your user status entirely.
or
-1. Click your avatar.
-1. Select **Profile**.
-1. Click **Edit profile** (pencil icon).
+1. In the top-right corner, select your avatar.
+1. Select your name or username.
+1. Select the Edit profile icon (**{pencil}**).
1. Enter your status message in the **Your status** text field.
-1. Click **Add status emoji** (smiley face), and select the desired emoji.
-1. Click **Update profile settings**.
+1. Select Add status emoji icon (**{slight-smile}**), and select the desired emoji.
+1. Select **Update profile settings**.
You can also set your current status [using the API](../../api/users.md#user-status).
-If you previously selected the "Busy" checkbox, remember to deselect it when you become available again.
+If you previously selected the **Busy** checkbox, remember to deselect it when you become available again.
## Busy status indicator
@@ -210,7 +215,7 @@ If you previously selected the "Busy" checkbox, remember to deselect it when you
> - It's not recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-busy-status-feature).
-To indicate to others that you are busy, you can set an indicator
+To indicate to others that you are busy, you can set an indicator.
![Busy status indicator](img/busy_status_indicator_v13_6.png)
@@ -218,16 +223,15 @@ To set the busy status indicator, either:
- Set it directly:
- 1. Click your avatar.
- 1. Click **Set status**, or **Edit status** if you have already set a status.
- 1. Select the **Busy** checkbox
+ 1. In the top-right corner, select your avatar.
+ 1. Select **Set status**, or **Edit status** if you have already set a status.
+ 1. Select the **Busy** checkbox.
- Set it on your profile:
- 1. Click your avatar.
- 1. Select **Profile**.
- 1. Click **Edit profile** (**{pencil}**).
- 1. Select the **Busy** checkbox
+ 1. In the top-right corner, select your avatar.
+ 1. Select **Edit profile**.
+ 1. Select the **Busy** checkbox.
### Disable busy status feature
@@ -256,12 +260,11 @@ Any of your own verified email addresses can be used as the commit email.
To change your commit email:
-1. Click your avatar.
-1. Select **Profile**.
-1. Click **Edit profile** (pencil icon).
-1. Click **Commit email** dropdown.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. Select the **Commit email** dropdown.
1. Select any of the verified emails.
-1. Click **Update profile settings**.
+1. Select **Update profile settings**.
### Private commit email
@@ -272,14 +275,13 @@ which allows the user to keep their email information private.
To enable this option:
-1. Click your avatar.
-1. Select **Profile**.
-1. Click **Edit profile** (pencil icon).
-1. Click **Commit email** dropdown.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. Select the **Commit email** dropdown.
1. Select **Use a private email** option.
-1. Click **Update profile settings**.
+1. Select **Update profile settings**.
-Once this option is enabled, every Git-related action is performed using the private commit email.
+After this option is enabled, every Git-related action is performed using the private commit email.
To stay fully anonymous, you can also copy this private commit email
and configure it on your local machine using the following command:
@@ -298,7 +300,7 @@ and expires after "Application settings -> Session duration (minutes)"/`session_
(defaults to `10080` minutes = 7 days) of no activity.
When signing in to the main GitLab application, you can also check the
-"Remember me" option which sets the `remember_user_token`
+**Remember me** option which sets the `remember_user_token`
cookie (via [`devise`](https://github.com/heartcombo/devise)).
`remember_user_token` expires after
`config/initializers/devise.rb` -> `config.remember_for` (defaults to 2 weeks).
@@ -326,7 +328,8 @@ GitLab uses both session and persistent cookies:
- Session cookie: Session cookies are normally removed at the end of the browser session when
the browser is closed. The `_gitlab_session` cookie has no fixed expiration date. However,
it expires based on its [`session_expire_delay`](#why-do-i-keep-getting-signed-out).
-- Persistent cookie: The `remember_user_token` is a cookie with an expiration date of two weeks. GitLab activates this cookie if you click Remember Me when you sign in.
+- Persistent cookie: The `remember_user_token` is a cookie with an expiration date of two weeks.
+ GitLab activates this cookie if you select **Remember Me** when you sign in.
By default, the server sets a time-to-live (TTL) of 1-week on any session that is used.
@@ -336,15 +339,3 @@ The server continues to reset the TTL for that session, independent of whether 2
If you close your browser and open it up again, the `remember_user_token` cookie allows your user to reauthenticate itself.
Without the `config.extend_remember_period` flag, you would be forced to sign in again after two weeks.
-
-<!-- ## 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/profile/notifications.md b/doc/user/profile/notifications.md
index ae672d8414f..703154945db 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -15,8 +15,9 @@ Notifications are sent via email.
You receive notifications for one of the following reasons:
-- You participate in an issue, merge request, epic or design. In this context, _participate_ means comment, or edit.
-- You enable notifications in an issue, merge request, or epic. To enable notifications, click the **Notifications** toggle in the sidebar to _on_.
+- You participate in an issue, merge request, epic, or design. In this context, _participate_ means comment, or edit.
+- You [enable notifications in an issue, merge request, or epic](#notifications-on-issues-merge-requests-and-epics).
+- You configured notifications at the [project](#project-notifications) and/or [group](#group-notifications) level.
While notifications are enabled, you receive notification of actions occurring in that issue, merge request, or epic.
@@ -25,7 +26,9 @@ Notifications can be blocked by an administrator, preventing them from being sen
## Tuning your notifications
-The quantity of notifications can be overwhelming. GitLab allows you to tune the notifications you receive. For example, you may want to be notified about all activity in a specific project, but for others, only be notified when you are mentioned by name.
+The number of notifications can be overwhelming. GitLab allows you to tune the notifications you receive.
+For example, you might want to be notified about all activity in a specific project.
+For other projects, you only need to be notified when you are mentioned by name.
You can tune the notifications you receive by combining your notification settings:
@@ -53,6 +56,8 @@ Your **Global notification settings** are the default settings unless you select
- This is the email address your notifications are sent to.
- Global notification level
- This is the default [notification level](#notification-levels) which applies to all your notifications.
+- Receive product marketing emails
+ - Check this checkbox if you want to receive periodic emails related to GitLab features.
- Receive notifications about your own activity.
- Check this checkbox if you want to receive notification about your own activity. Default: Not checked.
@@ -159,49 +164,64 @@ Users are notified of the following events:
| Project moved | Project members (1) | (1) not disabled |
| New release | Project members | Custom notification |
-## Issue / Epics / Merge request events
+## Notifications on issues, merge requests, and epics
-In most of the below cases, the notification is sent to:
+To enable notifications on one specific issue, merge request or epic, you need to enable the **Notifications** toggle in the right sidebar.
+
+- **Enable**: If you are not a participant in the discussion on that issue, but
+ want to receive notifications on each update, subscribe to it.
+- **Disable**: If you are receiving notifications for updates to that issue but no
+ longer want to receive them, unsubscribe from it.
+
+Configuring this notification on an epic doesn't make you automatically subscribed to the issue that are linked to the epic.
+
+For most events, the notification is sent to:
- Participants:
- - the author and assignee of the issue/merge request
- - authors of comments on the issue/merge request
- - anyone mentioned by `@username` in the title or description of the issue, merge request or epic **(ULTIMATE)**
- - anyone with notification level "Participating" or higher that is mentioned by `@username` in any of the comments on the issue, merge request, or epic **(ULTIMATE)**
-- Watchers: users with notification level "Watch"
-- Subscribers: anyone who manually subscribed to the issue, merge request, or epic **(ULTIMATE)**
-- Custom: Users with notification level "custom" who turned on notifications for any of the events present in the table below
+ - The author and assignee of the issue/merge request.
+ - Authors of comments on the issue/merge request.
+ - Anyone mentioned by `@username` in the title or description of the issue, merge request or epic.
+ - Anyone with notification level "Participating" or higher that is mentioned by `@username` in any of the comments on the issue, merge request, or epic.
+- Watchers: users with notification level "Watch".
+- Subscribers: anyone who manually subscribed to the issue, merge request, or epic.
+- Custom: Users with notification level "custom" who turned on notifications for any of the events present in the table below.
NOTE:
-To minimize the number of notifications that do not require any action, from [GitLab 12.9 onwards](https://gitlab.com/gitlab-org/gitlab/-/issues/616), eligible approvers are no longer notified for all the activities in their projects. To receive them they have to change their user notification settings to **Watch** instead.
+To minimize the number of notifications that do not require any action, in
+[GitLab versions 12.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/616), eligible
+approvers are no longer notified for all the activities in their projects. To receive them they have
+to change their user notification settings to **Watch** instead.
+
+The following table presents the events that generate notifications for issues, merge requests, and
+epics:
| Event | Sent to |
|------------------------|---------|
-| New issue | |
+| Change milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
+| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
+| Close epic | |
| Close issue | |
-| Reassign issue | The above, plus the old assignee |
-| Reopen issue | |
+| Close merge request | |
| Due issue | Participants and Custom notification level with this event selected |
-| Change milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
-| Remove milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
+| Failed pipeline | The author of the pipeline |
+| Fixed pipeline ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24309) in GitLab 13.1.) | The author of the pipeline. Enabled by default. |
+| Merge merge request | |
+| Merge when pipeline succeeds ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211961) in GitLab 13.4) | |
+| New comment | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
+| New epic | |
+| New issue | |
| New merge request | |
| Push to merge request | Participants and Custom notification level with this event selected |
-| Reassign merge request | The above, plus the old assignee |
-| Close merge request | |
-| Reopen merge request | |
-| Merge merge request | |
-| Merge when pipeline succeeds ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211961) in GitLab 13.4) | |
-| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
+| Reassign issue | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus the old assignee |
+| Reassign merge request | Participants, Watchers, Subscribers, and Custom notification level with this event selected, plus the old assignee |
+| Remove milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
-| New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
-| Failed pipeline | The author of the pipeline |
-| Fixed pipeline | The author of the pipeline. Enabled by default. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24309) in GitLab 13.1. |
+| Reopen epic | |
+| Reopen issue | |
+| Reopen merge request | |
| Successful pipeline | The author of the pipeline, if they have the custom notification setting for successful pipelines set. If the pipeline failed previously, a `Fixed pipeline` message is sent for the first successful pipeline after the failure, then a `Successful pipeline` message for any further successful pipelines. |
-| New epic **(ULTIMATE)** | |
-| Close epic **(ULTIMATE)** | |
-| Reopen epic **(ULTIMATE)** | |
-In addition, if the title or description of an Issue or Merge Request is
+If the title or description of an issue or merge request is
changed, notifications are sent to any **new** mentions by `@username` as
if they had been mentioned in the original text.
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 49889cd3017..99db0c4b898 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -33,13 +33,14 @@ You can create as many personal access tokens as you like from your GitLab
profile.
1. Sign in to GitLab.
-1. In the upper-right corner, click your avatar and select **Settings**.
-1. On the **User Settings** menu, select **Access Tokens**.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **Access Tokens**.
1. Choose a name and optional expiry date for the token.
1. Choose the [desired scopes](#limiting-scopes-of-a-personal-access-token).
-1. Click the **Create personal access token** button.
+1. Select **Create personal access token**.
1. Save the personal access token somewhere safe. If you navigate away or refresh
-your page, and you did not save the token, you must create a new one.
+ your page, and you did not save the token, you must create a new one.
### Revoking a personal access token
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index af7bfb80cac..464edf13a7e 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -12,9 +12,8 @@ of GitLab to their liking.
To navigate to your profile's preferences:
-1. Click your avatar.
-1. Select **Settings**.
-1. Click **Preferences** in the sidebar.
+1. In the top-right corner, select your avatar.
+1. Select **Preferences**.
## Navigation theme
@@ -36,8 +35,7 @@ The default theme is Indigo. You can choose between 10 themes:
- Light Red
- Dark
- Light
-
-![Profile preferences navigation themes](img/profil-preferences-navigation-theme.png)
+- [Dark Mode](#dark-mode)
## Dark mode
@@ -47,7 +45,8 @@ GitLab has started work on dark mode! The dark mode Alpha release is available i
spirit of iteration and the lower expectations of
[Alpha versions](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha).
-Progress on dark mode is tracked in the [Dark theme epic](https://gitlab.com/groups/gitlab-org/-/epics/2902). See the epic for:
+Progress on dark mode is tracked in the [Dark theme epic](https://gitlab.com/groups/gitlab-org/-/epics/2902).
+See the epic for:
- A list of known issues.
- Our planned direction and next steps.
@@ -60,14 +59,15 @@ the future, we plan to make it configurable in its own section along with suppor
[different navigation themes](https://gitlab.com/gitlab-org/gitlab/-/issues/219512).
NOTE:
-Dark theme currently only works with the 'Dark' syntax highlighting.
+Dark theme only works with the **Dark** syntax highlighting theme.
## Syntax highlighting theme
NOTE:
GitLab uses the [rouge Ruby library](http://rouge.jneen.net/ "Rouge website")
for syntax highlighting outside of any Editor context. The WebIDE (like Snippets)
-uses [Monaco Editor](https://microsoft.github.io/monaco-editor/) and it's provided [Monarch](https://microsoft.github.io/monaco-editor/monarch.html) library for
+uses [Monaco Editor](https://microsoft.github.io/monaco-editor/) and it's provided
+[Monarch](https://microsoft.github.io/monaco-editor/monarch.html) library for
syntax highlighting. For a list of supported languages, visit the documentation of
the respective libraries.
@@ -76,12 +76,16 @@ syntax highlighted code on GitLab.
The default syntax theme is White, and you can choose among 5 different themes:
+<!-- vale gitlab.Spelling = NO -->
+
- White
- Dark
- Solarized light
- Solarized dark
- Monokai
+<!-- vale gitlab.Spelling = YES -->
+
![Profile preferences syntax highlighting themes](img/profile-preferences-syntax-themes.png)
[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2389) in 13.0, the theme
@@ -117,7 +121,7 @@ You have 8 options here that you can use for your default dashboard view:
- Your projects' activity
- Starred projects' activity
- Your groups
-- Your [to-dos](../todos.md)
+- Your [To-Do List](../todos.md)
- Assigned Issues
- Assigned Merge Requests
- Operations Dashboard **(PREMIUM)**
diff --git a/doc/user/project/autocomplete_characters.md b/doc/user/project/autocomplete_characters.md
index 1aa040c9cb8..8d8ff942d05 100644
--- a/doc/user/project/autocomplete_characters.md
+++ b/doc/user/project/autocomplete_characters.md
@@ -3,10 +3,12 @@ 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
-description: "Autocomplete chars in Markdown fields."
+description: "Autocomplete characters in Markdown fields."
---
-# Autocomplete characters
+# Autocomplete characters **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36705) in GitLab 13.9: you can search using the full name in user autocomplete.
The autocomplete characters provide a quick way of entering field values into
Markdown fields. When you start typing a word in a Markdown field with one of
@@ -57,4 +59,7 @@ If you continue to type, `@le`, the popup list changes to the following. The
popup now only includes users where `le` appears in their username, or a word in
their name.
-![Popup list which includes users whose username or name contains the string `le`](img/autocomplete_characters_example2_v12_0.png)
+![Popup list which includes users whose username or name contains the string](img/autocomplete_characters_example2_v12_0.png)
+
+You can also search across the full name to find a user.
+To find `Rosy Grant`, even if their username is for example `hunter2`, you can type their full name without spaces like `@rosygrant`.
diff --git a/doc/user/project/badges.md b/doc/user/project/badges.md
index f7bb88c33aa..7e6bba30001 100644
--- a/doc/user/project/badges.md
+++ b/doc/user/project/badges.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Badges
+# Badges **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41174) in GitLab 10.7.
diff --git a/doc/user/project/builds/artifacts.md b/doc/user/project/builds/artifacts.md
deleted file mode 100644
index e7572b4ff1f..00000000000
--- a/doc/user/project/builds/artifacts.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../pipelines/job_artifacts.md'
----
-
-This document was moved to [pipelines/job_artifacts](../pipelines/job_artifacts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/bulk_editing.md b/doc/user/project/bulk_editing.md
index a29c0754d31..d7e8133f9ad 100644
--- a/doc/user/project/bulk_editing.md
+++ b/doc/user/project/bulk_editing.md
@@ -14,27 +14,28 @@ For more details, see
If you want to update attributes across multiple issues or merge requests, you can do it
by bulk editing them, that is, editing them together.
-NOTE:
Only the items visible on the current page are selected for bulk editing (up to 20).
![Bulk editing](img/bulk-editing_v13_2.png)
## Bulk edit issues at the project level
-NOTE:
-You need a permission level of [Reporter or higher](../permissions.md) to manage issues.
+> - Assigning epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in GitLab 13.2.
+> - Editing health status [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) in GitLab 13.2.
+> - Editing iteration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196806) in GitLab 13.9.
+
+Users with permission level of [Reporter or higher](../permissions.md) can manage issues.
When bulk editing issues in a project, you can edit the following attributes:
- Status (open/closed)
- Assignee
-- Epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in
- [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.) **(PREMIUM)**
-- Milestone
-- Labels
-- Health status ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) in
- [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2.) **(ULTIMATE)**
-- Subscriptions
+- [Epic](../group/epics/index.md)
+- [Milestone](milestones/index.md)
+- [Labels](labels.md)
+- [Health status](issues/index.md#health-status)
+- Notification subscription
+- [Iteration](../group/iterations/index.md)
To update multiple project issues at the same time:
@@ -46,8 +47,7 @@ To update multiple project issues at the same time:
## Bulk edit merge requests at the project level
-NOTE:
-You need a permission level of [Developer or higher](../permissions.md) to manage merge requests.
+Users with permission level of [Developer or higher](../permissions.md) can manage merge requests.
When bulk editing merge requests in a project, you can edit the following attributes:
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index 85ac641f6e4..f7394093a3a 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -4,10 +4,10 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Canary Deployments **(CORE)**
+# Canary Deployments **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to GitLab Core in 13.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to GitLab Free in 13.8.
A popular [Continuous Deployment](https://en.wikipedia.org/wiki/Continuous_deployment)
strategy, where a small portion of the fleet is updated to the new version of
@@ -72,7 +72,7 @@ can easily notice them.
### Advanced traffic control with Canary Ingress
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215501) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to Core in GitLab 13.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to Free in GitLab 13.8.
Canary deployments can be more strategic with [Canary Ingress](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary),
which is an advanced traffic routing service that controls incoming HTTP
diff --git a/doc/user/project/ci_cd_for_external_repo.md b/doc/user/project/ci_cd_for_external_repo.md
deleted file mode 100644
index 57747be3859..00000000000
--- a/doc/user/project/ci_cd_for_external_repo.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../ci/ci_cd_for_external_repos/index.md'
----
-
-This document was moved to [another location](../../ci/ci_cd_for_external_repos/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index 9047e564598..eb6b8302667 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.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
---
-# Adding EKS clusters
+# Adding EKS clusters **(FREE)**
GitLab supports adding new and existing EKS clusters.
@@ -20,7 +20,7 @@ requirements are met:
- `kubectl` [installed and configured](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl)
for access to the EKS cluster.
-### Additional requirements for self-managed instances **(CORE ONLY)**
+### Additional requirements for self-managed instances **(FREE SELF)**
If you are using a self-managed GitLab instance, GitLab must first be configured with a set of
Amazon credentials. These credentials are used to assume an Amazon IAM role provided by the user
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index e3e6efc887f..af3a17dc60c 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.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
---
-# Adding GKE clusters
+# Adding GKE clusters **(FREE)**
GitLab supports adding new and existing GKE clusters.
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index beb8b71b917..718c60ccf0e 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.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
---
-# Adding and removing Kubernetes clusters
+# Adding and removing Kubernetes clusters **(FREE)**
GitLab offers integrated cluster creation for the following Kubernetes providers:
@@ -40,7 +40,7 @@ Before [adding a Kubernetes cluster](#create-new-cluster) using GitLab, you need
- [Maintainer access to a group](../../permissions.md#group-members-permissions) for a
group-level cluster.
- [Admin Area access](../../admin_area/index.md) for a self-managed instance-level
- cluster. **(CORE ONLY)**
+ cluster. **(FREE SELF)**
## Access controls
@@ -387,3 +387,13 @@ If you encounter this error while adding a Kubernetes cluster, ensure you're
properly pasting the service token. Some shells may add a line break to the
service token, making it invalid. Ensure that there are no line breaks by
pasting your token into an editor and removing any additional spaces.
+
+You may also experience this error if your certificate is not valid. To check that your certificate's
+subject alternative names contain the correct domain for your cluster's API, run this:
+
+```shell
+echo | openssl s_client -showcerts -connect kubernetes.example.com:443 2>/dev/null |
+openssl x509 -inform pem -noout -text
+```
+
+Note that the `-connect` argument expects a `host:port` combination. For example, `https://kubernetes.example.com` would be `kubernetes.example.com:443`.
diff --git a/doc/user/project/clusters/eks_and_gitlab/index.md b/doc/user/project/clusters/eks_and_gitlab/index.md
deleted file mode 100644
index e38fbb871c1..00000000000
--- a/doc/user/project/clusters/eks_and_gitlab/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../add_eks_clusters.md#existing-eks-cluster'
----
-
-This document was moved to [another location](../add_eks_clusters.md#existing-eks-cluster).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index a06846e33a6..d3d434762ab 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -4,7 +4,7 @@ group: Health
info: To 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 clusters
+# Kubernetes clusters **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35954) in GitLab 10.1 for projects.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34758) in
@@ -33,8 +33,10 @@ integrated at the [group level](../../group/clusters/index.md) or
To view your project level Kubernetes clusters, navigate to **Operations > Kubernetes**
from your project. On this page, you can [add a new cluster](#adding-and-removing-clusters)
-and view information about your existing clusters, such as nodes count and rough estimates
-of memory and CPU usage.
+and view information about your existing clusters, such as:
+
+- Nodes count.
+- Rough estimates of memory and CPU usage.
## Setting up
@@ -72,13 +74,12 @@ to:
### Multiple Kubernetes clusters
> - Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.3
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) to GitLab Core in 13.2.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35094) to GitLab Free in 13.2.
You can associate more than one Kubernetes cluster to your
project. That way you can have different clusters for different environments,
-like dev, staging, production, and so on.
-
-Simply add another cluster, like you did the first time, and make sure to
+like development, staging, production, and so on.
+Add another cluster, like you did the first time, and make sure to
[set an environment scope](#setting-the-environment-scope) that
differentiates the new cluster from the rest.
@@ -86,7 +87,7 @@ differentiates the new cluster from the rest.
When adding more than one Kubernetes cluster to your project, you need to differentiate
them with an environment scope. The environment scope associates clusters with [environments](../../../ci/environments/index.md) similar to how the
-[environment-specific variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-environment-variables) work.
+[environment-specific variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables) work.
The default environment scope is `*`, which means all jobs, regardless of their
environment, use that cluster. Each scope can be used only by a single cluster
@@ -165,7 +166,7 @@ details about the created resources.
If you choose to manage your own cluster, project-specific resources aren't created
automatically. If you are using [Auto DevOps](../../../topics/autodevops/index.md), you must
explicitly provide the `KUBE_NAMESPACE` [deployment variable](#deployment-variables)
-for your deployment jobs to use; otherwise a namespace is created for you.
+for your deployment jobs to use. Otherwise, a namespace is created for you.
#### Important notes
@@ -182,10 +183,10 @@ Note the following with GitLab and clusters:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31759) in GitLab 12.6.
-If you choose to allow GitLab to manage your cluster for you, GitLab stores a cached
+If you allow GitLab to manage your cluster, GitLab stores a cached
version of the namespaces and service accounts it creates for your projects. If you
modify these resources in your cluster manually, this cache can fall out of sync with
-your cluster, which can cause deployment jobs to fail.
+your cluster. This can cause deployment jobs to fail.
To clear the cache:
@@ -204,12 +205,61 @@ Specifying a base domain automatically sets `KUBE_INGRESS_BASE_DOMAIN` as an env
If you are using [Auto DevOps](../../../topics/autodevops/index.md), this domain is used for the different
stages. For example, Auto Review Apps and Auto Deploy.
-The domain should have a wildcard DNS configured to the Ingress IP address. After Ingress has been installed (see [Installing Applications](#installing-applications)),
+The domain should have a wildcard DNS configured to the Ingress IP address.
+After Ingress has been installed (see [Installing Applications](#installing-applications)),
you can either:
- Create an `A` record that points to the Ingress IP address with your domain provider.
- Enter a wildcard DNS address using a service such as nip.io or xip.io. For example, `192.168.1.1.xip.io`.
+To determine the external Ingress IP address, or external Ingress hostname:
+
+- *If the cluster is on GKE*:
+ 1. Click the **Google Kubernetes Engine** link in the **Advanced settings**,
+ or go directly to the [Google Kubernetes Engine dashboard](https://console.cloud.google.com/kubernetes/).
+ 1. Select the proper project and cluster.
+ 1. Click **Connect**
+ 1. Execute the `gcloud` command in a local terminal or using the **Cloud Shell**.
+
+- *If the cluster is not on GKE*: Follow the specific instructions for your
+ Kubernetes provider to configure `kubectl` with the right credentials.
+ The output of the following examples show the external endpoint of your
+ cluster. This information can then be used to set up DNS entries and forwarding
+ rules that allow external access to your deployed applications.
+
+Depending an your Ingress, the external IP address can be retrieved in various ways.
+This list provides a generic solution, and some GitLab-specific approaches:
+
+- In general, you can list the IP addresses of all load balancers by running:
+
+ ```shell
+ kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
+ ```
+
+- If you installed Ingress using the **Applications**, run:
+
+ ```shell
+ kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
+ ```
+
+- Some Kubernetes clusters return a hostname instead, like
+ [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
+
+ ```shell
+ kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
+ ```
+
+ If you use EKS, an [Elastic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/)
+ is also created, which incurs additional AWS costs.
+
+- Istio/Knative uses a different command. Run:
+
+ ```shell
+ kubectl get svc --namespace=istio-system istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
+ ```
+
+If you see a trailing `%` on some Kubernetes versions, do not include it.
+
## Installing applications
GitLab can install and manage some applications like Helm, GitLab Runner, Ingress,
@@ -224,10 +274,10 @@ Auto DevOps automatically detects, builds, tests, deploys, and monitors your
applications.
To make full use of Auto DevOps (Auto Deploy, Auto Review Apps, and
-Auto Monitoring) the Kubernetes project integration must be enabled, but
+Auto Monitoring) the Kubernetes project integration must be enabled. However,
Kubernetes clusters can be used without Auto DevOps.
-[Read more about Auto DevOps](../../../topics/autodevops/index.md)
+[Read more about Auto DevOps](../../../topics/autodevops/index.md).
## Deploying to a Kubernetes cluster
@@ -239,7 +289,7 @@ A Kubernetes cluster can be the destination for a deployment job. If
the cluster from your jobs using tools such as `kubectl` or `helm`.
- You don't use the GitLab cluster integration, you can still deploy to your
cluster. However, you must configure Kubernetes tools yourself
- using [environment variables](../../../ci/variables/README.md#custom-environment-variables)
+ using [environment variables](../../../ci/variables/README.md#custom-cicd-variables)
before you can interact with the cluster from your jobs.
### Deployment variables
@@ -260,9 +310,9 @@ following command in your deployment job script, for Kubernetes to access the re
kubectl create secret docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_DEPLOY_USER" --docker-password="$CI_DEPLOY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" -o yaml --dry-run | kubectl apply -f -
```
-The Kubernetes cluster integration exposes the following
-[deployment variables](../../../ci/variables/README.md#deployment-environment-variables) in the
-GitLab CI/CD build environment to deployment jobs, which are jobs that have
+The Kubernetes cluster integration exposes these
+[deployment variables](../../../ci/variables/README.md#deployment-variables) in the
+GitLab CI/CD build environment to deployment jobs. Deployment jobs have
[defined a target environment](../../../ci/environments/index.md#defining-environments).
| Variable | Description |
@@ -303,11 +353,11 @@ When you customize the namespace, existing environments remain linked to their c
namespaces until you [clear the cluster cache](#clearing-the-cluster-cache).
WARNING:
-By default, anyone who can create a deployment job can access any CI variable within
+By default, anyone who can create a deployment job can access any CI variable in
an environment's deployment job. This includes `KUBECONFIG`, which gives access to
any secret available to the associated service account in your cluster.
To keep your production credentials safe, consider using
-[Protected Environments](../../../ci/environments/protected_environments.md),
+[protected environments](../../../ci/environments/protected_environments.md),
combined with either
- a GitLab-managed cluster and namespace per environment,
@@ -327,8 +377,8 @@ the need to leave GitLab.
#### Deploy Boards
GitLab Deploy Boards offer a consolidated view of the current health and
-status of each CI [environment](../../../ci/environments/index.md) running on Kubernetes,
-displaying the status of the pods in the deployment. Developers and other
+status of each CI [environment](../../../ci/environments/index.md) running on Kubernetes.
+They display the status of the pods in the deployment. Developers and other
teammates can view the progress and status of a rollout, pod by pod, in the
workflow they already use without any need to access Kubernetes.
@@ -336,7 +386,7 @@ workflow they already use without any need to access Kubernetes.
#### Viewing pod logs
-GitLab makes it easy to view the logs of running pods in connected Kubernetes
+GitLab enables you to view the logs of running pods in connected Kubernetes
clusters. By displaying the logs directly in GitLab, developers can avoid having
to manage console tools or jump to a different interface.
@@ -349,7 +399,7 @@ to manage console tools or jump to a different interface.
When enabled, the Kubernetes integration adds [web terminal](../../../ci/environments/index.md#web-terminals)
support to your [environments](../../../ci/environments/index.md). This is based
on the `exec` functionality found in Docker and Kubernetes, so you get a new
-shell session within your existing containers. To use this integration, you
+shell session in your existing containers. To use this integration, you
should deploy to Kubernetes using the deployment variables above, ensuring any
deployments, replica sets, and pods are annotated with:
@@ -402,7 +452,7 @@ Automatically detect and monitor Kubernetes metrics. Automatic monitoring of
### Visualizing cluster health
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4701) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) to GitLab Core in 13.2.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/208224) to GitLab Free in 13.2.
When [Prometheus is deployed](#installing-applications), GitLab monitors the cluster's health. At the top of the cluster settings page, CPU and Memory utilization is displayed, along with the total amount available. Keeping an eye on cluster resources can be important, if the cluster runs out of memory pods may be shutdown or fail to start.
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index 2523dc3e0a2..349040e0bf6 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -4,10 +4,10 @@ group: Health
info: To 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
+# Kubernetes Logs **(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 Core](https://about.gitlab.com/pricing/) 12.9.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) to [GitLab Free](https://about.gitlab.com/pricing/) 12.9.
GitLab makes it easy to view the logs of running pods or managed applications in
[connected Kubernetes clusters](index.md). By displaying the logs directly in GitLab
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 8299844e511..a7cdd73acd7 100644
--- a/doc/user/project/clusters/protect/container_network_security/index.md
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -28,10 +28,9 @@ chart.
- GitLab managed installation of Cilium.
- Support for L3, L4, and L7 policies.
- Ability to export logs to a SIEM.
-- Statistics page showing volume of packets processed and dropped over time (Gold/Ultimate users
- only).
+- Statistics page showing volume of packets processed and dropped over time (Ultimate users only).
- Management of NetworkPolicies through code in a project (Available for auto DevOps users only).
-- Management of CiliumNetworkPolicies through a UI policy manager (Gold/Ultimate users only).
+- Management of CiliumNetworkPolicies through a UI policy manager (Ultimate users only).
## Supported container orchestrators
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 10f9380a1f2..e530f0dfcda 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
@@ -46,11 +46,11 @@ Network Policies can be managed through GitLab in one of two ways:
- Management through a YAML file in each application's project (for projects using Auto DevOps). For
more information, see the [Network Policy documentation](../../../../../topics/autodevops/stages.md#network-policy).
- Management through the GitLab Policy management UI (for projects not using Auto DevOps). For more
- information, see the [Container Network Policy documentation](../../../../application_security/threat_monitoring/index.md#container-network-policy-management) (Ultimate/Gold only).
+ information, see the [Container Network Policy documentation](../../../../application_security/threat_monitoring/index.md#container-network-policy-management) (Ultimate only).
Each method has benefits and drawbacks:
-| | YAML method | UI method (Ultimate/Gold only) |
+| | YAML method | UI method (Ultimate only) |
|--|:------------|:-------------------------------|
| **Benefits** | A change control process is possible by requiring [MR Approvals](../../../merge_requests/merge_request_approvals.md). All changes are fully tracked and audited in the same way that Git tracks the history of any file in its repository. | The UI provides a simple rules editor for users who are less familiar with the YAML syntax of NetworkPolicies. This view is a live representation of the policies currently deployed in the Kubernetes cluster. The UI also allows for multiple network policies to be created per environment. |
| **Drawbacks** | Only one network policy can be deployed per environment (although that policy can be as detailed as needed). Also, if changes were made in Kubernetes directly rather than through the `auto-deploy-values.yaml` file, the YAML file's contents don't represent the actual state of policies deployed in Kubernetes. | Policy changes aren't audited and a change control process isn't available. |
diff --git a/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
index e9a05b58fec..e7d8d591510 100644
--- a/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
+++ b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md
@@ -43,7 +43,7 @@ Google Kubernetes Engine integration. All you have to do is [follow this link](h
## Creating a new project from a template
We use a GitLab project templates to get started. As the name suggests,
-those projects provide a barebones application built on some well-known frameworks.
+those projects provide a bare-bones application built on some well-known frameworks.
1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select
**New project**.
@@ -55,7 +55,7 @@ those projects provide a barebones application built on some well-known framewor
1. Give your project a name, optionally a description, and make it public so that
you can take advantage of the features available in the
- [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com).
+ [GitLab Ultimate plan](https://about.gitlab.com/pricing/).
![Create project](../../../../../topics/autodevops/img/guide_create_project_v12_3.png)
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index 8572ab850e4..7f344349984 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.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
---
-# Runbooks
+# Runbooks **(FREE)**
Runbooks are a collection of documented procedures that explain how to
carry out a particular process, be it starting, stopping, debugging,
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index a52d3400aa2..192a7c7cd39 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.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
---
-# Deploying AWS Lambda function using GitLab CI/CD
+# Deploying AWS Lambda function using GitLab CI/CD **(FREE)**
GitLab allows users to easily deploy AWS Lambda functions and create rich serverless applications.
@@ -25,7 +25,7 @@ Additionally, in the [How To section](#how-to), you can read about different use
- Working with secrets.
- Setting up CORS.
-Alternatively, you can quickly [create a new project with a template](../../../../gitlab-basics/create-project.md#project-templates). The [`Serverless Framework/JS` template](https://gitlab.com/gitlab-org/project-templates/serverless-framework/) already includes all parts described below.
+Alternatively, you can quickly [create a new project with a template](../../working_with_projects.md#create-a-project). The [`Serverless Framework/JS` template](https://gitlab.com/gitlab-org/project-templates/serverless-framework/) already includes all parts described below.
### Example
@@ -74,7 +74,7 @@ Place this code in the file `src/handler.js`.
In our case, `module.exports.hello` defines the `hello` handler to reference later in the `serverless.yml`.
-You can learn more about the AWS Lambda Node.js function handler and all its various options here: <https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html>
+You can learn more about the [AWS Lambda Node.js function handler](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html) and all its various options in its documentation.
#### Creating a `serverless.yml` file
@@ -290,7 +290,7 @@ The example code is available:
- As a [clonable repository](https://gitlab.com/gitlab-org/serverless/examples/serverless-framework-js).
- In a version with [tests and secret variables](https://gitlab.com/gitlab-org/project-templates/serverless-framework/).
-You can also use a [template](../../../../gitlab-basics/create-project.md#project-templates)
+You can also use a [template](../../working_with_projects.md#project-templates)
(based on the version with tests and secret variables) from within the GitLab UI (see
the `Serverless Framework/JS` template).
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index 043c5e4ca79..c7ed8d6d2a5 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.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
---
-# Serverless
+# Serverless **(FREE)**
> Introduced in GitLab 11.5.
diff --git a/doc/user/project/code_intelligence.md b/doc/user/project/code_intelligence.md
index 19dc3588162..0e8c1bf8f4d 100644
--- a/doc/user/project/code_intelligence.md
+++ b/doc/user/project/code_intelligence.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Code Intelligence
+# Code Intelligence **(FREE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/1576) in GitLab 13.1.
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index 63ea84e42c9..3135aa78719 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -5,11 +5,11 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Code Owners **(STARTER)**
+# Code Owners **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6916)
-in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
-> - Code Owners for Merge Request approvals was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4418) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6916) in GitLab 11.3.
+> - Code Owners for Merge Request approvals was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4418) in GitLab Premium 11.9.
+> - Moved to GitLab Premium in 13.9.
## Introduction
@@ -18,7 +18,7 @@ to find out who should review or approve merge requests.
Additionally, if you have a question over a specific file or
code block, it may be difficult to know who to find the answer from.
-GitLab Code Owners is a feature to define who owns specific
+The GitLab Code Owners feature defines who owns specific
files or paths in a repository, allowing other users to understand
who is responsible for each file or path.
@@ -32,7 +32,7 @@ the process of finding the right reviewers and approvers for a given
merge request.
In larger organizations or popular open source projects, Code Owners
-can also be useful to understand who to contact if you have
+can help you understand who to contact if you have
a question that may not be related to code review or a merge request
approval.
@@ -49,12 +49,12 @@ You can choose to add the `CODEOWNERS` file in three places:
- Inside the `docs/` directory
The `CODEOWNERS` file is valid for the branch where it lives. For example, if you change the code owners
-in a feature branch, they won't be valid in the main branch until the feature branch is merged.
+in a feature branch, the changes aren't valid in the main branch until the feature branch is merged.
If you introduce new files to your repository and you want to identify the code owners for that file,
-you have to update `CODEOWNERS` accordingly. If you update the code owners when you are adding the files (in the same
-branch), GitLab will count the owners as soon as the branch is merged. If
-you don't, you can do that later, but your new files will not belong to anyone until you update your
+you must update `CODEOWNERS` accordingly. If you update the code owners when you are adding the files (in the same
+branch), GitLab counts the owners as soon as the branch is merged. If
+you don't, you can do that later, but your new files don't belong to anyone until you update your
`CODEOWNERS` file in the TARGET branch.
When a file matches multiple entries in the `CODEOWNERS` file,
@@ -73,29 +73,32 @@ The user that would show for `README.md` would be `@user2`.
## Approvals by Code Owners
-Once you've added Code Owners to a project, you can configure it to
+After you've added Code Owners to a project, you can configure it to
be used for merge request approvals:
- As [merge request eligible approvers](merge_requests/merge_request_approvals.md#code-owners-as-eligible-approvers).
- As required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners). **(PREMIUM)**
-Developer or higher [permissions](../permissions.md) are required in order to
+Developer or higher [permissions](../permissions.md) are required to
approve a merge request.
-Once set, Code Owners are displayed in merge requests widgets:
+After it's set, Code Owners are displayed in merge request widgets:
![MR widget - Code Owners](img/code_owners_mr_widget_v12_4.png)
-While the `CODEOWNERS` file can be used in addition to Merge Request [Approval Rules](merge_requests/merge_request_approvals.md#approval-rules),
-it can also be used as the sole driver of merge request approvals
-(without using [Approval Rules](merge_requests/merge_request_approvals.md#approval-rules)).
-To do so, create the file in one of the three locations specified above and
-set the code owners as required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners).
-Use [the syntax of Code Owners files](code_owners.md#the-syntax-of-code-owners-files)
-to specify the actual owners and granular permissions.
+While you can use the `CODEOWNERS` file in addition to Merge Request
+[Approval Rules](merge_requests/merge_request_approvals.md#approval-rules),
+you can also use it as the sole driver of merge request approvals
+without using [Approval Rules](merge_requests/merge_request_approvals.md#approval-rules):
-Using Code Owners in conjunction with [Protected Branches](protected_branches.md#protected-branches-approval-by-code-owners)
-will prevent any user who is not specified in the `CODEOWNERS` file from pushing
+1. Create the file in one of the three locations specified above.
+1. Set the code owners as required approvers for
+ [protected branches](protected_branches.md#protected-branches-approval-by-code-owners).
+1. Use [the syntax of Code Owners files](code_owners.md#the-syntax-of-code-owners-files)
+ to specify the actual owners and granular permissions.
+
+Using Code Owners in conjunction with [protected branches](protected_branches.md#protected-branches-approval-by-code-owners)
+prevents any user who is not specified in the `CODEOWNERS` file from pushing
changes for the specified files/paths, except those included in the
**Allowed to push** column. This allows for a more inclusive push strategy, as
administrators don't have to restrict developers from pushing directly to the
@@ -114,13 +117,13 @@ in the `.gitignore` file followed by one or more of:
- The `@name` of one or more groups that should be owners of the file.
- Lines starting with `#` are ignored.
-The order in which the paths are defined is significant: the last pattern that
-matches a given path will be used to find the code owners.
+The path definition order is significant: the last pattern
+matching a given path is used to find the code owners.
### Groups as Code Owners
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) in GitLab Starter 12.1.
-> - Group and subgroup hierarchy support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32432) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) in GitLab 12.1.
+> - Group and subgroup hierarchy support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32432) in GitLab 13.0.
Groups and subgroups members are inherited as eligible Code Owners to a
project, as long as the hierarchy is respected.
@@ -131,7 +134,7 @@ suppose you have a project called "Project A" within the group and a
"Project B" within the subgroup.
The eligible Code Owners to Project B are both the members of the Group X and
-the Subgroup Y. And the eligible Code Owners to the Project A are just the
+the Subgroup Y. The eligible Code Owners to the Project A are just the
members of the Group X, given that Project A doesn't belong to the Subgroup Y:
![Eligible Code Owners](img/code_owners_members_v13_4.png)
@@ -142,9 +145,9 @@ Code Owners:
![Invite subgroup members to become eligible Code Owners](img/code_owners_invite_members_v13_4.png)
-Once invited, any member (`@user`) of the group or subgroup can be set
-as Code Owner to files of the Project A or B, as well as the entire Group X
-(`@group-x`) or Subgroup Y (`@group-x/subgroup-y`), as exemplified below:
+After being invited, any member (`@user`) of the group or subgroup can be set
+as Code Owner to files of the Project A or B, and the entire Group X
+(`@group-x`) or Subgroup Y (`@group-x/subgroup-y`), as follows:
```plaintext
# A member of the group or subgroup as Code Owner to a file
@@ -162,7 +165,7 @@ file.md @group-x @group-x/subgroup-y
### Code Owners Sections **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12137) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2 behind a feature flag, enabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12137) in GitLab Premium 13.2 behind a feature flag, enabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42389) in GitLab 13.4.
Code Owner rules can be grouped into named sections. This allows for better
@@ -185,8 +188,8 @@ changes, to set their own independent patterns by specifying discrete sections i
teams can be added as reviewers.
Sections can be added to `CODEOWNERS` files as a new line with the name of the
-section inside square brackets. Every entry following it is assigned to that
-section. The following example would create 2 Code Owner rules for the "README
+section inside square brackets. Every entry following is assigned to that
+section. The following example would create two Code Owner rules for the "README
Owners" section:
```plaintext
@@ -196,7 +199,7 @@ internal/README.md @user2
```
Multiple sections can be used, even with matching file or directory patterns.
-Reusing the same section name will group the results together under the same
+Reusing the same section name groups the results together under the same
section, with the most specific rule or last matching pattern being used. For
example, consider the following entries in a `CODEOWNERS` file:
@@ -213,7 +216,7 @@ model/db @gl-database
README.md @gl-docs
```
-This will result in 3 entries under the "Documentation" section header, and 2
+This results in three entries under the "Documentation" section header, and two
entries under "Database". Case is not considered when combining sections, so in
this example, entries defined under the sections "Documentation" and
"DOCUMENTATION" would be combined into one, using the case of the first instance
@@ -227,9 +230,11 @@ the rules for "Groups" and "Documentation" sections:
#### Optional Code Owners Sections **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232995) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.8 behind a feature flag, enabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232995) in GitLab Premium 13.8 behind a feature flag, enabled by default.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53227) in GitLab 13.9.
-When you want to make a certain section optional, you can do so by adding a code owners section prepended with the caret `^` character. Approvals from owners listed in the section will **not** be required. For example:
+To make a certain section optional, add a code owners section prepended with the
+caret `^` character. Approvals from owners listed in the section are **not** required. For example:
```plaintext
[Documentation]
@@ -242,13 +247,13 @@ When you want to make a certain section optional, you can do so by adding a code
*.go @root
```
-The optional code owners section will be displayed in merge requests under the **Approval Rules** area:
+The optional code owners section displays in merge requests under the **Approval Rules** area:
![MR widget - Optional Code Owners Sections](img/optional_code_owners_sections_v13_8.png)
-If a section is duplicated in the file, and one of them is marked as optional and the other isn't, the requirement prevails.
+If a section is duplicated in the file, and one of them is marked as optional and the other isn't, the requirement prevails.
-For example, the code owners of the "Documentation" section below will still be required to approve merge requests:
+For example, the code owners of the "Documentation" section below is still required to approve merge requests:
```plaintext
[Documentation]
@@ -264,12 +269,12 @@ For example, the code owners of the "Documentation" section below will still be
*.txt @root
```
-Optional sections in the code owners file are currently treated as optional only
-when changes are submitted via merge requests. If a change is submitted directly
-to the protected branch, approval from code owners will still be required, even if the
-section is marked as optional. We plan to change this in a
+Optional sections in the code owners file are treated as optional only
+when changes are submitted by using merge requests. If a change is submitted directly
+to the protected branch, approval from code owners is still required, even if the
+section is marked as optional. We plan to change this behavior in a
[future release](https://gitlab.com/gitlab-org/gitlab/-/issues/297638),
-where direct pushes to the protected branch will be allowed for sections marked as optional.
+and allow direct pushes to the protected branch for sections marked as optional.
## Example `CODEOWNERS` file
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
deleted file mode 100644
index 17e86b6d7e8..00000000000
--- a/doc/user/project/container_registry.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../packages/container_registry/index.md'
----
-
-This document was moved to [another location](../packages/container_registry/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/cycle_analytics.md b/doc/user/project/cycle_analytics.md
deleted file mode 100644
index 5c235f6708b..00000000000
--- a/doc/user/project/cycle_analytics.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../analytics/value_stream_analytics.md'
----
-
-This document was moved to [another location](../analytics/value_stream_analytics.md)
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 831a8803622..72695580d9d 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -5,10 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto, reference
---
-# Deploy Boards **(CORE)**
+# Deploy Boards **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
-> - [Moved](<https://gitlab.com/gitlab-org/gitlab/-/issues/212320>) to GitLab Core in 13.8.
+> - [Moved](<https://gitlab.com/gitlab-org/gitlab/-/issues/212320>) to GitLab Free in 13.8.
GitLab Deploy Boards offer a consolidated view of the current health and
status of each CI [environment](../../ci/environments/index.md) running on [Kubernetes](https://kubernetes.io), displaying the status
@@ -93,7 +93,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
`$CI_PROJECT_PATH_SLUG` are the values of the CI variables. This is so we can
lookup the proper environment in a cluster/namespace which may have more
than one. These resources should be contained in the namespace defined in
- the Kubernetes service setting. You can use an [Autodeploy](../../topics/autodevops/stages.md#auto-deploy) `.gitlab-ci.yml`
+ the Kubernetes service setting. You can use an [Auto deploy](../../topics/autodevops/stages.md#auto-deploy) `.gitlab-ci.yml`
template which has predefined stages and commands to use, and automatically
applies the annotations. Each project must have a unique namespace in
Kubernetes as well. The image below demonstrates how this is shown inside
@@ -158,7 +158,7 @@ version of your application.
## Further reading
-- [GitLab Autodeploy](../../topics/autodevops/stages.md#auto-deploy)
+- [GitLab Auto deploy](../../topics/autodevops/stages.md#auto-deploy)
- [GitLab CI/CD environment variables](../../ci/variables/README.md)
- [Environments and deployments](../../ci/environments/index.md)
- [Kubernetes deploy example](https://gitlab.com/gitlab-examples/kubernetes-deploy)
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index 93ed1030e1f..a45c3d26f1a 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -5,12 +5,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto, reference
---
-# Deploy Keys
+# Deploy keys
-Deploy keys allow read-only or read-write (if enabled) access to one or
-more repositories, by importing an SSH public key to your GitLab instance.
+Deploy keys allow read-only or read-write access to your
+repositories by importing an SSH public key into your GitLab instance.
-This is useful for cloning repositories to your Continuous
+This is useful, for example, for cloning repositories to your Continuous
Integration (CI) server. By using deploy keys, you don't have to set up a
fake user account.
@@ -21,7 +21,7 @@ There are two types of deploy keys:
## Key details on deploy keys
-Deploy Keys allow a remote machine (VM, physical, and so on) to access a GitLab
+Deploy keys allow a remote machine (VM, physical, and so on) to access a GitLab
repository with just a few steps. If you want a remote machine to interact with a GitLab
repository in automation, it's a simple solution.
@@ -35,7 +35,7 @@ If this security implication is a concern for your organization,
[Deploy Tokens](../deploy_tokens/index.md) works as an alternative, but with more
security control.
-## Deploy Keys Permissions
+## Deploy keys permissions
You can choose the access level of a deploy key when you enable it on a project:
@@ -72,7 +72,7 @@ help you access a repository, but there are some notables differences between th
on it, but this [is possible with deploy tokens](../deploy_tokens/index.md#gitlab-deploy-token).
- You need an SSH key pair to use deploy keys, but not deploy tokens.
-## How to enable Deploy Keys
+## How to enable deploy keys
### Project deploy keys
@@ -80,17 +80,17 @@ help you access a repository, but there are some notables differences between th
can add or enable a deploy key for a project repository:
1. Navigate to the project's **Settings > Repository** page.
-1. Expand the **Deploy Keys** section.
+1. Expand the **Deploy keys** section.
1. Specify a title for the new deploy key and paste your public SSH key.
-1. (Optional) Check **Write access allowed** to allow `read-write` access. Leave it unchecked for `read-only` access.
+1. (Optional) Check **Grant write permissions to this key** to allow `read-write` access. Leave it unchecked for `read-only` access.
-There are three lists of Project Deploy Keys:
+There are three lists of project deploy keys:
- Enabled deploy keys
- Privately accessible deploy keys
- Public accessible deploy keys
-![Deploy Keys section](img/deploy_keys_v13_0.png)
+![Deploy keys section](img/deploy_keys_v13_0.png)
After you add a key, it's enabled for this project by default and it appears
in the **Enabled deploy keys** tab.
@@ -129,7 +129,7 @@ Instance administrators can add public deploy keys:
if the key gives access to a SaaS CI/CD instance, use the name of that service
in the key name if that is all the key is used for.
-![Public Deploy Keys section](img/public_deploy_key_v13_0.png)
+![Public deploy keys section](img/public_deploy_key_v13_0.png)
After adding a key, it's available to any shared systems. Project maintainers
or higher can [authorize a public deploy key](#project-deploy-keys) to start using it with the project.
@@ -153,7 +153,7 @@ until a project maintainer chooses to make use of it.
## Troubleshooting
-### Deploy Key cannot push to a protected branch
+### Deploy key cannot push to a protected branch
If the owner of this deploy key doesn't have access to a [protected
branch](../protected_branches.md), then this deploy key doesn't have access to
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 5a62730d989..6f05c40eefc 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -67,7 +67,7 @@ following table along with GitLab version it was introduced in:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29639) in GitLab 12.1.
-The default username format is `gitlab+deploy-token-#{n}`. Some tools or
+The default username format is `gitlab+deploy-token-{n}`. Some tools or
platforms may not support this format; in this case you can specify a custom
username to be used when creating the deploy token.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 3108bdda7a0..c56470ee07a 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -6,16 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Description templates
->[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4981) in GitLab 8.11.
-
We all know that a properly submitted issue is more likely to be addressed in
a timely manner by the developers of a project.
-Description templates allow you to define context-specific templates for issue
-and merge request description fields for your project, as well as help filter
-out a lot of unnecessary noise from issues.
-
-## Overview
+With description templates, you can define context-specific templates for issue and merge request
+description fields for your project, and filter out unnecessary noise from issues.
By using the description templates, users that create a new issue or merge
request can select a description template to help them communicate with other
@@ -28,7 +23,10 @@ Description templates must be written in [Markdown](../markdown.md) and stored
in your project's repository under a directory named `.gitlab`. Only the
templates of the default branch are taken into account.
-## Use-cases
+To learn how to create templates for various file types in groups, visit
+[Group file templates](../group/index.md#group-file-templates).
+
+## Use cases
- Add a template to be used in every issue for a specific project,
giving instructions and guidelines, requiring for information specific to that subject.
@@ -39,6 +37,8 @@ templates of the default branch are taken into account.
images guidelines, link to the related issue, reviewer name, and so on.
- You can also create issues and merge request templates for different
stages of your workflow, for example, feature proposal, feature improvement, or a bug report.
+- You can use an [issue description template](#creating-issue-templates) as a
+ [Service Desk email template](service_desk.md#new-service-desk-issues).
## Creating issue templates
@@ -47,20 +47,20 @@ directory in your repository. Commit and push to your default branch.
To create a Markdown file:
- 1. Click the `+` button next to `master` and click **New file**.
- 1. Add the name of your issue template to the **File name** text field next to `master`.
- Make sure that your file has the `.md` extension, for
- example `feature_request.md` or `Feature Request.md`.
- 1. Commit and push to your default branch.
+1. Click the `+` button next to `master` and click **New file**.
+1. Add the name of your issue template to the **File name** text field next to `master`.
+ Make sure that your file has the `.md` extension, for
+ example `feature_request.md` or `Feature Request.md`.
+1. Commit and push to your default branch.
If you don't have a `.gitlab/issue_templates` directory in your repository, you need to create it.
To create the `.gitlab/issue_templates` directory:
- 1. Click the `+` button next to `master` and select **New directory**.
- 1. Name this new directory `.gitlab` and commit to your default branch.
- 1. Click the `+` button next to `master` again and select **New directory**.This time, n
- 1. Name your directory `issue_templates` and commit to your default branch.
+1. Click the `+` button next to `master` and select **New directory**.
+1. Name this new directory `.gitlab` and commit to your default branch.
+1. Click the `+` button next to `master` again and select **New directory**.
+1. Name your directory `issue_templates` and commit to your default branch.
To check if this has worked correctly, [create a new issue](issues/managing_issues.md#create-a-new-issue)
and see if you can choose a description template.
@@ -80,17 +80,16 @@ to the issue description field. The **Reset template** button discards any
changes you made after picking the template and returns it to its initial status.
NOTE:
-You can create short-cut links to create an issue using a designated template. For example: `https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal`.
+You can create shortcut links to create an issue using a designated template.
+For example: `https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal`.
![Description templates](img/description_templates.png)
-## Setting a default template for merge requests and issues **(STARTER)**
+## Setting a default template for merge requests and issues **(PREMIUM)**
-> - This feature was introduced before [description templates](#overview) and is available in [GitLab Starter](https://about.gitlab.com/pricing/). It can be enabled in the project's settings.
-> - Templates for issues were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28) in GitLab EE 8.1.
-> - Templates for merge requests were [introduced](https://gitlab.com/gitlab-org/gitlab/commit/7478ece8b48e80782b5465b96c79f85cc91d391b) in GitLab EE 6.9.
+> - Moved to GitLab Premium in 13.9.
-The visibility of issues and/or merge requests should be set to either "Everyone
+The visibility of issues or merge requests should be set to either "Everyone
with access" or "Only Project Members" in your project's **Settings / Visibility, project features, permissions** section, otherwise the
template text areas don't show. This is the default behavior, so in most cases
you should be fine.
@@ -113,52 +112,46 @@ pre-filled with the text you entered in the template(s).
## Description template example
-We make use of Description Templates for Issues and Merge Requests within the GitLab Community
-Edition project. Please refer to the [`.gitlab` folder](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab)
-for some examples.
+We make use of description templates for issues and merge requests in the GitLab project.
+For some examples, refer to the [`.gitlab` folder](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab).
NOTE:
-It's possible to use [quick actions](quick_actions.md) within description templates to quickly add
+It's possible to use [quick actions](quick_actions.md) in description templates to quickly add
labels, assignees, and milestones. The quick actions are only executed if the user submitting
the issue or merge request has the permissions to perform the relevant actions.
Here is an example of a Bug report template:
-```plaintext
-Summary
+```markdown
+## Summary
(Summarize the bug encountered concisely)
-
-Steps to reproduce
+## Steps to reproduce
(How one can reproduce the issue - this is very important)
+## Example Project
-Example Project
-
-(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
+(If possible, please create an example project here on GitLab.com that exhibits the problematic
+behavior, and link to it here in the bug report.
+If you are using an older version of GitLab, this will also determine whether the bug has been fixed
+in a more recent version)
-(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
-
-
-What is the current bug behavior?
+## What is the current bug behavior?
(What actually happens)
-
-What is the expected correct behavior?
+## What is the expected correct behavior?
(What you should see instead)
+## Relevant logs and/or screenshots
-Relevant logs and/or screenshots
-
-(Paste any relevant logs - please use code blocks (```) to format console output,
-logs, and code as it's very hard to read otherwise.)
-
+(Paste any relevant logs - please use code blocks (```) to format console output, logs, and code, as
+it's very hard to read otherwise.)
-Possible fixes
+## Possible fixes
(If you can, link to the line of code that might be responsible for the problem)
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index 49918b8f023..5c24ec6caf6 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# File Locking **(CORE)**
+# File Locking **(FREE)**
Preventing wasted work caused by unresolvable merge conflicts requires
a different way of working. This means explicitly requesting write permissions,
@@ -26,7 +26,7 @@ GitLab supports two different modes of file locking:
- [Exclusive file locks](#exclusive-file-locks) for binary files: done **through
the command line** with Git LFS and `.gitattributes`, it prevents locked
- files from being modified on any branch. **(CORE)**
+ files from being modified on any branch. **(FREE)**
- [Default branch locks](#default-branch-file-and-directory-locks): done
**through the GitLab UI**, it prevents locked files and directories being
modified on the default branch. **(PREMIUM)**
@@ -41,7 +41,7 @@ users will be prevented from modifying locked files by pushing, merging,
or any other means, and will be shown an error like: `The path '.gitignore' is
locked by Administrator`.
-## Exclusive file locks
+## Exclusive file locks **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35856) in GitLab 10.5.
@@ -198,7 +198,8 @@ Suggested workflow for shared projects:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in GitLab Enterprise Edition 8.9. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
This process allows you to lock one file at a time through the GitLab UI and
-requires access to [GitLab Premium, GitLab.com Silver](https://about.gitlab.com/pricing/), or higher tiers.
+requires access to [GitLab Premium](https://about.gitlab.com/pricing/)
+or higher tiers.
Default branch file and directory locks only apply to the default branch set in
the project's settings (usually `master`).
diff --git a/doc/user/project/git_attributes.md b/doc/user/project/git_attributes.md
index 459abea455b..2806f6e48d1 100644
--- a/doc/user/project/git_attributes.md
+++ b/doc/user/project/git_attributes.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Git Attributes
+# Git Attributes **(FREE)**
GitLab supports defining custom [Git attributes](https://git-scm.com/docs/gitattributes) such as what
files to treat as binary, and what language to use for syntax highlighting
diff --git a/doc/user/project/gpg_signed_commits/index.md b/doc/user/project/gpg_signed_commits/index.md
deleted file mode 100644
index 206013210a0..00000000000
--- a/doc/user/project/gpg_signed_commits/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../repository/gpg_signed_commits/index.md'
----
-
-This document was moved to [another location](../repository/gpg_signed_commits/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/highlighting.md b/doc/user/project/highlighting.md
index 1d92e32e071..c914c90c923 100644
--- a/doc/user/project/highlighting.md
+++ b/doc/user/project/highlighting.md
@@ -5,24 +5,30 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Syntax Highlighting
+# Syntax Highlighting **(FREE)**
-GitLab provides syntax highlighting on all files through the [Rouge](https://rubygems.org/gems/rouge) Ruby gem. It will try to guess what language to use based on the file extension, which most of the time is sufficient.
+GitLab provides syntax highlighting on all files through the [Rouge](https://rubygems.org/gems/rouge) Ruby gem. It attempts to guess what language to use based on the file extension, which most of the time is sufficient.
NOTE:
The [Web IDE](web_ide/index.md) and [Snippets](../snippets.md) use [Monaco Editor](https://microsoft.github.io/monaco-editor/)
for text editing, which internally uses the [Monarch](https://microsoft.github.io/monaco-editor/monarch.html)
library for syntax highlighting.
-If GitLab is guessing wrong, you can override its choice of language using the `gitlab-language` attribute in `.gitattributes`. For example, if you are working in a Prolog project and using the `.pl` file extension (which would normally be highlighted as Perl), you can add the following to your `.gitattributes` file:
+If GitLab is guessing wrong, you can override its choice of language using the
+`gitlab-language` attribute in `.gitattributes`. For example, if you are working in a
+<!-- vale gitlab.Spelling = NO --> Prolog <!-- vale gitlab.Spelling = YES -->
+project and using the `.pl` file extension (which would normally be highlighted as Perl),
+you can add the following to your `.gitattributes` file:
``` conf
*.pl gitlab-language=prolog
```
-When you check in and push that change, all `*.pl` files in your project will be highlighted as Prolog.
+<!-- vale gitlab.Spelling = NO -->
+When you check in and push that change, all `*.pl` files in your project are highlighted as Prolog.
+<!-- vale gitlab.Spelling = YES -->
-The paths here are simply Git's built-in [`.gitattributes` interface](https://git-scm.com/docs/gitattributes). So, if you were to invent a file format called a `Nicefile` at the root of your project that used Ruby syntax, all you need is:
+The paths here are Git's built-in [`.gitattributes` interface](https://git-scm.com/docs/gitattributes). So, if you were to invent a file format called a `Nicefile` at the root of your project that used Ruby syntax, all you need is:
``` conf
/Nicefile gitlab-language=ruby
@@ -38,7 +44,8 @@ To disable highlighting entirely, use `gitlab-language=text`. Lots more fun shen
/other-file gitlab-language=text?token=Error
```
-Please note that these configurations will only take effect when the `.gitattributes` file is in your default branch (usually `master`).
+Please note that these configurations only take effect when the `.gitattributes`
+file is in your default branch (usually `master`).
NOTE:
The Web IDE does not support `.gitattribute` files, but it's [planned for a future release](https://gitlab.com/gitlab-org/gitlab/-/issues/22014).
diff --git a/doc/user/project/img/optional_code_owners_sections_v13_8.png b/doc/user/project/img/optional_code_owners_sections_v13_8.png
index 7a5a2fab6e3..50916466226 100644
--- a/doc/user/project/img/optional_code_owners_sections_v13_8.png
+++ b/doc/user/project/img/optional_code_owners_sections_v13_8.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_nav_item.png b/doc/user/project/img/service_desk_nav_item.png
deleted file mode 100644
index fdf8fa024c3..00000000000
--- a/doc/user/project/img/service_desk_nav_item.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/cvs.md b/doc/user/project/import/cvs.md
index 82ff889c043..61d4d29aa4d 100644
--- a/doc/user/project/import/cvs.md
+++ b/doc/user/project/import/cvs.md
@@ -62,7 +62,7 @@ Migrating to Git/GitLab will benefit you:
an open source end-to-end software development platform with built-in version
control, issue tracking, code review, CI/CD, and more.
- **Support for many network protocols**. Git supports SSH, HTTP/HTTPS and rsync
- among others, whereas CVS supports only SSH and its own insecure pserver
+ among others, whereas CVS supports only SSH and its own insecure `pserver`
protocol with no user authentication.
## How to migrate
@@ -70,7 +70,7 @@ Migrating to Git/GitLab will benefit you:
Here's a few links to get you started with the migration:
- [Migrate using the `cvs-fast-export` tool](https://gitlab.com/esr/cvs-fast-export)
-- [Stack Overflow post on importing the CVS repo](https://stackoverflow.com/a/11490134/974710)
+- [Stack Overflow post on importing the CVS repository](https://stackoverflow.com/a/11490134/974710)
- [Convert a CVS repository to Git](https://www.techrepublic.com/blog/linux-and-open-source/convert-cvs-repositories-to-git/)
- [Man page of the `git-cvsimport` tool](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-cvsimport.html)
- [Migrate using `reposurgeon`](http://www.catb.org/~esr/reposurgeon/repository-editing.html#conversion)
diff --git a/doc/user/project/import/gemnasium.md b/doc/user/project/import/gemnasium.md
index 38679914a9d..bac10cb0948 100644
--- a/doc/user/project/import/gemnasium.md
+++ b/doc/user/project/import/gemnasium.md
@@ -29,7 +29,8 @@ If you want to continue monitoring your dependencies, see the
## What happened to my account?
Your account has been automatically closed on May 15th, 2018. If you had a paid
-subscription at that time, your card will be refunded on a pro rata temporis basis.
+subscription at that time, your card will be refunded on a
+<!-- vale gitlab.Spelling = NO --> pro rata temporis <!-- vale gitlab.Spelling = YES --> basis.
You may contact `gemnasium@gitlab.com` regarding your closed account.
## Will my account/data be transferred to GitLab Inc.?
@@ -66,15 +67,18 @@ GitHub.com or GitHub Enterprise repository. This will automatically prompt
GitLab CI/CD to run whenever code is pushed to GitHub and post CI/CD results
back to both GitLab and GitHub when completed.
-1. Create a new project, and select "CI/CD for external repo":
+<!-- vale gitlab.Spelling = NO -->
+
+1. Create a new project, and select **CI/CD for external repo**:
![Create new Project](img/gemnasium/create_project_v13_5.png)
+ <!-- vale gitlab.Spelling = YES -->
-1. Use the "GitHub" button to connect your repositories.
+1. Use the **GitHub** button to connect your repositories.
![Connect from GitHub](img/gemnasium/connect_github_v13_5.png)
-1. Select the project(s) to be set up with GitLab CI/CD and chose "Connect".
+1. Select the project(s) to be set up with GitLab CI/CD and choose **Connect**.
![Select projects](img/gemnasium/select_project_v13_5.png)
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 754c3e31799..f6ed53763dd 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -74,3 +74,25 @@ In the event of merging two GitLab instances together (for example, both instanc
refer to the instructions in [Migrating from self-managed GitLab to GitLab.com](#migrating-from-self-managed-gitlab-to-gitlabcom).
Additionally, you can migrate users using the [Users API](../../../api/users.md) with an administrator user.
+
+## Project aliases **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in GitLab Premium 12.1.
+
+When migrating repositories to GitLab and they are being accessed by other systems,
+it's very useful to be able to access them using the same name especially when
+they are a lot. It reduces the risk of changing significant number of Git URLs in
+a large number of systems.
+
+GitLab provides a functionality to help with this. In GitLab, repositories are
+usually accessed with a namespace and project name. It is also possible to access
+them via a project alias. This feature is only available on Git over SSH.
+
+A project alias can be only created via API and only by GitLab administrators.
+Follow the [Project Aliases API documentation](../../../api/project_aliases.md) for
+more details.
+
+After an alias has been created for a project (such as an alias `gitlab` for the
+project `https://gitlab.com/gitlab-org/gitlab`), you can clone the repository
+with the alias (e.g `git clone git@gitlab.com:gitlab.git` instead of
+`git clone git@gitlab.com:gitlab-org/gitlab.git`).
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index 0e8cc159aec..3ff612c51a7 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -9,11 +9,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can import your existing repositories by providing the Git URL:
-1. From your GitLab dashboard click **New project**
-1. Switch to the **Import project** tab
-1. Click on the **Repo by URL** button
-1. Fill in the "Git repository URL" and the remaining project fields
-1. Click **Create project** to begin the import process
-1. Once complete, you will be redirected to your newly created project
+<!-- vale gitlab.Spelling = NO -->
+<!-- vale gitlab.SubstitutionWarning = NO -->
+
+1. From your GitLab dashboard click **New project**.
+1. Switch to the **Import project** tab.
+1. Click on the **Repo by URL** button.
+1. Fill in the "Git repository URL" and the remaining project fields.
+1. Click **Create project** to begin the import process.
+1. Once complete, you will be redirected to your newly created project.
+
+<!-- vale gitlab.Spelling = YES -->
+<!-- vale gitlab.SubstitutionWarning = YES -->
![Import project by repository URL](img/import_projects_from_repo_url.png)
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index 3642d07106c..a816dca59bc 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -30,7 +30,7 @@ There are two approaches to SVN to Git migration:
migration. It creates a writable Git mirror of a local or remote Subversion
repository and that way you can use both Subversion and Git as long as you like.
It requires access to your GitLab server as it talks with the Git repositories
-directly in a filesystem level.
+directly in a file system level.
### SubGit prerequisites
diff --git a/doc/user/project/import/tfs.md b/doc/user/project/import/tfs.md
deleted file mode 100644
index 31f9b200558..00000000000
--- a/doc/user/project/import/tfs.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'tfvc.md'
----
-
-This document was moved to [another location](tfvc.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index e3079c3731d..a8ab1cbbb63 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -5,63 +5,59 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Projects
+# Projects **(FREE)**
-In GitLab, you can create projects for hosting
-your codebase, use it as an issue tracker, collaborate on code, and continuously
-build, test, and deploy your app with built-in GitLab CI/CD.
+In GitLab, you can create projects to host
+your codebase. You can also use projects to track issues, plan work,
+collaborate on code, and continuously build, test, and use
+built-in CI/CD to deploy your app.
-Your projects can be [available](../../public_access/public_access.md)
-publicly, internally, or privately, at your choice. GitLab does not limit
-the number of private projects you create.
+Projects can be available [publicly, internally, or privately](../../public_access/public_access.md).
+GitLab does not limit the number of private projects you can create.
## Project features
-When you create a project in GitLab, you'll have access to a large number of
-[features](https://about.gitlab.com/features/):
+Projects include the following [features](https://about.gitlab.com/features/):
**Repositories:**
-- [Issue tracker](issues/index.md): Discuss implementations with your team within issues
- - [Issue Boards](issue_board.md): Organize and prioritize your workflow
- - [Multiple Issue Boards](issue_board.md#multiple-issue-boards): Allow your teams to create their own workflows (Issue Boards) for the same project
-- [Repositories](repository/index.md): Host your code in a fully
- integrated platform
- - [Branches](repository/branches/index.md): use Git branching strategies to
- collaborate on code
+- [Issue tracker](issues/index.md): Discuss implementations with your team.
+ - [Issue Boards](issue_board.md): Organize and prioritize your workflow.
+ - [Multiple Issue Boards](issue_board.md#multiple-issue-boards): Create team-specific workflows (Issue Boards) for a project.
+- [Repositories](repository/index.md): Host your code in a fully-integrated platform.
+ - [Branches](repository/branches/index.md): Use Git branching strategies to
+ collaborate on code.
- [Protected branches](protected_branches.md): Prevent collaborators
- from messing with history or pushing code without review
- - [Protected tags](protected_tags.md): Control over who has
- permission to create tags, and prevent accidental update or deletion
+ from changing history or pushing code without review.
+ - [Protected tags](protected_tags.md): Control who has
+ permission to create tags and prevent accidental updates or deletions.
- [Repository mirroring](repository/repository_mirroring.md)
- - [Signing commits](repository/gpg_signed_commits/index.md): use GPG to sign your commits
- - [Deploy tokens](deploy_tokens/index.md): Manage project-based deploy tokens that allow permanent access to the repository and Container Registry.
+ - [Signing commits](repository/gpg_signed_commits/index.md): Use GNU Privacy Guard (GPG) to sign your commits.
+ - [Deploy tokens](deploy_tokens/index.md): Manage access to the repository and Container Registry.
- [Web IDE](web_ide/index.md)
- [CVE ID Requests](../application_security/cve_id_request.md): Request a CVE identifier to track a
vulnerability in your project.
**Issues and merge requests:**
-- [Issue tracker](issues/index.md): Discuss implementations with your team within issues
- - [Issue Boards](issue_board.md): Organize and prioritize your workflow
- - [Multiple Issue Boards](issue_board.md#multiple-issue-boards): Allow your teams to create their own workflows (Issue Boards) for the same project
-- [Merge Requests](merge_requests/index.md): Apply your branching
- strategy and get reviewed by your team
+- [Issue tracker](issues/index.md): Discuss implementations with your team.
+ - [Issue Boards](issue_board.md): Organize and prioritize your workflow.
+ - [Multiple Issue Boards](issue_board.md#multiple-issue-boards): Create team-specific workflows (Issue Boards) for a project.
+- [Merge Requests](merge_requests/index.md): Apply a branching
+ strategy and get reviewed by your team.
- [Merge Request Approvals](merge_requests/merge_request_approvals.md): Ask for approval before
- implementing a change **(STARTER)**
- - [Fix merge conflicts from the UI](merge_requests/resolve_conflicts.md):
- Your Git diff tool right from the GitLab UI
- - [Review Apps](../../ci/review_apps/index.md): Live preview the results
- of the changes proposed in a merge request in a per-branch basis
-- [Labels](labels.md): Organize issues and merge requests by labels
-- [Time Tracking](time_tracking.md): Track estimate time
- and time spent on
- the conclusion of an issue or merge request
-- [Milestones](milestones/index.md): Work towards a target date
+ implementing a change.
+ - [Fix merge conflicts from the UI](merge_requests/resolve_conflicts.md): View Git diffs from the GitLab UI.
+ - [Review Apps](../../ci/review_apps/index.md): By branch, preview the results
+ of the changes proposed in a merge request.
+- [Labels](labels.md): Organize issues and merge requests by labels.
+- [Time Tracking](time_tracking.md): Track time estimated and
+ spent on issues and merge requests.
+- [Milestones](milestones/index.md): Work toward a target date.
- [Description templates](description_templates.md): Define context-specific
- templates for issue and merge request description fields for your project
-- [Slash commands (quick actions)](quick_actions.md): Textual shortcuts for
- common actions on issues or merge requests
+ templates for issue and merge request description fields.
+- [Slash commands (quick actions)](quick_actions.md): Create text shortcuts for
+ common actions.
- [Autocomplete characters](autocomplete_characters.md): Autocomplete
references to users, groups, issues, merge requests, and other GitLab
elements.
@@ -69,109 +65,55 @@ When you create a project in GitLab, you'll have access to a large number of
**GitLab CI/CD:**
-- [GitLab CI/CD](../../ci/README.md): the GitLab built-in [Continuous Integration, Delivery, and Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) tool
+- [GitLab CI/CD](../../ci/README.md): Use the built-in [Continuous Integration, Delivery, and Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) tool.
- [Container Registry](../packages/container_registry/index.md): Build and push Docker
- images out-of-the-box
+ images.
- [Auto Deploy](../../topics/autodevops/stages.md#auto-deploy): Configure GitLab CI/CD
- to automatically set up your app's deployment
+ to automatically set up your app's deployment.
- [Enable and disable GitLab CI/CD](../../ci/enable_or_disable_ci.md)
- [Pipelines](../../ci/pipelines/index.md): Configure and visualize
- your GitLab CI/CD pipelines from the UI
+ your GitLab CI/CD pipelines from the UI.
- [Scheduled Pipelines](../../ci/pipelines/schedules.md): Schedule a pipeline
- to start at a chosen time
+ to start at a chosen time.
- [Pipeline Graphs](../../ci/pipelines/index.md#visualize-pipelines): View your
- entire pipeline from the UI
+ pipeline from the UI.
- [Job artifacts](../../ci/pipelines/job_artifacts.md): Define,
- browse, and download job artifacts
- - [Pipeline settings](../../ci/pipelines/settings.md): Set up Git strategy (choose the default way your repository is fetched from GitLab in a job),
- timeout (defines the maximum amount of time in minutes that a job is able run), custom path for `.gitlab-ci.yml`, test coverage parsing, pipeline's visibility, and much more
- - [Kubernetes cluster integration](clusters/index.md): Connecting your GitLab project
- with a Kubernetes cluster
- - [Feature Flags](../../operations/feature_flags.md): Feature flags allow you to ship a project in
- different flavors by dynamically toggling certain functionality **(PREMIUM)**
+ browse, and download job artifacts.
+ - [Pipeline settings](../../ci/pipelines/settings.md): Set up Git strategy (how jobs fetch your repository),
+ timeout (the maximum amount of time a job can run), custom path for `.gitlab-ci.yml`, test coverage parsing, pipeline visibility, and more.
+ - [Kubernetes cluster integration](clusters/index.md): Connect your GitLab project
+ with a Kubernetes cluster.
+ - [Feature Flags](../../operations/feature_flags.md): Ship different features
+ by dynamically toggling functionality. **(PREMIUM)**
- [GitLab Pages](pages/index.md): Build, test, and deploy your static
- website with GitLab Pages
+ website.
**Other features:**
-- [Wiki](wiki/index.md): document your GitLab project in an integrated Wiki.
-- [Snippets](../snippets.md): store, share and collaborate on code snippets.
-- [Value Stream Analytics](../analytics/value_stream_analytics.md): review your development lifecycle.
-- [Insights](insights/index.md): configure the Insights that matter for your projects. **(ULTIMATE)**
-- [Security Dashboard](../application_security/security_dashboard/index.md): Security Dashboard. **(ULTIMATE)**
-- [Syntax highlighting](highlighting.md): an alternative to customize
- your code blocks, overriding the GitLab default choice of language.
-- [Badges](badges.md): badges for the project overview.
-- [Releases](releases/index.md): a way to track deliverables in your project as snapshot in time of
- the source, build output, other metadata, and other artifacts
+- [Wiki](wiki/index.md): Document your GitLab project in an integrated Wiki.
+- [Snippets](../snippets.md): Store, share and collaborate on code snippets.
+- [Value Stream Analytics](../analytics/value_stream_analytics.md): Review your development lifecycle.
+- [Insights](insights/index.md): Configure the insights that matter for your projects. **(ULTIMATE)**
+- [Security Dashboard](../application_security/security_dashboard/index.md) **(ULTIMATE)**
+- [Syntax highlighting](highlighting.md): Customize
+ your code blocks, overriding the default language choice.
+- [Badges](badges.md): Add an image to the project overview.
+- [Releases](releases/index.md): Take a snapshot of
+ the source, build output, metadata, and artifacts
associated with a released version of your code.
-- [Conan packages](../packages/conan_repository/index.md): your private Conan repository in GitLab.
-- [Maven packages](../packages/maven_repository/index.md): your private Maven repository in GitLab.
-- [NPM packages](../packages/npm_registry/index.md): your private NPM package registry in GitLab.
-- [Code owners](code_owners.md): specify code owners for certain files **(STARTER)**
-- [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): Requirements allow you to create criteria to check your products against. **(ULTIMATE)**
-- [Static Site Editor](static_site_editor/index.md): quickly edit content on static websites without prior knowledge of the codebase or Git commands.
-- [Code Intelligence](code_intelligence.md): code navigation features.
+- [Package Registry](../packages/package_registry/index.md): Publish and install packages.
+- [Code owners](code_owners.md): Specify code owners for specific files.
+- [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
+## Project integrations
[Integrate your project](integrations/index.md) with Jira, Mattermost,
Kubernetes, Slack, and a lot more.
-## New project
-
-Learn how to [create a new project](../../gitlab-basics/create-project.md) in GitLab.
-
-### Fork a project
-
-You can [fork a project](repository/forking_workflow.md) in order to:
-
-- Collaborate on code by forking a project and creating a merge request
- from your fork to the upstream project
-- Fork a sample project to work on the top of that
-
-### Star a project
-
-You can star a project to make it easier to find projects you frequently use.
-The number of stars a project has can indicate its popularity.
-
-To star a project:
-
-1. Go to the home page of the project you want to star.
-1. In the upper right corner of the page, click **Star**.
-
-To view your starred projects:
-
-1. Click **Projects** in the navigation bar.
-1. Click **Starred Projects**.
-1. GitLab displays information about your starred projects, including:
-
- - Project description, including name, description, and icon
- - Number of times this project has been starred
- - Number of times this project has been forked
- - Number of open merge requests
- - Number of open issues
-
-### Explore projects
-
-You can explore other popular projects available on GitLab. To explore projects:
-
-1. Click **Projects** in the navigation bar.
-1. Click **Explore Projects**.
-
-GitLab displays a list of projects, sorted by last updated date. To view
-projects with the most [stars](#star-a-project), click **Most stars**. To view
-projects with the largest number of comments in the past month, click **Trending**.
-
-## Project settings
-
-Set the project's visibility level and the access levels to its various pages
-and perform actions like archiving, renaming or transferring a project.
-
-Read through the documentation on [project settings](settings/index.md).
-
## Import or export a project
- [Import a project](import/index.md) from:
@@ -182,64 +124,6 @@ Read through the documentation on [project settings](settings/index.md).
- [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data)
- [Importing and exporting projects between GitLab instances](settings/import_export.md)
-## Delete a project
-
-To delete a project, first navigate to the home page for that project.
-
-1. Navigate to **Settings > General**.
-1. Expand the **Advanced** section.
-1. Scroll down to the **Delete project** section.
-1. Click **Delete project**
-1. Confirm this action by typing in the expected text.
-
-Projects in personal namespaces are deleted immediately on request. For information on delayed deletion of projects within a group, please see [Enabling delayed project removal](../group/index.md#enabling-delayed-project-removal).
-
-## CI/CD for external repositories **(PREMIUM)**
-
-Instead of importing a repository directly to GitLab, you can connect your repository
-as a CI/CD project.
-
-Read through the documentation on [CI/CD for external repositories](../../ci/ci_cd_for_external_repos/index.md).
-
-## Project members
-
-Learn how to [add members to your projects](members/index.md).
-
-## Project activity
-
-To view the activity of a project, navigate to **Project overview > Activity**.
-From there, you can click on the tabs to see **All** the activity, or see it
-filtered by **Push events**, **Merge events**, **Issue events**, **Comments**,
-**Team**, and **Wiki**.
-
-### Leave a project
-
-**Leave project** will only display on the project's dashboard
-when a project is part of a group (under a
-[group namespace](../group/index.md#namespaces)).
-If you choose to leave a project you will no longer be a project
-member, therefore, unable to contribute.
-
-## Project's landing page
-
-The project's landing page shows different information depending on
-the project's visibility settings and user permissions.
-
-For public projects, and to members of internal and private projects
-with [permissions to view the project's code](../permissions.md#project-members-permissions):
-
-- The content of a
- [`README` or an index file](repository/#repository-readme-and-index-files)
- is displayed (if any), followed by the list of directories within the
- project's repository.
-- If the project doesn't contain either of these files, the
- visitor will see the list of files and directories of the repository.
-
-For users without permissions to view the project's code:
-
-- The wiki homepage is displayed, if any.
-- The list of issues within the project is displayed.
-
## GitLab Workflow - VS Code extension
To avoid switching from the GitLab UI and VS Code while working in GitLab repositories, you can integrate
@@ -248,142 +132,6 @@ the [VS Code](https://code.visualstudio.com/) editor with GitLab through the
To review or contribute to the extension's code, visit [its codebase in GitLab](https://gitlab.com/gitlab-org/gitlab-vscode-extension/).
-## Redirects when changing repository paths
-
-When a repository path changes, it is essential to smoothly transition from the
-old location to the new one. GitLab provides two kinds of redirects: the web UI
-and Git push/pull redirects.
-
-Depending on the situation, different things apply.
-
-When [renaming a user](../profile/index.md#changing-your-username),
-[changing a group path](../group/index.md#changing-a-groups-path) or [renaming a repository](settings/index.md#renaming-a-repository):
-
-- Existing web URLs for the namespace and anything under it (e.g., projects) will
- redirect to the new URLs.
-- Starting with GitLab 10.3, existing Git remote URLs for projects under the
- namespace will redirect to the new remote URL. Every time you push/pull to a
- repository that has changed its location, a warning message to update
- your remote will be displayed instead of rejecting your action.
- This means that any automation scripts, or Git clients will continue to
- work after a rename, making any transition a lot smoother.
-- The redirects will be available as long as the original path is not claimed by
- another group, user or project.
-
-## Use your project as a Go package
-
-Any project can be used as a Go package. GitLab responds correctly to `go get`
-and `godoc.org` discovery requests, including the
-[`go-import`](https://golang.org/cmd/go/#hdr-Remote_import_paths) and
-[`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links) meta tags.
-
-Private projects, including projects in subgroups, can be used as a Go package,
-but may require configuration to work correctly. GitLab will respond correctly
-to `go get` discovery requests for projects that *are not* in subgroups,
-regardless of authentication or authorization.
-[Authentication](#authenticate-go-requests) is required to use a private project
-in a subgroup as a Go package. Otherwise, GitLab will truncate the path for
-private projects in subgroups to the first two segments, causing `go get` to
-fail.
-
-GitLab implements its own Go proxy. This feature must be enabled by an
-administrator and requires additional configuration. See [GitLab Go
-Proxy](../packages/go_proxy/index.md).
-
-### Disable Go module features for private projects
-
-In Go 1.12 and later, Go queries module proxies and checksum databases in the
-process of [fetching a
-module](../../development/go_guide/dependencies.md#fetching). This can be
-selectively disabled with `GOPRIVATE` (disable both),
-[`GONOPROXY`](../../development/go_guide/dependencies.md#proxies) (disable proxy
-queries), and [`GONOSUMDB`](../../development/go_guide/dependencies.md#fetching)
-(disable checksum queries).
-
-`GOPRIVATE`, `GONOPROXY`, and `GONOSUMDB` are comma-separated lists of Go
-modules and Go module prefixes. For example,
-`GOPRIVATE=gitlab.example.com/my/private/project` will disable queries for that
-one project, but `GOPRIVATE=gitlab.example.com` will disable queries for *all*
-projects on GitLab.com. Go will not query module proxies if the module name or a
-prefix of it appears in `GOPRIVATE` or `GONOPROXY`. Go will not query checksum
-databases if the module name or a prefix of it appears in `GONOPRIVATE` or
-`GONOSUMDB`.
-
-### Authenticate Go requests
-
-To authenticate requests to private projects made by Go, use a [`.netrc`
-file](https://ec.haxx.se/usingcurl-netrc.html) and a [personal access
-token](../profile/personal_access_tokens.md) in the password field. **This only
-works if your GitLab instance can be accessed with HTTPS.** The `go` command
-will not transmit credentials over insecure connections. This will authenticate
-all HTTPS requests made directly by Go but will not authenticate requests made
-through Git.
-
-For example:
-
-```plaintext
-machine gitlab.example.com
-login <gitlab_user_name>
-password <personal_access_token>
-```
-
-NOTE:
-On Windows, Go reads `~/_netrc` instead of `~/.netrc`.
-
-### Authenticate Git fetches
-
-If a module cannot be fetched from a proxy, Go will fall back to using Git (for
-GitLab projects). Git will use `.netrc` to authenticate requests. Alternatively,
-Git can be configured to embed specific credentials in the request URL, or to
-use SSH instead of HTTPS (as Go always uses HTTPS to fetch Git repositories):
-
-```shell
-# embed credentials in any request to GitLab.com:
-git config --global url."https://${user}:${personal_access_token}@gitlab.example.com".insteadOf "https://gitlab.example.com"
-
-# use SSH instead of HTTPS:
-git config --global url."git@gitlab.example.com".insteadOf "https://gitlab.example.com"
-```
-
-## Access project page with project ID
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53671) in GitLab 11.8.
-
-To quickly access a project from the GitLab UI using the project ID,
-visit the `/projects/:id` URL in your browser or other tool accessing the project.
-
-## Project aliases **(PREMIUM ONLY)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1.
-
-When migrating repositories to GitLab and they are being accessed by other systems,
-it's very useful to be able to access them using the same name especially when
-they are a lot. It reduces the risk of changing significant number of Git URLs in
-a large number of systems.
-
-GitLab provides a functionality to help with this. In GitLab, repositories are
-usually accessed with a namespace and project name. It is also possible to access
-them via a project alias. This feature is only available on Git over SSH.
-
-A project alias can be only created via API and only by GitLab administrators.
-Follow the [Project Aliases API documentation](../../api/project_aliases.md) for
-more details.
-
-Once an alias has been created for a project (e.g., an alias `gitlab` for the
-project `https://gitlab.com/gitlab-org/gitlab`), the repository can be cloned
-using the alias (e.g `git clone git@gitlab.com:gitlab.git` instead of
-`git clone git@gitlab.com:gitlab-org/gitlab.git`).
-
-## Project activity analytics overview **(ULTIMATE ONLY)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab [Ultimate](https://about.gitlab.com/pricing/) 13.7 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
-
-Project details include the following analytics:
-
-- Deployment Frequency
-
-For more information, see [Project Analytics API](../../api/project_analytics.md).
-
## Project APIs
There are numerous [APIs](../../api/README.md) to use with your projects:
@@ -404,4 +152,14 @@ There are numerous [APIs](../../api/README.md) to use with your projects:
- [Traffic](../../api/project_statistics.md)
- [Variables](../../api/project_level_variables.md)
- [Aliases](../../api/project_aliases.md)
-- [Analytics](../../api/project_analytics.md)
+- [DORA4 Analytics](../../api/dora4_project_analytics.md)
+
+## DORA4 analytics overview **(ULTIMATE ONLY)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab [Ultimate](https://about.gitlab.com/pricing/) 13.7 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta).
+
+Project details include the following analytics:
+
+- Deployment Frequency
+
+For more information, see [DORA4 Project Analytics API](../../api/dora4_project_analytics.md).
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
index 30a21dd7f66..fb9314f7504 100644
--- a/doc/user/project/integrations/bamboo.md
+++ b/doc/user/project/integrations/bamboo.md
@@ -50,7 +50,7 @@ service in GitLab.
1. Enter the build key from your Bamboo build plan. Build keys are typically made
up from the Project Key and Plan Key that are set on project/plan creation and
separated with a dash (`-`), for example **PROJ-PLAN**. This is a short, all
- uppercase identifier that is unique. When viewing a plan within Bamboo, the
+ uppercase identifier that is unique. When viewing a plan in Bamboo, the
build key is also shown in the browser URL, for example `https://bamboo.example.com/browse/PROJ-PLAN`.
1. If necessary, enter username and password for a Bamboo user that has
access to trigger the build plan. Leave these fields blank if you do not require
@@ -60,8 +60,12 @@ service in GitLab.
## Troubleshooting
+### Builds not triggered
+
If builds are not triggered, ensure you entered the right GitLab IP address in
Bamboo under 'Trigger IP addresses'. Also check [service hook logs](overview.md#troubleshooting-integrations) for request failures.
-NOTE:
-Starting with GitLab 8.14.0, builds are triggered on push events.
+### Advanced Atlassian Bamboo features not available in GitLab UI
+
+Advanced Atlassian Bamboo features are not compatible with GitLab. These features
+include, but are not limited to, the ability to watch the build logs from the GitLab UI.
diff --git a/doc/user/project/integrations/ewm.md b/doc/user/project/integrations/ewm.md
index 434ae760aff..d63599d02bc 100644
--- a/doc/user/project/integrations/ewm.md
+++ b/doc/user/project/integrations/ewm.md
@@ -4,7 +4,7 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# IBM Engineering Workflow Management (EWM) Integration **(CORE)**
+# IBM Engineering Workflow Management (EWM) Integration **(FREE)**
This service allows you to navigate from GitLab to EWM work items mentioned in merge request descriptions and commit messages. Each work item reference is automatically converted to a link back to the work item.
diff --git a/doc/user/project/integrations/generic_alerts.md b/doc/user/project/integrations/generic_alerts.md
deleted file mode 100644
index 1fbbee36173..00000000000
--- a/doc/user/project/integrations/generic_alerts.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/incident_management/generic_alerts.md'
----
-
-This document was moved to [another location](../../../operations/incident_management/generic_alerts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
index ccf4b6cb303..ef8c9d59132 100644
--- a/doc/user/project/integrations/gitlab_slack_application.md
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -4,7 +4,7 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Slack application **(FREE ONLY)**
+# GitLab Slack application **(FREE SAAS)**
> - Introduced in GitLab 9.4.
> - Distributed to Slack App Directory in GitLab 10.2.
diff --git a/doc/user/project/integrations/img/mattermost_configuration.png b/doc/user/project/integrations/img/mattermost_configuration.png
deleted file mode 100644
index 18c0036846d..00000000000
--- a/doc/user/project/integrations/img/mattermost_configuration.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_configuration_v2.png b/doc/user/project/integrations/img/mattermost_configuration_v2.png
new file mode 100644
index 00000000000..0470869c4f7
--- /dev/null
+++ b/doc/user/project/integrations/img/mattermost_configuration_v2.png
Binary files differ
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
index 8dd7e4309b4..58f7ea3279f 100644
--- a/doc/user/project/integrations/irker.md
+++ b/doc/user/project/integrations/irker.md
@@ -10,7 +10,7 @@ GitLab provides a way to push update messages to an Irker server. When
configured, pushes to a project trigger the service to send data directly
to the Irker server.
-See the project homepage for further information: <https://gitlab.com/esr/irker>
+See the [project homepage](https://gitlab.com/esr/irker) for further information.
## Needed setup
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index 306a16bd873..5857c3da803 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -6,57 +6,83 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Jira integration
-If you need to use Jira to track work that's implemented in GitLab, Jira integrations with GitLab make the process of working across systems more efficient.
+You can use Jira to track work implemented in GitLab. The Jira integration with GitLab makes the
+process of working across these systems more efficient.
-This page is about the GitLab Jira integration, which is available in every GitLab project by default, allowing you to connect it to any Jira instance, whether Cloud or self-managed. To compare features with the complementary Jira Development Panel integration, see [Jira integrations](jira_integrations.md).
+The GitLab Jira integration, available in every GitLab project by default, allows you to connect
+to any Jira instance, whether on Atlassian cloud or self-managed.
-After you set up this integration, you can cross-reference activity in the GitLab project with any of your projects in Jira. This includes the ability to close or transition Jira issues when work is completed in GitLab.
+You can also install the [Jira Development Panel integration](../../../integration/jira_development_panel.md).
+For more information about the differences between the two integrations, see
+[Jira integrations](jira_integrations.md).
-Features include:
+After you set up this integration, you can cross-reference activity in the GitLab project with any
+of your projects in Jira. This includes the ability to close or transition Jira issues when work is
+completed in GitLab and:
-- **Mention a Jira issue ID** in a commit message or MR (merge request) and
+- Mention a Jira issue ID in a commit message or MR (merge request) and:
- GitLab links to the Jira issue.
- The Jira issue adds a comment with details and a link back to the activity in GitLab.
-- **Mention that a commit or MR resolves or closes a specific Jira issue** and when it's merged to the default branch:
+- Mention that a commit or MR resolves or closes a specific Jira issue and when it's merged to the default branch:
- The GitLab MR displays a note that it closed the Jira issue. Prior to the merge, MRs indicate which issue they close.
- The Jira issue shows the activity and is closed or otherwise transitioned as specified in your GitLab settings.
-- **View a list of Jira issues directly in GitLab** **(PREMIUM)**
+- Run a pipeline on an MR linked to a Jira issue:
+ - The Jira issue shows the current pipeline status (in the sidebar as "builds").
+- Deploy to an environment from an MR linked to a Jira issue:
+ - The Jira issue shows the status of the deployment (in the sidebar as "deployments").
+- Create or modify a feature flag that mentions a Jira issue in its description:
+ - The Jira issue shows the details of the feature-flag (in the sidebar as "feature flags").
+- View a list of Jira issues directly in GitLab. **(PREMIUM)**
+- Create a Jira issue from a vulnerability. **(ULTIMATE)**
-For additional features, you can install the
-[Jira Development Panel integration](../../../integration/jira_development_panel.md).
-This enables you to:
+Additional features provided by the Jira Development Panel integration include:
- In a Jira issue, display relevant GitLab information in the [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/), including related branches, commits, and merge requests.
- Use Jira [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) in GitLab to add Jira comments, log time spent on the issue, or apply any issue transition.
-
-See the [feature comparison](jira_integrations.md#feature-comparison) for more details.
+- Showing pipeline, deployment, and feature flags in Jira issues.
## Configuration
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Agile Management - GitLab-Jira Basic Integration](https://www.youtube.com/watch?v=fWvwkx5_00E&feature=youtu.be).
-Each GitLab project can be configured to connect to an entire Jira instance. That
-means one GitLab project can interact with _all_ Jira projects in that instance, once
-configured. Therefore, you do not have to explicitly associate
-a GitLab project with any single Jira project.
+Each GitLab project can be configured to connect to an entire Jira instance. That means one GitLab
+project can interact with _all_ Jira projects in that instance, once configured. For:
+
+- The [view Jira issues](#view-jira-issues) feature, you must associate a GitLab project with a
+ specific Jira project.
+- Other features, you do not have to explicitly associate a GitLab project with any single Jira
+ project.
+
+If you have one Jira instance, you can pre-fill the settings. For more information, see the
+documentation for:
+
+- [Project integration management](../../admin_area/settings/project_integration_management.md).
+- [Services Templates](services_templates.md).
+
+To enable the Jira service in GitLab, you must:
-If you have one Jira instance, you can pre-fill the settings page with a default
-template. See the [Services Templates](services_templates.md) docs.
+1. Configure the project in Jira.
+1. Enter the correct values in GitLab.
-In order to enable the Jira service in GitLab, you need to first configure the project in Jira and then enter the correct values in GitLab.
+### Configure Jira
-### Configuring Jira
+The process for configuring Jira depends on whether you host Jira on your own server or on
+[Atlassian cloud](https://www.atlassian.com/cloud).
#### Jira Server
-**Jira Server** supports basic authentication. When connecting, a **username and password** are required. Note that connecting to Jira Server via CAS is not possible. [Set up a user in Jira Server](jira_server_configuration.md) first and then proceed to [Configuring GitLab](#configuring-gitlab).
+Jira Server supports basic authentication. When connecting, a **username and password** are
+required. Connecting to Jira Server via CAS is not possible. For more information, see
+[set up a user in Jira Server](jira_server_configuration.md).
-#### Jira Cloud
+#### Jira on Atlassian cloud
-**Jira Cloud** supports authentication through an API token. When connecting to **Jira Cloud**, an **email and API token** are required. [Set up a user in Jira Cloud](jira_cloud_configuration.md) first and then proceed to [Configuring GitLab](#configuring-gitlab).
+Jira on Atlassian cloud supports authentication through an API token. When connecting to Jira on
+Atlassian cloud, an **email and API token** are required. For more information, see
+[set up a user in Jira on Atlassian cloud](jira_cloud_configuration.md).
-### Configuring GitLab
+### Configure GitLab
> **Notes:**
>
@@ -65,37 +91,52 @@ In order to enable the Jira service in GitLab, you need to first configure the p
> to enable Basic Auth. The cookie being added to each request is `OBBasicAuth` with
> a value of `fromDialog`.
-To enable the Jira integration in a project, navigate to the
-[Integrations page](overview.md#accessing-integrations) and click
-the **Jira** service.
+To enable the Jira integration in a project:
+
+1. Go to the project's [Integrations page](overview.md#accessing-integrations) and select the
+ **Jira** service.
+
+1. Select **Enable integration**.
+
+1. Select **Trigger** actions.
+ This determines whether a mention of a Jira issue in GitLab commits, merge requests, or both,
+ should link the Jira issue back to that source commit/MR and transition the Jira issue, if
+ indicated.
+
+1. To include a comment on the Jira issue when the above reference is made in GitLab, select
+ **Enable comments**.
+
+ 1. Select the **Comment detail**: **Standard** or **All details**.
-Select **Enable integration**.
+1. Enter the further details on the page as described in the following table.
-Select a **Trigger** action. This determines whether a mention of a Jira issue in GitLab commits, merge requests, or both, should link the Jira issue back to that source commit/MR and transition the Jira issue, if indicated.
+ | Field | Description |
+ | ----- | ----------- |
+ | `Web URL` | The base URL to the Jira instance web interface which is being linked to this GitLab project. For example, `https://jira.example.com`. |
+ | `Jira API URL` | The base URL to the Jira instance API. Web URL value is used if not set. For example, `https://jira-api.example.com`. Leave this field blank (or use the same value of `Web URL`) if using **Jira on Atlassian cloud**. |
+ | `Username or Email` | Created in [configure Jira](#configure-jira) step. Use `username` for **Jira Server** or `email` for **Jira on Atlassian cloud**. |
+ | `Password/API token` | Created in [configure Jira](#configure-jira) step. Use `password` for **Jira Server** or `API token` for **Jira on Atlassian cloud**. |
+ | `Jira workflow transition IDs` | Required for closing Jira issues via commits or merge requests. These are the IDs of transitions in Jira that move issues to a particular state. (See [Obtaining a transition ID](#obtaining-a-transition-id).) If you insert multiple transition IDs separated by `,` or `;`, the issue is moved to each state, one after another, using the given order. In GitLab 13.6 and earlier, field was called `Transition ID`. |
-To include a comment on the Jira issue when the above reference is made in GitLab, check **Enable comments**.
+1. To enable users to view Jira issues inside the GitLab project, select **Enable Jira issues** and
+ enter a Jira project key. **(PREMIUM)**
-Enter the further details on the page as described in the following table.
+ You can only display issues from a single Jira project within a given GitLab project.
-| Field | Description |
-| ----- | ----------- |
-| `Web URL` | The base URL to the Jira instance web interface which is being linked to this GitLab project. E.g., `https://jira.example.com`. |
-| `Jira API URL` | The base URL to the Jira instance API. Web URL value is used if not set. For example, `https://jira-api.example.com`. Leave this field blank (or use the same value of `Web URL`) if using **Jira Cloud**. |
-| `Username or Email` | Created in [configuring Jira](#configuring-jira) step. Use `username` for **Jira Server** or `email` for **Jira Cloud**. |
-| `Password/API token` |Created in [configuring Jira](#configuring-jira) step. Use `password` for **Jira Server** or `API token` for **Jira Cloud**. |
-| `Jira workflow transition IDs` | Required for closing Jira issues via commits or merge requests. These are the IDs of transitions in Jira that move issues to a particular state. (See [Obtaining a transition ID](#obtaining-a-transition-id).) If you insert multiple transition IDs separated by `,` or `;`, the issue is moved to each state, one after another, using the given order. In GitLab 13.6 and earlier, field was called `Transition ID`. |
+ WARNING:
+ If you enable Jira issues with the setting above, all users that have access to this GitLab project
+ are able to view all issues from the specified Jira project.
-To enable users to view Jira issues inside the GitLab project, select **Enable Jira issues** and enter a Jira project key. **(PREMIUM)**
+1. To enable creation of issues for vulnerabilities, select **Enable Jira issues creation from vulnerabilities**.
-You can only display issues from a single Jira project within a given GitLab project.
+ 1. Select the **Jira issue type**. If the dropdown is empty, select refresh (**{retry}**) and try again.
-WARNING:
-If you enable Jira issues with the setting above, all users that have access to this GitLab project
-are able to view all issues from the specified Jira project.
+1. To verify the Jira connection is working, select **Test settings**.
-When you have configured all settings, click **Test settings and save changes**.
+1. Select **Save changes**.
-Your GitLab project can now interact with all Jira projects in your instance and the project now displays a Jira link that opens the Jira project.
+Your GitLab project can now interact with all Jira projects in your instance and the project now
+displays a Jira link that opens the Jira project.
#### Obtaining a transition ID
@@ -107,19 +148,19 @@ administration UI. You can get the ID you need in either of the following ways:
1. By mousing over the link for the transition you want and looking for the
"action" parameter in the URL
-Note that the transition ID may vary between workflows (e.g., bug vs. story),
+Note that the transition ID may vary between workflows (for example, bug vs. story),
even if the status you are changing to is the same.
#### Disabling comments on Jira issues
You can continue to have GitLab cross-link a source commit/MR with a Jira issue while disabling the comment added to the issue.
-See the [Configuring GitLab](#configuring-gitlab) section and uncheck the **Enable comments** setting.
+See the [Configure GitLab](#configure-gitlab) section and uncheck the **Enable comments** setting.
## Jira issues
-By now you should have [configured Jira](#configuring-jira) and enabled the
-[Jira service in GitLab](#configuring-gitlab). If everything is set up correctly
+By now you should have [configured Jira](#configure-jira) and enabled the
+[Jira service in GitLab](#configure-gitlab). If everything is set up correctly
you should be able to reference and close Jira issues by just mentioning their
ID in GitLab commits and merge requests.
@@ -201,7 +242,7 @@ with a link to the commit that resolved the issue.
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3622) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-You can browse and search issues from a selected Jira project directly in GitLab. This requires [configuration](#configuring-gitlab) in GitLab by an administrator.
+You can browse and search issues from a selected Jira project directly in GitLab. This requires [configuration](#configure-gitlab) in GitLab by an administrator.
![Jira issues integration enabled](img/jira/open_jira_issues_list_v13.2.png)
diff --git a/doc/user/project/integrations/jira_cloud_configuration.md b/doc/user/project/integrations/jira_cloud_configuration.md
index b8eebef8e42..e9f30f32308 100644
--- a/doc/user/project/integrations/jira_cloud_configuration.md
+++ b/doc/user/project/integrations/jira_cloud_configuration.md
@@ -4,10 +4,10 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Creating an API token in Jira Cloud
+# Create an API token in Jira on Atlassian cloud
-An API token is needed when integrating with Jira Cloud, follow the steps
-below to create one:
+For [integrations with Jira](jira.md), an API token is needed when integrating with Jira
+on Atlassian cloud. To create an API token:
1. Log in to [`id.atlassian.com`](https://id.atlassian.com/manage-profile/security/api-tokens) with your email address.
@@ -17,10 +17,11 @@ below to create one:
1. Click **Create API token**.
-![Jira API token](img/jira_api_token_menu.png)
+ ![Jira API token](img/jira_api_token_menu.png)
-![Jira API token](img/jira_api_token.png)
+1. Click **Copy**, or click **View** and write down the new API token. It is required when [configuring GitLab](jira.md#configure-gitlab).
-1. Click **Copy**, or click **View** and write down the new API token. It is required when [configuring GitLab](jira.md#configuring-gitlab).
+ ![Jira API token](img/jira_api_token.png)
-The Jira configuration is complete. You need the newly created token, and the associated email address, when [configuring GitLab](jira.md#configuring-gitlab) in the next section.
+The Jira configuration is complete. You need the newly created token, and the associated email
+address, when [configuring GitLab](jira.md#configure-gitlab).
diff --git a/doc/user/project/integrations/jira_integrations.md b/doc/user/project/integrations/jira_integrations.md
index 3c91fd3549f..6a1529f001a 100644
--- a/doc/user/project/integrations/jira_integrations.md
+++ b/doc/user/project/integrations/jira_integrations.md
@@ -6,26 +6,46 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Jira integrations
-## Introduction
+GitLab can be integrated with [Jira](https://www.atlassian.com/software/jira).
-GitLab Issues are a tool for discussing ideas and planning and tracking work. However, your organization may already use Jira for these purposes, with
-extensive, established data and business processes they rely on.
+[Issues](../issues/index.md) are a tool for discussing ideas, and planning and tracking work.
+However, your organization may already use Jira for these purposes, with extensive, established data
+and business processes they rely on.
-Although you can [migrate](../../../user/project/import/jira.md) your Jira issues and work exclusively in GitLab, you also have the option of continuing to use Jira by using the GitLab Jira integrations.
+Although you can [migrate](../../../user/project/import/jira.md) your Jira issues and work
+exclusively in GitLab, you can also continue to use Jira by using the GitLab Jira integrations.
-## Integrations
+## Integration types
-The following Jira integrations allow different types of cross-referencing between GitLab activity and Jira issues, with additional features:
+There are two different Jira integrations that allow different types of cross-referencing between
+GitLab activity and Jira issues, with additional features:
-- [**Jira integration**](jira.md) - This is built in to GitLab. In a given GitLab project, it can be configured to connect to any Jira instance, self-managed or Cloud.
-- [**Jira development panel integration**](../../../integration/jira_development_panel.md) - This connects all GitLab projects under a specified group or personal namespace.
- - If you're using Jira Cloud and GitLab.com, install the [GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) app in the Atlassian Marketplace and see its [documentation](../../../integration/jira_development_panel.md#gitlab-for-jira-app).
- - For all other environments, use the [Jira DVCS Connector configuration instructions](../../../integration/jira_development_panel.md#configuration).
+- [Jira integration](jira.md), built in to GitLab. In a given GitLab project, it can be configured
+ to connect to any Jira instance, either hosted by you or hosted in
+ [Atlassian cloud](https://www.atlassian.com/cloud).
+- [Jira development panel integration](../../../integration/jira_development_panel.md). Connects all
+ GitLab projects under a specified group or personal namespace.
-### Feature comparison
+Jira development panel integration configuration depends on whether:
+
+- You're using GitLab.com or a self-managed GitLab instance.
+- You're using Jira on [Atlassian cloud](https://www.atlassian.com/cloud) or on your own server.
+
+| You use Jira on: | For the Jira development panel integration, GitLab.com customers need: | For the Jira development panel integration, GitLab self-managed customers need: |
+|:-------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Atlassian cloud | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See a [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/268278) for more information. |
+| Your own server | The [Jira DVCS connector](../../../integration/jira_development_panel.md). | The [Jira DVCS connector](../../../integration/jira_development_panel.md). |
+
+NOTE:
+DVCS means distributed version control system.
+
+## Feature comparison
+
+The integration to use depends on the capabilities your require. You can install both at the same
+time.
| Capability | Jira integration | Jira Development Panel integration |
-|-----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
+|:----------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
| Mention of Jira issue ID in GitLab is automatically linked to that issue | Yes | No |
| Mention of Jira issue ID in GitLab issue/MR is reflected in the Jira issue | Yes, as a Jira comment with the GitLab issue/MR title and a link back to it. Its first mention also adds the GitLab page to the Jira issue under “Web linksâ€. | Yes, in the issue’s Development panel |
| Mention of Jira issue ID in GitLab commit message is reflected in the issue | Yes. The entire commit message is added to the Jira issue as a comment and under “Web linksâ€, each with a link back to the commit in GitLab. | Yes, in the issue’s Development panel and optionally with a custom comment on the Jira issue using Jira Smart Commits. |
@@ -33,3 +53,4 @@ The following Jira integrations allow different types of cross-referencing betwe
| Record Jira time tracking information against an issue | No | Yes. Time can be specified via Jira Smart Commits. |
| Transition or close a Jira issue with a Git commit or merge request | Yes. Only a single transition type, typically configured to close the issue by setting it to Done. | Yes. Transition to any state using Jira Smart Commits. |
| Display a list of Jira issues | Yes **(PREMIUM)** | No |
+| Create a Jira issue from a vulnerability or finding **(ULTIMATE)** | Yes | No |
diff --git a/doc/user/project/integrations/jira_server_configuration.md b/doc/user/project/integrations/jira_server_configuration.md
index d2a42c0535e..5bb17388a1e 100644
--- a/doc/user/project/integrations/jira_server_configuration.md
+++ b/doc/user/project/integrations/jira_server_configuration.md
@@ -4,61 +4,65 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Creating a username and password for Jira Server
+# Create Jira Server username and password
-We need to create a user in Jira to have access to all projects that need to integrate with GitLab.
+For [integrations with Jira](jira.md), you must create a user account in Jira to have access to
+all projects that need to integrate with GitLab.
-As an example, we create a user named `gitlab` and add it to a new group
-named `gitlab-developers`.
+The Jira user account created for the integration must have write access to
+your Jira projects.
-NOTE:
-It is important that the Jira user created for the integration is given 'write'
-access to your Jira projects. This is covered in the process below.
+As an example, the following process creates a user named `gitlab` and that's a
+member of a new group named `gitlab-developers`:
-1. Log in to your Jira instance as an administrator and under **Jira Administration**
- go to **User Management** to create a new user.
+1. Sign in to your Jira instance as an administrator, and
+ then go to the gear icon and select **User Management**.
![Jira user management link](img/jira_user_management_link.png)
-1. The next step is to create a new user (e.g., `gitlab`) who has write access
- to projects in Jira. Enter the user's name and a _valid_ e-mail address
- since Jira sends a verification e-mail to set up the password.
+1. Create a new user account (for example, `gitlab`) with write access to
+ projects in Jira. Enter the user account's name and a valid e-mail address,
+ because Jira sends a verification email to set up the password.
- Jira creates the username automatically by using the e-mail
- prefix. You can change it later, if needed. Our integration does not support SSO (such as SAML). You
- need to create an HTTP basic authentication password. You can do this by visiting the user
- profile, looking up the username, and setting a password.
+ Jira creates the username by using the email prefix. You can change the
+ username later, if needed. The GitLab integration doesn't support SSO (such
+ as SAML). You need to create an HTTP basic authentication password. You can
+ do this by visiting the user profile, looking up the username, and setting a
+ password.
![Jira create new user](img/jira_create_new_user.png)
-1. Create a `gitlab-developers` group (we give this group write access to Jira
- projects in a later step.) Go to the **Groups** tab on the left, and select **Add group**.
+1. From the sidebar, select **Groups**.
![Jira create new user](img/jira_create_new_group.png)
- Give it a name and click **Add group**.
+1. In the **Add group** section, enter a **Name** for the group (for example,
+ `gitlab-developers`), and then select **Add group**.
-1. Add the `gitlab` user to the `gitlab-developers` group by clicking **Edit members**.
- The `gitlab-developers` group should be listed in the leftmost box as a selected group.
- Under **Add members to selected group(s)**, enter `gitlab`.
+1. Add the `gitlab` user to the `gitlab-developers` group by selecting **Edit members**.
+ The `gitlab-developers` group should be listed in the leftmost box as a
+ selected group. In the **Add members to selected group(s)** area, enter `gitlab`.
![Jira add user to group](img/jira_add_user_to_group.png)
- Click **Add selected users** and `gitlab` should appear in the **Group member(s)** box.
- This membership is saved automatically.
+ Select **Add selected users**, and `gitlab` should appear in the **Group member(s)**
+ area. This membership is saved automatically.
![Jira added user to group](img/jira_added_user_to_group.png)
-1. To give the newly-created group 'write' access, you need to create a **Permission Scheme**.
- To do this, click the gear icon and select **Issues**. Then click **Permission Schemes**.
- Click **Add Permission Scheme** and enter a **Name** and, optionally, a **Description**.
+1. To give the newly-created group 'write' access, you must create a permission
+ scheme. To do this, in the admin menu, go to the gear icon and select **Issues**.
-1. Once your permission scheme is created, you are taken back to the permissions scheme list.
- Locate your new permissions scheme and click **Permissions**. Next to **Administer Projects**,
- click **Edit**. In the resulting dialog box, select **Group** and select `gitlab-developers`
- from the dropdown.
+1. From the sidebar, select **Permission Schemes**.
+
+1. Select **Add Permission Scheme**, enter a **Name** and (optionally) a
+ **Description**, and then select **Add**.
+
+1. In the permissions scheme list, locate your new permissions scheme, and
+ select **Permissions**. Next to **Administer Projects**, select **Edit**. In
+ the **Group** list, select `gitlab-developers`.
![Jira group access](img/jira_group_access.png)
The Jira configuration is complete. Write down the new Jira username and its
-password as they are needed when [configuring GitLab in the next section](jira.md#configuring-gitlab).
+password, as you need them when [configuring GitLab](jira.md#configure-gitlab).
diff --git a/doc/user/project/integrations/kubernetes.md b/doc/user/project/integrations/kubernetes.md
deleted file mode 100644
index 646c9ed66d5..00000000000
--- a/doc/user/project/integrations/kubernetes.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../clusters/index.md'
----
-
-This document was moved to [another location](../clusters/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index e80f672d05d..db190f47b01 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -58,5 +58,7 @@ At the end, fill in your Mattermost details:
| **Webhook** | The incoming webhook URL which you have to set up on Mattermost, similar to: `http://mattermost.example/hooks/5xo…` |
| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
+| **Branches to be notified** | Select which types of branches to send notifications for. |
+| **Labels to be notified** | Optional labels that the issue or merge request must have in order to trigger a notification. Leave blank to get all notifications. |
-![Mattermost configuration](img/mattermost_configuration.png)
+![Mattermost configuration](img/mattermost_configuration_v2.png)
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index c391877be20..b22a7c0295e 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -13,7 +13,7 @@ functionality to GitLab.
## Accessing integrations
You can find the available integrations under your project's
-**Settings âž” Integrations** page.
+**Settings > Integrations** page.
There are more than 20 integrations to integrate with. Click on the one that you
want to configure.
@@ -39,7 +39,7 @@ Click on the service links to see further configuration instructions and details
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | No |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki | No |
| Flowdock | Flowdock is a collaboration web app for technical teams | No |
-| [Generic alerts](../../../operations/incident_management/alert_integrations.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
+| [Generic alerts](../../../operations/incident_management/integrations.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
| [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No |
| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No |
| [HipChat](hipchat.md) | Private group chat and IM | No |
@@ -53,8 +53,8 @@ Click on the service links to see further configuration instructions and details
| Packagist | Update your projects on Packagist, the main Composer repository | Yes |
| Pipelines emails | Email the pipeline status to a list of recipients | No |
| [Slack Notifications](slack.md) | Send GitLab events (for example, an issue was created) to Slack as notifications | No |
-| [Slack slash commands](slack_slash_commands.md) **(CORE ONLY)** | Use slash commands in Slack to control GitLab | No |
-| [GitLab Slack application](gitlab_slack_application.md) **(FREE ONLY)** | Use Slack's official application | No |
+| [Slack slash commands](slack_slash_commands.md) **(FREE SELF)** | Use slash commands in Slack to control GitLab | No |
+| [GitLab Slack application](gitlab_slack_application.md) **(FREE SAAS)** | Use Slack's official application | No |
| PivotalTracker | Project Management Software (Source Commits Endpoint) | No |
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps | No |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | No |
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
deleted file mode 100644
index 69e2ea2856c..00000000000
--- a/doc/user/project/integrations/project_services.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'overview.md'
----
-
-This document was moved to [Integrations](overview.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 1507cea348a..c307fd8d628 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -4,22 +4,25 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Prometheus integration
+# Prometheus integration **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) in GitLab 9.0.
-GitLab offers powerful integration with [Prometheus](https://prometheus.io) for monitoring key metrics of your apps, directly within GitLab.
+GitLab offers powerful integration with [Prometheus](https://prometheus.io) for
+monitoring key metrics of your apps, directly in GitLab.
Metrics for each environment are retrieved from Prometheus, and then displayed
-within the GitLab interface.
+in the GitLab interface.
![Environment Dashboard](img/prometheus_dashboard.png)
There are two ways to set up Prometheus integration, depending on where your apps are running:
- For deployments on Kubernetes, GitLab can automatically [deploy and manage Prometheus](#managed-prometheus-on-kubernetes).
-- For other deployment targets, simply [specify the Prometheus server](#manual-configuration-of-prometheus).
+- For other deployment targets, [specify the Prometheus server](#manual-configuration-of-prometheus).
-Once enabled, GitLab detects metrics from known services in the [metric library](prometheus_library/index.md). You can also [add your own metrics](../../../operations/metrics/index.md#adding-custom-metrics) and create
+Once enabled, GitLab detects metrics from known services in the
+[metric library](prometheus_library/index.md). You can also
+[add your own metrics](../../../operations/metrics/index.md#adding-custom-metrics) and create
[custom dashboards](../../../operations/metrics/dashboards/index.md).
## Enabling Prometheus Integration
@@ -28,7 +31,8 @@ Once enabled, GitLab detects metrics from known services in the [metric library]
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28916) in GitLab 10.5.
-GitLab can seamlessly deploy and manage Prometheus on a [connected Kubernetes cluster](../clusters/index.md), making monitoring of your apps easy.
+GitLab can seamlessly deploy and manage Prometheus on a
+[connected Kubernetes cluster](../clusters/index.md), to help you monitor your apps.
#### Requirements
@@ -36,7 +40,7 @@ GitLab can seamlessly deploy and manage Prometheus on a [connected Kubernetes cl
#### Getting started
-Once you have a connected Kubernetes cluster, deploying a managed Prometheus is as easy as a single click.
+After you have a connected Kubernetes cluster, you can deploy a managed Prometheus with a single click.
1. Go to the **Operations > Kubernetes** page to view your connected clusters
1. Select the cluster you would like to deploy Prometheus to
@@ -46,17 +50,28 @@ Once you have a connected Kubernetes cluster, deploying a managed Prometheus is
#### About managed Prometheus deployments
-Prometheus is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/prometheus). Prometheus is only accessible within the cluster, with GitLab communicating through the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/).
+Prometheus is deployed into the `gitlab-managed-apps` namespace, using the
+[official Helm chart](https://github.com/helm/charts/tree/master/stable/prometheus).
+Prometheus is only accessible in the cluster, with GitLab communicating through the
+[Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/).
-The Prometheus server [automatically detects and monitors](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config) nodes, pods, and endpoints. To configure a resource to be monitored by Prometheus, simply set the following [Kubernetes annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/):
+The Prometheus server
+[automatically detects and monitors](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config)
+nodes, pods, and endpoints. To configure a resource to be monitored by Prometheus,
+set the following [Kubernetes annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/):
- `prometheus.io/scrape` to `true` to enable monitoring of the resource.
- `prometheus.io/port` to define the port of the metrics endpoint.
- `prometheus.io/path` to define the path of the metrics endpoint. Defaults to `/metrics`.
-CPU and Memory consumption is monitored, but requires [naming conventions](prometheus_library/kubernetes.md#specifying-the-environment) in order to determine the environment. If you are using [Auto DevOps](../../../topics/autodevops/index.md), this is handled automatically.
+CPU and Memory consumption is monitored, but requires
+[naming conventions](prometheus_library/kubernetes.md#specifying-the-environment)
+to determine the environment. If you are using
+[Auto DevOps](../../../topics/autodevops/index.md), this is handled automatically.
-The [NGINX Ingress](../clusters/index.md#installing-applications) that is deployed by GitLab to clusters, is automatically annotated for monitoring providing key response metrics: latency, throughput, and error rates.
+The [NGINX Ingress](../clusters/index.md#installing-applications) that is deployed
+by GitLab to clusters, is automatically annotated for monitoring providing key
+response metrics: latency, throughput, and error rates.
##### Example of Kubernetes service annotations and labels
@@ -161,15 +176,16 @@ Installing and configuring Prometheus to monitor applications is fairly straight
1. [Install Prometheus](https://prometheus.io/docs/prometheus/latest/installation/)
1. Set up one of the [supported monitoring targets](prometheus_library/index.md)
-1. Configure the Prometheus server to [collect their metrics](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config)
+1. Configure the Prometheus server to
+ [collect their metrics](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config)
#### Configuration in GitLab
-The actual configuration of Prometheus integration within GitLab
+The actual configuration of Prometheus integration in GitLab
requires the domain name or IP address of the Prometheus server you'd like
to integrate with. If the Prometheus resource is secured with Google's Identity-Aware Proxy (IAP),
-additional information like Client ID and Service Account credentials can be passed which
-GitLab can use to access the resource. More information about authentication from a
+you can pass information like Client ID and Service Account credentials.
+GitLab can use these to access the resource. More information about authentication from a
service account can be found at Google's documentation for
[Authenticating from a service account](https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account).
@@ -191,12 +207,13 @@ service account can be found at Google's documentation for
#### Thanos configuration in GitLab
You can configure [Thanos](https://thanos.io/) as a drop-in replacement for Prometheus
-with GitLab, using the domain name or IP address of the Thanos server you'd like
+with GitLab. Use the domain name or IP address of the Thanos server you'd like
to integrate with.
1. Navigate to the [Integrations page](overview.md#accessing-integrations).
1. Click the **Prometheus** service.
-1. Provide the domain name or IP address of your server, for example `http://thanos.example.com/` or `http://192.0.2.1/`.
+1. Provide the domain name or IP address of your server, for example
+ `http://thanos.example.com/` or `http://192.0.2.1/`.
1. Click **Save changes**.
### Precedence with multiple Prometheus configurations
@@ -223,7 +240,7 @@ can use only one:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10408) in GitLab 9.2.
> - GitLab 9.3 added the [numeric comparison](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/27439) of the 30 minute averages.
-Developers can view the performance impact of their changes within the merge
+Developers can view the performance impact of their changes in the merge
request workflow. This feature requires [Kubernetes](prometheus_library/kubernetes.md) metrics.
When a source branch has been deployed to an environment, a sparkline and
diff --git a/doc/user/project/integrations/prometheus_library/cloudwatch.md b/doc/user/project/integrations/prometheus_library/cloudwatch.md
index b563dd34896..4a88010a343 100644
--- a/doc/user/project/integrations/prometheus_library/cloudwatch.md
+++ b/doc/user/project/integrations/prometheus_library/cloudwatch.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring AWS resources
+# Monitoring AWS resources **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) in GitLab 9.4
diff --git a/doc/user/project/integrations/prometheus_library/haproxy.md b/doc/user/project/integrations/prometheus_library/haproxy.md
index c14c14658b7..290313ac1af 100644
--- a/doc/user/project/integrations/prometheus_library/haproxy.md
+++ b/doc/user/project/integrations/prometheus_library/haproxy.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring HAProxy
+# Monitoring HAProxy **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) in GitLab 9.4
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index 501e8ba7c1d..998300e255f 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Prometheus Metrics library
+# Prometheus Metrics library **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) in GitLab 9.0.
@@ -35,6 +35,6 @@ In order to isolate and only display relevant metrics for a given environment,
GitLab needs a method to detect which labels are associated. To do that,
GitLab uses the defined queries and fills in the environment specific variables.
Typically this involves looking for the
-[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-environment-variables),
+[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-cicd-variables),
but may also include other information such as the project's Kubernetes namespace.
Each search query is defined in the [exporter specific documentation](#exporters).
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index ae330158a58..2a6bc810f71 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring Kubernetes
+# Monitoring Kubernetes **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8935) in GitLab 9.0.
@@ -40,7 +40,7 @@ Prometheus needs to be deployed into the cluster and configured properly in orde
In order to isolate and only display relevant CPU and Memory metrics for a given environment, GitLab needs a method to detect which containers it is running. Because these metrics are tracked at the container level, traditional Kubernetes labels are not available.
-Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-environment-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
+Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-cicd-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
## Displaying Canary metrics **(PREMIUM)**
diff --git a/doc/user/project/integrations/prometheus_library/metrics.md b/doc/user/project/integrations/prometheus_library/metrics.md
deleted file mode 100644
index a275efce5bb..00000000000
--- a/doc/user/project/integrations/prometheus_library/metrics.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'index.md'
----
-
-This document was moved to [another location](index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/prometheus_library/nginx.md b/doc/user/project/integrations/prometheus_library/nginx.md
index 4cb827b3b4a..dcaef1e2ae6 100644
--- a/doc/user/project/integrations/prometheus_library/nginx.md
+++ b/doc/user/project/integrations/prometheus_library/nginx.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring NGINX
+# Monitoring NGINX **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12621) in GitLab 9.4
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index f7542ec78f7..f7e6b6e76d6 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring NGINX Ingress Controller
+# Monitoring NGINX Ingress Controller **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22133) in GitLab 11.7.
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 c855e564753..0c86c4921b3 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -4,7 +4,7 @@ group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Monitoring NGINX Ingress Controller with VTS metrics
+# Monitoring NGINX Ingress Controller with VTS metrics **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13438) in GitLab 9.5.
diff --git a/doc/user/project/integrations/prometheus_units.md b/doc/user/project/integrations/prometheus_units.md
deleted file mode 100644
index 0c2ce3002ee..00000000000
--- a/doc/user/project/integrations/prometheus_units.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/metrics/dashboards/yaml_number_format.md'
----
-
-This document was moved to [another location](../../../operations/metrics/dashboards/yaml_number_format.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md
index a60af93a899..7507792bb02 100644
--- a/doc/user/project/integrations/services_templates.md
+++ b/doc/user/project/integrations/services_templates.md
@@ -6,6 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Service templates
+WARNING:
+Service templates are [deprecated and scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032)
+in GitLab 14.0. Use [project integration management](#central-administration-of-project-integrations) instead.
+
Using a service template, GitLab administrators can:
- Provide default values for configuring integrations when creating new projects.
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
index 9e9f5b8297f..ab798675278 100644
--- a/doc/user/project/integrations/slack.md
+++ b/doc/user/project/integrations/slack.md
@@ -45,6 +45,7 @@ separately configured [Slack slash commands](slack_slash_commands.md).
1. Select the **Notify only broken pipelines** check box to only notify on failures.
1. In the **Branches to be notified** select box, choose which types of branches
to send notifications for.
+1. Leave the **Labels to be notified** field blank to get all notifications or add labels that the issue or merge request must have in order to trigger a notification.
1. Click **Test settings and save changes**.
Your Slack team now starts receiving GitLab event notifications as configured.
diff --git a/doc/user/project/integrations/slack_slash_commands.md b/doc/user/project/integrations/slack_slash_commands.md
index 1e4577fb88e..4f206cd3e45 100644
--- a/doc/user/project/integrations/slack_slash_commands.md
+++ b/doc/user/project/integrations/slack_slash_commands.md
@@ -4,7 +4,7 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Slack slash commands **(CORE ONLY)**
+# Slack slash commands **(FREE SELF)**
> Introduced in GitLab 8.15.
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 47a44e53b47..0cf01adef13 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -31,7 +31,7 @@ update a backup mirror, or even deploy to your production server.
Webhooks are available:
-- Per project, at a project's **Settings > Webhooks** menu. **(CORE)**
+- Per project, at a project's **Settings > Webhooks** menu. **(FREE)**
- Additionally per group, at a group's **Settings > Webhooks** menu. **(PREMIUM)**
NOTE:
@@ -1029,6 +1029,9 @@ X-Gitlab-Event: Wiki Page Hook
### Pipeline events
+In [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53159)
+and later, the pipeline webhook returns only the latest jobs.
+
Triggered on status change of Pipeline.
**Request Header**:
@@ -1151,10 +1154,15 @@ X-Gitlab-Event: Pipeline Hook
"email": "admin@example.com"
},
"runner": {
- "id":380987,
- "description":"shared-runners-manager-6.gitlab.com",
- "active":true,
- "is_shared":true
+ "id": 380987,
+ "description": "shared-runners-manager-6.gitlab.com",
+ "active": true,
+ "is_shared": true,
+ "tags": [
+ "linux",
+ "docker",
+ "shared-runner"
+ ]
},
"artifacts_file":{
"filename": null,
@@ -1183,7 +1191,11 @@ X-Gitlab-Event: Pipeline Hook
"id":380987,
"description":"shared-runners-manager-6.gitlab.com",
"active":true,
- "is_shared":true
+ "is_shared":true,
+ "tags": [
+ "linux",
+ "docker"
+ ]
},
"artifacts_file":{
"filename": null,
@@ -1209,10 +1221,14 @@ X-Gitlab-Event: Pipeline Hook
"email": "admin@example.com"
},
"runner": {
- "id":380987,
- "description":"shared-runners-manager-6.gitlab.com",
- "active":true,
- "is_shared":true
+ "id": 380987,
+ "description": "shared-runners-manager-6.gitlab.com",
+ "active": true,
+ "is_shared": true,
+ "tags": [
+ "linux",
+ "docker"
+ ]
},
"artifacts_file":{
"filename": null,
@@ -1308,7 +1324,11 @@ X-Gitlab-Event: Job Hook
"active": true,
"is_shared": false,
"id": 380987,
- "description": "shared-runners-manager-6.gitlab.com"
+ "description": "shared-runners-manager-6.gitlab.com",
+ "tags": [
+ "linux",
+ "docker"
+ ]
}
}
```
@@ -1468,6 +1488,74 @@ X-Gitlab-Event: Member Hook
}
```
+### Subgroup events **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260419) in GitLab 13.9.
+
+Subgroup events are triggered when:
+
+- A [subgroup is created in a group](#subgroup-created-in-a-group)
+- A [subgroup is removed from a group](#subgroup-removed-from-a-group)
+
+#### Subgroup created in a group
+
+**Request Header**:
+
+```plaintext
+X-Gitlab-Event: Subgroup Hook
+```
+
+**Request Body**:
+
+```json
+{
+
+ "created_at": "2021-01-20T09:40:12Z",
+ "updated_at": "2021-01-20T09:40:12Z",
+ "event_name": "subgroup_create",
+ "name": "subgroup1",
+ "path": "subgroup1",
+ "full_path": "group1/subgroup1",
+ "group_id": 10,
+ "parent_group_id": 7,
+ "parent_name": "group1",
+ "parent_path": "group1",
+ "parent_full_path": "group1"
+
+}
+```
+
+#### Subgroup removed from a group
+
+**Request Header**:
+
+```plaintext
+X-Gitlab-Event: Subgroup Hook
+```
+
+**Request Body**:
+
+```json
+{
+
+ "created_at": "2021-01-20T09:40:12Z",
+ "updated_at": "2021-01-20T09:40:12Z",
+ "event_name": "subgroup_destroy",
+ "name": "subgroup1",
+ "path": "subgroup1",
+ "full_path": "group1/subgroup1",
+ "group_id": 10,
+ "parent_group_id": 7,
+ "parent_name": "group1",
+ "parent_path": "group1",
+ "parent_full_path": "group1"
+
+}
+```
+
+NOTE:
+Webhooks for when a [subgroup is removed from a group](#subgroup-removed-from-a-group) are not triggered when a [subgroup is transferred to a new parent group](../../group/index.md#transferring-groups)
+
### Feature Flag events
Triggered when a feature flag is turned on or off.
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 7119970fca0..e4f42b97b84 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -4,9 +4,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Issue Boards **(CORE)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5554) in [GitLab 8.11](https://about.gitlab.com/releases/2016/08/22/gitlab-8-11-released/#issue-board).
+# Issue Boards **(FREE)**
The GitLab Issue Board is a software project management tool used to plan,
organize, and visualize a workflow for a feature or product release.
@@ -38,10 +36,9 @@ as shown in the following table:
| Tier | Number of project issue boards | Number of [group issue boards](#group-issue-boards) | [Configurable issue boards](#configurable-issue-boards) | [Assignee lists](#assignee-lists) |
|------------------|--------------------------------|------------------------------|---------------------------|----------------|
-| Core / Free | Multiple | 1 | No | No |
-| Starter / Bronze | Multiple | 1 | Yes | No |
-| Premium / Silver | Multiple | Multiple | Yes | Yes |
-| Ultimate / Gold | Multiple | Multiple | Yes | Yes |
+| Free | Multiple | 1 | No | No |
+| Premium | Multiple | Multiple | Yes | Yes |
+| Ultimate | Multiple | Multiple | Yes | Yes |
To learn more, visit [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards) below.
@@ -53,11 +50,10 @@ the Issue Board feature.
## Multiple issue boards
-> - [Introduced](https://about.gitlab.com/releases/2016/10/22/gitlab-8-13-released/) in GitLab 8.13.
-> - Multiple issue boards per project [moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53811) to [GitLab Core](https://about.gitlab.com/pricing/) in GitLab 12.1.
-> - Multiple issue boards per group are available in [GitLab Premium](https://about.gitlab.com/pricing/).
+> - Multiple issue boards per project [moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53811) to GitLab Free in 12.1.
+> - Multiple issue boards per group are available in GitLab Premium.
-Multiple issue boards allow for more than one issue board for a given project **(CORE)** or group **(PREMIUM)**.
+Multiple issue boards allow for more than one issue board for a given project **(FREE)** or group **(PREMIUM)**.
This is great for large projects with more than one team or when a repository hosts the code of multiple products.
Using the search box at the top of the menu, you can filter the listed boards.
@@ -228,13 +224,13 @@ and vice versa.
## GitLab Enterprise features for issue boards
-GitLab issue boards are available on GitLab Core and GitLab.com Free tiers, but some
+GitLab issue boards are available on the GitLab Free tier, but some
advanced functionality is present in [higher tiers only](https://about.gitlab.com/pricing/).
-### Configurable issue boards **(STARTER)**
+### Configurable issue boards **(PREMIUM)**
-> - [Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in GitLab 10.2.
> - Setting current iteration as scope [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196804) in GitLab 13.8.
+> - Moved to GitLab Premium in 13.9.
An issue board can be associated with a [milestone](milestones/index.md#milestones),
[labels](labels.md), assignee, weight, and current [iteration](../group/iterations/index.md),
@@ -257,14 +253,15 @@ the Configurable Issue Board feature.
### Focus mode
-> - [Introduced]((https://about.gitlab.com/releases/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep)) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.1.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28597) to the Free tier of GitLab.com in 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212331) to GitLab Core in 13.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28597) to GitLab Free SaaS in 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212331) to GitLab Free self-managed in 13.0.
To enable or disable focus mode, select the **Toggle focus mode** button (**{maximize}**) at the top
right. In focus mode, the navigation UI is hidden, allowing you to focus on issues in the board.
-### Sum of issue weights **(STARTER)**
+### Sum of issue weights **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
The top of each list indicates the sum of issue weights for the issues that
belong to that list. This is useful when using boards for capacity allocation,
@@ -274,9 +271,6 @@ especially in combination with [assignee lists](#assignee-lists).
### Group issue boards **(PREMIUM)**
-> - One group issue board per group introduced in GitLab 10.6.
-> - Multiple group issue boards [introduced](https://about.gitlab.com/releases/2017/09/22/gitlab-10-0-released/#group-issue-boards) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0.
-
Accessible at the group navigation level, a group issue board offers the same features as a project-level board.
It can display issues from all projects in that
group and its descendant subgroups. Similarly, you can only filter by group labels for these
@@ -360,9 +354,10 @@ You can also [drag issues](#drag-issues-between-lists) to change their position
![Drag issues between swimlanes](img/epics_swimlanes_drag_and_drop.png)
-## Work In Progress limits **(STARTER)**
+## Work In Progress limits **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11403) in GitLab 12.7
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11403) in GitLab 12.7
+> - Moved to GitLab Premium in 13.9.
You can set a Work In Progress (WIP) limit for each issue list on an issue board. When a limit is
set, the list's header shows the number of issues in the list and the soft limit of issues.
@@ -435,13 +430,13 @@ To remove a list from an issue board:
1. Select **Remove list**. A confirmation dialog appears.
1. Select **OK**.
-### Add issues to a list **(CORE ONLY)**
+### Add issues to a list **(FREE SELF)**
> - Feature flag [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47898) in GitLab 13.7.
> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
> - It's disabled on GitLab.com.
> - It's recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-adding-issues-to-the-list). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-adding-issues-to-the-list). **(FREE SELF)**
You can add issues to a list in a project issue board by clicking the **Add issues** button
in the top right corner of the issue board. This opens up a modal
@@ -461,7 +456,7 @@ the list by filtering by the following:
- Release
- Weight
-#### Enable or disable adding issues to the list **(CORE ONLY)**
+#### Enable or disable adding issues to the list **(FREE SELF)**
Adding issues to the list is deployed behind a feature flag that is **disabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
@@ -547,8 +542,8 @@ to another list, the label changes and a system note is recorded.
When dragging issues between lists, different behavior occurs depending on the source list and the target list.
-| | To Open | To Closed | To label `B` list | To assignee `Bob` list |
-|----------------------------|--------------------|--------------|------------------------------|---------------------------------------|
+| | To Open | To Closed | To label `B` list | To assignee `Bob` list |
+| ------------------------------ | ------------------ | ------------ | ---------------------------- | ------------------------------------- |
| **From Open** | - | Issue closed | `B` added | `Bob` assigned |
| **From Closed** | Issue reopened | - | Issue reopened<br/>`B` added | Issue reopened<br/>`Bob` assigned |
| **From label `A` list** | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
@@ -563,7 +558,7 @@ another list. This makes it faster to reorder many issues at once.
To select and move multiple cards:
-1. Select each card with <kbd>Ctrl</kbd>+`Click` on Windows or Linux, or <kbd>Cmd</kbd>+`Click` on MacOS.
+1. Select each card with <kbd>Control</kbd>+`Click` on Windows or Linux, or <kbd>Command</kbd>+`Click` on MacOS.
1. Drag one of the selected cards to another position or list and all selected cards are moved.
![Multi-select Issue Cards](img/issue_boards_multi_select_v12_4.png)
diff --git a/doc/user/project/issues/automatic_issue_closing.md b/doc/user/project/issues/automatic_issue_closing.md
deleted file mode 100644
index 6fa2822aa9a..00000000000
--- a/doc/user/project/issues/automatic_issue_closing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'managing_issues.md#closing-issues-automatically'
----
-
-This document was moved to [another location](managing_issues.md#closing-issues-automatically).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/closing_issues.md b/doc/user/project/issues/closing_issues.md
deleted file mode 100644
index 45b905f2fb5..00000000000
--- a/doc/user/project/issues/closing_issues.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'managing_issues.md#closing-issues'
----
-
-This document was moved to [another location](managing_issues.md#closing-issues).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index d4fbc4fb10b..e1918b68ddc 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -99,9 +99,9 @@ confidential information prematurely. To make a confidential commit public,
open a merge request from the private fork to the public upstream project.
Permissions are inherited from parent groups. Developers have the same permissions
-for private forks created in the same group or in a sub-group of the original
+for private forks created in the same group or in a subgroup of the original
Permissions are inherited from parent groups. When private forks are created
-in the same group or sub-group as the original upstream repository, users
+in the same group or subgroup as the original upstream repository, users
receive the same permissions in both projects. This inheritance ensures
Developer users have the needed permissions to both view confidential issues and
resolve them.
diff --git a/doc/user/project/issues/create_new_issue.md b/doc/user/project/issues/create_new_issue.md
deleted file mode 100644
index 53648b53ea3..00000000000
--- a/doc/user/project/issues/create_new_issue.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'managing_issues.md#create-a-new-issue'
----
-
-This document was moved to [another location](managing_issues.md#create-a-new-issue).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index e7cd1377603..5c95665230a 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -6,8 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Export Issues to CSV
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1126) in [GitLab Starter 9.0](https://about.gitlab.com/releases/2017/03/22/gitlab-9-0-released/#export-issues-ees-eep).
-> - Moved to GitLab Core in GitLab 12.10.
+> Moved to GitLab Free in 12.10.
Issues can be exported as CSV from GitLab and are sent to your default notification email as an attachment.
@@ -20,7 +19,7 @@ which stores tabular data in plain text.
> _CSVs are a handy way of getting data from one program to another where one program cannot read the other ones normal output._ [Ref](https://www.quora.com/What-is-a-CSV-file-and-its-uses)
CSV files can be used with any plotter or spreadsheet-based program, such as Microsoft Excel,
-Open Office Calc, or Google Spreadsheets.
+Open Office <!-- vale gitlab.Spelling = NO --> Calc, <!-- vale gitlab.Spelling = NO --> or Google Spreadsheets.
## Use cases
@@ -49,10 +48,6 @@ Exported issues are always sorted by `Issue ID`.
## Format
-> **Time Estimate** and **Time Spent** columns were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2627) in GitLab Starter 10.0.
->
-> **Weight** and **Locked** columns were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5300) in GitLab Starter 10.8.
-
Data is encoded with a comma as the column delimiter, with `"` used to quote fields if needed, and newlines to separate rows. The first row contains the headers, which are listed in the following table along with a description of the values:
| Column | Description |
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 0d10f028cbf..2757642e458 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -1,6 +1,6 @@
---
-stage: none
-group: unassigned
+stage: Manage
+group: Import
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
@@ -9,7 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23532) in GitLab 11.7.
Issues can be imported to a project by uploading a CSV file with the columns
-`title` and `description`.
+`title` and `description`. Other columns are **not** imported. If you want to
+retain columns such as labels and milestones, consider the [Move Issue feature](managing_issues.md#moving-issues).
The user uploading the CSV file is set as the author of the imported issues.
diff --git a/doc/user/project/issues/deleting_issues.md b/doc/user/project/issues/deleting_issues.md
deleted file mode 100644
index d8e1485a2dc..00000000000
--- a/doc/user/project/issues/deleting_issues.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'managing_issues.md#deleting-issues'
----
-
-This document was moved to [another location](managing_issues.md#deleting-issues).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 3739070be01..b6dff0842d8 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -1,14 +1,14 @@
---
-stage: Create
-group: Knowledge
+stage: Plan
+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"
---
-# Design Management **(CORE)**
+# Design Management **(FREE)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
> - Support for SVGs was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12771) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4.
-> - Design Management was [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Core in 13.0.
+> - Design Management was [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
Design Management allows you to upload design assets (wireframes, mockups, etc.)
to GitLab issues and keep them stored in one single place, accessed by the Design
@@ -46,7 +46,7 @@ If the requirements are not met, the **Designs** tab displays a message to the u
## Supported files
Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`,
-`gif`, `bmp`, `tiff`, `ico`, or `svg`.
+`gif`, `bmp`, `tiff`, `ico`, `webp`, or `svg`.
Support for [PDF](https://gitlab.com/gitlab-org/gitlab/issues/32811) is planned for a future release.
@@ -259,4 +259,4 @@ This will be rendered as:
User activity events on designs (creation, deletion, and updates) are tracked by GitLab and
displayed on the [user profile](../../profile/index.md#user-profile),
[group](../../group/index.md#view-group-activity),
-and [project](../index.md#project-activity) activity pages.
+and [project](../working_with_projects.md#project-activity) activity pages.
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 34e9340067c..909a20f0e2f 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -41,7 +41,7 @@ You can see issues with their due dates in the [issues list](index.md#issues-lis
Overdue issues have their icon and date colored red.
To sort issues by their due dates, select **Due date** from the dropdown menu on the right.
Issues are then sorted from the earliest due date to the latest.
-To display isses with the latest due dates at the top, select **Sort direction** (**{sort-lowest}**).
+To display issues with the latest due dates at the top, select **Sort direction** (**{sort-lowest}**).
Due dates also appear in your [to-do list](../../todos.md).
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 74311eefd83..e398c6f86d0 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -4,35 +4,29 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Issues **(CORE)**
+# Issues **(FREE)**
-Issues are the fundamental medium for collaborating on ideas and planning work in GitLab.
+Issues are the fundamental mechanism in GitLab to collaborate on ideas, solve
+problems, and plan work.
-## Overview
+Using issues, you can share and discuss proposals (both before and during their
+implementation) between you and your team, and outside collaborators.
-The GitLab issue tracker is an advanced tool for collaboratively developing ideas, solving problems,
-and planning work.
+You can use issues for many purposes, customized to your needs and workflow.
+Common use cases include:
-Issues can allow sharing and discussion of proposals before, and during,
-their implementation between:
+- Discussing the implementation of a new idea.
+- Tracking tasks and work status.
+- Accepting feature proposals, questions, support requests, or bug reports.
+- Elaborating on new code implementations.
-- You and your team.
-- Outside collaborators.
+For more information about using issues, see the
+[Always start a discussion with an issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/)
+GitLab blog post.
-They can also be used for a variety of other purposes, customized to your
-needs and workflow.
-
-Issues are always associated with a specific project. If you have multiple projects in a group,
-you can view all of the issues collectively at the group level.
-
-**Common use cases include:**
-
-- Discussing the implementation of a new idea
-- Tracking tasks and work status
-- Accepting feature proposals, questions, support requests, or bug reports
-- Elaborating on new code implementations
-
-See also [Always start a discussion with an issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/).
+Issues are always associated with a specific project. If you have multiple
+projects in a group, you can view all of the issues collectively at the group
+level.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
To learn how our Strategic Marketing department uses GitLab issues with [labels](../labels.md) and
@@ -41,63 +35,30 @@ To learn how our Strategic Marketing department uses GitLab issues with [labels]
## Parts of an issue
-Issues contain a variety of content and metadata, enabling a large range of flexibility
-in how they are used. Each issue can contain the following attributes, though not all items
-must be set.
-
-<table class="borderless-table fixed-table">
-<tr>
- <td>
- <ul>
- <li>Content</li>
- <ul>
- <li>Title</li>
- <li>Description and tasks</li>
- <li>Comments and other activity</li>
- </ul>
- <li>People</li>
- <ul>
- <li>Author</li>
- <li>Assignee(s)</li>
- </ul>
- <li>State</li>
- <ul>
- <li>State (open or closed)</li>
- <li>Health status (on track, needs attention, or at risk)</li>
- <li>Confidentiality</li>
- <li>Tasks (completed vs. outstanding)</li>
- </ul>
- </ul>
- </td>
- <td>
- <ul>
- <li>Planning and tracking</li>
- <ul>
- <li>Milestone</li>
- <li>Due date</li>
- <li>Weight</li>
- <li>Time tracking</li>
- <li>Labels</li>
- <li>Votes</li>
- <li>Reaction emoji</li>
- <li>Linked issues</li>
- <li>Assigned epic</li>
- <li>Unique issue number and URL</li>
- </ul>
- </ul>
- </td>
-</tr>
-</table>
-
-## Viewing and managing issues
-
-While you can view and manage details of an issue on the [issue page](#issue-page),
-you can also work with multiple issues at a time using:
-
-- [Issues List](#issues-list).
-- [Issue Boards](#issue-boards).
-- Issue references.
-- [Epics](#epics) **(PREMIUM)**.
+Issues have a flexible content and metadata structure. Here are some of the
+elements you can provide in an issue:
+
+- Title
+- Description and tasks
+- Comments and other activity
+- Author
+- Assignees
+- State (open or closed)
+- Health status (on track, needs attention, or at risk)
+- Confidentiality
+- Tasks (completed vs. outstanding)
+- Milestone
+- Due date
+- Weight
+- Time tracking
+- Labels
+- Votes
+- Reaction emoji
+- Linked issues
+- Assigned epic
+- Unique issue number and URL
+
+## View and manage issues
Key actions for issues include:
@@ -105,7 +66,17 @@ Key actions for issues include:
- [Moving issues](managing_issues.md#moving-issues)
- [Closing issues](managing_issues.md#closing-issues)
- [Deleting issues](managing_issues.md#deleting-issues)
-- [Promoting issues](managing_issues.md#promote-an-issue-to-an-epic) **(PREMIUM)**
+- [Promoting issues](managing_issues.md#promote-an-issue-to-an-epic)
+
+Although you can view and manage details of an issue on the [issue page](#issue-page),
+you can also work with several issues at a time by using these features:
+
+- [Issues List](#issues-list): View a list of issues in a project or group.
+- [Issue Boards](../issue_board.md): Organize issues with a project management
+ workflow for a feature or product release.
+- Issue references
+- [Epics](../../group/epics/index.md): Manage your portfolio of projects by
+ tracking groups of issues with a shared theme.
### Issue page
@@ -114,18 +85,18 @@ Key actions for issues include:
On an issue's page, you can view [all aspects of the issue](issue_data_and_actions.md),
and modify them if you have the necessary [permissions](../../permissions.md).
-#### Real-time sidebar **(CORE ONLY)**
+#### Real-time sidebar **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 13.3.
Assignees in the sidebar are updated in real time. This feature is **disabled by default**.
-To enable, you need to enable [ActionCable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html).
+To enable it, you need to enable [ActionCable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html).
### Issues List
![Project Issues List view](img/project_issues_list_view.png)
-On the Issues List, you can:
+In the Issues List, you can:
- View all issues in a project when opening the Issues List from a project context.
- View all issues in a groups's projects when opening the Issues List from a group context.
@@ -137,20 +108,22 @@ view, you can also make certain changes [in bulk](../bulk_editing.md) to the dis
For more information, see the [Issue Data and Actions](issue_data_and_actions.md) page
for a rundown of all the fields and information in an issue.
-You can sort a list of issues in several ways, for example by issue creation date, milestone due date. For more information, see the [Sorting and Ordering Issue Lists](sorting_issue_lists.md) page.
+You can sort a list of issues in several ways, for example by issue creation date, milestone due date.
+For more information, see the [Sorting and ordering issue lists](sorting_issue_lists.md) page.
-### Issue boards
+#### Cached issue count
-![Issue board](img/issue_board.png)
+> - [Introduced]([link-to-issue](https://gitlab.com/gitlab-org/gitlab/-/issues/243753)) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use this feature in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cached-issue-count) **(FREE SELF)**
-[Issue boards](../issue_board.md) are Kanban boards with columns that display issues based on their
-labels or their assignees**(PREMIUM)**. They offer the flexibility to manage issues using
-highly customizable workflows.
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
-You can reorder issues in the column. If you drag an issue card to another column, its
-associated label or assignee is changed to match that of the new column. The entire
-board can also be filtered to only include issues from a certain milestone or an overarching
-label.
+In a group, the sidebar displays the total count of open issues and this value is cached if higher
+than 1000. The cached value is rounded to thousands (or millions) and updated every 24 hours.
### Design Management
@@ -158,12 +131,6 @@ With [Design Management](design_management.md), you can upload design
assets to issues and view them all together for sharing and
collaboration with your team.
-### Epics **(PREMIUM)**
-
-[Epics](../../group/epics/index.md) let you manage your portfolio of projects more
-efficiently and with less effort. Epics track groups of issues that share a theme, across
-projects and milestones.
-
### Related issues
You can mark two issues as related, so that when viewing one, the other is always
@@ -226,3 +193,22 @@ You can then see issue statuses in the [issue list](#issues-list) and the
- [Issues API](../../../api/issues.md)
- Configure an [external issue tracker](../../../integration/external-issue-tracker.md)
such as Jira, Redmine, Bugzilla, or EWM.
+
+## Enable or disable cached issue count **(FREE SELF)**
+
+Cached issue count in the left sidebar 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(:cached_sidebar_open_issues_count)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:cached_sidebar_open_issues_count)
+```
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 4c8630581f5..c3adce33826 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -23,13 +23,13 @@ The numbers in the image correspond to the following features:
- **1.** [Issue actions](#issue-actions)
- **2.** [To Do](#to-do)
- **3.** [Assignee](#assignee)
- - **3.1.** [Multiple Assignees **(STARTER)**](#multiple-assignees)
-- **4.** [Epic **(PREMIUM)**](#epic)
+ - **3.1.** [Multiple Assignees](#multiple-assignees)
+- **4.** [Epic](#epic)
- **5.** [Milestone](#milestone)
- **6.** [Time tracking](#time-tracking)
- **7.** [Due date](#due-date)
- **8.** [Labels](#labels)
-- **9.** [Weight **(STARTER)**](#weight)
+- **9.** [Weight](#weight)
- **10.** [Confidentiality](#confidentiality)
- **11.** [Lock issue](#lock-issue)
- **12.** [Participants](#participants)
@@ -86,7 +86,7 @@ An issue can be assigned to:
- Yourself.
- Another person.
-- [Many people](#multiple-assignees). **(STARTER)**
+- [Many people](#multiple-assignees). **(PREMIUM)**
The assignees can be changed as often as needed. The idea is that the assignees are
responsible for that issue until it's reassigned to someone else to take it from there.
@@ -96,7 +96,7 @@ NOTE:
If a user is not member of that project, it can only be
assigned to them if they created the issue themselves.
-#### Multiple Assignees **(STARTER)**
+#### Multiple Assignees **(PREMIUM)**
Often, multiple people work on the same issue together. This can be difficult
to track in large teams where there is shared ownership of an issue.
@@ -129,7 +129,7 @@ element. Due dates can be changed as many times as needed.
### Labels
Categorize issues by giving them [labels](../labels.md). They help to organize workflows,
-and they enable you to work with the [GitLab Issue Board](index.md#issue-boards).
+and they enable you to work with the [GitLab Issue Board](../issue_board.md).
Group Labels, which allow you to use the same labels for all projects in the same
group, can also be given to issues. They work exactly the same, but are immediately
@@ -138,7 +138,7 @@ available to all projects in the group.
If a label doesn't exist yet, you can create one by clicking **Edit**
followed by **Create new label** in the dropdown menu.
-### Weight **(STARTER)**
+### Weight **(PREMIUM)**
[Assign a weight](issue_weight.md) to an issue.
Larger values are used to indicate more effort is required to complete the issue. Only
@@ -161,14 +161,9 @@ or were mentioned in the description or threads.
### Notifications
-Click on the icon to enable/disable [notifications](../../profile/notifications.md#issue--epics--merge-request-events)
+Select the toggle to enable or disable [notifications](../../profile/notifications.md#notifications-on-issues-merge-requests-and-epics)
for the issue. Notifications are automatically enabled after you participate in the issue in any way.
-- **Enable**: If you are not a participant in the discussion on that issue, but
- want to receive notifications on each update, subscribe to it.
-- **Disable**: If you are receiving notifications for updates to that issue but no
- longer want to receive them, unsubscribe from it.
-
### Reference
- A quick "copy" button for that issue's reference, which looks like
@@ -194,13 +189,14 @@ The plain text title and description of the issue fill the top center of the iss
The description fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm),
allowing many formatting options.
-> [In GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/10103) and later, changes to an issue's description are listed in the [issue history](#issue-history). **(STARTER)**
+[In GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/10103) and later, changes to an
+issue's description are listed in the [issue history](#issue-history). **(PREMIUM)**
### Mentions
You can mention a user or a group present in your GitLab instance with `@username` or
`@groupname`. All mentioned users are notified via to-do items and emails,
-unless they have disabled all notifications in their profile settings.
+unless they have disabled all [notifications](#notifications) in their user settings.
This is controlled in the [notification settings](../../profile/notifications.md).
Mentions for yourself (the current logged in user) are highlighted
@@ -244,8 +240,8 @@ Also:
- You can mention a user or a group present in your GitLab instance with
`@username` or `@groupname` and they are notified via to-do items
- and emails, unless they have [disabled all notifications](#notifications)
- in their profile settings.
+ and emails, unless they have disabled all [notifications](#notifications)
+ in their user settings.
- Mentions for yourself (the current logged-in user) are highlighted
in a different color, which allows you to quickly see which comments involve you.
@@ -291,7 +287,7 @@ supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-g
After you write a comment, you can:
-- Click **Comment** and to publish your comment.
+- Click **Comment** to publish your comment.
- Choose **Start thread** from the dropdown list and start a new [thread](../../discussions/index.md#threaded-discussions)
in that issue's main thread to discuss specific points. This invites other participants
to reply directly to your thread, keeping related comments grouped together.
diff --git a/doc/user/project/issues/issue_weight.md b/doc/user/project/issues/issue_weight.md
index 4e2c8bfd7f1..b10debf9888 100644
--- a/doc/user/project/issues/issue_weight.md
+++ b/doc/user/project/issues/issue_weight.md
@@ -5,15 +5,15 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Issue weight **(STARTER)**
+# Issue weight **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3.
+> - Moved to GitLab Premium in 13.9.
When you have a lot of issues, it can be hard to get an overview.
By adding a weight to each issue, you can get a better idea of how much time,
value or complexity a given issue has or costs.
-You can set the weight of an issue during its creation, by simply changing the
+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).
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index ef860df054e..f1739726cf8 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -270,7 +270,7 @@ closed issues remain as-is. Disabling automatic issue closing only affects merge
requests *in* the project and does not prevent other projects from closing it
via cross-project issues.
-#### Customizing the issue closing pattern **(CORE ONLY)**
+#### Customizing the issue closing pattern **(FREE SELF)**
In order to change the default issue closing pattern, GitLab administrators must edit the
[`gitlab.rb` or `gitlab.yml` file](../../../administration/issue_closing_pattern.md)
@@ -287,9 +287,9 @@ editing it and clicking on the delete button.
## Promote an issue to an epic **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3777) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) to [GitLab Premium](https://about.gitlab.com/pricing/) in 12.8.
-> - Promoting issues to epics via the UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233974) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
+> - [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.
You can promote an issue to an epic in the immediate parent group.
@@ -302,9 +302,10 @@ Alternatively, you can use the `/promote` [quick action](../quick_actions.md#qui
Read more about promoting an issue to an epic on the [Manage epics page](../../group/epics/manage_epics.md#promote-an-issue-to-an-epic).
-## Add an issue to an iteration **(STARTER)**
+## Add an issue to an iteration **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in GitLab 13.2.
+> - Moved to GitLab Premium in 13.9.
To add an issue to an [iteration](../../group/iterations/index.md):
diff --git a/doc/user/project/issues/moving_issues.md b/doc/user/project/issues/moving_issues.md
deleted file mode 100644
index 3b40affcdc3..00000000000
--- a/doc/user/project/issues/moving_issues.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'managing_issues.md#moving-issues'
----
-
-This document was moved to [another location](managing_issues.md#moving-issues).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/multiple_assignees_for_issues.md b/doc/user/project/issues/multiple_assignees_for_issues.md
index bb9038062f7..189777d40e7 100644
--- a/doc/user/project/issues/multiple_assignees_for_issues.md
+++ b/doc/user/project/issues/multiple_assignees_for_issues.md
@@ -4,9 +4,9 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Multiple Assignees for Issues **(STARTER)**
+# Multiple Assignees for Issues **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1904) in [GitLab Starter 9.2](https://about.gitlab.com/releases/2017/05/22/gitlab-9-2-released/#multiple-assignees-for-issues).
+> - 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
@@ -40,4 +40,4 @@ to assign the issue to.
![adding multiple assignees](img/multiple_assignees.gif)
-An assignee can be easily removed by deselecting them from the same dropdown menu.
+To remove an assignee, deselect them from the same dropdown menu.
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index 82b2d4fde52..91c26d49532 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -4,10 +4,10 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Related issues **(CORE)**
+# Related issues **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1797) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.4.
-> - The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.4.
+> - 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.
Related issues are a bi-directional relationship between any two issues
and appear in a block below the issue description. Issues can be across groups
diff --git a/doc/user/project/issues/similar_issues.md b/doc/user/project/issues/similar_issues.md
deleted file mode 100644
index 79a50d5f812..00000000000
--- a/doc/user/project/issues/similar_issues.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'index.md#similar-issues'
----
-
-This document was moved to [another location](index.md#similar-issues).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index b4cb1c383ba..3a393b18579 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -4,7 +4,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Sorting and ordering issue lists **(CORE)**
+# Sorting and ordering issue lists **(FREE)**
You can sort a list of issues several ways, including by:
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 22dfd3a8719..c0a66343a88 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -59,21 +59,25 @@ and edit labels.
> Showing all inherited labels [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241990) in GitLab 13.5.
-To view the project labels list, navigate to the project and click **Issues > Labels**.
-The list includes all labels that are defined at the project level, as well as all
-labels defined by its ancestor groups.
-For each label, you can see the project or group path from where it was created.
-You can filter the list by entering a search query at the top and clicking search (**{search}**).
+To view a project's available labels, in the project, go to **Issues > Labels**.
+Its list of labels includes both the labels defined at the project level, and
+all labels defined by its ancestor groups. For each label, you can see the
+project or group path from where it was created. You can filter the list by
+entering a search query in the **Filter** field, and then clicking its search
+icon (**{search}**).
To create a new project label:
-1. Navigate to **Issues > Labels** in the project.
-1. Click the **New label** button.
- - Enter the title.
- - (Optional) Enter a description.
- - (Optional) Select a background color by clicking on the available colors, or input
- a hex color value for a specific color.
-1. Click **Create label** to create the label.
+1. In your project, go to **Issues > Labels**.
+1. Select the **New label** button.
+1. In the **Title** field, enter a short, descriptive name for the label. You
+ can also use this field to create [scoped, mutually exclusive labels](#scoped-labels).
+1. (Optional) In the **Description** field, you can enter additional
+ information about how and when to use this label.
+1. (Optional) Select a background color for the label by selecting one of the
+ available colors, or by entering a hex color value in the **Background color**
+ field.
+1. Select **Create label**.
You can also create a new project label from within an issue or merge request. In the
label section of the right sidebar of an issue or a merge request:
diff --git a/doc/user/project/maven_packages.md b/doc/user/project/maven_packages.md
deleted file mode 100644
index 5bfa08de2ed..00000000000
--- a/doc/user/project/maven_packages.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../packages/maven_repository/index.md'
----
-
-This document was moved to [another location](../packages/maven_repository/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/members/img/access_requests_management_13_8.png b/doc/user/project/members/img/access_requests_management_13_8.png
deleted file mode 100644
index 950ef4dec01..00000000000
--- a/doc/user/project/members/img/access_requests_management_13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/access_requests_management_v13_9.png b/doc/user/project/members/img/access_requests_management_v13_9.png
new file mode 100644
index 00000000000..b7883e9d134
--- /dev/null
+++ b/doc/user/project/members/img/access_requests_management_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_accept_13_8.png b/doc/user/project/members/img/add_user_email_accept_13_8.png
deleted file mode 100644
index ed980036af5..00000000000
--- a/doc/user/project/members/img/add_user_email_accept_13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_accept_v13_9.png b/doc/user/project/members/img/add_user_email_accept_v13_9.png
new file mode 100644
index 00000000000..a6b303e05ca
--- /dev/null
+++ b/doc/user/project/members/img/add_user_email_accept_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_ready_13_8.png b/doc/user/project/members/img/add_user_email_ready_v13_8.png
index a610b46a176..a610b46a176 100644
--- a/doc/user/project/members/img/add_user_email_ready_13_8.png
+++ b/doc/user/project/members/img/add_user_email_ready_v13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_email_search_13_8.png b/doc/user/project/members/img/add_user_email_search_v13_8.png
index 934cf19bd3d..934cf19bd3d 100644
--- a/doc/user/project/members/img/add_user_email_search_13_8.png
+++ b/doc/user/project/members/img/add_user_email_search_v13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_give_permissions_13_8.png b/doc/user/project/members/img/add_user_give_permissions_v13_8.png
index 1916d056a52..1916d056a52 100644
--- a/doc/user/project/members/img/add_user_give_permissions_13_8.png
+++ b/doc/user/project/members/img/add_user_give_permissions_v13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png b/doc/user/project/members/img/add_user_import_members_from_another_project_v13_8.png
index a6dddec3fb7..a6dddec3fb7 100644
--- a/doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png
+++ b/doc/user/project/members/img/add_user_import_members_from_another_project_v13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_imported_members_13_8.png b/doc/user/project/members/img/add_user_imported_members_13_8.png
deleted file mode 100644
index 725e447604f..00000000000
--- a/doc/user/project/members/img/add_user_imported_members_13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_imported_members_v13_9.png b/doc/user/project/members/img/add_user_imported_members_v13_9.png
new file mode 100644
index 00000000000..e40240df2b2
--- /dev/null
+++ b/doc/user/project/members/img/add_user_imported_members_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_list_members_13_8.png b/doc/user/project/members/img/add_user_list_members_13_8.png
deleted file mode 100644
index b8c0160c6d8..00000000000
--- a/doc/user/project/members/img/add_user_list_members_13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/add_user_list_members_v13_9.png b/doc/user/project/members/img/add_user_list_members_v13_9.png
new file mode 100644
index 00000000000..7a07ea01d14
--- /dev/null
+++ b/doc/user/project/members/img/add_user_list_members_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/add_user_search_people_13_8.png b/doc/user/project/members/img/add_user_search_people_v13_8.png
index e9aa58512ab..e9aa58512ab 100644
--- a/doc/user/project/members/img/add_user_search_people_13_8.png
+++ b/doc/user/project/members/img/add_user_search_people_v13_8.png
Binary files differ
diff --git a/doc/user/project/members/img/project_groups_tab_13_8.png b/doc/user/project/members/img/project_groups_tab_13_8.png
deleted file mode 100644
index 5d7948f0761..00000000000
--- a/doc/user/project/members/img/project_groups_tab_13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/project_groups_tab_v13_9.png b/doc/user/project/members/img/project_groups_tab_v13_9.png
new file mode 100644
index 00000000000..d1b6a640341
--- /dev/null
+++ b/doc/user/project/members/img/project_groups_tab_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/project_members_13_8.png b/doc/user/project/members/img/project_members_13_8.png
deleted file mode 100644
index 9120d471b3b..00000000000
--- a/doc/user/project/members/img/project_members_13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/project_members_filter_direct_v13_9.png b/doc/user/project/members/img/project_members_filter_direct_v13_9.png
new file mode 100644
index 00000000000..50115ee4052
--- /dev/null
+++ b/doc/user/project/members/img/project_members_filter_direct_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/project_members_filter_inherited_v13_9.png b/doc/user/project/members/img/project_members_filter_inherited_v13_9.png
new file mode 100644
index 00000000000..433003fe58b
--- /dev/null
+++ b/doc/user/project/members/img/project_members_filter_inherited_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/project_members_search_v13_9.png b/doc/user/project/members/img/project_members_search_v13_9.png
new file mode 100644
index 00000000000..67280d11dca
--- /dev/null
+++ b/doc/user/project/members/img/project_members_search_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/project_members_sort_v13_9.png b/doc/user/project/members/img/project_members_sort_v13_9.png
new file mode 100644
index 00000000000..47abe18ba49
--- /dev/null
+++ b/doc/user/project/members/img/project_members_sort_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/project_members_v13_9.png b/doc/user/project/members/img/project_members_v13_9.png
new file mode 100644
index 00000000000..3b48c752c6a
--- /dev/null
+++ b/doc/user/project/members/img/project_members_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png b/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png
deleted file mode 100644
index 6cbbb386396..00000000000
--- a/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/members/img/share_project_with_groups_tab_v13_9.png b/doc/user/project/members/img/share_project_with_groups_tab_v13_9.png
new file mode 100644
index 00000000000..99be996c03e
--- /dev/null
+++ b/doc/user/project/members/img/share_project_with_groups_tab_v13_9.png
Binary files differ
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index cccb998fc31..00474098487 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -21,42 +21,74 @@ project's **Members**.
When your project belongs to the group, group members inherit the membership and permission
level for the project from the group.
-![Project members page](img/project_members_13_8.png)
+![Project members page](img/project_members_v13_9.png)
From the image above, we can deduce the following things:
- There are 3 members that have access to the project.
- User0 is a Reporter and has inherited their permissions from group `demo`
which contains current project.
-- For User1 there is no indication of a group, therefore they belong directly
+- User1 is shown as a **Direct member** in the **Source** column, therefore they belong directly
to the project we're inspecting.
- Administrator is the Owner and member of **all** groups and for that reason,
there is an indication of an ancestor group and inherited Owner permissions.
-[From GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/21727), you can filter this list
-using the dropdown on the right side:
+## Filter and sort members
-![Project members filter](img/project_members_filter_v12_6.png)
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) in GitLab 12.6.
+> - [Improved](https://gitlab.com/groups/gitlab-org/-/epics/4901) in GitLab 13.9.
+> - Improvements are [deployed behind a feature flag](../../feature_flags.md), enabled by default.
+> - Improvements are enabled on GitLab.com.
+> - Improvements are recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable improvements](#enable-or-disable-improvements-to-project-member-management). **(FREE SELF)**
-- **Show only direct members** displays only User1.
-- **Show only inherited members** displays User0 and Administrator.
+The following sections illustrate how you can filter and sort members in a project. To view these options,
+navigate to your desired project, go to **Members**, and include the noted search terms.
+
+### Membership filter
+
+By default, inherited and direct members are displayed. The membership filter can be used to display only inherited or only direct members.
+
+#### Display inherited members
+
+To display inherited members, include `Membership` `=` `Inherited` in the search text box.
+
+![Project members filter inherited](img/project_members_filter_inherited_v13_9.png)
+
+#### Display direct members
+
+To display direct members, include `Membership` `=` `Direct` in the search text box.
+
+![Project members filter direct](img/project_members_filter_direct_v13_9.png)
+
+### Search
+
+You can search for members by name, username, or email.
+
+![Project members search](img/project_members_search_v13_9.png)
+
+### Sort
+
+You can sort members by **Account**, **Access granted**, **Max role**, or **Last sign-in** in ascending or descending order.
+
+![Project members sort](img/project_members_sort_v13_9.png)
## Add a user
Right next to **People**, start typing the name or username of the user you
want to add.
-![Search for people](img/add_user_search_people_13_8.png)
+![Search for people](img/add_user_search_people_v13_8.png)
Select the user and the [permission level](../../permissions.md)
that you'd like to give the user. Note that you can select more than one user.
-![Give user permissions](img/add_user_give_permissions_13_8.png)
+![Give user permissions](img/add_user_give_permissions_v13_8.png)
Once done, select **Add users to project** and they are immediately added to
your project with the permissions you gave them above.
-![List members](img/add_user_list_members_13_8.png)
+![List members](img/add_user_list_members_v13_9.png)
From there on, you can either remove an existing user or change their access
level to the project.
@@ -68,14 +100,14 @@ You can import another project's users in your own project by hitting the
In the dropdown menu, you can see only the projects you are Maintainer on.
-![Import members from another project](img/add_user_import_members_from_another_project_13_8.png)
+![Import members from another project](img/add_user_import_members_from_another_project_v13_8.png)
Select the one you want and hit **Import project members**. A flash message
displays, notifying you that the import was successful, and the new members
are now in the project's members list. Notice that the permissions that they
had on the project you imported from are retained.
-![Members list of new members](img/add_user_imported_members_13_8.png)
+![Members list of new members](img/add_user_imported_members_v13_9.png)
## Invite people using their e-mail address
@@ -83,18 +115,18 @@ If a user you want to give access to doesn't have an account on your GitLab
instance, you can invite them just by typing their e-mail address in the
user search field.
-![Invite user by mail](img/add_user_email_search_13_8.png)
+![Invite user by mail](img/add_user_email_search_v13_8.png)
As you can imagine, you can mix inviting multiple people and adding existing
GitLab users to the project.
-![Invite user by mail ready to submit](img/add_user_email_ready_13_8.png)
+![Invite user by mail ready to submit](img/add_user_email_ready_v13_8.png)
Once done, hit **Add users to project** and watch that there is a new member
with the e-mail address we used above. From there on, you can resend the
invitation, change their access level, or even delete them.
-![Invite user members list](img/add_user_email_accept_13_8.png)
+![Invite user members list](img/add_user_email_accept_v13_9.png)
While unaccepted, the system automatically sends reminder emails on the second, fifth,
and tenth day after the invitation was initially sent.
@@ -130,7 +162,7 @@ NOTE:
If a project does not have any maintainers, the notification is sent to the
most recently active owners of the project's group.
-![Manage access requests](img/access_requests_management_13_8.png)
+![Manage access requests](img/access_requests_management_v13_9.png)
If you change your mind before your request is approved, just click the
**Withdraw Access Request** button.
@@ -167,3 +199,27 @@ To remove a member from a project:
A **Remove member** modal appears.
1. (Optional) Select the **Also unassign this user from related issues and merge requests** checkbox.
1. Click **Remove member**.
+
+## Enable or disable improvements to project member management **(FREE SELF)**
+
+Project member management improvements are deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable the improvements.
+
+To disable them:
+
+```ruby
+# For the instance
+Feature.disable(:vue_project_members_list)
+# For a single project
+Feature.disable(:vue_project_members_list, Project.find(<project id>))
+```
+
+To enable them:
+
+```ruby
+# For the instance
+Feature.enable(:vue_project_members_list)
+# For a single project
+Feature.enable(:vue_project_members_list, Project.find(<project id>))
+```
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index d17717fb29c..7000988d9bf 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -26,7 +26,7 @@ To share 'Project Acme' with the 'Engineering' group:
1. For 'Project Acme' use the left navigation menu to go to **Members**.
- ![share project with groups](img/share_project_with_groups_tab_v13_8.png)
+ ![share project with groups](img/share_project_with_groups_tab_v13_9.png)
1. Select the **Invite group** tab.
1. Add the 'Engineering' group with the maximum access level of your choice.
@@ -35,7 +35,7 @@ To share 'Project Acme' with the 'Engineering' group:
1. After sharing 'Project Acme' with 'Engineering':
- The group is listed in the **Groups** tab.
- !['Engineering' group is listed in Groups tab](img/project_groups_tab_13_8.png)
+ !['Engineering' group is listed in Groups tab](img/project_groups_tab_v13_9.png)
- The project is listed on the group dashboard.
diff --git a/doc/user/project/merge_requests.md b/doc/user/project/merge_requests.md
deleted file mode 100644
index 5762177882e..00000000000
--- a/doc/user/project/merge_requests.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'merge_requests/index.md'
----
-
-This document was moved to [merge_requests/index.md](merge_requests/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md
index 8adaae3b2ef..7aa7673366d 100644
--- a/doc/user/project/merge_requests/allow_collaboration.md
+++ b/doc/user/project/merge_requests/allow_collaboration.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Allow collaboration on merge requests across forks
+# Allow collaboration on merge requests across forks **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17395) in GitLab 10.6.
@@ -23,7 +23,7 @@ of the merge request.
## Enabling commit edits from upstream members
-From [GitLab 13.7 onwards](https://gitlab.com/gitlab-org/gitlab/-/issues/23308),
+In [GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/23308),
this setting is enabled by default. It can be changed by users with Developer
permissions to the source project. Once enabled, upstream members will also be
able to retry the pipelines and jobs of the merge request:
@@ -78,8 +78,23 @@ Here's how the process would look like:
local branch `thedude-awesome-project-update-docs` to the
`update-docs` branch of the `git@gitlab.com:thedude/awesome-project.git` repository.
-<!-- ## Troubleshooting
+## Troubleshooting
+
+### Pipeline status unavailable from MR page of forked project
+
+When a user forks a project, the permissions on the forked copy are not copied over
+from the original project. The creator of the fork must grant permissions to the
+forked copy before members in the upstream project can view or merge the changes
+in the merge request.
+To see the pipeline status from the merge request page of a forked project
+going back to the original project:
+
+1. Create a group containing all the upstream members.
+1. Go to the **Members** tab in the forked project and invite the newly-created
+ group to the forked project.
+
+<!-- ## 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.
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 7bb64987a31..36481ac0133 100644
--- a/doc/user/project/merge_requests/authorization_for_merge_requests.md
+++ b/doc/user/project/merge_requests/authorization_for_merge_requests.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts
---
-# Authorization for Merge requests
+# Authorization for Merge requests **(FREE)**
There are two main ways to have a merge request flow with GitLab:
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 4e87876b036..4c9a6557320 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Cherry-pick changes
+# Cherry-pick changes **(FREE)**
GitLab implements Git's powerful feature to
[cherry-pick any commit](https://git-scm.com/docs/git-cherry-pick "Git cherry-pick documentation")
@@ -13,12 +13,13 @@ with introducing a **Cherry-pick** button in merge requests and commit details.
## Cherry-picking a merge request
-After the merge request has been merged, a **Cherry-pick** button will be available
+After the merge request has been merged, a **Cherry-pick** button displays
to cherry-pick the changes introduced by that merge request.
![Cherry-pick Merge Request](img/cherry_pick_changes_mr.png)
-After you click that button, a modal will appear showing a [branch filter search box](../repository/branches/index.md#branch-filter-search-box)
+After you click that button, a modal displays a
+[branch filter search box](../repository/branches/index.md#branch-filter-search-box)
where you can choose to either:
- Cherry-pick the changes directly into the selected branch.
@@ -28,12 +29,12 @@ where you can choose to either:
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2675) in GitLab 12.9.
-When you cherry-pick a merge commit, GitLab will output a system note to the related merge
-request thread crosslinking the new commit and the existing merge request.
+When you cherry-pick a merge commit, GitLab displays a system note to the related merge
+request thread. It crosslinks the new commit and the existing merge request.
![Cherry-pick tracking in Merge Request timeline](img/cherry_pick_mr_timeline_v12_9.png)
-Each deployment's [list of associated merge requests](../../../api/deployments.md#list-of-merge-requests-associated-with-a-deployment) will include cherry-picked merge commits.
+Each deployment's [list of associated merge requests](../../../api/deployments.md#list-of-merge-requests-associated-with-a-deployment) includes cherry-picked merge commits.
NOTE:
We only track cherry-pick executed from GitLab (both UI and API). Support for [tracking cherry-picked commits through the command line](https://gitlab.com/gitlab-org/gitlab/-/issues/202215) is planned for a future release.
@@ -44,15 +45,15 @@ You can cherry-pick a commit from the commit details page:
![Cherry-pick commit](img/cherry_pick_changes_commit.png)
-Similar to cherry-picking a merge request, you can opt to cherry-pick the changes
+Similar to cherry-picking a merge request, you can cherry-pick the changes
directly into the target branch or create a new merge request to cherry-pick the
changes.
-Please note that when cherry-picking merge commits, the mainline will always be the
-first parent. If you want to use a different mainline then you need to do that
+When cherry-picking merge commits, the mainline is always the
+first parent. If you want to use a different mainline, you need to do that
from the command line.
-Here is a quick example to cherry-pick a merge commit using the second parent as the
+Here's a quick example to cherry-pick a merge commit using the second parent as the
mainline:
```shell
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index ca15ec154fc..55dc0bcc41a 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -5,9 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Code Quality
+# Code Quality **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in GitLab 9.3.
> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in 13.2.
Ensuring your project's code stays simple, readable and easy to contribute to can be problematic. With the help of [GitLab CI/CD](../../../ci/README.md), you can analyze your
@@ -28,7 +28,7 @@ Code Quality:
## Code Quality Widget
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1984) in GitLab 9.3.
> - Made [available in all tiers](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) in 13.2.
Going a step further, GitLab can show the Code Quality report right
@@ -73,9 +73,9 @@ GitLab 11.4 or earlier, you can view the deprecated job definitions in the
[documentation archive](https://docs.gitlab.com/12.10/ee/user/project/merge_requests/code_quality.html#previous-job-definitions).
- Using shared runners, the job should be configured For the [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker).
-- Using private runners, there is an [alternative configuration](#set-up-a-private-runner-for-code-quality-without-docker-in-docker) recommended for running CodeQuality analysis more efficiently.
+- Using private runners, there is an [alternative configuration](#set-up-a-private-runner-for-code-quality-without-docker-in-docker) recommended for running Code Quality analysis more efficiently.
-In either configuration, the runner mmust have enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB.
+In either configuration, the runner must have enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB.
Once you set up GitLab Runner, include the Code Quality template in your CI configuration:
@@ -161,6 +161,7 @@ to be consider, but may be preferable depending on your use case.
--locked="false" \
--access-level="not_protected" \
--docker-volumes "/cache"\
+ --docker-volumes "/builds:/builds"\
--docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
--registration-token="<project_token>" \
--non-interactive
@@ -173,8 +174,8 @@ to be consider, but may be preferable depending on your use case.
in the previous step.
```shell
- --builds-dir /tmp/builds
- --docker-volumes /tmp/builds:/tmp/builds
+ --builds-dir "/tmp/builds"
+ --docker-volumes "/tmp/builds:/tmp/builds" # Use this instead of --docker-volumes "/builds:/builds"
```
The resulting configuration:
@@ -219,8 +220,8 @@ The end result is that:
- Docker images, including all CodeClimate images, are cached, and not re-fetched for subsequent jobs.
With this configuration, the run time for a second pipeline is much shorter. For example
-this [small change](https://gitlab.com/drewcimino/test-code-quality-template/-/merge_requests/4/diffs?commit_id=1e705607aef7236c1b20bb6f637965f3f3e53a46)
-to an [open merge request](https://gitlab.com/drewcimino/test-code-quality-template/-/merge_requests/4/pipelines)
+this [small change](https://gitlab.com/drew/test-code-quality-template/-/merge_requests/4/diffs?commit_id=1e705607aef7236c1b20bb6f637965f3f3e53a46)
+to an [open merge request](https://gitlab.com/drew/test-code-quality-template/-/merge_requests/4/pipelines)
running Code Quality analysis ran significantly faster the second time:
![Code Quality sequential runs without DinD](img/code_quality_host_bound_sequential.png)
@@ -358,7 +359,7 @@ After the Code Quality job completes:
[downloadable artifact](../../../ci/pipelines/job_artifacts.md#downloading-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. **(STARTER)**
+ Code Quality tab of the Pipeline Details page. **(PREMIUM)**
### Generating an HTML report
@@ -411,7 +412,7 @@ plugins:
enabled: true
```
-This adds SonarJava to the `plugins:` section of the [default `.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml)
+This adds SonarJava to the `plugins:` section of the [default `.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml.template)
included in your project.
Changes to the `plugins:` section do not affect the `exclude_patterns` section of the
@@ -421,6 +422,71 @@ for more details.
Here's [an example project](https://gitlab.com/jheimbuck_gl/jh_java_example_project) that uses Code Quality with a `.codeclimate.yml` file.
+## Use a Code Quality image hosted in a registry with untrusted certificates
+
+If you set the `CODE_QUALITY_IMAGE` to an image that is hosted in a
+Docker registry which uses a TLS certificate that is not trusted, such as
+a self-signed certificate, you can see errors like the one below:
+
+```shell
+$ docker pull --quiet "$CODE_QUALITY_IMAGE"
+Error response from daemon: Get https://gitlab.example.com/v2/: x509: certificate signed by unknown authority
+```
+
+To fix this, configure the Docker daemon to [trust certificates](https://docs.docker.com/registry/insecure/#use-self-signed-certificates)
+by putting the certificate inside of the `/etc/docker/certs.d`
+directory.
+
+This Docker daemon is exposed to the subsequent Code Quality Docker container in the
+[GitLab Code Quality template](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.8.3-ee/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml#L41)
+and should be to exposed any other containers in which you want to have
+your certificate configuration apply.
+
+### Docker
+
+If you have access to GitLab Runner configuration, add the directory as a
+[volume mount](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runnersdocker-section). For example:
+
+```toml
+[[runners]]
+ ...
+ executor = "docker"
+ [runners.docker]
+ ...
+ privileged = true
+ volumes = ["/cache", "/etc/gitlab-runner/certs/gitlab.example.com.crt:/etc/docker/certs.d/gitlab.example.com/ca.crt:ro"]
+```
+
+Replace `gitlab.example.com` with the actual domain of the registry.
+
+### Kubernetes
+
+If you have access to GitLab Runner configuration and the Kubernetes cluster,
+you can [mount a ConfigMap](https://docs.gitlab.com/runner/executors/kubernetes.html#configmap-volumes):
+
+1. Create a ConfigMap with the certificate:
+
+ ```shell
+ kubectl create configmap registry-crt --namespace gitlab-runner --from-file /etc/gitlab-runner/certs/gitlab.example.com.crt
+ ```
+
+1. Update GitLab Runner `config.toml` to specify the ConfigMap:
+
+ ```toml
+ [[runners]]
+ ...
+ executor = "kubernetes"
+ [runners.kubernetes]
+ image = "alpine:3.12"
+ privileged = true
+ [[runners.kubernetes.volumes.config_map]]
+ name = "registry-crt"
+ mount_path = "/etc/docker/certs.d/gitlab.example.com/ca.crt"
+ sub_path = "gitlab.example.com.crt"
+ ```
+
+Replace `gitlab.example.com` with the actual domain of the registry.
+
## Troubleshooting
### Changing the default configuration has no effect
@@ -428,7 +494,7 @@ Here's [an example project](https://gitlab.com/jheimbuck_gl/jh_java_example_proj
A common issue is that the terms `Code Quality` (GitLab specific) and `Code Climate`
(Engine used by GitLab) are very similar. You must add a **`.codeclimate.yml`** file
to change the default configuration, **not** a `.codequality.yml` file. If you use
-the wrong filename, the [default `.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml)
+the wrong filename, the [default `.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml.template)
is still used.
### No Code Quality report is displayed in a Merge Request
@@ -438,21 +504,51 @@ This can be due to multiple reasons:
- You just added the Code Quality job in your `.gitlab-ci.yml`. The report does not
have anything to compare to yet, so no information can be displayed. It only displays
after future merge requests have something to compare to.
-- Your pipeline is not set to run the code quality job on your default branch. If there is no report generated from the default branch, your MR branch reports will not have anything to compare to.
+- Your pipeline is not set to run the code quality job on your default branch. If there is no report generated from the default branch, your MR branch reports have nothing to compare to.
- If no [degradation or error is detected](https://docs.codeclimate.com/docs/maintainability#section-checks),
nothing is displayed.
- The [`artifacts:expire_in`](../../../ci/yaml/README.md#artifactsexpire_in) CI/CD
setting can cause the Code Quality artifact(s) to expire faster than desired.
- If you use the [`REPORT_STDOUT` environment variable](https://gitlab.com/gitlab-org/ci-cd/codequality#environment-variables), no report file is generated and nothing displays in the merge request.
-- Large `codeclimate.json` files (esp. >10 MB) are [known to prevent the report from being displayed](https://gitlab.com/gitlab-org/gitlab/-/issues/2737).
+- Large `gl-code-quality-report.json` files (esp. >10 MB) are [known to prevent the report from being displayed](https://gitlab.com/gitlab-org/gitlab/-/issues/2737).
As a work-around, try removing [properties](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types)
that are [ignored by GitLab](#implementing-a-custom-tool). You can:
- Configure the Code Quality tool to not output those types.
- Use `sed`, `awk` or similar commands in the `.gitlab-ci.yml` script to
- edit the `codeclimate.json` before the job completes.
+ edit the `gl-code-quality-report.json` before the job completes.
### Only a single Code Quality report is displayed, but more are defined
GitLab only uses the Code Quality artifact from the latest created job (with the largest job ID).
If multiple jobs in a pipeline generate a code quality artifact, those of earlier jobs are ignored.
-To avoid confusion, configure only one job to generate a `codeclimate.json`.
+To avoid confusion, configure only one job to generate a `gl-code-quality-report.json`.
+
+### Rubocop errors
+
+When using Code Quality jobs on a Ruby project, you can encounter problems running Rubocop.
+For example, the following error can appear when using either a very recent or very old version
+of Ruby:
+
+```plaintext
+/usr/local/bundle/gems/rubocop-0.52.1/lib/rubocop/config.rb:510:in `check_target_ruby':
+Unknown Ruby version 2.7 found in `.ruby-version`. (RuboCop::ValidationError)
+Supported versions: 2.1, 2.2, 2.3, 2.4, 2.5
+```
+
+This is caused by the default version of Rubocop used by the check engine not covering
+support for the Ruby version in use.
+
+To use a custom version of Rubocop that
+[supports the version of Ruby used by the project](https://docs.rubocop.org/rubocop/compatibility.html#support-matrix),
+you can [override the configuration through a `.codeclimate.yml` file](https://docs.codeclimate.com/docs/rubocop#using-rubocops-newer-versions)
+created in the project repository.
+
+For example, to specify using Rubocop release **0.67**:
+
+```yaml
+version: "2"
+plugins:
+ rubocop:
+ enabled: true
+ channel: rubocop-0-67
+```
diff --git a/doc/user/project/merge_requests/code_quality_diff.md b/doc/user/project/merge_requests/code_quality_diff.md
deleted file mode 100644
index 2b7b2574ef7..00000000000
--- a/doc/user/project/merge_requests/code_quality_diff.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'code_quality.md'
----
-
-This document was moved to [another location](code_quality.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/container_scanning.md b/doc/user/project/merge_requests/container_scanning.md
deleted file mode 100644
index 5d61f2b36e8..00000000000
--- a/doc/user/project/merge_requests/container_scanning.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../application_security/container_scanning/index.md'
----
-
-This document was moved to [another location](../../application_security/container_scanning/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/creating_merge_requests.md b/doc/user/project/merge_requests/creating_merge_requests.md
index 5adc4ab6b6e..5cfedc6c9f1 100644
--- a/doc/user/project/merge_requests/creating_merge_requests.md
+++ b/doc/user/project/merge_requests/creating_merge_requests.md
@@ -7,7 +7,7 @@ description: "How to create Merge Requests in GitLab."
disqus_identifier: 'https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html'
---
-# How to create a merge request
+# How to create a merge request **(FREE)**
Before creating a merge request, read through an
[introduction to Merge Requests](getting_started.md)
@@ -178,7 +178,7 @@ fork from its upstream project in the **Settings > Advanced Settings** section b
For further details, [see the forking workflow documentation](../repository/forking_workflow.md).
-## New merge request by email **(CORE ONLY)**
+## New merge request by email **(FREE SELF)**
_This feature needs [incoming email](../../../administration/incoming_email.md)
to be configured by a GitLab administrator to be available._ It isn't
diff --git a/doc/user/project/merge_requests/csv_export.md b/doc/user/project/merge_requests/csv_export.md
index 0de9f246ceb..f4843b96c99 100644
--- a/doc/user/project/merge_requests/csv_export.md
+++ b/doc/user/project/merge_requests/csv_export.md
@@ -4,7 +4,7 @@ group: Compliance
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Export Merge Requests to CSV **(CORE)**
+# Export Merge Requests to CSV **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3619) in GitLab 13.6.
diff --git a/doc/user/project/merge_requests/dast.md b/doc/user/project/merge_requests/dast.md
deleted file mode 100644
index 37c0d5b4e37..00000000000
--- a/doc/user/project/merge_requests/dast.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../application_security/dast/index.md'
----
-
-This document was moved to [another location](../../application_security/dast/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/dependency_scanning.md b/doc/user/project/merge_requests/dependency_scanning.md
deleted file mode 100644
index dd5910121ed..00000000000
--- a/doc/user/project/merge_requests/dependency_scanning.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../application_security/dependency_scanning/index.md'
----
-
-This document was moved to [another location](../../application_security/dependency_scanning/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/fast_forward_merge.md b/doc/user/project/merge_requests/fast_forward_merge.md
index a89acff4bfc..c4a34f9c65c 100644
--- a/doc/user/project/merge_requests/fast_forward_merge.md
+++ b/doc/user/project/merge_requests/fast_forward_merge.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Fast-forward merge requests
+# Fast-forward merge requests **(FREE)**
Sometimes, a workflow policy might mandate a clean commit history without
merge commits. In such cases, the fast-forward merge is the perfect candidate.
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index dc5e1f81a63..b1a57d9c3e6 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -6,7 +6,7 @@ type: index, reference
description: "Getting started with Merge Requests."
---
-# Getting started with Merge Requests
+# Getting started with Merge Requests **(FREE)**
A Merge Request (**MR**) is the basis of GitLab as a code
collaboration and version control.
@@ -53,10 +53,10 @@ When you start a new merge request, you can immediately include the following
options, or add them later by clicking the **Edit** button on the merge
request's page at the top-right side:
-- [Assign](#assignee) the merge request to a colleague for review. With GitLab Starter and higher tiers, you can [assign it to more than one person at a time](#multiple-assignees).
+- [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](merge_request_approvals.md) from your team. **(STARTER)**
+- Require [approval](merge_request_approvals.md) from your team. **(PREMIUM)**
- [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.
@@ -87,9 +87,10 @@ Open the drop down box to search for the user you wish to assign,
and the merge request will be added to their
[assigned merge request list](../../search/index.md#issues-and-merge-requests).
-#### Multiple assignees **(STARTER)**
+#### Multiple assignees **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2004) in [GitLab Starter 11.11](https://about.gitlab.com/pricing/).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2004) in GitLab 11.11.
+> - Moved to GitLab Premium in 13.9
Multiple people often review merge requests at the same time.
GitLab allows you to have multiple assignees for merge requests
@@ -114,16 +115,9 @@ It is also possible to manage multiple assignees:
### Reviewer
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216054) in GitLab 13.5.
-> - It was [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49787) on GitLab 13.7.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - It can be enabled or disabled for a single project.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-merge-request-reviewers). **(CORE ONLY)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/245190) in GitLab 13.9.
WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
Requesting a code review is an important part of contributing code. However, deciding who should review
your code and asking for a review are no easy tasks. Using the "assignee" field for both authors and
reviewers makes it hard for others to determine who's doing what on a merge request.
@@ -136,48 +130,14 @@ This makes it easy to determine the relevant roles for the users involved in the
To request it, open the **Reviewers** drop-down box to search for the user you wish to get a review from.
-#### Enable or disable Merge Request Reviewers **(CORE ONLY)**
-
-Merge Request Reviewers is under development but ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-# For the instance
-Feature.enable(:merge_request_reviewers)
-# For a single project
-Feature.enable(:merge_request_reviewers, Project.find(<project id>))
-```
-
-To disable it:
+#### Approval Rule information for Reviewers **(PREMIUM)**
-```ruby
-# For the instance
-Feature.disable(:merge_request_reviewers)
-# For a single project
-Feature.disable(:merge_request_reviewers, Project.find(<project id>))
-```
-
-#### Approval Rule information for Reviewers **(STARTER)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233736) in GitLab 13.8.
-> - It was [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51183) in GitLab 13.8.
-> - It's enabled on GitLab.com.
-> - It's recommended for production use.
-> - It can be enabled or disabled for a single project.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-approval-rule-information-for-reviewers). **(STARTER ONLY)**
-
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233736) in GitLab 13.8. For this version only, GitLab administrators can opt to [enable it](#enable-or-disable-approval-rule-information).
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293742) in GitLab 13.9.
When editing the **Reviewers** field in a new or existing merge request, GitLab
displays the name of the matching [approval rule](merge_request_approvals.md#approval-rules)
-below the name of each suggested reviewer. [Code Owners](../code_owners.md) are displayed as **Code Owner** without group detail.
-We intend to iterate on this feature in future releases.
+below the name of each suggested reviewer. [Code Owners](../code_owners.md) are displayed as `Codeowner` without group detail.
This example shows reviewers and approval rules when creating a new merge request:
@@ -187,30 +147,20 @@ This example shows reviewers and approval rules in a merge request sidebar:
![Reviewer approval rules in sidebar](img/reviewer_approval_rules_sidebar_v13_8.png)
-##### Enable or disable Approval Rule information for Reviewers **(STARTER ONLY)**
+#### Requesting a new review
-Merge Request Reviewers is under development and ready for production use.
-It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/293933) in GitLab 13.9.
-```ruby
-# For the instance
-Feature.enable(:reviewer_approval_rules)
-# For a single project
-Feature.enable(:reviewer_approval_rules, Project.find(<project id>))
-```
+After a reviewer completes their [merge request reviews](../../discussions/index.md),
+the author of the merge request can request a new review from the reviewer:
-To disable it:
+1. If the right sidebar in the merge request is collapsed, click the
+ **{chevron-double-lg-left}** **Expand Sidebar** icon to expand it.
+1. In the **Reviewers** section, click the **Re-request a review** icon (**{redo}**)
+ next to the reviewer's name.
-```ruby
-# For the instance
-Feature.disable(:reviewer_approval_rules)
-# For a single project
-Feature.disable(:reviewer_approval_rules, Project.find(<project id>))
-```
+GitLab creates a new [to-do item](../../todos.md) for the reviewer, and sends
+them a notification email.
### Merge requests to close issues
@@ -244,6 +194,33 @@ is set for deletion, the merge request widget displays the
![Delete source branch status](img/remove_source_branch_status.png)
+### Branch retargeting on merge **(FREE SELF)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-branch-retargeting-on-merge).
+
+In specific circumstances, GitLab can retarget the destination branch of
+open merge request, if the destination branch merges while the merge request is
+open. Merge requests are often chained in this manner, with one merge request
+depending on another:
+
+- **Merge request 1**: merge `feature-alpha` into `master`.
+- **Merge request 2**: merge `feature-beta` into `feature-alpha`.
+
+These merge requests are usually handled in one of these ways:
+
+- Merge request 1 is merged into `master` first. Merge request 2 is then
+ retargeted to `master`.
+- Merge request 2 is merged into `feature-alpha`. The updated merge request 1, which
+ now contains the contents of `feature-alpha` and `feature-beta`, is merged into `master`.
+
+GitLab retargets up to four merge requests when their target branch is merged into
+`master`, so you don't need to perform this operation manually. Merge requests from
+forks are not retargeted.
+
## Recommendations and best practices for Merge Requests
- When working locally in your branch, add multiple commits and only push when
@@ -253,3 +230,49 @@ is set for deletion, the merge request widget displays the
- Take one thing at a time and ship the smallest changes possible. By doing so,
reviews are faster and your changes are less prone to errors.
- Do not use capital letters nor special chars in branch names.
+
+## Enable or disable Approval Rule information **(PREMIUM SELF)**
+
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293742) in GitLab 13.9.
+
+Merge Request Reviewers is under development and ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+# For the instance
+Feature.enable(:reviewer_approval_rules)
+# For a single project
+Feature.enable(:reviewer_approval_rules, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:reviewer_approval_rules)
+# For a single project
+Feature.disable(:reviewer_approval_rules, Project.find(<project id>))
+```
+
+### Enable or disable branch retargeting on merge **(FREE SELF)**
+
+Automatically retargeting merge requests is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:retarget_merge_requests)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:retarget_merge_requests)
+```
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 6af6cad5cdd..8ccf50e48b8 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# Merge requests
+# Merge requests **(FREE)**
A Merge Request (**MR**) is a _request_ to _merge_ one branch into another.
diff --git a/doc/user/project/merge_requests/license_management.md b/doc/user/project/merge_requests/license_management.md
deleted file mode 100644
index 4c598d851a9..00000000000
--- a/doc/user/project/merge_requests/license_management.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../compliance/license_compliance/index.md'
----
-
-This document was moved to [another location](../../compliance/license_compliance/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/maintainer_access.md b/doc/user/project/merge_requests/maintainer_access.md
deleted file mode 100644
index 29afff289fd..00000000000
--- a/doc/user/project/merge_requests/maintainer_access.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'allow_collaboration.md'
----
-
-This document was moved to [another location](allow_collaboration.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/merge_request_approvals.md b/doc/user/project/merge_requests/merge_request_approvals.md
index 887f563be51..1fcc09a9d8a 100644
--- a/doc/user/project/merge_requests/merge_request_approvals.md
+++ b/doc/user/project/merge_requests/merge_request_approvals.md
@@ -5,27 +5,28 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, concepts
---
-# Merge Request Approvals **(CORE)**
+# Merge Request Approvals **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/580) in GitLab Enterprise Edition 7.2. Available in GitLab Core and higher tiers.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/580) in GitLab Enterprise Edition 7.2. Available in GitLab Free and higher tiers.
> - 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.
-Code review is an essential practice of every successful project, and giving your
-approval once a merge request is in good shape is an important part of the review
+Code review is an essential practice of every successful project. Approving a
+merge request is an important part of the review
process, as it clearly communicates the ability to merge the change.
## Optional Approvals
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27426) in GitLab 13.2.
-Any user with Developer or greater [permissions](../../permissions.md) can approve a merge request in GitLab Core and higher tiers.
-This provides a consistent mechanism for reviewers to approve merge requests, and makes it easy for
-maintainers to know when a change is ready to merge. Approvals in Core are optional and do
+Any user with Developer or greater [permissions](../../permissions.md) can approve a merge request in GitLab Free and higher tiers.
+This provides a consistent mechanism for reviewers to approve merge requests, and ensures
+maintainers know a change is ready to merge. Approvals in Free are optional, and do
not prevent a merge request from being merged when there is no approval.
-## Required Approvals **(STARTER)**
+## Required Approvals **(PREMIUM)**
-> [Introduced](https://about.gitlab.com/releases/2015/06/22/gitlab-7-12-released/#merge-request-approvers-ee-only) in GitLab Enterprise Edition 7.12. Available in [GitLab Starter](https://about.gitlab.com/pricing/) and higher tiers.
+> - [Introduced](https://about.gitlab.com/releases/2015/06/22/gitlab-7-12-released/#merge-request-approvers-ee-only) in GitLab Enterprise Edition 7.12.
+> - Moved to GitLab Premium in 13.9.
Required approvals enable enforced code review by requiring specified people
to approve a merge request before it can be merged.
@@ -50,13 +51,12 @@ be merged, and optionally which users should do the approving. Approvals can be
- [As project defaults](#adding--editing-a-default-approval-rule).
- [Per merge request](#editing--overriding-approval-rules-per-merge-request).
-If no approval rules are defined, any user can approve a merge request, though the default
-minimum number of required approvers can still be set in the [project settings for merge request approvals](#merge-request-approvals-project-settings).
+If no approval rules are defined, any user can approve a merge request. However, the default
+minimum number of required approvers can still be set in the
+[project settings for merge request approvals](#merge-request-approvals-project-settings).
You can opt to define one single rule to approve a merge request among the available rules
-or choose more than one. Single approval rules are available in GitLab Starter and higher tiers,
-while [multiple approval rules](#multiple-approval-rules) are available in
-[GitLab Premium](https://about.gitlab.com/pricing/) and above.
+or choose more than one with [multiple approval rules](#multiple-approval-rules).
NOTE:
On GitLab.com, you can add a group as an approver if you're a member of that group or the
@@ -64,7 +64,7 @@ group is public.
#### Eligible Approvers
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10294) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.3, when an eligible approver comments on a merge request, it appears in the **Commented by** column of the Approvals widget.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10294) in GitLab 13.3, when an eligible approver comments on a merge request, it appears in the **Commented by** column of the Approvals widget.
The following users can approve merge requests:
@@ -83,29 +83,31 @@ A group of users can also be added as approvers. In the future, group approvers
[restricted to only groups with share access to the project](https://gitlab.com/gitlab-org/gitlab/-/issues/2048).
If a user is added as an individual approver and is also part of a group approver,
-then that user is just counted once. The merge request author, as well as users who have committed
+then that user is just counted once. The merge request author, and users who have committed
to the merge request, do not count as eligible approvers,
if [**Prevent author approval**](#allowing-merge-request-authors-to-approve-their-own-merge-requests) (enabled by default)
and [**Prevent committers approval**](#prevent-approval-of-merge-requests-by-their-committers) (disabled by default)
are enabled on the project settings.
-When an eligible approver comments on a merge request, it appears in the **Commented by** column of the Approvals widget,
-indicating who has engaged in the merge request review. Authors and reviewers can also easily identify who they should reach out
-to if they have any questions or inputs about the content of the merge request.
+When an eligible approver comments on a merge request, it displays in the
+**Commented by** column of the Approvals widget. It indicates who participated in
+the merge request review. Authors and reviewers can also identify who they should reach out
+to if they have any questions about the content of the merge request.
##### Implicit Approvers
If the number of required approvals is greater than the number of assigned approvers,
-approvals from other users will count towards meeting the requirement. These would be
+approvals from other users counts towards meeting the requirement. These would be
users with developer [permissions](../../permissions.md) or higher in the project who
were not explicitly listed in the approval rules.
##### Code Owners as eligible approvers
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7933) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7933) in GitLab 11.5.
+> - Moved to GitLab Premium in 13.9.
If you add [Code Owners](../code_owners.md) to your repository, the owners to the
-corresponding files will become eligible approvers, together with members with Developer
+corresponding files become eligible approvers, together with members with Developer
or higher [permissions](../../permissions.md).
To enable this merge request approval rule:
@@ -117,16 +119,17 @@ To enable this merge request approval rule:
![MR approvals by Code Owners](img/mr_approvals_by_code_owners_v12_7.png)
Once set, merge requests can only be merged once approved by the
-number of approvals you've set. GitLab will accept approvals from
+number of approvals you've set. GitLab accepts approvals from
users with Developer or higher permissions, as well as by Code Owners,
indistinguishably.
Alternatively, you can **require**
-[Code Owner's approvals for Protected Branches](../protected_branches.md#protected-branches-approval-by-code-owners). **(PREMIUM)**
+[Code Owner's approvals for protected branches](../protected_branches.md#protected-branches-approval-by-code-owners). **(PREMIUM)**
#### Merge Request approval segregation of duties
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in GitLab 13.4.
+> - Moved to Premium in 13.9.
Managers or operators with [Reporter permissions](../../permissions.md#project-members-permissions)
to a project sometimes need to be required approvers of a merge request,
@@ -156,27 +159,27 @@ To add or edit the default merge request approval rule:
1. Click **Add approval rule**, or **Edit**.
- Add or change the **Rule name**.
- Set the number of required approvals in **Approvals required**. The minimum value is `0`.
- - (Optional) Search for users or groups that will be [eligible to approve](#eligible-approvers)
+ - (Optional) Search for users or groups that are [eligible to approve](#eligible-approvers)
merge requests and click the **Add** button to add them as approvers. Before typing
- in the search field, approvers will be suggested based on the previous authors of
+ in the search field, approvers are suggested based on the previous authors of
the files being changed by the merge request.
- (Optional) Click the **{remove}** **Remove** button next to a group or user to delete it from
the rule.
1. Click **Add approval rule** or **Update approval rule**.
When [approval rule overrides](#prevent-overriding-default-approvals) are allowed,
-changes to these default rules will **not** be applied to existing merge
+changes to these default rules are not applied to existing merge
requests, except for changes to the [target branch](#scoped-to-protected-branch) of
the rule.
When approval rule overrides are not allowed, all changes to these default rules
-will be applied to existing merge requests. Any approval rules that had previously been
+are applied to existing merge requests. Any approval rules that had previously been
manually [overridden](#editing--overriding-approval-rules-per-merge-request) during a
-period when approval rule overrides where allowed, will not be modified.
+period when approval rule overrides where allowed, are not modified.
NOTE:
If a merge request targets a different project, such as from a fork to the upstream project,
-the default approval rules will be taken from the target (upstream) project, not the
+the default approval rules are taken from the target (upstream) project, not the
source (fork).
##### Editing / overriding approval rules per merge request
@@ -195,8 +198,8 @@ the same steps as [Adding / editing a default approval rule](#adding--editing-a-
#### Set up an optional approval rule
-MR approvals can be configured to be optional.
-This can be useful if you're working on a team where approvals are appreciated, but not required.
+MR approvals can be configured to be optional, which can help if you're working
+on a team where approvals are appreciated, but not required.
To configure an approval to be optional, set the number of required approvals in **Approvals required** to `0`.
@@ -211,20 +214,20 @@ as well as multiple default approval rules per project.
Adding or editing multiple default rules is identical to
[adding or editing a single default approval rule](#adding--editing-a-default-approval-rule),
-except the **Add approval rule** button will be available to add more rules, even after
+except the **Add approval rule** button is available to add more rules, even after
a rule is already defined.
Similarly, editing or overriding multiple approval rules per merge request is identical
to [editing or overriding approval rules per merge request](#editing--overriding-approval-rules-per-merge-request),
-except the **Add approval rule** button will be available to add more rules, even after
+except the **Add approval rule** button is available to add more rules, even after
a rule is already defined.
-When an [eligible approver](#eligible-approvers) approves a merge request, it will
-reduce the number of approvals left for all rules that the approver belongs to.
+When an [eligible approver](#eligible-approvers) approves a merge request, it
+reduces the number of approvals left for all rules that the approver belongs to.
![Approvals premium merge request widget](img/approvals_premium_mr_widget_v13_3.png)
-#### Scoped to Protected Branch **(PREMIUM)**
+#### Scoped to protected branch **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8.
@@ -236,7 +239,7 @@ the **Target branch** dropdown.
Alternatively, you can select a very specific protected branch from the **Target branch** dropdown:
-![Scoped to Protected Branch](img/scoped_to_protected_branch_v12_8.png)
+![Scoped to protected branch](img/scoped_to_protected_branch_v12_8.png)
To enable this configuration, see [Code Owner’s approvals for protected branches](../protected_branches.md#protected-branches-approval-by-code-owners).
@@ -269,7 +272,7 @@ The merge request author is not allowed to approve their own merge request if
[**Prevent author approval**](#allowing-merge-request-authors-to-approve-their-own-merge-requests)
is enabled in the project settings.
-Once the approval rules have been met, the merge request can be merged if there is nothing
+After the approval rules have been met, the merge request can be merged if there is nothing
else blocking it. Note that the merge request could still be blocked by other conditions,
such as merge conflicts, [pending discussions](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved),
or a [failed CI/CD pipeline](merge_when_pipeline_succeeds.md).
@@ -291,7 +294,7 @@ To prevent that from happening:
#### Resetting approvals on push
You can force all approvals on a merge request to be removed when new commits are
-pushed to the source branch of the merge request. If disabled, approvals will persist
+pushed to the source branch of the merge request. If disabled, approvals persist
even if there are changes added to the merge request. To enable this feature:
1. Check the **Require new approvals when new commits are added to an MR.**
@@ -300,11 +303,12 @@ even if there are changes added to the merge request. To enable this feature:
NOTE:
Approvals do not get reset when [rebasing a merge request](fast_forward_merge.md)
-from the UI. However, approvals will be reset if the target branch is changed.
+from the UI. However, approvals are reset if the target branch is changed.
-#### Allowing merge request authors to approve their own merge requests
+#### Allowing merge request authors to approve their own merge requests **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3349) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3349) in GitLab 11.3.
+> - Moved to GitLab Premium in 13.9.
By default, projects are configured to prevent merge requests from being approved by
their own authors. To change this setting:
@@ -315,24 +319,38 @@ their own authors. To change this setting:
Note that users can edit the approval rules in every merge request and override pre-defined settings unless it's set [**not to allow** overrides](#prevent-overriding-default-approvals).
-#### Prevent approval of merge requests by their committers
+You can prevent authors from approving their own merge requests
+[at the instance level](../../admin_area/merge_requests_approvals.md). When enabled,
+this setting is disabled on the project level, and not editable.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10441) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.10.
+#### Prevent approval of merge requests by their committers **(PREMIUM)**
-You can prevent users that have committed to a merge request from approving it. To
-enable this feature:
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10441) in GitLab 11.10.
+> - Moved to GitLab Premium in 13.9.
+
+You can prevent users who have committed to a merge request from approving it,
+though code authors can still approve. You can enable this feature
+[at the instance level](../../admin_area/merge_requests_approvals.md), which
+disables changes to this feature at the project level. If you prefer to manage
+this feature at the project level, you can:
1. Check the **Prevent MR approvals from users who make commits to the MR.** checkbox.
+ If this check box is disabled, this feature has been disabled
+ [at the instance level](../../admin_area/merge_requests_approvals.md).
1. Click **Save changes**.
+Read the official Git documentation for an explanation of the
+[differences between authors and committers](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History).
+
#### Require authentication when approving a merge request
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5981) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5981) in GitLab 12.0.
+> - Moved to GitLab Premium in 13.9.
NOTE:
To require authentication when approving a merge request, you must enable
**Password authentication enabled for web interface** under [sign-in restrictions](../../admin_area/settings/sign_in_restrictions.md#password-authentication-enabled).
-in the Admin area.
+in the Admin Area.
You can force the approver to enter a password in order to authenticate before adding
the approval. This enables an Electronic Signature for approvals such as the one defined
diff --git a/doc/user/project/merge_requests/merge_request_dependencies.md b/doc/user/project/merge_requests/merge_request_dependencies.md
index 4a596ed6139..646d77391a3 100644
--- a/doc/user/project/merge_requests/merge_request_dependencies.md
+++ b/doc/user/project/merge_requests/merge_request_dependencies.md
@@ -17,7 +17,7 @@ then it cannot be merged until its dependency is itself merged.
NOTE:
Merge requests dependencies are a **PREMIUM** feature, but this restriction is
-only enforced for the dependent merge request. A merge request in a **CORE** or
+only enforced for the dependent merge request. A merge request in a **FREE** or
**STARTER** project can be a dependency of a **PREMIUM** merge request, but not
vice-versa.
diff --git a/doc/user/project/merge_requests/merge_request_discussion_resolution.md b/doc/user/project/merge_requests/merge_request_discussion_resolution.md
deleted file mode 100644
index f8d15f31875..00000000000
--- a/doc/user/project/merge_requests/merge_request_discussion_resolution.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../discussions/index.md'
----
-
-This document was moved to [another location](../../discussions/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/merge_when_build_succeeds.md b/doc/user/project/merge_requests/merge_when_build_succeeds.md
deleted file mode 100644
index 48d32d2882f..00000000000
--- a/doc/user/project/merge_requests/merge_when_build_succeeds.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-redirect_to: 'merge_when_pipeline_succeeds.md'
----
-
-This document was moved to [merge_when_pipeline_succeeds](merge_when_pipeline_succeeds.md).
-
->[Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7135) by the "Rename MWBS service to Merge When Pipeline Succeeds" change.
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
index b813e4f7d28..d33a8e40aac 100644
--- a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Merge when pipeline succeeds
+# Merge when pipeline succeeds **(FREE)**
When reviewing a merge request that looks ready to merge but still has a
pipeline running, you can set it to merge automatically when the
@@ -42,8 +42,12 @@ complete, the merge is blocked until you resolve all existing threads.
## Only allow merge requests to be merged if the pipeline succeeds
-You can prevent merge requests from being merged if their pipeline did not succeed
-or if there are threads to be resolved. This works for both:
+You can prevent merge requests from being merged if:
+
+- No pipeline ran.
+- The pipeline did not succeed.
+
+This works for both:
- GitLab CI/CD pipelines
- Pipelines run from an [external CI integration](../integrations/overview.md#integrations-listing)
@@ -58,6 +62,7 @@ CI providers with this feature. To enable it, you must:
1. Press **Save** for the changes to take effect.
This setting also prevents merge requests from being merged if there is no pipeline.
+You should be careful to configure CI/CD so that pipelines run for every merge request.
### Limitations
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
index 99e70f35d6d..a53b5032e1d 100644
--- a/doc/user/project/merge_requests/resolve_conflicts.md
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -5,18 +5,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Merge request conflict resolution
+# Merge request conflict resolution **(FREE)**
Merge conflicts occur when two branches have different changes that cannot be
merged automatically.
-Git is able to automatically merge changes between branches in most cases, but
-there are situations where Git will require your assistance to resolve the
+Git can merge changes between branches in most cases, but
+occasionally Git requires your assistance to resolve the
conflicts manually. Typically, this is necessary when people change the same
parts of the same files.
-GitLab will prevent merge requests from being merged until all conflicts are
-resolved. Conflicts can be resolved locally, or in many cases within GitLab
+GitLab prevents merge requests from being merged until all conflicts are
+resolved. Conflicts can be resolved locally, or in many cases in GitLab
(see [conflicts available for resolution](#conflicts-available-for-resolution)
for information on when this is available).
@@ -24,35 +24,30 @@ for information on when this is available).
NOTE:
GitLab resolves conflicts by creating a merge commit in the source branch that
-is not automatically merged into the target branch. This allows the merge
-commit to be reviewed and tested before the changes are merged, preventing
+is not automatically merged into the target branch. The merge
+commit can be reviewed and tested before the changes are merged. This prevents
unintended changes entering the target branch without review or breaking the
build.
## Resolve conflicts: interactive mode
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5479) in GitLab 8.11.
-
-Clicking this will show a list of files with conflicts, with conflict sections
+Clicking **Resolve Conflicts** displays a list of files with conflicts, with conflict sections
highlighted:
![Conflict section](img/conflict_section.png)
-Once all conflicts have been marked as using 'ours' or 'theirs', the conflict
-can be resolved. This will perform a merge of the target branch of the merge
-request into the source branch, resolving the conflicts using the options
+After all conflicts have been marked as using 'ours' or 'theirs', the conflict
+can be resolved. Resolving conflicts merges the target branch of the merge
+request into the source branch, using the options
chosen. If the source branch is `feature` and the target branch is `master`,
this is similar to performing `git checkout feature; git merge master` locally.
## Resolve conflicts: inline editor
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6374) in GitLab 8.13.
-
-The merge conflict resolution editor allows for more complex merge conflicts,
-which require the user to manually modify a file in order to resolve a conflict,
-to be solved right form the GitLab interface. Use the **Edit inline** button
-to open the editor. Once you're sure about your changes, hit the
-**Commit to source branch** button.
+Some merge conflicts are more complex, requiring you to manually modify a file to
+resolve them. Use the merge conflict resolution editor to resolve complex
+conflicts in the GitLab interface. Click **Edit inline** to open the editor.
+After you're sure about your changes, click **Commit to source branch**.
![Merge conflict editor](img/merge_conflict_editor.png)
@@ -66,13 +61,16 @@ GitLab allows resolving conflicts in a file where all of the below are true:
- The file, with conflict markers added, is not over 200 KB in size
- The file exists under the same path in both branches
-If any file with conflicts in that merge request does not meet all of these
-criteria, the conflicts for that merge request cannot be resolved in the UI.
+If any file in your merge request containing conflicts can't meet all of these
+criteria, you can't resolve the merge conflict in the UI.
Additionally, GitLab does not detect conflicts in renames away from a path. For
-example, this will not create a conflict: on branch `a`, doing `git mv file1
-file2`; on branch `b`, doing `git mv file1 file3`. Instead, both files will be
-present in the branch after the merge request is merged.
+example, this does not create a conflict:
+
+1. On branch `a`, doing `git mv file1 file2`
+1. On branch `b`, doing `git mv file1 file3`.
+
+Instead, both files are present in the branch after the merge request is merged.
<!-- ## Troubleshooting
diff --git a/doc/user/project/merge_requests/revert_changes.md b/doc/user/project/merge_requests/revert_changes.md
index 40a4631694b..d5d0578c07c 100644
--- a/doc/user/project/merge_requests/revert_changes.md
+++ b/doc/user/project/merge_requests/revert_changes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Reverting changes
+# Reverting changes **(FREE)**
You can use Git's powerful feature to [revert any commit](https://git-scm.com/docs/git-revert "Git revert documentation")
by clicking the **Revert** button in merge requests and commit details.
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index e2d6ba9ea1c..94f48fa544f 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# Reviewing and managing merge requests **(CORE)**
+# Reviewing and managing merge requests **(FREE)**
Merge requests are the primary method of making changes to files in a GitLab project.
Changes are proposed by [creating and submitting a merge request](creating_merge_requests.md),
@@ -13,10 +13,10 @@ which is then reviewed, and accepted (or rejected).
## View project merge requests
-View all the merge requests within a project by navigating to **Project > Merge Requests**.
+View all the merge requests in a project by navigating to **Project > Merge Requests**.
-When you access your project's merge requests, GitLab will present them in a list,
-and you can use the tabs available to quickly filter by open and closed. You can also [search and filter the results](../../search/index.md#filtering-issue-and-merge-request-lists).
+When you access your project's merge requests, GitLab displays them in a list.
+Use the tabs to quickly filter by open and closed. You can also [search and filter the results](../../search/index.md#filtering-issue-and-merge-request-lists).
![Project merge requests list view](img/project_merge_requests_list_view_v13_5.png)
@@ -32,7 +32,7 @@ You can [search and filter the results](../../search/index.md#filtering-issue-an
A merge commit is created for every merge, but the branch is only merged if
a fast-forward merge is possible. This ensures that if the merge request build
-succeeded, the target branch build will also succeed after merging.
+succeeded, the target branch build also succeeds after the merge.
Navigate to a project's settings, select the **Merge commit with semi-linear history**
option under **Merge Requests: Merge method** and save your changes.
@@ -80,21 +80,23 @@ Click **Expand file** on any file to view the changes for that file.
> - [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.
-For larger merge requests it might sometimes be useful to review single files at a time. To enable,
-from your avatar on the top-right navigation bar, click **Settings**, and go to **Preferences** on the left
-sidebar. Scroll down to the **Behavior** section and select **Show one file at a time on merge request's Changes tab**.
-Click **Save changes** to apply.
+For larger merge requests, consider reviewing one file at a time. To enable this feature:
-From there, when reviewing merge requests' **Changes** tab, you will see only one file at a time. You can then click the buttons **Prev** and **Next** to view the other files changed.
+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. 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 click **Prev** and **Next** to view other changed files.
![File-by-file diff navigation](img/file_by_file_v13_2.png)
-From [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/233898) onwards, if you want to change
+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:
1. Go to the merge request's **Changes** tab.
-1. Click the cog icon (**{settings}**) to reveal the merge request's settings dropdown.
+1. Select the cog icon (**{settings}**) to reveal the merge request's settings dropdown.
1. Select or deselect the checkbox **Show one file at a time** to change the setting accordingly.
This change overrides the choice you made in your user preferences and persists until you clear your
@@ -104,10 +106,14 @@ browser's cookies or change this behavior again.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18140) in GitLab 13.0.
-To seamlessly navigate among commits in a merge request, from the **Commits** tab, click one of
-the commits to open the single-commit view. From there, you can navigate among the commits
-by clicking the **Prev** and **Next** buttons on the top-right of the page or by using the
-<kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts.
+To seamlessly navigate among commits in a merge request:
+
+1. Select the **Commits** tab.
+1. Select a commit to open it in the single-commit view.
+1. Navigate through the commits by either:
+
+ - Selecting **Prev** and **Next** buttons on the top-right of the page.
+ - Using the <kbd>X</kbd> and <kbd>C</kbd> keyboard shortcuts.
![Merge requests commit navigation](img/commit_nav_v13_4.png)
@@ -120,7 +126,7 @@ to expand the entire file.
![Incrementally expand merge request diffs](img/incrementally_expand_merge_request_diffs_v12_2.png)
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205401) in GitLab 13.1, when viewing a
+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 clicking **Show file contents**.
@@ -136,24 +142,60 @@ NOTE:
You can append `?w=1` while on the diffs page of a merge request to ignore any
whitespace changes.
+## Mark files as viewed
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513) in GitLab 13.9.
+> - It's deployed behind a feature flag, enabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-file-views). **(FREE SELF)**
+
+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.
+
+To mark a file as viewed:
+
+1. Go to the merge request's **Diffs** tab.
+1. On the right-top of the file, locate the **Viewed** checkbox.
+1. Check it to mark the file as viewed.
+
+Once checked, the file remains marked for that reviewer unless there are newly introduced
+changes to its content or the checkbox is unchecked.
+
+### Enable or disable file views **(FREE SELF)**
+
+The file view feature is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can opt to enable it for your instance.
+
+To enable it:
+
+```ruby
+Feature.enable(:local_file_reviews)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:local_file_reviews)
+```
+
## Perform inline code reviews
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13950) in GitLab 11.5.
-GitLab provides a way of leaving comments in any part of the file being changed
-in a Merge Request. To do so, click the **{comment}** **comment** icon in the gutter of the Merge Request diff UI to expand the diff lines and leave a comment, just as you would for a changed line.
+In a merge request, you can leave comments in any part of the file being changed.
+In the Merge Request Diff UI, click the **{comment}** **comment** icon in the gutter
+to expand the diff lines and leave a comment, just as you would for a changed line.
![Comment on any diff file line](img/comment-on-any-diff-line.png)
### Commenting on multiple lines
> - [Introduced](https://gitlab.com/gitlab-org/ux-research/-/issues/870) in GitLab 13.2.
-> - It's deployed behind a feature flag, enabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221268) on GitLab 13.3.
-> - It's enabled on GitLab.com.
-> - It can be disabled or enabled per-project.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiline-comments). **(CORE ONLY)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299121) in GitLab 13.9.
GitLab provides a way to select which lines of code a comment refers to. After starting a comment
a dropdown selector is shown to select the first line that this comment refers to.
@@ -169,53 +211,33 @@ above it.
![Multiline comment selection displayed above comment](img/multiline-comment-saved.png)
-### Enable or disable multiline comments **(CORE ONLY)**
-
-The multiline comments feature is under development but 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 opt to enable it for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:multiline_comments)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:multiline_comments)
-```
-
## Pipeline status in merge requests widgets
If you've set up [GitLab CI/CD](../../../ci/README.md) in your project,
-you will be able to see:
+you can see:
- Both pre-merge and post-merge pipelines and the environment information if any.
- Which deployments are in progress.
-If there's an [environment](../../../ci/environments/index.md) and the application is
-successfully deployed to it, the deployed environment and the link to the
-Review App will be shown as well.
+If an application is successfully deployed to an
+[environment](../../../ci/environments/index.md), the deployed environment and the link to the
+Review App are both shown.
NOTE:
-When the default branch (for example, `main`) is red due to a failed CI pipeline, the `merge` button
-When the pipeline fails in a merge request but it can be merged nonetheless,
-the **Merge** button will be colored in red.
+When the pipeline fails in a merge request but it can still be merged,
+the **Merge** button is colored red.
### Post-merge pipeline status
When a merge request is merged, you can see the post-merge pipeline status of
the branch the merge request was merged into. For example, when a merge request
-is merged into the master branch and then triggers a deployment to the staging
+is merged into the `master` branch and then triggers a deployment to the staging
environment.
-Deployments that are ongoing will be shown, as well as the deploying/deployed state
+Ongoing deployments are shown, and the state (deploying or deployed)
for environments. If it's the first time the branch is deployed, the link
-will return a `404` error until done. During the deployment, the stop button will
-be disabled. If the pipeline fails to deploy, the deployment information will be hidden.
+returns a `404` error until done. During the deployment, the stop button is
+disabled. If the pipeline fails to deploy, the deployment information is hidden.
![Merge request pipeline](img/merge_request_pipeline.png)
@@ -223,14 +245,15 @@ For more information, [read about pipelines](../../../ci/pipelines/index.md).
### Merge when pipeline succeeds (MWPS)
-Set a merge request that looks ready to merge to [merge automatically when CI pipeline succeeds](merge_when_pipeline_succeeds.md).
+Set a merge request that looks ready to merge to
+[merge automatically when CI pipeline succeeds](merge_when_pipeline_succeeds.md).
### Live preview with Review Apps
If you configured [Review Apps](https://about.gitlab.com/stages-devops-lifecycle/review-apps/) for your project,
-you can preview the changes submitted to a feature-branch through a merge request
-in a per-branch basis. No need to checkout the branch, install and preview locally;
-all your changes will be available to preview by anyone with the Review Apps link.
+you can preview the changes submitted to a feature branch through a merge request
+on a per-branch basis. You don't need to checkout the branch, install, and preview locally.
+All your changes are available to preview by anyone with the Review Apps link.
With GitLab [Route Maps](../../../ci/review_apps/index.md#route-maps) set, the
merge request widget takes you directly to the pages changed, making it easier and
@@ -240,21 +263,26 @@ faster to preview proposed modifications.
## Associated features
-There is also a large number of features to associated to merge requests:
-
-| Feature | Description |
-|-------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Bulk editing merge requests](../../project/bulk_editing.md) | Update the attributes of multiple merge requests simultaneously. |
-| [Cherry-pick changes](cherry_pick_changes.md) | Cherry-pick any commit in the UI by simply clicking the **Cherry-pick** button in a merged merge requests or a commit. |
-| [Fast-forward merge requests](fast_forward_merge.md) | For a linear Git history and a way to accept merge requests without creating merge commits |
-| [Find the merge request that introduced a change](versions.md) | When viewing the commit details page, GitLab will link to the merge request(s) containing that commit. |
-| [Merge requests versions](versions.md) | Select and compare the different versions of merge request diffs |
-| [Resolve conflicts](resolve_conflicts.md) | GitLab can provide the option to resolve certain merge request conflicts in the GitLab UI. |
-| [Revert changes](revert_changes.md) | Revert changes from any commit from within a merge request. |
+These features are associated with merge requests:
+
+- [Bulk editing merge requests](../../project/bulk_editing.md):
+ Update the attributes of multiple merge requests simultaneously.
+- [Cherry-pick changes](cherry_pick_changes.md):
+ Cherry-pick any commit in the UI by clicking the **Cherry-pick** button in a merged merge requests or a commit.
+- [Fast-forward merge requests](fast_forward_merge.md):
+ For a linear Git history and a way to accept merge requests without creating merge commits
+- [Find the merge request that introduced a change](versions.md):
+ When viewing the commit details page, GitLab links to the merge request(s) containing that commit.
+- [Merge requests versions](versions.md):
+ Select and compare the different versions of merge request diffs
+- [Resolve conflicts](resolve_conflicts.md):
+ GitLab can provide the option to resolve certain merge request conflicts in the GitLab UI.
+- [Revert changes](revert_changes.md):
+ Revert changes from any commit from a merge request.
## Troubleshooting
-Sometimes things don't go as expected in a merge request, here are some
+Sometimes things don't go as expected in a merge request. Here are some
troubleshooting steps.
### Merge request cannot retrieve the pipeline status
@@ -264,7 +292,7 @@ This can occur if Sidekiq doesn't pick up the changes fast enough.
#### Sidekiq
Sidekiq didn't process the CI state change fast enough. Please wait a few
-seconds and the status will update automatically.
+seconds and the status should update automatically.
#### Bug
@@ -280,12 +308,9 @@ Merge Request again.
## Tips
-Here are some tips that will help you be more efficient with merge requests in
+Here are some tips to help you be more efficient with merge requests in
the command line.
-NOTE:
-This section might move in its own document in the future.
-
### Copy the branch name for local checkout
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23767) in GitLab 13.4.
@@ -294,7 +319,7 @@ The merge request sidebar contains the branch reference for the source branch
used to contribute changes for this merge request.
To copy the branch reference into your clipboard, click the **Copy branch name** button
-(**{copy-to-clipboard}**) in the right sidebar. You can then use it to checkout the branch locally
+(**{copy-to-clipboard}**) in the right sidebar. Use it to checkout the branch locally
via command line by running `git checkout <branch-name>`.
### Checkout merge requests locally through the `head` ref
@@ -303,7 +328,7 @@ A merge request contains all the history from a repository, plus the additional
commits added to the branch associated with the merge request. Here's a few
ways to checkout a merge request locally.
-Please note that you can checkout a merge request locally even if the source
+You can checkout a merge request locally even if the source
project is a fork (even a private fork) of the target project.
This relies on the merge request `head` ref (`refs/merge-requests/:iid/head`)
@@ -312,10 +337,10 @@ request via its ID instead of its branch.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223156) in GitLab
13.4, 14 days after a merge request gets closed or merged, the merge request
-`head` ref will be deleted. This means that the merge request will not be available
+`head` ref is deleted. This means that the merge request is not available
for local checkout via the merge request `head` ref anymore. The merge request
-can still be re-opened. Also, as long as the merge request's branch
-exists, you can still check out the branch as it won't be affected.
+can still be re-opened. If the merge request's branch
+exists, you can still check out the branch, as it isn't affected.
#### Checkout locally by adding a Git alias
@@ -334,7 +359,7 @@ from the `origin` remote, do:
git mr origin 5
```
-This will fetch the merge request into a local `mr-origin-5` branch and check
+This fetches the merge request into a local `mr-origin-5` branch and check
it out.
#### Checkout locally by modifying `.git/config` for a given repository
diff --git a/doc/user/project/merge_requests/sast.md b/doc/user/project/merge_requests/sast.md
deleted file mode 100644
index 11f85749fb7..00000000000
--- a/doc/user/project/merge_requests/sast.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../application_security/sast/index.md'
----
-
-This document was moved to [another location](../../application_security/sast/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/sast_docker.md b/doc/user/project/merge_requests/sast_docker.md
deleted file mode 100644
index 5d61f2b36e8..00000000000
--- a/doc/user/project/merge_requests/sast_docker.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../application_security/container_scanning/index.md'
----
-
-This document was moved to [another location](../../application_security/container_scanning/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 93b85ce8669..1b99b1b5c44 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -5,10 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Squash and merge
+# Squash and merge **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1024) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.17.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) from [GitLab Starter](https://about.gitlab.com/pricing/)to GitLab Core in 11.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) from [GitLab Starter](https://about.gitlab.com/pricing/)to GitLab Free in 11.0.
With squash and merge you can combine all your merge request's commits into one
and retain a clean history.
@@ -110,7 +110,6 @@ squashing can itself be considered equivalent to rebasing.
> - It's enabled on GitLab.com.
> - It can be enabled per project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-squash-commit-options). **(CORE ONLY)**
With Squash Commits Options you can configure the behavior of Squash and Merge for your project.
To set it up, navigate to your project's **Settings > General** and expand **Merge requests**.
@@ -133,31 +132,6 @@ NOTE:
If your project is set to **Do not allow** Squash and Merge, the users still have the option to
squash commits locally through the command line and force-push to their remote branch before merging.
-### Enable or disable Squash Commit Options **(CORE ONLY)**
-
-Squash Commit Options is under development but ready for production use. It is
-deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to disable it.
-
-To enable it:
-
-```ruby
-# Instance-wide
-Feature.enable(:squash_options)
-# or by project
-Feature.enable(:squash_options, Project.find(<project ID>))
-```
-
-To disable it:
-
-```ruby
-# Instance-wide
-Feature.disable(:squash_options)
-# or by project
-Feature.disable(:squash_options, Project.find(<project ID>))
-```
-
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index 3960f916f9b..e60f2f712d3 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -52,7 +52,52 @@ Hovering over the coverage bar will provide further information, such as the num
of times the line was checked by tests.
NOTE:
-The Cobertura XML parser currently does not support the `sources` element and ignores it. It is assumed that
+A limit of 100 `<source>` nodes for Cobertura format XML files applies. If your Cobertura report exceeds
+100 nodes, there can be mismatches or no matches in the Merge Request diff view.
+
+### Automatic class path correction
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217664) in GitLab 13.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284822) in GitLab 13.9.
+
+For the coverage report to properly match the files displayed on a merge request diff, the `filename` of a `class` element
+must contain the full path relative to the project root. But in some coverage analysis frameworks, the generated
+Cobertura XML has the `filename` path relative to the class package directory instead.
+
+To make an intelligent guess on the project root relative `class` path, the Cobertura XML parser will attempt to build the
+full path by doing following:
+
+1. Extract a portion of the `source` paths from the `sources` element and combine them with the class `filename` path.
+1. Check if the candidate path exists in the project.
+1. Use the first candidate that matches as the class full path.
+
+As an example scenario, given the project's full path is `test-org/test-project`, and has the following file tree relative
+to the project root:
+
+```shell
+Auth/User.cs
+Lib/Utils/User.cs
+```
+
+And the `sources` from Cobertura XML with paths in the format of `<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...`:
+
+```xml
+<sources>
+ <source>/builds/test-org/test-project/Auth</source>
+ <source>/builds/test-org/test-project/Lib/Utils</source>
+</sources>
+```
+
+The parser will extract `Auth` and `Lib/Utils` from the sources and use these as basis to determine the class path relative to
+the project root, combining these extracted sources and the class filename.
+
+If for example there is a `class` element with the `filename` value of `User.cs`, the parser will take the first candidate path
+that matches which is `Auth/User.cs`.
+
+For each `class` element, the parser will attempt to look for a match for each extracted `source` path up to `100` iterations. If it reaches this limit without finding a matching path in the file tree, the class will not be included in the final coverage report.
+
+NOTE:
+The automatic class path correction only works on `source` paths in the format of `<CI_BUILDS_DIR>/<PROJECT_FULL_PATH>/...`. If `source` will be ignored if the path does not follow this pattern. The parser will assume that
the `filename` of a `class` element contains the full path relative to the project root.
## Example test coverage configurations
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 4ad960413ef..8f3ce9186f1 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -64,9 +64,10 @@ In GitLab 12.10, we added a comparison mode, which
shows a diff calculated by simulating how it would look like once merged - a more accurate
representation of the changes rather than using the base of the two
branches. The new mode is available from the comparison target drop down
-by selecting **master (HEAD)**. In the future it will
-[replace](https://gitlab.com/gitlab-org/gitlab/-/issues/198458) the
-current default comparison.
+by selecting **master (HEAD)**. In GitLab 13.9, it
+[replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/198458) the
+old default comparison. For technical details, additional information is available in the
+[developer documentation](../../../development/diffs.md#merge-request-diffs-against-the-head-of-the-target-branch).
![Merge request versions compare HEAD](img/versions_compare_head_v12_10.png)
diff --git a/doc/user/project/merge_requests/work_in_progress_merge_requests.md b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
index 7417320eea0..43ab03114fa 100644
--- a/doc/user/project/merge_requests/work_in_progress_merge_requests.md
+++ b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
@@ -5,12 +5,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, concepts
---
-# Draft merge requests **(CORE)**
+# Draft merge requests **(FREE)**
If a merge request is not yet ready to be merged, perhaps due to continued development
or open threads, you can prevent it from being accepted before it's ready by flagging
-it as a **Draft**. This will disable the "Merge" button, preventing it from
-being merged, and it will stay disabled until the "Draft" flag has been removed.
+it as a **Draft**. This disables the **Merge** button, preventing it from
+being merged. It stays disabled until the **Draft** flag has been removed.
![Blocked Merge Button](img/draft_blocked_merge_button_v13_2.png)
@@ -22,7 +22,7 @@ To run pipelines for merged results, you must [remove the draft status](#removin
## Adding the "Draft" flag to a merge request
-> - [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** will be removed 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**. Support for using **WIP** is scheduled for removal in GitLab 14.0.
> - **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:
@@ -30,15 +30,15 @@ There are several ways to flag a merge request as a Draft:
- Click the **Mark as draft** button on the top-right corner of the merge request's page.
- Add `[Draft]`, `Draft:` or `(Draft)` to the start of the merge request's title. Clicking on
**Start the title with Draft:**, under the title box, when editing the merge request's
- description will have the same effect.
+ description has the same effect.
- **Deprecated** Add `[WIP]` or `WIP:` to the start of the merge request's title.
- **WIP** still works but was deprecated in favor of **Draft**. It will be removed in the next major version (GitLab 14.0).
+ **WIP** still works but was deprecated in favor of **Draft**. It is scheduled for removal in the next major version (GitLab 14.0).
- Add the `/draft` (or `/wip`) [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics)
in a comment in the merge request. This is a toggle, and can be repeated
- to change the status back. Note that any other text in the comment will be discarded.
+ to change the status back. Note that any other text in the comment is discarded.
- Add `draft:`, `Draft:`, `fixup!`, or `Fixup!` to the beginning of a commit message targeting the
merge request's source branch. This is not a toggle, and doing it again in another
- commit will have no effect.
+ commit has no effect.
## Removing the "Draft" flag from a merge request
@@ -48,10 +48,10 @@ Similar to above, when a Merge Request is ready to be merged, you can remove the
- Click the **Mark as ready** button on the top-right corner of the merge request's page.
- Remove `[Draft]`, `Draft:` or `(Draft)` from the start of the merge request's title. Clicking on
**Remove the Draft: prefix from the title**, under the title box, when editing the merge
- request's description, will have the same effect.
+ request's description, has the same effect.
- Add the `/draft` (or `/wip`) [quick action](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics)
in a comment in the merge request. This is a toggle, and can be repeated
- to change the status back. Note that any other text in the comment will be discarded.
+ to change the status back. Note that any other text in the comment is discarded.
- Click on the **Resolve Draft status** button near the bottom of the merge request description,
next to the **Merge** button (see [image above](#draft-merge-requests)).
Must have at least Developer level permissions on the project for the button to
@@ -60,8 +60,8 @@ Similar to above, when a Merge Request is ready to be merged, you can remove the
## Including/excluding WIP merge requests when searching
When viewing/searching the merge requests list, you can choose to include or exclude
-WIP merge requests by adding a "WIP" filter in the search box, and choosing "Yes"
-(to include) or "No" (to exclude).
+WIP merge requests. Add a **WIP** filter in the search box, and choose **Yes**
+to include, or **No** to exclude.
![Filter WIP MRs](img/filter_wip_merge_requests.png)
diff --git a/doc/user/project/milestones/burndown_and_burnup_charts.md b/doc/user/project/milestones/burndown_and_burnup_charts.md
index 3e266d054be..7c22b271ec2 100644
--- a/doc/user/project/milestones/burndown_and_burnup_charts.md
+++ b/doc/user/project/milestones/burndown_and_burnup_charts.md
@@ -5,18 +5,17 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Burndown and burnup charts **(STARTER)**
+# Burndown and burnup charts **(PREMIUM)**
[Burndown](#burndown-charts) and [burnup](#burnup-charts) charts show the progress of completing a milestone.
![burndown and burnup chart](img/burndown_and_burnup_charts_v13_6.png)
-## Burndown charts
+## Burndown charts **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1540) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.1 for project milestones.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5354) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.8 for group milestones.
-> - [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6495) to [GitLab Starter](https://about.gitlab.com/pricing/) 11.2 for group milestones.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) [fixed burndown charts](#fixed-burndown-charts) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6.
+> - [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.
+> - Moved to GitLab Premium in 13.9.
Burndown charts show the number of issues over the course of a milestone.
@@ -101,10 +100,11 @@ 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
+## Burnup charts **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268350) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.7.
+> - [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.
+> - Moved to GitLab Premium in 13.9.
Burnup charts show the assigned and completed work for a milestone.
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index acf32bb0f92..fe34dca4959 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -5,7 +5,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Milestones **(CORE)**
+# Milestones **(FREE)**
Milestones in GitLab are a way to track issues and merge requests created to achieve a broader goal in a certain period of time.
@@ -123,10 +123,16 @@ From the project and group issue/merge request list pages, you can [filter](../.
### Filtering in issue boards
-- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [search and filter bar](../../search/index.md#issue-boards).
-- From [group issue boards](../issue_board.md#group-issue-boards), you can filter by only group milestones in the [search and filter bar](../../search/index.md#issue-boards). **(PREMIUM)**
-- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards). **(STARTER)**
-- From [group issue boards](../issue_board.md#group-issue-boards) you can filter by only group milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards). **(STARTER)**
+From [project issue boards](../issue_board.md), you can filter by both group milestones and project
+milestones in:
+
+- [Search and filter bar](../../search/index.md#issue-boards)
+- [Issue board configuration](../issue_board.md#configurable-issue-boards)
+
+From [group issue boards](../issue_board.md#group-issue-boards), you can filter by only group milestones in:
+
+- [Search and filter bar](../../search/index.md#issue-boards)
+- [Issue board configuration](../issue_board.md#configurable-issue-boards)
### Special milestone filters
@@ -155,15 +161,17 @@ There are also tabs below these that show the following:
- **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 **(STARTER)**
+### Project Burndown Charts
-For project milestones in [GitLab Starter](https://about.gitlab.com/pricing/), a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view, showing the progress of completing a milestone.
+For project 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_chart_v13_6.png)
-### Group Burndown Charts **(STARTER)**
+### Group Burndown Charts
-For group milestones in [GitLab Starter](https://about.gitlab.com/pricing/), a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view, showing the progress of completing a milestone.
+For group milestones, a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view,
+showing the progress of completing a milestone.
### Milestone sidebar
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 4910751ece1..585d97c74c2 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -195,7 +195,7 @@ As a user:
### Dependent repositories
-The [Job environment variable](../../ci/variables/README.md#predefined-environment-variables) `CI_JOB_TOKEN` can be used to
+The [CI/CD variable](../../ci/variables/README.md#predefined-cicd-variables) `CI_JOB_TOKEN` can be used to
authenticate any clones of dependent repositories. For example:
```shell
diff --git a/doc/user/project/operations/alert_management.md b/doc/user/project/operations/alert_management.md
deleted file mode 100644
index e60e7d93d12..00000000000
--- a/doc/user/project/operations/alert_management.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/incident_management/index.md'
----
-
-This document was moved to [another location](../../../operations/incident_management/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/operations/dashboard_settings.md b/doc/user/project/operations/dashboard_settings.md
deleted file mode 100644
index ef106181acc..00000000000
--- a/doc/user/project/operations/dashboard_settings.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/metrics/dashboards/settings.md'
----
-
-This document was moved to [another location](../../../operations/metrics/dashboards/settings.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/operations/error_tracking.md b/doc/user/project/operations/error_tracking.md
deleted file mode 100644
index 399ab0d53dc..00000000000
--- a/doc/user/project/operations/error_tracking.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/error_tracking.md'
----
-
-This document was moved to [another location](../../../operations/error_tracking.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/operations/feature_flags.md b/doc/user/project/operations/feature_flags.md
deleted file mode 100644
index 03f2cad6d78..00000000000
--- a/doc/user/project/operations/feature_flags.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/feature_flags.md'
----
-
-This document was moved to [another location](../../../operations/feature_flags.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/operations/index.md b/doc/user/project/operations/index.md
deleted file mode 100644
index d19cf393883..00000000000
--- a/doc/user/project/operations/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/index.md'
----
-
-This document was moved to [another location](../../../operations/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/operations/linking_to_an_external_dashboard.md b/doc/user/project/operations/linking_to_an_external_dashboard.md
deleted file mode 100644
index ef106181acc..00000000000
--- a/doc/user/project/operations/linking_to_an_external_dashboard.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/metrics/dashboards/settings.md'
----
-
-This document was moved to [another location](../../../operations/metrics/dashboards/settings.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/operations/tracing.md b/doc/user/project/operations/tracing.md
deleted file mode 100644
index dcf9894f9e1..00000000000
--- a/doc/user/project/operations/tracing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/tracing.md'
----
-
-This document was moved to [another location](../../../operations/tracing.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/packages/maven.md b/doc/user/project/packages/maven.md
deleted file mode 100644
index 13b5d69586a..00000000000
--- a/doc/user/project/packages/maven.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../packages/maven_repository/index.md'
----
-
-This document was moved to [another location](../../packages/maven_repository/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/packages/maven_packages.md b/doc/user/project/packages/maven_packages.md
deleted file mode 100644
index 13b5d69586a..00000000000
--- a/doc/user/project/packages/maven_packages.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../packages/maven_repository/index.md'
----
-
-This document was moved to [another location](../../packages/maven_repository/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/packages/maven_repository.md b/doc/user/project/packages/maven_repository.md
deleted file mode 100644
index 13b5d69586a..00000000000
--- a/doc/user/project/packages/maven_repository.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../packages/maven_repository/index.md'
----
-
-This document was moved to [another location](../../packages/maven_repository/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/packages/npm_registry.md b/doc/user/project/packages/npm_registry.md
deleted file mode 100644
index f874b05e7e2..00000000000
--- a/doc/user/project/packages/npm_registry.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../packages/npm_registry/index.md'
----
-
-This document was moved to [another location](../../packages/npm_registry/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
index aa06a15a8c0..86e34842aaf 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
@@ -19,7 +19,7 @@ GitLab does it for you, out-of-the-box.
open source Certificate Authority.
WARNING:
-This feature covers only certificates for **custom domains**, not the wildcard certificate required to run [Pages daemon](../../../../administration/pages/index.md) **(CORE ONLY)**. Wildcard certificate generation is tracked in [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3342).
+This feature covers only certificates for **custom domains**, not the wildcard certificate required to run [Pages daemon](../../../../administration/pages/index.md) **(FREE SELF)**. Wildcard certificate generation is tracked in [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3342).
## Requirements
@@ -28,7 +28,8 @@ Before you can enable automatic provisioning of an SSL certificate for your doma
- Created a [project](../index.md#getting-started) in GitLab
containing your website's source code.
- Acquired a domain (`example.com`) and added a [DNS entry](index.md)
- pointing it to your Pages website.
+ pointing it to your Pages website. The top-level domain (`.com`) must be a
+ [public suffix](https://publicsuffix.org/).
- [Added your domain to your Pages project](index.md#1-add-a-custom-domain-to-pages)
and verified your ownership.
- Verified your website is up and running, accessible through your custom domain.
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
index e8c6305dbab..d9f57253396 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
@@ -32,7 +32,9 @@ nor credit card transactions, then why do we need secure connections?
Back in the 1990s, where HTTPS came out, [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security#SSL_1.0.2C_2.0_and_3.0) was considered a "special"
security measure, necessary just for big companies like banks and shopping sites
with financial transactions.
+<!-- vale gitlab.Spelling = NO -->
Now we have a different picture. [According to Josh Aas](https://letsencrypt.org/2015/10/29/phishing-and-malware.html), Executive Director at [ISRG](https://en.wikipedia.org/wiki/Internet_Security_Research_Group):
+<!-- vale gitlab.rulename = YES -->
> _We’ve since come to realize that HTTPS is important for almost all websites. It’s important for any website that allows people to log in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn’t want its content altered](https://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We’ve also learned that any site not secured by HTTPS [can be used to attack other sites](https://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
diff --git a/doc/user/project/pages/getting_started/fork_sample_project.md b/doc/user/project/pages/getting_started/fork_sample_project.md
deleted file mode 100644
index 2cf118c9066..00000000000
--- a/doc/user/project/pages/getting_started/fork_sample_project.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'pages_forked_sample_project.md'
----
-
-This document was moved to [pages_forked_sample_project.md](pages_forked_sample_project.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/getting_started/new_or_existing_website.md b/doc/user/project/pages/getting_started/new_or_existing_website.md
deleted file mode 100644
index 2fc833fbd34..00000000000
--- a/doc/user/project/pages/getting_started/new_or_existing_website.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'pages_ci_cd_template.md'
----
-
-This document was moved to [another location](pages_ci_cd_template.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/getting_started/pages_bundled_template.md b/doc/user/project/pages/getting_started/pages_bundled_template.md
deleted file mode 100644
index 0dab1f6ee19..00000000000
--- a/doc/user/project/pages/getting_started/pages_bundled_template.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'pages_new_project_template.md'
----
-
-This document was moved to [pages_new_project_template.md](pages_new_project_template.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/getting_started/pages_forked_sample_project.md b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
index c7916b7c01e..d9ec2aae2b7 100644
--- a/doc/user/project/pages/getting_started/pages_forked_sample_project.md
+++ b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
@@ -18,7 +18,7 @@ configured to generate a Pages site.
To fork a sample project and create a Pages website:
1. View the sample projects by navigating to the [GitLab Pages examples](https://gitlab.com/pages) group.
-1. Click the name of the project you want to [fork](../../../../gitlab-basics/fork-project.md).
+1. Click the name of the project you want to [fork](../../../../user/project/working_with_projects.md#fork-a-project).
1. In the top right, click the **Fork** button, and then choose a namespace to fork to.
1. Go to your project's **CI/CD > Pipelines** and click **Run pipeline**.
GitLab CI/CD builds and deploys your site.
@@ -52,5 +52,5 @@ You can take some **optional** further steps:
![Change repository's path](../img/change_path_v12_10.png)
- - Now go to your SSG's configuration file and change the [base URL](../getting_started_part_one.md#urls-and-baseurls)
+ - Now go to your SSG's configuration file and change the [base URL](../getting_started_part_one.md#urls-and-base-urls)
from `"project-name"` to `""`. The project name setting varies by SSG and may not be in the configuration file.
diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md
deleted file mode 100644
index 361323a9073..00000000000
--- a/doc/user/project/pages/getting_started_part_four.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'getting_started/pages_from_scratch.md'
----
-
-This document was moved to [getting_started/pages_from_scratch.md](getting_started/pages_from_scratch.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 801fe0c7ef0..dee021b8225 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -4,7 +4,7 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab Pages domain names, URLs, and baseurls
+# GitLab Pages domain names, URLs, and base URLs
On this document, learn how to name your project for GitLab Pages
according to your intended website's URL.
@@ -78,7 +78,7 @@ To understand Pages domains clearly, read the examples below.
- On your GitLab instance, replace `gitlab.io` above with your
Pages server domain. Ask your sysadmin for this information.
-## URLs and baseurls
+## URLs and base URLs
NOTE:
The `baseurl` option might be called named differently in some static site generators.
diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md
deleted file mode 100644
index 9d7f401ca91..00000000000
--- a/doc/user/project/pages/getting_started_part_three.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'custom_domains_ssl_tls_certification/index.md'
----
-
-This document was moved to [another location](custom_domains_ssl_tls_certification/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
deleted file mode 100644
index 4b2b186ca28..00000000000
--- a/doc/user/project/pages/getting_started_part_two.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'index.md'
----
-
-This document was moved to [another location](index.md#getting-started).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index c9e28bf15c2..6eb06972945 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -103,7 +103,7 @@ optionally secure it with SSL/TLS certificates.
If you're using GitLab.com, your website is publicly available to the internet.
To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md).
-If you're using a self-managed instance (Core, Starter, Premium, or Ultimate),
+If you're using a self-managed instance (Free, Premium, or Ultimate),
your websites are published on your own server, according to the
[Pages settings](../../../administration/pages/index.md) chosen by your sysadmin,
who can make them public or internal.
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 8380f367212..fbc86abbe66 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 **(CORE)**
+## GitLab Pages Access Control **(FREE)**
To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md).
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
index a2a17a4f2ca..2e0fc87b3df 100644
--- a/doc/user/project/pages/pages_access_control.md
+++ b/doc/user/project/pages/pages_access_control.md
@@ -38,7 +38,9 @@ For a demonstration, see [Pages access controls](https://www.youtube.com/watch?v
- **Only project members**: Only project members are able to browse the website.
- **Everyone with access**: Everyone, both logged into and logged out of GitLab, is able to browse the website, no matter their project membership.
-1. Click **Save changes**.
+1. Click **Save changes**. Note that your changes may not take effect immediately. GitLab Pages uses
+ a caching mechanism for efficiency. Your changes may not take effect until that cache is
+ invalidated, which usually takes less than a minute.
The next time someone tries to access your website and the access control is
enabled, they're presented with a page to sign into GitLab and verify they
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
deleted file mode 100644
index cf5f33534cd..00000000000
--- a/doc/user/project/pipelines/job_artifacts.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../ci/pipelines/job_artifacts.md'
----
-
-This document was moved to [another location](../../../ci/pipelines/job_artifacts.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md
deleted file mode 100644
index 52352a29c5a..00000000000
--- a/doc/user/project/pipelines/schedules.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../ci/pipelines/schedules.md'
----
-
-This document was moved to [another location](../../../ci/pipelines/schedules.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pipelines/settings.md b/doc/user/project/pipelines/settings.md
deleted file mode 100644
index f19f28743a8..00000000000
--- a/doc/user/project/pipelines/settings.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../ci/pipelines/settings.md'
----
-
-This document was moved to [another location](../../../ci/pipelines/settings.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index 5754a3b7a9d..4629c87f41e 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Protected branches
+# Protected branches **(FREE)**
[Permissions](../permissions.md) in GitLab are fundamentally defined around the
idea of having read or write permission to the repository and branches. To impose
@@ -13,7 +13,7 @@ further restrictions on certain branches, they can be protected.
## Overview
-By default, a protected branch does four simple things:
+By default, a protected branch does these things:
- It prevents its creation, if not already created, from everybody except users
with Maintainer permission.
@@ -21,66 +21,69 @@ By default, a protected branch does four simple things:
- It prevents **anyone** from force pushing to the branch.
- It prevents **anyone** from deleting the branch.
-NOTE:
-A GitLab administrator is allowed to push to the protected branches.
+**Permissions:**
-See the [Changelog](#changelog) section for changes over time.
+- GitLab administrators are allowed to push to the protected branches.
+- Users with [Developer permissions](../permissions.md) are allowed to
+ create a project in a group, but might not be allowed to initially
+ push to the [default branch](repository/branches/index.md#default-branch).
The default branch protection level is set in the [Admin Area](../admin_area/settings/visibility_and_access_controls.md#default-branch-protection).
+See the [Changelog](#changelog) section for changes over time.
+
## Configuring protected branches
-To protect a branch, you need to have at least Maintainer permission level. Note
-that the `master` branch is protected by default.
+To protect a branch, you need to have at least Maintainer permission level.
+The `master` branch is protected by default.
-1. Navigate to your project's **Settings âž” Repository**
+1. In your project, go to **Settings > Repository**.
1. Scroll to find the **Protected branches** section.
1. From the **Branch** dropdown menu, select the branch you want to protect and
click **Protect**. In the screenshot below, we chose the `develop` branch.
![Protected branches page](img/protected_branches_page_v12_3.png)
-1. Once done, the protected branch will appear in the "Protected branches" list.
+1. Once done, the protected branch displays in the **Protected branches** list.
![Protected branches list](img/protected_branches_list_v12_3.png)
## Using the Allowed to merge and Allowed to push settings
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) in GitLab 8.11.
-
In GitLab 8.11 and later, we added another layer of branch protection which provides
-more granular management of protected branches. The "Developers can push"
-option was replaced by an "Allowed to push" setting which can be set to
-allow/prohibit Maintainers and/or Developers to push to a protected branch.
+more granular management of protected branches. The **Developers can push**
+option was replaced by **Allowed to push**. You can set this value to allow
+or prohibit Maintainers and/or Developers to push to a protected branch.
-Using the "Allowed to push" and "Allowed to merge" settings, you can control
+Using the **Allowed to push** and **Allowed to merge** settings, you can control
the actions that different roles can perform with the protected branch.
-For example, you could set "Allowed to push" to "No one", and "Allowed to merge"
-to "Developers + Maintainers", to require _everyone_ to submit a merge request for
+For example, you could set **Allowed to push** to "No one", and **Allowed to merge**
+to "Developers + Maintainers", to require everyone to submit a merge request for
changes going into the protected branch. This is compatible with workflows like
the [GitLab workflow](../../topics/gitlab_flow.md).
However, there are workflows where that is not needed, and only protecting from
force pushes and branch removal is useful. For those workflows, you can allow
everyone with write access to push to a protected branch by setting
-"Allowed to push" to "Developers + Maintainers".
+**Allowed to push** to "Developers + Maintainers".
-You can set the "Allowed to push" and "Allowed to merge" options while creating
+You can set the **Allowed to push** and **Allowed to merge** options while creating
a protected branch or afterwards by selecting the option you want from the
-dropdown list in the "Already protected" area.
+dropdown list in the **Already protected** area.
![Developers can push](img/protected_branches_devs_can_push_v12_3.png)
If you don't choose any of those options while creating a protected branch,
-they are set to "Maintainers" by default.
+they are set to Maintainers by default.
-### Allow Deploy Keys to push to a protected branch
+### Allow deploy keys to push to a protected branch
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30769) in GitLab 13.7.
> - This feature is being selectively deployed in GitLab.com 13.7, and may not be available for all users.
+> - This feature is available for all users in GitLab 13.9.
You can allow specific machines to access protected branches in your repository with
-[Deploy Keys](deploy_keys/index.md). This can be useful for your CI/CD workflow,
+[deploy keys](deploy_keys/index.md). This can be useful for your CI/CD workflow,
for example.
Deploy keys can be selected in the **Allowed to push** dropdown when:
@@ -88,7 +91,7 @@ Deploy keys can be selected in the **Allowed to push** dropdown when:
- Defining a protected branch.
- Updating an existing branch.
-Select a deploy key to allow the owner of the key to push to the chosen protected branch,
+Select a deploy key to allow the key's owner to push to the chosen protected branch,
even if they aren't a member of the related project. The owner of the selected deploy
key must have at least read access to the given project.
@@ -97,30 +100,26 @@ For a deploy key to be selectable:
- It must be [enabled for your project](deploy_keys/index.md#how-to-enable-deploy-keys).
- It must have [write access](deploy_keys/index.md#deploy-keys-permissions) to your project repository.
-Deploy Keys are not available in the **Allowed to merge** dropdown.
-
-![Deploy Keys on protected branches](img/protected_branches_deploy_keys_v13_5.png)
+Deploy keys are not available in the **Allowed to merge** dropdown.
-## Restricting push and merge access to certain users **(STARTER)**
+![Deploy keys on protected branches](img/protected_branches_deploy_keys_v13_5.png)
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.11.
+## Restricting push and merge access to certain users **(PREMIUM)**
-With GitLab Enterprise Edition you can restrict access to protected branches
-by choosing a role (Maintainers, Developers) as well as certain users. From the
+With GitLab Premium you can restrict access to protected branches
+by choosing a role (Maintainers, Developers) and certain users. From the
dropdown menu select the role and/or the users you want to have merge or push
access.
![Select roles and users](img/protected_branches_select_roles_and_users.png)
-Click **Protect** and the branch will appear in the "Protected branch" list.
+Click **Protect** and the branch displays in the **Protected branch** list.
![Roles and users list](img/protected_branches_select_roles_and_users_list.png)
## Wildcard protected branches
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4665) in GitLab 8.10.
-
-You can specify a wildcard protected branch, which will protect all branches
+You can specify a wildcard protected branch, which protects all branches
matching the wildcard. For example:
| Wildcard Protected Branch | Matching Branches |
@@ -129,15 +128,15 @@ matching the wildcard. For example:
| `production/*` | `production/app-server`, `production/load-balancer` |
| `*gitlab*` | `gitlab`, `gitlab/staging`, `master/gitlab/production` |
-Protected branch settings (like "Developers can push") apply to all matching
+Protected branch settings, like **Developers can push**, apply to all matching
branches.
Two different wildcards can potentially match the same branch. For example,
`*-stable` and `production-*` would both match a `production-stable` branch.
In that case, if _any_ of these protected branches have a setting like
-"Allowed to push", then `production-stable` will also inherit this setting.
+"Allowed to push", then `production-stable` also inherit this setting.
-If you click on a protected branch's name, you will be presented with a list of
+If you click on a protected branch's name, GitLab displays a list of
all matching branches:
![Protected branch matches](img/protected_branches_matches.png)
@@ -151,41 +150,36 @@ When a protected branch or wildcard protected branches are set to
Developers (and users with higher [permission levels](../permissions.md)) are
allowed to create a new protected branch as long as they are
[**Allowed to merge**](#using-the-allowed-to-merge-and-allowed-to-push-settings).
-This can only be done via the UI or through the API (to avoid creating protected
-branches accidentally from the command line or from a Git client application).
+This can only be done by using the UI or through the API, to avoid creating protected
+branches accidentally from the command line or from a Git client application.
To create a new branch through the user interface:
-1. Visit **Repository > Branches**.
+1. Go to **Repository > Branches**.
1. Click on **New branch**.
-1. Fill in the branch name and select an existing branch, tag, or commit that
- the new branch will be based off. Only existing protected branches and commits
- that are already in protected branches will be accepted.
+1. Fill in the branch name and select an existing branch, tag, or commit to
+ base the new branch on. Only existing protected branches and commits
+ that are already in protected branches are accepted.
## Deleting a protected branch
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21393) in GitLab 9.3.
-
-From time to time, it may be required to delete or clean up branches that are
-protected.
+From time to time, you may need to delete or clean up protected branches.
+User with [Maintainer permissions](../permissions.md) and greater can manually delete protected
+branches by using the GitLab web interface:
-User with [Maintainer permissions](../permissions.md) and up can manually delete protected
-branches via the GitLab web interface:
-
-1. Visit **Repository > Branches**
-1. Click on the delete icon next to the branch you wish to delete
-1. In order to prevent accidental deletion, an additional confirmation is
- required
+1. Go to **Repository > Branches**.
+1. Click on the delete icon next to the branch you wish to delete.
+1. To prevent accidental deletion, an additional confirmation is required.
![Delete protected branches](img/protected_branches_delete.png)
-Deleting a protected branch is only allowed via the web interface, not via Git.
+Deleting a protected branch is allowed only by using the web interface; not from Git.
This means that you can't accidentally delete a protected branch from your
command line or a Git client application.
-## Protected Branches approval by Code Owners **(PREMIUM)**
+## Protected branches approval by Code Owners **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13251) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13251) in GitLab Premium 12.4.
It is possible to require at least one approval by a
[Code Owner](code_owners.md) to a file changed by the
@@ -208,7 +202,7 @@ To enable Code Owner's approval to branches already protected:
![Code Owners approval - branch already protected](img/code_owners_approval_protected_branch_v12_4.png)
-When enabled, all merge requests targeting these branches will require approval
+When enabled, all merge requests targeting these branches require approval
by a Code Owner per matched rule before they can be merged.
Additionally, direct pushes to the protected branch are denied if a rule is matched.
@@ -224,26 +218,9 @@ for details about the pipelines security model.
## Changelog
-**13.5**
-
-- [Allow Deploy keys to push to protected branches once more](https://gitlab.com/gitlab-org/gitlab/-/issues/30769).
-
-**11.9**
-
-- [Allow protected branches to be created](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361) by Developers (and users with higher permission levels) through the API and the user interface.
-
-**9.2**
-
-- Allow deletion of protected branches via the web interface ([issue #21393](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21393)).
-
-**8.11**
-
-- Allow creating protected branches that can't be pushed to ([merge request !5081](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5081)).
-
-**8.10**
-
-- Allow developers without push access to merge into a protected branch ([merge request !4892](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4892)).
-- Allow specifying protected branches using wildcards ([merge request !4665](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/4665)).
+- **13.5**: [Allow Deploy keys to push to protected branches once more](https://gitlab.com/gitlab-org/gitlab/-/issues/30769).
+- **11.9**: [Allow protected branches to be created](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53361)
+ by Developers (and users with higher permission levels) through the API and the user interface.
<!-- ## Troubleshooting
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index 7e09c526312..3ea0bb62c0b 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Protected tags
+# Protected tags **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10356) in GitLab 9.1.
@@ -15,11 +15,13 @@ This feature evolved out of [protected branches](protected_branches.md)
## Overview
-Protected tags will prevent anyone from updating or deleting the tag, and will prevent creation of matching tags based on the permissions you have selected. By default, anyone without Maintainer permission will be prevented from creating tags.
+Protected tags prevent anyone from updating or deleting the tag, and prevent
+creation of matching tags based on the permissions you have selected. By default,
+anyone without Maintainer [permissions](../permissions.md) is prevented from creating tags.
## Configuring protected tags
-To protect a tag, you need to have at least Maintainer permission level.
+To protect a tag, you need to have at least Maintainer [permissions](../permissions.md).
1. Navigate to the project's **Settings > Repository**:
@@ -29,17 +31,18 @@ To protect a tag, you need to have at least Maintainer permission level.
![Protected tags page](img/protected_tags_page_v12_3.png)
-1. From the **Allowed to create** dropdown, select who will have permission to create matching tags and then click **Protect**:
+1. From the **Allowed to create** dropdown, select users with permission to create
+ matching tags, and click **Protect**:
![Allowed to create tags dropdown](img/protected_tags_permissions_dropdown_v12_3.png)
-1. Once done, the protected tag will appear in the **Protected tags** list:
+1. After done, the protected tag displays in the **Protected tags** list:
![Protected tags list](img/protected_tags_list_v12_3.png)
## Wildcard protected tags
-You can specify a wildcard protected tag, which will protect all tags
+You can specify a wildcard protected tag, which protects all tags
matching the wildcard. For example:
| Wildcard Protected Tag | Matching Tags |
@@ -52,9 +55,9 @@ matching the wildcard. For example:
Two different wildcards can potentially match the same tag. For example,
`*-stable` and `production-*` would both match a `production-stable` tag.
In that case, if _any_ of these protected tags have a setting like
-**Allowed to create**, then `production-stable` will also inherit this setting.
+**Allowed to create**, then `production-stable` also inherit this setting.
-If you click on a protected tag's name, you will be presented with a list of
+If you click on a protected tag's name, GitLab displays a list of
all matching tags:
![Protected tag matches](img/protected_tag_matches.png)
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index 8af4307c013..f94a4075363 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
-# Push Options
+# Push Options **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15643) in GitLab 11.7.
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 64be3182dab..ac65fabd6a7 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -34,9 +34,9 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/assign @user` | ✓ | ✓ | | Assign one user. |
| `/assign @user1 @user2` | ✓ | ✓ | | Assign multiple users. **(STARTER)** |
| `/assign me` | ✓ | ✓ | | Assign yourself. |
-| `/assign_reviewer @user` | | ✓ | | Assign one user as a reviewer. |
-| `/assign_reviewer @user1 @user2` | | ✓ | | Assign multiple users as reviewers. **(STARTER)** |
-| `/assign_reviewer me` | | ✓ | | Assign yourself as a reviewer. |
+| `/assign_reviewer @user` or `/reviewer @user` or `/request_review @user` | | ✓ | | Assign one user as a reviewer. |
+| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` or `/request_review @user1 @user2` | | ✓ | | Assign multiple users as reviewers. **(STARTER)** |
+| `/assign_reviewer me` or `/reviewer me` or `/request_review me` | | ✓ | | Assign yourself as a reviewer. |
| `/award :emoji:` | ✓ | ✓ | ✓ | Toggle emoji award. |
| `/child_epic <epic>` | | | ✓ | Add child 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.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). **(ULTIMATE)** |
| `/clear_weight` | ✓ | | | Clear weight. **(STARTER)** |
@@ -49,7 +49,7 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/done` | ✓ | ✓ | ✓ | Mark to do as done. |
| `/draft` | | ✓ | | Toggle the draft status. |
| `/due <date>` | ✓ | | | Set due date. Examples of valid `<date>` include `in 2 days`, `this Friday` and `December 31st`. |
-| `/duplicate <#issue>` | ✓ | | | Close this issue and mark as a duplicate of another issue. **(CORE)** Also, mark both as related. **(STARTER)** |
+| `/duplicate <#issue>` | ✓ | | | Close this issue and mark as a duplicate of another issue. **(FREE)** Also, mark both as related. **(STARTER)** |
| `/epic <epic>` | ✓ | | | Add to epic `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic. **(PREMIUM)** |
| `/estimate <<W>w <DD>d <hh>h <mm>m>` | ✓ | ✓ | | Set time estimate. For example, `/estimate 1w 3d 2h 14m`. |
| `/iteration *iteration:"iteration name"` | ✓ | | | Set iteration. For example, to set the `Late in July` iteration: `/iteration *iteration:"Late in July"` ([introduced in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/issues/196795)). **(STARTER)** |
@@ -62,7 +62,7 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/promote` | ✓ | | | Promote issue to epic. **(PREMIUM)** |
| `/publish` | ✓ | | | Publish issue to an associated [Status Page](../../operations/incident_management/status_page.md) ([Introduced in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906)) **(ULTIMATE)** |
| `/reassign @user1 @user2` | ✓ | ✓ | | Replace current assignees with those specified. **(STARTER)** |
-| `/rebase` | | ✓ | | Rebase source branch. This will schedule a background task that attempt to rebase the changes in the source branch on the latest commit of the target branch. If `/rebase` is used, `/merge` will be ignored to avoid a race condition where the source branch is merged or deleted before it is rebased. If there are merge conflicts, GitLab will display a message that a rebase cannot be scheduled. Rebase failures will be displayed with the merge request status. |
+| `/rebase` | | ✓ | | Rebase source branch. This schedules a background task that attempts to rebase the changes in the source branch on the latest commit of the target branch. If `/rebase` is used, `/merge` is ignored to avoid a race condition where the source branch is merged or deleted before it is rebased. If there are merge conflicts, GitLab displays a message that a rebase cannot be scheduled. Rebase failures are displayed with the merge request status. |
| `/reassign_reviewer @user1 @user2` | | ✓ | | Replace current reviewers with those specified. **(STARTER)** |
| `/relabel ~label1 ~label2` | ✓ | ✓ | ✓ | Replace current labels with those specified. |
| `/relate #issue1 #issue2` | ✓ | | | Mark issues as related. **(STARTER)** |
@@ -87,8 +87,8 @@ The following quick actions are applicable to descriptions, discussions and thre
| `/todo` | ✓ | ✓ | ✓ | Add a to-do item. |
| `/unassign @user1 @user2` | ✓ | ✓ | | Remove specific assignees. **(STARTER)** |
| `/unassign` | | ✓ | | Remove all assignees. |
-| `/unassign_reviewer @user1 @user2` | | ✓ | | Remove specific reviewers. **(STARTER)** |
-| `/unassign_reviewer` | | ✓ | | Remove all reviewers. |
+| `/unassign_reviewer @user1 @user2` or `/remove_reviewer @user1 @user2` | | ✓ | | Remove specific reviewers. **(STARTER)** |
+| `/unassign_reviewer` or `/remove_reviewer` | | ✓ | | Remove all reviewers. |
| `/unlabel ~label1 ~label2` or `/remove_label ~label1 ~label2` | ✓ | ✓ | ✓ | Remove specified labels. |
| `/unlabel` or `/remove_label` | ✓ | ✓ | ✓ | Remove all labels. |
| `/unlock` | ✓ | ✓ | | Unlock the discussions. |
diff --git a/doc/user/project/releases.md b/doc/user/project/releases.md
deleted file mode 100644
index 6dd5a6f0b0d..00000000000
--- a/doc/user/project/releases.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'releases/index.md'
----
-
-This document was moved to [another location](releases/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 90d7ac0a3c2..b5751797870 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -407,7 +407,7 @@ Here is an example of a release evidence object:
}
```
-### Collect release evidence **(PREMIUM ONLY)**
+### Collect release evidence **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
@@ -475,6 +475,16 @@ terminal.
Read the [Release CLI documentation](https://gitlab.com/gitlab-org/release-cli/-/blob/master/docs/index.md)
for details.
+## Release Metrics **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259703) in GitLab Premium 13.9.
+
+Group-level release metrics are available by navigating to **Group > Analytics > CI/CD**.
+These metrics include:
+
+- Total number of releases in the group
+- Percentage of projects in the group that have at least one release
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index ffd4b383bcb..4d0cf28593d 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: concepts, howto
---
-# Branches
+# Branches **(FREE)**
A branch is a version of a project's working tree. You create a branch for each
set of related changes you make. This keeps each set of changes separate from
@@ -53,14 +53,14 @@ the target is the project's **default branch**.
The default branch is also initially [protected](../../protected_branches.md#protected-branches)
against accidental deletion and forced pushes.
-### Custom initial branch name **(CORE ONLY)**
+### Custom initial branch name **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221013) in GitLab 13.2.
> - It's deployed behind a feature flag, enabled by default.
> - It's enabled on GitLab.com.
> - It cannot be enabled or disabled per-project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-custom-initial-branch-name). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-custom-initial-branch-name). **(FREE SELF)**
By default, when you create a new project in GitLab, the initial branch is called `master`.
For self-managed instances, a GitLab administrator can customize the initial branch name to something
@@ -71,7 +71,7 @@ else. This way, every new project created from then on will start from the custo
1. Change the default initial branch to a custom name of your choice.
1. **Save Changes**.
-#### Enable or disable custom initial branch name **(CORE ONLY)**
+#### Enable or disable custom initial branch name **(FREE SELF)**
Setting the default initial branch name is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
diff --git a/doc/user/project/repository/file_finder.md b/doc/user/project/repository/file_finder.md
index 4f996df5fef..df3e24fbf30 100644
--- a/doc/user/project/repository/file_finder.md
+++ b/doc/user/project/repository/file_finder.md
@@ -17,8 +17,8 @@ project.
![Find file button](img/file_finder_find_button_v12_10.png)
-For those who prefer to keep their fingers on the keyboard, there is a
-[shortcut button](../../shortcuts.md) as well, which you can invoke from _anywhere_
+If you prefer to keep their fingers on the keyboard, use the
+[shortcut button](../../shortcuts.md), which you can invoke from anywhere
in a project.
Press `t` to launch the File search function when in **Issues**,
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index f7da3629c23..1a5e169ec6b 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/forking_workflow.html'
---
-# Project forking workflow
+# Project forking workflow **(FREE)**
Whenever possible, it's recommended to work in a common Git repository and use
[branching strategies](../../../topics/gitlab_flow.md) to manage your work. However,
diff --git a/doc/user/project/repository/git_blame.md b/doc/user/project/repository/git_blame.md
index 4322c79daa7..81995291911 100644
--- a/doc/user/project/repository/git_blame.md
+++ b/doc/user/project/repository/git_blame.md
@@ -6,7 +6,7 @@ type: reference, howto
description: "Documentation on Git file blame."
---
-# Git file blame
+# Git file blame **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/commit/39c657930625ddc3ac8a921f01ffc83acadce68f) in GitLab 2.5.
diff --git a/doc/user/project/repository/git_history.md b/doc/user/project/repository/git_history.md
index 51cc6bb3483..2e27cab4177 100644
--- a/doc/user/project/repository/git_history.md
+++ b/doc/user/project/repository/git_history.md
@@ -6,7 +6,7 @@ type: reference, howto
description: "Documentation on Git file history."
---
-# Git file history
+# Git file history **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/blob/9ba1224867665844b117fa037e1465bb706b3685/app/controllers/commits_controller.rb) in GitLab 0.8.0
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 57e9d814c95..1a46c140507 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: concepts, howto
---
-# Signing commits with GPG
+# Signing commits with GPG **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9546) in GitLab 9.5.
> - Subkeys support was added in GitLab 10.1.
@@ -138,27 +138,25 @@ started:
gpg --armor --export 30F2B65B9246B6CA
```
-1. Finally, copy the public key and [add it in your profile settings](#adding-a-gpg-key-to-your-account)
+1. Finally, copy the public key and [add it in your user settings](#adding-a-gpg-key-to-your-account)
## Adding a GPG key to your account
NOTE:
-Once you add a key, you cannot edit it, only remove it. In case the paste
-didn't work, you'll have to remove the offending key and re-add it.
+After you add a key, you cannot edit it, only remove it. In case the paste
+didn't work, you have to remove the offending key and re-add it.
-You can add a GPG key in your profile's settings:
+You can add a GPG key in your user settings:
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
- ![Settings dropdown](../../../profile/img/profile_settings_dropdown.png)
-
-1. Navigate to the **GPG keys** tab and paste your _public_ key in the 'Key'
- box.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **GPG Keys**.
+1. Paste your _public_ key in the **Key** text box.
![Paste GPG public key](img/profile_settings_gpg_keys_paste_pub.png)
-1. Finally, click on **Add key** to add it to GitLab. You will be able to see
- its fingerprint, the corresponding email address and creation date.
+1. Select **Add key** to add it to GitLab. You can see the key's fingerprint, the corresponding
+ email address, and creation date.
![GPG key single page](img/profile_settings_gpg_keys_single_key.png)
@@ -248,22 +246,24 @@ in case your key has been compromised.
To revoke a GPG key:
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-1. Navigate to the **GPG keys** tab.
-1. Click on **Revoke** besides the GPG key you want to delete.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **GPG Keys**.
+1. Select **Revoke** next to the GPG key you want to delete.
## Removing a GPG key
Removing a key **does not unverify** already signed commits. Commits that were
-verified by using this key will stay verified. Only unpushed commits will stay
-unverified once you remove this key. To unverify already signed commits, you need
+verified by using this key stay verified. Only unpushed commits stay
+unverified after you remove this key. To unverify already signed commits, you need
to [revoke the associated GPG key](#revoking-a-gpg-key) from your account.
To remove a GPG key from your account:
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-1. Navigate to the **GPG keys** tab.
-1. Click on the trash icon besides the GPG key you want to delete.
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the left sidebar, select **GPG Keys**.
+1. Select the trash icon (**{remove}**) next to the GPG key you want to delete.
## Rejecting commits that are not signed **(PREMIUM)**
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index c4f5d330f63..5a915ebef89 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
-# Repository
+# Repository **(FREE)**
A [repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)
is what you use to store your codebase in GitLab and change it with version control.
@@ -14,7 +14,7 @@ A repository is part of a [project](../index.md), which has a lot of other featu
## Create a repository
To create a new repository, all you need to do is
-[create a new project](../../../gitlab-basics/create-project.md) or
+[create a new project](../../../user/project/working_with_projects.md#create-a-project) or
[fork an existing project](forking_workflow.md).
Once you create a new project, you can add new files via UI
@@ -43,7 +43,7 @@ You can either use the user interface (UI), or connect your local computer
with GitLab [through the command line](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
To configure [GitLab CI/CD](../../../ci/README.md) to build, test, and deploy
-your code, add a file called [`.gitlab-ci.yml`](../../../ci/quick_start/README.md)
+your code, add a file called [`.gitlab-ci.yml`](../../../ci/quick_start/index.md)
to your repository's root.
**From the user interface:**
@@ -242,13 +242,32 @@ Learn how to [clone a repository through the command line](../../../gitlab-basic
Alternatively, clone directly into a code editor as documented below.
-### Clone to Apple Xcode
+### Clone and open in Apple Xcode
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0.
Projects that contain a `.xcodeproj` or `.xcworkspace` directory can now be cloned
-into Xcode using the new **Open in Xcode** button, located next to the Git URL
-used for cloning your project. The button is only shown on macOS.
+into Xcode on macOS. To do that:
+
+1. From the GitLab UI, go to the project's overview page.
+1. Click **Clone**.
+1. Select **Xcode**.
+
+The project will be cloned onto your computer in a folder of your choice and you'll
+be prompted to open in XCode.
+
+### Clone and open in Visual Studio Code
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220957) in GitLab 13.8.
+
+All projects can be cloned into Visual Studio Code. To do that:
+
+1. From the GitLab UI, go to the project's overview page.
+1. Click **Clone**.
+1. Select **VS Code**
+
+You'll be prompted to select a folder to clone the project into. When VS Code has
+successfully cloned your project, it will open the folder.
## Download Source Code
@@ -270,6 +289,28 @@ By clicking the download icon, a dropdown will open with links to download the f
- **Artifacts:**
allows users to download the artifacts of the latest CI build.
+## Redirects when changing repository paths
+
+When a repository path changes, it is essential to smoothly transition from the
+old location to the new one. GitLab provides two kinds of redirects: the web UI
+and Git push/pull redirects.
+
+Depending on the situation, different things apply.
+
+When [renaming a user](../../profile/index.md#changing-your-username),
+[changing a group path](../../group/index.md#changing-a-groups-path) or [renaming a repository](../settings/index.md#renaming-a-repository):
+
+- Existing web URLs for the namespace and anything under it (such as projects) will
+ redirect to the new URLs.
+- Starting with GitLab 10.3, existing Git remote URLs for projects under the
+ namespace redirect to the new remote URL. Every time you push/pull to a
+ repository that has changed its location, a warning message to update
+ your remote is displayed instead of rejecting your action.
+ This means that any automation scripts, or Git clients continue to
+ work after a rename, making any transition a lot smoother.
+- The redirects are available as long as the original path is not claimed by
+ another group, user or project.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/repository/jupyter_notebooks/index.md b/doc/user/project/repository/jupyter_notebooks/index.md
index 91fe9049b53..123df9097f9 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -4,7 +4,7 @@ group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
type: reference
---
-# Jupyter Notebook Files
+# Jupyter Notebook Files **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/2508/) in GitLab 9.1.
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 fb798738160..7847930366a 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
@@ -23,107 +23,28 @@ Rewriting repository history is a destructive operation. Make sure to back up yo
you begin. The best way back up a repository is to
[export the project](../settings/import_export.md#exporting-a-project-and-its-data).
-NOTE:
-Git LFS files can only be removed by an Administrator using a
-[Rake task](../../../raketasks/cleanup.md). Removal of this limitation
-[is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/223621).
-
## Purge files from repository history
-To reduce the size of your repository in GitLab, you must remove references to large files from branches, tags, and
+To reduce the size of your repository in GitLab, you must first remove references to large files from branches, tags, *and*
other internal references (refs) that are automatically created by GitLab. These refs include:
- `refs/merge-requests/*` for merge requests.
- `refs/pipelines/*` for
[pipelines](../../../ci/troubleshooting.md#fatal-reference-is-not-a-tree-error).
- `refs/environments/*` for environments.
+- `refs/keep-around/*` are created as hidden refs to prevent commits referenced in the database from being removed
-Git doesn't usually download these refs to make cloning and fetch faster, but we can use the `--mirror` option to
-download all the advertised refs.
-
-1. [Install `git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md)
- using a supported package manager or from source.
-
-1. Clone a fresh copy of the repository using `--bare` and `--mirror`:
-
- ```shell
- git clone --bare --mirror https://gitlab.example.com/my/project.git
- ```
-
-1. Using `git filter-repo`, purge any files from the history of your repository.
-
- To purge large files, the `--strip-blobs-bigger-than` option can be used:
-
- ```shell
- git filter-repo --strip-blobs-bigger-than 10M
- ```
-
- To purge large files stored using Git LFS, the `--blob--callback` option can
- be used. The example below, uses the callback to read the file size from the
- Git LFS pointer, and removes files larger than 10MB.
-
- ```shell
- git filter-repo --blob-callback '
- if blob.data.startswith(b"version https://git-lfs.github.com/spec/v1"):
- size_in_bytes = int.from_bytes(blob.data[124:], byteorder="big")
- if size_in_bytes > 10*1000:
- blob.skip()
- '
- ```
-
- To purge specific large files by path, the `--path` and `--invert-paths` options can be combined:
-
- ```shell
- git filter-repo --path path/to/big/file.m4v --invert-paths
- ```
-
- See the
- [`git filter-repo` documentation](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)
- for more examples and the complete documentation.
-
-1. Force push your changes to overwrite all branches on GitLab:
-
- ```shell
- git push origin --force 'refs/heads/*'
- ```
-
- [Protected branches](../protected_branches.md) cause this to fail. To proceed, you must
- remove branch protection, push, and then re-enable protected branches.
-
-1. To remove large files from tagged releases, force push your changes to all tags on GitLab:
-
- ```shell
- git push origin --force 'refs/tags/*'
- ```
-
- [Protected tags](../protected_tags.md) cause this to fail. To proceed, you must remove tag
- protection, push, and then re-enable protected tags.
-
-1. To prevent dead links to commits that no longer exist, push the `refs/replace` created by `git filter-repo`.
-
- ```shell
- git push origin --force 'refs/replace/*'
- ```
-
- Refer to the Git [`replace`](https://git-scm.com/book/en/v2/Git-Tools-Replace) documentation for information on how this works.
-
-1. Run a [repository cleanup](#repository-cleanup).
-
-NOTE:
-Project statistics are cached for performance. You may need to wait 5-10 minutes
-to see a reduction in storage utilization.
-
-## Purge files from GitLab storage
-
-In addition to the refs mentioned above, GitLab also creates hidden `refs/keep-around/*`to prevent commits being deleted. Hidden refs are not advertised, which means we can't download them using Git, but these refs are included in a project export.
+These refs are not automatically downloaded and hidden refs are not advertised, but we can remove these refs using a project export.
-To purge files from GitLab storage:
+To purge files from a GitLab repository:
1. [Install `git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md)
using a supported package manager or from source.
1. Generate a fresh [export from the
project](../settings/import_export.html#exporting-a-project-and-its-data) and download it.
+ This project export contains a backup copy of your repository *and* refs
+ we can use to purge files from your repository.
1. Decompress the backup using `tar`:
@@ -134,7 +55,7 @@ To purge files from GitLab storage:
This contains a `project.bundle` file, which was created by
[`git bundle`](https://git-scm.com/docs/git-bundle).
-1. Clone a fresh copy of the repository from the bundle:
+1. Clone a fresh copy of the repository from the bundle using `--bare` and `--mirror` options:
```shell
git clone --bare --mirror /path/to/project.bundle
@@ -149,7 +70,7 @@ To purge files from GitLab storage:
the previous run. You need this file from **every** run. Do the next step every time you run
`git filter-repo`.
- To purge all large files, the `--strip-blobs-bigger-than` option can be used:
+ To purge all files larger than 10M, the `--strip-blobs-bigger-than` option can be used:
```shell
git filter-repo --strip-blobs-bigger-than 10M
@@ -236,14 +157,14 @@ This:
- Runs `git gc --prune=30.minutes.ago` against the repository to remove unreferenced objects. Repacking your repository temporarily
causes the size of your repository to increase significantly, because the old pack files are not removed until the
new pack files have been created.
-- Unlinks any unused LFS objects currently attached to your project, freeing up storage space.
+- Unlinks any unused LFS objects attached to your project, freeing up storage space.
- Recalculates the size of your repository on disk.
GitLab sends an email notification with the recalculated repository size after the cleanup has completed.
If the repository size does not decrease, this may be caused by loose objects
being kept around because they were referenced in a Git operation that happened
-in the last 30 minutes. Try re-running these steps once the repository has been
+in the last 30 minutes. Try re-running these steps after the repository has been
dormant for at least 30 minutes.
When using repository cleanup, note:
@@ -263,7 +184,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. **(STARTER ONLY)**
+ on self-managed instances. **(PREMIUM SELF)**
- 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/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index 4a7f75ba1ac..4d5e4a5ef02 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
---
-# Repository mirroring
+# Repository mirroring **(FREE)**
Repository mirroring allows for mirroring of repositories to and from external sources. It can be
used to mirror branches, tags, and commits between repositories. It is useful when you want to use
@@ -16,8 +16,8 @@ at most once every 5 minutes on GitLab.com with [the limit set by the administra
There are two kinds of repository mirroring supported by GitLab:
-- [Push](#pushing-to-a-remote-repository): for mirroring a GitLab repository to another location. **(CORE)**
-- [Pull](#pulling-from-a-remote-repository): for mirroring a repository from another location to GitLab. **(STARTER)**
+- [Push](#pushing-to-a-remote-repository): for mirroring a GitLab repository to another location. **(FREE)**
+- [Pull](#pulling-from-a-remote-repository): for mirroring a repository from another location to GitLab. **(PREMIUM)**
When the mirror repository is updated, all new branches, tags, and commits will be visible in the
project's activity feed.
@@ -37,7 +37,7 @@ The following are some possible use cases for repository mirroring:
- You migrated to GitLab but still need to keep your project in another source. In that case, you
can simply set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
- and branches will be available in your GitLab instance. **(STARTER)**
+ and branches will be available in your GitLab instance. **(PREMIUM)**
- You have old projects in another source that you don't use actively anymore, but don't want to
remove for archiving purposes. In that case, you can create a push mirror so that your active
GitLab repository can push its changes to the old location.
@@ -47,10 +47,10 @@ The following are some possible use cases for repository mirroring:
GitLab.com repository that's public, allows you to open source specific projects and contribute back
to the open source community.
-## Pushing to a remote repository **(CORE)**
+## Pushing to a remote repository **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/249) in GitLab Enterprise Edition 8.7.
-> - [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) in 10.8.
+> - [Moved to GitLab Free](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) in 10.8.
> - [LFS support over HTTPS added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40137) in 13.5
For an existing project, you can set up push mirroring as follows:
@@ -205,10 +205,11 @@ If it is not working correctly a red `error` tag appears and shows the error mes
1. Fill in the **Password** field with the GitLab personal access token created on the destination GitLab instance.
1. Click the **Mirror repository** button.
-## Pulling from a remote repository **(STARTER)**
+## Pulling from a remote repository **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51) in GitLab Enterprise Edition 8.2.
-> - [Added Git LFS support](https://gitlab.com/gitlab-org/gitlab/-/issues/10871) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.11.
+> - [Added Git LFS support](https://gitlab.com/gitlab-org/gitlab/-/issues/10871) in GitLab 11.11.
+> - Moved to GitLab Premium in 13.9.
You can set up a repository to automatically have its branches, tags, and commits updated from an
upstream repository.
@@ -262,9 +263,10 @@ Repository mirrors are updated as Sidekiq becomes available to process them. If
- Fails (for example, a branch diverged from upstream), it will be attempted again later. Mirrors can fail
up to 14 times before they will not be enqueued for update again.
-### Overwrite diverged branches **(STARTER)**
+### Overwrite diverged branches **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in GitLab 10.6.
+> - Moved to GitLab Premium in 13.9.
You can choose to always update your local branches with remote versions, even if they have
diverged from the remote.
@@ -274,7 +276,9 @@ For mirrored branches, enabling this option results in the loss of local changes
To use this option, check the **Overwrite diverged branches** box when creating a repository mirror.
-### Trigger pipelines for mirror updates **(STARTER)**
+### Trigger pipelines for mirror updates **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
If this option is enabled, pipelines will be triggered when branches or tags are
updated from the remote repository. Depending on the activity of the remote
@@ -282,9 +286,10 @@ repository, this may greatly increase the load on your CI runners. Only enable
this if you know they can handle the load. CI will run using the credentials
assigned when you set up pull mirroring.
-### Hard failure **(STARTER)**
+### Hard failure **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in GitLab 10.2.
+> - Moved to GitLab Premium in 13.9.
Once the mirroring process is unsuccessfully retried 14 times in a row, it will get marked as hard
failed. This will become visible in either the:
@@ -295,9 +300,10 @@ failed. This will become visible in either the:
When a project is hard failed, it will no longer get picked up for mirroring.
You can resume the project mirroring again by [forcing an update](#forcing-an-update).
-### Trigger an update using the API **(STARTER)**
+### Trigger an update using the API **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in GitLab 10.3.
+> - Moved to GitLab Premium in 13.9.
Pull mirroring uses polling to detect new branches and commits added upstream, often minutes
afterwards. If you notify GitLab by [API](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project),
@@ -305,19 +311,21 @@ updates will be pulled immediately.
For more information, see [Start the pull mirroring process for a Project](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project).
-## Mirror only protected branches **(STARTER)**
+## Mirror only protected branches **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
Based on the mirror direction that you choose, you can opt to mirror only the
[protected branches](../protected_branches.md) from/to your remote repository.
For pull mirroring, non-protected branches are not mirrored and can diverge.
To use this option, check the **Only mirror protected branches** box when
-creating a repository mirror.
+creating a repository mirror. **(PREMIUM)**
## SSH authentication
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5 for Pull mirroring.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) in [GitLab Core](https://about.gitlab.com/pricing/) 11.6 for Push mirroring.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551) in GitLab 9.5 for Pull mirroring.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) in GitLab 11.6 for Push mirroring.
SSH authentication is mutual:
@@ -332,7 +340,7 @@ If you're mirroring over SSH (that is, using an `ssh://` URL), you can authentic
- Password-based authentication, just as over HTTPS.
- Public key authentication. This is often more secure than password authentication,
- especially when the other repository supports [Deploy Keys](../../../ssh/README.md#deploy-keys).
+ especially when the other repository supports [deploy keys](../../../ssh/README.md#deploy-keys).
To get started:
@@ -393,7 +401,7 @@ GitLab generates a 4096-bit RSA key that can be copied by clicking the **Copy SS
You then need to add the public SSH key to the other repository's configuration:
- If the other repository is hosted on GitLab, you should add the public SSH key
- as a [Deploy Key](../../../ssh/README.md#deploy-keys).
+ as a [deploy key](../../../ssh/README.md#deploy-keys).
- If the other repository is hosted elsewhere, you may need to add the key to
your user's `authorized_keys` file. Paste the entire public SSH key into the
file on its own line and save it.
@@ -403,17 +411,19 @@ to generate a new key. You'll have to update the other repository with the new
key to keep the mirror running.
NOTE:
-The generated keys are stored in the GitLab database, not in the filesystem. Therefore,
+The generated keys are stored in the GitLab database, not in the file system. Therefore,
SSH public key authentication for mirrors cannot be used in a pre-receive hook.
-## Forcing an update **(CORE)**
+## Forcing an update **(FREE)**
While mirrors are scheduled to update automatically, you can always force an update by using the
update button which is available on the **Mirroring repositories** section of the **Repository Settings** page.
![Repository mirroring force update user interface](img/repository_mirroring_force_update.png)
-## Bidirectional mirroring **(STARTER)**
+## Bidirectional mirroring **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
WARNING:
Bidirectional mirroring may cause conflicts.
@@ -536,7 +546,9 @@ Note that this sample has a few limitations:
- The script circumvents the Git hook quarantine environment because the update of `$TARGET_REPO`
is seen as a ref update and Git will complain about it.
-### Mirroring with Perforce Helix via Git Fusion **(STARTER)**
+### Mirroring with Perforce Helix via Git Fusion **(PREMIUM)**
+
+> Moved to GitLab Premium in 13.9.
WARNING:
Bidirectional mirroring should not be used as a permanent configuration. Refer to
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index b9477da3937..a9e249bb8c3 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -21,8 +21,8 @@ Choose **New file** from the dropdown.
Enter a filename in the **Filename** box. Then, add file content in the editor
area. Add a descriptive commit message and choose a branch. The branch field
-will default to the branch you were viewing in the file browser. If you enter
-a new branch name, a checkbox will appear, allowing you to start a new merge
+defaults to the branch you were viewing in the file browser. If you enter
+a new branch name, a checkbox displays, allowing you to start a new merge
request after you commit the changes.
When you are satisfied with your new file, click **Commit Changes** at the bottom.
@@ -31,46 +31,45 @@ When you are satisfied with your new file, click **Commit Changes** at the botto
### Shortcuts
-You can use handy shortcuts when editing a file through the Web Editor, which are the same as
-the Web IDE's. For details, see the documentation for [Command Palette](../web_ide/index.md#command-palette).
+You can use shortcuts when editing a file through the Web Editor. It uses the same shortcuts
+as the Web IDE. For details, read the documentation for [Command Palette](../web_ide/index.md#command-palette).
### Template dropdowns
When starting a new project, there are some common files that the new project
-might need too. Therefore a message will be displayed by GitLab to make this
-easy for you.
+might need. GitLab displays a message to help you:
![First file for your project](img/web_editor_template_dropdown_first_file.png)
-When clicking on either `LICENSE` or `.gitignore` and so on, a dropdown will be displayed
-to provide you with a template that might be suitable for your project.
+When clicking on either `LICENSE` or `.gitignore` and so on, a dropdown displays
+to provide you a template that may be suitable for your project:
![MIT license selected](img/web_editor_template_dropdown_mit_license.png)
-The license, changelog, contribution guide, or `.gitlab-ci.yml` file could also
-be added through a button on the project page. In the example below, the license
+The license, changelog, contribution guide, or `.gitlab-ci.yml` file can also
+be added through a button on the project page. In this example, the license
has already been created, which creates a link to the license itself.
![New file button](img/web_editor_template_dropdown_buttons.png)
NOTE:
-The **Set up CI/CD** button will not appear on an empty repository. You have to at
-least add a file in order for the button to show up.
+The **Set up CI/CD** button does not appear on an empty repository. For the button
+to display, add a file to your repository.
## Upload a file
The ability to create a file is great when the content is text. However, this
-doesn't work well for binary data such as images, PDFs, or other file types. In
+doesn't work well for binary data such as images, PDFs, or other binary file types. In
this case, you need to upload a file.
From a project's files page, click the '+' button to the right of the branch
-selector. Choose **Upload file** from the dropdown.
+selector. Choose **Upload file** from the dropdown:
![Upload file dropdown menu](img/web_editor_upload_file_dropdown.png)
-Once the upload dialog pops up, there are two ways to upload your file. Either
-drag and drop a file on the popup or use the **click to upload** link. A file
-preview will appear once you have selected a file to upload.
+After the upload dialog pops up, there are two ways to upload your file. Either
+drag and drop a file on the popup or use the **click to upload** link. After you
+select a file to upload, a file preview displays.
Enter a commit message, choose a branch, and click **Upload file** when you are
ready.
@@ -100,19 +99,22 @@ There are multiple ways to create a branch from the GitLab web interface.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2808) in GitLab 8.6.
-If your development workflow dictates to have an issue for every merge
-request, you can quickly create a branch directly from the issue to speed the process up.
-The new branch, and later its merge request, will be marked as related to this issue.
-Once merged, the MR will automatically close the issue.
+If your development workflow requires an issue for every merge
+request, you can create a branch directly from the issue to speed the process up.
+The new branch, and later its merge request, are marked as related to this issue.
+Once merged, the merge request closes the issue.
You can see a **Create merge request** dropdown below the issue description.
-NOTE:
-You won't see the **Create merge request** button if there is already a branch with the same
-name or a referenced merge request or your project has an active
-fork relationship.
-If you would like to make this button appear, a possible workaround is to [remove your project's
-fork relationship](../settings/index.md#removing-a-fork-relationship). 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.
+The **Create merge request** button doesn't display if:
+
+- A branch with the same name already exists.
+- The branch already has a referenced merge request.
+- Your project has an active fork relationship.
+
+To make this button appear, one possible workaround is to
+[remove your project's fork relationship](../settings/index.md#removing-a-fork-relationship).
+After removal, the fork relationship cannot be restored. This project can no longer
+be able to receive or send merge requests to the source project, or other forks.
![Create Button](img/web_editor_new_branch_from_issue_create_button_v12_6.png)
@@ -120,46 +122,47 @@ This dropdown contains the options **Create merge request and branch** and **Cre
![New Branch Button](img/web_editor_new_branch_from_issue_v_12_6.png)
-Once you choose one of these options, a new branch or branch and merge request
-will be created based on the default
-branch of your project (by default, `master`). The branch name will be based on
-the title of the issue, and as a prefix, it will have its internal ID. Thus, the example
-screenshot above will create a branch named
+After selecting one of these options, a new branch or branch and merge request
+is created based on your project's default branch. By default, this branch is `master`.
+The branch name is based on an internal ID, and the issue title. The example
+screenshot above creates a branch named
`2-make-static-site-auto-deploy-and-serve`.
When you click the **Create branch** button in an empty
-repository project, GitLab automatically creates a `master` branch, commits
-a blank `README.md` file to it, and creates and redirects you to a new branch
-based on the issue title.
-If your [project is already configured with a deployment service](../integrations/overview.md),
-such as Kubernetes, GitLab takes one step further and prompts you to set up
-[auto deploy](../../../topics/autodevops/stages.md#auto-deploy)
-by helping you create a `.gitlab-ci.yml` file.
+repository project, GitLab performs these actions:
+
+- Creates a `master` branch.
+- Commits a blank `README.md` file to it.
+- Creates and redirects you to a new branch based on the issue title.
+- _If your project is [configured with a deployment service](../integrations/overview.md) like Kubernetes,_
+ GitLab prompts you to set up [auto deploy](../../../topics/autodevops/stages.md#auto-deploy)
+ by helping you create a `.gitlab-ci.yml` file.
After the branch is created, you can edit files in the repository to fix
-the issue. When a merge request is created based on the newly created branch,
-the description field will automatically display the [issue closing pattern](../issues/managing_issues.md#closing-issues-automatically)
-`Closes #ID`, where `ID` the ID of the issue. This will close the issue once the
+the issue. When a merge request is created based on the newly-created branch,
+the description field displays the [issue closing pattern](../issues/managing_issues.md#closing-issues-automatically)
+`Closes #ID`, where `ID` is the ID of the issue. This closes the issue when the
merge request is merged.
### Create a new branch from a project's dashboard
If you want to make changes to several files before creating a new merge
-request, you can create a new branch upfront. From a project's files page,
-choose **New branch** from the dropdown.
+request, you can create a new branch upfront.
-![New branch dropdown](img/web_editor_new_branch_dropdown.png)
+1. From a project's files page, choose **New branch** from the dropdown.
-Enter a new **Branch name**. Optionally, change the **Create from** field
-to choose which branch, tag, or commit SHA this new branch will originate from.
-This field will autocomplete if you start typing an existing branch or tag.
-Click **Create branch** and you will be returned to the file browser on this new
-branch.
+ ![New branch dropdown](img/web_editor_new_branch_dropdown.png)
-![New branch page](img/web_editor_new_branch_page.png)
+1. Enter a new **Branch name**.
+1. (Optional) Change the **Create from** field to choose which branch, tag, or
+ commit SHA this new branch originates from. This field autocompletes if you
+ start typing an existing branch or tag.
+1. Click **Create branch** to return to the file browser on this new branch.
+
+ ![New branch page](img/web_editor_new_branch_page.png)
You can now make changes to any files, as needed. When you're ready to merge
-the changes back to master, you can use the widget at the top of the screen.
+the changes back to `master`, you can use the widget at the top of the screen.
This widget only appears for a period of time after you create the branch or
modify files.
@@ -167,31 +170,35 @@ modify files.
## Create a new tag
-Tags are useful for marking major milestones such as production releases,
-release candidates, and more. You can create a tag from a branch or a commit
-SHA. From a project's files page, choose **New tag** from the dropdown.
+Tags help you mark major milestones such as production releases and
+release candidates. You can create a tag from a branch or a commit
+SHA:
+
+1. From a project's files page, choose **New tag** from the dropdown.
-![New tag dropdown](img/web_editor_new_tag_dropdown.png)
+ ![New tag dropdown](img/web_editor_new_tag_dropdown.png)
-Give the tag a name such as `v1.0.0`. Choose the branch or SHA from which you
-would like to create this new tag. You can optionally add a message and
-release notes. The release notes section supports Markdown format and you can
-also upload an attachment. Click **Create tag**, and you will be taken to the tag
-list page.
+1. Give the tag a name such as `v1.0.0`.
+1. Choose the branch or SHA from which you want to create this new tag.
+1. (Optional) Add a message and release notes. The release notes section supports
+ Markdown format.
+1. (Optional) Upload an attachment.
+1. Click **Create tag**, and GitLab redirects you to the tag list page.
-![New tag page](img/web_editor_new_tag_page.png)
+ ![New tag page](img/web_editor_new_tag_page.png)
## Tips
When creating or uploading a new file or creating a new directory, you can
-trigger a new merge request rather than committing directly to `master`. Enter
-a new branch name in the **Target branch** field. You will notice a checkbox
-appear that is labeled **Start a new merge request with these changes**. After
-you commit the changes you will be taken to a new merge request form.
+trigger a new merge request rather than committing directly to `master`:
+
+1. Enter a new branch name in the **Target branch** field.
+1. GitLab displays the **Start a new merge request with these changes** check box.
+1. Commit your changes, and GitLab redirects you to a new merge request form.
-![Start a new merge request with these changes](img/web_editor_start_new_merge_request.png)
+ ![Start a new merge request with these changes](img/web_editor_start_new_merge_request.png)
-If you'd prefer _not_ to use your primary email address for commits created
+If you'd prefer to not use your primary email address for commits created
through the web editor, you can choose to use another of your linked email
addresses from the **User Settings > Edit Profile** page.
diff --git a/doc/user/project/repository/x509_signed_commits/index.md b/doc/user/project/repository/x509_signed_commits/index.md
index 639bca0d354..29c1c32145d 100644
--- a/doc/user/project/repository/x509_signed_commits/index.md
+++ b/doc/user/project/repository/x509_signed_commits/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: concepts, howto
---
-# Signing commits and tags with X.509
+# Signing commits and tags with X.509 **(FREE)**
[X.509](https://en.wikipedia.org/wiki/X.509) is a standard format for public key
certificates issued by a public or private Public Key Infrastructure (PKI).
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index c99b0d91523..c7dda81685c 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -23,6 +23,10 @@ When a feature is no longer necessary, you can [archive the related requirement]
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [GitLab 12.10 Introduces Requirements Management](https://www.youtube.com/watch?v=uSS7oUNSEoU).
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a more in-depth walkthrough using a [demonstration project](https://gitlab.com/gitlab-org/requiremeents-mgmt),
+see [GitLab Requirements Traceability Walkthrough](https://youtu.be/VIiuTQYFVa0) (Feb 2021).
+
![requirements list view](img/requirements_list_v13_5.png)
## Create a requirement
@@ -260,7 +264,9 @@ For GitLab.com, it is set to 10 MB.
## Export requirements to a CSV file
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290813) in GitLab 13.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290813) in GitLab 13.8.
+> - Revised CSV column headers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299247) in GitLab 13.9.
+> - Ability to select which fields to export [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290823) in GitLab 13.9.
You can export GitLab requirements to a
[CSV file](https://en.wikipedia.org/wiki/Comma-separated_values) sent to your default notification
@@ -275,19 +281,41 @@ Users with Reporter or higher [permissions](../../permissions.md) can export req
To export requirements:
1. In a project, go to **Requirements**.
-1. Select the **Export as CSV** icon (**{export}**) in the top right. A confirmation modal appears.
+1. In the top right, select the **Export as CSV** icon (**{export}**).
+
+ A confirmation modal appears.
+
+1. Under **Advanced export options**, select which fields to export.
+
+ All fields are selected by default. To exclude a field from being exported, clear the checkbox next to it.
+
1. Select **Export requirements**. The exported CSV file is sent to the email address associated with your user.
### Exported CSV file format
+<!-- vale gitlab.Spelling = NO -->
You can preview the exported CSV file in a spreadsheet editor, such as Microsoft Excel,
OpenOffice Calc, or Google Sheets.
+<!-- vale gitlab.Spelling = YES -->
+
+The exported CSV file contains the following headers:
+
+- In GitLab 13.8:
+
+ - Requirement ID
+ - Title
+ - Description
+ - Author Username
+ - Latest Test Report State
+ - Latest Test Report Created At (UTC)
-The exported CSV file contains the following columns:
+- In GitLab 13.9 and later:
-- Requirement ID
-- Title
-- Description
-- Author Username
-- Latest Test Report State
-- Latest Test Report Created At (UTC)
+ - Requirement ID
+ - Title
+ - Description
+ - Author
+ - Author Username
+ - Created At (UTC)
+ - State
+ - State Updated At (UTC)
diff --git a/doc/user/project/security_dashboard.md b/doc/user/project/security_dashboard.md
deleted file mode 100644
index d9440e8deea..00000000000
--- a/doc/user/project/security_dashboard.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../application_security/security_dashboard/index.md'
----
-
-This document was moved to [another location](../application_security/security_dashboard/index.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 76156690fe7..debe5c51d51 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -4,11 +4,9 @@ group: Certify
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Service Desk **(CORE)**
+# Service Desk **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/149) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215364) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.2.
+> Moved to GitLab Free in 13.2.
Service Desk is a module that allows your team to connect
with any external party through email, without any external tools.
@@ -34,7 +32,7 @@ It provides a unique email address for end users to create issues in a project.
Follow-up notes can be sent either through the GitLab interface or by email. End
users only see the thread through email.
-For instance, let's assume you develop a game for iOS or Android.
+For example, let's assume you develop a game for iOS or Android.
The codebase is hosted in your GitLab instance, built and deployed
with GitLab CI/CD.
@@ -56,74 +54,99 @@ Here's how Service Desk works for you:
## Configuring Service Desk
-NOTE:
-Service Desk is enabled on GitLab.com.
-You can skip step 1 below; you only need to enable it per project.
+Users with Maintainer and higher access in a project can configure Service Desk.
+
+Service Desk issues are [confidential](issues/confidential_issues.md), so they are
+only visible to project members. In GitLab 11.7 we updated the generated email
+address format. The older format is still supported, so existing aliases or
+contacts still work.
+
+If you have [templates](description_templates.md) in your repository, you can optionally select
+one from the selector menu to append it to all Service Desk issues.
-If you have project maintainer access you have the option to set up Service Desk. Follow these steps:
+To enable Service Desk in your project:
-1. [Set up incoming email](../../administration/incoming_email.md#set-it-up) for the GitLab instance.
+1. (GitLab self-managed only) [Set up incoming email](../../administration/incoming_email.md#set-it-up) for the GitLab instance.
We recommend using [email sub-addressing](../../administration/incoming_email.md#email-sub-addressing),
- but in GitLab 11.7 and later you can also use [catch-all mailboxes](../../administration/incoming_email.md#catch-all-mailbox).
-1. Navigate to your project's **Settings > General** and locate the **Service Desk** section.
+ but you can also use [catch-all mailboxes](../../administration/incoming_email.md#catch-all-mailbox).
+1. In a project, in the left sidebar, go to **Settings > General** and expand the **Service Desk** section.
1. Enable the **Activate Service Desk** toggle. This reveals a unique email address to email issues
- to the project. These issues are [confidential](issues/confidential_issues.md), so they are
- only visible to project members. Note that in GitLab 11.7, we updated the generated email
- address's format. The older format is still supported, however, allowing existing aliases or
- contacts to continue working.
+ to the project.
- WARNING:
- This email address can be used by anyone to create an issue on this project, regardless
- of their access level to your GitLab instance. We recommend **putting this behind an alias** so it can be
- changed if needed. We also recommend **[enabling Akismet](../../integration/akismet.md)** on your GitLab
- instance to add spam checking to this service. Unblocked email spam would result in many spam
- issues being created.
+Service Desk is now enabled for this project! To access it in a project, in the left sidebar, select
+**Issues > Service Desk**.
- If you have [templates](description_templates.md) in your repository, you can optionally select
- one from the selector menu to append it to all Service Desk issues.
+WARNING:
+Anyone in your project can use the Service Desk email address to create an issue in this project, **regardless
+of their access level** to your GitLab instance.
-Service Desk is now enabled for this project! You should be able to access it from your project's
-**Issues** menu.
+To improve your project's security, we recommend the following:
-![Service Desk Navigation Item](img/service_desk_nav_item.png)
+- Put the Service Desk email address behind an alias on your email system so you can change it later.
+- [Enable Akismet](../../integration/akismet.md) on your GitLab instance to add spam checking to this service.
+ Unblocked email spam can result in many spam issues being created.
+
+The unique internal email address is visible to project members with Maintainer (or higher)
+[permission level](../permissions.md)
+in your GitLab instance. However, when using an email alias externally, an end user
+(issue creator) cannot see the internal email address displayed in the information note.
### Using customized email templates
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215364) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in GitLab Premium 12.7.
+> - Moved to GitLab Free in 13.2.
An email is sent to the author when:
- A user submits a new issue using Service Desk.
- A new note is created on a Service Desk issue.
-The body of these email messages can be customized by using templates. To create a new customized template,
-create a new Markdown (`.md`) file inside the `.gitlab/service_desk_templates/`
-directory in your repository. Commit and push to your default branch.
+You can customize the body of these email messages with templates.
+Save your templates in the `.gitlab/service_desk_templates/`
+directory in your repository.
+
+With Service Desk, you can use templates for:
+
+- [Thank you emails](#thank-you-email)
+- [New note emails](#new-note-email)
+- [New Service Desk issues](#new-service-desk-issues)
#### Thank you email
-The **Thank you email** is the email sent to a user after they submit an issue.
-The filename of the template has to be `thank_you.md`.
-There are a few placeholders you can use which are automatically replaced in the email:
+When a user submits an issue through Service Desk, GitLab sends a **thank you email**.
+You must name the template file `thank_you.md`.
+
+You can use these placeholders to be automatically replaced in each email:
- `%{ISSUE_ID}`: issue IID
- `%{ISSUE_PATH}`: project path appended with the issue IID
-As the Service Desk issues are created as confidential (only project members can see them)
-the response email does not provide the issue link.
+Because Service Desk issues are created as [confidential](issues/confidential_issues.md) (only project members can see them),
+the response email does not contain the issue link.
#### New note email
-When a user-submitted issue receives a new comment, GitLab sends a **New note email**
-to the user. The filename of this template must be `new_note.md`, and you can
-use these placeholders in the email:
+When a user-submitted issue receives a new comment, GitLab sends a **new note email**.
+You must name the template file `new_note.md`.
+
+You can use these placeholders to be automatically replaced in each email:
- `%{ISSUE_ID}`: issue IID
- `%{ISSUE_PATH}`: project path appended with the issue IID
- `%{NOTE_TEXT}`: note text
+#### New Service Desk issues
+
+You can select one [issue description template](description_templates.md#creating-issue-templates)
+**per project** to be appended to every new Service Desk issue's description.
+Issue description templates should reside in your repository's `.gitlab/issue_templates/` directory.
+
+To use a custom issue template with Service Desk, in your project:
+
+1. [Create a description template](description_templates.md#creating-issue-templates)
+1. Go to **Settings > General > Service Desk**.
+1. From the dropdown **Template to append to all Service Desk issues**, select your template.
+
### Using custom email display name
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7529) in GitLab 12.8.
@@ -139,7 +162,7 @@ To edit the custom email display name:
### Using custom email address
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in GitLab Premium 13.0.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) in GitLab 13.8.
If the `service_desk_email` is configured, then you can create Service Desk
@@ -215,7 +238,8 @@ The configuration options are the same as for configuring
## Using Service Desk
-There are a few ways Service Desk can be used.
+You can use Service Desk to [create an issue](#as-an-end-user-issue-creator) or [respond to one](#as-a-responder-to-the-issue).
+In these issues, you can also see our friendly neighborhood [Support Bot](#support-bot-user).
### As an end user (issue creator)
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 27727890383..6f230f1798a 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -18,7 +18,7 @@ The **GitLab import/export** button is displayed if the project import option is
See also:
- [Project import/export API](../../../api/project_import_export.md)
-- [Project import/export administration Rake tasks](../../../administration/raketasks/project_import_export.md) **(CORE ONLY)**
+- [Project import/export administration Rake tasks](../../../administration/raketasks/project_import_export.md) **(FREE SELF)**
- [Group import/export](../../group/settings/import_export.md)
- [Group import/export API](../../../api/group_import_export.md)
@@ -180,14 +180,14 @@ all imported projects are given the visibility of `Private`.
NOTE:
The maximum import file size can be set by the Administrator, default is `0` (unlimited).
-As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin Area UI](../../admin_area/settings/account_and_limit_settings.md).
+As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin Area UI](../../admin_area/settings/account_and_limit_settings.md). Default [modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8.
### Project import status
You can query an import through the [Project import/export API](../../../api/project_import_export.md#import-status).
As described in the API documentation, the query may return an import error or exceptions.
-### Import large projects **(CORE ONLY)**
+### Import large projects **(FREE SELF)**
If you have a larger project, consider using a Rake task, as described in our [developer documentation](../../../development/import_project.md#importing-via-a-rake-task).
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 26ef5e2260a..8ab82fe7296 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, index, howto
---
-# Project settings
+# Project settings **(FREE)**
NOTE:
Only project maintainers and administrators have the [permissions](../../permissions.md#project-members-permissions)
@@ -40,6 +40,26 @@ You can select a framework label to identify that your project has certain compl
NOTE:
Compliance framework labels do not affect your project settings.
+#### Custom compliance frameworks
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276221) in GitLab 13.9.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-custom-compliance-frameworks). **(PREMIUM)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+GitLab 13.9 introduces custom compliance frameworks at the group-level. A group owner can create a compliance framework label
+and assign it to any number of projects within that group or subgroups. When this feature is enabled, projects can only
+be assigned compliance framework labels that already exist within that group.
+
+If existing [Compliance frameworks](#compliance-framework) are not sufficient, project and group owners
+can now create their own.
+
+New compliance framework labels can be created and updated using GraphQL.
+
### Sharing and permissions
For your repository, you can set up features such as public access, repository features,
@@ -59,7 +79,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) |
-| **Forks** | ✓ | Enables [forking](../index.md#fork-a-project) functionality |
+| **Forks** | ✓ | Enables [forking](../working_with_projects.md#fork-a-project) functionality |
| **Pipelines** | ✓ | Enables [CI/CD](../../../ci/README.md) functionality |
| **Container Registry** | | Activates a [registry](../../packages/container_registry/) for your Docker images |
| **Git Large File Storage** | | Enables the use of [large files](../../../topics/git/lfs/index.md#git-large-file-storage-lfs) |
@@ -120,7 +140,7 @@ Set up your project's merge request settings:
- Set up the merge request method (merge commit, [fast-forward merge](../merge_requests/fast_forward_merge.md)).
- Add merge request [description templates](../description_templates.md#description-templates).
-- Enable [merge request approvals](../merge_requests/merge_request_approvals.md). **(STARTER)**
+- Enable [merge request approvals](../merge_requests/merge_request_approvals.md).
- Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.md).
- Enable [merge only when all threads are resolved](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved).
- Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.md#deleting-the-source-branch)
@@ -128,7 +148,7 @@ Set up your project's merge request settings:
![project's merge request settings](img/merge_requests_settings.png)
-### Service Desk **(STARTER)**
+### Service Desk
Enable [Service Desk](../service_desk.md) for your project to offer customer support.
@@ -201,7 +221,7 @@ To rename a repository:
Remember that this can have unintended side effects since everyone with the
old URL won't be able to push or pull. Read more about what happens with the
-[redirects when renaming repositories](../index.md#redirects-when-changing-repository-paths).
+[redirects when renaming repositories](../repository/index.md#redirects-when-changing-repository-paths).
#### Transferring an existing project into another namespace
@@ -225,7 +245,7 @@ To transfer a project:
Once done, you will be taken to the new project's namespace. At this point,
read what happens with the
-[redirects from the old project to the new one](../index.md#redirects-when-changing-repository-paths).
+[redirects from the old project to the new one](../repository/index.md#redirects-when-changing-repository-paths).
NOTE:
GitLab administrators can use the administration interface to move any project to any
@@ -245,8 +265,8 @@ To delete a project:
This action:
- Deletes a project including all associated resources (issues, merge requests etc).
-- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
-group administrators can [configure](../../group/index.md#enabling-delayed-project-removal) projects within a group
+- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on [Premium](https://about.gitlab.com/pricing/) or higher tiers,
+group owners can [configure](../../group/index.md#enabling-delayed-project-removal) projects within a group
to be deleted after a delayed period.
When enabled, actual deletion happens after number of days
specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
@@ -299,3 +319,22 @@ Add the URL of a Jaeger server to allow your users to [easily access the Jaeger
[Add Storage credentials](../../../operations/incident_management/status_page.md#sync-incidents-to-the-status-page)
to enable the syncing of public Issues to a [deployed status page](../../../operations/incident_management/status_page.md#create-a-status-page-project).
+
+### Enable or disable custom compliance frameworks **(PREMIUM)**
+
+Enabling or disabling custom compliance frameworks 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(:ff_custom_compliance_frameworks)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ff_custom_compliance_frameworks)
+```
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index 39de9ab9ca2..590f549577e 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -8,13 +8,11 @@ type: reference, howto
# Project access tokens
NOTE:
-Project access tokens are supported for self-managed instances on Core and above. They are also supported on GitLab.com Bronze and above (excluding [trial licenses](https://about.gitlab.com/free-trial/)).
+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/)).
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2587) in GitLab 13.0.
-> - It was [deployed](https://gitlab.com/groups/gitlab-org/-/epics/2587) behind a feature flag, disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/218722) in GitLab 13.3.
-> - It's recommended for production use.
-> - [Became available on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in 13.5 for paid groups only.
+> - [Became available on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in GitLab 13.5 for paid groups only.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in GitLab 13.5.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
diff --git a/doc/user/project/slash_commands.md b/doc/user/project/slash_commands.md
deleted file mode 100644
index 5844861c91e..00000000000
--- a/doc/user/project/slash_commands.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: 'quick_actions.md'
----
-
-This document was moved to [user/project/quick_actions.md](quick_actions.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/static_site_editor/index.md b/doc/user/project/static_site_editor/index.md
index 07f122a7828..002eb398406 100644
--- a/doc/user/project/static_site_editor/index.md
+++ b/doc/user/project/static_site_editor/index.md
@@ -6,11 +6,11 @@ type: reference, how-to
description: "The static site editor enables users to edit content on static websites without prior knowledge of the underlying templating language, site architecture or Git commands."
---
-# Static Site Editor **(CORE)**
+# Static Site Editor **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28758) in GitLab 12.10.
> - WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214559) in GitLab 13.0.
-> - Non-Markdown content blocks uneditable on the WYSIWYG mode [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216836) in GitLab 13.3.
+> - 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.
Static Site Editor (SSE) enables users to edit content on static websites without
@@ -23,8 +23,8 @@ and submit the changes for review.
The Static Site Editor allows collaborators to submit changes to static site
files seamlessly. For example:
-- Non-technical collaborators can easily edit a page directly from the browser;
- they don't need to know Git and the details of your project to be able to contribute.
+- Non-technical collaborators can edit a page directly from the browser.
+ They don't need to know Git and the details of your project to contribute.
- Recently hired team members can quickly edit content.
- Temporary collaborators can jump from project to project and quickly edit pages instead
of having to clone or fork every single project they need to submit changes to.
@@ -68,11 +68,11 @@ The editor can then navigate to the merge request to assign it to a colleague fo
## Set up your project
First, set up the project. Once done, you can use the Static Site Editor to
-easily [edit your content](#edit-content).
+[edit your content](#edit-content).
1. To get started, create a new project from the [Static Site Editor - Middleman](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman)
template. You can either [fork it](../repository/forking_workflow.md#creating-a-fork)
- or [create a new project from a template](../../../gitlab-basics/create-project.md#built-in-templates).
+ or [create a new project from a template](../working_with_projects.md#built-in-templates).
1. Edit the [`data/config.yml`](#static-site-generator-configuration) configuration file
to replace `<username>` and `<project-name>` with the proper values for
your project's path.
@@ -101,7 +101,7 @@ To edit a file:
wish to edit the raw Markdown instead, you can toggle the **Markdown** mode
in the bottom-right corner.
1. When you're done, click **Submit changes...**.
-1. (Optional) Adjust the default title and description of the merge request that will be submitted
+1. (Optional) Adjust the default title and description of the merge request, to submit
with your changes. Alternatively, select a [merge request template](../../../user/project/description_templates.md#creating-merge-request-templates)
from the dropdown menu and edit it accordingly.
1. Click **Submit changes**.
@@ -154,9 +154,9 @@ so you can verify the correct image is included and there aren't any references
You can embed YouTube videos on the WYSIWYG mode by clicking the video icon (**{live-preview}**).
The following URL/ID formats are supported:
-- YouTube watch URL (e.g. `https://www.youtube.com/watch?v=0t1DgySidms`)
-- YouTube embed URL (e.g. `https://www.youtube.com/embed/0t1DgySidms`)
-- YouTube video ID (e.g. `0t1DgySidms`)
+- **YouTube watch URLs**: `https://www.youtube.com/watch?v=0t1DgySidms`
+- **YouTube embed URLs**: `https://www.youtube.com/embed/0t1DgySidms`
+- **YouTube video IDs**: `0t1DgySidms`
### Front matter
@@ -164,13 +164,13 @@ The following URL/ID formats are supported:
> - Ability to edit page front matter [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235921) in GitLab 13.5.
Front matter is a flexible and convenient way to define page-specific variables in data files
-intended to be parsed by a static site generator. It is commonly used for setting a page's
-title, layout template, or author, but can be used to pass any kind of metadata to the
+intended to be parsed by a static site generator. Use it to set a page's
+title, layout template, or author. You can also pass any kind of metadata to the
generator as the page renders out to HTML. Included at the very top of each data file, the
-front matter is often formatted as YAML or JSON and requires consistent and accurate syntax.
+front matter is often formatted as YAML or JSON, and requires consistent and accurate syntax.
To edit the front matter from the Static Site Editor you can use the GitLab regular file editor,
-the Web IDE, or easily update the data directly from the WYSIWYG editor:
+the Web IDE, or update the data directly from the WYSIWYG editor:
1. Click the **Page settings** button on the bottom-right to reveal a web form with the data you
have on the page's front matter. The form is populated with the current data:
@@ -181,10 +181,16 @@ the Web IDE, or easily update the data directly from the WYSIWYG editor:
1. When you're done, click **Submit changes...**.
1. Describe your changes (add a commit message).
1. Click **Submit changes**.
-1. Click **View merge request** and GitLab will take you there.
+1. Click **View merge request** to view it.
-Note that support for adding new attributes to the page's front matter from the form is not supported
-yet. You can do so by editing the file locally, through the GitLab regular file editor, or through the Web IDE. Once added, the form will load the new fields.
+Adding new attributes to the page's front matter from the form is not supported.
+To add new attributes:
+
+- Edit the file locally
+- Edit the file with the GitLab regular file editor.
+- Edit the file with the Web IDE.
+
+After adding an attribute, the form loads the new fields.
## Configuration files
@@ -206,8 +212,8 @@ use to customize behavior of the Static Site Editor (SSE). If the file does not
default values which support a default Middleman project configuration are used.
The [Static Site Editor - Middleman](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman) project template generates a file pre-populated with these defaults.
-To customize the behavior of the SSE, edit `.gitlab/static-site-editor.yml`'s entries
-(described in the table below) according to what works best for your project (respecting YAML syntax).
+To customize the behavior of the SSE, edit `.gitlab/static-site-editor.yml`'s entries,
+according to your project's needs. Make sure to respect YAML syntax.
After the table, see an [example of the SSE configuration file](#gitlabstatic-site-editoryml-example).
@@ -224,8 +230,9 @@ image_upload_path: 'source/images' # Relative path to the project's root. Don't
### Static Site Generator configuration
The Static Site Editor uses Middleman's configuration file, `data/config.yml`
-to customize the behavior of the project itself and to control the **Edit this
-page** button, rendered through the file [`layout.erb`](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman/-/blob/master/source/layouts/layout.erb).
+to customize the behavior of the project itself. This file also controls the
+**Edit this page** button, rendered through the file
+[`layout.erb`](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman/-/blob/master/source/layouts/layout.erb).
To [configure the project template to your own project](#set-up-your-project),
you must replace the `<username>` and `<project-name>` in the `data/config.yml`
@@ -236,7 +243,7 @@ the Static Site Editor may use different configuration files or approaches.
## Using Other Static Site Generators
-Although Middleman is the only Static Site Generator currently officially supported
+Although Middleman is the only Static Site Generator officially supported
by the Static Site Editor, you can configure your project's build and deployment
to use a different Static Site Generator. In this case, use the Middleman layout
as an example, and follow a similar approach to properly render an **Edit this page**
diff --git a/doc/user/project/status_page/index.md b/doc/user/project/status_page/index.md
deleted file mode 100644
index 513c410a6f9..00000000000
--- a/doc/user/project/status_page/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-redirect_to: '../../../operations/incident_management/status_page.md'
----
-
-This document was moved to [status_page.md](../../../operations/incident_management/status_page.md).
-
-<!-- This redirect file can be deleted after February 1, 2021. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md
index c94795578ef..2b0ca38c57c 100644
--- a/doc/user/project/time_tracking.md
+++ b/doc/user/project/time_tracking.md
@@ -81,7 +81,7 @@ The following time units are available:
Default conversion rates are 1mo = 4w, 1w = 5d and 1d = 8h.
-### Limit displayed units to hours **(CORE ONLY)**
+### Limit displayed units to hours **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29469/) in GitLab 12.1.
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index af8e78afb28..07f46cb94f7 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -5,12 +5,12 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, how-to
---
-# Web IDE **(CORE)**
+# Web IDE **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) to GitLab Core in 10.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) to GitLab Free in 10.7.
-The Web IDE editor makes it faster and easier to contribute changes to your
+The Web Integrated Development Environment (IDE) editor makes it faster and easier to contribute changes to your
projects by providing an advanced editor with commit staging.
## Open the Web IDE
@@ -22,11 +22,11 @@ and from merge requests.
## File finder
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18323) in [GitLab Core](https://about.gitlab.com/pricing/) 10.8.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18323) in [GitLab Free](https://about.gitlab.com/pricing/) 10.8.
The file finder allows you to quickly open files in the current branch by
searching for fragments of the file path. The file finder is launched using the keyboard shortcut
-<kbd>Cmd</kbd>+<kbd>p</kbd>, <kbd>Ctrl</kbd>+<kbd>p</kbd>, or <kbd>t</kbd>
+<kbd>Command</kbd>+<kbd>p</kbd>, <kbd>Control</kbd>+<kbd>p</kbd>, or <kbd>t</kbd>
(when editor is not in focus). Type the filename or file path fragments to
start seeing results.
@@ -102,7 +102,7 @@ based on the [JSON Schema Store](https://www.schemastore.org/json/).
The Web IDE has validation for certain files built in. This feature is only supported for
the `*.gitlab-ci.yml` files.
-#### Enable or disable validation based on predefined schemas **(CORE ONLY)**
+#### Enable or disable validation based on predefined schemas **(FREE SELF)**
Validation based on predefined schemas is under development and not ready for production use. It is
deployed behind a feature flag that is **disabled by default** for self-managed instances,
@@ -154,7 +154,7 @@ Each schema entry supports two properties:
## Configure the Web IDE
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23352) in [GitLab Core](https://about.gitlab.com/pricing/) 13.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23352) in [GitLab Free](https://about.gitlab.com/pricing/) 13.1.
The Web IDE supports configuration of certain editor settings by using
[`.editorconfig` files](https://editorconfig.org/). When opening a file, the
@@ -174,7 +174,7 @@ The Web IDE currently supports the following `.editorconfig` settings:
## Commit changes
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4539) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) to GitLab Core in 10.7.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44157) to GitLab Free in 10.7.
> - From [GitLab 12.7 onward](https://gitlab.com/gitlab-org/gitlab/-/issues/33441), files were automatically staged.
> - From [GitLab 12.9 onward](https://gitlab.com/gitlab-org/gitlab/-/issues/196609), support for staging files was removed to prevent loss of unstaged data. All your current changes necessarily have to be committed or discarded.
@@ -202,7 +202,7 @@ shows you a preview of the merge request diff if you commit your changes.
## View CI job logs
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19279) in [GitLab Core](https://about.gitlab.com/pricing/) 11.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19279) in [GitLab Free](https://about.gitlab.com/pricing/) 11.0.
You can use the Web IDE to quickly fix failing tests by opening
the branch or merge request in the Web IDE and opening the logs of the failed
@@ -215,7 +215,7 @@ left.
## Switching merge requests
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19318) in [GitLab Core](https://about.gitlab.com/pricing/) 11.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19318) in [GitLab Free](https://about.gitlab.com/pricing/) 11.0.
To switch between your authored and assigned merge requests, click the
dropdown in the top of the sidebar to open a list of merge requests. You need to commit or discard all your changes before switching to a different merge
@@ -223,7 +223,7 @@ request.
## Switching branches
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20850) in [GitLab Core](https://about.gitlab.com/pricing/) 11.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20850) in [GitLab Free](https://about.gitlab.com/pricing/) 11.2.
To switch between branches of the current project repository, click the dropdown
in the top of the sidebar to open a list of branches.
@@ -232,8 +232,8 @@ different branch.
## Markdown editing
-> - Markdown preview [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18059) in [GitLab Core](https://about.gitlab.com/pricing/) 10.7.
-> - Support for pasting images [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22822) in [GitLab Core](https://about.gitlab.com/pricing/) 13.1.
+> - Markdown preview [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18059) in [GitLab Free](https://about.gitlab.com/pricing/) 10.7.
+> - Support for pasting images [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22822) in [GitLab Free](https://about.gitlab.com/pricing/) 13.1.
When you edit Markdown files in the Web IDE, you can preview your changes by
clicking the **Preview Markdown** tab above the file editor. The Markdown preview
@@ -246,7 +246,7 @@ added to the filename.
## Live Preview
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19764) in [GitLab Core](https://about.gitlab.com/pricing/) 11.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19764) in [GitLab Free](https://about.gitlab.com/pricing/) 11.2.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/213853) from _Client Side Evaluation_ to _Live Preview_ in GitLab 13.0.
You can use the Web IDE to preview JavaScript projects right in the browser.
@@ -285,7 +285,7 @@ below.
## Interactive Web Terminals for the Web IDE
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5426) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/211685) to GitLab Core in 13.1.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/211685) to GitLab Free in 13.1.
WARNING:
Interactive Web Terminals for the Web IDE is currently in **Beta**.
@@ -307,7 +307,7 @@ to work:
This section requires at least a `session_timeout` value (which defaults to 1800
seconds) and a `listen_address` value. If `advertise_address` is not defined, `listen_address` is used.
- If you are using a reverse proxy with your GitLab instance, web terminals need to be
- [enabled](../../../administration/integration/terminal.md#enabling-and-disabling-terminal-support). **(ULTIMATE ONLY)**
+ [enabled](../../../administration/integration/terminal.md#enabling-and-disabling-terminal-support). **(ULTIMATE SELF)**
If you have the terminal open and the job has finished with its tasks, the
terminal blocks the job from finishing for the duration configured in
@@ -389,7 +389,7 @@ click **Restart Terminal** to start a new terminal session.
### File syncing to web terminal
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5276) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/211686) to GitLab Core in 13.1.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/211686) to GitLab Free in 13.1.
File changes in the Web IDE can be synced to a running web terminal.
This enables users to test their code changes in a preconfigured terminal
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 779179a6665..187fcb5b3f9 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -1,11 +1,11 @@
---
stage: Create
-group: Knowledge
+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, how-to
---
-# Wiki **(CORE)**
+# Wiki **(FREE)**
A separate system for documentation called Wiki, is built right into each
GitLab project. It is enabled by default on all new projects and you can find
@@ -184,7 +184,7 @@ Similar to versioned diff file views, you can see the changes made in a given Wi
Wiki events (creation, deletion, and updates) are tracked by GitLab and
displayed on the [user profile](../../profile/index.md#user-profile),
[group](../../group/index.md#view-group-activity),
-and [project](../index.md#project-activity) activity pages.
+and [project](../working_with_projects.md#project-activity) activity pages.
## Adding and editing wiki pages locally
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
new file mode 100644
index 00000000000..3fe6193c414
--- /dev/null
+++ b/doc/user/project/working_with_projects.md
@@ -0,0 +1,341 @@
+---
+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"
+---
+
+# Working with projects **(FREE)**
+
+Most work in GitLab is done in a [project](../../user/project/index.md). Files and
+code are saved in projects, and most features are in the scope of projects.
+
+## Explore projects
+
+You can explore other popular projects available on GitLab. To explore projects:
+
+1. Click **Projects** in the navigation bar.
+1. Click **Explore Projects**.
+
+GitLab displays a list of projects, sorted by last updated date. To view
+projects with the most [stars](#star-a-project), click **Most stars**. To view
+projects with the largest number of comments in the past month, click **Trending**.
+
+## Create a project
+
+To create a project in GitLab:
+
+1. In your dashboard, click the green **New project** button or use the plus
+ icon in the navigation bar. This opens the **New project** page.
+1. On the **New project** page, choose if you want to:
+ - Create a [blank project](#blank-projects).
+ - Create a project using one of the available [project templates](#project-templates).
+ - [Import a project](../../user/project/import/index.md) from a different repository,
+ if enabled on your GitLab instance. Contact your GitLab administrator if this is unavailable.
+ - Run [CI/CD pipelines for external repositories](../../ci/ci_cd_for_external_repos/index.md). **(PREMIUM)**
+
+NOTE:
+For a list of words that can't be used as project names see
+[Reserved project and group names](../../user/reserved_names.md).
+
+### Blank projects
+
+To create a new blank project on the **New project** page:
+
+1. On the **Blank project** tab, provide the following information:
+ - The name of your project in the **Project name** field. You can't use
+ special characters, but you can use spaces, hyphens, underscores, or even
+ emoji. When adding the name, the **Project slug** auto populates.
+ The slug is what the GitLab instance uses as the URL path to the project.
+ If you want a different slug, input the project name first,
+ then change the slug after.
+ - The path to your project in the **Project slug** field. This is the URL
+ path for your project that the GitLab instance uses. If the
+ **Project name** is blank, it auto populates when you fill in
+ the **Project slug**.
+ - The **Project description (optional)** field enables you to enter a
+ description for your project's dashboard, which helps others
+ understand what your project is about. Though it's not required, it's a good
+ idea to fill this in.
+ - Changing the **Visibility Level** modifies the project's
+ [viewing and access rights](../../public_access/public_access.md) for users.
+ - Selecting the **Initialize repository with a README** option creates a
+ README file so that the Git repository is initialized, has a default branch, and
+ can be cloned.
+1. Click **Create project**.
+
+### Project templates
+
+Project templates can pre-populate a new project with the necessary files to get you
+started quickly.
+
+There are two main types of project templates:
+
+- [Built-in templates](#built-in-templates), sourced from the following groups:
+ - [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
+ - [`pages`](https://gitlab.com/pages)
+- [Custom project templates](#custom-project-templates), for custom templates
+ configured by GitLab administrators and users.
+
+#### Built-in templates
+
+Built-in templates are project templates that are:
+
+- Developed and maintained in the [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
+ and [`pages`](https://gitlab.com/pages) groups.
+- Released with GitLab.
+
+To use a built-in template on the **New project** page:
+
+1. On the **Create from template** tab, select the **Built-in** tab.
+1. From the list of available built-in templates, click the:
+ - **Preview** button to look at the template source itself.
+ - **Use template** button to start creating the project.
+1. Finish creating the project by filling out the project's details. The process is
+ the same as creating a [blank project](#blank-projects).
+
+##### Enterprise templates **(ULTIMATE)**
+
+GitLab is developing Enterprise templates to help you streamline audit management with selected regulatory standards. These templates automatically import issues that correspond to each regulatory requirement.
+
+To create a new project with an Enterprise template, on the **New project** page:
+
+1. On the **Create from template** tab, select the **Built-in** tab.
+1. From the list of available built-in Enterprise templates, click the:
+ - **Preview** button to look at the template source itself.
+ - **Use template** button to start creating the project.
+1. Finish creating the project by filling out the project's details. The process is the same as creating a [blank project](#blank-projects).
+
+Available Enterprise templates include:
+
+- HIPAA Audit Protocol template ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) in GitLab 12.10)
+
+NOTE:
+You can improve the existing built-in templates or contribute new ones in the
+[`project-templates`](https://gitlab.com/gitlab-org/project-templates) and
+[`pages`](https://gitlab.com/pages) groups by following [these steps](https://gitlab.com/gitlab-org/project-templates/contributing).
+
+##### Custom project templates **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2.
+
+Creating new projects based on custom project templates is a convenient option for
+quickly starting projects.
+
+Custom projects are available at the [instance-level](../../user/admin_area/custom_project_templates.md)
+from the **Instance** tab, or at the [group-level](../../user/group/custom_project_templates.md)
+from the **Group** tab, under the **Create from template** tab.
+
+To use a custom project template on the **New project** page:
+
+1. On the **Create from template** tab, select the **Instance** tab or the **Group** tab.
+1. From the list of available custom templates, click the:
+ - **Preview** button to look at the template source itself.
+ - **Use template** button to start creating the project.
+1. Finish creating the project by filling out the project's details. The process is
+ the same as creating a [blank project](#blank-projects).
+
+## Push to create a new project
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) in GitLab 10.5.
+
+When you create a new repository locally, instead of manually creating a new project in GitLab
+and then [cloning the repository](../../gitlab-basics/start-using-git.md#clone-a-repository)
+locally, you can directly push it to GitLab to create the new project, all without leaving
+your terminal. If you have access rights to the associated namespace, GitLab
+automatically creates a new project under that GitLab namespace with its visibility
+set to Private by default (you can later change it in the [project's settings](../../public_access/public_access.md#how-to-change-project-visibility)).
+
+This can be done by using either SSH or HTTPS:
+
+```shell
+## Git push using SSH
+git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git master
+
+## Git push using HTTPS
+git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master
+```
+
+You can pass the flag `--tags` to the `git push` command to export existing repository tags.
+
+Once the push finishes successfully, a remote message indicates
+the command to set the remote and the URL to the new project:
+
+```plaintext
+remote:
+remote: The private project namespace/nonexistent-project was created.
+remote:
+remote: To configure the remote, run:
+remote: git remote add origin https://gitlab.example.com/namespace/nonexistent-project.git
+remote:
+remote: To view the project, visit:
+remote: https://gitlab.example.com/namespace/nonexistent-project
+remote:
+```
+
+## Fork a project
+
+A fork is a copy of an original repository that you put in another namespace
+where you can experiment and apply changes that you can later decide whether or
+not to share, without affecting the original project.
+
+It takes just a few steps to [fork a project in GitLab](repository/forking_workflow.md#creating-a-fork).
+
+## Star a project
+
+You can star a project to make it easier to find projects you frequently use.
+The number of stars a project has can indicate its popularity.
+
+To star a project:
+
+1. Go to the home page of the project you want to star.
+1. In the upper right corner of the page, click **Star**.
+
+To view your starred projects:
+
+1. Click **Projects** in the navigation bar.
+1. Click **Starred Projects**.
+1. GitLab displays information about your starred projects, including:
+
+ - Project description, including name, description, and icon
+ - Number of times this project has been starred
+ - Number of times this project has been forked
+ - Number of open merge requests
+ - Number of open issues
+
+## Delete a project
+
+To delete a project, first navigate to the home page for that project.
+
+1. Navigate to **Settings > General**.
+1. Expand the **Advanced** section.
+1. Scroll down to the **Delete project** section.
+1. Click **Delete project**
+1. Confirm this action by typing in the expected text.
+
+Projects in personal namespaces are deleted immediately on request. For information on delayed deletion of projects in a group, please see [Enabling delayed project removal](../group/index.md#enabling-delayed-project-removal).
+
+## Project settings
+
+Set the project's visibility level and the access levels to its various pages
+and perform actions like archiving, renaming or transferring a project.
+
+Read through the documentation on [project settings](settings/index.md).
+
+## Project activity
+
+To view the activity of a project, navigate to **Project overview > Activity**.
+From there, you can click on the tabs to see **All** the activity, or see it
+filtered by **Push events**, **Merge events**, **Issue events**, **Comments**,
+**Team**, and **Wiki**.
+
+### Leave a project
+
+**Leave project** only displays on the project's dashboard
+when a project is part of a group (under a
+[group namespace](../group/index.md#namespaces)).
+If you choose to leave a project you are no longer a project
+member, and cannot contribute.
+
+## Use your project as a Go package
+
+Any project can be used as a Go package. GitLab responds correctly to `go get`
+and `godoc.org` discovery requests, including the
+[`go-import`](https://golang.org/cmd/go/#hdr-Remote_import_paths) and
+[`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links) meta tags.
+
+Private projects, including projects in subgroups, can be used as a Go package,
+but may require configuration to work correctly. GitLab responds correctly
+to `go get` discovery requests for projects that *are not* in subgroups,
+regardless of authentication or authorization.
+[Authentication](#authenticate-go-requests) is required to use a private project
+in a subgroup as a Go package. Otherwise, GitLab truncates the path for
+private projects in subgroups to the first two segments, causing `go get` to
+fail.
+
+GitLab implements its own Go proxy. This feature must be enabled by an
+administrator and requires additional configuration. See [GitLab Go
+Proxy](../packages/go_proxy/index.md).
+
+### Disable Go module features for private projects
+
+In Go 1.12 and later, Go queries module proxies and checksum databases in the
+process of [fetching a
+module](../../development/go_guide/dependencies.md#fetching). This can be
+selectively disabled with `GOPRIVATE` (disable both),
+[`GONOPROXY`](../../development/go_guide/dependencies.md#proxies) (disable proxy
+queries), and [`GONOSUMDB`](../../development/go_guide/dependencies.md#fetching)
+(disable checksum queries).
+
+`GOPRIVATE`, `GONOPROXY`, and `GONOSUMDB` are comma-separated lists of Go
+modules and Go module prefixes. For example,
+`GOPRIVATE=gitlab.example.com/my/private/project` disables queries for that
+one project, but `GOPRIVATE=gitlab.example.com` disables queries for *all*
+projects on GitLab.com. Go does not query module proxies if the module name or a
+prefix of it appears in `GOPRIVATE` or `GONOPROXY`. Go does not query checksum
+databases if the module name or a prefix of it appears in `GONOPRIVATE` or
+`GONOSUMDB`.
+
+### Authenticate Go requests
+
+To authenticate requests to private projects made by Go, use a [`.netrc`
+file](https://ec.haxx.se/usingcurl-netrc.html) and a [personal access
+token](../profile/personal_access_tokens.md) in the password field. **This only
+works if your GitLab instance can be accessed with HTTPS.** The `go` command
+does not transmit credentials over insecure connections. This authenticates
+all HTTPS requests made directly by Go, but does not authenticate requests made
+through Git.
+
+For example:
+
+```plaintext
+machine gitlab.example.com
+login <gitlab_user_name>
+password <personal_access_token>
+```
+
+NOTE:
+On Windows, Go reads `~/_netrc` instead of `~/.netrc`.
+
+### Authenticate Git fetches
+
+If a module cannot be fetched from a proxy, Go falls back to using Git (for
+GitLab projects). Git uses `.netrc` to authenticate requests. You can also
+configure Git to either:
+
+- Embed specific credentials in the request URL.
+- Use SSH instead of HTTPS, as Go always uses HTTPS to fetch Git repositories.
+
+```shell
+# Embed credentials in any request to GitLab.com:
+git config --global url."https://${user}:${personal_access_token}@gitlab.example.com".insteadOf "https://gitlab.example.com"
+
+# Use SSH instead of HTTPS:
+git config --global url."git@gitlab.example.com".insteadOf "https://gitlab.example.com"
+```
+
+## Access project page with project ID
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53671) in GitLab 11.8.
+
+To quickly access a project from the GitLab UI using the project ID,
+visit the `/projects/:id` URL in your browser or other tool accessing the project.
+
+## Project's landing page
+
+The project's landing page shows different information depending on
+the project's visibility settings and user permissions.
+
+For public projects, and to members of internal and private projects
+with [permissions to view the project's code](../permissions.md#project-members-permissions):
+
+- The content of a
+ [`README` or an index file](repository/#repository-readme-and-index-files)
+ is displayed (if any), followed by the list of directories in the
+ project's repository.
+- If the project doesn't contain either of these files, the
+ visitor sees the list of files and directories of the repository.
+
+For users without permissions to view the project's code, GitLab displays:
+
+- The wiki homepage, if any.
+- The list of issues in the project.
diff --git a/doc/user/search/advanced_global_search.md b/doc/user/search/advanced_global_search.md
index 1898bdf06a9..2d1a05cd966 100644
--- a/doc/user/search/advanced_global_search.md
+++ b/doc/user/search/advanced_global_search.md
@@ -5,9 +5,10 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Advanced Search **(STARTER)**
+# Advanced Search **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109) in GitLab [Starter](https://about.gitlab.com/pricing/) 8.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109) in GitLab 8.4.
+> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9.
NOTE:
Advanced Search (powered by Elasticsearch) is enabled for Bronze and above on GitLab.com since 2020-07-10.
diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md
index e3501be8e8e..19f7305124e 100644
--- a/doc/user/search/advanced_search_syntax.md
+++ b/doc/user/search/advanced_search_syntax.md
@@ -5,12 +5,10 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Advanced Search Syntax **(STARTER)**
+# Advanced Search Syntax **(PREMIUM)**
-> - Introduced in [GitLab Enterprise Starter](https://about.gitlab.com/pricing/) 9.2
-
-NOTE:
-Advanced Search (powered by Elasticsearch) is enabled for Bronze and above on GitLab.com since 2020-07-10.
+> - Introduced in [GitLab](https://about.gitlab.com/pricing/) 9.2.
+> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9.
Use advanced queries for more targeted search results.
diff --git a/doc/user/search/img/search_history.gif b/doc/user/search/img/search_history.gif
deleted file mode 100644
index 4cfa48ee0ab..00000000000
--- a/doc/user/search/img/search_history.gif
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index d229c27b608..ffd331248be 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -9,16 +9,14 @@ type: index, reference, howto
## Issues and merge requests
-To search through issues and merge requests in multiple projects, you can use the **Issues** or **Merge Requests** links
-in the top-right part of your screen.
+To search through issues and merge requests in multiple projects, use the **Issues** or **Merge Requests** links
+in the top-right part of your screen. These instructions are valid for both.
-Both of them work in the same way, therefore, the following notes are valid for both.
-
-The number displayed on their right represents the number of issues and merge requests assigned to you.
+The number displayed on their right represents the number of issues and merge requests assigned to you:
![issues and MRs dashboard links](img/dashboard_links.png)
-When you click **Issues**, the opened issues assigned to you are shown straight away:
+When you click **Issues**, GitLab shows the opened issues assigned to you:
![Issues assigned to you](img/issues_assigned_to_you.png)
@@ -30,7 +28,7 @@ You can also filter the results using the search and filter field, as described
### Issues and MRs assigned to you or created by you
GitLab shows shortcuts to issues and merge requests created by you or assigned to you
-on the search field on the top-right of your screen:
+in the search field in the upper right corner:
![shortcut to your issues and merge requests](img/issues_mrs_shortcut.png)
@@ -38,7 +36,7 @@ on the search field on the top-right of your screen:
> - Filtering by Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
> - Filtering by child Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
-> - Filtering by Iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6.
+> - Filtering by Iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9.
Follow these steps to filter the **Issues** and **Merge Requests** list pages in projects and
groups:
@@ -101,32 +99,34 @@ You can filter the **Issues** list to individual instances by their ID. For exam
![filter issues by specific id](img/issue_search_by_id.png)
-### Filtering merge requests by approvers **(STARTER)**
+### Filtering merge requests by approvers **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9468) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9468) in GitLab 11.9.
+> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9.
To filter merge requests by an individual approver, you can type (or select from
the dropdown) **Approver** and select the user.
![Filter MRs by an approver](img/filter_approver_merge_requests.png)
-### Filtering merge requests by "approved by" **(STARTER)**
+### Filtering merge requests by "approved by" **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30335) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30335) in GitLab 13.0.
+> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9.
To filter merge requests already approved by a specific individual, you can type (or select from
the dropdown) **Approved-By** and select the user.
![Filter MRs by approved by](img/filter_approved_by_merge_requests_v13_0.png)
-### Filtering merge requests by reviewer **(CORE)**
+### Filtering merge requests by reviewer **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47605) in GitLab 13.7.
To filter review requested merge requests for a specific individual, you can type (or select from
the dropdown) **Reviewer** and select the user.
-### Filtering merge requests by environment or deployment date **(CORE)**
+### Filtering merge requests by environment or deployment date **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6.
@@ -156,15 +156,16 @@ using the filter functionality, you can start typing characters to bring up
relevant users or other attributes.
For performance optimization, there is a requirement of a minimum of three
-characters to begin your search. For example, if you want to search for
-issues that have the assignee "Simone Presley", you must type at
-least "Sim" before autocomplete gives any relevant results.
+characters to begin your search. To search for issues with the assignee `Simone Presley`,
+you must type at least `Sim` before autocomplete displays results.
## Search history
-You can view recent searches by clicking on the little arrow-clock icon, which is to the left of the search input. Click the search entry to run that search again. This feature is available for issues and merge requests. Searches are stored locally in your browser.
+Search history is available for issues and merge requests, and is stored locally
+in your browser. To run a search from history:
-![search history](img/search_history.gif)
+1. In the top menu, click **Issues** or **Merge requests**.
+1. To the left of the search bar, click **Recent searches**, and select a search from the list.
## Removing search filters
@@ -174,7 +175,7 @@ To delete filter tokens one at a time, the <kbd>⌥</kbd> (Mac) / <kbd>Control</
## Filtering with multiple filters of the same type
-Some filters can be added multiple times. These include but are not limited to assignees and labels. When you filter with these multiple filters of the same type, the AND logic is applied. For example, if you were filtering `assignee:@sam assignee:@sarah`, your results include only entries whereby the assignees are assigned to both Sam and Sarah are returned.
+Some filters can be added multiple times. These include but are not limited to assignees and labels. When you filter with these multiple filters of the same type, the `AND` logic is applied. For example, if you were filtering `assignee:@sam assignee:@sarah`, your results include only entries whereby the assignees are assigned to both Sam and Sarah are returned.
![multiple assignees filtering](img/multiple_assignees.png)
@@ -192,8 +193,8 @@ You can search through your projects from the left menu, by clicking the menu ba
On the field **Filter by name**, type the project or group name you want to find, and GitLab
filters them for you as you type.
-You can also look for the projects you [starred](../project/index.md#star-a-project) (**Starred projects**), and **Explore** all
-public and internal projects available in GitLab.com, from which you can filter by visibility,
+You can also look for the projects you [starred](../project/working_with_projects.md#star-a-project) (**Starred projects**).
+You can **Explore** all public and internal projects available in GitLab.com, from which you can filter by visibility,
through **Trending**, best rated with **Most stars**, or **All** of them.
You can also sort them by **Name**, **Last created**, **Oldest created**, **Last updated**,
@@ -217,7 +218,7 @@ and sort them by **Last created**, **Oldest created**, **Last updated**, or **Ol
From an [Issue Board](../../user/project/issue_board.md), you can filter issues by **Author**, **Assignee**, **Milestone**, and **Labels**.
You can also filter them by name (issue title), from the field **Filter by name**, which is loaded as you type.
-When you want to search for issues to add to lists present in your Issue Board, click
+To search for issues to add to lists present in your Issue Board, click
the button **Add issues** on the top-right of your screen, opening a modal window from which
you can, besides filtering them by **Name**, **Author**, **Assignee**, **Milestone**,
and **Labels**, select multiple issues to add to a list of your choice:
@@ -226,10 +227,14 @@ and **Labels**, select multiple issues to add to a list of your choice:
## Shortcut
-GitLab shows a shortcut on the search field on the top-right of the project's dashboard to
-quickly access issues and merge requests created or assigned to you in that project:
+To view issues and merge requests created or assigned to you in a project:
+
+1. Go to your project.
+1. In the top navigation bar, click the search box to display a list of issues and
+ merge requests.
+1. Select your desired issue or merge request:
-![search per project - shortcut](img/project_search.png)
+ ![search per project - shortcut](img/project_search.png)
### Autocomplete suggestions
@@ -246,7 +251,7 @@ You can also type in this search bar to see autocomplete suggestions for:
## Basic search
-The Basic search in GitLab is a global search service that allows you to search
+The Basic search in GitLab enables you to search
across the entire GitLab instance, in a group, or in a single project. Basic search is
backed by the database and allows searching in:
@@ -288,14 +293,14 @@ redirected to the commit result and given the option to return to the search res
![project SHA search redirect](img/project_search_sha_redirect.png)
-## Advanced Search **(STARTER)**
+## Advanced Search **(PREMIUM)**
Leverage Elasticsearch for faster, more advanced code search across your entire
GitLab instance.
[Learn how to use the Advanced Search.](advanced_global_search.md)
-## Advanced Search Syntax **(STARTER)**
+## Advanced Search Syntax **(PREMIUM)**
Use advanced queries for more targeted search results.
@@ -307,7 +312,7 @@ Use advanced queries for more targeted search results.
> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default.
> - It's disabled on GitLab.com.
> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-search-project-settings). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-search-project-settings). **(FREE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -318,7 +323,7 @@ appear highlighted in the sections that match the search term.
![Search project settings](img/project_search_general_settings_v13_8.png)
-### Enable or disable Search project settings **(CORE ONLY)**
+### Enable or disable Search project settings **(FREE SELF)**
Search project settings is under development and not ready for production use. It is
deployed behind a feature flag that is **disabled by default**.
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index 282e3296735..014555cffed 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -35,6 +35,7 @@ These shortcuts are available in most areas of GitLab
| <kbd>Shift</kbd> + <kbd>m</kbd> | Go to your Merge requests page.|
| <kbd>Shift</kbd> + <kbd>t</kbd> | Go to your To-Do List page. |
| <kbd>p</kbd> + <kbd>b</kbd> | Show/hide the Performance Bar. |
+| <kbd>g</kbd> + <kbd>x</kbd> | Toggle between [GitLab](https://gitlab.com/) and [GitLab Next](https://next.gitlab.com/) (GitLab SaaS only). |
Additionally, the following shortcuts are available when editing text in text fields,
for example comments, replies, issue descriptions, and merge request descriptions:
@@ -42,10 +43,10 @@ for example comments, replies, issue descriptions, and merge request description
| Keyboard Shortcut | Description |
| ---------------------------------------------------------------------- | ----------- |
| <kbd>↑</kbd> | Edit your last comment. You must be in a blank text field below a thread, and you must already have at least one comment in the thread. |
-| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>p</kbd> | Toggle Markdown preview, when editing text in a text field that has **Write** and **Preview** tabs at the top. |
-| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>b</kbd> | Bold the selected text (surround it with `**`). |
-| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>i</kbd> | Italicize the selected text (surround it with `_`). |
-| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>k</kbd> | Add a link (surround the selected text with `[]()`). |
+| <kbd>⌘</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Shift</kbd> + <kbd>p</kbd> | Toggle Markdown preview, when editing text in a text field that has **Write** and **Preview** tabs at the top. |
+| <kbd>⌘</kbd> (Mac) / <kbd>Control</kbd> + <kbd>b</kbd> | Bold the selected text (surround it with `**`). |
+| <kbd>⌘</kbd> (Mac) / <kbd>Control</kbd> + <kbd>i</kbd> | Italicize the selected text (surround it with `_`). |
+| <kbd>⌘</kbd> (Mac) / <kbd>Control</kbd> + <kbd>k</kbd> | Add a link (surround the selected text with `[]()`). |
NOTE:
The shortcuts for editing in text fields are always enabled, even when
@@ -104,7 +105,7 @@ These shortcuts are available when browsing the files in a project (navigate to
| <kbd>↑</kbd> | Move selection up. |
| <kbd>↓</kbd> | Move selection down. |
| <kbd>enter</kbd> | Open selection. |
-| <kbd>esc</kbd> | Go back to file list screen (only while searching for files, **Repository > Files** then click on **Find File**). |
+| <kbd>Escape</kbd> | Go back to file list screen (only while searching for files, **Repository > Files** then click on **Find File**). |
| <kbd>y</kbd> | Go to file permalink (only while viewing a file). |
### Web IDE
@@ -113,8 +114,8 @@ These shortcuts are available when editing a file with the [Web IDE](project/web
| Keyboard Shortcut | Description |
| ------------------------------------------------------- | ----------- |
-| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>p</kbd> | Search for, and then open another file for editing. |
-| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>Enter</kbd> | Commit (when editing the commit message). |
+| <kbd>⌘</kbd> (Mac) / <kbd>Control</kbd> + <kbd>p</kbd> | Search for, and then open another file for editing. |
+| <kbd>⌘</kbd> (Mac) / <kbd>Control</kbd> + <kbd>Enter</kbd> | Commit (when editing the commit message). |
### Repository Graph
@@ -145,7 +146,7 @@ These shortcuts are available when using a [filtered search input](search/index.
| Keyboard Shortcut | Description |
| ----------------------------------------------------- | ----------- |
| <kbd>⌘</kbd> (Mac) + <kbd>⌫</kbd> | Clear entire search filter. |
-| <kbd>⌥</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>⌫</kbd> | Clear one token at a time. |
+| <kbd>⌥</kbd> (Mac) / <kbd>Control</kbd> + <kbd>⌫</kbd> | Clear one token at a time. |
## Epics **(ULTIMATE)**
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index af499221da6..e919e73f404 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -65,8 +65,8 @@ have version control enabled by default.
This means that all snippets get their own underlying repository initialized with
a `master` branch at the moment the snippet is created. Whenever a change to the snippet is saved, a
-new commit to the master branch is recorded. Commit messages are automatically
-generated. The snippet's repository has only one branch (master) by default, deleting
+new commit to the `master` branch is recorded. Commit messages are automatically
+generated. The snippet's repository has only one branch (`master`) by default, deleting
it or creating other branches is not supported.
Existing snippets are automatically migrated in 13.0. Their current
@@ -75,14 +75,14 @@ content is saved as the initial commit to the snippets' repository.
### Filenames
Snippets support syntax highlighting based on the filename and
-extension provided for them. While it is possible to submit a snippet
+extension provided for them. While you can submit a snippet
without specifying a filename and extension, it needs a valid name so the
content can be created as a file in the snippet's repository.
-In case the user does not attribute a filename and extension to a snippet,
-GitLab automatically adds a filename in the format `snippetfile<x>.txt`
+If you don't attribute a filename and extension to a snippet,
+GitLab adds a filename in the format `snippetfile<x>.txt`
where `<x>` represents a number added to the file, starting with 1. This
-number increases incrementally when more snippets without an attributed
+number increments when more snippets without an attributed
filename are added.
When upgrading from an earlier version of GitLab to 13.0, existing snippets
@@ -96,14 +96,15 @@ direct or embedded links to the snippet.
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2829) in GitLab 13.5.
-GitLab Snippets support multiple files in one single snippet. It can be very handy
+GitLab Snippets support multiple files in one single snippet. This is helpful
when your code snippet is composed of multiple parts or when they relate
to a certain context. For example:
- A snippet that includes a script and its output.
- A snippet that includes HTML, CSS, and JS code.
- A snippet with a `docker-compose.yml` file and its associated `.env` file.
-- A `gulpfile.js` file coupled with a `package.json` file, which together can be used to bootstrap a project and manage its dependencies.
+- A `gulpfile.js` file coupled with a `package.json` file, which together can be
+ used to bootstrap a project and manage its dependencies.
Snippets support between 1 and 10 files. They can be managed via Git (because they're [versioned](#versioned-snippets)
by a Git repository), through the [Snippets API](../api/snippets.md), or in the GitLab UI.
@@ -135,7 +136,7 @@ button above the snippet content to copy the URL of your choice.
This allows you to have a local copy of the snippet's repository and make
changes as needed. You can commit those changes and push them to the remote
-master branch.
+`master` branch.
### Reduce snippets repository size
@@ -148,15 +149,15 @@ see the documentation on [reducing repository size](../user/project/repository/r
### Limitations
- Binary files are not supported.
-- Creating or deleting branches is not supported. Only a default *master* branch is used.
+- Creating or deleting branches is not supported. Only a default `master` branch is used.
- Git tags are not supported in snippet repositories.
- Snippets' repositories are limited to 10 files. Attempting to push more
-than 10 files results in an error.
-- Revisions are not *yet* visible to the user on the GitLab UI, but
-it's planned to be added in future iterations. See the [revisions tab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39271)
-for updates.
+ than 10 files results in an error.
+- Revisions are not visible to the user on the GitLab UI, but this feature is planned
+ in future iterations. See the [revisions tab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39271)
+ for updates.
- The [maximum size for a snippet](../administration/snippets/index.md#snippets-content-size-limit)
-is 50 MB, by default.
+ is 50 MB, by default.
- Git LFS is not supported.
## Discover snippets
@@ -168,10 +169,10 @@ dashboard of your GitLab instance via the top navigation. For GitLab.com you can
navigate to an [overview]((https://gitlab.com/dashboard/snippets)) that shows snippets
you created and allows you to explore all snippets.
-If you want to discover snippets that belong to a specific project, you can navigate
+To discover snippets that belong to a specific project, navigate
to the Snippets page via the left side navigation on the project page.
-Project snippets are enabled and available by default, but they can
-be disabled by navigating to your project's **Settings**, expanding
+Project snippets are enabled and available by default. You can
+disable them by navigating to your project's **Settings**, expanding
**Visibility, project features, permissions** and scrolling down to
**Snippets**. From there, you can toggle to disable them or select a
different visibility level from the dropdown menu.
@@ -181,7 +182,7 @@ different visibility level from the dropdown menu.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/12910) in GitLab 9.2.
With GitLab Snippets you engage in a conversation about that piece of code,
-facilitating the collaboration among users.
+encouraging user collaboration.
## Downloading snippets
@@ -207,20 +208,23 @@ To embed a snippet, first make sure that:
- In **Project > Settings > Permissions**, the snippets permissions are
set to **Everyone with access**
-After the above conditions are met, the "Embed" section appears in your
-snippet where you can simply click on the "Copy" button. This copies a one-line
-script that you can add to any website or blog post.
-
-Here's how an example code looks like:
+After the above conditions are met, the **Embed** section appears in your
+snippet. Click the **Copy** button to copy a one-line
+script that you can add to any website or blog post. For example:
```html
<script src="https://gitlab.com/namespace/project/snippets/SNIPPET_ID.js"></script>
```
-Here's how an embedded snippet looks like:
+Here's what an embedded snippet looks like:
<script src="https://gitlab.com/gitlab-org/gitlab-foss/snippets/1717978.js"></script>
-Embedded snippets are displayed with a header that shows the filename if it's defined,
-the snippet size, a link to GitLab, and the actual snippet content. Actions in
-the header allow users to see the snippet in raw format and download it.
+Embedded snippets are displayed with a header that shows:
+
+- The filename, if defined.
+- The snippet size.
+- A link to GitLab.
+- The actual snippet content.
+
+Actions in the header enable users to see the snippet in raw format, and download it.
diff --git a/doc/user/todos.md b/doc/user/todos.md
index 27a849719c5..57ab7d4d888 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -5,7 +5,7 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GitLab To-Do List **(CORE)**
+# GitLab To-Do List **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2817) in GitLab 8.5.
diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md
index e50b6959a70..183ce5e4312 100644
--- a/doc/user/upgrade_email_bypass.md
+++ b/doc/user/upgrade_email_bypass.md
@@ -116,7 +116,7 @@ LDAP Users remain confirmed if all of the following conditions are met:
- The ["User email confirmation at sign-up" option](../security/user_email_confirmation.md) is set to false.
- The first sign-in is based on user LDAP credentials.
-- The user has added and verified [a secondary email address](profile/index.md#profile-settings) some time later.
+- The user has added and verified [a secondary email address](profile/index.md#user-settings) some time later.
NOTE:
Confirmation timestamps (primary vs. secondary) are different.
@@ -124,6 +124,6 @@ Confirmation timestamps (primary vs. secondary) are different.
Users remain unconfirmed by the background migration if any of the following conditions are met:
- They [create an account through GitLab](profile/account/create_accounts.md).
-- They [swap their primary email address](profile/index.md#profile-settings) and verify it.
+- They [swap their primary email address](profile/index.md#user-settings) and verify it.
- If they have two email addresses with the same `confirmed_at` timestamp due to the linked [security issue](https://gitlab.com/gitlab-org/gitlab/-/issues/121664).
- [LDAP is introduced](../administration/auth/ldap/index.md), and users' primary email address matches that in LDAP.
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index 8662efc03a7..16ba2582101 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -1,13 +1,13 @@
---
type: howto
stage: Fulfillment
-group: Provision
+group: Utilization
info: 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
---
# Storage usage quota
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13294) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/13294) in GitLab 12.0.
> - Moved to GitLab Free.
A project's repository has a free storage quota of 10 GB. When a project's repository reaches
@@ -32,11 +32,11 @@ namespace to trigger a recalculation.
A stacked bar graph shows the proportional storage used for the namespace, including a total per
storage item. Click on each project's title to see a breakdown per storage item.
-## Storage usage statistics **(BRONZE ONLY)**
+## Storage usage statistics
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247831) in GitLab 13.7.
> - It's [deployed behind a feature flag](../user/feature_flags.md), enabled by default.
-> - It's enabled on GitLab.com.
+> - It's enabled on GitLab SaaS.
> - It's recommended for production use.
WARNING:
diff --git a/generator_templates/usage_metric_definition/metric_definition.yml b/generator_templates/usage_metric_definition/metric_definition.yml
new file mode 100644
index 00000000000..abe9a266dd6
--- /dev/null
+++ b/generator_templates/usage_metric_definition/metric_definition.yml
@@ -0,0 +1,21 @@
+---
+# See Usage Ping metrics dictionary docs https://docs.gitlab.com/ee/development/usage_ping/metrics_dictionary.html
+key_path: <%= key_path %>
+description:
+product_section:
+product_stage:
+product_group:
+product_category:
+value_type: <%= value_type %>
+status: implemented
+milestone: <%= milestone %>
+introduced_by_url:
+time_frame: <%= time_frame %>
+data_source:
+distribution:
+<%= distribution %>
+# Add here corresponding tiers
+# tier:
+# - free
+# - premium
+# - ultimate
diff --git a/lefthook.yml b/lefthook.yml
index 5e307f9af30..3469cd9bddf 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -16,7 +16,7 @@ pre-push:
markdownlint:
tags: documentation style
files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
- glob: "*.md"
+ glob: "doc/*.md"
run: yarn markdownlint {files}
scss-lint:
tags: stylesheet css style
@@ -32,5 +32,5 @@ pre-push:
vale: # Requires Vale: https://docs.gitlab.com/ee/development/documentation/#install-linters
tags: documentation style
files: git diff --name-only $(git merge-base origin/master HEAD)..HEAD
- glob: "*.md"
+ glob: "doc/*.md"
run: if command -v vale 2> /dev/null; then vale --config .vale.ini --minAlertLevel error {files}; else echo "Vale not found. Install Vale"; fi
diff --git a/lib/api/api.rb b/lib/api/api.rb
index ada0da28749..0598f03c7ab 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -30,7 +30,7 @@ module API
]
allow_access_with_scope :api
- allow_access_with_scope :read_api, if: -> (request) { request.get? }
+ allow_access_with_scope :read_api, if: -> (request) { request.get? || request.head? }
prefix :api
version 'v3', using: :path do
@@ -68,6 +68,10 @@ module API
set_peek_enabled_for_current_request
end
+ after do
+ Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter.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 }
@@ -123,13 +127,32 @@ module API
format :json
formatter :json, Gitlab::Json::GrapeFormatter
+ content_type :json, 'application/json'
+ # Remove the `text/plain+deprecated` with `api_always_use_application_json` feature flag
# There is a small chance some users depend on the old behavior.
# We this change under a feature flag to see if affects GitLab.com users.
- if Gitlab::Database.cached_table_exists?('features') && Feature.enabled?(:api_json_content_type)
- content_type :json, 'application/json'
- else
- content_type :txt, 'text/plain'
+ # The `+deprecated` is added to distinguish content type
+ # as defined by `API::API` vs ex. `API::Repositories`
+ content_type :txt, 'text/plain+deprecated'
+
+ before do
+ # the feature flag workaround is only for `.txt`
+ api_format = env[Grape::Env::API_FORMAT]
+ next unless api_format == :txt
+
+ # get all defined content-types for the endpoint
+ api_endpoint = env[Grape::Env::API_ENDPOINT]
+ content_types = api_endpoint&.namespace_stackable_with_hash(:content_types).to_h
+
+ # Only overwrite `text/plain+deprecated`
+ if content_types[api_format] == 'text/plain+deprecated'
+ if Feature.enabled?(:api_always_use_application_json)
+ content_type 'application/json'
+ else
+ content_type 'text/plain'
+ end
+ end
end
# Ensure the namespace is right, otherwise we might load Grape::API::Helpers
@@ -249,6 +272,8 @@ module API
mount ::API::Release::Links
mount ::API::RemoteMirrors
mount ::API::Repositories
+ mount ::API::ResourceAccessTokens
+ mount ::API::RubygemPackages
mount ::API::Search
mount ::API::Services
mount ::API::Settings
@@ -294,4 +319,4 @@ module API
end
end
-API::API.prepend_if_ee('::EE::API::API')
+API::API.prepend_ee_mod
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index 8b14e16b495..b883f83cc19 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -8,15 +8,6 @@ module API
feature_category :authentication_and_authorization
resource :applications do
- helpers do
- def validate_redirect_uri(value)
- uri = ::URI.parse(value)
- !uri.is_a?(URI::HTTP) || uri.host
- rescue URI::InvalidURIError
- false
- end
- end
-
desc 'Create a new application' do
detail 'This feature was introduced in GitLab 10.5'
success Entities::ApplicationWithSecret
@@ -30,13 +21,6 @@ module API
desc: 'Application will be used where the client secret is confidential'
end
post do
- # Validate that host in uri is specified
- # Please remove it when https://github.com/doorkeeper-gem/doorkeeper/pull/1440 is merged
- # and the doorkeeper gem version is bumped
- unless validate_redirect_uri(declared_params[:redirect_uri])
- render_api_error!({ redirect_uri: ["must be an absolute URI."] }, :bad_request)
- end
-
application = Doorkeeper::Application.new(declared_params)
if application.save
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 1b36e27f6c9..fa75d012613 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -121,6 +121,7 @@ module API
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ optional :include_retried, type: Boolean, default: false, desc: 'Includes retried jobs'
use :optional_scope
use :pagination
end
diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb
index 6c8b3a1ba4a..1796d51324f 100644
--- a/lib/api/concerns/packages/conan_endpoints.rb
+++ b/lib/api/concerns/packages/conan_endpoints.rb
@@ -72,6 +72,7 @@ module API
namespace 'users' do
format :txt
+ content_type :txt, 'text/plain'
desc 'Authenticate user against conan CLI' do
detail 'This feature was introduced in GitLab 12.2'
diff --git a/lib/api/debian_group_packages.rb b/lib/api/debian_group_packages.rb
index e3cacc4132f..f138f400601 100644
--- a/lib/api/debian_group_packages.rb
+++ b/lib/api/debian_group_packages.rb
@@ -8,12 +8,14 @@ module API
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
+ require_packages_enabled!
+
not_found! unless ::Feature.enabled?(:debian_packages, user_group)
authorize_read_package!(user_group)
end
- namespace ':id/-/packages/debian' do
+ namespace ':id/packages/debian' do
include DebianPackageEndpoints
end
end
diff --git a/lib/api/debian_package_endpoints.rb b/lib/api/debian_package_endpoints.rb
index c95c75b7e5c..e7689b3feff 100644
--- a/lib/api/debian_package_endpoints.rb
+++ b/lib/api/debian_package_endpoints.rb
@@ -32,6 +32,7 @@ module API
helpers ::API::Helpers::Packages::BasicAuthHelpers
format :txt
+ content_type :txt, 'text/plain'
rescue_from ArgumentError do |e|
render_api_error!(e.message, 400)
@@ -50,33 +51,33 @@ module API
end
namespace 'dists/*distribution', requirements: DISTRIBUTION_REQUIREMENTS do
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/Release.gpg
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release.gpg
desc 'The Release file signature' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Release.gpg' do
not_found!
end
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/Release
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/Release
desc 'The unsigned Release file' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Release' do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO Release'
end
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/InRelease
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/InRelease
desc 'The signed Release file' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'InRelease' do
not_found!
end
@@ -87,12 +88,12 @@ module API
end
namespace ':component/binary-:architecture', requirements: COMPONENT_ARCHITECTURE_REQUIREMENTS do
- # GET {projects|groups}/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages
+ # GET {projects|groups}/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages
desc 'The binary files index' do
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Packages' do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO Packages'
@@ -107,7 +108,7 @@ module API
end
namespace 'pool/:component/:letter/:source_package', requirements: COMPONENT_LETTER_SOURCE_PACKAGE_REQUIREMENTS do
- # GET {projects|groups}/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name
+ # GET {projects|groups}/:id/packages/debian/pool/:component/:letter/:source_package/:file_name
params do
requires :file_name, type: String, desc: 'The Debian File Name'
end
@@ -115,7 +116,7 @@ module API
detail 'This feature was introduced in GitLab 13.5'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get ':file_name', requirements: FILE_NAME_REQUIREMENTS do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO File'
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index f8129c18dff..8c0db42a448 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -8,27 +8,29 @@ module API
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
+ require_packages_enabled!
+
not_found! unless ::Feature.enabled?(:debian_packages, user_project)
authorize_read_package!
end
- namespace ':id/-/packages/debian' do
+ namespace ':id/packages/debian' do
include DebianPackageEndpoints
params do
requires :file_name, type: String, desc: 'The file name'
end
- namespace 'incoming/:file_name', requirements: FILE_NAME_REQUIREMENTS do
+ namespace ':file_name', requirements: FILE_NAME_REQUIREMENTS do
content_type :json, Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
- # PUT {projects|groups}/:id/-/packages/debian/incoming/:file_name
+ # PUT {projects|groups}/:id/packages/debian/:file_name
params do
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put do
authorize_upload!(authorized_user_project)
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size)
@@ -42,8 +44,8 @@ module API
forbidden!
end
- # PUT {projects|groups}/:id/-/packages/debian/incoming/:file_name/authorize
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
+ # PUT {projects|groups}/:id/packages/debian/:file_name/authorize
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put 'authorize' do
authorize_workhorse!(
subject: authorized_user_project,
diff --git a/lib/api/deploy_tokens.rb b/lib/api/deploy_tokens.rb
index 5fab590eb4e..30ec4e52b2a 100644
--- a/lib/api/deploy_tokens.rb
+++ b/lib/api/deploy_tokens.rb
@@ -28,8 +28,6 @@ module API
use :pagination
end
get 'deploy_tokens' do
- service_unavailable! unless Feature.enabled?(:deploy_tokens_api, default_enabled: true)
-
authenticated_as_admin!
present paginate(DeployToken.all), with: Entities::DeployToken
@@ -39,10 +37,6 @@ module API
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- before do
- service_unavailable! unless Feature.enabled?(:deploy_tokens_api, user_project, default_enabled: true)
- end
-
params do
use :pagination
end
@@ -102,10 +96,6 @@ module API
requires :id, type: String, desc: 'The ID of a group'
end
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
- before do
- service_unavailable! unless Feature.enabled?(:deploy_tokens_api, user_group, default_enabled: true)
- end
-
params do
use :pagination
end
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 5346fcf03c9..d0c842bb19d 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -36,7 +36,7 @@ module API
get ':id/deployments' do
authorize! :read_deployment, user_project
- deployments = DeploymentsFinder.new(user_project, params).execute
+ deployments = DeploymentsFinder.new(params.merge(project: user_project)).execute
present paginate(deployments), with: Entities::Deployment
end
diff --git a/lib/api/entities/application_setting.rb b/lib/api/entities/application_setting.rb
index e9572a8d430..2468c1f9b18 100644
--- a/lib/api/entities/application_setting.rb
+++ b/lib/api/entities/application_setting.rb
@@ -31,6 +31,7 @@ module API
expose :password_authentication_enabled_for_web, as: :password_authentication_enabled
expose :password_authentication_enabled_for_web, as: :signin_enabled
expose :allow_local_requests_from_web_hooks_and_services, as: :allow_local_requests_from_hooks_and_services
+ expose :asset_proxy_allowlist, as: :asset_proxy_whitelist
end
end
end
diff --git a/lib/api/entities/ci/job.rb b/lib/api/entities/ci/job.rb
index 7fe1a802e24..76487ed01dc 100644
--- a/lib/api/entities/ci/job.rb
+++ b/lib/api/entities/ci/job.rb
@@ -9,6 +9,9 @@ module API
expose :job_artifacts, as: :artifacts, using: ::API::Entities::Ci::JobArtifact
expose :runner, with: ::API::Entities::Runner
expose :artifacts_expire_at
+ expose :tag_list do |job|
+ job.tags.map(&:name).sort
+ end
end
end
end
diff --git a/lib/api/entities/merge_request_basic.rb b/lib/api/entities/merge_request_basic.rb
index 7f1b5b87725..88c84c494e2 100644
--- a/lib/api/entities/merge_request_basic.rb
+++ b/lib/api/entities/merge_request_basic.rb
@@ -27,7 +27,7 @@ module API
expose(:downvotes) { |merge_request, options| issuable_metadata.downvotes }
expose :author, :assignees, :assignee, using: Entities::UserBasic
- expose :reviewers, if: -> (merge_request, _) { merge_request.allows_reviewers? }, using: Entities::UserBasic
+ expose :reviewers, using: Entities::UserBasic
expose :source_project_id, :target_project_id
expose :labels do |merge_request, options|
if options[:with_labels_details]
diff --git a/lib/api/entities/user.rb b/lib/api/entities/user.rb
index 4aa5c9b7236..248a86751d2 100644
--- a/lib/api/entities/user.rb
+++ b/lib/api/entities/user.rb
@@ -6,9 +6,16 @@ module API
include UsersHelper
expose :created_at, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) }
expose :bio, :bio_html, :location, :public_email, :skype, :linkedin, :twitter, :website_url, :organization, :job_title
+ expose :bot?, as: :bot
expose :work_information do |user|
work_information(user)
end
+ expose :followers, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) } do |user|
+ user.followers.count
+ end
+ expose :following, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) } do |user|
+ user.followees.count
+ end
end
end
end
diff --git a/lib/api/entities/user_status.rb b/lib/api/entities/user_status.rb
index 1d5cc27e5ef..ef4772f60c6 100644
--- a/lib/api/entities/user_status.rb
+++ b/lib/api/entities/user_status.rb
@@ -9,6 +9,7 @@ module API
expose :message_html do |entity|
MarkupHelper.markdown_field(entity, :message)
end
+ expose :clear_status_at
end
end
end
diff --git a/lib/api/events.rb b/lib/api/events.rb
index 233c62b5389..db5ed7b7e6e 100644
--- a/lib/api/events.rb
+++ b/lib/api/events.rb
@@ -6,7 +6,7 @@ module API
include APIGuard
helpers ::API::Helpers::EventsHelpers
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
feature_category :users
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index 167531fdaec..24d726f4a41 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -7,6 +7,8 @@ module API
file_name: API::NO_SLASH_URL_PART_REGEX
}.freeze
+ ALLOWED_STATUSES = %w[default hidden].freeze
+
feature_category :package_registry
before do
@@ -35,6 +37,7 @@ module API
requires :package_name, type: String, desc: 'Package name', regexp: Gitlab::Regex.generic_package_name_regex, file_path: true
requires :package_version, type: String, desc: 'Package version', regexp: Gitlab::Regex.generic_package_version_regex
requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.generic_package_file_name_regex, file_path: true
+ optional :status, type: String, values: ALLOWED_STATUSES, desc: 'Package status'
end
put 'authorize' do
@@ -49,6 +52,7 @@ module API
requires :package_name, type: String, desc: 'Package name', regexp: Gitlab::Regex.generic_package_name_regex, file_path: true
requires :package_version, type: String, desc: 'Package version', regexp: Gitlab::Regex.generic_package_version_regex
requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.generic_package_file_name_regex, file_path: true
+ optional :status, type: String, values: ALLOWED_STATUSES, desc: 'Package status'
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end
diff --git a/lib/api/go_proxy.rb b/lib/api/go_proxy.rb
index 2d978019f2a..ea30f17522e 100755
--- a/lib/api/go_proxy.rb
+++ b/lib/api/go_proxy.rb
@@ -30,20 +30,6 @@ module API
str.gsub(/![[:alpha:]]/) { |s| s[1..].upcase }
end
- def find_project!(id)
- # based on API::Helpers::Packages::BasicAuthHelpers#authorized_project_find!
-
- project = find_project(id)
-
- return project if project && can?(current_user, :read_project, project)
-
- if current_user
- not_found!('Project')
- else
- unauthorized!
- end
- end
-
def find_module
not_found! unless Feature.enabled?(:go_proxy, user_project)
@@ -74,7 +60,7 @@ module API
requires :id, type: String, desc: 'The ID of a project'
requires :module_name, type: String, desc: 'Module name', coerce_with: ->(val) { CGI.unescape(val) }
end
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, authenticate_non_public: true
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
authorize_read_package!
diff --git a/lib/api/group_labels.rb b/lib/api/group_labels.rb
index 7fbf4445116..bea538441ee 100644
--- a/lib/api/group_labels.rb
+++ b/lib/api/group_labels.rb
@@ -12,7 +12,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :groups, requirements: ::API::Labels::LABEL_ENDPOINT_REQUIREMENTS do
desc 'Get all labels of the group' do
detail 'This feature was added in GitLab 11.8'
success Entities::GroupLabel
diff --git a/lib/api/group_packages.rb b/lib/api/group_packages.rb
index d482f4d0585..ab4e91ff925 100644
--- a/lib/api/group_packages.rb
+++ b/lib/api/group_packages.rb
@@ -33,12 +33,14 @@ module API
desc: 'Return packages with this name'
optional :include_versionless, type: Boolean,
desc: 'Returns packages without a version'
+ optional :status, type: String, values: Packages::Package.statuses.keys,
+ desc: 'Return packages with specified status'
end
get ':id/packages' do
packages = Packages::GroupPackagesFinder.new(
current_user,
user_group,
- declared(params).slice(:exclude_subgroups, :order_by, :sort, :package_type, :package_name, :include_versionless)
+ declared(params).slice(:exclude_subgroups, :order_by, :sort, :package_type, :package_name, :include_versionless, :status)
).execute
present paginate(packages), with: ::API::Entities::Package, user: current_user, group: true
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 79af9c37378..0abb21c9831 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -119,11 +119,10 @@ module API
def find_project!(id)
project = find_project(id)
- if can?(current_user, :read_project, project)
- project
- else
- not_found!('Project')
- end
+ return project if can?(current_user, :read_project, project)
+ return unauthorized! if authenticate_non_public?
+
+ not_found!('Project')
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -139,11 +138,10 @@ module API
def find_group!(id)
group = find_group(id)
- if can?(current_user, :read_group, group)
- group
- else
- not_found!('Group')
- end
+ return group if can?(current_user, :read_group, group)
+ return unauthorized! if authenticate_non_public?
+
+ not_found!('Group')
end
def check_namespace_access(namespace)
@@ -657,6 +655,10 @@ module API
Gitlab::Shell.secret_token
end
+ def authenticate_non_public?
+ route_authentication_setting[:authenticate_non_public] && !current_user
+ end
+
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index 12b0a053e79..9a1ff2ba8ce 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -124,7 +124,7 @@ 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
+ features: Feature::Gitaly.server_feature_flags(repository.project)
}
end
end
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 8aed578905e..2de077b5a3b 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-# rubocop:disable GitlabSecurity/PublicSend
-
module API
module Helpers
module MembersHelpers
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index 6798c4d284b..71a18524104 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -138,7 +138,7 @@ module API
parent = noteable_parent(noteable)
::Discussions::ResolveService.new(parent, current_user, one_or_more_discussions: discussion).execute
else
- discussion.unresolve!
+ ::Discussions::UnresolveService.new(discussion, current_user).execute
end
present discussion, with: Entities::Discussion
diff --git a/lib/api/helpers/rate_limiter.rb b/lib/api/helpers/rate_limiter.rb
index 5a531b5324a..3a16aef6a74 100644
--- a/lib/api/helpers/rate_limiter.rb
+++ b/lib/api/helpers/rate_limiter.rb
@@ -3,8 +3,8 @@
module API
module Helpers
module RateLimiter
- def check_rate_limit!(key, scope)
- if rate_limiter.throttled?(key, scope: scope)
+ def check_rate_limit!(key, scope, users_allowlist = nil)
+ if rate_limiter.throttled?(key, scope: scope, users_allowlist: users_allowlist)
log_request(key)
render_exceeded_limit_error!
end
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 12bb6e77c3e..a3fee49cd8f 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -52,7 +52,9 @@ module API
actor.update_last_used_at!
check_result = begin
- access_check!(actor, params)
+ Gitlab::Auth::CurrentUserMode.bypass_session!(actor.user&.id) do
+ access_check!(actor, params)
+ end
rescue Gitlab::GitAccess::ForbiddenError => e
# The return code needs to be 401. If we return 403
# the custom message we return won't be shown to the user
@@ -114,6 +116,10 @@ module API
'Could not find a user for the given key' unless actor.user
end
+
+ def two_factor_otp_check
+ { success: false, message: 'Feature is not available' }
+ end
end
namespace 'internal' do
@@ -276,6 +282,11 @@ module API
present response, with: Entities::InternalPostReceive::Response
end
+ # This endpoint was added in https://gitlab.com/gitlab-org/gitlab/-/issues/212308
+ # It was added with the plan to be used by GitLab PAM module but we
+ # decided to pursue a different approach, so it's currently not used.
+ # We might revive the PAM module though as it provides better user
+ # flow.
post '/two_factor_config', feature_category: :authentication_and_authorization do
status 200
@@ -301,28 +312,7 @@ module API
post '/two_factor_otp_check', feature_category: :authentication_and_authorization do
status 200
- break { success: false, message: 'Feature flag is disabled' } unless Feature.enabled?(:two_factor_for_cli)
-
- actor.update_last_used_at!
- user = actor.user
-
- error_message = validate_actor_key(actor, params[:key_id])
-
- break { success: false, message: error_message } if error_message
-
- break { success: false, message: 'Deploy keys cannot be used for Two Factor' } if actor.key.is_a?(DeployKey)
-
- break { success: false, message: 'Two-factor authentication is not enabled for this user' } unless user.two_factor_enabled?
-
- otp_validation_result = ::Users::ValidateOtpService.new(user).execute(params.fetch(:otp_attempt))
-
- if otp_validation_result[:status] == :success
- ::Gitlab::Auth::Otp::SessionEnforcer.new(actor.key).update_session
-
- { success: true }
- else
- { success: false, message: 'Invalid OTP' }
- end
+ two_factor_otp_check
end
end
end
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index 73723a96401..87ad79d601f 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -52,6 +52,8 @@ module API
def check_agent_token
forbidden! unless agent_token
+
+ forbidden! unless Gitlab::Kas.included_in_gitlab_com_rollout?(agent.project)
end
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 73e2163248d..ea09174f03a 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -231,7 +231,7 @@ module API
post ':id/issues' do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42320')
- check_rate_limit! :issues_create, [current_user, :issues_create]
+ check_rate_limit! :issues_create, [current_user]
authorize! :create_issue, user_project
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index e14a4a5e680..390dbc892e2 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -45,7 +45,7 @@ module API
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
- builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, pipeline: :project)
+ builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, :tags, pipeline: :project)
present paginate(builds), with: Entities::Ci::Job
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -82,7 +82,8 @@ module API
content_type 'text/plain'
env['api.format'] = :binary
- trace = build.trace.raw
+ # The trace can be nil bu body method expects a string as an argument.
+ trace = build.trace.raw || ''
body trace
end
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index c9f29865664..aa3746dae42 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -9,10 +9,14 @@ module API
feature_category :issue_tracking
+ LABEL_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
+ name: API::NO_SLASH_URL_PART_REGEX,
+ label_id: API::NO_SLASH_URL_PART_REGEX)
+
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource :projects, requirements: LABEL_ENDPOINT_REQUIREMENTS do
desc 'Get all labels of the project' do
success Entities::ProjectLabel
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 9bea74e2ce9..42f608102b3 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -137,12 +137,14 @@ module API
authorize_admin_source!(source_type, source)
member = source_members(source).find_by!(user_id: params[:user_id])
- updated_member =
- ::Members::UpdateService
- .new(current_user, declared_params(include_missing: false))
- .execute(member)
- if updated_member.valid?
+ result = ::Members::UpdateService
+ .new(current_user, declared_params(include_missing: false))
+ .execute(member)
+
+ updated_member = result[:member]
+
+ if result[:status] == :success
present_members updated_member
else
render_validation_error!(updated_member)
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 142ecd0dc1e..5051c1a5529 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -26,6 +26,7 @@ module API
%i[
assignee_id
assignee_ids
+ reviewer_ids
description
labels
add_labels
@@ -160,7 +161,8 @@ module API
helpers do
params :optional_params do
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
- optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The array of user IDs to assign issue'
+ optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Comma-separated list of assignee ids'
+ optional :reviewer_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Comma-separated list of reviewer ids'
optional :description, type: String, desc: 'The description of the merge request'
optional :labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :add_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
@@ -368,7 +370,7 @@ module API
with: Entities::MergeRequestChanges,
current_user: current_user,
project: user_project,
- access_raw_diffs: params.fetch(:access_raw_diffs, false)
+ access_raw_diffs: to_boolean(params.fetch(:access_raw_diffs, false))
end
desc 'Get the merge request pipelines' do
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index d249431b2f8..418efe3d1a7 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -4,6 +4,7 @@ module API
class Notes < ::API::Base
include PaginationParams
helpers ::API::Helpers::NotesHelpers
+ helpers Helpers::RateLimiter
before { authenticate! }
@@ -72,6 +73,9 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note'
end
post ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
+ allowlist =
+ Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
+ check_rate_limit! :notes_create, [current_user], allowlist
noteable = find_noteable(noteable_type, params[:noteable_id])
opts = {
diff --git a/lib/api/nuget_group_packages.rb b/lib/api/nuget_group_packages.rb
index e373f051b24..a80de06d6b0 100644
--- a/lib/api/nuget_group_packages.rb
+++ b/lib/api/nuget_group_packages.rb
@@ -18,7 +18,7 @@ module API
default_format :json
authenticate_with do |accept|
- accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username)
.sent_through(:http_basic_auth)
end
diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb
index 2146f4d4b78..e071b6bd68f 100644
--- a/lib/api/nuget_project_packages.rb
+++ b/lib/api/nuget_project_packages.rb
@@ -20,7 +20,7 @@ module API
default_format :json
authenticate_with do |accept|
- accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ accept.token_types(:personal_access_token_with_username, :deploy_token_with_username, :job_token_with_username)
.sent_through(:http_basic_auth)
end
diff --git a/lib/api/project_packages.rb b/lib/api/project_packages.rb
index 32636662987..0fdaa4b2656 100644
--- a/lib/api/project_packages.rb
+++ b/lib/api/project_packages.rb
@@ -32,11 +32,13 @@ module API
desc: 'Return packages with this name'
optional :include_versionless, type: Boolean,
desc: 'Returns packages without a version'
+ optional :status, type: String, values: Packages::Package.statuses.keys,
+ desc: 'Return packages with specified status'
end
get ':id/packages' do
packages = ::Packages::PackagesFinder.new(
user_project,
- declared_params.slice(:order_by, :sort, :package_type, :package_name, :include_versionless)
+ declared_params.slice(:order_by, :sort, :package_type, :package_name, :include_versionless, :status)
).execute
present paginate(packages), with: ::API::Entities::Package, user: current_user
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
index 19244ed697f..fdfdc244cbe 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -26,9 +26,7 @@ module API
use :pagination
end
get ':id/templates/:type' do
- templates = TemplateFinder
- .build(params[:type], user_project)
- .execute
+ templates = TemplateFinder.all_template_names_array(user_project, params[:type])
present paginate(::Kaminari.paginate_array(templates)), with: Entities::TemplatesList
end
@@ -38,16 +36,22 @@ module API
end
params do
requires :name, type: String, desc: 'The name of the template'
-
+ optional :source_template_project_id, type: Integer,
+ desc: 'The project id where a given template is being stored. This is useful when multiple templates from different projects have the same name'
optional :project, type: String, desc: 'The project name to use when expanding placeholders in the template. Only affects licenses'
optional :fullname, type: String, desc: 'The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses'
end
get ':id/templates/:type/:name', requirements: TEMPLATE_NAMES_ENDPOINT_REQUIREMENTS do
begin
- template = TemplateFinder
- .build(params[:type], user_project, name: params[:name])
- .execute
+ template = TemplateFinder.build(
+ params[:type],
+ user_project,
+ {
+ name: params[:name],
+ source_template_project_id: params[:source_template_project_id]
+ }
+ ).execute
rescue ::Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
not_found!('Template')
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 2d09ad01757..fca68c3606b 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -295,6 +295,8 @@ module API
optional :namespace_path, type: String, desc: 'The path of the namespace that the project will be forked into'
optional :path, type: String, desc: 'The path that will be assigned to the fork'
optional :name, type: String, desc: 'The name that will be assigned to the fork'
+ optional :description, type: String, desc: 'The description that will be assigned to the fork'
+ optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the fork'
end
post ':id/fork', feature_category: :source_code_management do
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42284')
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 8af8ffc3b63..eaedd53aedb 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -170,6 +170,65 @@ module API
not_found!("Merge Base")
end
end
+
+ desc 'Generates a changelog section for a release' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ requires :version,
+ type: String,
+ regexp: Gitlab::Regex.unbounded_semver_regex,
+ desc: 'The version of the release, using the semantic versioning format'
+
+ optional :from,
+ type: String,
+ desc: 'The first commit in the range of commits to use for the changelog'
+
+ requires :to,
+ type: String,
+ desc: 'The last commit in the range of commits to use for the changelog'
+
+ optional :date,
+ type: DateTime,
+ desc: 'The date and time of the release'
+
+ optional :branch,
+ type: String,
+ desc: 'The branch to commit the changelog changes to'
+
+ optional :trailer,
+ type: String,
+ desc: 'The Git trailer to use for determining if commits are to be included in the changelog',
+ default: ::Repositories::ChangelogService::DEFAULT_TRAILER
+
+ optional :file,
+ type: String,
+ desc: 'The file to commit the changelog changes to',
+ default: ::Repositories::ChangelogService::DEFAULT_FILE
+
+ optional :message,
+ type: String,
+ desc: 'The commit message to use when committing the changelog'
+ end
+ post ':id/repository/changelog' do
+ branch = params[:branch] || user_project.default_branch_or_master
+ access = Gitlab::UserAccess.new(current_user, container: user_project)
+
+ unless access.can_push_to_branch?(branch)
+ forbidden!("You are not allowed to commit a changelog on this branch")
+ end
+
+ service = ::Repositories::ChangelogService.new(
+ user_project,
+ current_user,
+ **declared_params(include_missing: false)
+ )
+
+ service.execute
+ status(200)
+ rescue Gitlab::Changelog::Error => ex
+ render_api_error!("Failed to generate the changelog: #{ex.message}", 422)
+ end
end
end
end
diff --git a/lib/api/resource_access_tokens.rb b/lib/api/resource_access_tokens.rb
new file mode 100644
index 00000000000..66948f9eaf3
--- /dev/null
+++ b/lib/api/resource_access_tokens.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+module API
+ class ResourceAccessTokens < ::API::Base
+ include PaginationParams
+
+ before { authenticate! }
+
+ feature_category :authentication_and_authorization
+
+ %w[project].each do |source_type|
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ desc 'Get list of all access tokens for the specified resource' do
+ detail 'This feature was introduced in GitLab 13.9.'
+ end
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ end
+ get ":id/access_tokens" do
+ resource = find_source(source_type, params[:id])
+
+ next unauthorized! unless has_permission_to_read?(resource)
+
+ tokens = PersonalAccessTokensFinder.new({ user: resource.bots, impersonation: false }).execute
+
+ present paginate(tokens), with: Entities::PersonalAccessToken
+ end
+
+ desc 'Revoke a resource access token' do
+ detail 'This feature was introduced in GitLab 13.9.'
+ end
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ requires :token_id, type: String, desc: "The ID of the token"
+ end
+ delete ':id/access_tokens/:token_id' do
+ resource = find_source(source_type, params[:id])
+ token = find_token(resource, params[:token_id])
+
+ if token.nil?
+ next not_found!("Could not find #{source_type} access token with token_id: #{params[:token_id]}")
+ end
+
+ service = ::ResourceAccessTokens::RevokeService.new(
+ current_user,
+ resource,
+ token
+ ).execute
+
+ service.success? ? no_content! : bad_request!(service.message)
+ end
+
+ desc 'Create a resource access token' do
+ detail 'This feature was introduced in GitLab 13.9.'
+ end
+ params do
+ requires :id, type: String, desc: "The #{source_type} ID"
+ requires :name, type: String, desc: "Resource access token name"
+ requires :scopes, type: Array[String], desc: "The permissions of the token"
+ optional :expires_at, type: Date, desc: "The expiration date of the token"
+ end
+ post ':id/access_tokens' do
+ resource = find_source(source_type, params[:id])
+
+ token_response = ::ResourceAccessTokens::CreateService.new(
+ current_user,
+ resource,
+ declared_params
+ ).execute
+
+ if token_response.success?
+ present token_response.payload[:access_token], with: Entities::PersonalAccessToken
+ else
+ bad_request!(token_response.message)
+ end
+ end
+ end
+ end
+
+ helpers do
+ def find_source(source_type, id)
+ public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def find_token(resource, token_id)
+ PersonalAccessTokensFinder.new({ user: resource.bots, impersonation: false }).find_by_id(token_id)
+ end
+
+ def has_permission_to_read?(resource)
+ can?(current_user, :project_bot_access, resource) || can?(current_user, :admin_resource_access_tokens, resource)
+ end
+ end
+ end
+end
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
new file mode 100644
index 00000000000..7819aab879c
--- /dev/null
+++ b/lib/api/rubygem_packages.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+###
+# API endpoints for the RubyGem package registry
+module API
+ class RubygemPackages < ::API::Base
+ include ::API::Helpers::Authentication
+ helpers ::API::Helpers::PackagesHelpers
+
+ feature_category :package_registry
+
+ # The Marshal version can be found by "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
+ # Updating the version should require a GitLab API version change.
+ MARSHAL_VERSION = '4.8'
+
+ FILE_NAME_REQUIREMENTS = {
+ file_name: API::NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ content_type :binary, 'application/octet-stream'
+
+ authenticate_with do |accept|
+ accept.token_types(:personal_access_token, :deploy_token, :job_token)
+ .sent_through(:http_token)
+ end
+
+ before do
+ require_packages_enabled!
+ authenticate!
+ not_found! unless Feature.enabled?(:rubygem_packages, user_project)
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID or full path of a project'
+ end
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ namespace ':id/packages/rubygems' do
+ desc 'Download the spec index file' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ requires :file_name, type: String, desc: 'Spec file name'
+ end
+ get ":file_name", requirements: FILE_NAME_REQUIREMENTS do
+ # To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299267
+ not_found!
+ end
+
+ desc 'Download the gemspec file' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ requires :file_name, type: String, desc: 'Gemspec file name'
+ end
+ get "quick/Marshal.#{MARSHAL_VERSION}/:file_name", requirements: FILE_NAME_REQUIREMENTS do
+ # To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299284
+ not_found!
+ end
+
+ desc 'Download the .gem package' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ requires :file_name, type: String, desc: 'Package file name'
+ end
+ get "gems/:file_name", requirements: FILE_NAME_REQUIREMENTS do
+ # To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299283
+ not_found!
+ end
+
+ namespace 'api/v1' do
+ desc 'Authorize a gem upload from workhorse' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ post 'gems/authorize' do
+ # To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299263
+ not_found!
+ end
+
+ desc 'Upload a gem' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ post 'gems' do
+ # To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299263
+ not_found!
+ end
+
+ desc 'Fetch a list of dependencies' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ optional :gems, type: String, desc: 'Comma delimited gem names'
+ end
+ get 'dependencies' do
+ # To be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299282
+ not_found!
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index f329a94adf2..e7ee8b08d87 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -10,8 +10,7 @@ module API
helpers do
def current_settings
- @current_setting ||=
- (ApplicationSetting.current_without_cache || ApplicationSetting.create_from_defaults)
+ @current_setting ||= ApplicationSetting.find_or_create_without_cache
end
def filter_attributes_using_license(attrs)
@@ -42,7 +41,8 @@ module API
optional :asset_proxy_enabled, type: Boolean, desc: 'Enable proxying of assets'
optional :asset_proxy_url, type: String, desc: 'URL of the asset proxy server'
optional :asset_proxy_secret_key, type: String, desc: 'Shared secret with the asset proxy server'
- optional :asset_proxy_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted.'
+ optional :asset_proxy_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :asset_proxy_allowlist instead. Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically whitelisted.'
+ optional :asset_proxy_allowlist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Assets that match these domain(s) will NOT be proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed.'
optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)'
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
optional :default_ci_config_path, type: String, desc: 'The instance default CI configuration path for new projects'
@@ -211,6 +211,11 @@ module API
attrs[:abuse_notification_email] = attrs.delete(:admin_notification_email)
end
+ # support legacy names, can be removed in v5
+ if attrs.has_key?(:asset_proxy_whitelist)
+ attrs[:asset_proxy_allowlist] = attrs.delete(:asset_proxy_whitelist)
+ end
+
# since 13.0 it's not possible to disable hashed storage - support can be removed in 14.0
attrs.delete(:hashed_storage_enabled) if attrs.has_key?(:hashed_storage_enabled)
diff --git a/lib/api/snippet_repository_storage_moves.rb b/lib/api/snippet_repository_storage_moves.rb
index 1a5b41eb1ec..84dbc03ba33 100644
--- a/lib/api/snippet_repository_storage_moves.rb
+++ b/lib/api/snippet_repository_storage_moves.rb
@@ -58,9 +58,14 @@ module API
resource :snippets do
helpers do
def user_snippet
- Snippet.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
+ @user_snippet ||= Snippet.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
end
end
+
+ before do
+ not_found!('Snippet') unless user_snippet
+ end
+
desc 'Get a list of all snippets repository storage moves' do
detail 'This feature was introduced in GitLab 13.8.'
success Entities::SnippetRepositoryStorageMove
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
index 914bab52929..87dc1358a51 100644
--- a/lib/api/subscriptions.rb
+++ b/lib/api/subscriptions.rb
@@ -6,6 +6,9 @@ module API
before { authenticate! }
+ SUBSCRIBE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
+ subscribable_id: API::NO_SLASH_URL_PART_REGEX)
+
subscribables = [
{
type: 'merge_requests',
@@ -44,7 +47,7 @@ module API
requires :id, type: String, desc: "The #{source_type} ID"
requires :subscribable_id, type: String, desc: 'The ID of a resource'
end
- resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ resource source_type.pluralize, requirements: SUBSCRIBE_ENDPOINT_REQUIREMENTS do
desc 'Subscribe to a resource' do
success subscribable[:entity]
end
diff --git a/lib/api/suggestions.rb b/lib/api/suggestions.rb
index a024d6de874..7921700e365 100644
--- a/lib/api/suggestions.rb
+++ b/lib/api/suggestions.rb
@@ -12,12 +12,13 @@ module API
end
params do
requires :id, type: String, desc: 'The suggestion ID'
+ optional :commit_message, type: String, desc: "A custom commit message to use instead of the default generated message or the project's default message"
end
put ':id/apply' do
suggestion = Suggestion.find_by_id(params[:id])
if suggestion
- apply_suggestions(suggestion, current_user)
+ apply_suggestions(suggestion, current_user, params[:commit_message])
else
render_api_error!(_('Suggestion is not applicable as the suggestion was not found.'), :not_found)
end
@@ -28,6 +29,7 @@ module API
end
params do
requires :ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: "An array of suggestion ID's"
+ optional :commit_message, type: String, desc: "A custom commit message to use instead of the default generated message or the project's default message"
end
put 'batch_apply' do
ids = params[:ids]
@@ -35,7 +37,7 @@ module API
suggestions = Suggestion.id_in(ids)
if suggestions.size == ids.length
- apply_suggestions(suggestions, current_user)
+ apply_suggestions(suggestions, current_user, params[:commit_message])
else
render_api_error!(_('Suggestions are not applicable as one or more suggestions were not found.'), :not_found)
end
@@ -43,10 +45,10 @@ module API
end
helpers do
- def apply_suggestions(suggestions, current_user)
+ def apply_suggestions(suggestions, current_user, message)
authorize_suggestions(*suggestions)
- result = ::Suggestions::ApplyService.new(current_user, *suggestions).execute
+ result = ::Suggestions::ApplyService.new(current_user, *suggestions, message: message).execute
if result[:status] == :success
present suggestions, with: Entities::Suggestion, current_user: current_user
diff --git a/lib/api/support/git_access_actor.rb b/lib/api/support/git_access_actor.rb
index 39730da1251..71395086ac2 100644
--- a/lib/api/support/git_access_actor.rb
+++ b/lib/api/support/git_access_actor.rb
@@ -37,6 +37,8 @@ module API
end
def update_last_used_at!
+ return if Feature.enabled?(:disable_ssh_key_used_tracking)
+
key&.update_last_used_at
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index cee09f60a2b..f91e3c34ef2 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -6,7 +6,7 @@ module API
include APIGuard
include Helpers::CustomAttributes
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key']
@@ -159,6 +159,68 @@ module API
present user.status || {}, with: Entities::UserStatus
end
+ desc 'Follow a user' do
+ success Entities::User
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the user'
+ end
+ post ':id/follow', feature_category: :users do
+ user = find_user(params[:id])
+ not_found!('User') unless user
+
+ if current_user.follow(user)
+ present user, with: Entities::UserBasic
+ else
+ not_modified!
+ end
+ end
+
+ desc 'Unfollow a user' do
+ success Entities::User
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the user'
+ end
+ post ':id/unfollow', feature_category: :users do
+ user = find_user(params[:id])
+ not_found!('User') unless user
+
+ if current_user.unfollow(user)
+ present user, with: Entities::UserBasic
+ else
+ not_modified!
+ end
+ end
+
+ desc 'Get the users who follow a user' do
+ success Entities::UserBasic
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the user'
+ use :pagination
+ end
+ get ':id/following', feature_category: :users do
+ user = find_user(params[:id])
+ not_found!('User') unless user && can?(current_user, :read_user_profile, user)
+
+ present paginate(user.followees), with: Entities::UserBasic
+ end
+
+ desc 'Get the followers of a user' do
+ success Entities::UserBasic
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the user'
+ use :pagination
+ end
+ get ':id/followers', feature_category: :users do
+ user = find_user(params[:id])
+ not_found!('User') unless user && can?(current_user, :read_user_profile, user)
+
+ present paginate(user.followers), with: Entities::UserBasic
+ end
+
desc 'Create a user. Available only for admins.' do
success Entities::UserWithAdmin
end
@@ -1004,11 +1066,15 @@ module API
optional :emoji, type: String, desc: "The emoji to set on the status"
optional :message, type: String, desc: "The status message to set"
optional :availability, type: String, desc: "The availability of user to set"
+ optional :clear_status_after, type: String, desc: "Automatically clear emoji, message and availability fields after a certain time", values: UserStatus::CLEAR_STATUS_QUICK_OPTIONS.keys
end
put "status", feature_category: :users do
forbidden! unless can?(current_user, :update_user_status, current_user)
- if ::Users::SetStatusService.new(current_user, declared_params).execute
+ update_params = declared_params
+ update_params.delete(:clear_status_after) if Feature.disabled?(:clear_status_with_quick_options, current_user, default_enabled: :yaml)
+
+ if ::Users::SetStatusService.new(current_user, update_params).execute
present current_user.status, with: Entities::UserStatus
else
render_validation_error!(current_user.status)
diff --git a/lib/api/version.rb b/lib/api/version.rb
index f8072658cc6..86eb34ca589 100644
--- a/lib/api/version.rb
+++ b/lib/api/version.rb
@@ -5,7 +5,7 @@ module API
helpers ::API::Helpers::GraphqlHelpers
include APIGuard
- allow_access_with_scope :read_user, if: -> (request) { request.get? }
+ allow_access_with_scope :read_user, if: -> (request) { request.get? || request.head? }
before { authenticate! }
diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb
index c67fe24d456..6f87b7b7d3c 100644
--- a/lib/atlassian/jira_connect/client.rb
+++ b/lib/atlassian/jira_connect/client.rb
@@ -4,7 +4,7 @@ module Atlassian
module JiraConnect
class Client < Gitlab::HTTP
def self.generate_update_sequence_id
- Gitlab::Metrics::System.monotonic_time.to_i
+ (Time.now.utc.to_f * 1000).round
end
def initialize(base_uri, shared_secret)
@@ -33,8 +33,6 @@ module Atlassian
private
def store_ff_info(project:, feature_flags:, **opts)
- return unless Feature.enabled?(:jira_sync_feature_flags, project)
-
items = feature_flags.map { |flag| ::Atlassian::JiraConnect::Serializers::FeatureFlagEntity.represent(flag, opts) }
items.reject! { |item| item.issue_keys.empty? }
@@ -57,8 +55,6 @@ module Atlassian
end
def store_deploy_info(project:, deployments:, **opts)
- return unless Feature.enabled?(:jira_sync_deployments, project)
-
items = deployments.map { |d| ::Atlassian::JiraConnect::Serializers::DeploymentEntity.represent(d, opts) }
items.reject! { |d| d.issue_keys.empty? }
@@ -69,8 +65,6 @@ module Atlassian
end
def store_build_info(project:, pipelines:, update_sequence_id: nil)
- return unless Feature.enabled?(:jira_sync_builds, project)
-
builds = pipelines.map do |pipeline|
build = ::Atlassian::JiraConnect::Serializers::BuildEntity.represent(
pipeline,
diff --git a/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb b/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb
index e17c150aacb..3193d5bbd1e 100644
--- a/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb
+++ b/lib/atlassian/jira_connect/serializers/feature_flag_entity.rb
@@ -50,7 +50,7 @@ module Atlassian
# edit path as an interim solution.
def summary(strategies = flag.strategies)
{
- url: project_url(flag.project) + "/-/feature_flags/#{flag.id}/edit",
+ url: edit_project_feature_flag_url(flag.project, flag),
lastUpdated: flag.updated_at.iso8601,
status: {
enabled: flag.active,
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index 0f6ed847dea..42cfff98239 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -137,7 +137,7 @@ module Backup
if s == DEFAULT_EXCLUDE
'--exclude=' + s
elsif fmt == :rsync
- '--exclude=/' + s
+ '--exclude=/' + File.join(File.basename(app_files_dir), s)
elsif fmt == :tar
'--exclude=./' + s
end
diff --git a/lib/banzai/filter/asset_proxy_filter.rb b/lib/banzai/filter/asset_proxy_filter.rb
index 55dc426edaf..4c14ee7299b 100644
--- a/lib/banzai/filter/asset_proxy_filter.rb
+++ b/lib/banzai/filter/asset_proxy_filter.rb
@@ -59,7 +59,9 @@ module Banzai
end
def self.determine_allowlist(application_settings)
- application_settings.asset_proxy_whitelist.presence || [Gitlab.config.gitlab.host]
+ application_settings.try(:asset_proxy_allowlist).presence ||
+ application_settings.try(:asset_proxy_whitelist).presence ||
+ [Gitlab.config.gitlab.host]
end
end
end
diff --git a/lib/banzai/filter/custom_emoji_filter.rb b/lib/banzai/filter/custom_emoji_filter.rb
new file mode 100644
index 00000000000..1ee8f4e31e8
--- /dev/null
+++ b/lib/banzai/filter/custom_emoji_filter.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class CustomEmojiFilter < HTML::Pipeline::Filter
+ IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
+
+ def call
+ return doc unless context[:project]
+ return doc unless Feature.enabled?(:custom_emoji, context[:project])
+
+ doc.search(".//text()").each do |node|
+ content = node.to_html
+
+ next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
+ next unless content.include?(':')
+ next unless namespace && namespace.custom_emoji.any?
+
+ html = custom_emoji_name_element_filter(content)
+
+ node.replace(html) unless html == content
+ end
+
+ doc
+ end
+
+ def custom_emoji_pattern
+ @emoji_pattern ||=
+ /(?<=[^[:alnum:]:]|\n|^)
+ :(#{CustomEmoji::NAME_REGEXP}):
+ (?=[^[:alnum:]:]|$)/x
+ end
+
+ def custom_emoji_name_element_filter(text)
+ text.gsub(custom_emoji_pattern) do |match|
+ name = Regexp.last_match[1]
+ custom_emoji = all_custom_emoji[name]
+
+ if custom_emoji
+ Gitlab::Emoji.custom_emoji_tag(custom_emoji.name, custom_emoji.url)
+ else
+ match
+ end
+ end
+ end
+
+ private
+
+ def namespace
+ context[:project].namespace.root_ancestor
+ end
+
+ def custom_emoji_candidates
+ doc.to_html.scan(/:(#{CustomEmoji::NAME_REGEXP}):/).flatten
+ end
+
+ def all_custom_emoji
+ @all_custom_emoji ||= namespace.custom_emoji.by_name(custom_emoji_candidates).index_by(&:name)
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/feature_flag_reference_filter.rb b/lib/banzai/filter/feature_flag_reference_filter.rb
new file mode 100644
index 00000000000..c11576901ce
--- /dev/null
+++ b/lib/banzai/filter/feature_flag_reference_filter.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class FeatureFlagReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :feature_flag
+
+ def self.object_class
+ Operations::FeatureFlag
+ end
+
+ def self.object_sym
+ :feature_flag
+ end
+
+ def parent_records(parent, ids)
+ parent.operations_feature_flags.where(iid: ids.to_a)
+ end
+
+ def url_for_object(feature_flag, project)
+ ::Gitlab::Routing.url_helpers.edit_project_feature_flag_url(
+ project,
+ feature_flag.iid,
+ only_path: context[:only_path]
+ )
+ end
+
+ def object_link_title(object, matches)
+ object.name
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/markdown_post_escape_filter.rb b/lib/banzai/filter/markdown_post_escape_filter.rb
new file mode 100644
index 00000000000..ad32e9afbf5
--- /dev/null
+++ b/lib/banzai/filter/markdown_post_escape_filter.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class MarkdownPostEscapeFilter < HTML::Pipeline::Filter
+ LITERAL_KEYWORD = MarkdownPreEscapeFilter::LITERAL_KEYWORD
+ LITERAL_REGEX = %r{#{LITERAL_KEYWORD}-(.*?)-#{LITERAL_KEYWORD}}.freeze
+ NOT_LITERAL_REGEX = %r{#{LITERAL_KEYWORD}-((%5C|\\).+?)-#{LITERAL_KEYWORD}}.freeze
+ SPAN_REGEX = %r{<span>(.*?)</span>}.freeze
+
+ def call
+ return doc unless result[:escaped_literals]
+
+ # For any literals that actually didn't get escape processed
+ # (for example in code blocks), remove the special sequence.
+ html.gsub!(NOT_LITERAL_REGEX, '\1')
+
+ # Replace any left over literal sequences with `span` so that our
+ # reference processing is short-circuited
+ html.gsub!(LITERAL_REGEX, '<span>\1</span>')
+
+ # Since literals are converted in links, we need to remove any surrounding `span`.
+ # Note: this could have been done in the renderer,
+ # Banzai::Renderer::CommonMark::HTML. However, we eventually want to use
+ # the built-in compiled renderer, rather than the ruby version, for speed.
+ # So let's do this work here.
+ doc.css('a').each do |node|
+ node.attributes['href'].value = node.attributes['href'].value.gsub(SPAN_REGEX, '\1') if node.attributes['href']
+ node.attributes['title'].value = node.attributes['title'].value.gsub(SPAN_REGEX, '\1') if node.attributes['title']
+ end
+
+ doc.css('code').each do |node|
+ node.attributes['lang'].value = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
+ end
+
+ doc
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/markdown_pre_escape_filter.rb b/lib/banzai/filter/markdown_pre_escape_filter.rb
new file mode 100644
index 00000000000..9fd77c48659
--- /dev/null
+++ b/lib/banzai/filter/markdown_pre_escape_filter.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # In order to allow a user to short-circuit our reference shortcuts
+ # (such as # or !), the user should be able to escape them, like \#.
+ # CommonMark supports this, however it removes all information about
+ # what was actually a literal. In order to short-circuit the reference,
+ # we must surround backslash escaped ASCII punctuation with a custom sequence.
+ # This way CommonMark will properly handle the backslash escaped chars
+ # but we will maintain knowledge (the sequence) that it was a literal.
+ #
+ # We need to surround the character, not just prefix it. It could
+ # get converted into an entity by CommonMark and we wouldn't know how many
+ # characters there are. The entire literal needs to be surrounded with
+ # a `span` tag, which short-circuits our reference processing.
+ #
+ # We can't use a custom HTML tag since we could be initially surrounding
+ # text in an href, and then CommonMark will not be able to parse links
+ # properly. So we use `cmliteral-` and `-cmliteral`
+ #
+ # https://spec.commonmark.org/0.29/#backslash-escapes
+ #
+ # This filter does the initial surrounding, and MarkdownPostEscapeFilter
+ # does the conversion into span tags.
+ class MarkdownPreEscapeFilter < HTML::Pipeline::TextFilter
+ ASCII_PUNCTUATION = %r{([\\][!"#$%&'()*+,-./:;<=>?@\[\\\]^_`{|}~])}.freeze
+ LITERAL_KEYWORD = 'cmliteral'
+
+ def call
+ return @text unless Feature.enabled?(:honor_escaped_markdown, context[:group] || context[:project]&.group)
+
+ @text.gsub(ASCII_PUNCTUATION) do |match|
+ # The majority of markdown does not have literals. If none
+ # are found, we can bypass the post filter
+ result[:escaped_literals] = true
+
+ "#{LITERAL_KEYWORD}-#{match}-#{LITERAL_KEYWORD}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 1a75cd14b11..37d4126c1ba 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -9,7 +9,7 @@ module Banzai
#
class PlantumlFilter < HTML::Pipeline::Filter
def call
- return doc unless doc.at('pre > code[lang="plantuml"]') && settings.plantuml_enabled
+ return doc unless settings.plantuml_enabled? && doc.at('pre > code[lang="plantuml"]')
plantuml_setup
diff --git a/lib/banzai/filter/truncate_source_filter.rb b/lib/banzai/filter/truncate_source_filter.rb
index c903b83d868..44f88b253d9 100644
--- a/lib/banzai/filter/truncate_source_filter.rb
+++ b/lib/banzai/filter/truncate_source_filter.rb
@@ -6,7 +6,9 @@ module Banzai
def call
return text unless context.key?(:limit)
- text.truncate_bytes(context[:limit])
+ # Use three dots instead of the ellipsis Unicode character because
+ # some clients show the raw Unicode value in the merge commit.
+ text.truncate_bytes(context[:limit], omission: '...')
end
end
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 344afc9b33c..e5ec0a0a006 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -34,6 +34,7 @@ module Banzai
Filter::FootnoteFilter,
*reference_filters,
Filter::EmojiFilter,
+ Filter::CustomEmojiFilter,
Filter::TaskListFilter,
Filter::InlineDiffFilter,
Filter::SetDirectionFilter
@@ -61,7 +62,8 @@ module Banzai
Filter::CommitReferenceFilter,
Filter::LabelReferenceFilter,
Filter::MilestoneReferenceFilter,
- Filter::AlertReferenceFilter
+ Filter::AlertReferenceFilter,
+ Filter::FeatureFlagReferenceFilter
]
end
diff --git a/lib/banzai/pipeline/plain_markdown_pipeline.rb b/lib/banzai/pipeline/plain_markdown_pipeline.rb
index b64f13cde47..1da0f72996b 100644
--- a/lib/banzai/pipeline/plain_markdown_pipeline.rb
+++ b/lib/banzai/pipeline/plain_markdown_pipeline.rb
@@ -5,7 +5,9 @@ module Banzai
class PlainMarkdownPipeline < BasePipeline
def self.filters
FilterArray[
- Filter::MarkdownFilter
+ Filter::MarkdownPreEscapeFilter,
+ Filter::MarkdownFilter,
+ Filter::MarkdownPostEscapeFilter
]
end
end
diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb
index a2fe6d52a90..4bf98099662 100644
--- a/lib/banzai/pipeline/single_line_pipeline.rb
+++ b/lib/banzai/pipeline/single_line_pipeline.rb
@@ -24,7 +24,8 @@ module Banzai
Filter::SnippetReferenceFilter,
Filter::CommitRangeReferenceFilter,
Filter::CommitReferenceFilter,
- Filter::AlertReferenceFilter
+ Filter::AlertReferenceFilter,
+ Filter::FeatureFlagReferenceFilter
]
end
diff --git a/lib/banzai/reference_parser/feature_flag_parser.rb b/lib/banzai/reference_parser/feature_flag_parser.rb
new file mode 100644
index 00000000000..6092b0f7e66
--- /dev/null
+++ b/lib/banzai/reference_parser/feature_flag_parser.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Banzai
+ module ReferenceParser
+ class FeatureFlagParser < BaseParser
+ self.reference_type = :feature_flag
+
+ def references_relation
+ Operations::FeatureFlag
+ end
+
+ private
+
+ def can_read_reference?(user, feature_flag, node)
+ can?(user, :read_feature_flag, feature_flag)
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/extractors/graphql_extractor.rb b/lib/bulk_imports/common/extractors/graphql_extractor.rb
index af274ee1299..cde3d1cad5b 100644
--- a/lib/bulk_imports/common/extractors/graphql_extractor.rb
+++ b/lib/bulk_imports/common/extractors/graphql_extractor.rb
@@ -4,17 +4,22 @@ module BulkImports
module Common
module Extractors
class GraphqlExtractor
- def initialize(query)
- @query = query[:query]
+ def initialize(options = {})
+ @query = options[:query]
end
def extract(context)
client = graphql_client(context)
- client.execute(
+ response = client.execute(
client.parse(query.to_s),
- query.variables(context.entity)
+ query.variables(context)
).original_hash.deep_dup
+
+ BulkImports::Pipeline::ExtractedData.new(
+ data: response.dig(*query.data_path),
+ page_info: response.dig(*query.page_info_path)
+ )
end
private
@@ -27,10 +32,6 @@ module BulkImports
token: context.configuration.access_token
)
end
-
- def parsed_query
- @parsed_query ||= graphql_client.parse(query.to_s)
- end
end
end
end
diff --git a/lib/bulk_imports/common/loaders/entity_loader.rb b/lib/bulk_imports/common/loaders/entity_loader.rb
index 4540b892c88..8644f3c9dcb 100644
--- a/lib/bulk_imports/common/loaders/entity_loader.rb
+++ b/lib/bulk_imports/common/loaders/entity_loader.rb
@@ -7,7 +7,7 @@ module BulkImports
def initialize(*args); end
def load(context, entity)
- context.entity.bulk_import.entities.create!(entity)
+ context.bulk_import.entities.create!(entity)
end
end
end
diff --git a/lib/bulk_imports/common/transformers/award_emoji_transformer.rb b/lib/bulk_imports/common/transformers/award_emoji_transformer.rb
new file mode 100644
index 00000000000..260b47ab917
--- /dev/null
+++ b/lib/bulk_imports/common/transformers/award_emoji_transformer.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Transformers
+ class AwardEmojiTransformer
+ def initialize(*args); end
+
+ def transform(context, data)
+ user = find_user(context, data&.dig('user', 'public_email')) || context.current_user
+
+ data
+ .except('user')
+ .merge('user_id' => user.id)
+ end
+
+ private
+
+ def find_user(context, email)
+ return if email.blank?
+
+ context.group.users.find_by_any_email(email, confirmed: true) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/transformers/hash_key_digger.rb b/lib/bulk_imports/common/transformers/hash_key_digger.rb
deleted file mode 100644
index b4897b5b2bf..00000000000
--- a/lib/bulk_imports/common/transformers/hash_key_digger.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Common
- module Transformers
- class HashKeyDigger
- def initialize(options = {})
- @key_path = options[:key_path]
- end
-
- def transform(_, data)
- raise ArgumentError, "Given data must be a Hash" unless data.is_a?(Hash)
-
- data.dig(*Array.wrap(key_path))
- end
-
- private
-
- attr_reader :key_path
- end
- end
- end
-end
diff --git a/lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb b/lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb
deleted file mode 100644
index b32ab28fdbb..00000000000
--- a/lib/bulk_imports/common/transformers/underscorify_keys_transformer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Common
- module Transformers
- class UnderscorifyKeysTransformer
- def initialize(options = {})
- @options = options
- end
-
- def transform(_, data)
- data.deep_transform_keys do |key|
- key.to_s.underscore
- end
- end
- end
- end
- end
-end
diff --git a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
index 5c5e686cec5..b01fb6f68ac 100644
--- a/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
+++ b/lib/bulk_imports/groups/extractors/subgroups_extractor.rb
@@ -9,9 +9,11 @@ module BulkImports
def extract(context)
encoded_parent_path = ERB::Util.url_encode(context.entity.source_full_path)
- http_client(context.entity.bulk_import.configuration)
+ response = http_client(context.configuration)
.each_page(:get, "groups/#{encoded_parent_path}/subgroups")
.flat_map(&:itself)
+
+ BulkImports::Pipeline::ExtractedData.new(data: response)
end
private
diff --git a/lib/bulk_imports/groups/graphql/get_group_query.rb b/lib/bulk_imports/groups/graphql/get_group_query.rb
index 2bc0f60baa2..6852e25c87f 100644
--- a/lib/bulk_imports/groups/graphql/get_group_query.rb
+++ b/lib/bulk_imports/groups/graphql/get_group_query.rb
@@ -12,25 +12,37 @@ module BulkImports
group(fullPath: $full_path) {
name
path
- fullPath
+ full_path: fullPath
description
visibility
- emailsDisabled
- lfsEnabled
- mentionsDisabled
- projectCreationLevel
- requestAccessEnabled
- requireTwoFactorAuthentication
- shareWithGroupLock
- subgroupCreationLevel
- twoFactorGracePeriod
+ emails_disabled: emailsDisabled
+ lfs_enabled: lfsEnabled
+ mentions_disabled: mentionsDisabled
+ project_creation_level: projectCreationLevel
+ request_access_enabled: requestAccessEnabled
+ require_two_factor_authentication: requireTwoFactorAuthentication
+ share_with_group_lock: shareWithGroupLock
+ subgroup_creation_level: subgroupCreationLevel
+ two_factor_grace_period: twoFactorGracePeriod
}
}
GRAPHQL
end
- def variables(entity)
- { full_path: entity.source_full_path }
+ def variables(context)
+ { full_path: context.entity.source_full_path }
+ end
+
+ def base_path
+ %w[data group]
+ end
+
+ def data_path
+ base_path
+ end
+
+ def page_info_path
+ base_path << 'page_info'
end
end
end
diff --git a/lib/bulk_imports/groups/graphql/get_labels_query.rb b/lib/bulk_imports/groups/graphql/get_labels_query.rb
new file mode 100644
index 00000000000..d1fe791c2ce
--- /dev/null
+++ b/lib/bulk_imports/groups/graphql/get_labels_query.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Graphql
+ module GetLabelsQuery
+ extend self
+
+ def to_s
+ <<-'GRAPHQL'
+ query ($full_path: ID!, $cursor: String) {
+ group(fullPath: $full_path) {
+ labels(first: 100, after: $cursor) {
+ page_info: pageInfo {
+ end_cursor: endCursor
+ has_next_page: hasNextPage
+ }
+ nodes {
+ title
+ description
+ color
+ }
+ }
+ }
+ }
+ GRAPHQL
+ end
+
+ def variables(context)
+ {
+ full_path: context.entity.source_full_path,
+ cursor: context.entity.next_page_for(:labels)
+ }
+ end
+
+ def base_path
+ %w[data group labels]
+ end
+
+ def data_path
+ base_path << 'nodes'
+ end
+
+ def page_info_path
+ base_path << 'page_info'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/graphql/get_members_query.rb b/lib/bulk_imports/groups/graphql/get_members_query.rb
new file mode 100644
index 00000000000..e3a78124a47
--- /dev/null
+++ b/lib/bulk_imports/groups/graphql/get_members_query.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Graphql
+ module GetMembersQuery
+ extend self
+ def to_s
+ <<-'GRAPHQL'
+ query($full_path: ID!, $cursor: String) {
+ group(fullPath: $full_path) {
+ group_members: groupMembers(relations: DIRECT, first: 100, after: $cursor) {
+ page_info: pageInfo {
+ end_cursor: endCursor
+ has_next_page: hasNextPage
+ }
+ nodes {
+ created_at: createdAt
+ updated_at: updatedAt
+ expires_at: expiresAt
+ access_level: accessLevel {
+ integer_value: integerValue
+ }
+ user {
+ public_email: publicEmail
+ }
+ }
+ }
+ }
+ }
+ GRAPHQL
+ end
+
+ def variables(context)
+ {
+ full_path: context.entity.source_full_path,
+ cursor: context.entity.next_page_for(:group_members)
+ }
+ end
+
+ def base_path
+ %w[data group group_members]
+ end
+
+ def data_path
+ base_path << 'nodes'
+ end
+
+ def page_info_path
+ base_path << 'page_info'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/loaders/labels_loader.rb b/lib/bulk_imports/groups/loaders/labels_loader.rb
new file mode 100644
index 00000000000..b8c9ba9609c
--- /dev/null
+++ b/lib/bulk_imports/groups/loaders/labels_loader.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Loaders
+ class LabelsLoader
+ def initialize(*); end
+
+ def load(context, data)
+ Labels::CreateService.new(data).execute(group: context.group)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/loaders/members_loader.rb b/lib/bulk_imports/groups/loaders/members_loader.rb
new file mode 100644
index 00000000000..ccf44b31aee
--- /dev/null
+++ b/lib/bulk_imports/groups/loaders/members_loader.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Loaders
+ class MembersLoader
+ def initialize(*); end
+
+ def load(context, data)
+ return unless data
+
+ context.group.members.create!(data)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/group_pipeline.rb b/lib/bulk_imports/groups/pipelines/group_pipeline.rb
index 5169e292180..8c6f089e8a4 100644
--- a/lib/bulk_imports/groups/pipelines/group_pipeline.rb
+++ b/lib/bulk_imports/groups/pipelines/group_pipeline.rb
@@ -10,8 +10,6 @@ module BulkImports
extractor Common::Extractors::GraphqlExtractor, query: Graphql::GetGroupQuery
- transformer Common::Transformers::HashKeyDigger, key_path: %w[data group]
- transformer Common::Transformers::UnderscorifyKeysTransformer
transformer Common::Transformers::ProhibitedAttributesTransformer
transformer Groups::Transformers::GroupAttributesTransformer
diff --git a/lib/bulk_imports/groups/pipelines/labels_pipeline.rb b/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
new file mode 100644
index 00000000000..40dab9b444c
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/labels_pipeline.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Pipelines
+ class LabelsPipeline
+ include Pipeline
+
+ extractor BulkImports::Common::Extractors::GraphqlExtractor,
+ query: BulkImports::Groups::Graphql::GetLabelsQuery
+
+ transformer Common::Transformers::ProhibitedAttributesTransformer
+
+ loader BulkImports::Groups::Loaders::LabelsLoader
+
+ def after_run(extracted_data)
+ context.entity.update_tracker_for(
+ relation: :labels,
+ has_next_page: extracted_data.has_next_page?,
+ next_page: extracted_data.next_page
+ )
+
+ if extracted_data.has_next_page?
+ run
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/members_pipeline.rb b/lib/bulk_imports/groups/pipelines/members_pipeline.rb
new file mode 100644
index 00000000000..b00c4c1a659
--- /dev/null
+++ b/lib/bulk_imports/groups/pipelines/members_pipeline.rb
@@ -0,0 +1,31 @@
+# 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
+
+ loader BulkImports::Groups::Loaders::MembersLoader
+
+ def after_run(extracted_data)
+ context.entity.update_tracker_for(
+ relation: :group_members,
+ has_next_page: extracted_data.has_next_page?,
+ next_page: extracted_data.next_page
+ )
+
+ if extracted_data.has_next_page?
+ run
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb b/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb
new file mode 100644
index 00000000000..622f5b60ffe
--- /dev/null
+++ b/lib/bulk_imports/groups/transformers/member_attributes_transformer.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Groups
+ module Transformers
+ class MemberAttributesTransformer
+ def initialize(*); end
+
+ def transform(context, data)
+ data
+ .then { |data| add_user(data) }
+ .then { |data| add_access_level(data) }
+ .then { |data| add_author(data, context) }
+ end
+
+ private
+
+ def add_user(data)
+ user = find_user(data&.dig('user', 'public_email'))
+
+ return unless user
+
+ data
+ .except('user')
+ .merge('user_id' => user.id)
+ end
+
+ 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)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/importers/group_importer.rb b/lib/bulk_imports/importers/group_importer.rb
index 6e1b86e9515..f967b7ad7ab 100644
--- a/lib/bulk_imports/importers/group_importer.rb
+++ b/lib/bulk_imports/importers/group_importer.rb
@@ -8,16 +8,9 @@ module BulkImports
end
def execute
- bulk_import = entity.bulk_import
- configuration = bulk_import.configuration
+ context = BulkImports::Pipeline::Context.new(entity)
- context = BulkImports::Pipeline::Context.new(
- current_user: bulk_import.user,
- entity: entity,
- configuration: configuration
- )
-
- pipelines.each { |pipeline| pipeline.new.run(context) }
+ pipelines.each { |pipeline| pipeline.new(context).run }
entity.finish!
end
@@ -29,7 +22,9 @@ module BulkImports
def pipelines
[
BulkImports::Groups::Pipelines::GroupPipeline,
- BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline
+ BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline,
+ BulkImports::Groups::Pipelines::MembersPipeline,
+ BulkImports::Groups::Pipelines::LabelsPipeline
]
end
end
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
index 06b81b5da14..1d55ad95887 100644
--- a/lib/bulk_imports/pipeline.rb
+++ b/lib/bulk_imports/pipeline.rb
@@ -4,12 +4,17 @@ module BulkImports
module Pipeline
extend ActiveSupport::Concern
include Gitlab::ClassAttributes
+ include Runner
- included do
- include Runner
+ def initialize(context)
+ @context = context
+ end
+ included do
private
+ attr_reader :context
+
def extractor
@extractor ||= instantiate(self.class.get_extractor)
end
@@ -22,10 +27,6 @@ module BulkImports
@loaders ||= instantiate(self.class.get_loader)
end
- def after_run
- @after_run ||= self.class.after_run_callback
- end
-
def pipeline
@pipeline ||= self.class.name
end
@@ -52,10 +53,6 @@ module BulkImports
class_attributes[:loader] = { klass: klass, options: options }
end
- def after_run(&block)
- class_attributes[:after_run] = block
- end
-
def get_extractor
class_attributes[:extractor]
end
@@ -68,10 +65,6 @@ module BulkImports
class_attributes[:loader]
end
- def after_run_callback
- class_attributes[:after_run]
- end
-
def abort_on_failure!
class_attributes[:abort_on_failure] = true
end
diff --git a/lib/bulk_imports/pipeline/context.rb b/lib/bulk_imports/pipeline/context.rb
index ad19f5cad7d..dd121b2dbed 100644
--- a/lib/bulk_imports/pipeline/context.rb
+++ b/lib/bulk_imports/pipeline/context.rb
@@ -3,30 +3,25 @@
module BulkImports
module Pipeline
class Context
- include Gitlab::Utils::LazyAttributes
+ attr_reader :entity, :bulk_import
+ attr_accessor :extra
- Attribute = Struct.new(:name, :type)
-
- PIPELINE_ATTRIBUTES = [
- Attribute.new(:current_user, User),
- Attribute.new(:entity, ::BulkImports::Entity),
- Attribute.new(:configuration, ::BulkImports::Configuration)
- ].freeze
-
- def initialize(args)
- assign_attributes(args)
+ def initialize(entity, extra = {})
+ @entity = entity
+ @bulk_import = entity.bulk_import
+ @extra = extra
end
- private
+ def group
+ entity.group
+ end
- PIPELINE_ATTRIBUTES.each do |attr|
- lazy_attr_reader attr.name, type: attr.type
+ def current_user
+ bulk_import.user
end
- def assign_attributes(values)
- values.slice(*PIPELINE_ATTRIBUTES.map(&:name)).each do |name, value|
- instance_variable_set("@#{name}", value)
- end
+ def configuration
+ bulk_import.configuration
end
end
end
diff --git a/lib/bulk_imports/pipeline/extracted_data.rb b/lib/bulk_imports/pipeline/extracted_data.rb
new file mode 100644
index 00000000000..685a91a4afe
--- /dev/null
+++ b/lib/bulk_imports/pipeline/extracted_data.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Pipeline
+ class ExtractedData
+ attr_reader :data
+
+ def initialize(data: nil, page_info: {})
+ @data = Array.wrap(data)
+ @page_info = page_info
+ end
+
+ def has_next_page?
+ @page_info['has_next_page']
+ end
+
+ def next_page
+ @page_info['end_cursor']
+ end
+
+ def each(&block)
+ data.each(&block)
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/pipeline/runner.rb b/lib/bulk_imports/pipeline/runner.rb
index 11fb9722173..d39f4121b51 100644
--- a/lib/bulk_imports/pipeline/runner.rb
+++ b/lib/bulk_imports/pipeline/runner.rb
@@ -7,75 +7,86 @@ module BulkImports
MarkedAsFailedError = Class.new(StandardError)
- def run(context)
- raise MarkedAsFailedError if marked_as_failed?(context)
+ def run
+ raise MarkedAsFailedError if marked_as_failed?
- info(context, message: 'Pipeline started', pipeline_class: pipeline)
+ info(message: 'Pipeline started')
- Array.wrap(extracted_data_from(context)).each do |entry|
+ extracted_data = extracted_data_from
+
+ extracted_data&.each do |entry|
transformers.each do |transformer|
- entry = run_pipeline_step(:transformer, transformer.class.name, context) do
+ entry = run_pipeline_step(:transformer, transformer.class.name) do
transformer.transform(context, entry)
end
end
- run_pipeline_step(:loader, loader.class.name, context) do
+ run_pipeline_step(:loader, loader.class.name) do
loader.load(context, entry)
end
end
- after_run.call(context) if after_run.present?
+ if respond_to?(:after_run)
+ run_pipeline_step(:after_run) do
+ after_run(extracted_data)
+ end
+ end
+
+ info(message: 'Pipeline finished')
rescue MarkedAsFailedError
- log_skip(context)
+ log_skip
end
private # rubocop:disable Lint/UselessAccessModifier
- def run_pipeline_step(type, class_name, context)
- raise MarkedAsFailedError if marked_as_failed?(context)
+ def run_pipeline_step(step, class_name = nil)
+ raise MarkedAsFailedError if marked_as_failed?
- info(context, type => class_name)
+ info(pipeline_step: step, step_class: class_name)
yield
rescue MarkedAsFailedError
- log_skip(context, type => class_name)
+ log_skip(step => class_name)
rescue => e
- log_import_failure(e, context)
+ log_import_failure(e, step)
- mark_as_failed(context) if abort_on_failure?
+ mark_as_failed if abort_on_failure?
+
+ nil
end
- def extracted_data_from(context)
- run_pipeline_step(:extractor, extractor.class.name, context) do
+ def extracted_data_from
+ run_pipeline_step(:extractor, extractor.class.name) do
extractor.extract(context)
end
end
- def mark_as_failed(context)
- warn(context, message: 'Pipeline failed', pipeline_class: pipeline)
+ def mark_as_failed
+ warn(message: 'Pipeline failed', pipeline_class: pipeline)
context.entity.fail_op!
end
- def marked_as_failed?(context)
+ def marked_as_failed?
return true if context.entity.failed?
false
end
- def log_skip(context, extra = {})
+ def log_skip(extra = {})
log = {
message: 'Skipping due to failed pipeline status',
pipeline_class: pipeline
}.merge(extra)
- info(context, log)
+ info(log)
end
- def log_import_failure(exception, context)
+ def log_import_failure(exception, step)
attributes = {
bulk_import_entity_id: context.entity.id,
pipeline_class: pipeline,
+ pipeline_step: step,
exception_class: exception.class.to_s,
exception_message: exception.message.truncate(255),
correlation_id_value: Labkit::Correlation::CorrelationId.current_or_new_id
@@ -84,19 +95,22 @@ module BulkImports
BulkImports::Failure.create(attributes)
end
- def warn(context, extra = {})
- logger.warn(log_base_params(context).merge(extra))
+ def warn(extra = {})
+ logger.warn(log_params(extra))
end
- def info(context, extra = {})
- logger.info(log_base_params(context).merge(extra))
+ def info(extra = {})
+ logger.info(log_params(extra))
end
- def log_base_params(context)
- {
+ def log_params(extra)
+ defaults = {
bulk_import_entity_id: context.entity.id,
- bulk_import_entity_type: context.entity.source_type
+ bulk_import_entity_type: context.entity.source_type,
+ pipeline_class: pipeline
}
+
+ defaults.merge(extra).compact
end
def logger
diff --git a/lib/feature.rb b/lib/feature.rb
index 3d4a919b043..7c926b25587 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -133,7 +133,7 @@ class Feature
# This method is called from config/initializers/flipper.rb and can be used
# to register Flipper groups.
- # See https://docs.gitlab.com/ee/development/feature_flags.html#feature-groups
+ # See https://docs.gitlab.com/ee/development/feature_flags/index.html
def register_feature_groups
end
diff --git a/lib/feature/gitaly.rb b/lib/feature/gitaly.rb
index 2d0fdf98e8c..e603a1dc8d2 100644
--- a/lib/feature/gitaly.rb
+++ b/lib/feature/gitaly.rb
@@ -5,25 +5,25 @@ class Feature
PREFIX = "gitaly_"
class << self
- def enabled?(feature_flag)
+ def enabled?(feature_flag, project = nil)
return false unless Feature::FlipperFeature.table_exists?
- Feature.enabled?("#{PREFIX}#{feature_flag}")
+ Feature.enabled?("#{PREFIX}#{feature_flag}", project)
rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad
false
end
- def server_feature_flags
+ def server_feature_flags(project = nil)
# We need to check that both the DB connection and table exists
return {} unless ::Gitlab::Database.cached_table_exists?(FlipperFeature.table_name)
Feature.persisted_names
.select { |f| f.start_with?(PREFIX) }
- .map do |f|
+ .to_h do |f|
flag = f.delete_prefix(PREFIX)
- ["gitaly-feature-#{flag.tr('_', '-')}", enabled?(flag).to_s]
- end.to_h
+ ["gitaly-feature-#{flag.tr('_', '-')}", enabled?(flag, project).to_s]
+ end
end
end
end
diff --git a/lib/generators/gitlab/usage_metric_definition_generator.rb b/lib/generators/gitlab/usage_metric_definition_generator.rb
new file mode 100644
index 00000000000..d3fac4c74f3
--- /dev/null
+++ b/lib/generators/gitlab/usage_metric_definition_generator.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'rails/generators'
+
+module Gitlab
+ class UsageMetricDefinitionGenerator < Rails::Generators::Base
+ Directory = Struct.new(:name, :time_frame, :value_type) do
+ def match?(str)
+ (name == str || time_frame == str) && str != 'none'
+ end
+ end
+
+ TIME_FRAME_DIRS = [
+ Directory.new('counts_7d', '7d', 'number'),
+ Directory.new('counts_28d', '28d', 'number'),
+ Directory.new('counts_all', 'all', 'number'),
+ Directory.new('settings', 'none', 'boolean'),
+ Directory.new('license', 'none', 'string')
+ ].freeze
+
+ VALID_INPUT_DIRS = (TIME_FRAME_DIRS.flat_map { |d| [d.name, d.time_frame] } - %w(none)).freeze
+
+ source_root File.expand_path('../../../generator_templates/usage_metric_definition', __dir__)
+
+ desc 'Generates a metric definition yml file'
+
+ class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if metric is for ee'
+ class_option :dir,
+ type: :string, desc: "Indicates the metric location. It must be one of: #{VALID_INPUT_DIRS.join(', ')}"
+
+ argument :key_path, type: :string, desc: 'Unique JSON key path for the metric'
+
+ def create_metric_file
+ validate!
+
+ template "metric_definition.yml", file_path
+ end
+
+ def time_frame
+ directory&.time_frame
+ end
+
+ def value_type
+ directory&.value_type
+ end
+
+ def distribution
+ value = ['- ce']
+ value << '- ee' if ee?
+ value.join("\n")
+ end
+
+ def milestone
+ Gitlab::VERSION.match('(\d+\.\d+)').captures.first
+ end
+
+ private
+
+ def file_path
+ path = File.join('config', 'metrics', directory&.name, "#{file_name}.yml")
+ path = File.join('ee', path) if ee?
+ path
+ end
+
+ def validate!
+ raise "--dir option is required" unless input_dir.present?
+ raise "Invalid dir #{input_dir}, allowed options are #{VALID_INPUT_DIRS.join(', ')}" unless directory.present?
+ end
+
+ def ee?
+ options[:ee]
+ end
+
+ def input_dir
+ options[:dir]
+ end
+
+ # Example of file name
+ #
+ # 20210201124931_g_project_management_issue_title_changed_weekly.yml
+ def file_name
+ "#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_#{key_path.split('.').last}"
+ end
+
+ def directory
+ @directory ||= TIME_FRAME_DIRS.find { |d| d.match?(input_dir) }
+ end
+ end
+end
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 0f2fd01e3c7..f943b532454 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -48,6 +48,10 @@ module Gitlab
Gitlab.config.gitlab.url == COM_URL || gl_subdomain?
end
+ def self.com
+ yield if com?
+ end
+
def self.staging?
Gitlab.config.gitlab.url == STAGING_COM_URL
end
@@ -117,7 +121,7 @@ module Gitlab
end
def self.maintenance_mode?
- return false unless ::Feature.enabled?(:maintenance_mode)
+ return false unless ::Gitlab::CurrentSettings.current_application_settings?
::Gitlab::CurrentSettings.maintenance_mode
end
diff --git a/lib/gitlab/alert_management/payload.rb b/lib/gitlab/alert_management/payload.rb
index ce09ffd87ee..a1063001330 100644
--- a/lib/gitlab/alert_management/payload.rb
+++ b/lib/gitlab/alert_management/payload.rb
@@ -17,13 +17,14 @@ module Gitlab
# @param project [Project]
# @param payload [Hash]
# @param monitoring_tool [String]
- def parse(project, payload, monitoring_tool: nil)
+ # @param integration [AlertManagement::HttpIntegration]
+ def parse(project, payload, monitoring_tool: nil, integration: nil)
payload_class = payload_class_for(
monitoring_tool: monitoring_tool || payload&.dig('monitoring_tool'),
payload: payload
)
- payload_class.new(project: project, payload: payload)
+ payload_class.new(project: project, payload: payload, integration: integration)
end
private
@@ -47,3 +48,5 @@ module Gitlab
end
end
end
+
+Gitlab::AlertManagement::Payload.prepend_if_ee('EE::Gitlab::AlertManagement::Payload')
diff --git a/lib/gitlab/alert_management/payload/base.rb b/lib/gitlab/alert_management/payload/base.rb
index 0fd593a3780..c8b8d6c259d 100644
--- a/lib/gitlab/alert_management/payload/base.rb
+++ b/lib/gitlab/alert_management/payload/base.rb
@@ -12,7 +12,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
include Gitlab::Routing
- attr_accessor :project, :payload
+ attr_accessor :project, :payload, :integration
# Any attribute expected to be specifically read from
# or derived from an alert payload should be defined.
@@ -44,11 +44,25 @@ module Gitlab
:title
].freeze
+ private_constant :EXPECTED_PAYLOAD_ATTRIBUTES
+
# Define expected API for a payload
EXPECTED_PAYLOAD_ATTRIBUTES.each do |key|
define_method(key) {}
end
+ SEVERITY_MAPPING = {
+ 'critical' => :critical,
+ 'high' => :high,
+ 'medium' => :medium,
+ 'low' => :low,
+ 'info' => :info
+ }.freeze
+
+ # Handle an unmapped severity value the same way we treat missing values
+ # so we can fallback to alert's default severity `critical`.
+ UNMAPPED_SEVERITY = nil
+
# Defines a method which allows access to a given
# value within an alert payload
#
@@ -131,9 +145,21 @@ module Gitlab
true
end
+ def severity
+ severity_mapping.fetch(severity_raw.to_s.downcase, UNMAPPED_SEVERITY)
+ end
+
private
- def plain_gitlab_fingerprint; end
+ def plain_gitlab_fingerprint
+ end
+
+ def severity_raw
+ end
+
+ def severity_mapping
+ SEVERITY_MAPPING
+ end
def truncate_hosts(hosts)
return hosts if hosts.join.length <= ::AlertManagement::Alert::HOSTS_MAX_LENGTH
@@ -147,6 +173,7 @@ module Gitlab
end
end
+ # Overriden in EE::Gitlab::AlertManagement::Payload::Generic
def value_for_paths(paths)
target_path = paths.find { |path| payload&.dig(*path) }
diff --git a/lib/gitlab/alert_management/payload/generic.rb b/lib/gitlab/alert_management/payload/generic.rb
index e8e85155bef..0eb1bee8181 100644
--- a/lib/gitlab/alert_management/payload/generic.rb
+++ b/lib/gitlab/alert_management/payload/generic.rb
@@ -6,7 +6,6 @@ module Gitlab
module Payload
class Generic < Base
DEFAULT_TITLE = 'New: Incident'
- DEFAULT_SEVERITY = 'critical'
attribute :description, paths: 'description'
attribute :ends_at, paths: 'end_time', type: :time
@@ -15,10 +14,12 @@ module Gitlab
attribute :monitoring_tool, paths: 'monitoring_tool'
attribute :runbook, paths: 'runbook'
attribute :service, paths: 'service'
- attribute :severity, paths: 'severity', fallback: -> { DEFAULT_SEVERITY }
attribute :starts_at, paths: 'start_time', type: :time, fallback: -> { Time.current.utc }
attribute :title, paths: 'title', fallback: -> { DEFAULT_TITLE }
+ attribute :severity_raw, paths: 'severity'
+ private :severity_raw
+
attribute :plain_gitlab_fingerprint, paths: 'fingerprint'
private :plain_gitlab_fingerprint
end
diff --git a/lib/gitlab/alert_management/payload/prometheus.rb b/lib/gitlab/alert_management/payload/prometheus.rb
index 336e9b319e8..4c36ebbf3aa 100644
--- a/lib/gitlab/alert_management/payload/prometheus.rb
+++ b/lib/gitlab/alert_management/payload/prometheus.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
-# Attribute mapping for alerts via prometheus alerting integration.
module Gitlab
module AlertManagement
module Payload
+ # Attribute mapping for alerts via prometheus alerting integration.
class Prometheus < Base
+ extend Gitlab::Utils::Override
+
attribute :alert_markdown, paths: %w(annotations gitlab_incident_markdown)
attribute :annotations, paths: 'annotations'
attribute :description, paths: %w(annotations description)
@@ -26,13 +28,40 @@ module Gitlab
paths: [%w(annotations title),
%w(annotations summary),
%w(labels alertname)]
-
attribute :starts_at_raw,
paths: [%w(startsAt)]
private :starts_at_raw
+ attribute :severity_raw, paths: %w(labels severity)
+ private :severity_raw
+
METRIC_TIME_WINDOW = 30.minutes
+ ADDITIONAL_SEVERITY_MAPPING = {
+ 's1' => :critical,
+ 's2' => :high,
+ 's3' => :medium,
+ 's4' => :low,
+ 's5' => :info,
+ 'p1' => :critical,
+ 'p2' => :high,
+ 'p3' => :medium,
+ 'p4' => :low,
+ 'p5' => :info,
+ 'debug' => :info,
+ 'information' => :info,
+ 'notice' => :info,
+ 'warn' => :low,
+ 'warning' => :low,
+ 'minor' => :low,
+ 'error' => :medium,
+ 'major' => :high,
+ 'emergency' => :critical,
+ 'fatal' => :critical,
+ 'alert' => :medium,
+ 'page' => :high
+ }.freeze
+
def monitoring_tool
Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
end
@@ -67,6 +96,11 @@ module Gitlab
private
+ override :severity_mapping
+ def severity_mapping
+ super.merge(ADDITIONAL_SEVERITY_MAPPING)
+ end
+
def plain_gitlab_fingerprint
[starts_at_raw, title, full_query].join('/')
end
diff --git a/lib/gitlab/api_authentication/token_locator.rb b/lib/gitlab/api_authentication/token_locator.rb
index 32a98908e5b..09039f3fc43 100644
--- a/lib/gitlab/api_authentication/token_locator.rb
+++ b/lib/gitlab/api_authentication/token_locator.rb
@@ -10,7 +10,7 @@ module Gitlab
attr_reader :location
- validates :location, inclusion: { in: %i[http_basic_auth] }
+ validates :location, inclusion: { in: %i[http_basic_auth http_token] }
def initialize(location)
@location = location
@@ -21,6 +21,8 @@ module Gitlab
case @location
when :http_basic_auth
extract_from_http_basic_auth request
+ when :http_token
+ extract_from_http_token request
end
end
@@ -32,6 +34,13 @@ module Gitlab
UsernameAndPassword.new(username, password)
end
+
+ def extract_from_http_token(request)
+ password = request.headers['Authorization']
+ return unless password.present?
+
+ UsernameAndPassword.new(nil, password)
+ end
end
end
end
diff --git a/lib/gitlab/api_authentication/token_resolver.rb b/lib/gitlab/api_authentication/token_resolver.rb
index 5b30777b6ec..9234837cdf7 100644
--- a/lib/gitlab/api_authentication/token_resolver.rb
+++ b/lib/gitlab/api_authentication/token_resolver.rb
@@ -7,7 +7,16 @@ module Gitlab
attr_reader :token_type
- validates :token_type, inclusion: { in: %i[personal_access_token job_token deploy_token] }
+ validates :token_type, inclusion: {
+ in: %i[
+ personal_access_token_with_username
+ job_token_with_username
+ deploy_token_with_username
+ personal_access_token
+ job_token
+ deploy_token
+ ]
+ }
def initialize(token_type)
@token_type = token_type
@@ -38,49 +47,94 @@ module Gitlab
when :deploy_token
resolve_deploy_token raw
+
+ when :personal_access_token_with_username
+ resolve_personal_access_token_with_username raw
+
+ when :job_token_with_username
+ resolve_job_token_with_username raw
+
+ when :deploy_token_with_username
+ resolve_deploy_token_with_username raw
end
end
private
- def resolve_personal_access_token(raw)
- # Check if the password is a personal access token
- pat = ::PersonalAccessToken.find_by_token(raw.password)
- return unless pat
+ def resolve_personal_access_token_with_username(raw)
+ raise ::Gitlab::Auth::UnauthorizedError unless raw.username
+
+ with_personal_access_token(raw) do |pat|
+ break unless pat
- # Ensure that the username matches the token. This check is a subtle
- # departure from the existing behavior of #find_personal_access_token_from_http_basic_auth.
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_435907856
- raise ::Gitlab::Auth::UnauthorizedError unless pat.user.username == raw.username
+ # Ensure that the username matches the token. This check is a subtle
+ # departure from the existing behavior of #find_personal_access_token_from_http_basic_auth.
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_435907856
+ raise ::Gitlab::Auth::UnauthorizedError unless pat.user.username == raw.username
- pat
+ pat
+ end
end
- def resolve_job_token(raw)
+ def resolve_job_token_with_username(raw)
# Only look for a job if the username is correct
return if ::Gitlab::Auth::CI_JOB_USER != raw.username
- job = ::Ci::AuthJobFinder.new(token: raw.password).execute
+ with_job_token(raw) do |job|
+ job
+ end
+ end
- # Actively reject credentials with the username `gitlab-ci-token` if
- # the password is not a valid job token. This replicates existing
- # behavior of #find_user_from_job_token.
- raise ::Gitlab::Auth::UnauthorizedError unless job
+ def resolve_deploy_token_with_username(raw)
+ with_deploy_token(raw) do |token|
+ break unless token
+
+ # Ensure that the username matches the token. This check is a subtle
+ # departure from the existing behavior of #deploy_token_from_request.
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_474826205
+ raise ::Gitlab::Auth::UnauthorizedError unless token.username == raw.username
- job
+ token
+ end
+ end
+
+ def resolve_personal_access_token(raw)
+ with_personal_access_token(raw) do |pat|
+ pat
+ end
+ end
+
+ def resolve_job_token(raw)
+ with_job_token(raw) do |job|
+ job
+ end
end
def resolve_deploy_token(raw)
- # Check if the password is a deploy token
+ with_deploy_token(raw) do |token|
+ token
+ end
+ end
+
+ def with_personal_access_token(raw, &block)
+ pat = ::PersonalAccessToken.find_by_token(raw.password)
+ return unless pat
+
+ yield(pat)
+ end
+
+ def with_deploy_token(raw, &block)
token = ::DeployToken.active.find_by_token(raw.password)
return unless token
- # Ensure that the username matches the token. This check is a subtle
- # departure from the existing behavior of #deploy_token_from_request.
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38627#note_474826205
- raise ::Gitlab::Auth::UnauthorizedError unless token.username == raw.username
+ yield(token)
+ end
+
+ def with_job_token(raw, &block)
+ job = ::Ci::AuthJobFinder.new(token: raw.password).execute
+ raise ::Gitlab::Auth::UnauthorizedError unless job
- token
+ yield(job)
end
end
end
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index fbba86d1253..0a69a9c503d 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -20,6 +20,7 @@ module Gitlab
def rate_limits
{
issues_create: { threshold: -> { application_settings.issues_create_limit }, interval: 1.minute },
+ notes_create: { threshold: -> { application_settings.notes_create_limit }, interval: 1.minute },
project_export: { threshold: -> { application_settings.project_export_limit }, interval: 1.minute },
project_download_export: { threshold: -> { application_settings.project_download_export_limit }, interval: 1.minute },
project_repositories_archive: { threshold: 5, interval: 1.minute },
@@ -46,15 +47,17 @@ module Gitlab
# @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
# @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
# @option interval [Integer] Optional interval value to override default one registered in `.rate_limits`
+ # @option users_allowlist [Array<String>] Optional list of usernames to excepted from the limit. This param will only be functional if Scope includes a current user.
#
# @return [Boolean] Whether or not a request should be throttled
- def throttled?(key, scope: nil, interval: nil, threshold: nil)
+ def throttled?(key, **options)
return unless rate_limits[key]
- threshold_value = threshold || threshold(key)
+ return if scoped_user_in_allowlist?(options)
+ threshold_value = options[:threshold] || threshold(key)
threshold_value > 0 &&
- increment(key, scope, interval) > threshold_value
+ increment(key, options[:scope], options[:interval]) > threshold_value
end
# Increments the given cache key and increments the value by 1 with the
@@ -140,6 +143,15 @@ module Gitlab
def application_settings
Gitlab::CurrentSettings.current_application_settings
end
+
+ def scoped_user_in_allowlist?(options)
+ return unless options[:users_allowlist].present?
+
+ scoped_user = [options[:scope]].flatten.find { |s| s.is_a?(User) }
+ return unless scoped_user
+
+ scoped_user.username.downcase.in?(options[:users_allowlist])
+ end
end
end
end
diff --git a/lib/gitlab/auth/otp/session_enforcer.rb b/lib/gitlab/auth/otp/session_enforcer.rb
deleted file mode 100644
index 8cc280756cc..00000000000
--- a/lib/gitlab/auth/otp/session_enforcer.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Auth
- module Otp
- class SessionEnforcer
- OTP_SESSIONS_NAMESPACE = 'session:otp'
- DEFAULT_EXPIRATION = 15.minutes.to_i
-
- def initialize(key)
- @key = key
- end
-
- def update_session
- Gitlab::Redis::SharedState.with do |redis|
- redis.setex(key_name, DEFAULT_EXPIRATION, true)
- end
- end
-
- def access_restricted?
- Gitlab::Redis::SharedState.with do |redis|
- !redis.get(key_name)
- end
- end
-
- private
-
- attr_reader :key
-
- def key_name
- @key_name ||= "#{OTP_SESSIONS_NAMESPACE}:#{key.id}"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/auth/u2f_webauthn_converter.rb b/lib/gitlab/auth/u2f_webauthn_converter.rb
new file mode 100644
index 00000000000..f85b2248aeb
--- /dev/null
+++ b/lib/gitlab/auth/u2f_webauthn_converter.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ class U2fWebauthnConverter
+ def initialize(u2f_registration)
+ @u2f_registration = u2f_registration
+ end
+
+ def convert
+ now = Time.current
+
+ converted_credential = WebAuthn::U2fMigrator.new(
+ app_id: Gitlab.config.gitlab.url,
+ certificate: u2f_registration.certificate,
+ key_handle: u2f_registration.key_handle,
+ public_key: u2f_registration.public_key,
+ counter: u2f_registration.counter
+ ).credential
+
+ {
+ credential_xid: Base64.strict_encode64(converted_credential.id),
+ public_key: Base64.strict_encode64(converted_credential.public_key),
+ counter: u2f_registration.counter || 0,
+ name: u2f_registration.name || '',
+ user_id: u2f_registration.user_id,
+ u2f_registration_id: u2f_registration.id,
+ created_at: now,
+ updated_at: now
+ }
+ end
+
+ private
+
+ attr_reader :u2f_registration
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index d1b9062a23c..9f4d6557023 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -33,7 +33,7 @@ module Gitlab
next unless job.queue == self.queue
next unless migration_class == steal_class
- next if block_given? && !(yield migration_args)
+ next if block_given? && !(yield job)
begin
perform(migration_class, migration_args) if job.delete
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
new file mode 100644
index 00000000000..61eb3b332de
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move.rb
@@ -0,0 +1,22 @@
+# 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 = ProjectRepositoryStorageMove.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 (
+ #{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/migrate_devops_segments_to_groups.rb b/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb
new file mode 100644
index 00000000000..de2d9909961
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_devops_segments_to_groups.rb
@@ -0,0 +1,13 @@
+# 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_if_ee('EE::Gitlab::BackgroundMigration::MigrateDevopsSegmentsToGroups')
diff --git a/lib/gitlab/background_migration/migrate_u2f_webauthn.rb b/lib/gitlab/background_migration/migrate_u2f_webauthn.rb
index b8c14aa2573..091e6660bac 100644
--- a/lib/gitlab/background_migration/migrate_u2f_webauthn.rb
+++ b/lib/gitlab/background_migration/migrate_u2f_webauthn.rb
@@ -16,26 +16,9 @@ module Gitlab
def perform(start_id, end_id)
old_registrations = U2fRegistration.where(id: start_id..end_id)
old_registrations.each_slice(100) do |slice|
- now = Time.now
values = slice.map do |u2f_registration|
- converted_credential = WebAuthn::U2fMigrator.new(
- app_id: Gitlab.config.gitlab.url,
- certificate: u2f_registration.certificate,
- key_handle: u2f_registration.key_handle,
- public_key: u2f_registration.public_key,
- counter: u2f_registration.counter
- ).credential
-
- {
- credential_xid: Base64.strict_encode64(converted_credential.id),
- public_key: Base64.strict_encode64(converted_credential.public_key),
- counter: u2f_registration.counter || 0,
- name: u2f_registration.name || '',
- user_id: u2f_registration.user_id,
- u2f_registration_id: u2f_registration.id,
- created_at: now,
- updated_at: now
- }
+ converter = Gitlab::Auth::U2fWebauthnConverter.new(u2f_registration)
+ converter.convert
end
WebauthnRegistration.insert_all(values, unique_by: :credential_xid, returning: false)
diff --git a/lib/gitlab/background_migration/populate_issue_email_participants.rb b/lib/gitlab/background_migration/populate_issue_email_participants.rb
new file mode 100644
index 00000000000..d6795296fb7
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_issue_email_participants.rb
@@ -0,0 +1,28 @@
+# 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
+
+ Gitlab::Database.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_uuids_for_security_findings.rb b/lib/gitlab/background_migration/populate_uuids_for_security_findings.rb
new file mode 100644
index 00000000000..3d3970f50e1
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_uuids_for_security_findings.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop:disable Style/Documentation
+ class PopulateUuidsForSecurityFindings
+ NOP_RELATION = Class.new { def each_batch(*); end }
+
+ def self.security_findings
+ NOP_RELATION.new
+ end
+
+ def perform(_scan_ids); end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PopulateUuidsForSecurityFindings.prepend_if_ee('::EE::Gitlab::BackgroundMigration::PopulateUuidsForSecurityFindings')
diff --git a/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb b/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb
new file mode 100644
index 00000000000..ca61118a06c
--- /dev/null
+++ b/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+# rubocop: disable Style/Documentation
+class Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings
+ DELETE_BATCH_SIZE = 100
+
+ # rubocop:disable Gitlab/NamespacedClass
+ class VulnerabilitiesFinding < ActiveRecord::Base
+ self.table_name = "vulnerability_occurrences"
+ end
+ # rubocop:enable Gitlab/NamespacedClass
+
+ def perform(start_id, end_id)
+ batch = VulnerabilitiesFinding.where(id: start_id..end_id)
+
+ cte = Gitlab::SQL::CTE.new(:batch, batch.select(:report_type, :location_fingerprint, :primary_identifier_id, :project_id))
+
+ query = VulnerabilitiesFinding
+ .select('batch.report_type', 'batch.location_fingerprint', 'batch.primary_identifier_id', 'batch.project_id', 'array_agg(id) as ids')
+ .distinct
+ .with(cte.to_arel)
+ .from(cte.alias_to(Arel.sql('batch')))
+ .joins(
+ %(
+ INNER JOIN
+ vulnerability_occurrences ON
+ vulnerability_occurrences.report_type = batch.report_type AND
+ vulnerability_occurrences.location_fingerprint = batch.location_fingerprint AND
+ vulnerability_occurrences.primary_identifier_id = batch.primary_identifier_id AND
+ vulnerability_occurrences.project_id = batch.project_id
+ )).group('batch.report_type', 'batch.location_fingerprint', 'batch.primary_identifier_id', 'batch.project_id')
+ .having('COUNT(*) > 1')
+
+ ids_to_delete = []
+
+ query.to_a.each do |record|
+ # We want to keep the latest finding since it might have recent metadata
+ duplicate_ids = record.ids.uniq.sort
+ duplicate_ids.pop
+ ids_to_delete.concat(duplicate_ids)
+
+ if ids_to_delete.size == DELETE_BATCH_SIZE
+ VulnerabilitiesFinding.where(id: ids_to_delete).delete_all
+ ids_to_delete.clear
+ end
+ end
+
+ VulnerabilitiesFinding.where(id: ids_to_delete).delete_all if ids_to_delete.any?
+ end
+end
diff --git a/lib/gitlab/background_migration/user_mentions/models/namespace.rb b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
index 6d7b9a86e69..8fa0db5fd4b 100644
--- a/lib/gitlab/background_migration/user_mentions/models/namespace.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
@@ -6,6 +6,7 @@ module Gitlab
module Models
# isolated Namespace model
class Namespace < ApplicationRecord
+ include FeatureGate
include ::Gitlab::VisibilityLevel
include ::Gitlab::Utils::StrongMemoize
include Gitlab::BackgroundMigration::UserMentions::Models::Concerns::Namespace::RecursiveTraversal
diff --git a/lib/gitlab/badge/base.rb b/lib/gitlab/badge/base.rb
deleted file mode 100644
index fb55b9e2f1f..00000000000
--- a/lib/gitlab/badge/base.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- class Base
- def entity
- raise NotImplementedError
- end
-
- def status
- raise NotImplementedError
- end
-
- def metadata
- raise NotImplementedError
- end
-
- def template
- raise NotImplementedError
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/coverage/metadata.rb b/lib/gitlab/badge/coverage/metadata.rb
deleted file mode 100644
index 9181ba2d4b0..00000000000
--- a/lib/gitlab/badge/coverage/metadata.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- module Coverage
- ##
- # Class that describes coverage badge metadata
- #
- class Metadata < Badge::Metadata
- def initialize(badge)
- @project = badge.project
- @ref = badge.ref
- @job = badge.job
- end
-
- def title
- 'coverage report'
- end
-
- def image_url
- coverage_project_badges_url(@project, @ref, format: :svg)
- end
-
- def link_url
- project_commits_url(@project, @ref)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
deleted file mode 100644
index 390da014a5a..00000000000
--- a/lib/gitlab/badge/coverage/report.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- module Coverage
- ##
- # Test coverage report badge
- #
- class Report < Badge::Base
- attr_reader :project, :ref, :job, :customization
-
- def initialize(project, ref, opts: { job: nil })
- @project = project
- @ref = ref
- @job = opts[:job]
- @customization = {
- key_width: opts[:key_width].to_i,
- key_text: opts[:key_text]
- }
- end
-
- def entity
- 'coverage'
- end
-
- def status
- @coverage ||= raw_coverage
- return unless @coverage
-
- @coverage.to_f.round(2)
- end
-
- def metadata
- @metadata ||= Coverage::Metadata.new(self)
- end
-
- def template
- @template ||= Coverage::Template.new(self)
- end
-
- private
-
- def successful_pipeline
- @successful_pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref)
- end
-
- def failed_pipeline
- @failed_pipeline ||= @project.ci_pipelines.latest_failed_for_ref(@ref)
- end
-
- def running_pipeline
- @running_pipeline ||= @project.ci_pipelines.latest_running_for_ref(@ref)
- end
-
- def raw_coverage
- latest =
- if @job.present?
- builds = ::Ci::Build
- .in_pipelines([successful_pipeline, running_pipeline, failed_pipeline])
- .latest
- .success
- .for_ref(@ref)
- .by_name(@job)
-
- builds.max_by(&:created_at)
- else
- successful_pipeline
- end
-
- latest&.coverage
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/coverage/template.rb b/lib/gitlab/badge/coverage/template.rb
deleted file mode 100644
index 1b985f83b22..00000000000
--- a/lib/gitlab/badge/coverage/template.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- module Coverage
- ##
- # Class that represents a coverage badge template.
- #
- # Template object will be passed to badge.svg.erb template.
- #
- class Template < Badge::Template
- STATUS_COLOR = {
- good: '#4c1',
- acceptable: '#a3c51c',
- medium: '#dfb317',
- low: '#e05d44',
- unknown: '#9f9f9f'
- }.freeze
-
- def initialize(badge)
- @entity = badge.entity
- @status = badge.status
- @key_text = badge.customization.dig(:key_text)
- @key_width = badge.customization.dig(:key_width)
- end
-
- def key_text
- if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
- @key_text
- else
- @entity.to_s
- end
- end
-
- def value_text
- @status ? ("%.2f%%" % @status) : 'unknown'
- end
-
- def key_width
- if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
- @key_width
- else
- 62
- end
- end
-
- def value_width
- @status ? 54 : 58
- end
-
- def value_color
- case @status
- when 95..100 then STATUS_COLOR[:good]
- when 90..95 then STATUS_COLOR[:acceptable]
- when 75..90 then STATUS_COLOR[:medium]
- when 0..75 then STATUS_COLOR[:low]
- else
- STATUS_COLOR[:unknown]
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/metadata.rb b/lib/gitlab/badge/metadata.rb
deleted file mode 100644
index b9ae68134b0..00000000000
--- a/lib/gitlab/badge/metadata.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- ##
- # Abstract class for badge metadata
- #
- class Metadata
- include Gitlab::Routing
- include ActionView::Helpers::AssetTagHelper
- include ActionView::Helpers::UrlHelper
-
- def initialize(badge)
- @badge = badge
- end
-
- def to_html
- link_to(image_tag(image_url, alt: title), link_url)
- end
-
- def to_markdown
- "[![#{title}](#{image_url})](#{link_url})"
- end
-
- def to_asciidoc
- "image:#{image_url}[link=\"#{link_url}\",title=\"#{title}\"]"
- end
-
- def title
- raise NotImplementedError
- end
-
- def image_url
- raise NotImplementedError
- end
-
- def link_url
- raise NotImplementedError
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/pipeline/metadata.rb b/lib/gitlab/badge/pipeline/metadata.rb
deleted file mode 100644
index d4d789558c9..00000000000
--- a/lib/gitlab/badge/pipeline/metadata.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- module Pipeline
- ##
- # Class that describes pipeline badge metadata
- #
- class Metadata < Badge::Metadata
- def initialize(badge)
- @project = badge.project
- @ref = badge.ref
- end
-
- def title
- 'pipeline status'
- end
-
- def image_url
- pipeline_project_badges_url(@project, @ref, format: :svg)
- end
-
- def link_url
- project_commits_url(@project, id: @ref)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/pipeline/status.rb b/lib/gitlab/badge/pipeline/status.rb
deleted file mode 100644
index f061ba22688..00000000000
--- a/lib/gitlab/badge/pipeline/status.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- module Pipeline
- ##
- # Pipeline status badge
- #
- class Status < Badge::Base
- attr_reader :project, :ref, :customization
-
- def initialize(project, ref, opts: {})
- @project = project
- @ref = ref
- @ignore_skipped = Gitlab::Utils.to_boolean(opts[:ignore_skipped], default: false)
- @customization = {
- key_width: opts[:key_width].to_i,
- key_text: opts[:key_text]
- }
-
- @sha = @project.commit(@ref).try(:sha)
- end
-
- def entity
- 'pipeline'
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def status
- pipelines = @project.ci_pipelines
- .where(sha: @sha)
-
- relation = @ignore_skipped ? pipelines.without_statuses([:skipped]) : pipelines
- relation.latest_status(@ref) || 'unknown'
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def metadata
- @metadata ||= Pipeline::Metadata.new(self)
- end
-
- def template
- @template ||= Pipeline::Template.new(self)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/pipeline/template.rb b/lib/gitlab/badge/pipeline/template.rb
deleted file mode 100644
index af8e318395b..00000000000
--- a/lib/gitlab/badge/pipeline/template.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- module Pipeline
- ##
- # Class that represents a pipeline badge template.
- #
- # Template object will be passed to badge.svg.erb template.
- #
- class Template < Badge::Template
- STATUS_RENAME = { 'success' => 'passed' }.freeze
- STATUS_COLOR = {
- success: '#4c1',
- failed: '#e05d44',
- running: '#dfb317',
- pending: '#dfb317',
- preparing: '#a7a7a7',
- canceled: '#9f9f9f',
- skipped: '#9f9f9f',
- unknown: '#9f9f9f'
- }.freeze
-
- def initialize(badge)
- @entity = badge.entity
- @status = badge.status
- @key_text = badge.customization.dig(:key_text)
- @key_width = badge.customization.dig(:key_width)
- end
-
- def key_text
- if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
- @key_text
- else
- @entity.to_s
- end
- end
-
- def value_text
- STATUS_RENAME[@status.to_s] || @status.to_s
- end
-
- def key_width
- if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
- @key_width
- else
- 62
- end
- end
-
- def value_width
- 54
- end
-
- def value_color
- STATUS_COLOR[@status.to_sym] || STATUS_COLOR[:unknown]
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/badge/template.rb b/lib/gitlab/badge/template.rb
deleted file mode 100644
index 9ac8f1c17f2..00000000000
--- a/lib/gitlab/badge/template.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Badge
- ##
- # Abstract template class for badges
- #
- class Template
- MAX_KEY_TEXT_SIZE = 64
- MAX_KEY_WIDTH = 512
-
- def initialize(badge)
- @entity = badge.entity
- @status = badge.status
- end
-
- def key_text
- raise NotImplementedError
- end
-
- def value_text
- raise NotImplementedError
- end
-
- def key_width
- raise NotImplementedError
- end
-
- def value_width
- raise NotImplementedError
- end
-
- def value_color
- raise NotImplementedError
- end
-
- def key_color
- '#555'
- end
-
- def key_text_anchor
- key_width / 2
- end
-
- def value_text_anchor
- key_width + (value_width / 2)
- end
-
- def width
- key_width + value_width
- end
- end
- end
-end
diff --git a/lib/gitlab/changelog/ast.rb b/lib/gitlab/changelog/ast.rb
new file mode 100644
index 00000000000..2c787d396f5
--- /dev/null
+++ b/lib/gitlab/changelog/ast.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # AST nodes to evaluate when rendering a template.
+ #
+ # Evaluating an AST is done by walking over the nodes and calling
+ # `evaluate`. This method takes two arguments:
+ #
+ # 1. An instance of `EvalState`, used for tracking data such as the number
+ # of nested loops.
+ # 2. An object used as the data for the current scope. This can be an Array,
+ # Hash, String, or something else. It's up to the AST node to determine
+ # what to do with it.
+ #
+ # While tree walking interpreters (such as implemented here) aren't usually
+ # the fastest type of interpreter, they are:
+ #
+ # 1. Fast enough for our use case
+ # 2. Easy to implement and maintain
+ #
+ # In addition, our AST interpreter doesn't allow for arbitrary code
+ # execution, unlike existing template engines such as Mustache
+ # (https://github.com/mustache/mustache/issues/244) or ERB.
+ #
+ # Our interpreter also takes care of limiting the number of nested loops.
+ # And unlike Liquid, our interpreter is much smaller and thus has a smaller
+ # attack surface. Liquid isn't without its share of issues, such as
+ # https://github.com/Shopify/liquid/pull/1071.
+ #
+ # We also evaluated using Handlebars using the project
+ # https://github.com/SmartBear/ruby-handlebars. Sadly, this implementation
+ # of Handlebars doesn't support control of whitespace
+ # (https://github.com/SmartBear/ruby-handlebars/issues/37), and the project
+ # didn't appear to be maintained that much.
+ #
+ # This doesn't mean these template engines aren't good, instead it means
+ # they won't work for our use case. For more information, refer to the
+ # comment https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50063#note_469293322.
+ module AST
+ # An identifier in a selector.
+ Identifier = Struct.new(:name) do
+ def evaluate(state, data)
+ return data if name == 'it'
+
+ data[name] if data.is_a?(Hash)
+ end
+ end
+
+ # An integer used in a selector.
+ Integer = Struct.new(:value) do
+ def evaluate(state, data)
+ data[value] if data.is_a?(Array)
+ end
+ end
+
+ # A selector used for loading a value.
+ Selector = Struct.new(:steps) do
+ def evaluate(state, data)
+ steps.reduce(data) do |current, step|
+ break if current.nil?
+
+ step.evaluate(state, current)
+ end
+ end
+ end
+
+ # A tag used for displaying a value in the output.
+ Variable = Struct.new(:selector) do
+ def evaluate(state, data)
+ selector.evaluate(state, data).to_s
+ end
+ end
+
+ # A collection of zero or more expressions.
+ Expressions = Struct.new(:nodes) do
+ def evaluate(state, data)
+ nodes.map { |node| node.evaluate(state, data) }.join('')
+ end
+ end
+
+ # A single text node.
+ Text = Struct.new(:text) do
+ def evaluate(*)
+ text
+ end
+ end
+
+ # An `if` expression, with an optional `else` clause.
+ If = Struct.new(:condition, :true_body, :false_body) do
+ def evaluate(state, data)
+ result =
+ if truthy?(condition.evaluate(state, data))
+ true_body.evaluate(state, data)
+ elsif false_body
+ false_body.evaluate(state, data)
+ end
+
+ result.to_s
+ end
+
+ def truthy?(value)
+ # We treat empty collections and such as false, removing the need for
+ # some sort of `if length(x) > 0` expression.
+ value.respond_to?(:empty?) ? !value.empty? : !!value
+ end
+ end
+
+ # An `each` expression.
+ Each = Struct.new(:collection, :body) do
+ def evaluate(state, data)
+ values = collection.evaluate(state, data)
+
+ return '' unless values.respond_to?(:each)
+
+ # While unlikely to happen, it's possible users attempt to nest many
+ # loops in order to negatively impact the GitLab instance. To make
+ # this more difficult, we limit the number of nested loops a user can
+ # create.
+ state.enter_loop do
+ values.map { |value| body.evaluate(state, value) }.join('')
+ end
+ end
+ end
+
+ # A class for transforming a raw Parslet AST into a more structured/easier
+ # to work with AST.
+ #
+ # For more information about Parslet transformations, refer to the
+ # documentation at http://kschiess.github.io/parslet/transform.html.
+ class Transformer < Parslet::Transform
+ rule(ident: simple(:name)) { Identifier.new(name.to_s) }
+ rule(int: simple(:name)) { Integer.new(name.to_i) }
+ rule(text: simple(:text)) { Text.new(text.to_s) }
+ rule(exprs: subtree(:nodes)) { Expressions.new(nodes) }
+ rule(selector: sequence(:steps)) { Selector.new(steps) }
+ rule(selector: simple(:step)) { Selector.new([step]) }
+ rule(variable: simple(:selector)) { Variable.new(selector) }
+ rule(each: simple(:values), body: simple(:body)) do
+ Each.new(values, body)
+ end
+
+ rule(if: simple(:cond), true_body: simple(:true_body)) do
+ If.new(cond, true_body)
+ end
+
+ rule(
+ if: simple(:cond),
+ true_body: simple(:true_body),
+ false_body: simple(:false_body)
+ ) do
+ If.new(cond, true_body, false_body)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/committer.rb b/lib/gitlab/changelog/committer.rb
new file mode 100644
index 00000000000..31661650eff
--- /dev/null
+++ b/lib/gitlab/changelog/committer.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # A class used for committing a release's changelog to a Git repository.
+ class Committer
+ def initialize(project, user)
+ @project = project
+ @user = user
+ end
+
+ # Commits a release's changelog to a file on a branch.
+ #
+ # The `release` argument is a `Gitlab::Changelog::Release` for which to
+ # update the changelog.
+ #
+ # The `file` argument specifies the path to commit the changes to.
+ #
+ # The `branch` argument specifies the branch to commit the changes on.
+ #
+ # The `message` argument specifies the commit message to use.
+ def commit(release:, file:, branch:, message:)
+ # When retrying, we need to reprocess the existing changelog from
+ # scratch, otherwise we may end up throwing away changes. As such, all
+ # the logic is contained within the retry block.
+ Retriable.retriable(on: Error) do
+ commit = Gitlab::Git::Commit.last_for_path(
+ @project.repository,
+ branch,
+ file,
+ literal_pathspec: true
+ )
+
+ content = blob_content(file, commit)
+
+ # If the release has already been added (e.g. concurrently by another
+ # API call), we don't want to add it again.
+ break if content&.match?(release.header_start_pattern)
+
+ service = Files::MultiService.new(
+ @project,
+ @user,
+ commit_message: message,
+ branch_name: branch,
+ start_branch: branch,
+ actions: [
+ {
+ action: content ? 'update' : 'create',
+ content: Generator.new(content.to_s).add(release),
+ file_path: file,
+ last_commit_id: commit&.sha
+ }
+ ]
+ )
+
+ result = service.execute
+
+ raise Error.new(result[:message]) if result[:status] != :success
+ end
+ end
+
+ def blob_content(file, commit = nil)
+ return unless commit
+
+ @project.repository.blob_at(commit.sha, file)&.data
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/config.rb b/lib/gitlab/changelog/config.rb
new file mode 100644
index 00000000000..105050936ce
--- /dev/null
+++ b/lib/gitlab/changelog/config.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # Configuration settings used when generating changelogs.
+ class Config
+ # When rendering changelog entries, authors are not included.
+ AUTHORS_NONE = 'none'
+
+ # The path to the configuration file as stored in the project's Git
+ # repository.
+ FILE_PATH = '.gitlab/changelog_config.yml'
+
+ # The default date format to use for formatting release dates.
+ DEFAULT_DATE_FORMAT = '%Y-%m-%d'
+
+ # The default template to use for generating release sections.
+ DEFAULT_TEMPLATE = File.read(File.join(__dir__, 'template.tpl'))
+
+ attr_accessor :date_format, :categories, :template
+
+ def self.from_git(project)
+ if (yaml = project.repository.changelog_config)
+ from_hash(project, YAML.safe_load(yaml))
+ else
+ new(project)
+ end
+ end
+
+ def self.from_hash(project, hash)
+ config = new(project)
+
+ if (date = hash['date_format'])
+ config.date_format = date
+ end
+
+ if (template = hash['template'])
+ config.template = Parser.new.parse_and_transform(template)
+ end
+
+ if (categories = hash['categories'])
+ if categories.is_a?(Hash)
+ config.categories = categories
+ else
+ raise Error, 'The "categories" configuration key must be a Hash'
+ end
+ end
+
+ config
+ end
+
+ def initialize(project)
+ @project = project
+ @date_format = DEFAULT_DATE_FORMAT
+ @template = Parser.new.parse_and_transform(DEFAULT_TEMPLATE)
+ @categories = {}
+ end
+
+ def contributor?(user)
+ @project.team.contributor?(user)
+ end
+
+ def category(name)
+ @categories[name] || name
+ end
+
+ def format_date(date)
+ date.strftime(@date_format)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/error.rb b/lib/gitlab/changelog/error.rb
new file mode 100644
index 00000000000..0bd886fbdb7
--- /dev/null
+++ b/lib/gitlab/changelog/error.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # An error raised when a changelog couldn't be generated.
+ Error = Class.new(StandardError)
+ end
+end
diff --git a/lib/gitlab/changelog/eval_state.rb b/lib/gitlab/changelog/eval_state.rb
new file mode 100644
index 00000000000..a0439df60cf
--- /dev/null
+++ b/lib/gitlab/changelog/eval_state.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # A class for tracking state when evaluating a template
+ class EvalState
+ MAX_LOOPS = 4
+
+ def initialize
+ @loops = 0
+ end
+
+ def enter_loop
+ if @loops == MAX_LOOPS
+ raise Error, "You can only nest up to #{MAX_LOOPS} loops"
+ end
+
+ @loops += 1
+ retval = yield
+ @loops -= 1
+
+ retval
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/generator.rb b/lib/gitlab/changelog/generator.rb
new file mode 100644
index 00000000000..a80ca0728f9
--- /dev/null
+++ b/lib/gitlab/changelog/generator.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # Parsing and generating of Markdown changelogs.
+ class Generator
+ # The regex used to parse a release header.
+ RELEASE_REGEX =
+ /^##\s+(?<version>#{Gitlab::Regex.unbounded_semver_regex})/.freeze
+
+ # The `input` argument must be a `String` containing the existing
+ # changelog Markdown. If no changelog exists, this should be an empty
+ # `String`.
+ def initialize(input = '')
+ @lines = input.lines
+ @locations = {}
+
+ @lines.each_with_index do |line, index|
+ matches = line.match(RELEASE_REGEX)
+
+ next if !matches || !matches[:version]
+
+ @locations[matches[:version]] = index
+ end
+ end
+
+ # Generates the Markdown for the given release and returns the new
+ # changelog Markdown content.
+ #
+ # The `release` argument must be an instance of
+ # `Gitlab::Changelog::Release`.
+ def add(release)
+ versions = [release.version, *@locations.keys]
+
+ VersionSorter.rsort!(versions)
+
+ new_index = versions.index(release.version)
+ new_lines = @lines.dup
+ markdown = release.to_markdown
+
+ if (insert_after = versions[new_index + 1])
+ line_index = @locations[insert_after]
+
+ new_lines.insert(line_index, markdown)
+ else
+ # When adding to the end of the changelog, the previous section only
+ # has a single newline, resulting in the release section title
+ # following it immediately. When this is the case, we insert an extra
+ # empty line to keep the changelog readable in its raw form.
+ new_lines.push("\n") if versions.length > 1
+ new_lines.push(markdown.rstrip)
+ new_lines.push("\n")
+ end
+
+ new_lines.join
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/parser.rb b/lib/gitlab/changelog/parser.rb
new file mode 100644
index 00000000000..a4c8da283cd
--- /dev/null
+++ b/lib/gitlab/changelog/parser.rb
@@ -0,0 +1,176 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # A parser for the template syntax used for generating changelogs.
+ #
+ # As a quick primer on the template syntax, a basic template looks like
+ # this:
+ #
+ # {% each users %}
+ # Name: {{name}}
+ # Age: {{age}}
+ #
+ # {% if birthday %}
+ # This user is celebrating their birthday today! Yay!
+ # {% end %}
+ # {% end %}
+ #
+ # For more information, refer to the Parslet documentation found at
+ # http://kschiess.github.io/parslet/.
+ class Parser < Parslet::Parser
+ root(:exprs)
+
+ rule(:exprs) do
+ (
+ variable | if_expr | each_expr | escaped | text | newline
+ ).repeat.as(:exprs)
+ end
+
+ rule(:space) { match('[ \\t]') }
+ rule(:whitespace) { match('\s').repeat }
+ rule(:lf) { str("\n") }
+ rule(:newline) { lf.as(:text) }
+
+ # Escaped newlines are ignored, allowing the user to control the
+ # whitespace in the output. All other escape sequences are treated as
+ # literal text.
+ #
+ # For example, this:
+ #
+ # foo \
+ # bar
+ #
+ # Is parsed into this:
+ #
+ # foo bar
+ rule(:escaped) do
+ backslash = str('\\')
+
+ (backslash >> lf).ignore | (backslash >> chars).as(:text)
+ end
+
+ # A sequence of regular characters, with the exception of newlines and
+ # escaped newlines.
+ rule(:chars) do
+ char = match("[^{\\\\\n]")
+
+ # The rules here are such that we do treat single curly braces or
+ # non-opening tags (e.g. `{foo}`) as text, but not opening tags
+ # themselves (e.g. `{{`).
+ (
+ char.repeat(1) | curly_open >> (curly_open | percent).absent?
+ ).repeat(1)
+ end
+
+ rule(:text) { chars.as(:text) }
+
+ # An integer, limited to 10 digits (= a 32 bits integer).
+ #
+ # The size is limited to prevents users from creating integers that are
+ # too large, as this may result in runtime errors.
+ rule(:integer) { match('\d').repeat(1, 10).as(:int) }
+
+ # An identifier to look up in a data structure.
+ #
+ # We only support simple ASCII identifiers as we simply don't have a need
+ # for more complex identifiers (e.g. those containing multibyte
+ # characters).
+ rule(:ident) { match('[a-zA-Z_]').repeat(1).as(:ident) }
+
+ # A selector is used for reading a value, consisting of one or more
+ # "steps".
+ #
+ # Examples:
+ #
+ # name
+ # users.0.name
+ # 0
+ # it
+ rule(:selector) do
+ step = ident | integer
+
+ whitespace >>
+ (step >> (str('.') >> step).repeat).as(:selector) >>
+ whitespace
+ end
+
+ rule(:curly_open) { str('{') }
+ rule(:curly_close) { str('}') }
+ rule(:percent) { str('%') }
+
+ # A variable tag.
+ #
+ # Examples:
+ #
+ # {{name}}
+ # {{users.0.name}}
+ rule(:variable) do
+ curly_open.repeat(2) >> selector.as(:variable) >> curly_close.repeat(2)
+ end
+
+ rule(:expr_open) { curly_open >> percent >> whitespace }
+ rule(:expr_close) do
+ # Since whitespace control is important (as Markdown is whitespace
+ # sensitive), we default to stripping a newline that follows a %} tag.
+ # This is less annoying compared to having to opt-in to this behaviour.
+ whitespace >> percent >> curly_close >> lf.maybe.ignore
+ end
+
+ rule(:end_tag) { expr_open >> str('end') >> expr_close }
+
+ # An `if` expression, with an optional `else` clause.
+ #
+ # Examples:
+ #
+ # {% if foo %}
+ # yes
+ # {% end %}
+ #
+ # {% if foo %}
+ # yes
+ # {% else %}
+ # no
+ # {% end %}
+ rule(:if_expr) do
+ else_tag =
+ expr_open >> str('else') >> expr_close >> exprs.as(:false_body)
+
+ expr_open >>
+ str('if') >>
+ space.repeat(1) >>
+ selector.as(:if) >>
+ expr_close >>
+ exprs.as(:true_body) >>
+ else_tag.maybe >>
+ end_tag
+ end
+
+ # An `each` expression, used for iterating over collections.
+ #
+ # Example:
+ #
+ # {% each users %}
+ # * {{name}}
+ # {% end %}
+ rule(:each_expr) do
+ expr_open >>
+ str('each') >>
+ space.repeat(1) >>
+ selector.as(:each) >>
+ expr_close >>
+ exprs.as(:body) >>
+ end_tag
+ end
+
+ def parse_and_transform(input)
+ AST::Transformer.new.apply(parse(input))
+ rescue Parslet::ParseFailed => ex
+ # We raise a custom error so it's easier to catch different changelog
+ # related errors. In addition, this ensures the caller of this method
+ # doesn't depend on a Parslet specific error class.
+ raise Error.new("Failed to parse the template: #{ex.message}")
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/release.rb b/lib/gitlab/changelog/release.rb
new file mode 100644
index 00000000000..f2a01c2b0dc
--- /dev/null
+++ b/lib/gitlab/changelog/release.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Changelog
+ # A release to add to a changelog.
+ class Release
+ attr_reader :version
+
+ def initialize(version:, date:, config:)
+ @version = version
+ @date = date
+ @config = config
+ @entries = Hash.new { |h, k| h[k] = [] }
+
+ # This ensures that entries are presented in the same order as the
+ # categories Hash in the user's configuration.
+ @config.categories.values.each do |category|
+ @entries[category] = []
+ end
+ end
+
+ def add_entry(
+ title:,
+ commit:,
+ category:,
+ author: nil,
+ merge_request: nil
+ )
+ # When changing these fields, keep in mind that this needs to be
+ # backwards compatible. For example, you can't just remove a field as
+ # this will break the changelog generation process for existing users.
+ entry = {
+ 'title' => title,
+ 'commit' => {
+ 'reference' => commit.to_reference(full: true),
+ 'trailers' => commit.trailers
+ }
+ }
+
+ if author
+ entry['author'] = {
+ 'reference' => author.to_reference(full: true),
+ 'contributor' => @config.contributor?(author)
+ }
+ end
+
+ if merge_request
+ entry['merge_request'] = {
+ 'reference' => merge_request.to_reference(full: true)
+ }
+ end
+
+ @entries[@config.category(category)] << entry
+ end
+
+ def to_markdown
+ state = EvalState.new
+ data = { 'categories' => entries_for_template }
+
+ # While not critical, we would like release sections to be separated by
+ # an empty line in the changelog; ensuring it's readable even in its
+ # raw form.
+ #
+ # Since it can be a bit tricky to get this right in a template, we
+ # enforce an empty line separator ourselves.
+ markdown = @config.template.evaluate(state, data).strip
+
+ # The release header can't be changed using the Liquid template, as we
+ # need this to be in a known format. Without this restriction, we won't
+ # know where to insert a new release section in an existing changelog.
+ "## #{@version} (#{release_date})\n\n#{markdown}\n\n"
+ end
+
+ def header_start_pattern
+ /^##\s*#{Regexp.escape(@version)}/
+ end
+
+ private
+
+ def release_date
+ @config.format_date(@date)
+ end
+
+ def entries_for_template
+ rows = []
+
+ @entries.each do |category, entries|
+ next if entries.empty?
+
+ rows << {
+ 'title' => category,
+ 'count' => entries.length,
+ 'single_change' => entries.length == 1,
+ 'entries' => entries
+ }
+ end
+
+ rows
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/changelog/template.tpl b/lib/gitlab/changelog/template.tpl
new file mode 100644
index 00000000000..584939dff51
--- /dev/null
+++ b/lib/gitlab/changelog/template.tpl
@@ -0,0 +1,15 @@
+{% if categories %}
+{% each categories %}
+### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})
+
+{% each entries %}
+- [{{ title }}]({{ commit.reference }})\
+{% if author.contributor %} by {{ author.reference }}{% end %}\
+{% if merge_request %} ([merge request]({{ merge_request.reference }})){% end %}
+
+{% end %}
+
+{% end %}
+{% else %}
+No changes.
+{% end %}
diff --git a/lib/gitlab/chaos.rb b/lib/gitlab/chaos.rb
index 911f2993b8a..029a9210dc9 100644
--- a/lib/gitlab/chaos.rb
+++ b/lib/gitlab/chaos.rb
@@ -47,5 +47,13 @@ module Gitlab
def self.kill
Process.kill("KILL", Process.pid)
end
+
+ def self.run_gc
+ # Tenure any live objects from young-gen to old-gen
+ 4.times { GC.start(full_mark: false) }
+ # Run a full mark-and-sweep collection
+ GC.start
+ GC.stat
+ end
end
end
diff --git a/lib/gitlab/ci/badge/base.rb b/lib/gitlab/ci/badge/base.rb
new file mode 100644
index 00000000000..c65f120753d
--- /dev/null
+++ b/lib/gitlab/ci/badge/base.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ class Base
+ def entity
+ raise NotImplementedError
+ end
+
+ def status
+ raise NotImplementedError
+ end
+
+ def metadata
+ raise NotImplementedError
+ end
+
+ def template
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/coverage/metadata.rb b/lib/gitlab/ci/badge/coverage/metadata.rb
new file mode 100644
index 00000000000..7654b6d6fc5
--- /dev/null
+++ b/lib/gitlab/ci/badge/coverage/metadata.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Coverage
+ ##
+ # Class that describes coverage badge metadata
+ #
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ @ref = badge.ref
+ @job = badge.job
+ end
+
+ def title
+ 'coverage report'
+ end
+
+ def image_url
+ coverage_project_badges_url(@project, @ref, format: :svg)
+ end
+
+ def link_url
+ project_commits_url(@project, @ref)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/coverage/report.rb b/lib/gitlab/ci/badge/coverage/report.rb
new file mode 100644
index 00000000000..28863a0703b
--- /dev/null
+++ b/lib/gitlab/ci/badge/coverage/report.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Coverage
+ ##
+ # Test coverage report badge
+ #
+ class Report < Badge::Base
+ attr_reader :project, :ref, :job, :customization
+
+ def initialize(project, ref, opts: { job: nil })
+ @project = project
+ @ref = ref
+ @job = opts[:job]
+ @customization = {
+ key_width: opts[:key_width].to_i,
+ key_text: opts[:key_text]
+ }
+ end
+
+ def entity
+ 'coverage'
+ end
+
+ def status
+ @coverage ||= raw_coverage
+ return unless @coverage
+
+ @coverage.to_f.round(2)
+ end
+
+ def metadata
+ @metadata ||= Coverage::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Coverage::Template.new(self)
+ end
+
+ private
+
+ def successful_pipeline
+ @successful_pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref)
+ end
+
+ def failed_pipeline
+ @failed_pipeline ||= @project.ci_pipelines.latest_failed_for_ref(@ref)
+ end
+
+ def running_pipeline
+ @running_pipeline ||= @project.ci_pipelines.latest_running_for_ref(@ref)
+ end
+
+ def raw_coverage
+ latest =
+ if @job.present?
+ builds = ::Ci::Build
+ .in_pipelines([successful_pipeline, running_pipeline, failed_pipeline])
+ .latest
+ .success
+ .for_ref(@ref)
+ .by_name(@job)
+
+ builds.max_by(&:created_at)
+ else
+ successful_pipeline
+ end
+
+ latest&.coverage
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/coverage/template.rb b/lib/gitlab/ci/badge/coverage/template.rb
new file mode 100644
index 00000000000..7589fa5ff8b
--- /dev/null
+++ b/lib/gitlab/ci/badge/coverage/template.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Coverage
+ ##
+ # Class that represents a coverage badge template.
+ #
+ # Template object will be passed to badge.svg.erb template.
+ #
+ class Template < Badge::Template
+ STATUS_COLOR = {
+ good: '#4c1',
+ acceptable: '#a3c51c',
+ medium: '#dfb317',
+ low: '#e05d44',
+ unknown: '#9f9f9f'
+ }.freeze
+
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ @key_text = badge.customization.dig(:key_text)
+ @key_width = badge.customization.dig(:key_width)
+ end
+
+ def key_text
+ if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
+ @key_text
+ else
+ @entity.to_s
+ end
+ end
+
+ def value_text
+ @status ? ("%.2f%%" % @status) : 'unknown'
+ end
+
+ def key_width
+ if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
+ @key_width
+ else
+ 62
+ end
+ end
+
+ def value_width
+ @status ? 54 : 58
+ end
+
+ def value_color
+ case @status
+ when 95..100 then STATUS_COLOR[:good]
+ when 90..95 then STATUS_COLOR[:acceptable]
+ when 75..90 then STATUS_COLOR[:medium]
+ when 0..75 then STATUS_COLOR[:low]
+ else
+ STATUS_COLOR[:unknown]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/metadata.rb b/lib/gitlab/ci/badge/metadata.rb
new file mode 100644
index 00000000000..eec9fedfaa9
--- /dev/null
+++ b/lib/gitlab/ci/badge/metadata.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ ##
+ # Abstract class for badge metadata
+ #
+ class Metadata
+ include Gitlab::Routing
+ include ActionView::Helpers::AssetTagHelper
+ include ActionView::Helpers::UrlHelper
+
+ def initialize(badge)
+ @badge = badge
+ end
+
+ def to_html
+ link_to(image_tag(image_url, alt: title), link_url)
+ end
+
+ def to_markdown
+ "[![#{title}](#{image_url})](#{link_url})"
+ end
+
+ def to_asciidoc
+ "image:#{image_url}[link=\"#{link_url}\",title=\"#{title}\"]"
+ end
+
+ def title
+ raise NotImplementedError
+ end
+
+ def image_url
+ raise NotImplementedError
+ end
+
+ def link_url
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/pipeline/metadata.rb b/lib/gitlab/ci/badge/pipeline/metadata.rb
new file mode 100644
index 00000000000..2aa08476336
--- /dev/null
+++ b/lib/gitlab/ci/badge/pipeline/metadata.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Pipeline
+ ##
+ # Class that describes pipeline badge metadata
+ #
+ class Metadata < Badge::Metadata
+ def initialize(badge)
+ @project = badge.project
+ @ref = badge.ref
+ end
+
+ def title
+ 'pipeline status'
+ end
+
+ def image_url
+ pipeline_project_badges_url(@project, @ref, format: :svg)
+ end
+
+ def link_url
+ project_commits_url(@project, id: @ref)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/pipeline/status.rb b/lib/gitlab/ci/badge/pipeline/status.rb
new file mode 100644
index 00000000000..a2ee2642872
--- /dev/null
+++ b/lib/gitlab/ci/badge/pipeline/status.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Pipeline
+ ##
+ # Pipeline status badge
+ #
+ class Status < Badge::Base
+ attr_reader :project, :ref, :customization
+
+ def initialize(project, ref, opts: {})
+ @project = project
+ @ref = ref
+ @ignore_skipped = Gitlab::Utils.to_boolean(opts[:ignore_skipped], default: false)
+ @customization = {
+ key_width: opts[:key_width].to_i,
+ key_text: opts[:key_text]
+ }
+
+ @sha = @project.commit(@ref).try(:sha)
+ end
+
+ def entity
+ 'pipeline'
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def status
+ pipelines = @project.ci_pipelines
+ .where(sha: @sha)
+
+ relation = @ignore_skipped ? pipelines.without_statuses([:skipped]) : pipelines
+ relation.latest_status(@ref) || 'unknown'
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def metadata
+ @metadata ||= Pipeline::Metadata.new(self)
+ end
+
+ def template
+ @template ||= Pipeline::Template.new(self)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/pipeline/template.rb b/lib/gitlab/ci/badge/pipeline/template.rb
new file mode 100644
index 00000000000..8430b01fc9a
--- /dev/null
+++ b/lib/gitlab/ci/badge/pipeline/template.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ module Pipeline
+ ##
+ # Class that represents a pipeline badge template.
+ #
+ # Template object will be passed to badge.svg.erb template.
+ #
+ class Template < Badge::Template
+ STATUS_RENAME = { 'success' => 'passed' }.freeze
+ STATUS_COLOR = {
+ success: '#4c1',
+ failed: '#e05d44',
+ running: '#dfb317',
+ pending: '#dfb317',
+ preparing: '#a7a7a7',
+ canceled: '#9f9f9f',
+ skipped: '#9f9f9f',
+ unknown: '#9f9f9f'
+ }.freeze
+
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ @key_text = badge.customization.dig(:key_text)
+ @key_width = badge.customization.dig(:key_width)
+ end
+
+ def key_text
+ if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
+ @key_text
+ else
+ @entity.to_s
+ end
+ end
+
+ def value_text
+ STATUS_RENAME[@status.to_s] || @status.to_s
+ end
+
+ def key_width
+ if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
+ @key_width
+ else
+ 62
+ end
+ end
+
+ def value_width
+ 54
+ end
+
+ def value_color
+ STATUS_COLOR[@status.to_sym] || STATUS_COLOR[:unknown]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/badge/template.rb b/lib/gitlab/ci/badge/template.rb
new file mode 100644
index 00000000000..0580dad72ba
--- /dev/null
+++ b/lib/gitlab/ci/badge/template.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci
+ module Badge
+ ##
+ # Abstract template class for badges
+ #
+ class Template
+ MAX_KEY_TEXT_SIZE = 64
+ MAX_KEY_WIDTH = 512
+
+ def initialize(badge)
+ @entity = badge.entity
+ @status = badge.status
+ end
+
+ def key_text
+ raise NotImplementedError
+ end
+
+ def value_text
+ raise NotImplementedError
+ end
+
+ def key_width
+ raise NotImplementedError
+ end
+
+ def value_width
+ raise NotImplementedError
+ end
+
+ def value_color
+ raise NotImplementedError
+ end
+
+ def key_color
+ '#555'
+ end
+
+ def key_text_anchor
+ key_width / 2
+ end
+
+ def value_text_anchor
+ key_width + (value_width / 2)
+ end
+
+ def width
+ key_width + value_width
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/credentials/base.rb b/lib/gitlab/ci/build/credentials/base.rb
index 58adf6e506d..2aeb8453703 100644
--- a/lib/gitlab/ci/build/credentials/base.rb
+++ b/lib/gitlab/ci/build/credentials/base.rb
@@ -6,7 +6,7 @@ module Gitlab
module Credentials
class Base
def type
- self.class.name.demodulize.underscore
+ raise NotImplementedError
end
end
end
diff --git a/lib/gitlab/ci/build/credentials/factory.rb b/lib/gitlab/ci/build/credentials/factory.rb
index fa805abb8bb..e8996cb9dc4 100644
--- a/lib/gitlab/ci/build/credentials/factory.rb
+++ b/lib/gitlab/ci/build/credentials/factory.rb
@@ -20,7 +20,7 @@ module Gitlab
end
def providers
- [Registry]
+ [Registry::GitlabRegistry, Registry::DependencyProxy]
end
end
end
diff --git a/lib/gitlab/ci/build/credentials/registry.rb b/lib/gitlab/ci/build/credentials/registry.rb
deleted file mode 100644
index 1c8588d9913..00000000000
--- a/lib/gitlab/ci/build/credentials/registry.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Build
- module Credentials
- class Registry < Base
- attr_reader :username, :password
-
- def initialize(build)
- @username = 'gitlab-ci-token'
- @password = build.token
- end
-
- def url
- Gitlab.config.registry.host_port
- end
-
- def valid?
- Gitlab.config.registry.enabled
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/build/credentials/registry/dependency_proxy.rb b/lib/gitlab/ci/build/credentials/registry/dependency_proxy.rb
new file mode 100644
index 00000000000..b6ac06cfb53
--- /dev/null
+++ b/lib/gitlab/ci/build/credentials/registry/dependency_proxy.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Build
+ module Credentials
+ module Registry
+ class DependencyProxy < GitlabRegistry
+ def url
+ "#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}"
+ end
+
+ def valid?
+ Gitlab.config.dependency_proxy.enabled
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/credentials/registry/gitlab_registry.rb b/lib/gitlab/ci/build/credentials/registry/gitlab_registry.rb
new file mode 100644
index 00000000000..5bd30e677e9
--- /dev/null
+++ b/lib/gitlab/ci/build/credentials/registry/gitlab_registry.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Build
+ module Credentials
+ module Registry
+ class GitlabRegistry < Credentials::Base
+ attr_reader :username, :password
+
+ def initialize(build)
+ @username = Gitlab::Auth::CI_JOB_USER
+ @password = build.token
+ end
+
+ def url
+ Gitlab.config.registry.host_port
+ end
+
+ def valid?
+ Gitlab.config.registry.enabled
+ end
+
+ def type
+ 'registry'
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/rules.rb b/lib/gitlab/ci/build/rules.rb
index a39afee194c..2d4f9cf635b 100644
--- a/lib/gitlab/ci/build/rules.rb
+++ b/lib/gitlab/ci/build/rules.rb
@@ -7,30 +7,17 @@ module Gitlab
include ::Gitlab::Utils::StrongMemoize
Result = Struct.new(:when, :start_in, :allow_failure, :variables) do
- def build_attributes(seed_attributes = {})
+ def build_attributes
{
when: self.when,
options: { start_in: start_in }.compact,
- allow_failure: allow_failure,
- yaml_variables: yaml_variables(seed_attributes[:yaml_variables])
+ allow_failure: allow_failure
}.compact
end
def pass?
self.when != 'never'
end
-
- private
-
- def yaml_variables(seed_variables)
- return unless variables && seed_variables
-
- indexed_seed_variables = seed_variables.deep_dup.index_by { |var| var[:key] }
-
- variables.each_with_object(indexed_seed_variables) do |var, hash|
- hash[var[0].to_s] = { key: var[0].to_s, value: var[1], public: true }
- end.values
- end
end
def initialize(rule_hashes, default_when:)
diff --git a/lib/gitlab/ci/charts.rb b/lib/gitlab/ci/charts.rb
index 25fb9c0ca97..797193a6be5 100644
--- a/lib/gitlab/ci/charts.rb
+++ b/lib/gitlab/ci/charts.rb
@@ -31,9 +31,10 @@ module Gitlab
current = @from
while current <= @to
- @labels << current.strftime(@format)
- @total << (totals_count[current] || 0)
- @success << (success_count[current] || 0)
+ label = current.strftime(@format)
+ @labels << label
+ @total << (totals_count[label] || 0)
+ @success << (success_count[label] || 0)
current += interval_step
end
@@ -45,6 +46,7 @@ module Gitlab
query
.group("date_trunc('#{interval}', #{::Ci::Pipeline.table_name}.created_at)")
.count(:created_at)
+ .transform_keys { |date| date.strftime(@format) }
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 8ed4dc61920..dbb48a81030 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -13,7 +13,8 @@ module Gitlab
RESCUE_ERRORS = [
Gitlab::Config::Loader::FormatError,
Extendable::ExtensionError,
- External::Processor::IncludeError
+ External::Processor::IncludeError,
+ Config::Yaml::Tags::TagError
].freeze
attr_reader :root
@@ -89,9 +90,10 @@ module Gitlab
end
def build_config(config)
- initial_config = Gitlab::Config::Loader::Yaml.new(config).load!
+ initial_config = Config::Yaml.load!(config)
initial_config = Config::External::Processor.new(initial_config, @context).perform
initial_config = Config::Extendable.new(initial_config).to_hash
+ initial_config = Config::Yaml::Tags::Resolver.new(initial_config).to_hash
initial_config = Config::EdgeStagesInjector.new(initial_config).to_hash
initial_config
diff --git a/lib/gitlab/ci/config/entry/commands.rb b/lib/gitlab/ci/config/entry/commands.rb
index 7a86fca3056..341f87b44ab 100644
--- a/lib/gitlab/ci/config/entry/commands.rb
+++ b/lib/gitlab/ci/config/entry/commands.rb
@@ -10,12 +10,14 @@ module Gitlab
class Commands < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
+ MAX_NESTING_LEVEL = 10
+
validations do
- validates :config, string_or_nested_array_of_strings: true
+ validates :config, string_or_nested_array_of_strings: { max_level: MAX_NESTING_LEVEL }
end
def value
- Array(@config).flatten(1)
+ Array(@config).flatten(MAX_NESTING_LEVEL)
end
end
end
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 85e3514499c..a20b802be58 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -14,7 +14,7 @@ module Gitlab
ALLOWED_KEYS = %i[tags script type image services start_in artifacts
cache dependencies before_script after_script
environment coverage retry parallel interruptible timeout
- resource_group release secrets].freeze
+ release secrets].freeze
REQUIRED_BY_NEEDS = %i[stage].freeze
@@ -30,7 +30,6 @@ module Gitlab
}
validates :dependencies, array_of_strings: true
- validates :resource_group, type: String
validates :allow_failure, hash_or_boolean: true
end
@@ -124,7 +123,7 @@ module Gitlab
attributes :script, :tags, :when, :dependencies,
:needs, :retry, :parallel, :start_in,
- :interruptible, :timeout, :resource_group,
+ :interruptible, :timeout,
:release, :allow_failure
def self.matching?(name, config)
@@ -174,7 +173,6 @@ module Gitlab
ignore: ignored?,
allow_failure_criteria: allow_failure_criteria,
needs: needs_defined? ? needs_value : nil,
- resource_group: resource_group,
scheduling_type: needs_defined? ? :dag : :stage
).compact
end
@@ -186,8 +184,6 @@ module Gitlab
private
def allow_failure_criteria
- return unless ::Gitlab::Ci::Features.allow_failure_with_exit_codes_enabled?
-
if allow_failure_defined? && allow_failure_value.is_a?(Hash)
allow_failure_value
end
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 5ef8cfbddb7..9584d19bdec 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -15,7 +15,7 @@ module Gitlab
include ::Gitlab::Config::Entry::Inheritable
PROCESSABLE_ALLOWED_KEYS = %i[extends stage only except rules variables
- inherit allow_failure when needs].freeze
+ inherit allow_failure when needs resource_group].freeze
included do
validations do
@@ -32,6 +32,7 @@ module Gitlab
with_options allow_nil: true do
validates :extends, array_of_strings_or_string: true
validates :rules, array_of_hashes: true
+ validates :resource_group, type: String
end
end
@@ -64,7 +65,7 @@ module Gitlab
inherit: false,
default: {}
- attributes :extends, :rules
+ attributes :extends, :rules, :resource_group
end
def compose!(deps = nil)
@@ -125,7 +126,8 @@ module Gitlab
rules: rules_value,
variables: root_and_job_variables_value,
only: only_value,
- except: except_value }.compact
+ except: except_value,
+ resource_group: resource_group }.compact
end
def root_and_job_variables_value
diff --git a/lib/gitlab/ci/config/external/file/base.rb b/lib/gitlab/ci/config/external/file/base.rb
index 4684a9eb981..7d3fddd850d 100644
--- a/lib/gitlab/ci/config/external/file/base.rb
+++ b/lib/gitlab/ci/config/external/file/base.rb
@@ -60,7 +60,7 @@ module Gitlab
def content_hash
strong_memoize(:content_yaml) do
- Gitlab::Config::Loader::Yaml.new(content).load!
+ ::Gitlab::Ci::Config::Yaml.load!(content)
end
rescue Gitlab::Config::Loader::FormatError
nil
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index 4d91cfd4c57..b85b7a9edeb 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -99,8 +99,6 @@ module Gitlab
end
def expand_variables(data)
- return data unless ::Feature.enabled?(:variables_in_include_section_ci)
-
if data.is_a?(String)
expand(data)
else
diff --git a/lib/gitlab/ci/config/yaml.rb b/lib/gitlab/ci/config/yaml.rb
new file mode 100644
index 00000000000..de833619c8d
--- /dev/null
+++ b/lib/gitlab/ci/config/yaml.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Yaml
+ AVAILABLE_TAGS = [Config::Yaml::Tags::Reference].freeze
+
+ class << self
+ def load!(content)
+ ensure_custom_tags
+
+ Gitlab::Config::Loader::Yaml.new(content, additional_permitted_classes: AVAILABLE_TAGS).load!
+ end
+
+ private
+
+ def ensure_custom_tags
+ @ensure_custom_tags ||= begin
+ AVAILABLE_TAGS.each { |klass| Psych.add_tag(klass.tag, klass) }
+
+ true
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/yaml/tags.rb b/lib/gitlab/ci/config/yaml/tags.rb
new file mode 100644
index 00000000000..1575edad3b0
--- /dev/null
+++ b/lib/gitlab/ci/config/yaml/tags.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Yaml
+ module Tags
+ TagError = Class.new(StandardError)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/yaml/tags/base.rb b/lib/gitlab/ci/config/yaml/tags/base.rb
new file mode 100644
index 00000000000..13416a4afb6
--- /dev/null
+++ b/lib/gitlab/ci/config/yaml/tags/base.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Yaml
+ module Tags
+ class Base
+ CircularReferenceError = Class.new(Tags::TagError)
+ NotValidError = Class.new(Tags::TagError)
+
+ extend ::Gitlab::Utils::Override
+
+ attr_accessor :resolved_status, :resolved_value, :data
+
+ def self.tag
+ raise NotImplementedError
+ end
+
+ # Only one of the `seq`, `scalar`, `map` fields is available.
+ def init_with(coder)
+ @data = {
+ tag: coder.tag, # This is the custom YAML tag, like !reference or !flatten
+ style: coder.style,
+ seq: coder.seq, # This holds Array data
+ scalar: coder.scalar, # This holds data of basic types, like String.
+ map: coder.map # This holds Hash data.
+ }
+ end
+
+ def valid?
+ raise NotImplementedError
+ end
+
+ def resolve(resolver)
+ raise NotValidError, validation_error_message unless valid?
+ raise CircularReferenceError, circular_error_message if resolving?
+ return resolved_value if resolved?
+
+ self.resolved_status = :in_progress
+ self.resolved_value = _resolve(resolver)
+ self.resolved_status = :done
+ resolved_value
+ end
+
+ private
+
+ def _resolve(resolver)
+ raise NotImplementedError
+ end
+
+ def resolved?
+ resolved_status == :done
+ end
+
+ def resolving?
+ resolved_status == :in_progress
+ end
+
+ def circular_error_message
+ "#{data[:tag]} #{data[:seq].inspect} is part of a circular chain"
+ end
+
+ def validation_error_message
+ "#{data[:tag]} #{(data[:scalar].presence || data[:map].presence || data[:seq]).inspect} is not valid"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/yaml/tags/reference.rb b/lib/gitlab/ci/config/yaml/tags/reference.rb
new file mode 100644
index 00000000000..22822614b67
--- /dev/null
+++ b/lib/gitlab/ci/config/yaml/tags/reference.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Yaml
+ module Tags
+ class Reference < Base
+ MissingReferenceError = Class.new(Tags::TagError)
+
+ def self.tag
+ '!reference'
+ end
+
+ override :valid?
+ def valid?
+ data[:seq].is_a?(Array) &&
+ !data[:seq].empty? &&
+ data[:seq].all? { |identifier| identifier.is_a?(String) }
+ end
+
+ private
+
+ def location
+ data[:seq].to_a.map(&:to_sym)
+ end
+
+ override :_resolve
+ def _resolve(resolver)
+ object = resolver.config.dig(*location)
+ value = resolver.deep_resolve(object)
+
+ raise MissingReferenceError, missing_ref_error_message unless value
+
+ value
+ end
+
+ def missing_ref_error_message
+ "#{data[:tag]} #{data[:seq].inspect} could not be found"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/yaml/tags/resolver.rb b/lib/gitlab/ci/config/yaml/tags/resolver.rb
new file mode 100644
index 00000000000..e207ec296b6
--- /dev/null
+++ b/lib/gitlab/ci/config/yaml/tags/resolver.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Yaml
+ module Tags
+ # This class is the entry point for transforming custom YAML tags back
+ # into primitive objects.
+ # Usage: `Resolver.new(a_hash_including_custom_tag_objects).to_hash`
+ #
+ class Resolver
+ attr_reader :config
+
+ def initialize(config)
+ @config = config.deep_dup
+ end
+
+ def to_hash
+ deep_resolve(config)
+ end
+
+ def deep_resolve(object)
+ case object
+ when Array
+ object.map(&method(:resolve_wrapper))
+ when Hash
+ object.deep_transform_values(&method(:resolve_wrapper))
+ else
+ resolve_wrapper(object)
+ end
+ end
+
+ def resolve_wrapper(object)
+ if object.respond_to?(:resolve)
+ object.resolve(self)
+ else
+ object
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index 7956cf14203..d1a366125ef 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -55,21 +55,30 @@ module Gitlab
::Feature.enabled?(:ci_trace_log_invalid_chunks, project, type: :ops, default_enabled: false)
end
- def self.pipeline_open_merge_requests?(project)
- ::Feature.enabled?(:ci_pipeline_open_merge_requests, project, default_enabled: true)
- end
-
def self.ci_pipeline_editor_page_enabled?(project)
::Feature.enabled?(:ci_pipeline_editor_page, project, default_enabled: :yaml)
end
- def self.allow_failure_with_exit_codes_enabled?
- ::Feature.enabled?(:ci_allow_failure_with_exit_codes, default_enabled: :yaml)
- end
-
def self.rules_variables_enabled?(project)
::Feature.enabled?(:ci_rules_variables, project, default_enabled: true)
end
+
+ def self.validate_build_dependencies?(project)
+ ::Feature.enabled?(:ci_validate_build_dependencies, project, default_enabled: :yaml) &&
+ ::Feature.disabled?(:ci_validate_build_dependencies_override, project)
+ end
+
+ def self.display_quality_on_mr_diff?(project)
+ ::Feature.enabled?(:codequality_mr_diff, project, default_enabled: false)
+ end
+
+ def self.display_codequality_backend_comparison?(project)
+ ::Feature.enabled?(:codequality_backend_comparison, project, default_enabled: :yaml)
+ end
+
+ def self.use_coverage_data_new_finder?(record)
+ ::Feature.enabled?(:coverage_data_new_finder, record, default_enabled: :yaml)
+ end
end
end
end
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index a8943eadf4f..0870c74053a 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -45,7 +45,7 @@ module Gitlab
end
def custom_claims
- {
+ fields = {
namespace_id: namespace.id.to_s,
namespace_path: namespace.full_path,
project_id: project.id.to_s,
@@ -59,6 +59,15 @@ module Gitlab
ref_type: ref_type,
ref_protected: build.protected.to_s
}
+
+ if include_environment_claims?
+ fields.merge!(
+ environment: environment.name,
+ environment_protected: environment_protected?.to_s
+ )
+ end
+
+ fields
end
def key
@@ -102,6 +111,20 @@ module Gitlab
def ref_type
::Ci::BuildRunnerPresenter.new(build).ref_type
end
+
+ def environment
+ build.persisted_environment
+ end
+
+ def environment_protected?
+ false # Overridden in EE
+ end
+
+ def include_environment_claims?
+ Feature.enabled?(:ci_jwt_include_environment) && environment.present?
+ end
end
end
end
+
+Gitlab::Ci::Jwt.prepend_if_ee('::EE::Gitlab::Ci::Jwt')
diff --git a/lib/gitlab/ci/parsers.rb b/lib/gitlab/ci/parsers.rb
index 985639982aa..2baa8faf849 100644
--- a/lib/gitlab/ci/parsers.rb
+++ b/lib/gitlab/ci/parsers.rb
@@ -20,6 +20,10 @@ module Gitlab
rescue KeyError
raise ParserNotFoundError, "Cannot find any parser matching file type '#{file_type}'"
end
+
+ def self.instrument!
+ parsers.values.each { |parser_class| parser_class.prepend(Parsers::Instrumentation) }
+ end
end
end
end
diff --git a/lib/gitlab/ci/parsers/instrumentation.rb b/lib/gitlab/ci/parsers/instrumentation.rb
new file mode 100644
index 00000000000..ab4a923d9aa
--- /dev/null
+++ b/lib/gitlab/ci/parsers/instrumentation.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Instrumentation
+ BUCKETS = [0.25, 1, 5, 10].freeze
+
+ def parse!(*args)
+ parser_result = nil
+
+ duration = Benchmark.realtime do
+ parser_result = super
+ end
+
+ labels = {}
+
+ histogram = Gitlab::Metrics.histogram(
+ :ci_report_parser_duration_seconds,
+ 'Duration of parsing a CI report artifact',
+ labels,
+ BUCKETS
+ )
+
+ histogram.observe({ parser: self.class.name }, duration)
+
+ parser_result
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index f0548284001..d3bc3a38f1f 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -23,7 +23,7 @@ module Gitlab
pipeline_schedule: @command.schedule,
merge_request: @command.merge_request,
external_pull_request: @command.external_pull_request,
- locked: @command.project.latest_pipeline_locked,
+ locked: @command.project.default_pipeline_lock,
variables_attributes: variables_attributes
)
end
diff --git a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
index 2ca51930c19..f0214bb4e38 100644
--- a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
+++ b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
@@ -25,7 +25,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def auto_cancelable_pipelines
- pipelines
+ project.all_pipelines.ci_and_parent_sources
.where(ref: pipeline.ref)
.where.not(id: pipeline.same_family_pipeline_ids)
.where.not(sha: project.commit(pipeline.ref).try(:id))
@@ -33,14 +33,6 @@ module Gitlab
.with_only_interruptible_builds
end
# rubocop: enable CodeReuse/ActiveRecord
-
- def pipelines
- if ::Feature.enabled?(:ci_auto_cancel_all_pipelines, project, default_enabled: true)
- project.all_pipelines.ci_and_parent_sources
- else
- project.ci_pipelines
- end
- end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/config/content.rb b/lib/gitlab/ci/pipeline/chain/config/content.rb
index 5314fd471c3..a7680f6e593 100644
--- a/lib/gitlab/ci/pipeline/chain/config/content.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/content.rb
@@ -34,16 +34,22 @@ module Gitlab
private
def find_config
- SOURCES.each do |source|
+ sources.each do |source|
config = source.new(@pipeline, @command)
return config if config.exists?
end
nil
end
+
+ def sources
+ SOURCES
+ end
end
end
end
end
end
end
+
+Gitlab::Ci::Pipeline::Chain::Config::Content.prepend_if_ee('EE::Gitlab::Ci::Pipeline::Chain::Config::Content')
diff --git a/lib/gitlab/ci/pipeline/chain/template_usage.rb b/lib/gitlab/ci/pipeline/chain/template_usage.rb
index c1a7b4ed453..2fcf1740b5f 100644
--- a/lib/gitlab/ci/pipeline/chain/template_usage.rb
+++ b/lib/gitlab/ci/pipeline/chain/template_usage.rb
@@ -19,7 +19,7 @@ module Gitlab
def track_event(template)
Gitlab::UsageDataCounters::CiTemplateUniqueCounter
- .track_unique_project_event(project_id: pipeline.project_id, template: template)
+ .track_unique_project_event(project_id: pipeline.project_id, template: template, config_source: pipeline.config_source)
end
def included_templates
diff --git a/lib/gitlab/ci/pipeline/metrics.rb b/lib/gitlab/ci/pipeline/metrics.rb
index db6cca27f1c..c77f4dcca5a 100644
--- a/lib/gitlab/ci/pipeline/metrics.rb
+++ b/lib/gitlab/ci/pipeline/metrics.rb
@@ -45,6 +45,15 @@ module Gitlab
Gitlab::Metrics.counter(name, comment)
end
end
+
+ def legacy_update_jobs_counter
+ strong_memoize(:legacy_update_jobs_counter) do
+ name = :ci_legacy_update_jobs_as_retried_total
+ comment = 'Counter of occurrences when jobs were not being set as retried before update_retried'
+
+ Gitlab::Metrics.counter(name, comment)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index fe3c2bca551..3770bb4b328 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -73,17 +73,28 @@ module Gitlab
def to_resource
strong_memoize(:resource) do
- if bridge?
- ::Ci::Bridge.new(attributes)
- else
- ::Ci::Build.new(attributes).tap do |build|
- build.assign_attributes(self.class.environment_attributes_for(build))
- build.resource_group = Seed::Build::ResourceGroup.new(build, @resource_group_key).to_resource
- end
+ processable = initialize_processable
+ assign_resource_group(processable)
+ processable
+ end
+ end
+
+ def initialize_processable
+ if bridge?
+ ::Ci::Bridge.new(attributes)
+ else
+ ::Ci::Build.new(attributes).tap do |build|
+ build.assign_attributes(self.class.environment_attributes_for(build))
end
end
end
+ def assign_resource_group(processable)
+ processable.resource_group =
+ Seed::Processable::ResourceGroup.new(processable, @resource_group_key)
+ .to_resource
+ end
+
def self.environment_attributes_for(build)
return {} unless build.has_environment?
@@ -159,7 +170,11 @@ module Gitlab
next {} unless @using_rules
if ::Gitlab::Ci::Features.rules_variables_enabled?(@pipeline.project)
- rules_result.build_attributes(@seed_attributes)
+ rules_variables_result = ::Gitlab::Ci::Variables::Helpers.merge_variables(
+ @seed_attributes[:yaml_variables], rules_result.variables
+ )
+
+ rules_result.build_attributes.merge(yaml_variables: rules_variables_result)
else
rules_result.build_attributes
end
@@ -188,7 +203,6 @@ module Gitlab
# we need to prevent the exit codes from being persisted because they
# would break the behavior defined by `rules:allow_failure`.
def allow_failure_criteria_attributes
- return {} unless ::Gitlab::Ci::Features.allow_failure_with_exit_codes_enabled?
return {} if rules_attributes[:allow_failure].nil?
return {} unless @seed_attributes.dig(:options, :allow_failure_criteria)
diff --git a/lib/gitlab/ci/pipeline/seed/build/resource_group.rb b/lib/gitlab/ci/pipeline/seed/build/resource_group.rb
deleted file mode 100644
index c0641d9ff0a..00000000000
--- a/lib/gitlab/ci/pipeline/seed/build/resource_group.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module Pipeline
- module Seed
- class Build
- class ResourceGroup < Seed::Base
- include Gitlab::Utils::StrongMemoize
-
- attr_reader :build, :resource_group_key
-
- def initialize(build, resource_group_key)
- @build = build
- @resource_group_key = resource_group_key
- end
-
- def to_resource
- return unless resource_group_key.present?
-
- resource_group = build.project.resource_groups
- .safe_find_or_create_by(key: expanded_resource_group_key)
-
- resource_group if resource_group.persisted?
- end
-
- private
-
- def expanded_resource_group_key
- strong_memoize(:expanded_resource_group_key) do
- ExpandVariables.expand(resource_group_key, -> { build.simple_variables })
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/pipeline/seed/processable/resource_group.rb b/lib/gitlab/ci/pipeline/seed/processable/resource_group.rb
new file mode 100644
index 00000000000..f8ea6d4184c
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/seed/processable/resource_group.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Seed
+ module Processable
+ class ResourceGroup < Seed::Base
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :processable, :resource_group_key
+
+ def initialize(processable, resource_group_key)
+ @processable = processable
+ @resource_group_key = resource_group_key
+ end
+
+ def to_resource
+ return unless resource_group_key.present?
+
+ resource_group = processable.project.resource_groups
+ .safe_find_or_create_by(key: expanded_resource_group_key)
+
+ resource_group if resource_group.persisted?
+ end
+
+ private
+
+ def expanded_resource_group_key
+ strong_memoize(:expanded_resource_group_key) do
+ ExpandVariables.expand(resource_group_key, -> { processable.simple_variables })
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/reports/codequality_mr_diff.rb b/lib/gitlab/ci/reports/codequality_mr_diff.rb
new file mode 100644
index 00000000000..e60a075e3f5
--- /dev/null
+++ b/lib/gitlab/ci/reports/codequality_mr_diff.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ class CodequalityMrDiff
+ attr_reader :files
+
+ def initialize(raw_report)
+ @raw_report = raw_report
+ @files = {}
+ build_report!
+ end
+
+ private
+
+ def build_report!
+ codequality_files = @raw_report.all_degradations.each_with_object({}) do |degradation, codequality_files|
+ unless codequality_files[degradation.dig(:location, :path)].present?
+ codequality_files[degradation.dig(:location, :path)] = []
+ end
+
+ build_mr_diff_payload(codequality_files, degradation)
+ end
+
+ @files = codequality_files
+ end
+
+ def build_mr_diff_payload(codequality_files, degradation)
+ codequality_files[degradation.dig(:location, :path)] << {
+ line: degradation.dig(:location, :lines, :begin) || degradation.dig(:location, :positions, :begin, :line),
+ description: degradation[:description],
+ severity: degradation[:severity]
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/status/bridge/factory.rb b/lib/gitlab/ci/status/bridge/factory.rb
index b9bd66cee71..4d5a94a3beb 100644
--- a/lib/gitlab/ci/status/bridge/factory.rb
+++ b/lib/gitlab/ci/status/bridge/factory.rb
@@ -8,6 +8,7 @@ module Gitlab
def self.extended_statuses
[[Status::Bridge::Failed],
[Status::Bridge::Manual],
+ [Status::Bridge::WaitingForResource],
[Status::Bridge::Play],
[Status::Bridge::Action]]
end
diff --git a/lib/gitlab/ci/status/bridge/waiting_for_resource.rb b/lib/gitlab/ci/status/bridge/waiting_for_resource.rb
new file mode 100644
index 00000000000..d2c8f71a609
--- /dev/null
+++ b/lib/gitlab/ci/status/bridge/waiting_for_resource.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ module Bridge
+ class WaitingForResource < Status::Processable::WaitingForResource
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/status/build/waiting_for_resource.rb b/lib/gitlab/ci/status/build/waiting_for_resource.rb
index 008e6a17bdd..5dcc060a990 100644
--- a/lib/gitlab/ci/status/build/waiting_for_resource.rb
+++ b/lib/gitlab/ci/status/build/waiting_for_resource.rb
@@ -4,22 +4,7 @@ module Gitlab
module Ci
module Status
module Build
- class WaitingForResource < Status::Extended
- ##
- # TODO: image is shared with 'pending'
- # until we get a dedicated one
- #
- def illustration
- {
- image: 'illustrations/pending_job_empty.svg',
- size: 'svg-430',
- title: _('This job is waiting for resource: ') + subject.resource_group.key
- }
- end
-
- def self.matches?(build, _)
- build.waiting_for_resource?
- end
+ class WaitingForResource < Status::Processable::WaitingForResource
end
end
end
diff --git a/lib/gitlab/ci/status/processable/waiting_for_resource.rb b/lib/gitlab/ci/status/processable/waiting_for_resource.rb
new file mode 100644
index 00000000000..c9b1dd795d0
--- /dev/null
+++ b/lib/gitlab/ci/status/processable/waiting_for_resource.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ module Processable
+ class WaitingForResource < Status::Extended
+ ##
+ # TODO: image is shared with 'pending'
+ # until we get a dedicated one
+ #
+ def illustration
+ {
+ image: 'illustrations/pending_job_empty.svg',
+ size: 'svg-430',
+ title: _('This job is waiting for resource: ') + subject.resource_group.key
+ }
+ end
+
+ def self.matches?(processable, _)
+ processable.waiting_for_resource?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
index 501d8737acd..daed75a42ee 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -7,7 +7,7 @@ code_quality:
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.19"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.22"
needs: []
script:
- export SOURCE_CODE=$PWD
diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
index 192b1509fdc..6f30fc2dcd5 100644
--- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
@@ -1,6 +1,6 @@
apply:
stage: deploy
- image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.37.0"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.40.0"
environment:
name: production
variables:
diff --git a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
index 84bb0ff3b33..8f64da24410 100644
--- a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
@@ -40,14 +40,14 @@ verify:jdk8:
<<: *verify
# To deploy packages from CI, create a ci_settings.xml file
-# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for more details.
+# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for more details.
# Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate.
# For `master` branch run `mvn deploy` automatically.
deploy:jdk8:
stage: deploy
script:
- if [ ! -f ci_settings.xml ];
- then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for instructions.";
+ then echo "CI settings missing\! If deploying to GitLab Maven Repository, please see https://docs.gitlab.com/ee/user/packages/maven_repository/index.html#create-maven-packages-with-gitlab-cicd for instructions.";
fi
- 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml'
only:
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 63237e41376..21e926ef275 100644
--- a/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/license_compliance/
+# Read more about this feature here: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html
#
# Configure the scanning tool through the environment variables.
# List of the variables: https://gitlab.com/gitlab-org/security-products/analyzers/license-finder#settings
@@ -21,7 +21,6 @@ license_scanning:
LM_REPORT_VERSION: '2.1'
SETUP_CMD: $LICENSE_MANAGEMENT_SETUP_CMD
allow_failure: true
- needs: []
script:
- /run.sh analyze .
artifacts:
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index 56c6fbd96bc..828352743b4 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -9,7 +9,7 @@ variables:
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- SAST_DEFAULT_ANALYZERS: "bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, sobelow, pmd-apex, kubesec, mobsf"
+ SAST_DEFAULT_ANALYZERS: "bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, sobelow, pmd-apex, kubesec, mobsf, semgrep"
SAST_EXCLUDED_ANALYZERS: ""
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SAST_ANALYZER_IMAGE_TAG: 2
@@ -66,7 +66,8 @@ brakeman-sast:
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /brakeman/
exists:
- - 'config/routes.rb'
+ - '**/*.rb'
+ - '**/Gemfile'
eslint-sast:
extends: .sast-analyzer
@@ -243,6 +244,23 @@ security-code-scan-sast:
- '**/*.csproj'
- '**/*.vbproj'
+semgrep-sast:
+ extends: .sast-analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/semgrep:latest"
+ rules:
+ - if: $SAST_DISABLED
+ when: never
+ - if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
+ when: never
+ - if: $CI_COMMIT_BRANCH &&
+ $SAST_DEFAULT_ANALYZERS =~ /semgrep/ &&
+ $SAST_EXPERIMENTAL_FEATURES == 'true'
+ exists:
+ - '**/*.py'
+
sobelow-sast:
extends: .sast-analyzer
image:
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index 0222ca021b7..3258d965c93 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -182,7 +182,7 @@ module Gitlab
if job.trace_chunks.any?
Gitlab::Ci::Trace::ChunkedIO.new(job) do |stream|
archive_stream!(stream)
- stream.destroy!
+ destroy_stream(job) { stream.destroy! }
end
elsif current_path
File.open(current_path) do |stream|
@@ -268,7 +268,21 @@ module Gitlab
end
def trace_artifact
- job.job_artifacts_trace
+ read_trace_artifact(job) { job.job_artifacts_trace }
+ end
+
+ ##
+ # Overridden in EE
+ #
+ def destroy_stream(job)
+ yield
+ end
+
+ ##
+ # Overriden in EE
+ #
+ def read_trace_artifact(job)
+ yield
end
def being_watched_cache_key
@@ -277,3 +291,5 @@ module Gitlab
end
end
end
+
+::Gitlab::Ci::Trace.prepend_if_ee('EE::Gitlab::Ci::Trace')
diff --git a/lib/gitlab/ci/trace/checksum.rb b/lib/gitlab/ci/trace/checksum.rb
index 7cdb6a6c03c..92bed817875 100644
--- a/lib/gitlab/ci/trace/checksum.rb
+++ b/lib/gitlab/ci/trace/checksum.rb
@@ -30,7 +30,11 @@ module Gitlab
end
def state_crc32
- strong_memoize(:state_crc32) { build.pending_state&.crc32 }
+ strong_memoize(:state_crc32) do
+ ::Gitlab::Database::Consistency.with_read_consistency do
+ build.pending_state&.crc32
+ end
+ end
end
def chunks_crc32
@@ -59,8 +63,10 @@ module Gitlab
#
def trace_chunks
strong_memoize(:trace_chunks) do
- build.trace_chunks.persisted
- .select(::Ci::BuildTraceChunk.metadata_attributes)
+ ::Ci::BuildTraceChunk.with_read_consistency(build) do
+ build.trace_chunks.persisted
+ .select(::Ci::BuildTraceChunk.metadata_attributes)
+ end
end
end
diff --git a/lib/gitlab/ci/trace/chunked_io.rb b/lib/gitlab/ci/trace/chunked_io.rb
index 6f3e4ccf48d..7c2e39b1e53 100644
--- a/lib/gitlab/ci/trace/chunked_io.rb
+++ b/lib/gitlab/ci/trace/chunked_io.rb
@@ -227,12 +227,20 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- def build_chunk
- @chunks_cache[chunk_index] = ::Ci::BuildTraceChunk.new(build: build, chunk_index: chunk_index)
+ def next_chunk
+ @chunks_cache[chunk_index] = begin
+ if ::Ci::BuildTraceChunk.consistent_reads_enabled?(build)
+ ::Ci::BuildTraceChunk
+ .safe_find_or_create_by(build: build, chunk_index: chunk_index)
+ else
+ ::Ci::BuildTraceChunk
+ .new(build: build, chunk_index: chunk_index)
+ end
+ end
end
def ensure_chunk
- current_chunk || build_chunk
+ current_chunk || next_chunk || current_chunk
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/ci/variables/collection/sorted.rb b/lib/gitlab/ci/variables/collection/sorted.rb
index 6abc6a5644f..e641df10462 100644
--- a/lib/gitlab/ci/variables/collection/sorted.rb
+++ b/lib/gitlab/ci/variables/collection/sorted.rb
@@ -8,8 +8,9 @@ module Gitlab
include TSort
include Gitlab::Utils::StrongMemoize
- def initialize(variables)
+ def initialize(variables, project)
@variables = variables
+ @project = project
end
def valid?
@@ -19,7 +20,7 @@ module Gitlab
# errors sorts an array of variables, ignoring unknown variable references,
# and returning an error string if a circular variable reference is found
def errors
- return if Feature.disabled?(:variable_inside_variable)
+ return if Feature.disabled?(:variable_inside_variable, @project)
strong_memoize(:errors) do
# Check for cyclic dependencies and build error message in that case
@@ -34,7 +35,7 @@ module Gitlab
# sort sorts an array of variables, ignoring unknown variable references.
# If a circular variable reference is found, the original array is returned
def sort
- return @variables if Feature.disabled?(:variable_inside_variable)
+ return @variables if Feature.disabled?(:variable_inside_variable, @project)
return @variables if errors
tsort
diff --git a/lib/gitlab/ci/variables/helpers.rb b/lib/gitlab/ci/variables/helpers.rb
new file mode 100644
index 00000000000..e2a54f90ecb
--- /dev/null
+++ b/lib/gitlab/ci/variables/helpers.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Variables
+ module Helpers
+ class << self
+ def merge_variables(current_vars, new_vars)
+ current_vars = transform_from_yaml_variables(current_vars)
+ new_vars = transform_from_yaml_variables(new_vars)
+
+ transform_to_yaml_variables(
+ current_vars.merge(new_vars)
+ )
+ end
+
+ def transform_to_yaml_variables(vars)
+ vars.to_h.map do |key, value|
+ { key: key.to_s, value: value, public: true }
+ end
+ end
+
+ def transform_from_yaml_variables(vars)
+ return vars.stringify_keys if vars.is_a?(Hash)
+
+ vars.to_a.map { |var| [var[:key].to_s, var[:value]] }.to_h
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index 86749cda9c7..3459b69bebc 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -123,9 +123,7 @@ module Gitlab
end
def transform_to_yaml_variables(variables)
- variables.to_h.map do |key, value|
- { key: key.to_s, value: value, public: true }
- end
+ ::Gitlab::Ci::Variables::Helpers.transform_to_yaml_variables(variables)
end
end
end
diff --git a/lib/gitlab/cleanup/orphan_job_artifact_files.rb b/lib/gitlab/cleanup/orphan_job_artifact_files.rb
index 6d18f9070cc..48a1ab23fc2 100644
--- a/lib/gitlab/cleanup/orphan_job_artifact_files.rb
+++ b/lib/gitlab/cleanup/orphan_job_artifact_files.rb
@@ -12,10 +12,9 @@ module Gitlab
VALID_NICENESS_LEVELS = %w{none realtime best-effort idle}.freeze
attr_accessor :batch, :total_found, :total_cleaned
- attr_reader :limit, :dry_run, :niceness, :logger
+ attr_reader :dry_run, :niceness, :logger
- def initialize(limit: nil, dry_run: true, niceness: nil, logger: nil)
- @limit = limit
+ def initialize(dry_run: true, niceness: nil, logger: nil)
@dry_run = dry_run
@niceness = (niceness || DEFAULT_NICENESS).downcase
@logger = logger || Gitlab::AppLogger
@@ -31,7 +30,11 @@ module Gitlab
batch << artifact_file
clean_batch! if batch.full?
- break if limit_reached?
+
+ if limit_reached?
+ log_info("Exiting due to reaching limit of #{limit}.")
+ break
+ end
end
clean_batch!
@@ -128,6 +131,10 @@ module Gitlab
def log_error(msg, params = {})
logger.error(msg)
end
+
+ def limit
+ ENV['LIMIT']&.to_i
+ end
end
end
end
diff --git a/lib/gitlab/cleanup/orphan_lfs_file_references.rb b/lib/gitlab/cleanup/orphan_lfs_file_references.rb
index a6638b2cbc8..99e7550629a 100644
--- a/lib/gitlab/cleanup/orphan_lfs_file_references.rb
+++ b/lib/gitlab/cleanup/orphan_lfs_file_references.rb
@@ -5,15 +5,14 @@ module Gitlab
class OrphanLfsFileReferences
include Gitlab::Utils::StrongMemoize
- attr_reader :project, :dry_run, :logger, :limit
+ attr_reader :project, :dry_run, :logger
DEFAULT_REMOVAL_LIMIT = 1000
- def initialize(project, dry_run: true, logger: nil, limit: nil)
+ def initialize(project, dry_run: true, logger: nil)
@project = project
@dry_run = dry_run
@logger = logger || Gitlab::AppLogger
- @limit = limit
end
def run!
@@ -67,6 +66,10 @@ module Gitlab
def log_info(msg)
logger.info("#{'[DRY RUN] ' if dry_run}#{msg}")
end
+
+ def limit
+ ENV['LIMIT']&.to_i
+ end
end
end
end
diff --git a/lib/gitlab/cluster/lifecycle_events.rb b/lib/gitlab/cluster/lifecycle_events.rb
index 4ae75e0db0a..3c71ca9fcf0 100644
--- a/lib/gitlab/cluster/lifecycle_events.rb
+++ b/lib/gitlab/cluster/lifecycle_events.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative '../utils' # Gitlab::Utils
+
module Gitlab
module Cluster
#
@@ -64,6 +66,10 @@ module Gitlab
# Blocks will be executed in the order in which they are registered.
#
class LifecycleEvents
+ FatalError = Class.new(Exception) # rubocop:disable Lint/InheritException
+
+ USE_FATAL_LIFECYCLE_EVENTS = Gitlab::Utils.to_boolean(ENV.fetch('GITLAB_FATAL_LIFECYCLE_EVENTS', 'true'))
+
class << self
#
# Hook registration methods (called from initializers)
@@ -111,24 +117,24 @@ module Gitlab
# Lifecycle integration methods (called from unicorn.rb, puma.rb, etc.)
#
def do_worker_start
- call(@worker_start_hooks)
+ call(:worker_start_hooks, @worker_start_hooks)
end
def do_before_fork
- call(@before_fork_hooks)
+ call(:before_fork_hooks, @before_fork_hooks)
end
def do_before_graceful_shutdown
- call(@master_blackout_period)
+ call(:master_blackout_period, @master_blackout_period)
blackout_seconds = ::Settings.shutdown.blackout_seconds.to_i
sleep(blackout_seconds) if blackout_seconds > 0
- call(@master_graceful_shutdown)
+ call(:master_graceful_shutdown, @master_graceful_shutdown)
end
def do_before_master_restart
- call(@master_restart_hooks)
+ call(:master_restart_hooks, @master_restart_hooks)
end
# DEPRECATED
@@ -143,8 +149,18 @@ module Gitlab
private
- def call(hooks)
- hooks&.each(&:call)
+ def call(name, hooks)
+ return unless hooks
+
+ hooks.each do |hook|
+ hook.call
+ rescue => e
+ Gitlab::ErrorTracking.track_exception(e, type: 'LifecycleEvents', hook: hook)
+ warn("ERROR: The hook #{name} failed with exception (#{e.class}) \"#{e.message}\".")
+
+ # we consider lifecycle hooks to be fatal errors
+ raise FatalError, e if USE_FATAL_LIFECYCLE_EVENTS
+ end
end
def in_clustered_environment?
diff --git a/lib/gitlab/cluster/puma_worker_killer_initializer.rb b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
index 822012e0ed6..fd9f58a34f3 100644
--- a/lib/gitlab/cluster/puma_worker_killer_initializer.rb
+++ b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
@@ -35,6 +35,10 @@ module Gitlab
# regularly rather than rely on OOM behavior for periodic restarting.
config.rolling_restart_frequency = 43200 # 12 hours in seconds.
+ # Spread the rolling restarts out over 1 hour to avoid too many simultaneous
+ # process startups.
+ config.rolling_restart_splay_seconds = 0.0..3600.0 # 0 to 1 hour in seconds.
+
observer = Gitlab::Cluster::PumaWorkerKillerObserver.new
config.pre_term = observer.callback
end
diff --git a/lib/gitlab/composer/cache.rb b/lib/gitlab/composer/cache.rb
new file mode 100644
index 00000000000..1f404d63047
--- /dev/null
+++ b/lib/gitlab/composer/cache.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'tempfile'
+
+module Gitlab
+ module Composer
+ class Cache
+ def initialize(project:, name:, last_page_sha: nil)
+ @project = project
+ @name = name
+ @last_page_sha = last_page_sha
+ end
+
+ def execute
+ Packages::Composer::Metadatum.transaction do # rubocop: disable CodeReuse/ActiveRecord
+ # make sure we lock these records at the start
+ locked_package_metadata
+
+ if locked_package_metadata.any?
+ mark_pages_for_delete(shas_to_delete)
+
+ create_cache_page!
+
+ # assign the newest page SHA to the packages
+ locked_package_metadata.update_all(version_cache_sha: version_index.sha)
+ elsif @last_page_sha
+ mark_pages_for_delete([@last_page_sha])
+ end
+ end
+ end
+
+ private
+
+ def mark_pages_for_delete(shas)
+ Packages::Composer::CacheFile
+ .with_namespace(@project.namespace)
+ .with_sha(shas)
+ .update_all(delete_at: 1.day.from_now)
+ end
+
+ def create_cache_page!
+ Packages::Composer::CacheFile
+ .safe_find_or_create_by!(namespace_id: @project.namespace_id, file_sha256: version_index.sha) do |cache_file|
+ cache_file.file = CarrierWaveStringFile.new(version_index.to_json)
+ end
+ end
+
+ def version_index
+ @version_index ||= ::Gitlab::Composer::VersionIndex.new(siblings)
+ end
+
+ def siblings
+ @siblings ||= locked_package_metadata.map(&:package)
+ end
+
+ # find all metadata of the package versions and lock it for update
+ def locked_package_metadata
+ @locked_package_metadata ||= Packages::Composer::Metadatum
+ .for_package(@name, @project.id)
+ .locked_for_update
+ end
+
+ def shas_to_delete
+ locked_package_metadata
+ .map(&:version_cache_sha)
+ .reject { |sha| sha == version_index.sha }
+ .compact
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/composer/version_index.rb b/lib/gitlab/composer/version_index.rb
index de9a17a453f..ac0071cdc53 100644
--- a/lib/gitlab/composer/version_index.rb
+++ b/lib/gitlab/composer/version_index.rb
@@ -20,7 +20,7 @@ module Gitlab
private
def package_versions_map
- @packages.each_with_object({}) do |package, map|
+ @packages.sort_by(&:version).each_with_object({}) do |package, map|
map[package.version] = package_metadata(package)
end
end
diff --git a/lib/gitlab/conan_token.rb b/lib/gitlab/conan_token.rb
index 7526c10b608..d03997b4158 100644
--- a/lib/gitlab/conan_token.rb
+++ b/lib/gitlab/conan_token.rb
@@ -35,7 +35,7 @@ module Gitlab
def secret
OpenSSL::HMAC.hexdigest(
- OpenSSL::Digest::SHA256.new,
+ OpenSSL::Digest.new('SHA256'),
::Settings.attr_encrypted_db_key_base,
HMAC_KEY
)
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb
index 88786ed82ff..8120f2c1243 100644
--- a/lib/gitlab/config/entry/validators.rb
+++ b/lib/gitlab/config/entry/validators.rb
@@ -268,17 +268,16 @@ module Gitlab
end
end
- class StringOrNestedArrayOfStringsValidator < NestedArrayOfStringsValidator
- def validate_each(record, attribute, value)
- unless validate_string_or_nested_array_of_strings(value)
- record.errors.add(attribute, 'should be a string or an array containing strings and arrays of strings')
- end
- end
+ class StringOrNestedArrayOfStringsValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+ include NestedArrayHelpers
- private
+ def validate_each(record, attribute, value)
+ max_level = options.fetch(:max_level, 1)
- def validate_string_or_nested_array_of_strings(values)
- validate_string(values) || validate_nested_array_of_strings(values)
+ unless validate_string(value) || validate_nested_array(value, max_level, &method(:validate_string))
+ record.errors.add(attribute, "should be a string or a nested array of strings up to #{max_level} levels deep")
+ end
end
end
diff --git a/lib/gitlab/config/entry/validators/nested_array_helpers.rb b/lib/gitlab/config/entry/validators/nested_array_helpers.rb
new file mode 100644
index 00000000000..9f5d17d74b0
--- /dev/null
+++ b/lib/gitlab/config/entry/validators/nested_array_helpers.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ module Validators
+ # Include this module to validate deeply nested array of values
+ #
+ # class MyNestedValidator < ActiveModel::EachValidator
+ # include NestedArrayHelpers
+ #
+ # def validate_each(record, attribute, value)
+ # max_depth = options.fetch(:max_depth, 1)
+ #
+ # unless validate_nested_array(value, max_depth) { |v| v.is_a?(Integer) }
+ # record.errors.add(attribute, "is invalid")
+ # end
+ # end
+ # end
+ #
+ module NestedArrayHelpers
+ def validate_nested_array(value, max_depth = 1, &validator_proc)
+ return false unless value.is_a?(Array)
+
+ validate_nested_array_recursively(value, max_depth, &validator_proc)
+ end
+
+ private
+
+ # rubocop: disable Performance/RedundantBlockCall
+ # Disables Rubocop rule for easier readability reasons.
+ def validate_nested_array_recursively(value, nesting_level, &validator_proc)
+ return true if validator_proc.call(value)
+ return false if nesting_level <= 0
+ return false unless value.is_a?(Array)
+
+ value.all? do |element|
+ validate_nested_array_recursively(element, nesting_level - 1, &validator_proc)
+ end
+ end
+ # rubocop: enable Performance/RedundantBlockCall
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/loader/yaml.rb b/lib/gitlab/config/loader/yaml.rb
index cb3fc49944c..80c9abecd8e 100644
--- a/lib/gitlab/config/loader/yaml.rb
+++ b/lib/gitlab/config/loader/yaml.rb
@@ -12,8 +12,12 @@ module Gitlab
MAX_YAML_SIZE = 1.megabyte
MAX_YAML_DEPTH = 100
- def initialize(config)
- @config = YAML.safe_load(config, [Symbol], [], true)
+ def initialize(config, additional_permitted_classes: [])
+ @config = YAML.safe_load(config,
+ permitted_classes: [Symbol, *additional_permitted_classes],
+ permitted_symbols: [],
+ aliases: true
+ )
rescue Psych::Exception => e
raise Loader::FormatError, e.message
end
diff --git a/lib/gitlab/crypto_helper.rb b/lib/gitlab/crypto_helper.rb
index 87a03d9c58f..4428354642d 100644
--- a/lib/gitlab/crypto_helper.rb
+++ b/lib/gitlab/crypto_helper.rb
@@ -6,25 +6,44 @@ module Gitlab
AES256_GCM_OPTIONS = {
algorithm: 'aes-256-gcm',
- key: Settings.attr_encrypted_db_key_base_32,
- iv: Settings.attr_encrypted_db_key_base_12
+ key: Settings.attr_encrypted_db_key_base_32
}.freeze
+ AES256_GCM_IV_STATIC = Settings.attr_encrypted_db_key_base_12
+
def sha256(value)
salt = Settings.attr_encrypted_db_key_base_truncated
::Digest::SHA256.base64digest("#{value}#{salt}")
end
- def aes256_gcm_encrypt(value)
- encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value))
- Base64.strict_encode64(encrypted_token)
+ def aes256_gcm_encrypt(value, nonce: nil)
+ aes256_gcm_encrypt_using_static_nonce(value)
end
def aes256_gcm_decrypt(value)
return unless value
+ nonce = Feature.enabled?(:dynamic_nonce_creation) ? dynamic_nonce(value) : AES256_GCM_IV_STATIC
encrypted_token = Base64.decode64(value)
- Encryptor.decrypt(AES256_GCM_OPTIONS.merge(value: encrypted_token))
+ decrypted_token = Encryptor.decrypt(AES256_GCM_OPTIONS.merge(value: encrypted_token, iv: nonce))
+ decrypted_token
+ end
+
+ def dynamic_nonce(value)
+ TokenWithIv.find_nonce_by_hashed_token(value) || AES256_GCM_IV_STATIC
+ end
+
+ def aes256_gcm_encrypt_using_static_nonce(value)
+ create_encrypted_token(value, AES256_GCM_IV_STATIC)
+ end
+
+ def read_only?
+ Gitlab::Database.read_only?
+ end
+
+ def create_encrypted_token(value, iv)
+ encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value, iv: iv))
+ Base64.strict_encode64(encrypted_token)
end
end
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index d0579a44219..0bf41f9dc0d 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -7,6 +7,10 @@ module Gitlab
Gitlab::SafeRequestStore.fetch(:current_application_settings) { ensure_application_settings! }
end
+ def current_application_settings?
+ Gitlab::SafeRequestStore.exist?(:current_application_settings) || ::ApplicationSetting.current.present?
+ end
+
def expire_current_application_settings
::ApplicationSetting.expire
Gitlab::SafeRequestStore.delete(:current_application_settings)
diff --git a/lib/gitlab/cycle_analytics/summary/deploy.rb b/lib/gitlab/cycle_analytics/summary/deploy.rb
index 5125c8e64ee..aaa2554dbfa 100644
--- a/lib/gitlab/cycle_analytics/summary/deploy.rb
+++ b/lib/gitlab/cycle_analytics/summary/deploy.rb
@@ -15,9 +15,16 @@ module Gitlab
private
def deployments_count
- query = @project.deployments.success.where("created_at >= ?", @from)
- query = query.where("created_at <= ?", @to) if @to
- query.count
+ if Feature.enabled?(:query_deploymenys_via_finished_at_in_vsa, default_enabled: :yaml)
+ DeploymentsFinder
+ .new(project: @project, finished_after: @from, finished_before: @to, status: :success)
+ .execute
+ .count
+ else
+ query = @project.deployments.success.where("created_at >= ?", @from)
+ query = query.where("created_at <= ?", @to) if @to
+ query.count
+ end
end
end
end
diff --git a/lib/gitlab/danger/base_linter.rb b/lib/gitlab/danger/base_linter.rb
deleted file mode 100644
index 898434724bd..00000000000
--- a/lib/gitlab/danger/base_linter.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'title_linting'
-
-module Gitlab
- module Danger
- class BaseLinter
- MIN_SUBJECT_WORDS_COUNT = 3
- MAX_LINE_LENGTH = 72
-
- attr_reader :commit, :problems
-
- def self.problems_mapping
- {
- subject_too_short: "The %s must contain at least #{MIN_SUBJECT_WORDS_COUNT} words",
- subject_too_long: "The %s may not be longer than #{MAX_LINE_LENGTH} characters",
- subject_starts_with_lowercase: "The %s must start with a capital letter",
- subject_ends_with_a_period: "The %s must not end with a period"
- }
- end
-
- def self.subject_description
- 'commit subject'
- end
-
- def initialize(commit)
- @commit = commit
- @problems = {}
- end
-
- def failed?
- problems.any?
- end
-
- def add_problem(problem_key, *args)
- @problems[problem_key] = sprintf(self.class.problems_mapping[problem_key], *args)
- end
-
- def lint_subject
- if subject_too_short?
- add_problem(:subject_too_short, self.class.subject_description)
- end
-
- if subject_too_long?
- add_problem(:subject_too_long, self.class.subject_description)
- end
-
- if subject_starts_with_lowercase?
- add_problem(:subject_starts_with_lowercase, self.class.subject_description)
- end
-
- if subject_ends_with_a_period?
- add_problem(:subject_ends_with_a_period, self.class.subject_description)
- end
-
- self
- end
-
- private
-
- def subject
- TitleLinting.remove_draft_flag(message_parts[0])
- end
-
- def subject_too_short?
- subject.split(' ').length < MIN_SUBJECT_WORDS_COUNT
- end
-
- def subject_too_long?
- line_too_long?(subject)
- end
-
- def line_too_long?(line)
- line.length > MAX_LINE_LENGTH
- end
-
- def subject_starts_with_lowercase?
- return false if ('A'..'Z').cover?(subject[0])
-
- first_char = subject.sub(/\A(\[.+\]|\w+:)\s/, '')[0]
- first_char_downcased = first_char.downcase
- return true unless ('a'..'z').cover?(first_char_downcased)
-
- first_char.downcase == first_char
- end
-
- def subject_ends_with_a_period?
- subject.end_with?('.')
- end
-
- def message_parts
- @message_parts ||= commit.message.split("\n", 3)
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/changelog.rb b/lib/gitlab/danger/changelog.rb
deleted file mode 100644
index 4b85775ed98..00000000000
--- a/lib/gitlab/danger/changelog.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'title_linting'
-
-module Gitlab
- module Danger
- module Changelog
- NO_CHANGELOG_LABELS = [
- 'tooling',
- 'tooling::pipelines',
- 'tooling::workflow',
- 'ci-build',
- 'meta'
- ].freeze
- NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
- CREATE_CHANGELOG_COMMAND = 'bin/changelog -m %<mr_iid>s "%<mr_title>s"'
- CREATE_EE_CHANGELOG_COMMAND = 'bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"'
- CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n"
- CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n"
-
- OPTIONAL_CHANGELOG_MESSAGE = <<~MSG
- If you want to create a changelog entry for GitLab FOSS, run the following:
-
- #{CREATE_CHANGELOG_COMMAND}
-
- If you want to create a changelog entry for GitLab EE, run the following instead:
-
- #{CREATE_EE_CHANGELOG_COMMAND}
-
- If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
- MSG
-
- REQUIRED_CHANGELOG_MESSAGE = <<~MSG
- To create a changelog entry, run the following:
-
- #{CREATE_CHANGELOG_COMMAND}
-
- This merge request requires a changelog entry because it [introduces a database migration](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
- MSG
-
- def required?
- git.added_files.any? { |path| path =~ %r{\Adb/(migrate|post_migrate)/} }
- end
- alias_method :db_changes?, :required?
-
- def optional?
- categories_need_changelog? && without_no_changelog_label?
- end
-
- def found
- @found ||= git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
- end
-
- def ee_changelog?
- found.start_with?('ee/')
- end
-
- def modified_text
- CHANGELOG_MODIFIED_URL_TEXT +
- format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
- end
-
- def required_text
- CHANGELOG_MISSING_URL_TEXT +
- format(REQUIRED_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
- end
-
- def optional_text
- CHANGELOG_MISSING_URL_TEXT +
- format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
- end
-
- private
-
- def mr_iid
- gitlab.mr_json["iid"]
- end
-
- def sanitized_mr_title
- TitleLinting.sanitize_mr_title(gitlab.mr_json["title"])
- end
-
- def categories_need_changelog?
- (helper.changes_by_category.keys - NO_CHANGELOG_CATEGORIES).any?
- end
-
- def without_no_changelog_label?
- (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/commit_linter.rb b/lib/gitlab/danger/commit_linter.rb
deleted file mode 100644
index e23f5900433..00000000000
--- a/lib/gitlab/danger/commit_linter.rb
+++ /dev/null
@@ -1,158 +0,0 @@
-# frozen_string_literal: true
-
-emoji_checker_path = File.expand_path('emoji_checker', __dir__)
-base_linter_path = File.expand_path('base_linter', __dir__)
-
-if defined?(Rails)
- require_dependency(base_linter_path)
- require_dependency(emoji_checker_path)
-else
- require_relative(base_linter_path)
- require_relative(emoji_checker_path)
-end
-
-module Gitlab
- module Danger
- class CommitLinter < BaseLinter
- MAX_CHANGED_FILES_IN_COMMIT = 3
- MAX_CHANGED_LINES_IN_COMMIT = 30
- SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(?<!`)(#|!|&|%)\d+(?<!`)}.freeze
-
- def self.problems_mapping
- super.merge(
- {
- separator_missing: "The commit subject and body must be separated by a blank line",
- details_too_many_changes: "Commits that change #{MAX_CHANGED_LINES_IN_COMMIT} or more lines across " \
- "at least #{MAX_CHANGED_FILES_IN_COMMIT} files must describe these changes in the commit body",
- details_line_too_long: "The commit body should not contain more than #{MAX_LINE_LENGTH} characters per line",
- message_contains_text_emoji: "Avoid the use of Markdown Emoji such as `:+1:`. These add limited value " \
- "to the commit message, and are displayed as plain text outside of GitLab",
- message_contains_unicode_emoji: "Avoid the use of Unicode Emoji. These add no value to the commit " \
- "message, and may not be displayed properly everywhere",
- message_contains_short_reference: "Use full URLs instead of short references (`gitlab-org/gitlab#123` or " \
- "`!123`), as short references are displayed as plain text outside of GitLab"
- }
- )
- end
-
- def initialize(commit)
- super
-
- @linted = false
- end
-
- def fixup?
- commit.message.start_with?('fixup!', 'squash!')
- end
-
- def suggestion?
- commit.message.start_with?('Apply suggestion to')
- end
-
- def merge?
- commit.message.start_with?('Merge branch')
- end
-
- def revert?
- commit.message.start_with?('Revert "')
- end
-
- def multi_line?
- !details.nil? && !details.empty?
- end
-
- def lint
- return self if @linted
-
- @linted = true
- lint_subject
- lint_separator
- lint_details
- lint_message
-
- self
- end
-
- private
-
- def lint_separator
- return self unless separator && !separator.empty?
-
- add_problem(:separator_missing)
-
- self
- end
-
- def lint_details
- if !multi_line? && many_changes?
- add_problem(:details_too_many_changes)
- end
-
- details&.each_line do |line|
- line_without_urls = line.strip.gsub(%r{https?://\S+}, '')
-
- # If the line includes a URL, we'll allow it to exceed MAX_LINE_LENGTH characters, but
- # only if the line _without_ the URL does not exceed this limit.
- next unless line_too_long?(line_without_urls)
-
- add_problem(:details_line_too_long)
- break
- end
-
- self
- end
-
- def lint_message
- if message_contains_text_emoji?
- add_problem(:message_contains_text_emoji)
- end
-
- if message_contains_unicode_emoji?
- add_problem(:message_contains_unicode_emoji)
- end
-
- if message_contains_short_reference?
- add_problem(:message_contains_short_reference)
- end
-
- self
- end
-
- def files_changed
- commit.diff_parent.stats[:total][:files]
- end
-
- def lines_changed
- commit.diff_parent.stats[:total][:lines]
- end
-
- def many_changes?
- files_changed > MAX_CHANGED_FILES_IN_COMMIT && lines_changed > MAX_CHANGED_LINES_IN_COMMIT
- end
-
- def separator
- message_parts[1]
- end
-
- def details
- message_parts[2]&.gsub(/^Signed-off-by.*$/, '')
- end
-
- def message_contains_text_emoji?
- emoji_checker.includes_text_emoji?(commit.message)
- end
-
- def message_contains_unicode_emoji?
- emoji_checker.includes_unicode_emoji?(commit.message)
- end
-
- def message_contains_short_reference?
- commit.message.match?(SHORT_REFERENCE_REGEX)
- end
-
- def emoji_checker
- @emoji_checker ||= Gitlab::Danger::EmojiChecker.new
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/emoji_checker.rb b/lib/gitlab/danger/emoji_checker.rb
deleted file mode 100644
index e31a6ae5011..00000000000
--- a/lib/gitlab/danger/emoji_checker.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'json'
-
-module Gitlab
- module Danger
- class EmojiChecker
- DIGESTS = File.expand_path('../../../fixtures/emojis/digests.json', __dir__)
- ALIASES = File.expand_path('../../../fixtures/emojis/aliases.json', __dir__)
-
- # A regex that indicates a piece of text _might_ include an Emoji. The regex
- # alone is not enough, as we'd match `:foo:bar:baz`. Instead, we use this
- # regex to save us from having to check for all possible emoji names when we
- # know one definitely is not included.
- LIKELY_EMOJI = /:[\+a-z0-9_\-]+:/.freeze
-
- UNICODE_EMOJI_REGEX = %r{(
- [\u{1F300}-\u{1F5FF}] |
- [\u{1F1E6}-\u{1F1FF}] |
- [\u{2700}-\u{27BF}] |
- [\u{1F900}-\u{1F9FF}] |
- [\u{1F600}-\u{1F64F}] |
- [\u{1F680}-\u{1F6FF}] |
- [\u{2600}-\u{26FF}]
- )}x.freeze
-
- def initialize
- names = JSON.parse(File.read(DIGESTS)).keys +
- JSON.parse(File.read(ALIASES)).keys
-
- @emoji = names.map { |name| ":#{name}:" }
- end
-
- def includes_text_emoji?(text)
- return false unless text.match?(LIKELY_EMOJI)
-
- @emoji.any? { |emoji| text.include?(emoji) }
- end
-
- def includes_unicode_emoji?(text)
- text.match?(UNICODE_EMOJI_REGEX)
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
deleted file mode 100644
index 09e013e24b8..00000000000
--- a/lib/gitlab/danger/helper.rb
+++ /dev/null
@@ -1,273 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'teammate'
-require_relative 'title_linting'
-
-module Gitlab
- module Danger
- module Helper
- RELEASE_TOOLS_BOT = 'gitlab-release-tools-bot'
-
- # Returns a list of all files that have been added, modified or renamed.
- # `git.modified_files` might contain paths that already have been renamed,
- # so we need to remove them from the list.
- #
- # Considering these changes:
- #
- # - A new_file.rb
- # - D deleted_file.rb
- # - M modified_file.rb
- # - R renamed_file_before.rb -> renamed_file_after.rb
- #
- # it will return
- # ```
- # [ 'new_file.rb', 'modified_file.rb', 'renamed_file_after.rb' ]
- # ```
- #
- # @return [Array<String>]
- def all_changed_files
- Set.new
- .merge(git.added_files.to_a)
- .merge(git.modified_files.to_a)
- .merge(git.renamed_files.map { |x| x[:after] })
- .subtract(git.renamed_files.map { |x| x[:before] })
- .to_a
- .sort
- end
-
- # Returns a string containing changed lines as git diff
- #
- # Considering changing a line in lib/gitlab/usage_data.rb it will return:
- #
- # [ "--- a/lib/gitlab/usage_data.rb",
- # "+++ b/lib/gitlab/usage_data.rb",
- # "+ # Test change",
- # "- # Old change" ]
- def changed_lines(changed_file)
- diff = git.diff_for_file(changed_file)
- return [] unless diff
-
- diff.patch.split("\n").select { |line| %r{^[+-]}.match?(line) }
- end
-
- def all_ee_changes
- all_changed_files.grep(%r{\Aee/})
- end
-
- def ee?
- # Support former project name for `dev` and support local Danger run
- %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('../../../ee', __dir__))
- end
-
- def gitlab_helper
- # Unfortunately the following does not work:
- # - respond_to?(:gitlab)
- # - respond_to?(:gitlab, true)
- gitlab
- rescue NameError
- nil
- end
-
- def release_automation?
- gitlab_helper&.mr_author == RELEASE_TOOLS_BOT
- end
-
- def project_name
- ee? ? 'gitlab' : 'gitlab-foss'
- end
-
- def markdown_list(items)
- list = items.map { |item| "* `#{item}`" }.join("\n")
-
- if items.size > 10
- "\n<details>\n\n#{list}\n\n</details>\n"
- else
- list
- end
- end
-
- # @return [Hash<String,Array<String>>]
- def changes_by_category
- all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash|
- categories_for_file(file).each { |category| hash[category] << file }
- end
- end
-
- # Determines the categories a file is in, e.g., `[:frontend]`, `[:backend]`, or `%i[frontend engineering_productivity]`
- # using filename regex and specific change regex if given.
- #
- # @return Array<Symbol>
- def categories_for_file(file)
- _, categories = CATEGORIES.find do |key, _|
- filename_regex, changes_regex = Array(key)
-
- found = filename_regex.match?(file)
- found &&= changed_lines(file).any? { |changed_line| changes_regex.match?(changed_line) } if changes_regex
-
- found
- end
-
- Array(categories || :unknown)
- end
-
- # Returns the GFM for a category label, making its best guess if it's not
- # a category we know about.
- #
- # @return[String]
- def label_for_category(category)
- CATEGORY_LABELS.fetch(category, "~#{category}")
- end
-
- CATEGORY_LABELS = {
- docs: "~documentation", # Docs are reviewed along DevOps stages, so don't need roulette for now.
- none: "",
- qa: "~QA",
- test: "~test ~Quality for `spec/features/*`",
- engineering_productivity: '~"Engineering Productivity" for CI, Danger',
- ci_template: '~"ci::templates"'
- }.freeze
- # First-match win, so be sure to put more specific regex at the top...
- CATEGORIES = {
- [%r{usage_data\.rb}, %r{^(\+|-).*\s+(count|distinct_count|estimate_batch_distinct_count)\(.*\)(.*)$}] => [:database, :backend],
-
- %r{\Adoc/.*(\.(md|png|gif|jpg))\z} => :docs,
- %r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
-
- %r{\A(ee/)?app/(assets|views)/} => :frontend,
- %r{\A(ee/)?public/} => :frontend,
- %r{\A(ee/)?spec/(javascripts|frontend)/} => :frontend,
- %r{\A(ee/)?vendor/assets/} => :frontend,
- %r{\A(ee/)?scripts/frontend/} => :frontend,
- %r{(\A|/)(
- \.babelrc |
- \.eslintignore |
- \.eslintrc(\.yml)? |
- \.nvmrc |
- \.prettierignore |
- \.prettierrc |
- \.scss-lint.yml |
- \.stylelintrc |
- \.haml-lint.yml |
- \.haml-lint_todo.yml |
- babel\.config\.js |
- jest\.config\.js |
- package\.json |
- yarn\.lock |
- config/.+\.js
- )\z}x => :frontend,
-
- %r{(\A|/)(
- \.gitlab/ci/frontend\.gitlab-ci\.yml
- )\z}x => %i[frontend engineering_productivity],
-
- %r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
- %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
- %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
- %r{\A(ee/)?app/finders/} => :database,
- %r{\Arubocop/cop/migration(/|\.rb)} => :database,
-
- %r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
- %r{\A\.codeclimate\.yml\z} => :engineering_productivity,
- %r{\Alefthook.yml\z} => :engineering_productivity,
- %r{\A\.editorconfig\z} => :engineering_productivity,
- %r{Dangerfile\z} => :engineering_productivity,
- %r{\A(ee/)?(danger/|lib/gitlab/danger/)} => :engineering_productivity,
- %r{\A(ee/)?scripts/} => :engineering_productivity,
- %r{\Atooling/} => :engineering_productivity,
- %r{(CODEOWNERS)} => :engineering_productivity,
- %r{(tests.yml)} => :engineering_productivity,
-
- %r{\Alib/gitlab/ci/templates} => :ci_template,
-
- %r{\A(ee/)?spec/features/} => :test,
- %r{\A(ee/)?spec/support/shared_examples/features/} => :test,
- %r{\A(ee/)?spec/support/shared_contexts/features/} => :test,
- %r{\A(ee/)?spec/support/helpers/features/} => :test,
-
- %r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
- %r{\A(ee/)?(bin|config|generator_templates|lib|rubocop)/} => :backend,
- %r{\A(ee/)?spec/} => :backend,
- %r{\A(ee/)?vendor/} => :backend,
- %r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
- %r{\A[A-Z_]+_VERSION\z} => :backend,
- %r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
- %r{\Afile_hooks/} => :backend,
-
- %r{\A(ee/)?qa/} => :qa,
-
- # Files that don't fit into any category are marked with :none
- %r{\A(ee/)?changelogs/} => :none,
- %r{\Alocale/gitlab\.pot\z} => :none,
- %r{\Adata/whats_new/} => :none,
-
- # GraphQL auto generated doc files and schema
- %r{\Adoc/api/graphql/reference/} => :backend,
-
- # Fallbacks in case the above patterns miss anything
- %r{\.rb\z} => :backend,
- %r{(
- \.(md|txt)\z |
- \.markdownlint\.json
- )}x => :none, # To reinstate roulette for documentation, set to `:docs`.
- %r{\.js\z} => :frontend
- }.freeze
-
- def new_teammates(usernames)
- usernames.map { |u| Gitlab::Danger::Teammate.new('username' => u) }
- end
-
- def draft_mr?
- return false unless gitlab_helper
-
- TitleLinting.has_draft_flag?(gitlab_helper.mr_json['title'])
- end
-
- def security_mr?
- return false unless gitlab_helper
-
- gitlab_helper.mr_json['web_url'].include?('/gitlab-org/security/')
- end
-
- def cherry_pick_mr?
- return false unless gitlab_helper
-
- /cherry[\s-]*pick/i.match?(gitlab_helper.mr_json['title'])
- end
-
- def stable_branch?
- return false unless gitlab_helper
-
- /\A\d+-\d+-stable-ee/i.match?(gitlab_helper.mr_json['target_branch'])
- end
-
- def mr_has_labels?(*labels)
- return false unless gitlab_helper
-
- labels = labels.flatten.uniq
- (labels & gitlab_helper.mr_labels) == labels
- end
-
- def labels_list(labels, sep: ', ')
- labels.map { |label| %Q{~"#{label}"} }.join(sep)
- end
-
- def prepare_labels_for_mr(labels)
- return '' unless labels.any?
-
- "/label #{labels_list(labels, sep: ' ')}"
- end
-
- def changed_files(regex)
- all_changed_files.grep(regex)
- end
-
- def has_database_scoped_labels?(current_mr_labels)
- current_mr_labels.any? { |label| label.start_with?('database::') }
- end
-
- def has_ci_changes?
- changed_files(%r{\A(\.gitlab-ci\.yml|\.gitlab/ci/)}).any?
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/merge_request_linter.rb b/lib/gitlab/danger/merge_request_linter.rb
deleted file mode 100644
index ed354bfc68d..00000000000
--- a/lib/gitlab/danger/merge_request_linter.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-base_linter_path = File.expand_path('base_linter', __dir__)
-
-if defined?(Rails)
- require_dependency(base_linter_path)
-else
- require_relative(base_linter_path)
-end
-
-module Gitlab
- module Danger
- class MergeRequestLinter < BaseLinter
- alias_method :lint, :lint_subject
-
- def self.subject_description
- 'merge request title'
- end
-
- def self.mr_run_options_regex
- [
- 'RUN AS-IF-FOSS',
- 'UPDATE CACHE',
- 'RUN ALL RSPEC',
- 'SKIP RSPEC FAIL-FAST'
- ].join('|')
- end
-
- private
-
- def subject
- super.gsub(/\[?(#{self.class.mr_run_options_regex})\]?/, '').strip
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/request_helper.rb b/lib/gitlab/danger/request_helper.rb
deleted file mode 100644
index 06da4ed9ad3..00000000000
--- a/lib/gitlab/danger/request_helper.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'net/http'
-require 'json'
-
-module Gitlab
- module Danger
- module RequestHelper
- HTTPError = Class.new(RuntimeError)
-
- # @param [String] url
- def self.http_get_json(url)
- rsp = Net::HTTP.get_response(URI.parse(url))
-
- unless rsp.is_a?(Net::HTTPOK)
- raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}"
- end
-
- JSON.parse(rsp.body)
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/roulette.rb b/lib/gitlab/danger/roulette.rb
deleted file mode 100644
index 21feda2cf20..00000000000
--- a/lib/gitlab/danger/roulette.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'teammate'
-require_relative 'request_helper' unless defined?(Gitlab::Danger::RequestHelper)
-require_relative 'weightage/reviewers'
-require_relative 'weightage/maintainers'
-
-module Gitlab
- module Danger
- module Roulette
- ROULETTE_DATA_URL = 'https://gitlab-org.gitlab.io/gitlab-roulette/roulette.json'
- HOURS_WHEN_PERSON_CAN_BE_PICKED = (6..14).freeze
-
- INCLUDE_TIMEZONE_FOR_CATEGORY = {
- database: false
- }.freeze
-
- Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role, :timezone_experiment)
-
- def team_mr_author
- team.find { |person| person.username == mr_author_username }
- end
-
- # Assigns GitLab team members to be reviewer and maintainer
- # for each change category that a Merge Request contains.
- #
- # @return [Array<Spin>]
- def spin(project, categories, timezone_experiment: false)
- spins = categories.sort.map do |category|
- including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)
-
- spin_for_category(project, category, timezone_experiment: including_timezone)
- end
-
- backend_spin = spins.find { |spin| spin.category == :backend }
-
- spins.each do |spin|
- including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(spin.category, timezone_experiment)
- case spin.category
- when :qa
- # MR includes QA changes, but also other changes, and author isn't an SET
- if categories.size > 1 && !team_mr_author&.reviewer?(project, spin.category, [])
- spin.optional_role = :maintainer
- end
- when :test
- spin.optional_role = :maintainer
-
- if spin.reviewer.nil?
- # Fetch an already picked backend reviewer, or pick one otherwise
- spin.reviewer = backend_spin&.reviewer || spin_for_category(project, :backend, timezone_experiment: including_timezone).reviewer
- end
- when :engineering_productivity
- if spin.maintainer.nil?
- # Fetch an already picked backend maintainer, or pick one otherwise
- spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
- end
- when :ci_template
- if spin.maintainer.nil?
- # Fetch an already picked backend maintainer, or pick one otherwise
- spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
- end
- end
- end
-
- spins
- end
-
- # Looks up the current list of GitLab team members and parses it into a
- # useful form
- #
- # @return [Array<Teammate>]
- def team
- @team ||=
- begin
- data = Gitlab::Danger::RequestHelper.http_get_json(ROULETTE_DATA_URL)
- data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) }
- rescue JSON::ParserError
- raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
- end
- end
-
- # Like +team+, but only returns teammates in the current project, based on
- # project_name.
- #
- # @return [Array<Teammate>]
- def project_team(project_name)
- team.select { |member| member.in_project?(project_name) }
- rescue => err
- warn("Reviewer roulette failed to load team data: #{err.message}")
- []
- end
-
- # Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
- # selection will change on next spin
- # @param [Array<Teammate>] people
- def spin_for_person(people, random:, timezone_experiment: false)
- shuffled_people = people.shuffle(random: random)
-
- if timezone_experiment
- shuffled_people.find(&method(:valid_person_with_timezone?))
- else
- shuffled_people.find(&method(:valid_person?))
- end
- end
-
- private
-
- # @param [Teammate] person
- # @return [Boolean]
- def valid_person?(person)
- !mr_author?(person) && person.available
- end
-
- # @param [Teammate] person
- # @return [Boolean]
- def valid_person_with_timezone?(person)
- valid_person?(person) && HOURS_WHEN_PERSON_CAN_BE_PICKED.cover?(person.local_hour)
- end
-
- # @param [Teammate] person
- # @return [Boolean]
- def mr_author?(person)
- person.username == mr_author_username
- end
-
- def mr_author_username
- helper.gitlab_helper&.mr_author || `whoami`
- end
-
- def mr_source_branch
- return `git rev-parse --abbrev-ref HEAD` unless helper.gitlab_helper&.mr_json
-
- helper.gitlab_helper.mr_json['source_branch']
- end
-
- def mr_labels
- helper.gitlab_helper&.mr_labels || []
- end
-
- def new_random(seed)
- Random.new(Digest::MD5.hexdigest(seed).to_i(16))
- end
-
- def spin_role_for_category(team, role, project, category)
- team.select do |member|
- member.public_send("#{role}?", project, category, mr_labels) # rubocop:disable GitlabSecurity/PublicSend
- end
- end
-
- def spin_for_category(project, category, timezone_experiment: false)
- team = project_team(project)
- reviewers, traintainers, maintainers =
- %i[reviewer traintainer maintainer].map do |role|
- spin_role_for_category(team, role, project, category)
- end
-
- random = new_random(mr_source_branch)
-
- weighted_reviewers = Weightage::Reviewers.new(reviewers, traintainers).execute
- weighted_maintainers = Weightage::Maintainers.new(maintainers).execute
-
- reviewer = spin_for_person(weighted_reviewers, random: random, timezone_experiment: timezone_experiment)
- maintainer = spin_for_person(weighted_maintainers, random: random, timezone_experiment: timezone_experiment)
-
- Spin.new(category, reviewer, maintainer, false, timezone_experiment)
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/sidekiq_queues.rb b/lib/gitlab/danger/sidekiq_queues.rb
deleted file mode 100644
index 726b6134abf..00000000000
--- a/lib/gitlab/danger/sidekiq_queues.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Danger
- module SidekiqQueues
- def changed_queue_files
- @changed_queue_files ||= git.modified_files.grep(%r{\A(ee/)?app/workers/all_queues\.yml})
- end
-
- def added_queue_names
- @added_queue_names ||= new_queues.keys - old_queues.keys
- end
-
- def changed_queue_names
- @changed_queue_names ||=
- (new_queues.values_at(*old_queues.keys) - old_queues.values)
- .compact.map { |queue| queue[:name] }
- end
-
- private
-
- def old_queues
- @old_queues ||= queues_for(gitlab.base_commit)
- end
-
- def new_queues
- @new_queues ||= queues_for(gitlab.head_commit)
- end
-
- def queues_for(branch)
- changed_queue_files
- .flat_map { |file| YAML.safe_load(`git show #{branch}:#{file}`, permitted_classes: [Symbol]) }
- .to_h { |queue| [queue[:name], queue] }
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/teammate.rb b/lib/gitlab/danger/teammate.rb
deleted file mode 100644
index 911b84d93ec..00000000000
--- a/lib/gitlab/danger/teammate.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Danger
- class Teammate
- attr_reader :options, :username, :name, :role, :projects, :available, :hungry, :reduced_capacity, :tz_offset_hours
-
- # The options data are produced by https://gitlab.com/gitlab-org/gitlab-roulette/-/blob/master/lib/team_member.rb
- def initialize(options = {})
- @options = options
- @username = options['username']
- @name = options['name']
- @markdown_name = options['markdown_name']
- @role = options['role']
- @projects = options['projects']
- @available = options['available']
- @hungry = options['hungry']
- @reduced_capacity = options['reduced_capacity']
- @tz_offset_hours = options['tz_offset_hours']
- end
-
- def to_h
- options
- end
-
- def ==(other)
- return false unless other.respond_to?(:username)
-
- other.username == username
- end
-
- def in_project?(name)
- projects&.has_key?(name)
- end
-
- def reviewer?(project, category, labels)
- has_capability?(project, category, :reviewer, labels)
- end
-
- def traintainer?(project, category, labels)
- has_capability?(project, category, :trainee_maintainer, labels)
- end
-
- def maintainer?(project, category, labels)
- has_capability?(project, category, :maintainer, labels)
- end
-
- def markdown_name(author: nil)
- "#{@markdown_name} (#{utc_offset_text(author)})"
- end
-
- def local_hour
- (Time.now.utc + tz_offset_hours * 3600).hour
- end
-
- protected
-
- def floored_offset_hours
- floored_offset = tz_offset_hours.floor(0)
-
- floored_offset == tz_offset_hours ? floored_offset : tz_offset_hours
- end
-
- private
-
- def utc_offset_text(author = nil)
- offset_text =
- if floored_offset_hours >= 0
- "UTC+#{floored_offset_hours}"
- else
- "UTC#{floored_offset_hours}"
- end
-
- return offset_text unless author
-
- "#{offset_text}, #{offset_diff_compared_to_author(author)}"
- end
-
- def offset_diff_compared_to_author(author)
- diff = floored_offset_hours - author.floored_offset_hours
- return "same timezone as `@#{author.username}`" if diff == 0
-
- ahead_or_behind = diff < 0 ? 'behind' : 'ahead of'
- pluralized_hours = pluralize(diff.abs, 'hour', 'hours')
-
- "#{pluralized_hours} #{ahead_or_behind} `@#{author.username}`"
- end
-
- def has_capability?(project, category, kind, labels)
- case category
- when :test
- area = role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
-
- area && labels.any?("devops::#{area.downcase}") if kind == :reviewer
- when :engineering_productivity
- return false unless role[/Engineering Productivity/]
- return true if kind == :reviewer
- return true if capabilities(project).include?("#{kind} engineering_productivity")
-
- capabilities(project).include?("#{kind} backend")
- else
- capabilities(project).include?("#{kind} #{category}")
- end
- end
-
- def capabilities(project)
- Array(projects.fetch(project, []))
- end
-
- def pluralize(count, singular, plural)
- word = count == 1 || count.to_s =~ /^1(\.0+)?$/ ? singular : plural
-
- "#{count || 0} #{word}"
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/title_linting.rb b/lib/gitlab/danger/title_linting.rb
deleted file mode 100644
index db1ccaaf9a9..00000000000
--- a/lib/gitlab/danger/title_linting.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Danger
- module TitleLinting
- DRAFT_REGEX = /\A*#{Regexp.union(/(?i)(\[WIP\]\s*|WIP:\s*|WIP$)/, /(?i)(\[draft\]|\(draft\)|draft:|draft\s\-\s|draft$)/)}+\s*/i.freeze
-
- module_function
-
- def sanitize_mr_title(title)
- remove_draft_flag(title).gsub(/`/, '\\\`')
- end
-
- def remove_draft_flag(title)
- title.gsub(DRAFT_REGEX, '')
- end
-
- def has_draft_flag?(title)
- DRAFT_REGEX.match?(title)
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/weightage.rb b/lib/gitlab/danger/weightage.rb
deleted file mode 100644
index 67fade27573..00000000000
--- a/lib/gitlab/danger/weightage.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Danger
- module Weightage
- CAPACITY_MULTIPLIER = 2 # change this number to change what it means to be a reduced capacity reviewer 1/this number
- BASE_REVIEWER_WEIGHT = 1
- end
- end
-end
diff --git a/lib/gitlab/danger/weightage/maintainers.rb b/lib/gitlab/danger/weightage/maintainers.rb
deleted file mode 100644
index cc0eb370e7a..00000000000
--- a/lib/gitlab/danger/weightage/maintainers.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../weightage'
-
-module Gitlab
- module Danger
- module Weightage
- class Maintainers
- def initialize(maintainers)
- @maintainers = maintainers
- end
-
- def execute
- maintainers.each_with_object([]) do |maintainer, weighted_maintainers|
- add_weighted_reviewer(weighted_maintainers, maintainer, BASE_REVIEWER_WEIGHT)
- end
- end
-
- private
-
- attr_reader :maintainers
-
- def add_weighted_reviewer(reviewers, reviewer, weight)
- if reviewer.reduced_capacity
- reviewers.fill(reviewer, reviewers.size, weight)
- else
- reviewers.fill(reviewer, reviewers.size, weight * CAPACITY_MULTIPLIER)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/weightage/reviewers.rb b/lib/gitlab/danger/weightage/reviewers.rb
deleted file mode 100644
index c8019be716e..00000000000
--- a/lib/gitlab/danger/weightage/reviewers.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../weightage'
-
-module Gitlab
- module Danger
- module Weightage
- # Weights after (current multiplier of 2)
- #
- # +------------------------------+--------------------------------+
- # | reviewer type | weight(times in reviewer pool) |
- # +------------------------------+--------------------------------+
- # | reduced capacity reviewer | 1 |
- # | reviewer | 2 |
- # | hungry reviewer | 4 |
- # | reduced capacity traintainer | 3 |
- # | traintainer | 6 |
- # | hungry traintainer | 8 |
- # +------------------------------+--------------------------------+
- #
- class Reviewers
- DEFAULT_REVIEWER_WEIGHT = CAPACITY_MULTIPLIER * BASE_REVIEWER_WEIGHT
- TRAINTAINER_WEIGHT = 3
-
- def initialize(reviewers, traintainers)
- @reviewers = reviewers
- @traintainers = traintainers
- end
-
- def execute
- # TODO: take CODEOWNERS into account?
- # https://gitlab.com/gitlab-org/gitlab/issues/26723
-
- weighted_reviewers + weighted_traintainers
- end
-
- private
-
- attr_reader :reviewers, :traintainers
-
- def weighted_reviewers
- reviewers.each_with_object([]) do |reviewer, total_reviewers|
- add_weighted_reviewer(total_reviewers, reviewer, BASE_REVIEWER_WEIGHT)
- end
- end
-
- def weighted_traintainers
- traintainers.each_with_object([]) do |reviewer, total_traintainers|
- add_weighted_reviewer(total_traintainers, reviewer, TRAINTAINER_WEIGHT)
- end
- end
-
- def add_weighted_reviewer(reviewers, reviewer, weight)
- if reviewer.reduced_capacity
- reviewers.fill(reviewer, reviewers.size, weight)
- elsif reviewer.hungry
- reviewers.fill(reviewer, reviewers.size, weight * CAPACITY_MULTIPLIER + DEFAULT_REVIEWER_WEIGHT)
- else
- reviewers.fill(reviewer, reviewers.size, weight * CAPACITY_MULTIPLIER)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb
index e6702c5a38b..e17bd25e57e 100644
--- a/lib/gitlab/data_builder/build.rb
+++ b/lib/gitlab/data_builder/build.rb
@@ -82,7 +82,8 @@ module Gitlab
id: runner.id,
description: runner.description,
active: runner.active?,
- is_shared: runner.instance_type?
+ is_shared: runner.instance_type?,
+ tags: runner.tags&.map(&:name)
}
end
end
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index 14facd6b1d4..3036bc57ca5 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -13,7 +13,7 @@ module Gitlab
user: pipeline.user.try(:hook_attrs),
project: pipeline.project.hook_attrs(backward: false),
commit: pipeline.commit.try(:hook_attrs),
- builds: pipeline.builds.map(&method(:build_hook_attrs))
+ builds: pipeline.builds.latest.map(&method(:build_hook_attrs))
}
end
@@ -76,7 +76,8 @@ module Gitlab
id: runner.id,
description: runner.description,
active: runner.active?,
- is_shared: runner.instance_type?
+ is_shared: runner.instance_type?,
+ tags: runner.tags&.map(&:name)
}
end
end
diff --git a/lib/gitlab/database/consistency.rb b/lib/gitlab/database/consistency.rb
new file mode 100644
index 00000000000..b7d06a26ddb
--- /dev/null
+++ b/lib/gitlab/database/consistency.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ ##
+ # This class is used to make it possible to ensure read consistency in
+ # GitLab EE without the need of overriding a lot of methods / classes /
+ # classs.
+ #
+ # This is a CE class that does nothing in CE, because database load
+ # balancing is EE-only feature, but you can still use it in CE. It will
+ # start ensuring read consistency once it is overridden in EE.
+ #
+ # Using this class in CE helps to avoid creeping discrepancy between CE /
+ # EE only to force usage of the primary database in EE.
+ #
+ class Consistency
+ ##
+ # In CE there is no database load balancing, so all reads are expected to
+ # be consistent by the ACID guarantees of a single PostgreSQL instance.
+ #
+ # This method is overridden in EE.
+ #
+ def self.with_read_consistency(&block)
+ yield
+ end
+ end
+ end
+end
+
+::Gitlab::Database::Consistency.singleton_class.prepend_if_ee('EE::Gitlab::Database::Consistency')
diff --git a/lib/gitlab/database/migration_helpers/v2.rb b/lib/gitlab/database/migration_helpers/v2.rb
new file mode 100644
index 00000000000..f20a9b30fa7
--- /dev/null
+++ b/lib/gitlab/database/migration_helpers/v2.rb
@@ -0,0 +1,219 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module MigrationHelpers
+ module V2
+ include Gitlab::Database::MigrationHelpers
+
+ # Renames a column without requiring downtime.
+ #
+ # Concurrent renames work by using database triggers to ensure both the
+ # old and new column are in sync. However, this method will _not_ remove
+ # the triggers or the old column automatically; this needs to be done
+ # manually in a post-deployment migration. This can be done using the
+ # method `cleanup_concurrent_column_rename`.
+ #
+ # table - The name of the database table containing the column.
+ # old_column - The old column name.
+ # new_column - The new column name.
+ # type - The type of the new column. If no type is given the old column's
+ # type is used.
+ # batch_column_name - option is for tables without primary key, in this
+ # case another unique integer column can be used. Example: :user_id
+ def rename_column_concurrently(table, old_column, new_column, type: nil, batch_column_name: :id)
+ setup_renamed_column(__callee__, table, old_column, new_column, type, batch_column_name)
+
+ with_lock_retries do
+ install_bidirectional_triggers(table, old_column, new_column)
+ end
+ end
+
+ # Reverses operations performed by rename_column_concurrently.
+ #
+ # This method takes care of removing previously installed triggers as well
+ # as removing the new column.
+ #
+ # table - The name of the database table.
+ # old_column - The name of the old column.
+ # new_column - The name of the new column.
+ def undo_rename_column_concurrently(table, old_column, new_column)
+ teardown_rename_mechanism(table, old_column, new_column, column_to_remove: new_column)
+ end
+
+ # Cleans up a concurrent column name.
+ #
+ # This method takes care of removing previously installed triggers as well
+ # as removing the old column.
+ #
+ # table - The name of the database table.
+ # old_column - The name of the old column.
+ # new_column - The name of the new column.
+ def cleanup_concurrent_column_rename(table, old_column, new_column)
+ teardown_rename_mechanism(table, old_column, new_column, column_to_remove: old_column)
+ end
+
+ # Reverses the operations performed by cleanup_concurrent_column_rename.
+ #
+ # This method adds back the old_column removed
+ # by cleanup_concurrent_column_rename.
+ # It also adds back the triggers that are removed
+ # by cleanup_concurrent_column_rename.
+ #
+ # table - The name of the database table containing the column.
+ # old_column - The old column name.
+ # new_column - The new column name.
+ # type - The type of the old column. If no type is given the new column's
+ # type is used.
+ # batch_column_name - option is for tables without primary key, in this
+ # case another unique integer column can be used. Example: :user_id
+ #
+ def undo_cleanup_concurrent_column_rename(table, old_column, new_column, type: nil, batch_column_name: :id)
+ setup_renamed_column(__callee__, table, new_column, old_column, type, batch_column_name)
+
+ with_lock_retries do
+ install_bidirectional_triggers(table, old_column, new_column)
+ end
+ end
+
+ private
+
+ def setup_renamed_column(calling_operation, table, old_column, new_column, type, batch_column_name)
+ if transaction_open?
+ raise "#{calling_operation} can not be run inside a transaction"
+ end
+
+ column = columns(table).find { |column| column.name == old_column.to_s }
+
+ unless column
+ raise "Column #{old_column} does not exist on #{table}"
+ end
+
+ if column.default
+ raise "#{calling_operation} does not currently support columns with default values"
+ end
+
+ unless column_exists?(table, batch_column_name)
+ raise "Column #{batch_column_name} does not exist on #{table}"
+ end
+
+ check_trigger_permissions!(table)
+
+ unless column_exists?(table, new_column)
+ create_column_from(table, old_column, new_column, type: type, batch_column_name: batch_column_name)
+ end
+ end
+
+ def teardown_rename_mechanism(table, old_column, new_column, column_to_remove:)
+ return unless column_exists?(table, column_to_remove)
+
+ with_lock_retries do
+ check_trigger_permissions!(table)
+
+ remove_bidirectional_triggers(table, old_column, new_column)
+
+ remove_column(table, column_to_remove)
+ end
+ end
+
+ def install_bidirectional_triggers(table, old_column, new_column)
+ insert_trigger_name, update_old_trigger_name, update_new_trigger_name =
+ bidirectional_trigger_names(table, old_column, new_column)
+
+ quoted_table = quote_table_name(table)
+ quoted_old = quote_column_name(old_column)
+ quoted_new = quote_column_name(new_column)
+
+ create_insert_trigger(insert_trigger_name, quoted_table, quoted_old, quoted_new)
+ create_update_trigger(update_old_trigger_name, quoted_table, quoted_new, quoted_old)
+ create_update_trigger(update_new_trigger_name, quoted_table, quoted_old, quoted_new)
+ end
+
+ def remove_bidirectional_triggers(table, old_column, new_column)
+ insert_trigger_name, update_old_trigger_name, update_new_trigger_name =
+ bidirectional_trigger_names(table, old_column, new_column)
+
+ quoted_table = quote_table_name(table)
+
+ drop_trigger(insert_trigger_name, quoted_table)
+ drop_trigger(update_old_trigger_name, quoted_table)
+ drop_trigger(update_new_trigger_name, quoted_table)
+ end
+
+ def bidirectional_trigger_names(table, old_column, new_column)
+ %w[insert update_old update_new].map do |operation|
+ 'trigger_' + Digest::SHA256.hexdigest("#{table}_#{old_column}_#{new_column}_#{operation}").first(12)
+ end
+ end
+
+ def function_name_for_trigger(trigger_name)
+ "function_for_#{trigger_name}"
+ end
+
+ def create_insert_trigger(trigger_name, quoted_table, quoted_old_column, quoted_new_column)
+ function_name = function_name_for_trigger(trigger_name)
+
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{function_name}()
+ RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ BEGIN
+ IF NEW.#{quoted_old_column} IS NULL AND NEW.#{quoted_new_column} IS NOT NULL THEN
+ NEW.#{quoted_old_column} = NEW.#{quoted_new_column};
+ END IF;
+
+ IF NEW.#{quoted_new_column} IS NULL AND NEW.#{quoted_old_column} IS NOT NULL THEN
+ NEW.#{quoted_new_column} = NEW.#{quoted_old_column};
+ END IF;
+
+ RETURN NEW;
+ END
+ $$;
+
+ DROP TRIGGER IF EXISTS #{trigger_name}
+ ON #{quoted_table};
+
+ CREATE TRIGGER #{trigger_name}
+ BEFORE INSERT ON #{quoted_table}
+ FOR EACH ROW EXECUTE FUNCTION #{function_name}();
+ SQL
+ end
+
+ def create_update_trigger(trigger_name, quoted_table, quoted_source_column, quoted_target_column)
+ function_name = function_name_for_trigger(trigger_name)
+
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{function_name}()
+ RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ BEGIN
+ NEW.#{quoted_target_column} := NEW.#{quoted_source_column};
+ RETURN NEW;
+ END
+ $$;
+
+ DROP TRIGGER IF EXISTS #{trigger_name}
+ ON #{quoted_table};
+
+ CREATE TRIGGER #{trigger_name}
+ BEFORE UPDATE OF #{quoted_source_column} ON #{quoted_table}
+ FOR EACH ROW EXECUTE FUNCTION #{function_name}();
+ SQL
+ end
+
+ def drop_trigger(trigger_name, quoted_table)
+ function_name = function_name_for_trigger(trigger_name)
+
+ execute(<<~SQL)
+ DROP TRIGGER IF EXISTS #{trigger_name}
+ ON #{quoted_table};
+
+ DROP FUNCTION IF EXISTS #{function_name};
+ SQL
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migrations/instrumentation.rb b/lib/gitlab/database/migrations/instrumentation.rb
new file mode 100644
index 00000000000..959028ce00b
--- /dev/null
+++ b/lib/gitlab/database/migrations/instrumentation.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ class Instrumentation
+ attr_reader :observations
+
+ def initialize(observers = ::Gitlab::Database::Migrations::Observers.all_observers)
+ @observers = observers
+ @observations = []
+ end
+
+ def observe(migration, &block)
+ observation = Observation.new(migration)
+ observation.success = true
+
+ exception = nil
+
+ on_each_observer { |observer| observer.before }
+
+ observation.walltime = Benchmark.realtime do
+ yield
+ rescue => e
+ exception = e
+ observation.success = false
+ end
+
+ on_each_observer { |observer| observer.after }
+ on_each_observer { |observer| observer.record(observation) }
+
+ record_observation(observation)
+
+ raise exception if exception
+
+ observation
+ end
+
+ private
+
+ attr_reader :observers
+
+ def record_observation(observation)
+ @observations << observation
+ end
+
+ def on_each_observer(&block)
+ observers.each do |observer|
+ yield observer
+ rescue => e
+ Gitlab::AppLogger.error("Migration observer #{observer.class} failed with: #{e}")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migrations/observation.rb b/lib/gitlab/database/migrations/observation.rb
new file mode 100644
index 00000000000..518c2c560d2
--- /dev/null
+++ b/lib/gitlab/database/migrations/observation.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ Observation = Struct.new(
+ :migration,
+ :walltime,
+ :success,
+ :total_database_size_change
+ )
+ end
+ end
+end
diff --git a/lib/gitlab/database/migrations/observers.rb b/lib/gitlab/database/migrations/observers.rb
new file mode 100644
index 00000000000..4b931d3c19c
--- /dev/null
+++ b/lib/gitlab/database/migrations/observers.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ module Observers
+ def self.all_observers
+ [
+ TotalDatabaseSizeChange.new
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migrations/observers/migration_observer.rb b/lib/gitlab/database/migrations/observers/migration_observer.rb
new file mode 100644
index 00000000000..9bfbf35887d
--- /dev/null
+++ b/lib/gitlab/database/migrations/observers/migration_observer.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ module Observers
+ class MigrationObserver
+ attr_reader :connection
+
+ def initialize
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def before
+ # implement in subclass
+ end
+
+ def after
+ # implement in subclass
+ end
+
+ def record(observation)
+ raise NotImplementedError, 'implement in subclass'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migrations/observers/total_database_size_change.rb b/lib/gitlab/database/migrations/observers/total_database_size_change.rb
new file mode 100644
index 00000000000..0b76b0bef5e
--- /dev/null
+++ b/lib/gitlab/database/migrations/observers/total_database_size_change.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ module Observers
+ class TotalDatabaseSizeChange < MigrationObserver
+ def before
+ @size_before = get_total_database_size
+ end
+
+ def after
+ @size_after = get_total_database_size
+ end
+
+ def record(observation)
+ return unless @size_after && @size_before
+
+ observation.total_database_size_change = @size_after - @size_before
+ end
+
+ private
+
+ def get_total_database_size
+ connection.execute("select pg_database_size(current_database())").first['pg_database_size']
+ end
+ end
+ end
+ end
+ end
+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 686dda80207..f4cf576dda7 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
@@ -164,8 +164,8 @@ module Gitlab
"this could indicate the previous partitioning migration has been rolled back."
end
- Gitlab::BackgroundMigration.steal(MIGRATION_CLASS_NAME) do |raw_arguments|
- JobArguments.from_array(raw_arguments).source_table_name == table_name.to_s
+ Gitlab::BackgroundMigration.steal(MIGRATION_CLASS_NAME) do |background_job|
+ JobArguments.from_array(background_job.args.second).source_table_name == table_name.to_s
end
primary_key = connection.primary_key(table_name)
diff --git a/lib/gitlab/diff/char_diff.rb b/lib/gitlab/diff/char_diff.rb
new file mode 100644
index 00000000000..c8bb39e9f5d
--- /dev/null
+++ b/lib/gitlab/diff/char_diff.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Diff
+ class CharDiff
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(old_string, new_string)
+ @old_string = old_string.to_s
+ @new_string = new_string.to_s
+ @changes = []
+ end
+
+ def generate_diff
+ @changes = diff_match_patch.diff_main(@old_string, @new_string)
+ diff_match_patch.diff_cleanupSemantic(@changes)
+
+ @changes
+ end
+
+ def changed_ranges(offset: 0)
+ old_diffs = []
+ new_diffs = []
+ new_pointer = old_pointer = offset
+
+ generate_diff.each do |(action, content)|
+ content_size = content.size
+
+ if action == :equal
+ new_pointer += content_size
+ old_pointer += content_size
+ end
+
+ if action == :delete
+ old_diffs << (old_pointer..(old_pointer + content_size - 1))
+ old_pointer += content_size
+ end
+
+ if action == :insert
+ new_diffs << (new_pointer..(new_pointer + content_size - 1))
+ new_pointer += content_size
+ end
+ end
+
+ [old_diffs, new_diffs]
+ end
+
+ def to_html
+ @changes.map do |op, text|
+ %{<span class="#{html_class_names(op)}">#{ERB::Util.html_escape(text)}</span>}
+ end.join.html_safe
+ end
+
+ private
+
+ def diff_match_patch
+ strong_memoize(:diff_match_patch) { DiffMatchPatch.new }
+ end
+
+ def html_class_names(operation)
+ class_names = ['idiff']
+
+ case operation
+ when :insert
+ class_names << 'addition'
+ when :delete
+ class_names << 'deletion'
+ end
+
+ class_names.join(' ')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb
index 8f4f8febec0..627abfbfe7e 100644
--- a/lib/gitlab/diff/file_collection/base.rb
+++ b/lib/gitlab/diff/file_collection/base.rb
@@ -117,7 +117,7 @@ module Gitlab
end
def sort_diffs(diffs)
- return diffs unless Feature.enabled?(:sort_diffs, project, default_enabled: false)
+ return diffs unless Feature.enabled?(:sort_diffs, project, default_enabled: :yaml)
Gitlab::Diff::FileCollectionSorter.new(diffs).sort
end
diff --git a/lib/gitlab/diff/file_collection_sorter.rb b/lib/gitlab/diff/file_collection_sorter.rb
index 94626875580..7b099543c83 100644
--- a/lib/gitlab/diff/file_collection_sorter.rb
+++ b/lib/gitlab/diff/file_collection_sorter.rb
@@ -3,6 +3,10 @@
module Gitlab
module Diff
class FileCollectionSorter
+ B_FOLLOWS_A = 1
+ A_FOLLOWS_B = -1
+ EQUIVALENT = 0
+
attr_reader :diffs
def initialize(diffs)
@@ -29,14 +33,16 @@ module Gitlab
a_part = a_parts.shift
b_part = b_parts.shift
- return 1 if a_parts.size < b_parts.size && a_parts.empty?
- return -1 if a_parts.size > b_parts.size && b_parts.empty?
+ return B_FOLLOWS_A if a_parts.size < b_parts.size && a_parts.empty?
+ return A_FOLLOWS_B if a_parts.size > b_parts.size && b_parts.empty?
comparison = a_part <=> b_part
- return comparison unless comparison == 0
+ return comparison unless comparison == EQUIVALENT
+ return compare_path_parts(a_parts, b_parts) if a_parts.any? && b_parts.any?
- compare_path_parts(a_parts, b_parts)
+ # If A and B have the same name (e.g. symlink change), they are identical so return 0
+ EQUIVALENT
end
end
end
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index a5259079345..035084d4861 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -3,12 +3,13 @@
module Gitlab
module Diff
class Highlight
- attr_reader :diff_file, :diff_lines, :raw_lines, :repository
+ attr_reader :diff_file, :diff_lines, :raw_lines, :repository, :project
delegate :old_path, :new_path, :old_sha, :new_sha, to: :diff_file, prefix: :diff
def initialize(diff_lines, repository: nil)
@repository = repository
+ @project = repository&.project
if diff_lines.is_a?(Gitlab::Diff::File)
@diff_file = diff_lines
@@ -66,7 +67,7 @@ module Gitlab
end
def inline_diffs
- @inline_diffs ||= InlineDiff.for_lines(@raw_lines)
+ @inline_diffs ||= InlineDiff.for_lines(@raw_lines, project: project)
end
def old_lines
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 90cb9c8638a..7932cd2a837 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -8,6 +8,7 @@ module Gitlab
EXPIRATION = 1.week
VERSION = 1
+ NEXT_VERSION = 2
delegate :diffable, to: :@diff_collection
delegate :diff_options, to: :@diff_collection
@@ -69,12 +70,20 @@ module Gitlab
def key
strong_memoize(:redis_key) do
- ['highlighted-diff-files', diffable.cache_key, VERSION, diff_options].join(":")
+ ['highlighted-diff-files', diffable.cache_key, version, diff_options].join(":")
end
end
private
+ def version
+ if Feature.enabled?(:improved_merge_diff_highlighting, diffable.project, default_enabled: :yaml)
+ NEXT_VERSION
+ else
+ VERSION
+ end
+ end
+
def set_highlighted_diff_lines(diff_file, content)
diff_file.highlighted_diff_lines = content.map do |line|
Gitlab::Diff::Line.safe_init_from_hash(line)
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index 5815d1bae4a..cf769262958 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -27,28 +27,19 @@ module Gitlab
@offset = offset
end
- def inline_diffs
+ def inline_diffs(project: nil)
# Skip inline diff if empty line was replaced with content
return if old_line == ""
- lcp = longest_common_prefix(old_line, new_line)
- lcs = longest_common_suffix(old_line[lcp..-1], new_line[lcp..-1])
-
- lcp += offset
- old_length = old_line.length + offset
- new_length = new_line.length + offset
-
- old_diff_range = lcp..(old_length - lcs - 1)
- new_diff_range = lcp..(new_length - lcs - 1)
-
- old_diffs = [old_diff_range] if old_diff_range.begin <= old_diff_range.end
- new_diffs = [new_diff_range] if new_diff_range.begin <= new_diff_range.end
-
- [old_diffs, new_diffs]
+ if Feature.enabled?(:improved_merge_diff_highlighting, project, default_enabled: :yaml)
+ CharDiff.new(old_line, new_line).changed_ranges(offset: offset)
+ else
+ deprecated_diff
+ end
end
class << self
- def for_lines(lines)
+ def for_lines(lines, project: nil)
changed_line_pairs = find_changed_line_pairs(lines)
inline_diffs = []
@@ -57,7 +48,7 @@ module Gitlab
old_line = lines[old_index]
new_line = lines[new_index]
- old_diffs, new_diffs = new(old_line, new_line, offset: 1).inline_diffs
+ old_diffs, new_diffs = new(old_line, new_line, offset: 1).inline_diffs(project: project)
inline_diffs[old_index] = old_diffs
inline_diffs[new_index] = new_diffs
@@ -97,6 +88,24 @@ module Gitlab
private
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/299884
+ def deprecated_diff
+ lcp = longest_common_prefix(old_line, new_line)
+ lcs = longest_common_suffix(old_line[lcp..-1], new_line[lcp..-1])
+
+ lcp += offset
+ old_length = old_line.length + offset
+ new_length = new_line.length + offset
+
+ old_diff_range = lcp..(old_length - lcs - 1)
+ new_diff_range = lcp..(new_length - lcs - 1)
+
+ old_diffs = [old_diff_range] if old_diff_range.begin <= old_diff_range.end
+ new_diffs = [new_diff_range] if new_diff_range.begin <= new_diff_range.end
+
+ [old_diffs, new_diffs]
+ end
+
def longest_common_prefix(a, b) # rubocop:disable Naming/UncommunicativeMethodParamName
max_length = [a.length, b.length].max
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index f66e8a8794f..d1dd616385d 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -35,7 +35,11 @@ module Gitlab
raise ProjectNotFound if project.nil?
create_issue!
- send_thank_you_email! if from_address
+
+ if from_address
+ add_email_participant
+ send_thank_you_email!
+ end
end
def metrics_params
@@ -146,6 +150,10 @@ module Gitlab
def author
User.support_bot
end
+
+ def add_email_participant
+ @issue.issue_email_participants.create(email: from_address)
+ end
end
end
end
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index cab21d875ab..e6f71e3ad3c 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -63,6 +63,16 @@ module Gitlab
ActionController::Base.helpers.content_tag('gl-emoji', emoji_info['moji'], options)
end
+ def custom_emoji_tag(name, image_source)
+ data = {
+ name: name
+ }
+
+ ActionController::Base.helpers.content_tag('gl-emoji', title: name, data: data) do
+ emoji_image_tag(name, image_source).html_safe
+ end
+ end
+
private
def emoji_unicode_versions_by_name
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 196203211ed..423f238a0a2 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -6,6 +6,7 @@
# Experiment options:
# - tracking_category (optional, used to set the category when tracking an experiment event)
# - use_backwards_compatible_subject_index (optional, set this to true if you need backwards compatibility -- you likely do not need this, see note in the next paragraph.)
+# - rollout_strategy: default is `:cookie` based rollout. We may also set it to `:user` based rollout
#
# Using the backwards-compatible subject index (use_backwards_compatible_subject_index option):
# This option was added when [the calculation of experimentation_subject_index was changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45733/diffs#41af4a6fa5a10c7068559ce21c5188483751d934_157_173). It is not intended to be used by new experiments, it exists merely for the segmentation integrity of in-flight experiments at the time the change was deployed. That is, we want users who were assigned to the "experimental" group or the "control" group before the change to still be in those same groups after the change. See [the original issue](https://gitlab.com/gitlab-org/gitlab/-/issues/270858) and [this related comment](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48110#note_458223745) for more information.
@@ -33,10 +34,6 @@
module Gitlab
module Experimentation
EXPERIMENTS = {
- onboarding_issues: {
- tracking_category: 'Growth::Conversion::Experiment::OnboardingIssues',
- use_backwards_compatible_subject_index: true
- },
ci_notification_dot: {
tracking_category: 'Growth::Expansion::Experiment::CiNotificationDot',
use_backwards_compatible_subject_index: true
@@ -69,13 +66,6 @@ module Gitlab
tracking_category: 'Growth::Conversion::Experiment::GroupOnlyTrials',
use_backwards_compatible_subject_index: true
},
- default_to_issues_board: {
- tracking_category: 'Growth::Conversion::Experiment::DefaultToIssuesBoard',
- use_backwards_compatible_subject_index: true
- },
- jobs_empty_state: {
- tracking_category: 'Growth::Activation::Experiment::JobsEmptyState'
- },
remove_known_trial_form_fields: {
tracking_category: 'Growth::Conversion::Experiment::RemoveKnownTrialFormFields'
},
@@ -92,19 +82,27 @@ module Gitlab
tracking_category: 'Growth::Conversion::Experiment::TrialDuringSignup'
},
ci_syntax_templates: {
- tracking_category: 'Growth::Activation::Experiment::CiSyntaxTemplates'
- },
- pipelines_empty_state: {
- tracking_category: 'Growth::Activation::Experiment::PipelinesEmptyState'
+ tracking_category: 'Growth::Activation::Experiment::CiSyntaxTemplates',
+ rollout_strategy: :user
},
invite_members_new_dropdown: {
tracking_category: 'Growth::Expansion::Experiment::InviteMembersNewDropdown'
},
show_trial_status_in_sidebar: {
- tracking_category: 'Growth::Conversion::Experiment::ShowTrialStatusInSidebar'
+ tracking_category: 'Growth::Conversion::Experiment::ShowTrialStatusInSidebar',
+ rollout_strategy: :group
},
trial_onboarding_issues: {
tracking_category: 'Growth::Conversion::Experiment::TrialOnboardingIssues'
+ },
+ learn_gitlab_a: {
+ tracking_category: 'Growth::Conversion::Experiment::LearnGitLabA'
+ },
+ learn_gitlab_b: {
+ tracking_category: 'Growth::Activation::Experiment::LearnGitLabB'
+ },
+ in_product_marketing_emails: {
+ tracking_category: 'Growth::Activation::Experiment::InProductMarketingEmails'
}
}.freeze
@@ -126,12 +124,44 @@ module Gitlab
return false if subject.blank?
return false unless active?(experiment_key)
+ log_invalid_rollout(experiment_key, subject)
+
experiment = get_experiment(experiment_key)
return false unless experiment
experiment.enabled_for_index?(index_for_subject(experiment, subject))
end
+ def rollout_strategy(experiment_key)
+ experiment = get_experiment(experiment_key)
+ return unless experiment
+
+ experiment.rollout_strategy
+ end
+
+ def log_invalid_rollout(experiment_key, subject)
+ return if valid_subject_for_rollout_strategy?(experiment_key, subject)
+
+ logger = Gitlab::ExperimentationLogger.build
+ logger.warn message: 'Subject must conform to the rollout strategy',
+ experiment_key: experiment_key,
+ subject: subject.class.to_s,
+ rollout_strategy: rollout_strategy(experiment_key)
+ end
+
+ def valid_subject_for_rollout_strategy?(experiment_key, subject)
+ case rollout_strategy(experiment_key)
+ when :user
+ subject.is_a?(User)
+ when :group
+ subject.is_a?(Group)
+ when :cookie
+ subject.nil? || subject.is_a?(String)
+ else
+ false
+ end
+ end
+
private
def index_for_subject(experiment, subject)
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
index e43f3c8c007..2b38b12c914 100644
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -40,6 +40,8 @@ module Gitlab
return true if forced_enabled?(experiment_key)
return false if dnt_enabled?
+ Experimentation.log_invalid_rollout(experiment_key, subject)
+
subject ||= fallback_experimentation_subject_index(experiment_key)
Experimentation.in_experiment_group?(experiment_key, subject: subject)
@@ -65,7 +67,9 @@ module Gitlab
return if dnt_enabled?
return unless Experimentation.active?(experiment_key) && current_user
- ::Experiment.add_user(experiment_key, tracking_group(experiment_key, nil, subject: current_user), current_user, context)
+ subject = Experimentation.rollout_strategy(experiment_key) == :cookie ? nil : current_user
+
+ ::Experiment.add_user(experiment_key, tracking_group(experiment_key, nil, subject: subject), current_user, context)
end
def record_experiment_conversion_event(experiment_key)
@@ -136,7 +140,7 @@ module Gitlab
cookies[:force_experiment].to_s.split(',').any? { |experiment| experiment.strip == experiment_key.to_s }
end
- def tracking_label(subject)
+ def tracking_label(subject = nil)
return experimentation_subject_id if subject.blank?
if subject.respond_to?(:to_global_id)
diff --git a/lib/gitlab/experimentation/experiment.rb b/lib/gitlab/experimentation/experiment.rb
index 36cd673a38f..17dda45f5b7 100644
--- a/lib/gitlab/experimentation/experiment.rb
+++ b/lib/gitlab/experimentation/experiment.rb
@@ -5,12 +5,13 @@ module Gitlab
class Experiment
FEATURE_FLAG_SUFFIX = "_experiment_percentage"
- attr_reader :key, :tracking_category, :use_backwards_compatible_subject_index
+ attr_reader :key, :tracking_category, :use_backwards_compatible_subject_index, :rollout_strategy
def initialize(key, **params)
@key = key
@tracking_category = params[:tracking_category]
@use_backwards_compatible_subject_index = params[:use_backwards_compatible_subject_index]
+ @rollout_strategy = params[:rollout_strategy] || :cookie
end
def active?
diff --git a/lib/gitlab/experimentation_logger.rb b/lib/gitlab/experimentation_logger.rb
new file mode 100644
index 00000000000..ba1b60d6b4c
--- /dev/null
+++ b/lib/gitlab/experimentation_logger.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class ExperimentationLogger < ::Gitlab::JsonLogger
+ def self.file_name_noext
+ 'experimentation_json'
+ end
+ end
+end
diff --git a/lib/gitlab/faraday.rb b/lib/gitlab/faraday.rb
deleted file mode 100644
index f92392ec1a9..00000000000
--- a/lib/gitlab/faraday.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Faraday
- ::Faraday::Request.register_middleware(gitlab_error_callback: -> { ::Gitlab::Faraday::ErrorCallback })
- end
-end
diff --git a/lib/gitlab/file_type_detection.rb b/lib/gitlab/file_type_detection.rb
index 38ccd2c38a9..ed25310b5cf 100644
--- a/lib/gitlab/file_type_detection.rb
+++ b/lib/gitlab/file_type_detection.rb
@@ -19,7 +19,7 @@
# `Content-Type` and `Content-Disposition` to the one we get from the detection.
module Gitlab
module FileTypeDetection
- SAFE_IMAGE_EXT = %w[png jpg jpeg gif bmp tiff ico].freeze
+ SAFE_IMAGE_EXT = %w[png jpg jpeg gif bmp tiff ico webp].freeze
SAFE_IMAGE_FOR_SCALING_EXT = %w[png jpg jpeg].freeze
PDF_EXT = 'pdf'
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 0bc7ecccf5e..35c3dc5b0b3 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -16,7 +16,7 @@ module Gitlab
SERIALIZE_KEYS = [
:id, :message, :parent_ids,
:authored_date, :author_name, :author_email,
- :committed_date, :committer_name, :committer_email
+ :committed_date, :committer_name, :committer_email, :trailers
].freeze
attr_accessor(*SERIALIZE_KEYS)
@@ -389,6 +389,7 @@ module Gitlab
@committer_name = commit.committer.name.dup
@committer_email = commit.committer.email.dup
@parent_ids = Array(commit.parent_ids)
+ @trailers = Hash[commit.trailers.map { |t| [t.key, t.value] }]
end
# Gitaly provides a UNIX timestamp in author.date.seconds, and a timezone
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index 209917073c7..53df0b7b389 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -244,6 +244,8 @@ module Gitlab
def prune_diff_if_eligible
if too_large?
+ ::Gitlab::Metrics.add_event(:patch_hard_limit_bytes_hit)
+
too_large!
elsif collapsed?
collapse!
diff --git a/lib/gitlab/git/push.rb b/lib/gitlab/git/push.rb
index b6577ba17f1..3d533a5185f 100644
--- a/lib/gitlab/git/push.rb
+++ b/lib/gitlab/git/push.rb
@@ -33,7 +33,9 @@ module Gitlab
end
def force_push?
- Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
+ strong_memoize(:force_push) do
+ Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
+ end
end
def branch_push?
diff --git a/lib/gitlab/git/rugged_impl/commit.rb b/lib/gitlab/git/rugged_impl/commit.rb
index 0eff35ab1c4..0607b151de2 100644
--- a/lib/gitlab/git/rugged_impl/commit.rb
+++ b/lib/gitlab/git/rugged_impl/commit.rb
@@ -103,6 +103,7 @@ module Gitlab
@committer_name = committer[:name]
@committer_email = committer[:email]
@parent_ids = commit.parents.map(&:oid)
+ @trailers = Hash[commit.trailers]
end
end
end
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index 11919be594d..55ff3c6caf1 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -151,6 +151,8 @@ module Gitlab
end
def gitaly_find_page(title:, version: nil, dir: nil)
+ return unless title.present?
+
wiki_page, version = gitaly_wiki_client.find_page(title: title, version: version, dir: dir)
return unless wiki_page
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index e0b145f69aa..c5ca46827cb 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -77,7 +77,6 @@ module Gitlab
check_authentication_abilities!
check_command_disabled!
check_command_existence!
- check_otp_session!
custom_action = check_custom_action
return custom_action if custom_action
@@ -255,31 +254,6 @@ module Gitlab
end
end
- def check_otp_session!
- return unless ssh?
- return if !key? || deploy_key?
- return unless Feature.enabled?(:two_factor_for_cli)
- return unless user.two_factor_enabled?
-
- if ::Gitlab::Auth::Otp::SessionEnforcer.new(actor).access_restricted?
- message = "OTP verification is required to access the repository.\n\n"\
- " Use: #{build_ssh_otp_verify_command}"
-
- raise ForbiddenError, message
- end
- end
-
- def build_ssh_otp_verify_command
- user = "#{Gitlab.config.gitlab_shell.ssh_user}@" unless Gitlab.config.gitlab_shell.ssh_user.empty?
- user_host = "#{user}#{Gitlab.config.gitlab_shell.ssh_host}"
-
- if Gitlab.config.gitlab_shell.ssh_port != 22
- "ssh #{user_host} -p #{Gitlab.config.gitlab_shell.ssh_port} 2fa_verify"
- else
- "ssh #{user_host} 2fa_verify"
- end
- end
-
def check_db_accessibility!
return unless receive_pack?
@@ -345,10 +319,8 @@ module Gitlab
end
def check_change_access!
- return if deploy_key? && !deploy_keys_on_protected_branches_enabled?
-
if changes == ANY
- can_push = (deploy_key? && deploy_keys_on_protected_branches_enabled?) ||
+ can_push = deploy_key? ||
user_can_push? ||
project&.any_branch_allows_collaboration?(user_access.user)
@@ -479,7 +451,7 @@ module Gitlab
CiAccess.new
elsif user && request_from_ci_build?
BuildAccess.new(user, container: container)
- elsif deploy_key? && deploy_keys_on_protected_branches_enabled?
+ elsif deploy_key?
DeployKeyAccess.new(deploy_key, container: container)
else
UserAccess.new(user, container: container)
@@ -558,10 +530,6 @@ module Gitlab
def size_checker
container.repository_size_checker
end
-
- def deploy_keys_on_protected_branches_enabled?
- Feature.enabled?(:deploy_keys_on_protected_branches, project)
- end
end
end
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 31734abe77f..3c7fa88977e 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -203,7 +203,7 @@ module Gitlab
def self.authorization_token(storage)
token = token(storage).to_s
issued_at = real_time.to_i.to_s
- hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, token, issued_at)
+ hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA256'), token, issued_at)
"v2.#{hmac}.#{issued_at}"
end
@@ -226,6 +226,7 @@ module Gitlab
metadata['username'] = context_data['meta.user'] if context_data&.fetch('meta.user', nil)
metadata['remote_ip'] = context_data['meta.remote_ip'] if context_data&.fetch('meta.remote_ip', nil)
metadata.merge!(Feature::Gitaly.server_feature_flags)
+ metadata.merge!(route_to_primary)
deadline_info = request_deadline(timeout)
metadata.merge!(deadline_info.slice(:deadline_type))
@@ -233,6 +234,26 @@ module Gitlab
{ metadata: metadata, deadline: deadline_info[:deadline] }
end
+ # Gitlab::Git::HookEnv will set the :gitlab_git_env variable in case we're
+ # running in the context of a Gitaly hook call, which may make use of
+ # quarantined object directories. We thus need to pass along the path of
+ # the quarantined object directory to Gitaly, otherwise it won't be able to
+ # find these quarantined objects. Given that the quarantine directory is
+ # generated with a random name, they'll have different names when multiple
+ # Gitaly nodes take part in a single transaction. As a result, we are
+ # forced to route all requests to the primary node which has injected the
+ # quarantine object directory to us.
+ def self.route_to_primary
+ return {} unless Gitlab::SafeRequestStore.active?
+
+ return {} unless Gitlab::SafeRequestStore[:gitlab_git_env]
+
+ return {} if Gitlab::SafeRequestStore[:gitlab_git_env].empty?
+
+ { 'gitaly-route-repository-accessor-policy' => 'primary-only' }
+ end
+ private_class_method :route_to_primary
+
def self.request_deadline(timeout)
# timeout being 0 means the request is allowed to run indefinitely.
# We can't allow that inside a request, but this won't count towards Gitaly
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index ea940150941..ef5221a8042 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -335,7 +335,8 @@ module Gitlab
all: !!options[:all],
first_parent: !!options[:first_parent],
global_options: parse_global_options!(options),
- disable_walk: true # This option is deprecated. The 'walk' implementation is being removed.
+ disable_walk: true, # This option is deprecated. The 'walk' implementation is being removed.
+ trailers: options[:trailers]
)
request.after = GitalyClient.timestamp(options[:after]) if options[:after]
request.before = GitalyClient.timestamp(options[:before]) if options[:before]
diff --git a/lib/gitlab/gitaly_client/conflicts_service.rb b/lib/gitlab/gitaly_client/conflicts_service.rb
index 6f08dcc69b6..fc40c23611a 100644
--- a/lib/gitlab/gitaly_client/conflicts_service.rb
+++ b/lib/gitlab/gitaly_client/conflicts_service.rb
@@ -67,7 +67,8 @@ module Gitlab
source_branch: encode_binary(source_branch),
target_branch: encode_binary(target_branch),
commit_message: encode_binary(resolution.commit_message),
- user: Gitlab::Git::User.from_gitlab(resolution.user).to_gitaly
+ user: Gitlab::Git::User.from_gitlab(resolution.user).to_gitaly,
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
end
end
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 4850d646de4..6f302b2c4e7 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -32,7 +32,8 @@ module Gitlab
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
tag_name: encode_binary(tag_name),
target_revision: encode_binary(target),
- message: encode_binary(message.to_s)
+ message: encode_binary(message.to_s),
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
response = GitalyClient.call(@repository.storage, :operation_service, :user_create_tag, request, timeout: GitalyClient.long_timeout)
@@ -111,7 +112,8 @@ module Gitlab
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
message: encode_binary(message),
first_parent_ref: encode_binary(first_parent_ref),
- allow_conflicts: allow_conflicts
+ allow_conflicts: allow_conflicts,
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
response = GitalyClient.call(@repository.storage, :operation_service,
@@ -140,7 +142,8 @@ module Gitlab
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
commit_id: source_sha,
branch: encode_binary(target_branch),
- message: encode_binary(message)
+ message: encode_binary(message),
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
)
@@ -234,7 +237,8 @@ module Gitlab
branch_sha: branch_sha,
remote_repository: remote_repository.gitaly_repository,
remote_branch: encode_binary(remote_branch),
- git_push_options: push_options
+ git_push_options: push_options,
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
)
)
@@ -255,7 +259,7 @@ module Gitlab
request_enum.close
end
- def user_squash(user, squash_id, start_sha, end_sha, author, message)
+ def user_squash(user, squash_id, start_sha, end_sha, author, message, time = Time.now.utc)
request = Gitaly::UserSquashRequest.new(
repository: @gitaly_repo,
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
@@ -263,7 +267,8 @@ module Gitlab
start_sha: start_sha,
end_sha: end_sha,
author: Gitlab::Git::User.from_gitlab(author).to_gitaly,
- commit_message: encode_binary(message)
+ commit_message: encode_binary(message),
+ timestamp: Google::Protobuf::Timestamp.new(seconds: time.to_i)
)
response = GitalyClient.call(
@@ -288,7 +293,8 @@ module Gitlab
commit_sha: commit_sha,
branch: encode_binary(branch),
submodule: encode_binary(submodule),
- commit_message: encode_binary(message)
+ commit_message: encode_binary(message),
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
response = GitalyClient.call(
@@ -357,7 +363,8 @@ module Gitlab
header = Gitaly::UserApplyPatchRequest::Header.new(
repository: @gitaly_repo,
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
- target_branch: encode_binary(branch_name)
+ target_branch: encode_binary(branch_name),
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
reader = binary_io(patches)
@@ -446,7 +453,8 @@ module Gitlab
start_branch_name: encode_binary(start_branch_name),
start_repository: start_repository.gitaly_repository,
force: force,
- start_sha: encode_binary(start_sha)
+ start_sha: encode_binary(start_sha),
+ timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
)
end
# rubocop:enable Metrics/ParameterLists
diff --git a/lib/gitlab/gitaly_client/storage_settings.rb b/lib/gitlab/gitaly_client/storage_settings.rb
index 43848772947..5e50ac72965 100644
--- a/lib/gitlab/gitaly_client/storage_settings.rb
+++ b/lib/gitlab/gitaly_client/storage_settings.rb
@@ -23,7 +23,6 @@ module Gitlab
MUTEX = Mutex.new
- DISK_ACCESS_DENIED_FLAG = :deny_disk_access
ALLOW_KEY = :allow_disk_access
# If your code needs this method then your code needs to be fixed.
@@ -34,7 +33,7 @@ module Gitlab
def self.disk_access_denied?
return false if rugged_enabled?
- !temporarily_allowed?(ALLOW_KEY) && Feature::Gitaly.enabled?(DISK_ACCESS_DENIED_FLAG)
+ !temporarily_allowed?(ALLOW_KEY)
rescue
false # Err on the side of caution, don't break gitlab for people
end
@@ -62,7 +61,7 @@ module Gitlab
def legacy_disk_path
if self.class.disk_access_denied?
- raise DirectPathAccessError, "git disk access denied via the gitaly_#{DISK_ACCESS_DENIED_FLAG} feature"
+ raise DirectPathAccessError, "git disk access denied"
end
@legacy_disk_path
diff --git a/lib/gitlab/global_id.rb b/lib/gitlab/global_id.rb
index e8a6006dce1..7e9412236cf 100644
--- a/lib/gitlab/global_id.rb
+++ b/lib/gitlab/global_id.rb
@@ -19,8 +19,8 @@ module Gitlab
value
when URI::GID
GlobalID.new(value)
- when Integer
- raise CoerceError, 'Cannot coerce Integer' unless model_name.present?
+ when Integer, String
+ raise CoerceError, "Cannot coerce #{value.class}" unless model_name.present?
GlobalID.new(::Gitlab::GlobalId.build(model_name: model_name, id: value))
else
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 0ba535b500e..3dd317c5a64 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -13,7 +13,6 @@ module Gitlab
gon.asset_host = ActionController::Base.asset_host
gon.webpack_public_path = webpack_public_path
gon.relative_url_root = Gitlab.config.gitlab.relative_url_root
- gon.shortcuts_path = Gitlab::Routing.url_helpers.help_page_path('shortcuts')
gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class
if Gitlab.config.sentry.enabled
@@ -33,6 +32,7 @@ module Gitlab
gon.suggested_label_colors = LabelsHelper.suggested_colors
gon.first_day_of_week = current_user&.first_day_of_week || Gitlab::CurrentSettings.first_day_of_week
gon.ee = Gitlab.ee?
+ gon.dot_com = Gitlab.com?
if current_user
gon.current_user_id = current_user.id
@@ -43,11 +43,9 @@ module Gitlab
# Initialize gon.features with any flags that should be
# made globally available to the frontend
- push_frontend_feature_flag(:webperf_experiment, default_enabled: false)
push_frontend_feature_flag(:snippets_binary_blob, default_enabled: false)
push_frontend_feature_flag(:usage_data_api, default_enabled: true)
push_frontend_feature_flag(:security_auto_fix, default_enabled: false)
- push_frontend_feature_flag(:gl_tooltips, default_enabled: :yaml)
end
# Exposes the state of a feature flag to the frontend code.
diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml
index 8f5a1788fa5..9dfb9b090a8 100644
--- a/lib/gitlab/graphql/docs/templates/default.md.haml
+++ b/lib/gitlab/graphql/docs/templates/default.md.haml
@@ -16,6 +16,8 @@
Fields that are deprecated are marked with **{warning-solid}**.
Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
in [Removed Items](../removed_items.md).
+
+ <!-- vale gitlab.Spelling = NO -->
\
:plain
diff --git a/lib/gitlab/graphql/pagination/connections.rb b/lib/gitlab/graphql/pagination/connections.rb
index 54a84be4274..965c01dd02f 100644
--- a/lib/gitlab/graphql/pagination/connections.rb
+++ b/lib/gitlab/graphql/pagination/connections.rb
@@ -6,6 +6,10 @@ module Gitlab
module Connections
def self.use(schema)
schema.connections.add(
+ ::Gitlab::Graphql::Pagination::OffsetPaginatedRelation,
+ ::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
+
+ schema.connections.add(
ActiveRecord::Relation,
Gitlab::Graphql::Pagination::Keyset::Connection)
diff --git a/lib/gitlab/graphql/pagination/offset_paginated_relation.rb b/lib/gitlab/graphql/pagination/offset_paginated_relation.rb
new file mode 100644
index 00000000000..8a8c6e5db50
--- /dev/null
+++ b/lib/gitlab/graphql/pagination/offset_paginated_relation.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+# Marker class to enable us to choose the correct
+# connection type during resolution
+module Gitlab
+ module Graphql
+ module Pagination
+ class OffsetPaginatedRelation < SimpleDelegator
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/queries.rb b/lib/gitlab/graphql/queries.rb
index de971743490..fcf293fb13e 100644
--- a/lib/gitlab/graphql/queries.rb
+++ b/lib/gitlab/graphql/queries.rb
@@ -145,6 +145,20 @@ module Gitlab
return redacted if printer.fields_printed > 0
end
+ def complexity(schema)
+ # See BaseResolver::resolver_complexity
+ # we want to see the max possible complexity.
+ fake_args = Struct
+ .new(:if, :keyword_arguments)
+ .new(nil, { sort: true, search: true })
+
+ query = GraphQL::Query.new(schema, text)
+ # We have no arguments, so fake them.
+ query.define_singleton_method(:arguments_for) { |_x, _y| fake_args }
+
+ GraphQL::Analysis::AST.analyze_query(query, [GraphQL::Analysis::AST::QueryComplexity]).first
+ end
+
def query
return @query if defined?(@query)
diff --git a/lib/gitlab/health_checks/base_abstract_check.rb b/lib/gitlab/health_checks/base_abstract_check.rb
index 7e1c5331b07..2eef359cc6e 100644
--- a/lib/gitlab/health_checks/base_abstract_check.rb
+++ b/lib/gitlab/health_checks/base_abstract_check.rb
@@ -11,6 +11,10 @@ module Gitlab
name.sub(/_check$/, '').capitalize
end
+ def available?
+ true
+ end
+
def readiness
raise NotImplementedError
end
diff --git a/lib/gitlab/health_checks/master_check.rb b/lib/gitlab/health_checks/master_check.rb
index 057bce84ddd..b2c3695e6d9 100644
--- a/lib/gitlab/health_checks/master_check.rb
+++ b/lib/gitlab/health_checks/master_check.rb
@@ -8,7 +8,16 @@ module Gitlab
extend SimpleAbstractCheck
class << self
+ extend ::Gitlab::Utils::Override
+
+ override :available?
+ def available?
+ Gitlab::Runtime.puma_in_clustered_mode?
+ end
+
def register_master
+ return unless available?
+
# when we fork, we pass the read pipe to child
# child can then react on whether the other end
# of pipe is still available
@@ -16,11 +25,15 @@ module Gitlab
end
def finish_master
+ return unless available?
+
close_read
close_write
end
def register_worker
+ return unless available?
+
# fork needs to close the pipe
close_write
end
diff --git a/lib/gitlab/health_checks/probes/collection.rb b/lib/gitlab/health_checks/probes/collection.rb
index 08b6d82291e..b34e4273d85 100644
--- a/lib/gitlab/health_checks/probes/collection.rb
+++ b/lib/gitlab/health_checks/probes/collection.rb
@@ -48,6 +48,7 @@ module Gitlab
def probe_readiness
checks
+ .select(&:available?)
.flat_map(&:readiness)
.compact
.group_by(&:name)
diff --git a/lib/gitlab/hook_data/base_builder.rb b/lib/gitlab/hook_data/base_builder.rb
index 434d30d9717..e5bae61ae4e 100644
--- a/lib/gitlab/hook_data/base_builder.rb
+++ b/lib/gitlab/hook_data/base_builder.rb
@@ -21,6 +21,12 @@ module Gitlab
private
+ def event_data(event)
+ event_name = "#{object.class.name.downcase}_#{event}"
+
+ { event_name: event_name }
+ end
+
def timestamps_data
{
created_at: object.created_at&.xmlschema,
diff --git a/lib/gitlab/hook_data/group_builder.rb b/lib/gitlab/hook_data/group_builder.rb
new file mode 100644
index 00000000000..5f76144eb83
--- /dev/null
+++ b/lib/gitlab/hook_data/group_builder.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HookData
+ class GroupBuilder < BaseBuilder
+ alias_method :group, :object
+
+ # Sample data
+ # {
+ # :created_at=>"2021-01-20T09:40:12Z",
+ # :updated_at=>"2021-01-20T09:40:12Z",
+ # :event_name=>"group_rename",
+ # :name=>"group1",
+ # :path=>"group1",
+ # :full_path=>"group1",
+ # :group_id=>1,
+ # :old_path=>"old-path",
+ # :old_full_path=>"old-path"
+ # }
+
+ def build(event)
+ [
+ timestamps_data,
+ event_data(event),
+ group_data,
+ event_specific_group_data(event)
+ ].reduce(:merge)
+ end
+
+ private
+
+ def group_data
+ {
+ name: group.name,
+ path: group.path,
+ full_path: group.full_path,
+ group_id: group.id
+ }
+ end
+
+ def event_specific_group_data(event)
+ return {} unless event == :rename
+
+ {
+ old_path: group.path_before_last_save,
+ old_full_path: group.full_path_before_last_save
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/hook_data/subgroup_builder.rb b/lib/gitlab/hook_data/subgroup_builder.rb
new file mode 100644
index 00000000000..a620219675a
--- /dev/null
+++ b/lib/gitlab/hook_data/subgroup_builder.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HookData
+ class SubgroupBuilder < GroupBuilder
+ # Sample data
+ # {
+ # :created_at=>"2021-01-20T09:40:12Z",
+ # :updated_at=>"2021-01-20T09:40:12Z",
+ # :event_name=>"subgroup_create",
+ # :name=>"subgroup1",
+ # :path=>"subgroup1",
+ # :full_path=>"group1/subgroup1",
+ # :group_id=>10,
+ # :parent_group_id=>7,
+ # :parent_name=>group1,
+ # :parent_path=>group1,
+ # :parent_full_path=>group1
+ # }
+
+ private
+
+ def event_data(event)
+ event_name = case event
+ when :create
+ 'subgroup_create'
+ when :destroy
+ 'subgroup_destroy'
+ end
+
+ { event_name: event_name }
+ end
+
+ def group_data
+ parent = group.parent
+
+ super.merge(
+ parent_group_id: parent.id,
+ parent_name: parent.name,
+ parent_path: parent.path,
+ parent_full_path: parent.full_path
+ )
+ end
+
+ def event_specific_group_data(event)
+ {}
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb
index 921072a4970..c4867746b0f 100644
--- a/lib/gitlab/import_export.rb
+++ b/lib/gitlab/import_export.rb
@@ -103,3 +103,7 @@ module Gitlab
end
Gitlab::ImportExport.prepend_if_ee('EE::Gitlab::ImportExport')
+
+# The methods in `Gitlab::ImportExport::GroupHelper` should be available as both
+# instance and class methods.
+Gitlab::ImportExport.extend_if_ee('Gitlab::ImportExport::GroupHelper')
diff --git a/lib/gitlab/import_export/decompressed_archive_size_validator.rb b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
index 219821a7150..37f1bdc3009 100644
--- a/lib/gitlab/import_export/decompressed_archive_size_validator.rb
+++ b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
@@ -1,24 +1,16 @@
# frozen_string_literal: true
-require 'zlib'
-
module Gitlab
module ImportExport
class DecompressedArchiveSizeValidator
include Gitlab::Utils::StrongMemoize
DEFAULT_MAX_BYTES = 10.gigabytes.freeze
- CHUNK_SIZE = 4096.freeze
-
- attr_reader :error
+ TIMEOUT_LIMIT = 60.seconds
def initialize(archive_path:, max_bytes: self.class.max_bytes)
@archive_path = archive_path
@max_bytes = max_bytes
- @bytes_read = 0
- @total_reads = 0
- @denominator = 5
- @error = nil
end
def valid?
@@ -31,59 +23,62 @@ module Gitlab
DEFAULT_MAX_BYTES
end
- def archive_file
- @archive_file ||= File.open(@archive_path)
- end
-
private
def validate
- until archive_file.eof?
- compressed_chunk = archive_file.read(CHUNK_SIZE)
+ pgrp = nil
+ valid_archive = true
- inflate_stream.inflate(compressed_chunk) do |chunk|
- @bytes_read += chunk.size
- @total_reads += 1
- end
+ Timeout.timeout(TIMEOUT_LIMIT) do
+ stdin, stdout, stderr, wait_thr = Open3.popen3(command, pgroup: true)
+ stdin.close
+ pgrp = Process.getpgid(wait_thr[:pid])
+ status = wait_thr.value
- # Start garbage collection every 5 reads in order
- # to prevent memory bloat during archive decompression
- GC.start if gc_start?
+ if status.success?
+ result = stdout.readline
- if @bytes_read > @max_bytes
- @error = error_message
+ if result.to_i > @max_bytes
+ valid_archive = false
- return false
+ log_error('Decompressed archive size limit reached')
+ end
+ else
+ valid_archive = false
+
+ log_error(stderr.readline)
end
+
+ ensure
+ stdout.close
+ stderr.close
end
- true
- rescue => e
- @error = error_message
+ valid_archive
+ rescue Timeout::Error
+ log_error('Timeout reached during archive decompression')
- Gitlab::ErrorTracking.track_exception(e)
-
- Gitlab::Import::Logger.info(
- message: @error,
- error: e.message
- )
+ Process.kill(-1, pgrp) if pgrp
false
- ensure
- inflate_stream.close
- archive_file.close
- end
+ rescue => e
+ log_error(e.message)
- def inflate_stream
- @inflate_stream ||= Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
+ Process.kill(-1, pgrp) if pgrp
+
+ false
end
- def gc_start?
- @total_reads % @denominator == 0
+ def command
+ "gzip -dc #{@archive_path} | wc -c"
end
- def error_message
- _('Decompressed archive size validation failed.')
+ def log_error(error)
+ Gitlab::Import::Logger.info(
+ message: error,
+ import_upload_archive_path: @archive_path,
+ import_upload_archive_size: File.size(@archive_path)
+ )
end
end
end
diff --git a/lib/gitlab/import_export/design_repo_restorer.rb b/lib/gitlab/import_export/design_repo_restorer.rb
index a702c58a7c2..e093b4b0697 100644
--- a/lib/gitlab/import_export/design_repo_restorer.rb
+++ b/lib/gitlab/import_export/design_repo_restorer.rb
@@ -3,10 +3,11 @@
module Gitlab
module ImportExport
class DesignRepoRestorer < RepoRestorer
- def initialize(project:, shared:, path_to_bundle:)
- super(project: project, shared: shared, path_to_bundle: path_to_bundle)
+ extend ::Gitlab::Utils::Override
- @repository = project.design_repository
+ override :repository
+ def repository
+ @repository ||= importable.design_repository
end
# `restore` method is handled in super class
diff --git a/lib/gitlab/import_export/design_repo_saver.rb b/lib/gitlab/import_export/design_repo_saver.rb
index db9ebee6a13..b400aedc205 100644
--- a/lib/gitlab/import_export/design_repo_saver.rb
+++ b/lib/gitlab/import_export/design_repo_saver.rb
@@ -3,16 +3,18 @@
module Gitlab
module ImportExport
class DesignRepoSaver < RepoSaver
- def save
- @repository = project.design_repository
+ extend ::Gitlab::Utils::Override
- super
+ override :repository
+ def repository
+ @repository ||= exportable.design_repository
end
private
- def bundle_full_path
- File.join(shared.export_path, ::Gitlab::ImportExport.design_repo_bundle_filename)
+ override :bundle_filename
+ def bundle_filename
+ ::Gitlab::ImportExport.design_repo_bundle_filename
end
end
end
diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb
index 5a6f6e017d2..51d58aae54f 100644
--- a/lib/gitlab/import_export/file_importer.rb
+++ b/lib/gitlab/import_export/file_importer.rb
@@ -87,7 +87,7 @@ module Gitlab
end
def validate_decompressed_archive_size
- raise ImporterError.new(size_validator.error) unless size_validator.valid?
+ raise ImporterError.new(_('Decompressed archive size validation failed.')) unless size_validator.valid?
end
def size_validator
diff --git a/lib/gitlab/import_export/group/tree_restorer.rb b/lib/gitlab/import_export/group/tree_restorer.rb
index dfe27118d66..925ab6680ba 100644
--- a/lib/gitlab/import_export/group/tree_restorer.rb
+++ b/lib/gitlab/import_export/group/tree_restorer.rb
@@ -6,7 +6,7 @@ module Gitlab
class TreeRestorer
include Gitlab::Utils::StrongMemoize
- attr_reader :user, :shared
+ attr_reader :user, :shared, :groups_mapping
def initialize(user:, shared:, group:)
@user = user
diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb
index 789249c7d91..390909efe36 100644
--- a/lib/gitlab/import_export/importer.rb
+++ b/lib/gitlab/import_export/importer.rb
@@ -75,19 +75,19 @@ module Gitlab
def repo_restorer
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: repo_path,
shared: shared,
- project: project)
+ importable: project)
end
def wiki_restorer
Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: wiki_repo_path,
shared: shared,
- project: ProjectWiki.new(project))
+ importable: ProjectWiki.new(project))
end
def design_repo_restorer
Gitlab::ImportExport::DesignRepoRestorer.new(path_to_bundle: design_repo_path,
shared: shared,
- project: project)
+ importable: project)
end
def uploads_restorer
diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb
index f808e30bd6e..8af7b68d78e 100644
--- a/lib/gitlab/import_export/repo_restorer.rb
+++ b/lib/gitlab/import_export/repo_restorer.rb
@@ -5,10 +5,12 @@ module Gitlab
class RepoRestorer
include Gitlab::ImportExport::CommandLineUtil
- def initialize(project:, shared:, path_to_bundle:)
- @repository = project.repository
+ attr_reader :importable
+
+ def initialize(importable:, shared:, path_to_bundle:)
@path_to_bundle = path_to_bundle
@shared = shared
+ @importable = importable
end
def restore
@@ -17,14 +19,25 @@ module Gitlab
ensure_repository_does_not_exist!
repository.create_from_bundle(path_to_bundle)
+ update_importable_repository_info
+
+ true
rescue => e
shared.error(e)
false
end
+ def repository
+ @repository ||= importable.repository
+ end
+
private
- attr_accessor :repository, :path_to_bundle, :shared
+ attr_accessor :path_to_bundle, :shared
+
+ def update_importable_repository_info
+ # No-op. Overridden in EE
+ end
def ensure_repository_does_not_exist!
if repository.exists?
@@ -38,3 +51,5 @@ module Gitlab
end
end
end
+
+Gitlab::ImportExport::RepoRestorer.prepend_if_ee('EE::Gitlab::ImportExport::RepoRestorer')
diff --git a/lib/gitlab/import_export/repo_saver.rb b/lib/gitlab/import_export/repo_saver.rb
index 898cd7898ba..0fdd0722b65 100644
--- a/lib/gitlab/import_export/repo_saver.rb
+++ b/lib/gitlab/import_export/repo_saver.rb
@@ -5,12 +5,11 @@ module Gitlab
class RepoSaver
include Gitlab::ImportExport::CommandLineUtil
- attr_reader :project, :repository, :shared
+ attr_reader :exportable, :shared
- def initialize(project:, shared:)
- @project = project
+ def initialize(exportable:, shared:)
+ @exportable = exportable
@shared = shared
- @repository = @project.repository
end
def save
@@ -19,6 +18,10 @@ module Gitlab
bundle_to_disk
end
+ def repository
+ @repository ||= @exportable.repository
+ end
+
private
def repository_exists?
@@ -26,11 +29,16 @@ module Gitlab
end
def bundle_full_path
- File.join(shared.export_path, ImportExport.project_bundle_filename)
+ File.join(shared.export_path, bundle_filename)
+ end
+
+ def bundle_filename
+ ::Gitlab::ImportExport.project_bundle_filename
end
def bundle_to_disk
- mkdir_p(shared.export_path)
+ mkdir_p(File.dirname(bundle_full_path))
+
repository.bundle_to_disk(bundle_full_path)
rescue => e
shared.error(e)
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index 045ba2495bf..bb2bbda4bd6 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -31,7 +31,7 @@ module Gitlab
@shared.error(e)
false
ensure
- remove_base_tmp_dir
+ remove_archive_tmp_dir
end
private
@@ -40,8 +40,8 @@ module Gitlab
tar_czf(archive: archive_file, dir: @shared.export_path)
end
- def remove_base_tmp_dir
- FileUtils.rm_rf(@shared.base_path)
+ def remove_archive_tmp_dir
+ FileUtils.rm_rf(@shared.archive_path)
end
def archive_file
diff --git a/lib/gitlab/import_export/wiki_repo_saver.rb b/lib/gitlab/import_export/wiki_repo_saver.rb
index 93ae6f6b02a..4b1cf4915e4 100644
--- a/lib/gitlab/import_export/wiki_repo_saver.rb
+++ b/lib/gitlab/import_export/wiki_repo_saver.rb
@@ -3,18 +3,21 @@
module Gitlab
module ImportExport
class WikiRepoSaver < RepoSaver
- def save
- wiki = ProjectWiki.new(project)
- @repository = wiki.repository
+ extend ::Gitlab::Utils::Override
- super
+ override :repository
+ def repository
+ @repository ||= exportable.wiki.repository
end
private
- def bundle_full_path
- File.join(shared.export_path, ImportExport.wiki_repo_bundle_filename)
+ override :bundle_filename
+ def bundle_filename
+ ::Gitlab::ImportExport.wiki_repo_bundle_filename
end
end
end
end
+
+Gitlab::ImportExport::WikiRepoSaver.prepend_if_ee('EE::Gitlab::ImportExport::WikiRepoSaver')
diff --git a/lib/gitlab/instrumentation/elasticsearch_transport.rb b/lib/gitlab/instrumentation/elasticsearch_transport.rb
index 56179eda22d..4bef043ecb0 100644
--- a/lib/gitlab/instrumentation/elasticsearch_transport.rb
+++ b/lib/gitlab/instrumentation/elasticsearch_transport.rb
@@ -9,12 +9,17 @@ module Gitlab
start = Time.now
headers = (headers || {})
.reverse_merge({ 'X-Opaque-Id': Labkit::Correlation::CorrelationId.current_or_new_id })
- super
+ response = super
ensure
if ::Gitlab::SafeRequestStore.active?
duration = (Time.now - start)
::Gitlab::Instrumentation::ElasticsearchTransport.increment_request_count
+
+ if response&.body && response.body.is_a?(Hash) && response.body['timed_out']
+ ::Gitlab::Instrumentation::ElasticsearchTransport.increment_timed_out_count
+ end
+
::Gitlab::Instrumentation::ElasticsearchTransport.add_duration(duration)
::Gitlab::Instrumentation::ElasticsearchTransport.add_call_details(duration, method, path, params, body)
end
@@ -25,6 +30,7 @@ module Gitlab
ELASTICSEARCH_REQUEST_COUNT = :elasticsearch_request_count
ELASTICSEARCH_CALL_DURATION = :elasticsearch_call_duration
ELASTICSEARCH_CALL_DETAILS = :elasticsearch_call_details
+ ELASTICSEARCH_TIMED_OUT_COUNT = :elasticsearch_timed_out_count
def self.get_request_count
::Gitlab::SafeRequestStore[ELASTICSEARCH_REQUEST_COUNT] || 0
@@ -49,6 +55,15 @@ module Gitlab
::Gitlab::SafeRequestStore[ELASTICSEARCH_CALL_DURATION] += duration
end
+ def self.increment_timed_out_count
+ ::Gitlab::SafeRequestStore[ELASTICSEARCH_TIMED_OUT_COUNT] ||= 0
+ ::Gitlab::SafeRequestStore[ELASTICSEARCH_TIMED_OUT_COUNT] += 1
+ end
+
+ def self.get_timed_out_count
+ ::Gitlab::SafeRequestStore[ELASTICSEARCH_TIMED_OUT_COUNT] || 0
+ end
+
def self.add_call_details(duration, method, path, params, body)
return unless Gitlab::PerformanceBar.enabled_for_request?
diff --git a/lib/gitlab/instrumentation/redis_cluster_validator.rb b/lib/gitlab/instrumentation/redis_cluster_validator.rb
index 6800e5667f6..644a5fc4fff 100644
--- a/lib/gitlab/instrumentation/redis_cluster_validator.rb
+++ b/lib/gitlab/instrumentation/redis_cluster_validator.rb
@@ -61,7 +61,7 @@ module Gitlab
key_slot(args.first)
end
- unless key_slots.uniq.length == 1
+ if key_slots.uniq.many? # rubocop: disable CodeReuse/ActiveRecord
raise CrossSlotError.new("Redis command #{command_name} arguments hash to different slots. See https://docs.gitlab.com/ee/development/redis.html#multi-key-commands")
end
end
diff --git a/lib/gitlab/instrumentation_helper.rb b/lib/gitlab/instrumentation_helper.rb
index 6b0f01757b7..61de6b02453 100644
--- a/lib/gitlab/instrumentation_helper.rb
+++ b/lib/gitlab/instrumentation_helper.rb
@@ -7,14 +7,33 @@ module Gitlab
DURATION_PRECISION = 6 # microseconds
def keys
- @keys ||= [:gitaly_calls,
- :gitaly_duration_s,
- :rugged_calls,
- :rugged_duration_s,
- :elasticsearch_calls,
- :elasticsearch_duration_s,
- *::Gitlab::Instrumentation::Redis.known_payload_keys,
- *::Gitlab::Metrics::Subscribers::ActiveRecord::DB_COUNTERS]
+ @keys ||= [
+ :cpu_s,
+ :gitaly_calls,
+ :gitaly_duration_s,
+ :rugged_calls,
+ :rugged_duration_s,
+ :elasticsearch_calls,
+ :elasticsearch_duration_s,
+ :elasticsearch_timed_out_count,
+ *::Gitlab::Memory::Instrumentation::KEY_MAPPING.values,
+ *::Gitlab::Instrumentation::Redis.known_payload_keys,
+ *::Gitlab::Metrics::Subscribers::ActiveRecord::DB_COUNTERS,
+ *::Gitlab::Metrics::Subscribers::ExternalHttp::KNOWN_PAYLOAD_KEYS,
+ *::Gitlab::Metrics::Subscribers::RackAttack::PAYLOAD_KEYS
+ ]
+ end
+
+ def init_instrumentation_data(request_ip: nil)
+ # Set `request_start_time` only if this is request
+ # This is done, as `request_start_time` imply `request_deadline`
+ if request_ip
+ Gitlab::RequestContext.instance.client_ip = request_ip
+ Gitlab::RequestContext.instance.request_start_time = Gitlab::Metrics::System.real_time
+ end
+
+ Gitlab::RequestContext.instance.start_thread_cpu_time = Gitlab::Metrics::System.thread_cpu_time
+ Gitlab::RequestContext.instance.thread_memory_allocations = Gitlab::Memory::Instrumentation.start_thread_memory_allocations
end
def add_instrumentation_data(payload)
@@ -24,6 +43,10 @@ module Gitlab
instrument_elasticsearch(payload)
instrument_throttle(payload)
instrument_active_record(payload)
+ instrument_external_http(payload)
+ instrument_rack_attack(payload)
+ instrument_cpu(payload)
+ instrument_thread_memory_allocations(payload)
end
def instrument_gitaly(payload)
@@ -57,6 +80,15 @@ module Gitlab
payload[:elasticsearch_calls] = elasticsearch_calls
payload[:elasticsearch_duration_s] = Gitlab::Instrumentation::ElasticsearchTransport.query_time
+ payload[:elasticsearch_timed_out_count] = Gitlab::Instrumentation::ElasticsearchTransport.get_timed_out_count
+ end
+
+ def instrument_external_http(payload)
+ external_http_count = Gitlab::Metrics::Subscribers::ExternalHttp.request_count
+
+ return if external_http_count == 0
+
+ payload.merge! Gitlab::Metrics::Subscribers::ExternalHttp.payload
end
def instrument_throttle(payload)
@@ -70,6 +102,26 @@ module Gitlab
payload.merge!(db_counters)
end
+ def instrument_rack_attack(payload)
+ rack_attack_redis_count = ::Gitlab::Metrics::Subscribers::RackAttack.payload[:rack_attack_redis_count]
+ return if rack_attack_redis_count == 0
+
+ payload.merge!(::Gitlab::Metrics::Subscribers::RackAttack.payload)
+ end
+
+ def instrument_cpu(payload)
+ cpu_s = ::Gitlab::Metrics::System.thread_cpu_duration(
+ ::Gitlab::RequestContext.instance.start_thread_cpu_time)
+
+ payload[:cpu_s] = cpu_s.round(DURATION_PRECISION) if cpu_s
+ end
+
+ def instrument_thread_memory_allocations(payload)
+ counters = ::Gitlab::Memory::Instrumentation.measure_thread_memory_allocations(
+ ::Gitlab::RequestContext.instance.thread_memory_allocations)
+ payload.merge!(counters) if counters
+ end
+
# Returns the queuing duration for a Sidekiq job in seconds, as a float, if the
# `enqueued_at` field or `created_at` field is available.
#
@@ -96,7 +148,7 @@ module Gitlab
#
# @param [Time] start
def self.elapsed_by_absolute_time(start)
- (Time.now - start).to_f.round(6)
+ (Time.now - start).to_f.round(DURATION_PRECISION)
end
private_class_method :elapsed_by_absolute_time
diff --git a/lib/gitlab/kas.rb b/lib/gitlab/kas.rb
index 08dde98e965..329c0f221b5 100644
--- a/lib/gitlab/kas.rb
+++ b/lib/gitlab/kas.rb
@@ -23,6 +23,12 @@ module Gitlab
write_secret
end
+
+ def included_in_gitlab_com_rollout?(project)
+ return true unless ::Gitlab.com?
+
+ Feature.enabled?(:kubernetes_agent_on_gitlab_com, project)
+ end
end
end
end
diff --git a/lib/gitlab/kroki.rb b/lib/gitlab/kroki.rb
index 8c5652fb766..2948b6ebd5b 100644
--- a/lib/gitlab/kroki.rb
+++ b/lib/gitlab/kroki.rb
@@ -13,11 +13,8 @@ module Gitlab
packetdiag
rackdiag
].freeze
- # Diagrams that require a companion container are disabled for now
- DIAGRAMS_FORMATS = ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES
- .reject { |diagram_type| diagram_type == 'mermaid' || diagram_type == 'bpmn' || BLOCKDIAG_FORMATS.include?(diagram_type) }
- DIAGRAMS_FORMATS_WO_PLANTUML = DIAGRAMS_FORMATS
- .reject { |diagram_type| diagram_type == 'plantuml' }
+ DIAGRAMS_FORMATS = (::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES - %w(mermaid)).freeze
+ DIAGRAMS_FORMATS_WO_PLANTUML = (DIAGRAMS_FORMATS - %w(plantuml)).freeze
# Get the list of diagram formats that are currently enabled
#
@@ -28,10 +25,18 @@ module Gitlab
# If PlantUML is enabled, PlantUML diagrams will be processed by the PlantUML server.
# In other words, the PlantUML server has precedence over Kroki since both can process PlantUML diagrams.
- if current_settings.plantuml_enabled
- DIAGRAMS_FORMATS_WO_PLANTUML
- else
- DIAGRAMS_FORMATS
+ diagram_formats = if current_settings.plantuml_enabled
+ DIAGRAMS_FORMATS_WO_PLANTUML
+ else
+ DIAGRAMS_FORMATS
+ end
+
+ # No additional diagram formats
+ return diagram_formats unless current_settings.kroki_formats.present?
+
+ # Diagrams that require a companion container must be explicitly enabled from the settings
+ diagram_formats.select do |diagram_type|
+ current_settings.kroki_format_supported?(diagram_type)
end
end
end
diff --git a/lib/gitlab/kubernetes/helm/v2/certificate.rb b/lib/gitlab/kubernetes/helm/v2/certificate.rb
index f603ff44ef3..17ea2eb5188 100644
--- a/lib/gitlab/kubernetes/helm/v2/certificate.rb
+++ b/lib/gitlab/kubernetes/helm/v2/certificate.rb
@@ -59,7 +59,7 @@ module Gitlab
cert.add_extension(extension_factory.create_extension('keyUsage', 'cRLSign,keyCertSign', true))
end
- cert.sign(signed_by&.key || key, OpenSSL::Digest::SHA256.new)
+ cert.sign(signed_by&.key || key, OpenSSL::Digest.new('SHA256'))
new(key, cert)
end
diff --git a/lib/gitlab/lograge/custom_options.rb b/lib/gitlab/lograge/custom_options.rb
index e6dd87a8bec..dce7cdb31a1 100644
--- a/lib/gitlab/lograge/custom_options.rb
+++ b/lib/gitlab/lograge/custom_options.rb
@@ -29,10 +29,6 @@ module Gitlab
payload[:etag_route] = event.payload[:etag_route] if event.payload[:etag_route]
payload[Labkit::Correlation::CorrelationId::LOG_KEY] = event.payload[Labkit::Correlation::CorrelationId::LOG_KEY] || Labkit::Correlation::CorrelationId.current_id
- if cpu_s = Gitlab::Metrics::System.thread_cpu_duration(::Gitlab::RequestContext.instance.start_thread_cpu_time)
- payload[:cpu_s] = cpu_s.round(2)
- end
-
CLOUDFLARE_CUSTOM_HEADERS.each do |_, value|
payload[value] = event.payload[value] if event.payload[value]
end
diff --git a/lib/gitlab/memory/instrumentation.rb b/lib/gitlab/memory/instrumentation.rb
new file mode 100644
index 00000000000..76e84e54d3a
--- /dev/null
+++ b/lib/gitlab/memory/instrumentation.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+# This class uses a custom Ruby patch to allow
+# a per-thread memory allocation tracking in a efficient manner
+#
+# This concept is currently tried to be upstreamed here:
+# - https://github.com/ruby/ruby/pull/3978
+module Gitlab
+ module Memory
+ class Instrumentation
+ KEY_MAPPING = {
+ total_allocated_objects: :mem_objects,
+ total_malloc_bytes: :mem_bytes,
+ total_mallocs: :mem_mallocs
+ }.freeze
+
+ MUTEX = Mutex.new
+
+ def self.available?
+ Thread.respond_to?(:trace_memory_allocations=) &&
+ Thread.current.respond_to?(:memory_allocations)
+ end
+
+ # This method changes a global state
+ def self.ensure_feature_flag!
+ return unless available?
+
+ enabled = Feature.enabled?(:trace_memory_allocations)
+ return if enabled == Thread.trace_memory_allocations
+
+ MUTEX.synchronize do
+ # This enables or disables feature dynamically
+ # based on a feature flag
+ Thread.trace_memory_allocations = enabled
+ end
+ end
+
+ def self.start_thread_memory_allocations
+ return unless available?
+
+ ensure_feature_flag!
+
+ # it will return `nil` if disabled
+ Thread.current.memory_allocations
+ end
+
+ # This method returns a hash with the following keys:
+ # - mem_objects: a number of allocated heap slots (as reflected by GC)
+ # - mem_mallocs: a number of malloc calls
+ # - mem_bytes: a number of bytes allocated with a mallocs tied to heap slots
+ def self.measure_thread_memory_allocations(previous)
+ return unless available?
+ return unless previous
+
+ current = Thread.current.memory_allocations
+ return unless current
+
+ # calculate difference in a memory allocations
+ previous.to_h do |key, value|
+ [KEY_MAPPING.fetch(key), current[key].to_i - value]
+ end
+ end
+
+ def self.with_memory_allocations
+ previous = self.start_thread_memory_allocations
+ yield
+ self.measure_thread_memory_allocations(previous)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/exporter/web_exporter.rb b/lib/gitlab/metrics/exporter/web_exporter.rb
index b6a27d8556a..558454eaa1c 100644
--- a/lib/gitlab/metrics/exporter/web_exporter.rb
+++ b/lib/gitlab/metrics/exporter/web_exporter.rb
@@ -12,6 +12,10 @@ module Gitlab
Gitlab::HealthChecks::Result.new(
'web_exporter', exporter.running)
end
+
+ def available?
+ true
+ end
end
attr_reader :running
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index 3100450bc00..8ddd76ad7ae 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -39,7 +39,7 @@ module Gitlab
options.evaluate(&block)
if disabled_by_feature(options)
- synchronized_cache_fill(name) { NullMetric.instance }
+ synchronized_cache_fill(name) { ::Gitlab::Metrics::NullMetric.instance }
else
synchronized_cache_fill(name) { build_metric!(type, name, options) }
end
diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb
index a6884ea6983..f7e53bf545b 100644
--- a/lib/gitlab/metrics/rack_middleware.rb
+++ b/lib/gitlab/metrics/rack_middleware.rb
@@ -10,7 +10,7 @@ module Gitlab
# env - A Hash containing Rack environment details.
def call(env)
- trans = WebTransaction.new(env)
+ trans = Gitlab::Metrics::WebTransaction.new(env)
begin
retval = trans.run { @app.call(env) }
diff --git a/lib/gitlab/metrics/subscribers/external_http.rb b/lib/gitlab/metrics/subscribers/external_http.rb
new file mode 100644
index 00000000000..94c5d965200
--- /dev/null
+++ b/lib/gitlab/metrics/subscribers/external_http.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Subscribers
+ # Class for tracking the total time spent in external HTTP
+ # See more at https://gitlab.com/gitlab-org/labkit-ruby/-/blob/v0.14.0/lib/gitlab-labkit.rb#L18
+ class ExternalHttp < ActiveSupport::Subscriber
+ attach_to :external_http
+
+ DEFAULT_STATUS_CODE = 'undefined'
+
+ DETAIL_STORE = :external_http_detail_store
+ COUNTER = :external_http_count
+ DURATION = :external_http_duration_s
+
+ KNOWN_PAYLOAD_KEYS = [COUNTER, DURATION].freeze
+
+ def self.detail_store
+ ::Gitlab::SafeRequestStore[DETAIL_STORE] ||= []
+ end
+
+ def self.duration
+ Gitlab::SafeRequestStore[DURATION].to_f
+ end
+
+ def self.request_count
+ Gitlab::SafeRequestStore[COUNTER].to_i
+ end
+
+ def self.payload
+ {
+ COUNTER => request_count,
+ DURATION => duration
+ }
+ end
+
+ def request(event)
+ payload = event.payload
+ add_to_detail_store(payload)
+ add_to_request_store(payload)
+ expose_metrics(payload)
+ end
+
+ private
+
+ def current_transaction
+ ::Gitlab::Metrics::Transaction.current
+ end
+
+ def add_to_detail_store(payload)
+ return unless Gitlab::PerformanceBar.enabled_for_request?
+
+ self.class.detail_store << {
+ duration: payload[:duration],
+ scheme: payload[:scheme],
+ method: payload[:method],
+ host: payload[:host],
+ port: payload[:port],
+ path: payload[:path],
+ query: payload[:query],
+ code: payload[:code],
+ exception_object: payload[:exception_object],
+ backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller)
+ }
+ end
+
+ def add_to_request_store(payload)
+ return unless Gitlab::SafeRequestStore.active?
+
+ Gitlab::SafeRequestStore[COUNTER] = Gitlab::SafeRequestStore[COUNTER].to_i + 1
+ Gitlab::SafeRequestStore[DURATION] = Gitlab::SafeRequestStore[DURATION].to_f + payload[:duration].to_f
+ end
+
+ def expose_metrics(payload)
+ return unless current_transaction
+
+ labels = { method: payload[:method], code: payload[:code] || DEFAULT_STATUS_CODE }
+
+ current_transaction.increment(:gitlab_external_http_total, 1, labels) do
+ docstring 'External HTTP calls'
+ label_keys labels.keys
+ end
+
+ current_transaction.observe(:gitlab_external_http_duration_seconds, payload[:duration]) do
+ docstring 'External HTTP time'
+ buckets [0.001, 0.01, 0.1, 1.0, 2.0, 5.0]
+ end
+
+ if payload[:exception_object].present?
+ current_transaction.increment(:gitlab_external_http_exception_total, 1) do
+ docstring 'External HTTP exceptions'
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/subscribers/rack_attack.rb b/lib/gitlab/metrics/subscribers/rack_attack.rb
new file mode 100644
index 00000000000..2791a39fb16
--- /dev/null
+++ b/lib/gitlab/metrics/subscribers/rack_attack.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Subscribers
+ # - Adds logging for all Rack Attack blocks and throttling events.
+ # - Instrument the cache operations of RackAttack to use in structured
+ # logs. Two fields are exposed:
+ # + rack_attack_redis_count: the number of redis calls triggered by
+ # RackAttack in a request.
+ # + rack_attack_redis_duration_s: the total duration of all redis calls
+ # triggered by RackAttack in a request.
+ class RackAttack < ActiveSupport::Subscriber
+ attach_to 'rack_attack'
+
+ INSTRUMENTATION_STORE_KEY = :rack_attack_instrumentation
+
+ THROTTLES_WITH_USER_INFORMATION = [
+ :throttle_authenticated_api,
+ :throttle_authenticated_web,
+ :throttle_authenticated_protected_paths_api,
+ :throttle_authenticated_protected_paths_web
+ ].freeze
+
+ PAYLOAD_KEYS = [
+ :rack_attack_redis_count,
+ :rack_attack_redis_duration_s
+ ].freeze
+
+ def self.payload
+ Gitlab::SafeRequestStore[INSTRUMENTATION_STORE_KEY] ||= {
+ rack_attack_redis_count: 0,
+ rack_attack_redis_duration_s: 0.0
+ }
+ end
+
+ def redis(event)
+ self.class.payload[:rack_attack_redis_count] += 1
+ self.class.payload[:rack_attack_redis_duration_s] += event.duration.to_f / 1000
+ end
+
+ def safelist(event)
+ req = event.payload[:request]
+ Gitlab::Instrumentation::Throttle.safelist = req.env['rack.attack.matched']
+ end
+
+ def throttle(event)
+ log_into_auth_logger(event)
+ end
+
+ def blocklist(event)
+ log_into_auth_logger(event)
+ end
+
+ def track(event)
+ log_into_auth_logger(event)
+ end
+
+ private
+
+ def log_into_auth_logger(event)
+ req = event.payload[:request]
+ rack_attack_info = {
+ message: 'Rack_Attack',
+ env: req.env['rack.attack.match_type'],
+ remote_ip: req.ip,
+ request_method: req.request_method,
+ path: req.fullpath,
+ matched: req.env['rack.attack.matched']
+ }
+
+ if THROTTLES_WITH_USER_INFORMATION.include? req.env['rack.attack.matched'].to_sym
+ user_id = req.env['rack.attack.match_discriminator']
+ user = User.find_by(id: user_id) # rubocop:disable CodeReuse/ActiveRecord
+
+ rack_attack_info[:user_id] = user_id
+ rack_attack_info['meta.user'] = user.username unless user.nil?
+ end
+
+ Gitlab::InstrumentationHelper.add_instrumentation_data(rack_attack_info)
+
+ logger.error(rack_attack_info)
+ end
+
+ def logger
+ Gitlab::AuthLogger
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/middleware/request_context.rb b/lib/gitlab/middleware/request_context.rb
index 953423b371c..07f6f87a68c 100644
--- a/lib/gitlab/middleware/request_context.rb
+++ b/lib/gitlab/middleware/request_context.rb
@@ -16,9 +16,7 @@ module Gitlab
# load balancer's IP.
req = Rack::Request.new(env)
- Gitlab::RequestContext.instance.client_ip = req.ip
- Gitlab::RequestContext.instance.start_thread_cpu_time = Gitlab::Metrics::System.thread_cpu_time
- Gitlab::RequestContext.instance.request_start_time = Gitlab::Metrics::System.real_time
+ ::Gitlab::InstrumentationHelper.init_instrumentation_data(request_ip: req.ip)
@app.call(env)
end
diff --git a/lib/gitlab/pages_transfer.rb b/lib/gitlab/pages_transfer.rb
index 8ae0ec5a78a..c1ccfae3e1f 100644
--- a/lib/gitlab/pages_transfer.rb
+++ b/lib/gitlab/pages_transfer.rb
@@ -7,16 +7,26 @@
#
module Gitlab
class PagesTransfer < ProjectTransfer
- class Async
- METHODS = %w[move_namespace move_project rename_project rename_namespace].freeze
+ METHODS = %w[move_namespace move_project rename_project rename_namespace].freeze
+ class Async
METHODS.each do |meth|
define_method meth do |*args|
+ next unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+
PagesTransferWorker.perform_async(meth, args)
end
end
end
+ METHODS.each do |meth|
+ define_method meth do |*args|
+ next unless Feature.enabled?(:pages_update_legacy_storage, default_enabled: true)
+
+ super(*args)
+ end
+ end
+
def async
@async ||= Async.new
end
diff --git a/lib/gitlab/patch/prependable.rb b/lib/gitlab/patch/prependable.rb
index 22ece0a6a8b..dde78cd9178 100644
--- a/lib/gitlab/patch/prependable.rb
+++ b/lib/gitlab/patch/prependable.rb
@@ -39,9 +39,14 @@ module Gitlab
def class_methods
super
+ class_methods_module = const_get(:ClassMethods, false)
+
if instance_variable_defined?(:@_prepended_class_methods)
- const_get(:ClassMethods, false).prepend @_prepended_class_methods
+ class_methods_module.prepend @_prepended_class_methods
end
+
+ # Hack to resolve https://gitlab.com/gitlab-org/gitlab/-/issues/23932
+ extend class_methods_module if ENV['STATIC_VERIFICATION']
end
def prepended(base = nil, &block)
diff --git a/lib/gitlab/performance_bar/stats.rb b/lib/gitlab/performance_bar/stats.rb
index d1504d88315..380340b80be 100644
--- a/lib/gitlab/performance_bar/stats.rb
+++ b/lib/gitlab/performance_bar/stats.rb
@@ -27,27 +27,40 @@ module Gitlab
end
def log_sql_queries(id, data)
- return [] unless queries = data.dig('data', 'active-record', 'details')
-
- queries.each do |query|
- next unless location = parse_backtrace(query['backtrace'])
+ queries_by_location(data).each do |location, queries|
+ next unless location
- log_info = location.merge(
+ duration = queries.sum { |query| query['duration'].to_f }
+ log_info = {
+ method_path: "#{location[:filename]}:#{location[:method]}",
+ filename: location[:filename],
type: :sql,
request_id: id,
- duration_ms: query['duration'].to_f
- )
+ count: queries.count,
+ duration_ms: duration
+ }
logger.info(log_info)
end
end
+ def queries_by_location(data)
+ return [] unless queries = data.dig('data', 'active-record', 'details')
+
+ queries.group_by do |query|
+ parse_backtrace(query['backtrace'])
+ end
+ end
+
def parse_backtrace(backtrace)
return unless match = /(?<filename>.*):(?<filenum>\d+):in `(?<method>.*)'/.match(backtrace.first)
{
filename: match[:filename],
- filenum: match[:filenum].to_i,
+ # filenum may change quite frequently with every change in the file,
+ # because the intention is to aggregate these queries, we group
+ # them rather by method name which should not change so frequently
+ # filenum: match[:filenum].to_i,
method: match[:method]
}
end
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index b56fd8278a1..6a404c34044 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -181,13 +181,12 @@ module Gitlab
end
types MergeRequest
condition do
- Feature.enabled?(:merge_request_reviewers, project, default_enabled: :yaml) &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
+ current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
parse_params do |reviewer_param|
extract_users(reviewer_param)
end
- command :assign_reviewer, :reviewer do |users|
+ command :assign_reviewer, :reviewer, :request_review do |users|
next if users.empty?
if quick_action_target.allows_multiple_reviewers?
@@ -221,7 +220,6 @@ module Gitlab
types MergeRequest
condition do
quick_action_target.persisted? &&
- Feature.enabled?(:merge_request_reviewers, project, default_enabled: :yaml) &&
quick_action_target.reviewers.any? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
diff --git a/lib/gitlab/rack_attack.rb b/lib/gitlab/rack_attack.rb
index 2a94fb91880..ae3c89c3565 100644
--- a/lib/gitlab/rack_attack.rb
+++ b/lib/gitlab/rack_attack.rb
@@ -12,13 +12,15 @@ module Gitlab
rack_attack::Request.include(Gitlab::RackAttack::Request)
# This is Rack::Attack::DEFAULT_THROTTLED_RESPONSE, modified to allow a custom response
- Rack::Attack.throttled_response = lambda do |env|
+ rack_attack.throttled_response = lambda do |env|
throttled_headers = Gitlab::RackAttack.throttled_response_headers(
env['rack.attack.matched'], env['rack.attack.match_data']
)
[429, { 'Content-Type' => 'text/plain' }.merge(throttled_headers), [Gitlab::Throttle.rate_limiting_response_text]]
end
+ rack_attack.cache.store = Gitlab::RackAttack::InstrumentedCacheStore.new
+
# Configure the throttles
configure_throttles(rack_attack)
diff --git a/lib/gitlab/rack_attack/instrumented_cache_store.rb b/lib/gitlab/rack_attack/instrumented_cache_store.rb
new file mode 100644
index 00000000000..8cf9082384f
--- /dev/null
+++ b/lib/gitlab/rack_attack/instrumented_cache_store.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RackAttack
+ # This class is a proxy for all Redis calls made by RackAttack. All the
+ # calls are instrumented, then redirected to ::Rails.cache. This class
+ # instruments the standard interfaces of ActiveRecord::Cache defined in
+ # https://github.com/rails/rails/blob/v6.0.3.1/activesupport/lib/active_support/cache.rb#L315
+ #
+ # For more information, please see
+ # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/751
+ class InstrumentedCacheStore
+ NOTIFICATION_CHANNEL = 'redis.rack_attack'
+
+ delegate :silence!, :mute, to: :@upstream_store
+
+ def initialize(upstream_store: ::Rails.cache, notifier: ActiveSupport::Notifications)
+ @upstream_store = upstream_store
+ @notifier = notifier
+ end
+
+ [:fetch, :read, :read_multi, :write_multi, :fetch_multi, :write, :delete,
+ :exist?, :delete_matched, :increment, :decrement, :cleanup, :clear].each do |interface|
+ define_method interface do |*args, **k_args, &block|
+ @notifier.instrument(NOTIFICATION_CHANNEL, operation: interface) do
+ @upstream_store.public_send(interface, *args, **k_args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/recaptcha.rb b/lib/gitlab/recaptcha.rb
index f3cbe1db901..a08cea5a435 100644
--- a/lib/gitlab/recaptcha.rb
+++ b/lib/gitlab/recaptcha.rb
@@ -2,8 +2,10 @@
module Gitlab
module Recaptcha
+ extend Gitlab::Utils::StrongMemoize
+
def self.load_configurations!
- if Gitlab::CurrentSettings.recaptcha_enabled || enabled_on_login?
+ if enabled? || enabled_on_login?
::Recaptcha.configure do |config|
config.site_key = Gitlab::CurrentSettings.recaptcha_site_key
config.secret_key = Gitlab::CurrentSettings.recaptcha_private_key
diff --git a/lib/gitlab/relative_positioning.rb b/lib/gitlab/relative_positioning.rb
index b5a923f0824..e2cbe4b2de0 100644
--- a/lib/gitlab/relative_positioning.rb
+++ b/lib/gitlab/relative_positioning.rb
@@ -13,5 +13,18 @@ module Gitlab
MIN_GAP = 2
NoSpaceLeft = Class.new(StandardError)
+ IllegalRange = Class.new(ArgumentError)
+
+ def self.range(lhs, rhs)
+ if lhs && rhs
+ ClosedRange.new(lhs, rhs)
+ elsif lhs
+ StartingFrom.new(lhs)
+ elsif rhs
+ EndingAt.new(rhs)
+ else
+ raise IllegalRange, 'One of rhs or lhs must be provided' unless lhs && rhs
+ end
+ end
end
end
diff --git a/lib/gitlab/relative_positioning/range.rb b/lib/gitlab/relative_positioning/range.rb
index 174d5ef4b35..0b0ccdf5be4 100644
--- a/lib/gitlab/relative_positioning/range.rb
+++ b/lib/gitlab/relative_positioning/range.rb
@@ -2,8 +2,6 @@
module Gitlab
module RelativePositioning
- IllegalRange = Class.new(ArgumentError)
-
class Range
attr_reader :lhs, :rhs
@@ -34,18 +32,6 @@ module Gitlab
end
end
- def self.range(lhs, rhs)
- if lhs && rhs
- ClosedRange.new(lhs, rhs)
- elsif lhs
- StartingFrom.new(lhs)
- elsif rhs
- EndingAt.new(rhs)
- else
- raise IllegalRange, 'One of rhs or lhs must be provided' unless lhs && rhs
- end
- end
-
class ClosedRange < RelativePositioning::Range
def initialize(lhs, rhs)
@lhs, @rhs = lhs, rhs
diff --git a/lib/gitlab/request_context.rb b/lib/gitlab/request_context.rb
index 952ae55d90a..c9eefe9a647 100644
--- a/lib/gitlab/request_context.rb
+++ b/lib/gitlab/request_context.rb
@@ -7,7 +7,7 @@ module Gitlab
RequestDeadlineExceeded = Class.new(StandardError)
- attr_accessor :client_ip, :start_thread_cpu_time, :request_start_time
+ attr_accessor :client_ip, :start_thread_cpu_time, :request_start_time, :thread_memory_allocations
class << self
def instance
diff --git a/lib/gitlab/request_forgery_protection.rb b/lib/gitlab/request_forgery_protection.rb
index 79562a8223b..a84a6ac2d14 100644
--- a/lib/gitlab/request_forgery_protection.rb
+++ b/lib/gitlab/request_forgery_protection.rb
@@ -23,7 +23,9 @@ module Gitlab
end
def self.verified?(env)
- call(env)
+ minimal_env = env.slice('REQUEST_METHOD', 'rack.session', 'HTTP_X_CSRF_TOKEN')
+ .merge('rack.input' => '')
+ call(minimal_env)
true
rescue ActionController::InvalidAuthenticityToken
diff --git a/lib/gitlab/runtime.rb b/lib/gitlab/runtime.rb
index 8b40aaa101a..647ac169f05 100644
--- a/lib/gitlab/runtime.rb
+++ b/lib/gitlab/runtime.rb
@@ -81,6 +81,10 @@ module Gitlab
puma? || sidekiq? || action_cable?
end
+ def puma_in_clustered_mode?
+ puma? && Puma.cli_config.options[:workers].to_i > 0
+ end
+
def max_threads
threads = 1 # main thread
diff --git a/lib/gitlab/sample_data_template.rb b/lib/gitlab/sample_data_template.rb
index 06ea53e4018..5a2a7d46bdf 100644
--- a/lib/gitlab/sample_data_template.rb
+++ b/lib/gitlab/sample_data_template.rb
@@ -5,7 +5,7 @@ module Gitlab
class << self
def localized_templates_table
[
- SampleDataTemplate.new('sample', 'Sample GitLab Project', _('Get started with a project that follows best practices for setting up GitLab for your own organization, including sample Issues, Merge Requests, and Milestones'), 'https://gitlab.com/gitlab-org/sample-data-templates/sample-gitlab-project')
+ SampleDataTemplate.new('sample', 'Sample GitLab Project', _('An example project that shows off the best practices for setting up GitLab for your own organization, including sample issues, merge requests, and milestones'), 'https://gitlab.com/gitlab-org/sample-data-templates/sample-gitlab-project')
].freeze
end
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb
index 5b1f9400bc7..c0420126ada 100644
--- a/lib/gitlab/search/query.rb
+++ b/lib/gitlab/search/query.rb
@@ -5,6 +5,9 @@ module Gitlab
class Query < SimpleDelegator
include EncodingHelper
+ QUOTES_REGEXP = %r{\A"|"\Z}.freeze
+ TOKEN_WITH_QUOTES_REGEXP = %r{\s(?=(?:[^"]|"[^"]*")*$)}.freeze
+
def initialize(query, filter_opts = {}, &block)
@raw_query = query.dup
@filters = []
@@ -35,22 +38,24 @@ module Gitlab
def extract_filters
fragments = []
+ query_tokens = parse_raw_query
filters = @filters.each_with_object([]) do |filter, parsed_filters|
- match = @raw_query.split.find { |part| part =~ /\A-?#{filter[:name]}:/ }
+ match = query_tokens.find { |part| part =~ /\A-?#{filter[:name]}:/ }
+
next unless match
input = match.split(':')[1..-1].join
next if input.empty?
filter[:negated] = match.start_with?("-")
- filter[:value] = parse_filter(filter, input)
+ filter[:value] = parse_filter(filter, input.gsub(QUOTES_REGEXP, ''))
filter[:regex_value] = Regexp.escape(filter[:value]).gsub('\*', '.*?')
fragments << match
parsed_filters << filter
end
- query = (@raw_query.split - fragments).join(' ')
+ query = (query_tokens - fragments).join(' ')
query = '*' if query.empty?
[query, filters]
@@ -61,6 +66,13 @@ module Gitlab
@filter_options[:encode_binary] ? encode_binary(result) : result
end
+
+ def parse_raw_query
+ # Positive lookahead for any non-quote char or even number of quotes
+ # for example '"search term" path:"foo bar.txt"' would break into
+ # ["search term", "path:\"foo bar.txt\""]
+ @raw_query.split(TOKEN_WITH_QUOTES_REGEXP).reject(&:empty?)
+ end
end
end
end
diff --git a/lib/gitlab/search/sort_options.rb b/lib/gitlab/search/sort_options.rb
index 3395c34d171..2ab38147462 100644
--- a/lib/gitlab/search/sort_options.rb
+++ b/lib/gitlab/search/sort_options.rb
@@ -11,6 +11,10 @@ module Gitlab
:created_at_asc
when %w[created_at desc], [nil, 'created_desc']
:created_at_desc
+ when %w[updated_at asc], [nil, 'updated_asc']
+ :updated_at_asc
+ when %w[updated_at desc], [nil, 'updated_desc']
+ :updated_at_desc
else
:unknown
end
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index 0091ae1e8ce..d0beb74c289 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -136,6 +136,10 @@ module Gitlab
scope.reorder('created_at ASC')
when :created_at_desc
scope.reorder('created_at DESC')
+ when :updated_at_asc
+ scope.reorder('updated_at ASC')
+ when :updated_at_desc
+ scope.reorder('updated_at DESC')
else
scope.reorder('created_at DESC')
end
diff --git a/lib/gitlab/sidekiq_death_handler.rb b/lib/gitlab/sidekiq_death_handler.rb
index f86d9f17b5f..91bfc7dca80 100644
--- a/lib/gitlab/sidekiq_death_handler.rb
+++ b/lib/gitlab/sidekiq_death_handler.rb
@@ -6,7 +6,7 @@ module Gitlab
include ::Gitlab::SidekiqMiddleware::MetricsHelper
def handler(job, _exception)
- labels = create_labels(job['class'].constantize, job['queue'])
+ labels = create_labels(job['class'].constantize, job['queue'], job)
counter.increment(labels)
end
diff --git a/lib/gitlab/sidekiq_logging/exception_handler.rb b/lib/gitlab/sidekiq_logging/exception_handler.rb
deleted file mode 100644
index 8ae6addc2c6..00000000000
--- a/lib/gitlab/sidekiq_logging/exception_handler.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module SidekiqLogging
- class ExceptionHandler
- def call(job_exception, context)
- data = {
- error_class: job_exception.class.name,
- error_message: job_exception.message
- }
-
- if context.is_a?(Hash)
- data.merge!(context)
- # correlation_id, jid, and class are available inside the job
- # Hash, so promote these arguments to the root tree so that
- # can be searched alongside other Sidekiq log messages.
- job_data = data.delete(:job)
- data.merge!(job_data) if job_data.present?
- end
-
- data[:error_backtrace] = Rails.backtrace_cleaner.clean(job_exception.backtrace) if job_exception.backtrace.present?
-
- Sidekiq.logger.warn(data)
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_logging/logs_jobs.rb b/lib/gitlab/sidekiq_logging/logs_jobs.rb
index dc81c34c4d0..6f8cc1c60e9 100644
--- a/lib/gitlab/sidekiq_logging/logs_jobs.rb
+++ b/lib/gitlab/sidekiq_logging/logs_jobs.rb
@@ -12,6 +12,7 @@ module Gitlab
# Error information from the previous try is in the payload for
# displaying in the Sidekiq UI, but is very confusing in logs!
job = job.except('error_backtrace', 'error_class', 'error_message')
+ job['class'] = job.delete('wrapped') if job['wrapped'].present?
# Add process id params
job['pid'] = ::Process.pid
diff --git a/lib/gitlab/sidekiq_logging/structured_logger.rb b/lib/gitlab/sidekiq_logging/structured_logger.rb
index eb845c5ff8d..654b17c5740 100644
--- a/lib/gitlab/sidekiq_logging/structured_logger.rb
+++ b/lib/gitlab/sidekiq_logging/structured_logger.rb
@@ -11,13 +11,25 @@ module Gitlab
def call(job, queue)
started_time = get_time
base_payload = parse_job(job)
+
ActiveRecord::LogSubscriber.reset_runtime
- Sidekiq.logger.info log_job_start(base_payload)
+ Sidekiq.logger.info log_job_start(job, base_payload)
yield
Sidekiq.logger.info log_job_done(job, started_time, base_payload)
+ rescue Sidekiq::JobRetry::Handled => job_exception
+ # Sidekiq::JobRetry::Handled is raised by the internal Sidekiq
+ # processor. It is a wrapper around real exception indicating an
+ # exception is already handled by the Job retrier. The real exception
+ # should be unwrapped before being logged.
+ #
+ # For more information:
+ # https://github.com/mperham/sidekiq/blob/v5.2.7/lib/sidekiq/processor.rb#L173
+ Sidekiq.logger.warn log_job_done(job, started_time, base_payload, job_exception.cause || job_exception)
+
+ raise
rescue => job_exception
Sidekiq.logger.warn log_job_done(job, started_time, base_payload, job_exception)
@@ -27,7 +39,9 @@ module Gitlab
private
def add_instrumentation_keys!(job, output_payload)
- output_payload.merge!(job.slice(*::Gitlab::InstrumentationHelper.keys))
+ instrumentation_values = job.slice(*::Gitlab::InstrumentationHelper.keys).stringify_keys
+
+ output_payload.merge!(instrumentation_values)
end
def add_logging_extras!(job, output_payload)
@@ -36,17 +50,15 @@ module Gitlab
)
end
- def add_db_counters!(job, output_payload)
- output_payload.merge!(job.slice(*::Gitlab::Metrics::Subscribers::ActiveRecord::DB_COUNTERS))
- end
-
- def log_job_start(payload)
+ def log_job_start(job, payload)
payload['message'] = "#{base_message(payload)}: start"
payload['job_status'] = 'start'
scheduling_latency_s = ::Gitlab::InstrumentationHelper.queue_duration_for_job(payload)
payload['scheduling_latency_s'] = scheduling_latency_s if scheduling_latency_s
+ payload['job_size_bytes'] = Sidekiq.dump_json(job).bytesize
+
payload
end
@@ -54,7 +66,6 @@ module Gitlab
payload = payload.dup
add_instrumentation_keys!(job, payload)
add_logging_extras!(job, payload)
- add_db_counters!(job, payload)
elapsed_time = elapsed(started_time)
add_time_keys!(elapsed_time, payload)
@@ -66,6 +77,7 @@ module Gitlab
payload['job_status'] = 'fail'
payload['error_message'] = job_exception.message
payload['error_class'] = job_exception.class.name
+ add_exception_backtrace!(job_exception, payload)
else
payload['message'] = "#{message}: done: #{payload['duration_s']} sec"
payload['job_status'] = 'done'
@@ -79,26 +91,22 @@ module Gitlab
def add_time_keys!(time, payload)
payload['duration_s'] = time[:duration].round(Gitlab::InstrumentationHelper::DURATION_PRECISION)
-
- # ignore `cpu_s` if the platform does not support Process::CLOCK_THREAD_CPUTIME_ID (time[:cputime] == 0)
- # supported OS version can be found at: https://www.rubydoc.info/stdlib/core/2.1.6/Process:clock_gettime
- payload['cpu_s'] = time[:cputime].round(Gitlab::InstrumentationHelper::DURATION_PRECISION) if time[:cputime] > 0
payload['completed_at'] = Time.now.utc.to_f
end
+ def add_exception_backtrace!(job_exception, payload)
+ return if job_exception.backtrace.blank?
+
+ payload['error_backtrace'] = Rails.backtrace_cleaner.clean(job_exception.backtrace)
+ end
+
def elapsed(t0)
t1 = get_time
- {
- duration: t1[:now] - t0[:now],
- cputime: t1[:thread_cputime] - t0[:thread_cputime]
- }
+ { duration: t1[:now] - t0[:now] }
end
def get_time
- {
- now: current_time,
- thread_cputime: defined?(Process::CLOCK_THREAD_CPUTIME_ID) ? Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID) : 0
- }
+ { now: current_time }
end
def current_time
diff --git a/lib/gitlab/sidekiq_middleware/client_metrics.rb b/lib/gitlab/sidekiq_middleware/client_metrics.rb
index 7ee8a623d30..6bc08a97c07 100644
--- a/lib/gitlab/sidekiq_middleware/client_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/client_metrics.rb
@@ -11,10 +11,10 @@ module Gitlab
@metrics = init_metrics
end
- def call(worker_class, _job, queue, _redis_pool)
+ def call(worker_class, job, queue, _redis_pool)
# worker_class can either be the string or class of the worker being enqueued.
worker_class = worker_class.safe_constantize if worker_class.respond_to?(:safe_constantize)
- labels = create_labels(worker_class, queue)
+ labels = create_labels(worker_class, queue, job)
@metrics.fetch(ENQUEUED).increment(labels, 1)
diff --git a/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb b/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
index 979a3fce7e6..a66a4de4655 100644
--- a/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
+++ b/lib/gitlab/sidekiq_middleware/instrumentation_logger.rb
@@ -4,8 +4,11 @@ module Gitlab
module SidekiqMiddleware
class InstrumentationLogger
def call(worker, job, queue)
+ ::Gitlab::InstrumentationHelper.init_instrumentation_data
+
yield
+ ensure
# The Sidekiq logger is called outside the middleware block, so
# we need to modify the job hash to pass along this information
# since RequestStore is only active in the Sidekiq middleware.
diff --git a/lib/gitlab/sidekiq_middleware/metrics_helper.rb b/lib/gitlab/sidekiq_middleware/metrics_helper.rb
index 5c1ce2b98e8..60e79ee1188 100644
--- a/lib/gitlab/sidekiq_middleware/metrics_helper.rb
+++ b/lib/gitlab/sidekiq_middleware/metrics_helper.rb
@@ -8,9 +8,11 @@ module Gitlab
private
- def create_labels(worker_class, queue)
+ def create_labels(worker_class, queue, job)
+ worker_name = (job['wrapped'].presence || worker_class).to_s
+
labels = { queue: queue.to_s,
- worker: worker_class.to_s,
+ worker: worker_name,
urgency: "",
external_dependencies: FALSE_LABEL,
feature_category: "",
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index 7f3048f4c6e..4ab8d313ad8 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -20,7 +20,7 @@ module Gitlab
# in metrics and can use them in the `ThreadsSampler` for setting a label
Thread.current.name ||= Gitlab::Metrics::Samplers::ThreadsSampler::SIDEKIQ_WORKER_THREAD_NAME
- labels = create_labels(worker.class, queue)
+ labels = create_labels(worker.class, queue, job)
queue_duration = ::Gitlab::InstrumentationHelper.queue_duration_for_job(job)
@metrics[:sidekiq_jobs_queue_duration_seconds].observe(labels, queue_duration) if queue_duration
diff --git a/lib/gitlab/suggestions/commit_message.rb b/lib/gitlab/suggestions/commit_message.rb
index d59a8fc3730..5bca3efe6e1 100644
--- a/lib/gitlab/suggestions/commit_message.rb
+++ b/lib/gitlab/suggestions/commit_message.rb
@@ -6,14 +6,15 @@ module Gitlab
DEFAULT_SUGGESTION_COMMIT_MESSAGE =
'Apply %{suggestions_count} suggestion(s) to %{files_count} file(s)'
- def initialize(user, suggestion_set)
+ def initialize(user, suggestion_set, custom_message = nil)
@user = user
@suggestion_set = suggestion_set
+ @custom_message = custom_message
end
def message
project = suggestion_set.project
- user_defined_message = project.suggestion_commit_message.presence
+ user_defined_message = @custom_message.presence || project.suggestion_commit_message.presence
message = user_defined_message || DEFAULT_SUGGESTION_COMMIT_MESSAGE
Gitlab::StringPlaceholderReplacer
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index c702c6f1add..db3c058184c 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -66,6 +66,18 @@ module Gitlab
answer
end
+ # Prompt the user to input a password
+ #
+ # message - custom message to display before input
+ def prompt_for_password(message = 'Enter password: ')
+ unless STDIN.tty?
+ print(message)
+ return STDIN.gets.chomp
+ end
+
+ STDIN.getpass(message)
+ end
+
# Runs the given command and matches the output against the given pattern
#
# Returns nil if nothing matched
diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb
index b659bff52ad..0f933a61598 100644
--- a/lib/gitlab/template/base_template.rb
+++ b/lib/gitlab/template/base_template.rb
@@ -8,6 +8,7 @@ module Gitlab
def initialize(path, project = nil, category: nil)
@path = path
@category = category
+ @project = project
@finder = self.class.finder(project)
end
@@ -31,6 +32,10 @@ module Gitlab
# override with a comment to be placed at the top of the blob.
end
+ def project_id
+ @project&.id
+ end
+
# Present for compatibility with license templates, which can replace text
# like `[fullname]` with a user-specified string. This is a no-op for
# other templates
@@ -76,7 +81,7 @@ module Gitlab
end
# Defines which strategy will be used to get templates files
- # RepoTemplateFinder - Finds templates on project repository, templates are filtered perproject
+ # RepoTemplateFinder - Finds templates on project repository, templates are filtered per project
# GlobalTemplateFinder - Finds templates on gitlab installation source, templates can be used in all projects
def finder(project = nil)
raise NotImplementedError
@@ -95,19 +100,29 @@ module Gitlab
File.join(base_dir, categories[category])
end
- # If template is organized by category it returns { category_name: [{ name: template_name }, { name: template2_name }] }
- # If no category is present returns [{ name: template_name }, { name: template2_name}]
- def dropdown_names(project = nil)
- return [] if project && !project.repository.exists?
+ # `repository_template_names` - reads through Gitaly the actual templates names within a
+ # given project's repository. This is only used by issue and merge request templates,
+ # that need to call this once and then cache the returned value.
+ #
+ # `template_names` - is an alias to `repository_template_names`. It would read through
+ # Gitaly the actual template names within a given project's repository for all file templates
+ # other than `issue` and `merge request` description templates, which would instead
+ # overwrite the `template_names` method to return a redis cached version, by reading cached values
+ # from `repository.issue_template_names_by_category` and `repository.merge_request_template_names_by_category`
+ # methods.
+ def repository_template_names(project)
+ template_names_by_category(self.all(project))
+ end
+ alias_method :template_names, :repository_template_names
- if categories.any?
- categories.keys.map do |category|
- files = self.by_category(category, project)
- [category, files.map { |t| { name: t.name } }]
- end.to_h
- else
- files = self.all(project)
- files.map { |t| { name: t.name } }
+ def template_names_by_category(items)
+ grouped = items.group_by(&:category)
+ categories = grouped.keys
+
+ categories.each_with_object({}) do |category, hash|
+ hash[category] = grouped[category].map do |item|
+ { name: item.name, id: item.key, key: item.key, project_id: item.try(:project_id) }
+ end
end
end
diff --git a/lib/gitlab/template/finders/global_template_finder.rb b/lib/gitlab/template/finders/global_template_finder.rb
index 9b39d386674..6d2677175e6 100644
--- a/lib/gitlab/template/finders/global_template_finder.rb
+++ b/lib/gitlab/template/finders/global_template_finder.rb
@@ -5,9 +5,10 @@ module Gitlab
module Template
module Finders
class GlobalTemplateFinder < BaseTemplateFinder
- def initialize(base_dir, extension, categories = {}, excluded_patterns: [])
+ def initialize(base_dir, extension, categories = {}, include_categories_for_file = {}, excluded_patterns: [])
@categories = categories
@extension = extension
+ @include_categories_for_file = include_categories_for_file
@excluded_patterns = excluded_patterns
super(base_dir)
@@ -47,7 +48,9 @@ module Gitlab
end
def select_directory(file_name)
- @categories.keys.find do |category|
+ categories = @categories
+ categories.merge!(@include_categories_for_file[file_name]) if @include_categories_for_file[file_name].present?
+ categories.keys.find do |category|
File.exist?(File.join(category_directory(category), file_name))
end
end
diff --git a/lib/gitlab/template/finders/repo_template_finder.rb b/lib/gitlab/template/finders/repo_template_finder.rb
index 8e234148a63..9f0ba97bcdf 100644
--- a/lib/gitlab/template/finders/repo_template_finder.rb
+++ b/lib/gitlab/template/finders/repo_template_finder.rb
@@ -11,8 +11,8 @@ module Gitlab
def initialize(project, base_dir, extension, categories = {})
@categories = categories
@extension = extension
- @repository = project.repository
- @commit = @repository.head_commit if @repository.exists?
+ @repository = project&.repository
+ @commit = @repository.head_commit if @repository&.exists?
super(base_dir)
end
@@ -51,7 +51,7 @@ module Gitlab
private
def select_directory(file_name)
- return [] unless @commit
+ return unless @commit
# Insert root as directory
directories = ["", *@categories.keys]
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index c295cc75da5..01158cafc4f 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -25,6 +25,12 @@ module Gitlab
}
end
+ def include_categories_for_file
+ {
+ "SAST#{self.extension}" => { 'Security' => 'Security' }
+ }
+ end
+
def excluded_patterns
strong_memoize(:excluded_patterns) do
BASE_EXCLUDED_PATTERNS + additional_excluded_patterns
@@ -41,7 +47,11 @@ module Gitlab
def finder(project = nil)
Gitlab::Template::Finders::GlobalTemplateFinder.new(
- self.base_dir, self.extension, self.categories, excluded_patterns: self.excluded_patterns
+ self.base_dir,
+ self.extension,
+ self.categories,
+ self.include_categories_for_file,
+ excluded_patterns: self.excluded_patterns
)
end
end
diff --git a/lib/gitlab/template/issue_template.rb b/lib/gitlab/template/issue_template.rb
index 01b191733d4..3049f43b322 100644
--- a/lib/gitlab/template/issue_template.rb
+++ b/lib/gitlab/template/issue_template.rb
@@ -15,6 +15,16 @@ module Gitlab
def finder(project)
Gitlab::Template::Finders::RepoTemplateFinder.new(project, self.base_dir, self.extension, self.categories)
end
+
+ def template_names(project)
+ return {} unless project&.repository&.exists?
+
+ # here we rely on project.repository caching mechanism. Ideally we would want the template finder to have its
+ # own caching mechanism to avoid the back and forth call jumps between finder and model.
+ #
+ # follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279
+ project.repository.issue_template_names_by_category
+ end
end
end
end
diff --git a/lib/gitlab/template/merge_request_template.rb b/lib/gitlab/template/merge_request_template.rb
index 357b31cd82e..9442f3b13fb 100644
--- a/lib/gitlab/template/merge_request_template.rb
+++ b/lib/gitlab/template/merge_request_template.rb
@@ -15,6 +15,16 @@ module Gitlab
def finder(project)
Gitlab::Template::Finders::RepoTemplateFinder.new(project, self.base_dir, self.extension, self.categories)
end
+
+ def template_names(project)
+ return {} unless project&.repository&.exists?
+
+ # here we rely on project.repository caching mechanism. Ideally we would want the template finder to have its
+ # own caching mechanism to avoid the back and forth call jumps between finder and model.
+ #
+ # follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279
+ project.repository.merge_request_template_names_by_category
+ end
end
end
end
diff --git a/lib/gitlab/terraform/state_migration_helper.rb b/lib/gitlab/terraform/state_migration_helper.rb
new file mode 100644
index 00000000000..04c1cbd0373
--- /dev/null
+++ b/lib/gitlab/terraform/state_migration_helper.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Terraform
+ class StateMigrationHelper
+ class << self
+ def migrate_to_remote_storage(&block)
+ migrate_in_batches(
+ ::Terraform::StateVersion.with_files_stored_locally.preload_state,
+ ::Terraform::StateUploader::Store::REMOTE,
+ &block
+ )
+ end
+
+ private
+
+ def batch_size
+ ENV.fetch('MIGRATION_BATCH_SIZE', 10).to_i
+ end
+
+ def migrate_in_batches(versions, store, &block)
+ versions.find_each(batch_size: batch_size) do |version| # rubocop:disable CodeReuse/ActiveRecord
+ version.file.migrate!(store)
+
+ yield version if block_given?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index ca4afb4c19c..09697705361 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -24,8 +24,8 @@ module Gitlab
Gitlab::CurrentSettings.snowplow_enabled?
end
- def event(category, action, label: nil, property: nil, value: nil, context: [], standard_context: nil)
- context.push(standard_context.to_context) if standard_context
+ def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil) # rubocop:disable Metrics/ParameterLists
+ context += [Tracking::StandardContext.new(project: project, user: user, namespace: namespace).to_context]
snowplow.event(category, action, label: label, property: property, value: value, context: context)
product_analytics.event(category, action, label: label, property: property, value: value, context: context)
diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb
index 71dfe27dd5a..92fdd008249 100644
--- a/lib/gitlab/tracking/standard_context.rb
+++ b/lib/gitlab/tracking/standard_context.rb
@@ -3,38 +3,36 @@
module Gitlab
module Tracking
class StandardContext
- GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-1'.freeze
+ GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-3'.freeze
+ GITLAB_RAILS_SOURCE = 'gitlab-rails'.freeze
- def initialize(namespace: nil, project: nil, **data)
- @namespace = namespace
- @project = project
+ def initialize(namespace: nil, project: nil, user: nil, **data)
@data = data
end
- def namespace_id
- namespace&.id
+ def to_context
+ SnowplowTracker::SelfDescribingJson.new(GITLAB_STANDARD_SCHEMA_URL, to_h)
end
- def project_id
- @project&.id
+ def environment
+ return 'production' if Gitlab.com_and_canary?
+
+ return 'staging' if Gitlab.staging?
+
+ 'development'
end
- def to_context
- SnowplowTracker::SelfDescribingJson.new(GITLAB_STANDARD_SCHEMA_URL, to_h)
+ def source
+ GITLAB_RAILS_SOURCE
end
private
- def namespace
- @namespace || @project&.namespace
- end
-
def to_h
- public_methods(false).each_with_object({}) do |method, hash|
- next if method == :to_context
-
- hash[method] = public_send(method) # rubocop:disable GitlabSecurity/PublicSend
- end.merge(@data)
+ {
+ environment: environment,
+ source: source
+ }.merge(@data)
end
end
end
diff --git a/lib/gitlab/usage/docs/helper.rb b/lib/gitlab/usage/docs/helper.rb
new file mode 100644
index 00000000000..8483334800b
--- /dev/null
+++ b/lib/gitlab/usage/docs/helper.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Docs
+ # Helper with functions to be used by HAML templates
+ module Helper
+ HEADER = %w(field value).freeze
+ SKIP_KEYS = %i(description).freeze
+
+ def auto_generated_comment
+ <<-MARKDOWN.strip_heredoc
+ ---
+ 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/#designated-technical-writers
+ ---
+
+ <!---
+ This documentation is auto generated by a script.
+
+ Please do not edit this file directly, check generate_metrics_dictionary task on lib/tasks/gitlab/usage_data.rake.
+ --->
+
+ <!-- vale gitlab.Spelling = NO -->
+ MARKDOWN
+ end
+
+ def render_name(name)
+ "## `#{name}`\n"
+ end
+
+ def render_description(object)
+ object.description
+ end
+
+ def render_attribute_row(key, value)
+ value = Gitlab::Usage::Docs::ValueFormatter.format(key, value)
+ table_row(["`#{key}`", value])
+ end
+
+ def render_attributes_table(object)
+ <<~MARKDOWN
+
+ #{table_row(HEADER)}
+ #{table_row(HEADER.map { '---' })}
+ #{table_value_rows(object.attributes)}
+ MARKDOWN
+ end
+
+ def table_value_rows(attributes)
+ attributes.reject { |k, _| k.in?(SKIP_KEYS) }.map do |key, value|
+ render_attribute_row(key, value)
+ end.join("\n")
+ end
+
+ def table_row(array)
+ "| #{array.join(' | ')} |"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/docs/renderer.rb b/lib/gitlab/usage/docs/renderer.rb
new file mode 100644
index 00000000000..7a7c58005bb
--- /dev/null
+++ b/lib/gitlab/usage/docs/renderer.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Docs
+ class Renderer
+ include Gitlab::Usage::Docs::Helper
+ DICTIONARY_PATH = Rails.root.join('doc', 'development', 'usage_ping')
+ TEMPLATE_PATH = Rails.root.join('lib', 'gitlab', 'usage', 'docs', 'templates', 'default.md.haml')
+
+ def initialize(metrics_definitions)
+ @layout = Haml::Engine.new(File.read(TEMPLATE_PATH))
+ @metrics_definitions = metrics_definitions.sort
+ end
+
+ def contents
+ # Render and remove an extra trailing new line
+ @contents ||= @layout.render(self, metrics_definitions: @metrics_definitions).sub!(/\n(?=\Z)/, '')
+ end
+
+ def write
+ filename = DICTIONARY_PATH.join('dictionary.md').to_s
+
+ FileUtils.mkdir_p(DICTIONARY_PATH)
+ File.write(filename, contents)
+
+ filename
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/docs/templates/default.md.haml b/lib/gitlab/usage/docs/templates/default.md.haml
new file mode 100644
index 00000000000..86e93be66c7
--- /dev/null
+++ b/lib/gitlab/usage/docs/templates/default.md.haml
@@ -0,0 +1,28 @@
+= auto_generated_comment
+
+:plain
+ # Metrics Dictionary
+
+ This file is autogenerated, please do not edit directly.
+
+ To generate these files from the GitLab repository, run:
+
+ ```shell
+ bundle exec rake gitlab:usage_data:generate_metrics_dictionary
+ ```
+
+ The Metrics Dictionary is based on the following metrics definition YAML files:
+
+ - [`config/metrics`]('https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics')
+ - [`ee/config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/config/metrics)
+
+Each table includes a `milestone`, which corresponds to the GitLab version when the metric
+was released.
+\
+- metrics_definitions.each do |name, object|
+
+ = render_name(name)
+
+ = render_description(object)
+
+ = render_attributes_table(object)
diff --git a/lib/gitlab/usage/docs/value_formatter.rb b/lib/gitlab/usage/docs/value_formatter.rb
new file mode 100644
index 00000000000..a2dc9b081f8
--- /dev/null
+++ b/lib/gitlab/usage/docs/value_formatter.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Docs
+ class ValueFormatter
+ def self.format(key, value)
+ case key
+ when :key_path
+ "**`#{value}`**"
+ when :data_source
+ value.to_s.capitalize
+ when :product_group
+ "`#{value}`"
+ when :introduced_by_url
+ "[Introduced by](#{value})"
+ when :distribution, :tier
+ Array(value).join(', ')
+ else
+ value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metric.rb b/lib/gitlab/usage/metric.rb
index e1648c78168..f3469209f48 100644
--- a/lib/gitlab/usage/metric.rb
+++ b/lib/gitlab/usage/metric.rb
@@ -7,16 +7,16 @@ module Gitlab
InvalidMetricError = Class.new(RuntimeError)
- attr_accessor :default_generation_path, :value
+ attr_accessor :key_path, :value
- validates :default_generation_path, presence: true
+ validates :key_path, presence: true
def definition
- self.class.definitions[default_generation_path]
+ self.class.definitions[key_path]
end
- def unflatten_default_path
- unflatten(default_generation_path.split('.'), value)
+ def unflatten_key_path
+ unflatten(key_path.split('.'), value)
end
class << self
diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb
index 96e572bb3db..01d202e4d45 100644
--- a/lib/gitlab/usage/metric_definition.rb
+++ b/lib/gitlab/usage/metric_definition.rb
@@ -13,9 +13,8 @@ module Gitlab
@attributes = opts
end
- # The key is defined by default_generation and full_path
def key
- full_path[default_generation.to_sym]
+ key_path
end
def to_h
@@ -23,8 +22,10 @@ module Gitlab
end
def validate!
- self.class.schemer.validate(attributes.stringify_keys).map do |error|
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new("#{error["details"] || error['data_pointer']} for `#{path}`"))
+ unless skip_validation?
+ self.class.schemer.validate(attributes.stringify_keys).each do |error|
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Metric::InvalidMetricError.new("#{error["details"] || error['data_pointer']} for `#{path}`"))
+ end
end
end
@@ -79,6 +80,10 @@ module Gitlab
def method_missing(method, *args)
attributes[method] || super
end
+
+ def skip_validation?
+ !!attributes[:skip_validation]
+ end
end
end
end
diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
new file mode 100644
index 00000000000..1fc40798320
--- /dev/null
+++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Aggregates
+ UNION_OF_AGGREGATED_METRICS = 'OR'
+ INTERSECTION_OF_AGGREGATED_METRICS = 'AND'
+ ALLOWED_METRICS_AGGREGATIONS = [UNION_OF_AGGREGATED_METRICS, INTERSECTION_OF_AGGREGATED_METRICS].freeze
+ AGGREGATED_METRICS_PATH = Rails.root.join('lib/gitlab/usage_data_counters/aggregated_metrics/*.yml')
+ AggregatedMetricError = Class.new(StandardError)
+ UnknownAggregationOperator = Class.new(AggregatedMetricError)
+ UnknownAggregationSource = Class.new(AggregatedMetricError)
+
+ DATABASE_SOURCE = 'database'
+ REDIS_SOURCE = 'redis'
+
+ SOURCES = {
+ DATABASE_SOURCE => Sources::PostgresHll,
+ REDIS_SOURCE => Sources::RedisHll
+ }.freeze
+
+ class Aggregate
+ delegate :weekly_time_range,
+ :monthly_time_range,
+ to: Gitlab::UsageDataCounters::HLLRedisCounter
+
+ def initialize(recorded_at)
+ @aggregated_metrics = load_metrics(AGGREGATED_METRICS_PATH)
+ @recorded_at = recorded_at
+ end
+
+ def monthly_data
+ aggregated_metrics_data(**monthly_time_range)
+ end
+
+ def weekly_data
+ aggregated_metrics_data(**weekly_time_range)
+ end
+
+ private
+
+ attr_accessor :aggregated_metrics, :recorded_at
+
+ def aggregated_metrics_data(start_date:, end_date:)
+ aggregated_metrics.each_with_object({}) do |aggregation, data|
+ next if aggregation[:feature_flag] && Feature.disabled?(aggregation[:feature_flag], default_enabled: :yaml, type: :development)
+
+ case aggregation[:source]
+ when REDIS_SOURCE
+ data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
+ when DATABASE_SOURCE
+ next unless Feature.enabled?('database_sourced_aggregated_metrics', default_enabled: false, type: :development)
+
+ data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
+ else
+ Gitlab::ErrorTracking
+ .track_and_raise_for_dev_exception(UnknownAggregationSource.new("Aggregation source: '#{aggregation[:source]}' must be included in #{SOURCES.keys}"))
+
+ data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
+ end
+ end
+ end
+
+ def calculate_count_for_aggregation(aggregation:, start_date:, end_date:)
+ source = SOURCES[aggregation[:source]]
+
+ case aggregation[:operator]
+ when UNION_OF_AGGREGATED_METRICS
+ source.calculate_metrics_union(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
+ when INTERSECTION_OF_AGGREGATED_METRICS
+ calculate_metrics_intersections(source: source, metric_names: aggregation[:events], start_date: start_date, end_date: end_date)
+ else
+ Gitlab::ErrorTracking
+ .track_and_raise_for_dev_exception(UnknownAggregationOperator.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}"))
+ Gitlab::Utils::UsageData::FALLBACK
+ end
+ rescue Gitlab::UsageDataCounters::HLLRedisCounter::EventError, AggregatedMetricError => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
+ Gitlab::Utils::UsageData::FALLBACK
+ end
+
+ # calculate intersection of 'n' sets based on inclusion exclusion principle https://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle
+ # this method will be extracted to dedicated module with https://gitlab.com/gitlab-org/gitlab/-/issues/273391
+ def calculate_metrics_intersections(source:, metric_names:, start_date:, end_date:, subset_powers_cache: Hash.new({}))
+ # calculate power of intersection of all given metrics from inclusion exclusion principle
+ # |A + B + C| = (|A| + |B| + |C|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C|) =>
+ # |A & B & C| = - (|A| + |B| + |C|) + (|A & B| + |A & C| + .. + |C & D|) + |A + B + C|
+ # |A + B + C + D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A & B & C & D| =>
+ # |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A + B + C + D|
+
+ # calculate each components of equation except for the last one |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - ...
+ subset_powers_data = subsets_intersection_powers(source, metric_names, start_date, end_date, subset_powers_cache)
+
+ # calculate last component of the equation |A & B & C & D| = .... - |A + B + C + D|
+ power_of_union_of_all_metrics = begin
+ subset_powers_cache[metric_names.size][metric_names.join('_+_')] ||= \
+ source.calculate_metrics_union(metric_names: metric_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at)
+ end
+
+ # in order to determine if part of equation (|A & B & C|, |A & B & C & D|), that represents the intersection that we need to calculate,
+ # is positive or negative in particular equation we need to determine if number of subsets is even or odd. Please take a look at two examples below
+ # |A + B + C| = (|A| + |B| + |C|) - (|A & B| + |A & C| + .. + |C & D|) + |A & B & C| =>
+ # |A & B & C| = - (|A| + |B| + |C|) + (|A & B| + |A & C| + .. + |C & D|) + |A + B + C|
+ # |A + B + C + D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A & B & C & D| =>
+ # |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A + B + C + D|
+ subset_powers_size_even = subset_powers_data.size.even?
+
+ # sum all components of equation except for the last one |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - ... =>
+ sum_of_all_subset_powers = sum_subset_powers(subset_powers_data, subset_powers_size_even)
+
+ # add last component of the equation |A & B & C & D| = sum_of_all_subset_powers - |A + B + C + D|
+ sum_of_all_subset_powers + (subset_powers_size_even ? power_of_union_of_all_metrics : -power_of_union_of_all_metrics)
+ end
+
+ def sum_subset_powers(subset_powers_data, subset_powers_size_even)
+ sum_without_sign = subset_powers_data.to_enum.with_index.sum do |value, index|
+ (index + 1).odd? ? value : -value
+ end
+
+ (subset_powers_size_even ? -1 : 1) * sum_without_sign
+ end
+
+ def subsets_intersection_powers(source, metric_names, start_date, end_date, subset_powers_cache)
+ subset_sizes = (1...metric_names.size)
+
+ subset_sizes.map do |subset_size|
+ if subset_size > 1
+ # calculate sum of powers of intersection between each subset (with given size) of metrics: #|A + B + C + D| = ... - (|A & B| + |A & C| + .. + |C & D|)
+ metric_names.combination(subset_size).sum do |metrics_subset|
+ subset_powers_cache[subset_size][metrics_subset.join('_&_')] ||=
+ calculate_metrics_intersections(source: source, metric_names: metrics_subset, start_date: start_date, end_date: end_date, subset_powers_cache: subset_powers_cache)
+ end
+ else
+ # calculate sum of powers of each set (metric) alone #|A + B + C + D| = (|A| + |B| + |C| + |D|) - ...
+ metric_names.sum do |metric|
+ subset_powers_cache[subset_size][metric] ||= \
+ source.calculate_metrics_union(metric_names: metric, start_date: start_date, end_date: end_date, recorded_at: recorded_at)
+ end
+ end
+ end
+ end
+
+ def load_metrics(wildcard)
+ Dir[wildcard].each_with_object([]) do |path, metrics|
+ metrics.push(*load_yaml_from_path(path))
+ end
+ end
+
+ def load_yaml_from_path(path)
+ YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb b/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
new file mode 100644
index 00000000000..33678d2b813
--- /dev/null
+++ b/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Aggregates
+ module Sources
+ class PostgresHll
+ class << self
+ def calculate_metrics_union(metric_names:, start_date:, end_date:, recorded_at:)
+ time_period = start_date && end_date ? (start_date..end_date) : nil
+
+ Array(metric_names).each_with_object(Gitlab::Database::PostgresHll::Buckets.new) do |event, buckets|
+ json = read_aggregated_metric(metric_name: event, time_period: time_period, recorded_at: recorded_at)
+ raise UnionNotAvailable, "Union data not available for #{metric_names}" unless json
+
+ buckets.merge_hash!(Gitlab::Json.parse(json))
+ end.estimated_distinct_count
+ end
+
+ def save_aggregated_metrics(metric_name:, time_period:, recorded_at_timestamp:, data:)
+ unless data.is_a? ::Gitlab::Database::PostgresHll::Buckets
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(StandardError.new("Unsupported data type: #{data.class}"))
+ return
+ end
+
+ # Usage Ping report generation for gitlab.com is very long running process
+ # to make sure that saved keys are available at the end of report generation process
+ # lets use triple max generation time
+ keys_expiration = ::Gitlab::UsageData::MAX_GENERATION_TIME_FOR_SAAS * 3
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(
+ redis_key(metric_name: metric_name, time_period: time_period&.values&.first, recorded_at: recorded_at_timestamp),
+ data.to_json,
+ ex: keys_expiration
+ )
+ end
+ rescue ::Redis::CommandError => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
+ end
+
+ private
+
+ def read_aggregated_metric(metric_name:, time_period:, recorded_at:)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.get(redis_key(metric_name: metric_name, time_period: time_period, recorded_at: recorded_at))
+ end
+ end
+
+ def redis_key(metric_name:, time_period:, recorded_at:)
+ # add timestamp at the end of the key to avoid stale keys if
+ # usage ping job is retried
+ "#{metric_name}_#{time_period_to_human_name(time_period)}-#{recorded_at.to_i}"
+ end
+
+ def time_period_to_human_name(time_period)
+ return Gitlab::Utils::UsageData::ALL_TIME_PERIOD_HUMAN_NAME if time_period.blank?
+
+ start_date = time_period.first.to_date
+ end_date = time_period.last.to_date
+
+ if (end_date - start_date).to_i > 7
+ Gitlab::Utils::UsageData::MONTHLY_PERIOD_HUMAN_NAME
+ else
+ Gitlab::Utils::UsageData::WEEKLY_PERIOD_HUMAN_NAME
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/aggregates/sources/redis_hll.rb b/lib/gitlab/usage/metrics/aggregates/sources/redis_hll.rb
new file mode 100644
index 00000000000..f3a4dcf1e31
--- /dev/null
+++ b/lib/gitlab/usage/metrics/aggregates/sources/redis_hll.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Aggregates
+ module Sources
+ UnionNotAvailable = Class.new(AggregatedMetricError)
+
+ class RedisHll
+ def self.calculate_metrics_union(metric_names:, start_date:, end_date:, recorded_at: nil)
+ union = Gitlab::UsageDataCounters::HLLRedisCounter
+ .calculate_events_union(event_names: metric_names, start_date: start_date, end_date: end_date)
+
+ return union if union >= 0
+
+ raise UnionNotAvailable, "Union data not available for #{metric_names}"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index f935c677930..8e096a9f351 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -12,6 +12,9 @@
# redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
module Gitlab
class UsageData
+ DEPRECATED_VALUE = -1000
+ MAX_GENERATION_TIME_FOR_SAAS = 40.hours
+
CE_MEMOIZED_VALUES = %i(
issue_minimum_id
issue_maximum_id
@@ -23,6 +26,8 @@ module Gitlab
deployment_minimum_id
deployment_maximum_id
auth_providers
+ aggregated_metrics
+ recorded_at
).freeze
class << self
@@ -75,7 +80,7 @@ module Gitlab
end
def recorded_at
- Time.current
+ @recorded_at ||= Time.current
end
# rubocop: disable Metrics/AbcSize
@@ -158,7 +163,7 @@ module Gitlab
projects_with_repositories_enabled: count(ProjectFeature.where('repository_access_level > ?', ProjectFeature::DISABLED)),
projects_with_tracing_enabled: count(ProjectTracingSetting),
projects_with_error_tracking_enabled: count(::ErrorTracking::ProjectErrorTrackingSetting.where(enabled: true)),
- projects_with_alerts_service_enabled: count(AlertsService.active),
+ projects_with_alerts_service_enabled: count(Service.active.where(type: 'AlertsService')),
projects_with_alerts_created: distinct_count(::AlertManagement::Alert, :project_id),
projects_with_enabled_alert_integrations: distinct_count(::AlertManagement::HttpIntegration.active, :project_id),
projects_with_prometheus_alerts: distinct_count(PrometheusAlert, :project_id),
@@ -580,27 +585,35 @@ module Gitlab
users_created: count(::User.where(time_period), start: user_minimum_id, finish: user_maximum_id),
omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' },
user_auth_by_provider: distinct_count_user_auth_by_provider(time_period),
+ unique_users_all_imports: unique_users_all_imports(time_period),
bulk_imports: {
- gitlab: distinct_count(::BulkImport.where(time_period, source_type: :gitlab), :user_id)
+ gitlab: DEPRECATED_VALUE,
+ gitlab_v1: count(::BulkImport.where(time_period, source_type: :gitlab))
},
+ project_imports: project_imports(time_period),
+ issue_imports: issue_imports(time_period),
+ group_imports: group_imports(time_period),
+
+ # Deprecated data to be removed
projects_imported: {
- total: distinct_count(::Project.where(time_period).where.not(import_type: nil), :creator_id),
- gitlab_project: projects_imported_count('gitlab_project', time_period),
- gitlab: projects_imported_count('gitlab', time_period),
- github: projects_imported_count('github', time_period),
- bitbucket: projects_imported_count('bitbucket', time_period),
- bitbucket_server: projects_imported_count('bitbucket_server', time_period),
- gitea: projects_imported_count('gitea', time_period),
- git: projects_imported_count('git', time_period),
- manifest: projects_imported_count('manifest', time_period)
+ total: DEPRECATED_VALUE,
+ gitlab_project: DEPRECATED_VALUE,
+ gitlab: DEPRECATED_VALUE,
+ github: DEPRECATED_VALUE,
+ bitbucket: DEPRECATED_VALUE,
+ bitbucket_server: DEPRECATED_VALUE,
+ gitea: DEPRECATED_VALUE,
+ git: DEPRECATED_VALUE,
+ manifest: DEPRECATED_VALUE
},
issues_imported: {
- jira: distinct_count(::JiraImportState.where(time_period), :user_id),
- fogbugz: projects_imported_count('fogbugz', time_period),
- phabricator: projects_imported_count('phabricator', time_period),
- csv: distinct_count(Issues::CsvImport.where(time_period), :user_id)
+ jira: DEPRECATED_VALUE,
+ fogbugz: DEPRECATED_VALUE,
+ phabricator: DEPRECATED_VALUE,
+ csv: DEPRECATED_VALUE
},
- groups_imported: distinct_count(::GroupImportState.where(time_period), :user_id)
+ groups_imported: DEPRECATED_VALUE
+ # End of deprecated keys
}
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -690,13 +703,13 @@ module Gitlab
def aggregated_metrics_monthly
{
- aggregated_metrics: ::Gitlab::UsageDataCounters::HLLRedisCounter.aggregated_metrics_monthly_data
+ aggregated_metrics: aggregated_metrics.monthly_data
}
end
def aggregated_metrics_weekly
{
- aggregated_metrics: ::Gitlab::UsageDataCounters::HLLRedisCounter.aggregated_metrics_weekly_data
+ aggregated_metrics: aggregated_metrics.weekly_data
}
end
@@ -741,6 +754,10 @@ module Gitlab
private
+ def aggregated_metrics
+ @aggregated_metrics ||= ::Gitlab::Usage::Metrics::Aggregates::Aggregate.new(recorded_at)
+ end
+
def event_monthly_active_users(date_range)
data = {
action_monthly_active_users_project_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION,
@@ -893,10 +910,52 @@ module Gitlab
count relation, start: deployment_minimum_id, finish: deployment_maximum_id
end
+ def project_imports(time_period)
+ {
+ gitlab_project: projects_imported_count('gitlab_project', time_period),
+ gitlab: projects_imported_count('gitlab', time_period),
+ github: projects_imported_count('github', time_period),
+ bitbucket: projects_imported_count('bitbucket', time_period),
+ bitbucket_server: projects_imported_count('bitbucket_server', time_period),
+ gitea: projects_imported_count('gitea', time_period),
+ git: projects_imported_count('git', time_period),
+ manifest: projects_imported_count('manifest', time_period),
+ gitlab_migration: count(::BulkImports::Entity.where(time_period).project_entity) # rubocop: disable CodeReuse/ActiveRecord
+ }
+ end
+
def projects_imported_count(from, time_period)
- distinct_count(::Project.imported_from(from).where(time_period).where.not(import_type: nil), :creator_id) # rubocop: disable CodeReuse/ActiveRecord
+ count(::Project.imported_from(from).where(time_period).where.not(import_type: nil)) # rubocop: disable CodeReuse/ActiveRecord
end
+ def issue_imports(time_period)
+ {
+ jira: count(::JiraImportState.where(time_period)), # rubocop: disable CodeReuse/ActiveRecord
+ fogbugz: projects_imported_count('fogbugz', time_period),
+ phabricator: projects_imported_count('phabricator', time_period),
+ csv: count(Issues::CsvImport.where(time_period)) # rubocop: disable CodeReuse/ActiveRecord
+ }
+ end
+
+ def group_imports(time_period)
+ {
+ group_import: count(::GroupImportState.where(time_period)), # rubocop: disable CodeReuse/ActiveRecord
+ gitlab_migration: count(::BulkImports::Entity.where(time_period).group_entity) # rubocop: disable CodeReuse/ActiveRecord
+ }
+ end
+
+ # rubocop:disable CodeReuse/ActiveRecord
+ def unique_users_all_imports(time_period)
+ project_imports = distinct_count(::Project.where(time_period).where.not(import_type: nil), :creator_id)
+ bulk_imports = distinct_count(::BulkImport.where(time_period), :user_id)
+ jira_issue_imports = distinct_count(::JiraImportState.where(time_period), :user_id)
+ csv_issue_imports = distinct_count(Issues::CsvImport.where(time_period), :user_id)
+ group_imports = distinct_count(::GroupImportState.where(time_period), :user_id)
+
+ project_imports + bulk_imports + jira_issue_imports + csv_issue_imports + group_imports
+ end
+ # rubocop:enable CodeReuse/ActiveRecord
+
# rubocop:disable CodeReuse/ActiveRecord
def distinct_count_user_auth_by_provider(time_period)
counts = auth_providers_except_ldap.each_with_object({}) do |provider, hash|
diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
index 4966afd534a..4d92202e7fd 100644
--- a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
+++ b/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml
@@ -4,21 +4,28 @@
# - "AND": counts unique elements that were observed triggering all of following events
# events: list of events names to aggregate into metric. All events in this list must have the same 'redis_slot' and 'aggregation' attributes
# see from lib/gitlab/usage_data_counters/known_events/ for the list of valid events.
+# source: defines which datasource will be used to locate events that should be included in aggregated metric. Valid values are:
+# - database
+# - redis
# feature_flag: name of development feature flag that will be checked before metrics aggregation is performed.
# Corresponding feature flag should have `default_enabled` attribute set to `false`.
# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
---
- name: compliance_features_track_unique_visits_union
operator: OR
+ source: redis
events: ['g_compliance_audit_events', 'g_compliance_dashboard', 'i_compliance_audit_events', 'a_compliance_audit_events_api', 'i_compliance_credential_inventory']
- name: product_analytics_test_metrics_union
operator: OR
+ source: redis
events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
- name: product_analytics_test_metrics_intersection
operator: AND
+ source: redis
events: ['i_search_total', 'i_search_advanced', 'i_search_paid']
- name: incident_management_alerts_total_unique_counts
operator: OR
+ source: redis
events: [
'incident_management_alert_status_changed',
'incident_management_alert_assigned',
@@ -27,6 +34,7 @@
]
- name: incident_management_incidents_total_unique_counts
operator: OR
+ source: redis
events: [
'incident_management_incident_created',
'incident_management_incident_reopened',
@@ -40,3 +48,13 @@
'incident_management_incident_unrelate',
'incident_management_incident_change_confidential'
]
+- name: i_testing_paid_monthly_active_user_total
+ operator: OR
+ source: redis
+ events: [
+ 'i_testing_web_performance_widget_total',
+ 'i_testing_full_code_quality_report_total',
+ 'i_testing_group_code_coverage_visit_total',
+ 'i_testing_load_performance_widget_total',
+ 'i_testing_metrics_report_widget_total'
+]
diff --git a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
index 572ad866895..772a4623280 100644
--- a/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/ci_template_unique_counter.rb
@@ -4,7 +4,9 @@ module Gitlab::UsageDataCounters
class CiTemplateUniqueCounter
REDIS_SLOT = 'ci_templates'.freeze
+ # NOTE: Events originating from implicit Auto DevOps pipelines get prefixed with `implicit_`
TEMPLATE_TO_EVENT = {
+ '5-Minute-Production-App.gitlab-ci.yml' => '5_min_production_app',
'Auto-DevOps.gitlab-ci.yml' => 'auto_devops',
'AWS/CF-Provision-and-Deploy-EC2.gitlab-ci.yml' => 'aws_cf_deploy_ec2',
'AWS/Deploy-ECS.gitlab-ci.yml' => 'aws_deploy_ecs',
@@ -17,19 +19,21 @@ module Gitlab::UsageDataCounters
}.freeze
class << self
- def track_unique_project_event(project_id:, template:)
+ def track_unique_project_event(project_id:, template:, config_source:)
return if Feature.disabled?(:usage_data_track_ci_templates_unique_projects, default_enabled: :yaml)
- if event = unique_project_event(template)
+ if event = unique_project_event(template, config_source)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event, values: project_id)
end
end
private
- def unique_project_event(template)
+ def unique_project_event(template, config_source)
if name = TEMPLATE_TO_EVENT[template]
- "p_#{REDIS_SLOT}_#{name}"
+ prefix = 'implicit_' if config_source.to_s == 'auto_devops_source'
+
+ "p_#{REDIS_SLOT}_#{prefix}#{name}"
end
end
end
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 47361d831b2..68ae239debb 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -13,15 +13,10 @@ module Gitlab
AggregationMismatch = Class.new(EventError)
SlotMismatch = Class.new(EventError)
CategoryMismatch = Class.new(EventError)
- UnknownAggregationOperator = Class.new(EventError)
InvalidContext = Class.new(EventError)
KNOWN_EVENTS_PATH = File.expand_path('known_events/*.yml', __dir__)
ALLOWED_AGGREGATIONS = %i(daily weekly).freeze
- UNION_OF_AGGREGATED_METRICS = 'OR'
- INTERSECTION_OF_AGGREGATED_METRICS = 'AND'
- ALLOWED_METRICS_AGGREGATIONS = [UNION_OF_AGGREGATED_METRICS, INTERSECTION_OF_AGGREGATED_METRICS].freeze
- AGGREGATED_METRICS_PATH = File.expand_path('aggregated_metrics/*.yml', __dir__)
# Track event on entity_id
# Increment a Redis HLL counter for unique event_name and entity_id
@@ -90,37 +85,40 @@ module Gitlab
events_names = events_for_category(category)
event_results = events_names.each_with_object({}) do |event, hash|
- hash["#{event}_weekly"] = unique_events(event_names: [event], start_date: 7.days.ago.to_date, end_date: Date.current)
- hash["#{event}_monthly"] = unique_events(event_names: [event], start_date: 4.weeks.ago.to_date, end_date: Date.current)
+ hash["#{event}_weekly"] = unique_events(**weekly_time_range.merge(event_names: [event]))
+ hash["#{event}_monthly"] = unique_events(**monthly_time_range.merge(event_names: [event]))
end
if eligible_for_totals?(events_names)
- event_results["#{category}_total_unique_counts_weekly"] = unique_events(event_names: events_names, start_date: 7.days.ago.to_date, end_date: Date.current)
- event_results["#{category}_total_unique_counts_monthly"] = unique_events(event_names: events_names, start_date: 4.weeks.ago.to_date, end_date: Date.current)
+ event_results["#{category}_total_unique_counts_weekly"] = unique_events(**weekly_time_range.merge(event_names: events_names))
+ event_results["#{category}_total_unique_counts_monthly"] = unique_events(**monthly_time_range.merge(event_names: events_names))
end
category_results["#{category}"] = event_results
end
end
- def known_event?(event_name)
- event_for(event_name).present?
+ def weekly_time_range
+ { start_date: 7.days.ago.to_date, end_date: Date.current }
end
- def aggregated_metrics_monthly_data
- aggregated_metrics_data(4.weeks.ago.to_date)
+ def monthly_time_range
+ { start_date: 4.weeks.ago.to_date, end_date: Date.current }
end
- def aggregated_metrics_weekly_data
- aggregated_metrics_data(7.days.ago.to_date)
+ def known_event?(event_name)
+ event_for(event_name).present?
end
def known_events
@known_events ||= load_events(KNOWN_EVENTS_PATH)
end
- def aggregated_metrics
- @aggregated_metrics ||= load_events(AGGREGATED_METRICS_PATH)
+ def calculate_events_union(event_names:, start_date:, end_date:)
+ count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date) do |events|
+ raise SlotMismatch, events unless events_in_same_slot?(events)
+ raise AggregationMismatch, events unless events_same_aggregation?(events)
+ end
end
private
@@ -131,6 +129,8 @@ module Gitlab
event = event_for(event_name)
raise UnknownEvent, "Unknown event #{event_name}" unless event.present?
+ return unless feature_enabled?(event)
+
Gitlab::Redis::HLL.add(key: redis_key(event, time, context), value: values, expiry: expiry(event))
end
@@ -139,93 +139,6 @@ module Gitlab
Plan.all_plans
end
- def aggregated_metrics_data(start_date)
- aggregated_metrics.each_with_object({}) do |aggregation, weekly_data|
- next if aggregation[:feature_flag] && Feature.disabled?(aggregation[:feature_flag], default_enabled: false, type: :development)
-
- weekly_data[aggregation[:name]] = calculate_count_for_aggregation(aggregation, start_date: start_date, end_date: Date.current)
- end
- end
-
- def calculate_count_for_aggregation(aggregation, start_date:, end_date:)
- case aggregation[:operator]
- when UNION_OF_AGGREGATED_METRICS
- calculate_events_union(event_names: aggregation[:events], start_date: start_date, end_date: end_date)
- when INTERSECTION_OF_AGGREGATED_METRICS
- calculate_events_intersections(event_names: aggregation[:events], start_date: start_date, end_date: end_date)
- else
- raise UnknownAggregationOperator, "Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}"
- end
- end
-
- # calculate intersection of 'n' sets based on inclusion exclusion principle https://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle
- # this method will be extracted to dedicated module with https://gitlab.com/gitlab-org/gitlab/-/issues/273391
- def calculate_events_intersections(event_names:, start_date:, end_date:, subset_powers_cache: Hash.new({}))
- # calculate power of intersection of all given metrics from inclusion exclusion principle
- # |A + B + C| = (|A| + |B| + |C|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C|) =>
- # |A & B & C| = - (|A| + |B| + |C|) + (|A & B| + |A & C| + .. + |C & D|) + |A + B + C|
- # |A + B + C + D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A & B & C & D| =>
- # |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A + B + C + D|
-
- # calculate each components of equation except for the last one |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - ...
- subset_powers_data = subsets_intersection_powers(event_names, start_date, end_date, subset_powers_cache)
-
- # calculate last component of the equation |A & B & C & D| = .... - |A + B + C + D|
- power_of_union_of_all_events = begin
- subset_powers_cache[event_names.size][event_names.join('_+_')] ||= \
- calculate_events_union(event_names: event_names, start_date: start_date, end_date: end_date)
- end
-
- # in order to determine if part of equation (|A & B & C|, |A & B & C & D|), that represents the intersection that we need to calculate,
- # is positive or negative in particular equation we need to determine if number of subsets is even or odd. Please take a look at two examples below
- # |A + B + C| = (|A| + |B| + |C|) - (|A & B| + |A & C| + .. + |C & D|) + |A & B & C| =>
- # |A & B & C| = - (|A| + |B| + |C|) + (|A & B| + |A & C| + .. + |C & D|) + |A + B + C|
- # |A + B + C + D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A & B & C & D| =>
- # |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - |A + B + C + D|
- subset_powers_size_even = subset_powers_data.size.even?
-
- # sum all components of equation except for the last one |A & B & C & D| = (|A| + |B| + |C| + |D|) - (|A & B| + |A & C| + .. + |C & D|) + (|A & B & C| + |B & C & D|) - ... =>
- sum_of_all_subset_powers = sum_subset_powers(subset_powers_data, subset_powers_size_even)
-
- # add last component of the equation |A & B & C & D| = sum_of_all_subset_powers - |A + B + C + D|
- sum_of_all_subset_powers + (subset_powers_size_even ? power_of_union_of_all_events : -power_of_union_of_all_events)
- end
-
- def sum_subset_powers(subset_powers_data, subset_powers_size_even)
- sum_without_sign = subset_powers_data.to_enum.with_index.sum do |value, index|
- (index + 1).odd? ? value : -value
- end
-
- (subset_powers_size_even ? -1 : 1) * sum_without_sign
- end
-
- def subsets_intersection_powers(event_names, start_date, end_date, subset_powers_cache)
- subset_sizes = (1..(event_names.size - 1))
-
- subset_sizes.map do |subset_size|
- if subset_size > 1
- # calculate sum of powers of intersection between each subset (with given size) of metrics: #|A + B + C + D| = ... - (|A & B| + |A & C| + .. + |C & D|)
- event_names.combination(subset_size).sum do |events_subset|
- subset_powers_cache[subset_size][events_subset.join('_&_')] ||= \
- calculate_events_intersections(event_names: events_subset, start_date: start_date, end_date: end_date, subset_powers_cache: subset_powers_cache)
- end
- else
- # calculate sum of powers of each set (metric) alone #|A + B + C + D| = (|A| + |B| + |C| + |D|) - ...
- event_names.sum do |event|
- subset_powers_cache[subset_size][event] ||= \
- unique_events(event_names: event, start_date: start_date, end_date: end_date)
- end
- end
- end
- end
-
- def calculate_events_union(event_names:, start_date:, end_date:)
- count_unique_events(event_names: event_names, start_date: start_date, end_date: end_date) do |events|
- raise SlotMismatch, events unless events_in_same_slot?(events)
- raise AggregationMismatch, events unless events_same_aggregation?(events)
- end
- end
-
def count_unique_events(event_names:, start_date:, end_date:, context: '')
events = events_for(Array(event_names).map(&:to_s))
@@ -237,6 +150,12 @@ module Gitlab
redis_usage_data { Gitlab::Redis::HLL.count(keys: keys) }
end
+ def feature_enabled?(event)
+ return true if event[:feature_flag].blank?
+
+ Feature.enabled?(event[:feature_flag], default_enabled: :yaml)
+ end
+
# Allow to add totals for events that are in the same redis slot, category and have the same aggregation level
# and if there are more than 1 event
def eligible_for_totals?(events_names)
@@ -340,12 +259,6 @@ module Gitlab
end.flatten
end
- def validate_aggregation_operator!(operator)
- return true if ALLOWED_METRICS_AGGREGATIONS.include?(operator)
-
- raise UnknownAggregationOperator.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}")
- end
-
def weekly_redis_keys(events:, start_date:, end_date:, context: '')
end_date = end_date.end_of_week - 1.week
(start_date.to_date..end_date.to_date).map do |date|
diff --git a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
index f649e7f407d..c2662a74432 100644
--- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -145,7 +145,6 @@ module Gitlab
private
def track_unique_action(action, author, time)
- return unless Feature.enabled?(:track_issue_activity_actions, default_enabled: true)
return unless author
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id, time: time)
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
new file mode 100644
index 00000000000..9c19c9e8b8c
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -0,0 +1,91 @@
+# Implicit Auto DevOps pipeline events
+- name: p_ci_templates_implicit_auto_devops
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_implicit_auto_devops_build
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_implicit_auto_devops_deploy
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_implicit_security_sast
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_implicit_security_secret_detection
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+# Explicit include:template pipeline events
+- name: p_ci_templates_5_min_production_app
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_auto_devops
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_aws_cf_deploy_ec2
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_aws_deploy_ecs
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_auto_devops_build
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_auto_devops_deploy
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_auto_devops_deploy_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_security_sast
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_security_secret_detection
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
+
+- name: p_ci_templates_terraform_base_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
+ feature_flag: usage_data_track_ci_templates_unique_projects
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
new file mode 100644
index 00000000000..d657c5487d7
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
@@ -0,0 +1,166 @@
+---
+- name: i_code_review_mr_diffs
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_mr_diffs
+- name: i_code_review_user_single_file_diffs
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_single_file_diffs
+- name: i_code_review_mr_single_file_diffs
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_mr_single_file_diffs
+- name: i_code_review_user_toggled_task_item_status
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_toggled_task_item_status
+- name: i_code_review_user_create_mr
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_create_mr
+- name: i_code_review_user_close_mr
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_close_mr
+- name: i_code_review_user_reopen_mr
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_reopen_mr
+- name: i_code_review_user_approve_mr
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_approve_mr
+- name: i_code_review_user_unapprove_mr
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_unapprove_mr
+- name: i_code_review_user_resolve_thread
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_resolve_thread
+- name: i_code_review_user_unresolve_thread
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_unresolve_thread
+- name: i_code_review_edit_mr_title
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_edit_mr_title
+- name: i_code_review_edit_mr_desc
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_edit_mr_desc
+- name: i_code_review_user_merge_mr
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_merge_mr
+- name: i_code_review_user_create_mr_comment
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_create_mr_comment
+- name: i_code_review_user_edit_mr_comment
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_edit_mr_comment
+- name: i_code_review_user_remove_mr_comment
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_remove_mr_comment
+- name: i_code_review_user_create_review_note
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_create_review_note
+- name: i_code_review_user_publish_review
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_publish_review
+- name: i_code_review_user_create_multiline_mr_comment
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_create_multiline_mr_comment
+- name: i_code_review_user_edit_multiline_mr_comment
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_edit_multiline_mr_comment
+- name: i_code_review_user_remove_multiline_mr_comment
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_remove_multiline_mr_comment
+- name: i_code_review_user_add_suggestion
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_add_suggestion
+- name: i_code_review_user_apply_suggestion
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_apply_suggestion
+- name: i_code_review_user_assigned
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_assigned
+- name: i_code_review_user_marked_as_draft
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_marked_as_draft
+- name: i_code_review_user_unmarked_as_draft
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_unmarked_as_draft
+- name: i_code_review_user_review_requested
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_review_requested
+- name: i_code_review_user_approval_rule_added
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_approval_rule_added
+- name: i_code_review_user_approval_rule_deleted
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_approval_rule_deleted
+- name: i_code_review_user_approval_rule_edited
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_approval_rule_edited
+- name: i_code_review_user_vs_code_api_request
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_vs_code_api_request
+- name: i_code_review_user_create_mr_from_issue
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+ feature_flag: usage_data_i_code_review_user_create_mr_from_issue
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index 4cbde0c0372..79f319b2d58 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -268,172 +268,154 @@
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_i_testing_web_performance_widget_total
+- name: i_testing_group_code_coverage_project_click_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_group_code_coverage_project_click_total
+- name: i_testing_load_performance_widget_total
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_load_performance_widget_total
+- name: i_testing_metrics_report_artifact_uploaders
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_metrics_report_artifact_uploaders
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_description_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_assignee_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_made_confidential
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_made_visible
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_created
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_closed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_reopened
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_label_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_milestone_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_iteration_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_weight_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_cross_referenced
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_moved
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_related
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_unrelated
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_marked_as_duplicate
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_locked
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_unlocked
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_added_to_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_removed_from_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_changed_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_designs_added
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_designs_modified
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_designs_removed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_due_date_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_time_estimate_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_time_spent_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_comment_added
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_comment_edited
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_comment_removed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_health_status_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
- name: g_project_management_issue_cloned
category: issues_edit
redis_slot: project_management
aggregation: daily
- feature_flag: track_issue_activity_actions
# Secrets Management
- name: i_ci_secrets_management_vault_build_created
category: ci_secrets_management
@@ -445,126 +427,15 @@
redis_slot: snippets
aggregation: weekly
feature_flag: usage_data_i_snippets_show
-# Merge request counters
-- name: i_code_review_mr_diffs
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_mr_diffs
-- name: i_code_review_user_single_file_diffs
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_single_file_diffs
-- name: i_code_review_mr_single_file_diffs
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_mr_single_file_diffs
-- name: i_code_review_user_create_mr
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_create_mr
-- name: i_code_review_user_close_mr
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_close_mr
-- name: i_code_review_user_reopen_mr
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_reopen_mr
-- name: i_code_review_user_merge_mr
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_merge_mr
-- name: i_code_review_user_create_mr_comment
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_create_mr_comment
-- name: i_code_review_user_edit_mr_comment
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_edit_mr_comment
-- name: i_code_review_user_remove_mr_comment
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_remove_mr_comment
-- name: i_code_review_user_create_review_note
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_create_review_note
-- name: i_code_review_user_publish_review
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_publish_review
-- name: i_code_review_user_create_multiline_mr_comment
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_create_multiline_mr_comment
-- name: i_code_review_user_edit_multiline_mr_comment
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_edit_multiline_mr_comment
-- name: i_code_review_user_remove_multiline_mr_comment
- redis_slot: code_review
- category: code_review
- aggregation: weekly
- feature_flag: usage_data_i_code_review_user_remove_multiline_mr_comment
# Terraform
- name: p_terraform_state_api_unique_users
category: terraform
redis_slot: terraform
aggregation: weekly
feature_flag: usage_data_p_terraform_state_api_unique_users
-# CI templates
-- name: p_ci_templates_auto_devops
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_aws_cf_deploy_ec2
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_auto_devops_build
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_auto_devops_deploy
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_auto_devops_deploy_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_security_sast
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_security_secret_detection
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
-- name: p_ci_templates_terraform_base_latest
- category: ci_templates
- redis_slot: ci_templates
- aggregation: weekly
- feature_flag: usage_data_track_ci_templates_unique_projects
+# Pipeline Authoring
+- name: o_pipeline_authoring_unique_users_committing_ciconfigfile
+ category: pipeline_authoring
+ redis_slot: pipeline_authoring
+ aggregation: weekly
+ feature_flag: usage_data_unique_users_committing_ciconfigfile
diff --git a/lib/gitlab/usage_data_counters/known_events/ecosystem.yml b/lib/gitlab/usage_data_counters/known_events/ecosystem.yml
new file mode 100644
index 00000000000..3fd02164f74
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/ecosystem.yml
@@ -0,0 +1,22 @@
+---
+# Ecosystem category
+- name: i_ecosystem_jira_service_close_issue
+ category: ecosystem
+ redis_slot: ecosystem
+ aggregation: weekly
+ feature_flag: usage_data_track_ecosystem_jira_service
+- name: i_ecosystem_jira_service_cross_reference
+ category: ecosystem
+ redis_slot: ecosystem
+ aggregation: weekly
+ feature_flag: usage_data_track_ecosystem_jira_service
+- name: i_ecosystem_jira_service_list_issues
+ category: ecosystem
+ redis_slot: ecosystem
+ aggregation: weekly
+ feature_flag: usage_data_track_ecosystem_jira_service
+- name: i_ecosystem_jira_service_create_issue
+ category: ecosystem
+ redis_slot: ecosystem
+ aggregation: weekly
+ feature_flag: usage_data_track_ecosystem_jira_service
diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
new file mode 100644
index 00000000000..bf292047da0
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
@@ -0,0 +1,326 @@
+---
+- name: i_quickactions_approve
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_assign_single
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_assign_multiple
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_assign_self
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_assign_reviewer
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_award
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_board_move
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_child_epic
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_clear_weight
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_clone
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_close
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_confidential
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_copy_metadata_merge_request
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_copy_metadata_issue
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_create_merge_request
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_done
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_draft
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_due
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_duplicate
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_epic
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_estimate
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_iteration
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_label
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_lock
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_merge
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_milestone
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_move
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_parent_epic
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_promote
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_publish
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_reassign
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_reassign_reviewer
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_rebase
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_relabel
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_relate
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_child_epic
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_due_date
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_epic
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_estimate
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_iteration
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_milestone
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_parent_epic
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_time_spent
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_remove_zoom
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_reopen
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_shrug
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_spend_subtract
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_spend_add
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_submit_review
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_subscribe
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_tableflip
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_tag
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_target_branch
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_title
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_todo
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unassign_specific
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unassign_all
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unassign_reviewer
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unlabel_specific
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unlabel_all
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unlock
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_unsubscribe
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_weight
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_wip
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
+- name: i_quickactions_zoom
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+ feature_flag: usage_data_track_quickactions
diff --git a/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
index 11d59257ed9..b9856e1f74a 100644
--- a/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter.rb
@@ -10,6 +10,8 @@ module Gitlab
MR_CLOSE_ACTION = 'i_code_review_user_close_mr'
MR_REOPEN_ACTION = 'i_code_review_user_reopen_mr'
MR_MERGE_ACTION = 'i_code_review_user_merge_mr'
+ MR_APPROVE_ACTION = 'i_code_review_user_approve_mr'
+ MR_UNAPPROVE_ACTION = 'i_code_review_user_unapprove_mr'
MR_CREATE_COMMENT_ACTION = 'i_code_review_user_create_mr_comment'
MR_EDIT_COMMENT_ACTION = 'i_code_review_user_edit_mr_comment'
MR_REMOVE_COMMENT_ACTION = 'i_code_review_user_remove_mr_comment'
@@ -18,6 +20,21 @@ module Gitlab
MR_CREATE_MULTILINE_COMMENT_ACTION = 'i_code_review_user_create_multiline_mr_comment'
MR_EDIT_MULTILINE_COMMENT_ACTION = 'i_code_review_user_edit_multiline_mr_comment'
MR_REMOVE_MULTILINE_COMMENT_ACTION = 'i_code_review_user_remove_multiline_mr_comment'
+ MR_ADD_SUGGESTION_ACTION = 'i_code_review_user_add_suggestion'
+ MR_APPLY_SUGGESTION_ACTION = 'i_code_review_user_apply_suggestion'
+ MR_MARKED_AS_DRAFT_ACTION = 'i_code_review_user_marked_as_draft'
+ MR_UNMARKED_AS_DRAFT_ACTION = 'i_code_review_user_unmarked_as_draft'
+ MR_RESOLVE_THREAD_ACTION = 'i_code_review_user_resolve_thread'
+ MR_UNRESOLVE_THREAD_ACTION = 'i_code_review_user_unresolve_thread'
+ MR_ASSIGNED_USERS_ACTION = 'i_code_review_user_assigned'
+ MR_REVIEW_REQUESTED_USERS_ACTION = 'i_code_review_user_review_requested'
+ MR_TASK_ITEM_STATUS_CHANGED_ACTION = 'i_code_review_user_toggled_task_item_status'
+ MR_APPROVAL_RULE_ADDED_USERS_ACTION = 'i_code_review_user_approval_rule_added'
+ MR_APPROVAL_RULE_EDITED_USERS_ACTION = 'i_code_review_user_approval_rule_edited'
+ MR_APPROVAL_RULE_DELETED_USERS_ACTION = 'i_code_review_user_approval_rule_deleted'
+ MR_EDIT_MR_TITLE_ACTION = 'i_code_review_edit_mr_title'
+ MR_EDIT_MR_DESC_ACTION = 'i_code_review_edit_mr_desc'
+ MR_CREATE_FROM_ISSUE_ACTION = 'i_code_review_user_create_mr_from_issue'
class << self
def track_mr_diffs_action(merge_request:)
@@ -45,6 +62,22 @@ module Gitlab
track_unique_action_by_user(MR_REOPEN_ACTION, user)
end
+ def track_approve_mr_action(user:)
+ track_unique_action_by_user(MR_APPROVE_ACTION, user)
+ end
+
+ def track_unapprove_mr_action(user:)
+ track_unique_action_by_user(MR_UNAPPROVE_ACTION, user)
+ end
+
+ def track_resolve_thread_action(user:)
+ track_unique_action_by_user(MR_RESOLVE_THREAD_ACTION, user)
+ end
+
+ def track_unresolve_thread_action(user:)
+ track_unique_action_by_user(MR_UNRESOLVE_THREAD_ACTION, user)
+ end
+
def track_create_comment_action(note:)
track_unique_action_by_user(MR_CREATE_COMMENT_ACTION, note.author)
track_multiline_unique_action(MR_CREATE_MULTILINE_COMMENT_ACTION, note)
@@ -68,6 +101,58 @@ module Gitlab
track_unique_action_by_user(MR_PUBLISH_REVIEW_ACTION, user)
end
+ def track_add_suggestion_action(user:)
+ track_unique_action_by_user(MR_ADD_SUGGESTION_ACTION, user)
+ end
+
+ def track_marked_as_draft_action(user:)
+ track_unique_action_by_user(MR_MARKED_AS_DRAFT_ACTION, user)
+ end
+
+ def track_unmarked_as_draft_action(user:)
+ track_unique_action_by_user(MR_UNMARKED_AS_DRAFT_ACTION, user)
+ end
+
+ def track_apply_suggestion_action(user:)
+ track_unique_action_by_user(MR_APPLY_SUGGESTION_ACTION, user)
+ end
+
+ def track_users_assigned_to_mr(users:)
+ track_unique_action_by_users(MR_ASSIGNED_USERS_ACTION, users)
+ end
+
+ def track_users_review_requested(users:)
+ track_unique_action_by_users(MR_REVIEW_REQUESTED_USERS_ACTION, users)
+ end
+
+ def track_title_edit_action(user:)
+ track_unique_action_by_user(MR_EDIT_MR_TITLE_ACTION, user)
+ end
+
+ def track_description_edit_action(user:)
+ track_unique_action_by_user(MR_EDIT_MR_DESC_ACTION, user)
+ end
+
+ def track_approval_rule_added_action(user:)
+ track_unique_action_by_user(MR_APPROVAL_RULE_ADDED_USERS_ACTION, user)
+ end
+
+ def track_approval_rule_edited_action(user:)
+ track_unique_action_by_user(MR_APPROVAL_RULE_EDITED_USERS_ACTION, user)
+ end
+
+ def track_approval_rule_deleted_action(user:)
+ track_unique_action_by_user(MR_APPROVAL_RULE_DELETED_USERS_ACTION, user)
+ end
+
+ def track_task_item_status_changed(user:)
+ track_unique_action_by_user(MR_TASK_ITEM_STATUS_CHANGED_ACTION, user)
+ end
+
+ def track_mr_create_from_issue(user:)
+ track_unique_action_by_user(MR_CREATE_FROM_ISSUE_ACTION, user)
+ end
+
private
def track_unique_action_by_merge_request(action, merge_request)
@@ -80,6 +165,12 @@ module Gitlab
track_unique_action(action, user.id)
end
+ def track_unique_action_by_users(action, users)
+ return if users.blank?
+
+ track_unique_action(action, users.map(&:id))
+ end
+
def track_unique_action(action, value)
Gitlab::UsageDataCounters::HLLRedisCounter.track_usage_event(action, value)
end
diff --git a/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb
new file mode 100644
index 00000000000..f757b51f73c
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module QuickActionActivityUniqueCounter
+ class << self
+ # Tracks the quick action with name `name`.
+ # `args` is expected to be a single string, will be split internally when necessary.
+ def track_unique_action(name, args:, user:)
+ return unless Feature.enabled?(:usage_data_track_quickactions, default_enabled: :yaml)
+ return unless user
+
+ args ||= ''
+ name = prepare_name(name, args)
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:"i_quickactions_#{name}", values: user.id)
+ end
+
+ private
+
+ def prepare_name(name, args)
+ case name
+ when 'assign'
+ event_name_for_assign(args)
+ when 'copy_metadata'
+ event_name_for_copy_metadata(args)
+ when 'remove_reviewer'
+ 'unassign_reviewer'
+ when 'request_review', 'reviewer'
+ 'assign_reviewer'
+ when 'spend'
+ event_name_for_spend(args)
+ when 'unassign'
+ event_name_for_unassign(args)
+ when 'unlabel', 'remove_label'
+ event_name_for_unlabel(args)
+ else
+ name
+ end
+ end
+
+ def event_name_for_assign(args)
+ args = args.split
+
+ if args.count == 1 && args.first == 'me'
+ 'assign_self'
+ elsif args.count == 1
+ 'assign_single'
+ else
+ 'assign_multiple'
+ end
+ end
+
+ def event_name_for_copy_metadata(args)
+ if args.start_with?('#')
+ 'copy_metadata_issue'
+ else
+ 'copy_metadata_merge_request'
+ end
+ end
+
+ def event_name_for_spend(args)
+ if args.start_with?('-')
+ 'spend_subtract'
+ else
+ 'spend_add'
+ end
+ end
+
+ def event_name_for_unassign(args)
+ if args.present?
+ 'unassign_specific'
+ else
+ 'unassign_all'
+ end
+ end
+
+ def event_name_for_unlabel(args)
+ if args.present?
+ 'unlabel_specific'
+ else
+ 'unlabel_all'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb
new file mode 100644
index 00000000000..703c4885b04
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module VSCodeExtensionActivityUniqueCounter
+ VS_CODE_API_REQUEST_ACTION = 'i_code_review_user_vs_code_api_request'
+ VS_CODE_USER_AGENT_REGEX = /\Avs-code-gitlab-workflow/.freeze
+
+ class << self
+ def track_api_request_when_trackable(user_agent:, user:)
+ user_agent&.match?(VS_CODE_USER_AGENT_REGEX) && track_unique_action_by_user(VS_CODE_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/utils/markdown.rb b/lib/gitlab/utils/markdown.rb
index e783ac785cc..5087020affe 100644
--- a/lib/gitlab/utils/markdown.rb
+++ b/lib/gitlab/utils/markdown.rb
@@ -4,7 +4,7 @@ module Gitlab
module Utils
module Markdown
PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze
- PRODUCT_SUFFIX = /\s*\**\((core|starter|premium|ultimate)(\s+only)?\)\**/.freeze
+ PRODUCT_SUFFIX = /\s*\**\((core|starter|premium|ultimate|free|bronze|silver|gold)(\s+(only|self|sass))?\)\**/.freeze
def string_to_anchor(string)
string
diff --git a/lib/gitlab/utils/measuring.rb b/lib/gitlab/utils/measuring.rb
index febe489f1f8..ffd12c1b518 100644
--- a/lib/gitlab/utils/measuring.rb
+++ b/lib/gitlab/utils/measuring.rb
@@ -53,14 +53,10 @@ module Gitlab
end
def with_gc_stats
- GC.start # perform a full mark-and-sweep
- stats_before = GC.stat
+ stats = ::Gitlab::Memory::Instrumentation.start_thread_memory_allocations
yield
- stats_after = GC.stat
- @gc_stats = stats_after.map do |key, after_value|
- before_value = stats_before[key]
- [key, before: before_value, after: after_value, diff: after_value - before_value]
- end.to_h
+ ensure
+ @gc_stats = ::Gitlab::Memory::Instrumentation.measure_thread_memory_allocations(stats)
end
def with_measure_time
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
index 784a6686962..c92865636d0 100644
--- a/lib/gitlab/utils/override.rb
+++ b/lib/gitlab/utils/override.rb
@@ -153,7 +153,13 @@ module Gitlab
def extended(mod = nil)
super
- queue_verification(mod.singleton_class) if mod
+ # Hack to resolve https://gitlab.com/gitlab-org/gitlab/-/issues/23932
+ is_not_concern_hack =
+ (mod.is_a?(Class) || !name&.end_with?('::ClassMethods'))
+
+ if mod && is_not_concern_hack
+ queue_verification(mod.singleton_class)
+ end
end
def queue_verification(base, verify: false)
@@ -174,7 +180,7 @@ module Gitlab
end
def self.verify!
- extensions.values.each(&:verify!)
+ extensions.each_value(&:verify!)
end
end
end
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index baccadd9594..28dc66e19f8 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -39,6 +39,9 @@ module Gitlab
FALLBACK = -1
DISTRIBUTED_HLL_FALLBACK = -2
+ ALL_TIME_PERIOD_HUMAN_NAME = "all_time"
+ WEEKLY_PERIOD_HUMAN_NAME = "weekly"
+ MONTHLY_PERIOD_HUMAN_NAME = "monthly"
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
if batch
@@ -61,10 +64,13 @@ module Gitlab
end
def estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)
- Gitlab::Database::PostgresHll::BatchDistinctCounter
+ buckets = Gitlab::Database::PostgresHll::BatchDistinctCounter
.new(relation, column)
.execute(batch_size: batch_size, start: start, finish: finish)
- .estimated_distinct_count
+
+ yield buckets if block_given?
+
+ buckets.estimated_distinct_count
rescue ActiveRecord::StatementInvalid
FALLBACK
# catch all rescue should be removed as a part of feature flag rollout issue
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 8e7af8876a4..e9905bae985 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -32,7 +32,7 @@ module Gitlab
GitalyServer: {
address: Gitlab::GitalyClient.address(repository.storage),
token: Gitlab::GitalyClient.token(repository.storage),
- features: Feature::Gitaly.server_feature_flags
+ features: Feature::Gitaly.server_feature_flags(repository.project)
}
}
@@ -231,7 +231,7 @@ module Gitlab
{
address: Gitlab::GitalyClient.address(repository.shard),
token: Gitlab::GitalyClient.token(repository.shard),
- features: Feature::Gitaly.server_feature_flags
+ features: Feature::Gitaly.server_feature_flags(repository.project)
}
end
diff --git a/lib/gitlab_danger.rb b/lib/gitlab_danger.rb
deleted file mode 100644
index b0974e02edd..00000000000
--- a/lib/gitlab_danger.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-class GitlabDanger
- LOCAL_RULES ||= %w[
- changes_size
- documentation
- frozen_string
- duplicate_yarn_dependencies
- prettier
- eslint
- karma
- database
- commit_messages
- product_intelligence
- utility_css
- pajamas
- pipeline
- ].freeze
-
- CI_ONLY_RULES ||= %w[
- metadata
- changelog
- specs
- roulette
- ce_ee_vue_templates
- sidekiq_queues
- specialization_labels
- ci_templates
- ].freeze
-
- MESSAGE_PREFIX = '==>'.freeze
-
- attr_reader :gitlab_danger_helper
-
- def initialize(gitlab_danger_helper)
- @gitlab_danger_helper = gitlab_danger_helper
- end
-
- def self.local_warning_message
- "#{MESSAGE_PREFIX} Only the following Danger rules can be run locally: #{LOCAL_RULES.join(', ')}"
- end
-
- def self.success_message
- "#{MESSAGE_PREFIX} No Danger rule violations!"
- end
-
- def rule_names
- ci? ? LOCAL_RULES | CI_ONLY_RULES : LOCAL_RULES
- end
-
- def html_link(str)
- self.ci? ? gitlab_danger_helper.html_link(str) : str
- end
-
- def ci?
- !gitlab_danger_helper.nil?
- end
-end
diff --git a/lib/object_storage/config.rb b/lib/object_storage/config.rb
index f933d4e4866..0e6408b4917 100644
--- a/lib/object_storage/config.rb
+++ b/lib/object_storage/config.rb
@@ -2,6 +2,8 @@
module ObjectStorage
class Config
+ include Gitlab::Utils::StrongMemoize
+
AWS_PROVIDER = 'AWS'
AZURE_PROVIDER = 'AzureRM'
GOOGLE_PROVIDER = 'Google'
@@ -66,6 +68,36 @@ module ObjectStorage
def provider
credentials[:provider].to_s
end
+
+ # This method converts fog-aws parameters to an endpoint for the
+ # Workhorse S3 client.
+ def s3_endpoint
+ strong_memoize(:s3_endpoint) do
+ # We could omit this line and let the following code handle this, but
+ # this will ensure that working configurations that use `endpoint`
+ # will continue to work.
+ next credentials[:endpoint] if credentials[:endpoint].present?
+
+ generate_s3_endpoint_from_credentials
+ end
+ end
+
+ def generate_s3_endpoint_from_credentials
+ # fog-aws has special handling of the host, region, scheme, etc:
+ # https://github.com/fog/fog-aws/blob/c7a11ba377a76d147861d0e921eb1e245bc11b6c/lib/fog/aws/storage.rb#L440-L449
+ # Rather than reimplement this, we derive it from a sample GET URL.
+ url = fog_connection.get_object_url(bucket, "tmp", nil)
+ uri = ::Addressable::URI.parse(url)
+
+ return unless uri&.scheme && uri&.host
+
+ endpoint = "#{uri.scheme}://#{uri.host}"
+ endpoint += ":#{uri.port}" if uri.port
+ endpoint
+ rescue ::URI::InvalidComponentError, ::Addressable::URI::InvalidURIError => e
+ Gitlab::ErrorTracking.track_exception(e)
+ nil
+ end
# End AWS-specific options
# Begin Azure-specific options
@@ -91,6 +123,10 @@ module ObjectStorage
end
end
+ def fog_connection
+ @connection ||= ::Fog::Storage.new(credentials)
+ end
+
private
# This returns a Hash of HTTP encryption headers to send along to S3.
diff --git a/lib/object_storage/direct_upload.rb b/lib/object_storage/direct_upload.rb
index 7f1c30e574d..9fb4b571e06 100644
--- a/lib/object_storage/direct_upload.rb
+++ b/lib/object_storage/direct_upload.rb
@@ -80,7 +80,7 @@ module ObjectStorage
S3Config: {
Bucket: bucket_name,
Region: credentials[:region],
- Endpoint: credentials[:endpoint],
+ Endpoint: config.s3_endpoint,
PathStyle: config.use_path_style?,
UseIamProfile: config.use_iam_profile?,
ServerSideEncryption: config.server_side_encryption,
@@ -229,7 +229,7 @@ module ObjectStorage
end
def connection
- @connection ||= ::Fog::Storage.new(credentials)
+ config.fog_connection
end
end
end
diff --git a/lib/peek/views/external_http.rb b/lib/peek/views/external_http.rb
new file mode 100644
index 00000000000..b925e3db7b6
--- /dev/null
+++ b/lib/peek/views/external_http.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module Peek
+ module Views
+ class ExternalHttp < DetailedView
+ DEFAULT_THRESHOLDS = {
+ calls: 10,
+ duration: 1000,
+ individual_call: 100
+ }.freeze
+
+ THRESHOLDS = {
+ production: {
+ calls: 10,
+ duration: 1000,
+ individual_call: 100
+ }
+ }.freeze
+
+ def key
+ 'external-http'
+ end
+
+ def results
+ super.merge(calls: calls)
+ end
+
+ def self.thresholds
+ @thresholds ||= THRESHOLDS.fetch(Rails.env.to_sym, DEFAULT_THRESHOLDS)
+ end
+
+ def format_call_details(call)
+ full_path = generate_path(call)
+ super.merge(
+ label: "#{call[:method]} #{full_path}",
+ code: code(call),
+ proxy: proxy(call),
+ error: error(call)
+ )
+ end
+
+ private
+
+ def duration
+ ::Gitlab::Metrics::Subscribers::ExternalHttp.duration * 1000
+ end
+
+ def calls
+ ::Gitlab::Metrics::Subscribers::ExternalHttp.request_count
+ end
+
+ def call_details
+ ::Gitlab::Metrics::Subscribers::ExternalHttp.detail_store
+ end
+
+ def proxy(call)
+ if call[:proxy_host].present?
+ "Proxied via #{call[:proxy_host]}:#{call[:proxy_port]}"
+ else
+ nil
+ end
+ end
+
+ def code(call)
+ if call[:code].present?
+ "Response status: #{call[:code]}"
+ else
+ nil
+ end
+ end
+
+ def error(call)
+ if call[:exception_object].present?
+ "Exception: #{call[:exception_object]}"
+ else
+ nil
+ end
+ end
+
+ def generate_path(call)
+ uri = URI("")
+ uri.scheme = call[:scheme]
+ # The host can be a domain, IPv4 or IPv6.
+ # Ruby handle IPv6 for us at
+ # https://github.com/ruby/ruby/blob/v2_6_0/lib/uri/generic.rb#L662
+ uri.hostname = call[:host]
+ uri.port = call[:port]
+ uri.path = call[:path]
+ uri.query = generate_query(call[:query])
+
+ uri.to_s
+ rescue StandardError
+ 'unknown'
+ end
+
+ def generate_query(query_string)
+ query_string.is_a?(Hash) ? query_string.to_query : query_string.to_s
+ end
+ end
+ end
+end
diff --git a/lib/release_highlights/validator/entry.rb b/lib/release_highlights/validator/entry.rb
index 0dbe0cdf882..3c83ca21123 100644
--- a/lib/release_highlights/validator/entry.rb
+++ b/lib/release_highlights/validator/entry.rb
@@ -5,7 +5,7 @@ module ReleaseHighlights
include ActiveModel::Validations
include ActiveModel::Validations::Callbacks
- PACKAGES = %w(Core Starter Premium Ultimate).freeze
+ PACKAGES = %w(Free Premium Ultimate).freeze
attr_reader :entry
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index e7e0d4e471f..8f18d6433e0 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -8,9 +8,9 @@ module Rouge
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
#
# [+tag+] The tag (language) of the lexer used to generate the formatted tokens
- def initialize(tag: nil)
+ def initialize(options = {})
@line_number = 1
- @tag = tag
+ @tag = options[:tag]
end
def stream(tokens)
diff --git a/lib/security/ci_configuration/sast_build_actions.rb b/lib/security/ci_configuration/sast_build_actions.rb
new file mode 100644
index 00000000000..b2d684bc1e1
--- /dev/null
+++ b/lib/security/ci_configuration/sast_build_actions.rb
@@ -0,0 +1,170 @@
+# frozen_string_literal: true
+
+module Security
+ module CiConfiguration
+ class SastBuildActions
+ SAST_DEFAULT_ANALYZERS = 'bandit, brakeman, eslint, flawfinder, gosec, kubesec, nodejs-scan, phpcs-security-audit, pmd-apex, security-code-scan, sobelow, spotbugs'
+
+ def initialize(auto_devops_enabled, params, existing_gitlab_ci_content)
+ @auto_devops_enabled = auto_devops_enabled
+ @variables = variables(params)
+ @existing_gitlab_ci_content = existing_gitlab_ci_content || {}
+ @default_sast_values = default_sast_values(params)
+ @default_values_overwritten = false
+ end
+
+ def generate
+ action = @existing_gitlab_ci_content.present? ? 'update' : 'create'
+
+ update_existing_content!
+
+ [{ action: action, file_path: '.gitlab-ci.yml', content: prepare_existing_content, default_values_overwritten: @default_values_overwritten }]
+ end
+
+ private
+
+ def variables(params)
+ # This early return is necessary for supporting REST API.
+ # Will be removed during the implementation of
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/246737
+ return params unless params['global'].present?
+
+ collect_values(params, 'value')
+ end
+
+ def default_sast_values(params)
+ collect_values(params, 'defaultValue')
+ end
+
+ def collect_values(config, key)
+ global_variables = config['global']&.to_h { |k| [k['field'], k[key]] } || {}
+ pipeline_variables = config['pipeline']&.to_h { |k| [k['field'], k[key]] } || {}
+
+ analyzer_variables = collect_analyzer_values(config, key)
+
+ global_variables.merge!(pipeline_variables).merge!(analyzer_variables)
+ end
+
+ def collect_analyzer_values(config, key)
+ analyzer_variables = analyzer_variables_for(config, key)
+ analyzer_variables['SAST_EXCLUDED_ANALYZERS'] = if key == 'value'
+ config['analyzers']
+ &.reject {|a| a['enabled'] }
+ &.collect {|a| a['name'] }
+ &.sort
+ &.join(', ')
+ else
+ ''
+ end
+
+ analyzer_variables
+ end
+
+ def analyzer_variables_for(config, key)
+ config['analyzers']
+ &.select {|a| a['enabled'] && a['variables'] }
+ &.flat_map {|a| a['variables'] }
+ &.collect {|v| [v['field'], v[key]] }.to_h
+ end
+
+ def update_existing_content!
+ @existing_gitlab_ci_content['stages'] = set_stages
+ @existing_gitlab_ci_content['variables'] = set_variables(global_variables, @existing_gitlab_ci_content)
+ @existing_gitlab_ci_content['sast'] = set_sast_block
+ @existing_gitlab_ci_content['include'] = set_includes
+
+ @existing_gitlab_ci_content.select! { |k, v| v.present? }
+ @existing_gitlab_ci_content['sast'].select! { |k, v| v.present? }
+ end
+
+ def set_includes
+ includes = @existing_gitlab_ci_content['include'] || []
+ includes = includes.is_a?(Array) ? includes : [includes]
+ includes << { 'template' => template }
+ includes.uniq
+ end
+
+ def set_stages
+ existing_stages = @existing_gitlab_ci_content['stages'] || []
+ base_stages = @auto_devops_enabled ? auto_devops_stages : ['test']
+ (existing_stages + base_stages + [sast_stage]).uniq
+ end
+
+ def auto_devops_stages
+ auto_devops_template = YAML.safe_load( Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps').content )
+ auto_devops_template['stages']
+ end
+
+ def sast_stage
+ @variables['stage'].presence ? @variables['stage'] : 'test'
+ end
+
+ def set_variables(variables, hash_to_update = {})
+ hash_to_update['variables'] ||= {}
+
+ variables.each do |key|
+ if @variables[key].present? && @variables[key].to_s != @default_sast_values[key].to_s
+ hash_to_update['variables'][key] = @variables[key]
+ @default_values_overwritten = true
+ else
+ hash_to_update['variables'].delete(key)
+ end
+ end
+
+ hash_to_update['variables']
+ end
+
+ def set_sast_block
+ sast_content = @existing_gitlab_ci_content['sast'] || {}
+ sast_content['variables'] = set_variables(sast_variables)
+ sast_content['stage'] = sast_stage
+ sast_content.select { |k, v| v.present? }
+ end
+
+ def prepare_existing_content
+ content = @existing_gitlab_ci_content.to_yaml
+ content = remove_document_delimeter(content)
+
+ content.prepend(sast_comment)
+ end
+
+ def remove_document_delimeter(content)
+ content.gsub(/^---\n/, '')
+ end
+
+ def sast_comment
+ <<~YAML
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ YAML
+ end
+
+ def template
+ return 'Auto-DevOps.gitlab-ci.yml' if @auto_devops_enabled
+
+ 'Security/SAST.gitlab-ci.yml'
+ end
+
+ def global_variables
+ %w(
+ SECURE_ANALYZERS_PREFIX
+ )
+ end
+
+ def sast_variables
+ %w(
+ SAST_ANALYZER_IMAGE_TAG
+ SAST_EXCLUDED_PATHS
+ SEARCH_MAX_DEPTH
+ SAST_EXCLUDED_ANALYZERS
+ SAST_BRAKEMAN_LEVEL
+ SAST_BANDIT_EXCLUDED_PATHS
+ SAST_FLAWFINDER_LEVEL
+ SAST_GOSEC_LEVEL
+ )
+ end
+ end
+ end
+end
diff --git a/lib/tasks/benchmark.rake b/lib/tasks/benchmark.rake
new file mode 100644
index 00000000000..6deafb2c351
--- /dev/null
+++ b/lib/tasks/benchmark.rake
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+return if Rails.env.production?
+
+namespace :benchmark do
+ desc 'Benchmark | Banzai pipeline/filters'
+ RSpec::Core::RakeTask.new(:banzai) do |t|
+ t.pattern = 'spec/benchmarks/banzai_benchmark.rb'
+ ENV['BENCHMARK'] = '1'
+ end
+end
diff --git a/lib/tasks/brakeman.rake b/lib/tasks/brakeman.rake
index 2301ec9b228..44d2071751f 100644
--- a/lib/tasks/brakeman.rake
+++ b/lib/tasks/brakeman.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc 'Security check via brakeman'
task :brakeman do
# We get 0 warnings at level 'w3' but we would like to reach 'w2'. Merge
diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake
index 6af91d473a6..4d698e56444 100644
--- a/lib/tasks/cache.rake
+++ b/lib/tasks/cache.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :cache do
namespace :clear do
REDIS_CLEAR_BATCH_SIZE = 1000 # There seems to be no speedup when pushing beyond 1,000
diff --git a/lib/tasks/ci/cleanup.rake b/lib/tasks/ci/cleanup.rake
index 978a42be638..31c3928e797 100644
--- a/lib/tasks/ci/cleanup.rake
+++ b/lib/tasks/ci/cleanup.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :ci do
namespace :cleanup do
desc "GitLab | CI | Clean running builds"
diff --git a/lib/tasks/cleanup.rake b/lib/tasks/cleanup.rake
index 8574f26dbdc..c13da77217e 100644
--- a/lib/tasks/cleanup.rake
+++ b/lib/tasks/cleanup.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :cleanup do
desc "GitLab | Cleanup | Delete moved repositories"
diff --git a/lib/tasks/config_lint.rake b/lib/tasks/config_lint.rake
index ddbcf1e1eb8..9bbefaa2d3a 100644
--- a/lib/tasks/config_lint.rake
+++ b/lib/tasks/config_lint.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ConfigLint
def self.run(files)
failures = files.reject do |file|
diff --git a/lib/tasks/db_obsolete_ignored_columns.rake b/lib/tasks/db_obsolete_ignored_columns.rake
index 00f60231f4f..cf35a355ce9 100644
--- a/lib/tasks/db_obsolete_ignored_columns.rake
+++ b/lib/tasks/db_obsolete_ignored_columns.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc 'Show a list of obsolete `ignored_columns`'
task 'db:obsolete_ignored_columns' => :environment do
list = Gitlab::Database::ObsoleteIgnoredColumns.new.execute
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index b3ba2434855..cb01f229cd3 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
task dev: ["dev:setup"]
namespace :dev do
diff --git a/lib/tasks/downtime_check.rake b/lib/tasks/downtime_check.rake
index ce97ed50fc7..3428e3f8f53 100644
--- a/lib/tasks/downtime_check.rake
+++ b/lib/tasks/downtime_check.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc 'Checks if migrations in a branch require downtime'
task downtime_check: :environment do
repo = if defined?(Gitlab::License)
diff --git a/lib/tasks/eslint.rake b/lib/tasks/eslint.rake
index 51f5d768102..ad63de66c81 100644
--- a/lib/tasks/eslint.rake
+++ b/lib/tasks/eslint.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
desc "GitLab | Run ESLint"
task eslint: ['yarn:check'] do
diff --git a/lib/tasks/file_hooks.rake b/lib/tasks/file_hooks.rake
index f767d63fe0d..a892d36b48e 100644
--- a/lib/tasks/file_hooks.rake
+++ b/lib/tasks/file_hooks.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :file_hooks do
desc 'Validate existing file hooks'
task validate: :environment do
diff --git a/lib/tasks/frontend.rake b/lib/tasks/frontend.rake
index 6e90229830d..b2d2c4e3f2b 100644
--- a/lib/tasks/frontend.rake
+++ b/lib/tasks/frontend.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
namespace :frontend do
desc 'GitLab | Frontend | Generate fixtures for JavaScript tests'
@@ -5,7 +7,7 @@ unless Rails.env.production?
directories = %w[spec]
directories << 'ee/spec' if Gitlab.ee?
directory_glob = "{#{directories.join(',')}}"
- args.with_defaults(pattern: "#{directory_glob}/frontend/fixtures/*.rb")
+ args.with_defaults(pattern: "#{directory_glob}/frontend/fixtures/**/*.rb")
ENV['NO_KNAPSACK'] = 'true'
t.pattern = args[:pattern]
t.rspec_opts = '--format documentation'
diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake
index 85393bba9a6..a4600a0ed16 100644
--- a/lib/tasks/gemojione.rake
+++ b/lib/tasks/gemojione.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gemojione do
desc 'Generates Emoji SHA256 digests'
diff --git a/lib/tasks/gitlab/artifacts/check.rake b/lib/tasks/gitlab/artifacts/check.rake
index a105261ed51..057bb17dbda 100644
--- a/lib/tasks/gitlab/artifacts/check.rake
+++ b/lib/tasks/gitlab/artifacts/check.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :artifacts do
desc 'GitLab | Artifacts | Check integrity of uploaded job artifacts'
diff --git a/lib/tasks/gitlab/artifacts/migrate.rake b/lib/tasks/gitlab/artifacts/migrate.rake
index 871fdfb4fde..94867e1a16a 100644
--- a/lib/tasks/gitlab/artifacts/migrate.rake
+++ b/lib/tasks/gitlab/artifacts/migrate.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
require 'resolv-replace'
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index de2dfca8c1b..c53ef8382b8 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'active_record/fixtures'
namespace :gitlab do
diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index 56cbbae1f67..df0c6a260a2 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :import do
desc "GitLab | Import | Add all users to all projects (admin users are added as maintainers)"
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 9e60a585330..d4e38100609 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
desc 'GitLab | Check the configuration of GitLab and its environment'
task check: :gitlab_environment do
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index a56a0435673..6c3a7a77e0e 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -56,7 +56,7 @@ namespace :gitlab do
task orphan_job_artifact_files: :gitlab_environment do
warn_user_is_not_gitlab
- cleaner = Gitlab::Cleanup::OrphanJobArtifactFiles.new(limit: limit, dry_run: dry_run?, niceness: niceness, logger: logger)
+ cleaner = Gitlab::Cleanup::OrphanJobArtifactFiles.new(dry_run: dry_run?, niceness: niceness, logger: logger)
cleaner.run!
if dry_run?
@@ -78,8 +78,7 @@ namespace :gitlab do
cleaner = Gitlab::Cleanup::OrphanLfsFileReferences.new(
project,
dry_run: dry_run?,
- logger: logger,
- limit: limit
+ logger: logger
)
cleaner.run!
@@ -162,10 +161,6 @@ namespace :gitlab do
ENV['DEBUG'].present?
end
- def limit
- ENV['LIMIT']&.to_i
- end
-
def niceness
ENV['NICENESS'].presence
end
diff --git a/lib/tasks/gitlab/container_registry.rake b/lib/tasks/gitlab/container_registry.rake
index cd18c873a5a..086f99971bc 100644
--- a/lib/tasks/gitlab/container_registry.rake
+++ b/lib/tasks/gitlab/container_registry.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :container_registry do
desc "GitLab | Container Registry | Configure"
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 901e349ea31..541a4fc62af 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :db do
desc 'GitLab | DB | Manually insert schema migration version'
@@ -229,5 +231,37 @@ namespace :gitlab do
puts "Found user created projects. Database active"
exit 0
end
+
+ desc 'Run migrations with instrumentation'
+ task :migration_testing, [:result_file] => :environment do |_, args|
+ result_file = args[:result_file] || raise("Please specify result_file argument")
+ raise "File exists already, won't overwrite: #{result_file}" if File.exist?(result_file)
+
+ verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, true
+
+ ctx = ActiveRecord::Base.connection.migration_context
+ existing_versions = ctx.get_all_versions.to_set
+
+ pending_migrations = ctx.migrations.reject do |migration|
+ existing_versions.include?(migration.version)
+ end
+
+ instrumentation = Gitlab::Database::Migrations::Instrumentation.new
+
+ pending_migrations.each do |migration|
+ instrumentation.observe(migration.version) do
+ ActiveRecord::Migrator.new(:up, ctx.migrations, ctx.schema_migration, migration.version).run
+ end
+ end
+ ensure
+ if instrumentation
+ File.open(result_file, 'wb+') do |io|
+ io << instrumentation.observations.to_json
+ end
+ end
+
+ ActiveRecord::Base.clear_cache!
+ ActiveRecord::Migration.verbose = verbose_was
+ end
end
end
diff --git a/lib/tasks/gitlab/doctor/secrets.rake b/lib/tasks/gitlab/doctor/secrets.rake
index 3fdef9dfc80..6e3f474312c 100644
--- a/lib/tasks/gitlab/doctor/secrets.rake
+++ b/lib/tasks/gitlab/doctor/secrets.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :doctor do
desc "GitLab | Check if the database encrypted values can be decrypted using current secrets"
diff --git a/lib/tasks/gitlab/exclusive_lease.rake b/lib/tasks/gitlab/exclusive_lease.rake
index 63b06d5251a..bee9782f373 100644
--- a/lib/tasks/gitlab/exclusive_lease.rake
+++ b/lib/tasks/gitlab/exclusive_lease.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :exclusive_lease do
desc 'GitLab | Exclusive Lease | Clear existing exclusive leases for specified scope (default: *)'
diff --git a/lib/tasks/gitlab/external_diffs.rake b/lib/tasks/gitlab/external_diffs.rake
index 08f25914007..7a5fa07aed1 100644
--- a/lib/tasks/gitlab/external_diffs.rake
+++ b/lib/tasks/gitlab/external_diffs.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :external_diffs do
desc "Override external diffs in file storage to be in object storage instead. This does not change the actual location of the data"
diff --git a/lib/tasks/gitlab/features.rake b/lib/tasks/gitlab/features.rake
index 2309aa5d214..e44328e0de1 100644
--- a/lib/tasks/gitlab/features.rake
+++ b/lib/tasks/gitlab/features.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :features do
desc 'GitLab | Features | Enable direct Git access via Rugged for NFS'
diff --git a/lib/tasks/gitlab/generate_sample_prometheus_data.rake b/lib/tasks/gitlab/generate_sample_prometheus_data.rake
index 250eaaa5568..4cd75af9d00 100644
--- a/lib/tasks/gitlab/generate_sample_prometheus_data.rake
+++ b/lib/tasks/gitlab/generate_sample_prometheus_data.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
desc "GitLab | Generate Sample Prometheus Data"
task :generate_sample_prometheus_data, [:environment_id] => :gitlab_environment do |_, args|
diff --git a/lib/tasks/gitlab/git.rake b/lib/tasks/gitlab/git.rake
index abb15f29328..9c5549b4a54 100644
--- a/lib/tasks/gitlab/git.rake
+++ b/lib/tasks/gitlab/git.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :git do
desc 'GitLab | Git | Check all repos integrity'
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index 49d2d3d62a2..9e474b00ba7 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :gitaly do
desc 'GitLab | Gitaly | Install or upgrade gitaly'
diff --git a/lib/tasks/gitlab/graphql.rake b/lib/tasks/gitlab/graphql.rake
index f708114c226..e4eb4604138 100644
--- a/lib/tasks/gitlab/graphql.rake
+++ b/lib/tasks/gitlab/graphql.rake
@@ -33,7 +33,43 @@ namespace :gitlab do
)
namespace :graphql do
- desc 'Gitlab | GraphQL | Validate queries'
+ desc 'GitLab | GraphQL | Analyze queries'
+ task analyze: [:environment, :enable_feature_flags] do |t, args|
+ queries = if args.to_a.present?
+ args.to_a.flat_map { |path| Gitlab::Graphql::Queries.find(path) }
+ else
+ Gitlab::Graphql::Queries.all
+ end
+
+ queries.each do |defn|
+ $stdout.puts defn.file
+ summary, errs = defn.validate(GitlabSchema)
+
+ if summary == :client_query
+ $stdout.puts " - client query"
+ elsif errs.present?
+ $stdout.puts " - invalid query".color(:red)
+ else
+ complexity = defn.complexity(GitlabSchema)
+ color = case complexity
+ when 0..GitlabSchema::DEFAULT_MAX_COMPLEXITY
+ :green
+ when GitlabSchema::DEFAULT_MAX_COMPLEXITY..GitlabSchema::AUTHENTICATED_COMPLEXITY
+ :yellow
+ when GitlabSchema::AUTHENTICATED_COMPLEXITY..GitlabSchema::ADMIN_COMPLEXITY
+ :orange
+ else
+ :red
+ end
+
+ $stdout.puts " - complexity: #{complexity}".color(color)
+ end
+
+ $stdout.puts ""
+ end
+ end
+
+ desc 'GitLab | GraphQL | Validate queries'
task validate: [:environment, :enable_feature_flags] do |t, args|
queries = if args.to_a.present?
args.to_a.flat_map { |path| Gitlab::Graphql::Queries.find(path) }
@@ -48,10 +84,10 @@ namespace :gitlab do
when :client_query
warn("SKIP #{defn.file}: client query")
else
- warn("OK #{defn.file}") if errs.empty?
+ warn("#{'OK'.color(:green)} #{defn.file}") if errs.empty?
errs.each do |err|
warn(<<~MSG)
- ERROR #{defn.file}: #{err.message} (at #{err.path.join('.')})
+ #{'ERROR'.color(:red)} #{defn.file}: #{err.message} (at #{err.path.join('.')})
MSG
end
end
diff --git a/lib/tasks/gitlab/helpers.rake b/lib/tasks/gitlab/helpers.rake
index 14d1125a03d..b61b1833c5a 100644
--- a/lib/tasks/gitlab/helpers.rake
+++ b/lib/tasks/gitlab/helpers.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Prevent StateMachine warnings from outputting during a cron task
StateMachines::Machine.ignore_method_conflicts = true if ENV['CRON']
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 701d40b7929..bf0ba40fb31 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :import do
# How to use:
diff --git a/lib/tasks/gitlab/import_export.rake b/lib/tasks/gitlab/import_export.rake
index adf696350d7..72598cdf863 100644
--- a/lib/tasks/gitlab/import_export.rake
+++ b/lib/tasks/gitlab/import_export.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :import_export do
desc 'GitLab | Import/Export | Show Import/Export version'
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index d85c8fc7949..2826002bdc2 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :env do
desc 'GitLab | Env | Show information about GitLab and its environment'
diff --git a/lib/tasks/gitlab/ldap.rake b/lib/tasks/gitlab/ldap.rake
index fe7920c621f..3b2834c0008 100644
--- a/lib/tasks/gitlab/ldap.rake
+++ b/lib/tasks/gitlab/ldap.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :ldap do
desc 'GitLab | LDAP | Rename provider'
diff --git a/lib/tasks/gitlab/lfs/check.rake b/lib/tasks/gitlab/lfs/check.rake
index 869463d4e5d..582b87337ae 100644
--- a/lib/tasks/gitlab/lfs/check.rake
+++ b/lib/tasks/gitlab/lfs/check.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :lfs do
desc 'GitLab | LFS | Check integrity of uploaded LFS objects'
diff --git a/lib/tasks/gitlab/lfs/migrate.rake b/lib/tasks/gitlab/lfs/migrate.rake
index 3d4c847a0f0..05249a126bc 100644
--- a/lib/tasks/gitlab/lfs/migrate.rake
+++ b/lib/tasks/gitlab/lfs/migrate.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
desc "GitLab | LFS | Migrate LFS objects to remote storage"
diff --git a/lib/tasks/gitlab/list_repos.rake b/lib/tasks/gitlab/list_repos.rake
index b854c34a8e5..56ec94d2aef 100644
--- a/lib/tasks/gitlab/list_repos.rake
+++ b/lib/tasks/gitlab/list_repos.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
task list_repos: :environment do
scope = Project
diff --git a/lib/tasks/gitlab/packages/events.rake b/lib/tasks/gitlab/packages/events.rake
index cfe97984dda..4bf4ce430f1 100644
--- a/lib/tasks/gitlab/packages/events.rake
+++ b/lib/tasks/gitlab/packages/events.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
desc "GitLab | Packages | Events | Generate hll counter events file for packages"
diff --git a/lib/tasks/gitlab/packages/migrate.rake b/lib/tasks/gitlab/packages/migrate.rake
index cd6dcf78da3..20a8c51db66 100644
--- a/lib/tasks/gitlab/packages/migrate.rake
+++ b/lib/tasks/gitlab/packages/migrate.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
desc "GitLab | Packages | Migrate packages files to remote storage"
diff --git a/lib/tasks/gitlab/pages.rake b/lib/tasks/gitlab/pages.rake
index e15cbb4e32e..b598dab901d 100644
--- a/lib/tasks/gitlab/pages.rake
+++ b/lib/tasks/gitlab/pages.rake
@@ -1,35 +1,55 @@
+# frozen_string_literal: true
+
require 'logger'
namespace :gitlab do
namespace :pages do
desc "GitLab | Pages | Migrate legacy storage to zip format"
task migrate_legacy_storage: :gitlab_environment do
- logger = Logger.new(STDOUT)
logger.info('Starting to migrate legacy pages storage to zip deployments')
- processed_projects = 0
-
- ProjectPagesMetadatum.only_on_legacy_storage.each_batch(of: 10) do |batch|
- batch.preload(project: [:namespace, :route, pages_metadatum: :pages_deployment]).each do |metadatum|
- project = metadatum.project
-
- result = nil
- time = Benchmark.realtime do
- result = ::Pages::MigrateLegacyStorageToDeploymentService.new(project).execute
- end
- processed_projects += 1
-
- if result[:status] == :success
- logger.info("project_id: #{project.id} #{project.pages_path} has been migrated in #{time} seconds")
- else
- logger.error("project_id: #{project.id} #{project.pages_path} failed to be migrated in #{time} seconds: #{result[:message]}")
- end
- rescue => e
- logger.error("#{e.message} project_id: #{project&.id}")
- Gitlab::ErrorTracking.track_exception(e, project_id: project&.id)
- end
-
- logger.info("#{processed_projects} pages projects are processed")
+
+ result = ::Pages::MigrateFromLegacyStorageService.new(logger,
+ migration_threads: migration_threads,
+ batch_size: batch_size,
+ ignore_invalid_entries: ignore_invalid_entries).execute
+
+ logger.info("A total of #{result[:migrated] + result[:errored]} projects were processed.")
+ logger.info("- The #{result[:migrated]} projects migrated successfully")
+ logger.info("- The #{result[:errored]} projects failed to be migrated")
+ end
+
+ desc "GitLab | Pages | DANGER: Removes data which was migrated from legacy storage on zip storage. Can be used if some bugs in migration are discovered and migration needs to be restarted from scratch."
+ task clean_migrated_zip_storage: :gitlab_environment do
+ destroyed_deployments = 0
+
+ logger.info("Starting to delete migrated pages deployments")
+
+ ::PagesDeployment.migrated_from_legacy_storage.each_batch(of: batch_size) do |batch|
+ destroyed_deployments += batch.count
+
+ # we need to destroy associated files, so can't use delete_all
+ batch.destroy_all # rubocop: disable Cop/DestroyAll
+
+ logger.info("#{destroyed_deployments} deployments were deleted")
end
end
+
+ def logger
+ @logger ||= Logger.new(STDOUT)
+ end
+
+ def migration_threads
+ ENV.fetch('PAGES_MIGRATION_THREADS', '3').to_i
+ end
+
+ def batch_size
+ ENV.fetch('PAGES_MIGRATION_BATCH_SIZE', '10').to_i
+ end
+
+ def ignore_invalid_entries
+ Gitlab::Utils.to_boolean(
+ ENV.fetch('PAGES_MIGRATION_IGNORE_INVALID_ENTRIES', 'false')
+ )
+ end
end
end
diff --git a/lib/tasks/gitlab/password.rake b/lib/tasks/gitlab/password.rake
new file mode 100644
index 00000000000..02c28578a2a
--- /dev/null
+++ b/lib/tasks/gitlab/password.rake
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+namespace :gitlab do
+ namespace :password do
+ desc "GitLab | Password | Reset a user's password"
+ task :reset, [:username] => :environment do |_, args|
+ username = args[:username] || Gitlab::TaskHelpers.prompt('Enter username: ')
+ abort('Username can not be empty.') if username.blank?
+
+ user = User.find_by(username: username)
+ abort("Unable to find user with username #{username}.") unless user
+
+ password = Gitlab::TaskHelpers.prompt_for_password
+ password_confirm = Gitlab::TaskHelpers.prompt_for_password('Confirm password: ')
+
+ user.password = password
+ user.password_confirmation = password_confirm
+ user.send_only_admin_changed_your_password_notification!
+
+ unless user.save
+ message = <<~EOF
+ Unable to change password of the user with username #{username}.
+ #{user.errors.full_messages.to_sentence}
+ EOF
+
+ abort(message)
+ end
+
+ puts "Password successfully updated for user with username #{username}."
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/praefect.rake b/lib/tasks/gitlab/praefect.rake
index a9b126ae379..346df3e0c75 100644
--- a/lib/tasks/gitlab/praefect.rake
+++ b/lib/tasks/gitlab/praefect.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :praefect do
def int?(string)
diff --git a/lib/tasks/gitlab/seed.rake b/lib/tasks/gitlab/seed.rake
index d758280ba69..36761165af5 100644
--- a/lib/tasks/gitlab/seed.rake
+++ b/lib/tasks/gitlab/seed.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :seed do
desc "GitLab | Seed | Seeds issues"
diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake
index 50774de77c9..31bd80e78d4 100644
--- a/lib/tasks/gitlab/setup.rake
+++ b/lib/tasks/gitlab/setup.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
desc "GitLab | Setup production application"
task setup: :gitlab_environment do
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index edbaec85bd9..b3abc48f8e0 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :shell do
desc "GitLab | Shell | Install or upgrade gitlab-shell"
diff --git a/lib/tasks/gitlab/snippets.rake b/lib/tasks/gitlab/snippets.rake
index ed2e88692d5..b55f82480e1 100644
--- a/lib/tasks/gitlab/snippets.rake
+++ b/lib/tasks/gitlab/snippets.rake
@@ -13,7 +13,7 @@ namespace :gitlab do
raise "Please supply the list of ids through the SNIPPET_IDS env var"
end
- raise "Invalid limit value" if limit == 0
+ raise "Invalid limit value" if snippet_task_limit == 0
if migration_running?
raise "There are already snippet migrations running. Please wait until they are finished."
@@ -41,8 +41,8 @@ namespace :gitlab do
end
end
- if ids.size > limit
- raise "The number of ids provided is higher than #{limit}. You can update this limit by using the env var `LIMIT`"
+ if ids.size > snippet_task_limit
+ raise "The number of ids provided is higher than #{snippet_task_limit}. You can update this limit by using the env var `LIMIT`"
end
ids
@@ -68,14 +68,14 @@ namespace :gitlab do
# bundle exec rake gitlab:snippets:list_non_migrated LIMIT=50
desc 'GitLab | Show non migrated snippets'
task list_non_migrated: :environment do
- raise "Invalid limit value" if limit == 0
+ raise "Invalid limit value" if snippet_task_limit == 0
non_migrated_count = non_migrated_snippets.count
if non_migrated_count == 0
puts "All snippets have been successfully migrated"
else
puts "There are #{non_migrated_count} snippets that haven't been migrated. Showing a batch of ids of those snippets:\n"
- puts non_migrated_snippets.limit(limit).pluck(:id).join(',')
+ puts non_migrated_snippets.limit(snippet_task_limit).pluck(:id).join(',')
end
end
@@ -84,7 +84,7 @@ namespace :gitlab do
end
# There are problems with the specs if we memoize this value
- def limit
+ def snippet_task_limit
ENV['LIMIT'] ? ENV['LIMIT'].to_i : DEFAULT_LIMIT
end
end
diff --git a/lib/tasks/gitlab/storage.rake b/lib/tasks/gitlab/storage.rake
index f7819fd974b..ede6b6af80b 100644
--- a/lib/tasks/gitlab/storage.rake
+++ b/lib/tasks/gitlab/storage.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :storage do
desc 'GitLab | Storage | Migrate existing projects to Hashed Storage'
diff --git a/lib/tasks/gitlab/tcp_check.rake b/lib/tasks/gitlab/tcp_check.rake
index 1400f57d6b9..4790d86832d 100644
--- a/lib/tasks/gitlab/tcp_check.rake
+++ b/lib/tasks/gitlab/tcp_check.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
desc "GitLab | Check TCP connectivity to a specific host and port"
task :tcp_check, [:host, :port] => :environment do |_t, args|
diff --git a/lib/tasks/gitlab/terraform/migrate.rake b/lib/tasks/gitlab/terraform/migrate.rake
new file mode 100644
index 00000000000..a9c16049240
--- /dev/null
+++ b/lib/tasks/gitlab/terraform/migrate.rake
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'logger'
+
+desc "GitLab | Terraform | Migrate Terraform states to remote storage"
+namespace :gitlab do
+ namespace :terraform_states do
+ task migrate: :environment do
+ logger = Logger.new(STDOUT)
+ logger.info('Starting transfer of Terraform states to object storage')
+
+ begin
+ Gitlab::Terraform::StateMigrationHelper.migrate_to_remote_storage do |state_version|
+ message = "Transferred Terraform state version ID #{state_version.id} (#{state_version.terraform_state.name}/#{state_version.version}) to object storage"
+
+ logger.info(message)
+ end
+ rescue => e
+ logger.error("Failed to migrate: #{e.message}")
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 2222807fe13..a83ba69bc75 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
desc "GitLab | Run all tests"
task :test do
diff --git a/lib/tasks/gitlab/two_factor.rake b/lib/tasks/gitlab/two_factor.rake
index 6a9e87e1541..9d10976fbce 100644
--- a/lib/tasks/gitlab/two_factor.rake
+++ b/lib/tasks/gitlab/two_factor.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :two_factor do
desc "GitLab | 2FA | Disable Two-factor authentication (2FA) for all users"
diff --git a/lib/tasks/gitlab/update_templates.rake b/lib/tasks/gitlab/update_templates.rake
index fdcd34320b1..e3a4e7f50b8 100644
--- a/lib/tasks/gitlab/update_templates.rake
+++ b/lib/tasks/gitlab/update_templates.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
desc "GitLab | Update templates"
task :update_templates do
diff --git a/lib/tasks/gitlab/uploads/check.rake b/lib/tasks/gitlab/uploads/check.rake
index 2be2ec7f9c9..8ccc84d15f4 100644
--- a/lib/tasks/gitlab/uploads/check.rake
+++ b/lib/tasks/gitlab/uploads/check.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :uploads do
desc 'GitLab | Uploads | Check integrity of uploaded files'
diff --git a/lib/tasks/gitlab/uploads/migrate.rake b/lib/tasks/gitlab/uploads/migrate.rake
index 879b07da1df..6052ff90341 100644
--- a/lib/tasks/gitlab/uploads/migrate.rake
+++ b/lib/tasks/gitlab/uploads/migrate.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :uploads do
namespace :migrate do
diff --git a/lib/tasks/gitlab/uploads/sanitize.rake b/lib/tasks/gitlab/uploads/sanitize.rake
index 4f23a0a5d82..eec423cbb8b 100644
--- a/lib/tasks/gitlab/uploads/sanitize.rake
+++ b/lib/tasks/gitlab/uploads/sanitize.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :uploads do
namespace :sanitize do
diff --git a/lib/tasks/gitlab/usage_data.rake b/lib/tasks/gitlab/usage_data.rake
index d6f5661d5eb..95072444fcf 100644
--- a/lib/tasks/gitlab/usage_data.rake
+++ b/lib/tasks/gitlab/usage_data.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :usage_data do
desc 'GitLab | UsageData | Generate raw SQLs for usage ping in YAML'
@@ -21,5 +23,11 @@ namespace :gitlab do
puts Gitlab::Json.pretty_generate(result.attributes)
end
+
+ desc 'GitLab | UsageData | Generate metrics dictionary'
+ task generate_metrics_dictionary: :environment do
+ items = Gitlab::Usage::MetricDefinition.definitions
+ Gitlab::Usage::Docs::Renderer.new(items).write
+ end
end
end
diff --git a/lib/tasks/gitlab/user_management.rake b/lib/tasks/gitlab/user_management.rake
index f47e549e795..29f2360f64a 100644
--- a/lib/tasks/gitlab/user_management.rake
+++ b/lib/tasks/gitlab/user_management.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :user_management do
desc "GitLab | User management | Update all users of a group with personal project limit to 0 and can_create_group to false"
diff --git a/lib/tasks/gitlab/web_hook.rake b/lib/tasks/gitlab/web_hook.rake
index b242329d720..091743485c9 100644
--- a/lib/tasks/gitlab/web_hook.rake
+++ b/lib/tasks/gitlab/web_hook.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :web_hook do
desc "GitLab | Webhook | Adds a webhook to the projects"
diff --git a/lib/tasks/gitlab/workhorse.rake b/lib/tasks/gitlab/workhorse.rake
index 2d72a01f66f..0d9f8efa64f 100644
--- a/lib/tasks/gitlab/workhorse.rake
+++ b/lib/tasks/gitlab/workhorse.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :workhorse do
desc "GitLab | Workhorse | Install or upgrade gitlab-workhorse"
diff --git a/lib/tasks/gitlab/x509/update.rake b/lib/tasks/gitlab/x509/update.rake
index eaba9196acf..de878a3d093 100644
--- a/lib/tasks/gitlab/x509/update.rake
+++ b/lib/tasks/gitlab/x509/update.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
desc "GitLab | X509 | Update signatures when certificate store has changed"
diff --git a/lib/tasks/gitlab_danger.rake b/lib/tasks/gitlab_danger.rake
index e75539f048c..5df4a8ce4f1 100644
--- a/lib/tasks/gitlab_danger.rake
+++ b/lib/tasks/gitlab_danger.rake
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
desc 'Run local Danger rules'
task :danger_local do
- require 'gitlab_danger'
+ require_relative '../../tooling/gitlab_danger'
require 'gitlab/popen'
puts("#{GitlabDanger.local_warning_message}\n")
diff --git a/lib/tasks/grape.rake b/lib/tasks/grape.rake
index ea2698da606..c72403a375a 100644
--- a/lib/tasks/grape.rake
+++ b/lib/tasks/grape.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :grape do
desc 'Print compiled grape routes'
task routes: :environment do
diff --git a/lib/tasks/haml-lint.rake b/lib/tasks/haml-lint.rake
index 305e15d69d5..270793359e1 100644
--- a/lib/tasks/haml-lint.rake
+++ b/lib/tasks/haml-lint.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
require 'haml_lint/rake_task'
require Rails.root.join('haml_lint/inline_javascript')
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index 500891df43d..633beb132d8 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'benchmark'
require 'rainbow/ext/string'
diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake
index 36590010406..fa3f8805159 100644
--- a/lib/tasks/karma.rake
+++ b/lib/tasks/karma.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
namespace :karma do
# alias exists for legacy reasons
diff --git a/lib/tasks/lint.rake b/lib/tasks/lint.rake
index 7a4d09bb6d4..5d60bc41f21 100644
--- a/lib/tasks/lint.rake
+++ b/lib/tasks/lint.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
namespace :lint do
task :static_verification_env do
diff --git a/lib/tasks/migrate/composite_primary_keys.rake b/lib/tasks/migrate/composite_primary_keys.rake
index 732dedf4d4f..68f7c4d6c4a 100644
--- a/lib/tasks/migrate/composite_primary_keys.rake
+++ b/lib/tasks/migrate/composite_primary_keys.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
namespace :gitlab do
namespace :db do
desc 'GitLab | DB | Adds primary keys to tables that only have composite unique keys'
diff --git a/lib/tasks/migrate/migrate_iids.rake b/lib/tasks/migrate/migrate_iids.rake
index cb7c496c31c..e0666a87656 100644
--- a/lib/tasks/migrate/migrate_iids.rake
+++ b/lib/tasks/migrate/migrate_iids.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc "GitLab | Build internal ids for issues and merge requests"
task migrate_iids: :environment do
puts 'Issues'.color(:yellow)
diff --git a/lib/tasks/migrate/setup_postgresql.rake b/lib/tasks/migrate/setup_postgresql.rake
index 4c8f13b63a4..27dd9e842ff 100644
--- a/lib/tasks/migrate/setup_postgresql.rake
+++ b/lib/tasks/migrate/setup_postgresql.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc 'GitLab | Generate PostgreSQL Password Hash'
task :postgresql_md5_hash do
require 'digest'
diff --git a/lib/tasks/pngquant.rake b/lib/tasks/pngquant.rake
index 63bc1c7c16e..45c0288cadf 100644
--- a/lib/tasks/pngquant.rake
+++ b/lib/tasks/pngquant.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
return if Rails.env.production?
require 'png_quantizator'
diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake
index 78ffccc9d06..f5d16835347 100644
--- a/lib/tasks/rubocop.rake
+++ b/lib/tasks/rubocop.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
require 'rubocop/rake_task'
diff --git a/lib/tasks/scss-lint.rake b/lib/tasks/scss-lint.rake
index 250fd8699e4..8a4809f80fd 100644
--- a/lib/tasks/scss-lint.rake
+++ b/lib/tasks/scss-lint.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless Rails.env.production?
require 'scss_lint/rake_task'
diff --git a/lib/tasks/setup.rake b/lib/tasks/setup.rake
index 4c79ffbfa6b..bae22f9a590 100644
--- a/lib/tasks/setup.rake
+++ b/lib/tasks/setup.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
desc "GitLab | Setup gitlab db"
task :setup do
Rake::Task["gitlab:setup"].invoke
diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake
index b52af81fc16..b24817468c6 100644
--- a/lib/tasks/test.rake
+++ b/lib/tasks/test.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Rake::Task["test"].clear
desc "GitLab | Run all tests"
diff --git a/lib/tasks/tokens.rake b/lib/tasks/tokens.rake
index 46635cd7c8f..b0ff2cce482 100644
--- a/lib/tasks/tokens.rake
+++ b/lib/tasks/tokens.rake
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../app/models/concerns/token_authenticatable.rb'
require_relative '../../app/models/concerns/token_authenticatable_strategies/base.rb'
require_relative '../../app/models/concerns/token_authenticatable_strategies/insecure.rb'
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 82fa7e3e31c..1986d479e2d 100644
--- a/locale/am_ET/gitlab.po
+++ b/locale/am_ET/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: am\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:54\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d የተስተካከለ የáተሻ á‹áŒ¤á‰µ"
msgstr[1] "%d የተስተካከሉ የáተሻ á‹áŒ¤á‰¶á‰½"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr "የ%{authorsName} ክር"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 13b37fb9ef3..96b2280166e 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:00\n"
+"PO-Revision-Date: 2021-02-01 17:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -304,6 +304,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -598,10 +607,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -976,6 +985,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1204,6 +1216,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1333,6 +1348,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1342,10 +1360,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1615,6 +1630,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1633,6 +1651,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1684,6 +1708,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1693,9 +1720,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1705,7 +1729,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1720,6 +1744,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1987,15 +2014,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2254,6 +2281,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2284,9 +2314,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2320,7 +2347,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2344,6 +2371,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2353,7 +2383,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2383,9 +2419,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2407,6 +2440,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2557,6 +2593,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2584,6 +2623,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2692,6 +2734,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -3124,7 +3169,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3265,7 +3310,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3316,6 +3361,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3367,6 +3415,9 @@ 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 ""
@@ -3394,6 +3445,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3610,6 +3664,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3781,6 +3838,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3895,12 +3955,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -4081,7 +4135,7 @@ 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}"
+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?"
@@ -4174,15 +4228,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4252,7 +4309,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4276,9 +4333,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4537,9 +4591,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4564,7 +4615,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4663,16 +4714,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4813,25 +4864,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4840,10 +4891,16 @@ 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 Gold."
+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}."
@@ -4864,6 +4921,9 @@ 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 ""
@@ -4873,6 +4933,9 @@ 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 ""
@@ -4888,6 +4951,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4978,10 +5044,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -5005,6 +5071,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -5200,6 +5269,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5239,16 +5311,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -5299,6 +5380,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5308,6 +5392,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5344,6 +5431,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5452,9 +5542,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5605,6 +5692,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5647,6 +5740,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,6 +5767,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5773,6 +5872,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5986,9 +6088,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -6007,6 +6106,9 @@ 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 ""
@@ -6166,12 +6268,24 @@ 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 ""
@@ -6214,7 +6328,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7393,7 +7507,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7411,9 +7525,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7450,6 +7561,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7675,6 +7789,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7849,9 +7969,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7969,9 +8086,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7999,6 +8122,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -8095,6 +8227,9 @@ 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 ""
@@ -8122,9 +8257,15 @@ 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 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 ""
@@ -8140,9 +8281,15 @@ 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 ""
@@ -8320,6 +8467,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8374,6 +8524,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8677,12 +8830,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8698,16 +8863,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8719,9 +8881,15 @@ 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 ""
@@ -8737,6 +8905,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8752,6 +8923,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8851,10 +9025,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8881,7 +9055,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8890,9 +9064,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8965,7 +9136,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -9181,7 +9352,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -9211,6 +9382,12 @@ 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 ""
@@ -9223,6 +9400,9 @@ 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 ""
@@ -9235,6 +9415,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9250,6 +9433,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9274,7 +9460,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9286,9 +9472,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9328,6 +9511,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9337,6 +9526,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9346,9 +9538,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9364,6 +9562,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9373,6 +9574,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9385,6 +9589,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9679,7 +9886,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -10051,6 +10258,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10234,7 +10468,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10285,25 +10519,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10330,22 +10564,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Create new segment"
-msgstr ""
-
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10354,24 +10585,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10393,18 +10624,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10462,7 +10687,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10759,9 +10984,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10990,6 +11212,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -11056,6 +11287,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -11065,6 +11299,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -11104,7 +11341,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -11143,7 +11380,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -11206,15 +11443,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11311,13 +11554,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11608,6 +11848,9 @@ 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 ""
@@ -11623,6 +11866,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -12013,9 +12262,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -12151,15 +12397,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12283,6 +12535,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12466,9 +12721,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12988,10 +13240,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -13015,12 +13279,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -13096,7 +13354,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -13144,6 +13402,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13558,7 +13819,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13588,9 +13849,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13627,6 +13885,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13711,9 +13972,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13741,6 +13999,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -14014,9 +14275,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -14032,9 +14290,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -14086,6 +14341,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -14095,6 +14356,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -14119,6 +14383,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14518,9 +14788,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14587,6 +14854,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14833,6 +15103,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14944,9 +15220,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14962,18 +15235,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -15232,15 +15502,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15376,9 +15991,39 @@ 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 ""
@@ -15460,7 +16105,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15502,10 +16147,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15535,9 +16180,21 @@ msgstr[5] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15643,6 +16300,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15673,6 +16333,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15682,12 +16348,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15712,6 +16384,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15739,6 +16414,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15826,6 +16504,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15886,6 +16567,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -16141,6 +16825,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -16195,9 +16885,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16237,6 +16924,9 @@ 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 ""
@@ -16339,24 +17029,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16372,6 +17080,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16384,9 +17095,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16465,6 +17188,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16504,7 +17230,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16579,6 +17305,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16606,6 +17335,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16795,7 +17527,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16879,7 +17611,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16900,9 +17632,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -17230,6 +17959,9 @@ msgstr[5] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17404,9 +18136,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17431,6 +18160,12 @@ 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 ""
@@ -17455,9 +18190,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17500,6 +18232,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17692,12 +18427,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17737,9 +18475,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17782,6 +18517,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17809,9 +18547,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17830,9 +18565,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17929,6 +18661,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -18022,6 +18757,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -18103,9 +18841,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -18172,15 +18907,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18583,6 +19312,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18757,6 +19489,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18808,9 +19543,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18979,9 +19711,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -19123,12 +19852,6 @@ 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 ""
@@ -19147,6 +19870,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -19201,6 +19930,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19453,7 +20185,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19570,6 +20302,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19663,6 +20398,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19738,9 +20476,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19750,6 +20485,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -20125,6 +20863,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -20134,12 +20875,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -20200,10 +20947,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -20215,9 +20962,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -20269,10 +21025,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20314,7 +21070,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20332,9 +21088,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20353,7 +21106,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20461,15 +21214,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20644,9 +21397,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20665,6 +21415,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20737,9 +21490,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20755,6 +21505,9 @@ 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 ""
@@ -20893,6 +21646,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -21007,6 +21763,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -21073,6 +21832,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -21085,6 +21847,9 @@ 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 ""
@@ -21253,9 +22018,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -21268,9 +22030,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21292,6 +22051,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21406,6 +22168,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -22075,12 +22840,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -22126,9 +22894,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22411,6 +23176,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22828,6 +23596,9 @@ 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|What are badges?"
msgstr ""
@@ -22951,7 +23722,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23326,6 +24097,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23374,6 +24148,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23410,6 +24187,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23419,9 +24199,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23431,7 +24208,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23650,6 +24427,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23767,12 +24547,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23800,21 +24589,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23914,9 +24691,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -24010,6 +24784,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -24265,6 +25042,15 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
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] ""
@@ -24436,6 +25222,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24577,7 +25366,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24700,6 +25489,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24751,6 +25543,9 @@ 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 ""
@@ -24796,6 +25591,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24841,6 +25639,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24862,21 +25663,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24889,21 +25678,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24925,24 +25729,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -25015,6 +25834,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25405,6 +26227,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25420,6 +26245,9 @@ 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 ""
@@ -25579,9 +26407,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25645,9 +26470,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25759,13 +26581,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25825,7 +26647,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25855,6 +26677,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25912,9 +26737,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -26197,6 +27019,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -26236,10 +27061,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -26254,9 +27079,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26401,9 +27223,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26458,6 +27277,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26704,9 +27526,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26851,6 +27670,9 @@ 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 %{listType} list"
msgstr ""
@@ -27217,7 +28039,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -27226,9 +28048,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -27247,9 +28066,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -27304,7 +28120,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27337,9 +28153,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27349,7 +28162,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27376,15 +28189,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27562,6 +28375,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27973,6 +28789,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27997,9 +28816,15 @@ 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 ""
@@ -28180,15 +29005,18 @@ msgstr[5] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -28243,10 +29071,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28588,9 +29416,6 @@ msgstr[5] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28645,6 +29470,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28663,6 +29491,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28678,7 +29515,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28696,9 +29536,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28744,6 +29581,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28771,9 +29611,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28828,7 +29665,7 @@ 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 an approval"
+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"
@@ -28936,7 +29773,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28984,6 +29821,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28996,6 +29836,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -29149,16 +29992,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -29188,7 +30040,7 @@ 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."
+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."
@@ -29203,22 +30055,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -29233,13 +30097,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -29317,9 +30184,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29332,13 +30196,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29368,6 +30235,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29491,6 +30361,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29500,6 +30373,15 @@ 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 ""
@@ -29536,7 +30418,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29593,6 +30475,9 @@ 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 ""
@@ -29626,18 +30511,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -30055,6 +30934,9 @@ 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 ""
@@ -30070,6 +30952,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -30079,6 +30964,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -30112,6 +31000,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -30127,7 +31018,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -30145,12 +31036,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -30166,9 +31051,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -30187,6 +31069,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -30214,6 +31099,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -30244,6 +31132,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30334,6 +31225,9 @@ 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 ""
@@ -30394,7 +31288,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30406,7 +31300,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30433,7 +31327,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30448,7 +31342,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30457,6 +31351,9 @@ 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 ""
@@ -30466,7 +31363,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30493,7 +31390,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30709,7 +31609,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30967,7 +31867,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30988,6 +31888,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -31186,12 +32089,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -31207,7 +32116,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -31321,7 +32233,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31480,21 +32392,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31558,9 +32464,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31585,6 +32488,15 @@ 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 ""
@@ -31762,6 +32674,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -32140,6 +33055,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -32149,6 +33070,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -32284,10 +33208,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -32305,7 +33229,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -32314,7 +33238,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -32335,6 +33259,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32347,6 +33274,9 @@ msgstr[5] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32707,9 +33637,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32731,9 +33658,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32758,9 +33682,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32782,6 +33703,9 @@ 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 ""
@@ -32797,15 +33721,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32833,7 +33757,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32974,6 +33898,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32986,6 +33913,9 @@ 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 no permissions"
msgstr ""
@@ -33169,6 +34099,9 @@ 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 ""
@@ -33205,13 +34138,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33367,6 +34300,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33451,6 +34387,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33541,9 +34483,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33862,6 +34810,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33907,8 +34858,14 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -34009,6 +34966,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -34261,6 +35221,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34387,9 +35353,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34459,7 +35422,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34540,6 +35503,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34783,6 +35749,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34921,6 +35890,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index fb43edc3225..4563890e6ae 100644
--- a/locale/as_IN/gitlab.po
+++ b/locale/as_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: as\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:09\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index e008ae794b0..4703e5cde81 100644
--- a/locale/az_AZ/gitlab.po
+++ b/locale/az_AZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: az\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:07\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index 76f2a561710..2330e50d445 100644
--- a/locale/ba_RU/gitlab.po
+++ b/locale/ba_RU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ba\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:10\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -318,10 +322,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -958,14 +968,14 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1155,6 +1165,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1789,6 +1811,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2119,6 +2153,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2227,6 +2264,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,7 +2694,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2795,7 +2835,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3140,6 +3189,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,7 +3640,7 @@ 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}"
+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?"
@@ -3679,15 +3728,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3757,7 +3809,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4032,9 +4081,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,7 +4105,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4158,16 +4204,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4308,25 +4354,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4335,10 +4381,16 @@ 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 Gold."
+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}."
@@ -4359,6 +4411,9 @@ 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 ""
@@ -4368,6 +4423,9 @@ 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 ""
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4690,6 +4754,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4834,6 +4916,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5497,6 +5591,9 @@ 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 ""
@@ -5656,12 +5753,24 @@ 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 ""
@@ -5704,7 +5813,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8316,10 +8485,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8346,7 +8515,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,7 +8596,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8641,7 +8807,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,7 +10112,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10184,9 +10404,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,7 +10761,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,7 +12769,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12564,6 +12817,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,7 +13234,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,7 +15495,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -14897,10 +15537,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -14925,9 +15565,21 @@ msgstr[0] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,7 +16615,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,7 +16907,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18319,9 +19046,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,7 +19505,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -18988,6 +19718,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 ""
@@ -20573,9 +21333,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21446,9 +22209,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21731,6 +22491,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,7 +24641,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -23985,6 +24764,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,7 +25852,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,16 +29162,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28368,7 +29210,7 @@ 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."
+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."
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,13 +29366,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 ""
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,7 +31271,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 ""
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31497,6 +32414,9 @@ msgstr[0] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr ""
@@ -32319,6 +33239,9 @@ 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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33497,9 +34448,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33569,7 +34517,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index b03e7155ebb..c3f8e4d8ba3 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:00\n"
+"PO-Revision-Date: 2021-02-01 17:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "от"
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Подбиране"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "ОтмÑна"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr "Ñи Ñъздадете личен жетон за доÑтъп"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Редактиране"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr "От Ñъздаването на проблема до внедрÑваÐ
msgid "From merge request merge until deploy to production"
msgstr "От прилагането на заÑвката за Ñливане до внедрÑването в крайната верÑиÑ"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr "ОÑвежаването започна уÑпешно"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Опции"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr "План за Ñхема"
msgid "Pipeline Schedules"
msgstr "Планове за Ñхема"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Свързани внедрени задачи"
-
msgid "Related Issues"
msgstr "Свързани проблеми"
-msgid "Related Jobs"
-msgstr "Свързани задачи"
-
-msgid "Related Merge Requests"
-msgstr "Свързани заÑвки за Ñливане"
-
-msgid "Related Merged Requests"
-msgstr "Свързани приложени заÑвки за Ñливане"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr "Изберете чаÑова зона"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Изберете целеви клон"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Създайте %{new_merge_request} Ñ Ñ‚ÐµÐ·Ð¸ промени"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "Връзката на разклонение беше премахната."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "Етапът от цикъла на разработка"
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Етапът на преглед и одобрение показва времето от Ñъздаването на заÑвката за Ñливане до прилагането Ñ. Данните ще бъдат добавени автоматично Ñлед като приложите първата Ñи заÑвка за Ñливане."
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "ден"
msgstr[1] "дни"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 17dcc57321a..90466370bb0 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:06\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index cc31963e35a..de6a0d7dc94 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:54\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index f1e2844a5e7..55390198313 100644
--- a/locale/bs_BA/gitlab.po
+++ b/locale/bs_BA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:57\n"
+"PO-Revision-Date: 2021-02-01 17:09\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -226,6 +226,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d grupa odabrana"
@@ -430,10 +436,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -787,6 +793,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -985,6 +994,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1108,16 +1120,16 @@ msgstr ""
msgid ", or "
msgstr " ili "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1339,6 +1351,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1357,6 +1372,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1408,6 +1429,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1417,9 +1441,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1429,7 +1450,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1444,6 +1465,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1708,15 +1732,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1975,6 +1999,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2005,9 +2032,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2041,7 +2065,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2065,6 +2089,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2074,7 +2101,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2104,9 +2137,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2128,6 +2158,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2278,6 +2311,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2305,6 +2341,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2413,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2842,7 +2884,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2983,7 +3025,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3034,6 +3076,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3085,6 +3130,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3328,6 +3379,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3499,6 +3553,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3613,12 +3670,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3787,7 +3838,7 @@ 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}"
+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?"
@@ -3877,15 +3928,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3955,7 +4009,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3979,9 +4033,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4234,9 +4285,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4261,7 +4309,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4360,16 +4408,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4510,25 +4558,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Naplata"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4537,10 +4585,16 @@ 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 Gold."
+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}."
@@ -4561,6 +4615,9 @@ 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 ""
@@ -4570,6 +4627,9 @@ 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 ""
@@ -4585,6 +4645,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4672,10 +4735,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4699,6 +4762,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4894,6 +4960,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4933,16 +5002,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4993,6 +5071,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5002,6 +5083,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5038,6 +5122,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5146,9 +5233,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5299,6 +5383,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5341,6 +5431,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5365,6 +5458,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5467,6 +5563,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5680,9 +5779,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5701,6 +5797,9 @@ 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 ""
@@ -5860,12 +5959,24 @@ 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 ""
@@ -5908,7 +6019,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7087,7 +7198,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7105,9 +7216,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7144,6 +7252,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7366,6 +7477,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7540,9 +7657,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7654,9 +7768,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7684,6 +7804,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7777,6 +7906,9 @@ 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 ""
@@ -7804,9 +7936,15 @@ 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 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 ""
@@ -7822,9 +7960,15 @@ 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 ""
@@ -8002,6 +8146,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8056,6 +8203,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8356,12 +8506,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8377,16 +8539,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8398,9 +8557,15 @@ 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 ""
@@ -8416,6 +8581,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8431,6 +8599,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Kreirano"
@@ -8530,10 +8701,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8560,7 +8731,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8569,9 +8740,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8644,7 +8812,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8857,7 +9025,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8887,6 +9055,12 @@ 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 ""
@@ -8899,6 +9073,9 @@ 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 ""
@@ -8911,6 +9088,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8926,6 +9106,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8950,7 +9133,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8962,9 +9145,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9004,6 +9184,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9013,6 +9199,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9022,9 +9211,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9040,6 +9235,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9049,6 +9247,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9061,6 +9262,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9355,7 +9559,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9709,6 +9913,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9892,7 +10123,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9943,25 +10174,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9988,22 +10219,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10012,24 +10240,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10051,18 +10279,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10120,7 +10342,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10414,9 +10636,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10645,6 +10864,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10711,6 +10939,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10720,6 +10951,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10759,7 +10993,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10798,7 +11032,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10861,15 +11095,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10966,13 +11206,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11263,6 +11500,9 @@ msgstr ""
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "Jesi li siguran da želiš ukloniti %{bStart}%{targetIssueTitle}%{bEnd} iz %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11278,6 +11518,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11668,9 +11914,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11806,15 +12049,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11938,6 +12187,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12121,9 +12373,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12640,10 +12889,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12667,12 +12928,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12748,7 +13003,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12796,6 +13051,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13210,7 +13468,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13240,9 +13498,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13279,6 +13534,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13363,9 +13621,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13393,6 +13648,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13666,9 +13924,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13684,9 +13939,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13738,6 +13990,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13747,6 +14005,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13771,6 +14032,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14170,9 +14437,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14239,6 +14503,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14479,6 +14746,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14590,9 +14863,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14608,18 +14878,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14869,15 +15136,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15013,9 +15625,39 @@ 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 ""
@@ -15097,7 +15739,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15139,10 +15781,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15169,9 +15811,21 @@ msgstr[2] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15277,6 +15931,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15307,6 +15964,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15316,12 +15979,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,6 +16015,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15373,6 +16045,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15460,6 +16135,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15520,6 +16198,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15775,6 +16456,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15829,9 +16516,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15871,6 +16555,9 @@ 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 ""
@@ -15973,24 +16660,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16006,6 +16711,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16018,9 +16726,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16099,6 +16819,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16138,7 +16861,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16213,6 +16936,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16240,6 +16966,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16426,7 +17155,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16510,7 +17239,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16531,9 +17260,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16840,6 +17566,9 @@ msgstr[2] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17014,9 +17743,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17041,6 +17767,12 @@ 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 ""
@@ -17065,9 +17797,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17110,6 +17839,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17302,12 +18034,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17347,9 +18082,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17392,6 +18124,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17419,9 +18154,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17440,9 +18172,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17539,6 +18268,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17632,6 +18364,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17713,9 +18448,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17782,15 +18514,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18190,6 +18916,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18361,6 +19090,9 @@ msgstr "Minute"
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18412,9 +19144,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18583,9 +19312,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18721,12 +19447,6 @@ 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 ""
@@ -18745,6 +19465,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18799,6 +19525,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19048,7 +19777,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19165,6 +19894,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19258,6 +19990,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19333,9 +20068,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19345,6 +20077,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19720,6 +20455,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19729,12 +20467,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19795,10 +20539,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19810,9 +20554,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19864,10 +20617,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19906,7 +20659,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19924,9 +20677,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19945,7 +20695,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20053,15 +20803,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20236,9 +20986,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20257,6 +21004,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20329,9 +21079,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20347,6 +21094,9 @@ 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 ""
@@ -20485,6 +21235,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20599,6 +21352,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20665,6 +21421,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20677,6 +21436,9 @@ 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 ""
@@ -20845,9 +21607,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20860,9 +21619,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20884,6 +21640,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20998,6 +21757,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21667,12 +22429,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21718,9 +22483,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22003,6 +22765,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22420,6 +23185,9 @@ 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|What are badges?"
msgstr ""
@@ -22543,7 +23311,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22918,6 +23686,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22966,6 +23737,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23002,6 +23776,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23011,9 +23788,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23023,7 +23797,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23242,6 +24016,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23356,12 +24133,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23389,21 +24175,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23500,9 +24274,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23596,6 +24367,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23845,6 +24619,12 @@ 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] ""
+msgstr[2] ""
+
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] ""
@@ -24013,6 +24793,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24148,7 +24931,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24271,6 +25054,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24319,6 +25105,9 @@ 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 ""
@@ -24361,6 +25150,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24406,6 +25198,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24427,21 +25222,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24454,21 +25237,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24490,24 +25288,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24580,6 +25393,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24937,6 +25753,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24952,6 +25771,9 @@ 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 ""
@@ -25111,9 +25933,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25177,9 +25996,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25288,13 +26104,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25354,7 +26170,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25384,6 +26200,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25441,9 +26260,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25726,6 +26542,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25765,10 +26584,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25783,9 +26602,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25930,9 +26746,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25987,6 +26800,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26227,9 +27043,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26374,6 +27187,9 @@ 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 %{listType} list"
msgstr ""
@@ -26740,7 +27556,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26749,9 +27565,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26770,9 +27583,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26827,7 +27637,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26860,9 +27670,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26872,7 +27679,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26899,15 +27706,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27085,6 +27892,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27496,6 +28306,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27520,9 +28333,15 @@ 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 ""
@@ -27697,15 +28516,18 @@ msgstr[2] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27760,10 +28582,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28096,9 +28918,6 @@ msgstr[2] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28153,6 +28972,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28171,6 +28993,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28186,7 +29017,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28204,9 +29038,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28252,6 +29083,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28279,9 +29113,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28336,7 +29167,7 @@ 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 an approval"
+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"
@@ -28444,7 +29275,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28492,6 +29323,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28504,6 +29338,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28657,16 +29494,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28696,7 +29542,7 @@ 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."
+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."
@@ -28711,22 +29557,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28741,13 +29599,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28825,9 +29686,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28840,13 +29698,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28876,6 +29737,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28999,6 +29863,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29008,6 +29875,15 @@ 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 ""
@@ -29044,7 +29920,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29101,6 +29977,9 @@ 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 ""
@@ -29134,18 +30013,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29557,6 +30430,9 @@ 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 ""
@@ -29572,6 +30448,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29581,6 +30460,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29614,6 +30496,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29629,7 +30514,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29647,12 +30532,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29668,9 +30547,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29689,6 +30565,9 @@ msgstr ""
msgid "Today"
msgstr "Danas"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29716,6 +30595,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29746,6 +30628,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29836,6 +30721,9 @@ 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 ""
@@ -29893,7 +30781,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29905,7 +30793,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29932,7 +30820,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29947,7 +30835,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29956,6 +30844,9 @@ 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 ""
@@ -29965,7 +30856,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29992,7 +30883,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30208,7 +31102,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30466,7 +31360,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30487,6 +31381,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30685,12 +31582,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30706,7 +31609,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30820,7 +31726,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30979,21 +31885,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31057,9 +31957,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31084,6 +31981,15 @@ 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 ""
@@ -31255,6 +32161,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31633,6 +32542,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31642,6 +32557,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31777,10 +32695,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31798,7 +32716,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31807,7 +32725,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31828,6 +32746,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31837,6 +32758,9 @@ msgstr[2] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32197,9 +33121,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32221,9 +33142,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32248,9 +33166,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32272,6 +33187,9 @@ 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 ""
@@ -32287,15 +33205,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32323,7 +33241,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32464,6 +33382,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32476,6 +33397,9 @@ 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 no permissions"
msgstr ""
@@ -32659,6 +33583,9 @@ 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 ""
@@ -32695,13 +33622,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32857,6 +33784,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32941,6 +33871,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33028,9 +33964,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33343,6 +34285,9 @@ msgstr[0] "dan"
msgstr[1] "dana"
msgstr[2] "dana"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33385,8 +34330,11 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33481,6 +34429,9 @@ msgstr "grupa"
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33727,6 +34678,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33853,9 +34810,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33925,7 +34879,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34234,6 +35191,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34372,6 +35332,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 49f233fbd53..65679abdca1 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:00\n"
+"PO-Revision-Date: 2021-02-01 17:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr "Suprimeix l'usuari"
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anònim"
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ msgstr ""
msgid "Archived projects"
msgstr "Projectes arxivats"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Facturació"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Trieu un color."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Creat"
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr "Branca actual"
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr "Perfil"
msgid "CurrentUser|Settings"
msgstr "Configuració"
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr "Desactiva"
msgid "Disable for this project"
msgstr "Desactiva per a aquest projecte"
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Edita"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ msgstr "Missatge a peu de pàgina"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr "Identitats"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ msgstr[1] "Instàncies"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Cancel·la"
-
msgid "Modal|Close"
msgstr "Tanca"
@@ -18451,9 +19179,6 @@ msgstr "Nom"
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 3164c7baac1..a0c4f497d9e 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:00\n"
+"PO-Revision-Date: 2021-02-01 17:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,6 +252,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -486,10 +493,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1183,6 +1196,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1190,10 +1206,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1431,6 +1444,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1801,15 +1826,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2068,6 +2093,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2098,9 +2126,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2167,7 +2195,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2398,6 +2435,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2506,6 +2546,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2936,7 +2979,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3422,6 +3474,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3593,6 +3648,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3707,12 +3765,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,7 +3937,7 @@ 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}"
+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?"
@@ -3976,15 +4028,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4054,7 +4109,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "PÅ™iÅ™aÄte vlastní barvu jako například #FF0000"
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr "Přiřadit štítky"
@@ -4335,9 +4387,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4362,7 +4411,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4461,16 +4510,16 @@ msgstr "K dispozici"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4611,25 +4660,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4638,10 +4687,16 @@ 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 Gold."
+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}."
@@ -4662,6 +4717,9 @@ 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 ""
@@ -4671,6 +4729,9 @@ 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 ""
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4996,6 +5063,9 @@ msgstr "nastavení projektu"
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -5095,6 +5174,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5140,6 +5225,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5782,9 +5882,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ 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 ""
@@ -6010,7 +6122,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8463,12 +8614,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8637,10 +8809,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8667,7 +8839,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,7 +10457,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,7 +11109,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ 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 ""
@@ -11393,6 +11634,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12864,7 +13120,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13326,7 +13585,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,10 +15903,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15642,6 +16321,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,7 +16984,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16335,6 +17059,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,7 +17279,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 ""
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17477,9 +18213,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18715,9 +19445,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,7 +19913,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20813,6 +21573,9 @@ 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 ""
@@ -20981,9 +21744,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21854,9 +22620,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22139,6 +22902,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23493,12 +24271,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,7 +25076,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24414,6 +25199,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24463,6 +25251,9 @@ 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 ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24725,6 +25540,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,7 +26329,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,7 +27717,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26986,7 +27798,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27031,7 +27840,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27244,6 +28053,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28350,7 +29183,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28416,6 +29249,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,7 +29708,7 @@ 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."
+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."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29004,13 +29864,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29040,6 +29903,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 ""
@@ -29208,7 +30086,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ 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 ""
@@ -29738,6 +30616,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,7 +30682,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,7 +31271,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30633,7 +31529,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 "Pomocí %{code_start}::%{code_end} vytvořte sadu %{link_start} štítků s rozsahem %{link_end} (např. Priorita %{code_start}::1%{code_end})"
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,7 +31778,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31946,10 +32866,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32391,9 +33314,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ 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 ""
@@ -32865,13 +33794,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34031,9 +34991,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34103,7 +35060,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34184,6 +35141,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 67513c02769..bcd2259dcf1 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:07\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -304,6 +304,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -598,10 +607,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -976,6 +985,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1204,6 +1216,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1333,6 +1348,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1342,10 +1360,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1615,6 +1630,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1633,6 +1651,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1684,6 +1708,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1693,9 +1720,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1705,7 +1729,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1720,6 +1744,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1987,15 +2014,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2254,6 +2281,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2284,9 +2314,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2320,7 +2347,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2344,6 +2371,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2353,7 +2383,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2383,9 +2419,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2407,6 +2440,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2557,6 +2593,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2584,6 +2623,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2692,6 +2734,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -3124,7 +3169,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3265,7 +3310,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3316,6 +3361,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3367,6 +3415,9 @@ 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 ""
@@ -3394,6 +3445,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3610,6 +3664,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3781,6 +3838,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3895,12 +3955,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -4081,7 +4135,7 @@ 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}"
+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?"
@@ -4174,15 +4228,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4252,7 +4309,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4276,9 +4333,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4537,9 +4591,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4564,7 +4615,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4663,16 +4714,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4813,25 +4864,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4840,10 +4891,16 @@ 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 Gold."
+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}."
@@ -4864,6 +4921,9 @@ 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 ""
@@ -4873,6 +4933,9 @@ 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 ""
@@ -4888,6 +4951,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4978,10 +5044,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -5005,6 +5071,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -5200,6 +5269,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5239,16 +5311,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -5299,6 +5380,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5308,6 +5392,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5344,6 +5431,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5452,9 +5542,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5605,6 +5692,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5647,6 +5740,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5671,6 +5767,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5773,6 +5872,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5986,9 +6088,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -6007,6 +6106,9 @@ 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 ""
@@ -6166,12 +6268,24 @@ 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 ""
@@ -6214,7 +6328,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7393,7 +7507,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7411,9 +7525,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7450,6 +7561,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7675,6 +7789,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7849,9 +7969,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7969,9 +8086,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7999,6 +8122,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -8095,6 +8227,9 @@ 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 ""
@@ -8122,9 +8257,15 @@ 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 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 ""
@@ -8140,9 +8281,15 @@ 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 ""
@@ -8320,6 +8467,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8374,6 +8524,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8677,12 +8830,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8698,16 +8863,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8719,9 +8881,15 @@ 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 ""
@@ -8737,6 +8905,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8752,6 +8923,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8851,10 +9025,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8881,7 +9055,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8890,9 +9064,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8965,7 +9136,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -9181,7 +9352,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -9211,6 +9382,12 @@ 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 ""
@@ -9223,6 +9400,9 @@ 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 ""
@@ -9235,6 +9415,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9250,6 +9433,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9274,7 +9460,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9286,9 +9472,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9328,6 +9511,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9337,6 +9526,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9346,9 +9538,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9364,6 +9562,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9373,6 +9574,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9385,6 +9589,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9679,7 +9886,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -10051,6 +10258,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10234,7 +10468,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10285,25 +10519,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10330,22 +10564,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Create new segment"
-msgstr ""
-
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10354,24 +10585,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10393,18 +10624,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10462,7 +10687,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10759,9 +10984,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10990,6 +11212,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -11056,6 +11287,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -11065,6 +11299,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -11104,7 +11341,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -11143,7 +11380,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -11206,15 +11443,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11311,13 +11554,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11608,6 +11848,9 @@ 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 ""
@@ -11623,6 +11866,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -12013,9 +12262,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -12151,15 +12397,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12283,6 +12535,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12466,9 +12721,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12988,10 +13240,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -13015,12 +13279,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -13096,7 +13354,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -13144,6 +13402,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13558,7 +13819,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13588,9 +13849,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13627,6 +13885,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13711,9 +13972,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13741,6 +13999,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -14014,9 +14275,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -14032,9 +14290,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -14086,6 +14341,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -14095,6 +14356,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -14119,6 +14383,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14518,9 +14788,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14587,6 +14854,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14833,6 +15103,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14944,9 +15220,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14962,18 +15235,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -15232,15 +15502,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15376,9 +15991,39 @@ 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 ""
@@ -15460,7 +16105,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15502,10 +16147,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15535,9 +16180,21 @@ msgstr[5] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15643,6 +16300,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15673,6 +16333,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15682,12 +16348,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15712,6 +16384,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15739,6 +16414,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15826,6 +16504,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15886,6 +16567,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -16141,6 +16825,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -16195,9 +16885,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16237,6 +16924,9 @@ 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 ""
@@ -16339,24 +17029,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16372,6 +17080,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16384,9 +17095,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16465,6 +17188,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16504,7 +17230,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16579,6 +17305,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16606,6 +17335,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16795,7 +17527,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16879,7 +17611,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16900,9 +17632,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -17230,6 +17959,9 @@ msgstr[5] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17404,9 +18136,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17431,6 +18160,12 @@ 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 ""
@@ -17455,9 +18190,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17500,6 +18232,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17692,12 +18427,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17737,9 +18475,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17782,6 +18517,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17809,9 +18547,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17830,9 +18565,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17929,6 +18661,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -18022,6 +18757,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -18103,9 +18841,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -18172,15 +18907,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18583,6 +19312,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18757,6 +19489,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18808,9 +19543,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18979,9 +19711,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -19123,12 +19852,6 @@ 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 ""
@@ -19147,6 +19870,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -19201,6 +19930,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19453,7 +20185,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19570,6 +20302,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19663,6 +20398,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19738,9 +20476,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19750,6 +20485,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -20125,6 +20863,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -20134,12 +20875,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -20200,10 +20947,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -20215,9 +20962,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -20269,10 +21025,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20314,7 +21070,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20332,9 +21088,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20353,7 +21106,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20461,15 +21214,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20644,9 +21397,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20665,6 +21415,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20737,9 +21490,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20755,6 +21505,9 @@ 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 ""
@@ -20893,6 +21646,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -21007,6 +21763,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -21073,6 +21832,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -21085,6 +21847,9 @@ 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 ""
@@ -21253,9 +22018,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -21268,9 +22030,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21292,6 +22051,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21406,6 +22168,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -22075,12 +22840,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -22126,9 +22894,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22411,6 +23176,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22828,6 +23596,9 @@ 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|What are badges?"
msgstr ""
@@ -22951,7 +23722,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23326,6 +24097,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23374,6 +24148,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23410,6 +24187,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23419,9 +24199,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23431,7 +24208,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23650,6 +24427,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23767,12 +24547,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23800,21 +24589,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23914,9 +24691,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -24010,6 +24784,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -24265,6 +25042,15 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
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] ""
@@ -24436,6 +25222,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24577,7 +25366,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24700,6 +25489,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24751,6 +25543,9 @@ 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 ""
@@ -24796,6 +25591,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24841,6 +25639,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24862,21 +25663,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24889,21 +25678,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24925,24 +25729,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -25015,6 +25834,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25405,6 +26227,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25420,6 +26245,9 @@ 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 ""
@@ -25579,9 +26407,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25645,9 +26470,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25759,13 +26581,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25825,7 +26647,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25855,6 +26677,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25912,9 +26737,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -26197,6 +27019,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -26236,10 +27061,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -26254,9 +27079,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26401,9 +27223,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26458,6 +27277,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26704,9 +27526,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26851,6 +27670,9 @@ 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 %{listType} list"
msgstr ""
@@ -27217,7 +28039,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -27226,9 +28048,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -27247,9 +28066,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -27304,7 +28120,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27337,9 +28153,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27349,7 +28162,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27376,15 +28189,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27562,6 +28375,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27973,6 +28789,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27997,9 +28816,15 @@ 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 ""
@@ -28180,15 +29005,18 @@ msgstr[5] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -28243,10 +29071,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28588,9 +29416,6 @@ msgstr[5] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28645,6 +29470,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28663,6 +29491,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28678,7 +29515,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28696,9 +29536,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28744,6 +29581,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28771,9 +29611,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28828,7 +29665,7 @@ 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 an approval"
+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"
@@ -28936,7 +29773,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28984,6 +29821,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28996,6 +29836,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -29149,16 +29992,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -29188,7 +30040,7 @@ 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."
+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."
@@ -29203,22 +30055,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -29233,13 +30097,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -29317,9 +30184,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29332,13 +30196,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29368,6 +30235,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29491,6 +30361,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29500,6 +30373,15 @@ 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 ""
@@ -29536,7 +30418,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29593,6 +30475,9 @@ 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 ""
@@ -29626,18 +30511,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -30055,6 +30934,9 @@ 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 ""
@@ -30070,6 +30952,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -30079,6 +30964,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -30112,6 +31000,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -30127,7 +31018,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -30145,12 +31036,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -30166,9 +31051,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -30187,6 +31069,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -30214,6 +31099,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -30244,6 +31132,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30334,6 +31225,9 @@ 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 ""
@@ -30394,7 +31288,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30406,7 +31300,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30433,7 +31327,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30448,7 +31342,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30457,6 +31351,9 @@ 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 ""
@@ -30466,7 +31363,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30493,7 +31390,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30709,7 +31609,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30967,7 +31867,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30988,6 +31888,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -31186,12 +32089,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -31207,7 +32116,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -31321,7 +32233,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31480,21 +32392,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31558,9 +32464,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31585,6 +32488,15 @@ 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 ""
@@ -31762,6 +32674,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -32140,6 +33055,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -32149,6 +33070,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -32284,10 +33208,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -32305,7 +33229,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -32314,7 +33238,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -32335,6 +33259,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32347,6 +33274,9 @@ msgstr[5] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32707,9 +33637,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32731,9 +33658,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32758,9 +33682,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32782,6 +33703,9 @@ 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 ""
@@ -32797,15 +33721,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32833,7 +33757,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32974,6 +33898,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32986,6 +33913,9 @@ 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 no permissions"
msgstr ""
@@ -33169,6 +34099,9 @@ 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 ""
@@ -33205,13 +34138,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33367,6 +34300,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33451,6 +34387,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33541,9 +34483,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33862,6 +34810,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33907,8 +34858,14 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -34009,6 +34966,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -34261,6 +35221,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34387,9 +35353,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34459,7 +35422,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34540,6 +35503,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34783,6 +35749,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34921,6 +35890,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 94db870b536..60a76fe0dee 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:00\n"
+"PO-Revision-Date: 2021-02-01 17:56\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 3db3d8b874e..d68d95ba141 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:00\n"
+"PO-Revision-Date: 2021-02-01 17:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d festes Testergebnis"
msgstr[1] "%d feste Testergebnisse"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr "%{authorsName}s Unterhaltung"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr ""
msgid ", or "
msgstr ", oder "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- Ereignis"
msgstr[1] "- Ereignisse"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Prozessor ist aktiv und kann neue Jobs verarbeiten"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner ist angehalten und wird keine neuen Aufgaben entgegennehmen"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "Ein Default-Branch kann nicht für ein leeres Projekt ausgewählt werden
msgid "A deleted user"
msgstr "Ein(e) gelöschte(r) Benutzer(in)"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "In einem Projekt speicherst du deine Dateien (Repository), planst deine Arbeit (Tickets) und veröffentlichst deine Dokumentation (Wiki), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "Ein regulärer Ausdruck, der zum Suchen der Testabdeckung im Joblog verwendet wird. Leer lassen, um dies zu deaktivieren"
-
msgid "A secure token that identifies an external storage request."
msgstr "Ein sicheres Token, das die Anfrage eines externen Speichers identifiziert."
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr "Füge eine Grafana-Schaltfläche in der Administrator-Menüleiste im Üb
msgid "Add a To Do"
msgstr "To-Do hinzufügen"
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
msgstr "Aufzählungsliste hinzufügen"
msgid "Add a comment to this line"
msgstr ""
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Füge einen allgemeinen Kommentar zu %{noteableDisplayName} hinzu."
@@ -1882,6 +1905,9 @@ msgstr "Adminmodus deaktiviert"
msgid "Admin mode enabled"
msgstr "Adminmodus aktiviert"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Admin-Notizen"
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr "Inhaber(in)"
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr "Auto-DevOps-Domain"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "'Shared Runners' für neue Projekte aktivieren"
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Keine Pipeline erforderlich"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Erforderliche Pipeline-Konfiguration"
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Kann gesperrte LDAP-Benutzer(innen) nicht entsperren"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Deakivieren"
@@ -2212,6 +2247,9 @@ msgstr "Benutzer(in) löschen"
msgid "AdminUsers|Delete user and contributions"
msgstr "Benutzer(in) und Beiträge löschen"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Extern"
@@ -2320,6 +2358,9 @@ msgstr "Diese(r) Benutzer(in) kann nicht auf Git-Repositories zugreifen"
msgid "AdminUsers|User will not be able to login"
msgstr "Benutzer(in) wird sich nicht anmelden können"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "Wenn diese(r) Benutzer(in) sich wieder anmeldet, wird das Konto vollständig reaktiviert"
@@ -2748,8 +2789,8 @@ msgstr ""
msgid "Alerts"
msgstr "Alarme"
-msgid "Alerts endpoint"
-msgstr "Alarm-Endpunkt"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -2889,8 +2930,8 @@ msgstr ""
msgid "Allow projects within this group to use Git LFS"
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 "Erlaube den öffentlichen Zugriff auf Pipelines und Jobdetails, einschließlich Ausgabeprotokollen und Artefakten"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Rendering von PlantUML-Diagrammen in Asciidoc-Dokumenten erlauben."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Scheitern erlaubt"
@@ -2991,6 +3035,9 @@ msgstr "Dauer (in Stunden), für die der/die Benutzer(in) die erzwungene Konfigu
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 ""
@@ -3018,6 +3065,9 @@ msgstr "Es ist ein Fehler aufgetreten"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Beim Hinzufügen eines Entwurfs zur Diskussion ist ein Fehler aufgetreten."
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr "Vorfahren"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anonym"
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr "Vorschlag anwenden"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schre
msgid "Archived projects"
msgstr "Archivierte Projekte"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+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?"
@@ -3778,15 +3828,18 @@ 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 registration token?"
-msgstr "Bist du sicher, dass du den Registrierungstoken zurücksetzen willst?"
-
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?"
+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 ""
@@ -3856,8 +3909,8 @@ msgstr ""
msgid "Ascending"
msgstr "Aufsteigend"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "Bitte deine(n) Gruppenbetreuer(in) einen Gruppenrunner einzurichten."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "Assertion-Consumer-Service-URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "Benutzerdefinierte Farbe wie #FF0000 zuweisen"
-msgid "Assign epic"
-msgstr "Epic zuweisen"
-
msgid "Assign labels"
msgstr "Label zuweisen"
@@ -4133,9 +4183,6 @@ msgstr "Autorisierst du %{link_to_client} dein Konto zu verwenden?"
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "%{new_chat_name} autorisiert"
@@ -4160,8 +4207,8 @@ msgstr "Auto-DevOps, Runners und Jobartefakte"
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Lösche redundante, ausstehende Pipelines automatisch"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr "Referenzierte Tickets im Standard-Branch automatisch schließen"
@@ -4259,17 +4306,17 @@ msgstr "Verfügbar"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "Verfügbare Gruppen-Runner: %{runners}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "Verfügbare geteilte Runner:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "Verfügbare spezifische Runner"
@@ -4409,25 +4456,25 @@ msgstr "Vorsicht. Das Umbenennen des Projekt-Repositorys kann unbeabsichtigte Ne
msgid "Begin with the selected commit"
msgstr "Mit dem ausgewählten Commit beginnen"
-msgid "Below are examples of regex for existing tools:"
-msgstr "Im Folgenden findest du Beispiele für Regex für vorhandene Tools:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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 ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Abrechnung"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,11 +4483,17 @@ 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 Gold."
-msgstr "Erfahre mehr über unsere Tarife, indem du unsere %{faq_link} liest, oder beginne einen kostenlosen 30-Tage Test von GitLab.com Gold."
+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 "Erfahre mehr über jeden einzelnen Tarif, indem du unsere %{pricing_page_link} besuchst."
@@ -4460,6 +4513,9 @@ msgstr "Diese Gruppe verwendet den Tarif der übergeordneten Gruppe."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Im Abschnitt Abrechnung von %{parent_billing_page_link} kannst du den Tarif für diese Gruppe verwalten."
+msgid "BillingPlans|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 ""
@@ -4469,6 +4525,9 @@ 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 "Häufig gestellte Fragen (FAQ)"
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Einklappen"
@@ -4792,6 +4857,9 @@ msgstr "Projekteinstellungen"
msgid "Branches|protected"
msgstr "geschützt"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr "Integriert"
msgid "Bulk request concurrency"
msgstr "Parallelität von Massenanfragen"
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ msgstr ""
msgid "By %{user_name}"
msgstr "Von %{user_name}"
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr "Standardmäßig versendet GitLab E-Mails in HTML- und Nur-Text-Formaten,
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 default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "von"
@@ -4936,6 +5019,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD-Konfiguration"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD für externes Repo"
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Canary Deployments sind eine beliebte CI-Strategie, in der zunächst ein kleiner Teil deines Serverparks auf neue Anwendungsversionen aktualisiert werden."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr "Pfad ändern"
msgid "Change permissions"
msgstr "Berechtigungen ändern"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-Pick"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Wiederherstellen "
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Lies die %{docs_link_start}Dokumentation%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Wähle eine Farbe."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Datei auswählen…"
@@ -5599,6 +5694,9 @@ 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 "Wähle welche Repositories du verbinden und die CI/CD-Pipelines ausführen möchtest."
@@ -5758,12 +5856,24 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ist nicht verfügbar: %{reason}"
+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 "Leeren"
@@ -5806,8 +5916,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Klicke auf die Schaltfläche unten um den Installationsprozess zu starten indem du auf die Kubernetes-Seite gehst"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "Zum Erweitern klicken."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr "Kohorten"
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Seitenleiste einklappen"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr "DSGVO"
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "Wenden Sie sich an Sales, um ein Upgrade durchzuführen"
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr "Befehle kopieren"
msgid "Copy commit SHA"
msgstr "Commit-SHA kopieren"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "Konnte Admins nicht als Mitglieder hinzufügen"
@@ -8249,12 +8398,24 @@ msgstr "Erstelle einen persönlichen Zugriffstoken"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Erstellt"
@@ -8423,12 +8593,12 @@ msgstr ""
msgid "Current Branch"
msgstr "Aktueller Branch"
-msgid "Current Plan"
-msgstr ""
-
msgid "Current Project"
msgstr "Aktuelles Projekt"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "Aktueller Knoten"
@@ -8453,7 +8623,7 @@ msgstr "Profil"
msgid "CurrentUser|Settings"
msgstr "Einstellungen"
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,8 +8704,8 @@ msgstr "Sprach- und Region-bezogene Einstellungen anpassen."
msgid "Customize name"
msgstr "Name anpassen"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "Passe deine Pipeline-Konfiguration an und zeige deinen Pipeline-Status und den Abdeckungsbericht an."
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
@@ -8749,7 +8916,7 @@ msgstr "%{firstProject} und %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest} und %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,8 +10227,8 @@ msgstr "Deaktivieren"
msgid "Disable for this project"
msgstr "Für dieses Projekt deaktivieren"
-msgid "Disable group Runners"
-msgstr "Gruppen-Runner deaktivieren"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
@@ -10299,9 +10520,6 @@ msgstr "Während dieses Vorgangs wirst du nach URLs von GitLab gefragt. Verwende
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr "Jeder Runner kann in einem der folgenden Zustände sein:"
-
msgid "Edit"
msgstr "Bearbeiten"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr "zurücksetzen"
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Aktiviere die Pseudonymizer-Datensammlung"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,8 +10877,8 @@ msgstr ""
msgid "Enable for this project"
msgstr "Für dieses Projekt aktivieren"
-msgid "Enable group Runners"
-msgstr "Gruppen-Runner aktivieren"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr ""
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "Endet am (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr "Externe Autorisierung der Klassifikationsrichtlinie"
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr "Schneller als wenn es den Projektarbeitsplatz wieder benützt (fällt zurück auf den Clone wenn es nicht existiert)"
-
msgid "Faster releases. Better code. Less pain."
msgstr "Schnellere Releases. Besserer Code. Weniger Schmerzen."
@@ -12524,10 +12772,22 @@ msgstr "Fußzeilennachricht"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr "Weitere Informationen zum %{deactivating_usage_ping_link_start}Deaktivie
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Bei privaten Projekten kann jedes Mitglied (Gast oder höher) Pipelines ansehen und auf Job-Details zugreifen (Ausgabeprotokolle und Artefakte)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Bei öffentlichen Projekten, kann jeder sich die Pipelines ansehen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,8 +12886,8 @@ msgstr "Von der Ticketbeschreibung bis zur Bereitstellung"
msgid "From merge request merge until deploy to production"
msgstr "Vom Umsetzen des Merge Request bis zur Bereitstellung auf dem Produktivsystem"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "Installiere den Runner aus der Anwendungsliste in der Kubernetes-Cluster Detailansicht"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr ""
@@ -12680,6 +12934,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Geo-Knoten"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,8 +13351,8 @@ msgstr "Git-Revision"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
-msgstr "Git-Strategie für Pipelines"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "GitLab Gruppenrunner können Code für alle Projekte in dieser Gruppe ausführen."
-
msgid "GitLab Import"
msgstr "GitLab-Import"
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "Gruppen-CI/CD-Einstellungen"
-
msgid "Group Git LFS status:"
msgstr "Gruppen-Git-LFS-Status:"
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr "Gruppen Runner"
-
msgid "Group SAML must be enabled to test"
msgstr "Gruppen-SAML muss zum Testen aktiviert sein"
@@ -13622,6 +13873,12 @@ msgstr "Gruppenbetreuer können Gruppen-Runner unter %{link} registrieren"
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr "Gruppenname"
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr "Gruppe benötigt ein separates Konto"
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Häufig besucht"
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr "Bereinigung erfolgreich gestartet"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr "Identitäten"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr "Wenn diese Option deaktiviert ist, wird ein abweichender lokaler Branch
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "Wenn deaktiviert, hängt der Zugriffslevel von den Berechtigungen des/der Benutzers/Benutzerin im Projekts ab."
-
-msgid "If enabled"
-msgstr "When aktiv"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
msgstr "In Bearbeitung"
+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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,8 +15617,8 @@ msgstr "Inline"
msgid "Input host keys manually"
msgstr "Gib die Host-Schlüssel manuell ein"
-msgid "Input your repository URL"
-msgstr "Gib deine Repository-URL ein"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr ""
@@ -15018,11 +15659,11 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
-msgstr "Installiere einen GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Installiere einen Runner auf Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
@@ -15047,9 +15688,21 @@ msgstr[1] "Instanzen"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr "Tickets können Bugs, Tasks oder zu diskutierende Ideen sein. Tickets si
msgid "Issues closed"
msgstr "Geschlossene Tickets"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ msgstr ""
msgid "Issue|Title"
msgstr "Titel"
+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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ msgstr ""
msgid "Jobs"
msgstr "Jobs"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,8 +16738,8 @@ msgstr "Jobartefakte"
msgid "Job|Job has been erased"
msgstr "Job wurde gelöscht"
-msgid "Job|Job has been erased by"
-msgstr "Job wurde gelöscht von"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "Behalten"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr "Letzter Kontakt"
msgid "Last edited %{date}"
msgstr "Zuletzt bearbeitet %{date}"
-msgid "Last edited by %{name}"
-msgstr "Zuletzt bearbeitet von %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr "Erfahre mehr über Kubernetes"
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] "Anzeige beschränkt auf maximal %d Ereignisse"
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr "Prometheus-Monitoring mit GitLab verknüpfen."
@@ -16884,9 +17612,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ msgstr "Genehmigungsberechtigte"
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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr "Verwaltetes Konto"
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr "Maximale Job-Zeitüberschreitung"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr "Mai"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Mitglieder"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr "Merge-Request-Genehmigungen ermöglichen dir, die Zahl der notwendigen G
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr "Beim Hinzufügen des Kommentarentwurfs ist ein Fehler aufgetreten."
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr "Keine Dateien gefunden"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Merged"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr "Migration erfolgreich."
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr "Richtung der Spiegelung"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "Repository spiegeln"
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Abbrechen"
-
msgid "Modal|Close"
msgstr "Schließen"
@@ -18451,9 +19179,6 @@ msgstr "Name"
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "Neues Label benennen"
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,8 +19641,8 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "Neue Pipelines brechen ältere, ausstehende Pipelines in dem selben Branch ab"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Neues Projekt"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Es konnte keine Verbindung zu einem Gitaly-Server hergestellt werden. Bitte überprüfe deine Protokolle!"
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr "Nur geschützte Branches spiegeln"
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Optionen"
msgid "Or you can choose one of the suggested colors below"
msgstr "Oder du wählst eine der unten vorgeschlagenen Farben"
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Andere Labels"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "Andere Informationen"
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr "Bestanden"
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr "Frontend-Ressourcen"
@@ -20529,6 +21284,9 @@ msgstr "Zeitplan der Pipeline"
msgid "Pipeline Schedules"
msgstr "Zeitpläne der Pipeline"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 "Pipeline-Trigger"
@@ -20709,9 +21470,6 @@ msgstr "Pipelines laden"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "Der Projekt-Cache wurde erfolgreich zurückgesetzt."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Derzeit gibt es keine Pipelines."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Beim Abrufen der Pipelines ist ein Fehler aufgetreten. Versuche es in einigen Augenblicken noch einmal oder wende dich an dein Support-Team."
@@ -20862,6 +21620,9 @@ msgstr "Pipeline ausführen"
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr "Pfad"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Lege Position und Größe deines neuen Avatars fest"
@@ -21867,6 +22628,9 @@ msgstr "Projektname"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr "Für Bereitstellung zugelassen"
msgid "ProtectedEnvironment|Environment"
msgstr "Umgebung"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Schützen"
@@ -22875,9 +23651,6 @@ msgstr "Schütze eine Umgebung"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Geschützte Umgebung (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "Wähle eine Umgebung"
@@ -22887,8 +23660,8 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "Es gibt derzeit keine geschützten Umgebungen, schütze eine Umgebung mit dem Formular oben."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "Schutz aufheben"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr "Echtzeit-Features"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Zugehörige Bereitstellungsjobs"
-
msgid "Related Issues"
msgstr "Zugehörige Tickets"
-msgid "Related Jobs"
-msgstr "Zugehörige Jobs"
-
-msgid "Related Merge Requests"
-msgstr "Zugehörige Merge-Requests"
-
-msgid "Related Merged Requests"
-msgstr "Zugehörige umgesetzte Merge-Requests"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr "Entfernen"
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr "Runner entfernen"
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Sekundärknoten entfernen"
@@ -23705,6 +24478,11 @@ msgstr ""
msgid "Reports|Execution time"
msgstr "Ausführungszeit"
+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] ""
@@ -23872,6 +24650,9 @@ msgstr "Repository-Speicher"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,8 +24786,8 @@ msgstr "Zugriffstoken für den Health-Check zurücksetzen"
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
-msgstr "Registrierungstoken für Runner zurücksetzen"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr ""
@@ -24128,6 +24909,9 @@ msgstr "Wiederholen"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Wiederhole diese Aufgabe"
@@ -24175,6 +24959,9 @@ 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 "Überprüfe den Prozess zum Konfigurieren von Dienstanbietern bei deinem Identitätsanbieter. In diesem Fall ist GitLab der \"Dienstanbieter\" oder die \"vertrauende Seite\"."
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Unmarkierte Jobs ausführen"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr "Runner wurde erfolreich aktualisiert."
msgid "Runners"
msgstr "Runners"
-msgid "Runners API"
-msgstr "Runners-API"
-
-msgid "Runners activated for this project"
-msgstr "Für dieses Projekt aktivierte Runner"
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Runner können durch separate Benutzer, auf Servern und sogar auf deinem lokalen Rechner ausgeführt werden."
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr "Runners-Seite."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr "Öffentlicher SSH-Schlüssel"
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr "Secret"
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Sicherheit"
@@ -24796,6 +25613,9 @@ msgstr "Sicherheits-Dashboard"
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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,8 +26011,8 @@ msgstr "Zeitzone auswählen"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Wähle eine existierendes Kubernetes-Cluster aus oder erstelle ein neues"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr ""
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Zielbranch auswählen"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Wähle den Branch aus, den du als Standard für dieses Projekt festlegen möchtest. Alle Merge-Requests und Commits werden automatisch für diesen Branch ausgeführt, es sei denn, du gibst einen anderen an."
-
msgid "Select the custom project template source group."
msgstr "Wähle die Quellgruppe der benutzerdefinierten Projektvorlage aus."
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,11 +26425,11 @@ msgstr "CI/CD einrichten"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "Einen %{type} Runner manuell erstellen"
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr "Verwendete Pipeline-Minuten zurücksetzen"
msgid "Sherlock Transactions"
msgstr "Sherlock-Transaktionen"
-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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Neuste Version zeigen"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Langsamer, aber stellt sicher, dass der Projektarbeitsbereich unberührt ist, da das Repository für jeden Job neu geklont wird"
-
msgid "Smartcard"
msgstr "Smartcard"
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr "Etwas ist beim Laden der Liste %{listType} fehlgeschlagen"
@@ -26581,8 +27395,8 @@ msgstr "Spam- und Anti-Bot-Schutz"
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
-msgstr "Spezifische Runner"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr ""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "Gib ein Regex-Muster für E-Mail-Adressen an, um interne Standardbenutzer(innen) zu identifizieren."
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Gib die folgende URL während des Runner-Setups an:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr "Vormerken"
-msgid "Stage & Commit"
-msgstr "Vormerken & Committen"
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Beginne einen %{new_merge_request} mit diesen Änderungen"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr "Suche starten"
-msgid "Start the Runner!"
-msgstr "Starte den Runner!"
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Beginnt am (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Gib deine Nachricht an, um sie zu aktivieren"
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Systemmetriken (benutzerdefiniert)"
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "Die Beziehung des Forks wurde entfernt."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "Die Ticketphase stellt die Zeit vom Anlegen eines Tickets bis zum Zuweis
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ 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 path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "Die Phase des Entwicklungslebenszyklus."
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Die Pseudonymizer-Datensammlung ist deaktiviert. Wenn sie aktiv ist, führt GitLab einen Hintergrundjob aus, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
+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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Die Review-Phase stellt die Zeit vom Anlegen eines Merge-Requests bis zu dessen Merge dar. Sobald du deinen ersten Merge-Request abschließt, werden diese Daten hier automatisch angezeigt."
-msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr "Die Roadmap zeigt den Fortschritt deiner Epics anhand einer Zeitleiste an"
-
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 ""
@@ -28172,7 +29001,7 @@ 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 "Die Benutzerzuordnung legt fest, wie die E-Mail-Adressen und Benutzernamen der FogBuz-Benutzer(innen), die an deinem Projekt teilnehmen, in GitLab importiert werden. Du kannst dies ändern, indem du die Tabelle unten ausfüllst."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,17 +29328,26 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
-msgstr "Können unter %{link} verwaltet werden."
+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 "Third Party Advisory Link"
msgstr ""
@@ -28532,8 +29376,8 @@ 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 "Diese GitLab-Instanz stellt noch keine geteilten Runner bereit. Instanz-Administrator(inn)en können geteilte Runner im Admin-Bereich registrieren."
+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 ""
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr "Diese Anwendung wurde erstellt von %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Diese Anwendung wird in der Lage sein:"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,14 +29532,17 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Diese Gruppe"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "Diese Gruppe stellt noch keine Gruppenrunner zur Verfügung."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -28712,6 +29571,9 @@ msgstr "Dies ist ein in %{remainingTime} auszuführender verzögerter Job"
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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Dies bedeutet, dass du keinen Code pushen kannst, bevor du kein leeres Repository erstellt oder ein existierendes importiert hast."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 "Dieser Merge-Request ist gesperrt."
@@ -28880,8 +29754,8 @@ msgstr ""
msgid "This project"
msgstr "Dieses Projekt"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "Dieses Projekt gehört keiner Gruppe an und kann daher keine Gruppenrunner verwenden."
+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 ""
@@ -28937,6 +29811,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Dieser Runner wird nur Pipelines von geschützen Branches ausführen"
+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 "Diese Einstellung kann in jedem Projekt überschrieben werden."
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "Diese(r) Benutzer(in) wird der/die Autor(in) aller Ereignisse im Aktivitätsfeed sein, die die Folge eines Updates, wie die Erstellung neuer Branches oder das Pushen neuer Commits zu existierenden Branches, sind."
-
msgid "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ msgstr "Um einen SSH-Schlüssel hinzuzufügen, musst du %{generate_link_start}ei
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 ""
@@ -29406,6 +30280,9 @@ msgstr "Um ein SVN-Repository zu verbinden, lies %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Um interne Benutzer(innen) zu definieren, musst du zunächst externe Benutzer(innen) aktivieren"
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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 "Gib zunächst deine FogBuz-URL und Anmeldeinformationen unten ein. In den nächsten Schritten kannst du Benutzer(innen) zuordnen und die Projekte für den Import auswählen."
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr "Um deine Jobs zur Verfügung zu stellen, kannst du Runner zu deiner Gruppe hinzufügen"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Monatsansicht werden nur Epics des letzten Monats, des aktuellen Monats und der nächsten 5 Monate angezeigt."
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr "Heute"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Navigation umschalten"
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,8 +30687,8 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr "Pipelines für Mirror-Updates auslösen"
-msgid "Trigger pipelines when branches or tags are updated from 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 "Triggere Pipelines, wenn Branches oder Tags aus dem Upstream-Repository aktualisiert werden. Abhängig von der Aktivität des Upstream-Repositorys kann dies die Auslastung deiner CI-Runner erheblich erhöhen. Aktiviere diese Option nur, wenn du weißt, dass sie mit der Last umgehen können."
+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 ""
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr "Dieses Ticket kann gerade nicht aktualisiert werden."
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr "Aktualisiere"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Nutze den Service-Desk, um dich direkt in GitLab via E-Mail mit deinen Benutzer(inne)n zu verbinden (z. B. um Kunden-Support anzubieten)"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr "Verwende benutzerdefinierte Farbe #FF0000"
@@ -30539,8 +31440,11 @@ msgstr "Verwende eine Zeile pro URI"
msgid "Use template"
msgstr "Template verwenden"
-msgid "Use the following registration token during setup:"
-msgstr "Benutze den folgenden Registrierungstoken während des Setups:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "Benutze deine globalen Benachrichtigungseinstellungen"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr "Benutzer(innen)"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 "Verschiedene Einstellungen für die Container-Registry."
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr "Wenn diese Option aktiviert ist, können Benutzer(innen) GitLab nicht ve
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 merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "Du kannst stattdessen %{linkStart}den Blob anzeigen%{linkEnd}."
-
msgid "You can also create a project from the command line."
msgstr "Du kannst ein Projekt auch über die Kommandozeile erstellen."
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Du kannst einfach dazu beitragen, indem du um Aufnahme in diesen Gruppen bittest."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Du kannst ganz einfach einen Runner auf einem Kubernetes-Cluster installieren. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "Du kannst Dateien nur bearbeiten, wenn du dich auf einem Branch befindest"
@@ -32153,7 +33069,7 @@ msgstr "Du kannst den Merge-Konflikt lösen, indem du entweder den interaktiven
msgid "You can see your chat accounts."
msgstr "Sie können Ihre Chat-Konten sehen."
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr "Du hast keine Berechtigungen"
@@ -32489,6 +33411,9 @@ msgstr "YouTube"
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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 "ein(e) gelöschte(r) Benutzer(in)"
@@ -32857,9 +33791,15 @@ msgstr "Branch-Name"
msgid "by"
msgstr "von"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "Tag"
msgstr[1] "Tage"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr "Gruppe"
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr "Gruppen"
@@ -33549,6 +34497,12 @@ msgstr "Bitte stelle es wieder her, oder verwende einen anderen Branch %{missing
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr "%{link_start}Lerne mehr über das Lösen von Konflikten%{link_end}"
+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 "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} %{emphasisStart} gesunken %{emphasisEnd} von %{memoryFrom} MB auf %{memoryTo} MB"
@@ -33675,9 +34629,6 @@ msgstr "Merge"
msgid "mrWidget|Merge failed."
msgstr "Merge fehlgeschlagen."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr "Merge fehlgeschlagen: %{mergeError}. Bitte versuche es erneut."
-
msgid "mrWidget|Merge locally"
msgstr "Lokal mergen"
@@ -33747,8 +34698,8 @@ msgstr "Die Änderungen wurden nicht gemerged nach"
msgid "mrWidget|The changes will be merged into"
msgstr "Die Änderungen werden gemerged nach"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr "Die Pipeline für diesen Merge-Request ist fehlgeschlagen. Bitte wiederhole den Job oder pushe einen neuen Commit, um den Fehler zu beheben"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "Der HEAD des Quellbranches wurde kürzlich geändert. Bitte lade die Seite neu und überprüfe die Änderungen vor dem Mergen"
@@ -33828,6 +34779,9 @@ msgstr "wird automatisch zusammengeführt, wenn die Pipeline erfolgreich ist"
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr "Zurücksetzen."
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "ausgelöst"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 78533691c22..a5e37cb573b 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 256bd9f8292..796f0b406d1 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:57\n"
+"PO-Revision-Date: 2021-02-01 17:08\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "de"
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Precize elekti"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Malfari"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr "kreos propran atingoĵetonon"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Redakti"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr "De la kreado de la problemo Äis la disponigado en la publika versio"
msgid "From merge request merge until deploy to production"
msgstr "De la kunfandado de la peto pri kunfando Äis la disponigado en la publika versio"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr "La refreÅigo komenciÄis sukcese"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Opcioj"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr "Ĉenstabla plano"
msgid "Pipeline Schedules"
msgstr "Ĉenstablaj planoj"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Rilataj disponigitaj taskoj"
-
msgid "Related Issues"
msgstr "Rilataj problemoj"
-msgid "Related Jobs"
-msgstr "Rilataj taskoj"
-
-msgid "Related Merge Requests"
-msgstr "Rilataj petoj pri kunfando"
-
-msgid "Related Merged Requests"
-msgstr "Rilataj aplikitaj petoj pri kunfando"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr "Elektu horzonon"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Elektu celan branĉon"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Kreu %{new_merge_request} kun ĉi tiuj ÅanÄoj"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "La rilato de disbranĉigo estis forigita."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "La etapo de la problemo montras kiom la tempo pasas de la kreado de prob
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "La etapo de la disvolva ciklo."
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "La etapo de la kontrolo montras la tempon de la kreado de la peto pri kunfando Äis Äia aplikado. La datenoj aldoniÄos aÅ­tomate post kiam vi aplikos la unuan peton pri kunfando."
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Ĉi tiu signifas, ke vi ne povos alpuÅi kodon, antaÅ­ ol vi kreos malplenan deponejon aÅ­ enportos jam ekzistantan."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "tago"
msgstr[1] "tagoj"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 49a76901b83..f653d1e8a31 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d solucionado el resultado de la prueba"
msgstr[1] "%d solucionados los resultados de la prueba"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d grupo seleccionado"
@@ -374,10 +379,10 @@ msgstr "Hilo de %{authorsName}"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar noti
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 "%{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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr "+%{tags} más"
msgid ", or "
msgstr ", o "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- Evento"
msgstr[1] "- Eventos"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- El ejecutor está activo y puede procesar cualquier trabajo nuevo"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- El ejecutor está en pausa y no recibirá ningún trabajo nuevo"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "No se puede elegir una rama por defecto para un proyecto vacío."
msgid "A deleted user"
msgstr "Un usuario eliminado"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Se ha modificado un archivo."
@@ -1265,6 +1279,12 @@ msgstr "Un grupo es una colección de varios proyectos"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
msgstr "Un grupo representa a su organización en GitLab. Los grupos que le permiten administrar usuarios y colaborar a través de múltiples proyectos."
+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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Un proyecto es donde sus archivos (repositorio), planifica su trabajo (incidencias), y publica su documentación (wiki), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "Una expresión regular que se utilizará para rastrear la cantidad de cobertura de código en el log del trabajo. Déjelo en blanco para deshabilitar esta opción"
-
msgid "A secure token that identifies an external storage request."
msgstr "Un token seguro que identifica una petición de almacenamiento externo."
@@ -1337,7 +1357,7 @@ msgstr "Se ha realizado un inicio de sesión en su cuenta desde la siguiente dir
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "Ayuda de la API"
@@ -1615,15 +1638,15 @@ msgstr "Agrega un botón de Grafana en la sección de monitorización que se enc
msgid "Add a To Do"
msgstr "Añadir a tareas pendientes"
-msgid "Add a To-Do"
-msgstr "Añadir a tareas pendientes"
-
msgid "Add a bullet list"
msgstr "Añadir una lista de viñetas"
msgid "Add a comment to this line"
msgstr "Añadir un comentario a esta línea"
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Añadir un comentario general a este %{noteableDisplayName}."
@@ -1882,6 +1905,9 @@ msgstr "Modo Administrador deshabilitado"
msgid "Admin mode enabled"
msgstr "Modo administrador habilitado"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Notas del administrador"
@@ -1912,9 +1938,6 @@ msgstr "Desarrollador"
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr "Invitado"
@@ -1948,8 +1971,8 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr "Propietario"
-msgid "AdminArea|Projects: %{number_of_projects}"
-msgstr "AdminArea|Proyectos: %{number_of_projects}"
+msgid "AdminArea|Projects"
+msgstr ""
msgid "AdminArea|Reporter"
msgstr "Reportador"
@@ -1972,6 +1995,9 @@ msgstr "Usuarios totales"
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "Estadísticas de usuarios"
@@ -1981,8 +2007,14 @@ msgstr "Usuarios con el rol más alto"
msgid "AdminArea|Users without a Group and Project"
msgstr "Usuarios sin grupo y proyecto"
-msgid "AdminArea|Users: %{number_of_users}"
-msgstr "AdminArea|Usuarios: %{number_of_users}"
+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 "Está a punto de detener todos los trabajos. Esto detendrá todos los trabajos que se están ejecutando actualmente."
@@ -2011,9 +2043,6 @@ msgstr "Dominio Auto DevOps"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Habilitar ejecutores compartidos para los nuevos proyectos"
@@ -2035,6 +2064,9 @@ msgstr "Movido a integraciones"
msgid "AdminSettings|No required pipeline"
msgstr "No se requiere un pipeline"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Configuración del pipeline requerida"
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "No se pueden desbloquear los usuarios bloqueados de LDAP"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Desactivar"
@@ -2212,6 +2247,9 @@ msgstr "Eliminar usuario"
msgid "AdminUsers|Delete user and contributions"
msgstr "Eliminar el usuario y sus colaboraciones"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Externos"
@@ -2320,6 +2358,9 @@ msgstr "El usuario no podrá acceder a los repositorios git"
msgid "AdminUsers|User will not be able to login"
msgstr "El usuario no podrá iniciar sesión"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "Cuando el usuario vuelve a iniciar sesión, su cuenta se activará como una cuenta totalmente activa"
@@ -2748,8 +2789,8 @@ msgstr ""
msgid "Alerts"
msgstr "Alertas"
-msgid "Alerts endpoint"
-msgstr "Endpoint de alertas"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -2889,8 +2930,8 @@ msgstr "Permitir que los proyectos y subgrupos sobreescriban la configuración d
msgid "Allow projects within this group to use Git LFS"
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 "Permitir acceso público a los pipelines y a los detalles del trabajo, incluidos los logs de salida y los artefactos"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Permitir el renderizado de diagramas PlantUML en documentos Asciidoc."
@@ -2940,6 +2981,9 @@ msgstr "Dominios permitidos para suscripciones"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Sólo los grupos de nivel superior pueden restringir los dominios de correo electrónico permitidos"
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Permitido fallar"
@@ -2991,6 +3035,9 @@ msgstr "Cantidad de tiempo (en horas) que los usuarios pueden omitir la configur
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 ""
@@ -3018,6 +3065,9 @@ msgstr "Se ha producido un error"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+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."
@@ -3234,6 +3284,9 @@ msgstr "Se ha producido un error al cargar el archivo."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Se ha producido un error al cargar el archivo. Por favor, inténtelo más tarde."
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "Se ha producido un error al cargar los cambios del merge request."
@@ -3405,6 +3458,9 @@ msgstr "Analiza el código fuente en busca de vulnerabilidades conocidas."
msgid "Ancestors"
msgstr "Antepasados"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anónimo"
@@ -3519,12 +3575,6 @@ msgstr "Aplicar cambios"
msgid "Apply suggestion"
msgstr "Aplicar sugerencia"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr "Aplicar sugerencias"
@@ -3689,8 +3739,8 @@ msgstr "¡Proyecto archivado!. El repositorio y el resto de recursos del proyect
msgid "Archived projects"
msgstr "Proyectos archivados"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
-msgstr "Al archivar el proyecto se convertirá por completo en un proyecto de sólo lectura. Estárá oculto en el panel de control y no aparecerá en las búsquedas. %{strong_start}No se puede hacer commit al repositorio y tampoco se pueden crear incidencias, comentarios u otras entidades.%{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
@@ -3778,15 +3828,18 @@ msgstr "¿Está seguro de que desea eliminar esta identidad?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-msgstr "¿Está seguro que desea reinicializar el token de registro?"
-
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?"
+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 "¿Está seguro de que desea revocar este token %{type}? Esta acción no se puede deshacer."
@@ -3856,8 +3909,8 @@ msgstr "El token de acceso personal del usuario. El usuario debe tener acceso a
msgid "Ascending"
msgstr "Ascendente"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "Pídale al administrador de su grupo que configure un grupo de ejecutores."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL del servicio de aserción del consumidor"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "Asigne colores personalizados como #FF0000"
-msgid "Assign epic"
-msgstr "Asignar tarea épica"
-
msgid "Assign labels"
msgstr "Asignar etiquetas"
@@ -4133,9 +4183,6 @@ msgstr "¿Autorizar %{link_to_client} para utilizar su cuenta?"
msgid "Authorize %{user} to use your account?"
msgstr "¿Autorizar a %{user} para utilizar su cuenta?"
-msgid "Authorize external services to send alerts to GitLab"
-msgstr "Autorizar a servicios externos enviar alertas a GitLab"
-
msgid "Authorized %{new_chat_name}"
msgstr "Autorizado %{new_chat_name}"
@@ -4160,8 +4207,8 @@ msgstr "Auto DevOps, ejecutores y artefactos"
msgid "Auto stop successfully canceled."
msgstr "Parada automática cancelada con éxito."
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Cancelación redundante automática, pipelines pendientes"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4259,17 +4306,17 @@ msgstr "Disponible"
msgid "Available ID"
msgstr "ID disponible"
-msgid "Available Runners: %{runners}"
-msgstr "Ejecutores disponibles: %{runners}"
-
msgid "Available for dependency and container scanning"
msgstr "Disponible para análisis de dependencias y contenedores"
-msgid "Available group Runners: %{runners}"
-msgstr "Grupo de ejecutores disponible: %{runners}"
+msgid "Available group runners: %{runners}"
+msgstr ""
+
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "Ejecutores compartidos disponibles:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "Ejecutores dedicados disponibles"
@@ -4409,26 +4456,26 @@ msgstr "Tenga cuidado. Cambiar el nombre del repositorio de un proyecto puede te
msgid "Begin with the selected commit"
msgstr "Iniciar con el commit seleccionado"
-msgid "Below are examples of regex for existing tools:"
-msgstr "A continuación se muestran ejemplos de expresiones regulares para las herramientas existentes:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "A continuación se muestran las huellas de las claves SSH de la instancia actual."
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"
-msgid "Billable Users:"
-msgstr "Usuarios facturables:"
+msgid "Billable Users"
+msgstr ""
msgid "Billing"
msgstr "Facturación"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "actualmente %{group_name} está en el plan %{plan_name}."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "actualmente, @%{user_name} está utilizando el plan %{plan_name}."
@@ -4436,11 +4483,17 @@ msgstr "actualmente, @%{user_name} está utilizando el plan %{plan_name}."
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Enhorabuena, su plan de prueba está activado."
+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 "Si deseas cambiar su plan, por favor, póngase en contacto con %{support_link_start}Atención al cliente%{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 Gold."
-msgstr "Obtenga más información sobre cada plan leyendo nuestro %{faq_link}, o pruebe una versión gratuita de 30 días de Gitlab.com Gold."
+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 "Obtenga más información sobre cada plan visitando nuestro %{pricing_page_link}."
@@ -4460,6 +4513,9 @@ msgstr "Este grupo utiliza el mismo plan asociado que su grupo principal."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Para administrar el plan de este grupo, por favor visite la sección de facturación de %{parent_billing_page_link}."
+msgid "BillingPlans|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 ""
@@ -4469,6 +4525,9 @@ msgstr "Su periodo de prueba de GitLab.com Gold caducó en %{expiration_date}. P
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "%{price_per_year} pagados anualmente"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "preguntas frecuentes"
@@ -4484,6 +4543,9 @@ msgstr "Contactar con ventas"
msgid "BillingPlan|Upgrade"
msgstr "Actualizar"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Contraer"
@@ -4792,6 +4857,9 @@ msgstr "configuración del proyecto"
msgid "Branches|protected"
msgstr "protegido"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr "Integrado"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ msgstr "Compre más minutos de pipelines"
msgid "By %{user_name}"
msgstr "Por %{user_name}"
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr "De forma predeterminada, GitLab envía correos electrónicos en formatos
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 default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
@@ -4936,6 +5019,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "Configuración de CI/CD"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD para repositorio externo"
@@ -5044,9 +5130,6 @@ msgstr "No se puede actualizar el fragmento de código: %{err}"
msgid "Canary"
msgstr "Canary"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Canary Deployment es una estrategia de CI, donde solo una pequeña porción se actualiza a la nueva versión de tu aplicación."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr "Cambiar la ruta"
msgid "Change permissions"
msgstr "Modificar los permisos"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr "Cambiar estado"
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Revertir"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "Asignado(s) cambiado(s)."
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr "Título cambiado a \"%{title_param}\"."
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Compruebe la documentación %{docs_link_start}%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr "Compruebe sus imágenes de Docker para detectar vulnerabilidades conocidas."
@@ -5578,9 +5676,6 @@ msgstr "Elegir cualquier color."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Seleccione un archivo…"
@@ -5599,6 +5694,9 @@ msgstr "Escoja el nivel de visibilidad, habilite/deshabilite las característica
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 "Elija que repositorios quiere conectar y ejecutar los CI/CD pipelines."
@@ -5758,12 +5856,24 @@ msgstr "Etiqueta de clasificación (opcional)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "no está disponible: %{reason}"
+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 "Limpiar"
@@ -5806,8 +5916,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Haga clic en el botón que se muestra a continuación para comenzar con el proceso de instalación navegando hasta la página de Kubernetes"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "Haga clic para expandir."
@@ -6985,7 +7095,7 @@ msgstr "Revisión de código"
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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Patrón"
-msgid "Cohorts"
-msgstr "Cohortes"
-
msgid "Cohorts|Inactive users"
msgstr "Usuarios inactivos"
@@ -7042,6 +7149,9 @@ msgstr "Colapsar respuestas"
msgid "Collapse sidebar"
msgstr "Contraer la barra lateral"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr "Nombre del recolector"
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "Póngase en contacto con ventas para actualizar"
-
msgid "Contact support"
msgstr "Contactar con soporte"
@@ -7549,9 +7662,15 @@ msgstr "Copiar el comando de inicio de sesión"
msgid "ContainerRegistry|Copy push command"
msgstr "Copiar el comando push"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr "Eliminar seleccionados"
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr "Si no ha iniciado sesión, necesita autenticarse en el registro de conte
msgid "ContainerRegistry|Image Repositories"
msgstr "Repositorios de imágenes"
+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 tags"
msgstr "Etiquetas de la imagen"
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 "La última etiqueta relacionada con esta imagen fue eliminada recientemente. Esta imagen vacía y cualquier dato asociado se eliminarán automáticamente como parte del proceso llamado \"Garbage Collection\". Si tienes alguna pregunta, póngase en contacto con su administrador."
+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 ""
@@ -7716,9 +7853,15 @@ msgstr ""
msgid "ContainerRegistry|This image has no active tags"
msgstr "Esta imagen no tiene etiquetas activas"
+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 ""
@@ -7896,6 +8039,9 @@ msgstr "Copiar los comandos"
msgid "Copy commit SHA"
msgstr "Copiar el SHA del commit"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr "Copiar entorno"
@@ -7950,6 +8096,9 @@ msgstr "Copiar token de activación"
msgid "Copy value"
msgstr "Copiar valor"
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "No se puede agregar administradores como miembros"
@@ -8249,12 +8398,24 @@ msgstr "crear un token de acceso personal"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Creado"
@@ -8423,12 +8593,12 @@ msgstr ""
msgid "Current Branch"
msgstr "Rama actual"
-msgid "Current Plan"
-msgstr "Plan actual"
-
msgid "Current Project"
msgstr "Proyecto actual"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "Nodo actual"
@@ -8453,8 +8623,8 @@ msgstr "Perfil"
msgid "CurrentUser|Settings"
msgstr "Configuración"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "Inicie periodo de prueba Gold"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr "Actualizar"
@@ -8462,9 +8632,6 @@ msgstr "Actualizar"
msgid "Custom Attributes"
msgstr "Atributos personalizados"
-msgid "Custom CI configuration path"
-msgstr "Ruta de configuración CI personalizada"
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr "URL de clon de Git personalizado para HTTP(S)"
@@ -8537,8 +8704,8 @@ msgstr "Personalice los ajustes relacionados con el idioma y la región."
msgid "Customize name"
msgstr "Personalizar nombre"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "Personalice la configuración de su pipeline, vea el estado de su pipeline y el informe de cobertura."
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr "Personalice la configuración de su pipeline."
@@ -8749,8 +8916,8 @@ msgstr "%{firstProject} y %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest}, y %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
-msgstr "No se puede agregar %{invalidProjects}. Este panel de control está disponible tanto para proyectos públicos como para proyectos privados en grupos incluidos en el plan Gitlab.com Silver."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
+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 ""
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ msgstr "Eliminando"
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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr "Desplegar en AWS es fácil con GitLab"
msgid "Deployment Frequency"
msgstr "Frecuencia de despliegue"
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -9778,7 +10008,7 @@ msgstr "El número máximo de diseños permitidos que se pueden cargar es %{uplo
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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,8 +10227,8 @@ msgstr "Deshabilitar"
msgid "Disable for this project"
msgstr "Deshabilitar para este proyecto"
-msgid "Disable group Runners"
-msgstr "Desactivar el grupo de ejecutores"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr "Deshabilitar el acceso público a los sitios de Pages"
@@ -10299,9 +10520,6 @@ msgstr "Durante este proceso, le solicitaremos las URLs de parte de Gitlab.Por f
msgid "Dynamic Application Security Testing (DAST)"
msgstr "Prueba de seguridad de aplicaciones dinámica (DAST)"
-msgid "Each Runner can be in one of the following states:"
-msgstr "Cada ejecutor puede estar en uno de los siguientes estados:"
-
msgid "Edit"
msgstr "Editar"
@@ -10530,6 +10748,15 @@ msgstr "No se le permite realizar esta acción. Si cree que esto se debe a un er
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
msgstr "Su cuenta ha sido bloqueada. Si cree que esto se debe a un error, por favor, póngase en contacto con un miembro del personal."
+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 "EmailToken|reset it"
msgstr "reiniciarlo"
@@ -10596,6 +10823,9 @@ msgstr "Habilitar correos HTML"
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr "Habilitar PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr "Habilitar la recolección de datos Pseudonymizer"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,8 +10877,8 @@ msgstr "Habilitar función para elegir el nivel de acceso"
msgid "Enable for this project"
msgstr "Habilitar para este proyecto"
-msgid "Enable group Runners"
-msgstr "Habilitar el grupo de ejecutores"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr "Habilitar el encabezado y pie de página en los correos electrónicos"
@@ -10683,8 +10916,8 @@ msgstr ""
msgid "Enable proxy"
msgstr "Habilitar el proxy"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgstr "Habilite reCAPTCHA o Akismet y establezca límites por IP. Para reCAPTCHA, actualmente sólo soportamos %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
msgid "Enable shared runners"
msgstr ""
@@ -10746,15 +10979,21 @@ msgstr "Se ha producido un error al renderizar: %{err}"
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "Finaliza a las (UTC)"
+msgid "Ends on"
+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 ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
msgstr ""
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "Las variables de entorno están configuradas por el administrador para estar %{link_start}protegidas%{link_end} por defecto"
-
-msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ msgstr "Se ha producido un error al actualizar las etiquetas."
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "¿Está seguro de que desea eliminar %{bStart}%{targetIssueTitle}%{bEnd} de %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11163,6 +11402,12 @@ msgstr "Eliminar tarea épica"
msgid "Epics|Remove issue"
msgstr "Eliminar la incidencia"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "Mostrar más"
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "Ejemplo: @sub\\.empresa\\.com$"
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr "Ejemplo: Uso = consulta simple. (Solicitado)/(Capacidad) = Varias consultas combinadas en una sola fórmula."
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr "Exportar proyecto"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "Exporte este proyecto con todos los datos relacionados para mover su proyecto a una nueva instancia de GitLab. Una vez que finalice la exportación, puede importar el archivo desde la página \"Nuevo proyecto\"."
+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 Classification Policy Authorization"
msgstr "Política de autorización de clasificación externa"
@@ -11823,6 +12071,9 @@ msgstr "Error al encolar la operación de rebase, posiblemente debido a una tran
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr "Se ha producido un error al obtener ref."
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr "Fast-forward merge sin hacer merge commit"
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr "Lanzamientos más rápidos. Mejor código. Menos dolor."
@@ -12524,10 +12772,22 @@ msgstr "Mensaje a pie de página"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr "Para obtener más información, consulte la documentación en %{deactiva
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para los proyectos privados, cualquier miembro (visitante o administrador) puede visualizar los pipelines y acceder los detalles de los trabajos (registros de salida and artefactos)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para los proyectos públicos, cualquiera puede visualizar los pipelines y acceder los detalles de los trabajos (registros de salida and artefactos)"
-
msgid "Forgot your password?"
msgstr "¿Olvidó su contraseña?"
@@ -12632,8 +12886,8 @@ msgstr "Desde la creación de la incidencia hasta el despliegue a producción"
msgid "From merge request merge until deploy to production"
msgstr "Desde la integración de la solicitud de fusión hasta el despliegue a producción"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "Desde la vista de detalles del clúster de Kubernetes, seleccione instalar 'runner' desde la lista de aplicaciones"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr "Nombre completo"
@@ -12680,6 +12934,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Geo Nodos"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,8 +13351,8 @@ msgstr "Revisión de Git"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
-msgstr "Estrategia de Git para los 'pipelines'"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "El grupo de ejecutores de GitLab puede ejecutar código para todos los proyectos en este grupo."
-
msgid "GitLab Import"
msgstr "Importar desde GitLab"
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab para Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "Pueden pasar hasta 30 minutos antes de que el sitio esté disponible después del primer despliegue."
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr "Aprenda a subir tu sitio web estático y haga que GitLab lo sirva siguiendo la documentación %{link_start}de GitLab%{link_end}."
-
msgid "GitLabPages|Learn more."
msgstr "Más información."
@@ -13277,6 +13531,9 @@ msgstr "Al eliminar páginas evitará que estén expuestas al mundo exterior."
msgid "GitLabPages|Save"
msgstr "Guardar"
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr "El grupo %{group_name} se actualizó correctamente."
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "Configuración de grupo CI/CD"
-
msgid "Group Git LFS status:"
msgstr "Estado del grupo GIT LFS:"
@@ -13568,9 +13822,6 @@ msgstr "ID de grupo: %{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr "El propietario del grupo debe haber iniciado sesión con SAML antes de habilitar las cuentas administradas de grupo"
-msgid "Group Runners"
-msgstr "Grupo de ejecutores"
-
msgid "Group SAML must be enabled to test"
msgstr "El grupo SAML debe estar habilitado para poder probar"
@@ -13622,6 +13873,12 @@ msgstr "Los mantenedores de grupo pueden registrar grupos de ejecutores en el %{
msgid "Group members"
msgstr "Miembros del grupo"
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr "Hito del grupo"
@@ -13631,6 +13888,9 @@ msgstr "Nombre del grupo"
msgid "Group name (your organization)"
msgstr "Nombre del grupo (su organización)"
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr "Descripción general del grupo"
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "Variables de grupo (heredadas)"
@@ -14054,9 +14320,6 @@ msgstr "Grupos para sincronizar"
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "Grupos con acceso a %{strong_start}%{group_name}%{strong_end}"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Más visitado"
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ 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 runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr "Identidades"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-msgstr "Si algún trabajo supera este umbral de tiempo de espera, se marcará como fallido. Se permite la utilización del lenguaje de entrada de tiempo para humanos, como por ejemplo, \"1 hora\". Los valores que no contengan ninguna especificación de formato se representan como tiempo en segundos."
-
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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr "Si está deshabilitado, solo los administradores podrán configurar la replicación del repositorio."
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "Si está deshabilitado, el nivel de acceso dependerá de los permisos del usuario en el proyecto."
-
-msgid "If enabled"
-msgstr "Si está habilitado"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr "En %{time_to_now}"
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
msgstr "En progreso"
+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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr "Incidente"
@@ -14892,9 +15503,39 @@ msgstr ""
msgid "Incidents"
msgstr "Incidentes"
+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 ""
@@ -14976,8 +15617,8 @@ msgstr "En línea"
msgid "Input host keys manually"
msgstr "Introducir las claves del host manualmente"
-msgid "Input your repository URL"
-msgstr "Introduzca la URL de su repositorio"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr "Insertar un bloque de código"
@@ -15018,11 +15659,11 @@ msgstr ""
msgid "Install"
msgstr "Instalar"
-msgid "Install GitLab Runner"
-msgstr "Instalar GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Instalar Gitlab Runner en Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "Instale un autenticador de token por software como por ejemplo, %{free_otp_link} o Google Authenticator desde el repositorio de su aplicación y utilice esa aplicación para escanear este código QR. Hay más información disponible en la documentación %{help_link_start}%{help_link_end}."
@@ -15047,9 +15688,21 @@ msgstr[1] "Instancias"
msgid "Instance Configuration"
msgstr "Configuración de la instancia"
+msgid "Instance access request"
+msgstr ""
+
+msgid "Instance access request approved"
+msgstr ""
+
+msgid "Instance access request rejected"
+msgstr ""
+
msgid "Instance administrators group already exists"
msgstr "Ya existe el grupo de administrador de instancias"
+msgid "Instance overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Todos los detalles"
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Habilitar comentarios"
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "Estándar"
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr "Entrada no válida, por favor, evite los emojis"
msgid "Invalid login or password"
msgstr "Nombre de usuario o contraseña no válidos"
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "Código PIN inválido."
@@ -15398,6 +16075,9 @@ msgstr "Invitar al grupo"
msgid "Invite member"
msgstr "Invitar al miembro"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr "Estado"
msgid "IssueAnalytics|Weight"
msgstr "Peso"
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr "Las incidencias pueden ser errores, tareas o ideas para ser discutidas.
msgid "Issues closed"
msgstr "Incidencias cerradas"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Incidencias con comentarios, merge requests con diffs y comentarios, etiquetas, hitos, fragmentos de código y otras entidades de proyecto"
@@ -15749,6 +16432,9 @@ msgstr "Total:"
msgid "Issue|Title"
msgstr "Título"
+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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr "Los eventos para %{noteable_model_name} están deshabilitados."
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Si es diferente de la URL Web"
msgid "JiraService|Issue List"
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 "URL del API de JIRA"
@@ -15884,6 +16588,9 @@ msgstr "Los comentarios de Jira se crearán cuando se haga referencia a una inci
msgid "JiraService|Jira issue tracker"
msgstr "Gestos de incidencias Jira"
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "Contraseña o token del API"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ msgstr "Se reintentó el trabajo"
msgid "Jobs"
msgstr "Trabajos"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,8 +16738,8 @@ msgstr "Artefactos del trabajo"
msgid "Job|Job has been erased"
msgstr "Se ha eliminado el trabajo"
-msgid "Job|Job has been erased by"
-msgstr "El trabajo ha sido borrado por"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "Mantener"
@@ -16091,6 +16813,9 @@ msgstr "Solo yo"
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr "Último contacto"
msgid "Last edited %{date}"
msgstr "Última edición el %{date}"
-msgid "Last edited by %{name}"
-msgstr "Última edición por %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "Aprenda GitLab"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Aprenda más sobre Auto DevOps"
-msgid "Learn more about Kubernetes"
-msgstr "Aprenda más acerca de Kubernetes"
-
msgid "Learn more about License-Check"
msgstr "Obtenga más información sobre la verificación de licencias"
@@ -16710,6 +17435,9 @@ msgstr[1] "Limitado a mostrar %d eventos como máximo"
msgid "Line changes"
msgstr "Cambios de línea"
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ msgstr "Aprobadores"
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 "Mostrar sólo los cambios"
@@ -16935,9 +17666,6 @@ msgstr "Convertir este problema en confidencial"
msgid "Make sure you save it - you won't be able to access it again."
msgstr "Asegúrese de guardarlo, no podrá volver a acceder a él."
-msgid "Make this epic confidential"
-msgstr "Marcar esta tarea épica cómo confidencial"
-
msgid "Makes this issue confidential."
msgstr "Convierte la incidencia en confidencial."
@@ -16980,6 +17708,9 @@ msgstr "Administrar autenticación de dos factores"
msgid "Manage your license"
msgstr "Administrar su licencia"
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr "Cuenta gestionada"
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
-msgstr "Número máximo de usuarios:"
+msgid "Maximum Users"
+msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr "Tamaño máximo de los artefactos (MB)"
@@ -17217,9 +17951,6 @@ msgstr "Tiempo de espera máximo para el trabajo"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr "El tiempo de espera máximo para los trabajos tiene un valor que no puede ser aceptado"
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr "El tiempo máximo entre las actualizaciones que puede esperar una répli
msgid "May"
msgstr "Mayo"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Miembros"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "Miembros con acceso a %{strong_start}%{group_name}%{strong_end}"
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr "Las autorizaciones de los merge request le permiten establecer el númer
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr "Se ha producido un error al guardar el borrador del comentario."
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "Se ha producido un error al realizar el squash. Debe hacerse de forma manual."
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "Responder..."
@@ -17652,15 +18383,9 @@ msgstr "No se encontraron archivos"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Fusionado"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "Migrados %{success_count}/%{total_count} archivos."
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr "Migración correcta."
@@ -18229,6 +18957,9 @@ msgstr "Minutos"
msgid "Mirror direction"
msgstr "Dirección de la réplica"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "Replicar repositorio"
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Cancelar"
-
msgid "Modal|Close"
msgstr "Cerrar"
@@ -18451,9 +19179,6 @@ msgstr "Nombre"
msgid "Name has already been taken"
msgstr "El nombre ya está en uso"
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "Nombre de la nueva etiqueta"
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr "No se han detectado políticas"
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr "Las políticas son una especificación de cómo se permite a los grupos de pods comunicarse con los extremos de red de los demás."
@@ -18913,8 +19641,8 @@ msgstr "Nuevo hito"
msgid "New password"
msgstr "Nueva contraseña"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "Los nuevos 'pipelines' cancelarán los 'pipelines' más antiguos y pendientes en el mismo 'branch'"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Nuevo proyecto"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "¡No ha sido posible realizar la conexión con un servidor de Gitaly, por favor compruebe sus logs!"
@@ -19123,6 +19854,9 @@ msgstr "No se han encontrado resultados"
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr "No hay ningún favorito que coincida con su búsqueda"
msgid "No start date"
msgstr "Sin fecha de inicio"
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr "Ninguna plantilla"
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr "No existe ninguna prueba de cobertura"
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr "No se han encontrado vulnerabilidades"
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ msgstr ""
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
msgstr "Uno o más de tus tokens de acceso personal caducarán en %{days_to_expire} días o menos."
-msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr "Sólo los proyectos activos aparecen en la búsqueda y en el panel de co
msgid "Only admins can delete project"
msgstr "Solo los administradores pueden borrar un proyecto"
-msgid "Only mirror protected branches"
-msgstr "Sólo replicar ramas protegidas"
-
msgid "Only policy:"
msgstr "Sólo la política:"
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Opciones"
msgid "Or you can choose one of the suggested colors below"
msgstr "O puede seleccionar alguno de los colores sugeridos a continuación"
-msgid "Origin"
-msgstr "Origin"
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Otras etiquetas"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "Otra información"
@@ -20100,9 +20849,6 @@ msgstr "Eliminar la versión del paquete"
msgid "PackageRegistry|Delete package"
msgstr "Eliminar paquete"
-msgid "PackageRegistry|Filter by name"
-msgstr "Filtrar por nombre"
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr "Para obtener más información sobre el registro PyPiPi, %{linkStart}vea
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "Si todavía no lo ha hecho, necesitará añadir lo siguiente a su archivo %{codeStart}.pypirc%{codeEnd}."
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr "Participantes"
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr "Pasado"
@@ -20463,6 +21215,9 @@ msgstr "Descargar"
msgid "PerformanceBar|Elasticsearch calls"
msgstr "Llamadas de Elasticsearch"
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr "Recursos de Frontend"
@@ -20529,6 +21284,9 @@ msgstr "Programación del Pipeline"
msgid "Pipeline Schedules"
msgstr "Programaciones de los Pipelines"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "Cuota de minutos del pipeline"
@@ -20541,6 +21299,9 @@ 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 "Disparadores de los triggers"
@@ -20709,9 +21470,6 @@ msgstr "Cargar pipelines"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "Caché del proyecto restablecida correctamente."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Actualmente no hay pipelines."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Se ha producido un error al obtener los pipelines. Por favor, inténtelo de nuevo en unos momentos o contacte con su equipo de soporte."
@@ -20862,6 +21620,9 @@ msgstr "Ejecutar Pipeline"
msgid "Pipeline|Run for"
msgstr "Ejecutar para"
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr "Nombre completo"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "Incluir las contribuciones privadas en mi perfil"
@@ -21582,9 +22346,6 @@ msgstr "Organización"
msgid "Profiles|Path"
msgstr "Ruta"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Posición y tamaño de su nuevo avatar"
@@ -21867,6 +22628,9 @@ msgstr "Nombre del proyecto"
msgid "Project name suffix"
msgstr "Sufijo del nombre del proyecto"
+msgid "Project navigation"
+msgstr ""
+
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."
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr "Los proyectos que pertenecen a un grupo tienen como prefijo el espacio d
msgid "Projects to index"
msgstr "Proyectos a indexar"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr "Solicitar a los usuarios que carguen claves SSH"
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr "Proteger variable"
@@ -22830,6 +23600,9 @@ msgstr "Permitido push:"
msgid "ProtectedBranch|Branch"
msgstr "Rama"
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr "Aprobación del propietario del código"
@@ -22866,6 +23639,9 @@ msgstr "Permitido desplegar"
msgid "ProtectedEnvironment|Environment"
msgstr "Entorno"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
@@ -22875,9 +23651,6 @@ msgstr "Proteger un entorno"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Entorno Protegido (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr "Proteger un entorno restringe los usuarios que pueden realizar despliegues."
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "Seleccione un entorno"
@@ -22887,8 +23660,8 @@ msgstr "Seleccionar usuarios"
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr "Seleccione los usuarios para implementar y administrar las opciones de configuración de Feature Flags"
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "Actualmente no hay entornos protegidos, proteja un entorno con el formulario mostrado anteriormente."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "Desproteger"
@@ -23106,6 +23879,9 @@ msgstr "Lea más acerca de las incidencias relacionadas"
msgid "Real-time features"
msgstr "Características en tiempo real"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr "Rebase"
@@ -23219,12 +23995,21 @@ msgstr "Registrar un dispositivo universal de autenticación de dos factores (U2
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "Registrarse ahora"
+msgid "Register the runner with this URL:"
+msgstr ""
+
msgid "Register with two-factor app"
msgstr "Registrarse con la aplicación de dos factores"
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr "Rechazado (cerrado)"
-msgid "Related Deployed Jobs"
-msgstr "Trabajos Desplegados Relacionados"
-
msgid "Related Issues"
msgstr "Incidencias Relacionadas"
-msgid "Related Jobs"
-msgstr "Trabajos Relacionados"
-
-msgid "Related Merge Requests"
-msgstr "Solicitudes de fusión Relacionadas"
-
-msgid "Related Merged Requests"
-msgstr "Solicitudes de fusión Relacionadas"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr "Eliminar"
msgid "Remove %{displayReference}"
msgstr "Eliminar %{displayReference}"
-msgid "Remove Runner"
-msgstr "Eliminar ejecutor"
-
msgid "Remove Zoom meeting"
msgstr "Eliminar la reunión de Zoom"
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Eliminar nodo secundario"
@@ -23705,6 +24478,11 @@ msgstr "Nombre de la clase"
msgid "Reports|Execution time"
msgstr "Tiempo de ejecución"
+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] ""
@@ -23872,6 +24650,9 @@ msgstr "Almacenamiento del repositorio"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,8 +24786,8 @@ msgstr "Restablecer el token de acceso de verificación de estado"
msgid "Reset key"
msgstr "Reiniciar la clave"
-msgid "Reset runners registration token"
-msgstr "Reinicializar el token de registro del runner"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr "Restablecer plantilla"
@@ -24128,6 +24909,9 @@ msgstr "Reintentar"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Reintentar este trabajo"
@@ -24175,6 +24959,9 @@ 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 "Revise el proceso de configuración de los proveedores de servicios de su proveedor de identidad; en este caso, GitLab es el \"proveedor de servicios\" o la \"parte confiante\"."
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr "Tiempo de revisión"
@@ -24216,6 +25003,9 @@ msgstr "Se ha revocado el token de acceso personal %{personal_access_token_name}
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr "Agregar a"
@@ -24261,6 +25051,9 @@ msgstr "Ejecutar las pruebas contra su código a través del terminal web"
msgid "Run untagged jobs"
msgstr "Ejecutar trabajos no etiquetados"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr "El ejecutor se ha actualizado correctamente."
msgid "Runners"
msgstr "Runners"
-msgid "Runners API"
-msgstr "Runners API"
-
-msgid "Runners activated for this project"
-msgstr "Ejecutores activos para este proyecto"
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr "Los ejecutores son procesos que recogen y ejecutan trabajos para GitLab. Aquí puede registrar y ver los ejecutores para este proyecto."
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Los ejecutores se pueden instalar en usuarios separados, en servidores o incluso en su máquina local."
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr "Página de ejecutores."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr "Clave pública SSH"
msgid "SSL Verification:"
msgstr "Verificación SSL:"
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr "Secreto"
msgid "Secret Detection"
msgstr "Detección de secretos"
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Seguridad"
@@ -24796,6 +25613,9 @@ msgstr "Panel de control de seguridad"
msgid "Security dashboard"
msgstr "Panel de control de seguridad"
+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 ""
@@ -24955,9 +25775,6 @@ msgstr "False positivo"
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar descartados"
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr "Ver métricas"
msgid "See the affected projects in the GitLab admin panel"
msgstr "Ver los proyectos afectados en el panel de administración de GitLab"
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,8 +26011,8 @@ msgstr "Selecciona una zona horaria"
msgid "Select all"
msgstr "Seleccionar todo"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Seleccione un clúster existente de Kubernetes o cree un cluster nuevo"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr ""
@@ -25227,6 +26041,9 @@ msgstr "Seleccionar grupos a replicar"
msgid "Select health status"
msgstr "Seleccionar estado de salud"
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr "Seleccionar etiqueta"
@@ -25284,9 +26101,6 @@ msgstr "Seleccionar la suscripción"
msgid "Select target branch"
msgstr "Selecciona una rama de destino"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Seleccione la rama que desea establecer como predeterminada para este proyecto. Todas los merge request y los commit se realizarán automáticamente contra ese branch a menos que especifique uno diferente."
-
msgid "Select the custom project template source group."
msgstr "Seleccione el grupo de origen de plantilla de proyecto personalizado."
@@ -25569,6 +26383,9 @@ msgstr "Establecer la rama de destino a"
msgid "Set target branch to %{branch_name}."
msgstr "Establecer la rama de destino a %{branch_name}."
+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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,11 +26425,11 @@ msgstr "Configurar CI/CD"
msgid "Set up Jira Integration"
msgstr "Configurar la integración con Jira"
-msgid "Set up a %{type} Runner automatically"
-msgstr "Configurar un %{type} ejecutor automáticamente"
+msgid "Set up a %{type} runner automatically"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "Configurar un %{type} ejecutor manualmente"
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr "Establecer una nueva contraseña"
-msgid "Set up pipeline subscriptions for this project."
-msgstr "Configure las subscripciones a los pipelines para este proyecto."
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr "Restablecer los minutos utilizados de los 'pipelines'"
msgid "Sherlock Transactions"
msgstr "Transacciones de Sherlock"
-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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Mostrar la última versión"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr "Vea la lista de comandos disponibles en Slack después de configurar est
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "Este servicio permite a los usuarios realizar operaciones comunes en este proyecto utilizando comandos en Slack."
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Más lento, pero se asegura de que el espacio de trabajo del proyecto sea prístino, ya que se clona el repositorio desde cero para cada trabajo"
-
msgid "Smartcard"
msgstr "Tarjeta inteligente"
@@ -26215,6 +27026,9 @@ msgstr ""
msgid "Something went wrong while editing your comment. Please try again."
msgstr "Se ha producido un error al editar su comentario. Por favor, inténtalo de nuevo."
+msgid "Something went wrong while exporting requirements"
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr "Algo salió mal al obtener la lista de %{listType}. ¡Por favor, inténtelo de nuevo!"
@@ -26581,8 +27395,8 @@ msgstr "Protección Anti-Spam y Anti-Bot"
msgid "Spam log successfully submitted as ham."
msgstr "Se ha enviado el registro de spam correctamente."
-msgid "Specific Runners"
-msgstr "Ejecutores específicos"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr "No se puede usar la URL especificada: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr "No se puede usar la URL especificada: \"%{reason}\""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "Especifique un patrón para la expresión regular de direcciones de correo electrónico para identificar usuarios internos predeterminados."
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Especifique la siguiente dirección URL durante la configuración del ejecutor:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr "Etapa"
-msgid "Stage & Commit"
-msgstr "Stage & Commit"
-
msgid "Stage data updated"
msgstr "Datos de la etapa actualizados"
@@ -26668,8 +27476,8 @@ msgstr "Iniciar Terminal web"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar una %{new_merge_request} con estos cambios"
-msgid "Start a Free Gold Trial"
-msgstr "Iniciar una prueba Gold gratis"
+msgid "Start a Free Ultimate Trial"
+msgstr ""
msgid "Start a new discussion..."
msgstr "Comenzar una nueva discusión..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr "Iniciar una búsqueda"
-msgid "Start the Runner!"
-msgstr "¡Inicie el ejecutor!"
-
msgid "Start thread"
msgstr "Iniciar un hilo"
@@ -26713,8 +27518,8 @@ msgstr "Iniciar el hilo y cerrar %{noteable_name}"
msgid "Start thread & reopen %{noteable_name}"
msgstr "Iniciar el hilo y volver a abrir %{noteable_name}"
-msgid "Start your Free Gold Trial"
-msgstr "Comience su prueba Gold gratuita"
+msgid "Start your Free Ultimate Trial"
+msgstr ""
msgid "Start your free trial"
msgstr "Comience su prueba gratuita"
@@ -26740,15 +27545,15 @@ msgstr "Iniciando..."
msgid "Starts %{startsIn}"
msgstr "Comienza %{startsIn}"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Comienza a las (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Indique su mensaje para activar"
@@ -26926,6 +27731,9 @@ msgstr "Desconocido"
msgid "Subgroup milestone"
msgstr "Hito del subgrupo"
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr "Resumen del subgrupo"
@@ -27337,6 +28145,9 @@ msgstr "Encabezado y pie de página del sistema"
msgid "System hook was successfully updated."
msgstr "El hook del sistema se actualizó correctamente."
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Métricas del sistema (personalizadas)"
@@ -27361,9 +28172,15 @@ msgstr "Nombre de la etiqueta"
msgid "Tag name is required"
msgstr ""
+msgid "Tag push events"
+msgstr ""
+
msgid "Tag this commit."
msgstr "Etiquetar este commit."
+msgid "Tag:"
+msgstr ""
+
msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
msgstr "Se etiquetó a este commit a %{tag_name} con \"%{message}\"."
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
-msgstr "Se ha producido un error al generar un informe de Terraform."
+msgid "Terraform|A report failed to generate."
+msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
-msgstr "Se ha generado un informe de Terraform en sus pipelines."
+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 ""
@@ -27599,11 +28419,11 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
-msgstr "El informe de Terraform %{name} se generó en sus pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
+msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
msgstr ""
@@ -27932,9 +28752,6 @@ msgstr[1] "Se revocaron los siguientes tokens de acceso personal: %{token_names}
msgid "The fork relationship has been removed."
msgstr "La relación con la bifurcación se ha eliminado."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "La etapa de incidencia muestra el tiempo que toma desde la creación de
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "El tamaño máximo de archivo permitido es de %{size}."
+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 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 "Los conflictos en el merge para este merge request no se pueden resolver a través de GitLab. Por favor, intente resolverlos localmente."
@@ -28022,8 +28851,11 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "El nombre %{name} ya se está utilizando en este directorio."
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
-msgstr "El número de cambios que se recuperarán desde GitLab al clonar un repositorio. Al modificar esta opción puede acelerar la ejecución de los pipelines. Déjelo en blanco o con valor 0 para deshabilitar el clonado superficial por defecto y así hacer que GitLab CI clone todas las ramas y todas las etiquetas cada vez."
+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 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 ""
@@ -28040,9 +28872,6 @@ 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 path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "La etapa del ciclo de vida de desarrollo."
@@ -28088,6 +28917,9 @@ msgstr "El proyecto se ha importado correctamente."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr "La replica ha tardado demasiado tiempo en completarse."
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."
-msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr "La hoja de ruta muestra el progreso de sus tareas épicas a lo largo de una línea de tiempo"
-
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 ""
@@ -28172,7 +29001,7 @@ msgstr "Se ha guardado el mapa de usuario. Por favor, continue seleccionando los
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 "El mapa del usuarios es una asignación de los usuarios de FogBugz que participaron en sus proyectos a la forma en que su dirección de correo electrónico y nombre de usuario se importarán a GitLab. Puede cambiar esto rellenando la tabla a continuación."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr "Se ha producido un error al recuperar las etiquetas del proyecto."
msgid "There was a problem fetching project users."
msgstr "Se ha producido un problema al recuperar los usuarios del proyecto."
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr "Se ha producido un error al recuperar los usuarios."
@@ -28340,6 +29172,9 @@ msgstr "Se ha producido un error al guardar su etapa personalizada, por favor in
msgid "There was a problem sending the confirmation email"
msgstr "Se ha producido un error al enviar el correo electrónico de confirmación"
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr "Se ha producido un un error %{message} en la lista de tareas pendientes."
@@ -28493,17 +29328,26 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "Se ha producido un error con reCAPTCHA. Por favor, resuelva el reCAPTCHA de nuevo."
+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 "Estas incidencias tienen un título similar al de la incidencia que está creando. Sería mejor hacer un comentario en alguna de estas en vez de crear otra incidencia similar."
msgid "These paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
-msgstr "Estas variables están configuradas en la configuración del grupo principal, y estarán activas en el proyecto actual junto con las variables del proyecto."
+msgid "These runners are shared across projects in this group."
+msgstr ""
-msgid "They can be managed using the %{link}."
-msgstr "Se pueden administrar usando el %{link}."
+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 "Third Party Advisory Link"
msgstr ""
@@ -28532,8 +29376,8 @@ msgstr "Este %{viewer} no se puede mostrar porque %{reason}. En su lugar, puedes
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 "Esta instancia de GitLab aún no proporciona ningún 'runner' compartido. Los administradores de instancias pueden registrar 'runner' compartidos en el área de administración."
+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 ""
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+msgstr ""
+
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "Esta acción puede provocar la pérdida de datos. Para prevenir acciones accidentales, le pedimos que confirme su intención."
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr "Esta aplicación fue creada por %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Está aplicación podrá:"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-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."
@@ -28676,14 +29532,17 @@ msgstr ""
msgid "This field is required."
msgstr "Este campo es obligatorio."
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Este grupo"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "Este grupo aún no proporciona ningún grupo de 'runners'."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -28712,6 +29571,9 @@ msgstr ""
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
msgstr "Esta es una lista de dispositivos desde los que ha iniciado sesión. Cierre todas las sesiones que no reconozca."
+msgid "This is a merge train pipeline"
+msgstr ""
+
msgid "This is a security log of important events involving your account."
msgstr "Este es un registro de seguridad de eventos importantes relacionados con su cuenta."
@@ -28835,6 +29697,9 @@ msgstr "Esto puede exponer información confidencial ya que el fork seleccionado
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 "Este merge request está bloqueado."
@@ -28880,8 +29754,8 @@ msgstr ""
msgid "This project"
msgstr "Este proyecto"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "Este proyecto no pertenece a ningún grupo y, por lo tanto, no puede hacer uso de un grupo de ejecutores."
+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 ""
@@ -28937,6 +29811,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Este ejecutor solo se ejecutará en pipelines disparados sobre ramas protegidas"
+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 "Esta configuración se puede reemplazar en cada proyecto."
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr "Esta variable no se puede enmascarar."
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr "Esto le redirigirá a una página de inicio de sesión externa."
@@ -29391,6 +30262,9 @@ msgstr "Para agregar una clave SSH necesita %{generate_link_start}generar una%{l
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."
+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 ""
@@ -29406,6 +30280,9 @@ msgstr "Para conectar un repositorio SVN, eche un vistazo a %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Para definir los usuarios internos, primero habilite nuevos usuarios externos"
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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 "Para comenzar, introduzca su URL de FogBugz, y a continuación, introduzca la información de inicio de sesión. En los siguientes pasos, podrá asignar usuarios y seleccionar los proyectos que desea importar."
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr "Para comenzar, vincule esta página a su servidor Jaeger, o descubra cómo instalar %{link_start_tag}Jaeger%{link_end_tag}"
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr "Para abrir Jaeger y ver fácilmente la trazabilidad desde GitLab, enlace la página %{link} a su servidor"
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,8 +30346,8 @@ msgstr "Para recibir alertas de los servicios de Prometheus configurados manualm
msgid "To see all the user's personal access tokens you must impersonate them first."
msgstr "Para ver todos los tokens de acceso personales de los usuarios debe suplantar su identidad primero."
-msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Silver%{linkEnd}. You can also remove the project from the dashboard."
-msgstr "Para ver los detalles operacionales de este proyecto, %{linkStart}actualice el plan del grupo a un planSilver%{linkEnd}. También puede eliminar el proyecto desde el panel de control."
+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 "Para ver los detalles operacionales de este proyecto, contacte con un dueño del grupo %{groupName} para actualizar el plan. También puede eiminar el proyecto del panel de control."
@@ -29481,12 +30364,6 @@ 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 "Para especificar el nivel de notificación por proyecto de un grupo al que pertenece, debe visitar la página del proyecto y cambiar el nivel de las notificaciones."
-msgid "To start serving your jobs you can add Runners to your group"
-msgstr "Para empezar a servir sus trabajos, puede agregar ejecutores a su grupo"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr "Para comenzar a ejecutar sus trabajos, puede agregar ejecutores específicos a su proyecto o utilizar ejecutores compartidos"
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "Para ver la hoja de ruta, agregue una fecha de inicio o final para cada uno de las tareas épicas en este grupo o en uno de sus subgrupos. En la vista mensual, sólo se mostrarán las tareas las épicas del último mes, del mes en curso, y de los próximos 5 meses."
-
msgid "To widen your search, change or remove filters above"
msgstr "Para ampliar la búsqueda, cambie o elimine filtros"
@@ -29523,6 +30397,9 @@ msgstr "La tarea pendiente se ha marcado como realizada correctamente."
msgid "Today"
msgstr "Hoy"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Alternar navegación"
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ msgstr ""
msgid "Transfer project"
msgstr "Transferir proyecto"
+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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr "Saltar periodo de prueba (Continuar con cuenta gratuita)"
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ msgstr ""
msgid "Trigger"
msgstr "Disparador"
+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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr "Ejecutar pipelines para la actualización de las replicas"
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,8 +30714,11 @@ msgstr "El disparador se actualizó correctamente."
msgid "Triggerer"
msgstr "Disparador"
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
-msgstr "Los disparadores pueden forzar la reconstrucción de una rama o etiqueta específica con una llamada API. Estos tokens simulan a sus usuarios asociados, incluyendo el acceso a los proyectos y los permisos de proyecto."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
msgstr "Solucione problemas y supervise su aplicación con el seguimiento"
@@ -30041,7 +30933,7 @@ msgstr "No se puede actualizar esta incidencia en este momento."
msgid "Unarchive project"
msgstr "Desarchivar proyecto"
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr "Actualizaciones"
msgid "Updating"
msgstr "Actualizando"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr "Actualice su plan para mejorar los merge requests."
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Subir fichero CSV"
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Utilice la herramienta Service Desk para conectarse con sus usuarios (por ejemplo, para ofrecer soporte al cliente) a través del correo electrónico directamente desde dentro de GitLab"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "Utilice un autenticador de contraseña de un único uso en su dispositivo móvil u ordenador para habilitar la autenticación de dos factores (2FA)."
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr "Utilizar un color personalizado #FF0000"
@@ -30539,8 +31440,11 @@ msgstr "Utilice una línea por URI"
msgid "Use template"
msgstr "Utilizar plantilla"
-msgid "Use the following registration token during setup:"
-msgstr "Utilice el siguiente token de registro durante la configuración:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "Utiliza tu configuración de notificación global"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr "Usuarios"
msgid "Users in License"
msgstr ""
-msgid "Users in License:"
-msgstr "Usuarios en la licencia:"
-
msgid "Users or groups set as approvers in the project's or merge request's settings."
msgstr ""
-msgid "Users over License:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr "Usuarios que solicitan acceso a"
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ msgstr ""
msgid "Variables"
msgstr "Variables"
+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 "Varias opciones de configuración del registro de contenedores."
@@ -31086,6 +31990,9 @@ msgstr "Ver el panel de control del rendimiento en"
msgid "View users statistics"
msgstr "Ver las estadísticas de usuarios"
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "Ver commit"
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Webhook"
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Webhooks"
@@ -31608,12 +32524,12 @@ msgstr "¡Bienvenido! Su cuenta fue desactivada por inactividad pero ya se ha re
msgid "Welcome to GitLab"
msgstr "Bienvenido a GitLab"
-msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr ""
-
msgid "Welcome to GitLab, %{first_name}!"
msgstr "¡Bienvenido a GitLab %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
msgid "Welcome to the guided GitLab tour"
msgstr "Bienvenido a la visita guiada de GitLab"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr "¿Cuál es su nivel de experiencia?"
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr "Cuando está habilitado, los usuarios no pueden utilizar GitLab hasta qu
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 merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Cuando el merge request sea aceptado"
@@ -31667,6 +32586,9 @@ msgstr[1] "Cuando los merge request sean aceptados"
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "Cuando:"
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "Puede %{linkStart}ver el blob%{linkEnd} en su lugar."
-
msgid "You can also create a project from the command line."
msgstr "También puede crear un proyecto desde la línea de comandos."
@@ -32051,9 +32970,6 @@ msgstr "También puede subir archivos existentes desde su ordenador utilizando l
msgid "You can always edit this later"
msgstr "Siempre puede editar esto más tarde"
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr "Puedes crear unos nuevos en las opciones de configuración de sus tokens
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Puede contribuir fácilmente pidiendo unirse a estos grupos."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Puede instalar fácilmente un ejecutor en un clúster de Kubernetes. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-msgstr ""
-
msgid "You can now submit a merge request to get this change into the original branch."
msgstr "Puede enviar un merge request para tener este cambio en la rama original."
msgid "You can now submit a merge request to get this change into the original project."
msgstr "Puede enviar un merge request para tener este cambio en el proyecto original."
+msgid "You can only %{action} files when you are on a branch"
+msgstr ""
+
msgid "You can only edit files when you are on a branch"
msgstr "Solo puede agregar archivos cuando está en una rama"
@@ -32153,8 +33069,8 @@ msgstr "Puede resolver el conflicto del merge request utilizando el modo Interac
msgid "You can see your chat accounts."
msgstr "Puede ver sus cuentas de chat."
-msgid "You can set up as many Runners as you need to run your jobs."
-msgstr "Puede configurar tantos ejecutores como necesite para ejecutar sus trabajos."
+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 "Puede especificar el nivel de la notificación por grupo o por proyecto."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr "No tiene permisos"
@@ -32489,6 +33411,9 @@ msgstr "YouTube"
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 ""
@@ -32525,15 +33450,15 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "Sus claves GPG (%{count})"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr "Su grupo de GitLab"
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr ""
-
msgid "Your Groups"
msgstr "Sus grupos"
@@ -32687,6 +33612,9 @@ msgstr "Su licencia es válida desde"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "Su mensaje aquí"
@@ -32771,6 +33699,12 @@ msgstr "Se ha eliminado la reunión de Zoom"
msgid "[No reason]"
msgstr "[No hay razón]"
+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 "un usuario eliminado"
@@ -32857,9 +33791,15 @@ msgstr "nombre de la rama"
msgid "by"
msgstr "por"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "día"
msgstr[1] "días"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr "rama por defecto"
@@ -33211,8 +34154,10 @@ msgstr "por ejemplo %{token}"
msgid "element is not a hierarchy"
msgstr "el elemento no es una jerarquía"
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr "grupo"
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr "grupos"
@@ -33549,6 +34497,12 @@ msgstr "Restaure o use una rama diferente %{missingBranchName}"
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr "%{link_start}Obtenga más información sobre como resolver conflictos%{link_end}"
+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 "Uso de %{metricsLinkStart} memoria %{metricsLinkEnd} %{emphasisStart} disminuido %{emphasisEnd} de %{memoryFrom}MB a %{memoryTo}MB"
@@ -33675,9 +34629,6 @@ msgstr "Merge"
msgid "mrWidget|Merge failed."
msgstr "Merge fallido."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr "Se ha producido un error al realizar el merge: %{mergeError}. Por favor, inténtelo de nuevo."
-
msgid "mrWidget|Merge locally"
msgstr "Merge local"
@@ -33747,7 +34698,7 @@ msgstr "Los cambios no se fusionaron en"
msgid "mrWidget|The changes will be merged into"
msgstr "Los cambios se fusionarán en"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr "se ejecutará el merge cuando la ejecución del pipeline se finalice con
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr "restablecer."
msgid "revised"
msgstr "revisado"
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr "satisfecho"
@@ -34189,6 +35146,9 @@ msgstr "para listar"
msgid "toggle collapse"
msgstr "Colapsar/Expandir"
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "disparado"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 0d7ec929c2f..509af342db7 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:06\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 024018e5e51..e20dceb120b 100644
--- a/locale/fa_IR/gitlab.po
+++ b/locale/fa_IR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:06\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index a3c2ce82996..63fd9f90d65 100644
--- a/locale/fi_FI/gitlab.po
+++ b/locale/fi_FI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index aef913b4214..e9762d9d6eb 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:57\n"
+"PO-Revision-Date: 2021-02-01 17:08\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 9e05d1cf3b4..9b221f09e48 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d résultat du test corrigé"
msgstr[1] "%d résultats du test corrigés"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr ""
msgid ", or "
msgstr ", ou "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr "- l’exécuteur est actif et peut traiter de nouvelles tâches"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- l’exécuteur est en pause et ne recevra pas de nouvelles tâches"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "Une branche par défaut ne peut pas être choisie pour un projet vide."
msgid "A deleted user"
msgstr "Un utilisateur supprimé"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Un projet est l’endroit où vous hébergez vos fichiers (dépôt), planifiez votre travail (tickets) et publiez votre documentation (wiki), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
msgstr "Ajouter une liste à puces"
msgid "Add a comment to this line"
msgstr ""
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr "Domaine de DevOps automatique"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr "Supprimer un compte utilisateur"
msgid "AdminUsers|Delete user and contributions"
msgstr "Supprimer le compte et ses contributions"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,8 +2930,8 @@ msgstr ""
msgid "Allow projects within this group to use Git LFS"
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 "Autoriser l’accès public aux pipelines et aux détails des tâches, y compris les journaux de sortie et les artefacts"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Permettre le rendu des diagrammes PlantUML dans les documents Asciidoc."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ msgstr "Durée (en heures) durant laquelle les utilisateurs sont autorisés à
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 ""
@@ -3018,6 +3065,9 @@ msgstr "Une erreur est survenue"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anonyme"
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ msgstr "Projet archivé ! Le dépôt et les autres ressources du projet sont e
msgid "Archived projects"
msgstr "Projets archivés"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+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?"
@@ -3778,15 +3828,18 @@ 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 registration token?"
-msgstr "Êtesâ€vous sûr·e de vouloir réinitialiser le jeton d’inscription ?"
-
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é ?"
+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 ""
@@ -3856,8 +3909,8 @@ msgstr ""
msgid "Ascending"
msgstr "Croissant"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "Demandez au responsable du groupe de configurer un exécuteur de groupe."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL du service consommateur d’assertion"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "Attribuer une couleur personnalisée comme #FF0000"
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr "Attribuer des étiquettes"
@@ -4133,9 +4183,6 @@ msgstr "Autoriser %{link_to_client} à utiliser votre compte ?"
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,8 +4207,8 @@ msgstr "Auto DevOps, exécuteurs et artéfacts de tâches"
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Annuler automatiquement les pipelines redondants en attente"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4259,16 +4306,16 @@ msgstr "Disponible"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr "Commencer avec le commit sélectionné"
-msgid "Below are examples of regex for existing tools:"
-msgstr "Voici quelques exemples d’expressions rationnelles pour des outils existants :"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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 ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Facturation"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,11 +4483,17 @@ 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 Gold."
-msgstr "Renseignez-vous sur nos forfaits en lisant notre %{faq_link}, où essayez gratuitement l’édition Or sur GitLab.com pendant 30 jours."
+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 ""
@@ -4460,6 +4513,9 @@ msgstr "Ce groupe utilise le forfait associé à son groupe parent."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Pour gérer le forfait de ce groupe, rendez vous à la section facturation de %{parent_billing_page_link}."
+msgid "BillingPlans|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 ""
@@ -4469,6 +4525,9 @@ 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 "foire aux questions"
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr "paramètres du projet"
msgid "Branches|protected"
msgstr "protégée"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "par"
@@ -4936,6 +5019,9 @@ msgstr "Intégration et livraison continues"
msgid "CI/CD configuration"
msgstr "Configuration de l’intégration et de la livraison continues"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "Intégration et livraison continues pour dépôt externe"
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Picorer"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Défaire"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Veuillez vérifier la %{docs_link_start}documentation%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Choisissez n’importe quelle couleur."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 "Choisissez quels dépôts vous voulez connecter pour exécuter des pipelines d’intégration et de livraison continues (CI/CD)."
@@ -5758,12 +5856,24 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "est indisponible : %{reason}"
+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 ""
@@ -5806,8 +5916,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Cliquez sur le bouton ci-dessous pour lancer le processus d’installation en accédant à la page Kubernetes"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "Cliquez pour l’agrandir."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr "Cohortes"
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Masquer la barre latérale"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr "Créer un jeton d’accès personnel"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Créé"
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr "Branche actuelle"
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr "Profil"
msgid "CurrentUser|Settings"
msgstr "Paramètres"
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,8 +8704,8 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "Personnalisez la configuration de votre pipeline et affichez son état et le rapport de couverture."
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,8 +10227,8 @@ msgstr "Désactiver"
msgid "Disable for this project"
msgstr "Désactiver pour ce projet"
-msgid "Disable group Runners"
-msgstr "Désactiver les exécuteurs de groupe"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
@@ -10299,9 +10520,6 @@ msgstr "Au cours de ce processus, il vous sera demandé les URL de GitLab. Utili
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr "Chaque exécuteur peut être dans l’un des états suivants :"
-
msgid "Edit"
msgstr "Éditer"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Activer la collecte de données Pseudonymizer"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,8 +10877,8 @@ msgstr ""
msgid "Enable for this project"
msgstr "Activer pour ce projet"
-msgid "Enable group Runners"
-msgstr "Activer les exécuteurs de groupe"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr ""
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "Se termine à (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr "Autorisation de politique de classification externe"
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr "Plus rapide parce qu’il réutilise l’espace de travail du projet (faire un clone en solution de secours s’il n’existe pas)"
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ msgstr "Message de pied de page"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr "Pour plus d’informations, consultez la documentation sur la %{deactiva
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Pour les projets privés, tout membre (invité ou supérieur) peut afficher les pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Pour les projets publics, tout le monde peut afficher des pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,8 +12886,8 @@ msgstr "Depuis la création du ticket jusqu’au déploiement en production"
msgid "From merge request merge until deploy to production"
msgstr "Depuis la fusion de la demande de fusion jusqu’au déploiement en production"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "À partir de l’affichage des détails de la grappe de serveurs Kubernetes, installez un exécuteur à partir de la liste des applications"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr ""
@@ -12680,6 +12934,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "NÅ“uds Geo"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,8 +13351,8 @@ msgstr "Révision de Git"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
-msgstr "Stratégie Git pour les pipelines"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "Les exécuteurs de groupe peuvent exécuter du code pour tous les projets de ce groupe."
-
msgid "GitLab Import"
msgstr "Importation depuis GitLab"
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "Paramètres du groupe CI/CD"
-
msgid "Group Git LFS status:"
msgstr "Statut du stockage LFS Git du groupe :"
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr "Exécuteurs de groupe"
-
msgid "Group SAML must be enabled to test"
msgstr "Le SAML de groupe doit être activé afin de pouvoir tester"
@@ -13622,6 +13873,12 @@ msgstr "Les responsables de groupe peuvent créer des exécuteurs de groupe via
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr "Nom du groupe"
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Fréquemment consultés"
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr "Maintenance démarrée avec succès"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr "Identités"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr "Si cette option est désactivée, une branche locale divergente ne sera
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "Si désactivé, le niveau d’accès dépendra des autorisations de l’utilisateur ou l’utilisatrice pour ce projet."
-
-msgid "If enabled"
-msgstr "Si activé"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,8 +15617,8 @@ msgstr "En ligne"
msgid "Input host keys manually"
msgstr "Entrer les clefs d’hôte manuellement"
-msgid "Input your repository URL"
-msgstr "Entrez l’URL de votre dépôt"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr ""
@@ -15018,11 +15659,11 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
-msgstr "Installer GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Installez un exécuteur sur Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
@@ -15047,9 +15688,21 @@ msgstr[1] "Instances"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr "Les tickets peuvent être des bogues, des tâches ou des sujets de discu
msgid "Issues closed"
msgstr "Tickets clos"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ msgstr ""
msgid "Jobs"
msgstr "Tâches"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,8 +16738,8 @@ msgstr "Artefacts de la tâche"
msgid "Job|Job has been erased"
msgstr "La tâche a été effacée"
-msgid "Job|Job has been erased by"
-msgstr "La tâche a été supprimée par"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "Garder"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr "Dernier contact"
msgid "Last edited %{date}"
msgstr "Dernière modification le %{date}"
-msgid "Last edited by %{name}"
-msgstr "Dernière modification par %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr "En savoir plus sur Kubernetes"
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] "Affichage limité à %d événements maximum"
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr "Durée maximale d’exécution de la tâche"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr "mai"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Membres"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr "Une erreur est survenue lors de l’enregistrement du brouillon du comme
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr "Aucun fichier trouvé"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Fusionnée"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr "Sens du miroir"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Annuler"
-
msgid "Modal|Close"
msgstr "Fermer"
@@ -18451,9 +19179,6 @@ msgstr "Nom"
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "Nommez la nouvelle étiquette"
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,8 +19641,8 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "De nouveaux pipelines annuleront les anciens pipelines en attente sur la même branche"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Nouveau projet"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Aucune connexion n’a pu être établie avec un serveur Gitaly, veuillez vérifier votre journal !"
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr "Ne mettre en miroir que les branches protégées"
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Options"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ou vous pouvez choisir l’une des couleurs suggérées ciâ€dessous"
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Autres étiquettes"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "Autres informations"
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr "Planification de pipeline"
msgid "Pipeline Schedules"
msgstr "Planifications de pipelines"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 "Déclencheurs de pipeline"
@@ -20709,9 +21470,6 @@ msgstr "Chargement des pipelines"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "Réinitialisation du cache de projet réussie."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Il n’y a actuellement aucun pipeline."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Une erreur est survenue lors de la récupération des pipelines. Réessayez dans quelques instants ou contactez votre équipe d’assistance."
@@ -20862,6 +21620,9 @@ msgstr "Exécuter le pipeline"
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr "Chemin d’accès"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Position et taille de votre nouvel avatar"
@@ -21867,6 +22628,9 @@ msgstr "Nom du projet"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr "Les projets appartenant à un groupe sont préfixés avec l’espace de
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr "Autorisé à déployer"
msgid "ProtectedEnvironment|Environment"
msgstr "Environnement"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Protéger"
@@ -22875,9 +23651,6 @@ msgstr "Protéger un environnement"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Environnements protégés (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "Sélectionner un environnement"
@@ -22887,8 +23660,8 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "Il n’y a actuellement aucun environnement protégé, protégezâ€en un avec le formulaire ciâ€dessus."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "Déprotéger"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr "Fonctionnalités en temps réel"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Tâches déployées liées"
-
msgid "Related Issues"
msgstr "Tickets liés"
-msgid "Related Jobs"
-msgstr "Tâches liées"
-
-msgid "Related Merge Requests"
-msgstr "Demandes de fusion liées"
-
-msgid "Related Merged Requests"
-msgstr "Demandes fusionnées liées"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr "Supprimer"
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr "Supprimer l’exécuteur"
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ msgstr ""
msgid "Reports|Execution time"
msgstr "Durée d’exécution"
+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] ""
@@ -23872,6 +24650,9 @@ msgstr "Stockage du dépôt"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,8 +24786,8 @@ msgstr "Réinitialiser le jeton d’accès au bilan de santé"
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
-msgstr "Réinitialiser le jeton d’inscription des exécuteurs"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr ""
@@ -24128,6 +24909,9 @@ msgstr "Réessayer"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Relancer cette tâche"
@@ -24175,6 +24959,9 @@ 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 "Revoyez le processus de configuration des fournisseurs de service chez votre fournisseur d’identité — dans le cas présent, GitLab est le « fournisseur de service » ou le « tiers de confiance »."
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Exécuter les tâches non étiquetées"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr "Exécuteurs"
-msgid "Runners API"
-msgstr "API des exécuteurs"
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Les exécuteurs peuvent être placés sur différents utilisateurs et serveurs, voire sur votre machine locale."
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr "Page des exécuteurs."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr "Clef SSH publique"
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr "Secret"
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Sécurité"
@@ -24796,6 +25613,9 @@ msgstr "Tableau de bord de sécurité"
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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,8 +26011,8 @@ msgstr "Sélectionnez un fuseau horaire"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Sélectionnez une grappe de serveurs Kubernetes existante ou créezâ€en une nouvelle"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr ""
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Sélectionner une branche cible"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Sélectionnez la branche que vous souhaitez définir comme branche par défaut pour ce projet. Toutes les demandes de fusion et les commits seront automatiquement effectués sur cette branche, à moins que vous n’en spécifiez une autre."
-
msgid "Select the custom project template source group."
msgstr "Sélectionnez le groupe source de modèles de projet personnalisés."
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,11 +26425,11 @@ msgstr "Configuration CI/CD"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "Configurer manuellement un exécuteur %{type}"
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr "Réinitialiser les minutes du pipeline utilisées"
msgid "Sherlock Transactions"
msgstr "Transactions Sherlock"
-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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Afficher la dernière version"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Plus lent, mais permet de s’assurer que l’espace de travail du projet est vierge, comme il clone le dépôt à partir de zéro pour chaque tâche"
-
msgid "Smartcard"
msgstr "Carte à puce"
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr "Une erreur est survenue lors de la récupération de la liste de %{listType}"
@@ -26581,8 +27395,8 @@ msgstr "Protection antiâ€pourriel et antiâ€robot"
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
-msgstr "Exécuteurs spécifiques"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr ""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "Spécifiez un motif d’expression rationnelle permettant l’identification des adresses de courriel des utilisateurs internes."
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Spécifiez l’URL suivante lors de la configuration de l’exécuteur :"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr "Étape"
-msgid "Stage & Commit"
-msgstr "Étape & commit"
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Créer une %{new_merge_request} avec ces changements"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr "Démarrer l’exécuteur !"
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Démarre à (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Énoncez votre message à activer"
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Métriques du système (personnalisées)"
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "La relation de divergence a été supprimée."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "Le présentoir des tickets affiche le temps nécessaire entre la créati
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ 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 path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "La phase du cycle de développement."
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "La collecte de données du pseudonymiseur est désactivée. Lorsque cette option est activée, GitLab exécute un travail en tâche de fond produisant des fichiers CSV pseudonymisés à partir de la base de données GitLab qui seront téléchargés dans le répertoire de stockage d’objets que vous avez configuré."
+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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "L’étape d’évaluation montre le temps entre la création de la demande de fusion et la fusion effective de celleâ€ci. Ces données seront automatiquement ajoutées après que vous aurez fusionné votre première demande de fusion."
-msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr "La feuille de route affiche la progression de vos épopées dans le temps"
-
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 ""
@@ -28172,7 +29001,7 @@ 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 "La carte des utilisateurs met en correspondance les utilisateurs de FogBugz qui ont participé à vos projets en précisant la manière dont leurs adresses de courriel et leurs noms d’utilisateur sont importés dans GitLab. Vous pouvez y apporter des modifications en remplissant le tableau ciâ€dessous."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,17 +29328,26 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
-msgstr "Ils peuvent être gérés en utilisant %{link}."
+msgid "These variables are inherited from the parent group."
+msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
@@ -28532,8 +29376,8 @@ 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 "Cette instance de GitLab ne fournit aucun exécuteur partagé pour le moment. Les administra·teur·trice·s de l’instance peuvent enregistrer des exécuteurs partagés dans la zone d’administration."
+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 ""
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr "Cette application a été créée par %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Cette application sera en mesure de :"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,14 +29532,17 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Ce groupe"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "Ce groupe ne fournit pas encore d’exécuteurs de groupe."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -28712,6 +29571,9 @@ msgstr "Il s’agit d’une tâche différée devant être exécutée dans %{rem
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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Cela signifie que vous ne pouvez pas pousser du code tant que vous n’avez pas créé un dépôt vide ou que vous n’avez pas importé un dépôt existant."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 "Cette demande de fusion est verrouillée."
@@ -28880,8 +29754,8 @@ msgstr ""
msgid "This project"
msgstr "Ce projet"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "Ce projet n’appartient pas à un groupe et ne peut donc pas faire appel à un exécuteur de groupe."
+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 ""
@@ -28937,6 +29811,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Cet exécuteur ne fonctionnera que sur les pipelines déclenchés sur des branches protégées"
+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 "Ce paramètre peut être outrepassé pour chacun des projets."
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "Cet utilisateur sera l’auteur de tous les événements du flux d’activité résultant d’une mise à jour, comme la création de nouvelles branches ou les nouveaux commits poussés vers des branches existantes."
-
msgid "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ msgstr "Afin d’ajouter une clef SSH, vous devez soit %{generate_link_start}enÂ
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 ""
@@ -29406,6 +30280,9 @@ msgstr "Pour connecter un dépôt SVN, veuillez consulter %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Afin de définir les utilisateurs internes, veuillez d’abord activer les nouveaux utilisateurs définis comme externes"
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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 "Pour commencer, entrez votre URL FogBugz et vos informations de connexion ciâ€dessous. Dans les étapes suivantes, vous pourrez mettre en correspondance les comptes des utilisateurs et sélectionner les projets à importer."
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr "Pour commencer, créez un lien vers cette page sur votre serveur Jaeger, ou bien découvrez comment %{link_start_tag}installer Jaeger%{link_end_tag}"
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr "Pour commencer à exécuter vos tâches, vous pouvez ajouter des exécuteurs à votre groupe"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "Afin d’afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées."
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr "Aujourd’hui"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,8 +30687,8 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr "Déclencher des pipelines pour les mises à jour de miroirs"
-msgid "Trigger pipelines when branches or tags are updated from 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 "Déclenche les pipelines lorsque les branches ou les étiquettes sont mises à jour sur le dépôt en amont. Selon l’activité du dépôt en amont, cela peut considérablement augmenter la charge de vos exécuteurs d’intégration continue. N’activez ceci que si vous savez qu’ils peuvent tenir la charge."
+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 ""
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr "Mise à jour en cours"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Le service d’assistance (Service Desk) permet d’interagir avec vos utilisateurs (p. ex., pour offrir un support client) par courriel depuis GitLab"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,8 +31440,11 @@ msgstr "Utilisez une ligne par URI"
msgid "Use template"
msgstr "Utiliser ce modèle"
-msgid "Use the following registration token during setup:"
-msgstr "Utiliser le jeton d’inscription suivant pendant l’installation :"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "Utiliser vos paramètres de notification globaux"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr "Utilisateurs et utilisatrices"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 "Divers paramètres de registre de conteneur."
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr "Lorsque cette option est activée, les utilisateurs et utilisarices ne p
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 merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "Vous pouvez %{linkStart}afficher les données brutes%{linkEnd} à la place."
-
msgid "You can also create a project from the command line."
msgstr "Vous pouvez également créer un projet en ligne de commande."
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Vous pouvez facilement y contribuer en demandant à rejoindre ces groupes."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Vous pouvez facilement installer un Exécuteur sur un cluster Kubernetes. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "Vous ne pouvez modifier des fichiers que dans une branche"
@@ -32153,7 +33069,7 @@ msgstr "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif,
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr "Vous n’avez pas les autorisations"
@@ -32489,6 +33411,9 @@ msgstr "YouTube"
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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 "un utilisateur supprimé"
@@ -32857,9 +33791,15 @@ msgstr "nom de la branche"
msgid "by"
msgstr "par"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "jour"
msgstr[1] "jours"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr "Veuillez la restaurer ou utiliser une autre branche %{missingBranchName}
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}a diminué%{emphasisEnd} de %{memoryFrom}MO à %{memoryTo}MO"
@@ -33675,9 +34629,6 @@ msgstr "Fusionner"
msgid "mrWidget|Merge failed."
msgstr "La fusion a échoué."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr "Fusionner localement"
@@ -33747,8 +34698,8 @@ msgstr "Les modifications n’ont pas été fusionnées dans"
msgid "mrWidget|The changes will be merged into"
msgstr "Les modifications seront fusionnées dans"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr "Le pipeline de cette demande de fusion a échoué. Veuillez réexécuter la tâche ou pousser un nouveau commit pour résoudre le problème"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "La branche source HEAD a changé récemment. Veuillez recharger la page et vérifier les modifications avant d’effectuer la fusion"
@@ -33828,6 +34779,9 @@ msgstr "pour être fusionnée automatiquement lorsque le pipeline réussit"
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 0b1b80d59ff..1bcd85ca9e2 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16,7 +16,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
+msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author} &middot; updated %{issuable_updated}"
msgstr ""
msgid " %{start} to %{end}"
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -648,6 +653,12 @@ msgstr ""
msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
msgstr ""
+msgid "%{name} %{status}"
+msgstr ""
+
+msgid "%{name} (Busy)"
+msgstr ""
+
msgid "%{name} contained %{resultsString}"
msgstr ""
@@ -677,6 +688,15 @@ 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 "%{openOrClose} %{noteable}"
msgstr ""
@@ -724,9 +744,6 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
-msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
-msgstr ""
-
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -770,6 +787,9 @@ msgstr ""
msgid "%{spanStart}in%{spanEnd} %{errorFn}"
msgstr ""
+msgid "%{startDate} - %{endDate}"
+msgstr ""
+
msgid "%{start} to %{end}"
msgstr ""
@@ -971,6 +991,9 @@ msgstr ""
msgid "(+%{count}&nbsp;rules)"
msgstr ""
+msgid "(Group Managed Account)"
+msgstr ""
+
msgid "(No changes)"
msgstr ""
@@ -1010,9 +1033,6 @@ msgstr ""
msgid "+ %{numberOfHiddenAssignees} more"
msgstr ""
-msgid "+ %{numberOfHiddenReviewers} more"
-msgstr ""
-
msgid "+%d more"
msgid_plural "+%d more"
msgstr[0] ""
@@ -1106,6 +1126,11 @@ 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] ""
@@ -1253,6 +1278,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1328,6 +1356,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1337,9 +1368,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1349,6 +1377,9 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
+msgid "A title is required"
+msgstr ""
+
msgid "A user can only participate in a rotation once"
msgstr ""
@@ -1361,12 +1392,111 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
msgid "API Token"
msgstr ""
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API fuzzing target."
+msgstr ""
+
+msgid "APIFuzzing|Choose a method"
+msgstr ""
+
+msgid "APIFuzzing|Choose a profile"
+msgstr ""
+
+msgid "APIFuzzing|Code snippet for the API Fuzzing configuration"
+msgstr ""
+
+msgid "APIFuzzing|Copy code and open .gitlab-ci.yml file"
+msgstr ""
+
+msgid "APIFuzzing|Copy code only"
+msgstr ""
+
+msgid "APIFuzzing|Customize common API fuzzing settings to suit your requirements. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Enable authentication"
+msgstr ""
+
+msgid "APIFuzzing|Ex: $TestPassword"
+msgstr ""
+
+msgid "APIFuzzing|Ex: $TestUsername"
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgstr ""
+
+msgid "APIFuzzing|Generate code snippet"
+msgstr ""
+
+msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
+msgstr ""
+
+msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgstr ""
+
+msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgstr ""
+
+msgid "APIFuzzing|Make sure your credentials are secured"
+msgstr ""
+
+msgid "APIFuzzing|Password for basic authentication"
+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|The configuration could not be saved, please try again later."
+msgstr ""
+
+msgid "APIFuzzing|There are two ways to perform scans."
+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|Use this tool to generate API fuzzing configuration YAML to copy into your .gitlab-ci.yml file. This tool does not reflect or update your .gitlab-ci.yml file automatically."
+msgstr ""
+
+msgid "APIFuzzing|Username for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
+msgstr ""
+
+msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -1621,12 +1751,6 @@ msgstr ""
msgid "Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab."
msgstr ""
-msgid "Add a To Do"
-msgstr ""
-
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
msgstr ""
@@ -1705,6 +1829,9 @@ 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 domain"
msgstr ""
@@ -1897,6 +2024,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1927,9 +2057,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1963,7 +2090,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1987,6 +2114,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1996,7 +2126,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2026,9 +2162,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2044,12 +2177,21 @@ msgstr ""
msgid "AdminSettings|Integrations configured here will automatically apply to all projects on this instance."
msgstr ""
+msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
+msgstr ""
+
+msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
+msgstr ""
+
msgid "AdminSettings|Moved to integrations"
msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2065,6 +2207,9 @@ msgstr ""
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
+msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
+msgstr ""
+
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
msgstr ""
@@ -2074,6 +2219,9 @@ msgstr ""
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire."
+msgstr ""
+
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
@@ -2200,6 +2348,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2332,12 +2483,21 @@ msgstr ""
msgid "AdminUsers|Unblock user %{username}?"
msgstr ""
+msgid "AdminUsers|Unlock"
+msgstr ""
+
+msgid "AdminUsers|Unlock user %{username}?"
+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|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2395,6 +2555,9 @@ msgstr ""
msgid "Advanced Settings"
msgstr ""
+msgid "Advanced export options"
+msgstr ""
+
msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
@@ -2460,9 +2623,6 @@ msgstr ""
msgid "AlertManagement|Create incident"
msgstr ""
-msgid "AlertManagement|Critical"
-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 ""
@@ -2475,24 +2635,12 @@ msgstr ""
msgid "AlertManagement|Events"
msgstr ""
-msgid "AlertManagement|High"
-msgstr ""
-
msgid "AlertManagement|Incident"
msgstr ""
-msgid "AlertManagement|Info"
-msgstr ""
-
msgid "AlertManagement|Key"
msgstr ""
-msgid "AlertManagement|Low"
-msgstr ""
-
-msgid "AlertManagement|Medium"
-msgstr ""
-
msgid "AlertManagement|Metrics"
msgstr ""
@@ -2553,9 +2701,6 @@ 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 To-Do of the alert."
-msgstr ""
-
msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
msgstr ""
@@ -2565,6 +2710,9 @@ 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 ""
@@ -2574,9 +2722,6 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unknown"
-msgstr ""
-
msgid "AlertManagement|Value"
msgstr ""
@@ -2601,12 +2746,6 @@ 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 "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
-msgstr ""
-
-msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
-msgstr ""
-
msgid "AlertSettings|1. Select integration type"
msgstr ""
@@ -2766,9 +2905,6 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
-msgstr ""
-
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -2907,7 +3043,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2931,7 +3067,7 @@ msgstr ""
msgid "Allow subgroups to set up their own two-factor authentication rules"
msgstr ""
-msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
+msgid "Allow this key to push to this repository"
msgstr ""
msgid "Allow this secondary node to replicate content on Object Storage"
@@ -3039,9 +3175,15 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error occured while loading the notification settings. Please try again."
+msgstr ""
+
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3126,6 +3268,9 @@ 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 commits. Retry the search."
msgstr ""
@@ -3150,6 +3295,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching participants."
+msgstr ""
+
msgid "An error occurred while fetching pending comments"
msgstr ""
@@ -3258,6 +3406,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3315,7 +3466,7 @@ msgstr ""
msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while searching users."
msgstr ""
msgid "An error occurred while subscribing to notifications."
@@ -3372,6 +3523,9 @@ 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 ""
@@ -3710,7 +3864,7 @@ 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}"
+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?"
@@ -3904,9 +4058,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4100,6 +4251,9 @@ msgstr ""
msgid "Authenticating"
msgstr ""
+msgid "Authentication"
+msgstr ""
+
msgid "Authentication Failure"
msgstr ""
@@ -4181,7 +4335,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4430,25 +4584,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4457,10 +4611,16 @@ 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 Gold."
+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}."
@@ -4481,6 +4641,9 @@ 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 ""
@@ -4490,6 +4653,9 @@ 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 ""
@@ -4505,6 +4671,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4597,9 +4766,6 @@ 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 issues. Please reload the page."
msgstr ""
@@ -4621,6 +4787,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4687,12 +4856,6 @@ msgstr ""
msgid "Branch not loaded - %{branchId}"
msgstr ""
-msgid "BranchSwitcherPlaceholder|Search branches"
-msgstr ""
-
-msgid "BranchSwitcherTitle|Switch branch"
-msgstr ""
-
msgid "Branches"
msgstr ""
@@ -4816,6 +4979,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4855,16 +5021,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4873,6 +5048,9 @@ msgstr ""
msgid "BulkImport|Update of import statuses with realtime changes failed"
msgstr ""
+msgid "BulkImport|destination group cannot be part of the source group tree"
+msgstr ""
+
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr ""
@@ -4906,6 +5084,9 @@ msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "Busy"
+msgstr ""
+
msgid "Buy License"
msgstr ""
@@ -4966,12 +5147,35 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
msgid "CI/CD settings"
msgstr ""
+msgid "CICDAnalytics|%{percent}%{percentSymbol}"
+msgstr ""
+
+msgid "CICDAnalytics|All time"
+msgstr ""
+
+msgid "CICDAnalytics|Projects with releases"
+msgstr ""
+
+msgid "CICDAnalytics|Release"
+msgid_plural "CICDAnalytics|Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CICDAnalytics|Releases"
+msgstr ""
+
+msgid "CICDAnalytics|Something went wrong while fetching release statistics"
+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 ""
@@ -5260,18 +5464,15 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeActionLabel|Pick into branch"
-msgstr ""
-
-msgid "ChangeTypeActionLabel|Revert in branch"
-msgstr ""
-
msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5617,9 +5818,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5632,18 +5830,24 @@ msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
-msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
+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 ""
@@ -5797,12 +6001,24 @@ 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 ""
@@ -5992,6 +6208,9 @@ msgstr ""
msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
+msgid "ClusterAgent|This project is not included in the GitLab.com rollout for Kubernetes agent"
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7000,6 +7219,9 @@ msgstr ""
msgid "Code"
msgstr ""
+msgid "Code Coverage: %{coveragePercentage}"
+msgstr ""
+
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -7024,7 +7246,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7042,9 +7264,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7081,6 +7300,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7266,6 +7488,30 @@ 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 branch/tag"
+msgstr ""
+
+msgid "CompareRevisions|Tags"
+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 ""
@@ -7278,6 +7524,12 @@ msgstr ""
msgid "Compliance Dashboard"
msgstr ""
+msgid "Compliance framework"
+msgstr ""
+
+msgid "Compliance framework (optional)"
+msgstr ""
+
msgid "Compliance framework (optional)"
msgstr ""
@@ -7290,9 +7542,21 @@ msgstr ""
msgid "ComplianceFrameworks|All"
msgstr ""
+msgid "ComplianceFrameworks|Combines with the CI configuration at runtime."
+msgstr ""
+
+msgid "ComplianceFrameworks|Compliance pipeline configuration location (optional)"
+msgstr ""
+
+msgid "ComplianceFrameworks|Could not find this configuration location, please try a different location"
+msgstr ""
+
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
msgstr ""
+msgid "ComplianceFrameworks|Invalid format: it should follow the format [PATH].y(a)ml@[GROUP]/[PROJECT]"
+msgstr ""
+
msgid "ComplianceFrameworks|Once you have created a compliance framework it will appear here."
msgstr ""
@@ -7302,6 +7566,15 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
+msgid "ComplianceFrameworks|e.g. include-gitlab.ci.yml@group-name/project-name"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7374,6 +7647,9 @@ msgstr ""
msgid "Configure limit for issues created per minute by web and API requests."
msgstr ""
+msgid "Configure limit for notes created per minute by web and API requests."
+msgstr ""
+
msgid "Configure limits for Project/Group Import/Export."
msgstr ""
@@ -7428,9 +7704,6 @@ msgstr ""
msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
msgstr ""
-msgid "Congratulations! You have enabled Two-factor Authentication!"
-msgstr ""
-
msgid "Congratulations, your free trial is activated."
msgstr ""
@@ -7585,9 +7858,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7606,13 +7885,16 @@ msgstr ""
msgid "ContainerRegistry|Expiration policy will run in %{time}"
msgstr ""
-msgid "ContainerRegistry|Filter by name"
+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|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."
+msgid "ContainerRegistry|Image repository deletion failed"
msgstr ""
-msgid "ContainerRegistry|Image Repositories"
+msgid "ContainerRegistry|Image repository not found"
+msgstr ""
+
+msgid "ContainerRegistry|Image repository will be deleted"
msgstr ""
msgid "ContainerRegistry|Image tags"
@@ -7707,6 +7989,9 @@ 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 ""
@@ -7734,9 +8019,15 @@ 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 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 ""
@@ -7752,9 +8043,15 @@ 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 ""
@@ -7989,6 +8286,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8085,9 +8385,6 @@ msgstr ""
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
-msgid "Couldn't calculate number of %{issuables}."
-msgstr ""
-
msgid "Country"
msgstr ""
@@ -8138,9 +8435,6 @@ msgstr ""
msgid "Create a new branch"
msgstr ""
-msgid "Create a new deploy key for this project"
-msgstr ""
-
msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
msgstr ""
@@ -8204,6 +8498,9 @@ msgstr ""
msgid "Create iteration"
msgstr ""
+msgid "Create list"
+msgstr ""
+
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr ""
@@ -8219,6 +8516,9 @@ msgstr ""
msgid "Create new"
msgstr ""
+msgid "Create new %{name} by email"
+msgstr ""
+
msgid "Create new Value Stream"
msgstr ""
@@ -8291,12 +8591,24 @@ msgstr ""
msgid "CreateValueStreamForm|'%{name}' Value Stream created"
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|Default stages"
msgstr ""
@@ -8312,16 +8624,16 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
+msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Enter stage name"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Issue stage end"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8330,9 +8642,15 @@ 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 ""
@@ -8354,6 +8672,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8369,6 +8690,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8468,9 +8792,6 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
-msgstr ""
-
msgid "Current Project"
msgstr ""
@@ -8492,16 +8813,16 @@ msgstr ""
msgid "CurrentUser|Buy Pipeline minutes"
msgstr ""
-msgid "CurrentUser|One of your groups is running out"
+msgid "CurrentUser|Edit profile"
msgstr ""
-msgid "CurrentUser|Profile"
+msgid "CurrentUser|One of your groups is running out"
msgstr ""
-msgid "CurrentUser|Settings"
+msgid "CurrentUser|Preferences"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8510,9 +8831,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8528,6 +8846,9 @@ 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 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 %{notification_link}."
msgstr ""
@@ -8570,6 +8891,9 @@ msgstr ""
msgid "Customizable by an administrator."
msgstr ""
+msgid "Customizable by owners."
+msgstr ""
+
msgid "Customize colors"
msgstr ""
@@ -8585,7 +8909,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8767,7 +9091,7 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
-msgid "DAST Profiles"
+msgid "DAST Scans"
msgstr ""
msgid "DNS"
@@ -8797,7 +9121,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8923,7 +9247,13 @@ msgstr ""
msgid "DastProfiles|New site profile"
msgstr ""
-msgid "DastProfiles|No profiles created yet"
+msgid "DastProfiles|No scanner profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|No scans saved yet"
+msgstr ""
+
+msgid "DastProfiles|No site profiles created yet"
msgstr ""
msgid "DastProfiles|Not Validated"
@@ -8947,6 +9277,9 @@ msgstr ""
msgid "DastProfiles|Request headers"
msgstr ""
+msgid "DastProfiles|Run scan"
+msgstr ""
+
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@@ -9028,6 +9361,9 @@ 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 ""
@@ -9037,6 +9373,9 @@ msgstr ""
msgid "DastSiteValidation|Retry validation"
msgstr ""
+msgid "DastSiteValidation|Revoke validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9061,6 +9400,11 @@ 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|Validate"
msgstr ""
@@ -9079,6 +9423,9 @@ 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 ""
@@ -9100,6 +9447,9 @@ msgstr ""
msgid "Date range cannot exceed %{maxDateRange} days."
msgstr ""
+msgid "Date range is greater than %{quarter_days} days"
+msgstr ""
+
msgid "Day of month"
msgstr ""
@@ -9124,6 +9474,9 @@ msgstr ""
msgid "Dear Administrator,"
msgstr ""
+msgid "Debian package already exists in Distribution"
+msgstr ""
+
msgid "Debug"
msgstr ""
@@ -9142,9 +9495,6 @@ msgstr ""
msgid "Decompressed archive size validation failed."
msgstr ""
-msgid "Default Branch"
-msgstr ""
-
msgid "Default CI configuration path"
msgstr ""
@@ -9199,6 +9549,9 @@ msgstr ""
msgid "Define approval settings."
msgstr ""
+msgid "Define approval settings. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr ""
@@ -9331,7 +9684,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9484,13 +9837,10 @@ msgstr ""
msgid "Deploy key was successfully updated."
msgstr ""
-msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository"
+msgid "Deploy keys"
msgstr ""
-msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
-msgstr ""
-
-msgid "Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+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}."
@@ -9499,6 +9849,9 @@ 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|Freeze end"
msgstr ""
@@ -9508,15 +9861,12 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
msgstr ""
-msgid "DeployFreeze|You can specify deploy freezes using only %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
-msgstr ""
-
msgid "DeployKeys|+%{count} others"
msgstr ""
@@ -9541,6 +9891,9 @@ msgstr ""
msgid "DeployKeys|Expand %{count} other projects"
msgstr ""
+msgid "DeployKeys|Grant write permissions to this key"
+msgstr ""
+
msgid "DeployKeys|Loading deploy keys"
msgstr ""
@@ -9559,9 +9912,6 @@ msgstr ""
msgid "DeployKeys|Read access only"
msgstr ""
-msgid "DeployKeys|Write access allowed"
-msgstr ""
-
msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
msgstr ""
@@ -9571,19 +9921,19 @@ msgstr ""
msgid "DeployTokens|Add a deploy token"
msgstr ""
-msgid "DeployTokens|Allows read access to the package registry"
+msgid "DeployTokens|Allows read access to the package registry."
msgstr ""
-msgid "DeployTokens|Allows read-only access to the registry images"
+msgid "DeployTokens|Allows read-only access to registry images."
msgstr ""
-msgid "DeployTokens|Allows read-only access to the repository"
+msgid "DeployTokens|Allows read-only access to the repository."
msgstr ""
-msgid "DeployTokens|Allows write access to the package registry"
+msgid "DeployTokens|Allows write access to registry images."
msgstr ""
-msgid "DeployTokens|Allows write access to the registry images"
+msgid "DeployTokens|Allows write access to the package registry."
msgstr ""
msgid "DeployTokens|Copy deploy token"
@@ -9598,10 +9948,7 @@ msgstr ""
msgid "DeployTokens|Created"
msgstr ""
-msgid "DeployTokens|Default format is \"gitlab+deploy-token-{n}\". Enter custom username if you want to change it."
-msgstr ""
-
-msgid "DeployTokens|Deploy Tokens"
+msgid "DeployTokens|Deploy tokens"
msgstr ""
msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
@@ -9616,7 +9963,7 @@ msgstr ""
msgid "DeployTokens|Name"
msgstr ""
-msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgid "DeployTokens|Pick a name for your unique deploy token."
msgstr ""
msgid "DeployTokens|Revoke"
@@ -9637,10 +9984,16 @@ msgstr ""
msgid "DeployTokens|This action cannot be undone."
msgstr ""
-msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgid "DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}"
+msgstr ""
+
+msgid "DeployTokens|Unless you enter a date, the token does not expire."
+msgstr ""
+
+msgid "DeployTokens|Unless you specify a username, it is set to \"gitlab+deploy-token-{n}\"."
msgstr ""
-msgid "DeployTokens|Use this username as a login."
+msgid "DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered."
msgstr ""
msgid "DeployTokens|Username"
@@ -9649,7 +10002,7 @@ msgstr ""
msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
msgstr ""
-msgid "DeployTokens|Your New Deploy Token"
+msgid "DeployTokens|Your new Deploy Token username"
msgstr ""
msgid "DeployTokens|Your new group deploy token has been created."
@@ -9679,6 +10032,9 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|%{startDate} - %{endDate}"
+msgstr ""
+
msgid "DeploymentFrequencyCharts|Date"
msgstr ""
@@ -9688,16 +10044,10 @@ msgstr ""
msgid "DeploymentFrequencyCharts|Deployments charts"
msgstr ""
-msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
-msgstr ""
-
-msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
msgstr ""
-msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
msgstr ""
msgid "Deployments"
@@ -9925,18 +10275,6 @@ msgstr ""
msgid "DevOps Report"
msgstr ""
-msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
-msgstr ""
-
-msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
-msgstr ""
-
-msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
-msgstr ""
-
-msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
-msgstr ""
-
msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
@@ -9952,7 +10290,7 @@ msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
+msgid "DevopsAdoption|An error occured while removing the group. Please try again."
msgstr ""
msgid "DevopsAdoption|An error occured while saving the group. Please try again."
@@ -9961,7 +10299,7 @@ msgstr ""
msgid "DevopsAdoption|Approvals"
msgstr ""
-msgid "DevopsAdoption|Are you sure that you would like to delete %{name}?"
+msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
msgstr ""
msgid "DevopsAdoption|At least 1 MR opened"
@@ -9982,10 +10320,7 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete Group"
-msgstr ""
-
-msgid "DevopsAdoption|Delete Group"
+msgid "DevopsAdoption|Confirm remove Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
@@ -9994,18 +10329,12 @@ 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 Group"
-msgstr ""
-
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
-msgid "DevopsAdoption|Group data pending until the start of next month"
-msgstr ""
-
msgid "DevopsAdoption|Issues"
msgstr ""
@@ -10018,9 +10347,6 @@ msgstr ""
msgid "DevopsAdoption|My group"
msgstr ""
-msgid "DevopsAdoption|Name"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10030,6 +10356,12 @@ 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 ""
@@ -10563,6 +10895,9 @@ msgstr ""
msgid "Email Notification"
msgstr ""
+msgid "Email a new %{name} to this project"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -10635,12 +10970,6 @@ msgstr ""
msgid "EmailParticipantsWarning|and %{moreCount} more"
msgstr ""
-msgid "EmailToken|reset it"
-msgstr ""
-
-msgid "EmailToken|resetting..."
-msgstr ""
-
msgid "Emails"
msgstr ""
@@ -10869,6 +11198,9 @@ msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10923,19 +11255,13 @@ msgstr ""
msgid "Enter one or more user ID separated by commas"
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 issue description"
+msgid "Enter the %{name} description"
msgstr ""
-msgid "Enter the issue title"
+msgid "Enter the %{name} title"
msgstr ""
-msgid "Enter the merge request description"
-msgstr ""
-
-msgid "Enter the merge request title"
+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}."
@@ -10965,13 +11291,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11223,6 +11546,9 @@ msgstr ""
msgid "Epic"
msgstr ""
+msgid "Epic Boards"
+msgstr ""
+
msgid "Epic cannot be found."
msgstr ""
@@ -11247,6 +11573,12 @@ 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 ""
@@ -11262,6 +11594,9 @@ 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 ""
@@ -11271,12 +11606,21 @@ 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 ""
@@ -11292,6 +11636,9 @@ 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 ""
@@ -11658,6 +12005,9 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
+msgid "Ex: Example.com"
+msgstr ""
+
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -11673,6 +12023,9 @@ msgstr ""
msgid "Except policy:"
msgstr ""
+msgid "Exceptions"
+msgstr ""
+
msgid "Excess storage"
msgstr ""
@@ -11751,6 +12104,9 @@ msgstr ""
msgid "Expires at"
msgstr ""
+msgid "Expires at (optional)"
+msgstr ""
+
msgid "Expires in %{expires_at}"
msgstr ""
@@ -11784,6 +12140,9 @@ msgstr ""
msgid "Export"
msgstr ""
+msgid "Export %{requirementsCount} requirements?"
+msgstr ""
+
msgid "Export as CSV"
msgstr ""
@@ -11808,7 +12167,7 @@ msgstr ""
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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."
@@ -11907,10 +12266,10 @@ msgstr ""
msgid "Failed to create Merge Request. Please try again."
msgstr ""
-msgid "Failed to create To-Do for the design."
+msgid "Failed to create a branch for this issue. Please try again."
msgstr ""
-msgid "Failed to create a branch for this issue. Please try again."
+msgid "Failed to create a to-do item for the design."
msgstr ""
msgid "Failed to create framework"
@@ -11937,6 +12296,12 @@ 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 ""
@@ -11973,9 +12338,6 @@ msgstr ""
msgid "Failed to load group activity metrics. Please try again."
msgstr ""
-msgid "Failed to load groups & users."
-msgstr ""
-
msgid "Failed to load groups, users and deploy keys."
msgstr ""
@@ -12027,10 +12389,10 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to remove To-Do for the design."
+msgid "Failed to remove a Zoom meeting"
msgstr ""
-msgid "Failed to remove a Zoom meeting"
+msgid "Failed to remove a to-do item for the design."
msgstr ""
msgid "Failed to remove issue from board, please try again."
@@ -12075,7 +12437,7 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
-msgid "Failed to toggle To-Do for the design."
+msgid "Failed to toggle the to-do status for the design."
msgstr ""
msgid "Failed to update branch!"
@@ -12093,9 +12455,6 @@ msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to update tag!"
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -12126,9 +12485,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12635,6 +12991,12 @@ msgstr ""
msgid "Folder/%{name}"
msgstr ""
+msgid "Follow"
+msgstr ""
+
+msgid "Followed users"
+msgstr ""
+
msgid "Font Color"
msgstr ""
@@ -12650,10 +13012,16 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12677,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12728,7 +13090,7 @@ msgstr ""
msgid "Free Trial"
msgstr ""
-msgid "Free Trial of GitLab.com Gold"
+msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
msgid "Freeze end"
@@ -13187,9 +13549,6 @@ msgstr ""
msgid "Get started with GitLab"
msgstr ""
-msgid "Get started with a project that follows best practices for setting up GitLab for your own organization, including sample Issues, Merge Requests, and Milestones"
-msgstr ""
-
msgid "Get started with error tracking"
msgstr ""
@@ -13223,7 +13582,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13376,9 +13735,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13406,6 +13762,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13499,9 +13858,6 @@ msgstr ""
msgid "Go full screen"
msgstr ""
-msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
-msgstr ""
-
msgid "Go to Integrations"
msgstr ""
@@ -13652,6 +14008,9 @@ msgstr ""
msgid "Grant access"
msgstr ""
+msgid "Grant write permissions to this key"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -13700,6 +14059,9 @@ msgstr ""
msgid "Group URL"
msgstr ""
+msgid "Group Wikis"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
@@ -13760,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -14255,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14303,6 +14671,12 @@ msgstr ""
msgid "Guideline"
msgstr ""
+msgid "HAR (HTTP Archive)"
+msgstr ""
+
+msgid "HAR file path"
+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 ""
@@ -14384,9 +14758,6 @@ msgstr ""
msgid "Helps reduce request volume for protected paths"
msgstr ""
-msgid "Here are all your projects in your group, including the one you just created. To start, let’s take a look at your personalized learning project which will help you learn about GitLab at your own pace."
-msgstr ""
-
msgid "Here you will find recent merge request activity"
msgstr ""
@@ -14496,6 +14867,9 @@ msgstr ""
msgid "How do I configure runners?"
msgstr ""
+msgid "How do I generate it?"
+msgstr ""
+
msgid "How do I mirror repositories?"
msgstr ""
@@ -14610,9 +14984,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14628,12 +14999,6 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{linkEnd}"
msgstr ""
@@ -14895,10 +15260,352 @@ msgstr ""
msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
-msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In progress"
msgstr ""
-msgid "In progress"
+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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
msgstr ""
msgid "Incident"
@@ -15198,9 +15905,6 @@ msgstr ""
msgid "Install GitLab Runner on Kubernetes"
msgstr ""
-msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
-msgstr ""
-
msgid "Install on clusters"
msgstr ""
@@ -15221,9 +15925,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15362,6 +16078,9 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
@@ -15410,12 +16129,18 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
msgid "Integrations|This integration, and inheriting projects were reset."
msgstr ""
+msgid "Integrations|This requires mirroring your GitHub repository to this project. %{docs_link}"
+msgstr ""
+
msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
@@ -15605,9 +16330,42 @@ msgstr ""
msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} with the %{role} permission level."
+msgstr ""
+
+msgid "InviteEmail|As a developer, you have full access to projects, so you can take an idea from concept to production."
+msgstr ""
+
+msgid "InviteEmail|As a guest, you can view projects, leave comments, and create issues."
+msgstr ""
+
+msgid "InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production."
+msgstr ""
+
+msgid "InviteEmail|As a reporter, you can view projects and reports, and leave comments on issues."
+msgstr ""
+
+msgid "InviteEmail|As a user with minimal access, you can view the high-level group from the UI and API."
+msgstr ""
+
+msgid "InviteEmail|As an owner, you have full access to projects and can manage access to the group, including inviting new members."
+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|Projects can be used to host your code, track issues, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
+msgstr ""
+
+msgid "InviteEmail|What can I do with the %{role} permission level?"
+msgstr ""
+
+msgid "InviteEmail|What is a GitLab %{project_or_group}?"
+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 ""
@@ -15848,6 +16606,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15902,9 +16666,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -16049,24 +16810,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16082,24 +16861,45 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
msgid "JiraService|Jira workflow transition IDs"
msgstr ""
+msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}."
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
+msgid "JiraService|This issue is synchronized with Jira"
+msgstr ""
+
msgid "JiraService|Use a password for server version and an API token for cloud version"
msgstr ""
@@ -16175,6 +16975,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16214,7 +17017,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16319,6 +17122,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16364,9 +17170,6 @@ msgstr ""
msgid "Kubernetes error: %{error_code}"
msgstr ""
-msgid "Kubernetes popover"
-msgstr ""
-
msgid "LDAP"
msgstr ""
@@ -16510,6 +17313,9 @@ msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
+msgid "Last month"
+msgstr ""
+
msgid "Last name"
msgstr ""
@@ -16558,6 +17364,9 @@ msgstr ""
msgid "Last week"
msgstr ""
+msgid "Last year"
+msgstr ""
+
msgid "LastCommit|authored"
msgstr ""
@@ -16588,7 +17397,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,6 +17463,30 @@ msgstr ""
msgid "Learn more."
msgstr ""
+msgid "LearnGitLab|Add code owners"
+msgstr ""
+
+msgid "LearnGitLab|Create a repository"
+msgstr ""
+
+msgid "LearnGitLab|Enable require merge approvals"
+msgstr ""
+
+msgid "LearnGitLab|Invite your colleagues"
+msgstr ""
+
+msgid "LearnGitLab|Run a Security scan using CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Set-up CI/CD"
+msgstr ""
+
+msgid "LearnGitLab|Start a free trial of GitLab Gold"
+msgstr ""
+
+msgid "LearnGitLab|Submit a merge request (MR)"
+msgstr ""
+
msgid "Leave"
msgstr ""
@@ -16908,6 +17741,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16953,6 +17789,9 @@ msgstr ""
msgid "List of all merge commits"
msgstr ""
+msgid "List of users to be excluded from the limit"
+msgstr ""
+
msgid "List options"
msgstr ""
@@ -17106,6 +17945,12 @@ 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 ""
@@ -17130,9 +17975,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17175,6 +18017,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17346,6 +18191,9 @@ msgstr ""
msgid "Max file size is 200 KB."
msgstr ""
+msgid "Max requests per minute per user"
+msgstr ""
+
msgid "Max role"
msgstr ""
@@ -17367,12 +18215,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17454,6 +18305,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17595,6 +18449,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17679,6 +18536,9 @@ msgstr ""
msgid "Merge request (MR) approvals"
msgstr ""
+msgid "Merge request approval settings have been updated."
+msgstr ""
+
msgid "Merge request approvals"
msgstr ""
@@ -18532,6 +19392,9 @@ msgstr ""
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr ""
+msgid "Most relevant"
+msgstr ""
+
msgid "Most stars"
msgstr ""
@@ -18845,6 +19708,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19021,6 +19887,9 @@ msgstr ""
msgid "New User"
msgstr ""
+msgid "New application"
+msgstr ""
+
msgid "New branch"
msgstr ""
@@ -19093,7 +19962,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19210,6 +20079,12 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use."
+msgstr ""
+
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19273,6 +20148,9 @@ msgstr ""
msgid "No iteration"
msgstr ""
+msgid "No iterations found"
+msgstr ""
+
msgid "No iterations to show"
msgstr ""
@@ -19303,6 +20181,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19378,9 +20259,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19390,6 +20268,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19498,13 +20379,19 @@ msgstr ""
msgid "NoteForm|Note"
msgstr ""
+msgid "Notes Rate Limits"
+msgstr ""
+
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "Notes|Collapse replies"
msgstr ""
-msgid "Notes|Private comments are accessible by internal staff only"
+msgid "Notes|Confidential comments are only visible to project members"
+msgstr ""
+
+msgid "Notes|Make this comment confidential"
msgstr ""
msgid "Notes|Show all activity"
@@ -19519,6 +20406,9 @@ 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 ""
@@ -19849,10 +20739,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19864,9 +20754,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19918,10 +20817,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19959,7 +20858,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19995,7 +20894,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20004,6 +20903,12 @@ msgstr ""
msgid "Open"
msgstr ""
+msgid "Open API"
+msgstr ""
+
+msgid "Open API specification file path"
+msgstr ""
+
msgid "Open Selection"
msgstr ""
@@ -20016,10 +20921,10 @@ msgstr ""
msgid "Open errors"
msgstr ""
-msgid "Open in Xcode"
+msgid "Open in file view"
msgstr ""
-msgid "Open in file view"
+msgid "Open in your IDE"
msgstr ""
msgid "Open issues"
@@ -20103,9 +21008,6 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
@@ -20145,9 +21047,6 @@ msgstr ""
msgid "Outdent"
msgstr ""
-msgid "Overall Activity"
-msgstr ""
-
msgid "Overridden"
msgstr ""
@@ -20202,6 +21101,15 @@ msgstr ""
msgid "Package type must be PyPi"
msgstr ""
+msgid "Package type must be RubyGems"
+msgstr ""
+
+msgid "PackageRegistry|%{boldStart}Allow duplicates%{boldEnd} - Packages with the same name and version are accepted."
+msgstr ""
+
+msgid "PackageRegistry|%{boldStart}Do not allow duplicates%{boldEnd} - Packages with the same name and version are rejected."
+msgstr ""
+
msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
msgstr ""
@@ -20214,6 +21122,9 @@ msgstr ""
msgid "PackageRegistry|Add composer registry"
msgstr ""
+msgid "PackageRegistry|An error occurred while saving the settings"
+msgstr ""
+
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -20289,9 +21200,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20310,6 +21218,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20358,6 +21269,9 @@ msgstr ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr ""
+msgid "PackageRegistry|Packages can be published if their name or version matches this regex"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -20376,13 +21290,16 @@ msgstr ""
msgid "PackageRegistry|Remove package"
msgstr ""
-msgid "PackageRegistry|Sorry, your filter produced no results"
+msgid "PackageRegistry|Settings for Maven packages"
msgstr ""
-msgid "PackageRegistry|Source project located at %{link}"
+msgid "PackageRegistry|Settings saved successfully"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
+msgid "PackageRegistry|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
msgid "PackageRegistry|There are no other versions of this package."
@@ -20400,6 +21317,9 @@ 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 ""
@@ -20517,6 +21437,15 @@ msgstr ""
msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}"
msgstr ""
+msgid "Parameter `from` must be specified"
+msgstr ""
+
+msgid "Parameter `interval` must be one of (\"%{valid_intervals}\")"
+msgstr ""
+
+msgid "Parameter `to` is before the `from` date"
+msgstr ""
+
msgid "Parent"
msgstr ""
@@ -20538,6 +21467,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20571,10 +21503,10 @@ msgstr ""
msgid "Past due"
msgstr ""
-msgid "Paste a machine public key here. Read more about how to generate it"
+msgid "Paste a public key here."
msgstr ""
-msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}"
+msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
msgstr ""
msgid "Paste confidential epic link"
@@ -20652,6 +21584,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20820,15 +21755,6 @@ msgstr ""
msgid "Pipelines emails"
msgstr ""
-msgid "Pipelines for last month (%{oneMonthAgo} - %{today})"
-msgstr ""
-
-msgid "Pipelines for last week (%{oneWeekAgo} - %{today})"
-msgstr ""
-
-msgid "Pipelines for last year"
-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 ""
@@ -20856,10 +21782,10 @@ msgstr ""
msgid "Pipelines|Clear Runner Caches"
msgstr ""
-msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgid "Pipelines|Copy trigger token"
msgstr ""
-msgid "Pipelines|Copy trigger token"
+msgid "Pipelines|Could not load merged YAML content"
msgstr ""
msgid "Pipelines|Description"
@@ -20874,9 +21800,6 @@ msgstr ""
msgid "Pipelines|Get started with CI/CD"
msgstr ""
-msgid "Pipelines|Get started with Pipelines"
-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 ""
@@ -20901,6 +21824,9 @@ msgstr ""
msgid "Pipelines|Loading Pipelines"
msgstr ""
+msgid "Pipelines|Merged YAML is view only"
+msgstr ""
+
msgid "Pipelines|More Information"
msgstr ""
@@ -20973,6 +21899,9 @@ msgstr ""
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
+msgid "Pipelines|View merged YAML"
+msgstr ""
+
msgid "Pipelines|Visualize"
msgstr ""
@@ -21291,12 +22220,18 @@ 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 set a new password before proceeding."
msgstr ""
msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
+msgid "Please solve the captcha"
+msgstr ""
+
msgid "Please solve the reCAPTCHA"
msgstr ""
@@ -21357,21 +22292,39 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on your homepage."
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 mins 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 ""
@@ -21393,6 +22346,9 @@ msgstr ""
msgid "Preferences|Show whitespace changes in diffs"
msgstr ""
+msgid "Preferences|Sourcegraph"
+msgstr ""
+
msgid "Preferences|Syntax highlighting theme"
msgstr ""
@@ -21501,6 +22457,9 @@ 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 ""
@@ -21585,24 +22544,6 @@ msgstr ""
msgid "Profile Settings"
msgstr ""
-msgid "ProfilePreferences|Customize integrations with third party services."
-msgstr ""
-
-msgid "ProfilePreferences|Enable Gitpod integration"
-msgstr ""
-
-msgid "ProfilePreferences|Enable integrated code intelligence on code views"
-msgstr ""
-
-msgid "ProfilePreferences|Gitpod"
-msgstr ""
-
-msgid "ProfilePreferences|Integrations"
-msgstr ""
-
-msgid "ProfilePreferences|Sourcegraph"
-msgstr ""
-
msgid "ProfileSession|on"
msgstr ""
@@ -21726,12 +22667,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21777,9 +22721,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22062,6 +23003,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22221,10 +23165,7 @@ msgstr ""
msgid "ProjectSettings|Allow editing commit messages"
msgstr ""
-msgid "ProjectSettings|Allow users to make copies of your repository to a new project"
-msgstr ""
-
-msgid "ProjectSettings|Allow users to request access"
+msgid "ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets."
msgstr ""
msgid "ProjectSettings|Analytics"
@@ -22236,7 +23177,7 @@ msgstr ""
msgid "ProjectSettings|Badges"
msgstr ""
-msgid "ProjectSettings|Build, test, and deploy your changes"
+msgid "ProjectSettings|Build, test, and deploy your changes."
msgstr ""
msgid "ProjectSettings|Checkbox is visible and selected by default."
@@ -22251,6 +23192,9 @@ 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|Commit authors can edit commit messages on unprotected branches."
+msgstr ""
+
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr ""
@@ -22278,7 +23222,7 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
-msgid "ProjectSettings|Environments, logs, cluster management, and more"
+msgid "ProjectSettings|Environments, logs, cluster management, and more."
msgstr ""
msgid "ProjectSettings|Every merge creates a merge commit"
@@ -22287,7 +23231,7 @@ 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"
+msgid "ProjectSettings|Every project can have its own space to store its packages."
msgstr ""
msgid "ProjectSettings|Everyone"
@@ -22326,13 +23270,13 @@ msgstr ""
msgid "ProjectSettings|Issues"
msgstr ""
-msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
+msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
msgstr ""
-msgid "ProjectSettings|Lightweight issue tracking system for this project"
+msgid "ProjectSettings|Lightweight issue tracking system."
msgstr ""
-msgid "ProjectSettings|Manages large files such as audio, video, and graphics files"
+msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
msgid "ProjectSettings|Merge checks"
@@ -22368,13 +23312,16 @@ 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"
+msgid "ProjectSettings|Pages for project documentation."
msgstr ""
msgid "ProjectSettings|Pipelines"
@@ -22401,16 +23348,25 @@ msgstr ""
msgid "ProjectSettings|Require"
msgstr ""
+msgid "ProjectSettings|Require an associated issue from Jira"
+msgstr ""
+
msgid "ProjectSettings|Requirements"
msgstr ""
-msgid "ProjectSettings|Requirements management system for this project"
+msgid "ProjectSettings|Requirements management system."
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance"
+msgstr ""
+
+msgid "ProjectSettings|Security & Compliance for this project"
msgstr ""
msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
msgstr ""
-msgid "ProjectSettings|Share code pastes with others out of Git repository"
+msgid "ProjectSettings|Share code with others outside the project."
msgstr ""
msgid "ProjectSettings|Show default award emojis"
@@ -22434,7 +23390,7 @@ msgstr ""
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
msgstr ""
-msgid "ProjectSettings|Submit changes to be merged upstream"
+msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
msgid "ProjectSettings|The commit message used to apply merge request suggestions"
@@ -22458,52 +23414,49 @@ msgstr ""
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
msgstr ""
-msgid "ProjectSettings|This setting will override user notification preferences for all project members."
-msgstr ""
-
msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
msgstr ""
msgid "ProjectSettings|Transfer project"
msgstr ""
-msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgid "ProjectSettings|Users can copy the repository to a new project."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project"
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
-msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
+msgid "ProjectSettings|Users can request access"
msgstr ""
-msgid "ProjectSettings|View project analytics"
+msgid "ProjectSettings|View and edit files in this project."
msgstr ""
-msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
+msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access."
msgstr ""
-msgid "ProjectSettings|What are badges?"
+msgid "ProjectSettings|View project analytics."
msgstr ""
-msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
msgstr ""
-msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr ""
-msgid "ProjectSettings|When enabled, commit authors will be able to edit commit messages on unprotected branches."
+msgid "ProjectSettings|What are badges?"
msgstr ""
-msgid "ProjectSettings|When enabled, issues, merge requests, and snippets will always show thumbs-up and thumbs-down award emoji buttons."
+msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
msgstr ""
-msgid "ProjectSettings|Wiki"
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
msgstr ""
-msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab"
+msgid "ProjectSettings|Wiki"
msgstr ""
-msgid "ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics"
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
msgstr ""
msgid "ProjectTemplates|.NET Core"
@@ -22605,7 +23558,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22953,9 +23906,6 @@ msgstr ""
msgid "Promotions|Upgrade plan"
msgstr ""
-msgid "Promotions|Upgrade your plan"
-msgstr ""
-
msgid "Promotions|Upgrade your plan to activate Contribution Analytics."
msgstr ""
@@ -22998,9 +23948,6 @@ msgstr ""
msgid "Protected Environment"
msgstr ""
-msgid "Protected Environments"
-msgstr ""
-
msgid "Protected Paths"
msgstr ""
@@ -23013,6 +23960,9 @@ msgstr ""
msgid "Protected branches"
msgstr ""
+msgid "Protected environments"
+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 ""
@@ -23070,6 +24020,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23079,9 +24032,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23091,7 +24041,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,7 +24056,7 @@ msgstr ""
msgid "ProtectedEnvironment|Your environment has been unprotected"
msgstr ""
-msgid "Protip:"
+msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
msgid "Protocol"
@@ -23202,7 +24152,49 @@ msgstr ""
msgid "Push to create a project"
msgstr ""
-msgid "PushRule|Committer restriction"
+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"
@@ -23295,6 +24287,9 @@ msgstr ""
msgid "Re-authentication required"
msgstr ""
+msgid "Re-request review"
+msgstr ""
+
msgid "Re-verification interval"
msgstr ""
@@ -23331,6 +24326,9 @@ msgstr ""
msgid "Receive notifications about your own activity"
msgstr ""
+msgid "Receive product marketing emails"
+msgstr ""
+
msgid "Recent"
msgstr ""
@@ -23894,6 +24892,9 @@ msgstr ""
msgid "Reports|Actions"
msgstr ""
+msgid "Reports|Activity"
+msgstr ""
+
msgid "Reports|An error occured while loading report"
msgstr ""
@@ -23909,6 +24910,11 @@ 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] ""
@@ -23968,6 +24974,12 @@ msgstr ""
msgid "RepositoriesAnalytics|Average Coverage by Job"
msgstr ""
+msgid "RepositoriesAnalytics|Average coverage"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Average test coverage last 30 days"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -23995,6 +25007,12 @@ msgstr ""
msgid "RepositoriesAnalytics|Latest test coverage results"
msgstr ""
+msgid "RepositoriesAnalytics|No test coverage to display"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Overall activity"
+msgstr ""
+
msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
msgstr ""
@@ -24109,6 +25127,9 @@ msgstr ""
msgid "Requested design version does not exist."
msgstr ""
+msgid "Requested review"
+msgstr ""
+
msgid "Requested states are invalid"
msgstr ""
@@ -24221,9 +25242,6 @@ msgstr ""
msgid "Reset to project defaults"
msgstr ""
-msgid "Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
-msgstr ""
-
msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
msgstr ""
@@ -24516,21 +25534,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24552,24 +25585,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24660,9 +25708,6 @@ msgstr ""
msgid "Save Changes"
msgstr ""
-msgid "Save Push Rules"
-msgstr ""
-
msgid "Save application"
msgstr ""
@@ -24732,6 +25777,9 @@ msgstr ""
msgid "Scopes"
msgstr ""
+msgid "Scopes [Select 1 or more]"
+msgstr ""
+
msgid "Scopes can't be blank"
msgstr ""
@@ -24991,7 +26039,7 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
-msgid "Secret Token"
+msgid "Secret token"
msgstr ""
msgid "Security"
@@ -25009,6 +26057,9 @@ 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 ""
@@ -25033,12 +26084,18 @@ msgstr ""
msgid "SecurityConfiguration|Available for on-demand DAST"
msgstr ""
+msgid "SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}"
+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|Configure"
msgstr ""
+msgid "SecurityConfiguration|Configure via Merge Request"
+msgstr ""
+
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
@@ -25078,6 +26135,9 @@ msgstr ""
msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
+msgid "SecurityConfiguration|SAST merge request creation mutation failed"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -25114,6 +26174,9 @@ msgstr ""
msgid "SecurityReports|Add projects to your group"
msgstr ""
+msgid "SecurityReports|All"
+msgstr ""
+
msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
msgstr ""
@@ -25123,6 +26186,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
+msgid "SecurityReports|Create Jira issue"
+msgstr ""
+
msgid "SecurityReports|Create issue"
msgstr ""
@@ -25147,6 +26213,9 @@ msgstr ""
msgid "SecurityReports|Download results"
msgstr ""
+msgid "SecurityReports|Download scanned resources"
+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 ""
@@ -25168,9 +26237,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25195,6 +26261,12 @@ msgstr ""
msgid "SecurityReports|More information"
msgstr ""
+msgid "SecurityReports|No activity"
+msgstr ""
+
+msgid "SecurityReports|No longer detected"
+msgstr ""
+
msgid "SecurityReports|No vulnerabilities found"
msgstr ""
@@ -25234,9 +26306,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25246,13 +26315,13 @@ msgstr ""
msgid "SecurityReports|Severity"
msgstr ""
-msgid "SecurityReports|Sorry, your filter produced no results"
+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|Status"
+msgid "SecurityReports|Sorry, your filter produced no results"
msgstr ""
-msgid "SecurityReports|The rating \"unknown\" indicates that the underlying scanner doesn’t contain or provide a severity rating."
+msgid "SecurityReports|Status"
msgstr ""
msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
@@ -25323,6 +26392,9 @@ msgstr ""
msgid "SecurityReports|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly."
msgstr ""
+msgid "SecurityReports|With issues"
+msgstr ""
+
msgid "SecurityReports|Won't fix / Accept risk"
msgstr ""
@@ -25440,6 +26512,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25467,7 +26542,7 @@ msgstr ""
msgid "Select projects"
msgstr ""
-msgid "Select required regulatory standard"
+msgid "Select required regulatory standard."
msgstr ""
msgid "Select reviewer(s)"
@@ -25497,9 +26572,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25782,6 +26854,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -26278,9 +27353,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26686,9 +27758,6 @@ msgstr ""
msgid "SortOptions|Recently starred"
msgstr ""
-msgid "SortOptions|Relevant"
-msgstr ""
-
msgid "SortOptions|Size"
msgstr ""
@@ -26821,9 +27890,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26878,7 +27944,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26920,7 +27986,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27133,6 +28199,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27388,67 +28457,67 @@ msgstr ""
msgid "Suggested solutions help link"
msgstr ""
-msgid "SuggestedColors|Bright green"
+msgid "SuggestedColors|Aztec Gold"
msgstr ""
-msgid "SuggestedColors|Dark grayish cyan"
+msgid "SuggestedColors|Blue"
msgstr ""
-msgid "SuggestedColors|Dark moderate blue"
+msgid "SuggestedColors|Blue-gray"
msgstr ""
-msgid "SuggestedColors|Dark moderate orange"
+msgid "SuggestedColors|Carrot orange"
msgstr ""
-msgid "SuggestedColors|Dark moderate pink"
+msgid "SuggestedColors|Champagne"
msgstr ""
-msgid "SuggestedColors|Dark moderate violet"
+msgid "SuggestedColors|Charcoal grey"
msgstr ""
-msgid "SuggestedColors|Feijoa"
+msgid "SuggestedColors|Crimson"
msgstr ""
-msgid "SuggestedColors|Lime green"
+msgid "SuggestedColors|Dark coral"
msgstr ""
-msgid "SuggestedColors|Moderate blue"
+msgid "SuggestedColors|Dark green"
msgstr ""
-msgid "SuggestedColors|Pure red"
+msgid "SuggestedColors|Dark sea green"
msgstr ""
-msgid "SuggestedColors|Slightly desaturated blue"
+msgid "SuggestedColors|Dark violet"
msgstr ""
-msgid "SuggestedColors|Slightly desaturated green"
+msgid "SuggestedColors|Deep violet"
msgstr ""
-msgid "SuggestedColors|Soft orange"
+msgid "SuggestedColors|Gray"
msgstr ""
-msgid "SuggestedColors|Soft red"
+msgid "SuggestedColors|Green screen"
msgstr ""
-msgid "SuggestedColors|Strong pink"
+msgid "SuggestedColors|Green-cyan"
msgstr ""
-msgid "SuggestedColors|Strong red"
+msgid "SuggestedColors|Lavendar"
msgstr ""
-msgid "SuggestedColors|Strong yellow"
+msgid "SuggestedColors|Magenta-pink"
msgstr ""
-msgid "SuggestedColors|UA blue"
+msgid "SuggestedColors|Medium sea green"
msgstr ""
-msgid "SuggestedColors|Very dark desaturated blue"
+msgid "SuggestedColors|Red"
msgstr ""
-msgid "SuggestedColors|Very dark lime green"
+msgid "SuggestedColors|Rose red"
msgstr ""
-msgid "SuggestedColors|Very pale orange"
+msgid "SuggestedColors|Titanium yellow"
msgstr ""
msgid "Suggestion is not applicable as the suggestion was not found."
@@ -27535,6 +28604,12 @@ 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 ""
@@ -27544,7 +28619,7 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
-msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+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)"
@@ -27739,6 +28814,9 @@ msgstr ""
msgid "Terraform"
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] ""
@@ -27752,15 +28830,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27797,6 +28878,9 @@ msgstr ""
msgid "Terraform|Locked by %{user} %{timeAgo}"
msgstr ""
+msgid "Terraform|Locking state"
+msgstr ""
+
msgid "Terraform|Name"
msgstr ""
@@ -27809,16 +28893,19 @@ 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|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27830,6 +28917,9 @@ 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\twill remain intact, only the state file with all its versions are to be removed. This action is non-revertible."
msgstr ""
@@ -27877,9 +28967,6 @@ msgstr ""
msgid "TestCases|Something went wrong while creating a test case."
msgstr ""
-msgid "TestCases|Something went wrong while fetching count of test cases."
-msgstr ""
-
msgid "TestCases|Something went wrong while fetching test case."
msgstr ""
@@ -28223,6 +29310,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28238,7 +29334,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28256,9 +29355,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28304,6 +29400,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28331,9 +29430,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28361,6 +29457,9 @@ msgstr ""
msgid "The status of the table below only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
msgstr ""
+msgid "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 ""
@@ -28388,7 +29487,7 @@ 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 an approval"
+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"
@@ -28445,6 +29544,9 @@ 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 ""
@@ -28469,6 +29571,9 @@ msgstr ""
msgid "There are no matching files"
msgstr ""
+msgid "There are no open epics"
+msgstr ""
+
msgid "There are no open issues"
msgstr ""
@@ -28499,10 +29604,10 @@ msgstr ""
msgid "There is a halted Elasticsearch migration"
msgstr ""
-msgid "There is already a To-Do for this design."
+msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is already a repository with that name on disk"
+msgid "There is already a to-do item for this design."
msgstr ""
msgid "There is no chart data available."
@@ -28544,7 +29649,7 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
-msgid "There was a problem fetching the keep latest artifact setting."
+msgid "There was a problem fetching the keep latest artifacts setting."
msgstr ""
msgid "There was a problem fetching users."
@@ -28559,7 +29664,7 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
-msgid "There was a problem updating the keep latest artifact setting."
+msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
msgid "There was an error %{message} todo."
@@ -28631,6 +29736,9 @@ msgstr ""
msgid "There was an error importing the Jira project."
msgstr ""
+msgid "There was an error loading merge request approval settings."
+msgstr ""
+
msgid "There was an error loading users activity calendar."
msgstr ""
@@ -28673,6 +29781,9 @@ msgstr ""
msgid "There was an error trying to validate your query"
msgstr ""
+msgid "There was an error updating merge request approval settings."
+msgstr ""
+
msgid "There was an error updating the Geo Settings"
msgstr ""
@@ -28715,6 +29826,9 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 ""
@@ -28730,7 +29844,10 @@ msgstr ""
msgid "These runners are specific to this project."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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"
@@ -28775,34 +29892,22 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
-msgid "This URL will be triggered for each branch updated to the repository"
-msgstr ""
-
-msgid "This URL will be triggered when a merge request is created/updated/merged"
-msgstr ""
-
-msgid "This URL will be triggered when a new tag is pushed to the repository"
-msgstr ""
-
-msgid "This URL will be triggered when repository is updated"
-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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28904,10 +30009,10 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
+msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
-msgid "This epic does not exist or you don't have sufficient permission."
+msgid "This feature is disabled at the instance level."
msgstr ""
msgid "This feature requires local storage to be enabled"
@@ -28958,6 +30063,12 @@ 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 gets ahold of it can create issues or merge requests as if they were you. You should %{resetLinkStart}reset it%{resetLinkEnd} if that ever happens."
+msgstr ""
+
msgid "This is a security log of important events involving your account."
msgstr ""
@@ -29237,9 +30348,6 @@ msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29258,6 +30366,9 @@ msgstr ""
msgid "Threat Monitoring"
msgstr ""
+msgid "ThreatMonitoring|Alert Details"
+msgstr ""
+
msgid "ThreatMonitoring|Alerts"
msgstr ""
@@ -29667,7 +30778,7 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To ensure no loss of personal content, an Individual User should create a separate account under their own personal email address, not tied to the Enterprise email domain or name-space."
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
msgstr ""
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
@@ -29715,6 +30826,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29730,7 +30844,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29763,18 +30877,12 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-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"
-msgstr ""
-
msgid "To-Do List"
msgstr ""
@@ -29784,6 +30892,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29811,6 +30922,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29829,18 +30943,15 @@ msgstr ""
msgid "Toggle thread"
msgstr ""
-msgid "ToggleButton|Toggle Status: OFF"
-msgstr ""
-
-msgid "ToggleButton|Toggle Status: ON"
-msgstr ""
-
msgid "Toggled :%{name}: emoji award."
msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29931,6 +31042,9 @@ 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 ""
@@ -29987,7 +31101,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29999,7 +31113,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30026,7 +31140,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30041,7 +31155,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30050,6 +31164,9 @@ 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 ""
@@ -30086,12 +31203,18 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
+msgid "Trusted"
+msgstr ""
+
msgid "Try again"
msgstr ""
@@ -30194,6 +31317,21 @@ 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 ""
@@ -30302,7 +31440,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30326,6 +31464,9 @@ msgstr ""
msgid "Unexpected error"
msgstr ""
+msgid "Unfollow"
+msgstr ""
+
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
@@ -30497,9 +31638,6 @@ msgstr ""
msgid "Update failed"
msgstr ""
-msgid "Update failed. Please try again."
-msgstr ""
-
msgid "Update it"
msgstr ""
@@ -30560,6 +31698,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Upgrade offers available!"
+msgstr ""
+
msgid "Upgrade your plan"
msgstr ""
@@ -30674,6 +31815,12 @@ 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|Packages"
msgstr ""
@@ -30779,12 +31926,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30800,7 +31953,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use this token to validate received payloads"
+msgid "Use this token to validate received payloads."
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30968,6 +32124,12 @@ 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 ""
@@ -31010,6 +32172,9 @@ 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 ""
@@ -31025,6 +32190,9 @@ msgstr ""
msgid "UserProfile|This user is blocked"
msgstr ""
+msgid "UserProfile|This user isn't following other users."
+msgstr ""
+
msgid "UserProfile|Unconfirmed user"
msgstr ""
@@ -31034,9 +32202,15 @@ 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 ""
@@ -31073,13 +32247,10 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
@@ -31112,6 +32283,9 @@ msgstr ""
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
+msgid "Using additional formats requires starting the companion containers. Make sure that all %{kroki_images} are running."
+msgstr ""
+
msgid "Using required encryption strategy when encrypted field is missing!"
msgstr ""
@@ -31172,6 +32346,15 @@ 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 ""
@@ -31341,6 +32524,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31380,6 +32566,9 @@ msgstr ""
msgid "Visit settings page"
msgstr ""
+msgid "Visual Studio Code"
+msgstr ""
+
msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
msgstr ""
@@ -31446,6 +32635,9 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
+msgid "VulnerabilityManagement, Fetching linked Jira issues"
+msgstr ""
+
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -31467,15 +32659,27 @@ msgstr ""
msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
msgstr ""
+msgid "VulnerabilityManagement|Create Jira issue"
+msgstr ""
+
msgid "VulnerabilityManagement|Detected"
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
+msgid "VulnerabilityManagement|Read more about related issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Related Jira issues"
+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 ""
@@ -31674,6 +32878,9 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
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 that you buy more Pipeline minutes to avoid any interruption of service."
msgstr ""
@@ -31719,6 +32926,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31728,6 +32941,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31743,10 +32959,10 @@ msgstr ""
msgid "Webhooks|Comments"
msgstr ""
-msgid "Webhooks|Confidential Comments"
+msgid "Webhooks|Confidential comments"
msgstr ""
-msgid "Webhooks|Confidential Issues events"
+msgid "Webhooks|Confidential issues events"
msgstr ""
msgid "Webhooks|Deployment events"
@@ -31755,7 +32971,7 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
-msgid "Webhooks|Feature Flag events"
+msgid "Webhooks|Feature flag events"
msgstr ""
msgid "Webhooks|Issues events"
@@ -31782,64 +32998,73 @@ msgstr ""
msgid "Webhooks|SSL verification"
msgstr ""
-msgid "Webhooks|Secret Token"
+msgid "Webhooks|Secret token"
+msgstr ""
+
+msgid "Webhooks|Subgroup events"
msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
-msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgid "Webhooks|Trigger"
msgstr ""
-msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
+msgid "Webhooks|URL"
msgstr ""
-msgid "Webhooks|This URL is triggered when a release is created/updated"
+msgid "Webhooks|URL is triggered by a push to the repository"
msgstr ""
-msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgid "Webhooks|URL is triggered when a confidential issue is created, updated, or merged"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a group member is created/updated/removed"
+msgid "Webhooks|URL is triggered when a feature flag is turned on or off"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgid "Webhooks|URL is triggered when a group member is created, updated, or removed"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged"
msgstr ""
-msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgid "Webhooks|URL is triggered when a new tag is pushed to the repository"
msgstr ""
-msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgid "Webhooks|URL is triggered when a release is created or updated"
msgstr ""
-msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgid "Webhooks|URL is triggered when a subgroup is created or removed"
msgstr ""
-msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgid "Webhooks|URL is triggered when a wiki page is created or updated"
msgstr ""
-msgid "Webhooks|This URL will be triggered when the job status changes"
+msgid "Webhooks|URL is triggered when an issue is created, updated, or merged"
msgstr ""
-msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgid "Webhooks|URL is triggered when someone adds a comment"
msgstr ""
-msgid "Webhooks|Trigger"
+msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue"
msgstr ""
-msgid "Webhooks|URL"
+msgid "Webhooks|URL is triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|URL is triggered when the pipeline status changes"
msgstr ""
-msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgid "Webhooks|URL must be percent-encoded if neccessary."
msgstr ""
-msgid "Webhooks|Wiki Page events"
+msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki page events"
msgstr ""
msgid "Wednesday"
@@ -31863,10 +33088,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31893,7 +33118,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31914,6 +33139,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32168,9 +33396,6 @@ msgstr ""
msgid "Write a comment…"
msgstr ""
-msgid "Write access allowed"
-msgstr ""
-
msgid "Write milestone description..."
msgstr ""
@@ -32180,6 +33405,9 @@ msgstr ""
msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
msgstr ""
+msgid "Xcode"
+msgstr ""
+
msgid "YYYY-MM-DD"
msgstr ""
@@ -32285,9 +33513,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32312,6 +33537,9 @@ 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 ""
@@ -32459,6 +33687,9 @@ msgstr ""
msgid "You do not have any subscriptions yet"
msgstr ""
+msgid "You do not have permission to access deployment frequencies"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -32549,6 +33780,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32573,6 +33807,9 @@ 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 a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
@@ -32786,13 +34023,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33035,6 +34272,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33121,6 +34364,9 @@ msgstr ""
msgid "by"
msgstr ""
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
@@ -33262,6 +34508,9 @@ 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 ""
@@ -33437,6 +34686,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33478,8 +34730,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33537,6 +34791,9 @@ 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 ""
@@ -33819,6 +35076,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33945,9 +35208,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34017,7 +35277,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34098,6 +35358,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a Debian package"
+msgstr ""
+
msgid "must be a boolean value"
msgstr ""
@@ -34447,6 +35710,12 @@ 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 ""
@@ -34465,12 +35734,18 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
msgid "two-factor authentication settings"
msgstr ""
+msgid "type must be Debian"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -34498,9 +35773,6 @@ msgstr ""
msgid "username"
msgstr ""
-msgid "uses Kubernetes clusters to deploy your code!"
-msgstr ""
-
msgid "v%{version} published %{timeAgo}"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index d1c90435d50..8e56251aa50 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:05\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index f04e733d4d4..12eb4e397b4 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:57\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,6 +252,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -486,10 +493,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1183,6 +1196,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1190,10 +1206,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1431,6 +1444,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1801,15 +1826,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2068,6 +2093,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2098,9 +2126,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2167,7 +2195,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2398,6 +2435,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2506,6 +2546,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2936,7 +2979,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3422,6 +3474,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3593,6 +3648,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3707,12 +3765,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,7 +3937,7 @@ 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}"
+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?"
@@ -3976,15 +4028,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4054,7 +4109,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4335,9 +4387,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4362,7 +4411,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4461,16 +4510,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4611,25 +4660,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4638,10 +4687,16 @@ 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 Gold."
+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}."
@@ -4662,6 +4717,9 @@ 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 ""
@@ -4671,6 +4729,9 @@ 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 ""
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4996,6 +5063,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -5095,6 +5174,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5140,6 +5225,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5782,9 +5882,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ 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 ""
@@ -6010,7 +6122,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8463,12 +8614,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8637,10 +8809,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8667,7 +8839,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,7 +10457,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,7 +11109,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ 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 ""
@@ -11393,6 +11634,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12864,7 +13120,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13326,7 +13585,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,10 +15903,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15642,6 +16321,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,7 +16984,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16335,6 +17059,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,7 +17279,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 ""
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17477,9 +18213,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18715,9 +19445,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,7 +19913,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20813,6 +21573,9 @@ 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 ""
@@ -20981,9 +21744,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21854,9 +22620,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22139,6 +22902,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23493,12 +24271,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,7 +25076,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24414,6 +25199,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24463,6 +25251,9 @@ 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 ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24725,6 +25540,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,7 +26329,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,7 +27717,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26986,7 +27798,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27031,7 +27840,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27244,6 +28053,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28350,7 +29183,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28416,6 +29249,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,7 +29708,7 @@ 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."
+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."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29004,13 +29864,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29040,6 +29903,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 ""
@@ -29208,7 +30086,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ 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 ""
@@ -29738,6 +30616,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,7 +30682,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,7 +31271,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30633,7 +31529,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,7 +31778,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31946,10 +32866,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32391,9 +33314,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ 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 ""
@@ -32865,13 +33794,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34031,9 +34991,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34103,7 +35060,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34184,6 +35141,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index ce58ff867e0..3b542585576 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:07\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index e0adc702017..1ceafce33a2 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:06\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -226,6 +226,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -430,10 +436,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -787,6 +793,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -985,6 +994,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1108,16 +1120,16 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1339,6 +1351,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1357,6 +1372,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1408,6 +1429,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1417,9 +1441,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1429,7 +1450,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1444,6 +1465,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1708,15 +1732,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1975,6 +1999,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2005,9 +2032,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2041,7 +2065,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2065,6 +2089,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2074,7 +2101,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2104,9 +2137,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2128,6 +2158,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2278,6 +2311,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2305,6 +2341,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2413,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2842,7 +2884,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2983,7 +3025,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3034,6 +3076,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3085,6 +3130,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3328,6 +3379,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3499,6 +3553,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3613,12 +3670,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3787,7 +3838,7 @@ 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}"
+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?"
@@ -3877,15 +3928,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3955,7 +4009,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3979,9 +4033,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4234,9 +4285,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4261,7 +4309,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4360,16 +4408,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4510,25 +4558,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4537,10 +4585,16 @@ 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 Gold."
+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}."
@@ -4561,6 +4615,9 @@ 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 ""
@@ -4570,6 +4627,9 @@ 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 ""
@@ -4585,6 +4645,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4672,10 +4735,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4699,6 +4762,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4894,6 +4960,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4933,16 +5002,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4993,6 +5071,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5002,6 +5083,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5038,6 +5122,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5146,9 +5233,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5299,6 +5383,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5341,6 +5431,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5365,6 +5458,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5467,6 +5563,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5680,9 +5779,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5701,6 +5797,9 @@ 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 ""
@@ -5860,12 +5959,24 @@ 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 ""
@@ -5908,7 +6019,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7087,7 +7198,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7105,9 +7216,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7144,6 +7252,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7366,6 +7477,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7540,9 +7657,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7654,9 +7768,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7684,6 +7804,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7777,6 +7906,9 @@ 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 ""
@@ -7804,9 +7936,15 @@ 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 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 ""
@@ -7822,9 +7960,15 @@ 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 ""
@@ -8002,6 +8146,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8056,6 +8203,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8356,12 +8506,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8377,16 +8539,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8398,9 +8557,15 @@ 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 ""
@@ -8416,6 +8581,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8431,6 +8599,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8530,10 +8701,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8560,7 +8731,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8569,9 +8740,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8644,7 +8812,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8857,7 +9025,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8887,6 +9055,12 @@ 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 ""
@@ -8899,6 +9073,9 @@ 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 ""
@@ -8911,6 +9088,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8926,6 +9106,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8950,7 +9133,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8962,9 +9145,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9004,6 +9184,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9013,6 +9199,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9022,9 +9211,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9040,6 +9235,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9049,6 +9247,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9061,6 +9262,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9355,7 +9559,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9709,6 +9913,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9892,7 +10123,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9943,25 +10174,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9988,22 +10219,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10012,24 +10240,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10051,18 +10279,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10120,7 +10342,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10414,9 +10636,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10645,6 +10864,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10711,6 +10939,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10720,6 +10951,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10759,7 +10993,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10798,7 +11032,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10861,15 +11095,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10966,13 +11206,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11263,6 +11500,9 @@ 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 ""
@@ -11278,6 +11518,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11668,9 +11914,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11806,15 +12049,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11938,6 +12187,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12121,9 +12373,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12640,10 +12889,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12667,12 +12928,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12748,7 +13003,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12796,6 +13051,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13210,7 +13468,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13240,9 +13498,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13279,6 +13534,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13363,9 +13621,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13393,6 +13648,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13666,9 +13924,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13684,9 +13939,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13738,6 +13990,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13747,6 +14005,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13771,6 +14032,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14170,9 +14437,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14239,6 +14503,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14479,6 +14746,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14590,9 +14863,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14608,18 +14878,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14869,15 +15136,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15013,9 +15625,39 @@ 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 ""
@@ -15097,7 +15739,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15139,10 +15781,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15169,9 +15811,21 @@ msgstr[2] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15277,6 +15931,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15307,6 +15964,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15316,12 +15979,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,6 +16015,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15373,6 +16045,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15460,6 +16135,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15520,6 +16198,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15775,6 +16456,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15829,9 +16516,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15871,6 +16555,9 @@ 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 ""
@@ -15973,24 +16660,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16006,6 +16711,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16018,9 +16726,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16099,6 +16819,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16138,7 +16861,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16213,6 +16936,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16240,6 +16966,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16426,7 +17155,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16510,7 +17239,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16531,9 +17260,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16840,6 +17566,9 @@ msgstr[2] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17014,9 +17743,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17041,6 +17767,12 @@ 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 ""
@@ -17065,9 +17797,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17110,6 +17839,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17302,12 +18034,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17347,9 +18082,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17392,6 +18124,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17419,9 +18154,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17440,9 +18172,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17539,6 +18268,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17632,6 +18364,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17713,9 +18448,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17782,15 +18514,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18190,6 +18916,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18361,6 +19090,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18412,9 +19144,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18583,9 +19312,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18721,12 +19447,6 @@ 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 ""
@@ -18745,6 +19465,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18799,6 +19525,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19048,7 +19777,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19165,6 +19894,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19258,6 +19990,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19333,9 +20068,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19345,6 +20077,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19720,6 +20455,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19729,12 +20467,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19795,10 +20539,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19810,9 +20554,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19864,10 +20617,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19906,7 +20659,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19924,9 +20677,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19945,7 +20695,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20053,15 +20803,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20236,9 +20986,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20257,6 +21004,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20329,9 +21079,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20347,6 +21094,9 @@ 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 ""
@@ -20485,6 +21235,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20599,6 +21352,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20665,6 +21421,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20677,6 +21436,9 @@ 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 ""
@@ -20845,9 +21607,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20860,9 +21619,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20884,6 +21640,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20998,6 +21757,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21667,12 +22429,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21718,9 +22483,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22003,6 +22765,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22420,6 +23185,9 @@ 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|What are badges?"
msgstr ""
@@ -22543,7 +23311,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22918,6 +23686,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22966,6 +23737,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23002,6 +23776,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23011,9 +23788,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23023,7 +23797,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23242,6 +24016,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23356,12 +24133,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23389,21 +24175,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23500,9 +24274,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23596,6 +24367,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23845,6 +24619,12 @@ 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] ""
+msgstr[2] ""
+
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] ""
@@ -24013,6 +24793,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24148,7 +24931,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24271,6 +25054,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24319,6 +25105,9 @@ 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 ""
@@ -24361,6 +25150,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24406,6 +25198,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24427,21 +25222,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24454,21 +25237,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24490,24 +25288,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24580,6 +25393,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24937,6 +25753,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24952,6 +25771,9 @@ 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 ""
@@ -25111,9 +25933,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25177,9 +25996,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25288,13 +26104,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25354,7 +26170,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25384,6 +26200,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25441,9 +26260,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25726,6 +26542,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25765,10 +26584,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25783,9 +26602,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25930,9 +26746,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25987,6 +26800,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26227,9 +27043,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26374,6 +27187,9 @@ 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 %{listType} list"
msgstr ""
@@ -26740,7 +27556,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26749,9 +27565,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26770,9 +27583,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26827,7 +27637,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26860,9 +27670,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26872,7 +27679,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26899,15 +27706,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27085,6 +27892,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27496,6 +28306,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27520,9 +28333,15 @@ 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 ""
@@ -27697,15 +28516,18 @@ msgstr[2] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27760,10 +28582,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28096,9 +28918,6 @@ msgstr[2] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28153,6 +28972,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28171,6 +28993,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28186,7 +29017,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28204,9 +29038,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28252,6 +29083,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28279,9 +29113,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28336,7 +29167,7 @@ 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 an approval"
+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"
@@ -28444,7 +29275,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28492,6 +29323,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28504,6 +29338,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28657,16 +29494,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28696,7 +29542,7 @@ 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."
+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."
@@ -28711,22 +29557,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28741,13 +29599,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28825,9 +29686,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28840,13 +29698,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28876,6 +29737,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28999,6 +29863,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29008,6 +29875,15 @@ 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 ""
@@ -29044,7 +29920,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29101,6 +29977,9 @@ 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 ""
@@ -29134,18 +30013,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29557,6 +30430,9 @@ 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 ""
@@ -29572,6 +30448,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29581,6 +30460,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29614,6 +30496,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29629,7 +30514,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29647,12 +30532,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29668,9 +30547,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29689,6 +30565,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29716,6 +30595,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29746,6 +30628,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29836,6 +30721,9 @@ 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 ""
@@ -29893,7 +30781,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29905,7 +30793,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29932,7 +30820,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29947,7 +30835,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29956,6 +30844,9 @@ 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 ""
@@ -29965,7 +30856,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29992,7 +30883,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30208,7 +31102,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30466,7 +31360,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30487,6 +31381,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30685,12 +31582,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30706,7 +31609,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30820,7 +31726,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30979,21 +31885,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31057,9 +31957,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31084,6 +31981,15 @@ 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 ""
@@ -31255,6 +32161,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31633,6 +32542,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31642,6 +32557,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31777,10 +32695,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31798,7 +32716,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31807,7 +32725,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31828,6 +32746,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31837,6 +32758,9 @@ msgstr[2] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32197,9 +33121,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32221,9 +33142,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32248,9 +33166,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32272,6 +33187,9 @@ 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 ""
@@ -32287,15 +33205,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32323,7 +33241,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32464,6 +33382,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32476,6 +33397,9 @@ 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 no permissions"
msgstr ""
@@ -32659,6 +33583,9 @@ 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 ""
@@ -32695,13 +33622,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32857,6 +33784,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32941,6 +33871,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33028,9 +33964,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33343,6 +34285,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33385,8 +34330,11 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33481,6 +34429,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33727,6 +34678,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33853,9 +34810,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33925,7 +34879,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34234,6 +35191,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34372,6 +35332,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index 58fbc6434c3..d37326a1551 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
new file mode 100644
index 00000000000..85f9db67250
--- /dev/null
+++ b/locale/hy_AM/gitlab.po
@@ -0,0 +1,35264 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: Armenian\n"
+"Language: hy_AM\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: hy-AM\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"X-Crowdin-File-ID: 6\n"
+"PO-Revision-Date: 2021-02-01 17:58\n"
+
+msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
+msgstr ""
+
+msgid " %{start} to %{end}"
+msgstr ""
+
+msgid " (from %{timeoutSource})"
+msgstr ""
+
+msgid " Collected %{time}"
+msgstr ""
+
+msgid " Please sign in."
+msgstr ""
+
+msgid " Try to %{action} this file again."
+msgstr ""
+
+msgid " You need to do this before %{grace_period_deadline}."
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " and "
+msgstr ""
+
+msgid " and %{sliced}"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+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 "\"%{path}\" did not exist on \"%{ref}\""
+msgstr ""
+
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "%d Approval"
+msgid_plural "%d Approvals"
+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 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 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 commit"
+msgid_plural "%d commits"
+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 commits"
+msgstr ""
+
+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 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 fixed test result"
+msgid_plural "%d fixed test results"
+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 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 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 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 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 "%{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 "%{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_timeago}"
+msgstr ""
+
+msgid "%{completedCount} completed weight"
+msgstr ""
+
+msgid "%{completedWeight} of %{totalWeight} weight completed"
+msgstr ""
+
+msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
+msgstr ""
+
+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} files touched"
+msgstr ""
+
+msgid "%{count} issue selected"
+msgid_plural "%{count} issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} merge request selected"
+msgid_plural "%{count} merge requests selected"
+msgstr[0] ""
+msgstr[1] ""
+
+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} 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; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
+msgstr ""
+
+msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
+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 "%{extra} more downstream pipelines"
+msgstr ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
+msgstr ""
+
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{group_name} group members"
+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; opened %{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 "%{issuesCount} issues with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{issuesSize} 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}Scan Type:%{labelEnd} %{reportType}"
+msgstr ""
+
+msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgstr ""
+
+msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgstr ""
+
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{label_for_message} unavailable"
+msgstr ""
+
+msgid "%{label_name} %{span_open}will be permanently deleted from %{subject_name}. This cannot be undone.%{span_close}"
+msgstr ""
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+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 "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgstr ""
+
+msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgstr ""
+
+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_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
+msgid "%{mrText}, this issue will be closed automatically."
+msgstr ""
+
+msgid "%{name_with_link} 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} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
+msgid "%{name} is already being used for another emoji"
+msgstr ""
+
+msgid "%{name} is scheduled for %{action}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{name}(%{url}) has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name}(%{url}) has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+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 "%{openOrClose} %{noteable}"
+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 "%{primary} (%{secondary})"
+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 "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
+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 "%{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 "%{state} epics"
+msgstr ""
+
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
+msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
+msgstr ""
+
+msgid "%{strongStart}Tip:%{strongEnd} You can also checkout merge requests locally by %{linkStart}following these guidelines%{linkEnd}"
+msgstr ""
+
+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} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+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 "%{token}..."
+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 "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{userName} (cannot merge)"
+msgstr ""
+
+msgid "%{userName}'s avatar"
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "%{username} has asked for a GitLab account on your instance %{host}:"
+msgstr ""
+
+msgid "%{username}'s avatar"
+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 "%{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 "&lt; 1 hour"
+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}' stage already exists"
+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 "(No changes)"
+msgstr ""
+
+msgid "(UTC %{offset}) %{timezone}"
+msgstr ""
+
+msgid "(check progress)"
+msgstr ""
+
+msgid "(deleted)"
+msgstr ""
+
+msgid "(line: %{startLine})"
+msgstr ""
+
+msgid "(max size 15 MB)"
+msgstr ""
+
+msgid "(removed)"
+msgstr ""
+
+msgid "(revoked)"
+msgstr ""
+
+msgid "* * * * *"
+msgstr ""
+
+msgid "+ %{amount} more"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenAssignees} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenReviewers} more"
+msgstr ""
+
+msgid "+%d more"
+msgid_plural "+%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "+%{approvers} more approvers"
+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 ", or "
+msgstr ""
+
+msgid "- Available to run jobs."
+msgstr ""
+
+msgid "- Event"
+msgid_plural "- Events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- Not available to run jobs."
+msgstr ""
+
+msgid "- User"
+msgid_plural "- Users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- of - weight completed"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "."
+msgstr ""
+
+msgid "0 bytes"
+msgstr ""
+
+msgid "0 for unlimited"
+msgstr ""
+
+msgid "0 for unlimited, only effective with remote storage enabled."
+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 deploy key"
+msgid_plural "%d deploy keys"
+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 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 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-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+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 Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
+msgid "A 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 description is required"
+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 fork is a copy of a project."
+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 maximum of %{count} participants can be added"
+msgstr ""
+
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
+msgstr ""
+
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+msgstr ""
+
+msgid "A merge request hasn't yet been merged"
+msgstr ""
+
+msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} 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 branch will be created in your fork and a new merge request will be started."
+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 plain-text response to show to clients that hit the rate limit."
+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 containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
+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 secure token that identifies an external storage request."
+msgstr ""
+
+msgid "A sign-in to your account has been made from the following IP address: %{ip}"
+msgstr ""
+
+msgid "A string appended to the project path to form the Service Desk email address."
+msgstr ""
+
+msgid "A title is required"
+msgstr ""
+
+msgid "A user can only participate in a rotation once"
+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 Fuzzing"
+msgstr ""
+
+msgid "API Fuzzing Configuration"
+msgstr ""
+
+msgid "API Help"
+msgstr ""
+
+msgid "API Token"
+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 GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Acceptable for use in this project"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied for your LDAP account."
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+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 requests"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Access to Pages websites are controlled based on the user's membership to a given project. By checking this box, users will be required to be logged in to have access to all Pages websites in your instance."
+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|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 gets ahold of it can access repository static objects as if they were you. You should %{reset_link_start}reset it%{reset_link_end} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens."
+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 is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs."
+msgstr ""
+
+msgid "AccessTokens|Your incoming email token is used to authenticate you when you create a new issue by email, and is included in your personal project-specific email addresses."
+msgstr ""
+
+msgid "AccessTokens|Your static object token is used to authenticate you when repository static objects (e.g. archives, blobs, ...) are being served from an external storage."
+msgstr ""
+
+msgid "AccessTokens|reset it"
+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: %{account}"
+msgstr ""
+
+msgid "Action to take when receiving an alert. %{docsLink}"
+msgstr ""
+
+msgid "Actions"
+msgstr ""
+
+msgid "Activate Service Desk"
+msgstr ""
+
+msgid "Activate user activity analysis"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active %{type} (%{token_length})"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add \"%{value}\""
+msgstr ""
+
+msgid "Add %d issue"
+msgid_plural "Add %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+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 GitLab to Slack"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add LICENSE"
+msgstr ""
+
+msgid "Add New Node"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add Variable"
+msgstr ""
+
+msgid "Add Zoom meeting"
+msgstr ""
+
+msgid "Add a %{type}"
+msgstr ""
+
+msgid "Add a GPG key"
+msgstr ""
+
+msgid "Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab."
+msgstr ""
+
+msgid "Add a To Do"
+msgstr ""
+
+msgid "Add a bullet list"
+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 general comment to this %{noteableDisplayName}."
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+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 line"
+msgstr ""
+
+msgid "Add a link"
+msgstr ""
+
+msgid "Add a new issue"
+msgstr ""
+
+msgid "Add a numbered list"
+msgstr ""
+
+msgid "Add a related issue"
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add a task list"
+msgstr ""
+
+msgid "Add a to do"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add an SSH key"
+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 child epic to an epic"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add comment to design"
+msgstr ""
+
+msgid "Add deploy freeze"
+msgstr ""
+
+msgid "Add domain"
+msgstr ""
+
+msgid "Add email address"
+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 issues"
+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 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 to Slack"
+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 user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Add variable"
+msgstr ""
+
+msgid "Add webhook"
+msgstr ""
+
+msgid "Add/remove"
+msgstr ""
+
+msgid "AddContextCommits|Add previously merged commits"
+msgstr ""
+
+msgid "AddContextCommits|Add/remove"
+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 at"
+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 text"
+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 "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 Area"
+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|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|New group"
+msgstr ""
+
+msgid "AdminArea|New project"
+msgstr ""
+
+msgid "AdminArea|New user"
+msgstr ""
+
+msgid "AdminArea|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 "AdminArea|Owner"
+msgstr ""
+
+msgid "AdminArea|Projects"
+msgstr ""
+
+msgid "AdminArea|Reporter"
+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|User cap"
+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 "AdminNote|Note"
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once 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|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Disable feed token"
+msgstr ""
+
+msgid "AdminSettings|Enable shared runners for new projects"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Feed token"
+msgstr ""
+
+msgid "AdminSettings|Go to General Settings"
+msgstr ""
+
+msgid "AdminSettings|Integrations configured here will automatically apply to all projects on this instance."
+msgstr ""
+
+msgid "AdminSettings|Moved to integrations"
+msgstr ""
+
+msgid "AdminSettings|No required pipeline"
+msgstr ""
+
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
+msgid "AdminSettings|Required pipeline configuration"
+msgstr ""
+
+msgid "AdminSettings|Select a pipeline configuration file"
+msgstr ""
+
+msgid "AdminSettings|Select a template"
+msgstr ""
+
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
+msgid "AdminSettings|Service template allows you to set default values for integrations"
+msgstr ""
+
+msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
+msgstr ""
+
+msgid "AdminSettings|Some settings have moved"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
+msgstr ""
+
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+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|(Blocked)"
+msgstr ""
+
+msgid "AdminUsers|(Deactivated)"
+msgstr ""
+
+msgid "AdminUsers|(Internal)"
+msgstr ""
+
+msgid "AdminUsers|(Pending approval)"
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+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"
+msgstr ""
+
+msgid "AdminUsers|Activate user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Active"
+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|Admins"
+msgstr ""
+
+msgid "AdminUsers|Approve"
+msgstr ""
+
+msgid "AdminUsers|Approve user"
+msgstr ""
+
+msgid "AdminUsers|Approved users can:"
+msgstr ""
+
+msgid "AdminUsers|Are you sure?"
+msgstr ""
+
+msgid "AdminUsers|Automatically marked as default internal user"
+msgstr ""
+
+msgid "AdminUsers|Be added to groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Block"
+msgstr ""
+
+msgid "AdminUsers|Block this user"
+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|Deactivate"
+msgstr ""
+
+msgid "AdminUsers|Deactivate user"
+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"
+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|Is using seat"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|Log in"
+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 request"
+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 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|This user has requested access"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|Unblock"
+msgstr ""
+
+msgid "AdminUsers|Unblock user"
+msgstr ""
+
+msgid "AdminUsers|Unblock user %{username}?"
+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|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 cannot remove your own admin rights."
+msgstr ""
+
+msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
+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|View pending user approvals"
+msgstr ""
+
+msgid "Admin|Your instance has reached its user cap"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Advanced Search"
+msgstr ""
+
+msgid "Advanced Search with Elasticsearch"
+msgstr ""
+
+msgid "Advanced Settings"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+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 sign-out path"
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+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|Critical"
+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|High"
+msgstr ""
+
+msgid "AlertManagement|Incident"
+msgstr ""
+
+msgid "AlertManagement|Info"
+msgstr ""
+
+msgid "AlertManagement|Key"
+msgstr ""
+
+msgid "AlertManagement|Low"
+msgstr ""
+
+msgid "AlertManagement|Medium"
+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 To-Do of the alert."
+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|This assignee cannot be assigned to this alert."
+msgstr ""
+
+msgid "AlertManagement|Tool"
+msgstr ""
+
+msgid "AlertManagement|Triggered"
+msgstr ""
+
+msgid "AlertManagement|Unknown"
+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 "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
+msgstr ""
+
+msgid "AlertSettings|1. Select integration type"
+msgstr ""
+
+msgid "AlertSettings|2. Name integration"
+msgstr ""
+
+msgid "AlertSettings|3. Set up webhook"
+msgstr ""
+
+msgid "AlertSettings|4. Sample alert payload (optional)"
+msgstr ""
+
+msgid "AlertSettings|5. Map fields (optional)"
+msgstr ""
+
+msgid "AlertSettings|API URL"
+msgstr ""
+
+msgid "AlertSettings|Active"
+msgstr ""
+
+msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
+msgstr ""
+
+msgid "AlertSettings|Add new integrations"
+msgstr ""
+
+msgid "AlertSettings|Alert test payload"
+msgstr ""
+
+msgid "AlertSettings|Authorization key"
+msgstr ""
+
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
+msgstr ""
+
+msgid "AlertSettings|Copy"
+msgstr ""
+
+msgid "AlertSettings|Delete integration"
+msgstr ""
+
+msgid "AlertSettings|Edit payload"
+msgstr ""
+
+msgid "AlertSettings|Enter integration name"
+msgstr ""
+
+msgid "AlertSettings|Enter test alert JSON...."
+msgstr ""
+
+msgid "AlertSettings|External Prometheus"
+msgstr ""
+
+msgid "AlertSettings|HTTP Endpoint"
+msgstr ""
+
+msgid "AlertSettings|If you edit the payload, the stored mapping will be reset, and you'll need to re-map the fields."
+msgstr ""
+
+msgid "AlertSettings|If you've provided a sample alert payload, you can create a custom mapping for your endpoint. The default GitLab alert keys are listed below. Please define which payload key should map to the specified GitLab key."
+msgstr ""
+
+msgid "AlertSettings|In free versions of GitLab, only one integration for each type can be added. %{linkStart}Upgrade your subscription%{linkEnd} to add additional integrations."
+msgstr ""
+
+msgid "AlertSettings|Integration"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Proceed with editing"
+msgstr ""
+
+msgid "AlertSettings|Prometheus"
+msgstr ""
+
+msgid "AlertSettings|Prometheus API base URL"
+msgstr ""
+
+msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to create a custom mapping (optional), or to test the integration (also optional)."
+msgstr ""
+
+msgid "AlertSettings|Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional)."
+msgstr ""
+
+msgid "AlertSettings|Reset Key"
+msgstr ""
+
+msgid "AlertSettings|Reset key"
+msgstr ""
+
+msgid "AlertSettings|Reset the mapping"
+msgstr ""
+
+msgid "AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
+msgstr ""
+
+msgid "AlertSettings|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
+msgstr ""
+
+msgid "AlertSettings|Save and test payload"
+msgstr ""
+
+msgid "AlertSettings|Save integration"
+msgstr ""
+
+msgid "AlertSettings|Select integration type"
+msgstr ""
+
+msgid "AlertSettings|Submit payload"
+msgstr ""
+
+msgid "AlertSettings|Test alert payload"
+msgstr ""
+
+msgid "AlertSettings|Test alert sent successfully. If you have made other changes, please save them now."
+msgstr ""
+
+msgid "AlertSettings|Test failed. Do you still want to save your changes anyway?"
+msgstr ""
+
+msgid "AlertSettings|There was an error updating the alert settings."
+msgstr ""
+
+msgid "AlertSettings|There was an error while trying to reset the key. Please refresh the page to try again."
+msgstr ""
+
+msgid "AlertSettings|URL cannot be blank and must start with http or https"
+msgstr ""
+
+msgid "AlertSettings|Utilize the URL and authorization key below to authorize Prometheus to send alerts to GitLab. Review the Prometheus documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Webhook URL"
+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|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
+msgstr ""
+
+msgid "AlertSettings|Your integration was successfully updated."
+msgstr ""
+
+msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
+msgstr ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Alerts will not be created through this integration"
+msgstr ""
+
+msgid "AlertsIntegrations|Current integrations"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration Name"
+msgstr ""
+
+msgid "AlertsIntegrations|Integration payload is invalid. You can still save your changes."
+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 has been successfully removed."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration has been successfully saved. Alerts from this new integration should now appear on your alerts list."
+msgstr ""
+
+msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
+msgstr ""
+
+msgid "AlertsIntegrations|The test alert has been successfully sent, and should now be visible on your alerts list."
+msgstr ""
+
+msgid "AlertsIntegrations|You have opted to delete the %{integrationName} integration. Do you want to proceed? It means you will no longer receive alerts from this endpoint in your alert list, and this action cannot be undone."
+msgstr ""
+
+msgid "Algorithm"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All %{replicableType} are being scheduled for %{action}"
+msgstr ""
+
+msgid "All (default)"
+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 features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All groups and projects"
+msgstr ""
+
+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 URL%{relative_url_link_end}."
+msgstr ""
+
+msgid "All projects"
+msgstr ""
+
+msgid "All projects selected"
+msgstr ""
+
+msgid "All security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
+msgstr ""
+
+msgid "All threads resolved"
+msgstr ""
+
+msgid "All users must have a name."
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+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 only the selected protocols to be used for Git access."
+msgstr ""
+
+msgid "Allow overrides to approval lists per merge request (MR)"
+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 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 rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow rendering of diagrams in AsciiDoc and Markdown documents using %{link}."
+msgstr ""
+
+msgid "Allow repository mirroring to be configured by project maintainers"
+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 repository as well? (Default only allows pull access.)"
+msgstr ""
+
+msgid "Allow this secondary node to replicate content on Object Storage"
+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 domains for sign-ups"
+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 "Already blocked"
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+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"
+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 "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+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 empty index will be created if one does not already exist"
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured while saving changes: %{error}"
+msgstr ""
+
+msgid "An error occured while updating the notification settings. Please try again."
+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 previewing the blob"
+msgstr ""
+
+msgid "An error occurred when removing the label."
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue due date"
+msgstr ""
+
+msgid "An error occurred when updating the issue title"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+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 enabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while fetching branches. Retry the search."
+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 markdown preview"
+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 sidebar data"
+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 board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+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 pipeline."
+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 ""
+
+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 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 project creation UI"
+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 members, 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 pipeline."
+msgstr ""
+
+msgid "An error occurred while loading the pipelines jobs."
+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 requesting data from the Jira service"
+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 assignees"
+msgstr ""
+
+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 milestone."
+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 error ocurred while loading your content. Please try again."
+msgstr ""
+
+msgid "An example project for managing Kubernetes clusters integrated with GitLab"
+msgstr ""
+
+msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
+msgstr ""
+
+msgid "An instance-level serverless domain already exists."
+msgstr ""
+
+msgid "An issue already exists"
+msgstr ""
+
+msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
+msgstr ""
+
+msgid "An issue title is required"
+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 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 source code and git history for secrets."
+msgstr ""
+
+msgid "Analyze your source code for known vulnerabilities."
+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 branch"
+msgstr ""
+
+msgid "Any eligible user"
+msgstr ""
+
+msgid "Any encrypted tokens"
+msgstr ""
+
+msgid "Any files larger than this limit will not be indexed, and thus will not be searchable."
+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 "Any user"
+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 "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply"
+msgstr ""
+
+msgid "Apply a label"
+msgstr ""
+
+msgid "Apply a template"
+msgstr ""
+
+msgid "Apply changes"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Apply suggestions"
+msgstr ""
+
+msgid "Apply template"
+msgstr ""
+
+msgid "Apply this approval rule to any branch 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 "ApprovalRuleRemove|%d member"
+msgid_plural "ApprovalRuleRemove|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
+msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
+msgstr ""
+
+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|Approval rules"
+msgstr ""
+
+msgid "ApprovalRule|Approvals required"
+msgstr ""
+
+msgid "ApprovalRule|Approvers"
+msgstr ""
+
+msgid "ApprovalRule|Name"
+msgstr ""
+
+msgid "ApprovalRule|Rule name"
+msgstr ""
+
+msgid "ApprovalRule|Target branch"
+msgstr ""
+
+msgid "ApprovalRule|e.g. QA, Security, etc."
+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 "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 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 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 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}\" Value Stream?"
+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 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 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 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 regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to reindex?"
+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 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 ""
+
+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 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 "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+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|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer 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 some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assign to commenting user"
+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 lists show all issues assigned to the selected user."
+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 logging option is required to be enabled"
+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 a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
+msgid "Attachment"
+msgstr ""
+
+msgid "Attachments"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Audit Events is a way to keep track of important events that happened in GitLab."
+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 with GitHub"
+msgstr ""
+
+msgid "Authenticated API request rate limit"
+msgstr ""
+
+msgid "Authenticated web request rate limit"
+msgstr ""
+
+msgid "Authenticating"
+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 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 DevOps, runners and job artifacts"
+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 "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 "Automatically close incidents when the associated Prometheus alert resolves."
+msgstr ""
+
+msgid "Automatically create merge requests for vulnerabilities that have fixes available."
+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 for dependency and container scanning"
+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 for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Back to page %{number}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+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|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
+msgid "Based on"
+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 "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are the fingerprints for the current instance SSH host keys."
+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} plan."
+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|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|monthly"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
+msgid "BillingPlan|Upgrade"
+msgstr ""
+
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
+msgid "Billing|An email address is only visible for users with public emails."
+msgstr ""
+
+msgid "Billing|An error occurred while loading billable members list"
+msgstr ""
+
+msgid "Billing|Enter at least three characters to search."
+msgstr ""
+
+msgid "Billing|Group"
+msgstr ""
+
+msgid "Billing|No users to display."
+msgstr ""
+
+msgid "Billing|Private"
+msgstr ""
+
+msgid "Billing|Type to search"
+msgstr ""
+
+msgid "Billing|Users occupying seats in"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket Server import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blame"
+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 issues"
+msgstr ""
+
+msgid "Blocks"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardNewIssue|No matching results"
+msgstr ""
+
+msgid "BoardNewIssue|Projects"
+msgstr ""
+
+msgid "BoardNewIssue|Search projects"
+msgstr ""
+
+msgid "BoardNewIssue|Select a project"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Boards and Board Lists"
+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 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 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 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 list. Please try again."
+msgstr ""
+
+msgid "Boards|Board"
+msgstr ""
+
+msgid "Boards|Collapse"
+msgstr ""
+
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|Expand"
+msgstr ""
+
+msgid "Boards|View scope"
+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 issues"
+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 "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant 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 merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+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 ""
+
+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 %{delete_protected_branch}, 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|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|Sort by"
+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 %{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 ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+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 "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse artifacts"
+msgstr ""
+
+msgid "Browse files"
+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|From source group"
+msgstr ""
+
+msgid "BulkImport|Import groups from GitLab"
+msgstr ""
+
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
+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|To new group"
+msgstr ""
+
+msgid "BulkImport|Update of import statuses with realtime changes failed"
+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 "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
+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 "Buy License"
+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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgstr ""
+
+msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
+msgstr ""
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Analytics"
+msgstr ""
+
+msgid "CI / CD Settings"
+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 configuration"
+msgstr ""
+
+msgid "CI/CD configuration file"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+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|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|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run 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 "Callback URL"
+msgstr ""
+
+msgid "Can be manually deployed to"
+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 index deletion"
+msgstr ""
+
+msgid "Cancel running"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cancel, keep project"
+msgstr ""
+
+msgid "Canceled deployment to"
+msgstr ""
+
+msgid "Cancelling Preview"
+msgstr ""
+
+msgid "Cannot be assigned to other projects."
+msgstr ""
+
+msgid "Cannot be merged automatically"
+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 enable shared runners because parent group does not allow it"
+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 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 set confidential epic for a non-confidential issue"
+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 "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 milestone"
+msgstr ""
+
+msgid "Change path"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
+msgid "Change status"
+msgstr ""
+
+msgid "Change subscription"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+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 "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Search branches"
+msgstr ""
+
+msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
+msgstr ""
+
+msgid "ChangeTypeAction|Switch branch"
+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 affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used."
+msgstr ""
+
+msgid "Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used."
+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 are still tracked. Useful for cluster/index migrations."
+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 "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
+msgid "Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "Channel handle (e.g. town-square)"
+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 %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
+msgid "Check your Docker images for known vulnerabilities."
+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 user per year"
+msgstr ""
+
+msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
+msgstr ""
+
+msgid "Checkout|%{name}'s GitLab subscription"
+msgstr ""
+
+msgid "Checkout|%{selectedPlanText} plan"
+msgstr ""
+
+msgid "Checkout|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "Checkout|(x%{numberOfUsers})"
+msgstr ""
+
+msgid "Checkout|Billing address"
+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|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 register credit card. Please try again."
+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|Select"
+msgstr ""
+
+msgid "Checkout|State"
+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|Users"
+msgstr ""
+
+msgid "Checkout|You'll create your new group after checkout"
+msgstr ""
+
+msgid "Checkout|Your organization"
+msgstr ""
+
+msgid "Checkout|Your subscription will be applied to this group"
+msgstr ""
+
+msgid "Checkout|Zip code"
+msgstr ""
+
+msgid "Checkout|company or team"
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Child"
+msgstr ""
+
+msgid "Child epic does not exist."
+msgstr ""
+
+msgid "Child epic doesn't exist."
+msgstr ""
+
+msgid "Chinese language support using"
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a group"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color"
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose any color. Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Choose file…"
+msgstr ""
+
+msgid "Choose labels"
+msgstr ""
+
+msgid "Choose specific groups or storage shards"
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
+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 "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 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 weight."
+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 button below."
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Client request timeout"
+msgstr ""
+
+msgid "Clients"
+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 "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 %{tabname}"
+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 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 "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|An error occurred while loading your GitLab Agents"
+msgstr ""
+
+msgid "ClusterAgents|Configuration"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Name"
+msgstr ""
+
+msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgent|This feature is only available for premium plans"
+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 "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldStart}Note:%{boldEnd} Requires Ingress to be installed."
+msgstr ""
+
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+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|All data not committed to GitLab will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively, "
+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|Any running pipelines will be canceled."
+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|Blocking mode"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Can be safely removed. Prior to GitLab 13.2, GitLab used a remote Tiller server to manage the applications. GitLab no longer uses this server. Uninstalling this server will not affect your other applications. This row will disappear afterwards."
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates are valid and up-to-date."
+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 applications to install on your Kubernetes cluster."
+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 (alpha)"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster name is required."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters connected with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect cluster with certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Connection Error"
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative Endpoint"
+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 a provision role on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the account and external ID above. %{startMoreInfoLink}More information%{endLink}"
+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|Crossplane"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
+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|Elastic Stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Cloud Run for Anthos"
+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|Enabled stack"
+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|Fluentd"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Agent managed clusters"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Container Network Policies"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
+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|Global default"
+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|Helm release failed to install"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+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 install Prometheus in the Applications tab."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{linkStart}pricing%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Instance cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate with a cluster certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer."
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Key pair name"
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Endpoint:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+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 clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+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|Legacy Helm Tiller server"
+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|Logging mode"
+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 deployment cluster found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment found for this job"
+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|Point a wildcard DNS to this generated endpoint in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|Protect your clusters with GitLab Container Network Policies by enforcing how pods communicate with each other and other network endpoints. %{linkStart}Learn more about configuring Network Policies here.%{linkEnd}"
+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|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
+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|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Port"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Protocol"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Search Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Search VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Search domains"
+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 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 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 stack to install Crossplane."
+msgstr ""
+
+msgid "ClusterIntegration|Select a zone to choose a network"
+msgstr ""
+
+msgid "ClusterIntegration|Select existing domain or use new"
+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 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|Send Container Network Policies Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Send Web Application Firewall Logs"
+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|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while trying to save your settings. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+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 %{gitlabNamespace} namespace"
+msgstr ""
+
+msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+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 associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications."
+msgstr ""
+
+msgid "ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored. Your other applications will remain unaffected."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated private key will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The elastic stack collects logs from all pods in your cluster"
+msgstr ""
+
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+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 access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+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|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Unknown Error"
+msgstr ""
+
+msgid "ClusterIntegration|Update %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Use %{query}"
+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 are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
+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 must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You must specify a domain before you can install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You should select at least two subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days."
+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|can be used instead of a custom domain. "
+msgstr ""
+
+msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "ClusterIntergation|Select a VPC"
+msgstr ""
+
+msgid "ClusterIntergation|Select a network"
+msgstr ""
+
+msgid "ClusterIntergation|Select a security group"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnetwork"
+msgstr ""
+
+msgid "ClusterIntergation|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntergation|Select key pair"
+msgstr ""
+
+msgid "ClusterIntergation|Select service role"
+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 "CodeIntelligence|This is the definition"
+msgstr ""
+
+msgid "CodeNavigation|No references found"
+msgstr ""
+
+msgid "CodeOwner|Pattern"
+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 milestones"
+msgstr ""
+
+msgid "Collapse replies"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
+msgid "Collector hostname"
+msgstr ""
+
+msgid "ComboSearch is not defined"
+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 & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+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 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 "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 name"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare %{oldCommitId}...%{newCommitId}"
+msgstr ""
+
+msgid "Compare Git revisions"
+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|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Complete"
+msgstr ""
+
+msgid "Completed"
+msgstr ""
+
+msgid "Compliance"
+msgstr ""
+
+msgid "Compliance Dashboard"
+msgstr ""
+
+msgid "Compliance framework (optional)"
+msgstr ""
+
+msgid "ComplianceDashboard|created by:"
+msgstr ""
+
+msgid "ComplianceFrameworks|Add framework"
+msgstr ""
+
+msgid "ComplianceFrameworks|All"
+msgstr ""
+
+msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
+msgstr ""
+
+msgid "ComplianceFrameworks|Once you have created a compliance framework it will appear here."
+msgstr ""
+
+msgid "ComplianceFrameworks|Regulated"
+msgstr ""
+
+msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
+msgstr ""
+
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
+msgid "ComplianceFramework|GDPR"
+msgstr ""
+
+msgid "ComplianceFramework|GDPR - General Data Protection Regulation"
+msgstr ""
+
+msgid "ComplianceFramework|HIPAA"
+msgstr ""
+
+msgid "ComplianceFramework|HIPAA - Health Insurance Portability and Accountability Act"
+msgstr ""
+
+msgid "ComplianceFramework|PCI-DSS"
+msgstr ""
+
+msgid "ComplianceFramework|PCI-DSS - Payment Card Industry-Data Security Standard"
+msgstr ""
+
+msgid "ComplianceFramework|SOC 2"
+msgstr ""
+
+msgid "ComplianceFramework|SOC 2 - Service Organization Control 2"
+msgstr ""
+
+msgid "ComplianceFramework|SOX"
+msgstr ""
+
+msgid "ComplianceFramework|SOX - Sarbanes-Oxley"
+msgstr ""
+
+msgid "ComplianceFramework|This project is regulated by %{framework}."
+msgstr ""
+
+msgid "Confidence"
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Let's Encrypt"
+msgstr ""
+
+msgid "Configure Prometheus"
+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 automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure existing installation"
+msgstr ""
+
+msgid "Configure limit for issues created per minute by web and API requests."
+msgstr ""
+
+msgid "Configure limits for Project/Group Import/Export."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure limits on the number of inbound alerts able to be sent to a project."
+msgstr ""
+
+msgid "Configure paths to be protected by Rack Attack."
+msgstr ""
+
+msgid "Configure repository mirroring."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Configure which lists are shown for anyone who visits this board"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
+msgid "Confirmation required"
+msgstr ""
+
+msgid "Confluence"
+msgstr ""
+
+msgid "ConfluenceService|Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to GitLab"
+msgstr ""
+
+msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
+msgstr ""
+
+msgid "ConfluenceService|The URL of the Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
+msgstr ""
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+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 Sales to upgrade"
+msgstr ""
+
+msgid "Contact support"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "Container Scanning"
+msgstr ""
+
+msgid "Container does not exist"
+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|%{imageName} tags"
+msgstr ""
+
+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|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 pending"
+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 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"
+msgstr ""
+
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
+msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgstr ""
+
+msgid "ContainerRegistry|Digest: %{imageId}"
+msgstr ""
+
+msgid "ContainerRegistry|Docker connection error"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policies help manage the storage space used by the Container Registry, but the expiration policies for this registry are disabled. Contact your administrator to enable. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy will run in %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Filter by name"
+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 Repositories"
+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 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|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|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 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 Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{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 "Contains %{count} blobs of images (%{size})"
+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."
+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 the display of third party offers."
+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 %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy %{proxy_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 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 email address"
+msgstr ""
+
+msgid "Copy environment"
+msgstr ""
+
+msgid "Copy evidence SHA"
+msgstr ""
+
+msgid "Copy file contents"
+msgstr ""
+
+msgid "Copy file path"
+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 value"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token"
+msgstr ""
+
+msgid "Copy trigger token"
+msgstr ""
+
+msgid "Copy value"
+msgstr ""
+
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
+msgid "Could not add admins as members"
+msgstr ""
+
+msgid "Could not archive %{design}. Please try again."
+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 find design."
+msgstr ""
+
+msgid "Could not find iteration"
+msgstr ""
+
+msgid "Could not load instance counts. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not load the user chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "Could not remove the trigger."
+msgstr ""
+
+msgid "Could not restore the group"
+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}."
+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 calculate number of %{issuables}."
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Coverage"
+msgstr ""
+
+msgid "Coverage Fuzzing"
+msgstr ""
+
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create %{environment}"
+msgstr ""
+
+msgid "Create %{type}"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create Project"
+msgstr ""
+
+msgid "Create Value Stream"
+msgstr ""
+
+msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr ""
+
+msgid "Create a Mattermost team for this group"
+msgstr ""
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new deploy key for this project"
+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 repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
+msgid "Create an account using:"
+msgstr ""
+
+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 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 issue"
+msgstr ""
+
+msgid "Create iteration"
+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 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 issue in Jira"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project"
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create release"
+msgstr ""
+
+msgid "Create requirement"
+msgstr ""
+
+msgid "Create snippet"
+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 "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "CreateValueStreamForm|%{name} (default)"
+msgstr ""
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add stage"
+msgstr ""
+
+msgid "CreateValueStreamForm|All default stages are currently visible"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Default stages"
+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|Maximum length %{maxLength} characters"
+msgstr ""
+
+msgid "CreateValueStreamForm|Name is required"
+msgstr ""
+
+msgid "CreateValueStreamForm|New stage"
+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|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 %{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 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|No credentials found"
+msgstr ""
+
+msgid "CredentialsInventory|Personal Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|SSH Keys"
+msgstr ""
+
+msgid "Critical vulnerabilities present"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron time zone"
+msgstr ""
+
+msgid "Crossplane"
+msgstr ""
+
+msgid "Current"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current Project"
+msgstr ""
+
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "Current node must be the primary node or you will be locking yourself out"
+msgstr ""
+
+msgid "Current password"
+msgstr ""
+
+msgid "Current vulnerabilities count"
+msgstr ""
+
+msgid "CurrentUser|Buy Pipeline minutes"
+msgstr ""
+
+msgid "CurrentUser|One of your groups is running out"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+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 %{notification_link}."
+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 "CustomCycleAnalytics|Add a stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Editing stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|End event label"
+msgstr ""
+
+msgid "CustomCycleAnalytics|New stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Stage name already exists"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Start event label"
+msgstr ""
+
+msgid "Customer Portal"
+msgstr ""
+
+msgid "Customizable by an administrator."
+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 "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
+msgid "Cycle Time"
+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|Date"
+msgstr ""
+
+msgid "CycleAnalytics|Days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Display chart filters"
+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} labels"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Stages"
+msgstr ""
+
+msgid "CycleAnalytics|Tasks by type"
+msgstr ""
+
+msgid "CycleAnalytics|The given date range is larger than 180 days"
+msgstr ""
+
+msgid "CycleAnalytics|The total 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|Total days to completion"
+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 Profiles"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "Dashboard uid not found"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "DashboardProjects|Trending"
+msgstr ""
+
+msgid "Dashboards"
+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 "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|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 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 ""
+
+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 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 ""
+
+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|DAST Scan"
+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|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|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 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|Please enter a valid timeout value"
+msgstr ""
+
+msgid "DastProfiles|Profile name"
+msgstr ""
+
+msgid "DastProfiles|Request headers"
+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|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
+msgid "DastProfiles|Show debug messages"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
+msgid "DastProfiles|Site Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site name"
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Target"
+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|Turn on AJAX spider"
+msgstr ""
+
+msgid "DastProfiles|URL"
+msgstr ""
+
+msgid "DastProfiles|Username"
+msgstr ""
+
+msgid "DastProfiles|Username form field"
+msgstr ""
+
+msgid "DastProfiles|Validated"
+msgstr ""
+
+msgid "DastProfiles|Validation status"
+msgstr ""
+
+msgid "DastSiteValidation|Copy HTTP header to clipboard"
+msgstr ""
+
+msgid "DastSiteValidation|Could not create validation token. Please try again."
+msgstr ""
+
+msgid "DastSiteValidation|Download validation text file"
+msgstr ""
+
+msgid "DastSiteValidation|Header validation"
+msgstr ""
+
+msgid "DastSiteValidation|Retry 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 text to the target site"
+msgstr ""
+
+msgid "DastSiteValidation|Step 3 - Confirm header 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|Validate"
+msgstr ""
+
+msgid "DastSiteValidation|Validate target site"
+msgstr ""
+
+msgid "DastSiteValidation|Validated"
+msgstr ""
+
+msgid "DastSiteValidation|Validating..."
+msgstr ""
+
+msgid "DastSiteValidation|Validation failed"
+msgstr ""
+
+msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Database update failed"
+msgstr ""
+
+msgid "Datasource name not found"
+msgstr ""
+
+msgid "Date"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Date range"
+msgstr ""
+
+msgid "Date range cannot exceed %{maxDateRange} 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 "Dear Administrator,"
+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 "Default Branch"
+msgstr ""
+
+msgid "Default CI configuration path"
+msgstr ""
+
+msgid "Default artifacts expiration"
+msgstr ""
+
+msgid "Default branch"
+msgstr ""
+
+msgid "Default branch and protected branches"
+msgstr ""
+
+msgid "Default classification label"
+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: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "DefaultBranchLabel|default"
+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 approval settings."
+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 "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|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete %{name}"
+msgstr ""
+
+msgid "Delete Comment"
+msgstr ""
+
+msgid "Delete Value Stream"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Delete artifacts"
+msgstr ""
+
+msgid "Delete badge"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete domain"
+msgstr ""
+
+msgid "Delete label"
+msgstr ""
+
+msgid "Delete label: %{label_name} ?"
+msgstr ""
+
+msgid "Delete pipeline"
+msgstr ""
+
+msgid "Delete project"
+msgstr ""
+
+msgid "Delete project. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Delete serverless domain?"
+msgstr ""
+
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete subscription"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Delete user list"
+msgstr ""
+
+msgid "Delete variable"
+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 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 "Deleted"
+msgstr ""
+
+msgid "Deleted Projects"
+msgstr ""
+
+msgid "Deleted chat nickname: %{chat_name}!"
+msgstr ""
+
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+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, merge requests, etc."
+msgstr ""
+
+msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
+msgstr ""
+
+msgid "Denied"
+msgstr ""
+
+msgid "Denied authorization of chat nickname %{user_name}."
+msgstr ""
+
+msgid "Denied domains for sign-ups"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deny access request"
+msgstr ""
+
+msgid "Denylist file"
+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 proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+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 freezes"
+msgstr ""
+
+msgid "Deploy key was successfully updated."
+msgstr ""
+
+msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository"
+msgstr ""
+
+msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+msgstr ""
+
+msgid "Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+msgstr ""
+
+msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
+msgstr ""
+
+msgid "Deploy to..."
+msgstr ""
+
+msgid "DeployFreeze|Freeze end"
+msgstr ""
+
+msgid "DeployFreeze|Freeze start"
+msgstr ""
+
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
+
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgstr ""
+
+msgid "DeployFreeze|Time zone"
+msgstr ""
+
+msgid "DeployFreeze|You can specify deploy freezes using only %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
+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|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 "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read access to the package registry"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the package registry"
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token"
+msgstr ""
+
+msgid "DeployTokens|Copy username"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Default format is \"gitlab+deploy-token-{n}\". Enter custom username if you want to change it."
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
+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|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
+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|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+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 "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
+msgid "Deployment|API"
+msgstr ""
+
+msgid "Deployment|This deployment was created using the API"
+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 "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 templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Descriptive label"
+msgstr ""
+
+msgid "Deselect all"
+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."
+msgstr ""
+
+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|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."
+msgstr ""
+
+msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
+msgstr ""
+
+msgid "DesignManagement|and %{moreCount} more."
+msgstr ""
+
+msgid "Designs"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Detail"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegmentSelection|The selection cannot be configured for a project and for a group at the same time"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of segments has been reached"
+msgstr ""
+
+msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
+msgstr ""
+
+msgid "DevopsAdoption|%{selectedCount} group selected"
+msgstr ""
+
+msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgstr ""
+
+msgid "DevopsAdoption|Add Group"
+msgstr ""
+
+msgid "DevopsAdoption|Add a group to get started"
+msgstr ""
+
+msgid "DevopsAdoption|Adopted"
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
+msgstr ""
+
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
+msgstr ""
+
+msgid "DevopsAdoption|Approvals"
+msgstr ""
+
+msgid "DevopsAdoption|Are you sure that you would like to delete %{name}?"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 MR opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 approval on an MR"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 deploy"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 issue opened"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 pipeline successfully run"
+msgstr ""
+
+msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
+msgstr ""
+
+msgid "DevopsAdoption|Confirm delete Group"
+msgstr ""
+
+msgid "DevopsAdoption|Delete Group"
+msgstr ""
+
+msgid "DevopsAdoption|Deploys"
+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 Group"
+msgstr ""
+
+msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
+msgstr ""
+
+msgid "DevopsAdoption|Filter by name"
+msgstr ""
+
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
+msgid "DevopsAdoption|Issues"
+msgstr ""
+
+msgid "DevopsAdoption|MRs"
+msgstr ""
+
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
+msgstr ""
+
+msgid "DevopsAdoption|My group"
+msgstr ""
+
+msgid "DevopsAdoption|Name"
+msgstr ""
+
+msgid "DevopsAdoption|No filter results."
+msgstr ""
+
+msgid "DevopsAdoption|Not adopted"
+msgstr ""
+
+msgid "DevopsAdoption|Pipelines"
+msgstr ""
+
+msgid "DevopsAdoption|Runner configured for project/group"
+msgstr ""
+
+msgid "DevopsAdoption|Runners"
+msgstr ""
+
+msgid "DevopsAdoption|Save changes"
+msgstr ""
+
+msgid "DevopsAdoption|Scanning"
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
+msgstr ""
+
+msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
+msgstr ""
+
+msgid "DevopsReport|Adoption"
+msgstr ""
+
+msgid "DevopsReport|DevOps"
+msgstr ""
+
+msgid "DevopsReport|DevOps Score"
+msgstr ""
+
+msgid "DevopsReport|Score"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diff view settings"
+msgstr ""
+
+msgid "Difference between start date and now"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(HEAD)"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(base)"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direct member"
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group runners"
+msgstr ""
+
+msgid "Disable public access to Pages sites"
+msgstr ""
+
+msgid "Disable shared runners"
+msgstr ""
+
+msgid "Disable two-factor authentication"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Disabled 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|Receive event notifications in Discord"
+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|Give feedback for this page"
+msgstr ""
+
+msgid "Discover|Security capabilities, integrated into your development lifecycle"
+msgstr ""
+
+msgid "Discover|See the other features of the %{linkStart}gold plan%{linkEnd}"
+msgstr ""
+
+msgid "Discover|Start a free trial"
+msgstr ""
+
+msgid "Discover|Upgrade now"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+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 DevOps Report introduction"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss Value Stream Analytics introduction box"
+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 your monitoring tools directly within GitLab."
+msgstr ""
+
+msgid "Display name"
+msgstr ""
+
+msgid "Display rendered file"
+msgstr ""
+
+msgid "Display source"
+msgstr ""
+
+msgid "Do not display offers from third parties within GitLab"
+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 "Domain"
+msgstr ""
+
+msgid "Domain cannot be deleted while associated to one or more clusters."
+msgstr ""
+
+msgid "Domain denylist"
+msgstr ""
+
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Domain was successfully created."
+msgstr ""
+
+msgid "Domain was successfully deleted."
+msgstr ""
+
+msgid "Domain was successfully updated."
+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 usage data"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download %{format}"
+msgstr ""
+
+msgid "Download %{format}:"
+msgstr ""
+
+msgid "Download %{name} artifact"
+msgstr ""
+
+msgid "Download CSV"
+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 license"
+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 "Draft merge requests can't be merged."
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} designs 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 "Due Date"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "Duration"
+msgstr ""
+
+msgid "Duration for the last 30 commits"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit %{issuable}"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Comment"
+msgstr ""
+
+msgid "Edit Deploy Key"
+msgstr ""
+
+msgid "Edit Geo Node"
+msgstr ""
+
+msgid "Edit Group Hook"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Password"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+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 description"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit fork in Web IDE"
+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 iteration"
+msgstr ""
+
+msgid "Edit public deploy key"
+msgstr ""
+
+msgid "Edit sidebar"
+msgstr ""
+
+msgid "Edit stage"
+msgstr ""
+
+msgid "Edit this file only."
+msgstr ""
+
+msgid "Edit this release"
+msgstr ""
+
+msgid "Edit title and description"
+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 "Editor Lite instance is required to set up an extension."
+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 reindexing is already in progress"
+msgstr ""
+
+msgid "Elasticsearch reindexing triggered"
+msgstr ""
+
+msgid "Elasticsearch returned status code: %{status_code}"
+msgstr ""
+
+msgid "Elasticsearch zero-downtime reindexing"
+msgstr ""
+
+msgid "Elastic|None. Select namespaces to index."
+msgstr ""
+
+msgid "Elastic|None. Select projects to index."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email %{number}"
+msgstr ""
+
+msgid "Email Notification"
+msgstr ""
+
+msgid "Email address to use for Support Desk"
+msgstr ""
+
+msgid "Email cannot be blank"
+msgstr ""
+
+msgid "Email could not be sent"
+msgstr ""
+
+msgid "Email display name"
+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 restrictions"
+msgstr ""
+
+msgid "Email restrictions for sign-ups"
+msgstr ""
+
+msgid "Email sent"
+msgstr ""
+
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
+msgid "Email updates (optional)"
+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|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 "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Emails sent from Service Desk have this name."
+msgstr ""
+
+msgid "Emails sent to %{email} are also supported."
+msgstr ""
+
+msgid "Emails separated by comma"
+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 is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable %{linkStart}Gitpod%{linkEnd} integration to launch a development environment in your browser directly from GitLab."
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Gitpod"
+msgstr ""
+
+msgid "Enable Gitpod?"
+msgstr ""
+
+msgid "Enable HTML emails"
+msgstr ""
+
+msgid "Enable Incident Management inbound alert limit"
+msgstr ""
+
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
+msgid "Enable Kroki"
+msgstr ""
+
+msgid "Enable PlantUML"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SSL verification"
+msgstr ""
+
+msgid "Enable Seat Link"
+msgstr ""
+
+msgid "Enable Spam Check via external API endpoint"
+msgstr ""
+
+msgid "Enable access to Grafana"
+msgstr ""
+
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable and configure Grafana."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
+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 ""
+
+msgid "Enable email restrictions for sign ups"
+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 integration"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Indexing"
+msgstr ""
+
+msgid "Enable kuromoji custom analyzer: Search"
+msgstr ""
+
+msgid "Enable maintenance mode"
+msgstr ""
+
+msgid "Enable mirror configuration"
+msgstr ""
+
+msgid "Enable or disable Seat Link."
+msgstr ""
+
+msgid "Enable or disable keyboard shortcuts"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable protected paths rate limit"
+msgstr ""
+
+msgid "Enable proxy"
+msgstr ""
+
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
+
+msgid "Enable shared runners"
+msgstr ""
+
+msgid "Enable shared runners for all projects and subgroups in this group."
+msgstr ""
+
+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 snowplow tracking"
+msgstr ""
+
+msgid "Enable two-factor authentication"
+msgstr ""
+
+msgid "Enable usage ping"
+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|Close"
+msgstr ""
+
+msgid "EnableReviewApp|Copy snippet text"
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Enabled Git access protocols"
+msgstr ""
+
+msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
+msgstr ""
+
+msgid "Enabling this will only make licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public."
+msgstr ""
+
+msgid "Encountered an error while rendering: %{err}"
+msgstr ""
+
+msgid "End Time"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "Enforce SSH key expiration"
+msgstr ""
+
+msgid "Enforce personal access token expiration"
+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 2FA for Admin Mode"
+msgstr ""
+
+msgid "Enter Admin Mode"
+msgstr ""
+
+msgid "Enter IP address range"
+msgstr ""
+
+msgid "Enter a number"
+msgstr ""
+
+msgid "Enter an integer number between 0 and 100"
+msgstr ""
+
+msgid "Enter an integer number number between 0 and 100"
+msgstr ""
+
+msgid "Enter at least three characters to search"
+msgstr ""
+
+msgid "Enter domain"
+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 merge request URLs"
+msgstr ""
+
+msgid "Enter new %{field_title}"
+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 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 issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+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 weights for storages for new repositories."
+msgstr ""
+
+msgid "Enter your password to approve"
+msgstr ""
+
+msgid "Environment"
+msgstr ""
+
+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 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 %{link_to_read_more}."
+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|More information"
+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. %{readMoreLink}"
+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 in"
+msgstr ""
+
+msgid "Environments|Auto stops %{auto_stop_time}"
+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|Managed apps"
+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|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod name"
+msgstr ""
+
+msgid "Environments|Re-deploy"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{environment_name}?"
+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 %{environment_name}?"
+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"
+msgstr ""
+
+msgid "Environments|Stopping %{environmentName}"
+msgstr ""
+
+msgid "Environments|There was an error fetching the logs. Please try again."
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?"
+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 %{environment_name} for commit %{commit_id}, 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|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|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic cannot be found."
+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|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|How can I solve this?"
+msgstr ""
+
+msgid "Epics|Leave empty to inherit from milestone dates"
+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 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|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+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 perform this action"
+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 iteration"
+msgstr ""
+
+msgid "Error creating repository for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Error creating the snippet"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+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 when toggling the notification subscription"
+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 blocked"
+msgstr ""
+
+msgid "Error occurred. User was not confirmed"
+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: %{stripped}"
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error while loading the project data. 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: 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 find AWS role for current user"
+msgstr ""
+
+msgid "ErrorTracking|Active"
+msgstr ""
+
+msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgstr ""
+
+msgid "ErrorTracking|Auth Token"
+msgstr ""
+
+msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgstr ""
+
+msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgstr ""
+
+msgid "ErrorTracking|If you self-host Sentry, enter the full URL of your Sentry instance. If you're using 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 "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 "Events in %{project_path}"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day"
+msgstr ""
+
+msgid "Every day (at %{time})"
+msgstr ""
+
+msgid "Every month"
+msgstr ""
+
+msgid "Every month (Day %{day} at %{time})"
+msgstr ""
+
+msgid "Every three months"
+msgstr ""
+
+msgid "Every two weeks"
+msgstr ""
+
+msgid "Every week"
+msgstr ""
+
+msgid "Every week (%{weekday} at %{time})"
+msgstr ""
+
+msgid "Everyone"
+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: %{ip_address}. %{read_more_link}."
+msgstr ""
+
+msgid "Example: @sub\\.company\\.com$"
+msgstr ""
+
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Excess storage"
+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 milestones"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expected documents: %{expected_documents}"
+msgstr ""
+
+msgid "Experienced"
+msgstr ""
+
+msgid "ExperimentSubject|Must have exactly one of User, Group, or Project."
+msgstr ""
+
+msgid "Expiration"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expired:"
+msgstr ""
+
+msgid "Expires"
+msgstr ""
+
+msgid "Expires at"
+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 "Export"
+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 to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
+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 Classification Policy Authorization"
+msgstr ""
+
+msgid "External ID"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+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 ""
+
+msgid "External storage authentication token"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external 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 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 Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create To-Do for the design."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create framework"
+msgstr ""
+
+msgid "Failed to create import label for jira import."
+msgstr ""
+
+msgid "Failed to create new project 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 find import label for Jira import."
+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 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."
+msgstr ""
+
+msgid "Failed to load groups, users and deploy keys."
+msgstr ""
+
+msgid "Failed to load labels. Please try again."
+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 sidebar confidential toggle"
+msgstr ""
+
+msgid "Failed to load sidebar lock status"
+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 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 To-Do for the design."
+msgstr ""
+
+msgid "Failed to remove a Zoom meeting"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+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 To-Do 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 issues, please try again."
+msgstr ""
+
+msgid "Failed to update tag!"
+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 "Failed to verify domain ownership"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "False positive"
+msgstr ""
+
+msgid "Fast-forward merge is not possible. Rebase the source branch onto %{targetBranch} to allow this merge request to be merged."
+msgstr ""
+
+msgid "Fast-forward merge is not possible. Rebase the source branch onto the target branch."
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster releases. Better code. Less pain."
+msgstr ""
+
+msgid "Favicon was successfully removed."
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "Feature flag is not enabled on the environment's project."
+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|* (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 Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag User List Details"
+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|Flag is read-only"
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Get started with user lists"
+msgstr ""
+
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
+msgid "FeatureFlags|ID"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Include additional user IDs"
+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|Loading user lists"
+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|New user list"
+msgstr ""
+
+msgid "FeatureFlags|No user list selected"
+msgstr ""
+
+msgid "FeatureFlags|Percent of users"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout (logged in users)"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
+msgstr ""
+
+msgid "FeatureFlags|Protected"
+msgstr ""
+
+msgid "FeatureFlags|Remove"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Percentage"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Strategy"
+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|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the user lists."
+msgstr ""
+
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
+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|User lists allow you to define a set of users to use with Feature Flags."
+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 format is no longer supported"
+msgstr ""
+
+msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
+msgstr ""
+
+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 synchronization concurrency limit"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Filename"
+msgstr ""
+
+msgid "Files"
+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 %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by %{page_context_word} that are currently opened."
+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 name"
+msgstr ""
+
+msgid "Filter by name"
+msgstr ""
+
+msgid "Filter by status"
+msgstr ""
+
+msgid "Filter by test cases that are currently archived."
+msgstr ""
+
+msgid "Filter by test cases that are currently opened."
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+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 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 Seen"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "First seen"
+msgstr ""
+
+msgid "Fixed burndown chart"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "Flags"
+msgstr ""
+
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+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 "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 help setting up the Service Desk for your instance, please contact an administrator."
+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 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, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the File Hooks documentation."
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
+msgstr ""
+
+msgid "Forgot your password?"
+msgstr ""
+
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
+msgid "Fork project?"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from an inaccessible project"
+msgstr ""
+
+msgid "Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format: %{dateFormat}"
+msgstr ""
+
+msgid "Found errors in your %{gitlab_ci_yml}:"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Framework successfully deleted"
+msgstr ""
+
+msgid "Free Trial"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "Freeze end"
+msgstr ""
+
+msgid "Freeze start"
+msgstr ""
+
+msgid "Frequency"
+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 "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+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 "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Generate new export"
+msgstr ""
+
+msgid "Generate new token"
+msgstr ""
+
+msgid "Generic package file size in bytes"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo Nodes Beta"
+msgstr ""
+
+msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
+msgstr ""
+
+msgid "Geo Replication"
+msgstr ""
+
+msgid "Geo Settings"
+msgstr ""
+
+msgid "Geo nodes are paused using a command run on the node"
+msgstr ""
+
+msgid "GeoNodeStatusEvent|%{timeAgoStr} (%{pendingEvents} events)"
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Consult Geo troubleshooting information"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Internal URL"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Geo node statuses"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node URL"
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Node's status was updated %{timeAgo}."
+msgstr ""
+
+msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a Geo primary node stops the synchronization to all nodes. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a Geo secondary node stops the synchronization to that node. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replicated data is verified with the %{nodeText} using checksums"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Replication status"
+msgstr ""
+
+msgid "GeoNodes|Selective (%{syncLabel})"
+msgstr ""
+
+msgid "GeoNodes|Selective synchronization"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Updated %{timeAgo}"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "GeoNodes|primary node"
+msgstr ""
+
+msgid "GeoNodes|secondary nodes"
+msgstr ""
+
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+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|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 %{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|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|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing upload."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|Filter by status"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Go to the primary site"
+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|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|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+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 ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Please refer to Geo Troubleshooting."
+msgstr ""
+
+msgid "Geo|Primary node"
+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|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Remove entry"
+msgstr ""
+
+msgid "Geo|Remove tracking database entry"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Reverify"
+msgstr ""
+
+msgid "Geo|Reverify all"
+msgstr ""
+
+msgid "Geo|Review replication status, and resynchronize and reverify items with the primary node."
+msgstr ""
+
+msgid "Geo|Secondary node"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synced at"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Synchronization of %{itemTitle} is disabled."
+msgstr ""
+
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
+msgid "Geo|There are no %{replicable_type} to show"
+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|Tracking entry for upload (%{type}/%{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|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
+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 started"
+msgstr ""
+
+msgid "Get started with GitLab"
+msgstr ""
+
+msgid "Get started with a project that follows best practices for setting up GitLab for your own organization, including sample Issues, Merge Requests, and Milestones"
+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 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 "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 commit"
+msgstr ""
+
+msgid "GitLab export"
+msgstr ""
+
+msgid "GitLab for Slack"
+msgstr ""
+
+msgid "GitLab group: %{source_link}"
+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 undergoing maintenance and is operating in a read-only mode."
+msgstr ""
+
+msgid "GitLab member or Email address"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab restart is required to apply changes."
+msgstr ""
+
+msgid "GitLab single sign-on URL"
+msgstr ""
+
+msgid "GitLab username"
+msgstr ""
+
+msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+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|It may take up to 30 minutes before the site is available after the first deployment."
+msgstr ""
+
+msgid "GitLabPages|Learn more."
+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"
+msgstr ""
+
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 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."
+msgstr ""
+
+msgid "GitLabPages|With GitLab Pages you can host your static websites on GitLab. Combined with the power of GitLab CI and the help of GitLab Runner you can deploy static pages for your individual projects, your user or your group."
+msgstr ""
+
+msgid "GitLabPages|Your pages are served under:"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly relative path:"
+msgstr ""
+
+msgid "Gitaly storage name:"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Gitlab Pages"
+msgstr ""
+
+msgid "Gitpod"
+msgstr ""
+
+msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
+msgstr ""
+
+msgid "Gitpod|Enable Gitpod integration"
+msgstr ""
+
+msgid "Gitpod|Gitpod URL"
+msgstr ""
+
+msgid "Gitpod|e.g. https://gitpod.example.com"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Given epic is already related to this epic."
+msgstr ""
+
+msgid "Global Shortcuts"
+msgstr ""
+
+msgid "Global notification settings"
+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 %{tagStart}Open issues%{tagEnd} and select some issues to add to your board."
+msgstr ""
+
+msgid "Go full screen"
+msgstr ""
+
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
+msgstr ""
+
+msgid "Go to Webhooks"
+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 parent"
+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 activity feed"
+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 Platform"
+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|Embed Grafana charts in GitLab issues."
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the Grafana API Token."
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana URL"
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana authentication"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+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 Audit Events"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group Hooks"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group ID: %{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 avatar"
+msgstr ""
+
+msgid "Group by"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group export could not be started."
+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 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 info:"
+msgstr ""
+
+msgid "Group is required when cluster_type is :group"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+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"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group path is already taken. Suggestions: "
+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 push rule exists, try updating"
+msgstr ""
+
+msgid "Group requires separate account"
+msgstr ""
+
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
+msgid "Group variables (inherited)"
+msgstr ""
+
+msgid "Group was exported"
+msgstr ""
+
+msgid "Group was successfully updated."
+msgstr ""
+
+msgid "Group-level events in %{group_name} (no project-level events)"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "Group: %{name}"
+msgstr ""
+
+msgid "GroupActivityMetrics|Issues opened"
+msgstr ""
+
+msgid "GroupActivityMetrics|Members added"
+msgstr ""
+
+msgid "GroupActivityMetrics|Merge Requests opened"
+msgstr ""
+
+msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+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 "GroupRoadmap|%{dateWord} – No end date"
+msgstr ""
+
+msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
+msgstr ""
+
+msgid "GroupRoadmap|No start and end date"
+msgstr ""
+
+msgid "GroupRoadmap|No start date – %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
+msgstr ""
+
+msgid "GroupRoadmap|Some of your epics might not be visible"
+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|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 "GroupSAML|Active SAML Group Links (%{count})"
+msgstr ""
+
+msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
+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 this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforced SSO"
+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"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks for this group."
+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 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 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 enforced SSO, you first need to enable SAML authentication."
+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|Toggle SAML authentication"
+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|Your SCIM token"
+msgstr ""
+
+msgid "GroupSAML|as %{access_level}"
+msgstr ""
+
+msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
+msgstr ""
+
+msgid "GroupSAML|should be \"persistent\""
+msgstr ""
+
+msgid "GroupSAML|should be a random persistent ID, emails are discouraged"
+msgstr ""
+
+msgid "GroupSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_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 group URL can have unintended side effects."
+msgstr ""
+
+msgid "GroupSettings|Compliance frameworks"
+msgstr ""
+
+msgid "GroupSettings|Configure frameworks to apply enforceable rules to projects."
+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 delayed project removal"
+msgstr ""
+
+msgid "GroupSettings|Export group"
+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|Integrations configured here will automatically apply to all projects in this group."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|New runners registration token has been generated!"
+msgstr ""
+
+msgid "GroupSettings|Pipeline settings was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "GroupSettings|Prevent forking outside of the group"
+msgstr ""
+
+msgid "GroupSettings|Prevent forking setting was not saved"
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
+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|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects."
+msgstr ""
+
+msgid "GroupSettings|This setting will prevent group members from being notified if the group is mentioned."
+msgstr ""
+
+msgid "GroupSettings|This setting will prevent group members from forking projects outside of the group."
+msgstr ""
+
+msgid "GroupSettings|Transfer group"
+msgstr ""
+
+msgid "GroupSettings|What are badges?"
+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 (%{groups})"
+msgstr ""
+
+msgid "Groups and projects"
+msgstr ""
+
+msgid "Groups and subgroups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups to synchronize"
+msgstr ""
+
+msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
+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|Connect instance"
+msgstr ""
+
+msgid "GroupsNew|Contact an administrator to enable options for importing your group."
+msgstr ""
+
+msgid "GroupsNew|Create"
+msgstr ""
+
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|GitLab source URL"
+msgstr ""
+
+msgid "GroupsNew|Import"
+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, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+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|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 "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 your users email"
+msgstr ""
+
+msgid "Header logo was successfully removed."
+msgstr ""
+
+msgid "Header message"
+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 there"
+msgstr ""
+
+msgid "Hello, %{username}!"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Helps prevent bots from brute-force attacks."
+msgstr ""
+
+msgid "Helps prevent bots from creating accounts."
+msgstr ""
+
+msgid "Helps reduce alert volume (e.g. if creating too many issues)"
+msgstr ""
+
+msgid "Helps reduce request volume for protected paths"
+msgstr ""
+
+msgid "Here are all your projects in your group, including the one you just created. To start, let’s take a look at your personalized learning project which will help you learn about GitLab at your own pace."
+msgstr ""
+
+msgid "Here you will find recent merge request activity"
+msgstr ""
+
+msgid "Hi %{username}!"
+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 help"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide shared projects"
+msgstr ""
+
+msgid "Hide stage"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "High or unknown vulnerabilities present"
+msgstr ""
+
+msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
+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 "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 "Hour (UTC)"
+msgstr ""
+
+msgid "Housekeeping"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr ""
+
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
+msgid "How does cleanup work?"
+msgstr ""
+
+msgid "How it works"
+msgstr ""
+
+msgid "How many days need to pass between marking entity for deletion and actual removing it."
+msgstr ""
+
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
+msgid "How many users will be evaluating the trial?"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
+msgstr ""
+
+msgid "I'd like to receive updates about GitLab via email"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "ID:"
+msgstr ""
+
+msgid "IDE"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+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 subnet restriction only allowed for top-level groups"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identifiers"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+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 admins will be able to configure repository mirroring."
+msgstr ""
+
+msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
+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 is no previous license or if the previous license has expired, some GitLab functionality will be blocked until a new, valid license is uploaded."
+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 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 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 remove this license, GitLab will fall back on the previous license, if any."
+msgstr ""
+
+msgid "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 "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 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 "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 failed due to a GitHub error: %{original}"
+msgstr ""
+
+msgid "Import from"
+msgstr ""
+
+msgid "Import from Jira"
+msgstr ""
+
+msgid "Import group from file"
+msgstr ""
+
+msgid "Import groups"
+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 "Import/Export Rate Limits"
+msgstr ""
+
+msgid "Import/Export illustration"
+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 "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve customer support with Service Desk"
+msgstr ""
+
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In %{time_to_now}"
+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 order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
+
+msgid "In progress"
+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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
+msgid "Incident"
+msgstr ""
+
+msgid "Incident Management Limits"
+msgstr ""
+
+msgid "Incident template (optional)"
+msgstr ""
+
+msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|%{minutes} minutes remaining"
+msgstr ""
+
+msgid "IncidentManagement|All"
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
+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|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|Alert integration"
+msgstr ""
+
+msgid "IncidentSettings|Grafana integration"
+msgstr ""
+
+msgid "IncidentSettings|Incident settings"
+msgstr ""
+
+msgid "IncidentSettings|Incidents"
+msgstr ""
+
+msgid "IncidentSettings|PagerDuty integration"
+msgstr ""
+
+msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
+msgstr ""
+
+msgid "IncidentSettings|Time limit"
+msgstr ""
+
+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 will apply to all new incidents within the project"
+msgstr ""
+
+msgid "IncidentSettings|You may choose to introduce a countdown timer in incident issues to better track Service Level Agreements (SLAs). The timer is automatically started when the incident is created, and sets a time limit for the incident to be resolved in. When activated, \"time to SLA\" countdown will appear on all new incidents."
+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 a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include author name in notification email body"
+msgstr ""
+
+msgid "Include description in commit message"
+msgstr ""
+
+msgid "Include merge request description"
+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 "Indent"
+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 "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
+msgid "Inherited"
+msgstr ""
+
+msgid "Inherited:"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input the remote repository URL"
+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 image"
+msgstr ""
+
+msgid "Insert inline code"
+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"
+msgstr ""
+
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
+
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
+
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Install on clusters"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+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 overview"
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the pipelines chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceStatistics|Could not load the projects and groups chart. Please refresh the page to try again."
+msgstr ""
+
+msgid "InstanceStatistics|Groups"
+msgstr ""
+
+msgid "InstanceStatistics|Issues"
+msgstr ""
+
+msgid "InstanceStatistics|Issues & Merge Requests"
+msgstr ""
+
+msgid "InstanceStatistics|Items"
+msgstr ""
+
+msgid "InstanceStatistics|Merge Requests"
+msgstr ""
+
+msgid "InstanceStatistics|Month"
+msgstr ""
+
+msgid "InstanceStatistics|No data available."
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines canceled"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines failed"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines skipped"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines succeeded"
+msgstr ""
+
+msgid "InstanceStatistics|Pipelines total"
+msgstr ""
+
+msgid "InstanceStatistics|Projects"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the cancelled pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the failed pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the issues"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the merge requests"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the skipped pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the successful pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error fetching the total pipelines"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the groups"
+msgstr ""
+
+msgid "InstanceStatistics|There was an error while loading the projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total groups"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects"
+msgstr ""
+
+msgid "InstanceStatistics|Total projects & groups"
+msgstr ""
+
+msgid "InstanceStatistics|Users"
+msgstr ""
+
+msgid "Integration"
+msgstr ""
+
+msgid "Integration Settings"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved and active."
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved, but not active."
+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|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|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
+msgid "Integrations|Enable comments"
+msgstr ""
+
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
+msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgstr ""
+
+msgid "Integrations|Includes commit title and branch"
+msgstr ""
+
+msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
+msgstr ""
+
+msgid "Integrations|Link namespaces"
+msgstr ""
+
+msgid "Integrations|Linked namespaces"
+msgstr ""
+
+msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
+msgstr ""
+
+msgid "Integrations|No available namespaces."
+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|Sign in to add namespaces"
+msgstr ""
+
+msgid "Integrations|Standard"
+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|Update your projects on Packagist, the main Composer repository"
+msgstr ""
+
+msgid "Integrations|Use custom settings"
+msgstr ""
+
+msgid "Integrations|Use default settings"
+msgstr ""
+
+msgid "Integrations|Use the GitLab Slack application"
+msgstr ""
+
+msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
+msgstr ""
+
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+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 users"
+msgstr ""
+
+msgid "Internal users cannot be deactivated"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Value Stream Analytics"
+msgstr ""
+
+msgid "Introducing Your DevOps Report"
+msgstr ""
+
+msgid "Invalid Insights config file detected"
+msgstr ""
+
+msgid "Invalid Login or password"
+msgstr ""
+
+msgid "Invalid OS"
+msgstr ""
+
+msgid "Invalid 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 query"
+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 "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 group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invite members"
+msgstr ""
+
+msgid "Invite team members"
+msgstr ""
+
+msgid "Invite your team"
+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|Join now"
+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 are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+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 role permission"
+msgstr ""
+
+msgid "InviteMembersModal|Close invite team members"
+msgstr ""
+
+msgid "InviteMembersModal|GitLab member or Email address"
+msgstr ""
+
+msgid "InviteMembersModal|Invite"
+msgstr ""
+
+msgid "InviteMembersModal|Invite team members"
+msgstr ""
+
+msgid "InviteMembersModal|Members were successfully added"
+msgstr ""
+
+msgid "InviteMembersModal|Search for members to invite"
+msgstr ""
+
+msgid "InviteMembersModal|Some of the members could not be added"
+msgstr ""
+
+msgid "InviteMembersModal|You're inviting members to the %{name} %{type}"
+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 "InviteMember|Oops, this feature isn't ready yet"
+msgstr ""
+
+msgid "InviteMember|See who can invite members for you"
+msgstr ""
+
+msgid "InviteMember|Until then, ask an owner to invite new project members for you"
+msgstr ""
+
+msgid "InviteMember|We're working to allow everyone to invite new members, making it easier for teams to get started with GitLab"
+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 "Is blocked by"
+msgstr ""
+
+msgid "Is this GitLab trial for your company?"
+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 already promoted to epic."
+msgstr ""
+
+msgid "Issue cannot be found."
+msgstr ""
+
+msgid "Issue created from vulnerability %{vulnerability_link}"
+msgstr ""
+
+msgid "Issue details"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "Issue first deployed to production"
+msgstr ""
+
+msgid "Issue label"
+msgstr ""
+
+msgid "Issue or Merge Request ID is required"
+msgstr ""
+
+msgid "Issue published on status page."
+msgstr ""
+
+msgid "Issue title"
+msgstr ""
+
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
+msgid "Issue weight"
+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|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
+msgstr ""
+
+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 "IssueTracker|Bugzilla issue tracker"
+msgstr ""
+
+msgid "IssueTracker|Custom issue tracker"
+msgstr ""
+
+msgid "IssueTracker|EWM work items tracker"
+msgstr ""
+
+msgid "IssueTracker|Redmine issue tracker"
+msgstr ""
+
+msgid "IssueTracker|YouTrack issue tracker"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues Rate Limits"
+msgstr ""
+
+msgid "Issues and Merge Requests"
+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 with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
+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 "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 "Iteration|Dates cannot overlap with other existing Iterations"
+msgstr ""
+
+msgid "Iteration|cannot be in the past"
+msgstr ""
+
+msgid "Iteration|cannot be more than 500 years in the future"
+msgstr ""
+
+msgid "I’m familiar with the basics of DevOps."
+msgstr ""
+
+msgid "I’m not familiar with the basics of DevOps."
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Japanese language support using"
+msgstr ""
+
+msgid "Jira Issues"
+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 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 "JiraService| on branch %{branch_link}"
+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 occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
+msgid "JiraService|For example, 12, 24"
+msgstr ""
+
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|Issue List"
+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 Issues"
+msgstr ""
+
+msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Jira issue type"
+msgstr ""
+
+msgid "JiraService|Jira project key"
+msgstr ""
+
+msgid "JiraService|Jira workflow transition IDs"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
+msgstr ""
+
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
+msgid "JiraService|This feature requires a Premium plan."
+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|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 will be 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|e.g. AB"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
+msgid "Job"
+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|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|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"
+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|for"
+msgstr ""
+
+msgid "Job|into"
+msgstr ""
+
+msgid "Job|with"
+msgstr ""
+
+msgid "Join Zoom meeting"
+msgstr ""
+
+msgid "Joined %{time_ago}"
+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 "Keep artifacts from most recent successful jobs"
+msgstr ""
+
+msgid "Keep divergent refs"
+msgstr ""
+
+msgid "Keep editing"
+msgstr ""
+
+msgid "Kerberos access denied"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Key: %{key}"
+msgstr ""
+
+msgid "Keyboard shortcuts"
+msgstr ""
+
+msgid "KeyboardKey|Ctrl+"
+msgstr ""
+
+msgid "KeyboardShortcuts|Global Shortcuts"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
+msgid "KeyboardShortcuts|Toggle the Performance Bar"
+msgstr ""
+
+msgid "Keys"
+msgstr ""
+
+msgid "Ki"
+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 deployment not found"
+msgstr ""
+
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
+msgid "Kubernetes popover"
+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 "LFS"
+msgstr ""
+
+msgid "LFS object"
+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 lists show all issues with the selected label."
+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|%{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 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 Pipeline"
+msgstr ""
+
+msgid "Last Seen"
+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 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 repository check run"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last sign-in"
+msgstr ""
+
+msgid "Last successful sync"
+msgstr ""
+
+msgid "Last successful update"
+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 "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 "Lead"
+msgstr ""
+
+msgid "Lead Time"
+msgstr ""
+
+msgid "Learn CI/CD syntax"
+msgstr ""
+
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn GitLab - Ultimate trial"
+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 how to enable synchronization"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{username}"
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about License-Check"
+msgstr ""
+
+msgid "Learn more about Needs relationships"
+msgstr ""
+
+msgid "Learn more about Vulnerability-Check"
+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 signing commits"
+msgstr ""
+
+msgid "Learn more about the dependency list"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Learn more."
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave Admin Mode"
+msgstr ""
+
+msgid "Leave blank for no limit. Once set, existing personal access tokens may be revoked."
+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 "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 "License"
+msgstr ""
+
+msgid "License Compliance"
+msgstr ""
+
+msgid "License History"
+msgstr ""
+
+msgid "License ID:"
+msgstr ""
+
+msgid "License overview"
+msgstr ""
+
+msgid "License-Check"
+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 a license"
+msgstr ""
+
+msgid "LicenseCompliance|Add license and related 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 Features"
+msgstr ""
+
+msgid "Licensed to"
+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|Disallow Merge request if detected and will instruct the developer to remove"
+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|Learn more about license compliance"
+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|View license details for your project"
+msgstr ""
+
+msgid "License|Buy license"
+msgstr ""
+
+msgid "License|License"
+msgstr ""
+
+msgid "License|You can restore access to the Gold features at any time by upgrading."
+msgstr ""
+
+msgid "License|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
+msgid "License|You do not have a license."
+msgstr ""
+
+msgid "License|Your License"
+msgstr ""
+
+msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
+msgstr ""
+
+msgid "Limit display of time tracking units to hours."
+msgstr ""
+
+msgid "Limit namespaces and projects that can be indexed"
+msgstr ""
+
+msgid "Limit the number of concurrent operations this secondary node can run in the background."
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Line changes"
+msgstr ""
+
+msgid "Link"
+msgstr ""
+
+msgid "Link Prometheus monitoring to GitLab."
+msgstr ""
+
+msgid "Link copied"
+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 "Linked emails (%{email_count})"
+msgstr ""
+
+msgid "Linked issues"
+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 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 issues"
+msgstr ""
+
+msgid "Loading more issues"
+msgstr ""
+
+msgid "Loading snippet"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Local IP addresses and domain names that hooks and services may access."
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Location"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+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 "Login with smartcard"
+msgstr ""
+
+msgid "Logo was successfully removed."
+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 "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"
+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 you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage milestones"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage storage usage"
+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 "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 %{originating_vulnerability}."
+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 as resolved"
+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 "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 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 "MattermostService|Add to Mattermost"
+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|See list of available commands in Mattermost after setting up this service, by entering"
+msgstr ""
+
+msgid "MattermostService|Suggestions:"
+msgstr ""
+
+msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
+msgstr ""
+
+msgid "Max 100,000 events"
+msgstr ""
+
+msgid "Max 20 characters"
+msgstr ""
+
+msgid "Max Group Export Download requests per minute per user"
+msgstr ""
+
+msgid "Max Group Export requests per minute per user"
+msgstr ""
+
+msgid "Max Group Import requests per minute per user"
+msgstr ""
+
+msgid "Max Project Export Download requests per minute per user"
+msgstr ""
+
+msgid "Max Project Export requests per minute per user"
+msgstr ""
+
+msgid "Max Project Import requests per minute per user"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Max file size is 200 KB."
+msgstr ""
+
+msgid "Max role"
+msgstr ""
+
+msgid "MaxBuilds"
+msgstr ""
+
+msgid "Maximum Conan package file size in bytes"
+msgstr ""
+
+msgid "Maximum Maven package file size in bytes"
+msgstr ""
+
+msgid "Maximum NPM 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 Users"
+msgstr ""
+
+msgid "Maximum allowable lifetime for personal access token (days)"
+msgstr ""
+
+msgid "Maximum artifacts size"
+msgstr ""
+
+msgid "Maximum artifacts size (MB)"
+msgstr ""
+
+msgid "Maximum attachment size (MB)"
+msgstr ""
+
+msgid "Maximum bulk request size (MiB)"
+msgstr ""
+
+msgid "Maximum capacity"
+msgstr ""
+
+msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
+msgstr ""
+
+msgid "Maximum delay (Minutes)"
+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 2MB. Please select a smaller file."
+msgstr ""
+
+msgid "Maximum import size (MB)"
+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 number of %{name} (%{count}) exceeded"
+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 page reached"
+msgstr ""
+
+msgid "Maximum push size (MB)"
+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 time between updates that a mirror can have when scheduled to synchronize."
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Mean time to merge"
+msgstr ""
+
+msgid "Measured in bytes of code. Excludes generated and vendored code."
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Medium vulnerabilities present"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+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 invited to %{strong_start}%{project_name}%{strong_end}"
+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 %{strong_open}%{project_name}%{strong_close}"
+msgstr ""
+
+msgid "Members of a group may only view projects they have permission to access"
+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|Expired"
+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|No expiration set"
+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 "Members|in %{time}"
+msgstr ""
+
+msgid "Member|Deny access"
+msgstr ""
+
+msgid "Member|Remove member"
+msgstr ""
+
+msgid "Member|Revoke invite"
+msgstr ""
+
+msgid "Memory Usage"
+msgstr ""
+
+msgid "Merge"
+msgstr ""
+
+msgid "Merge Conflicts"
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request Analytics"
+msgstr ""
+
+msgid "Merge Request Approvals"
+msgstr ""
+
+msgid "Merge Request Commits"
+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 commit SHA"
+msgstr ""
+
+msgid "Merge commit message"
+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 %{iid} authored by %{authorName}"
+msgstr ""
+
+msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
+msgstr ""
+
+msgid "Merge request (MR) approvals"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge request approvals allow you to set the number of necessary approvals and predefine a list of approvers that will need to approve every merge request in a project."
+msgstr ""
+
+msgid "Merge request dependencies"
+msgstr ""
+
+msgid "Merge request events"
+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 requests are read-only in a secondary Geo node"
+msgstr ""
+
+msgid "Merge the branch and fix any conflicts that come up"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+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 "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Select comment starting line"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while checking whether another squash is in progress."
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this thread in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+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|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 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 "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::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+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 dashboard"
+msgstr ""
+
+msgid "MetricsSettings|UTC (Coordinated Universal Time)"
+msgstr ""
+
+msgid "MetricsSettings|User's local timezone"
+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|View runbook - %{label}"
+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 "Microsoft Azure"
+msgstr ""
+
+msgid "Middleman project with Static Site Editor support"
+msgstr ""
+
+msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
+msgid "Migrated %{success_count}/%{total_count} files."
+msgstr ""
+
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
+msgid "Migration successful."
+msgstr ""
+
+msgid "Milestone"
+msgid_plural "Milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+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|No milestones 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 "Minimum password length (number of characters)"
+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 "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 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 your errors by integrating with Sentry."
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Month"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More Information"
+msgstr ""
+
+msgid "More Slack commands"
+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 "Most stars"
+msgstr ""
+
+msgid "Mount point %{mounted_as} not found in %{model_class}."
+msgstr ""
+
+msgid "Move"
+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 "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+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 "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}More information%{linkEnd}"
+msgstr ""
+
+msgid "My Awesome Group"
+msgstr ""
+
+msgid "My company or team"
+msgstr ""
+
+msgid "My-Reaction"
+msgstr ""
+
+msgid "N/A"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name has already been 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 %{locked_project_count} project. To unlock it, please purchase additional storage"
+msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To learn more about reducing storage capacity please visit our docs."
+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 "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 "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 Policy|New rule"
+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|+ Add alert"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml mode"
+msgstr ""
+
+msgid "NetworkPolicies|Actions"
+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|Are you sure you want to delete this policy? This action cannot be undone."
+msgstr ""
+
+msgid "NetworkPolicies|Choose whether to enforce this policy."
+msgstr ""
+
+msgid "NetworkPolicies|Create policy"
+msgstr ""
+
+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 inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
+msgid "NetworkPolicies|Description"
+msgstr ""
+
+msgid "NetworkPolicies|Edit policy"
+msgstr ""
+
+msgid "NetworkPolicies|Editor mode"
+msgstr ""
+
+msgid "NetworkPolicies|Enforcement status"
+msgstr ""
+
+msgid "NetworkPolicies|Environment does not have deployment platform"
+msgstr ""
+
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
+msgid "NetworkPolicies|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 "NetworkPolicies|Invalid or empty policy"
+msgstr ""
+
+msgid "NetworkPolicies|Kubernetes error: %{error}"
+msgstr ""
+
+msgid "NetworkPolicies|Last modified"
+msgstr ""
+
+msgid "NetworkPolicies|Name"
+msgstr ""
+
+msgid "NetworkPolicies|Namespace"
+msgstr ""
+
+msgid "NetworkPolicies|Network Policy"
+msgstr ""
+
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
+msgid "NetworkPolicies|New policy"
+msgstr ""
+
+msgid "NetworkPolicies|No policies detected"
+msgstr ""
+
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
+msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
+msgstr ""
+
+msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
+msgstr ""
+
+msgid "NetworkPolicies|Policy definition"
+msgstr ""
+
+msgid "NetworkPolicies|Policy description"
+msgstr ""
+
+msgid "NetworkPolicies|Policy editor"
+msgstr ""
+
+msgid "NetworkPolicies|Policy preview"
+msgstr ""
+
+msgid "NetworkPolicies|Policy status"
+msgstr ""
+
+msgid "NetworkPolicies|Policy type"
+msgstr ""
+
+msgid "NetworkPolicies|Rule"
+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|Rules"
+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|Status"
+msgstr ""
+
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
+msgid "NetworkPolicies|Unable to parse policy"
+msgstr ""
+
+msgid "NetworkPolicies|YAML editor"
+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 "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New %{issueType}"
+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 Merge Request"
+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 branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New changes were added. %{linkStart}Reload the page to review them%{linkEnd}"
+msgstr ""
+
+msgid "New confidential epic title "
+msgstr ""
+
+msgid "New confidential issue title"
+msgstr ""
+
+msgid "New deploy key"
+msgstr ""
+
+msgid "New directory"
+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 title"
+msgstr ""
+
+msgid "New iteration"
+msgstr ""
+
+msgid "New iteration created"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New password"
+msgstr ""
+
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New release"
+msgstr ""
+
+msgid "New requirement"
+msgstr ""
+
+msgid "New response for issue #%{issue_iid}:"
+msgstr ""
+
+msgid "New runner. Has not connected yet"
+msgstr ""
+
+msgid "New runners registration token has been generated!"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New test case"
+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 will by default be external"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Next commit"
+msgstr ""
+
+msgid "Next file in diff"
+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 Epic"
+msgstr ""
+
+msgid "No Matching Results"
+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 authentication methods configured."
+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 commits present here"
+msgstr ""
+
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+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 required."
+msgstr ""
+
+msgid "No data found"
+msgstr ""
+
+msgid "No data to display"
+msgstr ""
+
+msgid "No deployments found"
+msgstr ""
+
+msgid "No due date"
+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 grouping"
+msgstr ""
+
+msgid "No issues found"
+msgstr ""
+
+msgid "No iteration"
+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 labels"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No matching results for \"%{query}\""
+msgstr ""
+
+msgid "No matching results..."
+msgstr ""
+
+msgid "No members 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 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 public groups"
+msgstr ""
+
+msgid "No ref selected"
+msgstr ""
+
+msgid "No related merge requests found."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No required pipeline"
+msgstr ""
+
+msgid "No runner executable"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+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 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 webhooks found, add one in the form above."
+msgstr ""
+
+msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} to renew your subscription."
+msgstr ""
+
+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 can sign in with read-only access and make read-only API requests."
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "None of the group milestones have the same project as the release"
+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 applicable to personal namespaced projects, which are deleted immediately on request."
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not available to run jobs."
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+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 parameters are invalid: %{errors}"
+msgstr ""
+
+msgid "Note that pushing to GitLab requires write access to this repository."
+msgstr ""
+
+msgid "Note that 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 "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 "NoteForm|Note"
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Private comments are accessible by internal staff only"
+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|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 "Nothing to synchronize"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "Notification settings saved"
+msgstr ""
+
+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|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 "NotificationSetting|Custom"
+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 "Novice"
+msgstr ""
+
+msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
+msgstr ""
+
+msgid "Number of %{itemTitle}"
+msgstr ""
+
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
+msgid "Number of LOCs per commit"
+msgstr ""
+
+msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
+msgstr ""
+
+msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
+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 "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 "Oldest first"
+msgstr ""
+
+msgid "OmniAuth"
+msgstr ""
+
+msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
+msgstr ""
+
+msgid "On"
+msgstr ""
+
+msgid "On track"
+msgstr ""
+
+msgid "On-call Schedules"
+msgstr ""
+
+msgid "On-call schedules"
+msgstr ""
+
+msgid "OnCallSchedules|Add a rotation"
+msgstr ""
+
+msgid "OnCallSchedules|Add a schedule"
+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|Create on-call schedules in GitLab"
+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|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"
+msgstr ""
+
+msgid "OnCallSchedules|On-call schedule for the %{timezone}"
+msgstr ""
+
+msgid "OnCallSchedules|Restrict to time intervals"
+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|Your schedule has been successfully created and all alerts from this project will now be routed to this schedule. Currently, only one schedule can be created per project. More coming soon! To add individual users to this schedule, use the add a rotation button."
+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|Description (optional)"
+msgstr ""
+
+msgid "OnDemandScans|Edit on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|For example: Tests the login page for SQL injections"
+msgstr ""
+
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
+msgid "OnDemandScans|Manage profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
+msgid "OnDemandScans|My daily 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 run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|Run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save and run scan"
+msgstr ""
+
+msgid "OnDemandScans|Save scan"
+msgstr ""
+
+msgid "OnDemandScans|Scan name"
+msgstr ""
+
+msgid "OnDemandScans|Scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profile"
+msgstr ""
+
+msgid "OnDemandScans|Use existing scanner profile"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "OnDemandScans|You can either choose a passive scan or validate the target site in your chosen site profile. %{docsLinkStart}Learn more about site validation.%{docsLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
+msgstr ""
+
+msgid "Once 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 "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
+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 the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
+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 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 this projects shows up in the search and on the dashboard."
+msgstr ""
+
+msgid "Only admins can delete project"
+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 Gold license are available in Security Dashboards."
+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 comment type dropdown"
+msgstr ""
+
+msgid "Open epics"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open in file view"
+msgstr ""
+
+msgid "Open issues"
+msgstr ""
+
+msgid "Open raw"
+msgstr ""
+
+msgid "Open registration is enabled on your instance."
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open: %{open}"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened %{epicTimeagoDate}"
+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 "Operations Settings"
+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 "Optional"
+msgstr ""
+
+msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
+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 "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 "Our documentation includes an example DevOps Score report."
+msgstr ""
+
+msgid "Out-of-compliance with this project's policies and should be removed"
+msgstr ""
+
+msgid "Outbound 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 "Overall Activity"
+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 "Package Registry"
+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 type must be Conan"
+msgstr ""
+
+msgid "Package type must be Debian"
+msgstr ""
+
+msgid "Package type must be Maven"
+msgstr ""
+
+msgid "Package type must be NuGet"
+msgstr ""
+
+msgid "Package type must be PyPi"
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Add Conan Remote"
+msgstr ""
+
+msgid "PackageRegistry|Add NuGet Source"
+msgstr ""
+
+msgid "PackageRegistry|Add composer registry"
+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|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 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 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 yarn command"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn setup command"
+msgstr ""
+
+msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
+msgstr ""
+
+msgid "PackageRegistry|Delete Package Version"
+msgstr ""
+
+msgid "PackageRegistry|Delete package"
+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|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|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|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|NPM"
+msgstr ""
+
+msgid "PackageRegistry|NuGet"
+msgstr ""
+
+msgid "PackageRegistry|NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Package Registry"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived update"
+msgstr ""
+
+msgid "PackageRegistry|Package has %{number} archived updates"
+msgstr ""
+
+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|Publish and share packages for a variety of common package managers. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|PyPI"
+msgstr ""
+
+msgid "PackageRegistry|Recipe: %{recipe}"
+msgstr ""
+
+msgid "PackageRegistry|Remove package"
+msgstr ""
+
+msgid "PackageRegistry|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "PackageRegistry|Source project located at %{link}"
+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|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 command"
+msgstr ""
+
+msgid "PackageRegistry|published by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|yarn command"
+msgstr ""
+
+msgid "PackageType|Composer"
+msgstr ""
+
+msgid "PackageType|Conan"
+msgstr ""
+
+msgid "PackageType|Generic"
+msgstr ""
+
+msgid "PackageType|Maven"
+msgstr ""
+
+msgid "PackageType|NPM"
+msgstr ""
+
+msgid "PackageType|NuGet"
+msgstr ""
+
+msgid "PackageType|PyPI"
+msgstr ""
+
+msgid "Packages"
+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 "Pages getting started guide"
+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|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 "Partial token for reference only"
+msgstr ""
+
+msgid "Participants"
+msgstr ""
+
+msgid "Pass job variables"
+msgstr ""
+
+msgid "Passed"
+msgstr ""
+
+msgid "Passed on"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password (optional)"
+msgstr ""
+
+msgid "Password Policy Guidelines"
+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 "Passwords should be unique and not used for any other sites or services."
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste a machine public key here. Read more about how to generate it"
+msgstr ""
+
+msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{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 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 ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Paths can contain wildcards, like */welcome"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Pause Elasticsearch indexing"
+msgstr ""
+
+msgid "Pause replication"
+msgstr ""
+
+msgid "Paused runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "Pending comments"
+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 common operations on GitLab project"
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "PerformanceBar|Bullet notifications"
+msgstr ""
+
+msgid "PerformanceBar|Download"
+msgstr ""
+
+msgid "PerformanceBar|Elasticsearch calls"
+msgstr ""
+
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
+msgid "PerformanceBar|Frontend resources"
+msgstr ""
+
+msgid "PerformanceBar|Gitaly calls"
+msgstr ""
+
+msgid "PerformanceBar|Redis calls"
+msgstr ""
+
+msgid "PerformanceBar|Rugged calls"
+msgstr ""
+
+msgid "PerformanceBar|SQL queries"
+msgstr ""
+
+msgid "PerformanceBar|trace"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions Help"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal Access Token prefix"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+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 Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline cannot be run."
+msgstr ""
+
+msgid "Pipeline minutes quota"
+msgstr ""
+
+msgid "Pipeline minutes quota:"
+msgstr ""
+
+msgid "Pipeline ran in fork of project"
+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 ocurred when retrieving the analytics data"
+msgstr ""
+
+msgid "PipelineCharts|An error has ocurred 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 "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 "PipelineStatusTooltip|Pipeline: %{ciStatus}"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines emails"
+msgstr ""
+
+msgid "Pipelines for last month (%{oneMonthAgo} - %{today})"
+msgstr ""
+
+msgid "Pipelines for last week (%{oneWeekAgo} - %{today})"
+msgstr ""
+
+msgid "Pipelines for last year"
+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 ""
+
+msgid "Pipelines|API"
+msgstr ""
+
+msgid "Pipelines|Are you sure you want to run this pipeline?"
+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|Child pipeline"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Copy trigger token"
+msgstr ""
+
+msgid "Pipelines|Description"
+msgstr ""
+
+msgid "Pipelines|Edit"
+msgstr ""
+
+msgid "Pipelines|Editor"
+msgstr ""
+
+msgid "Pipelines|Get started with CI/CD"
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+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|Group %{namespace_name} has %{percentage}%% or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|Group %{namespace_name} has exceeded its pipeline minutes quota. Unless you buy additional pipeline minutes, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
+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|Lint"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+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|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+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 is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+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|Token"
+msgstr ""
+
+msgid "Pipelines|Trigger user has insufficient permissions to project"
+msgstr ""
+
+msgid "Pipelines|Validating GitLab CI configuration…"
+msgstr ""
+
+msgid "Pipelines|Visualize"
+msgstr ""
+
+msgid "Pipelines|Write pipeline configuration"
+msgstr ""
+
+msgid "Pipelines|invalid"
+msgstr ""
+
+msgid "Pipelines|parent"
+msgstr ""
+
+msgid "Pipeline|Branch name"
+msgstr ""
+
+msgid "Pipeline|Canceled"
+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|Coverage"
+msgstr ""
+
+msgid "Pipeline|Created"
+msgstr ""
+
+msgid "Pipeline|Date"
+msgstr ""
+
+msgid "Pipeline|Detached merge request pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Failed"
+msgstr ""
+
+msgid "Pipeline|Key"
+msgstr ""
+
+msgid "Pipeline|Manual"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline"
+msgstr ""
+
+msgid "Pipeline|Merged result pipeline"
+msgstr ""
+
+msgid "Pipeline|Passed"
+msgstr ""
+
+msgid "Pipeline|Pending"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Pipelines"
+msgstr ""
+
+msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run for"
+msgstr ""
+
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Running"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Skipped"
+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|Specify variable values to be used in this run. The values specified in %{settings_link} 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|Trigger author"
+msgstr ""
+
+msgid "Pipeline|Triggerer"
+msgstr ""
+
+msgid "Pipeline|Value"
+msgstr ""
+
+msgid "Pipeline|Variables"
+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|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "Plan"
+msgstr ""
+
+msgid "Plan:"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Play all manual"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+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 add a list to your board first"
+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 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 choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please complete your profile with email address"
+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 enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please ensure your account's %{account_link_start}recovery settings%{account_link_end} are up to date."
+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 or upload a license."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+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 only enable search after installing the plugin, enabling indexing and recreating the index"
+msgstr ""
+
+msgid "Please provide a name"
+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 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 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 set a new password before proceeding."
+msgstr ""
+
+msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+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 "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
+msgstr ""
+
+msgid "Pod does not exist"
+msgstr ""
+
+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 "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|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+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|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|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|Tab width"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+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 display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
+msgid "Prev"
+msgstr ""
+
+msgid "Prevent MR approvals by author."
+msgstr ""
+
+msgid "Prevent MR approvals by the author."
+msgstr ""
+
+msgid "Prevent MR approvals from users who make commits to the MR."
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+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 modifying MR approval rules."
+msgstr ""
+
+msgid "Prevent users from performing write operations on GitLab while performing maintenance."
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview Markdown"
+msgstr ""
+
+msgid "Preview changes"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Previous Artifacts"
+msgstr ""
+
+msgid "Previous commit"
+msgstr ""
+
+msgid "Previous file in diff"
+msgstr ""
+
+msgid "Previous unresolved discussion"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Print codes"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+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 "ProfilePreferences|Customize integrations with third party services."
+msgstr ""
+
+msgid "ProfilePreferences|Enable Gitpod integration"
+msgstr ""
+
+msgid "ProfilePreferences|Enable integrated code intelligence on code views"
+msgstr ""
+
+msgid "ProfilePreferences|Gitpod"
+msgstr ""
+
+msgid "ProfilePreferences|Integrations"
+msgstr ""
+
+msgid "ProfilePreferences|Sourcegraph"
+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|\"Busy\" will be shown next to your name"
+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|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+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|Click on icon to activate signin with one of the following services"
+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 profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Expires at"
+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."
+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 password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Key"
+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|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|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Public email"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+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 doesn't look like a public SSH key, are you sure you want to add it? It will be publicly visible."
+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|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+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|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 set your current timezone here"
+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 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 key has expired"
+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|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+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 Audit Events"
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project Files"
+msgstr ""
+
+msgid "Project ID"
+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 already deleted"
+msgstr ""
+
+msgid "Project and wiki repositories"
+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 details"
+msgstr ""
+
+msgid "Project does not exist or you don't have permission to perform this action"
+msgstr ""
+
+msgid "Project export could not be deleted."
+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 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 info:"
+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 name suffix"
+msgstr ""
+
+msgid "Project navigation"
+msgstr ""
+
+msgid "Project order will not be saved as local storage is not available."
+msgstr ""
+
+msgid "Project overview"
+msgstr ""
+
+msgid "Project path"
+msgstr ""
+
+msgid "Project scanning help page"
+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 "ProjectLifecycle|Stage"
+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 have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectService|%{service_title}: status off"
+msgstr ""
+
+msgid "ProjectService|%{service_title}: status on"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered by a push to the repository"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgstr ""
+
+msgid "ProjectService|To set up this service:"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow"
+msgstr ""
+
+msgid "ProjectSettings|Allow editing commit messages"
+msgstr ""
+
+msgid "ProjectSettings|Allow users to make copies of your repository to a new project"
+msgstr ""
+
+msgid "ProjectSettings|Allow users to request access"
+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 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|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Container registry"
+msgstr ""
+
+msgid "ProjectSettings|Customize this project's badges."
+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|Environments, logs, cluster management, and more"
+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|Forks"
+msgstr ""
+
+msgid "ProjectSettings|Git Large File Storage (LFS)"
+msgstr ""
+
+msgid "ProjectSettings|Global"
+msgstr ""
+
+msgid "ProjectSettings|If pipelines for merge requests are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches."
+msgstr ""
+
+msgid "ProjectSettings|Internal"
+msgstr ""
+
+msgid "ProjectSettings|Issues"
+msgstr ""
+
+msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
+msgstr ""
+
+msgid "ProjectSettings|Lightweight issue tracking system for this project"
+msgstr ""
+
+msgid "ProjectSettings|Manages large files such as audio, video, and graphics files"
+msgstr ""
+
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+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 suggestions"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
+msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|Operations"
+msgstr ""
+
+msgid "ProjectSettings|Packages"
+msgstr ""
+
+msgid "ProjectSettings|Pages"
+msgstr ""
+
+msgid "ProjectSettings|Pages for project documentation"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Private"
+msgstr ""
+
+msgid "ProjectSettings|Project visibility"
+msgstr ""
+
+msgid "ProjectSettings|Public"
+msgstr ""
+
+msgid "ProjectSettings|Repository"
+msgstr ""
+
+msgid "ProjectSettings|Require"
+msgstr ""
+
+msgid "ProjectSettings|Requirements"
+msgstr ""
+
+msgid "ProjectSettings|Requirements management system for this project"
+msgstr ""
+
+msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgstr ""
+
+msgid "ProjectSettings|Share code pastes with others out of Git repository"
+msgstr ""
+
+msgid "ProjectSettings|Show default award emojis"
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|Skipped pipelines are considered successful"
+msgstr ""
+
+msgid "ProjectSettings|Snippets"
+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|The commit message used to apply merge request suggestions"
+msgstr ""
+
+msgid "ProjectSettings|The variables GitLab supports:"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
+msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+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|This setting will override user notification preferences for all project members."
+msgstr ""
+
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
+msgid "ProjectSettings|Transfer 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|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 project analytics"
+msgstr ""
+
+msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
+msgstr ""
+
+msgid "ProjectSettings|What are badges?"
+msgstr ""
+
+msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
+msgstr ""
+
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectSettings|When enabled, commit authors will be able to edit commit messages on unprotected branches."
+msgstr ""
+
+msgid "ProjectSettings|When enabled, issues, merge requests, and snippets will always show thumbs-up and thumbs-down award emoji buttons."
+msgstr ""
+
+msgid "ProjectSettings|Wiki"
+msgstr ""
+
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab"
+msgstr ""
+
+msgid "ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics"
+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|iOS (Swift)"
+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 shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "Projects to index"
+msgstr ""
+
+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 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|Blank"
+msgstr ""
+
+msgid "ProjectsNew|Blank project"
+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 blank project"
+msgstr ""
+
+msgid "ProjectsNew|Create from template"
+msgstr ""
+
+msgid "ProjectsNew|Create new project"
+msgstr ""
+
+msgid "ProjectsNew|Creating project & repository."
+msgstr ""
+
+msgid "ProjectsNew|Description format"
+msgstr ""
+
+msgid "ProjectsNew|Import"
+msgstr ""
+
+msgid "ProjectsNew|Import project"
+msgstr ""
+
+msgid "ProjectsNew|Initialize repository with a README"
+msgstr ""
+
+msgid "ProjectsNew|No import options available"
+msgstr ""
+
+msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
+msgstr ""
+
+msgid "ProjectsNew|Run CI/CD for external repository"
+msgstr ""
+
+msgid "ProjectsNew|Template"
+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|%{count} alerts applied"
+msgstr ""
+
+msgid "PrometheusAlerts|%{firingCount} firing"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Firing: %{alerts}"
+msgstr ""
+
+msgid "PrometheusAlerts|Firing: %{alert}"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Runbook URL (optional)"
+msgstr ""
+
+msgid "PrometheusAlerts|Select query"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+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"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)"
+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|Contents of the credentials.json file of your service account, like: { \"type\": \"service_account\", \"project_id\": ... }"
+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|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+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 API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used."
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+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 has been deprecated."
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote confidential issue to a non-confidential epic"
+msgstr ""
+
+msgid "Promote issue to an epic"
+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 confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members."
+msgstr ""
+
+msgid "Promoted issue to an epic."
+msgstr ""
+
+msgid "Promotion is not supported."
+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|Dismiss burndown charts 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 milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Learn more"
+msgstr ""
+
+msgid "Promotions|Not now, thanks!"
+msgstr ""
+
+msgid "Promotions|See the other features in the %{subscription_link_start}bronze plan%{subscription_link_end}"
+msgstr ""
+
+msgid "Promotions|Start GitLab Ultimate trial"
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Promotions|Try it for free"
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
+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|With Contribution Analytics you can have an overview for the activity of issues, merge requests, and push events of your organization and its members."
+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 Environments"
+msgstr ""
+
+msgid "Protected Paths"
+msgstr ""
+
+msgid "Protected Tag"
+msgstr ""
+
+msgid "Protected Tags"
+msgstr ""
+
+msgid "Protected branches"
+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|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:"
+msgstr ""
+
+msgid "ProtectedBranch|Code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Does not apply to users allowed to push."
+msgstr ""
+
+msgid "ProtectedBranch|Protect"
+msgstr ""
+
+msgid "ProtectedBranch|Protect a branch"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
+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 code owner approval"
+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|Select users to deploy and manage Feature Flag settings"
+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 "Protip:"
+msgstr ""
+
+msgid "Protocol"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Proxy support for this API is not available currently"
+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 (%{deploy_keys_count})"
+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 "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 "PushRule|Committer restriction"
+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|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|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query cannot be processed"
+msgstr ""
+
+msgid "Query is valid"
+msgstr ""
+
+msgid "Queued"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Quick range"
+msgstr ""
+
+msgid "Quickly and easily edit multiple files in your project."
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Rails"
+msgstr ""
+
+msgid "Rake Tasks Help"
+msgstr ""
+
+msgid "Random"
+msgstr ""
+
+msgid "Raw blob request rate limit per minute"
+msgstr ""
+
+msgid "Re-authentication period expired or never requested. Please try again"
+msgstr ""
+
+msgid "Re-authentication required"
+msgstr ""
+
+msgid "Re-verification interval"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
+msgstr ""
+
+msgid "Read more about related issues"
+msgstr ""
+
+msgid "Real-time features"
+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 "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Receive notifications about your own activity"
+msgstr ""
+
+msgid "Recent"
+msgstr ""
+
+msgid "Recent Activity"
+msgstr ""
+
+msgid "Recent Project Activity"
+msgstr ""
+
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
+msgid "Recent jobs served by this runner"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Reconfigure"
+msgstr ""
+
+msgid "Recover hidden stage"
+msgstr ""
+
+msgid "Recovering projects"
+msgstr ""
+
+msgid "Recovery Codes"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Redis"
+msgstr ""
+
+msgid "Reduce project visibility"
+msgstr ""
+
+msgid "Reduce this project’s visibility?"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "References"
+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 key"
+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 "Region that Elasticsearch is configured"
+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 a runner on a Kubernetes cluster. %{link_to_help_page}"
+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|Checkout"
+msgstr ""
+
+msgid "Registration|Your GitLab group"
+msgstr ""
+
+msgid "Registration|Your first project"
+msgstr ""
+
+msgid "Registration|Your profile"
+msgstr ""
+
+msgid "Registry setup"
+msgstr ""
+
+msgid "Regulate approvals by authors/committers. Affects all projects."
+msgstr ""
+
+msgid "Reindexing Status: %{status}"
+msgstr ""
+
+msgid "Rejected (closed)"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related issues"
+msgstr ""
+
+msgid "Related merge requests"
+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 "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%{codeEnd}, %{codeStart}v2.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 "Remediations"
+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 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 avatar"
+msgstr ""
+
+msgid "Remove card"
+msgstr ""
+
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove description history"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
+msgid "Remove fork relationship"
+msgstr ""
+
+msgid "Remove from batch"
+msgstr ""
+
+msgid "Remove from board"
+msgstr ""
+
+msgid "Remove from epic"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove iteration"
+msgstr ""
+
+msgid "Remove license"
+msgstr ""
+
+msgid "Remove limit"
+msgstr ""
+
+msgid "Remove list"
+msgstr ""
+
+msgid "Remove member"
+msgstr ""
+
+msgid "Remove milestone"
+msgstr ""
+
+msgid "Remove node"
+msgstr ""
+
+msgid "Remove parent epic from an epic"
+msgstr ""
+
+msgid "Remove primary node"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove report"
+msgstr ""
+
+msgid "Remove reviewer"
+msgstr ""
+
+msgid "Remove runner"
+msgstr ""
+
+msgid "Remove secondary node"
+msgstr ""
+
+msgid "Remove spent time"
+msgstr ""
+
+msgid "Remove stage"
+msgstr ""
+
+msgid "Remove time estimate"
+msgstr ""
+
+msgid "Remove user & report"
+msgstr ""
+
+msgid "Remove user from group"
+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 %{type} with id %{id}"
+msgstr ""
+
+msgid "Removed all labels."
+msgstr ""
+
+msgid "Removed an issue from an epic."
+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 "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
+msgstr ""
+
+msgid "RemovedProjects|You haven’t removed any projects."
+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 "Renew subscription"
+msgstr ""
+
+msgid "Reopen"
+msgstr ""
+
+msgid "Reopen %{issueType}"
+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 "Repair authentication"
+msgstr ""
+
+msgid "Replace"
+msgstr ""
+
+msgid "Replace all label(s)"
+msgstr ""
+
+msgid "Replaced all labels with %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Replaces the clone URL root."
+msgstr ""
+
+msgid "Replication"
+msgstr ""
+
+msgid "Replication details"
+msgstr ""
+
+msgid "Replication enabled"
+msgstr ""
+
+msgid "Replication paused"
+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 %{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 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|An error occured while loading report"
+msgstr ""
+
+msgid "Reports|An error occurred while loading %{name} results"
+msgstr ""
+
+msgid "Reports|Class"
+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|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|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|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|Last Update"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Latest test coverage results"
+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|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 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 must contain at least 1 file."
+msgstr ""
+
+msgid "Repository size is above the limit."
+msgstr ""
+
+msgid "Repository static objects"
+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} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Request details"
+msgstr ""
+
+msgid "Request parameter %{param} is missing."
+msgstr ""
+
+msgid "Request review from"
+msgstr ""
+
+msgid "Request to link SAML account must be authorized"
+msgstr ""
+
+msgid "Requested"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requested design version does not exist."
+msgstr ""
+
+msgid "Requested states are invalid"
+msgstr ""
+
+msgid "Requests"
+msgstr ""
+
+msgid "Requests Profiles"
+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 admin approval for new sign-ups"
+msgstr ""
+
+msgid "Require all users in this group to setup two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Require new approvals when new commits are added to an MR."
+msgstr ""
+
+msgid "Require user password for approvals."
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+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 "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 approval from %{names}."
+msgid_plural "Requires %{count} more approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires approval."
+msgid_plural "Requires %d more approvals."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires values to meet regular expression requirements."
+msgstr ""
+
+msgid "Resend Request"
+msgstr ""
+
+msgid "Resend confirmation email"
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Resend it"
+msgstr ""
+
+msgid "Reset"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset filters"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset registration token"
+msgstr ""
+
+msgid "Reset template"
+msgstr ""
+
+msgid "Reset to project defaults"
+msgstr ""
+
+msgid "Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
+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 all threads in new issue"
+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 "Resolves IP addresses once and uses them to submit requests"
+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 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 membership by email domain"
+msgstr ""
+
+msgid "Restrict projects for this runner"
+msgstr ""
+
+msgid "Restricts sign-ups for email addresses that match the given regex. See the %{supported_syntax_link_start}supported syntax%{supported_syntax_link_end} for more information."
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Resync"
+msgstr ""
+
+msgid "Resync all"
+msgstr ""
+
+msgid "Resync all %{replicableType}"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry job"
+msgstr ""
+
+msgid "Retry migration"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry this job in order to create the necessary resources."
+msgstr ""
+
+msgid "Retry update"
+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 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 impersonation token %{token_name}!"
+msgstr ""
+
+msgid "Revoked personal access token %{personal_access_token_name}!"
+msgstr ""
+
+msgid "Revoked project access token %{project_access_token_name}!"
+msgstr ""
+
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Role"
+msgstr ""
+
+msgid "Rollback"
+msgstr ""
+
+msgid "Rook"
+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 CI/CD pipelines for external repositories"
+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 is %{status}, last contact was %{runner_contact} ago"
+msgstr ""
+
+msgid "Runner token"
+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 can be:"
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|Active"
+msgstr ""
+
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
+msgid "Runners|Architecture"
+msgstr ""
+
+msgid "Runners|Can run untagged jobs"
+msgstr ""
+
+msgid "Runners|Copy instructions"
+msgstr ""
+
+msgid "Runners|Description"
+msgstr ""
+
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
+msgid "Runners|Group"
+msgstr ""
+
+msgid "Runners|IP Address"
+msgstr ""
+
+msgid "Runners|Install a Runner"
+msgstr ""
+
+msgid "Runners|Last contact"
+msgstr ""
+
+msgid "Runners|Locked to this project"
+msgstr ""
+
+msgid "Runners|Maximum job timeout"
+msgstr ""
+
+msgid "Runners|Name"
+msgstr ""
+
+msgid "Runners|Platform"
+msgstr ""
+
+msgid "Runners|Property Name"
+msgstr ""
+
+msgid "Runners|Protected"
+msgstr ""
+
+msgid "Runners|Register Runner"
+msgstr ""
+
+msgid "Runners|Revision"
+msgstr ""
+
+msgid "Runners|Shared"
+msgstr ""
+
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
+msgid "Runners|Specific"
+msgstr ""
+
+msgid "Runners|Tags"
+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|Value"
+msgstr ""
+
+msgid "Runners|Version"
+msgstr ""
+
+msgid "Runners|View installation instructions"
+msgstr ""
+
+msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+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 "Runs jobs from all unassigned projects in its group."
+msgstr ""
+
+msgid "Runs jobs from all unassigned projects."
+msgstr ""
+
+msgid "Runs jobs from assigned projects."
+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 allow you to establish a secure connection between your computer and GitLab."
+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 Push Rules"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save password"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save space and find images in the Container Registry. Remove unneeded tags and keep only the ones you want."
+msgstr ""
+
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
+msgid "Saving"
+msgstr ""
+
+msgid "Saving project."
+msgstr ""
+
+msgid "Scanner"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Scheduled Deletion At - %{permanent_deletion_time}"
+msgstr ""
+
+msgid "Scheduled a rebase of branch %{branch}."
+msgstr ""
+
+msgid "Scheduled to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Schedules to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Scheduling"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scope board to current iteration"
+msgstr ""
+
+msgid "Scopes"
+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 Jira issues"
+msgstr ""
+
+msgid "Search a group"
+msgstr ""
+
+msgid "Search an environment spec"
+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 merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or filter results…"
+msgstr ""
+
+msgid "Search or jump to…"
+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 "Seat Link"
+msgstr ""
+
+msgid "Seat Link is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "SeatUsage|Seat usage"
+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 "Seconds"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Secret Detection"
+msgstr ""
+
+msgid "Secret Token"
+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 "SecurityApprovals|Configurable if security scanners are enabled. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}Learn more%{linkEnd}."
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilities of Critical, High, or Unknown severity. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|An error occurred while creating the merge request."
+msgstr ""
+
+msgid "SecurityConfiguration|Available for on-demand DAST"
+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|Configure"
+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"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable via Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled with Auto DevOps"
+msgstr ""
+
+msgid "SecurityConfiguration|Feature documentation for %{featureName}"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage"
+msgstr ""
+
+msgid "SecurityConfiguration|More information"
+msgstr ""
+
+msgid "SecurityConfiguration|Not enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Analyzers"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
+msgid "SecurityConfiguration|Security Control"
+msgstr ""
+
+msgid "SecurityConfiguration|Status"
+msgstr ""
+
+msgid "SecurityConfiguration|Testing & Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|View history"
+msgstr ""
+
+msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgstr ""
+
+msgid "SecurityReports|Add a project to your dashboard"
+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|Add projects to your group"
+msgstr ""
+
+msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Create issue"
+msgstr ""
+
+msgid "SecurityReports|Dismiss Selected"
+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 Report"
+msgstr ""
+
+msgid "SecurityReports|Download results"
+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|Failed to get security report information. Please reload the page or try again later."
+msgstr ""
+
+msgid "SecurityReports|False positive"
+msgstr ""
+
+msgid "SecurityReports|Fuzzing artifacts"
+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|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
+msgstr ""
+
+msgid "SecurityReports|More information"
+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|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|Scanner"
+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|Select a reason"
+msgstr ""
+
+msgid "SecurityReports|Severity"
+msgstr ""
+
+msgid "SecurityReports|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "SecurityReports|Status"
+msgstr ""
+
+msgid "SecurityReports|The rating \"unknown\" indicates that the underlying scanner doesn’t contain or provide a severity rating."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+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 %d vulnerability. Please try again later."
+msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
+msgstr[0] ""
+msgstr[1] ""
+
+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|To widen your search, change or remove filters above"
+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 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|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "SecurityReports|Won't fix / Accept risk"
+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|[No reason]"
+msgstr ""
+
+msgid "See GitLab's %{password_policy_guidelines}"
+msgstr ""
+
+msgid "See metrics"
+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 GitLab project to link with your Slack team"
+msgstr ""
+
+msgid "Select Page"
+msgstr ""
+
+msgid "Select Stack"
+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 namespace to fork the project"
+msgstr ""
+
+msgid "Select a new namespace"
+msgstr ""
+
+msgid "Select a project"
+msgstr ""
+
+msgid "Select a project to read Insights configuration file"
+msgstr ""
+
+msgid "Select a reason"
+msgstr ""
+
+msgid "Select a repository"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a template type"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select all"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select due date"
+msgstr ""
+
+msgid "Select epic"
+msgstr ""
+
+msgid "Select file"
+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 projects"
+msgstr ""
+
+msgid "Select required regulatory standard"
+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 subscription"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Select timezone"
+msgstr ""
+
+msgid "Select type"
+msgstr ""
+
+msgid "Select user"
+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 "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 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|Disable self monitoring?"
+msgstr ""
+
+msgid "SelfMonitoring|Disabling this feature will delete the self monitoring project. Are you sure you want to delete the project?"
+msgstr ""
+
+msgid "SelfMonitoring|Enable or disable instance self monitoring"
+msgstr ""
+
+msgid "SelfMonitoring|Enabling this feature creates a %{projectLinkStart}project%{projectLinkEnd} that can be used to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Enabling this feature creates a project that can be used to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring"
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project has been successfully created."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
+msgstr ""
+
+msgid "Send a separate email notification to Developers."
+msgstr ""
+
+msgid "Send confirmation email"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send email notification"
+msgstr ""
+
+msgid "Send message"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sentry event"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "Separate topics with commas."
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "SeriesFinalConjunction|and"
+msgstr ""
+
+msgid "Serve repository static objects (e.g. archives, blobs, ...) from an external storage (e.g. a CDN)."
+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 domain"
+msgstr ""
+
+msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
+msgstr ""
+
+msgid "ServerlessDetails|Install Prometheus"
+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|Install Knative"
+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 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 Desk is enabled but not yet active"
+msgstr ""
+
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session ID"
+msgstr ""
+
+msgid "Session duration (minutes)"
+msgstr ""
+
+msgid "Set %{epic_ref} as the parent epic."
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning 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 "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 a template repository for projects in this group"
+msgstr ""
+
+msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set due date"
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set iteration"
+msgstr ""
+
+msgid "Set limit to 0 to allow any file size."
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set milestone"
+msgstr ""
+
+msgid "Set new password"
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set parent epic to an epic"
+msgstr ""
+
+msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
+msgstr ""
+
+msgid "Set the default name of the initial branch when creating new repositories through the user interface."
+msgstr ""
+
+msgid "Set the due date to %{due_date}."
+msgstr ""
+
+msgid "Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}."
+msgstr ""
+
+msgid "Set the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Set the maximum file size for each job's artifacts"
+msgstr ""
+
+msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
+msgstr ""
+
+msgid "Set the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
+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 automatically"
+msgstr ""
+
+msgid "Set up a %{type} runner manually"
+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 node."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|\"Busy\" will be shown next to your name"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Busy"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+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 "Sets %{epic_ref} as parent epic."
+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 time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
+msgid "Setting this to 0 means using the system default timeout value."
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Settings related to the use and experience of using GitLab's Package Registry."
+msgstr ""
+
+msgid "Setup"
+msgstr ""
+
+msgid "Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity: %{severity}"
+msgstr ""
+
+msgid "SeverityWidget|There was an error while updating severity."
+msgstr ""
+
+msgid "Shards (%{shards})"
+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 disabled on group level"
+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 "Sherlock Transactions"
+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 all activity"
+msgstr ""
+
+msgid "Show all issues."
+msgstr ""
+
+msgid "Show all members"
+msgstr ""
+
+msgid "Show all test cases."
+msgstr ""
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Show comments on this file"
+msgstr ""
+
+msgid "Show comments only"
+msgstr ""
+
+msgid "Show commit description"
+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 links anyways"
+msgstr ""
+
+msgid "Show list"
+msgstr ""
+
+msgid "Show me advanced features"
+msgstr ""
+
+msgid "Show me how to add a pipeline"
+msgstr ""
+
+msgid "Show me the basics"
+msgstr ""
+
+msgid "Show one file at a time"
+msgstr ""
+
+msgid "Show only direct members"
+msgstr ""
+
+msgid "Show only inherited members"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+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_start}%{conflicts_text}%{strong_end} between %{ref_start}%{source_branch}%{strong_end} and %{ref_start}%{target_branch}%{strong_end}"
+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} issues"
+msgstr ""
+
+msgid "Showing all issues"
+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|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 "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+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 Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-in text"
+msgstr ""
+
+msgid "Sign-up restrictions"
+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 "Single or combined queries"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Size limit per repository (MB)"
+msgstr ""
+
+msgid "Size settings for static websites"
+msgstr ""
+
+msgid "Skip outdated deployment jobs"
+msgstr ""
+
+msgid "Skipped"
+msgstr ""
+
+msgid "Skipped deployment to"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack channels (e.g. general, development)"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported."
+msgstr ""
+
+msgid "SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event."
+msgstr ""
+
+msgid "SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below."
+msgstr ""
+
+msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
+msgstr ""
+
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
+msgstr ""
+
+msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
+msgstr ""
+
+msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, press %{strong_open}Save changes%{strong_close} and start using GitLab inside Slack!"
+msgstr ""
+
+msgid "SlackService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "SlackService|See list of available commands in Slack after setting up this service, by entering"
+msgstr ""
+
+msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+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|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
+msgid "Snippets|Description (optional)"
+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. %{read_more_link}."
+msgstr ""
+
+msgid "Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead."
+msgstr ""
+
+msgid "Some of the designs you tried uploading did not change:"
+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 "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 confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+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 package."
+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 %{listType} list"
+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 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 the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the package."
+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 moving issues."
+msgstr ""
+
+msgid "Something went wrong while obtaining the Let's Encrypt certificate."
+msgstr ""
+
+msgid "Something went wrong while performing the action."
+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 stopping this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while toggling auto-fix settings, please try again later."
+msgstr ""
+
+msgid "Something went wrong while updating a requirement."
+msgstr ""
+
+msgid "Something went wrong while updating assignees"
+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 epics matched your search"
+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|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Blocking"
+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|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Manual"
+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 joined"
+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|Relevant"
+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|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 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 "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 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 e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Speed up your pipelines with Needs relationships"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stack trace"
+msgstr ""
+
+msgid "Stacktrace snippet"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage data updated"
+msgstr ""
+
+msgid "Stage removed"
+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 review"
+msgstr ""
+
+msgid "Start and due date"
+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 search"
+msgstr ""
+
+msgid "Start thread"
+msgstr ""
+
+msgid "Start thread & close %{noteable_name}"
+msgstr ""
+
+msgid "Start thread & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start your Free Ultimate Trial"
+msgstr ""
+
+msgid "Start your free trial"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Started asynchronous removal of all repository check states."
+msgstr ""
+
+msgid "Started:"
+msgstr ""
+
+msgid "Starting..."
+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 "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 "StatusPage|AWS Secret access key"
+msgstr ""
+
+msgid "StatusPage|AWS access key ID"
+msgstr ""
+
+msgid "StatusPage|AWS documentation"
+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|For help with configuration, visit %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|S3 Bucket name"
+msgstr ""
+
+msgid "StatusPage|Status page"
+msgstr ""
+
+msgid "StatusPage|Status page URL"
+msgstr ""
+
+msgid "StatusPage|Status page frontend documentation"
+msgstr ""
+
+msgid "StatusPage|To publish incidents to an external status page, GitLab will store a JSON file in your Amazon S3 account in a location accessible to your external status page service. 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 "Still, we recommend keeping a backup saved somewhere. Otherwise, if you ever need it and have lost it, you will need to request GitLab Inc. to send it to you again."
+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 "Subgroup milestone"
+msgstr ""
+
+msgid "Subgroup navigation"
+msgstr ""
+
+msgid "Subgroup overview"
+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 %{humanized_resource_name}"
+msgstr ""
+
+msgid "Submit a review"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit changes"
+msgstr ""
+
+msgid "Submit changes..."
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit issue"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Submit the current review."
+msgstr ""
+
+msgid "Submit your changes"
+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 "Subscribes to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Subscription deletion failed."
+msgstr ""
+
+msgid "Subscription successfully applied to \"%{group_name}\""
+msgstr ""
+
+msgid "Subscription successfully created."
+msgstr ""
+
+msgid "Subscription successfully deleted."
+msgstr ""
+
+msgid "SubscriptionTable|Add seats"
+msgstr ""
+
+msgid "SubscriptionTable|An error occurred while loading billable members list"
+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|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|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|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Subscriptions"
+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 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 unblocked"
+msgstr ""
+
+msgid "Successfully unlocked"
+msgstr ""
+
+msgid "Successfully verified domain ownership"
+msgstr ""
+
+msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
+msgstr ""
+
+msgid "Suggested Solutions"
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Suggested solutions help link"
+msgstr ""
+
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+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 "Sunday"
+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 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 information"
+msgstr ""
+
+msgid "Sync now"
+msgstr ""
+
+msgid "Synced"
+msgstr ""
+
+msgid "Synchronization disabled"
+msgstr ""
+
+msgid "Synchronization settings"
+msgstr ""
+
+msgid "Syncing…"
+msgstr ""
+
+msgid "Syntax is correct."
+msgstr ""
+
+msgid "Syntax is incorrect."
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Hooks Help"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System hook was successfully updated."
+msgstr ""
+
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "System output"
+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|Sort by"
+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|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 ID: %{elastic_task}"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Team domain"
+msgstr ""
+
+msgid "Telephone number"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Template to append to all Service Desk issues"
+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 "Terraform"
+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|%{user} updated %{timeAgo}"
+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|Details"
+msgstr ""
+
+msgid "Terraform|Download JSON"
+msgstr ""
+
+msgid "Terraform|Find out how to use the %{linkStart}GitLab managed Terraform State%{linkEnd}"
+msgstr ""
+
+msgid "Terraform|Generating the report caused an error."
+msgstr ""
+
+msgid "Terraform|Get started with Terraform"
+msgstr ""
+
+msgid "Terraform|Job status"
+msgstr ""
+
+msgid "Terraform|Lock"
+msgstr ""
+
+msgid "Terraform|Locked"
+msgstr ""
+
+msgid "Terraform|Locked by %{user} %{timeAgo}"
+msgstr ""
+
+msgid "Terraform|Name"
+msgstr ""
+
+msgid "Terraform|Pipeline"
+msgstr ""
+
+msgid "Terraform|Remove"
+msgstr ""
+
+msgid "Terraform|Remove state file and versions"
+msgstr ""
+
+msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
+msgstr ""
+
+msgid "Terraform|States"
+msgstr ""
+
+msgid "Terraform|The report %{name} failed to generate."
+msgstr ""
+
+msgid "Terraform|The report %{name} was generated in your pipelines."
+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|You are about to remove the State file %{name}. This will permanently delete all the State versions and history. The infrastructure provisioned previously\twill remain intact, only the state file with all its versions are to be removed. This action is non-revertible."
+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 cases are not available for this project"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+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 Todo."
+msgstr ""
+
+msgid "TestCases|Something went wrong while creating a test case."
+msgstr ""
+
+msgid "TestCases|Something went wrong while fetching count of test cases."
+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 todo 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|Jobs"
+msgstr ""
+
+msgid "TestReports|Tests"
+msgstr ""
+
+msgid "TestReports|There are no test cases to display."
+msgstr ""
+
+msgid "TestReports|There are no test suites to show."
+msgstr ""
+
+msgid "TestReports|There are no tests to show."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the summary."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the test suite."
+msgstr ""
+
+msgid "Tests"
+msgstr ""
+
+msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
+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 your purchase!"
+msgstr ""
+
+msgid "That is ok, I do not 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 \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+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 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 "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
+msgstr ""
+
+msgid "The Compliance Dashboard gives you the ability to see a group's merge request activity by providing a high-level view for all projects in the group."
+msgstr ""
+
+msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
+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 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}More information%{linkEnd}"
+msgstr ""
+
+msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
+msgstr ""
+
+msgid "The Vulnerability Report shows the results of the last successful pipeline run on the default branch."
+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 ""
+
+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 coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The commit does not exist"
+msgstr ""
+
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+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 source is connected, but there is no data to display. %{documentationLink}"
+msgstr ""
+
+msgid "The default CI configuration path for new projects."
+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 designs you tried uploading did not change."
+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 errors we encountered were:"
+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 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 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 can be fully restored"
+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 will be placed in 'pending removal' state"
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+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 stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
+msgstr ""
+
+msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
+msgstr ""
+
+msgid "The 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 maximum file size allowed is %{size}."
+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 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 merge request can now be merged."
+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 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 passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipeline has been deleted"
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+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 pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+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 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 review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "The schedule time must be in the future!"
+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 staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The status of the table below only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
+msgid "The tag name can't be changed for an existing release."
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+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 usage ping is disabled, and cannot be configured through this form."
+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 value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "The value of the provided variable exceeds the %{count} character limit"
+msgstr ""
+
+msgid "The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax."
+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 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 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 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 to show."
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no matching files"
+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 variables yet."
+msgstr ""
+
+msgid "There are pending advanced search migrations. Indexing must remain paused until the migrations are completed."
+msgstr ""
+
+msgid "There are running deployments on the environment. Please retry later."
+msgstr ""
+
+msgid "There is a halted Elasticsearch migration"
+msgstr ""
+
+msgid "There is already a To-Do for this design."
+msgstr ""
+
+msgid "There is already a repository with that name on disk"
+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 groups."
+msgstr ""
+
+msgid "There was a problem fetching labels."
+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 the keep latest artifact setting."
+msgstr ""
+
+msgid "There was a problem fetching users."
+msgstr ""
+
+msgid "There was a problem refreshing the data, please try again"
+msgstr ""
+
+msgid "There was a problem saving your custom stage, please try again"
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
+msgid "There was an error %{message} todo."
+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 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 the %{replicableType}"
+msgstr ""
+
+msgid "There was an error fetching the Geo Settings"
+msgstr ""
+
+msgid "There was an error fetching the Node'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 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 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 removing your custom stage, please try again"
+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 Node."
+msgstr ""
+
+msgid "There was an error saving your changes."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+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 updating the stage order. Please try reloading the page."
+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 %{requestTypeName} data."
+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 with the reCAPTCHA. Please solve the reCAPTCHA again."
+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 paths are protected for POST requests."
+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 "Third Party Advisory Link"
+msgstr ""
+
+msgid "Third party offers"
+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 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 URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
+msgstr ""
+
+msgid "This action has been performed too many times. Try again later."
+msgstr ""
+
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+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, merge requests, etc."
+msgstr ""
+
+msgid "This also resolves all related threads"
+msgstr ""
+
+msgid "This also resolves this thread"
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+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 comment has changed since you started editing, please 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 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 credential has expired"
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+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 diff was suppressed by a .gitattributes entry."
+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 feature should be used with an index that was created after 13.0"
+msgstr ""
+
+msgid "This field is required."
+msgstr ""
+
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
+msgid "This 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, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
+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 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 Premium feature"
+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 security log of important events involving your account."
+msgstr ""
+
+msgid "This is a self-managed instance of GitLab."
+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 currently blocked by the following issues:"
+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 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 is still a draft."
+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 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 archived and cannot be commented on."
+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 removed on %{date}"
+msgstr ""
+
+msgid "This project will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+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 processes jobs for all projects in its group and subgroups."
+msgstr ""
+
+msgid "This runner processes jobs for all unassigned projects."
+msgstr ""
+
+msgid "This runner processes jobs for assigned projects only."
+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 will update the hostname that is used to generate private commit emails. %{learn_more}"
+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 does not have a pending request"
+msgstr ""
+
+msgid "This user has no active %{type}."
+msgstr ""
+
+msgid "This user has no identities"
+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 clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+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 "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Thread to reply to cannot be found"
+msgstr ""
+
+msgid "Threat Monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Alerts"
+msgstr ""
+
+msgid "ThreatMonitoring|All Environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Anomalous Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Application firewall not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
+msgstr ""
+
+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|Hide dismissed alerts"
+msgstr ""
+
+msgid "ThreatMonitoring|In review"
+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|Policies"
+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|The firewall is not installed or has been disabled. To view this data, ensure the web application firewall is installed and enabled for your cluster."
+msgstr ""
+
+msgid "ThreatMonitoring|The graph below is an overview of traffic coming to your application as tracked by the Web Application Firewall (WAF). View the docs for instructions on how to access the WAF logs to see what type of malicious traffic is trying to access your app. The docs link is also accessible by clicking the \"?\" icon next to the title below."
+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 "ThreatMonitoring|Web Application Firewall"
+msgstr ""
+
+msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
+msgstr ""
+
+msgid "Throughput"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Time"
+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 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 ""
+
+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 until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|%{startTag}Spent: %{endTag}%{timeSpentHumanReadable}"
+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 "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:"
+msgstr ""
+
+msgid "Tip: add a"
+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 access this domain create a new DNS record"
+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 ""
+
+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 define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect 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 link Sentry to GitLab, enter your Sentry URL and Auth Token."
+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 open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+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, %{forkLink} 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 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 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 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 service:"
+msgstr ""
+
+msgid "To simplify the billing process, GitLab will collect user counts in order to prorate charges for user growth throughout the year using a quarterly reconciliation process."
+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 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 Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
+msgstr ""
+
+msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
+msgstr ""
+
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+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"
+msgstr ""
+
+msgid "To-Do List"
+msgstr ""
+
+msgid "To-do item successfully marked as done."
+msgstr ""
+
+msgid "Today"
+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 navigation"
+msgstr ""
+
+msgid "Toggle project select"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "Toggle the Performance Bar"
+msgstr ""
+
+msgid "Toggle this dialog"
+msgstr ""
+
+msgid "Toggle thread"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Toggled :%{name}: emoji award."
+msgstr ""
+
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Token valid until revoked"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too many users specified (limit is %{user_limit})"
+msgstr ""
+
+msgid "Too much data"
+msgstr ""
+
+msgid "Topics (optional)"
+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 days to completion"
+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 time with quick actions"
+msgstr ""
+
+msgid "Track your GitLab projects with GitLab for Slack."
+msgstr ""
+
+msgid "Track your project with Audit Events."
+msgstr ""
+
+msgid "Transfer"
+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 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 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|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
+msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
+msgstr ""
+
+msgid "Trials|Go back to GitLab"
+msgstr ""
+
+msgid "Trials|Skip Trial"
+msgstr ""
+
+msgid "Trials|Skip Trial (Continue with Free Account)"
+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 can apply your trial to a new group or your personal account."
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group, an existing group, or your personal account."
+msgstr ""
+
+msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
+msgstr ""
+
+msgid "Trial|Company name"
+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|How many employees will use Gitlab?"
+msgstr ""
+
+msgid "Trial|Number of employees"
+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 "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 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 "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+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 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 "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+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 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 "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 is required"
+msgstr ""
+
+msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
+msgstr ""
+
+msgid "URL of the external Spam Check endpoint"
+msgstr ""
+
+msgid "URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...)."
+msgstr ""
+
+msgid "URL or request ID"
+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 unscanned projects"
+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 "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 request rate limit"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Undo Ignore"
+msgstr ""
+
+msgid "Undo ignore"
+msgstr ""
+
+msgid "Unexpected error"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Uninstall"
+msgstr ""
+
+msgid "Uninstalling"
+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 "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 "Unlock"
+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 "UnscannedProjects|15 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|30 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|5 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|60 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|Default branch scanning by project"
+msgstr ""
+
+msgid "UnscannedProjects|Out of date"
+msgstr ""
+
+msgid "UnscannedProjects|Project scanning"
+msgstr ""
+
+msgid "UnscannedProjects|Untested"
+msgstr ""
+
+msgid "UnscannedProjects|Your projects are up do date! Nice job!"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+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"
+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 all"
+msgstr ""
+
+msgid "Update approval rule"
+msgstr ""
+
+msgid "Update approvers"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update failed. Please try again."
+msgstr ""
+
+msgid "Update it"
+msgstr ""
+
+msgid "Update iteration"
+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|Error moving repository storage for %{container_full_path} - %{message}"
+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 to %{linkStart}chart v%{linkEnd}"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade offers available!"
+msgstr ""
+
+msgid "Upgrade your plan"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Audit Events."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to enable this feature of the Jira Integration."
+msgstr ""
+
+msgid "Upgrade your plan to improve Merge Requests."
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload License"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload New License"
+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 object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Uploaded on"
+msgstr ""
+
+msgid "Uploaded:"
+msgstr ""
+
+msgid "Uploading changes to terminal"
+msgstr ""
+
+msgid "Uploads"
+msgstr ""
+
+msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. Until that time:"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Uptime"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage"
+msgstr ""
+
+msgid "Usage Trends"
+msgstr ""
+
+msgid "Usage ping is off"
+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|%{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|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|Increase storage temporarily"
+msgstr ""
+
+msgid "UsageQuota|LFS Objects"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Purchase more storage"
+msgstr ""
+
+msgid "UsageQuota|Purchased storage available"
+msgstr ""
+
+msgid "UsageQuota|Repositories"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Snippets"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+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|This project is at risk of being locked because purchased storage is running low."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
+msgstr ""
+
+msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
+msgstr ""
+
+msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
+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 of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+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|Wikis"
+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 "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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
+msgid "Use cURL"
+msgstr ""
+
+msgid "Use custom color #FF0000"
+msgstr ""
+
+msgid "Use hashed storage"
+msgstr ""
+
+msgid "Use hashed storage paths for newly created and renamed repositories. Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents repositories from having to be moved or renamed when the Repository URL changes and may improve disk I/O performance. (Always enabled since 13.0)"
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+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 by members to sign in to your group in GitLab"
+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 ID"
+msgstr ""
+
+msgid "User OAuth applications"
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+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 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 subresources."
+msgstr ""
+
+msgid "User was successfully removed from project."
+msgstr ""
+
+msgid "User was successfully updated."
+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|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|Name"
+msgstr ""
+
+msgid "UserLists|New list"
+msgstr ""
+
+msgid "UserLists|Save"
+msgstr ""
+
+msgid "UserLists|There are no users"
+msgstr ""
+
+msgid "UserLists|User ID"
+msgstr ""
+
+msgid "UserLists|User IDs"
+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|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|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 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|Unconfirmed user"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+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 (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
+msgid "Username or email"
+msgstr ""
+
+msgid "Username: %{username}"
+msgstr ""
+
+msgid "Users"
+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 requesting access to %{strong_start}%{project_name}%{strong_end}"
+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 "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 "Validations failed."
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Value Stream"
+msgstr ""
+
+msgid "Value Stream Analytics"
+msgstr ""
+
+msgid "Value Stream Analytics can help you determine your team’s velocity"
+msgstr ""
+
+msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{days}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
+msgstr ""
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+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 localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification concurrency limit"
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Verify SAML Configuration"
+msgstr ""
+
+msgid "Verify configuration"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
+msgid "View Documentation"
+msgstr ""
+
+msgid "View alert details at"
+msgstr ""
+
+msgid "View alert details."
+msgstr ""
+
+msgid "View all issues"
+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 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 file @%{commit_sha}"
+msgstr ""
+
+msgid "View full dashboard"
+msgstr ""
+
+msgid "View full log"
+msgstr ""
+
+msgid "View group labels"
+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 merge request"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View page @ "
+msgstr ""
+
+msgid "View performance dashboard."
+msgstr ""
+
+msgid "View project"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+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 users statistics"
+msgstr ""
+
+msgid "Viewed"
+msgstr ""
+
+msgid "Viewing commit"
+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 "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} tags of every page of your application, ensuring the merge request ID is set or not set as required. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. If not previously %{linkStart}configured%{linkEnd} by a developer, enter the merge request ID for the review when prompted. The ID of this merge request is %{stepStart}%{mrId}%{stepStart}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. Leave feedback in the Review App."
+msgstr ""
+
+msgid "VisualReviewApp|Cancel"
+msgstr ""
+
+msgid "VisualReviewApp|Copy merge request ID"
+msgstr ""
+
+msgid "VisualReviewApp|Copy script"
+msgstr ""
+
+msgid "VisualReviewApp|Enable Visual Reviews"
+msgstr ""
+
+msgid "VisualReviewApp|Follow the steps below to enable Visual Reviews inside your application."
+msgstr ""
+
+msgid "VisualReviewApp|No review app found or available."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Steps 1 and 2 (and sometimes 3) are performed once by the developer before requesting feedback. Steps 3 (if necessary), 4 is performed by the reviewer each time they perform a review."
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerabilities over time"
+msgstr ""
+
+msgid "Vulnerability Report"
+msgstr ""
+
+msgid "Vulnerability remediated. Review before resolving."
+msgstr ""
+
+msgid "Vulnerability resolved in %{branch}"
+msgstr ""
+
+msgid "Vulnerability resolved in the default branch"
+msgstr ""
+
+msgid "Vulnerability-Check"
+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|A true-positive and will fix"
+msgstr ""
+
+msgid "VulnerabilityManagement|Change status"
+msgstr ""
+
+msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
+msgstr ""
+
+msgid "VulnerabilityManagement|Detected"
+msgstr ""
+
+msgid "VulnerabilityManagement|Needs triage"
+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 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|Verified as fixed or mitigated"
+msgstr ""
+
+msgid "VulnerabilityManagement|Will not fix or a false-positive"
+msgstr ""
+
+msgid "VulnerabilityManagement|invalid issue link or ID"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|All"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Confirmed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Detected"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Dismissed"
+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|Additional Info"
+msgstr ""
+
+msgid "Vulnerability|Class"
+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|Detected"
+msgstr ""
+
+msgid "Vulnerability|Download"
+msgstr ""
+
+msgid "Vulnerability|Evidence"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifier"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Image"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Method"
+msgstr ""
+
+msgid "Vulnerability|Namespace"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Reproduction Assets"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
+msgid "Vulnerability|Request/Response"
+msgstr ""
+
+msgid "Vulnerability|Scanner"
+msgstr ""
+
+msgid "Vulnerability|Scanner Provider"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Status"
+msgstr ""
+
+msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
+msgstr ""
+
+msgid "Vulnerability|Unmodified Response"
+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 "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 recommend that you buy more Pipeline minutes to avoid any interruption of service."
+msgstr ""
+
+msgid "We recommend that you buy more 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've found no vulnerabilities"
+msgstr ""
+
+msgid "Web Application Firewall"
+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|Merge request"
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
+msgid "Webhook"
+msgstr ""
+
+msgid "Webhook Logs"
+msgstr ""
+
+msgid "Webhook Settings"
+msgstr ""
+
+msgid "Webhook:"
+msgstr ""
+
+msgid "Webhooks"
+msgstr ""
+
+msgid "Webhooks Help"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Webhooks have moved. They can now be found under the Settings menu."
+msgstr ""
+
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+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|Releases events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL is triggered when a deployment starts, finishes, fails, or is canceled"
+msgstr ""
+
+msgid "Webhooks|This URL is triggered when a feature flag is turned on or off"
+msgstr ""
+
+msgid "Webhooks|This URL is triggered when a release is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a group member is created/updated/removed"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+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 to the guided GitLab tour"
+msgstr ""
+
+msgid "What are you searching for?"
+msgstr ""
+
+msgid "What describes you best?"
+msgstr ""
+
+msgid "What is squashing?"
+msgstr ""
+
+msgid "What is your job title? (optional)"
+msgstr ""
+
+msgid "What's new"
+msgstr ""
+
+msgid "What’s your experience level?"
+msgstr ""
+
+msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
+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, 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 "When enabled, any user visiting %{host} will be able to create an account."
+msgstr ""
+
+msgid "When enabled, if an NPM package isn't found in the GitLab Registry, we will attempt to pull from the global NPM registry."
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+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 ""
+
+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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
+msgid "When:"
+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 "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 "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+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 "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+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 %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wikis"
+msgstr ""
+
+msgid "Wiki|Create New Page"
+msgstr ""
+
+msgid "Wiki|Create 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 title"
+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 "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 access allowed"
+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 "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 delete %{domain} from your instance. This domain will no longer be available to any Knative application."
+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 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 %{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 the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
+msgid "You are not allowed to approve a user"
+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 perform this action"
+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 into 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 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 always edit this later"
+msgstr ""
+
+msgid "You can create a new %{link}."
+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 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 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 generate an access token scoped to this project for each application to use the GitLab API."
+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 edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved."
+msgstr ""
+
+msgid "You can only merge once this merge request is approved."
+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 register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want."
+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 access the raw file. Please wait a minute."
+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 make this a shared runner."
+msgstr ""
+
+msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
+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 could not create a new trigger."
+msgstr ""
+
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgstr ""
+
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
+msgstr ""
+
+msgid "You do not have an active license"
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to leave this %{namespaceType}."
+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 a license that activates at a future date. Please see the License History table below."
+msgstr ""
+
+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 %{title} %{name}."
+msgstr ""
+
+msgid "You have been invited"
+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 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 rotation for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to create an on-call schedule for this project"
+msgstr ""
+
+msgid "You have insufficient permissions to remove an 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 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 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 successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
+msgstr ""
+
+msgid "You haven't added any issues to your project yet"
+msgstr ""
+
+msgid "You haven't selected any issues yet"
+msgstr ""
+
+msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
+msgstr ""
+
+msgid "You may close the milestone now."
+msgstr ""
+
+msgid "You must be logged in to search across all of GitLab"
+msgstr ""
+
+msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
+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 select a stack for configuring your cloud provider. Learn more about"
+msgstr ""
+
+msgid "You must set up incoming email before it becomes active."
+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 be logged in."
+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 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 won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account"
+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 %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not be able to create issues or merge requests as well as many other features."
+msgstr ""
+
+msgid "Your CI configuration file is invalid."
+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 Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
+msgid "Your GitLab account request has been approved!"
+msgstr ""
+
+msgid "Your GitLab group"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your License"
+msgstr ""
+
+msgid "Your Personal Access Token was revoked"
+msgstr ""
+
+msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
+msgstr ""
+
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH key 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 Version"
+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 by your administrator. Please log back in to reactivate your account."
+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 applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+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 custom stage '%{title}' was created"
+msgstr ""
+
+msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+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 license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
+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 SCIM token"
+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 ""
+
+msgid "Your password reset token has expired."
+msgstr ""
+
+msgid "Your personal access token has expired"
+msgstr ""
+
+msgid "Your profile"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+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. Once 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 sign-in page is %{url}."
+msgstr ""
+
+msgid "Your subscription expired!"
+msgstr ""
+
+msgid "Your subscription has been downgraded."
+msgstr ""
+
+msgid "Your subscription will expire in %{remaining_days}."
+msgstr ""
+
+msgid "Your username is %{username}."
+msgstr ""
+
+msgid "Zoom meeting added"
+msgstr ""
+
+msgid "Zoom meeting removed"
+msgstr ""
+
+msgid "[No reason]"
+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 "a design"
+msgstr ""
+
+msgid "about 1 hour"
+msgid_plural "about %d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "access:"
+msgstr ""
+
+msgid "added %{created_at_timeago}"
+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 has a \"created\" issue link"
+msgstr ""
+
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "and"
+msgstr ""
+
+msgid "any-approver for the merge request already exists"
+msgstr ""
+
+msgid "any-approver for the project already exists"
+msgstr ""
+
+msgid "approved by: "
+msgstr ""
+
+msgid "archived"
+msgstr ""
+
+msgid "archived:"
+msgstr ""
+
+msgid "as %{role}."
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "at"
+msgstr ""
+
+msgid "at risk"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "authored"
+msgstr ""
+
+msgid "blocks"
+msgstr ""
+
+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't be enabled because signed commits are required for this project"
+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 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 modified"
+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 "child-pipeline"
+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|%{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 scanners"
+msgstr ""
+
+msgid "ciReport|All severities"
+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 test metrics: "
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Checks"
+msgstr ""
+
+msgid "ciReport|Code quality"
+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|Coverage Fuzzing"
+msgstr ""
+
+msgid "ciReport|Coverage fuzzing"
+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|Fixed"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Found %{issuesWithCount}"
+msgstr ""
+
+msgid "ciReport|Investigate this vulnerability by creating an issue"
+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|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 scanning"
+msgstr ""
+
+msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+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 issue"
+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 "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 "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "created"
+msgstr ""
+
+msgid "created %{timeAgo}"
+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 "designs"
+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 "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 "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "email '%{email}' is not a verified email."
+msgstr ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
+msgid "entries cannot be larger than 255 characters"
+msgstr ""
+
+msgid "entries cannot be nil"
+msgstr ""
+
+msgid "entries cannot contain HTML tags"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+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 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 "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 "fork this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "group"
+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 "help"
+msgstr ""
+
+msgid "http:"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+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 since the group is not top-level group."
+msgstr ""
+
+msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
+msgstr ""
+
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
+msgid "is not an email you own"
+msgstr ""
+
+msgid "is not in the group enforcing Group Managed Account"
+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"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "log in"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "math|The math in this entry is taking too long to render and may not be displayed as expected. For performance reasons, math blocks are also limited to %{maxChars} characters. Consider splitting up large formulae, splitting math blocks among multiple entries, or using an image instead."
+msgstr ""
+
+msgid "math|There was an error rendering this math block"
+msgstr ""
+
+msgid "member%{number}@company.com"
+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 "more information"
+msgstr ""
+
+msgid "most recent deployment"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+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|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
+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"
+msgstr ""
+
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+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|Are you adding technical debt or code vulnerabilities?"
+msgstr ""
+
+msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|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"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
+msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Jump to first unresolved thread"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mark as ready"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved."
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|More information"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+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 all threads in new issue"
+msgstr ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Revoke approval"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be 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 HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgstr ""
+
+msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge after removing denied licenses"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|Your password"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+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 greater than start date"
+msgstr ""
+
+msgid "must contain only valid frameworks"
+msgstr ""
+
+msgid "my-awesome-group"
+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 contributions"
+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 "notification emails"
+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 "open issue"
+msgstr ""
+
+msgid "opened %{timeAgoString} by %{email} via %{user}"
+msgstr ""
+
+msgid "opened %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "opened %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
+msgid "opened %{timeAgo}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "originating vulnerability"
+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 "paused"
+msgstr ""
+
+msgid "pending comment"
+msgstr ""
+
+msgid "pending removal"
+msgstr ""
+
+msgid "per day"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "personal access tokens"
+msgstr ""
+
+msgid "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 "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 "projects"
+msgstr ""
+
+msgid "quick actions"
+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 weight"
+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 "reset it."
+msgstr ""
+
+msgid "revised"
+msgstr ""
+
+msgid "runners"
+msgstr ""
+
+msgid "satisfied"
+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 "sort:"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "specific"
+msgstr ""
+
+msgid "specified top is not part of the tree"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time 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 "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 following issue(s)"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "time summary"
+msgstr ""
+
+msgid "to automatically add approvers based on file paths and file types."
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "to join %{source_name}"
+msgstr ""
+
+msgid "to list"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "train"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "two-factor authentication settings"
+msgstr ""
+
+msgid "unicode domains should use IDNA encoding"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "updated %{timeAgo}"
+msgstr ""
+
+msgid "updated %{time_ago}"
+msgstr ""
+
+msgid "uploaded"
+msgstr ""
+
+msgid "uploads"
+msgstr ""
+
+msgid "user avatar"
+msgstr ""
+
+msgid "user preferences"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "v%{version} published %{timeAgo}"
+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 "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 ""
+
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 4787bbc59a6..498e369549e 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:06\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -318,10 +322,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -958,14 +968,14 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1155,6 +1165,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1789,6 +1811,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2119,6 +2153,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2227,6 +2264,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,7 +2694,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2795,7 +2835,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3140,6 +3189,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,7 +3640,7 @@ 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}"
+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?"
@@ -3679,15 +3728,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3757,7 +3809,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4032,9 +4081,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,7 +4105,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4158,16 +4204,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4308,25 +4354,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4335,10 +4381,16 @@ 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 Gold."
+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}."
@@ -4359,6 +4411,9 @@ 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 ""
@@ -4368,6 +4423,9 @@ 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 ""
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4690,6 +4754,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4834,6 +4916,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5497,6 +5591,9 @@ 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 ""
@@ -5656,12 +5753,24 @@ 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 ""
@@ -5704,7 +5813,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8316,10 +8485,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8346,7 +8515,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,7 +8596,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8641,7 +8807,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,7 +10112,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10184,9 +10404,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,7 +10761,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,7 +12769,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12564,6 +12817,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,7 +13234,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,7 +15495,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -14897,10 +15537,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -14925,9 +15565,21 @@ msgstr[0] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,7 +16615,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,7 +16907,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18319,9 +19046,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,7 +19505,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -18988,6 +19718,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 ""
@@ -20573,9 +21333,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21446,9 +22209,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21731,6 +22491,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,7 +24641,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -23985,6 +24764,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,7 +25852,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,16 +29162,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28368,7 +29210,7 @@ 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."
+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."
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,13 +29366,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 ""
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,7 +31271,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 ""
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31497,6 +32414,9 @@ msgstr[0] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr ""
@@ -32319,6 +33239,9 @@ 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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33497,9 +34448,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33569,7 +34517,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index 028fef649f3..7757db13f90 100644
--- a/locale/ig_NG/gitlab.po
+++ b/locale/ig_NG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ig\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:54\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -318,10 +322,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -958,14 +968,14 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1155,6 +1165,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1789,6 +1811,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2119,6 +2153,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2227,6 +2264,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,7 +2694,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2795,7 +2835,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3140,6 +3189,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,7 +3640,7 @@ 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}"
+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?"
@@ -3679,15 +3728,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3757,7 +3809,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4032,9 +4081,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,7 +4105,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4158,16 +4204,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4308,25 +4354,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4335,10 +4381,16 @@ 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 Gold."
+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}."
@@ -4359,6 +4411,9 @@ 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 ""
@@ -4368,6 +4423,9 @@ 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 ""
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4690,6 +4754,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4834,6 +4916,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5497,6 +5591,9 @@ 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 ""
@@ -5656,12 +5753,24 @@ 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 ""
@@ -5704,7 +5813,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8316,10 +8485,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8346,7 +8515,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,7 +8596,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8641,7 +8807,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,7 +10112,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10184,9 +10404,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,7 +10761,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,7 +12769,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12564,6 +12817,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,7 +13234,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,7 +15495,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -14897,10 +15537,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -14925,9 +15565,21 @@ msgstr[0] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,7 +16615,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,7 +16907,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18319,9 +19046,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,7 +19505,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -18988,6 +19718,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 ""
@@ -20573,9 +21333,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21446,9 +22209,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21731,6 +22491,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,7 +24641,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -23985,6 +24764,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,7 +25852,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,16 +29162,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28368,7 +29210,7 @@ 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."
+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."
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,13 +29366,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 ""
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,7 +31271,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 ""
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31497,6 +32414,9 @@ msgstr[0] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr ""
@@ -32319,6 +33239,9 @@ 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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33497,9 +34448,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33569,7 +34517,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index 2669092e227..96e0ed945de 100644
--- a/locale/is_IS/gitlab.po
+++ b/locale/is_IS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: is\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:05\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 55039677a52..cc438b12dbf 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d risultato del test risolto"
msgstr[1] "%d risultati dei test risolti"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr ""
msgid ", or "
msgstr ", o "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Il runner è attivo e può processare nuovi lavori"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Il runner è in pausa e non riceverà nuovi lavori"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "Un ramo predefinito non può essere scelto per un progetto vuoto."
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-msgstr "Sei sicuro di voler ripristinare il token di registrazione?"
-
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?"
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr "Disponibile"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr "Impostazioni"
msgid "Branches|protected"
msgstr "Protetta"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "per"
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Ripristina"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr "Crea token d'accesso personale"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Modifica"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr "Dalla creazione di un issue fino al rilascio in produzione"
msgid "From merge request merge until deploy to production"
msgstr "Dalla richiesta di merge fino effettua il merge fino al rilascio in produzione"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr "Housekeeping iniziato con successo"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr "Se disabilitato, un ramo locale divergente non verrà automaticamente ag
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr ""
msgid "Last edited %{date}"
msgstr "Ultima modifica %{date}"
-msgid "Last edited by %{name}"
-msgstr "Modificato da %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Membri"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Opzioni"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr "Pianificazione Pipeline"
msgid "Pipeline Schedules"
msgstr "Pianificazione multipla Pipeline"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Attività di Rilascio Correlate"
-
msgid "Related Issues"
msgstr "Issues Correlati"
-msgid "Related Jobs"
-msgstr "Attività Correlate"
-
-msgid "Related Merge Requests"
-msgstr "Richieste di Merge Correlate"
-
-msgid "Related Merged Requests"
-msgstr "Richieste di Merge Completate Correlate"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr "Seleziona una timezone"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Seleziona una branch di destinazione"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Seleziona il ramo che vuoi impostare come predefinito per questo progetto. Tutte le richieste di merge e i commit verranno automaticamente eseguiti su questo ramo, a meno che non ne sia specificato uno diverso."
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "inizia una %{new_merge_request} con queste modifiche"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "La relazione del fork è stata rimossa"
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "Lo stadio di Issue mostra il tempo che impiega un issue ad esser correla
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "Il ciclo vitale della fase di sviluppo."
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Lo stadio di revisione mostra il tempo tra una richiesta di merge al suo svolgimento effettivo. Questo dato sarà disponibile appena avrai completato una MR (Merger Request)"
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Questo significa che non è possibile effettuare push di codice fino a che non crei una repository vuota o ne importi una esistente"
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "giorno"
msgstr[1] "giorni"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index a8e737c7b73..fb33c6418e0 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 件ã®ãƒ†ã‚¹ãƒˆã§ä¿®æ­£ã•ã‚Œã¾ã—ãŸ"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d 件ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžæ¸ˆã¿"
@@ -318,11 +322,11 @@ msgstr "%{authorsName}ã®ã‚¹ãƒ¬ãƒƒãƒ‰"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
-msgstr "%{code_open}マスク%{code_close} 変数ã¯ã‚¸ãƒ§ãƒ–ã®ãƒ­ã‚°ã«è¡¨ç¤ºã•ã‚Œã›ã‚“。(ãŸã ã—ã€æŒ‡å®šã®æ­£è¦è¡¨ç¾ã«ä¸€è‡´ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™)。"
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
+msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
-msgstr "%{code_open}ä¿è­·%{code_close} 変数ã¯ä¿è­·ãƒ–ランãƒã‚„ä¿è­·ã‚¿ã‚°ã«ã®ã¿å…¬é–‹ã•ã‚Œã¾ã™ã€‚"
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
+msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} ㌠%{commit_timeago} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸ"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr "%{retryButtonStart}ã‚‚ã†ä¸€åº¦è©¦ã™%{retryButtonEnd} ã¾ãŸã¯ %{newFileButtonStart}æ–°ã—ã„ファイルを添付ã™ã‚‹%{newFileButtonEnd}。"
@@ -839,6 +846,9 @@ 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 ""
+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 "&lt; 1 hour"
msgstr "&lt; 1時間"
@@ -867,7 +877,7 @@ msgid "'%{name}' Value Stream created"
msgstr "'%{name}' ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ãŒä½œæˆã•ã‚Œã¾ã—ãŸ"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "'%{name}' ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
msgid "'%{name}' stage already exists"
msgstr "'%{name}'ステージã¯ã™ã§ã«ã‚ã‚Šã¾ã™"
@@ -958,15 +968,15 @@ msgstr "+%{tags} 以上"
msgid ", or "
msgstr "ã€ã¾ãŸã¯"
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- イベント"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- RunnerãŒã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã§æ–°ã—ã„ジョブを処ç†ã§ãã¾ã™"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- RunnerãŒåœæ­¢ä¸­ã®ãŸã‚æ–°ã—ã„ジョブã¯å‡¦ç†ã•ã‚Œã¾ã›ã‚“"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1155,6 +1165,9 @@ msgstr "プロジェクトãŒç©ºã®å ´åˆã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ–ランãƒã‚’é¸
msgid "A deleted user"
msgstr "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "ファイルãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚"
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr "アメリカåˆè¡†å›½ä¿å¥ç¦ç¥‰çœãŒç™ºè¡Œã—ãŸHIPAA監査プロトã
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "プロジェクトã¨ã¯ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’æ ¼ç´ã—ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã§è¨ˆç”»ã‚’ç«‹ã¦ã€Wikiã§ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’公開ã™ã‚‹å ´æ‰€ã§ã™ã€‚ %{among_other_things_link}"
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "ジョブã®ãƒ­ã‚°ã‹ã‚‰ãƒ†ã‚¹ãƒˆã‚«ãƒãƒ¬ãƒƒã‚¸ã®çµæžœã‚’見ã¤ã‘ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã‚‹æ­£è¦è¡¨ç¾ã€‚無効ã«ã™ã‚‹å ´åˆã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
-
msgid "A secure token that identifies an external storage request."
msgstr "外部ストレージリクエストを識別ã™ã‚‹ã€ã‚»ã‚­ãƒ¥ã‚¢ãƒˆãƒ¼ã‚¯ãƒ³"
@@ -1245,8 +1264,8 @@ msgstr "次ã®IPアドレスã‹ã‚‰ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚µã‚¤ãƒ³ã‚¤ã
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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 "サブスクライブã—ãŸãƒ—ロジェクト㮠%{default_branch_docs} ã§æ–°ã—ã„ã‚¿ã‚°ã®ãƒ‘イプラインãŒæ­£å¸¸ã«å®Œäº†ã™ã‚‹ã¨ã€ã‚µãƒ–スクリプションã«ã‚ˆã£ã¦ã€ã“ã®ãƒ—ロジェクトã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ–ランãƒã§æ–°ã—ã„パイプラインをトリガーã—ã¾ã™ã€‚"
+msgid "A title is required"
+msgstr ""
msgid "A user can only participate in a rotation once"
msgstr ""
@@ -1260,6 +1279,9 @@ msgstr "アクションãŒå¿…è¦ï¼šGitLab Pagesã®ãƒ‰ãƒ¡ã‚¤ãƒ³ '%{domain}'ã¸ã®
msgid "API Fuzzing"
msgstr "APIファジング"
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "API ヘルプ"
@@ -1522,15 +1544,15 @@ msgstr "管ç†è€…ã®ã‚µã‚¤ãƒ‰ãƒãƒ¼ã®ãƒ¢ãƒ‹ã‚¿ãƒªãƒ³ã‚°éƒ¨ã« Grafana ボタン
msgid "Add a To Do"
msgstr "Todoを追加"
-msgid "Add a To-Do"
-msgstr "Todoを追加"
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr "ã“ã® %{noteableDisplayName} ã¸ä¸€èˆ¬çš„ãªã‚³ãƒ¡ãƒ³ãƒˆã‚’追加。"
@@ -1789,6 +1811,9 @@ msgstr "管ç†ãƒ¢ãƒ¼ãƒ‰ç„¡åŠ¹"
msgid "Admin mode enabled"
msgstr "管ç†ãƒ¢ãƒ¼ãƒ‰ã¯æœ‰åŠ¹ã§ã™"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "管ç†è€…メモ"
@@ -1819,9 +1844,6 @@ msgstr "開発者"
msgid "AdminArea|Features"
msgstr "機能"
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr "グループ: %{number_of_groups}"
-
msgid "AdminArea|Guest"
msgstr "ゲスト"
@@ -1855,8 +1877,8 @@ msgstr "インスタンスã®ãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°ãŒä¸Šé™ã«é”ã™ã‚‹ã¨ã€è¿½åŠ ã•
msgid "AdminArea|Owner"
msgstr "オーナー"
-msgid "AdminArea|Projects: %{number_of_projects}"
-msgstr "プロジェクト: %{number_of_projects}"
+msgid "AdminArea|Projects"
+msgstr ""
msgid "AdminArea|Reporter"
msgstr "レãƒãƒ¼ã‚¿ãƒ¼"
@@ -1879,6 +1901,9 @@ msgstr "全ユーザー"
msgid "AdminArea|User cap"
msgstr "ユーザーキャップ"
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "ユーザー統計"
@@ -1888,8 +1913,14 @@ msgstr "最高ä½ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "AdminArea|Users without a Group and Project"
msgstr "グループã¨ãƒ—ロジェクトã®ãªã„ユーザー"
-msgid "AdminArea|Users: %{number_of_users}"
-msgstr "ユーザー: %{number_of_users}"
+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 "å…¨ã¦ã®ã‚¸ãƒ§ãƒ–ã‚’åœæ­¢ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç¾åœ¨å®Ÿè¡Œä¸­ã®ã‚¸ãƒ§ãƒ–ã¯åœæ­¢ã•ã‚Œã¾ã™ã€‚"
@@ -1918,9 +1949,6 @@ msgstr "Auto DevOps ドメイン"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr "Elasticsearchã€PlantUMLã€Slackアプリケーションã€ã‚µãƒ¼ãƒ‰ãƒ‘ーティã®ã‚ªãƒ•ã‚¡ãƒ¼ã€Snowplowã€Amazon EKS 㯠設定 &gt; 全般 ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "æ–°ã—ã„プロジェクトã§å…±æœ‰ Runner を有効ã«ã™ã‚‹"
@@ -1942,6 +1970,9 @@ msgstr "インテグレーションã«ç§»å‹•"
msgid "AdminSettings|No required pipeline"
msgstr "必須パイプラインãªã—"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "管ç†è¨­å®š |必須パイプライン設定"
@@ -2092,6 +2123,9 @@ msgstr "サインインã¾ãŸã¯ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹æƒ…å ±ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "LDAP ã§ãƒ–ロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’ブロック解除ã§ãã¾ã›ã‚“"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "無効ã«ã™ã‚‹"
@@ -2119,6 +2153,9 @@ msgstr "ユーザーã®å‰Šé™¤"
msgid "AdminUsers|Delete user and contributions"
msgstr "ユーザーã¨è²¢çŒ®åº¦ã®å‰Šé™¤"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "外部"
@@ -2227,6 +2264,9 @@ msgstr "ユーザーã¯gitリãƒã‚¸ãƒˆãƒªã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªããªã‚Šã¾ã™
msgid "AdminUsers|User will not be able to login"
msgstr "ユーザーã¯ãƒ­ã‚°ã‚¤ãƒ³ã§ããªããªã‚Šã¾ã™"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå†ã³ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æœ‰åŠ¹ã«ãªã‚Šã¾ã™"
@@ -2319,7 +2359,7 @@ msgid "AlertManagement|Alert"
msgstr "アラート"
msgid "AlertManagement|Alert assignee(s): %{assignees}"
-msgstr ""
+msgstr "アラートã®æ‹…当者: %{assignees}"
msgid "AlertManagement|Alert detail"
msgstr ""
@@ -2340,7 +2380,7 @@ msgid "AlertManagement|Assign status"
msgstr ""
msgid "AlertManagement|Assignees"
-msgstr ""
+msgstr "担当者"
msgid "AlertManagement|Authorize external service"
msgstr ""
@@ -2454,7 +2494,7 @@ msgid "AlertManagement|There was an error while updating the status of the alert
msgstr ""
msgid "AlertManagement|This assignee cannot be assigned to this alert."
-msgstr ""
+msgstr "ã“ã®æ‹…当者ã¯ã“ã®ã‚¢ãƒ©ãƒ¼ãƒˆã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¾ã›ã‚“。"
msgid "AlertManagement|Tool"
msgstr ""
@@ -2654,8 +2694,8 @@ msgstr ""
msgid "Alerts"
msgstr "アラート"
-msgid "Alerts endpoint"
-msgstr "アラートエンドãƒã‚¤ãƒ³ãƒˆ"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -2795,8 +2835,8 @@ 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 public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Asciidocドキュメントã§ã®PlantUML図ã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚’許å¯ã—ã¾ã™ã€‚"
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "メールドメイン制é™ã¯ã€æœ€ä¸Šä½ã‚°ãƒ«ãƒ¼ãƒ—ã«ã®ã¿è¨±å¯ã•ã‚Œã¾ã™"
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "失敗を許容"
@@ -2897,6 +2940,9 @@ msgstr "ユーザーãŒå¼·åˆ¶çš„ãª2è¦ç´ èªè¨¼ã‚’無視ã§ãる時間(時間å
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 ""
@@ -2924,6 +2970,9 @@ msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "ã“ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã«ä¸‹æ›¸ãを追加ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3140,6 +3189,9 @@ msgstr "ファイルã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while loading the file. Please try again later."
msgstr "ファイルã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "マージリクエストã®å¤‰æ›´ã‚’読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -3219,7 +3271,7 @@ msgid "An error occurred while updating approvers"
msgstr "承èªè€…ã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while updating assignees."
-msgstr ""
+msgstr "担当者ã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while updating configuration."
msgstr ""
@@ -3234,7 +3286,7 @@ msgid "An error occurred while updating the configuration."
msgstr ""
msgid "An error occurred while updating the milestone."
-msgstr ""
+msgstr "マイルストーンã®æ›´æ–°ä¸­ã®ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while validating group path"
msgstr "グループパスã®æ¤œè¨¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3311,6 +3363,9 @@ msgstr "既知ã®è„†å¼±æ€§ã«å¯¾ã™ã‚‹ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã®åˆ†æžã‚’ã—ã¾ã™."
msgid "Ancestors"
msgstr "祖先"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "匿å"
@@ -3351,7 +3406,7 @@ msgid "Any member with at least Developer permissions on the project."
msgstr ""
msgid "Any milestone"
-msgstr ""
+msgstr "ä»»æ„ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³"
msgid "Any namespace"
msgstr "ä»»æ„ã®ãƒãƒ¼ãƒ ã‚¹ãƒšãƒ¼ã‚¹"
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr "æ案をé©ç”¨"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,8 +3640,8 @@ 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}"
-msgstr "プロジェクトをアーカイブã«ã™ã‚‹ã¨ã€ãƒ—ロジェクトã¯å®Œå…¨ã«èª­ã¿å–り専用ã«ãªã‚Šã¾ã™ã€‚ ã¾ãŸã€ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã‹ã‚‰è¡¨ç¤ºã•ã‚Œãšã€æ¤œç´¢ã§ã‚‚表示ã•ã‚Œã¾ã›ã‚“。 %{strong_start}ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã¯ã‚³ãƒŸãƒƒãƒˆã§ãã¾ã›ã‚“ã—ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã‚„コメントã¾ãŸä»–ã®ã‚¨ãƒ³ãƒ†ã‚£ãƒ†ã‚£ã‚’作æˆã§ãã¾ã›ã‚“。 %{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
@@ -3610,7 +3659,7 @@ msgid "Are you sure you want to close this blocked issue?"
msgstr "ã“ã®ãƒ–ロックã•ã‚Œã¦ã„るイシューをクローズã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to delete \"%{name}\" Value Stream?"
-msgstr ""
+msgstr "\"%{name}\" ã¨ã„ã†ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to delete %{name}?"
msgstr "%{name} を削除ã—ã¾ã™ã‹ï¼Ÿ"
@@ -3679,15 +3728,18 @@ msgstr "ã“ã® ID を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 "本当ã«ãƒ˜ãƒ«ã‚¹ãƒã‚§ãƒƒã‚¯ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
+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 ""
@@ -3757,8 +3809,8 @@ msgstr "ユーザーã®ãƒ‘ーソナルアクセストークン。ユーザーã¯
msgid "Ascending"
msgstr "昇順"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "グループ Runner ã®è¨­å®šã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã® Maintainer ã«ä¾é ¼ã—ã¦ãã ã•ã„。"
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "アサーション コンシューマー サービス URL"
@@ -3773,7 +3825,7 @@ msgid "Assign"
msgstr "割り当ã¦"
msgid "Assign Iteration"
-msgstr ""
+msgstr "イテレーションを割り当ã¦ã‚‹"
msgid "Assign To"
msgstr ""
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "#FF0000ã®ã‚ˆã†ãªã‚«ã‚¹ã‚¿ãƒ ã‚«ãƒ©ãƒ¼ã‚’割り当ã¦ã‚‹"
-msgid "Assign epic"
-msgstr "エピックã®å‰²ã‚Šå½“ã¦"
-
msgid "Assign labels"
msgstr "ラベルを割り当ã¦ã‚‹"
@@ -3791,10 +3840,10 @@ msgid "Assign milestone"
msgstr "マイルストーンを割り当ã¦ã‚‹"
msgid "Assign reviewer"
-msgstr ""
+msgstr "レビュアーを割り当ã¦ã‚‹"
msgid "Assign reviewer(s)"
-msgstr ""
+msgstr "レビュアーを割り当ã¦ã‚‹"
msgid "Assign some issues to this milestone."
msgstr "ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«ã„ãã¤ã‹ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’割り当ã¦ã¾ã™ã€‚"
@@ -3803,7 +3852,7 @@ msgid "Assign to"
msgstr "割り当ã¦å…ˆ"
msgid "Assign to commenting user"
-msgstr ""
+msgstr "コメントã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰²ã‚Šå½“ã¦"
msgid "Assign yourself to these issues"
msgstr "ã“れらã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
@@ -3815,7 +3864,7 @@ msgid "Assigned %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} を割り当ã¦ã¾ã—ãŸã€‚"
msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "%{reviewer_users_sentence} ã‚’ %{reviewer_text} ã¨ã—ã¦å‰²ã‚Šå½“ã¦ã¾ã—ãŸã€‚"
msgid "Assigned Issues"
msgstr "割り当ã¦ã‚‰ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
@@ -3827,13 +3876,13 @@ msgid "Assigned projects"
msgstr ""
msgid "Assigned to %{assigneeName}"
-msgstr ""
+msgstr "%{assigneeName} ã«å‰²ã‚Šå½“ã¦"
msgid "Assigned to %{assignee_name}"
-msgstr ""
+msgstr "%{assignee_name} ã«å‰²ã‚Šå½“ã¦"
msgid "Assigned to %{name}"
-msgstr ""
+msgstr "%{name} ã«å‰²ã‚Šå½“ã¦"
msgid "Assigned to me"
msgstr "自分ã«å‰²ã‚Šå½“ã¦ã‚‹"
@@ -3843,10 +3892,10 @@ msgstr ""
msgid "Assignee"
msgid_plural "%d Assignees"
-msgstr[0] ""
+msgstr[0] "%d 人ã®æ‹…当者"
msgid "Assignee has no permissions"
-msgstr ""
+msgstr "担当者ã«æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "Assignee lists not available with your current license"
msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯æ‹…当者リストを利用ã§ãã¾ã›ã‚“"
@@ -3858,13 +3907,13 @@ msgid "Assignee(s)"
msgstr "担当者"
msgid "Assignees"
-msgstr ""
+msgstr "担当者"
msgid "Assigns %{assignee_users_sentence}."
msgstr "%{assignee_users_sentence} を割り当ã¦ã¾ã™ã€‚"
msgid "Assigns %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "%{reviewer_users_sentence} ã‚’ %{reviewer_text} ã¨ã—ã¦å‰²ã‚Šå½“ã¦ã‚‹"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr "ãã‚Œãžã‚Œã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’変更ã™ã‚‹ã«ã¯ã€CODEOWNERã®ãƒ«ãƒ¼ãƒ«ã«ä¸€è‡´ã™ã‚‹ã€å°‘ãªãã¨ã‚‚1åã®ã‚³ãƒ¼ãƒ‰æ‰€æœ‰è€…ã‹ã‚‰ã®æ‰¿èªãŒå¿…è¦ã§ã™ã€‚"
@@ -4032,9 +4081,6 @@ msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã« %{link_to_client} を承èªã—ã¾ã™ã‹ï¼
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "%{new_chat_name} ãŒæ‰¿èªã•ã‚Œã¾ã—ãŸ"
@@ -4059,8 +4105,8 @@ msgstr "Auto DevOps, Runner,ãŠã‚ˆã³ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆ"
msgid "Auto stop successfully canceled."
msgstr "自動åœæ­¢æ©Ÿèƒ½ã‚’正常ã«ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã—ã¾ã—ãŸã€‚"
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "冗長・ä¿ç•™ä¸­ã®ãƒ‘イプラインを自動キャンセル"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr "デフォルトã®ãƒ–ランãƒã§å‚ç…§ã•ã‚Œã¦ã„るイシューを自動的ã«çµ‚了ã—ã¾ã™ã€‚"
@@ -4158,17 +4204,17 @@ msgstr "利用å¯èƒ½"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "利用å¯èƒ½ãªã‚°ãƒ«ãƒ¼ãƒ— Runner:%{runners}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "利用å¯èƒ½ãªå…±æœ‰ Runner"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "利用å¯èƒ½ãª Specific Runner"
@@ -4308,26 +4354,26 @@ msgstr "ã”注æ„ãã ã•ã„。プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®åå‰ã‚’
msgid "Begin with the selected commit"
msgstr "é¸æŠžã—ãŸã‚³ãƒŸãƒƒãƒˆã§ã¯ã˜ã‚ã‚‹"
-msgid "Below are examples of regex for existing tools:"
-msgstr "以下ã®ã‚‚ã®ã¯ã€æ—¢å­˜ã®æ­£è¦è¡¨ç¾ãƒ„ールã®ä¾‹ã§ã™:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "ç¾åœ¨ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã®SSHホストキーã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—リントã§ã™ã€‚"
msgid "Below you will find all the groups that are public."
msgstr "以下ã«å…¬é–‹ã•ã‚Œã¦ã„る全グループを表示ã—ã¾ã™ã€‚"
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "請求"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name} ã®ç¾åœ¨ã®ãƒ—ラン㯠%{plan_name} ã§ã™ã€‚"
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "@%{user_name} ã‚ãªãŸã®ç¾åœ¨ã®ãƒ—ランã¯%{plan_name} ã§ã™ã€‚"
@@ -4335,11 +4381,17 @@ msgstr "@%{user_name} ã‚ãªãŸã®ç¾åœ¨ã®ãƒ—ランã¯%{plan_name} ã§ã™ã€‚"
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 "プランをダウングレードを希望ã™ã‚‹å ´åˆã€ %{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 Gold."
-msgstr "%{faq_link} を読んã§å„プランã®è©³ç´°ã‚’確èªã™ã‚‹ã‹ã€GitLab.com Gold ã®30日間無料試用版を開始ã—ã¦ãã ã•ã„。"
+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 "å„プランã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{pricing_page_link} ã‚’ã”確èªãã ã•ã„。"
@@ -4359,6 +4411,9 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã€è¦ªã‚°ãƒ«ãƒ¼ãƒ—ã¨åŒã˜ãƒ—ランを使用ã—ã¾
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ—ランã®ç®¡ç†ã¯ã€%{parent_billing_page_link} ã®è«‹æ±‚ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’ã”覧ãã ã•ã„。"
+msgid "BillingPlans|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 ""
@@ -4368,6 +4423,9 @@ msgstr "GitLab.com ã®è©¦ç”¨ç‰ˆã¯ %{expiration_date} ã«æœŸé™åˆ‡ã‚Œã«ãªã‚Šã
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "å¹´é¡%{price_per_year} 請求ã•ã‚Œã¾ã™"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "FAQ 集"
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "アップグレード"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "折りãŸãŸã¿"
@@ -4690,6 +4754,9 @@ msgstr "プロジェクト設定"
msgid "Branches|protected"
msgstr "ä¿è­·"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr "ビルトイン"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -4760,7 +4836,7 @@ msgid "Burndown chart"
msgstr "ãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ãƒãƒ£ãƒ¼ãƒˆ"
msgid "Burndown charts are now fixed. This means that removing issues from a milestone after it has expired won't affect the chart. You can view the old chart using the %{strongStart}Legacy burndown chart%{strongEnd} button."
-msgstr ""
+msgstr "ãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ãƒãƒ£ãƒ¼ãƒˆãŒä¿®æ­£ã•ã‚Œã¾ã—ãŸã€‚期é™åˆ‡ã‚Œå¾Œã«ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’削除ã—ã¦ã‚‚ãƒãƒ£ãƒ¼ãƒˆã«ã¯å½±éŸ¿ã—ã¾ã›ã‚“。 %{strongStart}レガシーãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ãƒãƒ£ãƒ¼ãƒˆ%{strongEnd} ボタンを使用ã—ã¦ã€å¤ã„ãƒãƒ£ãƒ¼ãƒˆã‚’表示ã§ãã¾ã™ã€‚"
msgid "BurndownChartLabel|Open issue weight"
msgstr "イシューã®ã‚¦ã‚§ã‚¤ãƒˆã‚’é–‹ã"
@@ -4789,6 +4865,9 @@ msgstr "追加ã®ãƒ‘イプライン時間(分)を購入ã™ã‚‹"
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 ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr "デフォルトã§ã¯ã€GitLabã¯HTMLå½¢å¼ã¨ãƒ—レーンテキストå½
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "デフォルトã§ã¯ã€ã™ã¹ã¦ã®ãƒ—ロジェクトã¨ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«é€šçŸ¥è¨­å®šã‚’使用ã—ã¾ã™ã€‚"
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者"
@@ -4834,6 +4916,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD 設定"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD"
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr "カナリア"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "カナリアデプロイã¯ã€ä¸€éƒ¨ã®ã‚¢ãƒ—リケーションãŒã‚ãªãŸã®ã‚¢ãƒ—リケーションã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«æ›´æ–°ã•ã‚Œã‚‹ã€ã¨ã„ã†ä¸€èˆ¬çš„ãªCI戦略ã§ã™ã€‚"
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5021,10 +5103,10 @@ 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 ""
+msgstr "公開ã•ã‚Œã¦ã„ã‚‹å­ã‚¨ãƒ”ックãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã€ã“ã®ã‚¨ãƒ”ックをéžå…¬é–‹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "Cannot make the epic confidential if it contains non-confidential issues"
-msgstr ""
+msgstr "公開ã•ã‚Œã¦ã„るイシューãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã€ã‚¨ãƒ”ックをéžå…¬é–‹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "Cannot merge"
msgstr "マージã§ãã¾ã›ã‚“"
@@ -5045,7 +5127,7 @@ msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
msgid "Cannot set confidential epic for a non-confidential issue"
-msgstr ""
+msgstr "公開ã•ã‚Œã¦ã„るイシューã®ãŸã‚ã€ã‚¨ãƒ”ックをéžå…¬é–‹ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "プレビューを表示ã§ãã¾ã›ã‚“。Sketch ファイルをプレビューã™ã‚‹ã«ã¯ã€Sketch ãƒãƒ¼ã‚¸ãƒ§ãƒ³43以é™ã§å°Žå…¥ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«å½¢å¼ãŒå¿…è¦ã§ã™ã€‚"
@@ -5095,6 +5177,12 @@ msgstr "パスを変更"
msgid "Change permissions"
msgstr "アクセス権é™ã‚’変更"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5123,7 +5211,7 @@ msgid "ChangeReviewer|Reviewer changed to %{new}"
msgstr ""
msgid "ChangeReviewer|Unassigned"
-msgstr ""
+msgstr "未割り当ã¦"
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "ピック先ブランãƒ:"
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "ãƒã‚§ãƒªãƒ¼ãƒ”ック"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "リãƒãƒ¼ãƒˆ"
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "担当者を変更ã—ã¾ã—ãŸã€‚"
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr "タイトルを \"%{title_param}\" ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚"
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "%{docs_link_start}ドキュメント%{docs_link_end}を確èª"
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr "既知ã®è„†å¼±æ€§ã«å¯¾ã—ã¦ã€Dockerイメージをãƒã‚§ãƒƒã‚¯ã™ã‚‹."
@@ -5476,9 +5573,6 @@ msgstr "カラーをé¸æŠžã—ã¦ãã ã•ã„。"
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "ファイルをé¸æŠž..."
@@ -5497,6 +5591,9 @@ 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 "CI/CD パイプラインを実行ã—ãŸã„リãƒã‚¸ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。"
@@ -5656,12 +5753,24 @@ msgstr "分類ラベル (オプション)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "使用ã§ãã¾ã›ã‚“:%{reason}"
+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 "クリア"
@@ -5704,8 +5813,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "下ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã¨ã€Kubernetesã®ãƒšãƒ¼ã‚¸ã«é·ç§»ã—ã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ—ロセスを開始ã—ã¾ã™"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "クリックã—ã¦å±•é–‹ã€‚"
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "パターン"
-msgid "Cohorts"
-msgstr "コホート"
-
msgid "Cohorts|Inactive users"
msgstr "アクティブã§ã¯ãªã„ユーザー"
@@ -6932,7 +7038,7 @@ msgid "Collapse approvers"
msgstr "承èªè€…ã‚’éžè¡¨ç¤ºã«ã™ã‚‹"
msgid "Collapse milestones"
-msgstr ""
+msgstr "マイルストーンを折りãŸãŸã‚€"
msgid "Collapse replies"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "サイドãƒãƒ¼ã‚’éš ã™"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr "コレクタã®ãƒ›ã‚¹ãƒˆå"
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "アップグレードã®å•ã„åˆã‚ã›"
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr "ログインコマンドã®ã‚³ãƒ”ー"
msgid "ContainerRegistry|Copy push command"
msgstr "プッシュコマンドをコピー"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr "ã¾ã ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ãªã„å ´åˆã€GitLab ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr "コピーコマンド"
msgid "Copy commit SHA"
msgstr "コミットã®SHAをコピー"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr "環境をコピー"
@@ -7844,6 +7989,9 @@ msgstr "トリガートークンをコピー"
msgid "Copy value"
msgstr "値ã®ã‚³ãƒ”ー"
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "管ç†è€…ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦è¿½åŠ ã§ãã¾ã›ã‚“。"
@@ -7899,7 +8047,7 @@ msgid "Could not find design."
msgstr ""
msgid "Could not find iteration"
-msgstr ""
+msgstr "イテレーションãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "Could not load instance counts. Please refresh the page to try again."
msgstr ""
@@ -7975,7 +8123,7 @@ msgid "Create Project"
msgstr "プロジェクトを作æˆ"
msgid "Create Value Stream"
-msgstr ""
+msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’作æˆ"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
msgstr "ã¯ã˜ã‚ã«GitLabアカウントを作æˆã—ã€ãã®å¾Œ %{label} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«æŽ¥ç¶šã—ã¾ã™ã€‚"
@@ -8056,7 +8204,7 @@ msgid "Create issue"
msgstr "イシューã®ä½œæˆ"
msgid "Create iteration"
-msgstr ""
+msgstr "イテレーションã®ä½œæˆ"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "ラベルã‹ã‚‰ãƒªã‚¹ãƒˆã‚’作æˆã€‚ãã®ãƒ©ãƒ™ãƒ«ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
@@ -8074,13 +8222,13 @@ msgid "Create new"
msgstr "æ–°è¦ä½œæˆ "
msgid "Create new Value Stream"
-msgstr ""
+msgstr "æ–°è¦ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’作æˆ"
msgid "Create new branch"
msgstr "æ–°ã—ã„ブランãƒã‚’作æˆ"
msgid "Create new confidential %{issuableType}"
-msgstr ""
+msgstr "æ–°è¦ã®éžå…¬é–‹ %{issuableType} を作æˆ"
msgid "Create new directory"
msgstr "æ–°ã—ã„ディレクトリを作æˆ"
@@ -8140,81 +8288,102 @@ msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "個人用アクセストークンを作æˆ"
msgid "CreateValueStreamForm|%{name} (default)"
+msgstr "%{name} (デフォルト)"
+
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
msgstr ""
-msgid "CreateValueStreamForm|Add stage"
+msgid "CreateValueStreamForm|Add another stage"
msgstr ""
+msgid "CreateValueStreamForm|Add stage"
+msgstr "ステージを追加"
+
msgid "CreateValueStreamForm|All default stages are currently visible"
+msgstr "ã™ã¹ã¦ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã‚¹ãƒ†ãƒ¼ã‚¸ã¯ç¾åœ¨è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™"
+
+msgid "CreateValueStreamForm|Create from default template"
msgstr ""
-msgid "CreateValueStreamForm|Default stages"
+msgid "CreateValueStreamForm|Create from no template"
msgstr ""
+msgid "CreateValueStreamForm|Default stages"
+msgstr "デフォルトステージ"
+
msgid "CreateValueStreamForm|Editing stage"
-msgstr ""
+msgstr "ステージを編集"
msgid "CreateValueStreamForm|End event"
-msgstr ""
+msgstr "終了イベント"
msgid "CreateValueStreamForm|End event label"
-msgstr ""
+msgstr "終了イベントラベル"
msgid "CreateValueStreamForm|End event: "
-msgstr ""
-
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
+msgstr "終了イベント: "
msgid "CreateValueStreamForm|Enter stage name"
-msgstr ""
+msgstr "ステージåを入力"
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
-msgstr ""
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgstr "最大長 %{maxLength} 文字"
msgid "CreateValueStreamForm|Name is required"
-msgstr ""
+msgstr "åå‰ã¯å¿…é ˆã§ã™"
msgid "CreateValueStreamForm|New stage"
-msgstr ""
+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 ""
+msgstr "ステージを復元"
msgid "CreateValueStreamForm|Select end event"
-msgstr ""
+msgstr "終了イベントをé¸æŠž"
msgid "CreateValueStreamForm|Select start event"
-msgstr ""
+msgstr "開始イベントをé¸æŠž"
msgid "CreateValueStreamForm|Stage %{index}"
-msgstr ""
+msgstr "ステージ %{index}"
msgid "CreateValueStreamForm|Stage name already exists"
+msgstr "ステージåã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™"
+
+msgid "CreateValueStreamForm|Stage name is required"
msgstr ""
msgid "CreateValueStreamForm|Start event"
-msgstr ""
+msgstr "開始イベント"
msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
-msgstr ""
+msgstr "開始イベントãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚有効ãªçµ‚了イベントをé¸æŠžã—ã¦ãã ã•ã„"
msgid "CreateValueStreamForm|Start event label"
-msgstr ""
+msgstr "開始イベントラベル"
msgid "CreateValueStreamForm|Start event: "
-msgstr ""
+msgstr "開始イベント: "
msgid "CreateValueStreamForm|Update stage"
+msgstr "ステージを更新"
+
+msgid "CreateValueStreamForm|Value Stream name"
msgstr ""
msgid "Created"
@@ -8316,12 +8485,12 @@ msgstr ""
msgid "Current Branch"
msgstr "ç¾åœ¨ã®ãƒ–ランãƒ"
-msgid "Current Plan"
-msgstr "ç¾åœ¨ã®ãƒ—ラン"
-
msgid "Current Project"
msgstr "ç¾åœ¨ã®ãƒ—ロジェクト"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "ç¾åœ¨ã®ãƒŽãƒ¼ãƒ‰"
@@ -8346,8 +8515,8 @@ msgstr "プロフィール"
msgid "CurrentUser|Settings"
msgstr "設定"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "Gold試用版を開始"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr ""
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr "カスタムCIã®è¨­å®šãƒ‘ス"
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr "HTTP(S) 用ã®ã‚«ã‚¹ã‚¿ãƒ  Git クローン URL"
@@ -8430,8 +8596,8 @@ msgstr "言語ã¨åœ°åŸŸã®è¨­å®šã‚’カスタマイズã—ã¾ã™ã€‚"
msgid "Customize name"
msgstr "åå‰ã‚’カスタマイズ"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "Runner トークンã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€ãƒ‘イプラインã®è¨­å®šã‚’カスタマイズã€ãã—ã¦ãƒ‘イプラインã®çŠ¶æ…‹ã¨ã‚«ãƒãƒ¬ãƒƒã‚¸ãƒ¬ãƒãƒ¼ãƒˆã‚’閲覧ã—ã¾ã™ã€‚"
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr "パイプライン設定をカスタマイズ"
@@ -8641,8 +8807,8 @@ msgstr "%{firstProject} 㨠%{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest}, 㨠%{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
-msgstr "%{invalidProjects} を追加ã§ãã¾ã›ã‚“。ダッシュボードãŒåˆ©ç”¨ã§ãã‚‹ã®ã¯ã€å…¬é–‹ãƒ—ロジェクトã¨ã€æœ‰æ–™ã‚³ãƒ¼ã‚¹ã® Silverプランã®ãƒ—ライベートプロジェクトã ã‘ã§ã™ã€‚"
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
+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 ""
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8783,11 +8961,17 @@ msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider,
msgstr ""
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
-msgstr ""
+msgstr "ターゲットサイトãŠã‚ˆã³ã‚¹ã‚­ãƒ£ãƒ³ä»•æ§˜ã§ä¸€èˆ¬çš„ã«ä½¿ç”¨ã•ã‚Œã‚‹æ§‹æˆã‚’プロファイルã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚オンデマンドスキャンã§ã“れらを使用ã—ã¾ã™ã€‚"
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9044,7 +9246,7 @@ msgid "Delete Comment"
msgstr "コメントを削除"
msgid "Delete Value Stream"
-msgstr ""
+msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’削除"
msgid "Delete account"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -9518,7 +9747,7 @@ msgid "Description"
msgstr "説明"
msgid "Description (optional)"
-msgstr ""
+msgstr "説明 (オプション)"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
msgstr "%{link_start} GitLab風ã®ãƒžãƒ¼ã‚¯ãƒ€ã‚¦ãƒ³ %{link_end} ã§ãƒ‘ースã—ãŸèª¬æ˜Ž"
@@ -9527,7 +9756,7 @@ msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}.
msgstr ""
msgid "Description template"
-msgstr ""
+msgstr "説明テンプレート"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
msgstr "説明テンプレートを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŠã‚ˆã³ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®èª¬æ˜Žã«å¯¾ã™ã‚‹ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆå›ºæœ‰ã®ãƒ†ãƒ³ãƒ—レートを定義ã§ãã¾ã™ã€‚"
@@ -9664,7 +9893,7 @@ msgstr "デザインã¯æœ€å¤§ã§ %{upload_limit} ã¾ã§ã‚¢ãƒƒãƒ—ロードã§ãã
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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,8 +10112,8 @@ msgstr "無効"
msgid "Disable for this project"
msgstr "ã“ã®ãƒ—ロジェクトã§ã¯ç„¡åŠ¹ã«ã™ã‚‹"
-msgid "Disable group Runners"
-msgstr "グループ Runner を無効ã«ã™ã‚‹"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr "Pages サイトã¸ã®å…¬é–‹ã‚¢ã‚¯ã‚»ã‚¹ã‚’無効ã«ã™ã‚‹"
@@ -10184,9 +10404,6 @@ msgstr "ã“ã®ãƒ—ロセスã®é€”中ã§ã€GitLab å´ã‹ã‚‰ã® URL ã‚’èžã‹ã‚Œã‚‹
msgid "Dynamic Application Security Testing (DAST)"
msgstr "動的アプリケーションセキュリティテスト (DAST)"
-msgid "Each Runner can be in one of the following states:"
-msgstr "å„ Runner ã¯æ¬¡ã®ã„ãšã‚Œã‹ã®çŠ¶æ…‹ã‚’ã¨ã‚Šã¾ã™:"
-
msgid "Edit"
msgstr "編集"
@@ -10272,7 +10489,7 @@ msgid "Edit issues"
msgstr "イシューを編集"
msgid "Edit iteration"
-msgstr ""
+msgstr "イテレーションã®ç·¨é›†"
msgid "Edit public deploy key"
msgstr "公開デプロイキーã®ç·¨é›†"
@@ -10290,7 +10507,7 @@ msgid "Edit this release"
msgstr "ã“ã®ãƒªãƒªãƒ¼ã‚¹ã‚’編集ã—ã¾ã™ã€‚"
msgid "Edit title and description"
-msgstr ""
+msgstr "タイトルã¨èª¬æ˜Žã‚’編集"
msgid "Edit wiki page"
msgstr "Wikiページã®ç·¨é›†"
@@ -10347,28 +10564,28 @@ msgid "Email"
msgstr "メール"
msgid "Email %{number}"
-msgstr ""
+msgstr "%{number} 件ã®ãƒ¡ãƒ¼ãƒ«"
msgid "Email Notification"
-msgstr ""
+msgstr "メール通知"
msgid "Email address to use for Support Desk"
msgstr ""
msgid "Email cannot be blank"
-msgstr ""
+msgstr "メールを空白ã«ã§ãã¾ã›ã‚“"
msgid "Email could not be sent"
-msgstr ""
+msgstr "メールをé€ä¿¡ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Email display name"
-msgstr ""
+msgstr "メールã®è¡¨ç¤ºå"
msgid "Email not verified. Please verify your email in Salesforce."
msgstr "メールãŒç¢ºèªã§ãã¦ã„ã¾ã›ã‚“。 Salesforce ã§ãƒ¡ãƒ¼ãƒ«ã‚’確èªã—ã¦ãã ã•ã„。"
msgid "Email notification for unknown sign-ins"
-msgstr ""
+msgstr "ä¸æ˜Žãªã‚µã‚¤ãƒ³ã‚¤ãƒ³ã®ãƒ¡ãƒ¼ãƒ«é€šçŸ¥"
msgid "Email patch"
msgstr "パッãƒã‚’メールã™ã‚‹"
@@ -10377,7 +10594,7 @@ msgid "Email restrictions"
msgstr "メールã®åˆ¶é™"
msgid "Email restrictions for sign-ups"
-msgstr ""
+msgstr "サインアップ時ã®ãƒ¡ãƒ¼ãƒ«åˆ¶é™"
msgid "Email sent"
msgstr "メールé€ä¿¡å®Œäº†"
@@ -10389,7 +10606,7 @@ msgid "Email updates (optional)"
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 "メールãŒç©ºã®ã‚ˆã†ã§ã™ã€‚返信文ãŒãƒ¡ãƒ¼ãƒ«ã®ä¸€ç•ªä¸Šã«ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。インラインã®è¿”ä¿¡ã¯å‡¦ç†ã§ãã¾ã›ã‚“。"
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr "リセットã™ã‚‹"
@@ -10481,6 +10707,9 @@ msgstr "HTML メールã®æœ‰åŠ¹åŒ–"
msgid "Enable Incident Management inbound alert limit"
msgstr "インシデント管ç†ã‚¤ãƒ³ãƒã‚¦ãƒ³ãƒ‰ã‚¢ãƒ©ãƒ¼ãƒˆåˆ¶é™ã‚’有効ã«ã™ã‚‹"
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr "PlantUML を有効化"
msgid "Enable Pseudonymizer data collection"
msgstr "匿å化データã®åŽé›†ã‚’有効ã«ã—ã¾ã™"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr "シートリンクを有効ã«ã™ã‚‹"
@@ -10529,8 +10761,8 @@ msgstr "アクセスレベルをé¸æŠžã™ã‚‹æ©Ÿèƒ½ã‚’有効ã«ã™ã‚‹"
msgid "Enable for this project"
msgstr "ã“ã®ãƒ—ロジェクトã§ã¯æœ‰åŠ¹ã«ã™ã‚‹"
-msgid "Enable group Runners"
-msgstr "グループ Runner を有効ã«ã™ã‚‹"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr "メールã®ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’有効ã«ã™ã‚‹"
@@ -10568,8 +10800,8 @@ msgstr "ä¿è­·ã•ã‚ŒãŸãƒ‘スã®ãƒ¬ãƒ¼ãƒˆåˆ¶é™ã‚’有効ã«ã™ã‚‹"
msgid "Enable proxy"
msgstr "プロキシを有効ã«ã™ã‚‹"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgstr "reCAPTCHA ã¾ãŸã¯ Akismet を有効ã«ã—ã¦ã€IP制é™ã‚’設定ã—ã¾ã™ã€‚ reCAPTCHA ã«ã¤ã„ã¦ã¯ã€ç¾åœ¨ %{recaptcha_v2_link_start} v2 %{recaptcha_v2_link_end} ã®ã¿ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
msgid "Enable shared runners"
msgstr ""
@@ -10631,15 +10863,21 @@ msgstr "レンダリング中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %{err}"
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "終了時刻 (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr "DNSå†ãƒã‚¤ãƒ³ãƒ‰æ”»æ’ƒã«å¯¾ã™ã‚‹ä¿è­·ã‚’強化ã™ã‚‹"
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,14 +10974,11 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
msgstr ""
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "環境変数ã¯ã€ç®¡ç†è€…ã«ã‚ˆã£ã¦ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãŒ %{link_start}ä¿è­·%{link_end} ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚"
-
-msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
-msgstr "ã“ã® GitLab インスタンスã®ç’°å¢ƒå¤‰æ•°ã¯ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã¯ %{link_start}ä¿è­·%{link_end} ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
+msgstr ""
msgid "Environment:"
msgstr "環境:"
@@ -11033,6 +11268,9 @@ msgstr ""
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "本当㫠%{bStart}%{parentEpicTitle}%{bEnd} ã‹ã‚‰ %{bStart}%{targetIssueTitle}%{bEnd} を削除ã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11040,7 +11278,7 @@ msgid "Epics|How can I solve this?"
msgstr "ã©ã†ã™ã‚Œã°è§£æ±ºã§ãã¾ã™ã‹ï¼Ÿ"
msgid "Epics|Leave empty to inherit from milestone dates"
-msgstr ""
+msgstr "空ã®ã¾ã¾ã«ã—ãŸå ´åˆã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®æ—¥ä»˜ã‚’継承ã—ã¾ã™"
msgid "Epics|Remove epic"
msgstr "エピックを削除"
@@ -11048,6 +11286,12 @@ msgstr "エピックを削除"
msgid "Epics|Remove issue"
msgstr "イシューã®å‰Šé™¤"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "詳細を見る"
@@ -11079,7 +11323,7 @@ msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from
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 ""
+msgstr "ã“ã®ã‚¨ãƒ”ックã¨ã“ã‚Œå«ã¾ã‚Œã¦ã„ã‚‹å­ã‚¨ãƒ”ックã¯éžå…¬é–‹ã§ã‚ã‚Šã€å°‘ãªãã¨ã‚‚Reporterアクセス権é™ã®ã‚ã‚‹ãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã«ã®ã¿è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
msgstr "%{bStart}%{parentEpicTitle}%{bEnd} ã‹ã‚‰ %{bStart}%{targetEpicTitle}%{bEnd} 以下ã®å…¨ã¦ã®èª²é¡Œã‚’削除ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -11115,7 +11359,7 @@ msgid "Error creating label."
msgstr ""
msgid "Error creating new iteration"
-msgstr ""
+msgstr "æ–°ã—ã„イテレーションã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Error creating repository for snippet with id %{snippet_id}"
msgstr ""
@@ -11172,7 +11416,7 @@ msgid "Error loading issues"
msgstr ""
msgid "Error loading iterations"
-msgstr ""
+msgstr "イテレーションã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Error loading last commit."
msgstr "ç›´è¿‘ã®ã‚³ãƒŸãƒƒãƒˆã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "例: @sub\\.company\\.com$"
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr "例: Usage = å˜ä¸€ã‚¯ã‚¨ãƒªã€‚ (Requested) / (Capacity) = å¼ã‚’構æˆã™ã‚‹è¤‡æ•°ã‚¯ã‚¨ãƒªã€‚"
@@ -11490,7 +11731,7 @@ msgid "Expand file"
msgstr ""
msgid "Expand milestones"
-msgstr ""
+msgstr "マイルストーンを展開"
msgid "Expand sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "ã‚ãªãŸã®ãƒ—ロジェクトを新ã—ã„GitLabインスタンスã«ç§»å‹•ã™ã‚‹ãŸã‚ã«ã€ã“ã®ãƒ—ロジェクトã¨ãã®é–¢é€£ãƒ‡ãƒ¼ã‚¿ã™ã¹ã¦ã‚’ã¨å…±ã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚エクスãƒãƒ¼ãƒˆãŒå®Œäº†ã—ãŸã‚‰ã€\"æ–°ã—ã„プロジェクト\"ページã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’インãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚"
+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 Classification Policy Authorization"
msgstr "外部分類èªè¨¼ãƒãƒªã‚·ãƒ¼"
@@ -11646,7 +11893,7 @@ msgid "Failed to apply commands."
msgstr "コマンドã®é©ç”¨ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Failed to assign a reviewer because no user was found."
-msgstr ""
+msgstr "ユーザãŒè¦‹ã¤ã‹ã‚‰ãªã„ãŸã‚ã€ãƒ¬ãƒ“ュアーを割り当ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Failed to assign a user because no user was found."
msgstr "ユーザーã®å‰²ã‚Šå½“ã¦ã«å¤±æ•—ã—ã¾ã—ãŸã€‚見ã¤ã‹ã‚‰ãªã‹ã£ãŸã‹ã‚‰ã§ã™ã€‚"
@@ -11708,6 +11955,9 @@ msgstr "ãŠãらã長期間ã®ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒåŽŸå› ã§ã€rebaseæ“
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr "ref ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -11715,7 +11965,7 @@ msgid "Failed to install."
msgstr "インストールã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Failed to load assignees. Please try again."
-msgstr ""
+msgstr "担当者ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Failed to load authors. Please try again."
msgstr ""
@@ -11748,7 +11998,7 @@ msgid "Failed to load labels. Please try again."
msgstr ""
msgid "Failed to load milestones. Please try again."
-msgstr ""
+msgstr "マイルストーンã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Failed to load projects"
msgstr ""
@@ -11757,7 +12007,7 @@ msgid "Failed to load related branches"
msgstr "関連ã™ã‚‹ãƒ–ランãƒã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to load sidebar confidential toggle"
-msgstr ""
+msgstr "サイドãƒãƒ¼ã®éžå…¬é–‹ãƒˆã‚°ãƒ«ã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to load sidebar lock status"
msgstr ""
@@ -11835,7 +12085,7 @@ 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 ""
+msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®è¨­å®šã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Failed to signing using smartcard authentication"
msgstr "スマートカードèªè¨¼ã‚’使用ã—ã¦ã®ç½²åã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr "マージコミットã®ãªã„æ—©é€ã‚Šãƒžãƒ¼ã‚¸"
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr "プロジェクトワークスペースをå†åˆ©ç”¨ã™ã‚‹ã‚ˆã†ã«é«˜é€ŸåŒ–(存在ã—ãªã„å ´åˆã¯ã€ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’è¡Œã†)"
-
msgid "Faster releases. Better code. Less pain."
msgstr "より速ã„リリース。より良ã„コード。å•é¡Œã®æ¸›å°‘"
@@ -11914,7 +12161,7 @@ msgstr "機能フラグを正常ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚"
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
-msgstr[0] ""
+msgstr[0] "%d 人ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "FeatureFlags|%{percent} by available ID"
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr "詳細ã«ã¤ã„ã¦ã¯ %{deactivating_usage_ping_link_start}利用状æ³ã
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "プライベートãªãƒ—ロジェクトã®å ´åˆã€(ゲストã¾ãŸã¯ãれ以上ã®æ¨©é™ã®) ã™ã¹ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼ãŒãƒ‘イプラインを表示ã—ã€ã‚¸ãƒ§ãƒ–ã®è©³ç´°(出力ログãŠã‚ˆã³ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆ) ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "パブリックプロジェクトã®å ´åˆã€èª°ã§ã‚‚パイプラインを表示ã—ã€ã‚¸ãƒ§ãƒ–ã®è©³ç´° (出力ログãŠã‚ˆã³ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆ) ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
-
msgid "Forgot your password?"
msgstr "パスワードを忘れã¾ã—ãŸã‹ï¼Ÿ"
@@ -12516,8 +12769,8 @@ msgstr "イシューãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイ
msgid "From merge request merge until deploy to production"
msgstr "マージリクエストãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "Kubernetes クラスターã®è©³ç´°ç”»é¢ã‚’介ã—ã¦ã€ã‚¢ãƒ—リケーションリストã‹ã‚‰ Runner をインストールã—ã¾ã™ã€‚"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr "æ°å"
@@ -12564,6 +12817,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Geo ノード"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,8 +13234,8 @@ msgstr "Git リビジョン"
msgid "Git shallow clone"
msgstr "Git シャロークローン"
-msgid "Git strategy for pipelines"
-msgstr "パイプラインã®Git戦略"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "GitLab グループ Runner ã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã®å…¨ã¦ã®ãƒ—ロジェクトã®ã‚³ãƒ¼ãƒ‰ã‚’実行ã§ãã¾ã™ã€‚"
-
msgid "GitLab Import"
msgstr "GitLab インãƒãƒ¼ãƒˆ"
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "最åˆã®ãƒ‡ãƒ—ロイ後ã€ã‚µã‚¤ãƒˆãŒåˆ©ç”¨å¯èƒ½ã«ãªã‚‹ã¾ã§ã«æœ€å¤§ã§30分ã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr "é™çš„サイトをアップロードã—ã€GitLab ã§ãƒ›ã‚¹ãƒˆã™ã‚‹ã«ã¯ %{link_start} GitLab Pages ã®æ–‡æ›¸%{link_end} ã«å¾“ã£ã¦å­¦ã‚“ã§ãã ã•ã„。"
-
msgid "GitLabPages|Learn more."
msgstr "詳ã—ã見る。"
@@ -13161,6 +13414,9 @@ msgstr "ページを削除ã™ã‚‹ã¨ã€ãƒšãƒ¼ã‚¸ãŒå¤–部ã«å…¬é–‹ã•ã‚Œãªããª
msgid "GitLabPages|Save"
msgstr "ä¿å­˜"
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 "%{domain} ã® Let's Encrypt 証明書をå–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã™ã‚‹ã«ã¯ã€ %{link_start} ドメインã®è©³ç´° %{link_end} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。"
@@ -13434,9 +13690,6 @@ msgstr "'%{group_name}' グループã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "CI/CD グループ設定"
-
msgid "Group Git LFS status:"
msgstr "グループ Git LFS ã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹:"
@@ -13452,9 +13705,6 @@ msgstr "グループID:%{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr "グループ管ç†ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’有効ã«ã™ã‚‹å‰ã«ã€ã‚°ãƒ«ãƒ¼ãƒ—所有者ãŒSAMLã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
-msgid "Group Runners"
-msgstr "グループ Runner"
-
msgid "Group SAML must be enabled to test"
msgstr "グループ SAML を有効ã«ã—ã¦ãƒ†ã‚¹ãƒˆã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™"
@@ -13506,15 +13756,24 @@ msgstr "グループ Maintainer 㯠%{link} ã§ã‚°ãƒ«ãƒ¼ãƒ— Runner を登録ã§ã
msgid "Group members"
msgstr "グループã®ãƒ¡ãƒ³ãƒãƒ¼"
-msgid "Group milestone"
+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"
msgstr "グループã®æ¦‚è¦"
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr "グループã«ã¯åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¿…è¦ã§ã™"
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "グループ変数(継承)"
@@ -13609,7 +13874,7 @@ msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "エピックã®èª­ã¿è¾¼ã¿ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "GroupRoadmap|Something went wrong while fetching milestones"
-msgstr ""
+msgstr "マイルストーンã®èª­ã¿è¾¼ã¿ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "GroupRoadmap|Sorry, no epics matched your search"
msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ãƒžãƒƒãƒã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -13702,7 +13967,7 @@ msgid "GroupSAML|Prohibit outer forks for this group."
msgstr ""
msgid "GroupSAML|Role to assign members of this SAML group."
-msgstr ""
+msgstr "ã“ã® SAML グループã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’割り当ã¦ã‚‹ãƒ­ãƒ¼ãƒ«ã€‚"
msgid "GroupSAML|SAML Group Links"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "%{strong_start}%{group_name}%{strong_end} ã¸ã‚¢ã‚¯ã‚»ã‚¹ã§ãるグループ"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "よã使ã†ãƒ—ロジェクト"
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã€ãƒ‘スã€è»¢é€ã€å‰Šé™¤ã€ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–。"
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr "ID"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-msgstr "ã„ãšã‚Œã‹ã®ã‚¸ãƒ§ãƒ–ãŒã“ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆé–¾å€¤ã‚’超ãˆã‚‹ã¨ã€å¤±æ•—ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ã¾ã™ã€‚人間ãŒèª­ã‚る時間ã¨ã—ã¦\"1 hour\"ã®ã‚ˆã†ã«å…¥åŠ›ã§ãã¾ã™ã€‚å˜ä½æŒ‡å®šãªã—ã®å€¤ã¯ç§’ã¨ã—ã¦æ‰±ã„ã¾ã™ã€‚"
-
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 ""
@@ -14372,18 +14640,15 @@ msgstr "無効ã«ã™ã‚‹ã¨ã€åˆ†å²ã—ãŸãƒ­ãƒ¼ã‚«ãƒ«ãƒ–ランãƒã¯ã€ãƒ­ãƒ¼ã‚«
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr "無効ã«ã™ã‚‹ã¨ã€ç®¡ç†è€…ã®ã¿ãŒãƒªãƒã‚¸ãƒˆãƒªãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°ã‚’設定ã§ãã¾ã™ã€‚"
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "無効ã«ã™ã‚‹ã¨ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒ¬ãƒ™ãƒ«ã¯ãã®ãƒ—ロジェクトã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æ¨©é™ã«ä¾å­˜ã—ã¾ã™ã€‚"
-
-msgid "If enabled"
-msgstr "有効ã«ã—ãŸå ´åˆ"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14658,7 +15268,7 @@ msgid "IncidentManagement|All alerts promoted to incidents will automatically be
msgstr ""
msgid "IncidentManagement|Assignees"
-msgstr ""
+msgstr "担当者"
msgid "IncidentManagement|Closed"
msgstr ""
@@ -14715,7 +15325,7 @@ msgid "IncidentManagement|Time to SLA"
msgstr ""
msgid "IncidentManagement|Unassigned"
-msgstr ""
+msgstr "未割り当ã¦"
msgid "IncidentManagement|Unknown"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,8 +15495,8 @@ msgstr "インライン"
msgid "Input host keys manually"
msgstr "ホストキーã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«å…¥åŠ›"
-msgid "Input your repository URL"
-msgstr "リãƒã‚¸ãƒˆãƒªã® URL を入力ã—ã¦ãã ã•ã„"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr "コードブロックを挿入"
@@ -14886,22 +15526,22 @@ msgid "Insert video"
msgstr ""
msgid "Insights"
-msgstr "洞察"
+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 ""
+msgstr "プロジェクト㌠insights.yml ファイル内ã§é™¤å¤–ã•ã‚Œã„ã‚‹ãŸã‚ã€ã„ãã¤ã‹ã®é …ç›®ãŒè¡¨ç¤ºã•ã‚Œã¾ã›ã‚“(詳細ã«ã¤ã„ã¦ã¯ projects.only設定をå‚ç…§ã—ã¦ãã ã•ã„)。"
msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクトã¯insights.ymlファイルã§é™¤å¤–ã•ã‚Œã¾ã™ï¼ˆè©³ç´°ã«ã¤ã„ã¦ã¯ã€projects.only設定をå‚ç…§ã—ã¦ãã ã•ã„)。"
msgid "Install"
msgstr "インストール"
-msgid "Install GitLab Runner"
-msgstr "GitLab Runner ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Kubernetes 㫠Runner をインストール"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "アプリケーションリãƒã‚¸ãƒˆãƒªã‹ã‚‰ %{free_otp_link} ã‚„Google èªè¨¼ãªã©ã®ã‚½ãƒ•ãƒˆèªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’インストールã—ã€ãれを使ã£ã¦ã“ã®QRコードをスキャンã—ã¾ã™ã€‚より詳ã—ã„情報㯠%{help_link_start} 文書 %{help_link_end} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -14925,9 +15565,21 @@ msgstr[0] "インスタンス"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15163,7 +15836,7 @@ msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Insights config file detected"
-msgstr "無効㪠Insights 設定ファイルãŒã¿ã¤ã‹ã‚Šã¾ã—ãŸ"
+msgstr "無効ãªã‚¤ãƒ³ã‚µã‚¤ãƒˆè¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ãŒã¿ã¤ã‹ã‚Šã¾ã—ãŸ"
msgid "Invalid Login or password"
msgstr "ログインIDã¾ãŸã¯ãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚"
@@ -15216,6 +15889,9 @@ msgstr "入力ãŒç„¡åŠ¹ã§ã™ã€‚絵文字をå«ã‚ãªã„ã§ãã ã•ã„"
msgid "Invalid login or password"
msgstr "ログインIDã¾ãŸã¯ãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚"
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "PIN コードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚"
@@ -15262,7 +15938,7 @@ msgid "Invite"
msgstr "招待"
msgid "Invite \"%{email}\" by email"
-msgstr ""
+msgstr "メール㧠\"%{email}\" を招待"
msgid "Invite \"%{trimmed}\" by email"
msgstr "メール㧠\"%{trimmed}\" を招待"
@@ -15276,6 +15952,9 @@ msgstr "グループã«æ‹›å¾…ã™ã‚‹"
msgid "Invite member"
msgstr "メンãƒãƒ¼ã‚’招待ã™ã‚‹"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr "ステータス"
msgid "IssueAnalytics|Weight"
msgstr "ウェイト"
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr "イシューã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤
msgid "Issues closed"
msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "コメントã®ã‚るイシューã€å·®åˆ†ã¨ã‚³ãƒ¡ãƒ³ãƒˆã€ãƒ©ãƒ™ãƒ«ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆã€ãã®ä»–ã®ãƒ—ロジェクトエンティティã¨é–¢é€£ã—ãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15646,31 +16331,31 @@ msgid "It's you"
msgstr "ã‚ãªãŸã§ã™"
msgid "Iteration"
-msgstr ""
+msgstr "イテレーション"
msgid "Iteration changed to"
-msgstr ""
+msgstr "イテレーションを変更ã—ã¾ã—ãŸ"
msgid "Iteration lists not available with your current license"
-msgstr ""
+msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ä¸€è¦§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "Iteration removed"
-msgstr ""
+msgstr "イテレーションを削除ã—ã¾ã—ãŸ"
msgid "Iteration updated"
-msgstr ""
+msgstr "イテレーションを更新ã—ã¾ã—ãŸ"
msgid "Iterations"
-msgstr ""
+msgstr "イテレーション"
msgid "Iteration|Dates cannot overlap with other existing Iterations"
-msgstr ""
+msgstr "日付ã¯ä»–ã®æ—¢å­˜ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã¨é‡è¤‡ã§ãã¾ã›ã‚“"
msgid "Iteration|cannot be in the past"
-msgstr ""
+msgstr "éŽåŽ»ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "Iteration|cannot be more than 500 years in the future"
-msgstr ""
+msgstr "500年以上先ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
msgid "I’m familiar with the basics of DevOps."
msgstr ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} イベントã¯ç„¡åŠ¹ã§ã™ã€‚"
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Web URLã¨ç•°ãªã‚‹å ´åˆ"
msgid "JiraService|Issue List"
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 "JIRA APIã®URL"
@@ -15762,6 +16465,9 @@ msgstr "イシューãŒãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§å‚ç…§ã•ã‚Œã‚‹ã¨ Jiraã®ã‚³ã
msgid "JiraService|Jira issue tracker"
msgstr "Jiraイシュートラッカー"
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "パスワードã¾ãŸã¯APIトークン"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,8 +16615,8 @@ msgstr "ジョブã®ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆ"
msgid "Job|Job has been erased"
msgstr "ジョブãŒæ¶ˆåŽ»ã•ã‚Œã¾ã—ãŸ"
-msgid "Job|Job has been erased by"
-msgstr "ジョブãŒæ¶ˆåŽ»ã•ã‚Œã¾ã—ãŸ:"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "維æŒ"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,8 +16907,8 @@ msgstr "最終連絡日時"
msgid "Last edited %{date}"
msgstr "最終編集日 %{date}"
-msgid "Last edited by %{name}"
-msgstr "最終編集者 %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "GitLab ã‚’å­¦ã¶"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Auto DevOps ã®è©³ç´°"
-msgid "Learn more about Kubernetes"
-msgstr "Kubernetes ã®è©³ç´°"
-
msgid "Learn more about License-Check"
msgstr "ライセンスãƒã‚§ãƒƒã‚¯ã®è©³ç´°ã«ã¤ã„ã¦"
@@ -16580,6 +17304,9 @@ msgstr[0] "イベント表示数を最大 %d 個ã«åˆ¶é™"
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr "マージ済ã¿"
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 "変更ã®ã¿è¡¨ç¤º"
@@ -16805,9 +17535,6 @@ msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹"
msgid "Make sure you save it - you won't be able to access it again."
msgstr "ã“ã‚Œã¯å¿…ãšä¿å­˜ã—ã¦ãã ã•ã„。二度ã¨ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。"
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr "イシューをéžå…¬é–‹ã«ã™ã‚‹ã€‚"
@@ -16836,7 +17563,7 @@ msgid "Manage labels"
msgstr "ラベルを管ç†"
msgid "Manage milestones"
-msgstr ""
+msgstr "マイルストーンã®ç®¡ç†"
msgid "Manage project labels"
msgstr "プロジェクトラベルã®ç®¡ç†"
@@ -16850,6 +17577,9 @@ msgstr "2è¦ç´ èªè¨¼ã®ç®¡ç†"
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -16908,7 +17638,7 @@ msgid "Markdown enabled"
msgstr "マークダウンを使用ã§ãã¾ã™"
msgid "Markdown is supported"
-msgstr "マークダウンをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚"
+msgstr "MarkdownãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã™"
msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr "パーソナルアクセストークンã®æœ€é•·è¨±å®¹å¯¿å‘½(日数)"
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr "アーティファクトサイズã®ä¸Šé™ (MB)"
@@ -17087,9 +17820,6 @@ msgstr "ジョブタイムアウトã®æœ€å¤§å€¤"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr "最大ジョブタイムアウトã«ã¯å—ã‘入れられãªã„値ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã™"
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr "パーソナルアクセストークンã®æœ€é•·æœ‰åŠ¹æœŸé–“設定ãŒæœ‰åŠ¹ã§ã™ã€‚有効期é™ã¯ %{maximum_allowable_date} よりå‰ã«è¨­å®šã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -17132,6 +17862,9 @@ msgstr "åŒæœŸãŒã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã¨ãã«ãƒŸãƒ©ãƒ¼ãƒªãƒ³ã‚°ã®
msgid "May"
msgstr "5月"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr "測定ã—ãŸã‚³ãƒ¼ãƒ‰ã®ãƒã‚¤ãƒˆæ•°ã€‚自動生æˆã‚³ãƒ¼ãƒ‰ã¨ãƒ™ãƒ³ãƒ€ãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’除外ã—ã¾ã™ã€‚"
@@ -17159,9 +17892,6 @@ msgstr "メンãƒãƒ¼"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "%{strong_start}%{group_name}%{strong_end} ã¸ã‚¢ã‚¯ã‚»ã‚¹ã§ãるメンãƒãƒ¼"
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr "マージリクエストã®ä¾å­˜é–¢ä¿‚"
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr "下書ãコメントã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "スカッシュã«å¤±æ•—ã—ã¾ã—ãŸã€‚手動ã§è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "返信..."
@@ -17522,15 +18252,9 @@ msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "マージ済ã¿"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "%{success_count}/%{total_count} 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒç§»è¡Œã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr "移行æˆåŠŸ"
@@ -17942,85 +18669,85 @@ msgid "Milestone lists show all issues from the selected milestone."
msgstr "マイルストーンリストã«ã¯ã€é¸æŠžã—ãŸãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’表示ã—ã¾ã™ã€‚"
msgid "MilestoneCombobox|An error occurred while searching for milestones"
-msgstr ""
+msgstr "マイルストーンã®æ¤œç´¢ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "MilestoneCombobox|Group milestones"
-msgstr ""
+msgstr "グループマイルストーン"
msgid "MilestoneCombobox|Milestone"
-msgstr ""
+msgstr "マイルストーン"
msgid "MilestoneCombobox|No matching results"
-msgstr ""
+msgstr "一致ã™ã‚‹çµæžœãŒã‚ã‚Šã¾ã›ã‚“"
msgid "MilestoneCombobox|No milestone"
-msgstr ""
+msgstr "マイルストーンãªã—"
msgid "MilestoneCombobox|Project milestones"
-msgstr ""
+msgstr "プロジェクトマイルストーン"
msgid "MilestoneCombobox|Search Milestones"
-msgstr ""
+msgstr "マイルストーンを検索"
msgid "MilestoneCombobox|Select milestone"
-msgstr ""
+msgstr "マイルストーンをé¸æŠž"
msgid "MilestoneSidebar|Closed:"
-msgstr ""
+msgstr "クローズ:"
msgid "MilestoneSidebar|Copy reference"
-msgstr ""
+msgstr "å‚照をコピー"
msgid "MilestoneSidebar|Due date"
-msgstr ""
+msgstr "期é™"
msgid "MilestoneSidebar|Edit"
-msgstr ""
+msgstr "編集"
msgid "MilestoneSidebar|From"
-msgstr ""
+msgstr "開始"
msgid "MilestoneSidebar|Issues"
-msgstr ""
+msgstr "イシュー"
msgid "MilestoneSidebar|Merge requests"
-msgstr ""
+msgstr "マージリクエスト"
msgid "MilestoneSidebar|Merged:"
-msgstr ""
+msgstr "マージ:"
msgid "MilestoneSidebar|New Issue"
-msgstr ""
+msgstr "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "MilestoneSidebar|New issue"
-msgstr ""
+msgstr "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "MilestoneSidebar|No due date"
-msgstr ""
+msgstr "期é™ãªã—"
msgid "MilestoneSidebar|No start date"
-msgstr ""
+msgstr "開始日ãªã—"
msgid "MilestoneSidebar|None"
-msgstr ""
+msgstr "ãªã—"
msgid "MilestoneSidebar|Open:"
-msgstr ""
+msgstr "オープン:"
msgid "MilestoneSidebar|Reference:"
-msgstr ""
+msgstr "å‚ç…§:"
msgid "MilestoneSidebar|Start date"
-msgstr ""
+msgstr "開始日"
msgid "MilestoneSidebar|Toggle sidebar"
-msgstr ""
+msgstr "サイドãƒãƒ¼ã‚’トグル"
msgid "MilestoneSidebar|Until"
-msgstr ""
+msgstr "終了"
msgid "MilestoneSidebar|complete"
-msgstr ""
+msgstr "完了"
msgid "Milestones"
msgstr "マイルストーン"
@@ -18032,10 +18759,10 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
msgstr "ã‚ãªãŸã¯ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ %{milestoneTitle} を永久ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã¯ç¾åœ¨ã€ã‚¤ã‚·ãƒ¥ãƒ¼ã¾ãŸã¯ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Milestones|Close Milestone"
-msgstr ""
+msgstr "マイルストーンをクローズ"
msgid "Milestones|Completed Issues (closed)"
-msgstr ""
+msgstr "完了ã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼(クローズ)"
msgid "Milestones|Delete milestone"
msgstr "マイルストーンã®å‰Šé™¤"
@@ -18047,19 +18774,19 @@ msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
msgstr "マイルストーン %{milestoneTitle} ã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Milestones|Group Milestone"
-msgstr ""
+msgstr "グループマイルストーン"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
msgstr "マイルストーン %{milestoneTitle} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
msgid "Milestones|No milestones found"
-msgstr ""
+msgstr "マイルストーンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "Milestones|Ongoing Issues (open and assigned)"
-msgstr ""
+msgstr "進行中ã®ã‚¤ã‚·ãƒ¥ãƒ¼(オープンã‹ã¤å‰²ã‚Šå½“ã¦æ¸ˆã¿)"
msgid "Milestones|Project Milestone"
-msgstr ""
+msgstr "プロジェクトマイルストーン"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
msgstr "%{milestoneTitle} をグループマイルストーンã«æ˜‡æ ¼ã—ã¾ã™ã‹ï¼Ÿ"
@@ -18068,19 +18795,19 @@ msgid "Milestones|Promote Milestone"
msgstr "マイルストーンã®æ˜‡æ ¼"
msgid "Milestones|Promote to Group Milestone"
-msgstr ""
+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 "%{milestoneTitle} を昇格ã™ã‚‹ã¨ã€ %{groupName} 内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã§ä½¿ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚åŒã˜ã‚¿ã‚¤ãƒˆãƒ«ã‚’æŒã¤æ—¢å­˜ã®ãƒ—ロジェクトマイルストーンãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™ã€‚"
msgid "Milestones|Reopen Milestone"
-msgstr ""
+msgstr "マイルストーンをå†ã‚ªãƒ¼ãƒ—ン"
msgid "Milestones|This action cannot be reversed."
msgstr "ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。"
msgid "Milestones|Unstarted Issues (open and unassigned)"
-msgstr ""
+msgstr "開始ã—ã¦ã„ãªã„イシュー (オープンã‹ã¤æœªå‰²ã‚Šå½“ã¦)"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr "より多ãã®ãƒŸãƒ©ãƒ¼ã‚’優先的ã«ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã™ã‚‹å‰ã«ä½¿ç”¨å¯èƒ½ã«ãªã‚‹ãŸã‚ã®æœ€å°å®¹é‡ã€‚"
@@ -18097,6 +18824,9 @@ msgstr "分"
msgid "Mirror direction"
msgstr "ミラーã®æ–¹å‘"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "ミラーリãƒã‚¸ãƒˆãƒª"
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "キャンセル"
-
msgid "Modal|Close"
msgstr "é–‰ã˜ã‚‹"
@@ -18287,7 +19014,7 @@ msgid "Multiple Prometheus integrations are not supported"
msgstr ""
msgid "Multiple domains are supported."
-msgstr ""
+msgstr "複数ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚"
msgid "Multiple model types found: %{model_types}"
msgstr "複数ã®ãƒ¢ãƒ‡ãƒ«ã‚¿ã‚¤ãƒ—ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: %{model_types}"
@@ -18319,9 +19046,6 @@ msgstr "åå‰"
msgid "Name has already been taken"
msgstr "ãã®åå‰ã¯æ—¢ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "æ–°ã—ã„ラベルã«åå‰ã‚’ã¤ã‘ã‚‹"
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,11 +19195,17 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
msgid "NetworkPolicies|Description"
-msgstr ""
+msgstr "説明"
msgid "NetworkPolicies|Edit policy"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18541,7 +19268,7 @@ msgid "NetworkPolicies|Policy definition"
msgstr ""
msgid "NetworkPolicies|Policy description"
-msgstr ""
+msgstr "ãƒãƒªã‚·ãƒ¼ã®èª¬æ˜Ž"
msgid "NetworkPolicies|Policy editor"
msgstr ""
@@ -18716,10 +19443,10 @@ msgid "New changes were added. %{linkStart}Reload the page to review them%{linkE
msgstr "æ–°ã—ã„変更ãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸã€‚%{linkStart}ページをリロードã—ã¦ãƒ¬ãƒ“ューã—ã¦ãã ã•ã„%{linkEnd}"
msgid "New confidential epic title "
-msgstr ""
+msgstr "æ–°ã—ã„éžå…¬é–‹ã®ã‚¨ãƒ”ックã®ã‚¿ã‚¤ãƒˆãƒ« "
msgid "New confidential issue title"
-msgstr ""
+msgstr "æ–°ã—ã„éžå…¬é–‹ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¿ã‚¤ãƒˆãƒ«"
msgid "New deploy key"
msgstr "æ–°ã—ã„デプロイキー"
@@ -18761,10 +19488,10 @@ msgid "New issue title"
msgstr "æ–°è¦ã‚¤ã‚·ãƒ¥ãƒ¼ã®ã‚¿ã‚¤ãƒˆãƒ«"
msgid "New iteration"
-msgstr ""
+msgstr "æ–°è¦ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³"
msgid "New iteration created"
-msgstr ""
+msgstr "æ–°è¦ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒä½œæˆã•ã‚Œã¾ã—ãŸ"
msgid "New label"
msgstr "æ–°ã—ã„ラベル"
@@ -18778,8 +19505,8 @@ msgstr "æ–°ã—ã„マイルストーン"
msgid "New password"
msgstr "æ–°ã—ã„パスワード"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "æ–°ã—ã„パイプラインã¯ã€åŒã˜ãƒ–ランãƒã®å¤ã„パイプラインをキャンセルã—ã¾ã™"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "æ–°è¦ãƒ—ロジェクト"
@@ -18895,6 +19622,9 @@ msgstr "é©ç”¨ã•ã‚ŒãŸãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã¨ä¸€è‡´ã™ã‚‹å­ã‚¨ãƒ”ックã¯ã‚ã‚Šã¾
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Gitaly サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ログを確èªã—ã¦ãã ã•ã„ï¼"
@@ -18956,10 +19686,10 @@ msgid "No issues found"
msgstr ""
msgid "No iteration"
-msgstr ""
+msgstr "イテレーションãŒã‚ã‚Šã¾ã›ã‚“"
msgid "No iterations to show"
-msgstr ""
+msgstr "表示ã™ã‚‹ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "No job log"
msgstr "ジョブログãŒã‚ã‚Šã¾ã›ã‚“"
@@ -18988,6 +19718,9 @@ msgstr "一致ã™ã‚‹çµæžœãŒã‚ã‚Šã¾ã›ã‚“"
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -18998,7 +19731,7 @@ msgid "No messages were logged"
msgstr "メッセージã¯è¨˜éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "No milestone"
-msgstr ""
+msgstr "マイルストーンãªã—"
msgid "No milestones to show"
msgstr "表示ã™ã‚‹ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -19063,9 +19796,6 @@ msgstr "ã‚ãªãŸã®æ¤œç´¢ã«ãƒžãƒƒãƒã—ãŸãŠæ°—ã«å…¥ã‚Šã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "No start date"
msgstr "開始日ãªã—"
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr "テンプレートãŒã‚ã‚Šã¾ã›ã‚“"
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr "脆弱性ã¯ç™ºè¦‹ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -19106,7 +19839,7 @@ msgid "None"
msgstr "ãªã—"
msgid "None of the group milestones have the same project as the release"
-msgstr ""
+msgstr "リリースã¨åŒã˜ãƒ—ロジェクトをæŒã¤ã‚°ãƒ«ãƒ¼ãƒ—マイルストーンãŒã‚ã‚Šã¾ã›ã‚“"
msgid "Not Implemented"
msgstr "未実装"
@@ -19154,7 +19887,7 @@ msgid "Not started"
msgstr "開始ã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "Not supported"
-msgstr ""
+msgstr "サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "Note"
msgstr "注æ„事項"
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,29 +20267,38 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
msgstr ""
msgid "OnDemandScans|Edit on-demand DAST scan"
-msgstr ""
+msgstr "オンデマンドDASTスキャンを編集"
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
-msgstr ""
+msgstr "æ–°è¦ã‚ªãƒ³ãƒ‡ãƒžãƒ³ãƒ‰DASTスキャン"
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
msgstr ""
@@ -19556,10 +20307,10 @@ msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to
msgstr ""
msgid "OnDemandScans|On-demand Scans"
-msgstr ""
+msgstr "オンデマンドスキャン"
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
-msgstr ""
+msgstr "オンデマンドスキャン㯠DevOps ã®ã‚µã‚¤ã‚¯ãƒ«å¤–ã§å®Ÿè¡Œã•ã‚Œã€ãƒ—ロジェクトã®è„†å¼±æ€§ã‚’見ã¤ã‘ã¾ã™ã€‚%{learnMoreLinkStart}詳細を表示%{learnMoreLinkEnd}"
msgid "OnDemandScans|Run scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,8 +20385,8 @@ msgstr ""
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
msgstr "一ã¤ä»¥ä¸Šã®ãƒ‘ーソナルアクセストークン㌠%{days_to_expire} 日以内ã«å¤±åŠ¹ã—ã¾ã™"
-msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
-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 "出ç¾è¡Œã¯1ã¤ã ã‘存在ã§ãã¾ã™"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr "管ç†è€…ã ã‘ãŒãƒ—ロジェクトを削除ã§ãã¾ã™"
-msgid "Only mirror protected branches"
-msgstr "ä¿è­·ãƒ–ランãƒã®ã¿ãƒŸãƒ©ãƒ¼"
-
msgid "Only policy:"
msgstr "ãƒãƒªã‚·ãƒ¼ã®ã¿:"
@@ -19673,14 +20421,14 @@ 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 / Silver and above can see Productivity Analytics."
-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 "未解決(Open)"
+msgstr "オープン"
msgid "Open Selection"
msgstr "é¸æŠžæ¸ˆã¿ã®ã‚‚ã®ã‚’é–‹ã"
@@ -19781,15 +20529,15 @@ msgstr "オプション"
msgid "Or you can choose one of the suggested colors below"
msgstr "ã¾ãŸã¯ã€ä¸‹è¨˜ã®ã„ãšã‚Œã‹ã®è‰²ã‚’é¸æŠžã§ãã¾ã™"
-msgid "Origin"
-msgstr "Origin"
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "ãã®ä»–ã®ãƒ©ãƒ™ãƒ«"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "ãã®ä»–ã®æƒ…å ±"
@@ -19964,9 +20712,6 @@ msgstr "パッケージãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®å‰Šé™¤"
msgid "PackageRegistry|Delete package"
msgstr "パッケージã®å‰Šé™¤"
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr "Pypiã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{linkStart}ドキュã
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr "å‚加者"
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20253,10 +21004,10 @@ msgid "Paste a machine public key here. Read more about how to generate it %{lin
msgstr "マシンã®å…¬é–‹éµã‚’ã“ã“ã«è²¼ã‚Šä»˜ã‘ã¾ã™ã€‚生æˆæ–¹æ³•ã«ã¤ã„ã¦ã¯%{link_start}ã“ã¡ã‚‰%{link_end}を確èªã—ã¦ä¸‹ã•ã„。"
msgid "Paste confidential epic link"
-msgstr ""
+msgstr "éžå…¬é–‹ã‚¨ãƒ”ックリンクを貼り付ã‘"
msgid "Paste confidential issue link"
-msgstr ""
+msgstr "éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ã®ãƒªãƒ³ã‚¯ã‚’貼り付ã‘"
msgid "Paste epic link"
msgstr "エピックリンクã®è²¼ã‚Šä»˜ã‘"
@@ -20327,6 +21078,9 @@ msgstr "ダウンロード"
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr "フロントエンドリソース"
@@ -20393,6 +21147,9 @@ msgstr "パイプラインスケジュール"
msgid "Pipeline Schedules"
msgstr "パイプラインスケジュール"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "パイプラインクォータ(分)"
@@ -20405,6 +21162,9 @@ 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 "パイプラインã®ãƒˆãƒªã‚¬ãƒ¼"
@@ -20532,7 +21292,7 @@ msgid "Pipelines|Copy trigger token"
msgstr ""
msgid "Pipelines|Description"
-msgstr ""
+msgstr "説明"
msgid "Pipelines|Edit"
msgstr ""
@@ -20573,9 +21333,6 @@ msgstr "パイプラインを読ã¿è¾¼ã¿ä¸­"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "プロジェクトã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’正常ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã—ãŸã€‚"
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "パイプラインã¯ç¾åœ¨ã‚ã‚Šã¾ã›ã‚“。"
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "パイプラインをフェッãƒã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ã„ãŸã ãã‹ã€ã‚µãƒãƒ¼ãƒˆãƒãƒ¼ãƒ ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。"
@@ -20726,6 +21483,9 @@ msgstr "パイプラインを実行"
msgid "Pipeline|Run for"
msgstr "実行対象"
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr "フィードトークンを正常ã«ãƒªã‚»ãƒƒãƒˆã§ãã¾ã—ãŸ"
msgid "Profiles|Full name"
msgstr "フルãƒãƒ¼ãƒ "
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "プロフィールã«å€‹äººçš„ãªã‚³ãƒ³ãƒˆãƒªãƒ“ューションをå«ã‚ã‚‹"
@@ -21446,9 +22209,6 @@ msgstr "組織"
msgid "Profiles|Path"
msgstr "パス"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "ã‚ãªãŸã®æ–°ã—ã„ã‚¢ãƒã‚¿ãƒ¼ã®ä½ç½®ã¨ã‚µã‚¤ã‚º"
@@ -21723,7 +22483,7 @@ msgid "Project members"
msgstr "プロジェクトメンãƒãƒ¼"
msgid "Project milestone"
-msgstr ""
+msgstr "プロジェクトマイルストーン"
msgid "Project name"
msgstr "プロジェクトå"
@@ -21731,6 +22491,9 @@ msgstr "プロジェクトå"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr "ローカルストレージãŒåˆ©ç”¨ã§ããªã„ãŸã‚ã€ãƒ—ロジェクトã®é †åºã¯ä¿å­˜ã•ã‚Œã¾ã›ã‚“。"
@@ -21843,7 +22606,7 @@ msgid "ProjectService|Event will be triggered when a commit is created/updated"
msgstr ""
msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
-msgstr ""
+msgstr "イベントã¯ã€éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ãŒä½œæˆã€æ›´æ–°ã¾ãŸã¯ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸã¨ãã«ãƒˆãƒªã‚¬ãƒ¼ã•ã‚Œã¾ã™"
msgid "ProjectService|Event will be triggered when a deployment starts or finishes"
msgstr ""
@@ -21870,7 +22633,7 @@ msgid "ProjectService|Event will be triggered when someone adds a comment"
msgstr ""
msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
-msgstr ""
+msgstr "イベントã¯ã€éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ã¸ã®ã‚³ãƒ¡ãƒ³ãƒˆã®è¿½åŠ ã«ã‚ˆã£ã¦ãƒˆãƒªã‚¬ãƒ¼ã•ã‚Œã¾ã™"
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr "GitLabプロジェクト㮠%{project_name} ã§ä¸€èˆ¬çš„ãªæ“作を実行"
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr "グループã«å±žã™ã‚‹ãƒ—ロジェクトã®å…ˆé ­ã«ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—
msgid "Projects to index"
msgstr "インデックスを作æˆã™ã‚‹ãƒ—ロジェクト"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22533,7 +23299,7 @@ msgid "Promote"
msgstr "昇格"
msgid "Promote confidential issue to a non-confidential epic"
-msgstr ""
+msgstr "éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’公開エピックã«æ˜‡æ ¼ã™ã‚‹"
msgid "Promote issue to an epic"
msgstr "イシューをエピックã«æ˜‡æ ¼"
@@ -22554,16 +23320,16 @@ msgid "PromoteMilestone|Promotion failed - %{message}"
msgstr "プロモートã«å¤±æ•—ã—ã¾ã—㟠- %{message}"
msgid "Promoted confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members."
-msgstr ""
+msgstr "éžå…¬é–‹ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’公開エピックã«æ˜‡æ ¼ã—ã¾ã—ãŸã€‚エピックã¯ã‚°ãƒ«ãƒ¼ãƒ—メンãƒãƒ¼ã«å…¬é–‹ã•ã‚Œã‚‹ãŸã‚ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®æƒ…å ±ã¯éžå…¬é–‹ã§ã¯ãªããªã‚Šã¾ã—ãŸã€‚"
msgid "Promoted issue to an epic."
msgstr "イシューをエピックã«æ˜‡æ ¼æ¸ˆã¿"
msgid "Promotion is not supported."
-msgstr ""
+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 ""
+msgstr "ãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ ãƒãƒ£ãƒ¼ãƒˆã¯ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®é€²æ—を視覚的ã«è¡¨ç¾ã—ã¾ã™ã€‚ 一目ã§æŒ‡å®šãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®å®Œäº†çŠ¶æ³ã‚’把æ¡ã§ãã¾ã™ã€‚ã“ã‚ŒãŒãªã‘ã‚Œã°ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ãƒ‡ãƒ¼ã‚¿ã‚’æ•´ç†ã—ã¦è‡ªåˆ†ã§ãƒ—ロットã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "Promotions|Buy EE"
msgstr ""
@@ -22593,7 +23359,7 @@ msgid "Promotions|Improve issues management with Issue weight and GitLab Enterpr
msgstr ""
msgid "Promotions|Improve milestones with Burndown Charts."
-msgstr ""
+msgstr "ãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ãƒãƒ£ãƒ¼ãƒˆã§ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’改善ã—ã¾ã™ã€‚"
msgid "Promotions|Learn more"
msgstr "詳ã—ã見る"
@@ -22626,7 +23392,7 @@ msgid "Promotions|Upgrade your plan to activate Contribution Analytics."
msgstr "プランをアップグレードã—ã¦è²¢çŒ®åº¦åˆ†æžã‚’有効化ã™ã‚‹ã€‚"
msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
-msgstr ""
+msgstr "ãƒãƒ¼ãƒ³ãƒ€ã‚¦ãƒ³ãƒãƒ£ãƒ¼ãƒˆã§ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’改善ã™ã‚‹ã«ã¯ã€ãƒ—ランをアップグレードã—ã¦ãã ã•ã„。"
msgid "Promotions|Weight"
msgstr ""
@@ -22646,6 +23412,9 @@ msgstr "SSH éµã‚’アップロードã™ã‚‹ã‚ˆã†ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ä¿ƒã™"
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr "プッシュを許å¯:"
msgid "ProtectedBranch|Branch"
msgstr "ブランãƒ"
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr "コードオーナーã®æ‰¿èª"
@@ -22730,6 +23502,9 @@ msgstr "デプロイ許å¯"
msgid "ProtectedEnvironment|Environment"
msgstr "環境"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "ä¿è­·"
@@ -22739,9 +23514,6 @@ msgstr "環境をä¿è­·"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "ä¿è­·ç’°å¢ƒ (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr "環境をä¿è­·ã™ã‚‹ã¨ã€ãƒ‡ãƒ—ロイメントを実行ã§ãるユーザーãŒåˆ¶é™ã•ã‚Œã¾ã™ã€‚"
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "環境をé¸æŠž"
@@ -22751,8 +23523,8 @@ msgstr "ユーザーã®é¸æŠž"
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr "ユーザーをé¸æŠžã—ã¦ã€æ©Ÿèƒ½ãƒ•ãƒ©ã‚°è¨­å®šã‚’表示ã€ç®¡ç†ã—ã¾ã™ã€‚"
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "ç¾åœ¨ä¿è­·ç’°å¢ƒã¯ã‚ã‚Šã¾ã›ã‚“。上ã®ãƒ•ã‚©ãƒ¼ãƒ ã§ç’°å¢ƒã‚’ä¿è­·ã—ã¦ãã ã•ã„。"
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "ä¿è­·ã®è§£é™¤"
@@ -22970,6 +23742,9 @@ msgstr "関連ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã«ã¤ã„ã¦ã‚‚ã£ã¨èª­ã‚€"
msgid "Real-time features"
msgstr "リアルタイム機能"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr "Rebase"
@@ -23082,12 +23857,21 @@ msgstr "ユニãƒãƒ¼ã‚µãƒ«ãª2è¦ç´ èªè¨¼ãƒ‡ãƒã‚¤ã‚¹ã‚’登録ã™ã‚‹"
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "2è¦ç´ èªè¨¼ã‚¢ãƒ—リã§ç™»éŒ²"
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "関連ã™ã‚‹ãƒ‡ãƒ—ロイ済ジョブ"
-
msgid "Related Issues"
msgstr "関連ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼"
-msgid "Related Jobs"
-msgstr "関連ã™ã‚‹ã‚¸ãƒ§ãƒ–"
-
-msgid "Related Merge Requests"
-msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
-
-msgid "Related Merged Requests"
-msgstr "関連ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
-
msgid "Related issues"
msgstr ""
@@ -23150,7 +23922,7 @@ msgid "Release assets documentation"
msgstr ""
msgid "Release does not have the same project as the milestone"
-msgstr ""
+msgstr "リリースã«ã¯ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã¨åŒã˜ãƒ—ロジェクトãŒã‚ã‚Šã¾ã›ã‚“"
msgid "Release notes"
msgstr "リリースノート"
@@ -23224,9 +23996,6 @@ msgstr "削除"
msgid "Remove %{displayReference}"
msgstr "%{displayReference} を削除"
-msgid "Remove Runner"
-msgstr "Runner を削除"
-
msgid "Remove Zoom meeting"
msgstr "Zoom ミーティングを削除"
@@ -23237,7 +24006,7 @@ msgid "Remove all or specific label(s)"
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã¾ãŸã¯ç‰¹å®šã®ãƒ©ãƒ™ãƒ«ã‚’削除ã™ã‚‹"
msgid "Remove all or specific reviewer(s)"
-msgstr ""
+msgstr "ã™ã¹ã¦ã®ã€ã¾ãŸã¯ç‰¹å®šã®ãƒ¬ãƒ“ュアーを削除"
msgid "Remove approver"
msgstr ""
@@ -23264,7 +24033,7 @@ msgid "Remove child epic from an epic"
msgstr "エピックã‹ã‚‰å­ã‚¨ãƒ”ックを削除"
msgid "Remove description history"
-msgstr ""
+msgstr "説明履歴を削除"
msgid "Remove due date"
msgstr "期日を削除"
@@ -23285,7 +24054,7 @@ msgid "Remove group"
msgstr "グループを削除"
msgid "Remove iteration"
-msgstr ""
+msgstr "イテレーションを削除"
msgid "Remove license"
msgstr ""
@@ -23318,6 +24087,9 @@ msgid "Remove report"
msgstr ""
msgid "Remove reviewer"
+msgstr "レビューアを削除"
+
+msgid "Remove runner"
msgstr ""
msgid "Remove secondary node"
@@ -23348,7 +24120,7 @@ msgid "Removed %{epic_ref} from child epics."
msgstr "å­ã‚¨ãƒ”ックã‹ã‚‰ %{epic_ref} を削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{iteration_reference} iteration."
-msgstr ""
+msgstr "%{iteration_reference} ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} を削除ã—ã¾ã—ãŸã€‚"
@@ -23357,7 +24129,7 @@ msgid "Removed %{milestone_reference} milestone."
msgstr "%{milestone_reference} マイルストーンを削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{reviewer_text} %{reviewer_references}."
-msgstr ""
+msgstr "%{reviewer_text} %{reviewer_references} を削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{type} with id %{id}"
msgstr "Id %{id} 㮠%{type} を削除"
@@ -23396,7 +24168,7 @@ msgid "Removes %{epic_ref} from child epics."
msgstr "å­ã‚¨ãƒ”ックã‹ã‚‰ %{epic_ref} を削除"
msgid "Removes %{iteration_reference} iteration."
-msgstr ""
+msgstr "%{iteration_reference} ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã€‚"
msgid "Removes %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} を削除ã—ã¾ã™ã€‚"
@@ -23405,7 +24177,7 @@ msgid "Removes %{milestone_reference} milestone."
msgstr "%{milestone_reference} マイルストーンを削除"
msgid "Removes %{reviewer_text} %{reviewer_references}."
-msgstr ""
+msgstr "%{reviewer_text} %{reviewer_references} を削除ã—ã¾ã™ã€‚"
msgid "Removes all labels."
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除"
@@ -23516,7 +24288,7 @@ msgid "Report abuse to admin"
msgstr "管ç†è€…ã«ä¸æ­£åˆ©ç”¨ã‚’報告"
msgid "Reported %{timeAgo} by %{reportedBy}"
-msgstr ""
+msgstr "%{timeAgo} ã« %{reportedBy} ã«ã‚ˆã‚Šå ±å‘Š"
msgid "Reported by %{reporter}"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23609,7 +24385,7 @@ msgid "Reports|Vulnerability"
msgstr "脆弱性"
msgid "Reports|Vulnerability Name"
-msgstr ""
+msgstr "脆弱性å"
msgid "Reports|no changed test results"
msgstr "テストçµæžœã«å¤‰æ›´ã‚ã‚Šã¾ã›ã‚“。"
@@ -23731,6 +24507,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,8 +24641,8 @@ msgstr "正常性ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセット"
msgid "Reset key"
msgstr "éµã‚’リセット"
-msgid "Reset runners registration token"
-msgstr "Runner 登録トークンをリセット"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr "テンプレートã®ãƒªã‚»ãƒƒãƒˆ"
@@ -23985,6 +24764,9 @@ msgstr "å†è©¦è¡Œ"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "ジョブをå†è©¦è¡Œã—ã¦ãã ã•ã„"
@@ -24031,6 +24813,9 @@ 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 "ã‚ãªãŸã® ID プロãƒã‚¤ãƒ€ãƒ¼ã®ã‚µãƒ¼ãƒ“スプロãƒã‚¤ãƒ€ãƒ¼ã‚’構æˆã™ã‚‹ãŸã‚ã®ãƒ—ロセスを確èªã—ã¾ã™ã€‚ ã“ã®ä¾‹ã§ã¯ã€GitLab ã¯ã€Œã‚µãƒ¼ãƒ“スプロãƒã‚¤ãƒ€ãƒ¼ã€ã¾ãŸã¯ã€Œè¨¼æ˜Žæ›¸åˆ©ç”¨è€…ã€ã€‚"
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr "レビュー時間"
@@ -24042,7 +24827,7 @@ msgstr ""
msgid "Reviewer"
msgid_plural "%d Reviewers"
-msgstr[0] ""
+msgstr[0] "%d 人ã®ãƒ¬ãƒ“ュー"
msgid "Reviewer(s)"
msgstr ""
@@ -24071,6 +24856,9 @@ msgstr "パーソナルアクセストークン㮠%{personal_access_token_name}
msgid "Revoked project access token %{project_access_token_name}!"
msgstr "プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ %{project_access_token_name} を無効ã«ã—ã¾ã—ãŸã€‚"
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr "追加中"
@@ -24090,7 +24878,7 @@ msgid "Rook"
msgstr "Rook"
msgid "Ruby"
-msgstr ""
+msgstr "Ruby"
msgid "Rule name is already taken."
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr "Webターミナルを使用ã—ã¦ãƒ†ã‚¹ãƒˆã‚’実行"
msgid "Run untagged jobs"
msgstr "ã‚¿ã‚°ã®ãªã„ジョブã®å®Ÿè¡Œ"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr "Runner ã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Runners"
msgstr "Runner"
-msgid "Runners API"
-msgstr "Runner API"
-
-msgid "Runners activated for this project"
-msgstr "ã“ã®ãƒ—ロジェクト用ã«Runnerをアクティブ化"
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr "Runner ã¯ã€GitLab ã®ã‚¸ãƒ§ãƒ–ã‚’å–å¾—ã—ã¦å®Ÿè¡Œã™ã‚‹ãƒ—ロセスã§ã™ã€‚ã“ã“ã§ã€ã“ã®ãƒ—ロジェクト㮠Runner を登録ã—ã¦ç¢ºèªã§ãã¾ã™ã€‚"
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Runner ã¯åˆ¥ã€…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã‚µãƒ¼ãƒãƒ¼ã€ã•ã‚‰ã«ã¯ã‚ãªãŸã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒžã‚·ãƒ¼ãƒ³ã«ã‚‚é…ç½®ã§ãã¾ã™ã€‚"
-
msgid "Runners can be:"
msgstr ""
@@ -24164,13 +24943,25 @@ msgstr "Runner ã®ãƒšãƒ¼ã‚¸ã€‚"
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
+msgstr "説明"
+
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
msgstr ""
msgid "Runners|Group"
@@ -24179,6 +24970,9 @@ msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Runners |共有ランナーパイプラインã®%{quotaLimit} ã®ã†ã¡%{quotaUsed} を使用ã—ã¾ã—ãŸã€‚"
@@ -24290,6 +25099,9 @@ msgstr "SSH 公開éµ"
msgid "SSL Verification:"
msgstr "SSL ã®æ¤œè¨¼:"
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24372,7 +25184,7 @@ msgid "Scope"
msgstr "スコープ"
msgid "Scope board to current iteration"
-msgstr ""
+msgstr "ç¾åœ¨ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã§çµžã‚Šè¾¼ã‚“ã ãƒœãƒ¼ãƒ‰"
msgid "Scopes"
msgstr "スコープ"
@@ -24525,7 +25337,7 @@ msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "自身ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
-msgstr ""
+msgstr "自分ãŒãƒ¬ãƒ“ュアーã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "SearchAutocomplete|in all GitLab"
msgstr "å…¨ã¦ã® GitLab 中ã§"
@@ -24625,6 +25437,9 @@ msgstr "秘密"
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "セキュリティ"
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24737,7 +25555,7 @@ msgid "SecurityReports|Add a project to your dashboard"
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 ""
+msgstr "セキュリティエリアã§ç›£è¦–ã™ã‚‹ãƒ—ロジェクトを追加ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚ ã“ã®ä¸€è¦§ã«å«ã¾ã‚Œã‚‹ãƒ—ロジェクトã§ã¯ã€ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã¨è„†å¼±æ€§ãƒ¬ãƒãƒ¼ãƒˆã«çµæžœãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
msgid "SecurityReports|Add projects"
msgstr "プロジェクトを追加"
@@ -24746,13 +25564,13 @@ msgid "SecurityReports|Add projects to your group"
msgstr ""
msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
-msgstr ""
+msgstr "'%{vulnerabilityName}' ã«è¿½åŠ ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
-msgstr ""
+msgstr "'%{vulnerabilityName}' ã‹ã‚‰å‰Šé™¤ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
-msgstr ""
+msgstr "'%{vulnerabilityName}' ã®ç·¨é›†ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆ"
msgid "SecurityReports|Create issue"
msgstr "イシューを作æˆã™ã‚‹"
@@ -24761,13 +25579,13 @@ msgid "SecurityReports|Dismiss Selected"
msgstr ""
msgid "SecurityReports|Dismiss vulnerability"
-msgstr ""
+msgstr "脆弱性をéžè¡¨ç¤ºã«ã™ã‚‹"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
-msgstr ""
+msgstr "éžè¡¨ç¤ºã«ã•ã‚ŒãŸ '%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
-msgstr ""
+msgstr "'%{vulnerabilityName}'ã‚’éžè¡¨ç¤ºã«ã—ã¾ã—ãŸã€‚表示ã™ã‚‹ã«ã¯ã€éžè¡¨ç¤ºåˆ‡ã‚Šæ›¿ãˆã‚’オフã«ã—ã¾ã™ã€‚"
msgid "SecurityReports|Download %{artifactName}"
msgstr ""
@@ -24785,10 +25603,10 @@ msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd}
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "脆弱性件数ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®çŠ¶æ…‹ã‚’確èªã—ã€ã‚‚ã†ä¸€åº¦å®Ÿè¡Œã—ã¦ãã ã•ã„。"
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "脆弱性一覧ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®çŠ¶æ…‹ã‚’確èªã—ã€ã‚‚ã†ä¸€åº¦å®Ÿè¡Œã—ã¦ãã ã•ã„。"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
msgstr ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24809,7 +25624,7 @@ msgid "SecurityReports|Issue Created"
msgstr ""
msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
-msgstr ""
+msgstr "脆弱性ã‹ã‚‰ä½œæˆã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼ã¯å‰Šé™¤ã§ãã¾ã›ã‚“。"
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr "ダッシュボードã®è¨­å®šã®è©³ç´°"
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24909,13 +25721,13 @@ msgstr ""
msgid "SecurityReports|There was an error dismissing %d vulnerability. Please try again later."
msgid_plural "SecurityReports|There was an error dismissing %d vulnerabilities. Please try again later."
-msgstr[0] ""
+msgstr[0] "%d 件ã®è„†å¼±æ€§ã‚’éžè¡¨ç¤ºã«ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
msgstr ""
msgid "SecurityReports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "脆弱性をéžè¡¨ç¤ºã«ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "SecurityReports|There was an error reverting the dismissal."
msgstr ""
@@ -24939,13 +25751,13 @@ msgid "SecurityReports|Undo dismiss"
msgstr ""
msgid "SecurityReports|Upgrade to interact, track and shift left with vulnerability management features in the UI."
-msgstr ""
+msgstr "UIã®è„†å¼±æ€§ç®¡ç†æ©Ÿèƒ½ã‚’使用ã—ãŸã‚¤ãƒ³ã‚¿ãƒ©ã‚¯ãƒˆã€ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã€ã‚·ãƒ•ãƒˆãƒ¬ãƒ•ãƒˆã®ãŸã‚ã«ã‚¢ãƒƒãƒ—グレードã™ã‚‹ã€‚"
msgid "SecurityReports|Upgrade to manage vulnerabilities"
msgstr ""
msgid "SecurityReports|Vulnerability Report"
-msgstr ""
+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 ""
@@ -24974,15 +25786,15 @@ msgstr "メトリクスをå‚ç…§"
msgid "See the affected projects in the GitLab admin panel"
msgstr "GitLab管ç†ç”»é¢ã§å½±éŸ¿ã‚’å—ã‘るプロジェクトをå‚ç…§"
+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 "See what's new at GitLab"
-msgstr "GitLab ã®æœ€æ–°æƒ…報を見る"
-
msgid "Select"
msgstr "é¸æŠž"
@@ -25020,7 +25832,7 @@ msgid "Select a project"
msgstr "プロジェクトã®é¸æŠž"
msgid "Select a project to read Insights configuration file"
-msgstr "Insights構æˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’読むプロジェクトをé¸æŠžã—ã¦ãã ã•ã„"
+msgstr "インサイト設定ファイルを読むプロジェクトをé¸æŠžã—ã¦ãã ã•ã„"
msgid "Select a reason"
msgstr ""
@@ -25040,11 +25852,11 @@ msgstr "タイムゾーンをé¸æŠž"
msgid "Select all"
msgstr "ã™ã¹ã¦é¸æŠž"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "既存㮠Kubernetes クラスターをé¸æŠžã™ã‚‹ã‹ã€æ–°ã—ã„ã‚‚ã®ã‚’作æˆ"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
-msgstr ""
+msgstr "担当者をé¸æŠž"
msgid "Select branch"
msgstr "ブランãƒã®é¸æŠž"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr "ターゲットブランãƒã‚’é¸æŠž"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "ã“ã®ãƒ—ロジェクトã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã¨ã—ã¦è¨­å®šã™ã‚‹ãƒ–ランãƒã‚’é¸æŠžã—ã¾ã™ã€‚ã‚ãªãŸãŒä»–ã®ãƒ–ランãƒã‚’指定ã—ãªã„é™ã‚Šã€ã™ã¹ã¦ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¨ã‚³ãƒŸãƒƒãƒˆãŒã“ã®ãƒ–ランãƒã«å¯¾ã—ã¦è‡ªå‹•çš„ã«è¡Œã‚ã‚Œã¾ã™ã€‚"
-
msgid "Select the custom project template source group."
msgstr "カスタムã®ãƒ—ロジェクトテンプレートã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¾ã™ã€‚"
@@ -25335,7 +26147,7 @@ msgid "Service Desk is not enabled"
msgstr ""
msgid "Service Desk is not supported"
-msgstr ""
+msgstr "サービスデスクã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“"
msgid "Service Templates"
msgstr "サービス テンプレート"
@@ -25380,7 +26192,7 @@ msgid "Set instance-wide template repository"
msgstr "インスタンス全体レベルã®ãƒ†ãƒ³ãƒ—レートリãƒã‚¸ãƒˆãƒªã‚’設定ã—ã¾ã™ã€‚"
msgid "Set iteration"
-msgstr ""
+msgstr "イテレーションを設定"
msgid "Set limit to 0 to allow any file size."
msgstr ""
@@ -25412,6 +26224,9 @@ msgstr "ターゲットブランãƒã‚’設定"
msgid "Set target branch to %{branch_name}."
msgstr "ターゲットブランãƒã‚’ %{branch_name} ã«è¨­å®šã—ã¾ã—ãŸã€‚"
+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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25425,7 +26240,7 @@ msgid "Set the duration for which the jobs will be considered as old and expired
msgstr ""
msgid "Set the iteration to %{iteration_reference}."
-msgstr ""
+msgstr "イテレーションを %{iteration_reference} ã«è¨­å®šã—ã¾ã—ãŸã€‚"
msgid "Set the maximum file size for each job's artifacts"
msgstr "å„ジョブã®ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆã®æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã‚’設定"
@@ -25451,11 +26266,11 @@ msgstr "CI/CD を設定"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
-msgstr "%{type} ã® Runner ã®è‡ªå‹•ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—"
+msgid "Set up a %{type} runner automatically"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "%{type} ã®Runnerã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—"
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr "æ–°ã—ã„パスワードを設定"
-msgid "Set up pipeline subscriptions for this project."
-msgstr "ã“ã®ãƒ—ロジェクトã®ãƒ‘イプラインサブスクリプションを設定。"
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25536,7 +26348,7 @@ msgid "Sets the due date to %{due_date}."
msgstr "期日を %{due_date} ã«è¨­å®š 。"
msgid "Sets the iteration to %{iteration_reference}."
-msgstr ""
+msgstr "イテレーションを %{iteration_reference} ã«è¨­å®šã—ã¾ã™ã€‚"
msgid "Sets the milestone to %{milestone_reference}."
msgstr "マイルストーンを %{milestone_reference} ã«è¨­å®šã€‚"
@@ -25616,9 +26428,6 @@ msgstr "使用済ã¿ã®ãƒ‘イプライン実行時間をリセットã™ã‚‹"
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-msgstr "ã‚ãªãŸã®æºå¸¯é›»è©±ã‚’紛失ã—ãŸã‚Šãƒ¯ãƒ³ã‚¿ã‚¤ãƒ ãƒ‘スワードを紛失ã—ãŸå ´åˆã€ã“れらã®ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’ãã‚Œãžã‚Œï¼‘回ãšã¤ä½¿ç”¨ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’回復ã§ãã¾ã™ã€‚安全ãªå ´æ‰€ã«ä¿å­˜ã—ã¦ãã ã•ã„。ãã†ã—ãªã„ã¨ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’%{b_start} 失ã„ã¾ã™ã€‚%{b_end}"
-
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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr "ã“ã®ã‚µãƒ¼ãƒ“スを設定ã—ãŸå¾Œã« Slack 上ã§ä½¿ç”¨ã§ãるコãƒ
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "ã“ã®ã‚µãƒ¼ãƒ“スã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ Slack ã«ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚³ãƒžãƒ³ãƒ‰ã‚’入力ã—ã¦ã€ã“ã®ãƒ—ロジェクト上ã®ä¸€èˆ¬çš„ãªæ“作ãŒå®Ÿè¡Œã§ãã¾ã™ã€‚"
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "é…ããªã‚Šã¾ã™ãŒã€ãƒ—ロジェクトã®ä½œæ¥­é ˜åŸŸã¯ã€ã™ã¹ã¦ã®ã‚¸ãƒ§ãƒ–ã®ãŸã‚ã«ã‚¼ãƒ­ã‹ã‚‰ãƒªãƒã‚¸ãƒˆãƒªã‚’クローンã™ã‚‹ã®ã§ã€ã‚¯ãƒªã‚¢ãªçŠ¶æ…‹ã«ãªã‚Šã¾ã™"
-
msgid "Smartcard"
msgstr "スマートカード"
@@ -26039,7 +26848,7 @@ msgid "Something went wrong while creating a requirement."
msgstr ""
msgid "Something went wrong while deleting description changes. Please try again."
-msgstr ""
+msgstr "説明履歴を削除中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
msgid "Something went wrong while deleting the package."
msgstr "パッケージを削除ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr "%{listType} ã®ãƒªã‚¹ãƒˆå–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -26141,7 +26953,7 @@ msgid "Something went wrong while updating a requirement."
msgstr ""
msgid "Something went wrong while updating assignees"
-msgstr ""
+msgstr "担当者ã®æ›´æ–°ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Something went wrong while updating your list settings"
msgstr "リスト設定を更新ã™ã‚‹é–“ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -26422,8 +27234,8 @@ msgstr "スパムã¨ã‚¢ãƒ³ãƒãƒœãƒƒãƒˆä¿è­·"
msgid "Spam log successfully submitted as ham."
msgstr "スパムログã¯ãƒãƒ ã¨ã—ã¦é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚"
-msgid "Specific Runners"
-msgstr "特定㮠Runner"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr "指定ã®URLã¯ä½¿ç”¨ã§ãã¾ã›ã‚“: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr "指定ã®URLã¯ä½¿ç”¨ã§ãã¾ã›ã‚“: \"%{reason}\""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "メールアドレスã®æ­£è¦è¡¨ç¾ãƒ‘ターンを指定ã—ã¦ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®å†…部ユーザーを区別ã—ã¾ã™ã€‚"
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Runner セットアップã®éš›ã«æ¬¡ã® URL を指定ã—ã¦ãã ã•ã„:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr "ステージ"
-msgid "Stage & Commit"
-msgstr "ステージ&コミット"
-
msgid "Stage data updated"
msgstr "ステージデータã®æ›´æ–°"
@@ -26509,8 +27315,8 @@ msgstr "Webターミナルã®èµ·å‹•"
msgid "Start a %{new_merge_request} with these changes"
msgstr "ã“ã®å¤‰æ›´ã§ %{new_merge_request} を作æˆã™ã‚‹"
-msgid "Start a Free Gold Trial"
-msgstr "ç„¡æ–™ã®ã‚´ãƒ¼ãƒ«ãƒ‰è©¦ç”¨ç‰ˆã‚’開始ã™ã‚‹"
+msgid "Start a Free Ultimate Trial"
+msgstr ""
msgid "Start a new discussion..."
msgstr "æ–°ã—ã議論を開始"
@@ -26542,9 +27348,6 @@ msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã‚’開始
msgid "Start search"
msgstr "検索開始"
-msgid "Start the Runner!"
-msgstr "Runner ã‚’èµ·å‹•!"
-
msgid "Start thread"
msgstr "スレッドを開始ã—ã¾ã™ã€‚"
@@ -26554,8 +27357,8 @@ msgstr "スレッドã®é–‹å§‹ã¨ã‚¯ãƒ­ãƒ¼ã‚º %{noteable_name}"
msgid "Start thread & reopen %{noteable_name}"
msgstr "スレッドã®é–‹å§‹ã¨ %{noteable_name} ã®å†é–‹"
-msgid "Start your Free Gold Trial"
-msgstr "ç„¡æ–™ã®ã‚´ãƒ¼ãƒ«ãƒ‰è©¦ç”¨ç‰ˆã‚’開始ã™ã‚‹"
+msgid "Start your Free Ultimate Trial"
+msgstr ""
msgid "Start your free trial"
msgstr "無料トライアルを開始"
@@ -26581,15 +27384,15 @@ msgstr "開始中..."
msgid "Starts %{startsIn}"
msgstr "%{startsIn} を開始ã—ã¾ã™"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "開始時刻 (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "メッセージを有効ã«ã™ã‚‹"
@@ -26600,7 +27403,7 @@ 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 ""
+msgstr "2. 変更を行ã£ãŸç†ç”±ã®èª¬æ˜Žã‚’追加ã—ã¾ã™ã€‚"
msgid "StaticSiteEditor|3. Assign a person to review and accept the merge request."
msgstr ""
@@ -26765,6 +27568,9 @@ msgid "StorageSize|Unknown"
msgstr "ä¸æ˜Ž"
msgid "Subgroup milestone"
+msgstr "サブグループマイルストーン"
+
+msgid "Subgroup navigation"
msgstr ""
msgid "Subgroup overview"
@@ -27178,6 +27984,9 @@ msgstr "システムヘッダーã¨ãƒ•ãƒƒã‚¿ãƒ¼"
msgid "System hook was successfully updated."
msgstr "システムフックã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "システムメトリクス(カスタム)"
@@ -27202,9 +28011,15 @@ 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 "コミット㫠\"%{message}\" ã¨å…±ã« %{tag_name} タグを付ã‘ã¾ã—ãŸã€‚"
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27657,13 +28475,13 @@ msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated lis
msgstr "Elasticsearchã¸ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹URL。クラスタリングをサãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ã‚³ãƒ³ãƒžåŒºåˆ‡ã‚Šãƒªã‚¹ãƒˆã‚’使用ã—ã¾ã™(例: http://localhost:9200, http://localhost:9201)。"
msgid "The Vulnerability Report shows the results of the last successful pipeline run on the default branch."
-msgstr ""
+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 ""
+msgstr "クライアントシークレットをéžå…¬é–‹ã«ã§ãる場所ã§ã‚¢ãƒ—リケーションを使用ã—ã¾ã™ã€‚ãƒã‚¤ãƒ†ã‚£ãƒ–モãƒã‚¤ãƒ«ã‚¢ãƒ—リã¨ã‚·ãƒ³ã‚°ãƒ«ãƒšãƒ¼ã‚¸ã‚¢ãƒ—リã¯éžå…¬é–‹ã¨ã¯ã¿ãªã—ã¾ã›ã‚“。"
msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
msgstr ""
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr "フォークã®ãƒªãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ %{size} ã§ã™ã€‚"
+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 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 "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«å¯¾ã™ã‚‹ãƒžãƒ¼ã‚¸ã®ç«¶åˆã¯ GitLab ã§ã¯è§£æ±ºã§ãã¾ã›ã‚“。ローカルã§è§£æ±ºã—ã¦ãã ã•ã„。"
@@ -27858,8 +28685,11 @@ msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ä»Šã€ãƒžãƒ¼ã‚¸ã§ãã¾ã™ã€‚"
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã€ \"%{name}\" ã¨ã„ã†åå‰ãŒã™ã§ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚"
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
-msgstr "リãƒã‚¸ãƒˆãƒªã‚’クローンã™ã‚‹ã¨ãã« GitLab ã‹ã‚‰å–å¾—ã•ã‚Œã‚‹å¤‰æ›´ã®æ•°ã€‚ã“ã‚Œã«ã‚ˆã‚Šãƒ‘イプラインã®å®Ÿè¡Œé€Ÿåº¦ã‚’上ã’ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚空ã®ã¾ã¾ã«ã™ã‚‹ã‹ã€0 ã«è¨­å®šã—ã¦ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã‚·ãƒ£ãƒ­ãƒ¼ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’無効ã«ã—ã€GitLab CI ã«æ¯Žå›žã™ã¹ã¦ã®ãƒ–ランãƒã¨ã‚¿ã‚°ã‚’å–å¾—ã•ã›ã¾ã™ã€‚"
+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 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 ""
@@ -27871,14 +28701,11 @@ 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 ""
+msgstr "親エピックã¯éžå…¬é–‹ã§ã€éžå…¬é–‹ã®ã‚¨ãƒ”ックã¨ã‚¤ã‚·ãƒ¥ãƒ¼ã ã‘ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™"
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "秘密éµã®å¾©å·ã«å¿…è¦ã¨ãªã‚‹ãƒ‘スフレーズ。ã“ã‚Œã¯ã‚ªãƒ—ションã§ã€å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "開発ライフサイクルã®æ®µéšŽ"
@@ -27924,6 +28751,9 @@ msgstr "プロジェクトを正常ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã—ãŸã€‚"
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "匿å化データコレクションã¯ç„¡åŠ¹ã§ã™ã€‚有効ã«ã—ãŸã¨ãã€GitLab ã¯ã€ã‚ãªãŸãŒè¨­å®šã—ãŸã‚ªãƒ–ジェクトストレージディレクトリã«ã‚¢ãƒƒãƒ—ロードã™ã‚‹ GitLab データベースã®åŒ¿å化ã—㟠CSV を生æˆã™ã‚‹ã‚¸ãƒ§ãƒ–ã‚’ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§å®Ÿè¡Œã—ã¾ã™ã€‚"
+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 took to long to complete."
msgstr "リモートミラーãŒå®Œäº†ã™ã‚‹ã¾ã§ã«æ™‚é–“ãŒã‹ã‹ã‚Šã¾ã™ã€‚"
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "レビューステージã¨ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¦ã‹ã‚‰ãƒžãƒ¼ã‚¸ã™ã‚‹ã¾ã§ã®æ™‚é–“ã§ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚ŒãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 "ユーザーマップã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトã«å‚加ã—㟠FogBugz ユーザーã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¦ãƒ¼ã‚¶ãƒ¼åã‚’ GitLab ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹æ™‚ã«ãƒžãƒƒãƒ”ングã—ã¾ã™ã€‚ã“れを変更ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®è¡¨ã«å…¥åŠ›ã—ã¾ã™ã€‚"
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28153,7 +28980,7 @@ msgid "There was a problem fetching labels."
msgstr ""
msgid "There was a problem fetching milestones."
-msgstr ""
+msgstr "マイルストーンã®å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was a problem fetching project branches."
msgstr ""
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr "ã‚ãªãŸã®ã‚«ã‚¹ã‚¿ãƒ ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’ä¿å­˜ã™ã‚‹éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™º
msgid "There was a problem sending the confirmation email"
msgstr "確èªãƒ¡ãƒ¼ãƒ«ã®é€ä¿¡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr "Todoã® %{message} ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -28318,7 +29151,7 @@ msgid "There was an error while fetching the table data. Please refresh the page
msgstr ""
msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
-msgstr ""
+msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžãƒ‡ãƒ¼ã‚¿(%{requestTypeName})ã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error while fetching value stream analytics data."
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžãƒ‡ãƒ¼ã‚¿ã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -28329,17 +29162,26 @@ msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®æœŸé–“データをå–得中ã«ã‚¨ãƒ©
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚ reCAPTCHA ã‚’ã‚‚ã†ä¸€åº¦å®Ÿæ–½ã—ã¦ãã ã•ã„。"
+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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
-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 "They can be managed using the %{link}."
-msgstr "%{link}を使用ã—ã¦ãれらを管ç†ã§ãã¾ã™ã€‚"
+msgid "These variables are inherited from the parent group."
+msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
@@ -28351,13 +29193,13 @@ msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "ã“ã® %{issuableDisplayName} ã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚プロジェクトメンãƒãƒ¼ ã ã‘ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚"
msgid "This %{issuableType} is confidential"
-msgstr ""
+msgstr "ã“ã® %{issuableType} ã¯éžå…¬é–‹ã§ã™"
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 ""
+msgstr "ã“ã®%{noteableTypeText} 㯠%{confidentialLinkStart} éžå…¬é–‹ %{linkEnd} ã§ã‚り〠%{lockedLinkStart}ロック%{linkEnd}ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "This %{noteableTypeText} is locked."
msgstr ""
@@ -28368,8 +29210,8 @@ msgstr "%{reason} ã®ãŸã‚ã€ã“ã® %{viewer} ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“ã§ã—ãŸ
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 "ã“ã® GitLab インスタンスã¯ã¾ã å…±æœ‰ Runner ã‚’æä¾›ã—ã¦ã„ã¾ã›ã‚“。インスタンス管ç†è€…ã¯ç®¡ç†è€…エリアã§å…±æœ‰ Runner を登録ã§ãã¾ã™ã€‚"
+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 ""
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr "ã“ã® URL ã¯åˆ¥ã®ãƒªãƒ³ã‚¯ã§æ—¢ã«ä½¿ç”¨ã—ã¦ã„ã¾ã™ã€‚é‡è¤‡ã—㟠URL ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
-msgstr "ã“ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã¯ã€%{strongOpen}ç›´ã¡ã«%{strongClose}ã€ãƒªãƒã‚¸ãƒˆãƒªã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å«ã‚ã¦%{codeOpen}%{project}%{codeClose}ã‚’%{strongOpen}æ’ä¹…çš„ã«å‰Šé™¤ã—ã¾ã™%{strongClose}。"
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠%{link_to_owner} ã«ã‚ˆã£ã¦ä½œæˆã•
msgid "This application will be able to:"
msgstr "ã“ã®ã‚¢ãƒ—リケーションã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™:"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr "ã“ã®ã‚¨ãƒ”ックã«ã¯ã€æ—¢ã«æœ€å¤§æ•°ã®å­ã‚¨ãƒ”ックãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "ã“ã®ã‚¨ãƒ”ックã¯å­˜åœ¨ã—ãªã„ã‹ã€ã‚ãªãŸã«å分ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -28512,14 +29366,17 @@ msgstr ""
msgid "This field is required."
msgstr "ã“ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã¯å¿…é ˆã§ã™ã€‚"
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã¾ã ã‚°ãƒ«ãƒ¼ãƒ— Runner ã‚’æä¾›ã—ã¦ã„ã¾ã›ã‚“。"
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -28540,7 +29397,7 @@ msgid "This is a Premium feature"
msgstr ""
msgid "This is a confidential %{noteableTypeText}."
-msgstr ""
+msgstr "ã“れ㯠%{noteableTypeText} ã®éžå…¬é–‹æƒ…å ±ã§ã™ã€‚"
msgid "This is a delayed job to run in %{remainingTime}"
msgstr "ã“れ㯠%{remainingTime} ã«å®Ÿè¡Œã•ã‚Œã‚‹é…延ジョブã§ã™"
@@ -28548,6 +29405,9 @@ msgstr "ã“れ㯠%{remainingTime} ã«å®Ÿè¡Œã•ã‚Œã‚‹é…延ジョブã§ã™"
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 security log of important events involving your account."
msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«é–¢ã‚ã‚‹é‡è¦ãªã‚¤ãƒ™ãƒ³ãƒˆã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã§ã™ã€‚"
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -28716,8 +29588,8 @@ msgstr ""
msgid "This project"
msgstr "プロジェクト"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‰€å±žã—ã¦ã„ãªã„ãŸã‚ã€ã‚°ãƒ«ãƒ¼ãƒ— Runner を利用ã§ãã¾ã›ã‚“。"
+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 ""
@@ -28773,6 +29645,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "ã“ã® Runner ã¯ä¿è­·ãƒ–ランãƒä¸Šã§èµ·å‹•ã•ã‚ŒãŸãƒ‘イプラインã§ã®ã¿å®Ÿè¡Œã§ãã¾ã™ã€‚"
+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 "ã“ã®è¨­å®šã¯ã€å„プロジェクトã§ä¸Šæ›¸ãã§ãã¾ã™ã€‚"
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr "ã“ã®å¤‰æ•°ã¯ãƒžã‚¹ã‚¯ã§ãã¾ã›ã‚“."
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr "外部ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã—ã¾ã™ã€‚"
@@ -29225,6 +30094,9 @@ msgstr "SSH キーを追加ã™ã‚‹ã«ã¯ã€%{generate_link_start}キーを生æˆã
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 ""
@@ -29240,6 +30112,9 @@ msgstr "SVN リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã¨ãã¯ã€%{svn_link} ã‚’ã”確èªã
msgid "To define internal users, first enable new users set to external"
msgstr "内部ユーザーを定義ã™ã‚‹ãŸã‚ã«ã¯ã€å…ˆã«æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’外部ユーザーã«è¨­å®šã§ãるよã†ã«ã—ã¾ã™ã€‚"
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "アカウントをã•ã‚‰ã«ä¿è­·ã™ã‚‹ãŸã‚ã«ã€%{mfa_link_start}2è¦ç´ èªè¨¼%{mfa_link_end}を設定ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
@@ -29249,6 +30124,9 @@ msgstr "アカウントをã•ã‚‰ã«ä¿è­·ã™ã‚‹ã«ã¯ã€2 è¦ç´ èªè¨¼ã‚’設定ã
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 "ã¯ã˜ã‚ã« FogBugz ã® URL ã¨ãƒ­ã‚°ã‚¤ãƒ³æƒ…報を入力ã—ã¦ãã ã•ã„。次ã®ã‚¹ãƒ†ãƒƒãƒ—ã§ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’マップã—ã¦ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãƒ—ロジェクトをé¸æŠžã—ã¾ã™ã€‚"
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr "ã¯ã˜ã‚ã«ã€Jaeger サーãƒãƒ¼ã«ã“ã®ãƒšãƒ¼ã‚¸ã‚’リンクã™ã‚‹ã‹ã€%{link_start_tag}Jaeger ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«%{link_end_tag}方法を確èªã—ã¾ã™"
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr "Jaeger ã‚’é–‹ãã€GitLab ã‹ã‚‰ç°¡å˜ã«ãƒˆãƒ¬ãƒ¼ã‚·ãƒ³ã‚°ã‚’表示ã™ã‚‹ã«ã¯ã€ %{link} ページをサーãƒãƒ¼ã«ãƒªãƒ³ã‚¯ã—ã¾ã™"
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,8 +30178,8 @@ msgstr "手動ã§è¨­å®šã•ã‚ŒãŸPrometheus サービスã‹ã‚‰ã‚¢ãƒ©ãƒ¼ãƒˆã‚’å—ä
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 Silver%{linkEnd}. You can also remove the project from the dashboard."
-msgstr "ã“ã®ãƒ—ロジェクトã®é‹ç”¨ä¸Šã®è©³ç´°ã‚’確èªã™ã‚‹ã«ã¯ã€ %{linkStart}グループプランをSilverã¸ã‚¢ãƒƒãƒ—グレード%{linkEnd} ã—ã¦ãã ã•ã„。ダッシュボードã‹ã‚‰ãƒ—ロジェクトを削除ã§ãã¾ã™ã€‚"
+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 "ã“ã®ãƒ—ロジェクトã®é‹ç”¨ä¸Šã®è©³ç´°ã‚’確èªã™ã‚‹ã«ã¯ã€ %{groupName} グループã®ã‚ªãƒ¼ãƒŠãƒ¼ã«é€£çµ¡ã‚’ã¨ã£ã¦ãƒ—ランをアップグレードã—ã¦ãã ã•ã„。ダッシュボードã‹ã‚‰ãƒ—ロジェクトを削除ã§ãã¾ã™ã€‚"
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr "ジョブを開始ã™ã‚‹ãŸã‚ã€ã‚°ãƒ«ãƒ¼ãƒ—ã« Runner を追加ã§ãã¾ã™"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr "ジョブを開始ã™ã‚‹ãŸã‚ã€ãƒ—ロジェクトã«ç‰¹å®šã® Runner を追加ã—ã¦ãã ã•ã„。ã¾ãŸã¯å…±æœ‰ Runner を利用ã—ã¦ãã ã•ã„。"
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr "インスタンスレベルã®åˆ†æžã‚’表示ã™ã‚‹ã«ã¯ã€ç®¡ç†è€…ã« %{docLinkStart} 利用状æ³ã®é€ä¿¡ %{docLinkEnd}をオンã«ã™ã‚‹ã‚ˆã†ä¾é ¼ã—ã¦ãã ã•ã„。"
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€äºˆå®šé–‹å§‹æ—¥ã‹äºˆå®šçµ‚了日をã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹å­ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚¨ãƒ”ックã®1ã¤ã«è¿½åŠ ã—ã¦ãã ã•ã„。月表示ã§ã¯ã€å‰æœˆã€å½“月ã€ã‚‚ã—ãã¯5ヶ月先ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
-
msgid "To widen your search, change or remove filters above"
msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ä¸Šã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™"
@@ -29357,6 +30229,9 @@ msgstr "Todo ã‚’ 完了ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
msgid "Today"
msgstr "今日"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr "絵文字リアクションをトグル"
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "案内ã®åˆ‡ã‚Šæ›¿ãˆ"
@@ -29414,6 +30292,9 @@ msgstr ":%{name}: 絵文字リアクションをトグル。"
msgid "Toggles :%{name}: emoji award."
msgstr ":%{name}: 絵文字リアクションをトグル。"
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29475,7 +30356,7 @@ msgid "Total: %{total}"
msgstr "åˆè¨ˆ:%{total}"
msgid "TotalMilestonesIndicator|1000+"
-msgstr ""
+msgstr "1000+"
msgid "TotalRefCountIndicator|1000+"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,8 +30518,8 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr "ミラー更新ã®ãŸã‚ã®ã€ãƒ‘イプライントリガー"
-msgid "Trigger pipelines when branches or tags are updated from 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 "ブランãƒã¾ãŸã¯ã‚¿ã‚°ãŒã‚¢ãƒƒãƒ—ストリームリãƒã‚¸ãƒˆãƒªã‹ã‚‰æ›´æ–°ã•ã‚ŒãŸã¨ãã«ãƒ‘イプラインをトリガã—ã¾ã™ã€‚アップストリームリãƒã‚¸ãƒˆãƒªã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティã«ã‚ˆã£ã¦ã¯ã€ã“ã‚Œã«ã‚ˆã‚ŠCI runnerã®è² è·ãŒå¤§å¹…ã«å¢—加ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚è² è·ã‚’処ç†ã§ãã‚‹ã“ã¨ãŒã‚ã‹ã£ã¦ã„ã‚‹å ´åˆã«ã®ã¿ã€ã“れを有効ã«ã—ã¦ãã ã•ã„。"
+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 "トリガーを除去ã—ã¾ã—ãŸã€‚"
@@ -29658,8 +30545,11 @@ msgstr "トリガーã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Triggerer"
msgstr "トリガー"
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
-msgstr "トリガーã¯ã€ç‰¹å®šã®ãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ã‚’ API 呼ã³å‡ºã—ã§å¼·åˆ¶çš„ã«å†æ§‹ç¯‰ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“れらã®ãƒˆãƒ¼ã‚¯ãƒ³ã¯ã€ãƒ—ロジェクトã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãªã©ã€é–¢é€£ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’å½è£…ã—ã¾ã™ã€‚"
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
msgstr "トレーシングã§ã‚¢ãƒ—リケーションをトラブルシューティングãŠã‚ˆã³ç›£è¦–ã™ã‚‹"
@@ -29845,7 +30735,7 @@ msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "マージリクエストウィジェットをロードã§ãã¾ã›ã‚“。ページをå†èª­ã¿è¾¼ã¿ã—ã¦ãã ã•ã„。"
msgid "Unable to save iteration. Please try again"
-msgstr ""
+msgstr "イテレーションをä¿å­˜ã§ãã¾ã›ã‚“。もã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
msgid "Unable to save your changes. Please try again."
msgstr "変更をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -29874,14 +30764,14 @@ msgstr "ç¾æ™‚点ã§ã¯ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’æ›´æ–°ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“
msgid "Unarchive project"
msgstr "プロジェクトã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–解除"
-msgid "Unarchiving the project will restore people's 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}"
-msgstr "ã“ã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–化ã—ãŸãƒ—ロジェクトを解除ã™ã‚‹ã¨ã€ã“ã®ãƒ—ロジェクトã«å¤‰æ›´ã‚’加ãˆã‚‰ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªã¯ã‚³ãƒŸãƒƒãƒˆã§ãるよã†ã«ãªã‚Šã€ã‚¤ã‚·ãƒ¥ãƒ¼ã€ã‚³ãƒ¡ãƒ³ãƒˆã€ãã®ä»–ã®ã‚¨ãƒ³ãƒ†ã‚£ãƒ†ã‚£ã‚’作æˆã§ãã¾ã™ã€‚ %{strong_start}ã“ã®ãƒ—ロジェクトをアクティブ化ãŒçµ‚ã‚‹ã¨ã€ã“ã®ãƒ—ロジェクトã¯æ¤œç´¢ã¨ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚%{strong_end}"
+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 ""
+msgstr "未割り当ã¦"
msgid "Unauthenticated request rate limit"
msgstr ""
@@ -30076,7 +30966,7 @@ msgid "Update it"
msgstr "æ›´æ–°!"
msgid "Update iteration"
-msgstr ""
+msgstr "イテレーションã®æ›´æ–°"
msgid "Update now"
msgstr "今ã™ãæ›´æ–°"
@@ -30132,8 +31022,8 @@ msgstr ""
msgid "Updating"
msgstr "更新中"
-msgid "Upgrade plan to unlock Canary Deployments feature"
-msgstr "カナリアデプロイ機能を実行ã§ãるよã†ã«ã™ã‚‹ãŸã‚ã«ãƒ—ランをアップグレード"
+msgid "Upgrade offers available!"
+msgstr ""
msgid "Upgrade your plan"
msgstr ""
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr "マージリクエストã®æ©Ÿèƒ½ã‚’強化ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "CSVファイルã®ã‚¢ãƒƒãƒ—ロード"
@@ -30351,12 +31244,18 @@ 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 "%{link_start} スコープã®ãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆ%{link_end} を作æˆã™ã‚‹ã«ã¯ã€ %{code_start}::%{code_end} を使用ã—ã¾ã™ï¼ˆä¾‹ï¼š %{code_start}priority::1%{code_end})。"
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "サービスデスクを使用ã—ã¦ã€GitLab 内ã®ãƒ¡ãƒ¼ãƒ«ã§ãƒ¦ãƒ¼ã‚¶ã¨æŽ¥ç¶šï¼ˆä¾‹ï¼šé¡§å®¢ã‚µãƒãƒ¼ãƒˆï¼‰"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "モãƒã‚¤ãƒ«ãƒ‡ãƒã‚¤ã‚¹ã¾ãŸã¯ã‚³ãƒ³ãƒ”ュータã§ãƒ¯ãƒ³ã‚¿ã‚¤ãƒ ãƒ‘スワードèªè¨¼ã‚’使用ã—ã¦ã€2è¦ç´ èªè¨¼ã‚’有効ã«ã—ã¾ã™ã€‚"
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,8 +31271,11 @@ msgstr "URI ã”ã¨ã«1行使用"
msgid "Use template"
msgstr "テンプレートを使用"
-msgid "Use the following registration token during setup:"
-msgstr "セットアップã®éš›ã«æ¬¡ã®ç™»éŒ²ãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦ãã ã•ã„:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "全体通知設定を利用"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr "ユーザー"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr "次ã®å ´æ‰€ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„るユーザー"
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30712,7 +31608,7 @@ msgid "Value"
msgstr "値"
msgid "Value Stream"
-msgstr ""
+msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ "
msgid "Value Stream Analytics"
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æž"
@@ -30723,11 +31619,8 @@ msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã¯ã€ã‚ãªãŸã®ãƒãƒ¼ãƒ ã®é–‹ç™ºé€Ÿ
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã§ã¯ã€ã‚ãªãŸã®ãƒ—ロジェクトãŒã‚¢ã‚¤ãƒ‡ã‚£ã‚¢ã®æ®µéšŽã‹ã‚‰ãƒ—ロダクション環境ã«ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã‚‹ã¾ã§ã©ã‚Œãらã„時間ãŒã‹ã‹ã£ãŸã‹ä¿¯çž°ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
-msgstr ""
+msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã®ã«å分ãªãƒ‡ãƒ¼ã‚¿ãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "ValueStreamAnalytics|%{days}d"
msgstr "%{days}æ—¥"
@@ -30739,7 +31632,7 @@ msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "イシューã®ä½œæˆã‹ã‚‰ã‚¯ãƒ­ãƒ¼ã‚ºã¾ã§ã®æ™‚é–“ã®ä¸­å¤®å€¤ã€‚"
msgid "ValueStream|The Default Value Stream cannot be deleted"
-msgstr ""
+msgstr "デフォルトãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã¯å‰Šé™¤ã§ãã¾ã›ã‚“"
msgid "Variable"
msgstr ""
@@ -30750,6 +31643,15 @@ 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 "å„種コンテナレジストリã®è¨­å®šã€‚"
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "コミットを表示中"
@@ -31002,7 +31907,7 @@ msgid "Vulnerabilities over time"
msgstr "長期ã«ã‚ãŸã‚‹è„†å¼±æ€§"
msgid "Vulnerability Report"
-msgstr ""
+msgstr "脆弱性レãƒãƒ¼ãƒˆ"
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Webhooks"
@@ -31377,7 +32291,7 @@ msgid "Webhooks|This URL will be triggered by a push to the repository"
msgstr ""
msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
-msgstr ""
+msgstr "ã“ã® URL ã¯ã€éžå…¬é–‹ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒä½œæˆã€æ›´æ–°ã¾ãŸã¯ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸã¨ãã«ãƒˆãƒªã‚¬ãƒ¼ã•ã‚Œã¾ã™"
msgid "Webhooks|This URL will be triggered when a group member is created/updated/removed"
msgstr ""
@@ -31398,7 +32312,7 @@ msgid "Webhooks|This URL will be triggered when someone adds a comment"
msgstr ""
msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
-msgstr ""
+msgstr "ã“ã® URL ã¯ã€éžå…¬é–‹ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¸èª°ã‹ãŒã‚³ãƒ¡ãƒ³ãƒˆã‚’追加ã—ãŸã¨ãã«ãƒˆãƒªã‚¬ãƒ¼ã•ã‚Œã¾ã™"
msgid "Webhooks|This URL will be triggered when the job status changes"
msgstr ""
@@ -31439,12 +32353,12 @@ msgstr "ãŠã‹ãˆã‚Šãªã•ã„。ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯åˆ©ç”¨ã•ã‚Œã¦ã„ãªã‹
msgid "Welcome to GitLab"
msgstr "GitLab ã¸ã‚ˆã†ã“ã"
-msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr "%{name}ã•ã‚“%{br_tag} GitLab ã¸ã‚ˆã†ã“ãï¼"
-
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
msgid "Welcome to the guided GitLab tour"
msgstr ""
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr "有効ã«ã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦ç´„ã«åŒæ„ã•ã‚Œã‚‹ã¾ã§ Gi
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "マージリクエストãŒæ‰¿èªã•ã‚ŒãŸã¨ã"
@@ -31497,6 +32414,9 @@ msgstr[0] "マージリクエストãŒæ‰¿èªã•ã‚ŒãŸã¨ã"
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "日付"
@@ -31720,7 +32640,7 @@ msgid "Won't fix / Accept risk"
msgstr ""
msgid "Work in progress (open and unassigned)"
-msgstr ""
+msgstr "作業中(オープンã‹ã¤æœªå‰²ã‚Šå½“ã¦ï¼‰"
msgid "Work in progress Limit"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "代ã‚ã‚Šã«ã€%{linkStart} blob を見る%{linkEnd} ã“ã¨ãŒã§ãã¾ã™ã€‚"
-
msgid "You can also create a project from the command line."
msgstr "コマンドラインã‹ã‚‰ãƒ—ロジェクトを作æˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
@@ -31881,9 +32798,6 @@ msgstr "以下ã®æ‰‹é †ã«ãã£ã¦ã€ã‚ãªãŸã®ã‚³ãƒ³ãƒ”ューター上ã®æ—¢
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr "パーソナルアクセストークンã®è¨­å®š%{pat_link} ã§æ–°ã—ã„
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ã®å‚加をリクエストã™ã‚‹ã“ã¨ã§ã€ç°¡å˜ã«è²¢çŒ®ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Kubernetes クラスター㫠Runner ã‚’ç°¡å˜ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™ã€‚%{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr "グラフã®åˆ—をクリックã—ã¦ã€ãƒžãƒ¼ã‚¸æ—¥ã§ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã§ãã¾ã™ã€‚"
@@ -31932,6 +32843,9 @@ msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã™ã‚‹ã‹ã€åˆ¥ã®ã‚°ãƒ
msgid "You can invite a new member to %{project_name}."
msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
+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 "ä»–ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’%{project_name} ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr "セキュリティダッシュボードをCSVレãƒãƒ¼ãƒˆã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚"
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "ファイルを編集ã™ã‚‹ã«ã¯ã€ã©ã“ã‹ã®ãƒ–ランãƒã«ã„ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“"
@@ -31983,8 +32897,8 @@ msgstr "対話モードã§ã¯ã€%{use_ours} ボタンã¾ãŸã¯%{use_theirs} ボã
msgid "You can see your chat accounts."
msgstr "ãƒãƒ£ãƒƒãƒˆã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’見るã“ã¨ãŒã§ãã¾ã™"
-msgid "You can set up as many Runners as you need to run your jobs."
-msgstr "ジョブを実行ã™ã‚‹ãŸã‚ã«å¿…è¦ãªæ•°ã®Runnerをセットアップã§ãã¾ã™ã€‚"
+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 "グループã”ã¨ã¾ãŸã¯ãƒ—ロジェクトã”ã¨ã«é€šçŸ¥ãƒ¬ãƒ™ãƒ«ã‚’設定ã§ãã¾ã™ã€‚"
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr "権é™ãŒã‚ã‚Šã¾ã›ã‚“"
@@ -32319,6 +33239,9 @@ msgstr "YouTube"
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 ""
@@ -32355,15 +33278,15 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "GPG éµ (%{count})"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr "ã‚ãªãŸã® GitLab ã®ã‚°ãƒ«ãƒ¼ãƒ—"
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr "Gitlab Goldã®è©¦ç”¨æœŸé–“ã¯30日間続ãã€ãã®å¾Œã¯ç„¡æ–™ã®Gitlabアカウントを継続ã—ã¦ç¶­æŒã§ãã¾ã™ã€‚トライアルを有効ã«ã™ã‚‹ãŸã‚ã«ã¯ã€è¿½åŠ æƒ…報をæä¾›ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-
msgid "Your Groups"
msgstr "所属グループ"
@@ -32517,6 +33440,9 @@ msgstr "ライセンスã®æœ‰åŠ¹æœŸé™:"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "メッセージを入力ã—ã¦ãã ã•ã„。"
@@ -32601,6 +33527,12 @@ msgstr "Zoom ミーティングを削除ã—ã¾ã—ãŸ"
msgid "[No reason]"
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 "削除ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
@@ -32642,7 +33574,7 @@ msgid "among other things"
msgstr "ãã®ä»–ã®ã‚‚ã®"
msgid "and"
-msgstr ""
+msgstr "ã¨"
msgid "any-approver for the merge request already exists"
msgstr "マージリクエストã®æ‰¿èªè€…ã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™"
@@ -32686,9 +33618,15 @@ msgstr "ブランãƒå"
msgid "by"
msgstr "by"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] "æ—¥"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr "デフォルトブランãƒ"
@@ -33037,11 +33978,12 @@ msgstr "例 %{token}"
msgid "element is not a hierarchy"
msgstr "è¦ç´ ã¯éšŽå±¤ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
-msgstr ""
+msgstr "メール '%{email}'ã¯æ¤œè¨¼æ¸ˆã¿ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "enabled"
msgstr "有効"
@@ -33129,6 +34071,9 @@ msgstr "グループ"
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr "グループ"
@@ -33221,7 +34166,7 @@ msgid "is not allowed. Try again with a different email address, or contact your
msgstr "ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。別ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã‚‚ã†ä¸€åº¦è©¦ã™ã‹ã€GitLab管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
+msgstr "ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。ç¾åœ¨ã€ãƒ—ロジェクトレベルã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "is not an email you own"
msgstr "ã‚ãªãŸãŒæ‰€æœ‰ã™ã‚‹ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -33371,6 +34316,12 @@ msgstr "ブランãƒã‚’復元ã™ã‚‹ã‹ã€åˆ¥ã® %{missingBranchName} ブランãƒ
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr "%{link_start}競åˆã®è§£æ±ºã®è©³ç´°%{link_end}"
+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 "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㌠%{memoryFrom} MBã‹ã‚‰ %{memoryTo} MB㸠%{emphasisStart} 減少 %{emphasisEnd}"
@@ -33497,9 +34448,6 @@ msgstr "マージ"
msgid "mrWidget|Merge failed."
msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸ: %{mergeError}ã€ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-
msgid "mrWidget|Merge locally"
msgstr "ローカルã§ãƒžãƒ¼ã‚¸"
@@ -33569,8 +34517,8 @@ msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
msgid "mrWidget|The changes will be merged into"
msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "ソースブランãƒã® HEAD ãŒæœ€è¿‘変更ã•ã‚Œã¾ã—ãŸã€‚ページをå†èª­ã¿è¾¼ã¿ã—ã¦ãƒžãƒ¼ã‚¸å‰ã«å¤‰æ›´ã‚’確èªã—ã¦ãã ã•ã„"
@@ -33650,6 +34598,9 @@ msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã‚’開始ã™ã‚‹"
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33729,7 +34680,7 @@ msgid "open issue"
msgstr ""
msgid "opened %{timeAgoString} by %{email} via %{user}"
-msgstr ""
+msgstr "%{user}ãŒ%{email}ã§%{timeAgoString}ã«ã‚ªãƒ¼ãƒ—ン"
msgid "opened %{timeAgoString} by %{user}"
msgstr "%{user} ㌠%{timeAgoString} を開始ã—ã¾ã—ãŸã€‚"
@@ -33738,7 +34689,7 @@ msgid "opened %{timeAgoString} by %{user} in Jira"
msgstr ""
msgid "opened %{timeAgo}"
-msgstr ""
+msgstr "%{timeAgo}ã«ã‚ªãƒ¼ãƒ—ン"
msgid "or"
msgstr "ã¾ãŸã¯"
@@ -33868,6 +34819,9 @@ msgstr "リセットã—ã¾ã™ã€‚"
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr "リストã¸"
msgid "toggle collapse"
msgstr "表示・éžè¡¨ç¤ºåˆ‡ã‚Šæ›¿ãˆ"
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "トリガーã•ã‚ŒãŸ"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 11be5548778..51b3004ac82 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ka\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:58\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index 77e0bc12602..a2e8d36a964 100644
--- a/locale/kab/gitlab.po
+++ b/locale/kab/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: kab\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:04\n"
+"PO-Revision-Date: 2021-02-01 18:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 379a7448e56..203a0aab9bf 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:01\n"
+"PO-Revision-Date: 2021-02-01 17:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%dê±´ì˜ í…ŒìŠ¤íŠ¸ 결과를 고쳤습니다."
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "그룹 %dê°œ ì„ íƒë¨"
@@ -318,10 +322,10 @@ msgstr "%{authorsName} ì˜ ìŠ¤ë ˆë“œ"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{webhooks_link_start}%{webhook_type}%{link_end}ì„ ì‚¬ìš©í•˜ë©´ 그룹 ë˜ëŠ” 프로ì íŠ¸ì˜ ì´ë²¤íŠ¸ì— 대한 ì‘답으로 웹 애플리케ì´ì…˜ì— ì•Œë¦¼ì„ ë³´ë‚¼ 수 있습니다. Webhook보다 %{integrations_link_start}통합%{link_end}ì„ ì‚¬ìš©í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
+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 "&lt; 1 hour"
msgstr ""
@@ -958,15 +968,15 @@ msgstr "+%{tags}개"
msgid ", or "
msgstr ", ë˜ëŠ” "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- ì´ë²¤íŠ¸"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Runner ê°€ 활성화ë˜ì—ˆê³ , 새로운 ìž‘ì—…ì„ ì²˜ë¦¬í•  수 있습니다."
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner ê°€ ì¼ì‹œì •ì§€ ë˜ì–´ 새로운 ìž‘ì—…ì„ ë°›ì„ ìˆ˜ 없습니다."
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1155,6 +1165,9 @@ msgstr "빈 프로ì íŠ¸ì—서는 기본 브랜치를 ì„ íƒí•  수 없습니다
msgid "A deleted user"
msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "파ì¼ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -1173,6 +1186,12 @@ msgstr "ê·¸ë£¹ì€ ì—¬ëŸ¬ 프로ì íŠ¸ë“¤ì˜ 모ìŒìž…니다."
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
msgstr "ê·¸ë£¹ì€ GitLabì˜ ì¡°ì§ì„ 나타냅니다. ê·¸ë£¹ì„ ì‚¬ìš©í•˜ë©´ 사용ìžë¥¼ 관리하고, ì—¬ëŸ¬ê°œì˜ í”„ë¡œì íŠ¸ì—ì„œ ê³µë™ìœ¼ë¡œ ìž‘ì—…í•  수 있습니다."
+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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "프로ì íŠ¸ëŠ” 파ì¼ì„ 저장하고 (저장소), ìž‘ì—… 계íšì„ 세우며 (ì´ìŠˆ), 문서를 게시하는 ê³³ (위키) 입니다, %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr "ê´€ë¦¬ìž ì‚¬ì´ë“œ ë°”ì˜ ëª¨ë‹ˆí„°ë§ ì„¹ì…˜ì— Grafana ë²„íŠ¼ì„ ì¶”ê
msgid "Add a To Do"
msgstr "í• ì¼ ì¶”ê°€"
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr "ì´ %{noteableDisplayName} ì— ì¼ë°˜ì ì¸ 코멘트를 추가 합니다."
@@ -1789,6 +1811,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "관리 노트"
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr "ì´ ì‚¬ìš©ìž"
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "ì‚¬ìš©ìž í†µê³„"
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr "Auto DevOps ë„ë©”ì¸"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "새 프로ì íŠ¸ì— 공유 러너 활성화"
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "LDAP ì°¨ë‹¨ëœ ì‚¬ìš©ìžì˜ ì°¨ë‹¨ì„ í•´ì œí•  수 없습니다."
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "비활성화"
@@ -2119,6 +2153,9 @@ msgstr "ì‚¬ìš©ìž ì‚­ì œ"
msgid "AdminUsers|Delete user and contributions"
msgstr "사용ìžì™€ 기여 ì‚­ì œ"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "외부"
@@ -2227,6 +2264,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,7 +2694,7 @@ msgstr ""
msgid "Alerts"
msgstr "알림"
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2795,8 +2835,8 @@ 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 public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Asciidoc 문서ì—ì„œ PlantUML 다ì´ì–´ê·¸ëž¨ ë Œë”ë§ì„ 허용합니다."
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "실패 허용ë¨"
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3140,6 +3189,9 @@ msgstr "파ì¼ì„ 불러오는 ë„중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "머지 ë¦¬í€˜ìŠ¤íŠ¸ì˜ ë³€ê²½ ì‚¬í•­ì„ ë¶ˆëŸ¬ì˜¤ëŠ” ë„중 오류가 ë°œìƒ í•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "ìµëª…"
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr "제안 ì ìš©"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,7 +3640,7 @@ 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}"
+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?"
@@ -3679,15 +3728,18 @@ msgstr "ì •ë§ë¡œ 해당 í•­ëª©ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 "헬스 ì²´í¬ í† í°ì„ 초기화 하시겠습니까?"
+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 ""
@@ -3757,8 +3809,8 @@ msgstr ""
msgid "Ascending"
msgstr "오름차순"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "그룹 관리ìžì—게 그룹 Runner 를 설정하ë„ë¡ ìš”ì²­í•˜ì„¸ìš”"
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "문제 알림 ì†Œë¹„ìž ì„œë¹„ìŠ¤ URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "#FF0000ê³¼ ê°™ì´ ë§žì¶¤ ìƒ‰ìƒ ì§€ì •"
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr "ë¼ë²¨ 지정"
@@ -4032,9 +4081,6 @@ msgstr "%{link_to_client} ì„ ë‚´ 계정으로 ì¸ì¦í•˜ì‹œê² ì–´ìš”?"
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,8 +4105,8 @@ msgstr "ìžë™ DevOps, Runner ìž‘ì—… artifacts"
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "사용ë˜ì§€ 않거나 ë³´ë¥˜ì¤‘ì¸ íŒŒì´í”„ ë¼ì¸ì˜ ìžë™ 취소"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4158,17 +4204,17 @@ msgstr "ì´ìš© 가능"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "사용 가능한 그룹 러너: %{runners}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "사용 가능한 공유 러너:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "사용 가능한 지정 러너"
@@ -4308,26 +4354,26 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr "ì„ íƒí•œ 커밋으로 시작"
-msgid "Below are examples of regex for existing tools:"
-msgstr "다ìŒì€ 기존 ë„êµ¬ì— ëŒ€í•œ ì •ê·œì‹ì˜ 예입니다."
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "결제"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name}(ì€)는 %{plan_name} í”Œëžœì„ ì‚¬ìš©í•˜ê³  있습니다."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "@%{user_name}ë‹˜ì€ í˜„ìž¬ %{plan_name} í”Œëžœì„ ì‚¬ìš©í•˜ê³  있습니다."
@@ -4335,11 +4381,17 @@ msgstr "@%{user_name}ë‹˜ì€ í˜„ìž¬ %{plan_name} í”Œëžœì„ ì‚¬ìš©í•˜ê³  있습니
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 "요금제를 다운그레ì´ë“œí•˜ë ¤ë©´ %{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 Gold."
-msgstr "%{faq_link}ì„ ì½ìŒìœ¼ë¡œì¨ í”Œëžœì— ëŒ€í•´ ë” ìžì„¸ížˆ 알아보거나 GitLab.com Gold 무료 30 ì¼ í‰ê°€íŒì„ 시작하세요."
+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 "%{pricing_page_link}ì—ì„œ ê° ìš”ê¸ˆì œì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
@@ -4359,6 +4411,9 @@ msgstr "ì´ ê·¸ë£¹ì€ ìƒìœ„ ê·¸ë£¹ì˜ í”Œëžœê³¼ ì—°ê²°ë©ë‹ˆë‹¤."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "ì´ ê·¸ë£¹ì˜ í”Œëžœì„ ê´€ë¦¬í•˜ë ¤ë©´ %{parent_billing_page_link}ì˜ ê²°ì œ ì„¹ì…˜ì„ ë°©ë¬¸í•˜ì„¸ìš”."
+msgid "BillingPlans|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 ""
@@ -4368,6 +4423,9 @@ msgstr "ë‚´ GitLab.com ì²´í—˜íŒì´ %{expiration_date}ì— ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤.
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "매년 %{price_per_year} 청구"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "ìžì£¼ 묻는 질문"
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "업그레ì´ë“œ"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "접기"
@@ -4690,6 +4754,9 @@ msgstr "프로ì íŠ¸ 설정"
msgid "Branches|protected"
msgstr "보호ë¨"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr "내장ëœ"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ msgstr ""
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 ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "작성ìž"
@@ -4834,6 +4916,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD 구성"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "외부 저장소용 CI/CD"
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Canary Deployments는 ì¸ê¸°ìžˆëŠ” CI 전략으로, ë°°í¬í™˜ê²½ì˜ ì¼ë¶€ê°€ 새 ë²„ì „ì˜ ì‘ìš© 프로그램으로 ìš°ì„  ì—…ë°ì´íŠ¸ ë©ë‹ˆë‹¤."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr "경로 변경"
msgid "Change permissions"
msgstr "권한 변경"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Revert"
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "%{docs_link_start} 여기부터 %{docs_link_end} 여기까지 확ì¸."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr "아무 색ìƒì„ ì„ íƒí•´ 주세요."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "íŒŒì¼ ì„ íƒâ€¦"
@@ -5497,6 +5591,9 @@ 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 "Ci/CD 파ì´í”„ë¼ì¸ì´ ì—°ê²°ë˜ê³  실행할 저장소를 ì„ íƒí•´ 주세요."
@@ -5656,12 +5753,24 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "사용할 수 없습니다: %{reason}"
+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 "지우기"
@@ -5704,8 +5813,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Kubernetes 페ì´ì§€ë¡œ ì´ë™í•˜ì—¬ 설치 프로세스를 시작하려면 아래 ë²„íŠ¼ì„ í´ë¦­í•˜ì‹­ì‹œì˜¤."
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "í´ë¦­í•˜ì—¬ 확장하십시오."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "코드 ì†Œìœ ìž | 패턴"
-msgid "Cohorts"
-msgstr "Cohorts"
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "사ì´ë“œ ë°” 축소"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "업그레ì´ë“œ 위해 ì˜ì—…íŒ€ì— ë¬¸ì˜"
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ í† í° ë§Œë“¤ê¸°"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "ìƒì„±ë¨"
@@ -8316,12 +8485,12 @@ msgstr ""
msgid "Current Branch"
msgstr "현재 브랜치"
-msgid "Current Plan"
-msgstr ""
-
msgid "Current Project"
msgstr "현재 프로잭트"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "현재 노드"
@@ -8346,7 +8515,7 @@ msgstr "프로파ì¼"
msgid "CurrentUser|Settings"
msgstr "설정"
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,8 +8596,8 @@ msgstr "언어 ë° ì§€ì—­ 관련 ì„¤ì •ì„ ë³€ê²½í•©ë‹ˆë‹¤."
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "파ì´í”„ë¼ì¸ ì„¤ì •ì„ ë³€ê²½í•˜ê³ , ë‚˜ì˜ íŒŒì´í”„ë¼ì¸ìƒíƒœì™€ ì ìš© 범위 보고서를 보세요."
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
@@ -8641,7 +8807,7 @@ msgstr "대시 보드 |%{firstProject} 과 %{secondProject}"
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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,8 +10112,8 @@ msgstr "사용 안 함"
msgid "Disable for this project"
msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 사용 중지"
-msgid "Disable group Runners"
-msgstr "그룹 Runner 사용 중지"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
@@ -10184,9 +10404,6 @@ msgstr "ì´ ê³¼ì •ì—ì„œ GitLabì˜ URLì„ ë¬»ëŠ” 메시지가 나타납니다. ì
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr "ê° Runner는 ë‹¤ìŒ ìƒíƒœ 중 í•˜ë‚˜ì¼ ìˆ˜ 있습니다."
-
msgid "Edit"
msgstr "편집"
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr "HTML ì´ë©”ì¼ í™œì„±í™”"
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Pseudonymizer ë°ì´í„° 수집 사용"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,8 +10761,8 @@ msgstr ""
msgid "Enable for this project"
msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 사용"
-msgid "Enable group Runners"
-msgstr "그룹 Runner 사용"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr "ë©”ì¼ ë¨¸ë¦¬ë§ ë° ê¼¬ë¦¬ë§ ì‚¬ìš©"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "(UTC)ì— ì¢…ë£Œë©ë‹ˆë‹¤"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
msgstr ""
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "환경 변수가 기본으로 %{link_start}보호ë˜ë„ë¡%{link_end} 관리ìžì— ì˜í•´ 구성ë˜ì—ˆìŠµë‹ˆë‹¤."
-
-msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr "외부 분류 ì •ì±… ì¸ì¦"
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,8 +12769,8 @@ msgstr "ì´ìŠˆ ìƒì„±ì—ì„œ 프로ë•ì…˜ ë°°í¬ê¹Œì§€"
msgid "From merge request merge until deploy to production"
msgstr "머지 리퀘스트(MR) 머지ì—ì„œ 프로ë•ì…˜ í™˜ê²½ì— ë°°í¬ê¹Œì§€"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 세부사항 ë³´ê¸°ì˜ ì• í”Œë¦¬ì¼€ì´ì…˜ 목ë¡ì—ì„œ Runner를 설치하십시오."
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr ""
@@ -12564,6 +12817,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Geo 노드"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,8 +13234,8 @@ msgstr "Git 리비전"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
-msgstr "파ì´í”„ ë¼ì¸ì— 대한 Git ì „ëžµ"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "GitLab Group RunnersëŠ”ì´ ê·¸ë£¹ì˜ ëª¨ë“  프로ì íŠ¸ì— 대한 코드를 실행할 수 있습니다."
-
msgid "GitLab Import"
msgstr "GitLab 가져오기"
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "그룹 CI/CD 설정"
-
msgid "Group Git LFS status:"
msgstr "그룹 Git LFS ìƒíƒœ:"
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr "그룹 Runner"
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr "그룹 관리ìžëŠ” grouo runners를 여기서 ë“±ë¡ í•  수 있습니ë
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr "그룹명"
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr "그룹 개요"
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr "정리가 성공ì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "정리, 내보내기, 경로, 전송, 삭제, 보관"
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr "ID"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "ë¹„í™œì„±í™”ëœ ê²½ìš°, ì ‘ê·¼ ê¶Œí•œì€ í”„ë¡œì íŠ¸ì— 대한 ì‚¬ìš©ìž ê¶Œí•œì— ë”°ë¼ ë‹¬ë¼ì§‘니다."
-
-msgid "If enabled"
-msgstr "만약 활성화 ëœ ê²½ìš°"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,8 +15495,8 @@ msgstr "ì¸ë¼ì¸"
msgid "Input host keys manually"
msgstr "호스트 키를 수ë™ìœ¼ë¡œ ìž…ë ¥"
-msgid "Input your repository URL"
-msgstr "저장소 URLì„ ìž…ë ¥ 하세요"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr ""
@@ -14897,11 +15537,11 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
-msgstr "GitLab Runner 설치"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Kubernetesì— Runner 설치"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
@@ -14925,9 +15565,21 @@ msgstr[0] "ì¸ìŠ¤í„´ìŠ¤"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr "그룹 초대"
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr "ì´ìŠˆëŠ” 버그, ìž‘ì—… í˜¹ì€ ë…¼ì˜í•  ì•„ì´ë””ì–´ì¼ ìˆ˜ 있습니ë
msgid "Issues closed"
msgstr "ì´ìŠˆ 닫힘"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "JiraService | 비밀번호 ë˜ëŠ” API 토í°"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ msgstr ""
msgid "Jobs"
msgstr "Jobs"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,8 +16615,8 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr "ìž‘ì—…ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤"
-msgid "Job|Job has been erased by"
-msgstr "ìž‘ì—…|ìž‘ì—…ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤. by"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "유지"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,8 +16907,8 @@ msgstr "마지막 연결"
msgid "Last edited %{date}"
msgstr "%{date}ì— ë§ˆì§€ë§‰ 편집ë¨"
-msgid "Last edited by %{name}"
-msgstr "%{name}가 마지막으로 편집함"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr "Kubernetesì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] "최대 %d ì´ë²¤íŠ¸ 만 표시하는 것으로 제한ë©ë‹ˆë‹¤."
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr "최대 작업 시간 초과"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr "5ì›”"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr "회ì›"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "MergeRequests | 답장 ..."
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "머지ë¨"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr "분"
msgid "Mirror direction"
msgstr "미러 방향"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "미러 저장소"
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "취소"
-
msgid "Modal|Close"
msgstr "닫기"
@@ -18319,9 +19046,6 @@ msgstr "ì´ë¦„"
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "새 ë¼ë²¨ ì´ë¦„ 지정"
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,8 +19505,8 @@ msgstr ""
msgid "New password"
msgstr "새 비밀번호"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "새로운 파ì´í”„ ë¼ì¸ì€ ë™ì¼í•œ ë¸Œëžœì¹˜ì— ìžˆëŠ” ì´ì „ì˜ ëŒ€ê¸° ì¤‘ì¸ íŒŒì´í”„ ë¼ì¸ì„ 취소 합니다."
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "새 프로ì íŠ¸"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Gitaly Serverì— ì—°ê²°í•  수 없습니다. 로그를 확ì¸í•˜ì‹­ì‹œì˜¤!"
@@ -18988,6 +19718,9 @@ msgstr "ì¼ì¹˜í•˜ëŠ” 결과가 없습니다."
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr "템플릿 ì—†ìŒ"
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr "옵션 "
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "기타 ë¼ë²¨"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "다른 정보"
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr "파ì´í”„ë¼ì¸ 스케쥴"
msgid "Pipeline Schedules"
msgstr "파ì´í”„ë¼ì¸ 스케쥴"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 "파ì´í”„ë¼ì¸ 트리거"
@@ -20573,9 +21333,6 @@ msgstr "파ì´í”„ë¼ì¸ 로딩중"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "프로ì íŠ¸ ìºì‹œê°€ 성공ì ìœ¼ë¡œ 재설정ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "현재 ì‹¤í–‰ì¤‘ì¸ íŒŒì´í”„ë¼ì¸ì´ 없습니다."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr "파ì´í”„ë¼ì¸ 실행"
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr "피드 토í°ì´ 성공ì ìœ¼ë¡œ 초기화ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Profiles|Full name"
msgstr "ì´ë¦„"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "ë‚´ í”„ë¡œí•„ì— ë¹„ë°€ 기여 í¬í•¨"
@@ -21446,9 +22209,6 @@ msgstr "ì¡°ì§"
msgid "Profiles|Path"
msgstr "경로"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "새 아바타 위치 ë° í¬ê¸° ì¡°ì ˆ"
@@ -21731,6 +22491,9 @@ msgstr "프로ì íŠ¸ ì´ë¦„"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr "환경"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "보호"
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr "실시간 기능"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "관련 ë°°í¬ ëœ ìž‘ì—…"
-
msgid "Related Issues"
msgstr "관련 ì´ìŠˆ"
-msgid "Related Jobs"
-msgstr "관련 Jobs"
-
-msgid "Related Merge Requests"
-msgstr "관련 머지 리퀘스트(MR)"
-
-msgid "Related Merged Requests"
-msgstr "관련 머지 리퀘스트(MR)"
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr "삭제"
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr "Runner 제거"
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr "ì €ìž¥ì†Œì˜ ì €ìž¥ê³µê°„"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,8 +24641,8 @@ msgstr "헬스 ì²´í¬ ì ‘ê·¼ í† í° ì´ˆê¸°í™”"
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
-msgstr "runner ë“±ë¡ í† í° ì´ˆê¸°í™”"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr ""
@@ -23985,6 +24764,9 @@ msgstr "재시ë„"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "ì´ ìž‘ì—… 재시ë„"
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "태그없는 작업 실행"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr "Runners"
-msgid "Runners API"
-msgstr "Runners API"
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr "Runners 페ì´ì§€."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr "SSH 공개키"
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr "비밀"
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "보안"
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,8 +25852,8 @@ msgstr "시간대 ì„ íƒ"
msgid "Select all"
msgstr "ëª¨ë‘ ì„ íƒ"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "기존 Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ ì„ íƒí•˜ê±°ë‚˜ 새로 만듭니다."
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr ""
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ ì„ íƒ"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr "CI/CD 설정"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr "새 비밀번호 설정"
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-msgstr "휴대í°ì„ 분실하거나 ì¼íšŒìš© ë¹„ë°€ë²ˆí˜¸ì— ì ‘ê·¼í•˜ì§€ 못하는 경우 ë‹¤ìŒ ë³µêµ¬ 코드를 한번씩 사용하여 ë‚´ ê³„ì •ì— ë‹¤ì‹œ 접근할 수 있습니다. 복구 코드를 안전한 ê³³ì— ë³´ê´€í•´ì£¼ì„¸ìš”. 그렇지 않으면 ê³„ì •ì— ì ‘ê·¼í•  수 %{b_start}없게%{b_end} ë©ë‹ˆë‹¤."
-
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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr "최신 버전 보기"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr "스마트카드"
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr "스팸 ë° ì•ˆí‹°ë´‡ 보호"
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Runner 설정 중 ë‹¤ìŒ URLì„ ì§€ì •í•˜ì„¸ìš”."
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr "스테ì´ì§€"
-msgid "Stage & Commit"
-msgstr "스테ì´ì§• & 커밋"
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr "웹 í„°ë¯¸ë„ ì‹œìž‘"
msgid "Start a %{new_merge_request} with these changes"
msgstr "ì´ ë³€ê²½ 사항으로 %{new_merge_request} ì„ ì‹œìž‘í•˜ì‹­ì‹œì˜¤."
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr "Runner 시작!"
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "(UTC)ì— ì‹œìž‘"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr "í¬í¬ 관계가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "개발 ìˆ˜ëª…ì£¼ê¸°ì˜ ë‹¨ê³„."
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Review 단계ì—서는 머지 리퀘스트(MR)를 작성한 후 ë¨¸ì§€í•˜ê¸°ê¹Œì§€ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ëŠ” 첫 번째 머지 리퀘스트(MR)ì„ ë¨¸ì§€ í•œ í›„ì— ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,17 +29162,26 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
-msgstr "%{link}를 사용하여 관리 할 수 ​​있습니다."
+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 "Third Party Advisory Link"
msgstr ""
@@ -28368,8 +29210,8 @@ 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 "ì´ GitLab ì¸ìŠ¤í„´ìŠ¤ëŠ” 공유 Runnersê°€ 제공ë˜ì§€ 않습니다. ì¸ìŠ¤í„´ìŠ¤ 관리ìžëŠ” 관리 ì˜ì—­ì— 공유 Runners를 ë“±ë¡ í•  수 있습니다."
+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 ""
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr "ì´ ì‘ìš© í”„ë¡œê·¸ëž¨ì€ ë‹¤ìŒì„ 수행 í•  수 있습니다."
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,14 +29366,17 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "ì´ ê·¸ë£¹"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "ì´ ê·¸ë£¹ì€ ì•„ì§ ê·¸ë£¹ Runners를 제공하지 않습니다."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "즉, 빈 저장소를 만들거나 기존 저장소를 가져올 때까지 코드를 Push 할 수 없습니다."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 "ì´ ë¨¸ì§€ 리퀘스트(MR)는 잠겨있습니다."
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr "ì´ í”„ë¡œì íŠ¸"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr "SVN ì €ìž¥ì†Œì— ì—°ê²°í•˜ë ¤ë©´ %{svn_link}ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤."
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr "í•  ì¼ í•­ëª©ì´ ì„±ê³µì ìœ¼ë¡œ 완료로 표시ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Today"
msgstr "오늘"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "토글 네비게ì´ì…˜"
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr "ì—…ë°ì´íŠ¸ì¤‘..."
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "CSV íŒŒì¼ ì—…ë¡œë“œ"
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "휴대 기기 ë˜ëŠ” 컴퓨터ì—ì„œ ì¼íšŒìš© 비밀번호 ì¸ì¦ê¸°ë¥¼ 사용하여 ì´ì¤‘ ì¸ì¦(2FA)를 활성화하세요."
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,8 +31271,11 @@ msgstr ""
msgid "Use template"
msgstr "템플릿 사용"
-msgid "Use the following registration token during setup:"
-msgstr "설정 ì¤‘ì— ë‹¤ìŒ ë“±ë¡ í† í° ì´ìš© : "
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "전체 알림 설정 사용"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr "사용ìžë“¤"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 "여러가지 컨테ì´ë„ˆ 레지스트리 설정."
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr "사용 설정ë˜ë©´ 사용ìžëŠ” GitLab ì•½ê´€ì´ ìˆ˜ë½ ë  ë•Œê¹Œì§€ G
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "ì´ ë¨¸ì§€ 리퀘스트(MR)ê°€ 승ì¸ëì„ ë•Œ"
@@ -31497,6 +32414,9 @@ msgstr[0] "ì´ ë¨¸ì§€ 리퀘스트(MR)ê°€ 승ì¸ëì„ ë•Œ"
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr "ëª…ë ¹ì¤„ì„ í†µí•´ 프로ì íŠ¸ë¥¼ ìƒì„±í•  수 있습니다."
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì— Runner를 쉽게 설치할 수 있습니다. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "ë¸Œëžœì¹˜ì— ìžˆì„ ë•Œë§Œ 파ì¼ì„ 편집할 수 있습니다."
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr "ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
@@ -32319,6 +33239,9 @@ msgstr "YouTube"
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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 "ì‚­ì œëœ ì‚¬ìš©ìž"
@@ -32686,9 +33618,15 @@ msgstr "브랜치 ì´ë¦„"
msgid "by"
msgstr "by"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] "ì¼"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr "브랜치를 ë³µì›í•˜ê±°ë‚˜ 다른 %{missingBranchName} 브랜치를 ì‚
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{memoryTo}MB ë¡œ %{emphasisStart} ê°ì†Œí•˜ì˜€ìŠµë‹ˆë‹¤. %{emphasisEnd}"
@@ -33497,9 +34448,6 @@ msgstr "머지"
msgid "mrWidget|Merge failed."
msgstr "머지 실패."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr "로컬ì—ì„œ 머지"
@@ -33569,7 +34517,7 @@ msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì§€ 않았습니다."
msgid "mrWidget|The changes will be merged into"
msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë  ê²ƒ 입니다."
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr "파ì´í”„ë¼ì¸ì´ 성공하면 ìžë™ìœ¼ë¡œ 머지ë©ë‹ˆë‹¤."
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr "목ë¡ìœ¼ë¡œ ì´ë™"
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 56576c7a63f..f5bffb862bd 100644
--- a/locale/ku_TR/gitlab.po
+++ b/locale/ku_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ku\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:02\n"
+"PO-Revision-Date: 2021-02-01 17:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index ef263bb395c..3020745be9f 100644
--- a/locale/ky_KG/gitlab.po
+++ b/locale/ky_KG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ky\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:56\n"
+"PO-Revision-Date: 2021-02-01 17:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 508d8b48530..d4fd206a7a9 100644
--- a/locale/lt_LT/gitlab.po
+++ b/locale/lt_LT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: lt\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:02\n"
+"PO-Revision-Date: 2021-02-01 17:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,6 +252,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -486,10 +493,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1183,6 +1196,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1190,10 +1206,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1431,6 +1444,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1801,15 +1826,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2068,6 +2093,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2098,9 +2126,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2167,7 +2195,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2398,6 +2435,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2506,6 +2546,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2936,7 +2979,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3422,6 +3474,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3593,6 +3648,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3707,12 +3765,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,7 +3937,7 @@ 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}"
+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?"
@@ -3976,15 +4028,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4054,7 +4109,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4335,9 +4387,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4362,7 +4411,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4461,16 +4510,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4611,25 +4660,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4638,10 +4687,16 @@ 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 Gold."
+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}."
@@ -4662,6 +4717,9 @@ 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 ""
@@ -4671,6 +4729,9 @@ 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 ""
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4996,6 +5063,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -5095,6 +5174,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5140,6 +5225,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5782,9 +5882,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ 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 ""
@@ -6010,7 +6122,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8463,12 +8614,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8637,10 +8809,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8667,7 +8839,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,7 +10457,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,7 +11109,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ 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 ""
@@ -11393,6 +11634,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12864,7 +13120,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13326,7 +13585,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,10 +15903,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15642,6 +16321,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,7 +16984,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16335,6 +17059,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,7 +17279,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 ""
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17477,9 +18213,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18715,9 +19445,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,7 +19913,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20813,6 +21573,9 @@ 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 ""
@@ -20981,9 +21744,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21854,9 +22620,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22139,6 +22902,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23493,12 +24271,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,7 +25076,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24414,6 +25199,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24463,6 +25251,9 @@ 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 ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24725,6 +25540,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,7 +26329,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,7 +27717,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26986,7 +27798,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27031,7 +27840,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27244,6 +28053,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28350,7 +29183,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28416,6 +29249,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,7 +29708,7 @@ 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."
+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."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29004,13 +29864,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29040,6 +29903,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 ""
@@ -29208,7 +30086,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ 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 ""
@@ -29738,6 +30616,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,7 +30682,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,7 +31271,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30633,7 +31529,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,7 +31778,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31946,10 +32866,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32391,9 +33314,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ 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 ""
@@ -32865,13 +33794,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34031,9 +34991,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34103,7 +35060,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34184,6 +35141,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index 6510d36520f..75a0602686c 100644
--- a/locale/mk_MK/gitlab.po
+++ b/locale/mk_MK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:02\n"
+"PO-Revision-Date: 2021-02-01 17:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index ed1b52c323a..e27d59bb59c 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:02\n"
+"PO-Revision-Date: 2021-02-01 18:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index b81c8de9968..38a7d3755bf 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:10\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d fikset testresultat"
msgstr[1] "%d fiksede testresultater"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d gruppe valgt"
@@ -374,11 +379,11 @@ msgstr "%{authorsName} sin tråd"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
-msgstr "%{code_open}Beskyttede%{code_close} variabler eksponeres bare for beskyttede grener eller etiketter."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
+msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} forfattet %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} lar deg sende varsler t
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 "%{webhooks_link_start}%{webhook_type}%{link_end} lar deg sende varsler til nettapplikasjoner som svar på hendelser i en gruppe eller et prosjekt. Vi anbefaler at du bruker en %{integrations_link_start}integrasjon%{link_end} som det foretrukne fremfor en webhook."
+msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
+msgstr ""
+
msgid "&lt; 1 hour"
msgstr "&lt; 1 time"
@@ -1033,17 +1044,17 @@ msgstr "+%{tags} til"
msgid ", or "
msgstr ", eller "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- Hendelse"
msgstr[1] "- Hendelser"
-msgid "- Runner is active and can process any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner er satt på pause og vil ikke motta nye jobber"
-
msgid "- User"
msgid_plural "- Users"
msgstr[0] "- Bruker"
@@ -1247,6 +1258,9 @@ msgstr "En standardgren kan ikke velges for et tomt prosjekt."
msgid "A deleted user"
msgstr "En slettet bruker"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "En fil har blitt endret."
@@ -1265,6 +1279,12 @@ msgstr "En gruppe er en samling av flere prosjekter"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
msgstr "En gruppe representerer organisasjonen din i GitLab. Grupper lar deg administrere brukere og samarbeide på tvers av flere prosjekter."
+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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,8 +1357,8 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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 "Et abonnement vil trigge en ny rørledning på standardgrenen til dette prosjektet, når en rørledning blir vellykket fullført for en ny etikett på %{default_branch_docs} av det abonnerte prosjektet."
+msgid "A title is required"
+msgstr ""
msgid "A user can only participate in a rotation once"
msgstr ""
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "API-hjelp"
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr "Legg til et gjøremål"
-msgid "Add a To-Do"
-msgstr "Legg til et gjøremål"
-
msgid "Add a bullet list"
msgstr "Legg til en punktliste"
msgid "Add a comment to this line"
msgstr "Legg til en kommentar til denne linjen"
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Legg til en generell kommentar til denne %{noteableDisplayName}."
@@ -1882,6 +1905,9 @@ msgstr "Adminmodus skrudd av"
msgid "Admin mode enabled"
msgstr "Adminmodus skrudd på"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Admin-notater"
@@ -1912,9 +1938,6 @@ msgstr "Utvikler"
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr "Gjest"
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr "Eier"
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr "Totalt antall brukere"
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "Statistikk over brukere"
@@ -1981,7 +2007,13 @@ msgstr "Brukere med høyeste rolle"
msgid "AdminArea|Users without a Group and Project"
msgstr "Brukere uten gruppe og prosjekt"
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr "Auto DevOps-domene"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr "Elasticsearch, PlantUML, Slack-applikasjon, Tredjepartstilbud, Snowplow og Amazon EKS har blitt flyttet til Innstillinger &gt; Generelt."
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr "Flyttet til integrasjoner"
msgid "AdminSettings|No required pipeline"
msgstr "Ingen påkrevd rørledning"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Påkrevd rørledningsoppsett"
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Kan ikke oppheve blokkering av LDAP-blokkerte brukere"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Deaktiver"
@@ -2212,6 +2247,9 @@ msgstr "Slett brukere"
msgid "AdminUsers|Delete user and contributions"
msgstr "Slette brukeren og bidragene"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Ekstern"
@@ -2320,6 +2358,9 @@ msgstr "Brukeren vil ikke kunne gå inn på git-kodelagre"
msgid "AdminUsers|User will not be able to login"
msgstr "Brukeren vil ikke kunne logge på"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "Når brukeren logger på igjen, blir kontoen deres reaktivert som en fullt aktiv konto"
@@ -2748,8 +2789,8 @@ msgstr ""
msgid "Alerts"
msgstr "Varsler"
-msgid "Alerts endpoint"
-msgstr "Alarm-endepunkt"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -2889,7 +2930,7 @@ msgstr ""
msgid "Allow projects within this group to use Git LFS"
msgstr "Tillat prosjekter innenfor denne gruppen å bruke Git LFS"
-msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Tillatt å mislykkes"
@@ -2991,6 +3035,9 @@ msgstr "Tidsmengden (i timer) hvor brukere har lov til å hoppe over tvungen kon
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 "En %{link_start}alarm%{link_end} med samme fingeravtrykk er allerede åpent. Hvis du vil endre statusen til dette varselet, må du oppklare den tilknyttede alarmen."
+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 "En administrator endret passordet til GitLab-kontoen din på %{link_to}."
@@ -3018,6 +3065,9 @@ msgstr "En feil har oppstått"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "En feil oppstod under tillegging av et utkast til tråden."
@@ -3234,6 +3284,9 @@ msgstr "En feil oppstod under innlasting av filen."
msgid "An error occurred while loading the file. Please try again later."
msgstr "En feil oppstod under innlasting av filen. Vennligst prøv igjen senere."
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "Det oppstod en feil under innlasting av fletteforepørsels-endringene."
@@ -3405,6 +3458,9 @@ msgstr "Analyser kildekoden din for kjente sårbarheter."
msgid "Ancestors"
msgstr "Forfedre"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anonym"
@@ -3519,12 +3575,6 @@ msgstr "Benytt endringer"
msgid "Apply suggestion"
msgstr "Benytt forslag"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr "Benytt forslag"
@@ -3689,8 +3739,8 @@ msgstr "Arkivert prosjekt! kodelageret og andre prosjektressurser er skrivebesky
msgid "Archived projects"
msgstr "Arkiverte prosjekter"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
-msgstr "Arkivering av prosjektet vil gjøre det helt skrivebeskyttet. Den er skjult fra kontrollpanelet og vises ikke i søk. %{strong_start}Datalageret kan ikke motta commiter, og ingen saker, kommentarer eller andre enheter kan opprettes.%{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr "Er du HELT SIKKER på at du vil slette dette prosjektet?"
@@ -3778,15 +3828,18 @@ msgstr "Er du sikker på at du vil fjerne denne identiteten?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-msgstr "Er du sikker på at du vil nullstille registreringssjetongen?"
-
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?"
+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 "Er du sikker på at du vil trekke tilbake denne %{type}? Denne handlingen kan ikke angres på."
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr "Stigende"
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr "Tilordne til"
msgid "Assign custom color like #FF0000"
msgstr "Tilordne en tilpasset farge som #FF0000"
-msgid "Assign epic"
-msgstr "Tilordne epos"
-
msgid "Assign labels"
msgstr "Tilordne stempler"
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr "Vil du autorisere at %{user} kan bruke kontoen din?"
-msgid "Authorize external services to send alerts to GitLab"
-msgstr "Autoriser eksterne tjenester til å sende alarmer til GitLab"
-
msgid "Authorized %{new_chat_name}"
msgstr "Autoriserte %{new_chat_name}"
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr "Tilgjengelig"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,26 +4456,26 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr "Begynn med den valgte commiten"
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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 ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Fakturering"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name} bruker for tiden %{plan_name}-planen."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "%{user_name}, du bruker for tiden %{plan_name}-planen."
@@ -4436,11 +4483,17 @@ msgstr "%{user_name}, du bruker for tiden %{plan_name}-planen."
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 "Hvis du ønsker å nedgradere planen din, kan du kontakte %{support_link_start}Kundestøtte%{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 Gold."
-msgstr "Lær mer om hver plan ved å lese vår %{faq_link}, eller start en gratis 30-dagers prøveversjon av GitLab.com Gold."
+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 ""
@@ -4460,6 +4513,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "For å behandle planen til denne gruppen, besøk faktureringsseksjonen til %{parent_billing_page_link}."
+msgid "BillingPlans|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 "Din GitLab.com-%{plan}prøveperiode vil %{strong_open}utløpe etter %{expiration_date}%{strong_close}. Du kan beholde tilgangen til %{plan}-funksjonene ved å oppgradere nedenfor."
@@ -4469,6 +4525,9 @@ msgstr "Din GitLab.com-prøveperiode utløp den %{expiration_date}. Du kan når
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "faktureres årlig for %{price_per_year}"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "ofte stilte spørsmål"
@@ -4484,6 +4543,9 @@ msgstr "Kontakt salgsavdelingen"
msgid "BillingPlan|Upgrade"
msgstr "Oppgrader"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Klapp sammen"
@@ -4792,6 +4857,9 @@ msgstr "prosjektinnstillinger"
msgid "Branches|protected"
msgstr "beskyttet"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr "Innebygget"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ msgstr ""
msgid "By %{user_name}"
msgstr "Av %{user_name}"
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr "Som standard sender GitLab e-post i HTML- og rentekst-formater slik at e
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "av"
@@ -4936,6 +5019,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD-konfigurasjon"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD for eksternt kodelager"
@@ -5044,9 +5130,6 @@ msgstr "Kan ikke oppdatere utdrag: %{err}"
msgid "Canary"
msgstr "Canary"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr "Endre bane"
msgid "Change permissions"
msgstr "Endre rettigheter"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr "Endre status"
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Tilbakestill"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "Endret tilordnet person(er)."
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr "Endret tittelen til «%{title_param}»."
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Sjekk %{docs_link_start}dokumentasjonen%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Velg hvilken som helst farge."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Velg fil …"
@@ -5599,6 +5694,9 @@ msgstr "Velg synlighetsnivå, (de)aktiver prosjektets funksjoner (saker,kodelage
msgid "Choose what content you want to see on a group’s overview page."
msgstr "Velg hvilket innhold du vil se på en gruppes oversiktsside."
+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 ""
@@ -5758,12 +5856,24 @@ msgstr "Klassifiseringsetikett (valgfritt)"
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 "Nullstill"
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ msgstr "Kodevurdering"
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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr "Ingen referanser ble funnet"
msgid "CodeOwner|Pattern"
msgstr "Mønster"
-msgid "Cohorts"
-msgstr "Kohorter"
-
msgid "Cohorts|Inactive users"
msgstr "Inaktive brukere"
@@ -7042,6 +7149,9 @@ msgstr "Klapp sammen svar"
msgid "Collapse sidebar"
msgstr "Fold sammen sidepanelet"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "Kontakt salgsavdelingen for å oppgradere"
-
msgid "Contact support"
msgstr "Kontakt kundestøtte"
@@ -7549,9 +7662,15 @@ msgstr "Kopier innloggingskommando"
msgid "ContainerRegistry|Copy push command"
msgstr "Kopier pushkommando"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr "Slett valgt"
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr "Hvis du ikke allerede er logget inn, må du autentisere deg til containe
msgid "ContainerRegistry|Image Repositories"
msgstr "Bildekodelagre"
+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 tags"
msgstr "Bilde-etiketter"
@@ -7671,6 +7799,9 @@ msgstr "Noe gikk galt under markering av etikettene for sletting."
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 ""
@@ -7698,9 +7829,15 @@ 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 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 "Den siste etiketten som var relatert til dette bildet ble nylig fjernet. Dette tomme bildet og eventuelle tilknyttede data blir automatisk fjernet som en del av den vanlige søppeloppsamlingsprosessen. Kontakt administratoren din hvis du har spørsmål."
+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 "Verdien til denne inndataen skal være mindre enn 256 tegn"
@@ -7716,9 +7853,15 @@ msgstr ""
msgid "ContainerRegistry|This image has no active tags"
msgstr "Dette bildet har ingen aktive etiketter"
+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 ""
@@ -7896,6 +8039,9 @@ msgstr "Kopier kommandoer"
msgid "Copy commit SHA"
msgstr "Kopier commit-SHA-en"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr "Kopier miljø"
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr "Kopier verdi"
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Opprettet"
@@ -8423,12 +8593,12 @@ msgstr ""
msgid "Current Branch"
msgstr "Nåværende gren"
-msgid "Current Plan"
-msgstr "Gjeldende abonnement"
-
msgid "Current Project"
msgstr "Gjeldende prosjekt"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "Nåværende node"
@@ -8453,8 +8623,8 @@ msgstr "Profil"
msgid "CurrentUser|Settings"
msgstr "Innstillinger"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "Begynn en Gold-prøveperiode"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr "Oppgrader"
@@ -8462,9 +8632,6 @@ msgstr "Oppgrader"
msgid "Custom Attributes"
msgstr "Tilpassede attributter"
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr "Tilpass navn"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ msgstr "%{firstProject} og %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest}, og %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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."
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ 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 ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr "Vil du forkaste denne nettstedsprofilen?"
msgid "DastProfiles|Do you want to discard your changes?"
msgstr "Vil du forkaste dine endringer?"
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,8 +9024,8 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
-msgstr "Behandle profiler"
+msgid "DastProfiles|Manage DAST scans"
+msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr "Behandle profiler"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr "Minimum = 1 sekund, Maks = 3600 sekunder"
-msgid "DastProfiles|New Profile"
-msgstr "Ny profil"
-
msgid "DastProfiles|New scanner profile"
msgstr "Ny skannerprofil"
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr "Lagre profil"
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr "Skannerprofil"
msgid "DastProfiles|Scanner Profiles"
msgstr "Skanner-profiler"
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr "Nettstedsprofil"
msgid "DastProfiles|Site Profiles"
msgstr "Nettstedsprofiler"
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr "MÃ¥l-URL"
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ msgstr "Sletter"
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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr "Skru av"
msgid "Disable for this project"
msgstr "Deaktiver for dette prosjektet"
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Rediger"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr "tilbakestill den"
@@ -10596,6 +10823,9 @@ msgstr "Aktiver HTML e-poster"
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr "Skru på PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr "Skru på Seat Link"
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr "Aktiver for dette prosjektet"
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr "Skru på mellomtjener"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr "Sluttid"
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "Slutter den (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr "Miljøomfang"
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr "Miljøvariabler brukes på miljøer via Runner. Du kan bruke miljøvariabler til passord, hemmelige nøkler, osv. Gjør variabler tilgjengelig for den kjørende applikasjonen ved å forhåndsstille variabelnøkkelen med %{code_open}K8S_SECRET_%{code_close}. Du kan angi at variabler skal være:"
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 "Skriv inn en tittel på eposet ditt"
@@ -11163,6 +11402,12 @@ msgstr "Fjern epos"
msgid "Epics|Remove issue"
msgstr "Fjern saker"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "Vis mer"
@@ -11553,9 +11798,6 @@ msgstr "Eksempel: %{ip_address}. %{read_more_link}."
msgid "Example: @sub\\.company\\.com$"
msgstr "Eksempel: @sub\\.firma\\.com$"
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr "Eksporter prosjekt"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "Eksporter dette prosjektet med alle dens relaterte data for å flytte prosjektet til en ny GitLab-instans. Når eksporteringen er fullført, kan du importere filen fra siden «Nytt prosjekt»."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr "Raskere utgivelser. Bedre kode. Mindre smerte."
@@ -12524,10 +12772,22 @@ msgstr "Bunntekstmelding"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr "Glemt passordet ditt?"
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Geo-noder"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr "Git-revisjon"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr "GitLab-importering"
@@ -13163,6 +13417,9 @@ msgstr "GitLab-eksport"
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "Det kan ta opptil 30 minutter før nettstedet er tilgjengelig etter den første distribusjonen."
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr "Lær mer."
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr "Lagre"
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 "Noe gikk galt under innhenting av Let's Encrypt-sertifikatet for %{domain}. Gå til dine %{link_start}domenedetaljer%{link_end} for å prøve på nytt."
@@ -13550,9 +13807,6 @@ msgstr "Gruppen %{group_name} ble vellykket opprettet."
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "Gruppe-CI/CD-innstillinger"
-
msgid "Group Git LFS status:"
msgstr "Gruppe-Git-LFS-status:"
@@ -13568,9 +13822,6 @@ msgstr "Gruppe-ID: %{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr "Gruppemedlemmer"
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr "Gruppemilepæl"
@@ -13631,6 +13888,9 @@ msgstr "Gruppenavn"
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr "Gruppeoversikt"
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "Gruppevariabler (arvet)"
@@ -14054,9 +14320,6 @@ msgstr "Grupper å synkronise"
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr "Grupper med tilgang til %{strong_open}%{project_name}%{strong_close}"
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "Grupper med tilgang til %{strong_start}%{group_name}%{strong_end}"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Ofte besøkt"
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr "Ingen importalternativer er tilgjengelige"
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr "Identiteter"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr "Hvis et indeksert felt overskrider denne grensen, blir det avkortet til dette antall tegn, og resten vil ikke bli indeksert eller søkbart. Dette gjelder ikke indeksering av kodelageret og wikien. Hvis du setter dette til 0, betyr det at det er ubegrenset."
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr "Hvis det er deaktivert, vil en avvikende lokal gren ikke automatisk bli
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr "Hvis aktivert"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr "Om %{time_to_now}"
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
msgstr "Under arbeid"
+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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,8 +15617,8 @@ msgstr "Integrert"
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
-msgstr "Skriv inn din kodelager-URL"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr "Sett inn en kodeblokk"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr "Installer"
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ msgstr[1] "Instanser"
msgid "Instance Configuration"
msgstr "Instans-oppsett"
+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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Alle detaljer"
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Skru på kommentarer"
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr "Inkluderer commit-tittelen og grenen"
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "Standard "
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr "Ugyldig brukernavn eller passord"
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "Ugyldig PIN-kode"
@@ -15398,6 +16075,9 @@ msgstr "Inviter gruppe"
msgid "Invite member"
msgstr "Inviter medlem"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr "Status"
msgid "IssueAnalytics|Weight"
msgstr "Vektlegging"
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr "Saker lukket"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Saker med kommentarer, fletteforespørsler med differ og kommentarer, stempler, milepæler, utdrag og andre prosjektenheter"
@@ -15749,6 +16432,9 @@ msgstr "Totalt:"
msgid "Issue|Title"
msgstr "Tittel"
+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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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 "Å vise Jira-saker mens GitLab-saksfunksjonaliteten er aktivert, kan være forvirrende. Vurder å %{linkStart}deaktivere GitLab-saker%{linkEnd} hvis de ikke ellers blir brukt."
msgid "JiraService|Enable Jira issues"
msgstr "Skru på Jira-saker"
+msgid "JiraService|Enable Jira issues creation from vulnerabilities"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
msgstr "Saksliste"
+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 "Jira API-URL"
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr "Jira-sakssporer"
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Jira-prosjektnøkkel"
@@ -15896,9 +16603,21 @@ msgstr "Ã…pne Jira"
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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr "Denne funksjonen krever en Premium-plan."
@@ -15977,6 +16696,9 @@ msgstr "Jobben ble forsøkt på nytt"
msgid "Jobs"
msgstr "Jobber"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,8 +16738,8 @@ msgstr "Jobb-artefakter"
msgid "Job|Job has been erased"
msgstr "Jobben har blitt slettet"
-msgid "Job|Job has been erased by"
-msgstr "Jobben har blitt slettet av"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "Behold"
@@ -16091,6 +16813,9 @@ msgstr "Bare meg selv"
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr "Siste kontakt"
msgid "Last edited %{date}"
msgstr "Sist endret %{date}"
-msgid "Last edited by %{name}"
-msgstr "Sist endret av %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "Lær GitLab"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Lær mer om Auto DevOps"
-msgid "Learn more about Kubernetes"
-msgstr "Lær mer om Kubernetes"
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr "Linjeendringer"
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr "INNFLETTET"
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ msgstr "Godkjennere"
msgid "MRApprovals|Commented by"
msgstr "Kommentert av"
+msgid "MRDiffFile|Changes are too large to be shown."
+msgstr ""
+
+msgid "MRDiffFile|View file @ %{commitSha}"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "Vis kun endringer"
@@ -16935,9 +17666,6 @@ msgstr "Gjør saken konfidensiell"
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr "Gjør denne epos konfidensiell"
-
msgid "Makes this issue confidential."
msgstr "Gjør denne saken konfidensiell."
@@ -16980,6 +17708,9 @@ msgstr "Behandle 2-trinnsautentisering"
msgid "Manage your license"
msgstr "Behandle lisensen din"
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
-msgstr "Maks brukere:"
+msgid "Maximum Users"
+msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr "Maks artefaktstørrelse (MB)"
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr "Makslengde på 100 tegn"
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr "Mai"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Medlemmer"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr "Hopp til neste uoppklarte tråd"
-
msgid "MergeRequests|Reply..."
msgstr "Svar …"
@@ -17652,15 +18383,9 @@ msgstr "Ingen filer ble funnet"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr "Søk i filer (%{modifier_key}P)"
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Flettet"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr "Innflettede FF-er"
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr "Minutter"
msgid "Mirror direction"
msgstr "Speilingsretning"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "Speil kodelager"
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr "Legg til prosjekter"
-msgid "Modal|Cancel"
-msgstr "Avbryt"
-
msgid "Modal|Close"
msgstr "Lukk"
@@ -18451,9 +19179,6 @@ msgstr "Navn"
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr "Navn er påkrevd"
-
msgid "Name new label"
msgstr "Navnet på nytt stempel"
@@ -18587,12 +19312,6 @@ msgstr "Alle valgt"
msgid "NetworkPolicies|Allow"
msgstr "Tillat"
-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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr "Avvis all trafikk"
@@ -18665,6 +19390,9 @@ msgstr "Ingen retningslinjer ble oppdaget"
msgid "NetworkPolicies|None selected"
msgstr "Ingen valgt"
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr "New milestone"
msgid "New password"
msgstr "Nytt passord"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr "Ingen commiter er til stede her"
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr "Ingen samsvarende resultater"
msgid "No matching results for \"%{query}\""
msgstr "Ingen samsvarende resultater for \"%{query}\""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr "Ingen startdato"
-msgid "No status"
-msgstr "Ingen status"
-
msgid "No template"
msgstr "Ingen mal"
@@ -19210,6 +19941,9 @@ msgstr "Ingen mal valgt"
msgid "No test coverage"
msgstr "Ingen testdekning"
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr "Ingen sårbarheter er til stede"
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,11 +20403,11 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
-msgstr "Opprett en ny nettstedsprofil"
+msgid "OnDemandScans|Create new site profile"
+msgstr ""
msgid "OnDemandScans|Description (optional)"
msgstr ""
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr "Behandle profiler"
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,11 +20481,11 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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 "Når et prosjekt er permanent slettet, kan det %{strongStart}ikke gjenopprettes%{strongEnd}. Hvis du sletter dette prosjektet permanent, vil %{strongStart}umiddelbart slette%{strongEnd} kodelagrene og %{strongStart}alle relaterte ressurser%{strongEnd}, inkludert saker, fletteforespørsler, osv."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
-msgstr "Når et prosjekt er slettet permanent, kan det ikke gjenopprettes. Du mister dette prosjektets kodelager og alt innhold: saker, fletteforespørsler, osv."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
+msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr "Bare administratorer kan slette prosjektet"
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ msgstr ""
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr "Bare bekreftede brukere med en e-postadresse hos et av disse domenene kan legges til i gruppen."
-msgid "Only ‘Reporter’ roles and above on tiers Premium / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Innstillinger"
msgid "Or you can choose one of the suggested colors below"
msgstr "Eller så kan du velge en av de foreslåtte fargene nedenfor"
-msgid "Origin"
-msgstr "Opphav"
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Andre stempler"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "Annen informasjon"
@@ -20100,9 +20849,6 @@ msgstr "Slett pakkeversjonen"
msgid "PackageRegistry|Delete package"
msgstr "Slett pakke"
-msgid "PackageRegistry|Filter by name"
-msgstr "Filtrer etter navn"
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr "Det er ingen %{packageType}-pakker enda"
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr "Deltakere"
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr "Bestått"
@@ -20463,6 +21215,9 @@ msgstr "Last ned"
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ msgstr ""
msgid "Pipeline subscriptions"
msgstr "Rørledningsabonnementer"
+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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr "Mer informasjon"
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Det er ingen rørledninger for øyeblikket."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr "Kjør rørledning"
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr "Kjører"
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr "Fullt navn"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr "Organisasjon"
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Posisjoner og endre størrelsen på din nye avatar"
@@ -21867,6 +22628,9 @@ msgstr "Prosjektets navn"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr "Prosjekter å indeksere"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr "Beskytt"
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr "Beskytt variabel"
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr "Gren"
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr "Tillatt å distribuere"
msgid "ProtectedEnvironment|Environment"
msgstr "Miljø"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Beskytt"
@@ -22875,9 +23651,6 @@ msgstr "Beskytt et miljø"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Beskyttet miljø (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "Velg et miljø"
@@ -22887,8 +23660,8 @@ msgstr "Velg brukere"
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "Det er for tiden ingen beskyttede miljøer, beskytt et miljø med skjemaet ovenfor."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "Ubeskyttet"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr "Sanntidsfunksjoner"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr "Nullstill"
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "Registrer deg nå"
+msgid "Register the runner with this URL:"
+msgstr ""
+
msgid "Register with two-factor app"
msgstr "Registrer med 2-trinnsapp"
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr "Avslått (lukket)"
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr "Relaterte saker"
-msgid "Related Jobs"
-msgstr "Relaterte jobber"
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr "Relaterte saker"
@@ -23362,9 +24135,6 @@ msgstr "Fjern"
msgid "Remove %{displayReference}"
msgstr "Fjern %{displayReference}"
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr "Fjern Zoom-møte"
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Fjern sekundærnode"
@@ -23705,6 +24478,11 @@ msgstr "Klassenavn"
msgid "Reports|Execution time"
msgstr "Kjøretid"
+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] ""
@@ -23872,6 +24650,9 @@ msgstr "Kodelager-lagring"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr "Tilbakestill nøkkel"
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr "Forsøk igjen"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Prøv denne jobben på nytt"
@@ -24175,6 +24959,9 @@ 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 "Gjennomgangstid"
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr "legge til en"
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr "Løpere"
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr "Runners|Egenskapsnavn"
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr "Offentlig SSH-nøkkel"
msgid "SSL Verification:"
msgstr "SSL-verifisering:"
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr "Hemmelig"
msgid "Secret Detection"
msgstr "Hemmelig oppdagelse"
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Sikkerhet"
@@ -24796,6 +25613,9 @@ msgstr "Sikkerhetskontrollpanel"
msgid "Security dashboard"
msgstr "Sikkerhetskontrollpanel"
+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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,15 +25945,15 @@ msgstr "Se målinger"
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 "See what's new at GitLab"
-msgstr "Se hva som er nytt hos GitLab"
-
msgid "Select"
msgstr "Velg"
@@ -25197,8 +26011,8 @@ msgstr "Velg en tidssone"
msgid "Select all"
msgstr "Velg alt"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Velg en eksisterende Kubernetes-klynge eller opprett en ny"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr "Velg tilordnet"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr "Velg helsestatus"
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr "Velg stempel"
@@ -25284,9 +26101,6 @@ msgstr "Velg abonnement"
msgid "Select target branch"
msgstr "Velg målgren"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Velg grenen du vil angi som standarden for dette prosjektet. Alle fletteforespørsler og commiter vil automatisk bli utført mot denne grenen med mindre du spesifiserer en annen en."
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ msgstr "Bestem målgren"
msgid "Set target branch to %{branch_name}."
msgstr "Sett målgrenen til %{branch_name}."
+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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr "Angi standard utløpstid for hver jobb. 0 for ubegrenset. Standardenheten er i sekunder, men du kan definere et alternativ. For eksempel: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
@@ -25608,10 +26425,10 @@ msgstr "Sett opp CI/CD"
msgid "Set up Jira Integration"
msgstr "Sett opp Jira-integrering"
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr "Sett opp nytt passord"
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-msgstr "Hvis du noen gang mister telefonen eller tilgang til din éngangs passordhemmelighet, kan hver av disse gjenopprettingskodene brukes én gang hver for å få tilgang til kontoen din igjen. Vennligst lagre dem på et trygt sted, ellers vil du %{b_start}vil%{b_end} miste tilgang til kontoen din."
-
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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Vis nyeste versjon"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr "Vis liste"
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr "Smartkort"
@@ -26215,6 +27026,9 @@ msgstr ""
msgid "Something went wrong while editing your comment. Please try again."
msgstr "Noe gikk galt under redigering av kommentaren din. Prøv igjen senere."
+msgid "Something went wrong while exporting requirements"
+msgstr ""
+
msgid "Something went wrong while fetching %{listType} list"
msgstr "Noe gikk feil under henting av %{listType} listen"
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr "Stacktrace-utdrag"
msgid "Stage"
msgstr "Trinn"
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr "Start netterminal"
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr "Start søk"
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr "Start tråd"
@@ -26713,7 +27518,7 @@ msgstr "Start tråd og lukk %{noteable_name}"
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr "Starter …"
msgid "Starts %{startsIn}"
msgstr "Starter %{startsIn}"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Starter (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr "Ukjent"
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Systemmåltall (egendefinert)"
@@ -27361,9 +28172,15 @@ msgstr "Navn på tag"
msgid "Tag name is required"
msgstr "Etikettnavn er påkrevd"
+msgid "Tag push events"
+msgstr ""
+
msgid "Tag this commit."
msgstr "Gi denne commiten en etikett."
+msgid "Tag:"
+msgstr ""
+
msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
msgstr ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "Den maks tillatte filstørrelsen er %{size}."
+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 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 ""
@@ -28022,8 +28851,11 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
-msgstr "Antall endringer som skal innhentes fra GitLab når du kloner et kodelager. Dette kan øke hastigheten på utførelsen av rørledninger. Hold det tomt eller sett til 0 for å deaktivere tynn kloning som standard og få GitLab CI til å hente alle grener og etiketter hver gang."
+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 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 ""
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr "Prosjektet ble vellykket importert."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Pseudonymisert datainnsamling er deaktivert. Når den er aktivert, vil GitLab kjøre en bakgrunnsjobb som vil opprette pseudonymiserte CSV-filer av GitLab-databasen. Disse vil bli lastet opp til den konfigurerte objektlagringskatalogen."
+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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 "Brukerkartet er en kartlegging av FogBugz-brukerne som deltok på prosjektene dine til måten deres e-postadresse og brukernavn blir importert til GitLab. Du kan endre dette ved å fylle ut tabellen nedenfor."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr "En feil oppstod under innhenting av prosjektetiketter."
msgid "There was a problem fetching project users."
msgstr "En feil oppstod under innhenting av prosjektbrukere."
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr "En feil oppstod under innhenting av brukere."
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,23 +29391,35 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
-msgstr "Denne handlingen vil %{strongOpen}permanent slette%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}umiddelbart%{strongClose}, inkludert kodelagrene dens og alt innhold: saker, fletteforespørsler, osv."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
-msgstr "Denne handlingen vil %{strongOpen}permanent slette%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}den %{date}%{strongClose}, inkludert kodelagrene dens og alt innhold: saker, fletteforespørsler, osv."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
msgid "This also resolves all related threads"
msgstr ""
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
-msgstr "Dette vedlegget har blitt avkortet for å unngå å overskride den maksimalt tillatte størrelsen på vedlegg på 15 MB. %{written_count} av %{issues_count} saker har blitt inkludert. Vurder å eksportere på nytt med et smalere valg av saker."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr "Dette feltet er påkrevd."
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Denne gruppen"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,9 @@ msgstr "Dette kan avsløre konfidensiell informasjon, ettersom den valgte utgrei
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 ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr "Dette prosjektet"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "Denne brukeren vil være skaperen for alle hendelser i aktivitetsstrømmen som er resultatet av en oppdatering, for eksempel nye grener som blir opprettet eller nye commits som blir pushet til eksisterende grener."
-
msgid "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 "For å koble til GitHub-kodelagre, kan du bruke en %{personal_access_token_link}. Når du oppretter din personlige tilgangsnøkkel, må du velge %{code_open}kodelager%{code_close}-omfang, så vi kan vise en liste over dine offentlige og private kodelagre som er tilgjengelige for å koble til."
@@ -29406,6 +30280,9 @@ msgstr "For å koble til et SVN-kodelager, sjekk ut %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "For å beskytte kontoen din ytterligere, bør du vurdere å konfigurere en %{mfa_link_start}2-trinnsautentiserings%{mfa_link_end}metode."
@@ -29415,6 +30292,9 @@ msgstr "For å beskytte kontoen din ytterligere, bør du vurdere å konfigurere
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 "For å komme i gang, skriv inn din FogBugz-URL og -påloggingsinformasjon nedenfor. I de neste trinnene vil du kunne kartlegge brukere og velge prosjektene du vil importere."
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ msgstr "For å motta alarmer fra manuelt konfigurerte Prometheus-tjenester, legg
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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "For å vise veikartet, legg til en start- eller forfallsdato til en av dine eposer i denne gruppen eller dens undergrupper. I månedsvisningen vises bare innholdet i den siste måneden, denne måneden og de neste 5 månedene."
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr "I dag"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr "Veksle Markdown-forhåndsvisning"
@@ -29550,6 +30427,9 @@ msgstr "Veksle nedfall"
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Veksle navigasjon"
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ msgstr "Overfør eierskap"
msgid "Transfer project"
msgstr "Overfør prosjekt"
+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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ msgstr ""
msgid "Trigger"
msgstr "Utløser"
+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 ""
@@ -29798,8 +30687,8 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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 "Trigg rørledninger når grener eller koder oppdateres fra oppstrømskodelageret. Avhengig av aktiviteten til oppstrømsregisteret, kan dette øke belastningen på CI-kjørerne dine kraftig. Bare aktiver dette hvis du vet at de kan takle belastningen."
+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 "Trigger fjernet."
@@ -29825,7 +30714,10 @@ msgstr "Triggeren ble vellykket oppdatert."
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,8 +30933,8 @@ msgstr ""
msgid "Unarchive project"
msgstr "Opphev arkivering av prosjekt"
-msgid "Unarchiving the project will restore people's 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}"
-msgstr "Å fjerne arkivering av prosjektet vil gjenopprette folks evne til å gjøre endringer i det. Datalageret kan bli kodeinnsmettet til, og saker, kommentarer og andre enheter kan opprettes. %{strong_start}Når dette prosjektet er aktivt, vises det i søket og på kontrollpanelet.%{strong_end}"
+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 ""
@@ -30299,7 +31191,7 @@ msgstr "Oppdateringer"
msgid "Updating"
msgstr "Oppdaterer"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Last opp CSV-fil"
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr "Bruk en linje per URI"
msgid "Use template"
msgstr "Bruk mal"
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ msgstr "Rediger %{name}"
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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr "Brukere"
msgid "Users in License"
msgstr ""
-msgid "Users in License:"
-msgstr "Brukere i lisensen:"
-
msgid "Users or groups set as approvers in the project's or merge request's settings."
msgstr "Brukere eller grupper som er angitt som godkjennere i innstillingene til prosjektet eller fletteforespørselen."
-msgid "Users over License:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr "Brukere som ber om tilgang til"
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr "Verdistrømnavn"
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ msgstr "Variabelen vil bli maskert i jobbloggføringene."
msgid "Variables"
msgstr "Variabler"
+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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "Viser commit"
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr "Fletteforespørsel"
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Webhook"
@@ -31473,6 +32386,9 @@ msgstr "Webhook-loggføringer"
msgid "Webhook Settings"
msgstr "Webhook-innstillinger"
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Webhooks"
@@ -31608,12 +32524,12 @@ msgstr "Velkommen tilbake! Kontoen din hadde blitt deaktivert på grunn av inakt
msgid "Welcome to GitLab"
msgstr "Velkommen til GitLab"
-msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr "Velkommen til GitLab%{br_tag}%{name}!"
-
msgid "Welcome to GitLab, %{first_name}!"
msgstr "Velkommen til GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
msgid "Welcome to the guided GitLab tour"
msgstr "Velkommen til den guidede GitLab-turen"
@@ -31629,8 +32545,8 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
-msgstr "Hva er nytt hos GitLab"
+msgid "What's new"
+msgstr ""
msgid "What’s your experience level?"
msgstr "Hva er ditt erfaringsnivå?"
@@ -31638,7 +32554,7 @@ msgstr "Hva er ditt erfaringsnivå?"
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr "Når det er aktivert, så kan brukere ikke bruke GitLab frem til vilkår
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Når denne fletteforespørselen godtas"
@@ -31667,6 +32586,9 @@ msgstr[1] "Når disse fletteforespørslene godtas"
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 "Når du bruker %{code_open}http: //%{code_close} eller %{code_open}https: //%{code_close} protokollene, vennligst oppgi den nøyaktige URL-en til kodelageret. HTTP-viderekoblinger blir ikke fulgt."
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "NÃ¥r:"
@@ -32027,9 +32949,6 @@ 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 "Du bruker PostgreSQL %{pg_version_current}, men PostgreSQL %{pg_version_minimum} er påkrevd for denne versjonen av GitLab. Vennligst oppgrader ditt miljø til en støttet PostgreSQL-versjon, se %{pg_requirements_url} for detaljer."
-msgid "You can %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr "Du kan også opprette et prosjekt fra kommandolinjen."
@@ -32051,9 +32970,6 @@ msgstr "Du kan ogsÃ¥ laste opp eksisterende filer fra datamaskinen din ved Ã¥ fÃ
msgid "You can always edit this later"
msgstr "Du kan alltid redigere dette senere"
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ msgstr "Du kan invitere et nytt medlem til %{project_name} eller invitere en ann
msgid "You can invite a new member to %{project_name}."
msgstr "Du kan invitere et nytt medlem til %{project_name}."
+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 "Du kan invitere en annen gruppe til %{project_name}."
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "Du kan bare redigere filer når du er på en gren"
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr "Du kan se dine chatkontoer."
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr "Du har ingen tillatelser"
@@ -32489,6 +33411,9 @@ msgstr "YouTube"
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 ""
@@ -32525,15 +33450,15 @@ msgstr "DevOps-rapporten din gir en oversikt over hvordan du bruker GitLab fra e
msgid "Your GPG keys (%{count})"
msgstr "Dine GPG-nøkler (%{count})"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr "Din GitLab-gruppe"
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr ""
-
msgid "Your Groups"
msgstr "Dine grupper"
@@ -32687,6 +33612,9 @@ msgstr "Din lisens er gyldig fra"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr "Lisensen din vil bli inkludert i GitLab-sikkerhetskopien og vil overleve oppgraderinger, så ved normal bruk trenger du aldri å laste opp %{code_open}.gitlab-lisens%{code_close}-filen din på nytt."
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "Din melding her"
@@ -32771,6 +33699,12 @@ msgstr "Zoom-møte fjernet"
msgid "[No reason]"
msgstr "[Ingen grunn]"
+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 "en slettet bruker"
@@ -32857,9 +33791,15 @@ msgstr "grennavn"
msgid "by"
msgstr "av"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "dag"
msgstr[1] "dager"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr "standardgren"
@@ -33211,8 +34154,10 @@ msgstr "f.eks. %{token}"
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr "gruppe"
msgid "group members"
msgstr "gruppemedlemmer"
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr "grupper"
@@ -33549,6 +34497,12 @@ msgstr "Vennligst gjenopprett den eller bruk en annen %{missingBranchName}-fane"
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr "Flett"
msgid "mrWidget|Merge failed."
msgstr "Fletting mislyktes."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr "Flett lokalt"
@@ -33747,7 +34698,7 @@ msgstr "Endringene ble ikke flettet inn i"
msgid "mrWidget|The changes will be merged into"
msgstr "Endringene vil bli flettet inn i"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr "tilbakestille den."
msgid "revised"
msgstr "revidert"
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr "tilfredsstilt"
@@ -34189,6 +35146,9 @@ msgstr "Ã¥ liste opp"
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "utløst"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 80519ed1b7e..8813ebf4c9a 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:02\n"
+"PO-Revision-Date: 2021-02-01 18:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d opgelost testresultaat"
msgstr[1] "%d opgeloste testresultaten"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Runner is actief en kan nieuwe taken verwerken"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner is onderbroken en zal geen nieuwe taken ontvangen"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "door"
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 4a507651a88..98c3378861e 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pa-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index e24a195408c..42d15b150f4 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: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:00\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,6 +252,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -486,10 +493,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1183,6 +1196,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1190,10 +1206,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1431,6 +1444,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1801,15 +1826,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2068,6 +2093,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2098,9 +2126,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2167,7 +2195,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2398,6 +2435,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2506,6 +2546,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2936,7 +2979,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3422,6 +3474,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3593,6 +3648,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3707,12 +3765,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,7 +3937,7 @@ 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}"
+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?"
@@ -3976,15 +4028,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4054,7 +4109,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4335,9 +4387,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4362,7 +4411,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4461,16 +4510,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4611,25 +4660,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4638,10 +4687,16 @@ 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 Gold."
+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}."
@@ -4662,6 +4717,9 @@ 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 ""
@@ -4671,6 +4729,9 @@ 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 ""
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4996,6 +5063,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -5095,6 +5174,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5140,6 +5225,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5782,9 +5882,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ msgstr ""
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "jest niedostępna: %{reason}"
+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 ""
@@ -6010,7 +6122,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8463,12 +8614,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8637,10 +8809,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8667,7 +8839,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,7 +10457,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,7 +11109,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ 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 ""
@@ -11393,6 +11634,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12864,7 +13120,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13326,7 +13585,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,10 +15903,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15642,6 +16321,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,7 +16984,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16335,6 +17059,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,7 +17279,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 ""
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17477,9 +18213,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18715,9 +19445,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,7 +19913,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20813,6 +21573,9 @@ 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 ""
@@ -20981,9 +21744,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21854,9 +22620,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22139,6 +22902,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23493,12 +24271,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,7 +25076,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24414,6 +25199,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24463,6 +25251,9 @@ 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 "Przejrzyj proces celem konfiguracji dostawców usług u swojego dostawcy tożsamości - w tym przypadku GitLab jest \"dostawcą usług\" lub \"wierzycielem\"."
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Uruchom nieoznaczone zadania"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr ""
msgid "Runners"
msgstr "Robotnicy"
-msgid "Runners API"
-msgstr "API Robotników"
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Robotnicy mogą być przydzielani do oddzielnych użytkowników, serwerów, a nawet do Twojego lokalnego komputera."
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr "Strona Robotników."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24725,6 +25540,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,7 +26329,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Wolniej, ale zapewnia, że ​​przestrzeń robocza projektu jest nieskazitelna, ponieważ klonuje repozytorium dla każdego zadania kompletnie od zera"
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,8 +27717,8 @@ msgstr "Ochrona przed spamem i przed botami"
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
-msgstr "Określeni Wykonawcy"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr ""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "Określ wzór regex adresu e-mail, aby zidentyfikować domyślnych użytkowników wewnętrznych."
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr "Etap i Angaż"
-
msgid "Stage data updated"
msgstr ""
@@ -26986,7 +27798,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27031,7 +27840,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Rozpoczyna siÄ™ o (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Określ swoją wiadomość, aby aktywować"
@@ -27244,6 +28053,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Metryki systemowe (Niestandardowe)"
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28350,7 +29183,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28416,6 +29249,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Zbiór danych pseudonimizera jest wyłączony. Po włączeniu GitLab uruchomi zadanie w tle, które będzie wytwarzać pseudonimiczne pliki CSV bazy danych GitLab, które zostaną przesłane do skonfigurowanego katalogu przechowywania obiektów."
+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 took to long to complete."
msgstr ""
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 "Mapa użytkownika to mapowanie użytkowników FogBugz, którzy uczestniczyli w Twoich projektach, w celu zaimportowania ich adresów e-mail i nazw użytkowników do GitLab. Możesz to zmienić, wypełniając poniższą tabelę."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,7 +29708,7 @@ 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."
+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."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29004,13 +29864,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29040,6 +29903,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 ""
@@ -29208,7 +30086,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ 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 ""
@@ -29738,6 +30616,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,7 +30682,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,7 +31271,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30633,7 +31529,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,7 +31778,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31946,10 +32866,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32391,9 +33314,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ 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 ""
@@ -32865,13 +33794,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34031,9 +34991,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34103,7 +35060,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34184,6 +35141,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 2b54b342daa..cd935bc6e6f 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:05\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste corrigido"
msgstr[1] "%d resultados do teste corrigidos"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr "Tópico de %{authorsName}"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr ""
msgid ", or "
msgstr ", ou "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- Evento"
msgstr[1] "- Eventos"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- O runner está ativo e pode processar novas tarefas"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- O runner está pausado e não receberá nenhuma tarefa nova"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "Um branch padrão não pode ser escolhido para um projeto vazio."
msgid "A deleted user"
msgstr "Um usuário excluído"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Um projeto é onde você armazena seus arquivos (repositório), planeja seu trabalho (issues), e publica sua documentação (wiki), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr "Um token seguro que identifica uma requisição de armazenamento externo."
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr "Adicione um botão Grafana na barra lateral do administrador, monitorand
msgid "Add a To Do"
msgstr "Adicionar um afazer"
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
msgid "Add a comment to this line"
msgstr ""
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Adicionar um comentário geral para este %{noteableDisplayName}."
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Notas de administração"
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr "Domínio de Auto DevOps"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Ativar runners compartilhados para novos projetos"
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Nenhum pipeline necessário"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Configuração de pipeline necessária"
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Não é possível desbloquear usuários bloqueados pelo LDAP"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Desativar"
@@ -2212,6 +2247,9 @@ msgstr "Apagar usuário"
msgid "AdminUsers|Delete user and contributions"
msgstr "Excluir o usuário e suas contribuições"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Externo"
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr "Alertas"
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,8 +2930,8 @@ msgstr ""
msgid "Allow projects within this group to use Git LFS"
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 acesso público aos pipelines e detalhes de tarefas, incluindo logs de saída e artefatos"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Permitir renderização de diagramas PlantUML em documentos Asciidoc."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Permitido falhar"
@@ -2991,6 +3035,9 @@ msgstr "Quantidade de tempo (em horas) que os usuários podem ignorar a configur
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 ""
@@ -3018,6 +3065,9 @@ msgstr "Ocorreu um erro"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr "Ancestrais"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anônimo"
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr "Aplicar sugestão"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ msgstr "Projeto arquivado! Repositório e outros recursos de projeto são soment
msgid "Archived projects"
msgstr "Projetos arquivados"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr "Você tem certeza de que deseja excluir este item?"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-msgstr "Você tem certeza que quer recriar o token de registro?"
-
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?"
+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 ""
@@ -3856,8 +3909,8 @@ msgstr "Token de acesso pessoal do usuário. O usuário deve ter acesso à taref
msgid "Ascending"
msgstr "Ascendente"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "Solicite a um mantenedor do grupo para configurar um Runner de grupo."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL de serviço do consumidor de asserção"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "Coloque uma cor personalizada, como #FF0000"
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr "Atribuir etiquetas"
@@ -4133,9 +4183,6 @@ msgstr "Autorizar %{link_to_client} usar sua conta?"
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "%{new_chat_name} autorizado"
@@ -4160,8 +4207,8 @@ msgstr "Auto DevOps, runners e artefatos de tarefas"
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Cancelar automaticamente os pipelines redundantes pendentes"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4259,17 +4306,17 @@ msgstr "Disponível"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "Runners de grupo disponíveis: %{runners}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "Runners compartilhados disponíveis:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "Runners específicos disponíveis"
@@ -4409,25 +4456,25 @@ msgstr "Tenha cuidado. Renomear o repositório de um projeto pode ter efeitos co
msgid "Begin with the selected commit"
msgstr "Comece com o commit selecionado"
-msgid "Below are examples of regex for existing tools:"
-msgstr "Abaixo estão exemplos de regex para ferramentas existentes:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "Abaixo estão as impressões digitais das chaves do host SSH da instância atual."
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 ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Cobrança"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,11 +4483,17 @@ 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 "Se você gostaria de diminuir o seu plano, por favor entre em contato com o %{support_link_start}Suporte ao Cliente%{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 Gold."
-msgstr "Saiba mais sobre cada plano lendo nossas %{faq_link}, ou inicie uma avaliação gratuita de 30 dias do GitLab.com Gold."
+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 "Saiba mais sobre cada plano visitando nossa %{pricing_page_link}."
@@ -4460,6 +4513,9 @@ msgstr "Esse grupo usa o plano associado com seu grupo pai."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Para gerenciar o plano para esse grupo, visite a seção de cobrança de %{parent_billing_page_link}."
+msgid "BillingPlans|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 ""
@@ -4469,6 +4525,9 @@ 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 "perguntas frequentes"
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Recolher"
@@ -4792,6 +4857,9 @@ msgstr "configurações do projeto"
msgid "Branches|protected"
msgstr "protegido"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr "Embutido"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ msgstr ""
msgid "By %{user_name}"
msgstr "Por %{user_name}"
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr "Por padrão, o GitLab envia e-mails em formatos HTML e texto plano para
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 default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
@@ -4936,6 +5019,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "Configuração de CI/CD"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD para um repositório externo"
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Canary Deployments é uma estratégia popular em CI onde uma pequena porção da frota é atualizada para a nova versão do seu aplicativo."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr "Alterar caminho"
msgid "Change permissions"
msgstr "Alterar permissões"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Reverter"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr "Alterou o título para \"%{title_param}\"."
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Verifique a %{docs_link_start}documentação%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Escolha qualquer cor."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Escolher arquivo…"
@@ -5599,6 +5694,9 @@ msgstr "Escolha o nível de visibilidade, ative/desative os recursos do projeto
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 "Escolha quais repositórios você deseja se conectar e executar pipelines de CI/CD."
@@ -5758,12 +5856,24 @@ msgstr "Etiqueta de Classificação (opcional)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "está indisponível: %{reason}"
+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 "Limpar"
@@ -5806,8 +5916,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Clique no botão abaixo para iniciar o processo de instalação navegando para a página do Kubernetes"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "Clique para expandir."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Padrão"
-msgid "Cohorts"
-msgstr "Cohorts"
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Minimizar barra lateral"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "Entre em contato com o departamento de vendas para atualizar"
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr "criar um token de acesso pessoal"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Feito"
@@ -8423,12 +8593,12 @@ msgstr ""
msgid "Current Branch"
msgstr "Branch atual"
-msgid "Current Plan"
-msgstr ""
-
msgid "Current Project"
msgstr "Projeto atual"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "Nó atual"
@@ -8453,7 +8623,7 @@ msgstr "Perfil"
msgid "CurrentUser|Settings"
msgstr "Configurações"
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,8 +8704,8 @@ msgstr "Personalize as configurações relacionadas a idioma e região."
msgid "Customize name"
msgstr "Customizar nome"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "Personalize a sua configuração, visualize o status da pipeline e relatório de cobertura."
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
@@ -8749,7 +8916,7 @@ msgstr "%{firstProject} e %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest} e %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,8 +10227,8 @@ msgstr "Desabilitar"
msgid "Disable for this project"
msgstr "Desativar para este projeto"
-msgid "Disable group Runners"
-msgstr "Desabilitar runners de grupo"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
@@ -10299,9 +10520,6 @@ msgstr "Durante esse processo, você será perguntado por URLs do lado do GitLab
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr "Cada runner pode estar em um dos seguintes estados:"
-
msgid "Edit"
msgstr "Alterar"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr "Habilitar e-mails em HTML"
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr "Ativar coleção de dados Pseudonymizer"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,8 +10877,8 @@ msgstr ""
msgid "Enable for this project"
msgstr "Ativar para este projeto"
-msgid "Enable group Runners"
-msgstr "Ativar grupo de runners"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr "Ativar cabeçalho e rodapé em e-mails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr "Habilitar proxy"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "Termina em (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
msgstr ""
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "As variáveis de ambiente são configuradas pelo seu administrador para serem %{link_start}protegidas%{link_end} por padrão"
-
-msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ msgstr ""
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "Você tem certeza de que quer remover %{bStart}%{targetIssueTitle}%{bEnd} de %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11163,6 +11402,12 @@ msgstr "Remover épico"
msgid "Epics|Remove issue"
msgstr "Remover issue"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "Mostrar mais"
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr "Exemplo: Uso = consulta única. (Solicitada) / (Capacidade) = múltiplas consultas combinadas em uma fórmula."
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr "Exportar projeto"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "Exporte este projeto com todos os dados relacionados para mover seu projeto para uma nova instância do GitLab. Quando a exportação estiver concluída, você poderá importar o arquivo da página \"Novo projeto\"."
+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 Classification Policy Authorization"
msgstr "Autorização de Política de Classificação Externa"
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr "Mais rápido, uma vez que reutiliza o espaço de trabalho do projeto (voltando a clonar, se não existir)"
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ msgstr "Mensagem do Rodapé"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr "Para obter mais informações, consulte a documentação sobre %{deactiv
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para projetos privados, qualquer membro (guest ou superior) pode visualizar pipelines e acessar detalhes das tarefas (logs de saída e artefatos)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Para projetos públicos, qualquer pessoa pode visualizar pipelines e acessar detalhes das tarefas (logs de saída e artefatos)"
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,8 +12886,8 @@ msgstr "Da abertura de tarefas até a implantação para a produção"
msgid "From merge request merge until deploy to production"
msgstr "Do merge request até a implantação em produção"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "Na visualização de detalhes do cluster do Kubernetes, instale o Runner pela lista de aplicativos"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr "Nome completo"
@@ -12680,6 +12934,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Nós do Geo"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,8 +13351,8 @@ msgstr "Revisão do Git"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
-msgstr "Estratégia Git para pipelines"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "Os GitLab Group Runners podem executar código para todos os projetos neste grupo."
-
msgid "GitLab Import"
msgstr "Importação do GitLab"
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab para Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr "O grupo %{group_name} foi criado com sucesso."
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr "Configurações de CI/CD do grupo"
-
msgid "Group Git LFS status:"
msgstr "Status do LFS do grupo Git:"
@@ -13568,9 +13822,6 @@ msgstr "ID do grupo: %{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr "Group Runners"
-
msgid "Group SAML must be enabled to test"
msgstr "O grupo SAML deve ser habilitado para testar"
@@ -13622,6 +13873,12 @@ msgstr "Os mantenedores podem registrar grupos de runners em %{link}"
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr "Nome do grupo"
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Visitados frequentemente"
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr "Manutenção iniciada com sucesso"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr "Identidades"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr "Se desativada, um branch local divergente não será atualizada automati
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "Se desativado, o nível de acesso irá depender das permissões do usuário no projeto."
-
-msgid "If enabled"
-msgstr "Se ativado"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ msgstr ""
msgid "Incidents"
msgstr "Incidentes"
+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 ""
@@ -14976,8 +15617,8 @@ msgstr "Em linha"
msgid "Input host keys manually"
msgstr "Insira as chaves do host manualmente"
-msgid "Input your repository URL"
-msgstr "Insira seu URL do repositório"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr ""
@@ -15018,11 +15659,11 @@ msgstr ""
msgid "Install"
msgstr "Instalar"
-msgid "Install GitLab Runner"
-msgstr "Instalar o GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Instalar Runner no Kubernates"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
@@ -15047,9 +15688,21 @@ msgstr[1] "Instâncias"
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 "O grupo de administradores da instância já existe"
+msgid "Instance overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr "Entrada inválida, por favor, evite emojis"
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "Código PIN inválido"
@@ -15398,6 +16075,9 @@ msgstr "Convidar grupo"
msgid "Invite member"
msgstr "Convidar membro"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso
msgid "Issues closed"
msgstr "Issues fechadas"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Issues com comentários, merge requests com diffs e comentários, etiquetas, marcos, snippets e outras entidades do projeto"
@@ -15749,6 +16432,9 @@ msgstr "Total:"
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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr "Eventos para %{noteable_model_name} estão desabilitados."
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Se diferente do URL da Web"
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ msgstr ""
msgid "Jobs"
msgstr "Tarefas"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,8 +16738,8 @@ msgstr "Artefatos da tarefa"
msgid "Job|Job has been erased"
msgstr "A tarefa foi apagada"
-msgid "Job|Job has been erased by"
-msgstr "A tarefa foi apagada por"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "Manter"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr "Último contato"
msgid "Last edited %{date}"
msgstr "Última edição em %{date}"
-msgid "Last edited by %{name}"
-msgstr "Última edição por %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "Aprenda GitLab"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Saiba mais sobre o Auto DevOps"
-msgid "Learn more about Kubernetes"
-msgstr "Saiba mais sobre o Kubernetes"
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] "Limitado a mostrar %d eventos, no máximo"
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ msgstr "Aprovadores"
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 "Mostrar apenas alterações"
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr "Gerenciar a autenticação de dois fatores"
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr "Tempo limite máximo da tarefa"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr "Mai"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Membros"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr "Ocorreu um erro ao salvar o rascunho do comentário."
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "Responder..."
@@ -17652,15 +18383,9 @@ msgstr "Nenhum arquivo encontrado"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Merge realizado"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr "Migração bem sucedida."
@@ -18229,6 +18957,9 @@ msgstr "Minutos"
msgid "Mirror direction"
msgstr "Direção do espelho"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "Espelhar repositório"
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Cancelar"
-
msgid "Modal|Close"
msgstr "Fechar"
@@ -18451,9 +19179,6 @@ msgstr "Nome"
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "Nome da nova etiqueta"
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,8 +19641,8 @@ msgstr "Novo marco"
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "Novos pipelines cancelarão pipelines pendentes mais antigos no mesmo branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Novo projeto"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Nenhuma conexão pode ser feita para um servidor Gitaly, por favor check os logs!"
@@ -19123,6 +19854,9 @@ msgstr "Nenhum resultado correspondente"
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr "Nenhum modelo"
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr "Apenas branches protegidos por espelho"
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Opções"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ou você pode escolher uma das cores sugeridas abaixo"
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Outras etiquetas"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "Outra informação"
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr "Agendamento da Pipeline"
msgid "Pipeline Schedules"
msgstr "Agendamentos da Pipeline"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 "Gatilho de pipeline"
@@ -20709,9 +21470,6 @@ msgstr "Carregando Pipelines"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "Cache do projeto redefinido com sucesso."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Atualmente não há pipelines."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Ocorreu um erro ao buscar os pipelines. Tente novamente daqui a pouco ou entre em contato com sua equipe de suporte."
@@ -20862,6 +21620,9 @@ msgstr "Executar Pipeline"
msgid "Pipeline|Run for"
msgstr "Executar para"
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr "O token de feed foi redefinido com sucesso"
msgid "Profiles|Full name"
msgstr "Nome completo"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "Incluir contribuições privadas no meu perfil"
@@ -21582,9 +22346,6 @@ msgstr "Organização"
msgid "Profiles|Path"
msgstr "Caminho"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Posicione e dimensione seu novo avatar"
@@ -21867,6 +22628,9 @@ msgstr "Nome do projeto"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr "Projetos que pertencem a um grupo são prefixados com o namespace do gru
msgid "Projects to index"
msgstr "Projetos para indexar"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr "Permitido fazer deploy"
msgid "ProtectedEnvironment|Environment"
msgstr "Ambiente"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
@@ -22875,9 +23651,6 @@ msgstr "Proteger um ambiente"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "Ambiente Protegido (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "Selecione um ambiente"
@@ -22887,8 +23660,8 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "Atualmente não existem ambientes protegidos, proteja um ambiente com o formulário acima."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "Desproteger"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr "Recursos em tempo real"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr "Registrar dispositivo de Dois Fatores Universal (U2F)"
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "Registre-se com aplicativo de dois fatores"
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Tarefas Implantadas Relacionadas"
-
msgid "Related Issues"
msgstr "Issues Relacionadas"
-msgid "Related Jobs"
-msgstr "Tarefas Relacionadas"
-
-msgid "Related Merge Requests"
-msgstr "Merge Requests Relacionados"
-
-msgid "Related Merged Requests"
-msgstr "Merge Requests Relacionados"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr "Remover"
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr "Remover Runner"
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ msgstr "Noma da classe"
msgid "Reports|Execution time"
msgstr "Tempo de execução"
+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] ""
@@ -23872,6 +24650,9 @@ msgstr "Armazenamento do Repositório"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,8 +24786,8 @@ msgstr "Recriar o token de status de saúde"
msgid "Reset key"
msgstr "Redefinir chave"
-msgid "Reset runners registration token"
-msgstr "Recriar o token de registro de runners"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr "Redefinir modelo"
@@ -24128,6 +24909,9 @@ msgstr "Tentar novamente"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Refazer tarefa"
@@ -24175,6 +24959,9 @@ 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 "Revise o processo de configuração de provedores de serviços em seu provedor de identidade - nesse caso, o GitLab é o \"provedor de serviços\" ou a \"terceiro\"."
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr "Rodar tarefas sem tags"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr "Runners"
-msgid "Runners API"
-msgstr "Runners de API"
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Os corredores podem ser colocados em usuários, servidores e até mesmo em sua máquina local."
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr "Página de runners."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr "Chave SSH pública"
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr "Secreto"
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Segurança"
@@ -24796,6 +25613,9 @@ msgstr "Painel de segurança"
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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr "Ver métricas"
msgid "See the affected projects in the GitLab admin panel"
msgstr "Veja os projetos afetados no painel de administração do GitLab"
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,8 +26011,8 @@ msgstr "Selecionar fuso horário"
msgid "Select all"
msgstr "Selecionar todos"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Selecione um cluster existente do Kubernetes ou crie um novo"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr ""
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Selecionar branch de destino"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Selecione o branch que você deseja definir como o padrão para este projeto. Todas os merges requests e commits serão feitos automaticamente nesse branch, a menos que você especifique um diferente."
-
msgid "Select the custom project template source group."
msgstr "Selecione o grupo de origem dos modelos customizados de projeto."
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,11 +26425,11 @@ msgstr "Configurar CI/CD"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "Configure o Runner %{type} manualmente"
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr "Redefinir minutos usados de pipeline"
msgid "Sherlock Transactions"
msgstr "Transações de Sherlock"
-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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Mostrar a versão mais recente"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Mais lento, mas certifica-se que o espaço de trabalho do projeto está íntegro enquanto clona o repositório do zero para cada tarefa"
-
msgid "Smartcard"
msgstr "Cartão inteligente"
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr "Algo deu errado ao recuperar a lista de %{listType}"
@@ -26581,8 +27395,8 @@ msgstr "Proteção contra spam e anti-bot"
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
-msgstr "Runners Específicos"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr ""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "Especifique um padrão regex de endereço de e-mail para identificar usuários internos padrão."
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Especifique o seguinte URL durante a configuração do Runner:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr "Colocar na lista para commit"
-msgid "Stage & Commit"
-msgstr "Colocar na lista para commit e fazer commit"
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr "Iniciar Terminal Web"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar um %{new_merge_request} a partir dessas alterações"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr "Inicie o Runner!"
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr "Iniciando..."
msgid "Starts %{startsIn}"
msgstr "Inicia %{startsIn}"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Começa em (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Regitre sua mensagem para ativar"
@@ -26926,6 +27731,9 @@ msgstr "Desconhecido"
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr "Cabeçalho e rodapé do sistema"
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Métricas de sistema (Personalizado)"
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "O relacionamento como fork foi removido."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "A etapa de planejamento mostra o tempo que se leva desde a criação de
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ 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 path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "A fase do ciclo de vida do desenvolvimento."
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "A coleção de dados pseudonymizer está desativada. Quando ativada, o GitLab executará uma tarefa em segundo plano que produzirá CSVs com pseudônimos do banco de dados do GitLab que serão carregados no diretório de armazenamento de objetos configurado."
+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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "A etapa de revisão mostra o tempo de criação de uma solicitação de incorporação até sua aceitação. Os dados serão automaticamente adicionados depois que sua primeira solicitação de incorporação for aceita."
-msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr "O roadmap mostra o progresso de seus epics ao longo de uma linha do tempo"
-
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 ""
@@ -28172,7 +29001,7 @@ 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 "O mapa do usuário é um mapeamento dos usuários do FogBugz que participaram de seus projetos para a maneira como seus endereços de e-mail e nomes de usuários serão importados para o GitLab. Você pode alterar isso preenchendo a tabela abaixo."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,17 +29328,26 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
-msgstr "Eles podem ser gerenciados usando o %{link}."
+msgid "These variables are inherited from the parent group."
+msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
@@ -28532,8 +29376,8 @@ 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 "Esta instância do GitLab ainda não fornece nenhum Runner compartilhado. Os administradores da instância podem registrar os Runners compartilhados na área de administração."
+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 ""
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr "Esse aplicativo foi criado por %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Esse aplicativo será capaz de:"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,14 +29532,17 @@ msgstr ""
msgid "This field is required."
msgstr "Este campo é obrigatório."
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Esse grupo"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "Este grupo não fornece nenhum grupo de Runners ainda."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -28712,6 +29571,9 @@ msgstr "Esta tarefa foi atrasada para executar em %{remainingTime}"
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
msgstr "Esta é uma lista de dispositivos com os quais você logou em sua conta. Revogue qualquer sessão que você não reconheça."
+msgid "This is a merge train pipeline"
+msgstr ""
+
msgid "This is a security log of important events involving your account."
msgstr "Este é um registro de segurança de eventos importantes envolvendo a sua conta."
@@ -28835,6 +29697,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Isto significa que você não pode entregar código até que crie um repositório vazio ou importe um existente."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 "Esse merge request está bloqueado."
@@ -28880,8 +29754,8 @@ msgstr ""
msgid "This project"
msgstr "Este projeto"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "Este projeto não pertence a um grupo e, portanto, não pode usar os Runners do grupo."
+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 ""
@@ -28937,6 +29811,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Este Runner somente será executado em Pipelines acionados em branches protegidos"
+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 "Essa configuração pode ser substituída em cada projeto."
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "Esse usuário será o autor de todos os eventos no feed de atividades que são o resultado de uma atualização, como novos branches sendo criados ou novos commits sendo enviados para os branches existentes."
-
msgid "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ msgstr "Para adicionar uma chave SSH, você precisa %{generate_link_start}gerar
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 ""
@@ -29406,6 +30280,9 @@ msgstr "Para conectar um repositório SVN, confira %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Para definir usuários internos, primeiro ative os novos usuários definidos como externos"
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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 "Para começar, insira seu URL do FogBugz e as informações de login abaixo. Nas próximas etapas, você poderá associar usuários e selecionar os projetos que deseja importar."
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr "Para começar, vincule essa página ao seu servidor do Jaeger, ou descubra como %{link_start_tag}instalar o Jaeger%{link_end_tag}"
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr "Para começar a servir suas tarefas, você pode adicionar Runners ao seu grupo"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "Para visualizar o planejamento, adicione uma data de início ou fim para um de seus épicos nesse grupo ou seus subgrupos. No visualizador de meses, apenas épicos do mês passado, mês atual, e dos próximos 5 meses são exibidos."
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr "Hoje"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr "Alternar prêmio de emoji"
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Alternar navegação"
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr "Alternar :%{name}: prêmio de emoji."
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ msgstr ""
msgid "Transfer project"
msgstr "Transferir projeto"
+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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,8 +30687,8 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr "Pipelines de disparo para atualizações de espelho"
-msgid "Trigger pipelines when branches or tags are updated from 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 "Ative os pipelines quando os branches ou tags forem atualizados a partir do repositório upstream. Dependendo da atividade do repositório upstream, isso pode aumentar bastante a carga nos seus runners de CI. Ative isso somente se você sabe que eles podem manipular a carga."
+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 ""
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr "Desarquivar projeto"
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr "Atualizando"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Use o Balcão de Atendimento para se conectar com seus usuários (por exemplo, para oferecer suporte ao cliente) por email dentro do GitLab"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,8 +31440,11 @@ msgstr "Use uma linha por URI"
msgid "Use template"
msgstr "Utilizar modelo"
-msgid "Use the following registration token during setup:"
-msgstr "Use o seguinte token de registro durante a configuração:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "Utilizar configuração de notificação global"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr "Usuários"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ msgstr ""
msgid "Variables"
msgstr "Variáveis"
+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 "Várias configurações de registry container."
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "Vendo commit"
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Webhooks"
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr "Quando ativado, os usuários não podem usar o GitLab até que os termos
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 merge requests and commits in the default branch close, any issues they reference also close."
+msgstr ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "Quando:"
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "Você pode %{linkStart}visualizar o blob%{linkEnd} em vez disso."
-
msgid "You can also create a project from the command line."
msgstr "Você também pode criar um projeto a partir da linha de comando."
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Você pode facilmente contribuir para eles pedindo para se juntar nesses grupos."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Você pode instalar facilmente um Runner em um cluster Kubernetes. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 "Agora você pode enviar um merge request para fazer esta mudança no projeto original."
+msgid "You can only %{action} files when you are on a branch"
+msgstr ""
+
msgid "You can only edit files when you are on a branch"
msgstr "Você só pode editar arquivos quando estiver em um branch"
@@ -32153,7 +33069,7 @@ msgstr "Você pode resolver o conflito de merge usando o modo Interativo, escolh
msgid "You can see your chat accounts."
msgstr "Você pode ver suas contas de bate-papo."
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr "Você não tem permissão"
@@ -32489,6 +33411,9 @@ msgstr "YouTube"
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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "Sua mensagem aqui"
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 "um usuário excluído"
@@ -32857,9 +33791,15 @@ msgstr "nome da branch"
msgid "by"
msgstr "por"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "dia"
msgstr[1] "dias"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr "Por favor, restaurar ou usar um branch %{missingBranchName} diferente"
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 "%{metricsLinkStart} Memória %{metricsLinkEnd} uso %{emphasisStart} diminuição %{emphasisEnd} de %{memoryFrom}MB para %{memoryTo}MB"
@@ -33675,9 +34629,6 @@ msgstr "Fazer merge"
msgid "mrWidget|Merge failed."
msgstr "Falha ao fazer merge."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr "Fazer merge localmente"
@@ -33747,8 +34698,8 @@ msgstr "Não houve merge para as mudanças em"
msgid "mrWidget|The changes will be merged into"
msgstr "Será feito merge das alterações em"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr "A pipeline para este merge request falhou. Por favor, tente re-executar a tarefa ou faça push de um novo commit para corrigir a falha"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "O HEAD do branch origem foi modificado recentemente. Por favor, recarregue a página e revise as alterações antes de realizar o merge"
@@ -33828,6 +34779,9 @@ msgstr "para ser realizado merge automaticamente quando o pipeline for bem suced
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 9abb1a593e7..a102819d795 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste fixo"
msgstr[1] "%d resultados do teste fixos"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,16 +1044,16 @@ msgstr ""
msgid ", or "
msgstr ", ou "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr "- O executador está ativo e pode processar novos trabalhos"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- O executador está em pausa e não receberá nenhum trabalho novo"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "Um ramo padrão não pode ser escolhido para um projeto vazio."
msgid "A deleted user"
msgstr "Um utilizador apagado"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Um projeto é onde armazenas os teus ficheiros (repositório), planeias o teu trabalho (problemas), e publicas a tua documentação (wiki), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
msgid "Add a comment to this line"
msgstr ""
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Notas de administração"
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr "Domínio Auto DevOps"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Ativar executadores compartilhados aos novos projetos"
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Nenhum pipeline necessário"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Configuração de pipeline necessária"
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Não é possível desbloquear utilizadores bloqueados em LDAP"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr "Apagar utilizador"
msgid "AdminUsers|Delete user and contributions"
msgstr "Apagar utilizador e as suas contribuições"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Externo"
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr "Alertas"
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,8 +2930,8 @@ msgstr ""
msgid "Allow projects within this group to use Git LFS"
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 acesso público às pipelines e detalhes do trabalho, incluindo registos de saída e artefactos"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Permitir renderização de diagramas PlantUML em documentos Asciidoc."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Permissão para falhar"
@@ -2991,6 +3035,9 @@ msgstr "Quantidade de tempo (em horas) que os utilizadores podem ignorar a confi
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 ""
@@ -3018,6 +3065,9 @@ msgstr "Ocorreu um erro"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr "Ancestrais"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anónimo"
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr "Aplicar sugestão"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ msgstr "Projeto arquivado! Repositório e outros recursos de projeto são soment
msgid "Archived projects"
msgstr "Projetos arquivados"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+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?"
@@ -3778,15 +3828,18 @@ 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 registration token?"
-msgstr "Tens a certeza de que queres recriar o token de registo?"
-
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?"
+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 ""
@@ -3856,8 +3909,8 @@ msgstr "Token de Acesso Pessoal do Utilizador. O utilizador deve ter acesso à t
msgid "Ascending"
msgstr "Ascendente"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "Pede ao responsável do grupo para configurar um grupo Executador."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL de serviço ao consumidor de asserção"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "Atribui uma cor personalizada, como #FF0000"
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr "Atribuir etiquetas"
@@ -4133,9 +4183,6 @@ msgstr "Autorizar %{link_to_client} a usar a tua conta?"
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "Autorizado %{new_chat_name}"
@@ -4160,8 +4207,8 @@ msgstr "Auto DevOps, artefacto de executadores e trabalho"
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Cancelar, automaticamente, os pipelines redundantes pendentes"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4259,17 +4306,17 @@ msgstr "Disponível"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "Executadores de grupo, disponíveis: %{runners}}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "Executadores compartilhados disponíveis:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "Executadores específicos disponíveis"
@@ -4409,25 +4456,25 @@ msgstr "Tem cuidado. Renomear o repositório de um projeto pode ter efeitos secu
msgid "Begin with the selected commit"
msgstr "Começar com o envio selecionado"
-msgid "Below are examples of regex for existing tools:"
-msgstr "Abaixo estão exemplos de regex para ferramentas existentes:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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 ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Faturação"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,11 +4483,17 @@ 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 Gold."
-msgstr "Aprende mais sobre cada plano ao ler o nosso %{faq_link} ou inicia uma avaliação gratuita de 30 dias do GitLab.com Gold."
+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 ""
@@ -4460,6 +4513,9 @@ msgstr "Este grupo utiliza o plano de associados com o teu grupo pai."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Para gerir o plano para este grupo, visita a secção de faturação de %{parent_billing_page_link}."
+msgid "BillingPlans|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 ""
@@ -4469,6 +4525,9 @@ 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 "perguntas frequentes"
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Colapsar"
@@ -4792,6 +4857,9 @@ msgstr "definições do projeto"
msgid "Branches|protected"
msgstr "protegido"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr "Incorporado"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ msgstr ""
msgid "By %{user_name}"
msgstr "Por %{user_name}"
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr "Por padrão, o GitLab envia emails em formatos HTML e texto simples para
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 default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "por"
@@ -4936,6 +5019,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "Configuração de CI/CD"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD para um repositório externo"
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Canary Deploymentss é uma estratégia CI popular, onde uma pequena porção da frota é atualizada para a nova versão da tua aplicação."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr "Alterar caminho"
msgid "Change permissions"
msgstr "Alterar permissões"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Reverter"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Verifica a %{docs_link_start}documentação%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Escolhe qualquer cor."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Escolher um ficheiro…"
@@ -5599,6 +5694,9 @@ msgstr "Escolhe o nível de visibilidade, ativa/desativa os recursos do projeto
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 "Escolhe quais repositórios desejas conectar e executar pipelines de CI/CD."
@@ -5758,12 +5856,24 @@ msgstr "Etiqueta de classificação (opcional)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "está indisponível: %{reason}"
+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 "Limpar"
@@ -5806,8 +5916,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Clica no botão abaixo para começar o processo de instalação ao navegar para a página do Kubernetes"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "Clica para expandir."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr "Os responsáveis do grupo podem registar executadores de grupo no %{link
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "Responder..."
@@ -17652,15 +18383,9 @@ msgstr "Nenhum ficheiro encontrado"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr "Novo objetivo"
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr "Nenhum modelo"
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Outros Rótulos"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr "Solicitar que os utilizadores enviem chaves SSH"
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr "Repor os minutos de pipeline que foram usados"
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar um %{new_merge_request} a partir destas alterações"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ msgstr "A etapa do problema mostra o tempo necessário para criar um problema pa
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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "A coleta de dados do pseudomizador está desativada. Quando ativado, o GitLab executará um trabalho em segundo produzir que produzirá CSVs com pseudónimo da base de dados do GitLab que serão enviados no diretório de armazenamento de objetos configurados."
+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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "A fase de revisão mostra a hora do primeiro envio para criar o envio de mesclagem. Os dados serão adicionados, automaticamente,, assim que criares o teu primeiro pedido de mesclagem."
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr "Este é um registo de segurança de eventos importantes que envolvem a tua conta."
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr "A atualizar"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Enviar ficheiro CSV"
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr "Também podes enviar ficheiros existentes do teu computador ao usar as i
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 "um utilizador apagado"
@@ -32857,9 +33791,15 @@ msgstr "nome do ramo"
msgid "by"
msgstr ""
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index cab7261fb8a..f117e1678ab 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:54\n"
+"PO-Revision-Date: 2021-02-01 17:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -226,6 +226,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -430,10 +436,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -787,6 +793,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -985,6 +994,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1108,16 +1120,16 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1339,6 +1351,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1357,6 +1372,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1408,6 +1429,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1417,9 +1441,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1429,7 +1450,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1444,6 +1465,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1708,15 +1732,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1975,6 +1999,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2005,9 +2032,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2041,7 +2065,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2065,6 +2089,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2074,7 +2101,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2104,9 +2137,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2128,6 +2158,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2278,6 +2311,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2305,6 +2341,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2413,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2842,7 +2884,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2983,7 +3025,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3034,6 +3076,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3085,6 +3130,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3328,6 +3379,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3499,6 +3553,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3613,12 +3670,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3787,7 +3838,7 @@ 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}"
+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?"
@@ -3877,15 +3928,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3955,7 +4009,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3979,9 +4033,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4234,9 +4285,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4261,7 +4309,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4360,16 +4408,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4510,25 +4558,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4537,10 +4585,16 @@ 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 Gold."
+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}."
@@ -4561,6 +4615,9 @@ 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 ""
@@ -4570,6 +4627,9 @@ 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 ""
@@ -4585,6 +4645,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4672,10 +4735,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4699,6 +4762,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4894,6 +4960,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4933,16 +5002,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4993,6 +5071,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5002,6 +5083,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5038,6 +5122,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5146,9 +5233,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5299,6 +5383,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5341,6 +5431,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5365,6 +5458,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5467,6 +5563,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5680,9 +5779,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5701,6 +5797,9 @@ 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 ""
@@ -5860,12 +5959,24 @@ 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 ""
@@ -5908,7 +6019,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7087,7 +7198,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7105,9 +7216,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7144,6 +7252,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7366,6 +7477,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7540,9 +7657,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7654,9 +7768,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7684,6 +7804,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7777,6 +7906,9 @@ 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 ""
@@ -7804,9 +7936,15 @@ 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 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 ""
@@ -7822,9 +7960,15 @@ 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 ""
@@ -8002,6 +8146,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8056,6 +8203,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8356,12 +8506,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8377,16 +8539,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8398,9 +8557,15 @@ 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 ""
@@ -8416,6 +8581,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8431,6 +8599,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8530,10 +8701,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8560,7 +8731,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8569,9 +8740,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8644,7 +8812,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8857,7 +9025,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8887,6 +9055,12 @@ 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 ""
@@ -8899,6 +9073,9 @@ 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 ""
@@ -8911,6 +9088,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8926,6 +9106,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8950,7 +9133,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8962,9 +9145,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9004,6 +9184,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9013,6 +9199,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9022,9 +9211,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9040,6 +9235,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9049,6 +9247,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9061,6 +9262,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9355,7 +9559,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9709,6 +9913,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9892,7 +10123,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9943,25 +10174,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9988,22 +10219,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10012,24 +10240,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10051,18 +10279,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10120,7 +10342,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10414,9 +10636,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10645,6 +10864,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10711,6 +10939,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10720,6 +10951,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10759,7 +10993,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10798,7 +11032,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10861,15 +11095,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10966,13 +11206,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11263,6 +11500,9 @@ 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 ""
@@ -11278,6 +11518,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11668,9 +11914,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11806,15 +12049,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11938,6 +12187,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12121,9 +12373,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12640,10 +12889,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12667,12 +12928,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12748,7 +13003,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12796,6 +13051,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13210,7 +13468,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13240,9 +13498,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13279,6 +13534,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13363,9 +13621,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13393,6 +13648,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13666,9 +13924,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13684,9 +13939,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13738,6 +13990,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13747,6 +14005,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13771,6 +14032,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14170,9 +14437,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14239,6 +14503,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14479,6 +14746,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14590,9 +14863,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14608,18 +14878,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14869,15 +15136,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15013,9 +15625,39 @@ 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 ""
@@ -15097,7 +15739,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15139,10 +15781,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15169,9 +15811,21 @@ msgstr[2] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15277,6 +15931,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15307,6 +15964,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15316,12 +15979,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,6 +16015,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15373,6 +16045,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15460,6 +16135,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15520,6 +16198,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15775,6 +16456,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15829,9 +16516,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15871,6 +16555,9 @@ 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 ""
@@ -15973,24 +16660,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16006,6 +16711,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16018,9 +16726,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16099,6 +16819,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16138,7 +16861,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16213,6 +16936,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16240,6 +16966,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16426,7 +17155,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16510,7 +17239,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16531,9 +17260,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16840,6 +17566,9 @@ msgstr[2] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17014,9 +17743,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17041,6 +17767,12 @@ 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 ""
@@ -17065,9 +17797,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17110,6 +17839,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17302,12 +18034,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17347,9 +18082,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17392,6 +18124,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17419,9 +18154,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17440,9 +18172,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17539,6 +18268,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17632,6 +18364,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17713,9 +18448,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17782,15 +18514,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18190,6 +18916,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18361,6 +19090,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18412,9 +19144,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18583,9 +19312,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18721,12 +19447,6 @@ 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 ""
@@ -18745,6 +19465,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18799,6 +19525,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19048,7 +19777,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19165,6 +19894,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19258,6 +19990,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19333,9 +20068,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19345,6 +20077,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19720,6 +20455,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19729,12 +20467,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19795,10 +20539,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19810,9 +20554,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19864,10 +20617,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19906,7 +20659,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19924,9 +20677,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19945,7 +20695,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20053,15 +20803,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20236,9 +20986,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20257,6 +21004,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20329,9 +21079,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20347,6 +21094,9 @@ 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 ""
@@ -20485,6 +21235,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20599,6 +21352,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20665,6 +21421,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20677,6 +21436,9 @@ 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 ""
@@ -20845,9 +21607,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20860,9 +21619,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20884,6 +21640,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20998,6 +21757,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21667,12 +22429,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21718,9 +22483,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22003,6 +22765,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22420,6 +23185,9 @@ 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|What are badges?"
msgstr ""
@@ -22543,7 +23311,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22918,6 +23686,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22966,6 +23737,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23002,6 +23776,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23011,9 +23788,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23023,7 +23797,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23242,6 +24016,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23356,12 +24133,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23389,21 +24175,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23500,9 +24274,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23596,6 +24367,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23845,6 +24619,12 @@ 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] ""
+msgstr[2] ""
+
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] ""
@@ -24013,6 +24793,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24148,7 +24931,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24271,6 +25054,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24319,6 +25105,9 @@ 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 ""
@@ -24361,6 +25150,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24406,6 +25198,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24427,21 +25222,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24454,21 +25237,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24490,24 +25288,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24580,6 +25393,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24937,6 +25753,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24952,6 +25771,9 @@ 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 ""
@@ -25111,9 +25933,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25177,9 +25996,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25288,13 +26104,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25354,7 +26170,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25384,6 +26200,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25441,9 +26260,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25726,6 +26542,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25765,10 +26584,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25783,9 +26602,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25930,9 +26746,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25987,6 +26800,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26227,9 +27043,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26374,6 +27187,9 @@ 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 %{listType} list"
msgstr ""
@@ -26740,7 +27556,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26749,9 +27565,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26770,9 +27583,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26827,7 +27637,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26860,9 +27670,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26872,7 +27679,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26899,15 +27706,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27085,6 +27892,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27496,6 +28306,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27520,9 +28333,15 @@ 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 ""
@@ -27697,15 +28516,18 @@ msgstr[2] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27760,10 +28582,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28096,9 +28918,6 @@ msgstr[2] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28153,6 +28972,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28171,6 +28993,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28186,7 +29017,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28204,9 +29038,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28252,6 +29083,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28279,9 +29113,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28336,7 +29167,7 @@ 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 an approval"
+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"
@@ -28444,7 +29275,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28492,6 +29323,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28504,6 +29338,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28657,16 +29494,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28696,7 +29542,7 @@ 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."
+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."
@@ -28711,22 +29557,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28741,13 +29599,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28825,9 +29686,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28840,13 +29698,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28876,6 +29737,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28999,6 +29863,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29008,6 +29875,15 @@ 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 ""
@@ -29044,7 +29920,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29101,6 +29977,9 @@ 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 ""
@@ -29134,18 +30013,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29557,6 +30430,9 @@ 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 ""
@@ -29572,6 +30448,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29581,6 +30460,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29614,6 +30496,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29629,7 +30514,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29647,12 +30532,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29668,9 +30547,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29689,6 +30565,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29716,6 +30595,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29746,6 +30628,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29836,6 +30721,9 @@ 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 ""
@@ -29893,7 +30781,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29905,7 +30793,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29932,7 +30820,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29947,7 +30835,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29956,6 +30844,9 @@ 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 ""
@@ -29965,7 +30856,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29992,7 +30883,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30208,7 +31102,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30466,7 +31360,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30487,6 +31381,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30685,12 +31582,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30706,7 +31609,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30820,7 +31726,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30979,21 +31885,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31057,9 +31957,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31084,6 +31981,15 @@ 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 ""
@@ -31255,6 +32161,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31633,6 +32542,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31642,6 +32557,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31777,10 +32695,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31798,7 +32716,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31807,7 +32725,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31828,6 +32746,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31837,6 +32758,9 @@ msgstr[2] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32197,9 +33121,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32221,9 +33142,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32248,9 +33166,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32272,6 +33187,9 @@ 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 ""
@@ -32287,15 +33205,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32323,7 +33241,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32464,6 +33382,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32476,6 +33397,9 @@ 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 no permissions"
msgstr ""
@@ -32659,6 +33583,9 @@ 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 ""
@@ -32695,13 +33622,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32857,6 +33784,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32941,6 +33871,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33028,9 +33964,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33343,6 +34285,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33385,8 +34330,11 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33481,6 +34429,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33727,6 +34678,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33853,9 +34810,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33925,7 +34879,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34234,6 +35191,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34372,6 +35332,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 43acbd904e3..dd1b7078b34 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:01\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr " %{project_name}#%{issuable_iid} &middot; %{author} открыл %{issuable_created}"
@@ -252,6 +252,13 @@ msgstr[1] "%d иÑправленных результатов теÑта"
msgstr[2] "%d иÑправленных результатов теÑта"
msgstr[3] "%d иÑправленные результаты теÑта"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d группа выбрана"
@@ -486,10 +493,10 @@ msgstr "тема %{authorsName}"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr "%{reportType} обнаружено %{totalStart}%{total}%{totalEnd} по
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr "%{reportType} не обнаружено %{totalStart} ни одной %{totalEnd} уÑзвимоÑти."
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr "&lt; 1 чаÑ"
@@ -1183,6 +1196,9 @@ msgstr "+ещё %{tags}"
msgid ", or "
msgstr ", или "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- Событие"
@@ -1190,11 +1206,8 @@ msgstr[1] "- СобытиÑ"
msgstr[2] "- СобытиÑ"
msgstr[3] "- СобытиÑ"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Runner активен и может обрабатывать любые новые заданиÑ"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner приоÑтановлен и не получит новые заданиÑ"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1431,6 +1444,9 @@ msgstr "Ð”Ð»Ñ Ð¿ÑƒÑтого проекта Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð±Ñ€Ð°Ñ‚ÑŒ ветÐ
msgid "A deleted user"
msgstr "Удаленный пользователь"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Файл был изменён."
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Ð’ проекте вы размещаете Ñвои файлы (репозиторий), планируете Ñвою работу (обÑуждениÑ), и публикуете документацию (wiki), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "РегулÑрное выражение, которое будет иÑпользоватьÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка результатов Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами в логах заданиÑ. ОÑтавьте пуÑтым Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ"
-
msgid "A secure token that identifies an external storage request."
msgstr "Токен безопаÑноÑти, который идентифицирует Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ хранилища."
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr "ТРЕБУЕТСЯ ДЕЙСТВИЕ: Что-то пошло не так
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "Справка по API"
@@ -1801,15 +1826,15 @@ msgstr "Добавьте кнопку Grafana на боковой панели Ð
msgid "Add a To Do"
msgstr "Добавить в ÑпиÑок задач"
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr "Добавить общий комментарий Ð´Ð»Ñ Ñтого %{noteableDisplayName}."
@@ -2068,6 +2093,9 @@ msgstr "Режим админиÑтратора отключен"
msgid "Admin mode enabled"
msgstr "Режим админиÑтратора включен"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Заметки админиÑтратора"
@@ -2098,9 +2126,6 @@ msgstr "Developer"
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr "Групп : %{number_of_groups}"
-
msgid "AdminArea|Guest"
msgstr "Guest"
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr "Owner"
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr "Ð’Ñего пользователей"
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "СтатиÑтика пользователей"
@@ -2167,7 +2195,13 @@ msgstr "Пользователи Ñ Ð½Ð°Ð¸Ð²Ñ‹Ñшей ролью"
msgid "AdminArea|Users without a Group and Project"
msgstr "Пользователи без группы и проекта"
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr "Домен Auto DevOps"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "ИÑпользовать общие Runner'Ñ‹ в новых проектах"
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "Ðе требуетÑÑ ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Ð¢Ñ€ÐµÐ±ÑƒÐµÐ¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñборочной линии"
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Ðе удалоÑÑŒ разблокировать заблокированных пользователей LDAP"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Отключить"
@@ -2398,6 +2435,9 @@ msgstr "Удалить пользователÑ"
msgid "AdminUsers|Delete user and contributions"
msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ внеÑённые им изменениÑ"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Внешние"
@@ -2506,6 +2546,9 @@ msgstr "Пользователь не Ñможет получить доÑтуп
msgid "AdminUsers|User will not be able to login"
msgstr "Пользователь не Ñможет войти"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "Когда пользователь в Ñледующий раз войдёт в ÑиÑтему, его ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ Ñнова Ñтанет полноÑтью активной"
@@ -2936,8 +2979,8 @@ msgstr ""
msgid "Alerts"
msgstr "ОповещениÑ"
-msgid "Alerts endpoint"
-msgstr "Точка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ð¹"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Разрешено ограничение доменов Ñлектронной почты только Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿ верхнего уровнÑ"
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr "Произошла ошибка"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Произошла ошибка при добавлении черновика в тему."
@@ -3422,6 +3474,9 @@ msgstr "Произошла ошибка при загрузке файла."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Произошла ошибка при загрузке файла. ПожалуйÑта, попробуйте ещё раз позже."
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "Произошла ошибка при загрузке изменений запроÑа на ÑлиÑние."
@@ -3432,7 +3487,7 @@ msgid "An error occurred while loading the merge request."
msgstr ""
msgid "An error occurred while loading the pipeline."
-msgstr ""
+msgstr "Произошла ошибка при загрузке Ñборочной линии."
msgid "An error occurred while loading the pipelines jobs."
msgstr ""
@@ -3537,7 +3592,7 @@ msgid "An example project for managing Kubernetes clusters integrated with GitLa
msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
-msgstr ""
+msgstr "Пример, показывающий, как иÑпользовать Jsonnet Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸Ñ‡ÐµÑкими дочерними Ñборочными линиÑми GitLab"
msgid "An instance-level serverless domain already exists."
msgstr "Домен Serverless ÑƒÑ€Ð¾Ð²Ð½Ñ ÑкземплÑра уже ÑущеÑтвует."
@@ -3573,7 +3628,7 @@ msgid "An unknown error occurred while loading this graph."
msgstr ""
msgid "An unknown error occurred."
-msgstr ""
+msgstr "Произошла неизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°."
msgid "Analytics"
msgstr "Ðналитика"
@@ -3593,6 +3648,9 @@ msgstr "Ðнализируйте ваш иÑходный код на предмÐ
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Ðноним"
@@ -3702,17 +3760,11 @@ msgid "Apply a template"
msgstr "Применение шаблона"
msgid "Apply changes"
-msgstr ""
+msgstr "Применить изменениÑ"
msgid "Apply suggestion"
msgstr "Применить предложение"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,8 +3937,8 @@ 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}"
-msgstr "Ðрхивирование Ñтого проекта Ñделает его полноÑтью недоÑтупным Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ. Он не будет отображатьÑÑ Ð² панели ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ в поиÑке. %{strong_start}Ð’ репозиторий проекта Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ вноÑить коммиты, а также невозможно будет Ñоздавать обÑуждениÑ, комментарии и прочее.%{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
@@ -3976,15 +4028,18 @@ msgstr "Ð’Ñ‹ уверены, что вы хотите удалить Ñту ид
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот токен проверки работоÑпоÑобноÑти?"
+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 ""
@@ -4054,8 +4109,8 @@ msgstr "Личный токен доÑтупа пользователÑ. ПолÑ
msgid "Ascending"
msgstr "По возраÑтанию"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "ПопроÑите Ñопровождающего вашей группы наÑтроить групповой обработчик заданий."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr ""
@@ -4078,9 +4133,6 @@ msgstr "Ðазначить на "
msgid "Assign custom color like #FF0000"
msgstr "Ðазначьте пользовательÑкий цвет, например #FF0000"
-msgid "Assign epic"
-msgstr "Ðазначить цель"
-
msgid "Assign labels"
msgstr "Ðазначить метки"
@@ -4335,9 +4387,6 @@ msgstr "ÐвторизуйтеÑÑŒ %{link_to_client} Ð´Ð»Ñ Ð¸Ñпользова
msgid "Authorize %{user} to use your account?"
msgstr "Разрешить %{user} иÑпользовать вашу учетную запиÑÑŒ?"
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "Ðвторизован %{new_chat_name}"
@@ -4362,8 +4411,8 @@ msgstr "Auto DevOps, обработчики и артефакты заданий
msgid "Auto stop successfully canceled."
msgstr "ÐвтоматичеÑÐºÐ°Ñ Ð¾Ñтановка уÑпешно отменена."
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "ÐвтоматичеÑÐºÐ°Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð° избыточных, ожидающих Ñборочных линий"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4390,7 +4439,7 @@ msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Подробнее по ÑÑылке %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps была включена и будет иÑпользоватьÑÑ, еÑли не найдётÑÑ Ð°Ð»ÑŒÑ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð½Ð¾Ð³Ð¾ файла конфигурации CI."
msgid "AutoRemediation| 1 Merge Request"
msgstr ""
@@ -4461,17 +4510,17 @@ msgstr "ДоÑтупен"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "ДоÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° runner'ов: %{runners}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "ДоÑтупные общие Runner'Ñ‹:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "ДоÑтупные ÑпецифичеÑкие runner'Ñ‹"
@@ -4611,26 +4660,26 @@ msgstr "Будьте оÑторожны. Переименование репоз
msgid "Begin with the selected commit"
msgstr "Ðачать Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ коммита"
-msgid "Below are examples of regex for existing tools:"
-msgstr "Ðиже приведены примеры регулÑрных выражений Ð´Ð»Ñ ÑущеÑтвующих инÑтрументов:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "Ðиже приведены отпечатки ключей SSH текущего ÑкземплÑра."
msgid "Below you will find all the groups that are public."
msgstr "Ðиже показаны вÑе открытые группы."
-msgid "Bi-weekly code coverage"
+msgid "Beta"
msgstr ""
-msgid "Billable Users:"
+msgid "Bi-weekly code coverage"
+msgstr "Двухнедельное покрытие кода"
+
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Тарифы"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name} ÑÐµÐ¹Ñ‡Ð°Ñ Ð¸Ñпользует тарифный план %{plan_name}."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "@%{user_name}, ÑÐµÐ¹Ñ‡Ð°Ñ Ð²Ñ‹ иÑпользуете тарифный план %{plan_name}."
@@ -4638,11 +4687,17 @@ msgstr "@%{user_name}, ÑÐµÐ¹Ñ‡Ð°Ñ Ð²Ñ‹ иÑпользуете тарифный
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 "ЕÑли вы хотите понизить уровень Ñвоего тарифного плана, пожалуйÑта, ÑвÑжитеÑÑŒ Ñо %{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 Gold."
-msgstr "Узнайте больше о каждом плане, прочитав %{faq_link}, или начните иÑпользовать беÑплатный 30-дневный пробный период GitLab.com Gold."
+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 "Узнайте больше о каждом тарифе, поÑетив нашу %{pricing_page_link}."
@@ -4662,6 +4717,9 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ñ€Ð¸Ñ„Ð½Ñ‹Ð¼ планом Ñтой группы поÑетите раздел тарификации %{parent_billing_page_link}."
+msgid "BillingPlans|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 ""
@@ -4671,6 +4729,9 @@ msgstr ""
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "%{price_per_year} в год"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "чаÑто задаваемые вопроÑÑ‹"
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Улучшить"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Свернуть"
@@ -4996,6 +5063,9 @@ msgstr "наÑтройках проекта"
msgid "Branches|protected"
msgstr "защищена"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr "Ð’Ñтроенный"
msgid "Bulk request concurrency"
msgstr "РаÑпараллеливание маÑÑовых запроÑов"
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -5095,6 +5174,9 @@ msgstr "Купить минут Ð´Ð»Ñ CI"
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 ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr "По умолчанию GitLab отправлÑет пиÑьма в фо
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "По умолчанию вÑе проекты и группы будут иÑпользовать глобальные наÑтройки уведомлений."
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "по автору"
@@ -5140,6 +5225,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ CI/CD"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ репозиториÑ"
@@ -5177,7 +5265,7 @@ msgid "CICD|Jobs"
msgstr "ЗаданиÑ"
msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Auto DevOps запуÑкаетÑÑ Ð¿Ñ€Ð¸ отÑутÑтвии альтернативного файла конфигурации CI."
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr "Сборка Auto DevOps будет запущена, еÑли не будет найден иной файл конфигурации CI."
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr "Canary"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Ð Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Canary - популÑÑ€Ð½Ð°Ñ Ñтратегии CI, когда Ð½ÐµÐ±Ð¾Ð»ÑŒÑˆÐ°Ñ Ñ‡Ð°ÑÑ‚ÑŒ аудитории получает новую верÑию приложениÑ."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr "Изменить путь"
msgid "Change permissions"
msgstr "Изменить разрешениÑ"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr "Изменить ÑтатуÑ"
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Подобрать"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Отменить"
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "Изменён ответÑтвенный(ые)."
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Подробнее в %{docs_link_start}документации%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr "Проверьте ваши образы Docker на наличие извеÑтных уÑзвимоÑтей."
@@ -5782,9 +5882,6 @@ msgstr "Выберите любой цвет."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Выберите файл…"
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ 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 "ОчиÑтить"
@@ -6010,8 +6122,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "Ðажмите кнопку ниже, чтобы начать процеÑÑ ÑƒÑтановки, Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ Ð½Ð° Ñтраницу Kubernetes"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "Ðажмите, чтобы развернуть."
@@ -7106,7 +7218,7 @@ msgid "ClusterIntegration|You should select at least two subnets"
msgstr "Ðеобходимо выбрать как минимум две подÑети"
msgid "ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days."
-msgstr ""
+msgstr "Ваш клаÑтер Elasticsearch будет переÑоздан в ходе Ñтого апгрейда. Журналы будут переиндекированы, а архивные журналы хоÑтов, удалённых за поÑледние 30 дней, потерÑны."
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ должна иметь %{link_to_kubernetes_engine}"
@@ -7166,13 +7278,13 @@ msgid "Code"
msgstr "Код"
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
-msgstr ""
+msgstr "Покрытие кода: %{coveragePercentage}%{percentSymbol}"
msgid "Code Coverage| Empty code coverage data"
-msgstr ""
+msgstr "Ðет данных о покрытии кода"
msgid "Code Coverage|Couldn't fetch the code coverage data"
-msgstr ""
+msgstr "Ðе удалоÑÑŒ получить данные Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ ÐºÐ¾Ð´Ð°"
msgid "Code Owner"
msgstr ""
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Шаблон"
-msgid "Cohorts"
-msgstr "Когорты"
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Свернуть панель"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "СвÑзатьÑÑ Ñ Ð¾Ñ‚Ð´ÐµÐ»Ð¾Ð¼ продаж Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ"
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr "Скопировать команду входа"
msgid "ContainerRegistry|Copy push command"
msgstr "Скопировать команду Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr "Копировать SHA-Ñумму коммита"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr "Скопировать окружение"
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8272,10 +8423,10 @@ msgstr ""
msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано по покрытию %d заданиÑ."
+msgstr[1] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано уÑреднением Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ %d заданий."
+msgstr[2] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано уÑреднением Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ %d заданий."
+msgstr[3] "Покрытие кода Ð´Ð»Ñ Ñтой Ñборочной линии было раÑÑчитано уÑреднением Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ %d заданий."
msgid "Create"
msgstr "Создать"
@@ -8374,7 +8525,7 @@ msgid "Create group label"
msgstr "Создать метку группы"
msgid "Create issue"
-msgstr ""
+msgstr "Создать обÑуждение"
msgid "Create iteration"
msgstr "Создать итерацию"
@@ -8463,12 +8614,24 @@ msgstr "Ñоздать перÑональный токен доÑтупа"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Создан"
@@ -8637,12 +8809,12 @@ msgstr ""
msgid "Current Branch"
msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð’ÐµÑ‚ÐºÐ°"
-msgid "Current Plan"
-msgstr "Текущий план"
-
msgid "Current Project"
msgstr "Текущий проект"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "Текущий узел"
@@ -8667,8 +8839,8 @@ msgstr "Профиль"
msgid "CurrentUser|Settings"
msgstr "ÐаÑтройки"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "Ðачать пробный период Gold"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr ""
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr "ПользовательÑкий путь конфигурации CI"
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr "ÐаÑтройте параметры Ñзыка и региона."
msgid "Customize name"
msgstr "ÐаÑтройка имени"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ msgstr "%{firstProject} и %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest}, и %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Create new segment"
-msgstr ""
-
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,8 +10457,8 @@ msgstr "Отключить"
msgid "Disable for this project"
msgstr "Отключить Ð´Ð»Ñ Ñтого проекта"
-msgid "Disable group Runners"
-msgstr "Выключить групповые обработчиков заданий"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr "Отключить общий доÑтуп к Ñайтам Pages"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Редактировать"
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr "ÑброÑить Ñто"
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr "Включить ограничение на количеÑтво входÑщих оповещений в Управлении инцидентами"
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,8 +11109,8 @@ msgstr "Включить функцию выбора ÑƒÑ€Ð¾Ð²Ð½Ñ Ð´Ð¾Ñтупа
msgid "Enable for this project"
msgstr "Включить Ð´Ð»Ñ Ñтого проекта"
-msgid "Enable group Runners"
-msgstr "Включить групповые обработчики заданий"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr ""
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr "Включить прокÑи"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ñ€ÐµÐ½Ð´ÐµÑ€Ð¸Ð½Ð³Ð°: %{
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "ЗаканчиваетÑÑ Ð² (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr "ÐŸÑ€Ð¸Ð½ÑƒÐ´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ð° от перепривÑÐ·Ñ‹Ð²Ð°Ð½Ð¸Ñ DNS"
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
msgstr ""
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "Переменные Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроены админиÑтратором, чтобы быть %{link_start}защищенными%{link_end} по умолчанию"
-
-msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ msgstr "Произошла ошибка при обновлении меток."
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить %{bStart}%{targetIssueTitle}%{bEnd} из %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11393,6 +11634,12 @@ msgstr "Удалить цель"
msgid "Epics|Remove issue"
msgstr "Удалить обÑуждение"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "Показать еще"
@@ -11783,9 +12030,6 @@ msgstr "Пример: %{ip_address}. %{read_more_link}."
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr "Пример: Мой поток ценноÑти"
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr "ЭкÑпорт проекта"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "ЭкÑпортировать данный проект Ñо вÑеми ÑоответÑтвующими к нему данными, Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы перенеÑти проект на новую копию GitLab. Как только ÑкÑпорт будет завершён, вы Ñможете импортировать файл через Ñтраницу нового проекта."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ ÑÑылку"
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ð¸ в наÑтройке Службы поддержки Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра, пожалуйÑта, обратитеÑÑŒ к админиÑтратору."
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации обратитеÑÑŒ к документации по %{link_start}отключению Seat Link%{link_end}."
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Ð’ чаÑтных проектах: любой пользователь (гоÑÑ‚ÑŒ или выше) может проÑматривать Ñборочные линии и получать доÑтуп к заданиÑм (логам и артефактам)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Ð’ публичных проектах: любой пользователь может проÑматривать Ñборочные линии и получать доÑтуп к заданиÑм (логам и артефактам)"
-
msgid "Forgot your password?"
msgstr "Забыли пароль?"
@@ -12864,7 +13120,7 @@ msgstr "От ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ развертывани
msgid "From merge request merge until deploy to production"
msgstr "От запроÑа на ÑлиÑние до Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² рабочей Ñреде"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Узлы Geo"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr "ÐÐµÐ»ÑŒÐ·Ñ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ оÑновной узел, еÑли еÑÑ‚ÑŒ вторичные"
@@ -13326,8 +13585,8 @@ msgstr "Ð ÐµÐ²Ð¸Ð·Ð¸Ñ git"
msgid "Git shallow clone"
msgstr "ПоверхноÑтное клонирование Git"
-msgid "Git strategy for pipelines"
-msgstr "Команда Git Ð´Ð»Ñ Ñборочных линий"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "Групповые Обработчики Заданий (GitLab Group Runners) могут выполнÑÑ‚ÑŒ код Ð´Ð»Ñ Ð²Ñех проектов в Ñтой группе."
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr "GitLab Ð´Ð»Ñ Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "Может пройти до 30 минут, прежде чем Ñайт Ñтанет доÑтупен поÑле первого развёртываниÑ."
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr "Группа %{group_name} уÑпешно Ñоздана."
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr "Групповые Обработчики Заданий (GitLab Group Runner)"
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr "Ðазвание группы"
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr "Группы Ð´Ð»Ñ Ñинхронизации"
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "ЧаÑто поÑещаемые"
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr "ОчиÑтка уÑпешно запущена"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ОчиÑтка, ÑкÑпорт, путь, перемещение, удаление, архивирование."
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr "ЕÑли длина какого-либо индекÑированного Ð¿Ð¾Ð»Ñ Ð¿Ñ€ÐµÐ²Ñ‹ÑˆÐ°ÐµÑ‚ Ñтот порог, оно будет обрезано до ÑоответÑтвующего количеÑтва Ñимволов, а оÑтавшаÑÑÑ Ñ‡Ð°ÑÑ‚ÑŒ будет иÑключена из индекÑÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ поиÑка. Ðе отноÑитÑÑ Ðº репозиторию и индекÑированию в вики. УÑтановка Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² 0 означает неограниченную длину."
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-msgstr "ЕÑли какое-либо задание превышает порог выделенного времени, оно помечаетÑÑ ÐºÐ°Ðº невыполненное. Ð’Ñ€ÐµÐ¼Ñ Ð²Ð²Ð¾Ð´Ð¸Ñ‚ÑÑ Ð² человекочитаемом формате: например, \"1 hour\". ЕÑли единица времени не указано, Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¸Ð½Ð¸Ð¼Ð°ÐµÑ‚ÑÑ Ð² Ñекундах."
-
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 "ЕÑли пуÑто, уÑтановить разрешенное Ð²Ñ€ÐµÐ¼Ñ ÑущеÑÑ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ€Ð°Ð²Ð½Ñ‹Ð¼ %{instance_level_policy_in_words}, как определено админиÑтратором ÑкземплÑра. ПоÑле уÑтановки, ÑущеÑтвующие токены пользователей данной группы могут быть отозваны."
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr "ЕÑли включено"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
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 order to enable Service Desk for your instance, you must first set up incoming email."
msgstr "Чтобы включить Службу поддержки Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑкземплÑра, Ñначала наÑтройте входÑщую Ñлектронную почту."
-msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr "Инцидент"
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,11 +15903,11 @@ msgstr ""
msgid "Install"
msgstr "УÑтановить"
-msgid "Install GitLab Runner"
-msgstr "УÑтановите GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "УÑтановить Runner на Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
@@ -15291,9 +15934,21 @@ msgstr[3] "ЭкземплÑры"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "Ðеверный пин-код"
@@ -15642,6 +16321,9 @@ msgstr "ПриглаÑить группу"
msgid "Invite member"
msgstr "ПриглаÑить учаÑтников"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr "ОбÑуждениÑми могут быть ошибки, задачи
msgid "Issues closed"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr "ОбÑуждениÑ, упомÑнутые в запроÑах на ÑлиÑние и коммитах в ветви по умолчанию, будут автоматичеÑки закрыты"
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñми, запроÑÑ‹ на ÑлиÑние Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñми и комментариÑми, метками, Ñтапами, Ñниппетами и другими объектами проекта"
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16006,7 +16694,7 @@ msgid "It seems like the Dependency Scanning job ran successfully, but no depend
msgstr "Похоже, работа по Ñканированию завиÑимоÑтей завершилаÑÑŒ уÑпешно, но в вашем проекте не было обнаружено никаких завиÑимоÑтей."
msgid "It seems that there is currently no available data for code coverage"
-msgstr ""
+msgstr "Похоже, что в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ доÑтупных данных о покрытии кода"
msgid "It's you"
msgstr "Это вы"
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð´Ð»Ñ %{noteable_model_name} отключены."
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 "Jira API URL"
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr "СиÑтема отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Jira"
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "Пароль или API токен"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,8 +16984,8 @@ msgstr "Ðртефакты заданиÑ"
msgid "Job|Job has been erased"
msgstr "Задание было удалено"
-msgid "Job|Job has been erased by"
-msgstr "Задание было удалено пользователем"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "ОÑтавить"
@@ -16335,6 +17059,9 @@ msgstr "Только Ñ"
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr "Глобальные ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr "Показать/Ñкрыть панель производительноÑти"
@@ -16549,8 +17279,8 @@ msgstr ""
msgid "Last edited %{date}"
msgstr "Дата поÑледнего изменениÑ: %{date}"
-msgid "Last edited by %{name}"
-msgstr "Ðвтор поÑледнего изменениÑ: %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "Узнайте о GitLab"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Узнайте больше об \"Auto DevOps\""
-msgid "Learn more about Kubernetes"
-msgstr "Подробнее о Kubernates"
-
msgid "Learn more about License-Check"
msgstr "Узнайте больше о проверке лицензии"
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr "СЛИТО"
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 "Показать только изменениÑ"
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr "Управление двухфакторной аутентификац
msgid "Manage your license"
msgstr "УправлÑйте Ñвоей лицензией"
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr "МакÑимальный размер артефактов (Мбайт)"
@@ -17477,9 +18213,6 @@ msgstr "МакÑимальное Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð´Ð°Ð½Ð¸Ñ"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr "МакÑимальный тайм-аут Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐµÑ‚ значение, которое не может быть принÑто"
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr "МакÑимальное Ð²Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ обновлениÑми,
msgid "May"
msgstr "Май"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr "ИзмерÑетÑÑ Ð² байтах кода. ИÑключает Ñгенерированный и вендорÑкий код."
@@ -17549,9 +18285,6 @@ msgstr "УчаÑтники"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr "%{i_open}Maintainer'Ñ‹%{i_close} и %{i_open}Owner'Ñ‹%{i_close} могут добавлÑÑ‚ÑŒ новых учаÑтников"
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr "Ð£Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа на ÑлиÑние позволÑ
msgid "Merge request dependencies"
msgstr "ЗавиÑимоÑти запроÑа на ÑлиÑние"
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "Ðе удалоÑÑŒ объединить коммиты. Это должно быть выполнено вручную."
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr "Перейти к Ñледующей нерешённой теме"
-
msgid "MergeRequests|Reply..."
msgstr "Ответить..."
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr "ПоиÑк файлов (%{modifier_key}P)"
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Слито"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "ПеренеÑено %{success_count}/%{total_count} файлов."
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr "Минуты"
msgid "Mirror direction"
msgstr "Ðаправление зеркалированиÑ"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "Зеркалировать репозиторий"
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Отмена"
-
msgid "Modal|Close"
msgstr "Закрыть"
@@ -18715,9 +19445,6 @@ msgstr "ИмÑ"
msgid "Name has already been taken"
msgstr "Ð˜Ð¼Ñ ÑƒÐ¶Ðµ занÑто"
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "Ðазвать новую метку"
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,8 +19913,8 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ñтап"
msgid "New password"
msgstr "Ðовый пароль"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "Ðовые Ñборочные линии будут отключать более Ñтарые или находÑщиеÑÑ Ð² ожидании Ñборочные линии в рамках одной ветки."
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Ðовый проект"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr "Ðет результатов"
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr "Без Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами"
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,8 +20796,8 @@ msgstr ""
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
msgstr "Срок дейÑÑ‚Ð²Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ или неÑкольких ваших токенов личного доÑтупа иÑтечёт через %{days_to_expire} дней или раньше."
-msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
-msgstr "Только роли «Reporter» и выше на планах Premium / Silver и выше могут проÑматривать Ðналитику потока ценноÑти."
+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 ""
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr "ÐаÑтройки"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Другие Метки"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr "Удалить верÑию пакета"
msgid "PackageRegistry|Delete package"
msgstr "Удалить пакет"
-msgid "PackageRegistry|Filter by name"
-msgstr "Фильтровать по имени"
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информацÐ
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "ЕÑли вы еще не Ñделали Ñтого, вам нужно будет добавить нижераÑположенное в Ñвой файл %{codeStart}.pypirc%{codeEnd}."
@@ -20465,9 +21216,6 @@ msgstr "Извините, ваш фильтр иÑключил вÑе резул
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr "Пока что нет пакетов %{packageType}"
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr "УчаÑтники"
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr "Скачать"
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr "РаÑпиÑание Сборочной Линии"
msgid "Pipeline Schedules"
msgstr "РаÑпиÑÐ°Ð½Ð¸Ñ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ñ‹Ñ… Линий"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "Квота иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ CI в минутах"
@@ -20813,6 +21573,9 @@ 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 "Триггеры Ñборки"
@@ -20981,9 +21744,6 @@ msgstr "ЗагружаютÑÑ Ñборочные линии"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "КÑш проекта уÑпешно очищен."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ Ñборочных линий."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr "ЗапуÑтить Ñборочную линию"
msgid "Pipeline|Run for"
msgstr "ЗапуÑтить длÑ"
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr "Токен новоÑтной ленты уÑпешно Ñброшен"
msgid "Profiles|Full name"
msgstr "Полное имÑ"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "Включить вклад в приватные проекты в мой профиль"
@@ -21854,9 +22620,6 @@ msgstr "ОрганизациÑ"
msgid "Profiles|Path"
msgstr "Путь"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Положение и размер вашего нового аватара"
@@ -22139,6 +22902,9 @@ msgstr "Ð˜Ð¼Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr "Проекты Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑированиÑ"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr "Предлагать пользователÑм загружать клÑ
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr "Защитить переменную"
@@ -23102,6 +23874,9 @@ msgstr "Отправка разрешена:"
msgid "ProtectedBranch|Branch"
msgstr "Ветка"
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr "Одобрение владельцем кода"
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Защитить"
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr "Защищённое окружение ограничивает ÑпиÑок пользователей, которые могут выполнÑÑ‚ÑŒ развёртываниÑ."
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr "Выбрать пользователей"
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr "Выберите пользователей Ð´Ð»Ñ Ð½Ð°Ñтройки Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¸ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¾Ð½Ð°Ð»ÑŒÐ½Ñ‹Ð¼Ð¸ опциÑми"
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr "ПеремеÑтить"
@@ -23493,12 +24271,21 @@ msgstr "ЗарегиÑтрируйте универÑальное двухфак
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ помощи приложениÑ"
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "СвÑзанные Ð—Ð°Ð´Ð°Ð½Ð¸Ñ Ð Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ"
-
msgid "Related Issues"
msgstr "СвÑзанные ОбÑуждениÑ"
-msgid "Related Jobs"
-msgstr "СвÑзанные ЗаданиÑ"
-
-msgid "Related Merge Requests"
-msgstr "СвÑзанные ЗапроÑÑ‹ на СлиÑние"
-
-msgid "Related Merged Requests"
-msgstr "СвÑзанные Влитые ЗапроÑÑ‹"
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr "Удалить"
msgid "Remove %{displayReference}"
msgstr "Удалить %{displayReference}"
-msgid "Remove Runner"
-msgstr "Удалить Runner"
-
msgid "Remove Zoom meeting"
msgstr "Удалить вÑтречу в Zoom"
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24047,7 +24829,7 @@ msgid "RepositoriesAnalytics|Average Coverage by Job"
msgstr ""
msgid "RepositoriesAnalytics|Coverage"
-msgstr ""
+msgstr "Покрытие"
msgid "RepositoriesAnalytics|Coverage Jobs"
msgstr ""
@@ -24059,31 +24841,31 @@ msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
msgstr ""
msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
-msgstr ""
+msgstr "Скачать данные о покрытии теÑтами (.csv)"
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
-msgstr ""
+msgstr "Ð—Ð°Ð´Ð°Ð½Ð¸Ñ Ñ ÐŸÐ¾ÐºÑ€Ñ‹Ñ‚Ð¸ÐµÐ¼"
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
msgid "RepositoriesAnalytics|Latest test coverage results"
-msgstr ""
+msgstr "ПоÑледние результаты Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами"
msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
-msgstr ""
+msgstr "ПожалуйÑта, выберите один или неÑколько проектов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñледних данных Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами."
msgid "RepositoriesAnalytics|Please select projects to display."
msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
-msgstr ""
+msgstr "Проекты Ñ ÐŸÐ¾ÐºÑ€Ñ‹Ñ‚Ð¸ÐµÐ¼"
msgid "RepositoriesAnalytics|Test Code Coverage"
-msgstr ""
+msgstr "Покрытие кода теÑтами"
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
@@ -24154,6 +24936,9 @@ msgstr "Хранилище репозиториÑ"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,8 +25076,8 @@ msgstr "СброÑить ключ доÑтупа проверки работоÑ
msgid "Reset key"
msgstr "Ð¡Ð±Ñ€Ð¾Ñ ÐºÐ»ÑŽÑ‡Ð°"
-msgid "Reset runners registration token"
-msgstr "СброÑить ключ региÑтрации обработчиков заданий"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr "Ð¡Ð±Ñ€Ð¾Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°"
@@ -24414,6 +25199,9 @@ msgstr "Повторить"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Повторить Ñто фоновое задание"
@@ -24463,6 +25251,9 @@ 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 ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr "ЗапуÑкайте теÑÑ‚Ñ‹ Ð´Ð»Ñ Ñвоего кода в реал
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr "Обработчик заданий уÑпешно обновлен."
msgid "Runners"
msgstr "Runner'Ñ‹"
-msgid "Runners API"
-msgstr "API обработчиков заданий"
-
-msgid "Runners activated for this project"
-msgstr "Обработчики заданий активированы Ð´Ð»Ñ Ñтого проекта"
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr "Runner'Ñ‹ — Ñто процеÑÑÑ‹, которые подбирают и выполнÑÑŽÑ‚ Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð´Ð»Ñ GitLab. ЗдеÑÑŒ вы можете зарегиÑтрировать и увидеть Ñвои Runner'Ñ‹ Ð´Ð»Ñ Ñтого проекта."
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Обработчики заданий могут запуÑкатьÑÑ Ñƒ отдельных пользователей, Ñерверах и даже на вашей локальной машине."
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ð’Ñ‹ иÑпользовали %{quotaUsed} из %{quotaLimit} ваших минут Ñборки на общих Runner'ах."
@@ -24725,6 +25540,9 @@ msgstr "Открытый ключ SSH"
msgid "SSL Verification:"
msgstr "Ð’ÐµÑ€Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ SSL:"
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "БезопаÑноÑÑ‚ÑŒ"
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,15 +26263,15 @@ msgstr "ПоÑмотреть метрики"
msgid "See the affected projects in the GitLab admin panel"
msgstr "ПоÑмотреть затрагиваемые проекты в панели админиÑтратора GitLab"
+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 "See what's new at GitLab"
-msgstr "ПоÑмотрите, что нового в Gitlab"
-
msgid "Select"
msgstr ""
@@ -25511,8 +26329,8 @@ msgstr "Выбор временной зоны"
msgid "Select all"
msgstr "Выбрать вÑе"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Выбрать ÑущеÑтвующий клаÑтер Kubernetes или Ñоздать новый"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr "Выбрать ответÑтвенного"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Выбор целевой ветки"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Выберите ветвь, которую вы хотите уÑтановить по умолчанию Ð´Ð»Ñ Ñтого проекта. Ð’Ñе запроÑÑ‹ на ÑлиÑние и коммиты будут автоматичеÑки отправлÑÑ‚ÑŒÑÑ Ð² Ñту ветку, еÑли вы не укажете другую."
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr "ÐаÑтройка CI/CD"
msgid "Set up Jira Integration"
msgstr "ÐаÑтроить интеграцию Ñ Jira"
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¸Ñпользованных минут Ñборочной л
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-msgstr "ЕÑли вы когда-нибудь потерÑете Ñвой телефон или доÑтуп к вашему одноразовому паролю, каждый из Ñтих кодов воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть иÑпользован один раз, чтобы воÑÑтановить доÑтуп к вашей учетной запиÑи. ПожалуйÑта, храните их в надежном меÑте, или вы %{b_start}можете%{b_end} потерÑÑ‚ÑŒ доÑтуп к вашему аккаунту."
-
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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Показать поÑледнюю верÑию"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Медленнее, но гарантирует, что Ñ€Ð°Ð±Ð¾Ñ‡Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑ‚ÑŒ проекта оÑтаётÑÑ Ð½ÐµÑ‚Ñ€Ð¾Ð½ÑƒÑ‚Ð¾Ð¹, Ñ‚.к. репозиторий клонируетÑÑ Ñ Ð½ÑƒÐ»Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ заданиÑ"
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,8 +27717,8 @@ msgstr "Защита от Ñпама и ботов"
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
-msgstr "Конкретные обработчики заданий"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr ""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Укажите Ñледующий URL во Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñтройки Gitlab Runner:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr "Сниппет траÑÑировки Ñтека"
msgid "Stage"
msgstr "Этап"
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr "Данные Ñтапа обновлены"
@@ -26986,8 +27798,8 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Ðачать %{new_merge_request} Ñ Ñтих изменений"
-msgid "Start a Free Gold Trial"
-msgstr "Ðачать беÑплатный пробный период Gold"
+msgid "Start a Free Ultimate Trial"
+msgstr ""
msgid "Start a new discussion..."
msgstr "Ðачать новое обÑуждение ..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr "Ðачать поиÑк"
-msgid "Start the Runner!"
-msgstr "ЗапуÑтить GitLab Runner!"
-
msgid "Start thread"
msgstr ""
@@ -27031,8 +27840,8 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
-msgstr "Ðачните беÑплатный пробный период Gold"
+msgid "Start your Free Ultimate Trial"
+msgstr ""
msgid "Start your free trial"
msgstr "Ðачать беÑплатный пробный период"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr "Будет запущен %{startsIn}"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "Опубликовать (UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27244,6 +28053,9 @@ msgstr "ÐеизвеÑтный"
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "СиÑтемные метрики (наÑтраиваемые)"
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] "Следующие перÑональные токены доÑтуп
msgid "The fork relationship has been removed."
msgstr "СвÑзь Ñ Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ удалена."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr "Лицензионный ключ недейÑтвителен. УдоÑтоверьтеÑÑŒ, что он Ñовпадает Ñ Ñ‚ÐµÐ¼, что вы получили от GitLab Inc."
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальный размер файла - %{size}."
+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 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 "Конфликты ÑлиÑÐ½Ð¸Ñ Ð´Ð»Ñ Ñтого запроÑа на ÑлиÑние не могут быть разрешены Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ GitLab. ПожалуйÑта, попробуйте разрешить их локально."
@@ -28350,8 +29183,11 @@ msgstr "Теперь можно выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑнÐ
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "Ð˜Ð¼Ñ \"%{name}\" уже занÑто в Ñтом каталоге."
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
-msgstr "КоличеÑтво изменений, которые необходимо извлечь из GitLab при клонировании репозиториÑ. Это может уÑкорить выполнение конвейеров. ОÑтавьте пуÑтым или уÑтановите значение на 0, чтобы отключить поверхноÑтное клонирование по умолчанию, и заÑтавить GitLab CI клонировать вÑе ветки и теги каждый раз."
+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 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 ""
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Пароль, необходимый Ð´Ð»Ñ Ñ€Ð°Ñшифровки закрытого ключа. Он не ÑвлÑетÑÑ Ð½ÐµÐ¾Ð±Ñзательным, а значение будет зашифровано в ÑоÑтоÑнии покоÑ."
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "Фаза жизненного цикла разработки."
@@ -28416,6 +29249,9 @@ msgstr "Проект был уÑпешно импортирован."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr "Удаленное зеркалирование занÑло Ñлишком много времени."
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Этап обзора показывает Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа ÑлиÑÐ½Ð¸Ñ Ð´Ð¾ его выполнениÑ. Данные будут автоматичеÑки добавлены поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ запроÑа на ÑлиÑние."
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr "Произошла ошибка при Ñохранении пользо
msgid "There was a problem sending the confirmation email"
msgstr "Произошла ошибка при отправке пиÑьма Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸ÐµÐ¼"
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr "Произошла ошибка при получении аналити
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,8 +29708,8 @@ 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 "Этот ÑкземплÑÑ€ GitLab пока не предоÑтавлÑет никаких общих обработчиков заданий. ÐдминиÑтраторы ÑкземплÑров могут региÑтрировать общие обработчики заданий в Ñекции админиÑтрированиÑ."
+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 "Этот ÑкземплÑÑ€ GitLab лицензирован на уровне %{insufficient_license}. Geo доÑтупен только тем пользователÑм, у которых еÑÑ‚ÑŒ по крайней мере Premium-лицензиÑ."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr "Эта цель уже имеет макÑимально возможное количеÑтво дочерних целей."
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Этой цели не ÑущеÑтвует, или у Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно прав."
@@ -29004,14 +29864,17 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Эта группа"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "Эта группа пока не Ñодержит групповых обработчики заданий."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -29040,6 +29903,9 @@ msgstr ""
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
msgstr "Это ÑпиÑок уÑтройÑтв, c которых вошли в вашу учетную запиÑÑŒ. Отмените вÑе ÑеанÑÑ‹, которые вы не раÑпознаете."
+msgid "This is a merge train pipeline"
+msgstr ""
+
msgid "This is a security log of important events involving your account."
msgstr "Это журнал безопаÑноÑти важных Ñобытий, ÑвÑзанных Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑью."
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние заблокирован."
@@ -29208,8 +30086,8 @@ msgstr ""
msgid "This project"
msgstr "Этот проект"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-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 "Ð’ Ñтом проекте не включена %{service_desk_link_start}Служба поддержки%{service_desk_link_end}, поÑтому пользователь, Ñоздавший обÑуждение, переÑтанет получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте о новых дейÑтвиÑÑ…."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ msgstr "Чтобы добавить ключ SSH, вам нужно %{generate_l
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 ""
@@ -29738,6 +30616,9 @@ msgstr "Чтобы подключить репозиторий SVN, провер
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr "Чтобы открыть Jaeger и Ñ Ð»Ñ‘Ð³ÐºÐ¾Ñтью проÑматривать траÑÑировку из GitLab, привÑжите Ñтраницу %{link} к Ñвоему Ñерверу"
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,8 +30682,8 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
-msgstr "Чтобы увидеть детали проекта, %{linkStart}обновите план группы до Silver%{linkEnd}. Ð’Ñ‹ также можете удалить проект из панели управлениÑ."
+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 ""
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr "Чтобы начать выполнÑÑ‚ÑŒ Ñвои заданиÑ, вы можете добавить обработчик заданий в вашу группу"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr "Задача отмечена как выполненнаÑ."
msgid "Today"
msgstr "СегоднÑ"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr "Переключить предварительный проÑмотр Markdown"
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,8 +30962,8 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
-msgstr "Ð’Ñ‹ вÑегда можете продолжить Ñтот процеÑÑ, нажав на Ñвой аватар и выбрав \"Ðачать пробный период Gold\""
+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 ""
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,8 +31271,8 @@ msgstr "Ðевозможно обновить Ñто обÑуждение в дÐ
msgid "Unarchive project"
msgstr "ВоÑÑтановить проект"
-msgid "Unarchiving the project will restore people's 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}"
-msgstr "Разархивирование проекта вернёт людÑм возможноÑÑ‚ÑŒ вноÑить в него изменениÑ. Ð’ репозиторий можно будет отправлÑÑ‚ÑŒ коммиты, а также поÑвитÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ Ñоздавать обÑуждениÑ, комментарии и другие ÑущноÑти. %{strong_start}ПоÑле активации Ñтот проект поÑвитÑÑ Ð² поиÑке и на панели инÑтрументов.%{strong_end}"
+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 "Отменить назначение комментирующего пользователÑ"
@@ -30633,8 +31529,8 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
-msgstr "ОбновитеÑÑŒ на более выÑокий тарифный план, чтобы иÑпользовать развёртывание Canary"
+msgid "Upgrade offers available!"
+msgstr ""
msgid "Upgrade your plan"
msgstr ""
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 "ИÑпользуйте %{code_start}::%{code_end}, чтобы Ñоздать %{link_start}набор Ñелективных меток%{link_end} (например, %{code_start}priority::1%{code_end})"
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "ИÑпользуйте Службу поддержки Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ пользователÑми (например, Ð´Ð»Ñ Ð¾ÑущеÑÑ‚Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ клиентов) через Ñлектронную почту непоÑредÑтвенно в GitLab"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "ИÑпользуйте одноразовый аутентификатор Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ð° вашем мобильном уÑтройÑтве или компьютере, чтобы включить двухфакторную аутентификацию (2FA)."
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,8 +31778,11 @@ msgstr ""
msgid "Use template"
msgstr "ИÑпользовать шаблон"
-msgid "Use the following registration token during setup:"
-msgstr "ИÑпользуйте Ñледующий токен региÑтрации в процеÑÑе уÑтановки:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "ИÑпользуютÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ‹Ð¹ наÑтройки уведомлений"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr "Пользователи"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr "Ðналитика потока ценноÑти поможет вам Ð
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "Ðналитика потока ценноÑти дает общее предÑтавление о том, Ñколько времени в вашем проекте занимает путь от идеи до выпуÑка."
-msgid "Value Stream Name"
-msgstr "Ðазвание потока ценноÑти"
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr "У Ð½Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñтого Ñтапа."
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "ПроÑмотр коммита"
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Веб-обработчик"
@@ -31811,6 +32728,9 @@ msgstr "Журналы веб-обработчика"
msgid "Webhook Settings"
msgstr "ÐаÑтройки веб-обработчика"
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Веб-обработчики"
@@ -31946,12 +32866,12 @@ msgstr "Добро пожаловать! Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ б
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr "Добро пожаловать в GitLab%{br_tag}%{name}!"
-
msgid "Welcome to GitLab, %{first_name}!"
msgstr "Добро пожаловать в GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
msgid "Welcome to the guided GitLab tour"
msgstr ""
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "Когда:"
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "ВмеÑто Ñтого вы можете %{linkStart}проÑмотреть бинарные данные%{linkEnd}."
-
msgid "You can also create a project from the command line."
msgstr "Ð’Ñ‹ также можете Ñоздать проект из командной Ñтроки."
@@ -32391,9 +33314,6 @@ msgstr "Ð’Ñ‹ также можете загрузить ÑущеÑтвующие
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Ð’Ñ‹ можете легко поучаÑтвовать в них, попроÑив приÑоединитьÑÑ."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Ð’Ñ‹ можете легко уÑтановить Runner в клаÑтер Kubernetes. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr "Ð’Ñ‹ можете разрешить конфликт ÑлиÑниÑ, и
msgid "You can see your chat accounts."
msgstr "Ð’Ñ‹ можете проÑмотреть ваши аккаунты чата."
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ msgstr "YouTube"
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 ""
@@ -32865,15 +33794,15 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "Ваши ключи GPG (%{count})"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr "Ваша пробный период GitLab Gold продлитÑÑ 30 дней, поÑле которых вы будете иметь возможноÑÑ‚ÑŒ оÑтавить Ñвой беÑплатный аккаунт GitLab навÑегда. Ðам потребуетÑÑ Ð»Ð¸ÑˆÑŒ немного дополнительной информации, чтобы активировать ваш пробный период."
-
msgid "Your Groups"
msgstr "Ваши Группы"
@@ -33027,6 +33956,9 @@ msgstr "Ваша Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð´ÐµÐ¹Ñтвительна Ñ"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "Ваше Ñообщение здеÑÑŒ"
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] "днÑ"
msgstr[2] "дней"
msgstr[3] "дней"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr "Ñлемент не ÑвлÑетÑÑ Ð¸ÐµÑ€Ð°Ñ€Ñ…Ð¸ÐµÐ¹"
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr "группа"
msgid "group members"
msgstr "учаÑтники группы"
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr " ПожалуйÑта, воÑÑтановите её или иÑполь
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr "%{link_start}подробнее о разрешении конфликтов%{link_end}"
+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 "Потребление %{metricsLinkStart} памÑти %{metricsLinkEnd} %{emphasisStart} уменьшено %{emphasisEnd} Ñ %{memoryFrom}Мбайт до %{memoryTo}Мбайт"
@@ -34031,9 +34991,6 @@ msgstr "Слить"
msgid "mrWidget|Merge failed."
msgstr "СлиÑние не удалоÑÑŒ."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr "СлиÑние не удалоÑÑŒ: %{mergeError}. ПожалуйÑта, попробуйте ещё раз."
-
msgid "mrWidget|Merge locally"
msgstr "Слить локально"
@@ -34103,8 +35060,8 @@ msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ были Ñлиты в"
msgid "mrWidget|The changes will be merged into"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ Ñлиты в"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "СÑылка HEAD иÑходной ветви недавно изменилаÑÑŒ. ПожалуйÑта, обновите Ñтраницу и проÑмотрите Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´ ÑлиÑнием"
@@ -34184,6 +35141,9 @@ msgstr "будет Ñлито автоматичеÑки, еÑли ÑборочÐ
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr "ÑброÑить."
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr "к ÑпиÑку"
msgid "toggle collapse"
msgstr "Ñвернуть/развернуть"
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "запущено"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 46326486ed6..cb3ba37a0f9 100644
--- a/locale/si_LK/gitlab.po
+++ b/locale/si_LK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: si-LK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:57\n"
+"PO-Revision-Date: 2021-02-01 17:09\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 60a537ec8db..9ab8ca1ecc0 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,6 +252,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -486,10 +493,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1183,6 +1196,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1190,10 +1206,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1431,6 +1444,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1801,15 +1826,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2068,6 +2093,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2098,9 +2126,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2167,7 +2195,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2398,6 +2435,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2506,6 +2546,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2936,7 +2979,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3422,6 +3474,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3593,6 +3648,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3707,12 +3765,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,7 +3937,7 @@ 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}"
+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?"
@@ -3976,15 +4028,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4054,7 +4109,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4335,9 +4387,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4362,7 +4411,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4461,16 +4510,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4611,25 +4660,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4638,10 +4687,16 @@ 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 Gold."
+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}."
@@ -4662,6 +4717,9 @@ 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 ""
@@ -4671,6 +4729,9 @@ 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 ""
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4996,6 +5063,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -5095,6 +5174,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5140,6 +5225,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5782,9 +5882,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ 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 ""
@@ -6010,7 +6122,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8463,12 +8614,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8637,10 +8809,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8667,7 +8839,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,7 +10457,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,7 +11109,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ 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 ""
@@ -11393,6 +11634,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12864,7 +13120,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13326,7 +13585,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,10 +15903,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15642,6 +16321,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,7 +16984,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16335,6 +17059,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,7 +17279,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 ""
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17477,9 +18213,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18715,9 +19445,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,7 +19913,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20813,6 +21573,9 @@ 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 ""
@@ -20981,9 +21744,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21854,9 +22620,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22139,6 +22902,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23493,12 +24271,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,7 +25076,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24414,6 +25199,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24463,6 +25251,9 @@ 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 ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24725,6 +25540,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,7 +26329,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,7 +27717,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26986,7 +27798,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27031,7 +27840,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27244,6 +28053,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28350,7 +29183,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28416,6 +29249,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,7 +29708,7 @@ 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."
+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."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29004,13 +29864,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29040,6 +29903,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 ""
@@ -29208,7 +30086,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ 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 ""
@@ -29738,6 +30616,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,7 +30682,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,7 +31271,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30633,7 +31529,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,7 +31778,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31946,10 +32866,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32391,9 +33314,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ 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 ""
@@ -32865,13 +33794,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34031,9 +34991,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34103,7 +35060,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34184,6 +35141,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 7ee3e7426cc..a341cb6492d 100644
--- a/locale/sl_SI/gitlab.po
+++ b/locale/sl_SI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:02\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,6 +252,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -486,10 +493,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1183,6 +1196,9 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
@@ -1190,10 +1206,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1431,6 +1444,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1801,15 +1826,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -2068,6 +2093,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2098,9 +2126,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2167,7 +2195,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2398,6 +2435,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2506,6 +2546,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2936,7 +2979,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -3077,7 +3120,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3422,6 +3474,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3593,6 +3648,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3707,12 +3765,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3885,7 +3937,7 @@ 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}"
+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?"
@@ -3976,15 +4028,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -4054,7 +4109,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4335,9 +4387,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4362,7 +4411,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4461,16 +4510,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4611,25 +4660,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4638,10 +4687,16 @@ 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 Gold."
+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}."
@@ -4662,6 +4717,9 @@ 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 ""
@@ -4671,6 +4729,9 @@ 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 ""
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4996,6 +5063,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
+msgstr ""
+
+msgid "BulkImport|No groups available for import"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+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|To new group"
@@ -5095,6 +5174,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5140,6 +5225,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5248,9 +5336,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5782,9 +5882,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5803,6 +5900,9 @@ 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 ""
@@ -5962,12 +6062,24 @@ 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 ""
@@ -6010,7 +6122,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7246,6 +7355,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7759,9 +7874,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8162,6 +8310,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8463,12 +8614,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8637,10 +8809,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8667,7 +8839,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8676,9 +8848,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8751,7 +8920,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8965,7 +9134,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,7 +10457,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10529,9 +10752,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10826,6 +11055,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,7 +11109,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10913,7 +11148,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ 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 ""
@@ -11393,6 +11634,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -12053,6 +12303,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12864,7 +13120,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12912,6 +13168,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13326,7 +13585,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13395,6 +13651,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13509,6 +13765,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13782,9 +14041,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13800,9 +14056,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13854,6 +14107,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14286,9 +14554,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14726,18 +14997,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,7 +15861,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15260,10 +15903,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15642,6 +16321,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16128,6 +16834,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16140,9 +16849,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,7 +16984,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16335,6 +17059,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,7 +17279,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16970,6 +17697,9 @@ msgstr[3] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 ""
@@ -17195,9 +17928,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17240,6 +17970,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17477,9 +18213,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17912,15 +18645,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18493,6 +19223,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18715,9 +19445,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,7 +19913,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19393,6 +20126,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -20081,7 +20832,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20189,15 +20940,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20372,9 +21123,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20735,6 +21489,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20813,6 +21573,9 @@ 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 ""
@@ -20981,9 +21744,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -21020,6 +21777,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -21134,6 +21894,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21803,12 +22566,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21854,9 +22620,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22139,6 +22902,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23138,6 +23913,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23147,9 +23925,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23159,7 +23934,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23378,6 +24153,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23493,12 +24271,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,7 +25076,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24414,6 +25199,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24463,6 +25251,9 @@ 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 ""
@@ -24506,6 +25297,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24551,6 +25345,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24725,6 +25540,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,7 +26329,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25883,6 +26701,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,10 +26743,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26386,9 +27204,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr ""
@@ -26899,7 +27717,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26908,9 +27726,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26986,7 +27798,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -27019,9 +27831,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -27031,7 +27840,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27244,6 +28053,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27655,6 +28467,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27679,9 +28494,15 @@ 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 ""
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28350,7 +29183,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28416,6 +29249,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28821,16 +29660,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28860,7 +29708,7 @@ 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."
+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."
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -29004,13 +29864,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -29040,6 +29903,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 ""
@@ -29208,7 +30086,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29265,6 +30143,9 @@ 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 ""
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29723,6 +30598,9 @@ 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 ""
@@ -29738,6 +30616,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,7 +30682,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29855,6 +30733,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29912,6 +30796,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,7 +31025,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -30159,7 +31052,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,7 +31271,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30633,7 +31529,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30852,12 +31751,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30873,7 +31778,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 ""
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31946,10 +32866,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31967,7 +32887,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -32007,6 +32930,9 @@ msgstr[3] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32391,9 +33314,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32493,7 +33413,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr ""
@@ -32829,6 +33755,9 @@ 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 ""
@@ -32865,13 +33794,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -33111,6 +34043,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33559,8 +34506,12 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33905,6 +34859,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -34031,9 +34991,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -34103,7 +35060,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34184,6 +35141,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 3f57f5ee2ea..55fa7897b28 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:03\n"
+"PO-Revision-Date: 2021-02-01 18:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 52d2fd272cc..c7218db5e15 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:10\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -226,6 +226,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -430,10 +436,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -787,6 +793,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -985,6 +994,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1108,16 +1120,16 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1339,6 +1351,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1357,6 +1372,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1408,6 +1429,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1417,9 +1441,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1429,7 +1450,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1444,6 +1465,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1708,15 +1732,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1975,6 +1999,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2005,9 +2032,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2041,7 +2065,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2065,6 +2089,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2074,7 +2101,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2104,9 +2137,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2128,6 +2158,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2278,6 +2311,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2305,6 +2341,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2413,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2842,7 +2884,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2983,7 +3025,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3034,6 +3076,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3085,6 +3130,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3328,6 +3379,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3499,6 +3553,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3613,12 +3670,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3787,7 +3838,7 @@ 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}"
+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?"
@@ -3877,15 +3928,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3955,7 +4009,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3979,9 +4033,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4234,9 +4285,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4261,7 +4309,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4360,16 +4408,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4510,25 +4558,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4537,10 +4585,16 @@ 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 Gold."
+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}."
@@ -4561,6 +4615,9 @@ 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 ""
@@ -4570,6 +4627,9 @@ 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 ""
@@ -4585,6 +4645,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4672,10 +4735,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4699,6 +4762,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4894,6 +4960,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4933,16 +5002,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4993,6 +5071,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5002,6 +5083,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5038,6 +5122,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5146,9 +5233,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5299,6 +5383,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5341,6 +5431,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5365,6 +5458,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5467,6 +5563,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5680,9 +5779,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5701,6 +5797,9 @@ 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 ""
@@ -5860,12 +5959,24 @@ 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 ""
@@ -5908,7 +6019,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7087,7 +7198,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7105,9 +7216,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7144,6 +7252,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7366,6 +7477,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7540,9 +7657,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7654,9 +7768,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7684,6 +7804,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7777,6 +7906,9 @@ 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 ""
@@ -7804,9 +7936,15 @@ 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 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 ""
@@ -7822,9 +7960,15 @@ 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 ""
@@ -8002,6 +8146,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8056,6 +8203,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8356,12 +8506,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8377,16 +8539,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8398,9 +8557,15 @@ 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 ""
@@ -8416,6 +8581,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8431,6 +8599,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8530,10 +8701,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8560,7 +8731,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8569,9 +8740,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8644,7 +8812,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8857,7 +9025,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8887,6 +9055,12 @@ 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 ""
@@ -8899,6 +9073,9 @@ 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 ""
@@ -8911,6 +9088,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8926,6 +9106,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8950,7 +9133,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8962,9 +9145,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9004,6 +9184,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9013,6 +9199,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9022,9 +9211,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9040,6 +9235,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9049,6 +9247,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9061,6 +9262,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9355,7 +9559,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9709,6 +9913,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9892,7 +10123,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9943,25 +10174,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9988,22 +10219,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10012,24 +10240,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10051,18 +10279,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10120,7 +10342,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10414,9 +10636,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10645,6 +10864,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10711,6 +10939,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10720,6 +10951,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10759,7 +10993,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10798,7 +11032,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10861,15 +11095,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10966,13 +11206,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11263,6 +11500,9 @@ 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 ""
@@ -11278,6 +11518,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11668,9 +11914,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11806,15 +12049,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11938,6 +12187,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12121,9 +12373,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12640,10 +12889,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12667,12 +12928,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12748,7 +13003,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12796,6 +13051,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13210,7 +13468,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13240,9 +13498,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13279,6 +13534,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13363,9 +13621,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13393,6 +13648,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13666,9 +13924,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13684,9 +13939,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13738,6 +13990,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13747,6 +14005,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13771,6 +14032,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14170,9 +14437,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14239,6 +14503,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14479,6 +14746,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14590,9 +14863,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14608,18 +14878,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14869,15 +15136,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15013,9 +15625,39 @@ 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 ""
@@ -15097,7 +15739,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15139,10 +15781,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15169,9 +15811,21 @@ msgstr[2] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15277,6 +15931,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15307,6 +15964,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15316,12 +15979,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,6 +16015,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15373,6 +16045,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15460,6 +16135,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15520,6 +16198,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15775,6 +16456,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15829,9 +16516,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15871,6 +16555,9 @@ 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 ""
@@ -15973,24 +16660,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16006,6 +16711,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16018,9 +16726,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16099,6 +16819,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16138,7 +16861,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16213,6 +16936,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16240,6 +16966,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16426,7 +17155,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16510,7 +17239,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16531,9 +17260,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16840,6 +17566,9 @@ msgstr[2] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17014,9 +17743,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17041,6 +17767,12 @@ 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 ""
@@ -17065,9 +17797,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17110,6 +17839,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17302,12 +18034,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17347,9 +18082,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17392,6 +18124,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17419,9 +18154,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17440,9 +18172,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17539,6 +18268,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17632,6 +18364,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17713,9 +18448,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17782,15 +18514,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18190,6 +18916,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18361,6 +19090,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18412,9 +19144,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18583,9 +19312,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18721,12 +19447,6 @@ 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 ""
@@ -18745,6 +19465,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18799,6 +19525,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19048,7 +19777,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19165,6 +19894,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19258,6 +19990,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19333,9 +20068,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19345,6 +20077,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19720,6 +20455,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19729,12 +20467,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19795,10 +20539,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19810,9 +20554,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19864,10 +20617,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19906,7 +20659,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19924,9 +20677,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19945,7 +20695,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20053,15 +20803,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20236,9 +20986,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20257,6 +21004,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20329,9 +21079,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20347,6 +21094,9 @@ 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 ""
@@ -20485,6 +21235,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20599,6 +21352,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20665,6 +21421,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20677,6 +21436,9 @@ 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 ""
@@ -20845,9 +21607,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20860,9 +21619,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20884,6 +21640,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20998,6 +21757,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21667,12 +22429,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21718,9 +22483,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22003,6 +22765,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22420,6 +23185,9 @@ 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|What are badges?"
msgstr ""
@@ -22543,7 +23311,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22918,6 +23686,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22966,6 +23737,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23002,6 +23776,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23011,9 +23788,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23023,7 +23797,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23242,6 +24016,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23356,12 +24133,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23389,21 +24175,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23500,9 +24274,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23596,6 +24367,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23845,6 +24619,12 @@ 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] ""
+msgstr[2] ""
+
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] ""
@@ -24013,6 +24793,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24148,7 +24931,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24271,6 +25054,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24319,6 +25105,9 @@ 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 ""
@@ -24361,6 +25150,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24406,6 +25198,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24427,21 +25222,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24454,21 +25237,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24490,24 +25288,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24580,6 +25393,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24937,6 +25753,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24952,6 +25771,9 @@ 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 ""
@@ -25111,9 +25933,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25177,9 +25996,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25288,13 +26104,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25354,7 +26170,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25384,6 +26200,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25441,9 +26260,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25726,6 +26542,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25765,10 +26584,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25783,9 +26602,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25930,9 +26746,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25987,6 +26800,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26227,9 +27043,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26374,6 +27187,9 @@ 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 %{listType} list"
msgstr ""
@@ -26740,7 +27556,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26749,9 +27565,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26770,9 +27583,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26827,7 +27637,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26860,9 +27670,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26872,7 +27679,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26899,15 +27706,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27085,6 +27892,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27496,6 +28306,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27520,9 +28333,15 @@ 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 ""
@@ -27697,15 +28516,18 @@ msgstr[2] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27760,10 +28582,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28096,9 +28918,6 @@ msgstr[2] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28153,6 +28972,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28171,6 +28993,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28186,7 +29017,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28204,9 +29038,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28252,6 +29083,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28279,9 +29113,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28336,7 +29167,7 @@ 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 an approval"
+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"
@@ -28444,7 +29275,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28492,6 +29323,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28504,6 +29338,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28657,16 +29494,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28696,7 +29542,7 @@ 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."
+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."
@@ -28711,22 +29557,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28741,13 +29599,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28825,9 +29686,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28840,13 +29698,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28876,6 +29737,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28999,6 +29863,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29008,6 +29875,15 @@ 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 ""
@@ -29044,7 +29920,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29101,6 +29977,9 @@ 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 ""
@@ -29134,18 +30013,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29557,6 +30430,9 @@ 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 ""
@@ -29572,6 +30448,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29581,6 +30460,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29614,6 +30496,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29629,7 +30514,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29647,12 +30532,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29668,9 +30547,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29689,6 +30565,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29716,6 +30595,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29746,6 +30628,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29836,6 +30721,9 @@ 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 ""
@@ -29893,7 +30781,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29905,7 +30793,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29932,7 +30820,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29947,7 +30835,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29956,6 +30844,9 @@ 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 ""
@@ -29965,7 +30856,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29992,7 +30883,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30208,7 +31102,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30466,7 +31360,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30487,6 +31381,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30685,12 +31582,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30706,7 +31609,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30820,7 +31726,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30979,21 +31885,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31057,9 +31957,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31084,6 +31981,15 @@ 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 ""
@@ -31255,6 +32161,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31633,6 +32542,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31642,6 +32557,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31777,10 +32695,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31798,7 +32716,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31807,7 +32725,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31828,6 +32746,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31837,6 +32758,9 @@ msgstr[2] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32197,9 +33121,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32221,9 +33142,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32248,9 +33166,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32272,6 +33187,9 @@ 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 ""
@@ -32287,15 +33205,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32323,7 +33241,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32464,6 +33382,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32476,6 +33397,9 @@ 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 no permissions"
msgstr ""
@@ -32659,6 +33583,9 @@ 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 ""
@@ -32695,13 +33622,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32857,6 +33784,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32941,6 +33871,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33028,9 +33964,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33343,6 +34285,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33385,8 +34330,11 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33481,6 +34429,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33727,6 +34678,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33853,9 +34810,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33925,7 +34879,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34234,6 +35191,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34372,6 +35332,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 76a9042199a..929546a5217 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:04\n"
+"PO-Revision-Date: 2021-02-01 18:03\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -226,6 +226,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -430,10 +436,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -787,6 +793,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -985,6 +994,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1108,16 +1120,16 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1339,6 +1351,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1357,6 +1372,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1408,6 +1429,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1417,9 +1441,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1429,7 +1450,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1444,6 +1465,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1708,15 +1732,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1975,6 +1999,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -2005,9 +2032,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -2041,7 +2065,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2065,6 +2089,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -2074,7 +2101,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2104,9 +2137,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2128,6 +2158,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2278,6 +2311,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2305,6 +2341,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2413,6 +2452,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2842,7 +2884,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2983,7 +3025,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -3034,6 +3076,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -3085,6 +3130,9 @@ 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 ""
@@ -3112,6 +3160,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3328,6 +3379,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3499,6 +3553,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3613,12 +3670,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3787,7 +3838,7 @@ 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}"
+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?"
@@ -3877,15 +3928,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3955,7 +4009,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3979,9 +4033,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4234,9 +4285,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4261,7 +4309,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4360,16 +4408,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4510,25 +4558,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4537,10 +4585,16 @@ 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 Gold."
+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}."
@@ -4561,6 +4615,9 @@ 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 ""
@@ -4570,6 +4627,9 @@ 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 ""
@@ -4585,6 +4645,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4672,10 +4735,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4699,6 +4762,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4894,6 +4960,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4933,16 +5002,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4993,6 +5071,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5002,6 +5083,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -5038,6 +5122,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5146,9 +5233,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5299,6 +5383,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5341,6 +5431,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5365,6 +5458,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5467,6 +5563,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5680,9 +5779,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5701,6 +5797,9 @@ 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 ""
@@ -5860,12 +5959,24 @@ 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 ""
@@ -5908,7 +6019,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -7087,7 +7198,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7105,9 +7216,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7144,6 +7252,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7366,6 +7477,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7540,9 +7657,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7654,9 +7768,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7684,6 +7804,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7777,6 +7906,9 @@ 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 ""
@@ -7804,9 +7936,15 @@ 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 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 ""
@@ -7822,9 +7960,15 @@ 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 ""
@@ -8002,6 +8146,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -8056,6 +8203,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8356,12 +8506,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8377,16 +8539,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8398,9 +8557,15 @@ 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 ""
@@ -8416,6 +8581,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8431,6 +8599,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8530,10 +8701,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8560,7 +8731,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8569,9 +8740,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8644,7 +8812,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8857,7 +9025,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8887,6 +9055,12 @@ 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 ""
@@ -8899,6 +9073,9 @@ 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 ""
@@ -8911,6 +9088,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8926,6 +9106,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8950,7 +9133,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8962,9 +9145,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9004,6 +9184,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -9013,6 +9199,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9022,9 +9211,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9040,6 +9235,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9049,6 +9247,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9061,6 +9262,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9355,7 +9559,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9709,6 +9913,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9892,7 +10123,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9943,25 +10174,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9988,22 +10219,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10012,24 +10240,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10051,18 +10279,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10120,7 +10342,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10414,9 +10636,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10645,6 +10864,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10711,6 +10939,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10720,6 +10951,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10759,7 +10993,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10798,7 +11032,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10861,15 +11095,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10966,13 +11206,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11263,6 +11500,9 @@ 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 ""
@@ -11278,6 +11518,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11668,9 +11914,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11806,15 +12049,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11938,6 +12187,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12121,9 +12373,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12640,10 +12889,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12667,12 +12928,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12748,7 +13003,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12796,6 +13051,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13210,7 +13468,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13240,9 +13498,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13279,6 +13534,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13363,9 +13621,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13393,6 +13648,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13666,9 +13924,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13684,9 +13939,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13738,6 +13990,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13747,6 +14005,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13771,6 +14032,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14170,9 +14437,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14239,6 +14503,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14479,6 +14746,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14590,9 +14863,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14608,18 +14878,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14869,15 +15136,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -15013,9 +15625,39 @@ 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 ""
@@ -15097,7 +15739,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15139,10 +15781,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15169,9 +15811,21 @@ msgstr[2] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15277,6 +15931,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15307,6 +15964,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15316,12 +15979,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15346,6 +16015,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15373,6 +16045,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15460,6 +16135,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15520,6 +16198,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15775,6 +16456,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15829,9 +16516,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15871,6 +16555,9 @@ 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 ""
@@ -15973,24 +16660,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -16006,6 +16711,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -16018,9 +16726,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16099,6 +16819,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16138,7 +16861,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16213,6 +16936,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16240,6 +16966,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16426,7 +17155,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16510,7 +17239,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16531,9 +17260,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16840,6 +17566,9 @@ msgstr[2] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17014,9 +17743,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17041,6 +17767,12 @@ 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 ""
@@ -17065,9 +17797,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -17110,6 +17839,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17302,12 +18034,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17347,9 +18082,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17392,6 +18124,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17419,9 +18154,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17440,9 +18172,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17539,6 +18268,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17632,6 +18364,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17713,9 +18448,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17782,15 +18514,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18190,6 +18916,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18361,6 +19090,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18412,9 +19144,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18583,9 +19312,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18721,12 +19447,6 @@ 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 ""
@@ -18745,6 +19465,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18799,6 +19525,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19048,7 +19777,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19165,6 +19894,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19258,6 +19990,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19333,9 +20068,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19345,6 +20077,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19720,6 +20455,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19729,12 +20467,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19795,10 +20539,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19810,9 +20554,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19864,10 +20617,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19906,7 +20659,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19924,9 +20677,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19945,7 +20695,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -20053,15 +20803,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20236,9 +20986,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20257,6 +21004,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20329,9 +21079,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20347,6 +21094,9 @@ 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 ""
@@ -20485,6 +21235,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20599,6 +21352,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20665,6 +21421,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20677,6 +21436,9 @@ 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 ""
@@ -20845,9 +21607,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20860,9 +21619,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20884,6 +21640,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20998,6 +21757,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21667,12 +22429,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21718,9 +22483,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -22003,6 +22765,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22420,6 +23185,9 @@ 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|What are badges?"
msgstr ""
@@ -22543,7 +23311,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22918,6 +23686,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22966,6 +23737,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -23002,6 +23776,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -23011,9 +23788,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -23023,7 +23797,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23242,6 +24016,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23356,12 +24133,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23389,21 +24175,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23500,9 +24274,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23596,6 +24367,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23845,6 +24619,12 @@ 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] ""
+msgstr[2] ""
+
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] ""
@@ -24013,6 +24793,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24148,7 +24931,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24271,6 +25054,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24319,6 +25105,9 @@ 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 ""
@@ -24361,6 +25150,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24406,6 +25198,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24427,21 +25222,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24454,21 +25237,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24490,24 +25288,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24580,6 +25393,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24937,6 +25753,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24952,6 +25771,9 @@ 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 ""
@@ -25111,9 +25933,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25177,9 +25996,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25288,13 +26104,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25354,7 +26170,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25384,6 +26200,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25441,9 +26260,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25726,6 +26542,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25765,10 +26584,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25783,9 +26602,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25930,9 +26746,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25987,6 +26800,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26227,9 +27043,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26374,6 +27187,9 @@ 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 %{listType} list"
msgstr ""
@@ -26740,7 +27556,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26749,9 +27565,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26770,9 +27583,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26827,7 +27637,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26860,9 +27670,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26872,7 +27679,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26899,15 +27706,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -27085,6 +27892,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27496,6 +28306,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27520,9 +28333,15 @@ 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 ""
@@ -27697,15 +28516,18 @@ msgstr[2] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27760,10 +28582,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28096,9 +28918,6 @@ msgstr[2] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28153,6 +28972,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28171,6 +28993,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28186,7 +29017,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28204,9 +29038,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28252,6 +29083,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28279,9 +29113,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28336,7 +29167,7 @@ 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 an approval"
+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"
@@ -28444,7 +29275,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28492,6 +29323,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28504,6 +29338,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28657,16 +29494,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28696,7 +29542,7 @@ 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."
+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."
@@ -28711,22 +29557,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28741,13 +29599,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28825,9 +29686,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28840,13 +29698,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28876,6 +29737,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28999,6 +29863,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29008,6 +29875,15 @@ 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 ""
@@ -29044,7 +29920,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -29101,6 +29977,9 @@ 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 ""
@@ -29134,18 +30013,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29557,6 +30430,9 @@ 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 ""
@@ -29572,6 +30448,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29581,6 +30460,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29614,6 +30496,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29629,7 +30514,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29647,12 +30532,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29668,9 +30547,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29689,6 +30565,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29716,6 +30595,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29746,6 +30628,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29836,6 +30721,9 @@ 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 ""
@@ -29893,7 +30781,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29905,7 +30793,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29932,7 +30820,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29947,7 +30835,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29956,6 +30844,9 @@ 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 ""
@@ -29965,7 +30856,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29992,7 +30883,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30208,7 +31102,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30466,7 +31360,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30487,6 +31381,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30685,12 +31582,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30706,7 +31609,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30820,7 +31726,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30979,21 +31885,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31057,9 +31957,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31084,6 +31981,15 @@ 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 ""
@@ -31255,6 +32161,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31633,6 +32542,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31642,6 +32557,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31777,10 +32695,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31798,7 +32716,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31807,7 +32725,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31828,6 +32746,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31837,6 +32758,9 @@ msgstr[2] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32197,9 +33121,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32221,9 +33142,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32248,9 +33166,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32272,6 +33187,9 @@ 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 ""
@@ -32287,15 +33205,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32323,7 +33241,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32464,6 +33382,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32476,6 +33397,9 @@ 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 no permissions"
msgstr ""
@@ -32659,6 +33583,9 @@ 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 ""
@@ -32695,13 +33622,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32857,6 +33784,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32941,6 +33871,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -33028,9 +33964,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33343,6 +34285,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33385,8 +34330,11 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33481,6 +34429,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33727,6 +34678,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33853,9 +34810,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33925,7 +34879,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34234,6 +35191,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34372,6 +35332,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index af54a79c8f0..d6135a96850 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:04\n"
+"PO-Revision-Date: 2021-02-01 17:59\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index a68a0d39f94..fcb8cf563c5 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sw\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:09\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index 10ac0aabb5b..95af67a0561 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 23:02\n"
+"PO-Revision-Date: 2021-02-01 17:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d sabit test sonucu"
msgstr[1] "%d sabit test sonucu"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d grup seçildi"
@@ -374,10 +379,10 @@ msgstr "%{authorsName} kiÅŸisinin konusu"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr "&lt; 1 saat"
@@ -1033,16 +1044,16 @@ msgstr "+%{tags} daha fazla"
msgid ", or "
msgstr ", veya "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- Olay"
msgstr[1] "- Olaylar"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Çalıştırıcı aktif ve yeni işler işleyebilir"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Çalıştırıcı duraklatıldı ve yeni işler almayacak"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1247,6 +1258,9 @@ msgstr "Boş bir proje için bir varsayılan dal seçilemez."
msgid "A deleted user"
msgstr "Silinmiş kullanıcı"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Bir dosya deÄŸiÅŸtirildi."
@@ -1265,6 +1279,12 @@ msgstr "Bir grup birkaç proje topluluğudur"
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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Proje, dosyalarınızı depoladığınız (depo), çalışmanızı planladığınız (sorunlar) ve belgelerinizi yayınladığınız (wiki), %{among_other_things_link} bir yerdir."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr "Harici depolama isteğini tanımlayan güvenli bir erişim anahtarı."
@@ -1337,7 +1357,7 @@ msgstr "%{ip} IP adresinden hesabınızda oturum açıldı."
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "API Yardımı"
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr "Yapılacaklar listesi ekle"
-msgid "Add a To-Do"
-msgstr "Yapılacak ekle"
-
msgid "Add a bullet list"
msgstr "Madde iÅŸareti listesi ekle"
msgid "Add a comment to this line"
msgstr "Bu satıra yorum ekle"
+msgid "Add a comment to this line or drag for multiple lines"
+msgstr ""
+
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Bu %{noteableDisplayName} için genel bir yorum ekle."
@@ -1882,6 +1905,9 @@ msgstr "Yönetici modu devre dışı"
msgid "Admin mode enabled"
msgstr "Yönetici modu etkinleştirildi"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Yönetici notları"
@@ -1912,9 +1938,6 @@ msgstr "GeliÅŸtirici"
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr "Misafir"
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr "Sahibi"
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr "Toplam kullanıcı"
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "Kullanıcı istatistikleri"
@@ -1981,7 +2007,13 @@ msgstr "En yüksek role sahip kullanıcılar"
msgid "AdminArea|Users without a Group and Project"
msgstr "Grubu ve projesi olmayan kullanıcılar"
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr "Otomatik DevOps etki alanı"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Yeni projeler için paylaşılan çalıştırıcıları etkinleştir"
@@ -2035,6 +2064,9 @@ msgstr "Entegrasyonlara taşındı"
msgid "AdminSettings|No required pipeline"
msgstr "Gerekli iş hattı yok"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Gerekli iş hattı yapılandırması"
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "LDAP engelli kullanıcıların engellemesini kaldıramıyor"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Devre dışı bırak"
@@ -2212,6 +2247,9 @@ msgstr "Kullanıcıyı sil"
msgid "AdminUsers|Delete user and contributions"
msgstr "Kullanıcıyı ve katkılarını sil"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Harici"
@@ -2320,6 +2358,9 @@ msgstr "Kullanıcı git depolarına erişemeyecek"
msgid "AdminUsers|User will not be able to login"
msgstr "Kullanıcı oturum açamayacak"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr "Uyarılar"
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ msgstr ""
msgid "Allow projects within this group to use Git LFS"
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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Ä°zin verilmedi"
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr "Bir hata oluÅŸtu"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Konuya taslak eklenirken bir hata oluÅŸtu."
@@ -3234,6 +3284,9 @@ msgstr "Dosya yüklenirken bir hata oluştu."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Dosya yüklenirken bir hata oluştu. Lütfen daha sonra tekrar deneyin."
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "Birleştirme isteği değişiklikleri yüklenirken bir hata oluştu."
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr "Atalar"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anonim"
@@ -3519,12 +3575,6 @@ msgstr "DeÄŸiÅŸiklikleri uygula"
msgid "Apply suggestion"
msgstr "Öneriyi uygula"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr "Önerileri uygula"
@@ -3689,7 +3739,7 @@ msgstr "Proje arşivlendi! Depo ve diğer proje kaynakları sadece okunur"
msgid "Archived projects"
msgstr "ArÅŸivlenmiÅŸ projeler"
-msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+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?"
@@ -3778,15 +3828,18 @@ 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 registration token?"
-msgstr "Kayıt erişim anahtarını sıfırlamak istediğinizden emin misiniz?"
-
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?"
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr "Artan"
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "#FF0000 gibi özel renk ata"
-msgid "Assign epic"
-msgstr "Epik ata"
-
msgid "Assign labels"
msgstr "Etiket tanımla"
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "%{new_chat_name} yetkilendirildi"
@@ -4160,8 +4207,8 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Yedekli, bekleyen iş hatlarını otomatik olarak iptal et"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4259,16 +4306,16 @@ msgstr "Kullanılabilir"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,26 +4456,26 @@ msgstr "Dikkatli olun. Bir projenin deposunu yeniden isimlendirmenin istenmeyen
msgid "Begin with the selected commit"
msgstr "Seçili işlem ile başla"
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Fatura"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name} şu anda %{plan_name} planı kullanıyor."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "@%{user_name} olarak şu anda %{plan_name} planı kullanıyorsunuz."
@@ -4436,11 +4483,17 @@ msgstr "@%{user_name} olarak şu anda %{plan_name} planı kullanıyorsunuz."
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 Gold."
-msgstr "%{faq_link} bölümünü okuyarak her plan hakkında daha fazla bilgi edinin veya GitLab.com Altın paketinin ücretsiz 30 günlük deneme sürümünü başlatın."
+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 ""
@@ -4460,6 +4513,9 @@ msgstr "Bu grup, üst grup ile ilişkili planı kullanır."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Bu grubun planını yönetmek için, %{parent_billing_page_link} faturalandırma bölümünü ziyaret edin."
+msgid "BillingPlans|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 ""
@@ -4469,6 +4525,9 @@ msgstr ""
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "%{price_per_year} olarak faturalandırılır"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "Sık sorulan sorular"
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Yükselt"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Daralt"
@@ -4792,6 +4857,9 @@ msgstr "proje ayarları"
msgid "Branches|protected"
msgstr "korumalı"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr "Dahili"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ msgstr "Daha fazla İş Hattı dakikası satın al"
msgid "By %{user_name}"
msgstr "%{user_name} tarafından"
+msgid "By authenticating with an account tied to an Enterprise e-mail address, it is understood that this account is an Enterprise User. "
+msgstr ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr "Öntanımlı olarak GitLab, e-postaları HTML ve düz metin biçimlerind
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 default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "tarafından"
@@ -4936,6 +5019,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD ayarları"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD için harici depo"
@@ -5044,9 +5130,6 @@ msgstr "Parçacık güncellenemiyor: %{err}"
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr "Yolu deÄŸiÅŸtir"
msgid "Change permissions"
msgstr "Ä°zinleri deÄŸiÅŸtir"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr "Durumu deÄŸiÅŸtir"
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Dikkatli seç"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Geri al"
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "Vekil(ler) deÄŸiÅŸtirildi."
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr "Herhangi bir renk seçin."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Dosya seçin…"
@@ -5599,6 +5694,9 @@ msgstr "Görünürlük seviyesini seçin, proje özelliklerini etkinleştirin/de
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 ""
@@ -5758,12 +5856,24 @@ msgstr "Sınıflandırma Etiketi (isteğe bağlı)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "kullanılamıyor: %{reason}"
+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 "Temizle"
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ msgstr "Kod Ä°ncelemesi"
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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Desen"
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "Kenar çubuğunu daralt"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "Yükseltmek için satıcı ile iletişim kurun"
-
msgid "Contact support"
msgstr "Destek ile iletişime geçin"
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr "Yollama komutunu kopyala"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr "Seçileni sil"
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
msgstr "Resim Depoları"
+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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr "Komutları kopyala"
msgid "Copy commit SHA"
msgstr "İşlem SHA'sını kopyala"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr "DeÄŸeri kopyala"
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr "kiÅŸisel eriÅŸim belirteci oluÅŸtur"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "OluÅŸturdu:"
@@ -8423,12 +8593,12 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
-msgstr "Mevcut Plan"
-
msgid "Current Project"
msgstr "Mevcut Proje"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr ""
@@ -8453,8 +8623,8 @@ msgstr "Profil"
msgid "CurrentUser|Settings"
msgstr "Ayarlar"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "Altın denemesini başlat"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr "Yükselt"
@@ -8462,9 +8632,6 @@ msgstr "Yükselt"
msgid "Custom Attributes"
msgstr "Özel Nitelikler"
-msgid "Custom CI configuration path"
-msgstr "Özel CI yapılandırma yolu"
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr "Dil ve bölgeyle ilgili ayarları özelleştirin."
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ msgstr "Siliniyor"
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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr "Dağıtım Sıklığı"
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr "EtkisizleÅŸtir"
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "Düzenle"
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr "HTML e-postalarını etkinleştir"
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr "Korunan yolların sıklık limitini etkinleştir"
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr "EpiÄŸi sil"
msgid "Epics|Remove issue"
msgstr "Sorunu sil"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "Daha fazlasını göster"
@@ -11553,9 +11798,6 @@ msgstr "Örnek: %{ip_address}. %{read_more_link}."
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr "Örnek: Değer Akışım"
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr "Projeyi dışa aktar"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ msgstr "Altbilgi mesajı"
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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr "Åžifrenizi mi unuttunuz?"
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr "CoÄŸrafi"
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr "Git revizyonu"
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr "GitLab içe aktarma"
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr "Kaydet"
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr "Grup Git LFS durumu:"
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr "Grup sorumluları, grup çalıştırıcılarını %{link} içinde kayded
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr "Gruba genel bakış"
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr "Sık ziyaret edilenler"
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ 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 runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ msgstr "dakika"
msgid "Incidents"
msgstr "Olaylar"
+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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Tüm ayrıntılar"
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr "Yorumları etkinleştir"
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "Standart"
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr "Geçersiz giriş ya da şifre"
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "Geçersiz pin kodu"
@@ -15398,6 +16075,9 @@ msgstr "Grup davet et"
msgid "Invite member"
msgstr "Ãœye davet et"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr "Sorunlar kapalı"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ msgstr ""
msgid "Issue|Title"
msgstr "Başlık"
+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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ msgstr ""
msgid "Jobs"
msgstr "Ä°ÅŸler"
+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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,8 +16738,8 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
-msgstr "Ä°ÅŸi sildi:"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr ""
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,8 +17031,8 @@ msgstr ""
msgid "Last edited %{date}"
msgstr "Son düzenleme: %{date}"
-msgid "Last edited by %{name}"
-msgstr "En son %{name} tarafından düzenlendi"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "Otomatik DevOps hakkında daha fazla bilgi edinin"
-msgid "Learn more about Kubernetes"
-msgstr "Kubernetes hakkında daha fazla bilgi edinin"
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] "En fazla %d olay gösterimiyle sınırlı"
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr "BÄ°RLEÅžTÄ°RÄ°LDÄ°"
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr "May"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr "Ãœyeler"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr "Taslak yorum kaydedilirken bir hata oluÅŸtu."
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "Yanıt..."
@@ -17652,15 +18383,9 @@ msgstr "Dosya bulunamadı"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "BirleÅŸtirildi"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr "Dakika"
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr "Ä°ptal"
-
msgid "Modal|Close"
msgstr "Kapat"
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr "Yeni etiketi adlandır"
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,8 +19641,8 @@ msgstr "Yeni dönüm noktası"
msgid "New password"
msgstr "Yeni ÅŸifre"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "Yeni iş hatları, aynı daldaki daha eski iş hatlarını iptal edecek"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Yeni proje"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr "Seçenekler"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "DiÄŸer Etiketler"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr "İsme göre filtrele"
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr "Üzgünüz, filtreniz sonuç vermedi"
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr "Ä°ndir"
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr "İş Hattı Zamanlaması"
msgid "Pipeline Schedules"
msgstr "İş Hattı Zamanlamaları"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "İş hattı dakika kotası"
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr "İş Hatları Yükleniyor"
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr "Besleme erişim anahtarı başarıyla sıfırlandı"
msgid "Profiles|Full name"
msgstr "Tam isim"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "Profilime özel katkıları ekle"
@@ -21582,9 +22346,6 @@ msgstr "Organizasyon"
msgid "Profiles|Path"
msgstr "Yol"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Yeni profil resminizi konumlandırın ve boyutlandırın"
@@ -21867,6 +22628,9 @@ msgstr "Proje adı"
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr "Dağıtıma izin verildi"
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr "İlgili sorunlar hakkında daha fazla bilgi edinin"
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "İlgili Dağıtılmış İşler"
-
msgid "Related Issues"
msgstr "Ä°lgili Sorunlar"
-msgid "Related Jobs"
-msgstr "Ä°lgili Ä°ÅŸler"
-
-msgid "Related Merge Requests"
-msgstr "Ä°lgili BirleÅŸtirme Talepleri"
-
-msgid "Related Merged Requests"
-msgstr "Ä°lgili BirleÅŸtirme Talepleri"
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr "Kaldır"
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,8 +24786,8 @@ msgstr "Sağlık kontrolü erişim anahtarını sıfırla"
msgid "Reset key"
msgstr "Anahtarı sıfırla"
-msgid "Reset runners registration token"
-msgstr "Runner kayıt erişim anahtarını sıfırla"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr ""
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr "Çalıştırıcılar %{status}, son iletişim %{runner_contact} önceydi"
@@ -24282,21 +25075,9 @@ msgstr "Çalıştırıcı başarıyla güncellendi."
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Güvenlik"
@@ -24796,6 +25613,9 @@ msgstr "Güvenlik Kontrol Panosu"
msgid "Security dashboard"
msgstr "Güvenlik gösterge panosu"
+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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,15 +25945,15 @@ msgstr "Metrikleri gör"
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 "See what's new at GitLab"
-msgstr "GitLab'daki yenilikleri görün"
-
msgid "Select"
msgstr ""
@@ -25197,7 +26011,7 @@ msgstr "Zaman dilimini seçin"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr "Hedef dalı seç"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr "Özel proje şablonu kaynak grubunu seçin."
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr "CI/CD'yi kur"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr "Yeni ÅŸifre ayarla"
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr "Kullanılan iş hattı dakikalarını sıfırla"
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr "AÅŸama"
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,8 +27476,8 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Bu değişiklikler ile bir %{new_merge_request} başlatın"
-msgid "Start a Free Gold Trial"
-msgstr "Ücretsiz Altın Denemesini Başlatın"
+msgid "Start a Free Ultimate Trial"
+msgstr ""
msgid "Start a new discussion..."
msgstr ""
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr "Aramayı başlat"
-msgid "Start the Runner!"
-msgstr "Runner'ı Başlat!"
-
msgid "Start thread"
msgstr ""
@@ -26713,8 +27518,8 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
-msgstr "Ücretsiz Altın Denemesini Başlat"
+msgid "Start your Free Ultimate Trial"
+msgstr ""
msgid "Start your free trial"
msgstr "Ücretsiz denemenizi başlatın"
@@ -26740,15 +27545,15 @@ msgstr "Başlatılıyor..."
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr "Bilinmeyen"
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr "Sistem kancası başarıyla güncellendi."
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "Sistem metrikleri (Özel)"
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr "%{user} %{timeAgo} güncelledi"
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr "Çatal ilişkisi kaldırıldı."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr "Birleştirme isteği artık birleştirilebilir."
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr "Yol haritası, epiklerinizin bir zaman çizelgesi boyunca ilerlemesini gösterir"
-
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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+msgstr ""
+
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "Bu işlem veri kaybına yol açabilir. Yanlışlıkla yapılacak işlemleri önlemek için niyetinizi onaylamanızı istiyoruz."
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
msgstr ""
-msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Bu grup"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ msgstr ""
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
msgstr "Bu, hesabınıza giriş yaptığınız cihazların listesidir. Tanımadığınız veya bilmediğiniz tüm oturumları sonlandırın."
+msgid "This is a merge train pipeline"
+msgstr ""
+
msgid "This is a security log of important events involving your account."
msgstr "Bu, hesabınızla ilgili önemli olayların bir güvenlik günlüğüdür."
@@ -28835,6 +29697,9 @@ msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Bu, boş bir havuz oluşturmadan veya mevcut olanı içe aktarmadan kodu zorlayamazsınız anlamına gelir."
+msgid "This merge request cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 "Bu birleÅŸtirme isteÄŸi kilitlendi."
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr "Bu proje"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 "Ait olduğunuz bir grubun proje başına bildirim seviyesini belirlemek için proje sayfasını ziyaret etmeniz ve orada bildirim seviyesini değiştirmeniz gerekir."
-msgid "To start serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr "Aramanızı genişletmek için yukarıdaki filtreleri değiştirin veya kaldırın"
@@ -29523,6 +30397,9 @@ msgstr "Yapılacaklar öğesi başarıyla bitti olarak işaretlendi."
msgid "Today"
msgstr "Bugün"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr "Biçimlendirme önizlemesini aç/kapat"
@@ -29550,6 +30427,9 @@ msgstr "Açılır listeyi aç/kapat"
msgid "Toggle emoji award"
msgstr "İfade ödülünü aç/kapat"
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Gezinmeyi aç/kapat"
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ msgstr "SahipliÄŸi aktar"
msgid "Transfer project"
msgstr "Projeyi aktar"
+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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr "Tetikleyici başarıyla güncellendi."
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr "Güncelleniyor"
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,8 +31440,11 @@ msgstr ""
msgid "Use template"
msgstr "Åžablonu kullan"
-msgid "Use the following registration token during setup:"
-msgstr "Kurulum sırasında aşağıdaki kayıt kodunu kullanın:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "Genel bildirim ayarınızı kullanın"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,19 +31716,13 @@ msgstr "Kullanıcılar"
msgid "Users in License"
msgstr ""
-msgid "Users in License:"
-msgstr "Lisanslı kullanıcılar:"
-
msgid "Users or groups set as approvers in the project's or merge request's settings."
msgstr ""
-msgid "Users over License:"
-msgstr "Lisansı bitmiş kullanıcılar:"
-
-msgid "Users requesting access to"
+msgid "Users over License"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgid "Users requesting access to"
msgstr ""
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Bu gruplara katılmayı talep ederek onlara kolayca katkıda bulunabilirsiniz."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr "Sohbet hesaplarınızı görebilirsiniz."
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr "Ä°zinleriniz yok"
@@ -32489,6 +33411,9 @@ msgstr "YouTube"
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 ""
@@ -32525,15 +33450,15 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr "Gitlab grubunuz"
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr ""
-
msgid "Your Groups"
msgstr "Gruplarınız"
@@ -32687,6 +33612,9 @@ msgstr "Lisansınız şu tarihten itibaren geçerlidir:"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
msgstr "[Sebep yok]"
+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 "silinmiş bir kullanıcı"
@@ -32857,9 +33791,15 @@ msgstr "dal adı"
msgid "by"
msgstr "tarafından"
+msgid "cURL:"
+msgstr ""
+
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
msgstr ""
+msgid "can't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] "gün"
msgstr[1] "gün"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr "varsayılan dal"
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr "grup"
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr "BirleÅŸtir"
msgid "mrWidget|Merge failed."
msgstr "Birleştirme başarısız."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr "Yerel olarak birleÅŸtir"
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "daraltmayı aç/kapat"
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "tetiklendi"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 0dc9de8e5b4..4c17da74a60 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: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:08\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -252,13 +252,20 @@ msgstr[1] "%d виправлені результати теÑту"
msgstr[2] "%d виправлених результатів теÑту"
msgstr[3] "%d виправлених результатів теÑту"
-msgid "%d group selected"
-msgid_plural "%d groups selected"
+msgid "%d group"
+msgid_plural "%d groups"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d group selected"
+msgid_plural "%d groups selected"
+msgstr[0] "%d група обрана"
+msgstr[1] "%d групи обрано"
+msgstr[2] "%d груп обрано"
+msgstr[3] "%d груп обрано"
+
msgid "%d hour"
msgid_plural "%d hours"
msgstr[0] "%d година"
@@ -450,10 +457,10 @@ msgstr[3] "%d вразливоÑтей відхилено"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾:"
+msgstr[1] "%d Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾:"
+msgstr[2] "%d попереджень знайдено:"
+msgstr[3] "%d попереджень знайдено:"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -484,12 +491,12 @@ msgid "%{authorsName}'s thread"
msgstr "Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{authorsName}"
msgid "%{board_target} not found"
-msgstr ""
+msgstr "%{board_target} не знайдено"
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -502,13 +509,13 @@ msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
-msgstr ""
+msgstr "%{containerScanningLinkStart}Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð²%{containerScanningLinkEnd} та/або %{dependencyScanningLinkStart}ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей%{dependencyScanningLinkEnd} мають бути ввімкнені. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} буде автором автоматично Ñтвореного запиту на злиттÑ. %{moreInfoLinkStart}Додаткова інформаціÑ%{moreInfoLinkEnd}."
msgid "%{cores} cores"
msgstr "%{cores} Ñдер"
msgid "%{count} %{scope} for term '%{term}'"
-msgstr ""
+msgstr "%{count} %{scope}Ð´Ð»Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ '%{term}"
msgid "%{count} LOC/commit"
msgstr "%{count} Ñ€Ñдків коду/коміт"
@@ -588,13 +595,13 @@ 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; %{default_branch_link_start}search on %{default_branch} instead%{default_branch_link_end}."
-msgstr ""
+msgstr "%{doc_link_start}Розширений пошук%{doc_link_end} вимкнено, оÑкільки %{ref_elem} не Ñ” гілкою за замовчуваннÑм; %{default_branch_link_start}пошук на %{default_branch} заміÑÑ‚ÑŒ%{default_branch_link_end}."
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgstr ""
msgid "%{due_date} (Past due)"
-msgstr ""
+msgstr "%{due_date} (з проÑтроченнÑм)"
msgid "%{duration}ms"
msgstr "%{duration}мÑ"
@@ -672,10 +679,10 @@ 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 ""
+msgstr "%{labelStart}Стан збою:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}Дані:%{labelEnd} %{evidence}"
@@ -699,7 +706,7 @@ msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Сканер:%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}ÐадіÑланий запит:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr ""
@@ -711,7 +718,7 @@ msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупний"
msgid "%{label_name} %{span_open}will be permanently deleted from %{subject_name}. This cannot be undone.%{span_close}"
-msgstr ""
+msgstr "%{label_name} %{span_open}буде назавжди видалено з %{subject_name}. Це не можна буде ÑкаÑувати.%{span_close}"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} Ñ” безкоштовним, автоматизованим та відкритим центром Ñертифікації (CA), Ñкий випуÑкає цифрові Ñертифікати Ð´Ð»Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ HTTPS (SSL/TLS) Ð´Ð»Ñ Ð²ÐµÐ±Ñайтів."
@@ -850,6 +857,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -1058,6 +1068,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr "&lt; 1 година"
@@ -1183,6 +1196,9 @@ msgstr "+%{tags} більше"
msgid ", or "
msgstr ", або "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- ПодіÑ"
@@ -1190,11 +1206,8 @@ msgstr[1] "- Події"
msgstr[2] "- Подій"
msgstr[3] "- Подій"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Runner активний Ñ– може виконувати нові завданнÑ"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner призупинено Ñ– він не зможе виконувати нові завданнÑ"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1431,6 +1444,9 @@ msgstr "Ðе можна обирати уÑтавну гілку Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾
msgid "A deleted user"
msgstr "Видалений кориÑтувач"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "Файл змінено."
@@ -1449,6 +1465,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1500,6 +1522,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "Проєкт — це міÑце, де ви розміщуєте Ñвої файли (репозиторій), планувати роботу (питаннÑ) Ñ– публікувати документацію (вікі), %{among_other_things_link}."
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1509,9 +1534,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "РегулÑрний вираз, Ñкий буде викориÑтовуватиÑÑ Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами в журналі завданнÑ. Залиште пуÑтим Ð´Ð»Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ"
-
msgid "A secure token that identifies an external storage request."
msgstr "Секретний токен Ñкий ідентфікує запити до зовнішнього Ñховища."
@@ -1521,7 +1543,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1536,6 +1558,9 @@ msgstr "ÐЕОБХІДÐРДІЯ: ЩоÑÑŒ пішло не так при отр
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "Довідка API"
@@ -1801,15 +1826,15 @@ msgstr "Додати кнопку Ð´Ð»Ñ Grafana в Ñекції моніторÐ
msgid "Add a To Do"
msgstr "Додати нагадуваннÑ"
-msgid "Add a To-Do"
-msgstr "Додати нагадуваннÑ"
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr "Додайте загальний коментар до цього %{noteableDisplayName}."
@@ -1841,7 +1866,7 @@ msgid "Add a task list"
msgstr "Додати ÑпиÑок завдань"
msgid "Add a to do"
-msgstr ""
+msgstr "Додати нагадуваннÑ"
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Створіть додатковий текÑÑ‚, Ñкий буде приÑутній у вÑÑ–Ñ… повідомленнÑÑ… електронної пошти. МакÑимальна кількіÑÑ‚ÑŒ Ñимволів — %{character_limit}"
@@ -1997,7 +2022,7 @@ msgid "Added %{label_references} %{label_text}."
msgstr "Додано %{label_references} %{label_text}."
msgid "Added a to do."
-msgstr ""
+msgstr "Додано нагадуваннÑ."
msgid "Added an issue to an epic."
msgstr "Додано задачу до епіку."
@@ -2068,6 +2093,9 @@ msgstr "Режим адмініÑтратора вимкнено"
msgid "Admin mode enabled"
msgstr "Режим адмініÑтратора ввімкнено"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "Ðотатки адмініÑтратора"
@@ -2098,9 +2126,6 @@ msgstr "Розробник"
msgid "AdminArea|Features"
msgstr "Функції"
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr "ГіÑÑ‚ÑŒ"
@@ -2134,7 +2159,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr "ВлаÑник"
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -2158,6 +2183,9 @@ msgstr "Загальна кількіÑÑ‚ÑŒ кориÑтувачів"
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "СтатиÑтика кориÑтувачів"
@@ -2167,7 +2195,13 @@ msgstr "КориÑтувачі з найвищою роллю"
msgid "AdminArea|Users without a Group and Project"
msgstr "КориÑтувачі без групи та проєкту"
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2197,9 +2231,6 @@ msgstr "Домен Auto DevOps"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів"
@@ -2221,6 +2252,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "ВідÑутній обов’Ñзковий конвеєр"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "Ðеобхідна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñƒ"
@@ -2371,6 +2405,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Ðеможливо розблокувати кориÑтувачів заблокованих в LDAP"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "Деактивувати"
@@ -2398,6 +2435,9 @@ msgstr "Видалити кориÑтувача"
msgid "AdminUsers|Delete user and contributions"
msgstr "Видалити кориÑтувача Ñ– його внеÑки"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "Зовнішні"
@@ -2506,6 +2546,9 @@ msgstr "КориÑтувач не зможе отримувати доÑтуп Ð
msgid "AdminUsers|User will not be able to login"
msgstr "КориÑтувач не зможе увійти в ÑиÑтему"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "Коли кориÑтувач повторно увійде у ÑиÑтему, його обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾ активуєтьÑÑ Ð² повній мірі"
@@ -2936,8 +2979,8 @@ msgstr ""
msgid "Alerts"
msgstr "ПопередженнÑ"
-msgid "Alerts endpoint"
-msgstr "Кінцева точка Ð´Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½ÑŒ"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -3077,8 +3120,8 @@ 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 public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "Дозволити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ñ–Ð°Ð³Ñ€Ð°Ð¼ PlantUML в документах Asciidoc."
@@ -3128,6 +3171,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¸Ñ… доменів Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти допуÑкаєтьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ найвищого рівнÑ"
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "Ðевдача дозволена"
@@ -3179,6 +3225,9 @@ 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 ""
@@ -3206,6 +3255,9 @@ msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "Помилка при додаванні чернетки до обговореннÑ."
@@ -3422,6 +3474,9 @@ msgstr "Помилка при завантаженні файлу."
msgid "An error occurred while loading the file. Please try again later."
msgstr "Помилка при завантаженні файлу. Будь лаÑка, Ñпробуйте ще раз пізніше."
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "Помилка при завантаженні змін запиту на злиттÑ."
@@ -3593,6 +3648,9 @@ msgstr "Проаналізуйте ваш вихідний код на предÐ
msgid "Ancestors"
msgstr "Предки"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "Ðнонімно"
@@ -3707,12 +3765,6 @@ msgstr "ЗаÑтоÑувати зміни"
msgid "Apply suggestion"
msgstr "ЗаÑтоÑувати пропозицію"
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr "ЗаÑтоÑувати пропозиції"
@@ -3885,8 +3937,8 @@ 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}"
-msgstr "ÐÑ€Ñ…Ñ–Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ зробить його доÑтупним лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. Він буде прихований з панелі ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– не відображатиметьÑÑ Ð² пошуках. %{strong_start}Ð’ репозиторій не можна буде комітити, Ñ– не можливо буде Ñтворити жодних задач, коментарів чи інших об'єктів.%{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
@@ -3976,15 +4028,18 @@ msgstr "Ви впевнені, що хочете видалити цю іденÑ
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 "Ви впевнені, що Ви хочете перегенерувати цей ключ перевірки працездатноÑÑ‚Ñ–?"
+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 ""
@@ -4054,8 +4109,8 @@ msgstr "ОÑобиÑтий токен доÑтупу кориÑтувача. КÐ
msgid "Ascending"
msgstr "За зроÑтаннÑм"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "ЗвернітьÑÑ Ð´Ð¾ керівника групи, щоб налаштувати груповий Runner."
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "URL-адреÑа Ñлужби обробника тверджень"
@@ -4078,9 +4133,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr "Призначити влаÑний колір типу #FF0000"
-msgid "Assign epic"
-msgstr "Призначити епік"
-
msgid "Assign labels"
msgstr "Призначити мітку"
@@ -4335,9 +4387,6 @@ msgstr "ÐвторизуватиÑÑ %{link_to_client} викориÑтовуюÑ
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr "Ðвторизовано %{new_chat_name}"
@@ -4362,8 +4411,8 @@ msgstr "Auto DevOps, runner'и і артефакти завдань"
msgid "Auto stop successfully canceled."
msgstr "Ðвтозупинка уÑпішно ÑкаÑована."
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "Ðвтоматичне ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð´Ð»Ð¸ÑˆÐºÐ¾Ð²Ð¸Ñ…, очікуючих конвеєрів"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr ""
@@ -4461,17 +4510,17 @@ msgstr "ДоÑтупно"
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
-msgstr "ДоÑтупні групові Runner'и: %{runners}"
+msgid "Available runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "ДоÑтупні загальні Runner'и:"
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "ДоÑтупні Ñпеціальні Runner’и"
@@ -4611,26 +4660,26 @@ msgstr "Будьте обережні. ÐŸÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸
msgid "Begin with the selected commit"
msgstr "Почати із виділеного коміту"
-msgid "Below are examples of regex for existing tools:"
-msgstr "Ðижче наведені приклади регулÑрних виразів Ð´Ð»Ñ Ñ–Ñнуючих інÑтрументів:"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "Ðижче наведено відбитки SSH-ключів хоÑта поточного інÑтанÑу."
msgid "Below you will find all the groups that are public."
msgstr "Ðижче ви знайдете вÑÑ– загальнодоÑтупні групи."
+msgid "Beta"
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
-msgid "Billable Users:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr "Білінг"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name} наразі викориÑтовує план %{plan_name}."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "@%{user_name} наразі ви викориÑтовуєте план %{plan_name}."
@@ -4638,11 +4687,17 @@ msgstr "@%{user_name} наразі ви викориÑтовуєте план %{
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 "Якщо ви хочете перейти на нижчий план, будь лаÑка, зв'ÑжітьÑÑ Ð· %{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 Gold."
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про кожен план, прочитавши наш %{faq_link}, або розпочніть безкоштовну 30-денну пробну верÑÑ–ÑŽ GitLab.com Gold."
+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 "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про кожен план перейшовши на %{pricing_page_link}."
@@ -4662,6 +4717,9 @@ msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° викориÑтовує план, пов'Ñзаний Ð
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ð»Ð°Ð½Ð¾Ð¼ цієї групи відвідайте Ñекцію оплати %{parent_billing_page_link}."
+msgid "BillingPlans|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 ""
@@ -4671,6 +4729,9 @@ msgstr "Ваша пробна верÑÑ–Ñ GitLab.com закінчилаÑÑ %{e
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "рахунок виÑтавлÑєтьÑÑ Ñ‰Ð¾Ñ€Ñ–Ñ‡Ð½Ð¾ %{price_per_year}"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "ЧаÑÑ‚Ñ– питаннÑ"
@@ -4686,6 +4747,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr "Підвищити"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4774,10 +4838,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4801,6 +4865,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "Згорнути"
@@ -4996,6 +5063,9 @@ msgstr "ÐалаштуваннÑÑ… проєкту"
msgid "Branches|protected"
msgstr "захищена"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -5035,16 +5105,25 @@ msgstr "Вбудований"
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -5095,6 +5174,9 @@ msgstr ""
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 ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -5104,6 +5186,9 @@ msgstr "За замовчуваннÑм GitLab відправлÑÑ” електр
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "За замовчуваннÑм уÑÑ– проєкти та групи будуть викориÑтовувати глобальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень."
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "від"
@@ -5140,6 +5225,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторіÑ"
@@ -5248,9 +5336,6 @@ msgstr "Ðеможливо оновити Ñніпет: %{err}"
msgid "Canary"
msgstr "Canary"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "Canary Deployments — це популÑрна ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ð±ÐµÐ·Ð¿ÐµÑ€ÐµÑ€Ð²Ð½Ð¾Ñ— інтеграції, коли нова верÑÑ–Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ заÑтоÑунку вÑтановлюєтьÑÑ Ð½Ð° невелику кількіÑÑ‚ÑŒ машин."
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5401,6 +5486,12 @@ msgstr "Змінити шлÑÑ…"
msgid "Change permissions"
msgstr "Змінити права доÑтупу"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr "Змінити ÑтатуÑ"
@@ -5443,6 +5534,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Вибрати (cherry-pick)"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "Ðнулювати коміт"
@@ -5467,6 +5561,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "Змінено виконавцÑ(ців)."
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr "Змінено заголовок на \"%{title_param}\"."
@@ -5569,6 +5666,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "ПереглÑньте %{docs_link_start}документацію%{docs_link_end}."
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr "Перевірте Ñвої образи Docker на наÑвніÑÑ‚ÑŒ відомих вразливоÑтей."
@@ -5782,9 +5882,6 @@ msgstr "Вибрати будь-Ñкий колір."
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr "Виберіть файл…"
@@ -5803,6 +5900,9 @@ 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 "Виберіть, Ñкі репозиторії ви хочете підключити Ñ– запуÑтити конвеєри CI/CD."
@@ -5962,12 +6062,24 @@ msgstr "Мітка клаÑифікації (необов'Ñзково)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "не доÑтупно: %{reason}"
+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 "ОчиÑтити"
@@ -6010,8 +6122,8 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "ÐатиÑніть кнопку нижче, щоб розпочати Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð²ÑтановленнÑ, перейшовши на Ñторінку Kubernetes"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "ÐатиÑніть, щоб розгорнути його."
@@ -7189,7 +7301,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7207,9 +7319,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr "Шаблон"
-msgid "Cohorts"
-msgstr "Когорти"
-
msgid "Cohorts|Inactive users"
msgstr "Ðеактивні кориÑтувачі"
@@ -7246,6 +7355,9 @@ msgstr "Згорнути відповіді"
msgid "Collapse sidebar"
msgstr "Згорнути панель"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr "Ім'Ñ Ñ…Ð¾Ñта колектора"
@@ -7469,6 +7581,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7643,9 +7761,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr "ЗвернітьÑÑ Ð´Ð¾ відділу продажів Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ñƒ на вищий тарифний план"
-
msgid "Contact support"
msgstr "ЗвернутиÑÑ Ð´Ð¾ Ñлужби підтримки"
@@ -7759,9 +7874,15 @@ msgstr "Скопіювати команду входу"
msgid "ContainerRegistry|Copy push command"
msgstr "Скопіювати команду відправленнÑ"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7789,6 +7910,15 @@ msgstr "Якщо ви ще не виконали вхід вам необхідÐ
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7883,6 +8013,9 @@ 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 ""
@@ -7910,9 +8043,15 @@ 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 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 ""
@@ -7928,9 +8067,15 @@ 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 ""
@@ -8108,6 +8253,9 @@ msgstr "Скопіювати команди"
msgid "Copy commit SHA"
msgstr "Скопіювати SHA коміту"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr "Копіювати Ñередовище"
@@ -8162,6 +8310,9 @@ msgstr "Скопіювати токен тригера"
msgid "Copy value"
msgstr "Копіювати значеннÑ"
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ адмініÑтраторів Ñк учаÑників"
@@ -8463,12 +8614,24 @@ msgstr "Створити токен Ð´Ð»Ñ Ð¾ÑобиÑтого доÑтупу"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8484,16 +8647,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8505,9 +8665,15 @@ 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 ""
@@ -8523,6 +8689,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8538,6 +8707,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "Створено"
@@ -8637,12 +8809,12 @@ msgstr ""
msgid "Current Branch"
msgstr "Поточна гілка"
-msgid "Current Plan"
-msgstr "Поточний План"
-
msgid "Current Project"
msgstr "Поточний проєкт"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "Поточний вузол"
@@ -8667,8 +8839,8 @@ msgstr "Профіль"
msgid "CurrentUser|Settings"
msgstr "ÐалаштуваннÑ"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "Розпочати пробну верÑÑ–ÑŽ Gold"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr "Ðа вищий план"
@@ -8676,9 +8848,6 @@ msgstr "Ðа вищий план"
msgid "Custom Attributes"
msgstr "ВлаÑні атрибути"
-msgid "Custom CI configuration path"
-msgstr "КориÑтувацький шлÑÑ… до конфігурації CI"
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr "КориÑтувацька URL-адреÑа Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Git через HTTP(S)"
@@ -8751,8 +8920,8 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð²Ð¸ Ñ– параметрів, пов'Ñза
msgid "Customize name"
msgstr "Ðалаштувати ім'Ñ"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "Ðалаштуйте конфігурацію конвеєра, переглÑньте Ñтан Ñвого конвеєра Ñ– звіт про покриттÑ."
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr "Ðалаштувати конфігурацію конвеєра."
@@ -8965,8 +9134,8 @@ msgstr "%{firstProject} Ñ– %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}, %{rest}, Ñ– %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
-msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{invalidProjects}. Ð¦Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупна Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проєктів та приватних проєктів в групах із планом Silver."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
+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 ""
@@ -8995,6 +9164,12 @@ 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 ""
@@ -9007,6 +9182,9 @@ 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 ""
@@ -9019,6 +9197,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -9034,6 +9215,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -9058,7 +9242,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -9070,9 +9254,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -9112,6 +9293,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr "Режим ÑкануваннÑ"
@@ -9121,6 +9308,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -9130,9 +9320,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -9148,6 +9344,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -9157,6 +9356,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -9169,6 +9371,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9463,7 +9668,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9823,6 +10028,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr "ЧаÑтота РозгортаннÑ"
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -10006,7 +10238,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -10057,25 +10289,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -10102,22 +10334,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -10126,24 +10355,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -10165,18 +10394,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10234,8 +10457,8 @@ msgstr "Вимкнути"
msgid "Disable for this project"
msgstr "Вимкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
-msgid "Disable group Runners"
-msgstr "Вимкнути групові Runner'и"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr ""
@@ -10529,9 +10752,6 @@ msgstr "Під Ñ‡Ð°Ñ Ñ†ÑŒÐ¾Ð³Ð¾ процеÑу вам буде запропон
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr "Кожен Runner може бути в одному із таких Ñтанів:"
-
msgid "Edit"
msgstr "Редагувати"
@@ -10760,6 +10980,15 @@ 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 "EmailToken|reset it"
msgstr "Ñкинути його"
@@ -10826,6 +11055,9 @@ msgstr "Увімкнути HTML лиÑти"
msgid "Enable Incident Management inbound alert limit"
msgstr "Увімкнути ліміти попереджень Ð´Ð»Ñ Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ñ–Ð½Ñ†Ð¸Ð´ÐµÐ½Ñ‚Ð°Ð¼Ð¸"
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10835,6 +11067,9 @@ msgstr "Увімкнути PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr "Увімкнути збір даних Ð´Ð»Ñ Pseudonymizer"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10874,8 +11109,8 @@ msgstr "Увімкнути функцію Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ Ñ€Ñ–Ð²Ð½Ñ Ð´Ð¾ÑÑ
msgid "Enable for this project"
msgstr "Увімкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
-msgid "Enable group Runners"
-msgstr "Увімкнути групові Runner'и"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr "Увімкнути заголовок та футер в електронних лиÑтах"
@@ -10913,8 +11148,8 @@ msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰Ðµ
msgid "Enable proxy"
msgstr "ЗадіÑти прокÑÑ–-Ñервер"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgstr "Увімкнути reCAPTCHA або Akismet Ñ– вÑтановити Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾ IP. У випадку reCAPTCHA ми наразі підтримуємо лише %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
msgid "Enable shared runners"
msgstr ""
@@ -10976,15 +11211,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "ЗавершуєтьÑÑ Ð¾ (за Грінвічем)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr "ПримуÑово активувати захиÑÑ‚ від DNS rebinding"
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -11081,13 +11322,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
msgstr ""
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "Змінні Ñередовища налаштовані адмініÑтратором бути %{link_start}захищеними%{link_end} за замовчуваннÑм"
-
-msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11378,6 +11616,9 @@ msgstr "Помилка під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ñ–Ñ‚Ð¾Ðº."
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "Ви впевнені, що хочете видалити %{bStart}%{targetIssueTitle}%{bEnd} із %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr ""
@@ -11393,6 +11634,12 @@ msgstr "Видалити епік"
msgid "Epics|Remove issue"
msgstr "Видалити задачу"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "Показати більше"
@@ -11783,9 +12030,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "Приклад: @sub\\.company\\.com$"
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr "Ðаприклад: Usage = одиночний запит. (Requested) / (Capacity) = кілька запитів, пов’Ñзаних у формулу."
@@ -11921,15 +12165,21 @@ msgstr ""
msgid "Export project"
msgstr "ЕкÑпорт проєкту"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr "ЕкÑпортуйте цю групу з уÑіма відповідними даними в новий екземплÑÑ€ GitLab. ПіÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð²Ð¸ зможете імпортувати файл даних зі Ñторінки \"Ðова Група\"."
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "ЕкÑпортувати цей проєкт з уÑіма пов'Ñзаними даними Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб переміÑтити його на новий інÑÑ‚Ð°Ð½Ñ GitLab. ПіÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ÐµÐºÑпорту ви зможете імпортувати файл на Ñторінці \"Ðовий проєкт\"."
+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 Classification Policy Authorization"
msgstr "Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ ÐšÐ»Ð°ÑÐ¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ ÐŸÐ¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ Ðвторизації"
@@ -12053,6 +12303,9 @@ msgstr "Ðе вдалоÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚Ð¸ rebase в чергу, можливÐ
msgid "Failed to find import label for Jira import."
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ мітку Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ ÑиÑтеми Jira."
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ref."
@@ -12236,9 +12489,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr "Fast-forward Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÐµÐ· окремого коміту злиттÑ"
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr "Швидше, бо повтоно викориÑтовує робочу облаÑÑ‚ÑŒ проєкту (викориÑтовуючи clone, Ñкщо та відÑутнÑ)"
-
msgid "Faster releases. Better code. Less pain."
msgstr "Швидші релізи. Кращий код. Менше болю."
@@ -12756,10 +13006,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12783,12 +13045,6 @@ msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, пÐ
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… проєктів будь-Ñкий кориÑтувач (гіÑÑ‚ÑŒ або вище) може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "Ð”Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проєктів будь-Ñкий зареєÑтрований кориÑтувач може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
-
msgid "Forgot your password?"
msgstr "Забули ваш пароль?"
@@ -12864,8 +13120,8 @@ msgstr "З моменту ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– до розгортаÐ
msgid "From merge request merge until deploy to production"
msgstr "Від Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "Із Ñторінки деталей Kubernetes-клаÑтера, вÑтановіть runner зі ÑпиÑку заÑтоÑунків"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr "Повне ім'Ñ"
@@ -12912,6 +13168,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Гео-Вузли"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr "Ðеможливо видалити оÑновний вузол, Ñкщо Ñ” вторинний"
@@ -13326,8 +13585,8 @@ msgstr "Git-редакціÑ"
msgid "Git shallow clone"
msgstr "ЧаÑтковий (shallow) клон Git"
-msgid "Git strategy for pipelines"
-msgstr "Git Ñтратегії Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr ""
@@ -13356,9 +13615,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "Групові Runner'и Gitlab можуть виконувати код Ð´Ð»Ñ ÑƒÑÑ–Ñ… проєктів у цій групі."
-
msgid "GitLab Import"
msgstr "Імпорт з GitLab"
@@ -13395,6 +13651,9 @@ msgstr "ЕкÑпорт GitLab"
msgid "GitLab for Slack"
msgstr "GitLab Ð´Ð»Ñ Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13479,9 +13738,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "ПіÑÐ»Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñайт може бути недоÑтупним до 30 хвилин."
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr "ДізнайтеÑÑ Ñк розміÑтити ваш Ñтатичний Ñайт на GitLab переглÑнувши %{link_start}документацію по GitLab Pages%{link_end}."
-
msgid "GitLabPages|Learn more."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ."
@@ -13509,6 +13765,9 @@ msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñторінок зробить Ñ—Ñ… недоÑтуп
msgid "GitLabPages|Save"
msgstr "Зберегти"
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 "ЩоÑÑŒ пішло не так при отриманні Ñертифікату Let's Encrypt Ð´Ð»Ñ %{domain}. Перевірте %{link_start}деталі домену%{link_end}, щоб повторити Ñпробу."
@@ -13782,9 +14041,6 @@ msgstr "Групу %{group_name} уÑпішно Ñтворено."
msgid "Group Audit Events"
msgstr "Групові події аудиту"
-msgid "Group CI/CD settings"
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD групи"
-
msgid "Group Git LFS status:"
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð³Ñ€ÑƒÐ¿Ð¸ Git LFS:"
@@ -13800,9 +14056,6 @@ msgstr "ID групи: %{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr "Групові Runner'и"
-
msgid "Group SAML must be enabled to test"
msgstr "SAML Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸ повинна бути включена Ð´Ð»Ñ Ñ‚ÐµÑтуваннÑ"
@@ -13854,6 +14107,12 @@ msgstr "Керівники групи можуть зареєÑтрувати г
msgid "Group members"
msgstr "КориÑтувачі групи"
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13863,6 +14122,9 @@ msgstr "Ðазва групи"
msgid "Group name (your organization)"
msgstr "Ðазва групи (ваша організаціÑ)"
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr "ОглÑд групи"
@@ -13887,6 +14149,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr "Група вимагає окремий обліковий запиÑ"
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "Змінні групи (уÑпадковані)"
@@ -14286,9 +14554,6 @@ msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "Групи з доÑтупом до %{strong_start}%{group_name}%{strong_end}"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -14355,6 +14620,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14597,6 +14865,12 @@ msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно розпочато"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "ОчищеннÑ, екÑпорт, шлÑÑ…, перенеÑеннÑ, видаленнÑ, архівуваннÑ."
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14708,9 +14982,6 @@ msgstr "ІдентифікаціÑ"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-msgstr "Якщо будь-Ñке Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ²Ð¸Ñ‰Ð¸Ñ‚ÑŒ цей чаÑовий поріг, воно буде відмічене Ñк невдале. Ð”Ð»Ñ Ð²Ð²Ð¾Ð´Ñƒ чаÑу підтримуєтьÑÑ \"людÑкий\" формат, наприклад \"1 hour\" (1 година). Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±ÐµÐ· одиниць виміру предÑтавлÑÑŽÑ‚ÑŒ Ñекунди."
-
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 ""
@@ -14726,18 +14997,15 @@ msgstr "Якщо вимкнено, локальна гілка зі змінам
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr "Якщо вимкнено, лише адмініÑтратори зможуть налаштовувати Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²."
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "Якщо це відключено, то рівень доÑтупу буде залежати від дозволів кориÑтувача в проєкті."
-
-msgid "If enabled"
-msgstr "Якщо увімкнено"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14990,15 +15258,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr "Інцидент"
@@ -15134,9 +15747,39 @@ 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 ""
@@ -15218,8 +15861,8 @@ msgstr "Вбудований"
msgid "Input host keys manually"
msgstr "Введіть ключі хоÑта вручну"
-msgid "Input your repository URL"
-msgstr "Введіть ваш URL репозиторію"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr "Ð’Ñтавити блок коду"
@@ -15260,11 +15903,11 @@ msgstr ""
msgid "Install"
msgstr "Ð’Ñтановити"
-msgid "Install GitLab Runner"
-msgstr "Ð’Ñтановити GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "Ð’Ñтановити Runner на Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "Ð’Ñтановіть програмний автентифікатор, наприклад %{free_otp_link} або Google Authenticator зі Ñвого репозиторію заÑтоÑунків Ñ– викориÑтовуйте його Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ QR-коду. Більш детальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð¾Ñтупна в %{help_link_start}документації%{help_link_end}."
@@ -15291,9 +15934,21 @@ msgstr[3] "ІнÑтанÑів"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15399,6 +16054,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr "Ð’ÑÑ– деталі"
@@ -15429,6 +16087,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15438,12 +16102,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15468,6 +16138,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15495,6 +16168,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15582,6 +16258,9 @@ msgstr "Ðекорректний ввід, будь лаÑка, уникайте
msgid "Invalid login or password"
msgstr "Ðеправильний логін або пароль"
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "Ðеправильний PIN-код"
@@ -15642,6 +16321,9 @@ msgstr "ЗапроÑити групу"
msgid "Invite member"
msgstr "ЗапроÑити учаÑника"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15897,6 +16579,12 @@ msgstr "СтатуÑ"
msgid "IssueAnalytics|Weight"
msgstr "Вага"
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15951,9 +16639,6 @@ msgstr "Задачі можуть бути помилками, нагадуваÐ
msgid "Issues closed"
msgstr "Задачі закриті"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "Задачі з коментарÑми, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð· порівнÑннÑми (diff) та коментарÑми, мітки, етапи, Ñніпети та інші об'єкти в проєкті"
@@ -15993,6 +16678,9 @@ 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 ""
@@ -16095,24 +16783,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr "%{user_link} вказав цю задачу в %{entity_link} з %{project_link}%{branch}:{quote}%{entity_message}{quote}"
+msgid "JiraService|An error occured while fetching issue list"
+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 "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ Jira при увімкненій функціональноÑÑ‚Ñ– задач Gitlab може заплутати. Подумайте про %{linkStart}Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ GitLab%{linkEnd}, Ñкщо вони не викориÑтовуютьÑÑ."
msgid "JiraService|Enable Jira issues"
msgstr "Увімкнути задачі Jira"
+msgid "JiraService|Enable Jira issues creation from vulnerabilities"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Події Ð´Ð»Ñ %{noteable_model_name} вимкнені."
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "Якщо відрізнÑєтьÑÑ Ð²Ñ–Ð´ Веб URL"
msgid "JiraService|Issue List"
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 "URL-адреÑа Jira API"
@@ -16128,6 +16834,9 @@ msgstr "Коментарі в Jira будуть ÑтворюватиÑÑ ÐºÐ¾Ð»Ð
msgid "JiraService|Jira issue tracker"
msgstr "РеєÑÑ‚Ñ€ задач Jira"
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Ключ проєкту Jira"
@@ -16140,9 +16849,21 @@ msgstr "Відкрити Jira"
msgid "JiraService|Password or API token"
msgstr "Пароль або API токен"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -16221,6 +16942,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16260,8 +16984,8 @@ msgstr "Ðртефакти завдань"
msgid "Job|Job has been erased"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтерте"
-msgid "Job|Job has been erased by"
-msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтерте"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "Залишити"
@@ -16335,6 +17059,9 @@ msgstr "Лише Ñ"
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16362,6 +17089,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16549,8 +17279,8 @@ msgstr "ОÑтанній контакт"
msgid "Last edited %{date}"
msgstr "ОÑтанні зміни %{date}"
-msgid "Last edited by %{name}"
-msgstr "ОÑтанні зміни від %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr ""
@@ -16633,7 +17363,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "ДізнатиÑÑ Ð¿Ñ€Ð¾ GitLab"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16654,9 +17384,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps"
-msgid "Learn more about Kubernetes"
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
-
msgid "Learn more about License-Check"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про License-Check"
@@ -16970,6 +17697,9 @@ msgstr[3] "Показ обмежено тільки %d подіÑми"
msgid "Line changes"
msgstr "Зміни Ñ€Ñдка"
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -17144,9 +17874,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr "ЗЛИТО"
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -17171,6 +17898,12 @@ 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 "Показувати лише зміни"
@@ -17195,9 +17928,6 @@ msgstr "Зробити задачу конфіденційною"
msgid "Make sure you save it - you won't be able to access it again."
msgstr "ПереконайтеÑÑ, що ви його зберегли, бо ви не зможете отримати доÑтуп до нього знову."
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr "Робить цю задачу конфіденційною."
@@ -17240,6 +17970,9 @@ msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾ÑŽ автентифікаціє
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17432,12 +18165,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
-msgstr "МакÑимальна КількіÑÑ‚ÑŒ КориÑтувачів:"
+msgid "Maximum Users"
+msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr "МакÑимально допуÑтимий термін дії токена перÑонального доÑтупу (днів)"
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr "МакÑимальний розмір артефактів (МБ)"
@@ -17477,9 +18213,6 @@ msgstr "МакÑимальний Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr "МакÑимальний Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ має недопуÑтиме значеннÑ"
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17522,6 +18255,9 @@ msgstr "МакÑимальний можливий Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ оновленн
msgid "May"
msgstr "травень"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17549,9 +18285,6 @@ msgstr "КориÑтувачі"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17570,9 +18303,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "УчаÑники із доÑтупом до %{strong_start}%{group_name}%{strong_end}"
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17669,6 +18399,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17762,6 +18495,9 @@ msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»Ñ
msgid "Merge request dependencies"
msgstr "ЗалежноÑÑ‚Ñ– запиту на злиттÑ"
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17843,9 +18579,6 @@ msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "ÐевдалоÑÑ Ð¾Ð±â€™Ñ”Ð´Ð½Ð°Ñ‚Ð¸ коміти. Це повинно бути виконано вручну."
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr "ВідповіÑти..."
@@ -17912,15 +18645,9 @@ msgstr "Файлів не знайдено"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "Злито"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18321,6 +19048,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "ПеренеÑено %{success_count}/%{total_count} файлів."
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr "ÐœÑ–Ð³Ñ€Ð°Ñ†Ñ–Ñ ÑƒÑпішна."
@@ -18493,6 +19223,9 @@ msgstr "Хвилин"
msgid "Mirror direction"
msgstr "ÐапрÑмок віддзеркаленнÑ"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "Віддзеркалити репозиторій"
@@ -18544,9 +19277,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr "Додати проєкти"
-msgid "Modal|Cancel"
-msgstr "СкаÑувати"
-
msgid "Modal|Close"
msgstr "Закрити"
@@ -18715,9 +19445,6 @@ msgstr "Ім’Ñ"
msgid "Name has already been taken"
msgstr "Ð†Ð¼â€™Ñ Ð²Ð¶Ðµ викориÑтовуєтьÑÑ"
-msgid "Name is required"
-msgstr "Ð†Ð¼â€™Ñ Ð¾Ð±Ð¾Ð²Ê¼Ñзкове"
-
msgid "Name new label"
msgstr "Ðазвіть нову мітку"
@@ -18855,12 +19582,6 @@ 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 ""
@@ -18879,6 +19600,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18933,6 +19660,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -19183,8 +19913,8 @@ msgstr "Ðовий етап"
msgid "New password"
msgstr "Ðовий пароль"
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "Ðові конвеєри ÑкаÑують Ñтарі, що очікують на тій же гілці"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "Ðовий проєкт"
@@ -19300,6 +20030,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Ðеможливо з'єднатиÑÑŒ із Ñервером Gitaly, будь лаÑка, перевірте логи!"
@@ -19393,6 +20126,9 @@ msgstr "Ðемає відповідних результатів"
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19468,9 +20204,6 @@ msgstr "Ðіхто з тих, хто додав в обране не задовÑ
msgid "No start date"
msgstr "Ðемає дати початку"
-msgid "No status"
-msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ñ–Ð´Ñутній"
-
msgid "No template"
msgstr "Шаблон відÑутній"
@@ -19480,6 +20213,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr "ВразливоÑÑ‚Ñ– відÑутні"
@@ -19855,6 +20591,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19864,12 +20603,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19930,10 +20675,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19945,9 +20690,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19999,10 +20753,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -20042,7 +20796,7 @@ msgstr ""
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
msgstr "Термін дії одного або декількох ваших токенів оÑобиÑтого доÑтупу закінчитьÑÑ Ñ‡ÐµÑ€ÐµÐ· %{days_to_expire} днів або раніше."
-msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -20060,9 +20814,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr "Тільки адмініÑтратори можуть видалÑти проєкт"
-msgid "Only mirror protected branches"
-msgstr "Віддзеркалювати лише захищені гілки"
-
msgid "Only policy:"
msgstr "Политика включеннÑ:"
@@ -20081,8 +20832,8 @@ 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 / Silver and above can see Productivity Analytics."
-msgstr "Лише \"Репортер\" та більш виÑокі ролі на рівнÑÑ… Premium / Silver та вище можуть переглÑдати аналітику продуктивноÑÑ‚Ñ–."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
+msgstr ""
msgid "Oops, are you sure?"
msgstr "Ой, а ви впевнені?"
@@ -20189,15 +20940,15 @@ msgstr "Параметри"
msgid "Or you can choose one of the suggested colors below"
msgstr "Ðбо ви можете вибрати один із запропонованих нижче кольорів"
-msgid "Origin"
-msgstr "Джерело"
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr "Інші мітки"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "Інша інформаціÑ"
@@ -20372,9 +21123,6 @@ msgstr "Видалити верÑÑ–ÑŽ пакету"
msgid "PackageRegistry|Delete package"
msgstr "Видалити пакет"
-msgid "PackageRegistry|Filter by name"
-msgstr "Фільтр за іменем"
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20393,6 +21141,9 @@ msgstr "Щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про реєÑÑ‚Ñ€ PyPi, %{linkS
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "Якщо ви ще не зробили цього, вам потрібно буде додати розміщене нижче в Ñвій файл %{codeStart}.pypirc%{codeEnd}."
@@ -20465,9 +21216,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr "Ðемає ще %{packageType} пакетів"
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr "Ðемає інших верÑій цього пакету."
@@ -20483,6 +21231,9 @@ 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 ""
@@ -20621,6 +21372,9 @@ msgstr "ЧаÑтковий токен тільки Ð´Ð»Ñ Ð¿Ð¾ÑиланнÑ"
msgid "Participants"
msgstr "УчаÑники"
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr "УÑпішно пройдено"
@@ -20735,6 +21489,9 @@ msgstr "Завантажити"
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20801,6 +21558,9 @@ msgstr "Розклад Конвеєра"
msgid "Pipeline Schedules"
msgstr "Розклади Конвеєрів"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "Квота хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
@@ -20813,6 +21573,9 @@ 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 "Тригери конвеєру"
@@ -20981,9 +21744,6 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
msgid "Pipelines|More Information"
msgstr "Більше інформації"
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20996,9 +21756,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr "Кеш проєкту уÑпішно очищено."
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr "Відкликати"
@@ -21020,6 +21777,9 @@ msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” завершених конвеєрів.
msgid "Pipelines|There are currently no pipelines."
msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” конвеєрів."
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "Помилка при отриманні конвеєрів. Спробуйте знову через декілька хвилин, або звернітьÑÑ Ð´Ð¾ Ñлужби підтримки."
@@ -21134,6 +21894,9 @@ msgstr "ЗапуÑтити Конвеєр"
msgid "Pipeline|Run for"
msgstr "ЗапуÑтити длÑ"
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr "Запущено"
@@ -21803,12 +22566,15 @@ msgstr "Токен доÑтупу до каналів уÑпішно перегÐ
msgid "Profiles|Full name"
msgstr "Повне ім'Ñ"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "Включити приватні внеÑки до мого профілю"
@@ -21854,9 +22620,6 @@ msgstr "ОрганізаціÑ"
msgid "Profiles|Path"
msgstr "ШлÑÑ…"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "Спозиціонуйте ваш аватар та задайте його розмір"
@@ -22139,6 +22902,9 @@ msgstr "Ðазва проєкту"
msgid "Project name suffix"
msgstr "Ð¡ÑƒÑ„Ñ–ÐºÑ Ð½Ð°Ð·Ð²Ð¸ проєкту"
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr "ПорÑдок проєктів не буде збережено, тому що локальне Ñховище недоÑтупне."
@@ -22556,6 +23322,9 @@ 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|What are badges?"
msgstr ""
@@ -22679,7 +23448,7 @@ msgstr "Проекти, що належать до групи, викориÑÑ‚Ð
msgid "Projects to index"
msgstr "Проекти Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -23054,6 +23823,9 @@ msgstr "Пропонувати кориÑтувачам завантажуват
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -23102,6 +23874,9 @@ msgstr "Дозволена відправка:"
msgid "ProtectedBranch|Branch"
msgstr "Гілка"
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñника коду"
@@ -23138,6 +23913,9 @@ msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¾"
msgid "ProtectedEnvironment|Environment"
msgstr "Середовище"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "ЗахиÑтити"
@@ -23147,9 +23925,6 @@ msgstr "ЗахиÑити Ñередовище"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "ЗахиÑтити Середовище (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr "ЗахиÑÑ‚ Ñередовища обмежує коло кориÑтувачів, здатних здійÑнювати розгортаннÑ."
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "Виберіть Ñередовище"
@@ -23159,8 +23934,8 @@ msgstr "Виберіть кориÑтувачів"
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr "Виберіть кориÑтувачів Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ð°Ð¼Ð¸ функцій"
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "Ðаразі немає захищених Ñередовищ, захиÑÑ‚Ñ–Ñ‚ÑŒ Ñередовище за допомогою форми, що знаходитьÑÑ Ð²Ð¸Ñ‰Ðµ."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "ЗнÑти захиÑÑ‚"
@@ -23378,6 +24153,9 @@ msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про пов’Ñзані задачі"
msgid "Real-time features"
msgstr "Фунції реального чаÑу"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr "Rebase"
@@ -23493,12 +24271,21 @@ msgstr "ЗареєÑтрувати універÑальний двофактор
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "ЗареєÑтрувати за допомогою двофакторного заÑтоÑунку"
@@ -23526,21 +24313,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "Пов’Ñзані розгорнуті Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ (Jobs)"
-
msgid "Related Issues"
msgstr "Пов’Ñзані задачі"
-msgid "Related Jobs"
-msgstr "Пов’Ñзані Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ (Jobs)"
-
-msgid "Related Merge Requests"
-msgstr "Пов'Ñзані запити на злиттÑ"
-
-msgid "Related Merged Requests"
-msgstr "Пов'Ñзані виконані запити"
-
msgid "Related issues"
msgstr ""
@@ -23638,9 +24413,6 @@ msgstr "Видалити"
msgid "Remove %{displayReference}"
msgstr "Видалити %{displayReference}"
-msgid "Remove Runner"
-msgstr "Видалити Runner"
-
msgid "Remove Zoom meeting"
msgstr "Видалити Zoom-зуÑтріч"
@@ -23734,6 +24506,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "Видалити вторинний вузол"
@@ -23985,6 +24760,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
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] ""
@@ -24154,6 +24936,9 @@ msgstr "Сховище репозиторію"
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24291,8 +25076,8 @@ msgstr "Оновити токен доÑтупу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ прÐ
msgid "Reset key"
msgstr "Скинути ключ"
-msgid "Reset runners registration token"
-msgstr "Перегенерувати реєÑтраційний токен runner-ів"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr "Скинути шаблон"
@@ -24414,6 +25199,9 @@ msgstr "Спробувати знову"
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "Повторити це завданнÑ"
@@ -24463,6 +25251,9 @@ 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 "ПереглÑте Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð²Ð°Ð¹Ð´ÐµÑ€Ñ–Ð² поÑлуг у вашому провайдері ідентифікації — в такому разі GitLab Ñ” \"провайдером поÑлуг\" або \"довірÑючою Ñтороною\"."
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr ""
@@ -24506,6 +25297,9 @@ msgstr "Відкликано перÑональний токен доÑтупу
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr "додаваннÑ"
@@ -24551,6 +25345,9 @@ msgstr "ПротеÑтувати ваш запущений код за допоÐ
msgid "Run untagged jobs"
msgstr "Виконати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24572,21 +25369,9 @@ msgstr "Runner оновлено уÑпішно."
msgid "Runners"
msgstr "Runner'и"
-msgid "Runners API"
-msgstr "API Runner’ів"
-
-msgid "Runners activated for this project"
-msgstr "Runner'и активовані Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Runner’и можуть розміщуватиÑÑ Ñƒ різних кориÑтувачів, на Ñерверах Ñ– навіть на вашій локальній машині."
-
msgid "Runners can be:"
msgstr ""
@@ -24599,21 +25384,36 @@ msgstr "Сторінка Runner'ів."
msgid "Runners|Active"
msgstr "Ðктивні"
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr "Ðрхітектура"
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr "ОпиÑ"
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr "Група"
msgid "Runners|IP Address"
msgstr "IP-адреÑа"
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "ОÑтанній контакт"
@@ -24635,24 +25435,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr "Захищені"
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "ВерÑÑ–Ñ"
msgid "Runners|Shared"
msgstr "Спільні"
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr "ЗначеннÑ"
msgid "Runners|Version"
msgstr "ВерÑÑ–Ñ"
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² загальних runner'ів."
@@ -24725,6 +25540,9 @@ msgstr "Відкритий SSH-ключ"
msgid "SSL Verification:"
msgstr "Перевірка SSL:"
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -25093,6 +25911,9 @@ msgstr "Секрет"
msgid "Secret Detection"
msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ Ñекретів"
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "Безпека"
@@ -25108,6 +25929,9 @@ 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 ""
@@ -25267,9 +26091,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr "Сховати відхилені"
@@ -25333,9 +26154,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25445,13 +26263,13 @@ msgstr "ПереглÑнути метрики"
msgid "See the affected projects in the GitLab admin panel"
msgstr "ПереглÑнути уÑÑ– уражені проєкти на панелі адмініÑтратора GitLab"
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25511,8 +26329,8 @@ msgstr "Вибрати чаÑовий поÑÑ"
msgid "Select all"
msgstr "Вибрати вÑе"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "Виберіть Ñ–Ñнуючий клаÑтер Kubernetes або Ñтворіть новий"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr "Виберіть виконавцÑ"
@@ -25541,6 +26359,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25598,9 +26419,6 @@ msgstr "Виберіть підпиÑку"
msgid "Select target branch"
msgstr "Вибір цільової гілки"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "Виберіть гілку по замовчанню Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту. Ð’ÑÑ– запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° коміти будуть автоматично зроблені в ній, Ñкщо ви тільки не виберете іншу."
-
msgid "Select the custom project template source group."
msgstr "Вкажіть групу, де розміщені влаÑні шаблони проєктів."
@@ -25883,6 +26701,9 @@ msgstr "Ð’Ñтановити цільову гілку"
msgid "Set target branch to %{branch_name}."
msgstr "Ð’Ñтановити цільову гілку %{branch_name}."
+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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25922,11 +26743,11 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
-msgstr "Ðвтоматично налаштувати %{type} Runner"
+msgid "Set up a %{type} runner automatically"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "Ðалаштуйте %{type} runner вручну"
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr ""
@@ -25940,9 +26761,6 @@ msgstr ""
msgid "Set up new password"
msgstr "Ð’Ñтановити новий пароль"
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -26087,9 +26905,6 @@ msgstr "Обнулити викориÑтані хвилини в конвеєр
msgid "Sherlock Transactions"
msgstr "Sherlock транзакції"
-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 %{b_start}will%{b_end} lose access to your account."
-msgstr "Якщо ви коли-небудь втратите телефон або доÑтуп до Ñвоїх одноразових паролів, кожен із цих кодів Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути викориÑтаний один раз Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу до вашого облікового запиÑу. Будь лаÑка, зберігайте Ñ—Ñ… в надійному міÑці, інакше ви %{b_start}втратите%{b_end} доÑтуп до вашого облікового запиÑу."
-
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 ""
@@ -26144,6 +26959,9 @@ msgstr ""
msgid "Show latest version"
msgstr "Показати оÑтанню верÑÑ–ÑŽ"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr "Показати ÑпиÑок"
@@ -26386,9 +27204,6 @@ msgstr "ПереглÑньте ÑпиÑок уÑÑ–Ñ… доÑтупних кома
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "Цей ÑÐµÑ€Ð²Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” кориÑтувачам виконувати загальні операції в цьому проєкті шлÑхом вводу команд із коÑою риÑкою (/) в Slack."
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "Повільніше, але гарантує, що робоча облаÑÑ‚ÑŒ проєкту чиÑтою, оÑкільки воно клонує Ñховище з Ð½ÑƒÐ»Ñ Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ завданнÑ"
-
msgid "Smartcard"
msgstr "Смарт-карта"
@@ -26533,6 +27348,9 @@ 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 %{listType} list"
msgstr "Помилка при отриманні ÑпиÑку %{listType}"
@@ -26899,8 +27717,8 @@ msgstr "ЗахиÑÑ‚ від Ñпаму Ñ– ботів"
msgid "Spam log successfully submitted as ham."
msgstr "Ð—Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾ Ñпам уÑпішно анульовано."
-msgid "Specific Runners"
-msgstr "Спеціальні Runner’и"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr "Вказана URL-адреÑа не може бути викориÑтана: \"%{reason}\""
@@ -26908,9 +27726,6 @@ msgstr "Вказана URL-адреÑа не може бути викориÑÑ‚Ð
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "Вкажіть шаблон адреÑи електронної пошти у виглÑді регулÑрного виразу Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб автоматично визначати внутрішніх кориÑтувачів."
-msgid "Specify the following URL during the Runner setup:"
-msgstr "Зазначте наÑтупний URL під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Runner-а:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26929,9 +27744,6 @@ msgstr ""
msgid "Stage"
msgstr "СтадіÑ"
-msgid "Stage & Commit"
-msgstr "ПроіндекÑувати та закомітити"
-
msgid "Stage data updated"
msgstr ""
@@ -26986,8 +27798,8 @@ msgstr "ЗапуÑтити Веб-Термінал"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Почати %{new_merge_request} з цими змінами"
-msgid "Start a Free Gold Trial"
-msgstr "Розпочати безкоштовну пробну верÑÑ–ÑŽ Gold"
+msgid "Start a Free Ultimate Trial"
+msgstr ""
msgid "Start a new discussion..."
msgstr "Розпочати нове обговореннÑ..."
@@ -27019,9 +27831,6 @@ msgstr "Створити ланцюжок змін піÑÐ»Ñ ÑƒÑпішного
msgid "Start search"
msgstr "Розпочати пошук"
-msgid "Start the Runner!"
-msgstr "ЗапуÑÑ‚Ñ–Ñ‚ÑŒ Runner!"
-
msgid "Start thread"
msgstr "Розпочати обговореннÑ"
@@ -27031,7 +27840,7 @@ msgstr "Розпочати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° закрити %{noteable
msgid "Start thread & reopen %{noteable_name}"
msgstr "Розпочати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° повторно відкрити %{noteable_name}"
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -27058,15 +27867,15 @@ msgstr "ЗапуÑк..."
msgid "Starts %{startsIn}"
msgstr "Буде запущено %{startsIn}"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "ПочинаєтьÑÑ Ð¾ (за Грінвічем)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ—"
@@ -27244,6 +28053,9 @@ msgstr "Ðевідомо"
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr "ОглÑд підгрупи"
@@ -27655,6 +28467,9 @@ msgstr "Заголовок Ñ– футер ÑиÑтеми"
msgid "System hook was successfully updated."
msgstr "СиÑтемний хук уÑпішно оновлено."
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "СиÑтемні метрики (ВлаÑні)"
@@ -27679,9 +28494,15 @@ 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 "До цього коміту додано тег %{tag_name} з \"%{message}\"."
@@ -27858,15 +28679,18 @@ msgstr[3] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27921,10 +28745,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -28260,9 +29084,6 @@ msgstr[3] "ÐаÑтупні перÑональні токени доÑтупу:
msgid "The fork relationship has been removed."
msgstr "Зв'Ñзок форку видалено."
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -28317,6 +29138,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr "Ваш ліцензійний ключ недійÑний. ПереконайтеÑÑ, що він збігаєтьÑÑ Ð· тим, що ви отримали від GitLab Inc."
@@ -28335,6 +29159,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
msgstr "МакÑимальний розмір файлу — %{size}."
+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 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 "Конфлікти у цьому запитті на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ можуть бути вирішені через GitLab. Будь лаÑка, Ñпробуйте зробити це локально."
@@ -28350,8 +29183,11 @@ msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶Ðµ бути злито."
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
-msgstr "КількіÑÑ‚ÑŒ змін, Ñка буде отримуватиÑÑ Ñ–Ð· Ñерверу GitLab при клонуванні репозиторію. Це може приÑкорити Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð². Залиште порожнім, або вÑтановіть 0 Ð´Ð»Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ‡Ð°Ñткового (shallow) ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм, змуÑивши GitLab CI отримувати вÑÑ– гілки Ñ– теги кожного разу."
+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 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 ""
@@ -28368,9 +29204,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Пароль, Ñкий потрібен Ð´Ð»Ñ Ð´ÐµÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð³Ð¾ ключа. Він Ñ” необов’Ñзковим Ñ– зберігаєтьÑÑ Ñƒ зашифрованому виглÑді."
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "Фаза життєвого циклу розробки."
@@ -28416,6 +29249,9 @@ msgstr "Проект уÑпішно імпортовано."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "Збір даних пÑевдонімізованих данних вимкнено. Коли його буде увімкнено GitLab запуÑтить фонове завданнÑ, Ñке буде Ñтворювати пÑевдонімізовані CSV-файли бази даних GitLab, Ñкі будуть надÑилатиÑÑ Ð´Ð¾ вашого налаштованого Ñховища об'єктів."
+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 took to long to complete."
msgstr "Віддалене дзеркало зайнÑло забагато чаÑу Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ."
@@ -28443,9 +29279,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ° показує Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ про об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ його виконаннÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ запиту на злиттÑ."
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28500,7 +29333,7 @@ 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 "Мапа кориÑтувачів — це правила Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів FogBugz, Ñкі приймали учаÑÑ‚ÑŒ у ваших проєктах до Gitlab (зокрема Ñ—Ñ… імен та Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти). Ви можете вноÑити зміни шлÑхом Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ– нижче."
-msgid "The user you are trying to approve is not pending an approval"
+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"
@@ -28608,7 +29441,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28656,6 +29489,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28668,6 +29504,9 @@ msgstr "Проблема зі збереженнÑм вашої кориÑтув
msgid "There was a problem sending the confirmation email"
msgstr "Помилка при відÑиланні Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті"
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr "Під Ñ‡Ð°Ñ %{message} Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
@@ -28821,17 +29660,26 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° з reCAPTCHA. Будь лаÑка, пройдіть reCAPTCHA знову."
+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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
-msgstr "Ці змінні вÑтановлені в налаштуваннÑÑ… батьківÑької групи Ñ– будуть активними в поточному проєкті додатково до проєктних змінних."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
+msgstr ""
-msgid "They can be managed using the %{link}."
-msgstr "Ðими можна керувати за допомогою %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
+msgstr ""
msgid "Third Party Advisory Link"
msgstr ""
@@ -28860,8 +29708,8 @@ msgstr "Цей %{viewer} не може бути відображено череÐ
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 "Цей інÑÑ‚Ð°Ð½Ñ GitLab ще немає загальних Runner'ів. ÐдмініÑтратори можуть Ñ—Ñ… зареєÑтрувати у Ñпеціальному розділі конфігурації."
+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 ""
@@ -28875,22 +29723,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28905,13 +29765,16 @@ msgstr "Цей заÑтоÑунок було Ñтворено %{link_to_owner}."
msgid "This application will be able to:"
msgstr "Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° зможе:"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28989,9 +29852,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "Цей епік не Ñ–Ñнує або у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтатніх дозволів."
@@ -29004,14 +29864,17 @@ msgstr ""
msgid "This field is required."
msgstr "Це поле Ñ” обов'Ñзковим."
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð°"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
-msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° ще не має жодного групового Runner’а."
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr ""
@@ -29040,6 +29903,9 @@ msgstr "Це завданнÑ, відкладено на %{remainingTime}"
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 security log of important events involving your account."
msgstr "Це журнал безпеки, Ñкий міÑтить уÑÑ– важливі події пов’Ñзані із вашим обліковим запиÑом."
@@ -29163,6 +30029,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -29172,6 +30041,15 @@ 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 "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð¾."
@@ -29208,8 +30086,8 @@ msgstr ""
msgid "This project"
msgstr "Цей проєкт"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "Цей проєкт не входить до жодної групи Ñ– тому не може викориÑтовувати групові Runner’и."
+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 ""
@@ -29265,6 +30143,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Цей runner буде виконуватиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ на тих конвеєрах, Ñкі Ñпрацьовують на захищених гілках"
+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 "Цей параметр можна перевизначати Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ проєкту."
@@ -29298,18 +30179,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr "Це перенаправить Ð²Ð°Ñ Ð½Ð° зовнішню Ñторінку входу."
@@ -29723,6 +30598,9 @@ msgstr "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додати ключ SSH вам необхідÐ
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 ""
@@ -29738,6 +30616,9 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ SVN-репозиторію, переглÑн
msgid "To define internal users, first enable new users set to external"
msgstr "Ð”Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… кориÑтувачів, Ñпочатку вÑтановіть Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… кориÑтувачів \"зовнішній по замовчанню\""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29747,6 +30628,9 @@ 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 "Ð”Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ введіть URL-адреÑу FogBugz та параметри входу нижче. Далі ви зможете перенеÑти кориÑтувачів та вибрати проєкти Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ."
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr "Щоб почати роботу, з'єднайте цю Ñторінку з Ñервером Jaeger, або дізнайтеÑÑ, Ñк %{link_start_tag}вÑтановити Jaeger%{link_end_tag}"
@@ -29780,6 +30664,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr "Щоб відкривати Jaeger Ñ– легко переглÑдати інформацію про GitLab, додайте поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñторінку %{link} до вашого Ñервера"
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29795,8 +30682,8 @@ msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½ÑŒ від ÑервіÑів
msgid "To see all the user's personal access tokens you must impersonate them first."
msgstr "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ щоб бачити уÑÑ– перÑональні токени доÑтупe кориÑтувача вам необхідно Ñпочатку розпочати його імітуваннÑ."
-msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Silver%{linkEnd}. You can also remove the project from the dashboard."
-msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду оперативних даних цього проєкту %{linkStart}переведіть його групу на план Silver%{linkEnd}. Ви також можете видалити цей проєкт із панелі управліннÑ."
+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 "Щоб переглÑнути оперативні дані цього проєкту зв’ÑжітьÑÑ Ñ–Ð· влаÑником групи %{groupName} Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ñƒ на вищий тарифний план. Ви також можете видалити цей проєкт із панелі управліннÑ."
@@ -29813,12 +30700,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… завдань ви можете додати Runner’и до вашої групи"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr "Щоб почати ваші Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½ÑƒÐ²Ð°Ð»Ð¸ÑÑ, ви можете або додати Ñпеціальні Runner’и до вашого проєкту, або викориÑтовувати загальні"
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29834,9 +30715,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте дату початку чи Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків в цій групі або Ñ—Ñ— підгрупах. При поміÑÑчному переглÑді показуютьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ епіки за попередній, поточний, та наÑтупні 5 міÑÑців."
-
msgid "To widen your search, change or remove filters above"
msgstr "Щоб розширити пошук, змініть або видаліть фільтри вище"
@@ -29844,7 +30722,7 @@ msgid "To widen your search, change or remove filters."
msgstr "Щоб розширити пошук, змініть або видаліть фільтри."
msgid "To-Do"
-msgstr ""
+msgstr "ÐагадуваннÑ"
msgid "To-Do List"
msgstr "СпиÑок нагадувань"
@@ -29855,6 +30733,9 @@ msgstr "ÐÐ°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÑпішно позначене Ñк викон
msgid "Today"
msgstr "Сьогодні"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr "Увімкнути чи вимкнути попередній переглÑд Markdown"
@@ -29882,6 +30763,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr "Увімкнути/вимкнути Ñмайлики-нагороди"
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Переключити навігацію"
@@ -29912,6 +30796,9 @@ msgstr "Увімкнено/вимкнено :%{name}: Ñмайлик-винагÐ
msgid "Toggles :%{name}: emoji award."
msgstr "Вмикає/вимикає %{name} Ñмайлик-нагороду."
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -30002,6 +30889,9 @@ 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 ""
@@ -30060,7 +30950,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -30072,7 +30962,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -30099,7 +30989,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -30114,7 +31004,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -30123,6 +31013,9 @@ 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 ""
@@ -30132,8 +31025,8 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr "ЗапуÑкати конвеєри Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð¸Ñ… змін"
-msgid "Trigger pipelines when branches or tags are updated from 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 "Викликати конвеєри, коли гілки або теги оновлюютьÑÑ Ð² репозиторії upstream. Ð’ залежноÑÑ‚Ñ– від активноÑÑ‚Ñ– в репозиторії upstream, це може значно збільшити Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° CI runner'и. Вмикайте це тільки тоді, коли знаєте, що вони впораютьÑÑ Ð· навантаженнÑм."
+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 "Тригер видалено."
@@ -30159,7 +31052,10 @@ msgstr "Тригер уÑпішно оновлено."
msgid "Triggerer"
msgstr "Запущено"
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30375,8 +31271,8 @@ msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ цю задачу зараз."
msgid "Unarchive project"
msgstr "Розархівувати проєкт"
-msgid "Unarchiving the project will restore people's 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}"
-msgstr "Ð Ð¾Ð·Ð°Ñ€Ñ…Ñ–Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ знову даÑÑ‚ÑŒ можливіÑÑ‚ÑŒ людÑм вноÑити до нього зміни. До Ñховища можна буде відправлÑти коміти, також можуть бути Ñтворені задачі, коментарі та інше. %{strong_start}ПіÑÐ»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ—, цей проєкт з'ÑвлÑєтьÑÑ Ð² пошуку та на панелі керуваннÑ.%{strong_end}"
+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 ""
@@ -30633,8 +31529,8 @@ msgstr "ОновленнÑ"
msgid "Updating"
msgstr "ОновленнÑ"
-msgid "Upgrade plan to unlock Canary Deployments feature"
-msgstr "Перейдіть на вищий тарифний план, щоб отримати доÑтуп до функціональноÑÑ‚Ñ– Canary Deployments"
+msgid "Upgrade offers available!"
+msgstr ""
msgid "Upgrade your plan"
msgstr "Перейти на вищий тарифний план"
@@ -30654,6 +31550,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr "Перейдіть на вищий тарифний план Ð´Ð»Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на злиттÑ."
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "Завантажити CSV файл"
@@ -30852,12 +31751,18 @@ 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 "ВикориÑтовуйте %{code_start}::%{code_end} Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{link_start}набору Ñелективних міток%{link_end} (напр. %{code_start}priority::1%{code_end})"
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "ВикориÑтовуйте Service Desk Ð´Ð»Ñ Ð·Ð²â€™Ñзку з вашими кориÑтувачами (наприклад, щоб запропонувати клієнтÑьку підтримку) через електронну пошту безпоÑередньо із GitLab"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "ВикориÑтовуйте одноразовий пароль на вашому мобільному приÑтрої або комп’ютері Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— двофакторної автентифікації (2FA)."
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr "ВикориÑтовувати влаÑний колір #FF0000"
@@ -30873,8 +31778,11 @@ msgstr "ВикориÑтовуйте один Ñ€Ñдок Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ U
msgid "Use template"
msgstr "ВикориÑтовувати шаблон"
-msgid "Use the following registration token during setup:"
-msgstr "ВикориÑтовувати токен під Ñ‡Ð°Ñ ÑƒÑтановки:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "ВикориÑтовуютьÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ"
@@ -30987,7 +31895,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -31146,21 +32054,15 @@ msgstr "КориÑтувачі"
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr "КориÑтувачі, Ñкі запитують доÑтуп до"
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -31224,9 +32126,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -31251,6 +32150,15 @@ 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 "Різноманітні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑ”Ñтру контейнерів."
@@ -31424,6 +32332,9 @@ msgstr ""
msgid "View users statistics"
msgstr "ПереглÑд ÑтатиÑтики кориÑтувачів"
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "ПереглÑд коміту"
@@ -31802,6 +32713,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr "Запит на злиттÑ"
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Вебхук"
@@ -31811,6 +32728,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Веб-хуки"
@@ -31946,12 +32866,12 @@ msgstr "З поверненнÑм! Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾
msgid "Welcome to GitLab"
msgstr "ЛаÑкаво проÑимо до GitLab"
-msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr ""
-
msgid "Welcome to GitLab, %{first_name}!"
msgstr "ЛаÑкаво проÑимо до GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
msgid "Welcome to the guided GitLab tour"
msgstr ""
@@ -31967,8 +32887,8 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
-msgstr "Що нового в GitLab"
+msgid "What's new"
+msgstr ""
msgid "What’s your experience level?"
msgstr ""
@@ -31976,7 +32896,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31997,6 +32917,9 @@ 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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "Коли цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¸Ð¹Ð½Ñто"
@@ -32007,6 +32930,9 @@ msgstr[3] "Коли ці запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¸Ð¹Ð½Ñто"
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "Коли:"
@@ -32047,7 +32973,7 @@ msgid "WikiClone|Clone your wiki"
msgstr "Клонувати ваш вікі"
msgid "WikiClone|Git Access"
-msgstr "Git доÑтуп"
+msgstr "ДоÑтуп до Git"
msgid "WikiClone|Install Gollum"
msgstr "Ð’Ñтановити Gollum"
@@ -32367,9 +33293,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr "ЗаміÑÑ‚ÑŒ цього ви можете %{linkStart}переглÑнути бінарні дані%{linkEnd}."
-
msgid "You can also create a project from the command line."
msgstr "Ви також можете Ñтворити проєкт із командного Ñ€Ñдка."
@@ -32391,9 +33314,6 @@ msgstr "Також ви можете завантажувати файли з в
msgid "You can always edit this later"
msgstr "Ви завжди можете відредагувати це пізніше"
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32418,9 +33338,6 @@ msgstr "Ви можете Ñтворити нові в налаштуваннÑÑ
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Ви можете легко робити внеÑки до них, запроÑивши доÑтуп до цих груп."
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "Ви можете легко вÑтановити Runner на клаÑтері Kubernetes. %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr "Ви можете фільтрувати за \"днÑми до злиттÑ\", натиÑнувши на колонки в таблиці."
@@ -32442,6 +33359,9 @@ 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 ""
@@ -32457,15 +33377,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "Ви можете редагувати файли, лише перебуваючи у ÑкійÑÑŒ гілці"
@@ -32493,7 +33413,7 @@ msgstr "Ви можете розв’Ñзати цей конфлікт злит
msgid "You can see your chat accounts."
msgstr "Ви можете переглÑдати Ñвої облікові запиÑи чатів."
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32634,6 +33554,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32646,6 +33569,9 @@ 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 no permissions"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав доÑтупу"
@@ -32829,6 +33755,9 @@ msgstr "YouTube"
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 ""
@@ -32865,15 +33794,15 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "Ваші ключі GPG (%{count})"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr "Ваша група GitLab"
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr ""
-
msgid "Your Groups"
msgstr "Ваші групи"
@@ -33027,6 +33956,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "Ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚ÑƒÑ‚"
@@ -33111,6 +34043,12 @@ msgstr "Zoom-зуÑтріч видалено"
msgid "[No reason]"
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 "видалений кориÑтувач"
@@ -33199,9 +34137,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33516,6 +34460,9 @@ msgstr[1] "дні"
msgstr[2] "днів"
msgstr[3] "днів"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr "гілка за замовчуваннÑм"
@@ -33559,8 +34506,12 @@ msgstr "напр. %{token}"
msgid "element is not a hierarchy"
msgstr "елемент відÑутній в ієрархії"
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33657,6 +34608,9 @@ msgstr "група"
msgid "group members"
msgstr "учаÑники групи"
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr "групи"
@@ -33905,6 +34859,12 @@ msgstr "Будь лаÑка відновіть Ñ—Ñ— або викориÑтовÑ
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr "%{link_start}Докладніше про Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ð»Ñ–ÐºÑ‚Ñ–Ð²%{link_end}"
+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 "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLinkEnd} %{emphasisStart} впало %{emphasisEnd} з %{memoryFrom}Мб до %{memoryTo}Мб"
@@ -34031,9 +34991,6 @@ msgstr "ЗлиттÑ"
msgid "mrWidget|Merge failed."
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ невдало."
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð½ÐµÑƒÑпішне: %{mergeError}. Будь лаÑка, Ñпробуйте знову."
-
msgid "mrWidget|Merge locally"
msgstr "Злити локально"
@@ -34103,8 +35060,8 @@ msgstr "Зміни не були злиті в"
msgid "mrWidget|The changes will be merged into"
msgstr "Зміни будуть злиті в"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "HEAD гілки-джерела нещодавно було змінено. Будь лаÑка оновіть Ñторінку Ñ– переглÑньте зміни перед злиттÑм"
@@ -34184,6 +35141,9 @@ msgstr "буде злито автоматично, коли конвеєр за
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr "Ñтворити ланцюжок змін піÑÐ»Ñ ÑƒÑпішного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°"
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34417,6 +35377,9 @@ msgstr "Ñкинути його."
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34555,6 +35518,9 @@ msgstr "в ÑпиÑок"
msgid "toggle collapse"
msgstr "згорнути/розгорнути"
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "запущено"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 2e804cedc6e..f838eede643 100644
--- a/locale/ur_PK/gitlab.po
+++ b/locale/ur_PK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ur-PK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index fd400a0e456..ab4c80e508c 100644
--- a/locale/uz_UZ/gitlab.po
+++ b/locale/uz_UZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uz\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:58\n"
+"PO-Revision-Date: 2021-02-01 17:09\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -200,6 +200,11 @@ msgid_plural "%d fixed test results"
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] ""
@@ -374,10 +379,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -724,6 +729,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -912,6 +920,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -1033,15 +1044,15 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
msgstr[1] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1247,6 +1258,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1265,6 +1279,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1316,6 +1336,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1325,9 +1348,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1337,7 +1357,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1352,6 +1372,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1615,15 +1638,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1882,6 +1905,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1912,9 +1938,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1948,7 +1971,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1972,6 +1995,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1981,7 +2007,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -2011,9 +2043,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -2035,6 +2064,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2185,6 +2217,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2212,6 +2247,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2320,6 +2358,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2748,7 +2789,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2889,7 +2930,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2940,6 +2981,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2991,6 +3035,9 @@ 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 ""
@@ -3018,6 +3065,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3234,6 +3284,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3405,6 +3458,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3519,12 +3575,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3689,7 +3739,7 @@ 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}"
+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?"
@@ -3778,15 +3828,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3856,7 +3909,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3880,9 +3933,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4133,9 +4183,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4160,7 +4207,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4259,16 +4306,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4409,25 +4456,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4436,10 +4483,16 @@ 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 Gold."
+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}."
@@ -4460,6 +4513,9 @@ 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 ""
@@ -4469,6 +4525,9 @@ 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 ""
@@ -4484,6 +4543,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4570,10 +4632,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4597,6 +4659,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4792,6 +4857,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4831,16 +4899,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4891,6 +4968,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4900,6 +4980,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4936,6 +5019,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -5044,9 +5130,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5197,6 +5280,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5239,6 +5328,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5263,6 +5355,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5365,6 +5460,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5578,9 +5676,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5599,6 +5694,9 @@ 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 ""
@@ -5758,12 +5856,24 @@ 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 ""
@@ -5806,7 +5916,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6985,7 +7095,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -7003,9 +7113,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -7042,6 +7149,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7263,6 +7373,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7437,9 +7553,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7549,9 +7662,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7579,6 +7698,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7671,6 +7799,9 @@ 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 ""
@@ -7698,9 +7829,15 @@ 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 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 ""
@@ -7716,9 +7853,15 @@ 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 ""
@@ -7896,6 +8039,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7950,6 +8096,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8249,12 +8398,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8270,16 +8431,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8291,9 +8449,15 @@ 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 ""
@@ -8309,6 +8473,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8324,6 +8491,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8423,10 +8593,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8453,7 +8623,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8462,9 +8632,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8537,7 +8704,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8749,7 +8916,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8779,6 +8946,12 @@ 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 ""
@@ -8791,6 +8964,9 @@ 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 ""
@@ -8803,6 +8979,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8818,6 +8997,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8842,7 +9024,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8854,9 +9036,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8896,6 +9075,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8905,6 +9090,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8914,9 +9102,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8932,6 +9126,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8941,6 +9138,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8953,6 +9153,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9247,7 +9450,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9595,6 +9798,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9778,7 +10008,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9829,25 +10059,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9874,22 +10104,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9898,24 +10125,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9937,18 +10164,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -10006,7 +10227,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10299,9 +10520,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10530,6 +10748,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10596,6 +10823,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10605,6 +10835,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10644,7 +10877,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10683,7 +10916,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10746,15 +10979,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10851,13 +11090,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11148,6 +11384,9 @@ 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 ""
@@ -11163,6 +11402,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11553,9 +11798,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11691,15 +11933,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11823,6 +12071,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -12006,9 +12257,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12524,10 +12772,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12551,12 +12811,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12632,7 +12886,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12680,6 +12934,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -13094,7 +13351,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13124,9 +13381,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13163,6 +13417,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13247,9 +13504,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13277,6 +13531,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13550,9 +13807,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13568,9 +13822,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13622,6 +13873,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13631,6 +13888,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13655,6 +13915,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -14054,9 +14320,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14123,6 +14386,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14361,6 +14627,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14472,9 +14744,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14490,18 +14759,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14748,15 +15014,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14892,9 +15503,39 @@ 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 ""
@@ -14976,7 +15617,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -15018,10 +15659,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -15047,9 +15688,21 @@ 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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15155,6 +15808,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15185,6 +15841,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15194,12 +15856,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15224,6 +15892,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15251,6 +15922,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15338,6 +16012,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15398,6 +16075,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15653,6 +16333,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15707,9 +16393,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15749,6 +16432,9 @@ 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 ""
@@ -15851,24 +16537,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15884,6 +16588,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15896,9 +16603,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15977,6 +16696,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -16016,7 +16738,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -16091,6 +16813,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -16118,6 +16843,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16303,7 +17031,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16387,7 +17115,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16408,9 +17136,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16710,6 +17435,9 @@ msgstr[1] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16884,9 +17612,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16911,6 +17636,12 @@ 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 ""
@@ -16935,9 +17666,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16980,6 +17708,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17172,12 +17903,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17217,9 +17951,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17262,6 +17993,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17289,9 +18023,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17310,9 +18041,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17409,6 +18137,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17502,6 +18233,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17583,9 +18317,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17652,15 +18383,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -18059,6 +18784,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18229,6 +18957,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18280,9 +19011,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18451,9 +19179,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18587,12 +19312,6 @@ 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 ""
@@ -18611,6 +19330,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18665,6 +19390,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18913,7 +19641,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -19030,6 +19758,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -19123,6 +19854,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19198,9 +19932,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19210,6 +19941,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19585,6 +20319,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19594,12 +20331,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19660,10 +20403,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19675,9 +20418,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19729,10 +20481,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19770,7 +20522,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19788,9 +20540,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19809,7 +20558,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19917,15 +20666,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -20100,9 +20849,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -20121,6 +20867,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20193,9 +20942,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20211,6 +20957,9 @@ 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 ""
@@ -20349,6 +21098,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20463,6 +21215,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20529,6 +21284,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20541,6 +21299,9 @@ 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 ""
@@ -20709,9 +21470,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20724,9 +21482,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20748,6 +21503,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20862,6 +21620,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21531,12 +22292,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21582,9 +22346,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21867,6 +22628,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22284,6 +23048,9 @@ 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|What are badges?"
msgstr ""
@@ -22407,7 +23174,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22782,6 +23549,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22830,6 +23600,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22866,6 +23639,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22875,9 +23651,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22887,7 +23660,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -23106,6 +23879,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23219,12 +23995,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23252,21 +24037,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23362,9 +24135,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23458,6 +24228,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23705,6 +24478,11 @@ 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] ""
@@ -23872,6 +24650,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -24005,7 +24786,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -24128,6 +24909,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24175,6 +24959,9 @@ 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 ""
@@ -24216,6 +25003,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24261,6 +25051,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24282,21 +25075,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24309,21 +25090,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24345,24 +25141,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24435,6 +25246,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24781,6 +25595,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24796,6 +25613,9 @@ 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 ""
@@ -24955,9 +25775,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -25021,9 +25838,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -25131,13 +25945,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25197,7 +26011,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25227,6 +26041,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25284,9 +26101,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25569,6 +26383,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25608,10 +26425,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25626,9 +26443,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25773,9 +26587,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25830,6 +26641,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -26068,9 +26882,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26215,6 +27026,9 @@ 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 %{listType} list"
msgstr ""
@@ -26581,7 +27395,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26590,9 +27404,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26611,9 +27422,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26668,7 +27476,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26701,9 +27509,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26713,7 +27518,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26740,15 +27545,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26926,6 +27731,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27337,6 +28145,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27361,9 +28172,15 @@ 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 ""
@@ -27536,15 +28353,18 @@ msgstr[1] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27599,10 +28419,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27932,9 +28752,6 @@ msgstr[1] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27989,6 +28806,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -28007,6 +28827,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -28022,7 +28851,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -28040,9 +28872,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -28088,6 +28917,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -28115,9 +28947,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28172,7 +29001,7 @@ 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 an approval"
+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"
@@ -28280,7 +29109,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28328,6 +29157,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28340,6 +29172,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28493,16 +29328,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+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 "They can be managed using the %{link}."
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28532,7 +29376,7 @@ 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."
+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."
@@ -28547,22 +29391,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28577,13 +29433,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28661,9 +29520,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28676,13 +29532,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28712,6 +29571,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28835,6 +29697,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28844,6 +29709,15 @@ 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 ""
@@ -28880,7 +29754,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28937,6 +29811,9 @@ 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 ""
@@ -28970,18 +29847,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29391,6 +30262,9 @@ 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 ""
@@ -29406,6 +30280,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29415,6 +30292,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29448,6 +30328,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29463,7 +30346,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29481,12 +30364,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29502,9 +30379,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29523,6 +30397,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29550,6 +30427,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29580,6 +30460,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29670,6 +30553,9 @@ 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 ""
@@ -29726,7 +30612,7 @@ msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
msgstr[1] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29738,7 +30624,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29765,7 +30651,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29780,7 +30666,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29789,6 +30675,9 @@ 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 ""
@@ -29798,7 +30687,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29825,7 +30714,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -30041,7 +30933,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30299,7 +31191,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30320,6 +31212,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30518,12 +31413,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30539,7 +31440,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30653,7 +31557,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30812,21 +31716,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30890,9 +31788,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30917,6 +31812,15 @@ 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 ""
@@ -31086,6 +31990,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31464,6 +32371,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31473,6 +32386,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31608,10 +32524,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31629,7 +32545,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31638,7 +32554,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31659,6 +32575,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31667,6 +32586,9 @@ 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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -32027,9 +32949,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -32051,9 +32970,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -32078,9 +32994,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -32102,6 +33015,9 @@ 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 ""
@@ -32117,15 +33033,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -32153,7 +33069,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32294,6 +33210,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32306,6 +33225,9 @@ 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 no permissions"
msgstr ""
@@ -32489,6 +33411,9 @@ 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 ""
@@ -32525,13 +33450,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32687,6 +33612,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32771,6 +33699,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32857,9 +33791,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -33170,6 +34110,9 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33211,8 +34154,10 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
+msgstr[1] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33305,6 +34250,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33549,6 +34497,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33675,9 +34629,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33747,7 +34698,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33828,6 +34779,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -34051,6 +35005,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34189,6 +35146,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 6c5513b091f..401f669c8a2 100644
--- a/locale/vi_VN/gitlab.po
+++ b/locale/vi_VN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: vi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:55\n"
+"PO-Revision-Date: 2021-02-01 17:05\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -318,10 +322,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -958,14 +968,14 @@ msgstr ""
msgid ", or "
msgstr ""
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr ""
-
-msgid "- Runner is paused and will not receive any new jobs"
+msgid "- Not available to run jobs."
msgstr ""
msgid "- User"
@@ -1155,6 +1165,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr ""
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1789,6 +1811,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr ""
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2119,6 +2153,9 @@ msgstr ""
msgid "AdminUsers|Delete user and contributions"
msgstr ""
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr ""
@@ -2227,6 +2264,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,7 +2694,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2795,7 +2835,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3140,6 +3189,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,7 +3640,7 @@ 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}"
+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?"
@@ -3679,15 +3728,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3757,7 +3809,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4032,9 +4081,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,7 +4105,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4158,16 +4204,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4308,25 +4354,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4335,10 +4381,16 @@ 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 Gold."
+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}."
@@ -4359,6 +4411,9 @@ 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 ""
@@ -4368,6 +4423,9 @@ 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 ""
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4690,6 +4754,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
@@ -4834,6 +4916,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5497,6 +5591,9 @@ 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 ""
@@ -5656,12 +5753,24 @@ 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 ""
@@ -5704,7 +5813,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8316,10 +8485,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8346,7 +8515,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,7 +8596,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8641,7 +8807,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,7 +10112,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10184,9 +10404,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr ""
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,7 +10761,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,7 +12769,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12564,6 +12817,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,7 +13234,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,7 +15495,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -14897,10 +15537,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -14925,9 +15565,21 @@ msgstr[0] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,7 +16615,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,7 +16907,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr ""
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18319,9 +19046,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,7 +19505,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -18988,6 +19718,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 ""
@@ -20573,9 +21333,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21446,9 +22209,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21731,6 +22491,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,7 +24641,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -23985,6 +24764,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,7 +25852,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,16 +29162,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28368,7 +29210,7 @@ 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."
+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."
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,13 +29366,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 ""
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,7 +31271,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 ""
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31497,6 +32414,9 @@ msgstr[0] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr ""
@@ -32319,6 +33239,9 @@ 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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] ""
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33497,9 +34448,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33569,7 +34517,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 4e6212b8399..556437eb3f0 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:57\n"
+"PO-Revision-Date: 2021-02-01 17:55\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr " %{project_name}#%{issuable_iid} &middot;由%{author}于%{issuable_created}创建"
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d个修å¤çš„测试结果"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d个组已选择"
@@ -318,11 +322,11 @@ msgstr "%{authorsName}的主题"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
-msgstr "%{code_open}éšè—çš„%{code_close}å˜é‡åœ¨ä½œä¸šæ—¥å¿—中éšè—(虽然它们必须符åˆæŸäº›æ­£åˆ™è¡¨è¾¾å¼è¦æ±‚)。"
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
+msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
-msgstr "%{code_open}å—ä¿æŠ¤çš„%{code_close}å˜é‡ä»…å¯ç”¨äºŽå—ä¿æŠ¤çš„分支或标签中。"
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
+msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "由%{commit_author_link}编写于%{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr "%{reportType}检测到%{totalStart}%{total}%{totalEnd}个潜在的%{vuln
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr "%{reportType}检测到%{totalStart}æ— %{totalEnd}安全æ¼æ´žã€‚"
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr "%{retryButtonStart}é‡è¯•%{retryButtonEnd}或%{newFileButtonStart}添加新文件%{newFileButtonEnd}。"
@@ -839,6 +846,9 @@ 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 "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤ç»„或项目中的事件å‘é€é€šçŸ¥åˆ°web应用程åºã€‚ 如需使用webhook, 我们推è优先使用已有%{integrations_link_start}集æˆ%{link_end}。"
+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 "&lt; 1 hour"
msgstr "&lt; 1å°æ—¶"
@@ -958,15 +968,15 @@ msgstr "+其余%{tags}个"
msgid ", or "
msgstr ",或"
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- 事件"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- Runnerå·²å¯ç”¨ï¼Œéšæ—¶å¯ä»¥å¤„ç†æ–°ä½œä¸š"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- Runner已暂åœï¼Œæš‚æ—¶ä¸ä¼šæŽ¥å—新的作业"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1155,6 +1165,9 @@ msgstr "无法为空项目选择默认分支。"
msgid "A deleted user"
msgstr "已删除的用户"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr "文件已更改。"
@@ -1173,6 +1186,12 @@ msgstr "群组为多个项目的集åˆã€‚"
msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
msgstr "群组在GitLab中代表您的组织。群组å¯ä»¥ç”¨æ¥ç®¡ç†ç”¨æˆ·å¹¶åœ¨è¿›è¡Œè·¨é¡¹ç›®åˆä½œã€‚"
+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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr "项目包å«ç¾Žå›½å«ç”Ÿä¸Žå…¬å…±æœåŠ¡éƒ¨å‘布的HIPAA审计å议中æ
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "项目å¯ä»¥ç”¨äºŽå­˜æ”¾æ–‡ä»¶(仓库),安排计划(议题),并å‘布文档(wiki), %{among_other_things_link}。"
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "用于在作业日志中查找匹é…测试覆盖率输出的正则表达å¼ã€‚留空则ç¦ç”¨"
-
msgid "A secure token that identifies an external storage request."
msgstr "一个用于识别外部储存的请求安全令牌。"
@@ -1245,8 +1264,8 @@ msgstr "您的å¸æˆ·å·²ä»Žä¸‹åˆ—IP地å€ç™»å½•: %{ip}"
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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 "当被订阅项目%{default_branch_docs}上的新标签的æµæ°´çº¿æˆåŠŸå®Œæˆæ—¶ï¼Œè®¢é˜…将在当å‰é¡¹ç›®çš„默认分支上触å‘æ–°æµæ°´çº¿ã€‚"
+msgid "A title is required"
+msgstr ""
msgid "A user can only participate in a rotation once"
msgstr ""
@@ -1260,6 +1279,9 @@ msgstr "需è¦å¤„ç†ï¼š 获å–GitLab Pages域%{domain}çš„Let's Encrypt加密è¯ä
msgid "API Fuzzing"
msgstr "API模糊测试"
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr "API帮助"
@@ -1522,15 +1544,15 @@ msgstr "在监测部分的管ç†ä¾§æ æ·»åŠ ä¸€ä¸ª Grafana 按钮,以便访问
msgid "Add a To Do"
msgstr "添加一个待办事项"
-msgid "Add a To-Do"
-msgstr "添加一个待办事项"
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr "添加一般评论 %{noteableDisplayName}。"
@@ -1789,6 +1811,9 @@ msgstr "管ç†å‘˜æ¨¡å¼å·²åœç”¨"
msgid "Admin mode enabled"
msgstr "管ç†æ¨¡å¼å·²å¯ç”¨"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "管ç†å‘˜å¤‡æ³¨"
@@ -1819,9 +1844,6 @@ msgstr "å¼€å‘人员"
msgid "AdminArea|Features"
msgstr "功能"
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr "群组: %{number_of_groups}"
-
msgid "AdminArea|Guest"
msgstr "访客"
@@ -1855,8 +1877,8 @@ msgstr "一旦实例达到用户上é™ï¼Œä»»ä½•æ·»åŠ æˆ–请求访问的用户都
msgid "AdminArea|Owner"
msgstr "所有者"
-msgid "AdminArea|Projects: %{number_of_projects}"
-msgstr "项目: %{number_of_projects}"
+msgid "AdminArea|Projects"
+msgstr ""
msgid "AdminArea|Reporter"
msgstr "报告者"
@@ -1879,6 +1901,9 @@ msgstr "所有用户"
msgid "AdminArea|User cap"
msgstr "用户上é™"
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr "用户统计"
@@ -1888,8 +1913,14 @@ msgstr "用户的最高æƒé™ä¸º"
msgid "AdminArea|Users without a Group and Project"
msgstr "没有群组和项目的用户"
-msgid "AdminArea|Users: %{number_of_users}"
-msgstr "用户: %{number_of_users}"
+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 "您å³å°†åœæ­¢æ‰€æœ‰ä½œä¸šã€‚这会中断并结æŸæ‰€æœ‰æ­£åœ¨è¿è¡Œçš„作业。"
@@ -1918,9 +1949,6 @@ msgstr "Auto DevOps 域"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr "Elasticsearch,PlantUML,Slack应用程åºï¼Œç¬¬ä¸‰æ–¹ä¼˜æƒ ï¼ŒSnowplow,Amazon EKS已移至设置&gt;常规。"
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "为新项目å¯ç”¨å…±äº«Runner"
@@ -1942,6 +1970,9 @@ msgstr "移动到集æˆ"
msgid "AdminSettings|No required pipeline"
msgstr "没有必需的æµæ°´çº¿"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "强制æµæ°´çº¿é…ç½®"
@@ -2092,6 +2123,9 @@ msgstr "无法登录或访问实例信æ¯"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "无法解除已ç¦ç”¨çš„ LDAP 用户"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "冻结"
@@ -2119,6 +2153,9 @@ msgstr "删除用户"
msgid "AdminUsers|Delete user and contributions"
msgstr "删除用户åŠç›¸å…³è´¡çŒ®"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "外部"
@@ -2227,6 +2264,9 @@ msgstr "用户将无法访问git仓库"
msgid "AdminUsers|User will not be able to login"
msgstr "用户将无法登录"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr "用户é‡æ–°ç™»å½•åŽï¼Œå…¶å¸æˆ·å°†æ¢å¤ä¸ºå®Œå…¨æœ‰æ•ˆçš„å¸æˆ·"
@@ -2654,8 +2694,8 @@ msgstr "{ \"events\": [{ \"application\": \"应用å称\" }] }"
msgid "Alerts"
msgstr "警报"
-msgid "Alerts endpoint"
-msgstr "警报端点"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr "警报将通过此集æˆåˆ›å»º"
@@ -2795,8 +2835,8 @@ 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 public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "å…许在Asciidoc文档中渲染PlantUML图。"
@@ -2846,6 +2886,9 @@ msgstr "å…许注册的域"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "å…许使用电å­é‚®ä»¶åŸŸåé™åˆ¶ä»…å¯ç”¨äºŽé¡¶çº§ç¾¤ç»„"
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "å…许失败"
@@ -2897,6 +2940,9 @@ 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 "具有相åŒæŒ‡çº¹çš„%{link_start}警报%{link_end}已打开。è¦æ›´æ”¹æ­¤è­¦æŠ¥çš„状æ€ï¼Œè¯·å…ˆè§£å†³é“¾æŽ¥ä¸­çš„警报。"
+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 "管ç†å‘˜ä¿®æ”¹äº†æ‚¨åœ¨%{link_to}上的GitLabå¸æˆ·å¯†ç ã€‚"
@@ -2924,6 +2970,9 @@ msgstr "å‘生错误"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "å‘主题添加è‰ç¨¿æ—¶å‡ºé”™ã€‚"
@@ -3140,6 +3189,9 @@ msgstr "加载文件时å‘生错误。"
msgid "An error occurred while loading the file. Please try again later."
msgstr "加载文件时出错。请ç¨åŽå†è¯•ã€‚"
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "加载åˆå¹¶è¯·æ±‚çš„å˜æ›´å†…容时å‘生错误。"
@@ -3311,6 +3363,9 @@ msgstr "分æžæºä»£ç æŸ¥æ‰¾å·²çŸ¥æ¼æ´ž."
msgid "Ancestors"
msgstr "祖先"
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr "匿å"
@@ -3425,12 +3480,6 @@ msgstr "应用å˜æ›´"
msgid "Apply suggestion"
msgstr "应用建议"
-msgid "Apply suggestion commit message"
-msgstr "应用建议æ交消æ¯"
-
-msgid "Apply suggestion on %{fileName}"
-msgstr "在%{fileName}上应用建议"
-
msgid "Apply suggestions"
msgstr "应用建议"
@@ -3591,8 +3640,8 @@ 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}"
-msgstr "归档项目将使其完全åªè¯»ã€‚仪表æ¿ä¸­å’Œæœç´¢ç»“果中都ä¸ä¼šå‡ºçŽ°è¯¥é¡¹ç›®ã€‚%{strong_start}代ç å°†æ— æ³•æ交到仓库,也无法创建任何议题ã€è¯„论其他对象。%{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr "您确定è¦åˆ é™¤æ­¤é¡¹ç›®å—?"
@@ -3679,15 +3728,18 @@ msgstr "您确定è¦åˆ é™¤è¿™ä¸ªèº«ä»½æ ‡è¯†å—?"
msgid "Are you sure you want to remove this list?"
msgstr "您确定è¦åˆ é™¤æ­¤åˆ—表å—?"
-msgid "Are you sure you want to reset registration token?"
-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 "确定è¦é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥ä»¤ç‰Œå—?"
+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 "您确定è¦æ’¤é”€æ­¤%{type}å—?此æ“作ä¸å¯é€†ã€‚"
@@ -3757,8 +3809,8 @@ msgstr "用户个人访问令牌。用户必须能够访问任务,所有评论
msgid "Ascending"
msgstr "å‡åºæŽ’列"
-msgid "Ask your group maintainer to set up a group Runner."
-msgstr "请群组维护者é…置一个群组级 Runner。"
+msgid "Ask your group maintainer to set up a group runner."
+msgstr ""
msgid "Assertion consumer service URL"
msgstr "断言消费者æœåŠ¡ URL"
@@ -3781,9 +3833,6 @@ msgstr "分é…ç»™"
msgid "Assign custom color like #FF0000"
msgstr "分é…自定义颜色,如FF0000"
-msgid "Assign epic"
-msgstr "分é…å²è¯—"
-
msgid "Assign labels"
msgstr "指派标记"
@@ -4032,9 +4081,6 @@ msgstr "æŽˆæƒ %{link_to_client} 使用您的å¸æˆ·ï¼Ÿ"
msgid "Authorize %{user} to use your account?"
msgstr "授æƒ%{user}使用您的å¸æˆ·å—?"
-msgid "Authorize external services to send alerts to GitLab"
-msgstr "授æƒå¤–部æœåŠ¡å‘GitLabå‘é€è­¦æŠ¥"
-
msgid "Authorized %{new_chat_name}"
msgstr "已授æƒç»™ %{new_chat_name}"
@@ -4059,8 +4105,8 @@ msgstr "Auto DevOps, runnersåŠä½œä¸šäº§ç‰©"
msgid "Auto stop successfully canceled."
msgstr "自动åœæ­¢å·²æˆåŠŸå–消。"
-msgid "Auto-cancel redundant, pending pipelines"
-msgstr "自动å–消多余且处于等待状æ€çš„æµæ°´çº¿"
+msgid "Auto-cancel redundant pipelines"
+msgstr ""
msgid "Auto-close referenced issues on default branch"
msgstr "自动关闭默认分支上的引用问题"
@@ -4158,17 +4204,17 @@ msgstr "å¯ç”¨çš„"
msgid "Available ID"
msgstr "å¯ç”¨çš„ID"
-msgid "Available Runners: %{runners}"
-msgstr "å¯ç”¨çš„Runner: %{runners}"
-
msgid "Available for dependency and container scanning"
msgstr "å¯ç”¨äºŽä¾èµ–项和容器扫æ"
-msgid "Available group Runners: %{runners}"
-msgstr "å¯ç”¨çš„群组 Runner: %{runners}"
+msgid "Available group runners: %{runners}"
+msgstr ""
-msgid "Available shared Runners:"
-msgstr "å¯ç”¨çš„共享Runner:"
+msgid "Available runners: %{runners}"
+msgstr ""
+
+msgid "Available shared runners:"
+msgstr ""
msgid "Available specific runners"
msgstr "å¯ç”¨çš„指定Runner"
@@ -4303,31 +4349,31 @@ msgid "Be careful. Changing the project's namespace can have unintended side eff
msgstr "请注æ„,更改项目的命å空间å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
msgid "Be careful. Renaming a project's repository can have unintended side effects."
-msgstr "请注æ„,é‡å‘½å项目的仓库å¯èƒ½ä¼šäº§ç”Ÿæ„想ä¸åˆ°çš„副作用。"
+msgstr "请注æ„,é‡å‘½å项目的仓库å¯èƒ½ä¼šäº§ç”Ÿéžé¢„期的副作用。"
msgid "Begin with the selected commit"
msgstr "从选定的æ交开始"
-msgid "Below are examples of regex for existing tools:"
-msgstr "以下是现有工具的正则表达å¼ç¤ºä¾‹ï¼š"
-
msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "下é¢æ˜¯å½“å‰å®žä¾‹SSH主机密钥的指纹。"
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 "Billable Users"
+msgstr ""
msgid "Billing"
msgstr "计费"
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
-msgstr "%{group_name}正在使用%{plan_name}计划。"
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
+msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "@%{user_name}您正在使用%{plan_name}计划。"
@@ -4335,11 +4381,17 @@ msgstr "@%{user_name}您正在使用%{plan_name}计划。"
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 "如果您想è¦é™çº§æ‚¨çš„订阅计划,请è”ç³»%{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 Gold."
-msgstr "请查阅%{faq_link}æ¥äº†è§£æœ‰å…³å„订阅计划的更多信æ¯ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹é“¾æŽ¥å…费试用GitLab.comçš„Gold计划30天。"
+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 "通过阅读我们的 %{pricing_page_link} 了解有关æ¯ä¸ªè®¡åˆ’的更多信æ¯ã€‚"
@@ -4359,6 +4411,9 @@ msgstr "使用与其父项目一致的计划"
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "访问%{parent_billing_page_link}的计费部分以管ç†è¯¥é¡¹ç›®çš„订阅计划。"
+msgid "BillingPlans|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 "您的GitLab.com%{plan}试用将在%{strong_open}%{expiration_date}过期%{strong_close}。您å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼å‡çº§ä»¥ä¿ç•™å¯¹%{plan}功能的访问æƒé™ã€‚"
@@ -4368,6 +4423,9 @@ msgstr "您的GitLab.com试用已于%{expiration_date}到期。您å¯ä»¥é€šè¿‡ä»
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "æ¯å¹´æ”¯ä»˜%{price_per_year}"
+msgid "BillingPlans|for the remainder of your subscription"
+msgstr ""
+
msgid "BillingPlans|frequently asked questions"
msgstr "常è§é—®é¢˜"
@@ -4383,6 +4441,9 @@ msgstr "è”系销售人员"
msgid "BillingPlan|Upgrade"
msgstr "å‡çº§"
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,12 +4529,12 @@ msgstr "创建列表时å‘生错误。请å†è¯•ä¸€é。"
msgid "Boards|An error occurred while creating the list. 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 issues. Please reload the page."
msgstr "读å–看æ¿è®®é¢˜æ—¶å‡ºé”™ã€‚请é‡è¯•ã€‚"
@@ -4495,6 +4556,9 @@ msgstr "移除列表时å‘生错误。请é‡è¯•ã€‚"
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr "更新列表时出错。请é‡è¯•ã€‚"
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr "收起"
@@ -4690,6 +4754,9 @@ msgstr "项目设置"
msgid "Branches|protected"
msgstr "å—ä¿æŠ¤"
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr "关于å˜æ›´çš„简短标题"
@@ -4729,16 +4796,25 @@ msgstr "内置"
msgid "Bulk request concurrency"
msgstr "并å‘批é‡è¯·æ±‚"
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ msgstr "购买更多æµæ°´çº¿æ—¶é—´"
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 ""
+
msgid "By clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr "å•å‡»æ³¨å†Œå³ä»£è¡¨æˆ‘åŒæ„我已ç»é˜…读并接å—%{company_name}%{linkStart}使用æ¡æ¬¾å’Œéšç§æ”¿ç­–%{linkEnd}"
@@ -4798,6 +4877,9 @@ msgstr "默认情况下,GitLab 以 HTML 和纯文本格å¼å‘é€ç”µå­é‚®ä»¶ï¼
msgid "By default, all projects and groups will use the global notifications setting."
msgstr "默认情况下,所有项目和群组将使用全局通知设置。"
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -4834,6 +4916,9 @@ msgstr "CI/CD"
msgid "CI/CD configuration"
msgstr "CI/CD é…ç½®"
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr "为外部仓库设置的CI/CD"
@@ -4942,9 +5027,6 @@ msgstr "无法更新代ç æ®µ: %{err}"
msgid "Canary"
msgstr "金ä¸é›€"
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr "金ä¸é›€éƒ¨ç½²æ˜¯ä¸€é¡¹æµè¡Œçš„CI策略,其中一å°éƒ¨åˆ†èŠ‚点更新到您的新版本应用。"
-
msgid "Canary Ingress does not exist in the environment."
msgstr "该环境中ä¸å­˜åœ¨Canary Ingress。"
@@ -5095,6 +5177,12 @@ msgstr "更改路径"
msgid "Change permissions"
msgstr "更改æƒé™"
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr "更改状æ€"
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "优选"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "还原"
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr "å·²å˜æ›´çš„指派人"
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr "已将标题更改为“%{title_param}â€ã€‚"
@@ -5195,7 +5289,7 @@ msgid "Changes won't take place until the index is %{link_start}recreated%{link_
msgstr "在索引%{link_start}é‡æ–°åˆ›å»º%{link_end}之å‰ï¼Œæ›´æ”¹å°†ä¸ä¼šç”Ÿæ•ˆã€‚"
msgid "Changing group URL can have unintended side effects."
-msgstr "更改群组URLå¯èƒ½ä¼šæœ‰æ„想ä¸åˆ°çš„副作用。"
+msgstr "更改群组URLå¯èƒ½ä¼šæœ‰éžé¢„期的副作用。"
msgid "Channel handle (e.g. town-square)"
msgstr "频é“è´¦å·(例如town-square)"
@@ -5263,6 +5357,9 @@ msgstr "在本地检出ã€å®¡æ ¸å’Œåˆå¹¶"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "查看%{docs_link_start}文档%{docs_link_end}。"
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr "检查您的Dockeré•œåƒæ˜¯å¦å­˜åœ¨å·²çŸ¥æ¼æ´ž."
@@ -5476,9 +5573,6 @@ msgstr "选择任何颜色。"
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr "选择%{code_open}clone%{code_close}或%{code_open}fetch%{code_close}以获å–最近的应用程åºä»£ç "
-
msgid "Choose file…"
msgstr "选择文件…"
@@ -5497,6 +5591,9 @@ msgstr "选择å¯è§æ€§çº§åˆ«ï¼Œå¯ç”¨/ç¦ç”¨é¡¹ç›®åŠŸèƒ½ï¼ˆè®®é¢˜ï¼Œä»“库,wi
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 "请选择è¦è¿žæŽ¥å¹¶è¿è¡Œ CI/CD æµæ°´çº¿çš„代ç ä»“库。"
@@ -5656,12 +5753,24 @@ msgstr "分类标签(å¯é€‰)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ä¸å¯ç”¨: %{reason}"
+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 "清除"
@@ -5704,8 +5813,8 @@ msgstr "点击%{link_start}此处%{link_end}查看请求。"
msgid "Click %{link_to} to view the request."
msgstr "点击%{link_to}查看请求。"
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr "点击下é¢çš„按钮转到Kubernetes页é¢å¼€å§‹å®‰è£…过程"
+msgid "Click the button below."
+msgstr ""
msgid "Click to expand it."
msgstr "点击以展开。"
@@ -6883,8 +6992,8 @@ 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 master %{start_date} - %{end_date}"
-msgstr "master上%{start_date} - %{end_date}的代ç è¦†ç›–率统计"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
+msgstr ""
msgid "Code owner approval is required"
msgstr "代ç æ‰€æœ‰è€…的核准是必需的"
@@ -6901,9 +7010,6 @@ msgstr "找ä¸åˆ°å¼•ç”¨"
msgid "CodeOwner|Pattern"
msgstr "模å¼"
-msgid "Cohorts"
-msgstr "世代表"
-
msgid "Cohorts|Inactive users"
msgstr "éžæ´»è·ƒç”¨æˆ·"
@@ -6940,6 +7046,9 @@ msgstr "收起回å¤"
msgid "Collapse sidebar"
msgstr "收起侧边æ "
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr "Collector主机å"
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -7334,9 +7449,6 @@ msgstr "一致性ä¿éšœæ–¹æ³•"
msgid "Contact Sales to upgrade"
msgstr "è”系销售人员进行å‡çº§"
-msgid "Contact sales to upgrade"
-msgstr "è”系销售人员进行å‡çº§"
-
msgid "Contact support"
msgstr "è”系支æŒ"
@@ -7444,9 +7556,15 @@ msgstr "å¤åˆ¶ç™»å½•å‘½ä»¤"
msgid "ContainerRegistry|Copy push command"
msgstr "å¤åˆ¶æŽ¨é€å‘½ä»¤"
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr "删除选中项"
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr "由于缺少æƒé™æˆ–æƒé™ä¸è¶³ï¼Œåˆ é™¤åŠŸèƒ½å·²ç¦ç”¨ã€‚"
@@ -7474,6 +7592,15 @@ msgstr "如果您尚未登录,您需è¦ä½¿ç”¨æ‚¨çš„GitLab用户å和密ç æ¥
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr "é•œåƒæ ‡ç­¾"
@@ -7565,6 +7692,9 @@ msgstr "将标签标记为待删除时出错。"
msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
msgstr "安排删除%{title}时出错。请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
+msgstr ""
+
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
msgstr "更新清ç†æ”¿ç­–时出了错。"
@@ -7592,9 +7722,15 @@ 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 "清ç†ç­–略在删除所有标签之å‰è¶…时。 管ç†å‘˜å¯ä»¥%{adminLinkStart}ç«‹å³æ‰§è¡Œæ‰‹åŠ¨æ¸…ç†%{adminLinkEnd}或者等待清ç†ç­–略下次自动è¿è¡Œã€‚%{docLinkStart}更多信æ¯%{docLinkEnd}"
+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 "此输入的值应å°äºŽ256个字符"
@@ -7610,9 +7746,15 @@ 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 "此项目的标签清ç†ç­–略未å¯ç”¨ã€‚"
@@ -7790,6 +7932,9 @@ msgstr "å¤åˆ¶å‘½ä»¤"
msgid "Copy commit SHA"
msgstr "å¤åˆ¶æ交SHA"
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr "å¤åˆ¶çŽ¯å¢ƒ"
@@ -7844,6 +7989,9 @@ msgstr "å¤åˆ¶è§¦å‘令牌"
msgid "Copy value"
msgstr "å¤åˆ¶å€¼"
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr "无法将管ç†å‘˜æ·»åŠ ä¸ºæˆå‘˜"
@@ -8142,12 +8290,24 @@ msgstr "创建个人访问令牌"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr "创建于"
@@ -8316,12 +8485,12 @@ msgstr ""
msgid "Current Branch"
msgstr "当å‰åˆ†æ”¯"
-msgid "Current Plan"
-msgstr "当å‰è®¡åˆ’"
-
msgid "Current Project"
msgstr "当å‰é¡¹ç›®"
+msgid "Current forks will keep their visibility level."
+msgstr ""
+
msgid "Current node"
msgstr "当å‰èŠ‚点"
@@ -8346,8 +8515,8 @@ msgstr "用户资料"
msgid "CurrentUser|Settings"
msgstr "设置"
-msgid "CurrentUser|Start a Gold trial"
-msgstr "开始试用金牌计划"
+msgid "CurrentUser|Start an Ultimate trial"
+msgstr ""
msgid "CurrentUser|Upgrade"
msgstr "å‡çº§"
@@ -8355,9 +8524,6 @@ msgstr "å‡çº§"
msgid "Custom Attributes"
msgstr "自定义属性"
-msgid "Custom CI configuration path"
-msgstr "自定义CIé…置路径"
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr "自定义HTTP(S)åè®®Git克隆URL"
@@ -8430,8 +8596,8 @@ msgstr "自定义语言和区域相关设置。"
msgid "Customize name"
msgstr "自定义å称"
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
-msgstr "自定义æµæ°´çº¿é…置,查看æµæ°´çº¿çŠ¶æ€å’Œè¦†ç›–率报告。"
+msgid "Customize your pipeline configuration and coverage report."
+msgstr ""
msgid "Customize your pipeline configuration."
msgstr "自定义您的æµæ°´çº¿é…置。"
@@ -8641,8 +8807,8 @@ msgstr "%{firstProject} 和 %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
msgstr "%{firstProject}ã€%{rest} å’Œ %{secondProject}"
-msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
-msgstr "无法添加%{invalidProjects}。此仪表æ¿å¯ç”¨äºŽå…¬å¼€é¡¹ç›®ï¼Œä»¥åŠé“¶ç‰Œæ–¹æ¡ˆç¾¤ç»„中的ç§æœ‰é¡¹ç›®ã€‚"
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
+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 "被动扫æ监控å‘é€åˆ°ç›®æ ‡çš„所有HTTP消æ¯(请求和å“应)。主动扫æ会对目标进行攻击以å‘现潜在æ¼æ´žã€‚"
@@ -8671,6 +8837,12 @@ 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 "无法删除扫æ工具é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
@@ -8683,6 +8855,9 @@ 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 "无法获å–扫æ工具é…置。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
@@ -8695,6 +8870,9 @@ msgstr "无法更新扫æ工具é…置。请é‡è¯•ã€‚"
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr "无法更新站点é…置。请é‡è¯•ã€‚"
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr "调试消æ¯"
@@ -8710,6 +8888,9 @@ msgstr "您è¦æ”¾å¼ƒæ­¤ç«™ç‚¹é…ç½®å—?"
msgid "DastProfiles|Do you want to discard your changes?"
msgstr "您è¦æ”¾å¼ƒæ›´æ”¹å—?"
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr "编辑扫æ工具é…ç½®"
@@ -8734,8 +8915,8 @@ msgstr "éšè—调试消æ¯"
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr "在DAST控制å°è¾“出中包å«è°ƒè¯•æ¶ˆæ¯ã€‚"
-msgid "DastProfiles|Manage Profiles"
-msgstr "管ç†é…ç½®"
+msgid "DastProfiles|Manage DAST scans"
+msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr "管ç†é…ç½®"
@@ -8746,9 +8927,6 @@ msgstr "æœ€å° = 0 (无超时),最大 = 2880 分钟"
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr "æœ€å° = 1秒,最大 = 3600秒"
-msgid "DastProfiles|New Profile"
-msgstr "新建é…ç½®"
-
msgid "DastProfiles|New scanner profile"
msgstr "新建扫æ工具é…ç½®"
@@ -8788,6 +8966,12 @@ msgstr "将目标站点和扫æ设置的常用设定ä¿å­˜ä¸ºé…置。使用这
msgid "DastProfiles|Save profile"
msgstr "ä¿å­˜é…ç½®"
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr "扫æ模å¼"
@@ -8797,6 +8981,9 @@ msgstr "扫æ工具é…ç½®"
msgid "DastProfiles|Scanner Profiles"
msgstr "扫æ工具é…ç½®"
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr "显示调试消æ¯"
@@ -8806,9 +8993,15 @@ msgstr "站点é…ç½®"
msgid "DastProfiles|Site Profiles"
msgstr "站点é…ç½®"
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr "爬虫超时"
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr "目标URL"
@@ -8824,6 +9017,9 @@ msgstr "被测站点å“应请求所å…许的最大秒数。"
msgid "DastProfiles|Turn on AJAX spider"
msgstr "å¯ç”¨AJAX爬虫"
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr "用户å"
@@ -8833,6 +9029,9 @@ msgstr "用户å表å•å­—段"
msgid "DastProfiles|Validated"
msgstr "已验è¯"
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr "å¤åˆ¶HTTP报头到剪贴æ¿"
@@ -8845,6 +9044,9 @@ msgstr "下载验è¯æ–‡æœ¬æ–‡ä»¶"
msgid "DastSiteValidation|Header validation"
msgstr "报头验è¯"
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr "步骤 1 - 选择站点验è¯æ–¹æ³•"
@@ -9139,8 +9341,8 @@ 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 "删除项目会将其置于åªè¯»çŠ¶æ€ç›´è‡³%{date}。届时项目将被永久删除。确定è¦åˆ é™¤å—?"
-msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "删除项目将删除其存储库和所有相关资æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。"
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
+msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "删除等待中。此项目将于%{date}被删除。仓库和其他项目资æºä¸ºåªè¯»ã€‚"
@@ -9481,6 +9683,33 @@ msgstr "使用GitLabè½»æ¾éƒ¨ç½²åˆ° AWS"
msgid "Deployment Frequency"
msgstr "部署频率"
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr "API"
@@ -9664,8 +9893,8 @@ msgstr "å…许上传的设计最大数é‡ä¸º %{upload_limit}。请å†è¯•ä¸€æ¬¡ã€
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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
-msgstr "如需上传设计,请å¯ç”¨LFS并由管ç†å‘˜å¯ç”¨å“ˆå¸Œå­˜å‚¨ã€‚%{requirements_link_start}更多信æ¯%{requirements_link_end}"
+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 "将主题置为未解决"
@@ -9715,26 +9944,26 @@ msgstr "已达到最大阶段数"
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr "已达到最大选择数"
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
-msgstr "已选择%{selectedCount}个群组(最多20个)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
+msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
-msgstr "已选择%{selectedCount}个群组(最多20个)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
+msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
-msgstr "添加新阶段æ¥å¼€å§‹"
+msgid "DevopsAdoption|Add Group"
+msgstr ""
-msgid "DevopsAdoption|Add new segment"
-msgstr "添加新阶段"
+msgid "DevopsAdoption|Add a group to get started"
+msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
-msgstr "ä¿å­˜é˜¶æ®µæ—¶å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
+msgstr ""
msgid "DevopsAdoption|Approvals"
msgstr "核准"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Create new segment"
-msgstr "创建新阶段"
-
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr "部署"
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
-msgstr "DevOps采用率使用阶段æ¥è·Ÿè¸ªé€šè¿‡å…³é”®åŠŸèƒ½çš„采用。阶段是一次跟踪多个相关项目和群组的一ç§æ–¹å¼ã€‚ 例如,您å¯ä»¥ä¸ºå·¥ç¨‹éƒ¨é—¨æˆ–特定的产å“团队创建一个阶段。"
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr "议题"
msgid "DevopsAdoption|MRs"
msgstr "åˆå¹¶è¯·æ±‚"
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
-msgstr "我的阶段"
+msgid "DevopsAdoption|My group"
+msgstr ""
msgid "DevopsAdoption|Name"
msgstr "å称"
-msgid "DevopsAdoption|New segment"
-msgstr "创建新阶段"
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr "扫æ"
-msgid "DevopsAdoption|Segment"
-msgstr "阶段"
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr "获å–群组时å‘生错误。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr "获å–阶段时å‘生错误。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
-
msgid "DevopsReport|Adoption"
msgstr "采用率"
@@ -9892,8 +10112,8 @@ msgstr "ç¦ç”¨"
msgid "Disable for this project"
msgstr "在此项目中ç¦ç”¨"
-msgid "Disable group Runners"
-msgstr "ç¦ç”¨ç¾¤ç»„Runner"
+msgid "Disable group runners"
+msgstr ""
msgid "Disable public access to Pages sites"
msgstr "ç¦æ­¢å…¬å¼€è®¿é—®Pages网站"
@@ -10184,9 +10404,6 @@ msgstr "在此过程中,我们会è¦æ±‚您æä¾›æ¥è‡ª GitLab çš„ URL 。请ä½
msgid "Dynamic Application Security Testing (DAST)"
msgstr "动æ€åº”用程åºå®‰å…¨æ€§æµ‹è¯•(DAST)"
-msgid "Each Runner can be in one of the following states:"
-msgstr "æ¯ä¸ªRunnerå¯ä»¥å¤„于以下状æ€ä¸­çš„其中一ç§ï¼š"
-
msgid "Edit"
msgstr "编辑"
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr "é‡ç½®ä»¤ç‰Œ"
@@ -10481,6 +10707,9 @@ msgstr "å¯ç”¨ HTML 电å­é‚®ä»¶"
msgid "Enable Incident Management inbound alert limit"
msgstr "å¯ç”¨äº‹ä»¶ç®¡ç†ä¼ å…¥è­¦æŠ¥é™åˆ¶"
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr "å¯ç”¨Kroki"
@@ -10490,6 +10719,9 @@ msgstr "å¯ç”¨PlantUML"
msgid "Enable Pseudonymizer data collection"
msgstr "å¯ç”¨åŒ¿å化的数æ®æ”¶é›†"
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr "å¯ç”¨å¸­ä½é“¾æŽ¥"
@@ -10529,8 +10761,8 @@ msgstr "å¯ç”¨åŠŸèƒ½å¹¶é€‰æ‹©è®¿é—®çº§åˆ«"
msgid "Enable for this project"
msgstr "在此项目中å¯ç”¨"
-msgid "Enable group Runners"
-msgstr "å¯ç”¨ç¾¤ç»„Runner"
+msgid "Enable group runners"
+msgstr ""
msgid "Enable header and footer in emails"
msgstr "在电å­é‚®ä»¶ä¸­å¯ç”¨é¡µçœ‰å’Œé¡µè„š"
@@ -10568,8 +10800,8 @@ msgstr "å¯ç”¨ä¿æŠ¤è·¯å¾„速率é™åˆ¶"
msgid "Enable proxy"
msgstr "å¯ç”¨ä»£ç†"
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
-msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚对于reCAPTCHA,我们目å‰ä»…æ”¯æŒ %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
msgid "Enable shared runners"
msgstr "å¯ç”¨å…±äº«Runner"
@@ -10631,15 +10863,21 @@ msgstr "渲染时出现错误: %{err}"
msgid "End Time"
msgstr "结æŸæ—¶é—´"
-msgid "Ends at %{endsAt}"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr "结æŸäºŽ(UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
+msgstr ""
+
msgid "Enforce DNS rebinding attack protection"
msgstr "强制DNSé‡æ–°ç»‘定攻击ä¿æŠ¤"
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr "强制个人访问令牌过期"
@@ -10736,14 +10974,11 @@ msgstr "Stages::VariableEndpointInserter需è¦çŽ¯å¢ƒ"
msgid "Environment scope"
msgstr "环境范围"
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr "环境å˜é‡é€šè¿‡Runner应用于环境中。您å¯ä»¥é€šè¿‡çŽ¯å¢ƒå˜é‡æ¥å­˜å‚¨å¯†ç ï¼Œå¯†é’¥ç­‰ç­‰ã€‚如果您需è¦æŠŠå˜é‡ç”¨äºŽæœ€ç»ˆè¿è¡Œçš„应用,您å¯ä»¥åœ¨å˜é‡åå‰æ·»åŠ %{code_open}K8S_SECRET_%{code_close}。您å¯ä»¥å°†å˜é‡è®¾ç½®ä¸ºï¼š"
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
-msgstr "环境å˜é‡å·²è¢«ç®¡ç†å‘˜é…置为%{link_start}å—ä¿æŠ¤çš„(默认)%{link_end}"
+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 "æ­¤GitLab实例上的环境å˜é‡è¢«é…置为默认%{link_start}ä¿æŠ¤%{link_end}"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
+msgstr ""
msgid "Environment:"
msgstr "环境:"
@@ -11033,6 +11268,9 @@ msgstr "更新标记时出错。"
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
msgstr "确定è¦ä»Ž%{bStart}%{parentEpicTitle}%{bEnd}删除%{bStart}%{targetIssueTitle}%{bEnd}å—?"
+msgid "Epics|Assign Epic"
+msgstr ""
+
msgid "Epics|Enter a title for your epic"
msgstr "输入å²è¯—的标题"
@@ -11048,6 +11286,12 @@ msgstr "删除å²è¯—"
msgid "Epics|Remove issue"
msgstr "删除议题"
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr "显示更多"
@@ -11438,9 +11682,6 @@ msgstr "示例: %{ip_address}. %{read_more_link}."
msgid "Example: @sub\\.company\\.com$"
msgstr "示例: @sub\\.company\\.com$"
-msgid "Example: My Value Stream"
-msgstr "例如:My Value Stream"
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr "示例:使用é‡=å•ä¸€æŸ¥è¯¢ã€‚(请求)/(容é‡)=å½¢æˆå…¬å¼çš„多é‡æŸ¥è¯¢ã€‚"
@@ -11576,15 +11817,21 @@ msgstr "导出åˆå¹¶è¯·æ±‚"
msgid "Export project"
msgstr "导出项目"
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr "将所有相关数æ®å¯¼å‡ºåˆ°æ–°çš„GitLab实例。完æˆåŽï¼Œæ‚¨å¯ä»¥ä»Ž\"创建新群组\"页é¢å¯¼å…¥æ•°æ®æ–‡ä»¶ã€‚"
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
-msgstr "导出此项目åŠå…¶æ‰€æœ‰ç›¸å…³æ•°æ®ï¼Œä»¥ä¾¿å°†é¡¹ç›®ç§»åŠ¨åˆ°æ–°çš„GitLab实例。导出完æˆåŽï¼Œæ‚¨å¯ä»¥ä»Žâ€œæ–°å»ºé¡¹ç›®â€é¡µé¢å¯¼å…¥æ–‡ä»¶ã€‚"
+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 Classification Policy Authorization"
msgstr "外部分类政策授æƒ"
@@ -11708,6 +11955,9 @@ msgstr "无法将rebaseæ“作加入队列,å¯èƒ½æ˜¯ç”±äºŽäº‹åŠ¡æ—¶é—´è¿‡é•¿ã€‚
msgid "Failed to find import label for Jira import."
msgstr "找ä¸åˆ°ç”¨äºŽJira导入的导入标记。"
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr "获å–ref失败。"
@@ -11891,9 +12141,6 @@ msgstr "无法进行快进åˆå¹¶ã€‚请将æºåˆ†æ”¯å˜åŸº(rebase)到目标分支ä
msgid "Fast-forward merge without a merge commit"
msgstr "æ— åˆå¹¶æ交的快进å¼åˆå¹¶"
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr "速度更快,因其é‡ç”¨äº†é¡¹ç›®çš„工作空间(如果它ä¸å­˜åœ¨ï¼Œå°†å›žé€€åˆ°å…‹éš†ï¼‰"
-
msgid "Faster releases. Better code. Less pain."
msgstr "æ›´å¿«çš„å‘布。更好的代ç ã€‚更少的烦æ¼ã€‚"
@@ -12408,11 +12655,23 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr "如需帮助为您的实例设置æœåŠ¡å°ï¼Œè¯·è”系管ç†å‘˜ã€‚"
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
-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 more info, read the documentation."
msgstr "有关详细信æ¯ï¼Œè¯·é˜…读文档。"
@@ -12435,12 +12694,6 @@ msgstr "欲了解更多相关信æ¯ï¼Œè¯·å‚阅 %{deactivating_usage_ping_link_s
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr "欲了解更多信æ¯ï¼Œè¯·å‚阅%{link_start}ç¦ç”¨Seat Link%{link_end}的文档。"
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr "对于ç§æœ‰é¡¹ç›®ï¼Œä»»ä½•æˆå‘˜ï¼ˆè®¿å®¢æˆ–更高级别)都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和产物)"
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr "对于公开项目,任何人都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和产物)"
-
msgid "Forgot your password?"
msgstr "忘记密ç ï¼Ÿ"
@@ -12516,8 +12769,8 @@ msgstr "从创建议题到部署至生产环境"
msgid "From merge request merge until deploy to production"
msgstr "从åˆå¹¶è¯·æ±‚被åˆå¹¶åŽåˆ°éƒ¨ç½²è‡³ç”Ÿäº§çŽ¯å¢ƒ"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr "在Kubernetes集群详细信æ¯è§†å›¾ä¸­ï¼Œä»Žåº”用程åºåˆ—表中安装Runner"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
+msgstr ""
msgid "Full name"
msgstr "å…¨å"
@@ -12564,6 +12817,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr "Geo 节点"
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr "如果次è¦èŠ‚点存在,则ä¸èƒ½åˆ é™¤ä¸»è¦èŠ‚点。"
@@ -12978,8 +13234,8 @@ msgstr "Gitæ交版本"
msgid "Git shallow clone"
msgstr "Git 浅克隆"
-msgid "Git strategy for pipelines"
-msgstr "æµæ°´çº¿çš„Gitç­–ç•¥"
+msgid "Git strategy"
+msgstr ""
msgid "Git transfer in progress"
msgstr "Git传输正在进行中"
@@ -13008,9 +13264,6 @@ msgstr "GitLabå¸æˆ·åˆ›å»ºè¯·æ±‚"
msgid "GitLab Billing Team."
msgstr "GitLab计费团队。"
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr "Gitlab群组Runnerå¯ä»¥ç”¨æ¥è¿è¡Œç¾¤ç»„内所有项目的代ç ã€‚"
-
msgid "GitLab Import"
msgstr "GitLab导入"
@@ -13047,6 +13300,9 @@ msgstr "GitLab导出"
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr "GitLab是一个完整的DevOpså¹³å°ï¼Œä½œä¸ºå•ä¸ªåº”用程åºå‘ˆçŽ°ï¼Œä»Žæ ¹æœ¬ä¸Šæ”¹å˜äº†å¼€å‘,安全和è¿ç»´å›¢é˜Ÿçš„å作方å¼"
@@ -13131,9 +13387,6 @@ msgstr "GitLab Pages在此项目中ç¦ç”¨ã€‚您å¯ä»¥åœ¨æ‚¨çš„项目的%{strong_
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "首次部署åŽï¼Œç«™ç‚¹å¯èƒ½éœ€è¦è‡³å¤š30分钟æ‰å¯ç”¨ã€‚"
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr "了解如何上传é™æ€ç½‘站,并且通过按照%{link_start}GitLab Pages文档%{link_end}的指示æ¥ä½¿ç”¨GitLabæ¥æ供网站æœåŠ¡ã€‚"
-
msgid "GitLabPages|Learn more."
msgstr "了解更多。"
@@ -13161,6 +13414,9 @@ msgstr "删除页é¢åŽå¤–部将无法访问。"
msgid "GitLabPages|Save"
msgstr "ä¿å­˜"
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 "在获å–域å%{domain}çš„Let's Encryptè¯ä¹¦æ—¶å‡ºé”™ã€‚如需é‡è¯•ï¼Œè¯·è®¿é—®æ‚¨çš„%{link_start}域详细信æ¯%{link_end}。"
@@ -13434,9 +13690,6 @@ msgstr "群组 %{group_name} å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Group Audit Events"
msgstr "群组审计事件"
-msgid "Group CI/CD settings"
-msgstr "群组 CI/CD 设置"
-
msgid "Group Git LFS status:"
msgstr "群组Git LFS状æ€ï¼š"
@@ -13452,9 +13705,6 @@ msgstr "群组ID: %{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr "群组所有者必须先使用SAML登录,然åŽæ‰èƒ½å¯ç”¨ç¾¤ç»„托管å¸æˆ·"
-msgid "Group Runners"
-msgstr "群组Runner"
-
msgid "Group SAML must be enabled to test"
msgstr "å¿…é¡»å¯ç”¨ç¾¤ç»„SAMLæ‰èƒ½è¿›è¡Œæµ‹è¯•"
@@ -13506,6 +13756,12 @@ msgstr "群组维护者å¯ä»¥åœ¨é€šè¿‡ %{link} 注册群组级 Runner"
msgid "Group members"
msgstr "群组æˆå‘˜"
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr "群组里程碑"
@@ -13515,6 +13771,9 @@ msgstr "群组å称"
msgid "Group name (your organization)"
msgstr "群组å称(您的组织)"
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr "群组概览"
@@ -13539,6 +13798,12 @@ msgstr "群组推é€è§„则已存在,请å°è¯•æ›´æ–°"
msgid "Group requires separate account"
msgstr "群组需è¦å•ç‹¬è´¦æˆ·"
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr "群组å˜é‡ (继承)"
@@ -13798,7 +14063,7 @@ msgid "GroupSettings|Change group URL"
msgstr "更改群组URL"
msgid "GroupSettings|Changing group URL can have unintended side effects."
-msgstr "更改群组URLå¯èƒ½ä¼šæœ‰æ„想ä¸åˆ°çš„副作用。"
+msgstr "更改群组URLå¯èƒ½ä¼šæœ‰éžé¢„期的副作用。"
msgid "GroupSettings|Compliance frameworks"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr "需åŒæ­¥çš„群组"
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr "有æƒè®¿é—®%{strong_open}%{project_name}%{strong_close}的群组"
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "有æƒè®¿é—®%{strong_start}%{group_name}%{strong_end}的群组"
-
msgid "GroupsDropdown|Frequently visited"
msgstr "ç»å¸¸è®¿é—®çš„群组"
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr "æ— å¯ç”¨çš„导入选项"
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr "已开始维护"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr "管家,导出,路径,转移,删除,存档。"
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr "身份标识"
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr "如果任何索引字段超过此é™åˆ¶ï¼Œå®ƒå°†è¢«æˆªæ–­ä¸ºè¯¥å­—符数,其余部分将无法索引或ä¸å¯æœç´¢ã€‚此设置ä¸é€‚用于仓库和Wiki索引。将此设置为0表示它是无é™çš„。"
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-msgstr "如果任何作业超过这个超时阈值,它将被标记为失败。å¯è¾“入英文语å¥ï¼Œå¦‚ “1 hourâ€ã€‚默认å•ä½ä¸ºç§’。"
-
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 "如果为空,则将å…许寿命设置为 %{instance_level_policy_in_words},如实例管ç†å‘˜æ‰€å®šä¹‰ã€‚设置åŽï¼Œè¯¥ç¾¤ç»„中的用户现有令牌å¯èƒ½ä¼šè¢«æ’¤é”€ã€‚"
@@ -14372,18 +14640,15 @@ msgstr "如果ç¦ç”¨ï¼Œåˆ™ä¸ä¼šä½¿ç”¨è¿œç¨‹å‰¯æœ¬çš„æ交自动更新分å‰çš„
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr "如果ç¦ç”¨ï¼Œåˆ™åªæœ‰ç®¡ç†å‘˜æ‰èƒ½é…置仓库镜åƒã€‚"
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr "如果ç¦ç”¨ï¼Œåˆ™è®¿é—®çº§åˆ«å°†å–决于用户在项目中的æƒé™ã€‚"
-
-msgid "If enabled"
-msgstr "如果已å¯ç”¨"
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr "如果YouTube网å€ä¸ºhttps://www.youtube.com/watch?v=0t1DgySidms,则视频ID为%{id}"
@@ -14627,15 +14892,360 @@ msgstr "使用GitLabä¼ä¸šç‰ˆå…¨å±€æœç´¢å¸¦æ¥çš„增强æœç´¢åŠŸèƒ½"
msgid "In %{time_to_now}"
msgstr "%{time_to_now}åŽ"
+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 order to enable Service Desk for your instance, you must first set up incoming email."
msgstr "为了为您的实例å¯ç”¨æœåŠ¡å°ï¼Œæ‚¨å¿…须首先设置接收电å­é‚®ä»¶ã€‚"
-msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
-msgstr "为了能é‡èº«å®šåˆ¶æ‚¨åœ¨GitLab的体验,%{br_tag}我们希望对您有更多了解。"
-
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr "事件"
@@ -14771,9 +15381,39 @@ 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 "摘è¦"
@@ -14855,8 +15495,8 @@ msgstr "内è”"
msgid "Input host keys manually"
msgstr "手动输入主机密钥"
-msgid "Input your repository URL"
-msgstr "输入您的仓库URL"
+msgid "Input the remote repository URL"
+msgstr ""
msgid "Insert a code block"
msgstr "æ’入代ç å—"
@@ -14897,11 +15537,11 @@ msgstr "此项目已在insights.yml文件中筛选掉(è§projects.onlyé…置以ä
msgid "Install"
msgstr "安装"
-msgid "Install GitLab Runner"
-msgstr "安装GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
+msgstr ""
-msgid "Install Runner on Kubernetes"
-msgstr "在Kubernetes上安装Runner"
+msgid "Install GitLab Runner on Kubernetes"
+msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr "从您的应用程åºåº“安装软令牌验è¯å™¨å¦‚ %{free_otp_link} 或者谷歌验è¯å™¨ï¼Œç„¶åŽä½¿ç”¨è¯¥éªŒè¯å™¨æ‰«æ此二维ç ã€‚更多信æ¯è¯·æŸ¥çœ‹%{help_link_start}文档%{help_link_end}。"
@@ -14925,9 +15565,21 @@ msgstr[0] "实例"
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr "无法加载议题与åˆå¹¶è¯·æ±‚图表。请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
@@ -15033,6 +15685,9 @@ msgstr "%{integration}设置已ä¿å­˜å¹¶å¯ç”¨ã€‚"
msgid "Integrations|%{integration} settings saved, but not active."
msgstr "%{integration}设置已ä¿å­˜ä½†æœªå¯ç”¨ã€‚"
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr "所有详细信æ¯"
@@ -15063,6 +15718,12 @@ msgstr "默认设置继承自实例级别。"
msgid "Integrations|Enable comments"
msgstr "å¯ç”¨è¯„论"
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr "包括标准加整个æ交消æ¯ï¼Œæ交哈希和议题ID"
@@ -15072,12 +15733,18 @@ msgstr "包括æ交的标题和分支"
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr "当议题在Jira中设定的项目中创建åŽï¼ŒJira中创建的议题会显示于此。"
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr "使用自定义设置的项目ä¸ä¼šå—到影å“。"
@@ -15102,6 +15769,9 @@ msgstr "ä¿å­˜å°†æ›´æ–°æ‰€æœ‰ä¸ä½¿ç”¨è‡ªå®šä¹‰è®¾ç½®çš„项目的默认设置。
msgid "Integrations|Search Jira issues"
msgstr "æœç´¢Jira议题"
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr "标准"
@@ -15129,6 +15799,9 @@ msgstr "在æ交或åˆå¹¶è¯·æ±‚中æåŠJira议题时,将创建远程链接å’
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr "您现在å¯ä»¥å…³é—­æ­¤çª—å£å¹¶è¿”回GitLab for Jira应用。"
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr "交互模å¼"
@@ -15216,6 +15889,9 @@ msgstr "输入无效,请é¿å…使用表情符å·"
msgid "Invalid login or password"
msgstr "登录å或密ç æ— æ•ˆ"
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr "无效的 pin ç "
@@ -15276,6 +15952,9 @@ msgstr "邀请群组"
msgid "Invite member"
msgstr "邀请æˆå‘˜"
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr "邀请团队æˆå‘˜"
@@ -15531,6 +16210,12 @@ msgstr "状æ€"
msgid "IssueAnalytics|Weight"
msgstr "æƒé‡"
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€š
msgid "Issues closed"
msgstr "关闭议题"
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr "默认分支中的åˆå¹¶è¯·æ±‚å’Œæ交引用的议题将自动关闭"
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr "议题评论,åˆå¹¶è¯·æ±‚的差异和评论,标记,里程碑,代ç ç‰‡æ®µå’Œå…¶ä»–项目实体"
@@ -15627,6 +16309,9 @@ 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 "看起æ¥ä½ åœ¨è¿™ä¸ªåˆ†æ”¯ä¸Šæœ‰ä¸€äº›è‰ç¨¿æ交。"
@@ -15729,24 +16414,42 @@ msgstr "%{jira_docs_link_start}å¯ç”¨Jira集æˆ%{jira_docs_link_end}以在GitLab
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr "%{user_link}在%{project_link}%{branch}中的%{entity_link}中æåŠæ­¤è®®é¢˜: {quote}%{entity_message}{quote}"
+msgid "JiraService|An error occured while fetching issue list"
+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 "显示Jira议题且ä¿æŒGitLab自带议题功能å¯ç”¨å¯èƒ½å¼•èµ·æ··æ·†ã€‚如未计划使用,请考虑%{linkStart}ç¦ç”¨GitLab议题%{linkEnd}。"
msgid "JiraService|Enable Jira issues"
msgstr "å¯ç”¨Jira议题"
+msgid "JiraService|Enable Jira issues creation from vulnerabilities"
+msgstr ""
+
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} 事件已ç¦ç”¨ã€‚"
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr "如果与 Web URL ä¸åŒ"
msgid "JiraService|Issue List"
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 "Jira API URL"
@@ -15762,6 +16465,9 @@ msgstr "在åˆå¹¶è¯·æ±‚中引用议题时将创建Jira评论。"
msgid "JiraService|Jira issue tracker"
msgstr "Jira 议题跟踪"
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Jira project key"
@@ -15774,9 +16480,21 @@ msgstr "打开Jira"
msgid "JiraService|Password or API token"
msgstr "密ç æˆ– API 令牌"
+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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr "此功能需è¦é«˜çº§è®¡åˆ’。"
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr "确定è¦ç»§ç»­å—?"
@@ -15894,8 +16615,8 @@ msgstr "作业产物"
msgid "Job|Job has been erased"
msgstr "作业已被删除"
-msgid "Job|Job has been erased by"
-msgstr "作业已被删除"
+msgid "Job|Job has been erased by %{userLink}"
+msgstr ""
msgid "Job|Keep"
msgstr "ä¿æŒ"
@@ -15969,6 +16690,9 @@ msgstr "仅我自己"
msgid "K8s pod health"
msgstr "K8s podå¥åº·"
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr "ä¿ç•™åˆ†å‰çš„refs"
@@ -15996,6 +16720,9 @@ msgstr "Ctrl +"
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr "全局快æ·é”®"
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr "开关性能æ "
@@ -16180,8 +16907,8 @@ msgstr "最åŽè”ç³»"
msgid "Last edited %{date}"
msgstr "最åŽä¿®æ”¹äºŽ%{date}"
-msgid "Last edited by %{name}"
-msgstr "最åŽä¿®æ”¹æ¥è‡ªäºŽ%{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
+msgstr ""
msgid "Last item before this page loaded in your browser:"
msgstr "此页é¢åœ¨æ‚¨çš„æµè§ˆå™¨ä¸­è½½å…¥å‰çš„最åŽä¸€ä¸ªé¡¹ç›®ï¼š"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr "学习GitLab"
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr "进一步了解%{username}"
msgid "Learn more about Auto DevOps"
msgstr "了解更多关于Auto DevOps"
-msgid "Learn more about Kubernetes"
-msgstr "进一步了解关于Kubernetesçš„ä¿¡æ¯"
-
msgid "Learn more about License-Check"
msgstr "进一步了解有关许å¯è¯æ£€æŸ¥çš„ä¿¡æ¯"
@@ -16580,6 +17304,9 @@ msgstr[0] "最多显示 %d 个事件"
msgid "Line changes"
msgstr "è¡Œå˜æ›´"
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr "将Prometheus监控链接到 GitLab。"
@@ -16754,9 +17481,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr "å·²åˆå¹¶"
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr "返回åˆå¹¶è¯·æ±‚"
@@ -16781,6 +17505,12 @@ 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 "åªæŸ¥çœ‹å˜æ›´å†…容"
@@ -16805,9 +17535,6 @@ msgstr "将议题设置为ç§å¯†ã€‚"
msgid "Make sure you save it - you won't be able to access it again."
msgstr "请确ä¿å¦¥å–„ä¿å­˜å®ƒ - 您无法å†æ¬¡è®¿é—®å®ƒçš„内容。"
-msgid "Make this epic confidential"
-msgstr "将此å²è¯—设置为ç§å¯†"
-
msgid "Makes this issue confidential."
msgstr "将此议题设置为ç§å¯†."
@@ -16850,6 +17577,9 @@ msgstr "管ç†åŒé‡è®¤è¯"
msgid "Manage your license"
msgstr "管ç†è®¸å¯è¯"
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr "托管账户"
@@ -17042,12 +17772,15 @@ msgstr "最大NuGet文件包大å°ï¼ˆå­—节)"
msgid "Maximum PyPI package file size in bytes"
msgstr "最大PyPI文件包大å°ï¼ˆå­—节)"
-msgid "Maximum Users:"
-msgstr "最大用户数:"
+msgid "Maximum Users"
+msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr "个人访问令牌的最长有效期(天)"
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr "最大产物大å°ï¼ˆMB)"
@@ -17087,9 +17820,6 @@ msgstr "最大作业超时"
msgid "Maximum job timeout has a value which could not be accepted"
msgstr "作业最大超时设置无效"
-msgid "Maximum length 100 characters"
-msgstr "最大长度100个字符"
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr "个人访问令牌有最长有效期设定,过期日期必须设为%{maximum_allowable_date}之å‰ã€‚"
@@ -17132,6 +17862,9 @@ msgstr "åŒæ­¥é•œåƒè®¡åˆ’的最大时间间隔。"
msgid "May"
msgstr "5月"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr "以代ç å­—节为å•ä½ã€‚排除生æˆçš„代ç å’Œä¾›åº”商代ç ã€‚"
@@ -17159,9 +17892,6 @@ msgstr "æˆå‘˜"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr "æˆå‘˜å¯ç”±é¡¹ç›®çš„%{i_open}维护者%{i_close} 或 %{i_open}所有者%{i_close}添加"
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr "被邀请到%{strong_start}%{group_name}%{strong_end}çš„æˆå‘˜"
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr "%{strong_open}%{project_name}%{strong_close}çš„æˆå‘˜"
msgid "Members of a group may only view projects they have permission to access"
msgstr "群组æˆå‘˜åªèƒ½æŸ¥çœ‹ä»–们有æƒè®¿é—®çš„项目"
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "有æƒè®¿é—®%{strong_start}%{group_name}%{strong_end}çš„æˆå‘˜"
-
msgid "Members|%{time} by %{user}"
msgstr "于%{time}由%{user}"
@@ -17279,6 +18006,9 @@ msgstr "å·²æ¢å¤åˆ°LDAP群组åŒæ­¥è®¾ç½®."
msgid "Members|Role updated successfully."
msgstr "å·²æˆåŠŸæ›´æ–°è§’色。"
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr "æœç´¢å·²é‚€è¯·"
@@ -17372,6 +18102,9 @@ msgstr "åˆå¹¶è¯·æ±‚核准å…许您设置必è¦æ ¸å‡†çš„æ•°é‡ï¼Œå¹¶é¢„定义项
msgid "Merge request dependencies"
msgstr "åˆå¹¶è¯·æ±‚ä¾èµ–"
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶"
@@ -17453,9 +18186,6 @@ msgstr "ä¿å­˜è¯„论è‰ç¨¿æ—¶å‘生错误。"
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr "无法压缩(Squash)。应该手动完æˆã€‚"
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr "跳转到下一个未解决的主题"
-
msgid "MergeRequests|Reply..."
msgstr "回å¤..."
@@ -17522,15 +18252,9 @@ msgstr "未找到任何文件"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr "æœç´¢æ–‡ä»¶(%{modifier_key}P)"
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "å·²åˆå¹¶"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr "å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
@@ -17928,6 +18652,9 @@ msgstr "从外部数æ®æºè¿ç§»æ‚¨çš„æ•°æ®ï¼Œä¾‹å¦‚GitHub 〠Bitbucket或å¦å
msgid "Migrated %{success_count}/%{total_count} files."
msgstr "å·²è¿ç§» %{success_count}/%{total_count} 文件。"
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr "è¿ç§»æˆåŠŸã€‚"
@@ -18097,6 +18824,9 @@ msgstr "分钟"
msgid "Mirror direction"
msgstr "é•œåƒæ–¹å‘"
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr "é•œåƒä»“库"
@@ -18148,9 +18878,6 @@ msgstr "在您的个人资料中添加SSH密钥之å‰ï¼Œæ‚¨ä¸èƒ½é€šè¿‡SSHæ¥æ‹‰
msgid "ModalButton|Add projects"
msgstr "添加项目"
-msgid "Modal|Cancel"
-msgstr "å–消"
-
msgid "Modal|Close"
msgstr "关闭"
@@ -18319,9 +19046,6 @@ msgstr "å称"
msgid "Name has already been taken"
msgstr "å称已被使用"
-msgid "Name is required"
-msgstr "å称是必需的"
-
msgid "Name new label"
msgstr "命å新标记"
@@ -18453,12 +19177,6 @@ msgstr "全选"
msgid "NetworkPolicies|Allow"
msgstr "å…许"
-msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
-msgstr "å…许从%{ruleSelector}到%{selector}于%{ports}的所有入站æµé‡"
-
-msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
-msgstr "å…许从%{selector}到%{ruleSelector}于%{ports}的所有出站æµé‡"
-
msgid "NetworkPolicies|Are you sure you want to delete this policy? This action cannot be undone."
msgstr "您确定è¦åˆ é™¤æ­¤ç­–ç•¥å—?此æ“作ä¸èƒ½æ’¤æ¶ˆã€‚"
@@ -18477,6 +19195,12 @@ msgstr "删除策略"
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr "删除策略: %{policy}"
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr "æ‹’ç»æ‰€æœ‰æµé‡"
@@ -18531,6 +19255,9 @@ msgstr "未检测到策略"
msgid "NetworkPolicies|None selected"
msgstr "未选择"
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr "策略具体定义了pod组如何与其他组中的pod进行网络端点通信。"
@@ -18778,8 +19505,8 @@ msgstr "新里程碑"
msgid "New password"
msgstr "新密ç "
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr "æ–°æµæ°´çº¿å°†å–消åŒä¸€åˆ†æ”¯ä¸Šè¾ƒæ—§çš„待处ç†æµæ°´çº¿"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
+msgstr ""
msgid "New project"
msgstr "新建项目"
@@ -18895,6 +19622,9 @@ msgstr "没有匹é…当å‰ç­›é€‰å™¨çš„å­å²è¯—"
msgid "No commits present here"
msgstr "此处无æ交"
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
@@ -18988,6 +19718,9 @@ msgstr "没有匹é…的结果"
msgid "No matching results for \"%{query}\""
msgstr "没有与“%{query}â€åŒ¹é…的结果"
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr "未找到æˆå‘˜"
@@ -19063,9 +19796,6 @@ msgstr "没有符åˆæ‚¨æœç´¢æ¡ä»¶çš„星标用户"
msgid "No start date"
msgstr "没有开始日期"
-msgid "No status"
-msgstr "无状æ€"
-
msgid "No template"
msgstr "没有模æ¿"
@@ -19075,6 +19805,9 @@ msgstr "未选择模æ¿"
msgid "No test coverage"
msgstr "无测试覆盖率"
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr "æ— æ¼æ´ž"
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr "添加计划失败"
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,11 +20267,11 @@ msgstr "无法获å–站点é…置文件。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr "无法è¿è¡Œæ‰«æ。请é‡è¯•ã€‚"
-msgid "OnDemandScans|Create a new scanner profile"
-msgstr "创建一个新的扫æ工具é…置文件"
+msgid "OnDemandScans|Create new scanner profile"
+msgstr ""
-msgid "OnDemandScans|Create a new site profile"
-msgstr "创建一个新的站点é…置文件"
+msgid "OnDemandScans|Create new site profile"
+msgstr ""
msgid "OnDemandScans|Description (optional)"
msgstr ""
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr "管ç†é…置文件"
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,11 +20345,11 @@ msgstr "您å¯ä»¥è¿›è¡Œè¢«åŠ¨æ‰«æ或验è¯æ‚¨é€‰æ‹©çš„站点é…置中的目标
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr "您ä¸èƒ½å¯¹æœªéªŒè¯çš„网站上è¿è¡Œä¸»åŠ¨æ‰«æ。"
-msgid "Once 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 "一旦项目被永久删除将%{strongStart}无法æ¢å¤%{strongEnd}。永久删除此项目将%{strongStart}ç«‹å³åˆ é™¤%{strongEnd}其仓库和%{strongStart}所有相关的资æº%{strongEnd}包括议题ã€åˆå¹¶è¯·æ±‚等。"
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
-msgstr "项目永久删除åŽï¼Œå°†æ— æ³•æ¢å¤ã€‚您将丢失该项目的仓库和所有内容:议题,åˆå¹¶è¯·æ±‚等。"
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
+msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡SSH进行镜åƒã€‚点击%{link_start}此处%{link_end}了解更多."
@@ -19634,8 +20385,8 @@ msgstr "您的一个或多个个人访问令牌已过期。"
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
msgstr "您的一个或多个个人访问令牌将在%{days_to_expire}天内过期。"
-msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
-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 "åªèƒ½å­˜åœ¨ä¸€ä¸ªå¤–观行"
@@ -19652,9 +20403,6 @@ msgstr "仅活动的项目显示在æœç´¢å’Œä»ªè¡¨æ¿ä¸Šã€‚"
msgid "Only admins can delete project"
msgstr "åªæœ‰ç®¡ç†å‘˜å¯ä»¥åˆ é™¤é¡¹ç›®"
-msgid "Only mirror protected branches"
-msgstr "åªé•œåƒå—ä¿æŠ¤çš„分支"
-
msgid "Only policy:"
msgstr "ä»…ä»…(Only)æ¡ä»¶ï¼š"
@@ -19673,8 +20421,8 @@ 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 / Silver and above can see Productivity Analytics."
-msgstr "åªæœ‰â€œé«˜çº§â€æˆ–“银牌â€åŠä»¥ä¸Šçº§åˆ«ä¸­çš„“Reporterâ€åŠä»¥ä¸Šè§’色å¯ä»¥æŸ¥çœ‹æ•ˆçŽ‡åˆ†æžã€‚"
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
+msgstr ""
msgid "Oops, are you sure?"
msgstr "å•Š~~, 确定å—?"
@@ -19781,15 +20529,15 @@ msgstr "æ“作"
msgid "Or you can choose one of the suggested colors below"
msgstr "或者您å¯ä»¥é€‰æ‹©ä¸‹é¢çš„建议颜色之一"
-msgid "Origin"
-msgstr "æº"
-
msgid "Orphaned member"
msgstr "孤儿æˆå‘˜"
msgid "Other Labels"
msgstr "其他标记"
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr "其他信æ¯"
@@ -19964,9 +20712,6 @@ msgstr "删除软件包版本"
msgid "PackageRegistry|Delete package"
msgstr "删除软件包"
-msgid "PackageRegistry|Filter by name"
-msgstr "按å称筛选"
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr "关于Composer注册表的更多信æ¯ï¼Œ%{linkStart}请è§æ–‡æ¡£ã€‚%{linkEnd}"
@@ -19985,6 +20730,9 @@ msgstr "关于PyPi注册表的更多信æ¯ï¼Œ%{linkStart}请è§æ–‡æ¡£%{linkEnd}ã
msgid "PackageRegistry|Generic"
msgstr "通用"
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}.pypirc%{codeEnd}文件中。"
@@ -20057,9 +20805,6 @@ msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆç­›é€‰å™¨çš„任何结果"
msgid "PackageRegistry|Source project located at %{link}"
msgstr "æºé¡¹ç›®ä½äºŽ%{link}"
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr "当å‰æ— %{packageType}软件包"
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr "此软件包没有其他版本。"
@@ -20075,6 +20820,9 @@ msgstr "这个Nuget包没有ä¾èµ–项目。"
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 "无法获å–软件包版本信æ¯ã€‚"
@@ -20213,6 +20961,9 @@ msgstr "部分令牌内容仅供å‚考"
msgid "Participants"
msgstr "å‚与者"
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr "通过"
@@ -20327,6 +21078,9 @@ msgstr "下载"
msgid "PerformanceBar|Elasticsearch calls"
msgstr "Elasticsearch调用"
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr "å‰ç«¯èµ„æº"
@@ -20393,6 +21147,9 @@ msgstr "æµæ°´çº¿è®¡åˆ’"
msgid "Pipeline Schedules"
msgstr "æµæ°´çº¿è®¡åˆ’"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr "æµæ°´çº¿åˆ†é’Ÿæ•°é…é¢"
@@ -20405,6 +21162,9 @@ 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 "æµæ°´çº¿è§¦å‘器"
@@ -20573,9 +21333,6 @@ msgstr "载入æµæ°´çº¿"
msgid "Pipelines|More Information"
msgstr "更多信æ¯"
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr "在这个仓库中找ä¸åˆ°CI文件,请添加一个。"
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr "尚未创建触å‘器。请使用上é¢çš„表å•æ·»åŠ è§¦å‘器。"
@@ -20588,9 +21345,6 @@ msgstr "æµæ°´çº¿ç¼–辑器"
msgid "Pipelines|Project cache successfully reset."
msgstr "项目缓存é‡ç½®æˆåŠŸã€‚"
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr "仓库没有默认分支,请设置一个。"
-
msgid "Pipelines|Revoke"
msgstr "撤销"
@@ -20612,6 +21366,9 @@ msgstr "ç›®å‰æ²¡æœ‰å·²å®Œæˆçš„æµæ°´çº¿ã€‚"
msgid "Pipelines|There are currently no pipelines."
msgstr "当å‰æ— æµæ°´çº¿ã€‚"
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "获å–æµæ°´çº¿æ—¶å‡ºé”™ã€‚请ç¨åŽé‡è¯•æˆ–è”系支æŒå›¢é˜Ÿã€‚"
@@ -20726,6 +21483,9 @@ msgstr "è¿è¡Œæµæ°´çº¿"
msgid "Pipeline|Run for"
msgstr "è¿è¡ŒäºŽ"
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr "è¿è¡Œä¸­"
@@ -21395,12 +22155,15 @@ msgstr "ä¿¡æ¯åŠ¨æ€ä»¤ç‰Œå·²æˆåŠŸé‡ç½®"
msgid "Profiles|Full name"
msgstr "å…¨å"
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 "在个人资料中包å«éžå…¬å¼€è´¡çŒ®"
@@ -21446,9 +22209,6 @@ msgstr "组织"
msgid "Profiles|Path"
msgstr "路径"
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr "您新头åƒçš„ä½ç½®å’Œå¤§å°"
@@ -21731,6 +22491,9 @@ msgstr "项目å称"
msgid "Project name suffix"
msgstr "项目å称åŽç¼€"
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr "由于本地存储ä¸å¯ç”¨ï¼Œå› æ­¤ä¸ä¼šä¿å­˜é¡¹ç›®é¡ºåºã€‚"
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,8 +23037,8 @@ msgstr "属于群组的项目以群组å称为å‰ç¼€ã€‚现有项目å¯ä»¥ç§»åŠ¨
msgid "Projects to index"
msgstr "è¦ç´¢å¼•çš„项目"
-msgid "Projects will be permanently deleted after a 7-day waiting period."
-msgstr "项目将于7天等待期åŽè¢«æ°¸ä¹…删除。"
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
+msgstr ""
msgid "Projects will be permanently deleted immediately."
msgstr "项目将立å³è¢«æ°¸ä¹…删除。"
@@ -22646,6 +23412,9 @@ msgstr "æ示用户上传SSH密钥"
msgid "Protect"
msgstr "ä¿æŠ¤"
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr "ä¿æŠ¤å˜é‡"
@@ -22694,6 +23463,9 @@ msgstr "å…许推é€ï¼š"
msgid "ProtectedBranch|Branch"
msgstr "分支"
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr "代ç æ‰€æœ‰è€…批准"
@@ -22730,6 +23502,9 @@ msgstr "å…许部署"
msgid "ProtectedEnvironment|Environment"
msgstr "环境"
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "ä¿æŠ¤"
@@ -22739,9 +23514,6 @@ msgstr "ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒ"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "å—ä¿æŠ¤çš„环境 (%{protected_environments_count})"
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr "ä¿æŠ¤çŽ¯å¢ƒä¼šé™åˆ¶å¯ä»¥æ‰§è¡Œéƒ¨ç½²çš„用户的范围。"
-
msgid "ProtectedEnvironment|Select an environment"
msgstr "选择一个环境"
@@ -22751,8 +23523,8 @@ msgstr "选择用户"
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr "选择用户æ¥éƒ¨ç½²å’Œç®¡ç†åŠŸèƒ½æ ‡å¿—设置"
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr "ç›®å‰æ— å—ä¿æŠ¤çš„环境,请使用上述表å•ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒã€‚"
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
+msgstr ""
msgid "ProtectedEnvironment|Unprotect"
msgstr "å–消ä¿æŠ¤"
@@ -22970,6 +23742,9 @@ msgstr "了解更多关于相关议题的信æ¯"
msgid "Real-time features"
msgstr "实时功能"
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr "å˜åŸº"
@@ -23082,12 +23857,21 @@ msgstr "注册通用åŒé‡è®¤è¯è®¾å¤‡(U2F)"
msgid "Register WebAuthn Device"
msgstr "注册WebAuthn设备"
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 "使用åŒé‡è®¤è¯åº”用注册"
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr "已拒ç»(关闭)"
-msgid "Related Deployed Jobs"
-msgstr "相关的部署作业"
-
msgid "Related Issues"
msgstr "相关议题"
-msgid "Related Jobs"
-msgstr "相关的作业"
-
-msgid "Related Merge Requests"
-msgstr "相关的åˆå¹¶è¯·æ±‚"
-
-msgid "Related Merged Requests"
-msgstr "相关已åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
-
msgid "Related issues"
msgstr "相关议题"
@@ -23224,9 +23996,6 @@ msgstr "删除"
msgid "Remove %{displayReference}"
msgstr "删除%{displayReference}"
-msgid "Remove Runner"
-msgstr "移除Runner"
-
msgid "Remove Zoom meeting"
msgstr "删除Zoom会议"
@@ -23320,6 +24089,9 @@ msgstr "删除报告"
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr "删除次è¦èŠ‚点"
@@ -23565,6 +24337,10 @@ 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] ""
+
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] "过去14天中在%{base_branch}上,失败了%{count} 次"
@@ -23731,6 +24507,9 @@ msgstr "仓库存储"
msgid "Repository synchronization concurrency limit"
msgstr "仓库åŒæ­¥å¹¶å‘é™åˆ¶"
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr "仓库: %{counter_repositories} /Wikis: %{counter_wikis} /构建产物: %{counter_build_artifacts} /LFS: %{counter_lfs_objects} /代ç ç‰‡æ®µ: %{counter_snippets} /软件包: %{counter_packages} /上传: %{counter_uploads}"
@@ -23862,8 +24641,8 @@ msgstr "é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥è®¿é—®ä»¤ç‰Œ"
msgid "Reset key"
msgstr "é‡ç½®å¯†é’¥"
-msgid "Reset runners registration token"
-msgstr "é‡ç½® Runner 注册令牌"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr "é‡ç½®æ¨¡æ¿"
@@ -23985,6 +24764,9 @@ msgstr "é‡è¯•"
msgid "Retry job"
msgstr "é‡è¯•ä½œä¸š"
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr "é‡è¯•å½“å‰ä½œä¸š"
@@ -24031,6 +24813,9 @@ 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 "查看在您的身份验è¯æ供商中é…ç½®æœåŠ¡æ供商的æµç¨‹ - 在这里,GitLab是“æœåŠ¡æ供商â€æˆ–“ä¾èµ–æ–¹â€ã€‚"
+msgid "Review the target project before submitting to avoid exposing %{source} changes."
+msgstr ""
+
msgid "Review time"
msgstr "审核时间"
@@ -24071,6 +24856,9 @@ msgstr "撤销个人访问令牌 %{personal_access_token_name}ï¼"
msgid "Revoked project access token %{project_access_token_name}!"
msgstr "撤销项目访问令牌%{project_access_token_name}ï¼"
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr "添加"
@@ -24116,6 +24904,9 @@ msgstr "使用Web终端对您的代ç è¿›è¡Œå®žæ—¶æµ‹è¯•"
msgid "Run untagged jobs"
msgstr "è¿è¡Œæœªæ ‡è®°çš„作业"
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr "Runner处于%{status},最åŽä¸€æ¬¡è”系是%{runner_contact}å‰"
@@ -24137,21 +24928,9 @@ msgstr "Runnerå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Runners"
msgstr "Runner"
-msgid "Runners API"
-msgstr "Runners API"
-
-msgid "Runners activated for this project"
-msgstr "此项目已激活的Runner"
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr "Runner是GitLab获å–和执行æµæ°´çº¿ä½œä¸šçš„进程。在这里您å¯ä»¥æ³¨å†Œå¹¶æŸ¥çœ‹å½“å‰é¡¹ç›®çš„Runner。"
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr "Runnerå¯ä»¥æ”¾åœ¨ä¸åŒçš„用户ã€æœåŠ¡å™¨ï¼Œç”šè‡³æœ¬åœ°æœºå™¨ä¸Šã€‚"
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr "Runner页é¢."
msgid "Runners|Active"
msgstr "å¯ç”¨"
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr "架构"
msgid "Runners|Can run untagged jobs"
msgstr "å¯ä»¥è¿è¡Œæœªæ ‡è®°çš„作业"
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr "æè¿°"
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr "群组"
msgid "Runners|IP Address"
msgstr "IP地å€"
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "最åŽè”ç³»"
@@ -24200,24 +24994,39 @@ msgstr "属性å称"
msgid "Runners|Protected"
msgstr "å—ä¿æŠ¤"
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr "版本"
msgid "Runners|Shared"
msgstr "共享的"
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr "特定的"
msgid "Runners|Tags"
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|Value"
msgstr "值"
msgid "Runners|Version"
msgstr "版本"
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´çº¿æ—¶é—´é…é¢é™åˆ¶ï¼ˆ%{quotaLimit} )。"
@@ -24290,6 +25099,9 @@ msgstr "SSH公钥"
msgid "SSL Verification:"
msgstr "SSL验è¯ï¼š"
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr "满足"
@@ -24625,6 +25437,9 @@ msgstr "密ç "
msgid "Secret Detection"
msgstr "密ç æ£€æµ‹"
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr "安全"
@@ -24640,6 +25455,9 @@ 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 "安全报告已过时。请使用目标分支(%{targetBranchName})中的最新更改æ¥æ›´æ–°æ‚¨çš„分支。"
@@ -24799,9 +25617,6 @@ msgstr "误报"
msgid "SecurityReports|Fuzzing artifacts"
msgstr "Fuzzing产物"
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr "跳转到%{linkStart}æµæ°´çº¿é€‰é¡¹å¡%{linkEnd}下载安全报告"
-
msgid "SecurityReports|Hide dismissed"
msgstr "éšè—已忽略项"
@@ -24865,9 +25680,6 @@ msgstr "安全报告帮助页é¢é“¾æŽ¥"
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr "安全扫æå·²è¿è¡Œã€‚跳转到%{linkStart}æµæ°´çº¿é€‰é¡¹å¡%{linkEnd}下载安全报告"
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr "请使用上é¢çš„项目æœç´¢å­—段æ¥é€‰æ‹©è¦æ·»åŠ çš„项目。"
@@ -24974,15 +25786,15 @@ msgstr "查看指标"
msgid "See the affected projects in the GitLab admin panel"
msgstr "查看 GitLab 管ç†é¢æ¿ä¸­çš„å—å½±å“项目"
+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 "有关任何修å¤çš„详细信æ¯ï¼Œè¯·å‚è§æ¼æ´ž%{vulnerability_link}。"
msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr "有关任何解决方案的详细信æ¯ï¼Œè¯·å‚è§æ¼æ´ž %{vulnerability_link}。"
-msgid "See what's new at GitLab"
-msgstr "查看GitLab的新功能"
-
msgid "Select"
msgstr "选择"
@@ -25040,8 +25852,8 @@ msgstr "选择时区"
msgid "Select all"
msgstr "选择全部"
-msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr "选择一个既有的Kubernetes集群或者创建一个新的"
+msgid "Select an existing Kubernetes cluster or create a new one."
+msgstr ""
msgid "Select assignee"
msgstr "选择指派人"
@@ -25070,6 +25882,9 @@ msgstr "选择è¦å¤åˆ¶çš„群组。"
msgid "Select health status"
msgstr "选择å¥åº·çŠ¶å†µ"
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr "选择标记"
@@ -25127,9 +25942,6 @@ msgstr "选择订阅"
msgid "Select target branch"
msgstr "选择目标分支"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr "选择当å‰é¡¹ç›®çš„默认分支。除éžå¦è¡ŒæŒ‡å®šï¼Œå¦åˆ™æ‰€æœ‰åˆå¹¶è¯·æ±‚å’Œæ交都将指å‘此分支。"
-
msgid "Select the custom project template source group."
msgstr "选择自定义项目模æ¿æºç¾¤ç»„。"
@@ -25412,6 +26224,9 @@ msgstr "设置目标分支"
msgid "Set target branch to %{branch_name}."
msgstr "设置目标分支为%{branch_name}。"
+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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr "设置æ¯ä¸ªä½œä¸šçš„产物的默认到期时间。 0 表示无é™åˆ¶ã€‚默认以秒为å•ä½ï¼Œä½†æ‚¨å¯ä»¥å®šä¹‰æ›¿ä»£æ–¹æ¡ˆã€‚例如:%{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}。"
@@ -25451,11 +26266,11 @@ msgstr "é…ç½® CI/CD"
msgid "Set up Jira Integration"
msgstr "设置Jira集æˆ"
-msgid "Set up a %{type} Runner automatically"
-msgstr "自动设置一个%{type}的Runner"
+msgid "Set up a %{type} runner automatically"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
-msgstr "手动设置%{type} Runner "
+msgid "Set up a %{type} runner manually"
+msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
msgstr "设置一个硬件设备作为登录的第二个因素。"
@@ -25469,9 +26284,6 @@ msgstr "设置新设备"
msgid "Set up new password"
msgstr "设置新密ç "
-msgid "Set up pipeline subscriptions for this project."
-msgstr "为此项目设置æµæ°´çº¿è®¢é˜…。"
-
msgid "Set up shared runner availability"
msgstr "设置共享è¿è¡Œå™¨å¯ç”¨æ€§"
@@ -25616,9 +26428,6 @@ msgstr "é‡ç½®å·²ç”¨æµæ°´çº¿åˆ†é’Ÿæ•°"
msgid "Sherlock Transactions"
msgstr "Sherlock事物"
-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 %{b_start}will%{b_end} lose access to your account."
-msgstr "如果您一旦丢失手机或无法访问一次性密ç å¯†ä¿ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ¢å¤ç æ¥é‡æ–°èŽ·å¾—您的å¸æˆ·è®¿é—®æƒé™ã€‚æ¯ä¸ªæ¢å¤ç ä»…å¯ä½¿ç”¨ä¸€æ¬¡ã€‚请将它们ä¿å­˜åœ¨å®‰å…¨çš„地方,å¦åˆ™ä¸¢å¤±åŽä½ %{b_start}å°†%{b_end}无法访问您的å¸æˆ·ã€‚"
-
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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr "显示最新版本"
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr "显示列表"
@@ -25909,9 +26721,6 @@ msgstr "设置此æœåŠ¡åŽï¼Œè¯·è¾“入以下内容,查看Slack中å¯ç”¨å‘½ä»¤ç
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr "æ­¤æœåŠ¡å…许用户通过在Slack中输入斜æ å‘½ä»¤æ¥å¯¹è¯¥é¡¹ç›®æ‰§è¡Œå¸¸è§æ“作。"
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr "更慢,但能确ä¿é¡¹ç›®å·¥ä½œç©ºé—´ä¸ŽåŽŸå§‹ç‰ˆæœ¬ä¸€è‡´ï¼›å› å…¶å¯¹æ¯ä¸ªä½œä¸šå‡ä»Žå¤´å¼€å§‹å…‹éš†ä»“库"
-
msgid "Smartcard"
msgstr "智能å¡"
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr "åœ¨èŽ·å– %{listType} 列表时出错了"
@@ -26422,8 +27234,8 @@ msgstr "垃圾信æ¯åŠé˜²æœºå™¨äººä¿æŠ¤"
msgid "Spam log successfully submitted as ham."
msgstr "垃圾信æ¯æ—¥å¿—å·²æˆåŠŸæ”¹ä¸ºæœ‰æ•ˆä¿¡æ¯æ交。"
-msgid "Specific Runners"
-msgstr "指定Runner"
+msgid "Specific runners"
+msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr "无法使用指定的URL:“%{reason}â€"
@@ -26431,9 +27243,6 @@ msgstr "无法使用指定的URL:“%{reason}â€"
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户。"
-msgid "Specify the following URL during the Runner setup:"
-msgstr "在 Runner 设置时指定以下 URL:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr "通过Needs关系加速您的æµæ°´çº¿"
@@ -26452,9 +27261,6 @@ msgstr "堆栈跟踪代ç ç‰‡æ®µ"
msgid "Stage"
msgstr "æš‚å­˜"
-msgid "Stage & Commit"
-msgstr "æš‚å­˜ & æ交"
-
msgid "Stage data updated"
msgstr "阶段数æ®å·²æ›´æ–°"
@@ -26509,8 +27315,8 @@ msgstr "å¯åŠ¨Web终端"
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
-msgid "Start a Free Gold Trial"
-msgstr "开始å…费的金牌试用"
+msgid "Start a Free Ultimate Trial"
+msgstr ""
msgid "Start a new discussion..."
msgstr "å¯åŠ¨æ–°çš„讨论..."
@@ -26542,9 +27348,6 @@ msgstr "æµæ°´çº¿æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
msgid "Start search"
msgstr "开始æœç´¢"
-msgid "Start the Runner!"
-msgstr "å¯åŠ¨ Runner!"
-
msgid "Start thread"
msgstr "å¼€å¯ä¸»é¢˜"
@@ -26554,8 +27357,8 @@ msgstr "开始主题并关闭%{noteable_name}"
msgid "Start thread & reopen %{noteable_name}"
msgstr "å¼€å¯ä¸»é¢˜å¹¶é‡æ–°æ‰“å¼€%{noteable_name}"
-msgid "Start your Free Gold Trial"
-msgstr "开始å…费的金牌试用"
+msgid "Start your Free Ultimate Trial"
+msgstr ""
msgid "Start your free trial"
msgstr "开始å…费试用"
@@ -26581,15 +27384,15 @@ msgstr "正在å¯åŠ¨..."
msgid "Starts %{startsIn}"
msgstr "开始 %{startsIn}"
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr "开始于(UTC)"
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr "输入消æ¯ä»¥å¯ç”¨"
@@ -26767,6 +27570,9 @@ msgstr "未知"
msgid "Subgroup milestone"
msgstr "å­ç¾¤ç»„里程碑"
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr "å­ç¾¤ç»„概览"
@@ -27178,6 +27984,9 @@ msgstr "系统页头和页脚"
msgid "System hook was successfully updated."
msgstr "系统钩å­å·²æˆåŠŸæ›´æ–°ã€‚"
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr "系统指标(自定义)"
@@ -27202,9 +28011,15 @@ 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 "使用“%{message}â€ä¸ºæ­¤æ交设置%{tag_name} 标签。"
@@ -27375,15 +28190,18 @@ msgstr[0] "您的æµæ°´çº¿ç”Ÿæˆäº†%{number}个Terraform报告"
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr "%{user}更新于%{timeAgo}"
-msgid "Terraform|A Terraform report failed to generate."
-msgstr "Terraform报告生æˆå¤±è´¥ã€‚"
+msgid "Terraform|A report failed to generate."
+msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
-msgstr "您的æµæ°´çº¿ç”Ÿæˆäº†Terraform报告。"
+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 "加载您的Terraform状æ€æ—¶å‘生错误"
@@ -27438,11 +28256,11 @@ msgstr "报告资æºæ›´æ”¹: 添加%{addNum}项, 更改%{changeNum}项, 删除%{d
msgid "Terraform|States"
msgstr "状æ€"
-msgid "Terraform|The Terraform report %{name} failed to generate."
-msgstr "Terraform报告%{name}生æˆå¤±è´¥ã€‚"
+msgid "Terraform|The report %{name} failed to generate."
+msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
-msgstr "您的æµæ°´çº¿ç”Ÿæˆäº†Terraform报告%{name}。"
+msgid "Terraform|The report %{name} was generated in your pipelines."
+msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
msgstr ""
@@ -27768,9 +28586,6 @@ msgstr[0] "因为设置了新的个人访问令牌过期策略,以下个人访
msgid "The fork relationship has been removed."
msgstr "派生关系已被删除。"
-msgid "The form contains the following error:"
-msgstr "表å•åŒ…å«ä»¥ä¸‹é”™è¯¯ï¼š"
-
msgid "The form contains the following errors:"
msgstr "表å•åŒ…å«ä»¥ä¸‹é”™è¯¯ï¼š"
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr "许å¯è¯å¯†é’¥æ— æ•ˆã€‚请确ä¿å®ƒä¸Žæ‚¨ä»ŽGitLab Inc.收到的一致。"
@@ -27843,6 +28661,15 @@ msgstr "许å¯è¯å·²æˆåŠŸä¸Šä¼ ï¼Œå°†äºŽ%{starts_at}激活。您å¯ä»¥åœ¨ä¸‹é¢
msgid "The maximum file size allowed is %{size}."
msgstr "å…许的最大文件大å°ä¸º %{size}。"
+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 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 "GitLab无法解决此åˆå¹¶è¯·æ±‚çš„åˆå¹¶å†²çªã€‚请å°è¯•åœ¨æœ¬åœ°è§£å†³å®ƒä»¬ã€‚"
@@ -27858,8 +28685,11 @@ msgstr "åˆå¹¶è¯·æ±‚现在å¯ä»¥åˆå¹¶äº†ã€‚"
msgid "The name \"%{name}\" is already taken in this directory."
msgstr "å称“%{name}â€åœ¨æ­¤ç›®å½•ä¸­å·²ä½¿ç”¨ã€‚"
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
-msgstr "克隆仓库时从GitLab获å–çš„å˜æ›´æ•°ç›®ã€‚此设置å¯ä»¥åŠ å¿«æµæ°´çº¿çš„执行速度。ä¿æŒä¸ºç©ºæˆ–设置为0将默认ç¦ç”¨æµ…克隆,并使GitLab CIæ¯æ¬¡éƒ½èŽ·å–所有分支和标签。"
+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 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 "æ¯æœˆåˆå¹¶çš„åˆå¹¶è¯·æ±‚æ•°"
@@ -27876,9 +28706,6 @@ msgstr "父å²è¯—是ç§å¯†çš„,åªèƒ½åŒ…å«ç§å¯†å²è¯—和议题"
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "解密ç§é’¥æ‰€éœ€çš„密ç çŸ­è¯­ã€‚该项为å¯é€‰é¡¹, 并且内容被加密存储。"
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr "CIé…置文件的路径。默认为%{code_open}.gitlab-ci.yml%{code_close}"
-
msgid "The phase of the development lifecycle."
msgstr "项目生命周期中的å„个阶段。"
@@ -27924,6 +28751,9 @@ msgstr "该项目已æˆåŠŸå¯¼å…¥ã€‚"
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
msgstr "匿å化数æ®æœé›†å·²ç¦ç”¨ã€‚该功能å¯ç”¨æ—¶ï¼ŒGitLab会è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
+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 took to long to complete."
msgstr "远程仓库镜åƒè¶…时未完æˆã€‚"
@@ -27951,9 +28781,6 @@ msgstr "仓库必须能够通过%{code_open}http://%{code_close}, %{code_open}ht
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "审阅阶段概述了从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶çš„时间。当创建第一个åˆå¹¶è¯·æ±‚åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 "åŒä¸€ä¸ªå…±äº«runnerå¯æ‰§è¡Œå¤šä¸ªé¡¹ç›®çš„代ç ï¼Œé™¤éžæ‚¨é…置了自动伸缩,将%{link}设置为1 (GitLab.com 上的设置)。"
@@ -28008,8 +28835,8 @@ 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 "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å将被导入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹è¡¨æ ¼æ¥ä¿®æ”¹æ˜ å°„关系。"
-msgid "The user you are trying to approve is not pending an approval"
-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 "您正在å°è¯•å†»ç»“的用户在过去%{minimum_inactive_days}天一直处于活动状æ€ï¼Œå› æ­¤æ— æ³•å†»ç»“。"
@@ -28116,8 +28943,8 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr "环境上有正在è¿è¡Œçš„部署。请ç¨åŽé‡è¯•ã€‚"
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
-msgstr "项目的订阅和被订阅数é‡ä¸Šé™ä¸º%{ci_project_subscriptions_limit}。"
+msgid "There is a halted Elasticsearch migration"
+msgstr ""
msgid "There is already a To-Do for this design."
msgstr "此设计已ç»æœ‰ä¸€ä¸ªå¾…办事项。"
@@ -28164,6 +28991,9 @@ msgstr "获å–项目标签时出错。"
msgid "There was a problem fetching project users."
msgstr "获å–项目用户时出错。"
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr "获å–用户时出现问题。"
@@ -28176,6 +29006,9 @@ msgstr "ä¿å­˜æ‚¨çš„自定义阶段时出错,请é‡è¯•"
msgid "There was a problem sending the confirmation email"
msgstr "å‘é€ç¡®è®¤é‚®ä»¶æ—¶å‡ºçŽ°é—®é¢˜"
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr "%{message}待办事项时出现错误"
@@ -28329,17 +29162,26 @@ msgstr "获å–价值æµåˆ†æžæŒç»­æ—¶é—´æ—¶å‡ºé”™ã€‚"
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA 验è¯é”™è¯¯ã€‚请å†æ¬¡éªŒè¯ reCAPTCHA。"
+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 paths are protected for POST requests."
msgstr "这些路径å—POST请求ä¿æŠ¤ã€‚"
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
-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 "They can be managed using the %{link}."
-msgstr "å¯ä»¥ä½¿ç”¨ %{link} 进行托管。"
+msgid "These variables are inherited from the parent group."
+msgstr ""
msgid "Third Party Advisory Link"
msgstr "第三方建议链接"
@@ -28368,8 +29210,8 @@ msgstr "因为 %{reason}无法显示 %{viewer} 。您å¯ä»¥æ”¹ä¸º %{options}。"
msgid "This Cron pattern is invalid"
msgstr "æ­¤Cronæ ¼å¼æ— æ•ˆ"
-msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
-msgstr "æ­¤GitLab实例尚未æ供任何共享Runner。管ç†å‘˜å¯ä»¥åœ¨ç®¡ç†åŒºåŸŸä¸­æ³¨å†Œå…±äº«Runner。"
+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 "该GitLab实例的许å¯ä¸º%{insufficient_license}级别。拥有高级版或更高级别许å¯è¯çš„用户æ‰èƒ½ä½¿ç”¨Geo。"
@@ -28383,23 +29225,35 @@ msgstr "此项目目å‰å·²å­˜æ¡£å¹¶åªè¯»ã€‚如果您想è¦æ¢å¤æ‹‰å–é•œåƒï¼Œ
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr "æ­¤URLå·²ç»ç”¨äºŽå¦ä¸€ä¸ªé“¾æŽ¥ï¼›ä¸å…许é‡å¤ URL"
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 "æ­¤æ“作无法撤消,它将永久删除%{key}SSH密钥"
-msgid "This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
-msgstr "æ­¤æ“作无法撤消。您将丢失该项目的存储库和所有内容:问题,åˆå¹¶è¯·æ±‚等。"
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
+msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr "æ­¤æ“作已执行太多次。ç¨åŽå†è¯•ã€‚"
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
-msgstr "æ­¤æ“作将%{strongOpen}ç«‹å³%{strongClose}%{strongOpen}永久删除%{strongClose}%{codeOpen}%{project}%{codeClose},包括其仓库åŠæ‰€æœ‰å†…容:议题,åˆå¹¶è¯·æ±‚等。"
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
-msgstr "æ­¤æ“作将于%{strongOpen}%{date}%{strongClose}%{strongOpen}永久删除%{strongClose}%{codeOpen}%{project}%{codeClose},包括其仓库åŠæ‰€æœ‰å†…容:议题,åˆå¹¶è¯·æ±‚等。"
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
+msgstr ""
msgid "This also resolves all related threads"
msgstr "这也会åŒæ—¶è§£å†³æ‰€æœ‰ç›¸å…³ä¸»é¢˜"
@@ -28413,14 +29267,17 @@ msgstr "这个应用程åºæ˜¯ç”± %{link_to_owner} 创建的。"
msgid "This application will be able to:"
msgstr "此应用程åºå°†å¯ä»¥ï¼š"
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
-msgstr "该附件已被截断,以é¿å…超过å…许的最大附件大å°15MB。其中已包å«æ€»è®¡%{count}个议题中的%{written_count}个。请考虑选择较å°èŒƒå›´çš„议题é‡æ–°å¯¼å‡ºã€‚"
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
-msgstr "此附件已被截断,以é¿å…超过最大å…许的附件大å°15MB。总计%{issues_count}个议题中的%{written_count}的个议题包å«äºŽå…¶ä¸­ã€‚请考虑选择较少的议题é‡æ–°å¯¼å‡ºã€‚"
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
-msgstr "该附件已被截断,以é¿å…超过å…许的最大附件大å°15MBã€‚å…¶ä¸­å·²åŒ…å« %{merge_requests_count}个议题中的 %{written_count} 个。考虑选择范围更å°çš„问题进行é‡æ–°å¯¼å‡ºã€‚"
+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 "该阻塞为自我引用"
@@ -28497,9 +29354,6 @@ msgstr "此环境的Canary Ingress最近有更新。请ç¨åŽå†è¯•ã€‚"
msgid "This epic already has the maximum number of child epics."
msgstr "æ­¤å²è¯—çš„å­å²è¯—数目已达最大值。"
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr "æ­¤å²è¯—åŠå…¶å­å…ƒç´ åªå¯¹æ‹¥æœ‰æŠ¥å‘Šè€…访问æƒé™æˆ–更高的团队æˆå‘˜å¯è§ã€‚"
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr "æ­¤å²è¯—ä¸å­˜åœ¨æˆ–者您没有足够的æƒé™ã€‚"
@@ -28512,14 +29366,17 @@ msgstr "此功能应与13.0åŽåˆ›å»ºçš„索引一起使用"
msgid "This field is required."
msgstr "该字段是必填字段。"
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr "当å‰ç¾¤ç»„"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr "此群组ä¸èƒ½è¢«é‚€è¯·åˆ°å¼ºåˆ¶SSO的群组中"
-msgid "This group does not provide any group Runners yet."
-msgstr "该群组未æ供任何群组Runner。"
+msgid "This group does not have any group runners yet."
+msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
msgstr "此群组已安排在%{date}永久删除"
@@ -28548,6 +29405,9 @@ msgstr "这是一个将在%{remainingTime}åŽè¿è¡Œçš„延时作业。"
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 security log of important events involving your account."
msgstr "这是一个涉åŠæ‚¨çš„å¸æˆ·é‡è¦äº‹ä»¶çš„安全日志。"
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr "æ­¤åˆå¹¶è¯·æ±‚没有无障ç¢æ€§æ‰«æ报告"
@@ -28680,6 +29543,15 @@ 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 "æ­¤åˆå¹¶è¯·æ±‚å·²é”定。"
@@ -28716,8 +29588,8 @@ msgstr "æ­¤æµæ°´çº¿æ˜¯ç”±å®šæ—¶è®¡åˆ’触å‘çš„."
msgid "This project"
msgstr "当å‰é¡¹ç›®"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
-msgstr "该项目ä¸å±žäºŽä»»ä½•ç¾¤ç»„,因此ä¸èƒ½ä½¿ç”¨ç¾¤ç»„Runner。"
+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 "此项目未å¯ç”¨%{service_desk_link_start}æœåŠ¡å°%{service_desk_link_end}。因此创建议题的用户将ä¸å†æ”¶åˆ°å…³äºŽè®®é¢˜æ›´æ–°çš„电å­é‚®ä»¶é€šçŸ¥ã€‚"
@@ -28773,6 +29645,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "æ­¤Runner仅在å—ä¿æŠ¤åˆ†æ”¯ä¸Šè§¦å‘çš„æµæ°´çº¿ä¸Šè¿è¡Œ"
+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 "当å‰è®¾ç½®å¯åœ¨æ¯ä¸ªé¡¹ç›®ä¸­è¿›è¡Œæ›´æ”¹è¦†ç›–。"
@@ -28806,18 +29681,12 @@ msgstr "该用户在%{name}项目中的角色为%{access}。"
msgid "This user is the author of this %{noteable}."
msgstr "该用户是%{noteable}的作者。"
-msgid "This 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 "This variable can not be masked."
msgstr "æ­¤å˜é‡æ— æ³•è¢«éšè—。"
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr "这将清除数æ®åº“中所有项目仓库的检查状æ€ã€‚æ­¤æ“作无法撤销。确定继续å—?"
-msgid "This will help us personalize your onboarding experience."
-msgstr "这将帮助我们个人化您的å¯ç”¨ä½“验。"
-
msgid "This will redirect you to an external sign in page."
msgstr "这会将您é‡å®šå‘到外部登录页é¢ã€‚"
@@ -29225,6 +30094,9 @@ msgstr "è¦æ·»åŠ ä¸€ä¸ªSSH密钥, 您需è¦%{generate_link_start}生æˆä¸€ä¸ª%{l
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 "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}连接GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹©%{code_open}repo%{code_close}范围,以显示å¯ä¾›è¿žæŽ¥çš„公共和ç§æœ‰çš„仓库列表。"
@@ -29240,6 +30112,9 @@ msgstr "如è¦è¿žæŽ¥SVN仓库,请查看 %{svn_link}。"
msgid "To define internal users, first enable new users set to external"
msgstr "è¦å®šä¹‰å†…部用户,请首先å¯ç”¨è®¾ç½®ä¸ºå¤–部的新用户"
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "为了进一步ä¿æŠ¤æ‚¨çš„å¸æˆ·ï¼Œè¯·è€ƒè™‘é…置一个%{mfa_link_start}åŒé‡èº«ä»½éªŒè¯%{mfa_link_end}方法。"
@@ -29249,6 +30124,9 @@ 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 "首先请在下é¢è¾“入您的FogBugz URL和登录信æ¯ã€‚下一步,您将å¯ä»¥æ˜ å°„用户并选择è¦å¯¼å…¥çš„项目。"
+msgid "To get started, click the link below to confirm your account."
+msgstr ""
+
msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr "首先请将本页é¢ä¸Žæ‚¨çš„ Jaeger æœåŠ¡å™¨è¿žæŽ¥ï¼Œæˆ–者了解一下如何%{link_start_tag}安装 Jaeger%{link_end_tag}"
@@ -29282,6 +30160,9 @@ msgstr "如需外部仓库仅使用CI/CD功能时,请选择%{strong_open}使ç”
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr "请将%{link} 页é¢è¿žæŽ¥åˆ°æ‚¨çš„ Jaeger æœåŠ¡å™¨ï¼Œä»¥ä¾¿åœ¨ GitLab 打开并轻æ¾æŸ¥çœ‹è·Ÿè¸ª"
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr "为了ä¿è¯æ€§èƒ½ï¼Œä»…显示文件中的总计%{strong_open}%{real_size}中的%{display_size}%{strong_close}。"
@@ -29297,8 +30178,8 @@ msgstr "è¦ä»Žæ‰‹åŠ¨é…置的PrometheusæœåŠ¡æŽ¥æ”¶è­¦æŠ¥ï¼Œè¯·å°†ä»¥ä¸‹URLå’ŒæŽ
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 Silver%{linkEnd}. You can also remove the project from the dashboard."
-msgstr "è¦æŸ¥çœ‹æ­¤é¡¹ç›®çš„è¿ç»´è¯¦ç»†ä¿¡æ¯ï¼Œ 需%{linkStart}å‡çº§ç¾¤ç»„计划为银牌计划%{linkEnd}。您也å¯ä»¥ä»Žä»ªè¡¨æ¿ä¸Šåˆ é™¤æ­¤é¡¹ç›®ã€‚"
+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 "è¦æŸ¥çœ‹è¯¥é¡¹ç›®çš„è¿ç»´è¯¦ç»†ä¿¡æ¯ï¼Œè¯·ä¸Ž%{groupName}群组的所有者è”系以å‡çº§è®¢é˜…计划。或者您也å¯ä»¥ä»Žä»ªè¡¨æ¿ä¸Šåˆ é™¤æ­¤é¡¹ç›®ã€‚"
@@ -29315,12 +30196,6 @@ msgstr "为简化计费过程, GitLab将收集用户数,以便利用季度å¯
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 serving your jobs you can add Runners to your group"
-msgstr "è¦å¼€å§‹æ‰§è¡Œä»»åŠ¡ï¼Œè¯·æŠŠRunner加到群组中"
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr "è¦å¼€å§‹ä½¿ç”¨ä½œä¸šï¼Œæ‚¨å¯ä»¥å‘项目添加指定Runner或使用共享Runner"
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr "è‹¥è¦é€€è®¢æ­¤é—®é¢˜ï¼Œè¯·å°†ä»¥ä¸‹é“¾æŽ¥ç²˜è´´åˆ°æ‚¨çš„æµè§ˆå™¨ï¼š"
@@ -29336,9 +30211,6 @@ msgstr "如需查看所有%{scannedResourcesCount}已扫æ网å€ï¼Œ%{linkStart}
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr "è¦æŸ¥çœ‹å®žä¾‹çº§åˆ†æžï¼Œè¯·ç®¡ç†å‘˜æ‰“å¼€%{docLinkStart}使用情况检测%{docLinkEnd}。"
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ª å²è¯—。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的 å²è¯—."
-
msgid "To widen your search, change or remove filters above"
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器"
@@ -29357,6 +30229,9 @@ msgstr "待办事项已æˆåŠŸæ ‡è®°ä¸ºå·²å®Œæˆã€‚"
msgid "Today"
msgstr "今日"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr "切æ¢Markdown预览"
@@ -29384,6 +30259,9 @@ msgstr "切æ¢ä¸‹æ‹‰åˆ—表"
msgid "Toggle emoji award"
msgstr "切æ¢è¡¨æƒ…符å·èµžèµ"
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
@@ -29414,6 +30292,9 @@ msgstr "åˆ‡æ¢ :%{name}: 表情符å·èµžèµã€‚"
msgid "Toggles :%{name}: emoji award."
msgstr "åˆ‡æ¢ :%{name}: 表情符å·èµžèµã€‚"
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr "令牌有效直至被撤销"
@@ -29504,6 +30385,9 @@ 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 "无法将群组转移到其å­ç¾¤ç»„。"
@@ -29559,8 +30443,8 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
-msgstr "创建一个新群组,开始您的GitLab Gold试用。"
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
+msgstr ""
msgid "Trials|Go back to GitLab"
msgstr "返回GitLab"
@@ -29571,8 +30455,8 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr "跳过试用(继续使用å…è´¹å¸æˆ·)"
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
-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 "您å¯ä»¥å°†æ‚¨åœ¨ä¸€ä¸ªæ–°ç¾¤ç»„或一个现有群组上é¢è¿›è¡Œè¯•ç”¨ã€‚"
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 "触å‘集群é‡å»ºç´¢å¼•"
@@ -29631,8 +30518,8 @@ msgstr "触å‘手动作业"
msgid "Trigger pipelines for mirror updates"
msgstr "触å‘é•œåƒæ›´æ–°çš„æµæ°´çº¿"
-msgid "Trigger pipelines when branches or tags are updated from 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 "从上游仓库更新分支或标记时触å‘æµæ°´çº¿ã€‚如上游仓库更新频ç¹ï¼ŒCI Runnerçš„è´Ÿè·å¯èƒ½ä¼šå¤§å¤§å¢žåŠ ã€‚åªæœ‰æ˜Žç¡®CI Runner的处ç†èƒ½åŠ›èƒ½å¤Ÿæ‰¿å—这样的负è·æ—¶ï¼Œæ‰åº”å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
+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 "触å‘器已删除。"
@@ -29658,8 +30545,11 @@ msgstr "触å‘器已æˆåŠŸæ›´æ–°ã€‚"
msgid "Triggerer"
msgstr "触å‘者"
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
-msgstr "触å‘器å¯ä»¥é€šè¿‡API调用使特定的分支或标签被é‡æ–°æž„建,这些token使用与其关è”的用户(包括该用户对项目的访问æƒé™ä»¥åŠé¡¹ç›®çš„æƒé™)的身份"
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
+msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
msgstr "使用跟踪对应用程åºè¿›è¡Œæ•…障排除与监控"
@@ -29874,8 +30764,8 @@ msgstr "当å‰æ— æ³•æ›´æ–°è¿™ä¸ªè®®é¢˜ã€‚"
msgid "Unarchive project"
msgstr "å–消归档项目"
-msgid "Unarchiving the project will restore people's 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}"
-msgstr "å–消项目存档将æ¢å¤ç”¨æˆ·å¯¹å…¶è¿›è¡Œæ›´æ”¹çš„能力。æ交å¯ä»¥è¢«æŽ¨é€åˆ°ä»“库, 并且å¯ä»¥åˆ›å»ºè®®é¢˜ã€è¯„论和其他对象。%{strong_start}项目æ¢å¤åŽ, å°†å¯æ˜¾ç¤ºåœ¨æœç´¢å’Œä»ªè¡¨æ¿ä¸Šã€‚%{strong_end}"
+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 "å–消分é…给评论用户"
@@ -30132,8 +31022,8 @@ msgstr "æ›´æ–°"
msgid "Updating"
msgstr "更新中"
-msgid "Upgrade plan to unlock Canary Deployments feature"
-msgstr "å‡çº§åˆ°å¯ä½¿ç”¨é‡‘ä¸é›€éƒ¨ç½²åŠŸèƒ½çš„方案"
+msgid "Upgrade offers available!"
+msgstr ""
msgid "Upgrade your plan"
msgstr "å‡çº§ä½ çš„计划"
@@ -30153,6 +31043,9 @@ msgstr "å‡çº§æ‚¨çš„计划以å¯ç”¨æ­¤Jira集æˆåŠŸèƒ½ã€‚"
msgid "Upgrade your plan to improve Merge Requests."
msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的åˆå¹¶è¯·æ±‚。"
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr "上传CSV文件"
@@ -30351,12 +31244,18 @@ msgstr ",您命å空间存储上é™æ€»è®¡%{formattedLimit}"
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr "使用 %{code_start}::%{code_end} 创建 %{link_start}有范围标签集%{link_end} (例如 %{code_start}priority::1%{code_end})"
+msgid "Use .gitlab-ci.yml"
+msgstr ""
+
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "在GitLab内部使用æœåŠ¡å°é€šè¿‡ç”µå­é‚®ä»¶ä¸Žç”¨æˆ·è”系(例如æ供客户支æŒï¼‰"
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr "在您的手机或计算机上使用一次密ç éªŒè¯å™¨å¯ç”¨åŒé‡è®¤è¯ (2FA)。"
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr "使用自定义颜色#FF0000"
@@ -30372,8 +31271,11 @@ msgstr "æ¯ä¸ªURIå ä¸€è¡Œ"
msgid "Use template"
msgstr "使用模æ¿"
-msgid "Use the following registration token during setup:"
-msgstr "在安装过程中使用以下注册令牌:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "使用全局通知设置"
@@ -30486,8 +31388,8 @@ msgstr "编辑%{name}"
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 "输入一个逗å·åˆ†éš”的用户ID列表。这些ID应该是设置使用功能标志的系统的用户,而ä¸æ˜¯GitLab ID"
-msgid "UserLists|Feature flag list"
-msgstr "功能标志列表"
+msgid "UserLists|Feature flag user list"
+msgstr ""
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
msgstr "列表å…许您定义一组用于功能标志的用户。 %{linkStart}阅读更多关于功能标志列表的信æ¯ã€‚%{linkEnd}"
@@ -30645,21 +31547,15 @@ msgstr "用户"
msgid "Users in License"
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 over License"
+msgstr ""
msgid "Users requesting access to"
msgstr "请求访问的用户"
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "用户请求访问%{strong_start}%{group_name}%{strong_end}"
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr "价值æµåˆ†æžå¯ä»¥å¸®åŠ©æ‚¨äº†è§£å›¢é˜Ÿçš„效率"
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "价值æµåˆ†æžæ¦‚述了项目从想法到产å“实现的å„阶段所需的时间。"
-msgid "Value Stream Name"
-msgstr "价值æµå称"
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr "我们没有足够的数æ®æ¥æ˜¾ç¤ºæ­¤é˜¶æ®µã€‚"
@@ -30750,6 +31643,15 @@ 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 "容器镜åƒåº“相关设置。"
@@ -30917,6 +31819,9 @@ msgstr "查看性能仪表æ¿äºŽ"
msgid "View users statistics"
msgstr "查看用户统计"
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr "查看æ交"
@@ -31295,6 +32200,12 @@ msgstr "WebAuthnåªæ”¯æŒå¯ç”¨äº†HTTPS的网站。您å¯ä»¥è”系管ç†å‘˜èŽ·å¾
msgid "WebIDE|Merge request"
msgstr "åˆå¹¶è¯·æ±‚"
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr "Webhook"
@@ -31304,6 +32215,9 @@ msgstr "Webhook日志"
msgid "Webhook Settings"
msgstr "Webhook设置"
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr "Webhooks"
@@ -31439,12 +32353,12 @@ msgstr "欢迎回æ¥ï¼æ‚¨çš„å¸æˆ·ä¹‹å‰å› ä¸ºæ²¡æœ‰æ´»åŠ¨è€Œè¢«å†»ç»“,但目
msgid "Welcome to GitLab"
msgstr "欢迎æ¥åˆ°GitLab"
-msgid "Welcome to GitLab%{br_tag}%{name}!"
-msgstr "欢迎使用GitLab%{br_tag}%{name}!"
-
msgid "Welcome to GitLab, %{first_name}!"
msgstr "欢迎使用GitLab,%{first_name}ï¼"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
+msgstr ""
+
msgid "Welcome to the guided GitLab tour"
msgstr "欢迎æ¥åˆ°GitLab导览"
@@ -31460,8 +32374,8 @@ msgstr "什么是压缩?"
msgid "What is your job title? (optional)"
msgstr "您的工作èŒä½æ˜¯ä»€ä¹ˆï¼Ÿ(å¯é€‰)"
-msgid "What's new at GitLab"
-msgstr "GitLab的新功能"
+msgid "What's new"
+msgstr ""
msgid "What’s your experience level?"
msgstr "您的体验水平是多少?"
@@ -31469,8 +32383,8 @@ msgstr "您的体验水平是多少?"
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr "å¯ç”¨KrokiåŽï¼ŒGitLab会将图表å‘é€åˆ°Kroki实例以将其显示为图åƒã€‚您å¯ä»¥ä½¿ç”¨å…费的公有云实例%{kroki_public_url},也å¯ä»¥åœ¨è‡ªå·±çš„基础架构上使用%{install_link}。安装KrokiåŽï¼Œè¯·ç¡®ä¿æ›´æ–°æœåŠ¡å™¨URL以指å‘您的实例。"
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
-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 "当Runner被é”定时,ä¸èƒ½å°†å…¶åˆ†é…给其他项目"
@@ -31490,6 +32404,9 @@ msgstr "该项å¯ç”¨åŽï¼Œç”¨æˆ·åœ¨æŽ¥å—æ¡æ¬¾è¢«å‰å°†ä¸èƒ½ä½¿ç”¨GitLab。"
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] "当åˆå¹¶è¯·æ±‚被接å—æ—¶"
@@ -31497,6 +32414,9 @@ msgstr[0] "当åˆå¹¶è¯·æ±‚被接å—æ—¶"
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 "使用%{code_open}http://%{code_close}或%{code_open}https://%{code_close}å议时,请æ供仓库的实际地å€ã€‚ä¸æ”¯æŒHTTPé‡å®šå‘。"
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr "当:"
@@ -31857,9 +32777,6 @@ msgstr "您正在å°è¯•ä¸Šä¼ éžå›¾ç‰‡æ–‡ä»¶ã€‚请上传.pngã€.jpgã€.jpegã€.g
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 "您正在使用PostgreSQL %{pg_version_current},但此版本的GitLab需è¦PostgreSQL %{pg_version_minimum}。请将您的环境å‡çº§åˆ°æ”¯æŒçš„ PostgreSQL版本,详情请è§%{pg_requirements_url}。"
-msgid "You can %{linkStart}view the blob%{linkEnd} instead."
-msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 代替。"
-
msgid "You can also create a project from the command line."
msgstr "您也å¯ä»¥é€šè¿‡å‘½ä»¤è¡Œæ¥åˆ›å»ºæ–°é¡¹ç›®ã€‚"
@@ -31881,9 +32798,6 @@ msgstr "您还å¯ä»¥æŒ‰ç…§ä»¥ä¸‹è¯´æ˜Žä»Žè®¡ç®—机中上传现有文件。"
msgid "You can always edit this later"
msgstr "您也å¯ä»¥ç¨åŽç¼–辑此选项。"
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr "您å¯ä»¥åˆ›å»ºä¸€ä¸ªæ–°çš„%{link}。"
@@ -31908,9 +32822,6 @@ msgstr "您å¯ä»¥åœ¨ä¸ªäººè®¿é—®ä»¤ç‰Œè®¾ç½®%{pat_link}中创建新的访问令ç
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "您å¯ä»¥è¯·æ±‚加入这些群组,以便为群组项目åšå‡ºè´¡çŒ®ã€‚"
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr "å¯ä»¥è½»æ¾åœ°åœ¨Kubernetes集群上安装Runner。 %{link_to_help_page}"
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr "您å¯ä»¥é€šè¿‡å•å‡»å›¾è¡¨ä¸­çš„列æ¥æŒ‰â€œåˆå¹¶å¤©æ•°â€è¿›è¡Œç­›é€‰ã€‚"
@@ -31932,6 +32843,9 @@ msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜æˆ–å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。
msgid "You can invite a new member to %{project_name}."
msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜åŠ å…¥%{project_name}。"
+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 "您å¯ä»¥é‚€è¯·å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。"
@@ -31947,15 +32861,15 @@ msgstr "您现在å¯ä»¥å…³é—­æ­¤çª—å£ã€‚"
msgid "You can now export your security dashboard to a CSV report."
msgstr "现在你å¯ä»¥å¯¼å‡ºå®‰å…¨ä»ªè¡¨æ¿åˆ°CSV报告。"
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šç¼–辑文件"
@@ -31983,8 +32897,8 @@ msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs}
msgid "You can see your chat accounts."
msgstr "您å¯ä»¥æŸ¥çœ‹æ‚¨çš„èŠå¤©è´¦æˆ·ã€‚"
-msgid "You can set up as many Runners as you need to run your jobs."
-msgstr "您å¯ä»¥æ ¹æ®éœ€è¦è®¾ç½®ä»»æ„æ•°é‡çš„Runner。"
+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 "您å¯ä»¥æŒ‡å®šæ¯ä¸ªç¾¤ç»„或æ¯ä¸ªé¡¹ç›®çš„通知级别。"
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 "您没有足够的æƒé™ä»Žæ­¤é¡¹ç›®ä¸­åˆ é™¤é€šè¯è®¡åˆ’"
@@ -32136,6 +33053,9 @@ msgstr ""
msgid "You have insufficient permissions to update this HTTP integration"
msgstr "您没有足够的æƒé™æ¥æ›´æ–°æ­¤HTTP集æˆ"
+msgid "You have insufficient permissions to view shifts for this rotation"
+msgstr ""
+
msgid "You have no permissions"
msgstr "没有æƒé™"
@@ -32319,6 +33239,9 @@ msgstr "YouTube"
msgid "YouTube URL or ID"
msgstr "YouTube URL或ID"
+msgid "Your %{group} membership will now expire in %{days}."
+msgstr ""
+
msgid "Your %{host} account was signed in to from a new location"
msgstr "您在%{host}上的å¸æˆ·å·²ä»Žä¸€ä¸ªæ–°çš„ä½ç½®ç™»å½•"
@@ -32355,15 +33278,15 @@ msgstr "您的DevOps报告概述了从功能角度使用GitLabçš„æ–¹å¼ã€‚查看
msgid "Your GPG keys (%{count})"
msgstr "您的GPG密钥 (%{count})"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
msgid "Your GitLab account request has been approved!"
msgstr "您的GitLabå¸æˆ·åˆ›å»ºè¯·æ±‚已被批准ï¼"
msgid "Your GitLab group"
msgstr "您的GitLab群组"
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
-msgstr "您的Gitlab金牌试用的有效期为30天,之åŽæ‚¨å¯ä»¥æ°¸ä¹…ä¿ç•™å…费的Gitlabå¸æˆ·ã€‚我们åªéœ€è¦ä¸€äº›å…¶ä»–ä¿¡æ¯å³å¯æ¿€æ´»æ‚¨çš„试用版。"
-
msgid "Your Groups"
msgstr "您的群组"
@@ -32517,6 +33440,9 @@ msgstr "您的许å¯è¯æœ‰æ•ˆæœŸè‡ª"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr "您的许å¯è¯å°†åŒ…å«åœ¨æ‚¨çš„GitLab备份中,且å‡çº§åŽä¾ç„¶æœ‰æ•ˆï¼Œ 所以在正常使用中,您一般ä¸éœ€è¦é‡æ–°ä¸Šä¼ %{code_open}gitlab-license%{code_close}文件。"
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr "您的消æ¯æ˜¾ç¤ºäºŽæ­¤"
@@ -32601,6 +33527,12 @@ msgstr "已删除Zoom会议"
msgid "[No reason]"
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 "已删除的用户"
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr "ä¸èƒ½æ˜¯è¿‡åŽ»çš„日期"
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] "天"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr "默认分支"
@@ -33037,8 +33978,9 @@ msgstr "例如, %{token}"
msgid "element is not a hierarchy"
msgstr "此元素并éžç¾¤ç»„层级"
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr "邮箱“%{email}â€ä¸Žå…许的域 %{email_domains}ä¸åŒ¹é…"
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr "邮箱“%{email}â€è¿˜æœªè¢«éªŒè¯ã€‚"
@@ -33129,6 +34071,9 @@ msgstr "群组"
msgid "group members"
msgstr "群组æˆå‘˜"
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr "群组"
@@ -33371,6 +34316,12 @@ msgstr "请æ¢å¤æ­¤åˆ†æ”¯æˆ–使用其他的 %{missingBranchName} 分支"
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
msgstr "%{link_start}了解更多关于解决冲çª%{link_end}"
+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 "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} ä¸‹é™ %{emphasisEnd},从 %{memoryFrom}MB 到 %{memoryTo}MB"
@@ -33497,9 +34448,6 @@ msgstr "åˆå¹¶"
msgid "mrWidget|Merge failed."
msgstr "åˆå¹¶å¤±è´¥ã€‚"
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr "åˆå¹¶å¤±è´¥: %{mergeError}. 请å†è¯•ä¸€æ¬¡ã€‚"
-
msgid "mrWidget|Merge locally"
msgstr "本地åˆå¹¶"
@@ -33569,8 +34517,8 @@ msgstr "更改未åˆå¹¶åˆ°"
msgid "mrWidget|The changes will be merged into"
msgstr "更改将被åˆå¹¶åˆ°"
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-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 HEAD has recently changed. Please reload the page and review the changes before merging"
msgstr "æºåˆ†æ”¯HEAD最近已更改。请在é‡æ–°åˆå¹¶ä¹‹å‰é‡æ–°åŠ è½½é¡µé¢å¹¶æŸ¥çœ‹æ›´æ”¹"
@@ -33650,6 +34598,9 @@ msgstr "æµæ°´çº¿æˆåŠŸæ—¶è‡ªåŠ¨åˆå¹¶"
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr "æµæ°´çº¿æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr "必须是根命å空间"
@@ -33868,6 +34819,9 @@ msgstr "é‡ç½®å®ƒã€‚"
msgid "revised"
msgstr "已修订"
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr "满足"
@@ -34006,6 +34960,9 @@ msgstr "到列表中"
msgid "toggle collapse"
msgstr "切æ¢æŠ˜å "
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr "已触å‘"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 3b33ba6f497..c09f526216f 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:57\n"
+"PO-Revision-Date: 2021-02-01 17:08\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個已修復測試çµæžœ"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -318,10 +322,10 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -958,15 +968,15 @@ msgstr ""
msgid ", or "
msgstr "或"
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] ""
-msgid "- Runner is active and can process any new jobs"
-msgstr "- 執行器為啟用狀態,並且å¯ä»¥è™•ç†æ–°çš„任何工作。"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- 執行器為暫åœç‹€æ…‹ï¼Œä¸”å°‡ä¸æœƒæŽ¥å—任何新的工作"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1155,6 +1165,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "一個專案æ供了以下功能,存放你的文件(存儲庫),計劃你的工作(è­°é¡Œ),並發布你的文件(維基), %{among_other_things_link}。"
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr ""
-
msgid "A secure token that identifies an external storage request."
msgstr ""
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr ""
msgid "Add a To Do"
msgstr ""
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr ""
@@ -1789,6 +1811,9 @@ msgstr ""
msgid "Admin mode enabled"
msgstr ""
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr ""
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr ""
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr ""
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr ""
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "無法解å°éŽ–已被å°éŽ–çš„ LDAP 使用者"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr ""
@@ -2119,6 +2153,9 @@ msgstr "刪除使用者"
msgid "AdminUsers|Delete user and contributions"
msgstr "刪除使用者åŠå…¶è²¢ç»"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "外部"
@@ -2227,6 +2264,9 @@ msgstr ""
msgid "AdminUsers|User will not be able to login"
msgstr ""
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,7 +2694,7 @@ msgstr ""
msgid "Alerts"
msgstr ""
-msgid "Alerts endpoint"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
@@ -2795,7 +2835,7 @@ 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"
+msgid "Allow public access to pipelines and job details, including output logs and artifacts."
msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr ""
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr ""
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr ""
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3140,6 +3189,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr ""
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,7 +3640,7 @@ 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}"
+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?"
@@ -3679,15 +3728,18 @@ msgstr ""
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 "確定è¦é‡ç½®å¥åº·æª¢æŸ¥ä»¤ç‰Œå—Žï¼Ÿ"
+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 ""
@@ -3757,7 +3809,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr "指派標籤"
@@ -4032,9 +4081,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,7 +4105,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4158,16 +4204,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4308,25 +4354,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr "從é¸å®šçš„變更紀錄開始"
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4335,10 +4381,16 @@ 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 Gold."
+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}."
@@ -4359,6 +4411,9 @@ 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 ""
@@ -4368,6 +4423,9 @@ 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 ""
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4690,6 +4754,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -4834,6 +4916,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr "優é¸"
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr "還原"
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5497,6 +5591,9 @@ 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 ""
@@ -5656,12 +5753,24 @@ 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 ""
@@ -5704,7 +5813,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr "收起å´é‚Šæ¬„"
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr "創建個人訪å•ä»¤ç‰Œ"
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8316,10 +8485,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8346,7 +8515,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,7 +8596,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8641,7 +8807,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,7 +10112,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10184,9 +10404,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "編輯"
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,7 +10761,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,7 +12769,7 @@ msgstr "從創建議題到部署到生產環境"
msgid "From merge request merge until deploy to production"
msgstr "從åˆä½µè«‹æ±‚çš„åˆä½µåˆ°éƒ¨ç½²è‡³ç”Ÿç”¢ç’°å¢ƒ"
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12564,6 +12817,9 @@ msgstr ""
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,7 +13234,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr "已開始維護"
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,7 +15495,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -14897,10 +15537,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -14925,9 +15565,21 @@ msgstr[0] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,7 +16615,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,7 +16907,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr "五月"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr "å·²åˆä½µ"
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18319,9 +19046,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,7 +19505,7 @@ msgstr "新建里程碑"
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -18988,6 +19718,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr "æ“作"
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Pipeline Schedules"
msgstr "æµæ°´ç·šè¨ˆåŠƒ"
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 ""
@@ -20573,9 +21333,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21446,9 +22209,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21731,6 +22491,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr "相關的部署作業"
-
msgid "Related Issues"
msgstr "相關議題"
-msgid "Related Jobs"
-msgstr "相關的作業"
-
-msgid "Related Merge Requests"
-msgstr "相關的åˆä½µè«‹æ±‚"
-
-msgid "Related Merged Requests"
-msgstr "相關已åˆä½µçš„åˆä½µè«‹æ±‚"
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,8 +24641,8 @@ msgstr "é‡ç½®å¥åº·æª¢æŸ¥è¨ªå•ä»¤ç‰Œ"
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
-msgstr "é‡ç½® Runner 註冊令牌"
+msgid "Reset registration token"
+msgstr ""
msgid "Reset template"
msgstr ""
@@ -23985,6 +24764,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,7 +25852,7 @@ msgstr "é¸æ“‡æ™‚å€"
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr "在 Runner 設置時指定以下 URL:"
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr "é‹ä½œ Runner!"
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr "派生關係已被刪除。"
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr "項目生命週期中的å„個階段。"
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "評審階段概述了從創建åˆä½µè«‹æ±‚到åˆä½µçš„時間。當創建第壹個åˆä½µè«‹æ±‚後,數據將自動添加到此處。"
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,16 +29162,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
msgstr ""
-msgid "They can be managed using the %{link}."
+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 "Third Party Advisory Link"
@@ -28368,7 +29210,7 @@ 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."
+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."
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,13 +29366,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 ""
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr "這個專案"
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr ""
msgid "Today"
msgstr "今天"
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,8 +31271,11 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
-msgstr "在安è£éŽç¨‹ä¸­ä½¿ç”¨ä»¥ä¸‹è¨»å†Šä»¤ç‰Œï¼š"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
+msgstr ""
msgid "Use your global notification setting"
msgstr "使用全局通知設置"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 ""
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31497,6 +32414,9 @@ msgstr[0] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr ""
@@ -32319,6 +33239,9 @@ 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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] "天"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33497,9 +34448,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33569,7 +34517,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 787e9b452c2..f6a8b567823 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-01-08 22:59\n"
+"PO-Revision-Date: 2021-02-01 17:04\n"
msgid " %{project_name}#%{issuable_iid} &middot; opened %{issuable_created} by %{author}"
msgstr ""
@@ -174,6 +174,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個確定的測試çµæžœ"
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] ""
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] ""
@@ -318,10 +322,10 @@ msgstr "%{authorsName} 的話題"
msgid "%{board_target} not found"
msgstr ""
-msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
-msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
@@ -661,6 +665,9 @@ msgstr ""
msgid "%{reportType} detected %{totalStart}no%{totalEnd} vulnerabilities."
msgstr ""
+msgid "%{requirementCount} requirements have been selected for export. These will be sent to %{email} as an attachment once finished."
+msgstr ""
+
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr ""
@@ -839,6 +846,9 @@ 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 "%{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 "&lt; 1 hour"
msgstr ""
@@ -958,15 +968,15 @@ msgstr ""
msgid ", or "
msgstr "ã€æˆ– "
+msgid "- Available to run jobs."
+msgstr ""
+
msgid "- Event"
msgid_plural "- Events"
msgstr[0] "- 事件"
-msgid "- Runner is active and can process any new jobs"
-msgstr "- 執行器已啟用,隨時å¯ä»¥è™•ç†æ–°ä½œæ¥­"
-
-msgid "- Runner is paused and will not receive any new jobs"
-msgstr "- 執行器已暫åœï¼Œæš«æ™‚ä¸æœƒæŽ¥å—新的作業"
+msgid "- Not available to run jobs."
+msgstr ""
msgid "- User"
msgid_plural "- Users"
@@ -1155,6 +1165,9 @@ msgstr "無法設定空專案的é è¨­åˆ†æ”¯ã€‚"
msgid "A deleted user"
msgstr "已刪除的使用者"
+msgid "A description is required"
+msgstr ""
+
msgid "A file has been changed."
msgstr ""
@@ -1173,6 +1186,12 @@ 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 maximum of %{count} participants can be added"
msgstr ""
@@ -1224,6 +1243,9 @@ msgstr ""
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
msgstr "專案能讓您存放檔案(版本庫)ã€å®‰æŽ’計畫(議題),åŠç™¼å¸ƒæ–‡ä»¶ (Wiki),%{among_other_things_link}。"
+msgid "A project’s repository name defines its URL (the one you use to access the project via a browser) and its place on the file disk where GitLab is installed. %{link_start}Learn more.%{link_end}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1233,9 +1255,6 @@ msgstr ""
msgid "A rebase is already in progress."
msgstr ""
-msgid "A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
-msgstr "用來在作業記錄中尋找測試覆蓋率輸出的正è¦è¡¨ç¤ºå¼ã€‚空白則åœç”¨"
-
msgid "A secure token that identifies an external storage request."
msgstr "一個用於識別外部儲存請求的安全權æ–。"
@@ -1245,7 +1264,7 @@ msgstr ""
msgid "A string appended to the project path to form the Service Desk email address."
msgstr ""
-msgid "A subscription will 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."
+msgid "A title is required"
msgstr ""
msgid "A user can only participate in a rotation once"
@@ -1260,6 +1279,9 @@ msgstr ""
msgid "API Fuzzing"
msgstr ""
+msgid "API Fuzzing Configuration"
+msgstr ""
+
msgid "API Help"
msgstr ""
@@ -1522,15 +1544,15 @@ msgstr "在管ç†å´é‚Šæ¬„的監控部分加入 Grafana 按鈕,以便存å–é—œ
msgid "Add a To Do"
msgstr "加入待辦事項"
-msgid "Add a To-Do"
-msgstr ""
-
msgid "Add a bullet list"
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 general comment to this %{noteableDisplayName}."
msgstr "加入一般留言至 %{noteableDisplayName}。"
@@ -1789,6 +1811,9 @@ msgstr "管ç†å“¡æ¨¡å¼å·²åœç”¨"
msgid "Admin mode enabled"
msgstr "管ç†å“¡æ¨¡å¼å·²å•Ÿç”¨"
+msgid "Admin navigation"
+msgstr ""
+
msgid "Admin notes"
msgstr "管ç†å“¡å‚™è¨»"
@@ -1819,9 +1844,6 @@ msgstr ""
msgid "AdminArea|Features"
msgstr ""
-msgid "AdminArea|Groups: %{number_of_groups}"
-msgstr ""
-
msgid "AdminArea|Guest"
msgstr ""
@@ -1855,7 +1877,7 @@ msgstr ""
msgid "AdminArea|Owner"
msgstr ""
-msgid "AdminArea|Projects: %{number_of_projects}"
+msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
@@ -1879,6 +1901,9 @@ msgstr ""
msgid "AdminArea|User cap"
msgstr ""
+msgid "AdminArea|Users"
+msgstr ""
+
msgid "AdminArea|Users statistics"
msgstr ""
@@ -1888,7 +1913,13 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
-msgid "AdminArea|Users: %{number_of_users}"
+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."
@@ -1918,9 +1949,6 @@ msgstr "Auto DevOps 網域"
msgid "AdminSettings|Disable feed token"
msgstr ""
-msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
-msgstr ""
-
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "啟用新專案的共享執行器"
@@ -1942,6 +1970,9 @@ msgstr ""
msgid "AdminSettings|No required pipeline"
msgstr "沒有強制性的æµæ°´ç·š"
+msgid "AdminSettings|PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
msgid "AdminSettings|Required pipeline configuration"
msgstr "強制æµæ°´ç·šè¨­å®š"
@@ -2092,6 +2123,9 @@ msgstr ""
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "無法解除å°éŽ– LDAP å°éŽ–的使用者"
+msgid "AdminUsers|Cohorts"
+msgstr ""
+
msgid "AdminUsers|Deactivate"
msgstr "å‡çµ"
@@ -2119,6 +2153,9 @@ msgstr "刪除使用者"
msgid "AdminUsers|Delete user and contributions"
msgstr "刪除使用者åŠç›¸é—œè²¢ç»"
+msgid "AdminUsers|Export permissions as CSV"
+msgstr ""
+
msgid "AdminUsers|External"
msgstr "外部"
@@ -2227,6 +2264,9 @@ msgstr "ä½¿ç”¨è€…å°‡ç„¡æ³•å­˜å– git 版本庫"
msgid "AdminUsers|User will not be able to login"
msgstr "使用者將無法登入"
+msgid "AdminUsers|Users"
+msgstr ""
+
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
msgstr ""
@@ -2654,8 +2694,8 @@ msgstr ""
msgid "Alerts"
msgstr "警示"
-msgid "Alerts endpoint"
-msgstr "警示端點"
+msgid "Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead."
+msgstr ""
msgid "AlertsIntegrations|Alerts will be created through this integration"
msgstr ""
@@ -2795,8 +2835,8 @@ 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 public access to pipelines and job details, including output logs and artifacts."
+msgstr ""
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr "å…許在 Asciidoc 文件中繪製 PlantUML 圖。"
@@ -2846,6 +2886,9 @@ msgstr ""
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "åªå…許頂層群組使用電å­éƒµä»¶ç¶²åŸŸé™åˆ¶"
+msgid "Allowed to create:"
+msgstr ""
+
msgid "Allowed to fail"
msgstr "å…許失敗"
@@ -2897,6 +2940,9 @@ 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 ""
@@ -2924,6 +2970,9 @@ msgstr "發生錯誤"
msgid "An error occured while saving changes: %{error}"
msgstr ""
+msgid "An error occured while updating the notification settings. Please try again."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr "å‘話題加入è‰ç¨¿æ™‚發生錯誤。"
@@ -3140,6 +3189,9 @@ msgstr "載入檔案時發生錯誤。"
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
+msgid "An error occurred while loading the members, please try again."
+msgstr ""
+
msgid "An error occurred while loading the merge request changes."
msgstr "載入åˆä½µè«‹æ±‚的變更內容時發生錯誤。"
@@ -3311,6 +3363,9 @@ msgstr ""
msgid "Ancestors"
msgstr ""
+msgid "And this registration token:"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -3425,12 +3480,6 @@ msgstr ""
msgid "Apply suggestion"
msgstr ""
-msgid "Apply suggestion commit message"
-msgstr ""
-
-msgid "Apply suggestion on %{fileName}"
-msgstr ""
-
msgid "Apply suggestions"
msgstr ""
@@ -3591,8 +3640,8 @@ 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}"
-msgstr "歸檔專案將使其完全唯讀。儀表æ¿ä¸­å’Œæœå°‹çµæžœä¸­éƒ½ä¸æœƒå‡ºç¾è©²å°ˆæ¡ˆã€‚%{strong_start}程å¼ç¢¼å°‡ç„¡æ³•æ交到版本庫,也無法建立任何議題ã€ç•™è¨€ç­‰å…¶ä»–。%{strong_end}"
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end} %{link_start}Learn more.%{link_end}"
+msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
@@ -3679,15 +3728,18 @@ msgstr "您確定è¦ç§»é™¤é€™å€‹èº«ä»½è­˜åˆ¥å—Žï¼Ÿ"
msgid "Are you sure you want to remove this list?"
msgstr ""
-msgid "Are you sure you want to reset registration token?"
-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 ""
+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 ""
@@ -3757,7 +3809,7 @@ msgstr ""
msgid "Ascending"
msgstr ""
-msgid "Ask your group maintainer to set up a group Runner."
+msgid "Ask your group maintainer to set up a group runner."
msgstr ""
msgid "Assertion consumer service URL"
@@ -3781,9 +3833,6 @@ msgstr ""
msgid "Assign custom color like #FF0000"
msgstr ""
-msgid "Assign epic"
-msgstr ""
-
msgid "Assign labels"
msgstr ""
@@ -4032,9 +4081,6 @@ msgstr ""
msgid "Authorize %{user} to use your account?"
msgstr ""
-msgid "Authorize external services to send alerts to GitLab"
-msgstr ""
-
msgid "Authorized %{new_chat_name}"
msgstr ""
@@ -4059,7 +4105,7 @@ msgstr ""
msgid "Auto stop successfully canceled."
msgstr ""
-msgid "Auto-cancel redundant, pending pipelines"
+msgid "Auto-cancel redundant pipelines"
msgstr ""
msgid "Auto-close referenced issues on default branch"
@@ -4158,16 +4204,16 @@ msgstr ""
msgid "Available ID"
msgstr ""
-msgid "Available Runners: %{runners}"
+msgid "Available for dependency and container scanning"
msgstr ""
-msgid "Available for dependency and container scanning"
+msgid "Available group runners: %{runners}"
msgstr ""
-msgid "Available group Runners: %{runners}"
+msgid "Available runners: %{runners}"
msgstr ""
-msgid "Available shared Runners:"
+msgid "Available shared runners:"
msgstr ""
msgid "Available specific runners"
@@ -4308,25 +4354,25 @@ msgstr ""
msgid "Begin with the selected commit"
msgstr ""
-msgid "Below are examples of regex for existing tools:"
-msgstr ""
-
msgid "Below are the fingerprints for the current instance SSH host keys."
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:"
+msgid "Billable Users"
msgstr ""
msgid "Billing"
msgstr ""
-msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
@@ -4335,10 +4381,16 @@ 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 Gold."
+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}."
@@ -4359,6 +4411,9 @@ 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 ""
@@ -4368,6 +4423,9 @@ 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 ""
@@ -4383,6 +4441,9 @@ msgstr ""
msgid "BillingPlan|Upgrade"
msgstr ""
+msgid "BillingPlan|Upgrade for free"
+msgstr ""
+
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -4468,10 +4529,10 @@ msgstr ""
msgid "Boards|An error occurred while creating the list. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching issues. Please reload the page."
+msgid "Boards|An error occurred while fetching group projects. Please try again."
msgstr ""
-msgid "Boards|An error occurred while fetching labels. Please reload the page."
+msgid "Boards|An error occurred while fetching issues. Please reload the page."
msgstr ""
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
@@ -4495,6 +4556,9 @@ msgstr ""
msgid "Boards|An error occurred while updating the list. Please try again."
msgstr ""
+msgid "Boards|Board"
+msgstr ""
+
msgid "Boards|Collapse"
msgstr ""
@@ -4690,6 +4754,9 @@ msgstr ""
msgid "Branches|protected"
msgstr ""
+msgid "Breadcrumbs"
+msgstr ""
+
msgid "Brief title about the change"
msgstr ""
@@ -4729,16 +4796,25 @@ msgstr ""
msgid "Bulk request concurrency"
msgstr ""
+msgid "Bulk update"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
-msgid "BulkImport|Importing groups from %{link}"
+msgid "BulkImport|Importing the group failed"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|No groups available for import"
+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|To new group"
@@ -4789,6 +4865,9 @@ 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 clicking Register, I agree that I have read and accepted the %{company_name} %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
msgstr ""
@@ -4798,6 +4877,9 @@ msgstr ""
msgid "By default, all projects and groups will use the global notifications setting."
msgstr ""
+msgid "By default, if any ref (branch, tag, or commit) on the remote mirror has diverged from the local repository, the entire push will fail, and nothing will be updated. Choose this option to override this behavior. After the mirror is created, this can only be modified via the API."
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "作者:"
@@ -4834,6 +4916,9 @@ msgstr ""
msgid "CI/CD configuration"
msgstr ""
+msgid "CI/CD configuration file"
+msgstr ""
+
msgid "CI/CD for external repo"
msgstr ""
@@ -4942,9 +5027,6 @@ msgstr ""
msgid "Canary"
msgstr ""
-msgid "Canary Deployments is a popular CI strategy, where a small portion of the fleet is updated to the new version of your application."
-msgstr ""
-
msgid "Canary Ingress does not exist in the environment."
msgstr ""
@@ -5095,6 +5177,12 @@ msgstr ""
msgid "Change permissions"
msgstr ""
+msgid "Change reviewer(s)"
+msgstr ""
+
+msgid "Change reviewer(s)."
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -5137,6 +5225,9 @@ msgstr ""
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr ""
+
msgid "ChangeTypeAction|Revert"
msgstr ""
@@ -5161,6 +5252,9 @@ msgstr ""
msgid "Changed assignee(s)."
msgstr ""
+msgid "Changed reviewer(s)."
+msgstr ""
+
msgid "Changed the title to \"%{title_param}\"."
msgstr ""
@@ -5263,6 +5357,9 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
+msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
+msgstr ""
+
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5476,9 +5573,6 @@ msgstr ""
msgid "Choose any color. Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
-
msgid "Choose file…"
msgstr ""
@@ -5497,6 +5591,9 @@ 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 ""
@@ -5656,12 +5753,24 @@ 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 ""
@@ -5704,7 +5813,7 @@ msgstr ""
msgid "Click %{link_to} to view the request."
msgstr ""
-msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgid "Click the button below."
msgstr ""
msgid "Click to expand it."
@@ -6883,7 +6992,7 @@ 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 master %{start_date} - %{end_date}"
+msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
msgid "Code owner approval is required"
@@ -6901,9 +7010,6 @@ msgstr ""
msgid "CodeOwner|Pattern"
msgstr ""
-msgid "Cohorts"
-msgstr ""
-
msgid "Cohorts|Inactive users"
msgstr ""
@@ -6940,6 +7046,9 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Collapses this file (only for you) until it’s changed again."
+msgstr ""
+
msgid "Collector hostname"
msgstr ""
@@ -7160,6 +7269,12 @@ msgstr ""
msgid "ComplianceFrameworks|There are no compliance frameworks set up yet"
msgstr ""
+msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
+msgstr ""
+
+msgid "ComplianceFrameworks|Use %{codeStart}::%{codeEnd} to create a %{linkStart}scoped set%{linkEnd} (eg. %{codeStart}SOX::AWS%{codeEnd})"
+msgstr ""
+
msgid "ComplianceFramework|GDPR"
msgstr ""
@@ -7334,9 +7449,6 @@ msgstr ""
msgid "Contact Sales to upgrade"
msgstr ""
-msgid "Contact sales to upgrade"
-msgstr ""
-
msgid "Contact support"
msgstr ""
@@ -7444,9 +7556,15 @@ msgstr ""
msgid "ContainerRegistry|Copy push command"
msgstr ""
+msgid "ContainerRegistry|Delete image repository?"
+msgstr ""
+
msgid "ContainerRegistry|Delete selected"
msgstr ""
+msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone."
+msgstr ""
+
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
msgstr ""
@@ -7474,6 +7592,15 @@ msgstr ""
msgid "ContainerRegistry|Image Repositories"
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 tags"
msgstr ""
@@ -7565,6 +7692,9 @@ 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 ""
@@ -7592,9 +7722,15 @@ 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 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 ""
@@ -7610,9 +7746,15 @@ 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 ""
@@ -7790,6 +7932,9 @@ msgstr ""
msgid "Copy commit SHA"
msgstr ""
+msgid "Copy email address"
+msgstr ""
+
msgid "Copy environment"
msgstr ""
@@ -7844,6 +7989,9 @@ msgstr ""
msgid "Copy value"
msgstr ""
+msgid "CorpusManagement|Fuzz testing corpus management"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
@@ -8142,12 +8290,24 @@ msgstr ""
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
+msgid "CreateValueStreamForm|'%{name}' Value Stream created"
+msgstr ""
+
+msgid "CreateValueStreamForm|Add another stage"
+msgstr ""
+
msgid "CreateValueStreamForm|Add stage"
msgstr ""
msgid "CreateValueStreamForm|All default stages are currently visible"
msgstr ""
+msgid "CreateValueStreamForm|Create from default template"
+msgstr ""
+
+msgid "CreateValueStreamForm|Create from no template"
+msgstr ""
+
msgid "CreateValueStreamForm|Default stages"
msgstr ""
@@ -8163,16 +8323,13 @@ msgstr ""
msgid "CreateValueStreamForm|End event: "
msgstr ""
-msgid "CreateValueStreamForm|Enter a name for the stage"
-msgstr ""
-
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
-msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
+msgid "CreateValueStreamForm|Enter value stream name"
msgstr ""
-msgid "CreateValueStreamForm|Name"
+msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
msgstr ""
msgid "CreateValueStreamForm|Name is required"
@@ -8184,9 +8341,15 @@ 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 ""
@@ -8202,6 +8365,9 @@ msgstr ""
msgid "CreateValueStreamForm|Stage name already exists"
msgstr ""
+msgid "CreateValueStreamForm|Stage name is required"
+msgstr ""
+
msgid "CreateValueStreamForm|Start event"
msgstr ""
@@ -8217,6 +8383,9 @@ msgstr ""
msgid "CreateValueStreamForm|Update stage"
msgstr ""
+msgid "CreateValueStreamForm|Value Stream name"
+msgstr ""
+
msgid "Created"
msgstr ""
@@ -8316,10 +8485,10 @@ msgstr ""
msgid "Current Branch"
msgstr ""
-msgid "Current Plan"
+msgid "Current Project"
msgstr ""
-msgid "Current Project"
+msgid "Current forks will keep their visibility level."
msgstr ""
msgid "Current node"
@@ -8346,7 +8515,7 @@ msgstr ""
msgid "CurrentUser|Settings"
msgstr ""
-msgid "CurrentUser|Start a Gold trial"
+msgid "CurrentUser|Start an Ultimate trial"
msgstr ""
msgid "CurrentUser|Upgrade"
@@ -8355,9 +8524,6 @@ msgstr ""
msgid "Custom Attributes"
msgstr ""
-msgid "Custom CI configuration path"
-msgstr ""
-
msgid "Custom Git clone URL for HTTP(S)"
msgstr ""
@@ -8430,7 +8596,7 @@ msgstr ""
msgid "Customize name"
msgstr ""
-msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgid "Customize your pipeline configuration and coverage report."
msgstr ""
msgid "Customize your pipeline configuration."
@@ -8641,7 +8807,7 @@ 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 Silver plan."
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
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."
@@ -8671,6 +8837,12 @@ 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 ""
@@ -8683,6 +8855,9 @@ 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 ""
@@ -8695,6 +8870,9 @@ msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|DAST Scan"
+msgstr ""
+
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -8710,6 +8888,9 @@ msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Edit profile"
+msgstr ""
+
msgid "DastProfiles|Edit scanner profile"
msgstr ""
@@ -8734,7 +8915,7 @@ msgstr ""
msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
-msgid "DastProfiles|Manage Profiles"
+msgid "DastProfiles|Manage DAST scans"
msgstr ""
msgid "DastProfiles|Manage profiles"
@@ -8746,9 +8927,6 @@ msgstr ""
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New Profile"
-msgstr ""
-
msgid "DastProfiles|New scanner profile"
msgstr ""
@@ -8788,6 +8966,12 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Saved Scans"
+msgstr ""
+
+msgid "DastProfiles|Scan"
+msgstr ""
+
msgid "DastProfiles|Scan mode"
msgstr ""
@@ -8797,6 +8981,9 @@ msgstr ""
msgid "DastProfiles|Scanner Profiles"
msgstr ""
+msgid "DastProfiles|Scanner name"
+msgstr ""
+
msgid "DastProfiles|Show debug messages"
msgstr ""
@@ -8806,9 +8993,15 @@ msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site name"
+msgstr ""
+
msgid "DastProfiles|Spider timeout"
msgstr ""
+msgid "DastProfiles|Target"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
@@ -8824,6 +9017,9 @@ msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
msgstr ""
+msgid "DastProfiles|URL"
+msgstr ""
+
msgid "DastProfiles|Username"
msgstr ""
@@ -8833,6 +9029,9 @@ msgstr ""
msgid "DastProfiles|Validated"
msgstr ""
+msgid "DastProfiles|Validation status"
+msgstr ""
+
msgid "DastSiteValidation|Copy HTTP header to clipboard"
msgstr ""
@@ -8845,6 +9044,9 @@ msgstr ""
msgid "DastSiteValidation|Header validation"
msgstr ""
+msgid "DastSiteValidation|Retry validation"
+msgstr ""
+
msgid "DastSiteValidation|Step 1 - Choose site validation method"
msgstr ""
@@ -9139,7 +9341,7 @@ 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, merge requests etc."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests, etc."
msgstr ""
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
@@ -9481,6 +9683,33 @@ msgstr ""
msgid "Deployment Frequency"
msgstr ""
+msgid "DeploymentFrequencyCharts|Date"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments charts"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last month (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for last week (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Deployments to production for the last 90 days (%{startDate} - %{endDate})"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|Something went wrong while getting deployment frequency data"
+msgstr ""
+
+msgid "DeploymentFrequencyCharts|These charts display the frequency of deployments to the production environment, as part of the DORA 4 metrics. The environment must be named %{codeStart}production%{codeEnd} for its data to appear in these charts."
+msgstr ""
+
+msgid "Deployments"
+msgstr ""
+
msgid "Deployment|API"
msgstr ""
@@ -9664,7 +9893,7 @@ 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 admin enable hashed storage. %{requirements_link_start}More information%{requirements_link_end}"
+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"
@@ -9715,25 +9944,25 @@ msgstr ""
msgid "DevopsAdoptionSegment|The maximum number of selections has been reached"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} group selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} group selected"
msgstr ""
-msgid "DevopsAdoption|%{selectedCount} groups selected (20 max)"
+msgid "DevopsAdoption|%{selectedCount} groups selected"
msgstr ""
-msgid "DevopsAdoption|Add a segment to get started"
+msgid "DevopsAdoption|Add Group"
msgstr ""
-msgid "DevopsAdoption|Add new segment"
+msgid "DevopsAdoption|Add a group to get started"
msgstr ""
msgid "DevopsAdoption|Adopted"
msgstr ""
-msgid "DevopsAdoption|An error occured while deleting the segment. Please try again."
+msgid "DevopsAdoption|An error occured while deleting the group. Please try again."
msgstr ""
-msgid "DevopsAdoption|An error occured while saving the segment. Please try again."
+msgid "DevopsAdoption|An error occured while saving the group. Please try again."
msgstr ""
msgid "DevopsAdoption|Approvals"
@@ -9760,22 +9989,19 @@ msgstr ""
msgid "DevopsAdoption|At least 1 security scan of any type run in pipeline"
msgstr ""
-msgid "DevopsAdoption|Confirm delete segment"
-msgstr ""
-
-msgid "DevopsAdoption|Create new segment"
+msgid "DevopsAdoption|Confirm delete Group"
msgstr ""
-msgid "DevopsAdoption|Delete segment"
+msgid "DevopsAdoption|Delete Group"
msgstr ""
msgid "DevopsAdoption|Deploys"
msgstr ""
-msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
+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 segment"
+msgid "DevopsAdoption|Edit Group"
msgstr ""
msgid "DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}."
@@ -9784,24 +10010,24 @@ msgstr ""
msgid "DevopsAdoption|Filter by name"
msgstr ""
+msgid "DevopsAdoption|Group data pending until the start of next month"
+msgstr ""
+
msgid "DevopsAdoption|Issues"
msgstr ""
msgid "DevopsAdoption|MRs"
msgstr ""
-msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
+msgid "DevopsAdoption|Maximum %{maxSegments} groups allowed"
msgstr ""
-msgid "DevopsAdoption|My segment"
+msgid "DevopsAdoption|My group"
msgstr ""
msgid "DevopsAdoption|Name"
msgstr ""
-msgid "DevopsAdoption|New segment"
-msgstr ""
-
msgid "DevopsAdoption|No filter results."
msgstr ""
@@ -9823,18 +10049,12 @@ msgstr ""
msgid "DevopsAdoption|Scanning"
msgstr ""
-msgid "DevopsAdoption|Segment"
-msgstr ""
-
-msgid "DevopsAdoption|Segment data pending until the start of next month"
+msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page to try again."
msgstr ""
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page to try again."
msgstr ""
-msgid "DevopsAdoption|There was an error fetching Segments. Please refresh the page to try again."
-msgstr ""
-
msgid "DevopsReport|Adoption"
msgstr ""
@@ -9892,7 +10112,7 @@ msgstr ""
msgid "Disable for this project"
msgstr ""
-msgid "Disable group Runners"
+msgid "Disable group runners"
msgstr ""
msgid "Disable public access to Pages sites"
@@ -10184,9 +10404,6 @@ msgstr ""
msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
-msgid "Each Runner can be in one of the following states:"
-msgstr ""
-
msgid "Edit"
msgstr "編輯"
@@ -10415,6 +10632,15 @@ 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 "EmailToken|reset it"
msgstr ""
@@ -10481,6 +10707,9 @@ msgstr ""
msgid "Enable Incident Management inbound alert limit"
msgstr ""
+msgid "Enable Invisible Captcha during sign up"
+msgstr ""
+
msgid "Enable Kroki"
msgstr ""
@@ -10490,6 +10719,9 @@ msgstr ""
msgid "Enable Pseudonymizer data collection"
msgstr ""
+msgid "Enable SSL verification"
+msgstr ""
+
msgid "Enable Seat Link"
msgstr ""
@@ -10529,7 +10761,7 @@ msgstr ""
msgid "Enable for this project"
msgstr ""
-msgid "Enable group Runners"
+msgid "Enable group runners"
msgstr ""
msgid "Enable header and footer in emails"
@@ -10568,7 +10800,7 @@ msgstr ""
msgid "Enable proxy"
msgstr ""
-msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgid "Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
msgstr ""
msgid "Enable shared runners"
@@ -10631,15 +10863,21 @@ msgstr ""
msgid "End Time"
msgstr ""
-msgid "Ends at %{endsAt}"
+msgid "Ends at (UTC)"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Ends on"
+msgstr ""
+
+msgid "Ends: %{endsAt}"
msgstr ""
msgid "Enforce DNS rebinding attack protection"
msgstr ""
+msgid "Enforce SSH key expiration"
+msgstr ""
+
msgid "Enforce personal access token expiration"
msgstr ""
@@ -10736,13 +10974,10 @@ msgstr ""
msgid "Environment scope"
msgstr ""
-msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
-
-msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+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"
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
msgstr ""
msgid "Environment:"
@@ -11033,6 +11268,9 @@ 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 ""
@@ -11048,6 +11286,12 @@ msgstr ""
msgid "Epics|Remove issue"
msgstr ""
+msgid "Epics|Search epics"
+msgstr ""
+
+msgid "Epics|Select epic"
+msgstr ""
+
msgid "Epics|Show more"
msgstr ""
@@ -11438,9 +11682,6 @@ msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr ""
-msgid "Example: My Value Stream"
-msgstr ""
-
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr ""
@@ -11576,15 +11817,21 @@ msgstr ""
msgid "Export project"
msgstr ""
+msgid "Export requirements"
+msgstr ""
+
msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
msgstr ""
-msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+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 Classification Policy Authorization"
msgstr ""
@@ -11708,6 +11955,9 @@ msgstr ""
msgid "Failed to find import label for Jira import."
msgstr ""
+msgid "Failed to generate report, please try again after sometime"
+msgstr ""
+
msgid "Failed to get ref."
msgstr ""
@@ -11891,9 +12141,6 @@ msgstr ""
msgid "Fast-forward merge without a merge commit"
msgstr ""
-msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -12408,10 +12655,22 @@ 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 help setting up the Service Desk for your instance, please contact an administrator."
msgstr ""
-msgid "For internal projects, any logged in user except external users can view pipelines and access job details (output logs and artifacts)"
+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 more info, read the documentation."
@@ -12435,12 +12694,6 @@ msgstr ""
msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
msgstr ""
-msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
msgid "Forgot your password?"
msgstr ""
@@ -12516,7 +12769,7 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
-msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgid "From the Kubernetes cluster details view, applications list, install GitLab Runner."
msgstr ""
msgid "Full name"
@@ -12564,6 +12817,9 @@ msgstr "Geo"
msgid "Geo Nodes"
msgstr ""
+msgid "Geo Nodes Beta"
+msgstr ""
+
msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
msgstr ""
@@ -12978,7 +13234,7 @@ msgstr ""
msgid "Git shallow clone"
msgstr ""
-msgid "Git strategy for pipelines"
+msgid "Git strategy"
msgstr ""
msgid "Git transfer in progress"
@@ -13008,9 +13264,6 @@ msgstr ""
msgid "GitLab Billing Team."
msgstr ""
-msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
-
msgid "GitLab Import"
msgstr ""
@@ -13047,6 +13300,9 @@ msgstr ""
msgid "GitLab for Slack"
msgstr ""
+msgid "GitLab group: %{source_link}"
+msgstr ""
+
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
msgstr ""
@@ -13131,9 +13387,6 @@ msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr ""
-msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
-msgstr ""
-
msgid "GitLabPages|Learn more."
msgstr ""
@@ -13161,6 +13414,9 @@ msgstr ""
msgid "GitLabPages|Save"
msgstr ""
+msgid "GitLabPages|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 follow a %{samples_link_start}sample project%{link_end} or use a %{templates_link_start}GitLab CI template%{link_end}."
+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 ""
@@ -13434,9 +13690,6 @@ msgstr ""
msgid "Group Audit Events"
msgstr ""
-msgid "Group CI/CD settings"
-msgstr ""
-
msgid "Group Git LFS status:"
msgstr ""
@@ -13452,9 +13705,6 @@ msgstr ""
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr ""
-msgid "Group Runners"
-msgstr ""
-
msgid "Group SAML must be enabled to test"
msgstr ""
@@ -13506,6 +13756,12 @@ msgstr ""
msgid "Group members"
msgstr ""
+msgid "Group membership expiration date changed"
+msgstr ""
+
+msgid "Group membership expiration date removed"
+msgstr ""
+
msgid "Group milestone"
msgstr ""
@@ -13515,6 +13771,9 @@ msgstr ""
msgid "Group name (your organization)"
msgstr ""
+msgid "Group navigation"
+msgstr ""
+
msgid "Group overview"
msgstr ""
@@ -13539,6 +13798,12 @@ msgstr ""
msgid "Group requires separate account"
msgstr ""
+msgid "Group runners"
+msgstr ""
+
+msgid "Group runners can be managed with the %{link}."
+msgstr ""
+
msgid "Group variables (inherited)"
msgstr ""
@@ -13938,9 +14203,6 @@ msgstr ""
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
msgstr ""
-msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "GroupsDropdown|Frequently visited"
msgstr ""
@@ -14007,6 +14269,9 @@ msgstr ""
msgid "GroupsNew|No import options available"
msgstr ""
+msgid "GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature."
+msgstr ""
+
msgid "GroupsNew|Personal access token"
msgstr ""
@@ -14243,6 +14508,12 @@ msgstr ""
msgid "Housekeeping, export, path, transfer, remove, archive."
msgstr ""
+msgid "How do I configure runners?"
+msgstr ""
+
+msgid "How do I mirror repositories?"
+msgstr ""
+
msgid "How does cleanup work?"
msgstr ""
@@ -14354,9 +14625,6 @@ msgstr ""
msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
msgstr ""
-msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
-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 ""
@@ -14372,18 +14640,15 @@ msgstr ""
msgid "If disabled, only admins will be able to configure repository mirroring."
msgstr ""
-msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
-
-msgid "If enabled"
-msgstr ""
-
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{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 ""
+
msgid "If the YouTube URL is https://www.youtube.com/watch?v=0t1DgySidms then the video ID is %{id}"
msgstr ""
@@ -14627,15 +14892,360 @@ msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+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 order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In progress"
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|*GitLab*, noun: a synonym for efficient teams"
+msgstr ""
+
+msgid "InProductMarketing|...and you can get a free trial of GitLab Gold"
+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|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|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Gold and enable these features in less than 5 minutes with no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
+msgstr ""
+
+msgid "InProductMarketing|Create your first project!"
+msgstr ""
+
+msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
+msgstr ""
+
+msgid "InProductMarketing|Dig in and create a project and a repo"
+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|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|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 Gold 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 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|Go for the gold!"
+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 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|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|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|Our tool brings all the things together"
+msgstr ""
+
+msgid "InProductMarketing|Rapid development, simplified"
+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|Start a GitLab Gold trial today in less than one minute, no credit card required."
+msgstr ""
+
+msgid "InProductMarketing|Start a free trial of GitLab Gold – no CC 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 Gold free trial"
+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 your first steps with GitLab"
+msgstr ""
+
+msgid "InProductMarketing|Take your source code management to the next level"
+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 %{series} of 3 in the %{track} series."
+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 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 Gold for free"
+msgstr ""
+
+msgid "InProductMarketing|Try it out"
+msgstr ""
+
+msgid "InProductMarketing|Try it yourself"
+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|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 Gold and your teams will be on it from day one."
+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|using a CI/CD template"
+msgstr ""
+
+msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Incident"
msgstr ""
@@ -14771,9 +15381,39 @@ 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 ""
@@ -14855,7 +15495,7 @@ msgstr ""
msgid "Input host keys manually"
msgstr ""
-msgid "Input your repository URL"
+msgid "Input the remote repository URL"
msgstr ""
msgid "Insert a code block"
@@ -14897,10 +15537,10 @@ msgstr ""
msgid "Install"
msgstr ""
-msgid "Install GitLab Runner"
+msgid "Install GitLab Runner and ensure it's running."
msgstr ""
-msgid "Install Runner on Kubernetes"
+msgid "Install GitLab Runner on Kubernetes"
msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
@@ -14925,9 +15565,21 @@ msgstr[0] ""
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 overview"
+msgstr ""
+
msgid "InstanceStatistics|Could not load the issues and merge requests chart. Please refresh the page to try again."
msgstr ""
@@ -15033,6 +15685,9 @@ msgstr ""
msgid "Integrations|%{integration} settings saved, but not active."
msgstr ""
+msgid "Integrations|Add namespace"
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -15063,6 +15718,12 @@ msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Failed to link namespace. Please try again."
+msgstr ""
+
+msgid "Integrations|Failed to load namespaces. Please try again."
+msgstr ""
+
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
@@ -15072,12 +15733,18 @@ msgstr ""
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
msgstr ""
+msgid "Integrations|Link namespaces"
+msgstr ""
+
msgid "Integrations|Linked namespaces"
msgstr ""
msgid "Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance."
msgstr ""
+msgid "Integrations|No available namespaces."
+msgstr ""
+
msgid "Integrations|Projects using custom settings will not be affected."
msgstr ""
@@ -15102,6 +15769,9 @@ msgstr ""
msgid "Integrations|Search Jira issues"
msgstr ""
+msgid "Integrations|Sign in to add namespaces"
+msgstr ""
+
msgid "Integrations|Standard"
msgstr ""
@@ -15129,6 +15799,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -15216,6 +15889,9 @@ msgstr ""
msgid "Invalid login or password"
msgstr ""
+msgid "Invalid period"
+msgstr ""
+
msgid "Invalid pin code"
msgstr ""
@@ -15276,6 +15952,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invite members"
+msgstr ""
+
msgid "Invite team members"
msgstr ""
@@ -15531,6 +16210,12 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
+msgid "IssueBoards|An error occurred while assigning the selected epic to the issue."
+msgstr ""
+
+msgid "IssueBoards|An error occurred while fetching the assigned epic of the selected issue."
+msgstr ""
+
msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
msgstr ""
@@ -15585,9 +16270,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues referenced by merge requests and commits within the default branch will be closed automatically"
-msgstr ""
-
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
msgstr ""
@@ -15627,6 +16309,9 @@ 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 ""
@@ -15729,24 +16414,42 @@ msgstr ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
+msgid "JiraService|An error occured while fetching issue list"
+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|Events for %{noteable_model_name} are disabled."
msgstr ""
+msgid "JiraService|Fetch issue types for this Jira project"
+msgstr ""
+
msgid "JiraService|For example, 12, 24"
msgstr ""
+msgid "JiraService|GitLab for Jira Configuration"
+msgstr ""
+
msgid "JiraService|If different from Web URL"
msgstr ""
msgid "JiraService|Issue List"
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 ""
@@ -15762,6 +16465,9 @@ msgstr ""
msgid "JiraService|Jira issue tracker"
msgstr ""
+msgid "JiraService|Jira issue type"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -15774,9 +16480,21 @@ 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 transition IDs for Jira workflow transitions. %{link_start}Learn more%{link_end}"
msgstr ""
+msgid "JiraService|Sign in to GitLab.com to get started."
+msgstr ""
+
msgid "JiraService|This feature requires a Premium plan."
msgstr ""
@@ -15855,6 +16573,9 @@ 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|Are you sure you want to proceed?"
msgstr ""
@@ -15894,7 +16615,7 @@ msgstr ""
msgid "Job|Job has been erased"
msgstr ""
-msgid "Job|Job has been erased by"
+msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Keep"
@@ -15969,6 +16690,9 @@ msgstr ""
msgid "K8s pod health"
msgstr ""
+msgid "Keep artifacts from most recent successful jobs"
+msgstr ""
+
msgid "Keep divergent refs"
msgstr ""
@@ -15996,6 +16720,9 @@ msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
+msgid "KeyboardShortcuts|Toggle GitLab Next"
+msgstr ""
+
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
@@ -16180,7 +16907,7 @@ msgstr ""
msgid "Last edited %{date}"
msgstr ""
-msgid "Last edited by %{name}"
+msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
msgstr ""
msgid "Last item before this page loaded in your browser:"
@@ -16264,7 +16991,7 @@ msgstr ""
msgid "Learn GitLab"
msgstr ""
-msgid "Learn GitLab - Gold trial"
+msgid "Learn GitLab - Ultimate trial"
msgstr ""
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
@@ -16285,9 +17012,6 @@ msgstr ""
msgid "Learn more about Auto DevOps"
msgstr ""
-msgid "Learn more about Kubernetes"
-msgstr ""
-
msgid "Learn more about License-Check"
msgstr ""
@@ -16580,6 +17304,9 @@ msgstr[0] ""
msgid "Line changes"
msgstr ""
+msgid "Link"
+msgstr ""
+
msgid "Link Prometheus monitoring to GitLab."
msgstr ""
@@ -16754,9 +17481,6 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MERGED (REVERTED)"
-msgstr ""
-
msgid "MR widget|Back to the Merge request"
msgstr ""
@@ -16781,6 +17505,12 @@ 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 ""
@@ -16805,9 +17535,6 @@ msgstr ""
msgid "Make sure you save it - you won't be able to access it again."
msgstr ""
-msgid "Make this epic confidential"
-msgstr ""
-
msgid "Makes this issue confidential."
msgstr ""
@@ -16850,6 +17577,9 @@ msgstr ""
msgid "Manage your license"
msgstr ""
+msgid "Manage your project's triggers"
+msgstr ""
+
msgid "Managed Account"
msgstr ""
@@ -17042,12 +17772,15 @@ msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
-msgid "Maximum Users:"
+msgid "Maximum Users"
msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum artifacts size"
+msgstr ""
+
msgid "Maximum artifacts size (MB)"
msgstr ""
@@ -17087,9 +17820,6 @@ msgstr ""
msgid "Maximum job timeout has a value which could not be accepted"
msgstr ""
-msgid "Maximum length 100 characters"
-msgstr ""
-
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr ""
@@ -17132,6 +17862,9 @@ msgstr ""
msgid "May"
msgstr "5月"
+msgid "Mean time to merge"
+msgstr ""
+
msgid "Measured in bytes of code. Excludes generated and vendored code."
msgstr ""
@@ -17159,9 +17892,6 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
-msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members invited to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -17180,9 +17910,6 @@ msgstr ""
msgid "Members of a group may only view projects they have permission to access"
msgstr ""
-msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Members|%{time} by %{user}"
msgstr ""
@@ -17279,6 +18006,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
+msgid "Members|Search groups"
+msgstr ""
+
msgid "Members|Search invited"
msgstr ""
@@ -17372,6 +18102,9 @@ msgstr ""
msgid "Merge request dependencies"
msgstr ""
+msgid "Merge request events"
+msgstr ""
+
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -17453,9 +18186,6 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
-msgid "MergeRequests|Jump to next unresolved thread"
-msgstr ""
-
msgid "MergeRequests|Reply..."
msgstr ""
@@ -17522,15 +18252,9 @@ msgstr ""
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
-msgid "MergeRequest|reverted"
-msgstr ""
-
msgid "Merged"
msgstr ""
-msgid "Merged (%{reverted})"
-msgstr ""
-
msgid "Merged MRs"
msgstr ""
@@ -17928,6 +18652,9 @@ msgstr ""
msgid "Migrated %{success_count}/%{total_count} files."
msgstr ""
+msgid "Migration has been scheduled to be retried"
+msgstr ""
+
msgid "Migration successful."
msgstr ""
@@ -18097,6 +18824,9 @@ msgstr ""
msgid "Mirror direction"
msgstr ""
+msgid "Mirror only protected branches"
+msgstr ""
+
msgid "Mirror repository"
msgstr ""
@@ -18148,9 +18878,6 @@ msgstr ""
msgid "ModalButton|Add projects"
msgstr ""
-msgid "Modal|Cancel"
-msgstr ""
-
msgid "Modal|Close"
msgstr ""
@@ -18319,9 +19046,6 @@ msgstr ""
msgid "Name has already been taken"
msgstr ""
-msgid "Name is required"
-msgstr ""
-
msgid "Name new label"
msgstr ""
@@ -18453,12 +19177,6 @@ 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 ""
@@ -18477,6 +19195,12 @@ msgstr ""
msgid "NetworkPolicies|Delete policy: %{policy}"
msgstr ""
+msgid "NetworkPolicies|Deny all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Deny all traffic"
msgstr ""
@@ -18531,6 +19255,9 @@ msgstr ""
msgid "NetworkPolicies|None selected"
msgstr ""
+msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -18778,7 +19505,7 @@ msgstr ""
msgid "New password"
msgstr ""
-msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgid "New pipelines cause older pending pipelines on the same branch to be cancelled."
msgstr ""
msgid "New project"
@@ -18895,6 +19622,9 @@ msgstr ""
msgid "No commits present here"
msgstr ""
+msgid "No compliance frameworks are in use. Create one using the GraphQL API."
+msgstr ""
+
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr ""
@@ -18988,6 +19718,9 @@ msgstr ""
msgid "No matching results for \"%{query}\""
msgstr ""
+msgid "No matching results..."
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -19063,9 +19796,6 @@ msgstr ""
msgid "No start date"
msgstr ""
-msgid "No status"
-msgstr ""
-
msgid "No template"
msgstr ""
@@ -19075,6 +19805,9 @@ msgstr ""
msgid "No test coverage"
msgstr ""
+msgid "No triggers exist yet. Use the form above to create one."
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -19450,6 +20183,9 @@ msgstr ""
msgid "OnCallSchedules|Edit schedule"
msgstr ""
+msgid "OnCallSchedules|Enable end date"
+msgstr ""
+
msgid "OnCallSchedules|Failed to add rotation"
msgstr ""
@@ -19459,12 +20195,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
+msgid "OnCallSchedules|For this rotation, on-call will be:"
+msgstr ""
+
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
+msgid "OnCallSchedules|Restrict to time intervals"
+msgstr ""
+
msgid "OnCallSchedules|Rotation length"
msgstr ""
@@ -19525,10 +20267,10 @@ msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
-msgid "OnDemandScans|Create a new scanner profile"
+msgid "OnDemandScans|Create new scanner profile"
msgstr ""
-msgid "OnDemandScans|Create a new site profile"
+msgid "OnDemandScans|Create new site profile"
msgstr ""
msgid "OnDemandScans|Description (optional)"
@@ -19540,9 +20282,18 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Manage DAST scans"
+msgstr ""
+
msgid "OnDemandScans|Manage profiles"
msgstr ""
+msgid "OnDemandScans|Manage scanner profiles"
+msgstr ""
+
+msgid "OnDemandScans|Manage site profiles"
+msgstr ""
+
msgid "OnDemandScans|My daily scan"
msgstr ""
@@ -19594,10 +20345,10 @@ msgstr ""
msgid "OnDemandScans|You cannot run an active scan against an unvalidated site."
msgstr ""
-msgid "Once 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."
+msgid "Once 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 "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues, merge requests etc."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -19634,7 +20385,7 @@ 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 / Silver and above can see Value Stream Analytics."
+msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
msgid "Only 1 appearances row can exist"
@@ -19652,9 +20403,6 @@ msgstr ""
msgid "Only admins can delete project"
msgstr ""
-msgid "Only mirror protected branches"
-msgstr ""
-
msgid "Only policy:"
msgstr ""
@@ -19673,7 +20421,7 @@ 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 / Silver and above can see Productivity Analytics."
+msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
msgid "Oops, are you sure?"
@@ -19781,15 +20529,15 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
-msgid "Origin"
-msgstr ""
-
msgid "Orphaned member"
msgstr ""
msgid "Other Labels"
msgstr ""
+msgid "Other available runners"
+msgstr ""
+
msgid "Other information"
msgstr ""
@@ -19964,9 +20712,6 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
-msgid "PackageRegistry|Filter by name"
-msgstr ""
-
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
msgstr ""
@@ -19985,6 +20730,9 @@ msgstr ""
msgid "PackageRegistry|Generic"
msgstr ""
+msgid "PackageRegistry|GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package formats. %{linkStart}More Information%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@@ -20057,9 +20805,6 @@ msgstr ""
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
-msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
-
msgid "PackageRegistry|There are no other versions of this package."
msgstr ""
@@ -20075,6 +20820,9 @@ 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 ""
@@ -20213,6 +20961,9 @@ msgstr ""
msgid "Participants"
msgstr ""
+msgid "Pass job variables"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -20327,6 +21078,9 @@ msgstr ""
msgid "PerformanceBar|Elasticsearch calls"
msgstr ""
+msgid "PerformanceBar|External Http calls"
+msgstr ""
+
msgid "PerformanceBar|Frontend resources"
msgstr ""
@@ -20393,6 +21147,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
+msgid "Pipeline cannot be run."
+msgstr ""
+
msgid "Pipeline minutes quota"
msgstr ""
@@ -20405,6 +21162,9 @@ 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 ""
@@ -20573,9 +21333,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No CI file found in this repository, please add one."
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -20588,9 +21345,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset."
msgstr ""
-msgid "Pipelines|Repository does not have a default branch, please set one."
-msgstr ""
-
msgid "Pipelines|Revoke"
msgstr ""
@@ -20612,6 +21366,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines."
msgstr ""
+msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
+msgstr ""
+
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
@@ -20726,6 +21483,9 @@ msgstr ""
msgid "Pipeline|Run for"
msgstr ""
+msgid "Pipeline|Run for branch name or tag"
+msgstr ""
+
msgid "Pipeline|Running"
msgstr ""
@@ -21395,12 +22155,15 @@ msgstr ""
msgid "Profiles|Full name"
msgstr ""
-msgid "Profiles|GitLab is unable to verify your identity automatically."
+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."
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 ""
@@ -21446,9 +22209,6 @@ msgstr ""
msgid "Profiles|Path"
msgstr ""
-msgid "Profiles|Please email %{data_request} to begin the account deletion process."
-msgstr ""
-
msgid "Profiles|Position and size your new avatar"
msgstr ""
@@ -21731,6 +22491,9 @@ msgstr ""
msgid "Project name suffix"
msgstr ""
+msgid "Project navigation"
+msgstr ""
+
msgid "Project order will not be saved as local storage is not available."
msgstr ""
@@ -22148,6 +22911,9 @@ 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|What are badges?"
msgstr ""
@@ -22271,7 +23037,7 @@ msgstr ""
msgid "Projects to index"
msgstr ""
-msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
msgid "Projects will be permanently deleted immediately."
@@ -22646,6 +23412,9 @@ msgstr ""
msgid "Protect"
msgstr ""
+msgid "Protect a tag"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -22694,6 +23463,9 @@ msgstr ""
msgid "ProtectedBranch|Branch"
msgstr ""
+msgid "ProtectedBranch|Branch:"
+msgstr ""
+
msgid "ProtectedBranch|Code owner approval"
msgstr ""
@@ -22730,6 +23502,9 @@ msgstr ""
msgid "ProtectedEnvironment|Environment"
msgstr ""
+msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -22739,9 +23514,6 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
-msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
-msgstr ""
-
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
@@ -22751,7 +23523,7 @@ msgstr ""
msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
msgstr ""
-msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
@@ -22970,6 +23742,9 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Reauthenticating with SAML provider."
+msgstr ""
+
msgid "Rebase"
msgstr ""
@@ -23082,12 +23857,21 @@ msgstr ""
msgid "Register WebAuthn Device"
msgstr ""
+msgid "Register a runner on a Kubernetes cluster. %{link_to_help_page}"
+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 ""
@@ -23115,21 +23899,9 @@ msgstr ""
msgid "Rejected (closed)"
msgstr ""
-msgid "Related Deployed Jobs"
-msgstr ""
-
msgid "Related Issues"
msgstr ""
-msgid "Related Jobs"
-msgstr ""
-
-msgid "Related Merge Requests"
-msgstr ""
-
-msgid "Related Merged Requests"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -23224,9 +23996,6 @@ msgstr ""
msgid "Remove %{displayReference}"
msgstr ""
-msgid "Remove Runner"
-msgstr ""
-
msgid "Remove Zoom meeting"
msgstr ""
@@ -23320,6 +24089,9 @@ msgstr ""
msgid "Remove reviewer"
msgstr ""
+msgid "Remove runner"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -23565,6 +24337,10 @@ 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] ""
+
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] ""
@@ -23731,6 +24507,9 @@ msgstr ""
msgid "Repository synchronization concurrency limit"
msgstr ""
+msgid "Repository update events"
+msgstr ""
+
msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
@@ -23862,7 +24641,7 @@ msgstr ""
msgid "Reset key"
msgstr ""
-msgid "Reset runners registration token"
+msgid "Reset registration token"
msgstr ""
msgid "Reset template"
@@ -23985,6 +24764,9 @@ msgstr ""
msgid "Retry job"
msgstr ""
+msgid "Retry migration"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -24031,6 +24813,9 @@ 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 ""
@@ -24071,6 +24856,9 @@ msgstr ""
msgid "Revoked project access token %{project_access_token_name}!"
msgstr ""
+msgid "RightSidebar|Issue email: %{copyText}"
+msgstr ""
+
msgid "RightSidebar|adding a"
msgstr ""
@@ -24116,6 +24904,9 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner API"
+msgstr ""
+
msgid "Runner is %{status}, last contact was %{runner_contact} ago"
msgstr ""
@@ -24137,21 +24928,9 @@ msgstr ""
msgid "Runners"
msgstr ""
-msgid "Runners API"
-msgstr ""
-
-msgid "Runners activated for this project"
-msgstr ""
-
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
msgstr ""
-msgid "Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project."
-msgstr ""
-
-msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
-
msgid "Runners can be:"
msgstr ""
@@ -24164,21 +24943,36 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|An error has occurred fetching instructions"
+msgstr ""
+
msgid "Runners|Architecture"
msgstr ""
msgid "Runners|Can run untagged jobs"
msgstr ""
+msgid "Runners|Copy instructions"
+msgstr ""
+
msgid "Runners|Description"
msgstr ""
+msgid "Runners|Download Latest Binary"
+msgstr ""
+
+msgid "Runners|Download and Install Binary"
+msgstr ""
+
msgid "Runners|Group"
msgstr ""
msgid "Runners|IP Address"
msgstr ""
+msgid "Runners|Install a Runner"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -24200,24 +24994,39 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Register Runner"
+msgstr ""
+
msgid "Runners|Revision"
msgstr ""
msgid "Runners|Shared"
msgstr ""
+msgid "Runners|Show Runner installation instructions"
+msgstr ""
+
msgid "Runners|Specific"
msgstr ""
msgid "Runners|Tags"
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|Value"
msgstr ""
msgid "Runners|Version"
msgstr ""
+msgid "Runners|View installation instructions"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -24290,6 +25099,9 @@ msgstr ""
msgid "SSL Verification:"
msgstr ""
+msgid "SSL verification"
+msgstr ""
+
msgid "Satisfied"
msgstr ""
@@ -24625,6 +25437,9 @@ msgstr ""
msgid "Secret Detection"
msgstr ""
+msgid "Secret Token"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -24640,6 +25455,9 @@ 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 ""
@@ -24799,9 +25617,6 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
@@ -24865,9 +25680,6 @@ msgstr ""
msgid "SecurityReports|Security scans have run"
msgstr ""
-msgid "SecurityReports|Security scans have run. Go to the %{linkStart}pipelines tab%{linkEnd} to download the security reports"
-msgstr ""
-
msgid "SecurityReports|Select a project to add by using the project search field above."
msgstr ""
@@ -24974,13 +25786,13 @@ msgstr ""
msgid "See the affected projects in the GitLab admin panel"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Remediation details."
+msgid "See the list of available commands in Slack after setting up this service by entering"
msgstr ""
-msgid "See vulnerability %{vulnerability_link} for any Solution details."
+msgid "See vulnerability %{vulnerability_link} for any Remediation details."
msgstr ""
-msgid "See what's new at GitLab"
+msgid "See vulnerability %{vulnerability_link} for any Solution details."
msgstr ""
msgid "Select"
@@ -25040,7 +25852,7 @@ msgstr ""
msgid "Select all"
msgstr ""
-msgid "Select an existing Kubernetes cluster or create a new one"
+msgid "Select an existing Kubernetes cluster or create a new one."
msgstr ""
msgid "Select assignee"
@@ -25070,6 +25882,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
+msgid "Select iteration"
+msgstr ""
+
msgid "Select label"
msgstr ""
@@ -25127,9 +25942,6 @@ msgstr ""
msgid "Select target branch"
msgstr ""
-msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
-msgstr ""
-
msgid "Select the custom project template source group."
msgstr ""
@@ -25412,6 +26224,9 @@ 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 each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
msgstr ""
@@ -25451,10 +26266,10 @@ msgstr ""
msgid "Set up Jira Integration"
msgstr ""
-msgid "Set up a %{type} Runner automatically"
+msgid "Set up a %{type} runner automatically"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "Set up a %{type} runner manually"
msgstr ""
msgid "Set up a hardware device as a second factor to sign in."
@@ -25469,9 +26284,6 @@ msgstr ""
msgid "Set up new password"
msgstr ""
-msgid "Set up pipeline subscriptions for this project."
-msgstr ""
-
msgid "Set up shared runner availability"
msgstr ""
@@ -25616,9 +26428,6 @@ msgstr ""
msgid "Sherlock Transactions"
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 %{b_start}will%{b_end} lose access to your account."
-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 ""
@@ -25673,6 +26482,9 @@ msgstr ""
msgid "Show latest version"
msgstr ""
+msgid "Show links anyways"
+msgstr ""
+
msgid "Show list"
msgstr ""
@@ -25909,9 +26721,6 @@ msgstr ""
msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
msgstr ""
-msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
-msgstr ""
-
msgid "Smartcard"
msgstr ""
@@ -26056,6 +26865,9 @@ 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 %{listType} list"
msgstr ""
@@ -26422,7 +27234,7 @@ msgstr ""
msgid "Spam log successfully submitted as ham."
msgstr ""
-msgid "Specific Runners"
+msgid "Specific runners"
msgstr ""
msgid "Specified URL cannot be used: \"%{reason}\""
@@ -26431,9 +27243,6 @@ msgstr ""
msgid "Specify an e-mail address regex pattern to identify default internal users."
msgstr ""
-msgid "Specify the following URL during the Runner setup:"
-msgstr ""
-
msgid "Speed up your pipelines with Needs relationships"
msgstr ""
@@ -26452,9 +27261,6 @@ msgstr ""
msgid "Stage"
msgstr ""
-msgid "Stage & Commit"
-msgstr ""
-
msgid "Stage data updated"
msgstr ""
@@ -26509,7 +27315,7 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
-msgid "Start a Free Gold Trial"
+msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion..."
@@ -26542,9 +27348,6 @@ msgstr ""
msgid "Start search"
msgstr ""
-msgid "Start the Runner!"
-msgstr ""
-
msgid "Start thread"
msgstr ""
@@ -26554,7 +27357,7 @@ msgstr ""
msgid "Start thread & reopen %{noteable_name}"
msgstr ""
-msgid "Start your Free Gold Trial"
+msgid "Start your Free Ultimate Trial"
msgstr ""
msgid "Start your free trial"
@@ -26581,15 +27384,15 @@ msgstr ""
msgid "Starts %{startsIn}"
msgstr ""
-msgid "Starts at %{startsAt}"
-msgstr ""
-
msgid "Starts at (UTC)"
msgstr ""
msgid "Starts on"
msgstr ""
+msgid "Starts: %{startsAt}"
+msgstr ""
+
msgid "State your message to activate"
msgstr ""
@@ -26767,6 +27570,9 @@ msgstr ""
msgid "Subgroup milestone"
msgstr ""
+msgid "Subgroup navigation"
+msgstr ""
+
msgid "Subgroup overview"
msgstr ""
@@ -27178,6 +27984,9 @@ msgstr ""
msgid "System hook was successfully updated."
msgstr ""
+msgid "System hook will be triggered on set of events like creating project or adding ssh key. But you can also enable extra triggers like Push events."
+msgstr ""
+
msgid "System metrics (Custom)"
msgstr ""
@@ -27202,9 +28011,15 @@ 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 ""
@@ -27375,15 +28190,18 @@ msgstr[0] ""
msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
-msgid "Terraform|A Terraform report failed to generate."
+msgid "Terraform|A report failed to generate."
msgstr ""
-msgid "Terraform|A Terraform report was generated in your pipelines."
+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 ""
@@ -27438,10 +28256,10 @@ msgstr ""
msgid "Terraform|States"
msgstr ""
-msgid "Terraform|The Terraform report %{name} failed to generate."
+msgid "Terraform|The report %{name} failed to generate."
msgstr ""
-msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgid "Terraform|The report %{name} was generated in your pipelines."
msgstr ""
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
@@ -27768,9 +28586,6 @@ msgstr[0] ""
msgid "The fork relationship has been removed."
msgstr ""
-msgid "The form contains the following error:"
-msgstr ""
-
msgid "The form contains the following errors:"
msgstr ""
@@ -27825,6 +28640,9 @@ 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 license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
msgstr ""
@@ -27843,6 +28661,15 @@ msgstr ""
msgid "The maximum file size allowed is %{size}."
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 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 ""
@@ -27858,7 +28685,10 @@ msgstr ""
msgid "The name \"%{name}\" is already taken in this directory."
msgstr ""
-msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+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 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."
@@ -27876,9 +28706,6 @@ msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
-msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
-
msgid "The phase of the development lifecycle."
msgstr ""
@@ -27924,6 +28751,9 @@ msgstr ""
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
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 took to long to complete."
msgstr ""
@@ -27951,9 +28781,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The roadmap shows the progress of your epics along a timeline"
-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 ""
@@ -28008,7 +28835,7 @@ 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 an approval"
+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"
@@ -28116,7 +28943,7 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
-msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgid "There is a halted Elasticsearch migration"
msgstr ""
msgid "There is already a To-Do for this design."
@@ -28164,6 +28991,9 @@ msgstr ""
msgid "There was a problem fetching project users."
msgstr ""
+msgid "There was a problem fetching the keep latest artifact setting."
+msgstr ""
+
msgid "There was a problem fetching users."
msgstr ""
@@ -28176,6 +29006,9 @@ msgstr ""
msgid "There was a problem sending the confirmation email"
msgstr ""
+msgid "There was a problem updating the keep latest artifact setting."
+msgstr ""
+
msgid "There was an error %{message} todo."
msgstr ""
@@ -28329,16 +29162,25 @@ msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
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 paths are protected for POST requests."
msgstr ""
-msgid "These variables are configured in the parent group settings, and will be active in the current project in addition to the project variables."
+msgid "These runners are shared across projects in this group."
+msgstr ""
+
+msgid "These runners are shared across this GitLab instance."
msgstr ""
-msgid "They can be managed using the %{link}."
+msgid "These runners are specific to this project."
+msgstr ""
+
+msgid "These variables are inherited from the parent group."
msgstr ""
msgid "Third Party Advisory Link"
@@ -28368,7 +29210,7 @@ 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."
+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."
@@ -28383,22 +29225,34 @@ msgstr ""
msgid "This URL is already used for another link; duplicate URLs are not allowed"
msgstr ""
+msgid "This URL will be triggered for each branch updated to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "This URL will be triggered when repository is updated"
+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 cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This action has been performed too many times. Try again later."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}immediately%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
-msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
+msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all related resources, including issues, merge requests, etc."
msgstr ""
msgid "This also resolves all related threads"
@@ -28413,13 +29267,16 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
-msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+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"
@@ -28497,9 +29354,6 @@ msgstr ""
msgid "This epic already has the maximum number of child epics."
msgstr ""
-msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
-msgstr ""
-
msgid "This epic does not exist or you don't have sufficient permission."
msgstr ""
@@ -28512,13 +29366,16 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This graph has a large number of jobs and showing the links between them may have performance implications."
+msgstr ""
+
msgid "This group"
msgstr ""
msgid "This group cannot be invited to a project inside a group with enforced SSO"
msgstr ""
-msgid "This group does not provide any group Runners yet."
+msgid "This group does not have any group runners yet."
msgstr ""
msgid "This group has been scheduled for permanent removal on %{date}"
@@ -28548,6 +29405,9 @@ 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 security log of important events involving your account."
msgstr ""
@@ -28671,6 +29531,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 cannot be rebased while there are conflicts."
+msgstr ""
+
msgid "This merge request does not have accessibility reports"
msgstr ""
@@ -28680,6 +29543,15 @@ 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 ""
@@ -28716,7 +29588,7 @@ msgstr ""
msgid "This project"
msgstr ""
-msgid "This project does not belong to a group and can therefore not make use of group Runners."
+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."
@@ -28773,6 +29645,9 @@ 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 ""
@@ -28806,18 +29681,12 @@ msgstr ""
msgid "This user is the author of this %{noteable}."
msgstr ""
-msgid "This 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 "This variable can not be masked."
msgstr ""
msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
msgstr ""
-msgid "This will help us personalize your onboarding experience."
-msgstr ""
-
msgid "This will redirect you to an external sign in page."
msgstr ""
@@ -29225,6 +30094,9 @@ 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 ""
@@ -29240,6 +30112,9 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}."
+msgstr ""
+
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -29249,6 +30124,9 @@ 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, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
@@ -29282,6 +30160,9 @@ msgstr ""
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr ""
+msgid "To personalize your GitLab experience, we'd like to know a bit more about you. We won't share this information with anyone."
+msgstr ""
+
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
msgstr ""
@@ -29297,7 +30178,7 @@ 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 Silver%{linkEnd}. You can also remove the project from the dashboard."
+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."
@@ -29315,12 +30196,6 @@ 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 serving your jobs you can add Runners to your group"
-msgstr ""
-
-msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
-msgstr ""
-
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
@@ -29336,9 +30211,6 @@ msgstr ""
msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
-msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
-msgstr ""
-
msgid "To widen your search, change or remove filters above"
msgstr ""
@@ -29357,6 +30229,9 @@ msgstr ""
msgid "Today"
msgstr ""
+msgid "Toggle GitLab Next"
+msgstr ""
+
msgid "Toggle Markdown preview"
msgstr ""
@@ -29384,6 +30259,9 @@ msgstr ""
msgid "Toggle emoji award"
msgstr ""
+msgid "Toggle focus mode"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -29414,6 +30292,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token"
+msgstr ""
+
msgid "Token valid until revoked"
msgstr ""
@@ -29504,6 +30385,9 @@ 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 ""
@@ -29559,7 +30443,7 @@ msgid "Trials|%{plan} Trial %{en_dash} %{num} day left"
msgid_plural "Trials|%{plan} Trial %{en_dash} %{num} days left"
msgstr[0] ""
-msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Go back to GitLab"
@@ -29571,7 +30455,7 @@ msgstr ""
msgid "Trials|Skip Trial (Continue with Free Account)"
msgstr ""
-msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+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."
@@ -29598,7 +30482,7 @@ msgstr ""
msgid "Trial|Dismiss"
msgstr ""
-msgid "Trial|GitLab Gold trial (optional)"
+msgid "Trial|GitLab Ultimate trial (optional)"
msgstr ""
msgid "Trial|How many employees will use Gitlab?"
@@ -29613,7 +30497,7 @@ msgstr ""
msgid "Trial|Telephone number"
msgstr ""
-msgid "Trial|Upgrade to Gold to keep using GitLab with advanced features."
+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:"
@@ -29622,6 +30506,9 @@ 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 ""
@@ -29631,7 +30518,7 @@ msgstr ""
msgid "Trigger pipelines for mirror updates"
msgstr ""
-msgid "Trigger pipelines when branches or tags are updated from 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."
+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."
@@ -29658,7 +30545,10 @@ msgstr ""
msgid "Triggerer"
msgstr ""
-msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgid "Triggers|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 "Triggers|To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
msgstr ""
msgid "Troubleshoot and monitor your application with tracing"
@@ -29874,7 +30764,7 @@ msgstr ""
msgid "Unarchive project"
msgstr ""
-msgid "Unarchiving the project will restore people's 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}"
+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"
@@ -30132,7 +31022,7 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Upgrade plan to unlock Canary Deployments feature"
+msgid "Upgrade offers available!"
msgstr ""
msgid "Upgrade your plan"
@@ -30153,6 +31043,9 @@ msgstr ""
msgid "Upgrade your plan to improve Merge Requests."
msgstr ""
+msgid "Upload"
+msgstr ""
+
msgid "Upload CSV file"
msgstr ""
@@ -30351,12 +31244,18 @@ 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 Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
msgstr ""
+msgid "Use cURL"
+msgstr ""
+
msgid "Use custom color #FF0000"
msgstr ""
@@ -30372,7 +31271,10 @@ msgstr ""
msgid "Use template"
msgstr ""
-msgid "Use the following registration token during setup:"
+msgid "Use this token to validate received payloads"
+msgstr ""
+
+msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
@@ -30486,7 +31388,7 @@ 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 list"
+msgid "UserLists|Feature flag user list"
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}"
@@ -30645,21 +31547,15 @@ msgstr ""
msgid "Users in License"
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:"
+msgid "Users over License"
msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Users requesting access to %{strong_start}%{project_name}%{strong_end}"
msgstr ""
@@ -30723,9 +31619,6 @@ msgstr ""
msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
-msgid "Value Stream Name"
-msgstr ""
-
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""
@@ -30750,6 +31643,15 @@ 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 ""
@@ -30917,6 +31819,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
+msgid "Viewed"
+msgstr ""
+
msgid "Viewing commit"
msgstr ""
@@ -31295,6 +32200,12 @@ msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
+msgid "WebIDE|You need permission to edit files directly in this project."
+msgstr ""
+
+msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
+msgstr ""
+
msgid "Webhook"
msgstr ""
@@ -31304,6 +32215,9 @@ msgstr ""
msgid "Webhook Settings"
msgstr ""
+msgid "Webhook:"
+msgstr ""
+
msgid "Webhooks"
msgstr ""
@@ -31439,10 +32353,10 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -31460,7 +32374,7 @@ msgstr ""
msgid "What is your job title? (optional)"
msgstr ""
-msgid "What's new at GitLab"
+msgid "What's new"
msgstr ""
msgid "What’s your experience level?"
@@ -31469,7 +32383,7 @@ msgstr ""
msgid "When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you've installed Kroki, make sure to update the server URL to point to your instance."
msgstr ""
-msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+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"
@@ -31490,6 +32404,9 @@ msgstr ""
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 ""
+
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -31497,6 +32414,9 @@ msgstr[0] ""
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 using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
msgid "When:"
msgstr ""
@@ -31857,9 +32777,6 @@ 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 %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
-
msgid "You can also create a project from the command line."
msgstr ""
@@ -31881,9 +32798,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can configure jobs to use runners that are assigned specific tags. Separate tags with commas."
-msgstr ""
-
msgid "You can create a new %{link}."
msgstr ""
@@ -31908,9 +32822,6 @@ msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
-msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
-
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
@@ -31932,6 +32843,9 @@ 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 ""
@@ -31947,15 +32861,15 @@ msgstr ""
msgid "You can now export your security dashboard to a CSV report."
msgstr ""
-msgid "You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated."
-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 edit files when you are on a branch"
msgstr ""
@@ -31983,7 +32897,7 @@ msgstr ""
msgid "You can see your chat accounts."
msgstr ""
-msgid "You can set up as many Runners as you need to run your jobs."
+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."
@@ -32124,6 +33038,9 @@ msgstr ""
msgid "You have insufficient permissions to create an on-call schedule for this project"
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 ""
@@ -32136,6 +33053,9 @@ 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 no permissions"
msgstr ""
@@ -32319,6 +33239,9 @@ 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 ""
@@ -32355,13 +33278,13 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
-msgid "Your GitLab account request has been approved!"
+msgid "Your GitLab Ultimate trial will last 30 days after which point you can keep your free GitLab account forever. We just need some additional information to activate your trial."
msgstr ""
-msgid "Your GitLab group"
+msgid "Your GitLab account request has been approved!"
msgstr ""
-msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgid "Your GitLab group"
msgstr ""
msgid "Your Groups"
@@ -32517,6 +33440,9 @@ msgstr ""
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
msgstr ""
+msgid "Your membership in %{group} no longer expires."
+msgstr ""
+
msgid "Your message here"
msgstr ""
@@ -32601,6 +33527,12 @@ msgstr ""
msgid "[No reason]"
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 ""
@@ -32686,9 +33618,15 @@ 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't be enabled because signed commits are required for this project"
+msgstr ""
+
msgid "cannot be a date in the past"
msgstr ""
@@ -32997,6 +33935,9 @@ msgid "day"
msgid_plural "days"
msgstr[0] "天"
+msgid "days"
+msgstr ""
+
msgid "default branch"
msgstr ""
@@ -33037,8 +33978,9 @@ msgstr ""
msgid "element is not a hierarchy"
msgstr ""
-msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
-msgstr ""
+msgid "email '%{email}' does not match the allowed domain of %{email_domains}"
+msgid_plural "email '%{email}' does not match the allowed domains: %{email_domains}"
+msgstr[0] ""
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -33129,6 +34071,9 @@ msgstr ""
msgid "group members"
msgstr ""
+msgid "group's CI/CD settings."
+msgstr ""
+
msgid "groups"
msgstr ""
@@ -33371,6 +34316,12 @@ msgstr ""
msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
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 ""
@@ -33497,9 +34448,6 @@ msgstr ""
msgid "mrWidget|Merge failed."
msgstr ""
-msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
-msgstr ""
-
msgid "mrWidget|Merge locally"
msgstr ""
@@ -33569,7 +34517,7 @@ msgstr ""
msgid "mrWidget|The changes will be merged into"
msgstr ""
-msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+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 HEAD has recently changed. Please reload the page and review the changes before merging"
@@ -33650,6 +34598,9 @@ msgstr ""
msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr ""
+msgid "must be a boolean value"
+msgstr ""
+
msgid "must be a root namespace"
msgstr ""
@@ -33868,6 +34819,9 @@ msgstr ""
msgid "revised"
msgstr ""
+msgid "runners"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -34006,6 +34960,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "train"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/package.json b/package.json
index a5ca4851efa..eb39884a1d9 100644
--- a/package.json
+++ b/package.json
@@ -41,11 +41,11 @@
"@babel/plugin-proposal-private-methods": "^7.10.1",
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
- "@gitlab/at.js": "1.5.5",
+ "@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "1.178.0",
+ "@gitlab/svgs": "1.182.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "25.11.3",
+ "@gitlab/ui": "27.4.6",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-4",
"@rails/ujs": "^6.0.3-4",
@@ -60,17 +60,16 @@
"autosize": "^4.0.2",
"aws-sdk": "^2.637.0",
"axios": "^0.20.0",
- "babel-loader": "^8.0.6",
+ "babel-loader": "^8.2.2",
"babel-plugin-lodash": "^3.3.4",
"bootstrap": "4.4.1",
- "brace-expansion": "^1.1.8",
"cache-loader": "^4.1.0",
"clipboard": "^1.7.1",
"codemirror": "^5.48.4",
"codesandbox-api": "0.0.23",
- "compression-webpack-plugin": "^3.0.1",
- "copy-webpack-plugin": "^5.0.5",
- "core-js": "^3.6.4",
+ "compression-webpack-plugin": "^5.0.2",
+ "copy-webpack-plugin": "^5.1.2",
+ "core-js": "^3.8.3",
"cron-validator": "^1.1.1",
"cropper": "^2.3.0",
"css-loader": "^2.1.1",
@@ -90,16 +89,12 @@
"exports-loader": "^0.7.0",
"fast-mersenne-twister": "1.0.2",
"file-loader": "^5.1.0",
- "font-awesome": "4.7.0",
"fuzzaldrin-plus": "^0.6.0",
- "glob": "^7.1.6",
"graphql": "^15.4.0",
"graphql-tag": "^2.11.0",
"immer": "^7.0.7",
- "imports-loader": "^0.8.0",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
- "jest-transform-graphql": "^2.1.0",
"jquery": "^3.5.0",
"jquery.caret": "^0.3.1",
"jquery.waitforimages": "^2.2.0",
@@ -111,10 +106,8 @@
"lodash": "^4.17.20",
"marked": "^0.3.12",
"mathjax": "3",
- "mermaid": "^8.5.2",
+ "mermaid": "^8.9.0",
"minimatch": "^3.0.4",
- "miragejs": "^0.1.40",
- "mock-apollo-client": "^0.5.0",
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.0",
"monaco-yaml": "^2.5.1",
@@ -126,12 +119,11 @@
"prosemirror-markdown": "^1.3.0",
"prosemirror-model": "^1.6.4",
"raphael": "^2.2.7",
- "raw-loader": "^4.0.0",
+ "raw-loader": "^4.0.2",
"select2": "3.5.2-browserify",
"smooshpack": "^0.0.62",
"sortablejs": "^1.10.2",
"sql.js": "^0.4.0",
- "stickyfilljs": "^2.1.0",
"string-hash": "1.1.3",
"style-loader": "^1.3.0",
"swagger-ui-dist": "^3.32.4",
@@ -154,16 +146,16 @@
"vuedraggable": "^2.23.0",
"vuex": "^3.6.0",
"web-vitals": "^0.2.4",
- "webpack": "^4.42.0",
- "webpack-bundle-analyzer": "^3.6.0",
- "webpack-cli": "^3.3.11",
+ "webpack": "^4.46.0",
+ "webpack-bundle-analyzer": "^3.9.0",
+ "webpack-cli": "^3.3.12",
"webpack-stats-plugin": "^0.3.1",
"worker-loader": "^2.0.0",
"xterm": "3.14.5"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "6.0.0",
+ "@gitlab/eslint-plugin": "8.0.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.1.2",
"acorn": "^6.3.0",
@@ -175,16 +167,17 @@
"commander": "^2.18.0",
"custom-jquery-matchers": "^2.1.0",
"docdash": "^1.0.2",
- "eslint": "^6.8.0",
- "eslint-import-resolver-jest": "^2.1.1",
- "eslint-import-resolver-webpack": "^0.12.1",
- "eslint-plugin-jasmine": "^4.1.0",
- "eslint-plugin-no-jquery": "^2.3.0",
- "gettext-extractor": "^3.4.3",
- "gettext-extractor-vue": "^4.0.2",
+ "eslint": "7.19.0",
+ "eslint-import-resolver-jest": "3.0.0",
+ "eslint-import-resolver-webpack": "0.13.0",
+ "eslint-plugin-jasmine": "4.1.2",
+ "eslint-plugin-no-jquery": "2.5.0",
+ "gettext-extractor": "^3.5.3",
+ "gettext-extractor-vue": "^5.0.0",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.0",
"istanbul-reports": "^3.0.0",
+ "glob": "^7.1.6",
"jasmine-core": "^2.9.0",
"jasmine-diff": "^0.1.3",
"jasmine-jquery": "^2.1.1",
@@ -193,6 +186,7 @@
"jest-environment-jsdom": "^26.5.2",
"jest-junit": "^12.0.0",
"jest-raw-loader": "^1.0.1",
+ "jest-transform-graphql": "^2.1.0",
"jest-util": "^26.5.2",
"jsdoc": "^3.5.5",
"jsdoc-vue": "^1.0.0",
@@ -206,9 +200,10 @@
"karma-webpack": "^4.0.2",
"markdownlint-cli": "0.24.0",
"md5": "^2.2.1",
+ "miragejs": "^0.1.40",
+ "mock-apollo-client": "^0.5.0",
"node-sass": "^4.14.1",
"nodemon": "^2.0.4",
- "pixelmatch": "^4.0.2",
"postcss": "^7.0.14",
"prettier": "2.2.1",
"readdir-enhanced": "^2.2.4",
@@ -217,7 +212,7 @@
"stylelint-scss": "^3.9.2",
"timezone-mock": "^1.0.8",
"vue-jest": "4.0.0-rc.0",
- "webpack-dev-server": "^3.10.3",
+ "webpack-dev-server": "^3.11.2",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
"yarn-deduplicate": "^1.1.1"
diff --git a/qa/Dockerfile b/qa/Dockerfile
index d040bddfc7f..76c81d03071 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -3,8 +3,8 @@ LABEL maintainer="GitLab Quality Department <quality@gitlab.com>"
ENV DEBIAN_FRONTEND="noninteractive"
ENV DOCKER_VERSION="17.09.0-ce"
-ENV CHROME_VERSION="84.0.4147.89-1"
-ENV CHROME_DRIVER_VERSION="84.0.4147.30"
+ENV CHROME_VERSION="87.0.4280.141-1"
+ENV CHROME_DRIVER_VERSION="87.0.4280.88"
ENV CHROME_DEB="google-chrome-stable_${CHROME_VERSION}_amd64.deb"
ENV CHROME_URL="https://s3.amazonaws.com/gitlab-google-chrome-stable/${CHROME_DEB}"
diff --git a/qa/Gemfile b/qa/Gemfile
index da45ba3b955..f55d27c159b 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
source 'https://rubygems.org'
gem 'gitlab-qa'
diff --git a/qa/README.md b/qa/README.md
index 5070e1ee9bd..02fa84f4488 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -104,6 +104,15 @@ bundle exec bin/qa Test::Instance::All http://localhost:3000 -- qa/specs/feature
Note that the separator `--` is required; all subsequent options will be
ignored by the QA framework and passed to `rspec`.
+#### Running tests for transient bugs
+
+A suite of tests have been written to test for [transient bugs](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#transient-bugs).
+Those tests are tagged `:transient` and therefore can be run via:
+
+```shell
+bundle exec bin/qa Test::Instance::All http://localhost:3000 -- --tag transient
+```
+
### Overriding the authenticated user
Unless told otherwise, the QA tests will run as the default `root` user seeded
@@ -207,7 +216,7 @@ run all the tests in the `Test::Instance::All` scenario, and then enable the
feature flag again if it was enabled earlier.
Note: the QA framework doesn't currently allow you to easily toggle a feature
-flag during a single test, [as you can in unit tests](https://docs.gitlab.com/ee/development/feature_flags.html#specs),
+flag during a single test, [as you can in unit tests](https://docs.gitlab.com/ee/development/feature_flags/index.html),
but [that capability is planned](https://gitlab.com/gitlab-org/quality/team-tasks/issues/77).
Note also that the `--` separator isn't used because `--enable-feature` and `--disable-feature`
diff --git a/qa/Rakefile b/qa/Rakefile
index 6bafec2a67d..0a040f0aee7 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative 'qa/tools/revoke_all_personal_access_tokens'
require_relative 'qa/tools/delete_subgroups'
require_relative 'qa/tools/generate_perf_testdata'
diff --git a/qa/bin/qa b/qa/bin/qa
index cbaad4bd7ad..4328adf719b 100755
--- a/qa/bin/qa
+++ b/qa/bin/qa
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require_relative '../qa'
diff --git a/qa/bin/rubymine b/qa/bin/rubymine
index 0be0cf0ec33..7db50f4aade 100755
--- a/qa/bin/rubymine
+++ b/qa/bin/rubymine
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require_relative '../qa'
diff --git a/qa/qa.rb b/qa/qa.rb
index 1d1ac2e2749..1cf6d7b79f7 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -156,6 +156,7 @@ module QA
autoload :Mattermost, 'qa/scenario/test/integration/mattermost'
autoload :ObjectStorage, 'qa/scenario/test/integration/object_storage'
autoload :SMTP, 'qa/scenario/test/integration/smtp'
+ autoload :SSHTunnel, 'qa/scenario/test/integration/ssh_tunnel'
end
module Sanity
diff --git a/qa/qa/fixtures/auto_devops_rack/Gemfile b/qa/qa/fixtures/auto_devops_rack/Gemfile
index fc7514242d0..2c7c77adf94 100644
--- a/qa/qa/fixtures/auto_devops_rack/Gemfile
+++ b/qa/qa/fixtures/auto_devops_rack/Gemfile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
source 'https://rubygems.org'
gem 'rack'
gem 'rake'
diff --git a/qa/qa/fixtures/auto_devops_rack/Rakefile b/qa/qa/fixtures/auto_devops_rack/Rakefile
index c865c9aaac1..a6d08103d55 100644
--- a/qa/qa/fixtures/auto_devops_rack/Rakefile
+++ b/qa/qa/fixtures/auto_devops_rack/Rakefile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rake/testtask'
task default: %w[test]
diff --git a/qa/qa/fixtures/auto_devops_rack/config.ru b/qa/qa/fixtures/auto_devops_rack/config.ru
index e990662145a..aea28ef1893 100644
--- a/qa/qa/fixtures/auto_devops_rack/config.ru
+++ b/qa/qa/fixtures/auto_devops_rack/config.ru
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, StringIO.new("Hello World! #{ENV['OPTIONAL_MESSAGE']}\n")] }
diff --git a/qa/qa/flow/project.rb b/qa/qa/flow/project.rb
index db42a3a3594..8a9e2c86332 100644
--- a/qa/qa/flow/project.rb
+++ b/qa/qa/flow/project.rb
@@ -5,16 +5,6 @@ module QA
module Project
module_function
- def add_member(project:, username:)
- project.visit!
-
- Page::Project::Menu.perform(&:click_members)
-
- Page::Project::Members.perform do |member_settings|
- member_settings.add_member(username)
- end
- end
-
def go_to_create_project_from_template
if Page::Project::NewExperiment.perform(&:shown?)
Page::Project::NewExperiment.perform(&:click_create_from_template_link)
diff --git a/qa/qa/flow/sign_up.rb b/qa/qa/flow/sign_up.rb
index b367b7976e8..a2a62371092 100644
--- a/qa/qa/flow/sign_up.rb
+++ b/qa/qa/flow/sign_up.rb
@@ -5,6 +5,10 @@ module QA
module SignUp
module_function
+ def page
+ Capybara.current_session
+ end
+
def sign_up!(user)
Page::Main::Menu.perform(&:sign_out_if_signed_in)
Page::Main::Login.perform(&:switch_to_register_page)
@@ -14,6 +18,11 @@ module QA
sign_up.fill_new_user_username_field(user.username)
sign_up.fill_new_user_email_field(user.email)
sign_up.fill_new_user_password_field(user.password)
+
+ Support::Waiter.wait_until(sleep_interval: 0.5) do
+ page.has_content?("Username is available.")
+ end
+
sign_up.click_new_user_register_button
end
diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb
index fea95fdb84a..1885644d226 100644
--- a/qa/qa/page/admin/overview/users/index.rb
+++ b/qa/qa/page/admin/overview/users/index.rb
@@ -6,7 +6,7 @@ module QA
module Overview
module Users
class Index < QA::Page::Base
- view 'app/views/admin/users/index.html.haml' do
+ view 'app/views/admin/users/_users.html.haml' do
element :user_search_field
element :pending_approval_tab
end
diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb
index 15c1c25cbf9..4c1f03fbe86 100644
--- a/qa/qa/page/component/issue_board/show.rb
+++ b/qa/qa/page/component/issue_board/show.rb
@@ -39,7 +39,7 @@ module QA
element :boards_list
end
- view 'app/assets/javascripts/boards/toggle_focus.js' do
+ view 'app/assets/javascripts/boards/components/toggle_focus.vue' do
element :focus_mode_button
end
diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb
index 0454042289b..50567796bdb 100644
--- a/qa/qa/page/component/note.rb
+++ b/qa/qa/page/component/note.rb
@@ -162,10 +162,6 @@ module QA
fill_element :reply_field, reply_text
end
- def wait_for_loading
- has_no_element?(:skeleton_note_placeholer)
- end
-
private
def select_filter_with_text(text)
@@ -174,7 +170,7 @@ module QA
click_element :discussion_filter_dropdown
find_element(:filter_menu_item, text: text).click
- wait_for_loading
+ wait_for_requests
end
end
end
diff --git a/qa/qa/page/issuable/new.rb b/qa/qa/page/issuable/new.rb
index 7891074092e..c549190c65b 100644
--- a/qa/qa/page/issuable/new.rb
+++ b/qa/qa/page/issuable/new.rb
@@ -28,6 +28,10 @@ module QA
element :assign_to_me_link
end
+ view 'app/views/shared/issuable/form/_template_selector.html.haml' do
+ element :template_dropdown
+ end
+
def fill_title(title)
fill_element :issuable_form_title, title
end
@@ -43,6 +47,13 @@ module QA
end
end
+ def choose_template(template_name)
+ click_element :template_dropdown
+ within_element(:template_dropdown) do
+ click_on template_name
+ end
+ end
+
def select_label(label)
click_element :issuable_label
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index 627809dacf2..f0df901a8f0 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -6,7 +6,7 @@ module QA
class Menu < Page::Base
view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
element :sign_out_link
- element :settings_link
+ element :edit_profile_link
end
view 'app/views/layouts/header/_default.html.haml' do
@@ -115,10 +115,10 @@ module QA
sign_out if signed_in?
end
- def click_settings_link
+ def click_edit_profile_link
retry_until(reload: false) do
within_user_menu do
- click_link 'Settings'
+ click_element(:edit_profile_link)
end
has_text?('User Settings')
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index ac4d38e5918..18676807fd6 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -58,6 +58,9 @@ module QA
view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
element :file_name_content
+ element :file_title_container
+ element :dropdown_button
+ element :edit_in_ide_button
end
view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
@@ -87,6 +90,15 @@ module QA
element :review_preview_toggle
end
+ view 'app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue' do
+ element :apply_suggestions_batch_button
+ element :add_suggestion_batch_button
+ end
+
+ view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do
+ element :suggestion_button
+ end
+
def start_review
click_element(:start_review_button)
@@ -150,15 +162,12 @@ module QA
def click_discussions_tab
click_element(:notes_tab)
- wait_for_loading
+ wait_for_requests
end
def click_diffs_tab
click_element(:diffs_tab)
-
- wait_for_loading
-
- click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button)
+ click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button, wait: 1)
end
def click_pipeline_link
@@ -296,6 +305,31 @@ module QA
click_element(:open_in_web_ide_button)
wait_for_requests
end
+
+ def edit_file_in_web_ide(file_name)
+ within_element(:file_title_container, file_name: file_name) do
+ click_element(:dropdown_button)
+ click_element(:edit_in_ide_button)
+ end
+ end
+
+ def add_suggestion_to_diff(suggestion, line)
+ find("a[data-linenumber='#{line}']").hover
+ click_element(:diff_comment)
+ click_element(:suggestion_button)
+ initial_content = find_element(:reply_field).value
+ fill_element(:reply_field, '')
+ fill_element(:reply_field, initial_content.gsub(/(```suggestion:-0\+0\n).*(\n```)/, "\\1#{suggestion}\\2"))
+ click_element(:comment_now_button)
+ end
+
+ def add_suggestion_to_batch
+ all_elements(:add_suggestion_batch_button, minimum: 1).first.click
+ end
+
+ def apply_suggestions_batch
+ all_elements(:apply_suggestions_batch_button, minimum: 1).first.click
+ end
end
end
end
diff --git a/qa/qa/page/page_concern.rb b/qa/qa/page/page_concern.rb
index 6ba2d27f574..cf1153c0ca3 100644
--- a/qa/qa/page/page_concern.rb
+++ b/qa/qa/page/page_concern.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module QA
module Page
module PageConcern
diff --git a/qa/qa/page/project/commit/show.rb b/qa/qa/page/project/commit/show.rb
index ba09dd1b92a..8ece81f7088 100644
--- a/qa/qa/page/project/commit/show.rb
+++ b/qa/qa/page/project/commit/show.rb
@@ -14,12 +14,12 @@ module QA
def select_email_patches
click_element :options_button
- click_element :email_patches
+ visit_link_in_element :email_patches
end
def select_plain_diff
click_element :options_button
- click_element :plain_diff
+ visit_link_in_element :plain_diff
end
def commit_sha
diff --git a/qa/qa/page/project/members.rb b/qa/qa/page/project/members.rb
index 447049ce22a..7e722e02ad0 100644
--- a/qa/qa/page/project/members.rb
+++ b/qa/qa/page/project/members.rb
@@ -11,10 +11,6 @@ module QA
element :invite_member_button
end
- view 'app/views/projects/project_members/_team.html.haml' do
- element :members_list
- end
-
view 'app/views/projects/project_members/index.html.haml' do
element :invite_group_tab
element :groups_list_tab
@@ -25,11 +21,18 @@ module QA
element :invite_group_button
end
- view 'app/views/shared/members/_group.html.haml' do
+ view 'app/assets/javascripts/pages/projects/project_members/index.js' do
element :group_row
+ end
+
+ view 'app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue' do
element :delete_group_access_link
end
+ view 'app/assets/javascripts/members/components/modals/remove_group_link_modal.vue' do
+ element :remove_group_link_modal_content
+ end
+
def select_group(group_name)
click_element :group_select_field
search_and_select(group_name)
@@ -50,10 +53,13 @@ module QA
def remove_group(group_name)
click_element :invite_group_tab
click_element :groups_list_tab
- page.accept_alert do
- within_element(:group_row, text: group_name) do
- click_element :delete_group_access_link
- end
+
+ within_element(:group_row, text: group_name) do
+ click_element :delete_group_access_link
+ end
+
+ within_element(:remove_group_link_modal_content) do
+ click_button 'Remove group'
end
end
end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index a8b30922bd2..45c46004790 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -18,7 +18,8 @@ module QA
end
view 'app/assets/javascripts/ide/components/ide_tree.vue' do
- element :new_file
+ element :new_file_button
+ element :new_directory_button
end
view 'app/assets/javascripts/ide/components/ide_tree_list.vue' do
@@ -63,6 +64,7 @@ module QA
view 'app/assets/javascripts/ide/components/new_dropdown/index.vue' do
element :dropdown_button
element :rename_move_button
+ element :delete_button
end
view 'app/views/shared/_confirm_fork_modal.html.haml' do
@@ -82,6 +84,10 @@ module QA
element :changed_file_icon_content
end
+ view 'app/assets/javascripts/vue_shared/components/file_icon.vue' do
+ element :folder_icon_content
+ end
+
view 'app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue' do
element :preview_container
end
@@ -98,12 +104,20 @@ module QA
element :file_upload_field
end
+ view 'app/assets/javascripts/ide/components/commit_sidebar/list_item.vue' do
+ element :file_to_commit_content
+ end
+
def has_file?(file_name)
within_element(:file_list) do
- has_text?(file_name)
+ has_element?(:file_name_content, file_name: file_name)
end
end
+ def has_file_to_commit?(file_name)
+ has_element?(:file_to_commit_content, file_name: file_name)
+ end
+
def has_project_path?(project_path)
has_element?(:project_path_content, project_path: project_path)
end
@@ -114,6 +128,12 @@ module QA
end
end
+ def has_folder_icon?(file_name)
+ within_element(:file_row_container, file_name: file_name) do
+ has_element?(:folder_icon_content)
+ end
+ end
+
def has_download_button?(file_name)
click_element(:file_row_container, file_name: file_name)
within_element(:preview_container) do
@@ -128,12 +148,19 @@ module QA
end
end
+ def has_file_content?(file_name, file_content)
+ click_element(:file_row_container, file_name: file_name)
+ within_element(:editor_container) do
+ has_text?(file_content)
+ end
+ end
+
def go_to_project
click_element(:project_path_content, Page::Project::Show)
end
def create_new_file_from_template(file_name, template)
- click_element(:new_file, Page::Component::WebIDE::Modal::CreateNewFile)
+ click_element(:new_file_button, Page::Component::WebIDE::Modal::CreateNewFile)
within_element(:template_list) do
click_on file_name
@@ -226,7 +253,7 @@ module QA
end
def add_file(file_name, file_text)
- click_element(:new_file, Page::Component::WebIDE::Modal::CreateNewFile)
+ click_element(:new_file_button, Page::Component::WebIDE::Modal::CreateNewFile)
fill_element(:file_name_field, file_name)
click_button('Create file')
wait_until(reload: false) { has_file?(file_name) }
@@ -235,8 +262,15 @@ module QA
end
end
+ def add_directory(directory_name)
+ click_element(:new_directory_button, Page::Component::WebIDE::Modal::CreateNewFile)
+ fill_element(:file_name_field, directory_name)
+ click_button('Create directory')
+ wait_until(reload: false) { has_file?(directory_name) }
+ end
+
def rename_file(file_name, new_file_name)
- click_element(:file_name_content, text: file_name)
+ click_element(:file_name_content, file_name: file_name)
click_element(:dropdown_button)
click_element(:rename_move_button, Page::Component::WebIDE::Modal::CreateNewFile)
fill_element(:file_name_field, new_file_name)
@@ -259,6 +293,16 @@ module QA
find_element(:file_upload_field, visible: false).send_keys(file_path)
end
end
+
+ def delete_file(file_name)
+ click_element(:file_name_content, file_name: file_name)
+ click_element(:dropdown_button)
+ click_element(:delete_button)
+ end
+
+ def switch_to_commit_tab
+ click_element(:commit_mode_tab)
+ end
end
end
end
diff --git a/qa/qa/resource/ci_variable.rb b/qa/qa/resource/ci_variable.rb
index f14fcdaac9f..0b9f4eb6635 100644
--- a/qa/qa/resource/ci_variable.rb
+++ b/qa/qa/resource/ci_variable.rb
@@ -3,7 +3,7 @@
module QA
module Resource
class CiVariable < Base
- attr_accessor :key, :value, :masked
+ attr_accessor :key, :value, :masked, :protected
attribute :project do
Project.fabricate! do |resource|
@@ -12,6 +12,11 @@ module QA
end
end
+ def initialize
+ @masked = false
+ @protected = false
+ end
+
def fabricate!
project.visit!
@@ -49,7 +54,8 @@ module QA
{
key: key,
value: value,
- masked: masked
+ masked: masked,
+ protected: protected
}
end
end
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
index a6bd8987077..ffffa0eecda 100644
--- a/qa/qa/resource/issue.rb
+++ b/qa/qa/resource/issue.rb
@@ -5,7 +5,7 @@ require 'securerandom'
module QA
module Resource
class Issue < Base
- attr_writer :description, :milestone, :weight
+ attr_writer :description, :milestone, :template, :weight
attribute :project do
Project.fabricate! do |resource|
@@ -33,7 +33,8 @@ module QA
Page::Project::Issue::New.perform do |new_page|
new_page.fill_title(@title)
- new_page.fill_description(@description)
+ new_page.choose_template(@template) if @template
+ new_page.fill_description(@description) if @description
new_page.choose_milestone(@milestone) if @milestone
new_page.create_new_issue
end
diff --git a/qa/qa/resource/members.rb b/qa/qa/resource/members.rb
index 52928afa7db..a88980f26d8 100644
--- a/qa/qa/resource/members.rb
+++ b/qa/qa/resource/members.rb
@@ -31,12 +31,13 @@ module QA
end
class AccessLevel
- NO_ACCESS = 0
- GUEST = 10
- REPORTER = 20
- DEVELOPER = 30
- MAINTAINER = 40
- OWNER = 50
+ NO_ACCESS = 0
+ MINIMAL_ACCESS = 5
+ GUEST = 10
+ REPORTER = 20
+ DEVELOPER = 30
+ MAINTAINER = 40
+ OWNER = 50
end
end
end
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index ecf25b797a8..fd5f454f134 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -19,7 +19,8 @@ module QA
:file_name,
:file_content
attr_writer :no_preparation,
- :wait_for_merge
+ :wait_for_merge,
+ :template
attribute :merge_when_pipeline_succeeds
attribute :merge_status
@@ -73,7 +74,8 @@ module QA
Page::Project::Show.perform(&:new_merge_request)
Page::MergeRequest::New.perform do |new_page|
new_page.fill_title(@title)
- new_page.fill_description(@description)
+ new_page.choose_template(@template) if @template
+ new_page.fill_description(@description) unless @template
new_page.choose_milestone(@milestone) if @milestone
new_page.assign_to_me if @assignee == 'me'
labels.each do |label|
@@ -86,6 +88,8 @@ module QA
end
def fabricate_via_api!
+ raise ResourceNotFoundError unless id
+
resource_web_url(api_get)
rescue ResourceNotFoundError
populate_target_and_source_if_required
diff --git a/qa/qa/resource/personal_access_token.rb b/qa/qa/resource/personal_access_token.rb
index 488138326df..6b2301ba916 100644
--- a/qa/qa/resource/personal_access_token.rb
+++ b/qa/qa/resource/personal_access_token.rb
@@ -15,7 +15,7 @@ module QA
end
def fabricate!
- Page::Main::Menu.perform(&:click_settings_link)
+ Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_access_tokens)
Page::Profile::PersonalAccessTokens.perform do |token_page|
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index a92f7912b9e..efb6c2c0591 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -25,10 +25,6 @@ module QA
attribute :template_name
attribute :import
- attribute :default_branch do
- api_response[:default_branch] || Runtime::Env.default_branch
- end
-
attribute :group do
Group.fabricate!
end
@@ -224,6 +220,10 @@ module QA
parse_body(get(Runtime::API::Request.new(api_client, api_commits_path).url))
end
+ def default_branch
+ reload!.api_response[:default_branch] || Runtime::Env.default_branch
+ end
+
def import_status
response = get Runtime::API::Request.new(api_client, "/projects/#{id}/import").url
diff --git a/qa/qa/resource/repository/wiki_push.rb b/qa/qa/resource/repository/wiki_push.rb
index f188e52c969..edf76c7cd78 100644
--- a/qa/qa/resource/repository/wiki_push.rb
+++ b/qa/qa/resource/repository/wiki_push.rb
@@ -12,14 +12,11 @@ module QA
end
end
- def branch_name
- @branch_name ||= wiki.project.default_branch
- end
-
def initialize
@file_name = 'Home.md'
@file_content = 'This line was created using git push'
@commit_message = 'Updating using git push'
+ @branch_name = 'master'
@new_branch = false
end
diff --git a/qa/qa/resource/ssh_key.rb b/qa/qa/resource/ssh_key.rb
index fcd0a479fec..52526275cb0 100644
--- a/qa/qa/resource/ssh_key.rb
+++ b/qa/qa/resource/ssh_key.rb
@@ -22,7 +22,7 @@ module QA
end
def fabricate!
- Page::Main::Menu.perform(&:click_settings_link)
+ Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_ssh_keys)
Page::Profile::SSHKeys.perform do |profile_page|
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 1c637db5385..6c4139da83f 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -411,6 +411,10 @@ module QA
ENV.fetch('GITLAB_AGENTK_VERSION', 'v13.7.0')
end
+ def transient_trials
+ ENV.fetch('GITLAB_QA_TRANSIENT_TRIALS', 10).to_i
+ end
+
private
def remote_grid_credentials
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
new file mode 100644
index 00000000000..b7f71ad5bcd
--- /dev/null
+++ b/qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'User', :requires_admin do
+ before(:all) do
+ admin_api_client = Runtime::API::Client.as_admin
+
+ @user = Resource::User.fabricate_via_api! do |user|
+ user.api_client = admin_api_client
+ end
+
+ @user_api_client = Runtime::API::Client.new(:gitlab, user: @user)
+
+ @group = Resource::Group.fabricate_via_api!
+
+ @group.sandbox.add_member(@user)
+
+ @project = Resource::Project.fabricate_via_api! do |project|
+ project.group = @group
+ project.name = "project-for-user-group-access-termination"
+ project.initialize_with_readme = true
+ end
+ end
+
+ context 'after parent group membership termination' do
+ before do
+ @group.sandbox.remove_member(@user)
+ end
+
+ it 'is not allowed to push code via the CLI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1660' 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'
+ push.user = @user
+ end
+ end.to raise_error(QA::Support::Run::CommandError, /You are not allowed to push code to this project/)
+ end
+
+ it 'is not allowed to create a file via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1661' do
+ expect do
+ Resource::File.fabricate_via_api! do |file|
+ file.api_client = @user_api_client
+ file.project = @project
+ file.branch = 'new_branch'
+ 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
+
+ it 'is not allowed to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1662' do
+ expect do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = @user_api_client
+ commit.project = @project
+ commit.branch = 'new_branch'
+ 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
+
+ after(:all) do
+ @user.remove_via_api!
+ @project.remove_via_api!
+ begin
+ @group.remove_via_api!
+ rescue Resource::ApiFabricator::ResourceNotDeletedError
+ # It is ok if the group is already marked for deletion by another test
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
index c3cb503ed3f..9bf3474ba5a 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
@@ -88,6 +88,7 @@ module QA
read_from_project(project, number_of_reads)
praefect_manager.query_read_distribution.each_with_index do |data, index|
+ diff_found[index] = {} unless diff_found[index]
diff_found[index][:diff] = true if data[:value] > praefect_manager.value_for_node(pre_read_data, data[:node])
end
diff_found.all? { |node| node.key?(:diff) && node[:diff] }
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
index f6d2492c011..3702f95158c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
@@ -48,7 +48,7 @@ module QA
def enable_2fa_for_user(user)
Flow::Login.while_signed_in(as: user) do
- Page::Main::Menu.perform(&:click_settings_link)
+ Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_account)
Page::Profile::Accounts::Show.perform(&:click_enable_2fa_button)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
index 624f8d20b62..9b2540f67c7 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :smoke do
describe 'basic user login' do
- it 'user logs in using basic credentials and logs out', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/424' do
+ it 'user logs in using basic credentials and logs out', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1690' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
index f81dfe4b5c8..2fc3ff2f18f 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
@@ -101,7 +101,7 @@ module QA
two_fa_auth.click_copy_and_proceed
- expect(two_fa_auth).to have_text('Congratulations! You have enabled Two-factor Authentication!')
+ expect(two_fa_auth).to have_text('You have set up 2FA for your account!')
end
end
end
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 d9b246fc458..ffc2290b644 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
@@ -58,7 +58,7 @@ module QA
# this is the only test that exercise this UI.
# Other tests should use the API for this purpose.
Flow::Login.sign_in(as: user)
- Page::Main::Menu.perform(&:click_settings_link)
+ Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_account)
Page::Profile::Accounts::Show.perform do |show|
show.delete_account(user.password)
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 e71cbeb9837..85cfefd6c5c 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,8 +1,16 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage' do
+ RSpec.describe 'Manage', :requires_admin do
describe 'Add project member' do
+ before do
+ Runtime::Feature.enable('vue_project_members_list')
+ end
+
+ after do
+ Runtime::Feature.disable('vue_project_members_list')
+ end
+
it 'user adds project member', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/482' do
Flow::Login.sign_in
@@ -16,7 +24,7 @@ module QA
Page::Project::Members.perform do |members|
members.add_member(user.username)
- expect(members).to have_content(/@#{user.username}( Is using seat)?(\n| )?Given access/)
+ expect(members).to have_content("@#{user.username}")
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
index a2e01398c94..e722710ee00 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
@@ -4,7 +4,7 @@ module QA
RSpec.describe 'Manage', :smoke do
describe 'Project creation' do
it 'user creates a new project',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/429' do
+ testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1234' do
Flow::Login.sign_in
created_project = Resource::Project.fabricate_via_browser_ui! do |project|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
index aaf0c51a2db..f2822e3d368 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
@@ -41,7 +41,7 @@ module QA
end
end
- context 'when logged in as a new user', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/465' do
+ context 'when logged in as a new user', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1693' do
it_behaves_like 'loads all images' do
let(:new_user) { @new_user }
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
new file mode 100644
index 00000000000..7ec217cb47d
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'User', :requires_admin do
+ let(:admin_api_client) { Runtime::API::Client.as_admin }
+
+ let!(:user) do
+ Resource::User.fabricate_via_api! do |user|
+ user.api_client = admin_api_client
+ end
+ end
+
+ let!(:group) do
+ group = Resource::Group.fabricate_via_api!
+ group.sandbox.add_member(user)
+ group
+ end
+
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.group = group
+ project.name = "project-for-user-access-termination"
+ project.initialize_with_readme = true
+ end
+ end
+
+ context 'after parent group membership termination' do
+ before do
+ Flow::Login.while_signed_in_as_admin do
+ group.sandbox.visit!
+
+ Page::Group::Menu.perform(&:click_group_members_item)
+ Page::Group::Members.perform do |members_page|
+ members_page.remove_member(user.username)
+ end
+ end
+ end
+
+ it 'is not allowed to edit the project files', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1663' do
+ Flow::Login.sign_in(as: user)
+ project.visit!
+
+ Page::Project::Show.perform do |project|
+ project.click_file('README.md')
+ end
+
+ Page::File::Show.perform(&:click_edit)
+
+ expect(page).to have_text("You're not allowed to edit files in this project directly.")
+ end
+
+ after do
+ user.remove_via_api!
+ project.remove_via_api!
+ begin
+ group.remove_via_api!
+ rescue Resource::ApiFabricator::ResourceNotDeletedError
+ # It is ok if the group is already marked for deletion by another test
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
index 418865a63d2..f623efe5a3a 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Plan', :orchestrated, :smtp do
+ RSpec.describe 'Plan', :orchestrated, :smtp, :requires_admin do
describe 'Email Notification' do
include Support::Api
@@ -16,13 +16,23 @@ module QA
end
before do
+ Runtime::Feature.enable('vue_project_members_list', project: project)
Flow::Login.sign_in
end
+ after do
+ Runtime::Feature.disable('vue_project_members_list', project: project)
+ end
+
it 'is received by a user for project invitation', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/676' do
- Flow::Project.add_member(project: project, username: user.username)
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_members)
+ Page::Project::Members.perform do |member_settings|
+ member_settings.add_member(user.username)
+ end
- expect(page).to have_content(/@#{user.username}(\n| )?Given access/)
+ expect(page).to have_content("@#{user.username}")
mailhog_items = mailhog_json.dig('items')
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
index e394f6b1e9c..a7f862e8911 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
@@ -20,7 +20,7 @@ module QA
before do
Flow::Login.sign_in
- Flow::Project.add_member(project: project, username: user.username)
+ project.add_member(user)
Resource::Issue.fabricate_via_api! do |issue|
issue.project = project
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
index 6ed204a98d4..72c990cbbc2 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -13,7 +13,7 @@ module QA
issue.visit!
end
- it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/434' do
+ it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1163' do
Page::Project::Issue::Show.perform do |show|
show.select_all_activities_filter
show.start_discussion('My first discussion')
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
index d3780186f36..c5cd495f607 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'comments on an issue and edits the comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/450' do
+ it 'comments on an issue and edits the comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1151' do
Page::Project::Issue::Show.perform do |show|
first_version_of_comment = 'First version of the comment'
second_version_of_comment = 'Second version of the comment'
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 688f42c48c6..de6b24e8477 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates an issue', :reliable, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/432' do
+ it 'creates an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1167' do
issue = Resource::Issue.fabricate_via_browser_ui!
Page::Project::Menu.perform(&:click_issues)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb
new file mode 100644
index 00000000000..5f5fe161e71
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan' do
+ describe 'Custom issue templates' do
+ let(:template_name) { 'custom_issue_template'}
+ let(:template_content) { 'This is a custom issue template test' }
+
+ let(:template_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = "custom-issue-template-project"
+ project.initialize_with_readme = true
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = template_project
+ commit.commit_message = 'Add custom issue template'
+ commit.add_files([
+ {
+ file_path: ".gitlab/issue_templates/#{template_name}.md",
+ content: template_content
+ }
+ ])
+ end
+ end
+
+ it 'creates an issue via custom template', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1229' do
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
+ issue.project = template_project
+ issue.template = template_name
+ end
+
+ Page::Project::Issue::Show.perform do |issue_page|
+ expect(issue_page).to have_content(template_content)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
index c1113e7ec35..a23474ad6f2 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
@@ -24,7 +24,7 @@ module QA
Page::Project::Menu.perform(&:click_issues)
end
- it 'successfully exports issues list as CSV', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/764' do
+ it 'successfully exports issues list as CSV', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1141' do
Page::Project::Issue::Index.perform do |index|
index.click_export_as_csv_button
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
index 7c675862e26..ff33f9d4824 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
@@ -13,7 +13,7 @@ module QA
end.project.visit!
end
- it 'shows issue suggestions when creating a new issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/412' do
+ it 'shows issue suggestions when creating a new issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1175' do
Page::Project::Show.perform(&:go_to_new_issue)
Page::Project::Issue::New.perform do |new_page|
new_page.fill_title("issue")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
index 42b3e5364b7..1455847277e 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
@@ -39,27 +39,22 @@ module QA
private
def set_up_jira_integration
- # Retry is required because allow_local_requests_from_web_hooks_and_services
- # takes some time to get enabled.
- # Bug issue: https://gitlab.com/gitlab-org/gitlab/-/issues/217010
- QA::Support::Retrier.retry_on_exception(max_attempts: 5, sleep_interval: 3) do
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
- page.visit Runtime::Scenario.gitlab_address
- Flow::Login.sign_in_unless_signed_in
+ page.visit Runtime::Scenario.gitlab_address
+ Flow::Login.sign_in_unless_signed_in
- project.visit!
+ project.visit!
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
- QA::Page::Project::Settings::Services::Jira.perform do |jira|
- jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
- end
-
- expect(page).not_to have_text("Url is blocked")
- expect(page).to have_text("Jira settings saved and active.")
+ QA::Page::Project::Settings::Services::Jira.perform do |jira|
+ jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
end
+
+ expect(page).not_to have_text("Url is blocked")
+ expect(page).to have_text("Jira settings saved and active.")
end
def import_jira_issues
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
index 5a8c9a4601a..cc815fd0e67 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
@@ -21,7 +21,7 @@ module QA
end.visit!
end
- it 'mentions another user in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/446' do
+ it 'mentions another user in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1166' do
Page::Project::Issue::Show.perform do |show|
at_username = "@#{user.username}"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
index 7f60726af0e..8f17a25012b 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
@@ -13,7 +13,7 @@ module QA
Flow::Login.sign_in
end
- it 'focuses on issue board', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/820' do
+ it 'focuses on issue board', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1176' do
project.visit!
Page::Project::Menu.perform(&:go_to_boards)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
index 564cfbb8399..8c328abcbe9 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a group milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/922' do
+ it 'creates a group milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1148' do
group_milestone = Resource::GroupMilestone.fabricate_via_browser_ui! do |milestone|
milestone.title = title
milestone.description = description
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
index 99d547acb26..78d1471f484 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a project milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/901' do
+ it 'creates a project milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1165' do
project_milestone = Resource::ProjectMilestone.fabricate_via_browser_ui! do |milestone|
milestone.title = title
milestone.description = description
diff --git a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
index 6a133540f87..d907cfaab6d 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
@@ -25,7 +25,7 @@ module QA
Flow::Login.sign_in
end
- it 'relates and unrelates one issue to/from another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/541' do
+ it 'relates and unrelates one issue to/from another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1172' do
issue_1.visit!
Page::Project::Issue::Show.perform do |show|
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 051e8fcecbe..2e48899742b 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/quality/testcases/-/issues/955' do
+ it 'user adds a design and annotates it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1692' do
issue.visit!
Page::Project::Issue::Show.perform do |issue|
diff --git a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
index d53e7fcf69a..449795f9707 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
@@ -19,26 +19,21 @@ module QA
page.has_text? 'Welcome to Jira'
end
- # Retry is required because allow_local_requests_from_web_hooks_and_services
- # takes some time to get enabled.
- # Bug issue: https://gitlab.com/gitlab-org/gitlab/-/issues/217010
- QA::Support::Retrier.retry_on_exception(max_attempts: 5, sleep_interval: 3) do
- Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
- page.visit Runtime::Scenario.gitlab_address
- Flow::Login.sign_in_unless_signed_in
+ page.visit Runtime::Scenario.gitlab_address
+ Flow::Login.sign_in_unless_signed_in
- project.visit!
+ project.visit!
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ QA::Page::Project::Settings::Integrations.perform(&:click_jira_link)
- QA::Page::Project::Settings::Services::Jira.perform do |jira|
- jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
- end
-
- expect(page).not_to have_text("Requests to the local network are not allowed")
+ QA::Page::Project::Settings::Services::Jira.perform do |jira|
+ jira.setup_service_with(url: Vendor::Jira::JiraAPI.perform(&:base_url))
end
+
+ expect(page).not_to have_text("Requests to the local network are not allowed")
end
it 'closes an issue via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/827' do
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index 510fc0c9a16..81ad1896075 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -16,7 +16,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a basic merge request', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/409' do
+ it 'creates a basic merge request', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1276' do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = project
merge_request.title = merge_request_title
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb
new file mode 100644
index 00000000000..d8341eff41d
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Merge request custom templates' do
+ let(:template_name) { 'custom_merge_request_template'}
+ let(:template_content) { 'This is a custom merge request template test' }
+ let(:template_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'custom-mr-template-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ let(:merge_request_title) { 'One merge request to rule them all' }
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = template_project
+ commit.commit_message = 'Add custom merge request template'
+ commit.add_files([
+ {
+ file_path: ".gitlab/merge_request_templates/#{template_name}.md",
+ content: template_content
+ }
+ ])
+ end
+ end
+
+ it 'creates a merge request via custom template', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1230' do
+ Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
+ merge_request.project = template_project
+ merge_request.title = merge_request_title
+ merge_request.template = template_name
+ merge_request.target_new_branch = false
+ end
+
+ Page::MergeRequest::Show.perform do |merge_request|
+ expect(merge_request).to have_title(merge_request_title)
+ expect(merge_request).to have_description(template_content)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index 823a033ab6d..3414584bae3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/30226', type: :bug } do
describe 'Merge request rebasing' do
- it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/398' do
+ it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1274' do
Flow::Login.sign_in
project = Resource::Project.fabricate_via_api! do |project|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
index 5b1c15016bf..d11afde5648 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
@@ -15,7 +15,7 @@ module QA
merge_request.visit!
end
- it 'views the merge request email patches', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/416' do
+ it 'views the merge request email patches', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1689' do
Page::MergeRequest::Show.perform(&:view_email_patches)
expect(page.text).to start_with('From')
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index 8df68e0f53b..d400876c838 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -59,7 +59,7 @@ module QA
project.visit!
end
- it 'lists branches correctly after CRUD operations', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/413' do
+ it 'lists branches correctly after CRUD operations', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1688' do
Page::Project::Menu.perform(&:go_to_repository_branches)
expect(page).to have_content(master_branch)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
index 47117c4d456..9edde7ac12f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
@@ -14,10 +14,12 @@ module QA
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
+ repository.default_branch = project.default_branch
repository.act do
clone
configure_identity('GitLab QA', 'root@gitlab.com')
+ checkout(default_branch, new_branch: true)
commit_file('test.rb', 'class Test; end', 'Add Test class')
commit_file('README.md', '# Test', 'Add Readme')
push_changes
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
index 5781bf8a7f0..3440b462302 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
@@ -26,6 +26,8 @@ module QA
repository.use_default_credentials
repository.clone
repository.configure_identity(username, email)
+ repository.default_branch = project.default_branch
+ repository.checkout(project.default_branch, new_branch: true)
git_protocol_reported = repository.push_with_git_protocol(
git_protocol,
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
index 8d966c9e46d..38c9216005f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
@@ -49,6 +49,8 @@ module QA
repository.use_ssh_key(ssh_key)
repository.clone
repository.configure_identity(username, email)
+ repository.default_branch = project.default_branch
+ repository.checkout(project.default_branch, new_branch: true)
git_protocol_reported = repository.push_with_git_protocol(
git_protocol,
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
index 08af18a992e..35ec2135491 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP', :ldap_no_tls, :smoke do
- it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/430' do
+ it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1278' do
Flow::Login.sign_in
access_token = Resource::PersonalAccessToken.fabricate!.access_token
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
index 5e7c17cbfaf..c56e6d1267c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
@@ -26,7 +26,7 @@ module QA
Flow::Login.sign_in
end
- it 'pushes code to the repository via SSH', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/969' do
+ it 'pushes code to the repository via SSH', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1678' do
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.ssh_key = @key
@@ -41,7 +41,8 @@ module QA
end
end
- it 'pushes multiple branches and tags together', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/970' do
+ it 'pushes multiple branches and tags together', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1679
+ ' do
branches = []
tags = []
Git::Repository.perform do |repository|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
index 2001069c2a4..a90bb920107 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'user can add an SSH key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/929' do
+ it 'user can add an SSH key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1685' do
key = Resource::SSHKey.fabricate_via_browser_ui! do |resource|
resource.title = key_title
end
@@ -20,8 +20,8 @@ module QA
# Note this context ensures that the example it contains is executed after the example above. Be aware of the order of execution if you add new examples in either context.
context 'after adding an ssh key' do
- it 'can delete an ssh key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/930' do
- Page::Main::Menu.perform(&:click_settings_link)
+ it 'can delete an ssh key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1686' do
+ Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_ssh_keys)
Page::Profile::SSHKeys.perform do |ssh_keys|
ssh_keys.remove_key(key.title)
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 469335db5ab..604c98ca21e 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Multiple file snippet' do
+ describe 'Multiple file snippet', quarantine: { only: { pipeline: :master }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
let(:personal_snippet) do
Resource::Snippet.fabricate_via_api! do |snippet|
snippet.title = 'Personal snippet to add file to'
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
index a21c5d58aad..2940b2067a1 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Version control for personal snippets' do
+ describe 'Version control for personal snippets', quarantine: { only: { pipeline: :master }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
let(:commit_message) { 'Changes to snippets' }
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
index 4ce6c3fdcd3..b91424d5b65 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Version control for project snippets' do
+ describe 'Version control for project snippets', quarantine: { only: { pipeline: :master }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
let(:commit_message) { 'Changes to snippets' }
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 8002e95cf0d..5c0983dabb6 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Multiple file snippet' do
+ describe 'Multiple file snippet', quarantine: { only: { pipeline: :master }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
let(:personal_snippet) do
Resource::Snippet.fabricate_via_api! do |snippet|
snippet.title = 'Personal snippet to delete file from'
diff --git a/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb
new file mode 100644
index 00000000000..eab2729af83
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/transient/apply_suggestion_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ context 'Transient tests', :transient do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-for-transient-test'
+ end
+ end
+
+ let(:code_for_merge) do
+ Pathname
+ .new(__dir__)
+ .join('../../../../../fixtures/metrics_dashboards/templating.yml')
+ end
+
+ let(:merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.project = project
+ merge_request.title = 'Transient MR'
+ merge_request.description = 'detecting transient bugs'
+ merge_request.file_content = File.read(code_for_merge)
+ end
+ end
+
+ let(:dev_user) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
+
+ before do
+ project.add_member(dev_user)
+ Flow::Login.sign_in(as: dev_user, skip_page_validation: true)
+
+ merge_request.visit!
+
+ Page::MergeRequest::Show.perform(&:click_diffs_tab)
+
+ [4, 6, 10, 13].each do |line_number|
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.add_suggestion_to_diff("This is the #{line_number} suggestion!", line_number)
+ end
+ end
+
+ Flow::Login.sign_in
+
+ merge_request.visit!
+ end
+
+ it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1177' do
+ Page::MergeRequest::Show.perform do |merge_request|
+ merge_request.click_diffs_tab
+ 4.times { merge_request.add_suggestion_to_batch }
+ merge_request.apply_suggestions_batch
+
+ expect(merge_request).to have_css('.badge-success', text: "Applied", count: 4)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
new file mode 100644
index 00000000000..293c9043266
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Add a directory in Web IDE' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'add-directory-project'
+ project.initialize_with_readme = true
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ project.visit!
+ end
+
+ context 'when a directory with the same name already exists' do
+ let(:directory_name) { 'first_directory' }
+
+ before do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.add_files([
+ {
+ file_path: 'first_directory/test_file.txt',
+ content: "Test file content"
+ }
+ ])
+ end
+
+ project.visit!
+
+ Page::Project::Show.perform(&:open_web_ide!)
+ end
+
+ it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1615' do
+ Page::Project::WebIDE::Edit.perform do |ide|
+ ide.add_directory(directory_name)
+ end
+
+ expect(page).to have_content('The name "first_directory" is already taken in this directory.')
+ end
+ end
+
+ context 'when user adds a new empty directory' do
+ let(:directory_name) { 'new_empty_directory' }
+
+ before do
+ Page::Project::Show.perform(&:open_web_ide!)
+ end
+
+ it 'shows in the tree view but cannot be committed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1614' do
+ Page::Project::WebIDE::Edit.perform do |ide|
+ ide.add_directory(directory_name)
+
+ expect(ide).to have_file(directory_name)
+ expect(ide).to have_folder_icon(directory_name)
+ expect(ide).not_to have_file_addition_icon(directory_name)
+
+ ide.switch_to_commit_tab
+
+ expect(ide).not_to have_file_to_commit(directory_name)
+ end
+ end
+ end
+ end
+ end
+end
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 dad5ad74a4c..ce1b6f4a3ec 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
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Open a fork in Web IDE', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/284081', type: :investigating } do
+ describe 'Open a fork in Web IDE' do
let(:parent_project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'parent-project'
@@ -14,7 +14,7 @@ module QA
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
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/quality/testcases/-/issues/959' do
+ it 'suggests to create a fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1697' do
Flow::Login.sign_in(as: user)
parent_project.visit!
@@ -34,7 +34,7 @@ module QA
end
end
- it 'opens the fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/960' do
+ it 'opens the fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1698' do
Flow::Login.sign_in(as: user)
fork_project.upstream.visit!
Page::Project::Show.perform do |project_page|
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb
new file mode 100644
index 00000000000..1789e20e216
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Open Web IDE from Diff Tab' do
+ files = [
+ {
+ file_path: 'file1',
+ content: 'test1'
+ },
+ {
+ file_path: 'file2',
+ content: 'test2'
+ },
+ {
+ file_path: 'file3',
+ content: 'test3'
+ }
+ ]
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.initialize_with_readme = true
+ end
+ end
+
+ let(:source) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.branch = 'new-mr'
+ commit.start_branch = project.default_branch
+ commit.commit_message = 'Add new files'
+ commit.add_files(files)
+ end
+ end
+
+ let(:merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |mr|
+ mr.source = source
+ mr.project = project
+ mr.source_branch = 'new-mr'
+ mr.target_new_branch = false
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ merge_request.visit!
+ end
+
+ it 'opens and edits a multi-file merge request in Web IDE from Diff Tab', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/997' do
+ Page::MergeRequest::Show.perform do |show|
+ show.click_diffs_tab
+ show.edit_file_in_web_ide('file1')
+ end
+
+ Page::Project::WebIDE::Edit.perform do |ide|
+ files.each do |files|
+ expect(ide).to have_file(files[:file_path])
+ expect(ide).to have_file_content(files[:file_path], files[:content])
+ end
+
+ ide.delete_file('file1')
+ ide.commit_changes
+ end
+
+ merge_request.visit!
+
+ Page::MergeRequest::Show.perform do |show|
+ show.click_diffs_tab
+
+ expect(show).not_to have_file('file1')
+ expect(show).to have_file('file2')
+ expect(show).to have_file('file3')
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
index d62f894279f..0a342664dd2 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
@@ -22,7 +22,7 @@ module QA
context 'when a file with the same name already exists' do
let(:file_name) { 'README.md' }
- it 'throws an error' do
+ it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1136' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
end
@@ -34,7 +34,7 @@ module QA
context 'when the file is a text file' do
let(:file_name) { 'text_file.txt' }
- it 'shows the Edit tab with the text' do
+ it 'shows the Edit tab with the text', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1138' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
@@ -52,7 +52,7 @@ module QA
context 'when the file is binary' do
let(:file_name) { 'logo_sample.svg' }
- it 'shows a Download button' do
+ it 'shows a Download button', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1137' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
@@ -70,7 +70,7 @@ module QA
context 'when the file is an image' do
let(:file_name) { 'dk.png' }
- it 'shows an image viewer' do
+ it 'shows an image viewer', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1139' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb
new file mode 100644
index 00000000000..5b976ae4126
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require 'faker'
+
+module QA
+ RSpec.describe 'Verify', :runner do
+ describe 'Pipeline with protected variable' do
+ let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
+ let(:protected_value) { Faker::Alphanumeric.alphanumeric(8) }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-with-ci-variables'
+ project.description = 'project with CI variables'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = executor
+ runner.tags = [executor]
+ 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
+ job:
+ tags:
+ - #{executor}
+ script: echo $PROTECTED_VARIABLE
+ YAML
+ }
+ ]
+ )
+ end
+ end
+
+ let(:developer) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
+
+ let(:maintainer) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2)
+ end
+
+ before do
+ Flow::Login.sign_in
+ project.visit!
+ project.add_member(developer)
+ project.add_member(maintainer, Resource::Members::AccessLevel::MAINTAINER)
+ add_ci_variable
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'exposes variable on protected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/156' do
+ create_protected_branch
+
+ [developer, maintainer].each do |user|
+ user_commit_to_protected_branch(Runtime::API::Client.new(:gitlab, user: user))
+ go_to_pipeline_job(user)
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show.output).to have_content(protected_value), 'Expect protected variable to be in job log.'
+ end
+ end
+ end
+
+ it 'does not expose variable on unprotected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/156' do
+ [developer, maintainer].each do |user|
+ create_merge_request(Runtime::API::Client.new(:gitlab, user: user))
+ go_to_pipeline_job(user)
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show.output).to have_no_content(protected_value), 'Expect protected variable to NOT be in job log.'
+ end
+ end
+ end
+
+ private
+
+ def add_ci_variable
+ Resource::CiVariable.fabricate_via_api! do |ci_variable|
+ ci_variable.project = project
+ ci_variable.key = 'PROTECTED_VARIABLE'
+ ci_variable.value = protected_value
+ ci_variable.protected = true
+ end
+ end
+
+ def create_protected_branch
+ # Using default setups, which allows access for developer and maintainer
+ Resource::ProtectedBranch.fabricate_via_api! do |resource|
+ resource.branch_name = 'protected-branch'
+ resource.project = project
+ end
+ end
+
+ def user_commit_to_protected_branch(api_client)
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = api_client
+ commit.project = project
+ commit.branch = 'protected-branch'
+ commit.commit_message = Faker::Lorem.sentence
+ commit.add_files(
+ [
+ {
+ file_path: "#{Faker::Lorem.word}.txt",
+ content: Faker::Lorem.sentence
+ }
+ ]
+ )
+ end
+ end
+
+ def create_merge_request(api_client)
+ Resource::MergeRequest.fabricate_via_api! do |merge_request|
+ merge_request.api_client = api_client
+ merge_request.project = project
+ merge_request.description = Faker::Lorem.sentence
+ merge_request.target_new_branch = false
+ merge_request.file_name = "#{Faker::Lorem.word}.txt"
+ merge_request.file_content = Faker::Lorem.sentence
+ end
+ end
+
+ def go_to_pipeline_job(user)
+ Flow::Login.sign_in(as: user)
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('job')
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index 1e6cb4047f9..8617e05f912 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -24,7 +24,7 @@ module QA
runner.remove_via_api!
end
- it 'users creates a pipeline which gets processed', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/391' do
+ it 'users creates a pipeline which gets processed', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1279' do
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|
diff --git a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
index be6f3b17ccd..6c1a0cea209 100644
--- a/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/composer_registry_spec.rb
@@ -104,9 +104,7 @@ module QA
index.click_package(package_name)
end
- Page::Project::Packages::Show.perform do |package|
- package.click_delete
- end
+ Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
aggregate_failures 'package deletion' do
diff --git a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
index ae0580ff51b..7effefc4d73 100644
--- a/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/conan_repository_spec.rb
@@ -75,9 +75,7 @@ module QA
index.click_package(package_name)
end
- Page::Project::Packages::Show.perform do |package|
- package.click_delete
- end
+ Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully")
diff --git a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
index 9a0d832de09..3e3addf9eeb 100644
--- a/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/generic_repository_spec.rb
@@ -100,9 +100,7 @@ module QA
index.click_package(package_name)
end
- Page::Project::Packages::Show.perform do |package|
- package.click_delete
- end
+ Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
aggregate_failures 'package deletion' do
diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
index 552302addf9..6ab4a957c57 100644
--- a/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/maven_gradle_repository_spec.rb
@@ -112,9 +112,7 @@ module QA
index.click_package(package_name)
end
- Page::Project::Packages::Show.perform do |show|
- show.click_delete
- end
+ Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully")
diff --git a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
index be806fcbb3e..8c3f0930207 100644
--- a/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/nuget_repository_spec.rb
@@ -13,6 +13,13 @@ module QA
end
end
+ let(:another_project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'nuget-package-install-project'
+ project.template_name = 'dotnetcore'
+ end
+ end
+
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}"
@@ -22,11 +29,21 @@ module QA
end
end
+ let!(:another_runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.name = "qa-runner-#{Time.now.to_i}"
+ runner.tags = ["runner-for-#{another_project.name}"]
+ runner.executor = :docker
+ runner.project = another_project
+ end
+ end
+
after do
runner.remove_via_api!
+ another_runner.remove_via_api!
end
- it 'publishes a nuget package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do
+ it 'publishes a nuget package at the project level, installs and deletes it at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|
@@ -37,23 +54,23 @@ module QA
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
- image: mcr.microsoft.com/dotnet/core/sdk:3.1
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - dotnet restore -p:Configuration=Release
- - dotnet build -c Release
- - dotnet pack -c Release
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
- only:
- - "#{project.default_branch}"
- tags:
- - "runner-for-#{project.name}"
+ image: mcr.microsoft.com/dotnet/core/sdk:3.1
+
+ stages:
+ - deploy
+
+ deploy:
+ stage: deploy
+ script:
+ - dotnet restore -p:Configuration=Release
+ - dotnet build -c Release
+ - dotnet pack -c Release
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
+ - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
+ only:
+ - "#{project.default_branch}"
+ tags:
+ - "runner-for-#{project.name}"
YAML
}
]
@@ -71,16 +88,74 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Page::Project::Menu.perform(&:click_packages_link)
+ another_project.visit!
+
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = another_project
+ commit.commit_message = 'Add new csproj file'
+ commit.add_files(
+ [
+ {
+ file_path: 'otherdotnet.csproj',
+ content: <<~EOF
+ <Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>netcoreapp3.1</TargetFramework>
+ </PropertyGroup>
+
+ </Project>
+ EOF
+ }
+ ]
+ )
+ commit.update_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ image: mcr.microsoft.com/dotnet/core/sdk:3.1
+
+ 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 gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
+ - "dotnet add otherdotnet.csproj package #{package_name} --version 1.0.0"
+ only:
+ - "#{another_project.default_branch}"
+ tags:
+ - "runner-for-#{another_project.name}"
+ YAML
+ }
+ ]
+ )
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('install')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ project.group.sandbox.visit!
+
+ Page::Group::Menu.perform(&:go_to_group_packages)
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 do |package|
- package.click_delete
- end
+ Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully")
diff --git a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
index d5eca171d6c..396863b33c4 100644
--- a/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/pypi_repository_spec.rb
@@ -98,9 +98,7 @@ module QA
index.click_package(package_name)
end
- Page::Project::Packages::Show.perform do |package|
- package.click_delete
- end
+ Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index|
aggregate_failures do
diff --git a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
index 17c53b3ddc9..5ea7a7bb4cb 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
@@ -30,7 +30,7 @@ module QA
pipeline.visit!
end
- it 'runs a Pages-specific pipeline', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/296937' do
+ it 'runs a Pages-specific pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/877' do
Page::Project::Pipeline::Show.perform do |show|
expect(show).to have_job(:pages)
show.click_job(:pages)
diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
index 9ec05fcf5d3..0ef3715db5e 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
@@ -25,7 +25,7 @@ module QA
runner.remove_via_api!
end
- it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/751' do
+ it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1153' do
add_ci_files(success_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
@@ -35,7 +35,7 @@ module QA
end
end
- it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/752' do
+ it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1152' do
add_ci_files(fail_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
index ed8c8baae0e..6c7ab9f2f72 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
@@ -25,7 +25,7 @@ module QA
runner.remove_via_api!
end
- it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/754' do
+ it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1161' do
add_ci_files(success_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
@@ -35,7 +35,7 @@ module QA
end
end
- it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/753' do
+ it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1162' do
add_ci_files(fail_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index a619ccfad19..171a4776eaf 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -117,7 +117,7 @@ module QA
end
end
- it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/444' do
+ it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1277' do
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index 9027f17678d..04eaa02bda5 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -37,7 +37,7 @@ module QA
if tags.any?
tags.each { |tag| tags_for_rspec.push(['--tag', tag.to_s]) }
else
- tags_for_rspec.push(%w[--tag ~orchestrated]) unless (%w[-t --tag] & options).any?
+ tags_for_rspec.push(%w[--tag ~orchestrated --tag ~transient]) unless (%w[-t --tag] & options).any?
end
tags_for_rspec.push(%w[--tag ~geo]) unless QA::Runtime::Env.geo_environment?
diff --git a/qa/qa/tools/revoke_all_personal_access_tokens.rb b/qa/qa/tools/revoke_all_personal_access_tokens.rb
index e33d522bece..0aaf1ed6f7f 100644
--- a/qa/qa/tools/revoke_all_personal_access_tokens.rb
+++ b/qa/qa/tools/revoke_all_personal_access_tokens.rb
@@ -27,7 +27,7 @@ module QA
Runtime::Browser.visit(ENV['GITLAB_ADDRESS'], Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
- Page::Main::Menu.perform(&:click_settings_link)
+ Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_access_tokens)
token_name = 'api-test-token'
diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb
index b11054f0bd9..642d9e0745b 100644
--- a/qa/spec/specs/runner_spec.rb
+++ b/qa/spec/specs/runner_spec.rb
@@ -3,9 +3,9 @@
require 'active_support/core_ext/hash'
RSpec.describe QA::Specs::Runner do
- shared_examples 'excludes orchestrated and geo' do
- it 'excludes the orchestrated and geo tags and includes default args' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
+ shared_examples 'excludes orchestrated, transient, and geo' do
+ it 'excludes the orchestrated, transient, and geo tags, and includes default args' do
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
@@ -18,13 +18,13 @@ RSpec.describe QA::Specs::Runner do
QA::Runtime::Scenario.define(:gitlab_address, "http://gitlab.test")
end
- it_behaves_like 'excludes orchestrated and geo'
+ it_behaves_like 'excludes orchestrated, transient, and geo'
context 'when tty is set' do
subject { described_class.new.tap { |runner| runner.tty = true } }
it 'sets the `--tty` flag' do
- expect_rspec_runner_arguments(['--tty', '--tag', '~orchestrated', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
+ expect_rspec_runner_arguments(['--tty', '--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
@@ -43,7 +43,7 @@ RSpec.describe QA::Specs::Runner do
context 'when "--tag smoke" is set as options' do
subject { described_class.new.tap { |runner| runner.options = %w[--tag smoke] } }
- it 'focuses on the given tag without excluded the orchestrated tag' do
+ it 'focuses on the given tag without excluded tags' do
expect_rspec_runner_arguments(['--tag', '~geo', '--tag', 'smoke', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
@@ -53,8 +53,8 @@ RSpec.describe QA::Specs::Runner do
context 'when "qa/specs/features/foo" is set as options' do
subject { described_class.new.tap { |runner| runner.options = %w[qa/specs/features/foo] } }
- it 'passes the given tests path and excludes the orchestrated and geo tags' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', 'qa/specs/features/foo'])
+ it 'passes the given tests path and excludes the orchestrated, transient, and geo tags' do
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', 'qa/specs/features/foo'])
subject.perform
end
@@ -63,7 +63,7 @@ RSpec.describe QA::Specs::Runner do
context 'when "--tag smoke" and "qa/specs/features/foo" are set as options' do
subject { described_class.new.tap { |runner| runner.options = %w[--tag smoke qa/specs/features/foo] } }
- it 'focuses on the given tag and includes the path without excluding the orchestrated tag' do
+ it 'focuses on the given tag and includes the path without excluding the orchestrated or transient tags' do
expect_rspec_runner_arguments(['--tag', '~geo', '--tag', 'smoke', 'qa/specs/features/foo'])
subject.perform
@@ -76,7 +76,7 @@ RSpec.describe QA::Specs::Runner do
end
it 'includes default args and excludes the skip_signup_disabled tag' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
@@ -88,7 +88,7 @@ RSpec.describe QA::Specs::Runner do
end
it 'includes default args and excludes the skip_live_env tag' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS])
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
end
@@ -121,7 +121,7 @@ RSpec.describe QA::Specs::Runner do
end
it 'includes default args and excludes all unsupported tags' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~geo', *excluded_feature_tags_except(feature), *described_class::DEFAULT_TEST_PATH_ARGS])
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~transient', '--tag', '~geo', *excluded_feature_tags_except(feature), *described_class::DEFAULT_TEST_PATH_ARGS])
subject.perform
end
@@ -146,11 +146,11 @@ RSpec.describe QA::Specs::Runner do
end
end
- it_behaves_like 'excludes orchestrated and geo'
+ it_behaves_like 'excludes orchestrated, transient, and geo'
end
context 'when features are not specified' do
- it_behaves_like 'excludes orchestrated and geo'
+ it_behaves_like 'excludes orchestrated, transient, and geo'
end
end
diff --git a/qa/spec/support/matchers/have_assignee.rb b/qa/spec/support/matchers/have_assignee.rb
deleted file mode 100644
index 5e7aa2162b2..00000000000
--- a/qa/spec/support/matchers/have_assignee.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveAssignee
- RSpec::Matchers.define :have_assignee do |assignee|
- match do |page_object|
- page_object.has_assignee?(assignee)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_assignee?(assignee)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_child_pipeline.rb b/qa/spec/support/matchers/have_child_pipeline.rb
deleted file mode 100644
index d05d9d4209a..00000000000
--- a/qa/spec/support/matchers/have_child_pipeline.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveChildPipeline
- RSpec::Matchers.define :have_child_pipeline do
- match do |page_object|
- page_object.has_child_pipeline?
- end
-
- match_when_negated do |page_object|
- page_object.has_no_child_pipeline?
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_content.rb b/qa/spec/support/matchers/have_content.rb
deleted file mode 100644
index 66b30b3b6e4..00000000000
--- a/qa/spec/support/matchers/have_content.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveContent
- RSpec::Matchers.define :have_content do |content|
- match do |page_object|
- page_object.has_content?(content)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_content?(content)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_design.rb b/qa/spec/support/matchers/have_design.rb
deleted file mode 100644
index 85f1367297a..00000000000
--- a/qa/spec/support/matchers/have_design.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveDesign
- RSpec::Matchers.define :have_design do |design|
- match do |page_object|
- page_object.has_design?(design)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_design?(design)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_element.rb b/qa/spec/support/matchers/have_element.rb
deleted file mode 100644
index bf74a78a3b5..00000000000
--- a/qa/spec/support/matchers/have_element.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveElement
- RSpec::Matchers.define :have_element do |element, **kwargs|
- match do |page_object|
- page_object.has_element?(element, **kwargs)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_element?(element, **kwargs)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_file.rb b/qa/spec/support/matchers/have_file.rb
deleted file mode 100644
index 2ae295d5ca2..00000000000
--- a/qa/spec/support/matchers/have_file.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveFile
- RSpec::Matchers.define :have_file do |file|
- match do |page_object|
- page_object.has_file?(file)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_file?(file)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_file_content.rb b/qa/spec/support/matchers/have_file_content.rb
deleted file mode 100644
index e42ece6d59e..00000000000
--- a/qa/spec/support/matchers/have_file_content.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveFileContent
- RSpec::Matchers.define :have_file_content do |file_content, file_number|
- match do |page_object|
- page_object.has_file_content?(file_content, file_number)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_file_content?(file_content, file_number)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_issue.rb b/qa/spec/support/matchers/have_issue.rb
deleted file mode 100644
index 7ef30f22726..00000000000
--- a/qa/spec/support/matchers/have_issue.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveIssue
- RSpec::Matchers.define :have_issue do |issue|
- match do |page_object|
- page_object.has_issue?(issue)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_issue?(issue)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_job.rb b/qa/spec/support/matchers/have_job.rb
deleted file mode 100644
index 89829915fce..00000000000
--- a/qa/spec/support/matchers/have_job.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveJob
- RSpec::Matchers.define :have_job do |job|
- match do |page_object|
- page_object.has_job?(job)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_job?(job)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_matcher.rb b/qa/spec/support/matchers/have_matcher.rb
new file mode 100644
index 00000000000..43ae27f8796
--- /dev/null
+++ b/qa/spec/support/matchers/have_matcher.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Matchers
+ PREDICATE_TARGETS = %w[
+ element
+ file_content
+ assignee
+ child_pipeline
+ content
+ design
+ file
+ issue
+ job
+ package
+ pipeline
+ related_issue_item
+ snippet_description
+ ].each do |predicate|
+ RSpec::Matchers.define "have_#{predicate}" do |*args, **kwargs|
+ match do |page_object|
+ page_object.public_send("has_#{predicate}?", *args, **kwargs) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ match_when_negated do |page_object|
+ page_object.public_send("has_no_#{predicate}?", *args, **kwargs) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+end
diff --git a/qa/spec/support/matchers/have_package.rb b/qa/spec/support/matchers/have_package.rb
deleted file mode 100644
index 86e9bfee4d1..00000000000
--- a/qa/spec/support/matchers/have_package.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HavePackage
- RSpec::Matchers.define :have_package do |package|
- match do |page_object|
- page_object.has_package?(package)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_package?(package)
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_pipeline.rb b/qa/spec/support/matchers/have_pipeline.rb
deleted file mode 100644
index 2bfd49d671a..00000000000
--- a/qa/spec/support/matchers/have_pipeline.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HavePipeline
- RSpec::Matchers.define :have_pipeline do
- match do |page_object|
- page_object.has_pipeline?
- end
-
- match_when_negated do |page_object|
- page_object.has_no_pipeline?
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_related_issue_item.rb b/qa/spec/support/matchers/have_related_issue_item.rb
deleted file mode 100644
index 89403f2422a..00000000000
--- a/qa/spec/support/matchers/have_related_issue_item.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveRelatedIssueItem
- RSpec::Matchers.define :have_related_issue_item do
- match do |page_object|
- page_object.has_related_issue_item?
- end
-
- match_when_negated do |page_object|
- page_object.has_no_related_issue_item?
- end
- end
- end
-end
diff --git a/qa/spec/support/matchers/have_snippet_description.rb b/qa/spec/support/matchers/have_snippet_description.rb
deleted file mode 100644
index 7c407aefc83..00000000000
--- a/qa/spec/support/matchers/have_snippet_description.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Matchers
- module HaveSnippetDescription
- RSpec::Matchers.define :have_snippet_description do |description|
- match do |page_object|
- page_object.has_snippet_description?(description)
- end
-
- match_when_negated do |page_object|
- page_object.has_no_snippet_description?
- end
- end
- end
-end
diff --git a/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb b/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb
index eba38c1630f..e1c6a984e75 100644
--- a/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb
+++ b/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RuboCop
module Cop
# Cop that blacklists keyword arguments usage in Sidekiq workers
diff --git a/rubocop/cop/gitlab/finder_with_find_by.rb b/rubocop/cop/gitlab/finder_with_find_by.rb
index 764a5073143..8fa9fe4a2f9 100644
--- a/rubocop/cop/gitlab/finder_with_find_by.rb
+++ b/rubocop/cop/gitlab/finder_with_find_by.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RuboCop
module Cop
module Gitlab
diff --git a/rubocop/cop/gitlab/httparty.rb b/rubocop/cop/gitlab/httparty.rb
index 8acebff624d..20f0c381e11 100644
--- a/rubocop/cop/gitlab/httparty.rb
+++ b/rubocop/cop/gitlab/httparty.rb
@@ -4,13 +4,13 @@ module RuboCop
module Cop
module Gitlab
class HTTParty < RuboCop::Cop::Cop
- MSG_SEND = <<~EOL.freeze
+ MSG_SEND = <<~EOL
Avoid calling `HTTParty` directly. Instead, use the Gitlab::HTTP
wrapper. To allow request to localhost or the private network set
the option :allow_local_requests in the request call.
EOL
- MSG_INCLUDE = <<~EOL.freeze
+ MSG_INCLUDE = <<~EOL
Avoid including `HTTParty` directly. Instead, use the Gitlab::HTTP
wrapper. To allow request to localhost or the private network set
the option :allow_local_requests in the request call.
diff --git a/rubocop/cop/gitlab/json.rb b/rubocop/cop/gitlab/json.rb
index 8c9027223aa..7cc719aca09 100644
--- a/rubocop/cop/gitlab/json.rb
+++ b/rubocop/cop/gitlab/json.rb
@@ -4,7 +4,7 @@ module RuboCop
module Cop
module Gitlab
class Json < RuboCop::Cop::Cop
- MSG_SEND = <<~EOL.freeze
+ MSG = <<~EOL
Avoid calling `JSON` directly. Instead, use the `Gitlab::Json`
wrapper. This allows us to alter the JSON parser being used.
EOL
@@ -14,7 +14,7 @@ module RuboCop
PATTERN
def on_send(node)
- add_offense(node, location: :expression, message: MSG_SEND) if json_node?(node)
+ add_offense(node) if json_node?(node)
end
def autocorrect(node)
diff --git a/rubocop/cop/gitlab/keys-first-and-values-first.rb b/rubocop/cop/gitlab/keys-first-and-values-first.rb
index 544f9800304..e9bf266cdd7 100644
--- a/rubocop/cop/gitlab/keys-first-and-values-first.rb
+++ b/rubocop/cop/gitlab/keys-first-and-values-first.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RuboCop
module Cop
module Gitlab
diff --git a/rubocop/cop/gitlab/module_with_instance_variables.rb b/rubocop/cop/gitlab/module_with_instance_variables.rb
index dd8bd2dfdf0..40cdc0d3a57 100644
--- a/rubocop/cop/gitlab/module_with_instance_variables.rb
+++ b/rubocop/cop/gitlab/module_with_instance_variables.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module RuboCop
module Cop
module Gitlab
class ModuleWithInstanceVariables < RuboCop::Cop::Cop
- MSG = <<~EOL.freeze
+ MSG = <<~EOL
Do not use instance variables in a module. Please read this
for the rationale behind it:
diff --git a/rubocop/cop/gitlab/namespaced_class.rb b/rubocop/cop/gitlab/namespaced_class.rb
new file mode 100644
index 00000000000..1f1fd280922
--- /dev/null
+++ b/rubocop/cop/gitlab/namespaced_class.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that enforces use of namespaced classes in order to better identify
+ # high level domains within the codebase.
+
+ # @example
+ # # bad
+ # class MyClass
+ # end
+ #
+ # # good
+ # module MyDomain
+ # class MyClass
+ # end
+ # end
+
+ class NamespacedClass < RuboCop::Cop::Cop
+ MSG = 'Classes must be declared inside a module indicating a product domain namespace. For more info: https://gitlab.com/gitlab-org/gitlab/-/issues/212156'
+
+ def_node_matcher :compact_namespaced_class?, <<~PATTERN
+ (class (const (const ...) ...) ...)
+ PATTERN
+
+ def on_module(node)
+ @namespaced = true
+ end
+
+ def on_class(node)
+ return if @namespaced
+
+ add_offense(node) unless compact_namespaced_class?(node)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/predicate_memoization.rb b/rubocop/cop/gitlab/predicate_memoization.rb
index 3c25d61d087..4c851f90238 100644
--- a/rubocop/cop/gitlab/predicate_memoization.rb
+++ b/rubocop/cop/gitlab/predicate_memoization.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module RuboCop
module Cop
module Gitlab
class PredicateMemoization < RuboCop::Cop::Cop
- MSG = <<~EOL.freeze
+ MSG = <<~EOL
Avoid using `@value ||= query` inside predicate methods in order to
properly memoize `false` or `nil` values.
https://docs.gitlab.com/ee/development/utilities.html#strongmemoize
@@ -12,7 +14,7 @@ module RuboCop
return unless predicate_method?(node)
select_offenses(node).each do |offense|
- add_offense(offense, location: :expression)
+ add_offense(offense)
end
end
diff --git a/rubocop/cop/migration/add_concurrent_foreign_key.rb b/rubocop/cop/migration/add_concurrent_foreign_key.rb
index 31cf426b2d4..957bd30af63 100644
--- a/rubocop/cop/migration/add_concurrent_foreign_key.rb
+++ b/rubocop/cop/migration/add_concurrent_foreign_key.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/add_concurrent_index.rb b/rubocop/cop/migration/add_concurrent_index.rb
index a2e4ac72565..510f98ce373 100644
--- a/rubocop/cop/migration/add_concurrent_index.rb
+++ b/rubocop/cop/migration/add_concurrent_index.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/add_index.rb b/rubocop/cop/migration/add_index.rb
index 4aea3c0cce3..7415880e554 100644
--- a/rubocop/cop/migration/add_index.rb
+++ b/rubocop/cop/migration/add_index.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/add_limit_to_text_columns.rb b/rubocop/cop/migration/add_limit_to_text_columns.rb
index b2e37ad5137..126e4e21f22 100644
--- a/rubocop/cop/migration/add_limit_to_text_columns.rb
+++ b/rubocop/cop/migration/add_limit_to_text_columns.rb
@@ -20,6 +20,10 @@ module RuboCop
(def :down ...)
PATTERN
+ def_node_matcher :set_text_limit?, <<~PATTERN
+ (send _ :text_limit ...)
+ PATTERN
+
def_node_matcher :add_text_limit?, <<~PATTERN
(send _ :add_text_limit ...)
PATTERN
@@ -111,20 +115,31 @@ module RuboCop
limit_found = false
node.each_descendant(:send) do |send_node|
- next unless add_text_limit?(send_node)
-
- limit_table = send_node.children[2].value
- limit_attribute = send_node.children[3].value
-
- if limit_table == table_name && limit_attribute == attribute_name
- limit_found = true
- break
+ if set_text_limit?(send_node)
+ limit_found = matching_set_text_limit?(send_node, attribute_name)
+ elsif add_text_limit?(send_node)
+ limit_found = matching_add_text_limit?(send_node, table_name, attribute_name)
end
+
+ break if limit_found
end
!limit_found
end
+ def matching_set_text_limit?(send_node, attribute_name)
+ limit_attribute = send_node.children[2].value
+
+ limit_attribute == attribute_name
+ end
+
+ def matching_add_text_limit?(send_node, table_name, attribute_name)
+ limit_table = send_node.children[2].value
+ limit_attribute = send_node.children[3].value
+
+ limit_table == table_name && limit_attribute == attribute_name
+ end
+
def encrypted_attribute_name?(attribute_name)
attribute_name.to_s.start_with?('encrypted_')
end
diff --git a/rubocop/cop/migration/add_timestamps.rb b/rubocop/cop/migration/add_timestamps.rb
index ba32d6a9960..d16e8b1f45b 100644
--- a/rubocop/cop/migration/add_timestamps.rb
+++ b/rubocop/cop/migration/add_timestamps.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/datetime.rb b/rubocop/cop/migration/datetime.rb
index 5a6cdc74ca4..51e0c3e5a22 100644
--- a/rubocop/cop/migration/datetime.rb
+++ b/rubocop/cop/migration/datetime.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/hash_index.rb b/rubocop/cop/migration/hash_index.rb
index 3206b73bd3d..dba202ef0e3 100644
--- a/rubocop/cop/migration/hash_index.rb
+++ b/rubocop/cop/migration/hash_index.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'set'
require_relative '../../migration_helpers'
diff --git a/rubocop/cop/migration/remove_column.rb b/rubocop/cop/migration/remove_column.rb
index fffb4ab7fab..f63df71467c 100644
--- a/rubocop/cop/migration/remove_column.rb
+++ b/rubocop/cop/migration/remove_column.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/remove_concurrent_index.rb b/rubocop/cop/migration/remove_concurrent_index.rb
index 2328740cf36..8c2c6fb157e 100644
--- a/rubocop/cop/migration/remove_concurrent_index.rb
+++ b/rubocop/cop/migration/remove_concurrent_index.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/remove_index.rb b/rubocop/cop/migration/remove_index.rb
index 4df3b1ba756..15c2f37b4b0 100644
--- a/rubocop/cop/migration/remove_index.rb
+++ b/rubocop/cop/migration/remove_index.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/safer_boolean_column.rb b/rubocop/cop/migration/safer_boolean_column.rb
index 22d5d37a83d..06bb24707bd 100644
--- a/rubocop/cop/migration/safer_boolean_column.rb
+++ b/rubocop/cop/migration/safer_boolean_column.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/timestamps.rb b/rubocop/cop/migration/timestamps.rb
index 6cf5648b996..5584d49ee8c 100644
--- a/rubocop/cop/migration/timestamps.rb
+++ b/rubocop/cop/migration/timestamps.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/migration/update_column_in_batches.rb b/rubocop/cop/migration/update_column_in_batches.rb
index b1c43393f6a..d23e0d28380 100644
--- a/rubocop/cop/migration/update_column_in_batches.rb
+++ b/rubocop/cop/migration/update_column_in_batches.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative '../../migration_helpers'
module RuboCop
diff --git a/rubocop/cop/project_path_helper.rb b/rubocop/cop/project_path_helper.rb
index f3810622eb1..bc2454e5b1f 100644
--- a/rubocop/cop/project_path_helper.rb
+++ b/rubocop/cop/project_path_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RuboCop
module Cop
class ProjectPathHelper < RuboCop::Cop::Cop
diff --git a/rubocop/cop/rspec/factories_in_migration_specs.rb b/rubocop/cop/rspec/factories_in_migration_specs.rb
index 65c7638a0f4..732e0d92bbd 100644
--- a/rubocop/cop/rspec/factories_in_migration_specs.rb
+++ b/rubocop/cop/rspec/factories_in_migration_specs.rb
@@ -15,7 +15,7 @@ module RuboCop
# let(:user) { users.create!(name: 'User 1', username: 'user1') }
class FactoriesInMigrationSpecs < RuboCop::Cop::Cop
MESSAGE = "Don't use FactoryBot.%s in migration specs, use `table` instead.".freeze
- FORBIDDEN_METHODS = %i[build build_list create create_list].freeze
+ FORBIDDEN_METHODS = %i[build build_list create create_list attributes_for].freeze
def_node_search :forbidden_factory_usage?, <<~PATTERN
(send {(const nil? :FactoryBot) nil?} {#{FORBIDDEN_METHODS.map(&:inspect).join(' ')}} ...)
diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb
index e9533fb65b2..63b3766e126 100644
--- a/rubocop/migration_helpers.rb
+++ b/rubocop/migration_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RuboCop
# Module containing helper methods for writing migration cops.
module MigrationHelpers
@@ -7,18 +9,19 @@ module RuboCop
plan_limits
].freeze
- # Tables with large number of columns (> 50 on GitLab.com as of 03/2020)
+ # Tables with large number of columns (> 50 on GitLab.com as of 01/2021)
WIDE_TABLES = %i[
- users
- projects
ci_builds
+ namespaces
+ projects
+ users
].freeze
# List of helpers that add new columns, either directly (ADD_COLUMN_METHODS)
# or through a create/alter table (TABLE_METHODS)
ADD_COLUMN_METHODS = %i(add_column add_column_with_default change_column_type_concurrently).freeze
- TABLE_METHODS = %i(create_table create_table_if_not_exists change_table).freeze
+ TABLE_METHODS = %i(create_table create_table_if_not_exists change_table create_table_with_constraints).freeze
def high_traffic_tables
@high_traffic_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'HighTrafficTables')
diff --git a/rubocop/qa_helpers.rb b/rubocop/qa_helpers.rb
index f4adf7f4e9f..9d6396e412e 100644
--- a/rubocop/qa_helpers.rb
+++ b/rubocop/qa_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RuboCop
# Module containing helper methods for writing QA cops.
module QAHelpers
diff --git a/rubocop/rubocop-migrations.yml b/rubocop/rubocop-migrations.yml
index 41bd2a4ce7d..45f8270b34d 100644
--- a/rubocop/rubocop-migrations.yml
+++ b/rubocop/rubocop-migrations.yml
@@ -38,6 +38,7 @@ Migration/UpdateLargeTable:
- :users
- :user_preferences
- :user_details
+ - :vulnerability_occurrences
- :web_hook_logs
DeniedMethods:
- :change_column_type_concurrently
diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml
index 0e40a5971ee..bbc4d590ddc 100644
--- a/rubocop/rubocop-usage-data.yml
+++ b/rubocop/rubocop-usage-data.yml
@@ -21,6 +21,8 @@ UsageData/LargeTable:
- :Gitaly::Server
- :Gitlab::UsageData
- :Gitlab::UsageDataCounters
+ - :Arel::Nodes::NamedFunction
+ - :Arel
- :License
- :Rails
- :Time
diff --git a/scripts/api/get_job_id.rb b/scripts/api/get_job_id.rb
index c7fe859db91..dd0b7fbada0 100755
--- a/scripts/api/get_job_id.rb
+++ b/scripts/api/get_job_id.rb
@@ -16,8 +16,8 @@ class JobFinder
def initialize(options)
@project = options.delete(:project)
- @pipeline_query = options.delete(:pipeline_query)
- @job_query = options.delete(:job_query)
+ @pipeline_query = options.delete(:pipeline_query) || DEFAULT_OPTIONS[:pipeline_query]
+ @job_query = options.delete(:job_query) || DEFAULT_OPTIONS[:job_query]
@pipeline_id = options.delete(:pipeline_id)
@job_name = options.delete(:job_name)
@artifact_path = options.delete(:artifact_path)
diff --git a/scripts/flaky_examples/detect-new-flaky-examples b/scripts/flaky_examples/detect-new-flaky-examples
index 3bee4f9a34b..4805c5054a5 100755
--- a/scripts/flaky_examples/detect-new-flaky-examples
+++ b/scripts/flaky_examples/detect-new-flaky-examples
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'json'
diff --git a/scripts/flaky_examples/prune-old-flaky-examples b/scripts/flaky_examples/prune-old-flaky-examples
index 4df49c6d8fa..8c09c4cc860 100755
--- a/scripts/flaky_examples/prune-old-flaky-examples
+++ b/scripts/flaky_examples/prune-old-flaky-examples
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
# lib/rspec_flaky/flaky_examples_collection.rb is requiring
# `active_support/hash_with_indifferent_access`, and we install the `activesupport`
diff --git a/scripts/frontend/extract_gettext_all.js b/scripts/frontend/extract_gettext_all.js
index c34c9a0233d..67163a601bc 100644
--- a/scripts/frontend/extract_gettext_all.js
+++ b/scripts/frontend/extract_gettext_all.js
@@ -36,7 +36,9 @@ const jsParser = extractor.createJsParser([
}),
]);
-const vueParser = decorateJSParserWithVueSupport(jsParser);
+const vueParser = decorateJSParserWithVueSupport(jsParser, {
+ vue2TemplateCompiler: require('vue-template-compiler'),
+});
function printJson() {
const messages = extractor.getMessages().reduce((result, message) => {
diff --git a/scripts/gather-test-memory-data b/scripts/gather-test-memory-data
index 9992a83e6a6..3156365ac19 100755
--- a/scripts/gather-test-memory-data
+++ b/scripts/gather-test-memory-data
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'csv'
diff --git a/scripts/generate-gems-memory-metrics-static b/scripts/generate-gems-memory-metrics-static
index aa7ce3615bf..42191f078f1 100755
--- a/scripts/generate-gems-memory-metrics-static
+++ b/scripts/generate-gems-memory-metrics-static
@@ -1,4 +1,5 @@
#!/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
diff --git a/scripts/generate-gems-size-metrics-static b/scripts/generate-gems-size-metrics-static
index ceec8aaccf1..2406e720916 100755
--- a/scripts/generate-gems-size-metrics-static
+++ b/scripts/generate-gems-size-metrics-static
@@ -1,4 +1,5 @@
#!/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
diff --git a/scripts/generate-memory-metrics-on-boot b/scripts/generate-memory-metrics-on-boot
index 5197a8fcdcd..945661aa057 100755
--- a/scripts/generate-memory-metrics-on-boot
+++ b/scripts/generate-memory-metrics-on-boot
@@ -1,4 +1,5 @@
#!/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
diff --git a/scripts/generate-test-mapping b/scripts/generate-test-mapping
index eabe6a5b513..c4d0dfea4d8 100755
--- a/scripts/generate-test-mapping
+++ b/scripts/generate-test-mapping
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'json'
require_relative '../tooling/lib/tooling/test_map_generator'
diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build
index 62d3dbda911..bb561e2906a 100755
--- a/scripts/gitaly-test-build
+++ b/scripts/gitaly-test-build
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'fileutils'
diff --git a/scripts/gitaly-test-spawn b/scripts/gitaly-test-spawn
index caa41a9a0c3..8547d0b13e4 100755
--- a/scripts/gitaly-test-spawn
+++ b/scripts/gitaly-test-spawn
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
# This script is used both in CI and in local development 'rspec' runs.
diff --git a/scripts/gitaly_test.rb b/scripts/gitaly_test.rb
index c7b3f72d590..2262870eb96 100644
--- a/scripts/gitaly_test.rb
+++ b/scripts/gitaly_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This file contains environment settings for gitaly when it's running
# as part of the gitlab-ce/ee test suite.
#
@@ -52,7 +54,7 @@ module GitalyTest
if ENV['CI']
bundle_path = File.expand_path('../vendor/gitaly-ruby', __dir__)
- env_hash['BUNDLE_FLAGS'] << " --path=#{bundle_path}"
+ env_hash['BUNDLE_FLAGS'] += " --path=#{bundle_path}"
end
env_hash
diff --git a/scripts/insert-rspec-profiling-data b/scripts/insert-rspec-profiling-data
index 3af5fe763a2..b2011858558 100755
--- a/scripts/insert-rspec-profiling-data
+++ b/scripts/insert-rspec-profiling-data
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'csv'
require 'rspec_profiling'
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index 23e7cb6c455..17c8cdaabec 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -18,6 +18,18 @@ then
((ERRORCODE++))
fi
+# Documentation pages need front matter for tracking purposes.
+echo '=> Checking documentation for front matter...'
+echo
+no_frontmatter=$(find doc -name "*.md" -exec head -n1 {} \; | grep -v --count -- ---)
+if [ $no_frontmatter -ne 0 ]
+then
+ echo '✖ ERROR: These documentation pages need front matter. See https://docs.gitlab.com/ee/development/documentation/index.html#stage-and-group-metadata for how to add it.' >&2
+ find doc -name "*.md" -exec sh -c 'if (head -n 1 "{}" | grep -v -- --- >/dev/null); then echo "{}"; fi' \; 2>&1
+ echo
+ ((ERRORCODE++))
+fi
+
# Test for non-standard spaces (NBSP, NNBSP) in documentation.
echo '=> Checking for non-standard spaces...'
echo
@@ -57,7 +69,7 @@ fi
# Do not use 'README.md', instead use 'index.md'
# Number of 'README.md's as of 2020-10-13
-NUMBER_READMES=36
+NUMBER_READMES=28
FIND_READMES=$(find doc/ -name "README.md" | wc -l)
echo '=> Checking for new README.md files...'
echo
@@ -80,12 +92,12 @@ then
echo "Merge request pipeline (detached) detected. Testing all files."
else
MERGE_BASE=$(git merge-base ${CI_MERGE_REQUEST_TARGET_BRANCH_SHA} ${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA})
- if git diff --name-only "${MERGE_BASE}..${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA}" | grep -E "\.vale|\.markdownlint|lint-doc\.sh"
+ if git diff --diff-filter=d --name-only "${MERGE_BASE}..${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA}" | grep -E "\.vale|\.markdownlint|lint-doc\.sh"
then
MD_DOC_PATH=${MD_DOC_PATH:-doc}
echo "Vale, Markdownlint, or lint-doc.sh configuration changed. Testing all files."
else
- MD_DOC_PATH=$(git diff --name-only "${MERGE_BASE}..${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA}" 'doc/*.md')
+ MD_DOC_PATH=$(git diff --diff-filter=d --name-only "${MERGE_BASE}..${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA}" -- 'doc/*.md')
if [ -n "${MD_DOC_PATH}" ]
then
echo -e "Merged results pipeline detected. Testing only the following files:\n${MD_DOC_PATH}"
diff --git a/scripts/lint-rugged b/scripts/lint-rugged
index d7af5499e1c..038fd5199c2 100755
--- a/scripts/lint-rugged
+++ b/scripts/lint-rugged
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
ALLOWED = [
# https://gitlab.com/gitlab-org/gitaly/issues/760
diff --git a/scripts/merge-html-reports b/scripts/merge-html-reports
index 7d1e15186c8..de300851990 100755
--- a/scripts/merge-html-reports
+++ b/scripts/merge-html-reports
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'nokogiri'
diff --git a/scripts/merge-reports b/scripts/merge-reports
index 3a421f1f1fc..a1164495f2f 100755
--- a/scripts/merge-reports
+++ b/scripts/merge-reports
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'json'
diff --git a/scripts/merge-simplecov b/scripts/merge-simplecov
index c00dae81c4d..38dd2dfe2e9 100755
--- a/scripts/merge-simplecov
+++ b/scripts/merge-simplecov
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require_relative '../spec/simplecov_env'
SimpleCovEnv.configure_profile
diff --git a/scripts/no-ee-check b/scripts/no-ee-check
index 29d319dc822..a878a4424e9 100755
--- a/scripts/no-ee-check
+++ b/scripts/no-ee-check
@@ -1,4 +1,6 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
+
ee_path = File.join(File.expand_path(__dir__), '../ee')
if Dir.exist?(ee_path)
diff --git a/scripts/pack-test-mapping b/scripts/pack-test-mapping
index 58ace3eca67..b5148cd1882 100755
--- a/scripts/pack-test-mapping
+++ b/scripts/pack-test-mapping
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'json'
require_relative '../tooling/lib/tooling/test_map_packer'
diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh
index e95f20bc26c..cd41aa0ff14 100644
--- a/scripts/prepare_build.sh
+++ b/scripts/prepare_build.sh
@@ -6,7 +6,8 @@ export BUNDLE_INSTALL_FLAGS=${BUNDLE_INSTALL_FLAGS:-"--without=production develo
if [ "$USE_BUNDLE_INSTALL" != "false" ]; then
bundle --version
- run_timed_command "bundle install --clean ${BUNDLE_INSTALL_FLAGS}"
+ bundle config set clean 'true'
+ run_timed_command "bundle install ${BUNDLE_INSTALL_FLAGS}"
run_timed_command "bundle check"
# When we test multiple versions of PG in the same pipeline, we have a single `setup-test-env`
# job but the `pg` gem needs to be rebuilt since it includes extensions (https://guides.rubygems.org/gems-with-extensions).
diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb
index bef5b7ad5ee..0927481070b 100755
--- a/scripts/review_apps/automated_cleanup.rb
+++ b/scripts/review_apps/automated_cleanup.rb
@@ -22,7 +22,8 @@ class AutomatedCleanup
%w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME'])
end
- def initialize(project_path: ENV['CI_PROJECT_PATH'], gitlab_token: ENV['GITLAB_BOT_REVIEW_APPS_CLEANUP_TOKEN'])
+ # $GITLAB_PROJECT_REVIEW_APP_CLEANUP_API_TOKEN => `Automated Review App Cleanup` project token
+ def initialize(project_path: ENV['CI_PROJECT_PATH'], gitlab_token: ENV['GITLAB_PROJECT_REVIEW_APP_CLEANUP_API_TOKEN'])
@project_path = project_path
@gitlab_token = gitlab_token
end
diff --git a/scripts/security-harness b/scripts/security-harness
index b9492e16066..0c1ade06587 100755
--- a/scripts/security-harness
+++ b/scripts/security-harness
@@ -17,6 +17,7 @@ else
SHELL_CLEAR = "\e[0m"
end
+LEFTHOOK_GLOBAL_CONFIG_PATH = File.expand_path("../lefthook.yml", __dir__)
HOOK_PATH = File.expand_path("../.git/hooks/pre-push", __dir__)
HOOK_DATA = <<~HOOK
#!/usr/bin/env bash
@@ -24,42 +25,65 @@ HOOK_DATA = <<~HOOK
set -e
url="$2"
- harness=`dirname "$0"`/../security_harness
- if [ -e "$harness" ]
+ if [[ "$url" != *"gitlab-org/security/"* ]]
then
- if [[ "$url" != *"gitlab-org/security/"* ]]
- then
- echo "Pushing to remotes other than gitlab.com/gitlab-org/security has been disabled!"
- echo "Run scripts/security-harness to disable this check."
- echo
-
- exit 1
- fi
+ echo "Pushing to remotes other than gitlab.com/gitlab-org/security has been disabled!"
+ echo "Run scripts/security-harness to disable this check."
+ echo
+
+ exit 1
fi
HOOK
+def hook_exist?
+ File.exist?(HOOK_PATH)
+end
+
+def lefthook_hook_in_place?
+ hook_exist? && File.foreach(HOOK_PATH).grep(/lefthook/i).any?
+end
+
+def lefthook_available?
+ system('bundle exec lefthook run prepare-commit-msg &>/dev/null') # rubocop:disable GitlabSecurity/SystemCommandInjection
+end
+
+def uninstall_lefthook
+ return unless lefthook_available?
+
+ system('bundle exec lefthook uninstall') # rubocop:disable GitlabSecurity/SystemCommandInjection
+ # `bundle exec lefthook uninstall` removes the `lefthook.yml` file so we checkout it again
+ system("git checkout -- #{LEFTHOOK_GLOBAL_CONFIG_PATH}") # rubocop:disable GitlabSecurity/SystemCommandInjection
+ puts "#{SHELL_YELLOW}Lefthook was uninstalled to let the security harness work properly.#{SHELL_CLEAR}"
+end
+
+def install_lefthook
+ return unless lefthook_available?
+
+ system('bundle exec lefthook install') # rubocop:disable GitlabSecurity/SystemCommandInjection
+ puts "#{SHELL_GREEN}Lefthook was re-installed.#{SHELL_CLEAR}"
+end
+
def write_hook
FileUtils.mkdir_p(File.dirname(HOOK_PATH))
File.open(HOOK_PATH, 'w') do |file|
file.write(HOOK_DATA)
end
File.chmod(0755, HOOK_PATH)
+ puts "#{SHELL_GREEN}Security harness installed -- you will only be able to push to gitlab.com/gitlab-org/security!#{SHELL_CLEAR}"
end
-# Toggle the harness on or off
-def toggle
- harness_path = File.expand_path('../.git/security_harness', __dir__)
-
- if File.exist?(harness_path)
- FileUtils.rm(harness_path)
+def delete_hook
+ FileUtils.rm(HOOK_PATH)
+ puts "#{SHELL_YELLOW}Security harness removed -- you can now push to all remotes.#{SHELL_CLEAR}"
+end
- puts "#{SHELL_YELLOW}Security harness removed -- you can now push to all remotes.#{SHELL_CLEAR}"
- else
- FileUtils.touch(harness_path)
+def hook_file_sum
+ Digest::SHA256.file(HOOK_PATH).hexdigest
+end
- puts "#{SHELL_GREEN}Security harness installed -- you will only be able to push to gitlab.com/gitlab-org/security!#{SHELL_CLEAR}"
- end
+def hook_data_sum
+ Digest::SHA256.hexdigest(HOOK_DATA)
end
# If we were to change the script and then check for a pre-existing hook before
@@ -67,33 +91,39 @@ end
# the old hook. Checking previous version hashes allows us to safely overwrite a
# script that differs from the current version, as long as it's an old one and
# not custom.
-def previous_version?(dest_sum)
- # SHA256 hashes of previous iterations of the script contained in `DATA`
+def upgrade_available?
+ # SHA256 hashes of previous iterations of the script contained in `HOOK_DATA`
%w[
010bf0363a911ebab2bd5728d80795ed02388da51815f0b2530d08ae8ac574f0
- ].include?(dest_sum)
+ d9866fc672f373d631eed9cd8dc9c920fa3d36ff26d956fb96a4082a0931b371
+ ].include?(hook_file_sum)
end
-if !File.exist?(HOOK_PATH)
- write_hook
- toggle
-else
- # Deal with a pre-existing hook
- source_sum = Digest::SHA256.hexdigest(HOOK_DATA)
- dest_sum = Digest::SHA256.file(HOOK_PATH).hexdigest
+def current_version?
+ hook_data_sum == hook_file_sum
+end
- if previous_version?(dest_sum)
+# Uninstall Lefthook if it's in place
+uninstall_lefthook if lefthook_hook_in_place?
+
+if hook_exist?
+ # Deal with a pre-existing hook
+ if upgrade_available?
# Upgrading from a previous version, update in-place
write_hook
- toggle
- elsif source_sum != dest_sum
+ elsif current_version?
+ # Delete the hook if we're already using the current version
+ delete_hook
+
+ # Re-install Lefthook pre-push hook
+ install_lefthook
+ else
# Pre-existing hook we didn't create; do nothing
puts "#{SHELL_RED}#{HOOK_PATH} exists and is different from our hook!"
puts "Remove it and re-run this script to continue.#{SHELL_CLEAR}"
exit 1
- else
- # No hook update needed, just toggle
- toggle
end
+else
+ write_hook
end
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 9103a9c14af..febfdbd1da4 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
# We don't have auto-loading here
require_relative '../lib/gitlab'
diff --git a/scripts/sync-reports b/scripts/sync-reports
index 5ed65e78005..73afd276e6c 100755
--- a/scripts/sync-reports
+++ b/scripts/sync-reports
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'rubygems'
require 'fog/aws'
diff --git a/scripts/trigger-build b/scripts/trigger-build
index ab6dcc63e11..29d53609026 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -3,13 +3,6 @@
require 'gitlab'
-#
-# Configure credentials to be used with gitlab gem
-#
-Gitlab.configure do |config|
- config.endpoint = 'https://gitlab.com/api/v4'
-end
-
module Trigger
def self.ee?
# Support former project name for `dev`
@@ -34,18 +27,13 @@ module Trigger
ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
end
- def initialize
- # gitlab-bot's token "GitLab multi-project pipeline polling"
- Gitlab.private_token = self.class.access_token
- end
-
def invoke!(post_comment: false, downstream_job_name: nil)
pipeline_variables = variables
puts "Triggering downstream pipeline on #{downstream_project_path}"
puts "with variables #{pipeline_variables}"
- pipeline = Gitlab.run_trigger(
+ pipeline = gitlab_client(:downstream).run_trigger(
downstream_project_path,
trigger_token,
ref,
@@ -54,23 +42,34 @@ module Trigger
puts "Triggered downstream pipeline: #{pipeline.web_url}\n"
puts "Waiting for downstream pipeline status"
- Trigger::CommitComment.post!(pipeline) if post_comment
+ Trigger::CommitComment.post!(pipeline, gitlab_client(:upstream)) if post_comment
downstream_job =
if downstream_job_name
- Gitlab.pipeline_jobs(downstream_project_path, pipeline.id).auto_paginate.find do |potential_job|
+ gitlab_client(:downstream).pipeline_jobs(downstream_project_path, pipeline.id).auto_paginate.find do |potential_job|
potential_job.name == downstream_job_name
end
end
if downstream_job
- Trigger::Job.new(downstream_project_path, downstream_job.id)
+ Trigger::Job.new(downstream_project_path, downstream_job.id, gitlab_client(:downstream))
else
- Trigger::Pipeline.new(downstream_project_path, pipeline.id)
+ Trigger::Pipeline.new(downstream_project_path, pipeline.id, gitlab_client(:downstream))
end
end
private
+ # Override to trigger and work with pipeline on different GitLab instance
+ # type: :downstream -> downstream build and pipeline status
+ # type: :upstream -> this project, e.g. for posting comments
+ def gitlab_client(type)
+ # By default, always use the same client
+ @gitlab_client ||= Gitlab.client(
+ endpoint: 'https://gitlab.com/api/v4',
+ private_token: self.class.access_token
+ )
+ end
+
# Must be overridden
def downstream_project_path
raise NotImplementedError
@@ -201,7 +200,7 @@ module Trigger
class Docs < Base
def self.access_token
- ENV['DOCS_API_TOKEN']
+ ENV['DOCS_PROJECT_API_TOKEN']
end
SUCCESS_MESSAGE = <<~MSG
@@ -232,7 +231,7 @@ module Trigger
# Remove a remote branch in gitlab-docs.
#
def cleanup!
- Gitlab.delete_branch(downstream_project_path, ref)
+ gitlab_client(:downstream).delete_branch(downstream_project_path, ref)
puts "=> Remote branch '#{downstream_project_path}' deleted"
end
@@ -276,7 +275,7 @@ module Trigger
end
def create_remote_branch!
- Gitlab.create_branch(downstream_project_path, ref, 'master')
+ gitlab_client(:downstream).create_branch(downstream_project_path, ref, 'master')
puts "=> Remote branch '#{ref}' created"
rescue Gitlab::Error::BadRequest
puts "=> Remote branch '#{ref}' already exists!"
@@ -289,7 +288,7 @@ module Trigger
loop do
sleep 1
puts "=> Waiting for pipeline to start..."
- pipelines = Gitlab.pipelines(downstream_project_path, { ref: ref })
+ pipelines = gitlab_client(:downstream).pipelines(downstream_project_path, { ref: ref })
break if pipelines.any?
end
@@ -297,7 +296,7 @@ module Trigger
pipeline_id = pipelines.first.id
# Cancel the pipeline
- Gitlab.cancel_pipeline(downstream_project_path, pipeline_id)
+ gitlab_client(:downstream).cancel_pipeline(downstream_project_path, pipeline_id)
end
def display_success_message
@@ -305,9 +304,53 @@ module Trigger
end
end
+ class DatabaseTesting < Base
+ def self.access_token
+ ENV['GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN']
+ end
+
+ private
+
+ def gitlab_client(type)
+ @gitlab_clients ||= {
+ downstream: Gitlab.client(
+ endpoint: 'https://ops.gitlab.net/api/v4',
+ private_token: self.class.access_token
+ ),
+ upstream: Gitlab.client(
+ endpoint: 'https://gitlab.com/api/v4',
+ private_token: Base.access_token
+ )
+ }
+
+ @gitlab_clients[type]
+ end
+
+ def trigger_token
+ ENV['GITLABCOM_DATABASE_TESTING_TRIGGER_TOKEN']
+ end
+
+ def downstream_project_path
+ ENV['GITLABCOM_DATABASE_TESTING_PROJECT_PATH'] || 'gitlab-com/database-team/gitlab-com-database-testing'
+ end
+
+ def extra_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_COMMIT_SHA' => Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'],
+ 'TRIGGERED_USER_LOGIN' => ENV['GITLAB_USER_LOGIN']
+ }
+ end
+
+ def ref
+ ENV['GITLABCOM_DATABASE_TESTING_TRIGGER_REF'] || 'master'
+ end
+ end
+
class CommitComment
- def self.post!(downstream_pipeline)
- Gitlab.create_commit_comment(
+ def self.post!(downstream_pipeline, gitlab_client)
+ gitlab_client.create_commit_comment(
ENV['CI_PROJECT_PATH'],
Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'],
"The [`#{ENV['CI_JOB_NAME']}`](#{ENV['CI_JOB_URL']}) job from pipeline #{ENV['CI_PIPELINE_URL']} triggered #{downstream_pipeline.web_url} downstream.")
@@ -329,9 +372,10 @@ module Trigger
unscoped_class_name.downcase
end
- def initialize(project, id)
+ def initialize(project, id, gitlab_client)
@project = project
@id = id
+ @gitlab_client = gitlab_client
@start_time = Time.now.to_i
end
@@ -359,7 +403,7 @@ module Trigger
end
def status
- Gitlab.public_send(self.class.gitlab_api_method_name, project, id).status.to_sym # rubocop:disable GitlabSecurity/PublicSend
+ gitlab_client.public_send(self.class.gitlab_api_method_name, project, id).status.to_sym # rubocop:disable GitlabSecurity/PublicSend
rescue Gitlab::Error::Error => error
puts "Ignoring the following error: #{error}"
# Ignore GitLab API hiccups. If GitLab is really down, we'll hit the job
@@ -369,7 +413,7 @@ module Trigger
private
- attr_reader :project, :id, :start_time
+ attr_reader :project, :id, :gitlab_client, :start_time
end
Job = Class.new(Pipeline)
@@ -380,6 +424,8 @@ 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
@@ -395,5 +441,6 @@ when 'docs'
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"
+ 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/unpack-test-mapping b/scripts/unpack-test-mapping
index c0f706c3f9f..7176f9cecea 100755
--- a/scripts/unpack-test-mapping
+++ b/scripts/unpack-test-mapping
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'json'
require_relative '../tooling/lib/tooling/test_map_packer'
diff --git a/scripts/update-feature-categories b/scripts/update-feature-categories
index ed5d8dccdd6..88520b9f95f 100755
--- a/scripts/update-feature-categories
+++ b/scripts/update-feature-categories
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'uri'
require 'net/http'
diff --git a/scripts/used-feature-flags b/scripts/used-feature-flags
index 7ef3dbafd36..aebd007dda9 100755
--- a/scripts/used-feature-flags
+++ b/scripts/used-feature-flags
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'set'
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index 8bf25ea3b5f..9931e14008a 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require 'set'
diff --git a/spec/benchmarks/banzai_benchmark.rb b/spec/benchmarks/banzai_benchmark.rb
new file mode 100644
index 00000000000..a87414ba512
--- /dev/null
+++ b/spec/benchmarks/banzai_benchmark.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+return unless ENV.key?('BENCHMARK')
+
+require 'spec_helper'
+require 'erb'
+require 'benchmark/ips'
+
+# This benchmarks some of the Banzai pipelines and filters.
+# They are not definitive, but can be used by a developer to
+# get a rough idea how the changing or addition of a new filter
+# will effect performance.
+#
+# Run by:
+# BENCHMARK=1 rspec spec/benchmarks/banzai_benchmark.rb
+# or
+# rake benchmark:banzai
+#
+# rubocop: disable RSpec/TopLevelDescribePath
+RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures do
+ include MarkupHelper
+
+ let_it_be(:feature) { MarkdownFeature.new }
+ let_it_be(:project) { feature.project }
+ let_it_be(:group) { feature.group }
+ let_it_be(:wiki) { feature.wiki }
+ let_it_be(:wiki_page) { feature.wiki_page }
+ let_it_be(:markdown_text) { feature.raw_markdown }
+ let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
+ let_it_be(:default_context) do
+ {
+ project: project,
+ current_user: current_user,
+ suggestions_filter_enabled: true
+ }
+ end
+
+ let(:context) do
+ Banzai::Filter::AssetProxyFilter.transform_context(default_context)
+ end
+
+ let!(:render_context) { Banzai::RenderContext.new(project, current_user) }
+
+ before do
+ stub_application_setting(asset_proxy_enabled: true)
+ stub_application_setting(asset_proxy_secret_key: 'shared-secret')
+ stub_application_setting(asset_proxy_url: 'https://assets.example.com')
+ stub_application_setting(asset_proxy_whitelist: %w(gitlab.com *.mydomain.com))
+ stub_application_setting(plantuml_enabled: true, plantuml_url: 'http://localhost:8080')
+ stub_application_setting(kroki_enabled: true, kroki_url: 'http://localhost:8000')
+
+ Banzai::Filter::AssetProxyFilter.initialize_settings
+ end
+
+ context 'pipelines' do
+ it 'benchmarks several pipelines' do
+ path = 'images/example.jpg'
+ gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
+ allow(wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
+ allow(wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
+
+ puts "\n--> Benchmarking Full, Wiki, and Plain pipelines\n"
+
+ Benchmark.ips do |x|
+ x.config(time: 10, warmup: 2)
+
+ x.report('Full pipeline') { Banzai::Pipeline::FullPipeline.call(markdown_text, context) }
+ x.report('Wiki pipeline') { Banzai::Pipeline::WikiPipeline.call(markdown_text, context.merge(wiki: wiki, page_slug: wiki_page.slug)) }
+ x.report('Plain pipeline') { Banzai::Pipeline::PlainMarkdownPipeline.call(markdown_text, context) }
+
+ x.compare!
+ end
+ end
+ end
+
+ context 'filters' do
+ it 'benchmarks all filters in the FullPipeline' do
+ benchmark_pipeline_filters(:full)
+ end
+
+ it 'benchmarks all filters in the PlainMarkdownPipeline' do
+ benchmark_pipeline_filters(:plain_markdown)
+ end
+ end
+
+ # build up the source text for each filter
+ def build_filter_text(pipeline, initial_text)
+ filter_source = {}
+ input_text = initial_text
+
+ pipeline.filters.each do |filter_klass|
+ filter_source[filter_klass] = input_text
+
+ output = filter_klass.call(input_text, context)
+ input_text = output
+ end
+
+ filter_source
+ end
+
+ def benchmark_pipeline_filters(pipeline_type)
+ pipeline = Banzai::Pipeline[pipeline_type]
+ filter_source = build_filter_text(pipeline, markdown_text)
+
+ puts "\n--> Benchmarking #{pipeline.name.demodulize} filters\n"
+
+ Benchmark.ips do |x|
+ x.config(time: 10, warmup: 2)
+
+ pipeline.filters.each do |filter_klass|
+ label = filter_klass.name.demodulize.delete_suffix('Filter').truncate(20)
+
+ x.report(label) { filter_klass.call(filter_source[filter_klass], context) }
+ end
+
+ x.compare!
+ end
+ end
+
+ # Fake a `current_user` helper
+ def current_user
+ feature.user
+ end
+end
diff --git a/spec/config/object_store_settings_spec.rb b/spec/config/object_store_settings_spec.rb
index 9e7dfa043c3..68b37197ca7 100644
--- a/spec/config/object_store_settings_spec.rb
+++ b/spec/config/object_store_settings_spec.rb
@@ -49,6 +49,20 @@ RSpec.describe ObjectStoreSettings do
}
end
+ shared_examples 'consolidated settings for objects accelerated by Workhorse' do
+ it 'consolidates active object storage settings' do
+ described_class::WORKHORSE_ACCELERATED_TYPES.each do |object_type|
+ # Use to_h to avoid https://gitlab.com/gitlab-org/gitlab/-/issues/286873
+ section = subject.try(object_type).to_h
+
+ next unless section.dig('object_store', 'enabled')
+
+ expect(section['object_store']['connection']).to eq(connection)
+ expect(section['object_store']['consolidated_settings']).to be true
+ end
+ end
+ end
+
it 'sets correct default values' do
subject
@@ -77,9 +91,7 @@ RSpec.describe ObjectStoreSettings do
expect(settings.pages['object_store']['consolidated_settings']).to be true
expect(settings.external_diffs['enabled']).to be false
- expect(settings.external_diffs['object_store']['enabled']).to be false
- expect(settings.external_diffs['object_store']['remote_directory']).to eq('external_diffs')
- expect(settings.external_diffs['object_store']['consolidated_settings']).to be true
+ expect(settings.external_diffs['object_store']).to be_nil
end
it 'raises an error when a bucket is missing' do
@@ -95,29 +107,50 @@ RSpec.describe ObjectStoreSettings do
expect(settings.pages['object_store']).to eq(nil)
end
- it 'allows pages to define its own connection' do
- pages_connection = { 'provider' => 'Google', 'google_application_default' => true }
- config['pages'] = {
- 'enabled' => true,
- 'object_store' => {
+ context 'GitLab Pages' do
+ let(:pages_connection) { { 'provider' => 'Google', 'google_application_default' => true } }
+
+ before do
+ config['pages'] = {
'enabled' => true,
- 'connection' => pages_connection
+ 'object_store' => {
+ 'enabled' => true,
+ 'connection' => pages_connection
+ }
}
- }
+ end
- expect { subject }.not_to raise_error
+ it_behaves_like 'consolidated settings for objects accelerated by Workhorse'
- described_class::WORKHORSE_ACCELERATED_TYPES.each do |object_type|
- section = settings.try(object_type)
+ it 'allows pages to define its own connection' do
+ expect { subject }.not_to raise_error
- next unless section
+ expect(settings.pages['object_store']['connection']).to eq(pages_connection)
+ expect(settings.pages['object_store']['consolidated_settings']).to be_falsey
+ end
+ end
- expect(section['object_store']['connection']).to eq(connection)
- expect(section['object_store']['consolidated_settings']).to be true
+ context 'when object storage is disabled for artifacts with no bucket' do
+ before do
+ config['artifacts'] = {
+ 'enabled' => true,
+ 'object_store' => {}
+ }
+ config['object_store']['objects']['artifacts'] = {
+ 'enabled' => false
+ }
end
- expect(settings.pages['object_store']['connection']).to eq(pages_connection)
- expect(settings.pages['object_store']['consolidated_settings']).to be_falsey
+ it_behaves_like 'consolidated settings for objects accelerated by Workhorse'
+
+ it 'does not enable consolidated settings for artifacts' do
+ subject
+
+ expect(settings.artifacts['enabled']).to be true
+ expect(settings.artifacts['object_store']['remote_directory']).to be_nil
+ expect(settings.artifacts['object_store']['enabled']).to be_falsey
+ expect(settings.artifacts['object_store']['consolidated_settings']).to be_falsey
+ end
end
context 'with legacy config' do
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index f0b224484c6..71abf3191b8 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -150,6 +150,13 @@ RSpec.describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.repository_storages_weighted_default).to eq(75)
end
+ it 'updates kroki_formats setting' do
+ put :update, params: { application_setting: { kroki_formats_excalidraw: '1' } }
+
+ expect(response).to redirect_to(general_admin_application_settings_path)
+ expect(ApplicationSetting.current.kroki_formats_excalidraw).to eq(true)
+ end
+
it "updates default_branch_name setting" do
put :update, params: { application_setting: { default_branch_name: "example_branch_name" } }
diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb
index 9eb2a713517..77a9c8eb223 100644
--- a/spec/controllers/admin/cohorts_controller_spec.rb
+++ b/spec/controllers/admin/cohorts_controller_spec.rb
@@ -3,37 +3,15 @@
require 'spec_helper'
RSpec.describe Admin::CohortsController do
- context 'as admin' do
- let(:user) { create(:admin) }
+ let(:user) { create(:admin) }
- before do
- sign_in(user)
- end
-
- it 'renders 200' do
- get :index
-
- expect(response).to have_gitlab_http_status(:success)
- end
-
- describe 'GET #index' do
- it_behaves_like 'tracking unique visits', :index do
- let(:target_id) { 'i_analytics_cohorts' }
- end
- end
+ before do
+ sign_in(user)
end
- context 'as normal user' do
- let(:user) { create(:user) }
-
- before do
- sign_in(user)
- end
-
- it 'renders a 404' do
- get :index
+ it 'redirects to Overview->Users' do
+ get :index
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ expect(response).to redirect_to(admin_users_path(tab: 'cohorts'))
end
end
diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb
index 3fffc50475c..cba25dbff95 100644
--- a/spec/controllers/admin/runners_controller_spec.rb
+++ b/spec/controllers/admin/runners_controller_spec.rb
@@ -27,7 +27,8 @@ RSpec.describe Admin::RunnersController do
# There is still an N+1 query for `runner.builds.count`
# We also need to add 1 because it takes 2 queries to preload tags
- expect { get :index }.not_to exceed_query_limit(control_count + 6)
+ # also looking for token nonce requires database queries
+ expect { get :index }.not_to exceed_query_limit(control_count + 16)
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to have_content('tag1')
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index f902a3d2541..6faec315eb6 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -29,6 +29,11 @@ RSpec.describe Admin::UsersController do
expect(assigns(:users).first.association(:authorized_projects)).to be_loaded
end
+
+ it_behaves_like 'tracking unique visits', :index do
+ let(:target_id) { 'i_analytics_cohorts' }
+ let(:request_params) { { tab: 'cohorts' } }
+ end
end
describe 'GET :id' do
@@ -180,7 +185,7 @@ RSpec.describe Admin::UsersController do
it 'displays the error' do
subject
- expect(flash[:alert]).to eq('The user you are trying to approve is not pending an approval')
+ expect(flash[:alert]).to eq('The user you are trying to approve is not pending approval')
end
it 'does not activate the user' do
diff --git a/spec/controllers/chaos_controller_spec.rb b/spec/controllers/chaos_controller_spec.rb
index 550303d292a..cb4f12ff829 100644
--- a/spec/controllers/chaos_controller_spec.rb
+++ b/spec/controllers/chaos_controller_spec.rb
@@ -124,4 +124,23 @@ RSpec.describe ChaosController do
expect(response).to have_gitlab_http_status(:ok)
end
end
+
+ describe '#gc' do
+ let(:gc_stat) { GC.stat.stringify_keys }
+
+ it 'runs a full GC on the current web worker' do
+ expect(Prometheus::PidProvider).to receive(:worker_id).and_return('worker-0')
+ expect(Gitlab::Chaos).to receive(:run_gc).and_return(gc_stat)
+
+ post :gc
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response_json['worker_id']).to eq('worker-0')
+ expect(response_json['gc_stat']).to eq(gc_stat)
+ end
+ end
+
+ def response_json
+ Gitlab::Json.parse(response.body)
+ end
end
diff --git a/spec/controllers/concerns/redis_tracking_spec.rb b/spec/controllers/concerns/redis_tracking_spec.rb
index ef59adf8c1d..53b49dd30a6 100644
--- a/spec/controllers/concerns/redis_tracking_spec.rb
+++ b/spec/controllers/concerns/redis_tracking_spec.rb
@@ -3,18 +3,13 @@
require "spec_helper"
RSpec.describe RedisTracking do
- let(:feature) { 'approval_rule' }
let(:user) { create(:user) }
- before do
- skip_feature_flags_yaml_validation
- end
-
controller(ApplicationController) do
include RedisTracking
skip_before_action :authenticate_user!, only: :show
- track_redis_hll_event :index, :show, name: 'g_compliance_approval_rules', feature: :approval_rule, feature_default_enabled: true,
+ track_redis_hll_event :index, :show, name: 'g_compliance_approval_rules',
if: [:custom_condition_one?, :custom_condition_two?]
def index
@@ -49,97 +44,75 @@ RSpec.describe RedisTracking do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
end
- context 'with feature disabled' do
- it 'does not track the event' do
- stub_feature_flags(feature => false)
-
- expect_no_tracking
-
- get :index
- end
- end
-
- context 'with feature enabled' do
+ context 'when user is logged in' do
before do
- stub_feature_flags(feature => true)
+ sign_in(user)
end
- context 'when user is logged in' do
- before do
- sign_in(user)
- end
-
- it 'tracks the event' do
- expect_tracking
-
- get :index
- end
-
- it 'passes default_enabled flag' do
- expect(controller).to receive(:metric_feature_enabled?).with(feature.to_sym, true)
+ it 'tracks the event' do
+ expect_tracking
- get :index
- end
+ get :index
+ end
- it 'tracks the event if DNT is not enabled' do
- request.headers['DNT'] = '0'
+ it 'tracks the event if DNT is not enabled' do
+ request.headers['DNT'] = '0'
- expect_tracking
+ expect_tracking
- get :index
- end
+ get :index
+ end
- it 'does not track the event if DNT is enabled' do
- request.headers['DNT'] = '1'
+ it 'does not track the event if DNT is enabled' do
+ request.headers['DNT'] = '1'
- expect_no_tracking
+ expect_no_tracking
- get :index
- end
+ get :index
+ end
- it 'does not track the event if the format is not HTML' do
- expect_no_tracking
+ it 'does not track the event if the format is not HTML' do
+ expect_no_tracking
- get :index, format: :json
- end
+ get :index, format: :json
+ end
- it 'does not track the event if a custom condition returns false' do
- expect(controller).to receive(:custom_condition_two?).and_return(false)
+ it 'does not track the event if a custom condition returns false' do
+ expect(controller).to receive(:custom_condition_two?).and_return(false)
- expect_no_tracking
+ expect_no_tracking
- get :index
- end
+ get :index
+ end
- it 'does not track the event for untracked actions' do
- expect_no_tracking
+ it 'does not track the event for untracked actions' do
+ expect_no_tracking
- get :new
- end
+ get :new
end
+ end
- context 'when user is not logged in and there is a visitor_id' do
- let(:visitor_id) { SecureRandom.uuid }
+ context 'when user is not logged in and there is a visitor_id' do
+ let(:visitor_id) { SecureRandom.uuid }
- before do
- routes.draw { get 'show' => 'anonymous#show' }
- end
+ before do
+ routes.draw { get 'show' => 'anonymous#show' }
+ end
- it 'tracks the event' do
- cookies[:visitor_id] = { value: visitor_id, expires: 24.months }
+ it 'tracks the event' do
+ cookies[:visitor_id] = { value: visitor_id, expires: 24.months }
- expect_tracking
+ expect_tracking
- get :show
- end
+ get :show
end
+ end
- context 'when user is not logged in and there is no visitor_id' do
- it 'does not track the event' do
- expect_no_tracking
+ context 'when user is not logged in and there is no visitor_id' do
+ it 'does not track the event' do
+ expect_no_tracking
- get :index
- end
+ get :index
end
end
end
diff --git a/spec/controllers/concerns/spammable_actions_spec.rb b/spec/controllers/concerns/spammable_actions_spec.rb
index 3b5b4d11a9b..25d5398c9da 100644
--- a/spec/controllers/concerns/spammable_actions_spec.rb
+++ b/spec/controllers/concerns/spammable_actions_spec.rb
@@ -6,21 +6,8 @@ RSpec.describe SpammableActions do
controller(ActionController::Base) do
include SpammableActions
- # #create is used to test spammable_params
- # for testing purposes
- def create
- spam_params = spammable_params
-
- # replace the actual request with a string in the JSON response, all we care is that it got set
- spam_params[:request] = 'this is the request' if spam_params[:request]
-
- # just return the params in the response so they can be verified in this fake controller spec.
- # Normally, they are processed further by the controller action
- render json: spam_params.to_json, status: :ok
- end
-
- # #update is used to test recaptcha_check_with_fallback
- # for testing purposes
+ # #update is used here to test #recaptcha_check_with_fallback, but it could be invoked
+ # from #create or any other action which mutates a spammable via a controller.
def update
should_redirect = params[:should_redirect] == 'true'
@@ -35,80 +22,7 @@ RSpec.describe SpammableActions do
end
before do
- # Ordinarily we would not stub a method on the class under test, but :ensure_spam_config_loaded!
- # returns false in the test environment, and is also strong_memoized, so we need to stub it
- allow(controller).to receive(:ensure_spam_config_loaded!) { true }
- end
-
- describe '#spammable_params' do
- subject { post :create, format: :json, params: params }
-
- shared_examples 'expects request param only' do
- it do
- subject
-
- expect(response).to be_successful
- expect(json_response).to eq({ 'request' => 'this is the request' })
- end
- end
-
- shared_examples 'expects all spammable params' do
- it do
- subject
-
- expect(response).to be_successful
- expect(json_response['request']).to eq('this is the request')
- expect(json_response['recaptcha_verified']).to eq(true)
- expect(json_response['spam_log_id']).to eq('1')
- end
- end
-
- let(:recaptcha_response) { nil }
- let(:spam_log_id) { nil }
-
- context 'when recaptcha response is not present' do
- let(:params) do
- {
- spam_log_id: spam_log_id
- }
- end
-
- it_behaves_like 'expects request param only'
- end
-
- context 'when recaptcha response is present' do
- let(:recaptcha_response) { 'abd123' }
- let(:params) do
- {
- 'g-recaptcha-response': recaptcha_response,
- spam_log_id: spam_log_id
- }
- end
-
- context 'when verify_recaptcha returns falsey' do
- before do
- expect(controller).to receive(:verify_recaptcha).with(
- {
- response: recaptcha_response
- }) { false }
- end
-
- it_behaves_like 'expects request param only'
- end
-
- context 'when verify_recaptcha returns truthy' do
- let(:spam_log_id) { 1 }
-
- before do
- expect(controller).to receive(:verify_recaptcha).with(
- {
- response: recaptcha_response
- }) { true }
- end
-
- it_behaves_like 'expects all spammable params'
- end
- end
+ allow(Gitlab::Recaptcha).to receive(:load_configurations!) { true }
end
describe '#recaptcha_check_with_fallback' do
@@ -154,12 +68,9 @@ RSpec.describe SpammableActions do
allow(spammable).to receive(:valid?) { false }
end
- # NOTE: Not adding coverage of details of render_recaptcha?, the plan is to refactor it out
- # of this module anyway as part of adding support for the GraphQL reCAPTCHA flow.
-
- context 'when render_recaptcha? is true' do
+ context 'when spammable.render_recaptcha? is true' do
before do
- expect(controller).to receive(:render_recaptcha?) { true }
+ expect(spammable).to receive(:render_recaptcha?) { true }
end
context 'when format is :html' do
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index e4aea688a69..f10fbf5ef2c 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -66,6 +66,16 @@ RSpec.describe GraphqlController do
expect(assigns(:context)[:is_sessionless_user]).to be false
end
+
+ it 'calls the track api when trackable method' do
+ agent = 'vs-code-gitlab-workflow/3.11.1 VSCode/1.52.1 Node.js/12.14.1 (darwin; x64)'
+ request.env['HTTP_USER_AGENT'] = agent
+
+ expect(Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter)
+ .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
@@ -83,6 +93,16 @@ RSpec.describe GraphqlController do
expect(assigns(:context)[:is_sessionless_user]).to be true
end
+
+ it 'calls the track api when trackable method' do
+ agent = 'vs-code-gitlab-workflow/3.11.1 VSCode/1.52.1 Node.js/12.14.1 (darwin; x64)'
+ request.env['HTTP_USER_AGENT'] = agent
+
+ expect(Gitlab::UsageDataCounters::VSCodeExtensionActivityUniqueCounter)
+ .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/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index 4d78419e8eb..ff7a7f55863 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -225,6 +225,18 @@ RSpec.describe Groups::GroupMembersController do
expect(requester.reload.expires_at).not_to eq(expires_at.to_date)
end
+
+ it 'returns error status' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+
+ it 'returns error message' do
+ subject
+
+ expect(json_response).to eq({ 'message' => 'Expires at cannot be a date in the past' })
+ end
end
context 'when set to a date in the future' do
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 939c36a98b2..9e5f68820d9 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -306,66 +306,6 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
end
-
- describe 'tracking group creation for onboarding issues experiment' do
- before do
- sign_in(user)
- end
-
- subject(:create_namespace) { post :create, params: { group: { name: 'new_group', path: 'new_group' } } }
-
- context 'experiment disabled' do
- before do
- stub_experiment(onboarding_issues: false)
- end
-
- it 'does not track anything', :snowplow do
- create_namespace
-
- expect_no_snowplow_event
- end
- end
-
- context 'experiment enabled' do
- before do
- stub_experiment(onboarding_issues: true)
- end
-
- context 'and the user is part of the control group' do
- before do
- stub_experiment_for_subject(onboarding_issues: false)
- end
-
- it 'tracks the event with the "created_namespace" action with the "control_group" property', :snowplow do
- create_namespace
-
- expect_snowplow_event(
- category: 'Growth::Conversion::Experiment::OnboardingIssues',
- action: 'created_namespace',
- label: anything,
- property: 'control_group'
- )
- end
- end
-
- context 'and the user is part of the experimental group' do
- before do
- stub_experiment_for_subject(onboarding_issues: true)
- end
-
- it 'tracks the event with the "created_namespace" action with the "experimental_group" property', :snowplow do
- create_namespace
-
- expect_snowplow_event(
- category: 'Growth::Conversion::Experiment::OnboardingIssues',
- action: 'created_namespace',
- label: anything,
- property: 'experimental_group'
- )
- end
- end
- end
- end
end
describe 'GET #index' do
diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb
index 6927df3b1c7..629d9b50d73 100644
--- a/spec/controllers/help_controller_spec.rb
+++ b/spec/controllers/help_controller_spec.rb
@@ -7,6 +7,43 @@ RSpec.describe HelpController do
let(:user) { create(:user) }
+ shared_examples 'documentation pages local render' do
+ it 'renders HTML' do
+ aggregate_failures do
+ is_expected.to render_template('show.html.haml')
+ expect(response.media_type).to eq 'text/html'
+ end
+ end
+ end
+
+ shared_examples 'documentation pages redirect' do |documentation_base_url|
+ let(:gitlab_version) { '13.4.0-ee' }
+
+ before do
+ stub_version(gitlab_version, 'ignored_revision_value')
+ end
+
+ it 'redirects user to custom documentation url with a specified version' do
+ is_expected.to redirect_to("#{documentation_base_url}/13.4/ee/#{path}.html")
+ end
+
+ context 'when it is a pre-release' do
+ let(:gitlab_version) { '13.4.0-pre' }
+
+ it 'redirects user to custom documentation url without a version' do
+ is_expected.to redirect_to("#{documentation_base_url}/ee/#{path}.html")
+ end
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(help_page_documentation_redirect: false)
+ end
+
+ it_behaves_like 'documentation pages local render'
+ end
+ end
+
before do
sign_in(user)
end
@@ -99,69 +136,70 @@ RSpec.describe HelpController do
describe 'GET #show' do
context 'for Markdown formats' do
+ subject { get :show, params: { path: path }, format: :md }
+
+ let(:path) { 'ssh/README' }
+
context 'when requested file exists' do
before do
expect_file_read(File.join(Rails.root, 'doc/ssh/README.md'), content: fixture_file('blockquote_fence_after.md'))
- get :show, params: { path: 'ssh/README' }, format: :md
+ subject
end
it 'assigns to @markdown' do
expect(assigns[:markdown]).not_to be_empty
end
- it 'renders HTML' do
- aggregate_failures do
- expect(response).to render_template('show.html.haml')
- expect(response.media_type).to eq 'text/html'
- end
- end
+ it_behaves_like 'documentation pages local render'
end
- context 'when a custom help_page_documentation_url is set' do
+ context 'when a custom help_page_documentation_url is set in database' do
before do
- stub_application_setting(help_page_documentation_base_url: documentation_base_url)
- stub_version(gitlab_version, 'deadbeaf')
+ stub_application_setting(help_page_documentation_base_url: 'https://in-db.gitlab.com')
end
- subject { get :show, params: { path: path }, format: 'html' }
+ it_behaves_like 'documentation pages redirect', 'https://in-db.gitlab.com'
+ end
- let(:gitlab_version) { '13.4.0-ee' }
- let(:documentation_base_url) { 'https://docs.gitlab.com' }
- let(:path) { 'ssh/README' }
+ context 'when a custom help_page_documentation_url is set in configuration file' do
+ let(:host) { 'https://in-yaml.gitlab.com' }
+ let(:docs_enabled) { true }
- it 'redirects user to custom documentation url with a specified version' do
- is_expected.to redirect_to("#{documentation_base_url}/13.4/ee/#{path}.html")
+ before do
+ allow(Settings).to receive(:gitlab_docs) { double(enabled: docs_enabled, host: host) }
end
- context 'when documentation url ends with a slash' do
- let(:documentation_base_url) { 'https://docs.gitlab.com/' }
+ it_behaves_like 'documentation pages redirect', 'https://in-yaml.gitlab.com'
- it 'redirects user to custom documentation url without slash duplicates' do
- is_expected.to redirect_to("https://docs.gitlab.com/13.4/ee/#{path}.html")
- end
+ context 'when gitlab_docs is disabled' do
+ let(:docs_enabled) { false }
+
+ it_behaves_like 'documentation pages local render'
end
- context 'when it is a pre-release' do
- let(:gitlab_version) { '13.4.0-pre' }
+ context 'when host is missing' do
+ let(:host) { nil }
- it 'redirects user to custom documentation url without a version' do
- is_expected.to redirect_to("#{documentation_base_url}/ee/#{path}.html")
- end
+ it_behaves_like 'documentation pages local render'
end
+ end
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(help_page_documentation_redirect: false)
- end
+ context 'when help_page_documentation_url is set in both db and configuration file' do
+ before do
+ stub_application_setting(help_page_documentation_base_url: 'https://in-db.gitlab.com')
+ allow(Settings).to receive(:gitlab_docs) { double(enabled: true, host: 'https://in-yaml.gitlab.com') }
+ end
- it 'renders HTML' do
- aggregate_failures do
- is_expected.to render_template('show.html.haml')
- expect(response.media_type).to eq 'text/html'
- end
- end
+ it_behaves_like 'documentation pages redirect', 'https://in-yaml.gitlab.com'
+ end
+
+ context 'when help_page_documentation_url has a trailing slash' do
+ before do
+ allow(Settings).to receive(:gitlab_docs) { double(enabled: true, host: 'https://in-yaml.gitlab.com/') }
end
+
+ it_behaves_like 'documentation pages redirect', 'https://in-yaml.gitlab.com'
end
context 'when requested file is missing' do
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index d1c138617bb..08a54f112bb 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -59,7 +59,14 @@ RSpec.describe Import::BulkImportsController do
parsed_response: [
{ 'id' => 1, 'full_name' => 'group1', 'full_path' => 'full/path/group1', 'web_url' => 'http://demo.host/full/path/group1' },
{ 'id' => 2, 'full_name' => 'group2', 'full_path' => 'full/path/group2', 'web_url' => 'http://demo.host/full/path/group1' }
- ]
+ ],
+ headers: {
+ 'x-next-page' => '2',
+ 'x-page' => '1',
+ 'x-per-page' => '20',
+ 'x-total' => '37',
+ 'x-total-pages' => '2'
+ }
)
end
@@ -81,6 +88,17 @@ RSpec.describe Import::BulkImportsController do
expect(json_response).to eq({ importable_data: client_response.parsed_response }.as_json)
end
+ it 'forwards pagination headers' do
+ get :status, format: :json
+
+ expect(response.headers['x-per-page']).to eq client_response.headers['x-per-page']
+ expect(response.headers['x-page']).to eq client_response.headers['x-page']
+ expect(response.headers['x-next-page']).to eq client_response.headers['x-next-page']
+ expect(response.headers['x-prev-page']).to eq client_response.headers['x-prev-page']
+ expect(response.headers['x-total']).to eq client_response.headers['x-total']
+ expect(response.headers['x-total-pages']).to eq client_response.headers['x-total-pages']
+ end
+
context 'when filtering' do
it 'returns filtered result' do
filter = 'test'
@@ -167,6 +185,7 @@ RSpec.describe Import::BulkImportsController do
describe 'POST create' do
let(:instance_url) { "http://fake-intance" }
+ let(:bulk_import) { create(:bulk_import) }
let(:pat) { "fake-pat" }
before do
@@ -183,12 +202,13 @@ RSpec.describe Import::BulkImportsController do
expect_next_instance_of(
BulkImportService, user, bulk_import_params, { url: instance_url, access_token: pat }) do |service|
- expect(service).to receive(:execute)
+ allow(service).to receive(:execute).and_return(bulk_import)
end
post :create, params: { bulk_import: bulk_import_params }
expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq({ id: bulk_import.id }.to_json)
end
end
end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index e863f5ef2fc..a8d38d12f23 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe InvitesController, :snowplow do
+RSpec.describe InvitesController do
let_it_be(:user) { create(:user) }
let(:member) { create(:project_member, :invited, invite_email: user.email) }
let(:raw_invite_token) { member.raw_invite_token }
@@ -51,6 +51,28 @@ RSpec.describe InvitesController, :snowplow do
end
it_behaves_like 'invalid token'
+
+ context 'when invite comes from the initial email invite' do
+ let(:params) { { id: raw_invite_token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE } }
+
+ it 'tracks via experiment', :aggregate_failures do
+ experiment = double(track: true)
+ allow(controller).to receive(:experiment).and_return(experiment)
+
+ request
+
+ expect(experiment).to have_received(:track).with(:opened)
+ expect(experiment).to have_received(:track).with(:accepted)
+ end
+ end
+
+ context 'when invite does not come from initial email invite' do
+ it 'does not track via experiment' do
+ expect(controller).not_to receive(:experiment)
+
+ request
+ end
+ end
end
context 'when not logged in' do
@@ -82,6 +104,25 @@ RSpec.describe InvitesController, :snowplow do
subject(:request) { post :accept, params: params }
it_behaves_like 'invalid token'
+
+ context 'when invite comes from the initial email invite' do
+ it 'tracks via experiment' do
+ experiment = double(track: true)
+ allow(controller).to receive(:experiment).and_return(experiment)
+
+ post :accept, params: params, session: { invite_type: Members::InviteEmailExperiment::INVITE_TYPE }
+
+ expect(experiment).to have_received(:track).with(:accepted)
+ end
+ end
+
+ context 'when invite does not come from initial email invite' do
+ it 'does not track via experiment' do
+ expect(controller).not_to receive(:experiment)
+
+ request
+ end
+ end
end
describe 'POST #decline for link in UI' do
diff --git a/spec/controllers/profiles/notifications_controller_spec.rb b/spec/controllers/profiles/notifications_controller_spec.rb
index 90df7cc0991..03749366703 100644
--- a/spec/controllers/profiles/notifications_controller_spec.rb
+++ b/spec/controllers/profiles/notifications_controller_spec.rb
@@ -119,10 +119,11 @@ RSpec.describe Profiles::NotificationsController do
it 'updates only permitted attributes' do
sign_in(user)
- put :update, params: { user: { notification_email: 'new@example.com', notified_of_own_activity: true, admin: true } }
+ put :update, params: { user: { notification_email: 'new@example.com', email_opted_in: true, notified_of_own_activity: true, admin: true } }
user.reload
expect(user.notification_email).to eq('new@example.com')
+ expect(user.email_opted_in).to eq(true)
expect(user.notified_of_own_activity).to eq(true)
expect(user.admin).to eq(false)
expect(controller).to set_flash[:notice].to('Notification settings saved')
diff --git a/spec/controllers/profiles/preferences_controller_spec.rb b/spec/controllers/profiles/preferences_controller_spec.rb
index 4a68475c37f..b7870a63f9d 100644
--- a/spec/controllers/profiles/preferences_controller_spec.rb
+++ b/spec/controllers/profiles/preferences_controller_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Profiles::PreferencesController do
end
describe 'PATCH update' do
- def go(params: {}, format: :js)
+ def go(params: {}, format: :json)
params.reverse_merge!(
color_scheme_id: '1',
dashboard: 'stars',
@@ -35,9 +35,12 @@ RSpec.describe Profiles::PreferencesController do
end
context 'on successful update' do
- it 'sets the flash' do
+ it 'responds with success' do
go
- expect(flash[:notice]).to eq _('Preferences saved.')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.parsed_body['message']).to eq _('Preferences saved.')
+ expect(response.parsed_body['type']).to eq('notice')
end
it "changes the user's preferences" do
@@ -59,36 +62,26 @@ RSpec.describe Profiles::PreferencesController do
end
context 'on failed update' do
- it 'sets the flash' do
+ it 'responds with error' do
expect(user).to receive(:save).and_return(false)
go
- expect(flash[:alert]).to eq(_('Failed to save preferences.'))
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.parsed_body['message']).to eq _('Failed to save preferences.')
+ expect(response.parsed_body['type']).to eq('alert')
end
end
context 'on invalid dashboard setting' do
- it 'sets the flash' do
+ it 'responds with error' do
prefs = { dashboard: 'invalid' }
go params: prefs
- expect(flash[:alert]).to match(/\AFailed to save preferences \(.+\)\.\z/)
- end
- end
-
- context 'as js' do
- it 'renders' do
- go
- expect(response).to render_template :update
- end
- end
-
- context 'as html' do
- it 'redirects' do
- go format: :html
- expect(response).to redirect_to(profile_preferences_path)
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.parsed_body['message']).to match(/\AFailed to save preferences \(.+\)\.\z/)
+ expect(response.parsed_body['type']).to eq('alert')
end
end
end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index 16be7394174..68551ce4858 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -424,7 +424,7 @@ RSpec.describe Projects::BlobController do
end
end
- it_behaves_like 'tracking unique hll events', :track_editor_edit_actions do
+ it_behaves_like 'tracking unique hll events' do
subject(:request) { put :update, params: default_params }
let(:target_id) { 'g_edit_by_sfe' }
@@ -540,7 +540,7 @@ RSpec.describe Projects::BlobController do
sign_in(user)
end
- it_behaves_like 'tracking unique hll events', :track_editor_edit_actions do
+ it_behaves_like 'tracking unique hll events' do
subject(:request) { post :create, params: default_params }
let(:target_id) { 'g_edit_by_sfe' }
diff --git a/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb b/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb
index 594c24bb7e3..81318b49cd9 100644
--- a/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb
+++ b/spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
let(:end_date) { '2020-03-09' }
let(:allowed_to_read) { true }
let(:user) { create(:user) }
+ let(:feature_enabled?) { true }
before do
create_daily_coverage('rspec', 79.0, '2020-03-09')
@@ -24,6 +25,8 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_build_report_results, project).and_return(allowed_to_read)
+ stub_feature_flags(coverage_data_new_finder: feature_enabled?)
+
get :index, params: {
namespace_id: project.namespace,
project_id: project,
@@ -55,9 +58,7 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
end
end
- context 'when format is CSV' do
- let(:format) { :csv }
-
+ shared_examples 'CSV results' do
it 'serves the results in CSV' do
expect(response).to have_gitlab_http_status(:ok)
expect(response.headers['Content-Type']).to eq('text/csv; charset=utf-8')
@@ -88,9 +89,7 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
it_behaves_like 'ensuring policy'
end
- context 'when format is JSON' do
- let(:format) { :json }
-
+ shared_examples 'JSON results' do
it 'serves the results in JSON' do
expect(response).to have_gitlab_http_status(:ok)
@@ -137,6 +136,38 @@ RSpec.describe Projects::Ci::DailyBuildGroupReportResultsController do
it_behaves_like 'validating param_type'
it_behaves_like 'ensuring policy'
end
+
+ context 'when format is JSON' do
+ let(:format) { :json }
+
+ context 'when coverage_data_new_finder flag is enabled' do
+ let(:feature_enabled?) { true }
+
+ it_behaves_like 'JSON results'
+ end
+
+ context 'when coverage_data_new_finder flag is disabled' do
+ let(:feature_enabled?) { false }
+
+ it_behaves_like 'JSON results'
+ end
+ end
+
+ context 'when format is CSV' do
+ let(:format) { :csv }
+
+ context 'when coverage_data_new_finder flag is enabled' do
+ let(:feature_enabled?) { true }
+
+ it_behaves_like 'CSV results'
+ end
+
+ context 'when coverage_data_new_finder flag is disabled' do
+ let(:feature_enabled?) { false }
+
+ it_behaves_like 'CSV results'
+ end
+ end
end
def create_daily_coverage(group_name, coverage, date)
diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb
index f9d16e761cb..8a793e29bfa 100644
--- a/spec/controllers/projects/discussions_controller_spec.rb
+++ b/spec/controllers/projects/discussions_controller_spec.rb
@@ -186,6 +186,13 @@ RSpec.describe Projects::DiscussionsController do
expect(Note.find(note.id).discussion.resolved?).to be false
end
+ it "tracks thread unresolve usage data" do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_unresolve_thread_action).with(user: user)
+
+ delete :unresolve, params: request_params
+ end
+
it "returns status 200" do
delete :unresolve, params: request_params
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index e8b30294cdd..7da3d403b53 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -209,6 +209,13 @@ RSpec.describe Projects::ForksController do
}
end
+ let(:created_project) do
+ Namespace
+ .find_by_id(params[:namespace_key])
+ .projects
+ .find_by_path(params.fetch(:path, project.path))
+ end
+
subject do
post :create, params: params
end
@@ -260,6 +267,21 @@ RSpec.describe Projects::ForksController do
expect(response).to redirect_to(namespace_project_import_path(user.namespace, project, continue: continue_params))
end
end
+
+ context 'custom attributes set' do
+ let(:params) { super().merge(path: 'something_custom', name: 'Something Custom', description: 'Something Custom', visibility: 'private') }
+
+ it 'creates a project with custom values' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(namespace_project_import_path(user.namespace, params[:path]))
+ expect(created_project.path).to eq(params[:path])
+ expect(created_project.name).to eq(params[:name])
+ expect(created_project.description).to eq(params[:description])
+ expect(created_project.visibility).to eq(params[:visibility])
+ end
+ end
end
context 'when user is not signed in' do
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index d3bdf1baaae..81ffd2c4512 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -63,53 +63,20 @@ RSpec.describe Projects::IssuesController do
end
end
- describe 'the null hypothesis experiment', :snowplow do
- it 'defines the expected before actions' do
- expect(controller).to use_before_action(:run_null_hypothesis_experiment)
- end
-
- context 'when rolled out to 100%' do
- it 'assigns the candidate experience and tracks the event' do
- get :index, params: { namespace_id: project.namespace, project_id: project }
-
- expect_snowplow_event(
- category: 'null_hypothesis',
- action: 'index',
- context: [{
- schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0',
- data: { variant: 'candidate', experiment: 'null_hypothesis', key: anything }
- }]
- )
- end
+ describe 'the null hypothesis experiment', :experiment do
+ before do
+ stub_experiments(null_hypothesis: :candidate)
end
- context 'when not rolled out' do
- before do
- stub_feature_flags(null_hypothesis: false)
- end
-
- it 'assigns the control experience and tracks the event' do
- get :index, params: { namespace_id: project.namespace, project_id: project }
-
- expect_snowplow_event(
- category: 'null_hypothesis',
- action: 'index',
- context: [{
- schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0',
- data: { variant: 'control', experiment: 'null_hypothesis', key: anything }
- }]
- )
- end
+ it 'defines the expected before actions' do
+ expect(controller).to use_before_action(:run_null_hypothesis_experiment)
end
- context 'when gitlab_experiments is disabled' do
- it 'does not run the experiment at all' do
- stub_feature_flags(gitlab_experiments: false)
+ it 'assigns the candidate experience and tracks the event' do
+ expect(experiment(:null_hypothesis)).to track('index').on_any_instance.for(:candidate)
+ .with_context(project: project)
- expect(controller).not_to receive(:run_null_hypothesis_experiment)
-
- get :index, params: { namespace_id: project.namespace, project_id: project }
- end
+ get :index, params: { namespace_id: project.namespace, project_id: project }
end
end
end
@@ -1314,11 +1281,13 @@ RSpec.describe Projects::IssuesController do
let!(:last_spam_log) { spam_logs.last }
def post_verified_issue
- post_new_issue({}, { spam_log_id: last_spam_log.id, 'g-recaptcha-response': true } )
+ post_new_issue({}, { spam_log_id: last_spam_log.id, 'g-recaptcha-response': 'abc123' } )
end
before do
- expect(controller).to receive_messages(verify_recaptcha: true)
+ expect_next_instance_of(Captcha::CaptchaVerificationService) do |instance|
+ expect(instance).to receive(:execute) { true }
+ end
end
it 'accepts an issue after reCAPTCHA is verified' do
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 430808e1c63..80e1268cb01 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -15,54 +15,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'GET index' do
- describe 'pushing tracking_data to Gon' do
- before do
- stub_experiment(jobs_empty_state: experiment_active)
- stub_experiment_for_subject(jobs_empty_state: in_experiment_group)
-
- get_index
- end
-
- context 'when experiment not active' do
- let(:experiment_active) { false }
- let(:in_experiment_group) { false }
-
- it 'does not push tracking_data to Gon' do
- expect(Gon.tracking_data).to be_nil
- end
- end
-
- context 'when experiment active and user in control group' do
- let(:experiment_active) { true }
- let(:in_experiment_group) { false }
-
- it 'pushes tracking_data to Gon' do
- expect(Gon.tracking_data).to match(
- {
- category: 'Growth::Activation::Experiment::JobsEmptyState',
- action: 'click_button',
- label: anything,
- property: 'control_group'
- }
- )
- end
- end
-
- context 'when experiment active and user in experimental group' do
- let(:experiment_active) { true }
- let(:in_experiment_group) { true }
-
- it 'pushes tracking_data to gon' do
- expect(Gon.tracking_data).to match(
- category: 'Growth::Activation::Experiment::JobsEmptyState',
- action: 'click_button',
- label: anything,
- property: 'experimental_group'
- )
- end
- end
- end
-
context 'when scope is pending' do
before do
create(:ci_build, :pending, pipeline: pipeline)
diff --git a/spec/controllers/projects/learn_gitlab_controller_spec.rb b/spec/controllers/projects/learn_gitlab_controller_spec.rb
new file mode 100644
index 00000000000..f633f7aa246
--- /dev/null
+++ b/spec/controllers/projects/learn_gitlab_controller_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::LearnGitlabController do
+ describe 'GET #index' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, namespace: user.namespace) }
+
+ let(:learn_gitlab_experiment_enabled) { true }
+ let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
+
+ subject { get :index, params: params }
+
+ before do
+ allow(controller.helpers).to receive(:learn_gitlab_experiment_enabled?).and_return(learn_gitlab_experiment_enabled)
+ end
+
+ context 'unauthenticated user' do
+ it { is_expected.to have_gitlab_http_status(:redirect) }
+ end
+
+ context 'authenticated user' do
+ before do
+ sign_in(user)
+ end
+
+ it { is_expected.to render_template(:index) }
+
+ it 'pushes experiment to frontend' do
+ expect(controller).to receive(:push_frontend_experiment).with(:learn_gitlab_a, subject: user)
+ expect(controller).to receive(:push_frontend_experiment).with(:learn_gitlab_b, subject: user)
+
+ subject
+ end
+
+ context 'learn_gitlab experiment not enabled' do
+ let(:learn_gitlab_experiment_enabled) { false }
+
+ it { is_expected.to have_gitlab_http_status(:not_found) }
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index f54a07de853..50f8942d9d5 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -226,11 +226,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do
let(:diffable_merge_ref) { true }
it 'compares diffs with the head' do
- MergeRequests::MergeToRefService.new(project, merge_request.author).execute(merge_request)
-
- expect(CompareService).to receive(:new).with(
- project, merge_request.merge_ref_head.sha
- ).and_call_original
+ create(:merge_request_diff, :merge_head, merge_request: merge_request)
go(diff_head: true)
@@ -242,8 +238,6 @@ RSpec.describe Projects::MergeRequests::DiffsController do
let(:diffable_merge_ref) { false }
it 'compares diffs with the base' do
- expect(CompareService).not_to receive(:new)
-
go(diff_head: true)
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index cf8b4c564c4..9b37c46fd86 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1118,6 +1118,108 @@ RSpec.describe Projects::MergeRequestsController do
end
end
+ describe 'GET codequality_mr_diff_reports' do
+ let_it_be(:merge_request) do
+ create(:merge_request,
+ :with_merge_request_pipeline,
+ target_project: project,
+ source_project: project)
+ end
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ :success,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
+
+ before do
+ allow_any_instance_of(MergeRequest)
+ .to receive(:find_codequality_mr_diff_reports)
+ .and_return(report)
+
+ allow_any_instance_of(MergeRequest)
+ .to receive(:actual_head_pipeline)
+ .and_return(pipeline)
+ end
+
+ subject(:get_codequality_mr_diff_reports) do
+ get :codequality_mr_diff_reports, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: merge_request.iid
+ },
+ format: :json
+ end
+
+ context 'permissions on a public project with private CI/CD' do
+ let(:project) { create :project, :repository, :public, :builds_private }
+ let(:report) { { status: :parsed, data: { 'files' => {} } } }
+
+ context 'while signed out' do
+ before do
+ sign_out(user)
+ end
+
+ it 'responds with a 404' do
+ get_codequality_mr_diff_reports
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to be_blank
+ end
+ end
+
+ context 'while signed in as an unrelated user' do
+ before do
+ sign_in(create(:user))
+ end
+
+ it 'responds with a 404' do
+ get_codequality_mr_diff_reports
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to be_blank
+ end
+ end
+ end
+
+ context 'when pipeline has jobs with codequality mr diff report' do
+ before do
+ allow_any_instance_of(MergeRequest)
+ .to receive(:has_codequality_mr_diff_report?)
+ .and_return(true)
+ end
+
+ context 'when processing codequality mr diff report is in progress' do
+ let(:report) { { status: :parsing } }
+
+ it 'sends polling interval' do
+ expect(Gitlab::PollingInterval).to receive(:set_header)
+
+ get_codequality_mr_diff_reports
+ end
+
+ it 'returns 204 HTTP status' do
+ get_codequality_mr_diff_reports
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ context 'when processing codequality mr diff report is completed' do
+ let(:report) { { status: :parsed, data: { 'files' => {} } } }
+
+ it 'returns codequality mr diff report' do
+ get_codequality_mr_diff_reports
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'files' => {} })
+ end
+ end
+ end
+ end
+
describe 'GET terraform_reports' do
let_it_be(:merge_request) do
create(:merge_request,
@@ -1269,7 +1371,6 @@ RSpec.describe Projects::MergeRequestsController do
describe 'GET test_reports' do
let_it_be(:merge_request) do
create(:merge_request,
- :with_diffs,
:with_merge_request_pipeline,
target_project: project,
source_project: project
@@ -1380,7 +1481,6 @@ RSpec.describe Projects::MergeRequestsController do
describe 'GET accessibility_reports' do
let_it_be(:merge_request) do
create(:merge_request,
- :with_diffs,
:with_merge_request_pipeline,
target_project: project,
source_project: project
@@ -1501,7 +1601,6 @@ RSpec.describe Projects::MergeRequestsController do
describe 'GET codequality_reports' do
let_it_be(:merge_request) do
create(:merge_request,
- :with_diffs,
:with_merge_request_pipeline,
target_project: project,
source_project: project
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index e96113c0133..edebaf294c4 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -150,7 +150,7 @@ RSpec.describe Projects::NotesController do
end
it 'returns an empty page of notes' do
- expect(Gitlab::EtagCaching::Middleware).not_to receive(:skip!)
+ expect(Gitlab::EtagCaching::Middleware).to receive(:skip!)
request.headers['X-Last-Fetched-At'] = microseconds(Time.zone.now)
@@ -169,6 +169,8 @@ RSpec.describe Projects::NotesController do
end
it 'returns all notes' do
+ expect(Gitlab::EtagCaching::Middleware).to receive(:skip!)
+
get :index, params: request_params
expect(json_response['notes'].count).to eq((page_1 + page_2 + page_3).size + 1)
@@ -313,7 +315,7 @@ RSpec.describe Projects::NotesController do
let(:note_text) { 'some note' }
let(:request_params) do
{
- note: { note: note_text, noteable_id: merge_request.id, noteable_type: 'MergeRequest' },
+ note: { note: note_text, noteable_id: merge_request.id, noteable_type: 'MergeRequest' }.merge(extra_note_params),
namespace_id: project.namespace,
project_id: project,
merge_request_diff_head_sha: 'sha',
@@ -323,6 +325,7 @@ RSpec.describe Projects::NotesController do
end
let(:extra_request_params) { {} }
+ let(:extra_note_params) { {} }
let(:project_visibility) { Gitlab::VisibilityLevel::PUBLIC }
let(:merge_requests_access_level) { ProjectFeature::ENABLED }
@@ -421,6 +424,41 @@ RSpec.describe Projects::NotesController do
end
end
+ context 'when creating a confidential note' do
+ let(:extra_request_params) { { format: :json } }
+
+ context 'when `confidential` parameter is not provided' do
+ it 'sets `confidential` to `false` in JSON response' do
+ create!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be false
+ end
+ end
+
+ context 'when `confidential` parameter is `false`' do
+ let(:extra_note_params) { { confidential: false } }
+
+ it 'sets `confidential` to `false` in JSON response' do
+ create!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be false
+ end
+ end
+
+ context 'when `confidential` parameter is `true`' do
+ let(:extra_note_params) { { confidential: true } }
+
+ it 'sets `confidential` to `true` in JSON response' do
+ create!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be true
+ end
+ end
+ end
+
context 'when creating a note with quick actions' do
context 'with commands that return changes' do
let(:note_text) { "/award :thumbsup:\n/estimate 1d\n/spend 3h" }
@@ -725,6 +763,51 @@ RSpec.describe Projects::NotesController do
end
end
end
+
+ context 'when the endpoint receives requests above the limit' do
+ before do
+ stub_application_setting(notes_create_limit: 3)
+ end
+
+ it 'prevents from creating more notes', :request_store do
+ 3.times { create! }
+
+ expect { create! }
+ .to change { Gitlab::GitalyClient.get_request_count }.by(0)
+
+ create!
+ expect(response.body).to eq(_('This endpoint has been requested too many times. Try again later.'))
+ expect(response).to have_gitlab_http_status(:too_many_requests)
+ end
+
+ it 'logs the event in auth.log' do
+ attributes = {
+ message: 'Application_Rate_Limiter_Request',
+ env: :notes_create_request_limit,
+ remote_ip: '0.0.0.0',
+ request_method: 'POST',
+ path: "/#{project.full_path}/notes",
+ user_id: user.id,
+ username: user.username
+ }
+
+ expect(Gitlab::AuthLogger).to receive(:error).with(attributes).once
+
+ project.add_developer(user)
+ sign_in(user)
+
+ 4.times { create! }
+ end
+
+ it 'allows user in allow-list to create notes, even if the case is different' do
+ user.update_attribute(:username, user.username.titleize)
+ stub_application_setting(notes_create_limit_allowlist: ["#{user.username.downcase}"])
+ 3.times { create! }
+
+ create!
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
end
describe 'PUT update' do
diff --git a/spec/controllers/projects/pipelines/tests_controller_spec.rb b/spec/controllers/projects/pipelines/tests_controller_spec.rb
index 61118487e20..e6ff3a487ac 100644
--- a/spec/controllers/projects/pipelines/tests_controller_spec.rb
+++ b/spec/controllers/projects/pipelines/tests_controller_spec.rb
@@ -34,20 +34,38 @@ RSpec.describe Projects::Pipelines::TestsController do
end
describe 'GET #show.json' do
- context 'when pipeline has build report results' do
- let(:pipeline) { create(:ci_pipeline, :with_report_results, project: project) }
+ context 'when pipeline has builds with test reports' do
+ let(:main_pipeline) { create(:ci_pipeline, :with_test_reports_with_three_failures, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :with_test_reports_with_three_failures, project: project, ref: 'new-feature') }
let(:suite_name) { 'test' }
let(:build_ids) { pipeline.latest_builds.pluck(:id) }
+ before do
+ build = main_pipeline.builds.last
+ build.update_column(:finished_at, 1.day.ago) # Just to be sure we are included in the report window
+
+ # The JUnit fixture for the given build has 3 failures.
+ # This service will create 1 test case failure record for each.
+ Ci::TestFailureHistoryService.new(main_pipeline).execute
+ end
+
it 'renders test suite data' do
get_tests_show_json(build_ids)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq('test')
+
+ # Each test failure in this pipeline has a matching failure in the default branch
+ recent_failures = json_response['test_cases'].map { |tc| tc['recent_failures'] }
+ expect(recent_failures).to eq([
+ { 'count' => 1, 'base_branch' => 'master' },
+ { 'count' => 1, 'base_branch' => 'master' },
+ { 'count' => 1, 'base_branch' => 'master' }
+ ])
end
end
- context 'when pipeline does not have build report results' do
+ context 'when pipeline has no builds that matches the given build_ids' do
let(:pipeline) { create(:ci_empty_pipeline) }
let(:suite_name) { 'test' }
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index be4a1504fc9..e1405660ccb 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -272,72 +272,6 @@ RSpec.describe Projects::PipelinesController do
end
end
- describe 'GET #index' do
- subject(:request) { get :index, params: { namespace_id: project.namespace, project_id: project } }
-
- context 'experiment not active' do
- it 'does not push tracking_data to gon' do
- request
-
- expect(Gon.tracking_data).to be_nil
- end
-
- it 'does not record experiment_user' do
- expect { request }.not_to change(ExperimentUser, :count)
- end
- end
-
- context 'when experiment active' do
- before do
- stub_experiment(pipelines_empty_state: true)
- stub_experiment_for_subject(pipelines_empty_state: true)
- end
-
- it 'pushes tracking_data to Gon' do
- request
-
- expect(Gon.experiments["pipelinesEmptyState"]).to eq(true)
- expect(Gon.tracking_data).to match(
- {
- category: 'Growth::Activation::Experiment::PipelinesEmptyState',
- action: 'view',
- label: anything,
- property: 'experimental_group',
- value: anything
- }
- )
- end
-
- context 'no pipelines created an no CI set up' do
- before do
- stub_application_setting(auto_devops_enabled: false)
- end
-
- it 'records experiment_user' do
- expect { request }.to change(ExperimentUser, :count).by(1)
- end
- end
-
- context 'CI set up' do
- it 'does not record experiment_user' do
- expect { request }.not_to change(ExperimentUser, :count)
- end
- end
-
- context 'pipelines created' do
- let!(:pipeline) { create(:ci_pipeline, project: project) }
-
- before do
- stub_application_setting(auto_devops_enabled: false)
- end
-
- it 'does not record experiment_user' do
- expect { request }.not_to change(ExperimentUser, :count)
- end
- end
- end
- end
-
describe 'GET show.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index d30cc8cbfd9..53a7c2ca069 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -325,6 +325,18 @@ RSpec.describe Projects::ProjectMembersController do
expect(requester.reload.expires_at).not_to eq(expires_at.to_date)
end
+
+ it 'returns error status' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+
+ it 'returns error message' do
+ subject
+
+ expect(json_response).to eq({ 'message' => 'Expires at cannot be a date in the past' })
+ end
end
context 'when set to a date in the future' do
diff --git a/spec/controllers/projects/security/configuration_controller_spec.rb b/spec/controllers/projects/security/configuration_controller_spec.rb
new file mode 100644
index 00000000000..ef255d1efd0
--- /dev/null
+++ b/spec/controllers/projects/security/configuration_controller_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Security::ConfigurationController do
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+
+ before do
+ allow(controller).to receive(:ensure_security_and_compliance_enabled!)
+
+ sign_in(user)
+ end
+
+ describe 'GET show' do
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(secure_security_and_compliance_configuration_page_on_ce: false)
+ end
+
+ it 'renders not found' do
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when feature flag is enabled' do
+ context 'when user has guest access' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'denies access' do
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user has developer access' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'grants access' do
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:show)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb
index 01593f4133c..fe282baf769 100644
--- a/spec/controllers/projects/templates_controller_spec.rb
+++ b/spec/controllers/projects/templates_controller_spec.rb
@@ -165,7 +165,8 @@ RSpec.describe Projects::TemplatesController do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.size).to eq(2)
- expect(json_response).to match(expected_template_names)
+ expect(json_response.size).to eq(2)
+ expect(json_response.map { |x| x.slice('name') }).to match(expected_template_names)
end
it 'fails for user with no access' do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index a611ac16cd9..1e4ec48b119 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -5,6 +5,7 @@ require('spec_helper')
RSpec.describe ProjectsController do
include ExternalAuthorizationServiceHelpers
include ProjectForksHelper
+ using RSpec::Parameterized::TableSyntax
let_it_be(:project, reload: true) { create(:project, service_desk_enabled: false) }
let_it_be(:public_project) { create(:project, :public) }
@@ -324,14 +325,39 @@ RSpec.describe ProjectsController do
end
end
- context "redirection from http://someproject.git" do
- it 'redirects to project page (format.html)' do
- project = create(:project, :public)
+ context 'redirection from http://someproject.git' do
+ where(:user_type, :project_visibility, :expected_redirect) do
+ :anonymous | :public | :redirect_to_project
+ :anonymous | :internal | :redirect_to_signup
+ :anonymous | :private | :redirect_to_signup
- get :show, params: { namespace_id: project.namespace, id: project }, format: :git
+ :signed_in | :public | :redirect_to_project
+ :signed_in | :internal | :redirect_to_project
+ :signed_in | :private | nil
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to(namespace_project_path)
+ :member | :public | :redirect_to_project
+ :member | :internal | :redirect_to_project
+ :member | :private | :redirect_to_project
+ end
+
+ with_them do
+ let(:redirect_to_signup) { new_user_session_path }
+ let(:redirect_to_project) { project_path(project) }
+
+ let(:expected_status) { expected_redirect ? :found : :not_found }
+
+ before do
+ project.update!(visibility: project_visibility.to_s)
+ project.team.add_user(user, :guest) if user_type == :member
+ sign_in(user) unless user_type == :anonymous
+ end
+
+ it 'returns the expected status' do
+ get :show, params: { namespace_id: project.namespace, id: project }, format: :git
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ expect(response).to redirect_to(send(expected_redirect)) if expected_status == :found
+ end
end
end
@@ -384,6 +410,29 @@ RSpec.describe ProjectsController do
end
end
+ describe 'POST create' do
+ let!(:project_params) do
+ {
+ path: 'foo',
+ description: 'bar',
+ namespace_id: user.namespace.id,
+ visibility_level: Gitlab::VisibilityLevel::PUBLIC
+ }
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ it 'tracks a created event for the new_project_readme experiment', :experiment do
+ expect(experiment(:new_project_readme)).to track(:created, property: 'blank').on_any_instance.with_context(
+ actor: user
+ )
+
+ post :create, params: { project: project_params }
+ end
+ end
+
describe 'POST #archive' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
diff --git a/spec/controllers/registrations/experience_levels_controller_spec.rb b/spec/controllers/registrations/experience_levels_controller_spec.rb
index 015daba8682..79fa3f1474a 100644
--- a/spec/controllers/registrations/experience_levels_controller_spec.rb
+++ b/spec/controllers/registrations/experience_levels_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Registrations::ExperienceLevelsController do
+ include AfterNextHelpers
+
let_it_be(:namespace) { create(:group, path: 'group-path' ) }
let_it_be(:user) { create(:user) }
@@ -19,20 +21,11 @@ RSpec.describe Registrations::ExperienceLevelsController do
context 'with an authenticated user' do
before do
sign_in(user)
- stub_experiment_for_subject(onboarding_issues: true)
end
it { is_expected.to have_gitlab_http_status(:ok) }
- it { is_expected.to render_template('layouts/devise_experimental_onboarding_issues') }
+ it { is_expected.to render_template('layouts/signup_onboarding') }
it { is_expected.to render_template(:show) }
-
- context 'when not part of the onboarding issues experiment' do
- before do
- stub_experiment_for_subject(onboarding_issues: false)
- end
-
- it { is_expected.to have_gitlab_http_status(:not_found) }
- end
end
end
@@ -45,17 +38,11 @@ RSpec.describe Registrations::ExperienceLevelsController do
end
context 'with an authenticated user' do
+ let_it_be(:project) { build(:project, namespace: namespace, creator: user, path: 'project-path') }
+ let_it_be(:issues_board) { build(:board, id: 123, project: project) }
+
before do
sign_in(user)
- stub_experiment_for_subject(onboarding_issues: true)
- end
-
- context 'when not part of the onboarding issues experiment' do
- before do
- stub_experiment_for_subject(onboarding_issues: false)
- end
-
- it { is_expected.to have_gitlab_http_status(:not_found) }
end
context 'when user is successfully updated' do
@@ -85,91 +72,57 @@ RSpec.describe Registrations::ExperienceLevelsController do
end
end
- describe 'redirection' do
- let(:project) { build(:project, namespace: namespace, creator: user, path: 'project-path') }
- let(:issues_board) { build(:board, id: 123, project: project) }
+ context 'when "Learn GitLab" project exists' do
+ let(:learn_gitlab_available?) { true }
before do
- stub_experiment_for_subject(
- onboarding_issues: true,
- default_to_issues_board: default_to_issues_board_xp?
- )
allow_next_instance_of(LearnGitlab) do |learn_gitlab|
allow(learn_gitlab).to receive(:available?).and_return(learn_gitlab_available?)
allow(learn_gitlab).to receive(:project).and_return(project)
allow(learn_gitlab).to receive(:board).and_return(issues_board)
+ allow(learn_gitlab).to receive(:label).and_return(double(id: 1))
end
end
- context 'when namespace_path param is missing' do
- let(:params) { super().merge(namespace_path: nil) }
-
- where(
- default_to_issues_board_xp?: [true, false],
- learn_gitlab_available?: [true, false]
- )
-
- with_them do
- it { is_expected.to redirect_to('/') }
- end
- end
-
- context 'when we have a namespace_path param' do
- using RSpec::Parameterized::TableSyntax
+ context 'redirection' do
+ context 'when namespace_path param is missing' do
+ let(:params) { super().merge(namespace_path: nil) }
- where(:default_to_issues_board_xp?, :learn_gitlab_available?, :path) do
- true | true | '/group-path/project-path/-/boards/123'
- true | false | '/group-path'
- false | true | '/group-path'
- false | false | '/group-path'
- end
-
- with_them do
- it { is_expected.to redirect_to(path) }
- end
- end
- end
+ where(
+ learn_gitlab_available?: [true, false]
+ )
- describe 'applying the chosen level' do
- context 'when a "Learn GitLab" project is available' do
- before do
- allow_next_instance_of(LearnGitlab) do |learn_gitlab|
- allow(learn_gitlab).to receive(:available?).and_return(true)
- allow(learn_gitlab).to receive(:label).and_return(double(id: 1))
+ with_them do
+ it { is_expected.to redirect_to('/') }
end
end
- context 'when novice' do
- let(:params) { super().merge(experience_level: :novice) }
-
- it 'adds a BoardLabel' do
- expect_next_instance_of(Boards::UpdateService) do |service|
- expect(service).to receive(:execute)
- end
+ context 'when we have a namespace_path param' do
+ using RSpec::Parameterized::TableSyntax
- subject
+ where(:learn_gitlab_available?, :path) do
+ true | '/group-path/project-path/-/boards/123'
+ false | '/group-path'
end
- end
-
- context 'when experienced' do
- let(:params) { super().merge(experience_level: :experienced) }
- it 'does not add a BoardLabel' do
- expect(Boards::UpdateService).not_to receive(:new)
-
- subject
+ with_them do
+ it { is_expected.to redirect_to(path) }
end
end
end
- context 'when no "Learn GitLab" project exists' do
+ context 'when novice' do
let(:params) { super().merge(experience_level: :novice) }
- before do
- allow_next_instance_of(LearnGitlab) do |learn_gitlab|
- allow(learn_gitlab).to receive(:available?).and_return(false)
- end
+ it 'adds a BoardLabel' do
+ expect_next(Boards::UpdateService).to receive(:execute)
+
+ subject
end
+ end
+
+ context 'when experienced' do
+ let(:params) { super().merge(experience_level: :experienced) }
it 'does not add a BoardLabel' do
expect(Boards::UpdateService).not_to receive(:new)
@@ -178,6 +131,20 @@ RSpec.describe Registrations::ExperienceLevelsController do
end
end
end
+
+ context 'when no "Learn GitLab" project exists' do
+ let(:params) { super().merge(experience_level: :novice) }
+
+ before do
+ allow_next(LearnGitlab).to receive(:available?).and_return(false)
+ end
+
+ it 'does not add a BoardLabel' do
+ expect(Boards::UpdateService).not_to receive(:new)
+
+ subject
+ end
+ end
end
context 'when user update fails' do
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 737ec4f95c5..aac7c10d878 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -73,6 +73,18 @@ RSpec.describe RegistrationsController do
end
end
end
+
+ context 'audit events' do
+ context 'when not licensed' do
+ before do
+ stub_licensed_features(admin_audit_log: false)
+ end
+
+ it 'does not log any audit event' do
+ expect { subject }.not_to change(AuditEvent, :count)
+ end
+ end
+ end
end
context 'when the `require_admin_approval_after_user_signup` setting is turned off' do
diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb
index 34052496871..d21f602f90c 100644
--- a/spec/controllers/repositories/git_http_controller_spec.rb
+++ b/spec/controllers/repositories/git_http_controller_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Repositories::GitHttpController do
context 'when project_statistics_sync feature flag is disabled' do
before do
- stub_feature_flags(project_statistics_sync: false)
+ stub_feature_flags(project_statistics_sync: false, disable_git_http_fetch_writes: false)
end
it 'updates project statistics async for projects' do
@@ -47,17 +47,40 @@ RSpec.describe Repositories::GitHttpController do
end
it 'updates project statistics sync for projects' do
+ stub_feature_flags(disable_git_http_fetch_writes: false)
+
expect { send_request }.to change {
Projects::DailyStatisticsFinder.new(container).total_fetch_count
}.from(0).to(1)
end
- it 'records an onboarding progress action' do
- expect_next_instance_of(OnboardingProgressService) do |service|
- expect(service).to receive(:execute).with(action: :git_read)
+ it_behaves_like 'records an onboarding progress action', :git_read do
+ let(:namespace) { project.namespace }
+
+ subject { send_request }
+
+ before do
+ stub_feature_flags(disable_git_http_fetch_writes: false)
+ end
+ end
+
+ context 'when disable_git_http_fetch_writes is enabled' do
+ before do
+ stub_feature_flags(disable_git_http_fetch_writes: true)
+ end
+
+ it 'does not increment statistics' do
+ expect(Projects::FetchStatisticsIncrementService).not_to receive(:new)
+ expect(ProjectDailyStatisticsWorker).not_to receive(:perform_async)
+
+ send_request
end
- send_request
+ it 'does not record onboarding progress' do
+ expect(OnboardingProgressService).not_to receive(:new)
+
+ send_request
+ end
end
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index bbd39fd4c83..95cea10f0d0 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -5,278 +5,296 @@ require 'spec_helper'
RSpec.describe SearchController do
include ExternalAuthorizationServiceHelpers
- let(:user) { create(:user) }
+ context 'authorized user' do
+ let(:user) { create(:user) }
- before do
- sign_in(user)
- end
-
- shared_examples_for 'when the user cannot read cross project' do |action, params|
before do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?)
- .with(user, :read_cross_project, :global) { false }
+ sign_in(user)
end
- it 'blocks access without a project_id' do
- get action, params: params
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ shared_examples_for 'when the user cannot read cross project' do |action, params|
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?)
+ .with(user, :read_cross_project, :global) { false }
+ end
- it 'allows access with a project_id' do
- get action, params: params.merge(project_id: create(:project, :public).id)
+ it 'blocks access without a project_id' do
+ get action, params: params
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- shared_examples_for 'with external authorization service enabled' do |action, params|
- let(:project) { create(:project, namespace: user.namespace) }
- let(:note) { create(:note_on_issue, project: project) }
+ it 'allows access with a project_id' do
+ get action, params: params.merge(project_id: create(:project, :public).id)
- before do
- enable_external_authorization_service_check
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
- it 'renders a 403 when no project is given' do
- get action, params: params
+ shared_examples_for 'with external authorization service enabled' do |action, params|
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:note) { create(:note_on_issue, project: project) }
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ before do
+ enable_external_authorization_service_check
+ end
- it 'renders a 200 when a project was set' do
- get action, params: params.merge(project_id: project.id)
+ it 'renders a 403 when no project is given' do
+ get action, params: params
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
- describe 'GET #show' do
- it_behaves_like 'when the user cannot read cross project', :show, { search: 'hello' } do
- it 'still allows accessing the search page' do
- get :show
+ it 'renders a 200 when a project was set' do
+ get action, params: params.merge(project_id: project.id)
expect(response).to have_gitlab_http_status(:ok)
end
end
- it_behaves_like 'with external authorization service enabled', :show, { search: 'hello' }
+ describe 'GET #show' do
+ it_behaves_like 'when the user cannot read cross project', :show, { search: 'hello' } do
+ it 'still allows accessing the search page' do
+ get :show
- context 'uses the right partials depending on scope' do
- using RSpec::Parameterized::TableSyntax
- render_views
-
- let_it_be(:project) { create(:project, :public, :repository, :wiki_repo) }
-
- before do
- expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
- subject { get(:show, params: { project_id: project.id, scope: scope, search: 'merge' }) }
+ it_behaves_like 'with external authorization service enabled', :show, { search: 'hello' }
- where(:partial, :scope) do
- '_blob' | :blobs
- '_wiki_blob' | :wiki_blobs
- '_commit' | :commits
- end
+ context 'uses the right partials depending on scope' do
+ using RSpec::Parameterized::TableSyntax
+ render_views
- with_them do
- it do
- project_wiki = create(:project_wiki, project: project, user: user)
- create(:wiki_page, wiki: project_wiki, title: 'merge', content: 'merge')
+ let_it_be(:project) { create(:project, :public, :repository, :wiki_repo) }
- expect(subject).to render_template("search/results/#{partial}")
+ before do
+ expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
end
- end
- end
- context 'global search' do
- using RSpec::Parameterized::TableSyntax
- render_views
+ subject { get(:show, params: { project_id: project.id, scope: scope, search: 'merge' }) }
- context 'when block_anonymous_global_searches is disabled' do
- before do
- stub_feature_flags(block_anonymous_global_searches: false)
+ where(:partial, :scope) do
+ '_blob' | :blobs
+ '_wiki_blob' | :wiki_blobs
+ '_commit' | :commits
end
- it 'omits pipeline status from load' do
- project = create(:project, :public)
- expect(Gitlab::Cache::Ci::ProjectPipelineStatus).not_to receive(:load_in_batch_for_projects)
+ with_them do
+ it do
+ project_wiki = create(:project_wiki, project: project, user: user)
+ create(:wiki_page, wiki: project_wiki, title: 'merge', content: 'merge')
- get :show, params: { scope: 'projects', search: project.name }
-
- expect(assigns[:search_objects].first).to eq project
+ expect(subject).to render_template("search/results/#{partial}")
+ end
end
+ end
- context 'check search term length' do
- let(:search_queries) do
- char_limit = SearchService::SEARCH_CHAR_LIMIT
- term_limit = SearchService::SEARCH_TERM_LIMIT
- {
- chars_under_limit: ('a' * (char_limit - 1)),
- chars_over_limit: ('a' * (char_limit + 1)),
- terms_under_limit: ('abc ' * (term_limit - 1)),
- terms_over_limit: ('abc ' * (term_limit + 1))
- }
+ context 'global search' do
+ using RSpec::Parameterized::TableSyntax
+ render_views
+
+ context 'when block_anonymous_global_searches is disabled' do
+ before do
+ stub_feature_flags(block_anonymous_global_searches: false)
end
- where(:string_name, :expectation) do
- :chars_under_limit | :not_to_set_flash
- :chars_over_limit | :set_chars_flash
- :terms_under_limit | :not_to_set_flash
- :terms_over_limit | :set_terms_flash
+ it 'omits pipeline status from load' do
+ project = create(:project, :public)
+ expect(Gitlab::Cache::Ci::ProjectPipelineStatus).not_to receive(:load_in_batch_for_projects)
+
+ get :show, params: { scope: 'projects', search: project.name }
+
+ expect(assigns[:search_objects].first).to eq project
end
- with_them do
- it do
- get :show, params: { scope: 'projects', search: search_queries[string_name] }
-
- case expectation
- when :not_to_set_flash
- expect(controller).not_to set_flash[:alert]
- when :set_chars_flash
- expect(controller).to set_flash[:alert].to(/characters/)
- when :set_terms_flash
- expect(controller).to set_flash[:alert].to(/terms/)
+ context 'check search term length' do
+ let(:search_queries) do
+ char_limit = SearchService::SEARCH_CHAR_LIMIT
+ term_limit = SearchService::SEARCH_TERM_LIMIT
+ {
+ chars_under_limit: ('a' * (char_limit - 1)),
+ chars_over_limit: ('a' * (char_limit + 1)),
+ terms_under_limit: ('abc ' * (term_limit - 1)),
+ terms_over_limit: ('abc ' * (term_limit + 1))
+ }
+ end
+
+ where(:string_name, :expectation) do
+ :chars_under_limit | :not_to_set_flash
+ :chars_over_limit | :set_chars_flash
+ :terms_under_limit | :not_to_set_flash
+ :terms_over_limit | :set_terms_flash
+ end
+
+ with_them do
+ it do
+ get :show, params: { scope: 'projects', search: search_queries[string_name] }
+
+ case expectation
+ when :not_to_set_flash
+ expect(controller).not_to set_flash[:alert]
+ when :set_chars_flash
+ expect(controller).to set_flash[:alert].to(/characters/)
+ when :set_terms_flash
+ expect(controller).to set_flash[:alert].to(/terms/)
+ end
end
end
end
end
- end
- context 'when block_anonymous_global_searches is enabled' do
- context 'for unauthenticated user' do
- before do
- sign_out(user)
- end
+ context 'when block_anonymous_global_searches is enabled' do
+ context 'for unauthenticated user' do
+ before do
+ sign_out(user)
+ end
- it 'redirects to login page' do
- get :show, params: { scope: 'projects', search: '*' }
+ it 'redirects to login page' do
+ get :show, params: { scope: 'projects', search: '*' }
- expect(response).to redirect_to new_user_session_path
+ expect(response).to redirect_to new_user_session_path
+ end
end
- end
- context 'for authenticated user' do
- it 'succeeds' do
- get :show, params: { scope: 'projects', search: '*' }
+ context 'for authenticated user' do
+ it 'succeeds' do
+ get :show, params: { scope: 'projects', search: '*' }
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
end
end
- end
- it 'finds issue comments' do
- project = create(:project, :public)
- note = create(:note_on_issue, project: project)
+ it 'finds issue comments' do
+ project = create(:project, :public)
+ note = create(:note_on_issue, project: project)
- get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
-
- expect(assigns[:search_objects].first).to eq note
- end
+ get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
- context 'unique users tracking' do
- before do
- allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+ expect(assigns[:search_objects].first).to eq note
end
- it_behaves_like 'tracking unique hll events', :search_track_unique_users do
- subject(:request) { get :show, params: { scope: 'projects', search: 'term' } }
+ context 'unique users tracking' do
+ before do
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+ end
+
+ it_behaves_like 'tracking unique hll events' do
+ subject(:request) { get :show, params: { scope: 'projects', search: 'term' } }
- let(:target_id) { 'i_search_total' }
- let(:expected_type) { instance_of(String) }
+ let(:target_id) { 'i_search_total' }
+ let(:expected_type) { instance_of(String) }
+ end
end
- end
- context 'on restricted projects' do
- context 'when signed out' do
- before do
- sign_out(user)
+ context 'on restricted projects' do
+ context 'when signed out' do
+ before do
+ sign_out(user)
+ end
+
+ it "doesn't expose comments on issues" do
+ project = create(:project, :public, :issues_private)
+ note = create(:note_on_issue, project: project)
+
+ get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
+
+ expect(assigns[:search_objects].count).to eq(0)
+ end
end
- it "doesn't expose comments on issues" do
- project = create(:project, :public, :issues_private)
- note = create(:note_on_issue, project: project)
+ it "doesn't expose comments on merge_requests" do
+ project = create(:project, :public, :merge_requests_private)
+ note = create(:note_on_merge_request, project: project)
get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
expect(assigns[:search_objects].count).to eq(0)
end
- end
- it "doesn't expose comments on merge_requests" do
- project = create(:project, :public, :merge_requests_private)
- note = create(:note_on_merge_request, project: project)
+ it "doesn't expose comments on snippets" do
+ project = create(:project, :public, :snippets_private)
+ note = create(:note_on_project_snippet, project: project)
- get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
+ get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
- expect(assigns[:search_objects].count).to eq(0)
+ expect(assigns[:search_objects].count).to eq(0)
+ end
end
+ end
- it "doesn't expose comments on snippets" do
- project = create(:project, :public, :snippets_private)
- note = create(:note_on_project_snippet, project: project)
-
- get :show, params: { project_id: project.id, scope: 'notes', search: note.note }
+ describe 'GET #count' do
+ it_behaves_like 'when the user cannot read cross project', :count, { search: 'hello', scope: 'projects' }
+ it_behaves_like 'with external authorization service enabled', :count, { search: 'hello', scope: 'projects' }
- expect(assigns[:search_objects].count).to eq(0)
- end
- end
- end
+ it 'returns the result count for the given term and scope' do
+ create(:project, :public, name: 'hello world')
+ create(:project, :public, name: 'foo bar')
- describe 'GET #count' do
- it_behaves_like 'when the user cannot read cross project', :count, { search: 'hello', scope: 'projects' }
- it_behaves_like 'with external authorization service enabled', :count, { search: 'hello', scope: 'projects' }
+ get :count, params: { search: 'hello', scope: 'projects' }
- it 'returns the result count for the given term and scope' do
- create(:project, :public, name: 'hello world')
- create(:project, :public, name: 'foo bar')
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'count' => '1' })
+ end
- get :count, params: { search: 'hello', scope: 'projects' }
+ it 'raises an error if search term is missing' do
+ expect do
+ get :count, params: { scope: 'projects' }
+ end.to raise_error(ActionController::ParameterMissing)
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to eq({ 'count' => '1' })
+ it 'raises an error if search scope is missing' do
+ expect do
+ get :count, params: { search: 'hello' }
+ end.to raise_error(ActionController::ParameterMissing)
+ end
end
- it 'raises an error if search term is missing' do
- expect do
- get :count, params: { scope: 'projects' }
- end.to raise_error(ActionController::ParameterMissing)
+ describe 'GET #autocomplete' do
+ it_behaves_like 'when the user cannot read cross project', :autocomplete, { term: 'hello' }
+ it_behaves_like 'with external authorization service enabled', :autocomplete, { term: 'hello' }
end
- it 'raises an error if search scope is missing' do
- expect do
- get :count, params: { search: 'hello' }
- end.to raise_error(ActionController::ParameterMissing)
- end
- end
+ describe '#append_info_to_payload' do
+ it 'appends search metadata for logging' do
+ last_payload = nil
+ original_append_info_to_payload = controller.method(:append_info_to_payload)
- describe 'GET #autocomplete' do
- it_behaves_like 'when the user cannot read cross project', :autocomplete, { term: 'hello' }
- it_behaves_like 'with external authorization service enabled', :autocomplete, { term: 'hello' }
- end
+ expect(controller).to receive(:append_info_to_payload) do |payload|
+ original_append_info_to_payload.call(payload)
+ last_payload = payload
+ end
- describe '#append_info_to_payload' do
- it 'appends search metadata for logging' do
- last_payload = nil
- original_append_info_to_payload = controller.method(:append_info_to_payload)
+ get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', confidential: true, state: true, force_search_results: true }
- expect(controller).to receive(:append_info_to_payload) do |payload|
- original_append_info_to_payload.call(payload)
- last_payload = payload
+ expect(last_payload[:metadata]['meta.search.group_id']).to eq('123')
+ expect(last_payload[:metadata]['meta.search.project_id']).to eq('456')
+ expect(last_payload[:metadata]).not_to have_key('meta.search.search')
+ expect(last_payload[:metadata]['meta.search.scope']).to eq('issues')
+ expect(last_payload[:metadata]['meta.search.force_search_results']).to eq('true')
+ expect(last_payload[:metadata]['meta.search.filters.confidential']).to eq('true')
+ expect(last_payload[:metadata]['meta.search.filters.state']).to eq('true')
end
+ end
+ end
- get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', confidential: true, state: true, force_search_results: true }
+ context 'unauthorized user' do
+ describe 'GET #opensearch' do
+ render_views
+
+ it 'renders xml' do
+ get :opensearch, format: :xml
+
+ doc = Nokogiri::XML.parse(response.body)
- expect(last_payload[:metadata]['meta.search.group_id']).to eq('123')
- expect(last_payload[:metadata]['meta.search.project_id']).to eq('456')
- expect(last_payload[:metadata]).not_to have_key('meta.search.search')
- expect(last_payload[:metadata]['meta.search.scope']).to eq('issues')
- expect(last_payload[:metadata]['meta.search.force_search_results']).to eq('true')
- expect(last_payload[:metadata]['meta.search.filters.confidential']).to eq('true')
- expect(last_payload[:metadata]['meta.search.filters.state']).to eq('true')
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(doc.css('OpenSearchDescription ShortName').text).to eq('GitLab')
+ expect(doc.css('OpenSearchDescription *').map(&:name)).to eq(%w[ShortName Description InputEncoding Image Url SearchForm])
+ end
end
end
end
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 51cecb348c8..50d6ac8f23d 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe SnippetsController do
expect(response).to have_gitlab_http_status(:ok)
end
- it_behaves_like 'tracking unique hll events', :usage_data_i_snippets_show do
+ it_behaves_like 'tracking unique hll events' do
subject(:request) { get :show, params: { id: public_snippet.to_param } }
let(:target_id) { 'i_snippets_show' }
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 3087beb1326..b2c77a06f19 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe 'Database schema' do
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 user_id],
+ ci_namespace_monthly_usages: %w[namespace_id],
ci_pipelines: %w[user_id],
ci_runner_projects: %w[runner_id],
ci_trigger_requests: %w[commit_id],
@@ -184,6 +185,7 @@ RSpec.describe 'Database schema' do
"ApplicationSetting" => %w[repository_storages_weighted],
"AlertManagement::Alert" => %w[payload],
"Ci::BuildMetadata" => %w[config_options config_variables],
+ "ExperimentSubject" => %w[context],
"ExperimentUser" => %w[context],
"Geo::Event" => %w[payload],
"GeoNodeStatus" => %w[status],
diff --git a/spec/deprecation_toolkit_env.rb b/spec/deprecation_toolkit_env.rb
index bc90f67f0db..d2ff2d2cb37 100644
--- a/spec/deprecation_toolkit_env.rb
+++ b/spec/deprecation_toolkit_env.rb
@@ -1,18 +1,84 @@
# frozen_string_literal: true
-if ENV.key?('RECORD_DEPRECATIONS')
- require 'deprecation_toolkit'
- require 'deprecation_toolkit/rspec'
- DeprecationToolkit::Configuration.test_runner = :rspec
- DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
- DeprecationToolkit::Configuration.behavior = DeprecationToolkit::Behaviors::Record
-
- # Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7.2
- Warning[:deprecated] = true
-
- kwargs_warnings = [
- # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
+require 'deprecation_toolkit'
+require 'deprecation_toolkit/rspec'
+
+module DeprecationToolkitEnv
+ module DeprecationBehaviors
+ class SelectiveRaise
+ attr_reader :disallowed_deprecations_proc
+
+ class RaiseDisallowedDeprecation < StandardError
+ def initialize(test, current_deprecations)
+ message = <<~EOF
+ Disallowed deprecations detected while running test #{test}:
+
+ #{current_deprecations.deprecations.join("\n")}
+ EOF
+
+ super(message)
+ end
+ end
+
+ def initialize(disallowed_deprecations_proc)
+ @disallowed_deprecations_proc = disallowed_deprecations_proc
+ end
+
+ # Note: trigger does not get called if the current_deprecations matches recorded_deprecations
+ # See https://github.com/Shopify/deprecation_toolkit/blob/2398f38acb62220fb79a6cd720f61d9cea26bc06/lib/deprecation_toolkit/test_triggerer.rb#L8-L11
+ def trigger(test, current_deprecations, recorded_deprecations)
+ if selected_for_raise?(current_deprecations)
+ raise RaiseDisallowedDeprecation.new(test, current_deprecations)
+ elsif ENV['RECORD_DEPRECATIONS']
+ record(test, current_deprecations, recorded_deprecations)
+ end
+ end
+
+ private
+
+ def selected_for_raise?(current_deprecations)
+ disallowed_deprecations_proc.call(current_deprecations.deprecations_without_stacktrace)
+ end
+
+ def record(test, current_deprecations, recorded_deprecations)
+ ::DeprecationToolkit::Behaviors::Record.trigger(test, current_deprecations, recorded_deprecations)
+ end
+ end
+ end
+
+ # Taken from https://github.com/jeremyevans/ruby-warning/blob/1.1.0/lib/warning.rb#L18
+ def self.kwargs_warning
%r{warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z}
- ]
- DeprecationToolkit::Configuration.warnings_treated_as_deprecation = kwargs_warnings
+ end
+
+ # Allow these Gem paths to trigger keyword warnings as we upgrade these gems
+ # one by one
+ def self.allowed_kwarg_warning_paths
+ %w[
+ activerecord-6.0.3.4/lib/active_record/migration.rb
+ devise-4.7.3/lib/devise/test/controller_helpers.rb
+ activesupport-6.0.3.4/lib/active_support/cache.rb
+ batch-loader-1.4.0/lib/batch_loader/graphql.rb
+ carrierwave-1.3.1/lib/carrierwave/sanitized_file.rb
+ activerecord-6.0.3.4/lib/active_record/relation.rb
+ ]
+ end
+
+ def self.configure!
+ # Enable ruby deprecations for keywords, it's suppressed by default in Ruby 2.7.2
+ Warning[:deprecated] = true
+
+ DeprecationToolkit::Configuration.test_runner = :rspec
+ DeprecationToolkit::Configuration.deprecation_path = 'deprecations'
+ DeprecationToolkit::Configuration.warnings_treated_as_deprecation = [kwargs_warning]
+
+ disallowed_deprecations = -> (deprecations) do
+ deprecations.any? do |deprecation|
+ kwargs_warning.match?(deprecation) &&
+ allowed_kwarg_warning_paths.none? { |path| deprecation.include?(path) }
+ end
+ end
+
+ DeprecationToolkit::Configuration.behavior = DeprecationBehaviors::SelectiveRaise.new(disallowed_deprecations)
+ end
end
diff --git a/spec/experiments/application_experiment/cache_spec.rb b/spec/experiments/application_experiment/cache_spec.rb
index a420d557155..4caa91e6ac4 100644
--- a/spec/experiments/application_experiment/cache_spec.rb
+++ b/spec/experiments/application_experiment/cache_spec.rb
@@ -51,16 +51,4 @@ RSpec.describe ApplicationExperiment::Cache do
'invalid call to clear a non-hash cache key'
)
end
-
- context "when the :caching_experiments feature is disabled" do
- before do
- stub_feature_flags(caching_experiments: false)
- end
-
- it "doesn't write to the cache" do
- subject.write(key_field, 'value')
-
- expect(subject.read(key_field)).to be_nil
- end
- end
end
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb
index ece52d37351..501d344e920 100644
--- a/spec/experiments/application_experiment_spec.rb
+++ b/spec/experiments/application_experiment_spec.rb
@@ -2,8 +2,60 @@
require 'spec_helper'
-RSpec.describe ApplicationExperiment do
- subject { described_class.new(:stub) }
+RSpec.describe ApplicationExperiment, :experiment do
+ subject { described_class.new('namespaced/stub') }
+
+ let(:feature_definition) do
+ { name: 'namespaced_stub', type: 'experiment', group: 'group::adoption', default_enabled: false }
+ end
+
+ around do |example|
+ Feature::Definition.definitions[:namespaced_stub] = Feature::Definition.new('namespaced_stub.yml', feature_definition)
+ example.run
+ Feature::Definition.definitions.delete(:namespaced_stub)
+ end
+
+ before do
+ allow(subject).to receive(:enabled?).and_return(true)
+ end
+
+ it "naively assumes a 1x1 relationship to feature flags for tests" do
+ expect(Feature).to receive(:persist_used!).with('namespaced_stub')
+
+ described_class.new('namespaced/stub')
+ end
+
+ describe "enabled" do
+ before do
+ allow(subject).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(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 "publishing results" do
it "tracks the assignment" do
@@ -16,9 +68,9 @@ RSpec.describe ApplicationExperiment do
expect(Gon.global).to receive(:push).with(
{
experiment: {
- 'stub' => { # string key because it can be namespaced
- experiment: 'stub',
- key: 'e8f65fd8d973f9985dc7ea3cf1614ae1',
+ 'namespaced/stub' => { # string key because it can be namespaced
+ experiment: 'namespaced/stub',
+ key: '86208ac54ca798e11f127e8b23ec396a',
variant: 'control'
}
}
@@ -31,8 +83,8 @@ RSpec.describe ApplicationExperiment do
end
describe "tracking events", :snowplow do
- it "doesn't track if excluded" do
- subject.exclude { true }
+ it "doesn't track if we shouldn't track" do
+ allow(subject).to receive(:should_track?).and_return(false)
subject.track(:action)
@@ -45,7 +97,7 @@ RSpec.describe ApplicationExperiment do
])
expect_snowplow_event(
- category: 'stub',
+ category: 'namespaced/stub',
action: 'action',
property: '_property_',
context: [
@@ -55,7 +107,7 @@ RSpec.describe ApplicationExperiment do
},
{
schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0',
- data: { experiment: 'stub', key: 'e8f65fd8d973f9985dc7ea3cf1614ae1', variant: 'control' }
+ data: { experiment: 'namespaced/stub', key: '86208ac54ca798e11f127e8b23ec396a', variant: 'control' }
}
]
)
@@ -63,18 +115,77 @@ RSpec.describe ApplicationExperiment do
end
describe "variant resolution" do
- it "returns nil when not rolled out" do
- stub_feature_flags(stub: false)
+ context "when using the default feature flag percentage rollout" do
+ 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)
+
+ expect(subject.variant.name).to eq('control')
+ end
+
+ it "returns nil when not rolled out" do
+ stub_feature_flags(namespaced_stub: false)
+
+ expect(subject.variant.name).to eq('control')
+ end
+
+ context "when rolled out to 100%" do
+ it "returns the first variant name" do
+ subject.try(:variant1) {}
+ subject.try(:variant2) {}
- expect(subject.variant.name).to eq('control')
+ expect(subject.variant.name).to eq('variant1')
+ end
+ end
end
- context "when rolled out to 100%" do
- it "returns the first variant name" do
- subject.try(:variant1) {}
- subject.try(:variant2) {}
+ context "when using the round_robin strategy", :clean_gitlab_redis_shared_state do
+ context "when variants aren't supplied" do
+ subject :inheriting_class do
+ Class.new(described_class) do
+ def rollout_strategy
+ :round_robin
+ end
+ end.new('namespaced/stub')
+ end
+
+ it "raises an error" do
+ expect { inheriting_class.variants }.to raise_error(NotImplementedError)
+ end
+ end
+
+ context "when variants are supplied" do
+ let(:inheriting_class) do
+ Class.new(described_class) do
+ def rollout_strategy
+ :round_robin
+ end
+
+ def variants
+ %i[variant1 variant2 control]
+ end
+ end
+ end
+
+ it "proves out round robin in variant selection", :aggregate_failures do
+ instance_1 = inheriting_class.new('namespaced/stub')
+ allow(instance_1).to receive(:enabled?).and_return(true)
+ instance_2 = inheriting_class.new('namespaced/stub')
+ allow(instance_2).to receive(:enabled?).and_return(true)
+ instance_3 = inheriting_class.new('namespaced/stub')
+ allow(instance_3).to receive(:enabled?).and_return(true)
+
+ instance_1.try {}
+
+ expect(instance_1.variant.name).to eq('variant2')
+
+ instance_2.try {}
+
+ expect(instance_2.variant.name).to eq('control')
+
+ instance_3.try {}
- expect(subject.variant.name).to eq('variant1')
+ expect(instance_3.variant.name).to eq('variant1')
+ end
end
end
end
@@ -105,7 +216,7 @@ RSpec.describe ApplicationExperiment do
# every control variant assigned, we'd inflate the cache size and
# wouldn't be able to roll out to subjects that we'd already assigned to
# the control.
- stub_feature_flags(stub: false) # simulate being not rolled out
+ stub_feature_flags(namespaced_stub: false) # simulate being not rolled out
expect(subject.variant.name).to eq('control') # if we ask, it should be control
diff --git a/spec/experiments/members/invite_email_experiment_spec.rb b/spec/experiments/members/invite_email_experiment_spec.rb
new file mode 100644
index 00000000000..4376c021385
--- /dev/null
+++ b/spec/experiments/members/invite_email_experiment_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Members::InviteEmailExperiment do
+ subject :invite_email do
+ experiment('members/invite_email', actor: double('Member', created_by: double('User', avatar_url: '_avatar_url_')))
+ end
+
+ before do
+ allow(invite_email).to receive(:enabled?).and_return(true)
+ end
+
+ describe "#rollout_strategy" do
+ it "resolves to round_robin" do
+ expect(invite_email.rollout_strategy).to eq(:round_robin)
+ end
+ end
+
+ describe "#variants" do
+ it "has all the expected variants" do
+ expect(invite_email.variants).to match(%i[avatar permission_info control])
+ end
+ end
+
+ describe "exclusions", :experiment do
+ it "excludes when created by is nil" do
+ expect(experiment('members/invite_email')).to exclude(actor: double(created_by: nil))
+ end
+
+ it "excludes when avatar_url is nil" do
+ member_without_avatar_url = double('Member', created_by: double('User', avatar_url: nil))
+
+ expect(experiment('members/invite_email')).to exclude(actor: member_without_avatar_url)
+ end
+ end
+end
diff --git a/spec/experiments/new_project_readme_experiment_spec.rb b/spec/experiments/new_project_readme_experiment_spec.rb
new file mode 100644
index 00000000000..17e28cf6e7f
--- /dev/null
+++ b/spec/experiments/new_project_readme_experiment_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe NewProjectReadmeExperiment, :experiment do
+ subject { described_class.new(actor: actor) }
+
+ let(:actor) { User.new(id: 42, created_at: Time.current) }
+
+ before do
+ stub_experiments(new_project_readme: :control)
+ end
+
+ describe "exclusions" do
+ let(:threshold) { described_class::MAX_ACCOUNT_AGE }
+
+ it { is_expected.to exclude(actor: User.new(created_at: (threshold + 1.minute).ago)) }
+ it { is_expected.not_to exclude(actor: User.new(created_at: (threshold - 1.minute).ago)) }
+ end
+
+ describe "the control behavior" do
+ subject { described_class.new(actor: actor).run(:control) }
+
+ it { is_expected.to be false }
+ end
+
+ describe "the candidate behavior" do
+ subject { described_class.new(actor: actor).run(:candidate) }
+
+ it { is_expected.to be true }
+ end
+
+ context "when tracking initial writes" do
+ let!(:project) { create(:project, :repository) }
+
+ def stub_gitaly_count(count = 1)
+ allow(Gitlab::GitalyClient).to receive(:call).and_call_original
+ allow(Gitlab::GitalyClient).to receive(:call).with(anything, :commit_service, :count_commits, anything, anything)
+ .and_return(double(count: count))
+ end
+
+ before do
+ stub_gitaly_count
+ end
+
+ it "tracks an event for the first commit on a project with a repository" do
+ expect(subject).to receive(:track).with(:write, property: project.created_at.to_s, value: 1).and_call_original
+
+ subject.track_initial_writes(project)
+ end
+
+ it "tracks an event for the second commit on a project with a repository" do
+ stub_gitaly_count(2)
+
+ expect(subject).to receive(:track).with(:write, property: project.created_at.to_s, value: 2).and_call_original
+
+ subject.track_initial_writes(project)
+ end
+
+ it "doesn't track if the repository has more then 2 commits" do
+ stub_gitaly_count(3)
+
+ expect(subject).not_to receive(:track)
+
+ subject.track_initial_writes(project)
+ end
+
+ it "doesn't track when we generally shouldn't" do
+ allow(subject).to receive(:should_track?).and_return(false)
+
+ expect(subject).not_to receive(:track)
+
+ subject.track_initial_writes(project)
+ end
+
+ it "doesn't track if the project is older" do
+ expect(project).to receive(:created_at).and_return(described_class::EXPERIMENT_START_DATE - 1.minute)
+
+ expect(subject).not_to receive(:track)
+
+ subject.track_initial_writes(project)
+ end
+
+ it "handles exceptions by logging them" do
+ allow(Gitlab::GitalyClient).to receive(:call).with(anything, :commit_service, :count_commits, anything, anything)
+ .and_raise(e = StandardError.new('_message_'))
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(e, experiment: 'new_project_readme')
+
+ subject.track_initial_writes(project)
+ end
+ end
+end
diff --git a/spec/experiments/strategy/round_robin_spec.rb b/spec/experiments/strategy/round_robin_spec.rb
new file mode 100644
index 00000000000..f837a4701b2
--- /dev/null
+++ b/spec/experiments/strategy/round_robin_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Strategy::RoundRobin, :clean_gitlab_redis_shared_state do
+ subject(:round_robin) { described_class.new('_key_', %i[variant1 variant2]) }
+
+ describe "execute" do
+ context "when there are 2 variants" do
+ it "proves out round robin in selection", :aggregate_failures do
+ expect(round_robin.execute).to eq :variant2
+ expect(round_robin.execute).to eq :variant1
+ expect(round_robin.execute).to eq :variant2
+ end
+ end
+
+ context "when there are more than 2 variants" do
+ subject(:round_robin) { described_class.new('_key_', %i[variant1 variant2 variant3]) }
+
+ it "proves out round robin in selection", :aggregate_failures do
+ expect(round_robin.execute).to eq :variant2
+ expect(round_robin.execute).to eq :variant3
+ expect(round_robin.execute).to eq :variant1
+
+ expect(round_robin.execute).to eq :variant2
+ expect(round_robin.execute).to eq :variant3
+ expect(round_robin.execute).to eq :variant1
+ end
+ end
+
+ context "when writing to cache fails" do
+ subject(:round_robin) { described_class.new('_key_', []) }
+
+ it "raises an error and logs" do
+ allow(Gitlab::Redis::SharedState).to receive(:with).and_raise(Strategy::RoundRobin::CacheError)
+ expect(Gitlab::AppLogger).to receive(:warn)
+
+ expect { round_robin.execute }.to raise_error(Strategy::RoundRobin::CacheError)
+ end
+ end
+ end
+
+ describe "#counter_expires_in" do
+ it 'displays the expiration time in seconds' do
+ round_robin.execute
+
+ expect(round_robin.counter_expires_in).to be_between(0, described_class::COUNTER_EXPIRE_TIME)
+ end
+ end
+
+ describe '#value' do
+ it 'get the count' do
+ expect(round_robin.counter_value).to eq(0)
+
+ round_robin.execute
+
+ expect(round_robin.counter_value).to eq(1)
+ end
+ end
+
+ describe '#reset!' do
+ it 'resets the count down to zero' do
+ 3.times { round_robin.execute }
+
+ expect { round_robin.reset! }.to change { round_robin.counter_value }.from(3).to(0)
+ end
+ end
+end
diff --git a/spec/factories/audit_events.rb b/spec/factories/audit_events.rb
index 4e72976a9e5..05b86d2f13b 100644
--- a/spec/factories/audit_events.rb
+++ b/spec/factories/audit_events.rb
@@ -49,6 +49,21 @@ FactoryBot.define do
end
end
+ trait :unauthenticated do
+ author_id { -1 }
+ details do
+ {
+ custom_message: 'Custom action',
+ author_name: 'An unauthenticated user',
+ target_id: target_project.id,
+ target_type: 'Project',
+ target_details: target_project.name,
+ ip_address: '127.0.0.1',
+ entity_path: target_project.full_path
+ }
+ end
+ end
+
trait :group_event do
transient { target_group { association(:group) } }
diff --git a/spec/factories/ci/bridge.rb b/spec/factories/ci/bridge.rb
index 7727a468633..6cbcabca7ab 100644
--- a/spec/factories/ci/bridge.rb
+++ b/spec/factories/ci/bridge.rb
@@ -1,17 +1,10 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :ci_bridge, class: 'Ci::Bridge' do
+ factory :ci_bridge, class: 'Ci::Bridge', parent: :ci_processable do
name { 'bridge' }
- stage { 'test' }
- stage_idx { 0 }
- ref { 'master' }
- tag { false }
created_at { '2013-10-29 09:50:00 CET' }
status { :created }
- scheduling_type { 'stage' }
-
- pipeline factory: :ci_pipeline
trait :variables do
yaml_variables do
@@ -53,6 +46,11 @@ FactoryBot.define do
finished_at { '2013-10-29 09:53:28 CET' }
end
+ trait :success do
+ finished
+ status { 'success' }
+ end
+
trait :failed do
finished
status { 'failed' }
@@ -75,5 +73,9 @@ FactoryBot.define do
trait :playable do
manual
end
+
+ trait :allowed_to_fail do
+ allow_failure { true }
+ end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 24abad66530..c4f9a4ce82b 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -3,15 +3,10 @@
include ActionDispatch::TestProcess
FactoryBot.define do
- factory :ci_build, class: 'Ci::Build' do
+ factory :ci_build, class: 'Ci::Build', parent: :ci_processable do
name { 'test' }
- stage { 'test' }
- stage_idx { 0 }
- ref { 'master' }
- tag { false }
add_attribute(:protected) { false }
created_at { 'Di 29. Okt 09:50:00 CET 2013' }
- scheduling_type { 'stage' }
pending
options do
@@ -28,7 +23,6 @@ FactoryBot.define do
]
end
- pipeline factory: :ci_pipeline
project { pipeline.project }
trait :degenerated do
@@ -79,10 +73,6 @@ FactoryBot.define do
status { 'created' }
end
- trait :waiting_for_resource do
- status { 'waiting_for_resource' }
- end
-
trait :preparing do
status { 'preparing' }
end
@@ -213,14 +203,6 @@ FactoryBot.define do
trigger_request factory: :ci_trigger_request
end
- trait :resource_group do
- waiting_for_resource_at { 5.minutes.ago }
-
- after(:build) do |build, evaluator|
- build.resource_group = create(:ci_resource_group, project: build.project)
- end
- end
-
trait :with_deployment do
after(:build) do |build, evaluator|
##
@@ -314,6 +296,18 @@ FactoryBot.define do
end
end
+ trait :sast_report do
+ after(:build) do |build|
+ build.job_artifacts << create(:ci_job_artifact, :sast, job: build)
+ end
+ end
+
+ trait :secret_detection_report do
+ after(:build) do |build|
+ build.job_artifacts << create(:ci_job_artifact, :secret_detection, job: build)
+ end
+ end
+
trait :test_reports do
after(:build) do |build|
build.job_artifacts << create(:ci_job_artifact, :junit, job: build)
diff --git a/spec/factories/ci/daily_build_group_report_results.rb b/spec/factories/ci/daily_build_group_report_results.rb
index d836ee9567c..55f4f116c97 100644
--- a/spec/factories/ci/daily_build_group_report_results.rb
+++ b/spec/factories/ci/daily_build_group_report_results.rb
@@ -7,6 +7,7 @@ FactoryBot.define do
project
last_pipeline factory: :ci_pipeline
group_name { 'rspec' }
+ group
data do
{ 'coverage' => 77.0 }
end
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index ad98e9d1f24..bfd8506566b 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -269,6 +269,26 @@ FactoryBot.define do
end
end
+ trait :sast do
+ file_type { :sast }
+ file_format { :raw }
+
+ after(:build) do |artifact, _|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/security_reports/master/gl-sast-report.json'), 'application/json')
+ end
+ end
+
+ trait :secret_detection do
+ file_type { :secret_detection }
+ file_format { :raw }
+
+ after(:build) do |artifact, _|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/security_reports/master/gl-secret-detection-report.json'), 'application/json')
+ end
+ end
+
trait :lsif do
file_type { :lsif }
file_format { :zip }
diff --git a/spec/factories/ci/pipeline_artifacts.rb b/spec/factories/ci/pipeline_artifacts.rb
index fa33609dd6c..05ff7afed7c 100644
--- a/spec/factories/ci/pipeline_artifacts.rb
+++ b/spec/factories/ci/pipeline_artifacts.rb
@@ -4,18 +4,30 @@ FactoryBot.define do
factory :ci_pipeline_artifact, class: 'Ci::PipelineArtifact' do
pipeline factory: :ci_pipeline
project { pipeline.project }
- file_type { :code_coverage }
file_format { :raw }
file_store { ObjectStorage::SUPPORTED_STORES.first }
- size { 1.megabytes }
-
+ size { 1.megabyte }
+ file_type { :code_coverage }
after(:build) do |artifact, _evaluator|
artifact.file = fixture_file_upload(
Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json')
end
- trait :with_multibyte_characters do
+ trait :with_coverage_report do
+ file_type { :code_coverage }
+
+ after(:build) do |artifact, _evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json')
+ end
+
+ size { file.size }
+ end
+
+ trait :with_coverage_multibyte_characters do
+ file_type { :code_coverage }
size { { "utf8" => "✓" }.to_json.bytesize }
+
after(:build) do |artifact, _evaluator|
artifact.file = CarrierWaveStringFile.new_file(
file_content: { "utf8" => "✓" }.to_json,
@@ -26,12 +38,25 @@ FactoryBot.define do
end
trait :with_code_coverage_with_multiple_files do
+ file_type { :code_coverage }
+
after(:build) do |artifact, _evaluator|
artifact.file = fixture_file_upload(
Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage_with_multiple_files.json'), 'application/json'
)
end
+ size { 1.megabyte }
+ end
+
+ trait :with_codequality_mr_diff_report do
+ file_type { :code_quality_mr_diff }
+
+ after(:build) do |artifact, _evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/pipeline_artifacts/code_quality_mr_diff.json'), 'application/json')
+ end
+
size { file.size }
end
end
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index 86a8b008e48..e0d7ad3c133 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -101,6 +101,22 @@ FactoryBot.define do
end
end
+ trait :with_sast_report do
+ status { :success }
+
+ after(:build) do |pipeline, evaluator|
+ pipeline.builds << build(:ci_build, :sast_report, pipeline: pipeline, project: pipeline.project)
+ end
+ end
+
+ trait :with_secret_detection_report do
+ status { :success }
+
+ after(:build) do |pipeline, evaluator|
+ pipeline.builds << build(:ci_build, :secret_detection_report, pipeline: pipeline, project: pipeline.project)
+ end
+ end
+
trait :with_test_reports do
status { :success }
@@ -159,7 +175,13 @@ FactoryBot.define do
trait :with_coverage_report_artifact do
after(:build) do |pipeline, evaluator|
- pipeline.pipeline_artifacts << build(:ci_pipeline_artifact, pipeline: pipeline, project: pipeline.project)
+ pipeline.pipeline_artifacts << build(:ci_pipeline_artifact, :with_coverage_report, pipeline: pipeline, project: pipeline.project)
+ end
+ end
+
+ trait :with_codequality_mr_diff_report do
+ after(:build) do |pipeline, evaluator|
+ pipeline.pipeline_artifacts << build(:ci_pipeline_artifact, :with_codequality_mr_diff_report, pipeline: pipeline, project: pipeline.project)
end
end
diff --git a/spec/factories/ci/processable.rb b/spec/factories/ci/processable.rb
new file mode 100644
index 00000000000..0550f4c23fa
--- /dev/null
+++ b/spec/factories/ci/processable.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_processable, class: 'Ci::Processable' do
+ name { 'processable' }
+ stage { 'test' }
+ stage_idx { 0 }
+ ref { 'master' }
+ tag { false }
+ pipeline factory: :ci_pipeline
+ project { pipeline.project }
+ scheduling_type { 'stage' }
+
+ trait :waiting_for_resource do
+ status { 'waiting_for_resource' }
+ end
+
+ trait :resource_group do
+ waiting_for_resource_at { 5.minutes.ago }
+
+ after(:build) do |processable, evaluator|
+ processable.resource_group = create(:ci_resource_group, project: processable.project)
+ end
+ end
+ end
+end
diff --git a/spec/factories/ci/reports/codequality_degradations.rb b/spec/factories/ci/reports/codequality_degradations.rb
new file mode 100644
index 00000000000..d82157b457a
--- /dev/null
+++ b/spec/factories/ci/reports/codequality_degradations.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :codequality_degradation_1, class: Hash do
+ skip_create
+
+ initialize_with do
+ {
+ "categories": [
+ "Complexity"
+ ],
+ "check_name": "argument_count",
+ "content": {
+ "body": ""
+ },
+ "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
+ "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
+ "location": {
+ "path": "file_a.rb",
+ "lines": {
+ "begin": 10,
+ "end": 10
+ }
+ },
+ "other_locations": [],
+ "remediation_points": 900000,
+ "severity": "major",
+ "type": "issue",
+ "engine_name": "structure"
+ }.with_indifferent_access
+ end
+ end
+
+ factory :codequality_degradation_2, class: Hash do
+ skip_create
+
+ initialize_with do
+ {
+ "categories": [
+ "Complexity"
+ ],
+ "check_name": "argument_count",
+ "content": {
+ "body": ""
+ },
+ "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
+ "fingerprint": "f3bdc1e8c102ba5fbd9e7f6cda51c95e",
+ "location": {
+ "path": "file_a.rb",
+ "lines": {
+ "begin": 10,
+ "end": 10
+ }
+ },
+ "other_locations": [],
+ "remediation_points": 900000,
+ "severity": "major",
+ "type": "issue",
+ "engine_name": "structure"
+ }.with_indifferent_access
+ end
+ end
+
+ factory :codequality_degradation_3, class: Hash do
+ skip_create
+
+ initialize_with do
+ {
+ "type": "Issue",
+ "check_name": "Rubocop/Metrics/ParameterLists",
+ "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
+ "categories": [
+ "Complexity"
+ ],
+ "remediation_points": 550000,
+ "location": {
+ "path": "file_b.rb",
+ "positions": {
+ "begin": {
+ "column": 14,
+ "line": 10
+ },
+ "end": {
+ "column": 39,
+ "line": 10
+ }
+ }
+ },
+ "content": {
+ "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
+ },
+ "engine_name": "rubocop",
+ "fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
+ "severity": "minor"
+ }.with_indifferent_access
+ end
+ end
+end
diff --git a/spec/factories/ci/resource.rb b/spec/factories/ci/resource.rb
index 515329506e5..dec26013a25 100644
--- a/spec/factories/ci/resource.rb
+++ b/spec/factories/ci/resource.rb
@@ -5,7 +5,7 @@ FactoryBot.define do
resource_group factory: :ci_resource_group
trait(:retained) do
- build factory: :ci_build
+ processable factory: :ci_build
end
end
end
diff --git a/spec/factories/design_management/design_at_version.rb b/spec/factories/design_management/design_at_version.rb
index 3d85269ee27..6c0848ed11f 100644
--- a/spec/factories/design_management/design_at_version.rb
+++ b/spec/factories/design_management/design_at_version.rb
@@ -17,7 +17,7 @@ FactoryBot.define do
attrs[:design] ||= association(:design, issue: issue)
attrs[:version] ||= association(:design_version, issue: issue)
- new(attrs)
+ new(**attrs)
end
end
end
diff --git a/spec/factories/diff_position.rb b/spec/factories/diff_position.rb
index 0185c4ce156..41f9a7b574e 100644
--- a/spec/factories/diff_position.rb
+++ b/spec/factories/diff_position.rb
@@ -24,7 +24,7 @@ FactoryBot.define do
head_sha { diff_refs&.head_sha }
start_sha { diff_refs&.start_sha }
- initialize_with { new(attributes) }
+ initialize_with { new(**attributes) }
trait :moved do
new_path { 'path/to/new.file' }
diff --git a/spec/factories/merge_request_diffs.rb b/spec/factories/merge_request_diffs.rb
index 481cabdae6d..f93f3f22109 100644
--- a/spec/factories/merge_request_diffs.rb
+++ b/spec/factories/merge_request_diffs.rb
@@ -10,12 +10,18 @@ FactoryBot.define do
head_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
start_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ diff_type { :regular }
+
trait :external do
external_diff { fixture_file_upload("spec/fixtures/doc_sample.txt", "plain/txt") }
stored_externally { true }
importing { true } # this avoids setting the state to 'empty'
end
+ trait :merge_head do
+ diff_type { :merge_head }
+ end
+
factory :external_merge_request_diff, traits: [:external]
end
end
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index e69743122cc..fce44c2cee0 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -21,7 +21,12 @@ FactoryBot.define do
merge_status { "can_be_merged" }
- trait :with_diffs do
+ trait :draft_merge_request do
+ title { generate(:draft_title) }
+ end
+
+ trait :wip_merge_request do
+ title { generate(:wip_title) }
end
trait :jira_title do
@@ -200,6 +205,18 @@ FactoryBot.define do
end
end
+ trait :with_codequality_mr_diff_reports do
+ after(:build) do |merge_request|
+ merge_request.head_pipeline = build(
+ :ci_pipeline,
+ :success,
+ :with_codequality_mr_diff_report,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
+ end
+
trait :with_terraform_reports do
after(:build) do |merge_request|
merge_request.head_pipeline = build(
@@ -212,6 +229,30 @@ FactoryBot.define do
end
end
+ trait :with_sast_reports do
+ after(:build) do |merge_request|
+ merge_request.head_pipeline = build(
+ :ci_pipeline,
+ :success,
+ :with_sast_report,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
+ end
+
+ trait :with_secret_detection_reports do
+ after(:build) do |merge_request|
+ merge_request.head_pipeline = build(
+ :ci_pipeline,
+ :success,
+ :with_secret_detection_report,
+ project: merge_request.source_project,
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha)
+ end
+ end
+
trait :with_exposed_artifacts do
after(:build) do |merge_request|
merge_request.head_pipeline = build(
@@ -294,7 +335,7 @@ FactoryBot.define do
factory :closed_merge_request, traits: [:closed]
factory :reopened_merge_request, traits: [:opened]
factory :invalid_merge_request, traits: [:invalid]
- factory :merge_request_with_diffs, traits: [:with_diffs]
+ factory :merge_request_with_diffs
factory :merge_request_with_diff_notes do
after(:create) do |mr|
create(:diff_note_on_merge_request, noteable: mr, project: mr.source_project)
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 4b1f3194ce5..299d08972b7 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -8,7 +8,7 @@ FactoryBot.define do
factory :note do
project
note { generate(:title) }
- author { project&.creator || create(:user) }
+ author { project&.creator || association(:user) }
on_issue
factory :note_on_commit, traits: [:on_commit]
@@ -55,7 +55,7 @@ FactoryBot.define do
end
position do
- build(:text_diff_position,
+ association(:text_diff_position,
file: "files/ruby/popen.rb",
old_line: nil,
new_line: line_number,
@@ -64,7 +64,7 @@ FactoryBot.define do
trait :folded_position do
position do
- build(:text_diff_position,
+ association(:text_diff_position,
file: "files/ruby/popen.rb",
old_line: 1,
new_line: 1,
@@ -74,7 +74,7 @@ FactoryBot.define do
factory :image_diff_note_on_merge_request do
position do
- build(:image_diff_position,
+ association(:image_diff_position,
file: "files/images/any_image.png",
diff_refs: diff_refs)
end
@@ -90,7 +90,7 @@ FactoryBot.define do
end
position do
- build(:text_diff_position,
+ association(:text_diff_position,
file: "files/ruby/popen.rb",
old_line: nil,
new_line: line_number,
@@ -100,7 +100,11 @@ FactoryBot.define do
end
factory :diff_note_on_design, parent: :note, traits: [:on_design], class: 'DiffNote' do
- position { build(:image_diff_position, file: noteable.full_path, diff_refs: noteable.diff_refs) }
+ position do
+ association(:image_diff_position,
+ file: noteable.full_path,
+ diff_refs: noteable.diff_refs)
+ end
end
trait :on_commit do
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index 31f1aabe5dd..2c64abefb01 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -6,6 +6,15 @@ FactoryBot.define do
name { 'my/company/app/my-app' }
sequence(:version) { |n| "1.#{n}-SNAPSHOT" }
package_type { :maven }
+ status { :default }
+
+ trait :hidden do
+ status { :hidden }
+ end
+
+ trait :processing do
+ status { :processing }
+ end
factory :maven_package do
maven_metadatum
@@ -21,6 +30,23 @@ FactoryBot.define do
end
end
+ factory :rubygems_package do
+ sequence(:name) { |n| "my_gem_#{n}" }
+ sequence(:version) { |n| "1.#{n}" }
+ package_type { :rubygems }
+
+ after :create do |package|
+ create :package_file, :gem, package: package
+ create :package_file, :gemspec, package: package
+ end
+
+ trait(:with_metadatum) do
+ after :build do |pkg|
+ pkg.rubygems_metadatum = build(:rubygems_metadatum)
+ end
+ end
+ end
+
factory :debian_package do
sequence(:name) { |n| "package-#{n}" }
sequence(:version) { |n| "1.0-#{n}" }
@@ -29,6 +55,15 @@ FactoryBot.define do
transient do
without_package_files { false }
file_metadatum_trait { :keep }
+ published_in { :create }
+ end
+
+ after :build do |package, evaluator|
+ if evaluator.published_in == :create
+ create(:debian_publication, package: package)
+ elsif !evaluator.published_in.nil?
+ create(:debian_publication, package: package, distribution: evaluator.published_in)
+ end
end
after :create do |package, evaluator|
@@ -50,6 +85,7 @@ FactoryBot.define do
transient do
without_package_files { false }
file_metadatum_trait { :unknown }
+ published_in { nil }
end
end
end
@@ -176,6 +212,24 @@ FactoryBot.define do
composer_json { { name: 'foo' } }
end
+ factory :composer_cache_file, class: 'Packages::Composer::CacheFile' do
+ group
+
+ file_sha256 { '1' * 64 }
+
+ transient do
+ file_fixture { 'spec/fixtures/packages/composer/package.json' }
+ end
+
+ after(:build) do |cache_file, evaluator|
+ cache_file.file = fixture_file_upload(evaluator.file_fixture)
+ end
+
+ trait(:object_storage) do
+ file_store { Packages::Composer::CacheUploader::Store::REMOTE }
+ end
+ end
+
factory :maven_metadatum, class: 'Packages::Maven::Metadatum' do
association :package, package_type: :maven
path { 'my/company/app/my-app/1.0-SNAPSHOT' }
diff --git a/spec/factories/packages/debian/component_file.rb b/spec/factories/packages/debian/component_file.rb
new file mode 100644
index 00000000000..19157b3c8c6
--- /dev/null
+++ b/spec/factories/packages/debian/component_file.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_project_component_file, class: 'Packages::Debian::ProjectComponentFile' do
+ component { association(:debian_project_component) }
+ architecture { association(:debian_project_architecture, distribution: component.distribution) }
+
+ factory :debian_group_component_file, class: 'Packages::Debian::GroupComponentFile' do
+ component { association(:debian_group_component) }
+ architecture { association(:debian_group_architecture, distribution: component.distribution) }
+ end
+
+ file_type { :packages }
+
+ after(:build) do |component_file, evaluator|
+ component_file.file = fixture_file_upload('spec/fixtures/packages/debian/distribution/Packages')
+ end
+
+ file_md5 { '12345abcde' }
+ file_sha256 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
+
+ trait(:packages) do
+ file_type { :packages }
+ end
+
+ trait(:source) do
+ file_type { :source }
+ architecture { nil }
+ end
+
+ trait(:di_packages) do
+ file_type { :di_packages }
+ end
+
+ trait(:object_storage) do
+ file_store { Packages::PackageFileUploader::Store::REMOTE }
+ end
+ end
+end
diff --git a/spec/factories/packages/debian/distribution.rb b/spec/factories/packages/debian/distribution.rb
index 2015f2923b8..619308e4e18 100644
--- a/spec/factories/packages/debian/distribution.rb
+++ b/spec/factories/packages/debian/distribution.rb
@@ -14,7 +14,7 @@ FactoryBot.define do
trait(:with_file) do
after(:build) do |distribution, evaluator|
- distribution.file = fixture_file_upload('spec/fixtures/packages/debian/README.md')
+ distribution.file = fixture_file_upload('spec/fixtures/packages/debian/distribution/Release')
end
end
diff --git a/spec/factories/packages/debian/group_component.rb b/spec/factories/packages/debian/group_component.rb
new file mode 100644
index 00000000000..92d438be389
--- /dev/null
+++ b/spec/factories/packages/debian/group_component.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_group_component, class: 'Packages::Debian::GroupComponent' do
+ distribution { association(:debian_group_distribution) }
+
+ sequence(:name) { |n| "group-component-#{n}" }
+ end
+end
diff --git a/spec/factories/packages/debian/project_component.rb b/spec/factories/packages/debian/project_component.rb
new file mode 100644
index 00000000000..a56aec4cef0
--- /dev/null
+++ b/spec/factories/packages/debian/project_component.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_project_component, class: 'Packages::Debian::ProjectComponent' do
+ distribution { association(:debian_project_distribution) }
+
+ sequence(:name) { |n| "project-component-#{n}" }
+ end
+end
diff --git a/spec/factories/packages/debian/publication.rb b/spec/factories/packages/debian/publication.rb
new file mode 100644
index 00000000000..314c7064e9b
--- /dev/null
+++ b/spec/factories/packages/debian/publication.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :debian_publication, class: 'Packages::Debian::Publication' do
+ package { association(:debian_package, published_in: nil) }
+
+ distribution { association(:debian_project_distribution, project: package.project) }
+ end
+end
diff --git a/spec/factories/packages/package_file.rb b/spec/factories/packages/package_file.rb
index c328c01ec95..6d8b119040e 100644
--- a/spec/factories/packages/package_file.rb
+++ b/spec/factories/packages/package_file.rb
@@ -221,6 +221,22 @@ FactoryBot.define do
size { 300.kilobytes }
end
+ trait(:gem) do
+ package
+ file_fixture { 'spec/fixtures/packages/rubygems/package-0.0.1.gem' }
+ file_name { 'package-0.0.1.gem' }
+ file_sha1 { '5fe852b2a6abd96c22c11fa1ff2fb19d9ce58b57' }
+ size { 4.kilobytes }
+ end
+
+ trait(:gemspec) do
+ package
+ file_fixture { 'spec/fixtures/packages/rubygems/package.gemspec' }
+ file_name { 'package.gemspec' }
+ file_sha1 { '5fe852b2a6abd96c22c11fa1ff2fb19d9ce58b57' }
+ size { 242.bytes }
+ end
+
trait(:pypi) do
package
file_fixture { 'spec/fixtures/packages/pypi/sample-project.tar.gz' }
diff --git a/spec/factories/packages/rubygems/metadata.rb b/spec/factories/packages/rubygems/metadata.rb
new file mode 100644
index 00000000000..9f03bf80dc3
--- /dev/null
+++ b/spec/factories/packages/rubygems/metadata.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :rubygems_metadatum, class: 'Packages::Rubygems::Metadatum' do
+ package { association(:rubygems_package) }
+ authors { FFaker::Name.name }
+ email { FFaker::Internet.email }
+ end
+end
diff --git a/spec/factories/pages_deployments.rb b/spec/factories/pages_deployments.rb
index 56aab4fa9f3..d3e2fefb4ae 100644
--- a/spec/factories/pages_deployments.rb
+++ b/spec/factories/pages_deployments.rb
@@ -4,12 +4,20 @@ FactoryBot.define do
factory :pages_deployment, class: 'PagesDeployment' do
project
- after(:build) do |deployment, _evaluator|
- filepath = Rails.root.join("spec/fixtures/pages.zip")
+ transient do
+ filename { nil }
+ end
+
+ trait(:migrated) do
+ filename { PagesDeployment::MIGRATED_FILE_NAME }
+ end
+
+ after(:build) do |deployment, evaluator|
+ file = UploadedFile.new("spec/fixtures/pages.zip", filename: evaluator.filename)
- deployment.file = fixture_file_upload(filepath)
- deployment.file_sha256 = Digest::SHA256.file(filepath).hexdigest
- ::Zip::File.open(filepath) do |zip_archive|
+ deployment.file = file
+ deployment.file_sha256 = Digest::SHA256.file(file.path).hexdigest
+ ::Zip::File.open(file.path) do |zip_archive|
deployment.file_count = zip_archive.count
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 54a5dea49bb..e8e0362fc62 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -40,7 +40,7 @@ FactoryBot.define do
group_runners_enabled { nil }
merge_pipelines_enabled { nil }
merge_trains_enabled { nil }
- ci_keep_latest_artifact { nil }
+ keep_latest_artifact { nil }
import_status { nil }
import_jid { nil }
import_correlation_id { nil }
@@ -86,7 +86,7 @@ FactoryBot.define do
project.group_runners_enabled = evaluator.group_runners_enabled unless evaluator.group_runners_enabled.nil?
project.merge_pipelines_enabled = evaluator.merge_pipelines_enabled unless evaluator.merge_pipelines_enabled.nil?
project.merge_trains_enabled = evaluator.merge_trains_enabled unless evaluator.merge_trains_enabled.nil?
- project.ci_keep_latest_artifact = evaluator.ci_keep_latest_artifact unless evaluator.ci_keep_latest_artifact.nil?
+ project.keep_latest_artifact = evaluator.keep_latest_artifact unless evaluator.keep_latest_artifact.nil?
project.restrict_user_defined_variables = evaluator.restrict_user_defined_variables unless evaluator.restrict_user_defined_variables.nil?
if evaluator.import_status
diff --git a/spec/factories/sequences.rb b/spec/factories/sequences.rb
index b338fd99625..f9952cd9966 100644
--- a/spec/factories/sequences.rb
+++ b/spec/factories/sequences.rb
@@ -15,6 +15,8 @@ FactoryBot.define do
sequence(:sha) { |n| Digest::SHA1.hexdigest("commit-like-#{n}") }
sequence(:oid) { |n| Digest::SHA2.hexdigest("oid-like-#{n}") }
sequence(:variable) { |n| "var#{n}" }
+ sequence(:draft_title) { |n| "Draft: #{n}" }
+ sequence(:wip_title) { |n| "WIP: #{n}" }
sequence(:jira_title) { |n| "[PROJ-#{n}]: fix bug" }
sequence(:jira_branch) { |n| "feature/PROJ-#{n}" }
end
diff --git a/spec/factories/services_data.rb b/spec/factories/services_data.rb
index c62fff2af55..7b6a705c791 100644
--- a/spec/factories/services_data.rb
+++ b/spec/factories/services_data.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-# these factories should never be called directly, they are used when creating services
+# These factories should not be called directly unless we are testing a _tracker_data model.
+# The factories are used when creating integrations.
FactoryBot.define do
factory :jira_tracker_data do
service
diff --git a/spec/factories/token_with_ivs.rb b/spec/factories/token_with_ivs.rb
new file mode 100644
index 00000000000..68989f6c5bc
--- /dev/null
+++ b/spec/factories/token_with_ivs.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :token_with_iv do
+ hashed_token { ::Digest::SHA256.digest(SecureRandom.hex(50)) }
+ iv { ::Digest::SHA256.digest(SecureRandom.hex(50)) }
+ hashed_plaintext_token { ::Digest::SHA256.digest(SecureRandom.hex(50)) }
+ end
+end
diff --git a/spec/factories/u2f_registrations.rb b/spec/factories/u2f_registrations.rb
index 7017b0ee9e7..40ad221415c 100644
--- a/spec/factories/u2f_registrations.rb
+++ b/spec/factories/u2f_registrations.rb
@@ -2,6 +2,8 @@
FactoryBot.define do
factory :u2f_registration do
+ user
+
certificate { FFaker::BaconIpsum.characters(728) }
key_handle { FFaker::BaconIpsum.characters(86) }
public_key { FFaker::BaconIpsum.characters(88) }
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index 0ed4176109a..714f8451f39 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -121,8 +121,8 @@ FactoryBot.define do
env = create(:environment, project: projects[3])
[3, 31].each do |n|
deployment_options = { created_at: n.days.ago, project: env.project, environment: env }
- create(:deployment, :failed, deployment_options)
- create(:deployment, :success, deployment_options)
+ create(:deployment, :failed, **deployment_options)
+ create(:deployment, :success, **deployment_options)
create_list(:project_snippet, 2, project: projects[0], created_at: n.days.ago)
create(:personal_snippet, created_at: n.days.ago)
end
diff --git a/spec/features/admin/admin_cohorts_spec.rb b/spec/features/admin/admin_cohorts_spec.rb
deleted file mode 100644
index 982a9333275..00000000000
--- a/spec/features/admin/admin_cohorts_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Cohorts page' do
- before do
- admin = create(:admin)
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- end
-
- context 'with usage ping enabled' do
- it 'shows users count per month' do
- stub_application_setting(usage_ping_enabled: true)
-
- create_list(:user, 2)
-
- visit admin_cohorts_path
-
- expect(page).to have_content("#{Time.now.strftime('%b %Y')} 3 0")
- end
- end
-
- context 'with usage ping disabled' do
- it 'shows empty state', :js do
- stub_application_setting(usage_ping_enabled: false)
-
- visit admin_cohorts_path
-
- expect(page).to have_selector(".js-empty-state")
- end
- end
-end
diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
index f7f0592a315..b370b779afe 100644
--- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb
+++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
@@ -37,7 +37,10 @@ RSpec.describe 'Admin disables Git access protocol', :js do
it 'shows only the SSH clone information' do
resize_screen_xs
visit_project
- find('.dropdown-toggle').click
+
+ within('.js-mobile-git-clone') do
+ find('.dropdown-toggle').click
+ end
expect(page).to have_content('Copy SSH clone URL')
expect(page).not_to have_content('Copy HTTP clone URL')
@@ -66,7 +69,10 @@ RSpec.describe 'Admin disables Git access protocol', :js do
it 'shows only the HTTP clone information' do
resize_screen_xs
visit_project
- find('.dropdown-toggle').click
+
+ within('.js-mobile-git-clone') do
+ find('.dropdown-toggle').click
+ end
expect(page).to have_content('Copy HTTP clone URL')
expect(page).not_to have_content('Copy SSH clone URL')
@@ -97,7 +103,10 @@ RSpec.describe 'Admin disables Git access protocol', :js do
it 'shows both SSH and HTTP clone information' do
resize_screen_xs
visit_project
- find('.dropdown-toggle').click
+
+ within('.js-mobile-git-clone') do
+ find('.dropdown-toggle').click
+ end
expect(page).to have_content('Copy HTTP clone URL')
expect(page).to have_content('Copy SSH clone URL')
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index a8e18385bd2..bbdf2f7f4a9 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe 'Admin Groups' do
click_button "Create group"
expect(current_path).to eq admin_group_path(Group.find_by(path: path_component))
- content = page.find('div#content-body')
+ content = page.find('#content-body')
h3_texts = content.all('h3').collect(&:text).join("\n")
expect(h3_texts).to match group_name
li_texts = content.all('li').collect(&:text).join("\n")
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index ff4e592234b..aab2e6d7cef 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe "Admin::Projects" do
+ include Spec::Support::Helpers::Features::MembersHelpers
include Select2Helper
let(:user) { create :user }
@@ -91,45 +92,97 @@ RSpec.describe "Admin::Projects" do
end
end
- describe 'add admin himself to a project' do
- before do
- project.add_maintainer(user)
- end
+ context 'when `vue_project_members_list` feature flag is enabled', :js do
+ describe 'admin adds themselves to the project' do
+ before do
+ project.add_maintainer(user)
+ stub_feature_flags(invite_members_group_modal: false)
+ end
- it 'adds admin a to a project as developer', :js do
- visit project_project_members_path(project)
+ it 'adds admin to the project as developer', :js do
+ visit project_project_members_path(project)
- page.within '.invite-users-form' do
- select2(current_user.id, from: '#user_ids', multiple: true)
- select 'Developer', from: 'access_level'
+ page.within '.invite-users-form' do
+ select2(current_user.id, from: '#user_ids', multiple: true)
+ select 'Developer', from: 'access_level'
+ end
+
+ click_button 'Invite'
+
+ expect(find_member_row(current_user)).to have_content('Developer')
end
+ end
+
+ describe 'admin removes themselves from the project' do
+ before do
+ project.add_maintainer(user)
+ project.add_developer(current_user)
+ end
+
+ it 'removes admin from the project' do
+ visit project_project_members_path(project)
+
+ expect(find_member_row(current_user)).to have_content('Developer')
+
+ page.within find_member_row(current_user) do
+ click_button 'Leave'
+ end
- click_button 'Invite'
+ page.within('[role="dialog"]') do
+ click_button('Leave')
+ end
- page.within '.content-list' do
- expect(page).to have_content(current_user.name)
- expect(page).to have_content('Developer')
+ expect(current_path).to match dashboard_projects_path
end
end
end
- describe 'admin remove himself from a project' do
+ context 'when `vue_project_members_list` feature flag is disabled' do
before do
- project.add_maintainer(user)
- project.add_developer(current_user)
+ stub_feature_flags(vue_project_members_list: false)
end
- it 'removes admin from the project' do
- visit project_project_members_path(project)
+ describe 'admin adds themselves to the project' do
+ before do
+ project.add_maintainer(user)
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it 'adds admin to the project as developer', :js do
+ visit project_project_members_path(project)
+
+ page.within '.invite-users-form' do
+ select2(current_user.id, from: '#user_ids', multiple: true)
+ select 'Developer', from: 'access_level'
+ end
+
+ click_button 'Invite'
+
+ page.within '.content-list' do
+ expect(page).to have_content(current_user.name)
+ expect(page).to have_content('Developer')
+ end
+ end
+ end
- page.within '.content-list' do
- expect(page).to have_content(current_user.name)
- expect(page).to have_content('Developer')
+ describe 'admin removes themselves from the project' do
+ before do
+ project.add_maintainer(user)
+ project.add_developer(current_user)
end
- find(:css, '.content-list li', text: current_user.name).find(:css, 'a.btn-danger').click
+ it 'removes admin from the project' do
+ visit project_project_members_path(project)
+
+ page.within '.content-list' do
+ expect(page).to have_content(current_user.name)
+ expect(page).to have_content('Developer')
+ end
- expect(page).not_to have_selector(:css, '.content-list')
+ find(:css, '.content-list li', text: current_user.name).find(:css, 'a.btn-danger').click
+
+ expect(page).not_to have_selector(:css, '.content-list')
+ end
end
end
end
diff --git a/spec/features/admin/admin_search_settings_spec.rb b/spec/features/admin/admin_search_settings_spec.rb
new file mode 100644
index 00000000000..a78d17a6651
--- /dev/null
+++ b/spec/features/admin/admin_search_settings_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin searches application settings', :js do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:application_settings) { create(:application_setting) }
+
+ before do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ end
+
+ context 'in appearances page' do
+ before do
+ visit(admin_appearances_path)
+ end
+
+ it_behaves_like 'cannot search settings'
+ end
+
+ context 'in ci/cd settings page' do
+ let(:visit_path) { ci_cd_admin_application_settings_path }
+
+ it_behaves_like 'can search settings with feature flag check', 'Variables', 'Package Registry'
+ end
+end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 0c66775c323..52f39f65bd0 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -306,59 +306,70 @@ RSpec.describe 'Admin updates settings' do
page.within('.as-ci-cd') do
check 'Default to Auto DevOps pipeline for all projects'
fill_in 'application_setting_auto_devops_domain', with: 'domain.com'
+ uncheck 'Keep the latest artifacts for all jobs in the latest successful pipelines'
click_button 'Save changes'
end
expect(current_settings.auto_devops_enabled?).to be true
expect(current_settings.auto_devops_domain).to eq('domain.com')
+ expect(current_settings.keep_latest_artifact).to be false
expect(page).to have_content "Application settings saved successfully"
end
context 'Container Registry' do
- context 'delete tags service execution timeout' do
- let(:feature_flag_enabled) { true }
- let(:client_support) { true }
-
- before do
- stub_container_registry_config(enabled: true)
- stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
- allow(ContainerRegistry::Client).to receive(:supports_tag_delete?).and_return(client_support)
- end
+ let(:feature_flag_enabled) { true }
+ let(:client_support) { true }
+ let(:settings_titles) do
+ {
+ container_registry_delete_tags_service_timeout: 'Container Registry delete tags service execution timeout',
+ container_registry_expiration_policies_worker_capacity: 'Cleanup policy maximum workers running concurrently',
+ container_registry_cleanup_tags_service_max_list_size: 'Cleanup policy maximum number of tags to be deleted'
+ }
+ end
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
+ allow(ContainerRegistry::Client).to receive(:supports_tag_delete?).and_return(client_support)
+ end
- RSpec.shared_examples 'not having service timeout settings' do
- it 'lacks the timeout settings' do
- visit ci_cd_admin_application_settings_path
+ shared_examples 'not having container registry setting' do |registry_setting|
+ it "lacks the container setting #{registry_setting}" do
+ visit ci_cd_admin_application_settings_path
- expect(page).not_to have_content "Container Registry delete tags service execution timeout"
- end
+ expect(page).not_to have_content(settings_titles[registry_setting])
end
+ end
- context 'with feature flag enabled' do
- context 'with client supporting tag delete' do
- it 'changes the timeout' do
- visit ci_cd_admin_application_settings_path
+ %i[container_registry_delete_tags_service_timeout container_registry_expiration_policies_worker_capacity container_registry_cleanup_tags_service_max_list_size].each do |setting|
+ context "for container registry setting #{setting}" do
+ context 'with feature flag enabled' do
+ context 'with client supporting tag delete' do
+ it 'changes the setting' do
+ visit ci_cd_admin_application_settings_path
- page.within('.as-registry') do
- fill_in 'application_setting_container_registry_delete_tags_service_timeout', with: 400
- click_button 'Save changes'
- end
+ page.within('.as-registry') do
+ fill_in "application_setting_#{setting}", with: 400
+ click_button 'Save changes'
+ end
- expect(current_settings.container_registry_delete_tags_service_timeout).to eq(400)
- expect(page).to have_content "Application settings saved successfully"
+ expect(current_settings.public_send(setting)).to eq(400)
+ expect(page).to have_content "Application settings saved successfully"
+ end
end
- end
- context 'with client not supporting tag delete' do
- let(:client_support) { false }
+ context 'with client not supporting tag delete' do
+ let(:client_support) { false }
- it_behaves_like 'not having service timeout settings'
+ it_behaves_like 'not having container registry setting', setting
+ end
end
- end
- context 'with feature flag disabled' do
- let(:feature_flag_enabled) { false }
+ context 'with feature flag disabled' do
+ let(:feature_flag_enabled) { false }
- it_behaves_like 'not having service timeout settings'
+ it_behaves_like 'not having container registry setting', setting
+ end
end
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
new file mode 100644
index 00000000000..4fc60d17886
--- /dev/null
+++ b/spec/features/admin/admin_users_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Admin::Users" do
+ let(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ gitlab_enable_admin_mode_sign_in(current_user)
+ end
+
+ describe 'Tabs', :js do
+ let(:tabs_selector) { '.js-users-tabs' }
+ let(:active_tab_selector) { '.nav-link.active' }
+
+ it 'does not add the tab param when the Users tab is selected' do
+ visit admin_users_path
+
+ within tabs_selector do
+ click_link 'Users'
+ end
+
+ expect(page).to have_current_path(admin_users_path)
+ end
+
+ it 'adds the ?tab=cohorts param when the Cohorts tab is selected' do
+ visit admin_users_path
+
+ within tabs_selector do
+ click_link 'Cohorts'
+ end
+
+ expect(page).to have_current_path(admin_users_path(tab: 'cohorts'))
+ end
+
+ it 'shows the cohorts tab when the tab param is set' do
+ visit admin_users_path(tab: 'cohorts')
+
+ within tabs_selector do
+ expect(page).to have_selector active_tab_selector, text: 'Cohorts'
+ end
+ end
+ end
+
+ describe 'Cohorts tab content' do
+ context 'with usage ping enabled' do
+ it 'shows users count per month' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ create_list(:user, 2)
+
+ visit admin_users_path(tab: 'cohorts')
+
+ expect(page).to have_content("#{Time.now.strftime('%b %Y')} 3 0")
+ end
+ end
+
+ context 'with usage ping disabled' do
+ it 'shows empty state', :js do
+ stub_application_setting(usage_ping_enabled: false)
+
+ visit admin_users_path(tab: 'cohorts')
+
+ expect(page).to have_selector(".js-empty-state")
+ expect(page).to have_content("Activate user activity analysis")
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb
index e7dd50ed514..befa7bd338b 100644
--- a/spec/features/admin/users/user_spec.rb
+++ b/spec/features/admin/users/user_spec.rb
@@ -171,7 +171,7 @@ RSpec.describe 'Admin::Users::User' do
it 'logs in as the user when impersonate is clicked' do
subject
- expect(page.find(:css, '.header-user .profile-link')['data-user']).to eql(another_user.username)
+ expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eql(another_user.username)
end
it 'sees impersonation log out icon' do
@@ -205,7 +205,7 @@ RSpec.describe 'Admin::Users::User' do
it 'logs out of impersonated user back to original user' do
subject
- expect(page.find(:css, '.header-user .profile-link')['data-user']).to eq(current_user.username)
+ expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eq(current_user.username)
end
it 'is redirected back to the impersonated users page in the admin after stopping' do
diff --git a/spec/features/alert_management/alert_details_spec.rb b/spec/features/alert_management/alert_details_spec.rb
index d190e4b6939..ce82b5adf8d 100644
--- a/spec/features/alert_management/alert_details_spec.rb
+++ b/spec/features/alert_management/alert_details_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe 'Alert details', :js do
expect(page).to have_selector('[data-testid="alert-todo-button"]')
todo_button = find('[data-testid="alert-todo-button"]')
- expect(todo_button).to have_content('Add a To-Do')
+ expect(todo_button).to have_content('Add a to do')
find('[data-testid="alert-todo-button"]').click
wait_for_requests
diff --git a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
index 698a36d3f76..07c87f98eb6 100644
--- a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
+++ b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb
@@ -19,13 +19,14 @@ RSpec.describe 'Alert integrations settings form', :js do
describe 'when viewing alert integrations as a maintainer' do
context 'with the default page permissions' do
before do
+ stub_feature_flags(multiple_http_integrations_custom_mapping: false)
visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
wait_for_requests
end
it 'shows the alerts setting form title' do
page.within('#js-alert-management-settings') do
- expect(find('h3')).to have_content('Alerts')
+ expect(find('h4')).to have_content('Alerts')
end
end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index b3cc2eb418d..2d6b669f28b 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -13,12 +13,14 @@ RSpec.describe 'Issue Boards', :js do
let_it_be(:user2) { create(:user) }
before do
+ stub_feature_flags(board_new_list: false)
+
project.add_maintainer(user)
project.add_maintainer(user2)
- set_cookie('sidebar_collapsed', 'true')
-
sign_in(user)
+
+ set_cookie('sidebar_collapsed', 'true')
end
context 'no lists' do
@@ -573,7 +575,7 @@ RSpec.describe 'Issue Boards', :js do
end
it 'shows the button' do
- expect(page).to have_link('Toggle focus mode')
+ expect(page).to have_button('Toggle focus mode')
end
end
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index 2af5b787a78..08bc70d7116 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -107,17 +107,20 @@ RSpec.describe 'Issue Boards', :js do
click_card(card)
page.within('.assignee') do
- click_link 'Edit'
+ click_button('Edit')
wait_for_requests
- page.within('.dropdown-menu-user') do
- click_link user.name
+ assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
- wait_for_requests
+ page.within('.dropdown-menu-user') do
+ first('.gl-avatar-labeled').click
end
- expect(page).to have_content(user.name)
+ click_button('Edit')
+ wait_for_requests
+
+ expect(page).to have_content(assignee)
end
expect(card).to have_selector('.avatar')
@@ -128,15 +131,15 @@ RSpec.describe 'Issue Boards', :js do
click_card(card_two)
page.within('.assignee') do
- click_link 'Edit'
+ click_button('Edit')
wait_for_requests
page.within('.dropdown-menu-user') do
- click_link 'Unassigned'
+ find('[data-testid="unassign"]').click
end
- close_dropdown_menu_if_visible
+ click_button('Edit')
wait_for_requests
expect(page).to have_content('None')
@@ -165,17 +168,20 @@ RSpec.describe 'Issue Boards', :js do
click_card(card)
page.within('.assignee') do
- click_link 'Edit'
+ click_button('Edit')
wait_for_requests
- page.within('.dropdown-menu-user') do
- click_link user.name
+ assignee = first('.gl-avatar-labeled').find('.gl-avatar-labeled-label').text
- wait_for_requests
+ page.within('.dropdown-menu-user') do
+ first('.gl-avatar-labeled').click
end
- expect(page).to have_content(user.name)
+ click_button('Edit')
+ wait_for_requests
+
+ expect(page).to have_content(assignee)
end
page.within(find('.board:nth-child(2)')) do
@@ -183,9 +189,9 @@ RSpec.describe 'Issue Boards', :js do
end
page.within('.assignee') do
- click_link 'Edit'
+ click_button('Edit')
- expect(find('.dropdown-menu')).to have_selector('.is-active')
+ expect(find('.dropdown-menu')).to have_selector('.gl-new-dropdown-item-check-icon')
end
end
end
@@ -411,10 +417,10 @@ RSpec.describe 'Issue Boards', :js do
wait_for_requests
page.within('.subscriptions') do
- find('.js-issuable-subscribe-button button:not(.is-checked)').click
+ find('[data-testid="subscription-toggle"] button:not(.is-checked)').click
wait_for_requests
- expect(page).to have_css('.js-issuable-subscribe-button button.is-checked')
+ expect(page).to have_css('[data-testid="subscription-toggle"] button.is-checked')
end
end
@@ -427,10 +433,10 @@ RSpec.describe 'Issue Boards', :js do
wait_for_requests
page.within('.subscriptions') do
- find('.js-issuable-subscribe-button button.is-checked').click
+ find('[data-testid="subscription-toggle"] button.is-checked').click
wait_for_requests
- expect(page).to have_css('.js-issuable-subscribe-button button:not(.is-checked)')
+ expect(page).to have_css('[data-testid="subscription-toggle"] button:not(.is-checked)')
end
end
end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index 60d485d4558..ee156bdcab4 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -113,8 +113,8 @@ RSpec.describe 'Contributions Calendar', :js do
describe 'deselect calendar day' do
before do
cells[0].click
- page.find('.js-overview-tab a').click
wait_for_requests
+ cells[0].click
end
it 'hides calendar day activities' do
diff --git a/spec/features/commit_spec.rb b/spec/features/commit_spec.rb
new file mode 100644
index 00000000000..02754cc803e
--- /dev/null
+++ b/spec/features/commit_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Commit' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ describe "single commit view" do
+ let(:commit) do
+ project.repository.commits(nil, limit: 100).find do |commit|
+ commit.diffs.size > 1
+ end
+ end
+
+ let(:files) { commit.diffs.diff_files.to_a }
+
+ before do
+ stub_feature_flags(async_commit_diff_files: false)
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ describe "commit details" do
+ before do
+ visit project_commit_path(project, commit)
+ end
+
+ it "shows the short commit message" do
+ expect(page).to have_content(commit.title)
+ end
+
+ it "reports the correct number of total changes" do
+ expect(page).to have_content("Changes #{commit.diffs.size}")
+ end
+ end
+
+ context "pagination enabled" do
+ before do
+ stub_feature_flags(paginate_commit_view: true)
+ stub_const("Projects::CommitController::COMMIT_DIFFS_PER_PAGE", 1)
+
+ visit project_commit_path(project, commit)
+ end
+
+ it "shows an adjusted count for changed files on this page" do
+ expect(page).to have_content("Showing 1 changed file")
+ end
+
+ it "shows only the first diff on the first page" do
+ expect(page).to have_selector(".files ##{files[0].file_hash}")
+ expect(page).not_to have_selector(".files ##{files[1].file_hash}")
+ end
+
+ it "can navigate to the second page" do
+ within(".files .gl-pagination") do
+ click_on("2")
+ end
+
+ expect(page).not_to have_selector(".files ##{files[0].file_hash}")
+ expect(page).to have_selector(".files ##{files[1].file_hash}")
+ end
+ end
+
+ context "pagination disabled" do
+ before do
+ stub_feature_flags(paginate_commit_view: false)
+
+ visit project_commit_path(project, commit)
+ end
+
+ it "shows both diffs on the page" do
+ expect(page).to have_selector(".files ##{files[0].file_hash}")
+ expect(page).to have_selector(".files ##{files[1].file_hash}")
+ end
+ end
+ end
+end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index f8e84043c1b..1622979812d 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -138,9 +138,8 @@ RSpec.describe 'Commits' do
end
end
- context 'when accessing internal project with disallowed access', :js do
+ context 'when accessing internal project with disallowed access', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/299575' do
before do
- stub_feature_flags(graphql_pipeline_header: false)
project.update(
visibility_level: Gitlab::VisibilityLevel::INTERNAL,
public_builds: false)
diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb
index b419a063858..e75e661b513 100644
--- a/spec/features/dashboard/activity_spec.rb
+++ b/spec/features/dashboard/activity_spec.rb
@@ -9,6 +9,26 @@ RSpec.describe 'Dashboard > Activity' do
sign_in(user)
end
+ context 'tabs' do
+ it 'shows Your Projects' do
+ visit activity_dashboard_path
+
+ expect(find('.top-area .nav-tabs li.active')).to have_content('Your projects')
+ end
+
+ it 'shows Starred Projects' do
+ visit activity_dashboard_path(filter: 'starred')
+
+ expect(find('.top-area .nav-tabs li.active')).to have_content('Starred projects')
+ end
+
+ it 'shows Followed Projects' do
+ visit activity_dashboard_path(filter: 'followed')
+
+ expect(find('.top-area .nav-tabs li.active')).to have_content('Followed users')
+ end
+ end
+
context 'rss' do
before do
visit activity_dashboard_path
diff --git a/spec/features/discussion_comments/issue_spec.rb b/spec/features/discussion_comments/issue_spec.rb
index 2ad77a2884c..86743e31fbd 100644
--- a/spec/features/discussion_comments/issue_spec.rb
+++ b/spec/features/discussion_comments/issue_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Thread Comments Issue', :js do
let(:issue) { create(:issue, project: project) }
before do
+ stub_feature_flags(remove_comment_close_reopen: false)
+
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/discussion_comments/merge_request_spec.rb b/spec/features/discussion_comments/merge_request_spec.rb
index 761cc7ae796..82dcdf9f918 100644
--- a/spec/features/discussion_comments/merge_request_spec.rb
+++ b/spec/features/discussion_comments/merge_request_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'Thread Comments Merge Request', :js do
before do
stub_feature_flags(remove_resolve_note: false)
+ stub_feature_flags(remove_comment_close_reopen: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/discussion_comments/snippets_spec.rb b/spec/features/discussion_comments/snippets_spec.rb
index b2d3fbf4b5d..42053e571e9 100644
--- a/spec/features/discussion_comments/snippets_spec.rb
+++ b/spec/features/discussion_comments/snippets_spec.rb
@@ -4,15 +4,34 @@ require 'spec_helper'
RSpec.describe 'Thread Comments Snippet', :js do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be(:snippet) { create(:project_snippet, :private, :repository, project: project, author: user) }
before do
- project.add_maintainer(user)
sign_in(user)
+ end
+
+ context 'with project snippets' do
+ let_it_be(:project) do
+ create(:project).tap do |p|
+ p.add_maintainer(user)
+ end
+ end
+
+ let_it_be(:snippet) { create(:project_snippet, :private, :repository, project: project, author: user) }
+
+ before do
+ visit project_snippet_path(project, snippet)
+ end
- visit project_snippet_path(project, snippet)
+ it_behaves_like 'thread comments', 'snippet'
end
- it_behaves_like 'thread comments', 'snippet'
+ context 'with personal snippets' do
+ let_it_be(:snippet) { create(:personal_snippet, :private, :repository, author: user) }
+
+ before do
+ visit snippet_path(snippet)
+ end
+
+ it_behaves_like 'thread comments', 'snippet'
+ end
end
diff --git a/spec/features/groups/import_export/connect_instance_spec.rb b/spec/features/groups/import_export/connect_instance_spec.rb
index 2e1bf27ba8b..73de49101ea 100644
--- a/spec/features/groups/import_export/connect_instance_spec.rb
+++ b/spec/features/groups/import_export/connect_instance_spec.rb
@@ -23,8 +23,8 @@ RSpec.describe 'Import/Export - Connect to another instance', :js do
source_url = 'https://gitlab.com'
pat = 'demo-pat'
stub_path = 'stub-group'
-
- stub_request(:get, "%{url}/api/v4/groups?page=1&per_page=30&top_level_only=true&min_access_level=40" % { url: source_url }).to_return(
+ total = 37
+ stub_request(:get, "%{url}/api/v4/groups?page=1&per_page=20&top_level_only=true&min_access_level=40&search=" % { url: source_url }).to_return(
body: [{
id: 2595438,
web_url: 'https://gitlab.com/groups/auto-breakfast',
@@ -33,17 +33,25 @@ RSpec.describe 'Import/Export - Connect to another instance', :js do
full_name: 'Stub',
full_path: stub_path
}].to_json,
- headers: { 'Content-Type' => 'application/json' }
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'X-Next-Page' => 2,
+ 'X-Page' => 1,
+ 'X-Per-Page' => 20,
+ 'X-Total' => total,
+ 'X-Total-Pages' => 2
+ }
)
expect(page).to have_content 'Import groups from another instance of GitLab'
+ expect(page).to have_content 'Not all related objects are migrated'
fill_in :bulk_import_gitlab_url, with: source_url
fill_in :bulk_import_gitlab_access_token, with: pat
click_on 'Connect instance'
- expect(page).to have_content 'Importing groups from %{url}' % { url: source_url }
+ expect(page).to have_content 'Showing 1-1 of %{total} groups from %{url}' % { url: source_url, total: total }
expect(page).to have_content stub_path
end
end
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index a4c450c9a2c..7025874a4ff 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -87,12 +87,4 @@ RSpec.describe 'Group navbar' do
it_behaves_like 'verified navigation bar'
end
-
- context 'when invite team members is not available' do
- it 'does not display the js-invite-members-trigger' do
- visit group_path(group)
-
- expect(page).not_to have_selector('.js-invite-members-trigger')
- end
- end
end
diff --git a/spec/features/groups/settings/packages_and_registries_spec.rb b/spec/features/groups/settings/packages_and_registries_spec.rb
index b8ffd73335d..45ea77e3868 100644
--- a/spec/features/groups/settings/packages_and_registries_spec.rb
+++ b/spec/features/groups/settings/packages_and_registries_spec.rb
@@ -7,15 +7,17 @@ RSpec.describe 'Group Packages & Registries settings' do
let(:user) { create(:user) }
let(:group) { create(:group) }
+ let(:sub_group) { create(:group, parent: group) }
before do
group.add_owner(user)
+ sub_group.add_owner(user)
sign_in(user)
end
- context 'when the feature flag is off' do
+ context 'when packges feature is disabled on the group' do
before do
- stub_feature_flags(packages_and_registries_group_settings: false)
+ stub_packages_setting(enabled: false)
end
it 'the menu item is not visible' do
@@ -25,9 +27,15 @@ RSpec.describe 'Group Packages & Registries settings' do
expect(settings_menu).not_to have_content 'Packages & Registries'
end
+
+ it 'renders 404 when navigating to page' do
+ visit_settings_page
+
+ expect(page).to have_content('Not Found')
+ end
end
- context 'when the feature flag is on' do
+ context 'when packages feature is enabled on the group' do
it 'the menu item is visible' do
visit group_path(group)
@@ -47,6 +55,56 @@ RSpec.describe 'Group Packages & Registries settings' do
sidebar = find('.nav-sidebar')
expect(sidebar).to have_link _('Packages & Registries')
end
+
+ it 'has a Package Registry section', :js do
+ visit_settings_page
+
+ expect(page).to have_content('Package Registry')
+ expect(page).to have_button('Collapse')
+ end
+
+ it 'automatically saves changes to the server', :js do
+ visit_settings_page
+
+ expect(page).to have_content('Allow duplicates')
+
+ find('.gl-toggle').click
+
+ expect(page).to have_content('Do not allow duplicates')
+
+ visit_settings_page
+
+ expect(page).to have_content('Do not allow duplicates')
+ end
+
+ it 'shows an error on wrong regex', :js do
+ visit_settings_page
+
+ expect(page).to have_content('Allow duplicates')
+
+ find('.gl-toggle').click
+
+ expect(page).to have_content('Do not allow duplicates')
+
+ fill_in 'Exceptions', with: ')'
+
+ # simulate blur event
+ find('body').click
+
+ expect(page).to have_content('is an invalid regexp')
+ end
+
+ context 'in a sub group' do
+ it 'works correctly', :js do
+ visit_sub_group_settings_page
+
+ expect(page).to have_content('Allow duplicates')
+
+ find('.gl-toggle').click
+
+ expect(page).to have_content('Do not allow duplicates')
+ end
+ end
end
def find_settings_menu
@@ -56,4 +114,8 @@ RSpec.describe 'Group Packages & Registries settings' do
def visit_settings_page
visit group_settings_packages_and_registries_path(group)
end
+
+ def visit_sub_group_settings_page
+ visit group_settings_packages_and_registries_path(sub_group)
+ end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 3a42fd508b4..5067f11be67 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -163,6 +163,7 @@ RSpec.describe 'Group show page' do
let!(:project) { create(:project, namespace: group) }
before do
+ stub_feature_flags(vue_notification_dropdown: false)
group.add_maintainer(maintainer)
sign_in(maintainer)
end
diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb
index 1f8397e45f7..90647305281 100644
--- a/spec/features/help_pages_spec.rb
+++ b/spec/features/help_pages_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'Help Pages' do
it 'opens shortcuts help dialog' do
find('.js-trigger-shortcut').click
- expect(page).to have_selector('#modal-shortcuts')
+ expect(page).to have_selector('[data-testid="modal-shortcuts"]')
end
end
end
diff --git a/spec/features/ide/user_opens_merge_request_spec.rb b/spec/features/ide/user_opens_merge_request_spec.rb
index e6101e90a83..7ae43f35901 100644
--- a/spec/features/ide/user_opens_merge_request_spec.rb
+++ b/spec/features/ide/user_opens_merge_request_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'IDE merge request', :js do
- let(:merge_request) { create(:merge_request, :with_diffs, :simple, source_project: project) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:project) { create(:project, :public, :repository) }
let(:user) { project.owner }
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index cfd0c7e210f..dfd6211a683 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -52,6 +52,6 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
end
def second_row
- page.all('table.import-table tbody tr')[1]
+ page.all('table tbody tr')[1]
end
end
diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb
index 3f00bdc478d..a0786d36fdf 100644
--- a/spec/features/issuables/issuable_list_spec.rb
+++ b/spec/features/issuables/issuable_list_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe 'issuable list', :js do
visit_issuable_list(:issue)
- expect(page).to have_text('Open ? Closed ? All ?')
+ expect(page).to have_text('Open Closed All')
end
it "counts merge requests closing issues icons for each issue" do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 9b2a11c4b0e..e2087868035 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -183,6 +183,16 @@ RSpec.describe 'GFM autocomplete', :js do
expect(find('#at-view-users')).to have_content(user.name)
end
+ it 'searches across full name for assignees' do
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('@speciÄ…lsome')
+ end
+
+ wait_for_requests
+
+ expect(find('.atwho-view li', visible: true)).to have_content(user.name)
+ end
+
it 'selects the first item for non-assignee dropdowns if a query is entered' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys(':1')
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index 59fba5f65e0..ca44978d223 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -11,6 +11,11 @@ RSpec.describe 'Issue Sidebar' do
let!(:label) { create(:label, project: project, title: 'bug') }
let(:issue) { create(:labeled_issue, project: project, labels: [label]) }
let!(:xss_label) { create(:label, project: project, title: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
+ let!(:milestone_expired) { create(:milestone, project: project, due_date: 5.days.ago) }
+ let!(:milestone_no_duedate) { create(:milestone, project: project, title: 'Foo - No due date') }
+ let!(:milestone1) { create(:milestone, project: project, title: 'Milestone-1', due_date: 20.days.from_now) }
+ let!(:milestone2) { create(:milestone, project: project, title: 'Milestone-2', due_date: 15.days.from_now) }
+ let!(:milestone3) { create(:milestone, project: project, title: 'Milestone-3', due_date: 10.days.from_now) }
before do
stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
@@ -134,6 +139,36 @@ RSpec.describe 'Issue Sidebar' do
end
end
+ context 'editing issue milestone', :js do
+ before do
+ page.within('.block.milestone > .title') do
+ click_on 'Edit'
+ end
+ end
+
+ it 'shows milestons list in the dropdown' do
+ page.within('.block.milestone .dropdown-content') do
+ # 5 milestones + "No milestone" = 6 items
+ expect(page.find('ul')).to have_selector('li[data-milestone-id]', count: 6)
+ end
+ end
+
+ it 'shows expired milestone at the bottom of the list' do
+ page.within('.block.milestone .dropdown-content ul') do
+ expect(page.find('li:last-child')).to have_content milestone_expired.title
+ end
+ end
+
+ it 'shows milestone due earliest at the top of the list' do
+ page.within('.block.milestone .dropdown-content ul') do
+ expect(page.all('li[data-milestone-id]')[1]).to have_content milestone3.title
+ expect(page.all('li[data-milestone-id]')[2]).to have_content milestone2.title
+ expect(page.all('li[data-milestone-id]')[3]).to have_content milestone1.title
+ expect(page.all('li[data-milestone-id]')[4]).to have_content milestone_no_duedate.title
+ end
+ end
+ end
+
context 'editing issue labels', :js do
before do
issue.update(labels: [label])
diff --git a/spec/features/issues/issue_state_spec.rb b/spec/features/issues/issue_state_spec.rb
index d5a115433aa..409f498798b 100644
--- a/spec/features/issues/issue_state_spec.rb
+++ b/spec/features/issues/issue_state_spec.rb
@@ -42,9 +42,15 @@ RSpec.describe 'issue state', :js do
end
describe 'when open', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297348' do
- context 'when clicking the top `Close issue` button', :aggregate_failures do
- let(:open_issue) { create(:issue, project: project) }
+ let(:open_issue) { create(:issue, project: project) }
+ it_behaves_like 'page with comment and close button', 'Close issue' do
+ def setup
+ visit project_issue_path(project, open_issue)
+ end
+ end
+
+ context 'when clicking the top `Close issue` button', :aggregate_failures do
before do
visit project_issue_path(project, open_issue)
end
@@ -53,9 +59,8 @@ RSpec.describe 'issue state', :js do
end
context 'when clicking the bottom `Close issue` button', :aggregate_failures do
- let(:open_issue) { create(:issue, project: project) }
-
before do
+ stub_feature_flags(remove_comment_close_reopen: false)
visit project_issue_path(project, open_issue)
end
@@ -64,9 +69,15 @@ RSpec.describe 'issue state', :js do
end
describe 'when closed', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297201' do
- context 'when clicking the top `Reopen issue` button', :aggregate_failures do
- let(:closed_issue) { create(:issue, project: project, state: 'closed') }
+ let(:closed_issue) { create(:issue, project: project, state: 'closed') }
+ it_behaves_like 'page with comment and close button', 'Reopen issue' do
+ def setup
+ visit project_issue_path(project, closed_issue)
+ end
+ end
+
+ context 'when clicking the top `Reopen issue` button', :aggregate_failures do
before do
visit project_issue_path(project, closed_issue)
end
@@ -75,9 +86,8 @@ RSpec.describe 'issue state', :js do
end
context 'when clicking the bottom `Reopen issue` button', :aggregate_failures do
- let(:closed_issue) { create(:issue, project: project, state: 'closed') }
-
before do
+ stub_feature_flags(remove_comment_close_reopen: false)
visit project_issue_path(project, closed_issue)
end
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index 24a261f592b..004488f2f64 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -39,8 +39,6 @@ RSpec.describe "User comments on issue", :js do
add_note(comment)
- wait_for_requests
-
expect(page.find('pre code').text).to eq code_block_content
end
@@ -51,8 +49,6 @@ RSpec.describe "User comments on issue", :js do
add_note(comment)
- wait_for_requests
-
expect(page.find('svg.mermaid')).to have_content html_content
within('svg.mermaid') { expect(page).not_to have_selector('img') }
end
diff --git a/spec/features/issues/user_creates_issue_by_email_spec.rb b/spec/features/issues/user_creates_issue_by_email_spec.rb
index 5a0036170ab..c47f24ab836 100644
--- a/spec/features/issues/user_creates_issue_by_email_spec.rb
+++ b/spec/features/issues/user_creates_issue_by_email_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Issues > User creates issue by email' do
project.add_developer(user)
end
- describe 'new issue by email' do
+ describe 'new issue by email', :js do
shared_examples 'show the email in the modal' do
let(:issue) { create(:issue, project: project) }
@@ -28,7 +28,7 @@ RSpec.describe 'Issues > User creates issue by email' do
page.within '#issuable-email-modal' do
email = project.new_issuable_address(user, 'issue')
- expect(page).to have_selector("input[value='#{email}']")
+ expect(page.find('input[type="text"]').value).to eq email
end
end
end
diff --git a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
index a20f65abebf..2b1c25174c2 100644
--- a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
+++ b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb
@@ -16,17 +16,17 @@ RSpec.describe 'Issues > User resets their incoming email token' do
end
it 'changes incoming email address token', :js do
- find('.issuable-email-modal-btn').click
- previous_token = find('input#issuable_email').value
- find('.incoming-email-token-reset').click
-
- wait_for_requests
-
- expect(page).to have_no_field('issuable_email', with: previous_token)
- new_token = project.new_issuable_address(user.reload, 'issue')
- expect(page).to have_field(
- 'issuable_email',
- with: new_token
- )
+ page.find('[data-testid="issuable-email-modal-btn"]').click
+
+ page.within '#issuable-email-modal' do
+ previous_token = page.find('input[type="text"]').value
+ page.find('[data-testid="incoming-email-token-reset"]').click
+
+ wait_for_requests
+
+ expect(page.find('input[type="text"]').value).not_to eq previous_token
+ new_token = project.new_issuable_address(user.reload, 'issue')
+ expect(page.find('input[type="text"]').value).to eq new_token
+ end
end
end
diff --git a/spec/features/issues/user_toggles_subscription_spec.rb b/spec/features/issues/user_toggles_subscription_spec.rb
index 971c8a3b431..d91c187c840 100644
--- a/spec/features/issues/user_toggles_subscription_spec.rb
+++ b/spec/features/issues/user_toggles_subscription_spec.rb
@@ -15,13 +15,13 @@ RSpec.describe "User toggles subscription", :js do
end
it "unsubscribes from issue" do
- subscription_button = find(".js-issuable-subscribe-button")
+ subscription_button = find('[data-testid="subscription-toggle"]')
# Check we're subscribed.
expect(subscription_button).to have_css("button.is-checked")
# Toggle subscription.
- find(".js-issuable-subscribe-button button").click
+ find('[data-testid="subscription-toggle"]').click
wait_for_requests
# Check we're unsubscribed.
@@ -33,7 +33,7 @@ RSpec.describe "User toggles subscription", :js do
it 'is disabled' do
expect(page).to have_content('Notifications have been disabled by the project or group owner')
- expect(page).not_to have_selector('.js-issuable-subscribe-button')
+ expect(page).not_to have_selector('[data-testid="subscription-toggle"]')
end
end
end
diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb
index 5d141580874..aeb42cc2edb 100644
--- a/spec/features/labels_hierarchy_spec.rb
+++ b/spec/features/labels_hierarchy_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe 'Labels Hierarchy', :js do
before do
stub_feature_flags(graphql_board_lists: false)
+ stub_feature_flags(board_new_list: false)
grandparent.add_owner(user)
sign_in(user)
@@ -270,6 +271,10 @@ RSpec.describe 'Labels Hierarchy', :js do
end
context 'creating boards lists' do
+ before do
+ stub_feature_flags(board_new_list: false)
+ end
+
context 'on project boards' do
let(:board) { create(:board, project: project_1) }
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index 151ef76e884..8e28f89f49e 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -206,6 +206,9 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
# `markdown` helper expects a `@project` and `@group` variable
@project = @feat.project
@group = @feat.group
+
+ stub_application_setting(plantuml_enabled: true, plantuml_url: 'http://localhost:8080')
+ stub_application_setting(kroki_enabled: true, kroki_url: 'http://localhost:8000')
end
let(:project) { @feat.project } # Shadow this so matchers can use it
@@ -265,6 +268,18 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
aggregate_failures 'ColorFilter' do
expect(doc).to parse_colors
end
+
+ aggregate_failures 'MermaidFilter' do
+ expect(doc).to parse_mermaid
+ end
+
+ aggregate_failures 'PlantumlFilter' do
+ expect(doc).to parse_plantuml
+ end
+
+ aggregate_failures 'KrokiFilter' do
+ expect(doc).to parse_kroki
+ end
end
end
@@ -338,6 +353,18 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
aggregate_failures 'ColorFilter' do
expect(doc).to parse_colors
end
+
+ aggregate_failures 'MermaidFilter' do
+ expect(doc).to parse_mermaid
+ end
+
+ aggregate_failures 'PlantumlFilter' do
+ expect(doc).to parse_plantuml
+ end
+
+ aggregate_failures 'KrokiFilter' do
+ expect(doc).to parse_kroki
+ end
end
end
diff --git a/spec/features/markdown/mermaid_spec.rb b/spec/features/markdown/mermaid_spec.rb
index 23cdd9d2ce5..207678e07c3 100644
--- a/spec/features/markdown/mermaid_spec.rb
+++ b/spec/features/markdown/mermaid_spec.rb
@@ -108,7 +108,7 @@ RSpec.describe 'Mermaid rendering', :js do
expect(svg[:style]).to match(/max-width/)
expect(svg[:width].to_i).to eq(100)
- expect(svg[:height].to_i).to eq(0)
+ expect(svg[:height].to_i).to be_within(5).of(220)
end
end
diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb
index 3d18aef9327..d4b185a82e9 100644
--- a/spec/features/merge_request/user_accepts_merge_request_spec.rb
+++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inline do
- let(:merge_request) { create(:merge_request, :with_diffs, :simple, source_project: project) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:project) { create(:project, :public, :repository) }
let(:user) { create(:user) }
diff --git a/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb b/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb
index 2b94c072c8b..ab3ef7c1ac0 100644
--- a/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb
+++ b/spec/features/merge_request/user_closes_reopens_merge_request_state_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'User closes/reopens a merge request', :js do
+RSpec.describe 'User closes/reopens a merge request', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297500' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
@@ -12,9 +12,15 @@ RSpec.describe 'User closes/reopens a merge request', :js do
end
describe 'when open' do
- context 'when clicking the top `Close merge request` link', :aggregate_failures do
- let(:open_merge_request) { create(:merge_request, source_project: project, target_project: project) }
+ let(:open_merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ it_behaves_like 'page with comment and close button', 'Close merge request' do
+ def setup
+ visit merge_request_path(open_merge_request)
+ end
+ end
+ context 'when clicking the top `Close merge request` link', :aggregate_failures do
before do
visit merge_request_path(open_merge_request)
end
@@ -34,9 +40,8 @@ RSpec.describe 'User closes/reopens a merge request', :js do
end
context 'when clicking the bottom `Close merge request` button', :aggregate_failures do
- let(:open_merge_request) { create(:merge_request, source_project: project, target_project: project) }
-
before do
+ stub_feature_flags(remove_comment_close_reopen: false)
visit merge_request_path(open_merge_request)
end
@@ -55,10 +60,23 @@ RSpec.describe 'User closes/reopens a merge request', :js do
end
end
- describe 'when closed', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297500' do
- context 'when clicking the top `Reopen merge request` link', :aggregate_failures do
- let(:closed_merge_request) { create(:merge_request, source_project: project, target_project: project, state: 'closed') }
+ describe 'when closed' do
+ let(:closed_merge_request) { create(:merge_request, source_project: project, target_project: project, state: 'closed') }
+ it_behaves_like 'page with comment and close button', 'Close merge request' do
+ def setup
+ visit merge_request_path(closed_merge_request)
+
+ within '.detail-page-header' do
+ click_button 'Toggle dropdown'
+ click_link 'Reopen merge request'
+ end
+
+ wait_for_requests
+ end
+ end
+
+ context 'when clicking the top `Reopen merge request` link', :aggregate_failures do
before do
visit merge_request_path(closed_merge_request)
end
@@ -78,9 +96,8 @@ RSpec.describe 'User closes/reopens a merge request', :js do
end
context 'when clicking the bottom `Reopen merge request` button', :aggregate_failures do
- let(:closed_merge_request) { create(:merge_request, source_project: project, target_project: project, state: 'closed') }
-
before do
+ stub_feature_flags(remove_comment_close_reopen: false)
visit merge_request_path(closed_merge_request)
end
diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb
index 817b4e0b48e..2c949ed84f4 100644
--- a/spec/features/merge_request/user_edits_mr_spec.rb
+++ b/spec/features/merge_request/user_edits_mr_spec.rb
@@ -20,14 +20,4 @@ RSpec.describe 'Merge request > User edits MR' do
include_context 'merge request edit context'
it_behaves_like 'an editable merge request'
end
-
- context 'when merge_request_reviewers is turned off' do
- before do
- stub_feature_flags(merge_request_reviewers: false)
- end
-
- it 'does not render reviewers dropdown' do
- expect(page).not_to have_selector('.js-reviewer-search')
- end
- end
end
diff --git a/spec/features/merge_request/user_manages_subscription_spec.rb b/spec/features/merge_request/user_manages_subscription_spec.rb
index 9ed5b67fa0e..3cdb22000f6 100644
--- a/spec/features/merge_request/user_manages_subscription_spec.rb
+++ b/spec/features/merge_request/user_manages_subscription_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'User manages subscription', :js do
end
it 'toggles subscription' do
- page.within('.js-issuable-subscribe-button') do
+ page.within('[data-testid="subscription-toggle"]') do
wait_for_requests
expect(page).to have_css 'button:not(.is-checked)'
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 ea3e90a4508..8438c0af553 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('Please retry the job or push a new commit to fix the failure')
+ 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.')
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('Please retry the job or push a new commit to fix the failure')
+ 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.')
end
end
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 5e99383e4a1..63b463a2c5f 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
wait_for_requests
- expect(page).to have_content 'Merge when pipeline succeeds', wait: 0
+ expect(page).to have_content 'Merge when pipeline succeeds'
end
it_behaves_like 'Merge when pipeline succeeds activator'
@@ -145,7 +145,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
before do
merge_request.update!(
merge_user: merge_request.author,
- merge_error: 'Something went wrong.'
+ merge_error: 'Something went wrong'
)
refresh
end
@@ -155,7 +155,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
wait_for_requests
page.within('.mr-section-container') do
- expect(page).to have_content('Merge failed: Something went wrong. Please try again.')
+ expect(page).to have_content('Something went wrong. Try again.')
end
end
end
@@ -174,7 +174,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
wait_for_requests
page.within('.mr-section-container') do
- expect(page).to have_content('Merge failed: Something went wrong. Please try again.')
+ expect(page).to have_content('Something went wrong. Try again.')
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 489582521b5..e629bc0dc53 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -161,7 +161,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
fill_in 'note[note]', with: 'Some new content'
accept_confirm do
- find('.btn-cancel').click
+ find('[data-testid="cancel"]').click
end
end
expect(find('.js-note-text').text).to eq ''
diff --git a/spec/features/merge_request/user_reverts_merge_request_spec.rb b/spec/features/merge_request/user_reverts_merge_request_spec.rb
index 5e9611de460..9cbba6c470f 100644
--- a/spec/features/merge_request/user_reverts_merge_request_spec.rb
+++ b/spec/features/merge_request/user_reverts_merge_request_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'User reverts a merge request', :js do
- let(:merge_request) { create(:merge_request, :with_diffs, :simple, source_project: project) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:project) { create(:project, :public, :repository) }
let(:user) { create(:user) }
@@ -17,46 +17,28 @@ RSpec.describe 'User reverts a merge request', :js do
wait_for_requests
- visit(merge_request_path(merge_request))
+ # do not reload the page by visiting, let javascript update the page as it will validate we have loaded the modal
+ # code correctly on page update that adds the `revert` button
end
it 'reverts a merge request', :sidekiq_might_not_need_inline do
- find("a[href='#modal-revert-commit']").click
+ revert_commit
- page.within('#modal-revert-commit') do
- uncheck('create_merge_request')
- click_button('Revert')
- end
+ wait_for_requests
expect(page).to have_content('The merge request has been successfully reverted.')
-
- wait_for_requests
end
it 'does not revert a merge request that was previously reverted', :sidekiq_might_not_need_inline do
- find("a[href='#modal-revert-commit']").click
-
- page.within('#modal-revert-commit') do
- uncheck('create_merge_request')
- click_button('Revert')
- end
-
- find("a[href='#modal-revert-commit']").click
+ revert_commit
- page.within('#modal-revert-commit') do
- uncheck('create_merge_request')
- click_button('Revert')
- end
+ revert_commit
expect(page).to have_content('Sorry, we cannot revert this merge request automatically.')
end
it 'reverts a merge request in a new merge request', :sidekiq_might_not_need_inline do
- find("a[href='#modal-revert-commit']").click
-
- page.within('#modal-revert-commit') do
- click_button('Revert')
- end
+ revert_commit(create_merge_request: true)
expect(page).to have_content('The merge request has been successfully reverted. You can now submit a merge request to get this change into the original branch.')
end
@@ -68,4 +50,13 @@ RSpec.describe 'User reverts a merge request', :js do
expect(page).not_to have_link('Revert')
end
+
+ def revert_commit(create_merge_request: false)
+ click_button('Revert')
+
+ page.within('[data-testid="modal-commit"]') do
+ uncheck('create_merge_request') unless create_merge_request
+ click_button('Revert')
+ end
+ end
end
diff --git a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb
index 7f4249336fe..78c1b2a718e 100644
--- a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb
+++ b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Merge request > User cherry-picks', :js do
it 'does not show a Cherry-pick button' do
visit project_merge_request_path(project, merge_request)
- expect(page).not_to have_link 'Cherry-pick'
+ expect(page).not_to have_button 'Cherry-pick'
end
end
@@ -40,7 +40,7 @@ RSpec.describe 'Merge request > User cherry-picks', :js do
it 'shows a Cherry-pick button' do
visit project_merge_request_path(project, merge_request)
- expect(page).to have_link 'Cherry-pick'
+ expect(page).to have_button 'Cherry-pick'
end
it 'hides the cherry pick button for an archived project' do
@@ -48,7 +48,7 @@ RSpec.describe 'Merge request > User cherry-picks', :js do
visit project_merge_request_path(project, merge_request)
- expect(page).not_to have_link 'Cherry-pick'
+ expect(page).not_to have_button 'Cherry-pick'
end
end
@@ -56,18 +56,12 @@ RSpec.describe 'Merge request > User cherry-picks', :js do
before do
visit project_merge_request_path(project, merge_request)
- click_link('Cherry-pick')
+ click_button('Cherry-pick')
end
it 'shows the cherry-pick modal' do
expect(page).to have_content('Cherry-pick this merge request')
end
-
- it 'closes the cherry-pick modal with escape keypress' do
- find('#modal-cherry-pick-commit').send_keys(:escape)
-
- expect(page).not_to have_content('Start a new merge request with these changes')
- end
end
end
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 d9743f6f330..708ce53b4fe 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
@@ -160,7 +160,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'merges the merge request' do
expect(page).to have_content('Merged by')
- expect(page).to have_link('Revert')
+ expect(page).to have_button('Revert')
end
end
@@ -357,7 +357,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'merges the merge request' do
expect(page).to have_content('Merged by')
- expect(page).to have_link('Revert')
+ expect(page).to have_button('Revert')
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 c2b2ada47be..0854a8b9fb7 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -77,15 +77,26 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
it 'allows me to merge, see cherry-pick modal and load branches list', :sidekiq_might_not_need_inline do
+ modal_selector = '[data-testid="modal-commit"]'
+
wait_for_requests
click_button 'Merge'
wait_for_requests
- click_link 'Cherry-pick'
- page.find('.js-project-refs-dropdown').click
- wait_for_requests
- expect(page.all('.js-cherry-pick-form .dropdown-content li').size).to be > 1
+ click_button 'Cherry-pick'
+
+ page.within(modal_selector) do
+ click_button 'master'
+ end
+
+ page.within("#{modal_selector} .dropdown-menu") do
+ find('[data-testid="dropdown-search-box"]').set('')
+
+ wait_for_requests
+
+ expect(page.all('[data-testid="dropdown-item"]').size).to be > 1
+ end
end
end
@@ -319,7 +330,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
wait_for_requests
page.within('.mr-section-container') do
- expect(page).to have_content('Merge failed: Something went wrong')
+ expect(page).to have_content('Something went wrong.')
end
end
end
@@ -340,7 +351,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
wait_for_requests
page.within('.mr-section-container') do
- expect(page).to have_content('Merge failed: Something went wrong')
+ expect(page).to have_content('Something went wrong.')
end
end
end
@@ -377,7 +388,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
click_button 'Merge'
page.within('.mr-widget-body') do
- expect(page).to have_content('Conflicts detected during merge')
+ expect(page).to have_content('An error occurred while merging')
end
end
end
diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
index 04d8c52df61..1ef6d2a1068 100644
--- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
+++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb
@@ -9,152 +9,166 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master', status: 'running', sha: project.commit.id) }
let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test') }
- before do
- build.run
- build.trace.set('hello')
- sign_in(user)
- visit_merge_request
- end
-
- def visit_merge_request(format: :html, serializer: nil)
- visit project_merge_request_path(project, merge_request, format: format, serializer: serializer)
- end
-
- it 'displays a mini pipeline graph' do
- expect(page).to have_selector('.mr-widget-pipeline-graph')
- end
-
- context 'as json' do
- let(:artifacts_file1) { fixture_file_upload(File.join('spec/fixtures/banana_sample.gif'), 'image/gif') }
- let(:artifacts_file2) { fixture_file_upload(File.join('spec/fixtures/dk.png'), 'image/png') }
-
+ shared_examples 'mini pipeline renders' do |ci_mini_pipeline_gl_dropdown_enabled|
before do
- job = create(:ci_build, :success, :trace_artifact, pipeline: pipeline)
- create(:ci_job_artifact, :archive, file: artifacts_file1, job: job)
- create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
+ build.run
+ build.trace.set('hello')
+ sign_in(user)
+ stub_feature_flags(ci_mini_pipeline_gl_dropdown: ci_mini_pipeline_gl_dropdown_enabled)
+ visit_merge_request
end
- # TODO: https://gitlab.com/gitlab-org/gitlab-foss/issues/48034
- xit 'avoids repeated database queries' do
- before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
-
- job = create(:ci_build, :success, :trace_artifact, pipeline: pipeline)
- create(:ci_job_artifact, :archive, file: artifacts_file2, job: job)
- create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
-
- after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
+ let_it_be(:dropdown_toggle_selector) do
+ if ci_mini_pipeline_gl_dropdown_enabled
+ '[data-testid="mini-pipeline-graph-dropdown"] .dropdown-toggle'
+ else
+ '[data-testid="mini-pipeline-graph-dropdown-toggle"]'
+ end
+ end
- expect(before.count).to eq(after.count)
- expect(before.cached_count).to eq(after.cached_count)
+ def visit_merge_request(format: :html, serializer: nil)
+ visit project_merge_request_path(project, merge_request, format: format, serializer: serializer)
end
- end
- describe 'build list toggle' do
- let(:toggle) do
- find('.mini-pipeline-graph-dropdown-toggle')
- first('.mini-pipeline-graph-dropdown-toggle')
+ it 'displays a mini pipeline graph' do
+ expect(page).to have_selector('.mr-widget-pipeline-graph')
end
- # Status icon button styles should update as described in
- # https://gitlab.com/gitlab-org/gitlab-foss/issues/42769
- it 'has unique styles for default, :hover, :active, and :focus states' do
- find('.mini-pipeline-graph-dropdown-toggle')
- default_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
- default_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
- default_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
+ context 'as json' do
+ let(:artifacts_file1) { fixture_file_upload(File.join('spec/fixtures/banana_sample.gif'), 'image/gif') }
+ let(:artifacts_file2) { fixture_file_upload(File.join('spec/fixtures/dk.png'), 'image/png') }
- toggle.hover
+ before do
+ job = create(:ci_build, :success, :trace_artifact, pipeline: pipeline)
+ create(:ci_job_artifact, :archive, file: artifacts_file1, job: job)
+ create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
+ end
- find('.mini-pipeline-graph-dropdown-toggle')
- hover_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
- hover_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
- hover_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
+ # TODO: https://gitlab.com/gitlab-org/gitlab-foss/issues/48034
+ xit 'avoids repeated database queries' do
+ before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
- page.driver.browser.action.click_and_hold(toggle.native).perform
+ job = create(:ci_build, :success, :trace_artifact, pipeline: pipeline)
+ create(:ci_job_artifact, :archive, file: artifacts_file2, job: job)
+ create(:ci_build, :manual, pipeline: pipeline, when: 'manual')
- find('.mini-pipeline-graph-dropdown-toggle')
- active_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
- active_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
- active_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
+ after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
- page.driver.browser.action.release(toggle.native)
- .move_by(100, 100)
- .perform
+ expect(before.count).to eq(after.count)
+ expect(before.cached_count).to eq(after.cached_count)
+ end
+ end
- find('.mini-pipeline-graph-dropdown-toggle')
- focus_background_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('background-color');")
- focus_foreground_color = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible svg').css('fill');")
- focus_box_shadow = evaluate_script("$('.mini-pipeline-graph-dropdown-toggle:visible').css('box-shadow');")
+ describe 'build list toggle' do
+ let(:toggle) do
+ find(dropdown_toggle_selector)
+ first(dropdown_toggle_selector)
+ end
- expect(default_background_color).not_to eq(hover_background_color)
- expect(hover_background_color).not_to eq(active_background_color)
- expect(default_background_color).not_to eq(active_background_color)
+ # Status icon button styles should update as described in
+ # https://gitlab.com/gitlab-org/gitlab-foss/issues/42769
+ it 'has unique styles for default, :hover, :active, and :focus states' do
+ default_background_color, default_foreground_color, default_box_shadow = get_toggle_colors(dropdown_toggle_selector)
- expect(default_foreground_color).not_to eq(hover_foreground_color)
- expect(hover_foreground_color).not_to eq(active_foreground_color)
- expect(default_foreground_color).not_to eq(active_foreground_color)
+ toggle.hover
+ hover_background_color, hover_foreground_color, hover_box_shadow = get_toggle_colors(dropdown_toggle_selector)
- expect(focus_background_color).to eq(hover_background_color)
- expect(focus_foreground_color).to eq(hover_foreground_color)
+ page.driver.browser.action.click_and_hold(toggle.native).perform
+ active_background_color, active_foreground_color, active_box_shadow = get_toggle_colors(dropdown_toggle_selector)
+ page.driver.browser.action.release(toggle.native).perform
- expect(default_box_shadow).to eq('none')
- expect(hover_box_shadow).to eq('none')
- expect(active_box_shadow).not_to eq('none')
- expect(focus_box_shadow).not_to eq('none')
- end
+ page.driver.browser.action.click(toggle.native).move_by(100, 100).perform
+ focus_background_color, focus_foreground_color, focus_box_shadow = get_toggle_colors(dropdown_toggle_selector)
- it 'shows tooltip when hovered' do
- toggle.hover
+ expect(default_background_color).not_to eq(hover_background_color)
+ expect(hover_background_color).not_to eq(active_background_color)
+ expect(default_background_color).not_to eq(active_background_color)
- expect(page).to have_selector('.tooltip')
- end
- end
+ expect(default_foreground_color).not_to eq(hover_foreground_color)
+ expect(hover_foreground_color).not_to eq(active_foreground_color)
+ expect(default_foreground_color).not_to eq(active_foreground_color)
- describe 'builds list menu' do
- let(:toggle) do
- find('.mini-pipeline-graph-dropdown-toggle')
- first('.mini-pipeline-graph-dropdown-toggle')
- end
+ expect(focus_background_color).to eq(hover_background_color)
+ expect(focus_foreground_color).to eq(hover_foreground_color)
- before do
- toggle.click
- wait_for_requests
- end
+ expect(default_box_shadow).to eq('none')
+ expect(hover_box_shadow).to eq('none')
+ expect(active_box_shadow).not_to eq('none')
+ expect(focus_box_shadow).not_to eq('none')
+ end
+
+ it 'shows tooltip when hovered' do
+ toggle.hover
- it 'pens when toggle is clicked' do
- expect(toggle.find(:xpath, '..')).to have_selector('.mini-pipeline-graph-dropdown-menu')
+ expect(page).to have_selector('.tooltip')
+ end
end
- it 'closes when toggle is clicked again' do
- toggle.click
+ describe 'builds list menu' do
+ let(:toggle) do
+ find(dropdown_toggle_selector)
+ first(dropdown_toggle_selector)
+ end
- expect(toggle.find(:xpath, '..')).not_to have_selector('.mini-pipeline-graph-dropdown-menu')
- end
+ before do
+ toggle.click
+ wait_for_requests
+ end
- it 'closes when clicking somewhere else' do
- find('body').click
+ it 'pens when toggle is clicked' do
+ expect(toggle.find(:xpath, '..')).to have_selector('.mini-pipeline-graph-dropdown-menu')
+ end
- expect(toggle.find(:xpath, '..')).not_to have_selector('.mini-pipeline-graph-dropdown-menu')
- end
+ it 'closes when toggle is clicked again' do
+ toggle.click
- describe 'build list build item' do
- let(:build_item) do
- find('.mini-pipeline-graph-dropdown-item')
- first('.mini-pipeline-graph-dropdown-item')
+ expect(toggle.find(:xpath, '..')).not_to have_selector('.mini-pipeline-graph-dropdown-menu')
end
- it 'visits the build page when clicked' do
- build_item.click
- find('.build-page')
+ it 'closes when clicking somewhere else' do
+ find('body').click
- expect(current_path).to eql(project_job_path(project, build))
+ expect(toggle.find(:xpath, '..')).not_to have_selector('.mini-pipeline-graph-dropdown-menu')
end
- it 'shows tooltip when hovered' do
- build_item.hover
+ describe 'build list build item' do
+ let(:build_item) do
+ find('.mini-pipeline-graph-dropdown-item')
+ first('.mini-pipeline-graph-dropdown-item')
+ end
- expect(page).to have_selector('.tooltip')
+ it 'visits the build page when clicked' do
+ build_item.click
+ find('.build-page')
+
+ expect(current_path).to eql(project_job_path(project, build))
+ end
+
+ it 'shows tooltip when hovered' do
+ build_item.hover
+
+ expect(page).to have_selector('.tooltip')
+ end
end
end
end
+
+ context 'with ci_mini_pipeline_gl_dropdown disabled' do
+ it_behaves_like "mini pipeline renders", false
+ end
+
+ context 'with ci_mini_pipeline_gl_dropdown enabled' do
+ it_behaves_like "mini pipeline renders", true
+ end
+
+ private
+
+ def get_toggle_colors(selector)
+ find(selector)
+ [
+ evaluate_script("$('#{selector}:visible').css('background-color');"),
+ evaluate_script("$('#{selector}:visible svg').css('fill');"),
+ evaluate_script("$('#{selector}:visible').css('box-shadow');")
+ ]
+ end
end
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 a2ec34335ec..bbeb91bbd19 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
@@ -73,6 +73,23 @@ RSpec.describe 'User comments on a diff', :js do
end
end
+ it 'allows suggestions in replies' do
+ click_diff_line(find("[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```")
+ click_button('Add comment now')
+ end
+
+ wait_for_requests
+
+ click_button 'Reply...'
+
+ find('.js-suggestion-btn').click
+
+ expect(find('.js-vue-issue-note-form').value).to include("url = https://github.com/gitlabhq/gitlab-shell.git")
+ end
+
it 'suggestion is appliable' do
click_diff_line(find("[id='#{sample_compare.changes[1][:line_code]}']"))
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 e8998f9457a..9bda48a3ec5 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
@@ -30,19 +30,6 @@ RSpec.describe 'User views an open merge request' do
end
end
- context 'when merge_request_reviewers is turned off' do
- let(:project) { create(:project, :public, :repository) }
-
- before do
- stub_feature_flags(merge_request_reviewers: false)
- visit(merge_request_path(merge_request))
- end
-
- it 'has reviewers in sidebar' do
- expect(page).not_to have_css('.reviewer')
- end
- end
-
context 'when a merge request has repository', :js do
let(:project) { create(:project, :public, :repository) }
@@ -107,5 +94,21 @@ RSpec.describe 'User views an open merge request' do
end
end
end
+
+ context 'when the assignee\'s availability set' do
+ before do
+ merge_request.author.create_status(availability: 'busy')
+ merge_request.assignees << merge_request.author
+
+ visit(merge_request_path(merge_request))
+ end
+
+ it 'exposes the availability in the data-availability attribute' do
+ assignees_data = find_all("input[name='merge_request[assignee_ids][]']", visible: false)
+
+ expect(assignees_data.size).to eq(1)
+ expect(assignees_data.first['data-availability']).to eq('busy')
+ end
+ end
end
end
diff --git a/spec/features/merge_requests/user_filters_by_milestones_spec.rb b/spec/features/merge_requests/user_filters_by_milestones_spec.rb
index 41a0b0012d1..877d5e6a4ee 100644
--- a/spec/features/merge_requests/user_filters_by_milestones_spec.rb
+++ b/spec/features/merge_requests/user_filters_by_milestones_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Merge Requests > User filters by milestones', :js do
let(:milestone) { create(:milestone, project: project) }
before do
- create(:merge_request, :with_diffs, source_project: project)
+ create(:merge_request, source_project: project)
create(:merge_request, :simple, source_project: project, milestone: milestone)
sign_in(user)
diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
index 36d28ae2822..6b8dcd7dbb6 100644
--- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
@@ -40,9 +40,8 @@ RSpec.describe 'Merge requests > User lists merge requests' do
updated_at: 10.seconds.ago)
end
- context 'when merge_request_reviewers is turned on' do
+ context 'merge request reviewers' do
before do
- stub_feature_flags(merge_request_reviewers: true)
visit_merge_requests(project, reviewer_id: user.id)
end
@@ -62,15 +61,6 @@ RSpec.describe 'Merge requests > User lists merge requests' do
end
end
- context 'when merge_request_reviewers is turned false' do
- it 'has no reviewers in MR list' do
- stub_feature_flags(merge_request_reviewers: false)
- visit_merge_requests(project, reviewer_id: user.id)
-
- expect(page).not_to have_css('.issuable-reviewers')
- end
- end
-
it 'filters on no assignee' do
visit_merge_requests(project, assignee_id: IssuableFinder::Params::FILTER_NONE)
diff --git a/spec/features/profiles/user_edit_preferences_spec.rb b/spec/features/profiles/user_edit_preferences_spec.rb
index d489d92c524..3129e4bd952 100644
--- a/spec/features/profiles/user_edit_preferences_spec.rb
+++ b/spec/features/profiles/user_edit_preferences_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe 'User edit preferences profile' do
+RSpec.describe 'User edit preferences profile', :js do
let(:user) { create(:user) }
before do
@@ -53,7 +53,14 @@ RSpec.describe 'User edit preferences profile' do
fill_in 'Tab width', with: -1
click_button 'Save changes'
- expect(page).to have_content('Failed to save preferences')
+ field = page.find_field('user[tab_width]')
+ message = field.native.attribute("validationMessage")
+ expect(message).to eq "Value must be greater than or equal to 1."
+
+ # User trying to hack an invalid value
+ page.execute_script("document.querySelector('#user_tab_width').setAttribute('min', '-1')")
+ click_button 'Save changes'
+ expect(page).to have_content('Failed to save preferences.')
end
end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 239bc04a9cb..bd4917824d1 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -199,6 +199,38 @@ RSpec.describe 'User edit profile' do
expect(busy_status.checked?).to eq(true)
end
+ context 'with user status set to busy' do
+ let(:project) { create(:project, :public) }
+ let(:issue) { create(:issue, project: project, author: user) }
+
+ before do
+ toggle_busy_status
+ submit_settings
+
+ project.add_developer(user)
+ visit project_issue_path(project, issue)
+ end
+
+ it 'shows author as busy in the assignee dropdown' do
+ find('.block.assignee .edit-link').click
+ wait_for_requests
+
+ page.within '.dropdown-menu-user' do
+ expect(page).to have_content("#{user.name} (Busy)")
+ end
+ end
+
+ it 'displays the assignee busy status' do
+ click_button 'assign yourself'
+ wait_for_requests
+
+ visit project_issue_path(project, issue)
+ wait_for_requests
+
+ expect(page.find('[data-testid="expanded-assignee"]')).to have_text("#{user.name} (Busy)")
+ end
+ end
+
context 'with set_user_availability_status feature flag disabled' do
before do
stub_feature_flags(set_user_availability_status: false)
diff --git a/spec/features/profiles/user_search_settings_spec.rb b/spec/features/profiles/user_search_settings_spec.rb
new file mode 100644
index 00000000000..60df0d7532b
--- /dev/null
+++ b/spec/features/profiles/user_search_settings_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User searches their settings', :js do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'in profile page' do
+ let(:visit_path) { profile_path }
+
+ it_behaves_like 'can search settings with feature flag check', 'Public Avatar', 'Main settings'
+ end
+
+ context 'in preferences page' do
+ before do
+ visit profile_preferences_path
+ end
+
+ it_behaves_like 'can search settings', 'Syntax highlighting theme', 'Behavior'
+ end
+end
diff --git a/spec/features/profiles/user_visits_notifications_tab_spec.rb b/spec/features/profiles/user_visits_notifications_tab_spec.rb
index 997cc8e3c4b..289fbff0404 100644
--- a/spec/features/profiles/user_visits_notifications_tab_spec.rb
+++ b/spec/features/profiles/user_visits_notifications_tab_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'User visits the notifications tab', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(vue_notification_dropdown: false)
project.add_maintainer(user)
sign_in(user)
visit(profile_notifications_path)
diff --git a/spec/features/profiles/user_visits_profile_preferences_page_spec.rb b/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
index 56db7efff51..da63f7c0f41 100644
--- a/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
+++ b/spec/features/profiles/user_visits_profile_preferences_page_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'User visits the profile preferences page' do
+RSpec.describe 'User visits the profile preferences page', :js do
include Select2Helper
let(:user) { create(:user) }
@@ -39,7 +39,7 @@ RSpec.describe 'User visits the profile preferences page' do
describe 'User changes their default dashboard', :js do
it 'creates a flash message' do
select2('stars', from: '#user_dashboard')
- click_button 'Save'
+ click_button 'Save changes'
wait_for_requests
@@ -48,7 +48,7 @@ RSpec.describe 'User visits the profile preferences page' do
it 'updates their preference' do
select2('stars', from: '#user_dashboard')
- click_button 'Save'
+ click_button 'Save changes'
wait_for_requests
@@ -67,7 +67,7 @@ RSpec.describe 'User visits the profile preferences page' do
describe 'User changes their language', :js do
it 'creates a flash message', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/31404' do
select2('en', from: '#user_preferred_language')
- click_button 'Save'
+ click_button 'Save changes'
wait_for_requests
@@ -77,7 +77,7 @@ RSpec.describe 'User visits the profile preferences page' do
it 'updates their preference' do
wait_for_requests
select2('pt_BR', from: '#user_preferred_language')
- click_button 'Save'
+ click_button 'Save changes'
wait_for_requests
refresh
@@ -94,6 +94,8 @@ RSpec.describe 'User visits the profile preferences page' do
click_button 'Save changes'
+ wait_for_requests
+
expect(user.reload.render_whitespace_in_code).to be(true)
expect(render_whitespace_field).to be_checked
end
diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb
index 77da1f138c7..475fda5e7a1 100644
--- a/spec/features/profiles/user_visits_profile_spec.rb
+++ b/spec/features/profiles/user_visits_profile_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe 'User visits their profile' do
find(:css, '.header-user-dropdown-toggle').click
page.within ".header-user" do
- click_link "Profile"
+ click_link user.username
end
end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index dcad7ee66a3..4bfe8852291 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -21,11 +21,11 @@ RSpec.describe 'Branches' do
before do
# Add 4 stale branches
(1..4).reverse_each do |i|
- travel_to((threshold + i).ago) { create_file(message: "a commit in stale-#{i}", branch_name: "stale-#{i}") }
+ travel_to((threshold + i.hours).ago) { create_file(message: "a commit in stale-#{i}", branch_name: "stale-#{i}") }
end
# Add 6 active branches
(1..6).each do |i|
- travel_to((threshold - i).ago) { create_file(message: "a commit in active-#{i}", branch_name: "active-#{i}") }
+ travel_to((threshold - i.hours).ago) { create_file(message: "a commit in active-#{i}", branch_name: "active-#{i}") }
end
end
@@ -34,7 +34,7 @@ RSpec.describe 'Branches' do
visit project_branches_path(project)
expect(page).to have_content(sorted_branches(repository, count: 5, sort_by: :updated_desc, state: 'active'))
- expect(page).to have_content(sorted_branches(repository, count: 4, sort_by: :updated_desc, state: 'stale'))
+ expect(page).to have_content(sorted_branches(repository, count: 4, sort_by: :updated_asc, state: 'stale'))
expect(page).to have_link('Show more active branches', href: project_branches_filtered_path(project, state: 'active'))
expect(page).not_to have_content('Show more stale branches')
@@ -50,10 +50,10 @@ RSpec.describe 'Branches' do
end
describe 'Stale branches page' do
- it 'shows 4 active branches sorted by last updated' do
+ it 'shows 4 stale branches sorted by last updated' do
visit project_branches_filtered_path(project, state: 'stale')
- expect(page).to have_content(sorted_branches(repository, count: 4, sort_by: :updated_desc, state: 'stale'))
+ expect(page).to have_content(sorted_branches(repository, count: 4, sort_by: :updated_asc, state: 'stale'))
end
end
diff --git a/spec/features/projects/commit/cherry_pick_spec.rb b/spec/features/projects/commit/cherry_pick_spec.rb
index 9fe3f4cd63e..489a90cc8fc 100644
--- a/spec/features/projects/commit/cherry_pick_spec.rb
+++ b/spec/features/projects/commit/cherry_pick_spec.rb
@@ -2,108 +2,126 @@
require 'spec_helper'
-RSpec.describe 'Cherry-pick Commits' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project) { create(:project, :repository, namespace: group) }
- let(:master_pickable_commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
- let(:master_pickable_merge) { project.commit('e56497bb5f03a90a51293fc6d516788730953899') }
+RSpec.describe 'Cherry-pick Commits', :js do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
+ let!(:project) { create_default(:project, :repository, namespace: user.namespace) }
+ let(:master_pickable_commit) { project.commit(sha) }
before do
sign_in(user)
- project.add_maintainer(user)
- visit project_commit_path(project, master_pickable_commit.id)
end
- context "I cherry-pick a commit" do
- it do
- find("a[href='#modal-cherry-pick-commit']").click
- expect(page).not_to have_content('v1.0.0') # Only branches, not tags
- page.within('#modal-cherry-pick-commit') do
- uncheck 'create_merge_request'
- click_button 'Cherry-pick'
- end
- expect(page).to have_content('The commit has been successfully cherry-picked into master.')
- end
- end
+ context 'when clicking cherry-pick from the dropdown for a commit on pipelines tab' do
+ it 'launches the modal form' do
+ create(:ci_empty_pipeline, sha: sha)
+ visit project_commit_path(project, master_pickable_commit.id)
+ click_link 'Pipelines'
- context "I cherry-pick a merge commit" do
- it do
- find("a[href='#modal-cherry-pick-commit']").click
- page.within('#modal-cherry-pick-commit') do
- uncheck 'create_merge_request'
- click_button 'Cherry-pick'
+ open_modal
+
+ page.within(modal_selector) do
+ expect(page).to have_content('Cherry-pick this commit')
end
- expect(page).to have_content('The commit has been successfully cherry-picked into master.')
end
end
- context "I cherry-pick a commit that was previously cherry-picked" do
- it do
- find("a[href='#modal-cherry-pick-commit']").click
- page.within('#modal-cherry-pick-commit') do
- uncheck 'create_merge_request'
- click_button 'Cherry-pick'
- end
+ context 'when starting from the commit tab' do
+ before do
visit project_commit_path(project, master_pickable_commit.id)
- find("a[href='#modal-cherry-pick-commit']").click
- page.within('#modal-cherry-pick-commit') do
- uncheck 'create_merge_request'
- click_button 'Cherry-pick'
- end
- expect(page).to have_content('Sorry, we cannot cherry-pick this commit automatically.')
end
- end
- context "I cherry-pick a commit in a new merge request", :js do
- it do
- find('.header-action-buttons a.dropdown-toggle').click
- find("a[href='#modal-cherry-pick-commit']").click
- page.within('#modal-cherry-pick-commit') do
- click_button 'Cherry-pick'
+ context 'when cherry-picking a commit' do
+ specify do
+ cherry_pick_commit
+
+ expect(page).to have_content('The commit has been successfully cherry-picked into master.')
end
+ end
- wait_for_requests
+ context 'when cherry-picking a merge commit' do
+ specify do
+ cherry_pick_commit
- expect(page).to have_content("The commit has been successfully cherry-picked into cherry-pick-#{master_pickable_commit.short_id}. You can now submit a merge request to get this change into the original branch.")
- expect(page).to have_content("From cherry-pick-#{master_pickable_commit.short_id} into master")
+ expect(page).to have_content('The commit has been successfully cherry-picked into master.')
+ end
end
- end
- context "I cherry-pick a commit from a different branch", :js do
- it do
- find('.header-action-buttons a.dropdown-toggle').click
- find(:css, "a[href='#modal-cherry-pick-commit']").click
+ context 'when cherry-picking a commit that was previously cherry-picked' do
+ specify do
+ cherry_pick_commit
- page.within('#modal-cherry-pick-commit') do
- click_button 'master'
+ visit project_commit_path(project, master_pickable_commit.id)
+
+ cherry_pick_commit
+
+ expect(page).to have_content('Sorry, we cannot cherry-pick this commit automatically.')
end
+ end
- wait_for_requests
+ context 'when cherry-picking a commit in a new merge request' do
+ specify do
+ cherry_pick_commit(create_merge_request: true)
- page.within('#modal-cherry-pick-commit .dropdown-menu') do
- find('.dropdown-input input').set('feature')
- wait_for_requests
- click_link "feature"
+ expect(page).to have_content("The commit has been successfully cherry-picked into cherry-pick-#{master_pickable_commit.short_id}. You can now submit a merge request to get this change into the original branch.")
+ expect(page).to have_content("From cherry-pick-#{master_pickable_commit.short_id} into master")
end
+ end
- page.within('#modal-cherry-pick-commit') do
- uncheck 'create_merge_request'
- click_button 'Cherry-pick'
+ context 'when I cherry-picking a commit from a different branch' do
+ specify do
+ open_modal
+
+ page.within(modal_selector) do
+ click_button 'master'
+ end
+
+ page.within("#{modal_selector} .dropdown-menu") do
+ find('[data-testid="dropdown-search-box"]').set('feature')
+ wait_for_requests
+ click_button 'feature'
+ end
+
+ submit_cherry_pick
+
+ expect(page).to have_content('The commit has been successfully cherry-picked into feature.')
end
+ end
+
+ context 'when the project is archived' do
+ let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
- expect(page).to have_content('The commit has been successfully cherry-picked into feature.')
+ it 'does not show the cherry-pick link' do
+ open_dropdown
+
+ expect(page).not_to have_text("Cherry-pick")
+ end
end
end
- context 'when the project is archived' do
- let(:project) { create(:project, :repository, :archived, namespace: group) }
+ def cherry_pick_commit(create_merge_request: false)
+ open_modal
- it 'does not show the cherry-pick link' do
- find('.header-action-buttons a.dropdown-toggle').click
+ submit_cherry_pick(create_merge_request: create_merge_request)
+ end
+
+ def open_dropdown
+ find('.header-action-buttons .dropdown').click
+ end
- expect(page).not_to have_text("Cherry-pick")
- expect(page).not_to have_css("a[href='#modal-cherry-pick-commit']")
+ def open_modal
+ open_dropdown
+ find('[data-testid="cherry-pick-commit-link"]').click
+ end
+
+ def submit_cherry_pick(create_merge_request: false)
+ page.within(modal_selector) do
+ uncheck('create_merge_request') unless create_merge_request
+ click_button('Cherry-pick')
end
end
+
+ def modal_selector
+ '[data-testid="modal-commit"]'
+ end
end
diff --git a/spec/features/projects/commit/user_reverts_commit_spec.rb b/spec/features/projects/commit/user_reverts_commit_spec.rb
index f3c364dab97..72c639a027e 100644
--- a/spec/features/projects/commit/user_reverts_commit_spec.rb
+++ b/spec/features/projects/commit/user_reverts_commit_spec.rb
@@ -6,58 +6,89 @@ RSpec.describe 'User reverts a commit', :js do
include RepoHelpers
let_it_be(:user) { create(:user) }
- let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let!(:project) { create_default(:project, :repository, namespace: user.namespace) }
before do
sign_in(user)
-
- visit(project_commit_path(project, sample_commit.id))
end
- def revert_commit(create_merge_request: false)
- find('.header-action-buttons .dropdown').click
- find('[data-testid="revert-commit-link"]').click
+ context 'when clicking revert from the dropdown for a commit on pipelines tab' do
+ it 'launches the modal and is able to submit the revert' do
+ sha = '7d3b0f7cff5f37573aea97cebfd5692ea1689924'
+ create(:ci_empty_pipeline, sha: sha)
+ visit project_commit_path(project, project.commit(sha).id)
+ click_link 'Pipelines'
- page.within('[data-testid="modal-commit"]') do
- uncheck('create_merge_request') unless create_merge_request
- click_button('Revert')
+ open_modal
+
+ page.within(modal_selector) do
+ expect(page).to have_content('Revert this commit')
+ end
end
end
- context 'without creating a new merge request' do
- it 'reverts a commit' do
- revert_commit
+ context 'when starting from the commit tab' do
+ before do
+ visit project_commit_path(project, sample_commit.id)
+ end
+
+ context 'without creating a new merge request' do
+ it 'reverts a commit' do
+ revert_commit
+
+ expect(page).to have_content('The commit has been successfully reverted.')
+ end
+
+ it 'does not revert a previously reverted commit' do
+ revert_commit
+ # Visit the comment again once it was reverted.
+ visit project_commit_path(project, sample_commit.id)
+
+ revert_commit
- expect(page).to have_content('The commit has been successfully reverted.')
+ expect(page).to have_content('Sorry, we cannot revert this commit automatically.')
+ end
end
- it 'does not revert a previously reverted commit' do
- revert_commit
- # Visit the comment again once it was reverted.
- visit project_commit_path(project, sample_commit.id)
+ context 'with creating a new merge request' do
+ it 'reverts a commit' do
+ revert_commit(create_merge_request: true)
+
+ expect(page).to have_content('The commit has been successfully reverted. You can now submit a merge request to get this change into the original branch.')
+ expect(page).to have_content("From revert-#{Commit.truncate_sha(sample_commit.id)} into master")
+ end
+ end
- revert_commit
+ context 'when the project is archived' do
+ let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
- expect(page).to have_content('Sorry, we cannot revert this commit automatically.')
+ it 'does not show the revert link' do
+ open_dropdown
+
+ expect(page).not_to have_link('Revert')
+ end
end
end
- context 'with creating a new merge request' do
- it 'reverts a commit' do
- revert_commit(create_merge_request: true)
+ def revert_commit(create_merge_request: false)
+ open_modal
- expect(page).to have_content('The commit has been successfully reverted. You can now submit a merge request to get this change into the original branch.')
- expect(page).to have_content("From revert-#{Commit.truncate_sha(sample_commit.id)} into master")
+ page.within(modal_selector) do
+ uncheck('create_merge_request') unless create_merge_request
+ click_button('Revert')
end
end
- context 'when the project is archived' do
- let(:project) { create(:project, :repository, :archived, namespace: user.namespace) }
+ def open_dropdown
+ find('.header-action-buttons .dropdown').click
+ end
- it 'does not show the revert link' do
- find('.header-action-buttons .dropdown').click
+ def open_modal
+ open_dropdown
+ find('[data-testid="revert-commit-link"]').click
+ end
- expect(page).not_to have_link('Revert')
- end
+ def modal_selector
+ '[data-testid="modal-commit"]'
end
end
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 596b4773716..4894e2b7f3e 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -203,10 +203,11 @@ RSpec.describe 'User browses commits' do
context 'when click the compare tab' do
before do
+ wait_for_requests
click_link('Compare')
end
- it 'does not render create merge request button' do
+ it 'does not render create merge request button', :js do
expect(page).not_to have_link 'Create merge request'
end
end
@@ -236,10 +237,11 @@ RSpec.describe 'User browses commits' do
context 'when click the compare tab' do
before do
+ wait_for_requests
click_link('Compare')
end
- it 'renders create merge request button' do
+ it 'renders create merge request button', :js do
expect(page).to have_link 'Create merge request'
end
end
@@ -276,10 +278,11 @@ RSpec.describe 'User browses commits' do
context 'when click the compare tab' do
before do
+ wait_for_requests
click_link('Compare')
end
- it 'renders button to the merge request' do
+ it 'renders button to the merge request', :js do
expect(page).not_to have_link 'Create merge request'
expect(page).to have_link 'View open merge request', href: project_merge_request_path(project, merge_request)
end
diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb
index e387ea4d473..64e9968061c 100644
--- a/spec/features/projects/compare_spec.rb
+++ b/spec/features/projects/compare_spec.rb
@@ -17,10 +17,10 @@ RSpec.describe "Compare", :js do
visit project_compare_index_path(project, from: 'master', to: 'master')
select_using_dropdown 'from', 'feature'
- expect(find('.js-compare-from-dropdown .dropdown-toggle-text')).to have_content('feature')
+ expect(find('.js-compare-from-dropdown .gl-new-dropdown-button-text')).to have_content('feature')
select_using_dropdown 'to', 'binary-encoding'
- expect(find('.js-compare-to-dropdown .dropdown-toggle-text')).to have_content('binary-encoding')
+ expect(find('.js-compare-to-dropdown .gl-new-dropdown-button-text')).to have_content('binary-encoding')
click_button 'Compare'
@@ -32,8 +32,8 @@ RSpec.describe "Compare", :js do
it "pre-populates fields" do
visit project_compare_index_path(project, from: "master", to: "master")
- expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("master")
- expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("master")
+ expect(find(".js-compare-from-dropdown .gl-new-dropdown-button-text")).to have_content("master")
+ expect(find(".js-compare-to-dropdown .gl-new-dropdown-button-text")).to have_content("master")
end
it_behaves_like 'compares branches'
@@ -99,7 +99,7 @@ RSpec.describe "Compare", :js do
find(".js-compare-from-dropdown .compare-dropdown-toggle").click
- expect(find(".js-compare-from-dropdown .dropdown-content")).to have_selector("li", count: 3)
+ expect(find(".js-compare-from-dropdown .gl-new-dropdown-contents")).to have_selector('li.gl-new-dropdown-item', count: 1)
end
context 'when commit has overflow', :js do
@@ -125,10 +125,10 @@ RSpec.describe "Compare", :js do
visit project_compare_index_path(project, from: "master", to: "master")
select_using_dropdown "from", "v1.0.0"
- expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("v1.0.0")
+ expect(find(".js-compare-from-dropdown .gl-new-dropdown-button-text")).to have_content("v1.0.0")
select_using_dropdown "to", "v1.1.0"
- expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("v1.1.0")
+ expect(find(".js-compare-to-dropdown .gl-new-dropdown-button-text")).to have_content("v1.1.0")
click_button "Compare"
expect(page).to have_content "Commits"
@@ -136,19 +136,22 @@ RSpec.describe "Compare", :js do
end
def select_using_dropdown(dropdown_type, selection, commit: false)
+ wait_for_requests
+
dropdown = find(".js-compare-#{dropdown_type}-dropdown")
dropdown.find(".compare-dropdown-toggle").click
# find input before using to wait for the inputs visibility
dropdown.find('.dropdown-menu')
dropdown.fill_in("Filter by Git revision", with: selection)
+
wait_for_requests
if commit
- dropdown.find('input[type="search"]').send_keys(:return)
+ dropdown.find('.gl-search-box-by-type-input').send_keys(:return)
else
# find before all to wait for the items visibility
- dropdown.find("a[data-ref=\"#{selection}\"]", match: :first)
- dropdown.all("a[data-ref=\"#{selection}\"]").last.click
+ dropdown.find(".js-compare-#{dropdown_type}-dropdown .dropdown-item", text: selection, match: :first)
+ dropdown.all(".js-compare-#{dropdown_type}-dropdown .dropdown-item", text: selection).first.click
end
end
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index 2f0fbd29cb5..c94247f65d2 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -187,7 +187,7 @@ RSpec.describe 'Edit Project Settings' do
click_button "Save changes"
end
- expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 4)
+ expect(find(".sharing-permissions")).to have_selector(".gl-toggle.is-disabled", minimum: 4)
end
it "shows empty features project homepage" do
@@ -282,10 +282,10 @@ RSpec.describe 'Edit Project Settings' do
end
def toggle_feature_off(feature_name)
- find(".project-feature-controls[data-for=\"#{feature_name}\"] .project-feature-toggle.is-checked").click
+ find(".project-feature-controls[data-for=\"#{feature_name}\"] .gl-toggle.is-checked").click
end
def toggle_feature_on(feature_name)
- find(".project-feature-controls[data-for=\"#{feature_name}\"] .project-feature-toggle:not(.is-checked)").click
+ find(".project-feature-controls[data-for=\"#{feature_name}\"] .gl-toggle:not(.is-checked)").click
end
end
diff --git a/spec/features/projects/files/dockerfile_dropdown_spec.rb b/spec/features/projects/files/dockerfile_dropdown_spec.rb
index 17258f7042f..40d19a94b42 100644
--- a/spec/features/projects/files/dockerfile_dropdown_spec.rb
+++ b/spec/features/projects/files/dockerfile_dropdown_spec.rb
@@ -2,14 +2,16 @@
require 'spec_helper'
-RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297400' do
+RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', :js do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
before do
project = create(:project, :repository)
sign_in project.owner
visit project_new_blob_path(project, 'master', file_name: 'Dockerfile')
end
- it 'user can pick a Dockerfile file from the dropdown', :js do
+ it 'user can pick a Dockerfile file from the dropdown' do
expect(page).to have_css('.dockerfile-selector')
find('.js-dockerfile-selector').click
@@ -24,6 +26,6 @@ RSpec.describe 'Projects > Files > User wants to add a Dockerfile file', quarant
wait_for_requests
expect(page).to have_css('.dockerfile-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(page).to have_content('COPY ./ /usr/local/apache2/htdocs/')
+ expect(editor_get_value).to have_content('COPY ./ /usr/local/apache2/htdocs/')
end
end
diff --git a/spec/features/projects/files/gitignore_dropdown_spec.rb b/spec/features/projects/files/gitignore_dropdown_spec.rb
index 5a39f2bcd98..a9f2463ecf6 100644
--- a/spec/features/projects/files/gitignore_dropdown_spec.rb
+++ b/spec/features/projects/files/gitignore_dropdown_spec.rb
@@ -2,14 +2,16 @@
require 'spec_helper'
-RSpec.describe 'Projects > Files > User wants to add a .gitignore file' do
+RSpec.describe 'Projects > Files > User wants to add a .gitignore file', :js do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
before do
project = create(:project, :repository)
sign_in project.owner
visit project_new_blob_path(project, 'master', file_name: '.gitignore')
end
- it 'user can pick a .gitignore file from the dropdown', :js do
+ it 'user can pick a .gitignore file from the dropdown' do
expect(page).to have_css('.gitignore-selector')
find('.js-gitignore-selector').click
@@ -24,7 +26,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitignore file' do
wait_for_requests
expect(page).to have_css('.gitignore-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(page).to have_content('/.bundle')
- expect(page).to have_content('config/initializers/secret_token.rb')
+ expect(editor_get_value).to have_content('/.bundle')
+ expect(editor_get_value).to have_content('config/initializers/secret_token.rb')
end
end
diff --git a/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb
index 6308acb41f5..ca6f03472dd 100644
--- a/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_syntax_yml_dropdown_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
before do
project = create(:project, :repository)
sign_in project.owner
@@ -34,8 +36,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do
let(:experiment_active) { true }
let(:in_experiment_group) { true }
- it 'allows the user to pick a "Learn CI/CD syntax" template from the dropdown', :js,
- { quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297347' } } do
+ it 'allows the user to pick a "Learn CI/CD syntax" template from the dropdown', :js do
expect(page).to have_css('.gitlab-ci-syntax-yml-selector')
find('.js-gitlab-ci-syntax-yml-selector').click
@@ -50,7 +51,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do
wait_for_requests
expect(page).to have_css('.gitlab-ci-syntax-yml-selector .dropdown-toggle-text', text: 'Learn CI/CD syntax')
- expect(page).to have_content('You can use artifacts to pass data to jobs in later stages.')
+ expect(editor_get_value).to have_content('You can use artifacts to pass data to jobs in later stages.')
end
end
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 879cb6a65c8..55b9f38d8e7 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -2,14 +2,16 @@
require 'spec_helper'
-RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do
+RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file', :js do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
before do
project = create(:project, :repository)
sign_in project.owner
visit project_new_blob_path(project, 'master', file_name: '.gitlab-ci.yml')
end
- it 'user can pick a template from the dropdown', :js do
+ it 'user can pick a template from the dropdown' do
expect(page).to have_css('.gitlab-ci-yml-selector')
find('.js-gitlab-ci-yml-selector').click
@@ -24,7 +26,7 @@ RSpec.describe 'Projects > Files > User wants to add a .gitlab-ci.yml file' do
wait_for_requests
expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Apply a template')
- expect(page).to have_content('This file is a template, and might need editing before it works on your project')
- expect(page).to have_content('jekyll build -d test')
+ expect(editor_get_value).to have_content('This file is a template, and might need editing before it works on your project')
+ expect(editor_get_value).to have_content('jekyll build -d test')
end
end
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 1e84d1552a1..8d0500f5e13 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -9,22 +9,45 @@ RSpec.describe 'Project fork' do
let(:project) { create(:project, :public, :repository) }
before do
- sign_in user
+ sign_in(user)
end
- it 'allows user to fork project' do
+ it 'allows user to fork project from the project page' do
visit project_path(project)
- expect(page).not_to have_css('a.disabled', text: 'Select')
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
end
- it 'disables fork button when user has exceeded project limit' do
- user.projects_limit = 0
- user.save!
+ context 'user has exceeded personal project limit' do
+ before do
+ user.update!(projects_limit: 0)
+ end
- visit project_path(project)
+ it 'disables fork button on project page' do
+ visit project_path(project)
+
+ expect(page).to have_css('a.disabled', text: 'Fork')
+ end
+
+ context 'with a group to fork to' do
+ let!(:group) { create(:group).tap { |group| group.add_owner(user) } }
+
+ it 'enables fork button on project page' do
+ visit project_path(project)
+
+ expect(page).not_to have_css('a.disabled', text: 'Fork')
+ end
+
+ it 'allows user to fork only to the group on fork page', :js do
+ visit new_project_fork_path(project)
+
+ to_personal_namespace = find('[data-qa-selector=fork_namespace_button].disabled')
+ to_group = find(".fork-groups button[data-qa-name=#{group.name}]")
- expect(page).to have_css('a.disabled', text: 'Fork')
+ expect(to_personal_namespace).not_to be_nil
+ expect(to_group).not_to be_disabled
+ end
+ end
end
context 'forking enabled / disabled in project settings' do
diff --git a/spec/features/projects/graph_spec.rb b/spec/features/projects/graph_spec.rb
index 7b9f79c9f7f..72df84bf905 100644
--- a/spec/features/projects/graph_spec.rb
+++ b/spec/features/projects/graph_spec.rb
@@ -72,9 +72,9 @@ RSpec.describe 'Project Graph', :js do
it 'renders CI graphs' do
expect(page).to have_content 'Overall'
- expect(page).to have_content 'Pipelines for last week'
- expect(page).to have_content 'Pipelines for last month'
- expect(page).to have_content 'Pipelines for last year'
+ expect(page).to have_content 'Last week'
+ expect(page).to have_content 'Last month'
+ expect(page).to have_content 'Last year'
expect(page).to have_content 'Duration for the last 30 commits'
end
end
diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb
index 8f1c31f229f..12c5820a69d 100644
--- a/spec/features/projects/issuable_templates_spec.rb
+++ b/spec/features/projects/issuable_templates_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe 'issuable templates', :js do
let(:bug_template_content) { 'this is merge request bug template' }
let(:template_override_warning) { 'Applying a template will replace the existing issue description.' }
let(:updated_description) { 'updated merge request description' }
- let(:merge_request) { create(:merge_request, :with_diffs, source_project: project) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
before do
project.repository.create_file(
@@ -154,7 +154,7 @@ RSpec.describe 'issuable templates', :js do
let(:template_content) { 'this is a test "feature-proposal" template' }
let(:fork_user) { create(:user) }
let(:forked_project) { fork_project(project, fork_user, repository: true) }
- let(:merge_request) { create(:merge_request, :with_diffs, source_project: forked_project, target_project: project) }
+ let(:merge_request) { create(:merge_request, source_project: forked_project, target_project: project) }
before do
sign_out(:user)
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 1557a8a2d72..7811394b541 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -27,40 +27,12 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
describe "GET /:project/jobs" do
context 'with no jobs' do
before do
- stub_experiment(jobs_empty_state: experiment_active)
- stub_experiment_for_subject(jobs_empty_state: in_experiment_group)
-
visit project_jobs_path(project)
end
- context 'when experiment not active' do
- let(:experiment_active) { false }
- let(:in_experiment_group) { false }
-
- it 'shows the empty state control page' do
- expect(page).to have_content('No jobs to show')
- expect(page).to have_link('Get started with Pipelines')
- end
- end
-
- context 'when experiment active and user in control group' do
- let(:experiment_active) { true }
- let(:in_experiment_group) { false }
-
- it 'shows the empty state control page' do
- expect(page).to have_content('No jobs to show')
- expect(page).to have_link('Get started with Pipelines')
- end
- end
-
- context 'when experiment active and user in experimental group' do
- let(:experiment_active) { true }
- let(:in_experiment_group) { true }
-
- it 'shows the empty state experiment page' do
- expect(page).to have_content('Use jobs to automate your tasks')
- expect(page).to have_link('Create CI/CD configuration file')
- end
+ it 'shows the empty state page' do
+ expect(page).to have_content('Use jobs to automate your tasks')
+ expect(page).to have_link('Create CI/CD configuration file', href: project.present(current_user: user).add_ci_yml_path)
end
end
@@ -102,7 +74,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
it "shows Finished tab jobs" do
expect(page).to have_selector('.nav-links li.active', text: 'Finished')
- expect(page).to have_content 'No jobs to show'
+ expect(page).to have_content('Use jobs to automate your tasks')
end
end
@@ -533,10 +505,10 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
expect(page).to have_content('Trigger token')
expect(page).to have_content('Trigger variables')
- expect(page).not_to have_css('.js-reveal-variables')
+ expect(page).not_to have_selector('[data-testid="trigger-reveal-values-button"]')
- expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1')
- expect(page).to have_selector('.js-build-value', text: '••••••')
+ expect(page).to have_selector('[data-testid="trigger-build-key"]', text: 'TRIGGER_KEY_1')
+ expect(page).to have_selector('[data-testid="trigger-build-value"]', text: '••••••')
end
end
@@ -571,17 +543,17 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
expect(page).to have_content('Trigger token')
expect(page).to have_content('Trigger variables')
- expect(page).to have_css('.js-reveal-variables')
+ expect(page).to have_selector('[data-testid="trigger-reveal-values-button"]')
- expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1')
- expect(page).to have_selector('.js-build-value', text: '••••••')
+ expect(page).to have_selector('[data-testid="trigger-build-key"]', text: 'TRIGGER_KEY_1')
+ expect(page).to have_selector('[data-testid="trigger-build-value"]', text: '••••••')
end
it 'reveals values on button click', :js do
click_button 'Reveal values'
- expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1')
- expect(page).to have_selector('.js-build-value', text: 'TRIGGER_VALUE_1')
+ expect(page).to have_selector('[data-testid="trigger-build-key"]', text: 'TRIGGER_KEY_1')
+ expect(page).to have_selector('[data-testid="trigger-build-value"]', text: 'TRIGGER_VALUE_1')
end
end
diff --git a/spec/features/projects/members/anonymous_user_sees_members_spec.rb b/spec/features/projects/members/anonymous_user_sees_members_spec.rb
index 3b0f00c5494..d710ecf6c88 100644
--- a/spec/features/projects/members/anonymous_user_sees_members_spec.rb
+++ b/spec/features/projects/members/anonymous_user_sees_members_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Anonymous user sees members' do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create(:user) }
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public) }
@@ -12,11 +14,25 @@ RSpec.describe 'Projects > Members > Anonymous user sees members' do
create(:project_group_link, project: project, group: group)
end
- it "anonymous user visits the project's members page and sees the list of members" do
- visit project_project_members_path(project)
+ context 'when `vue_project_members_list` feature flag is enabled', :js do
+ it "anonymous user visits the project's members page and sees the list of members" do
+ visit project_project_members_path(project)
+
+ expect(find_member_row(user)).to have_content(user.name)
+ end
+ end
+
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+ end
+
+ it "anonymous user visits the project's members page and sees the list of members" do
+ visit project_project_members_path(project)
- expect(current_path).to eq(
- project_project_members_path(project))
- expect(page).to have_content(user.name)
+ expect(current_path).to eq(
+ project_project_members_path(project))
+ expect(page).to have_content(user.name)
+ end
end
end
diff --git a/spec/features/projects/members/group_members_spec.rb b/spec/features/projects/members/group_members_spec.rb
index aa15f04bf24..1abd00421ec 100644
--- a/spec/features/projects/members/group_members_spec.rb
+++ b/spec/features/projects/members/group_members_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Projects members', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:user) { create(:user) }
let(:developer) { create(:user) }
let(:group) { create(:group, :public) }
@@ -18,117 +20,218 @@ RSpec.describe 'Projects members', :js do
sign_in(user)
end
- context 'with a group invitee' do
- before do
- group_invitee
- visit project_project_members_path(project)
- end
+ context 'when `vue_project_members_list` feature flag is enabled' do
+ context 'with a group invitee' do
+ before do
+ group_invitee
+ visit project_project_members_path(project)
+ end
- it 'does not appear in the project members page' do
- page.within first('.content-list') do
- expect(page).not_to have_content('test2@abc.com')
+ it 'does not appear in the project members page' do
+ expect(members_table).not_to have_content('test2@abc.com')
end
end
- end
- context 'with a group' do
- it 'shows group and project members by default' do
- visit project_project_members_path(project)
+ context 'with a group' do
+ it 'shows group and project members by default' do
+ visit project_project_members_path(project)
+
+ expect(members_table).to have_content(developer.name)
+ expect(members_table).to have_content(user.name)
+ expect(members_table).to have_content(group.name)
+ end
+
+ it 'shows project members only if requested' do
+ visit project_project_members_path(project, with_inherited_permissions: 'exclude')
+
+ expect(members_table).to have_content(developer.name)
+ expect(members_table).not_to have_content(user.name)
+ expect(members_table).not_to have_content(group.name)
+ end
- page.within first('.content-list') do
- expect(page).to have_content(developer.name)
+ it 'shows group members only if requested' do
+ visit project_project_members_path(project, with_inherited_permissions: 'only')
- expect(page).to have_content(user.name)
- expect(page).to have_content(group.name)
+ expect(members_table).not_to have_content(developer.name)
+ expect(members_table).to have_content(user.name)
+ expect(members_table).to have_content(group.name)
end
end
- it 'shows project members only if requested' do
- visit project_project_members_path(project, with_inherited_permissions: 'exclude')
+ context 'with a group, a project invitee, and a project requester' do
+ before do
+ group.request_access(group_requester)
+ project.request_access(project_requester)
+ group_invitee
+ project_invitee
+ visit project_project_members_path(project)
+ end
+
+ it 'shows the group owner' do
+ expect(members_table).to have_content(user.name)
+ expect(members_table).to have_content(group.name)
+ end
+
+ it 'shows the project developer' do
+ expect(members_table).to have_content(developer.name)
+ end
+
+ it 'shows the project invitee' do
+ click_link 'Invited'
+
+ expect(members_table).to have_content('test1@abc.com')
+ expect(members_table).not_to have_content('test2@abc.com')
+ end
- page.within first('.content-list') do
- expect(page).to have_content(developer.name)
+ it 'shows the project requester' do
+ click_link 'Access requests'
- expect(page).not_to have_content(user.name)
- expect(page).not_to have_content(group.name)
+ expect(members_table).to have_content(project_requester.name)
+ expect(members_table).not_to have_content(group_requester.name)
end
end
- it 'shows group members only if requested' do
- visit project_project_members_path(project, with_inherited_permissions: 'only')
+ context 'with a group requester' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ group.request_access(group_requester)
+ visit project_project_members_path(project)
+ end
+
+ it 'does not appear in the project members page' do
+ expect(page).not_to have_link('Access requests')
+ expect(members_table).not_to have_content(group_requester.name)
+ end
+ end
+
+ context 'showing status of members' do
+ it 'shows the status' do
+ create(:user_status, user: user, emoji: 'smirk', message: 'Authoring this object')
- page.within first('.content-list') do
- expect(page).not_to have_content(developer.name)
+ visit project_project_members_path(project)
- expect(page).to have_content(user.name)
- expect(page).to have_content(group.name)
+ expect(first_row).to have_selector('gl-emoji[data-name="smirk"]')
end
end
end
- context 'with a group, a project invitee, and a project requester' do
+ context 'when `vue_project_members_list` feature flag is disabled' do
before do
- group.request_access(group_requester)
- project.request_access(project_requester)
- group_invitee
- project_invitee
- visit project_project_members_path(project)
+ stub_feature_flags(vue_project_members_list: false)
end
- it 'shows the group owner' do
- page.within first('.content-list') do
- # Group owner
- expect(page).to have_content(user.name)
- expect(page).to have_content(group.name)
+ context 'with a group invitee' do
+ before do
+ group_invitee
+ visit project_project_members_path(project)
end
- end
- it 'shows the project developer' do
- page.within first('.content-list') do
- # Project developer
- expect(page).to have_content(developer.name)
+ it 'does not appear in the project members page' do
+ page.within first('.content-list') do
+ expect(page).not_to have_content('test2@abc.com')
+ end
end
end
- it 'shows the project invitee' do
- click_link 'Invited'
+ context 'with a group' do
+ it 'shows group and project members by default' do
+ visit project_project_members_path(project)
- page.within first('.content-list') do
- expect(page).to have_content('test1@abc.com')
- expect(page).not_to have_content('test2@abc.com')
+ page.within first('.content-list') do
+ expect(page).to have_content(developer.name)
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content(group.name)
+ end
+ end
+
+ it 'shows project members only if requested' do
+ visit project_project_members_path(project, with_inherited_permissions: 'exclude')
+
+ page.within first('.content-list') do
+ expect(page).to have_content(developer.name)
+
+ expect(page).not_to have_content(user.name)
+ expect(page).not_to have_content(group.name)
+ end
end
- end
- it 'shows the project requester' do
- click_link 'Access requests'
+ it 'shows group members only if requested' do
+ visit project_project_members_path(project, with_inherited_permissions: 'only')
- page.within first('.content-list') do
- expect(page).to have_content(project_requester.name)
- expect(page).not_to have_content(group_requester.name)
+ page.within first('.content-list') do
+ expect(page).not_to have_content(developer.name)
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content(group.name)
+ end
end
end
- end
- context 'with a group requester' do
- before do
- stub_feature_flags(invite_members_group_modal: false)
- group.request_access(group_requester)
- visit project_project_members_path(project)
+ context 'with a group, a project invitee, and a project requester' do
+ before do
+ group.request_access(group_requester)
+ project.request_access(project_requester)
+ group_invitee
+ project_invitee
+ visit project_project_members_path(project)
+ end
+
+ it 'shows the group owner' do
+ page.within first('.content-list') do
+ # Group owner
+ expect(page).to have_content(user.name)
+ expect(page).to have_content(group.name)
+ end
+ end
+
+ it 'shows the project developer' do
+ page.within first('.content-list') do
+ # Project developer
+ expect(page).to have_content(developer.name)
+ end
+ end
+
+ it 'shows the project invitee' do
+ click_link 'Invited'
+
+ page.within first('.content-list') do
+ expect(page).to have_content('test1@abc.com')
+ expect(page).not_to have_content('test2@abc.com')
+ end
+ end
+
+ it 'shows the project requester' do
+ click_link 'Access requests'
+
+ page.within first('.content-list') do
+ expect(page).to have_content(project_requester.name)
+ expect(page).not_to have_content(group_requester.name)
+ end
+ end
end
- it 'does not appear in the project members page' do
- expect(page).not_to have_link('Access requests')
- page.within first('.content-list') do
- expect(page).not_to have_content(group_requester.name)
+ context 'with a group requester' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ group.request_access(group_requester)
+ visit project_project_members_path(project)
+ end
+
+ it 'does not appear in the project members page' do
+ expect(page).not_to have_link('Access requests')
+ page.within first('.content-list') do
+ expect(page).not_to have_content(group_requester.name)
+ end
end
end
- end
- describe 'showing status of members' do
- it_behaves_like 'showing user status' do
- let(:user_with_status) { developer }
+ context 'showing status of members' do
+ it_behaves_like 'showing user status' do
+ let(:user_with_status) { developer }
- subject { visit project_project_members_path(project) }
+ subject { visit project_project_members_path(project) }
+ end
end
end
end
diff --git a/spec/features/projects/members/groups_with_access_list_spec.rb b/spec/features/projects/members/groups_with_access_list_spec.rb
index 686d86b1783..9d087dfd5f6 100644
--- a/spec/features/projects/members/groups_with_access_list_spec.rb
+++ b/spec/features/projects/members/groups_with_access_list_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Groups with access list', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public) }
@@ -15,86 +17,172 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
project.add_maintainer(user)
sign_in(user)
- visit project_project_members_path(project)
- click_groups_tab
end
- it 'updates group access level' do
- click_button group_link.human_access
-
- page.within '.dropdown-menu' do
- click_link 'Guest'
+ context 'when `vue_project_members_list` feature flag is enabled' do
+ before do
+ visit project_project_members_path(project)
+ click_groups_tab
end
- wait_for_requests
+ it 'updates group access level' do
+ click_button group_link.human_access
+ click_button 'Guest'
- visit project_project_members_path(project)
+ wait_for_requests
- click_groups_tab
+ visit project_project_members_path(project)
- expect(first('.group_member')).to have_content('Guest')
- end
+ click_groups_tab
+
+ expect(find_group_row(group)).to have_content('Guest')
+ end
- it 'updates expiry date' do
- expires_at_field = "member_expires_at_#{group.id}"
- fill_in expires_at_field, with: 3.days.from_now.to_date
+ it 'updates expiry date' do
+ page.within find_group_row(group) do
+ fill_in 'Expiration date', with: 5.days.from_now.to_date
+ find_field('Expiration date').native.send_keys :enter
- find_field(expires_at_field).native.send_keys :enter
- wait_for_requests
+ wait_for_requests
- page.within(find('li.group_member')) do
- expect(page).to have_content('Expires in 3 days')
+ expect(page).to have_content(/in \d days/)
+ end
end
- end
- context 'when link has expiry date set' do
- let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } }
+ context 'when link has expiry date set' do
+ let(:additional_link_attrs) { { expires_at: 5.days.from_now.to_date } }
- it 'clears expiry date' do
- page.within(find('li.group_member')) do
- expect(page).to have_content('Expires in 3 days')
+ it 'clears expiry date' do
+ page.within find_group_row(group) do
+ expect(page).to have_content(/in \d days/)
- page.within(find('.js-edit-member-form')) do
- find('.js-clear-input').click
+ find('[data-testid="clear-button"]').click
+
+ wait_for_requests
+
+ expect(page).to have_content('No expiration set')
end
+ end
+ end
- wait_for_requests
+ it 'deletes group link' do
+ expect(page).to have_content(group.full_name)
+
+ page.within find_group_row(group) do
+ click_button 'Remove group'
+ end
- expect(page).not_to have_content('Expires in')
+ page.within('[role="dialog"]') do
+ click_button('Remove group')
+ end
+
+ expect(page).not_to have_content(group.full_name)
+ end
+
+ context 'search in existing members' do
+ it 'finds no results' do
+ fill_in_filtered_search 'Search groups', with: 'testing 123'
+
+ click_groups_tab
+
+ expect(page).not_to have_content(group.full_name)
+ end
+
+ it 'finds results' do
+ fill_in_filtered_search 'Search groups', with: group.full_name
+
+ click_groups_tab
+
+ expect(members_table).to have_content(group.full_name)
end
end
end
- it 'deletes group link' do
- page.within(first('.group_member')) do
- accept_confirm { find('.btn-danger').click }
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+
+ visit project_project_members_path(project)
+ click_groups_tab
end
- wait_for_requests
- expect(page).not_to have_selector('.group_member')
- end
+ it 'updates group access level' do
+ click_button group_link.human_access
- context 'search in existing members' do
- it 'finds no results' do
- page.within '.user-search-form' do
- fill_in 'search_groups', with: 'testing 123'
- find('.user-search-btn').click
+ page.within '.dropdown-menu' do
+ click_link 'Guest'
end
+ wait_for_requests
+
+ visit project_project_members_path(project)
+
click_groups_tab
+ expect(first('.group_member')).to have_content('Guest')
+ end
+
+ it 'updates expiry date' do
+ expires_at_field = "member_expires_at_#{group.id}"
+ fill_in expires_at_field, with: 3.days.from_now.to_date
+
+ find_field(expires_at_field).native.send_keys :enter
+ wait_for_requests
+
+ page.within(find('li.group_member')) do
+ expect(page).to have_content('Expires in 3 days')
+ end
+ end
+
+ context 'when link has expiry date set' do
+ let(:additional_link_attrs) { { expires_at: 3.days.from_now.to_date } }
+
+ it 'clears expiry date' do
+ page.within(find('li.group_member')) do
+ expect(page).to have_content('Expires in 3 days')
+
+ page.within(find('.js-edit-member-form')) do
+ find('.js-clear-input').click
+ end
+
+ wait_for_requests
+
+ expect(page).not_to have_content('Expires in')
+ end
+ end
+ end
+
+ it 'deletes group link' do
+ page.within(first('.group_member')) do
+ accept_confirm { find('.btn-danger').click }
+ end
+ wait_for_requests
+
expect(page).not_to have_selector('.group_member')
end
- it 'finds results' do
- page.within '.user-search-form' do
- fill_in 'search_groups', with: group.name
- find('.user-search-btn').click
+ context 'search in existing members' do
+ it 'finds no results' do
+ page.within '.user-search-form' do
+ fill_in 'search_groups', with: 'testing 123'
+ find('.user-search-btn').click
+ end
+
+ click_groups_tab
+
+ expect(page).not_to have_selector('.group_member')
end
- click_groups_tab
+ it 'finds results' do
+ page.within '.user-search-form' do
+ fill_in 'search_groups', with: group.name
+ find('.user-search-btn').click
+ end
+
+ click_groups_tab
- expect(page).to have_selector('.group_member', count: 1)
+ expect(page).to have_selector('.group_member', count: 1)
+ end
end
end
diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb
index bb56ae348fb..f0d115fef1d 100644
--- a/spec/features/projects/members/invite_group_spec.rb
+++ b/spec/features/projects/members/invite_group_spec.rb
@@ -5,9 +5,14 @@ require 'spec_helper'
RSpec.describe 'Project > Members > Invite group', :js do
include Select2Helper
include ActionView::Helpers::DateHelper
+ include Spec::Support::Helpers::Features::MembersHelpers
let(:maintainer) { create(:user) }
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
describe 'Share with group lock' do
shared_examples 'the project can be shared with groups' do
it 'the "Invite group" tab exists' do
@@ -36,21 +41,45 @@ RSpec.describe 'Project > Members > Invite group', :js do
context 'when the group has "Share with group lock" disabled' do
it_behaves_like 'the project can be shared with groups'
- it 'the project can be shared with another group' do
- visit project_project_members_path(project)
+ context 'when `vue_project_members_list` feature flag is enabled' do
+ it 'the project can be shared with another group' do
+ visit project_project_members_path(project)
- expect(page).not_to have_link 'Groups'
+ expect(page).not_to have_link 'Groups'
- click_on 'invite-group-tab'
+ click_on 'invite-group-tab'
- select2 group_to_share_with.id, from: '#link_group_id'
- page.find('body').click
- find('.btn-success').click
+ select2 group_to_share_with.id, from: '#link_group_id'
+ page.find('body').click
+ find('.btn-success').click
- click_link 'Groups'
+ click_link 'Groups'
- page.within('[data-testid="project-member-groups"]') do
- expect(page).to have_content(group_to_share_with.name)
+ expect(members_table).to have_content(group_to_share_with.name)
+ end
+ end
+
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+ end
+
+ it 'the project can be shared with another group' do
+ visit project_project_members_path(project)
+
+ expect(page).not_to have_link 'Groups'
+
+ click_on 'invite-group-tab'
+
+ select2 group_to_share_with.id, from: '#link_group_id'
+ page.find('body').click
+ find('.btn-success').click
+
+ click_link 'Groups'
+
+ page.within('[data-testid="project-member-groups"]') do
+ expect(page).to have_content(group_to_share_with.name)
+ end
end
end
end
@@ -117,7 +146,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
freeze_time { example.run }
end
- before do
+ def setup
project.add_maintainer(maintainer)
group.add_guest(maintainer)
sign_in(maintainer)
@@ -128,20 +157,37 @@ RSpec.describe 'Project > Members > Invite group', :js do
select2 group.id, from: '#link_group_id'
- fill_in 'expires_at_groups', with: (Time.now + 4.5.days).strftime('%Y-%m-%d')
+ fill_in 'expires_at_groups', with: 5.days.from_now.strftime('%Y-%m-%d')
click_on 'invite-group-tab'
find('.btn-success').click
end
- it 'the group link shows the expiration time with a warning class' do
- click_link 'Groups'
+ context 'when `vue_project_members_list` feature flag is enabled' do
+ it 'the group link shows the expiration time with a warning class' do
+ setup
+ click_link 'Groups'
+
+ expect(find_group_row(group)).to have_content(/in \d days/)
+ expect(find_group_row(group)).to have_selector('.gl-text-orange-500')
+ end
+ end
+
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+ end
- page.within('[data-testid="project-member-groups"]') do
- # Using distance_of_time_in_words_to_now because it is not the same as
- # subtraction, and this way avoids time zone issues as well
- expires_in_text = distance_of_time_in_words_to_now(project.project_group_links.first.expires_at)
- expect(page).to have_content(expires_in_text)
- expect(page).to have_selector('.text-warning')
+ it 'the group link shows the expiration time with a warning class' do
+ setup
+ click_link 'Groups'
+
+ page.within('[data-testid="project-member-groups"]') do
+ # Using distance_of_time_in_words_to_now because it is not the same as
+ # subtraction, and this way avoids time zone issues as well
+ expires_in_text = distance_of_time_in_words_to_now(project.project_group_links.first.expires_at)
+ expect(page).to have_content(expires_in_text)
+ expect(page).to have_selector('.text-warning')
+ end
end
end
end
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 62115f2dce6..b0fe5b9c48a 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe 'Project members list' do
include Select2Helper
- include Spec::Support::Helpers::Features::ListRowsHelpers
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
@@ -13,102 +12,215 @@ RSpec.describe 'Project members list' do
before do
stub_feature_flags(invite_members_group_modal: false)
+
sign_in(user1)
group.add_owner(user1)
end
- it 'show members from project and group' do
- project.add_developer(user2)
+ context 'when `vue_project_members_list` feature flag is enabled', :js do
+ include Spec::Support::Helpers::Features::MembersHelpers
- visit_members_page
+ it 'pushes `vue_project_members_list` feature flag to the frontend' do
+ visit_members_page
- expect(first_row.text).to include(user1.name)
- expect(second_row.text).to include(user2.name)
- end
+ expect(page).to have_pushed_frontend_feature_flags(vueProjectMembersList: true)
+ end
- it 'show user once if member of both group and project' do
- project.add_developer(user1)
+ it 'show members from project and group' do
+ project.add_developer(user2)
- visit_members_page
+ visit_members_page
- expect(first_row.text).to include(user1.name)
- expect(second_row).to be_blank
- end
+ expect(first_row).to have_content(user1.name)
+ expect(second_row).to have_content(user2.name)
+ end
+
+ it 'show user once if member of both group and project' do
+ project.add_developer(user1)
- it 'update user access level', :js do
- project.add_developer(user2)
+ visit_members_page
+
+ expect(first_row).to have_content(user1.name)
+ expect(second_row).to be_blank
+ end
+
+ it 'update user access level', :js do
+ project.add_developer(user2)
- visit_members_page
+ visit_members_page
- page.within(second_row) do
- click_button('Developer')
- click_link('Reporter')
+ page.within find_member_row(user2) do
+ click_button('Developer')
+ click_button('Reporter')
- expect(page).to have_button('Reporter')
+ expect(page).to have_button('Reporter')
+ end
end
- end
- it 'add user to project', :js do
- visit_members_page
+ it 'add user to project', :js do
+ visit_members_page
- add_user(user2.id, 'Reporter')
+ add_user(user2.id, 'Reporter')
- page.within(second_row) do
- expect(page).to have_content(user2.name)
- expect(page).to have_button('Reporter')
+ page.within find_member_row(user2) do
+ expect(page).to have_button('Reporter')
+ end
end
- end
- it 'remove user from project', :js do
- other_user = create(:user)
- project.add_developer(other_user)
+ it 'remove user from project', :js do
+ other_user = create(:user)
+ project.add_developer(other_user)
- visit_members_page
+ visit_members_page
- # Open modal
- find(:css, 'li.project_member', text: other_user.name).find(:css, 'button.btn-danger').click
+ # Open modal
+ page.within find_member_row(other_user) do
+ click_button 'Remove member'
+ end
- expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ page.within('[role="dialog"]') do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
- click_on('Remove member')
+ wait_for_requests
- wait_for_requests
+ expect(members_table).not_to have_content(other_user.name)
+ end
- expect(page).not_to have_content(other_user.name)
- expect(project.users).not_to include(other_user)
- end
+ it 'invite user to project', :js do
+ visit_members_page
+
+ add_user('test@example.com', 'Reporter')
+
+ click_link 'Invited'
+
+ page.within find_invited_member_row('test@example.com') do
+ expect(page).to have_button('Reporter')
+ end
+ end
- it 'invite user to project', :js do
- visit_members_page
+ context 'project bots' do
+ let(:project_bot) { create(:user, :project_bot, name: 'project_bot') }
- add_user('test@example.com', 'Reporter')
+ before do
+ project.add_maintainer(project_bot)
+ end
- click_link 'Invited'
+ it 'does not show form used to change roles and "Expiration date" or the remove user button' do
+ visit_members_page
- page.within(first_row) do
- expect(page).to have_content('test@example.com')
- expect(page).to have_content('Invited')
- expect(page).to have_button('Reporter')
+ page.within find_member_row(project_bot) do
+ expect(page).not_to have_button('Maintainer')
+ expect(page).to have_field('Expiration date', disabled: true)
+ expect(page).not_to have_button('Remove member')
+ end
+ end
end
end
- context 'project bots' do
- let(:project_bot) { create(:user, :project_bot, name: 'project_bot') }
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ include Spec::Support::Helpers::Features::ListRowsHelpers
before do
- project.add_maintainer(project_bot)
+ stub_feature_flags(vue_project_members_list: false)
+ end
+
+ it 'show members from project and group' do
+ project.add_developer(user2)
+
+ visit_members_page
+
+ expect(first_row.text).to include(user1.name)
+ expect(second_row.text).to include(user2.name)
+ end
+
+ it 'show user once if member of both group and project' do
+ project.add_developer(user1)
+
+ visit_members_page
+
+ expect(first_row.text).to include(user1.name)
+ expect(second_row).to be_blank
end
- it 'does not show form used to change roles and "Expiration date" or the remove user button' do
- project_member = project.project_members.find_by(user_id: project_bot.id)
+ it 'update user access level', :js do
+ project.add_developer(user2)
+
+ visit_members_page
+
+ page.within(second_row) do
+ click_button('Developer')
+ click_link('Reporter')
+
+ expect(page).to have_button('Reporter')
+ end
+ end
+ it 'add user to project', :js do
visit_members_page
- expect(page).not_to have_selector("#edit_project_member_#{project_member.id}")
- expect(page).to have_no_selector("#project_member_#{project_member.id} .btn-danger")
+ add_user(user2.id, 'Reporter')
+
+ page.within(second_row) do
+ expect(page).to have_content(user2.name)
+ expect(page).to have_button('Reporter')
+ end
+ end
+
+ it 'remove user from project', :js do
+ other_user = create(:user)
+ project.add_developer(other_user)
+
+ visit_members_page
+
+ # Open modal
+ find(:css, 'li.project_member', text: other_user.name).find(:css, 'button.btn-danger').click
+
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+
+ click_on('Remove member')
+
+ wait_for_requests
+
+ expect(page).not_to have_content(other_user.name)
+ expect(project.users).not_to include(other_user)
+ end
+
+ it 'invite user to project', :js do
+ visit_members_page
+
+ add_user('test@example.com', 'Reporter')
+
+ click_link 'Invited'
+
+ page.within(first_row) do
+ expect(page).to have_content('test@example.com')
+ expect(page).to have_content('Invited')
+ expect(page).to have_button('Reporter')
+ end
+ end
+
+ context 'project bots' do
+ let(:project_bot) { create(:user, :project_bot, name: 'project_bot') }
+
+ before do
+ project.add_maintainer(project_bot)
+ end
+
+ it 'does not show form used to change roles and "Expiration date" or the remove user button' do
+ project_member = project.project_members.find_by(user_id: project_bot.id)
+
+ visit_members_page
+
+ expect(page).not_to have_selector("#edit_project_member_#{project_member.id}")
+ expect(page).to have_no_selector("#project_member_#{project_member.id} .btn-danger")
+ end
end
end
+ private
+
def add_user(id, role)
page.within ".invite-users-form" do
select2(id, from: "#user_ids", multiple: true)
diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
index d69c3f2652c..1127c64e0c7 100644
--- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
+++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Members > Maintainer adds member with expiration date', :js do
include Select2Helper
include ActiveSupport::Testing::TimeHelpers
+ include Spec::Support::Helpers::Features::MembersHelpers
let_it_be(:maintainer) { create(:user) }
let_it_be(:project) { create(:project) }
@@ -17,49 +18,107 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
sign_in(maintainer)
end
- it 'expiration date is displayed in the members list' do
- visit project_project_members_path(project)
+ context 'when `vue_project_members_list` feature flag is enabled' do
+ it 'expiration date is displayed in the members list' do
+ stub_feature_flags(invite_members_group_modal: false)
- page.within '.invite-users-form' do
- select2(new_member.id, from: '#user_ids', multiple: true)
+ visit project_project_members_path(project)
- fill_in 'expires_at', with: 3.days.from_now.to_date
- find_field('expires_at').native.send_keys :enter
+ page.within '.invite-users-form' do
+ select2(new_member.id, from: '#user_ids', multiple: true)
- click_on 'Invite'
+ fill_in 'expires_at', with: 5.days.from_now.to_date
+ find_field('expires_at').native.send_keys :enter
+
+ click_on 'Invite'
+ end
+
+ page.within find_member_row(new_member) do
+ expect(page).to have_content(/in \d days/)
+ end
end
- page.within "#project_member_#{project_member_id}" do
- expect(page).to have_content('Expires in 3 days')
+ it 'changes expiration date' do
+ project.team.add_users([new_member.id], :developer, expires_at: 3.days.from_now.to_date)
+ visit project_project_members_path(project)
+
+ page.within find_member_row(new_member) do
+ fill_in 'Expiration date', with: 5.days.from_now.to_date
+ find_field('Expiration date').native.send_keys :enter
+
+ wait_for_requests
+
+ expect(page).to have_content(/in \d days/)
+ end
end
- end
- it 'changes expiration date' do
- project.team.add_users([new_member.id], :developer, expires_at: Date.today.to_date)
- visit project_project_members_path(project)
+ it 'clears expiration date' do
+ project.team.add_users([new_member.id], :developer, expires_at: 5.days.from_now.to_date)
+ visit project_project_members_path(project)
- page.within "#project_member_#{project_member_id}" do
- fill_in 'Expiration date', with: 3.days.from_now.to_date
- find_field('Expiration date').native.send_keys :enter
+ page.within find_member_row(new_member) do
+ expect(page).to have_content(/in \d days/)
- wait_for_requests
+ find('[data-testid="clear-button"]').click
- expect(page).to have_content('Expires in 3 days')
+ wait_for_requests
+
+ expect(page).to have_content('No expiration set')
+ end
end
end
- it 'clears expiration date' do
- project.team.add_users([new_member.id], :developer, expires_at: 3.days.from_now.to_date)
- visit project_project_members_path(project)
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+ end
+
+ it 'expiration date is displayed in the members list' do
+ stub_feature_flags(invite_members_group_modal: false)
+
+ visit project_project_members_path(project)
+
+ page.within '.invite-users-form' do
+ select2(new_member.id, from: '#user_ids', multiple: true)
+
+ fill_in 'expires_at', with: 3.days.from_now.to_date
+ find_field('expires_at').native.send_keys :enter
+
+ click_on 'Invite'
+ end
+
+ page.within "#project_member_#{project_member_id}" do
+ expect(page).to have_content('Expires in 3 days')
+ end
+ end
+
+ it 'changes expiration date' do
+ project.team.add_users([new_member.id], :developer, expires_at: 1.day.from_now.to_date)
+ visit project_project_members_path(project)
+
+ page.within "#project_member_#{project_member_id}" do
+ fill_in 'Expiration date', with: 3.days.from_now.to_date
+ find_field('Expiration date').native.send_keys :enter
+
+ wait_for_requests
+
+ expect(page).to have_content('Expires in 3 days')
+ end
+ end
+
+ it 'clears expiration date' do
+ project.team.add_users([new_member.id], :developer, expires_at: 3.days.from_now.to_date)
+ visit project_project_members_path(project)
- page.within "#project_member_#{project_member_id}" do
- expect(page).to have_content('Expires in 3 days')
+ page.within "#project_member_#{project_member_id}" do
+ expect(page).to have_content('Expires in 3 days')
- find('.js-clear-input').click
+ find('.js-clear-input').click
- wait_for_requests
+ wait_for_requests
- expect(page).not_to have_content('Expires in')
+ expect(page).not_to have_content('Expires in')
+ end
end
end
diff --git a/spec/features/projects/members/sorting_spec.rb b/spec/features/projects/members/sorting_spec.rb
index be27cbc0d66..3c132747bc4 100644
--- a/spec/features/projects/members/sorting_spec.rb
+++ b/spec/features/projects/members/sorting_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Sorting' do
+ include Spec::Support::Helpers::Features::MembersHelpers
+
let(:maintainer) { create(:user, name: 'John Doe') }
let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) }
let(:project) { create(:project, namespace: maintainer.namespace, creator: maintainer) }
@@ -13,78 +15,169 @@ RSpec.describe 'Projects > Members > Sorting' do
sign_in(maintainer)
end
- it 'sorts alphabetically by default' do
- visit_members_list(sort: nil)
+ context 'when `vue_project_members_list` feature flag is enabled', :js do
+ it 'sorts by account by default' do
+ visit_members_list(sort: nil)
- expect(first_member).to include(maintainer.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
- end
+ expect(first_row).to have_content(maintainer.name)
+ expect(second_row).to have_content(developer.name)
- it 'sorts by access level ascending' do
- visit_members_list(sort: :access_level_asc)
+ expect_sort_by('Account', :asc)
+ end
- expect(first_member).to include(developer.name)
- expect(second_member).to include(maintainer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, ascending')
- end
+ it 'sorts by max role ascending' do
+ visit_members_list(sort: :access_level_asc)
- it 'sorts by access level descending' do
- visit_members_list(sort: :access_level_desc)
+ expect(first_row).to have_content(developer.name)
+ expect(second_row).to have_content(maintainer.name)
- expect(first_member).to include(maintainer.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, descending')
- end
+ expect_sort_by('Max role', :asc)
+ end
- it 'sorts by last joined' do
- visit_members_list(sort: :last_joined)
+ it 'sorts by max role descending' do
+ visit_members_list(sort: :access_level_desc)
- expect(first_member).to include(maintainer.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Last joined')
- end
+ expect(first_row).to have_content(maintainer.name)
+ expect(second_row).to have_content(developer.name)
- it 'sorts by oldest joined' do
- visit_members_list(sort: :oldest_joined)
+ expect_sort_by('Max role', :desc)
+ end
- expect(first_member).to include(developer.name)
- expect(second_member).to include(maintainer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest joined')
- end
+ it 'sorts by access granted ascending' do
+ visit_members_list(sort: :last_joined)
- it 'sorts by name ascending' do
- visit_members_list(sort: :name_asc)
+ expect(first_row).to have_content(maintainer.name)
+ expect(second_row).to have_content(developer.name)
- expect(first_member).to include(maintainer.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
- end
+ expect_sort_by('Access granted', :asc)
+ end
- it 'sorts by name descending' do
- visit_members_list(sort: :name_desc)
+ it 'sorts by access granted descending' do
+ visit_members_list(sort: :oldest_joined)
- expect(first_member).to include(developer.name)
- expect(second_member).to include(maintainer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
- end
+ expect(first_row).to have_content(developer.name)
+ expect(second_row).to have_content(maintainer.name)
+
+ expect_sort_by('Access granted', :desc)
+ end
+
+ it 'sorts by account ascending' do
+ visit_members_list(sort: :name_asc)
- it 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
- visit_members_list(sort: :recent_sign_in)
+ expect(first_row).to have_content(maintainer.name)
+ expect(second_row).to have_content(developer.name)
- expect(first_member).to include(maintainer.name)
- expect(second_member).to include(developer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
+ expect_sort_by('Account', :asc)
+ end
+
+ it 'sorts by account descending' do
+ visit_members_list(sort: :name_desc)
+
+ expect(first_row).to have_content(developer.name)
+ expect(second_row).to have_content(maintainer.name)
+
+ expect_sort_by('Account', :desc)
+ end
+
+ it 'sorts by last sign-in ascending', :clean_gitlab_redis_shared_state do
+ visit_members_list(sort: :recent_sign_in)
+
+ expect(first_row).to have_content(maintainer.name)
+ expect(second_row).to have_content(developer.name)
+
+ expect_sort_by('Last sign-in', :asc)
+ end
+
+ it 'sorts by last sign-in descending', :clean_gitlab_redis_shared_state do
+ visit_members_list(sort: :oldest_sign_in)
+
+ expect(first_row).to have_content(developer.name)
+ expect(second_row).to have_content(maintainer.name)
+
+ expect_sort_by('Last sign-in', :desc)
+ end
end
- it 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
- visit_members_list(sort: :oldest_sign_in)
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+ end
+
+ it 'sorts alphabetically by default' do
+ visit_members_list(sort: nil)
- expect(first_member).to include(developer.name)
- expect(second_member).to include(maintainer.name)
- expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest sign in')
+ expect(first_member).to include(maintainer.name)
+ expect(second_member).to include(developer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
+ end
+
+ it 'sorts by access level ascending' do
+ visit_members_list(sort: :access_level_asc)
+
+ expect(first_member).to include(developer.name)
+ expect(second_member).to include(maintainer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, ascending')
+ end
+
+ it 'sorts by access level descending' do
+ visit_members_list(sort: :access_level_desc)
+
+ expect(first_member).to include(maintainer.name)
+ expect(second_member).to include(developer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Access level, descending')
+ end
+
+ it 'sorts by last joined' do
+ visit_members_list(sort: :last_joined)
+
+ expect(first_member).to include(maintainer.name)
+ expect(second_member).to include(developer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Last joined')
+ end
+
+ it 'sorts by oldest joined' do
+ visit_members_list(sort: :oldest_joined)
+
+ expect(first_member).to include(developer.name)
+ expect(second_member).to include(maintainer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest joined')
+ end
+
+ it 'sorts by name ascending' do
+ visit_members_list(sort: :name_asc)
+
+ expect(first_member).to include(maintainer.name)
+ expect(second_member).to include(developer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, ascending')
+ end
+
+ it 'sorts by name descending' do
+ visit_members_list(sort: :name_desc)
+
+ expect(first_member).to include(developer.name)
+ expect(second_member).to include(maintainer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
+ end
+
+ it 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
+ visit_members_list(sort: :recent_sign_in)
+
+ expect(first_member).to include(maintainer.name)
+ expect(second_member).to include(developer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
+ end
+
+ it 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
+ visit_members_list(sort: :oldest_sign_in)
+
+ expect(first_member).to include(developer.name)
+ expect(second_member).to include(maintainer.name)
+ expect(page).to have_css('.qa-user-sort-dropdown .dropdown-toggle-text', text: 'Oldest sign in')
+ end
end
+ private
+
def visit_members_list(sort:)
visit project_project_members_path(project, sort: sort)
end
@@ -96,4 +189,11 @@ RSpec.describe 'Projects > Members > Sorting' do
def second_member
page.all('ul.content-list > li').last.text
end
+
+ def expect_sort_by(text, sort_direction)
+ within('[data-testid="members-sort-dropdown"]') do
+ expect(page).to have_css('button[aria-haspopup="true"]', text: text)
+ expect(page).to have_button("Sorting Direction: #{sort_direction == :asc ? 'Ascending' : 'Descending'}")
+ end
+ end
end
diff --git a/spec/features/projects/members/tabs_spec.rb b/spec/features/projects/members/tabs_spec.rb
index bdcf02c82a4..eef3395de91 100644
--- a/spec/features/projects/members/tabs_spec.rb
+++ b/spec/features/projects/members/tabs_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Members > Tabs' do
+ include Spec::Support::Helpers::Features::MembersHelpers
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
@@ -19,55 +20,93 @@ RSpec.describe 'Projects > Members > Tabs' do
end
end
- before do
- allow(Kaminari.config).to receive(:default_per_page).and_return(1)
-
- sign_in(user)
- visit project_project_members_path(project)
- end
+ context 'tabs' do
+ before do
+ sign_in(user)
+ visit project_project_members_path(project)
+ end
- where(:tab, :count) do
- 'Members' | 3
- 'Invited' | 2
- 'Groups' | 2
- 'Access requests' | 2
- end
+ where(:tab, :count) do
+ 'Members' | 3
+ 'Invited' | 2
+ 'Groups' | 2
+ 'Access requests' | 2
+ end
- with_them do
- it "renders #{params[:tab]} tab" do
- expect(page).to have_selector('.nav-link', text: "#{tab} #{count}")
+ with_them do
+ it "renders #{params[:tab]} tab" do
+ expect(page).to have_selector('.nav-link', text: "#{tab} #{count}")
+ end
end
- end
- context 'displays "Members" tab by default' do
- it_behaves_like 'active "Members" tab'
+ context 'displays "Members" tab by default' do
+ it_behaves_like 'active "Members" tab'
+ end
end
- context 'when searching "Groups"', :js do
+ context 'when `vue_project_members_list` feature flag is enabled' do
before do
- click_link 'Groups'
+ sign_in(user)
+ visit project_project_members_path(project)
+ end
+
+ context 'when searching "Groups"', :js do
+ before do
+ click_link 'Groups'
+
+ fill_in_filtered_search 'Search groups', with: 'group'
+ end
- page.within '[data-testid="group-link-search-form"]' do
- fill_in 'search_groups', with: 'group'
- find('button[type="submit"]').click
+ it 'displays "Groups" tab' do
+ expect(page).to have_selector('.nav-link.active', text: 'Groups')
+ end
+
+ context 'and then searching "Members"' do
+ before do
+ click_link 'Members 3'
+
+ fill_in_filtered_search 'Filter members', with: 'user'
+ end
+
+ it_behaves_like 'active "Members" tab'
end
end
+ end
+
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
- it 'displays "Groups" tab' do
- expect(page).to have_selector('.nav-link.active', text: 'Groups')
+ sign_in(user)
+ visit project_project_members_path(project)
end
- context 'and then searching "Members"' do
+ context 'when searching "Groups"', :js do
before do
- click_link 'Members 3'
+ click_link 'Groups'
- page.within '[data-testid="user-search-form"]' do
- fill_in 'search', with: 'user'
+ page.within '[data-testid="group-link-search-form"]' do
+ fill_in 'search_groups', with: 'group'
find('button[type="submit"]').click
end
end
- it_behaves_like 'active "Members" tab'
+ it 'displays "Groups" tab' do
+ expect(page).to have_selector('.nav-link.active', text: 'Groups')
+ end
+
+ context 'and then searching "Members"' do
+ before do
+ click_link 'Members 3'
+
+ page.within '[data-testid="user-search-form"]' do
+ fill_in 'search', with: 'user'
+ find('button[type="submit"]').click
+ end
+ end
+
+ it_behaves_like 'active "Members" tab'
+ end
end
end
end
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 25791b393bc..4ff3827b240 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -67,23 +67,4 @@ RSpec.describe 'Project navbar' do
it_behaves_like 'verified navigation bar'
end
-
- context 'when invite team members is not available' do
- it 'does not display the js-invite-members-trigger' do
- visit project_path(project)
-
- expect(page).not_to have_selector('.js-invite-members-trigger')
- end
- end
-
- context 'when invite team members is available' do
- it 'includes the div for js-invite-members-trigger' do
- stub_feature_flags(invite_members_group_modal: true)
- allow_any_instance_of(InviteMembersHelper).to receive(:invite_members_allowed?).and_return(true)
-
- visit project_path(project)
-
- expect(page).to have_selector('.js-invite-members-trigger')
- end
- end
end
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
new file mode 100644
index 00000000000..24c9edb79e5
--- /dev/null
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -0,0 +1,185 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'User adds pages domain', :js do
+ include LetsEncryptHelpers
+
+ let_it_be(:project) { create(:project, pages_https_only: false) }
+ let(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+
+ project.add_maintainer(user)
+
+ sign_in(user)
+ end
+
+ context 'when pages are exposed on external HTTP address', :http_pages_enabled do
+ let(:project) { create(:project, pages_https_only: false) }
+
+ shared_examples 'adds new domain' do
+ it 'adds new domain' do
+ visit new_project_pages_domain_path(project)
+
+ fill_in 'Domain', with: 'my.test.domain.com'
+ click_button 'Create New Domain'
+
+ expect(page).to have_content('my.test.domain.com')
+ end
+ end
+
+ it 'allows to add new domain' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('New Domain')
+ end
+
+ it_behaves_like 'adds new domain'
+
+ context 'when project in group namespace' do
+ it_behaves_like 'adds new domain' do
+ let(:group) { create :group }
+ let(:project) { create(:project, namespace: group, pages_https_only: false) }
+ end
+ end
+
+ context 'when pages domain is added' do
+ before do
+ create(:pages_domain, project: project, domain: 'my.test.domain.com')
+
+ visit new_project_pages_domain_path(project)
+ end
+
+ it 'renders certificates is disabled' do
+ expect(page).to have_content('Support for custom certificates is disabled')
+ end
+
+ it 'does not adds new domain and renders error message' do
+ fill_in 'Domain', with: 'my.test.domain.com'
+ click_button 'Create New Domain'
+
+ expect(page).to have_content('Domain has already been taken')
+ end
+ end
+ end
+
+ context 'when pages are exposed on external HTTPS address', :https_pages_enabled, :js do
+ let(:certificate_pem) do
+ attributes_for(:pages_domain)[:certificate]
+ end
+
+ let(:certificate_key) do
+ attributes_for(:pages_domain)[:key]
+ end
+
+ it 'adds new domain with certificate' do
+ visit new_project_pages_domain_path(project)
+
+ fill_in 'Domain', with: 'my.test.domain.com'
+
+ fill_in 'Certificate (PEM)', with: certificate_pem
+ fill_in 'Key (PEM)', with: certificate_key
+ click_button 'Create New Domain'
+
+ expect(page).to have_content('my.test.domain.com')
+ end
+
+ it "adds new domain with certificate if Let's Encrypt is enabled" do
+ stub_lets_encrypt_settings
+
+ visit new_project_pages_domain_path(project)
+
+ fill_in 'Domain', with: 'my.test.domain.com'
+
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+
+ fill_in 'Certificate (PEM)', with: certificate_pem
+ fill_in 'Key (PEM)', with: certificate_key
+ click_button 'Create New Domain'
+
+ expect(page).to have_content('my.test.domain.com')
+ end
+
+ it 'shows validation error if domain is duplicated' do
+ project.pages_domains.create!(domain: 'my.test.domain.com')
+
+ visit new_project_pages_domain_path(project)
+
+ fill_in 'Domain', with: 'my.test.domain.com'
+ click_button 'Create New Domain'
+
+ expect(page).to have_content('Domain has already been taken')
+ end
+
+ describe 'with dns verification enabled' do
+ before do
+ stub_application_setting(pages_domain_verification_enabled: true)
+ end
+
+ it 'shows the DNS verification record' do
+ domain = create(:pages_domain, project: project)
+
+ visit project_pages_path(project)
+
+ within('#content-body') { click_link 'Edit' }
+ expect(page).to have_field :domain_verification, with: "#{domain.verification_domain} TXT #{domain.keyed_verification_code}"
+ end
+ end
+
+ describe 'updating the certificate for an existing domain' do
+ let!(:domain) do
+ create(:pages_domain, project: project, auto_ssl_enabled: false)
+ end
+
+ it 'allows the certificate to be updated' do
+ visit project_pages_path(project)
+
+ within('#content-body') { click_link 'Edit' }
+ click_button 'Save Changes'
+
+ expect(page).to have_content('Domain was updated')
+ end
+
+ context 'when the certificate is invalid' do
+ let!(:domain) do
+ create(:pages_domain, :without_certificate, :without_key, project: project)
+ end
+
+ it 'tells the user what the problem is' do
+ visit project_pages_path(project)
+
+ within('#content-body') { click_link 'Edit' }
+
+ fill_in 'Certificate (PEM)', with: 'invalid data'
+ click_button 'Save Changes'
+
+ expect(page).to have_content('Certificate must be a valid PEM certificate')
+ expect(page).to have_content('Certificate misses intermediates')
+ expect(page).to have_content("Key doesn't match the certificate")
+ end
+ end
+
+ it 'allows the certificate to be removed', :js do
+ visit project_pages_path(project)
+
+ within('#content-body') { click_link 'Edit' }
+
+ accept_confirm { click_link 'Remove' }
+
+ expect(page).to have_field('Certificate (PEM)', with: '')
+ expect(page).to have_field('Key (PEM)', with: '')
+ domain.reload
+ expect(domain.certificate).to be_nil
+ expect(domain.key).to be_nil
+ end
+
+ it 'shows the DNS CNAME record' do
+ visit project_pages_path(project)
+
+ within('#content-body') { click_link 'Edit' }
+ expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}."
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
new file mode 100644
index 00000000000..cf8438d5e6f
--- /dev/null
+++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
+ include LetsEncryptHelpers
+
+ let(:project) { create(:project, pages_https_only: false) }
+ let(:user) { create(:user) }
+ let(:role) { :maintainer }
+ let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
+
+ let(:certificate_key) { attributes_for(:pages_domain)[:key] }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+ stub_lets_encrypt_settings
+
+ project.add_role(user, role)
+ sign_in(user)
+ project.namespace.update!(owner: user)
+ allow_next_instance_of(Project) do |instance|
+ allow(instance).to receive(:pages_deployed?) { true }
+ end
+ end
+
+ it "creates new domain with Let's Encrypt enabled by default" do
+ visit new_project_pages_domain_path(project)
+
+ fill_in 'Domain', with: 'my.test.domain.com'
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ click_button 'Create New Domain'
+
+ expect(page).to have_content('my.test.domain.com')
+ expect(PagesDomain.find_by_domain('my.test.domain.com').auto_ssl_enabled).to eq(true)
+ end
+
+ context 'when the auto SSL management is initially disabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: false, project: project)
+ end
+
+ it 'enables auto SSL and dynamically updates the form accordingly', :js do
+ visit project_pages_domain_path(project, domain)
+
+ expect(domain.auto_ssl_enabled).to eq false
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_selector '.card-header', text: 'Certificate'
+ expect(page).to have_text domain.subject
+
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_selector '.card-header', text: 'Certificate'
+ expect(page).not_to have_text domain.subject
+
+ click_on 'Save Changes'
+
+ expect(domain.reload.auto_ssl_enabled).to eq true
+ end
+ end
+
+ context 'when the auto SSL management is initially enabled' do
+ let(:domain) do
+ create(:pages_domain, :letsencrypt, auto_ssl_enabled: true, project: project)
+ end
+
+ it 'disables auto SSL and dynamically updates the form accordingly', :js do
+ visit project_pages_domain_path(project, domain)
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
+
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
+
+ click_on 'Save Changes'
+
+ expect(domain.reload.auto_ssl_enabled).to eq false
+ end
+ end
+
+ context "when we failed to obtain Let's Encrypt certificate", :js do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: true, auto_ssl_failed: true, project: project)
+ end
+
+ it 'user can retry obtaining certificate' do
+ visit project_pages_domain_path(project, domain)
+
+ expect(page).to have_text("Something went wrong while obtaining the Let's Encrypt certificate.")
+
+ click_on('Retry')
+
+ expect(page).to have_text("GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.")
+ end
+ end
+
+ shared_examples 'user sees private keys only for user provided certificate' do
+ shared_examples 'user do not see private key' do
+ it 'user do not see private key' do
+ visit project_pages_domain_path(project, domain)
+
+ expect(page).not_to have_selector '.card-header', text: 'Certificate'
+ expect(page).not_to have_text domain.subject
+ end
+ end
+
+ context 'when auto_ssl is enabled for domain' do
+ let(:domain) { create(:pages_domain, :letsencrypt, project: project, auto_ssl_enabled: true) }
+
+ include_examples 'user do not see private key'
+ end
+
+ context 'when auto_ssl is disabled for domain' do
+ let(:domain) { create(:pages_domain, :letsencrypt, project: project) }
+
+ include_examples 'user do not see private key'
+ end
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain, project: project, auto_ssl_enabled: false) }
+
+ it 'user sees certificate subject' do
+ visit project_pages_domain_path(project, domain)
+
+ expect(page).to have_selector '.card-header', text: 'Certificate'
+ expect(page).to have_text domain.subject
+ end
+
+ it 'user can delete the certificate', :js do
+ visit project_pages_domain_path(project, domain)
+
+ expect(page).to have_selector '.card-header', text: 'Certificate'
+ expect(page).to have_text domain.subject
+ within('.card') { accept_confirm { click_on 'Remove' } }
+ expect(page).to have_field 'Certificate (PEM)', with: ''
+ expect(page).to have_field 'Key (PEM)', with: ''
+ end
+ end
+ end
+
+ include_examples 'user sees private keys only for user provided certificate'
+
+ context 'when letsencrypt is disabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: false, project: project)
+ end
+
+ before do
+ stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
+
+ visit project_pages_domain_path(project, domain)
+ end
+
+ it "does not render the Let's Encrypt field", :js do
+ expect(page).not_to have_selector '.js-auto-ssl-toggle-container'
+ end
+
+ include_examples 'user sees private keys only for user provided certificate'
+ end
+end
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
new file mode 100644
index 00000000000..3649fae17ce
--- /dev/null
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -0,0 +1,201 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'Pages edits pages settings', :js do
+ let(:project) { create(:project, pages_https_only: false) }
+ let(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+
+ project.add_maintainer(user)
+
+ sign_in(user)
+ end
+
+ context 'when user is the owner' do
+ before do
+ project.namespace.update!(owner: user)
+ end
+
+ context 'when pages deployed' do
+ before do
+ project.mark_pages_as_deployed
+ end
+
+ it 'renders Access pages' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Access pages')
+ end
+
+ context 'when pages are disabled in the project settings' do
+ it 'renders disabled warning' do
+ project.project_feature.update!(pages_access_level: ProjectFeature::DISABLED)
+
+ visit project_pages_path(project)
+
+ expect(page).to have_content('GitLab Pages are disabled for this project')
+ end
+ end
+
+ it 'renders first deployment warning' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.')
+ end
+
+ shared_examples 'does not render access control warning' do
+ it 'does not render access control warning' do
+ visit project_pages_path(project)
+
+ expect(page).not_to have_content('Access Control is enabled for this Pages website')
+ end
+ end
+
+ include_examples 'does not render access control warning'
+
+ context 'when access control is enabled in gitlab settings' do
+ before do
+ stub_pages_setting(access_control: true)
+ end
+
+ it 'renders access control warning' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Access Control is enabled for this Pages website')
+ end
+
+ context 'when pages are public' do
+ before do
+ project.project_feature.update!(pages_access_level: ProjectFeature::PUBLIC)
+ end
+
+ include_examples 'does not render access control warning'
+ end
+ end
+
+ context 'when support for external domains is disabled' do
+ it 'renders message that support is disabled' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Support for domains and certificates is disabled')
+ end
+ end
+ end
+
+ it 'does not see anything to destroy' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Configure pages')
+ expect(page).not_to have_link('Remove pages')
+ end
+
+ describe 'project settings page' do
+ it 'renders "Pages" tab' do
+ visit edit_project_path(project)
+
+ page.within '.nav-sidebar' do
+ expect(page).to have_link('Pages')
+ end
+ end
+
+ context 'when pages are disabled' do
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(false)
+ end
+
+ it 'does not render "Pages" tab' do
+ visit edit_project_path(project)
+
+ page.within '.nav-sidebar' do
+ expect(page).not_to have_link('Pages')
+ end
+ end
+ end
+ end
+ end
+
+ describe 'HTTPS settings', :https_pages_enabled do
+ before do
+ project.namespace.update!(owner: user)
+
+ project.mark_pages_as_deployed
+ end
+
+ it 'tries to change the setting' do
+ visit project_pages_path(project)
+ expect(page).to have_content("Force HTTPS (requires valid certificates)")
+
+ uncheck :project_pages_https_only
+
+ click_button 'Save'
+
+ expect(page).to have_text('Your changes have been saved')
+ expect(page).not_to have_checked_field('project_pages_https_only')
+ end
+
+ context 'setting could not be updated' do
+ let(:service) { instance_double('Projects::UpdateService') }
+
+ before do
+ allow(Projects::UpdateService).to receive(:new).and_return(service)
+ allow(service).to receive(:execute).and_return(status: :error, message: 'Some error has occured')
+ end
+
+ it 'tries to change the setting' do
+ visit project_pages_path(project)
+
+ uncheck :project_pages_https_only
+
+ click_button 'Save'
+
+ expect(page).to have_text('Some error has occured')
+ end
+ end
+
+ context 'non-HTTPS domain exists' do
+ let(:project) { create(:project, pages_https_only: false) }
+
+ before do
+ create(:pages_domain, :without_key, :without_certificate, project: project)
+ end
+
+ it 'the setting is disabled' do
+ visit project_pages_path(project)
+
+ expect(page).to have_field(:project_pages_https_only, disabled: true)
+ expect(page).to have_button('Save')
+ end
+ end
+
+ context 'HTTPS pages are disabled', :https_pages_disabled do
+ it 'the setting is unavailable' do
+ visit project_pages_path(project)
+
+ expect(page).not_to have_field(:project_pages_https_only)
+ expect(page).not_to have_content('Force HTTPS (requires valid certificates)')
+ expect(page).to have_button('Save')
+ end
+ end
+ end
+
+ describe 'Remove page' do
+ context 'when pages are deployed' do
+ before do
+ project.mark_pages_as_deployed
+ end
+
+ it 'removes the pages', :sidekiq_inline do
+ visit project_pages_path(project)
+
+ expect(page).to have_link('Remove pages')
+
+ accept_confirm { click_link 'Remove pages' }
+
+ expect(page).to have_content('Pages were scheduled for removal')
+ expect(project.reload.pages_deployed?).to be_falsey
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/pages_lets_encrypt_spec.rb b/spec/features/projects/pages_lets_encrypt_spec.rb
deleted file mode 100644
index 302e9f5e533..00000000000
--- a/spec/features/projects/pages_lets_encrypt_spec.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
- include LetsEncryptHelpers
-
- let(:project) { create(:project, pages_https_only: false) }
- let(:user) { create(:user) }
- let(:role) { :maintainer }
- let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
-
- let(:certificate_key) { attributes_for(:pages_domain)[:key] }
-
- before do
- allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
- stub_lets_encrypt_settings
-
- project.add_role(user, role)
- sign_in(user)
- project.namespace.update(owner: user)
- allow_next_instance_of(Project) do |instance|
- allow(instance).to receive(:pages_deployed?) { true }
- end
- end
-
- it "creates new domain with Let's Encrypt enabled by default" do
- visit new_project_pages_domain_path(project)
-
- fill_in 'Domain', with: 'my.test.domain.com'
-
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- click_button 'Create New Domain'
-
- expect(page).to have_content('my.test.domain.com')
- expect(PagesDomain.find_by_domain('my.test.domain.com').auto_ssl_enabled).to eq(true)
- end
-
- context 'when the auto SSL management is initially disabled' do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: false, project: project)
- end
-
- it 'enables auto SSL and dynamically updates the form accordingly', :js do
- visit project_pages_domain_path(project, domain)
-
- expect(domain.auto_ssl_enabled).to eq false
-
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
- expect(page).to have_selector '.card-header', text: 'Certificate'
- expect(page).to have_text domain.subject
-
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
-
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- expect(page).not_to have_selector '.card-header', text: 'Certificate'
- expect(page).not_to have_text domain.subject
-
- click_on 'Save Changes'
-
- expect(domain.reload.auto_ssl_enabled).to eq true
- end
- end
-
- context 'when the auto SSL management is initially enabled' do
- let(:domain) do
- create(:pages_domain, :letsencrypt, auto_ssl_enabled: true, project: project)
- end
-
- it 'disables auto SSL and dynamically updates the form accordingly', :js do
- visit project_pages_domain_path(project, domain)
-
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
-
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
-
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).to have_field 'Key (PEM)', type: 'textarea'
-
- click_on 'Save Changes'
-
- expect(domain.reload.auto_ssl_enabled).to eq false
- end
- end
-
- context "when we failed to obtain Let's Encrypt certificate", :js do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: true, auto_ssl_failed: true, project: project)
- end
-
- it 'user can retry obtaining certificate' do
- visit project_pages_domain_path(project, domain)
-
- expect(page).to have_text("Something went wrong while obtaining the Let's Encrypt certificate.")
-
- click_on('Retry')
-
- expect(page).to have_text("GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.")
- end
- end
-
- shared_examples 'user sees private keys only for user provided certificate' do
- shared_examples 'user do not see private key' do
- it 'user do not see private key' do
- visit project_pages_domain_path(project, domain)
-
- expect(page).not_to have_selector '.card-header', text: 'Certificate'
- expect(page).not_to have_text domain.subject
- end
- end
-
- context 'when auto_ssl is enabled for domain' do
- let(:domain) { create(:pages_domain, :letsencrypt, project: project, auto_ssl_enabled: true) }
-
- include_examples 'user do not see private key'
- end
-
- context 'when auto_ssl is disabled for domain' do
- let(:domain) { create(:pages_domain, :letsencrypt, project: project) }
-
- include_examples 'user do not see private key'
- end
-
- context 'when certificate is provided by user' do
- let(:domain) { create(:pages_domain, project: project, auto_ssl_enabled: false) }
-
- it 'user sees certificate subject' do
- visit project_pages_domain_path(project, domain)
-
- expect(page).to have_selector '.card-header', text: 'Certificate'
- expect(page).to have_text domain.subject
- end
-
- it 'user can delete the certificate', :js do
- visit project_pages_domain_path(project, domain)
-
- expect(page).to have_selector '.card-header', text: 'Certificate'
- expect(page).to have_text domain.subject
- within('.card') { accept_confirm { click_on 'Remove' } }
- expect(page).to have_field 'Certificate (PEM)', with: ''
- expect(page).to have_field 'Key (PEM)', with: ''
- end
- end
- end
-
- include_examples 'user sees private keys only for user provided certificate'
-
- context 'when letsencrypt is disabled' do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: false, project: project)
- end
-
- before do
- stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
-
- visit project_pages_domain_path(project, domain)
- end
-
- it "does not render the Let's Encrypt field", :js do
- expect(page).not_to have_selector '.js-auto-ssl-toggle-container'
- end
-
- include_examples 'user sees private keys only for user provided certificate'
- end
-end
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
deleted file mode 100644
index 11f712fde81..00000000000
--- a/spec/features/projects/pages_spec.rb
+++ /dev/null
@@ -1,411 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.shared_examples 'pages settings editing' do
- let_it_be(:project) { create(:project, pages_https_only: false) }
- let(:user) { create(:user) }
- let(:role) { :maintainer }
-
- before do
- allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
-
- project.add_role(user, role)
-
- sign_in(user)
- end
-
- context 'when user is the owner' do
- before do
- project.namespace.update(owner: user)
- end
-
- context 'when pages deployed' do
- before do
- allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
- end
-
- it 'renders Access pages' do
- visit project_pages_path(project)
-
- expect(page).to have_content('Access pages')
- end
-
- context 'when pages are disabled in the project settings' do
- it 'renders disabled warning' do
- project.project_feature.update!(pages_access_level: ProjectFeature::DISABLED)
-
- visit project_pages_path(project)
-
- expect(page).to have_content('GitLab Pages are disabled for this project')
- end
- end
-
- it 'renders first deployment warning' do
- visit project_pages_path(project)
-
- expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.')
- end
-
- shared_examples 'does not render access control warning' do
- it 'does not render access control warning' do
- visit project_pages_path(project)
-
- expect(page).not_to have_content('Access Control is enabled for this Pages website')
- end
- end
-
- include_examples 'does not render access control warning'
-
- context 'when access control is enabled in gitlab settings' do
- before do
- stub_pages_setting(access_control: true)
- end
-
- it 'renders access control warning' do
- visit project_pages_path(project)
-
- expect(page).to have_content('Access Control is enabled for this Pages website')
- end
-
- context 'when pages are public' do
- before do
- project.project_feature.update!(pages_access_level: ProjectFeature::PUBLIC)
- end
-
- include_examples 'does not render access control warning'
- end
- end
-
- context 'when support for external domains is disabled' do
- it 'renders message that support is disabled' do
- visit project_pages_path(project)
-
- expect(page).to have_content('Support for domains and certificates is disabled')
- end
- end
-
- context 'when pages are exposed on external HTTP address', :http_pages_enabled do
- let(:project) { create(:project, pages_https_only: false) }
-
- shared_examples 'adds new domain' do
- it 'adds new domain' do
- visit new_project_pages_domain_path(project)
-
- fill_in 'Domain', with: 'my.test.domain.com'
- click_button 'Create New Domain'
-
- expect(page).to have_content('my.test.domain.com')
- end
- end
-
- it 'allows to add new domain' do
- visit project_pages_path(project)
-
- expect(page).to have_content('New Domain')
- end
-
- it_behaves_like 'adds new domain'
-
- context 'when project in group namespace' do
- it_behaves_like 'adds new domain' do
- let(:group) { create :group }
- let(:project) { create(:project, namespace: group, pages_https_only: false) }
- end
- end
-
- context 'when pages domain is added' do
- before do
- create(:pages_domain, project: project, domain: 'my.test.domain.com')
-
- visit new_project_pages_domain_path(project)
- end
-
- it 'renders certificates is disabled' do
- expect(page).to have_content('Support for custom certificates is disabled')
- end
-
- it 'does not adds new domain and renders error message' do
- fill_in 'Domain', with: 'my.test.domain.com'
- click_button 'Create New Domain'
-
- expect(page).to have_content('Domain has already been taken')
- end
- end
- end
-
- context 'when pages are exposed on external HTTPS address', :https_pages_enabled, :js do
- let(:certificate_pem) do
- attributes_for(:pages_domain)[:certificate]
- end
-
- let(:certificate_key) do
- attributes_for(:pages_domain)[:key]
- end
-
- it 'adds new domain with certificate' do
- visit new_project_pages_domain_path(project)
-
- fill_in 'Domain', with: 'my.test.domain.com'
-
- if ::Gitlab::LetsEncrypt.enabled?
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
- end
-
- fill_in 'Certificate (PEM)', with: certificate_pem
- fill_in 'Key (PEM)', with: certificate_key
- click_button 'Create New Domain'
-
- expect(page).to have_content('my.test.domain.com')
- end
-
- it 'shows validation error if domain is duplicated' do
- project.pages_domains.create!(domain: 'my.test.domain.com')
-
- visit new_project_pages_domain_path(project)
-
- fill_in 'Domain', with: 'my.test.domain.com'
- click_button 'Create New Domain'
-
- expect(page).to have_content('Domain has already been taken')
- end
-
- describe 'with dns verification enabled' do
- before do
- stub_application_setting(pages_domain_verification_enabled: true)
- end
-
- it 'shows the DNS verification record' do
- domain = create(:pages_domain, project: project)
-
- visit project_pages_path(project)
-
- within('#content-body') { click_link 'Edit' }
- expect(page).to have_field :domain_verification, with: "#{domain.verification_domain} TXT #{domain.keyed_verification_code}"
- end
- end
-
- describe 'updating the certificate for an existing domain' do
- let!(:domain) do
- create(:pages_domain, project: project, auto_ssl_enabled: false)
- end
-
- it 'allows the certificate to be updated' do
- visit project_pages_path(project)
-
- within('#content-body') { click_link 'Edit' }
- click_button 'Save Changes'
-
- expect(page).to have_content('Domain was updated')
- end
-
- context 'when the certificate is invalid' do
- let!(:domain) do
- create(:pages_domain, :without_certificate, :without_key, project: project)
- end
-
- it 'tells the user what the problem is' do
- visit project_pages_path(project)
-
- within('#content-body') { click_link 'Edit' }
-
- if ::Gitlab::LetsEncrypt.enabled?
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
- end
-
- fill_in 'Certificate (PEM)', with: 'invalid data'
- click_button 'Save Changes'
-
- expect(page).to have_content('Certificate must be a valid PEM certificate')
- expect(page).to have_content('Certificate misses intermediates')
- expect(page).to have_content("Key doesn't match the certificate")
- end
- end
-
- it 'allows the certificate to be removed', :js do
- visit project_pages_path(project)
-
- within('#content-body') { click_link 'Edit' }
-
- accept_confirm { click_link 'Remove' }
-
- expect(page).to have_field('Certificate (PEM)', with: '')
- expect(page).to have_field('Key (PEM)', with: '')
- domain.reload
- expect(domain.certificate).to be_nil
- expect(domain.key).to be_nil
- end
-
- it 'shows the DNS CNAME record' do
- visit project_pages_path(project)
-
- within('#content-body') { click_link 'Edit' }
- expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}."
- end
- end
- end
- end
-
- it 'does not see anything to destroy' do
- visit project_pages_path(project)
-
- expect(page).to have_content('Configure pages')
- expect(page).not_to have_link('Remove pages')
- end
-
- describe 'project settings page' do
- it 'renders "Pages" tab' do
- visit edit_project_path(project)
-
- page.within '.nav-sidebar' do
- expect(page).to have_link('Pages')
- end
- end
-
- context 'when pages are disabled' do
- before do
- allow(Gitlab.config.pages).to receive(:enabled).and_return(false)
- end
-
- it 'does not render "Pages" tab' do
- visit edit_project_path(project)
-
- page.within '.nav-sidebar' do
- expect(page).not_to have_link('Pages')
- end
- end
- end
- end
- end
-
- describe 'HTTPS settings', :https_pages_enabled do
- before do
- project.namespace.update(owner: user)
-
- allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
- end
-
- it 'tries to change the setting' do
- visit project_pages_path(project)
- expect(page).to have_content("Force HTTPS (requires valid certificates)")
-
- uncheck :project_pages_https_only
-
- click_button 'Save'
-
- expect(page).to have_text('Your changes have been saved')
- expect(page).not_to have_checked_field('project_pages_https_only')
- end
-
- context 'setting could not be updated' do
- let(:service) { instance_double('Projects::UpdateService') }
-
- before do
- allow(Projects::UpdateService).to receive(:new).and_return(service)
- allow(service).to receive(:execute).and_return(status: :error, message: 'Some error has occured')
- end
-
- it 'tries to change the setting' do
- visit project_pages_path(project)
-
- uncheck :project_pages_https_only
-
- click_button 'Save'
-
- expect(page).to have_text('Some error has occured')
- end
- end
-
- context 'non-HTTPS domain exists' do
- let(:project) { create(:project, pages_https_only: false) }
-
- before do
- create(:pages_domain, :without_key, :without_certificate, project: project)
- end
-
- it 'the setting is disabled' do
- visit project_pages_path(project)
-
- expect(page).to have_field(:project_pages_https_only, disabled: true)
- expect(page).to have_button('Save')
- end
- end
-
- context 'HTTPS pages are disabled', :https_pages_disabled do
- it 'the setting is unavailable' do
- visit project_pages_path(project)
-
- expect(page).not_to have_field(:project_pages_https_only)
- expect(page).not_to have_content('Force HTTPS (requires valid certificates)')
- expect(page).to have_button('Save')
- end
- end
- end
-
- describe 'Remove page' do
- let(:project) { create :project, :repository }
-
- context 'when pages are deployed' do
- let(:pipeline) do
- commit_sha = project.commit('HEAD').sha
-
- project.ci_pipelines.create(
- ref: 'HEAD',
- sha: commit_sha,
- source: :push,
- protected: false
- )
- end
-
- let(:ci_build) do
- create(
- :ci_build,
- project: project,
- pipeline: pipeline,
- ref: 'HEAD')
- end
-
- let!(:artifact) do
- create(:ci_job_artifact, :archive, :correct_checksum,
- file: fixture_file_upload(File.join('spec/fixtures/pages.zip')), job: ci_build)
- end
-
- let!(:metadata) do
- create(:ci_job_artifact, :metadata,
- file: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta')), job: ci_build)
- end
-
- before do
- result = Projects::UpdatePagesService.new(project, ci_build).execute
- expect(result[:status]).to eq(:success)
- expect(project).to be_pages_deployed
- end
-
- it 'removes the pages', :sidekiq_inline do
- visit project_pages_path(project)
-
- expect(page).to have_link('Remove pages')
-
- accept_confirm { click_link 'Remove pages' }
-
- expect(page).to have_content('Pages were scheduled for removal')
- expect(project.reload.pages_deployed?).to be_falsey
- end
- end
- end
-end
-
-RSpec.describe 'Pages', :js do
- include LetsEncryptHelpers
-
- context 'when editing normally' do
- include_examples 'pages settings editing'
- end
-
- context 'when letsencrypt support is enabled' do
- before do
- stub_lets_encrypt_settings
- end
-
- include_examples 'pages settings editing'
- end
-end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index ac3566fbbdd..94800717677 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe 'Pipeline', :js do
before do
sign_in(user)
project.add_role(user, role)
- stub_feature_flags(graphql_pipeline_details: false)
end
shared_context 'pipeline builds' do
@@ -57,7 +56,7 @@ RSpec.describe 'Pipeline', :js do
end
end
- describe 'GET /:project/pipelines/:id' do
+ describe 'GET /:project/-/pipelines/:id' do
include_context 'pipeline builds'
let(:group) { create(:group) }
@@ -69,7 +68,7 @@ RSpec.describe 'Pipeline', :js do
it 'shows the pipeline graph' do
visit_pipeline
- expect(page).to have_selector('.pipeline-visualization')
+ expect(page).to have_selector('.js-pipeline-graph')
expect(page).to have_content('Build')
expect(page).to have_content('Test')
expect(page).to have_content('Deploy')
@@ -625,20 +624,6 @@ RSpec.describe 'Pipeline', :js do
end
end
end
-
- context 'when FF dag_pipeline_tab is disabled' do
- before do
- stub_feature_flags(dag_pipeline_tab: false)
- visit_pipeline
- end
-
- it 'does not show DAG link' do
- expect(page).to have_link('Pipeline')
- expect(page).to have_link('Jobs')
- expect(page).not_to have_link('DAG')
- expect(page).to have_link('Failed Jobs')
- end
- end
end
context 'when user does not have access to read jobs' do
@@ -646,7 +631,7 @@ RSpec.describe 'Pipeline', :js do
project.update(public_builds: false)
end
- describe 'GET /:project/pipelines/:id' do
+ describe 'GET /:project/-/pipelines/:id' do
include_context 'pipeline builds'
let(:project) { create(:project, :repository) }
@@ -657,7 +642,7 @@ RSpec.describe 'Pipeline', :js do
end
it 'shows the pipeline graph' do
- expect(page).to have_selector('.pipeline-visualization')
+ expect(page).to have_selector('.js-pipeline-graph')
expect(page).to have_content('Build')
expect(page).to have_content('Test')
expect(page).to have_content('Deploy')
@@ -691,13 +676,13 @@ RSpec.describe 'Pipeline', :js do
downstream: downstream)
end
- describe 'GET /:project/pipelines/:id' do
+ describe 'GET /:project/-/pipelines/:id' do
before do
visit project_pipeline_path(project, pipeline)
end
it 'shows the pipeline with a bridge job' do
- expect(page).to have_selector('.pipeline-visualization')
+ expect(page).to have_selector('.js-pipeline-graph')
expect(page).to have_content('cross-build')
end
@@ -740,7 +725,7 @@ RSpec.describe 'Pipeline', :js do
end
end
- describe 'GET /:project/pipelines/:id/builds' do
+ describe 'GET /:project/-/pipelines/:id/builds' do
before do
visit builds_project_pipeline_path(project, pipeline)
end
@@ -767,9 +752,64 @@ RSpec.describe 'Pipeline', :js do
stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group)
end
- describe 'GET /:project/pipelines/:id' do
+ describe 'GET /:project/-/pipelines/:id' do
subject { visit project_pipeline_path(project, pipeline) }
+ # remove when :graphql_pipeline_details flag is removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/299112
+ context 'when :graphql_pipeline_details flag is off' do
+ before do
+ stub_feature_flags(graphql_pipeline_details: false)
+ stub_feature_flags(graphql_pipeline_details_users: false)
+ end
+
+ it 'shows deploy job as created' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('pending')
+ end
+
+ within('.js-pipeline-graph') do
+ within '.stage-column:nth-child(1)' do
+ expect(page).to have_content('test')
+ expect(page).to have_css('.ci-status-icon-pending')
+ end
+
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-created')
+ end
+ end
+ end
+
+ context 'when test job succeeded' do
+ before do
+ test_job.success!
+ end
+
+ it 'shows deploy job as pending' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('running')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(1)' do
+ expect(page).to have_content('test')
+ expect(page).to have_css('.ci-status-icon-success')
+ end
+
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-pending')
+ end
+ end
+ end
+ end
+ end
+
it 'shows deploy job as created' do
subject
@@ -777,13 +817,13 @@ RSpec.describe 'Pipeline', :js do
expect(page).to have_content('pending')
end
- within('.pipeline-graph') do
- within '.stage-column:nth-child(1)' do
+ within('.js-pipeline-graph') do
+ within(all('[data-testid="stage-column"]')[0]) do
expect(page).to have_content('test')
expect(page).to have_css('.ci-status-icon-pending')
end
- within '.stage-column:nth-child(2)' do
+ within(all('[data-testid="stage-column"]')[1]) do
expect(page).to have_content('deploy')
expect(page).to have_css('.ci-status-icon-created')
end
@@ -802,13 +842,13 @@ RSpec.describe 'Pipeline', :js do
expect(page).to have_content('running')
end
- within('.pipeline-graph') do
- within '.stage-column:nth-child(1)' do
+ within('.js-pipeline-graph') do
+ within(all('[data-testid="stage-column"]')[0]) do
expect(page).to have_content('test')
expect(page).to have_css('.ci-status-icon-success')
end
- within '.stage-column:nth-child(2)' do
+ within(all('[data-testid="stage-column"]')[1]) do
expect(page).to have_content('deploy')
expect(page).to have_css('.ci-status-icon-pending')
end
@@ -831,14 +871,37 @@ RSpec.describe 'Pipeline', :js do
expect(page).to have_content('waiting')
end
- within('.pipeline-graph') do
- within '.stage-column:nth-child(2)' do
+ within('.js-pipeline-graph') do
+ within(all('[data-testid="stage-column"]')[1]) do
expect(page).to have_content('deploy')
expect(page).to have_css('.ci-status-icon-waiting-for-resource')
end
end
end
+ # remove when :graphql_pipeline_details flag is removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/299112
+ context 'when :graphql_pipeline_details flag is off' do
+ before do
+ stub_feature_flags(graphql_pipeline_details: false)
+ stub_feature_flags(graphql_pipeline_details_users: false)
+ end
+ it 'shows deploy job as waiting for resource' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('waiting')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-waiting-for-resource')
+ end
+ end
+ end
+ end
+
context 'when resource is released from another job' do
before do
another_job.success!
@@ -851,19 +914,86 @@ RSpec.describe 'Pipeline', :js do
expect(page).to have_content('running')
end
- within('.pipeline-graph') do
- within '.stage-column:nth-child(2)' do
+ within('.js-pipeline-graph') do
+ within(all('[data-testid="stage-column"]')[1]) do
expect(page).to have_content('deploy')
expect(page).to have_css('.ci-status-icon-pending')
end
end
end
+
+ # remove when :graphql_pipeline_details flag is removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/299112
+ context 'when :graphql_pipeline_details flag is off' do
+ before do
+ stub_feature_flags(graphql_pipeline_details: false)
+ stub_feature_flags(graphql_pipeline_details_users: false)
+ end
+ it 'shows deploy job as pending' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('running')
+ end
+
+ within('.pipeline-graph') do
+ within '.stage-column:nth-child(2)' do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-pending')
+ end
+ end
+ end
+ end
+ end
+
+ context 'when deploy job is a bridge to trigger a downstream pipeline' do
+ let!(:deploy_job) do
+ create(:ci_bridge, :created, stage: 'deploy', name: 'deploy',
+ stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group)
+ end
+
+ it 'shows deploy job as waiting for resource' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('waiting')
+ end
+
+ within('.js-pipeline-graph') do
+ within(all('[data-testid="stage-column"]')[1]) do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-waiting-for-resource')
+ end
+ end
+ end
+ end
+
+ context 'when deploy job is a bridge to trigger a downstream pipeline' do
+ let!(:deploy_job) do
+ create(:ci_bridge, :created, stage: 'deploy', name: 'deploy',
+ stage_idx: 2, pipeline: pipeline, project: project, resource_group: resource_group)
+ end
+
+ it 'shows deploy job as waiting for resource' do
+ subject
+
+ within('.pipeline-header-container') do
+ expect(page).to have_content('waiting')
+ end
+
+ within('.js-pipeline-graph') do
+ within(all('[data-testid="stage-column"]')[1]) do
+ expect(page).to have_content('deploy')
+ expect(page).to have_css('.ci-status-icon-waiting-for-resource')
+ end
+ end
+ end
end
end
end
end
- describe 'GET /:project/pipelines/:id/builds' do
+ describe 'GET /:project/-/pipelines/:id/builds' do
include_context 'pipeline builds'
let(:project) { create(:project, :repository) }
@@ -965,7 +1095,7 @@ RSpec.describe 'Pipeline', :js do
end
end
- describe 'GET /:project/pipelines/:id/failures' do
+ describe 'GET /:project/-/pipelines/:id/failures' do
let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: '1234') }
let(:pipeline_failures_page) { failures_project_pipeline_path(project, pipeline) }
let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) }
@@ -1078,12 +1208,29 @@ RSpec.describe 'Pipeline', :js do
expect(current_path).to eq(pipeline_path(pipeline))
expect(page).not_to have_content('Failed Jobs')
- expect(page).to have_selector('.pipeline-visualization')
+ expect(page).to have_selector('.js-pipeline-graph')
+ end
+
+ # remove when :graphql_pipeline_details flag is removed
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/299112
+ context 'when :graphql_pipeline_details flag is off' do
+ before do
+ stub_feature_flags(graphql_pipeline_details: false)
+ stub_feature_flags(graphql_pipeline_details_users: false)
+ end
+
+ it 'displays the pipeline graph' do
+ subject
+
+ expect(current_path).to eq(pipeline_path(pipeline))
+ expect(page).not_to have_content('Failed Jobs')
+ expect(page).to have_selector('.pipeline-visualization')
+ end
end
end
end
- describe 'GET /:project/pipelines/:id/dag' do
+ describe 'GET /:project/-/pipelines/:id/dag' do
include_context 'pipeline builds'
let(:project) { create(:project, :repository) }
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 450524b8d70..6421d3db2cd 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -13,11 +13,13 @@ RSpec.describe 'Pipelines', :js do
before do
sign_in(user)
stub_feature_flags(graphql_pipeline_details: false)
+ stub_feature_flags(graphql_pipeline_details_users: false)
+
project.add_developer(user)
project.update!(auto_devops_attributes: { enabled: false })
end
- describe 'GET /:project/pipelines' do
+ describe 'GET /:project/-/pipelines' do
let(:project) { create(:project, :repository) }
let!(:pipeline) do
@@ -287,23 +289,23 @@ RSpec.describe 'Pipelines', :js do
end
it 'has a dropdown with play button' do
- expect(page).to have_selector('.dropdown-new.btn.btn-default .icon-play')
+ expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] [data-testid="play-icon"]')
end
it 'has link to the manual action' do
- find('.js-pipeline-dropdown-manual-actions').click
+ find('[data-testid="pipelines-manual-actions-dropdown"]').click
expect(page).to have_button('manual build')
end
context 'when manual action was played' do
before do
- find('.js-pipeline-dropdown-manual-actions').click
+ find('[data-testid="pipelines-manual-actions-dropdown"]').click
click_button('manual build')
end
it 'enqueues manual action job' do
- expect(page).to have_selector('.js-pipeline-dropdown-manual-actions:disabled')
+ expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] .gl-dropdown-toggle:disabled')
end
end
end
@@ -321,11 +323,11 @@ RSpec.describe 'Pipelines', :js do
end
it 'has a dropdown for actionable jobs' do
- expect(page).to have_selector('.dropdown-new.btn.btn-default .icon-play')
+ expect(page).to have_selector('[data-testid="pipelines-manual-actions-dropdown"] [data-testid="play-icon"]')
end
it "has link to the delayed job's action" do
- find('.js-pipeline-dropdown-manual-actions').click
+ find('[data-testid="pipelines-manual-actions-dropdown"]').click
time_diff = [0, delayed_job.scheduled_at - Time.now].max
expect(page).to have_button('delayed job 1')
@@ -341,7 +343,7 @@ RSpec.describe 'Pipelines', :js do
end
it "shows 00:00:00 as the remaining time" do
- find('.js-pipeline-dropdown-manual-actions').click
+ find('[data-testid="pipelines-manual-actions-dropdown"]').click
expect(page).to have_content("00:00:00")
end
@@ -349,7 +351,7 @@ RSpec.describe 'Pipelines', :js do
context 'when user played a delayed job immediately' do
before do
- find('.js-pipeline-dropdown-manual-actions').click
+ find('[data-testid="pipelines-manual-actions-dropdown"]').click
page.accept_confirm { click_button('delayed job 1') }
wait_for_requests
end
@@ -517,56 +519,75 @@ RSpec.describe 'Pipelines', :js do
end
end
- context 'mini pipeline graph' do
- let!(:build) do
- create(:ci_build, :pending, pipeline: pipeline,
- stage: 'build',
- name: 'build')
- end
-
- before do
- visit_project_pipelines
- end
+ shared_examples 'mini pipeline renders' do |ci_mini_pipeline_gl_dropdown_enabled|
+ context 'mini pipeline graph' do
+ let!(:build) do
+ create(:ci_build, :pending, pipeline: pipeline,
+ stage: 'build',
+ name: 'build')
+ end
- it 'renders a mini pipeline graph' do
- expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]')
- expect(page).to have_selector('.js-builds-dropdown-button')
- end
+ before do
+ stub_feature_flags(ci_mini_pipeline_gl_dropdown: ci_mini_pipeline_gl_dropdown_enabled)
+ visit_project_pipelines
+ end
- context 'when clicking a stage badge' do
- it 'opens a dropdown' do
- find('.js-builds-dropdown-button').click
+ let_it_be(:dropdown_toggle_selector) do
+ if ci_mini_pipeline_gl_dropdown_enabled
+ '[data-testid="mini-pipeline-graph-dropdown"] .dropdown-toggle'
+ else
+ '[data-testid="mini-pipeline-graph-dropdown-toggle"]'
+ end
+ end
- expect(page).to have_link build.name
+ it 'renders a mini pipeline graph' do
+ expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]')
+ expect(page).to have_selector(dropdown_toggle_selector)
end
- it 'is possible to cancel pending build' do
- find('.js-builds-dropdown-button').click
- find('.js-ci-action').click
- wait_for_requests
+ context 'when clicking a stage badge' do
+ it 'opens a dropdown' do
+ find(dropdown_toggle_selector).click
- expect(build.reload).to be_canceled
- end
- end
+ expect(page).to have_link build.name
+ end
- context 'for a failed pipeline' do
- let!(:build) do
- create(:ci_build, :failed, pipeline: pipeline,
- stage: 'build',
- name: 'build')
+ it 'is possible to cancel pending build' do
+ find(dropdown_toggle_selector).click
+ find('.js-ci-action').click
+ wait_for_requests
+
+ expect(build.reload).to be_canceled
+ end
end
- it 'displays the failure reason' do
- find('.js-builds-dropdown-button').click
+ context 'for a failed pipeline' do
+ let!(:build) do
+ create(:ci_build, :failed, pipeline: pipeline,
+ stage: 'build',
+ name: 'build')
+ end
+
+ it 'displays the failure reason' do
+ find(dropdown_toggle_selector).click
- within('.js-builds-dropdown-list') do
- build_element = page.find('.mini-pipeline-graph-dropdown-item')
- expect(build_element['title']).to eq('build - failed - (unknown failure)')
+ within('.js-builds-dropdown-list') do
+ build_element = page.find('.mini-pipeline-graph-dropdown-item')
+ expect(build_element['title']).to eq('build - failed - (unknown failure)')
+ end
end
end
end
end
+ context 'with ci_mini_pipeline_gl_dropdown disabled' do
+ it_behaves_like "mini pipeline renders", false
+ end
+
+ context 'with ci_mini_pipeline_gl_dropdown enabled' do
+ it_behaves_like "mini pipeline renders", true
+ end
+
context 'with pagination' do
before do
allow(Ci::Pipeline).to receive(:default_per_page).and_return(1)
@@ -597,7 +618,7 @@ RSpec.describe 'Pipelines', :js do
end
end
- describe 'GET /:project/pipelines/show' do
+ describe 'GET /:project/-/pipelines/show' do
let(:project) { create(:project, :repository) }
let(:pipeline) do
@@ -649,7 +670,7 @@ RSpec.describe 'Pipelines', :js do
end
end
- describe 'POST /:project/pipelines' do
+ describe 'POST /:project/-/pipelines' do
let(:project) { create(:project, :repository) }
before do
diff --git a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
index 3994f55caee..4dfd4416eeb 100644
--- a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
@@ -40,4 +40,8 @@ RSpec.describe 'Slack slash commands', :js do
value = find_field('url').value
expect(value).to match("api/v4/projects/#{project.id}/services/slack_slash_commands/trigger")
end
+
+ it 'shows help content' do
+ expect(page).to have_content('This service allows users to perform common operations on this project by entering slash commands in Slack.')
+ end
end
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index c087237fd7c..39c4315bf0f 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe "Projects > Settings > Pipelines settings" do
it 'updates auto_cancel_pending_pipelines' do
visit project_settings_ci_cd_path(project)
- page.check('Auto-cancel redundant, pending pipelines')
+ page.check('Auto-cancel redundant pipelines')
page.within '#js-general-pipeline-settings' do
click_on 'Save changes'
end
diff --git a/spec/features/projects/settings/project_settings_spec.rb b/spec/features/projects/settings/project_settings_spec.rb
index 7b2b5594c22..cd1c9ecde9c 100644
--- a/spec/features/projects/settings/project_settings_spec.rb
+++ b/spec/features/projects/settings/project_settings_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Projects settings' do
let_it_be(:project) { create(:project) }
let(:user) { project.owner }
let(:panel) { find('.general-settings', match: :first) }
- let(:button) { panel.find('.btn.js-settings-toggle') }
+ let(:button) { panel.find('.btn.gl-button.js-settings-toggle') }
let(:title) { panel.find('.settings-title') }
before do
@@ -39,7 +39,7 @@ RSpec.describe 'Projects settings' do
visit edit_project_path(project)
forking_enabled_input = find('input[name="project[project_feature_attributes][forking_access_level]"]', visible: :hidden)
- forking_enabled_button = find('input[name="project[project_feature_attributes][forking_access_level]"] + label > button')
+ forking_enabled_button = find('[data-for="project[project_feature_attributes][forking_access_level]"] .gl-toggle')
expect(forking_enabled_input.value).to eq('20')
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 2b03ecf5af1..6e4082d1391 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
select('7 days', from: 'Remove tags older than:')
fill_in('Remove tags matching:', with: '.*-production')
- submit_button = find('.btn.btn-success')
+ submit_button = find('.btn.gl-button.btn-success')
expect(submit_button).not_to be_disabled
submit_button.click
end
@@ -53,7 +53,7 @@ RSpec.describe 'Project > Settings > CI/CD > Container registry tag expiration p
within '#js-registry-policies' do
fill_in('Remove tags matching:', with: '*-production')
- submit_button = find('.btn.btn-success')
+ submit_button = find('.btn.gl-button.btn-success')
expect(submit_button).not_to be_disabled
submit_button.click
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 3e520142117..2f257d299d8 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
click_button 'Add key'
expect(page).to have_content('new_deploy_key')
- expect(page).to have_content('Write access allowed')
+ expect(page).to have_content('Grant write permissions to this key')
end
it 'edit an existing deploy key' do
@@ -77,7 +77,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
click_button 'Save changes'
expect(page).to have_content('updated_deploy_key')
- expect(page).to have_content('Write access allowed')
+ expect(page).to have_content('Grant write permissions to this key')
end
it 'edit an existing public deploy key to be writable' do
@@ -90,7 +90,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
click_button 'Save changes'
expect(page).to have_content('public_deploy_key')
- expect(page).to have_content('Write access allowed')
+ expect(page).to have_content('Grant write permissions to this key')
end
it 'edit a deploy key from projects user has access to' do
diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
index e97e4a2030a..e8e32d93f7b 100644
--- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(page).to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do
- find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
+ find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click
find('input[value="Save changes"]').send_keys(:return)
end
@@ -71,7 +71,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(page).to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do
- find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click
+ find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click
find('input[value="Save changes"]').send_keys(:return)
end
@@ -92,7 +92,7 @@ RSpec.describe 'Projects > Settings > User manages merge request settings' do
expect(page).not_to have_content 'All discussions must be resolved'
within('.sharing-permissions-form') do
- find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
+ find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click
find('input[value="Save changes"]').send_keys(:return)
end
diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/settings/user_manages_project_members_spec.rb
index 726b8fb6840..0d22da34b91 100644
--- a/spec/features/projects/settings/user_manages_project_members_spec.rb
+++ b/spec/features/projects/settings/user_manages_project_members_spec.rb
@@ -3,6 +3,9 @@
require 'spec_helper'
RSpec.describe 'Projects > Settings > User manages project members' do
+ include Spec::Support::Helpers::Features::MembersHelpers
+ include Select2Helper
+
let(:group) { create(:group, name: 'OpenSource') }
let(:project) { create(:project) }
let(:project2) { create(:project) }
@@ -16,62 +19,123 @@ RSpec.describe 'Projects > Settings > User manages project members' do
sign_in(user)
end
- it 'cancels a team member', :js do
- visit(project_project_members_path(project))
+ context 'when `vue_project_members_list` feature flag is enabled' do
+ it 'cancels a team member', :js do
+ visit(project_project_members_path(project))
+
+ page.within find_member_row(user_dmitriy) do
+ click_button 'Remove member'
+ end
+
+ page.within('[role="dialog"]') do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
+
+ visit(project_project_members_path(project))
+
+ expect(members_table).not_to have_content(user_dmitriy.name)
+ expect(members_table).not_to have_content(user_dmitriy.username)
+ end
+
+ it 'imports a team from another project', :js do
+ stub_feature_flags(invite_members_group_modal: false)
+
+ project2.add_maintainer(user)
+ project2.add_reporter(user_mike)
+
+ visit(project_project_members_path(project))
- project_member = project.project_members.find_by(user_id: user_dmitriy.id)
+ page.within('.invite-users-form') do
+ click_link('Import')
+ end
- page.within("#project_member_#{project_member.id}") do
- # Open modal
- click_on('Remove user from project')
+ select2(project2.id, from: '#source_project_id')
+ click_button('Import project members')
+
+ expect(find_member_row(user_mike)).to have_content('Reporter')
end
- expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ it 'shows all members of project shared group', :js do
+ group.add_owner(user)
+ group.add_developer(user_dmitriy)
+
+ share_link = project.project_group_links.new(group_access: Gitlab::Access::MAINTAINER)
+ share_link.group_id = group.id
+ share_link.save!
- click_on('Remove member')
+ visit(project_project_members_path(project))
- visit(project_project_members_path(project))
+ click_link 'Groups'
- expect(page).not_to have_content(user_dmitriy.name)
- expect(page).not_to have_content(user_dmitriy.username)
+ expect(find_group_row(group)).to have_content('Maintainer')
+ end
end
- it 'imports a team from another project' do
- project2.add_maintainer(user)
- project2.add_reporter(user_mike)
+ context 'when `vue_project_members_list` feature flag is disabled' do
+ before do
+ stub_feature_flags(vue_project_members_list: false)
+ end
+
+ it 'cancels a team member', :js do
+ visit(project_project_members_path(project))
+
+ project_member = project.project_members.find_by(user_id: user_dmitriy.id)
+
+ page.within("#project_member_#{project_member.id}") do
+ # Open modal
+ click_on('Remove user from project')
+ end
+
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+
+ click_on('Remove member')
- visit(project_project_members_path(project))
+ visit(project_project_members_path(project))
- page.within('.invite-users-form') do
- click_link('Import')
+ expect(page).not_to have_content(user_dmitriy.name)
+ expect(page).not_to have_content(user_dmitriy.username)
end
- select(project2.full_name, from: 'source_project_id')
- click_button('Import')
+ it 'imports a team from another project' do
+ stub_feature_flags(invite_members_group_modal: false)
- project_member = project.project_members.find_by(user_id: user_mike.id)
+ project2.add_maintainer(user)
+ project2.add_reporter(user_mike)
- page.within("#project_member_#{project_member.id}") do
- expect(page).to have_content('Mike')
- expect(page).to have_content('Reporter')
+ visit(project_project_members_path(project))
+
+ page.within('.invite-users-form') do
+ click_link('Import')
+ end
+
+ select(project2.full_name, from: 'source_project_id')
+ click_button('Import')
+
+ project_member = project.project_members.find_by(user_id: user_mike.id)
+
+ page.within("#project_member_#{project_member.id}") do
+ expect(page).to have_content('Mike')
+ expect(page).to have_content('Reporter')
+ end
end
- end
- it 'shows all members of project shared group', :js do
- group.add_owner(user)
- group.add_developer(user_dmitriy)
+ it 'shows all members of project shared group', :js do
+ group.add_owner(user)
+ group.add_developer(user_dmitriy)
- share_link = project.project_group_links.new(group_access: Gitlab::Access::MAINTAINER)
- share_link.group_id = group.id
- share_link.save!
+ share_link = project.project_group_links.new(group_access: Gitlab::Access::MAINTAINER)
+ share_link.group_id = group.id
+ share_link.save!
- visit(project_project_members_path(project))
+ visit(project_project_members_path(project))
- click_link 'Groups'
+ click_link 'Groups'
- page.within('[data-testid="project-member-groups"]') do
- expect(page).to have_content('OpenSource')
- expect(first('.group_member')).to have_content('Maintainer')
+ page.within('[data-testid="project-member-groups"]') do
+ expect(page).to have_content('OpenSource')
+ expect(first('.group_member')).to have_content('Maintainer')
+ end
end
end
end
diff --git a/spec/features/projects/settings/visibility_settings_spec.rb b/spec/features/projects/settings/visibility_settings_spec.rb
index 6cecbbdb3d0..becb30c02b7 100644
--- a/spec/features/projects/settings/visibility_settings_spec.rb
+++ b/spec/features/projects/settings/visibility_settings_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
context 'merge requests select' do
it 'hides merge requests section' do
- find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .project-feature-toggle').click
+ find('.project-feature-controls[data-for="project[project_feature_attributes][merge_requests_access_level]"] .gl-toggle').click
expect(page).to have_selector('.merge-requests-feature', visible: false)
end
@@ -46,7 +46,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
context 'builds select' do
it 'hides builds select section' do
- find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .project-feature-toggle').click
+ find('.project-feature-controls[data-for="project[project_feature_attributes][builds_access_level]"] .gl-toggle').click
expect(page).to have_selector('.builds-feature', visible: false)
end
diff --git a/spec/features/projects/show/user_manages_notifications_spec.rb b/spec/features/projects/show/user_manages_notifications_spec.rb
index d444ea27d35..5f7d9b0963b 100644
--- a/spec/features/projects/show/user_manages_notifications_spec.rb
+++ b/spec/features/projects/show/user_manages_notifications_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do
let(:project) { create(:project, :public, :repository) }
before do
+ stub_feature_flags(vue_notification_dropdown: false)
sign_in(project.owner)
end
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 febdb70de86..e6157887c12 100644
--- a/spec/features/projects/show/user_sees_git_instructions_spec.rb
+++ b/spec/features/projects/show/user_sees_git_instructions_spec.rb
@@ -5,6 +5,13 @@ require 'spec_helper'
RSpec.describe 'Projects > Show > User sees Git instructions' do
let_it_be(:user) { create(:user) }
+ before do
+ # Reset user notification settings between examples to prevent
+ # validation failure on NotificationSetting.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/299822#note_492817174
+ user.notification_settings.reset
+ end
+
shared_examples_for 'redirects to the sign in page' do
it 'redirects to the sign in page' do
expect(current_path).to eq(new_user_session_path)
diff --git a/spec/features/projects/terraform_spec.rb b/spec/features/projects/terraform_spec.rb
index dfa4dad8490..55b906c2bc5 100644
--- a/spec/features/projects/terraform_spec.rb
+++ b/spec/features/projects/terraform_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'Terraform', :js do
fill_in "terraform-state-remove-input-#{additional_state.name}", with: additional_state.name
click_button 'Remove'
- expect(page).not_to have_content(additional_state.name)
+ expect(page).to have_content("#{additional_state.name} successfully removed")
expect { additional_state.reload }.to raise_error ActiveRecord::RecordNotFound
end
end
diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb
index feb5f348256..aff3022bd4e 100644
--- a/spec/features/projects/user_creates_project_spec.rb
+++ b/spec/features/projects/user_creates_project_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'User creates a project', :js do
before do
sign_in(user)
create(:personal_key, user: user)
+
+ stub_experiments(new_project_readme: :candidate)
end
it 'creates a new project' do
@@ -16,6 +18,10 @@ RSpec.describe 'User creates a project', :js do
find('[data-qa-selector="blank_project_link"]').click
fill_in(:project_name, with: 'Empty')
+ # part of the new_project_readme experiment
+ expect(page).to have_checked_field 'Initialize repository with a README'
+ uncheck 'Initialize repository with a README'
+
page.within('#content-body') do
click_button('Create project')
end
diff --git a/spec/features/projects/user_sees_user_popover_spec.rb b/spec/features/projects/user_sees_user_popover_spec.rb
index 9cfc6234969..52e65deae3b 100644
--- a/spec/features/projects/user_sees_user_popover_spec.rb
+++ b/spec/features/projects/user_sees_user_popover_spec.rb
@@ -38,8 +38,6 @@ RSpec.describe 'User sees user popover', :js do
it "displays user popover in system note" do
add_note("/assign @#{user.username}")
- wait_for_requests
-
find('.system-note-message .js-user-link').hover
page.within(popover_selector) do
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
index 8fa5f741a95..13ae035e8ef 100644
--- a/spec/features/projects/user_uses_shortcuts_spec.rb
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -27,14 +27,13 @@ RSpec.describe 'User uses shortcuts', :js do
open_modal_shortcut_keys
- # modal-shortcuts still in the DOM, but hidden
- expect(find('#modal-shortcuts', visible: false)).not_to be_visible
+ expect(page).not_to have_selector('[data-testid="modal-shortcuts"]')
page.refresh
open_modal_shortcut_keys
# after reload, shortcuts modal doesn't exist at all until we add it
- expect(page).not_to have_selector('#modal-shortcuts')
+ expect(page).not_to have_selector('[data-testid="modal-shortcuts"]')
end
it 're-enables shortcuts' do
@@ -47,7 +46,7 @@ RSpec.describe 'User uses shortcuts', :js do
close_modal
open_modal_shortcut_keys
- expect(find('#modal-shortcuts')).to be_visible
+ expect(find('[data-testid="modal-shortcuts"]')).to be_visible
end
def open_modal_shortcut_keys
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 95d268ab1be..eb099359df9 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -9,10 +9,6 @@ RSpec.describe 'Protected Branches', :js do
let(:admin) { create(:admin) }
let(:project) { create(:project, :repository) }
- before do
- stub_feature_flags(deploy_keys_on_protected_branches: false)
- end
-
context 'logged in as developer' do
before do
project.add_developer(user)
@@ -174,7 +170,7 @@ RSpec.describe 'Protected Branches', :js do
stub_licensed_features(protected_refs_for_users: false)
end
- include_examples 'when the deploy_keys_on_protected_branches FF is turned on' do
+ include_examples 'Deploy keys with protected branches' do
let(:all_dropdown_sections) { %w(Roles Deploy\ Keys) }
end
end
diff --git a/spec/features/registrations/experience_level_spec.rb b/spec/features/registrations/experience_level_spec.rb
index 25496e2fef1..f432215d4a8 100644
--- a/spec/features/registrations/experience_level_spec.rb
+++ b/spec/features/registrations/experience_level_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe 'Experience level screen' do
before do
group.add_owner(user)
gitlab_sign_in(user)
- stub_experiment_for_subject(onboarding_issues: true)
visit users_sign_up_experience_level_path(namespace_path: group.to_param)
end
diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb
index b860cd08e64..1a882050126 100644
--- a/spec/features/search/user_searches_for_commits_spec.rb
+++ b/spec/features/search/user_searches_for_commits_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'User searches for commits' do
+RSpec.describe 'User searches for commits', :js do
let(:project) { create(:project, :repository) }
let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
let(:user) { create(:user) }
@@ -41,7 +41,7 @@ RSpec.describe 'User searches for commits' do
submit_search('See merge request')
select_search_scope('Commits')
- expect(page).to have_selector('.commit-row-description', count: 9)
+ expect(page).to have_selector('.commit-row-description', visible: false, count: 9)
end
end
end
diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb
index e253b9f2f7a..828e478d701 100644
--- a/spec/features/search/user_searches_for_issues_spec.rb
+++ b/spec/features/search/user_searches_for_issues_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe 'User searches for issues', :js do
expect(page.all('.search-result-row').last).to have_link(issue1.title)
end
- find('.reverse-sort-btn').click
+ find('[data-testid="sort-highest-icon"]').click
page.within('.results') do
expect(page.all('.search-result-row').first).to have_link(issue1.title)
diff --git a/spec/features/search/user_searches_for_merge_requests_spec.rb b/spec/features/search/user_searches_for_merge_requests_spec.rb
index 21e8075739f..7271716644b 100644
--- a/spec/features/search/user_searches_for_merge_requests_spec.rb
+++ b/spec/features/search/user_searches_for_merge_requests_spec.rb
@@ -5,8 +5,14 @@ require 'spec_helper'
RSpec.describe 'User searches for merge requests', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
- let!(:merge_request1) { create(:merge_request, title: 'Foo', source_project: project, target_project: project) }
- let!(:merge_request2) { create(:merge_request, :simple, title: 'Bar', source_project: project, target_project: project) }
+ let!(:merge_request1) { create(:merge_request, title: 'Merge Request Foo', source_project: project, target_project: project, created_at: 1.hour.ago) }
+ let!(:merge_request2) { create(:merge_request, :simple, title: 'Merge Request Bar', source_project: project, target_project: project) }
+
+ def search_for_mr(search)
+ fill_in('dashboard_search', with: search)
+ find('.btn-search').click
+ select_search_scope('Merge requests')
+ end
before do
project.add_maintainer(user)
@@ -18,9 +24,7 @@ RSpec.describe 'User searches for merge requests', :js do
include_examples 'top right search form'
it 'finds a merge request' do
- fill_in('dashboard_search', with: merge_request1.title)
- find('.btn-search').click
- select_search_scope('Merge requests')
+ search_for_mr(merge_request1.title)
page.within('.results') do
expect(page).to have_link(merge_request1.title)
@@ -28,6 +32,22 @@ RSpec.describe 'User searches for merge requests', :js do
end
end
+ it 'sorts by created date' do
+ search_for_mr('Merge Request')
+
+ page.within('.results') do
+ expect(page.all('.search-result-row').first).to have_link(merge_request2.title)
+ expect(page.all('.search-result-row').last).to have_link(merge_request1.title)
+ end
+
+ find('[data-testid="sort-highest-icon"]').click
+
+ page.within('.results') do
+ expect(page.all('.search-result-row').first).to have_link(merge_request1.title)
+ expect(page.all('.search-result-row').last).to have_link(merge_request2.title)
+ end
+ end
+
context 'when on a project page' do
it 'finds a merge request' do
find('[data-testid="project-filter"]').click
@@ -38,9 +58,7 @@ RSpec.describe 'User searches for merge requests', :js do
click_on(project.full_name)
end
- fill_in('dashboard_search', with: merge_request1.title)
- find('.btn-search').click
- select_search_scope('Merge requests')
+ search_for_mr(merge_request1.title)
page.within('.results') do
expect(page).to have_link(merge_request1.title)
diff --git a/spec/features/search/user_searches_for_projects_spec.rb b/spec/features/search/user_searches_for_projects_spec.rb
index b64909dd42f..e34ae031679 100644
--- a/spec/features/search/user_searches_for_projects_spec.rb
+++ b/spec/features/search/user_searches_for_projects_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'User searches for projects' do
+RSpec.describe 'User searches for projects', :js do
let!(:project) { create(:project, :public, name: 'Shop') }
context 'when signed out' do
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 0f8daaf8e15..e17521e1d02 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -69,7 +69,13 @@ RSpec.describe 'Task Lists', :js do
wait_for_requests
expect(page).to have_selector(".md .task-list .task-list-item .task-list-item-checkbox")
- expect(page).to have_selector('.btn-close')
+ end
+
+ it_behaves_like 'page with comment and close button', 'Close issue' do
+ def setup
+ visit_issue(project, issue)
+ wait_for_requests
+ end
end
it 'is only editable by author' do
diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb
index 5762a54a717..eed67e3ac78 100644
--- a/spec/features/u2f_spec.rb
+++ b/spec/features/u2f_spec.rb
@@ -39,6 +39,11 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
end
it 'allows the same device to be registered for multiple users' do
+ # U2f specs will be removed after WebAuthn migration completed
+ pending('FakeU2fDevice has static key handle, '\
+ 'leading to duplicate credential_xid for WebAuthn during migration, '\
+ 'resulting in unique constraint violation')
+
# First user
visit profile_account_path
manage_two_factor_authentication
@@ -148,6 +153,11 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
describe "and also the current user" do
it "allows logging in with that particular device" do
+ # U2f specs will be removed after WebAuthn migration completed
+ pending('FakeU2fDevice has static key handle, '\
+ 'leading to duplicate credential_xid for WebAuthn during migration, '\
+ 'resulting in unique constraint violation')
+
# Register current user with the same U2F device
current_user = gitlab_sign_in(:user)
current_user.update_attribute(:otp_required_for_login, true)
diff --git a/spec/features/user_sees_revert_modal_spec.rb b/spec/features/user_sees_revert_modal_spec.rb
index 331f51dad95..5edf8358244 100644
--- a/spec/features/user_sees_revert_modal_spec.rb
+++ b/spec/features/user_sees_revert_modal_spec.rb
@@ -7,26 +7,33 @@ RSpec.describe 'Merge request > User sees revert modal', :js, :sidekiq_might_not
let(:user) { project.creator }
let(:merge_request) { create(:merge_request, source_project: project) }
+ shared_examples 'showing the revert modal' do
+ it 'shows the revert modal' do
+ click_button('Revert')
+
+ page.within('[data-testid="modal-commit"]') do
+ expect(page).to have_content 'Revert this merge request'
+ end
+ end
+ end
+
before do
sign_in(user)
visit(project_merge_request_path(project, merge_request))
click_button('Merge')
wait_for_requests
-
- visit(merge_request_path(merge_request))
- click_link('Revert')
end
- it 'shows the revert modal' do
- page.within('.modal-header') do
- expect(page).to have_content 'Revert this merge request'
- end
+ context 'without page reload after merge validates js correctly loaded' do
+ it_behaves_like 'showing the revert modal'
end
- it 'closes the revert modal with escape keypress' do
- find('#modal-revert-commit').send_keys(:escape)
+ context 'with page reload validates js correctly loaded' do
+ before do
+ visit(merge_request_path(merge_request))
+ end
- expect(page).not_to have_selector('#modal-revert-commit', visible: true)
+ it_behaves_like 'showing the revert modal'
end
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 5a537c1d4df..1d1120709b5 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -765,7 +765,7 @@ RSpec.describe 'Login' do
click_link 'Proceed'
expect(current_path).to eq(profile_account_path)
- expect(page).to have_content('Congratulations! You have enabled Two-factor Authentication!')
+ expect(page).to have_content('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 use that key to generate additional recovery codes.')
end
end
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
index 67216b04504..902079b7b93 100644
--- a/spec/features/users/overview_spec.rb
+++ b/spec/features/users/overview_spec.rb
@@ -151,6 +151,132 @@ RSpec.describe 'Overview tab on a user profile', :js do
end
end
+ describe 'followers section' do
+ describe 'user has no followers' do
+ before do
+ visit user.username
+ page.find('.js-followers-tab a').click
+ wait_for_requests
+ end
+
+ it 'shows an empty followers list with an info message' do
+ page.within('#followers') do
+ expect(page).to have_content('You do not have any followers')
+ expect(page).not_to have_selector('.gl-card.gl-mb-5')
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+ end
+ end
+
+ describe 'user has less then 20 followers' do
+ let(:follower) { create(:user) }
+
+ before do
+ follower.follow(user)
+ visit user.username
+ page.find('.js-followers-tab a').click
+ wait_for_requests
+ end
+
+ it 'shows followers' do
+ page.within('#followers') do
+ expect(page).to have_content(follower.name)
+ expect(page).to have_selector('.gl-card.gl-mb-5')
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+ end
+ end
+
+ describe 'user has more then 20 followers' do
+ let(:other_users) { create_list(:user, 21) }
+
+ before do
+ other_users.each do |follower|
+ follower.follow(user)
+ end
+
+ visit user.username
+ page.find('.js-followers-tab a').click
+ wait_for_requests
+ end
+ it 'shows paginated followers' do
+ page.within('#followers') do
+ other_users.each_with_index do |follower, i|
+ break if i == 20
+
+ expect(page).to have_content(follower.name)
+ end
+ expect(page).to have_selector('.gl-card.gl-mb-5')
+ expect(page).to have_selector('.gl-pagination')
+ expect(page).to have_selector('.gl-pagination .js-pagination-page', count: 2)
+ end
+ end
+ end
+ end
+
+ describe 'following section' do
+ describe 'user is not following others' do
+ before do
+ visit user.username
+ page.find('.js-following-tab a').click
+ wait_for_requests
+ end
+
+ it 'shows an empty following list with an info message' do
+ page.within('#following') do
+ expect(page).to have_content('You are not following other users')
+ expect(page).not_to have_selector('.gl-card.gl-mb-5')
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+ end
+ end
+
+ describe 'user is following less then 20 people' do
+ let(:followee) { create(:user) }
+
+ before do
+ user.follow(followee)
+ visit user.username
+ page.find('.js-following-tab a').click
+ wait_for_requests
+ end
+
+ it 'shows following user' do
+ page.within('#following') do
+ expect(page).to have_content(followee.name)
+ expect(page).to have_selector('.gl-card.gl-mb-5')
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+ end
+ end
+
+ describe 'user is following more then 20 people' do
+ let(:other_users) { create_list(:user, 21) }
+
+ before do
+ other_users.each do |followee|
+ user.follow(followee)
+ end
+
+ visit user.username
+ page.find('.js-following-tab a').click
+ wait_for_requests
+ end
+ it 'shows paginated following' do
+ page.within('#following') do
+ other_users.each_with_index do |followee, i|
+ break if i == 20
+
+ expect(page).to have_content(followee.name)
+ end
+ expect(page).to have_selector('.gl-card.gl-mb-5')
+ expect(page).to have_selector('.gl-pagination')
+ expect(page).to have_selector('.gl-pagination .js-pagination-page', count: 2)
+ end
+ end
+ end
+ end
+
describe 'bot user' do
let(:bot_user) { create(:user, user_type: :security_bot) }
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index 6aeb3023db8..a8372800700 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -20,6 +20,8 @@ RSpec.describe 'User page' do
expect(page).to have_link('Contributed projects')
expect(page).to have_link('Personal projects')
expect(page).to have_link('Snippets')
+ expect(page).to have_link('Followers')
+ expect(page).to have_link('Following')
end
end
@@ -54,6 +56,50 @@ RSpec.describe 'User page' do
expect(page).to have_content('GitLab - work info test')
end
end
+
+ context 'follow/unfollow and followers/following' do
+ let_it_be(:followee) { create(:user) }
+ let_it_be(:follower) { create(:user) }
+
+ it 'does not show link to follow' do
+ subject
+
+ expect(page).not_to have_link(text: 'Follow', class: 'gl-button')
+ end
+
+ it 'shows 0 followers and 0 following' do
+ subject
+
+ expect(page).to have_content('0 followers')
+ expect(page).to have_content('0 following')
+ end
+
+ it 'shows 1 followers and 1 following' do
+ follower.follow(user)
+ user.follow(followee)
+
+ subject
+
+ expect(page).to have_content('1 follower')
+ expect(page).to have_content('1 following')
+ end
+
+ it 'does show link to follow' do
+ sign_in(user)
+ visit user_path(followee)
+
+ expect(page).to have_link(text: 'Follow', class: 'gl-button')
+ end
+
+ it 'does show link to unfollow' do
+ sign_in(user)
+ user.follow(followee)
+
+ visit user_path(followee)
+
+ expect(page).to have_link(text: 'Unfollow', class: 'gl-button')
+ end
+ end
end
context 'with private profile' do
@@ -83,6 +129,8 @@ RSpec.describe 'User page' do
expect(page).to have_link('Contributed projects')
expect(page).to have_link('Personal projects')
expect(page).to have_link('Snippets')
+ expect(page).to have_link('Followers')
+ expect(page).to have_link('Following')
end
end
end
@@ -242,6 +290,8 @@ RSpec.describe 'User page' do
expect(page).not_to have_link('Contributed projects')
expect(page).not_to have_link('Personal projects')
expect(page).not_to have_link('Snippets')
+ expect(page).not_to have_link('Followers')
+ expect(page).not_to have_link('Following')
end
end
end
@@ -261,6 +311,8 @@ RSpec.describe 'User page' do
expect(page).to have_link('Contributed projects')
expect(page).to have_link('Personal projects')
expect(page).to have_link('Snippets')
+ expect(page).to have_link('Followers')
+ expect(page).to have_link('Following')
end
end
end
diff --git a/spec/features/webauthn_spec.rb b/spec/features/webauthn_spec.rb
index 2ffb6bb3477..4eebc9d2c1e 100644
--- a/spec/features/webauthn_spec.rb
+++ b/spec/features/webauthn_spec.rb
@@ -129,6 +129,10 @@ RSpec.describe 'Using WebAuthn Devices for Authentication', :js do
end
it 'falls back to U2F' do
+ # WebAuthn registration is automatically created with the U2fRegistration because of the after_create callback
+ # so we need to delete it
+ WebauthnRegistration.delete_all
+
gitlab_sign_in(user)
u2f_device.respond_to_u2f_authentication
diff --git a/spec/features/whats_new_spec.rb b/spec/features/whats_new_spec.rb
new file mode 100644
index 00000000000..7c5625486f5
--- /dev/null
+++ b/spec/features/whats_new_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "renders a `whats new` dropdown item", :js do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'shows notification dot and count and removes it once viewed' do
+ visit root_dashboard_path
+
+ page.within '.header-help' do
+ expect(page).to have_selector('.notification-dot', visible: true)
+
+ find('.header-help-dropdown-toggle').click
+
+ expect(page).to have_button(text: "What's new")
+ expect(page).to have_selector('.js-whats-new-notification-count')
+
+ find('button', text: "What's new").click
+ end
+
+ find('.whats-new-drawer .gl-drawer-close-button').click
+ find('.header-help-dropdown-toggle').click
+
+ page.within '.header-help' do
+ expect(page).not_to have_selector('.notification-dot', visible: true)
+ expect(page).to have_button(text: "What's new")
+ expect(page).not_to have_selector('.js-whats-new-notification-count')
+ end
+ end
+end
diff --git a/spec/finders/autocomplete/users_finder_spec.rb b/spec/finders/autocomplete/users_finder_spec.rb
index 357b6dfcea2..28bd7e12916 100644
--- a/spec/finders/autocomplete/users_finder_spec.rb
+++ b/spec/finders/autocomplete/users_finder_spec.rb
@@ -118,5 +118,10 @@ RSpec.describe Autocomplete::UsersFinder do
it { is_expected.to match_array([user1, external_user, omniauth_user, current_user]) }
end
+
+ it 'preloads the status association' do
+ associations = subject.map { |user| user.association(:status) }
+ expect(associations).to all(be_loaded)
+ end
end
end
diff --git a/spec/finders/ci/jobs_finder_spec.rb b/spec/finders/ci/jobs_finder_spec.rb
index 4a6585e3f2b..ab056dd26e8 100644
--- a/spec/finders/ci/jobs_finder_spec.rb
+++ b/spec/finders/ci/jobs_finder_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Ci::JobsFinder, '#execute' do
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
let_it_be(:job_1) { create(:ci_build) }
let_it_be(:job_2) { create(:ci_build, :running) }
- let_it_be(:job_3) { create(:ci_build, :success, pipeline: pipeline) }
+ let_it_be(:job_3) { create(:ci_build, :success, pipeline: pipeline, name: 'build') }
let(:params) { {} }
@@ -95,4 +95,35 @@ RSpec.describe Ci::JobsFinder, '#execute' do
end
end
end
+
+ context 'when pipeline is present' do
+ before_all do
+ project.add_maintainer(user)
+ job_3.update!(retried: true)
+ end
+
+ let_it_be(:job_4) { create(:ci_build, :success, pipeline: pipeline, name: 'build') }
+
+ subject { described_class.new(current_user: user, pipeline: pipeline, params: params).execute }
+
+ it 'does not return retried jobs by default' do
+ expect(subject).to match_array([job_4])
+ end
+
+ context 'when include_retried is false' do
+ let(:params) { { include_retried: false } }
+
+ it 'does not return retried jobs' do
+ expect(subject).to match_array([job_4])
+ end
+ end
+
+ context 'when include_retried is true' do
+ let(:params) { { include_retried: true } }
+
+ it 'returns retried jobs' do
+ expect(subject).to match_array([job_3, job_4])
+ end
+ end
+ end
end
diff --git a/spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb
new file mode 100644
index 00000000000..a703f3b800c
--- /dev/null
+++ b/spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Testing::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(:ref_path) { 'refs/heads/master' }
+ let(:limit) { nil }
+ let_it_be(:default_branch) { false }
+ let(:start_date) { '2020-03-09' }
+ let(:end_date) { '2020-03-10' }
+ let(:sort) { true }
+
+ let_it_be(:rspec_coverage_1) { create_daily_coverage('rspec', 79.0, '2020-03-09') }
+ let_it_be(:karma_coverage_1) { create_daily_coverage('karma', 89.0, '2020-03-09') }
+ let_it_be(:rspec_coverage_2) { create_daily_coverage('rspec', 95.0, '2020-03-10') }
+ let_it_be(:karma_coverage_2) { create_daily_coverage('karma', 92.0, '2020-03-10') }
+ let_it_be(:rspec_coverage_3) { create_daily_coverage('rspec', 97.0, '2020-03-11') }
+ let_it_be(:karma_coverage_3) { create_daily_coverage('karma', 99.0, '2020-03-11') }
+
+ let(:finder) { described_class.new(params: params, current_user: current_user) }
+
+ let(:params) do
+ {
+ project: project,
+ coverage: true,
+ ref_path: ref_path,
+ start_date: start_date,
+ end_date: end_date,
+ limit: limit,
+ sort: sort
+ }
+ end
+
+ subject(:coverages) { finder.execute }
+
+ context 'when params are provided' do
+ context 'when current user is not allowed to read data' do
+ let(:current_user) { user_without_permission }
+
+ it 'returns an empty collection' do
+ expect(coverages).to be_empty
+ end
+ end
+
+ context 'when current user is allowed to read data' do
+ let(:current_user) { user_with_permission }
+
+ it 'returns matching coverages within the given date range' do
+ expect(coverages).to match_array([
+ karma_coverage_2,
+ rspec_coverage_2,
+ karma_coverage_1,
+ rspec_coverage_1
+ ])
+ end
+
+ context 'when ref_path is nil' do
+ let(:default_branch) { true }
+ let(:ref_path) { nil }
+
+ it 'returns coverages for the default branch' do
+ rspec_coverage_4 = create_daily_coverage('rspec', 66.0, '2020-03-10')
+
+ expect(coverages).to contain_exactly(rspec_coverage_4)
+ end
+ end
+
+ context 'when limit is specified' do
+ let(:limit) { 2 }
+
+ it 'returns limited number of matching coverages within the given date range' do
+ expect(coverages).to match_array([
+ karma_coverage_2,
+ rspec_coverage_2
+ ])
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def create_daily_coverage(group_name, coverage, date)
+ create(
+ :ci_daily_build_group_report_result,
+ project: project,
+ ref_path: ref_path || 'feature-branch',
+ group_name: group_name,
+ data: { 'coverage' => coverage },
+ date: date,
+ default_branch: default_branch
+ )
+ end
+end
diff --git a/spec/finders/container_repositories_finder_spec.rb b/spec/finders/container_repositories_finder_spec.rb
index b6305e3f5b7..983f6dba28b 100644
--- a/spec/finders/container_repositories_finder_spec.rb
+++ b/spec/finders/container_repositories_finder_spec.rb
@@ -32,6 +32,34 @@ RSpec.describe ContainerRepositoriesFinder do
end
end
+ shared_examples 'with sorting' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:sort_repository) do
+ create(:container_repository, name: 'bar', project: project, created_at: 1.day.ago)
+ end
+
+ let_it_be(:sort_repository2) do
+ create(:container_repository, name: 'foo', project: project, created_at: 1.hour.ago, updated_at: 1.hour.ago)
+ end
+
+ [:created_desc, :updated_asc, :name_desc].each do |order|
+ context "with sort set to #{order}" do
+ let(:params) { { sort: order } }
+
+ it { is_expected.to eq([sort_repository2, sort_repository])}
+ end
+ end
+
+ [:created_asc, :updated_desc, :name_asc].each do |order|
+ context "with sort set to #{order}" do
+ let(:params) { { sort: order } }
+
+ it { is_expected.to eq([sort_repository, sort_repository2])}
+ end
+ end
+ end
+
describe '#execute' do
context 'with authorized user' do
subject { described_class.new(user: reporter, subject: subject_object, params: params).execute }
@@ -47,6 +75,7 @@ RSpec.describe ContainerRepositoriesFinder do
it { is_expected.to match_array([project_repository, other_repository]) }
it_behaves_like 'with name search'
+ it_behaves_like 'with sorting'
end
context 'when subject_type is project' do
@@ -55,6 +84,7 @@ RSpec.describe ContainerRepositoriesFinder do
it { is_expected.to match_array([project_repository]) }
it_behaves_like 'with name search'
+ it_behaves_like 'with sorting'
end
context 'with invalid subject_type' do
diff --git a/spec/finders/deployments_finder_spec.rb b/spec/finders/deployments_finder_spec.rb
index e4e0f366eeb..0f659fa1dab 100644
--- a/spec/finders/deployments_finder_spec.rb
+++ b/spec/finders/deployments_finder_spec.rb
@@ -3,130 +3,161 @@
require 'spec_helper'
RSpec.describe DeploymentsFinder do
- subject { described_class.new(project, params).execute }
-
- let(:project) { create(:project, :public, :test_repo) }
- let(:params) { {} }
+ subject { described_class.new(params).execute }
describe "#execute" do
- it 'returns all deployments by default' do
- deployments = create_list(:deployment, 2, :success, project: project)
- is_expected.to match_array(deployments)
+ context 'when project or group is missing' do
+ let(:params) { {} }
+
+ it 'returns nothing' do
+ is_expected.to eq([])
+ end
end
- describe 'filtering' do
- context 'when updated_at filters are specified' do
- let(:params) { { updated_before: 1.day.ago, updated_after: 3.days.ago } }
- let!(:deployment_1) { create(:deployment, :success, project: project, updated_at: 2.days.ago) }
- let!(:deployment_2) { create(:deployment, :success, project: project, updated_at: 4.days.ago) }
- let!(:deployment_3) { create(:deployment, :success, project: project, updated_at: 1.hour.ago) }
+ context 'at project scope' do
+ let_it_be(:project) { create(:project, :public, :test_repo) }
+ let(:base_params) { { project: project } }
+
+ describe 'filtering' do
+ context 'when updated_at filters are specified' do
+ let(:params) { { **base_params, updated_before: 1.day.ago, updated_after: 3.days.ago } }
+ let!(:deployment_1) { create(:deployment, :success, project: project, updated_at: 2.days.ago) }
+ let!(:deployment_2) { create(:deployment, :success, project: project, updated_at: 4.days.ago) }
+ let!(:deployment_3) { create(:deployment, :success, project: project, updated_at: 1.hour.ago) }
- it 'returns deployments with matched updated_at' do
- is_expected.to match_array([deployment_1])
+ it 'returns deployments with matched updated_at' do
+ is_expected.to match_array([deployment_1])
+ end
end
- end
- context 'when the environment name is specified' do
- let!(:environment1) { create(:environment, project: project) }
- let!(:environment2) { create(:environment, project: project) }
- let!(:deployment1) do
- create(:deployment, project: project, environment: environment1)
+ context 'when the environment name is specified' do
+ let!(:environment1) { create(:environment, project: project) }
+ let!(:environment2) { create(:environment, project: project) }
+ let!(:deployment1) do
+ create(:deployment, project: project, environment: environment1)
+ end
+
+ let!(:deployment2) do
+ create(:deployment, project: project, environment: environment2)
+ end
+
+ let(:params) { { **base_params, environment: environment1.name } }
+
+ it 'returns deployments for the given environment' do
+ is_expected.to match_array([deployment1])
+ end
end
- let!(:deployment2) do
- create(:deployment, project: project, environment: environment2)
+ context 'when the deployment status is specified' do
+ let!(:deployment1) { create(:deployment, :success, project: project) }
+ let!(:deployment2) { create(:deployment, :failed, project: project) }
+ let(:params) { { **base_params, status: 'success' } }
+
+ it 'returns deployments for the given environment' do
+ is_expected.to match_array([deployment1])
+ end
end
- let(:params) { { environment: environment1.name } }
+ context 'when using an invalid deployment status' do
+ let(:params) { { **base_params, status: 'kittens' } }
- it 'returns deployments for the given environment' do
- is_expected.to match_array([deployment1])
+ it 'raises ArgumentError' do
+ expect { subject }.to raise_error(ArgumentError)
+ end
end
end
- context 'when the deployment status is specified' do
- let!(:deployment1) { create(:deployment, :success, project: project) }
- let!(:deployment2) { create(:deployment, :failed, project: project) }
- let(:params) { { status: 'success' } }
+ describe 'ordering' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:params) { { **base_params, order_by: order_by, sort: sort } }
+
+ let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: 2.days.ago, updated_at: Time.now, finished_at: Time.now) }
+ let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago, updated_at: 2.hours.ago, finished_at: 2.hours.ago) }
+ let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'video', created_at: Time.now, updated_at: 1.hour.ago, finished_at: 1.hour.ago) }
+
+ where(:order_by, :sort, :ordered_deployments) do
+ 'created_at' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
+ 'created_at' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
+ 'id' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
+ 'id' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
+ 'iid' | 'asc' | [:deployment_3, :deployment_1, :deployment_2]
+ 'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
+ 'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
+ 'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
+ 'updated_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
+ 'updated_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
+ 'finished_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
+ 'finished_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
+ 'invalid' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
+ 'iid' | 'err' | [:deployment_3, :deployment_1, :deployment_2]
+ end
- it 'returns deployments for the given environment' do
- is_expected.to match_array([deployment1])
+ with_them do
+ it 'returns the deployments ordered' do
+ expect(subject).to eq(ordered_deployments.map { |name| public_send(name) })
+ end
end
end
- context 'when using an invalid deployment status' do
- let(:params) { { status: 'kittens' } }
+ describe 'transform `created_at` sorting to `id` sorting' do
+ let(:params) { { **base_params, order_by: 'created_at', sort: 'asc' } }
- it 'raises ArgumentError' do
- expect { subject }.to raise_error(ArgumentError)
+ it 'sorts by only one column' do
+ expect(subject.order_values.size).to eq(1)
end
- end
- end
- describe 'ordering' do
- using RSpec::Parameterized::TableSyntax
-
- let(:params) { { order_by: order_by, sort: sort } }
-
- let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: 2.days.ago, updated_at: Time.now) }
- let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago, updated_at: 2.hours.ago) }
- let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'video', created_at: Time.now, updated_at: 1.hour.ago) }
-
- where(:order_by, :sort, :ordered_deployments) do
- 'created_at' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
- 'created_at' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
- 'id' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
- 'id' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
- 'iid' | 'asc' | [:deployment_3, :deployment_1, :deployment_2]
- 'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
- 'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
- 'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
- 'updated_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
- 'updated_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
- 'invalid' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
- 'iid' | 'err' | [:deployment_3, :deployment_1, :deployment_2]
+ it 'sorts by `id`' do
+ expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
+ end
end
- with_them do
- it 'returns the deployments ordered' do
- expect(subject).to eq(ordered_deployments.map { |name| public_send(name) })
+ describe 'tie-breaker for `finished_at` sorting' do
+ let(:params) { { **base_params, order_by: 'updated_at', sort: 'asc' } }
+
+ it 'sorts by two columns' do
+ expect(subject.order_values.size).to eq(2)
end
- end
- end
- describe 'transform `created_at` sorting to `id` sorting' do
- let(:params) { { order_by: 'created_at', sort: 'asc' } }
+ it 'adds `id` sorting as the second order column' do
+ order_value = subject.order_values[1]
- it 'sorts by only one column' do
- expect(subject.order_values.size).to eq(1)
- end
+ expect(order_value.to_sql).to eq(Deployment.arel_table[:id].desc.to_sql)
+ end
- it 'sorts by `id`' do
- expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
- end
- end
+ it 'uses the `id DESC` as tie-breaker when ordering' do
+ updated_at = Time.now
- describe 'tie-breaker for `updated_at` sorting' do
- let(:params) { { order_by: 'updated_at', sort: 'asc' } }
+ deployment_1 = create(:deployment, :success, project: project, updated_at: updated_at)
+ deployment_2 = create(:deployment, :success, project: project, updated_at: updated_at)
+ deployment_3 = create(:deployment, :success, project: project, updated_at: updated_at)
- it 'sorts by two columns' do
- expect(subject.order_values.size).to eq(2)
+ expect(subject).to eq([deployment_3, deployment_2, deployment_1])
+ end
end
- it 'adds `id` sorting as the second order column' do
- order_value = subject.order_values[1]
+ context 'when filtering by finished time' do
+ let!(:deployment_1) { create(:deployment, :success, project: project, finished_at: 2.days.ago) }
+ let!(:deployment_2) { create(:deployment, :success, project: project, finished_at: 4.days.ago) }
+ let!(:deployment_3) { create(:deployment, :success, project: project, finished_at: 5.hours.ago) }
- expect(order_value.to_sql).to eq(Deployment.arel_table[:id].desc.to_sql)
- end
+ context 'when filtering by finished_after and finished_before' do
+ let(:params) { { **base_params, finished_after: 3.days.ago, finished_before: 1.day.ago } }
+
+ it { is_expected.to match_array([deployment_1]) }
+ end
- it 'uses the `id DESC` as tie-breaker when ordering' do
- updated_at = Time.now
+ context 'when the finished_before parameter is missing' do
+ let(:params) { { **base_params, finished_after: 3.days.ago } }
- deployment_1 = create(:deployment, :success, project: project, updated_at: updated_at)
- deployment_2 = create(:deployment, :success, project: project, updated_at: updated_at)
- deployment_3 = create(:deployment, :success, project: project, updated_at: updated_at)
+ it { is_expected.to match_array([deployment_1, deployment_3]) }
+ end
+
+ context 'when finished_after is missing' do
+ let(:params) { { **base_params, finished_before: 3.days.ago } }
- expect(subject).to eq([deployment_3, deployment_2, deployment_1])
+ it { is_expected.to match_array([deployment_2]) }
+ end
end
end
end
diff --git a/spec/finders/license_template_finder_spec.rb b/spec/finders/license_template_finder_spec.rb
index 93f13632b6f..754b92faccc 100644
--- a/spec/finders/license_template_finder_spec.rb
+++ b/spec/finders/license_template_finder_spec.rb
@@ -3,12 +3,7 @@
require 'spec_helper'
RSpec.describe LicenseTemplateFinder do
- describe '#execute' do
- subject(:result) { described_class.new(nil, params).execute }
-
- let(:categories) { categorised_licenses.keys }
- let(:categorised_licenses) { result.group_by(&:category) }
-
+ RSpec.shared_examples 'filters by popular category' do
context 'popular: true' do
let(:params) { { popular: true } }
@@ -26,6 +21,15 @@ RSpec.describe LicenseTemplateFinder do
expect(categorised_licenses[:Other]).to be_present
end
end
+ end
+
+ describe '#execute' do
+ subject(:result) { described_class.new(nil, params).execute }
+
+ let(:categories) { categorised_licenses.keys }
+ let(:categorised_licenses) { result.group_by(&:category) }
+
+ it_behaves_like 'filters by popular category'
context 'popular: nil' do
let(:params) { { popular: nil } }
@@ -48,4 +52,31 @@ RSpec.describe LicenseTemplateFinder do
end
end
end
+
+ describe '#template_names' do
+ let(:params) { {} }
+
+ subject(:template_names) { described_class.new(nil, params).template_names }
+
+ let(:categories) { categorised_licenses.keys }
+ let(:categorised_licenses) { template_names }
+
+ it_behaves_like 'filters by popular category'
+
+ context 'popular: nil' do
+ let(:params) { { popular: nil } }
+
+ it 'returns all licenses known by the Licensee gem' do
+ from_licensee = Licensee::License.all.map { |l| l.key }
+
+ expect(template_names.values.flatten.map { |x| x[:key] }).to match_array(from_licensee)
+ end
+ end
+
+ context 'template names hash keys' do
+ it 'has all the expected keys' do
+ expect(template_names.values.flatten.first.keys).to match_array(%i(id key name project_id))
+ end
+ end
+ end
end
diff --git a/spec/finders/merge_request/metrics_finder_spec.rb b/spec/finders/merge_request/metrics_finder_spec.rb
new file mode 100644
index 00000000000..ea039462e66
--- /dev/null
+++ b/spec/finders/merge_request/metrics_finder_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequest::MetricsFinder do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:merge_request_not_merged) { create(:merge_request, :unique_branches, source_project: project) }
+ let_it_be(:merged_at) { Time.new(2020, 5, 1) }
+ let_it_be(:merge_request_merged) do
+ create(:merge_request, :unique_branches, :merged, source_project: project).tap do |mr|
+ mr.metrics.update!(merged_at: merged_at)
+ end
+ end
+
+ let(:params) do
+ {
+ target_project: project,
+ merged_after: merged_at - 10.days,
+ merged_before: merged_at + 10.days
+ }
+ end
+
+ subject { described_class.new(current_user, params).execute.to_a }
+
+ context 'when target project is missing' do
+ before do
+ params.delete(:target_project)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when the user is not part of the project' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'when user is part of the project' do
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'returns merge request records' do
+ is_expected.to eq([merge_request_merged.metrics])
+ end
+
+ it 'excludes not merged records' do
+ is_expected.not_to eq([merge_request_not_merged.metrics])
+ end
+
+ context 'when only merged_before is given' do
+ before do
+ params.delete(:merged_after)
+ end
+
+ it { is_expected.to eq([merge_request_merged.metrics]) }
+ end
+
+ context 'when only merged_after is given' do
+ before do
+ params.delete(:merged_before)
+ end
+
+ it { is_expected.to eq([merge_request_merged.metrics]) }
+ end
+
+ context 'when no records matching the date range' do
+ before do
+ params[:merged_before] = merged_at - 1.year
+ params[:merged_after] = merged_at - 2.years
+ end
+
+ it { is_expected.to be_empty }
+ end
+ end
+end
diff --git a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
new file mode 100644
index 00000000000..4e9d021fa5d
--- /dev/null
+++ b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::OldestPerCommitFinder do
+ describe '#execute' do
+ it 'returns a Hash mapping commit SHAs to their oldest merge requests' do
+ project = create(:project)
+ mr1 = create(:merge_request, :merged, target_project: project)
+ mr2 = create(:merge_request, :merged, target_project: project)
+ mr1_diff = create(:merge_request_diff, merge_request: mr1)
+ mr2_diff = create(:merge_request_diff, merge_request: mr2)
+ sha1 = Digest::SHA1.hexdigest('foo')
+ sha2 = Digest::SHA1.hexdigest('bar')
+
+ create(:merge_request_diff_commit, merge_request_diff: mr1_diff, sha: sha1)
+ create(:merge_request_diff_commit, merge_request_diff: mr2_diff, sha: sha1)
+ create(
+ :merge_request_diff_commit,
+ merge_request_diff: mr2_diff,
+ sha: sha2,
+ relative_order: 1
+ )
+
+ commits = [double(:commit, id: sha1), double(:commit, id: sha2)]
+
+ expect(described_class.new(project).execute(commits)).to eq(
+ sha1 => mr1,
+ sha2 => mr2
+ )
+ end
+
+ it 'skips merge requests that are not merged' do
+ mr = create(:merge_request)
+ mr_diff = create(:merge_request_diff, merge_request: mr)
+ sha = Digest::SHA1.hexdigest('foo')
+
+ create(:merge_request_diff_commit, merge_request_diff: mr_diff, sha: sha)
+
+ commits = [double(:commit, id: sha)]
+
+ expect(described_class.new(mr.target_project).execute(commits))
+ .to be_empty
+ end
+ end
+end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 8dd53b9c3f9..445482a5a96 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -147,6 +147,7 @@ RSpec.describe Packages::GroupPackagesFinder do
end
it_behaves_like 'concerning versionless param'
+ it_behaves_like 'concerning package statuses'
end
context 'group has package of all types' do
diff --git a/spec/finders/packages/packages_finder_spec.rb b/spec/finders/packages/packages_finder_spec.rb
index 77a171db144..6e92616bafa 100644
--- a/spec/finders/packages/packages_finder_spec.rb
+++ b/spec/finders/packages/packages_finder_spec.rb
@@ -82,5 +82,6 @@ RSpec.describe ::Packages::PackagesFinder do
end
it_behaves_like 'concerning versionless param'
+ it_behaves_like 'concerning package statuses'
end
end
diff --git a/spec/finders/repositories/commits_with_trailer_finder_spec.rb b/spec/finders/repositories/commits_with_trailer_finder_spec.rb
new file mode 100644
index 00000000000..0c457aae340
--- /dev/null
+++ b/spec/finders/repositories/commits_with_trailer_finder_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::CommitsWithTrailerFinder do
+ let(:project) { create(:project, :repository) }
+
+ describe '#each_page' do
+ it 'only yields commits with the given trailer' do
+ finder = described_class.new(
+ project: project,
+ from: '570e7b2abdd848b95f2f578043fc23bd6f6fd24d',
+ to: 'c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd'
+ )
+
+ commits = finder.each_page('Signed-off-by').to_a.flatten
+
+ expect(commits.length).to eq(1)
+ expect(commits.first.id).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
+ expect(commits.first.trailers).to eq(
+ 'Signed-off-by' => 'Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>'
+ )
+ end
+
+ it 'supports paginating of commits' do
+ finder = described_class.new(
+ project: project,
+ from: 'c1acaa58bbcbc3eafe538cb8274ba387047b69f8',
+ to: '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
+ per_page: 1
+ )
+
+ commits = finder.each_page('Signed-off-by')
+
+ expect(commits.count).to eq(4)
+ end
+ end
+end
diff --git a/spec/finders/repositories/previous_tag_finder_spec.rb b/spec/finders/repositories/previous_tag_finder_spec.rb
new file mode 100644
index 00000000000..7cc33d11baf
--- /dev/null
+++ b/spec/finders/repositories/previous_tag_finder_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::PreviousTagFinder do
+ let(:project) { build_stubbed(:project) }
+ let(:finder) { described_class.new(project) }
+
+ describe '#execute' do
+ context 'when there is a previous tag' do
+ it 'returns the previous tag' do
+ tag1 = double(:tag1, name: 'v1.0.0')
+ tag2 = double(:tag2, name: 'v1.1.0')
+ tag3 = double(:tag3, name: 'v2.0.0')
+ tag4 = double(:tag4, name: '1.0.0')
+
+ allow(project.repository)
+ .to receive(:tags)
+ .and_return([tag1, tag3, tag2, tag4])
+
+ expect(finder.execute('2.1.0')).to eq(tag3)
+ expect(finder.execute('2.0.0')).to eq(tag2)
+ expect(finder.execute('1.5.0')).to eq(tag2)
+ expect(finder.execute('1.0.1')).to eq(tag1)
+ end
+ end
+
+ context 'when there is no previous tag' do
+ it 'returns nil' do
+ tag1 = double(:tag1, name: 'v1.0.0')
+ tag2 = double(:tag2, name: 'v1.1.0')
+
+ allow(project.repository)
+ .to receive(:tags)
+ .and_return([tag1, tag2])
+
+ expect(finder.execute('1.0.0')).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index 2da864b9a46..164975fdfb6 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -5,6 +5,102 @@ require 'spec_helper'
RSpec.describe TemplateFinder do
using RSpec::Parameterized::TableSyntax
+ let_it_be(:template_files) do
+ {
+ "Dockerfile/project_dockerfiles_template.dockerfile" => "project_dockerfiles_template content",
+ "gitignore/project_gitignores_template.gitignore" => "project_gitignores_template content",
+ "gitlab-ci/project_gitlab_ci_ymls_template.yml" => "project_gitlab_ci_ymls_template content",
+ ".gitlab/issue_templates/project_issues_template.md" => "project_issues_template content",
+ ".gitlab/merge_request_templates/project_merge_requests_template.md" => "project_merge_requests_template content"
+ }
+ end
+
+ RSpec.shared_examples 'fetches predefined vendor templates' do
+ where(:type, :vendored_name) do
+ :dockerfiles | 'Binary'
+ :gitignores | 'Actionscript'
+ :gitlab_ci_ymls | 'Android'
+ :metrics_dashboard_ymls | 'Default'
+ :gitlab_ci_syntax_ymls | 'Artifacts example'
+ end
+
+ with_them do
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to include(have_attributes(name: vendored_name))
+ end
+
+ context 'with name param' do
+ let(:params) { { name: vendored_name } }
+
+ it 'returns only the specified vendored template when a name is specified' do
+ expect(result).to have_attributes(name: vendored_name)
+ end
+
+ context 'with mistaken name param' do
+ let(:params) { { name: 'unknown' } }
+
+ it 'returns nil when an unknown name is specified' do
+ expect(result).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ RSpec.shared_examples 'no issues and merge requests templates available' do
+ context 'with issue and merge request templates' do
+ where(:type, :vendored_name) do
+ :issues | nil
+ :merge_requests | nil
+ end
+
+ with_them do
+ context 'when fetching all templates' do
+ it 'returns empty array' do
+ expect(result).to eq([])
+ end
+ end
+
+ context 'when looking for specific template by name' do
+ let(:params) { { name: 'anything' } }
+
+ it 'raises an error' do
+ expect { result }.to raise_exception(Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError)
+ end
+ end
+ end
+ end
+ end
+
+ RSpec.shared_examples 'fetches issues and merge requests templates' do
+ where(:type, :template_name) do
+ :issues | 'project_issues_template'
+ :merge_requests | 'project_merge_requests_template'
+ end
+
+ with_them do
+ it 'returns all repository template files for issues and merge requests' do
+ expect(result).to include(have_attributes(name: template_name))
+ end
+
+ context 'with name param' do
+ let(:params) { { name: template_name } }
+
+ it 'returns only the specified vendored template when a name is specified' do
+ expect(result).to have_attributes(name: template_name)
+ end
+
+ context 'with mistaken name param' do
+ let(:params) { { name: 'unknown' } }
+
+ it 'raises an error when an unknown name is specified' do
+ expect { result }.to raise_exception(Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError)
+ end
+ end
+ end
+ end
+ end
+
describe '#build' do
let(:project) { build_stubbed(:project) }
@@ -15,6 +111,8 @@ RSpec.describe TemplateFinder do
:licenses | ::LicenseTemplateFinder
:metrics_dashboard_ymls | described_class
:gitlab_ci_syntax_ymls | described_class
+ :issues | described_class
+ :merge_requests | described_class
end
with_them do
@@ -26,6 +124,37 @@ RSpec.describe TemplateFinder do
end
describe '#execute' do
+ let_it_be(:project) { nil }
+ let(:params) { {} }
+
+ subject(:result) { described_class.new(type, project, params).execute }
+
+ context 'when no project is passed in' do
+ it_behaves_like 'fetches predefined vendor templates'
+ it_behaves_like 'no issues and merge requests templates available'
+ end
+
+ context 'when project has no repository' do
+ let_it_be(:project) { create(:project) }
+
+ it_behaves_like 'fetches predefined vendor templates'
+ it_behaves_like 'no issues and merge requests templates available'
+ end
+
+ context 'when project has a repository' do
+ let_it_be(:project) { create(:project, :custom_repo, files: template_files) }
+
+ it_behaves_like 'fetches predefined vendor templates'
+ it_behaves_like 'fetches issues and merge requests templates'
+ end
+ end
+
+ describe '#template_names' do
+ let_it_be(:project) { nil }
+ let(:params) { {} }
+
+ subject(:result) { described_class.new(type, project, params).template_names.values.flatten.map { |el| OpenStruct.new(el) } }
+
where(:type, :vendored_name) do
:dockerfiles | 'Binary'
:gitignores | 'Actionscript'
@@ -35,22 +164,67 @@ RSpec.describe TemplateFinder do
end
with_them do
- it 'returns all vendored templates when no name is specified' do
- result = described_class.new(type, nil).execute
+ context 'when no project is passed in' do
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to include(have_attributes(name: vendored_name))
+ end
+ end
- expect(result).to include(have_attributes(name: vendored_name))
+ context 'when project has no repository' do
+ let_it_be(:project) { create(:project) }
+
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to include(have_attributes(name: vendored_name))
+ end
end
- it 'returns only the specified vendored template when a name is specified' do
- result = described_class.new(type, nil, name: vendored_name).execute
+ context 'when project has a repository' do
+ let_it_be(:project) { create(:project, :custom_repo, files: template_files) }
- expect(result).to have_attributes(name: vendored_name)
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to include(have_attributes(name: vendored_name))
+ end
end
- it 'returns nil when an unknown name is specified' do
- result = described_class.new(type, nil, name: 'unknown').execute
+ context 'template names hash keys' do
+ it 'has all the expected keys' do
+ expect(result.first.to_h.keys).to match_array(%i(id key name project_id))
+ end
+ end
+ end
+
+ where(:type, :template_name) do
+ :issues | 'project_issues_template'
+ :merge_requests | 'project_merge_requests_template'
+ end
+
+ with_them do
+ context 'when no project is passed in' do
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to eq([])
+ end
+ end
+
+ context 'when project has no repository' do
+ let_it_be(:project) { create(:project) }
+
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to eq([])
+ end
+ end
+
+ context 'when project has a repository' do
+ let_it_be(:project) { create(:project, :custom_repo, files: template_files) }
+
+ it 'returns all vendored templates when no name is specified' do
+ expect(result).to include(have_attributes(name: template_name))
+ end
- expect(result).to be_nil
+ context 'template names hash keys' do
+ it 'has all the expected keys' do
+ expect(result.first.to_h.keys).to match_array(%i(id key name project_id))
+ end
+ end
end
end
end
diff --git a/spec/finders/terraform/states_finder_spec.rb b/spec/finders/terraform/states_finder_spec.rb
new file mode 100644
index 00000000000..260e5f4818f
--- /dev/null
+++ b/spec/finders/terraform/states_finder_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Terraform::StatesFinder do
+ describe '#execute' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:state_1) { create(:terraform_state, project: project) }
+ let_it_be(:state_2) { create(:terraform_state, project: project) }
+
+ let(:user) { project.creator }
+
+ subject { described_class.new(project, user).execute }
+
+ it { is_expected.to contain_exactly(state_1, state_2) }
+
+ context 'user does not have permission' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'filtering by name' do
+ let(:params) { { name: name_param } }
+
+ subject { described_class.new(project, user, params: params).execute }
+
+ context 'name does not match' do
+ let(:name_param) { 'other-name' }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'name does match' do
+ let(:name_param) { state_1.name }
+
+ it { is_expected.to contain_exactly(state_1) }
+ end
+ end
+ end
+end
diff --git a/spec/finders/user_recent_events_finder_spec.rb b/spec/finders/user_recent_events_finder_spec.rb
index ddba9b595a4..5a9243d150d 100644
--- a/spec/finders/user_recent_events_finder_spec.rb
+++ b/spec/finders/user_recent_events_finder_spec.rb
@@ -5,16 +5,17 @@ require 'spec_helper'
RSpec.describe UserRecentEventsFinder do
let_it_be(:project_owner, reload: true) { create(:user) }
let_it_be(:current_user, reload: true) { create(:user) }
- let(:private_project) { create(:project, :private, creator: project_owner) }
- let(:internal_project) { create(:project, :internal, creator: project_owner) }
- let(:public_project) { create(:project, :public, creator: project_owner) }
+ let_it_be(:private_project) { create(:project, :private, creator: project_owner) }
+ let_it_be(:internal_project) { create(:project, :internal, creator: project_owner) }
+ let_it_be(:public_project) { create(:project, :public, creator: project_owner) }
let!(:private_event) { create(:event, project: private_project, author: project_owner) }
let!(:internal_event) { create(:event, project: internal_project, author: project_owner) }
let!(:public_event) { create(:event, project: public_project, author: project_owner) }
+ let_it_be(:issue) { create(:issue, project: public_project) }
let(:limit) { nil }
let(:params) { { limit: limit } }
- subject(:finder) { described_class.new(current_user, project_owner, params) }
+ subject(:finder) { described_class.new(current_user, project_owner, nil, params) }
describe '#execute' do
context 'when profile is public' do
@@ -39,11 +40,116 @@ RSpec.describe UserRecentEventsFinder do
expect(finder.execute).to be_empty
end
- describe 'design activity events' do
- let_it_be(:event_a) { create(:design_event, author: project_owner) }
- let_it_be(:event_b) { create(:design_event, author: project_owner) }
+ context 'events from multiple users' do
+ let_it_be(:second_user, reload: true) { create(:user) }
+ let_it_be(:private_project_second_user) { create(:project, :private, creator: second_user) }
+ let(:internal_project_second_user) { create(:project, :internal, creator: second_user) }
+ let(:public_project_second_user) { create(:project, :public, creator: second_user) }
+ let!(:private_event_second_user) { create(:event, project: private_project_second_user, author: second_user) }
+ let!(:internal_event_second_user) { create(:event, project: internal_project_second_user, author: second_user) }
+ let!(:public_event_second_user) { create(:event, project: public_project_second_user, author: second_user) }
+
+ it 'includes events from all users', :aggregate_failures do
+ events = described_class.new(current_user, [project_owner, second_user], nil, params).execute
+
+ expect(events).to include(private_event, internal_event, public_event)
+ expect(events).to include(private_event_second_user, internal_event_second_user, public_event_second_user)
+ expect(events.size).to eq(6)
+ end
+
+ it 'does not include events from users with private profile', :aggregate_failures do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(current_user, :read_user_profile, second_user).and_return(false)
+
+ events = described_class.new(current_user, [project_owner, second_user], nil, params).execute
+
+ expect(events).to include(private_event, internal_event, public_event)
+ expect(events.size).to eq(3)
+ end
+ end
+
+ context 'filter activity events' do
+ let!(:push_event) { create(:push_event, project: public_project, author: project_owner) }
+ let!(:merge_event) { create(:event, :merged, project: public_project, author: project_owner) }
+ let!(:issue_event) { create(:event, :closed, project: public_project, target: issue, author: project_owner) }
+ let!(:comment_event) { create(:event, :commented, project: public_project, author: project_owner) }
+ let!(:wiki_event) { create(:wiki_page_event, project: public_project, author: project_owner) }
+ let!(:design_event) { create(:design_event, project: public_project, author: project_owner) }
+ let!(:team_event) { create(:event, :joined, project: public_project, author: project_owner) }
+
+ it 'includes all events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::ALL)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(private_event, internal_event, public_event)
+ expect(events).to include(push_event, merge_event, issue_event, comment_event, wiki_event, design_event, team_event)
+ expect(events.size).to eq(10)
+ end
+
+ it 'only includes push events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::PUSH)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(push_event)
+ expect(events.size).to eq(1)
+ end
+
+ it 'only includes merge events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::MERGED)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(merge_event)
+ expect(events.size).to eq(1)
+ end
+
+ it 'only includes issue events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::ISSUE)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(issue_event)
+ expect(events.size).to eq(1)
+ end
+
+ it 'only includes comments events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::COMMENTS)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(comment_event)
+ expect(events.size).to eq(1)
+ end
+
+ it 'only includes wiki events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::WIKI)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(wiki_event)
+ expect(events.size).to eq(1)
+ end
it 'only includes design events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::DESIGNS)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(design_event)
+ expect(events.size).to eq(1)
+ end
+
+ it 'only includes team events', :aggregate_failures do
+ event_filter = EventFilter.new(EventFilter::TEAM)
+ events = described_class.new(current_user, project_owner, event_filter, params).execute
+
+ expect(events).to include(private_event, internal_event, public_event, team_event)
+ expect(events.size).to eq(4)
+ end
+ end
+
+ describe 'issue activity events' do
+ let(:issue) { create(:issue, project: public_project) }
+ let(:note) { create(:note_on_issue, noteable: issue, project: public_project) }
+ let!(:event_a) { create(:event, :commented, target: note, author: project_owner) }
+ let!(:event_b) { create(:event, :closed, target: issue, author: project_owner) }
+
+ it 'includes all issue related events', :aggregate_failures do
events = finder.execute
expect(events).to include(event_a)
diff --git a/spec/fixtures/api/schemas/entities/codequality_mr_diff_report.json b/spec/fixtures/api/schemas/entities/codequality_mr_diff_report.json
new file mode 100644
index 00000000000..63e0c68e9cd
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/codequality_mr_diff_report.json
@@ -0,0 +1,21 @@
+{
+ "type": "object",
+ "description": "The schema used to display codequality report in mr diff",
+ "required": ["files"],
+ "properties": {
+ "patternProperties": {
+ ".*.": {
+ "type": "array",
+ "items": {
+ "required": ["line", "description", "severity"],
+ "properties": {
+ "line": { "type": "integer" },
+ "description": { "type": "string" },
+ "severity": { "type": "string" }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/group_group_link.json b/spec/fixtures/api/schemas/entities/group_group_link.json
deleted file mode 100644
index bf94bbb3ce4..00000000000
--- a/spec/fixtures/api/schemas/entities/group_group_link.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "type": "object",
- "required": [
- "id",
- "created_at",
- "expires_at",
- "can_update",
- "can_remove",
- "access_level",
- "valid_roles"
- ],
- "properties": {
- "id": { "type": "integer" },
- "created_at": { "type": "date-time" },
- "expires_at": { "type": ["date-time", "null"] },
- "can_update": { "type": "boolean" },
- "can_remove": { "type": "boolean" },
- "access_level": {
- "type": "object",
- "required": ["integer_value", "string_value"],
- "properties": {
- "integer_value": { "type": "integer" },
- "string_value": { "type": "string" }
- }
- },
- "valid_roles": { "type": "object" },
- "shared_with_group": {
- "type": "object",
- "required": ["id", "name", "full_name", "full_path", "avatar_url", "web_url"],
- "properties": {
- "id": { "type": "integer" },
- "name": { "type": "string" },
- "full_name": { "type": "string" },
- "full_path": { "type": "string" },
- "avatar_url": { "type": ["string", "null"] },
- "web_url": { "type": "string" }
- }
- }
- }
-}
diff --git a/spec/fixtures/api/schemas/entities/member.json b/spec/fixtures/api/schemas/entities/member.json
index e8b40745803..03b1872632e 100644
--- a/spec/fixtures/api/schemas/entities/member.json
+++ b/spec/fixtures/api/schemas/entities/member.json
@@ -9,7 +9,8 @@
"source",
"valid_roles",
"can_update",
- "can_remove"
+ "can_remove",
+ "is_direct_member"
],
"properties": {
"id": { "type": "integer" },
@@ -18,6 +19,7 @@
"requested_at": { "type": ["date-time", "null"] },
"can_update": { "type": "boolean" },
"can_remove": { "type": "boolean" },
+ "is_direct_member": { "type": "boolean" },
"access_level": {
"type": "object",
"required": ["integer_value", "string_value"],
diff --git a/spec/fixtures/api/schemas/entities/member_user.json b/spec/fixtures/api/schemas/entities/member_user.json
index 983cdb7b9d9..ebd26bfaaaa 100644
--- a/spec/fixtures/api/schemas/entities/member_user.json
+++ b/spec/fixtures/api/schemas/entities/member_user.json
@@ -9,6 +9,7 @@
"web_url": { "type": "string" },
"blocked": { "type": "boolean" },
"two_factor_enabled": { "type": "boolean" },
+ "availability": { "type": ["string", "null"] },
"status": {
"type": "object",
"required": ["emoji"],
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_composer_details.json b/spec/fixtures/api/schemas/graphql/packages/package_composer_details.json
deleted file mode 100644
index bcf64a6e567..00000000000
--- a/spec/fixtures/api/schemas/graphql/packages/package_composer_details.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "type": "object",
- "allOf": [{ "$ref": "./package_details.json" }],
- "properties": {
- "target_sha": {
- "type": "string"
- },
- "composer_json": {
- "type": "object"
- }
- }
-}
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_composer_metadata.json b/spec/fixtures/api/schemas/graphql/packages/package_composer_metadata.json
new file mode 100644
index 00000000000..db9b25889be
--- /dev/null
+++ b/spec/fixtures/api/schemas/graphql/packages/package_composer_metadata.json
@@ -0,0 +1,21 @@
+{
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["targetSha", "composerJson"],
+ "properties": {
+ "targetSha": {
+ "type": "string"
+ },
+ "composerJson": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["name", "type", "license", "version"],
+ "properties": {
+ "name": { "type": "string" },
+ "type": { "type": "string" },
+ "license": { "type": "string" },
+ "version": { "type": "string" }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
index 4f90285183c..d2e2e65db54 100644
--- a/spec/fixtures/api/schemas/graphql/packages/package_details.json
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -1,5 +1,10 @@
{
"type": "object",
+ "additionalProperties": false,
+ "required": [
+ "id", "name", "createdAt", "updatedAt", "version", "packageType",
+ "project", "tags", "pipelines", "versions", "metadata"
+ ],
"properties": {
"id": {
"type": "string"
@@ -16,21 +21,46 @@
"version": {
"type": ["string", "null"]
},
- "package_type": {
+ "packageType": {
"type": ["string"],
"enum": ["MAVEN", "NPM", "CONAN", "NUGET", "PYPI", "COMPOSER", "GENERIC", "GOLANG", "DEBIAN"]
},
"tags": {
- "type": "object"
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pageInfo": { "type": "object" },
+ "edges": { "type": "array" },
+ "nodes": { "type": "array" }
+ }
},
"project": {
"type": "object"
},
"pipelines": {
- "type": "object"
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pageInfo": { "type": "object" },
+ "count": { "type": "integer" },
+ "edges": { "type": "array" },
+ "nodes": { "type": "array" }
+ }
},
"versions": {
- "type": "object"
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pageInfo": { "type": "object" },
+ "edges": { "type": "array" },
+ "nodes": { "type": "array" }
+ }
+ },
+ "metadata": {
+ "anyOf": [
+ { "$ref": "./package_composer_metadata.json" },
+ { "type": "null" }
+ ]
}
}
}
diff --git a/spec/fixtures/api/schemas/group_group_links.json b/spec/fixtures/api/schemas/group_group_links.json
deleted file mode 100644
index f8b4e7f035b..00000000000
--- a/spec/fixtures/api/schemas/group_group_links.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "type": "array",
- "items": {
- "$ref": "entities/group_group_link.json"
- }
-}
diff --git a/spec/fixtures/api/schemas/group_link/group_group_link.json b/spec/fixtures/api/schemas/group_link/group_group_link.json
new file mode 100644
index 00000000000..bfca5c885e3
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_link/group_group_link.json
@@ -0,0 +1,16 @@
+{
+ "type": "object",
+ "allOf": [
+ { "$ref": "group_link.json" },
+ {
+ "required": [
+ "can_update",
+ "can_remove"
+ ],
+ "properties": {
+ "can_update": { "type": "boolean" },
+ "can_remove": { "type": "boolean" }
+ }
+ }
+ ]
+}
diff --git a/spec/fixtures/api/schemas/group_link/group_group_links.json b/spec/fixtures/api/schemas/group_link/group_group_links.json
new file mode 100644
index 00000000000..2c0bf20f524
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_link/group_group_links.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "group_group_link.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/group_link/group_link.json b/spec/fixtures/api/schemas/group_link/group_link.json
new file mode 100644
index 00000000000..300790728a8
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_link/group_link.json
@@ -0,0 +1,38 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "created_at",
+ "expires_at",
+ "access_level",
+ "valid_roles"
+ ],
+ "properties": {
+ "id": { "type": "integer" },
+ "created_at": { "type": "date-time" },
+ "expires_at": { "type": ["date-time", "null"] },
+ "access_level": {
+ "type": "object",
+ "required": ["integer_value", "string_value"],
+ "properties": {
+ "integer_value": { "type": "integer" },
+ "string_value": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "valid_roles": { "type": "object" },
+ "shared_with_group": {
+ "type": "object",
+ "required": ["id", "name", "full_name", "full_path", "avatar_url", "web_url"],
+ "properties": {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "full_name": { "type": "string" },
+ "full_path": { "type": "string" },
+ "avatar_url": { "type": ["string", "null"] },
+ "web_url": { "type": "string" }
+ },
+ "additionalProperties": false
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/group_link/project_group_link.json b/spec/fixtures/api/schemas/group_link/project_group_link.json
new file mode 100644
index 00000000000..bfca5c885e3
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_link/project_group_link.json
@@ -0,0 +1,16 @@
+{
+ "type": "object",
+ "allOf": [
+ { "$ref": "group_link.json" },
+ {
+ "required": [
+ "can_update",
+ "can_remove"
+ ],
+ "properties": {
+ "can_update": { "type": "boolean" },
+ "can_remove": { "type": "boolean" }
+ }
+ }
+ ]
+}
diff --git a/spec/fixtures/api/schemas/group_link/project_group_links.json b/spec/fixtures/api/schemas/group_link/project_group_links.json
new file mode 100644
index 00000000000..fc024d67f36
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_link/project_group_links.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "project_group_link.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/job.json b/spec/fixtures/api/schemas/public_api/v4/job.json
index c038ae0a664..b50479841a9 100644
--- a/spec/fixtures/api/schemas/public_api/v4/job.json
+++ b/spec/fixtures/api/schemas/public_api/v4/job.json
@@ -18,6 +18,7 @@
"web_url",
"artifacts",
"artifacts_expire_at",
+ "tag_list",
"runner"
],
"properties": {
@@ -53,6 +54,9 @@
]
},
"artifacts_expire_at": { "type": ["null", "string"] },
+ "tag_list": {
+ "type": "array"
+ },
"runner": {
"oneOf": [
{ "type": "null" },
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index aff4b1aae23..100d17cc16e 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -170,6 +170,8 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Ignores invalid: <%= User.reference_prefix %>fake_user
- Ignored in code: `<%= user.to_reference %>`
- Ignored in links: [Link to <%= user.to_reference %>](#user-link)
+- Ignored when backslash escaped: \<%= user.to_reference %>
+- Ignored when backslash escaped: \<%= group.to_reference %>
- Link to user by reference: [User](<%= user.to_reference %>)
#### IssueReferenceFilter
@@ -178,6 +180,7 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Issue in another project: <%= xissue.to_reference(project) %>
- Ignored in code: `<%= issue.to_reference %>`
- Ignored in links: [Link to <%= issue.to_reference %>](#issue-link)
+- Ignored when backslash escaped: \<%= issue.to_reference %>
- Issue by URL: <%= urls.project_issue_url(issue.project, issue) %>
- Link to issue by reference: [Issue](<%= issue.to_reference %>)
- Link to issue by URL: [Issue](<%= urls.project_issue_url(issue.project, issue) %>)
@@ -188,6 +191,7 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Merge request in another project: <%= xmerge_request.to_reference(project) %>
- Ignored in code: `<%= merge_request.to_reference %>`
- Ignored in links: [Link to <%= merge_request.to_reference %>](#merge-request-link)
+- Ignored when backslash escaped: \<%= merge_request.to_reference %>
- Merge request by URL: <%= urls.project_merge_request_url(merge_request.project, merge_request) %>
- Link to merge request by reference: [Merge request](<%= merge_request.to_reference %>)
- Link to merge request by URL: [Merge request](<%= urls.project_merge_request_url(merge_request.project, merge_request) %>)
@@ -198,6 +202,7 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Snippet in another project: <%= xsnippet.to_reference(project) %>
- Ignored in code: `<%= snippet.to_reference %>`
- Ignored in links: [Link to <%= snippet.to_reference %>](#snippet-link)
+- Ignored when backslash escaped: \<%= snippet.to_reference %>
- Snippet by URL: <%= urls.project_snippet_url(snippet.project, snippet) %>
- Link to snippet by reference: [Snippet](<%= snippet.to_reference %>)
- Link to snippet by URL: [Snippet](<%= urls.project_snippet_url(snippet.project, snippet) %>)
@@ -229,6 +234,7 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Label by name in quotes: <%= label.to_reference(format: :name) %>
- Ignored in code: `<%= simple_label.to_reference %>`
- Ignored in links: [Link to <%= simple_label.to_reference %>](#label-link)
+- Ignored when backslash escaped: \<%= simple_label.to_reference %>
- Link to label by reference: [Label](<%= label.to_reference %>)
#### MilestoneReferenceFilter
@@ -239,6 +245,7 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Milestone in another project: <%= xmilestone.to_reference(project) %>
- Ignored in code: `<%= simple_milestone.to_reference %>`
- Ignored in links: [Link to <%= simple_milestone.to_reference %>](#milestone-link)
+- Ignored when backslash escaped: \<%= simple_milestone.to_reference %>
- Milestone by URL: <%= urls.milestone_url(milestone) %>
- Link to milestone by URL: [Milestone](<%= milestone.to_reference %>)
- Group milestone by name: <%= Milestone.reference_prefix %><%= group_milestone.name %>
@@ -250,6 +257,7 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Alert in another project: <%= xalert.to_reference(project) %>
- Ignored in code: `<%= alert.to_reference %>`
- Ignored in links: [Link to <%= alert.to_reference %>](#alert-link)
+- Ignored when backslash escaped: \<%= alert.to_reference %>
- Alert by URL: <%= alert.details_url %>
- Link to alert by reference: [Alert](<%= alert.to_reference %>)
- Link to alert by URL: [Alert](<%= alert.details_url %>)
@@ -350,3 +358,17 @@ For details see the [Mermaid official page][mermaid].
[mermaid]: https://mermaidjs.github.io/ "Mermaid website"
+### PLantUML
+
+```plantuml
+Bob -> Sara : Hello
+```
+
+### Kroki
+
+```nomnoml
+[Pirate|eyeCount: Int|raid();pillage()|
+ [beard]--[parrot]
+ [beard]-:>[foul mouth]
+]
+```
diff --git a/spec/fixtures/packages/composer/package.json b/spec/fixtures/packages/composer/package.json
new file mode 100644
index 00000000000..0967ef424bc
--- /dev/null
+++ b/spec/fixtures/packages/composer/package.json
@@ -0,0 +1 @@
+{}
diff --git a/spec/fixtures/packages/debian/distribution/Packages b/spec/fixtures/packages/debian/distribution/Packages
new file mode 100644
index 00000000000..d2d8af553d7
--- /dev/null
+++ b/spec/fixtures/packages/debian/distribution/Packages
@@ -0,0 +1,2 @@
+Package: example-package
+Description: This is an incomplete Packages file
diff --git a/spec/fixtures/packages/debian/distribution/Release b/spec/fixtures/packages/debian/distribution/Release
new file mode 100644
index 00000000000..a2d62c45645
--- /dev/null
+++ b/spec/fixtures/packages/debian/distribution/Release
@@ -0,0 +1 @@
+Codename: fixture-distribution
diff --git a/spec/fixtures/packages/rubygems/package-0.0.1.gem b/spec/fixtures/packages/rubygems/package-0.0.1.gem
new file mode 100644
index 00000000000..2143ef408ac
--- /dev/null
+++ b/spec/fixtures/packages/rubygems/package-0.0.1.gem
Binary files differ
diff --git a/spec/fixtures/packages/rubygems/package.gemspec b/spec/fixtures/packages/rubygems/package.gemspec
new file mode 100644
index 00000000000..bb87c47f5dc
--- /dev/null
+++ b/spec/fixtures/packages/rubygems/package.gemspec
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |s|
+ s.name = %q{package}
+ s.authors = ["Tanuki Steve"]
+ s.version = "0.0.1"
+ s.date = %q{2011-09-29}
+ s.summary = %q{package is the best}
+ s.files = [
+ "lib/package.rb"
+ ]
+ s.required_ruby_version = '>= 2.7.0'
+ s.rubygems_version = '>= 1.8.11'
+ s.require_paths = ["lib"]
+end
diff --git a/spec/fixtures/pipeline_artifacts/code_quality_mr_diff.json b/spec/fixtures/pipeline_artifacts/code_quality_mr_diff.json
new file mode 100644
index 00000000000..c3ee2bc4cac
--- /dev/null
+++ b/spec/fixtures/pipeline_artifacts/code_quality_mr_diff.json
@@ -0,0 +1,23 @@
+{
+ "files": {
+ "file_a.rb": [
+ {
+ "line": 10,
+ "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
+ "severity": "major"
+ },
+ {
+ "line": 10,
+ "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
+ "severity": "minor"
+ }
+ ],
+ "file_b.rb": [
+ {
+ "line": 10,
+ "description": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count.",
+ "severity": "minor"
+ }
+ ]
+ }
+}
diff --git a/spec/fixtures/security_reports/master/gl-sast-report.json b/spec/fixtures/security_reports/master/gl-sast-report.json
new file mode 100644
index 00000000000..98bb15e349f
--- /dev/null
+++ b/spec/fixtures/security_reports/master/gl-sast-report.json
@@ -0,0 +1,983 @@
+{
+ "version": "1.2",
+ "vulnerabilities": [
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "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"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 1,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2"
+ },
+ "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"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 47,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 41,
+ "end_line": 41,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken1"
+ },
+ "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"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 41,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 11,
+ "end_line": 11
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 11,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 12,
+ "end_line": 12
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 12,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 13,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 14,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Pickle library appears to be in use, possible security issue.",
+ "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 15,
+ "end_line": 15
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B301",
+ "value": "B301"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 15,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Cipher with no integrity",
+ "message": "Cipher with no integrity",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-CIPHER_INTEGRITY",
+ "value": "CIPHER_INTEGRITY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "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"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 14,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10
+ },
+ "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"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 10,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 22,
+ "end_line": 22
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B106",
+ "value": "B106",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 22,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'root'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 5,
+ "end_line": 5
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 5,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: ''",
+ "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 13,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 23,
+ "end_line": 23
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 23,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 24,
+ "end_line": 24
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 24,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 7,
+ "end_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
+ "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B602",
+ "value": "B602",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 1,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 7,
+ "end_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with loads module.",
+ "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "flawfinder_func_name",
+ "name": "Flawfinder - char",
+ "value": "char"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 4,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
+ "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
+ "confidence": "Low",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "flawfinder_func_name",
+ "name": "Flawfinder - fopen",
+ "value": "fopen"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-362",
+ "value": "362",
+ "url": "https://cwe.mitre.org/data/definitions/362.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 8,
+ "url": "https://cwe.mitre.org/data/definitions/362.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "flawfinder_func_name",
+ "name": "Flawfinder - char",
+ "value": "char"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 6,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
+ "confidence": "Low",
+ "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "flawfinder_func_name",
+ "name": "Flawfinder - strcpy",
+ "value": "strcpy"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 7,
+ "url": "https://cwe.mitre.org/data/definitions/120.html",
+ "tool": "flawfinder"
+ }
+ ],
+ "remediations": [],
+ "scan": {
+ "scanner": {
+ "id": "gosec",
+ "name": "Gosec",
+ "url": "https://github.com/securego/gosec",
+ "vendor": {
+ "name": "GitLab"
+ },
+ "version": "2.3.0"
+ },
+ "type": "sast",
+ "status": "success",
+ "start_time": "placeholder-value",
+ "end_time": "placeholder-value"
+ }
+}
diff --git a/spec/fixtures/security_reports/master/gl-secret-detection-report.json b/spec/fixtures/security_reports/master/gl-secret-detection-report.json
new file mode 100644
index 00000000000..f0250ec9145
--- /dev/null
+++ b/spec/fixtures/security_reports/master/gl-secret-detection-report.json
@@ -0,0 +1,33 @@
+{
+ "version": "3.0",
+ "vulnerabilities": [
+ {
+ "id": "27d2322d519c94f803ffed1cf6d14e455df97e5a0668e229eb853fdb0d277d2c",
+ "category": "secret_detection",
+ "name": "AWS API key",
+ "message": "AWS API key",
+ "description": "Historic AWS secret has been found in commit 0830d9e4c0b43c0533cde798841b499e9df0653a.",
+ "cve": "aws-key.py:e275768c071cf6a6ea70a70b40f27c98debfe26bfe623c1539ec21c4478c6fca:AWS",
+ "severity": "Critical",
+ "confidence": "Unknown",
+ "scanner": {
+ "id": "gitleaks",
+ "name": "Gitleaks"
+ },
+ "location": {
+ "file": "aws-key.py",
+ "dependency": {
+ "package": {}
+ }
+ },
+ "identifiers": [
+ {
+ "type": "gitleaks_rule_id",
+ "name": "Gitleaks rule ID AWS",
+ "value": "AWS"
+ }
+ ]
+ }
+ ],
+ "remediations": []
+}
diff --git a/spec/fixtures/whats_new/invalid.yml b/spec/fixtures/whats_new/invalid.yml
index 0e588efaf8f..a3342be0f24 100644
--- a/spec/fixtures/whats_new/invalid.yml
+++ b/spec/fixtures/whats_new/invalid.yml
@@ -13,7 +13,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Starter]
+ packages: [Free]
url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/12_10/jwt-vault-1.png
published_at: 2020-04-22
diff --git a/spec/fixtures/whats_new/valid.yml b/spec/fixtures/whats_new/valid.yml
index cbe9d666357..ec465f47989 100644
--- a/spec/fixtures/whats_new/valid.yml
+++ b/spec/fixtures/whats_new/valid.yml
@@ -13,7 +13,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Starter]
+ packages: [Free]
url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/12_10/jwt-vault-1.png
published_at: 2020-04-22
diff --git a/spec/frontend/__helpers__/emoji.js b/spec/frontend/__helpers__/emoji.js
index ea6613b53c9..9f9134f6f63 100644
--- a/spec/frontend/__helpers__/emoji.js
+++ b/spec/frontend/__helpers__/emoji.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
+import axios from '~/lib/utils/axios_utils';
export const emojiFixtureMap = {
atom: {
@@ -29,10 +29,6 @@ export const emojiFixtureMap = {
unicodeVersion: '6.0',
description: 'white question mark ornament',
},
-
- // used for regression tests
- // black_heart MUST come before heart
- // custard MUST come before star
black_heart: {
moji: '🖤',
unicodeVersion: '1.1',
@@ -55,34 +51,18 @@ export const emojiFixtureMap = {
},
};
-Object.keys(emojiFixtureMap).forEach((k) => {
- emojiFixtureMap[k].name = k;
- if (!emojiFixtureMap[k].aliases) {
- emojiFixtureMap[k].aliases = [];
- }
-});
+export const mockEmojiData = Object.keys(emojiFixtureMap).reduce((acc, k) => {
+ const { moji: e, unicodeVersion: u, category: c, description: d } = emojiFixtureMap[k];
+ acc[k] = { name: k, e, u, c, d };
-export async function initEmojiMock() {
- const emojiData = Object.fromEntries(
- Object.values(emojiFixtureMap).map((m) => {
- const { name: n, moji: e, unicodeVersion: u, category: c, description: d } = m;
- return [n, { c, e, d, u }];
- }),
- );
+ return acc;
+}, {});
+export async function initEmojiMock(mockData = mockEmojiData) {
const mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(emojiData));
+ mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(mockData));
await initEmojiMap();
return mock;
}
-
-export function describeEmojiFields(label, tests) {
- describe.each`
- field | accessor
- ${'name'} | ${(e) => e.name}
- ${'alias'} | ${(e) => e.aliases[0]}
- ${'description'} | ${(e) => e.description}
- `(label, tests);
-}
diff --git a/spec/frontend/__helpers__/fake_date.js b/spec/frontend/__helpers__/fake_date.js
deleted file mode 100644
index 5391ae04797..00000000000
--- a/spec/frontend/__helpers__/fake_date.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// Frida Kahlo's birthday (6 = July)
-export const DEFAULT_ARGS = [2020, 6, 6];
-
-const RealDate = Date;
-
-const isMocked = (val) => Boolean(val.mock);
-
-export const createFakeDateClass = (ctorDefault) => {
- const FakeDate = new Proxy(RealDate, {
- construct: (target, argArray) => {
- const ctorArgs = argArray.length ? argArray : ctorDefault;
-
- return new RealDate(...ctorArgs);
- },
- apply: (target, thisArg, argArray) => {
- const ctorArgs = argArray.length ? argArray : ctorDefault;
-
- return new RealDate(...ctorArgs).toString();
- },
- // We want to overwrite the default 'now', but only if it's not already mocked
- get: (target, prop) => {
- if (prop === 'now' && !isMocked(target[prop])) {
- return () => new RealDate(...ctorDefault).getTime();
- }
-
- return target[prop];
- },
- getPrototypeOf: (target) => {
- return target.prototype;
- },
- // We need to be able to set props so that `jest.spyOn` will work.
- set: (target, prop, value) => {
- // eslint-disable-next-line no-param-reassign
- target[prop] = value;
- return true;
- },
- });
-
- return FakeDate;
-};
-
-export const useFakeDate = (...args) => {
- const FakeDate = createFakeDateClass(args.length ? args : DEFAULT_ARGS);
- global.Date = FakeDate;
-};
-
-export const useRealDate = () => {
- global.Date = RealDate;
-};
diff --git a/spec/frontend/__helpers__/fake_date/fake_date.js b/spec/frontend/__helpers__/fake_date/fake_date.js
new file mode 100644
index 00000000000..bc088ad96b6
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/fake_date.js
@@ -0,0 +1,60 @@
+// Frida Kahlo's birthday (6 = July)
+const DEFAULT_ARGS = [2020, 6, 6];
+
+const RealDate = Date;
+
+const isMocked = (val) => Boolean(val.mock);
+
+const createFakeDateClass = (ctorDefaultParam = []) => {
+ const ctorDefault = ctorDefaultParam.length ? ctorDefaultParam : DEFAULT_ARGS;
+
+ const FakeDate = new Proxy(RealDate, {
+ construct: (target, argArray) => {
+ const ctorArgs = argArray.length ? argArray : ctorDefault;
+
+ return new RealDate(...ctorArgs);
+ },
+ apply: (target, thisArg, argArray) => {
+ const ctorArgs = argArray.length ? argArray : ctorDefault;
+
+ return new RealDate(...ctorArgs).toString();
+ },
+ // We want to overwrite the default 'now', but only if it's not already mocked
+ get: (target, prop) => {
+ if (prop === 'now' && !isMocked(target[prop])) {
+ return () => new RealDate(...ctorDefault).getTime();
+ }
+
+ return target[prop];
+ },
+ getPrototypeOf: (target) => {
+ return target.prototype;
+ },
+ // We need to be able to set props so that `jest.spyOn` will work.
+ set: (target, prop, value) => {
+ // eslint-disable-next-line no-param-reassign
+ target[prop] = value;
+ return true;
+ },
+ });
+
+ return FakeDate;
+};
+
+const setGlobalDateToFakeDate = (...args) => {
+ const FakeDate = createFakeDateClass(args);
+ global.Date = FakeDate;
+};
+
+const setGlobalDateToRealDate = () => {
+ global.Date = RealDate;
+};
+
+// We use commonjs so that the test environment module can pick this up
+// eslint-disable-next-line import/no-commonjs
+module.exports = {
+ setGlobalDateToFakeDate,
+ setGlobalDateToRealDate,
+ createFakeDateClass,
+ RealDate,
+};
diff --git a/spec/frontend/__helpers__/fake_date/fake_date_spec.js b/spec/frontend/__helpers__/fake_date/fake_date_spec.js
new file mode 100644
index 00000000000..730765e52d2
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/fake_date_spec.js
@@ -0,0 +1,33 @@
+import { createFakeDateClass } from './fake_date';
+
+describe('spec/helpers/fake_date', () => {
+ describe('createFakeDateClass', () => {
+ let FakeDate;
+
+ beforeEach(() => {
+ FakeDate = createFakeDateClass();
+ });
+
+ it('should use default args', () => {
+ expect(new FakeDate()).toMatchInlineSnapshot(`2020-07-06T00:00:00.000Z`);
+ });
+
+ it('should use default args when called as a function', () => {
+ expect(FakeDate()).toMatchInlineSnapshot(
+ `"Mon Jul 06 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"`,
+ );
+ });
+
+ it('should have deterministic now()', () => {
+ expect(FakeDate.now()).toMatchInlineSnapshot(`1593993600000`);
+ });
+
+ it('should be instanceof Date', () => {
+ expect(new FakeDate()).toBeInstanceOf(Date);
+ });
+
+ it('should be instanceof self', () => {
+ expect(new FakeDate()).toBeInstanceOf(FakeDate);
+ });
+ });
+});
diff --git a/spec/frontend/__helpers__/fake_date/index.js b/spec/frontend/__helpers__/fake_date/index.js
new file mode 100644
index 00000000000..3d1b124ce79
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/index.js
@@ -0,0 +1,2 @@
+export * from './fake_date';
+export * from './jest';
diff --git a/spec/frontend/__helpers__/fake_date/jest.js b/spec/frontend/__helpers__/fake_date/jest.js
new file mode 100644
index 00000000000..65e45619049
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/jest.js
@@ -0,0 +1,41 @@
+import { createJestExecutionWatcher } from '../jest_execution_watcher';
+import { RealDate, createFakeDateClass } from './fake_date';
+
+const throwInsideExecutionError = (fnName) => {
+ throw new Error(`Cannot call "${fnName}" during test execution (i.e. within "it", "beforeEach", "beforeAll", etc.).
+
+Instead, please move the call to "${fnName}" inside the "describe" block itself.
+
+ describe('', () => {
+ + ${fnName}();
+
+ it('', () => {
+ - ${fnName}();
+ })
+ })
+`);
+};
+
+const isExecutingTest = createJestExecutionWatcher();
+
+export const useDateInScope = (fnName, factory) => {
+ if (isExecutingTest()) {
+ throwInsideExecutionError(fnName);
+ }
+
+ let origDate;
+
+ beforeAll(() => {
+ origDate = global.Date;
+ global.Date = factory();
+ });
+
+ afterAll(() => {
+ global.Date = origDate;
+ });
+};
+
+export const useFakeDate = (...args) =>
+ useDateInScope('useFakeDate', () => createFakeDateClass(args));
+
+export const useRealDate = () => useDateInScope('useRealDate', () => RealDate);
diff --git a/spec/frontend/__helpers__/fake_date_spec.js b/spec/frontend/__helpers__/fake_date_spec.js
deleted file mode 100644
index b3ed13e238a..00000000000
--- a/spec/frontend/__helpers__/fake_date_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { createFakeDateClass, DEFAULT_ARGS, useRealDate } from './fake_date';
-
-describe('spec/helpers/fake_date', () => {
- describe('createFakeDateClass', () => {
- let FakeDate;
-
- beforeAll(() => {
- useRealDate();
- });
-
- beforeEach(() => {
- FakeDate = createFakeDateClass(DEFAULT_ARGS);
- });
-
- it('should use default args', () => {
- expect(new FakeDate()).toMatchInlineSnapshot(`2020-07-06T00:00:00.000Z`);
- });
-
- it('should use default args when called as a function', () => {
- expect(FakeDate()).toMatchInlineSnapshot(
- `"Mon Jul 06 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"`,
- );
- });
-
- it('should have deterministic now()', () => {
- expect(FakeDate.now()).toMatchInlineSnapshot(`1593993600000`);
- });
-
- it('should be instanceof Date', () => {
- expect(new FakeDate()).toBeInstanceOf(Date);
- });
-
- it('should be instanceof self', () => {
- expect(new FakeDate()).toBeInstanceOf(FakeDate);
- });
- });
-});
diff --git a/spec/frontend/__helpers__/graphql_helpers.js b/spec/frontend/__helpers__/graphql_helpers.js
new file mode 100644
index 00000000000..63123aa046f
--- /dev/null
+++ b/spec/frontend/__helpers__/graphql_helpers.js
@@ -0,0 +1,14 @@
+/**
+ * Returns a clone of the given object with all __typename keys omitted,
+ * including deeply nested ones.
+ *
+ * Only works with JSON-serializable objects.
+ *
+ * @param {object} An object with __typename keys (e.g., a GraphQL response)
+ * @returns {object} A new object with no __typename keys
+ */
+export const stripTypenames = (object) => {
+ return JSON.parse(
+ JSON.stringify(object, (key, value) => (key === '__typename' ? undefined : value)),
+ );
+};
diff --git a/spec/frontend/__helpers__/graphql_helpers_spec.js b/spec/frontend/__helpers__/graphql_helpers_spec.js
new file mode 100644
index 00000000000..dd23fbbf4e9
--- /dev/null
+++ b/spec/frontend/__helpers__/graphql_helpers_spec.js
@@ -0,0 +1,23 @@
+import { stripTypenames } from './graphql_helpers';
+
+describe('stripTypenames', () => {
+ it.each`
+ input | expected
+ ${{}} | ${{}}
+ ${{ __typename: 'Foo' }} | ${{}}
+ ${{ bar: 'bar', __typename: 'Foo' }} | ${{ bar: 'bar' }}
+ ${{ bar: { __typename: 'Bar' }, __typename: 'Foo' }} | ${{ bar: {} }}
+ ${{ bar: [{ __typename: 'Bar' }], __typename: 'Foo' }} | ${{ bar: [{}] }}
+ ${[]} | ${[]}
+ ${[{ __typename: 'Foo' }]} | ${[{}]}
+ ${[{ bar: [{ a: 1, __typename: 'Bar' }] }]} | ${[{ bar: [{ a: 1 }] }]}
+ `('given $input returns $expected, with all __typename keys removed', ({ input, expected }) => {
+ const actual = stripTypenames(input);
+ expect(actual).toEqual(expected);
+ expect(input).not.toBe(actual);
+ });
+
+ it('given null returns null', () => {
+ expect(stripTypenames(null)).toEqual(null);
+ });
+});
diff --git a/spec/frontend/__helpers__/init_vue_mr_page_helper.js b/spec/frontend/__helpers__/init_vue_mr_page_helper.js
index b9aed63d0f6..ee01e9e6268 100644
--- a/spec/frontend/__helpers__/init_vue_mr_page_helper.js
+++ b/spec/frontend/__helpers__/init_vue_mr_page_helper.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
-import initMRPage from '~/mr_notes';
import axios from '~/lib/utils/axios_utils';
-import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data';
+import initMRPage from '~/mr_notes';
import diffFileMockData from '../diffs/mock_data/diff_file';
+import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data';
export default function initVueMRPage() {
const mrTestEl = document.createElement('div');
diff --git a/spec/frontend/__helpers__/jest_execution_watcher.js b/spec/frontend/__helpers__/jest_execution_watcher.js
new file mode 100644
index 00000000000..0fc3d330ec3
--- /dev/null
+++ b/spec/frontend/__helpers__/jest_execution_watcher.js
@@ -0,0 +1,12 @@
+export const createJestExecutionWatcher = () => {
+ let isExecuting = false;
+
+ beforeAll(() => {
+ isExecuting = true;
+ });
+ afterAll(() => {
+ isExecuting = false;
+ });
+
+ return () => isExecuting;
+};
diff --git a/spec/frontend/__helpers__/stub_component.js b/spec/frontend/__helpers__/stub_component.js
index 45550450517..96fe3a8bc45 100644
--- a/spec/frontend/__helpers__/stub_component.js
+++ b/spec/frontend/__helpers__/stub_component.js
@@ -1,7 +1,32 @@
+/**
+ * Returns a new object with keys pointing to stubbed methods
+ *
+ * This is helpful for stubbing components like GlModal where it's supported
+ * in the API to call `.show()` and `.hide()` ([Bootstrap Vue docs][1]).
+ *
+ * [1]: https://bootstrap-vue.org/docs/components/modal#using-show-hide-and-toggle-component-methods
+ *
+ * @param {Object} methods - Object whose keys will be in the returned object.
+ */
+const createStubbedMethods = (methods = {}) => {
+ if (!methods) {
+ return {};
+ }
+
+ return Object.keys(methods).reduce(
+ (acc, key) =>
+ Object.assign(acc, {
+ [key]: () => {},
+ }),
+ {},
+ );
+};
+
export function stubComponent(Component, options = {}) {
return {
props: Component.props,
model: Component.model,
+ methods: createStubbedMethods(Component.methods),
// Do not render any slots/scoped slots except default
// This differs from VTU behavior which renders all slots
template: '<div><slot></slot></div>',
diff --git a/spec/frontend/__mocks__/@gitlab/ui.js b/spec/frontend/__mocks__/@gitlab/ui.js
index 7cdecefab05..ecd67247362 100644
--- a/spec/frontend/__mocks__/@gitlab/ui.js
+++ b/spec/frontend/__mocks__/@gitlab/ui.js
@@ -38,7 +38,9 @@ jest.mock('@gitlab/ui/dist/components/base/popover/popover.js', () => ({
required: false,
default: () => [],
},
- ...Object.fromEntries(['target', 'triggers', 'placement'].map((prop) => [prop, {}])),
+ ...Object.fromEntries(
+ ['target', 'triggers', 'placement', 'boundary', 'container'].map((prop) => [prop, {}]),
+ ),
},
render(h) {
return h(
diff --git a/spec/frontend/access_tokens/components/expires_at_field_spec.js b/spec/frontend/access_tokens/components/expires_at_field_spec.js
index cd235d0afa5..4a2815e6931 100644
--- a/spec/frontend/access_tokens/components/expires_at_field_spec.js
+++ b/spec/frontend/access_tokens/components/expires_at_field_spec.js
@@ -1,10 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import { useFakeDate } from 'helpers/fake_date';
import ExpiresAtField from '~/access_tokens/components/expires_at_field.vue';
describe('~/access_tokens/components/expires_at_field', () => {
- useFakeDate();
-
let wrapper;
const createComponent = () => {
diff --git a/spec/frontend/actioncable_connection_monitor_spec.js b/spec/frontend/actioncable_connection_monitor_spec.js
new file mode 100644
index 00000000000..c68eb53acde
--- /dev/null
+++ b/spec/frontend/actioncable_connection_monitor_spec.js
@@ -0,0 +1,79 @@
+import ConnectionMonitor from '~/actioncable_connection_monitor';
+
+describe('ConnectionMonitor', () => {
+ let monitor;
+
+ beforeEach(() => {
+ monitor = new ConnectionMonitor({});
+ });
+
+ describe('#getPollInterval', () => {
+ beforeEach(() => {
+ Math.originalRandom = Math.random;
+ });
+ afterEach(() => {
+ Math.random = Math.originalRandom;
+ });
+
+ const { staleThreshold, reconnectionBackoffRate } = ConnectionMonitor;
+ const backoffFactor = 1 + reconnectionBackoffRate;
+ const ms = 1000;
+
+ it('uses exponential backoff', () => {
+ Math.random = () => 0;
+
+ monitor.reconnectAttempts = 0;
+ expect(monitor.getPollInterval()).toEqual(staleThreshold * ms);
+
+ monitor.reconnectAttempts = 1;
+ expect(monitor.getPollInterval()).toEqual(staleThreshold * backoffFactor * ms);
+
+ monitor.reconnectAttempts = 2;
+ expect(monitor.getPollInterval()).toEqual(
+ staleThreshold * backoffFactor * backoffFactor * ms,
+ );
+ });
+
+ it('caps exponential backoff after some number of reconnection attempts', () => {
+ Math.random = () => 0;
+ monitor.reconnectAttempts = 42;
+ const cappedPollInterval = monitor.getPollInterval();
+
+ monitor.reconnectAttempts = 9001;
+ expect(monitor.getPollInterval()).toEqual(cappedPollInterval);
+ });
+
+ it('uses 100% jitter when 0 reconnection attempts', () => {
+ Math.random = () => 0;
+ expect(monitor.getPollInterval()).toEqual(staleThreshold * ms);
+
+ Math.random = () => 0.5;
+ expect(monitor.getPollInterval()).toEqual(staleThreshold * 1.5 * ms);
+ });
+
+ it('uses reconnectionBackoffRate for jitter when >0 reconnection attempts', () => {
+ monitor.reconnectAttempts = 1;
+
+ Math.random = () => 0.25;
+ expect(monitor.getPollInterval()).toEqual(
+ staleThreshold * backoffFactor * (1 + reconnectionBackoffRate * 0.25) * ms,
+ );
+
+ Math.random = () => 0.5;
+ expect(monitor.getPollInterval()).toEqual(
+ staleThreshold * backoffFactor * (1 + reconnectionBackoffRate * 0.5) * ms,
+ );
+ });
+
+ it('applies jitter after capped exponential backoff', () => {
+ monitor.reconnectAttempts = 9001;
+
+ Math.random = () => 0;
+ const withoutJitter = monitor.getPollInterval();
+ Math.random = () => 0.5;
+ const withJitter = monitor.getPollInterval();
+
+ expect(withJitter).toBeGreaterThan(withoutJitter);
+ });
+ });
+});
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 1a3b151afa0..d32e582e498 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,12 +1,12 @@
+import { GlModal, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlModal, GlSearchBoxByType } from '@gitlab/ui';
import AddReviewItemsModal from '~/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue';
-import getDiffWithCommit from '../../diffs/mock_data/diff_with_commit';
-import defaultState from '~/add_context_commits_modal/store/state';
-import mutations from '~/add_context_commits_modal/store/mutations';
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';
+import getDiffWithCommit from '../../diffs/mock_data/diff_with_commit';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js b/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js
index 4e65713a680..75f1cc41e23 100644
--- a/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js
+++ b/spec/frontend/add_context_commits_modal/components/review_tab_container_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ReviewTabContainer from '~/add_context_commits_modal/components/review_tab_container.vue';
import CommitItem from '~/diffs/components/commit_item.vue';
import getDiffWithCommit from '../../diffs/mock_data/diff_with_commit';
diff --git a/spec/frontend/add_context_commits_modal/store/actions_spec.js b/spec/frontend/add_context_commits_modal/store/actions_spec.js
index 3bb3cb68f56..fa4d52cbfbb 100644
--- a/spec/frontend/add_context_commits_modal/store/actions_spec.js
+++ b/spec/frontend/add_context_commits_modal/store/actions_spec.js
@@ -1,7 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
import {
setBaseConfig,
setTabIndex,
@@ -16,6 +15,7 @@ import {
resetModalState,
} from '~/add_context_commits_modal/store/actions';
import * as types from '~/add_context_commits_modal/store/mutation_types';
+import axios from '~/lib/utils/axios_utils';
describe('AddContextCommitsModalStoreActions', () => {
const contextCommitEndpoint =
diff --git a/spec/frontend/add_context_commits_modal/store/mutations_spec.js b/spec/frontend/add_context_commits_modal/store/mutations_spec.js
index 22f82570ab1..2331a4af1bc 100644
--- a/spec/frontend/add_context_commits_modal/store/mutations_spec.js
+++ b/spec/frontend/add_context_commits_modal/store/mutations_spec.js
@@ -1,6 +1,6 @@
import { TEST_HOST } from 'helpers/test_constants';
-import mutations from '~/add_context_commits_modal/store/mutations';
import * as types from '~/add_context_commits_modal/store/mutation_types';
+import mutations from '~/add_context_commits_modal/store/mutations';
import getDiffWithCommit from '../../diffs/mock_data/diff_with_commit';
describe('AddContextCommitsModalStoreMutations', () => {
diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js
index a4dcfa1a480..9c424491d04 100644
--- a/spec/frontend/admin/statistics_panel/components/app_spec.js
+++ b/spec/frontend/admin/statistics_panel/components/app_spec.js
@@ -1,12 +1,12 @@
-import Vuex from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { GlLoadingIcon } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import Vuex from 'vuex';
import StatisticsPanelApp from '~/admin/statistics_panel/components/app.vue';
import statisticsLabels from '~/admin/statistics_panel/constants';
import createStore from '~/admin/statistics_panel/store';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import mockStatistics from '../mock_data';
const localVue = createLocalVue();
diff --git a/spec/frontend/admin/statistics_panel/store/actions_spec.js b/spec/frontend/admin/statistics_panel/store/actions_spec.js
index ecbc823be12..c7481b664b3 100644
--- a/spec/frontend/admin/statistics_panel/store/actions_spec.js
+++ b/spec/frontend/admin/statistics_panel/store/actions_spec.js
@@ -1,10 +1,10 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import * as actions from '~/admin/statistics_panel/store/actions';
import * as types from '~/admin/statistics_panel/store/mutation_types';
import getInitialState from '~/admin/statistics_panel/store/state';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import mockStatistics from '../mock_data';
describe('Admin statistics panel actions', () => {
diff --git a/spec/frontend/admin/statistics_panel/store/getters_spec.js b/spec/frontend/admin/statistics_panel/store/getters_spec.js
index 152d82531ed..6cdd40b1a98 100644
--- a/spec/frontend/admin/statistics_panel/store/getters_spec.js
+++ b/spec/frontend/admin/statistics_panel/store/getters_spec.js
@@ -1,5 +1,5 @@
-import createState from '~/admin/statistics_panel/store/state';
import * as getters from '~/admin/statistics_panel/store/getters';
+import createState from '~/admin/statistics_panel/store/state';
describe('Admin statistics panel getters', () => {
let state;
diff --git a/spec/frontend/admin/statistics_panel/store/mutations_spec.js b/spec/frontend/admin/statistics_panel/store/mutations_spec.js
index 179f38d2bc5..0a3dad09c9a 100644
--- a/spec/frontend/admin/statistics_panel/store/mutations_spec.js
+++ b/spec/frontend/admin/statistics_panel/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/admin/statistics_panel/store/mutations';
import * as types from '~/admin/statistics_panel/store/mutation_types';
+import mutations from '~/admin/statistics_panel/store/mutations';
import getInitialState from '~/admin/statistics_panel/store/state';
import mockStatistics from '../mock_data';
diff --git a/spec/frontend/admin/users/components/actions/actions_spec.js b/spec/frontend/admin/users/components/actions/actions_spec.js
new file mode 100644
index 00000000000..5e232f34311
--- /dev/null
+++ b/spec/frontend/admin/users/components/actions/actions_spec.js
@@ -0,0 +1,98 @@
+import { GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { kebabCase } from 'lodash';
+import { nextTick } from 'vue';
+import Actions from '~/admin/users/components/actions';
+import SharedDeleteAction from '~/admin/users/components/actions/shared/shared_delete_action.vue';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+
+import { CONFIRMATION_ACTIONS, DELETE_ACTIONS } from '../../constants';
+
+describe('Action components', () => {
+ let wrapper;
+
+ const findDropdownItem = () => wrapper.find(GlDropdownItem);
+
+ const initComponent = ({ component, props, stubs = {} } = {}) => {
+ wrapper = shallowMount(component, {
+ propsData: {
+ ...props,
+ },
+ stubs,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('CONFIRMATION_ACTIONS', () => {
+ it.each(CONFIRMATION_ACTIONS)('renders a dropdown item for "%s"', async (action) => {
+ initComponent({
+ component: Actions[capitalizeFirstCharacter(action)],
+ props: {
+ username: 'John Doe',
+ path: '/test',
+ },
+ });
+
+ await nextTick();
+
+ const div = wrapper.find('div');
+ expect(div.attributes('data-path')).toBe('/test');
+ expect(div.attributes('data-modal-attributes')).toContain('John Doe');
+ expect(findDropdownItem().exists()).toBe(true);
+ });
+ });
+
+ describe('LINK_ACTIONS', () => {
+ it.each`
+ action | method
+ ${'Approve'} | ${'put'}
+ ${'Reject'} | ${'delete'}
+ `(
+ 'renders a dropdown item link with method "$method" for "$action"',
+ async ({ action, method }) => {
+ initComponent({
+ component: Actions[action],
+ props: {
+ path: '/test',
+ },
+ });
+
+ await nextTick();
+
+ const item = wrapper.find(GlDropdownItem);
+ expect(item.attributes('href')).toBe('/test');
+ expect(item.attributes('data-method')).toContain(method);
+ },
+ );
+ });
+
+ describe('DELETE_ACTION_COMPONENTS', () => {
+ it.each(DELETE_ACTIONS)('renders a dropdown item for "%s"', async (action) => {
+ initComponent({
+ component: Actions[capitalizeFirstCharacter(action)],
+ props: {
+ username: 'John Doe',
+ paths: {
+ delete: '/delete',
+ block: '/block',
+ },
+ },
+ stubs: { SharedDeleteAction },
+ });
+
+ await nextTick();
+
+ const sharedAction = wrapper.find(SharedDeleteAction);
+
+ expect(sharedAction.attributes('data-block-user-url')).toBe('/block');
+ expect(sharedAction.attributes('data-delete-user-url')).toBe('/delete');
+ expect(sharedAction.attributes('data-gl-modal-action')).toBe(kebabCase(action));
+ expect(sharedAction.attributes('data-username')).toBe('John Doe');
+ expect(findDropdownItem().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/admin/users/components/user_actions_spec.js b/spec/frontend/admin/users/components/user_actions_spec.js
new file mode 100644
index 00000000000..0745d961f25
--- /dev/null
+++ b/spec/frontend/admin/users/components/user_actions_spec.js
@@ -0,0 +1,158 @@
+import { GlDropdownDivider } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Actions from '~/admin/users/components/actions';
+import AdminUserActions from '~/admin/users/components/user_actions.vue';
+import { I18N_USER_ACTIONS } from '~/admin/users/constants';
+import { generateUserPaths } from '~/admin/users/utils';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+
+import { CONFIRMATION_ACTIONS, DELETE_ACTIONS, LINK_ACTIONS, LDAP, EDIT } from '../constants';
+import { users, paths } from '../mock_data';
+
+describe('AdminUserActions component', () => {
+ let wrapper;
+ const user = users[0];
+ const userPaths = generateUserPaths(paths, user.username);
+
+ const findEditButton = () => wrapper.find('[data-testid="edit"]');
+ const findActionsDropdown = () => wrapper.find('[data-testid="actions"');
+ const findDropdownDivider = () => wrapper.find(GlDropdownDivider);
+
+ const initComponent = ({ actions = [] } = {}) => {
+ wrapper = shallowMount(AdminUserActions, {
+ propsData: {
+ user: {
+ ...user,
+ actions,
+ },
+ paths,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('edit button', () => {
+ describe('when the user has an edit action attached', () => {
+ beforeEach(() => {
+ initComponent({ actions: [EDIT] });
+ });
+
+ it('renders the edit button linking to the user edit path', () => {
+ expect(findEditButton().exists()).toBe(true);
+ expect(findEditButton().attributes('href')).toBe(userPaths.edit);
+ });
+ });
+
+ describe('when there is no edit action attached to the user', () => {
+ beforeEach(() => {
+ initComponent({ actions: [] });
+ });
+
+ it('does not render the edit button linking to the user edit path', () => {
+ expect(findEditButton().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('actions dropdown', () => {
+ describe('when there are actions', () => {
+ const actions = [EDIT, ...LINK_ACTIONS];
+
+ beforeEach(() => {
+ initComponent({ actions });
+ });
+
+ it('renders the actions dropdown', () => {
+ expect(findActionsDropdown().exists()).toBe(true);
+ });
+
+ describe('when there are actions that should render as links', () => {
+ beforeEach(() => {
+ initComponent({ actions: LINK_ACTIONS });
+ });
+
+ it.each(LINK_ACTIONS)('renders an action component item for "%s"', (action) => {
+ const component = wrapper.find(Actions[capitalizeFirstCharacter(action)]);
+
+ expect(component.props('path')).toBe(userPaths[action]);
+ expect(component.text()).toBe(I18N_USER_ACTIONS[action]);
+ });
+ });
+
+ describe('when there are actions that require confirmation', () => {
+ beforeEach(() => {
+ initComponent({ actions: CONFIRMATION_ACTIONS });
+ });
+
+ it.each(CONFIRMATION_ACTIONS)('renders an action component item for "%s"', (action) => {
+ const component = wrapper.find(Actions[capitalizeFirstCharacter(action)]);
+
+ expect(component.props('username')).toBe(user.name);
+ expect(component.props('path')).toBe(userPaths[action]);
+ expect(component.text()).toBe(I18N_USER_ACTIONS[action]);
+ });
+ });
+
+ describe('when there is a LDAP action', () => {
+ beforeEach(() => {
+ initComponent({ actions: [LDAP] });
+ });
+
+ it('renders the LDAP dropdown item without a link', () => {
+ const dropdownAction = wrapper.find(`[data-testid="${LDAP}"]`);
+ expect(dropdownAction.exists()).toBe(true);
+ expect(dropdownAction.attributes('href')).toBe(undefined);
+ expect(dropdownAction.text()).toBe(I18N_USER_ACTIONS[LDAP]);
+ });
+ });
+
+ describe('when there is a delete action', () => {
+ beforeEach(() => {
+ initComponent({ actions: [LDAP, ...DELETE_ACTIONS] });
+ });
+
+ it('renders a dropdown divider', () => {
+ expect(findDropdownDivider().exists()).toBe(true);
+ });
+
+ it('only renders delete dropdown items for actions containing the word "delete"', () => {
+ const { length } = wrapper.findAll(`[data-testid*="delete-"]`);
+ expect(length).toBe(DELETE_ACTIONS.length);
+ });
+
+ it.each(DELETE_ACTIONS)('renders a delete action component item for "%s"', (action) => {
+ const component = wrapper.find(Actions[capitalizeFirstCharacter(action)]);
+
+ expect(component.props('username')).toBe(user.name);
+ expect(component.props('paths')).toEqual(userPaths);
+ expect(component.text()).toBe(I18N_USER_ACTIONS[action]);
+ });
+ });
+
+ describe('when there are no delete actions', () => {
+ it('does not render a dropdown divider', () => {
+ expect(findDropdownDivider().exists()).toBe(false);
+ });
+
+ it('does not render a delete dropdown item', () => {
+ const anyDeleteAction = wrapper.find(`[data-testid*="delete-"]`);
+ expect(anyDeleteAction.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('when there are no actions', () => {
+ beforeEach(() => {
+ initComponent({ actions: [] });
+ });
+
+ it('does not render the actions dropdown', () => {
+ expect(findActionsDropdown().exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/admin/users/components/user_avatar_spec.js b/spec/frontend/admin/users/components/user_avatar_spec.js
index ba4e83690d0..8bbfb89bec1 100644
--- a/spec/frontend/admin/users/components/user_avatar_spec.js
+++ b/spec/frontend/admin/users/components/user_avatar_spec.js
@@ -1,7 +1,10 @@
-import { GlAvatarLink, GlAvatarLabeled, GlBadge } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { GlAvatarLabeled, GlBadge, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import AdminUserAvatar from '~/admin/users/components/user_avatar.vue';
+import { LENGTH_OF_USER_NOTE_TOOLTIP } from '~/admin/users/constants';
+import { truncate } from '~/lib/utils/text_utility';
import { users, paths } from '../mock_data';
describe('AdminUserAvatar component', () => {
@@ -9,17 +12,25 @@ describe('AdminUserAvatar component', () => {
const user = users[0];
const adminUserPath = paths.adminUser;
+ const findNote = () => wrapper.find(GlIcon);
const findAvatar = () => wrapper.find(GlAvatarLabeled);
- const findAvatarLink = () => wrapper.find(GlAvatarLink);
+ const findUserLink = () => wrapper.find('.js-user-link');
const findAllBadges = () => wrapper.findAll(GlBadge);
+ const findTooltip = () => getBinding(findNote().element, 'gl-tooltip');
const initComponent = (props = {}) => {
- wrapper = mount(AdminUserAvatar, {
+ wrapper = shallowMount(AdminUserAvatar, {
propsData: {
user,
adminUserPath,
...props,
},
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ stubs: {
+ GlAvatarLabeled,
+ },
});
};
@@ -33,31 +44,83 @@ describe('AdminUserAvatar component', () => {
initComponent();
});
- it("links to the user's admin path", () => {
- expect(findAvatarLink().attributes()).toMatchObject({
- href: adminUserPath.replace('id', user.username),
+ it('adds a user link hover card', () => {
+ expect(findUserLink().attributes()).toMatchObject({
'data-user-id': user.id.toString(),
'data-username': user.username,
});
});
- it("renders the user's name", () => {
- expect(findAvatar().props('label')).toBe(user.name);
+ it("renders the user's name with an admin path link", () => {
+ const avatar = findAvatar();
+
+ expect(avatar.props('label')).toBe(user.name);
+ expect(avatar.props('labelLink')).toBe(adminUserPath.replace('id', user.username));
});
- it("renders the user's email", () => {
- expect(findAvatar().props('subLabel')).toBe(user.email);
+ it("renders the user's email with a mailto link", () => {
+ const avatar = findAvatar();
+
+ expect(avatar.props('subLabel')).toBe(user.email);
+ expect(avatar.props('subLabelLink')).toBe(`mailto:${user.email}`);
});
it("renders the user's avatar image", () => {
expect(findAvatar().attributes('src')).toBe(user.avatarUrl);
});
+ it('renders a user note icon', () => {
+ expect(findNote().exists()).toBe(true);
+ expect(findNote().props('name')).toBe('document');
+ });
+
+ it("renders the user's note tooltip", () => {
+ const tooltip = findTooltip();
+
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value).toBe(user.note);
+ });
+
it("renders the user's badges", () => {
findAllBadges().wrappers.forEach((badge, idx) => {
expect(badge.text()).toBe(user.badges[idx].text);
expect(badge.props('variant')).toBe(user.badges[idx].variant);
});
});
+
+ describe('and the user note is very long', () => {
+ const noteText = new Array(LENGTH_OF_USER_NOTE_TOOLTIP + 1).join('a');
+
+ beforeEach(() => {
+ initComponent({
+ user: {
+ ...user,
+ note: noteText,
+ },
+ });
+ });
+
+ it("renders a truncated user's note tooltip", () => {
+ const tooltip = findTooltip();
+
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value).toBe(truncate(noteText, LENGTH_OF_USER_NOTE_TOOLTIP));
+ });
+ });
+
+ describe('and the user does not have a note', () => {
+ beforeEach(() => {
+ initComponent({
+ user: {
+ ...user,
+ note: null,
+ },
+ });
+ });
+
+ it('does not render a user note', () => {
+ expect(findNote().exists()).toBe(false);
+ });
+ });
});
});
diff --git a/spec/frontend/admin/users/components/user_date_spec.js b/spec/frontend/admin/users/components/user_date_spec.js
new file mode 100644
index 00000000000..6428b10059b
--- /dev/null
+++ b/spec/frontend/admin/users/components/user_date_spec.js
@@ -0,0 +1,34 @@
+import { shallowMount } from '@vue/test-utils';
+
+import UserDate from '~/admin/users/components/user_date.vue';
+import { users } from '../mock_data';
+
+const mockDate = users[0].createdAt;
+
+describe('FormatDate component', () => {
+ let wrapper;
+
+ const initComponent = (props = {}) => {
+ wrapper = shallowMount(UserDate, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each`
+ date | output
+ ${mockDate} | ${'13 Nov, 2020'}
+ ${null} | ${'Never'}
+ ${undefined} | ${'Never'}
+ `('renders $date as $output', ({ date, output }) => {
+ initComponent({ date });
+
+ expect(wrapper.text()).toBe(output);
+ });
+});
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index b79d2d4d39d..f1fcc20fb65 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -1,8 +1,11 @@
import { GlTable } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import AdminUsersTable from '~/admin/users/components/users_table.vue';
+import AdminUserActions from '~/admin/users/components/user_actions.vue';
import AdminUserAvatar from '~/admin/users/components/user_avatar.vue';
+import AdminUserDate from '~/admin/users/components/user_date.vue';
+import AdminUsersTable from '~/admin/users/components/users_table.vue';
+
import { users, paths } from '../mock_data';
describe('AdminUsersTable component', () => {
@@ -39,18 +42,21 @@ describe('AdminUsersTable component', () => {
initComponent();
});
- it.each`
- key | label
- ${'name'} | ${'Name'}
- ${'projectsCount'} | ${'Projects'}
- ${'createdAt'} | ${'Created on'}
- ${'lastActivityOn'} | ${'Last activity'}
- `('renders users.$key in column $label', ({ key, label }) => {
- expect(getCellByLabel(0, label).text()).toContain(`${user[key]}`);
+ it('renders the projects count', () => {
+ expect(getCellByLabel(0, 'Projects').text()).toContain(`${user.projectsCount}`);
});
- it('renders an AdminUserAvatar component', () => {
- expect(getCellByLabel(0, 'Name').find(AdminUserAvatar).exists()).toBe(true);
+ it('renders the user actions', () => {
+ expect(wrapper.find(AdminUserActions).exists()).toBe(true);
+ });
+
+ it.each`
+ component | label
+ ${AdminUserAvatar} | ${'Name'}
+ ${AdminUserDate} | ${'Created on'}
+ ${AdminUserDate} | ${'Last activity'}
+ `('renders the component for column $label', ({ component, label }) => {
+ expect(getCellByLabel(0, label).find(component).exists()).toBe(true);
});
});
diff --git a/spec/frontend/admin/users/constants.js b/spec/frontend/admin/users/constants.js
new file mode 100644
index 00000000000..60abdc6c248
--- /dev/null
+++ b/spec/frontend/admin/users/constants.js
@@ -0,0 +1,19 @@
+const BLOCK = 'block';
+const UNBLOCK = 'unblock';
+const DELETE = 'delete';
+const DELETE_WITH_CONTRIBUTIONS = 'deleteWithContributions';
+const UNLOCK = 'unlock';
+const ACTIVATE = 'activate';
+const DEACTIVATE = 'deactivate';
+const REJECT = 'reject';
+const APPROVE = 'approve';
+
+export const EDIT = 'edit';
+
+export const LDAP = 'ldapBlocked';
+
+export const LINK_ACTIONS = [APPROVE, REJECT];
+
+export const CONFIRMATION_ACTIONS = [ACTIVATE, BLOCK, DEACTIVATE, UNLOCK, UNBLOCK];
+
+export const DELETE_ACTIONS = [DELETE, DELETE_WITH_CONTRIBUTIONS];
diff --git a/spec/frontend/admin/users/index_spec.js b/spec/frontend/admin/users/index_spec.js
index 171d54c8f4f..20b60bd8640 100644
--- a/spec/frontend/admin/users/index_spec.js
+++ b/spec/frontend/admin/users/index_spec.js
@@ -1,5 +1,5 @@
import { createWrapper } from '@vue/test-utils';
-import initAdminUsers from '~/admin/users';
+import { initAdminUsersApp } from '~/admin/users';
import AdminUsersApp from '~/admin/users/components/app.vue';
import { users, paths } from './mock_data';
@@ -16,7 +16,7 @@ describe('initAdminUsersApp', () => {
document.body.appendChild(el);
- wrapper = createWrapper(initAdminUsers(el));
+ wrapper = createWrapper(initAdminUsersApp(el));
});
afterEach(() => {
diff --git a/spec/frontend/admin/users/mock_data.js b/spec/frontend/admin/users/mock_data.js
index 860994a9152..c3918ef5173 100644
--- a/spec/frontend/admin/users/mock_data.js
+++ b/spec/frontend/admin/users/mock_data.js
@@ -14,6 +14,7 @@ export const users = [
],
projectsCount: 0,
actions: [],
+ note: 'Create per issue #999',
},
];
diff --git a/spec/frontend/alert_management/components/alert_details_spec.js b/spec/frontend/alert_management/components/alert_details_spec.js
deleted file mode 100644
index 976e50625a6..00000000000
--- a/spec/frontend/alert_management/components/alert_details_spec.js
+++ /dev/null
@@ -1,338 +0,0 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import AlertDetails from '~/alert_management/components/alert_details.vue';
-import AlertSummaryRow from '~/alert_management/components/alert_summary_row.vue';
-import {
- ALERTS_SEVERITY_LABELS,
- trackAlertsDetailsViewsOptions,
-} from '~/alert_management/constants';
-import createIssueMutation from '~/alert_management/graphql/mutations/create_issue_from_alert.mutation.graphql';
-import { joinPaths } from '~/lib/utils/url_utility';
-import Tracking from '~/tracking';
-import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
-import mockAlerts from '../mocks/alerts.json';
-
-const mockAlert = mockAlerts[0];
-const environmentName = 'Production';
-const environmentPath = '/fake/path';
-
-describe('AlertDetails', () => {
- let environmentData = { name: environmentName, path: environmentPath };
- let mock;
- let wrapper;
- const projectPath = 'root/alerts';
- const projectIssuesPath = 'root/alerts/-/issues';
- const projectId = '1';
- const $router = { replace: jest.fn() };
-
- function mountComponent({ data, loading = false, mountMethod = shallowMount, stubs = {} } = {}) {
- wrapper = extendedWrapper(
- mountMethod(AlertDetails, {
- provide: {
- alertId: 'alertId',
- projectPath,
- projectIssuesPath,
- projectId,
- },
- data() {
- return {
- alert: {
- ...mockAlert,
- environment: environmentData,
- },
- sidebarStatus: false,
- ...data,
- };
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- queries: {
- alert: {
- loading,
- },
- sidebarStatus: {},
- },
- },
- $router,
- $route: { params: {} },
- },
- stubs: {
- ...stubs,
- AlertSummaryRow,
- },
- }),
- );
- }
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
- mock.restore();
- });
-
- const findCreateIncidentBtn = () => wrapper.findByTestId('createIncidentBtn');
- const findViewIncidentBtn = () => wrapper.findByTestId('viewIncidentBtn');
- const findIncidentCreationAlert = () => wrapper.findByTestId('incidentCreationError');
- const findEnvironmentName = () => wrapper.findByTestId('environmentName');
- const findEnvironmentPath = () => wrapper.findByTestId('environmentPath');
- const findDetailsTable = () => wrapper.find(AlertDetailsTable);
-
- describe('Alert details', () => {
- describe('when alert is null', () => {
- beforeEach(() => {
- mountComponent({ data: { alert: null } });
- });
-
- it('shows an empty state', () => {
- expect(wrapper.findByTestId('alertDetailsTabs').exists()).toBe(false);
- });
- });
-
- describe('when alert is present', () => {
- beforeEach(() => {
- mountComponent({ data: { alert: mockAlert } });
- });
-
- it('renders a tab with overview information', () => {
- expect(wrapper.findByTestId('overview').exists()).toBe(true);
- });
-
- it('renders a tab with an activity feed', () => {
- expect(wrapper.findByTestId('activity').exists()).toBe(true);
- });
-
- it('renders severity', () => {
- expect(wrapper.findByTestId('severity').text()).toBe(
- ALERTS_SEVERITY_LABELS[mockAlert.severity],
- );
- });
-
- it('renders a title', () => {
- expect(wrapper.findByTestId('title').text()).toBe(mockAlert.title);
- });
-
- it('renders a start time', () => {
- expect(wrapper.findByTestId('startTimeItem').exists()).toBe(true);
- expect(wrapper.findByTestId('startTimeItem').props('time')).toBe(mockAlert.startedAt);
- });
- });
-
- describe('individual alert fields', () => {
- describe.each`
- field | data | isShown
- ${'eventCount'} | ${1} | ${true}
- ${'eventCount'} | ${undefined} | ${false}
- ${'monitoringTool'} | ${'New Relic'} | ${true}
- ${'monitoringTool'} | ${undefined} | ${false}
- ${'service'} | ${'Prometheus'} | ${true}
- ${'service'} | ${undefined} | ${false}
- ${'runbook'} | ${undefined} | ${false}
- ${'runbook'} | ${'run.com'} | ${true}
- `(`$desc`, ({ field, data, isShown }) => {
- beforeEach(() => {
- mountComponent({ data: { alert: { ...mockAlert, [field]: data } } });
- });
-
- it(`${field} is ${isShown ? 'displayed' : 'hidden'} correctly`, () => {
- const element = wrapper.findByTestId(field);
- if (isShown) {
- expect(element.text()).toContain(data.toString());
- } else {
- expect(wrapper.findByTestId(field).exists()).toBe(false);
- }
- });
- });
- });
-
- describe('environment fields', () => {
- it('should show the environment name with a link to the path', () => {
- mountComponent();
- const path = findEnvironmentPath();
-
- expect(findEnvironmentName().exists()).toBe(false);
- expect(path.text()).toBe(environmentName);
- expect(path.attributes('href')).toBe(environmentPath);
- });
-
- it('should only show the environment name if the path is not provided', () => {
- environmentData = { name: environmentName, path: null };
- mountComponent();
-
- expect(findEnvironmentPath().exists()).toBe(false);
- expect(findEnvironmentName().text()).toBe(environmentName);
- });
- });
-
- describe('Create incident from alert', () => {
- it('should display "View incident" button that links the incident page when incident exists', () => {
- const issueIid = '3';
- mountComponent({
- data: { alert: { ...mockAlert, issueIid }, sidebarStatus: false },
- });
-
- expect(findViewIncidentBtn().exists()).toBe(true);
- expect(findViewIncidentBtn().attributes('href')).toBe(
- joinPaths(projectIssuesPath, issueIid),
- );
- expect(findCreateIncidentBtn().exists()).toBe(false);
- });
-
- it('should display "Create incident" button when incident doesn\'t exist yet', () => {
- const issueIid = null;
- mountComponent({
- mountMethod: mount,
- data: { alert: { ...mockAlert, issueIid } },
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findViewIncidentBtn().exists()).toBe(false);
- expect(findCreateIncidentBtn().exists()).toBe(true);
- });
- });
-
- it('calls `$apollo.mutate` with `createIssueQuery`', () => {
- const issueIid = '10';
- mountComponent({
- mountMethod: mount,
- data: { alert: { ...mockAlert } },
- });
-
- jest
- .spyOn(wrapper.vm.$apollo, 'mutate')
- .mockResolvedValue({ data: { createAlertIssue: { issue: { iid: issueIid } } } });
- findCreateIncidentBtn().trigger('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: createIssueMutation,
- variables: {
- iid: mockAlert.iid,
- projectPath,
- },
- });
- });
-
- it('shows error alert when incident creation fails ', async () => {
- const errorMsg = 'Something went wrong';
- mountComponent({
- mountMethod: mount,
- data: { alert: { ...mockAlert, alertIid: 1 } },
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
- findCreateIncidentBtn().trigger('click');
-
- await waitForPromises();
- expect(findIncidentCreationAlert().text()).toBe(errorMsg);
- });
- });
-
- describe('View full alert details', () => {
- beforeEach(() => {
- mountComponent({ data: { alert: mockAlert } });
- });
-
- it('should display a table of raw alert details data', () => {
- expect(findDetailsTable().exists()).toBe(true);
- });
- });
-
- describe('loading state', () => {
- beforeEach(() => {
- mountComponent({ loading: true });
- });
-
- it('displays a loading state when loading', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- });
- });
-
- describe('error state', () => {
- it('displays a error state correctly', () => {
- mountComponent({ data: { errored: true } });
- expect(wrapper.find(GlAlert).exists()).toBe(true);
- });
-
- it('renders html-errors correctly', () => {
- mountComponent({
- data: { errored: true, sidebarErrorMessage: '<span data-testid="htmlError" />' },
- });
- expect(wrapper.findByTestId('htmlError').exists()).toBe(true);
- });
-
- it('does not display an error when dismissed', () => {
- mountComponent({ data: { errored: true, isErrorDismissed: true } });
- expect(wrapper.find(GlAlert).exists()).toBe(false);
- });
- });
-
- describe('header', () => {
- const findHeader = () => wrapper.findByTestId('alert-header');
- const stubs = { TimeAgoTooltip: { template: '<span>now</span>' } };
-
- describe('individual header fields', () => {
- describe.each`
- createdAt | monitoringTool | result
- ${'2020-04-17T23:18:14.996Z'} | ${null} | ${'Alert Reported now'}
- ${'2020-04-17T23:18:14.996Z'} | ${'Datadog'} | ${'Alert Reported now by Datadog'}
- `(
- `When createdAt=$createdAt, monitoringTool=$monitoringTool`,
- ({ createdAt, monitoringTool, result }) => {
- beforeEach(() => {
- mountComponent({
- data: { alert: { ...mockAlert, createdAt, monitoringTool } },
- mountMethod: mount,
- stubs,
- });
- });
-
- it('header text is shown correctly', () => {
- expect(findHeader().text()).toBe(result);
- });
- },
- );
- });
- });
-
- describe('tab navigation', () => {
- beforeEach(() => {
- mountComponent({ data: { alert: mockAlert } });
- });
-
- it.each`
- index | tabId
- ${0} | ${'overview'}
- ${1} | ${'metrics'}
- ${2} | ${'activity'}
- `('will navigate to the correct tab via $tabId', ({ index, tabId }) => {
- wrapper.setData({ currentTabIndex: index });
- expect($router.replace).toHaveBeenCalledWith({ name: 'tab', params: { tabId } });
- });
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alert: mockAlert },
- loading: false,
- });
- });
-
- it('should track alert details page views', () => {
- const { category, action } = trackAlertsDetailsViewsOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/alert_management_empty_state_spec.js b/spec/frontend/alert_management/components/alert_management_empty_state_spec.js
index 509c67743c1..c2bf90e7635 100644
--- a/spec/frontend/alert_management/components/alert_management_empty_state_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_empty_state_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import AlertManagementEmptyState from '~/alert_management/components/alert_management_empty_state.vue';
import defaultProvideValues from '../mocks/alerts_provide_config.json';
diff --git a/spec/frontend/alert_management/components/alert_management_list_wrapper_spec.js b/spec/frontend/alert_management/components/alert_management_list_wrapper_spec.js
index 1d79b10a796..bba5fcbbf08 100644
--- a/spec/frontend/alert_management/components/alert_management_list_wrapper_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_list_wrapper_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import AlertManagementList from '~/alert_management/components/alert_management_list_wrapper.vue';
import AlertManagementEmptyState from '~/alert_management/components/alert_management_empty_state.vue';
+import AlertManagementList from '~/alert_management/components/alert_management_list_wrapper.vue';
import AlertManagementTable from '~/alert_management/components/alert_management_table.vue';
import defaultProvideValues from '../mocks/alerts_provide_config.json';
diff --git a/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js b/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js
deleted file mode 100644
index ea7b4584a63..00000000000
--- a/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { mount } from '@vue/test-utils';
-import SidebarTodo from '~/alert_management/components/sidebar/sidebar_todo.vue';
-import createAlertTodoMutation from '~/alert_management/graphql/mutations/alert_todo_create.mutation.graphql';
-import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
-import mockAlerts from '../mocks/alerts.json';
-
-const mockAlert = mockAlerts[0];
-
-describe('Alert Details Sidebar To Do', () => {
- let wrapper;
-
- function mountComponent({ data, sidebarCollapsed = true, loading = false, stubs = {} } = {}) {
- wrapper = mount(SidebarTodo, {
- propsData: {
- alert: { ...mockAlert },
- ...data,
- sidebarCollapsed,
- projectPath: 'projectPath',
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- queries: {
- alert: {
- loading,
- },
- },
- },
- },
- stubs,
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findToDoButton = () => wrapper.find('[data-testid="alert-todo-button"]');
-
- describe('updating the alert to do', () => {
- const mockUpdatedMutationResult = {
- data: {
- updateAlertTodo: {
- errors: [],
- alert: {},
- },
- },
- };
-
- describe('adding a todo', () => {
- beforeEach(() => {
- mountComponent({
- data: { alert: mockAlert },
- sidebarCollapsed: false,
- loading: false,
- });
- });
-
- it('renders a button for adding a To-Do', async () => {
- await wrapper.vm.$nextTick();
-
- expect(findToDoButton().text()).toBe('Add a To-Do');
- });
-
- it('calls `$apollo.mutate` with `createAlertTodoMutation` mutation and variables containing `iid`, `todoEvent`, & `projectPath`', async () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
-
- findToDoButton().trigger('click');
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: createAlertTodoMutation,
- variables: {
- iid: '1527542',
- projectPath: 'projectPath',
- },
- });
- });
- });
-
- describe('removing a todo', () => {
- beforeEach(() => {
- mountComponent({
- data: { alert: { ...mockAlert, todos: { nodes: [{ id: '1234' }] } } },
- sidebarCollapsed: false,
- loading: false,
- });
- });
-
- it('renders a Mark As Done button when todo is present', async () => {
- await wrapper.vm.$nextTick();
-
- expect(findToDoButton().text()).toBe('Mark as done');
- });
-
- it('calls `$apollo.mutate` with `todoMarkDoneMutation` mutation and variables containing `id`', async () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
-
- findToDoButton().trigger('click');
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: todoMarkDoneMutation,
- update: expect.anything(),
- variables: {
- id: '1234',
- },
- });
- });
- });
- });
-});
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 0cc3d565e10..cea665aa50d 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -1,12 +1,12 @@
-import { mount } from '@vue/test-utils';
import { GlTable, GlAlert, GlLoadingIcon, GlDropdown, GlIcon, GlAvatar } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import { visitUrl } from '~/lib/utils/url_utility';
-import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import mockAlerts from 'jest/vue_shared/alert_details/mocks/alerts.json';
import AlertManagementTable from '~/alert_management/components/alert_management_table.vue';
+import { visitUrl } from '~/lib/utils/url_utility';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import mockAlerts from '../mocks/alerts.json';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import defaultProvideValues from '../mocks/alerts_provide_config.json';
jest.mock('~/lib/utils/url_utility', () => ({
diff --git a/spec/frontend/alert_management/components/alert_metrics_spec.js b/spec/frontend/alert_management/components/alert_metrics_spec.js
deleted file mode 100644
index 42da8c3768b..00000000000
--- a/spec/frontend/alert_management/components/alert_metrics_spec.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import MockAdapter from 'axios-mock-adapter';
-import axios from 'axios';
-import AlertMetrics from '~/alert_management/components/alert_metrics.vue';
-import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
-
-jest.mock('~/monitoring/stores', () => ({
- monitoringDashboard: {},
-}));
-
-jest.mock('~/monitoring/components/embeds/metric_embed.vue', () => ({
- render(h) {
- return h('div');
- },
-}));
-
-describe('Alert Metrics', () => {
- let wrapper;
- const mock = new MockAdapter(axios);
-
- function mountComponent({ props } = {}) {
- wrapper = shallowMount(AlertMetrics, {
- propsData: {
- ...props,
- },
- });
- }
-
- const findChart = () => wrapper.find(MetricEmbed);
- const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
- });
-
- afterAll(() => {
- mock.restore();
- });
-
- describe('Empty state', () => {
- it('should display a message when metrics dashboard url is not provided ', () => {
- mountComponent();
- expect(findChart().exists()).toBe(false);
- expect(findEmptyState().text()).toBe("Metrics weren't available in the alerts payload.");
- });
- });
-
- describe('Chart', () => {
- it('should be rendered when dashboard url is provided', async () => {
- mountComponent({ props: { dashboardUrl: 'metrics.url' } });
-
- await waitForPromises();
- await wrapper.vm.$nextTick();
-
- expect(findEmptyState().exists()).toBe(false);
- expect(findChart().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/alert_status_spec.js b/spec/frontend/alert_management/components/alert_status_spec.js
deleted file mode 100644
index 6f2ddb86020..00000000000
--- a/spec/frontend/alert_management/components/alert_status_spec.js
+++ /dev/null
@@ -1,151 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
-import { trackAlertStatusUpdateOptions } from '~/alert_management/constants';
-import AlertManagementStatus from '~/alert_management/components/alert_status.vue';
-import updateAlertStatusMutation from '~/graphql_shared/mutations/update_alert_status.mutation.graphql';
-import Tracking from '~/tracking';
-import mockAlerts from '../mocks/alerts.json';
-
-const mockAlert = mockAlerts[0];
-
-describe('AlertManagementStatus', () => {
- let wrapper;
- const findStatusDropdown = () => wrapper.find(GlDropdown);
- const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
-
- const selectFirstStatusOption = () => {
- findFirstStatusOption().vm.$emit('click');
-
- return waitForPromises();
- };
-
- function mountComponent({ props = {}, loading = false, stubs = {} } = {}) {
- wrapper = shallowMount(AlertManagementStatus, {
- propsData: {
- alert: { ...mockAlert },
- projectPath: 'gitlab-org/gitlab',
- isSidebar: false,
- ...props,
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- queries: {
- alert: {
- loading,
- },
- },
- },
- },
- stubs,
- });
- }
-
- beforeEach(() => {
- mountComponent();
- });
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- describe('updating the alert status', () => {
- const iid = '1527542';
- const mockUpdatedMutationResult = {
- data: {
- updateAlertStatus: {
- errors: [],
- alert: {
- iid,
- status: 'acknowledged',
- },
- },
- },
- };
-
- beforeEach(() => {
- mountComponent({});
- });
-
- it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
- findFirstStatusOption().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: updateAlertStatusMutation,
- variables: {
- iid,
- status: 'TRIGGERED',
- projectPath: 'gitlab-org/gitlab',
- },
- });
- });
-
- describe('when a request fails', () => {
- beforeEach(() => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
- });
-
- it('emits an error', async () => {
- await selectFirstStatusOption();
-
- expect(wrapper.emitted('alert-error')[0]).toEqual([
- 'There was an error while updating the status of the alert. Please try again.',
- ]);
- });
-
- it('emits an error when triggered a second time', async () => {
- await selectFirstStatusOption();
- await wrapper.vm.$nextTick();
- await selectFirstStatusOption();
- // Should emit two errors [0,1]
- expect(wrapper.emitted('alert-error').length > 1).toBe(true);
- });
- });
-
- it('shows an error when response includes HTML errors', async () => {
- const mockUpdatedMutationErrorResult = {
- data: {
- updateAlertStatus: {
- errors: ['<span data-testid="htmlError" />'],
- alert: {
- iid,
- status: 'acknowledged',
- },
- },
- },
- };
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationErrorResult);
-
- await selectFirstStatusOption();
-
- expect(wrapper.emitted('alert-error').length > 0).toBe(true);
- expect(wrapper.emitted('alert-error')[0]).toEqual([
- 'There was an error while updating the status of the alert. <span data-testid="htmlError" />',
- ]);
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent({});
- });
-
- it('should track alert status updates', () => {
- Tracking.event.mockClear();
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
- findFirstStatusOption().vm.$emit('click');
- const status = findFirstStatusOption().text();
- setImmediate(() => {
- const { category, action, label } = trackAlertStatusUpdateOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property: status });
- });
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/alert_summary_row_spec.js b/spec/frontend/alert_management/components/alert_summary_row_spec.js
deleted file mode 100644
index 47c715c089a..00000000000
--- a/spec/frontend/alert_management/components/alert_summary_row_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import AlertSummaryRow from '~/alert_management/components/alert_summary_row.vue';
-
-const label = 'a label';
-const value = 'a value';
-
-describe('AlertSummaryRow', () => {
- let wrapper;
-
- function mountComponent({ mountMethod = shallowMount, props, defaultSlot } = {}) {
- wrapper = mountMethod(AlertSummaryRow, {
- propsData: props,
- scopedSlots: {
- default: defaultSlot,
- },
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- describe('Alert Summary Row', () => {
- beforeEach(() => {
- mountComponent({
- props: {
- label,
- },
- defaultSlot: `<span class="value">${value}</span>`,
- });
- });
-
- it('should display a label and a value', () => {
- expect(wrapper.text()).toBe(`${label} ${value}`);
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js b/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js
deleted file mode 100644
index 00c479071fe..00000000000
--- a/spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js
+++ /dev/null
@@ -1,173 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import { GlDropdownItem } from '@gitlab/ui';
-import SidebarAssignee from '~/alert_management/components/sidebar/sidebar_assignee.vue';
-import SidebarAssignees from '~/alert_management/components/sidebar/sidebar_assignees.vue';
-import AlertSetAssignees from '~/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql';
-import mockAlerts from '../../mocks/alerts.json';
-
-const mockAlert = mockAlerts[0];
-
-describe('Alert Details Sidebar Assignees', () => {
- let wrapper;
- let mock;
-
- function mountComponent({
- data,
- users = [],
- isDropdownSearching = false,
- sidebarCollapsed = true,
- loading = false,
- stubs = {},
- } = {}) {
- wrapper = shallowMount(SidebarAssignees, {
- data() {
- return {
- users,
- isDropdownSearching,
- };
- },
- propsData: {
- alert: { ...mockAlert },
- ...data,
- sidebarCollapsed,
- projectPath: 'projectPath',
- projectId: '1',
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- queries: {
- alert: {
- loading,
- },
- },
- },
- },
- stubs,
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
- mock.restore();
- });
-
- const findAssigned = () => wrapper.find('[data-testid="assigned-users"]');
- const findUnassigned = () => wrapper.find('[data-testid="unassigned-users"]');
-
- describe('updating the alert status', () => {
- const mockUpdatedMutationResult = {
- data: {
- alertSetAssignees: {
- errors: [],
- alert: {
- assigneeUsernames: ['root'],
- },
- },
- },
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- const path = '/-/autocomplete/users.json';
- const users = [
- {
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- id: 1,
- name: 'User 1',
- username: 'root',
- },
- {
- avatar_url:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- id: 2,
- name: 'User 2',
- username: 'not-root',
- },
- ];
-
- mock.onGet(path).replyOnce(200, users);
- mountComponent({
- data: { alert: mockAlert },
- sidebarCollapsed: false,
- loading: false,
- users,
- stubs: {
- SidebarAssignee,
- },
- });
- });
-
- it('renders a unassigned option', async () => {
- wrapper.setData({ isDropdownSearching: false });
- await wrapper.vm.$nextTick();
- expect(wrapper.find(GlDropdownItem).text()).toBe('Unassigned');
- });
-
- it('calls `$apollo.mutate` with `AlertSetAssignees` mutation and variables containing `iid`, `assigneeUsernames`, & `projectPath`', async () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
- wrapper.setData({ isDropdownSearching: false });
-
- await wrapper.vm.$nextTick();
- wrapper.find(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: AlertSetAssignees,
- variables: {
- iid: '1527542',
- assigneeUsernames: ['root'],
- projectPath: 'projectPath',
- },
- });
- });
-
- it('emits an error when request contains error messages', () => {
- wrapper.setData({ isDropdownSearching: false });
- const errorMutationResult = {
- data: {
- alertSetAssignees: {
- errors: ['There was a problem for sure.'],
- alert: {},
- },
- },
- };
-
- 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();
- });
- });
-
- it('stops updating and cancels loading when the request fails', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
- wrapper.vm.updateAlertAssignees('root');
- expect(findUnassigned().text()).toBe('assign yourself');
- });
-
- it('shows a user avatar, username and full name when a user is set', () => {
- mountComponent({
- data: { alert: mockAlerts[1] },
- sidebarCollapsed: false,
- loading: false,
- stubs: {
- SidebarAssignee,
- },
- });
-
- expect(findAssigned().find('img').attributes('src')).toBe('/url');
- expect(findAssigned().find('.dropdown-menu-user-full-name').text()).toBe('root');
- expect(findAssigned().find('.dropdown-menu-user-username').text()).toBe('@root');
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/sidebar/alert_sidebar_spec.js b/spec/frontend/alert_management/components/sidebar/alert_sidebar_spec.js
deleted file mode 100644
index 5235ae63fee..00000000000
--- a/spec/frontend/alert_management/components/sidebar/alert_sidebar_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { shallowMount, mount } from '@vue/test-utils';
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import AlertSidebar from '~/alert_management/components/alert_sidebar.vue';
-import SidebarAssignees from '~/alert_management/components/sidebar/sidebar_assignees.vue';
-import mockAlerts from '../../mocks/alerts.json';
-
-const mockAlert = mockAlerts[0];
-
-describe('Alert Details Sidebar', () => {
- let wrapper;
- let mock;
-
- function mountComponent({ mountMethod = shallowMount, stubs = {}, alert = {} } = {}) {
- wrapper = mountMethod(AlertSidebar, {
- data() {
- return {
- sidebarStatus: false,
- };
- },
- propsData: {
- alert,
- },
- provide: {
- projectPath: 'projectPath',
- projectId: '1',
- },
- stubs,
- mocks: {
- $apollo: {
- queries: {
- sidebarStatus: {},
- },
- },
- },
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
- mock.restore();
- });
-
- describe('the sidebar renders', () => {
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mountComponent();
- });
-
- it('open as default', () => {
- expect(wrapper.classes('right-sidebar-expanded')).toBe(true);
- });
-
- it('should render side bar assignee dropdown', () => {
- mountComponent({
- mountMethod: mount,
- alert: mockAlert,
- });
- expect(wrapper.find(SidebarAssignees).exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js b/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
deleted file mode 100644
index 0b60a36cf54..00000000000
--- a/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlDropdown, GlDropdownItem, GlLoadingIcon } from '@gitlab/ui';
-import { trackAlertStatusUpdateOptions } from '~/alert_management/constants';
-import AlertSidebarStatus from '~/alert_management/components/sidebar/sidebar_status.vue';
-import updateAlertStatusMutation from '~/graphql_shared/mutations/update_alert_status.mutation.graphql';
-import Tracking from '~/tracking';
-import mockAlerts from '../../mocks/alerts.json';
-
-const mockAlert = mockAlerts[0];
-
-describe('Alert Details Sidebar Status', () => {
- let wrapper;
- const findStatusDropdown = () => wrapper.find(GlDropdown);
- const findStatusDropdownItem = () => wrapper.find(GlDropdownItem);
- const findStatusLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findStatusDropdownHeader = () => wrapper.find('[data-testid="dropdown-header"]');
-
- function mountComponent({ data, sidebarCollapsed = true, loading = false, stubs = {} } = {}) {
- wrapper = mount(AlertSidebarStatus, {
- propsData: {
- alert: { ...mockAlert },
- ...data,
- sidebarCollapsed,
- projectPath: 'projectPath',
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- queries: {
- alert: {
- loading,
- },
- },
- },
- },
- stubs,
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
- });
-
- describe('Alert Sidebar Dropdown Status', () => {
- beforeEach(() => {
- mountComponent({
- data: { alert: mockAlert },
- sidebarCollapsed: false,
- loading: false,
- });
- });
-
- it('displays status dropdown', () => {
- expect(findStatusDropdown().exists()).toBe(true);
- });
-
- it('displays the dropdown status header', () => {
- expect(findStatusDropdownHeader().exists()).toBe(true);
- });
-
- describe('updating the alert status', () => {
- const mockUpdatedMutationResult = {
- data: {
- updateAlertStatus: {
- errors: [],
- alert: {
- status: 'acknowledged',
- },
- },
- },
- };
-
- beforeEach(() => {
- mountComponent({
- data: { alert: mockAlert },
- sidebarCollapsed: false,
- loading: false,
- });
- });
-
- it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
- findStatusDropdownItem().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: updateAlertStatusMutation,
- variables: {
- iid: '1527542',
- status: 'TRIGGERED',
- projectPath: 'projectPath',
- },
- });
- });
-
- it('stops updating when the request fails', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
- findStatusDropdownItem().vm.$emit('click');
- expect(findStatusLoadingIcon().exists()).toBe(false);
- expect(wrapper.find('[data-testid="status"]').text()).toBe('Triggered');
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alert: mockAlert },
- loading: false,
- });
- });
-
- it('should track alert status updates', () => {
- Tracking.event.mockClear();
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
- findStatusDropdownItem().vm.$emit('click');
- const status = findStatusDropdownItem().text();
- setImmediate(() => {
- const { category, action, label } = trackAlertStatusUpdateOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action, {
- label,
- property: status,
- });
- });
- });
- });
- });
-});
diff --git a/spec/frontend/alert_management/components/system_notes/alert_management_system_note_spec.js b/spec/frontend/alert_management/components/system_notes/alert_management_system_note_spec.js
deleted file mode 100644
index 65cfc600d76..00000000000
--- a/spec/frontend/alert_management/components/system_notes/alert_management_system_note_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import SystemNote from '~/alert_management/components/system_notes/system_note.vue';
-import mockAlerts from '../../mocks/alerts.json';
-
-const mockAlert = mockAlerts[1];
-
-describe('Alert Details System Note', () => {
- let wrapper;
-
- function mountComponent({ stubs = {} } = {}) {
- wrapper = shallowMount(SystemNote, {
- propsData: {
- note: { ...mockAlert.notes.nodes[0] },
- },
- stubs,
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- describe('System notes', () => {
- beforeEach(() => {
- mountComponent({});
- });
-
- it('renders the correct system note', () => {
- const noteId = wrapper.find('.note-wrapper').attributes('id');
- const iconName = wrapper.find(GlIcon).attributes('name');
-
- expect(noteId).toBe('note_1628');
- expect(iconName).toBe(mockAlert.notes.nodes[0].systemNoteIconName);
- });
- });
-});
diff --git a/spec/frontend/alerts_service_settings/components/__snapshots__/alerts_service_form_spec.js.snap b/spec/frontend/alerts_service_settings/components/__snapshots__/alerts_service_form_spec.js.snap
deleted file mode 100644
index 0d4171a20b3..00000000000
--- a/spec/frontend/alerts_service_settings/components/__snapshots__/alerts_service_form_spec.js.snap
+++ /dev/null
@@ -1,9 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AlertsServiceForm with default values renders "authorization-key" input 1`] = `"<gl-form-input-stub id=\\"authorization-key\\" readonly=\\"true\\" value=\\"abcedfg123\\"></gl-form-input-stub>"`;
-
-exports[`AlertsServiceForm with default values renders "url" input 1`] = `"<gl-form-input-stub id=\\"url\\" readonly=\\"true\\" value=\\"https://gitlab.com/endpoint-url\\"></gl-form-input-stub>"`;
-
-exports[`AlertsServiceForm with default values renders toggle button 1`] = `"<toggle-button-stub id=\\"activated\\"></toggle-button-stub>"`;
-
-exports[`AlertsServiceForm with default values shows description and docs links 1`] = `"<p><gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub></p><p><gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub></p>"`;
diff --git a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js b/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
deleted file mode 100644
index 346059ed7be..00000000000
--- a/spec/frontend/alerts_service_settings/components/alerts_service_form_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import { nextTick } from 'vue';
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
-import { GlModal } from '@gitlab/ui';
-import AlertsServiceForm from '~/alerts_service_settings/components/alerts_service_form.vue';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-
-jest.mock('~/flash');
-
-const defaultProps = {
- initialAuthorizationKey: 'abcedfg123',
- formPath: 'http://invalid',
- url: 'https://gitlab.com/endpoint-url',
- alertsSetupUrl: 'http://invalid',
- alertsUsageUrl: 'http://invalid',
- initialActivated: false,
- isDisabled: false,
-};
-
-describe('AlertsServiceForm', () => {
- let wrapper;
- let mockAxios;
-
- const createComponent = (props = defaultProps) => {
- wrapper = shallowMount(AlertsServiceForm, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
-
- const findUrl = () => wrapper.find('#url');
- const findAuthorizationKey = () => wrapper.find('#authorization-key');
- const findDescription = () => wrapper.find('[data-testid="description"');
-
- beforeEach(() => {
- mockAxios = new MockAdapter(axios);
- });
-
- afterEach(() => {
- wrapper.destroy();
- mockAxios.restore();
- });
-
- describe('with default values', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders "url" input', () => {
- expect(findUrl().html()).toMatchSnapshot();
- });
-
- it('renders "authorization-key" input', () => {
- expect(findAuthorizationKey().html()).toMatchSnapshot();
- });
-
- it('renders toggle button', () => {
- expect(wrapper.find(ToggleButton).html()).toMatchSnapshot();
- });
-
- it('shows description and docs links', () => {
- expect(findDescription().element.innerHTML).toMatchSnapshot();
- });
- });
-
- describe('reset key', () => {
- it('updates the authorization key on success', async () => {
- const formPath = 'some/path';
- mockAxios.onPut(formPath).replyOnce(200, { token: 'newToken' });
-
- createComponent({ formPath });
-
- wrapper.find(GlModal).vm.$emit('ok');
- await axios.waitForAll();
-
- expect(findAuthorizationKey().attributes('value')).toBe('newToken');
- });
-
- it('shows flash message on error', () => {
- const formPath = 'some/path';
- mockAxios.onPut(formPath).replyOnce(404);
-
- createComponent({ formPath });
-
- return wrapper.vm.resetKey().then(() => {
- expect(findAuthorizationKey().attributes('value')).toBe(
- defaultProps.initialAuthorizationKey,
- );
- expect(createFlash).toHaveBeenCalled();
- });
- });
- });
-
- describe('activate toggle', () => {
- describe('successfully completes', () => {
- describe.each`
- initialActivated | value
- ${false} | ${true}
- ${true} | ${false}
- `(
- 'when initialActivated=$initialActivated and value=$value',
- ({ initialActivated, value }) => {
- beforeEach(() => {
- const formPath = 'some/path';
- mockAxios
- .onPut(formPath, { service: { active: value } })
- .replyOnce(200, { active: value });
- createComponent({ initialActivated, formPath });
-
- return wrapper.vm.toggleActivated(value);
- });
-
- it(`updates toggle button value to ${value}`, () => {
- expect(wrapper.find(ToggleButton).props('value')).toBe(value);
- });
- },
- );
- });
-
- describe('error is encountered', () => {
- beforeEach(() => {
- const formPath = 'some/path';
- mockAxios.onPut(formPath).replyOnce(500);
- });
-
- it('restores previous value', () => {
- createComponent({ initialActivated: false });
-
- return wrapper.vm.toggleActivated(true).then(() => {
- expect(wrapper.find(ToggleButton).props('value')).toBe(false);
- });
- });
- });
- });
-
- describe('form is disabled', () => {
- beforeEach(() => {
- createComponent({ isDisabled: true });
- });
-
- it('cannot be toggled', () => {
- wrapper.find(ToggleButton).vm.$emit('change');
- return nextTick().then(() => {
- expect(wrapper.find(ToggleButton).props('disabledInput')).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap
deleted file mode 100644
index ef68a6a2c32..00000000000
--- a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_spec.js.snap
+++ /dev/null
@@ -1,98 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`AlertsSettingsFormNew with default values renders the initial template 1`] = `
-"<form class=\\"gl-mt-6\\">
- <h5 class=\\"gl-font-lg gl-my-5\\">Add new integrations</h5>
- <div id=\\"integration-type\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"integration-type__BV_label_\\" for=\\"integration-type\\" class=\\"d-block col-form-label\\">1. Select integration type</label>
- <div class=\\"bv-no-focus-ring\\"><select class=\\"gl-form-select mw-100 custom-select\\" id=\\"__BVID__8\\">
- <option value=\\"\\">Select integration type</option>
- <option value=\\"HTTP\\">HTTP Endpoint</option>
- <option value=\\"PROMETHEUS\\">External Prometheus</option>
- </select>
- <!---->
- <!---->
- <!---->
- <!---->
- </div>
- </div>
- <transition-stub css=\\"true\\" enterclass=\\"\\" leaveclass=\\"collapse show\\" entertoclass=\\"collapse show\\" leavetoclass=\\"collapse\\" enteractiveclass=\\"collapsing\\" leaveactiveclass=\\"collapsing\\" class=\\"gl-mt-3\\">
- <div class=\\"collapse\\" style=\\"display: none;\\" id=\\"__BVID__10\\">
- <div>
- <div id=\\"name-integration\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"name-integration__BV_label_\\" for=\\"name-integration\\" class=\\"d-block col-form-label\\">2. Name integration</label>
- <div class=\\"bv-no-focus-ring\\"><input type=\\"text\\" placeholder=\\"Enter integration name\\" class=\\"gl-form-input form-control\\" id=\\"__BVID__15\\">
- <!---->
- <!---->
- <!---->
- </div>
- </div>
- <div id=\\"integration-webhook\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"integration-webhook__BV_label_\\" for=\\"integration-webhook\\" class=\\"d-block col-form-label\\">3. Set up webhook</label>
- <div class=\\"bv-no-focus-ring\\"><span>Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the <a rel=\\"noopener noreferrer\\" target=\\"_blank\\" href=\\"https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html\\" class=\\"gl-link gl-display-inline-block\\">GitLab documentation</a> to learn more about configuring your endpoint.</span> <label class=\\"gl-display-flex gl-flex-direction-column gl-mb-0 gl-w-max-content gl-my-4 gl-font-weight-normal\\">
- <div class=\\"gl-toggle-wrapper\\"><span class=\\"gl-toggle-label\\">Active</span>
- <!----> <button aria-label=\\"Active\\" type=\\"button\\" class=\\"gl-toggle\\"><span class=\\"toggle-icon\\"><svg data-testid=\\"close-icon\\" aria-hidden=\\"true\\" class=\\"gl-icon s16\\"><use href=\\"#close\\"></use></svg></span></button></div>
- <!---->
- </label>
- <!---->
- <div class=\\"gl-my-4\\"><span class=\\"gl-font-weight-bold\\">
- Webhook URL
- </span>
- <div id=\\"url\\" readonly=\\"readonly\\">
- <div role=\\"group\\" class=\\"input-group\\">
- <!---->
- <!----> <input id=\\"url\\" type=\\"text\\" readonly=\\"readonly\\" class=\\"gl-form-input form-control\\">
- <div class=\\"input-group-append\\"><button title=\\"Copy\\" data-clipboard-text=\\"\\" aria-label=\\"Copy this value\\" type=\\"button\\" class=\\"btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon\\">
- <!----> <svg data-testid=\\"copy-to-clipboard-icon\\" aria-hidden=\\"true\\" class=\\"gl-button-icon gl-icon s16\\">
- <use href=\\"#copy-to-clipboard\\"></use>
- </svg>
- <!----></button></div>
- <!---->
- </div>
- </div>
- </div>
- <div class=\\"gl-my-4\\"><span class=\\"gl-font-weight-bold\\">
- Authorization key
- </span>
- <div id=\\"authorization-key\\" readonly=\\"readonly\\" class=\\"gl-mb-3\\">
- <div role=\\"group\\" class=\\"input-group\\">
- <!---->
- <!----> <input id=\\"authorization-key\\" type=\\"text\\" readonly=\\"readonly\\" class=\\"gl-form-input form-control\\">
- <div class=\\"input-group-append\\"><button title=\\"Copy\\" data-clipboard-text=\\"\\" aria-label=\\"Copy this value\\" type=\\"button\\" class=\\"btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon\\">
- <!----> <svg data-testid=\\"copy-to-clipboard-icon\\" aria-hidden=\\"true\\" class=\\"gl-button-icon gl-icon s16\\">
- <use href=\\"#copy-to-clipboard\\"></use>
- </svg>
- <!----></button></div>
- <!---->
- </div>
- </div> <button type=\\"button\\" disabled=\\"disabled\\" class=\\"btn btn-default btn-md disabled gl-button\\">
- <!---->
- <!----> <span class=\\"gl-button-text\\">
- Reset Key
- </span></button>
- <!---->
- </div>
- <!---->
- <!---->
- <!---->
- </div>
- </div>
- <div id=\\"test-integration\\" role=\\"group\\" class=\\"form-group gl-form-group\\"><label id=\\"test-integration__BV_label_\\" for=\\"test-integration\\" class=\\"d-block col-form-label\\">4. Sample alert payload (optional)</label>
- <div class=\\"bv-no-focus-ring\\"><span>Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional).</span> <textarea id=\\"test-payload\\" disabled=\\"disabled\\" placeholder=\\"{ &quot;events&quot;: [{ &quot;application&quot;: &quot;Name of application&quot; }] }\\" wrap=\\"soft\\" class=\\"gl-form-input gl-form-textarea gl-my-3 form-control is-valid\\" style=\\"resize: none; overflow-y: scroll;\\"></textarea>
- <!---->
- <!---->
- <!---->
- </div>
- </div>
- <!---->
- <!---->
- </div>
- <div class=\\"gl-display-flex gl-justify-content-start gl-py-3\\"><button data-testid=\\"integration-form-submit\\" type=\\"submit\\" class=\\"btn js-no-auto-disable btn-success btn-md gl-button\\">
- <!---->
- <!----> <span class=\\"gl-button-text\\">Save integration
- </span></button> <button data-testid=\\"integration-test-and-submit\\" type=\\"button\\" disabled=\\"disabled\\" class=\\"btn gl-mx-3 js-no-auto-disable btn-success btn-md disabled gl-button btn-success-secondary\\">
- <!---->
- <!----> <span class=\\"gl-button-text\\">Save and test payload</span></button> <button type=\\"reset\\" class=\\"btn js-no-auto-disable btn-default btn-md gl-button\\">
- <!---->
- <!----> <span class=\\"gl-button-text\\">Cancel</span></button></div>
- </div>
- </transition-stub>
-</form>"
-`;
diff --git a/spec/frontend/alerts_settings/alert_mapping_builder_spec.js b/spec/frontend/alerts_settings/alert_mapping_builder_spec.js
deleted file mode 100644
index 5d48ff02e35..00000000000
--- a/spec/frontend/alerts_settings/alert_mapping_builder_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { GlIcon, GlFormInput, GlDropdown, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import AlertMappingBuilder, { i18n } from '~/alerts_settings/components/alert_mapping_builder.vue';
-import gitlabFields from '~/alerts_settings/components/mocks/gitlabFields.json';
-import parsedMapping from '~/alerts_settings/components/mocks/parsedMapping.json';
-
-describe('AlertMappingBuilder', () => {
- let wrapper;
-
- function mountComponent() {
- wrapper = shallowMount(AlertMappingBuilder, {
- propsData: {
- payloadFields: parsedMapping.samplePayload.payloadAlerFields.nodes,
- mapping: parsedMapping.storedMapping.nodes,
- },
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- beforeEach(() => {
- mountComponent();
- });
-
- const findColumnInRow = (row, column) =>
- wrapper.findAll('.gl-display-table-row').at(row).findAll('.gl-display-table-cell ').at(column);
-
- it('renders column captions', () => {
- expect(findColumnInRow(0, 0).text()).toContain(i18n.columns.gitlabKeyTitle);
- expect(findColumnInRow(0, 2).text()).toContain(i18n.columns.payloadKeyTitle);
- expect(findColumnInRow(0, 3).text()).toContain(i18n.columns.fallbackKeyTitle);
-
- const fallbackColumnIcon = findColumnInRow(0, 3).find(GlIcon);
- expect(fallbackColumnIcon.exists()).toBe(true);
- expect(fallbackColumnIcon.attributes('name')).toBe('question');
- expect(fallbackColumnIcon.attributes('title')).toBe(i18n.fallbackTooltip);
- });
-
- it('renders disabled form input for each mapped field', () => {
- gitlabFields.forEach((field, index) => {
- const input = findColumnInRow(index + 1, 0).find(GlFormInput);
- expect(input.attributes('value')).toBe(`${field.label} (${field.type.join(' or ')})`);
- expect(input.attributes('disabled')).toBe('');
- });
- });
-
- it('renders right arrow next to each input', () => {
- gitlabFields.forEach((field, index) => {
- const arrow = findColumnInRow(index + 1, 1).find('.right-arrow');
- expect(arrow.exists()).toBe(true);
- });
- });
-
- it('renders mapping dropdown for each field', () => {
- gitlabFields.forEach(({ compatibleTypes }, index) => {
- const dropdown = findColumnInRow(index + 1, 2).find(GlDropdown);
- const searchBox = dropdown.find(GlSearchBoxByType);
- const dropdownItems = dropdown.findAll(GlDropdownItem);
- const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
- const numberOfMappingOptions = nodes.filter(({ type }) =>
- type.some((t) => compatibleTypes.includes(t)),
- );
-
- expect(dropdown.exists()).toBe(true);
- expect(searchBox.exists()).toBe(true);
- expect(dropdownItems).toHaveLength(numberOfMappingOptions.length);
- });
- });
-
- it('renders fallback dropdown only for the fields that have fallback', () => {
- gitlabFields.forEach(({ compatibleTypes, numberOfFallbacks }, index) => {
- const dropdown = findColumnInRow(index + 1, 3).find(GlDropdown);
- expect(dropdown.exists()).toBe(Boolean(numberOfFallbacks));
-
- if (numberOfFallbacks) {
- const searchBox = dropdown.find(GlSearchBoxByType);
- const dropdownItems = dropdown.findAll(GlDropdownItem);
- const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
- const numberOfMappingOptions = nodes.filter(({ type }) =>
- type.some((t) => compatibleTypes.includes(t)),
- );
-
- expect(searchBox.exists()).toBe(Boolean(numberOfFallbacks));
- expect(dropdownItems).toHaveLength(numberOfMappingOptions.length);
- }
- });
- });
-});
diff --git a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
deleted file mode 100644
index 5a3874d055b..00000000000
--- a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
+++ /dev/null
@@ -1,118 +0,0 @@
-import { GlTable, GlIcon, GlButton } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
-import Tracking from '~/tracking';
-import AlertIntegrationsList, {
- i18n,
-} from '~/alerts_settings/components/alerts_integrations_list.vue';
-import { trackAlertIntegrationsViewsOptions } from '~/alerts_settings/constants';
-
-const mockIntegrations = [
- {
- id: '1',
- active: true,
- name: 'Integration 1',
- type: 'HTTP endpoint',
- },
- {
- id: '2',
- active: false,
- name: 'Integration 2',
- type: 'HTTP endpoint',
- },
-];
-
-describe('AlertIntegrationsList', () => {
- let wrapper;
- const { trigger: triggerIntersection } = useMockIntersectionObserver();
-
- function mountComponent({ data = {}, props = {} } = {}) {
- wrapper = mount(AlertIntegrationsList, {
- data() {
- return { ...data };
- },
- propsData: {
- integrations: mockIntegrations,
- ...props,
- },
- stubs: {
- GlIcon: true,
- GlButton: true,
- },
- });
- }
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- beforeEach(() => {
- mountComponent();
- });
-
- const findTableComponent = () => wrapper.find(GlTable);
- const findTableComponentRows = () => wrapper.find(GlTable).findAll('table tbody tr');
- const finsStatusCell = () => wrapper.findAll('[data-testid="integration-activated-status"]');
-
- it('renders a table', () => {
- expect(findTableComponent().exists()).toBe(true);
- });
-
- it('renders an empty state when no integrations provided', () => {
- mountComponent({ props: { integrations: [] } });
- expect(findTableComponent().text()).toContain(i18n.emptyState);
- });
-
- it('renders an an edit and delete button for each integration', () => {
- expect(findTableComponent().findAll(GlButton).length).toBe(4);
- });
-
- it('renders an highlighted row when a current integration is selected to edit', () => {
- mountComponent({ data: { currentIntegration: { id: '1' } } });
- expect(findTableComponentRows().at(0).classes()).toContain('gl-bg-blue-50');
- });
-
- describe('integration status', () => {
- it('enabled', () => {
- const cell = finsStatusCell().at(0);
- const activatedIcon = cell.find(GlIcon);
- expect(cell.text()).toBe(i18n.status.enabled.name);
- expect(activatedIcon.attributes('name')).toBe('check-circle-filled');
- expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
- });
-
- it('disabled', () => {
- const cell = finsStatusCell().at(1);
- const notActivatedIcon = cell.find(GlIcon);
- expect(cell.text()).toBe(i18n.status.disabled.name);
- expect(notActivatedIcon.attributes('name')).toBe('warning-solid');
- expect(notActivatedIcon.attributes('title')).toBe(i18n.status.disabled.tooltip);
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- mountComponent();
- jest.spyOn(Tracking, 'event');
- });
-
- it('should NOT track alert list page views when list is collapsed', () => {
- triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: false } });
-
- expect(Tracking.event).not.toHaveBeenCalled();
- });
-
- it('should track alert list page views only once when list is expanded', () => {
- triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
- triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
- triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
-
- const { category, action } = trackAlertIntegrationsViewsOptions;
- expect(Tracking.event).toHaveBeenCalledTimes(1);
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
- });
-});
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_spec.js
deleted file mode 100644
index 21cdec6f94c..00000000000
--- a/spec/frontend/alerts_settings/alerts_settings_form_spec.js
+++ /dev/null
@@ -1,351 +0,0 @@
-import { mount } from '@vue/test-utils';
-import {
- GlForm,
- GlFormSelect,
- GlCollapse,
- GlFormInput,
- GlToggle,
- GlFormTextarea,
-} from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
-import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
-import { defaultAlertSettingsConfig } from './util';
-import { typeSet } from '~/alerts_settings/constants';
-
-describe('AlertsSettingsFormNew', () => {
- let wrapper;
- const mockToastShow = jest.fn();
-
- const createComponent = ({
- data = {},
- props = {},
- multipleHttpIntegrationsCustomMapping = false,
- } = {}) => {
- wrapper = mount(AlertsSettingsForm, {
- data() {
- return { ...data };
- },
- propsData: {
- loading: false,
- canAddIntegration: true,
- ...props,
- },
- provide: {
- glFeatures: { multipleHttpIntegrationsCustomMapping },
- ...defaultAlertSettingsConfig,
- },
- mocks: {
- $toast: {
- show: mockToastShow,
- },
- },
- });
- };
-
- const findForm = () => wrapper.find(GlForm);
- const findSelect = () => wrapper.find(GlFormSelect);
- const findFormSteps = () => wrapper.find(GlCollapse);
- const findFormFields = () => wrapper.findAll(GlFormInput);
- const findFormToggle = () => wrapper.find(GlToggle);
- const findTestPayloadSection = () => wrapper.find(`[id = "test-integration"]`);
- const findMappingBuilderSection = () => wrapper.find(`[id = "mapping-builder"]`);
- const findSubmitButton = () => wrapper.find(`[type = "submit"]`);
- const findMultiSupportText = () =>
- wrapper.find(`[data-testid="multi-integrations-not-supported"]`);
- const findJsonTestSubmit = () => wrapper.find(`[data-testid="integration-test-and-submit"]`);
- const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`);
- const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`);
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- describe('with default values', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders the initial template', () => {
- expect(wrapper.html()).toMatchSnapshot();
- });
-
- it('render the initial form with only an integration type dropdown', () => {
- expect(findForm().exists()).toBe(true);
- expect(findSelect().exists()).toBe(true);
- expect(findMultiSupportText().exists()).toBe(false);
- expect(findFormSteps().attributes('visible')).toBeUndefined();
- });
-
- it('shows the rest of the form when the dropdown is used', async () => {
- const options = findSelect().findAll('option');
- await options.at(1).setSelected();
-
- await wrapper.vm.$nextTick();
-
- expect(findFormFields().at(0).isVisible()).toBe(true);
- });
-
- it('disables the dropdown and shows help text when multi integrations are not supported', async () => {
- createComponent({ props: { canAddIntegration: false } });
- expect(findSelect().attributes('disabled')).toBe('disabled');
- expect(findMultiSupportText().exists()).toBe(true);
- });
-
- it('disabled the name input when the selected value is prometheus', async () => {
- createComponent();
- const options = findSelect().findAll('option');
- await options.at(2).setSelected();
-
- expect(findFormFields().at(0).attributes('disabled')).toBe('disabled');
- });
- });
-
- describe('submitting integration form', () => {
- it('allows for create-new-integration with the correct form values for HTTP', async () => {
- createComponent();
-
- const options = findSelect().findAll('option');
- await options.at(1).setSelected();
-
- await findFormFields().at(0).setValue('Test integration');
- await findFormToggle().trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(findSubmitButton().exists()).toBe(true);
- expect(findSubmitButton().text()).toBe('Save integration');
-
- findForm().trigger('submit');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('create-new-integration')).toBeTruthy();
- expect(wrapper.emitted('create-new-integration')[0]).toEqual([
- { type: typeSet.http, variables: { name: 'Test integration', active: true } },
- ]);
- });
-
- it('allows for create-new-integration with the correct form values for PROMETHEUS', async () => {
- createComponent();
-
- const options = findSelect().findAll('option');
- await options.at(2).setSelected();
-
- await findFormFields().at(0).setValue('Test integration');
- await findFormFields().at(1).setValue('https://test.com');
- await findFormToggle().trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(findSubmitButton().exists()).toBe(true);
- expect(findSubmitButton().text()).toBe('Save integration');
-
- findForm().trigger('submit');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('create-new-integration')).toBeTruthy();
- expect(wrapper.emitted('create-new-integration')[0]).toEqual([
- { type: typeSet.prometheus, variables: { apiUrl: 'https://test.com', active: true } },
- ]);
- });
-
- it('allows for update-integration with the correct form values for HTTP', async () => {
- createComponent({
- data: {
- selectedIntegration: typeSet.http,
- currentIntegration: { id: '1', name: 'Test integration pre' },
- },
- props: {
- loading: false,
- },
- });
-
- await findFormFields().at(0).setValue('Test integration post');
- await findFormToggle().trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(findSubmitButton().exists()).toBe(true);
- expect(findSubmitButton().text()).toBe('Save integration');
-
- findForm().trigger('submit');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('update-integration')).toBeTruthy();
- expect(wrapper.emitted('update-integration')[0]).toEqual([
- { type: typeSet.http, variables: { name: 'Test integration post', active: true } },
- ]);
- });
-
- it('allows for update-integration with the correct form values for PROMETHEUS', async () => {
- createComponent({
- data: {
- selectedIntegration: typeSet.prometheus,
- currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' },
- },
- props: {
- loading: false,
- },
- });
-
- await findFormFields().at(0).setValue('Test integration');
- await findFormFields().at(1).setValue('https://test-post.com');
- await findFormToggle().trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(findSubmitButton().exists()).toBe(true);
- expect(findSubmitButton().text()).toBe('Save integration');
-
- findForm().trigger('submit');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('update-integration')).toBeTruthy();
- expect(wrapper.emitted('update-integration')[0]).toEqual([
- { type: typeSet.prometheus, variables: { apiUrl: 'https://test-post.com', active: true } },
- ]);
- });
- });
-
- describe('submitting the integration with a JSON test payload', () => {
- beforeEach(() => {
- createComponent({
- data: {
- selectedIntegration: typeSet.http,
- currentIntegration: { id: '1', name: 'Test' },
- active: true,
- },
- props: {
- loading: false,
- },
- });
- });
-
- it('should not allow a user to test invalid JSON', async () => {
- jest.useFakeTimers();
- await findJsonTextArea().setValue('Invalid JSON');
-
- jest.runAllTimers();
- await wrapper.vm.$nextTick();
-
- expect(findJsonTestSubmit().exists()).toBe(true);
- expect(findJsonTestSubmit().text()).toBe('Save and test payload');
- expect(findJsonTestSubmit().props('disabled')).toBe(true);
- });
-
- it('should allow for the form to be automatically saved if the test payload is successfully submitted', async () => {
- jest.useFakeTimers();
- await findJsonTextArea().setValue('{ "value": "value" }');
-
- jest.runAllTimers();
- await wrapper.vm.$nextTick();
- expect(findJsonTestSubmit().props('disabled')).toBe(false);
- });
- });
-
- describe('Test payload section for HTTP integration', () => {
- beforeEach(() => {
- createComponent({
- multipleHttpIntegrationsCustomMapping: true,
- props: {
- currentIntegration: {
- type: typeSet.http,
- },
- },
- });
- });
-
- describe.each`
- active | resetSamplePayloadConfirmed | disabled
- ${true} | ${true} | ${undefined}
- ${false} | ${true} | ${'disabled'}
- ${true} | ${false} | ${'disabled'}
- ${false} | ${false} | ${'disabled'}
- `('', ({ active, resetSamplePayloadConfirmed, disabled }) => {
- const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed';
- const enabledState = disabled === 'disabled' ? 'disabled' : 'enabled';
- const activeState = active ? 'active' : 'not active';
-
- it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and current integration is ${activeState}`, async () => {
- wrapper.setData({
- customMapping: { samplePayload: true },
- active,
- resetSamplePayloadConfirmed,
- });
- await wrapper.vm.$nextTick();
- expect(findTestPayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(disabled);
- });
- });
-
- describe('action buttons for sample payload', () => {
- describe.each`
- resetSamplePayloadConfirmed | samplePayload | caption
- ${false} | ${true} | ${'Edit payload'}
- ${true} | ${false} | ${'Submit payload'}
- ${true} | ${true} | ${'Submit payload'}
- ${false} | ${false} | ${'Submit payload'}
- `('', ({ resetSamplePayloadConfirmed, samplePayload, caption }) => {
- const samplePayloadMsg = samplePayload ? 'was provided' : 'was not provided';
- const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed';
-
- it(`shows ${caption} button when sample payload ${samplePayloadMsg} and payload reset ${payloadResetMsg}`, async () => {
- wrapper.setData({
- selectedIntegration: typeSet.http,
- customMapping: { samplePayload },
- resetSamplePayloadConfirmed,
- });
- await wrapper.vm.$nextTick();
- expect(findActionBtn().text()).toBe(caption);
- });
- });
- });
-
- describe('Parsing payload', () => {
- it('displays a toast message on successful parse', async () => {
- jest.useFakeTimers();
- wrapper.setData({
- selectedIntegration: typeSet.http,
- customMapping: { samplePayload: false },
- });
- await wrapper.vm.$nextTick();
-
- findActionBtn().vm.$emit('click');
- jest.advanceTimersByTime(1000);
-
- await waitForPromises();
-
- expect(mockToastShow).toHaveBeenCalledWith(
- 'Sample payload has been parsed. You can now map the fields.',
- );
- });
- });
- });
-
- describe('Mapping builder section', () => {
- describe.each`
- featureFlag | integrationOption | visible
- ${true} | ${1} | ${true}
- ${true} | ${2} | ${false}
- ${false} | ${1} | ${false}
- ${false} | ${2} | ${false}
- `('', ({ featureFlag, integrationOption, visible }) => {
- const visibleMsg = visible ? 'is rendered' : 'is not rendered';
- const featureFlagMsg = featureFlag ? 'is enabled' : 'is disabled';
- const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
-
- it(`${visibleMsg} when multipleHttpIntegrationsCustomMapping feature flag ${featureFlagMsg} and integration type is ${integrationType}`, async () => {
- createComponent({ multipleHttpIntegrationsCustomMapping: featureFlag });
- const options = findSelect().findAll('option');
- options.at(integrationOption).setSelected();
- await wrapper.vm.$nextTick();
- expect(findMappingBuilderSection().exists()).toBe(visible);
- });
- });
- });
-});
diff --git a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
deleted file mode 100644
index 4d0732ca76c..00000000000
--- a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
+++ /dev/null
@@ -1,379 +0,0 @@
-import VueApollo from 'vue-apollo';
-import { mount, createLocalVue } from '@vue/test-utils';
-import AxiosMockAdapter from 'axios-mock-adapter';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
-import { GlLoadingIcon } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
-import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
-import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
-import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
-import getIntegrationsQuery from '~/alerts_settings/graphql/queries/get_integrations.query.graphql';
-import createHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
-import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql';
-import updateHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
-import updatePrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql';
-import destroyHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql';
-import resetHttpTokenMutation from '~/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql';
-import resetPrometheusTokenMutation from '~/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql';
-import { typeSet } from '~/alerts_settings/constants';
-import {
- ADD_INTEGRATION_ERROR,
- RESET_INTEGRATION_TOKEN_ERROR,
- UPDATE_INTEGRATION_ERROR,
- INTEGRATION_PAYLOAD_TEST_ERROR,
- DELETE_INTEGRATION_ERROR,
-} from '~/alerts_settings/utils/error_messages';
-import createFlash from '~/flash';
-import { defaultAlertSettingsConfig } from './util';
-import mockIntegrations from './mocks/integrations.json';
-import {
- createHttpVariables,
- updateHttpVariables,
- createPrometheusVariables,
- updatePrometheusVariables,
- ID,
- errorMsg,
- getIntegrationsQueryResponse,
- destroyIntegrationResponse,
- integrationToDestroy,
- destroyIntegrationResponseWithErrors,
-} from './mocks/apollo_mock';
-
-jest.mock('~/flash');
-
-const localVue = createLocalVue();
-
-describe('AlertsSettingsWrapper', () => {
- let wrapper;
- let fakeApollo;
- let destroyIntegrationHandler;
- useMockIntersectionObserver();
-
- const findLoader = () => wrapper.find(IntegrationsList).find(GlLoadingIcon);
- const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr');
-
- async function destroyHttpIntegration(localWrapper) {
- await jest.runOnlyPendingTimers();
- await localWrapper.vm.$nextTick();
-
- localWrapper
- .find(IntegrationsList)
- .vm.$emit('delete-integration', { id: integrationToDestroy.id });
- }
-
- async function awaitApolloDomMock() {
- await wrapper.vm.$nextTick(); // kick off the DOM update
- await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
- await wrapper.vm.$nextTick(); // kick off the DOM update for flash
- }
-
- const createComponent = ({ data = {}, provide = {}, loading = false } = {}) => {
- wrapper = mount(AlertsSettingsWrapper, {
- data() {
- return { ...data };
- },
- provide: {
- ...defaultAlertSettingsConfig,
- ...provide,
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- query: jest.fn(),
- queries: {
- integrations: {
- loading,
- },
- },
- },
- },
- });
- };
-
- function createComponentWithApollo({
- destroyHandler = jest.fn().mockResolvedValue(destroyIntegrationResponse),
- } = {}) {
- localVue.use(VueApollo);
- destroyIntegrationHandler = destroyHandler;
-
- const requestHandlers = [
- [getIntegrationsQuery, jest.fn().mockResolvedValue(getIntegrationsQueryResponse)],
- [destroyHttpIntegrationMutation, destroyIntegrationHandler],
- ];
-
- fakeApollo = createMockApollo(requestHandlers);
-
- wrapper = mount(AlertsSettingsWrapper, {
- localVue,
- apolloProvider: fakeApollo,
- provide: {
- ...defaultAlertSettingsConfig,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('rendered via default permissions', () => {
- it('renders the GraphQL alerts integrations list and new form', () => {
- createComponent();
- expect(wrapper.find(IntegrationsList).exists()).toBe(true);
- expect(wrapper.find(AlertsSettingsForm).exists()).toBe(true);
- });
-
- it('uses a loading state inside the IntegrationsList table', () => {
- createComponent({
- data: { integrations: {} },
- loading: true,
- });
- expect(wrapper.find(IntegrationsList).exists()).toBe(true);
- expect(findLoader().exists()).toBe(true);
- });
-
- it('renders the IntegrationsList table using the API data', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
- expect(findLoader().exists()).toBe(false);
- expect(findIntegrations()).toHaveLength(mockIntegrations.length);
- });
-
- it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
- });
- wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {
- type: typeSet.http,
- variables: createHttpVariables,
- });
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: createHttpIntegrationMutation,
- update: expect.anything(),
- variables: createHttpVariables,
- });
- });
-
- it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { updateHttpIntegrationMutation: { integration: { id: '1' } } },
- });
- wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {
- type: typeSet.http,
- variables: updateHttpVariables,
- });
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: updateHttpIntegrationMutation,
- variables: updateHttpVariables,
- });
- });
-
- it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { resetHttpTokenMutation: { integration: { id: '1' } } },
- });
- wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {
- type: typeSet.http,
- variables: { id: ID },
- });
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: resetHttpTokenMutation,
- variables: {
- id: ID,
- },
- });
- });
-
- it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } },
- });
- wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {
- type: typeSet.prometheus,
- variables: createPrometheusVariables,
- });
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: createPrometheusIntegrationMutation,
- update: expect.anything(),
- variables: createPrometheusVariables,
- });
- });
-
- it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } },
- });
- wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {
- type: typeSet.prometheus,
- variables: updatePrometheusVariables,
- });
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: updatePrometheusIntegrationMutation,
- variables: updatePrometheusVariables,
- });
- });
-
- it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
- data: { resetPrometheusTokenMutation: { integration: { id: '1' } } },
- });
- wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {
- type: typeSet.prometheus,
- variables: { id: ID },
- });
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: resetPrometheusTokenMutation,
- variables: {
- id: ID,
- },
- });
- });
-
- it('shows an error alert when integration creation fails ', async () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(ADD_INTEGRATION_ERROR);
- wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {});
-
- await waitForPromises();
-
- expect(createFlash).toHaveBeenCalledWith({ message: ADD_INTEGRATION_ERROR });
- });
-
- it('shows an error alert when integration token reset fails ', async () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(RESET_INTEGRATION_TOKEN_ERROR);
-
- wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {});
-
- await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR });
- });
-
- it('shows an error alert when integration update fails ', async () => {
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
-
- wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {});
-
- await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
- });
-
- it('shows an error alert when integration test payload fails ', async () => {
- const mock = new AxiosMockAdapter(axios);
- mock.onPost(/(.*)/).replyOnce(403);
- createComponent({
- data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
- loading: false,
- });
-
- return wrapper.vm.validateAlertPayload({ endpoint: '', data: '', token: '' }).then(() => {
- expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
- expect(createFlash).toHaveBeenCalledTimes(1);
- mock.restore();
- });
- });
- });
-
- describe('with mocked Apollo client', () => {
- it('has a selection of integrations loaded via the getIntegrationsQuery', async () => {
- createComponentWithApollo();
-
- await jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- expect(findIntegrations()).toHaveLength(4);
- });
-
- it('calls a mutation with correct parameters and destroys a integration', async () => {
- createComponentWithApollo();
-
- await destroyHttpIntegration(wrapper);
-
- expect(destroyIntegrationHandler).toHaveBeenCalled();
-
- await wrapper.vm.$nextTick();
-
- expect(findIntegrations()).toHaveLength(3);
- });
-
- it('displays flash if mutation had a recoverable error', async () => {
- createComponentWithApollo({
- destroyHandler: jest.fn().mockResolvedValue(destroyIntegrationResponseWithErrors),
- });
-
- await destroyHttpIntegration(wrapper);
- await awaitApolloDomMock();
-
- expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
- });
-
- it('displays flash if mutation had a non-recoverable error', async () => {
- createComponentWithApollo({
- destroyHandler: jest.fn().mockRejectedValue('Error'),
- });
-
- await destroyHttpIntegration(wrapper);
- await awaitApolloDomMock();
-
- expect(createFlash).toHaveBeenCalledWith({
- message: DELETE_INTEGRATION_ERROR,
- });
- });
- });
-});
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap
new file mode 100644
index 00000000000..eb2b82a0211
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/__snapshots__/alerts_settings_form_spec.js.snap
@@ -0,0 +1,406 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
+<form
+ class="gl-mt-6"
+>
+ <h5
+ class="gl-font-lg gl-my-5"
+ >
+ Add new integrations
+ </h5>
+
+ <div
+ class="form-group gl-form-group"
+ id="integration-type"
+ role="group"
+ >
+ <label
+ class="d-block col-form-label"
+ for="integration-type"
+ id="integration-type__BV_label_"
+ >
+ 1. Select integration type
+ </label>
+ <div
+ class="bv-no-focus-ring"
+ >
+ <select
+ class="gl-form-select mw-100 custom-select"
+ id="__BVID__8"
+ >
+ <option
+ value=""
+ >
+ Select integration type
+ </option>
+ <option
+ value="HTTP"
+ >
+ HTTP Endpoint
+ </option>
+ <option
+ value="PROMETHEUS"
+ >
+ External Prometheus
+ </option>
+ </select>
+
+ <!---->
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+
+ <transition-stub
+ class="gl-mt-3"
+ css="true"
+ enteractiveclass="collapsing"
+ enterclass=""
+ entertoclass="collapse show"
+ leaveactiveclass="collapsing"
+ leaveclass="collapse show"
+ leavetoclass="collapse"
+ >
+ <div
+ class="collapse"
+ id="__BVID__10"
+ style="display: none;"
+ >
+ <div>
+ <div
+ class="form-group gl-form-group"
+ id="name-integration"
+ role="group"
+ >
+ <label
+ class="d-block col-form-label"
+ for="name-integration"
+ id="name-integration__BV_label_"
+ >
+ 2. Name integration
+ </label>
+ <div
+ class="bv-no-focus-ring"
+ >
+ <input
+ class="gl-form-input form-control"
+ id="__BVID__15"
+ placeholder="Enter integration name"
+ type="text"
+ />
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+
+ <div
+ class="form-group gl-form-group"
+ id="integration-webhook"
+ role="group"
+ >
+ <label
+ class="d-block col-form-label"
+ for="integration-webhook"
+ id="integration-webhook__BV_label_"
+ >
+ 3. Set up webhook
+ </label>
+ <div
+ class="bv-no-focus-ring"
+ >
+ <span>
+ Utilize the URL and authorization key below to authorize an external service to send alerts to GitLab. Review your external service's documentation to learn where to add these details, and the
+ <a
+ class="gl-link gl-display-inline-block"
+ href="https://docs.gitlab.com/ee/operations/incident_management/alert_integrations.html"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ GitLab documentation
+ </a>
+ to learn more about configuring your endpoint.
+ </span>
+
+ <label
+ class="gl-display-flex gl-flex-direction-column gl-mb-0 gl-w-max-content gl-my-4 gl-font-weight-normal"
+ >
+ <span
+ class="gl-toggle-wrapper"
+ >
+ <span
+ class="gl-toggle-label"
+ data-testid="toggle-label"
+ >
+ Active
+ </span>
+
+ <!---->
+
+ <button
+ aria-label="Active"
+ class="gl-toggle"
+ role="switch"
+ type="button"
+ >
+ <span
+ class="toggle-icon"
+ >
+ <svg
+ aria-hidden="true"
+ class="gl-icon s16"
+ data-testid="close-icon"
+ >
+ <use
+ href="#close"
+ />
+ </svg>
+ </span>
+ </button>
+ </span>
+
+ <!---->
+ </label>
+
+ <!---->
+
+ <div
+ class="gl-my-4"
+ >
+ <span
+ class="gl-font-weight-bold"
+ >
+
+ Webhook URL
+
+ </span>
+
+ <div
+ id="url"
+ readonly="readonly"
+ >
+ <div
+ class="input-group"
+ role="group"
+ >
+ <!---->
+ <!---->
+
+ <input
+ class="gl-form-input form-control"
+ id="url"
+ readonly="readonly"
+ type="text"
+ />
+
+ <div
+ class="input-group-append"
+ >
+ <button
+ aria-label="Copy this value"
+ class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon"
+ data-clipboard-text=""
+ title="Copy"
+ type="button"
+ >
+ <!---->
+
+ <svg
+ aria-hidden="true"
+ class="gl-button-icon gl-icon s16"
+ data-testid="copy-to-clipboard-icon"
+ >
+ <use
+ href="#copy-to-clipboard"
+ />
+ </svg>
+
+ <!---->
+ </button>
+ </div>
+ <!---->
+ </div>
+ </div>
+ </div>
+
+ <div
+ class="gl-my-4"
+ >
+ <span
+ class="gl-font-weight-bold"
+ >
+
+ Authorization key
+
+ </span>
+
+ <div
+ class="gl-mb-3"
+ id="authorization-key"
+ readonly="readonly"
+ >
+ <div
+ class="input-group"
+ role="group"
+ >
+ <!---->
+ <!---->
+
+ <input
+ class="gl-form-input form-control"
+ id="authorization-key"
+ readonly="readonly"
+ type="text"
+ />
+
+ <div
+ class="input-group-append"
+ >
+ <button
+ aria-label="Copy this value"
+ class="btn gl-m-0! btn-default btn-md gl-button btn-default-secondary btn-icon"
+ data-clipboard-text=""
+ title="Copy"
+ type="button"
+ >
+ <!---->
+
+ <svg
+ aria-hidden="true"
+ class="gl-button-icon gl-icon s16"
+ data-testid="copy-to-clipboard-icon"
+ >
+ <use
+ href="#copy-to-clipboard"
+ />
+ </svg>
+
+ <!---->
+ </button>
+ </div>
+ <!---->
+ </div>
+ </div>
+
+ <button
+ class="btn btn-default btn-md disabled gl-button"
+ disabled="disabled"
+ type="button"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+
+ Reset Key
+
+ </span>
+ </button>
+
+ <!---->
+ </div>
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+
+ <div
+ class="form-group gl-form-group"
+ id="test-integration"
+ role="group"
+ >
+ <label
+ class="d-block col-form-label"
+ for="test-integration"
+ id="test-integration__BV_label_"
+ >
+ 4. Sample alert payload (optional)
+ </label>
+ <div
+ class="bv-no-focus-ring"
+ >
+ <span>
+ Provide an example payload from the monitoring tool you intend to integrate with. This payload can be used to test the integration (optional).
+ </span>
+
+ <textarea
+ class="gl-form-input gl-form-textarea gl-my-3 form-control is-valid"
+ disabled="disabled"
+ id="test-payload"
+ placeholder="{ \\"events\\": [{ \\"application\\": \\"Name of application\\" }] }"
+ style="resize: none; overflow-y: scroll;"
+ wrap="soft"
+ />
+ <!---->
+ <!---->
+ <!---->
+ </div>
+ </div>
+
+ <!---->
+
+ <!---->
+ </div>
+
+ <div
+ class="gl-display-flex gl-justify-content-start gl-py-3"
+ >
+ <button
+ class="btn js-no-auto-disable btn-success btn-md gl-button"
+ data-testid="integration-form-submit"
+ type="submit"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+ Save integration
+
+ </span>
+ </button>
+
+ <button
+ class="btn gl-mx-3 js-no-auto-disable btn-success btn-md disabled gl-button btn-success-secondary"
+ data-testid="integration-test-and-submit"
+ disabled="disabled"
+ type="button"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+ Save and test payload
+ </span>
+ </button>
+
+ <button
+ class="btn js-no-auto-disable btn-default btn-md gl-button"
+ type="reset"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+ Cancel
+ </span>
+ </button>
+ </div>
+ </div>
+ </transition-stub>
+</form>
+`;
diff --git a/spec/frontend/alerts_settings/components/alert_mapping_builder_spec.js b/spec/frontend/alerts_settings/components/alert_mapping_builder_spec.js
new file mode 100644
index 00000000000..7e1d1acb62c
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/alert_mapping_builder_spec.js
@@ -0,0 +1,102 @@
+import { GlIcon, GlFormInput, GlDropdown, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AlertMappingBuilder, { i18n } from '~/alerts_settings/components/alert_mapping_builder.vue';
+import parsedMapping from '~/alerts_settings/components/mocks/parsedMapping.json';
+import * as transformationUtils from '~/alerts_settings/utils/mapping_transformations';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import alertFields from '../mocks/alertFields.json';
+
+describe('AlertMappingBuilder', () => {
+ let wrapper;
+
+ function mountComponent() {
+ wrapper = shallowMount(AlertMappingBuilder, {
+ propsData: {
+ parsedPayload: parsedMapping.samplePayload.payloadAlerFields.nodes,
+ savedMapping: parsedMapping.storedMapping.nodes,
+ alertFields,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ const findColumnInRow = (row, column) =>
+ wrapper.findAll('.gl-display-table-row').at(row).findAll('.gl-display-table-cell ').at(column);
+
+ it('renders column captions', () => {
+ expect(findColumnInRow(0, 0).text()).toContain(i18n.columns.gitlabKeyTitle);
+ expect(findColumnInRow(0, 2).text()).toContain(i18n.columns.payloadKeyTitle);
+ expect(findColumnInRow(0, 3).text()).toContain(i18n.columns.fallbackKeyTitle);
+
+ const fallbackColumnIcon = findColumnInRow(0, 3).find(GlIcon);
+ expect(fallbackColumnIcon.exists()).toBe(true);
+ expect(fallbackColumnIcon.attributes('name')).toBe('question');
+ expect(fallbackColumnIcon.attributes('title')).toBe(i18n.fallbackTooltip);
+ });
+
+ it('renders disabled form input for each mapped field', () => {
+ alertFields.forEach((field, index) => {
+ const input = findColumnInRow(index + 1, 0).find(GlFormInput);
+ const types = field.types.map((t) => capitalizeFirstCharacter(t.toLowerCase())).join(' or ');
+ expect(input.attributes('value')).toBe(`${field.label} (${types})`);
+ expect(input.attributes('disabled')).toBe('');
+ });
+ });
+
+ it('renders right arrow next to each input', () => {
+ alertFields.forEach((field, index) => {
+ const arrow = findColumnInRow(index + 1, 1).find('.right-arrow');
+ expect(arrow.exists()).toBe(true);
+ });
+ });
+
+ it('renders mapping dropdown for each field', () => {
+ alertFields.forEach(({ types }, index) => {
+ const dropdown = findColumnInRow(index + 1, 2).find(GlDropdown);
+ const searchBox = dropdown.findComponent(GlSearchBoxByType);
+ const dropdownItems = dropdown.findAllComponents(GlDropdownItem);
+ const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
+ const mappingOptions = nodes.filter(({ type }) => types.includes(type));
+
+ expect(dropdown.exists()).toBe(true);
+ expect(searchBox.exists()).toBe(true);
+ expect(dropdownItems).toHaveLength(mappingOptions.length);
+ });
+ });
+
+ it('renders fallback dropdown only for the fields that have fallback', () => {
+ alertFields.forEach(({ types, numberOfFallbacks }, index) => {
+ const dropdown = findColumnInRow(index + 1, 3).find(GlDropdown);
+ expect(dropdown.exists()).toBe(Boolean(numberOfFallbacks));
+
+ if (numberOfFallbacks) {
+ const searchBox = dropdown.findComponent(GlSearchBoxByType);
+ const dropdownItems = dropdown.findAllComponents(GlDropdownItem);
+ const { nodes } = parsedMapping.samplePayload.payloadAlerFields;
+ const mappingOptions = nodes.filter(({ type }) => types.includes(type));
+
+ expect(searchBox.exists()).toBe(Boolean(numberOfFallbacks));
+ expect(dropdownItems).toHaveLength(mappingOptions.length);
+ }
+ });
+ });
+
+ it('emits event with selected mapping', () => {
+ const mappingToSave = { fieldName: 'TITLE', mapping: 'PARSED_TITLE' };
+ jest.spyOn(transformationUtils, 'transformForSave').mockReturnValue(mappingToSave);
+ const dropdown = findColumnInRow(1, 2).find(GlDropdown);
+ const option = dropdown.find(GlDropdownItem);
+ option.vm.$emit('click');
+ expect(wrapper.emitted('onMappingUpdate')[0]).toEqual([mappingToSave]);
+ });
+});
diff --git a/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js
new file mode 100644
index 00000000000..c43d78a1cf3
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/alerts_integrations_list_spec.js
@@ -0,0 +1,118 @@
+import { GlTable, GlIcon, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import AlertIntegrationsList, {
+ i18n,
+} from '~/alerts_settings/components/alerts_integrations_list.vue';
+import { trackAlertIntegrationsViewsOptions } from '~/alerts_settings/constants';
+import Tracking from '~/tracking';
+
+const mockIntegrations = [
+ {
+ id: '1',
+ active: true,
+ name: 'Integration 1',
+ type: 'HTTP endpoint',
+ },
+ {
+ id: '2',
+ active: false,
+ name: 'Integration 2',
+ type: 'HTTP endpoint',
+ },
+];
+
+describe('AlertIntegrationsList', () => {
+ let wrapper;
+ const { trigger: triggerIntersection } = useMockIntersectionObserver();
+
+ function mountComponent({ data = {}, props = {} } = {}) {
+ wrapper = mount(AlertIntegrationsList, {
+ data() {
+ return { ...data };
+ },
+ propsData: {
+ integrations: mockIntegrations,
+ ...props,
+ },
+ stubs: {
+ GlIcon: true,
+ GlButton: true,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ const findTableComponent = () => wrapper.find(GlTable);
+ const findTableComponentRows = () => wrapper.find(GlTable).findAll('table tbody tr');
+ const finsStatusCell = () => wrapper.findAll('[data-testid="integration-activated-status"]');
+
+ it('renders a table', () => {
+ expect(findTableComponent().exists()).toBe(true);
+ });
+
+ it('renders an empty state when no integrations provided', () => {
+ mountComponent({ props: { integrations: [] } });
+ expect(findTableComponent().text()).toContain(i18n.emptyState);
+ });
+
+ it('renders an an edit and delete button for each integration', () => {
+ expect(findTableComponent().findAll(GlButton).length).toBe(4);
+ });
+
+ it('renders an highlighted row when a current integration is selected to edit', () => {
+ mountComponent({ data: { currentIntegration: { id: '1' } } });
+ expect(findTableComponentRows().at(0).classes()).toContain('gl-bg-blue-50');
+ });
+
+ describe('integration status', () => {
+ it('enabled', () => {
+ const cell = finsStatusCell().at(0);
+ const activatedIcon = cell.find(GlIcon);
+ expect(cell.text()).toBe(i18n.status.enabled.name);
+ expect(activatedIcon.attributes('name')).toBe('check-circle-filled');
+ expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
+ });
+
+ it('disabled', () => {
+ const cell = finsStatusCell().at(1);
+ const notActivatedIcon = cell.find(GlIcon);
+ expect(cell.text()).toBe(i18n.status.disabled.name);
+ expect(notActivatedIcon.attributes('name')).toBe('warning-solid');
+ expect(notActivatedIcon.attributes('title')).toBe(i18n.status.disabled.tooltip);
+ });
+ });
+
+ describe('Snowplow tracking', () => {
+ beforeEach(() => {
+ mountComponent();
+ jest.spyOn(Tracking, 'event');
+ });
+
+ it('should NOT track alert list page views when list is collapsed', () => {
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: false } });
+
+ expect(Tracking.event).not.toHaveBeenCalled();
+ });
+
+ it('should track alert list page views only once when list is expanded', () => {
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
+ triggerIntersection(wrapper.vm.$el, { entry: { isIntersecting: true } });
+
+ const { category, action } = trackAlertIntegrationsViewsOptions;
+ expect(Tracking.event).toHaveBeenCalledTimes(1);
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
new file mode 100644
index 00000000000..02229b3d3da
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
@@ -0,0 +1,385 @@
+import {
+ GlForm,
+ GlFormSelect,
+ GlCollapse,
+ GlFormInput,
+ GlToggle,
+ GlFormTextarea,
+} from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+import MappingBuilder from '~/alerts_settings/components/alert_mapping_builder.vue';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
+import { typeSet } from '~/alerts_settings/constants';
+import alertFields from '../mocks/alertFields.json';
+import { defaultAlertSettingsConfig } from './util';
+
+describe('AlertsSettingsForm', () => {
+ let wrapper;
+ const mockToastShow = jest.fn();
+
+ const createComponent = ({
+ data = {},
+ props = {},
+ multipleHttpIntegrationsCustomMapping = false,
+ multiIntegrations = true,
+ } = {}) => {
+ wrapper = mount(AlertsSettingsForm, {
+ data() {
+ return { ...data };
+ },
+ propsData: {
+ loading: false,
+ canAddIntegration: true,
+ ...props,
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ glFeatures: { multipleHttpIntegrationsCustomMapping },
+ multiIntegrations,
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ });
+ };
+
+ const findForm = () => wrapper.find(GlForm);
+ const findSelect = () => wrapper.find(GlFormSelect);
+ const findFormSteps = () => wrapper.find(GlCollapse);
+ const findFormFields = () => wrapper.findAll(GlFormInput);
+ const findFormToggle = () => wrapper.find(GlToggle);
+ const findTestPayloadSection = () => wrapper.find(`[id = "test-integration"]`);
+ const findMappingBuilderSection = () => wrapper.find(`[id = "mapping-builder"]`);
+ const findMappingBuilder = () => wrapper.findComponent(MappingBuilder);
+ const findSubmitButton = () => wrapper.find(`[type = "submit"]`);
+ const findMultiSupportText = () =>
+ wrapper.find(`[data-testid="multi-integrations-not-supported"]`);
+ const findJsonTestSubmit = () => wrapper.find(`[data-testid="integration-test-and-submit"]`);
+ const findJsonTextArea = () => wrapper.find(`[id = "test-payload"]`);
+ const findActionBtn = () => wrapper.find(`[data-testid="payload-action-btn"]`);
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const selectOptionAtIndex = async (index) => {
+ const options = findSelect().findAll('option');
+ await options.at(index).setSelected();
+ };
+
+ const enableIntegration = (index, value) => {
+ findFormFields().at(index).setValue(value);
+ findFormToggle().trigger('click');
+ };
+
+ describe('with default values', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the initial template', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('render the initial form with only an integration type dropdown', () => {
+ expect(findForm().exists()).toBe(true);
+ expect(findSelect().exists()).toBe(true);
+ expect(findMultiSupportText().exists()).toBe(false);
+ expect(findFormSteps().attributes('visible')).toBeUndefined();
+ });
+
+ it('shows the rest of the form when the dropdown is used', async () => {
+ await selectOptionAtIndex(1);
+
+ expect(findFormFields().at(0).isVisible()).toBe(true);
+ });
+
+ it('disables the dropdown and shows help text when multi integrations are not supported', async () => {
+ createComponent({ props: { canAddIntegration: false } });
+ expect(findSelect().attributes('disabled')).toBe('disabled');
+ expect(findMultiSupportText().exists()).toBe(true);
+ });
+
+ it('disabled the name input when the selected value is prometheus', async () => {
+ createComponent();
+ await selectOptionAtIndex(2);
+
+ expect(findFormFields().at(0).attributes('disabled')).toBe('disabled');
+ });
+ });
+
+ describe('submitting integration form', () => {
+ describe('HTTP', () => {
+ it('create', async () => {
+ createComponent();
+
+ const integrationName = 'Test integration';
+ await selectOptionAtIndex(1);
+ enableIntegration(0, integrationName);
+
+ const submitBtn = findSubmitButton();
+ expect(submitBtn.exists()).toBe(true);
+ expect(submitBtn.text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ expect(wrapper.emitted('create-new-integration')[0]).toEqual([
+ { type: typeSet.http, variables: { name: integrationName, active: true } },
+ ]);
+ });
+
+ it('create with custom mapping', async () => {
+ createComponent({
+ multipleHttpIntegrationsCustomMapping: true,
+ multiIntegrations: true,
+ props: { alertFields },
+ });
+
+ const integrationName = 'Test integration';
+ await selectOptionAtIndex(1);
+
+ enableIntegration(0, integrationName);
+
+ const sampleMapping = { field: 'test' };
+ findMappingBuilder().vm.$emit('onMappingUpdate', sampleMapping);
+ findForm().trigger('submit');
+
+ expect(wrapper.emitted('create-new-integration')[0]).toEqual([
+ {
+ type: typeSet.http,
+ variables: {
+ name: integrationName,
+ active: true,
+ payloadAttributeMappings: sampleMapping,
+ payloadExample: null,
+ },
+ },
+ ]);
+ });
+
+ it('update', () => {
+ createComponent({
+ data: {
+ selectedIntegration: typeSet.http,
+ currentIntegration: { id: '1', name: 'Test integration pre' },
+ },
+ props: {
+ loading: false,
+ },
+ });
+ const updatedIntegrationName = 'Test integration post';
+ enableIntegration(0, updatedIntegrationName);
+
+ const submitBtn = findSubmitButton();
+ expect(submitBtn.exists()).toBe(true);
+ expect(submitBtn.text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ expect(wrapper.emitted('update-integration')[0]).toEqual([
+ { type: typeSet.http, variables: { name: updatedIntegrationName, active: true } },
+ ]);
+ });
+ });
+
+ describe('PROMETHEUS', () => {
+ it('create', async () => {
+ createComponent();
+
+ await selectOptionAtIndex(2);
+
+ const apiUrl = 'https://test.com';
+ enableIntegration(1, apiUrl);
+
+ findFormToggle().trigger('click');
+
+ const submitBtn = findSubmitButton();
+ expect(submitBtn.exists()).toBe(true);
+ expect(submitBtn.text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ expect(wrapper.emitted('create-new-integration')[0]).toEqual([
+ { type: typeSet.prometheus, variables: { apiUrl, active: true } },
+ ]);
+ });
+
+ it('update', () => {
+ createComponent({
+ data: {
+ selectedIntegration: typeSet.prometheus,
+ currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' },
+ },
+ props: {
+ loading: false,
+ },
+ });
+
+ const apiUrl = 'https://test-post.com';
+ enableIntegration(1, apiUrl);
+
+ const submitBtn = findSubmitButton();
+ expect(submitBtn.exists()).toBe(true);
+ expect(submitBtn.text()).toBe('Save integration');
+
+ findForm().trigger('submit');
+
+ expect(wrapper.emitted('update-integration')[0]).toEqual([
+ { type: typeSet.prometheus, variables: { apiUrl, active: true } },
+ ]);
+ });
+ });
+ });
+
+ describe('submitting the integration with a JSON test payload', () => {
+ beforeEach(() => {
+ createComponent({
+ data: {
+ selectedIntegration: typeSet.http,
+ currentIntegration: { id: '1', name: 'Test' },
+ active: true,
+ },
+ props: {
+ loading: false,
+ },
+ });
+ });
+
+ it('should not allow a user to test invalid JSON', async () => {
+ jest.useFakeTimers();
+ await findJsonTextArea().setValue('Invalid JSON');
+
+ jest.runAllTimers();
+ await wrapper.vm.$nextTick();
+
+ const jsonTestSubmit = findJsonTestSubmit();
+ expect(jsonTestSubmit.exists()).toBe(true);
+ expect(jsonTestSubmit.text()).toBe('Save and test payload');
+ expect(jsonTestSubmit.props('disabled')).toBe(true);
+ });
+
+ it('should allow for the form to be automatically saved if the test payload is successfully submitted', async () => {
+ jest.useFakeTimers();
+ await findJsonTextArea().setValue('{ "value": "value" }');
+
+ jest.runAllTimers();
+ await wrapper.vm.$nextTick();
+ expect(findJsonTestSubmit().props('disabled')).toBe(false);
+ });
+ });
+
+ describe('Test payload section for HTTP integration', () => {
+ beforeEach(() => {
+ createComponent({
+ multipleHttpIntegrationsCustomMapping: true,
+ props: {
+ currentIntegration: {
+ type: typeSet.http,
+ },
+ alertFields,
+ },
+ });
+ });
+
+ describe.each`
+ active | resetSamplePayloadConfirmed | disabled
+ ${true} | ${true} | ${undefined}
+ ${false} | ${true} | ${'disabled'}
+ ${true} | ${false} | ${'disabled'}
+ ${false} | ${false} | ${'disabled'}
+ `('', ({ active, resetSamplePayloadConfirmed, disabled }) => {
+ const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed';
+ const enabledState = disabled === 'disabled' ? 'disabled' : 'enabled';
+ const activeState = active ? 'active' : 'not active';
+
+ it(`textarea should be ${enabledState} when payload reset ${payloadResetMsg} and current integration is ${activeState}`, async () => {
+ wrapper.setData({
+ customMapping: { samplePayload: true },
+ active,
+ resetSamplePayloadConfirmed,
+ });
+ await wrapper.vm.$nextTick();
+ expect(findTestPayloadSection().find(GlFormTextarea).attributes('disabled')).toBe(disabled);
+ });
+ });
+
+ describe('action buttons for sample payload', () => {
+ describe.each`
+ resetSamplePayloadConfirmed | samplePayload | caption
+ ${false} | ${true} | ${'Edit payload'}
+ ${true} | ${false} | ${'Submit payload'}
+ ${true} | ${true} | ${'Submit payload'}
+ ${false} | ${false} | ${'Submit payload'}
+ `('', ({ resetSamplePayloadConfirmed, samplePayload, caption }) => {
+ const samplePayloadMsg = samplePayload ? 'was provided' : 'was not provided';
+ const payloadResetMsg = resetSamplePayloadConfirmed ? 'was confirmed' : 'was not confirmed';
+
+ it(`shows ${caption} button when sample payload ${samplePayloadMsg} and payload reset ${payloadResetMsg}`, async () => {
+ wrapper.setData({
+ selectedIntegration: typeSet.http,
+ customMapping: { samplePayload },
+ resetSamplePayloadConfirmed,
+ });
+ await wrapper.vm.$nextTick();
+ expect(findActionBtn().text()).toBe(caption);
+ });
+ });
+ });
+
+ describe('Parsing payload', () => {
+ it('displays a toast message on successful parse', async () => {
+ jest.useFakeTimers();
+ wrapper.setData({
+ selectedIntegration: typeSet.http,
+ customMapping: { samplePayload: false },
+ });
+ await wrapper.vm.$nextTick();
+
+ findActionBtn().vm.$emit('click');
+ jest.advanceTimersByTime(1000);
+
+ await waitForPromises();
+
+ expect(mockToastShow).toHaveBeenCalledWith(
+ 'Sample payload has been parsed. You can now map the fields.',
+ );
+ });
+ });
+ });
+
+ describe('Mapping builder section', () => {
+ describe.each`
+ alertFieldsProvided | multiIntegrations | featureFlag | integrationOption | visible
+ ${true} | ${true} | ${true} | ${1} | ${true}
+ ${true} | ${true} | ${true} | ${2} | ${false}
+ ${true} | ${true} | ${false} | ${1} | ${false}
+ ${true} | ${true} | ${false} | ${2} | ${false}
+ ${true} | ${false} | ${true} | ${1} | ${false}
+ ${false} | ${true} | ${true} | ${1} | ${false}
+ `('', ({ alertFieldsProvided, multiIntegrations, featureFlag, integrationOption, visible }) => {
+ const visibleMsg = visible ? 'is rendered' : 'is not rendered';
+ const featureFlagMsg = featureFlag ? 'is enabled' : 'is disabled';
+ const alertFieldsMsg = alertFieldsProvided ? 'are provided' : 'are not provided';
+ const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus;
+
+ it(`${visibleMsg} when multipleHttpIntegrationsCustomMapping feature flag ${featureFlagMsg} and integration type is ${integrationType} and alert fields ${alertFieldsMsg}`, async () => {
+ createComponent({
+ multipleHttpIntegrationsCustomMapping: featureFlag,
+ multiIntegrations,
+ props: {
+ alertFields: alertFieldsProvided ? alertFields : [],
+ },
+ });
+ await selectOptionAtIndex(integrationOption);
+
+ expect(findMappingBuilderSection().exists()).toBe(visible);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
new file mode 100644
index 00000000000..80293597ab6
--- /dev/null
+++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
@@ -0,0 +1,379 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import waitForPromises from 'helpers/wait_for_promises';
+import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
+import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
+import { typeSet } from '~/alerts_settings/constants';
+import createHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
+import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql';
+import destroyHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql';
+import resetHttpTokenMutation from '~/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql';
+import resetPrometheusTokenMutation from '~/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql';
+import updateHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
+import updatePrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql';
+import getIntegrationsQuery from '~/alerts_settings/graphql/queries/get_integrations.query.graphql';
+import {
+ ADD_INTEGRATION_ERROR,
+ RESET_INTEGRATION_TOKEN_ERROR,
+ UPDATE_INTEGRATION_ERROR,
+ INTEGRATION_PAYLOAD_TEST_ERROR,
+ DELETE_INTEGRATION_ERROR,
+} from '~/alerts_settings/utils/error_messages';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import {
+ createHttpVariables,
+ updateHttpVariables,
+ createPrometheusVariables,
+ updatePrometheusVariables,
+ ID,
+ errorMsg,
+ getIntegrationsQueryResponse,
+ destroyIntegrationResponse,
+ integrationToDestroy,
+ destroyIntegrationResponseWithErrors,
+} from './mocks/apollo_mock';
+import mockIntegrations from './mocks/integrations.json';
+import { defaultAlertSettingsConfig } from './util';
+
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+
+describe('AlertsSettingsWrapper', () => {
+ let wrapper;
+ let fakeApollo;
+ let destroyIntegrationHandler;
+ useMockIntersectionObserver();
+
+ const findLoader = () => wrapper.find(IntegrationsList).find(GlLoadingIcon);
+ const findIntegrations = () => wrapper.find(IntegrationsList).findAll('table tbody tr');
+
+ async function destroyHttpIntegration(localWrapper) {
+ await jest.runOnlyPendingTimers();
+ await localWrapper.vm.$nextTick();
+
+ localWrapper
+ .find(IntegrationsList)
+ .vm.$emit('delete-integration', { id: integrationToDestroy.id });
+ }
+
+ async function awaitApolloDomMock() {
+ await wrapper.vm.$nextTick(); // kick off the DOM update
+ await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
+ await wrapper.vm.$nextTick(); // kick off the DOM update for flash
+ }
+
+ const createComponent = ({ data = {}, provide = {}, loading = false } = {}) => {
+ wrapper = mount(AlertsSettingsWrapper, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ ...provide,
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ query: jest.fn(),
+ queries: {
+ integrations: {
+ loading,
+ },
+ },
+ },
+ },
+ });
+ };
+
+ function createComponentWithApollo({
+ destroyHandler = jest.fn().mockResolvedValue(destroyIntegrationResponse),
+ } = {}) {
+ localVue.use(VueApollo);
+ destroyIntegrationHandler = destroyHandler;
+
+ const requestHandlers = [
+ [getIntegrationsQuery, jest.fn().mockResolvedValue(getIntegrationsQueryResponse)],
+ [destroyHttpIntegrationMutation, destroyIntegrationHandler],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+
+ wrapper = mount(AlertsSettingsWrapper, {
+ localVue,
+ apolloProvider: fakeApollo,
+ provide: {
+ ...defaultAlertSettingsConfig,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('rendered via default permissions', () => {
+ it('renders the GraphQL alerts integrations list and new form', () => {
+ createComponent();
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsForm).exists()).toBe(true);
+ });
+
+ it('uses a loading state inside the IntegrationsList table', () => {
+ createComponent({
+ data: { integrations: {} },
+ loading: true,
+ });
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('renders the IntegrationsList table using the API data', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+ expect(findLoader().exists()).toBe(false);
+ expect(findIntegrations()).toHaveLength(mockIntegrations.length);
+ });
+
+ it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {
+ type: typeSet.http,
+ variables: createHttpVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createHttpIntegrationMutation,
+ update: expect.anything(),
+ variables: createHttpVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { updateHttpIntegrationMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {
+ type: typeSet.http,
+ variables: updateHttpVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updateHttpIntegrationMutation,
+ variables: updateHttpVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { resetHttpTokenMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {
+ type: typeSet.http,
+ variables: { id: ID },
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: resetHttpTokenMutation,
+ variables: {
+ id: ID,
+ },
+ });
+ });
+
+ it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } },
+ });
+ wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {
+ type: typeSet.prometheus,
+ variables: createPrometheusVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createPrometheusIntegrationMutation,
+ update: expect.anything(),
+ variables: createPrometheusVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } },
+ });
+ wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {
+ type: typeSet.prometheus,
+ variables: updatePrometheusVariables,
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updatePrometheusIntegrationMutation,
+ variables: updatePrometheusVariables,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
+ data: { resetPrometheusTokenMutation: { integration: { id: '1' } } },
+ });
+ wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {
+ type: typeSet.prometheus,
+ variables: { id: ID },
+ });
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: resetPrometheusTokenMutation,
+ variables: {
+ id: ID,
+ },
+ });
+ });
+
+ it('shows an error alert when integration creation fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(ADD_INTEGRATION_ERROR);
+ wrapper.find(AlertsSettingsForm).vm.$emit('create-new-integration', {});
+
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({ message: ADD_INTEGRATION_ERROR });
+ });
+
+ it('shows an error alert when integration token reset fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(RESET_INTEGRATION_TOKEN_ERROR);
+
+ wrapper.find(AlertsSettingsForm).vm.$emit('reset-token', {});
+
+ await waitForPromises();
+ expect(createFlash).toHaveBeenCalledWith({ message: RESET_INTEGRATION_TOKEN_ERROR });
+ });
+
+ it('shows an error alert when integration update fails ', async () => {
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
+
+ wrapper.find(AlertsSettingsForm).vm.$emit('update-integration', {});
+
+ await waitForPromises();
+ expect(createFlash).toHaveBeenCalledWith({ message: UPDATE_INTEGRATION_ERROR });
+ });
+
+ it('shows an error alert when integration test payload fails ', async () => {
+ const mock = new AxiosMockAdapter(axios);
+ mock.onPost(/(.*)/).replyOnce(403);
+ createComponent({
+ data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
+ loading: false,
+ });
+
+ return wrapper.vm.validateAlertPayload({ endpoint: '', data: '', token: '' }).then(() => {
+ expect(createFlash).toHaveBeenCalledWith({ message: INTEGRATION_PAYLOAD_TEST_ERROR });
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ mock.restore();
+ });
+ });
+ });
+
+ describe('with mocked Apollo client', () => {
+ it('has a selection of integrations loaded via the getIntegrationsQuery', async () => {
+ createComponentWithApollo();
+
+ await jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(findIntegrations()).toHaveLength(4);
+ });
+
+ it('calls a mutation with correct parameters and destroys a integration', async () => {
+ createComponentWithApollo();
+
+ await destroyHttpIntegration(wrapper);
+
+ expect(destroyIntegrationHandler).toHaveBeenCalled();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findIntegrations()).toHaveLength(3);
+ });
+
+ it('displays flash if mutation had a recoverable error', async () => {
+ createComponentWithApollo({
+ destroyHandler: jest.fn().mockResolvedValue(destroyIntegrationResponseWithErrors),
+ });
+
+ await destroyHttpIntegration(wrapper);
+ await awaitApolloDomMock();
+
+ expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' });
+ });
+
+ it('displays flash if mutation had a non-recoverable error', async () => {
+ createComponentWithApollo({
+ destroyHandler: jest.fn().mockRejectedValue('Error'),
+ });
+
+ await destroyHttpIntegration(wrapper);
+ await awaitApolloDomMock();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_INTEGRATION_ERROR,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/mocks/apollo_mock.js b/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
index e0eba1e8421..e0eba1e8421 100644
--- a/spec/frontend/alerts_settings/mocks/apollo_mock.js
+++ b/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
diff --git a/spec/frontend/alerts_settings/mocks/integrations.json b/spec/frontend/alerts_settings/components/mocks/integrations.json
index b1284fc55a2..b1284fc55a2 100644
--- a/spec/frontend/alerts_settings/mocks/integrations.json
+++ b/spec/frontend/alerts_settings/components/mocks/integrations.json
diff --git a/spec/frontend/alerts_settings/util.js b/spec/frontend/alerts_settings/components/util.js
index 5c07f22f1c9..5c07f22f1c9 100644
--- a/spec/frontend/alerts_settings/util.js
+++ b/spec/frontend/alerts_settings/components/util.js
diff --git a/spec/frontend/alerts_settings/mocks/alertFields.json b/spec/frontend/alerts_settings/mocks/alertFields.json
new file mode 100644
index 00000000000..ffe59dd0c05
--- /dev/null
+++ b/spec/frontend/alerts_settings/mocks/alertFields.json
@@ -0,0 +1,123 @@
+[
+ {
+ "name": "title",
+ "label": "Title",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ],
+ "numberOfFallbacks": 1
+ },
+ {
+ "name": "description",
+ "label": "Description",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "start_time",
+ "label": "Start time",
+ "type": [
+ "datetime"
+ ],
+ "types": [
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "end_time",
+ "label": "End time",
+ "type": [
+ "datetime"
+ ],
+ "types": [
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "service",
+ "label": "Service",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "monitoring_tool",
+ "label": "Monitoring tool",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "hosts",
+ "label": "Hosts",
+ "type": [
+ "string",
+ "ARRAY"
+ ],
+ "types": [
+ "string",
+ "ARRAY",
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "severity",
+ "label": "Severity",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "fingerprint",
+ "label": "Fingerprint",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ]
+ },
+ {
+ "name": "gitlab_environment_name",
+ "label": "Environment",
+ "type": [
+ "string"
+ ],
+ "types": [
+ "string",
+ "number",
+ "datetime"
+ ]
+ }
+]
diff --git a/spec/frontend/alerts_settings/utils/mapping_transformations_spec.js b/spec/frontend/alerts_settings/utils/mapping_transformations_spec.js
new file mode 100644
index 00000000000..8c1977ffebe
--- /dev/null
+++ b/spec/frontend/alerts_settings/utils/mapping_transformations_spec.js
@@ -0,0 +1,81 @@
+import parsedMapping from '~/alerts_settings/components/mocks/parsedMapping.json';
+import {
+ getMappingData,
+ getPayloadFields,
+ transformForSave,
+} from '~/alerts_settings/utils/mapping_transformations';
+import alertFields from '../mocks/alertFields.json';
+
+describe('Mapping Transformation Utilities', () => {
+ const nameField = {
+ label: 'Name',
+ path: ['alert', 'name'],
+ type: 'string',
+ };
+ const dashboardField = {
+ label: 'Dashboard Id',
+ path: ['alert', 'dashboardId'],
+ type: 'string',
+ };
+
+ describe('getMappingData', () => {
+ it('should return mapping data', () => {
+ const result = getMappingData(
+ alertFields,
+ getPayloadFields(parsedMapping.samplePayload.payloadAlerFields.nodes.slice(0, 3)),
+ parsedMapping.storedMapping.nodes.slice(0, 3),
+ );
+
+ result.forEach((data, index) => {
+ expect(data).toEqual(
+ expect.objectContaining({
+ ...alertFields[index],
+ searchTerm: '',
+ fallbackSearchTerm: '',
+ }),
+ );
+ });
+ });
+ });
+
+ describe('transformForSave', () => {
+ it('should transform mapped data for save', () => {
+ const fieldName = 'title';
+ const mockMappingData = [
+ {
+ name: fieldName,
+ mapping: 'alert_name',
+ mappingFields: getPayloadFields([dashboardField, nameField]),
+ },
+ ];
+ const result = transformForSave(mockMappingData);
+ const { path, type, label } = nameField;
+ expect(result).toEqual([
+ { fieldName: fieldName.toUpperCase(), path, type: type.toUpperCase(), label },
+ ]);
+ });
+
+ it('should return empty array if no mapping provided', () => {
+ const fieldName = 'title';
+ const mockMappingData = [
+ {
+ name: fieldName,
+ mapping: null,
+ mappingFields: getPayloadFields([nameField, dashboardField]),
+ },
+ ];
+ const result = transformForSave(mockMappingData);
+ expect(result).toEqual([]);
+ });
+ });
+
+ describe('getPayloadFields', () => {
+ it('should add name field to each payload field', () => {
+ const result = getPayloadFields([nameField, dashboardField]);
+ expect(result).toEqual([
+ { ...nameField, name: 'alert_name' },
+ { ...dashboardField, name: 'alert_dashboardId' },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/analytics/components/activity_chart_spec.js b/spec/frontend/analytics/components/activity_chart_spec.js
index 1f0f9a6c5d7..a6b45ffe20f 100644
--- a/spec/frontend/analytics/components/activity_chart_spec.js
+++ b/spec/frontend/analytics/components/activity_chart_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
import ActivityChart from '~/analytics/product_analytics/components/activity_chart.vue';
describe('Activity Chart Bundle', () => {
diff --git a/spec/frontend/analytics/instance_statistics/components/app_spec.js b/spec/frontend/analytics/instance_statistics/components/app_spec.js
index cc676e86e99..b945cc20bd6 100644
--- a/spec/frontend/analytics/instance_statistics/components/app_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/app_spec.js
@@ -1,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
-import InstanceStatisticsApp from '~/analytics/instance_statistics/components/app.vue';
import InstanceCounts from '~/analytics/instance_statistics/components//instance_counts.vue';
+import InstanceStatisticsApp from '~/analytics/instance_statistics/components/app.vue';
import InstanceStatisticsCountChart from '~/analytics/instance_statistics/components/instance_statistics_count_chart.vue';
-import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
import ProjectsAndGroupsChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
+import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
describe('InstanceStatisticsApp', () => {
let wrapper;
diff --git a/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
index a69f3388cbb..e80dcdff426 100644
--- a/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
@@ -1,13 +1,13 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLineChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import InstanceStatisticsCountChart from '~/analytics/instance_statistics/components/instance_statistics_count_chart.vue';
import statsQuery from '~/analytics/instance_statistics/graphql/queries/instance_count.query.graphql';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import { mockCountsData1 } from '../mock_data';
import { mockQueryResponse, mockApolloResponse } from '../apollo_mock_data';
+import { mockCountsData1 } from '../mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
diff --git a/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
index bf94e476ea3..bbfc65f19b1 100644
--- a/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
@@ -1,15 +1,14 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLineChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { useFakeDate } from 'helpers/fake_date';
import ProjectsAndGroupChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
-import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import projectsQuery from '~/analytics/instance_statistics/graphql/queries/projects.query.graphql';
import groupsQuery from '~/analytics/instance_statistics/graphql/queries/groups.query.graphql';
-import { mockCountsData2, roundedSortedCountsMonthlyChartData2 } from '../mock_data';
+import projectsQuery from '~/analytics/instance_statistics/graphql/queries/projects.query.graphql';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import { mockQueryResponse } from '../apollo_mock_data';
+import { mockCountsData2, roundedSortedCountsMonthlyChartData2 } from '../mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -45,8 +44,8 @@ describe('ProjectsAndGroupChart', () => {
return shallowMount(ProjectsAndGroupChart, {
props: {
- startDate: useFakeDate(2020, 9, 26),
- endDate: useFakeDate(2020, 10, 1),
+ startDate: new Date(2020, 9, 26),
+ endDate: new Date(2020, 10, 1),
totalDataPoints: mockCountsData2.length,
},
localVue,
diff --git a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
index b9fa30643df..d857b7fae61 100644
--- a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
@@ -1,18 +1,17 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
+import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { useFakeDate } from 'helpers/fake_date';
import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
-import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import usersQuery from '~/analytics/instance_statistics/graphql/queries/users.query.graphql';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import { mockQueryResponse } from '../apollo_mock_data';
import {
mockCountsData1,
mockCountsData2,
roundedSortedCountsMonthlyChartData2,
} from '../mock_data';
-import { mockQueryResponse } from '../apollo_mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -31,8 +30,8 @@ describe('UsersChart', () => {
return shallowMount(UsersChart, {
props: {
- startDate: useFakeDate(2020, 9, 26),
- endDate: useFakeDate(2020, 10, 1),
+ startDate: new Date(2020, 9, 26),
+ endDate: new Date(2020, 10, 1),
totalDataPoints: mockCountsData2.length,
},
localVue,
diff --git a/spec/frontend/analytics/shared/components/metric_card_spec.js b/spec/frontend/analytics/shared/components/metric_card_spec.js
index e89d499ed9b..7f587d227ab 100644
--- a/spec/frontend/analytics/shared/components/metric_card_spec.js
+++ b/spec/frontend/analytics/shared/components/metric_card_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import MetricCard from '~/analytics/shared/components/metric_card.vue';
diff --git a/spec/frontend/api/api_utils_spec.js b/spec/frontend/api/api_utils_spec.js
index 3fec26f0149..04be442ef71 100644
--- a/spec/frontend/api/api_utils_spec.js
+++ b/spec/frontend/api/api_utils_spec.js
@@ -20,6 +20,10 @@ describe('~/api/api_utils.js', () => {
);
});
+ it('ensures the URL is prefixed with a /', () => {
+ expect(apiUtils.buildApiUrl('api/:version/projects/:id')).toEqual('/api/v7/projects/:id');
+ });
+
describe('when gon includes a relative_url_root property', () => {
beforeEach(() => {
window.gon.relative_url_root = '/relative/root';
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index 76d67195499..d2522a0124a 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import Api from '~/api';
+import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
describe('Api', () => {
@@ -260,6 +260,28 @@ describe('Api', () => {
});
});
+ describe('groupLabels', () => {
+ it('fetches group labels', (done) => {
+ const options = { params: { search: 'foo' } };
+ const expectedGroup = 'gitlab-org';
+ const expectedUrl = `${dummyUrlRoot}/groups/${expectedGroup}/-/labels`;
+ mock.onGet(expectedUrl).reply(httpStatus.OK, [
+ {
+ id: 1,
+ title: 'Foo Label',
+ },
+ ]);
+
+ Api.groupLabels(expectedGroup, options)
+ .then((res) => {
+ expect(res.length).toBe(1);
+ expect(res[0].title).toBe('Foo Label');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
describe('namespaces', () => {
it('fetches namespaces', (done) => {
const query = 'dummy query';
diff --git a/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap b/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
index 9d05e6d99f6..bfe7e40fb32 100644
--- a/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
+++ b/spec/frontend/artifacts_settings/components/__snapshots__/keep_latest_artifact_checkbox_spec.js.snap
@@ -1,29 +1,64 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Keep latest artifact checkbox sets correct setting value in checkbox with query result 1`] = `
+exports[`Keep latest artifact checkbox when application keep latest artifact setting is disabled checkbox is disabled when application setting is disabled 1`] = `
<div>
<!---->
- <gl-form-checkbox-stub
+ <b-form-checkbox-stub
checked="true"
+ class="gl-form-checkbox"
+ disabled="true"
+ plain="true"
+ value="true"
>
- <b
+ <strong
class="gl-mr-3"
>
Keep artifacts from most recent successful jobs
- </b>
+ </strong>
<gl-link-stub
href="/help/ci/pipelines/job_artifacts"
>
More information
</gl-link-stub>
- </gl-form-checkbox-stub>
+
+ <p
+ class="help-text"
+ >
+ This feature is disabled at the instance level.
+ </p>
+ </b-form-checkbox-stub>
+</div>
+`;
+
+exports[`Keep latest artifact checkbox when application keep latest artifact setting is enabled sets correct setting value in checkbox with query result 1`] = `
+<div>
+ <!---->
- <p>
-
- The latest artifacts created by jobs in the most recent successful pipeline will be stored.
-
- </p>
+ <b-form-checkbox-stub
+ checked="true"
+ class="gl-form-checkbox"
+ plain="true"
+ value="true"
+ >
+ <strong
+ class="gl-mr-3"
+ >
+ Keep artifacts from most recent successful jobs
+ </strong>
+
+ <gl-link-stub
+ href="/help/ci/pipelines/job_artifacts"
+ >
+ More information
+ </gl-link-stub>
+
+ <p
+ class="help-text"
+ >
+ The latest artifacts created by jobs in the most recent successful pipeline will be stored.
+ </p>
+ </b-form-checkbox-stub>
</div>
`;
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 d7f07526b58..fe2886d6c95 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
@@ -2,14 +2,15 @@ import { GlFormCheckbox, GlLink } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-import KeepLatestArtifactCheckbox from '~/artifacts_settings/keep_latest_artifact_checkbox.vue';
-import GetKeepLatestArtifactProjectSetting from '~/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql';
import UpdateKeepLatestArtifactProjectSetting from '~/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql';
+import GetKeepLatestArtifactApplicationSetting from '~/artifacts_settings/graphql/queries/get_keep_latest_artifact_application_setting.query.graphql';
+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);
-const keepLatestArtifactMock = {
+const keepLatestArtifactProjectMock = {
data: {
project: {
ciCdSettings: { keepLatestArtifact: true },
@@ -17,6 +18,14 @@ const keepLatestArtifactMock = {
},
};
+const keepLatestArtifactApplicationMock = {
+ data: {
+ ciApplicationSettings: {
+ keepLatestArtifact: true,
+ },
+ },
+};
+
const keepLatestArtifactMockResponse = {
data: { ciCdSettingsUpdate: { errors: [], __typename: 'CiCdSettingsUpdatePayload' } },
};
@@ -34,7 +43,12 @@ describe('Keep latest artifact checkbox', () => {
const createComponent = (handlers) => {
requestHandlers = {
- keepLatestArtifactQueryHandler: jest.fn().mockResolvedValue(keepLatestArtifactMock),
+ keepLatestArtifactProjectQueryHandler: jest
+ .fn()
+ .mockResolvedValue(keepLatestArtifactProjectMock),
+ keepLatestArtifactApplicationQueryHandler: jest
+ .fn()
+ .mockResolvedValue(keepLatestArtifactApplicationMock),
keepLatestArtifactMutationHandler: jest
.fn()
.mockResolvedValue(keepLatestArtifactMockResponse),
@@ -42,7 +56,11 @@ describe('Keep latest artifact checkbox', () => {
};
apolloProvider = createMockApollo([
- [GetKeepLatestArtifactProjectSetting, requestHandlers.keepLatestArtifactQueryHandler],
+ [GetKeepLatestArtifactProjectSetting, requestHandlers.keepLatestArtifactProjectQueryHandler],
+ [
+ GetKeepLatestArtifactApplicationSetting,
+ requestHandlers.keepLatestArtifactApplicationQueryHandler,
+ ],
[UpdateKeepLatestArtifactProjectSetting, requestHandlers.keepLatestArtifactMutationHandler],
]);
@@ -51,38 +69,74 @@ describe('Keep latest artifact checkbox', () => {
fullPath,
helpPagePath,
},
+ stubs: {
+ GlFormCheckbox,
+ },
localVue,
apolloProvider,
});
};
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
apolloProvider = null;
});
- it('displays the checkbox and the help link', () => {
- expect(findCheckbox().exists()).toBe(true);
- expect(findHelpLink().exists()).toBe(true);
- });
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('displays the checkbox and the help link', () => {
+ expect(findCheckbox().exists()).toBe(true);
+ expect(findHelpLink().exists()).toBe(true);
+ });
- it('sets correct setting value in checkbox with query result', async () => {
- await wrapper.vm.$nextTick();
+ it('calls mutation on artifact setting change with correct payload', () => {
+ findCheckbox().vm.$emit('change', false);
- expect(wrapper.element).toMatchSnapshot();
+ expect(requestHandlers.keepLatestArtifactMutationHandler).toHaveBeenCalledWith({
+ fullPath,
+ keepLatestArtifact: false,
+ });
+ });
});
- it('calls mutation on artifact setting change with correct payload', () => {
- findCheckbox().vm.$emit('change', false);
+ describe('when application keep latest artifact setting is enabled', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('sets correct setting value in checkbox with query result', async () => {
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('checkbox is enabled when application setting is enabled', async () => {
+ await wrapper.vm.$nextTick();
+
+ expect(findCheckbox().attributes('disabled')).toBeUndefined();
+ });
+ });
- expect(requestHandlers.keepLatestArtifactMutationHandler).toHaveBeenCalledWith({
- fullPath,
- keepLatestArtifact: false,
+ describe('when application keep latest artifact setting is disabled', () => {
+ it('checkbox is disabled when application setting is disabled', async () => {
+ createComponent({
+ keepLatestArtifactApplicationQueryHandler: jest.fn().mockResolvedValue({
+ data: {
+ ciApplicationSettings: {
+ keepLatestArtifact: false,
+ },
+ },
+ }),
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.element).toMatchSnapshot();
+ expect(findCheckbox().attributes('disabled')).toBe('true');
});
});
});
diff --git a/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js b/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js
index 98c8ed4b95d..b77def195b6 100644
--- a/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js
+++ b/spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js
@@ -1,17 +1,17 @@
-import { mount } from '@vue/test-utils';
import { GlAlert, GlButton } from '@gitlab/ui';
-import { nextTick } from 'vue';
import { within } from '@testing-library/dom';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import Tracking from '~/tracking';
import RecoveryCodes, {
i18n,
} from '~/authentication/two_factor_auth/components/recovery_codes.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import {
RECOVERY_CODE_DOWNLOAD_FILENAME,
COPY_KEYBOARD_SHORTCUT,
} from '~/authentication/two_factor_auth/constants';
+import Tracking from '~/tracking';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { codes, codesFormattedString, codesDownloadHref, profileAccountPath } from '../mock_data';
describe('RecoveryCodes', () => {
diff --git a/spec/frontend/authentication/two_factor_auth/index_spec.js b/spec/frontend/authentication/two_factor_auth/index_spec.js
index b181170b0a1..f5345139021 100644
--- a/spec/frontend/authentication/two_factor_auth/index_spec.js
+++ b/spec/frontend/authentication/two_factor_auth/index_spec.js
@@ -1,8 +1,8 @@
-import { createWrapper } from '@vue/test-utils';
import { getByTestId, fireEvent } from '@testing-library/dom';
-import * as urlUtils from '~/lib/utils/url_utility';
+import { createWrapper } from '@vue/test-utils';
import { initRecoveryCodes, initClose2faSuccessMessage } from '~/authentication/two_factor_auth';
import RecoveryCodes from '~/authentication/two_factor_auth/components/recovery_codes.vue';
+import * as urlUtils from '~/lib/utils/url_utility';
import { codesJsonString, codes, profileAccountPath } from './mock_data';
describe('initRecoveryCodes', () => {
diff --git a/spec/frontend/avatar_helper_spec.js b/spec/frontend/avatar_helper_spec.js
index c4da7189751..91bf8e28774 100644
--- a/spec/frontend/avatar_helper_spec.js
+++ b/spec/frontend/avatar_helper_spec.js
@@ -1,5 +1,4 @@
import { TEST_HOST } from 'spec/test_constants';
-import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
import {
DEFAULT_SIZE_CLASS,
IDENTICON_BG_COUNT,
@@ -8,6 +7,7 @@ import {
getIdenticonBackgroundClass,
getIdenticonTitle,
} from '~/helpers/avatar_helper';
+import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
function matchAll(str) {
return new RegExp(`^${str}$`);
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index e9482ffbd3d..edd17cfd810 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -1,10 +1,10 @@
+import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import Cookies from 'js-cookie';
-import MockAdapter from 'axios-mock-adapter';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
-import axios from '~/lib/utils/axios_utils';
import loadAwardsHandler from '~/awards_handler';
import { EMOJI_VERSION } from '~/emoji';
+import axios from '~/lib/utils/axios_utils';
window.gl = window.gl || {};
window.gon = window.gon || {};
@@ -53,6 +53,12 @@ describe('AwardsHandler', () => {
d: 'smiling face with sunglasses',
u: '6.0',
},
+ grey_question: {
+ c: 'symbols',
+ e: 'â”',
+ d: 'white question mark ornament',
+ u: '6.0',
+ },
};
preloadFixtures('snippets/show.html');
@@ -285,16 +291,6 @@ describe('AwardsHandler', () => {
expect($('.js-emoji-menu-search').val()).toBe('');
});
- it('should fuzzy filter the emoji', async () => {
- await openAndWaitForEmojiMenu();
-
- awardsHandler.searchEmojis('sgls');
-
- expect($('[data-name=angel]').is(':visible')).toBe(false);
- expect($('[data-name=anger]').is(':visible')).toBe(false);
- expect($('[data-name=sunglasses]').is(':visible')).toBe(true);
- });
-
it('should filter by emoji description', async () => {
await openAndWaitForEmojiMenu();
diff --git a/spec/frontend/badges/components/badge_form_spec.js b/spec/frontend/badges/components/badge_form_spec.js
index 34c65d51115..e375fcb4705 100644
--- a/spec/frontend/badges/components/badge_form_spec.js
+++ b/spec/frontend/badges/components/badge_form_spec.js
@@ -1,11 +1,11 @@
-import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vue from 'vue';
import { DUMMY_IMAGE_URL, TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import store from '~/badges/store';
-import createEmptyBadge from '~/badges/empty_badge';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import BadgeForm from '~/badges/components/badge_form.vue';
+import createEmptyBadge from '~/badges/empty_badge';
+import store from '~/badges/store';
+import axios from '~/lib/utils/axios_utils';
// avoid preview background process
BadgeForm.methods.debouncedPreview = () => {};
diff --git a/spec/frontend/badges/components/badge_list_row_spec.js b/spec/frontend/badges/components/badge_list_row_spec.js
index c559c979cb3..372663017e2 100644
--- a/spec/frontend/badges/components/badge_list_row_spec.js
+++ b/spec/frontend/badges/components/badge_list_row_spec.js
@@ -1,8 +1,8 @@
import Vue 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';
import store from '~/badges/store';
-import BadgeListRow from '~/badges/components/badge_list_row.vue';
import { createDummyBadge } from '../dummy_badge';
describe('BadgeListRow component', () => {
diff --git a/spec/frontend/badges/components/badge_list_spec.js b/spec/frontend/badges/components/badge_list_spec.js
index da59e13e1e9..6cc90c6de46 100644
--- a/spec/frontend/badges/components/badge_list_spec.js
+++ b/spec/frontend/badges/components/badge_list_spec.js
@@ -1,8 +1,8 @@
import Vue 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';
import store from '~/badges/store';
-import BadgeList from '~/badges/components/badge_list.vue';
import { createDummyBadge } from '../dummy_badge';
describe('BadgeList component', () => {
diff --git a/spec/frontend/badges/components/badge_settings_spec.js b/spec/frontend/badges/components/badge_settings_spec.js
index 769be7cb1bd..0c29379763e 100644
--- a/spec/frontend/badges/components/badge_settings_spec.js
+++ b/spec/frontend/badges/components/badge_settings_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
-import store from '~/badges/store';
-import BadgeSettings from '~/badges/components/badge_settings.vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import BadgeList from '~/badges/components/badge_list.vue';
import BadgeListRow from '~/badges/components/badge_list_row.vue';
+import BadgeSettings from '~/badges/components/badge_settings.vue';
+import store from '~/badges/store';
import { createDummyBadge } from '../dummy_badge';
const localVue = createLocalVue();
diff --git a/spec/frontend/badges/store/actions_spec.js b/spec/frontend/badges/store/actions_spec.js
index 52ae29affac..75699f24463 100644
--- a/spec/frontend/badges/store/actions_spec.js
+++ b/spec/frontend/badges/store/actions_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
+import { TEST_HOST } from 'spec/test_constants';
import actions, { transformBackendBadge } from '~/badges/store/actions';
import mutationTypes from '~/badges/store/mutation_types';
import createState from '~/badges/store/state';
+import axios from '~/lib/utils/axios_utils';
import { createDummyBadge, createDummyBadgeResponse } from '../dummy_badge';
describe('Badges store actions', () => {
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
index ae7134b63c8..c2d488a465e 100644
--- a/spec/frontend/batch_comments/components/draft_note_spec.js
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { getByRole } from '@testing-library/dom';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import DraftNote from '~/batch_comments/components/draft_note.vue';
import { createStore } from '~/batch_comments/stores';
import NoteableNote from '~/notes/components/noteable_note.vue';
@@ -21,14 +21,11 @@ describe('Batch comments draft note component', () => {
const getList = () => getByRole(wrapper.element, 'list');
- const createComponent = (propsData = { draft }, features = {}) => {
+ const createComponent = (propsData = { draft }) => {
wrapper = shallowMount(localVue.extend(DraftNote), {
store,
propsData,
localVue,
- provide: {
- glFeatures: { multilineComments: true, ...features },
- },
});
jest.spyOn(wrapper.vm.$store, 'dispatch').mockImplementation();
@@ -145,16 +142,14 @@ describe('Batch comments draft note component', () => {
describe('multiline comments', () => {
describe.each`
- desc | props | features | event | expectedCalls
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]}
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]}
- ${'without `draft.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]}
- ${'without `draft.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]}
- `('$desc and features $features', ({ props, event, features, expectedCalls }) => {
+ desc | props | event | expectedCalls
+ ${'with `draft.position`'} | ${draftWithLineRange} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
+ ${'with `draft.position`'} | ${draftWithLineRange} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
+ ${'without `draft.position`'} | ${{}} | ${'mouseenter'} | ${[]}
+ ${'without `draft.position`'} | ${{}} | ${'mouseleave'} | ${[]}
+ `('$desc', ({ props, event, expectedCalls }) => {
beforeEach(() => {
- createComponent({ draft: { ...draft, ...props } }, features);
+ createComponent({ draft: { ...draft, ...props } });
jest.spyOn(store, 'dispatch');
});
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 173b2710a30..08167a94068 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -56,17 +56,30 @@ describe('Batch comments draft preview item component', () => {
createComponent(false, {
file_path: 'index.js',
file_hash: 'abc',
- position: { new_line: 1 },
+ position: {
+ line_range: {
+ start: {
+ new_line: 1,
+ type: 'new',
+ },
+ },
+ },
});
- expect(vm.$el.querySelector('.bold').textContent).toContain(':1');
+ expect(vm.$el.querySelector('.bold').textContent).toContain(':+1');
});
it('renders old line position', () => {
createComponent(false, {
file_path: 'index.js',
file_hash: 'abc',
- position: { old_line: 2 },
+ position: {
+ line_range: {
+ start: {
+ old_line: 2,
+ },
+ },
+ },
});
expect(vm.$el.querySelector('.bold').textContent).toContain(':2');
diff --git a/spec/frontend/batch_comments/components/publish_dropdown_spec.js b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
index f235867f002..bd8091c20e0 100644
--- a/spec/frontend/batch_comments/components/publish_dropdown_spec.js
+++ b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
import { createStore } from '~/mr_notes/stores';
import '~/behaviors/markdown/render_gfm';
diff --git a/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js b/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
index 3ad131de24e..885e02ef60f 100644
--- a/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
+++ b/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/batch_comments/stores/modules/batch_comments/actions';
import axios from '~/lib/utils/axios_utils';
diff --git a/spec/frontend/batch_comments/stores/modules/batch_comments/mutations_spec.js b/spec/frontend/batch_comments/stores/modules/batch_comments/mutations_spec.js
index 1406f66fd10..fe01de638c2 100644
--- a/spec/frontend/batch_comments/stores/modules/batch_comments/mutations_spec.js
+++ b/spec/frontend/batch_comments/stores/modules/batch_comments/mutations_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/batch_comments/stores/modules/batch_comments/state';
-import mutations from '~/batch_comments/stores/modules/batch_comments/mutations';
import * as types from '~/batch_comments/stores/modules/batch_comments/mutation_types';
+import mutations from '~/batch_comments/stores/modules/batch_comments/mutations';
+import createState from '~/batch_comments/stores/modules/batch_comments/state';
describe('Batch comments mutations', () => {
let state;
diff --git a/spec/frontend/behaviors/autosize_spec.js b/spec/frontend/behaviors/autosize_spec.js
index 352bd8a0ed0..a9dbee7fd08 100644
--- a/spec/frontend/behaviors/autosize_spec.js
+++ b/spec/frontend/behaviors/autosize_spec.js
@@ -1,12 +1,20 @@
import '~/behaviors/autosize';
-function load() {
- document.dispatchEvent(new Event('DOMContentLoaded'));
-}
-
jest.mock('~/helpers/startup_css_helper', () => {
return {
- waitForCSSLoaded: jest.fn().mockImplementation((cb) => cb.apply()),
+ waitForCSSLoaded: jest.fn().mockImplementation((cb) => {
+ // This is a hack:
+ // autosize.js will execute and modify the DOM
+ // whenever waitForCSSLoaded calls its callback function.
+ // This setTimeout is here because everything within setTimeout will be queued
+ // as async code until the current call stack is executed.
+ // If we would not do this, the mock for waitForCSSLoaded would call its callback
+ // before the fixture in the beforeEach is set and the Test would fail.
+ // more on this here: https://johnresig.com/blog/how-javascript-timers-work/
+ setTimeout(() => {
+ cb.apply();
+ }, 0);
+ }),
};
});
@@ -16,9 +24,15 @@ describe('Autosize behavior', () => {
});
it('is applied to the textarea', () => {
- load();
-
- const textarea = document.querySelector('textarea');
- expect(textarea.classList).toContain('js-autosize-initialized');
+ // This is the second part of the Hack:
+ // Because we are forcing the mock for WaitForCSSLoaded and the very end of our callstack
+ // to call its callback. This querySelector needs to go to the very end of our callstack
+ // as well, if we would not have this setTimeout Function here, the querySelector
+ // would run before the mockImplementation called its callBack Function
+ // the DOM Manipulation didn't happen yet and the test would fail.
+ setTimeout(() => {
+ const textarea = document.querySelector('textarea');
+ expect(textarea.classList).toContain('js-autosize-initialized');
+ }, 0);
});
});
diff --git a/spec/frontend/behaviors/copy_as_gfm_spec.js b/spec/frontend/behaviors/copy_as_gfm_spec.js
index 16ea4ba8624..acff990e84a 100644
--- a/spec/frontend/behaviors/copy_as_gfm_spec.js
+++ b/spec/frontend/behaviors/copy_as_gfm_spec.js
@@ -1,5 +1,5 @@
-import * as commonUtils from '~/lib/utils/common_utils';
import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
+import * as commonUtils from '~/lib/utils/common_utils';
describe('CopyAsGFM', () => {
describe('CopyAsGFM.pasteGFM', () => {
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index 6e476d84501..286ed269421 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
import installGlEmojiElement from '~/behaviors/gl_emoji';
+import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
import * as EmojiUnicodeSupport from '~/emoji/support';
+import axios from '~/lib/utils/axios_utils';
jest.mock('~/emoji/support');
diff --git a/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js b/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js
index 09c49617bc5..d7531d15b9a 100644
--- a/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js
+++ b/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js
@@ -1,7 +1,7 @@
import sqljs from 'sql.js';
import ClassSpecHelper from 'helpers/class_spec_helper';
-import axios from '~/lib/utils/axios_utils';
import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer';
+import axios from '~/lib/utils/axios_utils';
jest.mock('sql.js');
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 b54efb93bc9..31fb6addcac 100644
--- a/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
+++ b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
@@ -9,7 +9,7 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
/>
<div
- class="gl-display-none gl-display-sm-flex"
+ class="gl-display-none gl-sm-display-flex"
>
<viewer-switcher-stub
value="simple"
diff --git a/spec/frontend/blob/components/blob_content_error_spec.js b/spec/frontend/blob/components/blob_content_error_spec.js
index 95686be8294..0f5885c2acf 100644
--- a/spec/frontend/blob/components/blob_content_error_spec.js
+++ b/spec/frontend/blob/components/blob_content_error_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import BlobContentError from '~/blob/components/blob_content_error.vue';
import { BLOB_RENDER_ERRORS } from '~/blob/components/constants';
diff --git a/spec/frontend/blob/components/blob_content_spec.js b/spec/frontend/blob/components/blob_content_spec.js
index 3db95e5ad3f..8450c6b9332 100644
--- a/spec/frontend/blob/components/blob_content_spec.js
+++ b/spec/frontend/blob/components/blob_content_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import BlobContent from '~/blob/components/blob_content.vue';
import BlobContentError from '~/blob/components/blob_content_error.vue';
import {
@@ -7,6 +7,7 @@ import {
BLOB_RENDER_EVENT_SHOW_SOURCE,
BLOB_RENDER_ERRORS,
} from '~/blob/components/constants';
+import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
import {
Blob,
RichViewerMock,
@@ -14,7 +15,6 @@ import {
RichBlobContentMock,
SimpleBlobContentMock,
} from './mock_data';
-import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
describe('Blob Content component', () => {
let wrapper;
diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js
index 22e8e6d986c..ac3080c65a5 100644
--- a/spec/frontend/blob/components/blob_edit_header_spec.js
+++ b/spec/frontend/blob/components/blob_edit_header_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormInput, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import BlobEditHeader from '~/blob/components/blob_edit_header.vue';
describe('Blob Header Editing', () => {
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 e2c73a5d5d9..bce65899c43 100644
--- a/spec/frontend/blob/components/blob_header_default_actions_spec.js
+++ b/spec/frontend/blob/components/blob_header_default_actions_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlButtonGroup, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import BlobHeaderActions from '~/blob/components/blob_header_default_actions.vue';
import {
BTN_COPY_CONTENTS_TITLE,
diff --git a/spec/frontend/blob/components/blob_header_filepath_spec.js b/spec/frontend/blob/components/blob_header_filepath_spec.js
index 7b8b5050486..d935f73c0d1 100644
--- a/spec/frontend/blob/components/blob_header_filepath_spec.js
+++ b/spec/frontend/blob/components/blob_header_filepath_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import BlobHeaderFilepath from '~/blob/components/blob_header_filepath.vue';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { Blob as MockBlob } from './mock_data';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
jest.mock('~/lib/utils/number_utils', () => ({
numberToHumanSize: jest.fn(() => 'a lot'),
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
index b3f80183f6b..865e8ab1124 100644
--- a/spec/frontend/blob/components/blob_header_spec.js
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -1,8 +1,8 @@
import { shallowMount, mount } from '@vue/test-utils';
import BlobHeader from '~/blob/components/blob_header.vue';
-import ViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
import DefaultActions from '~/blob/components/blob_header_default_actions.vue';
import BlobFilepath from '~/blob/components/blob_header_filepath.vue';
+import ViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
import { Blob } from './mock_data';
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 cf1101bc22c..9a560ec11f7 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,5 @@
-import { mount } from '@vue/test-utils';
import { GlButtonGroup, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import BlobHeaderViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
import {
RICH_BLOB_VIEWER,
diff --git a/spec/frontend/blob/notebook/notebook_viever_spec.js b/spec/frontend/blob/notebook/notebook_viever_spec.js
index f6a926a5ecb..604104bb31f 100644
--- a/spec/frontend/blob/notebook/notebook_viever_spec.js
+++ b/spec/frontend/blob/notebook/notebook_viever_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import component from '~/blob/notebook/notebook_viewer.vue';
+import axios from '~/lib/utils/axios_utils';
import NotebookLab from '~/notebook/index.vue';
describe('iPython notebook renderer', () => {
diff --git a/spec/frontend/blob/pdf/pdf_viewer_spec.js b/spec/frontend/blob/pdf/pdf_viewer_spec.js
index 0eea3aea639..e332ea49fa6 100644
--- a/spec/frontend/blob/pdf/pdf_viewer_spec.js
+++ b/spec/frontend/blob/pdf/pdf_viewer_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { FIXTURES_PATH } from 'spec/test_constants';
import component from '~/blob/pdf/pdf_viewer.vue';
diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
index d4562019302..f4af57de41f 100644
--- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js
+++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
@@ -1,8 +1,8 @@
+import { GlSprintf, GlModal, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
-import { GlSprintf, GlModal, GlLink } from '@gitlab/ui';
-import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
import { stubComponent } from 'helpers/stub_component';
+import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue';
import modalProps from './pipeline_tour_success_mock_data';
diff --git a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
index e55b8e4af24..7e13994f2b7 100644
--- a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
+++ b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
@@ -1,6 +1,6 @@
+import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
-import { GlButton } from '@gitlab/ui';
import Popover from '~/blob/suggest_gitlab_ci_yml/components/popover.vue';
import * as utils from '~/lib/utils/common_utils';
diff --git a/spec/frontend/blob/utils_spec.js b/spec/frontend/blob/utils_spec.js
index fa83690c104..3ff2e47e0b6 100644
--- a/spec/frontend/blob/utils_spec.js
+++ b/spec/frontend/blob/utils_spec.js
@@ -1,5 +1,5 @@
-import Editor from '~/editor/editor_lite';
import * as utils from '~/blob/utils';
+import Editor from '~/editor/editor_lite';
jest.mock('~/editor/editor_lite');
diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js
index 4a5eb31602d..7449de48ec0 100644
--- a/spec/frontend/blob/viewer/index_spec.js
+++ b/spec/frontend/blob/viewer/index_spec.js
@@ -1,7 +1,7 @@
/* eslint-disable no-new */
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import { setTestTimeout } from 'helpers/timeout';
import BlobViewer from '~/blob/viewer/index';
import axios from '~/lib/utils/axios_utils';
diff --git a/spec/frontend/blob_edit/edit_blob_spec.js b/spec/frontend/blob_edit/edit_blob_spec.js
index 7927c14d2ac..3134feedcf3 100644
--- a/spec/frontend/blob_edit/edit_blob_spec.js
+++ b/spec/frontend/blob_edit/edit_blob_spec.js
@@ -1,8 +1,8 @@
import waitForPromises from 'helpers/wait_for_promises';
import EditBlob from '~/blob_edit/edit_blob';
import EditorLite from '~/editor/editor_lite';
-import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext';
import { FileTemplateExtension } from '~/editor/extensions/editor_file_template_ext';
+import { EditorMarkdownExtension } from '~/editor/extensions/editor_markdown_ext';
jest.mock('~/editor/editor_lite');
jest.mock('~/editor/extensions/editor_markdown_ext');
diff --git a/spec/frontend/boards/board_list_deprecated_spec.js b/spec/frontend/boards/board_list_deprecated_spec.js
index 393d7f954b1..b71564f7858 100644
--- a/spec/frontend/boards/board_list_deprecated_spec.js
+++ b/spec/frontend/boards/board_list_deprecated_spec.js
@@ -1,17 +1,16 @@
/* global List */
/* global ListIssue */
-
-import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-import eventHub from '~/boards/eventhub';
import BoardList from '~/boards/components/board_list_deprecated.vue';
+import eventHub from '~/boards/eventhub';
+import store from '~/boards/stores';
+import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
import '~/boards/models/issue';
import '~/boards/models/list';
import { listObj, boardsMockInterceptor } from './mock_data';
-import store from '~/boards/stores';
-import boardsStore from '~/boards/stores/boards_store';
const createComponent = ({ done, listIssueProps = {}, componentProps = {}, listProps = {} }) => {
const el = document.createElement('div');
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js
index f82b1f7ed5c..915b470df8d 100644
--- a/spec/frontend/boards/board_list_helper.js
+++ b/spec/frontend/boards/board_list_helper.js
@@ -1,17 +1,15 @@
/* global List */
/* global ListIssue */
-
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
import Sortable from 'sortablejs';
-import axios from '~/lib/utils/axios_utils';
+import Vue from 'vue';
import BoardList from '~/boards/components/board_list_deprecated.vue';
-
import '~/boards/models/issue';
import '~/boards/models/list';
-import { listObj, boardsMockInterceptor } from './mock_data';
import store from '~/boards/stores';
import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
+import { listObj, boardsMockInterceptor } from './mock_data';
window.Sortable = Sortable;
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 1b62f25044e..7ed20f20882 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -1,11 +1,11 @@
+import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
-import { createLocalVue, mount } from '@vue/test-utils';
-import eventHub from '~/boards/eventhub';
-import BoardList from '~/boards/components/board_list.vue';
import BoardCard from '~/boards/components/board_card.vue';
-import { mockList, mockIssuesByListId, issues, mockIssues } from './mock_data';
+import BoardList from '~/boards/components/board_list.vue';
+import eventHub from '~/boards/eventhub';
import defaultState from '~/boards/stores/state';
+import { mockList, mockIssuesByListId, issues, mockIssues } from './mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/boards/board_new_issue_deprecated_spec.js b/spec/frontend/boards/board_new_issue_deprecated_spec.js
index 8236b468189..1a29f680166 100644
--- a/spec/frontend/boards/board_new_issue_deprecated_spec.js
+++ b/spec/frontend/boards/board_new_issue_deprecated_spec.js
@@ -1,11 +1,11 @@
/* global List */
-import Vue from 'vue';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
+import Vue from 'vue';
import boardNewIssue from '~/boards/components/board_new_issue_deprecated.vue';
import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
import '~/boards/models/list';
import { listObj, boardsMockInterceptor } from './mock_data';
diff --git a/spec/frontend/boards/boards_store_spec.js b/spec/frontend/boards/boards_store_spec.js
index f1d249ff069..02881333273 100644
--- a/spec/frontend/boards/boards_store_spec.js
+++ b/spec/frontend/boards/boards_store_spec.js
@@ -1,12 +1,12 @@
import AxiosMockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import boardsStore from '~/boards/stores/boards_store';
import eventHub from '~/boards/eventhub';
-import { listObj, listObjDuplicate } from './mock_data';
import ListIssue from '~/boards/models/issue';
import List from '~/boards/models/list';
+import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
+import { listObj, listObjDuplicate } from './mock_data';
jest.mock('js-cookie');
diff --git a/spec/frontend/boards/boards_util_spec.js b/spec/frontend/boards/boards_util_spec.js
new file mode 100644
index 00000000000..0feb1411003
--- /dev/null
+++ b/spec/frontend/boards/boards_util_spec.js
@@ -0,0 +1,17 @@
+import { transformNotFilters } from '~/boards/boards_util';
+
+describe('transformNotFilters', () => {
+ const filters = {
+ 'not[labelName]': ['label'],
+ 'not[assigneeUsername]': 'assignee',
+ };
+
+ it('formats not filters, transforms epicId to fullEpicId', () => {
+ const result = transformNotFilters(filters);
+
+ expect(result).toEqual({
+ labelName: ['label'],
+ assigneeUsername: 'assignee',
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_assignee_dropdown_spec.js b/spec/frontend/boards/components/board_assignee_dropdown_spec.js
deleted file mode 100644
index e52c14f9783..00000000000
--- a/spec/frontend/boards/components/board_assignee_dropdown_spec.js
+++ /dev/null
@@ -1,380 +0,0 @@
-import { mount, createLocalVue } from '@vue/test-utils';
-import {
- GlDropdownItem,
- GlAvatarLink,
- GlAvatarLabeled,
- GlSearchBoxByType,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import VueApollo from 'vue-apollo';
-import BoardAssigneeDropdown from '~/boards/components/board_assignee_dropdown.vue';
-import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
-import MultiSelectDropdown from '~/vue_shared/components/sidebar/multiselect_dropdown.vue';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import store from '~/boards/stores';
-import getIssueParticipants from '~/vue_shared/components/sidebar/queries/getIssueParticipants.query.graphql';
-import searchUsers from '~/boards/graphql/users_search.query.graphql';
-import { participants } from '../mock_data';
-
-const localVue = createLocalVue();
-
-localVue.use(VueApollo);
-
-describe('BoardCardAssigneeDropdown', () => {
- let wrapper;
- let fakeApollo;
- let getIssueParticipantsSpy;
- let getSearchUsersSpy;
- let dispatchSpy;
-
- const iid = '111';
- const activeIssueName = 'test';
- const anotherIssueName = 'hello';
-
- const createComponent = (search = '', loading = false) => {
- wrapper = mount(BoardAssigneeDropdown, {
- data() {
- return {
- search,
- selected: [],
- participants,
- };
- },
- store,
- provide: {
- canUpdate: true,
- rootPath: '',
- },
- mocks: {
- $apollo: {
- queries: {
- participants: {
- loading,
- },
- },
- },
- },
- });
- };
-
- const createComponentWithApollo = (search = '') => {
- fakeApollo = createMockApollo([
- [getIssueParticipants, getIssueParticipantsSpy],
- [searchUsers, getSearchUsersSpy],
- ]);
- wrapper = mount(BoardAssigneeDropdown, {
- localVue,
- apolloProvider: fakeApollo,
- data() {
- return {
- search,
- selected: [],
- participants,
- };
- },
- store,
- provide: {
- canUpdate: true,
- rootPath: '',
- },
- });
- };
-
- const unassign = async () => {
- wrapper.find('[data-testid="unassign"]').trigger('click');
-
- await wrapper.vm.$nextTick();
- };
-
- const openDropdown = async () => {
- wrapper.find('[data-testid="edit-button"]').trigger('click');
-
- await wrapper.vm.$nextTick();
- };
-
- const findByText = (text) => {
- return wrapper.findAll(GlDropdownItem).wrappers.find((node) => node.text().indexOf(text) === 0);
- };
-
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
-
- beforeEach(() => {
- store.state.activeId = '1';
- store.state.issues = {
- 1: {
- iid,
- assignees: [{ username: activeIssueName, name: activeIssueName, id: activeIssueName }],
- },
- };
-
- dispatchSpy = jest.spyOn(store, 'dispatch').mockResolvedValue();
- });
-
- afterEach(() => {
- window.gon = {};
- jest.restoreAllMocks();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when mounted', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it.each`
- text
- ${anotherIssueName}
- ${activeIssueName}
- `('finds item with $text', ({ text }) => {
- const item = findByText(text);
-
- expect(item.exists()).toBe(true);
- });
-
- it('renders gl-avatar-link in gl-dropdown-item', () => {
- const item = findByText('hello');
-
- expect(item.find(GlAvatarLink).exists()).toBe(true);
- });
-
- it('renders gl-avatar-labeled in gl-avatar-link', () => {
- const item = findByText('hello');
-
- expect(item.find(GlAvatarLink).find(GlAvatarLabeled).exists()).toBe(true);
- });
- });
-
- describe('when selected users are present', () => {
- it('renders a divider', () => {
- createComponent();
-
- expect(wrapper.find('[data-testid="selected-user-divider"]').exists()).toBe(true);
- });
- });
-
- describe('when collapsed', () => {
- it('renders IssuableAssignees', () => {
- createComponent();
-
- expect(wrapper.find(IssuableAssignees).isVisible()).toBe(true);
- expect(wrapper.find(MultiSelectDropdown).isVisible()).toBe(false);
- });
- });
-
- describe('when dropdown is open', () => {
- beforeEach(async () => {
- createComponent();
-
- await openDropdown();
- });
-
- it('shows assignees dropdown', async () => {
- expect(wrapper.find(IssuableAssignees).isVisible()).toBe(false);
- expect(wrapper.find(MultiSelectDropdown).isVisible()).toBe(true);
- });
-
- it('shows the issue returned as the activeIssue', async () => {
- expect(findByText(activeIssueName).props('isChecked')).toBe(true);
- });
-
- describe('when "Unassign" is clicked', () => {
- it('unassigns assignees', async () => {
- await unassign();
-
- expect(findByText('Unassign').props('isChecked')).toBe(true);
- });
- });
-
- describe('when an unselected item is clicked', () => {
- beforeEach(async () => {
- await unassign();
- });
-
- it('assigns assignee in the dropdown', async () => {
- wrapper.find('[data-testid="item_test"]').trigger('click');
-
- await wrapper.vm.$nextTick();
-
- expect(findByText(activeIssueName).props('isChecked')).toBe(true);
- });
-
- it('calls setAssignees with username list', async () => {
- wrapper.find('[data-testid="item_test"]').trigger('click');
-
- await wrapper.vm.$nextTick();
-
- document.body.click();
-
- await wrapper.vm.$nextTick();
-
- expect(store.dispatch).toHaveBeenCalledWith('setAssignees', [activeIssueName]);
- });
- });
-
- describe('when the user off clicks', () => {
- beforeEach(async () => {
- await unassign();
-
- document.body.click();
-
- await wrapper.vm.$nextTick();
- });
-
- it('calls setAssignees with username list', async () => {
- expect(store.dispatch).toHaveBeenCalledWith('setAssignees', []);
- });
-
- it('closes the dropdown', async () => {
- expect(wrapper.find(IssuableAssignees).isVisible()).toBe(true);
- });
- });
- });
-
- it('renders divider after unassign', () => {
- createComponent();
-
- expect(wrapper.find('[data-testid="unassign-divider"]').exists()).toBe(true);
- });
-
- it.each`
- assignees | expected
- ${[{ id: 5, username: '', name: '' }]} | ${'Assignee'}
- ${[{ id: 6, username: '', name: '' }, { id: 7, username: '', name: '' }]} | ${'2 Assignees'}
- `(
- 'when assignees have a length of $assignees.length, it renders $expected',
- ({ assignees, expected }) => {
- store.state.issues['1'].assignees = assignees;
-
- createComponent();
-
- expect(wrapper.find(BoardEditableItem).props('title')).toBe(expected);
- },
- );
-
- describe('when participants is loading', () => {
- beforeEach(() => {
- createComponent('', true);
- });
-
- it('finds a loading icon in the dropdown', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- });
- });
-
- describe('when participants is loading is false', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('does not find GlLoading icon in the dropdown', () => {
- expect(findLoadingIcon().exists()).toBe(false);
- });
-
- it('finds at least 1 GlDropdownItem', () => {
- expect(wrapper.findAll(GlDropdownItem).length).toBeGreaterThan(0);
- });
- });
-
- describe('Apollo', () => {
- beforeEach(() => {
- getIssueParticipantsSpy = jest.fn().mockResolvedValue({
- data: {
- issue: {
- participants: {
- nodes: [
- {
- username: 'participant',
- name: 'participant',
- webUrl: '',
- avatarUrl: '',
- id: '',
- },
- ],
- },
- },
- },
- });
- getSearchUsersSpy = jest.fn().mockResolvedValue({
- data: {
- users: {
- nodes: [{ username: 'root', name: 'root', webUrl: '', avatarUrl: '', id: '' }],
- },
- },
- });
- });
-
- describe('when search is empty', () => {
- beforeEach(() => {
- createComponentWithApollo();
- });
-
- it('calls getIssueParticipants', async () => {
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- expect(getIssueParticipantsSpy).toHaveBeenCalledWith({ id: 'gid://gitlab/Issue/111' });
- });
- });
-
- describe('when search is not empty', () => {
- beforeEach(() => {
- createComponentWithApollo('search term');
- });
-
- it('calls searchUsers', async () => {
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- expect(getSearchUsersSpy).toHaveBeenCalledWith({ search: 'search term' });
- });
- });
- });
-
- it('finds GlSearchBoxByType', async () => {
- createComponent();
-
- await openDropdown();
-
- expect(wrapper.find(GlSearchBoxByType).exists()).toBe(true);
- });
-
- describe('when assign-self is emitted from IssuableAssignees', () => {
- const currentUser = { username: 'self', name: '', id: '' };
-
- beforeEach(() => {
- window.gon = { current_username: currentUser.username };
-
- dispatchSpy.mockResolvedValue([currentUser]);
- createComponent();
-
- wrapper.find(IssuableAssignees).vm.$emit('assign-self');
- });
-
- it('calls setAssignees with currentUser', () => {
- expect(store.dispatch).toHaveBeenCalledWith('setAssignees', currentUser.username);
- });
-
- it('adds the user to the selected list', async () => {
- expect(findByText(currentUser.username).exists()).toBe(true);
- });
- });
-
- describe('when setting an assignee', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('passes loading state from Vuex to BoardEditableItem', async () => {
- store.state.isSettingAssignees = true;
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find(BoardEditableItem).props('loading')).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/boards/components/board_card_layout_deprecated_spec.js b/spec/frontend/boards/components/board_card_layout_deprecated_spec.js
new file mode 100644
index 00000000000..426c5289ba6
--- /dev/null
+++ b/spec/frontend/boards/components/board_card_layout_deprecated_spec.js
@@ -0,0 +1,158 @@
+/* global List */
+/* global ListLabel */
+
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+
+import MockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import '~/boards/models/label';
+import '~/boards/models/assignee';
+import '~/boards/models/list';
+import BoardCardLayout from '~/boards/components/board_card_layout_deprecated.vue';
+import issueCardInner from '~/boards/components/issue_card_inner.vue';
+import { ISSUABLE } from '~/boards/constants';
+import boardsVuexStore from '~/boards/stores';
+import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
+import { listObj, boardsMockInterceptor, setMockEndpoints } from '../mock_data';
+
+describe('Board card layout', () => {
+ let wrapper;
+ let mock;
+ let list;
+ let store;
+
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ const createStore = ({ getters = {}, actions = {} } = {}) => {
+ store = new Vuex.Store({
+ ...boardsVuexStore,
+ actions,
+ getters,
+ });
+ };
+
+ // this particular mount component needs to be used after the root beforeEach because it depends on list being initialized
+ const mountComponent = ({ propsData = {}, provide = {} } = {}) => {
+ wrapper = shallowMount(BoardCardLayout, {
+ localVue,
+ stubs: {
+ issueCardInner,
+ },
+ store,
+ propsData: {
+ list,
+ issue: list.issues[0],
+ disabled: false,
+ index: 0,
+ ...propsData,
+ },
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ scopedLabelsAvailable: false,
+ ...provide,
+ },
+ });
+ };
+
+ const setupData = () => {
+ list = new List(listObj);
+ boardsStore.create();
+ boardsStore.detail.issue = {};
+ const label1 = new ListLabel({
+ id: 3,
+ title: 'testing 123',
+ color: '#000cff',
+ text_color: 'white',
+ description: 'test',
+ });
+ return waitForPromises().then(() => {
+ list.issues[0].labels.push(label1);
+ });
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onAny().reply(boardsMockInterceptor);
+ setMockEndpoints();
+ return setupData();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ list = null;
+ mock.restore();
+ });
+
+ describe('mouse events', () => {
+ it('sets showDetail to true on mousedown', async () => {
+ createStore();
+ mountComponent();
+
+ wrapper.trigger('mousedown');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.showDetail).toBe(true);
+ });
+
+ it('sets showDetail to false on mousemove', async () => {
+ createStore();
+ mountComponent();
+ wrapper.trigger('mousedown');
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.showDetail).toBe(true);
+ wrapper.trigger('mousemove');
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.showDetail).toBe(false);
+ });
+
+ it("calls 'setActiveId' when 'graphqlBoardLists' feature flag is turned on", async () => {
+ const setActiveId = jest.fn();
+ createStore({
+ actions: {
+ setActiveId,
+ },
+ });
+ mountComponent({
+ provide: {
+ glFeatures: { graphqlBoardLists: true },
+ },
+ });
+
+ wrapper.trigger('mouseup');
+ await wrapper.vm.$nextTick();
+
+ expect(setActiveId).toHaveBeenCalledTimes(1);
+ expect(setActiveId).toHaveBeenCalledWith(expect.any(Object), {
+ id: list.issues[0].id,
+ sidebarType: ISSUABLE,
+ });
+ });
+
+ it("calls 'setActiveId' when epic swimlanes is active", async () => {
+ const setActiveId = jest.fn();
+ const isSwimlanesOn = () => true;
+ createStore({
+ getters: { isSwimlanesOn },
+ actions: {
+ setActiveId,
+ },
+ });
+ mountComponent();
+
+ wrapper.trigger('mouseup');
+ await wrapper.vm.$nextTick();
+
+ expect(setActiveId).toHaveBeenCalledTimes(1);
+ expect(setActiveId).toHaveBeenCalledWith(expect.any(Object), {
+ id: list.issues[0].id,
+ sidebarType: ISSUABLE,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_card_layout_spec.js b/spec/frontend/boards/components/board_card_layout_spec.js
index d8633871e8d..3fa8714807c 100644
--- a/spec/frontend/boards/components/board_card_layout_spec.js
+++ b/spec/frontend/boards/components/board_card_layout_spec.js
@@ -1,28 +1,14 @@
-/* global List */
-/* global ListLabel */
-
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
-import MockAdapter from 'axios-mock-adapter';
-import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-
-import '~/boards/models/label';
-import '~/boards/models/assignee';
-import '~/boards/models/list';
-import boardsVuexStore from '~/boards/stores';
-import boardsStore from '~/boards/stores/boards_store';
import BoardCardLayout from '~/boards/components/board_card_layout.vue';
-import issueCardInner from '~/boards/components/issue_card_inner.vue';
-import { listObj, boardsMockInterceptor, setMockEndpoints } from '../mock_data';
-
+import IssueCardInner from '~/boards/components/issue_card_inner.vue';
import { ISSUABLE } from '~/boards/constants';
+import defaultState from '~/boards/stores/state';
+import { mockLabelList, mockIssue } from '../mock_data';
describe('Board card layout', () => {
let wrapper;
- let mock;
- let list;
let store;
const localVue = createLocalVue();
@@ -30,7 +16,7 @@ describe('Board card layout', () => {
const createStore = ({ getters = {}, actions = {} } = {}) => {
store = new Vuex.Store({
- ...boardsVuexStore,
+ state: defaultState,
actions,
getters,
});
@@ -41,12 +27,12 @@ describe('Board card layout', () => {
wrapper = shallowMount(BoardCardLayout, {
localVue,
stubs: {
- issueCardInner,
+ IssueCardInner,
},
store,
propsData: {
- list,
- issue: list.issues[0],
+ list: mockLabelList,
+ issue: mockIssue,
disabled: false,
index: 0,
...propsData,
@@ -60,34 +46,9 @@ describe('Board card layout', () => {
});
};
- const setupData = () => {
- list = new List(listObj);
- boardsStore.create();
- boardsStore.detail.issue = {};
- const label1 = new ListLabel({
- id: 3,
- title: 'testing 123',
- color: '#000cff',
- text_color: 'white',
- description: 'test',
- });
- return waitForPromises().then(() => {
- list.issues[0].labels.push(label1);
- });
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onAny().reply(boardsMockInterceptor);
- setMockEndpoints();
- return setupData();
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
- list = null;
- mock.restore();
});
describe('mouse events', () => {
@@ -112,25 +73,21 @@ describe('Board card layout', () => {
expect(wrapper.vm.showDetail).toBe(false);
});
- it("calls 'setActiveId' when 'graphqlBoardLists' feature flag is turned on", async () => {
+ it("calls 'setActiveId'", async () => {
const setActiveId = jest.fn();
createStore({
actions: {
setActiveId,
},
});
- mountComponent({
- provide: {
- glFeatures: { graphqlBoardLists: true },
- },
- });
+ mountComponent();
wrapper.trigger('mouseup');
await wrapper.vm.$nextTick();
expect(setActiveId).toHaveBeenCalledTimes(1);
expect(setActiveId).toHaveBeenCalledWith(expect.any(Object), {
- id: list.issues[0].id,
+ id: mockIssue.id,
sidebarType: ISSUABLE,
});
});
@@ -151,7 +108,7 @@ describe('Board card layout', () => {
expect(setActiveId).toHaveBeenCalledTimes(1);
expect(setActiveId).toHaveBeenCalledWith(expect.any(Object), {
- id: list.issues[0].id,
+ id: mockIssue.id,
sidebarType: ISSUABLE,
});
});
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 1084009caad..5f26ae1bb3b 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -6,17 +6,17 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
+import BoardCard from '~/boards/components/board_card.vue';
+import issueCardInner from '~/boards/components/issue_card_inner.vue';
+import eventHub from '~/boards/eventhub';
+import store from '~/boards/stores';
+import boardsStore from '~/boards/stores/boards_store';
import axios from '~/lib/utils/axios_utils';
-import eventHub from '~/boards/eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/list';
-import store from '~/boards/stores';
-import boardsStore from '~/boards/stores/boards_store';
-import BoardCard from '~/boards/components/board_card.vue';
-import issueCardInner from '~/boards/components/issue_card_inner.vue';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { listObj, boardsMockInterceptor, setMockEndpoints } from '../mock_data';
diff --git a/spec/frontend/boards/components/board_column_deprecated_spec.js b/spec/frontend/boards/components/board_column_deprecated_spec.js
index a703caca4eb..e6d65e48c3f 100644
--- a/spec/frontend/boards/components/board_column_deprecated_spec.js
+++ b/spec/frontend/boards/components/board_column_deprecated_spec.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import Vue, { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { listObj } from 'jest/boards/mock_data';
import Board from '~/boards/components/board_column_deprecated.vue';
-import List from '~/boards/models/list';
import { ListType } from '~/boards/constants';
+import List from '~/boards/models/list';
import axios from '~/lib/utils/axios_utils';
describe('Board Column Component', () => {
@@ -30,6 +30,7 @@ describe('Board Column Component', () => {
const createComponent = ({
listType = ListType.backlog,
collapsed = false,
+ highlighted = false,
withLocalStorage = true,
} = {}) => {
const boardId = '1';
@@ -37,6 +38,7 @@ describe('Board Column Component', () => {
const listMock = {
...listObj,
list_type: listType,
+ highlighted,
collapsed,
};
@@ -91,4 +93,14 @@ describe('Board Column Component', () => {
expect(isCollapsed()).toBe(true);
});
});
+
+ describe('highlighting', () => {
+ it('scrolls to column when highlighted', async () => {
+ createComponent({ highlighted: true });
+
+ await nextTick();
+
+ expect(wrapper.element.scrollIntoView).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js
index 1dcdad2b492..4e523d636cd 100644
--- a/spec/frontend/boards/components/board_column_spec.js
+++ b/spec/frontend/boards/components/board_column_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { listObj } from 'jest/boards/mock_data';
import BoardColumn from '~/boards/components/board_column.vue';
@@ -66,4 +67,16 @@ describe('Board Column Component', () => {
expect(isCollapsed()).toBe(true);
});
});
+
+ describe('highlighting', () => {
+ it('scrolls to column when highlighted', async () => {
+ createComponent();
+
+ store.state.highlightedLists.push(listObj.id);
+
+ await nextTick();
+
+ expect(wrapper.element.scrollIntoView).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/boards/components/board_configuration_options_spec.js b/spec/frontend/boards/components/board_configuration_options_spec.js
index d9614c254e2..6f0971a9458 100644
--- a/spec/frontend/boards/components/board_configuration_options_spec.js
+++ b/spec/frontend/boards/components/board_configuration_options_spec.js
@@ -7,6 +7,7 @@ describe('BoardConfigurationOptions', () => {
const defaultProps = {
hideBacklogList: false,
hideClosedList: false,
+ readonly: false,
};
const createComponent = (props = {}) => {
@@ -61,4 +62,18 @@ describe('BoardConfigurationOptions', () => {
expect(wrapper.emitted('update:hideClosedList')).toEqual([[true]]);
});
+
+ it('renders checkboxes disabled when user does not have edit rights', () => {
+ createComponent({ readonly: true });
+
+ expect(closedListCheckbox().attributes('disabled')).toBe('true');
+ expect(backlogListCheckbox().attributes('disabled')).toBe('true');
+ });
+
+ it('renders checkboxes enabled when user has edit rights', () => {
+ createComponent();
+
+ expect(closedListCheckbox().attributes('disabled')).toBeUndefined();
+ expect(backlogListCheckbox().attributes('disabled')).toBeUndefined();
+ });
});
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index 98be02d7dbf..159b67ccc67 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -1,12 +1,12 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlAlert } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import Draggable from 'vuedraggable';
+import Vuex from 'vuex';
import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
import getters from 'ee_else_ce/boards/stores/getters';
import BoardColumnDeprecated from '~/boards/components/board_column_deprecated.vue';
-import { mockLists, mockListsWithModel } from '../mock_data';
import BoardContent from '~/boards/components/board_content.vue';
+import { mockLists, mockListsWithModel } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index c34987a55de..858efea99ad 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -1,16 +1,15 @@
+import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-
import { TEST_HOST } from 'helpers/test_constants';
-import { GlModal } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { visitUrl } from '~/lib/utils/url_utility';
-import boardsStore from '~/boards/stores/boards_store';
import BoardForm from '~/boards/components/board_form.vue';
-import updateBoardMutation from '~/boards/graphql/board_update.mutation.graphql';
+import { formType } from '~/boards/constants';
import createBoardMutation from '~/boards/graphql/board_create.mutation.graphql';
import destroyBoardMutation from '~/boards/graphql/board_destroy.mutation.graphql';
+import updateBoardMutation from '~/boards/graphql/board_update.mutation.graphql';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'),
@@ -35,6 +34,7 @@ const defaultProps = {
labelsPath: `${TEST_HOST}/labels/path`,
labelsWebUrl: `${TEST_HOST}/-/labels`,
currentBoard,
+ currentPage: '',
};
describe('BoardForm', () => {
@@ -75,14 +75,12 @@ describe('BoardForm', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
- boardsStore.state.currentPage = null;
mutate = null;
});
describe('when user can not admin the board', () => {
beforeEach(() => {
- boardsStore.state.currentPage = 'new';
- createComponent();
+ createComponent({ currentPage: formType.new });
});
it('hides modal footer when user is not a board admin', () => {
@@ -100,8 +98,7 @@ describe('BoardForm', () => {
describe('when user can admin the board', () => {
beforeEach(() => {
- boardsStore.state.currentPage = 'new';
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.new });
});
it('shows modal footer when user is a board admin', () => {
@@ -118,13 +115,9 @@ describe('BoardForm', () => {
});
describe('when creating a new board', () => {
- beforeEach(() => {
- boardsStore.state.currentPage = 'new';
- });
-
describe('on non-scoped-board', () => {
beforeEach(() => {
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.new });
});
it('clears the form', () => {
@@ -165,7 +158,7 @@ describe('BoardForm', () => {
});
it('does not call API if board name is empty', async () => {
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.new });
findInput().trigger('keyup.enter', { metaKey: true });
await waitForPromises();
@@ -174,7 +167,7 @@ describe('BoardForm', () => {
});
it('calls a correct GraphQL mutation and redirects to correct page from existing board', async () => {
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.new });
fillForm();
await waitForPromises();
@@ -194,7 +187,7 @@ describe('BoardForm', () => {
it('shows an error flash if GraphQL mutation fails', async () => {
mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.new });
fillForm();
await waitForPromises();
@@ -209,13 +202,9 @@ describe('BoardForm', () => {
});
describe('when editing a board', () => {
- beforeEach(() => {
- boardsStore.state.currentPage = 'edit';
- });
-
describe('on non-scoped-board', () => {
beforeEach(() => {
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.edit });
});
it('clears the form', () => {
@@ -247,7 +236,7 @@ describe('BoardForm', () => {
},
});
window.location = new URL('https://test/boards/1');
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.edit });
findInput().trigger('keyup.enter', { metaKey: true });
@@ -273,7 +262,7 @@ describe('BoardForm', () => {
},
});
window.location = new URL('https://test/boards/1?group_by=epic');
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.edit });
findInput().trigger('keyup.enter', { metaKey: true });
@@ -294,7 +283,7 @@ describe('BoardForm', () => {
it('shows an error flash if GraphQL mutation fails', async () => {
mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.edit });
findInput().trigger('keyup.enter', { metaKey: true });
await waitForPromises();
@@ -308,24 +297,20 @@ describe('BoardForm', () => {
});
describe('when deleting a board', () => {
- beforeEach(() => {
- boardsStore.state.currentPage = 'delete';
- });
-
it('passes correct primary action text and variant', () => {
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.delete });
expect(findModalActionPrimary().text).toBe('Delete');
expect(findModalActionPrimary().attributes[0].variant).toBe('danger');
});
it('renders delete confirmation message', () => {
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.delete });
expect(findDeleteConfirmation().exists()).toBe(true);
});
it('calls a correct GraphQL mutation and redirects to correct page after deleting board', async () => {
mutate = jest.fn().mockResolvedValue({});
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.delete });
findModal().vm.$emit('primary');
await waitForPromises();
@@ -343,7 +328,7 @@ describe('BoardForm', () => {
it('shows an error flash if GraphQL mutation fails', async () => {
mutate = jest.fn().mockRejectedValue('Houston, we have a problem');
- createComponent({ canAdminBoard: true });
+ createComponent({ canAdminBoard: true, currentPage: formType.delete });
findModal().vm.$emit('primary');
await waitForPromises();
diff --git a/spec/frontend/boards/components/board_list_header_deprecated_spec.js b/spec/frontend/boards/components/board_list_header_deprecated_spec.js
index 6207724e6a9..fdc7cd2b1d4 100644
--- a/spec/frontend/boards/components/board_list_header_deprecated_spec.js
+++ b/spec/frontend/boards/components/board_list_header_deprecated_spec.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { listObj } from 'jest/boards/mock_data';
import BoardListHeader from '~/boards/components/board_list_header_deprecated.vue';
-import List from '~/boards/models/list';
import { ListType } from '~/boards/constants';
+import List from '~/boards/models/list';
import axios from '~/lib/utils/axios_utils';
describe('Board List Header Component', () => {
@@ -74,7 +74,13 @@ describe('Board List Header Component', () => {
describe('Add issue button', () => {
const hasNoAddButton = [ListType.closed];
- const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee];
+ const hasAddButton = [
+ ListType.backlog,
+ ListType.label,
+ ListType.milestone,
+ ListType.iteration,
+ ListType.assignee,
+ ];
it.each(hasNoAddButton)('does not render when List Type is `%s`', (listType) => {
createComponent({ listType });
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 357d05ced02..f30e3792435 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 Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { mockLabelList } from 'jest/boards/mock_data';
import BoardListHeader from '~/boards/components/board_list_header.vue';
@@ -78,7 +78,13 @@ describe('Board List Header Component', () => {
describe('Add issue button', () => {
const hasNoAddButton = [ListType.closed];
- const hasAddButton = [ListType.backlog, ListType.label, ListType.milestone, ListType.assignee];
+ const hasAddButton = [
+ ListType.backlog,
+ ListType.label,
+ ListType.milestone,
+ ListType.iteration,
+ ListType.assignee,
+ ];
it.each(hasNoAddButton)('does not render when List Type is `%s`', (listType) => {
createComponent({ listType });
@@ -167,7 +173,7 @@ describe('Board List Header Component', () => {
describe('user can drag', () => {
const cannotDragList = [ListType.backlog, ListType.closed];
- const canDragList = [ListType.label, ListType.milestone, ListType.assignee];
+ const canDragList = [ListType.label, ListType.milestone, ListType.iteration, ListType.assignee];
it.each(cannotDragList)(
'does not have user-can-drag-class so user cannot drag list',
diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js
index 5a01221a5be..ce8c95527e9 100644
--- a/spec/frontend/boards/components/board_new_issue_spec.js
+++ b/spec/frontend/boards/components/board_new_issue_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import BoardNewIssue from '~/boards/components/board_new_issue.vue';
import '~/boards/models/list';
diff --git a/spec/frontend/boards/components/board_settings_sidebar_spec.js b/spec/frontend/boards/components/board_settings_sidebar_spec.js
index 12c9431f2d4..52b4d71f7b9 100644
--- a/spec/frontend/boards/components/board_settings_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_settings_sidebar_spec.js
@@ -1,14 +1,14 @@
import '~/boards/models/list';
-import MockAdapter from 'axios-mock-adapter';
+import { GlDrawer, GlLabel } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlDrawer, GlLabel } from '@gitlab/ui';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
-import boardsStore from '~/boards/stores/boards_store';
+import { inactiveId, LIST } from '~/boards/constants';
import { createStore } from '~/boards/stores';
+import boardsStore from '~/boards/stores/boards_store';
import sidebarEventHub from '~/sidebar/event_hub';
-import { inactiveId, LIST } from '~/boards/constants';
const localVue = createLocalVue();
diff --git a/spec/frontend/boards/components/boards_selector_deprecated_spec.js b/spec/frontend/boards/components/boards_selector_deprecated_spec.js
new file mode 100644
index 00000000000..cc078861d75
--- /dev/null
+++ b/spec/frontend/boards/components/boards_selector_deprecated_spec.js
@@ -0,0 +1,214 @@
+import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { TEST_HOST } from 'spec/test_constants';
+import BoardsSelector from '~/boards/components/boards_selector_deprecated.vue';
+import boardsStore from '~/boards/stores/boards_store';
+
+const throttleDuration = 1;
+
+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;
+ const boards = boardGenerator(20);
+ const recentBoards = boardGenerator(5);
+
+ const fillSearchBox = (filterTerm) => {
+ const searchBox = wrapper.find({ ref: 'searchBox' });
+ const searchBoxInput = searchBox.find('input');
+ searchBoxInput.setValue(filterTerm);
+ searchBoxInput.trigger('input');
+ };
+
+ const getDropdownItems = () => wrapper.findAll('.js-dropdown-item');
+ const getDropdownHeaders = () => wrapper.findAll(GlDropdownSectionHeader);
+ const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findDropdown = () => wrapper.find(GlDropdown);
+
+ beforeEach(() => {
+ const $apollo = {
+ queries: {
+ boards: {
+ loading: false,
+ },
+ },
+ };
+
+ boardsStore.setEndpoints({
+ boardsEndpoint: '',
+ recentBoardsEndpoint: '',
+ listsEndpoint: '',
+ bulkUpdatePath: '',
+ boardId: '',
+ });
+
+ allBoardsResponse = Promise.resolve({
+ data: {
+ group: {
+ boards: {
+ edges: boards.map((board) => ({ node: board })),
+ },
+ },
+ },
+ });
+ recentBoardsResponse = Promise.resolve({
+ data: recentBoards,
+ });
+
+ boardsStore.allBoards = jest.fn(() => allBoardsResponse);
+ boardsStore.recentBoards = jest.fn(() => recentBoardsResponse);
+
+ wrapper = mount(BoardsSelector, {
+ propsData: {
+ throttleDuration,
+ currentBoard: {
+ id: 1,
+ name: 'Development',
+ milestone_id: null,
+ weight: null,
+ assignee_id: null,
+ labels: [],
+ },
+ boardBaseUrl: `${TEST_HOST}/board/base/url`,
+ hasMissingBoards: false,
+ canAdminBoard: true,
+ multipleIssueBoardsAvailable: true,
+ labelsPath: `${TEST_HOST}/labels/path`,
+ labelsWebUrl: `${TEST_HOST}/labels`,
+ projectId: 42,
+ groupId: 19,
+ scopedIssueBoardFeatureEnabled: true,
+ weights: [],
+ },
+ mocks: { $apollo },
+ attachTo: document.body,
+ });
+
+ wrapper.vm.$apollo.addSmartQuery = jest.fn((_, options) => {
+ wrapper.setData({
+ [options.loadingKey]: true,
+ });
+ });
+
+ // Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
+ findDropdown().vm.$emit('show');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('loading', () => {
+ // we are testing loading state, so don't resolve responses until after the tests
+ afterEach(() => {
+ return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
+ });
+
+ it('shows loading spinner', () => {
+ expect(getDropdownHeaders()).toHaveLength(0);
+ expect(getDropdownItems()).toHaveLength(0);
+ expect(getLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('loaded', () => {
+ beforeEach(async () => {
+ await wrapper.setData({
+ loadingBoards: false,
+ });
+ return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
+ });
+
+ it('hides loading spinner', () => {
+ expect(getLoadingIcon().exists()).toBe(false);
+ });
+
+ describe('filtering', () => {
+ beforeEach(() => {
+ wrapper.setData({
+ boards,
+ });
+
+ return nextTick();
+ });
+
+ it('shows all boards without filtering', () => {
+ expect(getDropdownItems()).toHaveLength(boards.length + recentBoards.length);
+ });
+
+ it('shows only matching boards when filtering', () => {
+ const filterTerm = 'board1';
+ const expectedCount = boards.filter((board) => board.name.includes(filterTerm)).length;
+
+ fillSearchBox(filterTerm);
+
+ return nextTick().then(() => {
+ expect(getDropdownItems()).toHaveLength(expectedCount);
+ });
+ });
+
+ it('shows message if there are no matching boards', () => {
+ fillSearchBox('does not exist');
+
+ return nextTick().then(() => {
+ expect(getDropdownItems()).toHaveLength(0);
+ expect(wrapper.text().includes('No matching boards found')).toBe(true);
+ });
+ });
+ });
+
+ describe('recent boards section', () => {
+ it('shows only when boards are greater than 10', () => {
+ wrapper.setData({
+ boards,
+ });
+
+ return nextTick().then(() => {
+ expect(getDropdownHeaders()).toHaveLength(2);
+ });
+ });
+
+ it('does not show when boards are less than 10', () => {
+ wrapper.setData({
+ boards: boards.slice(0, 5),
+ });
+
+ return nextTick().then(() => {
+ expect(getDropdownHeaders()).toHaveLength(0);
+ });
+ });
+
+ it('does not show when recentBoards api returns empty array', () => {
+ wrapper.setData({
+ recentBoards: [],
+ });
+
+ return nextTick().then(() => {
+ expect(getDropdownHeaders()).toHaveLength(0);
+ });
+ });
+
+ it('does not show when search is active', () => {
+ fillSearchBox('Random string');
+
+ return nextTick().then(() => {
+ expect(getDropdownHeaders()).toHaveLength(0);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js
index 81575bf486a..bf317b51e83 100644
--- a/spec/frontend/boards/components/boards_selector_spec.js
+++ b/spec/frontend/boards/components/boards_selector_spec.js
@@ -1,9 +1,10 @@
-import { nextTick } from 'vue';
-import { mount } from '@vue/test-utils';
import { GlDropdown, GlLoadingIcon, GlDropdownSectionHeader } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { TEST_HOST } from 'spec/test_constants';
import BoardsSelector from '~/boards/components/boards_selector.vue';
-import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
const throttleDuration = 1;
@@ -23,6 +24,7 @@ describe('BoardsSelector', () => {
let wrapper;
let allBoardsResponse;
let recentBoardsResponse;
+ let mock;
const boards = boardGenerator(20);
const recentBoards = boardGenerator(5);
@@ -39,6 +41,7 @@ describe('BoardsSelector', () => {
const findDropdown = () => wrapper.find(GlDropdown);
beforeEach(() => {
+ mock = new MockAdapter(axios);
const $apollo = {
queries: {
boards: {
@@ -47,14 +50,6 @@ describe('BoardsSelector', () => {
},
};
- boardsStore.setEndpoints({
- boardsEndpoint: '',
- recentBoardsEndpoint: '',
- listsEndpoint: '',
- bulkUpdatePath: '',
- boardId: '',
- });
-
allBoardsResponse = Promise.resolve({
data: {
group: {
@@ -68,9 +63,6 @@ describe('BoardsSelector', () => {
data: recentBoards,
});
- boardsStore.allBoards = jest.fn(() => allBoardsResponse);
- boardsStore.recentBoards = jest.fn(() => recentBoardsResponse);
-
wrapper = mount(BoardsSelector, {
propsData: {
throttleDuration,
@@ -95,6 +87,10 @@ describe('BoardsSelector', () => {
},
mocks: { $apollo },
attachTo: document.body,
+ provide: {
+ fullPath: '',
+ recentBoardsEndpoint: `${TEST_HOST}/recent`,
+ },
});
wrapper.vm.$apollo.addSmartQuery = jest.fn((_, options) => {
@@ -103,6 +99,8 @@ describe('BoardsSelector', () => {
});
});
+ mock.onGet(`${TEST_HOST}/recent`).replyOnce(200, recentBoards);
+
// Emits gl-dropdown show event to simulate the dropdown is opened at initialization time
findDropdown().vm.$emit('show');
});
@@ -110,6 +108,7 @@ describe('BoardsSelector', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ mock.restore();
});
describe('loading', () => {
@@ -133,7 +132,8 @@ describe('BoardsSelector', () => {
return Promise.all([allBoardsResponse, recentBoardsResponse]).then(() => nextTick());
});
- it('hides loading spinner', () => {
+ it('hides loading spinner', async () => {
+ await wrapper.vm.$nextTick();
expect(getLoadingIcon().exists()).toBe(false);
});
diff --git a/spec/frontend/boards/components/issue_time_estimate_spec.js b/spec/frontend/boards/components/issue_time_estimate_spec.js
index 9ac8fae3fcc..2e253d24125 100644
--- a/spec/frontend/boards/components/issue_time_estimate_spec.js
+++ b/spec/frontend/boards/components/issue_time_estimate_spec.js
@@ -1,5 +1,5 @@
-import { config as vueConfig } from 'vue';
import { shallowMount } from '@vue/test-utils';
+import { config as vueConfig } from 'vue';
import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue';
describe('Issue Time Estimate component', () => {
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 de414bb929e..12e9a9ba365 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import BoardSidebarItem from '~/boards/components/sidebar/board_editable_item.vue';
describe('boards sidebar remove issue', () => {
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
index b034c8cb11d..7838b5a0b2f 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_due_date_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDatepicker } from '@gitlab/ui';
-import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
+import { shallowMount } from '@vue/test-utils';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import BoardSidebarDueDate from '~/boards/components/sidebar/board_sidebar_due_date.vue';
import { createStore } from '~/boards/stores';
import createFlash from '~/flash';
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js
index 86895c648a4..bc7df1c76c6 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_issue_title_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlFormInput, GlForm } from '@gitlab/ui';
-import BoardSidebarIssueTitle from '~/boards/components/sidebar/board_sidebar_issue_title.vue';
+import { shallowMount } from '@vue/test-utils';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import createFlash from '~/flash';
+import BoardSidebarIssueTitle from '~/boards/components/sidebar/board_sidebar_issue_title.vue';
import { createStore } from '~/boards/stores';
+import createFlash from '~/flash';
const TEST_TITLE = 'New issue title';
const TEST_ISSUE_A = {
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
index 2342caa9dfd..12b873ba7d8 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
@@ -1,12 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLabel } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import { labels as TEST_LABELS, mockIssue as TEST_ISSUE } from 'jest/boards/mock_data';
-import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
import { createStore } from '~/boards/stores';
import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
jest.mock('~/flash');
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js
index 74d88d9f34c..8820ec7ae63 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_milestone_select_spec.js
@@ -1,8 +1,8 @@
+import { GlLoadingIcon, GlDropdown } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
import { mockMilestone as TEST_MILESTONE } from 'jest/boards/mock_data';
-import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import BoardSidebarMilestoneSelect from '~/boards/components/sidebar/board_sidebar_milestone_select.vue';
import { createStore } from '~/boards/stores';
import createFlash from '~/flash';
@@ -20,7 +20,7 @@ describe('~/boards/components/sidebar/board_sidebar_milestone_select.vue', () =>
wrapper = null;
});
- const createWrapper = ({ milestone = null } = {}) => {
+ const createWrapper = ({ milestone = null, loading = false } = {}) => {
store = createStore();
store.state.issues = { [TEST_ISSUE.id]: { ...TEST_ISSUE, milestone } };
store.state.activeId = TEST_ISSUE.id;
@@ -38,7 +38,7 @@ describe('~/boards/components/sidebar/board_sidebar_milestone_select.vue', () =>
},
mocks: {
$apollo: {
- loading: false,
+ loading,
},
},
});
@@ -46,10 +46,42 @@ describe('~/boards/components/sidebar/board_sidebar_milestone_select.vue', () =>
const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findBoardEditableItem = () => wrapper.find(BoardEditableItem);
const findDropdownItem = () => wrapper.find('[data-testid="milestone-item"]');
const findUnsetMilestoneItem = () => wrapper.find('[data-testid="no-milestone-item"]');
const findNoMilestonesFoundItem = () => wrapper.find('[data-testid="no-milestones-found"]');
+ describe('when not editing', () => {
+ it('opens the milestone dropdown on clicking edit', async () => {
+ createWrapper();
+ wrapper.vm.$refs.dropdown.show = jest.fn();
+
+ await findBoardEditableItem().vm.$emit('open');
+
+ expect(wrapper.vm.$refs.dropdown.show).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('when editing', () => {
+ beforeEach(() => {
+ createWrapper();
+ jest.spyOn(wrapper.vm.$refs.sidebarItem, 'collapse');
+ });
+
+ it('collapses BoardEditableItem on clicking edit', async () => {
+ await findBoardEditableItem().vm.$emit('close');
+
+ expect(wrapper.vm.$refs.sidebarItem.collapse).toHaveBeenCalledTimes(1);
+ });
+
+ it('collapses BoardEditableItem on hiding dropdown', async () => {
+ await findDropdown().vm.$emit('hide');
+
+ expect(wrapper.vm.$refs.sidebarItem.collapse).toHaveBeenCalledTimes(1);
+ });
+ });
+
it('renders "None" when no milestone is selected', () => {
createWrapper();
@@ -63,12 +95,7 @@ describe('~/boards/components/sidebar/board_sidebar_milestone_select.vue', () =>
});
it('shows loader while Apollo is loading', async () => {
- createWrapper({ milestone: TEST_MILESTONE });
-
- expect(findLoader().exists()).toBe(false);
-
- wrapper.vm.$apollo.loading = true;
- await wrapper.vm.$nextTick();
+ createWrapper({ milestone: TEST_MILESTONE, loading: true });
expect(findLoader().exists()).toBe(true);
});
@@ -76,8 +103,7 @@ describe('~/boards/components/sidebar/board_sidebar_milestone_select.vue', () =>
it('shows message when error or no milestones found', async () => {
createWrapper();
- wrapper.setData({ milestones: [] });
- await wrapper.vm.$nextTick();
+ await wrapper.setData({ milestones: [] });
expect(findNoMilestonesFoundItem().text()).toBe('No milestones found');
});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
index b1df0f2d771..3e6b0be0267 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
@@ -1,11 +1,11 @@
-import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlToggle, GlLoadingIcon } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import BoardSidebarSubscription from '~/boards/components/sidebar/board_sidebar_subscription.vue';
-import * as types from '~/boards/stores/mutation_types';
import { createStore } from '~/boards/stores';
-import { mockActiveIssue } from '../../mock_data';
+import * as types from '~/boards/stores/mutation_types';
import createFlash from '~/flash';
+import { mockActiveIssue } from '../../mock_data';
jest.mock('~/flash.js');
diff --git a/spec/frontend/boards/components/sidebar/remove_issue_spec.js b/spec/frontend/boards/components/sidebar/remove_issue_spec.js
index 1b7a78e6e58..1f740c10106 100644
--- a/spec/frontend/boards/components/sidebar/remove_issue_spec.js
+++ b/spec/frontend/boards/components/sidebar/remove_issue_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import RemoveIssue from '~/boards/components/sidebar/remove_issue.vue';
diff --git a/spec/frontend/boards/issue_card_deprecated_spec.js b/spec/frontend/boards/issue_card_deprecated_spec.js
index fd7b0edb97e..909be275030 100644
--- a/spec/frontend/boards/issue_card_deprecated_spec.js
+++ b/spec/frontend/boards/issue_card_deprecated_spec.js
@@ -1,14 +1,14 @@
/* global ListAssignee, ListLabel, ListIssue */
+import { GlLabel } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { range } from 'lodash';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
-import { GlLabel } from '@gitlab/ui';
import IssueCardInner from '~/boards/components/issue_card_inner_deprecated.vue';
-import { listObj } from './mock_data';
import store from '~/boards/stores';
+import { listObj } from './mock_data';
describe('Issue card component', () => {
const user = new ListAssignee({
diff --git a/spec/frontend/boards/issue_card_inner_spec.js b/spec/frontend/boards/issue_card_inner_spec.js
index f9ad78494af..b9f84fed6b3 100644
--- a/spec/frontend/boards/issue_card_inner_spec.js
+++ b/spec/frontend/boards/issue_card_inner_spec.js
@@ -1,11 +1,11 @@
+import { GlLabel } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { range } from 'lodash';
-import { GlLabel } from '@gitlab/ui';
import IssueCardInner from '~/boards/components/issue_card_inner.vue';
-import { mockLabelList } from './mock_data';
-import defaultStore from '~/boards/stores';
import eventHub from '~/boards/eventhub';
+import defaultStore from '~/boards/stores';
import { updateHistory } from '~/lib/utils/url_utility';
+import { mockLabelList } from './mock_data';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/boards/eventhub');
diff --git a/spec/frontend/boards/issue_spec.js b/spec/frontend/boards/issue_spec.js
index d68e17c06a7..1f354fb04db 100644
--- a/spec/frontend/boards/issue_spec.js
+++ b/spec/frontend/boards/issue_spec.js
@@ -41,7 +41,7 @@ describe('Issue model', () => {
});
expect(issue.labels.length).toBe(1);
- expect(issue.labels[0].color).toBe('red');
+ expect(issue.labels[0].color).toBe('#F0AD4E');
});
it('adds other label with same title', () => {
diff --git a/spec/frontend/boards/list_spec.js b/spec/frontend/boards/list_spec.js
index db01f62c9a6..4d6a82bdff0 100644
--- a/spec/frontend/boards/list_spec.js
+++ b/spec/frontend/boards/list_spec.js
@@ -2,16 +2,15 @@
/* global ListAssignee */
/* global ListIssue */
/* global ListLabel */
-
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import { ListType } from '~/boards/constants';
import boardsStore from '~/boards/stores/boards_store';
+import axios from '~/lib/utils/axios_utils';
import { listObj, listObjDuplicate, boardsMockInterceptor } from './mock_data';
describe('List model', () => {
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index d5cfb9b7d07..e106b9235d6 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -1,7 +1,7 @@
/* global List */
-import Vue from 'vue';
import { keyBy } from 'lodash';
+import Vue from 'vue';
import '~/boards/models/list';
import boardsStore from '~/boards/stores/boards_store';
@@ -137,7 +137,7 @@ export const rawIssue = {
{
id: 1,
title: 'test',
- color: 'red',
+ color: '#F0AD4E',
description: 'testing',
},
],
@@ -165,7 +165,7 @@ export const mockIssue = {
{
id: 1,
title: 'test',
- color: 'red',
+ color: '#F0AD4E',
description: 'testing',
},
],
diff --git a/spec/frontend/boards/project_select_deprecated_spec.js b/spec/frontend/boards/project_select_deprecated_spec.js
index e4f8f96bd33..9042c4bf9ba 100644
--- a/spec/frontend/boards/project_select_deprecated_spec.js
+++ b/spec/frontend/boards/project_select_deprecated_spec.js
@@ -1,14 +1,13 @@
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import axios from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
-import httpStatus from '~/lib/utils/http_status';
-import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
+import ProjectSelect from '~/boards/components/project_select_deprecated.vue';
import { ListType } from '~/boards/constants';
import eventHub from '~/boards/eventhub';
import { deprecatedCreateFlash as flash } from '~/flash';
-
-import ProjectSelect from '~/boards/components/project_select_deprecated.vue';
+import httpStatus from '~/lib/utils/http_status';
+import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
import { listObj, mockRawGroupProjects } from './mock_data';
diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js
index 14ddab3542b..aa71952c42b 100644
--- a/spec/frontend/boards/project_select_spec.js
+++ b/spec/frontend/boards/project_select_spec.js
@@ -1,9 +1,8 @@
-import Vuex from 'vuex';
-import { createLocalVue, mount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
-import defaultState from '~/boards/stores/state';
-
+import { createLocalVue, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
import ProjectSelect from '~/boards/components/project_select.vue';
+import defaultState from '~/boards/stores/state';
import { mockList, mockGroupProjects } from './mock_data';
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index e4209cd5e55..32d0e7ae886 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -1,5 +1,17 @@
import testAction from 'helpers/vuex_action_helper';
import {
+ fullBoardId,
+ formatListIssues,
+ formatBoardLists,
+ formatIssueInput,
+} from '~/boards/boards_util';
+import { inactiveId } from '~/boards/constants';
+import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
+import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
+import issueMoveListMutation from '~/boards/graphql/issue_move_list.mutation.graphql';
+import actions, { gqlClient } from '~/boards/stores/actions';
+import * as types from '~/boards/stores/mutation_types';
+import {
mockLists,
mockListsById,
mockIssue,
@@ -11,20 +23,6 @@ import {
mockActiveIssue,
mockGroupProjects,
} from '../mock_data';
-import actions, { gqlClient } from '~/boards/stores/actions';
-import * as types from '~/boards/stores/mutation_types';
-import { inactiveId } from '~/boards/constants';
-import issueMoveListMutation from '~/boards/graphql/issue_move_list.mutation.graphql';
-import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
-import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
-import updateAssignees from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql';
-import {
- fullBoardId,
- formatListIssues,
- formatBoardLists,
- formatIssueInput,
-} from '~/boards/boards_util';
-import createFlash from '~/flash';
jest.mock('~/flash');
@@ -71,7 +69,7 @@ describe('setFilters', () => {
actions.setFilters,
filters,
state,
- [{ type: types.SET_FILTERS, payload: filters }],
+ [{ type: types.SET_FILTERS, payload: { ...filters, not: {} } }],
[],
done,
);
@@ -186,7 +184,27 @@ describe('fetchLists', () => {
});
describe('createList', () => {
- it('should dispatch addList action when creating backlog list', (done) => {
+ let commit;
+ let dispatch;
+ let getters;
+ let state;
+
+ beforeEach(() => {
+ state = {
+ fullPath: 'gitlab-org',
+ boardId: '1',
+ boardType: 'group',
+ disabled: false,
+ boardLists: [{ type: 'closed' }],
+ };
+ commit = jest.fn();
+ dispatch = jest.fn();
+ getters = {
+ getListByLabelId: jest.fn(),
+ };
+ });
+
+ it('should dispatch addList action when creating backlog list', async () => {
const backlogList = {
id: 'gid://gitlab/List/1',
listType: 'backlog',
@@ -205,25 +223,35 @@ describe('createList', () => {
}),
);
- const state = {
- fullPath: 'gitlab-org',
- boardId: '1',
- boardType: 'group',
- disabled: false,
- boardLists: [{ type: 'closed' }],
+ await actions.createList({ getters, state, commit, dispatch }, { backlog: true });
+
+ expect(dispatch).toHaveBeenCalledWith('addList', backlogList);
+ });
+
+ it('dispatches highlightList after addList has succeeded', async () => {
+ const list = {
+ id: 'gid://gitlab/List/1',
+ listType: 'label',
+ title: 'Open',
+ labelId: '4',
};
- testAction(
- actions.createList,
- { backlog: true },
- state,
- [],
- [{ type: 'addList', payload: backlogList }],
- done,
- );
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ boardListCreate: {
+ list,
+ errors: [],
+ },
+ },
+ });
+
+ await actions.createList({ getters, state, commit, dispatch }, { labelId: '4' });
+
+ expect(dispatch).toHaveBeenCalledWith('addList', list);
+ expect(dispatch).toHaveBeenCalledWith('highlightList', list.id);
});
- it('should commit CREATE_LIST_FAILURE mutation when API returns an error', (done) => {
+ it('should commit CREATE_LIST_FAILURE mutation when API returns an error', async () => {
jest.spyOn(gqlClient, 'mutate').mockReturnValue(
Promise.resolve({
data: {
@@ -235,22 +263,49 @@ describe('createList', () => {
}),
);
- const state = {
- fullPath: 'gitlab-org',
- boardId: '1',
- boardType: 'group',
- disabled: false,
- boardLists: [{ type: 'closed' }],
+ await actions.createList({ getters, state, commit, dispatch }, { backlog: true });
+
+ expect(commit).toHaveBeenCalledWith(types.CREATE_LIST_FAILURE);
+ });
+
+ it('highlights list and does not re-query if it already exists', async () => {
+ const existingList = {
+ id: 'gid://gitlab/List/1',
+ listType: 'label',
+ title: 'Some label',
+ position: 1,
};
- testAction(
- actions.createList,
- { backlog: true },
- state,
- [{ type: types.CREATE_LIST_FAILURE }],
- [],
- done,
- );
+ getters = {
+ getListByLabelId: jest.fn().mockReturnValue(existingList),
+ };
+
+ await actions.createList({ getters, state, commit, dispatch }, { backlog: true });
+
+ expect(dispatch).toHaveBeenCalledWith('highlightList', existingList.id);
+ expect(dispatch).toHaveBeenCalledTimes(1);
+ expect(commit).not.toHaveBeenCalled();
+ });
+});
+
+describe('fetchLabels', () => {
+ it('should commit mutation RECEIVE_LABELS_SUCCESS on success', async () => {
+ const queryResponse = {
+ data: {
+ group: {
+ labels: {
+ nodes: labels,
+ },
+ },
+ },
+ };
+ jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
+
+ await testAction({
+ action: actions.fetchLabels,
+ state: { boardType: 'group' },
+ expectedMutations: [{ type: types.RECEIVE_LABELS_SUCCESS, payload: labels }],
+ });
});
});
@@ -669,65 +724,27 @@ describe('moveIssue', () => {
describe('setAssignees', () => {
const node = { username: 'name' };
- const name = 'username';
const projectPath = 'h/h';
const refPath = `${projectPath}#3`;
const iid = '1';
describe('when succeeds', () => {
- beforeEach(() => {
- jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
- data: { issueSetAssignees: { issue: { assignees: { nodes: [{ ...node }] } } } },
- });
- });
-
- it('calls mutate with the correct values', async () => {
- await actions.setAssignees(
- { commit: () => {}, getters: { activeIssue: { iid, referencePath: refPath } } },
- [name],
- );
-
- expect(gqlClient.mutate).toHaveBeenCalledWith({
- mutation: updateAssignees,
- variables: { iid, assigneeUsernames: [name], projectPath },
- });
- });
-
it('calls the correct mutation with the correct values', (done) => {
testAction(
actions.setAssignees,
- {},
+ [node],
{ activeIssue: { iid, referencePath: refPath }, commit: () => {} },
[
- { type: types.SET_ASSIGNEE_LOADING, payload: true },
{
type: 'UPDATE_ISSUE_BY_ID',
payload: { prop: 'assignees', issueId: undefined, value: [node] },
},
- { type: types.SET_ASSIGNEE_LOADING, payload: false },
],
[],
done,
);
});
});
-
- describe('when fails', () => {
- beforeEach(() => {
- jest.spyOn(gqlClient, 'mutate').mockRejectedValue();
- });
-
- it('calls createFlash', async () => {
- await actions.setAssignees({
- commit: () => {},
- getters: { activeIssue: { iid, referencePath: refPath } },
- });
-
- expect(createFlash).toHaveBeenCalledWith({
- message: 'An error occurred while updating assignees.',
- });
- });
- });
});
describe('createNewIssue', () => {
@@ -1201,6 +1218,40 @@ describe('setSelectedProject', () => {
});
});
+describe('toggleBoardItemMultiSelection', () => {
+ const boardItem = mockIssue;
+
+ it('should commit mutation ADD_BOARD_ITEM_TO_SELECTION if item is not on selection state', () => {
+ testAction(
+ actions.toggleBoardItemMultiSelection,
+ boardItem,
+ { selectedBoardItems: [] },
+ [
+ {
+ type: types.ADD_BOARD_ITEM_TO_SELECTION,
+ payload: boardItem,
+ },
+ ],
+ [],
+ );
+ });
+
+ it('should commit mutation REMOVE_BOARD_ITEM_FROM_SELECTION if item is on selection state', () => {
+ testAction(
+ actions.toggleBoardItemMultiSelection,
+ boardItem,
+ { selectedBoardItems: [mockIssue] },
+ [
+ {
+ type: types.REMOVE_BOARD_ITEM_FROM_SELECTION,
+ payload: boardItem,
+ },
+ ],
+ [],
+ );
+ });
+});
+
describe('fetchBacklog', () => {
expectNotImplemented(actions.fetchBacklog);
});
diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js
index 44b41b5667d..d5a19bf613f 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -1,5 +1,5 @@
-import getters from '~/boards/stores/getters';
import { inactiveId } from '~/boards/constants';
+import getters from '~/boards/stores/getters';
import {
mockIssue,
mockIssue2,
@@ -62,6 +62,22 @@ describe('Boards - Getters', () => {
});
});
+ describe('groupPathByIssueId', () => {
+ it('returns group path for the active issue', () => {
+ const mockActiveIssue = {
+ referencePath: 'gitlab-org/gitlab-test#1',
+ };
+ expect(getters.groupPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual(
+ 'gitlab-org',
+ );
+ });
+
+ it('returns empty string as group path when active issue is an empty object', () => {
+ const mockActiveIssue = {};
+ expect(getters.groupPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual('');
+ });
+ });
+
describe('projectPathByIssueId', () => {
it('returns project path for the active issue', () => {
const mockActiveIssue = {
@@ -72,7 +88,7 @@ describe('Boards - Getters', () => {
);
});
- it('returns empty string as project when active issue is an empty object', () => {
+ it('returns empty string as project path when active issue is an empty object', () => {
const mockActiveIssue = {};
expect(getters.projectPathForActiveIssue({}, { activeIssue: mockActiveIssue })).toEqual('');
});
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index c5fe0e22c3c..9423f2ed583 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -1,7 +1,14 @@
-import mutations from '~/boards/stores/mutations';
import * as types from '~/boards/stores/mutation_types';
+import mutations from '~/boards/stores/mutations';
import defaultState from '~/boards/stores/state';
-import { mockLists, rawIssue, mockIssue, mockIssue2, mockGroupProjects } from '../mock_data';
+import {
+ mockLists,
+ rawIssue,
+ mockIssue,
+ mockIssue2,
+ mockGroupProjects,
+ labels,
+} from '../mock_data';
const expectNotImplemented = (action) => {
it('is not implemented', () => {
@@ -99,13 +106,11 @@ describe('Board Store Mutations', () => {
});
});
- describe('RECEIVE_LABELS_FAILURE', () => {
- it('sets error message', () => {
- mutations.RECEIVE_LABELS_FAILURE(state);
+ describe('RECEIVE_LABELS_SUCCESS', () => {
+ it('sets labels on state', () => {
+ mutations.RECEIVE_LABELS_SUCCESS(state, labels);
- expect(state.error).toEqual(
- 'An error occurred while fetching labels. Please reload the page.',
- );
+ expect(state.labels).toEqual(labels);
});
});
@@ -589,4 +594,27 @@ describe('Board Store Mutations', () => {
expect(state.selectedProject).toEqual(mockGroupProjects[0]);
});
});
+
+ describe('ADD_BOARD_ITEM_TO_SELECTION', () => {
+ it('Should add boardItem to selectedBoardItems state', () => {
+ expect(state.selectedBoardItems).toEqual([]);
+
+ mutations[types.ADD_BOARD_ITEM_TO_SELECTION](state, mockIssue);
+
+ expect(state.selectedBoardItems).toEqual([mockIssue]);
+ });
+ });
+
+ describe('REMOVE_BOARD_ITEM_FROM_SELECTION', () => {
+ it('Should remove boardItem to selectedBoardItems state', () => {
+ state = {
+ ...state,
+ selectedBoardItems: [mockIssue],
+ };
+
+ mutations[types.REMOVE_BOARD_ITEM_FROM_SELECTION](state, mockIssue);
+
+ expect(state.selectedBoardItems).toEqual([]);
+ });
+ });
});
diff --git a/spec/frontend/branches/divergence_graph_spec.js b/spec/frontend/branches/divergence_graph_spec.js
index adf39a2216a..be97a1724d3 100644
--- a/spec/frontend/branches/divergence_graph_spec.js
+++ b/spec/frontend/branches/divergence_graph_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import init from '~/branches/divergence_graph';
+import axios from '~/lib/utils/axios_utils';
describe('Divergence graph', () => {
let mock;
diff --git a/spec/frontend/captcha/captcha_modal_spec.js b/spec/frontend/captcha/captcha_modal_spec.js
new file mode 100644
index 00000000000..b8448f9ff0a
--- /dev/null
+++ b/spec/frontend/captcha/captcha_modal_spec.js
@@ -0,0 +1,171 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { stubComponent } from 'helpers/stub_component';
+import CaptchaModal from '~/captcha/captcha_modal.vue';
+import { initRecaptchaScript } from '~/captcha/init_recaptcha_script';
+
+jest.mock('~/captcha/init_recaptcha_script');
+
+describe('Captcha Modal', () => {
+ let wrapper;
+ let modal;
+ let grecaptcha;
+
+ const captchaSiteKey = 'abc123';
+
+ function createComponent({ props = {} } = {}) {
+ wrapper = shallowMount(CaptchaModal, {
+ propsData: {
+ captchaSiteKey,
+ ...props,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal),
+ },
+ });
+ }
+
+ beforeEach(() => {
+ grecaptcha = {
+ render: jest.fn(),
+ };
+
+ initRecaptchaScript.mockResolvedValue(grecaptcha);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGlModal = () => {
+ const glModal = wrapper.find(GlModal);
+
+ jest.spyOn(glModal.vm, 'show').mockImplementation(() => glModal.vm.$emit('shown'));
+ jest
+ .spyOn(glModal.vm, 'hide')
+ .mockImplementation(() => glModal.vm.$emit('hide', { trigger: '' }));
+
+ return glModal;
+ };
+
+ const showModal = () => {
+ wrapper.setProps({ needsCaptchaResponse: true });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ modal = findGlModal();
+ });
+
+ describe('rendering', () => {
+ it('renders', () => {
+ expect(modal.exists()).toBe(true);
+ });
+
+ it('assigns the modal a unique ID', () => {
+ const firstInstanceModalId = modal.props('modalId');
+ createComponent();
+ const secondInstanceModalId = findGlModal().props('modalId');
+ expect(firstInstanceModalId).not.toEqual(secondInstanceModalId);
+ });
+ });
+
+ describe('functionality', () => {
+ describe('when modal is shown', () => {
+ describe('when initRecaptchaScript promise resolves successfully', () => {
+ beforeEach(async () => {
+ showModal();
+
+ await nextTick();
+ });
+
+ it('shows modal', async () => {
+ expect(findGlModal().vm.show).toHaveBeenCalled();
+ });
+
+ it('renders window.grecaptcha', () => {
+ expect(grecaptcha.render).toHaveBeenCalledWith(wrapper.vm.$refs.captcha, {
+ sitekey: captchaSiteKey,
+ callback: expect.any(Function),
+ });
+ });
+
+ describe('then the user solves the captcha', () => {
+ const captchaResponse = 'a captcha response';
+
+ beforeEach(() => {
+ // simulate the grecaptcha library invoking the callback
+ const { callback } = grecaptcha.render.mock.calls[0][1];
+ callback(captchaResponse);
+ });
+
+ it('emits receivedCaptchaResponse exactly once with the captcha response', () => {
+ expect(wrapper.emitted('receivedCaptchaResponse')).toEqual([[captchaResponse]]);
+ });
+
+ it('hides modal with null trigger', async () => {
+ // Assert that hide is called with zero args, so that we don't trigger the logic
+ // for hiding the modal via cancel, esc, headerclose, etc, without a captcha response
+ expect(modal.vm.hide).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('then the user hides the modal without solving the captcha', () => {
+ // Even though we don't explicitly check for these trigger values, these are the
+ // currently supported ones which can be emitted.
+ // See https://bootstrap-vue.org/docs/components/modal#prevent-closing
+ describe.each`
+ trigger | expected
+ ${'cancel'} | ${[[null]]}
+ ${'esc'} | ${[[null]]}
+ ${'backdrop'} | ${[[null]]}
+ ${'headerclose'} | ${[[null]]}
+ `('using the $trigger trigger', ({ trigger, expected }) => {
+ beforeEach(() => {
+ const bvModalEvent = {
+ trigger,
+ };
+ modal.vm.$emit('hide', bvModalEvent);
+ });
+
+ it(`emits receivedCaptchaResponse with ${JSON.stringify(expected)}`, () => {
+ expect(wrapper.emitted('receivedCaptchaResponse')).toEqual(expected);
+ });
+ });
+ });
+ });
+
+ describe('when initRecaptchaScript promise rejects', () => {
+ const fakeError = {};
+
+ beforeEach(() => {
+ initRecaptchaScript.mockImplementation(() => Promise.reject(fakeError));
+
+ jest.spyOn(console, 'error').mockImplementation();
+
+ showModal();
+ });
+
+ it('emits receivedCaptchaResponse exactly once with null', () => {
+ expect(wrapper.emitted('receivedCaptchaResponse')).toEqual([[null]]);
+ });
+
+ it('hides modal with null trigger', async () => {
+ // Assert that hide is called with zero args, so that we don't trigger the logic
+ // for hiding the modal via cancel, esc, headerclose, etc, without a captcha response
+ expect(modal.vm.hide).toHaveBeenCalledWith();
+ });
+
+ it('calls console.error with a message and the exception', () => {
+ // eslint-disable-next-line no-console
+ expect(console.error).toHaveBeenCalledWith(
+ expect.stringMatching(/exception.*captcha/),
+ fakeError,
+ );
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/captcha/init_recaptcha_script_spec.js b/spec/frontend/captcha/init_recaptcha_script_spec.js
new file mode 100644
index 00000000000..af07c9e474e
--- /dev/null
+++ b/spec/frontend/captcha/init_recaptcha_script_spec.js
@@ -0,0 +1,59 @@
+import {
+ RECAPTCHA_API_URL_PREFIX,
+ RECAPTCHA_ONLOAD_CALLBACK_NAME,
+ clearMemoizeCache,
+ initRecaptchaScript,
+} from '~/captcha/init_recaptcha_script';
+
+describe('initRecaptchaScript', () => {
+ afterEach(() => {
+ document.head.innerHTML = '';
+ clearMemoizeCache();
+ });
+
+ const getScriptOnload = () => window[RECAPTCHA_ONLOAD_CALLBACK_NAME];
+ const triggerScriptOnload = () => window[RECAPTCHA_ONLOAD_CALLBACK_NAME]();
+
+ describe('when called', () => {
+ let result;
+
+ beforeEach(() => {
+ result = initRecaptchaScript();
+ });
+
+ it('adds script to head', () => {
+ expect(document.head).toMatchInlineSnapshot(`
+ <head>
+ <script
+ class="js-recaptcha-script"
+ src="${RECAPTCHA_API_URL_PREFIX}?onload=${RECAPTCHA_ONLOAD_CALLBACK_NAME}&render=explicit"
+ />
+ </head>
+ `);
+ });
+
+ it('is memoized', () => {
+ expect(initRecaptchaScript()).toBe(result);
+ expect(document.head.querySelectorAll('script').length).toBe(1);
+ });
+
+ describe('when onload is triggered', () => {
+ beforeEach(() => {
+ window.grecaptcha = 'fake grecaptcha';
+ triggerScriptOnload();
+ });
+
+ afterEach(() => {
+ window.grecaptcha = undefined;
+ });
+
+ it('resolves promise with window.grecaptcha as argument', async () => {
+ await expect(result).resolves.toBe(window.grecaptcha);
+ });
+
+ it('sets window[RECAPTCHA_ONLOAD_CALLBACK_NAME] to undefined', async () => {
+ expect(getScriptOnload()).toBeUndefined();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/ci_lint/components/ci_lint_spec.js b/spec/frontend/ci_lint/components/ci_lint_spec.js
index 1c99fdb3505..8a065436da0 100644
--- a/spec/frontend/ci_lint/components/ci_lint_spec.js
+++ b/spec/frontend/ci_lint/components/ci_lint_spec.js
@@ -1,10 +1,10 @@
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
import CiLint from '~/ci_lint/components/ci_lint.vue';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
import lintCIMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
import { mockLintDataValid } from '../mock_data';
describe('CI Lint', () => {
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 30aa634fc81..41af257ad89 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,9 +1,9 @@
-import { mount } from '@vue/test-utils';
import { GlTable, GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+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';
-import TriggersList from '~/ci_settings_pipeline_triggers/components/triggers_list.vue';
import { triggers } from '../mock_data';
describe('TriggersList', () => {
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 faa88394447..75c6e8e4540 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,6 +1,6 @@
-import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlDropdownItem, GlIcon } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
const localVue = createLocalVue();
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 b2e51029a06..991dc8592e9 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,8 +1,8 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
-import { AWS_ACCESS_KEY_ID } from '~/ci_variable_list/constants';
+import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
import CiVariableModal from '~/ci_variable_list/components/ci_variable_modal.vue';
+import { AWS_ACCESS_KEY_ID } from '~/ci_variable_list/constants';
import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
import ModalStub from '../stubs';
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js
index 5d37f059161..b43153d3d7c 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import CiVariablePopover from '~/ci_variable_list/components/ci_variable_popover.vue';
import mockData from '../services/mock_data';
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 12449fc7615..03f90f72d87 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,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import CiVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
import createStore from '~/ci_variable_list/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 fbc34528d4d..ade2d65b857 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,6 +1,6 @@
-import Vuex from 'vuex';
-import { createLocalVue, mount } from '@vue/test-utils';
import { GlTable } from '@gitlab/ui';
+import { createLocalVue, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
import CiVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
diff --git a/spec/frontend/ci_variable_list/store/actions_spec.js b/spec/frontend/ci_variable_list/store/actions_spec.js
index 075e5829305..be3640936dc 100644
--- a/spec/frontend/ci_variable_list/store/actions_spec.js
+++ b/spec/frontend/ci_variable_list/store/actions_spec.js
@@ -1,13 +1,13 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import getInitialState from '~/ci_variable_list/store/state';
import * as actions from '~/ci_variable_list/store/actions';
import * as types from '~/ci_variable_list/store/mutation_types';
-import mockData from '../services/mock_data';
+import getInitialState from '~/ci_variable_list/store/state';
import { prepareDataForDisplay, prepareEnvironments } from '~/ci_variable_list/store/utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import mockData from '../services/mock_data';
jest.mock('~/api.js');
jest.mock('~/flash.js');
diff --git a/spec/frontend/ci_variable_list/store/mutations_spec.js b/spec/frontend/ci_variable_list/store/mutations_spec.js
index a333fb7d8f9..ae750ff426d 100644
--- a/spec/frontend/ci_variable_list/store/mutations_spec.js
+++ b/spec/frontend/ci_variable_list/store/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/ci_variable_list/store/state';
-import mutations from '~/ci_variable_list/store/mutations';
import * as types from '~/ci_variable_list/store/mutation_types';
+import mutations from '~/ci_variable_list/store/mutations';
+import state from '~/ci_variable_list/store/state';
describe('CI variable list mutations', () => {
let stateCopy;
diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
index ee4ec4636ea..6047b404197 100644
--- a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
+++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
@@ -60,8 +60,8 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
>
<svg
aria-hidden="true"
- class="gl-icon s16 gl-new-dropdown-item-check-icon"
- data-testid="mobile-issue-close-icon"
+ class="gl-icon s16 gl-new-dropdown-item-check-icon gl-mt-3 gl-align-self-start"
+ data-testid="dropdown-item-checkbox"
>
<use
href="#mobile-issue-close"
@@ -115,8 +115,8 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
>
<svg
aria-hidden="true"
- class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden"
- data-testid="mobile-issue-close-icon"
+ class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden gl-mt-3 gl-align-self-start"
+ data-testid="dropdown-item-checkbox"
>
<use
href="#mobile-issue-close"
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index 49a299cfb3c..eff3493d7bd 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -1,10 +1,10 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
-import eventHub from '~/clusters/event_hub';
-import { APPLICATION_STATUS, ELASTIC_STACK } from '~/clusters/constants';
+import { shallowMount } from '@vue/test-utils';
import ApplicationRow from '~/clusters/components/application_row.vue';
import UninstallApplicationConfirmationModal from '~/clusters/components/uninstall_application_confirmation_modal.vue';
import UpdateApplicationConfirmationModal from '~/clusters/components/update_application_confirmation_modal.vue';
+import { APPLICATION_STATUS, ELASTIC_STACK } from '~/clusters/constants';
+import eventHub from '~/clusters/event_hub';
import { DEFAULT_APPLICATION_STATE } from '../services/mock_data';
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index cf89246c1a5..db5915cb1eb 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -1,13 +1,13 @@
import { shallowMount, mount } from '@vue/test-utils';
-import Applications from '~/clusters/components/applications.vue';
-import { CLUSTER_TYPE, PROVIDER_TYPE } from '~/clusters/constants';
-import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
-import eventHub from '~/clusters/event_hub';
import ApplicationRow from '~/clusters/components/application_row.vue';
-import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
+import Applications from '~/clusters/components/applications.vue';
import CrossplaneProviderStack from '~/clusters/components/crossplane_provider_stack.vue';
-import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
import FluentdOutputSettings from '~/clusters/components/fluentd_output_settings.vue';
+import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
+import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
+import { CLUSTER_TYPE, PROVIDER_TYPE } from '~/clusters/constants';
+import eventHub from '~/clusters/event_hub';
+import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
describe('Applications', () => {
let wrapper;
@@ -16,7 +16,7 @@ describe('Applications', () => {
gon.features = gon.features || {};
});
- const createApp = ({ applications, type, propsData } = {}, isShallow) => {
+ const createComponent = ({ applications, type, propsData } = {}, isShallow) => {
const mountMethod = isShallow ? shallowMount : mount;
wrapper = mountMethod(Applications, {
@@ -29,7 +29,7 @@ describe('Applications', () => {
});
};
- const createShallowApp = (options) => createApp(options, true);
+ const createShallowComponent = (options) => createComponent(options, true);
const findByTestId = (id) => wrapper.find(`[data-testid="${id}"]`);
afterEach(() => {
wrapper.destroy();
@@ -37,7 +37,7 @@ describe('Applications', () => {
describe('Project cluster applications', () => {
beforeEach(() => {
- createApp({ type: CLUSTER_TYPE.PROJECT });
+ createComponent({ type: CLUSTER_TYPE.PROJECT });
});
it('renders a row for Ingress', () => {
@@ -82,7 +82,7 @@ describe('Applications', () => {
describe('Group cluster applications', () => {
beforeEach(() => {
- createApp({ type: CLUSTER_TYPE.GROUP });
+ createComponent({ type: CLUSTER_TYPE.GROUP });
});
it('renders a row for Ingress', () => {
@@ -128,7 +128,7 @@ describe('Applications', () => {
describe('Instance cluster applications', () => {
beforeEach(() => {
- createApp({ type: CLUSTER_TYPE.INSTANCE });
+ createComponent({ type: CLUSTER_TYPE.INSTANCE });
});
it('renders a row for Ingress', () => {
@@ -174,14 +174,14 @@ describe('Applications', () => {
describe('Helm application', () => {
it('does not render a row for Helm Tiller', () => {
- createApp();
+ createComponent();
expect(wrapper.find('.js-cluster-application-row-helm').exists()).toBe(false);
});
});
describe('Ingress application', () => {
it('shows the correct warning message', () => {
- createApp();
+ createComponent();
expect(findByTestId('ingressCostWarning').element).toMatchSnapshot();
});
@@ -195,7 +195,7 @@ describe('Applications', () => {
},
};
- beforeEach(() => createShallowApp(propsData));
+ beforeEach(() => createShallowComponent(propsData));
it('renders IngressModsecuritySettings', () => {
const modsecuritySettings = wrapper.find(IngressModsecuritySettings);
@@ -206,7 +206,7 @@ describe('Applications', () => {
describe('when installed', () => {
describe('with ip address', () => {
it('renders ip address with a clipboard button', () => {
- createApp({
+ createComponent({
applications: {
ingress: {
title: 'Ingress',
@@ -225,7 +225,7 @@ describe('Applications', () => {
describe('with hostname', () => {
it('renders hostname with a clipboard button', () => {
- createApp({
+ createComponent({
applications: {
ingress: {
title: 'Ingress',
@@ -255,7 +255,7 @@ describe('Applications', () => {
describe('without ip address', () => {
it('renders an input text with a loading icon and an alert text', () => {
- createApp({
+ createComponent({
applications: {
ingress: {
title: 'Ingress',
@@ -272,7 +272,7 @@ describe('Applications', () => {
describe('before installing', () => {
it('does not render the IP address', () => {
- createApp();
+ createComponent();
expect(wrapper.text()).not.toContain('Ingress IP Address');
expect(wrapper.find('.js-endpoint').exists()).toBe(false);
@@ -282,13 +282,13 @@ describe('Applications', () => {
describe('Cert-Manager application', () => {
it('shows the correct description', () => {
- createApp();
+ createComponent();
expect(findByTestId('certManagerDescription').element).toMatchSnapshot();
});
describe('when not installed', () => {
it('renders email & allows editing', () => {
- createApp({
+ createComponent({
applications: {
cert_manager: {
title: 'Cert-Manager',
@@ -305,7 +305,7 @@ describe('Applications', () => {
describe('when installed', () => {
it('renders email in readonly', () => {
- createApp({
+ createComponent({
applications: {
cert_manager: {
title: 'Cert-Manager',
@@ -324,7 +324,7 @@ describe('Applications', () => {
describe('Jupyter application', () => {
describe('with ingress installed with ip & jupyter installable', () => {
it('renders hostname active input', () => {
- createApp({
+ createComponent({
applications: {
ingress: {
title: 'Ingress',
@@ -342,7 +342,7 @@ describe('Applications', () => {
describe('with ingress installed without external ip', () => {
it('does not render hostname input', () => {
- createApp({
+ createComponent({
applications: {
ingress: { title: 'Ingress', status: 'installed' },
},
@@ -356,7 +356,7 @@ describe('Applications', () => {
describe('with ingress & jupyter installed', () => {
it('renders readonly input', () => {
- createApp({
+ createComponent({
applications: {
ingress: {
title: 'Ingress',
@@ -375,7 +375,7 @@ describe('Applications', () => {
describe('without ingress installed', () => {
beforeEach(() => {
- createApp();
+ createComponent();
});
it('does not render input', () => {
@@ -388,7 +388,7 @@ describe('Applications', () => {
describe('Prometheus application', () => {
it('shows the correct description', () => {
- createApp();
+ createComponent();
expect(findByTestId('prometheusDescription').element).toMatchSnapshot();
});
});
@@ -414,14 +414,14 @@ describe('Applications', () => {
let knativeDomainEditor;
beforeEach(() => {
- createShallowApp(propsData);
+ createShallowComponent(propsData);
jest.spyOn(eventHub, '$emit');
knativeDomainEditor = wrapper.find(KnativeDomainEditor);
});
it('shows the correct description', async () => {
- createApp();
+ createComponent();
wrapper.setProps({
providerType: PROVIDER_TYPE.GCP,
preInstalledKnative: true,
@@ -487,7 +487,7 @@ describe('Applications', () => {
},
};
- beforeEach(() => createShallowApp(propsData));
+ beforeEach(() => createShallowComponent(propsData));
it('renders the correct Component', () => {
const crossplane = wrapper.find(CrossplaneProviderStack);
@@ -495,7 +495,7 @@ describe('Applications', () => {
});
it('shows the correct description', () => {
- createApp();
+ createComponent();
expect(findByTestId('crossplaneDescription').element).toMatchSnapshot();
});
});
@@ -503,7 +503,7 @@ describe('Applications', () => {
describe('Elastic Stack application', () => {
describe('with elastic stack installable', () => {
it('renders the install button enabled', () => {
- createApp();
+ createComponent();
expect(
wrapper
@@ -517,7 +517,7 @@ describe('Applications', () => {
describe('elastic stack installed', () => {
it('renders uninstall button', () => {
- createApp({
+ createComponent({
applications: {
elastic_stack: { title: 'Elastic Stack', status: 'installed' },
},
@@ -535,7 +535,7 @@ describe('Applications', () => {
});
describe('Fluentd application', () => {
- beforeEach(() => createShallowApp());
+ beforeEach(() => createShallowComponent());
it('renders the correct Component', () => {
expect(wrapper.find(FluentdOutputSettings).exists()).toBe(true);
@@ -544,7 +544,7 @@ describe('Applications', () => {
describe('Cilium application', () => {
it('shows the correct description', () => {
- createApp({ propsData: { ciliumHelpPath: 'cilium-help-path' } });
+ createComponent({ propsData: { ciliumHelpPath: 'cilium-help-path' } });
expect(findByTestId('ciliumDescription').element).toMatchSnapshot();
});
});
diff --git a/spec/frontend/clusters/components/fluentd_output_settings_spec.js b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
index cd996ae915b..2c6e5bbd46a 100644
--- a/spec/frontend/clusters/components/fluentd_output_settings_spec.js
+++ b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlDropdown, GlFormCheckbox } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import FluentdOutputSettings from '~/clusters/components/fluentd_output_settings.vue';
import { APPLICATION_STATUS, FLUENTD } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
diff --git a/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js b/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js
index 1f07a0b7908..fd6d9854868 100644
--- a/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js
+++ b/spec/frontend/clusters/components/ingress_modsecurity_settings_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlToggle, GlDropdown } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import IngressModsecuritySettings from '~/clusters/components/ingress_modsecurity_settings.vue';
import { APPLICATION_STATUS, INGRESS } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
diff --git a/spec/frontend/clusters/components/knative_domain_editor_spec.js b/spec/frontend/clusters/components/knative_domain_editor_spec.js
index b7f76211fd6..207eb071171 100644
--- a/spec/frontend/clusters/components/knative_domain_editor_spec.js
+++ b/spec/frontend/clusters/components/knative_domain_editor_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
import { APPLICATION_STATUS } from '~/clusters/constants';
diff --git a/spec/frontend/clusters/components/new_cluster_spec.js b/spec/frontend/clusters/components/new_cluster_spec.js
index bb4898f98ba..e4bca5eaaa5 100644
--- a/spec/frontend/clusters/components/new_cluster_spec.js
+++ b/spec/frontend/clusters/components/new_cluster_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import NewCluster from '~/clusters/components/new_cluster.vue';
import createClusterStore from '~/clusters/stores/new_cluster';
diff --git a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
index f448948843a..e2726b93ea5 100644
--- a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
+++ b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
@@ -1,7 +1,7 @@
-import { mount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
-import SplitButton from '~/vue_shared/components/split_button.vue';
+import { mount } from '@vue/test-utils';
import RemoveClusterConfirmation from '~/clusters/components/remove_cluster_confirmation.vue';
+import SplitButton from '~/vue_shared/components/split_button.vue';
describe('Remove cluster confirmation modal', () => {
let wrapper;
diff --git a/spec/frontend/clusters/components/uninstall_application_button_spec.js b/spec/frontend/clusters/components/uninstall_application_button_spec.js
index c106292965e..2596820e5ac 100644
--- a/spec/frontend/clusters/components/uninstall_application_button_spec.js
+++ b/spec/frontend/clusters/components/uninstall_application_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UninstallApplicationButton from '~/clusters/components/uninstall_application_button.vue';
import { APPLICATION_STATUS } from '~/clusters/constants';
diff --git a/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js b/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js
index c07f6851826..74ae4ecc486 100644
--- a/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js
+++ b/spec/frontend/clusters/components/uninstall_application_confirmation_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UninstallApplicationConfirmationModal from '~/clusters/components/uninstall_application_confirmation_modal.vue';
import { INGRESS } from '~/clusters/constants';
diff --git a/spec/frontend/clusters/components/update_application_confirmation_modal_spec.js b/spec/frontend/clusters/components/update_application_confirmation_modal_spec.js
index dd3aaf6f946..e933f17a980 100644
--- a/spec/frontend/clusters/components/update_application_confirmation_modal_spec.js
+++ b/spec/frontend/clusters/components/update_application_confirmation_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UpdateApplicationConfirmationModal from '~/clusters/components/update_application_confirmation_modal.vue';
import { ELASTIC_STACK } from '~/clusters/constants';
diff --git a/spec/frontend/clusters/forms/components/integration_form_spec.js b/spec/frontend/clusters/forms/components/integration_form_spec.js
index 3a3700eb0b7..0323245244d 100644
--- a/spec/frontend/clusters/forms/components/integration_form_spec.js
+++ b/spec/frontend/clusters/forms/components/integration_form_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlToggle, GlButton } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import IntegrationForm from '~/clusters/forms/components/integration_form.vue';
import { createStore } from '~/clusters/forms/stores/index';
diff --git a/spec/frontend/clusters/services/application_state_machine_spec.js b/spec/frontend/clusters/services/application_state_machine_spec.js
index a3850a64f3b..55230625ba4 100644
--- a/spec/frontend/clusters/services/application_state_machine_spec.js
+++ b/spec/frontend/clusters/services/application_state_machine_spec.js
@@ -1,10 +1,10 @@
-import transitionApplicationState from '~/clusters/services/application_state_machine';
import {
APPLICATION_STATUS,
UNINSTALL_EVENT,
UPDATE_EVENT,
INSTALL_EVENT,
} from '~/clusters/constants';
+import transitionApplicationState from '~/clusters/services/application_state_machine';
const {
NO_STATUS,
diff --git a/spec/frontend/clusters/services/crossplane_provider_stack_spec.js b/spec/frontend/clusters/services/crossplane_provider_stack_spec.js
index 3e5f8de8e7b..f95b175ca64 100644
--- a/spec/frontend/clusters/services/crossplane_provider_stack_spec.js
+++ b/spec/frontend/clusters/services/crossplane_provider_stack_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import CrossplaneProviderStack from '~/clusters/components/crossplane_provider_stack.vue';
describe('CrossplaneProviderStack component', () => {
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
index df10d9af273..c80949531c8 100644
--- a/spec/frontend/clusters/stores/clusters_store_spec.js
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -1,5 +1,5 @@
-import ClustersStore from '~/clusters/stores/clusters_store';
import { APPLICATION_INSTALLED_STATUSES, APPLICATION_STATUS, RUNNER } from '~/clusters/constants';
+import ClustersStore from '~/clusters/stores/clusters_store';
import { CLUSTERS_MOCK_DATA } from '../services/mock_data';
describe('Clusters Store', () => {
diff --git a/spec/frontend/clusters_list/components/ancestor_notice_spec.js b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
index 79f917d4601..c7ee2a00f5b 100644
--- a/spec/frontend/clusters_list/components/ancestor_notice_spec.js
+++ b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import AncestorNotice from '~/clusters_list/components/ancestor_notice.vue';
import ClusterStore from '~/clusters_list/store';
diff --git a/spec/frontend/clusters_list/components/clusters_spec.js b/spec/frontend/clusters_list/components/clusters_spec.js
index d61f79071d5..f398d7a0965 100644
--- a/spec/frontend/clusters_list/components/clusters_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_spec.js
@@ -1,15 +1,15 @@
-import MockAdapter from 'axios-mock-adapter';
-import { mount } from '@vue/test-utils';
import {
GlLoadingIcon,
GlPagination,
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlTable,
} from '@gitlab/ui';
-import * as Sentry from '~/sentry/wrapper';
-import axios from '~/lib/utils/axios_utils';
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
import Clusters from '~/clusters_list/components/clusters.vue';
import ClusterStore from '~/clusters_list/store';
+import axios from '~/lib/utils/axios_utils';
+import * as Sentry from '~/sentry/wrapper';
import { apiData } from '../mock_data';
describe('Clusters', () => {
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 fa566c2dc57..18d27f3fd80 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,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlPopover } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import NodeErrorHelpText from '~/clusters_list/components/node_error_help_text.vue';
describe('NodeErrorHelpText', () => {
diff --git a/spec/frontend/clusters_list/store/actions_spec.js b/spec/frontend/clusters_list/store/actions_spec.js
index 6214cb50e13..00b998166aa 100644
--- a/spec/frontend/clusters_list/store/actions_spec.js
+++ b/spec/frontend/clusters_list/store/actions_spec.js
@@ -1,14 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import * as Sentry from '~/sentry/wrapper';
-import Poll from '~/lib/utils/poll';
+import { MAX_REQUESTS } from '~/clusters_list/constants';
+import * as actions from '~/clusters_list/store/actions';
+import * as types from '~/clusters_list/store/mutation_types';
import { deprecatedCreateFlash as flashError } from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
+import * as Sentry from '~/sentry/wrapper';
import { apiData } from '../mock_data';
-import { MAX_REQUESTS } from '~/clusters_list/constants';
-import * as types from '~/clusters_list/store/mutation_types';
-import * as actions from '~/clusters_list/store/actions';
jest.mock('~/flash.js');
diff --git a/spec/frontend/clusters_list/store/mutations_spec.js b/spec/frontend/clusters_list/store/mutations_spec.js
index df0dfe587b6..c0fe634a703 100644
--- a/spec/frontend/clusters_list/store/mutations_spec.js
+++ b/spec/frontend/clusters_list/store/mutations_spec.js
@@ -1,7 +1,7 @@
import * as types from '~/clusters_list/store/mutation_types';
-import { apiData } from '../mock_data';
-import getInitialState from '~/clusters_list/store/state';
import mutations from '~/clusters_list/store/mutations';
+import getInitialState from '~/clusters_list/store/state';
+import { apiData } from '../mock_data';
describe('Admin statistics panel mutations', () => {
let state;
diff --git a/spec/frontend/code_navigation/components/app_spec.js b/spec/frontend/code_navigation/components/app_spec.js
index 6dfc81dcc40..ea389fa35c0 100644
--- a/spec/frontend/code_navigation/components/app_spec.js
+++ b/spec/frontend/code_navigation/components/app_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import createState from '~/code_navigation/store/state';
+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();
diff --git a/spec/frontend/code_navigation/components/popover_spec.js b/spec/frontend/code_navigation/components/popover_spec.js
index 7b323cfab72..c038c04a0f8 100644
--- a/spec/frontend/code_navigation/components/popover_spec.js
+++ b/spec/frontend/code_navigation/components/popover_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import Popover from '~/code_navigation/components/popover.vue';
import DocLine from '~/code_navigation/components/doc_line.vue';
+import Popover from '~/code_navigation/components/popover.vue';
const DEFINITION_PATH_PREFIX = 'http://gitlab.com';
diff --git a/spec/frontend/code_navigation/store/actions_spec.js b/spec/frontend/code_navigation/store/actions_spec.js
index 39cf4acd5ce..73f935deeca 100644
--- a/spec/frontend/code_navigation/store/actions_spec.js
+++ b/spec/frontend/code_navigation/store/actions_spec.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import actions from '~/code_navigation/store/actions';
-import axios from '~/lib/utils/axios_utils';
import { setCurrentHoverElement, addInteractionClass } from '~/code_navigation/utils';
+import axios from '~/lib/utils/axios_utils';
jest.mock('~/code_navigation/utils');
diff --git a/spec/frontend/collapsed_sidebar_todo_spec.js b/spec/frontend/collapsed_sidebar_todo_spec.js
index cc89a3c68f0..ef53cc9e103 100644
--- a/spec/frontend/collapsed_sidebar_todo_spec.js
+++ b/spec/frontend/collapsed_sidebar_todo_spec.js
@@ -1,10 +1,13 @@
/* eslint-disable no-new */
-import { clone } from 'lodash';
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
+import { clone } from 'lodash';
import waitForPromises from 'helpers/wait_for_promises';
+import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import Sidebar from '~/right_sidebar';
+import { fixTitle } from '~/tooltips';
+
+jest.mock('~/tooltips');
describe('Issuable right sidebar collapsed todo toggle', () => {
const fixtureName = 'issues/open-issue.html';
@@ -96,11 +99,10 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setImmediate(() => {
- expect(
- document
- .querySelector('.js-issuable-todo.sidebar-collapsed-icon')
- .getAttribute('data-original-title'),
- ).toBe('Mark as done');
+ const el = document.querySelector('.js-issuable-todo.sidebar-collapsed-icon');
+
+ expect(el.getAttribute('title')).toBe('Mark as done');
+ expect(fixTitle).toHaveBeenCalledWith(el);
done();
});
diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js
index 6e4368b5de8..a56f761269a 100644
--- a/spec/frontend/commit/commit_pipeline_status_component_spec.js
+++ b/spec/frontend/commit/commit_pipeline_status_component_spec.js
@@ -1,11 +1,11 @@
-import Visibility from 'visibilityjs';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import Visibility from 'visibilityjs';
import { getJSONFixture } from 'helpers/fixtures';
-import Poll from '~/lib/utils/poll';
import { deprecatedCreateFlash as flash } from '~/flash';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import Poll from '~/lib/utils/poll';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
jest.mock('~/lib/utils/poll');
jest.mock('visibilityjs');
@@ -141,8 +141,8 @@ describe('Commit pipeline status component', () => {
expect(findLink().attributes('href')).toEqual(mockCiStatus.details_path);
});
- it('renders CI icon', () => {
- expect(findCiIcon().attributes('title')).toEqual('Pipeline: pending');
+ it('renders CI icon with the correct title and status', () => {
+ expect(findCiIcon().attributes('title')).toEqual('Pipeline: passed');
expect(findCiIcon().props('status')).toEqual(mockCiStatus);
});
});
diff --git a/spec/frontend/commit/pipelines/pipelines_spec.js b/spec/frontend/commit/pipelines/pipelines_spec.js
index 15b1f224699..f8bdd00f5da 100644
--- a/spec/frontend/commit/pipelines/pipelines_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_spec.js
@@ -1,9 +1,9 @@
-import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
import Api from '~/api';
import pipelinesTable from '~/commit/pipelines/pipelines_table.vue';
+import axios from '~/lib/utils/axios_utils';
describe('Pipelines table in Commits and Merge requests', () => {
const jsonFixtureName = 'pipelines/pipelines.json';
diff --git a/spec/frontend/commits_spec.js b/spec/frontend/commits_spec.js
index e1b947ddd0d..954025091cf 100644
--- a/spec/frontend/commits_spec.js
+++ b/spec/frontend/commits_spec.js
@@ -1,8 +1,8 @@
+import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import 'vendor/jquery.endless-scroll';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import CommitsList from '~/commits';
+import axios from '~/lib/utils/axios_utils';
import Pager from '~/pager';
describe('Commits List', () => {
diff --git a/spec/frontend/commons/nav/user_merge_requests_spec.js b/spec/frontend/commons/nav/user_merge_requests_spec.js
index c441668f7c7..8f974051232 100644
--- a/spec/frontend/commons/nav/user_merge_requests_spec.js
+++ b/spec/frontend/commons/nav/user_merge_requests_spec.js
@@ -1,9 +1,9 @@
+import * as UserApi from '~/api/user_api';
import {
openUserCountsBroadcast,
closeUserCountsBroadcast,
refreshUserMergeRequestCounts,
} from '~/commons/nav/user_merge_requests';
-import * as UserApi from '~/api/user_api';
jest.mock('~/api');
diff --git a/spec/frontend/confidential_merge_request/components/dropdown_spec.js b/spec/frontend/confidential_merge_request/components/dropdown_spec.js
index 401948e24e4..14a0b98a0d5 100644
--- a/spec/frontend/confidential_merge_request/components/dropdown_spec.js
+++ b/spec/frontend/confidential_merge_request/components/dropdown_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import Dropdown from '~/confidential_merge_request/components/dropdown.vue';
let vm;
diff --git a/spec/frontend/confidential_merge_request/components/project_form_group_spec.js b/spec/frontend/confidential_merge_request/components/project_form_group_spec.js
index 975701ebd96..67f6d360f52 100644
--- a/spec/frontend/confidential_merge_request/components/project_form_group_spec.js
+++ b/spec/frontend/confidential_merge_request/components/project_form_group_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import ProjectFormGroup from '~/confidential_merge_request/components/project_form_group.vue';
+import axios from '~/lib/utils/axios_utils';
const mockData = [
{
diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js
index 24816e4e8ac..de55be4aa72 100644
--- a/spec/frontend/contributors/component/contributors_spec.js
+++ b/spec/frontend/contributors/component/contributors_spec.js
@@ -1,9 +1,9 @@
-import Vue from 'vue';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
+import ContributorsCharts from '~/contributors/components/contributors.vue';
import { createStore } from '~/contributors/stores';
import axios from '~/lib/utils/axios_utils';
-import ContributorsCharts from '~/contributors/components/contributors.vue';
let wrapper;
let mock;
diff --git a/spec/frontend/contributors/store/actions_spec.js b/spec/frontend/contributors/store/actions_spec.js
index 7d2f93c4940..82b6492b779 100644
--- a/spec/frontend/contributors/store/actions_spec.js
+++ b/spec/frontend/contributors/store/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as flashError } from '~/flash';
import * as actions from '~/contributors/stores/actions';
import * as types from '~/contributors/stores/mutation_types';
+import { deprecatedCreateFlash as flashError } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
jest.mock('~/flash.js');
diff --git a/spec/frontend/contributors/store/mutations_spec.js b/spec/frontend/contributors/store/mutations_spec.js
index e9e756d4a65..e8da1a48c5c 100644
--- a/spec/frontend/contributors/store/mutations_spec.js
+++ b/spec/frontend/contributors/store/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/contributors/stores/state';
-import mutations from '~/contributors/stores/mutations';
import * as types from '~/contributors/stores/mutation_types';
+import mutations from '~/contributors/stores/mutations';
+import state from '~/contributors/stores/state';
describe('Contributors mutations', () => {
let stateCopy;
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 90c0e2d7827..0c6095e601f 100644
--- a/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
+++ b/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
@@ -1,7 +1,7 @@
+import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import $ from 'jquery';
-import { GlIcon } from '@gitlab/ui';
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';
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 e0913fe2e88..95810e882a1 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,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+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';
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 a4835f8c1c1..53a6f12c381 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,7 +1,7 @@
+import { GlFormCheckbox } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
import Vue from 'vue';
-import { GlFormCheckbox } from '@gitlab/ui';
+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';
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 d2d6db31d1b..d866ffd4efb 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,6 +1,6 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+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';
diff --git a/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js b/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js
index 2853d18e2cb..7b93b6d0a09 100644
--- a/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/services/aws_services_facade_spec.js
@@ -1,5 +1,5 @@
-import AWS from 'aws-sdk/global';
import EC2 from 'aws-sdk/clients/ec2';
+import AWS from 'aws-sdk/global';
import {
setAWSConfig,
fetchRoles,
diff --git a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
index 35348d3a03b..f10cf4b4140 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -1,7 +1,7 @@
-import testAction from 'helpers/vuex_action_helper';
-import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import MockAdapter from 'axios-mock-adapter';
-import createState from '~/create_cluster/eks_cluster/store/state';
+import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
+import testAction from 'helpers/vuex_action_helper';
+import { DEFAULT_REGION } from '~/create_cluster/eks_cluster/constants';
import * as actions from '~/create_cluster/eks_cluster/store/actions';
import {
SET_CLUSTER_NAME,
@@ -23,9 +23,9 @@ import {
REQUEST_CREATE_CLUSTER,
CREATE_CLUSTER_ERROR,
} from '~/create_cluster/eks_cluster/store/mutation_types';
-import { DEFAULT_REGION } from '~/create_cluster/eks_cluster/constants';
-import axios from '~/lib/utils/axios_utils';
+import createState from '~/create_cluster/eks_cluster/store/state';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
jest.mock('~/flash');
diff --git a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
index 633cea595d1..54d66e79be7 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
@@ -17,8 +17,8 @@ import {
REQUEST_CREATE_CLUSTER,
CREATE_CLUSTER_ERROR,
} from '~/create_cluster/eks_cluster/store/mutation_types';
-import createState from '~/create_cluster/eks_cluster/store/state';
import mutations from '~/create_cluster/eks_cluster/store/mutations';
+import createState from '~/create_cluster/eks_cluster/store/state';
describe('Create EKS cluster store mutations', () => {
let clusterName;
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 c09eaa63d4d..8f4903dd91b 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,10 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { selectedMachineTypeMock, gapiMachineTypesResponseMock } from '../mock_data';
+import GkeMachineTypeDropdown from '~/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue';
import createState from '~/create_cluster/gke_cluster/store/state';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-import GkeMachineTypeDropdown from '~/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue';
+import { selectedMachineTypeMock, gapiMachineTypesResponseMock } from '../mock_data';
const componentConfig = {
fieldId: 'cluster_provider_gcp_attributes_gcp_machine_type',
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 ce24d186511..23a56766037 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,7 +1,7 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import GkeNetworkDropdown from '~/create_cluster/gke_cluster/components/gke_network_dropdown.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();
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 eb58108bf3c..b191b107609 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,10 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import createState from '~/create_cluster/gke_cluster/store/state';
-import { selectedProjectMock, gapiProjectsResponseMock } from '../mock_data';
import GkeProjectIdDropdown from '~/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue';
+import createState from '~/create_cluster/gke_cluster/store/state';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
+import { selectedProjectMock, gapiProjectsResponseMock } from '../mock_data';
const componentConfig = {
docsUrl: 'https://console.cloud.google.com/home/dashboard',
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 9401ba83ef4..014ed6013bd 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,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import GkeSubmitButton from '~/create_cluster/gke_cluster/components/gke_submit_button.vue';
const localVue = createLocalVue();
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 35e43d5b033..cfa8a678a9b 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,7 +1,7 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import GkeSubnetworkDropdown from '~/create_cluster/gke_cluster/components/gke_subnetwork_dropdown.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();
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 c07e3f81964..4054b768e34 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,13 +1,13 @@
import { shallowMount } from '@vue/test-utils';
import GkeZoneDropdown from '~/create_cluster/gke_cluster/components/gke_zone_dropdown.vue';
-import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
import { createStore } from '~/create_cluster/gke_cluster/store';
import {
SET_PROJECT,
SET_ZONES,
SET_PROJECT_BILLING_STATUS,
} from '~/create_cluster/gke_cluster/store/mutation_types';
+import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
+import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import { selectedZoneMock, selectedProjectMock, gapiZonesResponseMock } from '../mock_data';
const propsData = {
diff --git a/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js b/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
index 8852baafec7..55c502b96bb 100644
--- a/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/stores/actions_spec.js
@@ -1,7 +1,7 @@
import testAction from 'helpers/vuex_action_helper';
-import createState from '~/create_cluster/gke_cluster/store/state';
-import * as types from '~/create_cluster/gke_cluster/store/mutation_types';
import * as actions from '~/create_cluster/gke_cluster/store/actions';
+import * as types from '~/create_cluster/gke_cluster/store/mutation_types';
+import createState from '~/create_cluster/gke_cluster/store/state';
import gapi from '../helpers';
import {
selectedProjectMock,
diff --git a/spec/frontend/create_cluster/gke_cluster/stores/mutations_spec.js b/spec/frontend/create_cluster/gke_cluster/stores/mutations_spec.js
index 2a742b6ed8f..4493d49af43 100644
--- a/spec/frontend/create_cluster/gke_cluster/stores/mutations_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/stores/mutations_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/create_cluster/gke_cluster/store/state';
import * as types from '~/create_cluster/gke_cluster/store/mutation_types';
import mutations from '~/create_cluster/gke_cluster/store/mutations';
+import createState from '~/create_cluster/gke_cluster/store/state';
import {
gapiProjectsResponseMock,
gapiZonesResponseMock,
diff --git a/spec/frontend/create_cluster/init_create_cluster_spec.js b/spec/frontend/create_cluster/init_create_cluster_spec.js
index 1fdcb57492d..42d1ceed864 100644
--- a/spec/frontend/create_cluster/init_create_cluster_spec.js
+++ b/spec/frontend/create_cluster/init_create_cluster_spec.js
@@ -1,6 +1,6 @@
-import initCreateCluster from '~/create_cluster/init_create_cluster';
import initGkeDropdowns from '~/create_cluster/gke_cluster';
import initGkeNamespace from '~/create_cluster/gke_cluster_namespace';
+import initCreateCluster from '~/create_cluster/init_create_cluster';
import PersistentUserCallout from '~/persistent_user_callout';
// This import is loaded dynamically in `init_create_cluster`.
diff --git a/spec/frontend/create_cluster/store/cluster_dropdown/actions_spec.js b/spec/frontend/create_cluster/store/cluster_dropdown/actions_spec.js
index 014b527161f..c0e8b11cf1e 100644
--- a/spec/frontend/create_cluster/store/cluster_dropdown/actions_spec.js
+++ b/spec/frontend/create_cluster/store/cluster_dropdown/actions_spec.js
@@ -1,8 +1,8 @@
import testAction from 'helpers/vuex_action_helper';
-import createState from '~/create_cluster/store/cluster_dropdown/state';
-import * as types from '~/create_cluster/store/cluster_dropdown/mutation_types';
import actionsFactory from '~/create_cluster/store/cluster_dropdown/actions';
+import * as types from '~/create_cluster/store/cluster_dropdown/mutation_types';
+import createState from '~/create_cluster/store/cluster_dropdown/state';
describe('Cluster dropdown Store Actions', () => {
const items = [{ name: 'item 1' }];
diff --git a/spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js b/spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js
index 4b700e31675..197fcfc2600 100644
--- a/spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js
+++ b/spec/frontend/create_cluster/store/cluster_dropdown/mutations_spec.js
@@ -3,8 +3,8 @@ import {
RECEIVE_ITEMS_SUCCESS,
RECEIVE_ITEMS_ERROR,
} from '~/create_cluster/store/cluster_dropdown/mutation_types';
-import createState from '~/create_cluster/store/cluster_dropdown/state';
import mutations from '~/create_cluster/store/cluster_dropdown/mutations';
+import createState from '~/create_cluster/store/cluster_dropdown/state';
describe('Cluster dropdown store mutations', () => {
let state;
diff --git a/spec/frontend/create_merge_request_dropdown_spec.js b/spec/frontend/create_merge_request_dropdown_spec.js
index 698725b769d..08c05c6ec38 100644
--- a/spec/frontend/create_merge_request_dropdown_spec.js
+++ b/spec/frontend/create_merge_request_dropdown_spec.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import CreateMergeRequestDropdown from '~/create_merge_request_dropdown';
import confidentialState from '~/confidential_merge_request/state';
+import CreateMergeRequestDropdown from '~/create_merge_request_dropdown';
+import axios from '~/lib/utils/axios_utils';
describe('CreateMergeRequestDropdown', () => {
let axiosMock;
diff --git a/spec/frontend/cycle_analytics/limit_warning_component_spec.js b/spec/frontend/cycle_analytics/limit_warning_component_spec.js
index edde3725dd6..3dac7438909 100644
--- a/spec/frontend/cycle_analytics/limit_warning_component_spec.js
+++ b/spec/frontend/cycle_analytics/limit_warning_component_spec.js
@@ -1,7 +1,7 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
-import Translate from '~/vue_shared/translate';
+import Vue from 'vue';
import LimitWarningComponent from '~/cycle_analytics/components/limit_warning_component.vue';
+import Translate from '~/vue_shared/translate';
Vue.use(Translate);
diff --git a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
index 650825d1cb7..d8ce184940a 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_modal_spec.js
@@ -1,9 +1,9 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlButton, GlModal } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
-import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import createStore from '~/deploy_freeze/store';
+import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue();
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 c29a0c0ca73..392652292cf 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_settings_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import DeployFreezeSettings from '~/deploy_freeze/components/deploy_freeze_settings.vue';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
-import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import createStore from '~/deploy_freeze/store';
import { timezoneDataFixture } from '../helpers';
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 3b8e8f8485e..e4ee1b9ad26 100644
--- a/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
+++ b/spec/frontend/deploy_freeze/components/deploy_freeze_table_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index 1b03cc03d02..4dd5c29a917 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlDropdownItem, GlDropdown } from '@gitlab/ui';
-import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+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();
diff --git a/spec/frontend/deploy_freeze/store/actions_spec.js b/spec/frontend/deploy_freeze/store/actions_spec.js
index 3c9d25c4f5c..f4d9802e39a 100644
--- a/spec/frontend/deploy_freeze/store/actions_spec.js
+++ b/spec/frontend/deploy_freeze/store/actions_spec.js
@@ -1,11 +1,11 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import getInitialState from '~/deploy_freeze/store/state';
import * as actions from '~/deploy_freeze/store/actions';
import * as types from '~/deploy_freeze/store/mutation_types';
+import getInitialState from '~/deploy_freeze/store/state';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
jest.mock('~/api.js');
diff --git a/spec/frontend/deploy_freeze/store/mutations_spec.js b/spec/frontend/deploy_freeze/store/mutations_spec.js
index 7cb208f16b2..54cbdfcb64c 100644
--- a/spec/frontend/deploy_freeze/store/mutations_spec.js
+++ b/spec/frontend/deploy_freeze/store/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/deploy_freeze/store/state';
-import mutations from '~/deploy_freeze/store/mutations';
import * as types from '~/deploy_freeze/store/mutation_types';
+import mutations from '~/deploy_freeze/store/mutations';
+import state from '~/deploy_freeze/store/state';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { findTzByName, formatTz, freezePeriodsFixture, timezoneDataFixture } from '../helpers';
diff --git a/spec/frontend/deploy_keys/components/action_btn_spec.js b/spec/frontend/deploy_keys/components/action_btn_spec.js
index b8211b02464..21281ff15b1 100644
--- a/spec/frontend/deploy_keys/components/action_btn_spec.js
+++ b/spec/frontend/deploy_keys/components/action_btn_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
-import eventHub from '~/deploy_keys/eventhub';
+import { shallowMount } from '@vue/test-utils';
import actionBtn from '~/deploy_keys/components/action_btn.vue';
+import eventHub from '~/deploy_keys/eventhub';
describe('Deploy keys action btn', () => {
const data = getJSONFixture('deploy_keys/keys.json');
diff --git a/spec/frontend/deploy_keys/components/app_spec.js b/spec/frontend/deploy_keys/components/app_spec.js
index 479320f92f2..b48e0424580 100644
--- a/spec/frontend/deploy_keys/components/app_spec.js
+++ b/spec/frontend/deploy_keys/components/app_spec.js
@@ -1,10 +1,10 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-import eventHub from '~/deploy_keys/eventhub';
+import { TEST_HOST } from 'spec/test_constants';
import deployKeysApp from '~/deploy_keys/components/app.vue';
+import eventHub from '~/deploy_keys/eventhub';
+import axios from '~/lib/utils/axios_utils';
const TEST_ENDPOINT = `${TEST_HOST}/dummy/`;
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index fcb4e31dec8..5420f9a01f9 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
-import DeployKeysStore from '~/deploy_keys/store';
import key from '~/deploy_keys/components/key.vue';
+import DeployKeysStore from '~/deploy_keys/store';
import { getTimeago } from '~/lib/utils/datetime_utility';
describe('Deploy keys key', () => {
@@ -76,7 +76,7 @@ describe('Deploy keys key', () => {
createComponent({ deployKey: { ...deployKey, deploy_keys_projects: deployKeysProjects } });
expect(wrapper.find('.deploy-project-label').attributes('title')).toBe(
- 'Write access allowed',
+ 'Grant write permissions to this key',
);
});
diff --git a/spec/frontend/deploy_keys/components/keys_panel_spec.js b/spec/frontend/deploy_keys/components/keys_panel_spec.js
index 34b592017e9..d6419356166 100644
--- a/spec/frontend/deploy_keys/components/keys_panel_spec.js
+++ b/spec/frontend/deploy_keys/components/keys_panel_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
-import DeployKeysStore from '~/deploy_keys/store';
import deployKeysPanel from '~/deploy_keys/components/keys_panel.vue';
+import DeployKeysStore from '~/deploy_keys/store';
describe('Deploy keys panel', () => {
const data = getJSONFixture('deploy_keys/keys.json');
diff --git a/spec/frontend/design_management/components/delete_button_spec.js b/spec/frontend/design_management/components/delete_button_spec.js
index 961f5bdd2ae..8f7d8e0b214 100644
--- a/spec/frontend/design_management/components/delete_button_spec.js
+++ b/spec/frontend/design_management/components/delete_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import BatchDeleteButton from '~/design_management/components/delete_button.vue';
describe('Batch delete button component', () => {
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 77fc70e08d1..92e188f4bcc 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,14 +1,14 @@
-import { mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
-import notes from '../../mock_data/notes';
+import { mount } from '@vue/test-utils';
import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.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 ToggleRepliesWidget from '~/design_management/components/design_notes/toggle_replies_widget.vue';
import createNoteMutation from '~/design_management/graphql/mutations/create_note.mutation.graphql';
import toggleResolveDiscussionMutation from '~/design_management/graphql/mutations/toggle_resolve_discussion.mutation.graphql';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
-import ToggleRepliesWidget from '~/design_management/components/design_notes/toggle_replies_widget.vue';
import mockDiscussion from '../../mock_data/discussion';
+import notes from '../../mock_data/notes';
const defaultMockDiscussion = {
id: '0',
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 043091e3dc2..1cd556eabb4 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,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
import DesignNote from '~/design_management/components/design_notes/design_note.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
const scrollIntoViewMock = jest.fn();
const note = {
diff --git a/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js b/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js
index 7eda294d2d3..f87228663b6 100644
--- a/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js
+++ b/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlButton, GlLink } from '@gitlab/ui';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { shallowMount } from '@vue/test-utils';
import ToggleRepliesWidget from '~/design_management/components/design_notes/toggle_replies_widget.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import notes from '../../mock_data/notes';
describe('Toggle replies widget component', () => {
diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index a026cc39c84..d3119be7159 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils';
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';
import notes from '../mock_data/notes';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '~/design_management/constants';
const mutate = jest.fn(() => Promise.resolve());
diff --git a/spec/frontend/design_management/components/design_presentation_spec.js b/spec/frontend/design_management/components/design_presentation_spec.js
index 31fd154dc4b..edf8b965153 100644
--- a/spec/frontend/design_management/components/design_presentation_spec.js
+++ b/spec/frontend/design_management/components/design_presentation_spec.js
@@ -1,7 +1,7 @@
-import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
-import DesignPresentation from '~/design_management/components/design_presentation.vue';
+import { nextTick } from 'vue';
import DesignOverlay from '~/design_management/components/design_overlay.vue';
+import DesignPresentation from '~/design_management/components/design_presentation.vue';
const mockOverlayData = {
overlayDimensions: {
diff --git a/spec/frontend/design_management/components/design_scaler_spec.js b/spec/frontend/design_management/components/design_scaler_spec.js
index 40f53e8d0bf..8a123b2d1e5 100644
--- a/spec/frontend/design_management/components/design_scaler_spec.js
+++ b/spec/frontend/design_management/components/design_scaler_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DesignScaler from '~/design_management/components/design_scaler.vue';
describe('Design management design scaler component', () => {
diff --git a/spec/frontend/design_management/components/design_sidebar_spec.js b/spec/frontend/design_management/components/design_sidebar_spec.js
index 60266883fcd..8eb993ec7b5 100644
--- a/spec/frontend/design_management/components/design_sidebar_spec.js
+++ b/spec/frontend/design_management/components/design_sidebar_spec.js
@@ -1,12 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
import { GlCollapse, GlPopover } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
+import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue';
import DesignSidebar from '~/design_management/components/design_sidebar.vue';
+import DesignTodoButton from '~/design_management/components/design_todo_button.vue';
+import updateActiveDiscussionMutation from '~/design_management/graphql/mutations/update_active_discussion.mutation.graphql';
import Participants from '~/sidebar/components/participants/participants.vue';
-import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue';
import design from '../mock_data/design';
-import updateActiveDiscussionMutation from '~/design_management/graphql/mutations/update_active_discussion.mutation.graphql';
-import DesignTodoButton from '~/design_management/components/design_todo_button.vue';
const scrollIntoViewMock = jest.fn();
HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
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 9ebc6ca26a2..20686d0ae6c 100644
--- a/spec/frontend/design_management/components/design_todo_button_spec.js
+++ b/spec/frontend/design_management/components/design_todo_button_spec.js
@@ -1,8 +1,8 @@
import { shallowMount, mount } from '@vue/test-utils';
-import TodoButton from '~/vue_shared/components/todo_button.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';
+import TodoButton from '~/vue_shared/components/todo_button.vue';
import mockDesign from '../mock_data/design';
const mockDesignWithPendingTodos = {
@@ -111,7 +111,7 @@ describe('Design management design todo button', () => {
});
it('renders correct button text', () => {
- expect(wrapper.text()).toBe('Add a To Do');
+ expect(wrapper.text()).toBe('Add a to do');
});
describe('when clicked', () => {
diff --git a/spec/frontend/design_management/components/image_spec.js b/spec/frontend/design_management/components/image_spec.js
index 52d60b04a8a..765d902f9a6 100644
--- a/spec/frontend/design_management/components/image_spec.js
+++ b/spec/frontend/design_management/components/image_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DesignImage from '~/design_management/components/image.vue';
describe('Design management large image component', () => {
diff --git a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
index 36a2ffd19c3..8fe3e92360a 100644
--- a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
+++ b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
@@ -26,9 +26,10 @@ exports[`Design management list item component with notes renders item with mult
<img
alt="test"
- class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
+ class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full design-img"
data-qa-filename="test"
data-qa-selector="design_image"
+ data-testid="design-img-1"
src=""
/>
</gl-intersection-observer-stub>
@@ -43,6 +44,8 @@ exports[`Design management list item component with notes renders item with mult
<span
class="gl-font-weight-bold str-truncated-100"
data-qa-selector="design_file_name"
+ data-testid="design-img-filename-1"
+ title="test"
>
test
</span>
@@ -100,9 +103,10 @@ exports[`Design management list item component with notes renders item with sing
<img
alt="test"
- class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
+ class="gl-display-block gl-mx-auto gl-max-w-full gl-max-h-full design-img"
data-qa-filename="test"
data-qa-selector="design_image"
+ data-testid="design-img-1"
src=""
/>
</gl-intersection-observer-stub>
@@ -117,6 +121,8 @@ exports[`Design management list item component with notes renders item with sing
<span
class="gl-font-weight-bold str-truncated-100"
data-qa-selector="design_file_name"
+ data-testid="design-img-filename-1"
+ title="test"
>
test
</span>
diff --git a/spec/frontend/design_management/components/list/item_spec.js b/spec/frontend/design_management/components/list/item_spec.js
index 55c6ecbc26b..caf0f8bb5bc 100644
--- a/spec/frontend/design_management/components/list/item_spec.js
+++ b/spec/frontend/design_management/components/list/item_spec.js
@@ -1,6 +1,7 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlIcon, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
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();
@@ -17,8 +18,11 @@ const DESIGN_VERSION_EVENT = {
describe('Design management list item component', () => {
let wrapper;
+ const imgId = 1;
+ const imgFilename = 'test';
- const findDesignEvent = () => wrapper.find('[data-testid="designEvent"]');
+ const findDesignEvent = () => wrapper.findByTestId('design-event');
+ const findImgFilename = (id = imgId) => wrapper.findByTestId(`design-img-filename-${id}`);
const findEventIcon = () => findDesignEvent().find(GlIcon);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
@@ -28,25 +32,27 @@ describe('Design management list item component', () => {
isUploading = false,
imageLoading = false,
} = {}) {
- wrapper = shallowMount(Item, {
- localVue,
- router,
- propsData: {
- id: 1,
- filename: 'test',
- image: 'http://via.placeholder.com/300',
- isUploading,
- event,
- notesCount,
- updatedAt: '01-01-2019',
- },
- data() {
- return {
- imageLoading,
- };
- },
- stubs: ['router-link'],
- });
+ wrapper = extendedWrapper(
+ shallowMount(Item, {
+ localVue,
+ router,
+ propsData: {
+ id: imgId,
+ filename: imgFilename,
+ image: 'http://via.placeholder.com/300',
+ isUploading,
+ event,
+ notesCount,
+ updatedAt: '01-01-2019',
+ },
+ data() {
+ return {
+ imageLoading,
+ };
+ },
+ stubs: ['router-link'],
+ }),
+ );
}
afterEach(() => {
@@ -75,6 +81,10 @@ describe('Design management list item component', () => {
return wrapper.vm.$nextTick();
});
+ it('renders a tooltip', () => {
+ expect(findImgFilename().attributes('title')).toEqual(imgFilename);
+ });
+
describe('before image is loaded', () => {
it('renders loading spinner', () => {
expect(wrapper.find(GlLoadingIcon)).toExist();
diff --git a/spec/frontend/design_management/components/toolbar/index_spec.js b/spec/frontend/design_management/components/toolbar/index_spec.js
index 6ac088a2c53..44c865d976d 100644
--- a/spec/frontend/design_management/components/toolbar/index_spec.js
+++ b/spec/frontend/design_management/components/toolbar/index_spec.js
@@ -1,8 +1,8 @@
+import { GlButton } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueRouter from 'vue-router';
-import { GlButton } from '@gitlab/ui';
-import Toolbar from '~/design_management/components/toolbar/index.vue';
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();
diff --git a/spec/frontend/design_management/components/upload/button_spec.js b/spec/frontend/design_management/components/upload/button_spec.js
index ea738496ad6..d123db43ce6 100644
--- a/spec/frontend/design_management/components/upload/button_spec.js
+++ b/spec/frontend/design_management/components/upload/button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UploadButton from '~/design_management/components/upload/button.vue';
describe('Design management upload button component', () => {
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 d841aabf2f3..1b01a363688 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DesignVersionDropdown from '~/design_management/components/upload/design_version_dropdown.vue';
import mockAllVersions from './mock_data/all_versions';
diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js
index 9c11af28cf0..11c88c3d0f5 100644
--- a/spec/frontend/design_management/pages/design/index_spec.js
+++ b/spec/frontend/design_management/pages/design/index_spec.js
@@ -1,32 +1,32 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import VueRouter from 'vue-router';
import { GlAlert } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
+import VueRouter from 'vue-router';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
-import createFlash from '~/flash';
import Api from '~/api';
-import DesignIndex from '~/design_management/pages/design/index.vue';
-import DesignSidebar from '~/design_management/components/design_sidebar.vue';
import DesignPresentation from '~/design_management/components/design_presentation.vue';
+import DesignSidebar from '~/design_management/components/design_sidebar.vue';
+import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management/constants';
import createImageDiffNoteMutation from '~/design_management/graphql/mutations/create_image_diff_note.mutation.graphql';
import updateActiveDiscussion from '~/design_management/graphql/mutations/update_active_discussion.mutation.graphql';
+import DesignIndex from '~/design_management/pages/design/index.vue';
+import createRouter from '~/design_management/router';
+import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from '~/design_management/router/constants';
+import * as utils from '~/design_management/utils/design_management_utils';
import {
DESIGN_NOT_FOUND_ERROR,
DESIGN_VERSION_NOT_EXIST_ERROR,
} from '~/design_management/utils/error_messages';
-import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from '~/design_management/router/constants';
-import createRouter from '~/design_management/router';
-import * as utils from '~/design_management/utils/design_management_utils';
-import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management/constants';
-import design from '../../mock_data/design';
-import mockResponseWithDesigns from '../../mock_data/designs';
-import mockResponseNoDesigns from '../../mock_data/no_designs';
-import mockAllVersions from '../../mock_data/all_versions';
import {
DESIGN_TRACKING_PAGE_NAME,
DESIGN_SNOWPLOW_EVENT_TYPES,
DESIGN_USAGE_PING_EVENT_TYPES,
} from '~/design_management/utils/tracking';
+import createFlash from '~/flash';
+import mockAllVersions from '../../mock_data/all_versions';
+import design from '../../mock_data/design';
+import mockResponseWithDesigns from '../../mock_data/designs';
+import mockResponseNoDesigns from '../../mock_data/no_designs';
jest.mock('~/flash');
jest.mock('~/api.js');
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 7d28d6f6d11..4f162ca8e7f 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -1,27 +1,32 @@
-import { nextTick } from 'vue';
+import { GlEmptyState } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import VueApollo, { ApolloMutation } from 'vue-apollo';
-import VueDraggable from 'vuedraggable';
import VueRouter from 'vue-router';
-import { GlEmptyState } from '@gitlab/ui';
+import VueDraggable from 'vuedraggable';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
-import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
-import Index from '~/design_management/pages/index.vue';
-import uploadDesignMutation from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
-import DesignDestroyer from '~/design_management/components/design_destroyer.vue';
-import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
+import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
import DeleteButton from '~/design_management/components/delete_button.vue';
+import DesignDestroyer from '~/design_management/components/design_destroyer.vue';
import Design from '~/design_management/components/list/item.vue';
+import moveDesignMutation from '~/design_management/graphql/mutations/move_design.mutation.graphql';
+import uploadDesignMutation from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
+import Index from '~/design_management/pages/index.vue';
+import createRouter from '~/design_management/router';
import { DESIGNS_ROUTE_NAME } from '~/design_management/router/constants';
+import * as utils from '~/design_management/utils/design_management_utils';
import {
EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
} from '~/design_management/utils/error_messages';
+import {
+ DESIGN_TRACKING_PAGE_NAME,
+ DESIGN_SNOWPLOW_EVENT_TYPES,
+} from '~/design_management/utils/tracking';
import createFlash from '~/flash';
-import createRouter from '~/design_management/router';
-import * as utils from '~/design_management/utils/design_management_utils';
+import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
import {
designListQueryResponse,
designUploadMutationCreatedResponse,
@@ -31,11 +36,6 @@ import {
reorderedDesigns,
moveDesignMutationResponseWithErrors,
} from '../mock_data/apollo_mock';
-import moveDesignMutation from '~/design_management/graphql/mutations/move_design.mutation.graphql';
-import {
- DESIGN_TRACKING_PAGE_NAME,
- DESIGN_SNOWPLOW_EVENT_TYPES,
-} from '~/design_management/utils/tracking';
jest.mock('~/flash.js');
const mockPageEl = {
diff --git a/spec/frontend/design_management/router_spec.js b/spec/frontend/design_management/router_spec.js
index 0b4e68eea78..ac5e6895408 100644
--- a/spec/frontend/design_management/router_spec.js
+++ b/spec/frontend/design_management/router_spec.js
@@ -2,8 +2,8 @@ import { mount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import VueRouter from 'vue-router';
import App from '~/design_management/components/app.vue';
-import Designs from '~/design_management/pages/index.vue';
import DesignDetail from '~/design_management/pages/design/index.vue';
+import Designs from '~/design_management/pages/index.vue';
import createRouter from '~/design_management/router';
import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from '~/design_management/router/constants';
import '~/commons/bootstrap';
diff --git a/spec/frontend/design_management/utils/cache_update_spec.js b/spec/frontend/design_management/utils/cache_update_spec.js
index 2fb08c3ef05..7327cf00abd 100644
--- a/spec/frontend/design_management/utils/cache_update_spec.js
+++ b/spec/frontend/design_management/utils/cache_update_spec.js
@@ -10,8 +10,8 @@ import {
ADD_IMAGE_DIFF_NOTE_ERROR,
UPDATE_IMAGE_DIFF_NOTE_ERROR,
} from '~/design_management/utils/error_messages';
-import design from '../mock_data/design';
import createFlash from '~/flash';
+import design from '../mock_data/design';
jest.mock('~/flash.js');
diff --git a/spec/frontend/design_management/utils/design_management_utils_spec.js b/spec/frontend/design_management/utils/design_management_utils_spec.js
index 368448ead10..5b7f99e9d96 100644
--- a/spec/frontend/design_management/utils/design_management_utils_spec.js
+++ b/spec/frontend/design_management/utils/design_management_utils_spec.js
@@ -8,9 +8,9 @@ import {
extractDesign,
extractDesignNoteId,
} from '~/design_management/utils/design_management_utils';
-import mockResponseNoDesigns from '../mock_data/no_designs';
-import mockResponseWithDesigns from '../mock_data/designs';
import mockDesign from '../mock_data/design';
+import mockResponseWithDesigns from '../mock_data/designs';
+import mockResponseNoDesigns from '../mock_data/no_designs';
jest.mock('lodash/uniqueId', () => () => 1);
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 7fbeb33dd93..d2b5338a0cc 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -1,26 +1,26 @@
-import Vue, { nextTick } from 'vue';
-import Vuex from 'vuex';
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
import Mousetrap from 'mousetrap';
+import Vue, { nextTick } from 'vue';
+import Vuex from 'vuex';
+import { TEST_HOST } from 'spec/test_constants';
import App from '~/diffs/components/app.vue';
-import NoChanges from '~/diffs/components/no_changes.vue';
-import DiffFile from '~/diffs/components/diff_file.vue';
-import CompareVersions from '~/diffs/components/compare_versions.vue';
-import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue';
import CommitWidget from '~/diffs/components/commit_widget.vue';
+import CompareVersions from '~/diffs/components/compare_versions.vue';
+import DiffFile from '~/diffs/components/diff_file.vue';
+import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
+import NoChanges from '~/diffs/components/no_changes.vue';
import TreeList from '~/diffs/components/tree_list.vue';
-import createDiffsStore from '../create_diffs_store';
-import axios from '~/lib/utils/axios_utils';
-import * as urlUtils from '~/lib/utils/url_utility';
-import diffsMockData from '../mock_data/merge_request_diffs';
import { EVT_VIEW_FILE_BY_FILE } from '~/diffs/constants';
import eventHub from '~/diffs/event_hub';
+import axios from '~/lib/utils/axios_utils';
+import * as urlUtils from '~/lib/utils/url_utility';
+import createDiffsStore from '../create_diffs_store';
+import diffsMockData from '../mock_data/merge_request_diffs';
const mergeRequestDiff = { version_index: 1 };
const TEST_ENDPOINT = `${TEST_HOST}/diff/endpoint`;
diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
index 75e76d88b6b..77c2e19cb68 100644
--- a/spec/frontend/diffs/components/collapsed_files_warning_spec.js
+++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
@@ -1,9 +1,9 @@
-import Vuex from 'vuex';
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
-import createStore from '~/diffs/store/modules';
+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 eventHub from '~/diffs/event_hub';
+import createStore from '~/diffs/store/modules';
const propsData = {
limited: true,
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index f588f65dafd..8cb4fd20063 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import { trimText } from 'helpers/text_helper';
-import { getTimeago } from '~/lib/utils/datetime_utility';
import Component from '~/diffs/components/commit_item.vue';
+import { getTimeago } from '~/lib/utils/datetime_utility';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import getDiffWithCommit from '../mock_data/diff_with_commit';
diff --git a/spec/frontend/diffs/components/commit_widget_spec.js b/spec/frontend/diffs/components/commit_widget_spec.js
index 54e7596b726..fbff473e4df 100644
--- a/spec/frontend/diffs/components/commit_widget_spec.js
+++ b/spec/frontend/diffs/components/commit_widget_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import CommitWidget from '~/diffs/components/commit_widget.vue';
import CommitItem from '~/diffs/components/commit_item.vue';
+import CommitWidget from '~/diffs/components/commit_widget.vue';
describe('diffs/components/commit_widget', () => {
let wrapper;
diff --git a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js
index d99933a1ee9..98f88226742 100644
--- a/spec/frontend/diffs/components/compare_dropdown_layout_spec.js
+++ b/spec/frontend/diffs/components/compare_dropdown_layout_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import CompareDropdownLayout from '~/diffs/components/compare_dropdown_layout.vue';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
const TEST_COMMIT_TEXT = '1 commit';
const TEST_CREATED_AT = '2018-10-23T11:49:16.611Z';
@@ -69,7 +69,7 @@ describe('CompareDropdownLayout', () => {
expect(findListItemsData()).toEqual([
{
href: 'version/1',
- text: 'version 1 (base) abcdef1 1 commit 2 years ago',
+ text: 'version 1 (base) abcdef1 1 commit 1 year ago',
createdAt: TEST_CREATED_AT,
isActive: true,
},
diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js
index 949cc855200..c93a3771ec0 100644
--- a/spec/frontend/diffs/components/compare_versions_spec.js
+++ b/spec/frontend/diffs/components/compare_versions_spec.js
@@ -1,10 +1,10 @@
-import { trimText } from 'helpers/text_helper';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
+import { trimText } from 'helpers/text_helper';
import CompareVersionsComponent from '~/diffs/components/compare_versions.vue';
import { createStore } from '~/mr_notes/stores';
-import diffsMockData from '../mock_data/merge_request_diffs';
import getDiffWithCommit from '../mock_data/diff_with_commit';
+import diffsMockData from '../mock_data/merge_request_diffs';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/diffs/components/diff_comment_cell_spec.js b/spec/frontend/diffs/components/diff_comment_cell_spec.js
index d6b68fc52d7..b636a178593 100644
--- a/spec/frontend/diffs/components/diff_comment_cell_spec.js
+++ b/spec/frontend/diffs/components/diff_comment_cell_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import DiffCommentCell from '~/diffs/components/diff_comment_cell.vue';
-import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
import DiffDiscussionReply from '~/diffs/components/diff_discussion_reply.vue';
+import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
describe('DiffCommentCell', () => {
const createWrapper = (props = {}) => {
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index c1cf4793c88..db4d69f0176 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -1,17 +1,17 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
import DiffContentComponent from '~/diffs/components/diff_content.vue';
+import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
+import DiffView from '~/diffs/components/diff_view.vue';
import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
-import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
-import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
-import NoteForm from '~/notes/components/note_form.vue';
-import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
-import diffFileMockData from '../mock_data/diff_file';
import { diffViewerModes } from '~/ide/constants';
-import DiffView from '~/diffs/components/diff_view.vue';
+import NoteForm from '~/notes/components/note_form.vue';
+import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
+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);
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index 5c390054247..bd6f4cd2545 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -1,10 +1,10 @@
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
-import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
-import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import { createStore } from '~/mr_notes/stores';
+import DiscussionNotes from '~/notes/components/discussion_notes.vue';
+import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import '~/behaviors/markdown/render_gfm';
import discussionsMockData from '../mock_data/diff_discussions';
diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
index 62e85b31f76..f53f10d955d 100644
--- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js
+++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
@@ -1,10 +1,10 @@
-import { cloneDeep } from 'lodash';
-import { mount } from '@vue/test-utils';
import { getByText } from '@testing-library/dom';
-import { createStore } from '~/mr_notes/stores';
+import { mount } from '@vue/test-utils';
+import { cloneDeep } from 'lodash';
import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
-import { getPreviousLineIndex } from '~/diffs/store/utils';
import { INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
+import { getPreviousLineIndex } from '~/diffs/store/utils';
+import { createStore } from '~/mr_notes/stores';
import diffFileMockData from '../mock_data/diff_file';
const EXPAND_UP_CLASS = '.js-unfold';
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index e9a63e861ed..b16ef8fe6b0 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -1,22 +1,29 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
import { cloneDeep } from 'lodash';
+import Vuex from 'vuex';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
+import { DIFF_FILE_AUTOMATIC_COLLAPSE, DIFF_FILE_MANUAL_COLLAPSE } from '~/diffs/constants';
+import { reviewFile } from '~/diffs/store/actions';
+import { SET_MR_FILE_REVIEWS } from '~/diffs/store/mutation_types';
+import { diffViewerModes } from '~/ide/constants';
+import { scrollToElement } from '~/lib/utils/common_utils';
+import { truncateSha } from '~/lib/utils/text_utility';
+import { __, sprintf } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
+
+import testAction from '../../__helpers__/vuex_action_helper';
import diffDiscussionsMockData from '../mock_data/diff_discussions';
-import { truncateSha } from '~/lib/utils/text_utility';
-import { diffViewerModes } from '~/ide/constants';
-import { __, sprintf } from '~/locale';
-import { scrollToElement } from '~/lib/utils/common_utils';
jest.mock('~/lib/utils/common_utils');
const diffFile = Object.freeze(
Object.assign(diffDiscussionsMockData.diff_file, {
+ id: '123',
+ file_identifier_hash: 'abc',
edit_path: 'link:/to/edit/path',
blob: {
id: '848ed9407c6730ff16edb3dd24485a0eea24292a',
@@ -52,6 +59,8 @@ describe('DiffFileHeader component', () => {
toggleFileDiscussionWrappers: jest.fn(),
toggleFullDiff: jest.fn(),
toggleActiveFileByHash: jest.fn(),
+ setFileCollapsedByUser: jest.fn(),
+ reviewFile: jest.fn(),
},
},
},
@@ -79,10 +88,11 @@ describe('DiffFileHeader component', () => {
const findViewFileButton = () => wrapper.find({ ref: 'viewButton' });
const findCollapseIcon = () => wrapper.find({ ref: 'collapseIcon' });
const findEditButton = () => wrapper.find({ ref: 'editButton' });
+ const findReviewFileCheckbox = () => wrapper.find("[data-testid='fileReviewCheckbox']");
- const createComponent = (props) => {
+ const createComponent = ({ props, options = {} } = {}) => {
mockStoreConfig = cloneDeep(defaultMockStoreConfig);
- const store = new Vuex.Store(mockStoreConfig);
+ const store = new Vuex.Store({ ...mockStoreConfig, ...(options.store || {}) });
wrapper = shallowMount(DiffFileHeader, {
propsData: {
@@ -91,6 +101,7 @@ describe('DiffFileHeader component', () => {
viewDiffsFileByFile: false,
...props,
},
+ ...options,
localVue,
store,
});
@@ -101,7 +112,7 @@ describe('DiffFileHeader component', () => {
${'visible'} | ${true}
${'hidden'} | ${false}
`('collapse toggle is $visibility if collapsible is $collapsible', ({ collapsible }) => {
- createComponent({ collapsible });
+ createComponent({ props: { collapsible } });
expect(findCollapseIcon().exists()).toBe(collapsible);
});
@@ -110,7 +121,7 @@ describe('DiffFileHeader component', () => {
${true} | ${'chevron-down'}
${false} | ${'chevron-right'}
`('collapse icon is $icon if expanded is $expanded', ({ icon, expanded }) => {
- createComponent({ expanded, collapsible: true });
+ createComponent({ props: { expanded, collapsible: true } });
expect(findCollapseIcon().props('name')).toBe(icon);
});
@@ -124,7 +135,7 @@ describe('DiffFileHeader component', () => {
});
it('when collapseIcon is clicked emits toggleFile', () => {
- createComponent({ collapsible: true });
+ createComponent({ props: { collapsible: true } });
findCollapseIcon().vm.$emit('click', new Event('click'));
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleFile).toBeDefined();
@@ -132,7 +143,7 @@ describe('DiffFileHeader component', () => {
});
it('when other element in header is clicked does not emits toggleFile', () => {
- createComponent({ collapsible: true });
+ createComponent({ props: { collapsible: true } });
findTitleLink().trigger('click');
return wrapper.vm.$nextTick().then(() => {
@@ -171,10 +182,12 @@ describe('DiffFileHeader component', () => {
it('prefers submodule_tree_url over submodule_link for href', () => {
const submoduleTreeUrl = 'some://tree/url';
createComponent({
- discussionLink: 'discussionLink',
- diffFile: {
- ...submoduleDiffFile,
- submodule_tree_url: 'some://tree/url',
+ props: {
+ discussionLink: 'discussionLink',
+ diffFile: {
+ ...submoduleDiffFile,
+ submodule_tree_url: 'some://tree/url',
+ },
},
});
@@ -184,8 +197,10 @@ describe('DiffFileHeader component', () => {
it('uses submodule_link for href if submodule_tree_url does not exists', () => {
const submoduleLink = 'link://to/submodule';
createComponent({
- discussionLink: 'discussionLink',
- diffFile: submoduleDiffFile,
+ props: {
+ discussionLink: 'discussionLink',
+ diffFile: submoduleDiffFile,
+ },
});
expect(findTitleLink().attributes('href')).toBe(submoduleLink);
@@ -193,7 +208,9 @@ describe('DiffFileHeader component', () => {
it('uses file_path + SHA as link text', () => {
createComponent({
- diffFile: submoduleDiffFile,
+ props: {
+ diffFile: submoduleDiffFile,
+ },
});
expect(findTitleLink().text()).toContain(
@@ -203,15 +220,19 @@ describe('DiffFileHeader component', () => {
it('does not render file actions', () => {
createComponent({
- diffFile: submoduleDiffFile,
- addMergeRequestButtons: true,
+ props: {
+ diffFile: submoduleDiffFile,
+ addMergeRequestButtons: true,
+ },
});
expect(findFileActions().exists()).toBe(false);
});
it('renders submodule icon', () => {
createComponent({
- diffFile: submoduleDiffFile,
+ props: {
+ diffFile: submoduleDiffFile,
+ },
});
expect(wrapper.find(FileIcon).props('submodule')).toBe(true);
@@ -223,13 +244,15 @@ describe('DiffFileHeader component', () => {
it('for mode_changed file mode displays mode changes', () => {
createComponent({
- diffFile: {
- ...diffFile,
- a_mode: 'old-mode',
- b_mode: 'new-mode',
- viewer: {
- ...diffFile.viewer,
- name: diffViewerModes.mode_changed,
+ props: {
+ diffFile: {
+ ...diffFile,
+ a_mode: 'old-mode',
+ b_mode: 'new-mode',
+ viewer: {
+ ...diffFile.viewer,
+ name: diffViewerModes.mode_changed,
+ },
},
},
});
@@ -240,13 +263,15 @@ describe('DiffFileHeader component', () => {
'for %s file mode does not display mode changes',
(mode) => {
createComponent({
- diffFile: {
- ...diffFile,
- a_mode: 'old-mode',
- b_mode: 'new-mode',
- viewer: {
- ...diffFile.viewer,
- name: diffViewerModes[mode],
+ props: {
+ diffFile: {
+ ...diffFile,
+ a_mode: 'old-mode',
+ b_mode: 'new-mode',
+ viewer: {
+ ...diffFile.viewer,
+ name: diffViewerModes[mode],
+ },
},
},
});
@@ -256,32 +281,38 @@ describe('DiffFileHeader component', () => {
it('displays the LFS label for files stored in LFS', () => {
createComponent({
- diffFile: { ...diffFile, stored_externally: true, external_storage: 'lfs' },
+ props: {
+ diffFile: { ...diffFile, stored_externally: true, external_storage: 'lfs' },
+ },
});
expect(findLfsLabel().exists()).toBe(true);
});
it('does not display the LFS label for files stored in repository', () => {
createComponent({
- diffFile: { ...diffFile, stored_externally: false },
+ props: {
+ diffFile: { ...diffFile, stored_externally: false },
+ },
});
expect(findLfsLabel().exists()).toBe(false);
});
it('does not render view replaced file button if no replaced view path is present', () => {
createComponent({
- diffFile: { ...diffFile, replaced_view_path: null },
+ props: {
+ diffFile: { ...diffFile, replaced_view_path: null },
+ },
});
expect(findReplacedFileButton().exists()).toBe(false);
});
describe('when addMergeRequestButtons is false', () => {
it('does not render file actions', () => {
- createComponent({ addMergeRequestButtons: false });
+ createComponent({ props: { addMergeRequestButtons: false } });
expect(findFileActions().exists()).toBe(false);
});
it('should not render edit button', () => {
- createComponent({ addMergeRequestButtons: false });
+ createComponent({ props: { addMergeRequestButtons: false } });
expect(findEditButton().exists()).toBe(false);
});
});
@@ -290,7 +321,7 @@ describe('DiffFileHeader component', () => {
describe('without discussions', () => {
it('does not render a toggle discussions button', () => {
diffHasDiscussionsResultMock.mockReturnValue(false);
- createComponent({ addMergeRequestButtons: true });
+ createComponent({ props: { addMergeRequestButtons: true } });
expect(findToggleDiscussionsButton().exists()).toBe(false);
});
});
@@ -298,7 +329,7 @@ describe('DiffFileHeader component', () => {
describe('with discussions', () => {
it('dispatches toggleFileDiscussionWrappers when user clicks on toggle discussions button', () => {
diffHasDiscussionsResultMock.mockReturnValue(true);
- createComponent({ addMergeRequestButtons: true });
+ createComponent({ props: { addMergeRequestButtons: true } });
expect(findToggleDiscussionsButton().exists()).toBe(true);
findToggleDiscussionsButton().vm.$emit('click');
expect(
@@ -309,7 +340,9 @@ describe('DiffFileHeader component', () => {
it('should show edit button', () => {
createComponent({
- addMergeRequestButtons: true,
+ props: {
+ addMergeRequestButtons: true,
+ },
});
expect(findEditButton().exists()).toBe(true);
});
@@ -319,25 +352,27 @@ describe('DiffFileHeader component', () => {
const externalUrl = 'link://to/external';
const formattedExternalUrl = 'link://formatted';
createComponent({
- diffFile: {
- ...diffFile,
- external_url: externalUrl,
- formatted_external_url: formattedExternalUrl,
+ props: {
+ diffFile: {
+ ...diffFile,
+ external_url: externalUrl,
+ formatted_external_url: formattedExternalUrl,
+ },
+ addMergeRequestButtons: true,
},
- addMergeRequestButtons: true,
});
expect(findExternalLink().exists()).toBe(true);
});
it('is hidden by default', () => {
- createComponent({ addMergeRequestButtons: true });
+ createComponent({ props: { addMergeRequestButtons: true } });
expect(findExternalLink().exists()).toBe(false);
});
});
describe('without file blob', () => {
beforeEach(() => {
- createComponent({ diffFile: { ...diffFile, blob: false } });
+ createComponent({ props: { diffFile: { ...diffFile, blob: false } } });
});
it('should not render toggle discussions button', () => {
@@ -352,8 +387,10 @@ describe('DiffFileHeader component', () => {
it('should render correct file view button', () => {
const viewPath = 'link://view-path';
createComponent({
- diffFile: { ...diffFile, view_path: viewPath },
- addMergeRequestButtons: true,
+ props: {
+ diffFile: { ...diffFile, view_path: viewPath },
+ addMergeRequestButtons: true,
+ },
});
expect(findViewFileButton().attributes('href')).toBe(viewPath);
expect(findViewFileButton().text()).toEqual(
@@ -367,9 +404,11 @@ describe('DiffFileHeader component', () => {
describe('when diff is fully expanded', () => {
it('is not rendered', () => {
createComponent({
- diffFile: {
- ...diffFile,
- is_fully_expanded: true,
+ props: {
+ diffFile: {
+ ...diffFile,
+ is_fully_expanded: true,
+ },
},
});
expect(findExpandButton().exists()).toBe(false);
@@ -387,17 +426,17 @@ describe('DiffFileHeader component', () => {
};
it('renders expand to full file button if not showing full file already', () => {
- createComponent(fullyNotExpandedFileProps);
+ createComponent({ props: fullyNotExpandedFileProps });
expect(findExpandButton().exists()).toBe(true);
});
it('renders loading icon when loading full file', () => {
- createComponent(fullyNotExpandedFileProps);
+ createComponent({ props: fullyNotExpandedFileProps });
expect(findExpandButton().exists()).toBe(true);
});
it('toggles full diff on click', () => {
- createComponent(fullyNotExpandedFileProps);
+ createComponent({ props: fullyNotExpandedFileProps });
findExpandButton().vm.$emit('click');
expect(mockStoreConfig.modules.diffs.actions.toggleFullDiff).toHaveBeenCalled();
});
@@ -407,7 +446,9 @@ describe('DiffFileHeader component', () => {
it('uses discussionPath for link if it is defined', () => {
const discussionPath = 'link://to/discussion';
createComponent({
- discussionPath,
+ props: {
+ discussionPath,
+ },
});
expect(findTitleLink().attributes('href')).toBe(discussionPath);
});
@@ -436,21 +477,21 @@ describe('DiffFileHeader component', () => {
describe('for new file', () => {
it('displays the path', () => {
- createComponent({ diffFile: { ...diffFile, new_file: true } });
+ createComponent({ props: { diffFile: { ...diffFile, new_file: true } } });
expect(findTitleLink().text()).toBe(diffFile.file_path);
});
});
describe('for deleted file', () => {
it('displays the path', () => {
- createComponent({ diffFile: { ...diffFile, deleted_file: true } });
+ createComponent({ props: { diffFile: { ...diffFile, deleted_file: true } } });
expect(findTitleLink().text()).toBe(
sprintf(__('%{filePath} deleted'), { filePath: diffFile.file_path }, false),
);
});
it('does not show edit button', () => {
- createComponent({ diffFile: { ...diffFile, deleted_file: true } });
+ createComponent({ props: { diffFile: { ...diffFile, deleted_file: true } } });
expect(findEditButton().exists()).toBe(false);
});
});
@@ -458,11 +499,13 @@ describe('DiffFileHeader component', () => {
describe('for renamed file', () => {
it('displays old and new path if the file was renamed', () => {
createComponent({
- diffFile: {
- ...diffFile,
- renamed_file: true,
- old_path_html: 'old',
- new_path_html: 'new',
+ props: {
+ diffFile: {
+ ...diffFile,
+ renamed_file: true,
+ old_path_html: 'old',
+ new_path_html: 'new',
+ },
},
});
expect(findTitleLink().text()).toMatch(/^old.+new/s);
@@ -473,13 +516,132 @@ describe('DiffFileHeader component', () => {
it('renders view replaced file button', () => {
const replacedViewPath = 'some/path';
createComponent({
- diffFile: {
- ...diffFile,
- replaced_view_path: replacedViewPath,
+ props: {
+ diffFile: {
+ ...diffFile,
+ replaced_view_path: replacedViewPath,
+ },
+ addMergeRequestButtons: true,
},
- addMergeRequestButtons: true,
});
expect(findReplacedFileButton().exists()).toBe(true);
});
});
+
+ describe('file reviews', () => {
+ it('calls the action to set the new review', () => {
+ createComponent({
+ props: {
+ diffFile: {
+ ...diffFile,
+ viewer: {
+ ...diffFile.viewer,
+ automaticallyCollapsed: false,
+ manuallyCollapsed: null,
+ },
+ },
+ showLocalFileReviews: true,
+ addMergeRequestButtons: true,
+ },
+ });
+
+ const file = wrapper.vm.diffFile;
+
+ findReviewFileCheckbox().vm.$emit('change', true);
+
+ return testAction(
+ reviewFile,
+ { file, reviewed: true },
+ {},
+ [{ type: SET_MR_FILE_REVIEWS, payload: { [file.file_identifier_hash]: [file.id] } }],
+ [],
+ );
+ });
+
+ it.each`
+ description | newReviewedStatus | collapseType | aCollapse | mCollapse | callAction
+ ${'does nothing'} | ${true} | ${DIFF_FILE_MANUAL_COLLAPSE} | ${false} | ${true} | ${false}
+ ${'does nothing'} | ${false} | ${DIFF_FILE_AUTOMATIC_COLLAPSE} | ${true} | ${null} | ${false}
+ ${'does nothing'} | ${true} | ${'not collapsed'} | ${false} | ${null} | ${false}
+ ${'does nothing'} | ${false} | ${'not collapsed'} | ${false} | ${null} | ${false}
+ ${'collapses the file'} | ${true} | ${DIFF_FILE_AUTOMATIC_COLLAPSE} | ${true} | ${null} | ${true}
+ `(
+ "$description if the new review status is reviewed = $newReviewedStatus and the file's collapse type is collapse = $collapseType",
+ ({ newReviewedStatus, aCollapse, mCollapse, callAction }) => {
+ createComponent({
+ props: {
+ diffFile: {
+ ...diffFile,
+ viewer: {
+ ...diffFile.viewer,
+ automaticallyCollapsed: aCollapse,
+ manuallyCollapsed: mCollapse,
+ },
+ },
+ showLocalFileReviews: true,
+ addMergeRequestButtons: true,
+ },
+ });
+
+ findReviewFileCheckbox().vm.$emit('change', newReviewedStatus);
+
+ if (callAction) {
+ expect(mockStoreConfig.modules.diffs.actions.setFileCollapsedByUser).toHaveBeenCalled();
+ } else {
+ expect(
+ mockStoreConfig.modules.diffs.actions.setFileCollapsedByUser,
+ ).not.toHaveBeenCalled();
+ }
+ },
+ );
+
+ it.each`
+ description | show | visible
+ ${'shows'} | ${true} | ${true}
+ ${'hides'} | ${false} | ${false}
+ `(
+ '$description the file review feature given { showLocalFileReviewsProp: $show }',
+ ({ show, visible }) => {
+ createComponent({
+ props: {
+ showLocalFileReviews: show,
+ addMergeRequestButtons: true,
+ },
+ });
+
+ expect(findReviewFileCheckbox().exists()).toEqual(visible);
+ },
+ );
+
+ it.each`
+ open | status | fires
+ ${true} | ${true} | ${true}
+ ${false} | ${false} | ${true}
+ ${true} | ${false} | ${false}
+ ${false} | ${true} | ${false}
+ `(
+ 'toggles appropriately when { fileExpanded: $open, newReviewStatus: $status }',
+ ({ open, status, fires }) => {
+ createComponent({
+ props: {
+ diffFile: {
+ ...diffFile,
+ viewer: {
+ ...diffFile.viewer,
+ automaticallyCollapsed: false,
+ manuallyCollapsed: null,
+ },
+ },
+ showLocalFileReviews: true,
+ addMergeRequestButtons: true,
+ expanded: open,
+ },
+ });
+
+ findReviewFileCheckbox().vm.$emit('change', status);
+
+ expect(Boolean(wrapper.emitted().toggleFile)).toBe(fires);
+ },
+ );
+ });
});
diff --git a/spec/frontend/diffs/components/diff_file_row_spec.js b/spec/frontend/diffs/components/diff_file_row_spec.js
index 7403a7918a9..1d1c5fec293 100644
--- a/spec/frontend/diffs/components/diff_file_row_spec.js
+++ b/spec/frontend/diffs/components/diff_file_row_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import DiffFileRow from '~/diffs/components/diff_file_row.vue';
-import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from '~/diffs/components/file_row_stats.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
+import FileRow from '~/vue_shared/components/file_row.vue';
describe('Diff File Row component', () => {
let wrapper;
diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js
index c715d779986..9c3c3e82ad5 100644
--- a/spec/frontend/diffs/components/diff_file_spec.js
+++ b/spec/frontend/diffs/components/diff_file_spec.js
@@ -1,26 +1,25 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
-import axios from '~/lib/utils/axios_utils';
-import httpStatus from '~/lib/utils/http_status';
-import createDiffsStore from '~/diffs/store/modules';
-import createNotesStore from '~/notes/stores/modules';
-import diffFileMockDataReadable from '../mock_data/diff_file';
-import diffFileMockDataUnreadable from '../mock_data/diff_file_unreadable';
-
+import DiffContentComponent from '~/diffs/components/diff_content.vue';
import DiffFileComponent from '~/diffs/components/diff_file.vue';
import DiffFileHeaderComponent from '~/diffs/components/diff_file_header.vue';
-import DiffContentComponent from '~/diffs/components/diff_content.vue';
-import eventHub from '~/diffs/event_hub';
import {
EVT_EXPAND_ALL_FILES,
EVT_PERF_MARK_DIFF_FILES_END,
EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN,
} from '~/diffs/constants';
+import eventHub from '~/diffs/event_hub';
+import createDiffsStore from '~/diffs/store/modules';
import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
+import axios from '~/lib/utils/axios_utils';
+import httpStatus from '~/lib/utils/http_status';
+import createNotesStore from '~/notes/stores/modules';
+import diffFileMockDataReadable from '../mock_data/diff_file';
+import diffFileMockDataUnreadable from '../mock_data/diff_file_unreadable';
function changeViewer(store, index, { automaticallyCollapsed, manuallyCollapsed, name }) {
const file = store.state.diffs.diffFiles[index];
@@ -66,7 +65,7 @@ function markFileToBeRendered(store, index = 0) {
});
}
-function createComponent({ file, first = false, last = false }) {
+function createComponent({ file, first = false, last = false, options = {}, props = {} }) {
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -89,7 +88,9 @@ function createComponent({ file, first = false, last = false }) {
viewDiffsFileByFile: false,
isFirstFile: first,
isLastFile: last,
+ ...props,
},
+ ...options,
});
return {
@@ -220,6 +221,53 @@ describe('DiffFile', () => {
});
});
+ describe('computed', () => {
+ describe('showLocalFileReviews', () => {
+ let gon;
+
+ function setLoggedIn(bool) {
+ window.gon.current_user_id = bool;
+ }
+
+ beforeAll(() => {
+ gon = window.gon;
+ window.gon = {};
+ });
+
+ afterEach(() => {
+ window.gon = gon;
+ });
+
+ it.each`
+ loggedIn | featureOn | bool
+ ${true} | ${true} | ${true}
+ ${false} | ${true} | ${false}
+ ${true} | ${false} | ${false}
+ ${false} | ${false} | ${false}
+ `(
+ 'should be $bool when { userIsLoggedIn: $loggedIn, featureEnabled: $featureOn }',
+ ({ loggedIn, featureOn, bool }) => {
+ setLoggedIn(loggedIn);
+
+ ({ wrapper } = createComponent({
+ options: {
+ provide: {
+ glFeatures: {
+ localFileReviews: featureOn,
+ },
+ },
+ },
+ props: {
+ file: store.state.diffs.diffFiles[0],
+ },
+ }));
+
+ expect(wrapper.vm.showLocalFileReviews).toBe(bool);
+ },
+ );
+ });
+ });
+
describe('collapsing', () => {
describe(`\`${EVT_EXPAND_ALL_FILES}\` event`, () => {
beforeEach(() => {
@@ -422,9 +470,11 @@ describe('DiffFile', () => {
await wrapper.vm.$nextTick();
- expect(wrapper.vm.$el.innerText).toContain(
- 'This source diff could not be displayed because it is too large',
- );
+ const button = wrapper.find('[data-testid="blob-button"]');
+
+ expect(wrapper.text()).toContain('Changes are too large to be shown.');
+ expect(button.html()).toContain('View file @');
+ expect(button.attributes('href')).toBe('/file/view/path');
});
});
});
diff --git a/spec/frontend/diffs/components/diff_line_note_form_spec.js b/spec/frontend/diffs/components/diff_line_note_form_spec.js
index faa68159c58..a192f7e2e9a 100644
--- a/spec/frontend/diffs/components/diff_line_note_form_spec.js
+++ b/spec/frontend/diffs/components/diff_line_note_form_spec.js
@@ -1,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
-import NoteForm from '~/notes/components/note_form.vue';
import { createStore } from '~/mr_notes/stores';
-import diffFileMockData from '../mock_data/diff_file';
+import NoteForm from '~/notes/components/note_form.vue';
import { noteableDataMock } from '../../notes/mock_data';
+import diffFileMockData from '../mock_data/diff_file';
describe('DiffLineNoteForm', () => {
let wrapper;
@@ -17,6 +17,7 @@ describe('DiffLineNoteForm', () => {
const store = createStore();
store.state.notes.userData.id = 1;
store.state.notes.noteableData = noteableDataMock;
+ store.state.diffs.diffFiles = [diffFile];
store.replaceState({ ...store.state, ...args.state });
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
index c06d8e78316..5682b29d697 100644
--- a/spec/frontend/diffs/components/diff_row_spec.js
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -1,10 +1,10 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { getByTestId, fireEvent } from '@testing-library/dom';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import diffsModule from '~/diffs/store/modules';
import DiffRow from '~/diffs/components/diff_row.vue';
-import diffFileMockData from '../mock_data/diff_file';
import { mapParallel } from '~/diffs/components/diff_row_utils';
+import diffsModule from '~/diffs/store/modules';
+import diffFileMockData from '../mock_data/diff_file';
describe('DiffRow', () => {
const testLines = [
diff --git a/spec/frontend/diffs/components/diff_row_utils_spec.js b/spec/frontend/diffs/components/diff_row_utils_spec.js
index d70d6b609ac..47ae3cd5867 100644
--- a/spec/frontend/diffs/components/diff_row_utils_spec.js
+++ b/spec/frontend/diffs/components/diff_row_utils_spec.js
@@ -143,10 +143,21 @@ describe('addCommentTooltip', () => {
'Commenting on symbolic links that replace or are replaced by files is currently not supported.';
const brokenRealTooltip =
'Commenting on files that replace or are replaced by symbolic links is currently not supported.';
+ const commentTooltip = 'Add a comment to this line';
+ const dragTooltip = 'Add a comment to this line or drag for multiple lines';
+
it('should return default tooltip', () => {
expect(utils.addCommentTooltip()).toBeUndefined();
});
+ it('should return comment tooltip', () => {
+ expect(utils.addCommentTooltip({})).toEqual(commentTooltip);
+ });
+
+ it('should return drag comment tooltip when dragging is enabled', () => {
+ expect(utils.addCommentTooltip({}, true)).toEqual(dragTooltip);
+ });
+
it('should return broken symlink tooltip', () => {
expect(utils.addCommentTooltip({ commentsDisabled: { wasSymbolic: true } })).toEqual(
brokenSymLinkTooltip,
diff --git a/spec/frontend/diffs/components/diff_stats_spec.js b/spec/frontend/diffs/components/diff_stats_spec.js
index 0aaec027c0a..504158fb7fc 100644
--- a/spec/frontend/diffs/components/diff_stats_spec.js
+++ b/spec/frontend/diffs/components/diff_stats_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DiffStats from '~/diffs/components/diff_stats.vue';
const TEST_ADDED_LINES = 100;
diff --git a/spec/frontend/diffs/components/diff_view_spec.js b/spec/frontend/diffs/components/diff_view_spec.js
index 3d36ebf14a3..83b173c1f5d 100644
--- a/spec/frontend/diffs/components/diff_view_spec.js
+++ b/spec/frontend/diffs/components/diff_view_spec.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DiffView from '~/diffs/components/diff_view.vue';
@@ -55,12 +55,12 @@ describe('DiffView', () => {
});
it.each`
- type | side | container | sides | total
- ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {} }, right: { lineDraft: {} } }} | ${2}
- ${'parallel'} | ${'right'} | ${'.new'} | ${{ left: { lineDraft: {} }, right: { lineDraft: {} } }} | ${2}
- ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {} } }} | ${1}
- ${'inline'} | ${'right'} | ${'.new'} | ${{ right: { lineDraft: {} } }} | ${1}
- ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {} }, right: { lineDraft: {} } }} | ${1}
+ type | side | container | sides | total
+ ${'parallel'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2}
+ ${'parallel'} | ${'right'} | ${'.new'} | ${{ left: { lineDraft: {}, renderDiscussion: true }, right: { lineDraft: {}, renderDiscussion: true } }} | ${2}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true } }} | ${1}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true } }} | ${1}
+ ${'inline'} | ${'left'} | ${'.old'} | ${{ left: { lineDraft: {}, renderDiscussion: true } }} | ${1}
`(
'renders a $type comment row with comment cell on $side',
({ type, container, sides, total }) => {
diff --git a/spec/frontend/diffs/components/image_diff_overlay_spec.js b/spec/frontend/diffs/components/image_diff_overlay_spec.js
index 93c9b922fdd..47b144b2387 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 { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } 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';
diff --git a/spec/frontend/diffs/components/inline_diff_table_row_spec.js b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
index 21e7d7397a0..7e6f75ad6f8 100644
--- a/spec/frontend/diffs/components/inline_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
@@ -1,10 +1,10 @@
import { shallowMount } from '@vue/test-utils';
-import { createStore } from '~/mr_notes/stores';
-import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
-import diffFileMockData from '../mock_data/diff_file';
-import discussionsMockData from '../mock_data/diff_discussions';
import { mapInline } from '~/diffs/components/diff_row_utils';
+import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
+import { createStore } from '~/mr_notes/stores';
+import discussionsMockData from '../mock_data/diff_discussions';
+import diffFileMockData from '../mock_data/diff_file';
const TEST_USER_ID = 'abc123';
const TEST_USER = { id: TEST_USER_ID };
diff --git a/spec/frontend/diffs/components/inline_diff_view_spec.js b/spec/frontend/diffs/components/inline_diff_view_spec.js
index 6a1791509fd..27834804f77 100644
--- a/spec/frontend/diffs/components/inline_diff_view_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_view_spec.js
@@ -1,11 +1,11 @@
import '~/behaviors/markdown/render_gfm';
-import { mount } from '@vue/test-utils';
import { getByText } from '@testing-library/dom';
-import { createStore } from '~/mr_notes/stores';
-import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
+import { mount } from '@vue/test-utils';
import { mapInline } from '~/diffs/components/diff_row_utils';
-import diffFileMockData from '../mock_data/diff_file';
+import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
+import { createStore } from '~/mr_notes/stores';
import discussionsMockData from '../mock_data/diff_discussions';
+import diffFileMockData from '../mock_data/diff_file';
describe('InlineDiffView', () => {
let wrapper;
diff --git a/spec/frontend/diffs/components/no_changes_spec.js b/spec/frontend/diffs/components/no_changes_spec.js
index df9af51f9cf..164c58dc8e4 100644
--- a/spec/frontend/diffs/components/no_changes_spec.js
+++ b/spec/frontend/diffs/components/no_changes_spec.js
@@ -1,8 +1,8 @@
+import { GlButton } from '@gitlab/ui';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlButton } from '@gitlab/ui';
-import { createStore } from '~/mr_notes/stores';
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();
diff --git a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
index 445553706b7..dbe8303077d 100644
--- a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/mr_notes/stores';
-import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
-import { mapParallel } from '~/diffs/components/diff_row_utils';
-import diffFileMockData from '../mock_data/diff_file';
import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
+import { mapParallel } from '~/diffs/components/diff_row_utils';
+import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
+import { createStore } from '~/mr_notes/stores';
import discussionsMockData from '../mock_data/diff_discussions';
+import diffFileMockData from '../mock_data/diff_file';
describe('ParallelDiffTableRow', () => {
const mockDiffContent = {
diff --git a/spec/frontend/diffs/components/parallel_diff_view_spec.js b/spec/frontend/diffs/components/parallel_diff_view_spec.js
index 44ed303d0ef..452e1f58551 100644
--- a/spec/frontend/diffs/components/parallel_diff_view_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_view_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { createStore } from '~/mr_notes/stores';
-import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
+import Vuex from 'vuex';
import parallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
+import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
+import { createStore } from '~/mr_notes/stores';
import diffFileMockData from '../mock_data/diff_file';
let wrapper;
diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js
index fcb627c570a..99fa83b64f1 100644
--- a/spec/frontend/diffs/components/settings_dropdown_spec.js
+++ b/spec/frontend/diffs/components/settings_dropdown_spec.js
@@ -1,6 +1,5 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import diffModule from '~/diffs/store/modules';
import SettingsDropdown from '~/diffs/components/settings_dropdown.vue';
import {
EVT_VIEW_FILE_BY_FILE,
@@ -8,6 +7,7 @@ import {
INLINE_DIFF_VIEW_TYPE,
} from '~/diffs/constants';
import eventHub from '~/diffs/event_hub';
+import diffModule from '~/diffs/store/modules';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js
index 4666321e0c2..f316a9fdf01 100644
--- a/spec/frontend/diffs/components/tree_list_spec.js
+++ b/spec/frontend/diffs/components/tree_list_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import TreeList from '~/diffs/components/tree_list.vue';
import createStore from '~/diffs/store/modules';
import FileTree from '~/vue_shared/components/file_tree.vue';
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index 056ac23fcf7..ed3210ecfaf 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import Cookies from 'js-cookie';
-import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
+import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import {
DIFF_VIEW_COOKIE_NAME,
INLINE_DIFF_VIEW_TYPE,
@@ -52,14 +52,14 @@ import {
setFileByFile,
reviewFile,
} from '~/diffs/store/actions';
-import eventHub from '~/notes/event_hub';
import * as types from '~/diffs/store/mutation_types';
-import axios from '~/lib/utils/axios_utils';
import * as utils from '~/diffs/store/utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+import eventHub from '~/notes/event_hub';
import { diffMetadata } from '../mock_data/diff_metadata';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
diff --git a/spec/frontend/diffs/store/getters_spec.js b/spec/frontend/diffs/store/getters_spec.js
index 4d7f861ac22..04606b48662 100644
--- a/spec/frontend/diffs/store/getters_spec.js
+++ b/spec/frontend/diffs/store/getters_spec.js
@@ -1,6 +1,6 @@
+import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
import * as getters from '~/diffs/store/getters';
import state from '~/diffs/store/modules/diff_state';
-import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
import discussion from '../mock_data/diff_discussions';
describe('Diffs Module Getters', () => {
@@ -376,24 +376,62 @@ describe('Diffs Module Getters', () => {
});
});
- describe('fileReviews', () => {
- const file1 = { id: '123', file_identifier_hash: 'abc' };
- const file2 = { id: '098', file_identifier_hash: 'abc' };
+ describe('suggestionCommitMessage', () => {
+ beforeEach(() => {
+ Object.assign(localState, {
+ defaultSuggestionCommitMessage:
+ '%{branch_name}%{project_path}%{project_name}%{username}%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}',
+ branchName: 'branch',
+ projectPath: '/path',
+ projectName: 'name',
+ username: 'user',
+ userFullName: 'user userton',
+ });
+ });
it.each`
- reviews | files | fileReviews
- ${{}} | ${[file1, file2]} | ${[false, false]}
- ${{ abc: ['123'] }} | ${[file1, file2]} | ${[true, false]}
- ${{ abc: ['098'] }} | ${[file1, file2]} | ${[false, true]}
- ${{ def: ['123'] }} | ${[file1, file2]} | ${[false, false]}
- ${{ abc: ['123'], def: ['098'] }} | ${[]} | ${[]}
+ specialState | output
+ ${{}} | ${'branch/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ userFullName: null }} | ${'branch/pathnameuser%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ username: null }} | ${'branch/pathname%{username}user userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ projectName: null }} | ${'branch/path%{project_name}useruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ projectPath: null }} | ${'branch%{project_path}nameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ branchName: null }} | ${'%{branch_name}/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
`(
- 'returns $fileReviews based on the diff files in state and the existing reviews $reviews',
- ({ reviews, files, fileReviews }) => {
- localState.diffFiles = files;
- localState.mrReviews = reviews;
+ 'provides the correct "base" default commit message based on state ($specialState)',
+ ({ specialState, output }) => {
+ Object.assign(localState, specialState);
+
+ expect(getters.suggestionCommitMessage(localState)()).toBe(output);
+ },
+ );
- expect(getters.fileReviews(localState)).toStrictEqual(fileReviews);
+ it.each`
+ stateOverrides | output
+ ${{}} | ${'branch/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ user_full_name: null }} | ${'branch/pathnameuser%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ username: null }} | ${'branch/pathname%{username}user userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ project_name: null }} | ${'branch/path%{project_name}useruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ project_path: null }} | ${'branch%{project_path}nameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ ${{ branch_name: null }} | ${'%{branch_name}/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ `(
+ "properly overrides state values ($stateOverrides) if they're provided",
+ ({ stateOverrides, output }) => {
+ expect(getters.suggestionCommitMessage(localState)(stateOverrides)).toBe(output);
+ },
+ );
+
+ it.each`
+ providedValues | output
+ ${{ file_paths: 'path1, path2', suggestions_count: 1, files_count: 1 }} | ${'branch/pathnameuseruser usertonpath1, path211'}
+ ${{ suggestions_count: 1, files_count: 1 }} | ${'branch/pathnameuseruser userton%{file_paths}11'}
+ ${{ file_paths: 'path1, path2', files_count: 1 }} | ${'branch/pathnameuseruser usertonpath1, path2%{suggestions_count}1'}
+ ${{ file_paths: 'path1, path2', suggestions_count: 1 }} | ${'branch/pathnameuseruser usertonpath1, path21%{files_count}'}
+ ${{ something_unused: 'CrAzY TeXt' }} | ${'branch/pathnameuseruser userton%{file_paths}%{suggestions_count}%{files_count}'}
+ `(
+ "fills in any missing interpolations ($providedValues) when they're provided at the getter callsite",
+ ({ providedValues, output }) => {
+ expect(getters.suggestionCommitMessage(localState)(providedValues)).toBe(output);
},
);
});
diff --git a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
index f7954515422..dbef547c297 100644
--- a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
+++ b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
@@ -1,9 +1,9 @@
-import * as getters from '~/diffs/store/getters';
-import state from '~/diffs/store/modules/diff_state';
import {
DIFF_COMPARE_BASE_VERSION_INDEX,
DIFF_COMPARE_HEAD_VERSION_INDEX,
} from '~/diffs/constants';
+import * as getters from '~/diffs/store/getters';
+import state from '~/diffs/store/modules/diff_state';
import diffsMockData from '../mock_data/merge_request_diffs';
describe('Compare diff version dropdowns', () => {
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index 2c342d8e2a5..a8ae759e693 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -1,9 +1,9 @@
+import { INLINE_DIFF_VIEW_TYPE, INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
import createState from '~/diffs/store/modules/diff_state';
-import mutations from '~/diffs/store/mutations';
import * as types from '~/diffs/store/mutation_types';
-import { INLINE_DIFF_VIEW_TYPE, INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
-import diffFileMockData from '../mock_data/diff_file';
+import mutations from '~/diffs/store/mutations';
import * as utils from '~/diffs/store/utils';
+import diffFileMockData from '../mock_data/diff_file';
describe('DiffsStoreMutations', () => {
describe('SET_BASE_CONFIG', () => {
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index a19e5e91677..dcb58f7a380 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -1,5 +1,4 @@
import { clone } from 'lodash';
-import * as utils from '~/diffs/store/utils';
import {
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
@@ -12,10 +11,11 @@ import {
INLINE_DIFF_VIEW_TYPE,
INLINE_DIFF_LINES_KEY,
} from '~/diffs/constants';
+import * as utils from '~/diffs/store/utils';
import { MERGE_REQUEST_NOTEABLE_TYPE } from '~/notes/constants';
+import { noteableDataMock } from '../../notes/mock_data';
import diffFileMockData from '../mock_data/diff_file';
import { diffMetadata } from '../mock_data/diff_metadata';
-import { noteableDataMock } from '../../notes/mock_data';
const getDiffFileMock = () => JSON.parse(JSON.stringify(diffFileMockData));
const getDiffMetadataMock = () => JSON.parse(JSON.stringify(diffMetadata));
diff --git a/spec/frontend/diffs/utils/diff_file_spec.js b/spec/frontend/diffs/utils/diff_file_spec.js
index 2de8db28e71..c6cfdfced65 100644
--- a/spec/frontend/diffs/utils/diff_file_spec.js
+++ b/spec/frontend/diffs/utils/diff_file_spec.js
@@ -1,4 +1,4 @@
-import { prepareRawDiffFile } from '~/diffs/utils/diff_file';
+import { prepareRawDiffFile, getShortShaFromFile } from '~/diffs/utils/diff_file';
function getDiffFiles() {
const loadFull = 'namespace/project/-/merge_requests/12345/diff_for_path?file_identifier=abc';
@@ -143,4 +143,15 @@ describe('diff_file utilities', () => {
expect(preppedFile).not.toHaveProp('id');
});
});
+
+ describe('getShortShaFromFile', () => {
+ it.each`
+ response | cs
+ ${'12345678'} | ${'12345678abcdogcat'}
+ ${null} | ${undefined}
+ ${'hidogcat'} | ${'hidogcatmorethings'}
+ `('returns $response for a file with { content_sha: $cs }', ({ response, cs }) => {
+ expect(getShortShaFromFile({ content_sha: cs })).toBe(response);
+ });
+ });
});
diff --git a/spec/frontend/diffs/utils/file_reviews_spec.js b/spec/frontend/diffs/utils/file_reviews_spec.js
index 819426ee75f..a58c19a7245 100644
--- a/spec/frontend/diffs/utils/file_reviews_spec.js
+++ b/spec/frontend/diffs/utils/file_reviews_spec.js
@@ -5,6 +5,7 @@ import {
setReviewsForMergeRequest,
isFileReviewed,
markFileReview,
+ reviewStatuses,
reviewable,
} from '~/diffs/utils/file_reviews';
@@ -28,6 +29,39 @@ describe('File Review(s) utilities', () => {
localStorage.clear();
});
+ describe('isFileReviewed', () => {
+ it.each`
+ description | diffFile | fileReviews
+ ${'the file does not have an `id`'} | ${{ ...file, id: undefined }} | ${getDefaultReviews()}
+ ${'there are no reviews for the file'} | ${file} | ${{ ...getDefaultReviews(), abc: undefined }}
+ `('returns `false` if $description', ({ diffFile, fileReviews }) => {
+ expect(isFileReviewed(fileReviews, diffFile)).toBe(false);
+ });
+
+ it("returns `true` for a file if it's available in the provided reviews", () => {
+ expect(isFileReviewed(reviews, file)).toBe(true);
+ });
+ });
+
+ describe('reviewStatuses', () => {
+ const file1 = { id: '123', file_identifier_hash: 'abc' };
+ const file2 = { id: '098', file_identifier_hash: 'abc' };
+
+ it.each`
+ mrReviews | files | fileReviews
+ ${{}} | ${[file1, file2]} | ${[false, false]}
+ ${{ abc: ['123'] }} | ${[file1, file2]} | ${[true, false]}
+ ${{ abc: ['098'] }} | ${[file1, file2]} | ${[false, true]}
+ ${{ def: ['123'] }} | ${[file1, file2]} | ${[false, false]}
+ ${{ abc: ['123'], def: ['098'] }} | ${[]} | ${[]}
+ `(
+ 'returns $fileReviews based on the diff files in state and the existing reviews $reviews',
+ ({ mrReviews, files, fileReviews }) => {
+ expect(reviewStatuses(files, mrReviews)).toStrictEqual(fileReviews);
+ },
+ );
+ });
+
describe('getReviewsForMergeRequest', () => {
it('fetches the appropriate stored reviews from localStorage', () => {
getReviewsForMergeRequest(mrPath);
@@ -73,20 +107,6 @@ describe('File Review(s) utilities', () => {
});
});
- describe('isFileReviewed', () => {
- it.each`
- description | diffFile | fileReviews
- ${'the file does not have an `id`'} | ${{ ...file, id: undefined }} | ${getDefaultReviews()}
- ${'there are no reviews for the file'} | ${file} | ${{ ...getDefaultReviews(), abc: undefined }}
- `('returns `false` if $description', ({ diffFile, fileReviews }) => {
- expect(isFileReviewed(fileReviews, diffFile)).toBe(false);
- });
-
- it("returns `true` for a file if it's available in the provided reviews", () => {
- expect(isFileReviewed(reviews, file)).toBe(true);
- });
- });
-
describe('reviewable', () => {
it.each`
response | diffFile | description
diff --git a/spec/frontend/diffs/utils/preferences_spec.js b/spec/frontend/diffs/utils/preferences_spec.js
index a48db1d7512..b09db2c1003 100644
--- a/spec/frontend/diffs/utils/preferences_spec.js
+++ b/spec/frontend/diffs/utils/preferences_spec.js
@@ -1,12 +1,11 @@
import Cookies from 'js-cookie';
-import { getParameterValues } from '~/lib/utils/url_utility';
-
-import { fileByFile } from '~/diffs/utils/preferences';
import {
DIFF_FILE_BY_FILE_COOKIE_NAME,
DIFF_VIEW_FILE_BY_FILE,
DIFF_VIEW_ALL_FILES,
} from '~/diffs/constants';
+import { fileByFile } from '~/diffs/utils/preferences';
+import { getParameterValues } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility');
diff --git a/spec/frontend/diffs/utils/suggestions_spec.js b/spec/frontend/diffs/utils/suggestions_spec.js
new file mode 100644
index 00000000000..fbfe9cef857
--- /dev/null
+++ b/spec/frontend/diffs/utils/suggestions_spec.js
@@ -0,0 +1,15 @@
+import { computeSuggestionCommitMessage } from '~/diffs/utils/suggestions';
+
+describe('Diff Suggestions utilities', () => {
+ describe('computeSuggestionCommitMessage', () => {
+ it.each`
+ description | input | values | output
+ ${'makes the appropriate replacements'} | ${'%{foo} %{bar}'} | ${{ foo: 'foo', bar: 'bar' }} | ${'foo bar'}
+ ${"skips replacing values that aren't passed"} | ${'%{foo} %{bar}'} | ${{ foo: 'foo' }} | ${'foo %{bar}'}
+ ${'treats the number 0 as a valid value (not falsey)'} | ${'%{foo} %{bar}'} | ${{ foo: 'foo', bar: 0 }} | ${'foo 0'}
+ ${"works when the variables don't have any space between them"} | ${'%{foo}%{bar}'} | ${{ foo: 'foo', bar: 'bar' }} | ${'foobar'}
+ `('$description', ({ input, output, values }) => {
+ expect(computeSuggestionCommitMessage({ message: input, values })).toBe(output);
+ });
+ });
+});
diff --git a/spec/frontend/dirty_submit/dirty_submit_factory_spec.js b/spec/frontend/dirty_submit/dirty_submit_factory_spec.js
index 40843a68582..5822ccf861b 100644
--- a/spec/frontend/dirty_submit/dirty_submit_factory_spec.js
+++ b/spec/frontend/dirty_submit/dirty_submit_factory_spec.js
@@ -1,6 +1,6 @@
+import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
-import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
import { createForm } from './helper';
describe('DirtySubmitCollection', () => {
diff --git a/spec/frontend/droplab/drop_down_spec.js b/spec/frontend/droplab/drop_down_spec.js
index c1fbda6f211..dcdbbcd4ccf 100644
--- a/spec/frontend/droplab/drop_down_spec.js
+++ b/spec/frontend/droplab/drop_down_spec.js
@@ -1,6 +1,6 @@
+import { SELECTED_CLASS } from '~/droplab/constants';
import DropDown from '~/droplab/drop_down';
import utils from '~/droplab/utils';
-import { SELECTED_CLASS } from '~/droplab/constants';
describe('DropLab DropDown', () => {
let testContext;
diff --git a/spec/frontend/droplab/hook_spec.js b/spec/frontend/droplab/hook_spec.js
index 11488cab521..0b897a570f6 100644
--- a/spec/frontend/droplab/hook_spec.js
+++ b/spec/frontend/droplab/hook_spec.js
@@ -1,5 +1,5 @@
-import Hook from '~/droplab/hook';
import DropDown from '~/droplab/drop_down';
+import Hook from '~/droplab/hook';
jest.mock('~/droplab/drop_down', () => jest.fn());
diff --git a/spec/frontend/droplab/plugins/ajax_filter_spec.js b/spec/frontend/droplab/plugins/ajax_filter_spec.js
index d91884a60e5..d442d5cf416 100644
--- a/spec/frontend/droplab/plugins/ajax_filter_spec.js
+++ b/spec/frontend/droplab/plugins/ajax_filter_spec.js
@@ -1,5 +1,5 @@
-import AjaxCache from '~/lib/utils/ajax_cache';
import AjaxFilter from '~/droplab/plugins/ajax_filter';
+import AjaxCache from '~/lib/utils/ajax_cache';
describe('AjaxFilter', () => {
let dummyConfig;
diff --git a/spec/frontend/droplab/plugins/ajax_spec.js b/spec/frontend/droplab/plugins/ajax_spec.js
index 1d7576ce420..7c6452e8337 100644
--- a/spec/frontend/droplab/plugins/ajax_spec.js
+++ b/spec/frontend/droplab/plugins/ajax_spec.js
@@ -1,5 +1,5 @@
-import AjaxCache from '~/lib/utils/ajax_cache';
import Ajax from '~/droplab/plugins/ajax';
+import AjaxCache from '~/lib/utils/ajax_cache';
describe('Ajax', () => {
describe('preprocessing', () => {
diff --git a/spec/frontend/dropzone_input_spec.js b/spec/frontend/dropzone_input_spec.js
index 4cfc6478bd2..5e6ccbd7cda 100644
--- a/spec/frontend/dropzone_input_spec.js
+++ b/spec/frontend/dropzone_input_spec.js
@@ -1,9 +1,9 @@
import $ from 'jquery';
import mock from 'xhr-mock';
-import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-import dropzoneInput from '~/dropzone_input';
+import { TEST_HOST } from 'spec/test_constants';
import PasteMarkdownTable from '~/behaviors/markdown/paste_markdown_table';
+import dropzoneInput from '~/dropzone_input';
const TEST_FILE = new File([], 'somefile.jpg');
TEST_FILE.upload = {};
diff --git a/spec/frontend/editor/editor_ci_schema_ext_spec.js b/spec/frontend/editor/editor_ci_schema_ext_spec.js
index 9dd88aad7e6..17a9ae7335f 100644
--- a/spec/frontend/editor/editor_ci_schema_ext_spec.js
+++ b/spec/frontend/editor/editor_ci_schema_ext_spec.js
@@ -1,8 +1,8 @@
import { languages } from 'monaco-editor';
import { TEST_HOST } from 'helpers/test_constants';
+import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants';
import EditorLite from '~/editor/editor_lite';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
-import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants';
describe('~/editor/editor_ci_config_ext', () => {
const defaultBlobPath = '.gitlab-ci.yml';
diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js
index c3099997287..815457e012f 100644
--- a/spec/frontend/editor/editor_lite_spec.js
+++ b/spec/frontend/editor/editor_lite_spec.js
@@ -1,14 +1,21 @@
/* eslint-disable max-classes-per-file */
-import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
+import { editor as monacoEditor, languages as monacoLanguages } from 'monaco-editor';
import waitForPromises from 'helpers/wait_for_promises';
-import Editor from '~/editor/editor_lite';
+import {
+ EDITOR_LITE_INSTANCE_ERROR_NO_EL,
+ URI_PREFIX,
+ EDITOR_READY_EVENT,
+} from '~/editor/constants';
+import EditorLite from '~/editor/editor_lite';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
-import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from '~/editor/constants';
+import { joinPaths } from '~/lib/utils/url_utility';
describe('Base editor', () => {
let editorEl;
let editor;
+ let defaultArguments;
+ const blobOriginalContent = 'Foo Foo';
const blobContent = 'Foo Bar';
const blobPath = 'test.md';
const blobGlobalId = 'snippet_777';
@@ -17,15 +24,19 @@ describe('Base editor', () => {
beforeEach(() => {
setFixtures('<div id="editor" data-editor-loading></div>');
editorEl = document.getElementById('editor');
- editor = new Editor();
+ defaultArguments = { el: editorEl, blobPath, blobContent, blobGlobalId };
+ editor = new EditorLite();
});
afterEach(() => {
editor.dispose();
editorEl.remove();
+ monacoEditor.getModels().forEach((model) => {
+ model.dispose();
+ });
});
- const createUri = (...paths) => Uri.file([URI_PREFIX, ...paths].join('/'));
+ const uriFilePath = joinPaths('/', URI_PREFIX, blobGlobalId, blobPath);
it('initializes Editor with basic properties', () => {
expect(editor).toBeDefined();
@@ -38,76 +49,192 @@ describe('Base editor', () => {
expect(editorEl.dataset.editorLoading).toBeUndefined();
});
- describe('instance of the Editor', () => {
+ describe('instance of the Editor Lite', () => {
let modelSpy;
let instanceSpy;
- let setModel;
- let dispose;
+ const setModel = jest.fn();
+ const dispose = jest.fn();
+ const mockModelReturn = (res = fakeModel) => {
+ modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => res);
+ };
+ const mockDecorateInstance = (decorations = {}) => {
+ jest.spyOn(EditorLite, 'convertMonacoToELInstance').mockImplementation((inst) => {
+ return Object.assign(inst, decorations);
+ });
+ };
beforeEach(() => {
- setModel = jest.fn();
- dispose = jest.fn();
- modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => fakeModel);
- instanceSpy = jest.spyOn(monacoEditor, 'create').mockImplementation(() => ({
- setModel,
- dispose,
- onDidDispose: jest.fn(),
- }));
+ modelSpy = jest.spyOn(monacoEditor, 'createModel');
});
- it('throws an error if no dom element is supplied', () => {
- expect(() => {
- editor.createInstance();
- }).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
+ describe('instance of the Code Editor', () => {
+ beforeEach(() => {
+ instanceSpy = jest.spyOn(monacoEditor, 'create');
+ });
- expect(modelSpy).not.toHaveBeenCalled();
- expect(instanceSpy).not.toHaveBeenCalled();
- expect(setModel).not.toHaveBeenCalled();
- });
+ it('throws an error if no dom element is supplied', () => {
+ mockDecorateInstance();
+ expect(() => {
+ editor.createInstance();
+ }).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
- it('creates model to be supplied to Monaco editor', () => {
- editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId: '' });
+ expect(modelSpy).not.toHaveBeenCalled();
+ expect(instanceSpy).not.toHaveBeenCalled();
+ expect(EditorLite.convertMonacoToELInstance).not.toHaveBeenCalled();
+ });
- expect(modelSpy).toHaveBeenCalledWith(blobContent, undefined, createUri(blobPath));
- expect(setModel).toHaveBeenCalledWith(fakeModel);
- });
+ it('creates model to be supplied to Monaco editor', () => {
+ mockModelReturn();
+ mockDecorateInstance({
+ setModel,
+ });
+ editor.createInstance(defaultArguments);
- it('initializes the instance on a supplied DOM node', () => {
- editor.createInstance({ el: editorEl });
+ expect(modelSpy).toHaveBeenCalledWith(
+ blobContent,
+ undefined,
+ expect.objectContaining({
+ path: uriFilePath,
+ }),
+ );
+ expect(setModel).toHaveBeenCalledWith(fakeModel);
+ });
- expect(editor.editorEl).not.toBe(null);
- expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything());
- });
+ it('does not create a model automatically if model is passed as `null`', () => {
+ mockDecorateInstance({
+ setModel,
+ });
+ editor.createInstance({ ...defaultArguments, model: null });
+ expect(modelSpy).not.toHaveBeenCalled();
+ expect(setModel).not.toHaveBeenCalled();
+ });
- it('with blobGlobalId, creates model with id in uri', () => {
- editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId });
+ it('initializes the instance on a supplied DOM node', () => {
+ editor.createInstance({ el: editorEl });
- expect(modelSpy).toHaveBeenCalledWith(
- blobContent,
- undefined,
- createUri(blobGlobalId, blobPath),
- );
- });
+ expect(editor.editorEl).not.toBe(null);
+ expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything());
+ });
- it('initializes instance with passed properties', () => {
- const instanceOptions = {
- foo: 'bar',
- };
- editor.createInstance({
- el: editorEl,
- ...instanceOptions,
+ it('with blobGlobalId, creates model with the id in uri', () => {
+ editor.createInstance(defaultArguments);
+
+ expect(modelSpy).toHaveBeenCalledWith(
+ blobContent,
+ undefined,
+ expect.objectContaining({
+ path: uriFilePath,
+ }),
+ );
+ });
+
+ it('initializes instance with passed properties', () => {
+ const instanceOptions = {
+ foo: 'bar',
+ };
+ editor.createInstance({
+ el: editorEl,
+ ...instanceOptions,
+ });
+ expect(instanceSpy).toHaveBeenCalledWith(
+ editorEl,
+ expect.objectContaining(instanceOptions),
+ );
+ });
+
+ it('disposes instance when the global editor is disposed', () => {
+ mockDecorateInstance({
+ dispose,
+ });
+ editor.createInstance(defaultArguments);
+
+ expect(dispose).not.toHaveBeenCalled();
+
+ editor.dispose();
+
+ expect(dispose).toHaveBeenCalled();
+ });
+
+ it("removes the disposed instance from the global editor's storage and disposes the associated model", () => {
+ mockModelReturn();
+ mockDecorateInstance({
+ setModel,
+ });
+ const instance = editor.createInstance(defaultArguments);
+
+ expect(editor.instances).toHaveLength(1);
+ expect(fakeModel.dispose).not.toHaveBeenCalled();
+
+ instance.dispose();
+
+ expect(editor.instances).toHaveLength(0);
+ expect(fakeModel.dispose).toHaveBeenCalled();
});
- expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.objectContaining(instanceOptions));
});
- it('disposes instance when the editor is disposed', () => {
- editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId });
+ describe('instance of the Diff Editor', () => {
+ beforeEach(() => {
+ instanceSpy = jest.spyOn(monacoEditor, 'createDiffEditor');
+ });
- expect(dispose).not.toHaveBeenCalled();
+ it('Diff Editor goes through the normal path of Code Editor just with the flag ON', () => {
+ const spy = jest.spyOn(editor, 'createInstance').mockImplementation(() => {});
+ editor.createDiffInstance();
+ expect(spy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ isDiff: true,
+ }),
+ );
+ });
- editor.dispose();
+ it('initializes the instance on a supplied DOM node', () => {
+ const wrongInstanceSpy = jest.spyOn(monacoEditor, 'create').mockImplementation(() => ({}));
+ editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
+
+ expect(editor.editorEl).not.toBe(null);
+ expect(wrongInstanceSpy).not.toHaveBeenCalled();
+ expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything());
+ });
+
+ it('creates correct model for the Diff Editor', () => {
+ const instance = editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
+ const getDiffModelValue = (model) => instance.getModel()[model].getValue();
+
+ expect(modelSpy).toHaveBeenCalledTimes(2);
+ expect(modelSpy.mock.calls[0]).toEqual([
+ blobContent,
+ undefined,
+ expect.objectContaining({
+ path: uriFilePath,
+ }),
+ ]);
+ expect(modelSpy.mock.calls[1]).toEqual([blobOriginalContent, 'markdown']);
+ expect(getDiffModelValue('original')).toBe(blobOriginalContent);
+ expect(getDiffModelValue('modified')).toBe(blobContent);
+ });
- expect(dispose).toHaveBeenCalled();
+ it('correctly disposes the diff editor model', () => {
+ const modifiedModel = fakeModel;
+ const originalModel = { ...fakeModel };
+ mockDecorateInstance({
+ getModel: jest.fn().mockReturnValue({
+ original: originalModel,
+ modified: modifiedModel,
+ }),
+ });
+
+ const instance = editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
+
+ expect(editor.instances).toHaveLength(1);
+ expect(originalModel.dispose).not.toHaveBeenCalled();
+ expect(modifiedModel.dispose).not.toHaveBeenCalled();
+
+ instance.dispose();
+
+ expect(editor.instances).toHaveLength(0);
+ expect(originalModel.dispose).toHaveBeenCalled();
+ expect(modifiedModel.dispose).toHaveBeenCalled();
+ });
});
});
@@ -127,16 +254,14 @@ describe('Base editor', () => {
editorEl2 = document.getElementById('editor2');
inst1Args = {
el: editorEl1,
- blobGlobalId,
};
inst2Args = {
el: editorEl2,
blobContent,
blobPath,
- blobGlobalId,
};
- editor = new Editor();
+ editor = new EditorLite();
instanceSpy = jest.spyOn(monacoEditor, 'create');
});
@@ -166,8 +291,20 @@ describe('Base editor', () => {
expect(model1).not.toEqual(model2);
});
+ it('does not create a new model if a model for the path & globalId combo already exists', () => {
+ const modelSpy = jest.spyOn(monacoEditor, 'createModel');
+ inst1 = editor.createInstance({ ...inst2Args, blobGlobalId });
+ inst2 = editor.createInstance({ ...inst2Args, el: editorEl1, blobGlobalId });
+
+ const model1 = inst1.getModel();
+ const model2 = inst2.getModel();
+
+ expect(modelSpy).toHaveBeenCalledTimes(1);
+ expect(model1).toBe(model2);
+ });
+
it('shares global editor options among all instances', () => {
- editor = new Editor({
+ editor = new EditorLite({
readOnly: true,
});
@@ -179,7 +316,7 @@ describe('Base editor', () => {
});
it('allows overriding editor options on the instance level', () => {
- editor = new Editor({
+ editor = new EditorLite({
readOnly: true,
});
inst1 = editor.createInstance({
@@ -200,6 +337,7 @@ describe('Base editor', () => {
expect(monacoEditor.getModels()).toHaveLength(2);
inst1.dispose();
+
expect(inst1.getModel()).toBe(null);
expect(inst2.getModel()).not.toBe(null);
expect(editor.instances).toHaveLength(1);
@@ -402,19 +540,20 @@ describe('Base editor', () => {
el: editorEl,
blobPath,
blobContent,
- blobGlobalId,
extensions,
});
};
beforeEach(() => {
- editorExtensionSpy = jest.spyOn(Editor, 'pushToImportsArray').mockImplementation((arr) => {
- arr.push(
- Promise.resolve({
- default: {},
- }),
- );
- });
+ editorExtensionSpy = jest
+ .spyOn(EditorLite, 'pushToImportsArray')
+ .mockImplementation((arr) => {
+ arr.push(
+ Promise.resolve({
+ default: {},
+ }),
+ );
+ });
});
it.each([undefined, [], [''], ''])(
@@ -446,15 +585,20 @@ describe('Base editor', () => {
expect(editorExtensionSpy).toHaveBeenCalledWith(expect.any(Array), expectation);
});
- it('emits editor-ready event after all extensions were applied', async () => {
+ it('emits EDITOR_READY_EVENT event after all extensions were applied', async () => {
const calls = [];
const eventSpy = jest.fn().mockImplementation(() => {
calls.push('event');
});
- const useSpy = jest.spyOn(editor, 'use').mockImplementation(() => {
+ const useSpy = jest.fn().mockImplementation(() => {
calls.push('use');
});
- editorEl.addEventListener('editor-ready', eventSpy);
+ jest.spyOn(EditorLite, 'convertMonacoToELInstance').mockImplementation((inst) => {
+ const decoratedInstance = inst;
+ decoratedInstance.use = useSpy;
+ return decoratedInstance;
+ });
+ editorEl.addEventListener(EDITOR_READY_EVENT, eventSpy);
instance = instanceConstructor('foo, bar');
await waitForPromises();
expect(useSpy.mock.calls).toHaveLength(2);
@@ -487,12 +631,6 @@ describe('Base editor', () => {
expect(inst1.alpha()).toEqual(alphaRes);
expect(inst2.alpha()).toEqual(alphaRes);
});
-
- it('extends specific instance if it has been passed', () => {
- editor.use(AlphaExt, inst2);
- expect(inst1.alpha).toBeUndefined();
- expect(inst2.alpha()).toEqual(alphaRes);
- });
});
});
@@ -526,7 +664,7 @@ describe('Base editor', () => {
it('sets default syntax highlighting theme', () => {
const expectedTheme = themes.find((t) => t.name === DEFAULT_THEME);
- editor = new Editor();
+ editor = new EditorLite();
expect(themeDefineSpy).toHaveBeenCalledWith(DEFAULT_THEME, expectedTheme.data);
expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME);
@@ -538,7 +676,7 @@ describe('Base editor', () => {
expect(expectedTheme.name).not.toBe(DEFAULT_THEME);
window.gon.user_color_scheme = expectedTheme.name;
- editor = new Editor();
+ editor = new EditorLite();
expect(themeDefineSpy).toHaveBeenCalledWith(expectedTheme.name, expectedTheme.data);
expect(themeSetSpy).toHaveBeenCalledWith(expectedTheme.name);
@@ -549,7 +687,7 @@ describe('Base editor', () => {
const nonExistentTheme = { name };
window.gon.user_color_scheme = nonExistentTheme.name;
- editor = new Editor();
+ editor = new EditorLite();
expect(themeDefineSpy).not.toHaveBeenCalled();
expect(themeSetSpy).toHaveBeenCalledWith(DEFAULT_THEME);
diff --git a/spec/frontend/emoji/emoji_spec.js b/spec/frontend/emoji/emoji_spec.js
deleted file mode 100644
index feec445bc8d..00000000000
--- a/spec/frontend/emoji/emoji_spec.js
+++ /dev/null
@@ -1,476 +0,0 @@
-import { trimText } from 'helpers/text_helper';
-import { emojiFixtureMap, initEmojiMock, describeEmojiFields } from 'helpers/emoji';
-import { glEmojiTag, searchEmoji, getEmoji } from '~/emoji';
-import isEmojiUnicodeSupported, {
- isFlagEmoji,
- isRainbowFlagEmoji,
- isKeycapEmoji,
- isSkinToneComboEmoji,
- isHorceRacingSkinToneComboEmoji,
- isPersonZwjEmoji,
-} from '~/emoji/support/is_emoji_unicode_supported';
-
-const emptySupportMap = {
- personZwj: false,
- horseRacing: false,
- flag: false,
- skinToneModifier: false,
- '9.0': false,
- '8.0': false,
- '7.0': false,
- 6.1: false,
- '6.0': false,
- 5.2: false,
- 5.1: false,
- 4.1: false,
- '4.0': false,
- 3.2: false,
- '3.0': false,
- 1.1: false,
-};
-
-describe('gl_emoji', () => {
- let mock;
-
- beforeEach(async () => {
- mock = await initEmojiMock();
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('glEmojiTag', () => {
- it('bomb emoji', () => {
- const emojiKey = 'bomb';
- const markup = glEmojiTag(emojiFixtureMap[emojiKey].name);
-
- expect(trimText(markup)).toMatchInlineSnapshot(
- `"<gl-emoji data-name=\\"bomb\\"></gl-emoji>"`,
- );
- });
-
- it('bomb emoji with sprite fallback readiness', () => {
- const emojiKey = 'bomb';
- const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
- sprite: true,
- });
- expect(trimText(markup)).toMatchInlineSnapshot(
- `"<gl-emoji data-fallback-sprite-class=\\"emoji-bomb\\" data-name=\\"bomb\\"></gl-emoji>"`,
- );
- });
- });
-
- describe('isFlagEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isFlagEmoji('')).toBeFalsy();
- });
-
- it('should detect flag_ac', () => {
- expect(isFlagEmoji('🇦🇨')).toBeTruthy();
- });
-
- it('should detect flag_us', () => {
- expect(isFlagEmoji('🇺🇸')).toBeTruthy();
- });
-
- it('should detect flag_zw', () => {
- expect(isFlagEmoji('🇿🇼')).toBeTruthy();
- });
-
- it('should not detect flags', () => {
- expect(isFlagEmoji('ðŸŽ')).toBeFalsy();
- });
-
- it('should not detect triangular_flag_on_post', () => {
- expect(isFlagEmoji('🚩')).toBeFalsy();
- });
-
- it('should not detect single letter', () => {
- expect(isFlagEmoji('🇦')).toBeFalsy();
- });
-
- it('should not detect >2 letters', () => {
- expect(isFlagEmoji('🇦🇧🇨')).toBeFalsy();
- });
- });
-
- describe('isRainbowFlagEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isRainbowFlagEmoji('')).toBeFalsy();
- });
-
- it('should detect rainbow_flag', () => {
- expect(isRainbowFlagEmoji('ðŸ³ðŸŒˆ')).toBeTruthy();
- });
-
- it("should not detect flag_white on its' own", () => {
- expect(isRainbowFlagEmoji('ðŸ³')).toBeFalsy();
- });
-
- it("should not detect rainbow on its' own", () => {
- expect(isRainbowFlagEmoji('🌈')).toBeFalsy();
- });
-
- it('should not detect flag_white with something else', () => {
- expect(isRainbowFlagEmoji('ðŸ³ðŸ”µ')).toBeFalsy();
- });
- });
-
- describe('isKeycapEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isKeycapEmoji('')).toBeFalsy();
- });
-
- it('should detect one(keycap)', () => {
- expect(isKeycapEmoji('1ï¸âƒ£')).toBeTruthy();
- });
-
- it('should detect nine(keycap)', () => {
- expect(isKeycapEmoji('9ï¸âƒ£')).toBeTruthy();
- });
-
- it('should not detect ten(keycap)', () => {
- expect(isKeycapEmoji('🔟')).toBeFalsy();
- });
-
- it('should not detect hash(keycap)', () => {
- expect(isKeycapEmoji('#⃣')).toBeFalsy();
- });
- });
-
- describe('isSkinToneComboEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isSkinToneComboEmoji('')).toBeFalsy();
- });
-
- it('should detect hand_splayed_tone5', () => {
- expect(isSkinToneComboEmoji('ðŸ–ðŸ¿')).toBeTruthy();
- });
-
- it('should not detect hand_splayed', () => {
- expect(isSkinToneComboEmoji('ðŸ–')).toBeFalsy();
- });
-
- it('should detect lifter_tone1', () => {
- expect(isSkinToneComboEmoji('ðŸ‹ðŸ»')).toBeTruthy();
- });
-
- it('should not detect lifter', () => {
- expect(isSkinToneComboEmoji('ðŸ‹')).toBeFalsy();
- });
-
- it('should detect rowboat_tone4', () => {
- expect(isSkinToneComboEmoji('🚣ðŸ¾')).toBeTruthy();
- });
-
- it('should not detect rowboat', () => {
- expect(isSkinToneComboEmoji('🚣')).toBeFalsy();
- });
-
- it('should not detect individual tone emoji', () => {
- expect(isSkinToneComboEmoji('ðŸ»')).toBeFalsy();
- });
- });
-
- describe('isHorceRacingSkinToneComboEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isHorceRacingSkinToneComboEmoji('')).toBeFalsy();
- });
-
- it('should detect horse_racing_tone2', () => {
- expect(isHorceRacingSkinToneComboEmoji('ðŸ‡ðŸ¼')).toBeTruthy();
- });
-
- it('should not detect horse_racing', () => {
- expect(isHorceRacingSkinToneComboEmoji('ðŸ‡')).toBeFalsy();
- });
- });
-
- describe('isPersonZwjEmoji', () => {
- it('should gracefully handle empty string', () => {
- expect(isPersonZwjEmoji('')).toBeFalsy();
- });
-
- it('should detect couple_mm', () => {
- expect(isPersonZwjEmoji('👨â€â¤ï¸â€ðŸ‘¨')).toBeTruthy();
- });
-
- it('should not detect couple_with_heart', () => {
- expect(isPersonZwjEmoji('💑')).toBeFalsy();
- });
-
- it('should not detect couplekiss', () => {
- expect(isPersonZwjEmoji('ðŸ’')).toBeFalsy();
- });
-
- it('should detect family_mmb', () => {
- expect(isPersonZwjEmoji('👨â€ðŸ‘¨â€ðŸ‘¦')).toBeTruthy();
- });
-
- it('should detect family_mwgb', () => {
- expect(isPersonZwjEmoji('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦')).toBeTruthy();
- });
-
- it('should not detect family', () => {
- expect(isPersonZwjEmoji('👪')).toBeFalsy();
- });
-
- it('should detect kiss_ww', () => {
- expect(isPersonZwjEmoji('👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©')).toBeTruthy();
- });
-
- it('should not detect girl', () => {
- expect(isPersonZwjEmoji('👧')).toBeFalsy();
- });
-
- it('should not detect girl_tone5', () => {
- expect(isPersonZwjEmoji('👧ðŸ¿')).toBeFalsy();
- });
-
- it('should not detect man', () => {
- expect(isPersonZwjEmoji('👨')).toBeFalsy();
- });
-
- it('should not detect woman', () => {
- expect(isPersonZwjEmoji('👩')).toBeFalsy();
- });
- });
-
- describe('isEmojiUnicodeSupported', () => {
- it('should gracefully handle empty string with unicode support', () => {
- const isSupported = isEmojiUnicodeSupported({ '1.0': true }, '', '1.0');
-
- expect(isSupported).toBeTruthy();
- });
-
- it('should gracefully handle empty string without unicode support', () => {
- const isSupported = isEmojiUnicodeSupported({}, '', '1.0');
-
- expect(isSupported).toBeFalsy();
- });
-
- it('bomb(6.0) with 6.0 support', () => {
- const emojiKey = 'bomb';
- const unicodeSupportMap = { ...emptySupportMap, '6.0': true };
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeTruthy();
- });
-
- it('bomb(6.0) without 6.0 support', () => {
- const emojiKey = 'bomb';
- const unicodeSupportMap = emptySupportMap;
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
-
- it('bomb(6.0) without 6.0 but with 9.0 support', () => {
- const emojiKey = 'bomb';
- const unicodeSupportMap = { ...emptySupportMap, '9.0': true };
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
-
- it('construction_worker_tone5(8.0) without skin tone modifier support', () => {
- const emojiKey = 'construction_worker_tone5';
- const unicodeSupportMap = {
- ...emptySupportMap,
- skinToneModifier: false,
- '9.0': true,
- '8.0': true,
- '7.0': true,
- 6.1: true,
- '6.0': true,
- 5.2: true,
- 5.1: true,
- 4.1: true,
- '4.0': true,
- 3.2: true,
- '3.0': true,
- 1.1: true,
- };
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
-
- it('use native keycap on >=57 chrome', () => {
- const emojiKey = 'five';
- const unicodeSupportMap = {
- ...emptySupportMap,
- '3.0': true,
- meta: {
- isChrome: true,
- chromeVersion: 57,
- },
- };
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeTruthy();
- });
-
- it('fallback keycap on <57 chrome', () => {
- const emojiKey = 'five';
- const unicodeSupportMap = {
- ...emptySupportMap,
- '3.0': true,
- meta: {
- isChrome: true,
- chromeVersion: 50,
- },
- };
- const isSupported = isEmojiUnicodeSupported(
- unicodeSupportMap,
- emojiFixtureMap[emojiKey].moji,
- emojiFixtureMap[emojiKey].unicodeVersion,
- );
-
- expect(isSupported).toBeFalsy();
- });
- });
-
- describe('getEmoji', () => {
- const { grey_question } = emojiFixtureMap;
-
- describe('when query is undefined', () => {
- it('should return null by default', () => {
- expect(getEmoji()).toBe(null);
- });
-
- it('should return fallback emoji when fallback is true', () => {
- expect(getEmoji(undefined, true).name).toEqual(grey_question.name);
- });
- });
- });
-
- describe('searchEmoji', () => {
- const { atom, grey_question } = emojiFixtureMap;
- const search = (query, opts) => searchEmoji(query, opts).map(({ name }) => name);
- const mangle = (str) => str.slice(0, 1) + str.slice(-1);
- const partial = (str) => str.slice(0, 2);
-
- describe('with default options', () => {
- const subject = (query) => search(query);
-
- describeEmojiFields('with $field', ({ accessor }) => {
- it(`should match by lower case: ${accessor(atom)}`, () => {
- expect(subject(accessor(atom))).toContain(atom.name);
- });
-
- it(`should match by upper case: ${accessor(atom).toUpperCase()}`, () => {
- expect(subject(accessor(atom).toUpperCase())).toContain(atom.name);
- });
-
- it(`should not match by partial: ${mangle(accessor(atom))}`, () => {
- expect(subject(mangle(accessor(atom)))).not.toContain(atom.name);
- });
- });
-
- it(`should match by unicode value: ${atom.moji}`, () => {
- expect(subject(atom.moji)).toContain(atom.name);
- });
-
- it('should not return a fallback value', () => {
- expect(subject('foo bar baz')).toHaveLength(0);
- });
-
- it('should not return a fallback value when query is falsey', () => {
- expect(subject()).toHaveLength(0);
- });
- });
-
- describe('with fuzzy match', () => {
- const subject = (query) => search(query, { match: 'fuzzy' });
-
- describeEmojiFields('with $field', ({ accessor }) => {
- it(`should match by lower case: ${accessor(atom)}`, () => {
- expect(subject(accessor(atom))).toContain(atom.name);
- });
-
- it(`should match by upper case: ${accessor(atom).toUpperCase()}`, () => {
- expect(subject(accessor(atom).toUpperCase())).toContain(atom.name);
- });
-
- it(`should match by partial: ${mangle(accessor(atom))}`, () => {
- expect(subject(mangle(accessor(atom)))).toContain(atom.name);
- });
- });
- });
-
- describe('with contains match', () => {
- const subject = (query) => search(query, { match: 'contains' });
-
- describeEmojiFields('with $field', ({ accessor }) => {
- it(`should match by lower case: ${accessor(atom)}`, () => {
- expect(subject(accessor(atom))).toContain(atom.name);
- });
-
- it(`should match by upper case: ${accessor(atom).toUpperCase()}`, () => {
- expect(subject(accessor(atom).toUpperCase())).toContain(atom.name);
- });
-
- it(`should match by partial: ${partial(accessor(atom))}`, () => {
- expect(subject(partial(accessor(atom)))).toContain(atom.name);
- });
-
- it(`should not match by mangled: ${mangle(accessor(atom))}`, () => {
- expect(subject(mangle(accessor(atom)))).not.toContain(atom.name);
- });
- });
- });
-
- describe('with fallback', () => {
- const subject = (query) => search(query, { fallback: true });
-
- it.each`
- query
- ${'foo bar baz'} | ${undefined}
- `('should return a fallback value when given $query', ({ query }) => {
- expect(subject(query)).toContain(grey_question.name);
- });
- });
-
- describe('with name and alias fields', () => {
- const subject = (query) => search(query, { fields: ['name', 'alias'] });
-
- it(`should match by name: ${atom.name}`, () => {
- expect(subject(atom.name)).toContain(atom.name);
- });
-
- it(`should match by alias: ${atom.aliases[0]}`, () => {
- expect(subject(atom.aliases[0])).toContain(atom.name);
- });
-
- it(`should not match by description: ${atom.description}`, () => {
- expect(subject(atom.description)).not.toContain(atom.name);
- });
-
- it(`should not match by unicode value: ${atom.moji}`, () => {
- expect(subject(atom.moji)).not.toContain(atom.name);
- });
- });
- });
-});
diff --git a/spec/frontend/emoji/index_spec.js b/spec/frontend/emoji/index_spec.js
new file mode 100644
index 00000000000..1e6f5483160
--- /dev/null
+++ b/spec/frontend/emoji/index_spec.js
@@ -0,0 +1,623 @@
+import { emojiFixtureMap, mockEmojiData, initEmojiMock } from 'helpers/emoji';
+import { trimText } from 'helpers/text_helper';
+import { glEmojiTag, searchEmoji, getEmojiInfo, sortEmoji } from '~/emoji';
+import isEmojiUnicodeSupported, {
+ isFlagEmoji,
+ isRainbowFlagEmoji,
+ isKeycapEmoji,
+ isSkinToneComboEmoji,
+ isHorceRacingSkinToneComboEmoji,
+ isPersonZwjEmoji,
+} from '~/emoji/support/is_emoji_unicode_supported';
+
+const emptySupportMap = {
+ personZwj: false,
+ horseRacing: false,
+ flag: false,
+ skinToneModifier: false,
+ '9.0': false,
+ '8.0': false,
+ '7.0': false,
+ 6.1: false,
+ '6.0': false,
+ 5.2: false,
+ 5.1: false,
+ 4.1: false,
+ '4.0': false,
+ 3.2: false,
+ '3.0': false,
+ 1.1: false,
+};
+
+describe('emoji', () => {
+ let mock;
+
+ beforeEach(async () => {
+ mock = await initEmojiMock();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('glEmojiTag', () => {
+ it('bomb emoji', () => {
+ const emojiKey = 'bomb';
+ const markup = glEmojiTag(emojiKey);
+
+ expect(trimText(markup)).toMatchInlineSnapshot(
+ `"<gl-emoji data-name=\\"bomb\\"></gl-emoji>"`,
+ );
+ });
+
+ it('bomb emoji with sprite fallback readiness', () => {
+ const emojiKey = 'bomb';
+ const markup = glEmojiTag(emojiKey, {
+ sprite: true,
+ });
+ expect(trimText(markup)).toMatchInlineSnapshot(
+ `"<gl-emoji data-fallback-sprite-class=\\"emoji-bomb\\" data-name=\\"bomb\\"></gl-emoji>"`,
+ );
+ });
+ });
+
+ describe('isFlagEmoji', () => {
+ it('should gracefully handle empty string', () => {
+ expect(isFlagEmoji('')).toBeFalsy();
+ });
+
+ it('should detect flag_ac', () => {
+ expect(isFlagEmoji('🇦🇨')).toBeTruthy();
+ });
+
+ it('should detect flag_us', () => {
+ expect(isFlagEmoji('🇺🇸')).toBeTruthy();
+ });
+
+ it('should detect flag_zw', () => {
+ expect(isFlagEmoji('🇿🇼')).toBeTruthy();
+ });
+
+ it('should not detect flags', () => {
+ expect(isFlagEmoji('ðŸŽ')).toBeFalsy();
+ });
+
+ it('should not detect triangular_flag_on_post', () => {
+ expect(isFlagEmoji('🚩')).toBeFalsy();
+ });
+
+ it('should not detect single letter', () => {
+ expect(isFlagEmoji('🇦')).toBeFalsy();
+ });
+
+ it('should not detect >2 letters', () => {
+ expect(isFlagEmoji('🇦🇧🇨')).toBeFalsy();
+ });
+ });
+
+ describe('isRainbowFlagEmoji', () => {
+ it('should gracefully handle empty string', () => {
+ expect(isRainbowFlagEmoji('')).toBeFalsy();
+ });
+
+ it('should detect rainbow_flag', () => {
+ expect(isRainbowFlagEmoji('ðŸ³ðŸŒˆ')).toBeTruthy();
+ });
+
+ it("should not detect flag_white on its' own", () => {
+ expect(isRainbowFlagEmoji('ðŸ³')).toBeFalsy();
+ });
+
+ it("should not detect rainbow on its' own", () => {
+ expect(isRainbowFlagEmoji('🌈')).toBeFalsy();
+ });
+
+ it('should not detect flag_white with something else', () => {
+ expect(isRainbowFlagEmoji('ðŸ³ðŸ”µ')).toBeFalsy();
+ });
+ });
+
+ describe('isKeycapEmoji', () => {
+ it('should gracefully handle empty string', () => {
+ expect(isKeycapEmoji('')).toBeFalsy();
+ });
+
+ it('should detect one(keycap)', () => {
+ expect(isKeycapEmoji('1ï¸âƒ£')).toBeTruthy();
+ });
+
+ it('should detect nine(keycap)', () => {
+ expect(isKeycapEmoji('9ï¸âƒ£')).toBeTruthy();
+ });
+
+ it('should not detect ten(keycap)', () => {
+ expect(isKeycapEmoji('🔟')).toBeFalsy();
+ });
+
+ it('should not detect hash(keycap)', () => {
+ expect(isKeycapEmoji('#⃣')).toBeFalsy();
+ });
+ });
+
+ describe('isSkinToneComboEmoji', () => {
+ it('should gracefully handle empty string', () => {
+ expect(isSkinToneComboEmoji('')).toBeFalsy();
+ });
+
+ it('should detect hand_splayed_tone5', () => {
+ expect(isSkinToneComboEmoji('ðŸ–ðŸ¿')).toBeTruthy();
+ });
+
+ it('should not detect hand_splayed', () => {
+ expect(isSkinToneComboEmoji('ðŸ–')).toBeFalsy();
+ });
+
+ it('should detect lifter_tone1', () => {
+ expect(isSkinToneComboEmoji('ðŸ‹ðŸ»')).toBeTruthy();
+ });
+
+ it('should not detect lifter', () => {
+ expect(isSkinToneComboEmoji('ðŸ‹')).toBeFalsy();
+ });
+
+ it('should detect rowboat_tone4', () => {
+ expect(isSkinToneComboEmoji('🚣ðŸ¾')).toBeTruthy();
+ });
+
+ it('should not detect rowboat', () => {
+ expect(isSkinToneComboEmoji('🚣')).toBeFalsy();
+ });
+
+ it('should not detect individual tone emoji', () => {
+ expect(isSkinToneComboEmoji('ðŸ»')).toBeFalsy();
+ });
+ });
+
+ describe('isHorceRacingSkinToneComboEmoji', () => {
+ it('should gracefully handle empty string', () => {
+ expect(isHorceRacingSkinToneComboEmoji('')).toBeFalsy();
+ });
+
+ it('should detect horse_racing_tone2', () => {
+ expect(isHorceRacingSkinToneComboEmoji('ðŸ‡ðŸ¼')).toBeTruthy();
+ });
+
+ it('should not detect horse_racing', () => {
+ expect(isHorceRacingSkinToneComboEmoji('ðŸ‡')).toBeFalsy();
+ });
+ });
+
+ describe('isPersonZwjEmoji', () => {
+ it('should gracefully handle empty string', () => {
+ expect(isPersonZwjEmoji('')).toBeFalsy();
+ });
+
+ it('should detect couple_mm', () => {
+ expect(isPersonZwjEmoji('👨â€â¤ï¸â€ðŸ‘¨')).toBeTruthy();
+ });
+
+ it('should not detect couple_with_heart', () => {
+ expect(isPersonZwjEmoji('💑')).toBeFalsy();
+ });
+
+ it('should not detect couplekiss', () => {
+ expect(isPersonZwjEmoji('ðŸ’')).toBeFalsy();
+ });
+
+ it('should detect family_mmb', () => {
+ expect(isPersonZwjEmoji('👨â€ðŸ‘¨â€ðŸ‘¦')).toBeTruthy();
+ });
+
+ it('should detect family_mwgb', () => {
+ expect(isPersonZwjEmoji('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦')).toBeTruthy();
+ });
+
+ it('should not detect family', () => {
+ expect(isPersonZwjEmoji('👪')).toBeFalsy();
+ });
+
+ it('should detect kiss_ww', () => {
+ expect(isPersonZwjEmoji('👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©')).toBeTruthy();
+ });
+
+ it('should not detect girl', () => {
+ expect(isPersonZwjEmoji('👧')).toBeFalsy();
+ });
+
+ it('should not detect girl_tone5', () => {
+ expect(isPersonZwjEmoji('👧ðŸ¿')).toBeFalsy();
+ });
+
+ it('should not detect man', () => {
+ expect(isPersonZwjEmoji('👨')).toBeFalsy();
+ });
+
+ it('should not detect woman', () => {
+ expect(isPersonZwjEmoji('👩')).toBeFalsy();
+ });
+ });
+
+ describe('isEmojiUnicodeSupported', () => {
+ it('should gracefully handle empty string with unicode support', () => {
+ const isSupported = isEmojiUnicodeSupported({ '1.0': true }, '', '1.0');
+
+ expect(isSupported).toBeTruthy();
+ });
+
+ it('should gracefully handle empty string without unicode support', () => {
+ const isSupported = isEmojiUnicodeSupported({}, '', '1.0');
+
+ expect(isSupported).toBeFalsy();
+ });
+
+ it('bomb(6.0) with 6.0 support', () => {
+ const emojiKey = 'bomb';
+ const unicodeSupportMap = { ...emptySupportMap, '6.0': true };
+ const isSupported = isEmojiUnicodeSupported(
+ unicodeSupportMap,
+ emojiFixtureMap[emojiKey].moji,
+ emojiFixtureMap[emojiKey].unicodeVersion,
+ );
+
+ expect(isSupported).toBeTruthy();
+ });
+
+ it('bomb(6.0) without 6.0 support', () => {
+ const emojiKey = 'bomb';
+ const unicodeSupportMap = emptySupportMap;
+ const isSupported = isEmojiUnicodeSupported(
+ unicodeSupportMap,
+ emojiFixtureMap[emojiKey].moji,
+ emojiFixtureMap[emojiKey].unicodeVersion,
+ );
+
+ expect(isSupported).toBeFalsy();
+ });
+
+ it('bomb(6.0) without 6.0 but with 9.0 support', () => {
+ const emojiKey = 'bomb';
+ const unicodeSupportMap = { ...emptySupportMap, '9.0': true };
+ const isSupported = isEmojiUnicodeSupported(
+ unicodeSupportMap,
+ emojiFixtureMap[emojiKey].moji,
+ emojiFixtureMap[emojiKey].unicodeVersion,
+ );
+
+ expect(isSupported).toBeFalsy();
+ });
+
+ it('construction_worker_tone5(8.0) without skin tone modifier support', () => {
+ const emojiKey = 'construction_worker_tone5';
+ const unicodeSupportMap = {
+ ...emptySupportMap,
+ skinToneModifier: false,
+ '9.0': true,
+ '8.0': true,
+ '7.0': true,
+ 6.1: true,
+ '6.0': true,
+ 5.2: true,
+ 5.1: true,
+ 4.1: true,
+ '4.0': true,
+ 3.2: true,
+ '3.0': true,
+ 1.1: true,
+ };
+ const isSupported = isEmojiUnicodeSupported(
+ unicodeSupportMap,
+ emojiFixtureMap[emojiKey].moji,
+ emojiFixtureMap[emojiKey].unicodeVersion,
+ );
+
+ expect(isSupported).toBeFalsy();
+ });
+
+ it('use native keycap on >=57 chrome', () => {
+ const emojiKey = 'five';
+ const unicodeSupportMap = {
+ ...emptySupportMap,
+ '3.0': true,
+ meta: {
+ isChrome: true,
+ chromeVersion: 57,
+ },
+ };
+ const isSupported = isEmojiUnicodeSupported(
+ unicodeSupportMap,
+ emojiFixtureMap[emojiKey].moji,
+ emojiFixtureMap[emojiKey].unicodeVersion,
+ );
+
+ expect(isSupported).toBeTruthy();
+ });
+
+ it('fallback keycap on <57 chrome', () => {
+ const emojiKey = 'five';
+ const unicodeSupportMap = {
+ ...emptySupportMap,
+ '3.0': true,
+ meta: {
+ isChrome: true,
+ chromeVersion: 50,
+ },
+ };
+ const isSupported = isEmojiUnicodeSupported(
+ unicodeSupportMap,
+ emojiFixtureMap[emojiKey].moji,
+ emojiFixtureMap[emojiKey].unicodeVersion,
+ );
+
+ expect(isSupported).toBeFalsy();
+ });
+ });
+
+ describe('getEmojiInfo', () => {
+ it.each(['atom', 'five', 'black_heart'])("should return a correct emoji for '%s'", (name) => {
+ expect(getEmojiInfo(name)).toEqual(mockEmojiData[name]);
+ });
+
+ it('should return fallback emoji by default', () => {
+ expect(getEmojiInfo('atjs')).toEqual(mockEmojiData.grey_question);
+ });
+
+ it('should return null when fallback is false', () => {
+ expect(getEmojiInfo('atjs', false)).toBe(null);
+ });
+
+ describe('when query is undefined', () => {
+ it('should return fallback emoji by default', () => {
+ expect(getEmojiInfo()).toEqual(mockEmojiData.grey_question);
+ });
+
+ it('should return null when fallback is false', () => {
+ expect(getEmojiInfo(undefined, false)).toBe(null);
+ });
+ });
+ });
+
+ describe('searchEmoji', () => {
+ const emojiFixture = Object.keys(mockEmojiData).reduce((acc, k) => {
+ const { name, e, u, d } = mockEmojiData[k];
+ acc[k] = { name, e, u, d };
+
+ return acc;
+ }, {});
+
+ it.each([undefined, null, ''])("should return all emoji when the input is '%s'", (input) => {
+ const search = searchEmoji(input);
+
+ const expected = [
+ 'atom',
+ 'bomb',
+ 'construction_worker_tone5',
+ 'five',
+ 'grey_question',
+ 'black_heart',
+ 'heart',
+ 'custard',
+ 'star',
+ ].map((name) => {
+ return {
+ emoji: emojiFixture[name],
+ field: 'd',
+ fieldValue: emojiFixture[name].d,
+ score: 0,
+ };
+ });
+
+ expect(search).toEqual(expected);
+ });
+
+ it.each([
+ [
+ 'searching by unicode value',
+ 'âš›',
+ [
+ {
+ name: 'atom',
+ field: 'e',
+ fieldValue: 'atom',
+ score: 0,
+ },
+ ],
+ ],
+ [
+ 'searching by partial alias',
+ '_symbol',
+ [
+ {
+ name: 'atom',
+ field: 'alias',
+ fieldValue: 'atom_symbol',
+ score: 4,
+ },
+ ],
+ ],
+ [
+ 'searching by full alias',
+ 'atom_symbol',
+ [
+ {
+ name: 'atom',
+ field: 'alias',
+ fieldValue: 'atom_symbol',
+ score: 0,
+ },
+ ],
+ ],
+ ])('should return a correct result when %s', (_, query, searchResult) => {
+ const expected = searchResult.map((item) => {
+ const { field, score, fieldValue, name } = item;
+
+ return {
+ emoji: emojiFixture[name],
+ field,
+ fieldValue,
+ score,
+ };
+ });
+
+ expect(searchEmoji(query)).toEqual(expected);
+ });
+
+ it.each([
+ ['searching with a non-existing emoji name', 'asdf', []],
+ [
+ 'searching by full name',
+ 'atom',
+ [
+ {
+ name: 'atom',
+ field: 'd',
+ score: 0,
+ },
+ ],
+ ],
+
+ [
+ 'searching by full description',
+ 'atom symbol',
+ [
+ {
+ name: 'atom',
+ field: 'd',
+ score: 0,
+ },
+ ],
+ ],
+
+ [
+ 'searching by partial name',
+ 'question',
+ [
+ {
+ name: 'grey_question',
+ field: 'name',
+ score: 5,
+ },
+ ],
+ ],
+ [
+ 'searching by partial description',
+ 'ment',
+ [
+ {
+ name: 'grey_question',
+ field: 'd',
+ score: 24,
+ },
+ ],
+ ],
+ [
+ 'searching with query "heart"',
+ 'heart',
+ [
+ {
+ name: 'black_heart',
+ field: 'd',
+ score: 6,
+ },
+ {
+ name: 'heart',
+ field: 'name',
+ score: 0,
+ },
+ ],
+ ],
+ [
+ 'searching with query "HEART"',
+ 'HEART',
+ [
+ {
+ name: 'black_heart',
+ field: 'd',
+ score: 6,
+ },
+ {
+ name: 'heart',
+ field: 'name',
+ score: 0,
+ },
+ ],
+ ],
+ [
+ 'searching with query "star"',
+ 'star',
+ [
+ {
+ name: 'custard',
+ field: 'd',
+ score: 2,
+ },
+ {
+ name: 'star',
+ field: 'name',
+ score: 0,
+ },
+ ],
+ ],
+ ])('should return a correct result when %s', (_, query, searchResult) => {
+ const expected = searchResult.map((item) => {
+ const { field, score, name } = item;
+
+ return {
+ emoji: emojiFixture[name],
+ field,
+ fieldValue: emojiFixture[name][field],
+ score,
+ };
+ });
+
+ expect(searchEmoji(query)).toEqual(expected);
+ });
+ });
+
+ describe('sortEmoji', () => {
+ const testCases = [
+ [
+ 'should correctly sort by score',
+ [
+ { score: 10, fieldValue: '', emoji: { name: 'a' } },
+ { score: 5, fieldValue: '', emoji: { name: 'b' } },
+ { score: 0, fieldValue: '', emoji: { name: 'c' } },
+ ],
+ [
+ { score: 0, fieldValue: '', emoji: { name: 'c' } },
+ { score: 5, fieldValue: '', emoji: { name: 'b' } },
+ { score: 10, fieldValue: '', emoji: { name: 'a' } },
+ ],
+ ],
+ [
+ 'should correctly sort by fieldValue',
+ [
+ { score: 0, fieldValue: 'y', emoji: { name: 'b' } },
+ { score: 0, fieldValue: 'x', emoji: { name: 'a' } },
+ { score: 0, fieldValue: 'z', emoji: { name: 'c' } },
+ ],
+ [
+ { score: 0, fieldValue: 'x', emoji: { name: 'a' } },
+ { score: 0, fieldValue: 'y', emoji: { name: 'b' } },
+ { score: 0, fieldValue: 'z', emoji: { name: 'c' } },
+ ],
+ ],
+ [
+ 'should correctly sort by score and then by fieldValue (in order)',
+ [
+ { score: 5, fieldValue: 'y', emoji: { name: 'c' } },
+ { score: 0, fieldValue: 'z', emoji: { name: 'a' } },
+ { score: 5, fieldValue: 'x', emoji: { name: 'b' } },
+ ],
+ [
+ { score: 0, fieldValue: 'z', emoji: { name: 'a' } },
+ { score: 5, fieldValue: 'x', emoji: { name: 'b' } },
+ { score: 5, fieldValue: 'y', emoji: { name: 'c' } },
+ ],
+ ],
+ ];
+
+ it.each(testCases)('%s', (_, scoredItems, expected) => {
+ expect(sortEmoji(scoredItems)).toEqual(expected);
+ });
+ });
+});
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index c055702d832..d1bc11538a3 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -1,8 +1,12 @@
/* eslint-disable import/no-commonjs, max-classes-per-file */
const path = require('path');
-const { ErrorWithStack } = require('jest-util');
const JSDOMEnvironment = require('jest-environment-jsdom');
+const { ErrorWithStack } = require('jest-util');
+const {
+ setGlobalDateToFakeDate,
+ setGlobalDateToRealDate,
+} = require('./__helpers__/fake_date/fake_date');
const { TEST_HOST } = require('./__helpers__/test_constants');
const ROOT_PATH = path.resolve(__dirname, '../..');
@@ -12,6 +16,10 @@ class CustomEnvironment extends JSDOMEnvironment {
// Setup testURL so that window.location is setup properly
super({ ...config, testURL: TEST_HOST }, context);
+ // Fake the `Date` for `jsdom` which fixes things like document.cookie
+ // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39496#note_503084332
+ setGlobalDateToFakeDate();
+
Object.assign(context.console, {
error(...args) {
throw new ErrorWithStack(
@@ -69,6 +77,9 @@ class CustomEnvironment extends JSDOMEnvironment {
}
async teardown() {
+ // Reset `Date` so that Jest can report timing accurately *roll eyes*...
+ setGlobalDateToRealDate();
+
await new Promise(setImmediate);
if (this.rejectedPromises.length > 0) {
diff --git a/spec/frontend/environments/canary_ingress_spec.js b/spec/frontend/environments/canary_ingress_spec.js
index 3dd67de1369..6c7a786e652 100644
--- a/spec/frontend/environments/canary_ingress_spec.js
+++ b/spec/frontend/environments/canary_ingress_spec.js
@@ -1,8 +1,8 @@
-import { mount } from '@vue/test-utils';
import { GlDropdownItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { CANARY_UPDATE_MODAL } from '~/environments/constants';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
+import { CANARY_UPDATE_MODAL } from '~/environments/constants';
describe('/environments/components/canary_ingress.vue', () => {
let wrapper;
diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js
index d0b97cf2eda..c7129ee1320 100644
--- a/spec/frontend/environments/canary_update_modal_spec.js
+++ b/spec/frontend/environments/canary_update_modal_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlAlert, GlModal } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
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';
diff --git a/spec/frontend/environments/confirm_rollback_modal_spec.js b/spec/frontend/environments/confirm_rollback_modal_spec.js
index a1a22274e8f..8fb53579f96 100644
--- a/spec/frontend/environments/confirm_rollback_modal_spec.js
+++ b/spec/frontend/environments/confirm_rollback_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ConfirmRollbackModal from '~/environments/components/confirm_rollback_modal.vue';
import eventHub from '~/environments/event_hub';
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
index dbef03f99d8..53220341a62 100644
--- a/spec/frontend/environments/deploy_board_component_spec.js
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -1,8 +1,8 @@
import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
-import DeployBoard from '~/environments/components/deploy_board.vue';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
+import DeployBoard from '~/environments/components/deploy_board.vue';
import { deployBoardMockData, environment } from './mock_data';
const logsPath = `gitlab-org/gitlab-test/-/logs?environment_name=${environment.name}`;
diff --git a/spec/frontend/environments/enable_review_app_modal_spec.js b/spec/frontend/environments/enable_review_app_modal_spec.js
index 7ea49a6e1d0..f5063cff620 100644
--- a/spec/frontend/environments/enable_review_app_modal_spec.js
+++ b/spec/frontend/environments/enable_review_app_modal_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import EnableReviewAppButton from '~/environments/components/enable_review_app_modal.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
describe('Enable Review App Button', () => {
let wrapper;
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index 875a01c07ea..db78a6b0cdd 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -1,9 +1,9 @@
+import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import eventHub from '~/environments/event_hub';
import EnvironmentActions from '~/environments/components/environment_actions.vue';
+import eventHub from '~/environments/event_hub';
const scheduledJobAction = {
name: 'scheduled action',
diff --git a/spec/frontend/environments/environment_item_spec.js b/spec/frontend/environments/environment_item_spec.js
index bc692352103..09ab1223fd1 100644
--- a/spec/frontend/environments/environment_item_spec.js
+++ b/spec/frontend/environments/environment_item_spec.js
@@ -1,9 +1,9 @@
-import { cloneDeep } from 'lodash';
import { mount } from '@vue/test-utils';
+import { cloneDeep } from 'lodash';
import { format } from 'timeago.js';
+import DeleteComponent from '~/environments/components/environment_delete.vue';
import EnvironmentItem from '~/environments/components/environment_item.vue';
import PinComponent from '~/environments/components/environment_pin.vue';
-import DeleteComponent from '~/environments/components/environment_delete.vue';
import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
import { environment, folder, tableData } from './mock_data';
diff --git a/spec/frontend/environments/environment_monitoring_spec.js b/spec/frontend/environments/environment_monitoring_spec.js
index bbd49c04fb6..3a53b57c3c6 100644
--- a/spec/frontend/environments/environment_monitoring_spec.js
+++ b/spec/frontend/environments/environment_monitoring_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MonitoringComponent from '~/environments/components/environment_monitoring.vue';
describe('Monitoring Component', () => {
diff --git a/spec/frontend/environments/environment_pin_spec.js b/spec/frontend/environments/environment_pin_spec.js
index f48091adb44..5cdd52294b6 100644
--- a/spec/frontend/environments/environment_pin_spec.js
+++ b/spec/frontend/environments/environment_pin_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlIcon } from '@gitlab/ui';
-import eventHub from '~/environments/event_hub';
+import { shallowMount } from '@vue/test-utils';
import PinComponent from '~/environments/components/environment_pin.vue';
+import eventHub from '~/environments/event_hub';
describe('Pin Component', () => {
let wrapper;
diff --git a/spec/frontend/environments/environment_rollback_spec.js b/spec/frontend/environments/environment_rollback_spec.js
index fb62a096c3d..b6c3d436c18 100644
--- a/spec/frontend/environments/environment_rollback_spec.js
+++ b/spec/frontend/environments/environment_rollback_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
-import eventHub from '~/environments/event_hub';
+import { shallowMount, mount } from '@vue/test-utils';
import RollbackComponent from '~/environments/components/environment_rollback.vue';
+import eventHub from '~/environments/event_hub';
describe('Rollback Component', () => {
const retryUrl = 'https://gitlab.com/retry';
diff --git a/spec/frontend/environments/environment_stop_spec.js b/spec/frontend/environments/environment_stop_spec.js
index 1865403cdc4..dff444b79f3 100644
--- a/spec/frontend/environments/environment_stop_spec.js
+++ b/spec/frontend/environments/environment_stop_spec.js
@@ -1,6 +1,6 @@
-import $ from 'jquery';
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import $ from 'jquery';
import StopComponent from '~/environments/components/environment_stop.vue';
import eventHub from '~/environments/event_hub';
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index daef35bcf99..863c4526bb9 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils';
+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';
import eventHub from '~/environments/event_hub';
-import DeployBoard from '~/environments/components/deploy_board.vue';
-import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import { folder, deployBoardMockData } from './mock_data';
const eeOnlyProps = {
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index d6614e2fd2b..50d84b19ce8 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -1,11 +1,11 @@
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import EnableReviewAppModal from '~/environments/components/enable_review_app_modal.vue';
import Container from '~/environments/components/container.vue';
+import DeployBoard from '~/environments/components/deploy_board.vue';
import EmptyState from '~/environments/components/empty_state.vue';
+import EnableReviewAppModal from '~/environments/components/enable_review_app_modal.vue';
import EnvironmentsApp from '~/environments/components/environments_app.vue';
-import DeployBoard from '~/environments/components/deploy_board.vue';
import axios from '~/lib/utils/axios_utils';
import { environment, folder } from './mock_data';
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index 0b9e0008ed7..b469a855d23 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -1,5 +1,3 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import Vuex from 'vuex';
import {
GlButton,
GlLoadingIcon,
@@ -9,21 +7,23 @@ import {
GlAlert,
GlSprintf,
} from '@gitlab/ui';
-import { __ } from '~/locale';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import Stacktrace from '~/error_tracking/components/stacktrace.vue';
-import ErrorDetails from '~/error_tracking/components/error_details.vue';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import {
severityLevel,
severityLevelVariant,
errorStatus,
} from '~/error_tracking/components/constants';
-import Tracking from '~/tracking';
+import ErrorDetails from '~/error_tracking/components/error_details.vue';
+import Stacktrace from '~/error_tracking/components/stacktrace.vue';
import {
trackClickErrorLinkToSentryOptions,
trackErrorDetailsViewsOptions,
trackErrorStatusUpdateOptions,
} from '~/error_tracking/utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { __ } from '~/locale';
+import Tracking from '~/tracking';
jest.mock('~/flash');
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 05b3d2f1dec..e21c40423c3 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
describe('Error Tracking Actions', () => {
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 da12237b1d9..c6ce236af01 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -1,12 +1,12 @@
+import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination, GlDropdown } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination, GlDropdown } from '@gitlab/ui';
import stubChildren from 'helpers/stub_children';
-import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
+import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue';
import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '~/error_tracking/utils';
-import errorsList from './list_mock.json';
import Tracking from '~/tracking';
+import errorsList from './list_mock.json';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -298,9 +298,7 @@ describe('ErrorTrackingList', () => {
});
it('shows empty state', () => {
- expect(wrapper.find('a').attributes('href')).toBe(
- '/help/user/project/operations/error_tracking.html',
- );
+ expect(wrapper.find(GlEmptyState).isVisible()).toBe(true);
});
});
diff --git a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
index 6df25ad6819..0b43167c19b 100644
--- a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
+++ b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
import StackTraceEntry from '~/error_tracking/components/stacktrace_entry.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
diff --git a/spec/frontend/error_tracking/store/actions_spec.js b/spec/frontend/error_tracking/store/actions_spec.js
index 34ad600af05..9d598344acd 100644
--- a/spec/frontend/error_tracking/store/actions_spec.js
+++ b/spec/frontend/error_tracking/store/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import * as actions from '~/error_tracking/store/actions';
import * as types from '~/error_tracking/store/mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/flash.js');
diff --git a/spec/frontend/error_tracking/store/details/actions_spec.js b/spec/frontend/error_tracking/store/details/actions_spec.js
index 152ecde6985..0c19dce7bad 100644
--- a/spec/frontend/error_tracking/store/details/actions_spec.js
+++ b/spec/frontend/error_tracking/store/details/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import * as actions from '~/error_tracking/store/details/actions';
import * as types from '~/error_tracking/store/details/mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import Poll from '~/lib/utils/poll';
let mockedAdapter;
diff --git a/spec/frontend/error_tracking/store/list/actions_spec.js b/spec/frontend/error_tracking/store/list/actions_spec.js
index a93608fe70d..39481a8576f 100644
--- a/spec/frontend/error_tracking/store/list/actions_spec.js
+++ b/spec/frontend/error_tracking/store/list/actions_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import * as actions from '~/error_tracking/store/list/actions';
import * as types from '~/error_tracking/store/list/mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
jest.mock('~/flash.js');
diff --git a/spec/frontend/error_tracking/store/list/mutation_spec.js b/spec/frontend/error_tracking/store/list/mutation_spec.js
index a326a6c55c0..d28d3ecc79f 100644
--- a/spec/frontend/error_tracking/store/list/mutation_spec.js
+++ b/spec/frontend/error_tracking/store/list/mutation_spec.js
@@ -1,6 +1,6 @@
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
-import mutations from '~/error_tracking/store/list/mutations';
import * as types from '~/error_tracking/store/list/mutation_types';
+import mutations from '~/error_tracking/store/list/mutations';
const ADD_RECENT_SEARCH = mutations[types.ADD_RECENT_SEARCH];
const CLEAR_RECENT_SEARCHES = mutations[types.CLEAR_RECENT_SEARCHES];
diff --git a/spec/frontend/error_tracking_settings/components/app_spec.js b/spec/frontend/error_tracking_settings/components/app_spec.js
index 5c3efa24551..e0be81b3899 100644
--- a/spec/frontend/error_tracking_settings/components/app_spec.js
+++ b/spec/frontend/error_tracking_settings/components/app_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
import ErrorTrackingSettings from '~/error_tracking_settings/components/app.vue';
import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
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 e2a8b57f555..7ebaf0c3f2a 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,6 +1,6 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlFormInput, GlButton } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+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';
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 d924f895da8..79518a487d4 100644
--- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
+++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
@@ -1,7 +1,7 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import { pick, clone } from 'lodash';
import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
import { defaultProps, projectList, staleProject } from '../mock';
diff --git a/spec/frontend/error_tracking_settings/store/actions_spec.js b/spec/frontend/error_tracking_settings/store/actions_spec.js
index 216bf8011e8..281db7d9686 100644
--- a/spec/frontend/error_tracking_settings/store/actions_spec.js
+++ b/spec/frontend/error_tracking_settings/store/actions_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/error_tracking_settings/store/actions';
import * as types from '~/error_tracking_settings/store/mutation_types';
import defaultState from '~/error_tracking_settings/store/state';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { projectList } from '../mock';
jest.mock('~/lib/utils/url_utility');
diff --git a/spec/frontend/error_tracking_settings/store/mutation_spec.js b/spec/frontend/error_tracking_settings/store/mutation_spec.js
index fa188462c3f..78fd56904b3 100644
--- a/spec/frontend/error_tracking_settings/store/mutation_spec.js
+++ b/spec/frontend/error_tracking_settings/store/mutation_spec.js
@@ -1,7 +1,7 @@
import { TEST_HOST } from 'helpers/test_constants';
+import * as types from '~/error_tracking_settings/store/mutation_types';
import mutations from '~/error_tracking_settings/store/mutations';
import defaultState from '~/error_tracking_settings/store/state';
-import * as types from '~/error_tracking_settings/store/mutation_types';
import {
initialEmptyState,
initialPopulatedState,
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 21b894ccbef..84e71ffd204 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal, GlSprintf, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Component from '~/feature_flags/components/configure_feature_flags_modal.vue';
describe('Configure Feature Flags Modal', () => {
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 a754c682356..e2717b98ea9 100644
--- a/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
+++ b/spec/frontend/feature_flags/components/edit_feature_flag_spec.js
@@ -1,13 +1,13 @@
-import Vuex from 'vuex';
+import { GlToggle, GlAlert } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { GlToggle, GlAlert } from '@gitlab/ui';
-import { TEST_HOST } from 'spec/test_constants';
+import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
-import { LEGACY_FLAG, NEW_VERSION_FLAG } from '~/feature_flags/constants';
+import { TEST_HOST } from 'spec/test_constants';
+import EditFeatureFlag from '~/feature_flags/components/edit_feature_flag.vue';
import Form from '~/feature_flags/components/form.vue';
+import { LEGACY_FLAG, NEW_VERSION_FLAG } from '~/feature_flags/constants';
import createStore from '~/feature_flags/store/edit';
-import EditFeatureFlag from '~/feature_flags/components/edit_feature_flag.vue';
import axios from '~/lib/utils/axios_utils';
const localVue = createLocalVue();
@@ -75,6 +75,8 @@ describe('Edit feature flag form', () => {
});
const findAlert = () => wrapper.find(GlAlert);
+ const findWarningGlAlert = () =>
+ wrapper.findAll(GlAlert).filter((c) => c.props('variant') === 'warning');
it('should display the iid', () => {
expect(wrapper.find('h3').text()).toContain('^5');
@@ -88,7 +90,7 @@ describe('Edit feature flag form', () => {
expect(wrapper.find(GlToggle).props('value')).toBe(true);
});
- it('should not alert users that feature flags are changing soon', () => {
+ it('should alert users the flag is read only', () => {
expect(findAlert().text()).toContain('GitLab is moving to a new way of managing feature flags');
});
@@ -96,8 +98,9 @@ describe('Edit feature flag form', () => {
it('should render the error', () => {
store.dispatch('receiveUpdateFeatureFlagError', { message: ['The name is required'] });
return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.alert-danger').exists()).toEqual(true);
- expect(wrapper.find('.alert-danger').text()).toContain('The name is required');
+ const warningGlAlert = findWarningGlAlert();
+ expect(warningGlAlert.at(1).exists()).toEqual(true);
+ expect(warningGlAlert.at(1).text()).toContain('The name is required');
});
});
});
diff --git a/spec/frontend/feature_flags/components/environments_dropdown_spec.js b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
index 042fccaa369..9194db3a182 100644
--- a/spec/frontend/feature_flags/components/environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
@@ -1,8 +1,8 @@
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlButton, GlSearchBoxByType } from '@gitlab/ui';
-import { TEST_HOST } from 'spec/test_constants';
+import { shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
+import { TEST_HOST } from 'spec/test_constants';
import EnvironmentsDropdown from '~/feature_flags/components/environments_dropdown.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js
index 8242d667d2e..b519aab0dc4 100644
--- a/spec/frontend/feature_flags/components/feature_flags_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_spec.js
@@ -1,18 +1,18 @@
+import { GlAlert, GlEmptyState, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
import MockAdapter from 'axios-mock-adapter';
-import { GlAlert, GlEmptyState, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import Vuex from 'vuex';
import { TEST_HOST } from 'spec/test_constants';
import Api from '~/api';
-import createStore from '~/feature_flags/store/index';
-import FeatureFlagsTab from '~/feature_flags/components/feature_flags_tab.vue';
+import ConfigureFeatureFlagsModal from '~/feature_flags/components/configure_feature_flags_modal.vue';
import FeatureFlagsComponent from '~/feature_flags/components/feature_flags.vue';
+import FeatureFlagsTab from '~/feature_flags/components/feature_flags_tab.vue';
import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
import UserListsTable from '~/feature_flags/components/user_lists_table.vue';
-import ConfigureFeatureFlagsModal from '~/feature_flags/components/configure_feature_flags_modal.vue';
import { FEATURE_FLAG_SCOPE, USER_LIST_SCOPE } from '~/feature_flags/constants';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import createStore from '~/feature_flags/store/index';
import axios from '~/lib/utils/axios_utils';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import { getRequestData, userList } from '../mock_data';
const localVue = createLocalVue();
diff --git a/spec/frontend/feature_flags/components/feature_flags_tab_spec.js b/spec/frontend/feature_flags/components/feature_flags_tab_spec.js
index 23cc7045d1f..c2170e8a768 100644
--- a/spec/frontend/feature_flags/components/feature_flags_tab_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_tab_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlAlert, GlBadge, GlEmptyState, GlLink, GlLoadingIcon, GlTabs } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import FeatureFlagsTab from '~/feature_flags/components/feature_flags_tab.vue';
const DEFAULT_PROPS = {
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 8881cfae88d..8f4d39d4a11 100644
--- a/spec/frontend/feature_flags/components/feature_flags_table_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_table_spec.js
@@ -1,7 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlToggle, GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
import { mockTracking } from 'helpers/tracking_helper';
+import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
import {
ROLLOUT_STRATEGY_ALL_USERS,
ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
@@ -11,7 +12,6 @@ import {
LEGACY_FLAG,
DEFAULT_PERCENT_ROLLOUT,
} from '~/feature_flags/constants';
-import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
const getDefaultProps = () => ({
featureFlags: [
diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js
index 3a057aedde9..a05e23a4250 100644
--- a/spec/frontend/feature_flags/components/form_spec.js
+++ b/spec/frontend/feature_flags/components/form_spec.js
@@ -1,9 +1,10 @@
-import { uniqueId } from 'lodash';
+import { GlFormTextarea, GlFormCheckbox, GlButton, GlToggle } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormTextarea, GlFormCheckbox, GlButton } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Api from '~/api';
-import Form from '~/feature_flags/components/form.vue';
import EnvironmentsDropdown from '~/feature_flags/components/environments_dropdown.vue';
+import Form from '~/feature_flags/components/form.vue';
import Strategy from '~/feature_flags/components/strategy.vue';
import {
ROLLOUT_STRATEGY_ALL_USERS,
@@ -14,7 +15,6 @@ import {
NEW_VERSION_FLAG,
} from '~/feature_flags/constants';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
import { featureFlag, userList, allUsersStrategy } from '../mock_data';
jest.mock('~/api.js');
@@ -35,14 +35,19 @@ describe('feature flag form', () => {
},
};
+ const findAddNewScopeRow = () => wrapper.findByTestId('add-new-scope');
+ const findGlToggle = () => wrapper.find(GlToggle);
+
const factory = (props = {}, provide = {}) => {
- wrapper = shallowMount(Form, {
- propsData: { ...requiredProps, ...props },
- provide: {
- ...requiredInjections,
- ...provide,
- },
- });
+ wrapper = extendedWrapper(
+ shallowMount(Form, {
+ propsData: { ...requiredProps, ...props },
+ provide: {
+ ...requiredInjections,
+ ...provide,
+ },
+ }),
+ );
};
beforeEach(() => {
@@ -102,13 +107,13 @@ describe('feature flag form', () => {
});
it('should render scopes table with a new row ', () => {
- expect(wrapper.find('.js-add-new-scope').exists()).toBe(true);
+ expect(findAddNewScopeRow().exists()).toBe(true);
});
describe('status toggle', () => {
describe('without filled text input', () => {
it('should add a new scope with the text value empty and the status', () => {
- wrapper.find(ToggleButton).vm.$emit('change', true);
+ findGlToggle().vm.$emit('change', true);
expect(wrapper.vm.formScopes).toHaveLength(1);
expect(wrapper.vm.formScopes[0].active).toEqual(true);
@@ -121,7 +126,7 @@ describe('feature flag form', () => {
it('should be disabled if the feature flag is not active', (done) => {
wrapper.setProps({ active: false });
wrapper.vm.$nextTick(() => {
- expect(wrapper.find(ToggleButton).props('disabledInput')).toBe(true);
+ expect(findGlToggle().props('disabled')).toBe(true);
done();
});
});
@@ -166,11 +171,11 @@ describe('feature flag form', () => {
describe('scopes', () => {
it('should be possible to remove a scope', () => {
- expect(wrapper.find('.js-feature-flag-delete').exists()).toEqual(true);
+ expect(wrapper.findByTestId('feature-flag-delete').exists()).toEqual(true);
});
it('renders empty row to add a new scope', () => {
- expect(wrapper.find('.js-add-new-scope').exists()).toEqual(true);
+ expect(findAddNewScopeRow().exists()).toEqual(true);
});
it('renders the user id checkbox', () => {
@@ -186,7 +191,7 @@ describe('feature flag form', () => {
describe('update scope', () => {
describe('on click on toggle', () => {
it('should update the scope', () => {
- wrapper.find(ToggleButton).vm.$emit('change', false);
+ findGlToggle().vm.$emit('change', false);
expect(wrapper.vm.formScopes[0].active).toBe(false);
});
@@ -195,7 +200,7 @@ describe('feature flag form', () => {
wrapper.setProps({ active: false });
wrapper.vm.$nextTick(() => {
- expect(wrapper.find(ToggleButton).props('disabledInput')).toBe(true);
+ expect(findGlToggle().props('disabled')).toBe(true);
done();
});
});
@@ -294,7 +299,7 @@ describe('feature flag form', () => {
const row = wrapper.findAll('.gl-responsive-table-row').at(2);
expect(row.find(EnvironmentsDropdown).vm.disabled).toBe(true);
- expect(row.find(ToggleButton).vm.disabledInput).toBe(true);
+ expect(row.find(GlToggle).props('disabled')).toBe(true);
expect(row.find('.js-delete-scope').exists()).toBe(false);
});
});
@@ -347,10 +352,10 @@ describe('feature flag form', () => {
return wrapper.vm.$nextTick();
})
.then(() => {
- wrapper.find('.js-add-new-scope').find(ToggleButton).vm.$emit('change', true);
+ findAddNewScopeRow().find(GlToggle).vm.$emit('change', true);
})
.then(() => {
- wrapper.find(ToggleButton).vm.$emit('change', true);
+ findGlToggle().vm.$emit('change', true);
return wrapper.vm.$nextTick();
})
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 ad58ceaf5f8..6342ac0bda7 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,6 @@
+import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import NewEnvironmentsDropdown from '~/feature_flags/components/new_environments_dropdown.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
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 e317ac4b092..e209c14d8c7 100644
--- a/spec/frontend/feature_flags/components/new_feature_flag_spec.js
+++ b/spec/frontend/feature_flags/components/new_feature_flag_spec.js
@@ -1,11 +1,11 @@
+import { GlAlert } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlAlert } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants';
import Form from '~/feature_flags/components/form.vue';
-import createStore from '~/feature_flags/store/new';
import NewFeatureFlag from '~/feature_flags/components/new_feature_flag.vue';
import { ROLLOUT_STRATEGY_ALL_USERS, DEFAULT_PERCENT_ROLLOUT } from '~/feature_flags/constants';
+import createStore from '~/feature_flags/store/new';
import { allUsersStrategy } from '../mock_data';
const userCalloutId = 'feature_flags_new_version';
@@ -41,6 +41,9 @@ describe('New feature flag form', () => {
});
};
+ const findWarningGlAlert = () =>
+ wrapper.findAll(GlAlert).filter((c) => c.props('variant') === 'warning');
+
beforeEach(() => {
factory();
});
@@ -53,8 +56,9 @@ describe('New feature flag form', () => {
it('should render the error', () => {
store.dispatch('receiveCreateFeatureFlagError', { message: ['The name is required'] });
return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.alert').exists()).toEqual(true);
- expect(wrapper.find('.alert').text()).toContain('The name is required');
+ const warningGlAlert = findWarningGlAlert();
+ expect(warningGlAlert.at(0).exists()).toBe(true);
+ expect(warningGlAlert.at(0).text()).toContain('The name is required');
});
});
});
@@ -81,10 +85,6 @@ describe('New feature flag form', () => {
expect(wrapper.find(Form).props('scopes')).toContainEqual(defaultScope);
});
- it('should not alert users that feature flags are changing soon', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(false);
- });
-
it('has an all users strategy by default', () => {
const strategies = wrapper.find(Form).props('strategies');
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 725f53d4409..02216370b79 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,5 @@
-import { mount } from '@vue/test-utils';
import { GlFormInput, GlFormSelect } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
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';
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 1c85eadc678..6188672b23b 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,9 +1,9 @@
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import Api from '~/api';
-import createStore from '~/feature_flags/store/new';
import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue';
+import createStore from '~/feature_flags/store/new';
import { userListStrategy, userList } from '../../mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js b/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js
index a0ffdb1fca0..33696064d55 100644
--- a/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue';
describe('~/feature_flags/strategies/parameter_form_group.vue', () => {
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 696b3b2e4c9..442f7faf161 100644
--- a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
@@ -1,7 +1,7 @@
-import { mount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
-import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue';
+import { mount } from '@vue/test-utils';
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';
import { percentRolloutStrategy } from '../../mock_data';
diff --git a/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js b/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js
index 460df6ef2ec..745fbca00fe 100644
--- a/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlFormTextarea } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import UsersWithId from '~/feature_flags/components/strategies/users_with_id.vue';
import { usersWithIdStrategy } from '../../mock_data';
diff --git a/spec/frontend/feature_flags/components/strategy_parameters_spec.js b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
index 82811c05195..979ca255b08 100644
--- a/spec/frontend/feature_flags/components/strategy_parameters_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
@@ -1,16 +1,16 @@
import { shallowMount } from '@vue/test-utils';
import { last } from 'lodash';
+import Default from '~/feature_flags/components/strategies/default.vue';
+import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue';
+import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue';
+import UsersWithId from '~/feature_flags/components/strategies/users_with_id.vue';
+import StrategyParameters from '~/feature_flags/components/strategy_parameters.vue';
import {
ROLLOUT_STRATEGY_ALL_USERS,
ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
ROLLOUT_STRATEGY_USER_ID,
ROLLOUT_STRATEGY_GITLAB_USER_LIST,
} from '~/feature_flags/constants';
-import Default from '~/feature_flags/components/strategies/default.vue';
-import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue';
-import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue';
-import UsersWithId from '~/feature_flags/components/strategies/users_with_id.vue';
-import StrategyParameters from '~/feature_flags/components/strategy_parameters.vue';
import { allUsersStrategy } from '../mock_data';
const DEFAULT_PROPS = {
diff --git a/spec/frontend/feature_flags/components/strategy_spec.js b/spec/frontend/feature_flags/components/strategy_spec.js
index 67cf70c37e2..4fdf436bfc4 100644
--- a/spec/frontend/feature_flags/components/strategy_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_spec.js
@@ -1,9 +1,11 @@
+import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
import { last } from 'lodash';
-import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui';
+import Vuex from 'vuex';
import Api from '~/api';
-import createStore from '~/feature_flags/store/new';
+import NewEnvironmentsDropdown from '~/feature_flags/components/new_environments_dropdown.vue';
+import Strategy from '~/feature_flags/components/strategy.vue';
+import StrategyParameters from '~/feature_flags/components/strategy_parameters.vue';
import {
PERCENT_ROLLOUT_GROUP_ID,
ROLLOUT_STRATEGY_ALL_USERS,
@@ -12,9 +14,7 @@ import {
ROLLOUT_STRATEGY_USER_ID,
ROLLOUT_STRATEGY_GITLAB_USER_LIST,
} from '~/feature_flags/constants';
-import Strategy from '~/feature_flags/components/strategy.vue';
-import NewEnvironmentsDropdown from '~/feature_flags/components/new_environments_dropdown.vue';
-import StrategyParameters from '~/feature_flags/components/strategy_parameters.vue';
+import createStore from '~/feature_flags/store/new';
import { userList } from '../mock_data';
diff --git a/spec/frontend/feature_flags/components/user_lists_table_spec.js b/spec/frontend/feature_flags/components/user_lists_table_spec.js
index 974f63ba934..1b04ecee146 100644
--- a/spec/frontend/feature_flags/components/user_lists_table_spec.js
+++ b/spec/frontend/feature_flags/components/user_lists_table_spec.js
@@ -1,6 +1,6 @@
+import { GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import * as timeago from 'timeago.js';
-import { GlModal } from '@gitlab/ui';
import UserListsTable from '~/feature_flags/components/user_lists_table.vue';
import { userList } from '../mock_data';
diff --git a/spec/frontend/feature_flags/store/edit/actions_spec.js b/spec/frontend/feature_flags/store/edit/actions_spec.js
index 20cec5daac0..afcac53468c 100644
--- a/spec/frontend/feature_flags/store/edit/actions_spec.js
+++ b/spec/frontend/feature_flags/store/edit/actions_spec.js
@@ -2,6 +2,11 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
import {
+ NEW_VERSION_FLAG,
+ LEGACY_FLAG,
+ ROLLOUT_STRATEGY_ALL_USERS,
+} from '~/feature_flags/constants';
+import {
updateFeatureFlag,
requestUpdateFeatureFlag,
receiveUpdateFeatureFlagSuccess,
@@ -12,14 +17,9 @@ import {
receiveFeatureFlagError,
toggleActive,
} from '~/feature_flags/store/edit/actions';
+import * as types from '~/feature_flags/store/edit/mutation_types';
import state from '~/feature_flags/store/edit/state';
import { mapStrategiesToRails, mapFromScopesViewModel } from '~/feature_flags/store/helpers';
-import {
- NEW_VERSION_FLAG,
- LEGACY_FLAG,
- ROLLOUT_STRATEGY_ALL_USERS,
-} from '~/feature_flags/constants';
-import * as types from '~/feature_flags/store/edit/mutation_types';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/lib/utils/url_utility');
diff --git a/spec/frontend/feature_flags/store/edit/mutations_spec.js b/spec/frontend/feature_flags/store/edit/mutations_spec.js
index 1d817fb8004..4b43f8b82df 100644
--- a/spec/frontend/feature_flags/store/edit/mutations_spec.js
+++ b/spec/frontend/feature_flags/store/edit/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/feature_flags/store/edit/state';
-import mutations from '~/feature_flags/store/edit/mutations';
import * as types from '~/feature_flags/store/edit/mutation_types';
+import mutations from '~/feature_flags/store/edit/mutations';
+import state from '~/feature_flags/store/edit/state';
describe('Feature flags Edit Module Mutations', () => {
let stateCopy;
diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js
index aba578cca59..b4887d23e4b 100644
--- a/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js
+++ b/spec/frontend/feature_flags/store/gitlab_user_lists/actions_spec.js
@@ -1,8 +1,8 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import createState from '~/feature_flags/store/gitlab_user_list/state';
import { fetchUserLists, setFilter } from '~/feature_flags/store/gitlab_user_list/actions';
import * as types from '~/feature_flags/store/gitlab_user_list/mutation_types';
+import createState from '~/feature_flags/store/gitlab_user_list/state';
import { userList } from '../../mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js
index e267cd59f50..1f02cbb44a1 100644
--- a/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js
+++ b/spec/frontend/feature_flags/store/gitlab_user_lists/getters_spec.js
@@ -4,8 +4,8 @@ import {
isLoading,
hasError,
} from '~/feature_flags/store/gitlab_user_list/getters';
-import statuses from '~/feature_flags/store/gitlab_user_list/status';
import createState from '~/feature_flags/store/gitlab_user_list/state';
+import statuses from '~/feature_flags/store/gitlab_user_list/status';
import { userList } from '../../mock_data';
describe('~/feature_flags/store/gitlab_user_list/getters', () => {
diff --git a/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js b/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js
index 88d4554a227..46233c43b07 100644
--- a/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js
+++ b/spec/frontend/feature_flags/store/gitlab_user_lists/mutations_spec.js
@@ -1,7 +1,7 @@
-import statuses from '~/feature_flags/store/gitlab_user_list/status';
-import createState from '~/feature_flags/store/gitlab_user_list/state';
import * as types from '~/feature_flags/store/gitlab_user_list/mutation_types';
import mutations from '~/feature_flags/store/gitlab_user_list/mutations';
+import createState from '~/feature_flags/store/gitlab_user_list/state';
+import statuses from '~/feature_flags/store/gitlab_user_list/status';
import { userList } from '../../mock_data';
describe('~/feature_flags/store/gitlab_user_list/mutations', () => {
diff --git a/spec/frontend/feature_flags/store/helpers_spec.js b/spec/frontend/feature_flags/store/helpers_spec.js
index 301b1d09fcc..711e2a1286e 100644
--- a/spec/frontend/feature_flags/store/helpers_spec.js
+++ b/spec/frontend/feature_flags/store/helpers_spec.js
@@ -1,12 +1,5 @@
import { uniqueId } from 'lodash';
import {
- mapToScopesViewModel,
- mapFromScopesViewModel,
- createNewEnvironmentScope,
- mapStrategiesToViewModel,
- mapStrategiesToRails,
-} from '~/feature_flags/store/helpers';
-import {
ROLLOUT_STRATEGY_ALL_USERS,
ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
ROLLOUT_STRATEGY_USER_ID,
@@ -16,6 +9,13 @@ import {
LEGACY_FLAG,
NEW_VERSION_FLAG,
} from '~/feature_flags/constants';
+import {
+ mapToScopesViewModel,
+ mapFromScopesViewModel,
+ createNewEnvironmentScope,
+ mapStrategiesToViewModel,
+ mapStrategiesToRails,
+} from '~/feature_flags/store/helpers';
describe('feature flags helpers spec', () => {
describe('mapToScopesViewModel', () => {
diff --git a/spec/frontend/feature_flags/store/index/actions_spec.js b/spec/frontend/feature_flags/store/index/actions_spec.js
index 82e16958d33..a7ab2e92cb2 100644
--- a/spec/frontend/feature_flags/store/index/actions_spec.js
+++ b/spec/frontend/feature_flags/store/index/actions_spec.js
@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
import Api from '~/api';
+import { mapToScopesViewModel } from '~/feature_flags/store/helpers';
import {
requestFeatureFlags,
receiveFeatureFlagsSuccess,
@@ -24,9 +25,8 @@ import {
receiveDeleteUserListError,
clearAlert,
} from '~/feature_flags/store/index/actions';
-import { mapToScopesViewModel } from '~/feature_flags/store/helpers';
-import state from '~/feature_flags/store/index/state';
import * as types from '~/feature_flags/store/index/mutation_types';
+import state from '~/feature_flags/store/index/state';
import axios from '~/lib/utils/axios_utils';
import { getRequestData, rotateData, featureFlag, userList } from '../../mock_data';
diff --git a/spec/frontend/feature_flags/store/index/mutations_spec.js b/spec/frontend/feature_flags/store/index/mutations_spec.js
index eec56800a8d..08b5868d1b4 100644
--- a/spec/frontend/feature_flags/store/index/mutations_spec.js
+++ b/spec/frontend/feature_flags/store/index/mutations_spec.js
@@ -1,7 +1,7 @@
-import state from '~/feature_flags/store/index/state';
-import mutations from '~/feature_flags/store/index/mutations';
-import * as types from '~/feature_flags/store/index/mutation_types';
import { mapToScopesViewModel } from '~/feature_flags/store/helpers';
+import * as types from '~/feature_flags/store/index/mutation_types';
+import mutations from '~/feature_flags/store/index/mutations';
+import state from '~/feature_flags/store/index/state';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { getRequestData, rotateData, featureFlag, userList } from '../../mock_data';
diff --git a/spec/frontend/feature_flags/store/new/actions_spec.js b/spec/frontend/feature_flags/store/new/actions_spec.js
index 9168f11fdfb..00dfb982ded 100644
--- a/spec/frontend/feature_flags/store/new/actions_spec.js
+++ b/spec/frontend/feature_flags/store/new/actions_spec.js
@@ -2,20 +2,20 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
import {
- createFeatureFlag,
- requestCreateFeatureFlag,
- receiveCreateFeatureFlagSuccess,
- receiveCreateFeatureFlagError,
-} from '~/feature_flags/store/new/actions';
-import state from '~/feature_flags/store/new/state';
-import * as types from '~/feature_flags/store/new/mutation_types';
-import {
ROLLOUT_STRATEGY_ALL_USERS,
ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
LEGACY_FLAG,
NEW_VERSION_FLAG,
} from '~/feature_flags/constants';
import { mapFromScopesViewModel, mapStrategiesToRails } from '~/feature_flags/store/helpers';
+import {
+ createFeatureFlag,
+ requestCreateFeatureFlag,
+ receiveCreateFeatureFlagSuccess,
+ receiveCreateFeatureFlagError,
+} from '~/feature_flags/store/new/actions';
+import * as types from '~/feature_flags/store/new/mutation_types';
+import state from '~/feature_flags/store/new/state';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/lib/utils/url_utility');
diff --git a/spec/frontend/feature_flags/store/new/mutations_spec.js b/spec/frontend/feature_flags/store/new/mutations_spec.js
index e8609a6d116..c97e62247bb 100644
--- a/spec/frontend/feature_flags/store/new/mutations_spec.js
+++ b/spec/frontend/feature_flags/store/new/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/feature_flags/store/new/state';
-import mutations from '~/feature_flags/store/new/mutations';
import * as types from '~/feature_flags/store/new/mutation_types';
+import mutations from '~/feature_flags/store/new/mutations';
+import state from '~/feature_flags/store/new/state';
describe('Feature flags New Module Mutations', () => {
let stateCopy;
diff --git a/spec/frontend/feature_highlight/feature_highlight_helper_spec.js b/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
index beae5041156..1b5bffc1f9b 100644
--- a/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
+++ b/spec/frontend/feature_highlight/feature_highlight_helper_spec.js
@@ -1,62 +1,40 @@
-import $ from 'jquery';
+import MockAdapter from 'axios-mock-adapter';
+import { dismiss } from '~/feature_highlight/feature_highlight_helper';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { getSelector, dismiss, inserted } from '~/feature_highlight/feature_highlight_helper';
-import { togglePopover } from '~/shared/popover';
+import httpStatusCodes from '~/lib/utils/http_status';
-describe('feature highlight helper', () => {
- describe('getSelector', () => {
- it('returns js-feature-highlight selector', () => {
- const highlightId = 'highlightId';
-
- expect(getSelector(highlightId)).toEqual(
- `.js-feature-highlight[data-highlight=${highlightId}]`,
- );
- });
- });
+jest.mock('~/flash');
+describe('feature highlight helper', () => {
describe('dismiss', () => {
- const context = {
- hide: () => {},
- attr: () => '/-/callouts/dismiss',
- };
+ let mockAxios;
+ const endpoint = '/-/callouts/dismiss';
+ const highlightId = '123';
+ const { CREATED, INTERNAL_SERVER_ERROR } = httpStatusCodes;
beforeEach(() => {
- jest.spyOn(axios, 'post').mockResolvedValue();
- jest.spyOn(togglePopover, 'call').mockImplementation(() => {});
- jest.spyOn(context, 'hide').mockImplementation(() => {});
- dismiss.call(context);
+ mockAxios = new MockAdapter(axios);
});
- it('calls persistent dismissal endpoint', () => {
- expect(axios.post).toHaveBeenCalledWith(
- '/-/callouts/dismiss',
- expect.objectContaining({ feature_name: undefined }),
- );
+ afterEach(() => {
+ mockAxios.reset();
});
- it('calls hide popover', () => {
- expect(togglePopover.call).toHaveBeenCalledWith(context, false);
- });
+ it('calls persistent dismissal endpoint with highlightId', async () => {
+ mockAxios.onPost(endpoint, { feature_name: highlightId }).replyOnce(CREATED);
- it('calls hide', () => {
- expect(context.hide).toHaveBeenCalled();
+ await expect(dismiss(endpoint, highlightId)).resolves.toEqual(expect.anything());
});
- });
- describe('inserted', () => {
- it('registers click event callback', (done) => {
- const context = {
- getAttribute: () => 'popoverId',
- dataset: {
- highlight: 'some-feature',
- },
- };
-
- jest.spyOn($.fn, 'on').mockImplementation((event) => {
- expect(event).toEqual('click');
- done();
- });
- inserted.call(context);
+ it('triggers flash when dismiss request fails', async () => {
+ mockAxios.onPost(endpoint, { feature_name: highlightId }).replyOnce(INTERNAL_SERVER_ERROR);
+
+ await dismiss(endpoint, highlightId);
+
+ expect(Flash).toHaveBeenCalledWith(
+ 'An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.',
+ );
});
});
});
diff --git a/spec/frontend/feature_highlight/feature_highlight_options_spec.js b/spec/frontend/feature_highlight/feature_highlight_options_spec.js
deleted file mode 100644
index f82f984cb7f..00000000000
--- a/spec/frontend/feature_highlight/feature_highlight_options_spec.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import domContentLoaded from '~/feature_highlight/feature_highlight_options';
-
-describe('feature highlight options', () => {
- describe('domContentLoaded', () => {
- it.each`
- breakPoint | shouldCall
- ${'xs'} | ${false}
- ${'sm'} | ${false}
- ${'md'} | ${false}
- ${'lg'} | ${false}
- ${'xl'} | ${true}
- `(
- 'when breakpoint is $breakPoint should call highlightFeatures is $shouldCall',
- ({ breakPoint, shouldCall }) => {
- jest.spyOn(bp, 'getBreakpointSize').mockReturnValue(breakPoint);
-
- expect(domContentLoaded()).toBe(shouldCall);
- },
- );
- });
-});
diff --git a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
new file mode 100644
index 00000000000..1d558366ce8
--- /dev/null
+++ b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js
@@ -0,0 +1,80 @@
+import { GlPopover, GlLink, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+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';
+
+jest.mock('~/feature_highlight/feature_highlight_helper');
+
+describe('feature_highlight/feature_highlight_popover', () => {
+ let wrapper;
+ const props = {
+ autoDevopsHelpPath: '/help/autodevops',
+ highlightId: '123',
+ dismissEndpoint: '/api/dismiss',
+ };
+
+ const buildWrapper = (propsData = props) => {
+ wrapper = mount(FeatureHighlightPopover, {
+ propsData,
+ });
+ };
+ const findPopoverTarget = () => wrapper.find(`#${POPOVER_TARGET_ID}`);
+ const findPopover = () => wrapper.findComponent(GlPopover);
+ const findAutoDevopsHelpLink = () => wrapper.findComponent(GlLink);
+ const findDismissButton = () => wrapper.findComponent(GlButton);
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders popover target', () => {
+ expect(findPopoverTarget().exists()).toBe(true);
+ });
+
+ it('renders popover', () => {
+ expect(findPopover().props()).toMatchObject({
+ target: POPOVER_TARGET_ID,
+ cssClasses: ['feature-highlight-popover'],
+ triggers: 'hover',
+ container: 'body',
+ placement: 'right',
+ boundary: 'viewport',
+ });
+ });
+
+ it('renders link that points to the autodevops help page', () => {
+ expect(findAutoDevopsHelpLink().attributes().href).toBe(props.autoDevopsHelpPath);
+ expect(findAutoDevopsHelpLink().text()).toBe('Auto DevOps');
+ });
+
+ it('renders dismiss button', () => {
+ expect(findDismissButton().props()).toMatchObject({
+ size: 'small',
+ icon: 'thumb-up',
+ variant: 'confirm',
+ });
+ });
+
+ it('dismisses popover when dismiss button is clicked', async () => {
+ await findDismissButton().trigger('click');
+
+ expect(findPopover().emitted('close')).toHaveLength(1);
+ expect(dismiss).toHaveBeenCalledWith(props.dismissEndpoint, props.highlightId);
+ });
+
+ describe('when popover is dismissed and hidden', () => {
+ it('hides the popover target', async () => {
+ await findDismissButton().trigger('click');
+ findPopover().vm.$emit('hidden');
+ await wrapper.vm.$nextTick();
+
+ expect(findPopoverTarget().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/feature_highlight/feature_highlight_spec.js b/spec/frontend/feature_highlight/feature_highlight_spec.js
deleted file mode 100644
index 79c4050c8c4..00000000000
--- a/spec/frontend/feature_highlight/feature_highlight_spec.js
+++ /dev/null
@@ -1,120 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import * as featureHighlight from '~/feature_highlight/feature_highlight';
-import * as popover from '~/shared/popover';
-import axios from '~/lib/utils/axios_utils';
-
-jest.mock('~/shared/popover');
-
-describe('feature highlight', () => {
- beforeEach(() => {
- setFixtures(`
- <div>
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" data-dismiss-endpoint="/test" disabled>
- Trigger
- </div>
- </div>
- <div class="feature-highlight-popover-content">
- Content
- <div class="dismiss-feature-highlight">
- Dismiss
- </div>
- </div>
- `);
- });
-
- describe('setupFeatureHighlightPopover', () => {
- let mock;
- const selector = '.js-feature-highlight[data-highlight=test]';
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet('/test').reply(200);
- jest.spyOn(window, 'addEventListener').mockImplementation(() => {});
- featureHighlight.setupFeatureHighlightPopover('test', 0);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('setup popover content', () => {
- const $popoverContent = $('.feature-highlight-popover-content');
- const outerHTML = $popoverContent.prop('outerHTML');
-
- expect($(selector).data('content')).toEqual(outerHTML);
- });
-
- it('setup mouseenter', () => {
- $(selector).trigger('mouseenter');
-
- expect(popover.mouseenter).toHaveBeenCalledWith(expect.any(Object));
- });
-
- it('setup debounced mouseleave', () => {
- $(selector).trigger('mouseleave');
-
- expect(popover.debouncedMouseleave).toHaveBeenCalled();
- });
-
- it('setup show.bs.popover', () => {
- $(selector).trigger('show.bs.popover');
-
- expect(window.addEventListener).toHaveBeenCalledWith('scroll', expect.any(Function), {
- once: true,
- });
- });
-
- it('removes disabled attribute', () => {
- expect($('.js-feature-highlight').is(':disabled')).toEqual(false);
- });
- });
-
- describe('findHighestPriorityFeature', () => {
- beforeEach(() => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-high-priority" data-highlight-priority="20" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-low-priority" data-highlight-priority="0" disabled></div>
- `);
- });
-
- it('should pick the highest priority feature highlight', () => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-high-priority" data-highlight-priority="20" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-low-priority" data-highlight-priority="0" disabled></div>
- `);
-
- expect($('.js-feature-highlight').length).toBeGreaterThan(1);
- expect(featureHighlight.findHighestPriorityFeature()).toEqual('test-high-priority');
- });
-
- it('should work when no priority is set', () => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test" disabled></div>
- `);
-
- expect(featureHighlight.findHighestPriorityFeature()).toEqual('test');
- });
-
- it('should pick the highest priority feature highlight when some have no priority set', () => {
- setFixtures(`
- <div class="js-feature-highlight" data-highlight="test-no-priority1" disabled></div>
- <div class="js-feature-highlight" data-highlight="test" data-highlight-priority="10" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-no-priority2" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-high-priority" data-highlight-priority="20" disabled></div>
- <div class="js-feature-highlight" data-highlight="test-low-priority" data-highlight-priority="0" disabled></div>
- `);
-
- expect($('.js-feature-highlight').length).toBeGreaterThan(1);
- expect(featureHighlight.findHighestPriorityFeature()).toEqual('test-high-priority');
- });
- });
-
- describe('highlightFeatures', () => {
- it('calls setupFeatureHighlightPopover', () => {
- expect(featureHighlight.highlightFeatures()).toEqual('test');
- });
- });
-});
diff --git a/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js b/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js
index f1cff02261d..897ad5ee2bf 100644
--- a/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js
+++ b/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import eventHub from '~/filtered_search/event_hub';
import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content.vue';
+import eventHub from '~/filtered_search/event_hub';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
describe('Recent Searches Dropdown Content', () => {
diff --git a/spec/frontend/filtered_search/dropdown_user_spec.js b/spec/frontend/filtered_search/dropdown_user_spec.js
index c1c09ea5d3e..0e2d2ee6c09 100644
--- a/spec/frontend/filtered_search/dropdown_user_spec.js
+++ b/spec/frontend/filtered_search/dropdown_user_spec.js
@@ -1,4 +1,7 @@
import DropdownUtils from '~/filtered_search/dropdown_utils';
+// TODO: Moving this line up throws an error about `FilteredSearchDropdown`
+// being undefined in test. See gitlab-org/gitlab#321476 for more info.
+// eslint-disable-next-line import/order
import DropdownUser from '~/filtered_search/dropdown_user';
import FilteredSearchTokenizer from '~/filtered_search/filtered_search_tokenizer';
import IssuableFilteredTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
diff --git a/spec/frontend/filtered_search/filtered_search_manager_spec.js b/spec/frontend/filtered_search/filtered_search_manager_spec.js
index def0aa14349..465e1ee1ef1 100644
--- a/spec/frontend/filtered_search/filtered_search_manager_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_manager_spec.js
@@ -1,16 +1,16 @@
import FilteredSearchManager from 'ee_else_ce/filtered_search/filtered_search_manager';
import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
-import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
-import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import DropdownUtils from '~/filtered_search/dropdown_utils';
-import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
+import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
+import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
+import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
+import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
+import * as commonUtils from '~/lib/utils/common_utils';
import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes';
import { visitUrl } from '~/lib/utils/url_utility';
-import * as commonUtils from '~/lib/utils/common_utils';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
diff --git a/spec/frontend/filtered_search/filtered_search_tokenizer_spec.js b/spec/frontend/filtered_search/filtered_search_tokenizer_spec.js
index dec03e5ab93..b6a95eb55c7 100644
--- a/spec/frontend/filtered_search/filtered_search_tokenizer_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_tokenizer_spec.js
@@ -1,5 +1,5 @@
-import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import FilteredSearchTokenizer from '~/filtered_search/filtered_search_tokenizer';
+import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
describe('Filtered Search Tokenizer', () => {
const allowedKeys = IssuableFilteredSearchTokenKeys.getKeys();
diff --git a/spec/frontend/filtered_search/recent_searches_root_spec.js b/spec/frontend/filtered_search/recent_searches_root_spec.js
index 6bb9e68d591..fa3267c98a1 100644
--- a/spec/frontend/filtered_search/recent_searches_root_spec.js
+++ b/spec/frontend/filtered_search/recent_searches_root_spec.js
@@ -1,32 +1,51 @@
-import Vue from 'vue';
+import { setHTMLFixture } from 'helpers/fixtures';
import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
-jest.mock('vue');
+const containerId = 'test-container';
+const dropdownElementId = 'test-dropdown-element';
describe('RecentSearchesRoot', () => {
describe('render', () => {
- let recentSearchesRoot;
- let data;
- let template;
+ let recentSearchesRootMockInstance;
+ let vm;
+ let containerEl;
beforeEach(() => {
- recentSearchesRoot = {
+ setHTMLFixture(`
+ <div id="${containerId}">
+ <div id="${dropdownElementId}"></div>
+ </div>
+ `);
+
+ containerEl = document.getElementById(containerId);
+
+ recentSearchesRootMockInstance = {
store: {
- state: 'state',
+ state: {
+ recentSearches: ['foo', 'bar', 'qux'],
+ isLocalStorageAvailable: true,
+ allowedKeys: ['test'],
+ },
},
+ wrapperElement: document.getElementById(dropdownElementId),
};
- Vue.mockImplementation((options) => {
- ({ data, template } = options);
- });
+ RecentSearchesRoot.prototype.render.call(recentSearchesRootMockInstance);
+ vm = recentSearchesRootMockInstance.vm;
- RecentSearchesRoot.prototype.render.call(recentSearchesRoot);
+ return vm.$nextTick();
});
- it('should instantiate Vue', () => {
- expect(Vue).toHaveBeenCalled();
- expect(data()).toBe(recentSearchesRoot.store.state);
- expect(template).toContain(':is-local-storage-available="isLocalStorageAvailable"');
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render the recent searches', () => {
+ const { recentSearches } = recentSearchesRootMockInstance.store.state;
+
+ recentSearches.forEach((recentSearch) => {
+ expect(containerEl.textContent).toContain(recentSearch);
+ });
});
});
});
diff --git a/spec/frontend/filtered_search/visual_token_value_spec.js b/spec/frontend/filtered_search/visual_token_value_spec.js
index 2a76c4a27df..a2082271efe 100644
--- a/spec/frontend/filtered_search/visual_token_value_spec.js
+++ b/spec/frontend/filtered_search/visual_token_value_spec.js
@@ -1,10 +1,10 @@
import { escape } from 'lodash';
-import { TEST_HOST } from 'helpers/test_constants';
import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
+import { TEST_HOST } from 'helpers/test_constants';
+import DropdownUtils from '~/filtered_search//dropdown_utils';
import VisualTokenValue from '~/filtered_search/visual_token_value';
import AjaxCache from '~/lib/utils/ajax_cache';
import UsersCache from '~/lib/utils/users_cache';
-import DropdownUtils from '~/filtered_search//dropdown_utils';
describe('Filtered Search Visual Tokens', () => {
const findElements = (tokenElement) => {
diff --git a/spec/frontend/fixtures/api_merge_requests.rb b/spec/frontend/fixtures/api_merge_requests.rb
index f3280e216ff..7117c9a1c7a 100644
--- a/spec/frontend/fixtures/api_merge_requests.rb
+++ b/spec/frontend/fixtures/api_merge_requests.rb
@@ -6,9 +6,10 @@ RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
include ApiHelpers
include JavaScriptFixturesHelpers
- let(:admin) { create(:admin, name: 'root') }
- let(:namespace) { create(:namespace, name: 'gitlab-test' )}
- let(:project) { create(:project, :repository, namespace: namespace, path: 'lorem-ipsum') }
+ let_it_be(:admin) { create(:admin, name: 'root') }
+ let_it_be(:namespace) { create(:namespace, name: 'gitlab-test' )}
+ let_it_be(:project) { create(:project, :repository, namespace: namespace, path: 'lorem-ipsum') }
+ let_it_be(:mr) { create(:merge_request, source_project: project) }
before(:all) do
clean_frontend_fixtures('api/merge_requests')
@@ -21,4 +22,16 @@ RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
expect(response).to be_successful
end
+
+ it 'api/merge_requests/versions.json' do
+ get api("/projects/#{project.id}/merge_requests/#{mr.iid}/versions", admin)
+
+ expect(response).to be_successful
+ end
+
+ it 'api/merge_requests/changes.json' do
+ get api("/projects/#{project.id}/merge_requests/#{mr.iid}/changes", admin)
+
+ expect(response).to be_successful
+ end
end
diff --git a/spec/frontend/fixtures/merge_requests.rb b/spec/frontend/fixtures/merge_requests.rb
index acce3891ada..418912638f9 100644
--- a/spec/frontend/fixtures/merge_requests.rb
+++ b/spec/frontend/fixtures/merge_requests.rb
@@ -22,7 +22,6 @@ RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type:
let(:merge_request) do
create(
:merge_request,
- :with_diffs,
source_project: project,
target_project: project,
description: description
diff --git a/spec/frontend/fixtures/merge_requests_diffs.rb b/spec/frontend/fixtures/merge_requests_diffs.rb
index 6e07ef679f5..5ad4176f7b8 100644
--- a/spec/frontend/fixtures/merge_requests_diffs.rb
+++ b/spec/frontend/fixtures/merge_requests_diffs.rb
@@ -8,7 +8,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(:merge_request) { create(:merge_request, :with_diffs, source_project: project, target_project: project, description: '- [ ] Task List Item') }
+ 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
build(:text_diff_position, :added,
diff --git a/spec/frontend/fixtures/pipelines.rb b/spec/frontend/fixtures/pipelines.rb
index 4270e38afcb..b4b7f0e332f 100644
--- a/spec/frontend/fixtures/pipelines.rb
+++ b/spec/frontend/fixtures/pipelines.rb
@@ -12,7 +12,7 @@ RSpec.describe Projects::PipelinesController, '(JavaScript fixtures)', type: :co
let!(:user) { create(:user, developer_projects: [project], email: commit.author_email) }
let!(:pipeline) { create(:ci_pipeline, project: project, sha: commit.id, user: user) }
let!(:pipeline_without_author) { create(:ci_pipeline, project: project, sha: commit_without_author.id) }
- let!(:pipeline_without_commit) { create(:ci_pipeline, project: project, sha: '0000') }
+ let!(:pipeline_without_commit) { create(:ci_pipeline, status: :success, project: project, sha: '0000') }
render_views
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index b74e4ac45cf..80059c4c87f 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -1,15 +1,16 @@
import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { useRealDate } from 'helpers/fake_date';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import appComponent from '~/frequent_items/components/app.vue';
-import eventHub from '~/frequent_items/event_hub';
import { FREQUENT_ITEMS, HOUR_IN_MS } from '~/frequent_items/constants';
+import eventHub from '~/frequent_items/event_hub';
+import { createStore } from '~/frequent_items/store';
import { getTopFrequentItems } from '~/frequent_items/utils';
+import axios from '~/lib/utils/axios_utils';
import { currentSession, mockFrequentProjects, mockSearchedProjects } from '../mock_data';
-import { createStore } from '~/frequent_items/store';
useLocalStorageSpy();
@@ -93,23 +94,27 @@ describe('Frequent Items App Component', () => {
expect(projects.length).toBe(1);
});
- it('should increase frequency of report if it was logged multiple times over the course of an hour', () => {
- let projects;
- const newTimestamp = Date.now() + HOUR_IN_MS + 1;
+ describe('with real date', () => {
+ useRealDate();
- vm.logItemAccess(session.storageKey, session.project);
- projects = JSON.parse(storage[session.storageKey]);
+ it('should increase frequency of report if it was logged multiple times over the course of an hour', () => {
+ let projects;
+ const newTimestamp = Date.now() + HOUR_IN_MS + 1;
- expect(projects[0].frequency).toBe(1);
+ vm.logItemAccess(session.storageKey, session.project);
+ projects = JSON.parse(storage[session.storageKey]);
- vm.logItemAccess(session.storageKey, {
- ...session.project,
- lastAccessedOn: newTimestamp,
- });
- projects = JSON.parse(storage[session.storageKey]);
+ expect(projects[0].frequency).toBe(1);
+
+ vm.logItemAccess(session.storageKey, {
+ ...session.project,
+ lastAccessedOn: newTimestamp,
+ });
+ projects = JSON.parse(storage[session.storageKey]);
- expect(projects[0].frequency).toBe(2);
- expect(projects[0].lastAccessedOn).not.toBe(session.project.lastAccessedOn);
+ expect(projects[0].frequency).toBe(2);
+ expect(projects[0].lastAccessedOn).not.toBe(session.project.lastAccessedOn);
+ });
});
it('should always update project metadata', () => {
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 19095c4474e..66fb346cb38 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,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { trimText } from 'helpers/text_helper';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
import { createStore } from '~/frequent_items/store';
import { mockProject } from '../mock_data';
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 96f73ab1468..bd0711005b3 100644
--- a/spec/frontend/frequent_items/components/frequent_items_list_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
-import { createStore } from '~/frequent_items/store';
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';
describe('FrequentItemsListComponent', () => {
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 cdd8b127676..0280fdb0ca2 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,8 +1,8 @@
+import { GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import searchComponent from '~/frequent_items/components/frequent_items_search_input.vue';
import { createStore } from '~/frequent_items/store';
-import eventHub from '~/frequent_items/event_hub';
describe('FrequentItemsSearchInputComponent', () => {
let wrapper;
@@ -16,6 +16,8 @@ describe('FrequentItemsSearchInputComponent', () => {
propsData: { namespace },
});
+ const findSearchBoxByType = () => wrapper.find(GlSearchBoxByType);
+
beforeEach(() => {
store = createStore({ dropdownType: 'project' });
jest.spyOn(store, 'dispatch').mockImplementation(() => {});
@@ -33,59 +35,13 @@ describe('FrequentItemsSearchInputComponent', () => {
vm.$destroy();
});
- describe('methods', () => {
- describe('setFocus', () => {
- it('should set focus to search input', () => {
- jest.spyOn(vm.$refs.search, 'focus').mockImplementation(() => {});
-
- vm.setFocus();
-
- expect(vm.$refs.search.focus).toHaveBeenCalled();
- });
- });
- });
-
- describe('mounted', () => {
- it('should listen `dropdownOpen` event', (done) => {
- jest.spyOn(eventHub, '$on').mockImplementation(() => {});
- const vmX = createComponent().vm;
-
- vmX.$nextTick(() => {
- expect(eventHub.$on).toHaveBeenCalledWith(
- `${vmX.namespace}-dropdownOpen`,
- expect.any(Function),
- );
- done();
- });
- });
- });
-
- describe('beforeDestroy', () => {
- it('should unbind event listeners on eventHub', (done) => {
- const vmX = createComponent().vm;
- jest.spyOn(eventHub, '$off').mockImplementation(() => {});
-
- vmX.$mount();
- vmX.$destroy();
-
- vmX.$nextTick(() => {
- expect(eventHub.$off).toHaveBeenCalledWith(
- `${vmX.namespace}-dropdownOpen`,
- expect.any(Function),
- );
- done();
- });
- });
- });
-
describe('template', () => {
it('should render component element', () => {
expect(wrapper.classes()).toContain('search-input-container');
- expect(wrapper.find('input.form-control').exists()).toBe(true);
- expect(wrapper.find('.search-icon').exists()).toBe(true);
- expect(wrapper.find('input.form-control').attributes('placeholder')).toBe(
- 'Search your projects',
- );
+ expect(findSearchBoxByType().exists()).toBe(true);
+ expect(findSearchBoxByType().attributes()).toMatchObject({
+ placeholder: 'Search your projects',
+ });
});
});
@@ -96,9 +52,7 @@ describe('FrequentItemsSearchInputComponent', () => {
const value = 'my project';
- const input = wrapper.find('input');
- input.setValue(value);
- input.trigger('input');
+ findSearchBoxByType().vm.$emit('input', value);
await wrapper.vm.$nextTick();
diff --git a/spec/frontend/frequent_items/store/actions_spec.js b/spec/frontend/frequent_items/store/actions_spec.js
index 351fde25f49..dacfc7ce707 100644
--- a/spec/frontend/frequent_items/store/actions_spec.js
+++ b/spec/frontend/frequent_items/store/actions_spec.js
@@ -1,10 +1,10 @@
-import testAction from 'helpers/vuex_action_helper';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import AccessorUtilities from '~/lib/utils/accessor';
+import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/frequent_items/store/actions';
import * as types from '~/frequent_items/store/mutation_types';
import state from '~/frequent_items/store/state';
+import AccessorUtilities from '~/lib/utils/accessor';
+import axios from '~/lib/utils/axios_utils';
import {
mockNamespace,
mockStorageKey,
diff --git a/spec/frontend/frequent_items/store/getters_spec.js b/spec/frontend/frequent_items/store/getters_spec.js
index 1cd12eb6832..97732cd95fc 100644
--- a/spec/frontend/frequent_items/store/getters_spec.js
+++ b/spec/frontend/frequent_items/store/getters_spec.js
@@ -1,5 +1,5 @@
-import state from '~/frequent_items/store/state';
import * as getters from '~/frequent_items/store/getters';
+import state from '~/frequent_items/store/state';
describe('Frequent Items Dropdown Store Getters', () => {
let mockedState;
diff --git a/spec/frontend/frequent_items/store/mutations_spec.js b/spec/frontend/frequent_items/store/mutations_spec.js
index d36964b2600..e593c9fae58 100644
--- a/spec/frontend/frequent_items/store/mutations_spec.js
+++ b/spec/frontend/frequent_items/store/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/frequent_items/store/state';
-import mutations from '~/frequent_items/store/mutations';
import * as types from '~/frequent_items/store/mutation_types';
+import mutations from '~/frequent_items/store/mutations';
+import state from '~/frequent_items/store/state';
import {
mockNamespace,
mockStorageKey,
diff --git a/spec/frontend/frequent_items/utils_spec.js b/spec/frontend/frequent_items/utils_spec.js
index 181dd9268dc..a7ab18b0d10 100644
--- a/spec/frontend/frequent_items/utils_spec.js
+++ b/spec/frontend/frequent_items/utils_spec.js
@@ -1,11 +1,11 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import { HOUR_IN_MS, FREQUENT_ITEMS } from '~/frequent_items/constants';
import {
isMobile,
getTopFrequentItems,
updateExistingFrequentItem,
sanitizeItem,
} from '~/frequent_items/utils';
-import { HOUR_IN_MS, FREQUENT_ITEMS } from '~/frequent_items/constants';
import { mockProject, unsortedFrequentItems, sortedFrequentItems } from './mock_data';
describe('Frequent Items utils spec', () => {
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index c2ff66f6afc..08368e1f2ca 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -1,16 +1,12 @@
/* eslint no-param-reassign: "off" */
-
+import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
-import { emojiFixtureMap, initEmojiMock, describeEmojiFields } from 'helpers/emoji';
-import '~/lib/utils/jquery_at_who';
import GfmAutoComplete, { membersBeforeSave } from 'ee_else_ce/gfm_auto_complete';
-
-import { TEST_HOST } from 'helpers/test_constants';
+import { initEmojiMock } from 'helpers/emoji';
+import '~/lib/utils/jquery_at_who';
import { getJSONFixture } from 'helpers/fixtures';
-
+import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-
-import MockAdapter from 'axios-mock-adapter';
import AjaxCache from '~/lib/utils/ajax_cache';
import axios from '~/lib/utils/axios_utils';
@@ -493,7 +489,7 @@ describe('GfmAutoComplete', () => {
username: 'my-group',
avatarTag: '<div class="avatar rect-avatar center avatar-inline s26">M</div>',
title: 'My Group (2)',
- search: 'my-group My Group',
+ search: 'MyGroup my-group',
icon: '',
},
]);
@@ -506,7 +502,7 @@ describe('GfmAutoComplete', () => {
avatarTag:
'<img src="./group.jpg" alt="my-group" class="avatar rect-avatar avatar-inline center s26"/>',
title: 'My Group (2)',
- search: 'my-group My Group',
+ search: 'MyGroup my-group',
icon: '',
},
]);
@@ -519,7 +515,7 @@ describe('GfmAutoComplete', () => {
avatarTag:
'<img src="./group.jpg" alt="my-group" class="avatar rect-avatar avatar-inline center s26"/>',
title: 'My Group',
- search: 'my-group My Group',
+ search: 'MyGroup my-group',
icon:
'<svg class="s16 vertical-align-middle gl-ml-2"><use xlink:href="undefined#notifications-off" /></svg>',
},
@@ -537,7 +533,7 @@ describe('GfmAutoComplete', () => {
avatarTag:
'<img src="./users.jpg" alt="my-user" class="avatar avatar-inline center s26"/>',
title: 'My User',
- search: 'my-user My User',
+ search: 'MyUser my-user',
icon: '',
},
]);
@@ -717,16 +713,20 @@ describe('GfmAutoComplete', () => {
});
describe('emoji', () => {
- const { atom, heart, star } = emojiFixtureMap;
- const assertInserted = ({ input, subject, emoji }) =>
- expect(subject).toBe(`:${emoji?.name || input}:`);
- const assertTemplated = ({ input, subject, emoji, field }) =>
- expect(subject.replace(/\s+/g, ' ')).toBe(
- `<li>${field || input} <gl-emoji data-name="${emoji?.name || input}"></gl-emoji> </li>`,
- );
-
let mock;
+ const mockItem = {
+ 'atwho-at': ':',
+ emoji: {
+ c: 'symbols',
+ d: 'negative squared ab',
+ e: '🆎',
+ name: 'ab',
+ u: '6.0',
+ },
+ fieldValue: 'ab',
+ };
+
beforeEach(async () => {
mock = await initEmojiMock();
@@ -738,90 +738,22 @@ describe('GfmAutoComplete', () => {
mock.restore();
});
- describe.each`
- name | inputFormat | assert
- ${'insertTemplateFunction'} | ${(name) => ({ name })} | ${assertInserted}
- ${'templateFunction'} | ${(name) => name} | ${assertTemplated}
- `('Emoji.$name', ({ name, inputFormat, assert }) => {
- const execute = (accessor, input, emoji) =>
- assert({
- input,
- emoji,
- field: accessor && accessor(emoji),
- subject: GfmAutoComplete.Emoji[name](inputFormat(input)),
- });
-
- describeEmojiFields('for $field', ({ accessor }) => {
- it('should work with lowercase', () => {
- execute(accessor, accessor(atom), atom);
- });
-
- it('should work with uppercase', () => {
- execute(accessor, accessor(atom).toUpperCase(), atom);
- });
-
- it('should work with partial value', () => {
- execute(accessor, accessor(atom).slice(1), atom);
- });
- });
-
- it('should work with unicode value', () => {
- execute(null, atom.moji, atom);
- });
+ describe('Emoji.templateFunction', () => {
+ it('should return a correct template', () => {
+ const actual = GfmAutoComplete.Emoji.templateFunction(mockItem);
+ const glEmojiTag = `<gl-emoji data-name="${mockItem.emoji.name}"></gl-emoji>`;
+ const expected = `<li>${mockItem.fieldValue} ${glEmojiTag}</li>`;
- it('should pass through unknown value', () => {
- execute(null, 'foo bar baz');
+ expect(actual).toBe(expected);
});
});
- const expectEmojiOrder = (first, second) => {
- const keys = Object.keys(emojiFixtureMap);
- const firstIndex = keys.indexOf(first);
- const secondIndex = keys.indexOf(second);
- expect(firstIndex).toBeGreaterThanOrEqual(0);
- expect(secondIndex).toBeGreaterThanOrEqual(0);
- expect(firstIndex).toBeLessThan(secondIndex);
- };
-
describe('Emoji.insertTemplateFunction', () => {
- it('should map ":heart" to :heart: [regression]', () => {
- // the bug mapped heart to black_heart because the latter sorted first
- expectEmojiOrder('black_heart', 'heart');
-
- const item = GfmAutoComplete.Emoji.insertTemplateFunction({ name: 'heart' });
- expect(item).toEqual(`:${heart.name}:`);
- });
-
- it('should map ":star" to :star: [regression]', () => {
- // the bug mapped star to custard because the latter sorted first
- expectEmojiOrder('custard', 'star');
-
- const item = GfmAutoComplete.Emoji.insertTemplateFunction({ name: 'star' });
- expect(item).toEqual(`:${star.name}:`);
- });
- });
-
- describe('Emoji.templateFunction', () => {
- it('should map ":heart" to ⤠[regression]', () => {
- // the bug mapped heart to black_heart because the latter sorted first
- expectEmojiOrder('black_heart', 'heart');
-
- const item = GfmAutoComplete.Emoji.templateFunction('heart')
- .replace(/(<gl-emoji)\s+(data-name)/, '$1 $2')
- .replace(/>\s+|\s+</g, (s) => s.trim());
- expect(item).toEqual(
- `<li>${heart.name}<gl-emoji data-name="${heart.name}"></gl-emoji></li>`,
- );
- });
-
- it('should map ":star" to â­ [regression]', () => {
- // the bug mapped star to custard because the latter sorted first
- expectEmojiOrder('custard', 'star');
+ it('should return a correct template', () => {
+ const actual = GfmAutoComplete.Emoji.insertTemplateFunction(mockItem);
+ const expected = `:${mockItem.emoji.name}:`;
- const item = GfmAutoComplete.Emoji.templateFunction('star')
- .replace(/(<gl-emoji)\s+(data-name)/, '$1 $2')
- .replace(/>\s+|\s+</g, (s) => s.trim());
- expect(item).toEqual(`<li>${star.name}<gl-emoji data-name="${star.name}"></gl-emoji></li>`);
+ expect(actual).toBe(expected);
});
});
});
diff --git a/spec/frontend/gl_form_spec.js b/spec/frontend/gl_form_spec.js
index d9a01f7bcc1..07487fbb60e 100644
--- a/spec/frontend/gl_form_spec.js
+++ b/spec/frontend/gl_form_spec.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import autosize from 'autosize';
+import $ from 'jquery';
import GLForm from '~/gl_form';
import '~/lib/utils/text_utility';
import '~/lib/utils/common_utils';
diff --git a/spec/frontend/gpg_badges_spec.js b/spec/frontend/gpg_badges_spec.js
index 7c1f83e577c..cd2cc88fa5a 100644
--- a/spec/frontend/gpg_badges_spec.js
+++ b/spec/frontend/gpg_badges_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
import GpgBadges from '~/gpg_badges';
+import axios from '~/lib/utils/axios_utils';
describe('GpgBadges', () => {
let mock;
diff --git a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
index e880f585daa..0fc4343ec3c 100644
--- a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
+++ b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
@@ -8,13 +8,13 @@ exports[`grafana integration component default state to match the default snapsh
<div
class="settings-header"
>
- <h3
- class="js-section-header h4"
+ <h4
+ class="js-section-header"
>
Grafana authentication
- </h3>
+ </h4>
<gl-button-stub
buttontextclasses=""
diff --git a/spec/frontend/grafana_integration/components/grafana_integration_spec.js b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
index df88a336c09..ad1260d8030 100644
--- a/spec/frontend/grafana_integration/components/grafana_integration_spec.js
+++ b/spec/frontend/grafana_integration/components/grafana_integration_spec.js
@@ -1,11 +1,11 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import GrafanaIntegration from '~/grafana_integration/components/grafana_integration.vue';
import { createStore } from '~/grafana_integration/store';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/flash');
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 4ec739122c8..78950a8fe20 100644
--- a/spec/frontend/group_settings/components/shared_runners_form_spec.js
+++ b/spec/frontend/group_settings/components/shared_runners_form_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import SharedRunnersForm from '~/group_settings/components/shared_runners_form.vue';
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index 9244e4f331e..e559c9519f2 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -1,16 +1,16 @@
import '~/flash';
-import Vue from 'vue';
-import AxiosMockAdapter from 'axios-mock-adapter';
import { GlModal, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import appComponent from '~/groups/components/app.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
import groupItemComponent from '~/groups/components/group_item.vue';
import eventHub from '~/groups/event_hub';
-import GroupsStore from '~/groups/store/groups_store';
import GroupsService from '~/groups/service/groups_service';
+import GroupsStore from '~/groups/store/groups_store';
+import axios from '~/lib/utils/axios_utils';
import * as urlUtilities from '~/lib/utils/url_utility';
import {
@@ -60,8 +60,8 @@ describe('AppComponent', () => {
beforeEach(() => {
mock = new AxiosMockAdapter(axios);
mock.onGet('/dashboard/groups.json').reply(200, mockGroups);
- Vue.component('group-folder', groupFolderComponent);
- Vue.component('group-item', groupItemComponent);
+ Vue.component('GroupFolder', groupFolderComponent);
+ Vue.component('GroupItem', groupItemComponent);
createShallowComponent();
getGroupsSpy = jest.spyOn(vm.service, 'getGroups');
diff --git a/spec/frontend/groups/components/group_folder_spec.js b/spec/frontend/groups/components/group_folder_spec.js
index a40fa9bece8..1d8e10479b6 100644
--- a/spec/frontend/groups/components/group_folder_spec.js
+++ b/spec/frontend/groups/components/group_folder_spec.js
@@ -19,7 +19,7 @@ describe('GroupFolderComponent', () => {
let vm;
beforeEach(() => {
- Vue.component('group-item', groupItemComponent);
+ Vue.component('GroupItem', groupItemComponent);
vm = createComponent();
vm.$mount();
diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js
index d70ea709dee..4fcc9bafa46 100644
--- a/spec/frontend/groups/components/group_item_spec.js
+++ b/spec/frontend/groups/components/group_item_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import groupItemComponent from '~/groups/components/group_item.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
-import { getGroupItemMicrodata } from '~/groups/store/utils';
+import groupItemComponent from '~/groups/components/group_item.vue';
import eventHub from '~/groups/event_hub';
+import { getGroupItemMicrodata } from '~/groups/store/utils';
import * as urlUtilities from '~/lib/utils/url_utility';
import { mockParentGroupItem, mockChildren } from '../mock_data';
@@ -20,7 +20,7 @@ describe('GroupItemComponent', () => {
let vm;
beforeEach(() => {
- Vue.component('group-folder', groupFolderComponent);
+ Vue.component('GroupFolder', groupFolderComponent);
vm = createComponent();
diff --git a/spec/frontend/groups/components/groups_spec.js b/spec/frontend/groups/components/groups_spec.js
index 6205400eb03..dc1a10639fc 100644
--- a/spec/frontend/groups/components/groups_spec.js
+++ b/spec/frontend/groups/components/groups_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import groupsComponent from '~/groups/components/groups.vue';
import groupFolderComponent from '~/groups/components/group_folder.vue';
import groupItemComponent from '~/groups/components/group_item.vue';
+import groupsComponent from '~/groups/components/groups.vue';
import eventHub from '~/groups/event_hub';
import { mockGroups, mockPageInfo } from '../mock_data';
@@ -22,8 +22,8 @@ describe('GroupsComponent', () => {
let vm;
beforeEach(() => {
- Vue.component('group-folder', groupFolderComponent);
- Vue.component('group-item', groupItemComponent);
+ Vue.component('GroupFolder', groupFolderComponent);
+ Vue.component('GroupItem', groupItemComponent);
vm = createComponent();
diff --git a/spec/frontend/groups/components/invite_members_banner_spec.js b/spec/frontend/groups/components/invite_members_banner_spec.js
index 4e69f3cd433..9a2068a27a1 100644
--- a/spec/frontend/groups/components/invite_members_banner_spec.js
+++ b/spec/frontend/groups/components/invite_members_banner_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBanner, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
-import { setCookie, parseBoolean } from '~/lib/utils/common_utils';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
+import { setCookie, parseBoolean } from '~/lib/utils/common_utils';
jest.mock('~/lib/utils/common_utils');
diff --git a/spec/frontend/groups/components/item_actions_spec.js b/spec/frontend/groups/components/item_actions_spec.js
index 9adbc9abe13..ffbdf9b1aa6 100644
--- a/spec/frontend/groups/components/item_actions_spec.js
+++ b/spec/frontend/groups/components/item_actions_spec.js
@@ -66,6 +66,22 @@ describe('ItemActions', () => {
});
});
+ it('emits `showLeaveGroupModal` event with the correct prefix if `action` prop is passed', () => {
+ const group = {
+ ...mockParentGroupItem,
+ canEdit: true,
+ canLeave: true,
+ };
+ createComponent({
+ group,
+ action: 'test',
+ });
+ jest.spyOn(eventHub, '$emit');
+ findLeaveGroupBtn().vm.$emit('click', { stopPropagation: () => {} });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('testshowLeaveGroupModal', group, parentGroup);
+ });
+
it('does not render leave button if group can not be left', () => {
createComponent({
group: {
diff --git a/spec/frontend/groups/components/item_caret_spec.js b/spec/frontend/groups/components/item_caret_spec.js
index b2915607a06..cbe1f21d6e2 100644
--- a/spec/frontend/groups/components/item_caret_spec.js
+++ b/spec/frontend/groups/components/item_caret_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ItemCaret from '~/groups/components/item_caret.vue';
describe('ItemCaret', () => {
diff --git a/spec/frontend/groups/components/item_stats_value_spec.js b/spec/frontend/groups/components/item_stats_value_spec.js
index bca233883af..98186120a81 100644
--- a/spec/frontend/groups/components/item_stats_value_spec.js
+++ b/spec/frontend/groups/components/item_stats_value_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ItemStatsValue from '~/groups/components/item_stats_value.vue';
describe('ItemStatsValue', () => {
diff --git a/spec/frontend/groups/components/item_type_icon_spec.js b/spec/frontend/groups/components/item_type_icon_spec.js
index 5e7056be218..9310943841e 100644
--- a/spec/frontend/groups/components/item_type_icon_spec.js
+++ b/spec/frontend/groups/components/item_type_icon_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ItemTypeIcon from '~/groups/components/item_type_icon.vue';
import { ITEM_TYPE } from '../mock_data';
diff --git a/spec/frontend/groups/members/components/app_spec.js b/spec/frontend/groups/members/components/app_spec.js
deleted file mode 100644
index 9847dacbec8..00000000000
--- a/spec/frontend/groups/members/components/app_spec.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import Vuex from 'vuex';
-import { GlAlert } from '@gitlab/ui';
-import App from '~/groups/members/components/app.vue';
-import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
-import * as commonUtils from '~/lib/utils/common_utils';
-import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_types';
-import mutations from '~/members/store/mutations';
-
-describe('GroupMembersApp', () => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
-
- let wrapper;
- let store;
-
- const createComponent = (state = {}, options = {}) => {
- store = new Vuex.Store({
- state: {
- showError: true,
- errorMessage: 'Something went wrong, please try again.',
- ...state,
- },
- mutations,
- });
-
- wrapper = shallowMount(App, {
- localVue,
- store,
- ...options,
- });
- };
-
- const findAlert = () => wrapper.find(GlAlert);
- const findFilterSortContainer = () => wrapper.find(FilterSortContainer);
-
- beforeEach(() => {
- commonUtils.scrollToElement = jest.fn();
- });
-
- afterEach(() => {
- wrapper.destroy();
- store = null;
- });
-
- describe('when `showError` is changed to `true`', () => {
- it('renders and scrolls to error alert', async () => {
- createComponent({ showError: false, errorMessage: '' });
-
- store.commit(RECEIVE_MEMBER_ROLE_ERROR);
-
- await nextTick();
-
- const alert = findAlert();
-
- expect(alert.exists()).toBe(true);
- expect(alert.text()).toBe(
- "An error occurred while updating the member's role, please try again.",
- );
- expect(commonUtils.scrollToElement).toHaveBeenCalledWith(alert.element);
- });
- });
-
- describe('when `showError` is changed to `false`', () => {
- it('does not render and scroll to error alert', async () => {
- createComponent();
-
- store.commit(HIDE_ERROR);
-
- await nextTick();
-
- expect(findAlert().exists()).toBe(false);
- expect(commonUtils.scrollToElement).not.toHaveBeenCalled();
- });
- });
-
- describe('when alert is dismissed', () => {
- it('hides alert', async () => {
- createComponent();
-
- findAlert().vm.$emit('dismiss');
-
- await nextTick();
-
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- it('renders `FilterSortContainer`', () => {
- createComponent();
-
- expect(findFilterSortContainer().exists()).toBe(true);
- });
-});
diff --git a/spec/frontend/groups/members/index_spec.js b/spec/frontend/groups/members/index_spec.js
deleted file mode 100644
index 5c717e53229..00000000000
--- a/spec/frontend/groups/members/index_spec.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import { createWrapper } from '@vue/test-utils';
-import { initGroupMembersApp } from '~/groups/members';
-import GroupMembersApp from '~/groups/members/components/app.vue';
-import { membersJsonString, membersParsed } from './mock_data';
-
-describe('initGroupMembersApp', () => {
- let el;
- let vm;
- let wrapper;
-
- const setup = () => {
- vm = initGroupMembersApp(el, {
- tableFields: ['account'],
- tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
- tableSortableFields: ['account'],
- requestFormatter: () => ({}),
- filteredSearchBar: { show: false },
- });
- wrapper = createWrapper(vm);
- };
-
- beforeEach(() => {
- el = document.createElement('div');
- el.setAttribute('data-members', membersJsonString);
- el.setAttribute('data-group-id', '234');
- el.setAttribute('data-can-manage-members', 'true');
- el.setAttribute('data-member-path', '/groups/foo-bar/-/group_members/:id');
-
- window.gon = { current_user_id: 123 };
- });
-
- afterEach(() => {
- el = null;
-
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders `GroupMembersApp`', () => {
- setup();
-
- expect(wrapper.find(GroupMembersApp).exists()).toBe(true);
- });
-
- it('sets `currentUserId` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.currentUserId).toBe(123);
- });
-
- describe('when `gon.current_user_id` is not set (user is not logged in)', () => {
- it('sets `currentUserId` as `null` in Vuex store', () => {
- window.gon = {};
- setup();
-
- expect(vm.$store.state.currentUserId).toBeNull();
- });
- });
-
- it('parses and sets `data-group-id` as `sourceId` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.sourceId).toBe(234);
- });
-
- it('parses and sets `data-can-manage-members` as `canManageMembers` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.canManageMembers).toBe(true);
- });
-
- it('parses and sets `members` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.members).toEqual(membersParsed);
- });
-
- it('sets `tableFields` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.tableFields).toEqual(['account']);
- });
-
- it('sets `tableAttrs` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } });
- });
-
- it('sets `tableSortableFields` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.tableSortableFields).toEqual(['account']);
- });
-
- it('sets `requestFormatter` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.requestFormatter()).toEqual({});
- });
-
- it('sets `filteredSearchBar` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.filteredSearchBar).toEqual({ show: false });
- });
-
- it('sets `memberPath` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.memberPath).toBe('/groups/foo-bar/-/group_members/:id');
- });
-});
diff --git a/spec/frontend/groups/members/mock_data.js b/spec/frontend/groups/members/mock_data.js
deleted file mode 100644
index b84c9c6d446..00000000000
--- a/spec/frontend/groups/members/mock_data.js
+++ /dev/null
@@ -1,33 +0,0 @@
-export const membersJsonString =
- '[{"requested_at":null,"can_update":true,"can_remove":true,"can_override":false,"access_level":{"integer_value":50,"string_value":"Owner"},"source":{"id":323,"name":"My group / my subgroup","web_url":"http://127.0.0.1:3000/groups/my-group/my-subgroup"},"user":{"id":1,"name":"Administrator","username":"root","web_url":"http://127.0.0.1:3000/root","avatar_url":"https://www.gravatar.com/avatar/4816142ef496f956a277bedf1a40607b?s=80\u0026d=identicon","blocked":false,"two_factor_enabled":false},"id":524,"created_at":"2020-08-21T21:33:27.631Z","expires_at":null,"using_license":false,"group_sso":false,"group_managed_account":false}]';
-
-export const membersParsed = [
- {
- requestedAt: null,
- canUpdate: true,
- canRemove: true,
- canOverride: false,
- accessLevel: { integerValue: 50, stringValue: 'Owner' },
- source: {
- id: 323,
- name: 'My group / my subgroup',
- webUrl: 'http://127.0.0.1:3000/groups/my-group/my-subgroup',
- },
- user: {
- id: 1,
- name: 'Administrator',
- username: 'root',
- webUrl: 'http://127.0.0.1:3000/root',
- avatarUrl:
- 'https://www.gravatar.com/avatar/4816142ef496f956a277bedf1a40607b?s=80&d=identicon',
- blocked: false,
- twoFactorEnabled: false,
- },
- id: 524,
- createdAt: '2020-08-21T21:33:27.631Z',
- expiresAt: null,
- usingLicense: false,
- groupSso: false,
- groupManagedAccount: false,
- },
-];
diff --git a/spec/frontend/groups/members/utils_spec.js b/spec/frontend/groups/members/utils_spec.js
index 68945174e9d..0912e66e3e8 100644
--- a/spec/frontend/groups/members/utils_spec.js
+++ b/spec/frontend/groups/members/utils_spec.js
@@ -1,53 +1,14 @@
-import { membersJsonString, membersParsed } from './mock_data';
-import {
- parseDataAttributes,
- memberRequestFormatter,
- groupLinkRequestFormatter,
-} from '~/groups/members/utils';
+import { groupMemberRequestFormatter } from '~/groups/members/utils';
describe('group member utils', () => {
- describe('parseDataAttributes', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- el.setAttribute('data-members', membersJsonString);
- el.setAttribute('data-group-id', '234');
- el.setAttribute('data-can-manage-members', 'true');
- });
-
- afterEach(() => {
- el = null;
- });
-
- it('correctly parses the data attributes', () => {
- expect(parseDataAttributes(el)).toEqual({
- members: membersParsed,
- sourceId: 234,
- canManageMembers: true,
- });
- });
- });
-
- describe('memberRequestFormatter', () => {
+ describe('groupMemberRequestFormatter', () => {
it('returns expected format', () => {
expect(
- memberRequestFormatter({
+ groupMemberRequestFormatter({
accessLevel: 50,
expires_at: '2020-10-16',
}),
).toEqual({ group_member: { access_level: 50, expires_at: '2020-10-16' } });
});
});
-
- describe('groupLinkRequestFormatter', () => {
- it('returns expected format', () => {
- expect(
- groupLinkRequestFormatter({
- accessLevel: 50,
- expires_at: '2020-10-16',
- }),
- ).toEqual({ group_link: { group_access: 50, expires_at: '2020-10-16' } });
- });
- });
});
diff --git a/spec/frontend/groups/service/groups_service_spec.js b/spec/frontend/groups/service/groups_service_spec.js
index 38a565eba01..e037a6df1e2 100644
--- a/spec/frontend/groups/service/groups_service_spec.js
+++ b/spec/frontend/groups/service/groups_service_spec.js
@@ -1,6 +1,6 @@
+import GroupsService from '~/groups/service/groups_service';
import axios from '~/lib/utils/axios_utils';
-import GroupsService from '~/groups/service/groups_service';
import { mockEndpoint, mockParentGroupItem } from '../mock_data';
describe('GroupsService', () => {
diff --git a/spec/frontend/ide/commit_icon_spec.js b/spec/frontend/ide/commit_icon_spec.js
index 0dfcae00298..3acdfec5393 100644
--- a/spec/frontend/ide/commit_icon_spec.js
+++ b/spec/frontend/ide/commit_icon_spec.js
@@ -1,6 +1,6 @@
+import getCommitIconMap from '~/ide/commit_icon';
import { commitItemIconMap } from '~/ide/constants';
import { decorateData } from '~/ide/stores/utils';
-import getCommitIconMap from '~/ide/commit_icon';
const createFile = (name = 'name', id = name, type = '', parent = null) =>
decorateData({
diff --git a/spec/frontend/ide/components/activity_bar_spec.js b/spec/frontend/ide/components/activity_bar_spec.js
index 1a4b6ca0b71..657817eb3d8 100644
--- a/spec/frontend/ide/components/activity_bar_spec.js
+++ b/spec/frontend/ide/components/activity_bar_spec.js
@@ -1,14 +1,16 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
-import { leftSidebarViews } from '~/ide/constants';
import ActivityBar from '~/ide/components/activity_bar.vue';
+import { leftSidebarViews } from '~/ide/constants';
+import { createStore } from '~/ide/stores';
describe('IDE activity bar', () => {
const Component = Vue.extend(ActivityBar);
let vm;
let store;
+ const findChangesBadge = () => vm.$el.querySelector('.badge');
+
beforeEach(() => {
store = createStore();
@@ -69,4 +71,19 @@ describe('IDE activity bar', () => {
});
});
});
+
+ describe('changes badge', () => {
+ it('is rendered when files are staged', () => {
+ store.state.stagedFiles = [{ path: '/path/to/file' }];
+ vm.$mount();
+
+ expect(findChangesBadge()).toBeTruthy();
+ expect(findChangesBadge().textContent.trim()).toBe('1');
+ });
+
+ it('is not rendered when no changes are present', () => {
+ vm.$mount();
+ expect(findChangesBadge()).toBeFalsy();
+ });
+ });
});
diff --git a/spec/frontend/ide/components/branches/item_spec.js b/spec/frontend/ide/components/branches/item_spec.js
index f1aa9187a8d..f90c298c401 100644
--- a/spec/frontend/ide/components/branches/item_spec.js
+++ b/spec/frontend/ide/components/branches/item_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
-import { createStore } from '~/ide/stores';
-import { createRouter } from '~/ide/ide_router';
+import { shallowMount } from '@vue/test-utils';
import Item from '~/ide/components/branches/item.vue';
+import { createRouter } from '~/ide/ide_router';
+import { createStore } from '~/ide/stores';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { projectData } from '../../mock_data';
diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js
index 85776f8cc0e..0efa7af2c6c 100644
--- a/spec/frontend/ide/components/branches/search_list_spec.js
+++ b/spec/frontend/ide/components/branches/search_list_spec.js
@@ -1,9 +1,9 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-import List from '~/ide/components/branches/search_list.vue';
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();
diff --git a/spec/frontend/ide/components/commit_sidebar/actions_spec.js b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
index 91751bd34ea..c4dccf26af3 100644
--- a/spec/frontend/ide/components/commit_sidebar/actions_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/actions_spec.js
@@ -1,9 +1,12 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { projectData, branches } from 'jest/ide/mock_data';
-import { createStore } from '~/ide/stores';
import commitActions from '~/ide/components/commit_sidebar/actions.vue';
-import consts from '~/ide/stores/modules/commit/constants';
+import { createStore } from '~/ide/stores';
+import {
+ COMMIT_TO_NEW_BRANCH,
+ COMMIT_TO_CURRENT_BRANCH,
+} from '~/ide/stores/modules/commit/constants';
const ACTION_UPDATE_COMMIT_ACTION = 'commit/updateCommitAction';
@@ -126,16 +129,16 @@ describe('IDE commit sidebar actions', () => {
it.each`
input | expectedOption
- ${{ currentBranchId: BRANCH_DEFAULT }} | ${consts.COMMIT_TO_NEW_BRANCH}
- ${{ currentBranchId: BRANCH_DEFAULT, emptyRepo: true }} | ${consts.COMMIT_TO_CURRENT_BRANCH}
- ${{ currentBranchId: BRANCH_PROTECTED, hasMR: true }} | ${consts.COMMIT_TO_CURRENT_BRANCH}
- ${{ currentBranchId: BRANCH_PROTECTED, hasMR: false }} | ${consts.COMMIT_TO_CURRENT_BRANCH}
- ${{ currentBranchId: BRANCH_PROTECTED_NO_ACCESS, hasMR: true }} | ${consts.COMMIT_TO_NEW_BRANCH}
- ${{ currentBranchId: BRANCH_PROTECTED_NO_ACCESS, hasMR: false }} | ${consts.COMMIT_TO_NEW_BRANCH}
- ${{ currentBranchId: BRANCH_REGULAR, hasMR: true }} | ${consts.COMMIT_TO_CURRENT_BRANCH}
- ${{ currentBranchId: BRANCH_REGULAR, hasMR: false }} | ${consts.COMMIT_TO_CURRENT_BRANCH}
- ${{ currentBranchId: BRANCH_REGULAR_NO_ACCESS, hasMR: true }} | ${consts.COMMIT_TO_NEW_BRANCH}
- ${{ currentBranchId: BRANCH_REGULAR_NO_ACCESS, hasMR: false }} | ${consts.COMMIT_TO_NEW_BRANCH}
+ ${{ currentBranchId: BRANCH_DEFAULT }} | ${COMMIT_TO_NEW_BRANCH}
+ ${{ currentBranchId: BRANCH_DEFAULT, emptyRepo: true }} | ${COMMIT_TO_CURRENT_BRANCH}
+ ${{ currentBranchId: BRANCH_PROTECTED, hasMR: true }} | ${COMMIT_TO_CURRENT_BRANCH}
+ ${{ currentBranchId: BRANCH_PROTECTED, hasMR: false }} | ${COMMIT_TO_CURRENT_BRANCH}
+ ${{ currentBranchId: BRANCH_PROTECTED_NO_ACCESS, hasMR: true }} | ${COMMIT_TO_NEW_BRANCH}
+ ${{ currentBranchId: BRANCH_PROTECTED_NO_ACCESS, hasMR: false }} | ${COMMIT_TO_NEW_BRANCH}
+ ${{ currentBranchId: BRANCH_REGULAR, hasMR: true }} | ${COMMIT_TO_CURRENT_BRANCH}
+ ${{ currentBranchId: BRANCH_REGULAR, hasMR: false }} | ${COMMIT_TO_CURRENT_BRANCH}
+ ${{ currentBranchId: BRANCH_REGULAR_NO_ACCESS, hasMR: true }} | ${COMMIT_TO_NEW_BRANCH}
+ ${{ currentBranchId: BRANCH_REGULAR_NO_ACCESS, hasMR: false }} | ${COMMIT_TO_NEW_BRANCH}
`(
'with $input, it dispatches update commit action with $expectedOption',
({ input, expectedOption }) => {
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 ff780939026..50635ffe894 100644
--- a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
@@ -1,7 +1,7 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
-import { createStore } from '~/ide/stores';
+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();
diff --git a/spec/frontend/ide/components/commit_sidebar/empty_state_spec.js b/spec/frontend/ide/components/commit_sidebar/empty_state_spec.js
index c1dab4a04b6..4f81c0aa5d3 100644
--- a/spec/frontend/ide/components/commit_sidebar/empty_state_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/empty_state_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import emptyState from '~/ide/components/commit_sidebar/empty_state.vue';
+import { createStore } from '~/ide/stores';
describe('IDE commit panel empty state', () => {
let vm;
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js
index abd7e3bb8fc..2b567816ce8 100644
--- a/spec/frontend/ide/components/commit_sidebar/form_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js
@@ -1,11 +1,12 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
-import { getByText } from '@testing-library/dom';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { projectData } from 'jest/ide/mock_data';
+import { stubComponent } from 'helpers/stub_component';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import waitForPromises from 'helpers/wait_for_promises';
-import { createStore } from '~/ide/stores';
-import consts from '~/ide/stores/modules/commit/constants';
+import { projectData } from 'jest/ide/mock_data';
import CommitForm from '~/ide/components/commit_sidebar/form.vue';
+import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue';
import { leftSidebarViews } from '~/ide/constants';
import {
createCodeownersCommitError,
@@ -13,258 +14,287 @@ import {
createBranchChangedCommitError,
branchAlreadyExistsCommitError,
} from '~/ide/lib/errors';
+import { createStore } from '~/ide/stores';
+import { COMMIT_TO_NEW_BRANCH } from '~/ide/stores/modules/commit/constants';
describe('IDE commit form', () => {
- const Component = Vue.extend(CommitForm);
- let vm;
+ let wrapper;
let store;
- const beginCommitButton = () => vm.$el.querySelector('[data-testid="begin-commit-button"]');
+ const createComponent = () => {
+ wrapper = shallowMount(CommitForm, {
+ store,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal),
+ },
+ });
+ };
+
+ const setLastCommitMessage = (msg) => {
+ store.state.lastCommitMsg = msg;
+ };
+ const goToCommitView = () => {
+ store.state.currentActivityView = leftSidebarViews.commit.name;
+ };
+ const goToEditView = () => {
+ store.state.currentActivityView = leftSidebarViews.edit.name;
+ };
+ const findBeginCommitButton = () => wrapper.find('[data-testid="begin-commit-button"]');
+ const findBeginCommitButtonTooltip = () =>
+ wrapper.find('[data-testid="begin-commit-button-tooltip"]');
+ const findBeginCommitButtonData = () => ({
+ disabled: findBeginCommitButton().props('disabled'),
+ tooltip: getBinding(findBeginCommitButtonTooltip().element, 'gl-tooltip').value.title,
+ });
+ const findCommitButton = () => wrapper.find('[data-testid="commit-button"]');
+ const findCommitButtonTooltip = () => wrapper.find('[data-testid="commit-button-tooltip"]');
+ const findCommitButtonData = () => ({
+ 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);
+ const setCommitMessageInput = (val) => findCommitMessageInput().vm.$emit('input', val);
+ const findDiscardDraftButton = () => wrapper.find('[data-testid="discard-draft"]');
beforeEach(() => {
store = createStore();
- store.state.changedFiles.push('test');
+ store.state.stagedFiles.push('test');
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'master';
- Vue.set(store.state.projects, 'abcproject', { ...projectData });
-
- vm = createComponentWithStore(Component, store).$mount();
+ Vue.set(store.state.projects, 'abcproject', {
+ ...projectData,
+ userPermissions: { pushCode: true },
+ });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
- it('enables begin commit button when there are changes', () => {
- expect(beginCommitButton()).not.toHaveAttr('disabled');
- });
+ // Notes:
+ // - When there are no changes, there is no commit button so there's nothing to test :)
+ describe.each`
+ desc | stagedFiles | userPermissions | viewFn | buttonFn | disabled | tooltip
+ ${'when there are no changes'} | ${[]} | ${{ pushCode: true }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${''}
+ ${'when there are changes'} | ${['test']} | ${{ pushCode: true }} | ${goToEditView} | ${findBeginCommitButtonData} | ${false} | ${''}
+ ${'when there are changes'} | ${['test']} | ${{ pushCode: true }} | ${goToCommitView} | ${findCommitButtonData} | ${false} | ${''}
+ ${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${CommitForm.MSG_CANNOT_PUSH_CODE}
+ ${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToCommitView} | ${findCommitButtonData} | ${true} | ${CommitForm.MSG_CANNOT_PUSH_CODE}
+ `('$desc', ({ stagedFiles, userPermissions, viewFn, buttonFn, disabled, tooltip }) => {
+ beforeEach(async () => {
+ store.state.stagedFiles = stagedFiles;
+ store.state.projects.abcproject.userPermissions = userPermissions;
+
+ createComponent();
+ });
- it('disables begin commit button when there are no changes', async () => {
- store.state.changedFiles = [];
- await vm.$nextTick();
+ it(`at view=${viewFn.name}, ${buttonFn.name} has disabled=${disabled} tooltip=${tooltip}`, async () => {
+ viewFn();
- expect(beginCommitButton()).toHaveAttr('disabled');
+ await wrapper.vm.$nextTick();
+
+ expect(buttonFn()).toEqual({
+ disabled,
+ tooltip,
+ });
+ });
});
- describe('compact', () => {
- beforeEach(() => {
- vm.isCompact = true;
+ describe('on edit tab', () => {
+ beforeEach(async () => {
+ // Test that we react to switching to compact view.
+ goToCommitView();
+
+ createComponent();
- return vm.$nextTick();
+ goToEditView();
+
+ await wrapper.vm.$nextTick();
});
it('renders commit button in compact mode', () => {
- expect(beginCommitButton()).not.toBeNull();
- expect(beginCommitButton().textContent).toContain('Commit');
+ expect(findBeginCommitButton().exists()).toBe(true);
+ expect(findBeginCommitButton().text()).toBe('Commit…');
});
it('does not render form', () => {
- expect(vm.$el.querySelector('form')).toBeNull();
+ expect(findForm().exists()).toBe(false);
});
it('renders overview text', () => {
- vm.$store.state.stagedFiles.push('test');
-
- return vm.$nextTick(() => {
- expect(vm.$el.querySelector('p').textContent).toContain('1 changed file');
- });
+ expect(wrapper.find('p').text()).toBe('1 changed file');
});
- it('shows form when clicking commit button', () => {
- beginCommitButton().click();
-
- return vm.$nextTick(() => {
- expect(vm.$el.querySelector('form')).not.toBeNull();
- });
- });
+ it('when begin commit button is clicked, shows form', async () => {
+ findBeginCommitButton().vm.$emit('click');
- it('toggles activity bar view when clicking commit button', () => {
- beginCommitButton().click();
+ await wrapper.vm.$nextTick();
- return vm.$nextTick(() => {
- expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name);
- });
+ expect(findForm().exists()).toBe(true);
});
- it('collapses if lastCommitMsg is set to empty and current view is not commit view', async () => {
- store.state.lastCommitMsg = 'abc';
- store.state.currentActivityView = leftSidebarViews.edit.name;
- await vm.$nextTick();
-
- // if commit message is set, form is uncollapsed
- expect(vm.isCompact).toBe(false);
+ it('when begin commit button is clicked, sets activity view', async () => {
+ findBeginCommitButton().vm.$emit('click');
- store.state.lastCommitMsg = '';
- await vm.$nextTick();
+ await wrapper.vm.$nextTick();
- // collapsed when set to empty
- expect(vm.isCompact).toBe(true);
+ expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name);
});
- it('collapses if in commit view but there are no changes and vice versa', async () => {
- store.state.currentActivityView = leftSidebarViews.commit.name;
- await vm.$nextTick();
+ it('collapses if lastCommitMsg is set to empty and current view is not commit view', async () => {
+ // Test that it expands when lastCommitMsg is set
+ setLastCommitMessage('test');
+ goToEditView();
- // expanded by default if there are changes
- expect(vm.isCompact).toBe(false);
+ await wrapper.vm.$nextTick();
- store.state.changedFiles = [];
- await vm.$nextTick();
+ expect(findForm().exists()).toBe(true);
- expect(vm.isCompact).toBe(true);
+ // Now test that it collapses when lastCommitMsg is cleared
+ setLastCommitMessage('');
- store.state.changedFiles.push('test');
- await vm.$nextTick();
+ await wrapper.vm.$nextTick();
- // uncollapsed once again
- expect(vm.isCompact).toBe(false);
+ expect(findForm().exists()).toBe(false);
});
+ });
- it('collapses if switched from commit view to edit view and vice versa', async () => {
- store.state.currentActivityView = leftSidebarViews.edit.name;
- await vm.$nextTick();
-
- expect(vm.isCompact).toBe(true);
+ describe('on commit tab when window height is less than MAX_WINDOW_HEIGHT', () => {
+ let oldHeight;
- store.state.currentActivityView = leftSidebarViews.commit.name;
- await vm.$nextTick();
+ beforeEach(async () => {
+ oldHeight = window.innerHeight;
+ window.innerHeight = 700;
- expect(vm.isCompact).toBe(false);
+ createComponent();
- store.state.currentActivityView = leftSidebarViews.edit.name;
- await vm.$nextTick();
+ goToCommitView();
- expect(vm.isCompact).toBe(true);
+ await wrapper.vm.$nextTick();
});
- describe('when window height is less than MAX_WINDOW_HEIGHT', () => {
- let oldHeight;
-
- beforeEach(() => {
- oldHeight = window.innerHeight;
- window.innerHeight = 700;
- });
+ afterEach(() => {
+ window.innerHeight = oldHeight;
+ });
- afterEach(() => {
- window.innerHeight = oldHeight;
- });
+ it('stays collapsed if changes are added or removed', async () => {
+ expect(findForm().exists()).toBe(false);
- it('stays collapsed when switching from edit view to commit view and back', async () => {
- store.state.currentActivityView = leftSidebarViews.edit.name;
- await vm.$nextTick();
+ store.state.stagedFiles = [];
+ await wrapper.vm.$nextTick();
- expect(vm.isCompact).toBe(true);
+ expect(findForm().exists()).toBe(false);
- store.state.currentActivityView = leftSidebarViews.commit.name;
- await vm.$nextTick();
+ store.state.stagedFiles.push('test');
+ await wrapper.vm.$nextTick();
- expect(vm.isCompact).toBe(true);
+ expect(findForm().exists()).toBe(false);
+ });
+ });
- store.state.currentActivityView = leftSidebarViews.edit.name;
- await vm.$nextTick();
+ describe('on commit tab', () => {
+ beforeEach(async () => {
+ // Test that the component reacts to switching to full view
+ goToEditView();
- expect(vm.isCompact).toBe(true);
- });
+ createComponent();
- it('stays uncollapsed if changes are added or removed', async () => {
- store.state.currentActivityView = leftSidebarViews.commit.name;
- await vm.$nextTick();
+ goToCommitView();
- expect(vm.isCompact).toBe(true);
+ await wrapper.vm.$nextTick();
+ });
- store.state.changedFiles = [];
- await vm.$nextTick();
+ it('shows form', () => {
+ expect(findForm().exists()).toBe(true);
+ });
- expect(vm.isCompact).toBe(true);
+ it('hides begin commit button', () => {
+ expect(findBeginCommitButton().exists()).toBe(false);
+ });
- store.state.changedFiles.push('test');
- await vm.$nextTick();
+ describe('when no changed files', () => {
+ beforeEach(async () => {
+ store.state.stagedFiles = [];
+ await wrapper.vm.$nextTick();
+ });
- expect(vm.isCompact).toBe(true);
+ it('hides form', () => {
+ expect(findForm().exists()).toBe(false);
});
- it('uncollapses when clicked on Commit button in the edit view', async () => {
- store.state.currentActivityView = leftSidebarViews.edit.name;
- beginCommitButton().click();
- await waitForPromises();
+ it('expands again when staged files are added', async () => {
+ store.state.stagedFiles.push('test');
+ await wrapper.vm.$nextTick();
- expect(vm.isCompact).toBe(false);
+ expect(findForm().exists()).toBe(true);
});
});
- });
- describe('full', () => {
- beforeEach(() => {
- vm.isCompact = false;
+ it('updates commitMessage in store on input', async () => {
+ setCommitMessageInput('testing commit message');
- return vm.$nextTick();
+ await wrapper.vm.$nextTick();
+
+ expect(store.state.commit.commitMessage).toBe('testing commit message');
});
- it('updates commitMessage in store on input', () => {
- const textarea = vm.$el.querySelector('textarea');
+ describe('discard draft button', () => {
+ it('hidden when commitMessage is empty', () => {
+ expect(findDiscardDraftButton().exists()).toBe(false);
+ });
- textarea.value = 'testing commit message';
+ it('resets commitMessage when clicking discard button', async () => {
+ setCommitMessageInput('testing commit message');
- textarea.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
- return vm.$nextTick().then(() => {
- expect(vm.$store.state.commit.commitMessage).toBe('testing commit message');
- });
- });
+ expect(findCommitMessageInput().props('text')).toBe('testing commit message');
- it('updating currentActivityView not to commit view sets compact mode', () => {
- store.state.currentActivityView = 'a';
+ // Test that commitMessage is cleared on click
+ findDiscardDraftButton().vm.$emit('click');
- return vm.$nextTick(() => {
- expect(vm.isCompact).toBe(true);
+ await wrapper.vm.$nextTick();
+
+ expect(findCommitMessageInput().props('text')).toBe('');
});
});
- it('always opens itself in full view current activity view is not commit view when clicking commit button', () => {
- beginCommitButton().click();
+ describe('when submitting', () => {
+ beforeEach(async () => {
+ goToEditView();
- return vm.$nextTick(() => {
- expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name);
- expect(vm.isCompact).toBe(false);
- });
- });
+ createComponent();
- describe('discard draft button', () => {
- it('hidden when commitMessage is empty', () => {
- expect(vm.$el.querySelector('.btn-default').textContent).toContain('Collapse');
- });
+ goToCommitView();
+
+ await wrapper.vm.$nextTick();
- it('resets commitMessage when clicking discard button', () => {
- vm.$store.state.commit.commitMessage = 'testing commit message';
-
- return vm
- .$nextTick()
- .then(() => {
- vm.$el.querySelector('.btn-default').click();
- })
- .then(() => vm.$nextTick())
- .then(() => {
- expect(vm.$store.state.commit.commitMessage).not.toBe('testing commit message');
- });
+ setCommitMessageInput('testing commit message');
+
+ await wrapper.vm.$nextTick();
+
+ jest.spyOn(store, 'dispatch').mockResolvedValue();
});
- });
- describe('when submitting', () => {
- beforeEach(() => {
- jest.spyOn(vm, 'commitChanges');
+ it.each([clickCommitButton, submitForm])('when %p, commits changes', (fn) => {
+ fn();
- vm.$store.state.stagedFiles.push('test');
- vm.$store.state.commit.commitMessage = 'testing commit message';
+ expect(store.dispatch).toHaveBeenCalledWith('commit/commitChanges', undefined);
});
- it('calls commitChanges', () => {
- vm.commitChanges.mockResolvedValue({ success: true });
+ it('when cannot push code, submitting does nothing', async () => {
+ store.state.projects.abcproject.userPermissions.pushCode = false;
+ await wrapper.vm.$nextTick();
- return vm.$nextTick().then(() => {
- vm.$el.querySelector('.btn-success').click();
+ submitForm();
- expect(vm.commitChanges).toHaveBeenCalled();
- });
+ expect(store.dispatch).not.toHaveBeenCalled();
});
it.each`
@@ -272,31 +302,32 @@ describe('IDE commit form', () => {
${() => createCodeownersCommitError('test message')} | ${{ actionPrimary: { text: 'Create new branch' } }}
${createUnexpectedCommitError} | ${{ actionPrimary: null }}
`('opens error modal if commitError with $error', async ({ createError, props }) => {
- jest.spyOn(vm.$refs.commitErrorModal, 'show');
+ const modal = wrapper.find(GlModal);
+ modal.vm.show = jest.fn();
const error = createError();
store.state.commit.commitError = error;
- await vm.$nextTick();
+ await wrapper.vm.$nextTick();
- expect(vm.$refs.commitErrorModal.show).toHaveBeenCalled();
- expect(vm.$refs.commitErrorModal).toMatchObject({
+ expect(modal.vm.show).toHaveBeenCalled();
+ expect(modal.props()).toMatchObject({
actionCancel: { text: 'Cancel' },
...props,
});
// Because of the legacy 'mountComponent' approach here, the only way to
// test the text of the modal is by viewing the content of the modal added to the document.
- expect(document.body).toHaveText(error.messageHTML);
+ expect(modal.html()).toContain(error.messageHTML);
});
});
describe('with error modal with primary', () => {
beforeEach(() => {
- jest.spyOn(vm.$store, 'dispatch').mockReturnValue(Promise.resolve());
+ jest.spyOn(store, 'dispatch').mockResolvedValue();
});
const commitActions = [
- ['commit/updateCommitAction', consts.COMMIT_TO_NEW_BRANCH],
+ ['commit/updateCommitAction', COMMIT_TO_NEW_BRANCH],
['commit/commitChanges'],
];
@@ -310,27 +341,15 @@ describe('IDE commit form', () => {
async ({ commitError, expectedActions }) => {
store.state.commit.commitError = commitError('test message');
- await vm.$nextTick();
+ await wrapper.vm.$nextTick();
- getByText(document.body, 'Create new branch').click();
+ wrapper.find(GlModal).vm.$emit('ok');
await waitForPromises();
- expect(vm.$store.dispatch.mock.calls).toEqual(expectedActions);
+ expect(store.dispatch.mock.calls).toEqual(expectedActions);
},
);
});
});
-
- describe('commitButtonText', () => {
- it('returns commit text when staged files exist', () => {
- vm.$store.state.stagedFiles.push('testing');
-
- expect(vm.commitButtonText).toBe('Commit');
- });
-
- it('returns stage & commit text when staged files do not exist', () => {
- expect(vm.commitButtonText).toBe('Stage & Commit');
- });
- });
});
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 baa25a11c2a..b91ee88e0d6 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_item_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import { trimText } from 'helpers/text_helper';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import listItem from '~/ide/components/commit_sidebar/list_item.vue';
import { createRouter } from '~/ide/ide_router';
+import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
describe('Multi-file editor commit sidebar list item', () => {
diff --git a/spec/frontend/ide/components/commit_sidebar/list_spec.js b/spec/frontend/ide/components/commit_sidebar/list_spec.js
index 898ec4bebce..eb12fc994a5 100644
--- a/spec/frontend/ide/components/commit_sidebar/list_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/list_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import commitSidebarList from '~/ide/components/commit_sidebar/list.vue';
+import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
describe('Multi-file editor commit sidebar list', () => {
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 50da64abbbe..253c2a426ee 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
@@ -2,9 +2,12 @@ import Vue 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';
-import { createStore } from '~/ide/stores';
import { PERMISSION_CREATE_MR } from '~/ide/constants';
-import consts from '~/ide/stores/modules/commit/constants';
+import { createStore } from '~/ide/stores';
+import {
+ COMMIT_TO_CURRENT_BRANCH,
+ COMMIT_TO_NEW_BRANCH,
+} from '~/ide/stores/modules/commit/constants';
describe('create new MR checkbox', () => {
let store;
@@ -27,8 +30,8 @@ describe('create new MR checkbox', () => {
vm = createComponentWithStore(Component, store);
vm.$store.state.commit.commitAction = createNewBranch
- ? consts.COMMIT_TO_NEW_BRANCH
- : consts.COMMIT_TO_CURRENT_BRANCH;
+ ? COMMIT_TO_NEW_BRANCH
+ : COMMIT_TO_CURRENT_BRANCH;
vm.$store.state.currentBranchId = currentBranchId;
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 73d811f99b8..a6f3253321b 100644
--- a/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/radio_group_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import radioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
+import { createStore } from '~/ide/stores';
describe('IDE commit sidebar radio group', () => {
let vm;
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 b116321efb3..7bbe47d37af 100644
--- a/spec/frontend/ide/components/commit_sidebar/success_message_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/success_message_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import successMessage from '~/ide/components/commit_sidebar/success_message.vue';
+import { createStore } from '~/ide/stores';
describe('IDE commit panel successful commit state', () => {
let vm;
diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js
index fa6816d3546..2de3fa863a8 100644
--- a/spec/frontend/ide/components/error_message_spec.js
+++ b/spec/frontend/ide/components/error_message_spec.js
@@ -1,6 +1,6 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
import ErrorMessage from '~/ide/components/error_message.vue';
const localVue = createLocalVue();
diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js
index 275b98bc154..641407c7b77 100644
--- a/spec/frontend/ide/components/file_row_extra_spec.js
+++ b/spec/frontend/ide/components/file_row_extra_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
describe('IDE extra file row component', () => {
diff --git a/spec/frontend/ide/components/file_templates/bar_spec.js b/spec/frontend/ide/components/file_templates/bar_spec.js
index 158995c9c9c..4ca99f8d055 100644
--- a/spec/frontend/ide/components/file_templates/bar_spec.js
+++ b/spec/frontend/ide/components/file_templates/bar_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import Bar from '~/ide/components/file_templates/bar.vue';
+import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
describe('IDE file templates bar component', () => {
diff --git a/spec/frontend/ide/components/file_templates/dropdown_spec.js b/spec/frontend/ide/components/file_templates/dropdown_spec.js
index 628580103a4..44ac9aa954d 100644
--- a/spec/frontend/ide/components/file_templates/dropdown_spec.js
+++ b/spec/frontend/ide/components/file_templates/dropdown_spec.js
@@ -1,7 +1,7 @@
-import Vuex from 'vuex';
-import $ from 'jquery';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import $ from 'jquery';
+import Vuex from 'vuex';
import Dropdown from '~/ide/components/file_templates/dropdown.vue';
const localVue = createLocalVue();
diff --git a/spec/frontend/ide/components/ide_file_row_spec.js b/spec/frontend/ide/components/ide_file_row_spec.js
index c00ad7c8365..20c105460f2 100644
--- a/spec/frontend/ide/components/ide_file_row_spec.js
+++ b/spec/frontend/ide/components/ide_file_row_spec.js
@@ -1,9 +1,9 @@
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
-import IdeFileRow from '~/ide/components/ide_file_row.vue';
-import FileRow from '~/vue_shared/components/file_row.vue';
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);
diff --git a/spec/frontend/ide/components/ide_review_spec.js b/spec/frontend/ide/components/ide_review_spec.js
index 37f34a96495..740b7ada521 100644
--- a/spec/frontend/ide/components/ide_review_spec.js
+++ b/spec/frontend/ide/components/ide_review_spec.js
@@ -1,10 +1,10 @@
+import { createLocalVue, mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { createLocalVue, mount } from '@vue/test-utils';
-import { trimText } from 'helpers/text_helper';
import { keepAlive } from 'helpers/keep_alive_component_helper';
-import IdeReview from '~/ide/components/ide_review.vue';
+import { trimText } from 'helpers/text_helper';
import EditorModeDropdown from '~/ide/components/editor_mode_dropdown.vue';
+import IdeReview from '~/ide/components/ide_review.vue';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
diff --git a/spec/frontend/ide/components/ide_side_bar_spec.js b/spec/frontend/ide/components/ide_side_bar_spec.js
index 72e9463945b..c683612b142 100644
--- a/spec/frontend/ide/components/ide_side_bar_spec.js
+++ b/spec/frontend/ide/components/ide_side_bar_spec.js
@@ -1,13 +1,13 @@
+import { GlSkeletonLoading } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
-import { createStore } from '~/ide/stores';
+import IdeReview from '~/ide/components/ide_review.vue';
import IdeSidebar from '~/ide/components/ide_side_bar.vue';
import IdeTree from '~/ide/components/ide_tree.vue';
import RepoCommitSection from '~/ide/components/repo_commit_section.vue';
-import IdeReview from '~/ide/components/ide_review.vue';
import { leftSidebarViews } from '~/ide/constants';
+import { createStore } from '~/ide/stores';
import { projectData } from '../mock_data';
const localVue = createLocalVue();
diff --git a/spec/frontend/ide/components/ide_sidebar_nav_spec.js b/spec/frontend/ide/components/ide_sidebar_nav_spec.js
index 6b4cb9bd03d..2ea0c250794 100644
--- a/spec/frontend/ide/components/ide_sidebar_nav_spec.js
+++ b/spec/frontend/ide/components/ide_sidebar_nav_spec.js
@@ -1,8 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import IdeSidebarNav from '~/ide/components/ide_sidebar_nav.vue';
import { SIDE_RIGHT, SIDE_LEFT } from '~/ide/constants';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
const TEST_TABS = [
{
@@ -74,7 +75,7 @@ describe('ide/components/ide_sidebar_nav', () => {
createComponent({ isOpen, side });
bsTooltipHide = jest.fn();
- wrapper.vm.$root.$on('bv::hide::tooltip', bsTooltipHide);
+ wrapper.vm.$root.$on(BV_HIDE_TOOLTIP, bsTooltipHide);
});
it('renders buttons', () => {
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index 805fa898611..c9d19c18d03 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -1,9 +1,10 @@
-import Vuex from 'vuex';
+import { GlAlert } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
-import { createStore } from '~/ide/stores';
import ErrorMessage from '~/ide/components/error_message.vue';
-import ide from '~/ide/components/ide.vue';
+import Ide from '~/ide/components/ide.vue';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
@@ -15,12 +16,12 @@ describe('WebIDE', () => {
let wrapper;
- function createComponent({ projData = emptyProjData, state = {} } = {}) {
+ const createComponent = ({ projData = emptyProjData, state = {} } = {}) => {
const store = createStore();
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'master';
- store.state.projects.abcproject = { ...projData };
+ store.state.projects.abcproject = projData && { ...projData };
store.state.trees['abcproject/master'] = {
tree: [],
loading: false,
@@ -29,11 +30,13 @@ describe('WebIDE', () => {
store.state[key] = state[key];
});
- return shallowMount(ide, {
+ wrapper = shallowMount(Ide, {
store,
localVue,
});
- }
+ };
+
+ const findAlert = () => wrapper.find(GlAlert);
afterEach(() => {
wrapper.destroy();
@@ -42,7 +45,7 @@ describe('WebIDE', () => {
describe('ide component, empty repo', () => {
beforeEach(() => {
- wrapper = createComponent({
+ createComponent({
projData: {
empty_repo: true,
},
@@ -63,7 +66,7 @@ describe('WebIDE', () => {
`(
'should error message exists=$exists when errorMessage=$errorMessage',
async ({ errorMessage, exists }) => {
- wrapper = createComponent({
+ createComponent({
state: {
errorMessage,
},
@@ -78,12 +81,12 @@ describe('WebIDE', () => {
describe('onBeforeUnload', () => {
it('returns undefined when no staged files or changed files', () => {
- wrapper = createComponent();
+ createComponent();
expect(wrapper.vm.onBeforeUnload()).toBe(undefined);
});
it('returns warning text when their are changed files', () => {
- wrapper = createComponent({
+ createComponent({
state: {
changedFiles: [file()],
},
@@ -93,7 +96,7 @@ describe('WebIDE', () => {
});
it('returns warning text when their are staged files', () => {
- wrapper = createComponent({
+ createComponent({
state: {
stagedFiles: [file()],
},
@@ -104,7 +107,7 @@ describe('WebIDE', () => {
it('updates event object', () => {
const event = {};
- wrapper = createComponent({
+ createComponent({
state: {
stagedFiles: [file()],
},
@@ -118,7 +121,7 @@ describe('WebIDE', () => {
describe('non-existent branch', () => {
it('does not render "New file" button for non-existent branch when repo is not empty', () => {
- wrapper = createComponent({
+ createComponent({
state: {
projects: {},
},
@@ -130,7 +133,7 @@ describe('WebIDE', () => {
describe('branch with files', () => {
beforeEach(() => {
- wrapper = createComponent({
+ createComponent({
projData: {
empty_repo: false,
},
@@ -142,4 +145,31 @@ describe('WebIDE', () => {
});
});
});
+
+ it('when user cannot push code, shows alert', () => {
+ createComponent({
+ projData: {
+ userPermissions: {
+ pushCode: false,
+ },
+ },
+ });
+
+ expect(findAlert().props()).toMatchObject({
+ dismissible: false,
+ });
+ expect(findAlert().text()).toBe(Ide.MSG_CANNOT_PUSH_CODE);
+ });
+
+ it.each`
+ desc | projData
+ ${'when user can push code'} | ${{ userPermissions: { pushCode: true } }}
+ ${'when project is not ready'} | ${null}
+ `('$desc, no alert is shown', ({ projData }) => {
+ createComponent({
+ projData,
+ });
+
+ expect(findAlert().exists()).toBe(false);
+ });
});
diff --git a/spec/frontend/ide/components/ide_status_bar_spec.js b/spec/frontend/ide/components/ide_status_bar_spec.js
index 47506bb87e8..9d33a1e2554 100644
--- a/spec/frontend/ide/components/ide_status_bar_spec.js
+++ b/spec/frontend/ide/components/ide_status_bar_spec.js
@@ -1,10 +1,10 @@
-import Vue from 'vue';
import _ from 'lodash';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import { createStore } from '~/ide/stores';
+import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
import { rightSidebarViews } from '~/ide/constants';
+import { createStore } from '~/ide/stores';
import { projectData } from '../mock_data';
const TEST_PROJECT_ID = 'abcproject';
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index 02b5dc19bd8..036edfb3ec1 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+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';
diff --git a/spec/frontend/ide/components/ide_status_mr_spec.js b/spec/frontend/ide/components/ide_status_mr_spec.js
index ac1be4b21c0..0526d4653f8 100644
--- a/spec/frontend/ide/components/ide_status_mr_spec.js
+++ b/spec/frontend/ide/components/ide_status_mr_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import IdeStatusMr from '~/ide/components/ide_status_mr.vue';
diff --git a/spec/frontend/ide/components/ide_tree_spec.js b/spec/frontend/ide/components/ide_tree_spec.js
index c5934b032c4..6eef646b012 100644
--- a/spec/frontend/ide/components/ide_tree_spec.js
+++ b/spec/frontend/ide/components/ide_tree_spec.js
@@ -1,6 +1,6 @@
+import { mount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { keepAlive } from 'helpers/keep_alive_component_helper';
import IdeTree from '~/ide/components/ide_tree.vue';
import { createStore } from '~/ide/stores';
diff --git a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
index b323ad8320c..d632a34266a 100644
--- a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue';
describe('IDE job log scroll button', () => {
diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js
index 5c5c6602374..8797e07aef1 100644
--- a/spec/frontend/ide/components/jobs/list_spec.js
+++ b/spec/frontend/ide/components/jobs/list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import StageList from '~/ide/components/jobs/list.vue';
import Stage from '~/ide/components/jobs/stage.vue';
diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js
index e80215b9d13..9accd81a2ba 100644
--- a/spec/frontend/ide/components/jobs/stage_spec.js
+++ b/spec/frontend/ide/components/jobs/stage_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
-import Stage from '~/ide/components/jobs/stage.vue';
+import { shallowMount } from '@vue/test-utils';
import Item from '~/ide/components/jobs/item.vue';
+import Stage from '~/ide/components/jobs/stage.vue';
import { stages, jobs } from '../../mock_data';
describe('IDE pipeline stage', () => {
diff --git a/spec/frontend/ide/components/merge_requests/item_spec.js b/spec/frontend/ide/components/merge_requests/item_spec.js
index 20adaa7abbc..f0a97a0b10a 100644
--- a/spec/frontend/ide/components/merge_requests/item_spec.js
+++ b/spec/frontend/ide/components/merge_requests/item_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
-import { createStore } from '~/ide/stores';
-import { createRouter } from '~/ide/ide_router';
+import Vuex from 'vuex';
import Item from '~/ide/components/merge_requests/item.vue';
+import { createRouter } from '~/ide/ide_router';
+import { createStore } from '~/ide/stores';
const TEST_ITEM = {
iid: 1,
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index f0ac852fa67..85acabca38b 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -1,8 +1,8 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
-import List from '~/ide/components/merge_requests/list.vue';
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';
diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js
index 12a1a4c8013..4ddb3930764 100644
--- a/spec/frontend/ide/components/nav_dropdown_spec.js
+++ b/spec/frontend/ide/components/nav_dropdown_spec.js
@@ -1,8 +1,8 @@
-import $ from 'jquery';
import { mount } from '@vue/test-utils';
-import { createStore } from '~/ide/stores';
+import $ from 'jquery';
import NavDropdown from '~/ide/components/nav_dropdown.vue';
import { PERMISSION_READ_MR } from '~/ide/constants';
+import { createStore } from '~/ide/stores';
const TEST_PROJECT_ID = 'lorem-ipsum';
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index 793d950b3e0..5a1c0471206 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
import newDropdown from '~/ide/components/new_dropdown/index.vue';
+import { createStore } from '~/ide/stores';
describe('new dropdown component', () => {
let store;
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index 06434081e39..0600fcea917 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import { createStore } from '~/ide/stores';
-import modal from '~/ide/components/new_dropdown/modal.vue';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import modal from '~/ide/components/new_dropdown/modal.vue';
+import { createStore } from '~/ide/stores';
jest.mock('~/flash');
diff --git a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
index c3da2a46858..7216f50b05c 100644
--- a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
+++ b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
@@ -1,9 +1,9 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
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';
-import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
-import IdeSidebarNav from '~/ide/components/ide_sidebar_nav.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/ide/components/panes/right_spec.js b/spec/frontend/ide/components/panes/right_spec.js
index 57fd0e49e94..c6231d129ff 100644
--- a/spec/frontend/ide/components/panes/right_spec.js
+++ b/spec/frontend/ide/components/panes/right_spec.js
@@ -1,10 +1,10 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { createStore } from '~/ide/stores';
-import RightPane from '~/ide/components/panes/right.vue';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
+import RightPane from '~/ide/components/panes/right.vue';
import { rightSidebarViews } from '~/ide/constants';
+import { createStore } from '~/ide/stores';
import extendStore from '~/ide/stores/extend';
const localVue = createLocalVue();
diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js
index a1fbfd96c31..58d8c0629fb 100644
--- a/spec/frontend/ide/components/pipelines/list_spec.js
+++ b/spec/frontend/ide/components/pipelines/list_spec.js
@@ -1,13 +1,13 @@
+import { GlLoadingIcon, GlTab } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { GlLoadingIcon, GlTab } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import { pipelines } from 'jest/ide/mock_data';
-import List from '~/ide/components/pipelines/list.vue';
import JobsList from '~/ide/components/jobs/list.vue';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import List from '~/ide/components/pipelines/list.vue';
import IDEServices from '~/ide/services';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
Vue.use(Vuex);
diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js
index 220982e1fd9..1768f01f3b8 100644
--- a/spec/frontend/ide/components/preview/clientside_spec.js
+++ b/spec/frontend/ide/components/preview/clientside_spec.js
@@ -1,7 +1,7 @@
-import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import smooshpack from 'smooshpack';
+import Vuex from 'vuex';
import Clientside from '~/ide/components/preview/clientside.vue';
import eventHub from '~/ide/eventhub';
diff --git a/spec/frontend/ide/components/preview/navigator_spec.js b/spec/frontend/ide/components/preview/navigator_spec.js
index ba5ac3bbbea..ee760364c7e 100644
--- a/spec/frontend/ide/components/preview/navigator_spec.js
+++ b/spec/frontend/ide/components/preview/navigator_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
-import { TEST_HOST } from 'helpers/test_constants';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { listen } from 'codesandbox-api';
+import { TEST_HOST } from 'helpers/test_constants';
import ClientsideNavigator from '~/ide/components/preview/navigator.vue';
jest.mock('codesandbox-api', () => ({
diff --git a/spec/frontend/ide/components/repo_commit_section_spec.js b/spec/frontend/ide/components/repo_commit_section_spec.js
index e91debee4ca..c174f5e2006 100644
--- a/spec/frontend/ide/components/repo_commit_section_spec.js
+++ b/spec/frontend/ide/components/repo_commit_section_spec.js
@@ -1,10 +1,10 @@
import { mount } from '@vue/test-utils';
import { keepAlive } from 'helpers/keep_alive_component_helper';
-import { createStore } from '~/ide/stores';
-import { createRouter } from '~/ide/ide_router';
-import RepoCommitSection from '~/ide/components/repo_commit_section.vue';
import EmptyState from '~/ide/components/commit_sidebar/empty_state.vue';
+import RepoCommitSection from '~/ide/components/repo_commit_section.vue';
import { stageKeys } from '~/ide/constants';
+import { createRouter } from '~/ide/ide_router';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
const TEST_NO_CHANGES_SVG = 'nochangessvg';
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 89a7f423e34..1985feb1615 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -1,22 +1,22 @@
-import Vuex from 'vuex';
-import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import '~/behaviors/markdown/render_gfm';
import { Range } from 'monaco-editor';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import '~/behaviors/markdown/render_gfm';
+import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import waitForPromises from 'helpers/wait_for_promises';
import waitUsingRealTimer from 'helpers/wait_using_real_timer';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import service from '~/ide/services';
-import { createStoreOptions } from '~/ide/stores';
import RepoEditor from '~/ide/components/repo_editor.vue';
-import Editor from '~/ide/lib/editor';
import {
leftSidebarViews,
FILE_VIEW_MODE_EDITOR,
FILE_VIEW_MODE_PREVIEW,
viewerTypes,
} from '~/ide/constants';
+import Editor from '~/ide/lib/editor';
+import service from '~/ide/services';
+import { createStoreOptions } from '~/ide/stores';
+import axios from '~/lib/utils/axios_utils';
import { file } from '../helpers';
import { exampleConfigs, exampleFiles } from '../lib/editorconfig/mock_data';
diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js
index a44c8b4d5ee..b39a488b034 100644
--- a/spec/frontend/ide/components/repo_tab_spec.js
+++ b/spec/frontend/ide/components/repo_tab_spec.js
@@ -1,8 +1,8 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { createStore } from '~/ide/stores';
import RepoTab from '~/ide/components/repo_tab.vue';
import { createRouter } from '~/ide/ide_router';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
const localVue = createLocalVue();
diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js
index 45a17c37667..6ee73b0a437 100644
--- a/spec/frontend/ide/components/repo_tabs_spec.js
+++ b/spec/frontend/ide/components/repo_tabs_spec.js
@@ -1,7 +1,7 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
-import { createStore } from '~/ide/stores';
+import Vuex from 'vuex';
import RepoTabs from '~/ide/components/repo_tabs.vue';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
const localVue = createLocalVue();
diff --git a/spec/frontend/ide/components/resizable_panel_spec.js b/spec/frontend/ide/components/resizable_panel_spec.js
index b1a1212371e..6a5af52ea35 100644
--- a/spec/frontend/ide/components/resizable_panel_spec.js
+++ b/spec/frontend/ide/components/resizable_panel_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import ResizablePanel from '~/ide/components/resizable_panel.vue';
-import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import { SIDE_LEFT, SIDE_RIGHT } from '~/ide/constants';
+import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
const TEST_WIDTH = 500;
const TEST_MIN_WIDTH = 400;
diff --git a/spec/frontend/ide/components/terminal/empty_state_spec.js b/spec/frontend/ide/components/terminal/empty_state_spec.js
index b62470f67b6..57c816747aa 100644
--- a/spec/frontend/ide/components/terminal/empty_state_spec.js
+++ b/spec/frontend/ide/components/terminal/empty_state_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlButton, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'spec/test_constants';
import TerminalEmptyState from '~/ide/components/terminal/empty_state.vue';
diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js
index 5653c8bf14d..5659a7d15da 100644
--- a/spec/frontend/ide/components/terminal/session_spec.js
+++ b/spec/frontend/ide/components/terminal/session_spec.js
@@ -1,5 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import TerminalSession from '~/ide/components/terminal/session.vue';
import Terminal from '~/ide/components/terminal/terminal.vue';
diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
index 99182710218..416096083f0 100644
--- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import TerminalControls from '~/ide/components/terminal/terminal_controls.vue';
import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue';
+import TerminalControls from '~/ide/components/terminal/terminal_controls.vue';
describe('IDE TerminalControls', () => {
let wrapper;
diff --git a/spec/frontend/ide/components/terminal/terminal_spec.js b/spec/frontend/ide/components/terminal/terminal_spec.js
index 9cfe167d2f6..c4b186c004a 100644
--- a/spec/frontend/ide/components/terminal/terminal_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_spec.js
@@ -1,7 +1,7 @@
-import Vue, { nextTick } from 'vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
import Terminal from '~/ide/components/terminal/terminal.vue';
import TerminalControls from '~/ide/components/terminal/terminal_controls.vue';
import {
diff --git a/spec/frontend/ide/components/terminal/view_spec.js b/spec/frontend/ide/components/terminal/view_spec.js
index 37f7957c526..e97d4d8a73b 100644
--- a/spec/frontend/ide/components/terminal/view_spec.js
+++ b/spec/frontend/ide/components/terminal/view_spec.js
@@ -1,10 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
+import { TEST_HOST } from 'spec/test_constants';
import TerminalEmptyState from '~/ide/components/terminal/empty_state.vue';
-import TerminalView from '~/ide/components/terminal/view.vue';
import TerminalSession from '~/ide/components/terminal/session.vue';
+import TerminalView from '~/ide/components/terminal/view.vue';
const TEST_HELP_PATH = `${TEST_HOST}/help`;
const TEST_SVG_PATH = `${TEST_HOST}/illustration.svg`;
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 afdecb7bbbd..69077ef2c68 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,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+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';
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 d15583f81e4..c916c43d1e2 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,6 +1,6 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import TerminalSyncStatus from '~/ide/components/terminal_sync/terminal_sync_status.vue';
import {
MSG_TERMINAL_SYNC_CONNECTING,
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index f815c3d090e..9b7a4715d7f 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -1,6 +1,6 @@
import * as pathUtils from 'path';
-import { decorateData } from '~/ide/stores/utils';
import { commitActionTypes } from '~/ide/constants';
+import { decorateData } from '~/ide/stores/utils';
export const file = (name = 'name', id = name, type = '', parent = null) =>
decorateData({
diff --git a/spec/frontend/ide/lib/create_diff_spec.js b/spec/frontend/ide/lib/create_diff_spec.js
index 76494f9af1b..b33fa599d1c 100644
--- a/spec/frontend/ide/lib/create_diff_spec.js
+++ b/spec/frontend/ide/lib/create_diff_spec.js
@@ -1,6 +1,6 @@
+import { commitActionTypes } from '~/ide/constants';
import createDiff from '~/ide/lib/create_diff';
import createFileDiff from '~/ide/lib/create_file_diff';
-import { commitActionTypes } from '~/ide/constants';
import {
createNewFile,
createUpdatedFile,
diff --git a/spec/frontend/ide/lib/create_file_diff_spec.js b/spec/frontend/ide/lib/create_file_diff_spec.js
index 294f0a926aa..646304c431b 100644
--- a/spec/frontend/ide/lib/create_file_diff_spec.js
+++ b/spec/frontend/ide/lib/create_file_diff_spec.js
@@ -1,5 +1,5 @@
-import createFileDiff from '~/ide/lib/create_file_diff';
import { commitActionTypes } from '~/ide/constants';
+import createFileDiff from '~/ide/lib/create_file_diff';
import {
createUpdatedFile,
createNewFile,
diff --git a/spec/frontend/ide/lib/decorations/controller_spec.js b/spec/frontend/ide/lib/decorations/controller_spec.js
index e9b7faaadfe..b513f1b2eba 100644
--- a/spec/frontend/ide/lib/decorations/controller_spec.js
+++ b/spec/frontend/ide/lib/decorations/controller_spec.js
@@ -1,8 +1,8 @@
-import Editor from '~/ide/lib/editor';
-import DecorationsController from '~/ide/lib/decorations/controller';
import Model from '~/ide/lib/common/model';
-import { file } from '../../helpers';
+import DecorationsController from '~/ide/lib/decorations/controller';
+import Editor from '~/ide/lib/editor';
import { createStore } from '~/ide/stores';
+import { file } from '../../helpers';
describe('Multi-file editor library decorations controller', () => {
let editorInstance;
diff --git a/spec/frontend/ide/lib/diff/controller_spec.js b/spec/frontend/ide/lib/diff/controller_spec.js
index 57c134620c0..5f1344f1ea2 100644
--- a/spec/frontend/ide/lib/diff/controller_spec.js
+++ b/spec/frontend/ide/lib/diff/controller_spec.js
@@ -1,9 +1,9 @@
import { Range } from 'monaco-editor';
-import Editor from '~/ide/lib/editor';
import ModelManager from '~/ide/lib/common/model_manager';
import DecorationsController from '~/ide/lib/decorations/controller';
import DirtyDiffController, { getDiffChangeType, getDecorator } from '~/ide/lib/diff/controller';
import { computeDiff } from '~/ide/lib/diff/diff';
+import Editor from '~/ide/lib/editor';
import { createStore } from '~/ide/stores';
import { file } from '../../helpers';
diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js
index 12779c61dc3..c21a7edb2da 100644
--- a/spec/frontend/ide/lib/editor_spec.js
+++ b/spec/frontend/ide/lib/editor_spec.js
@@ -4,9 +4,10 @@ import {
Range,
Selection,
} from 'monaco-editor';
+import { EDITOR_TYPE_DIFF } from '~/editor/constants';
import Editor from '~/ide/lib/editor';
-import { createStore } from '~/ide/stores';
import { defaultEditorOptions } from '~/ide/lib/editor_options';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
describe('Multi-file editor library', () => {
@@ -125,7 +126,7 @@ describe('Multi-file editor library', () => {
});
it('sets original & modified when diff editor', () => {
- jest.spyOn(instance.instance, 'getEditorType').mockReturnValue('vs.editor.IDiffEditor');
+ jest.spyOn(instance.instance, 'getEditorType').mockReturnValue(EDITOR_TYPE_DIFF);
jest.spyOn(instance.instance, 'setModel').mockImplementation(() => {});
instance.attachModel(model);
diff --git a/spec/frontend/ide/lib/languages/hcl_spec.js b/spec/frontend/ide/lib/languages/hcl_spec.js
index c6ebad6a4f4..948c44d4543 100644
--- a/spec/frontend/ide/lib/languages/hcl_spec.js
+++ b/spec/frontend/ide/lib/languages/hcl_spec.js
@@ -1,6 +1,6 @@
import { editor } from 'monaco-editor';
-import { registerLanguages } from '~/ide/utils';
import hcl from '~/ide/lib/languages/hcl';
+import { registerLanguages } from '~/ide/utils';
describe('tokenization for .tf files', () => {
beforeEach(() => {
diff --git a/spec/frontend/ide/lib/languages/vue_spec.js b/spec/frontend/ide/lib/languages/vue_spec.js
index ba5c31bb101..e3a67ccd47f 100644
--- a/spec/frontend/ide/lib/languages/vue_spec.js
+++ b/spec/frontend/ide/lib/languages/vue_spec.js
@@ -1,6 +1,6 @@
import { editor } from 'monaco-editor';
-import { registerLanguages } from '~/ide/utils';
import vue from '~/ide/lib/languages/vue';
+import { registerLanguages } from '~/ide/utils';
// This file only tests syntax specific to vue. This does not test existing syntaxes
// of html, javascript, css and handlebars, which vue files extend.
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index c3d6182bd78..678d58cba34 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -1,10 +1,10 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import services from '~/ide/services';
import Api from '~/api';
+import getUserPermissions from '~/ide/queries/getUserPermissions.query.graphql';
+import services from '~/ide/services';
import { query } from '~/ide/services/gql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
-import getUserPermissions from '~/ide/queries/getUserPermissions.query.graphql';
import { projectData } from '../mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 9d367714bbe..6178fb08d8c 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
+import Vue from 'vue';
+import eventHub from '~/ide/eventhub';
+import { createRouter } from '~/ide/ide_router';
+import service from '~/ide/services';
import { createStore } from '~/ide/stores';
import * as actions from '~/ide/stores/actions/file';
import * as types from '~/ide/stores/mutation_types';
-import service from '~/ide/services';
-import { createRouter } from '~/ide/ide_router';
-import eventHub from '~/ide/eventhub';
+import axios from '~/lib/utils/axios_utils';
import { file, createTriggerRenameAction, createTriggerUpdatePayload } from '../../helpers';
const ORIGINAL_CONTENT = 'original content';
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index 9b17d95ea35..600bd5fe9e1 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -1,19 +1,33 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import { createStore } from '~/ide/stores';
+import { range } from 'lodash';
+import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '~/ide/constants';
+import service from '~/ide/services';
+import { createStore } from '~/ide/stores';
import {
getMergeRequestData,
getMergeRequestChanges,
getMergeRequestVersions,
+ openMergeRequestChanges,
openMergeRequest,
} from '~/ide/stores/actions/merge_request';
-import service from '~/ide/services';
-import { leftSidebarViews, PERMISSION_READ_MR } from '~/ide/constants';
+import * as types from '~/ide/stores/mutation_types';
+import axios from '~/lib/utils/axios_utils';
const TEST_PROJECT = 'abcproject';
const TEST_PROJECT_ID = 17;
+const createMergeRequestChange = (path) => ({
+ new_path: path,
+ path,
+});
+const createMergeRequestChangesCount = (n) =>
+ range(n).map((i) => createMergeRequestChange(`loremispum_${i}.md`));
+
+const testGetUrlForPath = (path) => `${TEST_HOST}/test/${path}`;
+
jest.mock('~/flash');
describe('IDE store merge request actions', () => {
@@ -353,6 +367,72 @@ describe('IDE store merge request actions', () => {
});
});
+ describe('openMergeRequestChanges', () => {
+ it.each`
+ desc | changes | entries
+ ${'with empty changes'} | ${[]} | ${{}}
+ ${'with changes not matching entries'} | ${[{ new_path: '123.md' }]} | ${{ '456.md': {} }}
+ `('$desc, does nothing', ({ changes, entries }) => {
+ const state = { entries };
+
+ return testAction({
+ action: openMergeRequestChanges,
+ state,
+ payload: changes,
+ expectedActions: [],
+ expectedMutations: [],
+ });
+ });
+
+ it('updates views and opens mr changes', () => {
+ // This is the payload sent to the action
+ const changesPayload = createMergeRequestChangesCount(15);
+
+ // Remove some items from the payload to use for entries
+ const changes = changesPayload.slice(1, 14);
+
+ const entries = changes.reduce(
+ (acc, { path }) => Object.assign(acc, { [path]: path, type: 'blob' }),
+ {},
+ );
+ const pathsToOpen = changes.slice(0, MAX_MR_FILES_AUTO_OPEN).map((x) => x.new_path);
+
+ return testAction({
+ action: openMergeRequestChanges,
+ state: { entries, getUrlForPath: testGetUrlForPath },
+ payload: changesPayload,
+ expectedActions: [
+ { type: 'updateActivityBarView', payload: leftSidebarViews.review.name },
+ // Only activates first file
+ { type: 'router/push', payload: testGetUrlForPath(pathsToOpen[0]) },
+ { type: 'setFileActive', payload: pathsToOpen[0] },
+ // Fetches data for other files
+ ...pathsToOpen.slice(1).map((path) => ({
+ type: 'getFileData',
+ payload: { path, makeFileActive: false },
+ })),
+ ...pathsToOpen.slice(1).map((path) => ({
+ type: 'getRawFileData',
+ payload: { path },
+ })),
+ ],
+ expectedMutations: [
+ ...changes.map((change) => ({
+ type: types.SET_FILE_MERGE_REQUEST_CHANGE,
+ payload: {
+ file: entries[change.new_path],
+ mrChange: change,
+ },
+ })),
+ ...pathsToOpen.map((path) => ({
+ type: types.TOGGLE_FILE_OPEN,
+ payload: path,
+ })),
+ ],
+ });
+ });
+ });
+
describe('openMergeRequest', () => {
const mr = {
projectId: TEST_PROJECT,
@@ -409,7 +489,6 @@ describe('IDE store merge request actions', () => {
case 'getFiles':
case 'getMergeRequestVersions':
case 'getBranchData':
- case 'setFileMrChange':
return Promise.resolve();
default:
return originalDispatch(type, payload);
@@ -445,6 +524,7 @@ describe('IDE store merge request actions', () => {
],
['getMergeRequestVersions', mr],
['getMergeRequestChanges', mr],
+ ['openMergeRequestChanges', testMergeRequestChanges.changes],
]);
})
.then(done)
@@ -454,9 +534,11 @@ describe('IDE store merge request actions', () => {
it('updates activity bar view and gets file data, if changes are found', (done) => {
store.state.entries.foo = {
type: 'blob',
+ path: 'foo',
};
store.state.entries.bar = {
type: 'blob',
+ path: 'bar',
};
testMergeRequestChanges.changes = [
@@ -467,24 +549,9 @@ describe('IDE store merge request actions', () => {
openMergeRequest({ state: store.state, dispatch: store.dispatch, getters: mockGetters }, mr)
.then(() => {
expect(store.dispatch).toHaveBeenCalledWith(
- 'updateActivityBarView',
- leftSidebarViews.review.name,
+ 'openMergeRequestChanges',
+ testMergeRequestChanges.changes,
);
-
- testMergeRequestChanges.changes.forEach((change, i) => {
- expect(store.dispatch).toHaveBeenCalledWith('setFileMrChange', {
- file: store.state.entries[change.new_path],
- mrChange: change,
- });
-
- expect(store.dispatch).toHaveBeenCalledWith('getFileData', {
- path: change.new_path,
- makeFileActive: i === 0,
- openFile: true,
- });
- });
-
- expect(store.state.openFiles.length).toBe(testMergeRequestChanges.changes.length);
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/ide/stores/actions/project_spec.js b/spec/frontend/ide/stores/actions/project_spec.js
index 1244c8af91a..23ffb5ff56b 100644
--- a/spec/frontend/ide/stores/actions/project_spec.js
+++ b/spec/frontend/ide/stores/actions/project_spec.js
@@ -1,7 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
-import axios from '~/lib/utils/axios_utils';
+import testAction from 'helpers/vuex_action_helper';
+import api from '~/api';
+import service from '~/ide/services';
import { createStore } from '~/ide/stores';
import {
refreshLastCommitData,
@@ -12,8 +13,7 @@ import {
loadFile,
loadBranch,
} from '~/ide/stores/actions';
-import service from '~/ide/services';
-import api from '~/api';
+import axios from '~/lib/utils/axios_utils';
const TEST_PROJECT_ID = 'abc/def';
diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js
index 7831df9f3a4..8de2188a5f4 100644
--- a/spec/frontend/ide/stores/actions/tree_spec.js
+++ b/spec/frontend/ide/stores/actions/tree_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
+import { createRouter } from '~/ide/ide_router';
+import service from '~/ide/services';
+import { createStore } from '~/ide/stores';
import { showTreeEntry, getFiles, setDirectoryData } from '~/ide/stores/actions/tree';
import * as types from '~/ide/stores/mutation_types';
import axios from '~/lib/utils/axios_utils';
-import { createStore } from '~/ide/stores';
-import service from '~/ide/services';
-import { createRouter } from '~/ide/ide_router';
import { file, createEntriesFromPaths } from '../../helpers';
describe('Multi-file store tree actions', () => {
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index 036bc91cd11..d47dd88dd47 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { createStore } from '~/ide/stores';
+import eventHub from '~/ide/eventhub';
import { createRouter } from '~/ide/ide_router';
+import { createStore } from '~/ide/stores';
import {
stageAllChanges,
unstageAllChanges,
@@ -18,10 +18,10 @@ import {
createTempEntry,
discardAllChanges,
} from '~/ide/stores/actions';
-import axios from '~/lib/utils/axios_utils';
import * as types from '~/ide/stores/mutation_types';
+import axios from '~/lib/utils/axios_utils';
+import { visitUrl } from '~/lib/utils/url_utility';
import { file, createTriggerRenameAction, createTriggerChangeAction } from '../helpers';
-import eventHub from '~/ide/eventhub';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index 1787f9e9361..450f5592026 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -1,6 +1,7 @@
import { TEST_HOST } from 'helpers/test_constants';
-import * as getters from '~/ide/stores/getters';
import { createStore } from '~/ide/stores';
+import * as getters from '~/ide/stores/getters';
+import { DEFAULT_PERMISSIONS } from '../../../../app/assets/javascripts/ide/constants';
import { file } from '../helpers';
const TEST_PROJECT_ID = 'test_project';
@@ -386,7 +387,9 @@ describe('IDE store getters', () => {
describe('findProjectPermissions', () => {
it('returns false if project not found', () => {
- expect(localStore.getters.findProjectPermissions(TEST_PROJECT_ID)).toEqual({});
+ expect(localStore.getters.findProjectPermissions(TEST_PROJECT_ID)).toEqual(
+ DEFAULT_PERMISSIONS,
+ );
});
it('finds permission in given project', () => {
diff --git a/spec/frontend/ide/stores/modules/branches/actions_spec.js b/spec/frontend/ide/stores/modules/branches/actions_spec.js
index b1c077c4082..135dbc1f746 100644
--- a/spec/frontend/ide/stores/modules/branches/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/branches/actions_spec.js
@@ -1,8 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import state from '~/ide/stores/modules/branches/state';
-import * as types from '~/ide/stores/modules/branches/mutation_types';
import {
requestBranches,
receiveBranchesError,
@@ -10,6 +7,9 @@ import {
fetchBranches,
resetBranches,
} from '~/ide/stores/modules/branches/actions';
+import * as types from '~/ide/stores/modules/branches/mutation_types';
+import state from '~/ide/stores/modules/branches/state';
+import axios from '~/lib/utils/axios_utils';
import { branches, projectData } from '../../../mock_data';
describe('IDE branches actions', () => {
diff --git a/spec/frontend/ide/stores/modules/branches/mutations_spec.js b/spec/frontend/ide/stores/modules/branches/mutations_spec.js
index ddf55479be9..fd6006749d2 100644
--- a/spec/frontend/ide/stores/modules/branches/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/branches/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/ide/stores/modules/branches/state';
-import mutations from '~/ide/stores/modules/branches/mutations';
import * as types from '~/ide/stores/modules/branches/mutation_types';
+import mutations from '~/ide/stores/modules/branches/mutations';
+import state from '~/ide/stores/modules/branches/state';
import { branches } from '../../../mock_data';
describe('IDE branches mutations', () => {
diff --git a/spec/frontend/ide/stores/modules/clientside/actions_spec.js b/spec/frontend/ide/stores/modules/clientside/actions_spec.js
index 05627f8ed0e..c167d056039 100644
--- a/spec/frontend/ide/stores/modules/clientside/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/clientside/actions_spec.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
+import testAction from 'helpers/vuex_action_helper';
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}/usage_ping/web_ide_clientside_preview`;
diff --git a/spec/frontend/ide/stores/modules/commit/actions_spec.js b/spec/frontend/ide/stores/modules/commit/actions_spec.js
index 5be0e22a9fc..b124eb391f3 100644
--- a/spec/frontend/ide/stores/modules/commit/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/actions_spec.js
@@ -1,17 +1,20 @@
-import { file } from 'jest/ide/helpers';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { createStore } from '~/ide/stores';
-import service from '~/ide/services';
-import { createRouter } from '~/ide/ide_router';
+import { file } from 'jest/ide/helpers';
+import { commitActionTypes, PERMISSION_CREATE_MR } from '~/ide/constants';
import eventHub from '~/ide/eventhub';
-import consts from '~/ide/stores/modules/commit/constants';
-import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
-import * as actions from '~/ide/stores/modules/commit/actions';
+import { createRouter } from '~/ide/ide_router';
import { createUnexpectedCommitError } from '~/ide/lib/errors';
-import { commitActionTypes, PERMISSION_CREATE_MR } from '~/ide/constants';
+import service from '~/ide/services';
+import { createStore } from '~/ide/stores';
+import * as actions from '~/ide/stores/modules/commit/actions';
+import {
+ COMMIT_TO_CURRENT_BRANCH,
+ COMMIT_TO_NEW_BRANCH,
+} from '~/ide/stores/modules/commit/constants';
+import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
+import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
@@ -425,12 +428,12 @@ describe('IDE commit module actions', () => {
});
it('resets stores commit actions', (done) => {
- store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
+ store.state.commit.commitAction = COMMIT_TO_NEW_BRANCH;
store
.dispatch('commit/commitChanges')
.then(() => {
- expect(store.state.commit.commitAction).not.toBe(consts.COMMIT_TO_NEW_BRANCH);
+ expect(store.state.commit.commitAction).not.toBe(COMMIT_TO_NEW_BRANCH);
})
.then(done)
.catch(done.fail);
@@ -450,7 +453,7 @@ describe('IDE commit module actions', () => {
it('redirects to new merge request page', (done) => {
jest.spyOn(eventHub, '$on').mockImplementation();
- store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
+ store.state.commit.commitAction = COMMIT_TO_NEW_BRANCH;
store.state.commit.shouldCreateMR = true;
store
@@ -468,7 +471,7 @@ describe('IDE commit module actions', () => {
it('does not redirect to new merge request page when shouldCreateMR is not checked', (done) => {
jest.spyOn(eventHub, '$on').mockImplementation();
- store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
+ store.state.commit.commitAction = COMMIT_TO_NEW_BRANCH;
store.state.commit.shouldCreateMR = false;
store
@@ -483,7 +486,7 @@ describe('IDE commit module actions', () => {
it('does not redirect to merge request page if shouldCreateMR is checked, but branch is the default branch', async () => {
jest.spyOn(eventHub, '$on').mockImplementation();
- store.state.commit.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ store.state.commit.commitAction = COMMIT_TO_CURRENT_BRANCH;
store.state.commit.shouldCreateMR = true;
await store.dispatch('commit/commitChanges');
diff --git a/spec/frontend/ide/stores/modules/commit/getters_spec.js b/spec/frontend/ide/stores/modules/commit/getters_spec.js
index 66ed51dbd13..0dc938bb637 100644
--- a/spec/frontend/ide/stores/modules/commit/getters_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/getters_spec.js
@@ -1,6 +1,9 @@
-import commitState from '~/ide/stores/modules/commit/state';
+import {
+ COMMIT_TO_CURRENT_BRANCH,
+ COMMIT_TO_NEW_BRANCH,
+} from '~/ide/stores/modules/commit/constants';
import * as getters from '~/ide/stores/modules/commit/getters';
-import consts from '~/ide/stores/modules/commit/constants';
+import commitState from '~/ide/stores/modules/commit/state';
describe('IDE commit module getters', () => {
let state;
@@ -147,13 +150,13 @@ describe('IDE commit module getters', () => {
describe('isCreatingNewBranch', () => {
it('returns false if NOT creating a new branch', () => {
- state.commitAction = consts.COMMIT_TO_CURRENT_BRANCH;
+ state.commitAction = COMMIT_TO_CURRENT_BRANCH;
expect(getters.isCreatingNewBranch(state)).toBeFalsy();
});
it('returns true if creating a new branch', () => {
- state.commitAction = consts.COMMIT_TO_NEW_BRANCH;
+ state.commitAction = COMMIT_TO_NEW_BRANCH;
expect(getters.isCreatingNewBranch(state)).toBeTruthy();
});
diff --git a/spec/frontend/ide/stores/modules/commit/mutations_spec.js b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
index 6393a70eac6..50342832d75 100644
--- a/spec/frontend/ide/stores/modules/commit/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
@@ -1,6 +1,6 @@
-import commitState from '~/ide/stores/modules/commit/state';
-import mutations from '~/ide/stores/modules/commit/mutations';
import * as types from '~/ide/stores/modules/commit/mutation_types';
+import mutations from '~/ide/stores/modules/commit/mutations';
+import commitState from '~/ide/stores/modules/commit/state';
describe('IDE commit module mutations', () => {
let state;
diff --git a/spec/frontend/ide/stores/modules/editor/actions_spec.js b/spec/frontend/ide/stores/modules/editor/actions_spec.js
index 6a420ac32de..f006018364b 100644
--- a/spec/frontend/ide/stores/modules/editor/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/editor/actions_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
-import * as types from '~/ide/stores/modules/editor/mutation_types';
import * as actions from '~/ide/stores/modules/editor/actions';
+import * as types from '~/ide/stores/modules/editor/mutation_types';
import { createTriggerRenamePayload } from '../../../helpers';
describe('~/ide/stores/modules/editor/actions', () => {
diff --git a/spec/frontend/ide/stores/modules/editor/getters_spec.js b/spec/frontend/ide/stores/modules/editor/getters_spec.js
index 55e1e31f66f..14099cdaeb2 100644
--- a/spec/frontend/ide/stores/modules/editor/getters_spec.js
+++ b/spec/frontend/ide/stores/modules/editor/getters_spec.js
@@ -1,5 +1,5 @@
-import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
import * as getters from '~/ide/stores/modules/editor/getters';
+import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
const TEST_PATH = 'test/path.md';
const TEST_FILE_EDITOR = {
diff --git a/spec/frontend/ide/stores/modules/editor/mutations_spec.js b/spec/frontend/ide/stores/modules/editor/mutations_spec.js
index e4b330b3174..35d13f375a3 100644
--- a/spec/frontend/ide/stores/modules/editor/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/editor/mutations_spec.js
@@ -1,6 +1,6 @@
-import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
import * as types from '~/ide/stores/modules/editor/mutation_types';
import mutations from '~/ide/stores/modules/editor/mutations';
+import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
import { createTriggerRenamePayload } from '../../../helpers';
const TEST_PATH = 'test/path.md';
diff --git a/spec/frontend/ide/stores/modules/file_templates/actions_spec.js b/spec/frontend/ide/stores/modules/file_templates/actions_spec.js
index 76898e83c7a..9ff950b0875 100644
--- a/spec/frontend/ide/stores/modules/file_templates/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/file_templates/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import createState from '~/ide/stores/modules/file_templates/state';
import * as actions from '~/ide/stores/modules/file_templates/actions';
import * as types from '~/ide/stores/modules/file_templates/mutation_types';
+import createState from '~/ide/stores/modules/file_templates/state';
+import axios from '~/lib/utils/axios_utils';
describe('IDE file templates actions', () => {
let state;
diff --git a/spec/frontend/ide/stores/modules/file_templates/getters_spec.js b/spec/frontend/ide/stores/modules/file_templates/getters_spec.js
index c9676b23fa1..e237b167f96 100644
--- a/spec/frontend/ide/stores/modules/file_templates/getters_spec.js
+++ b/spec/frontend/ide/stores/modules/file_templates/getters_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/ide/stores/state';
import { leftSidebarViews } from '~/ide/constants';
import * as getters from '~/ide/stores/modules/file_templates/getters';
+import createState from '~/ide/stores/state';
describe('IDE file templates getters', () => {
describe('templateTypes', () => {
diff --git a/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js b/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js
index 6a1a826093c..3ea3c9507dd 100644
--- a/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/file_templates/mutations_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/ide/stores/modules/file_templates/state';
import * as types from '~/ide/stores/modules/file_templates/mutation_types';
import mutations from '~/ide/stores/modules/file_templates/mutations';
+import createState from '~/ide/stores/modules/file_templates/state';
const mockFileTemplates = [['MIT'], ['CC']];
const mockTemplateType = 'test';
diff --git a/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js b/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js
index 6594d65f558..e1f2b165dd9 100644
--- a/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js
@@ -1,8 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
-import state from '~/ide/stores/modules/merge_requests/state';
-import * as types from '~/ide/stores/modules/merge_requests/mutation_types';
import {
requestMergeRequests,
receiveMergeRequestsError,
@@ -10,6 +7,9 @@ import {
fetchMergeRequests,
resetMergeRequests,
} from '~/ide/stores/modules/merge_requests/actions';
+import * as types from '~/ide/stores/modules/merge_requests/mutation_types';
+import state from '~/ide/stores/modules/merge_requests/state';
+import axios from '~/lib/utils/axios_utils';
import { mergeRequests } from '../../../mock_data';
describe('IDE merge requests actions', () => {
diff --git a/spec/frontend/ide/stores/modules/merge_requests/mutations_spec.js b/spec/frontend/ide/stores/modules/merge_requests/mutations_spec.js
index d33bda3652d..f45c577f801 100644
--- a/spec/frontend/ide/stores/modules/merge_requests/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/merge_requests/mutations_spec.js
@@ -1,7 +1,7 @@
import { TEST_HOST } from 'helpers/test_constants';
-import state from '~/ide/stores/modules/merge_requests/state';
-import mutations from '~/ide/stores/modules/merge_requests/mutations';
import * as types from '~/ide/stores/modules/merge_requests/mutation_types';
+import mutations from '~/ide/stores/modules/merge_requests/mutations';
+import state from '~/ide/stores/modules/merge_requests/state';
import { mergeRequests } from '../../../mock_data';
describe('IDE merge requests mutations', () => {
diff --git a/spec/frontend/ide/stores/modules/pane/mutations_spec.js b/spec/frontend/ide/stores/modules/pane/mutations_spec.js
index b5fcd35912e..eaeb2c8cd28 100644
--- a/spec/frontend/ide/stores/modules/pane/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/pane/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/ide/stores/modules/pane/state';
-import mutations from '~/ide/stores/modules/pane/mutations';
import * as types from '~/ide/stores/modules/pane/mutation_types';
+import mutations from '~/ide/stores/modules/pane/mutations';
+import state from '~/ide/stores/modules/pane/state';
describe('IDE pane module mutations', () => {
const TEST_VIEW = 'test-view';
diff --git a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
index b7ed257e954..9aa31136c89 100644
--- a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
@@ -1,8 +1,8 @@
-import Visibility from 'visibilityjs';
import MockAdapter from 'axios-mock-adapter';
+import Visibility from 'visibilityjs';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
+import { rightSidebarViews } from '~/ide/constants';
import {
requestLatestPipeline,
receiveLatestPipelineError,
@@ -22,9 +22,9 @@ import {
fetchJobLogs,
resetLatestPipeline,
} from '~/ide/stores/modules/pipelines/actions';
-import state from '~/ide/stores/modules/pipelines/state';
import * as types from '~/ide/stores/modules/pipelines/mutation_types';
-import { rightSidebarViews } from '~/ide/constants';
+import state from '~/ide/stores/modules/pipelines/state';
+import axios from '~/lib/utils/axios_utils';
import { pipelines, jobs } from '../../../mock_data';
describe('IDE pipelines actions', () => {
diff --git a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
index d820bf0291e..0e738b98918 100644
--- a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
@@ -1,6 +1,6 @@
+import * as types from '~/ide/stores/modules/pipelines/mutation_types';
import mutations from '~/ide/stores/modules/pipelines/mutations';
import state from '~/ide/stores/modules/pipelines/state';
-import * as types from '~/ide/stores/modules/pipelines/mutation_types';
import { fullPipelinesResponse, stages, jobs } from '../../../mock_data';
describe('IDE pipelines mutations', () => {
diff --git a/spec/frontend/ide/stores/modules/router/mutations_spec.js b/spec/frontend/ide/stores/modules/router/mutations_spec.js
index a4a83c9344d..5a9f266db94 100644
--- a/spec/frontend/ide/stores/modules/router/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/router/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/ide/stores/modules/router/mutations';
import * as types from '~/ide/stores/modules/router/mutation_types';
+import mutations from '~/ide/stores/modules/router/mutations';
import createState from '~/ide/stores/modules/router/state';
const TEST_PATH = 'test/path/abc';
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
index 05935f1db38..e5887ca0a33 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js
@@ -1,14 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'spec/test_constants';
+import * as actions from '~/ide/stores/modules/terminal/actions/checks';
import {
CHECK_CONFIG,
CHECK_RUNNERS,
RETRY_RUNNERS_INTERVAL,
} from '~/ide/stores/modules/terminal/constants';
-import * as mutationTypes from '~/ide/stores/modules/terminal/mutation_types';
import * as messages from '~/ide/stores/modules/terminal/messages';
-import * as actions from '~/ide/stores/modules/terminal/actions/checks';
+import * as mutationTypes from '~/ide/stores/modules/terminal/mutation_types';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
index dd51786745f..e42e760b841 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/session_controls_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import * as actions from '~/ide/stores/modules/terminal/actions/session_controls';
import { STARTING, PENDING, STOPPING, STOPPED } from '~/ide/stores/modules/terminal/constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
import * as mutationTypes from '~/ide/stores/modules/terminal/mutation_types';
-import * as actions from '~/ide/stores/modules/terminal/actions/session_controls';
-import httpStatus from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import httpStatus from '~/lib/utils/http_status';
jest.mock('~/flash');
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
index 0e123dce798..0227955754c 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/session_status_spec.js
@@ -1,11 +1,11 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import * as actions from '~/ide/stores/modules/terminal/actions/session_status';
import { PENDING, RUNNING, STOPPING, STOPPED } from '~/ide/stores/modules/terminal/constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
import * as mutationTypes from '~/ide/stores/modules/terminal/mutation_types';
-import * as actions from '~/ide/stores/modules/terminal/actions/session_status';
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
diff --git a/spec/frontend/ide/stores/modules/terminal/actions/setup_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/setup_spec.js
index 8bf3b58228e..a823c05c459 100644
--- a/spec/frontend/ide/stores/modules/terminal/actions/setup_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/actions/setup_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
-import * as mutationTypes from '~/ide/stores/modules/terminal/mutation_types';
import * as actions from '~/ide/stores/modules/terminal/actions/setup';
+import * as mutationTypes from '~/ide/stores/modules/terminal/mutation_types';
describe('IDE store terminal setup actions', () => {
describe('init', () => {
diff --git a/spec/frontend/ide/stores/modules/terminal/messages_spec.js b/spec/frontend/ide/stores/modules/terminal/messages_spec.js
index 1bb92a9dfa5..e8f375a70b5 100644
--- a/spec/frontend/ide/stores/modules/terminal/messages_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/messages_spec.js
@@ -1,8 +1,8 @@
import { escape } from 'lodash';
import { TEST_HOST } from 'spec/test_constants';
import * as messages from '~/ide/stores/modules/terminal/messages';
-import { sprintf } from '~/locale';
import httpStatus from '~/lib/utils/http_status';
+import { sprintf } from '~/locale';
const TEST_HELP_URL = `${TEST_HOST}/help`;
diff --git a/spec/frontend/ide/stores/modules/terminal/mutations_spec.js b/spec/frontend/ide/stores/modules/terminal/mutations_spec.js
index e9933bdd7be..3451932a185 100644
--- a/spec/frontend/ide/stores/modules/terminal/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal/mutations_spec.js
@@ -4,9 +4,9 @@ import {
RUNNING,
STOPPING,
} from '~/ide/stores/modules/terminal/constants';
-import createState from '~/ide/stores/modules/terminal/state';
import * as types from '~/ide/stores/modules/terminal/mutation_types';
import mutations from '~/ide/stores/modules/terminal/mutations';
+import createState from '~/ide/stores/modules/terminal/state';
describe('IDE store terminal mutations', () => {
let state;
diff --git a/spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js b/spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js
index 2ae7e8a8727..22b0615c6d0 100644
--- a/spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal_sync/actions_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
-import * as actions from '~/ide/stores/modules/terminal_sync/actions';
import mirror, { canConnect, SERVICE_NAME } from '~/ide/lib/mirror';
+import * as actions from '~/ide/stores/modules/terminal_sync/actions';
import * as types from '~/ide/stores/modules/terminal_sync/mutation_types';
jest.mock('~/ide/lib/mirror');
diff --git a/spec/frontend/ide/stores/modules/terminal_sync/mutations_spec.js b/spec/frontend/ide/stores/modules/terminal_sync/mutations_spec.js
index ecf35d60e96..b7dbf93f4e6 100644
--- a/spec/frontend/ide/stores/modules/terminal_sync/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/terminal_sync/mutations_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/ide/stores/modules/terminal_sync/state';
import * as types from '~/ide/stores/modules/terminal_sync/mutation_types';
import mutations from '~/ide/stores/modules/terminal_sync/mutations';
+import createState from '~/ide/stores/modules/terminal_sync/state';
const TEST_MESSAGE = 'lorem ipsum dolar sit';
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index 9bbdac0ae25..825d2a546cd 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/ide/stores/mutations/file';
import { createStore } from '~/ide/stores';
+import mutations from '~/ide/stores/mutations/file';
import { file } from '../../helpers';
describe('IDE store file mutations', () => {
diff --git a/spec/frontend/ide/stores/plugins/terminal_spec.js b/spec/frontend/ide/stores/plugins/terminal_spec.js
index 948c2131fd8..d4cdad16ecb 100644
--- a/spec/frontend/ide/stores/plugins/terminal_spec.js
+++ b/spec/frontend/ide/stores/plugins/terminal_spec.js
@@ -2,8 +2,8 @@ import { createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
import terminalModule from '~/ide/stores/modules/terminal';
-import createTerminalPlugin from '~/ide/stores/plugins/terminal';
import { SET_BRANCH_WORKING_REFERENCE } from '~/ide/stores/mutation_types';
+import createTerminalPlugin from '~/ide/stores/plugins/terminal';
const TEST_DATASET = {
eeWebTerminalSvgPath: `${TEST_HOST}/web/terminal/svg`,
diff --git a/spec/frontend/ide/stores/plugins/terminal_sync_spec.js b/spec/frontend/ide/stores/plugins/terminal_sync_spec.js
index 0e5f4184679..f12f80c1602 100644
--- a/spec/frontend/ide/stores/plugins/terminal_sync_spec.js
+++ b/spec/frontend/ide/stores/plugins/terminal_sync_spec.js
@@ -1,9 +1,9 @@
+import eventHub from '~/ide/eventhub';
+import { createStore } from '~/ide/stores';
+import { RUNNING, STOPPING } from '~/ide/stores/modules/terminal/constants';
+import { SET_SESSION_STATUS } from '~/ide/stores/modules/terminal/mutation_types';
import createTerminalPlugin from '~/ide/stores/plugins/terminal';
import createTerminalSyncPlugin from '~/ide/stores/plugins/terminal_sync';
-import { SET_SESSION_STATUS } from '~/ide/stores/modules/terminal/mutation_types';
-import { RUNNING, STOPPING } from '~/ide/stores/modules/terminal/constants';
-import { createStore } from '~/ide/stores';
-import eventHub from '~/ide/eventhub';
import { createTriggerUpdatePayload } from '../../helpers';
jest.mock('~/ide/lib/mirror');
diff --git a/spec/frontend/ide/stores/utils_spec.js b/spec/frontend/ide/stores/utils_spec.js
index b185013050e..46a0794b2e6 100644
--- a/spec/frontend/ide/stores/utils_spec.js
+++ b/spec/frontend/ide/stores/utils_spec.js
@@ -1,5 +1,5 @@
-import * as utils from '~/ide/stores/utils';
import { commitActionTypes } from '~/ide/constants';
+import * as utils from '~/ide/stores/utils';
import { file } from '../helpers';
describe('Multi-file store utils', () => {
diff --git a/spec/frontend/image_diff/image_badge_spec.js b/spec/frontend/image_diff/image_badge_spec.js
index a11b50ead47..8450b9b4694 100644
--- a/spec/frontend/image_diff/image_badge_spec.js
+++ b/spec/frontend/image_diff/image_badge_spec.js
@@ -1,5 +1,5 @@
-import ImageBadge from '~/image_diff/image_badge';
import imageDiffHelper from '~/image_diff/helpers/index';
+import ImageBadge from '~/image_diff/image_badge';
import * as mockData from './mock_data';
describe('ImageBadge', () => {
diff --git a/spec/frontend/image_diff/image_diff_spec.js b/spec/frontend/image_diff/image_diff_spec.js
index e14f8dc774f..16d19f45496 100644
--- a/spec/frontend/image_diff/image_diff_spec.js
+++ b/spec/frontend/image_diff/image_diff_spec.js
@@ -1,7 +1,7 @@
import { TEST_HOST } from 'helpers/test_constants';
+import imageDiffHelper from '~/image_diff/helpers/index';
import ImageDiff from '~/image_diff/image_diff';
import * as imageUtility from '~/lib/utils/image_utility';
-import imageDiffHelper from '~/image_diff/helpers/index';
import * as mockData from './mock_data';
describe('ImageDiff', () => {
diff --git a/spec/frontend/image_diff/init_discussion_tab_spec.js b/spec/frontend/image_diff/init_discussion_tab_spec.js
index f96d00230ee..5bc0c738944 100644
--- a/spec/frontend/image_diff/init_discussion_tab_spec.js
+++ b/spec/frontend/image_diff/init_discussion_tab_spec.js
@@ -1,5 +1,5 @@
-import initDiscussionTab from '~/image_diff/init_discussion_tab';
import initImageDiffHelper from '~/image_diff/helpers/init_image_diff';
+import initDiscussionTab from '~/image_diff/init_discussion_tab';
describe('initDiscussionTab', () => {
beforeEach(() => {
diff --git a/spec/frontend/image_diff/replaced_image_diff_spec.js b/spec/frontend/image_diff/replaced_image_diff_spec.js
index 16be4b82ad7..cc4a2530fc4 100644
--- a/spec/frontend/image_diff/replaced_image_diff_spec.js
+++ b/spec/frontend/image_diff/replaced_image_diff_spec.js
@@ -1,8 +1,8 @@
import { TEST_HOST } from 'helpers/test_constants';
-import ReplacedImageDiff from '~/image_diff/replaced_image_diff';
+import imageDiffHelper from '~/image_diff/helpers/index';
import ImageDiff from '~/image_diff/image_diff';
+import ReplacedImageDiff from '~/image_diff/replaced_image_diff';
import { viewTypes } from '~/image_diff/view_types';
-import imageDiffHelper from '~/image_diff/helpers/index';
describe('ReplacedImageDiff', () => {
let element;
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
index ac8b73aeb49..cdef4b1ee62 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlLink, GlFormInput } from '@gitlab/ui';
-import Select2Select from '~/vue_shared/components/select2_select.vue';
-import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue';
+import { shallowMount } from '@vue/test-utils';
import { STATUSES } from '~/import_entities/constants';
+import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue';
+import Select2Select from '~/vue_shared/components/select2_select.vue';
import { availableNamespacesFixture } from '../graphql/fixtures';
const getFakeGroup = (status) => ({
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
index cd184bb65cc..dd734782169 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
@@ -1,15 +1,15 @@
+import { GlEmptyState, GlLoadingIcon, GlSearchBoxByClick, GlSprintf } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
-import { GlLoadingIcon } from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
import createMockApollo from 'helpers/mock_apollo_helper';
-import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+import { STATUSES } from '~/import_entities/constants';
import ImportTable from '~/import_entities/import_groups/components/import_table.vue';
-import setTargetNamespaceMutation from '~/import_entities/import_groups/graphql/mutations/set_target_namespace.mutation.graphql';
-import setNewNameMutation from '~/import_entities/import_groups/graphql/mutations/set_new_name.mutation.graphql';
+import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue';
import importGroupMutation from '~/import_entities/import_groups/graphql/mutations/import_group.mutation.graphql';
-
-import { STATUSES } from '~/import_entities/constants';
+import setNewNameMutation from '~/import_entities/import_groups/graphql/mutations/set_new_name.mutation.graphql';
+import setTargetNamespaceMutation from '~/import_entities/import_groups/graphql/mutations/set_target_namespace.mutation.graphql';
+import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
import { availableNamespacesFixture, generateFakeEntry } from '../graphql/fixtures';
@@ -20,6 +20,9 @@ describe('import table', () => {
let wrapper;
let apolloProvider;
+ const FAKE_GROUP = generateFakeEntry({ id: 1, status: STATUSES.NONE });
+ const FAKE_PAGE_INFO = { page: 1, perPage: 20, total: 40, totalPages: 2 };
+
const createComponent = ({ bulkImportSourceGroups }) => {
apolloProvider = createMockApollo([], {
Query: {
@@ -34,6 +37,12 @@ describe('import table', () => {
});
wrapper = shallowMount(ImportTable, {
+ propsData: {
+ sourceUrl: 'https://demo.host',
+ },
+ stubs: {
+ GlSprintf,
+ },
localVue,
apolloProvider,
});
@@ -62,25 +71,50 @@ describe('import table', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
+ it('renders message about empty state when no groups are available for import', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: [],
+ pageInfo: FAKE_PAGE_INFO,
+ }),
+ });
+ await waitForPromises();
+
+ expect(wrapper.find(GlEmptyState).props().title).toBe('No groups available for import');
+ });
+
it('renders import row for each group in response', async () => {
const FAKE_GROUPS = [
generateFakeEntry({ id: 1, status: STATUSES.NONE }),
generateFakeEntry({ id: 2, status: STATUSES.FINISHED }),
];
createComponent({
- bulkImportSourceGroups: () => FAKE_GROUPS,
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ }),
});
await waitForPromises();
expect(wrapper.findAll(ImportTableRow)).toHaveLength(FAKE_GROUPS.length);
});
- describe('converts row events to mutation invocations', () => {
- const FAKE_GROUP = generateFakeEntry({ id: 1, status: STATUSES.NONE });
+ it('does not render status string when result list is empty', async () => {
+ createComponent({
+ bulkImportSourceGroups: jest.fn().mockResolvedValue({
+ nodes: [],
+ pageInfo: FAKE_PAGE_INFO,
+ }),
+ });
+ await waitForPromises();
+
+ expect(wrapper.text()).not.toContain('Showing 1-0');
+ });
+ describe('converts row events to mutation invocations', () => {
beforeEach(() => {
createComponent({
- bulkImportSourceGroups: () => [FAKE_GROUP],
+ bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
});
return waitForPromises();
});
@@ -100,4 +134,115 @@ describe('import table', () => {
});
});
});
+
+ describe('pagination', () => {
+ const bulkImportSourceGroupsQueryMock = jest
+ .fn()
+ .mockResolvedValue({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO });
+
+ beforeEach(() => {
+ createComponent({
+ bulkImportSourceGroups: bulkImportSourceGroupsQueryMock,
+ });
+ return waitForPromises();
+ });
+
+ it('correctly passes pagination info from query', () => {
+ expect(wrapper.find(PaginationLinks).props().pageInfo).toStrictEqual(FAKE_PAGE_INFO);
+ });
+
+ it('updates page when page change is requested', async () => {
+ const REQUESTED_PAGE = 2;
+ wrapper.find(PaginationLinks).props().change(REQUESTED_PAGE);
+
+ await waitForPromises();
+ expect(bulkImportSourceGroupsQueryMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ page: REQUESTED_PAGE }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('updates status text when page is changed', async () => {
+ const REQUESTED_PAGE = 2;
+ bulkImportSourceGroupsQueryMock.mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: {
+ page: 2,
+ total: 38,
+ perPage: 20,
+ totalPages: 2,
+ },
+ });
+ wrapper.find(PaginationLinks).props().change(REQUESTED_PAGE);
+ await waitForPromises();
+
+ expect(wrapper.text()).toContain('Showing 21-21 of 38');
+ });
+ });
+
+ describe('filters', () => {
+ const bulkImportSourceGroupsQueryMock = jest
+ .fn()
+ .mockResolvedValue({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO });
+
+ beforeEach(() => {
+ createComponent({
+ bulkImportSourceGroups: bulkImportSourceGroupsQueryMock,
+ });
+ return waitForPromises();
+ });
+
+ const findFilterInput = () => wrapper.find(GlSearchBoxByClick);
+
+ it('properly passes filter to graphql query when search box is submitted', async () => {
+ createComponent({
+ bulkImportSourceGroups: bulkImportSourceGroupsQueryMock,
+ });
+ await waitForPromises();
+
+ const FILTER_VALUE = 'foo';
+ findFilterInput().vm.$emit('submit', FILTER_VALUE);
+ await waitForPromises();
+
+ expect(bulkImportSourceGroupsQueryMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ filter: FILTER_VALUE }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('updates status string when search box is submitted', async () => {
+ createComponent({
+ bulkImportSourceGroups: bulkImportSourceGroupsQueryMock,
+ });
+ await waitForPromises();
+
+ const FILTER_VALUE = 'foo';
+ findFilterInput().vm.$emit('submit', FILTER_VALUE);
+ await waitForPromises();
+
+ expect(wrapper.text()).toContain('Showing 1-1 of 40 groups matching filter "foo"');
+ });
+
+ it('properly resets filter in graphql query when search box is cleared', async () => {
+ const FILTER_VALUE = 'foo';
+ findFilterInput().vm.$emit('submit', FILTER_VALUE);
+ await waitForPromises();
+
+ bulkImportSourceGroupsQueryMock.mockClear();
+ await apolloProvider.defaultClient.resetStore();
+ findFilterInput().vm.$emit('clear');
+ await waitForPromises();
+
+ expect(bulkImportSourceGroupsQueryMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ filter: '' }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+ });
});
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 514ed411138..4d3d2c41bbe 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,20 +1,20 @@
-import MockAdapter from 'axios-mock-adapter';
import { InMemoryCache } from 'apollo-cache-inmemory';
+import MockAdapter from 'axios-mock-adapter';
import { createMockClient } from 'mock-apollo-client';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
+import { STATUSES } from '~/import_entities/constants';
import {
clientTypenames,
createResolvers,
} from '~/import_entities/import_groups/graphql/client_factory';
+import importGroupMutation from '~/import_entities/import_groups/graphql/mutations/import_group.mutation.graphql';
+import setNewNameMutation from '~/import_entities/import_groups/graphql/mutations/set_new_name.mutation.graphql';
+import setTargetNamespaceMutation from '~/import_entities/import_groups/graphql/mutations/set_target_namespace.mutation.graphql';
+import availableNamespacesQuery from '~/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql';
+import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
-import { STATUSES } from '~/import_entities/constants';
-import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
-import availableNamespacesQuery from '~/import_entities/import_groups/graphql/queries/available_namespaces.query.graphql';
-import setTargetNamespaceMutation from '~/import_entities/import_groups/graphql/mutations/set_target_namespace.mutation.graphql';
-import setNewNameMutation from '~/import_entities/import_groups/graphql/mutations/set_new_name.mutation.graphql';
-import importGroupMutation from '~/import_entities/import_groups/graphql/mutations/import_group.mutation.graphql';
+import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import { statusEndpointFixture, availableNamespacesFixture } from './fixtures';
@@ -28,6 +28,7 @@ const FAKE_ENDPOINTS = {
status: '/fake_status_url',
availableNamespaces: '/fake_available_namespaces',
createBulkImport: '/fake_create_bulk_import',
+ jobs: '/fake_jobs',
};
describe('Bulk import resolvers', () => {
@@ -79,33 +80,61 @@ describe('Bulk import resolvers', () => {
axiosMockAdapter
.onGet(FAKE_ENDPOINTS.availableNamespaces)
.reply(httpStatus.OK, availableNamespacesFixture);
-
- const response = await client.query({ query: bulkImportSourceGroupsQuery });
- results = response.data.bulkImportSourceGroups;
});
- it('mirrors REST endpoint response fields', () => {
- const MIRRORED_FIELDS = ['id', 'full_name', 'full_path', 'web_url'];
- expect(
- results.every((r, idx) =>
- MIRRORED_FIELDS.every(
- (field) => r[field] === statusEndpointFixture.importable_data[idx][field],
+ describe('when called', () => {
+ beforeEach(async () => {
+ const response = await client.query({ query: bulkImportSourceGroupsQuery });
+ results = response.data.bulkImportSourceGroups.nodes;
+ });
+
+ it('mirrors REST endpoint response fields', () => {
+ const MIRRORED_FIELDS = ['id', 'full_name', 'full_path', 'web_url'];
+ expect(
+ results.every((r, idx) =>
+ MIRRORED_FIELDS.every(
+ (field) => r[field] === statusEndpointFixture.importable_data[idx][field],
+ ),
),
- ),
- ).toBe(true);
- });
+ ).toBe(true);
+ });
- it('populates each result instance with status field default to none', () => {
- expect(results.every((r) => r.status === STATUSES.NONE)).toBe(true);
- });
+ it('populates each result instance with status field default to none', () => {
+ expect(results.every((r) => r.status === STATUSES.NONE)).toBe(true);
+ });
+
+ it('populates each result instance with import_target defaulted to first available namespace', () => {
+ expect(
+ results.every(
+ (r) => r.import_target.target_namespace === availableNamespacesFixture[0].full_path,
+ ),
+ ).toBe(true);
+ });
- it('populates each result instance with import_target defaulted to first available namespace', () => {
- expect(
- results.every(
- (r) => r.import_target.target_namespace === availableNamespacesFixture[0].full_path,
- ),
- ).toBe(true);
+ it('starts polling when request completes', async () => {
+ const [statusPoller] = StatusPoller.mock.instances;
+ expect(statusPoller.startPolling).toHaveBeenCalled();
+ });
});
+
+ it.each`
+ variable | queryParam | value
+ ${'filter'} | ${'filter'} | ${'demo'}
+ ${'perPage'} | ${'per_page'} | ${30}
+ ${'page'} | ${'page'} | ${3}
+ `(
+ 'properly passes GraphQL variable $variable as REST $queryParam query parameter',
+ async ({ variable, queryParam, value }) => {
+ await client.query({
+ query: bulkImportSourceGroupsQuery,
+ variables: { [variable]: value },
+ });
+ const restCall = axiosMockAdapter.history.get.find(
+ (q) => q.url === FAKE_ENDPOINTS.status,
+ );
+ expect(restCall.params[queryParam]).toBe(value);
+ },
+ );
});
});
@@ -117,20 +146,28 @@ describe('Bulk import resolvers', () => {
client.writeQuery({
query: bulkImportSourceGroupsQuery,
data: {
- bulkImportSourceGroups: [
- {
- __typename: clientTypenames.BulkImportSourceGroup,
- id: GROUP_ID,
- status: STATUSES.NONE,
- web_url: 'https://fake.host/1',
- full_path: 'fake_group_1',
- full_name: 'fake_name_1',
- import_target: {
- target_namespace: 'root',
- new_name: 'group1',
+ bulkImportSourceGroups: {
+ nodes: [
+ {
+ __typename: clientTypenames.BulkImportSourceGroup,
+ id: GROUP_ID,
+ status: STATUSES.NONE,
+ web_url: 'https://fake.host/1',
+ full_path: 'fake_group_1',
+ full_name: 'fake_name_1',
+ import_target: {
+ target_namespace: 'root',
+ new_name: 'group1',
+ },
},
+ ],
+ pageInfo: {
+ page: 1,
+ perPage: 20,
+ total: 37,
+ totalPages: 2,
},
- ],
+ },
},
});
@@ -140,7 +177,7 @@ describe('Bulk import resolvers', () => {
fetchPolicy: 'cache-only',
})
.subscribe(({ data }) => {
- results = data.bulkImportSourceGroups;
+ results = data.bulkImportSourceGroups.nodes;
});
});
@@ -174,7 +211,9 @@ describe('Bulk import resolvers', () => {
});
await waitForPromises();
- const { bulkImportSourceGroups: intermediateResults } = client.readQuery({
+ const {
+ bulkImportSourceGroups: { nodes: intermediateResults },
+ } = client.readQuery({
query: bulkImportSourceGroupsQuery,
});
@@ -182,7 +221,7 @@ describe('Bulk import resolvers', () => {
});
it('sets group status to STARTED when request completes', async () => {
- axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK);
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
await client.mutate({
mutation: importGroupMutation,
variables: { sourceGroupId: GROUP_ID },
@@ -191,16 +230,6 @@ describe('Bulk import resolvers', () => {
expect(results[0].status).toBe(STATUSES.STARTED);
});
- it('starts polling when request completes', async () => {
- axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK);
- await client.mutate({
- mutation: importGroupMutation,
- variables: { sourceGroupId: GROUP_ID },
- });
- const [statusPoller] = StatusPoller.mock.instances;
- expect(statusPoller.startPolling).toHaveBeenCalled();
- });
-
it('resets status to NONE if request fails', async () => {
axiosMockAdapter
.onPost(FAKE_ENDPOINTS.createBulkImport)
diff --git a/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js
index 5940ea544ea..ca987ab3ab4 100644
--- a/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js
+++ b/spec/frontend/import_entities/import_groups/graphql/services/source_groups_manager_spec.js
@@ -1,7 +1,7 @@
import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
-import { SourceGroupsManager } from '~/import_entities/import_groups/graphql/services/source_groups_manager';
-import ImportSourceGroupFragment from '~/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql';
import { clientTypenames } from '~/import_entities/import_groups/graphql/client_factory';
+import ImportSourceGroupFragment from '~/import_entities/import_groups/graphql/fragments/bulk_import_source_group_item.fragment.graphql';
+import { SourceGroupsManager } from '~/import_entities/import_groups/graphql/services/source_groups_manager';
describe('SourceGroupsManager', () => {
let manager;
diff --git a/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js b/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
index e7f1626f81d..a5fc4e18a02 100644
--- a/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
+++ b/spec/frontend/import_entities/import_groups/graphql/services/status_poller_spec.js
@@ -1,215 +1,113 @@
-import { createMockClient } from 'mock-apollo-client';
-import { InMemoryCache } from 'apollo-cache-inmemory';
-import waitForPromises from 'helpers/wait_for_promises';
-
+import MockAdapter from 'axios-mock-adapter';
+import Visibility from 'visibilityjs';
import createFlash from '~/flash';
-import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
-import bulkImportSourceGroupsQuery from '~/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql';
import { STATUSES } from '~/import_entities/constants';
import { SourceGroupsManager } from '~/import_entities/import_groups/graphql/services/source_groups_manager';
-import { generateFakeEntry } from '../fixtures';
+import { StatusPoller } from '~/import_entities/import_groups/graphql/services/status_poller';
+import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
+jest.mock('visibilityjs');
jest.mock('~/flash');
+jest.mock('~/lib/utils/poll');
jest.mock('~/import_entities/import_groups/graphql/services/source_groups_manager', () => ({
SourceGroupsManager: jest.fn().mockImplementation(function mock() {
this.setImportStatus = jest.fn();
+ this.findByImportId = jest.fn();
}),
}));
-const TEST_POLL_INTERVAL = 1000;
+const FAKE_POLL_PATH = '/fake/poll/path';
+const CLIENT_MOCK = {};
describe('Bulk import status poller', () => {
let poller;
- let clientMock;
+ let mockAdapter;
- const listQueryCacheCalls = () =>
- clientMock.readQuery.mock.calls.filter((call) => call[0].query === bulkImportSourceGroupsQuery);
+ const getPollHistory = () => mockAdapter.history.get.filter((x) => x.url === FAKE_POLL_PATH);
beforeEach(() => {
- clientMock = createMockClient({
- cache: new InMemoryCache({
- fragmentMatcher: { match: () => true },
- }),
- });
-
- jest.spyOn(clientMock, 'readQuery');
-
- poller = new StatusPoller({
- client: clientMock,
- interval: TEST_POLL_INTERVAL,
- });
+ mockAdapter = new MockAdapter(axios);
+ mockAdapter.onGet(FAKE_POLL_PATH).reply(200, {});
+ poller = new StatusPoller({ client: CLIENT_MOCK, pollPath: FAKE_POLL_PATH });
});
- describe('general behavior', () => {
- beforeEach(() => {
- clientMock.cache.writeQuery({
- query: bulkImportSourceGroupsQuery,
- data: { bulkImportSourceGroups: [] },
- });
- });
-
- it('does not perform polling when constructed', () => {
- jest.runOnlyPendingTimers();
- expect(listQueryCacheCalls()).toHaveLength(0);
- });
-
- it('immediately start polling when requested', async () => {
- await poller.startPolling();
- expect(listQueryCacheCalls()).toHaveLength(1);
- });
-
- it('constantly polls when started', async () => {
- poller.startPolling();
- expect(listQueryCacheCalls()).toHaveLength(1);
-
- jest.advanceTimersByTime(TEST_POLL_INTERVAL);
- expect(listQueryCacheCalls()).toHaveLength(2);
-
- jest.advanceTimersByTime(TEST_POLL_INTERVAL);
- expect(listQueryCacheCalls()).toHaveLength(3);
- });
-
- it('does not start polling when requested multiple times', async () => {
- poller.startPolling();
- expect(listQueryCacheCalls()).toHaveLength(1);
-
- poller.startPolling();
- expect(listQueryCacheCalls()).toHaveLength(1);
- });
-
- it('stops polling when requested', async () => {
- poller.startPolling();
- expect(listQueryCacheCalls()).toHaveLength(1);
-
- poller.stopPolling();
- jest.runOnlyPendingTimers();
- expect(listQueryCacheCalls()).toHaveLength(1);
- });
-
- it('does not query server when list is empty', async () => {
- jest.spyOn(clientMock, 'query');
- poller.startPolling();
- expect(clientMock.query).not.toHaveBeenCalled();
- });
+ it('creates source group manager with proper client', () => {
+ expect(SourceGroupsManager.mock.calls).toHaveLength(1);
+ const [[{ client }]] = SourceGroupsManager.mock.calls;
+ expect(client).toBe(CLIENT_MOCK);
});
- it('does not query server when no groups have STARTED status', async () => {
- clientMock.cache.writeQuery({
- query: bulkImportSourceGroupsQuery,
- data: {
- bulkImportSourceGroups: [STATUSES.NONE, STATUSES.FINISHED].map((status, idx) =>
- generateFakeEntry({ status, id: idx }),
- ),
- },
- });
-
- jest.spyOn(clientMock, 'query');
+ it('creates poller with proper config', () => {
+ expect(Poll.mock.calls).toHaveLength(1);
+ const [[pollConfig]] = Poll.mock.calls;
+ expect(typeof pollConfig.method).toBe('string');
+
+ const pollOperation = pollConfig.resource[pollConfig.method];
+ expect(typeof pollOperation).toBe('function');
+ });
+
+ it('invokes axios when polling is performed', async () => {
+ const [[pollConfig]] = Poll.mock.calls;
+ const pollOperation = pollConfig.resource[pollConfig.method];
+ expect(getPollHistory()).toHaveLength(0);
+
+ pollOperation();
+ await axios.waitForAll();
+
+ expect(getPollHistory()).toHaveLength(1);
+ });
+
+ it('subscribes to visibility changes', () => {
+ expect(Visibility.change).toHaveBeenCalled();
+ });
+
+ it.each`
+ isHidden | action
+ ${true} | ${'stop'}
+ ${false} | ${'restart'}
+ `('$action polling when hidden is $isHidden', ({ action, isHidden }) => {
+ const [pollInstance] = Poll.mock.instances;
+ const [[changeHandler]] = Visibility.change.mock.calls;
+ Visibility.hidden.mockReturnValue(isHidden);
+ expect(pollInstance[action]).not.toHaveBeenCalled();
+
+ changeHandler();
+
+ expect(pollInstance[action]).toHaveBeenCalled();
+ });
+
+ it('does not perform polling when constructed', async () => {
+ await axios.waitForAll();
+
+ expect(getPollHistory()).toHaveLength(0);
+ });
+
+ it('immediately start polling when requested', async () => {
+ const [pollInstance] = Poll.mock.instances;
+
poller.startPolling();
- expect(clientMock.query).not.toHaveBeenCalled();
+
+ expect(pollInstance.makeRequest).toHaveBeenCalled();
+ });
+
+ it('when error occurs shows flash with error', () => {
+ const [[pollConfig]] = Poll.mock.calls;
+ pollConfig.errorCallback();
+ expect(createFlash).toHaveBeenCalled();
});
- describe('when there are groups which have STARTED status', () => {
- const TARGET_NAMESPACE = 'root';
-
- const STARTED_GROUP_1 = {
- status: STATUSES.STARTED,
- id: 'started1',
- import_target: {
- target_namespace: TARGET_NAMESPACE,
- new_name: 'group1',
- },
- };
-
- const STARTED_GROUP_2 = {
- status: STATUSES.STARTED,
- id: 'started2',
- import_target: {
- target_namespace: TARGET_NAMESPACE,
- new_name: 'group2',
- },
- };
-
- const NOT_STARTED_GROUP = {
- status: STATUSES.NONE,
- id: 'not_started',
- import_target: {
- target_namespace: TARGET_NAMESPACE,
- new_name: 'group3',
- },
- };
-
- it('query server only for groups with STATUSES.STARTED', async () => {
- clientMock.cache.writeQuery({
- query: bulkImportSourceGroupsQuery,
- data: {
- bulkImportSourceGroups: [
- STARTED_GROUP_1,
- NOT_STARTED_GROUP,
- STARTED_GROUP_2,
- ].map((group) => generateFakeEntry(group)),
- },
- });
-
- clientMock.query = jest.fn().mockResolvedValue({ data: {} });
- poller.startPolling();
-
- expect(clientMock.query).toHaveBeenCalledTimes(1);
- await waitForPromises();
- const [[doc]] = clientMock.query.mock.calls;
- const { selections } = doc.query.definitions[0].selectionSet;
- expect(selections.every((field) => field.name.value === 'group')).toBeTruthy();
- expect(selections).toHaveLength(2);
- expect(selections.map((sel) => sel.arguments[0].value.value)).toStrictEqual([
- `${TARGET_NAMESPACE}/${STARTED_GROUP_1.import_target.new_name}`,
- `${TARGET_NAMESPACE}/${STARTED_GROUP_2.import_target.new_name}`,
- ]);
- });
-
- it('updates statuses only for groups in response', async () => {
- clientMock.cache.writeQuery({
- query: bulkImportSourceGroupsQuery,
- data: {
- bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map((group) =>
- generateFakeEntry(group),
- ),
- },
- });
-
- clientMock.query = jest.fn().mockResolvedValue({ data: { group0: {} } });
- poller.startPolling();
- await waitForPromises();
- const [managerInstance] = SourceGroupsManager.mock.instances;
- expect(managerInstance.setImportStatus).toHaveBeenCalledTimes(1);
- expect(managerInstance.setImportStatus).toHaveBeenCalledWith(
- expect.objectContaining({ id: STARTED_GROUP_1.id }),
- STATUSES.FINISHED,
- );
- });
-
- describe('when error occurs', () => {
- beforeEach(() => {
- clientMock.cache.writeQuery({
- query: bulkImportSourceGroupsQuery,
- data: {
- bulkImportSourceGroups: [STARTED_GROUP_1, STARTED_GROUP_2].map((group) =>
- generateFakeEntry(group),
- ),
- },
- });
-
- clientMock.query = jest.fn().mockRejectedValue(new Error('dummy error'));
- poller.startPolling();
- return waitForPromises();
- });
-
- it('reports an error', () => {
- expect(createFlash).toHaveBeenCalled();
- });
-
- it('continues polling', async () => {
- jest.advanceTimersByTime(TEST_POLL_INTERVAL);
- expect(listQueryCacheCalls()).toHaveLength(2);
- });
- });
+ it('when success response arrives updates relevant group status', () => {
+ const FAKE_ID = 5;
+ const [[pollConfig]] = Poll.mock.calls;
+ const [managerInstance] = SourceGroupsManager.mock.instances;
+ managerInstance.findByImportId.mockReturnValue({ id: FAKE_ID });
+
+ pollConfig.successCallback({ data: [{ id: FAKE_ID, status_name: STATUSES.FINISHED }] });
+
+ expect(managerInstance.setImportStatus).toHaveBeenCalledWith(
+ expect.objectContaining({ id: FAKE_ID }),
+ STATUSES.FINISHED,
+ );
});
});
diff --git a/spec/frontend/import_entities/import_projects/components/bitbucket_status_table_spec.js b/spec/frontend/import_entities/import_projects/components/bitbucket_status_table_spec.js
index 8f8c01a8b81..ea88c361f7b 100644
--- a/spec/frontend/import_entities/import_projects/components/bitbucket_status_table_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/bitbucket_status_table_spec.js
@@ -1,7 +1,7 @@
-import { nextTick } from 'vue';
+import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
-import { GlAlert } from '@gitlab/ui';
import BitbucketStatusTable from '~/import_entities/import_projects/components/bitbucket_status_table.vue';
import ImportProjectsTable from '~/import_entities/import_projects/components/import_projects_table.vue';
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 27f642d15c8..d9f4168f1a5 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,18 +1,20 @@
+import { GlLoadingIcon, GlButton, GlIntersectionObserver, GlFormInput } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
-import state from '~/import_entities/import_projects/store/state';
-import * as getters from '~/import_entities/import_projects/store/getters';
import { STATUSES } from '~/import_entities/constants';
import ImportProjectsTable from '~/import_entities/import_projects/components/import_projects_table.vue';
import ProviderRepoTableRow from '~/import_entities/import_projects/components/provider_repo_table_row.vue';
+import * as getters from '~/import_entities/import_projects/store/getters';
+import state from '~/import_entities/import_projects/store/state';
describe('ImportProjectsTable', () => {
let wrapper;
const findFilterField = () =>
- wrapper.find('input[data-qa-selector="githubish_import_filter_field"]');
+ wrapper
+ .findAllComponents(GlFormInput)
+ .wrappers.find((w) => w.attributes('placeholder') === 'Filter your repositories by name');
const providerTitle = 'THE PROVIDER';
const providerRepo = {
@@ -205,7 +207,7 @@ describe('ImportProjectsTable', () => {
it('does not render filtering input field when filterable is false', () => {
createComponent({ filterable: false });
- expect(findFilterField().exists()).toBe(false);
+ expect(findFilterField()).toBeUndefined();
});
describe('when paginatable is set to true', () => {
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 2ed11ae277e..e15389be53a 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,10 +1,10 @@
+import { GlBadge, GlButton } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlBadge } from '@gitlab/ui';
-import ProviderRepoTableRow from '~/import_entities/import_projects/components/provider_repo_table_row.vue';
-import ImportStatus from '~/import_entities/components/import_status.vue';
import { STATUSES } from '~/import_entities//constants';
+import ImportStatus from '~/import_entities/components/import_status.vue';
+import ProviderRepoTableRow from '~/import_entities/import_projects/components/provider_repo_table_row.vue';
import Select2Select from '~/vue_shared/components/select2_select.vue';
describe('ProviderRepoTableRow', () => {
@@ -34,7 +34,7 @@ describe('ProviderRepoTableRow', () => {
}
const findImportButton = () => {
- const buttons = wrapper.findAll('button').filter((node) => node.text() === 'Import');
+ const buttons = wrapper.findAllComponents(GlButton).filter((node) => node.text() === 'Import');
return buttons.length ? buttons.at(0) : buttons;
};
@@ -91,7 +91,7 @@ describe('ProviderRepoTableRow', () => {
});
it('imports repo when clicking import button', async () => {
- findImportButton().trigger('click');
+ findImportButton().vm.$emit('click');
await nextTick();
diff --git a/spec/frontend/import_entities/import_projects/store/actions_spec.js b/spec/frontend/import_entities/import_projects/store/actions_spec.js
index bd731dc3929..9bff77cd34a 100644
--- a/spec/frontend/import_entities/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/actions_spec.js
@@ -1,9 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { STATUSES } from '~/import_entities/constants';
+import actionsFactory from '~/import_entities/import_projects/store/actions';
+import { getImportTarget } from '~/import_entities/import_projects/store/getters';
import {
REQUEST_REPOS,
RECEIVE_REPOS_SUCCESS,
@@ -18,10 +19,9 @@ import {
SET_PAGE,
SET_FILTER,
} from '~/import_entities/import_projects/store/mutation_types';
-import actionsFactory from '~/import_entities/import_projects/store/actions';
-import { getImportTarget } from '~/import_entities/import_projects/store/getters';
import state from '~/import_entities/import_projects/store/state';
-import { STATUSES } from '~/import_entities/constants';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
jest.mock('~/flash');
diff --git a/spec/frontend/import_entities/import_projects/store/getters_spec.js b/spec/frontend/import_entities/import_projects/store/getters_spec.js
index f0ccffc19f2..55826b20ca3 100644
--- a/spec/frontend/import_entities/import_projects/store/getters_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/getters_spec.js
@@ -1,3 +1,4 @@
+import { STATUSES } from '~/import_entities/constants';
import {
isLoading,
isImportingAnyRepo,
@@ -6,7 +7,6 @@ import {
importAllCount,
getImportTarget,
} from '~/import_entities/import_projects/store/getters';
-import { STATUSES } from '~/import_entities/constants';
import state from '~/import_entities/import_projects/store/state';
const IMPORTED_REPO = {
diff --git a/spec/frontend/import_entities/import_projects/store/mutations_spec.js b/spec/frontend/import_entities/import_projects/store/mutations_spec.js
index 8b7ddffe6f4..e062d889325 100644
--- a/spec/frontend/import_entities/import_projects/store/mutations_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/mutations_spec.js
@@ -1,7 +1,7 @@
+import { STATUSES } from '~/import_entities/constants';
import * as types from '~/import_entities/import_projects/store/mutation_types';
import mutations from '~/import_entities/import_projects/store/mutations';
import getInitialState from '~/import_entities/import_projects/store/state';
-import { STATUSES } from '~/import_entities/constants';
describe('import_projects store mutations', () => {
let state;
diff --git a/spec/frontend/import_entities/import_projects/utils_spec.js b/spec/frontend/import_entities/import_projects/utils_spec.js
index 7d9c4b7137e..d705f0acbfe 100644
--- a/spec/frontend/import_entities/import_projects/utils_spec.js
+++ b/spec/frontend/import_entities/import_projects/utils_spec.js
@@ -1,9 +1,9 @@
+import { STATUSES } from '~/import_entities/constants';
import {
isProjectImportable,
isIncompatible,
getImportStatus,
} from '~/import_entities/import_projects/utils';
-import { STATUSES } from '~/import_entities/constants';
describe('import_projects utils', () => {
const COMPATIBLE_PROJECT = {
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 8212776742c..df681658081 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -1,10 +1,6 @@
-import { mount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon, GlTable, GlAvatar, GlEmptyState } from '@gitlab/ui';
-import Tracking from '~/tracking';
-import { visitUrl, joinPaths, mergeUrlParams } from '~/lib/utils/url_utility';
+import { mount } from '@vue/test-utils';
import IncidentsList from '~/incidents/components/incidents_list.vue';
-import SeverityToken from '~/sidebar/components/severity/severity.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
I18N,
TH_CREATED_AT_TEST_ID,
@@ -14,6 +10,10 @@ import {
trackIncidentCreateNewOptions,
trackIncidentListViewsOptions,
} from '~/incidents/constants';
+import { visitUrl, joinPaths, mergeUrlParams } from '~/lib/utils/url_utility';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
+import Tracking from '~/tracking';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import mockIncidents from '../mocks/incidents.json';
jest.mock('~/lib/utils/url_utility', () => ({
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 2b3c803be08..4398d568501 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
@@ -9,9 +9,7 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
<div
class="settings-header"
>
- <h4
- class="gl-my-3! gl-py-1"
- >
+ <h4>
Incidents
diff --git a/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js b/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js
index 5010fc0bb5c..5476e895c68 100644
--- a/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js
+++ b/spec/frontend/incidents_settings/components/incidents_settings_service_spec.js
@@ -1,9 +1,9 @@
import AxiosMockAdapter from 'axios-mock-adapter';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { ERROR_MSG } from '~/incidents_settings/constants';
+import IncidentsSettingsService from '~/incidents_settings/incidents_settings_service';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
-import IncidentsSettingsService from '~/incidents_settings/incidents_settings_service';
-import { ERROR_MSG } from '~/incidents_settings/constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
jest.mock('~/flash');
diff --git a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
index c80d9ad2e5b..ff40f1fa008 100644
--- a/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
+++ b/spec/frontend/incidents_settings/components/incidents_settings_tabs_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlTab } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import IncidentsSettingTabs from '~/incidents_settings/components/incidents_settings_tabs.vue';
describe('IncidentsSettingTabs', () => {
diff --git a/spec/frontend/incidents_settings/components/pagerduty_form_spec.js b/spec/frontend/incidents_settings/components/pagerduty_form_spec.js
index 50d0de8a753..2ffd1292ddc 100644
--- a/spec/frontend/incidents_settings/components/pagerduty_form_spec.js
+++ b/spec/frontend/incidents_settings/components/pagerduty_form_spec.js
@@ -1,6 +1,6 @@
+import { GlAlert, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import { GlAlert, GlModal } from '@gitlab/ui';
import PagerDutySettingsForm from '~/incidents_settings/components/pagerduty_form.vue';
describe('Alert integration settings form', () => {
diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
index 38bcb1e0aab..76fd6dd3a48 100644
--- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js
+++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
@@ -1,8 +1,7 @@
-import { mount } from '@vue/test-utils';
import { GlFormCheckbox } from '@gitlab/ui';
-import { createStore } from '~/integrations/edit/store';
-
+import { mount } from '@vue/test-utils';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
+import { createStore } from '~/integrations/edit/store';
describe('ActiveCheckbox', () => {
let wrapper;
diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
index b570ab4e844..1c126f60c37 100644
--- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
+++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js
@@ -1,8 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
-import { createStore } from '~/integrations/edit/store';
-
+import { shallowMount } from '@vue/test-utils';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
+import { createStore } from '~/integrations/edit/store';
describe('ConfirmationModal', () => {
let wrapper;
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index ecd03103992..aaca9fc4e62 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
describe('DynamicField', () => {
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 97e77ac87ab..df855674804 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,38 +1,47 @@
import { shallowMount } from '@vue/test-utils';
+import { setHTMLFixture } from 'helpers/fixtures';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
-import { createStore } from '~/integrations/edit/store';
-import IntegrationForm from '~/integrations/edit/components/integration_form.vue';
-import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
-import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
-import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
+import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
+import IntegrationForm from '~/integrations/edit/components/integration_form.vue';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
+import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
+import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
+import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
-import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
import { integrationLevels } from '~/integrations/edit/constants';
+import { createStore } from '~/integrations/edit/store';
describe('IntegrationForm', () => {
let wrapper;
- const createComponent = (customStateProps = {}, featureFlags = {}, initialState = {}) => {
- wrapper = shallowMount(IntegrationForm, {
- propsData: {},
- store: createStore({
- customState: { ...mockIntegrationProps, ...customStateProps },
- ...initialState,
+ const createComponent = ({
+ customStateProps = {},
+ featureFlags = {},
+ initialState = {},
+ props = {},
+ } = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(IntegrationForm, {
+ propsData: { ...props },
+ store: createStore({
+ customState: { ...mockIntegrationProps, ...customStateProps },
+ ...initialState,
+ }),
+ stubs: {
+ OverrideDropdown,
+ ActiveCheckbox,
+ ConfirmationModal,
+ JiraTriggerFields,
+ TriggerFields,
+ },
+ provide: {
+ glFeatures: featureFlags,
+ },
}),
- stubs: {
- OverrideDropdown,
- ActiveCheckbox,
- ConfirmationModal,
- JiraTriggerFields,
- TriggerFields,
- },
- provide: {
- glFeatures: featureFlags,
- },
- });
+ );
};
afterEach(() => {
@@ -63,7 +72,9 @@ describe('IntegrationForm', () => {
describe('showActive is false', () => {
it('does not render ActiveCheckbox', () => {
createComponent({
- showActive: false,
+ customStateProps: {
+ showActive: false,
+ },
});
expect(findActiveCheckbox().exists()).toBe(false);
@@ -73,7 +84,9 @@ describe('IntegrationForm', () => {
describe('integrationLevel is instance', () => {
it('renders ConfirmationModal', () => {
createComponent({
- integrationLevel: integrationLevels.INSTANCE,
+ customStateProps: {
+ integrationLevel: integrationLevels.INSTANCE,
+ },
});
expect(findConfirmationModal().exists()).toBe(true);
@@ -82,7 +95,9 @@ describe('IntegrationForm', () => {
describe('resetPath is empty', () => {
it('does not render ResetConfirmationModal and button', () => {
createComponent({
- integrationLevel: integrationLevels.INSTANCE,
+ customStateProps: {
+ integrationLevel: integrationLevels.INSTANCE,
+ },
});
expect(findResetButton().exists()).toBe(false);
@@ -93,8 +108,10 @@ describe('IntegrationForm', () => {
describe('resetPath is present', () => {
it('renders ResetConfirmationModal and button', () => {
createComponent({
- integrationLevel: integrationLevels.INSTANCE,
- resetPath: 'resetPath',
+ customStateProps: {
+ integrationLevel: integrationLevels.INSTANCE,
+ resetPath: 'resetPath',
+ },
});
expect(findResetButton().exists()).toBe(true);
@@ -106,7 +123,9 @@ describe('IntegrationForm', () => {
describe('integrationLevel is group', () => {
it('renders ConfirmationModal', () => {
createComponent({
- integrationLevel: integrationLevels.GROUP,
+ customStateProps: {
+ integrationLevel: integrationLevels.GROUP,
+ },
});
expect(findConfirmationModal().exists()).toBe(true);
@@ -115,7 +134,9 @@ describe('IntegrationForm', () => {
describe('resetPath is empty', () => {
it('does not render ResetConfirmationModal and button', () => {
createComponent({
- integrationLevel: integrationLevels.GROUP,
+ customStateProps: {
+ integrationLevel: integrationLevels.GROUP,
+ },
});
expect(findResetButton().exists()).toBe(false);
@@ -126,8 +147,10 @@ describe('IntegrationForm', () => {
describe('resetPath is present', () => {
it('renders ResetConfirmationModal and button', () => {
createComponent({
- integrationLevel: integrationLevels.GROUP,
- resetPath: 'resetPath',
+ customStateProps: {
+ integrationLevel: integrationLevels.GROUP,
+ resetPath: 'resetPath',
+ },
});
expect(findResetButton().exists()).toBe(true);
@@ -139,7 +162,9 @@ describe('IntegrationForm', () => {
describe('integrationLevel is project', () => {
it('does not render ConfirmationModal', () => {
createComponent({
- integrationLevel: 'project',
+ customStateProps: {
+ integrationLevel: 'project',
+ },
});
expect(findConfirmationModal().exists()).toBe(false);
@@ -147,8 +172,10 @@ describe('IntegrationForm', () => {
it('does not render ResetConfirmationModal and button', () => {
createComponent({
- integrationLevel: 'project',
- resetPath: 'resetPath',
+ customStateProps: {
+ integrationLevel: 'project',
+ resetPath: 'resetPath',
+ },
});
expect(findResetButton().exists()).toBe(false);
@@ -158,7 +185,9 @@ describe('IntegrationForm', () => {
describe('type is "slack"', () => {
beforeEach(() => {
- createComponent({ type: 'slack' });
+ createComponent({
+ customStateProps: { type: 'slack' },
+ });
});
it('does not render JiraTriggerFields', () => {
@@ -172,14 +201,19 @@ describe('IntegrationForm', () => {
describe('type is "jira"', () => {
it('renders JiraTriggerFields', () => {
- createComponent({ type: 'jira' });
+ createComponent({
+ customStateProps: { type: 'jira' },
+ });
expect(findJiraTriggerFields().exists()).toBe(true);
});
describe('featureFlag jiraIssuesIntegration is false', () => {
it('does not render JiraIssuesFields', () => {
- createComponent({ type: 'jira' }, { jiraIssuesIntegration: false });
+ createComponent({
+ customStateProps: { type: 'jira' },
+ featureFlags: { jiraIssuesIntegration: false },
+ });
expect(findJiraIssuesFields().exists()).toBe(false);
});
@@ -187,8 +221,10 @@ describe('IntegrationForm', () => {
describe('featureFlag jiraIssuesIntegration is true', () => {
it('renders JiraIssuesFields', () => {
- createComponent({ type: 'jira' }, { jiraIssuesIntegration: true });
-
+ createComponent({
+ customStateProps: { type: 'jira' },
+ featureFlags: { jiraIssuesIntegration: true },
+ });
expect(findJiraIssuesFields().exists()).toBe(true);
});
});
@@ -200,8 +236,10 @@ describe('IntegrationForm', () => {
const type = 'slack';
createComponent({
- triggerEvents: events,
- type,
+ customStateProps: {
+ triggerEvents: events,
+ type,
+ },
});
expect(findTriggerFields().exists()).toBe(true);
@@ -218,7 +256,9 @@ describe('IntegrationForm', () => {
];
createComponent({
- fields,
+ customStateProps: {
+ fields,
+ },
});
const dynamicFields = wrapper.findAll(DynamicField);
@@ -232,13 +272,11 @@ describe('IntegrationForm', () => {
describe('defaultState state is null', () => {
it('does not render OverrideDropdown', () => {
- createComponent(
- {},
- {},
- {
+ createComponent({
+ initialState: {
defaultState: null,
},
- );
+ });
expect(findOverrideDropdown().exists()).toBe(false);
});
@@ -246,18 +284,43 @@ describe('IntegrationForm', () => {
describe('defaultState state is an object', () => {
it('renders OverrideDropdown', () => {
- createComponent(
- {},
- {},
- {
+ createComponent({
+ initialState: {
defaultState: {
...mockIntegrationProps,
},
},
- );
+ });
expect(findOverrideDropdown().exists()).toBe(true);
});
});
+
+ describe('with `helpHtml` prop', () => {
+ const mockTestId = 'jest-help-html-test';
+
+ setHTMLFixture(`
+ <div data-testid="${mockTestId}">
+ <svg class="gl-icon">
+ <use></use>
+ </svg>
+ </div>
+ `);
+
+ it('renders `helpHtml`', async () => {
+ const mockHelpHtml = document.querySelector(`[data-testid="${mockTestId}"]`);
+
+ createComponent({
+ props: {
+ helpHtml: mockHelpHtml.outerHTML,
+ },
+ });
+
+ const helpHtml = wrapper.findByTestId(mockTestId);
+
+ expect(helpHtml.isVisible()).toBe(true);
+ expect(helpHtml.find('svg').isVisible()).toBe(true);
+ });
+ });
});
});
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 eaeed2703d1..3938e7c7c22 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,20 +1,23 @@
-import { mount } from '@vue/test-utils';
-
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
+import eventHub from '~/integrations/edit/event_hub';
describe('JiraIssuesFields', () => {
let wrapper;
const defaultProps = {
- showJiraIssuesIntegration: true,
editProjectPath: '/edit',
+ showJiraIssuesIntegration: true,
+ showJiraVulnerabilitiesIntegration: true,
};
- const createComponent = (props) => {
+ const createComponent = ({ props, ...options } = {}) => {
wrapper = mount(JiraIssuesFields, {
propsData: { ...defaultProps, ...props },
+ stubs: ['jira-issue-creation-vulnerabilities'],
+ ...options,
});
};
@@ -28,11 +31,14 @@ describe('JiraIssuesFields', () => {
const findEnableCheckbox = () => wrapper.find(GlFormCheckbox);
const findProjectKey = () => wrapper.find(GlFormInput);
const expectedBannerText = 'This is a Premium feature';
+ const findJiraForVulnerabilities = () => wrapper.find('[data-testid="jira-for-vulnerabilities"]');
+ const setEnableCheckbox = async (isEnabled = true) =>
+ findEnableCheckbox().vm.$emit('input', isEnabled);
describe('template', () => {
describe('upgrade banner for non-Premium user', () => {
beforeEach(() => {
- createComponent({ initialProjectKey: '', showJiraIssuesIntegration: false });
+ createComponent({ props: { initialProjectKey: '', showJiraIssuesIntegration: false } });
});
it('shows upgrade banner', () => {
@@ -47,7 +53,7 @@ describe('JiraIssuesFields', () => {
describe('Enable Jira issues checkbox', () => {
beforeEach(() => {
- createComponent({ initialProjectKey: '' });
+ createComponent({ props: { initialProjectKey: '' } });
});
it('does not show upgrade banner', () => {
@@ -69,20 +75,16 @@ describe('JiraIssuesFields', () => {
});
describe('on enable issues', () => {
- it('enables project_key input', () => {
- findEnableCheckbox().vm.$emit('input', true);
+ it('enables project_key input', async () => {
+ await setEnableCheckbox(true);
- return wrapper.vm.$nextTick().then(() => {
- expect(findProjectKey().attributes('disabled')).toBeUndefined();
- });
+ expect(findProjectKey().attributes('disabled')).toBeUndefined();
});
- it('requires project_key input', () => {
- findEnableCheckbox().vm.$emit('input', true);
+ it('requires project_key input', async () => {
+ await setEnableCheckbox(true);
- return wrapper.vm.$nextTick().then(() => {
- expect(findProjectKey().attributes('required')).toBe('required');
- });
+ expect(findProjectKey().attributes('required')).toBe('required');
});
});
});
@@ -103,10 +105,60 @@ describe('JiraIssuesFields', () => {
});
it('does not contain warning when GitLab issues is disabled', () => {
- createComponent({ gitlabIssuesEnabled: false });
+ createComponent({ props: { gitlabIssuesEnabled: false } });
expect(wrapper.text()).not.toContain(expectedText);
});
});
+
+ describe('Vulnerabilities creation', () => {
+ beforeEach(() => {
+ createComponent({ provide: { glFeatures: { jiraForVulnerabilities: true } } });
+ });
+
+ it.each([true, false])(
+ 'shows the jira-vulnerabilities component correctly when jira issues enables is set to "%s"',
+ async (hasJiraIssuesEnabled) => {
+ await setEnableCheckbox(hasJiraIssuesEnabled);
+
+ expect(findJiraForVulnerabilities().exists()).toBe(hasJiraIssuesEnabled);
+ },
+ );
+
+ it('passes down the correct initial-issue-type-id value when value is empty', async () => {
+ await setEnableCheckbox(true);
+ expect(findJiraForVulnerabilities().attributes('initial-issue-type-id')).toBeUndefined();
+ });
+
+ it('passes down the correct initial-issue-type-id value when value is not empty', async () => {
+ const jiraIssueType = 'some-jira-issue-type';
+ wrapper.setProps({ initialVulnerabilitiesIssuetype: jiraIssueType });
+ await setEnableCheckbox(true);
+ expect(findJiraForVulnerabilities().attributes('initial-issue-type-id')).toBe(
+ jiraIssueType,
+ );
+ });
+
+ it('emits "getJiraIssueTypes" to the eventHub when the jira-vulnerabilities component requests to fetch issue types', async () => {
+ const eventHubEmitSpy = jest.spyOn(eventHub, '$emit');
+
+ await setEnableCheckbox(true);
+ await findJiraForVulnerabilities().vm.$emit('request-get-issue-types');
+
+ expect(eventHubEmitSpy).toHaveBeenCalledWith('getJiraIssueTypes');
+ });
+
+ describe('with "jiraForVulnerabilities" feature flag disabled', () => {
+ beforeEach(async () => {
+ createComponent({
+ provide: { glFeatures: { jiraForVulnerabilities: false } },
+ });
+ });
+
+ it('does not show section', () => {
+ expect(findJiraForVulnerabilities().exists()).toBe(false);
+ });
+ });
+ });
});
});
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 a69e8d6e163..c6e7ee44355 100644
--- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlFormCheckbox } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
describe('JiraTriggerFields', () => {
diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
index f312c456d5f..592f4514e45 100644
--- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js
+++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
@@ -1,9 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlLink } from '@gitlab/ui';
-import { createStore } from '~/integrations/edit/store';
-
-import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants';
+import { shallowMount } from '@vue/test-utils';
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
+import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants';
+import { createStore } from '~/integrations/edit/store';
describe('OverrideDropdown', () => {
let wrapper;
diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
index 3fa1e5b5f5a..3e5326812b1 100644
--- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlFormGroup, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
describe('TriggerFields', () => {
diff --git a/spec/frontend/integrations/edit/store/actions_spec.js b/spec/frontend/integrations/edit/store/actions_spec.js
index 1ff881c265d..e2f4c138ece 100644
--- a/spec/frontend/integrations/edit/store/actions_spec.js
+++ b/spec/frontend/integrations/edit/store/actions_spec.js
@@ -1,6 +1,4 @@
import testAction from 'helpers/vuex_action_helper';
-import { refreshCurrentPage } from '~/lib/utils/url_utility';
-import createState from '~/integrations/edit/store/state';
import {
setOverride,
setIsSaving,
@@ -9,8 +7,13 @@ import {
requestResetIntegration,
receiveResetIntegrationSuccess,
receiveResetIntegrationError,
+ requestJiraIssueTypes,
+ receiveJiraIssueTypesSuccess,
+ receiveJiraIssueTypesError,
} from '~/integrations/edit/store/actions';
import * as types from '~/integrations/edit/store/mutation_types';
+import createState from '~/integrations/edit/store/state';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility');
@@ -70,4 +73,34 @@ describe('Integration form store actions', () => {
]);
});
});
+
+ describe('requestJiraIssueTypes', () => {
+ it('should commit SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE and SET_IS_LOADING_JIRA_ISSUE_TYPES mutations', () => {
+ return testAction(requestJiraIssueTypes, null, state, [
+ { type: types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, payload: '' },
+ { type: types.SET_IS_LOADING_JIRA_ISSUE_TYPES, payload: true },
+ ]);
+ });
+ });
+
+ describe('receiveJiraIssueTypesSuccess', () => {
+ it('should commit SET_IS_LOADING_JIRA_ISSUE_TYPES and SET_JIRA_ISSUE_TYPES mutations', () => {
+ const issueTypes = ['issue', 'epic'];
+ return testAction(receiveJiraIssueTypesSuccess, issueTypes, state, [
+ { type: types.SET_IS_LOADING_JIRA_ISSUE_TYPES, payload: false },
+ { type: types.SET_JIRA_ISSUE_TYPES, payload: issueTypes },
+ ]);
+ });
+ });
+
+ describe('receiveJiraIssueTypesError', () => {
+ it('should commit SET_IS_LOADING_JIRA_ISSUE_TYPES, SET_JIRA_ISSUE_TYPES and SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE mutations', () => {
+ const errorMessage = 'something went wrong';
+ return testAction(receiveJiraIssueTypesError, errorMessage, state, [
+ { type: types.SET_IS_LOADING_JIRA_ISSUE_TYPES, payload: false },
+ { type: types.SET_JIRA_ISSUE_TYPES, payload: [] },
+ { type: types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, payload: errorMessage },
+ ]);
+ });
+ });
});
diff --git a/spec/frontend/integrations/edit/store/getters_spec.js b/spec/frontend/integrations/edit/store/getters_spec.js
index 7d4532a1059..ad7a887dff2 100644
--- a/spec/frontend/integrations/edit/store/getters_spec.js
+++ b/spec/frontend/integrations/edit/store/getters_spec.js
@@ -4,9 +4,9 @@ import {
isDisabled,
propsSource,
} from '~/integrations/edit/store/getters';
-import createState from '~/integrations/edit/store/state';
-import mutations from '~/integrations/edit/store/mutations';
import * as types from '~/integrations/edit/store/mutation_types';
+import mutations from '~/integrations/edit/store/mutations';
+import createState from '~/integrations/edit/store/state';
import { mockIntegrationProps } from '../mock_data';
describe('Integration form store getters', () => {
diff --git a/spec/frontend/integrations/edit/store/mutations_spec.js b/spec/frontend/integrations/edit/store/mutations_spec.js
index 81f39adb87f..18faa2f6bba 100644
--- a/spec/frontend/integrations/edit/store/mutations_spec.js
+++ b/spec/frontend/integrations/edit/store/mutations_spec.js
@@ -1,6 +1,6 @@
+import * as types from '~/integrations/edit/store/mutation_types';
import mutations from '~/integrations/edit/store/mutations';
import createState from '~/integrations/edit/store/state';
-import * as types from '~/integrations/edit/store/mutation_types';
describe('Integration form store mutations', () => {
let state;
@@ -56,4 +56,30 @@ describe('Integration form store mutations', () => {
expect(state.isResetting).toBe(false);
});
});
+
+ describe(`${types.SET_JIRA_ISSUE_TYPES}`, () => {
+ it('sets jiraIssueTypes', () => {
+ const jiraIssueTypes = ['issue', 'epic'];
+ mutations[types.SET_JIRA_ISSUE_TYPES](state, jiraIssueTypes);
+
+ expect(state.jiraIssueTypes).toBe(jiraIssueTypes);
+ });
+ });
+
+ describe(`${types.SET_IS_LOADING_JIRA_ISSUE_TYPES}`, () => {
+ it.each([true, false])('sets isLoadingJiraIssueTypes to "%s"', (isLoading) => {
+ mutations[types.SET_IS_LOADING_JIRA_ISSUE_TYPES](state, isLoading);
+
+ expect(state.isLoadingJiraIssueTypes).toBe(isLoading);
+ });
+ });
+
+ describe(`${types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE}`, () => {
+ it('sets loadingJiraIssueTypesErrorMessage', () => {
+ const errorMessage = 'something went wrong';
+ mutations[types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE](state, errorMessage);
+
+ expect(state.loadingJiraIssueTypesErrorMessage).toBe(errorMessage);
+ });
+ });
});
diff --git a/spec/frontend/integrations/edit/store/state_spec.js b/spec/frontend/integrations/edit/store/state_spec.js
index 4d0f4a1da71..6cd84836395 100644
--- a/spec/frontend/integrations/edit/store/state_spec.js
+++ b/spec/frontend/integrations/edit/store/state_spec.js
@@ -9,6 +9,9 @@ describe('Integration form state factory', () => {
isTesting: false,
isResetting: false,
override: false,
+ isLoadingJiraIssueTypes: false,
+ jiraIssueTypes: [],
+ loadingJiraIssueTypesErrorMessage: '',
});
});
diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js
index bba851ad796..348b942703f 100644
--- a/spec/frontend/integrations/integration_settings_form_spec.js
+++ b/spec/frontend/integrations/integration_settings_form_spec.js
@@ -1,6 +1,6 @@
import MockAdaptor from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import axios from '~/lib/utils/axios_utils';
import toast from '~/vue_shared/plugins/global_toast';
jest.mock('~/vue_shared/plugins/global_toast');
@@ -132,4 +132,83 @@ describe('IntegrationSettingsForm', () => {
expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
});
});
+
+ describe('getJiraIssueTypes', () => {
+ let integrationSettingsForm;
+ let formData;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdaptor(axios);
+
+ jest.spyOn(axios, 'put');
+
+ integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
+ integrationSettingsForm.init();
+
+ // eslint-disable-next-line no-jquery/no-serialize
+ formData = integrationSettingsForm.$form.serialize();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('should always dispatch `requestJiraIssueTypes`', async () => {
+ const dispatchSpy = jest.fn();
+
+ mock.onPut(integrationSettingsForm.testEndPoint).networkError();
+
+ integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
+
+ await integrationSettingsForm.getJiraIssueTypes();
+
+ expect(dispatchSpy).toHaveBeenCalledWith('requestJiraIssueTypes');
+ });
+
+ it('should make an ajax request with provided `formData`', async () => {
+ await integrationSettingsForm.getJiraIssueTypes(formData);
+
+ expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
+ });
+
+ it('should dispatch `receiveJiraIssueTypesSuccess` with the correct payload if ajax request is successful', async () => {
+ const mockData = ['ISSUE', 'EPIC'];
+ const dispatchSpy = jest.fn();
+
+ mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
+ error: false,
+ issuetypes: mockData,
+ });
+
+ integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
+
+ await integrationSettingsForm.getJiraIssueTypes(formData);
+
+ expect(dispatchSpy).toHaveBeenCalledWith('receiveJiraIssueTypesSuccess', mockData);
+ });
+
+ it.each(['something went wrong', undefined])(
+ 'should dispatch "receiveJiraIssueTypesError" with a message if the backend responds with error',
+ async (responseErrorMessage) => {
+ const defaultErrorMessage = 'Connection failed. Please check your settings.';
+ const expectedErrorMessage = responseErrorMessage || defaultErrorMessage;
+ const dispatchSpy = jest.fn();
+
+ mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
+ error: true,
+ message: responseErrorMessage,
+ });
+
+ integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
+
+ await integrationSettingsForm.getJiraIssueTypes(formData);
+
+ expect(dispatchSpy).toHaveBeenCalledWith(
+ 'receiveJiraIssueTypesError',
+ expectedErrorMessage,
+ );
+ },
+ );
+ });
});
diff --git a/spec/frontend/invite_member/components/invite_member_modal_spec.js b/spec/frontend/invite_member/components/invite_member_modal_spec.js
index 1140c2a9475..4eff19402a8 100644
--- a/spec/frontend/invite_member/components/invite_member_modal_spec.js
+++ b/spec/frontend/invite_member/components/invite_member_modal_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink, GlModal } from '@gitlab/ui';
-import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
+import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
+import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import InviteMemberModal from '~/invite_member/components/invite_member_modal.vue';
const memberPath = 'member_path';
diff --git a/spec/frontend/invite_member/components/invite_member_trigger_spec.js b/spec/frontend/invite_member/components/invite_member_trigger_spec.js
index 57b8918e3da..67c312fd155 100644
--- a/spec/frontend/invite_member/components/invite_member_trigger_spec.js
+++ b/spec/frontend/invite_member/components/invite_member_trigger_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import InviteMemberTrigger from '~/invite_member/components/invite_member_trigger.vue';
import triggerProvides from './invite_member_trigger_mock_data';
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 fc039bdf6da..e310a00133c 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink, GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
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 450d37a9748..18d6662d2d4 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
const displayText = 'Invite team members';
diff --git a/spec/frontend/invite_members/components/members_token_select_spec.js b/spec/frontend/invite_members/components/members_token_select_spec.js
index ff123a13ce7..a945b99bd54 100644
--- a/spec/frontend/invite_members/components/members_token_select_spec.js
+++ b/spec/frontend/invite_members/components/members_token_select_spec.js
@@ -1,8 +1,8 @@
+import { GlTokenSelector } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import { GlTokenSelector } from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
import { stubComponent } from 'helpers/stub_component';
+import waitForPromises from 'helpers/wait_for_promises';
import * as UserApi from '~/api/user_api';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
diff --git a/spec/frontend/issuable/components/issuable_by_email_spec.js b/spec/frontend/issuable/components/issuable_by_email_spec.js
new file mode 100644
index 00000000000..08a99f29479
--- /dev/null
+++ b/spec/frontend/issuable/components/issuable_by_email_spec.js
@@ -0,0 +1,164 @@
+import { GlModal, GlSprintf, GlFormInputGroup, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
+import httpStatus from '~/lib/utils/http_status';
+
+const initialEmail = 'user@gitlab.com';
+
+const mockToastShow = jest.fn();
+
+describe('IssuableByEmail', () => {
+ let wrapper;
+ let mockAxios;
+ let glModalDirective;
+
+ function createComponent(injectedProperties = {}) {
+ glModalDirective = jest.fn();
+
+ return extendedWrapper(
+ shallowMount(IssuableByEmail, {
+ stubs: {
+ GlModal,
+ GlSprintf,
+ GlFormInputGroup,
+ GlButton,
+ },
+ directives: {
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
+ },
+ },
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ provide: {
+ issuableType: 'issue',
+ initialEmail,
+ ...injectedProperties,
+ },
+ }),
+ );
+ }
+
+ beforeEach(() => {
+ mockAxios = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ mockAxios.restore();
+ });
+
+ const findFormInputGroup = () => wrapper.find(GlFormInputGroup);
+
+ const clickResetEmail = async () => {
+ wrapper.findByTestId('incoming-email-token-reset').vm.$emit('click');
+
+ await waitForPromises();
+ };
+
+ describe('modal button', () => {
+ it.each`
+ issuableType | buttonText
+ ${'issue'} | ${'Email a new issue to this project'}
+ ${'merge_request'} | ${'Email a new merge request to this project'}
+ `(
+ 'renders a link with "$buttonText" when type is "$issuableType"',
+ ({ issuableType, buttonText }) => {
+ wrapper = createComponent({ issuableType });
+ expect(wrapper.findByTestId('issuable-email-modal-btn').text()).toBe(buttonText);
+ },
+ );
+
+ it('opens the modal when the user clicks the button', () => {
+ wrapper = createComponent();
+
+ wrapper.findByTestId('issuable-email-modal-btn').vm.$emit('click');
+
+ expect(glModalDirective).toHaveBeenCalled();
+ });
+ });
+
+ describe('modal', () => {
+ it('renders a read-only email input field', () => {
+ wrapper = createComponent();
+
+ expect(findFormInputGroup().props('value')).toBe('user@gitlab.com');
+ });
+
+ it.each`
+ issuableType | subject | body
+ ${'issue'} | ${'Enter the issue title'} | ${'Enter the issue description'}
+ ${'merge_request'} | ${'Enter the merge request title'} | ${'Enter the merge request description'}
+ `('renders a mailto button when type is "$issuableType"', ({ issuableType, subject, body }) => {
+ wrapper = createComponent({
+ issuableType,
+ initialEmail,
+ });
+
+ expect(wrapper.findByTestId('mail-to-btn').attributes('href')).toBe(
+ `mailto:${initialEmail}?subject=${subject}&body=${body}`,
+ );
+ });
+
+ describe('reset email', () => {
+ const resetPath = 'gitlab-test/new_issuable_address?issuable_type=issue';
+
+ beforeEach(() => {
+ jest.spyOn(axios, 'put');
+ });
+ it('should send request to reset email token', async () => {
+ wrapper = createComponent({
+ issuableType: 'issue',
+ initialEmail,
+ resetPath,
+ });
+
+ await clickResetEmail();
+
+ expect(axios.put).toHaveBeenCalledWith(resetPath);
+ });
+
+ it('should update the email when the request succeeds', async () => {
+ mockAxios.onPut(resetPath).reply(httpStatus.OK, { new_address: 'foo@bar.com' });
+
+ wrapper = createComponent({
+ issuableType: 'issue',
+ initialEmail,
+ resetPath,
+ });
+
+ await clickResetEmail();
+
+ expect(findFormInputGroup().props('value')).toBe('foo@bar.com');
+ });
+
+ it('should show a toast message when the request fails', async () => {
+ mockAxios.onPut(resetPath).reply(httpStatus.NOT_FOUND, {});
+
+ wrapper = createComponent({
+ issuableType: 'issue',
+ initialEmail,
+ resetPath,
+ });
+
+ await clickResetEmail();
+
+ expect(mockToastShow).toHaveBeenCalledWith(
+ 'There was an error when reseting email token.',
+ { type: 'error' },
+ );
+ expect(findFormInputGroup().props('value')).toBe('user@gitlab.com');
+ });
+ });
+ });
+});
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 de2671816d8..173d12757e3 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,6 +1,6 @@
import { mount, shallowMount } from '@vue/test-utils';
-import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
+import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants';
const issuable1 = {
id: 200,
diff --git a/spec/frontend/issuable/related_issues/components/issue_token_spec.js b/spec/frontend/issuable/related_issues/components/issue_token_spec.js
index d5181d4a17a..d6aeacfe07a 100644
--- a/spec/frontend/issuable/related_issues/components/issue_token_spec.js
+++ b/spec/frontend/issuable/related_issues/components/issue_token_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import { PathIdSeparator } from '~/related_issues/constants';
import IssueToken from '~/related_issues/components/issue_token.vue';
+import { PathIdSeparator } from '~/related_issues/constants';
describe('IssueToken', () => {
const idKey = 200;
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 c0889b09adc..a450f912c4e 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
@@ -1,5 +1,5 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlButton, GlIcon } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import {
issuable1,
issuable2,
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 93fe321957c..e5e3478dc59 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
@@ -6,11 +6,11 @@ import {
issuable1,
issuable2,
} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
-import relatedIssuesService from '~/related_issues/services/related_issues_service';
import { linkedIssueTypesMap } from '~/related_issues/constants';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import relatedIssuesService from '~/related_issues/services/related_issues_service';
jest.mock('~/flash');
diff --git a/spec/frontend/issuable_create/components/issuable_form_spec.js b/spec/frontend/issuable_create/components/issuable_form_spec.js
index e489d1dae3e..a074fddf091 100644
--- a/spec/frontend/issuable_create/components/issuable_form_spec.js
+++ b/spec/frontend/issuable_create/components/issuable_form_spec.js
@@ -1,11 +1,10 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import IssuableForm from '~/issuable_create/components/issuable_form.vue';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-import IssuableForm from '~/issuable_create/components/issuable_form.vue';
-
const createComponent = ({
descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
descriptionHelpPath = '/help/user/markdown',
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
index 3c01bf2d319..987acf559e3 100644
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -1,6 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink, GlLabel, GlIcon, GlFormCheckbox } from '@gitlab/ui';
-
+import { shallowMount } from '@vue/test-utils';
+import { useFakeDate } from 'helpers/fake_date';
import IssuableItem from '~/issuable_list/components/issuable_item.vue';
import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
@@ -18,14 +18,19 @@ const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots
slots,
});
+const MOCK_GITLAB_URL = 'http://0.0.0.0:3000';
+
describe('IssuableItem', () => {
+ // The mock data is dependent that this is after our default date
+ useFakeDate(2020, 11, 11);
+
const mockLabels = mockIssuable.labels.nodes;
const mockAuthor = mockIssuable.author;
const originalUrl = gon.gitlab_url;
let wrapper;
beforeEach(() => {
- gon.gitlab_url = 'http://0.0.0.0:3000';
+ gon.gitlab_url = MOCK_GITLAB_URL;
wrapper = createComponent();
});
@@ -70,11 +75,11 @@ describe('IssuableItem', () => {
describe('isIssuableUrlExternal', () => {
it.each`
- issuableWebUrl | urlType | returnValue
- ${'/gitlab-org/gitlab-test/-/issues/2'} | ${'relative'} | ${false}
- ${'http://0.0.0.0:3000/gitlab-org/gitlab-test/-/issues/1'} | ${'absolute and internal'} | ${false}
- ${'http://jira.atlassian.net/browse/IG-1'} | ${'external'} | ${true}
- ${'https://github.com/gitlabhq/gitlabhq/issues/1'} | ${'external'} | ${true}
+ issuableWebUrl | urlType | returnValue
+ ${'/gitlab-org/gitlab-test/-/issues/2'} | ${'relative'} | ${false}
+ ${`${MOCK_GITLAB_URL}/gitlab-org/gitlab-test/-/issues/1`} | ${'absolute and internal'} | ${false}
+ ${'http://jira.atlassian.net/browse/IG-1'} | ${'external'} | ${true}
+ ${'https://github.com/gitlabhq/gitlabhq/issues/1'} | ${'external'} | ${true}
`(
'returns $returnValue when `issuable.webUrl` is $urlType',
async ({ issuableWebUrl, returnValue }) => {
@@ -214,14 +219,32 @@ describe('IssuableItem', () => {
});
describe('template', () => {
- it('renders issuable title', () => {
- const titleEl = wrapper.find('[data-testid="issuable-title"]');
+ it.each`
+ gitlabWebUrl | webUrl | expectedHref | expectedTarget
+ ${undefined} | ${`${MOCK_GITLAB_URL}/issue`} | ${`${MOCK_GITLAB_URL}/issue`} | ${undefined}
+ ${undefined} | ${'https://jira.com/issue'} | ${'https://jira.com/issue'} | ${'_blank'}
+ ${'/gitlab-org/issue'} | ${'https://jira.com/issue'} | ${'/gitlab-org/issue'} | ${undefined}
+ `(
+ 'renders issuable title correctly when `gitlabWebUrl` is `$gitlabWebUrl` and webUrl is `$webUrl`',
+ async ({ webUrl, gitlabWebUrl, expectedHref, expectedTarget }) => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ webUrl,
+ gitlabWebUrl,
+ },
+ });
- expect(titleEl.exists()).toBe(true);
- expect(titleEl.find(GlLink).attributes('href')).toBe(mockIssuable.webUrl);
- expect(titleEl.find(GlLink).attributes('target')).not.toBeDefined();
- expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
- });
+ await wrapper.vm.$nextTick();
+
+ const titleEl = wrapper.find('[data-testid="issuable-title"]');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.find(GlLink).attributes('href')).toBe(expectedHref);
+ expect(titleEl.find(GlLink).attributes('target')).toBe(expectedTarget);
+ expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
+ },
+ );
it('renders checkbox when `showCheckbox` prop is true', async () => {
wrapper.setProps({
@@ -257,6 +280,23 @@ describe('IssuableItem', () => {
);
});
+ it('renders issuable confidential icon when issuable is confidential', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ confidential: true,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const confidentialEl = wrapper.find('[data-testid="issuable-title"]').find(GlIcon);
+
+ expect(confidentialEl.exists()).toBe(true);
+ expect(confidentialEl.props('name')).toBe('eye-slash');
+ expect(confidentialEl.attributes('title')).toBe('Confidential');
+ });
+
it('renders issuable reference', () => {
const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
diff --git a/spec/frontend/issuable_list/components/issuable_list_root_spec.js b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
index add5d9e8e2d..9c57233548c 100644
--- a/spec/frontend/issuable_list/components/issuable_list_root_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
@@ -1,11 +1,11 @@
-import { mount } from '@vue/test-utils';
import { GlSkeletonLoading, GlPagination } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
+import IssuableItem from '~/issuable_list/components/issuable_item.vue';
import IssuableListRoot from '~/issuable_list/components/issuable_list_root.vue';
import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
-import IssuableItem from '~/issuable_list/components/issuable_item.vue';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import { mockIssuableListProps, mockIssuables } from '../mock_data';
diff --git a/spec/frontend/issuable_list/components/issuable_tabs_spec.js b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
index 12611400084..3cc237b9ce9 100644
--- a/spec/frontend/issuable_list/components/issuable_tabs_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlTab, GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
diff --git a/spec/frontend/issuable_show/components/issuable_body_spec.js b/spec/frontend/issuable_show/components/issuable_body_spec.js
index 4ffbbad4f37..bf166bea1e5 100644
--- a/spec/frontend/issuable_show/components/issuable_body_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_body_spec.js
@@ -1,10 +1,11 @@
import { shallowMount } from '@vue/test-utils';
+import { useFakeDate } from 'helpers/fake_date';
import IssuableBody from '~/issuable_show/components/issuable_body.vue';
-import IssuableTitle from '~/issuable_show/components/issuable_title.vue';
import IssuableDescription from '~/issuable_show/components/issuable_description.vue';
import IssuableEditForm from '~/issuable_show/components/issuable_edit_form.vue';
+import IssuableTitle from '~/issuable_show/components/issuable_title.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { mockIssuableShowProps, mockIssuable } from '../mock_data';
@@ -35,6 +36,9 @@ const createComponent = (propsData = issuableBodyProps) =>
});
describe('IssuableBody', () => {
+ // Some assertions expect a date later than our default
+ useFakeDate(2020, 11, 11);
+
let wrapper;
beforeEach(() => {
@@ -98,11 +102,8 @@ describe('IssuableBody', () => {
it('renders issuable edit info', () => {
const editedEl = wrapper.find('small');
- const sanitizedText = editedEl.text().replace(/\n/g, ' ').replace(/\s+/g, ' ');
- expect(sanitizedText).toContain('Edited');
- expect(sanitizedText).toContain('ago');
- expect(sanitizedText).toContain(`by ${mockIssuable.updatedBy.name}`);
+ expect(editedEl.text()).toMatchInterpolatedText('Edited 3 months ago by Administrator');
});
it('renders issuable-edit-form when `editFormVisible` prop is true', async () => {
diff --git a/spec/frontend/issuable_show/components/issuable_description_spec.js b/spec/frontend/issuable_show/components/issuable_description_spec.js
index 1dd8348b098..29ecce1002d 100644
--- a/spec/frontend/issuable_show/components/issuable_description_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_description_spec.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import { shallowMount } from '@vue/test-utils';
+import $ from 'jquery';
import IssuableDescription from '~/issuable_show/components/issuable_description.vue';
diff --git a/spec/frontend/issuable_show/components/issuable_edit_form_spec.js b/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
index 522374f2e9c..184c9fe251c 100644
--- a/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import { shallowMount } from '@vue/test-utils';
import IssuableEditForm from '~/issuable_show/components/issuable_edit_form.vue';
import IssuableEventHub from '~/issuable_show/event_hub';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { mockIssuableShowProps, mockIssuable } from '../mock_data';
diff --git a/spec/frontend/issuable_show/components/issuable_header_spec.js b/spec/frontend/issuable_show/components/issuable_header_spec.js
index f9c20ab04b8..2164caa40a8 100644
--- a/spec/frontend/issuable_show/components/issuable_header_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_header_spec.js
@@ -1,5 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlAvatarLabeled } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import IssuableHeader from '~/issuable_show/components/issuable_header.vue';
@@ -10,21 +11,23 @@ const issuableHeaderProps = {
...mockIssuableShowProps,
};
-const createComponent = (propsData = issuableHeaderProps) =>
- shallowMount(IssuableHeader, {
- propsData,
- slots: {
- 'status-badge': 'Open',
- 'header-actions': `
+const createComponent = (propsData = issuableHeaderProps, { stubs } = {}) =>
+ extendedWrapper(
+ shallowMount(IssuableHeader, {
+ propsData,
+ slots: {
+ 'status-badge': 'Open',
+ 'header-actions': `
<button class="js-close">Close issuable</button>
<a class="js-new" href="/gitlab-org/gitlab-shell/-/issues/new">New issuable</a>
`,
- },
- });
+ },
+ stubs,
+ }),
+ );
describe('IssuableHeader', () => {
let wrapper;
- const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
beforeEach(() => {
wrapper = createComponent();
@@ -63,7 +66,7 @@ describe('IssuableHeader', () => {
describe('template', () => {
it('renders issuable status icon and text', () => {
- const statusBoxEl = findByTestId('status');
+ const statusBoxEl = wrapper.findByTestId('status');
expect(statusBoxEl.exists()).toBe(true);
expect(statusBoxEl.find(GlIcon).props('name')).toBe(mockIssuableShowProps.statusIcon);
@@ -77,7 +80,7 @@ describe('IssuableHeader', () => {
await wrapper.vm.$nextTick();
- const blockedEl = findByTestId('blocked');
+ const blockedEl = wrapper.findByTestId('blocked');
expect(blockedEl.exists()).toBe(true);
expect(blockedEl.find(GlIcon).props('name')).toBe('lock');
@@ -90,7 +93,7 @@ describe('IssuableHeader', () => {
await wrapper.vm.$nextTick();
- const confidentialEl = findByTestId('confidential');
+ const confidentialEl = wrapper.findByTestId('confidential');
expect(confidentialEl.exists()).toBe(true);
expect(confidentialEl.find(GlIcon).props('name')).toBe('eye-slash');
@@ -105,7 +108,7 @@ describe('IssuableHeader', () => {
href: webUrl,
target: '_blank',
};
- const avatarEl = findByTestId('avatar');
+ const avatarEl = wrapper.findByTestId('avatar');
expect(avatarEl.exists()).toBe(true);
expect(avatarEl.attributes()).toMatchObject(avatarElAttrs);
expect(avatarEl.find(GlAvatarLabeled).attributes()).toMatchObject({
@@ -113,20 +116,46 @@ describe('IssuableHeader', () => {
src: avatarUrl,
label: name,
});
+ expect(avatarEl.find(GlAvatarLabeled).find(GlIcon).exists()).toBe(false);
});
it('renders sidebar toggle button', () => {
- const toggleButtonEl = findByTestId('sidebar-toggle');
+ const toggleButtonEl = wrapper.findByTestId('sidebar-toggle');
expect(toggleButtonEl.exists()).toBe(true);
expect(toggleButtonEl.props('icon')).toBe('chevron-double-lg-left');
});
it('renders header actions', () => {
- const actionsEl = findByTestId('header-actions');
+ const actionsEl = wrapper.findByTestId('header-actions');
expect(actionsEl.find('button.js-close').exists()).toBe(true);
expect(actionsEl.find('a.js-new').exists()).toBe(true);
});
+
+ describe('when author exists outside of GitLab', () => {
+ it("renders 'external-link' icon in avatar label", () => {
+ wrapper = createComponent(
+ {
+ ...issuableHeaderProps,
+ author: {
+ ...issuableHeaderProps.author,
+ webUrl: 'https://jira.com/test-user/author.jpg',
+ },
+ },
+ {
+ stubs: {
+ GlAvatarLabeled,
+ },
+ },
+ );
+
+ const avatarEl = wrapper.findComponent(GlAvatarLabeled);
+ const icon = avatarEl.find(GlIcon);
+
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('external-link');
+ });
+ });
});
});
diff --git a/spec/frontend/issuable_show/components/issuable_show_root_spec.js b/spec/frontend/issuable_show/components/issuable_show_root_spec.js
index 6cebfc150f9..3e3778492d2 100644
--- a/spec/frontend/issuable_show/components/issuable_show_root_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_show_root_spec.js
@@ -1,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
+import IssuableBody from '~/issuable_show/components/issuable_body.vue';
+import IssuableHeader from '~/issuable_show/components/issuable_header.vue';
import IssuableShowRoot from '~/issuable_show/components/issuable_show_root.vue';
-import IssuableHeader from '~/issuable_show/components/issuable_header.vue';
-import IssuableBody from '~/issuable_show/components/issuable_body.vue';
import IssuableSidebar from '~/issuable_sidebar/components/issuable_sidebar_root.vue';
import { mockIssuableShowProps, mockIssuable } from '../mock_data';
diff --git a/spec/frontend/issuable_show/components/issuable_title_spec.js b/spec/frontend/issuable_show/components/issuable_title_spec.js
index e8621c763b3..df6fbdea76b 100644
--- a/spec/frontend/issuable_show/components/issuable_title_spec.js
+++ b/spec/frontend/issuable_show/components/issuable_title_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import IssuableTitle from '~/issuable_show/components/issuable_title.vue';
diff --git a/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js b/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js
index 7686dad4644..62a0016d67b 100644
--- a/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js
+++ b/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
import IssuableSidebarRoot from '~/issuable_sidebar/components/issuable_sidebar_root.vue';
diff --git a/spec/frontend/issuable_spec.js b/spec/frontend/issuable_spec.js
index 6712b8bfd34..9c8f1e04609 100644
--- a/spec/frontend/issuable_spec.js
+++ b/spec/frontend/issuable_spec.js
@@ -1,6 +1,3 @@
-import $ from 'jquery';
-import MockAdaptor from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import IssuableIndex from '~/issuable_index';
import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
@@ -22,43 +19,4 @@ describe('Issuable', () => {
expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeDefined();
});
});
-
- describe('resetIncomingEmailToken', () => {
- let mock;
-
- beforeEach(() => {
- const element = document.createElement('a');
- element.classList.add('incoming-email-token-reset');
- element.setAttribute('href', 'foo');
- document.body.appendChild(element);
-
- const input = document.createElement('input');
- input.setAttribute('id', 'issuable_email');
- document.body.appendChild(input);
-
- new IssuableIndex('issue_'); // eslint-disable-line no-new
-
- mock = new MockAdaptor(axios);
-
- mock.onPut('foo').reply(200, {
- new_address: 'testing123',
- });
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should send request to reset email token', (done) => {
- jest.spyOn(axios, 'put');
- document.querySelector('.incoming-email-token-reset').click();
-
- setImmediate(() => {
- expect(axios.put).toHaveBeenCalledWith('foo');
- expect($('#issuable_email').val()).toBe('testing123');
-
- done();
- });
- });
- });
});
diff --git a/spec/frontend/issuable_suggestions/components/item_spec.js b/spec/frontend/issuable_suggestions/components/item_spec.js
index d0dde256edd..39083b3d8fb 100644
--- a/spec/frontend/issuable_suggestions/components/item_spec.js
+++ b/spec/frontend/issuable_suggestions/components/item_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlTooltip, GlLink, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import Suggestion from '~/issuable_suggestions/components/item.vue';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import mockData from '../mock_data';
describe('Issuable suggestions suggestion component', () => {
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index ec2055ca7d1..9e1bc8242fe 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -2,11 +2,15 @@ import { GlIntersectionObserver } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
-import axios from '~/lib/utils/axios_utils';
-import { visitUrl } from '~/lib/utils/url_utility';
import '~/behaviors/markdown/render_gfm';
import IssuableApp from '~/issue_show/components/app.vue';
+import DescriptionComponent from '~/issue_show/components/description.vue';
+import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
+import PinnedLinks from '~/issue_show/components/pinned_links.vue';
+import { IssuableStatus, IssuableStatusText } from '~/issue_show/constants';
import eventHub from '~/issue_show/event_hub';
+import axios from '~/lib/utils/axios_utils';
+import { visitUrl } from '~/lib/utils/url_utility';
import {
appProps,
initialRequest,
@@ -14,10 +18,6 @@ import {
secondRequest,
zoomMeetingUrl,
} from '../mock_data';
-import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
-import DescriptionComponent from '~/issue_show/components/description.vue';
-import PinnedLinks from '~/issue_show/components/pinned_links.vue';
-import { IssuableStatus, IssuableStatusText } from '~/issue_show/constants';
function formatText(text) {
return text.trim().replace(/\s\s+/g, ' ');
@@ -423,7 +423,7 @@ describe('Issuable output', () => {
});
it('shows the form if template names request is successful', () => {
- const mockData = [{ name: 'Bug' }];
+ const mockData = [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }];
mock.onGet('/issuable-templates-path').reply(() => Promise.resolve([200, mockData]));
return wrapper.vm.requestTemplatesAndShowForm().then(() => {
diff --git a/spec/frontend/issue_show/components/description_spec.js b/spec/frontend/issue_show/components/description_spec.js
index de53d98e6be..d59a257a2be 100644
--- a/spec/frontend/issue_show/components/description_spec.js
+++ b/spec/frontend/issue_show/components/description_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import Vue from 'vue';
import '~/behaviors/markdown/render_gfm';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import mountComponent from 'helpers/vue_mount_component_helper';
import Description from '~/issue_show/components/description.vue';
import TaskList from '~/task_list';
import { descriptionProps as props } from '../mock_data';
diff --git a/spec/frontend/issue_show/components/fields/description_spec.js b/spec/frontend/issue_show/components/fields/description_spec.js
index 96c81c419d0..a50be30cf4c 100644
--- a/spec/frontend/issue_show/components/fields/description_spec.js
+++ b/spec/frontend/issue_show/components/fields/description_spec.js
@@ -1,70 +1,70 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import DescriptionField from '~/issue_show/components/fields/description.vue';
import eventHub from '~/issue_show/event_hub';
-import Store from '~/issue_show/stores';
-import descriptionField from '~/issue_show/components/fields/description.vue';
-import { keyboardDownEvent } from '../../helpers';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
describe('Description field component', () => {
- let vm;
- let store;
-
- beforeEach((done) => {
- const Component = Vue.extend(descriptionField);
- const el = document.createElement('div');
- store = new Store({
- titleHtml: '',
- descriptionHtml: '',
- issuableRef: '',
- });
- store.formState.description = 'test';
-
- document.body.appendChild(el);
+ let wrapper;
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ const findTextarea = () => wrapper.find({ ref: 'textarea' });
- vm = new Component({
- el,
+ const mountComponent = (description = 'test') =>
+ shallowMount(DescriptionField, {
+ attachTo: document.body,
propsData: {
markdownPreviewPath: '/',
markdownDocsPath: '/',
- formState: store.formState,
+ formState: {
+ description,
+ },
+ },
+ stubs: {
+ MarkdownField,
},
- }).$mount();
+ });
+
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit');
+ });
- Vue.nextTick(done);
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
});
it('renders markdown field with description', () => {
- expect(vm.$el.querySelector('.md-area textarea').value).toBe('test');
+ wrapper = mountComponent();
+
+ expect(findTextarea().element.value).toBe('test');
});
- it('renders markdown field with a markdown description', (done) => {
- store.formState.description = '**test**';
+ it('renders markdown field with a markdown description', () => {
+ const markdown = '**test**';
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.md-area textarea').value).toBe('**test**');
+ wrapper = mountComponent(markdown);
- done();
- });
+ expect(findTextarea().element.value).toBe(markdown);
});
it('focuses field when mounted', () => {
- expect(document.activeElement).toBe(vm.$refs.textarea);
+ wrapper = mountComponent();
+
+ expect(document.activeElement).toBe(findTextarea().element);
});
it('triggers update with meta+enter', () => {
- vm.$el.querySelector('.md-area textarea').dispatchEvent(keyboardDownEvent(13, true));
+ wrapper = mountComponent();
- expect(eventHub.$emit).toHaveBeenCalled();
+ findTextarea().trigger('keydown.enter', { metaKey: true });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
it('triggers update with ctrl+enter', () => {
- vm.$el.querySelector('.md-area textarea').dispatchEvent(keyboardDownEvent(13, false, true));
+ wrapper = mountComponent();
- expect(eventHub.$emit).toHaveBeenCalled();
- });
+ findTextarea().trigger('keydown.enter', { ctrlKey: true });
- it('has a ref named `textarea`', () => {
- expect(vm.$refs.textarea).not.toBeNull();
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
});
diff --git a/spec/frontend/issue_show/components/fields/description_template_spec.js b/spec/frontend/issue_show/components/fields/description_template_spec.js
index 9ebab31f1ad..1193d4f8add 100644
--- a/spec/frontend/issue_show/components/fields/description_template_spec.js
+++ b/spec/frontend/issue_show/components/fields/description_template_spec.js
@@ -14,8 +14,10 @@ describe('Issue description template component', () => {
vm = new Component({
propsData: {
formState,
- issuableTemplates: [{ name: 'test' }],
+ issuableTemplates: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
+ projectId: 1,
projectPath: '/',
+ namespacePath: '/',
projectNamespace: '/',
},
}).$mount();
@@ -23,7 +25,7 @@ describe('Issue description template component', () => {
it('renders templates as JSON array in data attribute', () => {
expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
- '[{"name":"test"}]',
+ '[{"name":"test","id":"test","project_path":"/","namespace_path":"/"}]',
);
});
diff --git a/spec/frontend/issue_show/components/fields/title_spec.js b/spec/frontend/issue_show/components/fields/title_spec.js
index 99e8658b89f..783ce9eb76c 100644
--- a/spec/frontend/issue_show/components/fields/title_spec.js
+++ b/spec/frontend/issue_show/components/fields/title_spec.js
@@ -1,48 +1,42 @@
-import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import TitleField from '~/issue_show/components/fields/title.vue';
import eventHub from '~/issue_show/event_hub';
-import Store from '~/issue_show/stores';
-import titleField from '~/issue_show/components/fields/title.vue';
-import { keyboardDownEvent } from '../../helpers';
describe('Title field component', () => {
- let vm;
- let store;
+ let wrapper;
- beforeEach(() => {
- const Component = Vue.extend(titleField);
- store = new Store({
- titleHtml: '',
- descriptionHtml: '',
- issuableRef: '',
- });
- store.formState.title = 'test';
+ const findInput = () => wrapper.find({ ref: 'input' });
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit');
- vm = new Component({
+ wrapper = shallowMount(TitleField, {
propsData: {
- formState: store.formState,
+ formState: {
+ title: 'test',
+ },
},
- }).$mount();
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
});
it('renders form control with formState title', () => {
- expect(vm.$el.querySelector('.form-control').value).toBe('test');
+ expect(findInput().element.value).toBe('test');
});
it('triggers update with meta+enter', () => {
- vm.$el.querySelector('.form-control').dispatchEvent(keyboardDownEvent(13, true));
+ findInput().trigger('keydown.enter', { metaKey: true });
- expect(eventHub.$emit).toHaveBeenCalled();
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
it('triggers update with ctrl+enter', () => {
- vm.$el.querySelector('.form-control').dispatchEvent(keyboardDownEvent(13, false, true));
-
- expect(eventHub.$emit).toHaveBeenCalled();
- });
+ findInput().trigger('keydown.enter', { ctrlKey: true });
- it('has a ref named `input`', () => {
- expect(vm.$refs.input).not.toBeNull();
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
});
diff --git a/spec/frontend/issue_show/components/form_spec.js b/spec/frontend/issue_show/components/form_spec.js
index 4e123f606f6..4a8ec3cf66a 100644
--- a/spec/frontend/issue_show/components/form_spec.js
+++ b/spec/frontend/issue_show/components/form_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
-import formComponent from '~/issue_show/components/form.vue';
import Autosave from '~/autosave';
+import formComponent from '~/issue_show/components/form.vue';
import eventHub from '~/issue_show/event_hub';
jest.mock('~/autosave');
@@ -19,6 +19,7 @@ describe('Inline edit form component', () => {
markdownPreviewPath: '/',
markdownDocsPath: '/',
projectPath: '/',
+ projectId: 1,
projectNamespace: '/',
};
@@ -42,7 +43,11 @@ describe('Inline edit form component', () => {
});
it('renders template selector when templates exists', () => {
- createComponent({ issuableTemplates: ['test'] });
+ createComponent({
+ issuableTemplates: [
+ { name: 'test', id: 'test', project_path: 'test', namespace_path: 'test' },
+ ],
+ });
expect(vm.$el.querySelector('.js-issuable-selector-wrap')).not.toBeNull();
});
diff --git a/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js b/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
index 112cb4d4c3a..6758e6192b8 100644
--- a/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
+++ b/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
@@ -1,6 +1,6 @@
+import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import merge from 'lodash/merge';
-import { GlLink } from '@gitlab/ui';
import HighlightBar from '~/issue_show/components/incidents/highlight_bar.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
diff --git a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
index 416870d1408..f46b6ba6f54 100644
--- a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
+++ b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
@@ -1,15 +1,15 @@
+import { GlTab } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import merge from 'lodash/merge';
-import { GlTab } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
-import INVALID_URL from '~/lib/utils/invalid_url';
-import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
-import { descriptionProps } from '../../mock_data';
+import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
import DescriptionComponent from '~/issue_show/components/description.vue';
import HighlightBar from '~/issue_show/components/incidents/highlight_bar.vue';
-import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
+import INVALID_URL from '~/lib/utils/invalid_url';
import Tracking from '~/tracking';
-import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import { descriptionProps } from '../../mock_data';
const mockAlert = {
__typename: 'AlertManagementAlert',
diff --git a/spec/frontend/issue_show/components/pinned_links_spec.js b/spec/frontend/issue_show/components/pinned_links_spec.js
index 2d140fd068a..3fe1f9fd6d9 100644
--- a/spec/frontend/issue_show/components/pinned_links_spec.js
+++ b/spec/frontend/issue_show/components/pinned_links_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import PinnedLinks from '~/issue_show/components/pinned_links.vue';
import { STATUS_PAGE_PUBLISHED, JOIN_ZOOM_MEETING } from '~/issue_show/constants';
diff --git a/spec/frontend/issue_show/components/title_spec.js b/spec/frontend/issue_show/components/title_spec.js
index c274048fdd5..78880a7f540 100644
--- a/spec/frontend/issue_show/components/title_spec.js
+++ b/spec/frontend/issue_show/components/title_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import Store from '~/issue_show/stores';
import titleComponent from '~/issue_show/components/title.vue';
import eventHub from '~/issue_show/event_hub';
+import Store from '~/issue_show/stores';
describe('Title component', () => {
let vm;
diff --git a/spec/frontend/issue_show/helpers.js b/spec/frontend/issue_show/helpers.js
deleted file mode 100644
index 7ca6a22929d..00000000000
--- a/spec/frontend/issue_show/helpers.js
+++ /dev/null
@@ -1,9 +0,0 @@
-export const keyboardDownEvent = (code, metaKey = false, ctrlKey = false) => {
- const e = new CustomEvent('keydown');
-
- e.keyCode = code;
- e.metaKey = metaKey;
- e.ctrlKey = ctrlKey;
-
- return e;
-};
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
index 818f501882b..9cb7059dd7f 100644
--- a/spec/frontend/issue_show/issue_spec.js
+++ b/spec/frontend/issue_show/issue_spec.js
@@ -1,11 +1,11 @@
import MockAdapter from 'axios-mock-adapter';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import { initIssuableApp } from '~/issue_show/issue';
import * as parseData from '~/issue_show/utils/parse_data';
-import { appProps } from './mock_data';
+import axios from '~/lib/utils/axios_utils';
import createStore from '~/notes/stores';
+import { appProps } from './mock_data';
const mock = new MockAdapter(axios);
mock.onGet().reply(200);
diff --git a/spec/frontend/issue_show/mock_data.js b/spec/frontend/issue_show/mock_data.js
index 5a31a550088..fd08c95b454 100644
--- a/spec/frontend/issue_show/mock_data.js
+++ b/spec/frontend/issue_show/mock_data.js
@@ -52,6 +52,7 @@ export const appProps = {
markdownDocsPath: '/',
projectNamespace: '/',
projectPath: '/',
+ projectId: 1,
issuableTemplateNamesPath: '/issuable-templates-path',
zoomMeetingUrl,
publishedIncidentUrl,
diff --git a/spec/frontend/issue_spec.js b/spec/frontend/issue_spec.js
index 303267e784f..fb6caef41e2 100644
--- a/spec/frontend/issue_spec.js
+++ b/spec/frontend/issue_spec.js
@@ -1,7 +1,7 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
+import $ from 'jquery';
import Issue from '~/issue';
+import axios from '~/lib/utils/axios_utils';
import '~/lib/utils/text_utility';
describe('Issue', () => {
diff --git a/spec/frontend/issues_list/components/issuable_spec.js b/spec/frontend/issues_list/components/issuable_spec.js
index b47a84ad7f6..a8bf124373b 100644
--- a/spec/frontend/issues_list/components/issuable_spec.js
+++ b/spec/frontend/issues_list/components/issuable_spec.js
@@ -1,20 +1,26 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf, GlLabel, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import { trimText } from 'helpers/text_helper';
-import initUserPopovers from '~/user_popovers';
+import Issuable from '~/issues_list/components/issuable.vue';
+import { isScopedLabel } from '~/lib/utils/common_utils';
import { formatDate } from '~/lib/utils/datetime_utility';
import { mergeUrlParams } from '~/lib/utils/url_utility';
-import Issuable from '~/issues_list/components/issuable.vue';
+import initUserPopovers from '~/user_popovers';
import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
import { simpleIssue, testAssignees, testLabels } from '../issuable_list_test_data';
-import { isScopedLabel } from '~/lib/utils/common_utils';
jest.mock('~/user_popovers');
-const TEST_NOW = '2019-08-28T20:03:04.713Z';
-const TEST_MONTH_AGO = '2019-07-28';
-const TEST_MONTH_LATER = '2019-09-30';
+const TODAY = new Date();
+
+const createTestDateFromDelta = (timeDelta) =>
+ formatDate(new Date(TODAY.getTime() + timeDelta), 'yyyy-mm-dd');
+
+// TODO: Encapsulate date helpers https://gitlab.com/gitlab-org/gitlab/-/issues/320883
+const MONTHS_IN_MS = 1000 * 60 * 60 * 24 * 31;
+const TEST_MONTH_AGO = createTestDateFromDelta(-MONTHS_IN_MS);
+const TEST_MONTH_LATER = createTestDateFromDelta(MONTHS_IN_MS);
const DATE_FORMAT = 'mmm d, yyyy';
const TEST_USER_NAME = 'Tyler Durden';
const TEST_BASE_URL = `${TEST_HOST}/issues`;
@@ -26,16 +32,8 @@ const TEST_MILESTONE = {
const TEXT_CLOSED = 'CLOSED';
const TEST_META_COUNT = 100;
-// Use FixedDate so that time sensitive info in snapshots don't fail
-class FixedDate extends Date {
- constructor(date = TEST_NOW) {
- super(date);
- }
-}
-
describe('Issuable component', () => {
let issuable;
- let DateOrig;
let wrapper;
const factory = (props = {}, scopedLabelsAvailable = false) => {
@@ -63,15 +61,6 @@ describe('Issuable component', () => {
wrapper = null;
});
- beforeAll(() => {
- DateOrig = window.Date;
- window.Date = FixedDate;
- });
-
- afterAll(() => {
- window.Date = DateOrig;
- });
-
const checkExists = (findFn) => () => findFn().exists();
const hasIcon = (iconName, iconWrapper = wrapper) =>
iconWrapper.findAll(GlIcon).wrappers.some((icon) => icon.props('name') === iconName);
diff --git a/spec/frontend/issues_list/components/issuables_list_app_spec.js b/spec/frontend/issues_list/components/issuables_list_app_spec.js
index 9d603099ff7..fe3d2114463 100644
--- a/spec/frontend/issues_list/components/issuables_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issuables_list_app_spec.js
@@ -1,19 +1,19 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
import {
GlEmptyState,
GlPagination,
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
} from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
+import { shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
import { deprecatedCreateFlash as flash } from '~/flash';
-import IssuablesListApp from '~/issues_list/components/issuables_list_app.vue';
import Issuable from '~/issues_list/components/issuable.vue';
-import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import issueablesEventBus from '~/issues_list/eventhub';
+import IssuablesListApp from '~/issues_list/components/issuables_list_app.vue';
import { PAGE_SIZE, PAGE_SIZE_MANUAL, RELATIVE_POSITION } from '~/issues_list/constants';
+import issueablesEventBus from '~/issues_list/eventhub';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
jest.mock('~/flash');
jest.mock('~/issues_list/eventhub');
@@ -591,5 +591,75 @@ describe('Issuables list component', () => {
expect(findFilteredSearchBar().props('initialFilterValue')).toEqual(['free text']);
});
});
+
+ describe('on filter search', () => {
+ beforeEach(() => {
+ factory({ type: 'jira' });
+
+ window.history.pushState = jest.fn();
+ });
+
+ afterEach(() => {
+ window.history.pushState.mockRestore();
+ });
+
+ const emitOnFilter = (filter) => findFilteredSearchBar().vm.$emit('onFilter', filter);
+
+ describe('empty filter', () => {
+ const mockFilter = [];
+
+ it('updates URL with correct params', () => {
+ emitOnFilter(mockFilter);
+
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ {},
+ '',
+ `${TEST_LOCATION}?state=opened`,
+ );
+ });
+ });
+
+ describe('filter with search term', () => {
+ const mockFilter = [
+ {
+ type: 'filtered-search-term',
+ value: { data: 'free' },
+ },
+ ];
+
+ it('updates URL with correct params', () => {
+ emitOnFilter(mockFilter);
+
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ {},
+ '',
+ `${TEST_LOCATION}?state=opened&search=free`,
+ );
+ });
+ });
+
+ describe('filter with multiple search terms', () => {
+ const mockFilter = [
+ {
+ type: 'filtered-search-term',
+ value: { data: 'free' },
+ },
+ {
+ type: 'filtered-search-term',
+ value: { data: 'text' },
+ },
+ ];
+
+ it('updates URL with correct params', () => {
+ emitOnFilter(mockFilter);
+
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ {},
+ '',
+ `${TEST_LOCATION}?state=opened&search=free+text`,
+ );
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/jira_connect/api_spec.js b/spec/frontend/jira_connect/api_spec.js
index 8fecbee9ca7..240a57c7917 100644
--- a/spec/frontend/jira_connect/api_spec.js
+++ b/spec/frontend/jira_connect/api_spec.js
@@ -1,9 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
+import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/api';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
-import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/api';
-
describe('JiraConnect API', () => {
let mock;
let response;
@@ -14,7 +13,7 @@ describe('JiraConnect API', () => {
const mockJwt = 'jwt';
const mockResponse = { success: true };
- const tokenSpy = jest.fn().mockReturnValue(mockJwt);
+ const tokenSpy = jest.fn((callback) => callback(mockJwt));
window.AP = {
context: {
diff --git a/spec/frontend/jira_connect/components/app_spec.js b/spec/frontend/jira_connect/components/app_spec.js
index be990d5061c..d11b66b2089 100644
--- a/spec/frontend/jira_connect/components/app_spec.js
+++ b/spec/frontend/jira_connect/components/app_spec.js
@@ -1,19 +1,20 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
+import { GlAlert, GlButton, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { GlAlert } from '@gitlab/ui';
+
import JiraConnectApp from '~/jira_connect/components/app.vue';
import createStore from '~/jira_connect/store';
import { SET_ERROR_MESSAGE } from '~/jira_connect/store/mutation_types';
-Vue.use(Vuex);
+jest.mock('~/jira_connect/api');
describe('JiraConnectApp', () => {
let wrapper;
let store;
const findAlert = () => wrapper.findComponent(GlAlert);
+ const findGlButton = () => wrapper.findComponent(GlButton);
+ const findGlModal = () => wrapper.findComponent(GlModal);
const findHeader = () => wrapper.findByTestId('new-jira-connect-ui-heading');
const findHeaderText = () => findHeader().text();
@@ -44,6 +45,33 @@ describe('JiraConnectApp', () => {
expect(findHeaderText()).toBe('Linked namespaces');
});
+ describe('when user is not logged in', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures: { newJiraConnectUi: true },
+ usersPath: '/users',
+ },
+ });
+ });
+
+ it('renders "Sign in" button', () => {
+ expect(findGlButton().text()).toBe('Sign in to add namespaces');
+ expect(findGlModal().exists()).toBe(false);
+ });
+ });
+
+ describe('when user is logged in', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders "Add" button and modal', () => {
+ expect(findGlButton().text()).toBe('Add namespace');
+ expect(findGlModal().exists()).toBe(true);
+ });
+ });
+
describe('newJiraConnectUi is false', () => {
it('does not render new UI', () => {
createComponent({
diff --git a/spec/frontend/jira_connect/components/groups_list_item_spec.js b/spec/frontend/jira_connect/components/groups_list_item_spec.js
index 77577c53cf4..bb247534aca 100644
--- a/spec/frontend/jira_connect/components/groups_list_item_spec.js
+++ b/spec/frontend/jira_connect/components/groups_list_item_spec.js
@@ -1,27 +1,37 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlAvatar } from '@gitlab/ui';
+import { GlAvatar, GlButton } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { mockGroup1 } from '../mock_data';
+import waitForPromises from 'helpers/wait_for_promises';
+import * as JiraConnectApi from '~/jira_connect/api';
import GroupsListItem from '~/jira_connect/components/groups_list_item.vue';
+import { mockGroup1 } from '../mock_data';
describe('GroupsListItem', () => {
let wrapper;
+ const mockSubscriptionPath = 'subscriptionPath';
- const createComponent = () => {
+ const reloadSpy = jest.fn();
+
+ global.AP = {
+ navigator: {
+ reload: reloadSpy,
+ },
+ };
+
+ const createComponent = ({ mountFn = shallowMount } = {}) => {
wrapper = extendedWrapper(
- shallowMount(GroupsListItem, {
+ mountFn(GroupsListItem, {
propsData: {
group: mockGroup1,
},
+ provide: {
+ subscriptionsPath: mockSubscriptionPath,
+ },
}),
);
};
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -30,17 +40,82 @@ describe('GroupsListItem', () => {
const findGlAvatar = () => wrapper.find(GlAvatar);
const findGroupName = () => wrapper.findByTestId('group-list-item-name');
const findGroupDescription = () => wrapper.findByTestId('group-list-item-description');
+ const findLinkButton = () => wrapper.find(GlButton);
+ const clickLinkButton = () => findLinkButton().trigger('click');
- it('renders group avatar', () => {
- expect(findGlAvatar().exists()).toBe(true);
- expect(findGlAvatar().props('src')).toBe(mockGroup1.avatar_url);
- });
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders group avatar', () => {
+ expect(findGlAvatar().exists()).toBe(true);
+ expect(findGlAvatar().props('src')).toBe(mockGroup1.avatar_url);
+ });
+
+ it('renders group name', () => {
+ expect(findGroupName().text()).toBe(mockGroup1.full_name);
+ });
- it('renders group name', () => {
- expect(findGroupName().text()).toBe(mockGroup1.full_name);
+ it('renders group description', () => {
+ expect(findGroupDescription().text()).toBe(mockGroup1.description);
+ });
+
+ it('renders Link button', () => {
+ expect(findLinkButton().exists()).toBe(true);
+ expect(findLinkButton().text()).toBe('Link');
+ });
});
- it('renders group description', () => {
- expect(findGroupDescription().text()).toBe(mockGroup1.description);
+ describe('on Link button click', () => {
+ let addSubscriptionSpy;
+
+ beforeEach(() => {
+ createComponent({ mountFn: mount });
+
+ addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
+ });
+
+ it('sets button to loading and sends request', async () => {
+ expect(findLinkButton().props('loading')).toBe(false);
+
+ clickLinkButton();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findLinkButton().props('loading')).toBe(true);
+
+ expect(addSubscriptionSpy).toHaveBeenCalledWith(mockSubscriptionPath, mockGroup1.full_path);
+ });
+
+ describe('when request is successful', () => {
+ it('reloads the page', async () => {
+ clickLinkButton();
+
+ await waitForPromises();
+
+ expect(reloadSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when request has errors', () => {
+ const mockErrorMessage = 'error message';
+ const mockError = { response: { data: { error: mockErrorMessage } } };
+
+ beforeEach(() => {
+ addSubscriptionSpy = jest
+ .spyOn(JiraConnectApi, 'addSubscription')
+ .mockRejectedValue(mockError);
+ });
+
+ it('emits `error` event', async () => {
+ clickLinkButton();
+
+ await waitForPromises();
+
+ expect(reloadSpy).not.toHaveBeenCalled();
+ expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
+ });
+ });
});
});
diff --git a/spec/frontend/jira_connect/components/groups_list_spec.js b/spec/frontend/jira_connect/components/groups_list_spec.js
index 94f158e6344..5c645eccc0e 100644
--- a/spec/frontend/jira_connect/components/groups_list_spec.js
+++ b/spec/frontend/jira_connect/components/groups_list_spec.js
@@ -1,5 +1,5 @@
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import { fetchGroups } from '~/jira_connect/api';
@@ -28,6 +28,7 @@ describe('GroupsList', () => {
wrapper = null;
});
+ const findGlAlert = () => wrapper.find(GlAlert);
const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findAllItems = () => wrapper.findAll(GroupsListItem);
const findFirstItem = () => findAllItems().at(0);
@@ -45,6 +46,18 @@ describe('GroupsList', () => {
});
});
+ describe('error fetching groups', () => {
+ it('renders error message', async () => {
+ fetchGroups.mockRejectedValue();
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findGlAlert().exists()).toBe(true);
+ expect(findGlAlert().text()).toBe('Failed to load namespaces. Please try again.');
+ });
+ });
+
describe('no groups returned', () => {
it('renders empty state', async () => {
fetchGroups.mockResolvedValue(mockEmptyResponse);
@@ -57,15 +70,28 @@ describe('GroupsList', () => {
});
describe('with groups returned', () => {
- it('renders groups list', async () => {
+ beforeEach(async () => {
fetchGroups.mockResolvedValue({ data: [mockGroup1, mockGroup2] });
createComponent();
await waitForPromises();
+ });
+ it('renders groups list', () => {
expect(findAllItems().length).toBe(2);
expect(findFirstItem().props('group')).toBe(mockGroup1);
expect(findSecondItem().props('group')).toBe(mockGroup2);
});
+
+ it('shows error message on $emit from item', async () => {
+ const errorMessage = 'error message';
+
+ findFirstItem().vm.$emit('error', errorMessage);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlAlert().exists()).toBe(true);
+ expect(findGlAlert().text()).toContain(errorMessage);
+ });
});
});
diff --git a/spec/frontend/jira_connect/index_spec.js b/spec/frontend/jira_connect/index_spec.js
new file mode 100644
index 00000000000..eb54fe6476f
--- /dev/null
+++ b/spec/frontend/jira_connect/index_spec.js
@@ -0,0 +1,56 @@
+import waitForPromises from 'helpers/wait_for_promises';
+import { initJiraConnect } from '~/jira_connect';
+import { removeSubscription } from '~/jira_connect/api';
+
+jest.mock('~/jira_connect/api', () => ({
+ removeSubscription: jest.fn().mockResolvedValue(),
+ getLocation: jest.fn().mockResolvedValue('test/location'),
+}));
+
+describe('initJiraConnect', () => {
+ window.AP = {
+ navigator: {
+ reload: jest.fn(),
+ },
+ };
+
+ beforeEach(async () => {
+ setFixtures(`
+ <a class="js-jira-connect-sign-in" href="https://gitlab.com">Sign In</a>
+ <a class="js-jira-connect-sign-in" href="https://gitlab.com">Another Sign In</a>
+
+ <a href="https://gitlab.com/sub1" class="js-jira-connect-remove-subscription">Remove</a>
+ <a href="https://gitlab.com/sub2" class="js-jira-connect-remove-subscription">Remove</a>
+ <a href="https://gitlab.com/sub3" class="js-jira-connect-remove-subscription">Remove</a>
+ `);
+
+ await initJiraConnect();
+ });
+
+ describe('Sign in links', () => {
+ it('have `return_to` query parameter', () => {
+ Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
+ expect(el.href).toContain('return_to=test/location');
+ });
+ });
+ });
+
+ describe('`remove subscription` buttons', () => {
+ describe('on click', () => {
+ it('calls `removeSubscription`', () => {
+ Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach(
+ (removeSubscriptionButton) => {
+ removeSubscriptionButton.dispatchEvent(new Event('click'));
+
+ waitForPromises();
+
+ expect(removeSubscription).toHaveBeenCalledWith(removeSubscriptionButton.href);
+ expect(removeSubscription).toHaveBeenCalledTimes(1);
+
+ removeSubscription.mockClear();
+ },
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/mock_data.js b/spec/frontend/jira_connect/mock_data.js
index 31565912489..22255fabc3d 100644
--- a/spec/frontend/jira_connect/mock_data.js
+++ b/spec/frontend/jira_connect/mock_data.js
@@ -3,6 +3,7 @@ export const mockGroup1 = {
avatar_url: 'avatar.png',
name: 'Gitlab Org',
full_name: 'Gitlab Org',
+ full_path: 'gitlab-org',
description: 'Open source software to collaborate on code',
};
@@ -11,5 +12,6 @@ export const mockGroup2 = {
avatar_url: 'avatar.png',
name: 'Gitlab Com',
full_name: 'Gitlab Com',
+ full_path: 'gitlab-com',
description: 'For GitLab company related projects',
};
diff --git a/spec/frontend/jira_import/components/jira_import_form_spec.js b/spec/frontend/jira_import/components/jira_import_form_spec.js
index 00fb8f5435e..7a550d85204 100644
--- a/spec/frontend/jira_import/components/jira_import_form_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_form_spec.js
@@ -1,11 +1,21 @@
-import { GlAlert, GlButton, GlDropdown, GlFormSelect, GlLabel, GlTable } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlFormSelect,
+ GlLabel,
+ GlSearchBoxByType,
+ GlTable,
+} from '@gitlab/ui';
import { getByRole } from '@testing-library/dom';
import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
import getJiraUserMappingMutation from '~/jira_import/queries/get_jira_user_mapping.mutation.graphql';
import initiateJiraImportMutation from '~/jira_import/queries/initiate_jira_import.mutation.graphql';
+import searchProjectMembersQuery from '~/jira_import/queries/search_project_members.query.graphql';
+import axios from '~/lib/utils/axios_utils';
import {
imports,
issuesPath,
@@ -19,6 +29,7 @@ import {
describe('JiraImportForm', () => {
let axiosMock;
let mutateSpy;
+ let querySpy;
let wrapper;
const currentUsername = 'mrgitlab';
@@ -72,6 +83,7 @@ describe('JiraImportForm', () => {
$apollo: {
loading,
mutate,
+ query: querySpy,
},
},
currentUsername,
@@ -79,19 +91,21 @@ describe('JiraImportForm', () => {
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
- mutateSpy = jest.fn(() =>
- Promise.resolve({
- data: {
- jiraImportStart: { errors: [] },
- jiraImportUsers: { jiraUsers: [], errors: [] },
- },
- }),
- );
+ mutateSpy = jest.fn().mockResolvedValue({
+ data: {
+ jiraImportStart: { errors: [] },
+ jiraImportUsers: { jiraUsers: [], errors: [] },
+ },
+ });
+ querySpy = jest.fn().mockResolvedValue({
+ data: { project: { projectMembers: { nodes: [] } } },
+ });
});
afterEach(() => {
axiosMock.restore();
mutateSpy.mockRestore();
+ querySpy.mockRestore();
wrapper.destroy();
wrapper = null;
});
@@ -236,6 +250,53 @@ describe('JiraImportForm', () => {
});
});
+ describe('member search', () => {
+ describe('when searching for a member', () => {
+ beforeEach(() => {
+ querySpy = jest.fn().mockResolvedValue({
+ data: {
+ project: {
+ projectMembers: {
+ nodes: [
+ {
+ user: {
+ id: 7,
+ name: 'Frederic Chopin',
+ username: 'fchopin',
+ },
+ },
+ ],
+ },
+ },
+ },
+ });
+
+ wrapper = mountComponent({ mountFunction: mount });
+
+ wrapper.find(GlSearchBoxByType).vm.$emit('input', 'fred');
+ });
+
+ it('makes a GraphQL call', () => {
+ const queryArgument = {
+ query: searchProjectMembersQuery,
+ variables: {
+ fullPath: projectPath,
+ search: 'fred',
+ },
+ };
+
+ expect(querySpy).toHaveBeenCalledWith(expect.objectContaining(queryArgument));
+ });
+
+ it('updates the user list', () => {
+ expect(getUserDropdown().findAll(GlDropdownItem)).toHaveLength(1);
+ expect(getUserDropdown().find(GlDropdownItem).text()).toContain(
+ 'fchopin (Frederic Chopin)',
+ );
+ });
+ });
+ });
+
describe('buttons', () => {
describe('"Continue" button', () => {
it('is shown', () => {
diff --git a/spec/frontend/jira_import/mock_data.js b/spec/frontend/jira_import/mock_data.js
index 51dd939283e..8dc8ce08f49 100644
--- a/spec/frontend/jira_import/mock_data.js
+++ b/spec/frontend/jira_import/mock_data.js
@@ -1,6 +1,6 @@
import getJiraImportDetailsQuery from '~/jira_import/queries/get_jira_import_details.query.graphql';
-import { IMPORT_STATE } from '~/jira_import/utils/jira_import_utils';
import { userMappingsPageSize } from '~/jira_import/utils/constants';
+import { IMPORT_STATE } from '~/jira_import/utils/jira_import_utils';
export const fullPath = 'gitlab-org/gitlab-test';
diff --git a/spec/frontend/jira_import/utils/jira_import_utils_spec.js b/spec/frontend/jira_import/utils/jira_import_utils_spec.js
index 0992c9e8d16..9696d95f8c4 100644
--- a/spec/frontend/jira_import/utils/jira_import_utils_spec.js
+++ b/spec/frontend/jira_import/utils/jira_import_utils_spec.js
@@ -1,4 +1,5 @@
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issues_list/constants';
import {
calculateJiraImportLabel,
extractJiraProjectsOptions,
@@ -8,7 +9,6 @@ import {
setFinishedAlertHideMap,
shouldShowFinishedAlert,
} from '~/jira_import/utils/jira_import_utils';
-import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issues_list/constants';
useLocalStorageSpy();
diff --git a/spec/frontend/jobs/components/artifacts_block_spec.js b/spec/frontend/jobs/components/artifacts_block_spec.js
index 134463c6763..0c7c0a6c311 100644
--- a/spec/frontend/jobs/components/artifacts_block_spec.js
+++ b/spec/frontend/jobs/components/artifacts_block_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import { getTimeago } from '~/lib/utils/datetime_utility';
import ArtifactsBlock from '~/jobs/components/artifacts_block.vue';
+import { getTimeago } from '~/lib/utils/datetime_utility';
describe('Artifacts block', () => {
let wrapper;
diff --git a/spec/frontend/jobs/components/erased_block_spec.js b/spec/frontend/jobs/components/erased_block_spec.js
index b3e1d28eb16..057df20ccc2 100644
--- a/spec/frontend/jobs/components/erased_block_spec.js
+++ b/spec/frontend/jobs/components/erased_block_spec.js
@@ -1,7 +1,7 @@
-import { mount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
-import { getTimeago } from '~/lib/utils/datetime_utility';
+import { mount } from '@vue/test-utils';
import ErasedBlock from '~/jobs/components/erased_block.vue';
+import { getTimeago } from '~/lib/utils/datetime_utility';
describe('Erased block', () => {
let wrapper;
@@ -10,6 +10,8 @@ describe('Erased block', () => {
const timeago = getTimeago();
const formattedDate = timeago.format(erasedAt);
+ const findLink = () => wrapper.find(GlLink);
+
const createComponent = (props) => {
wrapper = mount(ErasedBlock, {
propsData: props,
@@ -32,7 +34,7 @@ describe('Erased block', () => {
});
it('renders username and link', () => {
- expect(wrapper.find(GlLink).attributes('href')).toEqual('gitlab.com/root');
+ expect(findLink().attributes('href')).toEqual('gitlab.com/root');
expect(wrapper.text().trim()).toContain('Job has been erased by');
expect(wrapper.text().trim()).toContain('root');
diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js
index 657687b5e2a..2974e91e46d 100644
--- a/spec/frontend/jobs/components/job_app_spec.js
+++ b/spec/frontend/jobs/components/job_app_spec.js
@@ -1,18 +1,18 @@
-import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
+import EmptyState from '~/jobs/components/empty_state.vue';
+import EnvironmentsBlock from '~/jobs/components/environments_block.vue';
+import ErasedBlock from '~/jobs/components/erased_block.vue';
import JobApp from '~/jobs/components/job_app.vue';
import Sidebar from '~/jobs/components/sidebar.vue';
import StuckBlock from '~/jobs/components/stuck_block.vue';
import UnmetPrerequisitesBlock from '~/jobs/components/unmet_prerequisites_block.vue';
-import EnvironmentsBlock from '~/jobs/components/environments_block.vue';
-import ErasedBlock from '~/jobs/components/erased_block.vue';
-import EmptyState from '~/jobs/components/empty_state.vue';
import createStore from '~/jobs/store';
+import axios from '~/lib/utils/axios_utils';
import job from '../mock_data';
describe('Job App', () => {
@@ -34,7 +34,6 @@ describe('Job App', () => {
const props = {
artifactHelpUrl: 'help/artifact',
- runnerHelpUrl: 'help/runner',
deploymentHelpUrl: 'help/deployment',
runnerSettingsUrl: 'settings/ci-cd/runners',
variablesSettingsUrl: 'settings/ci-cd/variables',
diff --git a/spec/frontend/jobs/components/job_container_item_spec.js b/spec/frontend/jobs/components/job_container_item_spec.js
index af7ce100d83..36038b69e64 100644
--- a/spec/frontend/jobs/components/job_container_item_spec.js
+++ b/spec/frontend/jobs/components/job_container_item_spec.js
@@ -1,78 +1,80 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { GlIcon, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import JobContainerItem from '~/jobs/components/job_container_item.vue';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
import job from '../mock_data';
describe('JobContainerItem', () => {
+ let wrapper;
const delayedJobFixture = getJSONFixture('jobs/delayed.json');
- const Component = Vue.extend(JobContainerItem);
- let vm;
+
+ const findCiIconComponent = () => wrapper.findComponent(CiIcon);
+ const findGlIconComponent = () => wrapper.findComponent(GlIcon);
+
+ function createComponent(jobData = {}, props = { isActive: false, retried: false }) {
+ wrapper = shallowMount(JobContainerItem, {
+ propsData: {
+ job: {
+ ...jobData,
+ retried: props.retried,
+ },
+ isActive: props.isActive,
+ },
+ });
+ }
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- const sharedTests = () => {
+ describe('when a job is not active and not retried', () => {
+ beforeEach(() => {
+ createComponent(job);
+ });
+
it('displays a status icon', () => {
- expect(vm.$el).toHaveSpriteIcon(job.status.icon);
+ const ciIcon = findCiIconComponent();
+
+ expect(ciIcon.props('status')).toBe(job.status);
});
it('displays the job name', () => {
- expect(vm.$el.innerText).toContain(job.name);
+ expect(wrapper.text()).toContain(job.name);
});
it('displays a link to the job', () => {
- const link = vm.$el.querySelector('.js-job-link');
+ const link = wrapper.findComponent(GlLink);
- expect(link.href).toBe(job.status.details_path);
+ expect(link.attributes('href')).toBe(job.status.details_path);
});
- };
-
- describe('when a job is not active and not retied', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- job,
- isActive: false,
- });
- });
-
- sharedTests();
});
describe('when a job is active', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- job,
- isActive: true,
- });
+ createComponent(job, { isActive: true });
});
- sharedTests();
+ it('displays an arrow sprite icon', () => {
+ const icon = findGlIconComponent();
- it('displays an arrow', () => {
- expect(vm.$el).toHaveSpriteIcon('arrow-right');
+ expect(icon.props('name')).toBe('arrow-right');
});
});
describe('when a job is retried', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- job: {
- ...job,
- retried: true,
- },
- isActive: false,
- });
+ createComponent(job, { isActive: false, retried: true });
});
- sharedTests();
+ it('displays a retry icon', () => {
+ const icon = findGlIconComponent();
- it('displays an icon', () => {
- expect(vm.$el).toHaveSpriteIcon('retry');
+ expect(icon.props('name')).toBe('retry');
});
});
- describe('for delayed job', () => {
+ describe('for a delayed job', () => {
beforeEach(() => {
const remainingMilliseconds = 1337000;
jest
@@ -80,22 +82,16 @@ describe('JobContainerItem', () => {
.mockImplementation(
() => new Date(delayedJobFixture.scheduled_at).getTime() - remainingMilliseconds,
);
+
+ createComponent(delayedJobFixture);
});
- it('displays remaining time in tooltip', (done) => {
- vm = mountComponent(Component, {
- job: delayedJobFixture,
- isActive: false,
- });
-
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-job-link').getAttribute('title')).toEqual(
- 'delayed job - delayed manual action (00:22:17)',
- );
- })
- .then(done)
- .catch(done.fail);
+ it('displays remaining time in tooltip', async () => {
+ await wrapper.vm.$nextTick();
+
+ const link = wrapper.findComponent(GlLink);
+
+ expect(link.attributes('title')).toMatch('delayed job - delayed manual action (00:22:17)');
});
});
});
diff --git a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
index bc0d455c309..2b56bd2d558 100644
--- a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
+++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import SidebarJobDetailsContainer from '~/jobs/components/sidebar_job_details_container.vue';
import DetailRow from '~/jobs/components/sidebar_detail_row.vue';
+import SidebarJobDetailsContainer from '~/jobs/components/sidebar_job_details_container.vue';
import createStore from '~/jobs/store';
import job from '../mock_data';
@@ -116,14 +116,5 @@ describe('Job Sidebar Details Container', () => {
expect(findJobTimeout().exists()).toBe(false);
});
-
- it('should pass the help URL', async () => {
- const helpUrl = 'fakeUrl';
- const props = { runnerHelpUrl: helpUrl };
- createWrapper({ props });
- await store.dispatch('receiveJobSuccess', { metadata: { timeout_human_readable } });
-
- expect(findJobTimeout().props('helpUrl')).toBe(helpUrl);
- });
});
});
diff --git a/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js b/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
index 4bf697ab7cc..8fc5b071e54 100644
--- a/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
+++ b/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
@@ -1,8 +1,8 @@
import { GlButton, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import job from '../mock_data';
import JobsSidebarRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
import createStore from '~/jobs/store';
+import job from '../mock_data';
describe('Job Sidebar Retry Button', () => {
let store;
diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js
index bb90949b1f4..9763e2f437b 100644
--- a/spec/frontend/jobs/components/log/line_header_spec.js
+++ b/spec/frontend/jobs/components/log/line_header_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
+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';
-import DurationBadge from '~/jobs/components/log/duration_badge.vue';
describe('Job Log Header Line', () => {
let wrapper;
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
index f662ffa1780..b7aff1f3e3b 100644
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ b/spec/frontend/jobs/components/log/log_spec.js
@@ -1,7 +1,7 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { logLinesParser } from '~/jobs/store/utils';
import Log from '~/jobs/components/log/log.vue';
+import { logLinesParser } from '~/jobs/store/utils';
import { jobLog } from './mock_data';
describe('Job Log', () => {
diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js
index f6c37407e2b..7172a319876 100644
--- a/spec/frontend/jobs/components/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/manual_variables_form_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import Form from '~/jobs/components/manual_variables_form.vue';
const localVue = createLocalVue();
diff --git a/spec/frontend/jobs/components/sidebar_detail_row_spec.js b/spec/frontend/jobs/components/sidebar_detail_row_spec.js
index 42d11266dad..bae4d6cf837 100644
--- a/spec/frontend/jobs/components/sidebar_detail_row_spec.js
+++ b/spec/frontend/jobs/components/sidebar_detail_row_spec.js
@@ -1,61 +1,55 @@
-import Vue from 'vue';
-import sidebarDetailRow from '~/jobs/components/sidebar_detail_row.vue';
+import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import SidebarDetailRow from '~/jobs/components/sidebar_detail_row.vue';
describe('Sidebar detail row', () => {
- let SidebarDetailRow;
- let vm;
+ let wrapper;
- beforeEach(() => {
- SidebarDetailRow = Vue.extend(sidebarDetailRow);
- });
+ const title = 'this is the title';
+ const value = 'this is the value';
+ const helpUrl = '/help/ci/runners/README.html';
- afterEach(() => {
- vm.$destroy();
- });
+ const findHelpLink = () => wrapper.findComponent(GlLink);
- it('should render no title', () => {
- vm = new SidebarDetailRow({
+ const createComponent = (props) => {
+ wrapper = shallowMount(SidebarDetailRow, {
propsData: {
- value: 'this is the value',
+ ...props,
},
- }).$mount();
+ });
+ };
- expect(vm.$el.textContent.replace(/\s+/g, ' ').trim()).toEqual('this is the value');
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
});
- beforeEach(() => {
- vm = new SidebarDetailRow({
- propsData: {
- title: 'this is the title',
- value: 'this is the value',
- },
- }).$mount();
- });
+ describe('with title/value and without helpUrl', () => {
+ beforeEach(() => {
+ createComponent({ title, value });
+ });
- it('should render provided title and value', () => {
- expect(vm.$el.textContent.replace(/\s+/g, ' ').trim()).toEqual(
- 'this is the title: this is the value',
- );
- });
+ it('should render the provided title and value', () => {
+ expect(wrapper.text()).toBe(`${title}: ${value}`);
+ });
- describe('when helpUrl not provided', () => {
- it('should not render help', () => {
- expect(vm.$el.querySelector('.help-button')).toBeNull();
+ it('should not render the help link', () => {
+ expect(findHelpLink().exists()).toBe(false);
});
});
describe('when helpUrl provided', () => {
beforeEach(() => {
- vm = new SidebarDetailRow({
- propsData: {
- helpUrl: 'help url',
- value: 'foo',
- },
- }).$mount();
+ createComponent({
+ helpUrl,
+ title,
+ value,
+ });
});
- it('should render help', () => {
- expect(vm.$el.querySelector('.help-button a').getAttribute('href')).toEqual('help url');
+ it('should render the help link', () => {
+ expect(findHelpLink().exists()).toBe(true);
+ expect(findHelpLink().attributes('href')).toBe(helpUrl);
});
});
});
diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js
index 22d555ffec7..5a2e699137d 100644
--- a/spec/frontend/jobs/components/sidebar_spec.js
+++ b/spec/frontend/jobs/components/sidebar_spec.js
@@ -1,10 +1,10 @@
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import Sidebar, { forwardDeploymentFailureModalId } from '~/jobs/components/sidebar.vue';
-import StagesDropdown from '~/jobs/components/stages_dropdown.vue';
-import JobsContainer from '~/jobs/components/jobs_container.vue';
import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
import JobRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
+import JobsContainer from '~/jobs/components/jobs_container.vue';
+import Sidebar, { forwardDeploymentFailureModalId } from '~/jobs/components/sidebar.vue';
+import StagesDropdown from '~/jobs/components/stages_dropdown.vue';
import createStore from '~/jobs/store';
import job, { jobsInStage } from '../mock_data';
diff --git a/spec/frontend/jobs/components/trigger_block_spec.js b/spec/frontend/jobs/components/trigger_block_spec.js
index 16ea276ee4a..e0eb873dc2f 100644
--- a/spec/frontend/jobs/components/trigger_block_spec.js
+++ b/spec/frontend/jobs/components/trigger_block_spec.js
@@ -1,100 +1,86 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import component from '~/jobs/components/trigger_block.vue';
+import { GlButton, GlTable } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import TriggerBlock from '~/jobs/components/trigger_block.vue';
describe('Trigger block', () => {
- const Component = Vue.extend(component);
- let vm;
+ let wrapper;
+
+ const findRevealButton = () => wrapper.find(GlButton);
+ const findVariableTable = () => wrapper.find(GlTable);
+ const findShortToken = () => wrapper.find('[data-testid="trigger-short-token"]');
+ const findVariableValue = (index) =>
+ wrapper.findAll('[data-testid="trigger-build-value"]').at(index);
+ const findVariableKey = (index) => wrapper.findAll('[data-testid="trigger-build-key"]').at(index);
+
+ const createComponent = (props) => {
+ wrapper = mount(TriggerBlock, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- describe('with short token', () => {
+ describe('with short token and no variables', () => {
it('renders short token', () => {
- vm = mountComponent(Component, {
+ createComponent({
trigger: {
short_token: '0a666b2',
+ variables: [],
},
});
- expect(vm.$el.querySelector('.js-short-token').textContent).toContain('0a666b2');
+ expect(findShortToken().text()).toContain('0a666b2');
});
});
- describe('without short token', () => {
+ describe('without variables or short token', () => {
+ beforeEach(() => {
+ createComponent({ trigger: { variables: [] } });
+ });
+
it('does not render short token', () => {
- vm = mountComponent(Component, { trigger: {} });
+ expect(findShortToken().exists()).toBe(false);
+ });
- expect(vm.$el.querySelector('.js-short-token')).toBeNull();
+ it('does not render variables', () => {
+ expect(findRevealButton().exists()).toBe(false);
+ expect(findVariableTable().exists()).toBe(false);
});
});
describe('with variables', () => {
describe('hide/reveal variables', () => {
- it('should toggle variables on click', (done) => {
- vm = mountComponent(Component, {
+ it('should toggle variables on click', async () => {
+ const hiddenValue = '••••••';
+ const gcsVar = { key: 'UPLOAD_TO_GCS', value: 'false', public: false };
+ const s3Var = { key: 'UPLOAD_TO_S3', value: 'true', public: false };
+
+ createComponent({
trigger: {
- short_token: 'bd7e',
- variables: [
- { key: 'UPLOAD_TO_GCS', value: 'false', public: false },
- { key: 'UPLOAD_TO_S3', value: 'true', public: false },
- ],
+ variables: [gcsVar, s3Var],
},
});
- vm.$el.querySelector('.js-reveal-variables').click();
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-build-variables')).not.toBeNull();
- expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
- 'Hide values',
- );
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_GCS',
- );
+ expect(findRevealButton().text()).toBe('Reveal values');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('false');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_S3',
- );
+ expect(findVariableValue(0).text()).toBe(hiddenValue);
+ expect(findVariableValue(1).text()).toBe(hiddenValue);
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('true');
+ expect(findVariableKey(0).text()).toBe(gcsVar.key);
+ expect(findVariableKey(1).text()).toBe(s3Var.key);
- vm.$el.querySelector('.js-reveal-variables').click();
- })
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
- 'Reveal values',
- );
+ await findRevealButton().trigger('click');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_GCS',
- );
+ expect(findRevealButton().text()).toBe('Hide values');
- expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
-
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
- 'UPLOAD_TO_S3',
- );
-
- expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
- })
- .then(done)
- .catch(done.fail);
+ expect(findVariableValue(0).text()).toBe(gcsVar.value);
+ expect(findVariableValue(1).text()).toBe(s3Var.value);
});
});
});
-
- describe('without variables', () => {
- it('does not render variables', () => {
- vm = mountComponent(Component, { trigger: {} });
-
- expect(vm.$el.querySelector('.js-reveal-variables')).toBeNull();
- expect(vm.$el.querySelector('.js-build-variables')).toBeNull();
- });
- });
});
diff --git a/spec/frontend/jobs/components/unmet_prerequisites_block_spec.js b/spec/frontend/jobs/components/unmet_prerequisites_block_spec.js
index 9092d3f8163..aeb85694e60 100644
--- a/spec/frontend/jobs/components/unmet_prerequisites_block_spec.js
+++ b/spec/frontend/jobs/components/unmet_prerequisites_block_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UnmetPrerequisitesBlock from '~/jobs/components/unmet_prerequisites_block.vue';
describe('Unmet Prerequisites Block Job component', () => {
diff --git a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
index 2175610b7a6..838323df755 100644
--- a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
+++ b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
@@ -1,46 +1,42 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { shallowMount } from '@vue/test-utils';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
describe('DelayedJobMixin', () => {
+ let wrapper;
const delayedJobFixture = getJSONFixture('jobs/delayed.json');
- const dummyComponent = Vue.extend({
- mixins: [delayedJobMixin],
+ const dummyComponent = {
props: {
job: {
type: Object,
required: true,
},
},
- render(createElement) {
- return createElement('div', this.remainingTime);
- },
- });
-
- let vm;
+ mixins: [delayedJobMixin],
+ template: '<div>{{remainingTime}}</div>',
+ };
afterEach(() => {
- vm.$destroy();
- jest.clearAllTimers();
+ wrapper.destroy();
+ wrapper = null;
});
describe('if job is empty object', () => {
beforeEach(() => {
- vm = mountComponent(dummyComponent, {
- job: {},
+ wrapper = shallowMount(dummyComponent, {
+ propsData: {
+ job: {},
+ },
});
});
it('sets remaining time to 00:00:00', () => {
- expect(vm.$el.innerText).toBe('00:00:00');
+ expect(wrapper.text()).toBe('00:00:00');
});
- describe('after mounting', () => {
- beforeEach(() => vm.$nextTick());
+ it('does not update remaining time after mounting', async () => {
+ await wrapper.vm.$nextTick();
- it('does not update remaining time', () => {
- expect(vm.$el.innerText).toBe('00:00:00');
- });
+ expect(wrapper.text()).toBe('00:00:00');
});
});
@@ -48,33 +44,32 @@ describe('DelayedJobMixin', () => {
describe('if job is delayed job', () => {
let remainingTimeInMilliseconds = 42000;
- beforeEach(() => {
+ beforeEach(async () => {
jest
.spyOn(Date, 'now')
.mockImplementation(
() => new Date(delayedJobFixture.scheduled_at).getTime() - remainingTimeInMilliseconds,
);
- vm = mountComponent(dummyComponent, {
- job: delayedJobFixture,
+ wrapper = shallowMount(dummyComponent, {
+ propsData: {
+ job: delayedJobFixture,
+ },
});
- });
- describe('after mounting', () => {
- beforeEach(() => vm.$nextTick());
+ await wrapper.vm.$nextTick();
+ });
- it('sets remaining time', () => {
- expect(vm.$el.innerText).toBe('00:00:42');
- });
+ it('sets remaining time', () => {
+ expect(wrapper.text()).toBe('00:00:42');
+ });
- it('updates remaining time', () => {
- remainingTimeInMilliseconds = 41000;
- jest.advanceTimersByTime(1000);
+ it('updates remaining time', async () => {
+ remainingTimeInMilliseconds = 41000;
+ jest.advanceTimersByTime(1000);
- return vm.$nextTick().then(() => {
- expect(vm.$el.innerText).toBe('00:00:41');
- });
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.text()).toBe('00:00:41');
});
});
});
@@ -96,33 +91,32 @@ describe('DelayedJobMixin', () => {
describe('if job is delayed job', () => {
let remainingTimeInMilliseconds = 42000;
- beforeEach(() => {
+ beforeEach(async () => {
jest
.spyOn(Date, 'now')
.mockImplementation(
() => mockGraphQlJob.scheduledAt.getTime() - remainingTimeInMilliseconds,
);
- vm = mountComponent(dummyComponent, {
- job: mockGraphQlJob,
+ wrapper = shallowMount(dummyComponent, {
+ propsData: {
+ job: mockGraphQlJob,
+ },
});
- });
- describe('after mounting', () => {
- beforeEach(() => vm.$nextTick());
+ await wrapper.vm.$nextTick();
+ });
- it('sets remaining time', () => {
- expect(vm.$el.innerText).toBe('00:00:42');
- });
+ it('sets remaining time', () => {
+ expect(wrapper.text()).toBe('00:00:42');
+ });
- it('updates remaining time', () => {
- remainingTimeInMilliseconds = 41000;
- jest.advanceTimersByTime(1000);
+ it('updates remaining time', async () => {
+ remainingTimeInMilliseconds = 41000;
+ jest.advanceTimersByTime(1000);
- return vm.$nextTick().then(() => {
- expect(vm.$el.innerText).toBe('00:00:41');
- });
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.text()).toBe('00:00:41');
});
});
});
diff --git a/spec/frontend/jobs/store/actions_spec.js b/spec/frontend/jobs/store/actions_spec.js
index 2d757ce76bf..a29bd15099f 100644
--- a/spec/frontend/jobs/store/actions_spec.js
+++ b/spec/frontend/jobs/store/actions_spec.js
@@ -1,7 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
-import axios from '~/lib/utils/axios_utils';
+import testAction from 'helpers/vuex_action_helper';
import {
setJobEndpoint,
setTraceOptions,
@@ -28,8 +27,9 @@ import {
showSidebar,
toggleSidebar,
} from '~/jobs/store/actions';
-import state from '~/jobs/store/state';
import * as types from '~/jobs/store/mutation_types';
+import state from '~/jobs/store/state';
+import axios from '~/lib/utils/axios_utils';
describe('Job State actions', () => {
let mockedState;
diff --git a/spec/frontend/jobs/store/mutations_spec.js b/spec/frontend/jobs/store/mutations_spec.js
index 608abc8f7c4..1c7e45dfb3d 100644
--- a/spec/frontend/jobs/store/mutations_spec.js
+++ b/spec/frontend/jobs/store/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/jobs/store/state';
-import mutations from '~/jobs/store/mutations';
import * as types from '~/jobs/store/mutation_types';
+import mutations from '~/jobs/store/mutations';
+import state from '~/jobs/store/state';
describe('Jobs Store Mutations', () => {
let stateCopy;
diff --git a/spec/frontend/lazy_loader_spec.js b/spec/frontend/lazy_loader_spec.js
index f8ac7568724..3d8b0d9c307 100644
--- a/spec/frontend/lazy_loader_spec.js
+++ b/spec/frontend/lazy_loader_spec.js
@@ -1,6 +1,6 @@
import { noop } from 'lodash';
-import { TEST_HOST } from 'helpers/test_constants';
import { useMockMutationObserver, useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import LazyLoader from '~/lazy_loader';
diff --git a/spec/frontend/lib/utils/ajax_cache_spec.js b/spec/frontend/lib/utils/ajax_cache_spec.js
index 641dd3684fa..d4b95172d18 100644
--- a/spec/frontend/lib/utils/ajax_cache_spec.js
+++ b/spec/frontend/lib/utils/ajax_cache_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import AjaxCache from '~/lib/utils/ajax_cache';
+import axios from '~/lib/utils/axios_utils';
describe('AjaxCache', () => {
const dummyEndpoint = '/AjaxCache/dummyEndpoint';
diff --git a/spec/frontend/lib/utils/array_utility_spec.js b/spec/frontend/lib/utils/array_utility_spec.js
new file mode 100644
index 00000000000..b95286ff254
--- /dev/null
+++ b/spec/frontend/lib/utils/array_utility_spec.js
@@ -0,0 +1,32 @@
+import * as arrayUtils from '~/lib/utils/array_utility';
+
+describe('array_utility', () => {
+ describe('swapArrayItems', () => {
+ it.each`
+ array | leftIndex | rightIndex | result
+ ${[]} | ${0} | ${0} | ${[]}
+ ${[1]} | ${0} | ${1} | ${[1]}
+ ${[1, 2]} | ${0} | ${0} | ${[1, 2]}
+ ${[1, 2]} | ${0} | ${1} | ${[2, 1]}
+ ${[1, 2]} | ${1} | ${2} | ${[1, 2]}
+ ${[1, 2]} | ${2} | ${1} | ${[1, 2]}
+ ${[1, 2]} | ${1} | ${10} | ${[1, 2]}
+ ${[1, 2]} | ${10} | ${1} | ${[1, 2]}
+ ${[1, 2]} | ${1} | ${-1} | ${[1, 2]}
+ ${[1, 2]} | ${-1} | ${1} | ${[1, 2]}
+ ${[1, 2, 3]} | ${1} | ${1} | ${[1, 2, 3]}
+ ${[1, 2, 3]} | ${0} | ${2} | ${[3, 2, 1]}
+ ${[1, 2, 3, 4]} | ${0} | ${2} | ${[3, 2, 1, 4]}
+ ${[1, 2, 3, 4, 5]} | ${0} | ${4} | ${[5, 2, 3, 4, 1]}
+ ${[1, 2, 3, 4, 5]} | ${1} | ${2} | ${[1, 3, 2, 4, 5]}
+ ${[1, 2, 3, 4, 5]} | ${2} | ${1} | ${[1, 3, 2, 4, 5]}
+ `(
+ 'given $array with index $leftIndex and $rightIndex will return $result',
+ ({ array, leftIndex, rightIndex, result }) => {
+ const actual = arrayUtils.swapArrayItems(array, leftIndex, rightIndex);
+ expect(actual).toEqual(result);
+ expect(actual).not.toBe(array);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/lib/utils/color_utils_spec.js b/spec/frontend/lib/utils/color_utils_spec.js
index 433e9d5a85e..8c846abd77f 100644
--- a/spec/frontend/lib/utils/color_utils_spec.js
+++ b/spec/frontend/lib/utils/color_utils_spec.js
@@ -1,4 +1,4 @@
-import { textColorForBackground, hexToRgb } from '~/lib/utils/color_utils';
+import { textColorForBackground, hexToRgb, validateHexColor } from '~/lib/utils/color_utils';
describe('Color utils', () => {
describe('Converting hex code to rgb', () => {
@@ -32,4 +32,19 @@ describe('Color utils', () => {
expect(textColorForBackground('#000')).toEqual('#FFFFFF');
});
});
+
+ describe('Validate hex color', () => {
+ it.each`
+ color | output
+ ${undefined} | ${null}
+ ${null} | ${null}
+ ${''} | ${null}
+ ${'ABC123'} | ${false}
+ ${'#ZZZ'} | ${false}
+ ${'#FF0'} | ${true}
+ ${'#FF0000'} | ${true}
+ `('returns $output when $color is given', ({ color, output }) => {
+ expect(validateHexColor(color)).toEqual(output);
+ });
+ });
});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index 90222f0f718..18be88a0b8b 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -1045,4 +1045,12 @@ describe('common_utils', () => {
expect(commonUtils.getDashPath('/some/url')).toEqual(null);
});
});
+
+ describe('convertArrayToCamelCase', () => {
+ it('returns a new array with snake_case string elements converted camelCase', () => {
+ const result = commonUtils.convertArrayToCamelCase(['hello', 'hello_world']);
+
+ expect(result).toEqual(['hello', 'helloWorld']);
+ });
+ });
});
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index 66efd43262b..32a24227cbd 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -1,8 +1,8 @@
import $ from 'jquery';
import timezoneMock from 'timezone-mock';
+import * as datetimeUtility from '~/lib/utils/datetime_utility';
import { __, s__ } from '~/locale';
import '~/commons/bootstrap';
-import * as datetimeUtility from '~/lib/utils/datetime_utility';
describe('Date time utils', () => {
describe('timeFor', () => {
@@ -584,22 +584,6 @@ describe('secondsToMilliseconds', () => {
});
});
-describe('dayAfter', () => {
- const date = new Date('2019-07-16T00:00:00.000Z');
-
- it('returns the following date', () => {
- const nextDay = datetimeUtility.dayAfter(date);
- const expectedNextDate = new Date('2019-07-17T00:00:00.000Z');
-
- expect(nextDay).toStrictEqual(expectedNextDate);
- });
-
- it('does not modifiy the original date', () => {
- datetimeUtility.dayAfter(date);
- expect(date).toStrictEqual(new Date('2019-07-16T00:00:00.000Z'));
- });
-});
-
describe('secondsToDays', () => {
it('converts seconds to days correctly', () => {
expect(datetimeUtility.secondsToDays(0)).toBe(0);
@@ -608,90 +592,214 @@ describe('secondsToDays', () => {
});
});
-describe('nDaysAfter', () => {
- const date = new Date('2019-07-16T00:00:00.000Z');
+describe('date addition/subtraction methods', () => {
+ beforeEach(() => {
+ timezoneMock.register('US/Eastern');
+ });
- it.each`
- numberOfDays | expectedResult
- ${1} | ${new Date('2019-07-17T00:00:00.000Z').valueOf()}
- ${90} | ${new Date('2019-10-14T00:00:00.000Z').valueOf()}
- ${-1} | ${new Date('2019-07-15T00:00:00.000Z').valueOf()}
- ${0} | ${date.valueOf()}
- ${0.9} | ${date.valueOf()}
- `('returns $numberOfDays day(s) after the provided date', ({ numberOfDays, expectedResult }) => {
- expect(datetimeUtility.nDaysAfter(date, numberOfDays)).toBe(expectedResult);
+ afterEach(() => {
+ timezoneMock.unregister();
});
-});
-describe('nDaysBefore', () => {
- const date = new Date('2019-07-16T00:00:00.000Z');
+ describe('dayAfter', () => {
+ const input = '2019-03-10T00:00:00.000Z';
+ const expectedLocalResult = '2019-03-10T23:00:00.000Z';
+ const expectedUTCResult = '2019-03-11T00:00:00.000Z';
+
+ it.each`
+ inputAsString | options | expectedAsString
+ ${input} | ${undefined} | ${expectedLocalResult}
+ ${input} | ${{}} | ${expectedLocalResult}
+ ${input} | ${{ utc: false }} | ${expectedLocalResult}
+ ${input} | ${{ utc: true }} | ${expectedUTCResult}
+ `(
+ 'when the provided date is $inputAsString and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.dayAfter(inputDate, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
+
+ it('does not modifiy the original date', () => {
+ const inputDate = new Date(input);
+ datetimeUtility.dayAfter(inputDate);
+ expect(inputDate.toISOString()).toBe(input);
+ });
+ });
- it.each`
- numberOfDays | expectedResult
- ${1} | ${new Date('2019-07-15T00:00:00.000Z').valueOf()}
- ${90} | ${new Date('2019-04-17T00:00:00.000Z').valueOf()}
- ${-1} | ${new Date('2019-07-17T00:00:00.000Z').valueOf()}
- ${0} | ${date.valueOf()}
- ${0.9} | ${new Date('2019-07-15T00:00:00.000Z').valueOf()}
- `('returns $numberOfDays day(s) before the provided date', ({ numberOfDays, expectedResult }) => {
- expect(datetimeUtility.nDaysBefore(date, numberOfDays)).toBe(expectedResult);
+ describe('nDaysAfter', () => {
+ const input = '2019-07-16T00:00:00.000Z';
+
+ it.each`
+ inputAsString | numberOfDays | options | expectedAsString
+ ${input} | ${1} | ${undefined} | ${'2019-07-17T00:00:00.000Z'}
+ ${input} | ${-1} | ${undefined} | ${'2019-07-15T00:00:00.000Z'}
+ ${input} | ${0} | ${undefined} | ${'2019-07-16T00:00:00.000Z'}
+ ${input} | ${0.9} | ${undefined} | ${'2019-07-16T00:00:00.000Z'}
+ ${input} | ${120} | ${undefined} | ${'2019-11-13T01:00:00.000Z'}
+ ${input} | ${120} | ${{}} | ${'2019-11-13T01:00:00.000Z'}
+ ${input} | ${120} | ${{ utc: false }} | ${'2019-11-13T01:00:00.000Z'}
+ ${input} | ${120} | ${{ utc: true }} | ${'2019-11-13T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString, numberOfDays is $numberOfDays, and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, numberOfDays, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.nDaysAfter(inputDate, numberOfDays, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
});
-});
-describe('nMonthsAfter', () => {
- // February has 28 days
- const feb2019 = new Date('2019-02-15T00:00:00.000Z');
- // Except in 2020, it had 29 days
- const feb2020 = new Date('2020-02-15T00:00:00.000Z');
- // April has 30 days
- const apr2020 = new Date('2020-04-15T00:00:00.000Z');
- // May has 31 days
- const may2020 = new Date('2020-05-15T00:00:00.000Z');
+ describe('nDaysBefore', () => {
+ const input = '2019-07-16T00:00:00.000Z';
+
+ it.each`
+ inputAsString | numberOfDays | options | expectedAsString
+ ${input} | ${1} | ${undefined} | ${'2019-07-15T00:00:00.000Z'}
+ ${input} | ${-1} | ${undefined} | ${'2019-07-17T00:00:00.000Z'}
+ ${input} | ${0} | ${undefined} | ${'2019-07-16T00:00:00.000Z'}
+ ${input} | ${0.9} | ${undefined} | ${'2019-07-15T00:00:00.000Z'}
+ ${input} | ${180} | ${undefined} | ${'2019-01-17T01:00:00.000Z'}
+ ${input} | ${180} | ${{}} | ${'2019-01-17T01:00:00.000Z'}
+ ${input} | ${180} | ${{ utc: false }} | ${'2019-01-17T01:00:00.000Z'}
+ ${input} | ${180} | ${{ utc: true }} | ${'2019-01-17T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString, numberOfDays is $numberOfDays, and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, numberOfDays, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.nDaysBefore(inputDate, numberOfDays, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
+ });
- it.each`
- date | numberOfMonths | expectedResult
- ${feb2019} | ${1} | ${new Date('2019-03-15T00:00:00.000Z').valueOf()}
- ${feb2020} | ${1} | ${new Date('2020-03-15T00:00:00.000Z').valueOf()}
- ${apr2020} | ${1} | ${new Date('2020-05-15T00:00:00.000Z').valueOf()}
- ${may2020} | ${1} | ${new Date('2020-06-15T00:00:00.000Z').valueOf()}
- ${may2020} | ${12} | ${new Date('2021-05-15T00:00:00.000Z').valueOf()}
- ${may2020} | ${-1} | ${new Date('2020-04-15T00:00:00.000Z').valueOf()}
- ${may2020} | ${0} | ${may2020.valueOf()}
- ${may2020} | ${0.9} | ${may2020.valueOf()}
- `(
- 'returns $numberOfMonths month(s) after the provided date',
- ({ date, numberOfMonths, expectedResult }) => {
- expect(datetimeUtility.nMonthsAfter(date, numberOfMonths)).toBe(expectedResult);
- },
- );
-});
+ describe('nWeeksAfter', () => {
+ const input = '2021-07-16T00:00:00.000Z';
+
+ it.each`
+ inputAsString | numberOfWeeks | options | expectedAsString
+ ${input} | ${1} | ${undefined} | ${'2021-07-23T00:00:00.000Z'}
+ ${input} | ${3} | ${undefined} | ${'2021-08-06T00:00:00.000Z'}
+ ${input} | ${-1} | ${undefined} | ${'2021-07-09T00:00:00.000Z'}
+ ${input} | ${0} | ${undefined} | ${'2021-07-16T00:00:00.000Z'}
+ ${input} | ${0.6} | ${undefined} | ${'2021-07-20T00:00:00.000Z'}
+ ${input} | ${18} | ${undefined} | ${'2021-11-19T01:00:00.000Z'}
+ ${input} | ${18} | ${{}} | ${'2021-11-19T01:00:00.000Z'}
+ ${input} | ${18} | ${{ utc: false }} | ${'2021-11-19T01:00:00.000Z'}
+ ${input} | ${18} | ${{ utc: true }} | ${'2021-11-19T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString, numberOfWeeks is $numberOfWeeks, and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, numberOfWeeks, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.nWeeksAfter(inputDate, numberOfWeeks, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
+ });
-describe('nMonthsBefore', () => {
- // The previous month (February) has 28 days
- const march2019 = new Date('2019-03-15T00:00:00.000Z');
- // Except in 2020, it had 29 days
- const march2020 = new Date('2020-03-15T00:00:00.000Z');
- // The previous month (April) has 30 days
- const may2020 = new Date('2020-05-15T00:00:00.000Z');
- // The previous month (May) has 31 days
- const june2020 = new Date('2020-06-15T00:00:00.000Z');
+ describe('nWeeksBefore', () => {
+ const input = '2021-07-16T00:00:00.000Z';
+
+ it.each`
+ inputAsString | numberOfWeeks | options | expectedAsString
+ ${input} | ${1} | ${undefined} | ${'2021-07-09T00:00:00.000Z'}
+ ${input} | ${3} | ${undefined} | ${'2021-06-25T00:00:00.000Z'}
+ ${input} | ${-1} | ${undefined} | ${'2021-07-23T00:00:00.000Z'}
+ ${input} | ${0} | ${undefined} | ${'2021-07-16T00:00:00.000Z'}
+ ${input} | ${0.6} | ${undefined} | ${'2021-07-11T00:00:00.000Z'}
+ ${input} | ${20} | ${undefined} | ${'2021-02-26T01:00:00.000Z'}
+ ${input} | ${20} | ${{}} | ${'2021-02-26T01:00:00.000Z'}
+ ${input} | ${20} | ${{ utc: false }} | ${'2021-02-26T01:00:00.000Z'}
+ ${input} | ${20} | ${{ utc: true }} | ${'2021-02-26T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString, numberOfWeeks is $numberOfWeeks, and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, numberOfWeeks, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.nWeeksBefore(inputDate, numberOfWeeks, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
+ });
- it.each`
- date | numberOfMonths | expectedResult
- ${march2019} | ${1} | ${new Date('2019-02-15T00:00:00.000Z').valueOf()}
- ${march2020} | ${1} | ${new Date('2020-02-15T00:00:00.000Z').valueOf()}
- ${may2020} | ${1} | ${new Date('2020-04-15T00:00:00.000Z').valueOf()}
- ${june2020} | ${1} | ${new Date('2020-05-15T00:00:00.000Z').valueOf()}
- ${june2020} | ${12} | ${new Date('2019-06-15T00:00:00.000Z').valueOf()}
- ${june2020} | ${-1} | ${new Date('2020-07-15T00:00:00.000Z').valueOf()}
- ${june2020} | ${0} | ${june2020.valueOf()}
- ${june2020} | ${0.9} | ${new Date('2020-05-15T00:00:00.000Z').valueOf()}
- `(
- 'returns $numberOfMonths month(s) before the provided date',
- ({ date, numberOfMonths, expectedResult }) => {
- expect(datetimeUtility.nMonthsBefore(date, numberOfMonths)).toBe(expectedResult);
- },
- );
+ describe('nMonthsAfter', () => {
+ // February has 28 days
+ const feb2019 = '2019-02-15T00:00:00.000Z';
+ // Except in 2020, it had 29 days
+ const feb2020 = '2020-02-15T00:00:00.000Z';
+ // April has 30 days
+ const apr2020 = '2020-04-15T00:00:00.000Z';
+ // May has 31 days
+ const may2020 = '2020-05-15T00:00:00.000Z';
+ // November 1, 2020 was the day Daylight Saving Time ended in 2020 (in the US)
+ const oct2020 = '2020-10-15T00:00:00.000Z';
+
+ it.each`
+ inputAsString | numberOfMonths | options | expectedAsString
+ ${feb2019} | ${1} | ${undefined} | ${'2019-03-14T23:00:00.000Z'}
+ ${feb2020} | ${1} | ${undefined} | ${'2020-03-14T23:00:00.000Z'}
+ ${apr2020} | ${1} | ${undefined} | ${'2020-05-15T00:00:00.000Z'}
+ ${may2020} | ${1} | ${undefined} | ${'2020-06-15T00:00:00.000Z'}
+ ${may2020} | ${12} | ${undefined} | ${'2021-05-15T00:00:00.000Z'}
+ ${may2020} | ${-1} | ${undefined} | ${'2020-04-15T00:00:00.000Z'}
+ ${may2020} | ${0} | ${undefined} | ${may2020}
+ ${may2020} | ${0.9} | ${undefined} | ${may2020}
+ ${oct2020} | ${1} | ${undefined} | ${'2020-11-15T01:00:00.000Z'}
+ ${oct2020} | ${1} | ${{}} | ${'2020-11-15T01:00:00.000Z'}
+ ${oct2020} | ${1} | ${{ utc: false }} | ${'2020-11-15T01:00:00.000Z'}
+ ${oct2020} | ${1} | ${{ utc: true }} | ${'2020-11-15T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString, numberOfMonths is $numberOfMonths, and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, numberOfMonths, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.nMonthsAfter(inputDate, numberOfMonths, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
+ });
+
+ describe('nMonthsBefore', () => {
+ // The previous month (February) has 28 days
+ const march2019 = '2019-03-15T00:00:00.000Z';
+ // Except in 2020, it had 29 days
+ const march2020 = '2020-03-15T00:00:00.000Z';
+ // The previous month (April) has 30 days
+ const may2020 = '2020-05-15T00:00:00.000Z';
+ // The previous month (May) has 31 days
+ const june2020 = '2020-06-15T00:00:00.000Z';
+ // November 1, 2020 was the day Daylight Saving Time ended in 2020 (in the US)
+ const nov2020 = '2020-11-15T00:00:00.000Z';
+
+ it.each`
+ inputAsString | numberOfMonths | options | expectedAsString
+ ${march2019} | ${1} | ${undefined} | ${'2019-02-15T01:00:00.000Z'}
+ ${march2020} | ${1} | ${undefined} | ${'2020-02-15T01:00:00.000Z'}
+ ${may2020} | ${1} | ${undefined} | ${'2020-04-15T00:00:00.000Z'}
+ ${june2020} | ${1} | ${undefined} | ${'2020-05-15T00:00:00.000Z'}
+ ${june2020} | ${12} | ${undefined} | ${'2019-06-15T00:00:00.000Z'}
+ ${june2020} | ${-1} | ${undefined} | ${'2020-07-15T00:00:00.000Z'}
+ ${june2020} | ${0} | ${undefined} | ${june2020}
+ ${june2020} | ${0.9} | ${undefined} | ${'2020-05-15T00:00:00.000Z'}
+ ${nov2020} | ${1} | ${undefined} | ${'2020-10-14T23:00:00.000Z'}
+ ${nov2020} | ${1} | ${{}} | ${'2020-10-14T23:00:00.000Z'}
+ ${nov2020} | ${1} | ${{ utc: false }} | ${'2020-10-14T23:00:00.000Z'}
+ ${nov2020} | ${1} | ${{ utc: true }} | ${'2020-10-15T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString, numberOfMonths is $numberOfMonths, and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, numberOfMonths, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.nMonthsBefore(inputDate, numberOfMonths, options);
+
+ expect(actual.toISOString()).toBe(expectedAsString);
+ },
+ );
+ });
});
describe('approximateDuration', () => {
@@ -843,7 +951,7 @@ describe('format24HourTimeStringFromInt', () => {
});
});
-describe('getOverlappingDaysInPeriods', () => {
+describe('getOverlapDateInPeriods', () => {
const start = new Date(2021, 0, 11);
const end = new Date(2021, 0, 13);
@@ -851,14 +959,15 @@ describe('getOverlappingDaysInPeriods', () => {
const givenPeriodLeft = new Date(2021, 0, 11);
const givenPeriodRight = new Date(2021, 0, 14);
- it('returns an overlap object that contains the amount of days overlapping, start date of overlap and end date of overlap', () => {
+ it('returns an overlap object that contains the amount of days overlapping, the amount of hours overlapping, start date of overlap and end date of overlap', () => {
expect(
- datetimeUtility.getOverlappingDaysInPeriods(
+ datetimeUtility.getOverlapDateInPeriods(
{ start, end },
{ start: givenPeriodLeft, end: givenPeriodRight },
),
).toEqual({
daysOverlap: 2,
+ hoursOverlap: 48,
overlapStartDate: givenPeriodLeft.getTime(),
overlapEndDate: end.getTime(),
});
@@ -871,7 +980,7 @@ describe('getOverlappingDaysInPeriods', () => {
it('returns an overlap object that contains a 0 value for days overlapping', () => {
expect(
- datetimeUtility.getOverlappingDaysInPeriods(
+ datetimeUtility.getOverlapDateInPeriods(
{ start, end },
{ start: givenPeriodLeft, end: givenPeriodRight },
),
@@ -886,14 +995,54 @@ describe('getOverlappingDaysInPeriods', () => {
it('throws an exception when the left period contains an invalid date', () => {
expect(() =>
- datetimeUtility.getOverlappingDaysInPeriods({ start, end }, { start: startInvalid, end }),
+ datetimeUtility.getOverlapDateInPeriods({ start, end }, { start: startInvalid, end }),
).toThrow(error);
});
it('throws an exception when the right period contains an invalid date', () => {
expect(() =>
- datetimeUtility.getOverlappingDaysInPeriods({ start, end }, { start, end: endInvalid }),
+ datetimeUtility.getOverlapDateInPeriods({ start, end }, { start, end: endInvalid }),
).toThrow(error);
});
});
});
+
+describe('isToday', () => {
+ const today = new Date();
+ it.each`
+ date | expected | negation
+ ${today} | ${true} | ${'is'}
+ ${new Date('2021-01-21T12:00:00.000Z')} | ${false} | ${'is NOT'}
+ `('returns $expected as $date $negation today', ({ date, expected }) => {
+ expect(datetimeUtility.isToday(date)).toBe(expected);
+ });
+});
+
+describe('getStartOfDay', () => {
+ beforeEach(() => {
+ timezoneMock.register('US/Eastern');
+ });
+
+ afterEach(() => {
+ timezoneMock.unregister();
+ });
+
+ it.each`
+ inputAsString | options | expectedAsString
+ ${'2021-01-29T18:08:23.014Z'} | ${undefined} | ${'2021-01-29T05:00:00.000Z'}
+ ${'2021-01-29T13:08:23.014-05:00'} | ${undefined} | ${'2021-01-29T05:00:00.000Z'}
+ ${'2021-01-30T03:08:23.014+09:00'} | ${undefined} | ${'2021-01-29T05:00:00.000Z'}
+ ${'2021-01-28T18:08:23.014-10:00'} | ${undefined} | ${'2021-01-28T05:00:00.000Z'}
+ ${'2021-01-28T18:08:23.014-10:00'} | ${{}} | ${'2021-01-28T05:00:00.000Z'}
+ ${'2021-01-28T18:08:23.014-10:00'} | ${{ utc: false }} | ${'2021-01-28T05:00:00.000Z'}
+ ${'2021-01-28T18:08:23.014-10:00'} | ${{ utc: true }} | ${'2021-01-29T00:00:00.000Z'}
+ `(
+ 'when the provided date is $inputAsString and the options parameter is $options, returns $expectedAsString',
+ ({ inputAsString, options, expectedAsString }) => {
+ const inputDate = new Date(inputAsString);
+ const actual = datetimeUtility.getStartOfDay(inputDate, options);
+
+ expect(actual.toISOString()).toEqual(expectedAsString);
+ },
+ );
+});
diff --git a/spec/frontend/lib/utils/poll_spec.js b/spec/frontend/lib/utils/poll_spec.js
index f2ca5df3672..861808e3ad8 100644
--- a/spec/frontend/lib/utils/poll_spec.js
+++ b/spec/frontend/lib/utils/poll_spec.js
@@ -1,6 +1,6 @@
import waitForPromises from 'helpers/wait_for_promises';
-import Poll from '~/lib/utils/poll';
import { successCodes } from '~/lib/utils/http_status';
+import Poll from '~/lib/utils/poll';
describe('Poll', () => {
let callbacks;
diff --git a/spec/frontend/lib/utils/poll_until_complete_spec.js b/spec/frontend/lib/utils/poll_until_complete_spec.js
index 38203c460e3..7509f954a84 100644
--- a/spec/frontend/lib/utils/poll_until_complete_spec.js
+++ b/spec/frontend/lib/utils/poll_until_complete_spec.js
@@ -1,8 +1,8 @@
import AxiosMockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
-import pollUntilComplete from '~/lib/utils/poll_until_complete';
import httpStatusCodes from '~/lib/utils/http_status';
+import pollUntilComplete from '~/lib/utils/poll_until_complete';
const endpoint = `${TEST_HOST}/foo`;
const mockData = 'mockData';
diff --git a/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js b/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js
index 26b942c3567..0ca70e0a77e 100644
--- a/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js
+++ b/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js
@@ -36,6 +36,27 @@ describe('unit_format/formatter_factory', () => {
expect(formatNumber(10 ** 7, undefined, 9)).toBe('1.00e+7');
expect(formatNumber(10 ** 7, undefined, 10)).toBe('10,000,000');
});
+
+ describe('formats with a different locale', () => {
+ let originalLang;
+
+ beforeAll(() => {
+ originalLang = document.documentElement.lang;
+ document.documentElement.lang = 'es';
+ });
+
+ afterAll(() => {
+ document.documentElement.lang = originalLang;
+ });
+
+ it('formats a using the correct thousands separator', () => {
+ expect(formatNumber(1000000)).toBe('1.000.000');
+ });
+
+ it('formats a using the correct decimal separator', () => {
+ expect(formatNumber(12.345)).toBe('12,345');
+ });
+ });
});
describe('suffixFormatter', () => {
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index 5846acbdb79..b60ddea81ee 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -492,6 +492,28 @@ describe('URL utility', () => {
});
});
+ describe('isExternal', () => {
+ const gitlabUrl = 'https://gitlab.com/';
+
+ beforeEach(() => {
+ gon.gitlab_url = gitlabUrl;
+ });
+
+ afterEach(() => {
+ gon.gitlab_url = '';
+ });
+
+ it.each`
+ url | urlType | external
+ ${'/gitlab-org/gitlab-test/-/issues/2'} | ${'relative'} | ${false}
+ ${gitlabUrl} | ${'absolute and internal'} | ${false}
+ ${`${gitlabUrl}/gitlab-org/gitlab-test`} | ${'absolute and internal'} | ${false}
+ ${'http://jira.atlassian.net/browse/IG-1'} | ${'absolute and external'} | ${true}
+ `('returns $external for $url ($urlType)', ({ url, external }) => {
+ expect(urlUtils.isExternal(url)).toBe(external);
+ });
+ });
+
describe('isBase64DataUrl', () => {
it.each`
url | valid
@@ -858,4 +880,37 @@ describe('URL utility', () => {
expect(urlUtils.getURLOrigin(url)).toBe(expectation);
});
});
+
+ describe('encodeSaferUrl', () => {
+ it.each`
+ character | input | output
+ ${' '} | ${'/url/hello 1.jpg'} | ${'/url/hello%201.jpg'}
+ ${'#'} | ${'/url/hello#1.jpg'} | ${'/url/hello%231.jpg'}
+ ${'!'} | ${'/url/hello!.jpg'} | ${'/url/hello%21.jpg'}
+ ${'~'} | ${'/url/hello~.jpg'} | ${'/url/hello%7E.jpg'}
+ ${'*'} | ${'/url/hello*.jpg'} | ${'/url/hello%2A.jpg'}
+ ${"'"} | ${"/url/hello'.jpg"} | ${'/url/hello%27.jpg'}
+ ${'('} | ${'/url/hello(.jpg'} | ${'/url/hello%28.jpg'}
+ ${')'} | ${'/url/hello).jpg'} | ${'/url/hello%29.jpg'}
+ ${'?'} | ${'/url/hello?.jpg'} | ${'/url/hello%3F.jpg'}
+ ${'='} | ${'/url/hello=.jpg'} | ${'/url/hello%3D.jpg'}
+ ${'+'} | ${'/url/hello+.jpg'} | ${'/url/hello%2B.jpg'}
+ ${'&'} | ${'/url/hello&.jpg'} | ${'/url/hello%26.jpg'}
+ `(
+ 'properly escapes `$character` characters while retaining the integrity of the URL',
+ ({ input, output }) => {
+ expect(urlUtils.encodeSaferUrl(input)).toBe(output);
+ },
+ );
+
+ it.each`
+ character | input
+ ${'/, .'} | ${'/url/hello.png'}
+ ${'\\d'} | ${'/url/hello123.png'}
+ ${'-'} | ${'/url/hello-123.png'}
+ ${'_'} | ${'/url/hello_123.png'}
+ `('makes no changes to unproblematic characters ($character)', ({ input }) => {
+ expect(urlUtils.encodeSaferUrl(input)).toBe(input);
+ });
+ });
});
diff --git a/spec/frontend/line_highlighter_spec.js b/spec/frontend/line_highlighter_spec.js
index 1091bbf8aba..8318f63ab3e 100644
--- a/spec/frontend/line_highlighter_spec.js
+++ b/spec/frontend/line_highlighter_spec.js
@@ -1,8 +1,8 @@
/* eslint-disable no-return-assign, no-new, no-underscore-dangle */
import $ from 'jquery';
-import LineHighlighter from '~/line_highlighter';
import * as utils from '~/lib/utils/common_utils';
+import LineHighlighter from '~/line_highlighter';
describe('LineHighlighter', () => {
const testContext = {};
diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js
index 351ff317feb..b40d9d7d5e2 100644
--- a/spec/frontend/logs/components/environment_logs_spec.js
+++ b/spec/frontend/logs/components/environment_logs_spec.js
@@ -1,9 +1,9 @@
import { GlSprintf, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { scrollDown } from '~/lib/utils/scroll_utils';
import EnvironmentLogs from '~/logs/components/environment_logs.vue';
import { createStore } from '~/logs/stores';
-import { scrollDown } from '~/lib/utils/scroll_utils';
import {
mockEnvName,
mockEnvironments,
diff --git a/spec/frontend/logs/components/log_advanced_filters_spec.js b/spec/frontend/logs/components/log_advanced_filters_spec.js
index dfa8913a301..111542ff33e 100644
--- a/spec/frontend/logs/components/log_advanced_filters_spec.js
+++ b/spec/frontend/logs/components/log_advanced_filters_spec.js
@@ -1,13 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFilteredSearch } from '@gitlab/ui';
-import { defaultTimeRange } from '~/vue_shared/constants';
+import { shallowMount } from '@vue/test-utils';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
-import { createStore } from '~/logs/stores';
+import LogAdvancedFilters from '~/logs/components/log_advanced_filters.vue';
import { TOKEN_TYPE_POD_NAME } from '~/logs/constants';
+import { createStore } from '~/logs/stores';
+import { defaultTimeRange } from '~/vue_shared/constants';
import { mockPods, mockSearch } from '../mock_data';
-import LogAdvancedFilters from '~/logs/components/log_advanced_filters.vue';
-
const module = 'environmentLogs';
describe('LogAdvancedFilters', () => {
diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js
index 55b28445786..9c1617e4daa 100644
--- a/spec/frontend/logs/components/log_control_buttons_spec.js
+++ b/spec/frontend/logs/components/log_control_buttons_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import LogControlButtons from '~/logs/components/log_control_buttons.vue';
describe('LogControlButtons', () => {
diff --git a/spec/frontend/logs/components/log_simple_filters_spec.js b/spec/frontend/logs/components/log_simple_filters_spec.js
index 5bd42fd7dbc..04ad2e03542 100644
--- a/spec/frontend/logs/components/log_simple_filters_spec.js
+++ b/spec/frontend/logs/components/log_simple_filters_spec.js
@@ -1,10 +1,9 @@
import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import LogSimpleFilters from '~/logs/components/log_simple_filters.vue';
import { createStore } from '~/logs/stores';
import { mockPods, mockPodName } from '../mock_data';
-import LogSimpleFilters from '~/logs/components/log_simple_filters.vue';
-
const module = 'environmentLogs';
describe('LogSimpleFilters', () => {
diff --git a/spec/frontend/logs/stores/actions_spec.js b/spec/frontend/logs/stores/actions_spec.js
index bc58f1e677f..92c2f82af27 100644
--- a/spec/frontend/logs/stores/actions_spec.js
+++ b/spec/frontend/logs/stores/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import Tracking from '~/tracking';
-import * as types from '~/logs/stores/mutation_types';
+import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
-import logsPageState from '~/logs/stores/state';
+import { TOKEN_TYPE_POD_NAME } from '~/logs/constants';
import {
setInitData,
showFilteredLogs,
@@ -13,12 +13,12 @@ import {
fetchMoreLogsPrepend,
fetchManagedApps,
} from '~/logs/stores/actions';
+import * as types from '~/logs/stores/mutation_types';
+import logsPageState from '~/logs/stores/state';
+import Tracking from '~/tracking';
import { defaultTimeRange } from '~/vue_shared/constants';
-import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from '~/flash';
-
import {
mockPodName,
mockEnvironmentsEndpoint,
@@ -34,7 +34,6 @@ import {
mockManagedApps,
mockManagedAppsEndpoint,
} from '../mock_data';
-import { TOKEN_TYPE_POD_NAME } from '~/logs/constants';
jest.mock('~/flash');
jest.mock('~/lib/utils/datetime_range');
diff --git a/spec/frontend/logs/stores/mutations_spec.js b/spec/frontend/logs/stores/mutations_spec.js
index 51f6494b011..111c795ba52 100644
--- a/spec/frontend/logs/stores/mutations_spec.js
+++ b/spec/frontend/logs/stores/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/logs/stores/mutations';
import * as types from '~/logs/stores/mutation_types';
+import mutations from '~/logs/stores/mutations';
import logsPageState from '~/logs/stores/state';
import {
diff --git a/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
index 30166e2d5ae..f86237dc160 100644
--- a/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import AccessRequestActionButtons from '~/members/components/action_buttons/access_request_action_buttons.vue';
-import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
import ApproveAccessRequestButton from '~/members/components/action_buttons/approve_access_request_button.vue';
+import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
import { accessRequest as member } from '../../mock_data';
describe('AccessRequestActionButtons', () => {
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 7ce2c633bb3..f77d41a642e 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,6 +1,6 @@
+import { GlButton, GlForm } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlButton, GlForm } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ApproveAccessRequestButton from '~/members/components/action_buttons/approve_access_request_button.vue';
diff --git a/spec/frontend/members/components/action_buttons/leave_button_spec.js b/spec/frontend/members/components/action_buttons/leave_button_spec.js
index 2afe112c74b..4859d033464 100644
--- a/spec/frontend/members/components/action_buttons/leave_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/leave_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import LeaveButton from '~/members/components/action_buttons/leave_button.vue';
import LeaveModal from '~/members/components/modals/leave_modal.vue';
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 45283788676..f6e342898cb 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,6 +1,6 @@
+import { GlButton } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlButton } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import RemoveGroupLinkButton from '~/members/components/action_buttons/remove_group_link_button.vue';
import { group } from '../../mock_data';
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 05ea0dc2886..49b6979f954 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,6 +1,6 @@
+import { GlButton } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlButton } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ResendInviteButton from '~/members/components/action_buttons/resend_invite_button.vue';
diff --git a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
index f28e5040006..1d7ea5b3109 100644
--- a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import UserActionButtons from '~/members/components/action_buttons/user_action_buttons.vue';
-import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
import LeaveButton from '~/members/components/action_buttons/leave_button.vue';
+import RemoveMemberButton from '~/members/components/action_buttons/remove_member_button.vue';
+import UserActionButtons from '~/members/components/action_buttons/user_action_buttons.vue';
import { member, orphanedMember } from '../../mock_data';
describe('UserActionButtons', () => {
diff --git a/spec/frontend/members/components/app_spec.js b/spec/frontend/members/components/app_spec.js
new file mode 100644
index 00000000000..a1329c3ee9f
--- /dev/null
+++ b/spec/frontend/members/components/app_spec.js
@@ -0,0 +1,95 @@
+import { GlAlert } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import Vuex from 'vuex';
+import * as commonUtils from '~/lib/utils/common_utils';
+import MembersApp from '~/members/components/app.vue';
+import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
+import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_types';
+import mutations from '~/members/store/mutations';
+
+describe('MembersApp', () => {
+ const localVue = createLocalVue();
+ localVue.use(Vuex);
+
+ let wrapper;
+ let store;
+
+ const createComponent = (state = {}, options = {}) => {
+ store = new Vuex.Store({
+ state: {
+ showError: true,
+ errorMessage: 'Something went wrong, please try again.',
+ ...state,
+ },
+ mutations,
+ });
+
+ wrapper = shallowMount(MembersApp, {
+ localVue,
+ store,
+ ...options,
+ });
+ };
+
+ const findAlert = () => wrapper.find(GlAlert);
+ const findFilterSortContainer = () => wrapper.find(FilterSortContainer);
+
+ beforeEach(() => {
+ commonUtils.scrollToElement = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ store = null;
+ });
+
+ describe('when `showError` is changed to `true`', () => {
+ it('renders and scrolls to error alert', async () => {
+ createComponent({ showError: false, errorMessage: '' });
+
+ store.commit(RECEIVE_MEMBER_ROLE_ERROR, { error: new Error('Network Error') });
+
+ await nextTick();
+
+ const alert = findAlert();
+
+ expect(alert.exists()).toBe(true);
+ expect(alert.text()).toBe(
+ "An error occurred while updating the member's role, please try again.",
+ );
+ expect(commonUtils.scrollToElement).toHaveBeenCalledWith(alert.element);
+ });
+ });
+
+ describe('when `showError` is changed to `false`', () => {
+ it('does not render and scroll to error alert', async () => {
+ createComponent();
+
+ store.commit(HIDE_ERROR);
+
+ await nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ expect(commonUtils.scrollToElement).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when alert is dismissed', () => {
+ it('hides alert', async () => {
+ createComponent();
+
+ findAlert().vm.$emit('dismiss');
+
+ await nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ it('renders `FilterSortContainer`', () => {
+ createComponent();
+
+ expect(findFilterSortContainer().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/members/components/avatars/group_avatar_spec.js b/spec/frontend/members/components/avatars/group_avatar_spec.js
index 658bb9462b0..9c1574a84ee 100644
--- a/spec/frontend/members/components/avatars/group_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/group_avatar_spec.js
@@ -1,8 +1,8 @@
-import { mount, createWrapper } from '@vue/test-utils';
-import { getByText as getByTextHelper } from '@testing-library/dom';
import { GlAvatarLink } from '@gitlab/ui';
-import { group as member } from '../../mock_data';
+import { getByText as getByTextHelper } from '@testing-library/dom';
+import { mount, createWrapper } from '@vue/test-utils';
import GroupAvatar from '~/members/components/avatars/group_avatar.vue';
+import { group as member } from '../../mock_data';
describe('MemberList', () => {
let wrapper;
diff --git a/spec/frontend/members/components/avatars/invite_avatar_spec.js b/spec/frontend/members/components/avatars/invite_avatar_spec.js
index 13ee727528b..b197a46c0d1 100644
--- a/spec/frontend/members/components/avatars/invite_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/invite_avatar_spec.js
@@ -1,7 +1,7 @@
-import { mount, createWrapper } from '@vue/test-utils';
import { getByText as getByTextHelper } from '@testing-library/dom';
-import { invite as member } from '../../mock_data';
+import { mount, createWrapper } from '@vue/test-utils';
import InviteAvatar from '~/members/components/avatars/invite_avatar.vue';
+import { invite as member } from '../../mock_data';
describe('MemberList', () => {
let wrapper;
diff --git a/spec/frontend/members/components/avatars/user_avatar_spec.js b/spec/frontend/members/components/avatars/user_avatar_spec.js
index 411ec1a54de..303c82582a3 100644
--- a/spec/frontend/members/components/avatars/user_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/user_avatar_spec.js
@@ -1,8 +1,8 @@
-import { mount, createWrapper } from '@vue/test-utils';
-import { within } from '@testing-library/dom';
import { GlAvatarLink, GlBadge } from '@gitlab/ui';
-import { member as memberMock, orphanedMember } from '../../mock_data';
+import { within } from '@testing-library/dom';
+import { mount, createWrapper } from '@vue/test-utils';
import UserAvatar from '~/members/components/avatars/user_avatar.vue';
+import { member as memberMock, orphanedMember } from '../../mock_data';
describe('UserAvatar', () => {
let wrapper;
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 2bed1e803ca..14b437a8c4e 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,6 +1,6 @@
+import { GlFilteredSearchToken } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlFilteredSearchToken } from '@gitlab/ui';
import MembersFilteredSearchBar from '~/members/components/filter_sort/members_filtered_search_bar.vue';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
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 d98c9116512..357fad741e9 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -1,8 +1,8 @@
+import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlSorting, GlSortingItem } from '@gitlab/ui';
-import SortDropdown from '~/members/components/filter_sort/sort_dropdown.vue';
import * as urlUtilities from '~/lib/utils/url_utility';
+import SortDropdown from '~/members/components/filter_sort/sort_dropdown.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/members/components/modals/leave_modal_spec.js b/spec/frontend/members/components/modals/leave_modal_spec.js
index dca47d1f6af..2d52911572f 100644
--- a/spec/frontend/members/components/modals/leave_modal_spec.js
+++ b/spec/frontend/members/components/modals/leave_modal_spec.js
@@ -1,7 +1,7 @@
-import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
import { GlModal, GlForm } from '@gitlab/ui';
-import { nextTick } from 'vue';
import { within } from '@testing-library/dom';
+import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Vuex from 'vuex';
import LeaveModal from '~/members/components/modals/leave_modal.vue';
import { LEAVE_MODAL_ID } from '~/members/constants';
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 234857419b6..62df912c1a2 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 { mount, createLocalVue, createWrapper } from '@vue/test-utils';
import { GlModal, GlForm } from '@gitlab/ui';
-import { nextTick } from 'vue';
import { within } from '@testing-library/dom';
+import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
+import { nextTick } from 'vue';
import Vuex from 'vuex';
import RemoveGroupLinkModal from '~/members/components/modals/remove_group_link_modal.vue';
import { REMOVE_GROUP_LINK_MODAL_ID } from '~/members/constants';
diff --git a/spec/frontend/members/components/table/created_at_spec.js b/spec/frontend/members/components/table/created_at_spec.js
index dc1f62722ab..74b71e22893 100644
--- a/spec/frontend/members/components/table/created_at_spec.js
+++ b/spec/frontend/members/components/table/created_at_spec.js
@@ -1,5 +1,5 @@
-import { mount, createWrapper } from '@vue/test-utils';
import { within } from '@testing-library/dom';
+import { mount, createWrapper } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
import CreatedAt from '~/members/components/table/created_at.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
diff --git a/spec/frontend/members/components/table/expiration_datepicker_spec.js b/spec/frontend/members/components/table/expiration_datepicker_spec.js
index 0caaafb8d7b..d26172b4ed1 100644
--- a/spec/frontend/members/components/table/expiration_datepicker_spec.js
+++ b/spec/frontend/members/components/table/expiration_datepicker_spec.js
@@ -1,7 +1,7 @@
+import { GlDatepicker } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
import { nextTick } from 'vue';
-import { GlDatepicker } from '@gitlab/ui';
+import Vuex from 'vuex';
import { useFakeDate } from 'helpers/fake_date';
import waitForPromises from 'helpers/wait_for_promises';
import ExpirationDatepicker from '~/members/components/table/expiration_datepicker.vue';
diff --git a/spec/frontend/members/components/table/expires_at_spec.js b/spec/frontend/members/components/table/expires_at_spec.js
index 321008727cd..02fe3c6d684 100644
--- a/spec/frontend/members/components/table/expires_at_spec.js
+++ b/spec/frontend/members/components/table/expires_at_spec.js
@@ -1,5 +1,5 @@
-import { mount, createWrapper } from '@vue/test-utils';
import { within } from '@testing-library/dom';
+import { mount, createWrapper } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ExpiresAt from '~/members/components/table/expires_at.vue';
diff --git a/spec/frontend/members/components/table/member_action_buttons_spec.js b/spec/frontend/members/components/table/member_action_buttons_spec.js
index b7a6df3d054..546d09732d6 100644
--- a/spec/frontend/members/components/table/member_action_buttons_spec.js
+++ b/spec/frontend/members/components/table/member_action_buttons_spec.js
@@ -1,11 +1,11 @@
import { shallowMount } from '@vue/test-utils';
-import { MEMBER_TYPES } from '~/members/constants';
-import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
-import MemberActionButtons from '~/members/components/table/member_action_buttons.vue';
-import UserActionButtons from '~/members/components/action_buttons/user_action_buttons.vue';
+import AccessRequestActionButtons from '~/members/components/action_buttons/access_request_action_buttons.vue';
import GroupActionButtons from '~/members/components/action_buttons/group_action_buttons.vue';
import InviteActionButtons from '~/members/components/action_buttons/invite_action_buttons.vue';
-import AccessRequestActionButtons from '~/members/components/action_buttons/access_request_action_buttons.vue';
+import UserActionButtons from '~/members/components/action_buttons/user_action_buttons.vue';
+import MemberActionButtons from '~/members/components/table/member_action_buttons.vue';
+import { MEMBER_TYPES } from '~/members/constants';
+import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
describe('MemberActionButtons', () => {
let wrapper;
diff --git a/spec/frontend/members/components/table/member_avatar_spec.js b/spec/frontend/members/components/table/member_avatar_spec.js
index 4341dfbbaf9..3cce64effbc 100644
--- a/spec/frontend/members/components/table/member_avatar_spec.js
+++ b/spec/frontend/members/components/table/member_avatar_spec.js
@@ -1,10 +1,10 @@
import { shallowMount } from '@vue/test-utils';
-import { MEMBER_TYPES } from '~/members/constants';
-import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
-import MemberAvatar from '~/members/components/table/member_avatar.vue';
-import UserAvatar from '~/members/components/avatars/user_avatar.vue';
import GroupAvatar from '~/members/components/avatars/group_avatar.vue';
import InviteAvatar from '~/members/components/avatars/invite_avatar.vue';
+import UserAvatar from '~/members/components/avatars/user_avatar.vue';
+import MemberAvatar from '~/members/components/table/member_avatar.vue';
+import { MEMBER_TYPES } from '~/members/constants';
+import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
describe('MemberList', () => {
let wrapper;
diff --git a/spec/frontend/members/components/table/member_source_spec.js b/spec/frontend/members/components/table/member_source_spec.js
index 95547090aed..2cd888207b1 100644
--- a/spec/frontend/members/components/table/member_source_spec.js
+++ b/spec/frontend/members/components/table/member_source_spec.js
@@ -1,5 +1,5 @@
-import { mount, createWrapper } from '@vue/test-utils';
import { getByText as getByTextHelper } from '@testing-library/dom';
+import { mount, createWrapper } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import MemberSource from '~/members/components/table/member_source.vue';
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 117c9255c00..b7dcd2a9fae 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -1,8 +1,15 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { MEMBER_TYPES } from '~/members/constants';
-import { member as memberMock, group, invite, accessRequest } from '../../mock_data';
import MembersTableCell from '~/members/components/table/members_table_cell.vue';
+import { MEMBER_TYPES } from '~/members/constants';
+import {
+ member as memberMock,
+ directMember,
+ inheritedMember,
+ group,
+ invite,
+ accessRequest,
+} from '../../mock_data';
describe('MembersTableCell', () => {
const WrappedComponent = {
@@ -31,7 +38,7 @@ describe('MembersTableCell', () => {
const localVue = createLocalVue();
localVue.use(Vuex);
- localVue.component('wrapped-component', WrappedComponent);
+ localVue.component('WrappedComponent', WrappedComponent);
const createStore = (state = {}) => {
return new Vuex.Store({
@@ -75,19 +82,12 @@ describe('MembersTableCell', () => {
const createComponentWithDirectMember = (member = {}) => {
createComponent({
- member: {
- ...memberMock,
- source: {
- ...memberMock.source,
- id: 1,
- },
- ...member,
- },
+ member: { ...directMember, ...member },
});
};
const createComponentWithInheritedMember = (member = {}) => {
createComponent({
- member: { ...memberMock, ...member },
+ member: { ...inheritedMember, ...member },
});
};
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index dbaccde069c..cf5811e72e7 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -1,21 +1,21 @@
-import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
-import Vuex from 'vuex';
+import { GlBadge, GlTable } from '@gitlab/ui';
import {
getByText as getByTextHelper,
getByTestId as getByTestIdHelper,
within,
} from '@testing-library/dom';
-import { GlBadge, GlTable } from '@gitlab/ui';
-import MembersTable from '~/members/components/table/members_table.vue';
-import MemberAvatar from '~/members/components/table/member_avatar.vue';
-import MemberSource from '~/members/components/table/member_source.vue';
-import ExpiresAt from '~/members/components/table/expires_at.vue';
+import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
+import Vuex from 'vuex';
import CreatedAt from '~/members/components/table/created_at.vue';
-import RoleDropdown from '~/members/components/table/role_dropdown.vue';
import ExpirationDatepicker from '~/members/components/table/expiration_datepicker.vue';
+import ExpiresAt from '~/members/components/table/expires_at.vue';
import MemberActionButtons from '~/members/components/table/member_action_buttons.vue';
+import MemberAvatar from '~/members/components/table/member_avatar.vue';
+import MemberSource from '~/members/components/table/member_source.vue';
+import MembersTable from '~/members/components/table/members_table.vue';
+import RoleDropdown from '~/members/components/table/role_dropdown.vue';
import * as initUserPopovers from '~/user_popovers';
-import { member as memberMock, invite, accessRequest } from '../../mock_data';
+import { member as memberMock, directMember, invite, accessRequest } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -74,11 +74,6 @@ describe('MembersTable', () => {
});
describe('fields', () => {
- const directMember = {
- ...memberMock,
- source: { ...memberMock.source, id: 1 },
- };
-
const memberCanUpdate = {
...directMember,
canUpdate: true,
@@ -154,7 +149,7 @@ describe('MembersTable', () => {
expect(findTableCellByMemberId('Actions', members[0].id).classes()).toStrictEqual([
'col-actions',
'gl-display-none!',
- 'gl-display-lg-table-cell!',
+ 'gl-lg-display-table-cell!',
]);
expect(findTableCellByMemberId('Actions', members[1].id).classes()).toStrictEqual([
'col-actions',
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index 96a388614f3..aa280599061 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -1,10 +1,11 @@
-import { mount, createWrapper, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import { nextTick } from 'vue';
-import { within } from '@testing-library/dom';
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 Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
+import { BV_DROPDOWN_SHOW } from '~/lib/utils/constants';
import RoleDropdown from '~/members/components/table/role_dropdown.vue';
import { member } from '../../mock_data';
@@ -67,7 +68,7 @@ describe('RoleDropdown', () => {
createComponent();
findDropdownToggle().trigger('click');
- wrapper.vm.$root.$on('bv::dropdown::shown', () => {
+ wrapper.vm.$root.$on(BV_DROPDOWN_SHOW, () => {
done();
});
});
diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js
new file mode 100644
index 00000000000..dd3b9ddd912
--- /dev/null
+++ b/spec/frontend/members/index_spec.js
@@ -0,0 +1,113 @@
+import { createWrapper } from '@vue/test-utils';
+import MembersApp from '~/members/components/app.vue';
+import { initMembersApp } from '~/members/index';
+import { membersJsonString, members } from './mock_data';
+
+describe('initMembersApp', () => {
+ let el;
+ let vm;
+ let wrapper;
+
+ const setup = () => {
+ vm = initMembersApp(el, {
+ tableFields: ['account'],
+ tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
+ tableSortableFields: ['account'],
+ requestFormatter: () => ({}),
+ filteredSearchBar: { show: false },
+ });
+ wrapper = createWrapper(vm);
+ };
+
+ beforeEach(() => {
+ el = document.createElement('div');
+ el.setAttribute('data-members', membersJsonString);
+ el.setAttribute('data-source-id', '234');
+ el.setAttribute('data-can-manage-members', 'true');
+ el.setAttribute('data-member-path', '/groups/foo-bar/-/group_members/:id');
+
+ window.gon = { current_user_id: 123 };
+ });
+
+ afterEach(() => {
+ el = null;
+
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders `MembersApp`', () => {
+ setup();
+
+ expect(wrapper.find(MembersApp).exists()).toBe(true);
+ });
+
+ it('sets `currentUserId` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.currentUserId).toBe(123);
+ });
+
+ describe('when `gon.current_user_id` is not set (user is not logged in)', () => {
+ it('sets `currentUserId` as `null` in Vuex store', () => {
+ window.gon = {};
+ setup();
+
+ expect(vm.$store.state.currentUserId).toBeNull();
+ });
+ });
+
+ it('parses and sets `data-source-id` as `sourceId` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.sourceId).toBe(234);
+ });
+
+ it('parses and sets `data-can-manage-members` as `canManageMembers` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.canManageMembers).toBe(true);
+ });
+
+ it('parses and sets `members` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.members).toEqual(members);
+ });
+
+ it('sets `tableFields` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.tableFields).toEqual(['account']);
+ });
+
+ it('sets `tableAttrs` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } });
+ });
+
+ it('sets `tableSortableFields` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.tableSortableFields).toEqual(['account']);
+ });
+
+ it('sets `requestFormatter` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.requestFormatter()).toEqual({});
+ });
+
+ it('sets `filteredSearchBar` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.filteredSearchBar).toEqual({ show: false });
+ });
+
+ it('sets `memberPath` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.memberPath).toBe('/groups/foo-bar/-/group_members/:id');
+ });
+});
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index e668f2a1998..fa324ce1cf9 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -4,6 +4,7 @@ export const member = {
canRemove: false,
canOverride: false,
isOverridden: false,
+ isDirectMember: false,
accessLevel: { integerValue: 50, stringValue: 'Owner' },
source: {
id: 178,
@@ -69,3 +70,8 @@ export const accessRequest = {
};
export const members = [member];
+
+export const membersJsonString = JSON.stringify(members);
+
+export const directMember = { ...member, isDirectMember: true };
+export const inheritedMember = { ...member, isDirectMember: false };
diff --git a/spec/frontend/members/store/actions_spec.js b/spec/frontend/members/store/actions_spec.js
index 5424fee0750..d913c5c56df 100644
--- a/spec/frontend/members/store/actions_spec.js
+++ b/spec/frontend/members/store/actions_spec.js
@@ -1,17 +1,17 @@
-import { noop } from 'lodash';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import { members, group } from 'jest/members/mock_data';
-import testAction from 'helpers/vuex_action_helper';
+import { noop } from 'lodash';
import { useFakeDate } from 'helpers/fake_date';
+import testAction from 'helpers/vuex_action_helper';
+import { members, group } from 'jest/members/mock_data';
import httpStatusCodes from '~/lib/utils/http_status';
-import * as types from '~/members/store/mutation_types';
import {
updateMemberRole,
showRemoveGroupLinkModal,
hideRemoveGroupLinkModal,
updateMemberExpiration,
} from '~/members/store/actions';
+import * as types from '~/members/store/mutation_types';
describe('Vuex members actions', () => {
describe('update member actions', () => {
@@ -57,15 +57,17 @@ describe('Vuex members actions', () => {
describe('unsuccessful request', () => {
it(`commits ${types.RECEIVE_MEMBER_ROLE_ERROR} mutation and throws error`, async () => {
- mock.onPut().networkError();
+ const error = new Error('Network Error');
+ mock.onPut().reply(() => Promise.reject(error));
await expect(
testAction(updateMemberRole, payload, state, [
{
type: types.RECEIVE_MEMBER_ROLE_ERROR,
+ payload: { error },
},
]),
- ).rejects.toThrowError(new Error('Network Error'));
+ ).rejects.toThrowError(error);
});
});
});
@@ -108,15 +110,17 @@ describe('Vuex members actions', () => {
describe('unsuccessful request', () => {
it(`commits ${types.RECEIVE_MEMBER_EXPIRATION_ERROR} mutation and throws error`, async () => {
- mock.onPut().networkError();
+ const error = new Error('Network Error');
+ mock.onPut().reply(() => Promise.reject(error));
await expect(
testAction(updateMemberExpiration, { memberId, expiresAt }, state, [
{
type: types.RECEIVE_MEMBER_EXPIRATION_ERROR,
+ payload: { error },
},
]),
- ).rejects.toThrowError(new Error('Network Error'));
+ ).rejects.toThrowError(error);
});
});
});
diff --git a/spec/frontend/members/store/mutations_spec.js b/spec/frontend/members/store/mutations_spec.js
index 488bfdf15fd..7ad7034eb6d 100644
--- a/spec/frontend/members/store/mutations_spec.js
+++ b/spec/frontend/members/store/mutations_spec.js
@@ -1,6 +1,6 @@
import { members, group } from 'jest/members/mock_data';
-import mutations from '~/members/store/mutations';
import * as types from '~/members/store/mutation_types';
+import mutations from '~/members/store/mutations';
describe('Vuex members mutations', () => {
describe('update member mutations', () => {
@@ -28,13 +28,33 @@ describe('Vuex members mutations', () => {
});
describe(types.RECEIVE_MEMBER_ROLE_ERROR, () => {
- it('shows error message', () => {
- mutations[types.RECEIVE_MEMBER_ROLE_ERROR](state);
+ describe('when error does not have a message', () => {
+ it('shows default error message', () => {
+ mutations[types.RECEIVE_MEMBER_ROLE_ERROR](state, {
+ error: new Error('Network Error'),
+ });
+
+ expect(state.showError).toBe(true);
+ expect(state.errorMessage).toBe(
+ "An error occurred while updating the member's role, please try again.",
+ );
+ });
+ });
+
+ describe('when error has a message', () => {
+ it('shows error message', () => {
+ const error = new Error('Request failed with status code 422');
+ const message =
+ 'User email "john.smith@gmail.com" does not match the allowed domain of example.com';
+
+ error.response = {
+ data: { message },
+ };
+ mutations[types.RECEIVE_MEMBER_ROLE_ERROR](state, { error });
- expect(state.showError).toBe(true);
- expect(state.errorMessage).toBe(
- "An error occurred while updating the member's role, please try again.",
- );
+ expect(state.showError).toBe(true);
+ expect(state.errorMessage).toBe(message);
+ });
});
});
@@ -52,13 +72,33 @@ describe('Vuex members mutations', () => {
});
describe(types.RECEIVE_MEMBER_EXPIRATION_ERROR, () => {
- it('shows error message', () => {
- mutations[types.RECEIVE_MEMBER_EXPIRATION_ERROR](state);
+ describe('when error does not have a message', () => {
+ it('shows default error message', () => {
+ mutations[types.RECEIVE_MEMBER_EXPIRATION_ERROR](state, {
+ error: new Error('Network Error'),
+ });
+
+ expect(state.showError).toBe(true);
+ expect(state.errorMessage).toBe(
+ "An error occurred while updating the member's expiration date, please try again.",
+ );
+ });
+ });
- expect(state.showError).toBe(true);
- expect(state.errorMessage).toBe(
- "An error occurred while updating the member's expiration date, please try again.",
- );
+ describe('when error has a message', () => {
+ it('shows error message', () => {
+ const error = new Error('Request failed with status code 422');
+ const message =
+ 'User email "john.smith@gmail.com" does not match the allowed domain of example.com';
+
+ error.response = {
+ data: { message },
+ };
+ mutations[types.RECEIVE_MEMBER_EXPIRATION_ERROR](state, { error });
+
+ expect(state.showError).toBe(true);
+ expect(state.errorMessage).toBe(message);
+ });
});
});
});
diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js
index 7cd4e735b55..f447a4c4ee9 100644
--- a/spec/frontend/members/utils_spec.js
+++ b/spec/frontend/members/utils_spec.js
@@ -1,3 +1,4 @@
+import { DEFAULT_SORT } from '~/members/constants';
import {
generateBadges,
isGroup,
@@ -9,12 +10,19 @@ import {
canOverride,
parseSortParam,
buildSortHref,
+ parseDataAttributes,
+ groupLinkRequestFormatter,
} from '~/members/utils';
-import { DEFAULT_SORT } from '~/members/constants';
-import { member as memberMock, group, invite } from './mock_data';
+import {
+ member as memberMock,
+ directMember,
+ inheritedMember,
+ group,
+ invite,
+ membersJsonString,
+ members,
+} from './mock_data';
-const DIRECT_MEMBER_ID = 178;
-const INHERITED_MEMBER_ID = 179;
const IS_CURRENT_USER_ID = 123;
const IS_NOT_CURRENT_USER_ID = 124;
const URL_HOST = 'https://localhost/';
@@ -57,11 +65,11 @@ describe('Members Utils', () => {
describe('isDirectMember', () => {
test.each`
- sourceId | expected
- ${DIRECT_MEMBER_ID} | ${true}
- ${INHERITED_MEMBER_ID} | ${false}
- `('returns $expected', ({ sourceId, expected }) => {
- expect(isDirectMember(memberMock, sourceId)).toBe(expected);
+ member | expected
+ ${directMember} | ${true}
+ ${inheritedMember} | ${false}
+ `('returns $expected', ({ member, expected }) => {
+ expect(isDirectMember(member)).toBe(expected);
});
});
@@ -76,18 +84,13 @@ describe('Members Utils', () => {
});
describe('canRemove', () => {
- const memberCanRemove = {
- ...memberMock,
- canRemove: true,
- };
-
test.each`
- member | sourceId | expected
- ${memberCanRemove} | ${DIRECT_MEMBER_ID} | ${true}
- ${memberCanRemove} | ${INHERITED_MEMBER_ID} | ${false}
- ${memberMock} | ${INHERITED_MEMBER_ID} | ${false}
- `('returns $expected', ({ member, sourceId, expected }) => {
- expect(canRemove(member, sourceId)).toBe(expected);
+ member | expected
+ ${{ ...directMember, canRemove: true }} | ${true}
+ ${{ ...inheritedMember, canRemove: true }} | ${false}
+ ${{ ...memberMock, canRemove: false }} | ${false}
+ `('returns $expected', ({ member, expected }) => {
+ expect(canRemove(member)).toBe(expected);
});
});
@@ -96,25 +99,20 @@ describe('Members Utils', () => {
member | expected
${invite} | ${true}
${{ ...invite, invite: { ...invite.invite, canResend: false } }} | ${false}
- `('returns $expected', ({ member, sourceId, expected }) => {
- expect(canResend(member, sourceId)).toBe(expected);
+ `('returns $expected', ({ member, expected }) => {
+ expect(canResend(member)).toBe(expected);
});
});
describe('canUpdate', () => {
- const memberCanUpdate = {
- ...memberMock,
- canUpdate: true,
- };
-
test.each`
- member | currentUserId | sourceId | expected
- ${memberCanUpdate} | ${IS_NOT_CURRENT_USER_ID} | ${DIRECT_MEMBER_ID} | ${true}
- ${memberCanUpdate} | ${IS_CURRENT_USER_ID} | ${DIRECT_MEMBER_ID} | ${false}
- ${memberCanUpdate} | ${IS_CURRENT_USER_ID} | ${INHERITED_MEMBER_ID} | ${false}
- ${memberMock} | ${IS_NOT_CURRENT_USER_ID} | ${DIRECT_MEMBER_ID} | ${false}
- `('returns $expected', ({ member, currentUserId, sourceId, expected }) => {
- expect(canUpdate(member, currentUserId, sourceId)).toBe(expected);
+ member | currentUserId | expected
+ ${{ ...directMember, canUpdate: true }} | ${IS_NOT_CURRENT_USER_ID} | ${true}
+ ${{ ...directMember, canUpdate: true }} | ${IS_CURRENT_USER_ID} | ${false}
+ ${{ ...inheritedMember, canUpdate: true }} | ${IS_CURRENT_USER_ID} | ${false}
+ ${{ ...directMember, canUpdate: false }} | ${IS_NOT_CURRENT_USER_ID} | ${false}
+ `('returns $expected', ({ member, currentUserId, expected }) => {
+ expect(canUpdate(member, currentUserId)).toBe(expected);
});
});
@@ -229,4 +227,38 @@ describe('Members Utils', () => {
});
});
});
+
+ describe('parseDataAttributes', () => {
+ let el;
+
+ beforeEach(() => {
+ el = document.createElement('div');
+ el.setAttribute('data-members', membersJsonString);
+ el.setAttribute('data-source-id', '234');
+ el.setAttribute('data-can-manage-members', 'true');
+ });
+
+ afterEach(() => {
+ el = null;
+ });
+
+ it('correctly parses the data attributes', () => {
+ expect(parseDataAttributes(el)).toEqual({
+ members,
+ sourceId: 234,
+ canManageMembers: true,
+ });
+ });
+ });
+
+ describe('groupLinkRequestFormatter', () => {
+ it('returns expected format', () => {
+ expect(
+ groupLinkRequestFormatter({
+ accessLevel: 50,
+ expires_at: '2020-10-16',
+ }),
+ ).toEqual({ group_link: { group_access: 50, expires_at: '2020-10-16' } });
+ });
+ });
});
diff --git a/spec/frontend/merge_request/components/status_box_spec.js b/spec/frontend/merge_request/components/status_box_spec.js
index e6b6512476b..9212ae19c2d 100644
--- a/spec/frontend/merge_request/components/status_box_spec.js
+++ b/spec/frontend/merge_request/components/status_box_spec.js
@@ -1,6 +1,6 @@
-import { nextTick } from 'vue';
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import StatusBox from '~/merge_request/components/status_box.vue';
import mrEventHub from '~/merge_request/eventhub';
@@ -18,6 +18,12 @@ const testCases = [
icon: 'issue-open-m',
},
{
+ name: 'Open',
+ state: 'locked',
+ class: 'status-box-open',
+ icon: 'issue-open-m',
+ },
+ {
name: 'Closed',
state: 'closed',
class: 'status-box-mr-closed',
diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js
index 5624043260a..84647a108b2 100644
--- a/spec/frontend/merge_request_spec.js
+++ b/spec/frontend/merge_request_spec.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
import MergeRequest from '~/merge_request';
diff --git a/spec/frontend/merge_request_tabs_spec.js b/spec/frontend/merge_request_tabs_spec.js
index 82462036219..fd2c240aff3 100644
--- a/spec/frontend/merge_request_tabs_spec.js
+++ b/spec/frontend/merge_request_tabs_spec.js
@@ -1,9 +1,8 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import initMrPage from 'helpers/init_vue_mr_page_helper';
import axios from '~/lib/utils/axios_utils';
import MergeRequestTabs from '~/merge_request_tabs';
-import '~/commit/pipelines/pipelines_bundle';
import '~/lib/utils/common_utils';
jest.mock('~/lib/utils/webpack', () => ({
diff --git a/spec/frontend/milestones/milestone_combobox_spec.js b/spec/frontend/milestones/milestone_combobox_spec.js
index 8c519abe382..4d1a0a0a440 100644
--- a/spec/frontend/milestones/milestone_combobox_spec.js
+++ b/spec/frontend/milestones/milestone_combobox_spec.js
@@ -1,13 +1,13 @@
-import Vue, { nextTick } from 'vue';
-import Vuex from 'vuex';
+import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
+import Vue, { nextTick } from 'vue';
+import Vuex from 'vuex';
import { ENTER_KEY } from '~/lib/utils/keys';
import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
-import { projectMilestones, groupMilestones } from './mock_data';
import createStore from '~/milestones/stores/';
+import { projectMilestones, groupMilestones } from './mock_data';
const extraLinks = [
{ text: 'Create new', url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/new' },
diff --git a/spec/frontend/milestones/stores/actions_spec.js b/spec/frontend/milestones/stores/actions_spec.js
index a62b0c49a80..4355ea71fb2 100644
--- a/spec/frontend/milestones/stores/actions_spec.js
+++ b/spec/frontend/milestones/stores/actions_spec.js
@@ -1,7 +1,7 @@
import testAction from 'helpers/vuex_action_helper';
-import createState from '~/milestones/stores/state';
import * as actions from '~/milestones/stores/actions';
import * as types from '~/milestones/stores/mutation_types';
+import createState from '~/milestones/stores/state';
let mockProjectMilestonesReturnValue;
let mockGroupMilestonesReturnValue;
diff --git a/spec/frontend/milestones/stores/mutations_spec.js b/spec/frontend/milestones/stores/mutations_spec.js
index 0b69a9d572d..91b2acf23c5 100644
--- a/spec/frontend/milestones/stores/mutations_spec.js
+++ b/spec/frontend/milestones/stores/mutations_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/milestones/stores/state';
-import mutations from '~/milestones/stores/mutations';
import * as types from '~/milestones/stores/mutation_types';
+import mutations from '~/milestones/stores/mutations';
+import createState from '~/milestones/stores/state';
describe('Milestones combobox Vuex store mutations', () => {
let state;
diff --git a/spec/frontend/mini_pipeline_graph_dropdown_spec.js b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
index b21ddabbfb1..3ff34c967e4 100644
--- a/spec/frontend/mini_pipeline_graph_dropdown_spec.js
+++ b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
diff --git a/spec/frontend/monitoring/alert_widget_spec.js b/spec/frontend/monitoring/alert_widget_spec.js
index fd9fb374274..1f0597bac67 100644
--- a/spec/frontend/monitoring/alert_widget_spec.js
+++ b/spec/frontend/monitoring/alert_widget_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlTooltip, GlSprintf, GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import AlertWidget from '~/monitoring/components/alert_widget.vue';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import AlertWidget from '~/monitoring/components/alert_widget.vue';
const mockReadAlert = jest.fn();
const mockCreateAlert = jest.fn();
diff --git a/spec/frontend/monitoring/components/alert_widget_form_spec.js b/spec/frontend/monitoring/components/alert_widget_form_spec.js
index 6d87fb85f4d..e0ef1040f6b 100644
--- a/spec/frontend/monitoring/components/alert_widget_form_spec.js
+++ b/spec/frontend/monitoring/components/alert_widget_form_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import INVALID_URL from '~/lib/utils/invalid_url';
import AlertWidgetForm from '~/monitoring/components/alert_widget_form.vue';
import ModalStub from '../stubs/modal_stub';
diff --git a/spec/frontend/monitoring/components/charts/anomaly_spec.js b/spec/frontend/monitoring/components/charts/anomaly_spec.js
index dad3003d536..c44fd8dce33 100644
--- a/spec/frontend/monitoring/components/charts/anomaly_spec.js
+++ b/spec/frontend/monitoring/components/charts/anomaly_spec.js
@@ -2,10 +2,10 @@ import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import Anomaly from '~/monitoring/components/charts/anomaly.vue';
+import MonitorTimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
import { colorValues } from '~/monitoring/constants';
-import { anomalyDeploymentData, mockProjectDir } from '../../mock_data';
import { anomalyGraphData } from '../../graph_data';
-import MonitorTimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
+import { anomalyDeploymentData, mockProjectDir } from '../../mock_data';
const mockProjectPath = `${TEST_HOST}${mockProjectDir}`;
diff --git a/spec/frontend/monitoring/components/charts/bar_spec.js b/spec/frontend/monitoring/components/charts/bar_spec.js
index 40edde5f666..6368c53943a 100644
--- a/spec/frontend/monitoring/components/charts/bar_spec.js
+++ b/spec/frontend/monitoring/components/charts/bar_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBarChart } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
import Bar from '~/monitoring/components/charts/bar.vue';
import { barGraphData } from '../../graph_data';
diff --git a/spec/frontend/monitoring/components/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index 0c4b6e8990d..e10cb3a456a 100644
--- a/spec/frontend/monitoring/components/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -1,6 +1,6 @@
+import { GlColumnChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
import timezoneMock from 'timezone-mock';
-import { GlColumnChart } from '@gitlab/ui/dist/charts';
import ColumnChart from '~/monitoring/components/charts/column.vue';
jest.mock('~/lib/utils/icon_utils', () => ({
diff --git a/spec/frontend/monitoring/components/charts/gauge_spec.js b/spec/frontend/monitoring/components/charts/gauge_spec.js
index 9215f2e411f..c8f67d5d8c7 100644
--- a/spec/frontend/monitoring/components/charts/gauge_spec.js
+++ b/spec/frontend/monitoring/components/charts/gauge_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlGaugeChart } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
import GaugeChart from '~/monitoring/components/charts/gauge.vue';
import { gaugeChartGraphData } from '../../graph_data';
diff --git a/spec/frontend/monitoring/components/charts/heatmap_spec.js b/spec/frontend/monitoring/components/charts/heatmap_spec.js
index c8375810a7b..841b7e0648a 100644
--- a/spec/frontend/monitoring/components/charts/heatmap_spec.js
+++ b/spec/frontend/monitoring/components/charts/heatmap_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlHeatmap } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
import timezoneMock from 'timezone-mock';
import Heatmap from '~/monitoring/components/charts/heatmap.vue';
import { heatmapGraphData } from '../../graph_data';
diff --git a/spec/frontend/monitoring/components/charts/single_stat_spec.js b/spec/frontend/monitoring/components/charts/single_stat_spec.js
index 37712eb3012..8633b49565f 100644
--- a/spec/frontend/monitoring/components/charts/single_stat_spec.js
+++ b/spec/frontend/monitoring/components/charts/single_stat_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
import { singleStatGraphData } from '../../graph_data';
@@ -27,8 +27,12 @@ describe('Single Stat Chart component', () => {
describe('computed', () => {
describe('statValue', () => {
- it('should interpolate the value and unit props', () => {
- expect(findChart().props('value')).toBe('1.00MB');
+ it('should display the correct value', () => {
+ expect(findChart().props('value')).toBe('1.00');
+ });
+
+ it('should display the correct value unit', () => {
+ expect(findChart().props('unit')).toBe('MB');
});
it('should change the value representation to a percentile one', () => {
@@ -36,7 +40,8 @@ describe('Single Stat Chart component', () => {
graphData: singleStatGraphData({ max_value: 120 }, { value: 91 }),
});
- expect(findChart().props('value')).toContain('75.83%');
+ expect(findChart().props('value')).toBe('75.83');
+ expect(findChart().props('unit')).toBe('%');
});
it('should display NaN for non numeric maxValue values', () => {
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
index 4d4224a8b11..f47728313c6 100644
--- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -1,7 +1,7 @@
+import { GlStackedColumnChart, GlChartLegend } from '@gitlab/ui/dist/charts';
import { shallowMount, mount } from '@vue/test-utils';
-import timezoneMock from 'timezone-mock';
import { cloneDeep } from 'lodash';
-import { GlStackedColumnChart, GlChartLegend } from '@gitlab/ui/dist/charts';
+import timezoneMock from 'timezone-mock';
import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
import { stackedColumnGraphData } from '../../graph_data';
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index b7e1cb91987..afa63bcff29 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -1,17 +1,18 @@
-import { mount, shallowMount } from '@vue/test-utils';
-import { setTestTimeout } from 'helpers/timeout';
-import timezoneMock from 'timezone-mock';
import { GlLink } from '@gitlab/ui';
-import { TEST_HOST } from 'helpers/test_constants';
import {
GlAreaChart,
GlLineChart,
GlChartSeriesLabel,
GlChartLegend,
} from '@gitlab/ui/dist/charts';
+import { mount, shallowMount } from '@vue/test-utils';
+import timezoneMock from 'timezone-mock';
+import { TEST_HOST } from 'helpers/test_constants';
+import { setTestTimeout } from 'helpers/timeout';
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
-import { panelTypes, chartHeight } from '~/monitoring/constants';
import TimeSeries from '~/monitoring/components/charts/time_series.vue';
+import { panelTypes, chartHeight } from '~/monitoring/constants';
+import { timeSeriesGraphData } from '../../graph_data';
import {
deploymentData,
mockProjectDir,
@@ -19,8 +20,6 @@ import {
mockFixedTimeRange,
} from '../../mock_data';
-import { timeSeriesGraphData } from '../../graph_data';
-
jest.mock('lodash/throttle', () =>
// this throttle mock executes immediately
jest.fn((func) => {
diff --git a/spec/frontend/monitoring/components/create_dashboard_modal_spec.js b/spec/frontend/monitoring/components/create_dashboard_modal_spec.js
index d1028445638..8202d423ff3 100644
--- a/spec/frontend/monitoring/components/create_dashboard_modal_spec.js
+++ b/spec/frontend/monitoring/components/create_dashboard_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import CreateDashboardModal from '~/monitoring/components/create_dashboard_modal.vue';
describe('Create dashboard modal', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
index 43d5937a3a1..6e98ca28071 100644
--- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
@@ -1,14 +1,14 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem } from '@gitlab/ui';
-import { createStore } from '~/monitoring/stores';
-import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants';
-import { setupAllDashboards, setupStoreWithData } from '../store_utils';
+import { shallowMount } from '@vue/test-utils';
+import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import { redirectTo } from '~/lib/utils/url_utility';
-import Tracking from '~/tracking';
import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
-import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
-import { dashboardActionsMenuProps, dashboardGitResponse } from '../mock_data';
+import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants';
+import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
+import Tracking from '~/tracking';
+import { dashboardActionsMenuProps, dashboardGitResponse } from '../mock_data';
+import { setupAllDashboards, setupStoreWithData } from '../store_utils';
jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js
index 32fd9c45e8d..8be7d641953 100644
--- a/spec/frontend/monitoring/components/dashboard_header_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_header_spec.js
@@ -1,20 +1,20 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem, GlSearchBoxByType, GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { redirectTo } from '~/lib/utils/url_utility';
+import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
+import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
+import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
+import RefreshButton from '~/monitoring/components/refresh_button.vue';
import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
-import RefreshButton from '~/monitoring/components/refresh_button.vue';
-import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
-import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
-import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
-import { setupAllDashboards, setupStoreWithDashboard, setupStoreWithData } from '../store_utils';
import {
environmentData,
dashboardGitResponse,
selfMonitoringDashboardGitResponse,
dashboardHeaderProps,
} from '../mock_data';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { setupAllDashboards, setupStoreWithDashboard, setupStoreWithData } from '../store_utils';
const mockProjectPath = 'https://path/to/project';
diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
index 08c69701bd2..b794d0c571e 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
@@ -1,14 +1,13 @@
-import { shallowMount } from '@vue/test-utils';
import { GlCard, GlForm, GlFormTextarea, GlAlert } from '@gitlab/ui';
-import { createStore } from '~/monitoring/stores';
+import { shallowMount } from '@vue/test-utils';
import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
+import DashboardPanelBuilder from '~/monitoring/components/dashboard_panel_builder.vue';
+import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
+import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import { metricsDashboardResponse } from '../fixture_data';
import { mockTimeRange } from '../mock_data';
-import DashboardPanelBuilder from '~/monitoring/components/dashboard_panel_builder.vue';
-import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
-
const mockPanel = metricsDashboardResponse.dashboard.panel_groups[0].panels[0];
describe('dashboard invalid url parameters', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index f64e05d3a2c..a72dbbd0f41 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -1,13 +1,32 @@
-import Vuex from 'vuex';
+import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
import { setTestTimeout } from 'helpers/timeout';
-import { GlDropdownItem } from '@gitlab/ui';
-import invalidUrl from '~/lib/utils/invalid_url';
import axios from '~/lib/utils/axios_utils';
+import invalidUrl from '~/lib/utils/invalid_url';
import AlertWidget from '~/monitoring/components/alert_widget.vue';
+import MonitorAnomalyChart from '~/monitoring/components/charts/anomaly.vue';
+import MonitorBarChart from '~/monitoring/components/charts/bar.vue';
+import MonitorColumnChart from '~/monitoring/components/charts/column.vue';
+import MonitorEmptyChart from '~/monitoring/components/charts/empty_chart.vue';
+import MonitorHeatmapChart from '~/monitoring/components/charts/heatmap.vue';
+import MonitorSingleStatChart from '~/monitoring/components/charts/single_stat.vue';
+import MonitorStackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
+import MonitorTimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
+import { panelTypes } from '~/monitoring/constants';
+
+import { createStore, monitoringDashboard } from '~/monitoring/stores';
+import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group';
+import { dashboardProps, graphData, graphDataEmpty } from '../fixture_data';
+import {
+ anomalyGraphData,
+ singleStatGraphData,
+ heatmapGraphData,
+ barGraphData,
+} from '../graph_data';
import {
mockAlert,
mockLogsHref,
@@ -16,27 +35,6 @@ import {
mockNamespacedData,
mockTimeRange,
} from '../mock_data';
-import { dashboardProps, graphData, graphDataEmpty } from '../fixture_data';
-import {
- anomalyGraphData,
- singleStatGraphData,
- heatmapGraphData,
- barGraphData,
-} from '../graph_data';
-
-import { panelTypes } from '~/monitoring/constants';
-
-import MonitorEmptyChart from '~/monitoring/components/charts/empty_chart.vue';
-import MonitorTimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
-import MonitorAnomalyChart from '~/monitoring/components/charts/anomaly.vue';
-import MonitorSingleStatChart from '~/monitoring/components/charts/single_stat.vue';
-import MonitorHeatmapChart from '~/monitoring/components/charts/heatmap.vue';
-import MonitorColumnChart from '~/monitoring/components/charts/column.vue';
-import MonitorBarChart from '~/monitoring/components/charts/bar.vue';
-import MonitorStackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
-
-import { createStore, monitoringDashboard } from '~/monitoring/stores';
-import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group';
const mocks = {
$toast: {
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index db35f1cdde3..5c7042d4cb5 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -1,22 +1,29 @@
import { shallowMount, mount } from '@vue/test-utils';
-import VueDraggable from 'vuedraggable';
import MockAdapter from 'axios-mock-adapter';
+import VueDraggable from 'vuedraggable';
import { TEST_HOST } from 'helpers/test_constants';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import { ESC_KEY } from '~/lib/utils/keys';
import { objectToQuery } from '~/lib/utils/url_utility';
-import axios from '~/lib/utils/axios_utils';
-import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
-import EmptyState from '~/monitoring/components/empty_state.vue';
-import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
+import EmptyState from '~/monitoring/components/empty_state.vue';
import GraphGroup from '~/monitoring/components/graph_group.vue';
+import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
import LinksSection from '~/monitoring/components/links_section.vue';
+import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import {
+ metricsDashboardViewModel,
+ metricsDashboardPanelCount,
+ dashboardProps,
+} from '../fixture_data';
+import { dashboardGitResponse, storeVariables } from '../mock_data';
+import {
setupAllDashboards,
setupStoreWithDashboard,
setMetricResult,
@@ -24,13 +31,6 @@ import {
setupStoreWithDataForPanelCount,
setupStoreWithLinks,
} from '../store_utils';
-import { dashboardGitResponse, storeVariables } from '../mock_data';
-import {
- metricsDashboardViewModel,
- metricsDashboardPanelCount,
- dashboardProps,
-} from '../fixture_data';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
diff --git a/spec/frontend/monitoring/components/dashboard_template_spec.js b/spec/frontend/monitoring/components/dashboard_template_spec.js
index 8941e57c4ce..4e220d724f4 100644
--- a/spec/frontend/monitoring/components/dashboard_template_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_template_spec.js
@@ -4,8 +4,8 @@ import axios from '~/lib/utils/axios_utils';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores';
-import { setupAllDashboards } from '../store_utils';
import { dashboardProps } from '../fixture_data';
+import { setupAllDashboards } from '../store_utils';
jest.mock('~/lib/utils/url_utility');
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index c4630bde32f..9830b6d047f 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -1,6 +1,7 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import {
queryToObject,
redirectTo,
@@ -8,14 +9,13 @@ import {
mergeUrlParams,
updateHistory,
} from '~/lib/utils/url_utility';
-import axios from '~/lib/utils/axios_utils';
-import { mockProjectDir } from '../mock_data';
-import { dashboardProps } from '../fixture_data';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores';
import { defaultTimeRange } from '~/vue_shared/constants';
+import { dashboardProps } from '../fixture_data';
+import { mockProjectDir } from '../mock_data';
jest.mock('~/flash');
jest.mock('~/lib/utils/url_utility');
diff --git a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
index 6ed190051ce..c9241834789 100644
--- a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
+++ b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
@@ -1,6 +1,6 @@
-import { nextTick } from 'vue';
-import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
index 4abb5b2e27b..9672f6a315a 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
@@ -1,5 +1,5 @@
-import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_form.vue';
import { dashboardGitResponse } from '../mock_data';
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
index 7e7065da179..1bc89e509b5 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
@@ -1,12 +1,12 @@
-import Vuex from 'vuex';
-import Vue from 'vue';
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon, GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
-import DuplicateDashboardModal from '~/monitoring/components/duplicate_dashboard_modal.vue';
import DuplicateDashboardForm from '~/monitoring/components/duplicate_dashboard_form.vue';
+import DuplicateDashboardModal from '~/monitoring/components/duplicate_dashboard_modal.vue';
import { dashboardGitResponse } from '../mock_data';
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
index cb06a1a6b64..79b223d96e4 100644
--- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -1,6 +1,6 @@
+import { GlButton, GlCard } from '@gitlab/ui';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlButton, GlCard } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import EmbedGroup from '~/monitoring/components/embeds/embed_group.vue';
import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
diff --git a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
index 74f265930b1..90647f50b14 100644
--- a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
+++ b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
@@ -1,7 +1,7 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { TEST_HOST } from 'helpers/test_constants';
import { setHTMLFixture } from 'helpers/fixtures';
+import { TEST_HOST } from 'helpers/test_constants';
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';
diff --git a/spec/frontend/monitoring/components/empty_state_spec.js b/spec/frontend/monitoring/components/empty_state_spec.js
index abb8b21e9f4..1ecb101574b 100644
--- a/spec/frontend/monitoring/components/empty_state_spec.js
+++ b/spec/frontend/monitoring/components/empty_state_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
-import { dashboardEmptyStates } from '~/monitoring/constants';
+import { shallowMount } from '@vue/test-utils';
import EmptyState from '~/monitoring/components/empty_state.vue';
+import { dashboardEmptyStates } from '~/monitoring/constants';
function createComponent(props) {
return shallowMount(EmptyState, {
diff --git a/spec/frontend/monitoring/components/graph_group_spec.js b/spec/frontend/monitoring/components/graph_group_spec.js
index c57461c2d09..625dd3f0b33 100644
--- a/spec/frontend/monitoring/components/graph_group_spec.js
+++ b/spec/frontend/monitoring/components/graph_group_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import GraphGroup from '~/monitoring/components/graph_group.vue';
describe('Graph group component', () => {
diff --git a/spec/frontend/monitoring/components/links_section_spec.js b/spec/frontend/monitoring/components/links_section_spec.js
index 2daad77d513..8fc287c50e4 100644
--- a/spec/frontend/monitoring/components/links_section_spec.js
+++ b/spec/frontend/monitoring/components/links_section_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
-import { createStore } from '~/monitoring/stores';
+import { shallowMount } from '@vue/test-utils';
import LinksSection from '~/monitoring/components/links_section.vue';
+import { createStore } from '~/monitoring/stores';
describe('Links Section component', () => {
let store;
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index a03d29309d4..248cf32d54b 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -1,8 +1,8 @@
+import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Visibility from 'visibilityjs';
-import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui';
-import { createStore } from '~/monitoring/stores';
import RefreshButton from '~/monitoring/components/refresh_button.vue';
+import { createStore } from '~/monitoring/stores';
describe('RefreshButton', () => {
let wrapper;
diff --git a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
index f5db17ce367..f5ee32e78e6 100644
--- a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DropdownField from '~/monitoring/components/variables/dropdown_field.vue';
describe('Custom variable component', () => {
diff --git a/spec/frontend/monitoring/components/variables/text_field_spec.js b/spec/frontend/monitoring/components/variables/text_field_spec.js
index 99c6facac38..28e02dff4bf 100644
--- a/spec/frontend/monitoring/components/variables/text_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/text_field_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import TextField from '~/monitoring/components/variables/text_field.vue';
describe('Text variable component', () => {
diff --git a/spec/frontend/monitoring/components/variables_section_spec.js b/spec/frontend/monitoring/components/variables_section_spec.js
index 3097906ee68..6157de0dafe 100644
--- a/spec/frontend/monitoring/components/variables_section_spec.js
+++ b/spec/frontend/monitoring/components/variables_section_spec.js
@@ -1,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import VariablesSection from '~/monitoring/components/variables_section.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';
-import { updateHistory, mergeUrlParams } from '~/lib/utils/url_utility';
+import VariablesSection from '~/monitoring/components/variables_section.vue';
import { createStore } from '~/monitoring/stores';
import { convertVariablesForURL } from '~/monitoring/utils';
import { storeVariables } from '../mock_data';
diff --git a/spec/frontend/monitoring/csv_export_spec.js b/spec/frontend/monitoring/csv_export_spec.js
index eb2a6e40243..42d19c21a7b 100644
--- a/spec/frontend/monitoring/csv_export_spec.js
+++ b/spec/frontend/monitoring/csv_export_spec.js
@@ -1,5 +1,5 @@
-import { timeSeriesGraphData } from './graph_data';
import { graphDataToCsv } from '~/monitoring/csv_export';
+import { timeSeriesGraphData } from './graph_data';
describe('monitoring export_csv', () => {
describe('graphDataToCsv', () => {
diff --git a/spec/frontend/monitoring/fixture_data.js b/spec/frontend/monitoring/fixture_data.js
index 0f3dbaac493..d20a111c701 100644
--- a/spec/frontend/monitoring/fixture_data.js
+++ b/spec/frontend/monitoring/fixture_data.js
@@ -1,7 +1,7 @@
-import { stateAndPropsFromDataset } from '~/monitoring/utils';
-import { mapToDashboardViewModel } from '~/monitoring/stores/utils';
-import { metricStates } from '~/monitoring/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { metricStates } from '~/monitoring/constants';
+import { mapToDashboardViewModel } from '~/monitoring/stores/utils';
+import { stateAndPropsFromDataset } from '~/monitoring/utils';
import { metricsResult } from './mock_data';
diff --git a/spec/frontend/monitoring/graph_data.js b/spec/frontend/monitoring/graph_data.js
index 0b23ee41927..981955efebb 100644
--- a/spec/frontend/monitoring/graph_data.js
+++ b/spec/frontend/monitoring/graph_data.js
@@ -1,5 +1,5 @@
-import { mapPanelToViewModel, normalizeQueryResponseData } from '~/monitoring/stores/utils';
import { panelTypes, metricStates } from '~/monitoring/constants';
+import { mapPanelToViewModel, normalizeQueryResponseData } from '~/monitoring/stores/utils';
const initTime = 1435781450; // "Wed, 01 Jul 2015 20:10:50 GMT"
const intervalSeconds = 120;
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index ca06c96c7d6..29a7c86491d 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -1,6 +1,6 @@
// The path below needs to be relative because we import the mock-data to karma
-import { TEST_HOST } from '../__helpers__/test_constants';
import invalidUrl from '~/lib/utils/invalid_url';
+import { TEST_HOST } from '../__helpers__/test_constants';
// This import path needs to be relative for now because this mock data is used in
// Karma specs too, where the helpers/test_constants alias can not be resolved
diff --git a/spec/frontend/monitoring/pages/dashboard_page_spec.js b/spec/frontend/monitoring/pages/dashboard_page_spec.js
index 675165e9e56..dbe9cc21ad5 100644
--- a/spec/frontend/monitoring/pages/dashboard_page_spec.js
+++ b/spec/frontend/monitoring/pages/dashboard_page_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import { createStore } from '~/monitoring/stores';
-import DashboardPage from '~/monitoring/pages/dashboard_page.vue';
import Dashboard from '~/monitoring/components/dashboard.vue';
+import DashboardPage from '~/monitoring/pages/dashboard_page.vue';
+import { createStore } from '~/monitoring/stores';
import { dashboardProps } from '../fixture_data';
describe('monitoring/pages/dashboard_page', () => {
diff --git a/spec/frontend/monitoring/pages/panel_new_page_spec.js b/spec/frontend/monitoring/pages/panel_new_page_spec.js
index 83365b754d9..c89cbc52bcb 100644
--- a/spec/frontend/monitoring/pages/panel_new_page_spec.js
+++ b/spec/frontend/monitoring/pages/panel_new_page_spec.js
@@ -1,10 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
-import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants';
-import { createStore } from '~/monitoring/stores';
+import { shallowMount } from '@vue/test-utils';
import DashboardPanelBuilder from '~/monitoring/components/dashboard_panel_builder.vue';
-
import PanelNewPage from '~/monitoring/pages/panel_new_page.vue';
+import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants';
+import { createStore } from '~/monitoring/stores';
const dashboard = 'dashboard.yml';
diff --git a/spec/frontend/monitoring/requests/index_spec.js b/spec/frontend/monitoring/requests/index_spec.js
index 078de5f15d1..b30b1e60575 100644
--- a/spec/frontend/monitoring/requests/index_spec.js
+++ b/spec/frontend/monitoring/requests/index_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
import { backoffMockImplementation } from 'helpers/backoff_helper';
import axios from '~/lib/utils/axios_utils';
-import statusCodes from '~/lib/utils/http_status';
import * as commonUtils from '~/lib/utils/common_utils';
-import { metricsDashboardResponse } from '../fixture_data';
+import statusCodes from '~/lib/utils/http_status';
import { getDashboard, getPrometheusQueryData } from '~/monitoring/requests';
+import { metricsDashboardResponse } from '../fixture_data';
describe('monitoring metrics_requests', () => {
let mock;
diff --git a/spec/frontend/monitoring/router_spec.js b/spec/frontend/monitoring/router_spec.js
index c30c4c56a6c..b027d60f61e 100644
--- a/spec/frontend/monitoring/router_spec.js
+++ b/spec/frontend/monitoring/router_spec.js
@@ -1,10 +1,10 @@
import { mount, createLocalVue } from '@vue/test-utils';
import VueRouter from 'vue-router';
+import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardPage from '~/monitoring/pages/dashboard_page.vue';
import PanelNewPage from '~/monitoring/pages/panel_new_page.vue';
-import Dashboard from '~/monitoring/components/dashboard.vue';
-import { createStore } from '~/monitoring/stores';
import createRouter from '~/monitoring/router';
+import { createStore } from '~/monitoring/stores';
import { dashboardProps } from './fixture_data';
import { dashboardHeaderProps } from './mock_data';
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index 319441b5ba2..b7f741c449f 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -1,17 +1,16 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { backoffMockImplementation } from 'helpers/backoff_helper';
-import Tracking from '~/tracking';
+import testAction from 'helpers/vuex_action_helper';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import statusCodes from '~/lib/utils/http_status';
import * as commonUtils from '~/lib/utils/common_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { defaultTimeRange } from '~/vue_shared/constants';
-import * as getters from '~/monitoring/stores/getters';
+import statusCodes from '~/lib/utils/http_status';
import { ENVIRONMENT_AVAILABLE_STATE } from '~/monitoring/constants';
+import getAnnotations from '~/monitoring/queries/getAnnotations.query.graphql';
+import getDashboardValidationWarnings from '~/monitoring/queries/getDashboardValidationWarnings.query.graphql';
+import getEnvironments from '~/monitoring/queries/getEnvironments.query.graphql';
import { createStore } from '~/monitoring/stores';
-import * as types from '~/monitoring/stores/mutation_types';
import {
setGettingStartedEmptyState,
setInitialState,
@@ -33,15 +32,21 @@ import {
fetchVariableMetricLabelValues,
fetchPanelPreview,
} from '~/monitoring/stores/actions';
+import * as getters from '~/monitoring/stores/getters';
+import * as types from '~/monitoring/stores/mutation_types';
+import storeState from '~/monitoring/stores/state';
import {
gqClient,
parseEnvironmentsResponse,
parseAnnotationsResponse,
} from '~/monitoring/stores/utils';
-import getEnvironments from '~/monitoring/queries/getEnvironments.query.graphql';
-import getAnnotations from '~/monitoring/queries/getAnnotations.query.graphql';
-import getDashboardValidationWarnings from '~/monitoring/queries/getDashboardValidationWarnings.query.graphql';
-import storeState from '~/monitoring/stores/state';
+import Tracking from '~/tracking';
+import { defaultTimeRange } from '~/vue_shared/constants';
+import {
+ metricsDashboardResponse,
+ metricsDashboardViewModel,
+ metricsDashboardPanelCount,
+} from '../fixture_data';
import {
deploymentData,
environmentData,
@@ -49,11 +54,6 @@ import {
dashboardGitResponse,
mockDashboardsErrorResponse,
} from '../mock_data';
-import {
- metricsDashboardResponse,
- metricsDashboardViewModel,
- metricsDashboardPanelCount,
-} from '../fixture_data';
jest.mock('~/flash');
diff --git a/spec/frontend/monitoring/store/embed_group/mutations_spec.js b/spec/frontend/monitoring/store/embed_group/mutations_spec.js
index a1d04e23e41..2f8d7687aad 100644
--- a/spec/frontend/monitoring/store/embed_group/mutations_spec.js
+++ b/spec/frontend/monitoring/store/embed_group/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/monitoring/stores/embed_group/state';
-import mutations from '~/monitoring/stores/embed_group/mutations';
import * as types from '~/monitoring/stores/embed_group/mutation_types';
+import mutations from '~/monitoring/stores/embed_group/mutations';
+import state from '~/monitoring/stores/embed_group/state';
import { mockNamespace } from '../../mock_data';
describe('Embed group mutations', () => {
diff --git a/spec/frontend/monitoring/store/getters_spec.js b/spec/frontend/monitoring/store/getters_spec.js
index 771ec0ea549..c7f3bdbf1f8 100644
--- a/spec/frontend/monitoring/store/getters_spec.js
+++ b/spec/frontend/monitoring/store/getters_spec.js
@@ -1,8 +1,9 @@
import _ from 'lodash';
+import { metricStates } from '~/monitoring/constants';
import * as getters from '~/monitoring/stores/getters';
-import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
-import { metricStates } from '~/monitoring/constants';
+import mutations from '~/monitoring/stores/mutations';
+import { metricsDashboardPayload } from '../fixture_data';
import {
customDashboardBasePath,
environmentData,
@@ -11,7 +12,6 @@ import {
storeVariables,
mockLinks,
} from '../mock_data';
-import { metricsDashboardPayload } from '../fixture_data';
describe('Monitoring store Getters', () => {
let state;
diff --git a/spec/frontend/monitoring/store/mutations_spec.js b/spec/frontend/monitoring/store/mutations_spec.js
index 571828eb67c..ae1a4e16b30 100644
--- a/spec/frontend/monitoring/store/mutations_spec.js
+++ b/spec/frontend/monitoring/store/mutations_spec.js
@@ -1,12 +1,12 @@
import httpStatusCodes from '~/lib/utils/http_status';
-import mutations from '~/monitoring/stores/mutations';
+import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
import * as types from '~/monitoring/stores/mutation_types';
+import mutations from '~/monitoring/stores/mutations';
import state from '~/monitoring/stores/state';
-import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
-import { deploymentData, dashboardGitResponse, storeTextVariables } from '../mock_data';
-import { prometheusMatrixMultiResult } from '../graph_data';
import { metricsDashboardPayload } from '../fixture_data';
+import { prometheusMatrixMultiResult } from '../graph_data';
+import { deploymentData, dashboardGitResponse, storeTextVariables } from '../mock_data';
describe('Monitoring mutations', () => {
let stateCopy;
diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js
index 58bb87cb332..697bdb9185f 100644
--- a/spec/frontend/monitoring/store/utils_spec.js
+++ b/spec/frontend/monitoring/store/utils_spec.js
@@ -1,4 +1,6 @@
import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
+import * as urlUtils from '~/lib/utils/url_utility';
+import { NOT_IN_DB_PREFIX } from '~/monitoring/constants';
import {
uniqMetricsId,
parseEnvironmentsResponse,
@@ -10,9 +12,7 @@ import {
addDashboardMetaDataToLink,
normalizeCustomDashboardPath,
} from '~/monitoring/stores/utils';
-import * as urlUtils from '~/lib/utils/url_utility';
import { annotationsData } from '../mock_data';
-import { NOT_IN_DB_PREFIX } from '~/monitoring/constants';
const projectPath = 'gitlab-org/gitlab-test';
diff --git a/spec/frontend/monitoring/store/variable_mapping_spec.js b/spec/frontend/monitoring/store/variable_mapping_spec.js
index de124b0313c..58e7175c04c 100644
--- a/spec/frontend/monitoring/store/variable_mapping_spec.js
+++ b/spec/frontend/monitoring/store/variable_mapping_spec.js
@@ -1,3 +1,4 @@
+import * as urlUtils from '~/lib/utils/url_utility';
import {
parseTemplatingVariables,
mergeURLVariables,
@@ -9,7 +10,6 @@ import {
storeCustomVariables,
storeMetricLabelValuesVariables,
} from '../mock_data';
-import * as urlUtils from '~/lib/utils/url_utility';
describe('Monitoring variable mapping', () => {
describe('parseTemplatingVariables', () => {
diff --git a/spec/frontend/monitoring/store_utils.js b/spec/frontend/monitoring/store_utils.js
index 911ccc78f7b..96219661b9b 100644
--- a/spec/frontend/monitoring/store_utils.js
+++ b/spec/frontend/monitoring/store_utils.js
@@ -1,6 +1,6 @@
import * as types from '~/monitoring/stores/mutation_types';
-import { metricsResult, environmentData, dashboardGitResponse } from './mock_data';
import { metricsDashboardPayload } from './fixture_data';
+import { metricsResult, environmentData, dashboardGitResponse } from './mock_data';
export const setMetricResult = ({ store, result, group = 0, panel = 0, metric = 0 }) => {
const { dashboard } = store.state.monitoringDashboard;
diff --git a/spec/frontend/monitoring/utils_spec.js b/spec/frontend/monitoring/utils_spec.js
index cd49e4c7968..25ae4dcd702 100644
--- a/spec/frontend/monitoring/utils_spec.js
+++ b/spec/frontend/monitoring/utils_spec.js
@@ -1,9 +1,9 @@
import { TEST_HOST } from 'helpers/test_constants';
-import * as monitoringUtils from '~/monitoring/utils';
import * as urlUtils from '~/lib/utils/url_utility';
-import { mockProjectDir, barMockData } from './mock_data';
-import { singleStatGraphData, anomalyGraphData } from './graph_data';
+import * as monitoringUtils from '~/monitoring/utils';
import { metricsDashboardViewModel, graphData } from './fixture_data';
+import { singleStatGraphData, anomalyGraphData } from './graph_data';
+import { mockProjectDir, barMockData } from './mock_data';
const mockPath = `${TEST_HOST}${mockProjectDir}/-/environments/29/metrics`;
diff --git a/spec/frontend/namespace_select_spec.js b/spec/frontend/namespace_select_spec.js
index d6f3eb75cd9..a38508dd601 100644
--- a/spec/frontend/namespace_select_spec.js
+++ b/spec/frontend/namespace_select_spec.js
@@ -1,5 +1,5 @@
-import NamespaceSelect from '~/namespace_select';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import NamespaceSelect from '~/namespace_select';
jest.mock('~/deprecated_jquery_dropdown');
diff --git a/spec/frontend/notebook/cells/markdown_spec.js b/spec/frontend/notebook/cells/markdown_spec.js
index ad33858da22..4d6addaf47c 100644
--- a/spec/frontend/notebook/cells/markdown_spec.js
+++ b/spec/frontend/notebook/cells/markdown_spec.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import katex from 'katex';
+import Vue from 'vue';
import MarkdownComponent from '~/notebook/cells/markdown.vue';
const Component = Vue.extend(MarkdownComponent);
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index 002c4f206cb..2f58f75ab70 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -1,15 +1,15 @@
-import { nextTick } from 'vue';
import { mount, shallowMount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
import Autosize from 'autosize';
+import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import { deprecatedCreateFlash as flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import createStore from '~/notes/stores';
import CommentForm from '~/notes/components/comment_form.vue';
import * as constants from '~/notes/constants';
import eventHub from '~/notes/event_hub';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import createStore from '~/notes/stores';
import { loggedOutnoteableData, notesDataMock, userDataMock, noteableDataMock } from '../mock_data';
jest.mock('autosize');
@@ -22,11 +22,25 @@ describe('issue_comment_form component', () => {
let wrapper;
let axiosMock;
- const findCloseReopenButton = () => wrapper.find('[data-testid="close-reopen-button"]');
+ const findCloseReopenButton = () => wrapper.findByTestId('close-reopen-button');
+ const findCommentButton = () => wrapper.findByTestId('comment-button');
+ const findTextArea = () => wrapper.findByTestId('comment-field');
+ const findConfidentialNoteCheckbox = () => wrapper.findByTestId('confidential-note-checkbox');
- const findCommentButton = () => wrapper.find('[data-testid="comment-button"]');
+ const createNotableDataMock = (data = {}) => {
+ return {
+ ...noteableDataMock,
+ ...data,
+ };
+ };
- const findTextArea = () => wrapper.find('[data-testid="comment-field"]');
+ const notableDataMockCanUpdateIssuable = createNotableDataMock({
+ current_user: { can_update: true, can_create_note: true },
+ });
+
+ const notableDataMockCannotUpdateIssuable = createNotableDataMock({
+ current_user: { can_update: false, can_create_note: true },
+ });
const mountComponent = ({
initialData = {},
@@ -34,23 +48,29 @@ describe('issue_comment_form component', () => {
noteableData = noteableDataMock,
notesData = notesDataMock,
userData = userDataMock,
+ features = {},
mountFunction = shallowMount,
} = {}) => {
store.dispatch('setNoteableData', noteableData);
store.dispatch('setNotesData', notesData);
store.dispatch('setUserData', userData);
- wrapper = mountFunction(CommentForm, {
- propsData: {
- noteableType,
- },
- data() {
- return {
- ...initialData,
- };
- },
- store,
- });
+ wrapper = extendedWrapper(
+ mountFunction(CommentForm, {
+ propsData: {
+ noteableType,
+ },
+ data() {
+ return {
+ ...initialData,
+ };
+ },
+ store,
+ provide: {
+ glFeatures: features,
+ },
+ }),
+ );
};
beforeEach(() => {
@@ -64,14 +84,6 @@ describe('issue_comment_form component', () => {
});
describe('user is logged in', () => {
- describe('avatar', () => {
- it('should render user avatar with link', () => {
- mountComponent({ mountFunction: mount });
-
- expect(wrapper.find(UserAvatarLink).attributes('href')).toBe(userDataMock.path);
- });
- });
-
describe('handleSave', () => {
it('should request to save note when note is entered', () => {
mountComponent({ mountFunction: mount, initialData: { note: 'hello world' } });
@@ -368,6 +380,83 @@ describe('issue_comment_form component', () => {
});
});
});
+
+ describe('confidential notes checkbox', () => {
+ describe('when confidentialNotes feature flag is `false`', () => {
+ const features = { confidentialNotes: false };
+
+ it('should not render checkbox', () => {
+ mountComponent({
+ mountFunction: mount,
+ initialData: { note: 'confidential note' },
+ noteableData: { ...notableDataMockCanUpdateIssuable },
+ features,
+ });
+
+ const checkbox = findConfidentialNoteCheckbox();
+ expect(checkbox.exists()).toBe(false);
+ });
+ });
+
+ describe('when confidentialNotes feature flag is `true`', () => {
+ const features = { confidentialNotes: true };
+
+ it('should render checkbox as unchecked by default', () => {
+ mountComponent({
+ mountFunction: mount,
+ initialData: { note: 'confidential note' },
+ noteableData: { ...notableDataMockCanUpdateIssuable },
+ features,
+ });
+
+ const checkbox = findConfidentialNoteCheckbox();
+ expect(checkbox.exists()).toBe(true);
+ expect(checkbox.element.checked).toBe(false);
+ });
+
+ describe.each`
+ shouldCheckboxBeChecked
+ ${true}
+ ${false}
+ `('when checkbox value is `$shouldCheckboxBeChecked`', ({ shouldCheckboxBeChecked }) => {
+ it(`sets \`confidential\` to \`${shouldCheckboxBeChecked}\``, async () => {
+ mountComponent({
+ mountFunction: mount,
+ initialData: { note: 'confidential note' },
+ noteableData: { ...notableDataMockCanUpdateIssuable },
+ features,
+ });
+
+ jest.spyOn(wrapper.vm, 'saveNote').mockResolvedValue({});
+
+ const checkbox = findConfidentialNoteCheckbox();
+
+ // check checkbox
+ checkbox.element.checked = shouldCheckboxBeChecked;
+ checkbox.trigger('change');
+ await wrapper.vm.$nextTick();
+
+ // submit comment
+ wrapper.findByTestId('comment-button').trigger('click');
+
+ const [providedData] = wrapper.vm.saveNote.mock.calls[0];
+ expect(providedData.data.note.confidential).toBe(shouldCheckboxBeChecked);
+ });
+ });
+
+ describe('when user cannot update issuable', () => {
+ it('should not render checkbox', () => {
+ mountComponent({
+ mountFunction: mount,
+ noteableData: { ...notableDataMockCannotUpdateIssuable },
+ features,
+ });
+
+ expect(findConfidentialNoteCheckbox().exists()).toBe(false);
+ });
+ });
+ });
+ });
});
describe('user is not logged in', () => {
diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js
index 3940439a32b..fdc89522901 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -1,10 +1,10 @@
import { mount } from '@vue/test-utils';
-import createStore from '~/notes/stores';
import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue';
+import createStore from '~/notes/stores';
-import { discussionMock } from '../mock_data';
import mockDiffFile from '../../diffs/mock_data/diff_discussions';
+import { discussionMock } from '../mock_data';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
diff --git a/spec/frontend/notes/components/diff_with_note_spec.js b/spec/frontend/notes/components/diff_with_note_spec.js
index 6480af015db..e997fc4da50 100644
--- a/spec/frontend/notes/components/diff_with_note_spec.js
+++ b/spec/frontend/notes/components/diff_with_note_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import DiffWithNote from '~/notes/components/diff_with_note.vue';
import { createStore } from '~/mr_notes/stores';
+import DiffWithNote from '~/notes/components/diff_with_note.vue';
const discussionFixture = 'merge_requests/diff_discussion.json';
const imageDiscussionFixture = 'merge_requests/image_diff_discussion.json';
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index 48e569720e9..03e5842bb0f 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -1,10 +1,10 @@
import { shallowMount, mount } from '@vue/test-utils';
-import { discussionMock } from '../mock_data';
import DiscussionActions from '~/notes/components/discussion_actions.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import createStore from '~/notes/stores';
+import { discussionMock } from '../mock_data';
// NOTE: clone mock_data so that it is not accidentally mutated
const createDiscussionMock = (props = {}) =>
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index ebf7d52f38b..9db0f823d84 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
-import notesModule from '~/notes/stores/modules';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
-import { noteableDataMock, discussionMock, notesDataMock, userDataMock } from '../mock_data';
+import notesModule from '~/notes/stores/modules';
import * as types from '~/notes/stores/mutation_types';
+import { noteableDataMock, discussionMock, notesDataMock, userDataMock } from '../mock_data';
describe('DiscussionCounter component', () => {
let store;
diff --git a/spec/frontend/notes/components/discussion_filter_note_spec.js b/spec/frontend/notes/components/discussion_filter_note_spec.js
index 9ae3f08df77..ad9a2e898eb 100644
--- a/spec/frontend/notes/components/discussion_filter_note_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_note_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DiscussionFilterNote from '~/notes/components/discussion_filter_note.vue';
import eventHub from '~/notes/event_hub';
diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js
index aeba8e8056c..6f62b8ba528 100644
--- a/spec/frontend/notes/components/discussion_filter_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_spec.js
@@ -1,13 +1,13 @@
-import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
import createEventHub from '~/helpers/event_hub_factory';
import axios from '~/lib/utils/axios_utils';
-import notesModule from '~/notes/stores/modules';
import DiscussionFilter from '~/notes/components/discussion_filter.vue';
import { DISCUSSION_FILTERS_DEFAULT_VALUE, DISCUSSION_FILTER_TYPES } from '~/notes/constants';
+import notesModule from '~/notes/stores/modules';
import { discussionFiltersMock, discussionMock } from '../mock_data';
diff --git a/spec/frontend/notes/components/discussion_navigator_spec.js b/spec/frontend/notes/components/discussion_navigator_spec.js
index 122814b8e3f..4d55eee2ffa 100644
--- a/spec/frontend/notes/components/discussion_navigator_spec.js
+++ b/spec/frontend/notes/components/discussion_navigator_spec.js
@@ -1,7 +1,7 @@
/* global Mousetrap */
import 'mousetrap';
-import Vue from 'vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import DiscussionNavigator from '~/notes/components/discussion_navigator.vue';
import eventHub from '~/notes/event_hub';
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index e803dcb7b4a..cd24b9afbdf 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -1,13 +1,13 @@
-import { shallowMount } from '@vue/test-utils';
import { getByRole } from '@testing-library/dom';
+import { shallowMount } from '@vue/test-utils';
import '~/behaviors/markdown/render_gfm';
-import { SYSTEM_NOTE } from '~/notes/constants';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableNote from '~/notes/components/noteable_note.vue';
+import { SYSTEM_NOTE } from '~/notes/constants';
+import createStore from '~/notes/stores';
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
import SystemNote from '~/vue_shared/components/notes/system_note.vue';
-import createStore from '~/notes/stores';
import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
const LINE_RANGE = {};
@@ -23,7 +23,7 @@ describe('DiscussionNotes', () => {
let wrapper;
const getList = () => getByRole(wrapper.element, 'list');
- const createComponent = (props, features = {}) => {
+ const createComponent = (props) => {
wrapper = shallowMount(DiscussionNotes, {
store,
propsData: {
@@ -38,9 +38,6 @@ describe('DiscussionNotes', () => {
slots: {
'avatar-badge': '<span class="avatar-badge-slot-content" />',
},
- provide: {
- glFeatures: { multilineComments: true, ...features },
- },
});
};
@@ -177,16 +174,14 @@ describe('DiscussionNotes', () => {
});
describe.each`
- desc | props | features | event | expectedCalls
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]}
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]}
- ${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]}
- ${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]}
- `('$desc and features $features', ({ props, event, features, expectedCalls }) => {
+ desc | props | event | expectedCalls
+ ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
+ ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
+ ${'without `discussion.position`'} | ${{}} | ${'mouseenter'} | ${[]}
+ ${'without `discussion.position`'} | ${{}} | ${'mouseleave'} | ${[]}
+ `('$desc', ({ props, event, expectedCalls }) => {
beforeEach(() => {
- createComponent(props, features);
+ createComponent(props);
jest.spyOn(store, 'dispatch');
});
diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js
index 5105e1013d3..64e061830b9 100644
--- a/spec/frontend/notes/components/discussion_resolve_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import resolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
const buttonTitle = 'Resolve discussion';
diff --git a/spec/frontend/notes/components/multiline_comment_form_spec.js b/spec/frontend/notes/components/multiline_comment_form_spec.js
index 081fd6e10ef..b6d603c6358 100644
--- a/spec/frontend/notes/components/multiline_comment_form_spec.js
+++ b/spec/frontend/notes/components/multiline_comment_form_spec.js
@@ -1,7 +1,7 @@
+import { GlFormSelect } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { mount } from '@vue/test-utils';
-import { GlFormSelect } from '@gitlab/ui';
import MultilineCommentForm from '~/notes/components/multiline_comment_form.vue';
import notesModule from '~/notes/stores/modules';
diff --git a/spec/frontend/notes/components/note_actions/reply_button_spec.js b/spec/frontend/notes/components/note_actions/reply_button_spec.js
index 720ab10b270..4993ded365d 100644
--- a/spec/frontend/notes/components/note_actions/reply_button_spec.js
+++ b/spec/frontend/notes/components/note_actions/reply_button_spec.js
@@ -1,29 +1,22 @@
-import Vuex from 'vuex';
-import { createLocalVue, mount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ReplyButton from '~/notes/components/note_actions/reply_button.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
describe('ReplyButton', () => {
let wrapper;
beforeEach(() => {
- wrapper = mount(localVue.extend(ReplyButton), {
- localVue,
- });
+ wrapper = shallowMount(ReplyButton);
});
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
});
it('emits startReplying on click', () => {
- const button = wrapper.find({ ref: 'button' });
-
- button.trigger('click');
+ wrapper.find(GlButton).vm.$emit('click');
- expect(wrapper.emitted().startReplying).toBeTruthy();
- expect(wrapper.emitted().startReplying.length).toBe(1);
+ expect(wrapper.emitted('startReplying')).toEqual([[]]);
});
});
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index 3cfc1445cb8..17717ebd09a 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -1,11 +1,12 @@
-import Vue from 'vue';
import { mount, createLocalVue, createWrapper } from '@vue/test-utils';
-import { TEST_HOST } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
-import createStore from '~/notes/stores';
+import Vue from 'vue';
+import { TEST_HOST } from 'spec/test_constants';
+import axios from '~/lib/utils/axios_utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import noteActions from '~/notes/components/note_actions.vue';
+import createStore from '~/notes/stores';
import { userDataMock } from '../mock_data';
-import axios from '~/lib/utils/axios_utils';
describe('noteActions', () => {
let wrapper;
@@ -135,7 +136,7 @@ describe('noteActions', () => {
.then(() => {
const emitted = Object.keys(rootWrapper.emitted());
- expect(emitted).toEqual(['bv::hide::tooltip']);
+ expect(emitted).toEqual([BV_HIDE_TOOLTIP]);
done();
})
.catch(done.fail);
diff --git a/spec/frontend/notes/components/note_awards_list_spec.js b/spec/frontend/notes/components/note_awards_list_spec.js
index 13a817902e6..9fc89ffa473 100644
--- a/spec/frontend/notes/components/note_awards_list_spec.js
+++ b/spec/frontend/notes/components/note_awards_list_spec.js
@@ -1,9 +1,9 @@
-import Vue from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
-import createStore from '~/notes/stores';
import awardsNote from '~/notes/components/note_awards_list.vue';
+import createStore from '~/notes/stores';
import { noteableDataMock, notesDataMock } from '../mock_data';
describe('note_awards_list component', () => {
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index 3c11c266f90..4922de987fa 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -1,6 +1,14 @@
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
-import createStore from '~/notes/stores';
+import Vuex from 'vuex';
+
+import { suggestionCommitMessage } from '~/diffs/store/getters';
import noteBody from '~/notes/components/note_body.vue';
+import createStore from '~/notes/stores';
+import notes from '~/notes/stores/modules/index';
+
+import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
+
import { noteableDataMock, notesDataMock, note } from '../mock_data';
describe('issue_note_body component', () => {
@@ -54,4 +62,50 @@ describe('issue_note_body component', () => {
expect(vm.autosave.key).toEqual(autosaveKey);
});
});
+
+ describe('commitMessage', () => {
+ let wrapper;
+
+ Vue.use(Vuex);
+
+ beforeEach(() => {
+ const notesStore = notes();
+
+ notesStore.state.notes = {};
+
+ store = new Vuex.Store({
+ modules: {
+ notes: notesStore,
+ diffs: {
+ namespaced: true,
+ state: {
+ defaultSuggestionCommitMessage:
+ '%{branch_name}%{project_path}%{project_name}%{username}%{user_full_name}%{file_paths}%{suggestions_count}%{files_count}',
+ branchName: 'branch',
+ projectPath: '/path',
+ projectName: 'name',
+ username: 'user',
+ userFullName: 'user userton',
+ },
+ getters: { suggestionCommitMessage },
+ },
+ },
+ });
+
+ wrapper = shallowMount(noteBody, {
+ store,
+ propsData: {
+ note: { ...note, suggestions: [12345] },
+ canEdit: true,
+ file: { file_path: 'abc' },
+ },
+ });
+ });
+
+ it('passes the correct default placeholder commit message for a suggestion to the suggestions component', () => {
+ const commitMessage = wrapper.find(Suggestions).attributes('defaultcommitmessage');
+
+ expect(commitMessage).toBe('branch/pathnameuseruser usertonabc11');
+ });
+ });
});
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index e64a75bede9..7615f3b70f1 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -1,13 +1,12 @@
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import createStore from '~/notes/stores';
-import NoteForm from '~/notes/components/note_form.vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
+import { getDraft, updateDraft } from '~/lib/utils/autosave';
+import NoteForm from '~/notes/components/note_form.vue';
+import createStore from '~/notes/stores';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { noteableDataMock, notesDataMock, discussionMock } from '../mock_data';
-import { getDraft, updateDraft } from '~/lib/utils/autosave';
-
jest.mock('~/lib/utils/autosave');
describe('issue_note_form component', () => {
@@ -25,6 +24,8 @@ describe('issue_note_form component', () => {
});
};
+ const findCancelButton = () => wrapper.find('[data-testid="cancel"]');
+
beforeEach(() => {
getDraft.mockImplementation((key) => {
if (key === dummyAutosaveKey) {
@@ -160,8 +161,8 @@ describe('issue_note_form component', () => {
});
await nextTick();
- const cancelButton = wrapper.find('[data-testid="cancel"]');
- cancelButton.trigger('click');
+ const cancelButton = findCancelButton();
+ cancelButton.vm.$emit('click');
await nextTick();
expect(wrapper.emitted().cancelForm).toHaveLength(1);
@@ -177,7 +178,7 @@ describe('issue_note_form component', () => {
const textarea = wrapper.find('textarea');
textarea.setValue('Foo');
const saveButton = wrapper.find('.js-vue-issue-save');
- saveButton.trigger('click');
+ saveButton.vm.$emit('click');
expect(wrapper.vm.isSubmitting).toBe(true);
});
@@ -272,7 +273,7 @@ describe('issue_note_form component', () => {
await nextTick();
const cancelButton = wrapper.find('[data-testid="cancelBatchCommentsEnabled"]');
- cancelButton.trigger('click');
+ cancelButton.vm.$emit('click');
expect(wrapper.vm.cancelHandler).toHaveBeenCalledWith(true);
});
@@ -302,16 +303,16 @@ describe('issue_note_form component', () => {
expect(wrapper.find('.js-resolve-checkbox').exists()).toBe(false);
});
- it('hides actions for commits', () => {
+ it('hides actions for commits', async () => {
wrapper.setProps({ discussion: { for_commit: true } });
- return nextTick(() => {
- expect(wrapper.find('.note-form-actions').text()).not.toContain('Start a review');
- });
+ await nextTick();
+
+ expect(wrapper.find('.note-form-actions').text()).not.toContain('Start a review');
});
describe('on enter', () => {
- it('should start review or add to review when cmd+enter is pressed', () => {
+ it('should start review or add to review when cmd+enter is pressed', async () => {
const textarea = wrapper.find('textarea');
jest.spyOn(wrapper.vm, 'handleAddToReview');
@@ -319,9 +320,8 @@ describe('issue_note_form component', () => {
textarea.setValue('Foo');
textarea.trigger('keydown.enter', { metaKey: true });
- return nextTick(() => {
- expect(wrapper.vm.handleAddToReview).toHaveBeenCalled();
- });
+ await nextTick();
+ expect(wrapper.vm.handleAddToReview).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js
index 132e3d8aa7e..774d5aaa7d3 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -1,9 +1,10 @@
+import { GlSprintf } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
-import { GlSprintf } from '@gitlab/ui';
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);
@@ -36,9 +37,7 @@ describe('NoteHeader component', () => {
username: 'root',
show_status: true,
status_tooltip_html: statusHtml,
- status: {
- availability: '',
- },
+ availability: '',
};
const createComponent = (props) => {
@@ -48,7 +47,7 @@ describe('NoteHeader component', () => {
actions,
}),
propsData: { ...props },
- stubs: { GlSprintf },
+ stubs: { GlSprintf, UserNameWithStatus },
});
};
@@ -110,7 +109,7 @@ describe('NoteHeader component', () => {
});
it('renders busy status if author availability is set', () => {
- createComponent({ author: { ...author, status: { availability: AVAILABILITY_STATUS.BUSY } } });
+ createComponent({ author: { ...author, availability: AVAILABILITY_STATUS.BUSY } });
expect(wrapper.find('.js-user-link').text()).toContain('(Busy)');
});
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index b87c6cd7f2b..87538279c3d 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -1,13 +1,13 @@
-import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
-import mockDiffFile from 'jest/diffs/mock_data/diff_file';
+import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
-import createStore from '~/notes/stores';
-import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import NoteForm from '~/notes/components/note_form.vue';
+import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
+import createStore from '~/notes/stores';
import '~/behaviors/markdown/render_gfm';
import {
noteableDataMock,
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index 6f06665f412..fe78e086403 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -1,22 +1,13 @@
-import { escape } from 'lodash';
import { mount, createLocalVue } from '@vue/test-utils';
-import createStore from '~/notes/stores';
-import issueNote from '~/notes/components/noteable_note.vue';
-import NoteHeader from '~/notes/components/note_header.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import { escape } from 'lodash';
import NoteActions from '~/notes/components/note_actions.vue';
import NoteBody from '~/notes/components/note_body.vue';
+import NoteHeader from '~/notes/components/note_header.vue';
+import issueNote from '~/notes/components/noteable_note.vue';
+import createStore from '~/notes/stores';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { noteableDataMock, notesDataMock, note } from '../mock_data';
-jest.mock('~/vue_shared/mixins/gl_feature_flags_mixin', () => () => ({
- inject: {
- glFeatures: {
- from: 'glFeatures',
- default: () => ({ multilineComments: true }),
- },
- },
-}));
-
describe('issue_note', () => {
let store;
let wrapper;
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index e495a4738e0..efee72dea96 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -1,18 +1,18 @@
-import $ from 'jquery';
+import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import Vue from 'vue';
-import { mount, shallowMount } from '@vue/test-utils';
import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
-import NotesApp from '~/notes/components/notes_app.vue';
+import * as urlUtility from '~/lib/utils/url_utility';
import CommentForm from '~/notes/components/comment_form.vue';
-import createStore from '~/notes/stores';
+import NotesApp from '~/notes/components/notes_app.vue';
import * as constants from '~/notes/constants';
+import createStore from '~/notes/stores';
import '~/behaviors/markdown/render_gfm';
// TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-foss/issues/62491)
-import * as mockData from '../mock_data';
-import * as urlUtility from '~/lib/utils/url_utility';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
+import * as mockData from '../mock_data';
jest.mock('~/user_popovers', () => jest.fn());
diff --git a/spec/frontend/notes/components/sort_discussion_spec.js b/spec/frontend/notes/components/sort_discussion_spec.js
index 739e247735d..60f03a0f5b5 100644
--- a/spec/frontend/notes/components/sort_discussion_spec.js
+++ b/spec/frontend/notes/components/sort_discussion_spec.js
@@ -1,10 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import SortDiscussion from '~/notes/components/sort_discussion.vue';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-import createStore from '~/notes/stores';
import { ASC, DESC } from '~/notes/constants';
+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);
diff --git a/spec/frontend/notes/components/timeline_toggle_spec.js b/spec/frontend/notes/components/timeline_toggle_spec.js
index b8df6fc7996..73fb2079e31 100644
--- a/spec/frontend/notes/components/timeline_toggle_spec.js
+++ b/spec/frontend/notes/components/timeline_toggle_spec.js
@@ -1,12 +1,12 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import TimelineToggle, {
timelineEnabledTooltip,
timelineDisabledTooltip,
} from '~/notes/components/timeline_toggle.vue';
-import createStore from '~/notes/stores';
import { ASC, DESC } from '~/notes/constants';
+import createStore from '~/notes/stores';
import { trackToggleTimelineView } from '~/notes/utils';
import Tracking from '~/tracking';
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 9c9a648d213..6a6e47ffcc5 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { setHTMLFixture } from 'helpers/fixtures';
+import createEventHub from '~/helpers/event_hub_factory';
import * as utils from '~/lib/utils/common_utils';
-import discussionNavigation from '~/notes/mixins/discussion_navigation';
import eventHub from '~/notes/event_hub';
-import createEventHub from '~/helpers/event_hub_factory';
+import discussionNavigation from '~/notes/mixins/discussion_navigation';
import notesModule from '~/notes/stores/modules';
const discussion = (id, index) => ({
diff --git a/spec/frontend/notes/old_notes_spec.js b/spec/frontend/notes/old_notes_spec.js
index 00821980e8a..432b660c4b3 100644
--- a/spec/frontend/notes/old_notes_spec.js
+++ b/spec/frontend/notes/old_notes_spec.js
@@ -1,13 +1,13 @@
/* eslint-disable import/no-commonjs, no-new */
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { createSpyObj } from 'helpers/jest_helpers';
-import { setTestTimeoutOnce } from 'helpers/timeout';
import { TEST_HOST } from 'helpers/test_constants';
-import * as urlUtility from '~/lib/utils/url_utility';
+import { setTestTimeoutOnce } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
+import * as urlUtility from '~/lib/utils/url_utility';
// These must be imported synchronously because they pull dependencies
// from the DOM.
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index f0e6a0a68dd..1852108b39f 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -1,13 +1,18 @@
-import { TEST_HOST } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
import Api from '~/api';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import * as actions from '~/notes/stores/actions';
-import mutations from '~/notes/stores/mutations';
-import * as mutationTypes from '~/notes/stores/mutation_types';
+import axios from '~/lib/utils/axios_utils';
import * as notesConstants from '~/notes/constants';
import createStore from '~/notes/stores';
+import * as actions from '~/notes/stores/actions';
+import * as mutationTypes from '~/notes/stores/mutation_types';
+import mutations from '~/notes/stores/mutations';
+import * as utils from '~/notes/stores/utils';
+import updateIssueConfidentialMutation from '~/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql';
+import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql';
+import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql';
import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub';
import { resetStore } from '../helpers';
import {
@@ -18,11 +23,6 @@ import {
individualNote,
batchSuggestionsInfoMock,
} from '../mock_data';
-import axios from '~/lib/utils/axios_utils';
-import * as utils from '~/notes/stores/utils';
-import updateIssueConfidentialMutation from '~/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql';
-import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql';
-import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql';
const TEST_ERROR_MESSAGE = 'Test error message';
jest.mock('~/flash');
@@ -291,9 +291,45 @@ describe('Actions Notes Store', () => {
[
{ type: 'updateOrCreateNotes', payload: discussionMock.notes },
{ type: 'startTaskList' },
+ { type: 'updateResolvableDiscussionsCounts' },
],
));
});
+
+ describe('paginated notes feature flag enabled', () => {
+ const lastFetchedAt = '12358';
+
+ beforeEach(() => {
+ window.gon = { features: { paginatedNotes: true } };
+
+ axiosMock.onGet(notesDataMock.notesPath).replyOnce(200, {
+ notes: discussionMock.notes,
+ more: false,
+ last_fetched_at: lastFetchedAt,
+ });
+ });
+
+ afterEach(() => {
+ window.gon = null;
+ });
+
+ it('should dispatch setFetchingState, setNotesFetchedState, setLoadingState, updateOrCreateNotes, startTaskList and commit SET_LAST_FETCHED_AT', () => {
+ return testAction(
+ actions.fetchData,
+ null,
+ { notesData: notesDataMock, isFetching: true },
+ [{ type: 'SET_LAST_FETCHED_AT', payload: lastFetchedAt }],
+ [
+ { type: 'setFetchingState', payload: false },
+ { type: 'setNotesFetchedState', payload: true },
+ { type: 'setLoadingState', payload: false },
+ { type: 'updateOrCreateNotes', payload: discussionMock.notes },
+ { type: 'startTaskList' },
+ { type: 'updateResolvableDiscussionsCounts' },
+ ],
+ );
+ });
+ });
});
describe('poll', () => {
@@ -1276,6 +1312,7 @@ describe('Actions Notes Store', () => {
return actions
.updateConfidentialityOnIssuable({ commit: commitSpy, state, getters }, actionArgs)
.then(() => {
+ expect(Flash).not.toHaveBeenCalled();
expect(commitSpy).toHaveBeenCalledWith(
mutationTypes.SET_ISSUE_CONFIDENTIAL,
confidential,
@@ -1283,6 +1320,22 @@ describe('Actions Notes Store', () => {
});
});
});
+
+ describe('on user recoverable error', () => {
+ it('sends the error to Flash', () => {
+ const error = 'error';
+
+ jest
+ .spyOn(utils.gqClient, 'mutate')
+ .mockResolvedValue({ data: { issueSetConfidential: { errors: [error] } } });
+
+ return actions
+ .updateConfidentialityOnIssuable({ commit: () => {}, state, getters }, actionArgs)
+ .then(() => {
+ expect(Flash).toHaveBeenCalledWith(error, 'alert');
+ });
+ });
+ });
});
describe.each`
@@ -1355,4 +1408,17 @@ describe('Actions Notes Store', () => {
);
});
});
+
+ describe('setFetchingState', () => {
+ it('commits SET_NOTES_FETCHING_STATE', (done) => {
+ testAction(
+ actions.setFetchingState,
+ true,
+ null,
+ [{ type: mutationTypes.SET_NOTES_FETCHING_STATE, payload: true }],
+ [],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js
index fd04d08b6a5..4ebfc679310 100644
--- a/spec/frontend/notes/stores/getters_spec.js
+++ b/spec/frontend/notes/stores/getters_spec.js
@@ -1,5 +1,5 @@
-import * as getters from '~/notes/stores/getters';
import { DESC } from '~/notes/constants';
+import * as getters from '~/notes/stores/getters';
import {
notesDataMock,
userDataMock,
diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js
index 66fc74525ad..99e24f724f4 100644
--- a/spec/frontend/notes/stores/mutation_spec.js
+++ b/spec/frontend/notes/stores/mutation_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import mutations from '~/notes/stores/mutations';
import { DISCUSSION_NOTE, ASC, DESC } from '~/notes/constants';
+import mutations from '~/notes/stores/mutations';
import {
note,
discussionMock,
@@ -400,6 +400,19 @@ describe('Notes Store mutations', () => {
expect(state.discussions[0].notes[0].note).toEqual('Foo');
});
+ it('does not update existing note if it matches', () => {
+ const state = {
+ discussions: [{ ...individualNote, individual_note: false }],
+ };
+ jest.spyOn(state.discussions[0].notes, 'splice');
+
+ const updated = individualNote.notes[0];
+
+ mutations.UPDATE_NOTE(state, updated);
+
+ expect(state.discussions[0].notes.splice).not.toHaveBeenCalled();
+ });
+
it('transforms an individual note to discussion', () => {
const state = {
discussions: [individualNote],
diff --git a/spec/frontend/notifications/components/custom_notifications_modal_spec.js b/spec/frontend/notifications/components/custom_notifications_modal_spec.js
new file mode 100644
index 00000000000..3e87f3107bd
--- /dev/null
+++ b/spec/frontend/notifications/components/custom_notifications_modal_spec.js
@@ -0,0 +1,267 @@
+import { GlSprintf, GlModal, GlFormGroup, GlFormCheckbox, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import httpStatus from '~/lib/utils/http_status';
+import CustomNotificationsModal from '~/notifications/components/custom_notifications_modal.vue';
+import { i18n } from '~/notifications/constants';
+
+const mockNotificationSettingsResponses = {
+ default: {
+ level: 'custom',
+ events: {
+ new_release: true,
+ new_note: false,
+ },
+ },
+ updated: {
+ level: 'custom',
+ events: {
+ new_release: true,
+ new_note: true,
+ },
+ },
+};
+
+const mockToastShow = jest.fn();
+
+describe('CustomNotificationsModal', () => {
+ let wrapper;
+ let mockAxios;
+
+ function createComponent(options = {}) {
+ const { injectedProperties = {}, props = {} } = options;
+ return extendedWrapper(
+ shallowMount(CustomNotificationsModal, {
+ props: {
+ ...props,
+ },
+ provide: {
+ ...injectedProperties,
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ stubs: {
+ GlModal,
+ GlFormGroup,
+ GlFormCheckbox,
+ },
+ }),
+ );
+ }
+
+ const findModalBodyDescription = () => wrapper.find(GlSprintf);
+ const findAllCheckboxes = () => wrapper.findAll(GlFormCheckbox);
+ const findCheckboxAt = (index) => findAllCheckboxes().at(index);
+
+ beforeEach(() => {
+ gon.api_version = 'v4';
+ mockAxios = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ mockAxios.restore();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('displays the body title and the body message', () => {
+ expect(wrapper.findByTestId('modalBodyTitle').text()).toBe(
+ i18n.customNotificationsModal.bodyTitle,
+ );
+ expect(findModalBodyDescription().attributes('message')).toContain(
+ i18n.customNotificationsModal.bodyMessage,
+ );
+ });
+
+ describe('checkbox items', () => {
+ beforeEach(async () => {
+ wrapper = createComponent();
+
+ wrapper.setData({
+ events: [
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: true },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it.each`
+ index | eventId | eventName | enabled | loading
+ ${0} | ${'new_release'} | ${'New release'} | ${true} | ${false}
+ ${1} | ${'new_note'} | ${'New note'} | ${false} | ${true}
+ `(
+ 'renders a checkbox for "$eventName" with checked=$enabled',
+ async ({ index, eventName, enabled, loading }) => {
+ const checkbox = findCheckboxAt(index);
+ expect(checkbox.text()).toContain(eventName);
+ expect(checkbox.vm.$attrs.checked).toBe(enabled);
+ expect(checkbox.find(GlLoadingIcon).exists()).toBe(loading);
+ },
+ );
+ });
+ });
+
+ describe('API calls', () => {
+ describe('load notification settings', () => {
+ beforeEach(() => {
+ jest.spyOn(axios, 'get');
+ });
+
+ it.each`
+ projectId | groupId | endpointUrl | notificationType | condition
+ ${1} | ${null} | ${'/api/v4/projects/1/notification_settings'} | ${'project'} | ${'a projectId is given'}
+ ${null} | ${1} | ${'/api/v4/groups/1/notification_settings'} | ${'group'} | ${'a groupId is given'}
+ ${null} | ${null} | ${'/api/v4/notification_settings'} | ${'global'} | ${'neither projectId nor groupId are given'}
+ `(
+ 'requests $notificationType notification settings when $condition',
+ async ({ projectId, groupId, endpointUrl }) => {
+ const injectedProperties = {
+ projectId,
+ groupId,
+ };
+
+ mockAxios
+ .onGet(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.default);
+
+ wrapper = createComponent({ injectedProperties });
+
+ wrapper.find(GlModal).vm.$emit('show');
+
+ await waitForPromises();
+
+ expect(axios.get).toHaveBeenCalledWith(endpointUrl);
+ },
+ );
+
+ it('updates the loading state and the events property', async () => {
+ const endpointUrl = '/api/v4/notification_settings';
+
+ mockAxios
+ .onGet(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.default);
+
+ wrapper = createComponent();
+
+ wrapper.find(GlModal).vm.$emit('show');
+ expect(wrapper.vm.isLoading).toBe(true);
+
+ await waitForPromises();
+
+ expect(axios.get).toHaveBeenCalledWith(endpointUrl);
+ expect(wrapper.vm.isLoading).toBe(false);
+ expect(wrapper.vm.events).toEqual([
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: false },
+ ]);
+ });
+
+ it('shows a toast message when the request fails', async () => {
+ mockAxios.onGet('/api/v4/notification_settings').reply(httpStatus.NOT_FOUND, {});
+ wrapper = createComponent();
+
+ wrapper.find(GlModal).vm.$emit('show');
+
+ await waitForPromises();
+
+ expect(
+ mockToastShow,
+ ).toHaveBeenCalledWith(
+ 'An error occured while loading the notification settings. Please try again.',
+ { type: 'error' },
+ );
+ });
+ });
+
+ describe('update notification settings', () => {
+ beforeEach(() => {
+ jest.spyOn(axios, 'put');
+ });
+
+ it.each`
+ projectId | groupId | endpointUrl | notificationType | condition
+ ${1} | ${null} | ${'/api/v4/projects/1/notification_settings'} | ${'project'} | ${'a projectId is given'}
+ ${null} | ${1} | ${'/api/v4/groups/1/notification_settings'} | ${'group'} | ${'a groupId is given'}
+ ${null} | ${null} | ${'/api/v4/notification_settings'} | ${'global'} | ${'neither projectId nor groupId are given'}
+ `(
+ 'updates the $notificationType notification settings when $condition and the user clicks the checkbox ',
+ async ({ projectId, groupId, endpointUrl }) => {
+ mockAxios
+ .onGet(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.default);
+
+ mockAxios
+ .onPut(endpointUrl)
+ .reply(httpStatus.OK, mockNotificationSettingsResponses.updated);
+
+ const injectedProperties = {
+ projectId,
+ groupId,
+ };
+
+ wrapper = createComponent({ injectedProperties });
+
+ wrapper.setData({
+ events: [
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: false },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ findCheckboxAt(1).vm.$emit('change', true);
+
+ await waitForPromises();
+
+ expect(axios.put).toHaveBeenCalledWith(endpointUrl, {
+ new_note: true,
+ });
+
+ expect(wrapper.vm.events).toEqual([
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: true, name: 'New note', loading: false },
+ ]);
+ },
+ );
+
+ it('shows a toast message when the request fails', async () => {
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.NOT_FOUND, {});
+ wrapper = createComponent();
+
+ wrapper.setData({
+ events: [
+ { id: 'new_release', enabled: true, name: 'New release', loading: false },
+ { id: 'new_note', enabled: false, name: 'New note', loading: false },
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ findCheckboxAt(1).vm.$emit('change', true);
+
+ await waitForPromises();
+
+ expect(
+ mockToastShow,
+ ).toHaveBeenCalledWith(
+ 'An error occured while updating the notification settings. Please try again.',
+ { type: 'error' },
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/notifications/components/notifications_dropdown_spec.js b/spec/frontend/notifications/components/notifications_dropdown_spec.js
new file mode 100644
index 00000000000..0673fb51a91
--- /dev/null
+++ b/spec/frontend/notifications/components/notifications_dropdown_spec.js
@@ -0,0 +1,274 @@
+import { GlButtonGroup, GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import waitForPromises from 'helpers/wait_for_promises';
+import httpStatus from '~/lib/utils/http_status';
+import CustomNotificationsModal from '~/notifications/components/custom_notifications_modal.vue';
+import NotificationsDropdown from '~/notifications/components/notifications_dropdown.vue';
+import NotificationsDropdownItem from '~/notifications/components/notifications_dropdown_item.vue';
+
+const mockDropdownItems = ['global', 'watch', 'participating', 'mention', 'disabled'];
+const mockToastShow = jest.fn();
+
+describe('NotificationsDropdown', () => {
+ let wrapper;
+ let mockAxios;
+ let glModalDirective;
+
+ function createComponent(injectedProperties = {}) {
+ glModalDirective = jest.fn();
+
+ return shallowMount(NotificationsDropdown, {
+ stubs: {
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ NotificationsDropdownItem,
+ CustomNotificationsModal,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ glModal: {
+ bind(_, { value }) {
+ glModalDirective(value);
+ },
+ },
+ },
+ provide: {
+ dropdownItems: mockDropdownItems,
+ initialNotificationLevel: 'global',
+ ...injectedProperties,
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
+ });
+ }
+
+ const findButtonGroup = () => wrapper.find(GlButtonGroup);
+ const findButton = () => wrapper.find(GlButton);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
+ const findAllNotificationsDropdownItems = () => wrapper.findAll(NotificationsDropdownItem);
+ const findDropdownItemAt = (index) =>
+ findAllNotificationsDropdownItems().at(index).find(GlDropdownItem);
+
+ const clickDropdownItemAt = async (index) => {
+ const dropdownItem = findDropdownItemAt(index);
+ dropdownItem.vm.$emit('click');
+
+ await waitForPromises();
+ };
+
+ beforeEach(() => {
+ gon.api_version = 'v4';
+ mockAxios = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ mockAxios.restore();
+ });
+
+ describe('template', () => {
+ describe('when notification level is "custom"', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialNotificationLevel: 'custom',
+ });
+ });
+
+ it('renders a button group', () => {
+ expect(findButtonGroup().exists()).toBe(true);
+ });
+
+ it('shows the button text when showLabel is true', () => {
+ wrapper = createComponent({
+ initialNotificationLevel: 'custom',
+ showLabel: true,
+ });
+
+ expect(findButton().text()).toBe('Custom');
+ });
+
+ it("doesn't show the button text when showLabel is false", () => {
+ wrapper = createComponent({
+ initialNotificationLevel: 'custom',
+ showLabel: false,
+ });
+
+ expect(findButton().text()).toBe('');
+ });
+
+ it('opens the modal when the user clicks the button', async () => {
+ jest.spyOn(axios, 'put');
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.OK, {});
+
+ wrapper = createComponent({
+ initialNotificationLevel: 'custom',
+ });
+
+ findButton().vm.$emit('click');
+
+ expect(glModalDirective).toHaveBeenCalled();
+ });
+ });
+
+ describe('when notification level is not "custom"', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialNotificationLevel: 'global',
+ });
+ });
+
+ it('does not render a button group', () => {
+ expect(findButtonGroup().exists()).toBe(false);
+ });
+
+ it('shows the button text when showLabel is true', () => {
+ wrapper = createComponent({
+ showLabel: true,
+ });
+
+ expect(findDropdown().props('text')).toBe('Global');
+ });
+
+ it("doesn't show the button text when showLabel is false", () => {
+ wrapper = createComponent({
+ showLabel: false,
+ });
+
+ expect(findDropdown().props('text')).toBe(null);
+ });
+ });
+
+ describe('button tooltip', () => {
+ const tooltipTitlePrefix = 'Notification setting';
+ it.each`
+ level | title
+ ${'global'} | ${'Global'}
+ ${'watch'} | ${'Watch'}
+ ${'participating'} | ${'Participate'}
+ ${'mention'} | ${'On mention'}
+ ${'disabled'} | ${'Disabled'}
+ ${'custom'} | ${'Custom'}
+ `(`renders "${tooltipTitlePrefix} - $title" for "$level" level`, ({ level, title }) => {
+ wrapper = createComponent({
+ initialNotificationLevel: level,
+ });
+
+ const tooltipElement = findByTestId('notificationButton');
+ const tooltip = getBinding(tooltipElement.element, 'gl-tooltip');
+
+ expect(tooltip.value.title).toBe(`${tooltipTitlePrefix} - ${title}`);
+ });
+ });
+
+ describe('button icon', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ initialNotificationLevel: 'disabled',
+ });
+ });
+
+ it('renders the "notifications-off" icon when notification level is "disabled"', () => {
+ expect(findDropdown().props('icon')).toBe('notifications-off');
+ });
+
+ it('renders the "notifications" icon when notification level is not "disabled"', () => {
+ wrapper = createComponent();
+
+ expect(findDropdown().props('icon')).toBe('notifications');
+ });
+ });
+
+ describe('dropdown items', () => {
+ it.each`
+ dropdownIndex | level | title | description
+ ${0} | ${'global'} | ${'Global'} | ${'Use your global notification setting'}
+ ${1} | ${'watch'} | ${'Watch'} | ${'You will receive notifications for any activity'}
+ ${2} | ${'participating'} | ${'Participate'} | ${'You will only receive notifications for threads you have participated in'}
+ ${3} | ${'mention'} | ${'On mention'} | ${'You will receive notifications only for comments in which you were @mentioned'}
+ ${4} | ${'disabled'} | ${'Disabled'} | ${'You will not get any notifications via email'}
+ ${5} | ${'custom'} | ${'Custom'} | ${'You will only receive notifications for the events you choose'}
+ `('displays "$title" and "$description"', ({ dropdownIndex, title, description }) => {
+ wrapper = createComponent();
+
+ expect(findAllNotificationsDropdownItems().at(dropdownIndex).props('title')).toBe(title);
+ expect(findAllNotificationsDropdownItems().at(dropdownIndex).props('description')).toBe(
+ description,
+ );
+ });
+ });
+ });
+
+ describe('when selecting an item', () => {
+ beforeEach(() => {
+ jest.spyOn(axios, 'put');
+ });
+
+ it.each`
+ projectId | groupId | endpointUrl | endpointType | condition
+ ${1} | ${null} | ${'/api/v4/projects/1/notification_settings'} | ${'project notifications'} | ${'a projectId is given'}
+ ${null} | ${1} | ${'/api/v4/groups/1/notification_settings'} | ${'group notifications'} | ${'a groupId is given'}
+ ${null} | ${null} | ${'/api/v4/notification_settings'} | ${'global notifications'} | ${'when neither projectId nor groupId are given'}
+ `(
+ 'calls the $endpointType endpoint when $condition',
+ async ({ projectId, groupId, endpointUrl }) => {
+ wrapper = createComponent({
+ projectId,
+ groupId,
+ });
+
+ await clickDropdownItemAt(1);
+
+ expect(axios.put).toHaveBeenCalledWith(endpointUrl, {
+ level: 'watch',
+ });
+ },
+ );
+
+ it('updates the selectedNotificationLevel and marks the item with a checkmark', async () => {
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.OK, {});
+ wrapper = createComponent();
+
+ const dropdownItem = findDropdownItemAt(1);
+
+ await clickDropdownItemAt(1);
+
+ expect(wrapper.vm.selectedNotificationLevel).toBe('watch');
+ expect(dropdownItem.props('isChecked')).toBe(true);
+ });
+
+ it("won't update the selectedNotificationLevel and shows a toast message when the request fails and ", async () => {
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.NOT_FOUND, {});
+ wrapper = createComponent();
+
+ await clickDropdownItemAt(1);
+
+ expect(wrapper.vm.selectedNotificationLevel).toBe('global');
+ expect(
+ mockToastShow,
+ ).toHaveBeenCalledWith(
+ 'An error occured while updating the notification settings. Please try again.',
+ { type: 'error' },
+ );
+ });
+
+ it('opens the modal when the user clicks on the "Custom" dropdown item', async () => {
+ mockAxios.onPut('/api/v4/notification_settings').reply(httpStatus.OK, {});
+ wrapper = createComponent();
+
+ const mockModalShow = jest.spyOn(wrapper.vm.$refs.customNotificationsModal, 'open');
+
+ await clickDropdownItemAt(5);
+
+ expect(mockModalShow).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/onboarding_issues/index_spec.js b/spec/frontend/onboarding_issues/index_spec.js
deleted file mode 100644
index d476ba1cf5a..00000000000
--- a/spec/frontend/onboarding_issues/index_spec.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import $ from 'jquery';
-import setWindowLocation from 'helpers/set_window_location_helper';
-import { showLearnGitLabIssuesPopover } from '~/onboarding_issues';
-import { getCookie, setCookie, removeCookie } from '~/lib/utils/common_utils';
-import Tracking from '~/tracking';
-
-describe('Onboarding Issues Popovers', () => {
- const COOKIE_NAME = 'onboarding_issues_settings';
- const getCookieValue = () => JSON.parse(getCookie(COOKIE_NAME));
-
- beforeEach(() => {
- jest.spyOn($.fn, 'popover');
- });
-
- afterEach(() => {
- $.fn.popover.mockRestore();
- document.getElementsByTagName('html')[0].innerHTML = '';
- removeCookie(COOKIE_NAME);
- });
-
- const setupShowLearnGitLabIssuesPopoverTest = ({
- currentPath = 'group/learn-gitlab',
- isIssuesBoardsLinkShown = true,
- isCookieSet = true,
- cookieValue = true,
- } = {}) => {
- setWindowLocation(`http://example.com/${currentPath}`);
-
- if (isIssuesBoardsLinkShown) {
- const elem = document.createElement('a');
- elem.setAttribute('data-qa-selector', 'issue_boards_link');
- document.body.appendChild(elem);
- }
-
- if (isCookieSet) {
- setCookie(COOKIE_NAME, { previous: true, 'issues#index': cookieValue });
- }
-
- showLearnGitLabIssuesPopover();
- };
-
- describe('showLearnGitLabIssuesPopover', () => {
- describe('when on another project', () => {
- beforeEach(() => {
- setupShowLearnGitLabIssuesPopoverTest({
- currentPath: 'group/another-project',
- });
- });
-
- it('does not show a popover', () => {
- expect($.fn.popover).not.toHaveBeenCalled();
- });
- });
-
- describe('when the issues boards link is not shown', () => {
- beforeEach(() => {
- setupShowLearnGitLabIssuesPopoverTest({
- isIssuesBoardsLinkShown: false,
- });
- });
-
- it('does not show a popover', () => {
- expect($.fn.popover).not.toHaveBeenCalled();
- });
- });
-
- describe('when the cookie is not set', () => {
- beforeEach(() => {
- setupShowLearnGitLabIssuesPopoverTest({
- isCookieSet: false,
- });
- });
-
- it('does not show a popover', () => {
- expect($.fn.popover).not.toHaveBeenCalled();
- });
- });
-
- describe('when the cookie value is false', () => {
- beforeEach(() => {
- setupShowLearnGitLabIssuesPopoverTest({
- cookieValue: false,
- });
- });
-
- it('does not show a popover', () => {
- expect($.fn.popover).not.toHaveBeenCalled();
- });
- });
-
- describe('with all the right conditions', () => {
- beforeEach(() => {
- setupShowLearnGitLabIssuesPopoverTest();
- });
-
- it('shows a popover', () => {
- expect($.fn.popover).toHaveBeenCalled();
- });
-
- it('does not change the cookie value', () => {
- expect(getCookieValue()['issues#index']).toBe(true);
- });
-
- it('disables the previous popover', () => {
- expect(getCookieValue().previous).toBe(false);
- });
-
- describe('when clicking the issues boards link', () => {
- beforeEach(() => {
- document.querySelector('a[data-qa-selector="issue_boards_link"]').click();
- });
-
- it('deletes the cookie', () => {
- expect(getCookie(COOKIE_NAME)).toBe(undefined);
- });
- });
-
- describe('when dismissing the popover', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- document.querySelector('.learn-gitlab.popover .close').click();
- });
-
- it('deletes the cookie', () => {
- expect(getCookie(COOKIE_NAME)).toBe(undefined);
- });
-
- it('sends a tracking event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(
- 'Growth::Conversion::Experiment::OnboardingIssues',
- 'dismiss_popover',
- );
- });
- });
- });
- });
-});
diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js
index 3216eece391..272e9b71f67 100644
--- a/spec/frontend/operation_settings/components/metrics_settings_spec.js
+++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js
@@ -1,15 +1,15 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import { timezones } from '~/monitoring/format_date';
+import DashboardTimezone from '~/operation_settings/components/form_group/dashboard_timezone.vue';
+import ExternalDashboard from '~/operation_settings/components/form_group/external_dashboard.vue';
import MetricsSettings from '~/operation_settings/components/metrics_settings.vue';
-import ExternalDashboard from '~/operation_settings/components/form_group/external_dashboard.vue';
-import DashboardTimezone from '~/operation_settings/components/form_group/dashboard_timezone.vue';
-import { timezones } from '~/monitoring/format_date';
import store from '~/operation_settings/store';
-import axios from '~/lib/utils/axios_utils';
-import { refreshCurrentPage } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/flash');
diff --git a/spec/frontend/operation_settings/store/mutations_spec.js b/spec/frontend/operation_settings/store/mutations_spec.js
index 88eb66095ad..db6b54b503d 100644
--- a/spec/frontend/operation_settings/store/mutations_spec.js
+++ b/spec/frontend/operation_settings/store/mutations_spec.js
@@ -1,6 +1,6 @@
+import { timezones } from '~/monitoring/format_date';
import mutations from '~/operation_settings/store/mutations';
import createState from '~/operation_settings/store/state';
-import { timezones } from '~/monitoring/format_date';
describe('operation settings mutations', () => {
let localState;
diff --git a/spec/frontend/packages/details/components/additional_metadata_spec.js b/spec/frontend/packages/details/components/additional_metadata_spec.js
index 8466a630ecb..b339aa84348 100644
--- a/spec/frontend/packages/details/components/additional_metadata_spec.js
+++ b/spec/frontend/packages/details/components/additional_metadata_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
-import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+import { shallowMount } from '@vue/test-utils';
import component from '~/packages/details/components/additional_metadata.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
import { mavenPackage, conanPackage, nugetPackage, npmPackage } from '../../mock_data';
diff --git a/spec/frontend/packages/details/components/app_spec.js b/spec/frontend/packages/details/components/app_spec.js
index 97df117df0b..11dad7ba34d 100644
--- a/spec/frontend/packages/details/components/app_spec.js
+++ b/spec/frontend/packages/details/components/app_spec.js
@@ -1,22 +1,21 @@
-import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlEmptyState, GlModal } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
-import Tracking from '~/tracking';
-import * as getters from '~/packages/details/store/getters';
-import PackagesApp from '~/packages/details/components/app.vue';
-import PackageTitle from '~/packages/details/components/package_title.vue';
-
-import * as SharedUtils from '~/packages/shared/utils';
-import { TrackingActions } from '~/packages/shared/constants';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-import PackageListRow from '~/packages/shared/components/package_list_row.vue';
-import DependencyRow from '~/packages/details/components/dependency_row.vue';
-import PackageHistory from '~/packages/details/components/package_history.vue';
import AdditionalMetadata from '~/packages/details/components/additional_metadata.vue';
+import PackagesApp from '~/packages/details/components/app.vue';
+import DependencyRow from '~/packages/details/components/dependency_row.vue';
import InstallationCommands from '~/packages/details/components/installation_commands.vue';
import PackageFiles from '~/packages/details/components/package_files.vue';
+import PackageHistory from '~/packages/details/components/package_history.vue';
+import PackageTitle from '~/packages/details/components/package_title.vue';
+import * as getters from '~/packages/details/store/getters';
+import PackageListRow from '~/packages/shared/components/package_list_row.vue';
+import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
+import { TrackingActions } from '~/packages/shared/constants';
+import * as SharedUtils from '~/packages/shared/utils';
+import Tracking from '~/tracking';
import {
composerPackage,
diff --git a/spec/frontend/packages/details/components/composer_installation_spec.js b/spec/frontend/packages/details/components/composer_installation_spec.js
index b44609e8ae7..a1d30d0ed22 100644
--- a/spec/frontend/packages/details/components/composer_installation_spec.js
+++ b/spec/frontend/packages/details/components/composer_installation_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf, GlLink } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { registryUrl as composerHelpPath } from 'jest/packages/details/mock_data';
import { composerPackage as packageEntity } from 'jest/packages/mock_data';
import ComposerInstallation from '~/packages/details/components/composer_installation.vue';
diff --git a/spec/frontend/packages/details/components/conan_installation_spec.js b/spec/frontend/packages/details/components/conan_installation_spec.js
index 92c1f8e7f4a..bf8a92a6350 100644
--- a/spec/frontend/packages/details/components/conan_installation_spec.js
+++ b/spec/frontend/packages/details/components/conan_installation_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import ConanInstallation from '~/packages/details/components/conan_installation.vue';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { conanPackage as packageEntity } from '../../mock_data';
diff --git a/spec/frontend/packages/details/components/installations_commands_spec.js b/spec/frontend/packages/details/components/installations_commands_spec.js
index 60da34ebcd9..065bf503585 100644
--- a/spec/frontend/packages/details/components/installations_commands_spec.js
+++ b/spec/frontend/packages/details/components/installations_commands_spec.js
@@ -1,12 +1,12 @@
import { shallowMount } from '@vue/test-utils';
+import ComposerInstallation from '~/packages/details/components/composer_installation.vue';
+import ConanInstallation from '~/packages/details/components/conan_installation.vue';
import InstallationCommands from '~/packages/details/components/installation_commands.vue';
-import NpmInstallation from '~/packages/details/components/npm_installation.vue';
import MavenInstallation from '~/packages/details/components/maven_installation.vue';
-import ConanInstallation from '~/packages/details/components/conan_installation.vue';
+import NpmInstallation from '~/packages/details/components/npm_installation.vue';
import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
import PypiInstallation from '~/packages/details/components/pypi_installation.vue';
-import ComposerInstallation from '~/packages/details/components/composer_installation.vue';
import {
conanPackage,
diff --git a/spec/frontend/packages/details/components/maven_installation_spec.js b/spec/frontend/packages/details/components/maven_installation_spec.js
index ff62969e709..dfeb6002186 100644
--- a/spec/frontend/packages/details/components/maven_installation_spec.js
+++ b/spec/frontend/packages/details/components/maven_installation_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { registryUrl as mavenPath } from 'jest/packages/details/mock_data';
import { mavenPackage as packageEntity } from 'jest/packages/mock_data';
import MavenInstallation from '~/packages/details/components/maven_installation.vue';
-import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/packages/details/components/npm_installation_spec.js b/spec/frontend/packages/details/components/npm_installation_spec.js
index dd6e62185a9..df820e7e948 100644
--- a/spec/frontend/packages/details/components/npm_installation_spec.js
+++ b/spec/frontend/packages/details/components/npm_installation_spec.js
@@ -1,11 +1,11 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { npmPackage as packageEntity } from 'jest/packages/mock_data';
+import Vuex from 'vuex';
import { registryUrl as nugetPath } from 'jest/packages/details/mock_data';
+import { npmPackage as packageEntity } from 'jest/packages/mock_data';
import NpmInstallation from '~/packages/details/components/npm_installation.vue';
-import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
import { npmInstallationCommand, npmSetupCommand } from '~/packages/details/store/getters';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/packages/details/components/nuget_installation_spec.js b/spec/frontend/packages/details/components/nuget_installation_spec.js
index 685d0808dd9..100e369751c 100644
--- a/spec/frontend/packages/details/components/nuget_installation_spec.js
+++ b/spec/frontend/packages/details/components/nuget_installation_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nugetPackage as packageEntity } from 'jest/packages/mock_data';
+import Vuex from 'vuex';
import { registryUrl as nugetPath } from 'jest/packages/details/mock_data';
+import { nugetPackage as packageEntity } from 'jest/packages/mock_data';
import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
-import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/packages/details/components/package_files_spec.js b/spec/frontend/packages/details/components/package_files_spec.js
index 9bcf6ed9235..b4e62bac8a3 100644
--- a/spec/frontend/packages/details/components/package_files_spec.js
+++ b/spec/frontend/packages/details/components/package_files_spec.js
@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils';
import stubChildren from 'helpers/stub_children';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import FileIcon from '~/vue_shared/components/file_icon.vue';
import component from '~/packages/details/components/package_files.vue';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { npmFiles, mavenFiles } from '../../mock_data';
diff --git a/spec/frontend/packages/details/components/package_history_spec.js b/spec/frontend/packages/details/components/package_history_spec.js
index 5a6b386e2ca..244805a9c82 100644
--- a/spec/frontend/packages/details/components/package_history_spec.js
+++ b/spec/frontend/packages/details/components/package_history_spec.js
@@ -1,10 +1,10 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
-import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
import component from '~/packages/details/components/package_history.vue';
+import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants';
+import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { mavenPackage, mockPipelineInfo } from '../../mock_data';
diff --git a/spec/frontend/packages/details/components/package_title_spec.js b/spec/frontend/packages/details/components/package_title_spec.js
index 61c6e824ab7..512cec85b40 100644
--- a/spec/frontend/packages/details/components/package_title_spec.js
+++ b/spec/frontend/packages/details/components/package_title_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import PackageTitle from '~/packages/details/components/package_title.vue';
import PackageTags from '~/packages/shared/components/package_tags.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
diff --git a/spec/frontend/packages/details/components/pypi_installation_spec.js b/spec/frontend/packages/details/components/pypi_installation_spec.js
index da30b4ba565..a6ccba71554 100644
--- a/spec/frontend/packages/details/components/pypi_installation_spec.js
+++ b/spec/frontend/packages/details/components/pypi_installation_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { pypiPackage as packageEntity } from 'jest/packages/mock_data';
import PypiInstallation from '~/packages/details/components/pypi_installation.vue';
diff --git a/spec/frontend/packages/details/store/actions_spec.js b/spec/frontend/packages/details/store/actions_spec.js
index e823a00ebc4..d11ee548b72 100644
--- a/spec/frontend/packages/details/store/actions_spec.js
+++ b/spec/frontend/packages/details/store/actions_spec.js
@@ -1,9 +1,9 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants';
import { fetchPackageVersions, deletePackage } from '~/packages/details/store/actions';
import * as types from '~/packages/details/store/mutation_types';
-import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
import { npmPackage as packageEntity } from '../../mock_data';
diff --git a/spec/frontend/packages/details/store/getters_spec.js b/spec/frontend/packages/details/store/getters_spec.js
index b8c2138e7f5..07c120f57f7 100644
--- a/spec/frontend/packages/details/store/getters_spec.js
+++ b/spec/frontend/packages/details/store/getters_spec.js
@@ -1,3 +1,4 @@
+import { NpmManager } from '~/packages/details/constants';
import {
conanInstallationCommand,
conanSetupCommand,
@@ -32,7 +33,6 @@ import {
registryUrl,
pypiSetupCommandStr,
} from '../mock_data';
-import { NpmManager } from '~/packages/details/constants';
describe('Getters PackageDetails Store', () => {
let state;
diff --git a/spec/frontend/packages/details/store/mutations_spec.js b/spec/frontend/packages/details/store/mutations_spec.js
index 501a56dcdde..6bc5fb7241f 100644
--- a/spec/frontend/packages/details/store/mutations_spec.js
+++ b/spec/frontend/packages/details/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/packages/details/store/mutations';
import * as types from '~/packages/details/store/mutation_types';
+import mutations from '~/packages/details/store/mutations';
import { npmPackage as packageEntity } from '../../mock_data';
describe('Mutations package details Store', () => {
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap
deleted file mode 100644
index ed77f25916f..00000000000
--- a/spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap
+++ /dev/null
@@ -1,14 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`packages_filter renders 1`] = `
-<gl-search-box-by-click-stub
- clearable="true"
- clearbuttontitle="Clear"
- clearrecentsearchestext="Clear recent searches"
- closebuttontitle="Close"
- norecentsearchestext="You don't have any recent searches"
- placeholder="Filter by name"
- recentsearchesheader="Recent searches"
- value=""
-/>
-`;
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
index b2df1ac5ab6..3f17731584c 100644
--- a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
+++ b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -6,517 +6,60 @@ exports[`packages_list_app renders 1`] = `
packagehelpurl="foo"
/>
- <b-tabs-stub
- activenavitemclass="gl-tab-nav-item-active gl-tab-nav-item-active-indigo"
- class="gl-tabs"
- contentclass=",gl-tab-content"
- navclass=",gl-tabs-nav"
- nofade="true"
- nonavstyle="true"
- tag="div"
- >
- <template>
-
- <b-tab-stub
- tag="div"
- title="All"
- titlelinkclass="gl-tab-nav-item"
- >
- <template>
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="Composer"
- titlelinkclass="gl-tab-nav-item"
- >
- <template>
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no Composer packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="Conan"
- titlelinkclass="gl-tab-nav-item"
- >
- <template>
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no Conan packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="Generic"
- titlelinkclass="gl-tab-nav-item"
- >
- <template>
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no Generic packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="Maven"
- titlelinkclass="gl-tab-nav-item"
- >
- <template>
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no Maven packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="NPM"
- titlelinkclass="gl-tab-nav-item"
+ <package-search-stub />
+
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
>
- <template>
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no NPM packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="NuGet"
- titlelinkclass="gl-tab-nav-item"
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt=""
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
>
- <template>
- <div>
- <section
- class="row empty-state text-center"
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
>
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no NuGet packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
- </b-tab-stub>
- <b-tab-stub
- tag="div"
- title="PyPI"
- titlelinkclass="gl-tab-nav-item"
- >
- <template>
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
<div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no PyPI packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div>
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
+ <!---->
+
+ <!---->
</div>
- </template>
- </b-tab-stub>
- </template>
- <template>
- <div
- class="gl-display-flex gl-align-self-center gl-py-2 gl-flex-grow-1 gl-justify-content-end"
- >
- <package-filter-stub
- class="gl-mr-2"
- />
-
- <package-sort-stub />
+ </div>
</div>
- </template>
- </b-tabs-stub>
+ </section>
+ </div>
</div>
`;
diff --git a/spec/frontend/packages/list/components/packages_filter_spec.js b/spec/frontend/packages/list/components/packages_filter_spec.js
deleted file mode 100644
index b186b5f5e48..00000000000
--- a/spec/frontend/packages/list/components/packages_filter_spec.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import Vuex from 'vuex';
-import { GlSearchBoxByClick } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import PackagesFilter from '~/packages/list/components/packages_filter.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('packages_filter', () => {
- let wrapper;
- let store;
-
- const findGlSearchBox = () => wrapper.find(GlSearchBoxByClick);
-
- const mountComponent = () => {
- store = new Vuex.Store();
- store.dispatch = jest.fn();
-
- wrapper = shallowMount(PackagesFilter, {
- localVue,
- store,
- });
- };
-
- beforeEach(mountComponent);
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('emits events', () => {
- it('sets the filter value in the store on input', () => {
- const searchString = 'foo';
- findGlSearchBox().vm.$emit('input', searchString);
-
- expect(store.dispatch).toHaveBeenCalledWith('setFilter', searchString);
- });
-
- it('emits the filter event when search box is submitted', () => {
- findGlSearchBox().vm.$emit('submit');
-
- expect(wrapper.emitted('filter')).toBeTruthy();
- });
- });
-});
diff --git a/spec/frontend/packages/list/components/packages_list_app_spec.js b/spec/frontend/packages/list/components/packages_list_app_spec.js
index 217096f822a..6862d23c4ff 100644
--- a/spec/frontend/packages/list/components/packages_list_app_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_app_spec.js
@@ -1,11 +1,12 @@
-import Vuex from 'vuex';
+import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlEmptyState, GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
-import * as commonUtils from '~/lib/utils/common_utils';
+import Vuex from 'vuex';
import createFlash from '~/flash';
+import * as commonUtils from '~/lib/utils/common_utils';
+import PackageSearch from '~/packages/list/components/package_search.vue';
import PackageListApp from '~/packages/list/components/packages_list_app.vue';
-import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
+import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
jest.mock('~/lib/utils/common_utils');
jest.mock('~/flash');
@@ -26,9 +27,9 @@ describe('packages_list_app', () => {
const emptyListHelpUrl = 'helpUrl';
const findEmptyState = () => wrapper.find(GlEmptyState);
const findListComponent = () => wrapper.find(PackageList);
- const findTabComponent = (index = 0) => wrapper.findAll(GlTab).at(index);
+ const findPackageSearch = () => wrapper.find(PackageSearch);
- const createStore = (filterQuery = '') => {
+ const createStore = (filter = []) => {
store = new Vuex.Store({
state: {
isLoading: false,
@@ -38,7 +39,7 @@ describe('packages_list_app', () => {
emptyListHelpUrl,
packageHelpUrl: 'foo',
},
- filterQuery,
+ filter,
},
});
store.dispatch = jest.fn();
@@ -52,8 +53,6 @@ describe('packages_list_app', () => {
GlEmptyState,
GlLoadingIcon,
PackageList,
- GlTab,
- GlTabs,
GlSprintf,
GlLink,
},
@@ -94,6 +93,7 @@ describe('packages_list_app', () => {
it('call requestPackagesList on page:changed', () => {
mountComponent();
+ store.dispatch.mockClear();
const list = findListComponent();
list.vm.$emit('page:changed', 1);
@@ -108,41 +108,15 @@ describe('packages_list_app', () => {
expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
});
- it('calls requestPackagesList on sort:changed', () => {
- mountComponent();
-
- const list = findListComponent();
- list.vm.$emit('sort:changed');
- expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
- });
-
it('does not call requestPackagesList two times on render', () => {
mountComponent();
expect(store.dispatch).toHaveBeenCalledTimes(1);
});
- describe('tab change', () => {
- it('calls requestPackagesList when all tab is clicked', () => {
- mountComponent();
-
- findTabComponent().trigger('click');
-
- expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
- });
-
- it('calls requestPackagesList when a package type tab is clicked', () => {
- mountComponent();
-
- findTabComponent(1).trigger('click');
-
- expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
- });
- });
-
describe('filter without results', () => {
beforeEach(() => {
- createStore('foo');
+ createStore([{ type: 'something' }]);
mountComponent();
});
@@ -154,12 +128,29 @@ describe('packages_list_app', () => {
});
});
+ describe('Package Search', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findPackageSearch().exists()).toBe(true);
+ });
+
+ it('on update fetches data from the store', () => {
+ mountComponent();
+ store.dispatch.mockClear();
+
+ findPackageSearch().vm.$emit('update');
+
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ });
+ });
+
describe('delete alert handling', () => {
const { location } = window.location;
const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
beforeEach(() => {
- createStore('foo');
+ createStore();
jest.spyOn(commonUtils, 'historyReplaceState').mockImplementation(() => {});
delete window.location;
window.location = {
diff --git a/spec/frontend/packages/list/components/packages_list_spec.js b/spec/frontend/packages/list/components/packages_list_spec.js
index f981cc2851a..b1478a5e6dc 100644
--- a/spec/frontend/packages/list/components/packages_list_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_spec.js
@@ -1,14 +1,14 @@
-import Vuex from 'vuex';
-import { last } from 'lodash';
import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
+import { last } from 'lodash';
+import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
-import Tracking from '~/tracking';
import PackagesList from '~/packages/list/components/packages_list.vue';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
-import * as SharedUtils from '~/packages/shared/utils';
+import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
import { TrackingActions } from '~/packages/shared/constants';
+import * as SharedUtils from '~/packages/shared/utils';
+import Tracking from '~/tracking';
import { packageList } from '../../mock_data';
const localVue = createLocalVue();
diff --git a/spec/frontend/packages/list/components/packages_search_spec.js b/spec/frontend/packages/list/components/packages_search_spec.js
new file mode 100644
index 00000000000..9b62dde8d2b
--- /dev/null
+++ b/spec/frontend/packages/list/components/packages_search_spec.js
@@ -0,0 +1,107 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import component from '~/packages/list/components/package_search.vue';
+import PackageTypeToken from '~/packages/list/components/tokens/package_type_token.vue';
+import getTableHeaders from '~/packages/list/utils';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Package Search', () => {
+ let wrapper;
+ let store;
+
+ const findRegistrySearch = () => wrapper.find(RegistrySearch);
+
+ const createStore = (isGroupPage) => {
+ const state = {
+ config: {
+ isGroupPage,
+ },
+ sorting: {
+ orderBy: 'version',
+ sort: 'desc',
+ },
+ filter: [],
+ };
+ store = new Vuex.Store({
+ state,
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = (isGroupPage = false) => {
+ createStore(isGroupPage);
+
+ wrapper = shallowMount(component, {
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('has a registry search component', () => {
+ mountComponent();
+
+ expect(findRegistrySearch().exists()).toBe(true);
+ expect(findRegistrySearch().props()).toMatchObject({
+ filter: store.state.filter,
+ sorting: store.state.sorting,
+ tokens: expect.arrayContaining([
+ expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
+ ]),
+ sortableFields: getTableHeaders(),
+ });
+ });
+
+ it.each`
+ isGroupPage | page
+ ${false} | ${'project'}
+ ${true} | ${'group'}
+ `('in a $page page binds the right props', ({ isGroupPage }) => {
+ mountComponent(isGroupPage);
+
+ expect(findRegistrySearch().props()).toMatchObject({
+ filter: store.state.filter,
+ sorting: store.state.sorting,
+ tokens: expect.arrayContaining([
+ expect.objectContaining({ token: PackageTypeToken, type: 'type', icon: 'package' }),
+ ]),
+ sortableFields: getTableHeaders(isGroupPage),
+ });
+ });
+
+ it('on sorting:changed emits update event and calls vuex setSorting', () => {
+ const payload = { sort: 'foo' };
+
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('sorting:changed', payload);
+
+ expect(store.dispatch).toHaveBeenCalledWith('setSorting', payload);
+ expect(wrapper.emitted('update')).toEqual([[]]);
+ });
+
+ it('on filter:changed calls vuex setFilter', () => {
+ const payload = ['foo'];
+
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('filter:changed', payload);
+
+ expect(store.dispatch).toHaveBeenCalledWith('setFilter', payload);
+ });
+
+ it('on filter:submit emits update event', () => {
+ mountComponent();
+
+ findRegistrySearch().vm.$emit('filter:submit');
+
+ expect(wrapper.emitted('update')).toEqual([[]]);
+ });
+});
diff --git a/spec/frontend/packages/list/components/packages_sort_spec.js b/spec/frontend/packages/list/components/packages_sort_spec.js
deleted file mode 100644
index d15ad9bd542..00000000000
--- a/spec/frontend/packages/list/components/packages_sort_spec.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import Vuex from 'vuex';
-import { GlSorting, GlSortingItem } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import stubChildren from 'helpers/stub_children';
-import PackagesSort from '~/packages/list/components/packages_sort.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('packages_sort', () => {
- let wrapper;
- let store;
- let sorting;
- let sortingItems;
-
- const findPackageListSorting = () => wrapper.find(GlSorting);
- const findSortingItems = () => wrapper.findAll(GlSortingItem);
-
- const createStore = (isGroupPage) => {
- const state = {
- config: {
- isGroupPage,
- },
- sorting: {
- orderBy: 'version',
- sort: 'desc',
- },
- };
- store = new Vuex.Store({
- state,
- });
- store.dispatch = jest.fn();
- };
-
- const mountComponent = (isGroupPage = false) => {
- createStore(isGroupPage);
-
- wrapper = mount(PackagesSort, {
- localVue,
- store,
- stubs: {
- ...stubChildren(PackagesSort),
- GlSortingItem,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when is in projects', () => {
- beforeEach(() => {
- mountComponent();
- sorting = findPackageListSorting();
- sortingItems = findSortingItems();
- });
-
- it('has all the sortable items', () => {
- expect(sortingItems).toHaveLength(wrapper.vm.sortableFields.length);
- });
-
- it('on sort change set sorting in vuex and emit event', () => {
- sorting.vm.$emit('sortDirectionChange');
- expect(store.dispatch).toHaveBeenCalledWith('setSorting', { sort: 'asc' });
- expect(wrapper.emitted('sort:changed')).toBeTruthy();
- });
-
- it('on sort item click set sorting and emit event', () => {
- const item = sortingItems.at(0);
- const { orderBy } = wrapper.vm.sortableFields[0];
- item.vm.$emit('click');
- expect(store.dispatch).toHaveBeenCalledWith('setSorting', { orderBy });
- expect(wrapper.emitted('sort:changed')).toBeTruthy();
- });
- });
-
- describe('when is in group', () => {
- beforeEach(() => {
- mountComponent(true);
- sorting = findPackageListSorting();
- sortingItems = findSortingItems();
- });
-
- it('has all the sortable items', () => {
- expect(sortingItems).toHaveLength(wrapper.vm.sortableFields.length);
- });
- });
-});
diff --git a/spec/frontend/packages/list/components/packages_title_spec.js b/spec/frontend/packages/list/components/packages_title_spec.js
index 5e9ebd8ecb0..3716e8daa7c 100644
--- a/spec/frontend/packages/list/components/packages_title_spec.js
+++ b/spec/frontend/packages/list/components/packages_title_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
+import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list//constants';
import PackageTitle from '~/packages/list/components/package_title.vue';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
-import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '~/packages/list//constants';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
describe('PackageTitle', () => {
let wrapper;
diff --git a/spec/frontend/packages/list/components/tokens/package_type_token_spec.js b/spec/frontend/packages/list/components/tokens/package_type_token_spec.js
new file mode 100644
index 00000000000..b0cbe34f0b9
--- /dev/null
+++ b/spec/frontend/packages/list/components/tokens/package_type_token_spec.js
@@ -0,0 +1,48 @@
+import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages/list/components/tokens/package_type_token.vue';
+import { PACKAGE_TYPES } from '~/packages/list/constants';
+
+describe('packages_filter', () => {
+ let wrapper;
+
+ const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
+ const findFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
+
+ const mountComponent = ({ attrs, listeners } = {}) => {
+ wrapper = shallowMount(component, {
+ attrs,
+ listeners,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('it binds all of his attrs to filtered search token', () => {
+ mountComponent({ attrs: { foo: 'bar' } });
+
+ expect(findFilteredSearchToken().attributes('foo')).toBe('bar');
+ });
+
+ it('it binds all of his events to filtered search token', () => {
+ const clickListener = jest.fn();
+ mountComponent({ listeners: { click: clickListener } });
+
+ findFilteredSearchToken().vm.$emit('click');
+
+ expect(clickListener).toHaveBeenCalled();
+ });
+
+ it.each(PACKAGE_TYPES.map((p, index) => [p, index]))(
+ 'displays a suggestion for %p',
+ (packageType, index) => {
+ mountComponent();
+ const item = findFilteredSearchSuggestions().at(index);
+ expect(item.text()).toBe(packageType.title);
+ expect(item.props('value')).toBe(packageType.type);
+ },
+ );
+});
diff --git a/spec/frontend/packages/list/stores/actions_spec.js b/spec/frontend/packages/list/stores/actions_spec.js
index 05e1fe57cae..b5b0177eb4e 100644
--- a/spec/frontend/packages/list/stores/actions_spec.js
+++ b/spec/frontend/packages/list/stores/actions_spec.js
@@ -3,9 +3,9 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { MISSING_DELETE_PATH_ERROR } from '~/packages/list/constants';
import * as actions from '~/packages/list/stores/actions';
import * as types from '~/packages/list/stores/mutation_types';
-import { MISSING_DELETE_PATH_ERROR } from '~/packages/list/constants';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
jest.mock('~/flash.js');
@@ -30,11 +30,13 @@ describe('Actions Package list store', () => {
sort: 'asc',
orderBy: 'version',
};
+
+ const filter = [];
it('should fetch the project packages list when isGroupPage is false', (done) => {
testAction(
actions.requestPackagesList,
undefined,
- { config: { isGroupPage: false, resourceId: 1 }, sorting },
+ { config: { isGroupPage: false, resourceId: 1 }, sorting, filter },
[],
[
{ type: 'setLoading', payload: true },
@@ -54,7 +56,7 @@ describe('Actions Package list store', () => {
testAction(
actions.requestPackagesList,
undefined,
- { config: { isGroupPage: true, resourceId: 2 }, sorting },
+ { config: { isGroupPage: true, resourceId: 2 }, sorting, filter },
[],
[
{ type: 'setLoading', payload: true },
@@ -70,7 +72,7 @@ describe('Actions Package list store', () => {
);
});
- it('should fetch packages of a certain type when selectedType is present', (done) => {
+ it('should fetch packages of a certain type when a filter with a type is present', (done) => {
const packageType = 'maven';
testAction(
@@ -79,7 +81,7 @@ describe('Actions Package list store', () => {
{
config: { isGroupPage: false, resourceId: 1 },
sorting,
- selectedType: { type: packageType },
+ filter: [{ type: 'type', value: { data: 'maven' } }],
},
[],
[
@@ -107,7 +109,7 @@ describe('Actions Package list store', () => {
testAction(
actions.requestPackagesList,
undefined,
- { config: { isGroupPage: false, resourceId: 2 }, sorting },
+ { config: { isGroupPage: false, resourceId: 2 }, sorting, filter },
[],
[
{ type: 'setLoading', payload: true },
diff --git a/spec/frontend/packages/list/stores/mutations_spec.js b/spec/frontend/packages/list/stores/mutations_spec.js
index 0d424a0c011..2ddf3a1da33 100644
--- a/spec/frontend/packages/list/stores/mutations_spec.js
+++ b/spec/frontend/packages/list/stores/mutations_spec.js
@@ -1,7 +1,7 @@
-import mutations from '~/packages/list/stores/mutations';
+import * as commonUtils from '~/lib/utils/common_utils';
import * as types from '~/packages/list/stores/mutation_types';
+import mutations from '~/packages/list/stores/mutations';
import createState from '~/packages/list/stores/state';
-import * as commonUtils from '~/lib/utils/common_utils';
import { npmPackage, mavenPackage } from '../../mock_data';
describe('Mutations Registry Store', () => {
@@ -78,17 +78,10 @@ describe('Mutations Registry Store', () => {
});
});
- describe('SET_SELECTED_TYPE', () => {
- it('should set the selected type', () => {
- mutations[types.SET_SELECTED_TYPE](mockState, { type: 'maven' });
- expect(mockState.selectedType).toEqual({ type: 'maven' });
- });
- });
-
describe('SET_FILTER', () => {
it('should set the filter query', () => {
mutations[types.SET_FILTER](mockState, 'foo');
- expect(mockState.filterQuery).toEqual('foo');
+ expect(mockState.filter).toEqual('foo');
});
});
});
diff --git a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
index 5faae5690db..4a75deebcf9 100644
--- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
+++ b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
@@ -6,7 +6,7 @@ exports[`packages_list_row renders 1`] = `
data-qa-selector="package_row"
>
<div
- class="gl-display-flex gl-align-items-center gl-py-5"
+ class="gl-display-flex gl-align-items-center gl-py-3"
>
<!---->
@@ -14,7 +14,7 @@ exports[`packages_list_row renders 1`] = `
class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1"
>
<div
- class="gl-display-flex gl-flex-direction-column gl-justify-content-space-between gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
+ class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
>
<div
class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0"
@@ -40,7 +40,7 @@ exports[`packages_list_row renders 1`] = `
</div>
<div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
>
<div
class="gl-display-flex"
@@ -85,7 +85,7 @@ exports[`packages_list_row renders 1`] = `
</div>
<div
- class="gl-display-flex gl-align-items-center gl-mt-1 gl-min-h-6"
+ class="gl-display-flex gl-align-items-center gl-min-h-6"
>
<span>
<gl-sprintf-stub
@@ -97,7 +97,7 @@ exports[`packages_list_row renders 1`] = `
</div>
<div
- class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-1"
+ class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
>
<gl-button-stub
aria-label="Remove package"
diff --git a/spec/frontend/packages/shared/components/package_list_row_spec.js b/spec/frontend/packages/shared/components/package_list_row_spec.js
index 0d0ea4e2122..bd122167273 100644
--- a/spec/frontend/packages/shared/components/package_list_row_spec.js
+++ b/spec/frontend/packages/shared/components/package_list_row_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
import PackagePath from '~/packages/shared/components/package_path.vue';
+import PackageTags from '~/packages/shared/components/package_tags.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import { packageList } from '../../mock_data';
diff --git a/spec/frontend/packages/shared/components/packages_list_loader_spec.js b/spec/frontend/packages/shared/components/packages_list_loader_spec.js
index 115a3a7095d..4ff01068f92 100644
--- a/spec/frontend/packages/shared/components/packages_list_loader_spec.js
+++ b/spec/frontend/packages/shared/components/packages_list_loader_spec.js
@@ -30,7 +30,7 @@ describe('PackagesListLoader', () => {
it('has the correct classes', () => {
expect(findDesktopShapes().classes()).toEqual([
'gl-display-none',
- 'gl-display-sm-flex',
+ 'gl-sm-display-flex',
'gl-flex-direction-column',
]);
});
@@ -44,7 +44,7 @@ describe('PackagesListLoader', () => {
it('has the correct classes', () => {
expect(findMobileShapes().classes()).toEqual([
'gl-flex-direction-column',
- 'gl-display-sm-none',
+ 'gl-sm-display-none',
]);
});
});
diff --git a/spec/frontend/packages/shared/utils_spec.js b/spec/frontend/packages/shared/utils_spec.js
index 590e3814bee..506f37f8895 100644
--- a/spec/frontend/packages/shared/utils_spec.js
+++ b/spec/frontend/packages/shared/utils_spec.js
@@ -1,10 +1,10 @@
+import { PackageType, TrackingCategories } from '~/packages/shared/constants';
import {
packageTypeToTrackCategory,
beautifyPath,
getPackageTypeLabel,
getCommitLink,
} from '~/packages/shared/utils';
-import { PackageType, TrackingCategories } from '~/packages/shared/constants';
import { packageList } from '../mock_data';
describe('Packages shared utils', () => {
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
new file mode 100644
index 00000000000..be0d7114e6e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
@@ -0,0 +1,309 @@
+import { GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import component from '~/packages_and_registries/settings/group/components/group_settings_app.vue';
+import MavenSettings from '~/packages_and_registries/settings/group/components/maven_settings.vue';
+import {
+ PACKAGE_SETTINGS_HEADER,
+ PACKAGE_SETTINGS_DESCRIPTION,
+ PACKAGES_DOCS_PATH,
+ ERROR_UPDATING_SETTINGS,
+ SUCCESS_UPDATING_SETTINGS,
+} from '~/packages_and_registries/settings/group/constants';
+
+import updateNamespacePackageSettings from '~/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql';
+import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
+import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
+import {
+ groupPackageSettingsMock,
+ groupPackageSettingsMutationMock,
+ groupPackageSettingsMutationErrorMock,
+} from '../mock_data';
+
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+
+describe('Group Settings App', () => {
+ let wrapper;
+ let apolloProvider;
+ let show;
+
+ const defaultProvide = {
+ defaultExpanded: false,
+ groupPath: 'foo_group_path',
+ };
+
+ const mountComponent = ({
+ provide = defaultProvide,
+ resolver = jest.fn().mockResolvedValue(groupPackageSettingsMock),
+ mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock()),
+ data = {},
+ } = {}) => {
+ localVue.use(VueApollo);
+
+ const requestHandlers = [
+ [getGroupPackagesSettingsQuery, resolver],
+ [updateNamespacePackageSettings, mutationResolver],
+ ];
+
+ apolloProvider = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(component, {
+ localVue,
+ apolloProvider,
+ provide,
+ data() {
+ return {
+ ...data,
+ };
+ },
+ stubs: {
+ GlSprintf,
+ SettingsBlock,
+ },
+ mocks: {
+ $toast: {
+ show,
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ show = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findSettingsBlock = () => wrapper.find(SettingsBlock);
+ const findDescription = () => wrapper.find('[data-testid="description"');
+ const findLink = () => wrapper.find(GlLink);
+ const findMavenSettings = () => wrapper.find(MavenSettings);
+ const findAlert = () => wrapper.find(GlAlert);
+
+ const waitForApolloQueryAndRender = async () => {
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
+ };
+
+ const emitSettingsUpdate = (override) => {
+ findMavenSettings().vm.$emit('update', {
+ mavenDuplicateExceptionRegex: ')',
+ ...override,
+ });
+ };
+
+ it('renders a settings block', () => {
+ mountComponent();
+
+ expect(findSettingsBlock().exists()).toBe(true);
+ });
+
+ it('passes the correct props to settings block', () => {
+ mountComponent();
+
+ expect(findSettingsBlock().props('defaultExpanded')).toBe(false);
+ });
+
+ it('has the correct header text', () => {
+ mountComponent();
+
+ expect(wrapper.text()).toContain(PACKAGE_SETTINGS_HEADER);
+ });
+
+ it('has the correct description text', () => {
+ mountComponent();
+
+ expect(findDescription().text()).toMatchInterpolatedText(PACKAGE_SETTINGS_DESCRIPTION);
+ });
+
+ it('has the correct link', () => {
+ mountComponent();
+
+ expect(findLink().attributes()).toMatchObject({
+ href: PACKAGES_DOCS_PATH,
+ target: '_blank',
+ });
+ expect(findLink().text()).toBe('More Information');
+ });
+
+ it('calls the graphql API with the proper variables', () => {
+ const resolver = jest.fn().mockResolvedValue(groupPackageSettingsMock);
+ mountComponent({ resolver });
+
+ expect(resolver).toHaveBeenCalledWith({
+ fullPath: defaultProvide.groupPath,
+ });
+ });
+
+ describe('maven settings', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findMavenSettings().exists()).toBe(true);
+ });
+
+ it('assigns duplication allowness and exception props', async () => {
+ mountComponent();
+
+ expect(findMavenSettings().props('loading')).toBe(true);
+
+ await waitForApolloQueryAndRender();
+
+ const {
+ mavenDuplicatesAllowed,
+ mavenDuplicateExceptionRegex,
+ } = groupPackageSettingsMock.data.group.packageSettings;
+
+ expect(findMavenSettings().props()).toMatchObject({
+ mavenDuplicatesAllowed,
+ mavenDuplicateExceptionRegex,
+ mavenDuplicateExceptionRegexError: '',
+ loading: false,
+ });
+ });
+
+ it('on update event calls the mutation', async () => {
+ const mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock());
+ mountComponent({ mutationResolver });
+
+ await waitForApolloQueryAndRender();
+
+ emitSettingsUpdate();
+
+ expect(mutationResolver).toHaveBeenCalledWith({
+ input: { mavenDuplicateExceptionRegex: ')', namespacePath: 'foo_group_path' },
+ });
+ });
+ });
+
+ describe('settings update', () => {
+ describe('success state', () => {
+ it('shows a success alert', async () => {
+ mountComponent();
+
+ await waitForApolloQueryAndRender();
+
+ emitSettingsUpdate();
+
+ await waitForPromises();
+
+ expect(show).toHaveBeenCalledWith(SUCCESS_UPDATING_SETTINGS, {
+ type: 'success',
+ });
+ });
+
+ it('has an optimistic response', async () => {
+ const mavenDuplicateExceptionRegex = 'latest[master]something';
+ mountComponent();
+
+ await waitForApolloQueryAndRender();
+
+ expect(findMavenSettings().props('mavenDuplicateExceptionRegex')).toBe('');
+
+ emitSettingsUpdate({ mavenDuplicateExceptionRegex });
+
+ // wait for apollo to update the model with the optimistic response
+ await wrapper.vm.$nextTick();
+
+ expect(findMavenSettings().props('mavenDuplicateExceptionRegex')).toBe(
+ mavenDuplicateExceptionRegex,
+ );
+
+ // wait for the call to resolve
+ await waitForPromises();
+
+ expect(findMavenSettings().props('mavenDuplicateExceptionRegex')).toBe(
+ mavenDuplicateExceptionRegex,
+ );
+ });
+ });
+
+ describe('errors', () => {
+ const verifyAlert = () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(ERROR_UPDATING_SETTINGS);
+ expect(findAlert().props('variant')).toBe('warning');
+ };
+
+ it('mutation payload with root level errors', async () => {
+ // note this is a complex test that covers all the path around errors that are shown in the form
+ // it's one single it case, due to the expensive preparation and execution
+ const mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationErrorMock);
+ mountComponent({ mutationResolver });
+
+ await waitForApolloQueryAndRender();
+
+ emitSettingsUpdate();
+
+ await waitForApolloQueryAndRender();
+
+ // errors are bound to the component
+ expect(findMavenSettings().props('mavenDuplicateExceptionRegexError')).toBe(
+ groupPackageSettingsMutationErrorMock.errors[0].extensions.problems[0].message,
+ );
+
+ // general error message is shown
+
+ verifyAlert();
+
+ emitSettingsUpdate();
+
+ await wrapper.vm.$nextTick();
+
+ // errors are reset on mutation call
+ expect(findMavenSettings().props('mavenDuplicateExceptionRegexError')).toBe('');
+ });
+
+ it.each`
+ type | mutationResolver
+ ${'local'} | ${jest.fn().mockResolvedValue(groupPackageSettingsMutationMock({ errors: ['foo'] }))}
+ ${'network'} | ${jest.fn().mockRejectedValue()}
+ `('mutation payload with $type error', async ({ mutationResolver }) => {
+ mountComponent({ mutationResolver });
+
+ await waitForApolloQueryAndRender();
+
+ emitSettingsUpdate();
+
+ await waitForPromises();
+
+ verifyAlert();
+ });
+
+ it('a successful request dismisses the alert', async () => {
+ mountComponent({ data: { alertMessage: 'foo' } });
+
+ await waitForApolloQueryAndRender();
+
+ expect(findAlert().exists()).toBe(true);
+
+ emitSettingsUpdate();
+
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('dismiss event from alert dismiss it from the page', async () => {
+ mountComponent({ data: { alertMessage: 'foo' } });
+
+ await waitForApolloQueryAndRender();
+
+ expect(findAlert().exists()).toBe(true);
+
+ findAlert().vm.$emit('dismiss');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js
new file mode 100644
index 00000000000..2433c50ff24
--- /dev/null
+++ b/spec/frontend/packages_and_registries/settings/group/components/maven_settings_spec.js
@@ -0,0 +1,153 @@
+import { GlSprintf, GlToggle, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/settings/group/components/maven_settings.vue';
+
+import {
+ MAVEN_TITLE,
+ MAVEN_SETTINGS_SUBTITLE,
+ MAVEN_DUPLICATES_ALLOWED_DISABLED,
+ MAVEN_DUPLICATES_ALLOWED_ENABLED,
+ MAVEN_SETTING_EXCEPTION_TITLE,
+ MAVEN_SETTINGS_EXCEPTION_LEGEND,
+} from '~/packages_and_registries/settings/group/constants';
+
+describe('Maven Settings', () => {
+ let wrapper;
+
+ const defaultProps = {
+ mavenDuplicatesAllowed: false,
+ mavenDuplicateExceptionRegex: 'foo',
+ };
+
+ const mountComponent = (propsData = defaultProps) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTitle = () => wrapper.find('h5');
+ const findSubTitle = () => wrapper.find('p');
+ const findToggle = () => wrapper.find(GlToggle);
+ const findToggleLabel = () => wrapper.find('[data-testid="toggle-label"');
+
+ const findInputGroup = () => wrapper.find(GlFormGroup);
+ const findInput = () => wrapper.find(GlFormInput);
+
+ it('has a title', () => {
+ mountComponent();
+
+ expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toBe(MAVEN_TITLE);
+ });
+
+ it('has a subtitle', () => {
+ mountComponent();
+
+ expect(findSubTitle().exists()).toBe(true);
+ expect(findSubTitle().text()).toBe(MAVEN_SETTINGS_SUBTITLE);
+ });
+
+ it('has a toggle', () => {
+ mountComponent();
+
+ expect(findToggle().exists()).toBe(true);
+ expect(findToggle().props('value')).toBe(defaultProps.mavenDuplicatesAllowed);
+ });
+
+ it('toggle emits an update event', () => {
+ mountComponent();
+
+ findToggle().vm.$emit('change', false);
+
+ expect(wrapper.emitted('update')).toEqual([[{ mavenDuplicatesAllowed: false }]]);
+ });
+
+ describe('when the duplicates are disabled', () => {
+ it('the toggle has the disabled message', () => {
+ mountComponent();
+
+ expect(findToggleLabel().exists()).toBe(true);
+ expect(findToggleLabel().text()).toMatchInterpolatedText(MAVEN_DUPLICATES_ALLOWED_DISABLED);
+ });
+
+ it('shows a form group with an input field', () => {
+ mountComponent();
+
+ expect(findInputGroup().exists()).toBe(true);
+
+ expect(findInputGroup().attributes()).toMatchObject({
+ 'label-for': 'maven-duplicated-settings-regex-input',
+ label: MAVEN_SETTING_EXCEPTION_TITLE,
+ description: MAVEN_SETTINGS_EXCEPTION_LEGEND,
+ });
+ });
+
+ it('shows an input field', () => {
+ mountComponent();
+
+ expect(findInput().exists()).toBe(true);
+
+ expect(findInput().attributes()).toMatchObject({
+ id: 'maven-duplicated-settings-regex-input',
+ value: defaultProps.mavenDuplicateExceptionRegex,
+ });
+ });
+
+ it('input change event emits an update event', () => {
+ mountComponent();
+
+ findInput().vm.$emit('change', 'bar');
+
+ expect(wrapper.emitted('update')).toEqual([[{ mavenDuplicateExceptionRegex: 'bar' }]]);
+ });
+
+ describe('valid state', () => {
+ it('form group has correct props', () => {
+ mountComponent();
+
+ expect(findInputGroup().attributes()).toMatchObject({
+ state: 'true',
+ 'invalid-feedback': '',
+ });
+ });
+ });
+
+ describe('invalid state', () => {
+ it('form group has correct props', () => {
+ const propsWithError = {
+ ...defaultProps,
+ mavenDuplicateExceptionRegexError: 'some error string',
+ };
+
+ mountComponent(propsWithError);
+
+ expect(findInputGroup().attributes()).toMatchObject({
+ 'invalid-feedback': propsWithError.mavenDuplicateExceptionRegexError,
+ });
+ });
+ });
+ });
+
+ describe('when the duplicates are enabled', () => {
+ it('has the correct toggle label', () => {
+ mountComponent({ ...defaultProps, mavenDuplicatesAllowed: true });
+
+ expect(findToggleLabel().exists()).toBe(true);
+ expect(findToggleLabel().text()).toMatchInterpolatedText(MAVEN_DUPLICATES_ALLOWED_ENABLED);
+ });
+
+ it('hides the form input group', () => {
+ mountComponent({ ...defaultProps, mavenDuplicatesAllowed: true });
+
+ expect(findInputGroup().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js b/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js
new file mode 100644
index 00000000000..e1a46f97318
--- /dev/null
+++ b/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js
@@ -0,0 +1,56 @@
+import expirationPolicyQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
+import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update';
+
+describe('Package and Registries settings group cache updates', () => {
+ let client;
+
+ const payload = {
+ data: {
+ updateNamespacePackageSettings: {
+ packageSettings: {
+ mavenDuplicatesAllowed: false,
+ mavenDuplicateExceptionRegex: 'latest[master]something',
+ },
+ },
+ },
+ };
+
+ const cacheMock = {
+ group: {
+ packageSettings: {
+ mavenDuplicatesAllowed: true,
+ mavenDuplicateExceptionRegex: '',
+ },
+ },
+ };
+
+ const queryAndVariables = {
+ query: expirationPolicyQuery,
+ variables: { fullPath: 'foo' },
+ };
+
+ beforeEach(() => {
+ client = {
+ readQuery: jest.fn().mockReturnValue(cacheMock),
+ writeQuery: jest.fn(),
+ };
+ });
+ describe('updateGroupPackageSettings', () => {
+ it('calls readQuery', () => {
+ updateGroupPackageSettings('foo')(client, payload);
+ expect(client.readQuery).toHaveBeenCalledWith(queryAndVariables);
+ });
+
+ it('writes the correct result in the cache', () => {
+ updateGroupPackageSettings('foo')(client, payload);
+ expect(client.writeQuery).toHaveBeenCalledWith({
+ ...queryAndVariables,
+ data: {
+ group: {
+ ...payload.data.updateNamespacePackageSettings,
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js b/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js
new file mode 100644
index 00000000000..a3c53d5768a
--- /dev/null
+++ b/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js
@@ -0,0 +1,20 @@
+import { updateGroupPackagesSettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
+
+describe('Optimistic responses', () => {
+ describe('updateGroupPackagesSettingsOptimisticResponse', () => {
+ it('returns the correct structure', () => {
+ expect(updateGroupPackagesSettingsOptimisticResponse({ foo: 'bar' })).toMatchInlineSnapshot(`
+ Object {
+ "__typename": "Mutation",
+ "updateNamespacePackageSettings": Object {
+ "__typename": "UpdateNamespacePackageSettingsPayload",
+ "errors": Array [],
+ "packageSettings": Object {
+ "foo": "bar",
+ },
+ },
+ }
+ `);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/group/mock_data.js b/spec/frontend/packages_and_registries/settings/group/mock_data.js
new file mode 100644
index 00000000000..777c0898de0
--- /dev/null
+++ b/spec/frontend/packages_and_registries/settings/group/mock_data.js
@@ -0,0 +1,48 @@
+export const groupPackageSettingsMock = {
+ data: {
+ group: {
+ packageSettings: {
+ mavenDuplicatesAllowed: true,
+ mavenDuplicateExceptionRegex: '',
+ },
+ },
+ },
+};
+
+export const groupPackageSettingsMutationMock = (override) => ({
+ data: {
+ updateNamespacePackageSettings: {
+ packageSettings: {
+ mavenDuplicatesAllowed: true,
+ mavenDuplicateExceptionRegex: 'latest[master]something',
+ },
+ errors: [],
+ ...override,
+ },
+ },
+});
+
+export const groupPackageSettingsMutationErrorMock = {
+ errors: [
+ {
+ message:
+ 'Variable $input of type UpdateNamespacePackageSettingsInput! was provided invalid value for mavenDuplicateExceptionRegex (latest[master]somethingj)) is an invalid regexp: unexpected ): latest[master]somethingj)))',
+ locations: [{ line: 1, column: 41 }],
+ extensions: {
+ value: {
+ namespacePath: 'gitlab-org',
+ mavenDuplicateExceptionRegex: 'latest[master]something))',
+ },
+ problems: [
+ {
+ path: ['mavenDuplicateExceptionRegex'],
+ explanation:
+ 'latest[master]somethingj)) is an invalid regexp: unexpected ): latest[master]something))',
+ message:
+ 'latest[master]somethingj)) is an invalid regexp: unexpected ): latest[master]something))',
+ },
+ ],
+ },
+ },
+ ],
+};
diff --git a/spec/frontend/pager_spec.js b/spec/frontend/pager_spec.js
index c8a129e38e7..ad4222e7cb2 100644
--- a/spec/frontend/pager_spec.js
+++ b/spec/frontend/pager_spec.js
@@ -1,9 +1,9 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
-import Pager from '~/pager';
import { removeParams } from '~/lib/utils/url_utility';
+import Pager from '~/pager';
jest.mock('~/lib/utils/url_utility', () => ({
removeParams: jest.fn().mockName('removeParams'),
diff --git a/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js b/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
index 81750b4827f..52648d3ce00 100644
--- a/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
+++ b/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { TEST_HOST } from 'helpers/test_constants';
-import { redirectTo } from '~/lib/utils/url_utility';
+import mountComponent from 'helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
+import { redirectTo } from '~/lib/utils/url_utility';
import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
jest.mock('~/lib/utils/url_utility', () => ({
diff --git a/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js b/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js
index d203a8ea0e0..c7293b00adf 100644
--- a/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js
+++ b/spec/frontend/pages/admin/users/components/delete_user_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DeleteUserModal from '~/pages/admin/users/components/delete_user_modal.vue';
import ModalStub from './stubs/modal_stub';
diff --git a/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js b/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js
index 6df2efd624d..3669bc40d7e 100644
--- a/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js
+++ b/spec/frontend/pages/admin/users/components/user_modal_manager_spec.js
@@ -3,6 +3,8 @@ import UserModalManager from '~/pages/admin/users/components/user_modal_manager.
import ModalStub from './stubs/modal_stub';
describe('Users admin page Modal Manager', () => {
+ let wrapper;
+
const modalConfiguration = {
action1: {
title: 'action1',
@@ -14,11 +16,12 @@ describe('Users admin page Modal Manager', () => {
},
};
- let wrapper;
+ const findModal = () => wrapper.find({ ref: 'modal' });
const createComponent = (props = {}) => {
wrapper = mount(UserModalManager, {
propsData: {
+ selector: '.js-delete-user-modal-button',
modalConfiguration,
csrfToken: 'dummyCSRF',
...props,
@@ -37,7 +40,7 @@ describe('Users admin page Modal Manager', () => {
describe('render behavior', () => {
it('does not renders modal when initialized', () => {
createComponent();
- expect(wrapper.find({ ref: 'modal' }).exists()).toBeFalsy();
+ expect(findModal().exists()).toBeFalsy();
});
it('throws if action has no proper configuration', () => {
@@ -55,7 +58,7 @@ describe('Users admin page Modal Manager', () => {
});
return wrapper.vm.$nextTick().then(() => {
- const modal = wrapper.find({ ref: 'modal' });
+ const modal = findModal();
expect(modal.exists()).toBeTruthy();
expect(modal.vm.$attrs.csrfToken).toEqual('dummyCSRF');
expect(modal.vm.$attrs.extraProp).toEqual('extraPropValue');
@@ -64,68 +67,60 @@ describe('Users admin page Modal Manager', () => {
});
});
- describe('global listener', () => {
+ describe('click handling', () => {
+ let button;
+ let button2;
+
+ const createButtons = () => {
+ button = document.createElement('button');
+ button2 = document.createElement('button');
+ button.setAttribute('class', 'js-delete-user-modal-button');
+ button.setAttribute('data-username', 'foo');
+ button.setAttribute('data-gl-modal-action', 'action1');
+ button.setAttribute('data-block-user-url', '/block');
+ button.setAttribute('data-delete-user-url', '/delete');
+ document.body.appendChild(button);
+ document.body.appendChild(button2);
+ };
+ const removeButtons = () => {
+ button.remove();
+ button = null;
+ button2.remove();
+ button2 = null;
+ };
+
beforeEach(() => {
- jest.spyOn(document, 'addEventListener');
- jest.spyOn(document, 'removeEventListener');
+ createButtons();
+ createComponent();
});
- afterAll(() => {
- jest.restoreAllMocks();
+ afterEach(() => {
+ removeButtons();
});
- it('registers global listener on mount', () => {
- createComponent();
- expect(document.addEventListener).toHaveBeenCalledWith('click', expect.any(Function));
- });
+ it('renders the modal when the button is clicked', async () => {
+ button.click();
- it('removes global listener on destroy', () => {
- createComponent();
- wrapper.destroy();
- expect(document.removeEventListener).toHaveBeenCalledWith('click', expect.any(Function));
+ await wrapper.vm.$nextTick();
+
+ expect(findModal().exists()).toBe(true);
});
- });
- describe('click handling', () => {
- let node;
+ it('does not render the modal when a misconfigured button is clicked', async () => {
+ button.removeAttribute('data-gl-modal-action');
+ button.click();
- beforeEach(() => {
- node = document.createElement('div');
- document.body.appendChild(node);
- });
+ await wrapper.vm.$nextTick();
- afterEach(() => {
- node.remove();
- node = null;
+ expect(findModal().exists()).toBe(false);
});
- it('ignores wrong clicks', () => {
- createComponent();
- const event = new window.MouseEvent('click', {
- bubbles: true,
- cancellable: true,
- });
- jest.spyOn(event, 'preventDefault');
- node.dispatchEvent(event);
- expect(event.preventDefault).not.toHaveBeenCalled();
- });
+ it('does not render the modal when a button without the selector class is clicked', async () => {
+ button2.click();
- it('captures click with glModalAction', () => {
- createComponent();
- node.dataset.glModalAction = 'action1';
- const event = new window.MouseEvent('click', {
- bubbles: true,
- cancellable: true,
- });
- jest.spyOn(event, 'preventDefault');
- node.dispatchEvent(event);
+ await wrapper.vm.$nextTick();
- expect(event.preventDefault).toHaveBeenCalled();
- return wrapper.vm.$nextTick().then(() => {
- const modal = wrapper.find({ ref: 'modal' });
- expect(modal.exists()).toBeTruthy();
- expect(modal.vm.showWasCalled).toBeTruthy();
- });
+ expect(findModal().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
index fbe2274c40d..63c1260560b 100644
--- a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
+++ b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBanner } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
-import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue';
import axios from '~/lib/utils/axios_utils';
+import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue';
const svgPath = '/illustrations/background';
const provide = {
diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
index 5018b0c4f73..fb612f17669 100644
--- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js
+++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
@@ -1,10 +1,10 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
-import Todos from '~/pages/dashboard/todos/index/todos';
+import $ from 'jquery';
import '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
import { addDelimiter } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
+import Todos from '~/pages/dashboard/todos/index/todos';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrl'),
diff --git a/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js b/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js
index a91fc5abe09..7a8a249cb2a 100644
--- a/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js
+++ b/spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js
@@ -1,8 +1,8 @@
+import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlButton } from '@gitlab/ui';
-import BitbucketServerStatusTable from '~/pages/import/bitbucket_server/status/components/bitbucket_server_status_table.vue';
import BitbucketStatusTable from '~/import_entities/import_projects/components/bitbucket_status_table.vue';
+import BitbucketServerStatusTable from '~/pages/import/bitbucket_server/status/components/bitbucket_server_status_table.vue';
const BitbucketStatusTableStub = {
name: 'BitbucketStatusTable',
diff --git a/spec/frontend/pages/labels/components/promote_label_modal_spec.js b/spec/frontend/pages/labels/components/promote_label_modal_spec.js
index 19807313c77..4d5d1f98b59 100644
--- a/spec/frontend/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/frontend/pages/labels/components/promote_label_modal_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import axios from '~/lib/utils/axios_utils';
import promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue';
import eventHub from '~/pages/projects/labels/event_hub';
-import axios from '~/lib/utils/axios_utils';
describe('Promote label modal', () => {
let vm;
diff --git a/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js b/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js
index 7bb637356c2..1fbec0d996d 100644
--- a/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js
+++ b/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { TEST_HOST } from 'helpers/test_constants';
-import { redirectTo } from '~/lib/utils/url_utility';
+import mountComponent from 'helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils';
+import { redirectTo } from '~/lib/utils/url_utility';
import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
import eventHub from '~/pages/milestones/shared/event_hub';
diff --git a/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
index 7cd94deb3da..d22e0474e06 100644
--- a/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ b/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
@@ -1,12 +1,12 @@
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { TEST_HOST } from 'helpers/test_constants';
import { setHTMLFixture } from 'helpers/fixtures';
+import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-import PromoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
+import * as flash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
-import * as flash from '~/flash';
+import PromoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/flash');
diff --git a/spec/frontend/pages/projects/edit/mount_search_settings_spec.js b/spec/frontend/pages/projects/edit/mount_search_settings_spec.js
deleted file mode 100644
index b48809b3d00..00000000000
--- a/spec/frontend/pages/projects/edit/mount_search_settings_spec.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import initSearch from '~/search_settings';
-import mountSearchSettings from '~/pages/projects/edit/mount_search_settings';
-
-jest.mock('~/search_settings');
-
-describe('pages/projects/edit/mount_search_settings', () => {
- afterEach(() => {
- resetHTMLFixture();
- });
-
- it('initializes search settings when js-search-settings-app is available', async () => {
- setHTMLFixture('<div class="js-search-settings-app"></div>');
-
- await mountSearchSettings();
-
- expect(initSearch).toHaveBeenCalled();
- });
-
- it('does not initialize search settings when js-search-settings-app is unavailable', async () => {
- await mountSearchSettings();
-
- expect(initSearch).not.toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_item_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_item_spec.js
index b90c07a335b..b5425fa6f2e 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_item_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_item_spec.js
@@ -1,14 +1,10 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBadge, GlButton, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ForkGroupsListItem from '~/pages/projects/forks/new/components/fork_groups_list_item.vue';
describe('Fork groups list item component', () => {
let wrapper;
- const DEFAULT_PROPS = {
- hasReachedProjectLimit: false,
- };
-
const DEFAULT_GROUP_DATA = {
id: 22,
name: 'Gitlab Org',
@@ -33,7 +29,6 @@ describe('Fork groups list item component', () => {
const createWrapper = (propsData) => {
wrapper = shallowMount(ForkGroupsListItem, {
propsData: {
- ...DEFAULT_PROPS,
...propsData,
},
});
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
index 91740c7ce3b..e7ac837a4c8 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js
@@ -1,10 +1,10 @@
-import AxiosMockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import ForkGroupsList from '~/pages/projects/forks/new/components/fork_groups_list.vue';
import ForkGroupsListItem from '~/pages/projects/forks/new/components/fork_groups_list_item.vue';
@@ -16,7 +16,6 @@ describe('Fork groups list component', () => {
const DEFAULT_PROPS = {
endpoint: '/dummy',
- hasReachedProjectLimit: false,
};
const replyWith = (...args) => axiosMock.onGet(DEFAULT_PROPS.endpoint).reply(...args);
@@ -94,10 +93,9 @@ describe('Fork groups list component', () => {
it('renders list items for each available group', async () => {
const namespaces = [{ name: 'dummy1' }, { name: 'dummy2' }, { name: 'otherdummy' }];
- const hasReachedProjectLimit = true;
replyWith(200, { namespaces });
- createWrapper({ hasReachedProjectLimit });
+ createWrapper();
await waitForPromises();
@@ -106,7 +104,6 @@ describe('Fork groups list component', () => {
namespaces.forEach((namespace, idx) => {
expect(wrapper.findAll(ForkGroupsListItem).at(idx).props()).toStrictEqual({
group: namespace,
- hasReachedProjectLimit,
});
});
});
diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
index 4a60c7fd509..1f9029b40c7 100644
--- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js
+++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
@@ -1,13 +1,13 @@
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
import CodeCoverage from '~/pages/projects/graphs/components/code_coverage.vue';
import { codeCoverageMockData, sortedDataByDates } from './mock_data';
-import httpStatusCodes from '~/lib/utils/http_status';
describe('Code Coverage', () => {
let wrapper;
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
new file mode 100644
index 00000000000..c9141d13a46
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_a_spec.js.snap
@@ -0,0 +1,66 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Learn GitLab Design A should render the loading state 1`] = `
+<ul>
+ <li>
+ <span>
+ Create a repository
+ </span>
+ </li>
+ <li>
+ <span>
+ Invite your colleagues
+ </span>
+ </li>
+ <li>
+ <span>
+ Set-up CI/CD
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Start a free trial of GitLab Gold
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Add code owners
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Enable require merge approvals
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Submit a merge request (MR)
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Run a Security scan using CI/CD
+ </gl-link-stub>
+ </span>
+ </li>
+</ul>
+`;
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
new file mode 100644
index 00000000000..85e3b675e5b
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_b_spec.js.snap
@@ -0,0 +1,66 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Learn GitLab Design B should render the loading state 1`] = `
+<ul>
+ <li>
+ <span>
+ Create a repository
+ </span>
+ </li>
+ <li>
+ <span>
+ Invite your colleagues
+ </span>
+ </li>
+ <li>
+ <span>
+ Set-up CI/CD
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Start a free trial of GitLab Gold
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Add code owners
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Enable require merge approvals
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Submit a merge request (MR)
+ </gl-link-stub>
+ </span>
+ </li>
+ <li>
+ <span>
+ <gl-link-stub
+ href="http://example.com/"
+ >
+ Run a Security scan using CI/CD
+ </gl-link-stub>
+ </span>
+ </li>
+</ul>
+`;
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js
new file mode 100644
index 00000000000..ddc5339e7e0
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_a_spec.js
@@ -0,0 +1,63 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import LearnGitlabA from '~/pages/projects/learn_gitlab/components/learn_gitlab_a.vue';
+
+const TEST_ACTIONS = {
+ gitWrite: {
+ url: 'http://example.com/',
+ completed: true,
+ },
+ userAdded: {
+ url: 'http://example.com/',
+ completed: true,
+ },
+ pipelineCreated: {
+ url: 'http://example.com/',
+ completed: true,
+ },
+ trialStarted: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ codeOwnersEnabled: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ requiredMrApprovalsEnabled: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ mergeRequestCreated: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ securityScanEnabled: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+};
+
+describe('Learn GitLab Design A', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createWrapper = () => {
+ wrapper = extendedWrapper(
+ shallowMount(LearnGitlabA, {
+ propsData: {
+ actions: TEST_ACTIONS,
+ },
+ }),
+ );
+ };
+
+ it('should render the loading state', () => {
+ createWrapper();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js
new file mode 100644
index 00000000000..be4f5768402
--- /dev/null
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_b_spec.js
@@ -0,0 +1,63 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import LearnGitlabA from '~/pages/projects/learn_gitlab/components/learn_gitlab_a.vue';
+
+const TEST_ACTIONS = {
+ gitWrite: {
+ url: 'http://example.com/',
+ completed: true,
+ },
+ userAdded: {
+ url: 'http://example.com/',
+ completed: true,
+ },
+ pipelineCreated: {
+ url: 'http://example.com/',
+ completed: true,
+ },
+ trialStarted: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ codeOwnersEnabled: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ requiredMrApprovalsEnabled: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ mergeRequestCreated: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+ securityScanEnabled: {
+ url: 'http://example.com/',
+ completed: false,
+ },
+};
+
+describe('Learn GitLab Design B', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const createWrapper = () => {
+ wrapper = extendedWrapper(
+ shallowMount(LearnGitlabA, {
+ propsData: {
+ actions: TEST_ACTIONS,
+ },
+ }),
+ );
+ };
+
+ it('should render the loading state', () => {
+ createWrapper();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/pages/projects/merge_requests/edit/check_form_state_spec.js b/spec/frontend/pages/projects/merge_requests/edit/check_form_state_spec.js
new file mode 100644
index 00000000000..ea49111760b
--- /dev/null
+++ b/spec/frontend/pages/projects/merge_requests/edit/check_form_state_spec.js
@@ -0,0 +1,41 @@
+import initCheckFormState from '~/pages/projects/merge_requests/edit/check_form_state';
+
+describe('Check form state', () => {
+ const findInput = () => document.querySelector('#form-input');
+
+ let beforeUnloadEvent;
+ let setDialogContent;
+
+ beforeEach(() => {
+ setFixtures(`
+ <form class="merge-request-form">
+ <input type="text" name="test" id="form-input"/>
+ </form>`);
+
+ beforeUnloadEvent = new Event('beforeunload');
+ jest.spyOn(beforeUnloadEvent, 'preventDefault');
+ setDialogContent = jest.spyOn(beforeUnloadEvent, 'returnValue', 'set');
+
+ initCheckFormState();
+ });
+
+ afterEach(() => {
+ beforeUnloadEvent.preventDefault.mockRestore();
+ setDialogContent.mockRestore();
+ });
+
+ it('shows confirmation dialog when there are unsaved changes', () => {
+ findInput().value = 'value changed';
+ window.dispatchEvent(beforeUnloadEvent);
+
+ expect(beforeUnloadEvent.preventDefault).toHaveBeenCalled();
+ expect(setDialogContent).toHaveBeenCalledWith('');
+ });
+
+ it('does not show confirmation dialog when there are no unsaved changes', () => {
+ window.dispatchEvent(beforeUnloadEvent);
+
+ expect(beforeUnloadEvent.preventDefault).not.toHaveBeenCalled();
+ expect(setDialogContent).not.toHaveBeenCalled();
+ });
+});
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 cfe54016410..5fed9fcaad2 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,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue';
diff --git a/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js b/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js
index c90ebd47b08..0fffcf433a3 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js
@@ -1,7 +1,6 @@
-import { mount, shallowMount } from '@vue/test-utils';
-
-import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
-import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
+import { GlToggle } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import ProjectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
describe('Project Feature Settings', () => {
const defaultProps = {
@@ -19,81 +18,76 @@ describe('Project Feature Settings', () => {
};
let wrapper;
- const mountComponent = (customProps) => {
- const propsData = { ...defaultProps, ...customProps };
- return shallowMount(projectFeatureSetting, { propsData });
- };
+ const findHiddenInput = () => wrapper.find(`input[name=${defaultProps.name}]`);
+ const findToggle = () => wrapper.findComponent(GlToggle);
- beforeEach(() => {
- wrapper = mountComponent();
- });
+ const mountComponent = (customProps = {}) =>
+ shallowMount(ProjectFeatureSetting, {
+ propsData: {
+ ...defaultProps,
+ ...customProps,
+ },
+ });
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
});
describe('Hidden name input', () => {
it('should set the hidden name input if the name exists', () => {
- expect(wrapper.find(`input[name=${defaultProps.name}]`).attributes().value).toBe('1');
+ wrapper = mountComponent();
+
+ expect(findHiddenInput().attributes('value')).toBe('1');
});
it('should not set the hidden name input if the name does not exist', () => {
- wrapper.setProps({ name: null });
+ wrapper = mountComponent({ name: null });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(`input[name=${defaultProps.name}]`).exists()).toBe(false);
- });
+ expect(findHiddenInput().exists()).toBe(false);
});
});
describe('Feature toggle', () => {
- it('should be hidden if "showToggle" is passed false', async () => {
- wrapper.setProps({ showToggle: false });
-
- await wrapper.vm.$nextTick();
+ it('should be hidden if "showToggle" is passed false', () => {
+ wrapper = mountComponent({ showToggle: false });
- expect(wrapper.find(projectFeatureToggle).element).toBeUndefined();
+ expect(findToggle().exists()).toBe(false);
});
it('should enable the feature toggle if the value is not 0', () => {
- expect(wrapper.find(projectFeatureToggle).props().value).toBe(true);
+ wrapper = mountComponent();
+
+ expect(findToggle().props('value')).toBe(true);
});
it('should enable the feature toggle if the value is less than 0', () => {
- wrapper.setProps({ value: -1 });
+ wrapper = mountComponent({ value: -1 });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(projectFeatureToggle).props().value).toBe(true);
- });
+ expect(findToggle().props('value')).toBe(true);
});
it('should disable the feature toggle if the value is 0', () => {
- wrapper.setProps({ value: 0 });
+ wrapper = mountComponent({ value: 0 });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(projectFeatureToggle).props().value).toBe(false);
- });
+ expect(findToggle().props('value')).toBe(false);
});
it('should disable the feature toggle if disabledInput is set', () => {
- wrapper.setProps({ disabledInput: true });
+ wrapper = mountComponent({ disabledInput: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find(projectFeatureToggle).props().disabledInput).toBe(true);
- });
+ expect(findToggle().props('disabled')).toBe(true);
});
it('should emit a change event when the feature toggle changes', () => {
- // Needs to be fully mounted to be able to trigger the click event on the internal button
- wrapper = mount(projectFeatureSetting, { propsData: defaultProps });
+ wrapper = mountComponent({ propsData: defaultProps });
+
+ expect(wrapper.emitted('change')).toBeUndefined();
- expect(wrapper.emitted().change).toBeUndefined();
- wrapper.find(projectFeatureToggle).find('button').trigger('click');
+ findToggle().vm.$emit('change', false);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().change.length).toBe(1);
- expect(wrapper.emitted().change[0]).toEqual([0]);
- });
+ expect(wrapper.emitted('change')).toHaveLength(1);
+ expect(wrapper.emitted('change')[0]).toEqual([0]);
});
});
@@ -108,26 +102,23 @@ describe('Project Feature Settings', () => {
`(
'should set disabled to $isDisabled when disabledInput is $disabledInput, the value is $value and options are $options',
({ disabledInput, value, options, isDisabled }) => {
- wrapper.setProps({ disabledInput, value, options });
-
- return wrapper.vm.$nextTick(() => {
- if (isDisabled) {
- expect(wrapper.find('select').attributes().disabled).toEqual('disabled');
- } else {
- expect(wrapper.find('select').attributes().disabled).toBeUndefined();
- }
- });
+ wrapper = mountComponent({ disabledInput, value, options });
+
+ const expected = isDisabled ? 'disabled' : undefined;
+
+ expect(wrapper.find('select').attributes('disabled')).toBe(expected);
},
);
it('should emit the change when a new option is selected', () => {
- expect(wrapper.emitted().change).toBeUndefined();
+ wrapper = mountComponent();
+
+ expect(wrapper.emitted('change')).toBeUndefined();
+
wrapper.findAll('option').at(1).trigger('change');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().change.length).toBe(1);
- expect(wrapper.emitted().change[0]).toEqual([2]);
- });
+ expect(wrapper.emitted('change')).toHaveLength(1);
+ expect(wrapper.emitted('change')[0]).toEqual([2]);
});
});
});
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 9aee6ec7ace..d7c754fd3cc 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
@@ -1,13 +1,12 @@
+import { GlToggle } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-
+import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
import settingsPanel from '~/pages/projects/shared/permissions/components/settings_panel.vue';
import {
featureAccessLevel,
visibilityLevelDescriptions,
visibilityOptions,
} from '~/pages/projects/shared/permissions/constants';
-import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
-import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
const defaultProps = {
currentSettings: {
@@ -69,57 +68,61 @@ describe('Settings Panel', () => {
});
};
- const overrideCurrentSettings = (
- currentSettingsProps,
- extraProps = {},
- mountFn = shallowMount,
- ) => {
- return mountComponent({ ...extraProps, currentSettings: currentSettingsProps }, mountFn);
- };
-
const findLFSSettingsRow = () => wrapper.find({ ref: 'git-lfs-settings' });
const findLFSSettingsMessage = () => findLFSSettingsRow().find('p');
- const findLFSFeatureToggle = () => findLFSSettingsRow().find(projectFeatureToggle);
-
+ const findLFSFeatureToggle = () => findLFSSettingsRow().find(GlToggle);
const findRepositoryFeatureProjectRow = () => wrapper.find({ ref: 'repository-settings' });
const findRepositoryFeatureSetting = () =>
findRepositoryFeatureProjectRow().find(projectFeatureSetting);
-
+ const findProjectVisibilitySettings = () => wrapper.find({ ref: 'project-visibility-settings' });
const findAnalyticsRow = () => wrapper.find({ ref: 'analytics-settings' });
-
- beforeEach(() => {
- wrapper = mountComponent();
- });
+ const findProjectVisibilityLevelInput = () => wrapper.find('[name="project[visibility_level]"]');
+ const findRequestAccessEnabledInput = () =>
+ wrapper.find('[name="project[request_access_enabled]"]');
+ const findMergeRequestsAccessLevelInput = () =>
+ wrapper.find('[name="project[project_feature_attributes][merge_requests_access_level]"]');
+ const findForkingAccessLevelInput = () =>
+ wrapper.find('[name="project[project_feature_attributes][forking_access_level]"]');
+ const findBuildsAccessLevelInput = () =>
+ wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]');
+ const findContainerRegistrySettings = () => wrapper.find({ ref: 'container-registry-settings' });
+ const findContainerRegistryEnabledInput = () =>
+ wrapper.find('[name="project[container_registry_enabled]"]');
+ const findPackageSettings = () => wrapper.find({ ref: 'package-settings' });
+ const findPackagesEnabledInput = () => wrapper.find('[name="project[packages_enabled]"]');
+ const findPagesSettings = () => wrapper.find({ ref: 'pages-settings' });
+ const findEmailSettings = () => wrapper.find({ ref: 'email-settings' });
+ const findShowDefaultAwardEmojis = () =>
+ wrapper.find('input[name="project[project_setting_attributes][show_default_award_emojis]"]');
+ const findMetricsVisibilitySettings = () => wrapper.find({ ref: 'metrics-visibility-settings' });
+ const findAllowEditingCommitMessages = () =>
+ wrapper.find({ ref: 'allow-editing-commit-messages' }).exists();
+ const findOperationsSettings = () => wrapper.find({ ref: 'operations-settings' });
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
});
describe('Project Visibility', () => {
it('should set the project visibility help path', () => {
- expect(wrapper.find({ ref: 'project-visibility-settings' }).props().helpPath).toBe(
+ wrapper = mountComponent();
+
+ expect(findProjectVisibilitySettings().props('helpPath')).toBe(
defaultProps.visibilityHelpPath,
);
});
it('should not disable the visibility level dropdown', () => {
- wrapper.setProps({ canChangeVisibilityLevel: true });
+ wrapper = mountComponent({ canChangeVisibilityLevel: true });
- return wrapper.vm.$nextTick(() => {
- expect(
- wrapper.find('[name="project[visibility_level]"]').attributes().disabled,
- ).toBeUndefined();
- });
+ expect(findProjectVisibilityLevelInput().attributes('disabled')).toBeUndefined();
});
it('should disable the visibility level dropdown', () => {
- wrapper.setProps({ canChangeVisibilityLevel: false });
+ wrapper = mountComponent({ canChangeVisibilityLevel: false });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('[name="project[visibility_level]"]').attributes().disabled).toBe(
- 'disabled',
- );
- });
+ expect(findProjectVisibilityLevelInput().attributes('disabled')).toBe('disabled');
});
it.each`
@@ -133,232 +136,209 @@ describe('Settings Panel', () => {
`(
'sets disabled to $disabled for the visibility option $option when given $allowedOptions',
({ option, allowedOptions, disabled }) => {
- wrapper.setProps({ allowedVisibilityOptions: allowedOptions });
-
- return wrapper.vm.$nextTick(() => {
- const attributeValue = wrapper
- .find(`[name="project[visibility_level]"] option[value="${option}"]`)
- .attributes().disabled;
-
- if (disabled) {
- expect(attributeValue).toBe('disabled');
- } else {
- expect(attributeValue).toBeUndefined();
- }
- });
+ wrapper = mountComponent({ allowedVisibilityOptions: allowedOptions });
+
+ const attributeValue = findProjectVisibilityLevelInput()
+ .find(`option[value="${option}"]`)
+ .attributes('disabled');
+
+ const expected = disabled ? 'disabled' : undefined;
+
+ expect(attributeValue).toBe(expected);
},
);
it('should set the visibility level description based upon the selected visibility level', () => {
- wrapper.find('[name="project[visibility_level]"]').setValue(visibilityOptions.INTERNAL);
+ wrapper = mountComponent();
+
+ findProjectVisibilityLevelInput().setValue(visibilityOptions.INTERNAL);
- expect(wrapper.find({ ref: 'project-visibility-settings' }).text()).toContain(
+ expect(findProjectVisibilitySettings().text()).toContain(
visibilityLevelDescriptions[visibilityOptions.INTERNAL],
);
});
it('should show the request access checkbox if the visibility level is not private', () => {
- wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.INTERNAL });
+ wrapper = mountComponent({
+ currentSettings: { visibilityLevel: visibilityOptions.INTERNAL },
+ });
- expect(wrapper.find('[name="project[request_access_enabled]"]').exists()).toBe(true);
+ expect(findRequestAccessEnabledInput().exists()).toBe(true);
});
it('should not show the request access checkbox if the visibility level is private', () => {
- wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PRIVATE });
+ wrapper = mountComponent({ currentSettings: { visibilityLevel: visibilityOptions.PRIVATE } });
- expect(wrapper.find('[name="project[request_access_enabled]"]').exists()).toBe(false);
+ expect(findRequestAccessEnabledInput().exists()).toBe(false);
});
});
describe('Repository', () => {
it('should set the repository help text when the visibility level is set to private', () => {
- wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PRIVATE });
+ wrapper = mountComponent({ currentSettings: { visibilityLevel: visibilityOptions.PRIVATE } });
- expect(findRepositoryFeatureProjectRow().props().helpText).toBe(
- 'View and edit files in this project',
+ expect(findRepositoryFeatureProjectRow().props('helpText')).toBe(
+ 'View and edit files in this project.',
);
});
it('should set the repository help text with a read access warning when the visibility level is set to non-private', () => {
- wrapper = overrideCurrentSettings({ visibilityLevel: visibilityOptions.PUBLIC });
+ 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',
+ expect(findRepositoryFeatureProjectRow().props('helpText')).toBe(
+ 'View and edit files in this project. Non-project members will only have read access.',
);
});
});
describe('Merge requests', () => {
it('should enable the merge requests access level input when the repository is enabled', () => {
- wrapper = overrideCurrentSettings({ repositoryAccessLevel: featureAccessLevel.EVERYONE });
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ });
- expect(
- wrapper
- .find('[name="project[project_feature_attributes][merge_requests_access_level]"]')
- .props().disabledInput,
- ).toBe(false);
+ expect(findMergeRequestsAccessLevelInput().props('disabledInput')).toBe(false);
});
it('should disable the merge requests access level input when the repository is disabled', () => {
- wrapper = overrideCurrentSettings({ repositoryAccessLevel: featureAccessLevel.NOT_ENABLED });
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
+ });
- expect(
- wrapper
- .find('[name="project[project_feature_attributes][merge_requests_access_level]"]')
- .props().disabledInput,
- ).toBe(true);
+ expect(findMergeRequestsAccessLevelInput().props('disabledInput')).toBe(true);
});
});
describe('Forks', () => {
it('should enable the forking access level input when the repository is enabled', () => {
- wrapper = overrideCurrentSettings({ repositoryAccessLevel: featureAccessLevel.EVERYONE });
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ });
- expect(
- wrapper.find('[name="project[project_feature_attributes][forking_access_level]"]').props()
- .disabledInput,
- ).toBe(false);
+ expect(findForkingAccessLevelInput().props('disabledInput')).toBe(false);
});
it('should disable the forking access level input when the repository is disabled', () => {
- wrapper = overrideCurrentSettings({ repositoryAccessLevel: featureAccessLevel.NOT_ENABLED });
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
+ });
- expect(
- wrapper.find('[name="project[project_feature_attributes][forking_access_level]"]').props()
- .disabledInput,
- ).toBe(true);
+ expect(findForkingAccessLevelInput().props('disabledInput')).toBe(true);
});
});
describe('Pipelines', () => {
it('should enable the builds access level input when the repository is enabled', () => {
- wrapper = overrideCurrentSettings({ repositoryAccessLevel: featureAccessLevel.EVERYONE });
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ });
- expect(
- wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]').props()
- .disabledInput,
- ).toBe(false);
+ expect(findBuildsAccessLevelInput().props('disabledInput')).toBe(false);
});
it('should disable the builds access level input when the repository is disabled', () => {
- wrapper = overrideCurrentSettings({ repositoryAccessLevel: featureAccessLevel.NOT_ENABLED });
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
+ });
- expect(
- wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]').props()
- .disabledInput,
- ).toBe(true);
+ expect(findBuildsAccessLevelInput().props('disabledInput')).toBe(true);
});
});
describe('Container registry', () => {
it('should show the container registry settings if the registry is available', () => {
- wrapper.setProps({ registryAvailable: true });
+ wrapper = mountComponent({ registryAvailable: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'container-registry-settings' }).exists()).toBe(true);
- });
+ expect(findContainerRegistrySettings().exists()).toBe(true);
});
it('should hide the container registry settings if the registry is not available', () => {
- wrapper.setProps({ registryAvailable: false });
+ wrapper = mountComponent({ registryAvailable: false });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'container-registry-settings' }).exists()).toBe(false);
- });
+ expect(findContainerRegistrySettings().exists()).toBe(false);
});
it('should set the container registry settings help path', () => {
- wrapper.setProps({ registryAvailable: true });
+ wrapper = mountComponent({ registryAvailable: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'container-registry-settings' }).props().helpPath).toBe(
- defaultProps.registryHelpPath,
- );
- });
+ expect(findContainerRegistrySettings().props('helpPath')).toBe(defaultProps.registryHelpPath);
});
it('should show the container registry public note if the visibility level is public and the registry is available', () => {
- wrapper = overrideCurrentSettings(
- { visibilityLevel: visibilityOptions.PUBLIC },
- { registryAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { visibilityLevel: visibilityOptions.PUBLIC },
+ registryAvailable: true,
+ });
- expect(wrapper.find({ ref: 'container-registry-settings' }).text()).toContain(
+ expect(findContainerRegistrySettings().text()).toContain(
'Note: the container registry is always visible when a project is public',
);
});
it('should hide the container registry public note if the visibility level is private and the registry is available', () => {
- wrapper = overrideCurrentSettings(
- { visibilityLevel: visibilityOptions.PRIVATE },
- { registryAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { visibilityLevel: visibilityOptions.PRIVATE },
+ registryAvailable: true,
+ });
- expect(wrapper.find({ ref: 'container-registry-settings' }).text()).not.toContain(
+ expect(findContainerRegistrySettings().text()).not.toContain(
'Note: the container registry is always visible when a project is public',
);
});
it('should enable the container registry input when the repository is enabled', () => {
- wrapper = overrideCurrentSettings(
- { repositoryAccessLevel: featureAccessLevel.EVERYONE },
- { registryAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ registryAvailable: true,
+ });
- expect(
- wrapper.find('[name="project[container_registry_enabled]"]').props().disabledInput,
- ).toBe(false);
+ expect(findContainerRegistryEnabledInput().props('disabled')).toBe(false);
});
it('should disable the container registry input when the repository is disabled', () => {
- wrapper = overrideCurrentSettings(
- { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
- { registryAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
+ registryAvailable: true,
+ });
- expect(
- wrapper.find('[name="project[container_registry_enabled]"]').props().disabledInput,
- ).toBe(true);
+ expect(findContainerRegistryEnabledInput().props('disabled')).toBe(true);
});
});
describe('Git Large File Storage', () => {
it('should show the LFS settings if LFS is available', () => {
- wrapper.setProps({ lfsAvailable: true });
+ wrapper = mountComponent({ lfsAvailable: true });
- return wrapper.vm.$nextTick(() => {
- expect(findLFSSettingsRow().exists()).toBe(true);
- });
+ expect(findLFSSettingsRow().exists()).toBe(true);
});
it('should hide the LFS settings if LFS is not available', () => {
- wrapper.setProps({ lfsAvailable: false });
+ wrapper = mountComponent({ lfsAvailable: false });
- return wrapper.vm.$nextTick(() => {
- expect(findLFSSettingsRow().exists()).toBe(false);
- });
+ expect(findLFSSettingsRow().exists()).toBe(false);
});
it('should set the LFS settings help path', () => {
- expect(findLFSSettingsRow().props().helpPath).toBe(defaultProps.lfsHelpPath);
+ wrapper = mountComponent();
+ expect(findLFSSettingsRow().props('helpPath')).toBe(defaultProps.lfsHelpPath);
});
it('should enable the LFS input when the repository is enabled', () => {
- wrapper = overrideCurrentSettings(
- { repositoryAccessLevel: featureAccessLevel.EVERYONE },
- { lfsAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ lfsAvailable: true,
+ });
- expect(findLFSFeatureToggle().props().disabledInput).toBe(false);
+ expect(findLFSFeatureToggle().props('disabled')).toBe(false);
});
it('should disable the LFS input when the repository is disabled', () => {
- wrapper = overrideCurrentSettings(
- { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
- { lfsAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
+ lfsAvailable: true,
+ });
- expect(findLFSFeatureToggle().props().disabledInput).toBe(true);
+ expect(findLFSFeatureToggle().props('disabled')).toBe(true);
});
it('should not change lfsEnabled when disabling the repository', async () => {
@@ -373,8 +353,7 @@ describe('Settings Panel', () => {
expect(isToggleButtonChecked(lfsFeatureToggleButton)).toBe(true);
expect(isToggleButtonChecked(repositoryFeatureToggleButton)).toBe(true);
- repositoryFeatureToggleButton.trigger('click');
- await wrapper.vm.$nextTick();
+ await repositoryFeatureToggleButton.trigger('click');
expect(isToggleButtonChecked(repositoryFeatureToggleButton)).toBe(false);
// LFS toggle should still be checked
@@ -400,7 +379,7 @@ describe('Settings Panel', () => {
const link = message.find('a');
expect(message.text()).toContain(
- 'LFS objects from this repository are still available to forks',
+ 'LFS objects from this repository are available to forks.',
);
expect(link.text()).toBe('How do I remove them?');
expect(link.attributes('href')).toBe(
@@ -418,47 +397,39 @@ describe('Settings Panel', () => {
describe('Packages', () => {
it('should show the packages settings if packages are available', () => {
- wrapper.setProps({ packagesAvailable: true });
+ wrapper = mountComponent({ packagesAvailable: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'package-settings' }).exists()).toBe(true);
- });
+ expect(findPackageSettings().exists()).toBe(true);
});
it('should hide the packages settings if packages are not available', () => {
- wrapper.setProps({ packagesAvailable: false });
+ wrapper = mountComponent({ packagesAvailable: false });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'package-settings' }).exists()).toBe(false);
- });
+ expect(findPackageSettings().exists()).toBe(false);
});
it('should set the package settings help path', () => {
- wrapper.setProps({ packagesAvailable: true });
+ wrapper = mountComponent({ packagesAvailable: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'package-settings' }).props().helpPath).toBe(
- defaultProps.packagesHelpPath,
- );
- });
+ expect(findPackageSettings().props('helpPath')).toBe(defaultProps.packagesHelpPath);
});
it('should enable the packages input when the repository is enabled', () => {
- wrapper = overrideCurrentSettings(
- { repositoryAccessLevel: featureAccessLevel.EVERYONE },
- { packagesAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.EVERYONE },
+ packagesAvailable: true,
+ });
- expect(wrapper.find('[name="project[packages_enabled]"]').props().disabledInput).toBe(false);
+ expect(findPackagesEnabledInput().props('disabled')).toBe(false);
});
it('should disable the packages input when the repository is disabled', () => {
- wrapper = overrideCurrentSettings(
- { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
- { packagesAvailable: true },
- );
+ wrapper = mountComponent({
+ currentSettings: { repositoryAccessLevel: featureAccessLevel.NOT_ENABLED },
+ packagesAvailable: true,
+ });
- expect(wrapper.find('[name="project[packages_enabled]"]').props().disabledInput).toBe(true);
+ expect(findPackagesEnabledInput().props('disabled')).toBe(true);
});
});
@@ -472,78 +443,66 @@ describe('Settings Panel', () => {
`(
'should $visibility the page settings if pagesAvailable is $pagesAvailable and pagesAccessControlEnabled is $pagesAccessControlEnabled',
({ pagesAvailable, pagesAccessControlEnabled, visibility }) => {
- wrapper.setProps({ pagesAvailable, pagesAccessControlEnabled });
+ wrapper = mountComponent({ pagesAvailable, pagesAccessControlEnabled });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'pages-settings' }).exists()).toBe(visibility === 'show');
- });
+ expect(findPagesSettings().exists()).toBe(visibility === 'show');
},
);
it('should set the pages settings help path', () => {
- wrapper.setProps({ pagesAvailable: true, pagesAccessControlEnabled: true });
+ wrapper = mountComponent({ pagesAvailable: true, pagesAccessControlEnabled: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'pages-settings' }).props().helpPath).toBe(
- defaultProps.pagesHelpPath,
- );
- });
+ expect(findPagesSettings().props('helpPath')).toBe(defaultProps.pagesHelpPath);
});
});
describe('Email notifications', () => {
it('should show the disable email notifications input if emails an be disabled', () => {
- wrapper.setProps({ canDisableEmails: true });
+ wrapper = mountComponent({ canDisableEmails: true });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'email-settings' }).exists()).toBe(true);
- });
+ expect(findEmailSettings().exists()).toBe(true);
});
it('should hide the disable email notifications input if emails cannot be disabled', () => {
- wrapper.setProps({ canDisableEmails: false });
+ wrapper = mountComponent({ canDisableEmails: false });
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'email-settings' }).exists()).toBe(false);
- });
+ expect(findEmailSettings().exists()).toBe(false);
});
});
describe('Default award emojis', () => {
it('should show the "Show default award emojis" input', () => {
- return wrapper.vm.$nextTick(() => {
- expect(
- wrapper
- .find('input[name="project[project_setting_attributes][show_default_award_emojis]"]')
- .exists(),
- ).toBe(true);
- });
+ wrapper = mountComponent();
+
+ expect(findShowDefaultAwardEmojis().exists()).toBe(true);
});
});
describe('Metrics dashboard', () => {
it('should show the metrics dashboard access toggle', () => {
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ ref: 'metrics-visibility-settings' }).exists()).toBe(true);
- });
+ wrapper = mountComponent();
+
+ expect(findMetricsVisibilitySettings().exists()).toBe(true);
});
it('should contain help text', () => {
- expect(wrapper.find({ ref: 'metrics-visibility-settings' }).props().helpText).toBe(
- 'With Metrics Dashboard you can visualize this project performance metrics',
+ wrapper = mountComponent();
+
+ expect(findMetricsVisibilitySettings().props('helpText')).toBe(
+ "Visualize the project's performance metrics.",
);
});
it.each`
- scenario | selectedOption | selectedOptionLabel
- ${{ visibilityLevel: visibilityOptions.PRIVATE }} | ${String(featureAccessLevel.PROJECT_MEMBERS)} | ${'Only Project Members'}
- ${{ operationsAccessLevel: featureAccessLevel.NOT_ENABLED }} | ${String(featureAccessLevel.NOT_ENABLED)} | ${'Enable feature to choose access level'}
+ scenario | selectedOption | selectedOptionLabel
+ ${{ currentSettings: { visibilityLevel: visibilityOptions.PRIVATE } }} | ${String(featureAccessLevel.PROJECT_MEMBERS)} | ${'Only Project Members'}
+ ${{ currentSettings: { operationsAccessLevel: featureAccessLevel.NOT_ENABLED } }} | ${String(featureAccessLevel.NOT_ENABLED)} | ${'Enable feature to choose access level'}
`(
'should disable the metrics visibility dropdown when #scenario',
({ scenario, selectedOption, selectedOptionLabel }) => {
- wrapper = overrideCurrentSettings(scenario, {}, mount);
+ wrapper = mountComponent(scenario, mount);
- const select = wrapper.find({ ref: 'metrics-visibility-settings' }).find('select');
+ const select = findMetricsVisibilitySettings().find('select');
const option = select.find('option');
expect(select.attributes('disabled')).toBe('disabled');
@@ -556,31 +515,29 @@ describe('Settings Panel', () => {
describe('Settings panel with feature flags', () => {
describe('Allow edit of commit message', () => {
- it('should show the allow editing of commit messages checkbox', async () => {
+ it('should show the allow editing of commit messages checkbox', () => {
wrapper = mountComponent({
glFeatures: { allowEditingCommitMessages: true },
});
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find({ ref: 'allow-editing-commit-messages' }).exists()).toBe(true);
+ expect(findAllowEditingCommitMessages()).toBe(true);
});
});
});
describe('Analytics', () => {
- it('should show the analytics toggle', async () => {
- await wrapper.vm.$nextTick();
+ it('should show the analytics toggle', () => {
+ wrapper = mountComponent();
expect(findAnalyticsRow().exists()).toBe(true);
});
});
describe('Operations', () => {
- it('should show the operations toggle', async () => {
- await wrapper.vm.$nextTick();
+ it('should show the operations toggle', () => {
+ wrapper = mountComponent();
- expect(wrapper.find({ ref: 'operations-settings' }).exists()).toBe(true);
+ expect(findOperationsSettings().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/performance_bar/components/detailed_metric_spec.js b/spec/frontend/performance_bar/components/detailed_metric_spec.js
index 754ffcc12e3..6ddd047d549 100644
--- a/spec/frontend/performance_bar/components/detailed_metric_spec.js
+++ b/spec/frontend/performance_bar/components/detailed_metric_spec.js
@@ -1,5 +1,5 @@
-import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import DetailedMetric from '~/performance_bar/components/detailed_metric.vue';
import RequestWarning from '~/performance_bar/components/request_warning.vue';
diff --git a/spec/frontend/persistent_user_callout_spec.js b/spec/frontend/persistent_user_callout_spec.js
index 578fd8d836a..403142d7ff7 100644
--- a/spec/frontend/persistent_user_callout_spec.js
+++ b/spec/frontend/persistent_user_callout_spec.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import PersistentUserCallout from '~/persistent_user_callout';
-import { deprecatedCreateFlash as Flash } from '~/flash';
jest.mock('~/flash');
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
index aae25a3aa6d..5dae77a4626 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlFormInput, GlFormTextarea } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import { mockCommitMessage, mockDefaultBranch } from '../../mock_data';
-describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
+describe('Pipeline Editor | Commit Form', () => {
let wrapper;
const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
@@ -21,8 +21,8 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
});
};
- const findCommitTextarea = () => wrapper.find(GlFormTextarea);
- const findBranchInput = () => wrapper.find(GlFormInput);
+ const findCommitTextarea = () => wrapper.findComponent(GlFormTextarea);
+ const findBranchInput = () => wrapper.findComponent(GlFormInput);
const findNewMrCheckbox = () => wrapper.find('[data-testid="new-mr-checkbox"]');
const findSubmitBtn = () => wrapper.find('[type="submit"]');
const findCancelBtn = () => wrapper.find('[type="reset"]');
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
new file mode 100644
index 00000000000..b87ff6ec0de
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -0,0 +1,223 @@
+import { GlFormTextarea, GlFormInput, GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+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_SUCCESS } from '~/pipeline_editor/constants';
+import commitCreate from '~/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql';
+
+import {
+ mockCiConfigPath,
+ mockCiYml,
+ mockCommitSha,
+ mockCommitNextSha,
+ mockCommitMessage,
+ mockDefaultBranch,
+ mockProjectFullPath,
+ mockNewMergeRequestPath,
+} from '../../mock_data';
+
+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 = {
+ projectPath: mockProjectFullPath,
+ startBranch: mockDefaultBranch,
+ message: mockCommitMessage,
+ filePath: mockCiConfigPath,
+ content: mockCiYml,
+ lastCommitId: mockCommitSha,
+};
+
+const mockProvide = {
+ ciConfigPath: mockCiConfigPath,
+ defaultBranch: mockDefaultBranch,
+ projectFullPath: mockProjectFullPath,
+ newMergeRequestPath: mockNewMergeRequestPath,
+};
+
+describe('Pipeline Editor | Commit section', () => {
+ let wrapper;
+ let mockMutate;
+
+ const defaultProps = { ciFileContent: mockCiYml };
+
+ const createComponent = ({ props = {}, options = {}, provide = {} } = {}) => {
+ mockMutate = jest.fn().mockResolvedValue({
+ data: {
+ commitCreate: {
+ errors: [],
+ commit: {
+ sha: mockCommitNextSha,
+ },
+ },
+ },
+ });
+
+ wrapper = mount(CommitSection, {
+ propsData: { ...defaultProps, ...props },
+ provide: { ...mockProvide, ...provide },
+ data() {
+ return {
+ commitSha: mockCommitSha,
+ };
+ },
+ mocks: {
+ $apollo: {
+ mutate: mockMutate,
+ },
+ },
+ attachTo: document.body,
+ ...options,
+ });
+ };
+
+ const findCommitForm = () => wrapper.findComponent(CommitForm);
+ const findCommitBtnLoadingIcon = () =>
+ wrapper.find('[type="submit"]').findComponent(GlLoadingIcon);
+
+ const submitCommit = async ({
+ message = mockCommitMessage,
+ branch = mockDefaultBranch,
+ openMergeRequest = false,
+ } = {}) => {
+ await findCommitForm().findComponent(GlFormTextarea).setValue(message);
+ await findCommitForm().findComponent(GlFormInput).setValue(branch);
+ if (openMergeRequest) {
+ await findCommitForm().find('[data-testid="new-mr-checkbox"]').setChecked(openMergeRequest);
+ }
+ await findCommitForm().find('[type="submit"]').trigger('click');
+ // Simulate the write to local cache that occurs after a commit
+ await wrapper.setData({ commitSha: mockCommitNextSha });
+ };
+
+ const cancelCommitForm = async () => {
+ const findCancelBtn = () => wrapper.find('[type="reset"]');
+ await findCancelBtn().trigger('click');
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ mockMutate.mockReset();
+
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when the user commits changes to the current branch', () => {
+ beforeEach(async () => {
+ await submitCommit();
+ });
+
+ it('calls the mutation with the default branch', () => {
+ expect(mockMutate).toHaveBeenCalledTimes(1);
+ expect(mockMutate).toHaveBeenCalledWith({
+ mutation: commitCreate,
+ update: expect.any(Function),
+ variables: {
+ ...mockVariables,
+ branch: mockDefaultBranch,
+ },
+ });
+ });
+
+ it('emits an event to communicate the commit was successful', () => {
+ expect(wrapper.emitted('commit')).toHaveLength(1);
+ expect(wrapper.emitted('commit')[0]).toEqual([{ type: COMMIT_SUCCESS }]);
+ });
+
+ it('shows no saving state', () => {
+ expect(findCommitBtnLoadingIcon().exists()).toBe(false);
+ });
+
+ it('a second commit submits the latest sha, keeping the form updated', async () => {
+ await submitCommit();
+
+ expect(mockMutate).toHaveBeenCalledTimes(2);
+ expect(mockMutate).toHaveBeenCalledWith({
+ mutation: commitCreate,
+ update: expect.any(Function),
+ variables: {
+ ...mockVariables,
+ lastCommitId: mockCommitNextSha,
+ branch: mockDefaultBranch,
+ },
+ });
+ });
+ });
+
+ describe('when the user commits changes to a new branch', () => {
+ const newBranch = 'new-branch';
+
+ beforeEach(async () => {
+ await submitCommit({
+ branch: newBranch,
+ });
+ });
+
+ it('calls the mutation with the new branch', () => {
+ expect(mockMutate).toHaveBeenCalledWith({
+ mutation: commitCreate,
+ update: expect.any(Function),
+ variables: {
+ ...mockVariables,
+ branch: newBranch,
+ },
+ });
+ });
+ });
+
+ describe('when the user commits changes to open a new merge request', () => {
+ const newBranch = 'new-branch';
+
+ beforeEach(async () => {
+ 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}`);
+ });
+ });
+
+ describe('when the commit is ocurring', () => {
+ it('shows a saving state', async () => {
+ mockMutate.mockImplementationOnce(() => {
+ expect(findCommitBtnLoadingIcon().exists()).toBe(true);
+ return Promise.resolve();
+ });
+
+ await submitCommit({
+ message: mockCommitMessage,
+ branch: mockDefaultBranch,
+ openMergeRequest: false,
+ });
+ });
+ });
+
+ describe('when the commit form is cancelled', () => {
+ beforeEach(async () => {
+ createComponent();
+ });
+
+ it('emits an event so that it cab be reseted', async () => {
+ await cancelCommitForm();
+
+ expect(wrapper.emitted('resetContent')).toHaveLength(1);
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js b/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js
new file mode 100644
index 00000000000..866069f337b
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/editor/ci_config_merged_preview_spec.js
@@ -0,0 +1,88 @@
+import { GlAlert, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+
+import { EDITOR_READY_EVENT } from '~/editor/constants';
+import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
+import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
+import { INVALID_CI_CONFIG } from '~/pipelines/constants';
+import { mockLintResponse, mockCiConfigPath } from '../../mock_data';
+
+describe('Text editor component', () => {
+ let wrapper;
+
+ const MockEditorLite = {
+ template: '<div/>',
+ props: ['value', 'fileName', 'editorOptions'],
+ mounted() {
+ this.$emit(EDITOR_READY_EVENT);
+ },
+ };
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(CiConfigMergedPreview, {
+ propsData: {
+ ciConfigData: mockLintResponse,
+ ...props,
+ },
+ provide: {
+ ciConfigPath: mockCiConfigPath,
+ },
+ stubs: {
+ EditorLite: MockEditorLite,
+ },
+ });
+ };
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findEditor = () => wrapper.findComponent(MockEditorLite);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when status is invalid', () => {
+ beforeEach(() => {
+ createComponent({ props: { ciConfigData: { status: CI_CONFIG_STATUS_INVALID } } });
+ });
+
+ it('show an error message', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[INVALID_CI_CONFIG]);
+ });
+
+ it('hides the editor', () => {
+ expect(findEditor().exists()).toBe(false);
+ });
+ });
+
+ describe('when status is valid', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows an information message that the section is not editable', () => {
+ expect(findIcon().exists()).toBe(true);
+ expect(wrapper.text()).toContain(wrapper.vm.$options.i18n.viewOnlyMessage);
+ });
+
+ it('contains an editor', () => {
+ expect(findEditor().exists()).toBe(true);
+ });
+
+ it('editor contains the value provided', () => {
+ expect(findEditor().props('value')).toBe(mockLintResponse.mergedYaml);
+ });
+
+ it('editor is configured for the CI config path', () => {
+ expect(findEditor().props('fileName')).toBe(mockCiConfigPath);
+ });
+
+ it('editor is readonly', () => {
+ expect(findEditor().props('editorOptions')).toMatchObject({
+ readOnly: true,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js b/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
new file mode 100644
index 00000000000..3bf5a291c69
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
@@ -0,0 +1,120 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { EDITOR_READY_EVENT } from '~/editor/constants';
+import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
+import {
+ mockCiConfigPath,
+ mockCiYml,
+ mockCommitSha,
+ mockProjectPath,
+ mockProjectNamespace,
+} from '../../mock_data';
+
+describe('Pipeline Editor | Text editor component', () => {
+ let wrapper;
+
+ let editorReadyListener;
+ let mockUse;
+ let mockRegisterCiSchema;
+
+ const MockEditorLite = {
+ template: '<div/>',
+ props: ['value', 'fileName'],
+ mounted() {
+ this.$emit(EDITOR_READY_EVENT);
+ },
+ methods: {
+ getEditor: () => ({
+ use: mockUse,
+ registerCiSchema: mockRegisterCiSchema,
+ }),
+ },
+ };
+
+ const createComponent = (opts = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(TextEditor, {
+ provide: {
+ projectPath: mockProjectPath,
+ projectNamespace: mockProjectNamespace,
+ ciConfigPath: mockCiConfigPath,
+ },
+ attrs: {
+ value: mockCiYml,
+ },
+ // Simulate graphQL client query result
+ data() {
+ return {
+ commitSha: mockCommitSha,
+ };
+ },
+ listeners: {
+ [EDITOR_READY_EVENT]: editorReadyListener,
+ },
+ stubs: {
+ EditorLite: MockEditorLite,
+ },
+ ...opts,
+ });
+ };
+
+ const findEditor = () => wrapper.findComponent(MockEditorLite);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+
+ mockUse.mockClear();
+ mockRegisterCiSchema.mockClear();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ editorReadyListener = jest.fn();
+ mockUse = jest.fn();
+ mockRegisterCiSchema = jest.fn();
+
+ createComponent();
+ });
+
+ it('contains an editor', () => {
+ expect(findEditor().exists()).toBe(true);
+ });
+
+ it('editor contains the value provided', () => {
+ expect(findEditor().props('value')).toBe(mockCiYml);
+ });
+
+ it('editor is configured for the CI config path', () => {
+ expect(findEditor().props('fileName')).toBe(mockCiConfigPath);
+ });
+
+ it('bubbles up events', () => {
+ findEditor().vm.$emit(EDITOR_READY_EVENT);
+
+ expect(editorReadyListener).toHaveBeenCalled();
+ });
+ });
+
+ describe('register CI schema', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ // Since the editor will have already mounted, the event will have fired.
+ // To ensure we properly test this, we clear the mock and re-remit the event.
+ mockRegisterCiSchema.mockClear();
+ mockUse.mockClear();
+
+ findEditor().vm.$emit(EDITOR_READY_EVENT);
+ });
+
+ it('configures editor with syntax highlight', async () => {
+ expect(mockUse).toHaveBeenCalledTimes(1);
+ expect(mockRegisterCiSchema).toHaveBeenCalledTimes(1);
+ expect(mockRegisterCiSchema).toHaveBeenCalledWith({
+ projectNamespace: mockProjectNamespace,
+ projectPath: mockProjectPath,
+ ref: mockCommitSha,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
new file mode 100644
index 00000000000..df15a6c8e7f
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
@@ -0,0 +1,34 @@
+import { shallowMount } from '@vue/test-utils';
+import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_editor_header.vue';
+import ValidationSegment from '~/pipeline_editor/components/header/validation_segment.vue';
+
+import { mockLintResponse } from '../../mock_data';
+
+describe('Pipeline editor header', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(PipelineEditorHeader, {
+ props: {
+ ciConfigData: mockLintResponse,
+ isCiConfigDataLoading: false,
+ },
+ });
+ };
+
+ const findValidationSegment = () => wrapper.findComponent(ValidationSegment);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+ it('renders the validation segment', () => {
+ expect(findValidationSegment().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
new file mode 100644
index 00000000000..cf1d89e1d7c
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
@@ -0,0 +1,120 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { escape } from 'lodash';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { sprintf } from '~/locale';
+import ValidationSegment, {
+ i18n,
+} from '~/pipeline_editor/components/header/validation_segment.vue';
+import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
+import { mockYmlHelpPagePath, mergeUnwrappedCiConfig } from '../../mock_data';
+
+describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = extendedWrapper(
+ shallowMount(ValidationSegment, {
+ provide: {
+ ymlHelpPagePath: mockYmlHelpPagePath,
+ },
+ propsData: {
+ ciConfig: mergeUnwrappedCiConfig(),
+ loading: false,
+ ...props,
+ },
+ }),
+ );
+ };
+
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findLearnMoreLink = () => wrapper.findByTestId('learnMoreLink');
+ const findValidationMsg = () => wrapper.findByTestId('validationMsg');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('shows the loading state', () => {
+ createComponent({ loading: true });
+
+ expect(wrapper.text()).toBe(i18n.loading);
+ });
+
+ describe('when config is valid', () => {
+ beforeEach(() => {
+ createComponent({});
+ });
+
+ it('has check icon', () => {
+ expect(findIcon().props('name')).toBe('check');
+ });
+
+ it('shows a message for valid state', () => {
+ expect(findValidationMsg().text()).toContain(i18n.valid);
+ });
+
+ it('shows the learn more link', () => {
+ expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath);
+ expect(findLearnMoreLink().text()).toBe(i18n.learnMore);
+ });
+ });
+
+ describe('when config is not valid', () => {
+ beforeEach(() => {
+ createComponent({
+ ciConfig: mergeUnwrappedCiConfig({
+ status: CI_CONFIG_STATUS_INVALID,
+ }),
+ });
+ });
+
+ it('has warning icon', () => {
+ expect(findIcon().props('name')).toBe('warning-solid');
+ });
+
+ it('has message for invalid state', () => {
+ expect(findValidationMsg().text()).toBe(i18n.invalid);
+ });
+
+ it('shows an invalid state with an error', () => {
+ const firstError = 'First Error';
+ const secondError = 'Second Error';
+
+ createComponent({
+ ciConfig: mergeUnwrappedCiConfig({
+ status: CI_CONFIG_STATUS_INVALID,
+ errors: [firstError, secondError],
+ }),
+ });
+
+ // Test the error is shown _and_ the string matches
+ expect(findValidationMsg().text()).toContain(firstError);
+ expect(findValidationMsg().text()).toBe(
+ sprintf(i18n.invalidWithReason, { reason: firstError }),
+ );
+ });
+
+ it('shows an invalid state with an error while preventing XSS', () => {
+ const evilError = '<script>evil();</script>';
+
+ createComponent({
+ ciConfig: mergeUnwrappedCiConfig({
+ status: CI_CONFIG_STATUS_INVALID,
+ errors: [evilError],
+ }),
+ });
+
+ const { innerHTML } = findValidationMsg().element;
+
+ expect(innerHTML).not.toContain(evilError);
+ expect(innerHTML).toContain(escape(evilError));
+ });
+
+ it('shows the learn more link', () => {
+ expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath);
+ expect(findLearnMoreLink().text()).toBe('Learn more');
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/info/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/info/validation_segment_spec.js
deleted file mode 100644
index 8a991d82018..00000000000
--- a/spec/frontend/pipeline_editor/components/info/validation_segment_spec.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import { escape } from 'lodash';
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { sprintf } from '~/locale';
-import ValidationSegment, { i18n } from '~/pipeline_editor/components/info/validation_segment.vue';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { mockYmlHelpPagePath, mergeUnwrappedCiConfig } from '../../mock_data';
-
-describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
- let wrapper;
-
- const createComponent = (props = {}) => {
- wrapper = extendedWrapper(
- shallowMount(ValidationSegment, {
- provide: {
- ymlHelpPagePath: mockYmlHelpPagePath,
- },
- propsData: {
- ciConfig: mergeUnwrappedCiConfig(),
- loading: false,
- ...props,
- },
- }),
- );
- };
-
- const findIcon = () => wrapper.findComponent(GlIcon);
- const findLearnMoreLink = () => wrapper.findByTestId('learnMoreLink');
- const findValidationMsg = () => wrapper.findByTestId('validationMsg');
-
- it('shows the loading state', () => {
- createComponent({ loading: true });
-
- expect(wrapper.text()).toBe(i18n.loading);
- });
-
- describe('when config is valid', () => {
- beforeEach(() => {
- createComponent({});
- });
-
- it('has check icon', () => {
- expect(findIcon().props('name')).toBe('check');
- });
-
- it('shows a message for valid state', () => {
- expect(findValidationMsg().text()).toContain(i18n.valid);
- });
-
- it('shows the learn more link', () => {
- expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath);
- expect(findLearnMoreLink().text()).toBe(i18n.learnMore);
- });
- });
-
- describe('when config is not valid', () => {
- beforeEach(() => {
- createComponent({
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- }),
- });
- });
-
- it('has warning icon', () => {
- expect(findIcon().props('name')).toBe('warning-solid');
- });
-
- it('has message for invalid state', () => {
- expect(findValidationMsg().text()).toBe(i18n.invalid);
- });
-
- it('shows an invalid state with an error', () => {
- const firstError = 'First Error';
- const secondError = 'Second Error';
-
- createComponent({
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- errors: [firstError, secondError],
- }),
- });
-
- // Test the error is shown _and_ the string matches
- expect(findValidationMsg().text()).toContain(firstError);
- expect(findValidationMsg().text()).toBe(
- sprintf(i18n.invalidWithReason, { reason: firstError }),
- );
- });
-
- it('shows an invalid state with an error while preventing XSS', () => {
- const evilError = '<script>evil();</script>';
-
- createComponent({
- ciConfig: mergeUnwrappedCiConfig({
- status: CI_CONFIG_STATUS_INVALID,
- errors: [evilError],
- }),
- });
-
- const { innerHTML } = findValidationMsg().element;
-
- expect(innerHTML).not.toContain(evilError);
- expect(innerHTML).toContain(escape(evilError));
- });
-
- it('shows the learn more link', () => {
- expect(findLearnMoreLink().attributes('href')).toBe(mockYmlHelpPagePath);
- expect(findLearnMoreLink().text()).toBe('Learn more');
- });
- });
-});
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
index 5e9471376bd..6775433deb9 100644
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlTable, GlLink } from '@gitlab/ui';
-import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
+import { shallowMount, mount } from '@vue/test-utils';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
import { mockJobs, mockErrors, mockWarnings } from '../../mock_data';
describe('CI Lint Results', () => {
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
index 5ccf4bbdab4..fdddca3d62b 100644
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlAlert, GlLink } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
import { mergeUnwrappedCiConfig, mockLintHelpPagePath } from '../../mock_data';
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_warnings_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_warnings_spec.js
index b441d26c146..4b576508ee9 100644
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_warnings_spec.js
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_warnings_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlAlert, GlSprintf } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
import CiLintWarnings from '~/pipeline_editor/components/lint/ci_lint_warnings.vue';
diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
new file mode 100644
index 00000000000..24af17e9ce6
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
@@ -0,0 +1,183 @@
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
+import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
+import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
+import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
+
+import { mockLintResponse, mockCiYml } from '../mock_data';
+
+describe('Pipeline editor tabs component', () => {
+ let wrapper;
+ const MockTextEditor = {
+ template: '<div />',
+ };
+ const mockProvide = {
+ glFeatures: {
+ ciConfigVisualizationTab: true,
+ ciConfigMergedTab: true,
+ },
+ };
+
+ const createComponent = ({ props = {}, provide = {}, mountFn = shallowMount } = {}) => {
+ wrapper = mountFn(PipelineEditorTabs, {
+ propsData: {
+ ciConfigData: mockLintResponse,
+ ciFileContent: mockCiYml,
+ isCiConfigDataLoading: false,
+ ...props,
+ },
+ provide: { ...mockProvide, ...provide },
+ stubs: {
+ TextEditor: MockTextEditor,
+ },
+ });
+ };
+
+ const findEditorTab = () => wrapper.find('[data-testid="editor-tab"]');
+ const findLintTab = () => wrapper.find('[data-testid="lint-tab"]');
+ const findMergedTab = () => wrapper.find('[data-testid="merged-tab"]');
+ const findVisualizationTab = () => wrapper.find('[data-testid="visualization-tab"]');
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findCiLint = () => wrapper.findComponent(CiLint);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findPipelineGraph = () => wrapper.findComponent(PipelineGraph);
+ const findTextEditor = () => wrapper.findComponent(MockTextEditor);
+ const findMergedPreview = () => wrapper.findComponent(CiConfigMergedPreview);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('editor tab', () => {
+ it('displays editor only after the tab is mounted', async () => {
+ createComponent({ mountFn: mount });
+
+ expect(findTextEditor().exists()).toBe(false);
+
+ await nextTick();
+
+ expect(findTextEditor().exists()).toBe(true);
+ expect(findEditorTab().exists()).toBe(true);
+ });
+ });
+
+ describe('visualization tab', () => {
+ describe('with feature flag on', () => {
+ describe('while loading', () => {
+ beforeEach(() => {
+ createComponent({ props: { isCiConfigDataLoading: true } });
+ });
+
+ it('displays a loading icon if the lint query is loading', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
+ });
+ describe('after loading', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('display the tab and visualization', () => {
+ expect(findVisualizationTab().exists()).toBe(true);
+ expect(findPipelineGraph().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('with feature flag off', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures: { ciConfigVisualizationTab: false },
+ },
+ });
+ });
+
+ it('does not display the tab or component', () => {
+ expect(findVisualizationTab().exists()).toBe(false);
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('lint tab', () => {
+ describe('while loading', () => {
+ beforeEach(() => {
+ createComponent({ props: { isCiConfigDataLoading: true } });
+ });
+
+ it('displays a loading icon if the lint query is loading', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
+ it('does not display the lint component', () => {
+ expect(findCiLint().exists()).toBe(false);
+ });
+ });
+ describe('after loading', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('display the tab and the lint component', () => {
+ expect(findLintTab().exists()).toBe(true);
+ expect(findCiLint().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('merged tab', () => {
+ describe('with feature flag on', () => {
+ describe('while loading', () => {
+ beforeEach(() => {
+ createComponent({ props: { isCiConfigDataLoading: true } });
+ });
+
+ it('displays a loading icon if the lint query is loading', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('when `mergedYaml` is undefined', () => {
+ beforeEach(() => {
+ createComponent({ props: { ciConfigData: {} } });
+ });
+
+ it('show an error message', () => {
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts.loadMergedYaml);
+ });
+
+ it('does not render the `meged_preview` component', () => {
+ expect(findMergedPreview().exists()).toBe(false);
+ });
+ });
+
+ describe('after loading', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('display the tab and the merged preview component', () => {
+ expect(findMergedTab().exists()).toBe(true);
+ expect(findMergedPreview().exists()).toBe(true);
+ });
+ });
+ });
+ describe('with feature flag off', () => {
+ beforeEach(() => {
+ createComponent({ provide: { glFeatures: { ciConfigMergedTab: false } } });
+ });
+
+ it('does not display the merged tab', () => {
+ expect(findMergedTab().exists()).toBe(false);
+ expect(findMergedPreview().exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/text_editor_spec.js b/spec/frontend/pipeline_editor/components/text_editor_spec.js
deleted file mode 100644
index 9221d64c44b..00000000000
--- a/spec/frontend/pipeline_editor/components/text_editor_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import {
- mockCiConfigPath,
- mockCiYml,
- mockCommitSha,
- mockProjectPath,
- mockProjectNamespace,
-} from '../mock_data';
-
-import TextEditor from '~/pipeline_editor/components/text_editor.vue';
-
-describe('~/pipeline_editor/components/text_editor.vue', () => {
- let wrapper;
-
- let editorReadyListener;
- let mockUse;
- let mockRegisterCiSchema;
-
- const MockEditorLite = {
- template: '<div/>',
- props: ['value', 'fileName'],
- mounted() {
- this.$emit('editor-ready');
- },
- methods: {
- getEditor: () => ({
- use: mockUse,
- registerCiSchema: mockRegisterCiSchema,
- }),
- },
- };
-
- const createComponent = (opts = {}, mountFn = shallowMount) => {
- wrapper = mountFn(TextEditor, {
- provide: {
- projectPath: mockProjectPath,
- projectNamespace: mockProjectNamespace,
- },
- propsData: {
- ciConfigPath: mockCiConfigPath,
- commitSha: mockCommitSha,
- },
- attrs: {
- value: mockCiYml,
- },
- listeners: {
- 'editor-ready': editorReadyListener,
- },
- stubs: {
- EditorLite: MockEditorLite,
- },
- ...opts,
- });
- };
-
- const findEditor = () => wrapper.find(MockEditorLite);
-
- beforeEach(() => {
- editorReadyListener = jest.fn();
- mockUse = jest.fn();
- mockRegisterCiSchema = jest.fn();
-
- createComponent();
- });
-
- it('contains an editor', () => {
- expect(findEditor().exists()).toBe(true);
- });
-
- it('editor contains the value provided', () => {
- expect(findEditor().props('value')).toBe(mockCiYml);
- });
-
- it('editor is configured for the CI config path', () => {
- expect(findEditor().props('fileName')).toBe(mockCiConfigPath);
- });
-
- it('editor is configured with syntax highligting', async () => {
- expect(mockUse).toHaveBeenCalledTimes(1);
- expect(mockRegisterCiSchema).toHaveBeenCalledTimes(1);
- expect(mockRegisterCiSchema).toHaveBeenCalledWith({
- projectNamespace: mockProjectNamespace,
- projectPath: mockProjectPath,
- ref: mockCommitSha,
- });
- });
-
- it('bubbles up events', () => {
- findEditor().vm.$emit('editor-ready');
-
- expect(editorReadyListener).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/pipeline_editor/components/ui/confirm_unsaved_changes_dialog_spec.js b/spec/frontend/pipeline_editor/components/ui/confirm_unsaved_changes_dialog_spec.js
new file mode 100644
index 00000000000..44fda2812d8
--- /dev/null
+++ b/spec/frontend/pipeline_editor/components/ui/confirm_unsaved_changes_dialog_spec.js
@@ -0,0 +1,42 @@
+import { shallowMount } from '@vue/test-utils';
+import ConfirmDialog from '~/pipeline_editor/components/ui/confirm_unsaved_changes_dialog.vue';
+
+describe('pipeline_editor/components/ui/confirm_unsaved_changes_dialog', () => {
+ let beforeUnloadEvent;
+ let setDialogContent;
+ let wrapper;
+
+ const createComponent = (propsData = {}) => {
+ wrapper = shallowMount(ConfirmDialog, {
+ propsData,
+ });
+ };
+
+ beforeEach(() => {
+ beforeUnloadEvent = new Event('beforeunload');
+ jest.spyOn(beforeUnloadEvent, 'preventDefault');
+ setDialogContent = jest.spyOn(beforeUnloadEvent, 'returnValue', 'set');
+ });
+
+ afterEach(() => {
+ beforeUnloadEvent.preventDefault.mockRestore();
+ setDialogContent.mockRestore();
+ wrapper.destroy();
+ });
+
+ it('shows confirmation dialog when there are unsaved changes', () => {
+ createComponent({ hasUnsavedChanges: true });
+ window.dispatchEvent(beforeUnloadEvent);
+
+ expect(beforeUnloadEvent.preventDefault).toHaveBeenCalled();
+ expect(setDialogContent).toHaveBeenCalledWith('');
+ });
+
+ it('does not show confirmation dialog when there are no unsaved changes', () => {
+ createComponent({ hasUnsavedChanges: false });
+ window.dispatchEvent(beforeUnloadEvent);
+
+ expect(beforeUnloadEvent.preventDefault).not.toHaveBeenCalled();
+ expect(setDialogContent).not.toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
index d3d9bf08209..291468c5229 100644
--- a/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/editor_tab_spec.js
@@ -1,6 +1,6 @@
-import { nextTick } from 'vue';
-import { mount } from '@vue/test-utils';
import { GlTabs } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
diff --git a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
index 3e008527415..d39c0d80296 100644
--- a/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
+++ b/spec/frontend/pipeline_editor/graphql/resolvers_spec.js
@@ -1,5 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
import Api from '~/api';
+import axios from '~/lib/utils/axios_utils';
+import httpStatus from '~/lib/utils/http_status';
+import { resolvers } from '~/pipeline_editor/graphql/resolvers';
import {
mockCiConfigPath,
mockCiYml,
@@ -7,9 +10,6 @@ import {
mockLintResponse,
mockProjectFullPath,
} from '../mock_data';
-import httpStatus from '~/lib/utils/http_status';
-import axios from '~/lib/utils/axios_utils';
-import { resolvers } from '~/pipeline_editor/graphql/resolvers';
jest.mock('~/api', () => {
return {
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index 3eacc467c51..8e248c11b87 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -54,6 +54,7 @@ export const mockCiConfigQueryResponse = {
data: {
ciConfig: {
errors: [],
+ mergedYaml: mockCiYml,
status: CI_CONFIG_STATUS_VALID,
stages: {
__typename: 'CiConfigStageConnection',
@@ -139,6 +140,8 @@ export const mergeUnwrappedCiConfig = (mergedConfig) => {
export const mockLintResponse = {
valid: true,
+ mergedYaml: mockCiYml,
+ status: CI_CONFIG_STATUS_VALID,
errors: [],
warnings: [],
jobs: [
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index d6b90900600..46d0452f437 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -1,119 +1,70 @@
-import { nextTick } from 'vue';
-import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlAlert, GlButton, GlFormInput, GlFormTextarea, GlLoadingIcon, GlTabs } from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
+import { GlAlert, GlButton, GlLoadingIcon, GlTabs } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
-
+import waitForPromises from 'helpers/wait_for_promises';
import httpStatusCodes from '~/lib/utils/http_status';
-import { objectToQuery, redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility';
+import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
+import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
+
+import { COMMIT_SUCCESS, COMMIT_FAILURE, LOAD_FAILURE_UNKNOWN } from '~/pipeline_editor/constants';
+import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
+import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
+import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
import {
mockCiConfigPath,
mockCiConfigQueryResponse,
mockCiYml,
- mockCommitSha,
- mockCommitNextSha,
- mockCommitMessage,
mockDefaultBranch,
- mockProjectPath,
mockProjectFullPath,
- mockProjectNamespace,
- mockNewMergeRequestPath,
} from './mock_data';
-import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
-import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
-import EditorTab from '~/pipeline_editor/components/ui/editor_tab.vue';
-import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
-import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
-import TextEditor from '~/pipeline_editor/components/text_editor.vue';
-
const localVue = createLocalVue();
localVue.use(VueApollo);
-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 MockEditorLite = {
template: '<div/>',
};
const mockProvide = {
+ ciConfigPath: mockCiConfigPath,
+ defaultBranch: mockDefaultBranch,
projectFullPath: mockProjectFullPath,
- projectPath: mockProjectPath,
- projectNamespace: mockProjectNamespace,
- glFeatures: {
- ciConfigVisualizationTab: true,
- },
};
-describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
+describe('Pipeline editor app component', () => {
let wrapper;
let mockApollo;
let mockBlobContentData;
let mockCiConfigData;
- let mockMutate;
-
- const createComponent = ({
- props = {},
- blobLoading = false,
- lintLoading = false,
- options = {},
- mountFn = shallowMount,
- provide = mockProvide,
- } = {}) => {
- mockMutate = jest.fn().mockResolvedValue({
- data: {
- commitCreate: {
- errors: [],
- commit: {
- sha: mockCommitNextSha,
- },
- },
- },
- });
- wrapper = mountFn(PipelineEditorApp, {
- propsData: {
- ciConfigPath: mockCiConfigPath,
- commitSha: mockCommitSha,
- defaultBranch: mockDefaultBranch,
- newMergeRequestPath: mockNewMergeRequestPath,
- ...props,
- },
- provide,
+ const createComponent = ({ blobLoading = false, options = {} } = {}) => {
+ wrapper = shallowMount(PipelineEditorApp, {
+ provide: mockProvide,
stubs: {
GlTabs,
GlButton,
CommitForm,
EditorLite: MockEditorLite,
- TextEditor,
},
mocks: {
$apollo: {
queries: {
- content: {
+ initialCiFileContent: {
loading: blobLoading,
},
ciConfigData: {
- loading: lintLoading,
+ loading: false,
},
},
- mutate: mockMutate,
},
},
- // attachTo is required for input/submit events
- attachTo: mountFn === mount ? document.body : null,
...options,
});
};
- const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
+ const createComponentWithApollo = ({ props = {} } = {}) => {
const handlers = [[getCiConfigData, mockCiConfigData]];
const resolvers = {
Query: {
@@ -134,18 +85,13 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
apolloProvider: mockApollo,
};
- createComponent({ props, options }, mountFn);
+ createComponent({ props, options });
};
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findAlert = () => wrapper.find(GlAlert);
- const findTabAt = (i) => wrapper.findAll(EditorTab).at(i);
- const findVisualizationTab = () => wrapper.find('[data-testid="visualization-tab"]');
- const findTextEditor = () => wrapper.find(TextEditor);
- const findEditorLite = () => wrapper.find(MockEditorLite);
- const findCommitForm = () => wrapper.find(CommitForm);
- const findPipelineGraph = () => wrapper.find(PipelineGraph);
- const findCommitBtnLoadingIcon = () => wrapper.find('[type="submit"]').find(GlLoadingIcon);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findEditorHome = () => wrapper.findComponent(PipelineEditorHome);
+ const findTextEditor = () => wrapper.findComponent(TextEditor);
beforeEach(() => {
mockBlobContentData = jest.fn();
@@ -155,9 +101,6 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
afterEach(() => {
mockBlobContentData.mockReset();
mockCiConfigData.mockReset();
- refreshCurrentPage.mockReset();
- redirectTo.mockReset();
- mockMutate.mockReset();
wrapper.destroy();
wrapper = null;
@@ -170,245 +113,6 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
expect(findTextEditor().exists()).toBe(false);
});
- describe('tabs', () => {
- describe('editor tab', () => {
- it('displays editor only after the tab is mounted', async () => {
- createComponent({ mountFn: mount });
-
- expect(findTabAt(0).find(TextEditor).exists()).toBe(false);
-
- await nextTick();
-
- expect(findTabAt(0).find(TextEditor).exists()).toBe(true);
- });
- });
-
- describe('visualization tab', () => {
- describe('with feature flag on', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('display the tab', () => {
- expect(findVisualizationTab().exists()).toBe(true);
- });
-
- it('displays a loading icon if the lint query is loading', () => {
- createComponent({ lintLoading: true });
-
- expect(findLoadingIcon().exists()).toBe(true);
- expect(findPipelineGraph().exists()).toBe(false);
- });
- });
-
- describe('with feature flag off', () => {
- beforeEach(() => {
- createComponent({
- provide: {
- ...mockProvide,
- glFeatures: { ciConfigVisualizationTab: false },
- },
- });
- });
-
- it('does not display the tab', () => {
- expect(findVisualizationTab().exists()).toBe(false);
- });
- });
- });
- });
-
- describe('when data is set', () => {
- beforeEach(async () => {
- createComponent({ mountFn: mount });
-
- wrapper.setData({
- content: mockCiYml,
- contentModel: mockCiYml,
- });
-
- await waitForPromises();
- });
-
- it('displays content after the query loads', () => {
- expect(findLoadingIcon().exists()).toBe(false);
-
- expect(findEditorLite().attributes('value')).toBe(mockCiYml);
- expect(findEditorLite().attributes('file-name')).toBe(mockCiConfigPath);
- });
-
- it('configures text editor', () => {
- expect(findTextEditor().props('commitSha')).toBe(mockCommitSha);
- });
-
- describe('commit form', () => {
- const mockVariables = {
- content: mockCiYml,
- filePath: mockCiConfigPath,
- lastCommitId: mockCommitSha,
- message: mockCommitMessage,
- projectPath: mockProjectFullPath,
- startBranch: mockDefaultBranch,
- };
-
- const findInForm = (selector) => findCommitForm().find(selector);
-
- const submitCommit = async ({
- message = mockCommitMessage,
- branch = mockDefaultBranch,
- openMergeRequest = false,
- } = {}) => {
- await findInForm(GlFormTextarea).setValue(message);
- await findInForm(GlFormInput).setValue(branch);
- if (openMergeRequest) {
- await findInForm('[data-testid="new-mr-checkbox"]').setChecked(openMergeRequest);
- }
- await findInForm('[type="submit"]').trigger('click');
- };
-
- const cancelCommitForm = async () => {
- const findCancelBtn = () => wrapper.find('[type="reset"]');
- await findCancelBtn().trigger('click');
- };
-
- describe('when the user commits changes to the current branch', () => {
- beforeEach(async () => {
- await submitCommit();
- });
-
- it('calls the mutation with the default branch', () => {
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: expect.any(Object),
- variables: {
- ...mockVariables,
- branch: mockDefaultBranch,
- },
- });
- });
-
- it('displays an alert to indicate success', () => {
- expect(findAlert().text()).toMatchInterpolatedText(
- 'Your changes have been successfully committed.',
- );
- });
-
- it('shows no saving state', () => {
- expect(findCommitBtnLoadingIcon().exists()).toBe(false);
- });
-
- it('a second commit submits the latest sha, keeping the form updated', async () => {
- await submitCommit();
-
- expect(mockMutate).toHaveBeenCalledTimes(2);
- expect(mockMutate).toHaveBeenLastCalledWith({
- mutation: expect.any(Object),
- variables: {
- ...mockVariables,
- lastCommitId: mockCommitNextSha,
- branch: mockDefaultBranch,
- },
- });
- });
- });
-
- describe('when the user commits changes to a new branch', () => {
- const newBranch = 'new-branch';
-
- beforeEach(async () => {
- await submitCommit({
- branch: newBranch,
- });
- });
-
- it('calls the mutation with the new branch', () => {
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: expect.any(Object),
- variables: {
- ...mockVariables,
- branch: newBranch,
- },
- });
- });
- });
-
- describe('when the user commits changes to open a new merge request', () => {
- const newBranch = 'new-branch';
-
- beforeEach(async () => {
- 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}`);
- });
- });
-
- describe('when the commit is ocurring', () => {
- it('shows a saving state', async () => {
- await mockMutate.mockImplementationOnce(() => {
- expect(findCommitBtnLoadingIcon().exists()).toBe(true);
- return Promise.resolve();
- });
-
- await submitCommit({
- message: mockCommitMessage,
- branch: mockDefaultBranch,
- openMergeRequest: false,
- });
- });
- });
-
- describe('when the commit fails', () => {
- it('shows an error message', async () => {
- mockMutate.mockRejectedValueOnce(new Error('commit failed'));
-
- await submitCommit();
-
- await waitForPromises();
-
- expect(findAlert().text()).toMatchInterpolatedText(
- 'The GitLab CI configuration could not be updated. commit failed',
- );
- });
-
- it('shows an unkown error', async () => {
- mockMutate.mockRejectedValueOnce();
-
- await submitCommit();
-
- await waitForPromises();
-
- expect(findAlert().text()).toMatchInterpolatedText(
- 'The GitLab CI configuration could not be updated.',
- );
- });
- });
-
- describe('when the commit form is cancelled', () => {
- const otherContent = 'other content';
-
- beforeEach(async () => {
- findTextEditor().vm.$emit('input', otherContent);
- await nextTick();
- });
-
- it('content is restored after cancel is called', async () => {
- await cancelCommitForm();
-
- expect(findEditorLite().attributes('value')).toBe(mockCiYml);
- });
- });
- });
- });
-
describe('when queries are called', () => {
beforeEach(() => {
mockBlobContentData.mockResolvedValue(mockCiYml);
@@ -422,14 +126,12 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
await waitForPromises();
});
- it('shows editor and commit form', () => {
- expect(findEditorLite().exists()).toBe(true);
- expect(findTextEditor().exists()).toBe(true);
+ it('shows pipeline editor home component', () => {
+ expect(findEditorHome().exists()).toBe(true);
});
- it('no error is shown when data is set', async () => {
+ it('no error is shown when data is set', () => {
expect(findAlert().exists()).toBe(false);
- expect(findEditorLite().attributes('value')).toBe(mockCiYml);
});
it('ci config query is called with correct variables', async () => {
@@ -445,10 +147,10 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
});
describe('when no file exists', () => {
- const expectedAlertMsg =
+ const noFileAlertMsg =
'There is no .gitlab-ci.yml file in this repository, please add one and visit the Pipeline Editor again.';
- it('shows a 404 error message and does not show editor or commit form', async () => {
+ it('shows a 404 error message and does not show editor home component', async () => {
mockBlobContentData.mockRejectedValueOnce({
response: {
status: httpStatusCodes.NOT_FOUND,
@@ -458,12 +160,11 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
await waitForPromises();
- expect(findAlert().text()).toBe(expectedAlertMsg);
- expect(findEditorLite().exists()).toBe(false);
- expect(findTextEditor().exists()).toBe(false);
+ expect(findAlert().text()).toBe(noFileAlertMsg);
+ expect(findEditorHome().exists()).toBe(false);
});
- it('shows a 400 error message and does not show editor or commit form', async () => {
+ it('shows a 400 error message and does not show editor home component', async () => {
mockBlobContentData.mockRejectedValueOnce({
response: {
status: httpStatusCodes.BAD_REQUEST,
@@ -473,9 +174,8 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
await waitForPromises();
- expect(findAlert().text()).toBe(expectedAlertMsg);
- expect(findEditorLite().exists()).toBe(false);
- expect(findTextEditor().exists()).toBe(false);
+ expect(findAlert().text()).toBe(noFileAlertMsg);
+ expect(findEditorHome().exists()).toBe(false);
});
it('shows a unkown error message', async () => {
@@ -483,9 +183,60 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
createComponentWithApollo();
await waitForPromises();
- expect(findAlert().text()).toBe('The CI configuration was not loaded, please try again.');
- expect(findEditorLite().exists()).toBe(true);
- expect(findTextEditor().exists()).toBe(true);
+ expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[LOAD_FAILURE_UNKNOWN]);
+ expect(findEditorHome().exists()).toBe(true);
+ });
+ });
+
+ describe('when the user commits', () => {
+ const updateFailureMessage = 'The GitLab CI configuration could not be updated.';
+
+ describe('and the commit mutation succeeds', () => {
+ beforeEach(() => {
+ createComponent();
+
+ findEditorHome().vm.$emit('commit', { type: COMMIT_SUCCESS });
+ });
+
+ it('shows a confirmation message', () => {
+ expect(findAlert().text()).toBe(wrapper.vm.$options.successTexts[COMMIT_SUCCESS]);
+ });
+ });
+ describe('and the commit mutation fails', () => {
+ const commitFailedReasons = ['Commit failed'];
+
+ beforeEach(() => {
+ createComponent();
+
+ findEditorHome().vm.$emit('showError', {
+ type: COMMIT_FAILURE,
+ reasons: commitFailedReasons,
+ });
+ });
+
+ it('shows an error message', () => {
+ expect(findAlert().text()).toMatchInterpolatedText(
+ `${updateFailureMessage} ${commitFailedReasons[0]}`,
+ );
+ });
+ });
+ describe('when an unknown error occurs', () => {
+ const unknownReasons = ['Commit failed'];
+
+ beforeEach(() => {
+ createComponent();
+
+ findEditorHome().vm.$emit('showError', {
+ type: COMMIT_FAILURE,
+ reasons: unknownReasons,
+ });
+ });
+
+ it('shows an error message', () => {
+ expect(findAlert().text()).toMatchInterpolatedText(
+ `${updateFailureMessage} ${unknownReasons[0]}`,
+ );
+ });
});
});
});
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
new file mode 100644
index 00000000000..9864f3c13f9
--- /dev/null
+++ b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
@@ -0,0 +1,78 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+
+import CommitSection from '~/pipeline_editor/components/commit/commit_section.vue';
+import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_editor_header.vue';
+import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
+import { MERGED_TAB, VISUALIZE_TAB } from '~/pipeline_editor/constants';
+import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
+
+import { mockLintResponse, mockCiYml } from './mock_data';
+
+describe('Pipeline editor home wrapper', () => {
+ let wrapper;
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = shallowMount(PipelineEditorHome, {
+ propsData: {
+ ciConfigData: mockLintResponse,
+ ciFileContent: mockCiYml,
+ isCiConfigDataLoading: false,
+ ...props,
+ },
+ });
+ };
+
+ const findPipelineEditorHeader = () => wrapper.findComponent(PipelineEditorHeader);
+ const findPipelineEditorTabs = () => wrapper.findComponent(PipelineEditorTabs);
+ const findCommitSection = () => wrapper.findComponent(CommitSection);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('renders', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows the pipeline editor header', () => {
+ expect(findPipelineEditorHeader().exists()).toBe(true);
+ });
+
+ it('shows the pipeline editor tabs', () => {
+ expect(findPipelineEditorTabs().exists()).toBe(true);
+ });
+
+ it('shows the commit section by default', () => {
+ expect(findCommitSection().exists()).toBe(true);
+ });
+ });
+
+ describe('commit form toggle', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('hides the commit form when in the merged tab', async () => {
+ expect(findCommitSection().exists()).toBe(true);
+
+ findPipelineEditorTabs().vm.$emit('set-current-tab', MERGED_TAB);
+ await nextTick();
+ expect(findCommitSection().exists()).toBe(false);
+ });
+
+ it('shows the form again when leaving the merged tab', async () => {
+ expect(findCommitSection().exists()).toBe(true);
+
+ findPipelineEditorTabs().vm.$emit('set-current-tab', MERGED_TAB);
+ await nextTick();
+ expect(findCommitSection().exists()).toBe(false);
+
+ findPipelineEditorTabs().vm.$emit('set-current-tab', VISUALIZE_TAB);
+ await nextTick();
+ expect(findCommitSection().exists()).toBe(true);
+ });
+ });
+});
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 421ad9f4939..51bb0ecee9c 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -1,9 +1,10 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem, GlForm, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import httpStatusCodes from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
+import { redirectTo } from '~/lib/utils/url_utility';
import PipelineNewForm from '~/pipeline_new/components/pipeline_new_form.vue';
import {
mockBranches,
@@ -13,7 +14,6 @@ import {
mockProjectId,
mockError,
} from '../mock_data';
-import { redirectTo } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
@@ -34,6 +34,7 @@ describe('Pipeline New Form', () => {
const findForm = () => wrapper.find(GlForm);
const findDropdown = () => wrapper.find(GlDropdown);
const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findSubmitButton = () => wrapper.find('[data-testid="run_pipeline_button"]');
const findVariableRows = () => wrapper.findAll('[data-testid="ci-variable-row"]');
const findRemoveIcons = () => wrapper.findAll('[data-testid="remove-ci-variable-row"]');
const findKeyInputs = () => wrapper.findAll('[data-testid="pipeline-form-ci-variable-key"]');
@@ -155,6 +156,18 @@ describe('Pipeline New Form', () => {
await waitForPromises();
});
+
+ it('disables the submit button immediately after submitting', async () => {
+ createComponent();
+
+ expect(findSubmitButton().props('disabled')).toBe(false);
+
+ findForm().vm.$emit('submit', dummySubmitEvent);
+ await waitForPromises();
+
+ expect(findSubmitButton().props('disabled')).toBe(true);
+ });
+
it('creates pipeline with full ref and variables', async () => {
createComponent();
@@ -167,6 +180,7 @@ describe('Pipeline New Form', () => {
expect(getExpectedPostParams().ref).toEqual(wrapper.vm.$data.refValue.fullName);
expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${postResponse.id}`);
});
+
it('creates a pipeline with short ref and variables', async () => {
// query params are used
createComponent('', mockParams);
@@ -225,42 +239,47 @@ describe('Pipeline New Form', () => {
});
});
- describe('when feature flag new_pipeline_form_prefilled_vars is enabled', () => {
- let origGon;
-
+ describe('when yml defines a variable', () => {
const mockYmlKey = 'yml_var';
const mockYmlValue = 'yml_var_val';
+ const mockYmlMultiLineValue = `A value
+ with multiple
+ lines`;
const mockYmlDesc = 'A var from yml.';
- beforeAll(() => {
- origGon = window.gon;
- window.gon = { features: { newPipelineFormPrefilledVars: true } };
- });
+ it('loading icon is shown when content is requested and hidden when received', async () => {
+ createComponent('', mockParams, mount);
- afterAll(() => {
- window.gon = origGon;
- });
+ mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
+ [mockYmlKey]: {
+ value: mockYmlValue,
+ description: mockYmlDesc,
+ },
+ });
- describe('loading state', () => {
- it('loading icon is shown when content is requested and hidden when received', async () => {
- createComponent('', mockParams, mount);
+ expect(findLoadingIcon().exists()).toBe(true);
- mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
- [mockYmlKey]: {
- value: mockYmlValue,
- description: mockYmlDesc,
- },
- });
+ await waitForPromises();
- expect(findLoadingIcon().exists()).toBe(true);
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
- await waitForPromises();
+ it('multi-line strings are added to the value field without removing line breaks', async () => {
+ createComponent('', mockParams, mount);
- expect(findLoadingIcon().exists()).toBe(false);
+ mock.onGet(configVariablesPath).reply(httpStatusCodes.OK, {
+ [mockYmlKey]: {
+ value: mockYmlMultiLineValue,
+ description: mockYmlDesc,
+ },
});
+
+ await waitForPromises();
+
+ expect(findValueInputs().at(0).element.value).toBe(mockYmlMultiLineValue);
});
- describe('when yml defines a variable with description', () => {
+ describe('with description', () => {
beforeEach(async () => {
createComponent('', mockParams, mount);
@@ -302,7 +321,7 @@ describe('Pipeline New Form', () => {
});
});
- describe('when yml defines a variable without description', () => {
+ describe('without description', () => {
beforeEach(async () => {
createComponent('', mockParams, mount);
@@ -325,31 +344,55 @@ describe('Pipeline New Form', () => {
describe('Form errors and warnings', () => {
beforeEach(() => {
createComponent();
+ });
- mock.onPost(pipelinesPath).reply(httpStatusCodes.BAD_REQUEST, mockError);
+ describe('when the error response can be handled', () => {
+ beforeEach(async () => {
+ mock.onPost(pipelinesPath).reply(httpStatusCodes.BAD_REQUEST, mockError);
- findForm().vm.$emit('submit', dummySubmitEvent);
+ findForm().vm.$emit('submit', dummySubmitEvent);
- return waitForPromises();
- });
+ await waitForPromises();
+ });
- it('shows both error and warning', () => {
- expect(findErrorAlert().exists()).toBe(true);
- expect(findWarningAlert().exists()).toBe(true);
- });
+ it('shows both error and warning', () => {
+ expect(findErrorAlert().exists()).toBe(true);
+ expect(findWarningAlert().exists()).toBe(true);
+ });
- it('shows the correct error', () => {
- expect(findErrorAlert().text()).toBe(mockError.errors[0]);
- });
+ it('shows the correct error', () => {
+ expect(findErrorAlert().text()).toBe(mockError.errors[0]);
+ });
- it('shows the correct warning title', () => {
- const { length } = mockError.warnings;
+ it('shows the correct warning title', () => {
+ const { length } = mockError.warnings;
+
+ expect(findWarningAlertSummary().attributes('message')).toBe(`${length} warnings found:`);
+ });
- expect(findWarningAlertSummary().attributes('message')).toBe(`${length} warnings found:`);
+ it('shows the correct amount of warnings', () => {
+ expect(findWarnings()).toHaveLength(mockError.warnings.length);
+ });
+
+ it('re-enables the submit button', () => {
+ expect(findSubmitButton().props('disabled')).toBe(false);
+ });
});
- it('shows the correct amount of warnings', () => {
- expect(findWarnings()).toHaveLength(mockError.warnings.length);
+ describe('when the error response cannot be handled', () => {
+ beforeEach(async () => {
+ mock
+ .onPost(pipelinesPath)
+ .reply(httpStatusCodes.INTERNAL_SERVER_ERROR, 'something went wrong');
+
+ findForm().vm.$emit('submit', dummySubmitEvent);
+
+ await waitForPromises();
+ });
+
+ it('re-enables the submit button', () => {
+ expect(findSubmitButton().props('disabled')).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/pipeline_new/utils/format_refs_spec.js b/spec/frontend/pipeline_new/utils/format_refs_spec.js
index 1fda6a8af83..405a747c3ba 100644
--- a/spec/frontend/pipeline_new/utils/format_refs_spec.js
+++ b/spec/frontend/pipeline_new/utils/format_refs_spec.js
@@ -1,5 +1,5 @@
-import formatRefs from '~/pipeline_new/utils/format_refs';
import { BRANCH_REF_TYPE, TAG_REF_TYPE } from '~/pipeline_new/constants';
+import formatRefs from '~/pipeline_new/utils/format_refs';
import { mockBranchRefs, mockTagRefs } from '../mock_data';
describe('Format refs util', () => {
diff --git a/spec/frontend/pipelines/blank_state_spec.js b/spec/frontend/pipelines/blank_state_spec.js
index c09d9232569..5dcf3d267ed 100644
--- a/spec/frontend/pipelines/blank_state_spec.js
+++ b/spec/frontend/pipelines/blank_state_spec.js
@@ -1,25 +1,20 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import component from '~/pipelines/components/pipelines_list/blank_state.vue';
+import { getByText } from '@testing-library/dom';
+import { mount } from '@vue/test-utils';
+import BlankState from '~/pipelines/components/pipelines_list/blank_state.vue';
describe('Pipelines Blank State', () => {
- let vm;
- let Component;
-
- beforeEach(() => {
- Component = Vue.extend(component);
-
- vm = mountComponent(Component, {
+ const wrapper = mount(BlankState, {
+ propsData: {
svgPath: 'foo',
message: 'Blank State',
- });
+ },
});
it('should render svg', () => {
- expect(vm.$el.querySelector('.svg-content img').getAttribute('src')).toEqual('foo');
+ expect(wrapper.find('.svg-content img').attributes('src')).toEqual('foo');
});
it('should render message', () => {
- expect(vm.$el.querySelector('h4').textContent.trim()).toEqual('Blank State');
+ expect(getByText(wrapper.element, /Blank State/i)).toBeTruthy();
});
});
diff --git a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
index 80807c0b330..1941a7f2777 100644
--- a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue';
import { singleNote, multiNote } from './mock_data';
diff --git a/spec/frontend/pipelines/components/dag/dag_graph_spec.js b/spec/frontend/pipelines/components/dag/dag_graph_spec.js
index ccfb2ae7cee..4619548d1bb 100644
--- a/spec/frontend/pipelines/components/dag/dag_graph_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_graph_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
-import DagGraph from '~/pipelines/components/dag/dag_graph.vue';
import { IS_HIGHLIGHTED, LINK_SELECTOR, NODE_SELECTOR } from '~/pipelines/components/dag/constants';
-import { highlightIn, highlightOut } from '~/pipelines/components/dag/interactions';
+import DagGraph from '~/pipelines/components/dag/dag_graph.vue';
import { createSankey } from '~/pipelines/components/dag/drawing_utils';
+import { highlightIn, highlightOut } from '~/pipelines/components/dag/interactions';
import { removeOrphanNodes } from '~/pipelines/components/parsing_utils';
import { parsedData } from './mock_data';
diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js
index f6195e30e44..14030930657 100644
--- a/spec/frontend/pipelines/components/dag/dag_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_spec.js
@@ -1,10 +1,10 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlAlert, GlEmptyState } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from '~/pipelines/components/dag/constants';
import Dag from '~/pipelines/components/dag/dag.vue';
-import DagGraph from '~/pipelines/components/dag/dag_graph.vue';
import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue';
+import DagGraph from '~/pipelines/components/dag/dag_graph.vue';
-import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from '~/pipelines/components/dag/constants';
import { PARSE_FAILURE, UNSUPPORTED_DATA } from '~/pipelines/constants';
import {
mockParsedGraphQLNodes,
diff --git a/spec/frontend/pipelines/components/dag/parsing_utils_spec.js b/spec/frontend/pipelines/components/dag/parsing_utils_spec.js
index 5d3f680a57c..84ff83883b7 100644
--- a/spec/frontend/pipelines/components/dag/parsing_utils_spec.js
+++ b/spec/frontend/pipelines/components/dag/parsing_utils_spec.js
@@ -1,3 +1,4 @@
+import { createSankey } from '~/pipelines/components/dag/drawing_utils';
import {
createNodeDict,
makeLinksFromNodes,
@@ -7,7 +8,6 @@ import {
getMaxNodes,
} from '~/pipelines/components/parsing_utils';
-import { createSankey } from '~/pipelines/components/dag/drawing_utils';
import { mockParsedGraphQLNodes } from './mock_data';
describe('DAG visualization parsing utilities', () => {
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index 00fe9e784b3..e43aa2a02f5 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -1,6 +1,6 @@
+import { GlFilteredSearch } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { GlFilteredSearch } from '@gitlab/ui';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import PipelinesFilteredSearch from '~/pipelines/components/pipelines_list/pipelines_filtered_search.vue';
diff --git a/spec/frontend/pipelines/empty_state_spec.js b/spec/frontend/pipelines/empty_state_spec.js
index 7e42a3b5ae9..3ebedc9ac87 100644
--- a/spec/frontend/pipelines/empty_state_spec.js
+++ b/spec/frontend/pipelines/empty_state_spec.js
@@ -1,7 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { withGonExperiment } from 'helpers/experimentation_helper';
import EmptyState from '~/pipelines/components/pipelines_list/empty_state.vue';
-import Tracking from '~/tracking';
describe('Pipelines Empty State', () => {
let wrapper;
@@ -40,104 +38,15 @@ describe('Pipelines Empty State', () => {
expect(findGetStartedButton().attributes('href')).toBe('foo');
});
- describe('when in control group', () => {
- it('should render empty state information', () => {
- expect(findInfoText()).toContain(
- 'Continuous Integration can help catch bugs by running your tests automatically',
- 'while Continuous Deployment can help you deliver code to your product environment',
- );
- });
-
- it('should render a button', () => {
- expect(findGetStartedButton().text()).toBe('Get started with Pipelines');
- });
- });
-
- describe('when in experiment group', () => {
- withGonExperiment('pipelinesEmptyState');
-
- beforeEach(() => {
- createWrapper();
- });
-
- it('should render empty state information', () => {
- expect(findInfoText()).toContain(
- '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',
- );
- });
-
- it('should render button text', () => {
- expect(findGetStartedButton().text()).toBe('Get started with CI/CD');
- });
+ it('should render empty state information', () => {
+ expect(findInfoText()).toContain(
+ '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',
+ );
});
- describe('tracking', () => {
- let origGon;
-
- describe('when data is set', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event').mockImplementation(() => {});
- origGon = window.gon;
-
- window.gon = {
- tracking_data: {
- category: 'Growth::Activation::Experiment::PipelinesEmptyState',
- value: 1,
- property: 'experimental_group',
- label: 'label',
- },
- };
- createWrapper();
- });
-
- afterEach(() => {
- window.gon = origGon;
- });
-
- it('tracks when mounted', () => {
- expect(Tracking.event).toHaveBeenCalledWith(
- 'Growth::Activation::Experiment::PipelinesEmptyState',
- 'viewed',
- {
- value: 1,
- label: 'label',
- property: 'experimental_group',
- },
- );
- });
-
- it('tracks when button is clicked', () => {
- findGetStartedButton().vm.$emit('click');
-
- expect(Tracking.event).toHaveBeenCalledWith(
- 'Growth::Activation::Experiment::PipelinesEmptyState',
- 'documentation_clicked',
- {
- value: 1,
- label: 'label',
- property: 'experimental_group',
- },
- );
- });
- });
-
- describe('when no data is defined', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event').mockImplementation(() => {});
-
- createWrapper();
- });
-
- it('does not track on view', () => {
- expect(Tracking.event).not.toHaveBeenCalled();
- });
-
- it('does not track when button is clicked', () => {
- findGetStartedButton().vm.$emit('click');
- expect(Tracking.event).not.toHaveBeenCalled();
- });
- });
+ it('should render button text', () => {
+ expect(findGetStartedButton().text()).toBe('Get started with CI/CD');
});
});
});
diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js
index 95d96e127c6..6a7018fa1e5 100644
--- a/spec/frontend/pipelines/graph/action_component_spec.js
+++ b/spec/frontend/pipelines/graph/action_component_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
diff --git a/spec/frontend/pipelines/graph/graph_component_legacy_spec.js b/spec/frontend/pipelines/graph/graph_component_legacy_spec.js
index 840b1f8baf5..a955572a481 100644
--- a/spec/frontend/pipelines/graph/graph_component_legacy_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_legacy_spec.js
@@ -1,14 +1,14 @@
-import { nextTick } from 'vue';
-import { mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { setHTMLFixture } from 'helpers/fixtures';
-import PipelineStore from '~/pipelines/stores/pipeline_store';
import GraphComponentLegacy from '~/pipelines/components/graph/graph_component_legacy.vue';
-import StageColumnComponentLegacy from '~/pipelines/components/graph/stage_column_component_legacy.vue';
import LinkedPipelinesColumnLegacy from '~/pipelines/components/graph/linked_pipelines_column_legacy.vue';
-import graphJSON from './mock_data_legacy';
-import linkedPipelineJSON from './linked_pipelines_mock_data';
+import StageColumnComponentLegacy from '~/pipelines/components/graph/stage_column_component_legacy.vue';
import PipelinesMediator from '~/pipelines/pipeline_details_mediator';
+import PipelineStore from '~/pipelines/stores/pipeline_store';
+import linkedPipelineJSON from './linked_pipelines_mock_data';
+import graphJSON from './mock_data_legacy';
describe('graph component', () => {
let store;
diff --git a/spec/frontend/pipelines/graph/graph_component_spec.js b/spec/frontend/pipelines/graph/graph_component_spec.js
index cfc3b7af282..3e8d4ba314c 100644
--- a/spec/frontend/pipelines/graph/graph_component_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_spec.js
@@ -1,10 +1,10 @@
import { mount, shallowMount } from '@vue/test-utils';
+import { GRAPHQL } from '~/pipelines/components/graph/constants';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
-import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
import JobItem from '~/pipelines/components/graph/job_item.vue';
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
+import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
-import { GRAPHQL } from '~/pipelines/components/graph/constants';
import {
generateResponse,
mockPipelineResponse,
@@ -22,6 +22,13 @@ describe('graph component', () => {
pipeline: generateResponse(mockPipelineResponse, 'root/fungi-xoxo'),
};
+ const defaultData = {
+ measurements: {
+ width: 800,
+ height: 800,
+ },
+ };
+
const createComponent = ({
data = {},
mountFn = shallowMount,
@@ -34,7 +41,10 @@ describe('graph component', () => {
...props,
},
data() {
- return { ...data };
+ return {
+ ...defaultData,
+ ...data,
+ };
},
provide: {
dataMethod: GRAPHQL,
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index 54593c527cb..202365ecd35 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -1,11 +1,11 @@
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import { shallowMount } from '@vue/test-utils';
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
-import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
+import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue';
import { mockPipelineResponse } from './mock_data';
const defaultProvide = {
diff --git a/spec/frontend/pipelines/graph/job_name_component_spec.js b/spec/frontend/pipelines/graph/job_name_component_spec.js
index f0aa646b8d7..658b5be87d4 100644
--- a/spec/frontend/pipelines/graph/job_name_component_spec.js
+++ b/spec/frontend/pipelines/graph/job_name_component_spec.js
@@ -1,7 +1,6 @@
import { mount } from '@vue/test-utils';
-import ciIcon from '~/vue_shared/components/ci_icon.vue';
-
import jobNameComponent from '~/pipelines/components/graph/job_name_component.vue';
+import ciIcon from '~/vue_shared/components/ci_icon.vue';
describe('job name component', () => {
let wrapper;
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index fb005d628a9..96f2cd1e371 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -1,9 +1,10 @@
-import { mount } from '@vue/test-utils';
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { UPSTREAM, DOWNSTREAM } from '~/pipelines/components/graph/constants';
import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
import mockData from './linked_pipelines_mock_data';
-import { UPSTREAM, DOWNSTREAM } from '~/pipelines/components/graph/constants';
const mockPipeline = mockData.triggered[0];
const validTriggeredPipelineId = mockPipeline.project.id;
@@ -212,11 +213,11 @@ describe('Linked pipeline', () => {
expect(wrapper.emitted().pipelineClicked).toBeTruthy();
});
- it('should emit `bv::hide::tooltip` to close the tooltip', () => {
+ it(`should emit ${BV_HIDE_TOOLTIP} to close the tooltip`, () => {
jest.spyOn(wrapper.vm.$root, '$emit');
findButton().trigger('click');
- expect(wrapper.vm.$root.$emit.mock.calls[0]).toEqual(['bv::hide::tooltip']);
+ expect(wrapper.vm.$root.$emit.mock.calls[0]).toEqual([BV_HIDE_TOOLTIP]);
});
it('should emit downstreamHovered with job name on mouseover', () => {
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_legacy_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_legacy_spec.js
index b6c700c65d2..200e3f48401 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_legacy_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_legacy_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import LinkedPipelinesColumnLegacy from '~/pipelines/components/graph/linked_pipelines_column_legacy.vue';
-import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
import { UPSTREAM } from '~/pipelines/components/graph/constants';
+import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
+import LinkedPipelinesColumnLegacy from '~/pipelines/components/graph/linked_pipelines_column_legacy.vue';
import mockData from './linked_pipelines_mock_data';
describe('Linked Pipelines Column', () => {
diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
index 6db152f2607..8f01accccc1 100644
--- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js
@@ -1,11 +1,11 @@
-import VueApollo from 'vue-apollo';
import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
+import { DOWNSTREAM, GRAPHQL, UPSTREAM } from '~/pipelines/components/graph/constants';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
-import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
-import { DOWNSTREAM, GRAPHQL } from '~/pipelines/components/graph/constants';
+import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
import { LOAD_FAILURE } from '~/pipelines/constants';
import {
mockPipelineResponse,
@@ -17,7 +17,7 @@ const processedPipeline = pipelineWithUpstreamDownstream(mockPipelineResponse);
describe('Linked Pipelines Column', () => {
const defaultProps = {
- columnTitle: 'Upstream',
+ columnTitle: 'Downstream',
linkedPipelines: processedPipeline.downstream,
type: DOWNSTREAM,
};
@@ -45,14 +45,15 @@ describe('Linked Pipelines Column', () => {
});
};
- const createComponentWithApollo = (
+ const createComponentWithApollo = ({
mountFn = shallowMount,
getPipelineDetailsHandler = jest.fn().mockResolvedValue(wrappedPipelineReturn),
- ) => {
+ props = {},
+ } = {}) => {
const requestHandlers = [[getPipelineDetails, getPipelineDetailsHandler]];
const apolloProvider = createMockApollo(requestHandlers);
- createComponent({ apolloProvider, mountFn });
+ createComponent({ apolloProvider, mountFn, props });
};
afterEach(() => {
@@ -86,34 +87,90 @@ describe('Linked Pipelines Column', () => {
await wrapper.vm.$nextTick();
};
- describe('when successful', () => {
- beforeEach(() => {
- createComponentWithApollo(mount);
+ describe('downstream', () => {
+ describe('when successful', () => {
+ beforeEach(() => {
+ createComponentWithApollo({ mountFn: mount });
+ });
+
+ it('toggles the pipeline visibility', async () => {
+ expect(findPipelineGraph().exists()).toBe(false);
+ await clickExpandButtonAndAwaitTimers();
+ expect(findPipelineGraph().exists()).toBe(true);
+ await clickExpandButton();
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
});
- it('toggles the pipeline visibility', async () => {
- expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
- expect(findPipelineGraph().exists()).toBe(true);
- await clickExpandButton();
- expect(findPipelineGraph().exists()).toBe(false);
+ describe('on error', () => {
+ beforeEach(() => {
+ createComponentWithApollo({
+ mountFn: mount,
+ getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
+ });
+ });
+
+ it('emits the error', async () => {
+ await clickExpandButton();
+ expect(wrapper.emitted().error).toEqual([[LOAD_FAILURE]]);
+ });
+
+ it('does not show the pipeline', async () => {
+ expect(findPipelineGraph().exists()).toBe(false);
+ await clickExpandButtonAndAwaitTimers();
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
});
});
- describe('on error', () => {
- beforeEach(() => {
- createComponentWithApollo(mount, jest.fn().mockRejectedValue(new Error('GraphQL error')));
- });
-
- it('emits the error', async () => {
- await clickExpandButton();
- expect(wrapper.emitted().error).toEqual([[LOAD_FAILURE]]);
+ describe('upstream', () => {
+ const upstreamProps = {
+ columnTitle: 'Upstream',
+ /*
+ Because the IDs need to match to work, rather
+ than make new mock data, we are representing
+ the upstream pipeline with the downstream data.
+ */
+ linkedPipelines: processedPipeline.downstream,
+ type: UPSTREAM,
+ };
+
+ describe('when successful', () => {
+ beforeEach(() => {
+ createComponentWithApollo({
+ mountFn: mount,
+ props: upstreamProps,
+ });
+ });
+
+ it('toggles the pipeline visibility', async () => {
+ expect(findPipelineGraph().exists()).toBe(false);
+ await clickExpandButtonAndAwaitTimers();
+ expect(findPipelineGraph().exists()).toBe(true);
+ await clickExpandButton();
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
});
- it('does not show the pipeline', async () => {
- expect(findPipelineGraph().exists()).toBe(false);
- await clickExpandButtonAndAwaitTimers();
- expect(findPipelineGraph().exists()).toBe(false);
+ describe('on error', () => {
+ beforeEach(() => {
+ createComponentWithApollo({
+ mountFn: mount,
+ getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
+ props: upstreamProps,
+ });
+ });
+
+ it('emits the error', async () => {
+ await clickExpandButton();
+ expect(wrapper.emitted().error).toEqual([[LOAD_FAILURE]]);
+ });
+
+ it('does not show the pipeline', async () => {
+ expect(findPipelineGraph().exists()).toBe(false);
+ await clickExpandButtonAndAwaitTimers();
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/pipelines/graph/stage_column_component_spec.js b/spec/frontend/pipelines/graph/stage_column_component_spec.js
index 202e25ccda3..16dc70a63a5 100644
--- a/spec/frontend/pipelines/graph/stage_column_component_spec.js
+++ b/spec/frontend/pipelines/graph/stage_column_component_spec.js
@@ -68,6 +68,10 @@ describe('stage column component', () => {
it('should render the provided groups', () => {
expect(findAllStageColumnGroups().length).toBe(mockGroups.length);
});
+
+ it('should emit updateMeasurements event on mount', () => {
+ expect(wrapper.emitted().updateMeasurements).toHaveLength(1);
+ });
});
describe('when job notifies action is complete', () => {
diff --git a/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap b/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap
new file mode 100644
index 00000000000..cf2b66dea5f
--- /dev/null
+++ b/spec/frontend/pipelines/graph_shared/__snapshots__/links_inner_spec.js.snap
@@ -0,0 +1,23 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Links Inner component with a large number of needs matches snapshot and has expected path 1`] = `
+"<div class=\\"gl-display-flex gl-relative\\"><svg id=\\"link-svg\\" viewBox=\\"0,0,1019,445\\" width=\\"1019px\\" height=\\"445px\\" class=\\"gl-absolute gl-pointer-events-none\\">
+ <path d=\\"M202,118L42,118C72,118,72,138,102,138\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ <path d=\\"M202,118L52,118C82,118,82,148,112,148\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ <path d=\\"M222,138L62,138C92,138,92,158,122,158\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ <path d=\\"M212,128L72,128C102,128,102,168,132,168\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ <path d=\\"M232,148L82,148C112,148,112,178,142,178\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ </svg> </div>"
+`;
+
+exports[`Links Inner component with a parallel need matches snapshot and has expected path 1`] = `
+"<div class=\\"gl-display-flex gl-relative\\"><svg id=\\"link-svg\\" viewBox=\\"0,0,1019,445\\" width=\\"1019px\\" height=\\"445px\\" class=\\"gl-absolute gl-pointer-events-none\\">
+ <path d=\\"M192,108L22,108C52,108,52,118,82,118\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ </svg> </div>"
+`;
+
+exports[`Links Inner component with one need matches snapshot and has expected path 1`] = `
+"<div class=\\"gl-display-flex gl-relative\\"><svg id=\\"link-svg\\" viewBox=\\"0,0,1019,445\\" width=\\"1019px\\" height=\\"445px\\" class=\\"gl-absolute gl-pointer-events-none\\">
+ <path d=\\"M202,118L42,118C72,118,72,138,102,138\\" stroke-width=\\"2\\" class=\\"gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease gl-stroke-gray-200\\"></path>
+ </svg> </div>"
+`;
diff --git a/spec/frontend/pipelines/graph_shared/links_inner_spec.js b/spec/frontend/pipelines/graph_shared/links_inner_spec.js
new file mode 100644
index 00000000000..6cabe2bc8a7
--- /dev/null
+++ b/spec/frontend/pipelines/graph_shared/links_inner_spec.js
@@ -0,0 +1,197 @@
+import { shallowMount } from '@vue/test-utils';
+import { setHTMLFixture } from 'helpers/fixtures';
+import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
+import { createJobsHash } from '~/pipelines/utils';
+import {
+ jobRect,
+ largePipelineData,
+ parallelNeedData,
+ pipelineData,
+ pipelineDataWithNoNeeds,
+ rootRect,
+} from '../pipeline_graph/mock_data';
+
+describe('Links Inner component', () => {
+ const containerId = 'pipeline-graph-container';
+ const defaultProps = {
+ containerId,
+ containerMeasurements: { width: 1019, height: 445 },
+ pipelineId: 1,
+ pipelineData: [],
+ };
+ let wrapper;
+
+ const createComponent = (props) => {
+ wrapper = shallowMount(LinksInner, {
+ propsData: { ...defaultProps, ...props },
+ });
+ };
+
+ const findLinkSvg = () => wrapper.find('#link-svg');
+ const findAllLinksPath = () => findLinkSvg().findAll('path');
+
+ // We create fixture so that each job has an empty div that represent
+ // the JobPill in the DOM. Each `JobPill` would have different coordinates,
+ // so we increment their coordinates on each iteration to simulat different positions.
+ const setFixtures = ({ stages }) => {
+ const jobs = createJobsHash(stages);
+ const arrayOfJobs = Object.keys(jobs);
+
+ const linksHtmlElements = arrayOfJobs.map((job) => {
+ return `<div id=${job}-${defaultProps.pipelineId} />`;
+ });
+
+ setHTMLFixture(`<div id="${containerId}">${linksHtmlElements.join(' ')}</div>`);
+
+ // We are mocking the clientRect data of each job and the container ID.
+ jest
+ .spyOn(document.getElementById(containerId), 'getBoundingClientRect')
+ .mockImplementation(() => rootRect);
+
+ arrayOfJobs.forEach((job, index) => {
+ jest
+ .spyOn(
+ document.getElementById(`${job}-${defaultProps.pipelineId}`),
+ 'getBoundingClientRect',
+ )
+ .mockImplementation(() => {
+ const newValue = 10 * index;
+ const { left, right, top, bottom, x, y } = jobRect;
+ return {
+ ...jobRect,
+ left: left + newValue,
+ right: right + newValue,
+ top: top + newValue,
+ bottom: bottom + newValue,
+ x: x + newValue,
+ y: y + newValue,
+ };
+ });
+ });
+ };
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('basic SVG creation', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders an SVG of the right size', () => {
+ expect(findLinkSvg().exists()).toBe(true);
+ expect(findLinkSvg().attributes('width')).toBe(
+ `${defaultProps.containerMeasurements.width}px`,
+ );
+ expect(findLinkSvg().attributes('height')).toBe(
+ `${defaultProps.containerMeasurements.height}px`,
+ );
+ });
+ });
+
+ describe('no pipeline data', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the component', () => {
+ expect(findLinkSvg().exists()).toBe(true);
+ expect(findAllLinksPath()).toHaveLength(0);
+ });
+ });
+
+ describe('pipeline data with no needs', () => {
+ beforeEach(() => {
+ createComponent({ pipelineData: pipelineDataWithNoNeeds.stages });
+ });
+
+ it('renders no links', () => {
+ expect(findLinkSvg().exists()).toBe(true);
+ expect(findAllLinksPath()).toHaveLength(0);
+ });
+ });
+
+ describe('with one need', () => {
+ beforeEach(() => {
+ setFixtures(pipelineData);
+ createComponent({ pipelineData: pipelineData.stages });
+ });
+
+ it('renders one link', () => {
+ expect(findAllLinksPath()).toHaveLength(1);
+ });
+
+ it('path does not contain NaN values', () => {
+ expect(wrapper.html()).not.toContain('NaN');
+ });
+
+ it('matches snapshot and has expected path', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+ });
+
+ describe('with a parallel need', () => {
+ beforeEach(() => {
+ setFixtures(parallelNeedData);
+ createComponent({ pipelineData: parallelNeedData.stages });
+ });
+
+ it('renders only one link for all the same parallel jobs', () => {
+ expect(findAllLinksPath()).toHaveLength(1);
+ });
+
+ it('path does not contain NaN values', () => {
+ expect(wrapper.html()).not.toContain('NaN');
+ });
+
+ it('matches snapshot and has expected path', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+ });
+
+ describe('with a large number of needs', () => {
+ beforeEach(() => {
+ setFixtures(largePipelineData);
+ createComponent({ pipelineData: largePipelineData.stages });
+ });
+
+ it('renders the correct number of links', () => {
+ expect(findAllLinksPath()).toHaveLength(5);
+ });
+
+ it('path does not contain NaN values', () => {
+ expect(wrapper.html()).not.toContain('NaN');
+ });
+
+ it('matches snapshot and has expected path', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+ });
+
+ describe('interactions', () => {
+ beforeEach(() => {
+ setFixtures(largePipelineData);
+ createComponent({ pipelineData: largePipelineData.stages });
+ });
+
+ it('highlight needs on hover', async () => {
+ const firstLink = findAllLinksPath().at(0);
+
+ const defaultColorClass = 'gl-stroke-gray-200';
+ const hoverColorClass = 'gl-stroke-blue-400';
+
+ expect(firstLink.classes(defaultColorClass)).toBe(true);
+ expect(firstLink.classes(hoverColorClass)).toBe(false);
+
+ // Because there is a watcher, we need to set the props after the component
+ // has mounted.
+ await wrapper.setProps({ highlightedJob: 'test_1' });
+
+ expect(firstLink.classes(defaultColorClass)).toBe(false);
+ expect(firstLink.classes(hoverColorClass)).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/graph_shared/links_layer_spec.js b/spec/frontend/pipelines/graph_shared/links_layer_spec.js
new file mode 100644
index 00000000000..0ff8583fbff
--- /dev/null
+++ b/spec/frontend/pipelines/graph_shared/links_layer_spec.js
@@ -0,0 +1,99 @@
+import { GlAlert, GlButton } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
+import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
+import { generateResponse, mockPipelineResponse } from '../graph/mock_data';
+
+describe('links layer component', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.find(GlAlert);
+ const findShowAnyways = () => findAlert().find(GlButton);
+ const findLinksInner = () => wrapper.find(LinksInner);
+
+ const pipeline = generateResponse(mockPipelineResponse, 'root/fungi-xoxo');
+ const containerId = `pipeline-links-container-${pipeline.id}`;
+ const slotContent = "<div>Ceci n'est pas un graphique</div>";
+
+ const tooManyStages = Array(101)
+ .fill(0)
+ .flatMap(() => pipeline.stages);
+
+ const defaultProps = {
+ containerId,
+ containerMeasurements: { width: 400, height: 400 },
+ pipelineId: pipeline.id,
+ pipelineData: pipeline.stages,
+ };
+
+ const createComponent = ({ mountFn = shallowMount, props = {} } = {}) => {
+ wrapper = mountFn(LinksLayer, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ slots: {
+ default: slotContent,
+ },
+ stubs: {
+ 'links-inner': true,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('with data under max stages', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the default slot', () => {
+ expect(wrapper.html()).toContain(slotContent);
+ });
+
+ it('renders the inner links component', () => {
+ expect(findLinksInner().exists()).toBe(true);
+ });
+ });
+
+ describe('with more than the max number of stages', () => {
+ describe('rendering', () => {
+ beforeEach(() => {
+ createComponent({ props: { pipelineData: tooManyStages } });
+ });
+
+ it('renders the default slot', () => {
+ expect(wrapper.html()).toContain(slotContent);
+ });
+
+ it('renders the alert component', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('does not render the inner links component', () => {
+ expect(findLinksInner().exists()).toBe(false);
+ });
+ });
+
+ describe('interactions', () => {
+ beforeEach(() => {
+ createComponent({ mountFn: mount, props: { pipelineData: tooManyStages } });
+ });
+
+ it('renders the disable button', () => {
+ expect(findShowAnyways().exists()).toBe(true);
+ expect(findShowAnyways().text()).toBe(wrapper.vm.$options.i18n.showLinksAnyways);
+ });
+
+ it('shows links when override is clicked', async () => {
+ expect(findLinksInner().exists()).toBe(false);
+ await findShowAnyways().trigger('click');
+ expect(findLinksInner().exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js
index 03e385e3cc8..57d846c53c8 100644
--- a/spec/frontend/pipelines/header_component_spec.js
+++ b/spec/frontend/pipelines/header_component_spec.js
@@ -1,15 +1,15 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+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 {
mockCancelledPipelineHeader,
mockFailedPipelineHeader,
mockRunningPipelineHeader,
mockSuccessfulPipelineHeader,
} from './mock_data';
-import HeaderComponent from '~/pipelines/components/header_component.vue';
-import deletePipelineMutation from '~/pipelines/graphql/mutations/delete_pipeline.mutation.graphql';
-import retryPipelineMutation from '~/pipelines/graphql/mutations/retry_pipeline.mutation.graphql';
-import cancelPipelineMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
describe('Pipeline details header', () => {
let wrapper;
diff --git a/spec/frontend/pipelines/legacy_header_component_spec.js b/spec/frontend/pipelines/legacy_header_component_spec.js
deleted file mode 100644
index fb7feb8898a..00000000000
--- a/spec/frontend/pipelines/legacy_header_component_spec.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlModal } from '@gitlab/ui';
-import LegacyHeaderComponent from '~/pipelines/components/legacy_header_component.vue';
-import CiHeader from '~/vue_shared/components/header_ci_component.vue';
-import eventHub from '~/pipelines/event_hub';
-
-describe('Pipeline details header', () => {
- let wrapper;
- let glModalDirective;
-
- const threeWeeksAgo = new Date();
- threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
-
- const findDeleteModal = () => wrapper.find(GlModal);
-
- const defaultProps = {
- pipeline: {
- details: {
- status: {
- group: 'failed',
- icon: 'status_failed',
- label: 'failed',
- text: 'failed',
- details_path: 'path',
- },
- },
- id: 123,
- created_at: threeWeeksAgo.toISOString(),
- user: {
- web_url: 'path',
- name: 'Foo',
- username: 'foobar',
- email: 'foo@bar.com',
- avatar_url: 'link',
- },
- retry_path: 'retry',
- cancel_path: 'cancel',
- delete_path: 'delete',
- },
- isLoading: false,
- };
-
- const createComponent = (props = {}) => {
- glModalDirective = jest.fn();
-
- wrapper = shallowMount(LegacyHeaderComponent, {
- propsData: {
- ...props,
- },
- directives: {
- glModal: {
- bind(el, { value }) {
- glModalDirective(value);
- },
- },
- },
- });
- };
-
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit');
-
- createComponent(defaultProps);
- });
-
- afterEach(() => {
- eventHub.$off();
-
- wrapper.destroy();
- wrapper = null;
- });
-
- it('should render provided pipeline info', () => {
- expect(wrapper.find(CiHeader).props()).toMatchObject({
- status: defaultProps.pipeline.details.status,
- itemId: defaultProps.pipeline.id,
- time: defaultProps.pipeline.created_at,
- user: defaultProps.pipeline.user,
- });
- });
-
- describe('action buttons', () => {
- it('should not trigger eventHub when nothing happens', () => {
- expect(eventHub.$emit).not.toHaveBeenCalled();
- });
-
- it('should call postAction when retry button action is clicked', () => {
- wrapper.find('[data-testid="retryButton"]').vm.$emit('click');
-
- expect(eventHub.$emit).toHaveBeenCalledWith('headerPostAction', 'retry');
- });
-
- it('should call postAction when cancel button action is clicked', () => {
- wrapper.find('[data-testid="cancelPipeline"]').vm.$emit('click');
-
- expect(eventHub.$emit).toHaveBeenCalledWith('headerPostAction', 'cancel');
- });
-
- it('does not show delete modal', () => {
- expect(findDeleteModal()).not.toBeVisible();
- });
-
- describe('when delete button action is clicked', () => {
- it('displays delete modal', () => {
- expect(findDeleteModal().props('modalId')).toBe(wrapper.vm.$options.DELETE_MODAL_ID);
- expect(glModalDirective).toHaveBeenCalledWith(wrapper.vm.$options.DELETE_MODAL_ID);
- });
-
- it('should call delete when modal is submitted', () => {
- findDeleteModal().vm.$emit('ok');
-
- expect(eventHub.$emit).toHaveBeenCalledWith('headerDeleteAction', 'delete');
- });
- });
- });
-});
diff --git a/spec/frontend/pipelines/pipeline_graph/mock_data.js b/spec/frontend/pipelines/pipeline_graph/mock_data.js
index 7d1a7a79c7f..339aac9f349 100644
--- a/spec/frontend/pipelines/pipeline_graph/mock_data.js
+++ b/spec/frontend/pipelines/pipeline_graph/mock_data.js
@@ -1,5 +1,3 @@
-import { createUniqueLinkId } from '~/pipelines/components/graph_shared/drawing_utils';
-
export const yamlString = `stages:
- empty
- build
@@ -41,10 +39,28 @@ deploy_a:
script: echo hello
`;
-const jobId1 = createUniqueLinkId('build', 'build_1');
-const jobId2 = createUniqueLinkId('test', 'test_1');
-const jobId3 = createUniqueLinkId('test', 'test_2');
-const jobId4 = createUniqueLinkId('deploy', 'deploy_1');
+export const pipelineDataWithNoNeeds = {
+ stages: [
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ },
+ ],
+ },
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'test_1',
+ jobs: [{ script: 'yarn test', stage: 'test' }],
+ },
+ ],
+ },
+ ],
+};
export const pipelineData = {
stages: [
@@ -54,7 +70,6 @@ export const pipelineData = {
{
name: 'build_1',
jobs: [{ script: 'echo hello', stage: 'build' }],
- id: jobId1,
},
],
},
@@ -64,12 +79,10 @@ export const pipelineData = {
{
name: 'test_1',
jobs: [{ script: 'yarn test', stage: 'test' }],
- id: jobId2,
},
{
name: 'test_2',
jobs: [{ script: 'yarn karma', stage: 'test' }],
- id: jobId3,
},
],
},
@@ -79,7 +92,86 @@ export const pipelineData = {
{
name: 'deploy_1',
jobs: [{ script: 'yarn magick', stage: 'deploy', needs: ['test_1'] }],
- id: jobId4,
+ },
+ ],
+ },
+ ],
+};
+
+export const parallelNeedData = {
+ stages: [
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ parallel: 3,
+ jobs: [
+ { script: 'echo hello', stage: 'build', name: 'build_1 1/3' },
+ { script: 'echo hello', stage: 'build', name: 'build_1 2/3' },
+ { script: 'echo hello', stage: 'build', name: 'build_1 3/3' },
+ ],
+ },
+ ],
+ },
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'test_1',
+ jobs: [{ script: 'yarn test', stage: 'test', needs: ['build_1'] }],
+ },
+ ],
+ },
+ ],
+};
+
+export const largePipelineData = {
+ stages: [
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ },
+ {
+ name: 'build_2',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ },
+ {
+ name: 'build_3',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ },
+ ],
+ },
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'test_1',
+ jobs: [{ script: 'yarn test', stage: 'test', needs: ['build_2'] }],
+ },
+ {
+ name: 'test_2',
+ jobs: [{ script: 'yarn karma', stage: 'test', needs: ['build_2'] }],
+ },
+ ],
+ },
+ {
+ name: 'deploy',
+ groups: [
+ {
+ name: 'deploy_1',
+ jobs: [{ script: 'yarn magick', stage: 'deploy', needs: ['test_1'] }],
+ },
+ {
+ name: 'deploy_2',
+ jobs: [{ script: 'yarn magick', stage: 'deploy', needs: ['build_3'] }],
+ },
+ {
+ name: 'deploy_3',
+ jobs: [{ script: 'yarn magick', stage: 'deploy', needs: ['test_2'] }],
},
],
},
@@ -94,9 +186,30 @@ export const singleStageData = {
{
name: 'build_1',
jobs: [{ script: 'echo hello', stage: 'build' }],
- id: jobId1,
},
],
},
],
};
+
+export const rootRect = {
+ bottom: 463,
+ height: 271,
+ left: 236,
+ right: 1252,
+ top: 192,
+ width: 1016,
+ x: 236,
+ y: 192,
+};
+
+export const jobRect = {
+ bottom: 312,
+ height: 24,
+ left: 308,
+ right: 428,
+ top: 288,
+ width: 120,
+ x: 308,
+ y: 288,
+};
diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
index b6b0a964383..718667fcc73 100644
--- a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
+++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert } from '@gitlab/ui';
-import { pipelineData, singleStageData } from './mock_data';
+import { shallowMount } from '@vue/test-utils';
import { CI_CONFIG_STATUS_INVALID, CI_CONFIG_STATUS_VALID } from '~/pipeline_editor/constants';
-import { DRAW_FAILURE, EMPTY_PIPELINE_DATA, INVALID_CI_CONFIG } from '~/pipelines/constants';
+import JobPill from '~/pipelines/components/pipeline_graph/job_pill.vue';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import StagePill from '~/pipelines/components/pipeline_graph/stage_pill.vue';
-import JobPill from '~/pipelines/components/pipeline_graph/job_pill.vue';
+import { DRAW_FAILURE, EMPTY_PIPELINE_DATA, INVALID_CI_CONFIG } from '~/pipelines/constants';
+import { pipelineData, singleStageData } from './mock_data';
describe('pipeline graph component', () => {
const defaultProps = { pipelineData };
diff --git a/spec/frontend/pipelines/pipeline_triggerer_spec.js b/spec/frontend/pipelines/pipeline_triggerer_spec.js
index ad8136890e6..467a97d95c7 100644
--- a/spec/frontend/pipelines/pipeline_triggerer_spec.js
+++ b/spec/frontend/pipelines/pipeline_triggerer_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import pipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_triggerer.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
describe('Pipelines Triggerer', () => {
let wrapper;
diff --git a/spec/frontend/pipelines/pipeline_url_spec.js b/spec/frontend/pipelines/pipeline_url_spec.js
index 47315bd42e6..44c9def99cc 100644
--- a/spec/frontend/pipelines/pipeline_url_spec.js
+++ b/spec/frontend/pipelines/pipeline_url_spec.js
@@ -1,6 +1,6 @@
+import { shallowMount } from '@vue/test-utils';
import $ from 'jquery';
import { trimText } from 'helpers/text_helper';
-import { shallowMount } from '@vue/test-utils';
import PipelineUrlComponent from '~/pipelines/components/pipelines_list/pipeline_url.vue';
$.fn.popover = () => {};
@@ -17,6 +17,7 @@ describe('Pipeline Url Component', () => {
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: {
@@ -141,6 +142,7 @@ describe('Pipeline Url Component', () => {
expect(findScheduledTag().exists()).toBe(true);
expect(findScheduledTag().text()).toContain('Scheduled');
});
+
it('should render the fork badge when the pipeline was run in a fork', () => {
createComponent({
pipeline: {
@@ -152,4 +154,28 @@ describe('Pipeline Url Component', () => {
expect(findForkTag().exists()).toBe(true);
expect(findForkTag().text()).toBe('fork');
});
+
+ it('should render the train badge when the pipeline is a merge train pipeline', () => {
+ createComponent({
+ pipeline: {
+ flags: {
+ merge_train_pipeline: true,
+ },
+ },
+ });
+
+ expect(findTrainTag().text()).toContain('train');
+ });
+
+ it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
+ createComponent({
+ pipeline: {
+ flags: {
+ merge_train_pipeline: false,
+ },
+ },
+ });
+
+ expect(findTrainTag().exists()).toBe(false);
+ });
});
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index 69c1b7ce43d..1e6c9e50a7e 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -1,25 +1,29 @@
-import { shallowMount } from '@vue/test-utils';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
-import { GlButton } from '@gitlab/ui';
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 PipelinesActions from '~/pipelines/components/pipelines_list/pipelines_actions.vue';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
+jest.mock('~/flash');
+
describe('Pipelines Actions dropdown', () => {
let wrapper;
let mock;
- const createComponent = (actions = []) => {
- wrapper = shallowMount(PipelinesActions, {
+ const createComponent = (props, mountFn = shallowMount) => {
+ wrapper = mountFn(PipelinesActions, {
propsData: {
- actions,
+ ...props,
},
});
};
- const findAllDropdownItems = () => wrapper.findAll(GlButton);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
const findAllCountdowns = () => wrapper.findAll(GlCountdown);
beforeEach(() => {
@@ -47,7 +51,7 @@ describe('Pipelines Actions dropdown', () => {
];
beforeEach(() => {
- createComponent(mockActions);
+ createComponent({ actions: mockActions });
});
it('renders a dropdown with the provided actions', () => {
@@ -59,16 +63,33 @@ describe('Pipelines Actions dropdown', () => {
});
describe('on click', () => {
- it('makes a request and toggles the loading state', () => {
+ beforeEach(() => {
+ createComponent({ actions: mockActions }, mount);
+ });
+
+ it('makes a request and toggles the loading state', async () => {
mock.onPost(mockActions.path).reply(200);
- wrapper.find(GlButton).vm.$emit('click');
+ findAllDropdownItems().at(0).vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().props('loading')).toBe(true);
+
+ await waitForPromises();
+ expect(findDropdown().props('loading')).toBe(false);
+ });
+
+ it('makes a failed request and toggles the loading state', async () => {
+ mock.onPost(mockActions.path).reply(500);
- expect(wrapper.vm.isLoading).toBe(true);
+ findAllDropdownItems().at(0).vm.$emit('click');
- return waitForPromises().then(() => {
- expect(wrapper.vm.isLoading).toBe(false);
- });
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().props('loading')).toBe(true);
+
+ await waitForPromises();
+ expect(findDropdown().props('loading')).toBe(false);
+ expect(createFlash).toHaveBeenCalledTimes(1);
});
});
});
@@ -89,10 +110,10 @@ describe('Pipelines Actions dropdown', () => {
beforeEach(() => {
jest.spyOn(Date, 'now').mockImplementation(() => new Date('2063-04-04T00:42:00Z').getTime());
- createComponent([scheduledJobAction, expiredJobAction]);
+ createComponent({ actions: [scheduledJobAction, expiredJobAction] });
});
- it('makes post request after confirming', () => {
+ it('makes post request after confirming', async () => {
mock.onPost(scheduledJobAction.path).reply(200);
jest.spyOn(window, 'confirm').mockReturnValue(true);
@@ -100,19 +121,22 @@ describe('Pipelines Actions dropdown', () => {
expect(window.confirm).toHaveBeenCalled();
- return waitForPromises().then(() => {
- expect(mock.history.post.length).toBe(1);
- });
+ await waitForPromises();
+
+ expect(mock.history.post).toHaveLength(1);
});
- it('does not make post request if confirmation is cancelled', () => {
+ it('does not make post request if confirmation is cancelled', async () => {
mock.onPost(scheduledJobAction.path).reply(200);
jest.spyOn(window, 'confirm').mockReturnValue(false);
findAllDropdownItems().at(0).vm.$emit('click');
expect(window.confirm).toHaveBeenCalled();
- expect(mock.history.post.length).toBe(0);
+
+ await waitForPromises();
+
+ expect(mock.history.post).toHaveLength(0);
});
it('displays the remaining time in the dropdown', () => {
diff --git a/spec/frontend/pipelines/pipelines_artifacts_spec.js b/spec/frontend/pipelines/pipelines_artifacts_spec.js
index 4f4c15fd4cc..f077833ae16 100644
--- a/spec/frontend/pipelines/pipelines_artifacts_spec.js
+++ b/spec/frontend/pipelines/pipelines_artifacts_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
describe('Pipelines Artifacts dropdown', () => {
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index 5d82669b0b8..811303a5624 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -1,49 +1,50 @@
-import { nextTick } from 'vue';
+import { GlFilteredSearch, GlButton, GlLoadingIcon, GlPagination } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { chunk } from 'lodash';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { GlFilteredSearch, GlButton, GlLoadingIcon } from '@gitlab/ui';
import Api from '~/api';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
-import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
-
-import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
-import EmptyState from '~/pipelines/components/pipelines_list/empty_state.vue';
import BlankState from '~/pipelines/components/pipelines_list/blank_state.vue';
-import PipelinesTableComponent from '~/pipelines/components/pipelines_list/pipelines_table.vue';
-
+import EmptyState from '~/pipelines/components/pipelines_list/empty_state.vue';
+import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue';
import PipelinesComponent from '~/pipelines/components/pipelines_list/pipelines.vue';
+import PipelinesTableComponent from '~/pipelines/components/pipelines_list/pipelines_table.vue';
+import { RAW_TEXT_WARNING } from '~/pipelines/constants';
import Store from '~/pipelines/stores/pipelines_store';
+import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+
import { pipelineWithStages, stageReply, users, mockSearch, branches } from './mock_data';
-import { RAW_TEXT_WARNING } from '~/pipelines/constants';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
-describe('Pipelines', () => {
- const jsonFixtureName = 'pipelines/pipelines.json';
+const mockProjectPath = 'twitter/flight';
+const mockProjectId = '21';
+const mockPipelinesEndpoint = `/${mockProjectPath}/pipelines.json`;
+const mockPipelinesResponse = getJSONFixture('pipelines/pipelines.json');
+const mockPipelinesIds = mockPipelinesResponse.pipelines.map(({ id }) => id);
- preloadFixtures(jsonFixtureName);
-
- let pipelines;
+describe('Pipelines', () => {
let wrapper;
let mock;
+ let origWindowLocation;
const paths = {
- endpoint: 'twitter/flight/pipelines.json',
autoDevopsHelpPath: '/help/topics/autodevops/index.md',
helpPagePath: '/help/ci/quick_start/README',
emptyStateSvgPath: '/assets/illustrations/pipelines_empty.svg',
errorStateSvgPath: '/assets/illustrations/pipelines_failed.svg',
noPipelinesSvgPath: '/assets/illustrations/pipelines_pending.svg',
ciLintPath: '/ci/lint',
- resetCachePath: '/twitter/flight/settings/ci_cd/reset_cache',
- newPipelinePath: '/twitter/flight/pipelines/new',
+ resetCachePath: `${mockProjectPath}/settings/ci_cd/reset_cache`,
+ newPipelinePath: `${mockProjectPath}/pipelines/new`,
};
const noPermissions = {
- endpoint: 'twitter/flight/pipelines.json',
autoDevopsHelpPath: '/help/topics/autodevops/index.md',
helpPagePath: '/help/ci/quick_start/README',
emptyStateSvgPath: '/assets/illustrations/pipelines_empty.svg',
@@ -57,101 +58,140 @@ describe('Pipelines', () => {
...paths,
};
- const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
- const findByTestId = (id) => wrapper.find(`[data-testid="${id}"]`);
- const findNavigationTabs = () => wrapper.find(NavigationTabs);
- const findNavigationControls = () => wrapper.find(NavigationControls);
- const findTab = (tab) => findByTestId(`pipelines-tab-${tab}`);
-
- const findRunPipelineButton = () => findByTestId('run-pipeline-button');
- const findCiLintButton = () => findByTestId('ci-lint-button');
- const findCleanCacheButton = () => findByTestId('clear-cache-button');
-
- const findEmptyState = () => wrapper.find(EmptyState);
- const findBlankState = () => wrapper.find(BlankState);
- const findStagesDropdown = () => wrapper.find('.js-builds-dropdown-button');
-
- const findTablePagination = () => wrapper.find(TablePagination);
+ const findFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
+ const findNavigationTabs = () => wrapper.findComponent(NavigationTabs);
+ const findNavigationControls = () => wrapper.findComponent(NavigationControls);
+ const findPipelinesTable = () => wrapper.findComponent(PipelinesTableComponent);
+ const findEmptyState = () => wrapper.findComponent(EmptyState);
+ const findBlankState = () => wrapper.findComponent(BlankState);
+ const findTablePagination = () => wrapper.findComponent(TablePagination);
+
+ const findTab = (tab) => wrapper.findByTestId(`pipelines-tab-${tab}`);
+ const findRunPipelineButton = () => wrapper.findByTestId('run-pipeline-button');
+ const findCiLintButton = () => wrapper.findByTestId('ci-lint-button');
+ const findCleanCacheButton = () => wrapper.findByTestId('clear-cache-button');
+ const findStagesDropdown = () => wrapper.findByTestId('mini-pipeline-graph-dropdown-toggle');
+ const findPipelineUrlLinks = () => wrapper.findAll('[data-testid="pipeline-url-link"]');
const createComponent = (props = defaultProps) => {
- wrapper = mount(PipelinesComponent, {
- propsData: {
- store: new Store(),
- projectId: '21',
- params: {},
- ...props,
- },
- });
+ wrapper = extendedWrapper(
+ mount(PipelinesComponent, {
+ propsData: {
+ store: new Store(),
+ projectId: mockProjectId,
+ endpoint: mockPipelinesEndpoint,
+ params: {},
+ ...props,
+ },
+ }),
+ );
};
- beforeEach(() => {
+ beforeAll(() => {
+ origWindowLocation = window.location;
delete window.location;
+ window.location = { search: '' };
+ });
+
+ afterAll(() => {
+ window.location = origWindowLocation;
});
beforeEach(() => {
- window.location = { search: '' };
mock = new MockAdapter(axios);
- pipelines = getJSONFixture(jsonFixtureName);
+ jest.spyOn(window.history, 'pushState');
jest.spyOn(Api, 'projectUsers').mockResolvedValue(users);
jest.spyOn(Api, 'branches').mockResolvedValue({ data: branches });
});
afterEach(() => {
wrapper.destroy();
- mock.restore();
+ mock.reset();
+ window.history.pushState.mockReset();
});
- describe('With permission', () => {
- describe('With pipelines in main tab', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
- createComponent();
- return waitForPromises();
- });
+ describe('when pipelines are not yet loaded', () => {
+ beforeEach(async () => {
+ createComponent();
+ await nextTick();
+ });
- it('renders tabs', () => {
- expect(findTab('all').text()).toContain('All');
- });
+ it('shows loading state when the app is loading', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
- it('renders Run Pipeline link', () => {
- expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
+ it('does not display tabs when the first request has not yet been made', () => {
+ expect(findNavigationTabs().exists()).toBe(false);
+ });
+
+ it('does not display buttons', () => {
+ expect(findNavigationControls().exists()).toBe(false);
+ });
+ });
+
+ describe('when there are pipelines in the project', () => {
+ beforeEach(() => {
+ mock
+ .onGet(mockPipelinesEndpoint, { params: { scope: 'all', page: '1' } })
+ .reply(200, mockPipelinesResponse);
+ });
+
+ describe('when user has no permissions', () => {
+ beforeEach(async () => {
+ createComponent({ hasGitlabCi: true, canCreatePipeline: false, ...noPermissions });
+ await waitForPromises();
});
- it('renders CI Lint link', () => {
- expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
+ it('renders "All" tab with count different from "0"', () => {
+ expect(findTab('all').text()).toMatchInterpolatedText('All 3');
});
- it('renders Clear Runner Cache button', () => {
- expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
+ it('does not render buttons', () => {
+ expect(findNavigationControls().exists()).toBe(false);
+
+ expect(findRunPipelineButton().exists()).toBe(false);
+ expect(findCiLintButton().exists()).toBe(false);
+ expect(findCleanCacheButton().exists()).toBe(false);
});
- it('renders pipelines table', () => {
- expect(wrapper.findAll('.gl-responsive-table-row')).toHaveLength(
- pipelines.pipelines.length + 1,
- );
+ it('renders pipelines in a table', () => {
+ expect(findPipelinesTable().exists()).toBe(true);
+
+ expect(findPipelineUrlLinks()).toHaveLength(mockPipelinesIds.length);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${mockPipelinesIds[0]}`);
+ expect(findPipelineUrlLinks().at(1).text()).toBe(`#${mockPipelinesIds[1]}`);
+ expect(findPipelineUrlLinks().at(2).text()).toBe(`#${mockPipelinesIds[2]}`);
});
});
- describe('Without pipelines on main tab with CI', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
- });
-
+ describe('when user has permissions', () => {
+ beforeEach(async () => {
createComponent();
+ await waitForPromises();
+ });
- return waitForPromises();
+ it('should set up navigation tabs', () => {
+ expect(findNavigationTabs().props('tabs')).toEqual([
+ { name: 'All', scope: 'all', count: '3', isActive: true },
+ { name: 'Finished', scope: 'finished', count: undefined, isActive: false },
+ { name: 'Branches', scope: 'branches', isActive: false },
+ { name: 'Tags', scope: 'tags', isActive: false },
+ ]);
});
- it('renders tabs', () => {
- expect(findTab('all').text()).toContain('All');
+ it('renders "All" tab with count different from "0"', () => {
+ expect(findTab('all').text()).toMatchInterpolatedText('All 3');
+ });
+
+ it('should render other navigation tabs', () => {
+ expect(findTab('finished').text()).toBe('Finished');
+ expect(findTab('branches').text()).toBe('Branches');
+ expect(findTab('tags').text()).toBe('Tags');
+ });
+
+ it('shows navigation controls', () => {
+ expect(findNavigationControls().exists()).toBe(true);
});
it('renders Run Pipeline link', () => {
@@ -166,549 +206,513 @@ describe('Pipelines', () => {
expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
});
- it('renders tab empty state', () => {
- expect(findBlankState().text()).toBe('There are currently no pipelines.');
- });
-
- it('renders tab empty state finished scope', () => {
- wrapper.vm.scope = 'finished';
+ it('renders pipelines in a table', () => {
+ expect(findPipelinesTable().exists()).toBe(true);
- return nextTick().then(() => {
- expect(findBlankState().text()).toBe('There are currently no finished pipelines.');
- });
+ expect(findPipelineUrlLinks()).toHaveLength(mockPipelinesIds.length);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${mockPipelinesIds[0]}`);
+ expect(findPipelineUrlLinks().at(1).text()).toBe(`#${mockPipelinesIds[1]}`);
+ expect(findPipelineUrlLinks().at(2).text()).toBe(`#${mockPipelinesIds[2]}`);
});
- });
-
- describe('Without pipelines nor CI', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
- });
- createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...paths });
+ describe('when user goes to a tab', () => {
+ const goToTab = (tab) => {
+ findNavigationTabs().vm.$emit('onChangeTab', tab);
+ };
- return waitForPromises();
- });
+ describe('when the scope in the tab has pipelines', () => {
+ const mockFinishedPipeline = mockPipelinesResponse.pipelines[0];
- it('renders empty state', () => {
- expect(findEmptyState().find('h4').text()).toBe('Build with confidence');
- expect(findEmptyState().find(GlButton).attributes('href')).toBe(paths.helpPagePath);
- });
+ beforeEach(async () => {
+ mock
+ .onGet(mockPipelinesEndpoint, { params: { scope: 'finished', page: '1' } })
+ .reply(200, {
+ pipelines: [mockFinishedPipeline],
+ count: mockPipelinesResponse.count,
+ });
- it('does not render tabs nor buttons', () => {
- expect(findTab('all').exists()).toBe(false);
- expect(findRunPipelineButton().exists()).toBeFalsy();
- expect(findCiLintButton().exists()).toBeFalsy();
- expect(findCleanCacheButton().exists()).toBeFalsy();
- });
- });
+ goToTab('finished');
- describe('When API returns error', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(500, {});
- createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...paths });
+ await waitForPromises();
+ });
- return waitForPromises();
- });
+ it('should filter pipelines', async () => {
+ expect(findPipelinesTable().exists()).toBe(true);
- it('renders tabs', () => {
- expect(findTab('all').text()).toContain('All');
- });
+ expect(findPipelineUrlLinks()).toHaveLength(1);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${mockFinishedPipeline.id}`);
+ });
- it('renders buttons', () => {
- expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
+ it('should update browser bar', () => {
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ `${window.location.pathname}?scope=finished&page=1`,
+ );
+ });
+ });
- expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
- expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
- });
+ describe('when the scope in the tab is empty', () => {
+ beforeEach(async () => {
+ mock
+ .onGet(mockPipelinesEndpoint, { params: { scope: 'branches', page: '1' } })
+ .reply(200, {
+ pipelines: [],
+ count: mockPipelinesResponse.count,
+ });
- it('renders error state', () => {
- expect(findBlankState().text()).toContain('There was an error fetching the pipelines.');
- });
- });
- });
+ goToTab('branches');
- describe('Without permission', () => {
- describe('With pipelines in main tab', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
+ await waitForPromises();
+ });
- createComponent({ hasGitlabCi: false, canCreatePipeline: false, ...noPermissions });
+ it('should filter pipelines', async () => {
+ expect(findBlankState().text()).toBe('There are currently no pipelines.');
+ });
- return waitForPromises();
+ it('should update browser bar', () => {
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ `${window.location.pathname}?scope=branches&page=1`,
+ );
+ });
+ });
});
- it('renders tabs', () => {
- expect(findTab('all').text()).toContain('All');
- });
+ describe('when user triggers a filtered search', () => {
+ const mockFilteredPipeline = mockPipelinesResponse.pipelines[1];
- it('does not render buttons', () => {
- expect(findRunPipelineButton().exists()).toBeFalsy();
- expect(findCiLintButton().exists()).toBeFalsy();
- expect(findCleanCacheButton().exists()).toBeFalsy();
- });
+ let expectedParams;
- it('renders pipelines table', () => {
- expect(wrapper.findAll('.gl-responsive-table-row')).toHaveLength(
- pipelines.pipelines.length + 1,
- );
- });
- });
+ beforeEach(async () => {
+ expectedParams = {
+ page: '1',
+ scope: 'all',
+ username: 'root',
+ ref: 'master',
+ status: 'pending',
+ };
+
+ mock
+ .onGet(mockPipelinesEndpoint, {
+ params: expectedParams,
+ })
+ .replyOnce(200, {
+ pipelines: [mockFilteredPipeline],
+ count: mockPipelinesResponse.count,
+ });
- describe('Without pipelines on main tab with CI', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
+ findFilteredSearch().vm.$emit('submit', mockSearch);
+
+ await waitForPromises();
});
- createComponent({ hasGitlabCi: true, canCreatePipeline: false, ...noPermissions });
+ it('requests data with query params on filter submit', async () => {
+ expect(mock.history.get[1].params).toEqual(expectedParams);
+ });
- return waitForPromises();
- });
+ it('renders filtered pipelines', async () => {
+ expect(findPipelineUrlLinks()).toHaveLength(1);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${mockFilteredPipeline.id}`);
+ });
- it('renders tabs', () => {
- expect(findTab('all').text()).toContain('All');
+ it('should update browser bar', () => {
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ `${window.location.pathname}?page=1&scope=all&username=root&ref=master&status=pending`,
+ );
+ });
});
- it('does not render buttons', () => {
- expect(findRunPipelineButton().exists()).toBeFalsy();
- expect(findCiLintButton().exists()).toBeFalsy();
- expect(findCleanCacheButton().exists()).toBeFalsy();
- });
+ describe('when user triggers a filtered search with raw text', () => {
+ beforeEach(async () => {
+ findFilteredSearch().vm.$emit('submit', ['rawText']);
- it('renders tab empty state', () => {
- expect(wrapper.find('.empty-state h4').text()).toBe('There are currently no pipelines.');
- });
- });
+ await waitForPromises();
+ });
- describe('Without pipelines nor CI', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [],
- count: {
- all: 0,
- pending: 0,
- running: 0,
- finished: 0,
- },
+ it('requests data with query params on filter submit', async () => {
+ expect(mock.history.get[1].params).toEqual({ page: '1', scope: 'all' });
});
- createComponent({ hasGitlabCi: false, canCreatePipeline: false, ...noPermissions });
+ it('displays a warning message if raw text search is used', () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith(RAW_TEXT_WARNING, 'warning');
+ });
- return waitForPromises();
+ it('should update browser bar', () => {
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ `${window.location.pathname}?page=1&scope=all`,
+ );
+ });
});
+ });
+ });
- it('renders empty state without button to set CI', () => {
- expect(findEmptyState().text()).toBe(
- 'This project is not currently set up to run pipelines.',
- );
+ describe('when there are multiple pages of pipelines', () => {
+ const mockPageSize = 2;
+ const mockPageHeaders = ({ page = 1 } = {}) => {
+ return {
+ 'X-PER-PAGE': `${mockPageSize}`,
+ 'X-PREV-PAGE': `${page - 1}`,
+ 'X-PAGE': `${page}`,
+ 'X-NEXT-PAGE': `${page + 1}`,
+ };
+ };
+ const [firstPage, secondPage] = chunk(mockPipelinesResponse.pipelines, mockPageSize);
+
+ const goToPage = (page) => {
+ findTablePagination().find(GlPagination).vm.$emit('input', page);
+ };
+
+ beforeEach(async () => {
+ mock.onGet(mockPipelinesEndpoint, { params: { scope: 'all', page: '1' } }).reply(
+ 200,
+ {
+ pipelines: firstPage,
+ count: mockPipelinesResponse.count,
+ },
+ mockPageHeaders({ page: 1 }),
+ );
+ mock.onGet(mockPipelinesEndpoint, { params: { scope: 'all', page: '2' } }).reply(
+ 200,
+ {
+ pipelines: secondPage,
+ count: mockPipelinesResponse.count,
+ },
+ mockPageHeaders({ page: 2 }),
+ );
- expect(findEmptyState().find(GlButton).exists()).toBeFalsy();
- });
+ createComponent();
- it('does not render tabs or buttons', () => {
- expect(findTab('all').exists()).toBe(false);
- expect(findRunPipelineButton().exists()).toBeFalsy();
- expect(findCiLintButton().exists()).toBeFalsy();
- expect(findCleanCacheButton().exists()).toBeFalsy();
- });
+ await waitForPromises();
});
- describe('When API returns error', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(500, {});
-
- createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...noPermissions });
+ it('shows the first page of pipelines', () => {
+ expect(findPipelineUrlLinks()).toHaveLength(firstPage.length);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${firstPage[0].id}`);
+ expect(findPipelineUrlLinks().at(1).text()).toBe(`#${firstPage[1].id}`);
+ });
- return waitForPromises();
- });
+ it('should not update browser bar', () => {
+ expect(window.history.pushState).not.toHaveBeenCalled();
+ });
- it('renders tabs', () => {
- expect(findTab('all').text()).toContain('All');
+ describe('when user goes to next page', () => {
+ beforeEach(async () => {
+ goToPage(2);
+ await waitForPromises();
});
- it('does not renders buttons', () => {
- expect(findRunPipelineButton().exists()).toBeFalsy();
- expect(findCiLintButton().exists()).toBeFalsy();
- expect(findCleanCacheButton().exists()).toBeFalsy();
+ it('should update page and keep scope the same scope', () => {
+ expect(findPipelineUrlLinks()).toHaveLength(secondPage.length);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${secondPage[0].id}`);
});
- it('renders error state', () => {
- expect(wrapper.find('.empty-state').text()).toContain(
- 'There was an error fetching the pipelines.',
+ it('should update browser bar', () => {
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.anything(),
+ `${window.location.pathname}?page=2&scope=all`,
);
});
});
});
- describe('successful request', () => {
- describe('with pipelines', () => {
- beforeEach(() => {
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
+ describe('when pipelines can be polled', () => {
+ beforeEach(() => {
+ const emptyResponse = {
+ pipelines: [],
+ count: { all: '0' },
+ };
+ // Mock no pipelines in the first attempt
+ mock
+ .onGet(mockPipelinesEndpoint, { params: { scope: 'all', page: '1' } })
+ .replyOnce(200, emptyResponse, {
+ 'POLL-INTERVAL': 100,
+ });
+ // Mock pipelines in the next attempt
+ mock
+ .onGet(mockPipelinesEndpoint, { params: { scope: 'all', page: '1' } })
+ .reply(200, mockPipelinesResponse, {
+ 'POLL-INTERVAL': 100,
+ });
+ });
+
+ describe('data is loaded for the first time', () => {
+ beforeEach(async () => {
createComponent();
- return waitForPromises();
+ await waitForPromises();
});
- it('should render table', () => {
- expect(wrapper.findAll('.gl-responsive-table-row')).toHaveLength(
- pipelines.pipelines.length + 1,
- );
+ it('shows tabs', () => {
+ expect(findNavigationTabs().exists()).toBe(true);
});
- it('should set up navigation tabs', () => {
- expect(findNavigationTabs().props('tabs')).toEqual([
- { name: 'All', scope: 'all', count: '3', isActive: true },
- { name: 'Finished', scope: 'finished', count: undefined, isActive: false },
- { name: 'Branches', scope: 'branches', isActive: false },
- { name: 'Tags', scope: 'tags', isActive: false },
- ]);
+ it('should update page and keep scope the same scope', () => {
+ expect(findPipelineUrlLinks()).toHaveLength(0);
});
- it('should render navigation tabs', () => {
- expect(findTab('all').html()).toContain('All');
- expect(findTab('finished').text()).toContain('Finished');
- expect(findTab('branches').text()).toContain('Branches');
- expect(findTab('tags').text()).toContain('Tags');
- });
-
- it('should make an API request when using tabs', () => {
- createComponent({ hasGitlabCi: true, canCreatePipeline: true, ...paths });
- jest.spyOn(wrapper.vm.service, 'getPipelines');
-
- return waitForPromises().then(() => {
- findTab('finished').trigger('click');
-
- expect(wrapper.vm.service.getPipelines).toHaveBeenCalledWith({
- scope: 'finished',
- page: '1',
- });
+ describe('data is loaded for a second time', () => {
+ beforeEach(async () => {
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
});
- });
-
- describe('with pagination', () => {
- it('should make an API request when using pagination', () => {
- createComponent({ hasGitlabCi: true, canCreatePipeline: true, ...paths });
- jest.spyOn(wrapper.vm.service, 'getPipelines');
- return waitForPromises()
- .then(() => {
- // Mock pagination
- wrapper.vm.store.state.pageInfo = {
- page: 1,
- total: 10,
- perPage: 2,
- nextPage: 2,
- totalPages: 5,
- };
+ it('shows tabs', () => {
+ expect(findNavigationTabs().exists()).toBe(true);
+ });
- return nextTick();
- })
- .then(() => {
- wrapper.find('.next-page-item').trigger('click');
- expect(wrapper.vm.service.getPipelines).toHaveBeenCalledWith({
- scope: 'all',
- page: '2',
- });
- });
+ it('is loading after a time', async () => {
+ expect(findPipelineUrlLinks()).toHaveLength(mockPipelinesIds.length);
+ expect(findPipelineUrlLinks().at(0).text()).toBe(`#${mockPipelinesIds[0]}`);
+ expect(findPipelineUrlLinks().at(1).text()).toBe(`#${mockPipelinesIds[1]}`);
+ expect(findPipelineUrlLinks().at(2).text()).toBe(`#${mockPipelinesIds[2]}`);
});
});
});
});
- describe('User Interaction', () => {
- let updateContentMock;
-
+ describe('when no pipelines exist', () => {
beforeEach(() => {
- jest.spyOn(window.history, 'pushState').mockImplementation(() => null);
- });
-
- beforeEach(() => {
- mock.onGet(paths.endpoint).reply(200, pipelines);
- createComponent();
-
- updateContentMock = jest.spyOn(wrapper.vm, 'updateContent');
-
- return waitForPromises();
+ mock.onGet(mockPipelinesEndpoint, { params: { scope: 'all', page: '1' } }).reply(200, {
+ pipelines: [],
+ count: { all: '0' },
+ });
});
- describe('when user changes tabs', () => {
- it('should set page to 1', () => {
- findNavigationTabs().vm.$emit('onChangeTab', 'running');
+ describe('when CI is enabled and user has permissions', () => {
+ beforeEach(async () => {
+ createComponent();
+ await waitForPromises();
+ });
- expect(updateContentMock).toHaveBeenCalledWith({ scope: 'running', page: '1' });
+ it('renders tab with count of "0"', () => {
+ expect(findNavigationTabs().exists()).toBe(true);
+ expect(findTab('all').text()).toMatchInterpolatedText('All 0');
});
- });
- describe('when user changes page', () => {
- it('should update page and keep scope', () => {
- findTablePagination().vm.change(4);
+ it('renders Run Pipeline link', () => {
+ expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
+ });
- expect(updateContentMock).toHaveBeenCalledWith({ scope: wrapper.vm.scope, page: '4' });
+ it('renders CI Lint link', () => {
+ expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
});
- });
- describe('updates results when a staged is clicked', () => {
- beforeEach(() => {
- const copyPipeline = { ...pipelineWithStages };
- copyPipeline.id += 1;
- mock
- .onGet('twitter/flight/pipelines.json')
- .reply(
- 200,
- {
- pipelines: [pipelineWithStages],
- count: {
- all: 1,
- finished: 1,
- pending: 0,
- running: 0,
- },
- },
- {
- 'POLL-INTERVAL': 100,
- },
- )
- .onGet(pipelineWithStages.details.stages[0].dropdown_path)
- .reply(200, stageReply);
+ it('renders Clear Runner Cache button', () => {
+ expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
+ });
- createComponent();
+ it('renders empty state', () => {
+ expect(findBlankState().text()).toBe('There are currently no pipelines.');
});
- describe('when a request is being made', () => {
- it('stops polling, cancels the request, & restarts polling', () => {
- const stopMock = jest.spyOn(wrapper.vm.poll, 'stop');
- const restartMock = jest.spyOn(wrapper.vm.poll, 'restart');
- const cancelMock = jest.spyOn(wrapper.vm.service.cancelationSource, 'cancel');
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
-
- return waitForPromises()
- .then(() => {
- wrapper.vm.isMakingRequest = true;
- findStagesDropdown().trigger('click');
- })
- .then(() => {
- expect(cancelMock).toHaveBeenCalled();
- expect(stopMock).toHaveBeenCalled();
- expect(restartMock).toHaveBeenCalled();
- });
+ it('renders tab empty state finished scope', async () => {
+ mock.onGet(mockPipelinesEndpoint, { params: { scope: 'finished', page: '1' } }).reply(200, {
+ pipelines: [],
+ count: { all: '0' },
});
- });
- describe('when no request is being made', () => {
- it('stops polling & restarts polling', () => {
- const stopMock = jest.spyOn(wrapper.vm.poll, 'stop');
- const restartMock = jest.spyOn(wrapper.vm.poll, 'restart');
- mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
+ findNavigationTabs().vm.$emit('onChangeTab', 'finished');
- return waitForPromises()
- .then(() => {
- findStagesDropdown().trigger('click');
- expect(stopMock).toHaveBeenCalled();
- })
- .then(() => {
- expect(restartMock).toHaveBeenCalled();
- });
- });
- });
- });
- });
+ await waitForPromises();
- describe('Rendered content', () => {
- beforeEach(() => {
- createComponent();
+ expect(findBlankState().text()).toBe('There are currently no finished pipelines.');
+ });
});
- describe('displays different content', () => {
- it('shows loading state when the app is loading', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ describe('when CI is not enabled and user has permissions', () => {
+ beforeEach(async () => {
+ createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...paths });
+ await waitForPromises();
});
- it('shows error state when app has error', () => {
- wrapper.vm.hasError = true;
- wrapper.vm.isLoading = false;
-
- return nextTick().then(() => {
- expect(findBlankState().props('message')).toBe(
- 'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
- );
- });
+ it('renders empty state', () => {
+ expect(findEmptyState().find('[data-testid="header-text"]').text()).toBe(
+ 'Build with confidence',
+ );
+ expect(findEmptyState().find('[data-testid="info-text"]').text()).toContain(
+ 'GitLab CI/CD can automatically build, test, and deploy your code.',
+ );
+ expect(findEmptyState().find(GlButton).text()).toBe('Get started with CI/CD');
+ expect(findEmptyState().find(GlButton).attributes('href')).toBe(paths.helpPagePath);
});
- it('shows table list when app has pipelines', () => {
- wrapper.vm.isLoading = false;
- wrapper.vm.hasError = false;
- wrapper.vm.state.pipelines = pipelines.pipelines;
-
- return nextTick().then(() => {
- expect(wrapper.find(PipelinesTableComponent).exists()).toBe(true);
- });
+ it('does not render tabs nor buttons', () => {
+ expect(findNavigationTabs().exists()).toBe(false);
+ expect(findTab('all').exists()).toBe(false);
+ expect(findRunPipelineButton().exists()).toBe(false);
+ expect(findCiLintButton().exists()).toBe(false);
+ expect(findCleanCacheButton().exists()).toBe(false);
});
+ });
- it('shows empty tab when app does not have pipelines but project has pipelines', () => {
- wrapper.vm.state.count.all = 10;
- wrapper.vm.isLoading = false;
-
- return nextTick().then(() => {
- expect(findBlankState().exists()).toBe(true);
- expect(findBlankState().props('message')).toBe('There are currently no pipelines.');
- });
+ describe('when CI is not enabled and user has no permissions', () => {
+ beforeEach(async () => {
+ createComponent({ hasGitlabCi: false, canCreatePipeline: false, ...noPermissions });
+ await waitForPromises();
});
- it('shows empty tab when project has CI', () => {
- wrapper.vm.isLoading = false;
+ it('renders empty state without button to set CI', () => {
+ expect(findEmptyState().text()).toBe(
+ 'This project is not currently set up to run pipelines.',
+ );
- return nextTick().then(() => {
- expect(findBlankState().exists()).toBe(true);
- expect(findBlankState().props('message')).toBe('There are currently no pipelines.');
- });
+ expect(findEmptyState().find(GlButton).exists()).toBe(false);
});
- it('shows empty state when project does not have pipelines nor CI', () => {
- createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...paths });
-
- wrapper.vm.isLoading = false;
-
- return nextTick().then(() => {
- expect(wrapper.find(EmptyState).exists()).toBe(true);
- });
+ it('does not render tabs or buttons', () => {
+ expect(findTab('all').exists()).toBe(false);
+ expect(findRunPipelineButton().exists()).toBe(false);
+ expect(findCiLintButton().exists()).toBe(false);
+ expect(findCleanCacheButton().exists()).toBe(false);
});
});
- describe('displays tabs', () => {
- it('returns true when state is loading & has already made the first request', () => {
- wrapper.vm.isLoading = true;
- wrapper.vm.hasMadeRequest = true;
+ describe('when CI is enabled and user has no permissions', () => {
+ beforeEach(() => {
+ createComponent({ hasGitlabCi: true, canCreatePipeline: false, ...noPermissions });
- return nextTick().then(() => {
- expect(findNavigationTabs().exists()).toBe(true);
- });
+ return waitForPromises();
});
- it('returns true when state is tableList & has already made the first request', () => {
- wrapper.vm.isLoading = false;
- wrapper.vm.state.pipelines = pipelines.pipelines;
- wrapper.vm.hasMadeRequest = true;
-
- return nextTick().then(() => {
- expect(findNavigationTabs().exists()).toBe(true);
- });
+ it('renders tab with count of "0"', () => {
+ expect(findTab('all').text()).toMatchInterpolatedText('All 0');
});
- it('returns true when state is error & has already made the first request', () => {
- wrapper.vm.isLoading = false;
- wrapper.vm.hasError = true;
- wrapper.vm.hasMadeRequest = true;
+ it('does not render buttons', () => {
+ expect(findRunPipelineButton().exists()).toBe(false);
+ expect(findCiLintButton().exists()).toBe(false);
+ expect(findCleanCacheButton().exists()).toBe(false);
+ });
- return nextTick().then(() => {
- expect(findNavigationTabs().exists()).toBe(true);
- });
+ it('renders empty state', () => {
+ expect(findBlankState().text()).toBe('There are currently no pipelines.');
});
+ });
+ });
- it('returns true when state is empty tab & has already made the first request', () => {
- wrapper.vm.isLoading = false;
- wrapper.vm.state.count.all = 10;
- wrapper.vm.hasMadeRequest = true;
+ describe('when a pipeline with stages exists', () => {
+ describe('updates results when a staged is clicked', () => {
+ let stopMock;
+ let restartMock;
+ let cancelMock;
- return nextTick().then(() => {
- expect(findNavigationTabs().exists()).toBe(true);
- });
- });
+ beforeEach(() => {
+ mock.onGet(mockPipelinesEndpoint, { scope: 'all', page: '1' }).reply(
+ 200,
+ {
+ pipelines: [pipelineWithStages],
+ count: { all: '1' },
+ },
+ {
+ 'POLL-INTERVAL': 100,
+ },
+ );
+ mock.onGet(pipelineWithStages.details.stages[0].dropdown_path).reply(200, stageReply);
- it('returns false when has not made first request', () => {
- wrapper.vm.hasMadeRequest = false;
+ createComponent();
- return nextTick().then(() => {
- expect(findNavigationTabs().exists()).toBe(false);
- });
+ stopMock = jest.spyOn(wrapper.vm.poll, 'stop');
+ restartMock = jest.spyOn(wrapper.vm.poll, 'restart');
+ cancelMock = jest.spyOn(wrapper.vm.service.cancelationSource, 'cancel');
});
- it('returns false when state is empty state', () => {
- createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...paths });
-
- wrapper.vm.isLoading = false;
- wrapper.vm.hasMadeRequest = true;
+ describe('when a request is being made', () => {
+ beforeEach(async () => {
+ mock.onGet(mockPipelinesEndpoint).reply(200, mockPipelinesResponse);
- return nextTick().then(() => {
- expect(findNavigationTabs().exists()).toBe(false);
+ await waitForPromises();
});
- });
- });
- describe('displays buttons', () => {
- it('returns true when it has paths & has made the first request', () => {
- wrapper.vm.hasMadeRequest = true;
+ it('stops polling, cancels the request, & restarts polling', async () => {
+ // Mock init a polling cycle
+ wrapper.vm.poll.options.notificationCallback(true);
+
+ findStagesDropdown().trigger('click');
- return nextTick().then(() => {
- expect(findNavigationControls().exists()).toBe(true);
+ await waitForPromises();
+
+ expect(cancelMock).toHaveBeenCalled();
+ expect(stopMock).toHaveBeenCalled();
+ expect(restartMock).toHaveBeenCalled();
});
- });
- it('returns false when it has not made the first request', () => {
- wrapper.vm.hasMadeRequest = false;
+ it('stops polling & restarts polling', async () => {
+ findStagesDropdown().trigger('click');
- return nextTick().then(() => {
- expect(findNavigationControls().exists()).toBe(false);
+ expect(cancelMock).not.toHaveBeenCalled();
+ expect(stopMock).toHaveBeenCalled();
+ expect(restartMock).toHaveBeenCalled();
});
});
});
});
- describe('Pipeline filters', () => {
- let updateContentMock;
-
- beforeEach(() => {
- mock.onGet(paths.endpoint).reply(200, pipelines);
- createComponent();
+ describe('when pipelines cannot be loaded', () => {
+ beforeEach(async () => {
+ mock.onGet(mockPipelinesEndpoint).reply(500, {});
+ });
- updateContentMock = jest.spyOn(wrapper.vm, 'updateContent');
+ describe('when user has no permissions', () => {
+ beforeEach(async () => {
+ createComponent({ hasGitlabCi: false, canCreatePipeline: true, ...noPermissions });
- return waitForPromises();
- });
+ await waitForPromises();
+ });
- it('updates request data and query params on filter submit', async () => {
- const expectedQueryParams = {
- page: '1',
- scope: 'all',
- username: 'root',
- ref: 'master',
- status: 'pending',
- };
+ it('renders tabs', () => {
+ expect(findNavigationTabs().exists()).toBe(true);
+ expect(findTab('all').text()).toBe('All');
+ });
- findFilteredSearch().vm.$emit('submit', mockSearch);
- await nextTick();
+ it('does not render buttons', () => {
+ expect(findRunPipelineButton().exists()).toBe(false);
+ expect(findCiLintButton().exists()).toBe(false);
+ expect(findCleanCacheButton().exists()).toBe(false);
+ });
- expect(wrapper.vm.requestData).toEqual(expectedQueryParams);
- expect(updateContentMock).toHaveBeenCalledWith(expectedQueryParams);
+ it('shows error state', () => {
+ expect(findBlankState().text()).toBe(
+ 'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
+ );
+ });
});
- it('does not add query params if raw text search is used', async () => {
- const expectedQueryParams = { page: '1', scope: 'all' };
+ describe('when user has permissions', () => {
+ beforeEach(async () => {
+ createComponent();
- findFilteredSearch().vm.$emit('submit', ['rawText']);
- await nextTick();
+ await waitForPromises();
+ });
- expect(wrapper.vm.requestData).toEqual(expectedQueryParams);
- expect(updateContentMock).toHaveBeenCalledWith(expectedQueryParams);
- });
+ it('renders tabs', () => {
+ expect(findTab('all').text()).toBe('All');
+ });
+
+ it('renders buttons', () => {
+ expect(findRunPipelineButton().attributes('href')).toBe(paths.newPipelinePath);
- it('displays a warning message if raw text search is used', () => {
- findFilteredSearch().vm.$emit('submit', ['rawText']);
+ expect(findCiLintButton().attributes('href')).toBe(paths.ciLintPath);
+ expect(findCleanCacheButton().text()).toBe('Clear Runner Caches');
+ });
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(RAW_TEXT_WARNING, 'warning');
+ it('shows error state', () => {
+ expect(findBlankState().text()).toBe(
+ 'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
+ );
+ });
});
});
});
diff --git a/spec/frontend/pipelines/pipelines_table_row_spec.js b/spec/frontend/pipelines/pipelines_table_row_spec.js
index 9cdd24b2ab5..660651547fc 100644
--- a/spec/frontend/pipelines/pipelines_table_row_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_row_spec.js
@@ -155,7 +155,9 @@ describe('Pipelines Table Row', () => {
it('should render an icon for each stage', () => {
expect(
- wrapper.findAll('.table-section:nth-child(4) .js-builds-dropdown-button').length,
+ wrapper.findAll(
+ '.table-section:nth-child(4) [data-testid="mini-pipeline-graph-dropdown-toggle"]',
+ ).length,
).toEqual(pipeline.details.stages.length);
});
});
diff --git a/spec/frontend/pipelines/shared/links_layer_spec.js b/spec/frontend/pipelines/shared/links_layer_spec.js
deleted file mode 100644
index 9ef5233dbce..00000000000
--- a/spec/frontend/pipelines/shared/links_layer_spec.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import { mount, shallowMount } from '@vue/test-utils';
-import { GlAlert, GlButton } from '@gitlab/ui';
-import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
-import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
-import { generateResponse, mockPipelineResponse } from '../graph/mock_data';
-
-describe('links layer component', () => {
- let wrapper;
-
- const findAlert = () => wrapper.find(GlAlert);
- const findShowAnyways = () => findAlert().find(GlButton);
- const findLinksInner = () => wrapper.find(LinksInner);
-
- const pipeline = generateResponse(mockPipelineResponse, 'root/fungi-xoxo');
- const containerId = `pipeline-links-container-${pipeline.id}`;
- const slotContent = "<div>Ceci n'est pas un graphique</div>";
-
- const tooManyStages = Array(101)
- .fill(0)
- .flatMap(() => pipeline.stages);
-
- const defaultProps = {
- containerId,
- containerMeasurements: { width: 400, height: 400 },
- pipelineId: pipeline.id,
- pipelineData: pipeline.stages,
- };
-
- const createComponent = ({ mountFn = shallowMount, props = {} } = {}) => {
- wrapper = mountFn(LinksLayer, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- slots: {
- default: slotContent,
- },
- stubs: {
- 'links-inner': true,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('with data under max stages', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders the default slot', () => {
- expect(wrapper.html()).toContain(slotContent);
- });
-
- it('renders the inner links component', () => {
- expect(findLinksInner().exists()).toBe(true);
- });
- });
-
- describe('with more than the max number of stages', () => {
- describe('rendering', () => {
- beforeEach(() => {
- createComponent({ props: { pipelineData: tooManyStages } });
- });
-
- it('renders the default slot', () => {
- expect(wrapper.html()).toContain(slotContent);
- });
-
- it('renders the alert component', () => {
- expect(findAlert().exists()).toBe(true);
- });
-
- it('does not render the inner links component', () => {
- expect(findLinksInner().exists()).toBe(false);
- });
- });
-
- describe('interactions', () => {
- beforeEach(() => {
- createComponent({ mountFn: mount, props: { pipelineData: tooManyStages } });
- });
-
- it('renders the disable button', () => {
- expect(findShowAnyways().exists()).toBe(true);
- expect(findShowAnyways().text()).toBe(wrapper.vm.$options.i18n.showLinksAnyways);
- });
-
- it('shows links when override is clicked', async () => {
- expect(findLinksInner().exists()).toBe(false);
- await findShowAnyways().trigger('click');
- expect(findLinksInner().exists()).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/pipelines/stage_spec.js b/spec/frontend/pipelines/stage_spec.js
index e4782a1dab1..87b43558252 100644
--- a/spec/frontend/pipelines/stage_spec.js
+++ b/spec/frontend/pipelines/stage_spec.js
@@ -1,6 +1,8 @@
import 'bootstrap/js/dist/dropdown';
+import { GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import StageComponent from '~/pipelines/components/pipelines_list/stage.vue';
import eventHub from '~/pipelines/event_hub';
@@ -9,6 +11,7 @@ import { stageReply } from './mock_data';
describe('Pipelines stage component', () => {
let wrapper;
let mock;
+ let glFeatures;
const defaultProps = {
stage: {
@@ -22,8 +25,6 @@ describe('Pipelines stage component', () => {
updateDropdown: false,
};
- const isDropdownOpen = () => wrapper.classes('show');
-
const createComponent = (props = {}) => {
wrapper = mount(StageComponent, {
attachTo: document.body,
@@ -31,110 +32,265 @@ describe('Pipelines stage component', () => {
...defaultProps,
...props,
},
+ provide: {
+ glFeatures,
+ },
});
};
beforeEach(() => {
mock = new MockAdapter(axios);
+ jest.spyOn(eventHub, '$emit');
+ glFeatures = {};
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ eventHub.$emit.mockRestore();
mock.restore();
});
- describe('default', () => {
- beforeEach(() => {
- createComponent();
+ describe('when ci_mini_pipeline_gl_dropdown feature flag is disabled', () => {
+ const isDropdownOpen = () => wrapper.classes('show');
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should render a dropdown with the status icon', () => {
+ expect(wrapper.attributes('class')).toEqual('dropdown');
+ expect(wrapper.find('svg').exists()).toBe(true);
+ expect(wrapper.find('button').attributes('data-toggle')).toEqual('dropdown');
+ });
});
- it('should render a dropdown with the status icon', () => {
- expect(wrapper.attributes('class')).toEqual('dropdown');
- expect(wrapper.find('svg').exists()).toBe(true);
- expect(wrapper.find('button').attributes('data-toggle')).toEqual('dropdown');
+ describe('with successful request', () => {
+ beforeEach(() => {
+ mock.onGet('path.json').reply(200, stageReply);
+ createComponent();
+ });
+
+ it('should render the received data and emit `clickedDropdown` event', async () => {
+ wrapper.find('button').trigger('click');
+
+ await axios.waitForAll();
+ expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
+ stageReply.latest_statuses[0].name,
+ );
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
+ });
});
- });
- describe('with successful request', () => {
- beforeEach(() => {
- mock.onGet('path.json').reply(200, stageReply);
+ it('when request fails should close the dropdown', async () => {
+ mock.onGet('path.json').reply(500);
createComponent();
- });
+ wrapper.find({ ref: 'dropdown' }).trigger('click');
- it('should render the received data and emit `clickedDropdown` event', async () => {
- jest.spyOn(eventHub, '$emit');
- wrapper.find('button').trigger('click');
+ expect(isDropdownOpen()).toBe(true);
+ wrapper.find('button').trigger('click');
await axios.waitForAll();
- expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
- stageReply.latest_statuses[0].name,
- );
- expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
+ expect(isDropdownOpen()).toBe(false);
});
- });
- it('when request fails should close the dropdown', async () => {
- mock.onGet('path.json').reply(500);
- createComponent();
- wrapper.find({ ref: 'dropdown' }).trigger('click');
- expect(isDropdownOpen()).toBe(true);
+ describe('update endpoint correctly', () => {
+ beforeEach(() => {
+ const copyStage = { ...stageReply };
+ copyStage.latest_statuses[0].name = 'this is the updated content';
+ mock.onGet('bar.json').reply(200, copyStage);
+ createComponent({
+ stage: {
+ status: {
+ group: 'running',
+ icon: 'status_running',
+ title: 'running',
+ },
+ dropdown_path: 'bar.json',
+ },
+ });
+ return axios.waitForAll();
+ });
+
+ it('should update the stage to request the new endpoint provided', async () => {
+ wrapper.find('button').trigger('click');
+ await axios.waitForAll();
+
+ expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
+ 'this is the updated content',
+ );
+ });
+ });
+
+ describe('pipelineActionRequestComplete', () => {
+ beforeEach(() => {
+ mock.onGet('path.json').reply(200, stageReply);
+ mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
+ });
+
+ const clickCiAction = async () => {
+ wrapper.find('button').trigger('click');
+ await axios.waitForAll();
+
+ wrapper.find('.js-ci-action').trigger('click');
+ await axios.waitForAll();
+ };
+
+ describe('within pipeline table', () => {
+ it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
+ createComponent({ type: 'PIPELINES_TABLE' });
+
+ await clickCiAction();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
+ });
+ });
+
+ describe('in MR widget', () => {
+ beforeEach(() => {
+ jest.spyOn($.fn, 'dropdown');
+ });
- wrapper.find('button').trigger('click');
- await axios.waitForAll();
+ it('closes the dropdown when `pipelineActionRequestComplete` is triggered', async () => {
+ createComponent();
- expect(isDropdownOpen()).toBe(false);
+ await clickCiAction();
+
+ expect($.fn.dropdown).toHaveBeenCalledWith('toggle');
+ });
+ });
+ });
});
- describe('update endpoint correctly', () => {
+ describe('when ci_mini_pipeline_gl_dropdown feature flag is enabled', () => {
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdownToggle = () => wrapper.find('button.gl-dropdown-toggle');
+ const findDropdownMenu = () =>
+ wrapper.find('[data-testid="mini-pipeline-graph-dropdown-menu-list"]');
+ const findCiActionBtn = () => wrapper.find('.js-ci-action');
+
+ const openGlDropdown = () => {
+ findDropdownToggle().trigger('click');
+ return new Promise((resolve) => {
+ wrapper.vm.$root.$on('bv::dropdown::show', resolve);
+ });
+ };
+
beforeEach(() => {
- const copyStage = { ...stageReply };
- copyStage.latest_statuses[0].name = 'this is the updated content';
- mock.onGet('bar.json').reply(200, copyStage);
- createComponent({
- stage: {
- status: {
- group: 'running',
- icon: 'status_running',
- title: 'running',
- },
- dropdown_path: 'bar.json',
- },
+ glFeatures = { ciMiniPipelineGlDropdown: true };
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should render a dropdown with the status icon', () => {
+ expect(findDropdown().exists()).toBe(true);
+ expect(findDropdownToggle().classes('gl-dropdown-toggle')).toEqual(true);
+ expect(wrapper.find('[data-testid="status_success_borderless-icon"]').exists()).toBe(true);
});
- return axios.waitForAll();
});
- it('should update the stage to request the new endpoint provided', async () => {
- wrapper.find('button').trigger('click');
+ describe('with successful request', () => {
+ beforeEach(() => {
+ mock.onGet('path.json').reply(200, stageReply);
+ createComponent();
+ });
+
+ it('should render the received data and emit `clickedDropdown` event', async () => {
+ await openGlDropdown();
+ await axios.waitForAll();
+
+ expect(findDropdownMenu().text()).toContain(stageReply.latest_statuses[0].name);
+ expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
+ });
+ });
+
+ it('when request fails should close the dropdown', async () => {
+ mock.onGet('path.json').reply(500);
+
+ createComponent();
+
+ await openGlDropdown();
await axios.waitForAll();
- expect(wrapper.find('.js-builds-dropdown-container ul').text()).toContain(
- 'this is the updated content',
- );
+ expect(findDropdown().classes('show')).toBe(false);
});
- });
- describe('pipelineActionRequestComplete', () => {
- beforeEach(() => {
- mock.onGet('path.json').reply(200, stageReply);
- mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
+ describe('update endpoint correctly', () => {
+ beforeEach(async () => {
+ const copyStage = { ...stageReply };
+ copyStage.latest_statuses[0].name = 'this is the updated content';
+ mock.onGet('bar.json').reply(200, copyStage);
+ createComponent({
+ stage: {
+ status: {
+ group: 'running',
+ icon: 'status_running',
+ title: 'running',
+ },
+ dropdown_path: 'bar.json',
+ },
+ });
+ await axios.waitForAll();
+ });
- createComponent({ type: 'PIPELINES_TABLE' });
+ it('should update the stage to request the new endpoint provided', async () => {
+ await openGlDropdown();
+ await axios.waitForAll();
+
+ expect(findDropdownMenu().text()).toContain('this is the updated content');
+ });
});
- describe('within pipeline table', () => {
- it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
- jest.spyOn(eventHub, '$emit');
+ describe('pipelineActionRequestComplete', () => {
+ beforeEach(() => {
+ mock.onGet('path.json').reply(200, stageReply);
+ mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
+ });
- wrapper.find('button').trigger('click');
+ const clickCiAction = async () => {
+ await openGlDropdown();
await axios.waitForAll();
- wrapper.find('.js-ci-action').trigger('click');
+ findCiActionBtn().trigger('click');
await axios.waitForAll();
+ };
+
+ describe('within pipeline table', () => {
+ beforeEach(() => {
+ createComponent({ type: 'PIPELINES_TABLE' });
+ });
+
+ it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
+ await clickCiAction();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
+ });
+ });
+
+ describe('in MR widget', () => {
+ beforeEach(() => {
+ jest.spyOn($.fn, 'dropdown');
+ createComponent();
+ });
+
+ it('closes the dropdown when `pipelineActionRequestComplete` is triggered', async () => {
+ const hidden = jest.fn();
+
+ wrapper.vm.$root.$on('bv::dropdown::hide', hidden);
+
+ expect(hidden).toHaveBeenCalledTimes(0);
+
+ await clickCiAction();
- expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
+ expect(hidden).toHaveBeenCalledTimes(1);
+ });
});
});
});
diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
index f7ff36c0a46..6258b08dfbb 100644
--- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
@@ -2,10 +2,10 @@ import MockAdapter from 'axios-mock-adapter';
import { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/pipelines/stores/test_reports/actions';
import * as types from '~/pipelines/stores/test_reports/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash.js');
@@ -16,7 +16,7 @@ describe('Actions TestReports Store', () => {
const testReports = getJSONFixture('pipelines/test_report.json');
const summary = { total_count: 1 };
- const suiteEndpoint = `${TEST_HOST}/tests/:suite_name.json`;
+ const suiteEndpoint = `${TEST_HOST}/tests/suite.json`;
const summaryEndpoint = `${TEST_HOST}/test_reports/summary.json`;
const defaultState = {
suiteEndpoint,
@@ -69,9 +69,8 @@ describe('Actions TestReports Store', () => {
beforeEach(() => {
const buildIds = [1];
testReports.test_suites[0].build_ids = buildIds;
- const endpoint = suiteEndpoint.replace(':suite_name', testReports.test_suites[0].name);
mock
- .onGet(endpoint, { params: { build_ids: buildIds } })
+ .onGet(suiteEndpoint, { params: { build_ids: buildIds } })
.replyOnce(200, testReports.test_suites[0], {});
});
diff --git a/spec/frontend/pipelines/test_reports/stores/getters_spec.js b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
index 7382a6beefa..f8298fdaba5 100644
--- a/spec/frontend/pipelines/test_reports/stores/getters_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
@@ -1,6 +1,10 @@
import { getJSONFixture } from 'helpers/fixtures';
import * as getters from '~/pipelines/stores/test_reports/getters';
-import { iconForTestStatus, formattedTime } from '~/pipelines/stores/test_reports/utils';
+import {
+ iconForTestStatus,
+ formatFilePath,
+ formattedTime,
+} from '~/pipelines/stores/test_reports/utils';
describe('Getters TestReports Store', () => {
let state;
@@ -8,6 +12,7 @@ describe('Getters TestReports Store', () => {
const testReports = getJSONFixture('pipelines/test_report.json');
const defaultState = {
+ blobPath: '/test/blob/path',
testReports,
selectedSuiteIndex: 0,
pageInfo: {
@@ -17,6 +22,7 @@ describe('Getters TestReports Store', () => {
};
const emptyState = {
+ blobPath: '',
testReports: {},
selectedSuite: null,
pageInfo: {
@@ -74,6 +80,7 @@ describe('Getters TestReports Store', () => {
const expected = testReports.test_suites[0].test_cases
.map((x) => ({
...x,
+ filePath: `${state.blobPath}/${formatFilePath(x.file)}`,
formattedTime: formattedTime(x.execution_time),
icon: iconForTestStatus(x.status),
}))
@@ -87,6 +94,70 @@ describe('Getters TestReports Store', () => {
expect(getters.getSuiteTests(state)).toEqual([]);
});
+
+ describe('when a test case classname property is null', () => {
+ it('should return an empty string value for the classname property', () => {
+ const testCases = testReports.test_suites[0].test_cases;
+ setupState({
+ ...defaultState,
+ testReports: {
+ ...testReports,
+ test_suites: [
+ {
+ test_cases: testCases.map((testCase) => ({
+ ...testCase,
+ classname: null,
+ })),
+ },
+ ],
+ },
+ });
+
+ const expected = testCases
+ .map((x) => ({
+ ...x,
+ classname: '',
+ filePath: `${state.blobPath}/${formatFilePath(x.file)}`,
+ formattedTime: formattedTime(x.execution_time),
+ icon: iconForTestStatus(x.status),
+ }))
+ .slice(0, state.pageInfo.perPage);
+
+ expect(getters.getSuiteTests(state)).toEqual(expected);
+ });
+ });
+
+ describe('when a test case name property is null', () => {
+ it('should return an empty string value for the name property', () => {
+ const testCases = testReports.test_suites[0].test_cases;
+ setupState({
+ ...defaultState,
+ testReports: {
+ ...testReports,
+ test_suites: [
+ {
+ test_cases: testCases.map((testCase) => ({
+ ...testCase,
+ name: null,
+ })),
+ },
+ ],
+ },
+ });
+
+ const expected = testCases
+ .map((x) => ({
+ ...x,
+ name: '',
+ filePath: `${state.blobPath}/${formatFilePath(x.file)}`,
+ formattedTime: formattedTime(x.execution_time),
+ icon: iconForTestStatus(x.status),
+ }))
+ .slice(0, state.pageInfo.perPage);
+
+ expect(getters.getSuiteTests(state)).toEqual(expected);
+ });
+ });
});
describe('getSuiteTestCount', () => {
diff --git a/spec/frontend/pipelines/test_reports/stores/utils_spec.js b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
index 7e632d099fc..703fe69026c 100644
--- a/spec/frontend/pipelines/test_reports/stores/utils_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
@@ -1,6 +1,20 @@
-import { formattedTime } from '~/pipelines/stores/test_reports/utils';
+import { formatFilePath, formattedTime } from '~/pipelines/stores/test_reports/utils';
describe('Test reports utils', () => {
+ describe('formatFilePath', () => {
+ it.each`
+ file | expected
+ ${'./test.js'} | ${'test.js'}
+ ${'/test.js'} | ${'test.js'}
+ ${'.//////////////test.js'} | ${'test.js'}
+ ${'test.js'} | ${'test.js'}
+ ${'mock/path./test.js'} | ${'mock/path./test.js'}
+ ${'./mock/path./test.js'} | ${'mock/path./test.js'}
+ `('should format $file to be $expected', ({ file, expected }) => {
+ expect(formatFilePath(file)).toBe(expected);
+ });
+ });
+
describe('formattedTime', () => {
describe('when time is smaller than a second', () => {
it('should return time in milliseconds fixed to 2 decimals', () => {
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 bfb8b43778d..e866586a2c3 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
@@ -11,12 +11,17 @@ describe('Test case details', () => {
classname: 'spec.test_spec',
name: 'Test#something cool',
formattedTime: '10.04ms',
+ recent_failures: {
+ count: 2,
+ base_branch: 'master',
+ },
system_output: 'Line 42 is broken',
};
const findModal = () => wrapper.find(GlModal);
const findName = () => wrapper.find('[data-testid="test-case-name"]');
const findDuration = () => wrapper.find('[data-testid="test-case-duration"]');
+ const findRecentFailures = () => wrapper.find('[data-testid="test-case-recent-failures"]');
const findSystemOutput = () => wrapper.find('[data-testid="test-case-trace"]');
const createComponent = (testCase = {}) => {
@@ -56,6 +61,36 @@ describe('Test case details', () => {
});
});
+ describe('when test case has recent failures', () => {
+ describe('has only 1 recent failure', () => {
+ it('renders the recent failure', () => {
+ createComponent({ recent_failures: { ...defaultTestCase.recent_failures, count: 1 } });
+
+ expect(findRecentFailures().text()).toContain(
+ `Failed 1 time in ${defaultTestCase.recent_failures.base_branch} in the last 14 days`,
+ );
+ });
+ });
+
+ describe('has more than 1 recent failure', () => {
+ it('renders the recent failures', () => {
+ createComponent();
+
+ expect(findRecentFailures().text()).toContain(
+ `Failed ${defaultTestCase.recent_failures.count} times in ${defaultTestCase.recent_failures.base_branch} in the last 14 days`,
+ );
+ });
+ });
+ });
+
+ describe('when test case does not have recent failures', () => {
+ it('does not render the recent failures', () => {
+ createComponent({ recent_failures: null });
+
+ expect(findRecentFailures().exists()).toBe(false);
+ });
+ });
+
describe('when test case has system output', () => {
it('renders the test case system output', () => {
createComponent();
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
index c8ab18b9086..da5763ddf8e 100644
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
import TestReports from '~/pipelines/components/test_reports/test_reports.vue';
import TestSummary from '~/pipelines/components/test_reports/test_summary.vue';
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 b8fd056610b..a87145cc557 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -1,10 +1,11 @@
-import Vuex from 'vuex';
+import { GlButton, GlFriendlyWrap, GlLink, GlPagination } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
-import { GlButton, GlFriendlyWrap, GlPagination } from '@gitlab/ui';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
-import * as getters from '~/pipelines/stores/test_reports/getters';
import { TestStatus } from '~/pipelines/constants';
+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();
@@ -20,15 +21,18 @@ describe('Test reports suite table', () => {
testSuite.test_cases = [...testSuite.test_cases, ...skippedTestCases];
const testCases = testSuite.test_cases;
+ const blobPath = '/test/blob/path';
const noCasesMessage = () => wrapper.find('.js-no-test-cases');
const allCaseRows = () => wrapper.findAll('.js-case-row');
const findCaseRowAtIndex = (index) => wrapper.findAll('.js-case-row').at(index);
+ const findLinkForRow = (row) => row.find(GlLink);
const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuite, perPage = 20) => {
store = new Vuex.Store({
state: {
+ blobPath,
testReports: {
test_suites: [suite],
},
@@ -64,7 +68,7 @@ describe('Test reports suite table', () => {
beforeEach(() => createComponent());
it('renders the correct number of rows', () => {
- expect(allCaseRows().length).toBe(testCases.length);
+ expect(allCaseRows()).toHaveLength(testCases.length);
});
it.each([
@@ -82,9 +86,13 @@ describe('Test reports suite table', () => {
it('renders the file name for the test with a copy button', () => {
const { file } = testCases[0];
+ const relativeFile = formatFilePath(file);
+ const filePath = `${blobPath}/${relativeFile}`;
const row = findCaseRowAtIndex(0);
+ const fileLink = findLinkForRow(row);
const button = row.find(GlButton);
+ expect(fileLink.attributes('href')).toBe(filePath);
expect(row.text()).toContain(file);
expect(button.exists()).toBe(true);
expect(button.attributes('data-clipboard-text')).toBe(file);
@@ -106,4 +114,32 @@ describe('Test reports suite table', () => {
expect(wrapper.find(GlPagination).exists()).toBe(true);
});
});
+
+ describe('when a test case classname property is null', () => {
+ it('still renders all test cases', () => {
+ createComponent({
+ ...testSuite,
+ test_cases: testSuite.test_cases.map((testCase) => ({
+ ...testCase,
+ classname: null,
+ })),
+ });
+
+ expect(allCaseRows()).toHaveLength(testCases.length);
+ });
+ });
+
+ describe('when a test case name property is null', () => {
+ it('still renders all test cases', () => {
+ createComponent({
+ ...testSuite,
+ test_cases: testSuite.test_cases.map((testCase) => ({
+ ...testCase,
+ name: null,
+ })),
+ });
+
+ expect(allCaseRows()).toHaveLength(testCases.length);
+ });
+ });
});
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 b585536ae09..892a3742fea 100644
--- a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
diff --git a/spec/frontend/pipelines/time_ago_spec.js b/spec/frontend/pipelines/time_ago_spec.js
index b7bc8d08a0f..55a19ef5165 100644
--- a/spec/frontend/pipelines/time_ago_spec.js
+++ b/spec/frontend/pipelines/time_ago_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import TimeAgo from '~/pipelines/components/pipelines_list/time_ago.vue';
describe('Timeago component', () => {
diff --git a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
index 371ba5a4f9b..7ddbbb3b005 100644
--- a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
+++ b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
@@ -1,6 +1,6 @@
import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlLoadingIcon } from '@gitlab/ui';
-import { stubComponent } from 'helpers/stub_component';
import { shallowMount } from '@vue/test-utils';
+import { stubComponent } from 'helpers/stub_component';
import Api from '~/api';
import PipelineTriggerAuthorToken from '~/pipelines/components/pipelines_list/tokens/pipeline_trigger_author_token.vue';
import { users } from '../mock_data';
diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js
index 63e0b3d9c49..0c164d97564 100644
--- a/spec/frontend/popovers/components/popovers_spec.js
+++ b/spec/frontend/popovers/components/popovers_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlPopover } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { useMockMutationObserver } from 'helpers/mock_dom_observer';
import Popovers from '~/popovers/components/popovers.vue';
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 63e27473979..f1784500baf 100644
--- a/spec/frontend/profile/account/components/delete_account_modal_spec.js
+++ b/spec/frontend/profile/account/components/delete_account_modal_spec.js
@@ -1,8 +1,8 @@
+import { mount } from '@vue/test-utils';
+import { merge } from 'lodash';
import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import { merge } from 'lodash';
-import { mount } from '@vue/test-utils';
import deleteAccountModal from '~/profile/account/components/delete_account_modal.vue';
const GlModalStub = {
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index 91c3c81ab30..8295d1d43cf 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
diff --git a/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap b/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap
deleted file mode 100644
index 2fd1fd6a04e..00000000000
--- a/spec/frontend/profile/preferences/components/__snapshots__/integration_view_spec.js.snap
+++ /dev/null
@@ -1,67 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`IntegrationView component should render IntegrationView properly 1`] = `
-<div
- name="sourcegraph"
->
- <label
- class="label-bold"
- >
-
- Foo
-
- </label>
-
- <gl-link-stub
- class="has-tooltip"
- href="http://foo.com/help"
- title="More information"
- >
- <gl-icon-stub
- class="vertical-align-middle"
- name="question-o"
- size="16"
- />
- </gl-link-stub>
-
- <div
- class="form-group form-check"
- data-testid="profile-preferences-integration-form-group"
- >
- <input
- data-testid="profile-preferences-integration-hidden-field"
- name="user[foo_enabled]"
- type="hidden"
- value="0"
- />
-
- <input
- class="form-check-input"
- data-testid="profile-preferences-integration-checkbox"
- id="user_foo_enabled"
- name="user[foo_enabled]"
- type="checkbox"
- value="1"
- />
-
- <label
- class="form-check-label"
- for="user_foo_enabled"
- >
-
- Enable foo
-
- </label>
-
- <gl-form-text-stub
- tag="div"
- textvariant="muted"
- >
- <integration-help-text-stub
- message="Click %{linkStart}Foo%{linkEnd}!"
- messageurl="http://foo.com"
- />
- </gl-form-text-stub>
- </div>
-</div>
-`;
diff --git a/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap b/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap
deleted file mode 100644
index 4df92cf86a5..00000000000
--- a/spec/frontend/profile/preferences/components/__snapshots__/profile_preferences_spec.js.snap
+++ /dev/null
@@ -1,51 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ProfilePreferences component should render ProfilePreferences properly 1`] = `
-<div
- class="row gl-mt-3 js-preferences-form"
->
- <div
- class="col-sm-12"
- >
- <hr
- data-testid="profile-preferences-integrations-rule"
- />
- </div>
-
- <div
- class="col-lg-4 profile-settings-sidebar"
- >
- <h4
- class="gl-mt-0"
- data-testid="profile-preferences-integrations-heading"
- >
-
- Integrations
-
- </h4>
-
- <p>
-
- Customize integrations with third party services.
-
- </p>
- </div>
-
- <div
- class="col-lg-8"
- >
- <integration-view-stub
- config="[object Object]"
- helplink="http://foo.com/help"
- message="Click %{linkStart}Foo%{linkEnd}!"
- messageurl="http://foo.com"
- />
- <integration-view-stub
- config="[object Object]"
- helplink="http://bar.com/help"
- message="Click %{linkStart}Bar%{linkEnd}!"
- messageurl="http://bar.com"
- />
- </div>
-</div>
-`;
diff --git a/spec/frontend/profile/preferences/components/integration_view_spec.js b/spec/frontend/profile/preferences/components/integration_view_spec.js
index 5d55a089119..6ab0c70298c 100644
--- a/spec/frontend/profile/preferences/components/integration_view_spec.js
+++ b/spec/frontend/profile/preferences/components/integration_view_spec.js
@@ -1,9 +1,9 @@
+import { GlFormText } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormText } from '@gitlab/ui';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import IntegrationView from '~/profile/preferences/components/integration_view.vue';
import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { integrationViews, userFields } from '../mock_data';
const viewProps = convertObjectPropsToCamelCase(integrationViews[0]);
@@ -115,10 +115,4 @@ describe('IntegrationView component', () => {
expect(findFormGroupLabel().text()).toBe('Enable foo');
});
-
- it('should render IntegrationView properly', () => {
- wrapper = createComponent();
-
- expect(wrapper.element).toMatchSnapshot();
- });
});
diff --git a/spec/frontend/profile/preferences/components/profile_preferences_spec.js b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
index fcc27d8faaf..82c41178410 100644
--- a/spec/frontend/profile/preferences/components/profile_preferences_spec.js
+++ b/spec/frontend/profile/preferences/components/profile_preferences_spec.js
@@ -1,27 +1,58 @@
+import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-
-import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import IntegrationView from '~/profile/preferences/components/integration_view.vue';
-import { integrationViews, userFields } from '../mock_data';
+import ProfilePreferences from '~/profile/preferences/components/profile_preferences.vue';
+import { i18n } from '~/profile/preferences/constants';
+import { integrationViews, userFields, bodyClasses } from '../mock_data';
+
+const expectedUrl = '/foo';
describe('ProfilePreferences component', () => {
let wrapper;
const defaultProvide = {
integrationViews: [],
userFields,
+ bodyClasses,
+ themes: [{ id: 1, css_class: 'foo' }],
+ profilePreferencesPath: '/update-profile',
+ formEl: document.createElement('form'),
};
function createComponent(options = {}) {
- const { props = {}, provide = {} } = options;
- return shallowMount(ProfilePreferences, {
- provide: {
- ...defaultProvide,
- ...provide,
- },
- propsData: props,
- });
+ const { props = {}, provide = {}, attachTo } = options;
+ return extendedWrapper(
+ shallowMount(ProfilePreferences, {
+ provide: {
+ ...defaultProvide,
+ ...provide,
+ },
+ propsData: props,
+ attachTo,
+ }),
+ );
+ }
+
+ function findIntegrationsDivider() {
+ return wrapper.findByTestId('profile-preferences-integrations-rule');
+ }
+
+ function findIntegrationsHeading() {
+ return wrapper.findByTestId('profile-preferences-integrations-heading');
+ }
+
+ function findSubmitButton() {
+ return wrapper.findComponent(GlButton);
}
+ function findFlashError() {
+ return document.querySelector('.flash-container .flash-text');
+ }
+
+ beforeEach(() => {
+ setFixtures('<div class="flash-container"></div>');
+ });
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -30,8 +61,8 @@ describe('ProfilePreferences component', () => {
it('should not render Integrations section', () => {
wrapper = createComponent();
const views = wrapper.findAll(IntegrationView);
- const divider = wrapper.find('[data-testid="profile-preferences-integrations-rule"]');
- const heading = wrapper.find('[data-testid="profile-preferences-integrations-heading"]');
+ const divider = findIntegrationsDivider();
+ const heading = findIntegrationsHeading();
expect(divider.exists()).toBe(false);
expect(heading.exists()).toBe(false);
@@ -40,8 +71,8 @@ describe('ProfilePreferences component', () => {
it('should render Integration section', () => {
wrapper = createComponent({ provide: { integrationViews } });
- const divider = wrapper.find('[data-testid="profile-preferences-integrations-rule"]');
- const heading = wrapper.find('[data-testid="profile-preferences-integrations-heading"]');
+ const divider = findIntegrationsDivider();
+ const heading = findIntegrationsHeading();
const views = wrapper.findAll(IntegrationView);
expect(divider.exists()).toBe(true);
@@ -49,9 +80,84 @@ describe('ProfilePreferences component', () => {
expect(views).toHaveLength(integrationViews.length);
});
- it('should render ProfilePreferences properly', () => {
- wrapper = createComponent({ provide: { integrationViews } });
+ describe('form submit', () => {
+ let form;
- expect(wrapper.element).toMatchSnapshot();
+ beforeEach(() => {
+ const div = document.createElement('div');
+ div.classList.add('container-fluid');
+ document.body.appendChild(div);
+ document.body.classList.add('content-wrapper');
+
+ form = document.createElement('form');
+ form.setAttribute('url', expectedUrl);
+ form.setAttribute('method', 'put');
+
+ const input = document.createElement('input');
+ input.setAttribute('name', 'user[theme_id]');
+ input.setAttribute('type', 'radio');
+ input.setAttribute('value', '1');
+ input.setAttribute('checked', 'checked');
+ form.appendChild(input);
+
+ wrapper = createComponent({ provide: { formEl: form }, attachTo: document.body });
+
+ const beforeSendEvent = new CustomEvent('ajax:beforeSend');
+ form.dispatchEvent(beforeSendEvent);
+ });
+
+ it('disables the submit button', async () => {
+ await wrapper.vm.$nextTick();
+ const button = findSubmitButton();
+ expect(button.props('disabled')).toBe(true);
+ });
+
+ it('success re-enables the submit button', async () => {
+ const successEvent = new CustomEvent('ajax:success');
+ form.dispatchEvent(successEvent);
+
+ await wrapper.vm.$nextTick();
+ const button = findSubmitButton();
+ expect(button.props('disabled')).toBe(false);
+ });
+
+ it('error re-enables the submit button', async () => {
+ const errorEvent = new CustomEvent('ajax:error');
+ form.dispatchEvent(errorEvent);
+
+ await wrapper.vm.$nextTick();
+ const button = findSubmitButton();
+ expect(button.props('disabled')).toBe(false);
+ });
+
+ it('displays the default success message', () => {
+ const successEvent = new CustomEvent('ajax:success');
+ form.dispatchEvent(successEvent);
+
+ expect(findFlashError().innerText.trim()).toEqual(i18n.defaultSuccess);
+ });
+
+ it('displays the custom success message', () => {
+ const message = 'foo';
+ const successEvent = new CustomEvent('ajax:success', { detail: [{ message }] });
+ form.dispatchEvent(successEvent);
+
+ expect(findFlashError().innerText.trim()).toEqual(message);
+ });
+
+ it('displays the default error message', () => {
+ const errorEvent = new CustomEvent('ajax:error');
+ form.dispatchEvent(errorEvent);
+
+ expect(findFlashError().innerText.trim()).toEqual(i18n.defaultError);
+ });
+
+ it('displays the custom error message', () => {
+ const message = 'bar';
+ const errorEvent = new CustomEvent('ajax:error', { detail: [{ message }] });
+ form.dispatchEvent(errorEvent);
+
+ expect(findFlashError().innerText.trim()).toEqual(message);
+ });
});
});
diff --git a/spec/frontend/profile/preferences/mock_data.js b/spec/frontend/profile/preferences/mock_data.js
index d07d5f565dc..ce33fc79a39 100644
--- a/spec/frontend/profile/preferences/mock_data.js
+++ b/spec/frontend/profile/preferences/mock_data.js
@@ -16,3 +16,5 @@ export const integrationViews = [
export const userFields = {
foo_enabled: true,
};
+
+export const bodyClasses = 'ui-light-indigo ui-light gl-dark';
diff --git a/spec/frontend/project_find_file_spec.js b/spec/frontend/project_find_file_spec.js
index 1af97dbca0a..5919910d791 100644
--- a/spec/frontend/project_find_file_spec.js
+++ b/spec/frontend/project_find_file_spec.js
@@ -2,8 +2,8 @@ import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { TEST_HOST } from 'helpers/test_constants';
import { sanitize } from '~/lib/dompurify';
-import ProjectFindFile from '~/project_find_file';
import axios from '~/lib/utils/axios_utils';
+import ProjectFindFile from '~/project_find_file';
jest.mock('~/lib/dompurify', () => ({
addHook: jest.fn(),
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
index 9fa7d658405..7686c28c7fc 100644
--- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js
+++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js
@@ -1,8 +1,8 @@
+import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue';
Vue.use(Vuex);
diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js
index 1c37b82fed3..1569f5b4bbe 100644
--- a/spec/frontend/projects/commit/components/form_modal_spec.js
+++ b/spec/frontend/projects/commit/components/form_modal_spec.js
@@ -1,12 +1,13 @@
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount, mount, createWrapper } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
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 { extendedWrapper } from 'helpers/vue_test_utils_helper';
import axios from '~/lib/utils/axios_utils';
-import eventHub from '~/projects/commit/event_hub';
-import CommitFormModal from '~/projects/commit/components/form_modal.vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue';
+import CommitFormModal from '~/projects/commit/components/form_modal.vue';
+import eventHub from '~/projects/commit/event_hub';
import createStore from '~/projects/commit/store';
import mockData from '../mock_data';
@@ -64,7 +65,7 @@ describe('CommitFormModal', () => {
wrapper.vm.show();
- expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', mockData.modalPropsData.modalId);
+ expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, mockData.modalPropsData.modalId);
});
it('Clears the modal state once modal is hidden', () => {
diff --git a/spec/frontend/projects/commit/components/form_trigger_spec.js b/spec/frontend/projects/commit/components/form_trigger_spec.js
index ca51419d6a5..4503493c0a6 100644
--- a/spec/frontend/projects/commit/components/form_trigger_spec.js
+++ b/spec/frontend/projects/commit/components/form_trigger_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import FormTrigger from '~/projects/commit/components/form_trigger.vue';
import eventHub from '~/projects/commit/event_hub';
diff --git a/spec/frontend/projects/commit/store/actions_spec.js b/spec/frontend/projects/commit/store/actions_spec.js
index ec528d4ee88..458372229cf 100644
--- a/spec/frontend/projects/commit/store/actions_spec.js
+++ b/spec/frontend/projects/commit/store/actions_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
-import getInitialState from '~/projects/commit/store/state';
+import axios from '~/lib/utils/axios_utils';
+import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants';
import * as actions from '~/projects/commit/store/actions';
import * as types from '~/projects/commit/store/mutation_types';
+import getInitialState from '~/projects/commit/store/state';
import mockData from '../mock_data';
-import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants';
jest.mock('~/flash.js');
diff --git a/spec/frontend/projects/commit/store/mutations_spec.js b/spec/frontend/projects/commit/store/mutations_spec.js
index 59ab3d9a74a..2ea50e71772 100644
--- a/spec/frontend/projects/commit/store/mutations_spec.js
+++ b/spec/frontend/projects/commit/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/projects/commit/store/mutations';
import * as types from '~/projects/commit/store/mutation_types';
+import mutations from '~/projects/commit/store/mutations';
describe('Commit form modal mutations', () => {
let stateCopy;
diff --git a/spec/frontend/projects/commit_box/info/load_branches_spec.js b/spec/frontend/projects/commit_box/info/load_branches_spec.js
index ebd4ee45dab..8100200cbdd 100644
--- a/spec/frontend/projects/commit_box/info/load_branches_spec.js
+++ b/spec/frontend/projects/commit_box/info/load_branches_spec.js
@@ -1,6 +1,6 @@
import axios from 'axios';
-import waitForPromises from 'helpers/wait_for_promises';
import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
import { loadBranches } from '~/projects/commit_box/info/load_branches';
const mockCommitPath = '/commit/abcd/branches';
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index 63920ddfd72..9a8f7ff7582 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -1,6 +1,6 @@
+import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import * as urlUtility from '~/lib/utils/url_utility';
import AuthorSelect from '~/projects/commits/components/author_select.vue';
import { createStore } from '~/projects/commits/store';
diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js
index a842aaa2a76..e2c993b8395 100644
--- a/spec/frontend/projects/commits/store/actions_spec.js
+++ b/spec/frontend/projects/commits/store/actions_spec.js
@@ -1,10 +1,10 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import * as types from '~/projects/commits/store/mutation_types';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import actions from '~/projects/commits/store/actions';
+import * as types from '~/projects/commits/store/mutation_types';
import createState from '~/projects/commits/store/state';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js
new file mode 100644
index 00000000000..d28a30e93b1
--- /dev/null
+++ b/spec/frontend/projects/compare/components/app_spec.js
@@ -0,0 +1,116 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import CompareApp from '~/projects/compare/components/app.vue';
+import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+
+const projectCompareIndexPath = 'some/path';
+const refsProjectPath = 'some/refs/path';
+const paramsFrom = 'master';
+const paramsTo = 'master';
+
+describe('CompareApp component', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(CompareApp, {
+ propsData: {
+ projectCompareIndexPath,
+ refsProjectPath,
+ paramsFrom,
+ paramsTo,
+ projectMergeRequestPath: '',
+ createMrPath: '',
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders component with prop', () => {
+ expect(wrapper.props()).toEqual(
+ expect.objectContaining({
+ projectCompareIndexPath,
+ refsProjectPath,
+ paramsFrom,
+ paramsTo,
+ }),
+ );
+ });
+
+ it('contains the correct form attributes', () => {
+ expect(wrapper.attributes('action')).toBe(projectCompareIndexPath);
+ expect(wrapper.attributes('method')).toBe('POST');
+ });
+
+ it('has input with csrf token', () => {
+ expect(wrapper.find('input[name="authenticity_token"]').attributes('value')).toBe(
+ 'mock-csrf-token',
+ );
+ });
+
+ it('has ellipsis', () => {
+ expect(wrapper.find('[data-testid="ellipsis"]').exists()).toBe(true);
+ });
+
+ it('render Source and Target BranchDropdown components', () => {
+ const branchDropdowns = wrapper.findAll(RevisionDropdown);
+
+ expect(branchDropdowns.length).toBe(2);
+ expect(branchDropdowns.at(0).props('revisionText')).toBe('Source');
+ expect(branchDropdowns.at(1).props('revisionText')).toBe('Target');
+ });
+
+ describe('compare button', () => {
+ const findCompareButton = () => wrapper.find(GlButton);
+
+ it('renders button', () => {
+ expect(findCompareButton().exists()).toBe(true);
+ });
+
+ it('submits form', () => {
+ findCompareButton().vm.$emit('click');
+ expect(wrapper.find('form').element.submit).toHaveBeenCalled();
+ });
+
+ it('has compare text', () => {
+ expect(findCompareButton().text()).toBe('Compare');
+ });
+ });
+
+ describe('merge request buttons', () => {
+ const findProjectMrButton = () => wrapper.find('[data-testid="projectMrButton"]');
+ const findCreateMrButton = () => wrapper.find('[data-testid="createMrButton"]');
+
+ it('does not have merge request buttons', () => {
+ createComponent();
+ expect(findProjectMrButton().exists()).toBe(false);
+ expect(findCreateMrButton().exists()).toBe(false);
+ });
+
+ it('has "View open merge request" button', () => {
+ createComponent({
+ projectMergeRequestPath: 'some/project/merge/request/path',
+ });
+ expect(findProjectMrButton().exists()).toBe(true);
+ expect(findCreateMrButton().exists()).toBe(false);
+ });
+
+ it('has "Create merge request" button', () => {
+ createComponent({
+ createMrPath: 'some/create/create/mr/path',
+ });
+ expect(findProjectMrButton().exists()).toBe(false);
+ expect(findCreateMrButton().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
new file mode 100644
index 00000000000..f3ff5e26d2b
--- /dev/null
+++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js
@@ -0,0 +1,92 @@
+import { GlDropdown } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue';
+
+const defaultProps = {
+ refsProjectPath: 'some/refs/path',
+ revisionText: 'Target',
+ paramsName: 'from',
+ paramsBranch: 'master',
+};
+
+jest.mock('~/flash');
+
+describe('RevisionDropdown component', () => {
+ let wrapper;
+ let axiosMock;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(RevisionDropdown, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ axiosMock.restore();
+ });
+
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+
+ it('sets hidden input', () => {
+ createComponent();
+ expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe(
+ defaultProps.paramsBranch,
+ );
+ });
+
+ it('update the branches on success', async () => {
+ const Branches = ['branch-1', 'branch-2'];
+ const Tags = ['tag-1', 'tag-2', 'tag-3'];
+
+ axiosMock.onGet(defaultProps.refsProjectPath).replyOnce(200, {
+ Branches,
+ Tags,
+ });
+
+ createComponent();
+
+ await axios.waitForAll();
+
+ expect(wrapper.vm.branches).toEqual(Branches);
+ expect(wrapper.vm.tags).toEqual(Tags);
+ });
+
+ it('shows flash message on error', async () => {
+ axiosMock.onGet('some/invalid/path').replyOnce(404);
+
+ createComponent();
+
+ await wrapper.vm.fetchBranchesAndTags();
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ describe('GlDropdown component', () => {
+ it('renders props', () => {
+ createComponent();
+ expect(wrapper.props()).toEqual(expect.objectContaining(defaultProps));
+ });
+
+ it('display default text', () => {
+ createComponent({
+ paramsBranch: null,
+ });
+ expect(findGlDropdown().props('text')).toBe('Select branch/tag');
+ });
+
+ it('display params branch text', () => {
+ createComponent();
+ expect(findGlDropdown().props('text')).toBe(defaultProps.paramsBranch);
+ });
+ });
+});
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 0b9f095a700..f0d72124379 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
@@ -53,12 +53,12 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
variant="danger"
>
<gl-sprintf-stub
- message="Once 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."
+ message="Once 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."
/>
</gl-alert-stub>
<p>
- This action cannot be undone. You will lose this project's repository and all content: issues, merge requests, etc.
+ This action cannot be undone. You will lose this project's repository and all related resources, including issues, merge requests, etc.
</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 cf7e41a2df2..3e491584670 100644
--- a/spec/frontend/projects/components/shared/delete_button_spec.js
+++ b/spec/frontend/projects/components/shared/delete_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
diff --git a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
index 9a5f200f5a9..b4ae50341d4 100644
--- a/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
+++ b/spec/frontend/projects/experiment_new_project_creation/components/app_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlBreadcrumb } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import App from '~/projects/experiment_new_project_creation/components/app.vue';
-import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
import LegacyContainer from '~/projects/experiment_new_project_creation/components/legacy_container.vue';
+import WelcomePage from '~/projects/experiment_new_project_creation/components/welcome.vue';
describe('Experimental new project creation app', () => {
let wrapper;
diff --git a/spec/frontend/projects/members/utils_spec.js b/spec/frontend/projects/members/utils_spec.js
new file mode 100644
index 00000000000..813e8455e85
--- /dev/null
+++ b/spec/frontend/projects/members/utils_spec.js
@@ -0,0 +1,14 @@
+import { projectMemberRequestFormatter } from '~/projects/members/utils';
+
+describe('project member utils', () => {
+ describe('projectMemberRequestFormatter', () => {
+ it('returns expected format', () => {
+ expect(
+ projectMemberRequestFormatter({
+ accessLevel: 50,
+ expires_at: '2020-10-16',
+ }),
+ ).toEqual({ project_member: { access_level: 50, expires_at: '2020-10-16' } });
+ });
+ });
+});
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index 44329944097..e8aace14db4 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -1,32 +1,19 @@
-import { merge } from 'lodash';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
import { GlTabs, GlTab } from '@gitlab/ui';
-import createMockApollo from 'helpers/mock_apollo_helper';
+import { shallowMount } from '@vue/test-utils';
+import { merge } from 'lodash';
+import setWindowLocation from 'helpers/set_window_location_helper';
+import { TEST_HOST } from 'helpers/test_constants';
+import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import Component from '~/projects/pipelines/charts/components/app.vue';
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
-import getPipelineCountByStatus from '~/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql';
-import getProjectPipelineStatistics from '~/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql';
-import { mockPipelineCount, mockPipelineStatistics } from '../mock_data';
-const projectPath = 'gitlab-org/gitlab';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+jest.mock('~/lib/utils/url_utility');
const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} };
describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
- function createMockApolloProvider() {
- const requestHandlers = [
- [getPipelineCountByStatus, jest.fn().mockResolvedValue(mockPipelineCount)],
- [getProjectPipelineStatistics, jest.fn().mockResolvedValue(mockPipelineStatistics)],
- ];
-
- return createMockApollo(requestHandlers);
- }
-
function createComponent(mountOptions = {}) {
wrapper = shallowMount(
Component,
@@ -34,11 +21,8 @@ describe('ProjectsPipelinesChartsApp', () => {
{},
{
provide: {
- projectPath,
shouldRenderDeploymentFrequencyCharts: false,
},
- localVue,
- apolloProvider: createMockApolloProvider(),
stubs: {
DeploymentFrequencyCharts: DeploymentFrequencyChartsStub,
},
@@ -57,52 +41,15 @@ describe('ProjectsPipelinesChartsApp', () => {
wrapper = null;
});
- describe('pipelines charts', () => {
- it('displays the pipeline charts', () => {
- const chart = wrapper.find(PipelineCharts);
- const analytics = mockPipelineStatistics.data.project.pipelineAnalytics;
-
- const {
- totalPipelines: total,
- successfulPipelines: success,
- failedPipelines: failed,
- } = mockPipelineCount.data.project;
-
- expect(chart.exists()).toBe(true);
- expect(chart.props()).toMatchObject({
- counts: {
- failed: failed.count,
- success: success.count,
- total: total.count,
- successRatio: (success.count / (success.count + failed.count)) * 100,
- },
- lastWeek: {
- labels: analytics.weekPipelinesLabels,
- totals: analytics.weekPipelinesTotals,
- success: analytics.weekPipelinesSuccessful,
- },
- lastMonth: {
- labels: analytics.monthPipelinesLabels,
- totals: analytics.monthPipelinesTotals,
- success: analytics.monthPipelinesSuccessful,
- },
- lastYear: {
- labels: analytics.yearPipelinesLabels,
- totals: analytics.yearPipelinesTotals,
- success: analytics.yearPipelinesSuccessful,
- },
- timesChart: {
- labels: analytics.pipelineTimesLabels,
- values: analytics.pipelineTimesValues,
- },
- });
- });
- });
-
- const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
const findGlTabs = () => wrapper.find(GlTabs);
const findAllGlTab = () => wrapper.findAll(GlTab);
const findGlTabAt = (i) => findAllGlTab().at(i);
+ const findDeploymentFrequencyCharts = () => wrapper.find(DeploymentFrequencyChartsStub);
+ const findPipelineCharts = () => wrapper.find(PipelineCharts);
+
+ it('renders the pipeline charts', () => {
+ expect(findPipelineCharts().exists()).toBe(true);
+ });
describe('when shouldRenderDeploymentFrequencyCharts is true', () => {
beforeEach(() => {
@@ -115,6 +62,97 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(findGlTabAt(1).attributes('title')).toBe('Deployments');
expect(findDeploymentFrequencyCharts().exists()).toBe(true);
});
+
+ it('sets the tab and url when a tab is clicked', async () => {
+ let chartsPath;
+ setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
+
+ mergeUrlParams.mockImplementation(({ chart }, path) => {
+ expect(chart).toBe('deployments');
+ expect(path).toBe(window.location.pathname);
+ chartsPath = `${path}?chart=${chart}`;
+ return chartsPath;
+ });
+
+ updateHistory.mockImplementation(({ url }) => {
+ expect(url).toBe(chartsPath);
+ });
+ const tabs = findGlTabs();
+
+ expect(tabs.attributes('value')).toBe('0');
+
+ tabs.vm.$emit('input', 1);
+
+ await wrapper.vm.$nextTick();
+
+ expect(tabs.attributes('value')).toBe('1');
+ });
+
+ it('should not try to push history if the tab does not change', async () => {
+ setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`);
+
+ mergeUrlParams.mockImplementation(({ chart }, path) => `${path}?chart=${chart}`);
+
+ const tabs = findGlTabs();
+
+ expect(tabs.attributes('value')).toBe('0');
+
+ tabs.vm.$emit('input', 0);
+
+ await wrapper.vm.$nextTick();
+
+ expect(updateHistory).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when provided with a query param', () => {
+ it.each`
+ chart | tab
+ ${'deployments'} | ${'1'}
+ ${'pipelines'} | ${'0'}
+ ${'fake'} | ${'0'}
+ ${''} | ${'0'}
+ `('shows the correct tab for URL parameter "$chart"', ({ chart, tab }) => {
+ setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts?chart=${chart}`);
+ getParameterValues.mockImplementation((name) => {
+ expect(name).toBe('chart');
+ return chart ? [chart] : [];
+ });
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+ expect(findGlTabs().attributes('value')).toBe(tab);
+ });
+
+ it('should set the tab when the back button is clicked', async () => {
+ let popstateHandler;
+
+ window.addEventListener = jest.fn();
+
+ window.addEventListener.mockImplementation((event, handler) => {
+ if (event === 'popstate') {
+ popstateHandler = handler;
+ }
+ });
+
+ getParameterValues.mockImplementation((name) => {
+ expect(name).toBe('chart');
+ return [];
+ });
+
+ createComponent({ provide: { shouldRenderDeploymentFrequencyCharts: true } });
+
+ expect(findGlTabs().attributes('value')).toBe('0');
+
+ getParameterValues.mockImplementationOnce((name) => {
+ expect(name).toBe('chart');
+ return ['deployments'];
+ });
+
+ popstateHandler();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlTabs().attributes('value')).toBe('1');
+ });
});
describe('when shouldRenderDeploymentFrequencyCharts is false', () => {
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
new file mode 100644
index 00000000000..037530ddd48
--- /dev/null
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
@@ -0,0 +1,94 @@
+import { GlSegmentedControl } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
+import CiCdAnalyticsCharts from '~/projects/pipelines/charts/components/ci_cd_analytics_charts.vue';
+import { transformedAreaChartData, chartOptions } from '../mock_data';
+
+const DEFAULT_PROPS = {
+ chartOptions,
+ charts: [
+ {
+ range: 'test range 1',
+ title: 'title 1',
+ data: transformedAreaChartData,
+ },
+ {
+ range: 'test range 2',
+ title: 'title 2',
+ data: transformedAreaChartData,
+ },
+ {
+ range: 'test range 3',
+ title: 'title 3',
+ data: transformedAreaChartData,
+ },
+ ],
+};
+
+describe('~/projects/pipelines/charts/components/ci_cd_analytics_charts.vue', () => {
+ let wrapper;
+
+ const createWrapper = (props = {}) =>
+ shallowMount(CiCdAnalyticsCharts, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('segmented control', () => {
+ let segmentedControl;
+
+ beforeEach(() => {
+ wrapper = createWrapper();
+ segmentedControl = wrapper.find(GlSegmentedControl);
+ });
+
+ it('should default to the first chart', () => {
+ expect(segmentedControl.props('checked')).toBe(0);
+ });
+
+ it('should use the title and index as values', () => {
+ const options = segmentedControl.props('options');
+ expect(options).toHaveLength(3);
+ expect(options).toEqual([
+ {
+ text: 'title 1',
+ value: 0,
+ },
+ {
+ text: 'title 2',
+ value: 1,
+ },
+ {
+ text: 'title 3',
+ value: 2,
+ },
+ ]);
+ });
+
+ it('should select a different chart on change', async () => {
+ segmentedControl.vm.$emit('input', 1);
+
+ const chart = wrapper.find(CiCdAnalyticsAreaChart);
+
+ await nextTick();
+
+ expect(chart.props('chartData')).toEqual(transformedAreaChartData);
+ expect(chart.text()).toBe('Date range: test range 2');
+ });
+ });
+
+ it('should not display charts if there are no charts', () => {
+ wrapper = createWrapper({ charts: [] });
+ expect(wrapper.find(CiCdAnalyticsAreaChart).exists()).toBe(false);
+ });
+});
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 598055d5828..c5cfe783569 100644
--- a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
@@ -1,35 +1,37 @@
-import { shallowMount } from '@vue/test-utils';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
-import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue';
-import CiCdAnalyticsAreaChart from '~/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import CiCdAnalyticsCharts from '~/projects/pipelines/charts/components/ci_cd_analytics_charts.vue';
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
-import {
- counts,
- timesChartData as timesChart,
- areaChartData as lastWeek,
- areaChartData as lastMonth,
- lastYearChartData as lastYear,
-} from '../mock_data';
+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';
+import getProjectPipelineStatistics from '~/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql';
+import { mockPipelineCount, mockPipelineStatistics } from '../mock_data';
+
+const projectPath = 'gitlab-org/gitlab';
+const localVue = createLocalVue();
+localVue.use(VueApollo);
-describe('ProjectsPipelinesChartsApp', () => {
+describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => {
let wrapper;
+ function createMockApolloProvider() {
+ const requestHandlers = [
+ [getPipelineCountByStatus, jest.fn().mockResolvedValue(mockPipelineCount)],
+ [getProjectPipelineStatistics, jest.fn().mockResolvedValue(mockPipelineStatistics)],
+ ];
+
+ return createMockApollo(requestHandlers);
+ }
+
beforeEach(() => {
wrapper = shallowMount(PipelineCharts, {
- propsData: {
- counts,
- timesChart,
- lastWeek,
- lastMonth,
- lastYear,
- },
provide: {
- projectPath: 'test/project',
- shouldRenderDeploymentFrequencyCharts: true,
- },
- stubs: {
- DeploymentFrequencyCharts: true,
+ projectPath,
},
+ localVue,
+ apolloProvider: createMockApolloProvider(),
});
});
@@ -43,7 +45,12 @@ describe('ProjectsPipelinesChartsApp', () => {
const list = wrapper.find(StatisticsList);
expect(list.exists()).toBe(true);
- expect(list.props('counts')).toBe(counts);
+ expect(list.props('counts')).toEqual({
+ total: 34,
+ success: 23,
+ failed: 1,
+ successRatio: (23 / (23 + 1)) * 100,
+ });
});
it('displays the commit duration chart', () => {
@@ -58,20 +65,17 @@ describe('ProjectsPipelinesChartsApp', () => {
});
describe('pipelines charts', () => {
- it('displays 3 area charts', () => {
- expect(wrapper.findAll(CiCdAnalyticsAreaChart)).toHaveLength(3);
+ it('displays the charts components', () => {
+ expect(wrapper.find(CiCdAnalyticsCharts).exists()).toBe(true);
});
describe('displays individual correctly', () => {
it('renders with the correct data', () => {
- const charts = wrapper.findAll(CiCdAnalyticsAreaChart);
- for (let i = 0; i < charts.length; i += 1) {
- const chart = charts.at(i);
-
- expect(chart.exists()).toBeTruthy();
- expect(chart.props('chartData')).toBe(wrapper.vm.areaCharts[i].data);
- expect(chart.text()).toBe(wrapper.vm.areaCharts[i].title);
- }
+ const charts = wrapper.find(CiCdAnalyticsCharts);
+ expect(charts.props()).toEqual({
+ charts: wrapper.vm.areaCharts,
+ chartOptions: wrapper.vm.$options.areaChartOptions,
+ });
});
});
});
diff --git a/spec/frontend/projects/pipelines/charts/mock_data.js b/spec/frontend/projects/pipelines/charts/mock_data.js
index 3bc09f0b0a0..2e2c594102c 100644
--- a/spec/frontend/projects/pipelines/charts/mock_data.js
+++ b/spec/frontend/projects/pipelines/charts/mock_data.js
@@ -57,6 +57,16 @@ export const mockPipelineCount = {
},
};
+export const chartOptions = {
+ xAxis: {
+ name: 'X axis title',
+ type: 'category',
+ },
+ yAxis: {
+ name: 'Y axis title',
+ },
+};
+
export const mockPipelineStatistics = {
data: {
project: {
diff --git a/spec/frontend/projects/settings/access_dropdown_spec.js b/spec/frontend/projects/settings/access_dropdown_spec.js
index 8a57930ac83..236968a3736 100644
--- a/spec/frontend/projects/settings/access_dropdown_spec.js
+++ b/spec/frontend/projects/settings/access_dropdown_spec.js
@@ -14,7 +14,6 @@ describe('AccessDropdown', () => {
`);
const $dropdown = $('#dummy-dropdown');
$dropdown.data('defaultLabel', defaultLabel);
- gon.features = { deployKeysOnProtectedBranches: true };
const options = {
$dropdown,
accessLevelsData: {
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 1fac3d07b16..2d6efe7ae83 100644
--- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
+++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
@@ -2,8 +2,8 @@ import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
import axios from '~/lib/utils/axios_utils';
+import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
const TEST_UPDATE_PATH = '/test/update_shared_runners';
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
index c83b1852147..f9fbb1b3016 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
@@ -1,20 +1,36 @@
-import { mount } from '@vue/test-utils';
+import { GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue';
-import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
+import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue';
+import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
describe('ServiceDeskRoot', () => {
- const endpoint = '/gitlab-org/gitlab-test/service_desk';
- const initialIncomingEmail = 'servicedeskaddress@example.com';
let axiosMock;
let wrapper;
let spy;
+ const provideData = {
+ customEmail: 'custom.email@example.com',
+ customEmailEnabled: true,
+ endpoint: '/gitlab-org/gitlab-test/service_desk',
+ initialIncomingEmail: 'servicedeskaddress@example.com',
+ initialIsEnabled: true,
+ outgoingName: 'GitLab Support Bot',
+ projectKey: 'key',
+ selectedTemplate: 'Bug',
+ templates: ['Bug', 'Documentation'],
+ };
+
+ const getAlertText = () => wrapper.find(GlAlert).text();
+
+ const createComponent = () => shallowMount(ServiceDeskRoot, { provide: provideData });
+
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
+ spy = jest.spyOn(axios, 'put');
});
afterEach(() => {
@@ -25,156 +41,122 @@ describe('ServiceDeskRoot', () => {
}
});
- it('sends a request to toggle service desk off when the toggle is clicked from the on state', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
+ describe('ServiceDeskSetting component', () => {
+ it('is rendered', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.find(ServiceDeskSetting).props()).toEqual({
+ customEmail: provideData.customEmail,
+ customEmailEnabled: provideData.customEmailEnabled,
+ incomingEmail: provideData.initialIncomingEmail,
+ initialOutgoingName: provideData.outgoingName,
+ initialProjectKey: provideData.projectKey,
+ initialSelectedTemplate: provideData.selectedTemplate,
+ isEnabled: provideData.initialIsEnabled,
+ isTemplateSaving: false,
+ templates: provideData.templates,
+ });
+ });
+
+ describe('toggle event', () => {
+ describe('when toggling service desk on', () => {
+ beforeEach(async () => {
+ wrapper = createComponent();
- spy = jest.spyOn(axios, 'put');
+ wrapper.find(ServiceDeskSetting).vm.$emit('toggle', true);
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- initialIncomingEmail,
- endpoint,
- },
- });
+ await waitForPromises();
+ });
+
+ it('sends a request to turn service desk on', () => {
+ axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
- wrapper.find('button.gl-toggle').trigger('click');
+ expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: true });
+ });
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: false });
+ it('shows a message when there is an error', () => {
+ axiosMock.onPut(provideData.endpoint).networkError();
+
+ expect(getAlertText()).toContain('An error occurred while enabling Service Desk.');
+ });
});
- });
- it('sends a request to toggle service desk on when the toggle is clicked from the off state', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
+ describe('when toggling service desk off', () => {
+ beforeEach(async () => {
+ wrapper = createComponent();
- spy = jest.spyOn(axios, 'put');
+ wrapper.find(ServiceDeskSetting).vm.$emit('toggle', false);
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: false,
- initialIncomingEmail: '',
- endpoint,
- },
- });
+ await waitForPromises();
+ });
- wrapper.find('button.gl-toggle').trigger('click');
+ it('sends a request to turn service desk off', () => {
+ axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
- return wrapper.vm.$nextTick(() => {
- expect(spy).toHaveBeenCalledWith(endpoint, { service_desk_enabled: true });
- });
- });
+ expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: false });
+ });
- it('shows an error message when there is an issue toggling service desk on', () => {
- axiosMock.onPut(endpoint).networkError();
+ it('shows a message when there is an error', () => {
+ axiosMock.onPut(provideData.endpoint).networkError();
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: false,
- initialIncomingEmail: '',
- endpoint,
- },
+ expect(getAlertText()).toContain('An error occurred while disabling Service Desk.');
+ });
+ });
});
- wrapper.find('button.gl-toggle').trigger('click');
+ describe('save event', () => {
+ describe('successful request', () => {
+ beforeEach(async () => {
+ axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK);
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain('An error occurred while enabling Service Desk.');
- });
- });
+ wrapper = createComponent();
- it('sends a request to update template when the "Save template" button is clicked', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
+ const payload = {
+ selectedTemplate: 'Bug',
+ outgoingName: 'GitLab Support Bot',
+ projectKey: 'key',
+ };
- spy = jest.spyOn(axios, 'put');
+ wrapper.find(ServiceDeskSetting).vm.$emit('save', payload);
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- initialIncomingEmail,
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- templates: ['Bug', 'Documentation'],
- projectKey: 'key',
- },
- });
+ await waitForPromises();
+ });
- wrapper.find('button.btn-success').trigger('click');
+ it('sends a request to update template', async () => {
+ expect(spy).toHaveBeenCalledWith(provideData.endpoint, {
+ issue_template_key: 'Bug',
+ outgoing_name: 'GitLab Support Bot',
+ project_key: 'key',
+ service_desk_enabled: true,
+ });
+ });
- return wrapper.vm.$nextTick(() => {
- expect(spy).toHaveBeenCalledWith(endpoint, {
- issue_template_key: 'Bug',
- outgoing_name: 'GitLab Support Bot',
- project_key: 'key',
- service_desk_enabled: true,
+ it('shows success message', () => {
+ expect(getAlertText()).toContain('Changes saved.');
+ });
});
- });
- });
- it('saves the template when the "Save template" button is clicked', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK);
-
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- initialIncomingEmail,
- selectedTemplate: 'Bug',
- templates: ['Bug', 'Documentation'],
- },
- });
+ describe('unsuccessful request', () => {
+ beforeEach(async () => {
+ axiosMock.onPut(provideData.endpoint).networkError();
- wrapper.find('button.btn-success').trigger('click');
+ wrapper = createComponent();
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain('Changes saved.');
- });
- });
+ const payload = {
+ selectedTemplate: 'Bug',
+ outgoingName: 'GitLab Support Bot',
+ projectKey: 'key',
+ };
- it('shows an error message when there is an issue saving the template', () => {
- axiosMock.onPut(endpoint).networkError();
-
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- initialIncomingEmail,
- selectedTemplate: 'Bug',
- templates: ['Bug', 'Documentation'],
- },
- });
+ wrapper.find(ServiceDeskSetting).vm.$emit('save', payload);
- wrapper.find('button.btn-success').trigger('click');
+ await waitForPromises();
+ });
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- expect(wrapper.html()).toContain('An error occured while saving changes:');
+ it('shows an error message', () => {
+ expect(getAlertText()).toContain('An error occured while saving changes:');
+ });
});
- });
-
- it('passes customEmail through updatedCustomEmail correctly', () => {
- const customEmail = 'foo';
-
- wrapper = mount(ServiceDeskRoot, {
- propsData: {
- initialIsEnabled: true,
- endpoint,
- customEmail,
- },
});
-
- expect(wrapper.find(ServiceDeskSetting).props('customEmail')).toEqual(customEmail);
});
});
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 ddd9a7b2fad..f6744f4971e 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
@@ -1,63 +1,68 @@
+import { GlButton, GlFormSelect, GlLoadingIcon, GlToggle } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
-import eventHub from '~/projects/settings_service_desk/event_hub';
+import { nextTick } from 'vue';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
describe('ServiceDeskSetting', () => {
let wrapper;
+ const findButton = () => wrapper.find(GlButton);
+ const findClipboardButton = () => wrapper.find(ClipboardButton);
+ const findIncomingEmail = () => wrapper.findByTestId('incoming-email');
+ const findIncomingEmailLabel = () => wrapper.findByTestId('incoming-email-describer');
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findTemplateDropdown = () => wrapper.find(GlFormSelect);
+ const findToggle = () => wrapper.find(GlToggle);
+
+ const createComponent = ({ props = {}, mountFunction = shallowMount } = {}) =>
+ extendedWrapper(
+ mountFunction(ServiceDeskSetting, {
+ propsData: {
+ isEnabled: true,
+ ...props,
+ },
+ }),
+ );
+
afterEach(() => {
if (wrapper) {
wrapper.destroy();
}
});
- const findTemplateDropdown = () => wrapper.find('#service-desk-template-select');
- const findIncomingEmail = () => wrapper.find('[data-testid="incoming-email"]');
-
describe('when isEnabled=true', () => {
describe('only isEnabled', () => {
describe('as project admin', () => {
beforeEach(() => {
- wrapper = shallowMount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent();
});
it('should see activation checkbox', () => {
- expect(wrapper.find('#service-desk-checkbox').exists()).toBe(true);
+ expect(findToggle().exists()).toBe(true);
});
it('should see main panel with the email info', () => {
- expect(wrapper.find('#incoming-email-describer').exists()).toBe(true);
+ expect(findIncomingEmailLabel().exists()).toBe(true);
});
it('should see loading spinner and not the incoming email', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(findLoadingIcon().exists()).toBe(true);
expect(findIncomingEmail().exists()).toBe(false);
});
});
});
describe('service desk toggle', () => {
- it('emits an event to turn on Service Desk when clicked', () => {
- const eventSpy = jest.fn();
- eventHub.$on('serviceDeskEnabledCheckboxToggled', eventSpy);
-
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: false,
- },
- });
+ it('emits an event to turn on Service Desk when clicked', async () => {
+ wrapper = createComponent();
- wrapper.find('#service-desk-checkbox').trigger('click');
+ findToggle().vm.$emit('change', true);
- expect(eventSpy).toHaveBeenCalledWith(true);
+ await nextTick();
- eventHub.$off('serviceDeskEnabledCheckboxToggled', eventSpy);
- eventSpy.mockRestore();
+ expect(wrapper.emitted('toggle')[0]).toEqual([true]);
});
});
@@ -65,23 +70,23 @@ describe('ServiceDeskSetting', () => {
const incomingEmail = 'foo@bar.com';
beforeEach(() => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- incomingEmail,
- },
+ wrapper = createComponent({
+ props: { incomingEmail },
});
});
it('should see email and not the loading spinner', () => {
expect(findIncomingEmail().element.value).toEqual(incomingEmail);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(findLoadingIcon().exists()).toBe(false);
});
it('renders a copy to clipboard button', () => {
- expect(wrapper.find('.qa-clipboard-button').exists()).toBe(true);
- expect(wrapper.find('.qa-clipboard-button').element.dataset.clipboardText).toBe(
- incomingEmail,
+ expect(findClipboardButton().exists()).toBe(true);
+ expect(findClipboardButton().props()).toEqual(
+ expect.objectContaining({
+ title: 'Copy',
+ text: incomingEmail,
+ }),
);
});
});
@@ -92,12 +97,8 @@ describe('ServiceDeskSetting', () => {
const customEmail = 'custom@bar.com';
beforeEach(() => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- incomingEmail,
- customEmail,
- },
+ wrapper = createComponent({
+ props: { incomingEmail, customEmail },
});
});
@@ -110,12 +111,8 @@ describe('ServiceDeskSetting', () => {
const email = 'foo@bar.com';
beforeEach(() => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- incomingEmail: email,
- customEmail: email,
- },
+ wrapper = createComponent({
+ props: { incomingEmail: email, customEmail: email },
});
});
@@ -127,21 +124,13 @@ describe('ServiceDeskSetting', () => {
describe('templates dropdown', () => {
it('renders a dropdown to choose a template', () => {
- wrapper = shallowMount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent();
- expect(wrapper.find('#service-desk-template-select').exists()).toBe(true);
+ expect(findTemplateDropdown().exists()).toBe(true);
});
it('renders a dropdown with a default value of ""', () => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent({ mountFunction: mount });
expect(findTemplateDropdown().element.value).toEqual('');
});
@@ -149,23 +138,18 @@ describe('ServiceDeskSetting', () => {
it('renders a dropdown with a value of "Bug" when it is the initial value', () => {
const templates = ['Bug', 'Documentation', 'Security release'];
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- initialSelectedTemplate: 'Bug',
- templates,
- },
+ wrapper = createComponent({
+ props: { initialSelectedTemplate: 'Bug', templates },
+ mountFunction: mount,
});
expect(findTemplateDropdown().element.value).toEqual('Bug');
});
it('renders a dropdown with no options when the project has no templates', () => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- templates: [],
- },
+ wrapper = createComponent({
+ props: { templates: [] },
+ mountFunction: mount,
});
// The dropdown by default has one empty option
@@ -174,11 +158,10 @@ describe('ServiceDeskSetting', () => {
it('renders a dropdown with options when the project has templates', () => {
const templates = ['Bug', 'Documentation', 'Security release'];
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- templates,
- },
+
+ wrapper = createComponent({
+ props: { templates },
+ mountFunction: mount,
});
// An empty-named template is prepended so the user can select no template
@@ -199,78 +182,59 @@ describe('ServiceDeskSetting', () => {
describe('save button', () => {
it('renders a save button to save a template', () => {
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
+ wrapper = createComponent();
- expect(wrapper.find('button.btn-success').text()).toContain('Save changes');
+ expect(findButton().text()).toContain('Save changes');
});
- it('emits a save event with the chosen template when the save button is clicked', () => {
- const eventSpy = jest.fn();
- eventHub.$on('serviceDeskTemplateSave', eventSpy);
-
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
+ it('emits a save event with the chosen template when the save button is clicked', async () => {
+ wrapper = createComponent({
+ props: {
initialSelectedTemplate: 'Bug',
initialOutgoingName: 'GitLab Support Bot',
initialProjectKey: 'key',
},
});
- wrapper.find('button.btn-success').trigger('click');
+ findButton().vm.$emit('click');
+
+ await nextTick();
- expect(eventSpy).toHaveBeenCalledWith({
+ const payload = {
selectedTemplate: 'Bug',
outgoingName: 'GitLab Support Bot',
projectKey: 'key',
- });
+ };
- eventHub.$off('serviceDeskTemplateSave', eventSpy);
- eventSpy.mockRestore();
+ expect(wrapper.emitted('save')[0]).toEqual([payload]);
});
});
describe('when isEnabled=false', () => {
beforeEach(() => {
- wrapper = shallowMount(ServiceDeskSetting, {
- propsData: {
- isEnabled: false,
- },
+ wrapper = createComponent({
+ props: { isEnabled: false },
});
});
it('does not render email panel', () => {
- expect(wrapper.find('#incoming-email-describer').exists()).toBe(false);
+ expect(findIncomingEmailLabel().exists()).toBe(false);
});
it('does not render template dropdown', () => {
- expect(wrapper.find('#service-desk-template-select').exists()).toBe(false);
+ expect(findTemplateDropdown().exists()).toBe(false);
});
it('does not render template save button', () => {
- expect(wrapper.find('button.btn-success').exists()).toBe(false);
+ expect(findButton().exists()).toBe(false);
});
- it('emits an event to turn on Service Desk when the toggle is clicked', () => {
- const eventSpy = jest.fn();
- eventHub.$on('serviceDeskEnabledCheckboxToggled', eventSpy);
-
- wrapper = mount(ServiceDeskSetting, {
- propsData: {
- isEnabled: true,
- },
- });
-
- wrapper.find('#service-desk-checkbox').trigger('click');
+ it('emits an event to turn on Service Desk when the toggle is clicked', async () => {
+ findToggle().vm.$emit('change', false);
- expect(eventSpy).toHaveBeenCalledWith(false);
+ await nextTick();
- eventHub.$off('serviceDeskEnabledCheckboxToggled', eventSpy);
- eventSpy.mockRestore();
+ expect(wrapper.emitted('toggle')[0]).toEqual([false]);
});
});
});
diff --git a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js b/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
deleted file mode 100644
index d5340df03fe..00000000000
--- a/spec/frontend/projects/settings_service_desk/services/service_desk_service_spec.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import AxiosMockAdapter from 'axios-mock-adapter';
-import ServiceDeskService from '~/projects/settings_service_desk/services/service_desk_service';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
-
-describe('ServiceDeskService', () => {
- const endpoint = `/gitlab-org/gitlab-test/service_desk`;
- const dummyResponse = { message: 'Dummy response' };
- const errorMessage = 'Network Error';
- let axiosMock;
- let service;
-
- beforeEach(() => {
- axiosMock = new AxiosMockAdapter(axios);
- service = new ServiceDeskService(endpoint);
- });
-
- afterEach(() => {
- axiosMock.restore();
- });
-
- describe('toggleServiceDesk', () => {
- it('makes a request to set service desk', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- return service.toggleServiceDesk(true).then((response) => {
- expect(response.data).toEqual(dummyResponse);
- });
- });
-
- it('fails on error response', () => {
- axiosMock.onPut(endpoint).networkError();
-
- return service.toggleServiceDesk(true).catch((error) => {
- expect(error.message).toBe(errorMessage);
- });
- });
-
- it('makes a request with the expected body', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- const spy = jest.spyOn(axios, 'put');
-
- service.toggleServiceDesk(true);
-
- expect(spy).toHaveBeenCalledWith(endpoint, {
- service_desk_enabled: true,
- });
-
- spy.mockRestore();
- });
- });
-
- describe('updateTemplate', () => {
- it('makes a request to update template', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- return service
- .updateTemplate(
- {
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- },
- true,
- )
- .then((response) => {
- expect(response.data).toEqual(dummyResponse);
- });
- });
-
- it('fails on error response', () => {
- axiosMock.onPut(endpoint).networkError();
-
- return service
- .updateTemplate(
- {
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- },
- true,
- )
- .catch((error) => {
- expect(error.message).toBe(errorMessage);
- });
- });
-
- it('makes a request with the expected body', () => {
- axiosMock.onPut(endpoint).replyOnce(httpStatusCodes.OK, dummyResponse);
-
- const spy = jest.spyOn(axios, 'put');
-
- service.updateTemplate(
- {
- selectedTemplate: 'Bug',
- outgoingName: 'GitLab Support Bot',
- projectKey: 'key',
- },
- true,
- );
-
- expect(spy).toHaveBeenCalledWith(endpoint, {
- issue_template_key: 'Bug',
- outgoing_name: 'GitLab Support Bot',
- project_key: 'key',
- service_desk_enabled: true,
- });
-
- spy.mockRestore();
- });
- });
-});
diff --git a/spec/frontend/prometheus_alerts/components/reset_key_spec.js b/spec/frontend/prometheus_alerts/components/reset_key_spec.js
index 489586a60fe..edf5297cc6a 100644
--- a/spec/frontend/prometheus_alerts/components/reset_key_spec.js
+++ b/spec/frontend/prometheus_alerts/components/reset_key_spec.js
@@ -1,10 +1,10 @@
+import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { GlModal } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
import ResetKey from '~/prometheus_alerts/components/reset_key.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import axios from '~/lib/utils/axios_utils';
describe('ResetKey', () => {
let mock;
diff --git a/spec/frontend/prometheus_metrics/custom_metrics_spec.js b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
index 1244d7342ad..3e3d4ee361a 100644
--- a/spec/frontend/prometheus_metrics/custom_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
-import CustomMetrics from '~/prometheus_metrics/custom_metrics';
import axios from '~/lib/utils/axios_utils';
import PANEL_STATE from '~/prometheus_metrics/constants';
+import CustomMetrics from '~/prometheus_metrics/custom_metrics';
import { metrics1 as metrics } from './mock_data';
describe('PrometheusMetrics', () => {
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index f6b2780e167..722a5274ad4 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
-import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import PANEL_STATE from '~/prometheus_metrics/constants';
+import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import { metrics2 as metrics, missingVarMetrics } from './mock_data';
describe('PrometheusMetrics', () => {
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index 7efb6e9ba4a..27ada131ed6 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -1,11 +1,11 @@
-import Vuex from 'vuex';
+import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem, GlIcon } from '@gitlab/ui';
+import Vuex from 'vuex';
import { trimText } from 'helpers/text_helper';
-import { sprintf } from '~/locale';
import { ENTER_KEY } from '~/lib/utils/keys';
+import { sprintf } from '~/locale';
import RefSelector from '~/ref/components/ref_selector.vue';
import { X_TOTAL_HEADER, DEFAULT_I18N } from '~/ref/constants';
import createStore from '~/ref/stores/';
diff --git a/spec/frontend/ref/stores/actions_spec.js b/spec/frontend/ref/stores/actions_spec.js
index 32966354c95..11acec27165 100644
--- a/spec/frontend/ref/stores/actions_spec.js
+++ b/spec/frontend/ref/stores/actions_spec.js
@@ -1,7 +1,7 @@
import testAction from 'helpers/vuex_action_helper';
-import createState from '~/ref/stores/state';
import * as actions from '~/ref/stores/actions';
import * as types from '~/ref/stores/mutation_types';
+import createState from '~/ref/stores/state';
let mockBranchesReturnValue;
let mockTagsReturnValue;
diff --git a/spec/frontend/ref/stores/mutations_spec.js b/spec/frontend/ref/stores/mutations_spec.js
index 78117436c33..cda13089766 100644
--- a/spec/frontend/ref/stores/mutations_spec.js
+++ b/spec/frontend/ref/stores/mutations_spec.js
@@ -1,7 +1,7 @@
-import createState from '~/ref/stores/state';
-import mutations from '~/ref/stores/mutations';
-import * as types from '~/ref/stores/mutation_types';
import { X_TOTAL_HEADER } from '~/ref/constants';
+import * as types from '~/ref/stores/mutation_types';
+import mutations from '~/ref/stores/mutations';
+import createState from '~/ref/stores/state';
describe('Ref selector Vuex store mutations', () => {
let state;
diff --git a/spec/frontend/registry/explorer/components/delete_button_spec.js b/spec/frontend/registry/explorer/components/delete_button_spec.js
index cd43e97009b..a557d9afacc 100644
--- a/spec/frontend/registry/explorer/components/delete_button_spec.js
+++ b/spec/frontend/registry/explorer/components/delete_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import component from '~/registry/explorer/components/delete_button.vue';
diff --git a/spec/frontend/registry/explorer/components/delete_image_spec.js b/spec/frontend/registry/explorer/components/delete_image_spec.js
new file mode 100644
index 00000000000..9a0d070e42b
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/delete_image_spec.js
@@ -0,0 +1,152 @@
+import { shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+import component from '~/registry/explorer/components/delete_image.vue';
+import { GRAPHQL_PAGE_SIZE } from '~/registry/explorer/constants/index';
+import deleteContainerRepositoryMutation from '~/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
+import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
+
+describe('Delete Image', () => {
+ let wrapper;
+ const id = '1';
+ const storeMock = {
+ readQuery: jest.fn().mockReturnValue({
+ containerRepository: {
+ status: 'foo',
+ },
+ }),
+ writeQuery: jest.fn(),
+ };
+
+ const updatePayload = {
+ data: {
+ destroyContainerRepository: {
+ containerRepository: {
+ status: 'baz',
+ },
+ },
+ },
+ };
+
+ const findButton = () => wrapper.find('button');
+
+ const mountComponent = ({
+ propsData = { id },
+ mutate = jest.fn().mockResolvedValue({}),
+ } = {}) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ mocks: {
+ $apollo: {
+ mutate,
+ },
+ },
+ scopedSlots: {
+ default: '<button @click="props.doDelete">test</button>',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('executes apollo mutate on doDelete', () => {
+ const mutate = jest.fn().mockResolvedValue({});
+ mountComponent({ mutate });
+
+ wrapper.vm.doDelete();
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: deleteContainerRepositoryMutation,
+ variables: {
+ id,
+ },
+ update: undefined,
+ });
+ });
+
+ it('on success emits the correct events', async () => {
+ const mutate = jest.fn().mockResolvedValue({});
+ mountComponent({ mutate });
+
+ wrapper.vm.doDelete();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('start')).toEqual([[]]);
+ expect(wrapper.emitted('success')).toEqual([[]]);
+ expect(wrapper.emitted('end')).toEqual([[]]);
+ });
+
+ it('when a payload contains an error emits an error event', async () => {
+ const mutate = jest
+ .fn()
+ .mockResolvedValue({ data: { destroyContainerRepository: { errors: ['foo'] } } });
+
+ mountComponent({ mutate });
+ wrapper.vm.doDelete();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[['foo']]]);
+ });
+
+ it('when the api call errors emits an error event', async () => {
+ const mutate = jest.fn().mockRejectedValue('error');
+
+ mountComponent({ mutate });
+ wrapper.vm.doDelete();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[['error']]]);
+ });
+
+ it('uses the update function, when the prop is set to true', () => {
+ const mutate = jest.fn().mockResolvedValue({});
+
+ mountComponent({ mutate, propsData: { id, useUpdateFn: true } });
+ wrapper.vm.doDelete();
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: deleteContainerRepositoryMutation,
+ variables: {
+ id,
+ },
+ update: wrapper.vm.updateImageStatus,
+ });
+ });
+
+ it('updateImage status reads and write to the cache', () => {
+ mountComponent();
+
+ const variables = {
+ id,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+
+ wrapper.vm.updateImageStatus(storeMock, updatePayload);
+
+ expect(storeMock.readQuery).toHaveBeenCalledWith({
+ query: getContainerRepositoryDetailsQuery,
+ variables,
+ });
+ expect(storeMock.writeQuery).toHaveBeenCalledWith({
+ query: getContainerRepositoryDetailsQuery,
+ variables,
+ data: {
+ containerRepository: {
+ status: updatePayload.data.destroyContainerRepository.containerRepository.status,
+ },
+ },
+ });
+ });
+
+ it('binds the doDelete function to the default scoped slot', () => {
+ const mutate = jest.fn().mockResolvedValue({});
+ mountComponent({ mutate });
+ findButton().trigger('click');
+ expect(mutate).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
index 6a7fbbe367a..c2a2a4e06ea 100644
--- a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import component from '~/registry/explorer/components/details_page/delete_alert.vue';
import {
DELETE_TAG_SUCCESS_MESSAGE,
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js b/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
index 636e0a285a6..8fe659694ba 100644
--- a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
@@ -1,9 +1,11 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import component from '~/registry/explorer/components/details_page/delete_modal.vue';
import {
REMOVE_TAG_CONFIRMATION_TEXT,
REMOVE_TAGS_CONFIRMATION_TEXT,
+ DELETE_IMAGE_CONFIRMATION_TITLE,
+ DELETE_IMAGE_CONFIRMATION_TEXT,
} from '~/registry/explorer/constants';
import { GlModal } from '../../stubs';
@@ -35,13 +37,13 @@ describe('Delete Modal', () => {
describe('events', () => {
it.each`
- glEvent | localEvent
- ${'ok'} | ${'confirmDelete'}
- ${'cancel'} | ${'cancelDelete'}
+ glEvent | localEvent
+ ${'primary'} | ${'confirmDelete'}
+ ${'cancel'} | ${'cancelDelete'}
`('GlModal $glEvent emits $localEvent', ({ glEvent, localEvent }) => {
mountComponent();
findModal().vm.$emit(glEvent);
- expect(wrapper.emitted(localEvent)).toBeTruthy();
+ expect(wrapper.emitted(localEvent)).toEqual([[]]);
});
});
@@ -53,27 +55,51 @@ describe('Delete Modal', () => {
});
});
- describe('itemsToBeDeleted contains one element', () => {
- beforeEach(() => {
- mountComponent({ itemsToBeDeleted: [{ path: 'foo' }] });
- });
- it(`has the correct description`, () => {
- expect(findDescription().text()).toBe(REMOVE_TAG_CONFIRMATION_TEXT.replace('%{item}', 'foo'));
+ describe('when we are deleting images', () => {
+ it('has the correct title', () => {
+ mountComponent({ deleteImage: true });
+
+ expect(wrapper.text()).toContain(DELETE_IMAGE_CONFIRMATION_TITLE);
});
- it('has the correct action', () => {
- expect(wrapper.text()).toContain('Remove tag');
+
+ it('has the correct description', () => {
+ mountComponent({ deleteImage: true });
+
+ expect(wrapper.text()).toContain(DELETE_IMAGE_CONFIRMATION_TEXT);
});
});
- describe('itemsToBeDeleted contains more than element', () => {
- beforeEach(() => {
- mountComponent({ itemsToBeDeleted: [{ path: 'foo' }, { path: 'bar' }] });
- });
- it(`has the correct description`, () => {
- expect(findDescription().text()).toBe(REMOVE_TAGS_CONFIRMATION_TEXT.replace('%{item}', '2'));
+ describe('when we are deleting tags', () => {
+ describe('itemsToBeDeleted contains one element', () => {
+ beforeEach(() => {
+ mountComponent({ itemsToBeDeleted: [{ path: 'foo' }] });
+ });
+
+ it(`has the correct description`, () => {
+ expect(findDescription().text()).toBe(
+ REMOVE_TAG_CONFIRMATION_TEXT.replace('%{item}', 'foo'),
+ );
+ });
+
+ it('has the correct title', () => {
+ expect(wrapper.text()).toContain('Remove tag');
+ });
});
- it('has the correct action', () => {
- expect(wrapper.text()).toContain('Remove tags');
+
+ describe('itemsToBeDeleted contains more than element', () => {
+ beforeEach(() => {
+ mountComponent({ itemsToBeDeleted: [{ path: 'foo' }, { path: 'bar' }] });
+ });
+
+ it(`has the correct description`, () => {
+ expect(findDescription().text()).toBe(
+ REMOVE_TAGS_CONFIRMATION_TEXT.replace('%{item}', '2'),
+ );
+ });
+
+ it('has the correct title', () => {
+ expect(wrapper.text()).toContain('Remove tags');
+ });
});
});
});
diff --git a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
index 337235e3de5..3fa3a2ae1de 100644
--- a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
@@ -1,7 +1,6 @@
+import { GlSprintf, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlSprintf } from '@gitlab/ui';
import { useFakeDate } from 'helpers/fake_date';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import component from '~/registry/explorer/components/details_page/details_header.vue';
import {
DETAILS_PAGE_TITLE,
@@ -15,6 +14,7 @@ import {
CLEANUP_ONGOING_TOOLTIP,
CLEANUP_UNFINISHED_TOOLTIP,
} from '~/registry/explorer/constants';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
describe('Details Header', () => {
let wrapper;
@@ -23,6 +23,7 @@ describe('Details Header', () => {
name: 'foo',
updatedAt: '2020-11-03T13:29:21Z',
tagsCount: 10,
+ canDelete: true,
project: {
visibility: 'public',
containerExpirationPolicy: {
@@ -36,8 +37,10 @@ describe('Details Header', () => {
const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
const findLastUpdatedAndVisibility = () => findByTestId('updated-and-visibility');
+ const findTitle = () => findByTestId('title');
const findTagsCount = () => findByTestId('tags-count');
const findCleanup = () => findByTestId('cleanup');
+ const findDeleteButton = () => wrapper.find(GlButton);
const waitForMetadataItems = async () => {
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
@@ -45,11 +48,9 @@ describe('Details Header', () => {
await wrapper.vm.$nextTick();
};
- const mountComponent = (image = defaultImage) => {
+ const mountComponent = (propsData = { image: defaultImage }) => {
wrapper = shallowMount(component, {
- propsData: {
- image,
- },
+ propsData,
stubs: {
GlSprintf,
TitleArea,
@@ -63,13 +64,65 @@ describe('Details Header', () => {
});
it('has the correct title ', () => {
- mountComponent({ ...defaultImage, name: '' });
- expect(wrapper.text()).toMatchInterpolatedText(DETAILS_PAGE_TITLE);
+ mountComponent({ image: { ...defaultImage, name: '' } });
+ expect(findTitle().text()).toMatchInterpolatedText(DETAILS_PAGE_TITLE);
});
it('shows imageName in the title', () => {
mountComponent();
- expect(wrapper.text()).toContain('foo');
+ expect(findTitle().text()).toContain('foo');
+ });
+
+ describe('delete button', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findDeleteButton().exists()).toBe(true);
+ });
+
+ it('is hidden while loading', () => {
+ mountComponent({ image: defaultImage, metadataLoading: true });
+
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+
+ it('has the correct text', () => {
+ mountComponent();
+
+ expect(findDeleteButton().text()).toBe('Delete');
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+
+ expect(findDeleteButton().props()).toMatchObject({
+ variant: 'danger',
+ disabled: false,
+ });
+ });
+
+ it('emits the correct event', () => {
+ mountComponent();
+
+ findDeleteButton().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[]]);
+ });
+
+ it.each`
+ canDelete | disabled | isDisabled
+ ${true} | ${false} | ${false}
+ ${true} | ${true} | ${true}
+ ${false} | ${false} | ${true}
+ ${false} | ${true} | ${true}
+ `(
+ 'when canDelete is $canDelete and disabled is $disabled is $isDisabled that the button is disabled',
+ ({ canDelete, disabled, isDisabled }) => {
+ mountComponent({ image: { ...defaultImage, canDelete }, disabled });
+
+ expect(findDeleteButton().props('disabled')).toBe(isDisabled);
+ },
+ );
});
describe('metadata items', () => {
@@ -82,7 +135,7 @@ describe('Details Header', () => {
});
it('when there is one tag has the correct text', async () => {
- mountComponent({ ...defaultImage, tagsCount: 1 });
+ mountComponent({ image: { ...defaultImage, tagsCount: 1 } });
await waitForMetadataItems();
expect(findTagsCount().props('text')).toBe('1 tag');
@@ -124,10 +177,12 @@ describe('Details Header', () => {
'when the status is $status the text is $text and the tooltip is $tooltip',
async ({ status, text, tooltip }) => {
mountComponent({
- ...defaultImage,
- expirationPolicyCleanupStatus: status,
- project: {
- containerExpirationPolicy: { enabled: true, nextRunAt: '2021-01-03T14:29:21Z' },
+ image: {
+ ...defaultImage,
+ expirationPolicyCleanupStatus: status,
+ project: {
+ containerExpirationPolicy: { enabled: true, nextRunAt: '2021-01-03T14:29:21Z' },
+ },
},
});
await waitForMetadataItems();
@@ -156,7 +211,7 @@ describe('Details Header', () => {
expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye');
});
it('shows an eye slashed when the project is not public', async () => {
- mountComponent({ ...defaultImage, project: { visibility: 'private' } });
+ mountComponent({ image: { ...defaultImage, project: { visibility: 'private' } } });
await waitForMetadataItems();
expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye-slash');
diff --git a/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js b/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js
new file mode 100644
index 00000000000..14b15945631
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js
@@ -0,0 +1,54 @@
+import { GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/registry/explorer/components/details_page/empty_state.vue';
+import {
+ NO_TAGS_TITLE,
+ NO_TAGS_MESSAGE,
+ MISSING_OR_DELETED_IMAGE_TITLE,
+ MISSING_OR_DELETED_IMAGE_MESSAGE,
+} from '~/registry/explorer/constants';
+
+describe('EmptyTagsState component', () => {
+ let wrapper;
+
+ const findEmptyState = () => wrapper.find(GlEmptyState);
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlEmptyState,
+ },
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('contains gl-empty-state', () => {
+ mountComponent();
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it.each`
+ isEmptyImage | title | description
+ ${false} | ${NO_TAGS_TITLE} | ${NO_TAGS_MESSAGE}
+ ${true} | ${MISSING_OR_DELETED_IMAGE_TITLE} | ${MISSING_OR_DELETED_IMAGE_MESSAGE}
+ `(
+ 'when isEmptyImage is $isEmptyImage has the correct props',
+ ({ isEmptyImage, title, description }) => {
+ mountComponent({
+ noContainersImage: 'foo',
+ isEmptyImage,
+ });
+
+ expect(findEmptyState().props()).toMatchObject({
+ title,
+ description,
+ svgPath: 'foo',
+ });
+ },
+ );
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/empty_tags_state_spec.js b/spec/frontend/registry/explorer/components/details_page/empty_tags_state_spec.js
deleted file mode 100644
index 09afd9d2d84..00000000000
--- a/spec/frontend/registry/explorer/components/details_page/empty_tags_state_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlEmptyState } from '@gitlab/ui';
-import component from '~/registry/explorer/components/details_page/empty_tags_state.vue';
-import {
- EMPTY_IMAGE_REPOSITORY_TITLE,
- EMPTY_IMAGE_REPOSITORY_MESSAGE,
-} from '~/registry/explorer/constants';
-
-describe('EmptyTagsState component', () => {
- let wrapper;
-
- const findEmptyState = () => wrapper.find(GlEmptyState);
-
- const mountComponent = () => {
- wrapper = shallowMount(component, {
- stubs: {
- GlEmptyState,
- },
- propsData: {
- noContainersImage: 'foo',
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('contains gl-empty-state', () => {
- mountComponent();
- expect(findEmptyState().exists()).toBe(true);
- });
-
- it('has the correct props', () => {
- mountComponent();
- expect(findEmptyState().props()).toMatchObject({
- title: EMPTY_IMAGE_REPOSITORY_TITLE,
- description: EMPTY_IMAGE_REPOSITORY_MESSAGE,
- svgPath: 'foo',
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js
index 17821d8be31..af8a23e412c 100644
--- a/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import component from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue';
import { DELETE_ALERT_TITLE, DELETE_ALERT_LINK_TEXT } from '~/registry/explorer/constants';
diff --git a/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js
new file mode 100644
index 00000000000..b079883cefd
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js
@@ -0,0 +1,57 @@
+import { GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/registry/explorer/components/details_page/status_alert.vue';
+import {
+ DELETE_SCHEDULED,
+ DELETE_FAILED,
+ PACKAGE_DELETE_HELP_PAGE_PATH,
+ SCHEDULED_FOR_DELETION_STATUS_TITLE,
+ SCHEDULED_FOR_DELETION_STATUS_MESSAGE,
+ FAILED_DELETION_STATUS_TITLE,
+ FAILED_DELETION_STATUS_MESSAGE,
+} from '~/registry/explorer/constants';
+
+describe('Status Alert', () => {
+ let wrapper;
+
+ const findLink = () => wrapper.find(GlLink);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findMessage = () => wrapper.find('[data-testid="message"]');
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each`
+ status | title | variant | message | link
+ ${DELETE_SCHEDULED} | ${SCHEDULED_FOR_DELETION_STATUS_TITLE} | ${'info'} | ${SCHEDULED_FOR_DELETION_STATUS_MESSAGE} | ${PACKAGE_DELETE_HELP_PAGE_PATH}
+ ${DELETE_FAILED} | ${FAILED_DELETION_STATUS_TITLE} | ${'warning'} | ${FAILED_DELETION_STATUS_MESSAGE} | ${''}
+ `(
+ `when the status is $status, title is $title, variant is $variant, message is $message and the link is $link`,
+ ({ status, title, variant, message, link }) => {
+ mountComponent({ status });
+
+ expect(findMessage().text()).toMatchInterpolatedText(message);
+ expect(findAlert().props()).toMatchObject({
+ title,
+ variant,
+ });
+ if (link) {
+ expect(findLink().attributes()).toMatchObject({
+ target: '_blank',
+ href: link,
+ });
+ }
+ },
+ );
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
index c2efc71c159..8b70f84c1bd 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
@@ -1,12 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormCheckbox, GlSprintf, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import component from '~/registry/explorer/components/details_page/tags_list_row.vue';
import DeleteButton from '~/registry/explorer/components/delete_button.vue';
-import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+import component from '~/registry/explorer/components/details_page/tags_list_row.vue';
import {
REMOVE_TAG_BUTTON_TITLE,
REMOVE_TAG_BUTTON_DISABLE_TOOLTIP,
@@ -14,6 +11,9 @@ import {
NOT_AVAILABLE_TEXT,
NOT_AVAILABLE_SIZE,
} from '~/registry/explorer/constants/index';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { tagsMock } from '../../mock_data';
import { ListItem } from '../../stubs';
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
index 413795a7a57..dc6760a17bd 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import component from '~/registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/registry/explorer/components/details_page/tags_list_row.vue';
import { TAGS_LIST_TITLE, REMOVE_TAGS_BUTTON_TITLE } from '~/registry/explorer/constants/index';
@@ -70,18 +70,25 @@ describe('Tags List', () => {
});
});
- it('is disabled when no item is selected', () => {
- mountComponent();
+ it.each`
+ disabled | doSelect | buttonDisabled
+ ${true} | ${false} | ${'true'}
+ ${true} | ${true} | ${'true'}
+ ${false} | ${false} | ${'true'}
+ ${false} | ${true} | ${undefined}
+ `(
+ 'is $buttonDisabled that the button is disabled when the component disabled state is $disabled and is $doSelect that the user selected a tag',
+ async ({ disabled, buttonDisabled, doSelect }) => {
+ mountComponent({ tags, disabled, isMobile: false });
- expect(findDeleteButton().attributes('disabled')).toBe('true');
- });
+ if (doSelect) {
+ findTagsListRow().at(0).vm.$emit('select');
+ await wrapper.vm.$nextTick();
+ }
- it('is enabled when at least one item is selected', async () => {
- mountComponent();
- findTagsListRow().at(0).vm.$emit('select');
- await wrapper.vm.$nextTick();
- expect(findDeleteButton().attributes('disabled')).toBe(undefined);
- });
+ expect(findDeleteButton().attributes('disabled')).toBe(buttonDisabled);
+ },
+ );
it('click event emits a deleted event with selected items', () => {
mountComponent();
@@ -100,12 +107,13 @@ describe('Tags List', () => {
});
it('the correct props are bound to it', () => {
- mountComponent();
+ mountComponent({ tags, disabled: true });
const rows = findTagsListRow();
expect(rows.at(0).attributes()).toMatchObject({
first: 'true',
+ disabled: 'true',
});
});
diff --git a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
index 74b9ea5fd96..8ca8fca65ed 100644
--- a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
@@ -1,9 +1,7 @@
-import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlDropdown } from '@gitlab/ui';
-import Tracking from '~/tracking';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import QuickstartDropdown from '~/registry/explorer/components/list_page/cli_commands.vue';
-import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
import {
QUICK_START,
LOGIN_COMMAND_LABEL,
@@ -13,6 +11,8 @@ import {
PUSH_COMMAND_LABEL,
COPY_PUSH_TITLE,
} from '~/registry/explorer/constants';
+import Tracking from '~/tracking';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
import { dockerCommands } from '../../mock_data';
diff --git a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
index 1ba2036dc34..989a60625e2 100644
--- a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
-import { GlEmptyState } from '../../stubs';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import groupEmptyState from '~/registry/explorer/components/list_page/group_empty_state.vue';
+import { GlEmptyState } from '../../stubs';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
index a06c4795b2e..d6ee871341b 100644
--- a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
@@ -1,11 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlSprintf, GlSkeletonLoader } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Component from '~/registry/explorer/components/list_page/image_list_row.vue';
-import ListItem from '~/vue_shared/components/registry/list_item.vue';
import DeleteButton from '~/registry/explorer/components/delete_button.vue';
+import Component from '~/registry/explorer/components/list_page/image_list_row.vue';
import {
ROW_SCHEDULED_FOR_DELETION,
LIST_DELETE_BUTTON_DISABLED,
@@ -15,8 +13,10 @@ import {
IMAGE_DELETE_SCHEDULED_STATUS,
IMAGE_FAILED_DELETED_STATUS,
} from '~/registry/explorer/constants';
-import { RouterLink } from '../../stubs';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
import { imagesListResponse } from '../../mock_data';
+import { RouterLink } from '../../stubs';
describe('Image List Row', () => {
let wrapper;
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
index 61c362f4d78..d7dd825ca3e 100644
--- a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlKeysetPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Component from '~/registry/explorer/components/list_page/image_list.vue';
import ImageListRow from '~/registry/explorer/components/list_page/image_list_row.vue';
diff --git a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
index 3a27cf1923c..111aa45f231 100644
--- a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
@@ -1,9 +1,9 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
-import { GlEmptyState } from '../../stubs';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import projectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
import { dockerCommands } from '../../mock_data';
+import { GlEmptyState } from '../../stubs';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
index 58439c185e3..07256d2bbf5 100644
--- a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
@@ -1,13 +1,13 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Component from '~/registry/explorer/components/list_page/registry_header.vue';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import {
CONTAINER_REGISTRY_TITLE,
LIST_INTRO_TEXT,
EXPIRATION_POLICY_DISABLED_MESSAGE,
EXPIRATION_POLICY_DISABLED_TEXT,
} from '~/registry/explorer/constants';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
jest.mock('~/lib/utils/datetime_utility', () => ({
approximateDuration: jest.fn(),
diff --git a/spec/frontend/registry/explorer/mock_data.js b/spec/frontend/registry/explorer/mock_data.js
index b0fc009872c..f4453912db4 100644
--- a/spec/frontend/registry/explorer/mock_data.js
+++ b/spec/frontend/registry/explorer/mock_data.js
@@ -235,3 +235,9 @@ export const graphQLProjectImageRepositoriesDetailsMock = {
},
},
};
+
+export const graphQLEmptyImageDetailsMock = {
+ data: {
+ containerRepository: null,
+ },
+};
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 1746a6a63b6..65c58bf9874 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -1,27 +1,35 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlKeysetPagination } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import Tracking from '~/tracking';
-import component from '~/registry/explorer/pages/details.vue';
+import axios from '~/lib/utils/axios_utils';
+import DeleteImage from '~/registry/explorer/components/delete_image.vue';
import DeleteAlert from '~/registry/explorer/components/details_page/delete_alert.vue';
-import PartialCleanupAlert from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue';
import DetailsHeader from '~/registry/explorer/components/details_page/details_header.vue';
-import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue';
+import EmptyTagsState from '~/registry/explorer/components/details_page/empty_state.vue';
+import PartialCleanupAlert from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue';
+import StatusAlert from '~/registry/explorer/components/details_page/status_alert.vue';
import TagsList from '~/registry/explorer/components/details_page/tags_list.vue';
-import EmptyTagsState from '~/registry/explorer/components/details_page/empty_tags_state.vue';
+import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue';
-import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
+import {
+ UNFINISHED_STATUS,
+ DELETE_SCHEDULED,
+ ALERT_DANGER_IMAGE,
+} from '~/registry/explorer/constants';
import deleteContainerRepositoryTagsMutation from '~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
+import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
-import { UNFINISHED_STATUS } from '~/registry/explorer/constants/index';
+import component from '~/registry/explorer/pages/details.vue';
+import Tracking from '~/tracking';
import {
graphQLImageDetailsMock,
graphQLImageDetailsEmptyTagsMock,
graphQLDeleteImageRepositoryTagsMock,
containerRepositoryMock,
+ graphQLEmptyImageDetailsMock,
tagsMock,
tagsPageInfo,
} from '../mock_data';
@@ -39,8 +47,10 @@ describe('Details Page', () => {
const findTagsList = () => wrapper.find(TagsList);
const findDeleteAlert = () => wrapper.find(DeleteAlert);
const findDetailsHeader = () => wrapper.find(DetailsHeader);
- const findEmptyTagsState = () => wrapper.find(EmptyTagsState);
+ const findEmptyState = () => wrapper.find(EmptyTagsState);
const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
+ const findStatusAlert = () => wrapper.find(StatusAlert);
+ const findDeleteImage = () => wrapper.find(DeleteImage);
const routeId = 1;
@@ -86,6 +96,7 @@ describe('Details Page', () => {
apolloProvider,
stubs: {
DeleteModal,
+ DeleteImage,
},
mocks: {
$route: {
@@ -133,6 +144,27 @@ describe('Details Page', () => {
});
});
+ describe('when the image does not exist', () => {
+ it('does not show the default ui', async () => {
+ mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
+
+ await waitForApolloRequestRender();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ expect(findDetailsHeader().exists()).toBe(false);
+ expect(findTagsList().exists()).toBe(false);
+ expect(findPagination().exists()).toBe(false);
+ });
+
+ it('shows an empty state message', async () => {
+ mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) });
+
+ await waitForApolloRequestRender();
+
+ expect(findEmptyState().exists()).toBe(true);
+ });
+ });
+
describe('when the list of tags is empty', () => {
const resolver = jest.fn().mockResolvedValue(graphQLImageDetailsEmptyTagsMock);
@@ -141,7 +173,7 @@ describe('Details Page', () => {
await waitForApolloRequestRender();
- expect(findEmptyTagsState().exists()).toBe(true);
+ expect(findEmptyState().exists()).toBe(true);
});
it('does not show the loader', async () => {
@@ -401,6 +433,9 @@ describe('Details Page', () => {
const config = {
runCleanupPoliciesHelpPagePath: 'foo',
cleanupPoliciesHelpPagePath: 'bar',
+ userCalloutsPath: 'call_out_path',
+ userCalloutId: 'call_out_id',
+ showUnfinishedTagCleanupCallout: true,
};
describe(`when expirationPolicyCleanupStatus is ${UNFINISHED_STATUS}`, () => {
@@ -413,8 +448,9 @@ describe('Details Page', () => {
}),
);
});
+
it('exists', async () => {
- mountComponent({ resolver });
+ mountComponent({ resolver, config });
await waitForApolloRequestRender();
@@ -426,11 +462,16 @@ describe('Details Page', () => {
await waitForApolloRequestRender();
- expect(findPartialCleanupAlert().props()).toEqual({ ...config });
+ expect(findPartialCleanupAlert().props()).toEqual({
+ runCleanupPoliciesHelpPagePath: config.runCleanupPoliciesHelpPagePath,
+ cleanupPoliciesHelpPagePath: config.cleanupPoliciesHelpPagePath,
+ });
});
it('dismiss hides the component', async () => {
- mountComponent({ resolver });
+ jest.spyOn(axios, 'post').mockReturnValue();
+
+ mountComponent({ resolver, config });
await waitForApolloRequestRender();
@@ -440,13 +481,25 @@ describe('Details Page', () => {
await wrapper.vm.$nextTick();
+ expect(axios.post).toHaveBeenCalledWith(config.userCalloutsPath, {
+ feature_name: config.userCalloutId,
+ });
+ expect(findPartialCleanupAlert().exists()).toBe(false);
+ });
+
+ it('is hidden if the callout is dismissed', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
expect(findPartialCleanupAlert().exists()).toBe(false);
});
});
describe(`when expirationPolicyCleanupStatus is not ${UNFINISHED_STATUS}`, () => {
it('the component is hidden', async () => {
- mountComponent();
+ mountComponent({ config });
+
await waitForApolloRequestRender();
expect(findPartialCleanupAlert().exists()).toBe(false);
@@ -463,4 +516,83 @@ describe('Details Page', () => {
expect(breadCrumbState.updateName).toHaveBeenCalledWith(containerRepositoryMock.name);
});
});
+
+ describe('when the image has a status different from null', () => {
+ const resolver = jest
+ .fn()
+ .mockResolvedValue(graphQLImageDetailsMock({ status: DELETE_SCHEDULED }));
+ it('disables all the actions', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findDetailsHeader().props('disabled')).toBe(true);
+ expect(findTagsList().props('disabled')).toBe(true);
+ });
+
+ it('shows a status alert', async () => {
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ expect(findStatusAlert().exists()).toBe(true);
+ expect(findStatusAlert().props()).toMatchObject({
+ status: DELETE_SCHEDULED,
+ });
+ });
+ });
+
+ describe('delete the image', () => {
+ const mountComponentAndDeleteImage = async () => {
+ mountComponent();
+
+ await waitForApolloRequestRender();
+ findDetailsHeader().vm.$emit('delete');
+
+ await wrapper.vm.$nextTick();
+ };
+
+ it('on delete event it deletes the image', async () => {
+ await mountComponentAndDeleteImage();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(findDeleteImage().emitted('start')).toEqual([[]]);
+ });
+
+ it('binds the correct props to the modal', async () => {
+ await mountComponentAndDeleteImage();
+
+ expect(findDeleteModal().props()).toMatchObject({
+ itemsToBeDeleted: [{ path: 'gitlab-org/gitlab-test/rails-12009' }],
+ deleteImage: true,
+ });
+ });
+
+ it('binds correctly to delete-image start and end events', async () => {
+ mountComponent();
+
+ findDeleteImage().vm.$emit('start');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTagsLoader().exists()).toBe(true);
+
+ findDeleteImage().vm.$emit('end');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ });
+
+ it('binds correctly to delete-image error event', async () => {
+ mountComponent();
+
+ findDeleteImage().vm.$emit('error');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findDeleteAlert().props('deleteAlertType')).toBe(ALERT_DANGER_IMAGE);
+ });
+ });
});
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index c4556934934..f7f207cc183 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -1,33 +1,32 @@
+import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
-import { GlSkeletonLoader, GlSprintf, GlAlert, GlSearchBoxByClick } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
-import Tracking from '~/tracking';
-import component from '~/registry/explorer/pages/list.vue';
+import DeleteImage from '~/registry/explorer/components/delete_image.vue';
import CliCommands from '~/registry/explorer/components/list_page/cli_commands.vue';
import GroupEmptyState from '~/registry/explorer/components/list_page/group_empty_state.vue';
+import ImageList from '~/registry/explorer/components/list_page/image_list.vue';
import ProjectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
import RegistryHeader from '~/registry/explorer/components/list_page/registry_header.vue';
-import ImageList from '~/registry/explorer/components/list_page/image_list.vue';
-import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-
import {
DELETE_IMAGE_SUCCESS_MESSAGE,
DELETE_IMAGE_ERROR_MESSAGE,
- IMAGE_REPOSITORY_LIST_LABEL,
- SEARCH_PLACEHOLDER_TEXT,
+ SORT_FIELDS,
} from '~/registry/explorer/constants';
-
-import getContainerRepositoriesDetails from '~/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
import deleteContainerRepositoryMutation from '~/registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
+import getContainerRepositoriesDetails from '~/registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
+import component from '~/registry/explorer/pages/list.vue';
+import Tracking from '~/tracking';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import { $toast } from '../../shared/mocks';
import {
graphQLImageListMock,
graphQLImageDeleteMock,
deletedContainerRepository,
- graphQLImageDeleteMockError,
graphQLEmptyImageListMock,
graphQLEmptyGroupImageListMock,
pageInfo,
@@ -35,7 +34,6 @@ import {
dockerCommands,
} from '../mock_data';
import { GlModal, GlEmptyState } from '../stubs';
-import { $toast } from '../../shared/mocks';
const localVue = createLocalVue();
@@ -55,9 +53,9 @@ describe('List Page', () => {
const findDeleteAlert = () => wrapper.find(GlAlert);
const findImageList = () => wrapper.find(ImageList);
- const findListHeader = () => wrapper.find('[data-testid="listHeader"]');
- const findSearchBox = () => wrapper.find(GlSearchBoxByClick);
+ const findRegistrySearch = () => wrapper.find(RegistrySearch);
const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
+ const findDeleteImage = () => wrapper.find(DeleteImage);
const waitForApolloRequestRender = async () => {
jest.runOnlyPendingTimers();
@@ -91,6 +89,7 @@ describe('List Page', () => {
GlSprintf,
RegistryHeader,
TitleArea,
+ DeleteImage,
},
mocks: {
$toast,
@@ -227,14 +226,6 @@ describe('List Page', () => {
expect(findCliCommands().exists()).toBe(false);
});
-
- it('list header is not visible', async () => {
- mountComponent({ resolver, config });
-
- await waitForApolloRequestRender();
-
- expect(findListHeader().exists()).toBe(false);
- });
});
});
@@ -256,16 +247,6 @@ describe('List Page', () => {
expect(findImageList().exists()).toBe(true);
});
- it('list header is visible', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- const header = findListHeader();
- expect(header.exists()).toBe(true);
- expect(header.text()).toBe(IMAGE_REPOSITORY_LIST_LABEL);
- });
-
describe('additional metadata', () => {
it('is called on component load', async () => {
const detailsResolver = jest
@@ -300,23 +281,22 @@ describe('List Page', () => {
});
describe('delete image', () => {
- const deleteImage = async () => {
- await wrapper.vm.$nextTick();
+ const selectImageForDeletion = async () => {
+ await waitForApolloRequestRender();
findImageList().vm.$emit('delete', deletedContainerRepository);
- findDeleteModal().vm.$emit('ok');
-
- await waitForApolloRequestRender();
};
it('should call deleteItem when confirming deletion', async () => {
const mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock);
mountComponent({ mutationResolver });
- await deleteImage();
+ await selectImageForDeletion();
+
+ findDeleteModal().vm.$emit('primary');
+ await waitForApolloRequestRender();
expect(wrapper.vm.itemToDelete).toEqual(deletedContainerRepository);
- expect(mutationResolver).toHaveBeenCalledWith({ id: deletedContainerRepository.id });
const updatedImage = findImageList()
.props('images')
@@ -326,10 +306,12 @@ describe('List Page', () => {
});
it('should show a success alert when delete request is successful', async () => {
- const mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMock);
- mountComponent({ mutationResolver });
+ mountComponent();
+
+ await selectImageForDeletion();
- await deleteImage();
+ findDeleteImage().vm.$emit('success');
+ await wrapper.vm.$nextTick();
const alert = findDeleteAlert();
expect(alert.exists()).toBe(true);
@@ -340,23 +322,12 @@ describe('List Page', () => {
describe('when delete request fails it shows an alert', () => {
it('user recoverable error', async () => {
- const mutationResolver = jest.fn().mockResolvedValue(graphQLImageDeleteMockError);
- mountComponent({ mutationResolver });
-
- await deleteImage();
-
- const alert = findDeleteAlert();
- expect(alert.exists()).toBe(true);
- expect(alert.text().replace(/\s\s+/gm, ' ')).toBe(
- DELETE_IMAGE_ERROR_MESSAGE.replace('%{title}', wrapper.vm.itemToDelete.path),
- );
- });
+ mountComponent();
- it('network error', async () => {
- const mutationResolver = jest.fn().mockRejectedValue();
- mountComponent({ mutationResolver });
+ await selectImageForDeletion();
- await deleteImage();
+ findDeleteImage().vm.$emit('error');
+ await wrapper.vm.$nextTick();
const alert = findDeleteAlert();
expect(alert.exists()).toBe(true);
@@ -368,10 +339,15 @@ describe('List Page', () => {
});
});
- describe('search', () => {
+ describe('search and sorting', () => {
const doSearch = async () => {
await waitForApolloRequestRender();
- findSearchBox().vm.$emit('submit', 'centos6');
+ findRegistrySearch().vm.$emit('filter:changed', [
+ { type: 'filtered-search-term', value: { data: 'centos6' } },
+ ]);
+
+ findRegistrySearch().vm.$emit('filter:submit');
+
await wrapper.vm.$nextTick();
};
@@ -380,9 +356,26 @@ describe('List Page', () => {
await waitForApolloRequestRender();
- const searchBox = findSearchBox();
- expect(searchBox.exists()).toBe(true);
- expect(searchBox.attributes('placeholder')).toBe(SEARCH_PLACEHOLDER_TEXT);
+ const registrySearch = findRegistrySearch();
+ expect(registrySearch.exists()).toBe(true);
+ expect(registrySearch.props()).toMatchObject({
+ filter: [],
+ sorting: { orderBy: 'UPDATED', sort: 'desc' },
+ sortableFields: SORT_FIELDS,
+ tokens: [],
+ });
+ });
+
+ it('performs sorting', async () => {
+ const resolver = jest.fn().mockResolvedValue(graphQLImageListMock);
+ mountComponent({ resolver });
+
+ await waitForApolloRequestRender();
+
+ findRegistrySearch().vm.$emit('sorting:changed', { sort: 'asc' });
+ await wrapper.vm.$nextTick();
+
+ expect(resolver).toHaveBeenCalledWith(expect.objectContaining({ sort: 'UPDATED_DESC' }));
});
it('performs a search', async () => {
@@ -499,9 +492,8 @@ describe('List Page', () => {
testTrackingCall('cancel_delete');
});
- it('send an event when confirm is clicked on modal', () => {
- const deleteModal = findDeleteModal();
- deleteModal.vm.$emit('ok');
+ it('send an event when the deletion starts', () => {
+ findDeleteImage().vm.$emit('start');
testTrackingCall('confirm_delete');
});
});
diff --git a/spec/frontend/registry/settings/components/expiration_input_spec.js b/spec/frontend/registry/settings/components/expiration_input_spec.js
index 383158067dc..b91599a2789 100644
--- a/spec/frontend/registry/settings/components/expiration_input_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_input_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlSprintf, GlFormInput, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { GlFormGroup } from 'jest/registry/shared/stubs';
import component from '~/registry/settings/components/expiration_input.vue';
import { NAME_REGEX_LENGTH } from '~/registry/settings/constants';
diff --git a/spec/frontend/registry/settings/components/expiration_run_text_spec.js b/spec/frontend/registry/settings/components/expiration_run_text_spec.js
index d74ee2d1c18..753bb10ad08 100644
--- a/spec/frontend/registry/settings/components/expiration_run_text_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_run_text_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { GlFormGroup } from 'jest/registry/shared/stubs';
import component from '~/registry/settings/components/expiration_run_text.vue';
import { NEXT_CLEANUP_LABEL, NOT_SCHEDULED_POLICY_TEXT } from '~/registry/settings/constants';
diff --git a/spec/frontend/registry/settings/components/expiration_toggle_spec.js b/spec/frontend/registry/settings/components/expiration_toggle_spec.js
index ce016e852ee..961bdfdf2c5 100644
--- a/spec/frontend/registry/settings/components/expiration_toggle_spec.js
+++ b/spec/frontend/registry/settings/components/expiration_toggle_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlToggle, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { GlFormGroup } from 'jest/registry/shared/stubs';
import component from '~/registry/settings/components/expiration_toggle.vue';
import {
diff --git a/spec/frontend/registry/settings/components/registry_settings_app_spec.js b/spec/frontend/registry/settings/components/registry_settings_app_spec.js
index 32d4f16221d..fd53efa884f 100644
--- a/spec/frontend/registry/settings/components/registry_settings_app_spec.js
+++ b/spec/frontend/registry/settings/components/registry_settings_app_spec.js
@@ -1,15 +1,15 @@
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
-import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
import component from '~/registry/settings/components/registry_settings_app.vue';
-import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql';
import SettingsForm from '~/registry/settings/components/settings_form.vue';
import {
FETCH_SETTINGS_ERROR_MESSAGE,
UNAVAILABLE_FEATURE_INTRO_TEXT,
UNAVAILABLE_USER_FEATURE_TEXT,
} from '~/registry/settings/constants';
+import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql';
import {
expirationPolicyPayload,
diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js
index 626f4fcc9f5..7527910ad59 100644
--- a/spec/frontend/registry/settings/components/settings_form_spec.js
+++ b/spec/frontend/registry/settings/components/settings_form_spec.js
@@ -2,14 +2,14 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import Tracking from '~/tracking';
import component from '~/registry/settings/components/settings_form.vue';
-import updateContainerExpirationPolicyMutation from '~/registry/settings/graphql/mutations/update_container_expiration_policy.mutation.graphql';
-import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql';
import {
UPDATE_SETTINGS_ERROR_MESSAGE,
UPDATE_SETTINGS_SUCCESS_MESSAGE,
} from '~/registry/settings/constants';
+import updateContainerExpirationPolicyMutation from '~/registry/settings/graphql/mutations/update_container_expiration_policy.mutation.graphql';
+import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql';
+import Tracking from '~/tracking';
import { GlCard, GlLoadingIcon } from '../../shared/stubs';
import { expirationPolicyPayload, expirationPolicyMutationPayload } from '../mock_data';
diff --git a/spec/frontend/registry/settings/graphql/cache_updated_spec.js b/spec/frontend/registry/settings/graphql/cache_updated_spec.js
index d88a5576f26..73655b6917b 100644
--- a/spec/frontend/registry/settings/graphql/cache_updated_spec.js
+++ b/spec/frontend/registry/settings/graphql/cache_updated_spec.js
@@ -1,5 +1,5 @@
-import { updateContainerExpirationPolicy } from '~/registry/settings/graphql/utils/cache_update';
import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql';
+import { updateContainerExpirationPolicy } from '~/registry/settings/graphql/utils/cache_update';
describe('Registry settings cache update', () => {
let client;
diff --git a/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js b/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
index c084410c65b..f306fdef624 100644
--- a/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
+++ b/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
@@ -1,9 +1,9 @@
import { mount, createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import RelatedMergeRequests from '~/related_merge_requests/components/related_merge_requests.vue';
import createStore from '~/related_merge_requests/store/index';
+import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
const FIXTURE_PATH = 'issues/related_merge_requests.json';
const API_ENDPOINT = '/api/v4/projects/2/issues/33/related_merge_requests';
diff --git a/spec/frontend/related_merge_requests/store/actions_spec.js b/spec/frontend/related_merge_requests/store/actions_spec.js
index a4257d67176..a14096388e6 100644
--- a/spec/frontend/related_merge_requests/store/actions_spec.js
+++ b/spec/frontend/related_merge_requests/store/actions_spec.js
@@ -2,8 +2,8 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import * as types from '~/related_merge_requests/store/mutation_types';
import * as actions from '~/related_merge_requests/store/actions';
+import * as types from '~/related_merge_requests/store/mutation_types';
jest.mock('~/flash');
diff --git a/spec/frontend/related_merge_requests/store/mutations_spec.js b/spec/frontend/related_merge_requests/store/mutations_spec.js
index 21b6e26376b..436c7dca6ce 100644
--- a/spec/frontend/related_merge_requests/store/mutations_spec.js
+++ b/spec/frontend/related_merge_requests/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/related_merge_requests/store/mutations';
import * as types from '~/related_merge_requests/store/mutation_types';
+import mutations from '~/related_merge_requests/store/mutations';
describe('RelatedMergeRequests Store Mutations', () => {
describe('SET_INITIAL_STATE', () => {
diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js
index 828d1b46a80..1e55ab8f9e4 100644
--- a/spec/frontend/releases/components/app_edit_new_spec.js
+++ b/spec/frontend/releases/components/app_edit_new_spec.js
@@ -1,13 +1,13 @@
-import Vuex from 'vuex';
import { mount } from '@vue/test-utils';
-import { merge } from 'lodash';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { merge } from 'lodash';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
-import ReleaseEditNewApp from '~/releases/components/app_edit_new.vue';
import * as commonUtils from '~/lib/utils/common_utils';
-import { BACK_URL_PARAM } from '~/releases/constants';
+import ReleaseEditNewApp from '~/releases/components/app_edit_new.vue';
import AssetLinksForm from '~/releases/components/asset_links_form.vue';
+import { BACK_URL_PARAM } from '~/releases/constants';
const originalRelease = getJSONFixture('api/releases/release.json');
const originalMilestones = originalRelease.milestones;
diff --git a/spec/frontend/releases/components/app_index_spec.js b/spec/frontend/releases/components/app_index_spec.js
index 1481dd30fd4..2b5270e29d6 100644
--- a/spec/frontend/releases/components/app_index_spec.js
+++ b/spec/frontend/releases/components/app_index_spec.js
@@ -1,15 +1,15 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { range as rge } from 'lodash';
import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
import { getJSONFixture } from 'helpers/fixtures';
+import waitForPromises from 'helpers/wait_for_promises';
+import api from '~/api';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import ReleasesApp from '~/releases/components/app_index.vue';
+import ReleasesPagination from '~/releases/components/releases_pagination.vue';
import createStore from '~/releases/stores';
import createListModule from '~/releases/stores/modules/list';
-import api from '~/api';
import { pageInfoHeadersWithoutPagination, pageInfoHeadersWithPagination } from '../mock_data';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import ReleasesPagination from '~/releases/components/releases_pagination.vue';
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index b1f94ca9859..5caea395f0a 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
import { shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import ReleaseShowApp from '~/releases/components/app_show.vue';
-import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue';
import ReleaseBlock from '~/releases/components/release_block.vue';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue';
const originalRelease = getJSONFixture('api/releases/release.json');
diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js
index 2b2ad0150ab..bbaa4e9dc94 100644
--- a/spec/frontend/releases/components/asset_links_form_spec.js
+++ b/spec/frontend/releases/components/asset_links_form_spec.js
@@ -1,9 +1,9 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
-import AssetLinksForm from '~/releases/components/asset_links_form.vue';
import * as commonUtils from '~/lib/utils/common_utils';
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();
diff --git a/spec/frontend/releases/components/evidence_block_spec.js b/spec/frontend/releases/components/evidence_block_spec.js
index b8c78f90fc2..50b6d1c4707 100644
--- a/spec/frontend/releases/components/evidence_block_spec.js
+++ b/spec/frontend/releases/components/evidence_block_spec.js
@@ -1,10 +1,10 @@
-import { mount } from '@vue/test-utils';
import { GlLink, GlIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { truncateSha } from '~/lib/utils/text_utility';
import EvidenceBlock from '~/releases/components/evidence_block.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
const originalRelease = getJSONFixture('api/releases/release.json');
diff --git a/spec/frontend/releases/components/release_block_assets_spec.js b/spec/frontend/releases/components/release_block_assets_spec.js
index 77bd35f94aa..3b9b16fa890 100644
--- a/spec/frontend/releases/components/release_block_assets_spec.js
+++ b/spec/frontend/releases/components/release_block_assets_spec.js
@@ -1,7 +1,7 @@
-import { mount } from '@vue/test-utils';
import { GlCollapse } from '@gitlab/ui';
-import { trimText } from 'helpers/text_helper';
+import { mount } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures';
+import { trimText } from 'helpers/text_helper';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import ReleaseBlockAssets from '~/releases/components/release_block_assets.vue';
import { ASSET_LINK_TYPE } from '~/releases/constants';
diff --git a/spec/frontend/releases/components/release_block_footer_spec.js b/spec/frontend/releases/components/release_block_footer_spec.js
index f1c0c24f8ca..e9fa22b4ec7 100644
--- a/spec/frontend/releases/components/release_block_footer_spec.js
+++ b/spec/frontend/releases/components/release_block_footer_spec.js
@@ -1,26 +1,16 @@
-import { mount } from '@vue/test-utils';
import { GlLink, GlIcon } from '@gitlab/ui';
-import { trimText } from 'helpers/text_helper';
-import { getJSONFixture } from 'helpers/fixtures';
+import { mount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
-import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue';
+import { getJSONFixture } from 'helpers/fixtures';
+import { trimText } from 'helpers/text_helper';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue';
const originalRelease = getJSONFixture('api/releases/release.json');
-const mockFutureDate = new Date(9999, 0, 0).toISOString();
-let mockIsFutureRelease = false;
-
-jest.mock('~/vue_shared/mixins/timeago', () => ({
- methods: {
- timeFormatted() {
- return mockIsFutureRelease ? 'in 1 month' : '7 fortnights ago';
- },
- tooltipTitle() {
- return 'February 30, 2401';
- },
- },
-}));
+// TODO: Encapsulate date helpers https://gitlab.com/gitlab-org/gitlab/-/issues/320883
+const MONTHS_IN_MS = 1000 * 60 * 60 * 24 * 31;
+const mockFutureDate = new Date(new Date().getTime() + MONTHS_IN_MS).toISOString();
describe('Release block footer', () => {
let wrapper;
@@ -44,7 +34,6 @@ describe('Release block footer', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
- mockIsFutureRelease = false;
});
const commitInfoSection = () => wrapper.find('.js-commit-info');
@@ -88,7 +77,7 @@ describe('Release block footer', () => {
it('renders the author and creation time info', () => {
expect(trimText(authorDateInfoSection().text())).toBe(
- `Created 7 fortnights ago by ${release.author.username}`,
+ `Created 1 year ago by ${release.author.username}`,
);
});
@@ -100,7 +89,6 @@ describe('Release block footer', () => {
describe('renders the author and creation time info with future release date', () => {
beforeEach(() => {
- mockIsFutureRelease = true;
factory({ releasedAt: mockFutureDate });
});
@@ -113,7 +101,6 @@ describe('Release block footer', () => {
describe('when the release date is in the future', () => {
beforeEach(() => {
- mockIsFutureRelease = true;
factory({ releasedAt: mockFutureDate });
});
@@ -177,13 +164,12 @@ describe('Release block footer', () => {
beforeEach(() => factory({ author: undefined }));
it('renders the release date without the author name', () => {
- expect(trimText(authorDateInfoSection().text())).toBe(`Created 7 fortnights ago`);
+ expect(trimText(authorDateInfoSection().text())).toBe(`Created 1 year ago`);
});
});
describe('future release without any author info', () => {
beforeEach(() => {
- mockIsFutureRelease = true;
factory({ author: undefined, releasedAt: mockFutureDate });
});
diff --git a/spec/frontend/releases/components/release_block_header_spec.js b/spec/frontend/releases/components/release_block_header_spec.js
index f2159871395..0f6657090e6 100644
--- a/spec/frontend/releases/components/release_block_header_spec.js
+++ b/spec/frontend/releases/components/release_block_header_spec.js
@@ -1,9 +1,9 @@
+import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { merge } from 'lodash';
-import { GlLink } from '@gitlab/ui';
import { getJSONFixture } from 'helpers/fixtures';
-import ReleaseBlockHeader from '~/releases/components/release_block_header.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import ReleaseBlockHeader from '~/releases/components/release_block_header.vue';
import { BACK_URL_PARAM } from '~/releases/constants';
const originalRelease = getJSONFixture('api/releases/release.json');
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 4eb15e9da12..47fe10af946 100644
--- a/spec/frontend/releases/components/release_block_milestone_info_spec.js
+++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js
@@ -1,10 +1,10 @@
-import { mount } from '@vue/test-utils';
import { GlProgressBar, GlLink, GlBadge, GlButton } from '@gitlab/ui';
-import { trimText } from 'helpers/text_helper';
+import { mount } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures';
+import { trimText } from 'helpers/text_helper';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import ReleaseBlockMilestoneInfo from '~/releases/components/release_block_milestone_info.vue';
import { MAX_MILESTONES_TO_DISPLAY } from '~/releases/constants';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
const { milestones: originalMilestones } = getJSONFixture('api/releases/release.json');
diff --git a/spec/frontend/releases/components/release_block_spec.js b/spec/frontend/releases/components/release_block_spec.js
index 633c6690529..1ca441f7a5a 100644
--- a/spec/frontend/releases/components/release_block_spec.js
+++ b/spec/frontend/releases/components/release_block_spec.js
@@ -1,13 +1,13 @@
-import $ from 'jquery';
import { mount } from '@vue/test-utils';
+import $ from 'jquery';
import { getJSONFixture } from 'helpers/fixtures';
+import * as commonUtils from '~/lib/utils/common_utils';
+import * as urlUtility from '~/lib/utils/url_utility';
import EvidenceBlock from '~/releases/components/evidence_block.vue';
import ReleaseBlock from '~/releases/components/release_block.vue';
import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import * as commonUtils from '~/lib/utils/common_utils';
import { BACK_URL_PARAM } from '~/releases/constants';
-import * as urlUtility from '~/lib/utils/url_utility';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
const originalRelease = getJSONFixture('api/releases/release.json');
diff --git a/spec/frontend/releases/components/release_skeleton_loader_spec.js b/spec/frontend/releases/components/release_skeleton_loader_spec.js
index 7fbf864568a..7f81081ff6c 100644
--- a/spec/frontend/releases/components/release_skeleton_loader_spec.js
+++ b/spec/frontend/releases/components/release_skeleton_loader_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlSkeletonLoader } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue';
describe('release_skeleton_loader.vue', () => {
diff --git a/spec/frontend/releases/components/releases_pagination_graphql_spec.js b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
index cee5e72e1c0..de80d82e93c 100644
--- a/spec/frontend/releases/components/releases_pagination_graphql_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
@@ -1,9 +1,9 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { historyPushState } from '~/lib/utils/common_utils';
+import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue';
import createStore from '~/releases/stores';
import createListModule from '~/releases/stores/modules/list';
-import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue';
-import { historyPushState } from '~/lib/utils/common_utils';
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
diff --git a/spec/frontend/releases/components/releases_pagination_rest_spec.js b/spec/frontend/releases/components/releases_pagination_rest_spec.js
index b015792c96b..6f2690f5322 100644
--- a/spec/frontend/releases/components/releases_pagination_rest_spec.js
+++ b/spec/frontend/releases/components/releases_pagination_rest_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
import { GlPagination } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import * as commonUtils from '~/lib/utils/common_utils';
import ReleasesPaginationRest from '~/releases/components/releases_pagination_rest.vue';
import createStore from '~/releases/stores';
import createListModule from '~/releases/stores/modules/list';
-import * as commonUtils from '~/lib/utils/common_utils';
commonUtils.historyPushState = jest.fn();
diff --git a/spec/frontend/releases/components/releases_sort_spec.js b/spec/frontend/releases/components/releases_sort_spec.js
index c089ee3cc38..f17c6678592 100644
--- a/spec/frontend/releases/components/releases_sort_spec.js
+++ b/spec/frontend/releases/components/releases_sort_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import ReleasesSort from '~/releases/components/releases_sort.vue';
import createStore from '~/releases/stores';
import createListModule from '~/releases/stores/modules/list';
diff --git a/spec/frontend/releases/components/tag_field_exsting_spec.js b/spec/frontend/releases/components/tag_field_exsting_spec.js
index d4110b57776..cef7a0272a6 100644
--- a/spec/frontend/releases/components/tag_field_exsting_spec.js
+++ b/spec/frontend/releases/components/tag_field_exsting_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
import { GlFormInput } from '@gitlab/ui';
import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import TagFieldExisting from '~/releases/components/tag_field_existing.vue';
import createStore from '~/releases/stores';
import createDetailModule from '~/releases/stores/modules/detail';
diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js
index eba0e286b27..d87718138b8 100644
--- a/spec/frontend/releases/components/tag_field_new_spec.js
+++ b/spec/frontend/releases/components/tag_field_new_spec.js
@@ -1,9 +1,9 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import RefSelector from '~/ref/components/ref_selector.vue';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
import createDetailModule from '~/releases/stores/modules/detail';
-import RefSelector from '~/ref/components/ref_selector.vue';
const TEST_TAG_NAME = 'test-tag-name';
const TEST_PROJECT_ID = '1234';
diff --git a/spec/frontend/releases/components/tag_field_spec.js b/spec/frontend/releases/components/tag_field_spec.js
index c7909a2369b..2cf5944f9e6 100644
--- a/spec/frontend/releases/components/tag_field_spec.js
+++ b/spec/frontend/releases/components/tag_field_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import TagField from '~/releases/components/tag_field.vue';
-import TagFieldNew from '~/releases/components/tag_field_new.vue';
import TagFieldExisting from '~/releases/components/tag_field_existing.vue';
+import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
import createDetailModule from '~/releases/stores/modules/detail';
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index 396e7bd8745..9c125fbb87b 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -1,17 +1,17 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
-import { getJSONFixture } from 'helpers/fixtures';
import { cloneDeep } from 'lodash';
-import * as actions from '~/releases/stores/modules/detail/actions';
-import * as types from '~/releases/stores/modules/detail/mutation_types';
-import createState from '~/releases/stores/modules/detail/state';
+import { getJSONFixture } from 'helpers/fixtures';
+import testAction from 'helpers/vuex_action_helper';
+import api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { redirectTo } from '~/lib/utils/url_utility';
-import api from '~/api';
import httpStatus from '~/lib/utils/http_status';
+import { redirectTo } from '~/lib/utils/url_utility';
import { ASSET_LINK_TYPE } from '~/releases/constants';
+import * as actions from '~/releases/stores/modules/detail/actions';
+import * as types from '~/releases/stores/modules/detail/mutation_types';
+import createState from '~/releases/stores/modules/detail/state';
import { releaseToApiJson, apiJsonToRelease } from '~/releases/util';
jest.mock('~/flash');
diff --git a/spec/frontend/releases/stores/modules/detail/mutations_spec.js b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
index 88eddc4019c..cdf26bfa834 100644
--- a/spec/frontend/releases/stores/modules/detail/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/mutations_spec.js
@@ -1,9 +1,9 @@
import { getJSONFixture } from 'helpers/fixtures';
-import createState from '~/releases/stores/modules/detail/state';
-import mutations from '~/releases/stores/modules/detail/mutations';
-import * as types from '~/releases/stores/modules/detail/mutation_types';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { ASSET_LINK_TYPE, DEFAULT_ASSET_LINK_TYPE } from '~/releases/constants';
+import * as types from '~/releases/stores/modules/detail/mutation_types';
+import mutations from '~/releases/stores/modules/detail/mutations';
+import createState from '~/releases/stores/modules/detail/state';
const originalRelease = getJSONFixture('api/releases/release.json');
diff --git a/spec/frontend/releases/stores/modules/list/actions_spec.js b/spec/frontend/releases/stores/modules/list/actions_spec.js
index 35551b77dc4..309f7387929 100644
--- a/spec/frontend/releases/stores/modules/list/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/list/actions_spec.js
@@ -1,6 +1,14 @@
import { cloneDeep } from 'lodash';
-import testAction from 'helpers/vuex_action_helper';
import { getJSONFixture } from 'helpers/fixtures';
+import testAction from 'helpers/vuex_action_helper';
+import api from '~/api';
+import {
+ normalizeHeaders,
+ parseIntPagination,
+ convertObjectPropsToCamelCase,
+} from '~/lib/utils/common_utils';
+import { PAGE_SIZE } from '~/releases/constants';
+import allReleasesQuery from '~/releases/queries/all_releases.query.graphql';
import {
fetchReleases,
fetchReleasesGraphQl,
@@ -8,18 +16,10 @@ import {
receiveReleasesError,
setSorting,
} from '~/releases/stores/modules/list/actions';
-import createState from '~/releases/stores/modules/list/state';
import * as types from '~/releases/stores/modules/list/mutation_types';
-import api from '~/api';
+import createState from '~/releases/stores/modules/list/state';
import { gqClient, convertAllReleasesGraphQLResponse } from '~/releases/util';
-import {
- normalizeHeaders,
- parseIntPagination,
- convertObjectPropsToCamelCase,
-} from '~/lib/utils/common_utils';
import { pageInfoHeadersWithoutPagination } from '../../../mock_data';
-import allReleasesQuery from '~/releases/queries/all_releases.query.graphql';
-import { PAGE_SIZE } from '~/releases/constants';
const originalRelease = getJSONFixture('api/releases/release.json');
const originalReleases = [originalRelease];
diff --git a/spec/frontend/releases/stores/modules/list/mutations_spec.js b/spec/frontend/releases/stores/modules/list/mutations_spec.js
index 78071573072..ea6a4ada16a 100644
--- a/spec/frontend/releases/stores/modules/list/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/list/mutations_spec.js
@@ -1,10 +1,10 @@
import { getJSONFixture } from 'helpers/fixtures';
-import createState from '~/releases/stores/modules/list/state';
-import mutations from '~/releases/stores/modules/list/mutations';
-import * as types from '~/releases/stores/modules/list/mutation_types';
import { parseIntPagination, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { pageInfoHeadersWithoutPagination } from '../../../mock_data';
+import * as types from '~/releases/stores/modules/list/mutation_types';
+import mutations from '~/releases/stores/modules/list/mutations';
+import createState from '~/releases/stores/modules/list/state';
import { convertAllReleasesGraphQLResponse } from '~/releases/util';
+import { pageInfoHeadersWithoutPagination } from '../../../mock_data';
const originalRelease = getJSONFixture('api/releases/release.json');
const originalReleases = [originalRelease];
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 ccceb78f2d1..b716d54c9fc 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,7 +1,7 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import GroupedAccessibilityReportsApp from '~/reports/accessibility_report/grouped_accessibility_reports_app.vue';
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';
diff --git a/spec/frontend/reports/accessibility_report/store/actions_spec.js b/spec/frontend/reports/accessibility_report/store/actions_spec.js
index 4e607fa5a76..46dbe1ff7a1 100644
--- a/spec/frontend/reports/accessibility_report/store/actions_spec.js
+++ b/spec/frontend/reports/accessibility_report/store/actions_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
import testAction from 'helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
+import createStore from '~/reports/accessibility_report/store';
import * as actions from '~/reports/accessibility_report/store/actions';
import * as types from '~/reports/accessibility_report/store/mutation_types';
-import createStore from '~/reports/accessibility_report/store';
import { mockReport } from '../mock_data';
describe('Accessibility Reports actions', () => {
diff --git a/spec/frontend/reports/accessibility_report/store/getters_spec.js b/spec/frontend/reports/accessibility_report/store/getters_spec.js
index d74c71cfa09..96344596003 100644
--- a/spec/frontend/reports/accessibility_report/store/getters_spec.js
+++ b/spec/frontend/reports/accessibility_report/store/getters_spec.js
@@ -1,5 +1,5 @@
-import * as getters from '~/reports/accessibility_report/store/getters';
import createStore from '~/reports/accessibility_report/store';
+import * as getters from '~/reports/accessibility_report/store/getters';
import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '~/reports/constants';
describe('Accessibility reports store getters', () => {
diff --git a/spec/frontend/reports/accessibility_report/store/mutations_spec.js b/spec/frontend/reports/accessibility_report/store/mutations_spec.js
index a4e9571b721..b336261d804 100644
--- a/spec/frontend/reports/accessibility_report/store/mutations_spec.js
+++ b/spec/frontend/reports/accessibility_report/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/reports/accessibility_report/store/mutations';
import createStore from '~/reports/accessibility_report/store';
+import mutations from '~/reports/accessibility_report/store/mutations';
describe('Accessibility Reports mutations', () => {
let localState;
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 ecb657af6f1..f0b23bb7b58 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,7 +1,7 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import GroupedCodequalityReportsApp from '~/reports/codequality_report/grouped_codequality_reports_app.vue';
import CodequalityIssueBody from '~/reports/codequality_report/components/codequality_issue_body.vue';
+import GroupedCodequalityReportsApp from '~/reports/codequality_report/grouped_codequality_reports_app.vue';
import { getStoreConfig } from '~/reports/codequality_report/store';
import { mockParsedHeadIssues, mockParsedBaseIssues } from './mock_data';
@@ -9,7 +9,6 @@ const localVue = createLocalVue();
localVue.use(Vuex);
describe('Grouped code quality reports app', () => {
- const Component = localVue.extend(GroupedCodequalityReportsApp);
let wrapper;
let mockStore;
@@ -22,7 +21,7 @@ describe('Grouped code quality reports app', () => {
};
const mountComponent = (props = {}) => {
- wrapper = mount(Component, {
+ wrapper = mount(GroupedCodequalityReportsApp, {
store: mockStore,
localVue,
propsData: {
@@ -135,7 +134,7 @@ describe('Grouped code quality reports app', () => {
});
it('renders error text', () => {
- expect(findWidget().text()).toEqual('Failed to load codeclimate report');
+ expect(findWidget().text()).toContain('Failed to load codeclimate report');
});
it('renders a help icon with more information', () => {
diff --git a/spec/frontend/reports/codequality_report/mock_data.js b/spec/frontend/reports/codequality_report/mock_data.js
index 9bd61527d3f..c5cecb34509 100644
--- a/spec/frontend/reports/codequality_report/mock_data.js
+++ b/spec/frontend/reports/codequality_report/mock_data.js
@@ -88,3 +88,53 @@ export const issueDiff = [
urlPath: 'headPath/lib/six.rb#L6',
},
];
+
+export const reportIssues = {
+ status: 'failed',
+ new_errors: [
+ {
+ description:
+ 'Method `long_if` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.',
+ severity: 'minor',
+ file_path: 'codequality.rb',
+ line: 5,
+ },
+ ],
+ resolved_errors: [
+ {
+ description: 'Insecure Dependency',
+ severity: 'major',
+ file_path: 'lib/six.rb',
+ line: 22,
+ },
+ ],
+ existing_errors: [],
+ summary: { total: 3, resolved: 0, errored: 3 },
+};
+
+export const parsedReportIssues = {
+ newIssues: [
+ {
+ description:
+ 'Method `long_if` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.',
+ file_path: 'codequality.rb',
+ line: 5,
+ name:
+ 'Method `long_if` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.',
+ path: 'codequality.rb',
+ severity: 'minor',
+ urlPath: 'null/codequality.rb#L5',
+ },
+ ],
+ resolvedIssues: [
+ {
+ description: 'Insecure Dependency',
+ file_path: 'lib/six.rb',
+ line: 22,
+ name: 'Insecure Dependency',
+ path: 'lib/six.rb',
+ severity: 'major',
+ urlPath: 'null/lib/six.rb#L22',
+ },
+ ],
+};
diff --git a/spec/frontend/reports/codequality_report/store/actions_spec.js b/spec/frontend/reports/codequality_report/store/actions_spec.js
index 321785cb85a..a2b256448ef 100644
--- a/spec/frontend/reports/codequality_report/store/actions_spec.js
+++ b/spec/frontend/reports/codequality_report/store/actions_spec.js
@@ -1,11 +1,18 @@
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'spec/test_constants';
import testAction from 'helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
import axios from '~/lib/utils/axios_utils';
+import createStore from '~/reports/codequality_report/store';
import * as actions from '~/reports/codequality_report/store/actions';
import * as types from '~/reports/codequality_report/store/mutation_types';
-import createStore from '~/reports/codequality_report/store';
-import { headIssues, baseIssues, mockParsedHeadIssues, mockParsedBaseIssues } from '../mock_data';
+import {
+ headIssues,
+ baseIssues,
+ mockParsedHeadIssues,
+ mockParsedBaseIssues,
+ reportIssues,
+ parsedReportIssues,
+} from '../mock_data';
// mock codequality comparison worker
jest.mock('~/reports/codequality_report/workers/codequality_comparison_worker', () =>
@@ -39,6 +46,7 @@ describe('Codequality Reports actions', () => {
headPath: 'headPath',
baseBlobPath: 'baseBlobPath',
headBlobPath: 'headBlobPath',
+ reportsPath: 'reportsPath',
helpPath: 'codequalityHelpPath',
};
@@ -55,68 +63,119 @@ describe('Codequality Reports actions', () => {
describe('fetchReports', () => {
let mock;
+ let diffFeatureFlagEnabled;
- beforeEach(() => {
- localState.headPath = `${TEST_HOST}/head.json`;
- localState.basePath = `${TEST_HOST}/base.json`;
- mock = new MockAdapter(axios);
- });
+ describe('with codequalityBackendComparison feature flag enabled', () => {
+ beforeEach(() => {
+ diffFeatureFlagEnabled = true;
+ localState.reportsPath = `${TEST_HOST}/codequality_reports.json`;
+ mock = new MockAdapter(axios);
+ });
- afterEach(() => {
- mock.restore();
- });
+ afterEach(() => {
+ mock.restore();
+ });
- describe('on success', () => {
- it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => {
- mock.onGet(`${TEST_HOST}/head.json`).reply(200, headIssues);
- mock.onGet(`${TEST_HOST}/base.json`).reply(200, baseIssues);
-
- testAction(
- actions.fetchReports,
- null,
- localState,
- [{ type: types.REQUEST_REPORTS }],
- [
- {
- payload: {
- newIssues: [mockParsedHeadIssues[0]],
- resolvedIssues: [mockParsedBaseIssues[0]],
+ describe('on success', () => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => {
+ mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(200, reportIssues);
+
+ testAction(
+ actions.fetchReports,
+ diffFeatureFlagEnabled,
+ localState,
+ [{ type: types.REQUEST_REPORTS }],
+ [
+ {
+ payload: parsedReportIssues,
+ type: 'receiveReportsSuccess',
},
- type: 'receiveReportsSuccess',
- },
- ],
- done,
- );
+ ],
+ done,
+ );
+ });
});
- });
- describe('on error', () => {
- it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
- mock.onGet(`${TEST_HOST}/head.json`).reply(500);
-
- testAction(
- actions.fetchReports,
- null,
- localState,
- [{ type: types.REQUEST_REPORTS }],
- [{ type: 'receiveReportsError' }],
- done,
- );
+ describe('on error', () => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
+ mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(500);
+
+ testAction(
+ actions.fetchReports,
+ diffFeatureFlagEnabled,
+ localState,
+ [{ type: types.REQUEST_REPORTS }],
+ [{ type: 'receiveReportsError', payload: expect.any(Error) }],
+ done,
+ );
+ });
});
});
- describe('with no base path', () => {
- it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
- localState.basePath = null;
-
- testAction(
- actions.fetchReports,
- null,
- localState,
- [{ type: types.REQUEST_REPORTS }],
- [{ type: 'receiveReportsError' }],
- done,
- );
+ describe('with codequalityBackendComparison feature flag disabled', () => {
+ beforeEach(() => {
+ diffFeatureFlagEnabled = false;
+ localState.headPath = `${TEST_HOST}/head.json`;
+ localState.basePath = `${TEST_HOST}/base.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('on success', () => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => {
+ mock.onGet(`${TEST_HOST}/head.json`).reply(200, headIssues);
+ mock.onGet(`${TEST_HOST}/base.json`).reply(200, baseIssues);
+
+ testAction(
+ actions.fetchReports,
+ diffFeatureFlagEnabled,
+ localState,
+ [{ type: types.REQUEST_REPORTS }],
+ [
+ {
+ payload: {
+ newIssues: [mockParsedHeadIssues[0]],
+ resolvedIssues: [mockParsedBaseIssues[0]],
+ },
+ type: 'receiveReportsSuccess',
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('on error', () => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
+ mock.onGet(`${TEST_HOST}/head.json`).reply(500);
+
+ testAction(
+ actions.fetchReports,
+ diffFeatureFlagEnabled,
+ localState,
+ [{ type: types.REQUEST_REPORTS }],
+ [{ type: 'receiveReportsError', payload: expect.any(Error) }],
+ done,
+ );
+ });
+ });
+
+ describe('with no base path', () => {
+ it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
+ localState.basePath = null;
+
+ testAction(
+ actions.fetchReports,
+ diffFeatureFlagEnabled,
+ localState,
+ [{ type: types.REQUEST_REPORTS }],
+ [{ type: 'receiveReportsError' }],
+ done,
+ );
+ });
});
});
});
@@ -142,7 +201,7 @@ describe('Codequality Reports actions', () => {
actions.receiveReportsError,
null,
localState,
- [{ type: types.RECEIVE_REPORTS_ERROR }],
+ [{ type: types.RECEIVE_REPORTS_ERROR, payload: null }],
[],
done,
);
diff --git a/spec/frontend/reports/codequality_report/store/getters_spec.js b/spec/frontend/reports/codequality_report/store/getters_spec.js
index a641e2fe74f..de025f814ef 100644
--- a/spec/frontend/reports/codequality_report/store/getters_spec.js
+++ b/spec/frontend/reports/codequality_report/store/getters_spec.js
@@ -1,5 +1,5 @@
-import * as getters from '~/reports/codequality_report/store/getters';
import createStore from '~/reports/codequality_report/store';
+import * as getters from '~/reports/codequality_report/store/getters';
import { LOADING, ERROR, SUCCESS } from '~/reports/constants';
describe('Codequality reports store getters', () => {
diff --git a/spec/frontend/reports/codequality_report/store/mutations_spec.js b/spec/frontend/reports/codequality_report/store/mutations_spec.js
index 658abf3088c..05a16cd6f82 100644
--- a/spec/frontend/reports/codequality_report/store/mutations_spec.js
+++ b/spec/frontend/reports/codequality_report/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/reports/codequality_report/store/mutations';
import createStore from '~/reports/codequality_report/store';
+import mutations from '~/reports/codequality_report/store/mutations';
describe('Codequality Reports mutations', () => {
let localState;
@@ -55,6 +55,12 @@ describe('Codequality Reports mutations', () => {
expect(localState.hasError).toEqual(false);
});
+ it('clears statusReason', () => {
+ mutations.RECEIVE_REPORTS_SUCCESS(localState, {});
+
+ expect(localState.statusReason).toEqual('');
+ });
+
it('sets newIssues and resolvedIssues from response data', () => {
const data = { newIssues: [{ id: 1 }], resolvedIssues: [{ id: 2 }] };
mutations.RECEIVE_REPORTS_SUCCESS(localState, data);
@@ -76,5 +82,13 @@ describe('Codequality Reports mutations', () => {
expect(localState.hasError).toEqual(true);
});
+
+ it('sets statusReason to string from error response data', () => {
+ const data = { status_reason: 'This merge request does not have codequality reports' };
+ const error = { response: { data } };
+ mutations.RECEIVE_REPORTS_ERROR(localState, error);
+
+ expect(localState.statusReason).toEqual(data.status_reason);
+ });
});
});
diff --git a/spec/frontend/reports/codequality_report/store/utils/codequality_comparison_spec.js b/spec/frontend/reports/codequality_report/store/utils/codequality_comparison_spec.js
index 085d697672d..389e9b4a1f6 100644
--- a/spec/frontend/reports/codequality_report/store/utils/codequality_comparison_spec.js
+++ b/spec/frontend/reports/codequality_report/store/utils/codequality_comparison_spec.js
@@ -2,7 +2,13 @@ import {
parseCodeclimateMetrics,
doCodeClimateComparison,
} from '~/reports/codequality_report/store/utils/codequality_comparison';
-import { baseIssues, mockParsedHeadIssues, mockParsedBaseIssues } from '../../mock_data';
+import {
+ baseIssues,
+ mockParsedHeadIssues,
+ mockParsedBaseIssues,
+ reportIssues,
+ parsedReportIssues,
+} from '../../mock_data';
jest.mock('~/reports/codequality_report/workers/codequality_comparison_worker', () => {
let mockPostMessageCallback;
@@ -34,7 +40,7 @@ describe('Codequality report store utils', () => {
let result;
describe('parseCodeclimateMetrics', () => {
- it('should parse the received issues', () => {
+ it('should parse the issues from codeclimate artifacts', () => {
[result] = parseCodeclimateMetrics(baseIssues, 'path');
expect(result.name).toEqual(baseIssues[0].check_name);
@@ -42,6 +48,14 @@ describe('Codequality report store utils', () => {
expect(result.line).toEqual(baseIssues[0].location.lines.begin);
});
+ it('should parse the issues from backend codequality diff', () => {
+ [result] = parseCodeclimateMetrics(reportIssues.new_errors, 'path');
+
+ expect(result.name).toEqual(parsedReportIssues.newIssues[0].name);
+ expect(result.path).toEqual(parsedReportIssues.newIssues[0].path);
+ expect(result.line).toEqual(parsedReportIssues.newIssues[0].line);
+ });
+
describe('when an issue has no location or path', () => {
const issue = { description: 'Insecure Dependency' };
diff --git a/spec/frontend/reports/components/grouped_test_reports_app_spec.js b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
index 492192988fb..ed261ed12c0 100644
--- a/spec/frontend/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
@@ -5,11 +5,11 @@ import GroupedTestReportsApp from '~/reports/components/grouped_test_reports_app
import { getStoreConfig } from '~/reports/store';
import { failedReport } from '../mock_data/mock_data';
-import successTestReports from '../mock_data/no_failures_report.json';
+import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json';
+import newErrorsTestReports from '../mock_data/new_errors_report.json';
import newFailedTestReports from '../mock_data/new_failures_report.json';
+import successTestReports from '../mock_data/no_failures_report.json';
import recentFailuresTestReports from '../mock_data/recent_failures_report.json';
-import newErrorsTestReports from '../mock_data/new_errors_report.json';
-import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json';
import resolvedFailures from '../mock_data/resolved_failures.json';
const localVue = createLocalVue();
@@ -18,12 +18,11 @@ localVue.use(Vuex);
describe('Grouped test reports app', () => {
const endpoint = 'endpoint.json';
const pipelinePath = '/path/to/pipeline';
- const Component = localVue.extend(GroupedTestReportsApp);
let wrapper;
let mockStore;
const mountComponent = ({ props = { pipelinePath } } = {}) => {
- wrapper = mount(Component, {
+ wrapper = mount(GroupedTestReportsApp, {
store: mockStore,
localVue,
propsData: {
diff --git a/spec/frontend/reports/components/modal_spec.js b/spec/frontend/reports/components/modal_spec.js
index 39b84d1ee05..d47bb964e8a 100644
--- a/spec/frontend/reports/components/modal_spec.js
+++ b/spec/frontend/reports/components/modal_spec.js
@@ -2,9 +2,9 @@ import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import CodeBlock from '~/vue_shared/components/code_block.vue';
import ReportsModal from '~/reports/components/modal.vue';
import state from '~/reports/store/state';
+import CodeBlock from '~/vue_shared/components/code_block.vue';
const StubbedGlModal = { template: '<div><slot></slot></div>', name: 'GlModal', props: ['title'] };
diff --git a/spec/frontend/reports/components/report_item_spec.js b/spec/frontend/reports/components/report_item_spec.js
index 6aac07984e3..a7243c5377b 100644
--- a/spec/frontend/reports/components/report_item_spec.js
+++ b/spec/frontend/reports/components/report_item_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
-import { STATUS_SUCCESS } from '~/reports/constants';
-import ReportItem from '~/reports/components/report_item.vue';
-import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
import { componentNames } from '~/reports/components/issue_body';
+import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
+import ReportItem from '~/reports/components/report_item.vue';
+import { STATUS_SUCCESS } from '~/reports/constants';
describe('ReportItem', () => {
describe('showReportSectionStatusIcon', () => {
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index c3219b34057..c9bf3185f8f 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
import reportSection from '~/reports/components/report_section.vue';
diff --git a/spec/frontend/reports/components/summary_row_spec.js b/spec/frontend/reports/components/summary_row_spec.js
index 85c68ed069b..bdd6de1e0be 100644
--- a/spec/frontend/reports/components/summary_row_spec.js
+++ b/spec/frontend/reports/components/summary_row_spec.js
@@ -32,7 +32,7 @@ describe('Summary row', () => {
it('renders provided summary', () => {
createComponent();
- expect(findSummary().text()).toEqual(props.summary);
+ expect(findSummary().text()).toContain(props.summary);
});
it('renders provided icon', () => {
@@ -48,7 +48,7 @@ describe('Summary row', () => {
createComponent({ slots: { summary: summarySlotContent } });
expect(wrapper.text()).not.toContain(props.summary);
- expect(findSummary().text()).toEqual(summarySlotContent);
+ expect(findSummary().text()).toContain(summarySlotContent);
});
});
});
diff --git a/spec/frontend/reports/components/test_issue_body_spec.js b/spec/frontend/reports/components/test_issue_body_spec.js
index c13a3599fef..2843620a18d 100644
--- a/spec/frontend/reports/components/test_issue_body_spec.js
+++ b/spec/frontend/reports/components/test_issue_body_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import { trimText } from 'helpers/text_helper';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import component from '~/reports/components/test_issue_body.vue';
import createStore from '~/reports/store';
import { issue } from '../mock_data/mock_data';
diff --git a/spec/frontend/reports/store/actions_spec.js b/spec/frontend/reports/store/actions_spec.js
index b7c4a31b1c8..25c3105466f 100644
--- a/spec/frontend/reports/store/actions_spec.js
+++ b/spec/frontend/reports/store/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
import axios from '~/lib/utils/axios_utils';
import {
setEndpoint,
@@ -13,8 +13,8 @@ import {
openModal,
closeModal,
} from '~/reports/store/actions';
-import state from '~/reports/store/state';
import * as types from '~/reports/store/mutation_types';
+import state from '~/reports/store/state';
describe('Reports Store Actions', () => {
let mockedState;
diff --git a/spec/frontend/reports/store/mutations_spec.js b/spec/frontend/reports/store/mutations_spec.js
index 59065d1151f..652b3b0ec45 100644
--- a/spec/frontend/reports/store/mutations_spec.js
+++ b/spec/frontend/reports/store/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/reports/store/state';
-import mutations from '~/reports/store/mutations';
import * as types from '~/reports/store/mutation_types';
+import mutations from '~/reports/store/mutations';
+import state from '~/reports/store/state';
import { issue } from '../mock_data/mock_data';
describe('Reports Store Mutations', () => {
diff --git a/spec/frontend/reports/store/utils_spec.js b/spec/frontend/reports/store/utils_spec.js
index 5249e9ffcce..cbc87bbb5ec 100644
--- a/spec/frontend/reports/store/utils_spec.js
+++ b/spec/frontend/reports/store/utils_spec.js
@@ -1,4 +1,3 @@
-import * as utils from '~/reports/store/utils';
import {
STATUS_FAILED,
STATUS_SUCCESS,
@@ -6,6 +5,7 @@ import {
ICON_SUCCESS,
ICON_NOTFOUND,
} from '~/reports/constants';
+import * as utils from '~/reports/store/utils';
describe('Reports store utils', () => {
describe('summaryTextbuilder', () => {
diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js
index a0dc608ddc9..2ac2069a177 100644
--- a/spec/frontend/repository/components/breadcrumbs_spec.js
+++ b/spec/frontend/repository/components/breadcrumbs_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import { GlDropdown } from '@gitlab/ui';
+import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import Breadcrumbs from '~/repository/components/breadcrumbs.vue';
let vm;
diff --git a/spec/frontend/repository/components/last_commit_spec.js b/spec/frontend/repository/components/last_commit_spec.js
index fe77057c3d4..ebea7dde34a 100644
--- a/spec/frontend/repository/components/last_commit_spec.js
+++ b/spec/frontend/repository/components/last_commit_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import LastCommit from '~/repository/components/last_commit.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -58,77 +58,75 @@ describe('Repository last commit component', () => {
loading | label
${true} | ${'shows'}
${false} | ${'hides'}
- `('$label when loading icon $loading is true', ({ loading }) => {
+ `('$label when loading icon $loading is true', async ({ loading }) => {
factory(createCommitData(), loading);
- return vm.vm.$nextTick(() => {
- expect(vm.find(GlLoadingIcon).exists()).toBe(loading);
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.find(GlLoadingIcon).exists()).toBe(loading);
});
- it('renders commit widget', () => {
+ it('renders commit widget', async () => {
factory();
- return vm.vm.$nextTick(() => {
- expect(vm.element).toMatchSnapshot();
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.element).toMatchSnapshot();
});
- it('renders short commit ID', () => {
+ it('renders short commit ID', async () => {
factory();
- return vm.vm.$nextTick(() => {
- expect(vm.find('[data-testid="last-commit-id-label"]').text()).toEqual('12345678');
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.find('[data-testid="last-commit-id-label"]').text()).toEqual('12345678');
});
- it('hides pipeline components when pipeline does not exist', () => {
+ it('hides pipeline components when pipeline does not exist', async () => {
factory(createCommitData({ pipeline: null }));
- return vm.vm.$nextTick(() => {
- expect(vm.find('.js-commit-pipeline').exists()).toBe(false);
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.find('.js-commit-pipeline').exists()).toBe(false);
});
- it('renders pipeline components', () => {
+ it('renders pipeline components', async () => {
factory();
- return vm.vm.$nextTick(() => {
- expect(vm.find('.js-commit-pipeline').exists()).toBe(true);
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.find('.js-commit-pipeline').exists()).toBe(true);
});
- it('hides author component when author does not exist', () => {
+ it('hides author component when author does not exist', async () => {
factory(createCommitData({ author: null }));
- return vm.vm.$nextTick(() => {
- expect(vm.find('.js-user-link').exists()).toBe(false);
- expect(vm.find(UserAvatarLink).exists()).toBe(false);
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.find('.js-user-link').exists()).toBe(false);
+ expect(vm.find(UserAvatarLink).exists()).toBe(false);
});
- it('does not render description expander when description is null', () => {
+ it('does not render description expander when description is null', async () => {
factory(createCommitData({ descriptionHtml: null }));
- return vm.vm.$nextTick(() => {
- expect(vm.find('.text-expander').exists()).toBe(false);
- expect(vm.find('.commit-row-description').exists()).toBe(false);
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.find('.text-expander').exists()).toBe(false);
+ expect(vm.find('.commit-row-description').exists()).toBe(false);
});
- it('expands commit description when clicking expander', () => {
+ it('expands commit description when clicking expander', async () => {
factory(createCommitData({ descriptionHtml: 'Test description' }));
- return vm.vm
- .$nextTick()
- .then(() => {
- vm.find('.text-expander').vm.$emit('click');
- return vm.vm.$nextTick();
- })
- .then(() => {
- expect(vm.find('.commit-row-description').isVisible()).toBe(true);
- expect(vm.find('.text-expander').classes('open')).toBe(true);
- });
+ await vm.vm.$nextTick();
+
+ vm.find('.text-expander').vm.$emit('click');
+
+ await vm.vm.$nextTick();
+
+ expect(vm.find('.commit-row-description').isVisible()).toBe(true);
+ expect(vm.find('.text-expander').classes('open')).toBe(true);
});
it('strips the first newline of the description', async () => {
@@ -141,19 +139,19 @@ describe('Repository last commit component', () => {
);
});
- it('renders the signature HTML as returned by the backend', () => {
+ it('renders the signature HTML as returned by the backend', async () => {
factory(createCommitData({ signatureHtml: '<button>Verified</button>' }));
- return vm.vm.$nextTick().then(() => {
- expect(vm.element).toMatchSnapshot();
- });
+ await vm.vm.$nextTick();
+
+ expect(vm.element).toMatchSnapshot();
});
- it('sets correct CSS class if the commit message is empty', () => {
+ it('sets correct CSS class if the commit message is empty', async () => {
factory(createCommitData({ message: '' }));
- return vm.vm.$nextTick().then(() => {
- expect(vm.find('.item-title').classes()).toContain(emptyMessageClass);
- });
+ await vm.vm.$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 ebd985e640c..466eed52739 100644
--- a/spec/frontend/repository/components/preview/index_spec.js
+++ b/spec/frontend/repository/components/preview/index_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { handleLocationHash } from '~/lib/utils/common_utils';
import Preview from '~/repository/components/preview/index.vue';
diff --git a/spec/frontend/repository/components/table/index_spec.js b/spec/frontend/repository/components/table/index_spec.js
index 1b8bbd5af6b..af263f43d7d 100644
--- a/spec/frontend/repository/components/table/index_spec.js
+++ b/spec/frontend/repository/components/table/index_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Table from '~/repository/components/table/index.vue';
import TableRow from '~/repository/components/table/row.vue';
diff --git a/spec/frontend/repository/components/table/parent_row_spec.js b/spec/frontend/repository/components/table/parent_row_spec.js
index b4800112fee..cf1ed272634 100644
--- a/spec/frontend/repository/components/table/parent_row_spec.js
+++ b/spec/frontend/repository/components/table/parent_row_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import ParentRow from '~/repository/components/table/parent_row.vue';
let vm;
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 767b117c798..69cb69de5df 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import { GlBadge, GlLink, GlIcon } from '@gitlab/ui';
+import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import TableRow from '~/repository/components/table/row.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { FILE_SYMLINK_MODE } from '~/vue_shared/constants';
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 70dbfaea551..2930e39df8a 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import TreeContent, { INITIAL_FETCH_COUNT } from '~/repository/components/tree_content.vue';
import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
+import TreeContent, { INITIAL_FETCH_COUNT } from '~/repository/components/tree_content.vue';
let vm;
let $apollo;
diff --git a/spec/frontend/repository/utils/dom_spec.js b/spec/frontend/repository/utils/dom_spec.js
index f9e619a82d1..9839ddc6cdb 100644
--- a/spec/frontend/repository/utils/dom_spec.js
+++ b/spec/frontend/repository/utils/dom_spec.js
@@ -1,5 +1,5 @@
-import { TEST_HOST } from 'helpers/test_constants';
import { setHTMLFixture } from 'helpers/fixtures';
+import { TEST_HOST } from 'helpers/test_constants';
import { updateElementsVisibility, updateFormAction } from '~/repository/utils/dom';
describe('updateElementsVisibility', () => {
diff --git a/spec/frontend/right_sidebar_spec.js b/spec/frontend/right_sidebar_spec.js
index 1b31030cb92..f3719b28baa 100644
--- a/spec/frontend/right_sidebar_spec.js
+++ b/spec/frontend/right_sidebar_spec.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import '~/commons/bootstrap';
import axios from '~/lib/utils/axios_utils';
import Sidebar from '~/right_sidebar';
diff --git a/spec/frontend/search/highlight_blob_search_result_spec.js b/spec/frontend/search/highlight_blob_search_result_spec.js
index 112e6f5124f..c1b0c7d794b 100644
--- a/spec/frontend/search/highlight_blob_search_result_spec.js
+++ b/spec/frontend/search/highlight_blob_search_result_spec.js
@@ -1,6 +1,7 @@
import setHighlightClass from '~/search/highlight_blob_search_result';
const fixture = 'search/blob_search_result.html';
+const searchKeyword = 'Send'; // spec/frontend/fixtures/search.rb#79
describe('search/highlight_blob_search_result', () => {
preloadFixtures(fixture);
@@ -8,7 +9,7 @@ describe('search/highlight_blob_search_result', () => {
beforeEach(() => loadFixtures(fixture));
it('highlights lines with search term occurrence', () => {
- setHighlightClass();
+ setHighlightClass(searchKeyword);
expect(document.querySelectorAll('.blob-result .hll').length).toBe(4);
});
diff --git a/spec/frontend/search/index_spec.js b/spec/frontend/search/index_spec.js
index 023cd341345..1992a7f4437 100644
--- a/spec/frontend/search/index_spec.js
+++ b/spec/frontend/search/index_spec.js
@@ -1,9 +1,11 @@
+import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
import { initSearchApp } from '~/search';
import createStore from '~/search/store';
jest.mock('~/search/store');
jest.mock('~/search/topbar');
jest.mock('~/search/sidebar');
+jest.mock('ee_else_ce/search/highlight_blob_search_result');
describe('initSearchApp', () => {
let defaultLocation;
@@ -42,6 +44,7 @@ describe('initSearchApp', () => {
it(`decodes ${search} to ${decodedSearch}`, () => {
expect(createStore).toHaveBeenCalledWith({ query: { search: decodedSearch } });
+ expect(setHighlightClass).toHaveBeenCalledWith(decodedSearch);
});
});
});
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
index ee509eaad8d..d076997b04a 100644
--- a/spec/frontend/search/mock_data.js
+++ b/spec/frontend/search/mock_data.js
@@ -26,7 +26,7 @@ export const MOCK_GROUPS = [
export const MOCK_PROJECT = {
name: 'test project',
- namespace_id: MOCK_GROUP.id,
+ namespace: MOCK_GROUP,
nameWithNamespace: 'test group test project',
id: 'test_1',
};
@@ -34,14 +34,30 @@ export const MOCK_PROJECT = {
export const MOCK_PROJECTS = [
{
name: 'test project',
- namespace_id: MOCK_GROUP.id,
+ namespace: MOCK_GROUP,
name_with_namespace: 'test group test project',
id: 'test_1',
},
{
name: 'test project 2',
- namespace_id: MOCK_GROUP.id,
+ namespace: MOCK_GROUP,
name_with_namespace: 'test group test project 2',
id: 'test_2',
},
];
+
+export const MOCK_SORT_OPTIONS = [
+ {
+ title: 'Most relevant',
+ sortable: false,
+ sortParam: 'relevant',
+ },
+ {
+ title: 'Created date',
+ sortable: true,
+ sortParam: {
+ asc: 'created_asc',
+ desc: 'created_desc',
+ },
+ },
+];
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
index 94a39b90d02..b93527c1fe9 100644
--- a/spec/frontend/search/sidebar/components/app_spec.js
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlButton, GlLink } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import GlobalSearchSidebar from '~/search/sidebar/components/app.vue';
import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter.vue';
diff --git a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
index 42fcc859308..3713e1d414f 100644
--- a/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/confidentiality_filter_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+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';
diff --git a/spec/frontend/search/sidebar/components/radio_filter_spec.js b/spec/frontend/search/sidebar/components/radio_filter_spec.js
index 9918af54cfe..4c81312e479 100644
--- a/spec/frontend/search/sidebar/components/radio_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/radio_filter_spec.js
@@ -1,10 +1,10 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
-import { stateFilterData } from '~/search/sidebar/constants/state_filter_data';
import { confidentialFilterData } from '~/search/sidebar/constants/confidential_filter_data';
+import { stateFilterData } from '~/search/sidebar/constants/state_filter_data';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/search/sidebar/components/status_filter_spec.js b/spec/frontend/search/sidebar/components/status_filter_spec.js
index 21fc663397e..08ce57b206b 100644
--- a/spec/frontend/search/sidebar/components/status_filter_spec.js
+++ b/spec/frontend/search/sidebar/components/status_filter_spec.js
@@ -1,8 +1,8 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
-import StatusFilter from '~/search/sidebar/components/status_filter.vue';
import RadioFilter from '~/search/sidebar/components/radio_filter.vue';
+import StatusFilter from '~/search/sidebar/components/status_filter.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/search/sort/components/app_spec.js b/spec/frontend/search/sort/components/app_spec.js
new file mode 100644
index 00000000000..5806d6b51d2
--- /dev/null
+++ b/spec/frontend/search/sort/components/app_spec.js
@@ -0,0 +1,168 @@
+import { GlButtonGroup, GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+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);
+
+describe('GlobalSearchSort', () => {
+ let wrapper;
+
+ const actionSpies = {
+ setQuery: jest.fn(),
+ applyQuery: jest.fn(),
+ };
+
+ const defaultProps = {
+ searchSortOptions: MOCK_SORT_OPTIONS,
+ };
+
+ const createComponent = (initialState, props) => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMount(GlobalSearchSort, {
+ localVue,
+ store,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findSortButtonGroup = () => wrapper.find(GlButtonGroup);
+ const findSortDropdown = () => wrapper.find(GlDropdown);
+ const findSortDirectionButton = () => wrapper.find(GlButton);
+ const findDropdownItems = () => findSortDropdown().findAll(GlDropdownItem);
+ const findDropdownItemsText = () => findDropdownItems().wrappers.map((w) => w.text());
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders Sort Button Group', () => {
+ expect(findSortButtonGroup().exists()).toBe(true);
+ });
+
+ it('renders Sort Dropdown', () => {
+ expect(findSortDropdown().exists()).toBe(true);
+ });
+
+ it('renders Sort Direction Button', () => {
+ expect(findSortDirectionButton().exists()).toBe(true);
+ });
+ });
+
+ describe('Sort Dropdown Items', () => {
+ describe('renders', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('an instance for each namespace', () => {
+ expect(findDropdownItemsText()).toStrictEqual(
+ MOCK_SORT_OPTIONS.map((option) => option.title),
+ );
+ });
+ });
+
+ describe.each`
+ sortQuery | value
+ ${null} | ${MOCK_SORT_OPTIONS[0].title}
+ ${'asdf'} | ${MOCK_SORT_OPTIONS[0].title}
+ ${MOCK_SORT_OPTIONS[0].sortParam} | ${MOCK_SORT_OPTIONS[0].title}
+ ${MOCK_SORT_OPTIONS[1].sortParam.desc} | ${MOCK_SORT_OPTIONS[1].title}
+ ${MOCK_SORT_OPTIONS[1].sortParam.asc} | ${MOCK_SORT_OPTIONS[1].title}
+ `('selected', ({ sortQuery, value }) => {
+ describe(`when sort option is ${sortQuery}`, () => {
+ beforeEach(() => {
+ createComponent({ query: { sort: sortQuery } });
+ });
+
+ it('is set correctly', () => {
+ expect(findSortDropdown().attributes('text')).toBe(value);
+ });
+ });
+ });
+ });
+
+ describe.each`
+ description | sortQuery | sortUi | disabled
+ ${'non-sortable'} | ${MOCK_SORT_OPTIONS[0].sortParam} | ${SORT_DIRECTION_UI.disabled} | ${'true'}
+ ${'descending sortable'} | ${MOCK_SORT_OPTIONS[1].sortParam.desc} | ${SORT_DIRECTION_UI.desc} | ${undefined}
+ ${'ascending sortable'} | ${MOCK_SORT_OPTIONS[1].sortParam.asc} | ${SORT_DIRECTION_UI.asc} | ${undefined}
+ `('Sort Direction Button', ({ description, sortQuery, sortUi, disabled }) => {
+ describe(`when sort option is ${description}`, () => {
+ beforeEach(() => {
+ createComponent({ query: { sort: sortQuery } });
+ });
+
+ it('sets the UI correctly', () => {
+ expect(findSortDirectionButton().attributes('disabled')).toBe(disabled);
+ expect(findSortDirectionButton().attributes('title')).toBe(sortUi.tooltip);
+ expect(findSortDirectionButton().attributes('icon')).toBe(sortUi.icon);
+ });
+ });
+ });
+
+ describe('actions', () => {
+ describe.each`
+ description | index | value
+ ${'non-sortable'} | ${0} | ${MOCK_SORT_OPTIONS[0].sortParam}
+ ${'sortable'} | ${1} | ${MOCK_SORT_OPTIONS[1].sortParam.desc}
+ `('handleSortChange', ({ description, index, value }) => {
+ describe(`when clicking a ${description} option`, () => {
+ beforeEach(() => {
+ createComponent();
+ findDropdownItems().at(index).vm.$emit('click');
+ });
+
+ it('calls setQuery and applyQuery correctly', () => {
+ expect(actionSpies.setQuery).toHaveBeenCalledTimes(1);
+ expect(actionSpies.applyQuery).toHaveBeenCalledTimes(1);
+ expect(actionSpies.setQuery).toHaveBeenCalledWith(expect.any(Object), {
+ key: 'sort',
+ value,
+ });
+ });
+ });
+ });
+
+ describe.each`
+ description | sortQuery | value
+ ${'descending'} | ${MOCK_SORT_OPTIONS[1].sortParam.desc} | ${MOCK_SORT_OPTIONS[1].sortParam.asc}
+ ${'ascending'} | ${MOCK_SORT_OPTIONS[1].sortParam.asc} | ${MOCK_SORT_OPTIONS[1].sortParam.desc}
+ `('handleSortDirectionChange', ({ description, sortQuery, value }) => {
+ describe(`when toggling a ${description} option`, () => {
+ beforeEach(() => {
+ createComponent({ query: { sort: sortQuery } });
+ findSortDirectionButton().vm.$emit('click');
+ });
+
+ it('calls setQuery and applyQuery correctly', () => {
+ expect(actionSpies.setQuery).toHaveBeenCalledTimes(1);
+ expect(actionSpies.applyQuery).toHaveBeenCalledTimes(1);
+ expect(actionSpies.setQuery).toHaveBeenCalledWith(expect.any(Object), {
+ key: 'sort',
+ value,
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index e4536a3e136..ab622c53387 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -1,12 +1,12 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import * as urlUtils from '~/lib/utils/url_utility';
import * as actions from '~/search/store/actions';
import * as types from '~/search/store/mutation_types';
-import * as urlUtils from '~/lib/utils/url_utility';
import createState from '~/search/store/state';
-import axios from '~/lib/utils/axios_utils';
-import createFlash from '~/flash';
import { MOCK_QUERY, MOCK_GROUPS, MOCK_PROJECT, MOCK_PROJECTS } from '../mock_data';
jest.mock('~/flash');
diff --git a/spec/frontend/search/store/mutations_spec.js b/spec/frontend/search/store/mutations_spec.js
index 560ed66263b..df94ba40ff2 100644
--- a/spec/frontend/search/store/mutations_spec.js
+++ b/spec/frontend/search/store/mutations_spec.js
@@ -1,6 +1,6 @@
+import * as types from '~/search/store/mutation_types';
import mutations from '~/search/store/mutations';
import createState from '~/search/store/state';
-import * as types from '~/search/store/mutation_types';
import { MOCK_QUERY, MOCK_GROUPS, MOCK_PROJECTS } from '../mock_data';
describe('Global Search Store Mutations', () => {
diff --git a/spec/frontend/search/topbar/components/app_spec.js b/spec/frontend/search/topbar/components/app_spec.js
new file mode 100644
index 00000000000..fb953f2ed1b
--- /dev/null
+++ b/spec/frontend/search/topbar/components/app_spec.js
@@ -0,0 +1,113 @@
+import { GlForm, GlSearchBoxByType, GlButton } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { MOCK_QUERY } from 'jest/search/mock_data';
+import GlobalSearchTopbar from '~/search/topbar/components/app.vue';
+import GroupFilter from '~/search/topbar/components/group_filter.vue';
+import ProjectFilter from '~/search/topbar/components/project_filter.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('GlobalSearchTopbar', () => {
+ let wrapper;
+
+ const actionSpies = {
+ applyQuery: jest.fn(),
+ setQuery: jest.fn(),
+ };
+
+ const createComponent = (initialState) => {
+ const store = new Vuex.Store({
+ state: {
+ query: MOCK_QUERY,
+ ...initialState,
+ },
+ actions: actionSpies,
+ });
+
+ wrapper = shallowMount(GlobalSearchTopbar, {
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTopbarForm = () => wrapper.find(GlForm);
+ const findGlSearchBox = () => wrapper.find(GlSearchBoxByType);
+ const findGroupFilter = () => wrapper.find(GroupFilter);
+ const findProjectFilter = () => wrapper.find(ProjectFilter);
+ const findSearchButton = () => wrapper.find(GlButton);
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders Topbar Form always', () => {
+ expect(findTopbarForm().exists()).toBe(true);
+ });
+
+ describe('Search box', () => {
+ it('renders always', () => {
+ expect(findGlSearchBox().exists()).toBe(true);
+ });
+
+ describe('onSearch', () => {
+ const testSearch = 'test search';
+
+ beforeEach(() => {
+ findGlSearchBox().vm.$emit('input', testSearch);
+ });
+
+ it('calls setQuery when input event is fired from GlSearchBoxByType', () => {
+ expect(actionSpies.setQuery).toHaveBeenCalledWith(expect.any(Object), {
+ key: 'search',
+ value: testSearch,
+ });
+ });
+ });
+ });
+
+ describe.each`
+ snippets | showFilters
+ ${null} | ${true}
+ ${{ query: { snippets: '' } }} | ${true}
+ ${{ query: { snippets: false } }} | ${true}
+ ${{ query: { snippets: true } }} | ${false}
+ ${{ query: { snippets: 'false' } }} | ${true}
+ ${{ query: { snippets: 'true' } }} | ${false}
+ `('topbar filters', ({ snippets, showFilters }) => {
+ beforeEach(() => {
+ createComponent(snippets);
+ });
+
+ it(`does${showFilters ? '' : ' not'} render when snippets is ${JSON.stringify(
+ snippets,
+ )}`, () => {
+ expect(findGroupFilter().exists()).toBe(showFilters);
+ expect(findProjectFilter().exists()).toBe(showFilters);
+ });
+ });
+
+ it('renders SearchButton always', () => {
+ expect(findSearchButton().exists()).toBe(true);
+ });
+ });
+
+ describe('actions', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('clicking SearchButton calls applyQuery', () => {
+ findTopbarForm().vm.$emit('submit', { preventDefault: () => {} });
+
+ expect(actionSpies.applyQuery).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/search/topbar/components/group_filter_spec.js b/spec/frontend/search/topbar/components/group_filter_spec.js
index 017808d576e..15b46f9c058 100644
--- a/spec/frontend/search/topbar/components/group_filter_spec.js
+++ b/spec/frontend/search/topbar/components/group_filter_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { MOCK_GROUP, MOCK_QUERY } from 'jest/search/mock_data';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
import GroupFilter from '~/search/topbar/components/group_filter.vue';
diff --git a/spec/frontend/search/topbar/components/project_filter_spec.js b/spec/frontend/search/topbar/components/project_filter_spec.js
index c1fc61d7e89..3bd0769b34a 100644
--- a/spec/frontend/search/topbar/components/project_filter_spec.js
+++ b/spec/frontend/search/topbar/components/project_filter_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { MOCK_PROJECT, MOCK_QUERY } from 'jest/search/mock_data';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
import ProjectFilter from '~/search/topbar/components/project_filter.vue';
@@ -99,7 +99,7 @@ describe('ProjectFilter', () => {
it('calls setUrlParams with project id, group id, then calls visitUrl', () => {
expect(setUrlParams).toHaveBeenCalledWith({
- [GROUP_DATA.queryParam]: MOCK_PROJECT.namespace_id,
+ [GROUP_DATA.queryParam]: MOCK_PROJECT.namespace.id,
[PROJECT_DATA.queryParam]: MOCK_PROJECT.id,
});
expect(visitUrl).toHaveBeenCalled();
diff --git a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
index 86e29571d0f..5de948592d4 100644
--- a/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
+++ b/spec/frontend/search/topbar/components/searchable_dropdown_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui';
+import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import Vuex from 'vuex';
import { MOCK_GROUPS, MOCK_GROUP, MOCK_QUERY } from 'jest/search/mock_data';
import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
import { ANY_OPTION, GROUP_DATA } from '~/search/topbar/constants';
diff --git a/spec/frontend/search_autocomplete_spec.js b/spec/frontend/search_autocomplete_spec.js
index e844bc96e05..a9fbe0fe552 100644
--- a/spec/frontend/search_autocomplete_spec.js
+++ b/spec/frontend/search_autocomplete_spec.js
@@ -1,11 +1,10 @@
/* eslint-disable no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign */
-
-import $ from 'jquery';
import AxiosMockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import axios from '~/lib/utils/axios_utils';
import initSearchAutocomplete from '~/search_autocomplete';
import '~/lib/utils/common_utils';
-import axios from '~/lib/utils/axios_utils';
describe('Search autocomplete dropdown', () => {
let widget = null;
diff --git a/spec/frontend/search_settings/components/search_settings_spec.js b/spec/frontend/search_settings/components/search_settings_spec.js
index b80f9b15abf..173936e1ce3 100644
--- a/spec/frontend/search_settings/components/search_settings_spec.js
+++ b/spec/frontend/search_settings/components/search_settings_spec.js
@@ -2,6 +2,7 @@ import { GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import SearchSettings from '~/search_settings/components/search_settings.vue';
import { HIGHLIGHT_CLASS, HIDE_CLASS } from '~/search_settings/constants';
+import { isExpanded, expandSection, closeSection } from '~/settings_panels';
describe('search_settings/components/search_settings.vue', () => {
const ROOT_ID = 'content-body';
@@ -9,6 +10,8 @@ describe('search_settings/components/search_settings.vue', () => {
const SEARCH_TERM = 'Delete project';
const GENERAL_SETTINGS_ID = 'js-general-settings';
const ADVANCED_SETTINGS_ID = 'js-advanced-settings';
+ const EXTRA_SETTINGS_ID = 'js-extra-settings';
+
let wrapper;
const buildWrapper = () => {
@@ -16,10 +19,15 @@ describe('search_settings/components/search_settings.vue', () => {
propsData: {
searchRoot: document.querySelector(`#${ROOT_ID}`),
sectionSelector: SECTION_SELECTOR,
+ isExpandedFn: isExpanded,
+ },
+ // Add real listeners so we can simplify and strengthen some tests.
+ listeners: {
+ expand: expandSection,
+ collapse: closeSection,
},
});
};
-
const sections = () => Array.from(document.querySelectorAll(SECTION_SELECTOR));
const sectionsCount = () => sections().length;
const visibleSectionsCount = () =>
@@ -39,7 +47,10 @@ describe('search_settings/components/search_settings.vue', () => {
<section id="${GENERAL_SETTINGS_ID}" class="settings">
<span>General</span>
</section>
- <section id="${ADVANCED_SETTINGS_ID}" class="settings">
+ <section id="${ADVANCED_SETTINGS_ID}" class="settings expanded">
+ <span>Advanced</span>
+ </section>
+ <section id="${EXTRA_SETTINGS_ID}" class="settings">
<span>${SEARCH_TERM}</span>
</section>
</div>
@@ -52,17 +63,6 @@ describe('search_settings/components/search_settings.vue', () => {
wrapper.destroy();
});
- it('expands first section and collapses the rest', () => {
- clearSearch();
-
- const [firstSection, ...otherSections] = sections();
-
- expect(wrapper.emitted()).toEqual({
- expand: [[firstSection]],
- collapse: otherSections.map((x) => [x]),
- });
- });
-
it('hides sections that do not match the search term', () => {
const hiddenSection = document.querySelector(`#${GENERAL_SETTINGS_ID}`);
search(SEARCH_TERM);
@@ -72,12 +72,11 @@ describe('search_settings/components/search_settings.vue', () => {
});
it('expands section that matches the search term', () => {
- const section = document.querySelector(`#${ADVANCED_SETTINGS_ID}`);
+ const section = document.querySelector(`#${EXTRA_SETTINGS_ID}`);
search(SEARCH_TERM);
- // Last called because expand is always called once to reset the page state
- expect(wrapper.emitted().expand[1][0]).toBe(section);
+ expect(wrapper.emitted('expand')).toEqual([[section]]);
});
it('highlight elements that match the search term', () => {
@@ -86,21 +85,64 @@ describe('search_settings/components/search_settings.vue', () => {
expect(highlightedElementsCount()).toBe(1);
});
- describe('when search term is cleared', () => {
- beforeEach(() => {
- search(SEARCH_TERM);
- });
-
- it('displays all sections', () => {
- expect(visibleSectionsCount()).toBe(1);
- clearSearch();
- expect(visibleSectionsCount()).toBe(sectionsCount());
+ describe('default', () => {
+ it('test setup starts with expansion state', () => {
+ expect(sections().map(isExpanded)).toEqual([false, true, false]);
});
- it('removes the highlight from all elements', () => {
- expect(highlightedElementsCount()).toBe(1);
- clearSearch();
- expect(highlightedElementsCount()).toBe(0);
+ describe('when searched and cleared', () => {
+ beforeEach(() => {
+ search('Test');
+ clearSearch();
+ });
+
+ it('displays all sections', () => {
+ expect(visibleSectionsCount()).toBe(sectionsCount());
+ });
+
+ it('removes the highlight from all elements', () => {
+ expect(highlightedElementsCount()).toBe(0);
+ });
+
+ it('should preserve original expansion state', () => {
+ expect(sections().map(isExpanded)).toEqual([false, true, false]);
+ });
+
+ it('should preserve state by emitting events', () => {
+ const [first, mid, last] = sections();
+
+ expect(wrapper.emitted()).toEqual({
+ expand: [[mid]],
+ collapse: [[first], [last]],
+ });
+ });
+
+ describe('after multiple searches and clear', () => {
+ beforeEach(() => {
+ search('Test');
+ search(SEARCH_TERM);
+ clearSearch();
+ });
+
+ it('should preserve last expansion state', () => {
+ expect(sections().map(isExpanded)).toEqual([false, true, false]);
+ });
+ });
+
+ describe('after user expands and collapses, search, and clear', () => {
+ beforeEach(() => {
+ const [first, mid] = sections();
+ closeSection(mid);
+ expandSection(first);
+
+ search(SEARCH_TERM);
+ clearSearch();
+ });
+
+ it('should preserve last expansion state', () => {
+ expect(sections().map(isExpanded)).toEqual([true, false, false]);
+ });
+ });
});
});
});
diff --git a/spec/frontend/search_settings/index_spec.js b/spec/frontend/search_settings/index_spec.js
index 122ee1251bb..1d56d054eea 100644
--- a/spec/frontend/search_settings/index_spec.js
+++ b/spec/frontend/search_settings/index_spec.js
@@ -1,36 +1,25 @@
-import $ from 'jquery';
-import { setHTMLFixture } from 'helpers/fixtures';
+import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import initSearch from '~/search_settings';
-import { expandSection, closeSection } from '~/settings_panels';
+import mount from '~/search_settings/mount';
-jest.mock('~/settings_panels');
-
-describe('search_settings/index', () => {
- let app;
-
- beforeEach(() => {
- const el = document.createElement('div');
-
- setHTMLFixture('<div id="content-body"></div>');
-
- app = initSearch({ el });
- });
+jest.mock('~/search_settings/mount');
+describe('~/search_settings', () => {
afterEach(() => {
- app.$destroy();
+ resetHTMLFixture();
});
- it('calls settings_panel.onExpand when expand event is emitted', () => {
- const section = { name: 'section' };
- app.$refs.searchSettings.$emit('expand', section);
+ it('initializes search settings when js-search-settings-app is available', async () => {
+ setHTMLFixture('<div class="js-search-settings-app"></div>');
+
+ await initSearch();
- expect(expandSection).toHaveBeenCalledWith($(section));
+ expect(mount).toHaveBeenCalled();
});
- it('calls settings_panel.closeSection when collapse event is emitted', () => {
- const section = { name: 'section' };
- app.$refs.searchSettings.$emit('collapse', section);
+ it('does not initialize search settings when js-search-settings-app is unavailable', async () => {
+ await initSearch();
- expect(closeSection).toHaveBeenCalledWith($(section));
+ expect(mount).not.toHaveBeenCalled();
});
});
diff --git a/spec/frontend/search_settings/mount_spec.js b/spec/frontend/search_settings/mount_spec.js
new file mode 100644
index 00000000000..8c141c4704e
--- /dev/null
+++ b/spec/frontend/search_settings/mount_spec.js
@@ -0,0 +1,35 @@
+import { setHTMLFixture } from 'helpers/fixtures';
+import mount from '~/search_settings/mount';
+import { expandSection, closeSection } from '~/settings_panels';
+
+jest.mock('~/settings_panels');
+
+describe('search_settings/mount', () => {
+ let app;
+
+ beforeEach(() => {
+ const el = document.createElement('div');
+
+ setHTMLFixture('<div id="content-body"></div>');
+
+ app = mount({ el });
+ });
+
+ afterEach(() => {
+ app.$destroy();
+ });
+
+ it('calls settings_panel.onExpand when expand event is emitted', () => {
+ const section = { name: 'section' };
+ app.$refs.searchSettings.$emit('expand', section);
+
+ expect(expandSection).toHaveBeenCalledWith(section);
+ });
+
+ it('calls settings_panel.closeSection when collapse event is emitted', () => {
+ const section = { name: 'section' };
+ app.$refs.searchSettings.$emit('collapse', section);
+
+ expect(closeSection).toHaveBeenCalledWith(section);
+ });
+});
diff --git a/spec/frontend/search_spec.js b/spec/frontend/search_spec.js
deleted file mode 100644
index d234a7fccb9..00000000000
--- a/spec/frontend/search_spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
-import Search from '~/pages/search/show/search';
-
-jest.mock('~/api');
-jest.mock('ee_else_ce/search/highlight_blob_search_result');
-
-describe('Search', () => {
- const fixturePath = 'search/show.html';
-
- preloadFixtures(fixturePath);
-
- describe('constructor side effects', () => {
- afterEach(() => {
- jest.restoreAllMocks();
- });
-
- it('highlights lines with search terms in blob search results', () => {
- new Search(); // eslint-disable-line no-new
-
- expect(setHighlightClass).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/security_configuration/app_spec.js b/spec/frontend/security_configuration/app_spec.js
new file mode 100644
index 00000000000..11d481fb210
--- /dev/null
+++ b/spec/frontend/security_configuration/app_spec.js
@@ -0,0 +1,27 @@
+import { shallowMount } from '@vue/test-utils';
+import App from '~/security_configuration/components/app.vue';
+import ConfigurationTable from '~/security_configuration/components/configuration_table.vue';
+
+describe('App Component', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(App, {});
+ };
+ const findConfigurationTable = () => wrapper.findComponent(ConfigurationTable);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders correct primary & Secondary Heading', () => {
+ createComponent();
+ expect(wrapper.text()).toContain('Security Configuration');
+ expect(wrapper.text()).toContain('Testing & Compliance');
+ });
+
+ it('renders ConfigurationTable Component', () => {
+ createComponent();
+ expect(findConfigurationTable().exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/security_configuration/configuration_table_spec.js b/spec/frontend/security_configuration/configuration_table_spec.js
new file mode 100644
index 00000000000..49f9a7a3ea8
--- /dev/null
+++ b/spec/frontend/security_configuration/configuration_table_spec.js
@@ -0,0 +1,48 @@
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import ConfigurationTable from '~/security_configuration/components/configuration_table.vue';
+import { features, UPGRADE_CTA } from '~/security_configuration/components/features_constants';
+
+import {
+ REPORT_TYPE_SAST,
+ REPORT_TYPE_DAST,
+ REPORT_TYPE_DEPENDENCY_SCANNING,
+ REPORT_TYPE_CONTAINER_SCANNING,
+ REPORT_TYPE_COVERAGE_FUZZING,
+ REPORT_TYPE_LICENSE_COMPLIANCE,
+} from '~/vue_shared/security_reports/constants';
+
+describe('Configuration Table Component', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = extendedWrapper(mount(ConfigurationTable, {}));
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it.each(features)('should match strings', (feature) => {
+ expect(wrapper.text()).toContain(feature.name);
+ expect(wrapper.text()).toContain(feature.description);
+
+ if (feature.type === REPORT_TYPE_SAST) {
+ expect(wrapper.findByTestId(feature.type).text()).toBe('Configure via Merge Request');
+ } else if (
+ [
+ REPORT_TYPE_DAST,
+ REPORT_TYPE_DEPENDENCY_SCANNING,
+ REPORT_TYPE_CONTAINER_SCANNING,
+ REPORT_TYPE_COVERAGE_FUZZING,
+ REPORT_TYPE_LICENSE_COMPLIANCE,
+ ].includes(feature.type)
+ ) {
+ expect(wrapper.findByTestId(feature.type).text()).toMatchInterpolatedText(UPGRADE_CTA);
+ }
+ });
+});
diff --git a/spec/frontend/security_configuration/manage_sast_spec.js b/spec/frontend/security_configuration/manage_sast_spec.js
new file mode 100644
index 00000000000..7c76f19ddb4
--- /dev/null
+++ b/spec/frontend/security_configuration/manage_sast_spec.js
@@ -0,0 +1,136 @@
+import { GlButton } from '@gitlab/ui';
+import { mount } 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 waitForPromises from 'helpers/wait_for_promises';
+import { redirectTo } from '~/lib/utils/url_utility';
+import ManageSast from '~/security_configuration/components/manage_sast.vue';
+import configureSastMutation from '~/security_configuration/graphql/configure_sast.mutation.graphql';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ redirectTo: jest.fn(),
+}));
+
+Vue.use(VueApollo);
+
+describe('Manage Sast Component', () => {
+ let wrapper;
+
+ const findButton = () => wrapper.findComponent(GlButton);
+ const successHandler = async () => {
+ return {
+ data: {
+ configureSast: {
+ successPath: 'testSuccessPath',
+ errors: [],
+ __typename: 'ConfigureSastPayload',
+ },
+ },
+ };
+ };
+
+ const noSuccessPathHandler = async () => {
+ return {
+ data: {
+ configureSast: {
+ successPath: '',
+ errors: [],
+ __typename: 'ConfigureSastPayload',
+ },
+ },
+ };
+ };
+
+ const errorHandler = async () => {
+ return {
+ data: {
+ configureSast: {
+ successPath: 'testSuccessPath',
+ errors: ['foo'],
+ __typename: 'ConfigureSastPayload',
+ },
+ },
+ };
+ };
+
+ const pendingHandler = () => new Promise(() => {});
+
+ function createMockApolloProvider(handler) {
+ const requestHandlers = [[configureSastMutation, handler]];
+
+ return createMockApollo(requestHandlers);
+ }
+
+ function createComponent(options = {}) {
+ const { mockApollo } = options;
+ wrapper = extendedWrapper(
+ mount(ManageSast, {
+ apolloProvider: mockApollo,
+ }),
+ );
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render Button with correct text', () => {
+ createComponent();
+ expect(findButton().text()).toContain('Configure via Merge Request');
+ });
+
+ describe('given a successful response', () => {
+ beforeEach(() => {
+ const mockApollo = createMockApolloProvider(successHandler);
+ createComponent({ mockApollo });
+ });
+
+ it('should call redirect helper with correct value', async () => {
+ await wrapper.trigger('click');
+ await waitForPromises();
+ expect(redirectTo).toHaveBeenCalledTimes(1);
+ expect(redirectTo).toHaveBeenCalledWith('testSuccessPath');
+ // This is done for UX reasons. If the loading prop is set to false
+ // on success, then there's a period where the button is clickable
+ // again. Instead, we want the button to display a loading indicator
+ // for the remainder of the lifetime of the page (i.e., until the
+ // browser can start painting the new page it's been redirected to).
+ expect(findButton().props().loading).toBe(true);
+ });
+ });
+
+ describe('given a pending response', () => {
+ beforeEach(() => {
+ const mockApollo = createMockApolloProvider(pendingHandler);
+ createComponent({ mockApollo });
+ });
+
+ it('renders spinner correctly', async () => {
+ expect(findButton().props('loading')).toBe(false);
+ await wrapper.trigger('click');
+ await waitForPromises();
+ expect(findButton().props('loading')).toBe(true);
+ });
+ });
+
+ describe.each`
+ handler | message
+ ${noSuccessPathHandler} | ${'SAST merge request creation mutation failed'}
+ ${errorHandler} | ${'foo'}
+ `('given an error response', ({ handler, message }) => {
+ beforeEach(() => {
+ const mockApollo = createMockApolloProvider(handler);
+ createComponent({ mockApollo });
+ });
+
+ it('should catch and emit error', async () => {
+ await wrapper.trigger('click');
+ await waitForPromises();
+ expect(wrapper.emitted('error')).toEqual([[message]]);
+ expect(findButton().props('loading')).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/upgrade_spec.js b/spec/frontend/security_configuration/upgrade_spec.js
new file mode 100644
index 00000000000..0ab1108b265
--- /dev/null
+++ b/spec/frontend/security_configuration/upgrade_spec.js
@@ -0,0 +1,29 @@
+import { mount } from '@vue/test-utils';
+import { UPGRADE_CTA } from '~/security_configuration/components/features_constants';
+import Upgrade from '~/security_configuration/components/upgrade.vue';
+
+let wrapper;
+const createComponent = () => {
+ wrapper = mount(Upgrade, {});
+};
+
+beforeEach(() => {
+ createComponent();
+});
+
+afterEach(() => {
+ wrapper.destroy();
+});
+
+describe('Upgrade component', () => {
+ it('renders correct text in link', () => {
+ expect(wrapper.text()).toMatchInterpolatedText(UPGRADE_CTA);
+ });
+
+ it('renders link with correct attributes', () => {
+ expect(wrapper.find('a').attributes()).toMatchObject({
+ href: 'https://about.gitlab.com/pricing/',
+ target: '_blank',
+ });
+ });
+});
diff --git a/spec/frontend/self_monitor/components/self_monitor_form_spec.js b/spec/frontend/self_monitor/components/self_monitor_form_spec.js
index dfa961c5115..5f5934305c6 100644
--- a/spec/frontend/self_monitor/components/self_monitor_form_spec.js
+++ b/spec/frontend/self_monitor/components/self_monitor_form_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import SelfMonitor from '~/self_monitor/components/self_monitor_form.vue';
import { createStore } from '~/self_monitor/store';
diff --git a/spec/frontend/sentry/index_spec.js b/spec/frontend/sentry/index_spec.js
index 82b6c445d96..13b9b9e909c 100644
--- a/spec/frontend/sentry/index_spec.js
+++ b/spec/frontend/sentry/index_spec.js
@@ -1,5 +1,5 @@
-import SentryConfig from '~/sentry/sentry_config';
import index from '~/sentry/index';
+import SentryConfig from '~/sentry/sentry_config';
describe('SentryConfig options', () => {
const dsn = 'https://123@sentry.gitlab.test/123';
diff --git a/spec/frontend/sentry/sentry_config_spec.js b/spec/frontend/sentry/sentry_config_spec.js
index 5ee261f480a..f7102f9b2f9 100644
--- a/spec/frontend/sentry/sentry_config_spec.js
+++ b/spec/frontend/sentry/sentry_config_spec.js
@@ -1,5 +1,5 @@
-import * as Sentry from '~/sentry/wrapper';
import SentryConfig from '~/sentry/sentry_config';
+import * as Sentry from '~/sentry/wrapper';
describe('SentryConfig', () => {
describe('IGNORE_ERRORS', () => {
diff --git a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
index 135a3844e78..772d6903052 100644
--- a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
+++ b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
@@ -1,6 +1,6 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
import Stacktrace from '~/error_tracking/components/stacktrace.vue';
import SentryErrorStackTrace from '~/sentry_error_stack_trace/components/sentry_error_stack_trace.vue';
diff --git a/spec/frontend/serverless/components/empty_state_spec.js b/spec/frontend/serverless/components/empty_state_spec.js
index daa1576a4ec..d63882c2a6d 100644
--- a/spec/frontend/serverless/components/empty_state_spec.js
+++ b/spec/frontend/serverless/components/empty_state_spec.js
@@ -1,7 +1,7 @@
import { GlEmptyState, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { createStore } from '~/serverless/store';
import EmptyStateComponent from '~/serverless/components/empty_state.vue';
+import { createStore } from '~/serverless/store';
describe('EmptyStateComponent', () => {
let wrapper;
diff --git a/spec/frontend/serverless/components/environment_row_spec.js b/spec/frontend/serverless/components/environment_row_spec.js
index a59b4fdbb7b..944283136d0 100644
--- a/spec/frontend/serverless/components/environment_row_spec.js
+++ b/spec/frontend/serverless/components/environment_row_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import environmentRowComponent from '~/serverless/components/environment_row.vue';
-import { mockServerlessFunctions, mockServerlessFunctionsDiffEnv } from '../mock_data';
import { translate } from '~/serverless/utils';
+import { mockServerlessFunctions, mockServerlessFunctionsDiffEnv } from '../mock_data';
const createComponent = (env, envName) =>
shallowMount(environmentRowComponent, {
diff --git a/spec/frontend/serverless/components/function_details_spec.js b/spec/frontend/serverless/components/function_details_spec.js
index 248dd418941..d2b8de71e01 100644
--- a/spec/frontend/serverless/components/function_details_spec.js
+++ b/spec/frontend/serverless/components/function_details_spec.js
@@ -1,6 +1,6 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import functionDetailsComponent from '~/serverless/components/function_details.vue';
import { createStore } from '~/serverless/store';
diff --git a/spec/frontend/serverless/components/functions_spec.js b/spec/frontend/serverless/components/functions_spec.js
index 0fca027fe56..01dd512c5d3 100644
--- a/spec/frontend/serverless/components/functions_spec.js
+++ b/spec/frontend/serverless/components/functions_spec.js
@@ -1,13 +1,13 @@
-import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
-import AxiosMockAdapter from 'axios-mock-adapter';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
-import functionsComponent from '~/serverless/components/functions.vue';
-import { createStore } from '~/serverless/store';
import EmptyState from '~/serverless/components/empty_state.vue';
import EnvironmentRow from '~/serverless/components/environment_row.vue';
+import functionsComponent from '~/serverless/components/functions.vue';
+import { createStore } from '~/serverless/store';
import { mockServerlessFunctions } from '../mock_data';
describe('functionsComponent', () => {
diff --git a/spec/frontend/serverless/components/missing_prometheus_spec.js b/spec/frontend/serverless/components/missing_prometheus_spec.js
index ffdb1f13111..d5b187452c6 100644
--- a/spec/frontend/serverless/components/missing_prometheus_spec.js
+++ b/spec/frontend/serverless/components/missing_prometheus_spec.js
@@ -1,7 +1,7 @@
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { createStore } from '~/serverless/store';
import missingPrometheusComponent from '~/serverless/components/missing_prometheus.vue';
+import { createStore } from '~/serverless/store';
describe('missingPrometheusComponent', () => {
let wrapper;
diff --git a/spec/frontend/serverless/components/url_spec.js b/spec/frontend/serverless/components/url_spec.js
index c43933e5b94..8c839577aa0 100644
--- a/spec/frontend/serverless/components/url_spec.js
+++ b/spec/frontend/serverless/components/url_spec.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import urlComponent from '~/serverless/components/url.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
diff --git a/spec/frontend/serverless/store/actions_spec.js b/spec/frontend/serverless/store/actions_spec.js
index 32e30a57d4b..61b9bd121af 100644
--- a/spec/frontend/serverless/store/actions_spec.js
+++ b/spec/frontend/serverless/store/actions_spec.js
@@ -1,9 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import axios from '~/lib/utils/axios_utils';
import statusCodes from '~/lib/utils/http_status';
import { fetchFunctions, fetchMetrics } from '~/serverless/store/actions';
import { mockServerlessFunctions, mockMetrics } from '../mock_data';
-import axios from '~/lib/utils/axios_utils';
import { adjustMetricQuery } from '../utils';
describe('ServerlessActions', () => {
diff --git a/spec/frontend/serverless/store/getters_spec.js b/spec/frontend/serverless/store/getters_spec.js
index 92853fda37c..e1942bd2759 100644
--- a/spec/frontend/serverless/store/getters_spec.js
+++ b/spec/frontend/serverless/store/getters_spec.js
@@ -1,5 +1,5 @@
-import serverlessState from '~/serverless/store/state';
import * as getters from '~/serverless/store/getters';
+import serverlessState from '~/serverless/store/state';
import { mockServerlessFunctions } from '../mock_data';
describe('Serverless Store Getters', () => {
diff --git a/spec/frontend/serverless/store/mutations_spec.js b/spec/frontend/serverless/store/mutations_spec.js
index e2771c7e5fd..a1a8f9a2ca7 100644
--- a/spec/frontend/serverless/store/mutations_spec.js
+++ b/spec/frontend/serverless/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/serverless/store/mutations';
import * as types from '~/serverless/store/mutation_types';
+import mutations from '~/serverless/store/mutations';
import { mockServerlessFunctions, mockMetrics } from '../mock_data';
describe('ServerlessMutations', () => {
diff --git a/spec/frontend/serverless/survey_banner_spec.js b/spec/frontend/serverless/survey_banner_spec.js
index 29b36fb9b5f..4682c2328c3 100644
--- a/spec/frontend/serverless/survey_banner_spec.js
+++ b/spec/frontend/serverless/survey_banner_spec.js
@@ -1,6 +1,6 @@
+import { GlBanner } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
-import { GlBanner } from '@gitlab/ui';
import SurveyBanner from '~/serverless/survey_banner.vue';
describe('Knative survey banner', () => {
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 f3085fb7ffb..21b9721438d 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal, GlFormCheckbox } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { initEmojiMock } from 'helpers/emoji';
import * as UserApi from '~/api/user_api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
diff --git a/spec/frontend/set_status_modal/user_availability_status_spec.js b/spec/frontend/set_status_modal/user_availability_status_spec.js
deleted file mode 100644
index 95ca0251ce0..00000000000
--- a/spec/frontend/set_status_modal/user_availability_status_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
-import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
-
-describe('UserAvailabilityStatus', () => {
- let wrapper;
-
- const createComponent = (props = {}) => {
- return shallowMount(UserAvailabilityStatus, {
- propsData: {
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('with availability status', () => {
- it(`set to ${AVAILABILITY_STATUS.BUSY}`, () => {
- wrapper = createComponent({ availability: AVAILABILITY_STATUS.BUSY });
- expect(wrapper.text()).toContain('(Busy)');
- });
-
- it(`set to ${AVAILABILITY_STATUS.NOT_SET}`, () => {
- wrapper = createComponent({ availability: AVAILABILITY_STATUS.NOT_SET });
- expect(wrapper.html()).toBe('');
- });
- });
-});
diff --git a/spec/frontend/set_status_modal/utils_spec.js b/spec/frontend/set_status_modal/utils_spec.js
new file mode 100644
index 00000000000..273f30f8311
--- /dev/null
+++ b/spec/frontend/set_status_modal/utils_spec.js
@@ -0,0 +1,15 @@
+import { AVAILABILITY_STATUS, isUserBusy } from '~/set_status_modal/utils';
+
+describe('Set status modal utils', () => {
+ describe('isUserBusy', () => {
+ it.each`
+ value | result
+ ${''} | ${false}
+ ${'fake status'} | ${false}
+ ${AVAILABILITY_STATUS.NOT_SET} | ${false}
+ ${AVAILABILITY_STATUS.BUSY} | ${true}
+ `('with $value returns $result', ({ value, result }) => {
+ expect(isUserBusy(value)).toBe(result);
+ });
+ });
+});
diff --git a/spec/frontend/settings_panels_spec.js b/spec/frontend/settings_panels_spec.js
index 2c5d91a45bc..8666106d3c6 100644
--- a/spec/frontend/settings_panels_spec.js
+++ b/spec/frontend/settings_panels_spec.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import initSettingsPanels from '~/settings_panels';
+import initSettingsPanels, { isExpanded } from '~/settings_panels';
describe('Settings Panels', () => {
preloadFixtures('groups/edit.html');
@@ -20,11 +20,11 @@ describe('Settings Panels', () => {
// Our test environment automatically expands everything so we need to clear that out first
panel.classList.remove('expanded');
- expect(panel.classList.contains('expanded')).toBe(false);
+ expect(isExpanded(panel)).toBe(false);
initSettingsPanels();
- expect(panel.classList.contains('expanded')).toBe(true);
+ expect(isExpanded(panel)).toBe(true);
});
});
@@ -35,11 +35,11 @@ describe('Settings Panels', () => {
initSettingsPanels();
- expect(panel.classList.contains('expanded')).toBe(true);
+ expect(isExpanded(panel)).toBe(true);
$(trigger).click();
- expect(panel.classList.contains('expanded')).toBe(false);
+ expect(isExpanded(panel)).toBe(false);
expect(trigger.textContent).toEqual(originalText);
});
});
diff --git a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
index e295c587d70..846f45345e7 100644
--- a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
+++ b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
@@ -3,7 +3,7 @@
exports[`SidebarTodo template renders component container element with proper data attributes 1`] = `
<button
aria-label="Mark as done"
- class="btn btn-default btn-todo issuable-header-btn float-right"
+ class="gl-button btn btn-default btn-todo issuable-header-btn float-right"
data-issuable-id="1"
data-issuable-type="epic"
type="button"
diff --git a/spec/frontend/sidebar/assignee_title_spec.js b/spec/frontend/sidebar/assignee_title_spec.js
index 9f5d51c7795..3079cb28406 100644
--- a/spec/frontend/sidebar/assignee_title_spec.js
+++ b/spec/frontend/sidebar/assignee_title_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import Component from '~/sidebar/components/assignees/assignee_title.vue';
diff --git a/spec/frontend/sidebar/assignees_realtime_spec.js b/spec/frontend/sidebar/assignees_realtime_spec.js
index 1c62c52dc67..0fab6a29f71 100644
--- a/spec/frontend/sidebar/assignees_realtime_spec.js
+++ b/spec/frontend/sidebar/assignees_realtime_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import ActionCable from '@rails/actioncable';
+import { shallowMount } from '@vue/test-utils';
+import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql';
import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import Mock from './mock_data';
-import query from '~/issuable_sidebar/queries/issue_sidebar.query.graphql';
jest.mock('@rails/actioncable', () => {
const mockConsumer = {
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index 23e82171fe9..74dce499999 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -1,6 +1,6 @@
+import { GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import { GlIcon } from '@gitlab/ui';
import UsersMockHelper from 'helpers/user_mock_data_helper';
import Assignee from '~/sidebar/components/assignees/assignees.vue';
import UsersMock from './mock_data';
diff --git a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
index 03d1ac3ab8d..5a3a152d201 100644
--- a/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
+++ b/spec/frontend/sidebar/components/assignees/assignee_avatar_link_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue';
import AssigneeAvatar from '~/sidebar/components/assignees/assignee_avatar.vue';
+import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue';
import userDataMock from '../../user_data_mock';
const TOOLTIP_PLACEMENT = 'bottom';
@@ -79,4 +79,34 @@ describe('AssigneeAvatarLink component', () => {
});
},
);
+
+ describe.each`
+ tooltipHasName | availability | canMerge | expected
+ ${true} | ${'Busy'} | ${false} | ${'Root (Busy) (cannot merge)'}
+ ${true} | ${'Busy'} | ${true} | ${'Root (Busy)'}
+ ${true} | ${''} | ${false} | ${'Root (cannot merge)'}
+ ${true} | ${''} | ${true} | ${'Root'}
+ ${false} | ${'Busy'} | ${false} | ${'Cannot merge'}
+ ${false} | ${'Busy'} | ${true} | ${''}
+ ${false} | ${''} | ${false} | ${'Cannot merge'}
+ ${false} | ${''} | ${true} | ${''}
+ `(
+ "with tooltipHasName=$tooltipHasName and availability='$availability' and canMerge=$canMerge",
+ ({ tooltipHasName, availability, canMerge, expected }) => {
+ beforeEach(() => {
+ createComponent({
+ tooltipHasName,
+ user: {
+ ...userDataMock(),
+ can_merge: canMerge,
+ availability,
+ },
+ });
+ });
+
+ it('sets tooltip to $expected', () => {
+ expect(findTooltipText()).toBe(expected);
+ });
+ },
+ );
});
diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
index 8e158c99971..5aa8264b98c 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UsersMockHelper from 'helpers/user_mock_data_helper';
-import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue';
import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue';
+import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue';
const DEFAULT_MAX_COUNTER = 99;
@@ -187,4 +187,26 @@ describe('CollapsedAssigneeList component', () => {
expect(findAvatarCounter().text()).toEqual(`${DEFAULT_MAX_COUNTER}+`);
});
});
+
+ const [busyUser] = UsersMockHelper.createNumberRandomUsers(1);
+ const [canMergeUser] = UsersMockHelper.createNumberRandomUsers(1);
+ busyUser.availability = 'busy';
+ canMergeUser.can_merge = true;
+
+ describe.each`
+ users | busy | canMerge | expected
+ ${[busyUser, canMergeUser]} | ${1} | ${1} | ${`${busyUser.name} (Busy), ${canMergeUser.name} (1/2 can merge)`}
+ ${[busyUser]} | ${1} | ${0} | ${`${busyUser.name} (Busy) (cannot merge)`}
+ ${[canMergeUser]} | ${0} | ${1} | ${`${canMergeUser.name}`}
+ ${[]} | ${0} | ${0} | ${'Assignee(s)'}
+ `(
+ 'with $users.length users, $busy is busy and $canMerge that can merge',
+ ({ users, expected }) => {
+ it('generates the tooltip text', () => {
+ createComponent({ users });
+
+ expect(getTooltipTitle()).toEqual(expected);
+ });
+ },
+ );
});
diff --git a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
index ee1f8ed8d2b..b49e6255923 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue';
import AssigneeAvatar from '~/sidebar/components/assignees/assignee_avatar.vue';
+import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue';
+import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
import userDataMock from '../../user_data_mock';
const TEST_USER = userDataMock();
@@ -18,6 +19,9 @@ describe('CollapsedAssignee assignee component', () => {
wrapper = shallowMount(CollapsedAssignee, {
propsData,
+ stubs: {
+ UserNameWithStatus,
+ },
});
}
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
new file mode 100644
index 00000000000..4ee12838491
--- /dev/null
+++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
@@ -0,0 +1,120 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
+
+describe('boards sidebar remove issue', () => {
+ let wrapper;
+
+ const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findEditButton = () => wrapper.find('[data-testid="edit-button"]');
+ const findTitle = () => wrapper.find('[data-testid="title"]');
+ const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
+ const findExpanded = () => wrapper.find('[data-testid="expanded-content"]');
+
+ const createComponent = ({ props = {}, slots = {}, canUpdate = false } = {}) => {
+ wrapper = shallowMount(SidebarEditableItem, {
+ attachTo: document.body,
+ provide: { canUpdate },
+ propsData: props,
+ slots,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('template', () => {
+ it('renders title', () => {
+ const title = 'Sidebar item title';
+ createComponent({ props: { title } });
+
+ expect(findTitle().text()).toBe(title);
+ });
+
+ it('hides edit button, loader and expanded content by default', () => {
+ createComponent();
+
+ expect(findEditButton().exists()).toBe(false);
+ expect(findLoader().exists()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(false);
+ });
+
+ it('shows "None" if empty collapsed slot', () => {
+ createComponent();
+
+ expect(findCollapsed().text()).toBe('None');
+ });
+
+ it('renders collapsed content by default', () => {
+ const slots = { collapsed: '<div>Collapsed content</div>' };
+ createComponent({ slots });
+
+ expect(findCollapsed().text()).toBe('Collapsed content');
+ });
+
+ it('shows edit button if can update', () => {
+ createComponent({ canUpdate: true });
+
+ expect(findEditButton().exists()).toBe(true);
+ });
+
+ it('shows loading icon if loading', () => {
+ createComponent({ props: { loading: true } });
+
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('shows expanded content and hides collapsed content when clicking edit button', async () => {
+ const slots = { default: '<div>Select item</div>' };
+ createComponent({ canUpdate: true, slots });
+ findEditButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick;
+
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(true);
+ });
+ });
+
+ describe('collapsing an item by offclicking', () => {
+ beforeEach(async () => {
+ createComponent({ canUpdate: true });
+ findEditButton().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('hides expanded section and displays collapsed section', async () => {
+ expect(findExpanded().isVisible()).toBe(true);
+ document.body.click();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findExpanded().isVisible()).toBe(false);
+ });
+ });
+
+ it('emits open when edit button is clicked and edit is initailized to false', async () => {
+ createComponent({ canUpdate: true });
+
+ findEditButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted().open.length).toBe(1);
+ });
+
+ it('does not emits events when collapsing with false `emitEvent`', async () => {
+ createComponent({ canUpdate: true });
+
+ findEditButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.vm.collapse({ emitEvent: false });
+
+ expect(wrapper.emitted().close).toBeUndefined();
+ });
+});
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 da69f56d442..7e81df1d7d2 100644
--- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js
@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import UsersMockHelper from 'helpers/user_mock_data_helper';
-import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue';
import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue';
+import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue';
import userDataMock from '../../user_data_mock';
const DEFAULT_RENDER_COUNT = 5;
diff --git a/spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js b/spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js
new file mode 100644
index 00000000000..9483c6624c5
--- /dev/null
+++ b/spec/frontend/sidebar/components/assignees/user_name_with_status_spec.js
@@ -0,0 +1,51 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
+import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
+
+const name = 'Goku';
+const containerClasses = 'gl-cool-class gl-over-9000';
+
+describe('UserNameWithStatus', () => {
+ let wrapper;
+
+ function createComponent(props = {}) {
+ return shallowMount(UserNameWithStatus, {
+ propsData: { name, containerClasses, ...props },
+ stubs: {
+ GlSprintf,
+ },
+ });
+ }
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('will render the users name', () => {
+ expect(wrapper.html()).toContain(name);
+ });
+
+ it('will not render "Busy"', () => {
+ expect(wrapper.html()).not.toContain('Busy');
+ });
+
+ it('will render all relevant containerClasses', () => {
+ const classes = wrapper.find('span').classes().join(' ');
+ expect(classes).toBe(containerClasses);
+ });
+
+ describe(`with availability="${AVAILABILITY_STATUS.BUSY}"`, () => {
+ beforeEach(() => {
+ wrapper = createComponent({ availability: AVAILABILITY_STATUS.BUSY });
+ });
+
+ it('will render "Busy"', () => {
+ expect(wrapper.html()).toContain('Goku (Busy)');
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
index b9132fa4450..704847f65bf 100644
--- a/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
+++ b/spec/frontend/sidebar/components/copy_email_to_clipboard_spec.js
@@ -1,7 +1,7 @@
-import { mount } from '@vue/test-utils';
import { getByText } from '@testing-library/dom';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { mount } from '@vue/test-utils';
import CopyEmailToClipboard from '~/sidebar/components/copy_email_to_clipboard.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
describe('CopyEmailToClipboard component', () => {
const sampleEmail = 'sample+email@test.com';
diff --git a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
new file mode 100644
index 00000000000..7c67149b517
--- /dev/null
+++ b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
@@ -0,0 +1,91 @@
+import { shallowMount } from '@vue/test-utils';
+import { TEST_HOST } from 'helpers/test_constants';
+import ReviewerAvatarLink from '~/sidebar/components/reviewers/reviewer_avatar_link.vue';
+import UncollapsedReviewerList from '~/sidebar/components/reviewers/uncollapsed_reviewer_list.vue';
+import userDataMock from '../../user_data_mock';
+
+describe('UncollapsedReviewerList component', () => {
+ let wrapper;
+
+ function createComponent(props = {}) {
+ const propsData = {
+ users: [],
+ rootPath: TEST_HOST,
+ ...props,
+ };
+
+ wrapper = shallowMount(UncollapsedReviewerList, {
+ propsData,
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('single reviewer', () => {
+ beforeEach(() => {
+ const user = userDataMock();
+
+ createComponent({
+ users: [user],
+ });
+ });
+
+ it('only has one user', () => {
+ expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(1);
+ });
+
+ it('shows one user with avatar, username and author name', () => {
+ expect(wrapper.text()).toContain(`@root`);
+ });
+
+ it('renders re-request loading icon', async () => {
+ await wrapper.setData({ loadingStates: { 1: 'loading' } });
+
+ expect(wrapper.find('[data-testid="re-request-button"]').props('loading')).toBe(true);
+ });
+
+ it('renders re-request success icon', async () => {
+ await wrapper.setData({ loadingStates: { 1: 'success' } });
+
+ expect(wrapper.find('[data-testid="re-request-success"]').exists()).toBe(true);
+ });
+ });
+
+ describe('multiple reviewers', () => {
+ beforeEach(() => {
+ const user = userDataMock();
+
+ createComponent({
+ users: [user, { ...user, id: 2, username: 'hello-world' }],
+ });
+ });
+
+ it('only has one user', () => {
+ expect(wrapper.findAll(ReviewerAvatarLink).length).toBe(2);
+ });
+
+ it('shows one user with avatar, username and author name', () => {
+ expect(wrapper.text()).toContain(`@root`);
+ expect(wrapper.text()).toContain(`@hello-world`);
+ });
+
+ it('renders re-request loading icon', async () => {
+ await wrapper.setData({ loadingStates: { 2: 'loading' } });
+
+ expect(wrapper.findAll('[data-testid="re-request-button"]').length).toBe(2);
+ expect(wrapper.findAll('[data-testid="re-request-button"]').at(1).props('loading')).toBe(
+ true,
+ );
+ });
+
+ it('renders re-request success icon', async () => {
+ await wrapper.setData({ loadingStates: { 2: 'success' } });
+
+ expect(wrapper.findAll('[data-testid="re-request-button"]').length).toBe(1);
+ expect(wrapper.findAll('[data-testid="re-request-success"]').length).toBe(1);
+ expect(wrapper.find('[data-testid="re-request-success"]').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/severity/severity_spec.js b/spec/frontend/sidebar/components/severity/severity_spec.js
index ba7cea0919c..1e4624e4dcd 100644
--- a/spec/frontend/sidebar/components/severity/severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/severity_spec.js
@@ -1,7 +1,7 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
-import SeverityToken from '~/sidebar/components/severity/severity.vue';
+import { shallowMount } from '@vue/test-utils';
import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
describe('SeverityToken', () => {
let wrapper;
diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
index fa40d75d4e9..747d370e1cf 100644
--- a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
-import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue';
-import SeverityToken from '~/sidebar/components/severity/severity.vue';
-import updateIssuableSeverity from '~/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql';
import { INCIDENT_SEVERITY, ISSUABLE_TYPES } from '~/sidebar/components/severity/constants';
+import updateIssuableSeverity from '~/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
+import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue';
jest.mock('~/flash');
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 0b6a2e6ceb9..4d03aedf1be 100644
--- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js
@@ -1,6 +1,6 @@
-import { createMockDirective } from 'helpers/vue_mock_directive';
import { mount } from '@vue/test-utils';
import { stubTransition } from 'helpers/stub_transition';
+import { createMockDirective } from 'helpers/vue_mock_directive';
import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue';
describe('Issuable Time Tracker', () => {
diff --git a/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js b/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js
index 8c868205295..427e3a89c29 100644
--- a/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/confidential/edit_form_buttons_spec.js
@@ -1,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
+import { deprecatedCreateFlash as flash } from '~/flash';
+import createStore from '~/notes/stores';
import EditFormButtons from '~/sidebar/components/confidential/edit_form_buttons.vue';
import eventHub from '~/sidebar/event_hub';
-import createStore from '~/notes/stores';
-import { deprecatedCreateFlash as flash } from '~/flash';
jest.mock('~/sidebar/event_hub', () => ({ $emit: jest.fn() }));
jest.mock('~/flash');
diff --git a/spec/frontend/sidebar/confidential_issue_sidebar_spec.js b/spec/frontend/sidebar/confidential_issue_sidebar_spec.js
index bc2df9305d0..93a6401b1fc 100644
--- a/spec/frontend/sidebar/confidential_issue_sidebar_spec.js
+++ b/spec/frontend/sidebar/confidential_issue_sidebar_spec.js
@@ -1,10 +1,10 @@
import { shallowMount } from '@vue/test-utils';
-import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
-import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
-import EditForm from '~/sidebar/components/confidential/edit_form.vue';
+import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import createStore from '~/notes/stores';
import * as types from '~/notes/stores/mutation_types';
+import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
+import EditForm from '~/sidebar/components/confidential/edit_form.vue';
jest.mock('~/flash');
jest.mock('~/sidebar/services/sidebar_service');
diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
index a14ca711204..49283ea99cf 100644
--- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js
@@ -1,9 +1,9 @@
import { mount } from '@vue/test-utils';
-import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue';
-import eventHub from '~/sidebar/event_hub';
import { deprecatedCreateFlash as flash } from '~/flash';
-import createStore from '~/notes/stores';
import { createStore as createMrStore } from '~/mr_notes/stores';
+import createStore from '~/notes/stores';
+import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue';
+import eventHub from '~/sidebar/event_hub';
import { ISSUABLE_TYPE_ISSUE, ISSUABLE_TYPE_MR } from './constants';
jest.mock('~/sidebar/event_hub', () => ({ $emit: jest.fn() }));
diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
index 92cdba4f1f2..1743e114bb0 100644
--- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
+++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js
@@ -1,10 +1,10 @@
import { shallowMount } from '@vue/test-utils';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import IssuableLockForm from '~/sidebar/components/lock/issuable_lock_form.vue';
-import EditForm from '~/sidebar/components/lock/edit_form.vue';
-import createStore from '~/notes/stores';
import { createStore as createMrStore } from '~/mr_notes/stores';
+import createStore from '~/notes/stores';
+import EditForm from '~/sidebar/components/lock/edit_form.vue';
+import IssuableLockForm from '~/sidebar/components/lock/issuable_lock_form.vue';
import { ISSUABLE_TYPE_ISSUE, ISSUABLE_TYPE_MR } from './constants';
describe('IssuableLockForm', () => {
diff --git a/spec/frontend/sidebar/reviewer_title_spec.js b/spec/frontend/sidebar/reviewer_title_spec.js
index cbd36040579..3c250be5d5e 100644
--- a/spec/frontend/sidebar/reviewer_title_spec.js
+++ b/spec/frontend/sidebar/reviewer_title_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import Component from '~/sidebar/components/reviewers/reviewer_title.vue';
diff --git a/spec/frontend/sidebar/reviewers_spec.js b/spec/frontend/sidebar/reviewers_spec.js
index 91f28e85f3b..fc24b51287f 100644
--- a/spec/frontend/sidebar/reviewers_spec.js
+++ b/spec/frontend/sidebar/reviewers_spec.js
@@ -1,6 +1,6 @@
+import { GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import { GlIcon } from '@gitlab/ui';
import UsersMockHelper from 'helpers/user_mock_data_helper';
import Reviewer from '~/sidebar/components/reviewers/reviewers.vue';
import UsersMock from './mock_data';
@@ -114,8 +114,7 @@ describe('Reviewer component', () => {
editable: true,
});
- expect(wrapper.findAll('.user-item').length).toBe(users.length);
- expect(wrapper.find('.user-list-more').exists()).toBe(false);
+ expect(wrapper.findAll('[data-testid="reviewer"]').length).toBe(users.length);
});
it('shows sorted reviewer where "can merge" users are sorted first', () => {
@@ -144,10 +143,10 @@ describe('Reviewer component', () => {
users,
});
- const userItems = wrapper.findAll('.user-list .user-item a');
+ const userItems = wrapper.findAll('[data-testid="reviewer"]');
expect(userItems.length).toBe(3);
- expect(userItems.at(0).attributes('title')).toBe(users[2].name);
+ expect(userItems.at(0).find('a').attributes('title')).toBe(users[2].name);
});
it('passes the sorted reviewers to the collapsed-reviewer-list', () => {
diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js
index f1c13a5f818..e737b57e33d 100644
--- a/spec/frontend/sidebar/sidebar_assignees_spec.js
+++ b/spec/frontend/sidebar/sidebar_assignees_spec.js
@@ -1,11 +1,11 @@
import { shallowMount } from '@vue/test-utils';
-import AxiosMockAdapter from 'axios-mock-adapter';
import axios from 'axios';
-import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue';
+import AxiosMockAdapter from 'axios-mock-adapter';
import Assigness from '~/sidebar/components/assignees/assignees.vue';
import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
+import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue';
import SidebarService from '~/sidebar/services/sidebar_service';
+import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data';
diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js
index 24bb5a8e916..6a7758ace40 100644
--- a/spec/frontend/sidebar/sidebar_move_issue_spec.js
+++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js
@@ -1,10 +1,10 @@
-import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
+import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
+import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
-import SidebarService from '~/sidebar/services/sidebar_service';
-import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
import Mock from './mock_data';
describe('SidebarMoveIssue', () => {
diff --git a/spec/frontend/sidebar/sidebar_subscriptions_spec.js b/spec/frontend/sidebar/sidebar_subscriptions_spec.js
index 18aaeabe3dd..d900fde7e70 100644
--- a/spec/frontend/sidebar/sidebar_subscriptions_spec.js
+++ b/spec/frontend/sidebar/sidebar_subscriptions_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import SidebarSubscriptions from '~/sidebar/components/subscriptions/sidebar_subscriptions.vue';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarService from '~/sidebar/services/sidebar_service';
+import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data';
diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js
index 043ffd972da..e7ae59e26cf 100644
--- a/spec/frontend/sidebar/subscriptions_spec.js
+++ b/spec/frontend/sidebar/subscriptions_spec.js
@@ -1,17 +1,20 @@
+import { GlToggle } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
import eventHub from '~/sidebar/event_hub';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
describe('Subscriptions', () => {
let wrapper;
- const findToggleButton = () => wrapper.find(ToggleButton);
+ const findToggleButton = () => wrapper.findComponent(GlToggle);
const mountComponent = (propsData) =>
- shallowMount(Subscriptions, {
- propsData,
- });
+ extendedWrapper(
+ shallowMount(Subscriptions, {
+ propsData,
+ }),
+ );
afterEach(() => {
wrapper.destroy();
@@ -24,7 +27,7 @@ describe('Subscriptions', () => {
subscribed: undefined,
});
- expect(findToggleButton().attributes('isloading')).toBe('true');
+ expect(findToggleButton().props('isLoading')).toBe(true);
});
it('is toggled "off" when currently not subscribed', () => {
@@ -32,7 +35,7 @@ describe('Subscriptions', () => {
subscribed: false,
});
- expect(findToggleButton().attributes('value')).toBeFalsy();
+ expect(findToggleButton().props('value')).toBe(false);
});
it('is toggled "on" when currently subscribed', () => {
@@ -40,7 +43,7 @@ describe('Subscriptions', () => {
subscribed: true,
});
- expect(findToggleButton().attributes('value')).toBe('true');
+ expect(findToggleButton().props('value')).toBe(true);
});
it('toggleSubscription method emits `toggleSubscription` event on eventHub and Component', () => {
@@ -93,14 +96,16 @@ describe('Subscriptions', () => {
});
it('sets the correct display text', () => {
- expect(wrapper.find('.issuable-header-text').text()).toContain(subscribeDisabledDescription);
+ expect(wrapper.findByTestId('subscription-title').text()).toContain(
+ subscribeDisabledDescription,
+ );
expect(wrapper.find({ ref: 'tooltip' }).attributes('title')).toBe(
subscribeDisabledDescription,
);
});
it('does not render the toggle button', () => {
- expect(wrapper.find('.js-issuable-subscribe-button').exists()).toBe(false);
+ expect(findToggleButton().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js
index 4adfaf7ad7b..ff6da3abad0 100644
--- a/spec/frontend/sidebar/todo_spec.js
+++ b/spec/frontend/sidebar/todo_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue';
@@ -26,7 +26,7 @@ describe('SidebarTodo', () => {
it.each`
state | classes
- ${false} | ${['btn', 'btn-default', 'btn-todo', 'issuable-header-btn', 'float-right']}
+ ${false} | ${['gl-button', 'btn', 'btn-default', 'btn-todo', 'issuable-header-btn', 'float-right']}
${true} | ${['btn-blank', 'btn-todo', 'sidebar-collapsed-icon', 'dont-change-state']}
`('returns todo button classes for when `collapsed` prop is `$state`', ({ state, classes }) => {
createComponent({ collapsed: state });
@@ -35,7 +35,7 @@ describe('SidebarTodo', () => {
it.each`
isTodo | iconClass | label | icon
- ${false} | ${''} | ${'Add a To-Do'} | ${'todo-add'}
+ ${false} | ${''} | ${'Add a to do'} | ${'todo-add'}
${true} | ${'todo-undone'} | ${'Mark as done'} | ${'todo-done'}
`(
'renders proper button when `isTodo` prop is `$isTodo`',
diff --git a/spec/frontend/sidebar/user_data_mock.js b/spec/frontend/sidebar/user_data_mock.js
index df90a65f6f9..41d0331f34a 100644
--- a/spec/frontend/sidebar/user_data_mock.js
+++ b/spec/frontend/sidebar/user_data_mock.js
@@ -8,4 +8,6 @@ export default () => ({
username: 'root',
web_url: `${TEST_HOST}/root`,
can_merge: true,
+ can_update_merge_request: true,
+ reviewed: true,
});
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index b818f98efb1..2b6d3ca8c2a 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -1,138 +1,120 @@
-import VueApollo, { ApolloMutation } from 'vue-apollo';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
+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';
+import { stubComponent } from 'helpers/stub_component';
+import waitForPromises from 'helpers/wait_for_promises';
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
+import CaptchaModal from '~/captcha/captcha_modal.vue';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as urlUtils from '~/lib/utils/url_utility';
import SnippetEditApp from '~/snippets/components/edit.vue';
+import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue';
import SnippetDescriptionEdit from '~/snippets/components/snippet_description_edit.vue';
import SnippetVisibilityEdit from '~/snippets/components/snippet_visibility_edit.vue';
-import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue';
-import TitleField from '~/vue_shared/components/form/title.vue';
-import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
import {
SNIPPET_VISIBILITY_PRIVATE,
SNIPPET_VISIBILITY_INTERNAL,
SNIPPET_VISIBILITY_PUBLIC,
} from '~/snippets/constants';
-import UpdateSnippetMutation from '~/snippets/mutations/updateSnippet.mutation.graphql';
import CreateSnippetMutation from '~/snippets/mutations/createSnippet.mutation.graphql';
-import { testEntries } from '../test_utils';
+import UpdateSnippetMutation from '~/snippets/mutations/updateSnippet.mutation.graphql';
+import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import TitleField from '~/vue_shared/components/form/title.vue';
+import { testEntries, createGQLSnippetsQueryResponse, createGQLSnippet } from '../test_utils';
jest.mock('~/flash');
const TEST_UPLOADED_FILES = ['foo/bar.txt', 'alpha/beta.js'];
-const TEST_API_ERROR = 'Ufff';
-const TEST_MUTATION_ERROR = 'Bummer';
-
+const TEST_API_ERROR = new Error('TEST_API_ERROR');
+const TEST_MUTATION_ERROR = 'Test mutation error';
+const TEST_CAPTCHA_RESPONSE = 'i-got-a-captcha';
+const TEST_CAPTCHA_SITE_KEY = 'abc123';
const TEST_ACTIONS = {
- NO_CONTENT: {
- ...testEntries.created.diff,
- content: '',
- },
- NO_PATH: {
- ...testEntries.created.diff,
- filePath: '',
- },
- VALID: {
- ...testEntries.created.diff,
- },
+ NO_CONTENT: merge({}, testEntries.created.diff, { content: '' }),
+ NO_PATH: merge({}, testEntries.created.diff, { filePath: '' }),
+ VALID: merge({}, testEntries.created.diff),
};
-
const TEST_WEB_URL = '/snippets/7';
+const TEST_SNIPPET_GID = 'gid://gitlab/PersonalSnippet/42';
+
+const createSnippet = () =>
+ merge(createGQLSnippet(), {
+ webUrl: TEST_WEB_URL,
+ visibilityLevel: SNIPPET_VISIBILITY_PRIVATE,
+ });
+
+const createQueryResponse = (obj = {}) =>
+ createGQLSnippetsQueryResponse([merge(createSnippet(), obj)]);
+
+const createMutationResponse = (key, obj = {}) => ({
+ data: {
+ [key]: merge(
+ {
+ errors: [],
+ snippet: {
+ __typename: 'Snippet',
+ webUrl: TEST_WEB_URL,
+ },
+ spamLogId: null,
+ needsCaptchaResponse: false,
+ captchaSiteKey: null,
+ },
+ obj,
+ ),
+ },
+});
+
+const createMutationResponseWithErrors = (key) =>
+ createMutationResponse(key, { errors: [TEST_MUTATION_ERROR] });
+
+const createMutationResponseWithRecaptcha = (key) =>
+ createMutationResponse(key, {
+ errors: ['ignored captcha error message'],
+ needsCaptchaResponse: true,
+ captchaSiteKey: TEST_CAPTCHA_SITE_KEY,
+ });
-const createTestSnippet = () => ({
- webUrl: TEST_WEB_URL,
- id: 7,
- title: 'Snippet Title',
- description: 'Lorem ipsum snippet desc',
- visibilityLevel: SNIPPET_VISIBILITY_PRIVATE,
+const getApiData = ({
+ id,
+ title = '',
+ description = '',
+ visibilityLevel = SNIPPET_VISIBILITY_PRIVATE,
+} = {}) => ({
+ id,
+ title,
+ description,
+ visibilityLevel,
+ blobActions: [],
});
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
describe('Snippet Edit app', () => {
+ useFakeDate();
+
let wrapper;
- let fakeApollo;
+ let getSpy;
+
+ // Mutate spy receives a "key" so that we can:
+ // - Use the same spy whether we are creating or updating.
+ // - Build the correct response object
+ // - Assert which mutation was sent
+ let mutateSpy;
+
const relativeUrlRoot = '/foo/';
const originalRelativeUrlRoot = gon.relative_url_root;
- const GetSnippetQuerySpy = jest.fn().mockResolvedValue({
- data: { snippets: { nodes: [createTestSnippet()] } },
- });
- const mutationTypes = {
- RESOLVE: jest.fn().mockResolvedValue({
- data: {
- updateSnippet: {
- errors: [],
- snippet: createTestSnippet(),
- },
- },
- }),
- RESOLVE_WITH_ERRORS: jest.fn().mockResolvedValue({
- data: {
- updateSnippet: {
- errors: [TEST_MUTATION_ERROR],
- snippet: createTestSnippet(),
- },
- createSnippet: {
- errors: [TEST_MUTATION_ERROR],
- snippet: null,
- },
- },
- }),
- REJECT: jest.fn().mockRejectedValue(TEST_API_ERROR),
- };
-
- function createComponent({
- props = {},
- loading = false,
- mutationRes = mutationTypes.RESOLVE,
- selectedLevel = SNIPPET_VISIBILITY_PRIVATE,
- withApollo = false,
- } = {}) {
- let componentData = {
- mocks: {
- $apollo: {
- queries: {
- snippet: { loading },
- },
- mutate: mutationRes,
- },
- },
- };
-
- if (withApollo) {
- const localVue = createLocalVue();
- localVue.use(VueApollo);
-
- const requestHandlers = [[GetSnippetQuery, GetSnippetQuerySpy]];
- fakeApollo = createMockApollo(requestHandlers);
- componentData = {
- localVue,
- apolloProvider: fakeApollo,
- };
- }
+ beforeEach(() => {
+ getSpy = jest.fn().mockResolvedValue(createQueryResponse());
- wrapper = shallowMount(SnippetEditApp, {
- ...componentData,
- stubs: {
- ApolloMutation,
- FormFooterActions,
- },
- provide: {
- selectedLevel,
- },
- propsData: {
- snippetGid: 'gid://gitlab/PersonalSnippet/42',
- markdownPreviewPath: 'http://preview.foo.bar',
- markdownDocsPath: 'http://docs.foo.bar',
- ...props,
- },
- });
- }
+ // See `mutateSpy` declaration comment for why we send a key
+ mutateSpy = jest.fn().mockImplementation((key) => Promise.resolve(createMutationResponse(key)));
- beforeEach(() => {
gon.relative_url_root = relativeUrlRoot;
jest.spyOn(urlUtils, 'redirectTo').mockImplementation();
});
@@ -144,10 +126,10 @@ describe('Snippet Edit app', () => {
});
const findBlobActions = () => wrapper.find(SnippetBlobActionsEdit);
+ const findCaptchaModal = () => wrapper.find(CaptchaModal);
const findSubmitButton = () => wrapper.find('[data-testid="snippet-submit-btn"]');
const findCancelButton = () => wrapper.find('[data-testid="snippet-cancel-btn"]');
const hasDisabledSubmit = () => Boolean(findSubmitButton().attributes('disabled'));
-
const clickSubmitBtn = () => wrapper.find('[data-testid="snippet-edit-form"]').trigger('submit');
const triggerBlobActions = (actions) => findBlobActions().vm.$emit('actions', actions);
const setUploadFilesHtml = (paths) => {
@@ -155,53 +137,92 @@ describe('Snippet Edit app', () => {
.map((path) => `<input name="files[]" value="${path}">`)
.join('');
};
- const getApiData = ({
- id,
- title = '',
- description = '',
- visibilityLevel = SNIPPET_VISIBILITY_PRIVATE,
- } = {}) => ({
- id,
- title,
- description,
- visibilityLevel,
- blobActions: [],
- });
+ const setTitle = (val) => wrapper.find(TitleField).vm.$emit('input', val);
+ const setDescription = (val) => wrapper.find(SnippetDescriptionEdit).vm.$emit('input', val);
- // Ideally we wouldn't call this method directly, but we don't have a way to trigger
- // apollo responses yet.
- const loadSnippet = (...nodes) => {
- if (nodes.length) {
- wrapper.setData({
- snippet: nodes[0],
- newSnippet: false,
- });
- } else {
- wrapper.setData({
- newSnippet: true,
- });
+ const createComponent = ({ props = {}, selectedLevel = SNIPPET_VISIBILITY_PRIVATE } = {}) => {
+ if (wrapper) {
+ throw new Error('wrapper already created');
}
+
+ const requestHandlers = [
+ [GetSnippetQuery, getSpy],
+ // See `mutateSpy` declaration comment for why we send a key
+ [UpdateSnippetMutation, (...args) => mutateSpy('updateSnippet', ...args)],
+ [CreateSnippetMutation, (...args) => mutateSpy('createSnippet', ...args)],
+ ];
+ const apolloProvider = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(SnippetEditApp, {
+ apolloProvider,
+ localVue,
+ stubs: {
+ ApolloMutation,
+ FormFooterActions,
+ CaptchaModal: stubComponent(CaptchaModal),
+ },
+ provide: {
+ selectedLevel,
+ },
+ propsData: {
+ snippetGid: TEST_SNIPPET_GID,
+ markdownPreviewPath: 'http://preview.foo.bar',
+ markdownDocsPath: 'http://docs.foo.bar',
+ ...props,
+ },
+ });
};
- describe('rendering', () => {
- it('renders loader while the query is in flight', () => {
- createComponent({ loading: true });
+ // Creates comopnent and waits for gql load
+ const createComponentAndLoad = async (...args) => {
+ createComponent(...args);
+
+ await waitForPromises();
+ };
+
+ // Creates loaded component and submits form
+ const createComponentAndSubmit = async (...args) => {
+ await createComponentAndLoad(...args);
+
+ clickSubmitBtn();
+
+ await waitForPromises();
+ };
+
+ describe('when loading', () => {
+ it('renders loader', () => {
+ createComponent();
+
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
+ });
- it.each([[{}], [{ snippetGid: '' }]])(
- 'should render all required components with %s',
- (props) => {
- createComponent(props);
+ describe.each`
+ snippetGid | expectedQueries
+ ${TEST_SNIPPET_GID} | ${[[{ ids: [TEST_SNIPPET_GID] }]]}
+ ${''} | ${[]}
+ `('when loaded with snippetGid=$snippetGid', ({ snippetGid, expectedQueries }) => {
+ beforeEach(() => createComponentAndLoad({ props: { snippetGid } }));
- expect(wrapper.find(TitleField).exists()).toBe(true);
- expect(wrapper.find(SnippetDescriptionEdit).exists()).toBe(true);
- expect(wrapper.find(SnippetVisibilityEdit).exists()).toBe(true);
- expect(wrapper.find(FormFooterActions).exists()).toBe(true);
- expect(findBlobActions().exists()).toBe(true);
- },
- );
+ it(`queries with ${JSON.stringify(expectedQueries)}`, () => {
+ expect(getSpy.mock.calls).toEqual(expectedQueries);
+ });
+ it('should render components', () => {
+ expect(wrapper.find(CaptchaModal).exists()).toBe(true);
+ expect(wrapper.find(TitleField).exists()).toBe(true);
+ expect(wrapper.find(SnippetDescriptionEdit).exists()).toBe(true);
+ expect(wrapper.find(SnippetVisibilityEdit).exists()).toBe(true);
+ expect(wrapper.find(FormFooterActions).exists()).toBe(true);
+ expect(findBlobActions().exists()).toBe(true);
+ });
+
+ it('should hide loader', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ });
+ });
+
+ describe('default', () => {
it.each`
title | actions | shouldDisable
${''} | ${[]} | ${true}
@@ -211,163 +232,241 @@ describe('Snippet Edit app', () => {
${'foo'} | ${[TEST_ACTIONS.VALID, TEST_ACTIONS.NO_CONTENT]} | ${true}
${'foo'} | ${[TEST_ACTIONS.VALID, TEST_ACTIONS.NO_PATH]} | ${false}
`(
- 'should handle submit disable (title=$title, actions=$actions, shouldDisable=$shouldDisable)',
+ 'should handle submit disable (title="$title", actions="$actions", shouldDisable="$shouldDisable")',
async ({ title, actions, shouldDisable }) => {
- createComponent();
+ getSpy.mockResolvedValue(createQueryResponse({ title }));
+
+ await createComponentAndLoad();
- loadSnippet({ title });
triggerBlobActions(actions);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(hasDisabledSubmit()).toBe(shouldDisable);
},
);
it.each`
- projectPath | snippetArg | expectation
- ${''} | ${[]} | ${urlUtils.joinPaths('/', relativeUrlRoot, '-', 'snippets')}
- ${'project/path'} | ${[]} | ${urlUtils.joinPaths('/', relativeUrlRoot, 'project/path/-', 'snippets')}
- ${''} | ${[createTestSnippet()]} | ${TEST_WEB_URL}
- ${'project/path'} | ${[createTestSnippet()]} | ${TEST_WEB_URL}
+ projectPath | snippetGid | expectation
+ ${''} | ${''} | ${urlUtils.joinPaths('/', relativeUrlRoot, '-', 'snippets')}
+ ${'project/path'} | ${''} | ${urlUtils.joinPaths('/', relativeUrlRoot, 'project/path/-', 'snippets')}
+ ${''} | ${TEST_SNIPPET_GID} | ${TEST_WEB_URL}
+ ${'project/path'} | ${TEST_SNIPPET_GID} | ${TEST_WEB_URL}
`(
- 'should set cancel href when (projectPath=$projectPath, snippet=$snippetArg)',
- async ({ projectPath, snippetArg, expectation }) => {
- createComponent({
- props: { projectPath },
+ 'should set cancel href (projectPath="$projectPath", snippetGid="$snippetGid")',
+ async ({ projectPath, snippetGid, expectation }) => {
+ await createComponentAndLoad({
+ props: {
+ projectPath,
+ snippetGid,
+ },
});
- loadSnippet(...snippetArg);
-
- await wrapper.vm.$nextTick();
-
expect(findCancelButton().attributes('href')).toBe(expectation);
},
);
- });
-
- describe('functionality', () => {
- it('does not fetch snippet when create a new snippet', async () => {
- createComponent({ props: { snippetGid: '' }, withApollo: true });
-
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
- expect(GetSnippetQuerySpy).not.toHaveBeenCalled();
- });
+ it.each([SNIPPET_VISIBILITY_PRIVATE, SNIPPET_VISIBILITY_INTERNAL, SNIPPET_VISIBILITY_PUBLIC])(
+ 'marks %s visibility by default',
+ async (visibility) => {
+ createComponent({
+ props: { snippetGid: '' },
+ selectedLevel: visibility,
+ });
- describe('default visibility', () => {
- it.each([SNIPPET_VISIBILITY_PRIVATE, SNIPPET_VISIBILITY_INTERNAL, SNIPPET_VISIBILITY_PUBLIC])(
- 'marks %s visibility by default',
- async (visibility) => {
- createComponent({
- props: { snippetGid: '' },
- selectedLevel: visibility,
- });
- expect(wrapper.vm.snippet.visibilityLevel).toEqual(visibility);
- },
- );
- });
+ expect(wrapper.find(SnippetVisibilityEdit).props('value')).toBe(visibility);
+ },
+ );
describe('form submission handling', () => {
it.each`
- snippetArg | projectPath | uploadedFiles | input | mutation
- ${[]} | ${'project/path'} | ${[]} | ${{ ...getApiData(), projectPath: 'project/path', uploadedFiles: [] }} | ${CreateSnippetMutation}
- ${[]} | ${''} | ${[]} | ${{ ...getApiData(), projectPath: '', uploadedFiles: [] }} | ${CreateSnippetMutation}
- ${[]} | ${''} | ${TEST_UPLOADED_FILES} | ${{ ...getApiData(), projectPath: '', uploadedFiles: TEST_UPLOADED_FILES }} | ${CreateSnippetMutation}
- ${[createTestSnippet()]} | ${'project/path'} | ${[]} | ${getApiData(createTestSnippet())} | ${UpdateSnippetMutation}
- ${[createTestSnippet()]} | ${''} | ${[]} | ${getApiData(createTestSnippet())} | ${UpdateSnippetMutation}
+ snippetGid | projectPath | uploadedFiles | input | mutationType
+ ${''} | ${'project/path'} | ${[]} | ${{ ...getApiData(), projectPath: 'project/path', uploadedFiles: [] }} | ${'createSnippet'}
+ ${''} | ${''} | ${[]} | ${{ ...getApiData(), projectPath: '', uploadedFiles: [] }} | ${'createSnippet'}
+ ${''} | ${''} | ${TEST_UPLOADED_FILES} | ${{ ...getApiData(), projectPath: '', uploadedFiles: TEST_UPLOADED_FILES }} | ${'createSnippet'}
+ ${TEST_SNIPPET_GID} | ${'project/path'} | ${[]} | ${getApiData(createSnippet())} | ${'updateSnippet'}
+ ${TEST_SNIPPET_GID} | ${''} | ${[]} | ${getApiData(createSnippet())} | ${'updateSnippet'}
`(
- 'should submit mutation with (snippet=$snippetArg, projectPath=$projectPath, uploadedFiles=$uploadedFiles)',
- async ({ snippetArg, projectPath, uploadedFiles, mutation, input }) => {
- createComponent({
+ 'should submit mutation $mutationType (snippetGid=$snippetGid, projectPath=$projectPath, uploadedFiles=$uploadedFiles)',
+ async ({ snippetGid, projectPath, uploadedFiles, mutationType, input }) => {
+ await createComponentAndLoad({
props: {
+ snippetGid,
projectPath,
},
});
- loadSnippet(...snippetArg);
+
setUploadFilesHtml(uploadedFiles);
- await wrapper.vm.$nextTick();
+ await nextTick();
clickSubmitBtn();
- expect(mutationTypes.RESOLVE).toHaveBeenCalledWith({
- mutation,
- variables: {
- input,
- },
+ expect(mutateSpy).toHaveBeenCalledTimes(1);
+ expect(mutateSpy).toHaveBeenCalledWith(mutationType, {
+ input,
});
},
);
it('should redirect to snippet view on successful mutation', async () => {
- createComponent();
- loadSnippet(createTestSnippet());
-
- clickSubmitBtn();
-
- await waitForPromises();
+ await createComponentAndSubmit();
expect(urlUtils.redirectTo).toHaveBeenCalledWith(TEST_WEB_URL);
});
it.each`
- snippetArg | projectPath | mutationRes | expectMessage
- ${[]} | ${'project/path'} | ${mutationTypes.RESOLVE_WITH_ERRORS} | ${`Can't create snippet: ${TEST_MUTATION_ERROR}`}
- ${[]} | ${''} | ${mutationTypes.RESOLVE_WITH_ERRORS} | ${`Can't create snippet: ${TEST_MUTATION_ERROR}`}
- ${[]} | ${''} | ${mutationTypes.REJECT} | ${`Can't create snippet: ${TEST_API_ERROR}`}
- ${[createTestSnippet()]} | ${'project/path'} | ${mutationTypes.RESOLVE_WITH_ERRORS} | ${`Can't update snippet: ${TEST_MUTATION_ERROR}`}
- ${[createTestSnippet()]} | ${''} | ${mutationTypes.RESOLVE_WITH_ERRORS} | ${`Can't update snippet: ${TEST_MUTATION_ERROR}`}
+ snippetGid | projectPath | mutationRes | expectMessage
+ ${''} | ${'project/path'} | ${createMutationResponseWithErrors('createSnippet')} | ${`Can't create snippet: ${TEST_MUTATION_ERROR}`}
+ ${''} | ${''} | ${createMutationResponseWithErrors('createSnippet')} | ${`Can't create snippet: ${TEST_MUTATION_ERROR}`}
+ ${TEST_SNIPPET_GID} | ${'project/path'} | ${createMutationResponseWithErrors('updateSnippet')} | ${`Can't update snippet: ${TEST_MUTATION_ERROR}`}
+ ${TEST_SNIPPET_GID} | ${''} | ${createMutationResponseWithErrors('updateSnippet')} | ${`Can't update snippet: ${TEST_MUTATION_ERROR}`}
`(
- 'should flash error with (snippet=$snippetArg, projectPath=$projectPath)',
- async ({ snippetArg, projectPath, mutationRes, expectMessage }) => {
- createComponent({
+ 'should flash error with (snippet=$snippetGid, projectPath=$projectPath)',
+ async ({ snippetGid, projectPath, mutationRes, expectMessage }) => {
+ mutateSpy.mockResolvedValue(mutationRes);
+
+ await createComponentAndSubmit({
props: {
projectPath,
+ snippetGid,
},
- mutationRes,
});
- loadSnippet(...snippetArg);
-
- clickSubmitBtn();
-
- await waitForPromises();
expect(urlUtils.redirectTo).not.toHaveBeenCalled();
expect(Flash).toHaveBeenCalledWith(expectMessage);
},
);
- });
- describe('on before unload', () => {
- it.each`
- condition | expectPrevented | action
- ${'there are no actions'} | ${false} | ${() => triggerBlobActions([])}
- ${'there are actions'} | ${true} | ${() => triggerBlobActions([testEntries.updated.diff])}
- ${'the snippet is being saved'} | ${false} | ${() => clickSubmitBtn()}
- `(
- 'handles before unload prevent when $condition (expectPrevented=$expectPrevented)',
- ({ expectPrevented, action }) => {
- createComponent();
- loadSnippet();
+ describe('with apollo network error', () => {
+ beforeEach(async () => {
+ jest.spyOn(console, 'error').mockImplementation();
+ mutateSpy.mockRejectedValue(TEST_API_ERROR);
- action();
+ await createComponentAndSubmit();
+ });
- const event = new Event('beforeunload');
- const returnValueSetter = jest.spyOn(event, 'returnValue', 'set');
+ it('should not redirect', () => {
+ expect(urlUtils.redirectTo).not.toHaveBeenCalled();
+ });
- window.dispatchEvent(event);
+ it('should flash', () => {
+ // Apollo automatically wraps the resolver's error in a NetworkError
+ expect(Flash).toHaveBeenCalledWith(
+ `Can't update snippet: Network error: ${TEST_API_ERROR.message}`,
+ );
+ });
- if (expectPrevented) {
- expect(returnValueSetter).toHaveBeenCalledWith(
- 'Are you sure you want to lose unsaved changes?',
- );
- } else {
- expect(returnValueSetter).not.toHaveBeenCalled();
- }
- },
- );
+ it('should console error', () => {
+ // eslint-disable-next-line no-console
+ expect(console.error).toHaveBeenCalledTimes(1);
+ // 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}` }),
+ );
+ });
+ });
+
+ describe('when needsCaptchaResponse is true', () => {
+ let modal;
+
+ beforeEach(async () => {
+ mutateSpy
+ .mockResolvedValueOnce(createMutationResponseWithRecaptcha('updateSnippet'))
+ .mockResolvedValueOnce(createMutationResponseWithErrors('updateSnippet'));
+
+ await createComponentAndSubmit();
+
+ modal = findCaptchaModal();
+
+ mutateSpy.mockClear();
+ });
+
+ it('should display captcha modal', () => {
+ expect(urlUtils.redirectTo).not.toHaveBeenCalled();
+ expect(modal.props()).toEqual({
+ needsCaptchaResponse: true,
+ captchaSiteKey: TEST_CAPTCHA_SITE_KEY,
+ });
+ });
+
+ describe.each`
+ response | expectedCalls
+ ${null} | ${[]}
+ ${TEST_CAPTCHA_RESPONSE} | ${[['updateSnippet', { input: { ...getApiData(createSnippet()), captchaResponse: TEST_CAPTCHA_RESPONSE } }]]}
+ `('when captcha response is $response', ({ response, expectedCalls }) => {
+ beforeEach(async () => {
+ modal.vm.$emit('receivedCaptchaResponse', response);
+
+ await nextTick();
+ });
+
+ it('sets needsCaptchaResponse to false', () => {
+ expect(modal.props('needsCaptchaResponse')).toEqual(false);
+ });
+
+ it(`expected to call times = ${expectedCalls.length}`, () => {
+ expect(mutateSpy.mock.calls).toEqual(expectedCalls);
+ });
+ });
+ });
});
});
+
+ describe('on before unload', () => {
+ it.each([
+ ['there are no actions', false, () => triggerBlobActions([])],
+ ['there is an empty action', false, () => triggerBlobActions([testEntries.empty.diff])],
+ ['there are actions', true, () => triggerBlobActions([testEntries.updated.diff])],
+ [
+ 'the title is set',
+ true,
+ () => {
+ triggerBlobActions([testEntries.empty.diff]);
+ setTitle('test');
+ },
+ ],
+ [
+ 'the description is set',
+ true,
+ () => {
+ triggerBlobActions([testEntries.empty.diff]);
+ setDescription('test');
+ },
+ ],
+ [
+ 'the snippet is being saved',
+ false,
+ () => {
+ triggerBlobActions([testEntries.updated.diff]);
+ clickSubmitBtn();
+ },
+ ],
+ ])(
+ 'handles before unload prevent when %s (expectPrevented=%s)',
+ async (_, expectPrevented, action) => {
+ await createComponentAndLoad({
+ props: {
+ snippetGid: '',
+ },
+ });
+
+ action();
+
+ const event = new Event('beforeunload');
+ const returnValueSetter = jest.spyOn(event, 'returnValue', 'set');
+
+ window.dispatchEvent(event);
+
+ if (expectPrevented) {
+ expect(returnValueSetter).toHaveBeenCalledWith(
+ 'Are you sure you want to lose unsaved changes?',
+ );
+ } else {
+ expect(returnValueSetter).not.toHaveBeenCalled();
+ }
+ },
+ );
+ });
});
diff --git a/spec/frontend/snippets/components/embed_dropdown_spec.js b/spec/frontend/snippets/components/embed_dropdown_spec.js
index f1eb7d43409..389b1c618a3 100644
--- a/spec/frontend/snippets/components/embed_dropdown_spec.js
+++ b/spec/frontend/snippets/components/embed_dropdown_spec.js
@@ -1,6 +1,6 @@
-import { escape as esc } from 'lodash';
-import { mount } from '@vue/test-utils';
import { GlFormInputGroup } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { escape as esc } from 'lodash';
import { TEST_HOST } from 'helpers/test_constants';
import EmbedDropdown from '~/snippets/components/embed_dropdown.vue';
diff --git a/spec/frontend/snippets/components/show_spec.js b/spec/frontend/snippets/components/show_spec.js
index b5ab7def753..e6162c6aad2 100644
--- a/spec/frontend/snippets/components/show_spec.js
+++ b/spec/frontend/snippets/components/show_spec.js
@@ -1,18 +1,17 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import { shallowMount } from '@vue/test-utils';
-import SnippetApp from '~/snippets/components/show.vue';
+import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import EmbedDropdown from '~/snippets/components/embed_dropdown.vue';
+import SnippetApp from '~/snippets/components/show.vue';
+import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
import SnippetHeader from '~/snippets/components/snippet_header.vue';
import SnippetTitle from '~/snippets/components/snippet_title.vue';
-import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
-import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
-
import {
SNIPPET_VISIBILITY_INTERNAL,
SNIPPET_VISIBILITY_PRIVATE,
SNIPPET_VISIBILITY_PUBLIC,
} from '~/snippets/constants';
+import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
describe('Snippet view app', () => {
let wrapper;
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 08056e788de..2693b26aeae 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,5 @@
-import { times } from 'lodash';
import { shallowMount } from '@vue/test-utils';
+import { times } from 'lodash';
import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue';
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
import {
diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
index 9d0311fd682..a7ab205ca7b 100644
--- a/spec/frontend/snippets/components/snippet_blob_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
@@ -1,14 +1,14 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
-import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'helpers/test_constants';
-import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
+import waitForPromises from 'helpers/wait_for_promises';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
+import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
jest.mock('~/flash');
diff --git a/spec/frontend/snippets/components/snippet_blob_view_spec.js b/spec/frontend/snippets/components/snippet_blob_view_spec.js
index 1ccecd7b5ba..b92c1907980 100644
--- a/spec/frontend/snippets/components/snippet_blob_view_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_view_spec.js
@@ -1,5 +1,5 @@
-import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import {
Blob as BlobMock,
SimpleViewerMock,
@@ -7,16 +7,16 @@ import {
RichBlobContentMock,
SimpleBlobContentMock,
} from 'jest/blob/components/mock_data';
-import SnippetBlobView from '~/snippets/components/snippet_blob_view.vue';
-import BlobHeader from '~/blob/components/blob_header.vue';
import BlobContent from '~/blob/components/blob_content.vue';
+import BlobHeader from '~/blob/components/blob_header.vue';
import {
BLOB_RENDER_EVENT_LOAD,
BLOB_RENDER_EVENT_SHOW_SOURCE,
BLOB_RENDER_ERRORS,
} from '~/blob/components/constants';
-import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
+import SnippetBlobView from '~/snippets/components/snippet_blob_view.vue';
import { SNIPPET_VISIBILITY_PUBLIC } from '~/snippets/constants';
+import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
describe('Blob Embeddable', () => {
let wrapper;
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index 93a66db32c6..585614a6b79 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -1,11 +1,11 @@
-import { ApolloMutation } from 'vue-apollo';
import { GlButton, GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
+import { ApolloMutation } from 'vue-apollo';
import waitForPromises from 'helpers/wait_for_promises';
-import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
-import SnippetHeader from '~/snippets/components/snippet_header.vue';
+import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
+import SnippetHeader from '~/snippets/components/snippet_header.vue';
+import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
describe('Snippet header component', () => {
let wrapper;
diff --git a/spec/frontend/snippets/components/snippet_title_spec.js b/spec/frontend/snippets/components/snippet_title_spec.js
index f201cfb19b7..48fb51ce703 100644
--- a/spec/frontend/snippets/components/snippet_title_spec.js
+++ b/spec/frontend/snippets/components/snippet_title_spec.js
@@ -1,7 +1,7 @@
import { GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import SnippetTitle from '~/snippets/components/snippet_title.vue';
import SnippetDescription from '~/snippets/components/snippet_description_view.vue';
+import SnippetTitle from '~/snippets/components/snippet_title.vue';
describe('Snippet header component', () => {
let wrapper;
diff --git a/spec/frontend/snippets/test_utils.js b/spec/frontend/snippets/test_utils.js
index 86262723157..8ba5a2fe5dc 100644
--- a/spec/frontend/snippets/test_utils.js
+++ b/spec/frontend/snippets/test_utils.js
@@ -1,3 +1,4 @@
+import { TEST_HOST } from 'helpers/test_constants';
import {
SNIPPET_BLOB_ACTION_CREATE,
SNIPPET_BLOB_ACTION_UPDATE,
@@ -8,6 +9,51 @@ import {
const CONTENT_1 = 'Lorem ipsum dolar\nSit amit\n\nGoodbye!\n';
const CONTENT_2 = 'Lorem ipsum dolar sit amit.\n\nGoodbye!\n';
+export const createGQLSnippet = () => ({
+ __typename: 'Snippet',
+ id: 7,
+ title: 'Snippet Title',
+ description: 'Lorem ipsum snippet desc',
+ descriptionHtml: '<p>Lorem ipsum snippet desc</p>',
+ createdAt: new Date(Date.now() - 1e6),
+ updatedAt: new Date(Date.now() - 1e3),
+ httpUrlToRepo: `${TEST_HOST}/repo`,
+ sshUrlToRepo: 'ssh://ssh.test/repo',
+ blobs: [],
+ userPermissions: {
+ __typename: 'SnippetPermissions',
+ adminSnippet: true,
+ updateSnippet: true,
+ },
+ project: {
+ __typename: 'Project',
+ fullPath: 'group/project',
+ webUrl: `${TEST_HOST}/group/project`,
+ },
+ author: {
+ __typename: 'User',
+ id: 1,
+ avatarUrl: `${TEST_HOST}/avatar.png`,
+ name: 'root',
+ username: 'root',
+ webUrl: `${TEST_HOST}/root`,
+ status: {
+ __typename: 'UserStatus',
+ emoji: '',
+ message: '',
+ },
+ },
+});
+
+export const createGQLSnippetsQueryResponse = (snippets) => ({
+ data: {
+ snippets: {
+ __typename: 'SnippetConnection',
+ nodes: snippets,
+ },
+ },
+});
+
export const testEntries = {
created: {
id: 'blob_1',
@@ -56,6 +102,15 @@ export const testEntries = {
content: CONTENT_2,
},
},
+ empty: {
+ id: 'empty',
+ diff: {
+ action: SNIPPET_BLOB_ACTION_CREATE,
+ filePath: '',
+ previousPath: '',
+ content: '',
+ },
+ },
};
export const createBlobFromTestEntry = ({ diff, origContent }, isOrig = false) => ({
diff --git a/spec/frontend/snippets/utils/error_spec.js b/spec/frontend/snippets/utils/error_spec.js
new file mode 100644
index 00000000000..385554568db
--- /dev/null
+++ b/spec/frontend/snippets/utils/error_spec.js
@@ -0,0 +1,16 @@
+import { getErrorMessage, UNEXPECTED_ERROR } from '~/snippets/utils/error';
+
+describe('~/snippets/utils/error', () => {
+ describe('getErrorMessage', () => {
+ it.each`
+ input | output
+ ${null} | ${UNEXPECTED_ERROR}
+ ${'message'} | ${'message'}
+ ${new Error('test message')} | ${'test message'}
+ ${{ networkError: 'Network error: test message' }} | ${'Network error: test message'}
+ ${{}} | ${UNEXPECTED_ERROR}
+ `('with $input, should return "$output"', ({ input, output }) => {
+ expect(getErrorMessage(input)).toBe(output);
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/components/edit_area_spec.js b/spec/frontend/static_site_editor/components/edit_area_spec.js
index 07097d00cc5..17fb3fe788a 100644
--- a/spec/frontend/static_site_editor/components/edit_area_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -1,15 +1,14 @@
-import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
-import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
-
import EditArea from '~/static_site_editor/components/edit_area.vue';
-import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
-import EditHeader from '~/static_site_editor/components/edit_header.vue';
import EditDrawer from '~/static_site_editor/components/edit_drawer.vue';
+import EditHeader from '~/static_site_editor/components/edit_header.vue';
+import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
import UnsavedChangesConfirmDialog from '~/static_site_editor/components/unsaved_changes_confirm_dialog.vue';
+import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
+import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
import {
sourceContentTitle as title,
diff --git a/spec/frontend/static_site_editor/components/edit_drawer_spec.js b/spec/frontend/static_site_editor/components/edit_drawer_spec.js
index c47eef59997..402dfe441c5 100644
--- a/spec/frontend/static_site_editor/components/edit_drawer_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_drawer_spec.js
@@ -1,6 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
-
import { GlDrawer } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import EditDrawer from '~/static_site_editor/components/edit_drawer.vue';
import FrontMatterControls from '~/static_site_editor/components/front_matter_controls.vue';
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 cf82efc3d0b..7a8834933e0 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,5 @@
-import { shallowMount } from '@vue/test-utils';
-
import { GlDropdown, GlDropdownItem, GlFormInput, GlFormTextarea } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue';
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 c7d0abee05c..3a336f6a230 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,12 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
-import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import axios from '~/lib/utils/axios_utils';
-import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue';
import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue';
+import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue';
import { MR_META_LOCAL_STORAGE_KEY } from '~/static_site_editor/constants';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import {
sourcePath,
mergeRequestMeta,
diff --git a/spec/frontend/static_site_editor/components/front_matter_controls_spec.js b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
index 8001f2fbd29..5fda3b40306 100644
--- a/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
+++ b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
@@ -1,6 +1,6 @@
+import { GlFormGroup } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from '@gitlab/ui';
import { humanize } from '~/lib/utils/text_utility';
import FrontMatterControls from '~/static_site_editor/components/front_matter_controls.vue';
diff --git a/spec/frontend/static_site_editor/components/submit_changes_error_spec.js b/spec/frontend/static_site_editor/components/submit_changes_error_spec.js
index 7af3014b338..82a5c5f624a 100644
--- a/spec/frontend/static_site_editor/components/submit_changes_error_spec.js
+++ b/spec/frontend/static_site_editor/components/submit_changes_error_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue';
diff --git a/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
index 750b777cf5d..a0529f5f945 100644
--- a/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
+++ b/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
@@ -1,6 +1,6 @@
import savedContentMetaQuery from '~/static_site_editor/graphql/queries/saved_content_meta.query.graphql';
-import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
import submitContentChangesResolver from '~/static_site_editor/graphql/resolvers/submit_content_changes';
+import submitContentChanges from '~/static_site_editor/services/submit_content_changes';
import {
projectId as project,
diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js
index 3e488a950dc..0936ba3011c 100644
--- a/spec/frontend/static_site_editor/pages/home_spec.js
+++ b/spec/frontend/static_site_editor/pages/home_spec.js
@@ -1,15 +1,15 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
-import Home from '~/static_site_editor/pages/home.vue';
-import SkeletonLoader from '~/static_site_editor/components/skeleton_loader.vue';
import EditArea from '~/static_site_editor/components/edit_area.vue';
import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue';
import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue';
+import SkeletonLoader from '~/static_site_editor/components/skeleton_loader.vue';
import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue';
-import submitContentChangesMutation from '~/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql';
+import { TRACKING_ACTION_INITIALIZE_EDITOR } from '~/static_site_editor/constants';
import hasSubmittedChangesMutation from '~/static_site_editor/graphql/mutations/has_submitted_changes.mutation.graphql';
+import submitContentChangesMutation from '~/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql';
+import Home from '~/static_site_editor/pages/home.vue';
import { SUCCESS_ROUTE } from '~/static_site_editor/router/constants';
-import { TRACKING_ACTION_INITIALIZE_EDITOR } from '~/static_site_editor/constants';
import {
project,
diff --git a/spec/frontend/static_site_editor/pages/success_spec.js b/spec/frontend/static_site_editor/pages/success_spec.js
index 3fc69dc4586..fbdc2c435a0 100644
--- a/spec/frontend/static_site_editor/pages/success_spec.js
+++ b/spec/frontend/static_site_editor/pages/success_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import Success from '~/static_site_editor/pages/success.vue';
-import { savedContentMeta, returnUrl, sourcePath } from '../mock_data';
import { HOME_ROUTE } from '~/static_site_editor/router/constants';
+import { savedContentMeta, returnUrl, sourcePath } from '../mock_data';
describe('~/static_site_editor/pages/success.vue', () => {
const mergeRequestsIllustrationPath = 'illustrations/merge_requests.svg';
diff --git a/spec/frontend/static_site_editor/services/front_matterify_spec.js b/spec/frontend/static_site_editor/services/front_matterify_spec.js
index 866897f21ef..ec3752b30c6 100644
--- a/spec/frontend/static_site_editor/services/front_matterify_spec.js
+++ b/spec/frontend/static_site_editor/services/front_matterify_spec.js
@@ -1,3 +1,4 @@
+import { frontMatterify, stringify } from '~/static_site_editor/services/front_matterify';
import {
sourceContentYAML as content,
sourceContentHeaderObjYAML as yamlFrontMatterObj,
@@ -5,8 +6,6 @@ import {
sourceContentBody as body,
} from '../mock_data';
-import { frontMatterify, stringify } from '~/static_site_editor/services/front_matterify';
-
describe('static_site_editor/services/front_matterify', () => {
const frontMatterifiedContent = {
source: content,
diff --git a/spec/frontend/static_site_editor/services/parse_source_file_spec.js b/spec/frontend/static_site_editor/services/parse_source_file_spec.js
index ab9e63f4cd2..fdd11297e09 100644
--- a/spec/frontend/static_site_editor/services/parse_source_file_spec.js
+++ b/spec/frontend/static_site_editor/services/parse_source_file_spec.js
@@ -1,3 +1,4 @@
+import parseSourceFile from '~/static_site_editor/services/parse_source_file';
import {
sourceContentYAML as content,
sourceContentHeaderYAML as yamlFrontMatter,
@@ -5,8 +6,6 @@ import {
sourceContentBody as body,
} from '../mock_data';
-import parseSourceFile from '~/static_site_editor/services/parse_source_file';
-
describe('static_site_editor/services/parse_source_file', () => {
const contentComplex = [content, content, content].join('');
const complexBody = [body, content, content].join('');
diff --git a/spec/frontend/task_list_spec.js b/spec/frontend/task_list_spec.js
index a8bdc506102..b6ac3167fea 100644
--- a/spec/frontend/task_list_spec.js
+++ b/spec/frontend/task_list_spec.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-import TaskList from '~/task_list';
import axios from '~/lib/utils/axios_utils';
+import TaskList from '~/task_list';
describe('TaskList', () => {
let taskList;
diff --git a/spec/frontend/terraform/components/states_table_actions_spec.js b/spec/frontend/terraform/components/states_table_actions_spec.js
index 3f5df8a96f8..61f6e9f0f7b 100644
--- a/spec/frontend/terraform/components/states_table_actions_spec.js
+++ b/spec/frontend/terraform/components/states_table_actions_spec.js
@@ -1,7 +1,8 @@
import { GlDropdown, GlModal, GlSprintf } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import createMockApollo from 'helpers/mock_apollo_helper';
import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import StateActions from '~/terraform/components/states_table_actions.vue';
import lockStateMutation from '~/terraform/graphql/mutations/lock_state.mutation.graphql';
import removeStateMutation from '~/terraform/graphql/mutations/remove_state.mutation.graphql';
@@ -13,7 +14,9 @@ localVue.use(VueApollo);
describe('StatesTableActions', () => {
let lockResponse;
let removeResponse;
+ let toast;
let unlockResponse;
+ let updateStateResponse;
let wrapper;
const defaultProps = {
@@ -26,7 +29,9 @@ describe('StatesTableActions', () => {
};
const createMockApolloProvider = () => {
- lockResponse = jest.fn().mockResolvedValue({ data: { terraformStateLock: { errors: [] } } });
+ lockResponse = jest
+ .fn()
+ .mockResolvedValue({ data: { terraformStateLock: { errors: ['There was an error'] } } });
removeResponse = jest
.fn()
@@ -36,26 +41,39 @@ describe('StatesTableActions', () => {
.fn()
.mockResolvedValue({ data: { terraformStateUnlock: { errors: [] } } });
- return createMockApollo([
- [lockStateMutation, lockResponse],
- [removeStateMutation, removeResponse],
- [unlockStateMutation, unlockResponse],
- ]);
+ updateStateResponse = jest.fn().mockResolvedValue({});
+
+ return createMockApollo(
+ [
+ [lockStateMutation, lockResponse],
+ [removeStateMutation, removeResponse],
+ [unlockStateMutation, unlockResponse],
+ ],
+ {
+ Mutation: {
+ addDataToTerraformState: updateStateResponse,
+ },
+ },
+ );
};
const createComponent = (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();
};
+ const findActionsDropdown = () => wrapper.find(GlDropdown);
const findLockBtn = () => wrapper.find('[data-testid="terraform-state-lock"]');
const findUnlockBtn = () => wrapper.find('[data-testid="terraform-state-unlock"]');
const findDownloadBtn = () => wrapper.find('[data-testid="terraform-state-download"]');
@@ -69,10 +87,44 @@ describe('StatesTableActions', () => {
afterEach(() => {
lockResponse = null;
removeResponse = null;
+ toast = null;
unlockResponse = null;
+ updateStateResponse = null;
wrapper.destroy();
});
+ describe('when the state is loading', () => {
+ describe('when lock/unlock is processing', () => {
+ beforeEach(() => {
+ return createComponent({
+ state: {
+ ...defaultProps.state,
+ loadingLock: true,
+ },
+ });
+ });
+
+ it('disables the actions dropdown', () => {
+ expect(findActionsDropdown().props('disabled')).toBe(true);
+ });
+ });
+
+ describe('when remove is processing', () => {
+ beforeEach(() => {
+ return createComponent({
+ state: {
+ ...defaultProps.state,
+ loadingRemove: true,
+ },
+ });
+ });
+
+ it('disables the actions dropdown', () => {
+ expect(findActionsDropdown().props('disabled')).toBe(true);
+ });
+ });
+ });
+
describe('download button', () => {
it('displays a download button', () => {
expect(findDownloadBtn().text()).toBe('Download JSON');
@@ -104,7 +156,8 @@ describe('StatesTableActions', () => {
describe('when clicking the unlock button', () => {
beforeEach(() => {
findUnlockBtn().vm.$emit('click');
- return wrapper.vm.$nextTick();
+
+ return waitForPromises();
});
it('calls the unlock mutation', () => {
@@ -137,7 +190,8 @@ describe('StatesTableActions', () => {
describe('when clicking the lock button', () => {
beforeEach(() => {
findLockBtn().vm.$emit('click');
- return wrapper.vm.$nextTick();
+
+ return waitForPromises();
});
it('calls the lock mutation', () => {
@@ -145,6 +199,44 @@ describe('StatesTableActions', () => {
stateID: unlockedProps.state.id,
});
});
+
+ it('calls mutations to set loading and errors', () => {
+ // loading update
+ expect(updateStateResponse).toHaveBeenNthCalledWith(
+ 1,
+ {},
+ {
+ terraformState: {
+ ...unlockedProps.state,
+ _showDetails: false,
+ errorMessages: [],
+ loadingLock: true,
+ loadingRemove: false,
+ },
+ },
+ // Apollo fields
+ expect.any(Object),
+ expect.any(Object),
+ );
+
+ // final update
+ expect(updateStateResponse).toHaveBeenNthCalledWith(
+ 2,
+ {},
+ {
+ terraformState: {
+ ...unlockedProps.state,
+ _showDetails: true,
+ errorMessages: ['There was an error'],
+ loadingLock: false,
+ loadingRemove: false,
+ },
+ },
+ // Apollo fields
+ expect.any(Object),
+ expect.any(Object),
+ );
+ });
});
});
@@ -156,7 +248,7 @@ describe('StatesTableActions', () => {
describe('when clicking the remove button', () => {
beforeEach(() => {
findRemoveBtn().vm.$emit('click');
- return wrapper.vm.$nextTick();
+ return waitForPromises();
});
it('displays a remove modal', () => {
@@ -166,21 +258,70 @@ describe('StatesTableActions', () => {
});
describe('when submitting the remove modal', () => {
- it('does not call the remove mutation when state name is missing', async () => {
- findRemoveModal().vm.$emit('ok');
- await wrapper.vm.$nextTick();
+ describe('when state name is missing', () => {
+ beforeEach(() => {
+ findRemoveModal().vm.$emit('ok');
+ return waitForPromises();
+ });
- expect(removeResponse).not.toHaveBeenCalledWith();
+ it('does not call the remove mutation', () => {
+ expect(removeResponse).not.toHaveBeenCalledWith();
+ });
});
- it('calls the remove mutation when state name is present', async () => {
- await wrapper.setData({ removeConfirmText: defaultProps.state.name });
+ describe('when state name is present', () => {
+ beforeEach(async () => {
+ await wrapper.setData({ removeConfirmText: defaultProps.state.name });
+
+ findRemoveModal().vm.$emit('ok');
- findRemoveModal().vm.$emit('ok');
- await wrapper.vm.$nextTick();
+ await waitForPromises();
+ });
+
+ it('calls the remove mutation', () => {
+ expect(removeResponse).toHaveBeenCalledWith({ stateID: defaultProps.state.id });
+ });
+
+ it('calls the toast action', () => {
+ expect(toast).toHaveBeenCalledWith(`${defaultProps.state.name} successfully removed`);
+ });
- expect(removeResponse).toHaveBeenCalledWith({
- stateID: defaultProps.state.id,
+ it('calls mutations to set loading and errors', () => {
+ // loading update
+ expect(updateStateResponse).toHaveBeenNthCalledWith(
+ 1,
+ {},
+ {
+ terraformState: {
+ ...defaultProps.state,
+ _showDetails: false,
+ errorMessages: [],
+ loadingLock: false,
+ loadingRemove: true,
+ },
+ },
+ // Apollo fields
+ expect.any(Object),
+ expect.any(Object),
+ );
+
+ // final update
+ expect(updateStateResponse).toHaveBeenNthCalledWith(
+ 2,
+ {},
+ {
+ terraformState: {
+ ...defaultProps.state,
+ _showDetails: false,
+ errorMessages: [],
+ loadingLock: false,
+ loadingRemove: false,
+ },
+ },
+ // Apollo fields
+ expect.any(Object),
+ expect.any(Object),
+ );
});
});
});
diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js
index f2b7bc00e5b..100e577f514 100644
--- a/spec/frontend/terraform/components/states_table_spec.js
+++ b/spec/frontend/terraform/components/states_table_spec.js
@@ -1,8 +1,8 @@
-import { GlIcon, GlTooltip } from '@gitlab/ui';
+import { GlIcon, GlLoadingIcon, GlTooltip } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
-import StateActions from '~/terraform/components/states_table_actions.vue';
import StatesTable from '~/terraform/components/states_table.vue';
+import StateActions from '~/terraform/components/states_table_actions.vue';
describe('StatesTable', () => {
let wrapper;
@@ -11,7 +11,11 @@ describe('StatesTable', () => {
const defaultProps = {
states: [
{
+ _showDetails: true,
+ errorMessages: ['State 1 has errored'],
name: 'state-1',
+ loadingLock: false,
+ loadingRemove: false,
lockedAt: '2020-10-13T00:00:00Z',
lockedByUser: {
name: 'user-1',
@@ -20,14 +24,22 @@ describe('StatesTable', () => {
latestVersion: null,
},
{
+ _showDetails: false,
+ errorMessages: [],
name: 'state-2',
+ loadingLock: true,
+ loadingRemove: false,
lockedAt: null,
lockedByUser: null,
updatedAt: '2020-10-10T00:00:00Z',
latestVersion: null,
},
{
+ _showDetails: false,
+ errorMessages: [],
name: 'state-3',
+ loadingLock: true,
+ loadingRemove: false,
lockedAt: '2020-10-10T00:00:00Z',
lockedByUser: {
name: 'user-2',
@@ -54,7 +66,11 @@ describe('StatesTable', () => {
},
},
{
+ _showDetails: true,
+ errorMessages: ['State 4 has errored'],
name: 'state-4',
+ loadingLock: false,
+ loadingRemove: false,
lockedAt: '2020-10-10T00:00:00Z',
lockedByUser: null,
updatedAt: '2020-10-10T00:00:00Z',
@@ -76,6 +92,17 @@ describe('StatesTable', () => {
},
},
},
+ {
+ _showDetails: false,
+ errorMessages: [],
+ name: 'state-5',
+ loadingLock: false,
+ loadingRemove: true,
+ lockedAt: null,
+ lockedByUser: null,
+ updatedAt: '2020-10-10T00:00:00Z',
+ latestVersion: null,
+ },
],
};
@@ -96,14 +123,15 @@ describe('StatesTable', () => {
});
it.each`
- name | toolTipText | locked | lineNumber
- ${'state-1'} | ${'Locked by user-1 2 days ago'} | ${true} | ${0}
- ${'state-2'} | ${null} | ${false} | ${1}
- ${'state-3'} | ${'Locked by user-2 5 days ago'} | ${true} | ${2}
- ${'state-4'} | ${'Locked by Unknown User 5 days ago'} | ${true} | ${3}
+ name | toolTipText | locked | loading | lineNumber
+ ${'state-1'} | ${'Locked by user-1 2 days ago'} | ${true} | ${false} | ${0}
+ ${'state-2'} | ${'Locking state'} | ${false} | ${true} | ${1}
+ ${'state-3'} | ${'Unlocking state'} | ${false} | ${true} | ${2}
+ ${'state-4'} | ${'Locked by Unknown User 5 days ago'} | ${true} | ${false} | ${3}
+ ${'state-5'} | ${'Removing'} | ${false} | ${true} | ${4}
`(
'displays the name and locked information "$name" for line "$lineNumber"',
- ({ name, toolTipText, locked, lineNumber }) => {
+ ({ name, toolTipText, locked, loading, lineNumber }) => {
const states = wrapper.findAll('[data-testid="terraform-states-table-name"]');
const state = states.at(lineNumber);
@@ -111,6 +139,7 @@ describe('StatesTable', () => {
expect(state.text()).toContain(name);
expect(state.find(GlIcon).exists()).toBe(locked);
+ expect(state.find(GlLoadingIcon).exists()).toBe(loading);
expect(toolTip.exists()).toBe(locked);
if (locked) {
@@ -154,6 +183,17 @@ describe('StatesTable', () => {
expect(findActions().length).toEqual(0);
});
+ it.each`
+ errorMessage | lineNumber
+ ${defaultProps.states[0].errorMessages[0]} | ${0}
+ ${defaultProps.states[3].errorMessages[0]} | ${1}
+ `('displays table error message "$errorMessage"', ({ errorMessage, lineNumber }) => {
+ const states = wrapper.findAll('[data-testid="terraform-states-table-error"]');
+ const state = states.at(lineNumber);
+
+ expect(state.text()).toBe(errorMessage);
+ });
+
describe('when user is a terraform administrator', () => {
beforeEach(() => {
return createComponent({
diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js
index fb56a7135a3..882b7b55b3e 100644
--- a/spec/frontend/terraform/components/terraform_list_spec.js
+++ b/spec/frontend/terraform/components/terraform_list_spec.js
@@ -1,7 +1,8 @@
import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import createMockApollo from 'helpers/mock_apollo_helper';
import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import EmptyState from '~/terraform/components/empty_state.vue';
import StatesTable from '~/terraform/components/states_table.vue';
import TerraformList from '~/terraform/components/terraform_list.vue';
@@ -27,8 +28,20 @@ describe('TerraformList', () => {
},
};
+ const mockResolvers = {
+ TerraformState: {
+ _showDetails: jest.fn().mockResolvedValue(false),
+ errorMessages: jest.fn().mockResolvedValue([]),
+ loadingLock: jest.fn().mockResolvedValue(false),
+ loadingRemove: jest.fn().mockResolvedValue(false),
+ },
+ Mutation: {
+ addDataToTerraformState: jest.fn().mockResolvedValue({}),
+ },
+ };
+
const statsQueryResponse = queryResponse || jest.fn().mockResolvedValue(apolloQueryResponse);
- const apolloProvider = createMockApollo([[getStatesQuery, statsQueryResponse]]);
+ const apolloProvider = createMockApollo([[getStatesQuery, statsQueryResponse]], mockResolvers);
wrapper = shallowMount(TerraformList, {
localVue,
@@ -52,20 +65,28 @@ describe('TerraformList', () => {
describe('when there is a list of terraform states', () => {
const states = [
{
+ _showDetails: false,
+ errorMessages: [],
id: 'gid://gitlab/Terraform::State/1',
name: 'state-1',
+ latestVersion: null,
+ loadingLock: false,
+ loadingRemove: false,
lockedAt: null,
- updatedAt: null,
lockedByUser: null,
- latestVersion: null,
+ updatedAt: null,
},
{
+ _showDetails: false,
+ errorMessages: [],
id: 'gid://gitlab/Terraform::State/2',
name: 'state-2',
+ latestVersion: null,
+ loadingLock: false,
+ loadingRemove: false,
lockedAt: null,
- updatedAt: null,
lockedByUser: null,
- latestVersion: null,
+ updatedAt: null,
},
];
@@ -83,7 +104,7 @@ describe('TerraformList', () => {
},
});
- return wrapper.vm.$nextTick();
+ return waitForPromises();
});
it('displays a states tab and count', () => {
@@ -111,7 +132,7 @@ describe('TerraformList', () => {
},
});
- return wrapper.vm.$nextTick();
+ return waitForPromises();
});
it('renders the states table without pagination buttons', () => {
@@ -131,7 +152,7 @@ describe('TerraformList', () => {
},
});
- return wrapper.vm.$nextTick();
+ return waitForPromises();
});
it('displays a states tab with no count', () => {
@@ -149,7 +170,7 @@ describe('TerraformList', () => {
beforeEach(() => {
createWrapper({ terraformStates: null, queryResponse: jest.fn().mockRejectedValue() });
- return wrapper.vm.$nextTick();
+ return waitForPromises();
});
it('displays an alert message', () => {
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index a122b06fdda..b6b29faef79 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -1,13 +1,13 @@
+import { config as testUtilsConfig } from '@vue/test-utils';
+import * as jqueryMatchers from 'custom-jquery-matchers';
import Vue from 'vue';
import 'jquery';
-
-import * as jqueryMatchers from 'custom-jquery-matchers';
-import { config as testUtilsConfig } from '@vue/test-utils';
+import { setGlobalDateToFakeDate } from 'helpers/fake_date';
import Translate from '~/vue_shared/translate';
-import { initializeTestTimeout } from './__helpers__/timeout';
import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './__helpers__/fixtures';
-import { setupManualMocks } from './mocks/mocks_helper';
+import { initializeTestTimeout } from './__helpers__/timeout';
import customMatchers from './matchers';
+import { setupManualMocks } from './mocks/mocks_helper';
import './__helpers__/dom_shims';
import './__helpers__/jquery';
@@ -20,6 +20,10 @@ process.on('unhandledRejection', global.promiseRejectionHandler);
setupManualMocks();
+// Fake the `Date` for the rest of the jest spec runtime environment.
+// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39496#note_503084332
+setGlobalDateToFakeDate();
+
afterEach(() =>
// give Promises a bit more time so they fail the right test
new Promise(setImmediate).then(() => {
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
index 3a894427643..e21626456e2 100644
--- a/spec/frontend/tooltips/components/tooltips_spec.js
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlTooltip } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { useMockMutationObserver } from 'helpers/mock_dom_observer';
import Tooltips from '~/tooltips/components/tooltips.vue';
diff --git a/spec/frontend/tooltips/index_spec.js b/spec/frontend/tooltips/index_spec.js
index bff9ee0c7f2..9c03ca8f4c9 100644
--- a/spec/frontend/tooltips/index_spec.js
+++ b/spec/frontend/tooltips/index_spec.js
@@ -1,4 +1,3 @@
-import jQuery from 'jquery';
import {
add,
initTooltips,
@@ -146,29 +145,4 @@ describe('tooltips/index.js', () => {
expect(tooltipsApp.fixTitle).toHaveBeenCalledWith(target);
});
-
- describe('when glTooltipsEnabled feature flag is disabled', () => {
- beforeEach(() => {
- window.gon.features.glTooltips = false;
- });
-
- it.each`
- method | methodName | bootstrapParams
- ${dispose} | ${'dispose'} | ${'dispose'}
- ${fixTitle} | ${'fixTitle'} | ${'_fixTitle'}
- ${enable} | ${'enable'} | ${'enable'}
- ${disable} | ${'disable'} | ${'disable'}
- ${hide} | ${'hide'} | ${'hide'}
- ${show} | ${'show'} | ${'show'}
- ${add} | ${'init'} | ${{ title: 'the title' }}
- `('delegates $methodName to bootstrap tooltip API', ({ method, bootstrapParams }) => {
- const elements = jQuery(createTooltipTarget());
-
- jest.spyOn(jQuery.fn, 'tooltip');
-
- method(elements, bootstrapParams);
-
- expect(elements.tooltip).toHaveBeenCalledWith(bootstrapParams);
- });
- });
});
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 958e86ac050..bd71a677a24 100644
--- a/spec/frontend/user_lists/components/edit_user_list_spec.js
+++ b/spec/frontend/user_lists/components/edit_user_list_spec.js
@@ -1,14 +1,14 @@
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { createLocalVue, mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { createLocalVue, mount } from '@vue/test-utils';
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import createStore from '~/user_lists/store/edit';
+import { redirectTo } from '~/lib/utils/url_utility';
import EditUserList from '~/user_lists/components/edit_user_list.vue';
import UserListForm from '~/user_lists/components/user_list_form.vue';
+import createStore from '~/user_lists/store/edit';
import { userList } from '../../feature_flags/mock_data';
-import { redirectTo } from '~/lib/utils/url_utility';
jest.mock('~/api');
jest.mock('~/lib/utils/url_utility');
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 421b49f40e9..a81e8912714 100644
--- a/spec/frontend/user_lists/components/new_user_list_spec.js
+++ b/spec/frontend/user_lists/components/new_user_list_spec.js
@@ -1,12 +1,12 @@
+import { GlAlert } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { GlAlert } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import createStore from '~/user_lists/store/new';
-import NewUserList from '~/user_lists/components/new_user_list.vue';
import { redirectTo } from '~/lib/utils/url_utility';
+import NewUserList from '~/user_lists/components/new_user_list.vue';
+import createStore from '~/user_lists/store/new';
import { userList } from '../../feature_flags/mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/user_lists/components/user_list_spec.js b/spec/frontend/user_lists/components/user_list_spec.js
index cd00c421154..f016b5091d9 100644
--- a/spec/frontend/user_lists/components/user_list_spec.js
+++ b/spec/frontend/user_lists/components/user_list_spec.js
@@ -1,12 +1,12 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
+import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { uniq } from 'lodash';
-import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import Vue from 'vue';
+import Vuex from 'vuex';
import Api from '~/api';
-import { parseUserIds, stringifyUserIds } from '~/user_lists/store/utils';
-import createStore from '~/user_lists/store/show';
import UserList from '~/user_lists/components/user_list.vue';
+import createStore from '~/user_lists/store/show';
+import { parseUserIds, stringifyUserIds } from '~/user_lists/store/utils';
import { userList } from '../../feature_flags/mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/user_lists/store/edit/actions_spec.js b/spec/frontend/user_lists/store/edit/actions_spec.js
index 7f0fb8e5401..c4b0f888d3e 100644
--- a/spec/frontend/user_lists/store/edit/actions_spec.js
+++ b/spec/frontend/user_lists/store/edit/actions_spec.js
@@ -1,9 +1,9 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import createState from '~/user_lists/store/edit/state';
-import * as types from '~/user_lists/store/edit/mutation_types';
-import * as actions from '~/user_lists/store/edit/actions';
import { redirectTo } from '~/lib/utils/url_utility';
+import * as actions from '~/user_lists/store/edit/actions';
+import * as types from '~/user_lists/store/edit/mutation_types';
+import createState from '~/user_lists/store/edit/state';
import { userList } from '../../../feature_flags/mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/user_lists/store/edit/mutations_spec.js b/spec/frontend/user_lists/store/edit/mutations_spec.js
index 3d4d2a59717..0943c64e934 100644
--- a/spec/frontend/user_lists/store/edit/mutations_spec.js
+++ b/spec/frontend/user_lists/store/edit/mutations_spec.js
@@ -1,7 +1,7 @@
import statuses from '~/user_lists/constants/edit';
-import createState from '~/user_lists/store/edit/state';
import * as types from '~/user_lists/store/edit/mutation_types';
import mutations from '~/user_lists/store/edit/mutations';
+import createState from '~/user_lists/store/edit/state';
import { userList } from '../../../feature_flags/mock_data';
describe('User List Edit Mutations', () => {
diff --git a/spec/frontend/user_lists/store/new/actions_spec.js b/spec/frontend/user_lists/store/new/actions_spec.js
index 9cc6212a125..916ec2e6da7 100644
--- a/spec/frontend/user_lists/store/new/actions_spec.js
+++ b/spec/frontend/user_lists/store/new/actions_spec.js
@@ -1,9 +1,9 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import createState from '~/user_lists/store/new/state';
-import * as types from '~/user_lists/store/new/mutation_types';
-import * as actions from '~/user_lists/store/new/actions';
import { redirectTo } from '~/lib/utils/url_utility';
+import * as actions from '~/user_lists/store/new/actions';
+import * as types from '~/user_lists/store/new/mutation_types';
+import createState from '~/user_lists/store/new/state';
import { userList } from '../../../feature_flags/mock_data';
jest.mock('~/api');
diff --git a/spec/frontend/user_lists/store/new/mutations_spec.js b/spec/frontend/user_lists/store/new/mutations_spec.js
index 89e8a83eb25..a928849e941 100644
--- a/spec/frontend/user_lists/store/new/mutations_spec.js
+++ b/spec/frontend/user_lists/store/new/mutations_spec.js
@@ -1,6 +1,6 @@
-import createState from '~/user_lists/store/new/state';
import * as types from '~/user_lists/store/new/mutation_types';
import mutations from '~/user_lists/store/new/mutations';
+import createState from '~/user_lists/store/new/state';
describe('User List Edit Mutations', () => {
let state;
diff --git a/spec/frontend/user_lists/store/show/actions_spec.js b/spec/frontend/user_lists/store/show/actions_spec.js
index 25a6b9ec0e4..7b82fd8cf24 100644
--- a/spec/frontend/user_lists/store/show/actions_spec.js
+++ b/spec/frontend/user_lists/store/show/actions_spec.js
@@ -1,10 +1,10 @@
import testAction from 'helpers/vuex_action_helper';
import { userList } from 'jest/feature_flags/mock_data';
import Api from '~/api';
-import { stringifyUserIds } from '~/user_lists/store/utils';
-import createState from '~/user_lists/store/show/state';
-import * as types from '~/user_lists/store/show/mutation_types';
import * as actions from '~/user_lists/store/show/actions';
+import * as types from '~/user_lists/store/show/mutation_types';
+import createState from '~/user_lists/store/show/state';
+import { stringifyUserIds } from '~/user_lists/store/utils';
jest.mock('~/api');
diff --git a/spec/frontend/user_lists/store/show/mutations_spec.js b/spec/frontend/user_lists/store/show/mutations_spec.js
index cd379641ee1..92e2fcb06be 100644
--- a/spec/frontend/user_lists/store/show/mutations_spec.js
+++ b/spec/frontend/user_lists/store/show/mutations_spec.js
@@ -1,9 +1,9 @@
import { uniq } from 'lodash';
import { userList } from 'jest/feature_flags/mock_data';
-import createState from '~/user_lists/store/show/state';
-import mutations from '~/user_lists/store/show/mutations';
import { states } from '~/user_lists/constants/show';
import * as types from '~/user_lists/store/show/mutation_types';
+import mutations from '~/user_lists/store/show/mutations';
+import createState from '~/user_lists/store/show/state';
describe('User Lists Show Mutations', () => {
let mockState;
diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js
index 1e0c4dd29ee..7c9c3d69efa 100644
--- a/spec/frontend/user_popovers_spec.js
+++ b/spec/frontend/user_popovers_spec.js
@@ -1,5 +1,5 @@
-import initUserPopovers from '~/user_popovers';
import UsersCache from '~/lib/utils/users_cache';
+import initUserPopovers from '~/user_popovers';
describe('User Popovers', () => {
const fixtureTemplate = 'merge_requests/merge_request_with_mentions.html';
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
index fd8b0dddc61..d6a1c2d3b07 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
+++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import Approvals from '~/vue_merge_request_widget/components/approvals/approvals.vue';
import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
import ApprovalsSummaryOptional from '~/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
FETCH_LOADING,
FETCH_ERROR,
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js b/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js
index d9a5230f55f..65cafc647e0 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js
+++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ApprovalsSummaryOptional from '~/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue';
const TEST_HELP_PATH = 'help/path';
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js b/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
index b8ba619fbb1..ef712ec23a6 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
+++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages';
-import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
import { toNounSeriesText } from '~/lib/utils/grammar';
+import ApprovalsSummary from '~/vue_merge_request_widget/components/approvals/approvals_summary.vue';
+import { APPROVED_MESSAGE } from '~/vue_merge_request_widget/components/approvals/messages';
import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
const testApprovers = () => Array.from({ length: 5 }, (_, i) => i).map((id) => ({ id }));
diff --git a/spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js b/spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js
index 2e1e21299b3..b2cc7d9be6b 100644
--- a/spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js
+++ b/spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js
@@ -1,8 +1,8 @@
+import { GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import Vuex from 'vuex';
-import Vue, { nextTick } from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import { GlLoadingIcon } from '@gitlab/ui';
+import Vue, { nextTick } from 'vue';
+import Vuex from 'vuex';
import { TEST_HOST as FAKE_ENDPOINT } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import ArtifactsListApp from '~/vue_merge_request_widget/components/artifacts_list_app.vue';
diff --git a/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js b/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js
index fd432381512..712abfe228a 100644
--- a/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js
+++ b/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ArtifactsList from '~/vue_merge_request_widget/components/artifacts_list.vue';
import { artifacts } from '../mock_data';
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 ba2a8ee0a41..94d4cccab5f 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,5 @@
-import { mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import MrCollapsibleSection from '~/vue_merge_request_widget/components/mr_collapsible_extension.vue';
describe('Merge Request Collapsible Extension', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
index 720ce613b85..07e869a070f 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import MrWidgetAlertMessage from '~/vue_merge_request_widget/components/mr_widget_alert_message.vue';
describe('MrWidgetAlertMessage', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js
index 4bcae904ddc..ebd10f31fa7 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
const TEST_ICON = 'commit';
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 79a0dd1e760..f55d313a719 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,6 @@
-import Vue from 'vue';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import MemoryUsage from '~/vue_merge_request_widget/components/deployment/memory_usage.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
index 7ff8d9678fe..3baade5161e 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
@@ -1,10 +1,10 @@
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import MrWidgetPipelineContainer from '~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue';
-import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
+import axios from '~/lib/utils/axios_utils';
import ArtifactsApp from '~/vue_merge_request_widget/components/artifacts_list_app.vue';
+import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
+import MrWidgetPipelineContainer from '~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue';
import { mockStore } from '../mock_data';
-import axios from '~/lib/utils/axios_utils';
describe('MrWidgetPipelineContainer', () => {
let wrapper;
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 3e5ab5cd32d..b93236d4628 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -1,9 +1,9 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import { SUCCESS } from '~/vue_merge_request_widget/constants';
-import PipelineComponent from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
import PipelineStage from '~/pipelines/components/pipelines_list/stage.vue';
+import PipelineComponent from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
+import { SUCCESS } from '~/vue_merge_request_widget/constants';
import mockData from '../mock_data';
describe('MRWidgetPipeline', () => {
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js
index bdd038edd71..5081e1e5906 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js
@@ -1,7 +1,7 @@
-import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
-import eventHub from '~/vue_merge_request_widget/event_hub';
+import { nextTick } from 'vue';
import WidgetRebase from '~/vue_merge_request_widget/components/states/mr_widget_rebase.vue';
+import eventHub from '~/vue_merge_request_widget/event_hub';
let wrapper;
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js
index 6c3b4a01659..c25e10c5249 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js
@@ -1,48 +1,60 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import mrStatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
describe('MR widget status icon component', () => {
- let vm;
- let Component;
+ let wrapper;
- beforeEach(() => {
- Component = Vue.extend(mrStatusIcon);
- });
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findDisabledMergeButton = () => wrapper.find('[data-testid="disabled-merge-button"]');
+
+ const createWrapper = (props, mountFn = shallowMount) => {
+ wrapper = mountFn(mrStatusIcon, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('while loading', () => {
it('renders loading icon', () => {
- vm = mountComponent(Component, { status: 'loading' });
+ createWrapper({ status: 'loading' });
- expect(vm.$el.querySelector('.mr-widget-icon span').classList).toContain('gl-spinner');
+ expect(findLoadingIcon().exists()).toBe(true);
});
});
describe('with status icon', () => {
- it('renders ci status icon', () => {
- vm = mountComponent(Component, { status: 'failed' });
+ it('renders success status icon', () => {
+ createWrapper({ status: 'success' }, mount);
+
+ expect(wrapper.find('[data-testid="status_success-icon"]').exists()).toBe(true);
+ });
+
+ it('renders failed status icon', () => {
+ createWrapper({ status: 'failed' }, mount);
- expect(vm.$el.querySelector('.js-ci-status-icon-failed')).not.toBeNull();
+ expect(wrapper.find('[data-testid="status_failed-icon"]').exists()).toBe(true);
});
});
describe('with disabled button', () => {
it('renders a disabled button', () => {
- vm = mountComponent(Component, { status: 'failed', showDisabledButton: true });
+ createWrapper({ status: 'failed', showDisabledButton: true });
- expect(vm.$el.querySelector('.js-disabled-merge-button').textContent.trim()).toEqual('Merge');
+ expect(findDisabledMergeButton().exists()).toBe(true);
});
});
describe('without disabled button', () => {
it('does not render a disabled button', () => {
- vm = mountComponent(Component, { status: 'failed' });
+ createWrapper({ status: 'failed' });
- expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeNull();
+ expect(findDisabledMergeButton().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
index 8fcc982ac99..b5afc1ab21a 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
@@ -1,12 +1,10 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
-import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
+import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import suggestPipelineComponent from '~/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue';
-import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
-import dismissibleContainer from '~/vue_shared/components/dismissible_container.vue';
-import { suggestProps, iconName } from './pipeline_tour_mock_data';
+import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
import axios from '~/lib/utils/axios_utils';
+import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
+import suggestPipelineComponent from '~/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue';
import {
SP_TRACK_LABEL,
SP_LINK_TRACK_EVENT,
@@ -15,6 +13,8 @@ import {
SP_SHOW_TRACK_VALUE,
SP_HELP_URL,
} from '~/vue_merge_request_widget/constants';
+import dismissibleContainer from '~/vue_shared/components/dismissible_container.vue';
+import { suggestProps, iconName } from './pipeline_tour_mock_data';
describe('MRWidgetSuggestPipeline', () => {
describe('template', () => {
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
new file mode 100644
index 00000000000..a124008b36a
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PipelineFailed should render error message with a disabled merge button 1`] = `
+<div
+ class="mr-widget-body media"
+>
+ <status-icon-stub
+ showdisabledbutton="true"
+ status="warning"
+ />
+
+ <div
+ class="media-body space-children"
+ >
+ <span
+ 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."
+ />
+ </span>
+ </div>
+</div>
+`;
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 850bbd93df5..4dd1bd2aa9c 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
@@ -1,11 +1,11 @@
-import { nextTick } from 'vue';
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 autoMergeEnabledComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue';
-import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
-import eventHub from '~/vue_merge_request_widget/event_hub';
import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
let wrapper;
let mergeRequestWidgetGraphqlEnabled = false;
@@ -202,7 +202,11 @@ describe('MRWidgetAutoMergeEnabled', () => {
wrapper.vm.cancelAutomaticMerge();
setImmediate(() => {
expect(wrapper.vm.isCancellingAutoMerge).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ if (mergeRequestWidgetGraphql) {
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ } else {
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ }
done();
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
index dca3798f7ea..24198096564 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
@@ -1,6 +1,6 @@
-import { nextTick } from 'vue';
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import AutoMergeFailedComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
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 706d60368b5..4c763f40cbe 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
const commits = [
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 f5a059698b6..d3fc1e0e05b 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,7 +1,7 @@
-import $ from 'jquery';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { removeBreakLine } from 'helpers/text_helper';
+import $ from 'jquery';
import { TEST_HOST } from 'helpers/test_constants';
+import { removeBreakLine } from 'helpers/text_helper';
import ConflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue';
describe('MRWidgetConflicts', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
index 48c1a9eedf9..c1471314c4a 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
@@ -54,7 +54,7 @@ describe('MRWidgetFailedToMerge', () => {
Vue.nextTick()
.then(() => {
- expect(vm.mergeError).toBe('contains line breaks');
+ expect(vm.mergeError).toBe('contains line breaks.');
})
.then(done)
.catch(done.fail);
@@ -113,14 +113,14 @@ describe('MRWidgetFailedToMerge', () => {
describe('while it is not regresing', () => {
it('renders warning icon and disabled merge button', () => {
expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull();
- expect(vm.$el.querySelector('.js-disabled-merge-button').getAttribute('disabled')).toEqual(
- 'disabled',
- );
+ expect(
+ vm.$el.querySelector('[data-testid="disabled-merge-button"]').getAttribute('disabled'),
+ ).toEqual('disabled');
});
it('renders given error', () => {
expect(vm.$el.querySelector('.has-error-message').textContent.trim()).toEqual(
- 'Merge error happened',
+ 'Merge error happened.',
);
});
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 36c4174c03d..6af8ac9e18e 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,5 +1,8 @@
+import { getByRole } from '@testing-library/dom';
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
+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';
import eventHub from '~/vue_merge_request_widget/event_hub';
@@ -16,6 +19,7 @@ describe('MRWidgetMerged', () => {
};
beforeEach(() => {
+ jest.spyOn(document, 'dispatchEvent');
const Component = Vue.extend(mergedComponent);
const mr = {
isRemovingSourceBranch: false,
@@ -147,6 +151,26 @@ describe('MRWidgetMerged', () => {
});
});
+ it('calls dispatchDocumentEvent to load in the modal component', () => {
+ expect(document.dispatchEvent).toHaveBeenCalledWith(new CustomEvent('merged:UpdateActions'));
+ });
+
+ it('emits event to open the revert modal on revert button click', () => {
+ const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
+
+ getByRole(vm.$el, 'button', { name: /Revert/i }).click();
+
+ expect(eventHubSpy).toHaveBeenCalledWith(OPEN_REVERT_MODAL);
+ });
+
+ it('emits event to open the cherry-pick modal on cherry-pick button click', () => {
+ const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
+
+ getByRole(vm.$el, 'button', { name: /Cherry-pick/i }).click();
+
+ expect(eventHubSpy).toHaveBeenCalledWith(OPEN_CHERRY_PICK_MODAL);
+ });
+
it('has merged by information', () => {
expect(vm.$el.textContent).toContain('Merged by');
expect(vm.$el.textContent).toContain('Administrator');
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
index 8847e4e6bdd..bd77a1d657e 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
@@ -1,25 +1,27 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import { removeBreakLine } from 'helpers/text_helper';
-import pipelineBlockedComponent from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue';
+import { shallowMount, mount } from '@vue/test-utils';
+import PipelineBlockedComponent from '~/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue';
describe('MRWidgetPipelineBlocked', () => {
- let vm;
- beforeEach(() => {
- const Component = Vue.extend(pipelineBlockedComponent);
- vm = mountComponent(Component);
- });
+ let wrapper;
+
+ const createWrapper = (mountFn = shallowMount) => {
+ wrapper = mountFn(PipelineBlockedComponent);
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders warning icon', () => {
- expect(vm.$el.querySelector('.ci-status-icon-warning')).not.toBe(null);
+ createWrapper(mount);
+
+ expect(wrapper.find('.ci-status-icon-warning').exists()).toBe(true);
});
it('renders information text', () => {
- expect(removeBreakLine(vm.$el.textContent).trim()).toContain(
+ createWrapper();
+
+ expect(wrapper.text()).toBe(
'Pipeline blocked. The pipeline for this merge request requires a manual action to proceed',
);
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
index 179adef12d9..3e0840fef4e 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
@@ -1,19 +1,30 @@
-import Vue from 'vue';
-import { removeBreakLine } from 'helpers/text_helper';
+import { shallowMount } from '@vue/test-utils';
+import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import PipelineFailed from '~/vue_merge_request_widget/components/states/pipeline_failed.vue';
describe('PipelineFailed', () => {
- describe('template', () => {
- const Component = Vue.extend(PipelineFailed);
- const vm = new Component({
- el: document.createElement('div'),
- });
- it('should have correct elements', () => {
- expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
- expect(removeBreakLine(vm.$el.innerText).trim()).toContain(
- 'The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure',
- );
- });
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(PipelineFailed);
+ };
+
+ const findStatusIcon = () => wrapper.find(statusIcon);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render error message with a disabled merge button', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('merge button should be disabled', () => {
+ expect(findStatusIcon().props('showDisabledButton')).toBe(true);
});
});
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 8eddf59820c..983e4a35078 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,14 +1,14 @@
-import Vue from 'vue';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-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 CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
+import Vue from 'vue';
+import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
+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 eventHub from '~/vue_merge_request_widget/event_hub';
+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 { MWPS_MERGE_STRATEGY, MTWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import simplePoll from '~/lib/utils/simple_poll';
+import eventHub from '~/vue_merge_request_widget/event_hub';
jest.mock('~/lib/utils/simple_poll', () =>
jest.fn().mockImplementation(jest.requireActual('~/lib/utils/simple_poll').default),
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
index 38920846a50..ef6a9b1e8fc 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
import { removeBreakLine } from 'helpers/text_helper';
+import mountComponent from 'helpers/vue_mount_component_helper';
import ShaMismatch from '~/vue_merge_request_widget/components/states/sha_mismatch.vue';
describe('ShaMismatch', () => {
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 cc160f6182d..8ead0002950 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,5 +1,5 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlFormCheckbox } from '@gitlab/ui';
+import { createLocalVue, 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';
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
index a5531577a8c..6c0d69ea109 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import UnresolvedDiscussions from '~/vue_merge_request_widget/components/states/unresolved_discussions.vue';
import notesEventHub from '~/notes/event_hub';
+import UnresolvedDiscussions from '~/vue_merge_request_widget/components/states/unresolved_discussions.vue';
function createComponent({ path = '' } = {}) {
return mount(UnresolvedDiscussions, {
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 6d63d4b1be3..e0077a008a2 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,7 +1,7 @@
import Vue from 'vue';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
import eventHub from '~/vue_merge_request_widget/event_hub';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
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 8da0d0f16d6..364f849eb4f 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,12 +1,12 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { invalidPlanWithName, plans, validPlanWithName } from './mock_data';
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';
import MrWidgetTerraformContainer from '~/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue';
-import Poll from '~/lib/utils/poll';
import TerraformPlan from '~/vue_merge_request_widget/components/terraform/terraform_plan.vue';
+import { invalidPlanWithName, plans, validPlanWithName } from './mock_data';
describe('MrWidgetTerraformConainer', () => {
let mock;
diff --git a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js b/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
index ea4eb44ebfe..f95a92c2cb1 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
+++ b/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
@@ -33,7 +33,7 @@ describe('TerraformPlan', () => {
it('diplays the header text with a name', () => {
expect(wrapper.text()).toContain(
- `The Terraform report ${validPlanWithName.job_name} was generated in your pipelines.`,
+ `The report ${validPlanWithName.job_name} was generated in your pipelines.`,
);
});
@@ -55,7 +55,7 @@ describe('TerraformPlan', () => {
});
it('diplays the header text without a name', () => {
- expect(wrapper.text()).toContain('A Terraform report was generated in your pipelines.');
+ expect(wrapper.text()).toContain('A report was generated in your pipelines.');
});
});
@@ -70,7 +70,7 @@ describe('TerraformPlan', () => {
it('diplays the header text with a name', () => {
expect(wrapper.text()).toContain(
- `The Terraform report ${invalidPlanWithName.job_name} failed to generate.`,
+ `The report ${invalidPlanWithName.job_name} failed to generate.`,
);
});
@@ -85,7 +85,7 @@ describe('TerraformPlan', () => {
});
it('diplays the header text without a name', () => {
- expect(wrapper.text()).toContain('A Terraform report failed to generate.');
+ expect(wrapper.text()).toContain('A report failed to generate.');
});
it('does not render button because url is missing', () => {
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
index bc0d2501809..8c5036e35f6 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
@@ -1,12 +1,12 @@
-import { mount } from '@vue/test-utils';
import { GlIcon, GlLoadingIcon, GlButton } from '@gitlab/ui';
-import DeploymentActionButton from '~/vue_merge_request_widget/components/deployment/deployment_action_button.vue';
+import { mount } from '@vue/test-utils';
import {
CREATED,
RUNNING,
DEPLOYING,
REDEPLOYING,
} from '~/vue_merge_request_widget/components/deployment/constants';
+import DeploymentActionButton from '~/vue_merge_request_widget/components/deployment/deployment_action_button.vue';
import { actionButtonMocks } from './deployment_mock_data';
const baseProps = {
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 13c0665f929..22e58ac6abf 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js
@@ -1,8 +1,6 @@
import { mount } from '@vue/test-utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
-import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
-import DeploymentActions from '~/vue_merge_request_widget/components/deployment/deployment_actions.vue';
import {
CREATED,
MANUAL_DEPLOY,
@@ -11,6 +9,8 @@ import {
REDEPLOYING,
STOPPING,
} from '~/vue_merge_request_widget/components/deployment/constants';
+import DeploymentActions from '~/vue_merge_request_widget/components/deployment/deployment_actions.vue';
+import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import {
actionButtonMocks,
deploymentMockData,
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
index 87bf32351bd..c27cbd8b781 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
@@ -1,7 +1,4 @@
import { mount } from '@vue/test-utils';
-import DeploymentComponent from '~/vue_merge_request_widget/components/deployment/deployment.vue';
-import DeploymentInfo from '~/vue_merge_request_widget/components/deployment/deployment_info.vue';
-import DeploymentViewButton from '~/vue_merge_request_widget/components/deployment/deployment_view_button.vue';
import {
CREATED,
RUNNING,
@@ -10,6 +7,9 @@ import {
CANCELED,
SKIPPED,
} from '~/vue_merge_request_widget/components/deployment/constants';
+import DeploymentComponent from '~/vue_merge_request_widget/components/deployment/deployment.vue';
+import DeploymentInfo from '~/vue_merge_request_widget/components/deployment/deployment_info.vue';
+import DeploymentViewButton from '~/vue_merge_request_widget/components/deployment/deployment_view_button.vue';
import { deploymentMockData, playDetails, retryDetails } from './deployment_mock_data';
describe('Deployment component', () => {
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
index 1ea7fe1fbfe..7b020813bd5 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -1,28 +1,26 @@
import { mount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import Api from '~/api';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { securityReportDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
import axios from '~/lib/utils/axios_utils';
-import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
-import eventHub from '~/vue_merge_request_widget/event_hub';
+import { setFaviconOverlay } from '~/lib/utils/favicon';
import notify from '~/lib/utils/notify';
import SmartInterval from '~/smart_interval';
-import { setFaviconOverlay } from '~/lib/utils/favicon';
+import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
-import mockData from './mock_data';
+import securityReportDownloadPathsQuery from '~/vue_shared/security_reports/queries/security_report_download_paths.query.graphql';
import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
-import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants';
+import mockData from './mock_data';
jest.mock('~/smart_interval');
jest.mock('~/lib/utils/favicon');
-const returnPromise = (data) =>
- new Promise((resolve) => {
- resolve({
- data,
- });
- });
+Vue.use(VueApollo);
describe('MrWidgetOptions', () => {
let wrapper;
@@ -48,7 +46,7 @@ describe('MrWidgetOptions', () => {
gon.features = {};
});
- const createComponent = (mrData = mockData) => {
+ const createComponent = (mrData = mockData, options = {}) => {
if (wrapper) {
wrapper.destroy();
}
@@ -57,6 +55,7 @@ describe('MrWidgetOptions', () => {
propsData: {
mrData: { ...mrData },
},
+ ...options,
});
return axios.waitForAll();
@@ -68,6 +67,7 @@ describe('MrWidgetOptions', () => {
describe('default', () => {
beforeEach(() => {
+ jest.spyOn(document, 'dispatchEvent');
return createComponent();
});
@@ -281,7 +281,7 @@ describe('MrWidgetOptions', () => {
let isCbExecuted;
beforeEach(() => {
- jest.spyOn(wrapper.vm.service, 'checkStatus').mockReturnValue(returnPromise(mockData));
+ jest.spyOn(wrapper.vm.service, 'checkStatus').mockResolvedValue({ data: mockData });
jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'handleNotification').mockImplementation(() => {});
@@ -331,7 +331,7 @@ describe('MrWidgetOptions', () => {
it('should fetch deployments', () => {
jest
.spyOn(wrapper.vm.service, 'fetchDeployments')
- .mockReturnValue(returnPromise([{ id: 1, status: SUCCESS }]));
+ .mockResolvedValue({ data: [{ id: 1, status: SUCCESS }] });
wrapper.vm.fetchPreMergeDeployments();
@@ -347,13 +347,16 @@ describe('MrWidgetOptions', () => {
it('should fetch content of Cherry Pick and Revert modals', () => {
jest
.spyOn(wrapper.vm.service, 'fetchMergeActionsContent')
- .mockReturnValue(returnPromise('hello world'));
+ .mockResolvedValue({ data: 'hello world' });
wrapper.vm.fetchActionsContent();
return nextTick().then(() => {
expect(wrapper.vm.service.fetchMergeActionsContent).toHaveBeenCalled();
expect(document.body.textContent).toContain('hello world');
+ expect(document.dispatchEvent).toHaveBeenCalledWith(
+ new CustomEvent('merged:UpdateActions'),
+ );
});
});
});
@@ -822,36 +825,34 @@ describe('MrWidgetOptions', () => {
describe('security widget', () => {
describe.each`
- context | hasPipeline | reportType | isFlagEnabled | shouldRender
- ${'security report and flag enabled'} | ${true} | ${'sast'} | ${true} | ${true}
- ${'security report and flag disabled'} | ${true} | ${'sast'} | ${false} | ${false}
- ${'no security report and flag enabled'} | ${true} | ${'foo'} | ${true} | ${false}
- ${'no pipeline and flag enabled'} | ${false} | ${'sast'} | ${true} | ${false}
- `('given $context', ({ hasPipeline, reportType, isFlagEnabled, shouldRender }) => {
+ context | hasPipeline | shouldRender
+ ${'there is a pipeline'} | ${true} | ${true}
+ ${'no pipeline'} | ${false} | ${false}
+ `('given $context', ({ hasPipeline, shouldRender }) => {
beforeEach(() => {
- gon.features.coreSecurityMrWidget = isFlagEnabled;
+ const mrData = {
+ ...mockData,
+ ...(hasPipeline ? {} : { pipeline: null }),
+ };
- if (hasPipeline) {
- jest.spyOn(Api, 'pipelineJobs').mockResolvedValue({
- data: [{ artifacts: [{ file_type: reportType }] }],
- });
- }
+ // Override top-level mocked requests, which always use a fresh copy of
+ // mockData, which always includes the full pipeline object.
+ mock.onGet(mockData.merge_request_widget_path).reply(() => [200, mrData]);
+ mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, mrData]);
- return createComponent({
- ...mockData,
- ...(hasPipeline ? {} : { pipeline: undefined }),
+ return createComponent(mrData, {
+ apolloProvider: createMockApollo([
+ [
+ securityReportDownloadPathsQuery,
+ async () => ({ data: securityReportDownloadPathsQueryResponse }),
+ ],
+ ]),
});
});
- if (shouldRender) {
- it('renders', () => {
- expect(findSecurityMrWidget().exists()).toBe(true);
- });
- } else {
- it('does not render', () => {
- expect(findSecurityMrWidget().exists()).toBe(false);
- });
- }
+ it(shouldRender ? 'renders' : 'does not render', () => {
+ expect(findSecurityMrWidget().exists()).toBe(shouldRender);
+ });
});
});
diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js b/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js
index 1dfa7564535..9423fa17c44 100644
--- a/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import testAction from 'helpers/vuex_action_helper';
import axios from '~/lib/utils/axios_utils';
import {
setEndpoint,
@@ -11,8 +11,8 @@ import {
receiveArtifactsSuccess,
receiveArtifactsError,
} from '~/vue_merge_request_widget/stores/artifacts_list/actions';
-import state from '~/vue_merge_request_widget/stores/artifacts_list/state';
import * as types from '~/vue_merge_request_widget/stores/artifacts_list/mutation_types';
+import state from '~/vue_merge_request_widget/stores/artifacts_list/state';
describe('Artifacts App Store Actions', () => {
let mockedState;
diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js b/spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js
index ea89fdb72e9..a4e6788c7f6 100644
--- a/spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js
@@ -1,6 +1,6 @@
-import state from '~/vue_merge_request_widget/stores/artifacts_list/state';
-import mutations from '~/vue_merge_request_widget/stores/artifacts_list/mutations';
import * as types from '~/vue_merge_request_widget/stores/artifacts_list/mutation_types';
+import mutations from '~/vue_merge_request_widget/stores/artifacts_list/mutations';
+import state from '~/vue_merge_request_widget/stores/artifacts_list/state';
describe('Artifacts Store Mutations', () => {
let stateCopy;
diff --git a/spec/frontend/vue_shared/alert_details/alert_details_spec.js b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
new file mode 100644
index 00000000000..dd9a7be6268
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
@@ -0,0 +1,361 @@
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { joinPaths } from '~/lib/utils/url_utility';
+import Tracking from '~/tracking';
+import AlertDetails from '~/vue_shared/alert_details/components/alert_details.vue';
+import AlertSummaryRow from '~/vue_shared/alert_details/components/alert_summary_row.vue';
+import { SEVERITY_LEVELS } from '~/vue_shared/alert_details/constants';
+import createIssueMutation from '~/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import mockAlerts from './mocks/alerts.json';
+
+const mockAlert = mockAlerts[0];
+const environmentName = 'Production';
+const environmentPath = '/fake/path';
+
+describe('AlertDetails', () => {
+ let environmentData = { name: environmentName, path: environmentPath };
+ let mock;
+ let wrapper;
+ const projectPath = 'root/alerts';
+ const projectIssuesPath = 'root/alerts/-/issues';
+ const projectId = '1';
+ const $router = { replace: jest.fn() };
+
+ function mountComponent({
+ data,
+ loading = false,
+ mountMethod = shallowMount,
+ provide = {},
+ stubs = {},
+ } = {}) {
+ wrapper = extendedWrapper(
+ mountMethod(AlertDetails, {
+ provide: {
+ alertId: 'alertId',
+ projectPath,
+ projectIssuesPath,
+ projectId,
+ ...provide,
+ },
+ data() {
+ return {
+ alert: {
+ ...mockAlert,
+ environment: environmentData,
+ },
+ sidebarStatus: false,
+ ...data,
+ };
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ queries: {
+ alert: {
+ loading,
+ },
+ sidebarStatus: {},
+ },
+ },
+ $router,
+ $route: { params: {} },
+ },
+ stubs: {
+ ...stubs,
+ AlertSummaryRow,
+ },
+ }),
+ );
+ }
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ mock.restore();
+ });
+
+ const findCreateIncidentBtn = () => wrapper.findByTestId('createIncidentBtn');
+ const findViewIncidentBtn = () => wrapper.findByTestId('viewIncidentBtn');
+ const findIncidentCreationAlert = () => wrapper.findByTestId('incidentCreationError');
+ const findEnvironmentName = () => wrapper.findByTestId('environmentName');
+ const findEnvironmentPath = () => wrapper.findByTestId('environmentPath');
+ const findDetailsTable = () => wrapper.find(AlertDetailsTable);
+ const findMetricsTab = () => wrapper.findByTestId('metrics');
+
+ describe('Alert details', () => {
+ describe('when alert is null', () => {
+ beforeEach(() => {
+ mountComponent({ data: { alert: null } });
+ });
+
+ it('shows an empty state', () => {
+ expect(wrapper.findByTestId('alertDetailsTabs').exists()).toBe(false);
+ });
+ });
+
+ describe('when alert is present', () => {
+ beforeEach(() => {
+ mountComponent({ data: { alert: mockAlert } });
+ });
+
+ it('renders a tab with overview information', () => {
+ expect(wrapper.findByTestId('overview').exists()).toBe(true);
+ });
+
+ it('renders a tab with an activity feed', () => {
+ expect(wrapper.findByTestId('activity').exists()).toBe(true);
+ });
+
+ it('renders severity', () => {
+ expect(wrapper.findByTestId('severity').text()).toBe(SEVERITY_LEVELS[mockAlert.severity]);
+ });
+
+ it('renders a title', () => {
+ expect(wrapper.findByTestId('title').text()).toBe(mockAlert.title);
+ });
+
+ it('renders a start time', () => {
+ expect(wrapper.findByTestId('startTimeItem').exists()).toBe(true);
+ expect(wrapper.findByTestId('startTimeItem').props('time')).toBe(mockAlert.startedAt);
+ });
+ });
+
+ describe('individual alert fields', () => {
+ describe.each`
+ field | data | isShown
+ ${'eventCount'} | ${1} | ${true}
+ ${'eventCount'} | ${undefined} | ${false}
+ ${'monitoringTool'} | ${'New Relic'} | ${true}
+ ${'monitoringTool'} | ${undefined} | ${false}
+ ${'service'} | ${'Prometheus'} | ${true}
+ ${'service'} | ${undefined} | ${false}
+ ${'runbook'} | ${undefined} | ${false}
+ ${'runbook'} | ${'run.com'} | ${true}
+ `(`$desc`, ({ field, data, isShown }) => {
+ beforeEach(() => {
+ mountComponent({ data: { alert: { ...mockAlert, [field]: data } } });
+ });
+
+ it(`${field} is ${isShown ? 'displayed' : 'hidden'} correctly`, () => {
+ const element = wrapper.findByTestId(field);
+ if (isShown) {
+ expect(element.text()).toContain(data.toString());
+ } else {
+ expect(wrapper.findByTestId(field).exists()).toBe(false);
+ }
+ });
+ });
+ });
+
+ describe('environment fields', () => {
+ it('should show the environment name with a link to the path', () => {
+ mountComponent();
+ const path = findEnvironmentPath();
+
+ expect(findEnvironmentName().exists()).toBe(false);
+ expect(path.text()).toBe(environmentName);
+ expect(path.attributes('href')).toBe(environmentPath);
+ });
+
+ it('should only show the environment name if the path is not provided', () => {
+ environmentData = { name: environmentName, path: null };
+ mountComponent();
+
+ expect(findEnvironmentPath().exists()).toBe(false);
+ expect(findEnvironmentName().text()).toBe(environmentName);
+ });
+ });
+
+ describe('Threat Monitoring details', () => {
+ it('should not render the metrics tab', () => {
+ mountComponent({
+ data: { alert: mockAlert, provide: { isThreatMonitoringPage: true } },
+ });
+ expect(findMetricsTab().exists()).toBe(false);
+ });
+ });
+
+ describe('Create incident from alert', () => {
+ it('should display "View incident" button that links the incident page when incident exists', () => {
+ const issueIid = '3';
+ mountComponent({
+ data: { alert: { ...mockAlert, issueIid }, sidebarStatus: false },
+ });
+
+ expect(findViewIncidentBtn().exists()).toBe(true);
+ expect(findViewIncidentBtn().attributes('href')).toBe(
+ joinPaths(projectIssuesPath, issueIid),
+ );
+ expect(findCreateIncidentBtn().exists()).toBe(false);
+ });
+
+ it('should display "Create incident" button when incident doesn\'t exist yet', () => {
+ const issueIid = null;
+ mountComponent({
+ mountMethod: mount,
+ data: { alert: { ...mockAlert, issueIid } },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findViewIncidentBtn().exists()).toBe(false);
+ expect(findCreateIncidentBtn().exists()).toBe(true);
+ });
+ });
+
+ it('calls `$apollo.mutate` with `createIssueQuery`', () => {
+ const issueIid = '10';
+ mountComponent({
+ mountMethod: mount,
+ data: { alert: { ...mockAlert } },
+ });
+
+ jest
+ .spyOn(wrapper.vm.$apollo, 'mutate')
+ .mockResolvedValue({ data: { createAlertIssue: { issue: { iid: issueIid } } } });
+ findCreateIncidentBtn().trigger('click');
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createIssueMutation,
+ variables: {
+ iid: mockAlert.iid,
+ projectPath,
+ },
+ });
+ });
+
+ it('shows error alert when incident creation fails ', async () => {
+ const errorMsg = 'Something went wrong';
+ mountComponent({
+ mountMethod: mount,
+ data: { alert: { ...mockAlert, alertIid: 1 } },
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
+ findCreateIncidentBtn().trigger('click');
+
+ await waitForPromises();
+ expect(findIncidentCreationAlert().text()).toBe(errorMsg);
+ });
+ });
+
+ describe('View full alert details', () => {
+ beforeEach(() => {
+ mountComponent({ data: { alert: mockAlert } });
+ });
+
+ it('should display a table of raw alert details data', () => {
+ expect(findDetailsTable().exists()).toBe(true);
+ });
+ });
+
+ describe('loading state', () => {
+ beforeEach(() => {
+ mountComponent({ loading: true });
+ });
+
+ it('displays a loading state when loading', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+
+ describe('error state', () => {
+ it('displays a error state correctly', () => {
+ mountComponent({ data: { errored: true } });
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+ });
+
+ it('renders html-errors correctly', () => {
+ mountComponent({
+ data: { errored: true, sidebarErrorMessage: '<span data-testid="htmlError" />' },
+ });
+ expect(wrapper.findByTestId('htmlError').exists()).toBe(true);
+ });
+
+ it('does not display an error when dismissed', () => {
+ mountComponent({ data: { errored: true, isErrorDismissed: true } });
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
+ });
+ });
+
+ describe('header', () => {
+ const findHeader = () => wrapper.findByTestId('alert-header');
+ const stubs = { TimeAgoTooltip: { template: '<span>now</span>' } };
+
+ describe('individual header fields', () => {
+ describe.each`
+ createdAt | monitoringTool | result
+ ${'2020-04-17T23:18:14.996Z'} | ${null} | ${'Alert Reported now'}
+ ${'2020-04-17T23:18:14.996Z'} | ${'Datadog'} | ${'Alert Reported now by Datadog'}
+ `(
+ `When createdAt=$createdAt, monitoringTool=$monitoringTool`,
+ ({ createdAt, monitoringTool, result }) => {
+ beforeEach(() => {
+ mountComponent({
+ data: { alert: { ...mockAlert, createdAt, monitoringTool } },
+ mountMethod: mount,
+ stubs,
+ });
+ });
+
+ it('header text is shown correctly', () => {
+ expect(findHeader().text()).toBe(result);
+ });
+ },
+ );
+ });
+ });
+
+ describe('tab navigation', () => {
+ beforeEach(() => {
+ mountComponent({ data: { alert: mockAlert } });
+ });
+
+ it.each`
+ index | tabId
+ ${0} | ${'overview'}
+ ${1} | ${'metrics'}
+ ${2} | ${'activity'}
+ `('will navigate to the correct tab via $tabId', ({ index, tabId }) => {
+ wrapper.setData({ currentTabIndex: index });
+ expect($router.replace).toHaveBeenCalledWith({ name: 'tab', params: { tabId } });
+ });
+ });
+ });
+
+ describe('Snowplow tracking', () => {
+ const mountOptions = {
+ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
+ data: { alert: mockAlert },
+ loading: false,
+ };
+
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ });
+
+ it('should not track alert details page views when the tracking options do not exist', () => {
+ mountComponent(mountOptions);
+ expect(Tracking.event).not.toHaveBeenCalled();
+ });
+
+ it('should track alert details page views when the tracking options exist', () => {
+ const trackAlertsDetailsViewsOptions = {
+ category: 'Alert Management',
+ action: 'view_alert_details',
+ };
+ mountComponent({ ...mountOptions, provide: { trackAlertsDetailsViewsOptions } });
+ const { category, action } = trackAlertsDetailsViewsOptions;
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
+ });
+ });
+});
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
new file mode 100644
index 00000000000..87ad5e36564
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/alert_management_sidebar_todo_spec.js
@@ -0,0 +1,112 @@
+import { mount } from '@vue/test-utils';
+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';
+import mockAlerts from './mocks/alerts.json';
+
+const mockAlert = mockAlerts[0];
+
+describe('Alert Details Sidebar To Do', () => {
+ let wrapper;
+
+ function mountComponent({ data, sidebarCollapsed = true, loading = false, stubs = {} } = {}) {
+ wrapper = mount(SidebarTodo, {
+ propsData: {
+ alert: { ...mockAlert },
+ ...data,
+ sidebarCollapsed,
+ projectPath: 'projectPath',
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ queries: {
+ alert: {
+ loading,
+ },
+ },
+ },
+ },
+ stubs,
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findToDoButton = () => wrapper.find('[data-testid="alert-todo-button"]');
+
+ describe('updating the alert to do', () => {
+ const mockUpdatedMutationResult = {
+ data: {
+ updateAlertTodo: {
+ errors: [],
+ alert: {},
+ },
+ },
+ };
+
+ describe('adding a todo', () => {
+ beforeEach(() => {
+ mountComponent({
+ data: { alert: mockAlert },
+ sidebarCollapsed: false,
+ loading: false,
+ });
+ });
+
+ it('renders a button for adding a To-Do', async () => {
+ await wrapper.vm.$nextTick();
+
+ expect(findToDoButton().text()).toBe('Add a to do');
+ });
+
+ it('calls `$apollo.mutate` with `createAlertTodoMutation` mutation and variables containing `iid`, `todoEvent`, & `projectPath`', async () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
+
+ findToDoButton().trigger('click');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: createAlertTodoMutation,
+ variables: {
+ iid: '1527542',
+ projectPath: 'projectPath',
+ },
+ });
+ });
+ });
+
+ describe('removing a todo', () => {
+ beforeEach(() => {
+ mountComponent({
+ data: { alert: { ...mockAlert, todos: { nodes: [{ id: '1234' }] } } },
+ sidebarCollapsed: false,
+ loading: false,
+ });
+ });
+
+ it('renders a Mark As Done button when todo is present', async () => {
+ await wrapper.vm.$nextTick();
+
+ expect(findToDoButton().text()).toBe('Mark as done');
+ });
+
+ it('calls `$apollo.mutate` with `todoMarkDoneMutation` mutation and variables containing `id`', async () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
+
+ findToDoButton().trigger('click');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: todoMarkDoneMutation,
+ update: expect.anything(),
+ variables: {
+ id: '1234',
+ },
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js b/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
new file mode 100644
index 00000000000..b5a61a4adc1
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
@@ -0,0 +1,62 @@
+import { shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+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';
+
+jest.mock('~/monitoring/stores', () => ({
+ monitoringDashboard: {},
+}));
+
+jest.mock('~/monitoring/components/embeds/metric_embed.vue', () => ({
+ render(h) {
+ return h('div');
+ },
+}));
+
+describe('Alert Metrics', () => {
+ let wrapper;
+ const mock = new MockAdapter(axios);
+
+ function mountComponent({ props } = {}) {
+ wrapper = shallowMount(AlertMetrics, {
+ propsData: {
+ ...props,
+ },
+ });
+ }
+
+ const findChart = () => wrapper.find(MetricEmbed);
+ const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ afterAll(() => {
+ mock.restore();
+ });
+
+ describe('Empty state', () => {
+ it('should display a message when metrics dashboard url is not provided ', () => {
+ mountComponent();
+ expect(findChart().exists()).toBe(false);
+ expect(findEmptyState().text()).toBe("Metrics weren't available in the alerts payload.");
+ });
+ });
+
+ describe('Chart', () => {
+ it('should be rendered when dashboard url is provided', async () => {
+ mountComponent({ props: { dashboardUrl: 'metrics.url' } });
+
+ await waitForPromises();
+ await wrapper.vm.$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
new file mode 100644
index 00000000000..a866fc13539
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
@@ -0,0 +1,166 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import waitForPromises from 'helpers/wait_for_promises';
+import updateAlertStatusMutation from '~/graphql_shared//mutations/alert_status_update.mutation.graphql';
+import Tracking from '~/tracking';
+import AlertManagementStatus from '~/vue_shared/alert_details/components/alert_status.vue';
+import mockAlerts from './mocks/alerts.json';
+
+const mockAlert = mockAlerts[0];
+
+describe('AlertManagementStatus', () => {
+ let wrapper;
+ const findStatusDropdown = () => wrapper.find(GlDropdown);
+ const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
+
+ const selectFirstStatusOption = () => {
+ findFirstStatusOption().vm.$emit('click');
+
+ return waitForPromises();
+ };
+
+ function mountComponent({ props = {}, provide = {}, loading = false, stubs = {} } = {}) {
+ wrapper = shallowMount(AlertManagementStatus, {
+ propsData: {
+ alert: { ...mockAlert },
+ projectPath: 'gitlab-org/gitlab',
+ isSidebar: false,
+ ...props,
+ },
+ provide,
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ queries: {
+ alert: {
+ loading,
+ },
+ },
+ },
+ },
+ stubs,
+ });
+ }
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('updating the alert status', () => {
+ const iid = '1527542';
+ const mockUpdatedMutationResult = {
+ data: {
+ updateAlertStatus: {
+ errors: [],
+ alert: {
+ iid,
+ status: 'acknowledged',
+ },
+ },
+ },
+ };
+
+ beforeEach(() => {
+ mountComponent({});
+ });
+
+ it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
+ findFirstStatusOption().vm.$emit('click');
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updateAlertStatusMutation,
+ variables: {
+ iid,
+ status: 'TRIGGERED',
+ projectPath: 'gitlab-org/gitlab',
+ },
+ });
+ });
+
+ describe('when a request fails', () => {
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
+ });
+
+ it('emits an error', async () => {
+ await selectFirstStatusOption();
+
+ expect(wrapper.emitted('alert-error')[0]).toEqual([
+ 'There was an error while updating the status of the alert. Please try again.',
+ ]);
+ });
+
+ it('emits an error when triggered a second time', async () => {
+ await selectFirstStatusOption();
+ await wrapper.vm.$nextTick();
+ await selectFirstStatusOption();
+ // Should emit two errors [0,1]
+ expect(wrapper.emitted('alert-error').length > 1).toBe(true);
+ });
+ });
+
+ it('shows an error when response includes HTML errors', async () => {
+ const mockUpdatedMutationErrorResult = {
+ data: {
+ updateAlertStatus: {
+ errors: ['<span data-testid="htmlError" />'],
+ alert: {
+ iid,
+ status: 'acknowledged',
+ },
+ },
+ },
+ };
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationErrorResult);
+
+ await selectFirstStatusOption();
+
+ expect(wrapper.emitted('alert-error').length > 0).toBe(true);
+ expect(wrapper.emitted('alert-error')[0]).toEqual([
+ 'There was an error while updating the status of the alert. <span data-testid="htmlError" />',
+ ]);
+ });
+ });
+
+ describe('Snowplow tracking', () => {
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ });
+
+ it('should not track alert status updates when the tracking options do not exist', () => {
+ mountComponent({});
+ Tracking.event.mockClear();
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
+ findFirstStatusOption().vm.$emit('click');
+ setImmediate(() => {
+ expect(Tracking.event).not.toHaveBeenCalled();
+ });
+ });
+
+ it('should track alert status updates when the tracking options exist', () => {
+ const trackAlertStatusUpdateOptions = {
+ category: 'Alert Management',
+ action: 'update_alert_status',
+ label: 'Status',
+ };
+ mountComponent({ provide: { trackAlertStatusUpdateOptions } });
+ Tracking.event.mockClear();
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
+ findFirstStatusOption().vm.$emit('click');
+ const status = findFirstStatusOption().text();
+ setImmediate(() => {
+ const { category, action, label } = trackAlertStatusUpdateOptions;
+ expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property: status });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/alert_details/alert_summary_row_spec.js b/spec/frontend/vue_shared/alert_details/alert_summary_row_spec.js
new file mode 100644
index 00000000000..a2981478954
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/alert_summary_row_spec.js
@@ -0,0 +1,40 @@
+import { shallowMount } from '@vue/test-utils';
+import AlertSummaryRow from '~/vue_shared/alert_details/components/alert_summary_row.vue';
+
+const label = 'a label';
+const value = 'a value';
+
+describe('AlertSummaryRow', () => {
+ let wrapper;
+
+ function mountComponent({ mountMethod = shallowMount, props, defaultSlot } = {}) {
+ wrapper = mountMethod(AlertSummaryRow, {
+ propsData: props,
+ scopedSlots: {
+ default: defaultSlot,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('Alert Summary Row', () => {
+ beforeEach(() => {
+ mountComponent({
+ props: {
+ label,
+ },
+ defaultSlot: `<span class="value">${value}</span>`,
+ });
+ });
+
+ it('should display a label and a value', () => {
+ expect(wrapper.text()).toBe(`${label} ${value}`);
+ });
+ });
+});
diff --git a/spec/frontend/alert_management/mocks/alerts.json b/spec/frontend/vue_shared/alert_details/mocks/alerts.json
index 5267a4fe50d..5267a4fe50d 100644
--- a/spec/frontend/alert_management/mocks/alerts.json
+++ b/spec/frontend/vue_shared/alert_details/mocks/alerts.json
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_managment_sidebar_assignees_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_managment_sidebar_assignees_spec.js
new file mode 100644
index 00000000000..28646994ed1
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_managment_sidebar_assignees_spec.js
@@ -0,0 +1,173 @@
+import { GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import SidebarAssignee from '~/vue_shared/alert_details/components/sidebar/sidebar_assignee.vue';
+import SidebarAssignees from '~/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue';
+import AlertSetAssignees from '~/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql';
+import mockAlerts from '../mocks/alerts.json';
+
+const mockAlert = mockAlerts[0];
+
+describe('Alert Details Sidebar Assignees', () => {
+ let wrapper;
+ let mock;
+
+ function mountComponent({
+ data,
+ users = [],
+ isDropdownSearching = false,
+ sidebarCollapsed = true,
+ loading = false,
+ stubs = {},
+ } = {}) {
+ wrapper = shallowMount(SidebarAssignees, {
+ data() {
+ return {
+ users,
+ isDropdownSearching,
+ };
+ },
+ propsData: {
+ alert: { ...mockAlert },
+ ...data,
+ sidebarCollapsed,
+ projectPath: 'projectPath',
+ projectId: '1',
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ queries: {
+ alert: {
+ loading,
+ },
+ },
+ },
+ },
+ stubs,
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ mock.restore();
+ });
+
+ const findAssigned = () => wrapper.find('[data-testid="assigned-users"]');
+ const findUnassigned = () => wrapper.find('[data-testid="unassigned-users"]');
+
+ describe('updating the alert status', () => {
+ const mockUpdatedMutationResult = {
+ data: {
+ alertSetAssignees: {
+ errors: [],
+ alert: {
+ assigneeUsernames: ['root'],
+ },
+ },
+ },
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ const path = '/-/autocomplete/users.json';
+ const users = [
+ {
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ id: 1,
+ name: 'User 1',
+ username: 'root',
+ },
+ {
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ id: 2,
+ name: 'User 2',
+ username: 'not-root',
+ },
+ ];
+
+ mock.onGet(path).replyOnce(200, users);
+ mountComponent({
+ data: { alert: mockAlert },
+ sidebarCollapsed: false,
+ loading: false,
+ users,
+ stubs: {
+ SidebarAssignee,
+ },
+ });
+ });
+
+ it('renders a unassigned option', async () => {
+ wrapper.setData({ isDropdownSearching: false });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find(GlDropdownItem).text()).toBe('Unassigned');
+ });
+
+ it('calls `$apollo.mutate` with `AlertSetAssignees` mutation and variables containing `iid`, `assigneeUsernames`, & `projectPath`', async () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
+ wrapper.setData({ isDropdownSearching: false });
+
+ await wrapper.vm.$nextTick();
+ wrapper.find(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: AlertSetAssignees,
+ variables: {
+ iid: '1527542',
+ assigneeUsernames: ['root'],
+ projectPath: 'projectPath',
+ },
+ });
+ });
+
+ it('emits an error when request contains error messages', () => {
+ wrapper.setData({ isDropdownSearching: false });
+ const errorMutationResult = {
+ data: {
+ alertSetAssignees: {
+ errors: ['There was a problem for sure.'],
+ alert: {},
+ },
+ },
+ };
+
+ 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();
+ });
+ });
+
+ it('stops updating and cancels loading when the request fails', () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
+ wrapper.vm.updateAlertAssignees('root');
+ expect(findUnassigned().text()).toBe('assign yourself');
+ });
+
+ it('shows a user avatar, username and full name when a user is set', () => {
+ mountComponent({
+ data: { alert: mockAlerts[1] },
+ sidebarCollapsed: false,
+ loading: false,
+ stubs: {
+ SidebarAssignee,
+ },
+ });
+
+ expect(findAssigned().find('img').attributes('src')).toBe('/url');
+ expect(findAssigned().find('.dropdown-menu-user-full-name').text()).toBe('root');
+ expect(findAssigned().find('.dropdown-menu-user-username').text()).toBe('@root');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
new file mode 100644
index 00000000000..70cf2597963
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
@@ -0,0 +1,95 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import AlertSidebar from '~/vue_shared/alert_details/components/alert_sidebar.vue';
+import SidebarAssignees from '~/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue';
+import SidebarStatus from '~/vue_shared/alert_details/components/sidebar/sidebar_status.vue';
+import mockAlerts from '../mocks/alerts.json';
+
+const mockAlert = mockAlerts[0];
+
+describe('Alert Details Sidebar', () => {
+ let wrapper;
+ let mock;
+
+ function mountComponent({
+ mountMethod = shallowMount,
+ stubs = {},
+ alert = {},
+ provide = {},
+ } = {}) {
+ wrapper = mountMethod(AlertSidebar, {
+ data() {
+ return {
+ sidebarStatus: false,
+ };
+ },
+ propsData: {
+ alert,
+ },
+ provide: {
+ projectPath: 'projectPath',
+ projectId: '1',
+ ...provide,
+ },
+ stubs,
+ mocks: {
+ $apollo: {
+ queries: {
+ sidebarStatus: {},
+ },
+ },
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ mock.restore();
+ });
+
+ describe('the sidebar renders', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mountComponent();
+ });
+
+ it('open as default', () => {
+ expect(wrapper.classes('right-sidebar-expanded')).toBe(true);
+ });
+
+ it('should render side bar assignee dropdown', () => {
+ mountComponent({
+ mountMethod: mount,
+ alert: mockAlert,
+ });
+ expect(wrapper.find(SidebarAssignees).exists()).toBe(true);
+ });
+
+ it('should render side bar status dropdown', () => {
+ mountComponent({
+ mountMethod: mount,
+ alert: mockAlert,
+ });
+ expect(wrapper.find(SidebarStatus).exists()).toBe(true);
+ });
+ });
+
+ describe('the sidebar renders for threat monitoring', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mountComponent();
+ });
+
+ it('should not render side bar status dropdown', () => {
+ mountComponent({
+ mountMethod: mount,
+ alert: mockAlert,
+ provide: { isThreatMonitoringPage: true },
+ });
+ expect(wrapper.find(SidebarStatus).exists()).toBe(false);
+ });
+ });
+});
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
new file mode 100644
index 00000000000..f5b9efb4d98
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_status_spec.js
@@ -0,0 +1,103 @@
+import { GlDropdown, GlDropdownItem, GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import updateAlertStatusMutation from '~/graphql_shared/mutations/alert_status_update.mutation.graphql';
+import AlertSidebarStatus from '~/vue_shared/alert_details/components/sidebar/sidebar_status.vue';
+import mockAlerts from '../mocks/alerts.json';
+
+const mockAlert = mockAlerts[0];
+
+describe('Alert Details Sidebar Status', () => {
+ let wrapper;
+ const findStatusDropdown = () => wrapper.find(GlDropdown);
+ const findStatusDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findStatusLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findStatusDropdownHeader = () => wrapper.find('[data-testid="dropdown-header"]');
+
+ function mountComponent({ data, sidebarCollapsed = true, loading = false, stubs = {} } = {}) {
+ wrapper = mount(AlertSidebarStatus, {
+ propsData: {
+ alert: { ...mockAlert },
+ ...data,
+ sidebarCollapsed,
+ projectPath: 'projectPath',
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ queries: {
+ alert: {
+ loading,
+ },
+ },
+ },
+ },
+ stubs,
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('Alert Sidebar Dropdown Status', () => {
+ beforeEach(() => {
+ mountComponent({
+ data: { alert: mockAlert },
+ sidebarCollapsed: false,
+ loading: false,
+ });
+ });
+
+ it('displays status dropdown', () => {
+ expect(findStatusDropdown().exists()).toBe(true);
+ });
+
+ it('displays the dropdown status header', () => {
+ expect(findStatusDropdownHeader().exists()).toBe(true);
+ });
+
+ describe('updating the alert status', () => {
+ const mockUpdatedMutationResult = {
+ data: {
+ updateAlertStatus: {
+ errors: [],
+ alert: {
+ status: 'acknowledged',
+ },
+ },
+ },
+ };
+
+ beforeEach(() => {
+ mountComponent({
+ data: { alert: mockAlert },
+ sidebarCollapsed: false,
+ loading: false,
+ });
+ });
+
+ it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
+ findStatusDropdownItem().vm.$emit('click');
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updateAlertStatusMutation,
+ variables: {
+ iid: '1527542',
+ status: 'TRIGGERED',
+ projectPath: 'projectPath',
+ },
+ });
+ });
+
+ it('stops updating when the request fails', () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
+ findStatusDropdownItem().vm.$emit('click');
+ expect(findStatusLoadingIcon().exists()).toBe(false);
+ expect(wrapper.find('[data-testid="status"]').text()).toBe('Triggered');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js b/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js
new file mode 100644
index 00000000000..a5a9fb55737
--- /dev/null
+++ b/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js
@@ -0,0 +1,40 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import SystemNote from '~/vue_shared/alert_details/components/system_notes/system_note.vue';
+import mockAlerts from '../mocks/alerts.json';
+
+const mockAlert = mockAlerts[1];
+
+describe('Alert Details System Note', () => {
+ let wrapper;
+
+ function mountComponent({ stubs = {} } = {}) {
+ wrapper = shallowMount(SystemNote, {
+ propsData: {
+ note: { ...mockAlert.notes.nodes[0] },
+ },
+ stubs,
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('System notes', () => {
+ beforeEach(() => {
+ mountComponent({});
+ });
+
+ it('renders the correct system note', () => {
+ const noteId = wrapper.find('.note-wrapper').attributes('id');
+ const iconName = wrapper.find(GlIcon).attributes('name');
+
+ expect(noteId).toBe('note_1628');
+ expect(iconName).toBe(mockAlert.notes.nodes[0].systemNoteIconName);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
index 20ea897e29c..3be609f0dad 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/awards_list_spec.js.snap
@@ -18,13 +18,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="thumbsup"
/>
-
-
</span>
<span
@@ -52,13 +48,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="thumbsdown"
/>
-
-
</span>
<span
@@ -86,13 +78,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="smile"
/>
-
-
</span>
<span
@@ -120,13 +108,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="ok_hand"
/>
-
-
</span>
<span
@@ -154,13 +138,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="cactus"
/>
-
-
</span>
<span
@@ -188,13 +168,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="a"
/>
-
-
</span>
<span
@@ -222,13 +198,9 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
class="award-emoji-block"
data-testid="award-html"
>
-
-
<gl-emoji
data-name="b"
/>
-
-
</span>
<span
diff --git a/spec/frontend/vue_shared/components/actions_button_spec.js b/spec/frontend/vue_shared/components/actions_button_spec.js
index 2ac4bfda29a..e5b7b693cb5 100644
--- a/spec/frontend/vue_shared/components/actions_button_spec.js
+++ b/spec/frontend/vue_shared/components/actions_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlDropdownDivider, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ActionsButton from '~/vue_shared/components/actions_button.vue';
diff --git a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
index 22643a17b2b..f592db935ec 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
+import { handleBlobRichViewer } from '~/blob/viewer';
import RichViewer from '~/vue_shared/components/blob_viewers/rich_viewer.vue';
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
-import { handleBlobRichViewer } from '~/blob/viewer';
jest.mock('~/blob/viewer');
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 8434fdaccde..9a0616343fe 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,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue';
import { HIGHLIGHT_CLASS_NAME } from '~/vue_shared/components/blob_viewers/constants';
+import SimpleViewer from '~/vue_shared/components/blob_viewers/simple_viewer.vue';
describe('Blob Simple Viewer component', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/changed_file_icon_spec.js b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
index 80918c5e771..6b9658a6d18 100644
--- a/spec/frontend/vue_shared/components/changed_file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
const changedFile = () => ({ changed: true });
diff --git a/spec/frontend/vue_shared/components/ci_badge_link_spec.js b/spec/frontend/vue_shared/components/ci_badge_link_spec.js
index a633ef65aa4..a943d931f67 100644
--- a/spec/frontend/vue_shared/components/ci_badge_link_spec.js
+++ b/spec/frontend/vue_shared/components/ci_badge_link_spec.js
@@ -1,10 +1,9 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import ciBadge from '~/vue_shared/components/ci_badge_link.vue';
+import { shallowMount } from '@vue/test-utils';
+import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
describe('CI Badge Link Component', () => {
- let CIBadge;
- let vm;
+ let wrapper;
const statuses = {
canceled: {
@@ -72,29 +71,30 @@ describe('CI Badge Link Component', () => {
},
};
- beforeEach(() => {
- CIBadge = Vue.extend(ciBadge);
- });
+ const findIcon = () => wrapper.findComponent(CiIcon);
+
+ const createComponent = (propsData) => {
+ wrapper = shallowMount(CiBadge, { propsData });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- it('should render each status badge', () => {
- Object.keys(statuses).map((status) => {
- vm = mountComponent(CIBadge, { status: statuses[status] });
+ it.each(Object.keys(statuses))('should render badge for status: %s', (status) => {
+ createComponent({ status: statuses[status] });
- expect(vm.$el.getAttribute('href')).toEqual(statuses[status].details_path);
- expect(vm.$el.textContent.trim()).toEqual(statuses[status].text);
- expect(vm.$el.getAttribute('class')).toContain(`ci-status ci-${statuses[status].group}`);
- expect(vm.$el.querySelector('svg')).toBeDefined();
- return vm;
- });
+ expect(wrapper.attributes('href')).toBe(statuses[status].details_path);
+ expect(wrapper.text()).toBe(statuses[status].text);
+ expect(wrapper.classes()).toContain('ci-status');
+ expect(wrapper.classes()).toContain(`ci-${statuses[status].group}`);
+ expect(findIcon().exists()).toBe(true);
});
it('should not render label', () => {
- vm = mountComponent(CIBadge, { status: statuses.canceled, showText: false });
+ createComponent({ status: statuses.canceled, showText: false });
- expect(vm.$el.textContent.trim()).toEqual('');
+ expect(wrapper.text()).toBe('');
});
});
diff --git a/spec/frontend/vue_shared/components/ci_icon_spec.js b/spec/frontend/vue_shared/components/ci_icon_spec.js
index 63afe631063..6d52db7ae65 100644
--- a/spec/frontend/vue_shared/components/ci_icon_spec.js
+++ b/spec/frontend/vue_shared/components/ci_icon_spec.js
@@ -1,122 +1,51 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
describe('CI Icon component', () => {
- const Component = Vue.extend(ciIcon);
- let vm;
+ let wrapper;
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
it('should render a span element with an svg', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_success',
- },
- });
-
- expect(vm.$el.tagName).toEqual('SPAN');
- expect(vm.$el.querySelector('span > svg')).toBeDefined();
- });
-
- it('should render a success status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_success',
- group: 'success',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-success')).toEqual(true);
- });
-
- it('should render a failed status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_failed',
- group: 'failed',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-failed')).toEqual(true);
- });
-
- it('should render success with warnings status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_warning',
- group: 'warning',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-warning')).toEqual(true);
- });
-
- it('should render pending status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_pending',
- group: 'pending',
- },
+ wrapper = shallowMount(ciIcon, {
+ propsData: {
+ status: {
+ icon: 'status_success',
+ },
+ },
+ });
+
+ expect(wrapper.find('span').exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
+ });
+
+ describe('rendering a status', () => {
+ it.each`
+ icon | group | cssClass
+ ${'status_success'} | ${'success'} | ${'ci-status-icon-success'}
+ ${'status_failed'} | ${'failed'} | ${'ci-status-icon-failed'}
+ ${'status_warning'} | ${'warning'} | ${'ci-status-icon-warning'}
+ ${'status_pending'} | ${'pending'} | ${'ci-status-icon-pending'}
+ ${'status_running'} | ${'running'} | ${'ci-status-icon-running'}
+ ${'status_created'} | ${'created'} | ${'ci-status-icon-created'}
+ ${'status_skipped'} | ${'skipped'} | ${'ci-status-icon-skipped'}
+ ${'status_canceled'} | ${'canceled'} | ${'ci-status-icon-canceled'}
+ ${'status_manual'} | ${'manual'} | ${'ci-status-icon-manual'}
+ `('should render a $group status', ({ icon, group, cssClass }) => {
+ wrapper = shallowMount(ciIcon, {
+ propsData: {
+ status: {
+ icon,
+ group,
+ },
+ },
+ });
+
+ expect(wrapper.classes()).toContain(cssClass);
});
-
- expect(vm.$el.classList.contains('ci-status-icon-pending')).toEqual(true);
- });
-
- it('should render running status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_running',
- group: 'running',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-running')).toEqual(true);
- });
-
- it('should render created status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_created',
- group: 'created',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-created')).toEqual(true);
- });
-
- it('should render skipped status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_skipped',
- group: 'skipped',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-skipped')).toEqual(true);
- });
-
- it('should render canceled status', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_canceled',
- group: 'canceled',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-canceled')).toEqual(true);
- });
-
- it('should render status for manual action', () => {
- vm = mountComponent(Component, {
- status: {
- icon: 'status_manual',
- group: 'manual',
- },
- });
-
- expect(vm.$el.classList.contains('ci-status-icon-manual')).toEqual(true);
});
});
diff --git a/spec/frontend/vue_shared/components/clipboard_button_spec.js b/spec/frontend/vue_shared/components/clipboard_button_spec.js
index 0d4266ce82f..ab4008484e5 100644
--- a/spec/frontend/vue_shared/components/clipboard_button_spec.js
+++ b/spec/frontend/vue_shared/components/clipboard_button_spec.js
@@ -1,7 +1,7 @@
-import { mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { mount } from '@vue/test-utils';
import initCopyToClipboard from '~/behaviors/copy_to_clipboard';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
describe('clipboard button', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/clone_dropdown_spec.js b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
index 5b8576ad761..eefd1838988 100644
--- a/spec/frontend/vue_shared/components/clone_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlFormInputGroup, GlDropdownSectionHeader } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import CloneDropdown from '~/vue_shared/components/clone_dropdown.vue';
describe('Clone Dropdown Button', () => {
diff --git a/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js b/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
index c8fe6c3131c..d30f36ec63c 100644
--- a/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
+++ b/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
@@ -13,6 +13,7 @@ describe('ColorPicker', () => {
};
const setColor = '#000000';
+ const invalidText = 'Please enter a valid hex (#RRGGBB or #RGB) color value';
const label = () => wrapper.find(GlFormGroup).attributes('label');
const colorPreview = () => wrapper.find('[data-testid="color-preview"]');
const colorPicker = () => wrapper.find(GlFormInput);
@@ -28,8 +29,6 @@ describe('ColorPicker', () => {
'#428BCA': 'Moderate blue',
'#44AD8E': 'Lime green',
};
-
- createComponent(shallowMount);
});
afterEach(() => {
@@ -38,6 +37,8 @@ describe('ColorPicker', () => {
describe('label', () => {
it('hides the label if the label is not passed', () => {
+ createComponent(shallowMount);
+
expect(label()).toBe('');
});
@@ -55,43 +56,37 @@ describe('ColorPicker', () => {
expect(colorPreview().attributes('style')).toBe(undefined);
expect(colorPicker().attributes('value')).toBe(undefined);
expect(colorInput().props('value')).toBe('');
+ expect(colorPreview().attributes('class')).toContain('gl-inset-border-1-gray-400');
});
it('has a color set on initialization', () => {
- createComponent(shallowMount, { setColor });
+ createComponent(mount, { value: setColor });
- expect(wrapper.vm.$data.selectedColor).toBe(setColor);
+ expect(colorInput().props('value')).toBe(setColor);
});
it('emits input event from component when a color is selected', async () => {
createComponent();
await colorInput().setValue(setColor);
- expect(wrapper.emitted().input[0]).toEqual([setColor]);
+ expect(wrapper.emitted().input[0]).toStrictEqual([setColor]);
});
it('trims spaces from submitted colors', async () => {
createComponent();
await colorInput().setValue(` ${setColor} `);
- expect(wrapper.vm.$data.selectedColor).toBe(setColor);
+ expect(wrapper.emitted().input[0]).toStrictEqual([setColor]);
+ expect(colorPreview().attributes('class')).toContain('gl-inset-border-1-gray-400');
+ expect(colorInput().attributes('class')).not.toContain('is-invalid');
});
- it('shows invalid feedback when an invalid color is used', async () => {
- createComponent();
- await colorInput().setValue('abcd');
-
- expect(invalidFeedback().text()).toBe(
- 'Please enter a valid hex (#RRGGBB or #RGB) color value',
- );
- expect(wrapper.emitted().input).toBe(undefined);
- });
-
- it('shows an invalid feedback border on the preview when an invalid color is used', async () => {
- createComponent();
- await colorInput().setValue('abcd');
+ it('shows invalid feedback when the state is marked as invalid', async () => {
+ createComponent(mount, { invalidFeedback: invalidText, state: false });
+ expect(invalidFeedback().text()).toBe(invalidText);
expect(colorPreview().attributes('class')).toContain('gl-inset-border-1-red-500');
+ expect(colorInput().attributes('class')).toContain('is-invalid');
});
});
@@ -100,14 +95,14 @@ describe('ColorPicker', () => {
createComponent();
await colorInput().setValue(setColor);
- expect(wrapper.vm.$data.selectedColor).toBe(setColor);
+ expect(wrapper.emitted().input[0]).toStrictEqual([setColor]);
});
it('has color picker value entered', async () => {
createComponent();
await colorPicker().setValue(setColor);
- expect(wrapper.vm.$data.selectedColor).toBe(setColor);
+ expect(wrapper.emitted().input[0]).toStrictEqual([setColor]);
});
});
@@ -132,7 +127,7 @@ describe('ColorPicker', () => {
createComponent();
await presetColors().at(0).trigger('click');
- expect(wrapper.vm.$data.selectedColor).toBe(setColor);
+ expect(wrapper.emitted().input[0]).toStrictEqual([setColor]);
});
});
});
diff --git a/spec/frontend/vue_shared/components/commit_spec.js b/spec/frontend/vue_shared/components/commit_spec.js
index 6f3c97f7194..66ceebed489 100644
--- a/spec/frontend/vue_shared/components/commit_spec.js
+++ b/spec/frontend/vue_shared/components/commit_spec.js
@@ -1,5 +1,6 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import CommitComponent from '~/vue_shared/components/commit.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -13,11 +14,14 @@ describe('Commit component', () => {
};
const findUserAvatar = () => wrapper.find(UserAvatarLink);
+ const findRefName = () => wrapper.findByTestId('ref-name');
const createComponent = (propsData) => {
- wrapper = shallowMount(CommitComponent, {
- propsData,
- });
+ wrapper = extendedWrapper(
+ shallowMount(CommitComponent, {
+ propsData,
+ }),
+ );
};
afterEach(() => {
@@ -223,4 +227,20 @@ describe('Commit component', () => {
expect(wrapper.find('.ref-name').exists()).toBe(false);
});
});
+
+ describe('When commitRef has a path property instead of ref_url property', () => {
+ it('should render path as href attribute', () => {
+ props = {
+ commitRef: {
+ name: 'master',
+ path: 'http://localhost/namespace2/gitlabhq/tree/master',
+ },
+ };
+
+ createComponent(props);
+
+ expect(findRefName().exists()).toBe(true);
+ expect(findRefName().attributes('href')).toBe(props.commitRef.path);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js
index 31e843297fa..af3b63ad7e5 100644
--- a/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js
@@ -33,4 +33,14 @@ describe('Image Viewer', () => {
},
);
});
+
+ describe('file path', () => {
+ it('should output a valid URL path for the image', () => {
+ wrapper = mount(ImageViewer, {
+ propsData: { path: '/url/hello#1.jpg' },
+ });
+
+ expect(wrapper.find('img').attributes('src')).toBe('/url/hello%231.jpg');
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
index 22ee6acfed8..3ffb23dc7a0 100644
--- a/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/viewers/markdown_viewer_spec.js
@@ -1,6 +1,6 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import MarkdownViewer from '~/vue_shared/components/content_viewer/viewers/markdown_viewer.vue';
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 b6bffbcc6f3..eacc41ccdad 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,6 +1,6 @@
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
import { compileToFunctions } from 'vue-template-compiler';
-import { mount } from '@vue/test-utils';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
import imageDiffViewer from '~/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue';
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 e91e6577aaf..9f433816b34 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,6 +1,5 @@
-import Vuex from 'vuex';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
-import Renamed from '~/vue_shared/components/diff_viewer/viewers/renamed.vue';
+import Vuex from 'vuex';
import {
TRANSITION_LOAD_START,
TRANSITION_LOAD_ERROR,
@@ -10,6 +9,7 @@ import {
STATE_LOADING,
STATE_ERRORED,
} from '~/diffs/constants';
+import Renamed from '~/vue_shared/components/diff_viewer/viewers/renamed.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/vue_shared/components/dismissible_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
index 17905254292..cfa6d1064e5 100644
--- a/spec/frontend/vue_shared/components/dismissible_alert_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
const TEST_HTML = 'Hello World! <strong>Foo</strong>';
diff --git a/spec/frontend/vue_shared/components/dismissible_container_spec.js b/spec/frontend/vue_shared/components/dismissible_container_spec.js
index 2c0e363fa0e..b8aeea38e77 100644
--- a/spec/frontend/vue_shared/components/dismissible_container_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_container_spec.js
@@ -1,5 +1,5 @@
-import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import dismissibleContainer from '~/vue_shared/components/dismissible_container.vue';
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 4c4baf23120..175d79dd1c2 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,5 @@
-import { mount, shallowMount } from '@vue/test-utils';
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import Component from '~/vue_shared/components/dismissible_feedback_alert.vue';
diff --git a/spec/frontend/vue_shared/components/editor_lite_spec.js b/spec/frontend/vue_shared/components/editor_lite_spec.js
index 70fdd8e24a5..badd5aed0e3 100644
--- a/spec/frontend/vue_shared/components/editor_lite_spec.js
+++ b/spec/frontend/vue_shared/components/editor_lite_spec.js
@@ -1,7 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import { EDITOR_READY_EVENT } from '~/editor/constants';
import Editor from '~/editor/editor_lite';
+import EditorLite from '~/vue_shared/components/editor_lite.vue';
jest.mock('~/editor/editor_lite');
@@ -110,13 +111,13 @@ describe('Editor Lite component', () => {
expect(wrapper.emitted().input).toEqual([[value]]);
});
- it('emits editor-ready event when the Editor Lite is ready', async () => {
+ it('emits EDITOR_READY_EVENT event when the Editor Lite is ready', async () => {
const el = wrapper.find({ ref: 'editor' }).element;
- expect(wrapper.emitted()['editor-ready']).toBeUndefined();
+ expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeUndefined();
- await el.dispatchEvent(new Event('editor-ready'));
+ await el.dispatchEvent(new Event(EDITOR_READY_EVENT));
- expect(wrapper.emitted()['editor-ready']).toBeDefined();
+ expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeDefined();
});
it('component API `getEditor()` returns the editor instance', () => {
diff --git a/spec/frontend/vue_shared/components/expand_button_spec.js b/spec/frontend/vue_shared/components/expand_button_spec.js
index 724405a109f..7874658cc0f 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 Vue from 'vue';
import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import ExpandButton from '~/vue_shared/components/expand_button.vue';
const text = {
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 238a5440664..d757b7fac72 100644
--- a/spec/frontend/vue_shared/components/file_finder/index_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/index_spec.js
@@ -1,9 +1,9 @@
-import Vue from 'vue';
import Mousetrap from 'mousetrap';
-import { file } from 'jest/ide/helpers';
+import Vue from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import FindFileComponent from '~/vue_shared/components/file_finder/index.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';
describe('File finder item spec', () => {
const Component = Vue.extend(FindFileComponent);
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 c60e6335389..1a4a97efb95 100644
--- a/spec/frontend/vue_shared/components/file_finder/item_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/item_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import { file } from 'jest/ide/helpers';
import createComponent from 'helpers/vue_mount_component_helper';
+import { file } from 'jest/ide/helpers';
import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
describe('File finder item spec', () => {
diff --git a/spec/frontend/vue_shared/components/file_icon_spec.js b/spec/frontend/vue_shared/components/file_icon_spec.js
index e55449dc684..c10663f6c14 100644
--- a/spec/frontend/vue_shared/components/file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/file_icon_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { FILE_SYMLINK_MODE } from '~/vue_shared/constants';
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
index bd6a18bf704..62fb29c455c 100644
--- a/spec/frontend/vue_shared/components/file_row_spec.js
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -1,10 +1,10 @@
-import { file } from 'jest/ide/helpers';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { file } from 'jest/ide/helpers';
+import { escapeFileUrl } from '~/lib/utils/url_utility';
+import FileIcon from '~/vue_shared/components/file_icon.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileHeader from '~/vue_shared/components/file_row_header.vue';
-import FileIcon from '~/vue_shared/components/file_icon.vue';
-import { escapeFileUrl } from '~/lib/utils/url_utility';
describe('File row component', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/file_tree_spec.js b/spec/frontend/vue_shared/components/file_tree_spec.js
index 7a4982fd29b..39a7c7a2b3a 100644
--- a/spec/frontend/vue_shared/components/file_tree_spec.js
+++ b/spec/frontend/vue_shared/components/file_tree_spec.js
@@ -1,5 +1,5 @@
-import { pick } from 'lodash';
import { shallowMount } from '@vue/test-utils';
+import { pick } from 'lodash';
import FileTree from '~/vue_shared/components/file_tree.vue';
const MockFileRow = {
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 b58ce0083c0..9fa9d35e3e2 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
@@ -1,4 +1,3 @@
-import { shallowMount, mount } from '@vue/test-utils';
import {
GlFilteredSearch,
GlButtonGroup,
@@ -7,13 +6,13 @@ import {
GlDropdownItem,
GlFormCheckbox,
} from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
+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';
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import { uniqueTokens } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
-import { SortDirection } from '~/vue_shared/components/filtered_search_bar/constants';
-
-import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
-import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import {
mockAvailableTokens,
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
index 1dd5f08e76a..05bad572472 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/actions_spec.js
@@ -2,12 +2,12 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { mockBranches } from 'jest/vue_shared/components/filtered_search_bar/mock_data';
+import Api from '~/api';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+import httpStatusCodes from '~/lib/utils/http_status';
import * as actions from '~/vue_shared/components/filtered_search_bar/store/modules/filters/actions';
import * as types from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutation_types';
import initialState from '~/vue_shared/components/filtered_search_bar/store/modules/filters/state';
-import httpStatusCodes from '~/lib/utils/http_status';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import Api from '~/api';
import { filterMilestones, filterUsers, filterLabels } from './mock_data';
const milestonesEndpoint = 'fake_milestones_endpoint';
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/mutations_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/mutations_spec.js
index 263a4ee178f..66c6267027b 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/store/modules/filters/mutations_spec.js
@@ -1,9 +1,9 @@
import { get } from 'lodash';
import { mockBranches } from 'jest/vue_shared/components/filtered_search_bar/mock_data';
-import initialState from '~/vue_shared/components/filtered_search_bar/store/modules/filters/state';
-import mutations from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutations';
-import * as types from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutation_types';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import * as types from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutation_types';
+import mutations from '~/vue_shared/components/filtered_search_bar/store/modules/filters/mutations';
+import initialState from '~/vue_shared/components/filtered_search_bar/store/modules/filters/state';
import { filterMilestones, filterUsers, filterLabels } from './mock_data';
let state = null;
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 3997d6a99a6..765e576914c 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -1,15 +1,15 @@
-import { mount } from '@vue/test-utils';
import {
GlFilteredSearchToken,
GlFilteredSearchTokenSegment,
GlFilteredSearchSuggestion,
GlDropdownDivider,
} from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
DEFAULT_LABEL_NONE,
DEFAULT_LABEL_ANY,
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 35f487330be..a20bc4986fc 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
@@ -1,15 +1,15 @@
-import { mount } from '@vue/test-utils';
import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlFilteredSearchTokenSegment,
GlDropdownDivider,
} from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
import {
DEFAULT_LABEL_NONE,
DEFAULT_LABEL_ANY,
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 dda0ad39bbc..7676ce10ce0 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -1,19 +1,19 @@
-import { mount } from '@vue/test-utils';
import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlFilteredSearchTokenSegment,
GlDropdownDivider,
} from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import {
mockRegularLabel,
mockLabels,
} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
DEFAULT_LABELS,
DEFAULT_LABEL_NONE,
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 164561f6244..9f550ac9afc 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
@@ -1,15 +1,15 @@
-import { mount } from '@vue/test-utils';
import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlFilteredSearchTokenSegment,
GlDropdownDivider,
} from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import createFlash from '~/flash';
import { DEFAULT_MILESTONES } from '~/vue_shared/components/filtered_search_bar/constants';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
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
index d8e6e37bb89..370b6eb01bc 100644
--- 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
@@ -1,12 +1,6 @@
// 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 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;"`;
@@ -21,10 +15,10 @@ exports[`gfm_autocomplete/utils labels config shows the title in the menu item 1
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-s24 gl-flex-shrink-0 gl-rounded-small
+ <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-font-sm gl-line-height-normal gl-ml-3\\">
+ <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>
@@ -36,8 +30,8 @@ exports[`gfm_autocomplete/utils members config shows an avatar character, name,
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-s24 gl-flex-shrink-0 gl-avatar-circle\\" src=\\"/uploads/-/system/user/avatar/123456/avatar.png\\" alt=\\"\\" />
- <div class=\\"gl-font-sm gl-line-height-normal gl-ml-3\\">
+ <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>
diff --git a/spec/frontend/vue_shared/components/gl_countdown_spec.js b/spec/frontend/vue_shared/components/gl_countdown_spec.js
index fcc5c0cd310..82d18c7fd3f 100644
--- a/spec/frontend/vue_shared/components/gl_countdown_spec.js
+++ b/spec/frontend/vue_shared/components/gl_countdown_spec.js
@@ -1,5 +1,5 @@
-import mountComponent from 'helpers/vue_mount_component_helper';
import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
describe('GlCountdown', () => {
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 6802499ed52..390a70792f3 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,7 @@
+import { GlModal } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue';
import createState from '~/vuex_shared/modules/modal/state';
@@ -129,7 +130,7 @@ describe('GlModalVuex', () => {
wrapper.vm
.$nextTick()
.then(() => {
- expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', TEST_MODAL_ID);
+ expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, TEST_MODAL_ID);
})
.then(done)
.catch(done.fail);
@@ -146,7 +147,7 @@ describe('GlModalVuex', () => {
wrapper.vm
.$nextTick()
.then(() => {
- expect(rootEmit).toHaveBeenCalledWith('bv::hide::modal', TEST_MODAL_ID);
+ expect(rootEmit).toHaveBeenCalledWith(BV_HIDE_MODAL, TEST_MODAL_ID);
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js
index 30afb044bbf..ac670b622b1 100644
--- a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js
+++ b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
import { GlToggle } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import GlToggleVuex from '~/vue_shared/components/gl_toggle_vuex.vue';
const localVue = createLocalVue();
diff --git a/spec/frontend/vue_shared/components/header_ci_component_spec.js b/spec/frontend/vue_shared/components/header_ci_component_spec.js
index 5233a64ce5e..b54d120b55b 100644
--- a/spec/frontend/vue_shared/components/header_ci_component_spec.js
+++ b/spec/frontend/vue_shared/components/header_ci_component_spec.js
@@ -1,93 +1,103 @@
-import Vue from 'vue';
-import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
-import headerCi from '~/vue_shared/components/header_ci_component.vue';
+import { GlButton, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import CiIconBadge from '~/vue_shared/components/ci_badge_link.vue';
+import HeaderCi from '~/vue_shared/components/header_ci_component.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
describe('Header CI Component', () => {
- let HeaderCi;
- let vm;
- let props;
-
- beforeEach(() => {
- HeaderCi = Vue.extend(headerCi);
- props = {
- status: {
- group: 'failed',
- icon: 'status_failed',
- label: 'failed',
- text: 'failed',
- details_path: 'path',
- },
- itemName: 'job',
- itemId: 123,
- time: '2017-05-08T14:57:39.781Z',
- user: {
- web_url: 'path',
- name: 'Foo',
- username: 'foobar',
- email: 'foo@bar.com',
- avatar_url: 'link',
- },
- hasSidebarButton: true,
- };
- });
+ let wrapper;
+
+ const defaultProps = {
+ status: {
+ group: 'failed',
+ icon: 'status_failed',
+ label: 'failed',
+ text: 'failed',
+ details_path: 'path',
+ },
+ itemName: 'job',
+ itemId: 123,
+ time: '2017-05-08T14:57:39.781Z',
+ user: {
+ web_url: 'path',
+ name: 'Foo',
+ username: 'foobar',
+ email: 'foo@bar.com',
+ avatar_url: 'link',
+ },
+ hasSidebarButton: true,
+ };
+
+ const findIconBadge = () => wrapper.findComponent(CiIconBadge);
+ const findTimeAgo = () => wrapper.findComponent(TimeagoTooltip);
+ const findUserLink = () => wrapper.findComponent(GlLink);
+ const findSidebarToggleBtn = () => wrapper.findComponent(GlButton);
+ const findActionButtons = () => wrapper.findByTestId('ci-header-action-buttons');
+ const findHeaderItemText = () => wrapper.findByTestId('ci-header-item-text');
+
+ const createComponent = (props, slots) => {
+ wrapper = extendedWrapper(
+ shallowMount(HeaderCi, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ ...slots,
+ }),
+ );
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
- const findActionButtons = () => vm.$el.querySelector('[data-testid="headerButtons"]');
-
describe('render', () => {
beforeEach(() => {
- vm = mountComponent(HeaderCi, props);
+ createComponent();
});
it('should render status badge', () => {
- expect(vm.$el.querySelector('.ci-failed')).toBeDefined();
- expect(vm.$el.querySelector('.ci-status-icon-failed svg')).toBeDefined();
- expect(vm.$el.querySelector('.ci-failed').getAttribute('href')).toEqual(
- props.status.details_path,
- );
+ expect(findIconBadge().exists()).toBe(true);
});
it('should render item name and id', () => {
- expect(vm.$el.querySelector('strong').textContent.trim()).toEqual('job #123');
+ expect(findHeaderItemText().text()).toBe('job #123');
});
it('should render timeago date', () => {
- expect(vm.$el.querySelector('time')).toBeDefined();
+ expect(findTimeAgo().exists()).toBe(true);
});
it('should render user icon and name', () => {
- expect(vm.$el.querySelector('.js-user-link').innerText.trim()).toContain(props.user.name);
+ expect(findUserLink().text()).toContain(defaultProps.user.name);
});
it('should render sidebar toggle button', () => {
- expect(vm.$el.querySelector('.js-sidebar-build-toggle')).not.toBeNull();
+ expect(findSidebarToggleBtn().exists()).toBe(true);
});
- it('should not render header action buttons when empty', () => {
- expect(findActionButtons()).toBeNull();
+ it('should not render header action buttons when slot is empty', () => {
+ expect(findActionButtons().exists()).toBe(false);
});
});
describe('slot', () => {
it('should render header action buttons', () => {
- vm = mountComponentWithSlots(HeaderCi, { props, slots: { default: 'Test Actions' } });
-
- const buttons = findActionButtons();
+ createComponent({}, { slots: { default: 'Test Actions' } });
- expect(buttons).not.toBeNull();
- expect(buttons.textContent).toEqual('Test Actions');
+ expect(findActionButtons().exists()).toBe(true);
+ expect(findActionButtons().text()).toBe('Test Actions');
});
});
describe('shouldRenderTriggeredLabel', () => {
- it('should rendered created keyword when the shouldRenderTriggeredLabel is false', () => {
- vm = mountComponent(HeaderCi, { ...props, shouldRenderTriggeredLabel: false });
+ it('should render created keyword when the shouldRenderTriggeredLabel is false', () => {
+ createComponent({ shouldRenderTriggeredLabel: false });
- expect(vm.$el.textContent).toContain('created');
- expect(vm.$el.textContent).not.toContain('triggered');
+ expect(wrapper.text()).toContain('created');
+ expect(wrapper.text()).not.toContain('triggered');
});
});
});
diff --git a/spec/frontend/vue_shared/components/help_popover_spec.js b/spec/frontend/vue_shared/components/help_popover_spec.js
new file mode 100644
index 00000000000..baf80a8a04e
--- /dev/null
+++ b/spec/frontend/vue_shared/components/help_popover_spec.js
@@ -0,0 +1,65 @@
+import { GlButton, GlPopover } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import HelpPopover from '~/vue_shared/components/help_popover.vue';
+
+describe('HelpPopover', () => {
+ let wrapper;
+ const title = 'popover <strong>title</strong>';
+ const content = 'popover <b>content</b>';
+
+ const findQuestionButton = () => wrapper.find(GlButton);
+ const findPopover = () => wrapper.find(GlPopover);
+ const buildWrapper = (options = {}) => {
+ wrapper = mount(HelpPopover, {
+ propsData: {
+ options: {
+ title,
+ content,
+ ...options,
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders a link button with an icon question', () => {
+ expect(findQuestionButton().props()).toMatchObject({
+ icon: 'question',
+ variant: 'link',
+ });
+ expect(findQuestionButton().attributes().tabindex).toBe('0');
+ });
+
+ it('renders popover that uses the question button as target', () => {
+ expect(findPopover().props().target()).toBe(findQuestionButton().vm.$el);
+ });
+
+ it('triggers popover on hover and focus', () => {
+ expect(findPopover().props().triggers).toBe('hover focus');
+ });
+
+ 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);
+ });
+
+ it('binds other popover options to the popover instance', () => {
+ const placement = 'bottom';
+
+ wrapper.destroy();
+ buildWrapper({ placement });
+
+ expect(findPopover().props().placement).toBe(placement);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/integration_help_text_spec.js b/spec/frontend/vue_shared/components/integration_help_text_spec.js
index 4269d36d0e2..c0e8b719007 100644
--- a/spec/frontend/vue_shared/components/integration_help_text_spec.js
+++ b/spec/frontend/vue_shared/components/integration_help_text_spec.js
@@ -1,6 +1,6 @@
+import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
describe('IntegrationHelpText component', () => {
diff --git a/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js b/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js
index a03a3915e1b..573501233b9 100644
--- a/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js
+++ b/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js
@@ -1,8 +1,8 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import IssuableHeaderWarnings from '~/vue_shared/components/issuable/issuable_header_warnings.vue';
-import createIssueStore from '~/notes/stores';
import { createStore as createMrStore } from '~/mr_notes/stores';
+import createIssueStore from '~/notes/stores';
+import IssuableHeaderWarnings from '~/vue_shared/components/issuable/issuable_header_warnings.vue';
const ISSUABLE_TYPE_ISSUE = 'issue';
const ISSUABLE_TYPE_MR = 'merge request';
diff --git a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
index 5f614bfc751..5c29c267c99 100644
--- a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { mockAssigneesList } from 'jest/boards/mock_data';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
const TEST_CSS_CLASSES = 'test-classes';
const TEST_MAX_VISIBLE = 4;
diff --git a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
index ffcb891c4fc..9a121050225 100644
--- a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
@@ -1,8 +1,8 @@
-import Vue from 'vue';
+import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import { mockMilestone } from 'jest/boards/mock_data';
-import { GlIcon } from '@gitlab/ui';
import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
const createComponent = (milestone = mockMilestone) => {
diff --git a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
index 3dc34583118..f34a2db0851 100644
--- a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
+++ b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
@@ -1,8 +1,8 @@
import { mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
-import IssueDueDate from '~/boards/components/issue_due_date.vue';
import { defaultAssignees, defaultMilestone } from './related_issuable_mock_data';
describe('RelatedIssuableItem', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js b/spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js
index b9f0d88548d..c56628fcbcd 100644
--- a/spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/apply_suggestion_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDropdown, GlFormTextarea, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ApplySuggestionComponent from '~/vue_shared/components/markdown/apply_suggestion.vue';
describe('Apply Suggestion component', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js
index a2ce6f40193..442032840e1 100644
--- a/spec/frontend/vue_shared/components/markdown/field_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/field_spec.js
@@ -1,9 +1,9 @@
import { mount } from '@vue/test-utils';
-import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants';
import AxiosMockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+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';
const markdownPreviewPath = `${TEST_HOST}/preview`;
const markdownDocsPath = `${TEST_HOST}/docs`;
diff --git a/spec/frontend/vue_shared/components/markdown/field_view_spec.js b/spec/frontend/vue_shared/components/markdown/field_view_spec.js
index 80cf1f655c6..be1d840dd29 100644
--- a/spec/frontend/vue_shared/components/markdown/field_view_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/field_view_spec.js
@@ -1,5 +1,5 @@
-import $ from 'jquery';
import { shallowMount } from '@vue/test-utils';
+import $ from 'jquery';
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
diff --git a/spec/frontend/vue_shared/components/memory_graph_spec.js b/spec/frontend/vue_shared/components/memory_graph_spec.js
index 9a5ee544d8f..53b96bd1b98 100644
--- a/spec/frontend/vue_shared/components/memory_graph_spec.js
+++ b/spec/frontend/vue_shared/components/memory_graph_spec.js
@@ -1,6 +1,6 @@
-import Vue from 'vue';
-import { shallowMount } from '@vue/test-utils';
import { GlSparklineChart } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import MemoryGraph from '~/vue_shared/components/memory_graph.vue';
describe('MemoryGraph', () => {
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 ca9f8ff54d4..adb72c3ef85 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 { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
describe('modal copy button', () => {
@@ -31,7 +32,7 @@ describe('modal copy button', () => {
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']]);
+ expect(root.emitted(BV_HIDE_TOOLTIP)).toEqual([['test-id']]);
});
});
it("should propagate the clipboard error event if execCommand doesn't work", () => {
diff --git a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
index 233c488b60b..99671f1ffb7 100644
--- a/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/multiselect_dropdown_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
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', () => {
diff --git a/spec/frontend/vue_shared/components/navigation_tabs_spec.js b/spec/frontend/vue_shared/components/navigation_tabs_spec.js
index b1119bfb150..30a89fed12f 100644
--- a/spec/frontend/vue_shared/components/navigation_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/navigation_tabs_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlTab } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
describe('navigation tabs component', () => {
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 cc9f05beb06..835759b1f20 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
describe('Issue Warning Component', () => {
diff --git a/spec/frontend/vue_shared/components/notes/system_note_spec.js b/spec/frontend/vue_shared/components/notes/system_note_spec.js
index d5eac7c2aa3..48dacc50923 100644
--- a/spec/frontend/vue_shared/components/notes/system_note_spec.js
+++ b/spec/frontend/vue_shared/components/notes/system_note_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
-import IssueSystemNote from '~/vue_shared/components/notes/system_note.vue';
-import createStore from '~/notes/stores';
import initMRPopovers from '~/mr_popover/index';
+import createStore from '~/notes/stores';
+import IssueSystemNote from '~/vue_shared/components/notes/system_note.vue';
jest.mock('~/mr_popover/index', () => jest.fn());
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 491f783622a..74e9cbcbb53 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,9 +1,9 @@
-import { mount } from '@vue/test-utils';
import { GlAlert, GlBadge, GlPagination, GlTabs, GlTab } from '@gitlab/ui';
-import PageWrapper from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
+import { mount } from '@vue/test-utils';
+import Tracking from '~/tracking';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
-import Tracking from '~/tracking';
+import PageWrapper from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
import mockItems from './mocks/items.json';
import mockFilters from './mocks/items_filters.json';
diff --git a/spec/frontend/vue_shared/components/pagination_links_spec.js b/spec/frontend/vue_shared/components/pagination_links_spec.js
index ad82aee0098..83f1e2844f9 100644
--- a/spec/frontend/vue_shared/components/pagination_links_spec.js
+++ b/spec/frontend/vue_shared/components/pagination_links_spec.js
@@ -1,6 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlPagination } from '@gitlab/ui';
-import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
+import { mount } from '@vue/test-utils';
import {
PREV,
NEXT,
@@ -9,6 +8,7 @@ import {
LABEL_NEXT_PAGE,
LABEL_LAST_PAGE,
} from '~/vue_shared/components/pagination/constants';
+import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
describe('Pagination links component', () => {
const pageInfo = {
diff --git a/spec/frontend/vue_shared/components/pikaday_spec.js b/spec/frontend/vue_shared/components/pikaday_spec.js
index 1c6876c282c..fed4ce5e696 100644
--- a/spec/frontend/vue_shared/components/pikaday_spec.js
+++ b/spec/frontend/vue_shared/components/pikaday_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlDatepicker } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import datePicker from '~/vue_shared/components/pikaday.vue';
describe('datePicker', () => {
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 016622fd0bb..06b00a8e196 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,8 +1,7 @@
-import Vue from 'vue';
-import { head } from 'lodash';
-
import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
+import { head } from 'lodash';
+import Vue from 'vue';
import { trimText } from 'helpers/text_helper';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
diff --git a/spec/frontend/vue_shared/components/registry/code_instruction_spec.js b/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
index 84c738764a3..4ec608aaf07 100644
--- a/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
+++ b/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
@@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
import Tracking from '~/tracking';
-import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
describe('Package code instruction', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/registry/details_row_spec.js b/spec/frontend/vue_shared/components/registry/details_row_spec.js
index 09dacfae363..3134e0d3e21 100644
--- a/spec/frontend/vue_shared/components/registry/details_row_spec.js
+++ b/spec/frontend/vue_shared/components/registry/details_row_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import component from '~/vue_shared/components/registry/details_row.vue';
describe('DetailsRow', () => {
diff --git a/spec/frontend/vue_shared/components/registry/history_item_spec.js b/spec/frontend/vue_shared/components/registry/history_item_spec.js
index d51ddda2e3e..f146f87342f 100644
--- a/spec/frontend/vue_shared/components/registry/history_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/history_item_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import component from '~/vue_shared/components/registry/history_item.vue';
diff --git a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
index 3d3cfbe13e3..1ccf3ddc5a5 100644
--- a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import component from '~/vue_shared/components/registry/metadata_item.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
diff --git a/spec/frontend/vue_shared/components/registry/registry_search_spec.js b/spec/frontend/vue_shared/components/registry/registry_search_spec.js
new file mode 100644
index 00000000000..28bdb275756
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/registry_search_spec.js
@@ -0,0 +1,105 @@
+import { GlSorting, GlSortingItem, GlFilteredSearch } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/vue_shared/components/registry/registry_search.vue';
+
+describe('Registry Search', () => {
+ let wrapper;
+
+ const findPackageListSorting = () => wrapper.find(GlSorting);
+ const findSortingItems = () => wrapper.findAll(GlSortingItem);
+ const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
+
+ const defaultProps = {
+ filter: [],
+ sorting: { sort: 'asc', orderBy: 'name' },
+ tokens: ['foo'],
+ sortableFields: [{ label: 'name', orderBy: 'name' }, { label: 'baz' }],
+ };
+
+ const mountComponent = (propsData = defaultProps) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSortingItem,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('searching', () => {
+ it('has a filtered-search component', () => {
+ mountComponent();
+
+ expect(findFilteredSearch().exists()).toBe(true);
+ });
+
+ it('binds the correct props to filtered-search', () => {
+ mountComponent();
+
+ expect(findFilteredSearch().props()).toMatchObject({
+ value: [],
+ placeholder: 'Filter results',
+ availableTokens: wrapper.vm.tokens,
+ });
+ });
+
+ it('emits filter:changed when value changes', () => {
+ mountComponent();
+
+ findFilteredSearch().vm.$emit('input', 'foo');
+
+ expect(wrapper.emitted('filter:changed')).toEqual([['foo']]);
+ });
+
+ it('emits filter:submit on submit event', () => {
+ mountComponent();
+
+ findFilteredSearch().vm.$emit('submit');
+ expect(wrapper.emitted('filter:submit')).toEqual([[]]);
+ });
+
+ it('emits filter:changed and filter:submit on clear event', () => {
+ mountComponent();
+
+ findFilteredSearch().vm.$emit('clear');
+
+ expect(wrapper.emitted('filter:changed')).toEqual([[[]]]);
+ expect(wrapper.emitted('filter:submit')).toEqual([[]]);
+ });
+
+ it('binds tokens prop', () => {
+ mountComponent();
+
+ expect(findFilteredSearch().props('availableTokens')).toEqual(defaultProps.tokens);
+ });
+ });
+
+ describe('sorting', () => {
+ it('has all the sortable items', () => {
+ mountComponent();
+
+ expect(findSortingItems()).toHaveLength(defaultProps.sortableFields.length);
+ });
+
+ it('on sort change emits sorting:changed event', () => {
+ mountComponent();
+
+ findPackageListSorting().vm.$emit('sortDirectionChange');
+ expect(wrapper.emitted('sorting:changed')).toEqual([[{ sort: 'desc' }]]);
+ });
+
+ it('on sort item click emits sorting:changed event ', () => {
+ mountComponent();
+
+ findSortingItems().at(0).vm.$emit('click');
+
+ expect(wrapper.emitted('sorting:changed')).toEqual([
+ [{ orderBy: defaultProps.sortableFields[0].orderBy }],
+ ]);
+ });
+ });
+});
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 3a5514ef318..1fce3c5d0b0 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 Vue from 'vue';
import { mount } from '@vue/test-utils';
import $ from 'jquery';
+import Vue from 'vue';
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
jest.mock('~/lib/utils/common_utils', () => ({
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
index 51619cd9578..ce2b0d1ddc1 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/editor_service_spec.js
@@ -1,3 +1,5 @@
+import buildCustomRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer';
+import buildHTMLToMarkdownRenderer from '~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer';
import {
generateToolbarItem,
addCustomEventListener,
@@ -8,8 +10,6 @@ import {
getMarkdown,
getEditorOptions,
} from '~/vue_shared/components/rich_content_editor/services/editor_service';
-import buildHTMLToMarkdownRenderer from '~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer';
-import buildCustomRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer';
import sanitizeHTML from '~/vue_shared/components/rich_content_editor/services/sanitize_html';
jest.mock('~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer');
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
index 16370a7aaad..97aecda97d2 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal_spec.js
@@ -1,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal, GlTabs } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { IMAGE_TABS } from '~/vue_shared/components/rich_content_editor/constants';
import AddImageModal from '~/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue';
import UploadImageTab from '~/vue_shared/components/rich_content_editor/modals/add_image/upload_image_tab.vue';
-import { IMAGE_TABS } from '~/vue_shared/components/rich_content_editor/constants';
describe('Add Image Modal', () => {
let wrapper;
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js
index d59d4cc1de9..3e9eaf58181 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/modals/insert_video_modal_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import InsertVideoModal from '~/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue';
describe('Insert Video Modal', () => {
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js
index b9b93b274d2..47b1abd2ad2 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_integration_spec.js
@@ -1,6 +1,6 @@
import Editor from '@toast-ui/editor';
-import { registerHTMLToMarkdownRenderer } from '~/vue_shared/components/rich_content_editor/services/editor_service';
import buildMarkdownToHTMLRenderer from '~/vue_shared/components/rich_content_editor/services/build_custom_renderer';
+import { registerHTMLToMarkdownRenderer } from '~/vue_shared/components/rich_content_editor/services/editor_service';
describe('vue_shared/components/rich_content_editor', () => {
let editor;
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
index 2eb353a1801..8eb880b3984 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/rich_content_editor_spec.js
@@ -1,14 +1,14 @@
-import { shallowMount } from '@vue/test-utils';
import { Editor, mockEditorApi } from '@toast-ui/vue-editor';
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
-import AddImageModal from '~/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue';
-import InsertVideoModal from '~/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue';
+import { shallowMount } from '@vue/test-utils';
import {
EDITOR_TYPES,
EDITOR_HEIGHT,
EDITOR_PREVIEW_STYLE,
CUSTOM_EVENTS,
} from '~/vue_shared/components/rich_content_editor/constants';
+import AddImageModal from '~/vue_shared/components/rich_content_editor/modals/add_image/add_image_modal.vue';
+import InsertVideoModal from '~/vue_shared/components/rich_content_editor/modals/insert_video_modal.vue';
+import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
import {
addCustomEventListener,
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
index d6bb01259bb..c1aaed6f0c3 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline_spec.js
@@ -1,5 +1,5 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline';
import { buildUneditableInlineTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
+import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_font_awesome_html_inline';
import { normalTextNode } from './mock_data';
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js
index b31684a400e..234f6a4d4ca 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_html_block_spec.js
@@ -1,5 +1,5 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_html_block';
import { buildUneditableHtmlAsTextTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
+import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_html_block';
describe('rich_content_editor/services/renderers/render_html_block', () => {
const htmlBlockNode = {
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
index 521885f5687..425d0f41bcd 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text_spec.js
@@ -1,5 +1,5 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text';
import { buildUneditableInlineTokens } from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
+import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_instance_text';
import { buildMockTextNode, normalTextNode } from './mock_data';
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
index 774f830f421..7c1809c290c 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
@@ -1,15 +1,14 @@
import {
+ buildUneditableBlockTokens,
+ buildUneditableOpenTokens,
+} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
+import {
renderUneditableLeaf,
renderUneditableBranch,
renderWithAttributeDefinitions,
willAlwaysRender,
} from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-import {
- buildUneditableBlockTokens,
- buildUneditableOpenTokens,
-} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-
import { originToken, uneditableCloseToken, attributeDefinition } from './mock_data';
describe('rich_content_editor/renderers/render_utils', () => {
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js
index 0e6f951bd53..5a56b499769 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js
@@ -1,6 +1,6 @@
+import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { GlIcon } from '@gitlab/ui';
import ToolbarItem from '~/vue_shared/components/rich_content_editor/toolbar_item.vue';
describe('Toolbar Item', () => {
diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
new file mode 100644
index 00000000000..01f7f3d49c7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
@@ -0,0 +1,107 @@
+export const mockGraphqlRunnerPlatforms = {
+ data: {
+ runnerPlatforms: {
+ nodes: [
+ {
+ name: 'linux',
+ humanReadableName: 'Linux',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: '386',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: 'arm',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: 'arm64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'osx',
+ humanReadableName: 'macOS',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'windows',
+ humanReadableName: 'Windows',
+ architectures: {
+ nodes: [
+ {
+ name: 'amd64',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe',
+ __typename: 'RunnerArchitecture',
+ },
+ {
+ name: '386',
+ downloadLocation:
+ 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-386.exe',
+ __typename: 'RunnerArchitecture',
+ },
+ ],
+ __typename: 'RunnerArchitectureConnection',
+ },
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'docker',
+ humanReadableName: 'Docker',
+ architectures: null,
+ __typename: 'RunnerPlatform',
+ },
+ {
+ name: 'kubernetes',
+ humanReadableName: 'Kubernetes',
+ architectures: null,
+ __typename: 'RunnerPlatform',
+ },
+ ],
+ __typename: 'RunnerPlatformConnection',
+ },
+ project: { id: 'gid://gitlab/Project/1', __typename: 'Project' },
+ group: null,
+ },
+};
+
+export const mockGraphqlInstructions = {
+ data: {
+ runnerSetup: {
+ installInstructions:
+ "# Download the binary for your system\nsudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64\n\n# Give it permissions to execute\nsudo chmod +x /usr/local/bin/gitlab-runner\n\n# Create a GitLab CI user\nsudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash\n\n# Install and run as service\nsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start\n",
+ registerInstructions:
+ 'sudo gitlab-runner register --url http://192.168.1.81:3000/ --registration-token GE5gsjeep_HAtBf9s3Yz',
+ __typename: 'RunnerSetup',
+ },
+ },
+};
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
new file mode 100644
index 00000000000..48db60bfd33
--- /dev/null
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
@@ -0,0 +1,113 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import getRunnerPlatforms from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql';
+import getRunnerSetupInstructions from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql';
+import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue';
+
+import { mockGraphqlRunnerPlatforms, mockGraphqlInstructions } from './mock_data';
+
+const projectPath = 'gitlab-org/gitlab';
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('RunnerInstructions component', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]');
+ const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]');
+ const findArchitectureDropdownItems = () =>
+ wrapper.findAll('[data-testid="architecture-dropdown-item"]');
+ const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]');
+ const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]');
+
+ beforeEach(async () => {
+ const requestHandlers = [
+ [getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
+ [getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+
+ wrapper = shallowMount(RunnerInstructions, {
+ provide: {
+ projectPath,
+ },
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should show the "Show Runner installation instructions" button', () => {
+ const button = findModalButton();
+
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Show Runner installation instructions');
+ });
+
+ it('should contain a number of platforms buttons', () => {
+ const buttons = findPlatformButtons();
+
+ expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length);
+ });
+
+ it('should contain a number of dropdown items for the architecture options', () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ return wrapper.vm.$nextTick(() => {
+ const dropdownItems = findArchitectureDropdownItems();
+
+ expect(dropdownItems).toHaveLength(
+ mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length,
+ );
+ });
+ });
+
+ it('should display the binary installation instructions for a selected architecture', async () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItem = findArchitectureDropdownItems().at(0);
+ dropdownItem.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const runner = findBinaryInstructionsSection();
+
+ expect(runner.text()).toMatch('sudo chmod +x /usr/local/bin/gitlab-runner');
+ expect(runner.text()).toMatch(
+ `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash`,
+ );
+ expect(runner.text()).toMatch(
+ 'sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner',
+ );
+ expect(runner.text()).toMatch('sudo gitlab-runner start');
+ });
+
+ it('should display the runner register instructions for a selected architecture', async () => {
+ const platformButton = findPlatformButtons().at(0);
+ platformButton.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const dropdownItem = findArchitectureDropdownItems().at(0);
+ dropdownItem.vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ const runner = findRunnerInstructionsSection();
+
+ expect(runner.text()).toMatch(mockGraphqlInstructions.data.runnerSetup.registerInstructions);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap b/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap
new file mode 100644
index 00000000000..51b8aa162bc
--- /dev/null
+++ b/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap
@@ -0,0 +1,43 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Settings Block renders the correct markup 1`] = `
+<section
+ class="settings no-animate"
+>
+ <div
+ class="settings-header"
+ >
+ <h4>
+ <div
+ data-testid="title-slot"
+ />
+ </h4>
+
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ icon=""
+ size="medium"
+ variant="default"
+ >
+
+ Expand
+
+ </gl-button-stub>
+
+ <p>
+ <div
+ data-testid="description-slot"
+ />
+ </p>
+ </div>
+
+ <div
+ class="settings-content"
+ >
+ <div
+ data-testid="default-slot"
+ />
+ </div>
+</section>
+`;
diff --git a/spec/frontend/vue_shared/components/settings/settings_block_spec.js b/spec/frontend/vue_shared/components/settings/settings_block_spec.js
new file mode 100644
index 00000000000..2db0b001b5b
--- /dev/null
+++ b/spec/frontend/vue_shared/components/settings/settings_block_spec.js
@@ -0,0 +1,86 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/vue_shared/components/settings/settings_block.vue';
+
+describe('Settings Block', () => {
+ let wrapper;
+
+ const mountComponent = (propsData) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ slots: {
+ title: '<div data-testid="title-slot"></div>',
+ description: '<div data-testid="description-slot"></div>',
+ default: '<div data-testid="default-slot"></div>',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
+ const findTitleSlot = () => wrapper.find('[data-testid="title-slot"]');
+ const findDescriptionSlot = () => wrapper.find('[data-testid="description-slot"]');
+ const findExpandButton = () => wrapper.find(GlButton);
+
+ it('renders the correct markup', () => {
+ mountComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('has a default slot', () => {
+ mountComponent();
+
+ expect(findDefaultSlot().exists()).toBe(true);
+ });
+
+ it('has a title slot', () => {
+ mountComponent();
+
+ expect(findTitleSlot().exists()).toBe(true);
+ });
+
+ it('has a description slot', () => {
+ mountComponent();
+
+ expect(findDescriptionSlot().exists()).toBe(true);
+ });
+
+ describe('expanded behaviour', () => {
+ it('is collapsed by default', () => {
+ mountComponent();
+
+ expect(wrapper.classes('expanded')).toBe(false);
+ });
+
+ it('adds expanded class when the expand button is clicked', async () => {
+ mountComponent();
+
+ expect(wrapper.classes('expanded')).toBe(false);
+ expect(findExpandButton().text()).toBe('Expand');
+
+ await findExpandButton().vm.$emit('click');
+
+ expect(wrapper.classes('expanded')).toBe(true);
+ expect(findExpandButton().text()).toBe('Collapse');
+ });
+
+ it('is expanded when `defaultExpanded` is true no matter what', async () => {
+ mountComponent({ defaultExpanded: true });
+
+ expect(wrapper.classes('expanded')).toBe(true);
+
+ await findExpandButton().vm.$emit('click');
+
+ expect(wrapper.classes('expanded')).toBe(true);
+
+ await findExpandButton().vm.$emit('click');
+
+ expect(wrapper.classes('expanded')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
index fc1fa3fc1c1..3221e88192b 100644
--- a/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/date_picker_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
-import SidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
import DatePicker from '~/vue_shared/components/pikaday.vue';
+import SidebarDatePicker from '~/vue_shared/components/sidebar/date_picker.vue';
describe('SidebarDatePicker', () => {
let wrapper;
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 256b3cff525..a5a099d803a 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
@@ -1,5 +1,3 @@
-import { shallowMount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
import {
GlIcon,
GlLoadingIcon,
@@ -9,6 +7,8 @@ import {
GlSearchBoxByType,
GlButton,
} from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import IssuableMoveDropdown from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
index a55ad37c498..68ea94e72ce 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/base_spec.js
@@ -1,6 +1,6 @@
+import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
-import { shallowMount } from '@vue/test-utils';
import LabelsSelect from '~/labels_select';
import BaseComponent from '~/vue_shared/components/sidebar/labels_select/base.vue';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
index 4b4d265800b..322e632da02 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
@@ -79,7 +79,7 @@ describe('DropdownCreateLabelComponent', () => {
const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0].colorCode);
- expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
+ expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 153, 102);');
});
it('renders color input element', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
index 5cbbb99eaef..30dd92b72a4 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue';
const createComponent = (canEdit = true) =>
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
index ecb3c3a42c8..37f59c108df 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlLabel } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import DropdownValueComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_value.vue';
import { mockConfig, mockLabels } from './mock_data';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
index 648ba84fe8f..73716d4edf3 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
@@ -16,27 +16,27 @@ export const mockLabels = [
];
export const mockSuggestedColors = {
- '#0033CC': 'UA blue',
- '#428BCA': 'Moderate blue',
- '#44AD8E': 'Lime green',
- '#A8D695': 'Feijoa',
- '#5CB85C': 'Slightly desaturated green',
- '#69D100': 'Bright green',
- '#004E00': 'Very dark lime green',
- '#34495E': 'Very dark desaturated blue',
- '#7F8C8D': 'Dark grayish cyan',
- '#A295D6': 'Slightly desaturated blue',
- '#5843AD': 'Dark moderate blue',
- '#8E44AD': 'Dark moderate violet',
- '#FFECDB': 'Very pale orange',
- '#AD4363': 'Dark moderate pink',
- '#D10069': 'Strong pink',
- '#CC0033': 'Strong red',
- '#FF0000': 'Pure red',
- '#D9534F': 'Soft red',
- '#D1D100': 'Strong yellow',
- '#F0AD4E': 'Soft orange',
- '#AD8D43': 'Dark moderate orange',
+ '#009966': 'Green-cyan',
+ '#8fbc8f': 'Dark sea green',
+ '#3cb371': 'Medium sea green',
+ '#00b140': 'Green screen',
+ '#013220': 'Dark green',
+ '#6699cc': 'Blue-gray',
+ '#0000ff': 'Blue',
+ '#e6e6fa': 'Lavendar',
+ '#9400d3': 'Dark violet',
+ '#330066': 'Deep violet',
+ '#808080': 'Gray',
+ '#36454f': 'Charcoal grey',
+ '#f7e7ce': 'Champagne',
+ '#c21e56': 'Rose red',
+ '#cc338b': 'Magenta-pink',
+ '#dc143c': 'Crimson',
+ '#ff0000': 'Red',
+ '#cd5b45': 'Dark coral',
+ '#eee600': 'Titanium yellow',
+ '#ed9121': 'Carrot orange',
+ '#c39953': 'Aztec Gold',
};
export const mockConfig = {
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 951f706421f..59b170bfba9 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,7 +1,7 @@
-import Vuex from 'vuex';
+import { GlIcon, GlButton } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
-import { GlIcon, GlButton } from '@gitlab/ui';
import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
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 0f49fe4fc5b..c4a645082e6 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,7 +1,7 @@
-import Vuex from 'vuex';
+import { GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
-import { GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue';
import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
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 989cd256e26..60903933505 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
@@ -1,6 +1,3 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-
import {
GlIntersectionObserver,
GlButton,
@@ -8,14 +5,16 @@ import {
GlSearchBoxByType,
GlLink,
} from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+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';
import LabelItem from '~/vue_shared/components/sidebar/labels_select_vue/label_item.vue';
-import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state';
-import mutations from '~/vue_shared/components/sidebar/labels_select_vue/store/mutations';
import * as actions from '~/vue_shared/components/sidebar/labels_select_vue/store/actions';
import * as getters from '~/vue_shared/components/sidebar/labels_select_vue/store/getters';
+import mutations from '~/vue_shared/components/sidebar/labels_select_vue/store/mutations';
+import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state';
import { mockConfig, mockLabels, mockRegularLabel } from './mock_data';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
index 97946993857..1175d183c6c 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import DropdownContents from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue';
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 c1d9be7393c..726a113dbd9 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,7 +1,7 @@
-import Vuex from 'vuex';
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
index 70311f8235f..0d1d6ebcfe5 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
@@ -1,7 +1,7 @@
-import Vuex from 'vuex';
+import { GlLabel } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
-import { GlLabel } from '@gitlab/ui';
import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
index a6ec01ad7e1..bd1705e7693 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
@@ -1,6 +1,6 @@
+import { GlIcon, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlIcon, GlLink } from '@gitlab/ui';
import LabelItem from '~/vue_shared/components/sidebar/labels_select_vue/label_item.vue';
import { mockRegularLabel } from './mock_data';
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 1206450bbeb..4cf36df2502 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,15 +1,15 @@
-import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
-import LabelsSelectRoot from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
-import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
+import { isInViewport } from '~/lib/utils/common_utils';
import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue';
import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
import DropdownContents from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue';
+import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
+import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
+import LabelsSelectRoot from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
-import { isInViewport } from '~/lib/utils/common_utils';
import { mockConfig } from './mock_data';
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
index 9697d6c30f2..85a14226585 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
@@ -50,25 +50,25 @@ export const mockConfig = {
};
export const mockSuggestedColors = {
- '#0033CC': 'UA blue',
- '#428BCA': 'Moderate blue',
- '#44AD8E': 'Lime green',
- '#A8D695': 'Feijoa',
- '#5CB85C': 'Slightly desaturated green',
- '#69D100': 'Bright green',
- '#004E00': 'Very dark lime green',
- '#34495E': 'Very dark desaturated blue',
- '#7F8C8D': 'Dark grayish cyan',
- '#A295D6': 'Slightly desaturated blue',
- '#5843AD': 'Dark moderate blue',
- '#8E44AD': 'Dark moderate violet',
- '#FFECDB': 'Very pale orange',
- '#AD4363': 'Dark moderate pink',
- '#D10069': 'Strong pink',
- '#CC0033': 'Strong red',
- '#FF0000': 'Pure red',
- '#D9534F': 'Soft red',
- '#D1D100': 'Strong yellow',
- '#F0AD4E': 'Soft orange',
- '#AD8D43': 'Dark moderate orange',
+ '#009966': 'Green-cyan',
+ '#8fbc8f': 'Dark sea green',
+ '#3cb371': 'Medium sea green',
+ '#00b140': 'Green screen',
+ '#013220': 'Dark green',
+ '#6699cc': 'Blue-gray',
+ '#0000ff': 'Blue',
+ '#e6e6fa': 'Lavendar',
+ '#9400d3': 'Dark violet',
+ '#330066': 'Deep violet',
+ '#808080': 'Gray',
+ '#36454f': 'Charcoal grey',
+ '#f7e7ce': 'Champagne',
+ '#c21e56': 'Rose red',
+ '#cc338b': 'Magenta-pink',
+ '#dc143c': 'Crimson',
+ '#ff0000': 'Red',
+ '#cd5b45': 'Dark coral',
+ '#eee600': 'Titanium yellow',
+ '#ed9121': 'Carrot orange',
+ '#c39953': 'Aztec Gold',
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
index 4909c43bc96..3f11095cb04 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js
@@ -1,11 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state';
-import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types';
-import * as actions from '~/vue_shared/components/sidebar/labels_select_vue/store/actions';
-
import axios from '~/lib/utils/axios_utils';
+import * as actions from '~/vue_shared/components/sidebar/labels_select_vue/store/actions';
+import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types';
+import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state';
describe('LabelsSelect Actions', () => {
let state;
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
index 208f2f2d42d..ab266ac8aed 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/vue_shared/components/sidebar/labels_select_vue/store/mutations';
import * as types from '~/vue_shared/components/sidebar/labels_select_vue/store/mutation_types';
+import mutations from '~/vue_shared/components/sidebar/labels_select_vue/store/mutations';
describe('LabelsSelect Mutations', () => {
describe(`${types.SET_INITIAL_STATE}`, () => {
diff --git a/spec/frontend/vue_shared/components/smart_virtual_list_spec.js b/spec/frontend/vue_shared/components/smart_virtual_list_spec.js
index e5f9b94128e..8802a832781 100644
--- a/spec/frontend/vue_shared/components/smart_virtual_list_spec.js
+++ b/spec/frontend/vue_shared/components/smart_virtual_list_spec.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import SmartVirtualScrollList from '~/vue_shared/components/smart_virtual_list.vue';
describe('Toggle Button', () => {
diff --git a/spec/frontend/vue_shared/components/table_pagination_spec.js b/spec/frontend/vue_shared/components/table_pagination_spec.js
index 12c47637358..ed23a47c328 100644
--- a/spec/frontend/vue_shared/components/table_pagination_spec.js
+++ b/spec/frontend/vue_shared/components/table_pagination_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
describe('Pagination component', () => {
diff --git a/spec/frontend/vue_shared/components/tabs/tabs_spec.js b/spec/frontend/vue_shared/components/tabs/tabs_spec.js
index 49d92094b34..fe7be5be899 100644
--- a/spec/frontend/vue_shared/components/tabs/tabs_spec.js
+++ b/spec/frontend/vue_shared/components/tabs/tabs_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import Tabs from '~/vue_shared/components/tabs/tabs';
import Tab from '~/vue_shared/components/tabs/tab.vue';
+import Tabs from '~/vue_shared/components/tabs/tabs';
describe('Tabs component', () => {
let vm;
diff --git a/spec/frontend/vue_shared/components/todo_button_spec.js b/spec/frontend/vue_shared/components/todo_button_spec.js
index 1f8a214d632..8043bb7785b 100644
--- a/spec/frontend/vue_shared/components/todo_button_spec.js
+++ b/spec/frontend/vue_shared/components/todo_button_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, mount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import TodoButton from '~/vue_shared/components/todo_button.vue';
describe('Todo Button', () => {
@@ -33,7 +33,7 @@ describe('Todo Button', () => {
it.each`
label | isTodo
${'Mark as done'} | ${true}
- ${'Add a To Do'} | ${false}
+ ${'Add a to do'} | ${false}
`('sets correct label when isTodo is $isTodo', ({ label, isTodo }) => {
createComponent({ isTodo });
diff --git a/spec/frontend/vue_shared/components/toggle_button_spec.js b/spec/frontend/vue_shared/components/toggle_button_spec.js
deleted file mode 100644
index 2822b1999bc..00000000000
--- a/spec/frontend/vue_shared/components/toggle_button_spec.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import ToggleButton from '~/vue_shared/components/toggle_button.vue';
-
-describe('Toggle Button component', () => {
- let wrapper;
-
- function createComponent(propsData = {}) {
- wrapper = shallowMount(ToggleButton, {
- propsData,
- });
- }
-
- const findInput = () => wrapper.find('input');
- const findButton = () => wrapper.find('button');
- const findToggleIcon = () => wrapper.find(GlIcon);
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders input with provided name', () => {
- createComponent({
- name: 'foo',
- });
-
- expect(findInput().attributes('name')).toBe('foo');
- });
-
- describe.each`
- value | iconName
- ${true} | ${'status_success_borderless'}
- ${false} | ${'status_failed_borderless'}
- `('when `value` prop is `$value`', ({ value, iconName }) => {
- beforeEach(() => {
- createComponent({
- value,
- name: 'foo',
- });
- });
-
- it('renders input with correct value attribute', () => {
- expect(findInput().attributes('value')).toBe(`${value}`);
- });
-
- it('renders correct icon', () => {
- const icon = findToggleIcon();
- expect(icon.isVisible()).toBe(true);
- expect(icon.props('name')).toBe(iconName);
- expect(findButton().classes('is-checked')).toBe(value);
- });
-
- describe('when clicked', () => {
- it('emits `change` event with correct event', async () => {
- findButton().trigger('click');
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('change')).toStrictEqual([[!value]]);
- });
- });
- });
-
- describe('when `disabledInput` prop is `true`', () => {
- beforeEach(() => {
- createComponent({
- value: true,
- disabledInput: true,
- });
- });
-
- it('renders disabled button', () => {
- expect(findButton().classes()).toContain('is-disabled');
- });
-
- it('does not emit change event when clicked', async () => {
- findButton().trigger('click');
- await wrapper.vm.$nextTick();
-
- expect(wrapper.emitted('change')).toBeFalsy();
- });
- });
-
- describe('when `isLoading` prop is `true`', () => {
- beforeEach(() => {
- createComponent({
- value: true,
- isLoading: true,
- });
- });
-
- it('renders loading class', () => {
- expect(findButton().classes()).toContain('is-loading');
- });
- });
-});
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 11982eb513d..ace486b1f32 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,5 @@
-import { shallowMount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
jest.mock('~/flash');
diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
index d151cd15bc4..d62c4a98b10 100644
--- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
+++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -1,10 +1,10 @@
+import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { each } from 'lodash';
import { trimText } from 'helpers/text_helper';
-import { shallowMount } from '@vue/test-utils';
-import { GlLink } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
describe('User Avatar Link Component', () => {
let wrapper;
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 e3cd2bb9aaa..1d15da491cd 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,8 +1,8 @@
-import { shallowMount } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'spec/test_constants';
-import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue';
const TEST_IMAGE_SIZE = 7;
const TEST_BREAKPOINT = 5;
diff --git a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
index 435c3a5406e..a6c5e23ae14 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -1,8 +1,8 @@
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
-import UserAvailabilityStatus from '~/set_status_modal/components/user_availability_status.vue';
import { AVAILABILITY_STATUS } from '~/set_status_modal/utils';
+import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
+import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
const DEFAULT_PROPS = {
user: {
@@ -36,7 +36,7 @@ describe('User Popover Component', () => {
const findByTestId = (testid) => wrapper.find(`[data-testid="${testid}"]`);
const findUserStatus = () => wrapper.find('.js-user-status');
const findTarget = () => document.querySelector('.js-user-link');
- const findAvailabilityStatus = () => wrapper.find(UserAvailabilityStatus);
+ const findUserName = () => wrapper.find(UserNameWithStatus);
const createWrapper = (props = {}, options = {}) => {
wrapper = shallowMount(UserPopover, {
@@ -47,7 +47,7 @@ describe('User Popover Component', () => {
},
stubs: {
GlSprintf,
- UserAvailabilityStatus,
+ UserNameWithStatus,
},
...options,
});
@@ -213,7 +213,7 @@ describe('User Popover Component', () => {
createWrapper({ user });
- expect(findAvailabilityStatus().exists()).toBe(true);
+ expect(findUserName().exists()).toBe(true);
expect(wrapper.text()).toContain(user.name);
expect(wrapper.text()).toContain('(Busy)');
});
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 8ed072bed13..eb23a8ef457 100644
--- a/spec/frontend/vue_shared/components/web_ide_link_spec.js
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
+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 ActionsButton from '~/vue_shared/components/actions_button.vue';
const TEST_EDIT_URL = '/gitlab-test/test/-/edit/master/';
const TEST_WEB_IDE_URL = '/-/ide/project/gitlab-test/test/edit/master/-/';
diff --git a/spec/frontend/vue_shared/directives/tooltip_spec.js b/spec/frontend/vue_shared/directives/tooltip_spec.js
index 28ec23ad4c1..99e8b5b552b 100644
--- a/spec/frontend/vue_shared/directives/tooltip_spec.js
+++ b/spec/frontend/vue_shared/directives/tooltip_spec.js
@@ -1,6 +1,6 @@
+import { mount } from '@vue/test-utils';
import $ from 'jquery';
import { escape } from 'lodash';
-import { mount } from '@vue/test-utils';
import tooltip from '~/vue_shared/directives/tooltip';
const DEFAULT_TOOLTIP_TEMPLATE = '<div v-tooltip :title="tooltip"></div>';
diff --git a/spec/frontend/vue_shared/directives/track_event_spec.js b/spec/frontend/vue_shared/directives/track_event_spec.js
index 8d867c8e3fc..d7d7f4edc3f 100644
--- a/spec/frontend/vue_shared/directives/track_event_spec.js
+++ b/spec/frontend/vue_shared/directives/track_event_spec.js
@@ -1,11 +1,11 @@
-import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Tracking from '~/tracking';
import TrackEvent from '~/vue_shared/directives/track_event';
jest.mock('~/tracking');
-const Component = Vue.component('dummy-element', {
+const Component = Vue.component('DummyElement', {
directives: {
TrackEvent,
},
diff --git a/spec/frontend/vue_shared/security_reports/mock_data.js b/spec/frontend/vue_shared/security_reports/mock_data.js
index b3ff7daef2b..7918f70d702 100644
--- a/spec/frontend/vue_shared/security_reports/mock_data.js
+++ b/spec/frontend/vue_shared/security_reports/mock_data.js
@@ -322,6 +322,23 @@ export const secretScanningDiffSuccessMock = {
head_report_created_at: '2020-01-10T10:00:00.000Z',
};
+export const securityReportDownloadPathsQueryNoArtifactsResponse = {
+ project: {
+ mergeRequest: {
+ headPipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/176',
+ jobs: {
+ nodes: [],
+ __typename: 'CiJobConnection',
+ },
+ __typename: 'Pipeline',
+ },
+ __typename: 'MergeRequest',
+ },
+ __typename: 'Project',
+ },
+};
+
export const securityReportDownloadPathsQueryResponse = {
project: {
mergeRequest: {
diff --git a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
index 50d1d130675..0b4816a951e 100644
--- a/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
+++ b/spec/frontend/vue_shared/security_reports/security_reports_app_spec.js
@@ -1,6 +1,7 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { merge } from 'lodash';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -8,26 +9,26 @@ import { trimText } from 'helpers/text_helper';
import waitForPromises from 'helpers/wait_for_promises';
import {
expectedDownloadDropdownProps,
+ securityReportDownloadPathsQueryNoArtifactsResponse,
securityReportDownloadPathsQueryResponse,
sastDiffSuccessMock,
secretScanningDiffSuccessMock,
} from 'jest/vue_shared/security_reports/mock_data';
-import Api from '~/api';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import HelpIcon from '~/vue_shared/security_reports/components/help_icon.vue';
+import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
import {
REPORT_TYPE_SAST,
REPORT_TYPE_SECRET_DETECTION,
} from '~/vue_shared/security_reports/constants';
-import HelpIcon from '~/vue_shared/security_reports/components/help_icon.vue';
-import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue';
-import SecurityReportsApp from '~/vue_shared/security_reports/security_reports_app.vue';
import securityReportDownloadPathsQuery from '~/vue_shared/security_reports/queries/security_report_download_paths.query.graphql';
+import SecurityReportsApp from '~/vue_shared/security_reports/security_reports_app.vue';
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(VueApollo);
+Vue.use(Vuex);
const SAST_COMPARISON_PATH = '/sast.json';
const SECRET_SCANNING_COMPARISON_PATH = '/secret_detection.json';
@@ -47,7 +48,6 @@ describe('Security reports app', () => {
SecurityReportsApp,
merge(
{
- localVue,
propsData: { ...props },
stubs: {
HelpIcon: true,
@@ -60,187 +60,94 @@ describe('Security reports app', () => {
const pendingHandler = () => new Promise(() => {});
const successHandler = () => Promise.resolve({ data: securityReportDownloadPathsQueryResponse });
+ const successEmptyHandler = () =>
+ Promise.resolve({ data: securityReportDownloadPathsQueryNoArtifactsResponse });
const failureHandler = () => Promise.resolve({ errors: [{ message: 'some error' }] });
const createMockApolloProvider = (handler) => {
- localVue.use(VueApollo);
-
const requestHandlers = [[securityReportDownloadPathsQuery, handler]];
return createMockApollo(requestHandlers);
};
- const anyParams = expect.any(Object);
-
const findDownloadDropdown = () => wrapper.find(SecurityReportDownloadDropdown);
- const findPipelinesTabAnchor = () => wrapper.find('[data-testid="show-pipelines"]');
const findHelpIconComponent = () => wrapper.find(HelpIcon);
- const setupMockJobArtifact = (reportType) => {
- jest
- .spyOn(Api, 'pipelineJobs')
- .mockResolvedValue({ data: [{ artifacts: [{ file_type: reportType }] }] });
- };
- const expectPipelinesTabAnchor = () => {
- const mrTabsMock = { tabShown: jest.fn() };
- window.mrTabs = mrTabsMock;
- findPipelinesTabAnchor().trigger('click');
- expect(mrTabsMock.tabShown.mock.calls).toEqual([['pipelines']]);
- };
afterEach(() => {
wrapper.destroy();
- delete window.mrTabs;
});
- describe.each([false, true])(
- 'given the coreSecurityMrWidgetCounts feature flag is %p',
- (coreSecurityMrWidgetCounts) => {
- const createComponentWithFlag = (options) =>
- createComponent(
- merge(
- {
- provide: {
- glFeatures: {
- coreSecurityMrWidgetCounts,
- },
- },
- },
- options,
- ),
- );
-
- describe.each(SecurityReportsApp.reportTypes)('given a report type %p', (reportType) => {
- beforeEach(() => {
- window.mrTabs = { tabShown: jest.fn() };
- setupMockJobArtifact(reportType);
- createComponentWithFlag();
- return wrapper.vm.$nextTick();
- });
-
- it('calls the pipelineJobs API correctly', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledTimes(1);
- expect(Api.pipelineJobs).toHaveBeenCalledWith(
- props.projectId,
- props.pipelineId,
- anyParams,
- );
- });
-
- it('renders the expected message', () => {
- expect(wrapper.text()).toMatchInterpolatedText(
- SecurityReportsApp.i18n.scansHaveRunWithDownloadGuidance,
- );
- });
-
- describe('clicking the anchor to the pipelines tab', () => {
- it('calls the mrTabs.tabShown global', () => {
- expectPipelinesTabAnchor();
- });
- });
-
- it('renders a help link', () => {
- expect(findHelpIconComponent().props()).toEqual({
- helpPath: props.securityReportsDocsPath,
- discoverProjectSecurityPath: props.discoverProjectSecurityPath,
- });
- });
+ describe('given the artifacts query is loading', () => {
+ beforeEach(() => {
+ createComponent({
+ apolloProvider: createMockApolloProvider(pendingHandler),
});
+ });
- describe('given a report type "foo"', () => {
- beforeEach(() => {
- setupMockJobArtifact('foo');
- createComponentWithFlag();
- return wrapper.vm.$nextTick();
- });
-
- it('calls the pipelineJobs API correctly', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledTimes(1);
- expect(Api.pipelineJobs).toHaveBeenCalledWith(
- props.projectId,
- props.pipelineId,
- anyParams,
- );
- });
+ // TODO: Remove this assertion as part of
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/273431
+ it('initially renders nothing', () => {
+ expect(wrapper.html()).toBe('');
+ });
+ });
- it('renders nothing', () => {
- expect(wrapper.html()).toBe('');
- });
+ describe('given the artifacts query loads successfully', () => {
+ beforeEach(() => {
+ createComponent({
+ apolloProvider: createMockApolloProvider(successHandler),
});
+ });
- describe('security artifacts on last page of multi-page response', () => {
- const numPages = 3;
-
- beforeEach(() => {
- jest
- .spyOn(Api, 'pipelineJobs')
- .mockImplementation(async (projectId, pipelineId, { page }) => {
- const requestedPage = parseInt(page, 10);
- if (requestedPage < numPages) {
- return {
- // Some jobs with no relevant artifacts
- data: [{}, {}],
- headers: { 'x-next-page': String(requestedPage + 1) },
- };
- } else if (requestedPage === numPages) {
- return {
- data: [{ artifacts: [{ file_type: SecurityReportsApp.reportTypes[0] }] }],
- };
- }
-
- throw new Error('Test failed due to request of non-existent jobs page');
- });
-
- createComponentWithFlag();
- return wrapper.vm.$nextTick();
- });
+ it('renders the download dropdown', () => {
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
+ });
- it('fetches all pages', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledTimes(numPages);
- });
+ it('renders the expected message', () => {
+ expect(wrapper.text()).toContain(SecurityReportsApp.i18n.scansHaveRun);
+ });
- it('renders the expected message', () => {
- expect(wrapper.text()).toMatchInterpolatedText(
- SecurityReportsApp.i18n.scansHaveRunWithDownloadGuidance,
- );
- });
+ it('renders a help link', () => {
+ expect(findHelpIconComponent().props()).toEqual({
+ helpPath: props.securityReportsDocsPath,
+ discoverProjectSecurityPath: props.discoverProjectSecurityPath,
});
+ });
+ });
- describe('given an error from the API', () => {
- let error;
-
- beforeEach(() => {
- error = new Error('an error');
- jest.spyOn(Api, 'pipelineJobs').mockRejectedValue(error);
- createComponentWithFlag();
- return wrapper.vm.$nextTick();
- });
+ describe('given the artifacts query loads successfully with no artifacts', () => {
+ beforeEach(() => {
+ createComponent({
+ apolloProvider: createMockApolloProvider(successEmptyHandler),
+ });
+ });
- it('calls the pipelineJobs API correctly', () => {
- expect(Api.pipelineJobs).toHaveBeenCalledTimes(1);
- expect(Api.pipelineJobs).toHaveBeenCalledWith(
- props.projectId,
- props.pipelineId,
- anyParams,
- );
- });
+ // TODO: Remove this assertion as part of
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/273431
+ it('initially renders nothing', () => {
+ expect(wrapper.html()).toBe('');
+ });
+ });
- it('renders nothing', () => {
- expect(wrapper.html()).toBe('');
- });
+ describe('given the artifacts query fails', () => {
+ beforeEach(() => {
+ createComponent({
+ apolloProvider: createMockApolloProvider(failureHandler),
+ });
+ });
- it('calls createFlash correctly', () => {
- expect(createFlash.mock.calls).toEqual([
- [
- {
- message: SecurityReportsApp.i18n.apiError,
- captureError: true,
- error,
- },
- ],
- ]);
- });
+ it('calls createFlash correctly', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: SecurityReportsApp.i18n.apiError,
+ captureError: true,
+ error: expect.any(Error),
});
- },
- );
+ });
+
+ // TODO: Remove this assertion as part of
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/273431
+ it('renders nothing', () => {
+ expect(wrapper.html()).toBe('');
+ });
+ });
describe('given the coreSecurityMrWidgetCounts feature flag is enabled', () => {
let mock;
@@ -253,6 +160,7 @@ describe('Security reports app', () => {
coreSecurityMrWidgetCounts: true,
},
},
+ apolloProvider: createMockApolloProvider(successHandler),
}),
);
@@ -274,11 +182,7 @@ describe('Security reports app', () => {
${REPORT_TYPE_SECRET_DETECTION} | ${'secretScanningComparisonPath'} | ${SECRET_SCANNING_COMPARISON_PATH} | ${secretScanningDiffSuccessMock} | ${SECRET_SCANNING_SUCCESS_MESSAGE}
`(
'given a $pathProp and $reportType artifact',
- ({ reportType, pathProp, path, successResponse, successMessage }) => {
- beforeEach(() => {
- setupMockJobArtifact(reportType);
- });
-
+ ({ pathProp, path, successResponse, successMessage }) => {
describe('when loading', () => {
beforeEach(() => {
mock = new MockAdapter(axios, { delayResponse: 1 });
@@ -294,11 +198,11 @@ describe('Security reports app', () => {
});
it('should have loading message', () => {
- expect(wrapper.text()).toBe('Security scanning is loading');
+ expect(wrapper.text()).toContain('Security scanning is loading');
});
- it('should not render the pipeline tab anchor', () => {
- expect(findPipelinesTabAnchor().exists()).toBe(false);
+ it('renders the download dropdown', () => {
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
});
});
@@ -319,8 +223,8 @@ describe('Security reports app', () => {
expect(trimText(wrapper.text())).toContain(successMessage);
});
- it('should render the pipeline tab anchor', () => {
- expectPipelinesTabAnchor();
+ it('renders the download dropdown', () => {
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
});
});
@@ -341,125 +245,25 @@ describe('Security reports app', () => {
expect(trimText(wrapper.text())).toContain('Loading resulted in an error');
});
- it('should render the pipeline tab anchor', () => {
- expectPipelinesTabAnchor();
+ it('renders the download dropdown', () => {
+ expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
});
});
- },
- );
- });
-
- describe('given coreSecurityMrWidgetDownloads feature flag is enabled', () => {
- const createComponentWithFlagEnabled = (options) =>
- createComponent(
- merge(options, {
- provide: {
- glFeatures: {
- coreSecurityMrWidgetDownloads: true,
- },
- },
- }),
- );
-
- describe('given the query is loading', () => {
- beforeEach(() => {
- createComponentWithFlagEnabled({
- apolloProvider: createMockApolloProvider(pendingHandler),
- });
- });
- // TODO: Remove this assertion as part of
- // https://gitlab.com/gitlab-org/gitlab/-/issues/273431
- it('initially renders nothing', () => {
- expect(wrapper.html()).toBe('');
- });
- });
-
- describe('given the query loads successfully', () => {
- beforeEach(() => {
- createComponentWithFlagEnabled({
- apolloProvider: createMockApolloProvider(successHandler),
- });
- });
-
- it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
- });
-
- it('renders the expected message', () => {
- const text = wrapper.text();
- expect(text).not.toContain(SecurityReportsApp.i18n.scansHaveRunWithDownloadGuidance);
- expect(text).toContain(SecurityReportsApp.i18n.scansHaveRun);
- });
+ describe('when the comparison endpoint is not provided', () => {
+ beforeEach(() => {
+ mock.onGet(path).replyOnce(500);
- it('should not render the pipeline tab anchor', () => {
- expect(findPipelinesTabAnchor().exists()).toBe(false);
- });
- });
+ createComponentWithFlagEnabled();
- describe('given the query fails', () => {
- beforeEach(() => {
- createComponentWithFlagEnabled({
- apolloProvider: createMockApolloProvider(failureHandler),
- });
- });
+ return waitForPromises();
+ });
- it('calls createFlash correctly', () => {
- expect(createFlash).toHaveBeenCalledWith({
- message: SecurityReportsApp.i18n.apiError,
- captureError: true,
- error: expect.any(Error),
+ it('renders the basic scansHaveRun message', () => {
+ expect(wrapper.text()).toContain(SecurityReportsApp.i18n.scansHaveRun);
+ });
});
- });
-
- // TODO: Remove this assertion as part of
- // https://gitlab.com/gitlab-org/gitlab/-/issues/273431
- it('renders nothing', () => {
- expect(wrapper.html()).toBe('');
- });
- });
- });
-
- describe('given coreSecurityMrWidgetCounts and coreSecurityMrWidgetDownloads feature flags are enabled', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet(SAST_COMPARISON_PATH).replyOnce(200, sastDiffSuccessMock);
- mock.onGet(SECRET_SCANNING_COMPARISON_PATH).replyOnce(200, secretScanningDiffSuccessMock);
- createComponent({
- propsData: {
- sastComparisonPath: SAST_COMPARISON_PATH,
- secretScanningComparisonPath: SECRET_SCANNING_COMPARISON_PATH,
- },
- provide: {
- glFeatures: {
- coreSecurityMrWidgetCounts: true,
- coreSecurityMrWidgetDownloads: true,
- },
- },
- apolloProvider: createMockApolloProvider(successHandler),
- });
-
- return waitForPromises();
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('renders the download dropdown', () => {
- expect(findDownloadDropdown().props()).toEqual(expectedDownloadDropdownProps);
- });
-
- it('renders the expected counts message', () => {
- expect(trimText(wrapper.text())).toContain(
- 'Security scanning detected 3 potential vulnerabilities 2 Critical 1 High and 0 Others',
- );
- });
-
- it('should not render the pipeline tab anchor', () => {
- expect(findPipelinesTabAnchor().exists()).toBe(false);
- });
+ },
+ );
});
});
diff --git a/spec/frontend/vue_shared/security_reports/store/getters_spec.js b/spec/frontend/vue_shared/security_reports/store/getters_spec.js
index b146a281d7b..97746c7c38b 100644
--- a/spec/frontend/vue_shared/security_reports/store/getters_spec.js
+++ b/spec/frontend/vue_shared/security_reports/store/getters_spec.js
@@ -1,7 +1,3 @@
-import createState from '~/vue_shared/security_reports/store/state';
-import createSastState from '~/vue_shared/security_reports/store/modules/sast/state';
-import createSecretScanningState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
-import { groupedTextBuilder } from '~/vue_shared/security_reports/store/utils';
import {
groupedSummaryText,
allReportsHaveError,
@@ -11,6 +7,10 @@ import {
anyReportHasIssues,
summaryCounts,
} from '~/vue_shared/security_reports/store/getters';
+import createSastState from '~/vue_shared/security_reports/store/modules/sast/state';
+import createSecretScanningState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
+import createState from '~/vue_shared/security_reports/store/state';
+import { groupedTextBuilder } from '~/vue_shared/security_reports/store/utils';
import { CRITICAL, HIGH, LOW } from '~/vulnerabilities/constants';
const generateVuln = (severity) => ({ severity });
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js
index c9d1db8a504..6af07273cf6 100644
--- a/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js
+++ b/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createState from '~/vue_shared/security_reports/store/modules/sast/state';
-import * as types from '~/vue_shared/security_reports/store/modules/sast/mutation_types';
-import * as actions from '~/vue_shared/security_reports/store/modules/sast/actions';
import axios from '~/lib/utils/axios_utils';
+import * as actions from '~/vue_shared/security_reports/store/modules/sast/actions';
+import * as types from '~/vue_shared/security_reports/store/modules/sast/mutation_types';
+import createState from '~/vue_shared/security_reports/store/modules/sast/state';
const diffEndpoint = 'diff-endpoint.json';
const blobPath = 'blob-path.json';
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js
index fd611f38a34..d6119f44619 100644
--- a/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js
+++ b/spec/frontend/vue_shared/security_reports/store/modules/sast/mutations_spec.js
@@ -1,6 +1,6 @@
import * as types from '~/vue_shared/security_reports/store/modules/sast/mutation_types';
-import createState from '~/vue_shared/security_reports/store/modules/sast/state';
import mutations from '~/vue_shared/security_reports/store/modules/sast/mutations';
+import createState from '~/vue_shared/security_reports/store/modules/sast/state';
const createIssue = ({ ...config }) => ({ changed: false, ...config });
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js
index beda1a55438..d22fee864e7 100644
--- a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js
+++ b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js
@@ -1,10 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import createState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
-import * as types from '~/vue_shared/security_reports/store/modules/secret_detection/mutation_types';
-import * as actions from '~/vue_shared/security_reports/store/modules/secret_detection/actions';
import axios from '~/lib/utils/axios_utils';
+import * as actions from '~/vue_shared/security_reports/store/modules/secret_detection/actions';
+import * as types from '~/vue_shared/security_reports/store/modules/secret_detection/mutation_types';
+import createState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
const diffEndpoint = 'diff-endpoint.json';
const blobPath = 'blob-path.json';
diff --git a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js
index 13fcc0f47a3..42da7476a40 100644
--- a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js
+++ b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/mutations_spec.js
@@ -1,6 +1,6 @@
import * as types from '~/vue_shared/security_reports/store/modules/secret_detection/mutation_types';
-import createState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
import mutations from '~/vue_shared/security_reports/store/modules/secret_detection/mutations';
+import createState from '~/vue_shared/security_reports/store/modules/secret_detection/state';
const createIssue = ({ ...config }) => ({ changed: false, ...config });
diff --git a/spec/frontend/vue_shared/security_reports/utils_spec.js b/spec/frontend/vue_shared/security_reports/utils_spec.js
index 7e5a27694ef..aa9e54fa10c 100644
--- a/spec/frontend/vue_shared/security_reports/utils_spec.js
+++ b/spec/frontend/vue_shared/security_reports/utils_spec.js
@@ -1,9 +1,9 @@
-import { extractSecurityReportArtifacts } from '~/vue_shared/security_reports/utils';
import {
REPORT_TYPE_SAST,
REPORT_TYPE_SECRET_DETECTION,
REPORT_FILE_TYPES,
} from '~/vue_shared/security_reports/constants';
+import { extractSecurityReportArtifacts } from '~/vue_shared/security_reports/utils';
import {
securityReportDownloadPathsQueryResponse,
sastArtifacts,
diff --git a/spec/frontend/vuex_shared/modules/modal/actions_spec.js b/spec/frontend/vuex_shared/modules/modal/actions_spec.js
index a8269194c0b..c151049df2d 100644
--- a/spec/frontend/vuex_shared/modules/modal/actions_spec.js
+++ b/spec/frontend/vuex_shared/modules/modal/actions_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
-import * as types from '~/vuex_shared/modules/modal/mutation_types';
import * as actions from '~/vuex_shared/modules/modal/actions';
+import * as types from '~/vuex_shared/modules/modal/mutation_types';
describe('Vuex ModalModule actions', () => {
describe('open', () => {
diff --git a/spec/frontend/vuex_shared/modules/modal/mutations_spec.js b/spec/frontend/vuex_shared/modules/modal/mutations_spec.js
index eaaf196d1ec..8e9ab6e6c86 100644
--- a/spec/frontend/vuex_shared/modules/modal/mutations_spec.js
+++ b/spec/frontend/vuex_shared/modules/modal/mutations_spec.js
@@ -1,5 +1,5 @@
-import mutations from '~/vuex_shared/modules/modal/mutations';
import * as types from '~/vuex_shared/modules/modal/mutation_types';
+import mutations from '~/vuex_shared/modules/modal/mutations';
describe('Vuex ModalModule mutations', () => {
describe(`${types.SHOW}`, () => {
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index 13e6bec47ab..ad062d04140 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -1,6 +1,6 @@
+import { GlDrawer, GlInfiniteScroll, GlTabs } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlDrawer, GlInfiniteScroll, GlTabs } from '@gitlab/ui';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import App from '~/whats_new/components/app.vue';
diff --git a/spec/frontend/whats_new/store/actions_spec.js b/spec/frontend/whats_new/store/actions_spec.js
index 82f17a2726f..c4125d28aba 100644
--- a/spec/frontend/whats_new/store/actions_spec.js
+++ b/spec/frontend/whats_new/store/actions_spec.js
@@ -1,10 +1,10 @@
-import testAction from 'helpers/vuex_action_helper';
-import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import MockAdapter from 'axios-mock-adapter';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import testAction from 'helpers/vuex_action_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
import actions from '~/whats_new/store/actions';
import * as types from '~/whats_new/store/mutation_types';
-import axios from '~/lib/utils/axios_utils';
describe('whats new actions', () => {
describe('openDrawer', () => {
diff --git a/spec/frontend/whats_new/store/mutations_spec.js b/spec/frontend/whats_new/store/mutations_spec.js
index 4967fb51d2b..a95c6885a77 100644
--- a/spec/frontend/whats_new/store/mutations_spec.js
+++ b/spec/frontend/whats_new/store/mutations_spec.js
@@ -1,6 +1,6 @@
+import * as types from '~/whats_new/store/mutation_types';
import mutations from '~/whats_new/store/mutations';
import createState from '~/whats_new/store/state';
-import * as types from '~/whats_new/store/mutation_types';
describe('whats new mutations', () => {
let state;
diff --git a/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js b/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js
index d096a3cbdc6..b199f4f0c49 100644
--- a/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js
+++ b/spec/frontend/whats_new/utils/get_drawer_body_height_spec.js
@@ -1,5 +1,5 @@
-import { mount } from '@vue/test-utils';
import { GlDrawer } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
import { getDrawerBodyHeight } from '~/whats_new/utils/get_drawer_body_height';
describe('~/whats_new/utils/get_drawer_body_height', () => {
diff --git a/spec/frontend/zen_mode_spec.js b/spec/frontend/zen_mode_spec.js
index e874d018e92..5cc1d2200d3 100644
--- a/spec/frontend/zen_mode_spec.js
+++ b/spec/frontend/zen_mode_spec.js
@@ -1,11 +1,11 @@
-import $ from 'jquery';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Dropzone from 'dropzone';
+import $ from 'jquery';
import Mousetrap from 'mousetrap';
+import initNotes from '~/init_notes';
import * as utils from '~/lib/utils/common_utils';
import ZenMode from '~/zen_mode';
-import initNotes from '~/init_notes';
describe('ZenMode', () => {
let mock;
diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js
index 8d5d047b146..9e6bafc1297 100644
--- a/spec/frontend_integration/ide/helpers/ide_helper.js
+++ b/spec/frontend_integration/ide/helpers/ide_helper.js
@@ -69,7 +69,7 @@ const openFileRow = (row) => {
row.click();
};
-const findAndTraverseToPath = async (path, index = 0, row = null) => {
+export const findAndTraverseToPath = async (path, index = 0, row = null) => {
if (!path) {
return row;
}
@@ -110,6 +110,12 @@ const findAndClickRootAction = async (name) => {
button.click();
};
+/**
+ * Drop leading "/-/ide" and file path from the current URL
+ */
+export const getBaseRoute = (url = window.location.pathname) =>
+ url.replace(/^\/-\/ide/, '').replace(/\/-\/.*$/, '');
+
export const clickPreviewMarkdown = () => {
screen.getByText('Preview Markdown').click();
};
diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js
index 43a996286e7..173a9610c84 100644
--- a/spec/frontend_integration/ide/helpers/start.js
+++ b/spec/frontend_integration/ide/helpers/start.js
@@ -1,14 +1,15 @@
import { TEST_HOST } from 'helpers/test_constants';
-import extendStore from '~/ide/stores/extend';
-import { IDE_DATASET } from './mock_data';
import { initIde } from '~/ide';
import Editor from '~/ide/lib/editor';
+import extendStore from '~/ide/stores/extend';
+import { IDE_DATASET } from './mock_data';
+
+export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) => {
+ const projectName = isRepoEmpty ? 'lorem-ipsum-empty' : 'lorem-ipsum';
+ const pathSuffix = mrId ? `merge_requests/${mrId}` : `tree/master/-/${path}`;
-export default (container, { isRepoEmpty = false, path = '' } = {}) => {
global.jsdom.reconfigure({
- url: `${TEST_HOST}/-/ide/project/gitlab-test/lorem-ipsum${
- isRepoEmpty ? '-empty' : ''
- }/tree/master/-/${path}`,
+ url: `${TEST_HOST}/-/ide/project/gitlab-test/${projectName}/${pathSuffix}`,
});
const el = document.createElement('div');
diff --git a/spec/frontend_integration/ide/ide_integration_spec.js b/spec/frontend_integration/ide/ide_integration_spec.js
index 00a73661d14..3ce88de11fe 100644
--- a/spec/frontend_integration/ide/ide_integration_spec.js
+++ b/spec/frontend_integration/ide/ide_integration_spec.js
@@ -1,8 +1,8 @@
-import { waitForText } from 'helpers/wait_for_text';
-import waitForPromises from 'helpers/wait_for_promises';
import { setTestTimeout } from 'helpers/timeout';
-import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
+import waitForPromises from 'helpers/wait_for_promises';
+import { waitForText } from 'helpers/wait_for_text';
import { createCommitId } from 'test_helpers/factories/commit_id';
+import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
diff --git a/spec/frontend_integration/ide/user_opens_file_spec.js b/spec/frontend_integration/ide/user_opens_file_spec.js
index 7fa6dcecc9e..2cb3363ef85 100644
--- a/spec/frontend_integration/ide/user_opens_file_spec.js
+++ b/spec/frontend_integration/ide/user_opens_file_spec.js
@@ -1,5 +1,5 @@
-import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import { screen } from '@testing-library/dom';
+import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
diff --git a/spec/frontend_integration/ide/user_opens_ide_spec.js b/spec/frontend_integration/ide/user_opens_ide_spec.js
index 502cb2e2c7d..f56cd008d1c 100644
--- a/spec/frontend_integration/ide/user_opens_ide_spec.js
+++ b/spec/frontend_integration/ide/user_opens_ide_spec.js
@@ -1,5 +1,5 @@
-import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import { screen } from '@testing-library/dom';
+import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
diff --git a/spec/frontend_integration/ide/user_opens_mr_spec.js b/spec/frontend_integration/ide/user_opens_mr_spec.js
new file mode 100644
index 00000000000..9cf0ff5da56
--- /dev/null
+++ b/spec/frontend_integration/ide/user_opens_mr_spec.js
@@ -0,0 +1,60 @@
+import { basename } from 'path';
+import { getMergeRequests, getMergeRequestWithChanges } from 'test_helpers/fixtures';
+import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
+import * as ideHelper from './helpers/ide_helper';
+import startWebIDE from './helpers/start';
+
+const getRelevantChanges = () =>
+ getMergeRequestWithChanges().changes.filter((x) => !x.deleted_file);
+
+describe('IDE: User opens Merge Request', () => {
+ useOverclockTimers();
+
+ let vm;
+ let container;
+ let changes;
+
+ beforeEach(async () => {
+ const [{ iid: mrId }] = getMergeRequests();
+
+ changes = getRelevantChanges();
+
+ setFixtures('<div class="webide-container"></div>');
+ container = document.querySelector('.webide-container');
+
+ vm = startWebIDE(container, { mrId });
+
+ await ideHelper.waitForTabToOpen(basename(changes[0].new_path));
+ await ideHelper.waitForMonacoEditor();
+ });
+
+ afterEach(async () => {
+ vm.$destroy();
+ vm = null;
+ });
+
+ const findAllTabs = () => Array.from(document.querySelectorAll('.multi-file-tab'));
+ const findAllTabsData = () =>
+ findAllTabs().map((el) => ({
+ title: el.getAttribute('title'),
+ text: el.textContent.trim(),
+ }));
+
+ it('shows first change as active in file tree', async () => {
+ const firstPath = changes[0].new_path;
+ const row = await ideHelper.findAndTraverseToPath(firstPath);
+
+ expect(row).toHaveClass('is-open');
+ expect(row).toHaveClass('is-active');
+ });
+
+ it('opens other changes', () => {
+ // We only show first 10 changes
+ const expectedTabs = changes.slice(0, 10).map((x) => ({
+ title: `${ideHelper.getBaseRoute()}/-/${x.new_path}/`,
+ text: basename(x.new_path),
+ }));
+
+ expect(findAllTabsData()).toEqual(expectedTabs);
+ });
+});
diff --git a/spec/frontend_integration/test_helpers/factories/commit.js b/spec/frontend_integration/test_helpers/factories/commit.js
index 09bb5fd589b..196295addbe 100644
--- a/spec/frontend_integration/test_helpers/factories/commit.js
+++ b/spec/frontend_integration/test_helpers/factories/commit.js
@@ -1,5 +1,5 @@
-import { withValues } from '../utils/obj';
import { getCommit } from '../fixtures';
+import { withValues } from '../utils/obj';
import { createCommitId } from './commit_id';
export const createNewCommit = ({ id = createCommitId(), message }, orig = getCommit()) => {
diff --git a/spec/frontend_integration/test_helpers/fixtures.js b/spec/frontend_integration/test_helpers/fixtures.js
index fde3fd8cb63..b2768440607 100644
--- a/spec/frontend_integration/test_helpers/fixtures.js
+++ b/spec/frontend_integration/test_helpers/fixtures.js
@@ -1,4 +1,10 @@
-/* eslint-disable global-require, import/no-unresolved */
+/* eslint-disable global-require */
+// We use "require" rather than `fs` so that this works in a browser environment.
+
+/* eslint "import/no-unresolved": 0 */
+// We don't want to require *all* fixtures to be generated (especailly in a local environment).
+// We use `eslint` instead of `eslint-disable`, so that we also don't trigger an `Unused eslint-disable directive` when all fixtures are present.
+
import { memoize } from 'lodash';
const createFactoryWithDefault = (fn, defaultValue) => () => {
@@ -25,6 +31,12 @@ export const getBranch = factory.json(() =>
export const getMergeRequests = factory.json(() =>
require('test_fixtures/api/merge_requests/get.json'),
);
+export const getMergeRequestWithChanges = factory.json(() =>
+ require('test_fixtures/api/merge_requests/changes.json'),
+);
+export const getMergeRequestVersions = factory.json(() =>
+ require('test_fixtures/api/merge_requests/versions.json'),
+);
export const getRepositoryFiles = factory.json(() =>
require('test_fixtures/projects_json/files.json'),
);
diff --git a/spec/frontend_integration/test_helpers/mock_server/index.js b/spec/frontend_integration/test_helpers/mock_server/index.js
index 2aebdefaafb..20cb441daa7 100644
--- a/spec/frontend_integration/test_helpers/mock_server/index.js
+++ b/spec/frontend_integration/test_helpers/mock_server/index.js
@@ -4,6 +4,8 @@ import {
getEmptyProject,
getBranch,
getMergeRequests,
+ getMergeRequestWithChanges,
+ getMergeRequestVersions,
getRepositoryFiles,
getBlobReadme,
getBlobImage,
@@ -16,6 +18,8 @@ export const createMockServerOptions = () => ({
project: Model,
branch: Model,
mergeRequest: Model,
+ mergeRequestChange: Model,
+ mergeRequestVersion: Model,
file: Model,
userPermission: Model,
},
@@ -30,6 +34,8 @@ export const createMockServerOptions = () => ({
projects: [getProject(), getEmptyProject()],
branches: [getBranch()],
mergeRequests: getMergeRequests(),
+ mergeRequestChanges: [getMergeRequestWithChanges()],
+ mergeRequestVersions: getMergeRequestVersions(),
filesRaw: [
{
raw: getBlobReadme(),
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/404.js b/spec/frontend_integration/test_helpers/mock_server/routes/404.js
index bc8edba927e..54183f1189c 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/404.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/404.js
@@ -1,3 +1,5 @@
+import { Response } from 'miragejs';
+
export default (server) => {
['get', 'post', 'put', 'delete', 'patch'].forEach((method) => {
server[method]('*', () => {
diff --git a/spec/frontend_integration/test_helpers/mock_server/routes/projects.js b/spec/frontend_integration/test_helpers/mock_server/routes/projects.js
index de37aa98eee..e6e09121fd4 100644
--- a/spec/frontend_integration/test_helpers/mock_server/routes/projects.js
+++ b/spec/frontend_integration/test_helpers/mock_server/routes/projects.js
@@ -20,4 +20,22 @@ export default (server) => {
return result.models;
});
+
+ server.get('/api/v4/projects/:id/merge_requests/:mid', (schema, request) => {
+ const mr = schema.mergeRequests.findBy({ iid: request.params.mid });
+
+ return mr.attrs;
+ });
+
+ server.get('/api/v4/projects/:id/merge_requests/:mid/versions', (schema, request) => {
+ const versions = schema.mergeRequestVersions.where({ merge_request_id: request.params.mid });
+
+ return versions.models;
+ });
+
+ server.get('/api/v4/projects/:id/merge_requests/:mid/changes', (schema, request) => {
+ const mrWithChanges = schema.mergeRequestChanges.findBy({ iid: request.params.mid });
+
+ return mrWithChanges.attrs;
+ });
};
diff --git a/spec/graphql/mutations/boards/lists/create_spec.rb b/spec/graphql/mutations/boards/lists/create_spec.rb
index 894dd1f34b4..815064e7c58 100644
--- a/spec/graphql/mutations/boards/lists/create_spec.rb
+++ b/spec/graphql/mutations/boards/lists/create_spec.rb
@@ -3,84 +3,8 @@
require 'spec_helper'
RSpec.describe Mutations::Boards::Lists::Create do
- include GraphqlHelpers
-
let_it_be(:group) { create(:group, :private) }
let_it_be(:board) { create(:board, group: group) }
- let_it_be(:user) { create(:user) }
- let_it_be(:guest) { create(:user) }
-
- let(:current_user) { user }
- let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
- let(:list_create_params) { {} }
-
- before_all do
- group.add_reporter(user)
- group.add_guest(guest)
- end
-
- subject { mutation.resolve(board_id: board.to_global_id.to_s, **list_create_params) }
-
- describe '#ready?' do
- it 'raises an error if required arguments are missing' do
- expect { mutation.ready?(board_id: 'some id') }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/)
- end
-
- it 'raises an error if too many required arguments are specified' do
- expect { mutation.ready?(board_id: 'some id', backlog: true, label_id: 'some label') }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/)
- end
- end
-
- describe '#resolve' do
- context 'with proper permissions' do
- describe 'backlog list' do
- let(:list_create_params) { { backlog: true } }
-
- it 'creates one and only one backlog' do
- expect { subject }.to change { board.lists.backlog.count }.from(0).to(1)
- expect(board.lists.backlog.first.list_type).to eq 'backlog'
-
- backlog_id = board.lists.backlog.first.id
-
- expect { subject }.not_to change { board.lists.backlog.count }
- expect(board.lists.backlog.last.id).to eq backlog_id
- end
- end
-
- describe 'label list' do
- let_it_be(:dev_label) do
- create(:group_label, title: 'Development', color: '#FFAABB', group: group)
- end
-
- let(:list_create_params) { { label_id: dev_label.to_global_id.to_s } }
-
- it 'creates a new issue board list for labels' do
- expect { subject }.to change { board.lists.count }.from(1).to(2)
-
- new_list = subject[:list]
-
- expect(new_list.title).to eq dev_label.title
- expect(new_list.position).to eq 0
- end
-
- context 'when label not found' do
- let(:list_create_params) { { label_id: "gid://gitlab/Label/#{non_existing_record_id}" } }
-
- it 'returns an error' do
- expect(subject[:errors]).to include 'Label not found'
- end
- end
- end
- end
-
- context 'without proper permissions' do
- let(:current_user) { guest }
- it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- end
- end
- end
+ it_behaves_like 'board lists create mutation'
end
diff --git a/spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb b/spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb
new file mode 100644
index 00000000000..ee8db7a1f31
--- /dev/null
+++ b/spec/graphql/mutations/concerns/mutations/can_mutate_spammable_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::CanMutateSpammable do
+ let(:mutation_class) do
+ Class.new(Mutations::BaseMutation) do
+ include Mutations::CanMutateSpammable
+ end
+ end
+
+ let(:request) { double(:request) }
+ let(:query) { double(:query, schema: GitlabSchema) }
+ let(:context) { GraphQL::Query::Context.new(query: query, object: nil, values: { request: request }) }
+
+ subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) }
+
+ describe '#additional_spam_params' do
+ it 'returns additional spam-related params' do
+ expect(subject.send(:additional_spam_params)).to eq({ api: true, request: request })
+ end
+ end
+
+ describe '#with_spam_action_fields' do
+ let(:spam_log) { double(:spam_log, id: 1) }
+ let(:spammable) { double(:spammable, spam?: true, render_recaptcha?: true, spam_log: spam_log) }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:recaptcha_site_key) { 'abc123' }
+ end
+
+ it 'merges in spam action fields from spammable' do
+ result = subject.send(:with_spam_action_fields, spammable) do
+ { other_field: true }
+ end
+ expect(result)
+ .to eq({
+ spam: true,
+ needs_captcha_response: true,
+ spam_log_id: 1,
+ captcha_site_key: 'abc123',
+ other_field: true
+ })
+ end
+ end
+end
diff --git a/spec/graphql/mutations/merge_requests/update_spec.rb b/spec/graphql/mutations/merge_requests/update_spec.rb
index 8acd2562ea8..206abaf34ce 100644
--- a/spec/graphql/mutations/merge_requests/update_spec.rb
+++ b/spec/graphql/mutations/merge_requests/update_spec.rb
@@ -12,10 +12,11 @@ RSpec.describe Mutations::MergeRequests::Update do
describe '#resolve' do
let(:attributes) { { title: 'new title', description: 'new description', target_branch: 'new-branch' } }
+ let(:arguments) { attributes }
let(:mutated_merge_request) { subject[:merge_request] }
subject do
- mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, **attributes)
+ mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, **arguments)
end
it_behaves_like 'permission level for merge request mutation is correctly verified'
@@ -61,6 +62,24 @@ RSpec.describe Mutations::MergeRequests::Update do
expect(mutated_merge_request).to have_attributes(attributes)
end
end
+
+ context 'when closing the MR' do
+ let(:arguments) { { state_event: ::Types::MergeRequestStateEventEnum.values['CLOSED'].value } }
+
+ it 'closes the MR' do
+ expect(mutated_merge_request).to be_closed
+ end
+ end
+
+ context 'when re-opening the MR' do
+ let(:arguments) { { state_event: ::Types::MergeRequestStateEventEnum.values['OPEN'].value } }
+
+ it 'closes the MR' do
+ merge_request.close!
+
+ expect(mutated_merge_request).to be_open
+ end
+ end
end
end
end
diff --git a/spec/graphql/mutations/security/ci_configuration/configure_sast_spec.rb b/spec/graphql/mutations/security/ci_configuration/configure_sast_spec.rb
new file mode 100644
index 00000000000..ed03a1cb906
--- /dev/null
+++ b/spec/graphql/mutations/security/ci_configuration/configure_sast_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Security::CiConfiguration::ConfigureSast do
+ subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
+
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let_it_be(:service_result_json) do
+ {
+ status: "success",
+ success_path: "http://127.0.0.1:3000/root/demo-historic-secrets/-/merge_requests/new?",
+ errors: nil
+ }
+ end
+
+ let_it_be(:service_error_result_json) do
+ {
+ status: "error",
+ success_path: nil,
+ errors: %w(error1 error2)
+ }
+ end
+
+ let(:context) do
+ GraphQL::Query::Context.new(
+ query: OpenStruct.new(schema: nil),
+ values: { current_user: user },
+ object: nil
+ )
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:push_code) }
+
+ describe '#resolve' do
+ subject { mutation.resolve(project_path: project.full_path, configuration: {}) }
+
+ let(:result) { subject }
+
+ it 'raises an error if the resource is not accessible to the user' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+
+ context 'when user does not have enough permissions' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when user is a maintainer of a different project' do
+ before do
+ create(:project_empty_repo).add_maintainer(user)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when the user does not have permission to create a new branch' do
+ before_all do
+ project.add_developer(user)
+ end
+
+ let(:error_message) { 'You are not allowed to create protected branches on this project.' }
+
+ it 'returns an array of errors' do
+ allow_next_instance_of(::Files::MultiService) do |multi_service|
+ allow(multi_service).to receive(:execute).and_raise(Gitlab::Git::PreReceiveError.new("GitLab: #{error_message}"))
+ end
+
+ expect(result).to match(
+ status: :error,
+ success_path: nil,
+ errors: match_array([error_message])
+ )
+ end
+ end
+
+ context 'when the user can create a merge request' do
+ before_all do
+ project.add_developer(user)
+ end
+
+ context 'when service successfully generates a path to create a new merge request' do
+ it 'returns a success path' do
+ allow_next_instance_of(::Security::CiConfiguration::SastCreateService) do |service|
+ allow(service).to receive(:execute).and_return(service_result_json)
+ end
+
+ expect(result).to match(
+ status: 'success',
+ success_path: service_result_json[:success_path],
+ errors: []
+ )
+ end
+ end
+
+ context 'when service can not generate any path to create a new merge request' do
+ it 'returns an array of errors' do
+ allow_next_instance_of(::Security::CiConfiguration::SastCreateService) do |service|
+ allow(service).to receive(:execute).and_return(service_error_result_json)
+ end
+
+ expect(result).to match(
+ status: 'error',
+ success_path: be_nil,
+ errors: match_array(service_error_result_json[:errors])
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/base_resolver_spec.rb b/spec/graphql/resolvers/base_resolver_spec.rb
index 8a24b69eb6f..8d2ae238bfe 100644
--- a/spec/graphql/resolvers/base_resolver_spec.rb
+++ b/spec/graphql/resolvers/base_resolver_spec.rb
@@ -277,8 +277,8 @@ RSpec.describe Resolvers::BaseResolver do
describe '#offset_pagination' do
let(:instance) { resolver_instance(resolver) }
- it 'is sugar for OffsetActiveRecordRelationConnection.new' do
- expect(instance.offset_pagination(User.none)).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
+ it 'is sugar for OffsetPaginatedRelation.new' do
+ expect(instance.offset_pagination(User.none)).to be_a(::Gitlab::Graphql::Pagination::OffsetPaginatedRelation)
end
end
end
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
index e7c56a526f4..5eda840854a 100644
--- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
@@ -23,19 +23,19 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
it 'returns the issues in the correct order' do
# by relative_position and then ID
- issues = resolve_board_list_issues.items
+ issues = resolve_board_list_issues
expect(issues.map(&:id)).to eq [issue3.id, issue1.id, issue2.id]
end
it 'finds only issues matching filters' do
- result = resolve_board_list_issues(args: { filters: { label_name: [label.title], not: { label_name: [label2.title] } } }).items
+ result = resolve_board_list_issues(args: { filters: { label_name: [label.title], not: { label_name: [label2.title] } } })
expect(result).to match_array([issue1, issue3])
end
it 'finds only issues matching search param' do
- result = resolve_board_list_issues(args: { filters: { search: issue1.title } }).items
+ result = resolve_board_list_issues(args: { filters: { search: issue1.title } })
expect(result).to match_array([issue1])
end
diff --git a/spec/graphql/resolvers/board_lists_resolver_spec.rb b/spec/graphql/resolvers/board_lists_resolver_spec.rb
index 71ebec4dc7e..fdcebd30bb3 100644
--- a/spec/graphql/resolvers/board_lists_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_lists_resolver_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Resolvers::BoardListsResolver do
end
it 'does not create the backlog list' do
- lists = resolve_board_lists.items
+ lists = resolve_board_lists
expect(lists.count).to eq 1
expect(lists[0].list_type).to eq 'closed'
@@ -38,7 +38,7 @@ RSpec.describe Resolvers::BoardListsResolver do
let!(:backlog_list) { create(:backlog_list, board: board) }
it 'returns a list of board lists' do
- lists = resolve_board_lists.items
+ lists = resolve_board_lists
expect(lists.count).to eq 3
expect(lists.map(&:list_type)).to eq %w(backlog label closed)
@@ -50,7 +50,7 @@ RSpec.describe Resolvers::BoardListsResolver do
end
it 'returns the complete list of board lists for this user' do
- lists = resolve_board_lists.items
+ lists = resolve_board_lists
expect(lists.count).to eq 3
end
@@ -58,7 +58,7 @@ RSpec.describe Resolvers::BoardListsResolver do
context 'when querying for a single list' do
it 'returns specified list' do
- list = resolve_board_lists(args: { id: global_id_of(label_list) }).items
+ list = resolve_board_lists(args: { id: global_id_of(label_list) })
expect(list).to eq [label_list]
end
@@ -69,13 +69,13 @@ RSpec.describe Resolvers::BoardListsResolver do
external_label = create(:group_label, group: group)
external_list = create(:list, board: external_board, label: external_label)
- list = resolve_board_lists(args: { id: global_id_of(external_list) }).items
+ list = resolve_board_lists(args: { id: global_id_of(external_list) })
expect(list).to eq List.none
end
it 'raises an argument error if list ID is not valid' do
- expect { resolve_board_lists(args: { id: 'test' }).items }
+ expect { resolve_board_lists(args: { id: 'test' }) }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end
diff --git a/spec/graphql/resolvers/ci/config_resolver_spec.rb b/spec/graphql/resolvers/ci/config_resolver_spec.rb
index ca7ae73fef8..73e9fab9f99 100644
--- a/spec/graphql/resolvers/ci/config_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/config_resolver_spec.rb
@@ -36,7 +36,8 @@ RSpec.describe Resolvers::Ci::ConfigResolver do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_includes.yml'))
end
- it 'lints the ci config file' do
+ it 'lints the ci config file and returns the merged yaml file' do
+ expect(response[:merged_yaml]).to eq(content)
expect(response[:status]).to eq(:valid)
expect(response[:errors]).to be_empty
end
diff --git a/spec/graphql/resolvers/container_repositories_resolver_spec.rb b/spec/graphql/resolvers/container_repositories_resolver_spec.rb
index b888d79626e..a17d2a7b0d5 100644
--- a/spec/graphql/resolvers/container_repositories_resolver_spec.rb
+++ b/spec/graphql/resolvers/container_repositories_resolver_spec.rb
@@ -27,6 +27,34 @@ RSpec.describe Resolvers::ContainerRepositoriesResolver do
it { is_expected.to contain_exactly(named_container_repository) }
end
+
+ context 'with a sort argument' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:sort_repository) do
+ create(:container_repository, name: 'bar', project: project, created_at: 1.day.ago)
+ end
+
+ let_it_be(:sort_repository2) do
+ create(:container_repository, name: 'foo', project: project, created_at: 1.hour.ago, updated_at: 1.hour.ago)
+ end
+
+ [:created_desc, :updated_asc, :name_desc].each do |order|
+ context "#{order}" do
+ let(:args) { { sort: order } }
+
+ it { is_expected.to eq([sort_repository2, sort_repository]) }
+ end
+ end
+
+ [:created_asc, :updated_desc, :name_asc].each do |order|
+ context "#{order}" do
+ let(:args) { { sort: order } }
+
+ it { is_expected.to eq([sort_repository, sort_repository2]) }
+ end
+ end
+ end
end
context 'with authorized user' do
diff --git a/spec/graphql/resolvers/group_labels_resolver_spec.rb b/spec/graphql/resolvers/group_labels_resolver_spec.rb
new file mode 100644
index 00000000000..ed94f12502a
--- /dev/null
+++ b/spec/graphql/resolvers/group_labels_resolver_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::GroupLabelsResolver do
+ include GraphqlHelpers
+
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group, reload: true) { create(:group, :private) }
+ let_it_be(:subgroup, reload: true) { create(:group, :private, parent: group) }
+ let_it_be(:sub_subgroup, reload: true) { create(:group, :private, parent: subgroup) }
+ let_it_be(:project, reload: true) { create(:project, :private, group: sub_subgroup) }
+ let_it_be(:label1) { create(:label, project: project, name: 'project feature') }
+ let_it_be(:label2) { create(:label, project: project, name: 'new project feature') }
+ let_it_be(:group_label1) { create(:group_label, group: group, name: 'group feature') }
+ let_it_be(:group_label2) { create(:group_label, group: group, name: 'new group feature') }
+ let_it_be(:subgroup_label1) { create(:group_label, group: subgroup, name: 'subgroup feature') }
+ let_it_be(:subgroup_label2) { create(:group_label, group: subgroup, name: 'new subgroup feature') }
+ let_it_be(:sub_subgroup_label1) { create(:group_label, group: sub_subgroup, name: 'sub_subgroup feature') }
+ let_it_be(:sub_subgroup_label2) { create(:group_label, group: sub_subgroup, name: 'new sub_subgroup feature') }
+
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::LabelType.connection_type)
+ end
+
+ describe '#resolve' do
+ context 'with unauthorized user' do
+ it 'raises error' do
+ expect { resolve_labels(subgroup) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with authorized user' do
+ it 'does not raise error' do
+ group.add_guest(current_user)
+
+ expect { resolve_labels(subgroup) }.not_to raise_error
+ end
+ end
+
+ context 'without parent' do
+ it 'returns no labels' do
+ expect(resolve_labels(nil)).to eq(Label.none)
+ end
+ end
+
+ context 'at group level' do
+ before_all do
+ group.add_developer(current_user)
+ end
+
+ # because :include_ancestor_groups, :include_descendant_groups, :only_group_labels default to false
+ # the `nil` value would be equivalent to passing in `false` so just check for `nil` option
+ where(:include_ancestor_groups, :include_descendant_groups, :only_group_labels, :search_term, :test) do
+ nil | nil | nil | nil | -> { expect(subject).to contain_exactly(subgroup_label1, subgroup_label2) }
+ nil | nil | true | nil | -> { expect(subject).to contain_exactly(subgroup_label1, subgroup_label2) }
+ nil | true | nil | nil | -> { expect(subject).to contain_exactly(subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2, label1, label2) }
+ nil | true | true | nil | -> { expect(subject).to contain_exactly(subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2) }
+ true | nil | nil | nil | -> { expect(subject).to contain_exactly(group_label1, group_label2, subgroup_label1, subgroup_label2) }
+ true | nil | true | nil | -> { expect(subject).to contain_exactly(group_label1, group_label2, subgroup_label1, subgroup_label2) }
+ true | true | nil | nil | -> { expect(subject).to contain_exactly(group_label1, group_label2, subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2, label1, label2) }
+ true | true | true | nil | -> { expect(subject).to contain_exactly(group_label1, group_label2, subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2) }
+
+ nil | nil | nil | 'new' | -> { expect(subject).to contain_exactly(subgroup_label2) }
+ nil | nil | true | 'new' | -> { expect(subject).to contain_exactly(subgroup_label2) }
+ nil | true | nil | 'new' | -> { expect(subject).to contain_exactly(subgroup_label2, sub_subgroup_label2, label2) }
+ nil | true | true | 'new' | -> { expect(subject).to contain_exactly(subgroup_label2, sub_subgroup_label2) }
+ true | nil | nil | 'new' | -> { expect(subject).to contain_exactly(group_label2, subgroup_label2) }
+ true | nil | true | 'new' | -> { expect(subject).to contain_exactly(group_label2, subgroup_label2) }
+ true | true | nil | 'new' | -> { expect(subject).to contain_exactly(group_label2, subgroup_label2, sub_subgroup_label2, label2) }
+ true | true | true | 'new' | -> { expect(subject).to contain_exactly(group_label2, subgroup_label2, sub_subgroup_label2) }
+ end
+
+ with_them do
+ let(:params) do
+ {
+ include_ancestor_groups: include_ancestor_groups,
+ include_descendant_groups: include_descendant_groups,
+ only_group_labels: only_group_labels,
+ search_term: search_term
+ }
+ end
+
+ subject { resolve_labels(subgroup, params) }
+
+ it { self.instance_exec(&test) }
+ end
+ end
+ end
+
+ def resolve_labels(parent, args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: parent, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 269ee9eabf9..8980f4aa19d 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -195,11 +195,11 @@ RSpec.describe Resolvers::IssuesResolver do
let_it_be(:priority_issue4) { create(:issue, project: project) }
it 'sorts issues ascending' do
- expect(resolve_issues(sort: :priority_asc).items).to eq([priority_issue3, priority_issue1, priority_issue2, priority_issue4])
+ expect(resolve_issues(sort: :priority_asc).to_a).to eq([priority_issue3, priority_issue1, priority_issue2, priority_issue4])
end
it 'sorts issues descending' do
- expect(resolve_issues(sort: :priority_desc).items).to eq([priority_issue1, priority_issue3, priority_issue2, priority_issue4])
+ expect(resolve_issues(sort: :priority_desc).to_a).to eq([priority_issue1, priority_issue3, priority_issue2, priority_issue4])
end
end
@@ -214,11 +214,11 @@ RSpec.describe Resolvers::IssuesResolver do
let_it_be(:label_issue4) { create(:issue, project: project) }
it 'sorts issues ascending' do
- expect(resolve_issues(sort: :label_priority_asc).items).to eq([label_issue3, label_issue1, label_issue2, label_issue4])
+ expect(resolve_issues(sort: :label_priority_asc).to_a).to eq([label_issue3, label_issue1, label_issue2, label_issue4])
end
it 'sorts issues descending' do
- expect(resolve_issues(sort: :label_priority_desc).items).to eq([label_issue2, label_issue3, label_issue1, label_issue4])
+ expect(resolve_issues(sort: :label_priority_desc).to_a).to eq([label_issue2, label_issue3, label_issue1, label_issue4])
end
end
@@ -231,11 +231,11 @@ RSpec.describe Resolvers::IssuesResolver do
let_it_be(:milestone_issue3) { create(:issue, project: project, milestone: late_milestone) }
it 'sorts issues ascending' do
- expect(resolve_issues(sort: :milestone_due_asc).items).to eq([milestone_issue2, milestone_issue3, milestone_issue1])
+ expect(resolve_issues(sort: :milestone_due_asc).to_a).to eq([milestone_issue2, milestone_issue3, milestone_issue1])
end
it 'sorts issues descending' do
- expect(resolve_issues(sort: :milestone_due_desc).items).to eq([milestone_issue3, milestone_issue2, milestone_issue1])
+ expect(resolve_issues(sort: :milestone_due_desc).to_a).to eq([milestone_issue3, milestone_issue2, milestone_issue1])
end
end
diff --git a/spec/graphql/resolvers/labels_resolver_spec.rb b/spec/graphql/resolvers/labels_resolver_spec.rb
new file mode 100644
index 00000000000..3d027a6c8d5
--- /dev/null
+++ b/spec/graphql/resolvers/labels_resolver_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::LabelsResolver do
+ include GraphqlHelpers
+
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group, reload: true) { create(:group, :private) }
+ let_it_be(:subgroup, reload: true) { create(:group, :private, parent: group) }
+ let_it_be(:sub_subgroup, reload: true) { create(:group, :private, parent: subgroup) }
+ let_it_be(:project, reload: true) { create(:project, :private, group: subgroup) }
+ let_it_be(:label1) { create(:label, project: project, name: 'project feature') }
+ let_it_be(:label2) { create(:label, project: project, name: 'new project feature') }
+ let_it_be(:group_label1) { create(:group_label, group: group, name: 'group feature') }
+ let_it_be(:group_label2) { create(:group_label, group: group, name: 'new group feature') }
+ let_it_be(:subgroup_label1) { create(:group_label, group: subgroup, name: 'subgroup feature') }
+ let_it_be(:subgroup_label2) { create(:group_label, group: subgroup, name: 'new subgroup feature') }
+ let_it_be(:sub_subgroup_label1) { create(:group_label, group: sub_subgroup, name: 'sub_subgroup feature') }
+ let_it_be(:sub_subgroup_label2) { create(:group_label, group: sub_subgroup, name: 'new sub_subgroup feature') }
+
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::LabelType.connection_type)
+ end
+
+ describe '#resolve' do
+ context 'with unauthorized user' do
+ it 'returns no labels' do
+ expect { resolve_labels(project) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'with authorized user' do
+ it 'returns no labels' do
+ group.add_guest(current_user)
+
+ expect { resolve_labels(project) }.not_to raise_error
+ end
+ end
+
+ context 'without parent' do
+ it 'returns no labels' do
+ expect(resolve_labels(nil)).to eq(Label.none)
+ end
+ end
+
+ context 'at project level' do
+ before_all do
+ group.add_developer(current_user)
+ end
+
+ # because :include_ancestor_groups, :include_descendant_groups, :only_group_labels default to false
+ # the `nil` value would be equivalent to passing in `false` so just check for `nil` option
+ where(:include_ancestor_groups, :include_descendant_groups, :only_group_labels, :search_term, :test) do
+ nil | nil | nil | nil | -> { expect(subject).to contain_exactly(label1, label2, subgroup_label1, subgroup_label2) }
+ nil | nil | true | nil | -> { expect(subject).to contain_exactly(label1, label2, subgroup_label1, subgroup_label2) }
+ nil | true | nil | nil | -> { expect(subject).to contain_exactly(label1, label2, subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2) }
+ nil | true | true | nil | -> { expect(subject).to contain_exactly(label1, label2, subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2) }
+ true | nil | nil | nil | -> { expect(subject).to contain_exactly(label1, label2, group_label1, group_label2, subgroup_label1, subgroup_label2) }
+ true | nil | true | nil | -> { expect(subject).to contain_exactly(label1, label2, group_label1, group_label2, subgroup_label1, subgroup_label2) }
+ true | true | nil | nil | -> { expect(subject).to contain_exactly(label1, label2, group_label1, group_label2, subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2) }
+ true | true | true | nil | -> { expect(subject).to contain_exactly(label1, label2, group_label1, group_label2, subgroup_label1, subgroup_label2, sub_subgroup_label1, sub_subgroup_label2) }
+
+ nil | nil | nil | 'new' | -> { expect(subject).to contain_exactly(label2, subgroup_label2) }
+ nil | nil | true | 'new' | -> { expect(subject).to contain_exactly(label2, subgroup_label2) }
+ nil | true | nil | 'new' | -> { expect(subject).to contain_exactly(label2, subgroup_label2, sub_subgroup_label2) }
+ nil | true | true | 'new' | -> { expect(subject).to contain_exactly(label2, subgroup_label2, sub_subgroup_label2) }
+ true | nil | nil | 'new' | -> { expect(subject).to contain_exactly(label2, group_label2, subgroup_label2) }
+ true | nil | true | 'new' | -> { expect(subject).to contain_exactly(label2, group_label2, subgroup_label2) }
+ true | true | nil | 'new' | -> { expect(subject).to contain_exactly(label2, group_label2, subgroup_label2, sub_subgroup_label2) }
+ true | true | true | 'new' | -> { expect(subject).to contain_exactly(label2, group_label2, subgroup_label2, sub_subgroup_label2) }
+ end
+
+ with_them do
+ let(:params) do
+ {
+ include_ancestor_groups: include_ancestor_groups,
+ include_descendant_groups: include_descendant_groups,
+ only_group_labels: only_group_labels,
+ search_term: search_term
+ }
+ end
+
+ subject { resolve_labels(project, params) }
+
+ it { self.instance_exec(&test) }
+ end
+ end
+ end
+
+ def resolve_labels(parent, args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: parent, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index 50b9243efa5..c5c368fc88f 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Resolvers::MergeRequestsResolver do
include GraphqlHelpers
+ include SortingHelper
let_it_be(:project) { create(:project, :repository) }
let_it_be(:milestone) { create(:milestone, project: project) }
@@ -30,6 +31,16 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
describe '#resolve' do
+ # One for the initial auth, then MRs, and the load of project and project_feature (for further auth):
+ # SELECT MAX("project_authorizations"."access_level") AS maximum_access_level,
+ # "project_authorizations"."user_id" AS project_authorizations_user_id
+ # FROM "project_authorizations"
+ # WHERE "project_authorizations"."project_id" = 2 AND "project_authorizations"."user_id" = 2
+ # GROUP BY "project_authorizations"."user_id"
+ # SELECT "merge_requests".* FROM "merge_requests" WHERE "merge_requests"."target_project_id" = 2
+ # AND "merge_requests"."iid" = 1 ORDER BY "merge_requests"."id" DESC
+ # SELECT "projects".* FROM "projects" WHERE "projects"."id" = 2
+ # SELECT "project_features".* FROM "project_features" WHERE "project_features"."project_id" = 2
let(:queries_per_project) { 3 }
context 'no arguments' do
@@ -72,15 +83,17 @@ RSpec.describe Resolvers::MergeRequestsResolver do
expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3)
end
- it 'can batch-resolve merge requests from different projects' do
+ it 'can batch-resolve merge requests from different projects', :request_store, :use_clean_rails_memory_store_caching do
# 2 queries for project_authorizations, and 2 for merge_requests
- result = batch_sync(max_queries: queries_per_project * 2) do
- resolve_mr(project, iids: [iid_1]) +
- resolve_mr(project, iids: [iid_2]) +
- resolve_mr(other_project, iids: [other_iid])
+ results = batch_sync(max_queries: queries_per_project * 2) do
+ a = resolve_mr(project, iids: [iid_1])
+ b = resolve_mr(project, iids: [iid_2])
+ c = resolve_mr(other_project, iids: [other_iid])
+
+ [a, b, c].flat_map(&:to_a)
end
- expect(result).to contain_exactly(merge_request_1, merge_request_2, other_merge_request)
+ expect(results).to contain_exactly(merge_request_1, merge_request_2, other_merge_request)
end
it 'resolves an unknown iid to be empty' do
@@ -134,9 +147,9 @@ RSpec.describe Resolvers::MergeRequestsResolver do
it 'takes more than one argument' do
mrs = [merge_request_3, merge_request_4]
branches = mrs.map(&:target_branch)
- result = resolve_mr(project, target_branches: branches )
+ result = resolve_mr(project, target_branches: branches)
- expect(result.compact).to match_array(mrs)
+ expect(result).to match_array(mrs)
end
end
@@ -173,7 +186,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
it 'returns merge requests merged between the given period' do
result = resolve_mr(project, merged_after: 20.days.ago, merged_before: 5.days.ago)
- expect(result).to eq([merge_request_1])
+ expect(result).to contain_exactly(merge_request_1)
end
it 'does not return anything' do
@@ -187,7 +200,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
it 'filters merge requests by milestone title' do
result = resolve_mr(project, milestone_title: milestone.title)
- expect(result).to eq([merge_request_with_milestone])
+ expect(result).to contain_exactly(merge_request_with_milestone)
end
it 'does not find anything' do
@@ -203,18 +216,29 @@ RSpec.describe Resolvers::MergeRequestsResolver do
result = resolve_mr(project, source_branches: [merge_request_4.source_branch], state: 'locked')
- expect(result.compact).to contain_exactly(merge_request_4)
+ expect(result).to contain_exactly(merge_request_4)
end
end
describe 'sorting' do
+ let(:mrs) do
+ [
+ merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4,
+ merge_request_3, merge_request_2, merge_request_1
+ ]
+ end
+
context 'when sorting by created' do
it 'sorts merge requests ascending' do
- expect(resolve_mr(project, sort: 'created_asc')).to eq [merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone]
+ expect(resolve_mr(project, sort: 'created_asc'))
+ .to match_array(mrs)
+ .and be_sorted(:created_at, :asc)
end
it 'sorts merge requests descending' do
- expect(resolve_mr(project, sort: 'created_desc')).to eq [merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_3, merge_request_2, merge_request_1]
+ expect(resolve_mr(project, sort: 'created_desc'))
+ .to match_array(mrs)
+ .and be_sorted(:created_at, :desc)
end
end
@@ -225,11 +249,19 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
it 'sorts merge requests ascending' do
- expect(resolve_mr(project, sort: :merged_at_asc)).to eq [merge_request_1, merge_request_3, merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_2]
+ expect(resolve_mr(project, sort: :merged_at_asc))
+ .to match_array(mrs)
+ .and be_sorted(->(mr) { [merged_at(mr), -mr.id] })
end
it 'sorts merge requests descending' do
- expect(resolve_mr(project, sort: :merged_at_desc)).to eq [merge_request_3, merge_request_1, merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_2]
+ expect(resolve_mr(project, sort: :merged_at_desc))
+ .to match_array(mrs)
+ .and be_sorted(->(mr) { [-merged_at(mr), -mr.id] })
+ end
+
+ def merged_at(mr)
+ nils_last(mr.metrics.merged_at)
end
context 'when label filter is given and the optimized_issuable_label_filter feature flag is off' do
diff --git a/spec/graphql/resolvers/package_details_resolver_spec.rb b/spec/graphql/resolvers/package_details_resolver_spec.rb
index 825b2aed40a..1bdc069b3bb 100644
--- a/spec/graphql/resolvers/package_details_resolver_spec.rb
+++ b/spec/graphql/resolvers/package_details_resolver_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Resolvers::PackageDetailsResolver do
include GraphqlHelpers
+ include ::Gitlab::Graphql::Laziness
let_it_be_with_reload(:project) { create(:project) }
let_it_be(:user) { project.owner }
@@ -11,10 +12,10 @@ RSpec.describe Resolvers::PackageDetailsResolver do
describe '#resolve' do
let(:args) do
- { id: package.to_global_id.to_s }
+ { id: global_id_of(package) }
end
- subject { resolve(described_class, ctx: { current_user: user }, args: args).sync }
+ subject { force(resolve(described_class, ctx: { current_user: user }, args: args)) }
it { is_expected.to eq(package) }
end
diff --git a/spec/graphql/resolvers/packages_resolver_spec.rb b/spec/graphql/resolvers/packages_resolver_spec.rb
index 9aec2c7e036..bc0588daf7f 100644
--- a/spec/graphql/resolvers/packages_resolver_spec.rb
+++ b/spec/graphql/resolvers/packages_resolver_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Resolvers::PackagesResolver do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:project) { create(:project, :public) }
let_it_be(:package) { create(:package, project: project) }
describe '#resolve' do
diff --git a/spec/graphql/resolvers/release_milestones_resolver_spec.rb b/spec/graphql/resolvers/release_milestones_resolver_spec.rb
index 5f66cba859d..f05069998d0 100644
--- a/spec/graphql/resolvers/release_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/release_milestones_resolver_spec.rb
@@ -6,18 +6,19 @@ RSpec.describe Resolvers::ReleaseMilestonesResolver do
include GraphqlHelpers
let_it_be(:release) { create(:release, :with_milestones, milestones_count: 2) }
+ let_it_be(:current_user) { create(:user, developer_projects: [release.project]) }
let(:resolved) do
- resolve(described_class, obj: release)
+ resolve(described_class, obj: release, ctx: { current_user: current_user })
end
describe '#resolve' do
- it "returns an OffsetActiveRecordRelationConnection" do
- expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
+ it "uses offset-pagination" do
+ expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetPaginatedRelation)
end
it "includes the release's milestones in the returned OffsetActiveRecordRelationConnection" do
- expect(resolved.items).to eq(release.milestones.order_by_dates_and_title)
+ expect(resolved.to_a).to eq(release.milestones.order_by_dates_and_title)
end
end
end
diff --git a/spec/graphql/resolvers/release_resolver_spec.rb b/spec/graphql/resolvers/release_resolver_spec.rb
index 04765fc68e9..782c9604f15 100644
--- a/spec/graphql/resolvers/release_resolver_spec.rb
+++ b/spec/graphql/resolvers/release_resolver_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Resolvers::ReleaseResolver do
let(:args) { {} }
it 'raises an error' do
- expect { resolve_release }.to raise_error(ArgumentError, "missing keyword: :tag_name")
+ expect { resolve_release }.to raise_error(ArgumentError)
end
end
end
diff --git a/spec/graphql/resolvers/terraform/states_resolver_spec.rb b/spec/graphql/resolvers/terraform/states_resolver_spec.rb
index 64b515528cd..91d48cd782b 100644
--- a/spec/graphql/resolvers/terraform/states_resolver_spec.rb
+++ b/spec/graphql/resolvers/terraform/states_resolver_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Resolvers::Terraform::StatesResolver do
include GraphqlHelpers
- it { expect(described_class.type).to eq(Types::Terraform::StateType) }
+ it { expect(described_class).to have_nullable_graphql_type(Types::Terraform::StateType.connection_type) }
it { expect(described_class.null).to be_truthy }
describe '#resolve' do
@@ -31,3 +31,21 @@ RSpec.describe Resolvers::Terraform::StatesResolver do
end
end
end
+
+RSpec.describe Resolvers::Terraform::StatesResolver.single do
+ it { expect(described_class).to be < Resolvers::Terraform::StatesResolver }
+
+ describe 'arguments' do
+ subject { described_class.arguments[argument] }
+
+ describe 'name' do
+ let(:argument) { 'name' }
+
+ it do
+ expect(subject).to be_present
+ expect(subject.type.to_s).to eq('String!')
+ expect(subject.description).to be_present
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/ci/pipeline_type_spec.rb b/spec/graphql/types/ci/pipeline_type_spec.rb
index d435e337ad7..2a1e030480d 100644
--- a/spec/graphql/types/ci/pipeline_type_spec.rb
+++ b/spec/graphql/types/ci/pipeline_type_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Types::Ci::PipelineType do
id iid sha before_sha status detailed_status config_source duration
coverage created_at updated_at started_at finished_at committed_at
stages user retryable cancelable jobs source_job downstream
- upstream path project active user_permissions
+ upstream path project active user_permissions warnings
]
if Gitlab.ee?
diff --git a/spec/graphql/types/ci_configuration/sast/analyzers_entity_input_type_spec.rb b/spec/graphql/types/ci_configuration/sast/analyzers_entity_input_type_spec.rb
new file mode 100644
index 00000000000..ac18f8d53a1
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/analyzers_entity_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::CiConfiguration::Sast::AnalyzersEntityInputType do
+ it { expect(described_class.graphql_name).to eq('SastCiConfigurationAnalyzersEntityInput') }
+
+ it { expect(described_class.arguments.keys).to match_array(%w[enabled name variables]) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb b/spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb
new file mode 100644
index 00000000000..27f6703b429
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['SastCiConfigurationAnalyzersEntity'] do
+ let(:fields) { %i[name label enabled description variables] }
+
+ it { expect(described_class.graphql_name).to eq('SastCiConfigurationAnalyzersEntity') }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/entity_input_type_spec.rb b/spec/graphql/types/ci_configuration/sast/entity_input_type_spec.rb
new file mode 100644
index 00000000000..cefcf64164a
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/entity_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::CiConfiguration::Sast::EntityInputType do
+ it { expect(described_class.graphql_name).to eq('SastCiConfigurationEntityInput') }
+
+ it { expect(described_class.arguments.keys).to match_array(%w[field defaultValue value]) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/entity_type_spec.rb b/spec/graphql/types/ci_configuration/sast/entity_type_spec.rb
new file mode 100644
index 00000000000..762798670a5
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/entity_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['SastCiConfigurationEntity'] do
+ let(:fields) { %i[field label description type options default_value value size] }
+
+ it { expect(described_class.graphql_name).to eq('SastCiConfigurationEntity') }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/input_type_spec.rb b/spec/graphql/types/ci_configuration/sast/input_type_spec.rb
new file mode 100644
index 00000000000..9f9d1dea98f
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::CiConfiguration::Sast::InputType do
+ it { expect(described_class.graphql_name).to eq('SastCiConfigurationInput') }
+
+ it { expect(described_class.arguments.keys).to match_array(%w[global pipeline analyzers]) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/options_entity_spec.rb b/spec/graphql/types/ci_configuration/sast/options_entity_spec.rb
new file mode 100644
index 00000000000..c60c8b9c84a
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/options_entity_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['SastCiConfigurationOptionsEntity'] do
+ let(:fields) { %i[label value] }
+
+ it { expect(described_class.graphql_name).to eq('SastCiConfigurationOptionsEntity') }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/type_spec.rb b/spec/graphql/types/ci_configuration/sast/type_spec.rb
new file mode 100644
index 00000000000..e7a8cd436e4
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['SastCiConfiguration'] do
+ let(:fields) { %i[global pipeline analyzers] }
+
+ it { expect(described_class.graphql_name).to eq('SastCiConfiguration') }
+
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/ci_configuration/sast/ui_component_size_enum_spec.rb b/spec/graphql/types/ci_configuration/sast/ui_component_size_enum_spec.rb
new file mode 100644
index 00000000000..23184df809f
--- /dev/null
+++ b/spec/graphql/types/ci_configuration/sast/ui_component_size_enum_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::CiConfiguration::Sast::UiComponentSizeEnum do
+ specify { expect(described_class.graphql_name).to eq('SastUiComponentSize') }
+
+ it 'exposes all sizes of ui components' do
+ expect(described_class.values.keys).to include(*%w[SMALL MEDIUM LARGE])
+ end
+end
diff --git a/spec/graphql/types/container_repository_sort_enum_spec.rb b/spec/graphql/types/container_repository_sort_enum_spec.rb
new file mode 100644
index 00000000000..eb936c6d3a1
--- /dev/null
+++ b/spec/graphql/types/container_repository_sort_enum_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositorySort'] do
+ specify { expect(described_class.graphql_name).to eq('ContainerRepositorySort') }
+
+ it_behaves_like 'common sort values'
+
+ it 'exposes all the existing issue sort values' do
+ expect(described_class.values.keys).to include(
+ *%w[NAME_ASC NAME_DESC]
+ )
+ end
+end
diff --git a/spec/graphql/types/event_type_spec.rb b/spec/graphql/types/event_type_spec.rb
new file mode 100644
index 00000000000..10c3b5e18ca
--- /dev/null
+++ b/spec/graphql/types/event_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::EventType do
+ specify { expect(described_class.graphql_name).to eq('Event') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_event) }
+
+ specify { expect(described_class).to have_graphql_fields(:id, :author, :action, :created_at, :updated_at) }
+end
diff --git a/spec/graphql/types/eventable_type_spec.rb b/spec/graphql/types/eventable_type_spec.rb
new file mode 100644
index 00000000000..c1c7bf6d65a
--- /dev/null
+++ b/spec/graphql/types/eventable_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::EventableType do
+ it 'exposes events field' do
+ expect(described_class).to have_graphql_fields(:events)
+ end
+end
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index de19e8b602a..bba702ba3e9 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -38,5 +38,7 @@ RSpec.describe GitlabSchema.types['Group'] do
it { is_expected.to have_graphql_resolver(Resolvers::GroupMembersResolver) }
end
- it_behaves_like 'a GraphQL type with labels'
+ it_behaves_like 'a GraphQL type with labels' do
+ let(:labels_resolver_arguments) { [:search_term, :includeAncestorGroups, :includeDescendantGroups, :onlyGroupLabels] }
+ end
end
diff --git a/spec/graphql/types/merge_request_state_event_enum_spec.rb b/spec/graphql/types/merge_request_state_event_enum_spec.rb
new file mode 100644
index 00000000000..94214b29755
--- /dev/null
+++ b/spec/graphql/types/merge_request_state_event_enum_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['MergeRequestNewState'] do
+ it 'has the appropriate values' do
+ expect(described_class.values).to contain_exactly(
+ ['OPEN', have_attributes(value: 'reopen')],
+ ['CLOSED', have_attributes(value: 'close')]
+ )
+ end
+end
diff --git a/spec/graphql/types/packages/composer/details_type_spec.rb b/spec/graphql/types/packages/composer/details_type_spec.rb
deleted file mode 100644
index 2e4cb965ded..00000000000
--- a/spec/graphql/types/packages/composer/details_type_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GitlabSchema.types['PackageComposerDetails'] do
- it { expect(described_class.graphql_name).to eq('PackageComposerDetails') }
-
- it 'includes all the package fields' do
- expected_fields = %w[
- id name version created_at updated_at package_type tags project pipelines versions
- ]
-
- expect(described_class).to include_graphql_fields(*expected_fields)
- end
-
- it 'includes composer specific files' do
- expected_fields = %w[
- composer_metadatum
- ]
-
- expect(described_class).to include_graphql_fields(*expected_fields)
- end
-end
diff --git a/spec/graphql/types/packages/composer/metadatum_type_spec.rb b/spec/graphql/types/packages/composer/metadatum_type_spec.rb
index 0f47d8f1812..a950c10a41d 100644
--- a/spec/graphql/types/packages/composer/metadatum_type_spec.rb
+++ b/spec/graphql/types/packages/composer/metadatum_type_spec.rb
@@ -2,9 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['PackageComposerMetadatumType'] do
- it { expect(described_class.graphql_name).to eq('PackageComposerMetadatumType') }
-
+RSpec.describe GitlabSchema.types['ComposerMetadata'] do
it 'includes composer metadatum fields' do
expected_fields = %w[
target_sha composer_json
diff --git a/spec/graphql/types/packages/package_type_enum_spec.rb b/spec/graphql/types/packages/package_type_enum_spec.rb
index 407d5786f65..ccd91485e4b 100644
--- a/spec/graphql/types/packages/package_type_enum_spec.rb
+++ b/spec/graphql/types/packages/package_type_enum_spec.rb
@@ -4,6 +4,6 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['PackageTypeEnum'] do
it 'exposes all package types' do
- expect(described_class.values.keys).to contain_exactly(*%w[MAVEN NPM CONAN NUGET PYPI COMPOSER GENERIC GOLANG DEBIAN])
+ expect(described_class.values.keys).to contain_exactly(*%w[MAVEN NPM CONAN NUGET PYPI COMPOSER GENERIC GOLANG DEBIAN RUBYGEMS])
end
end
diff --git a/spec/graphql/types/packages/package_type_spec.rb b/spec/graphql/types/packages/package_type_spec.rb
index 7003a4d4d07..43289a019b3 100644
--- a/spec/graphql/types/packages/package_type_spec.rb
+++ b/spec/graphql/types/packages/package_type_spec.rb
@@ -3,11 +3,12 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['Package'] do
- it { expect(described_class.graphql_name).to eq('Package') }
-
it 'includes all the package fields' do
expected_fields = %w[
- id name version created_at updated_at package_type tags project pipelines versions
+ id name version package_type
+ created_at updated_at
+ project
+ tags pipelines versions
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/packages/package_without_versions_type_spec.rb b/spec/graphql/types/packages/package_without_versions_type_spec.rb
new file mode 100644
index 00000000000..faa79e588d5
--- /dev/null
+++ b/spec/graphql/types/packages/package_without_versions_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackageWithoutVersions'] do
+ it 'includes all the package fields' do
+ expected_fields = %w[
+ id name version created_at updated_at package_type tags project pipelines
+ ]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 9d0d7a3918a..9579ef8b99b 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -31,12 +31,171 @@ RSpec.describe GitlabSchema.types['Project'] do
container_expiration_policy service_desk_enabled service_desk_address
issue_status_counts terraform_states alert_management_integrations
container_repositories container_repositories_count
- pipeline_analytics squash_read_only
+ pipeline_analytics squash_read_only sast_ci_configuration
]
expect(described_class).to include_graphql_fields(*expected_fields)
end
+ describe 'sast_ci_configuration' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ stub_licensed_features(security_dashboard: true)
+ project.add_developer(user)
+ allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_content)
+ end
+
+ include_context 'read ci configuration for sast enabled project'
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ sastCiConfiguration {
+ global {
+ nodes {
+ type
+ options {
+ nodes {
+ label
+ value
+ }
+ }
+ field
+ label
+ defaultValue
+ value
+ size
+ }
+ }
+ pipeline {
+ nodes {
+ type
+ options {
+ nodes {
+ label
+ value
+ }
+ }
+ field
+ label
+ defaultValue
+ value
+ size
+ }
+ }
+ analyzers {
+ nodes {
+ name
+ label
+ enabled
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
+
+ it "returns the project's sast configuration for global variables" do
+ secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration', 'global', 'nodes').first
+ expect(secure_analyzers_prefix['type']).to eq('string')
+ expect(secure_analyzers_prefix['field']).to eq('SECURE_ANALYZERS_PREFIX')
+ expect(secure_analyzers_prefix['label']).to eq('Image prefix')
+ expect(secure_analyzers_prefix['defaultValue']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(secure_analyzers_prefix['value']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(secure_analyzers_prefix['size']).to eq('LARGE')
+ expect(secure_analyzers_prefix['options']).to be_nil
+ end
+
+ it "returns the project's sast configuration for pipeline variables" do
+ pipeline_stage = subject.dig('data', 'project', 'sastCiConfiguration', 'pipeline', 'nodes').first
+ expect(pipeline_stage['type']).to eq('string')
+ expect(pipeline_stage['field']).to eq('stage')
+ expect(pipeline_stage['label']).to eq('Stage')
+ expect(pipeline_stage['defaultValue']).to eq('test')
+ expect(pipeline_stage['value']).to eq('test')
+ expect(pipeline_stage['size']).to eq('MEDIUM')
+ end
+
+ it "returns the project's sast configuration for analyzer variables" do
+ analyzer = subject.dig('data', 'project', 'sastCiConfiguration', 'analyzers', 'nodes').first
+ expect(analyzer['name']).to eq('brakeman')
+ expect(analyzer['label']).to eq('Brakeman')
+ expect(analyzer['enabled']).to eq(true)
+ end
+
+ context "with guest user" do
+ before do
+ project.add_guest(user)
+ end
+
+ context 'when project is private' do
+ let(:project) { create(:project, :private, :repository) }
+
+ it "returns no configuration" do
+ secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration')
+ expect(secure_analyzers_prefix).to be_nil
+ end
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when repository is accessible by everyone' do
+ it "returns the project's sast configuration for global variables" do
+ secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration', 'global', 'nodes').first
+
+ expect(secure_analyzers_prefix['type']).to eq('string')
+ expect(secure_analyzers_prefix['field']).to eq('SECURE_ANALYZERS_PREFIX')
+ end
+ end
+ end
+ end
+
+ context "with non-member user" do
+ before do
+ project.team.truncate
+ end
+
+ context 'when project is private' do
+ let(:project) { create(:project, :private, :repository) }
+
+ it "returns no configuration" do
+ secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration')
+ expect(secure_analyzers_prefix).to be_nil
+ end
+ end
+
+ context 'when project is public' do
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when repository is accessible by everyone' do
+ it "returns the project's sast configuration for global variables" do
+ secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration', 'global', 'nodes').first
+ expect(secure_analyzers_prefix['type']).to eq('string')
+ expect(secure_analyzers_prefix['field']).to eq('SECURE_ANALYZERS_PREFIX')
+ end
+ end
+
+ context 'when repository is accessible only by team members' do
+ it "returns no configuration" do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::PRIVATE)
+
+ secure_analyzers_prefix = subject.dig('data', 'project', 'sastCiConfiguration')
+ expect(secure_analyzers_prefix).to be_nil
+ end
+ end
+ end
+ end
+ end
+
describe 'issue field' do
subject { described_class.fields['issue'] }
@@ -159,6 +318,13 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::ContainerExpirationPolicyType) }
end
+ describe 'terraform state field' do
+ subject { described_class.fields['terraformState'] }
+
+ it { is_expected.to have_graphql_type(Types::Terraform::StateType) }
+ it { is_expected.to have_graphql_resolver(Resolvers::Terraform::StatesResolver.single) }
+ end
+
describe 'terraform states field' do
subject { described_class.fields['terraformStates'] }
@@ -166,7 +332,9 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_resolver(Resolvers::Terraform::StatesResolver) }
end
- it_behaves_like 'a GraphQL type with labels'
+ it_behaves_like 'a GraphQL type with labels' do
+ let(:labels_resolver_arguments) { [:search_term, :includeAncestorGroups] }
+ end
describe 'jira_imports' do
subject { resolve_field(:jira_imports, project) }
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index 3e716865e56..fea0a3bd37e 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -95,9 +95,9 @@ RSpec.describe GitlabSchema.types['Query'] do
it { is_expected.to have_graphql_type(Types::ContainerRepositoryDetailsType) }
end
- describe 'package_composer_details field' do
- subject { described_class.fields['packageComposerDetails'] }
+ describe 'package field' do
+ subject { described_class.fields['package'] }
- it { is_expected.to have_graphql_type(Types::Packages::Composer::DetailsType) }
+ it { is_expected.to have_graphql_type(Types::Packages::PackageType) }
end
end
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index 0eff33bb25b..5b3662383d8 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe GitlabSchema.types['User'] do
it 'has the expected fields' do
expected_fields = %w[
id
+ bot
user_permissions
snippets
name
diff --git a/spec/helpers/analytics/unique_visits_helper_spec.rb b/spec/helpers/analytics/unique_visits_helper_spec.rb
index ff363e81ac7..b4b370c169d 100644
--- a/spec/helpers/analytics/unique_visits_helper_spec.rb
+++ b/spec/helpers/analytics/unique_visits_helper_spec.rb
@@ -9,19 +9,6 @@ RSpec.describe Analytics::UniqueVisitsHelper do
let(:target_id) { 'p_analytics_valuestream' }
let(:current_user) { create(:user) }
- before do
- stub_feature_flags(track_unique_visits: true)
- end
-
- it 'does not track visits if feature flag disabled' do
- stub_feature_flags(track_unique_visits: false)
- sign_in(current_user)
-
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).not_to receive(:track_visit)
-
- helper.track_visit(target_id)
- end
-
it 'does not track visit if user is not logged in' do
expect_any_instance_of(Gitlab::Analytics::UniqueVisits).not_to receive(:track_visit)
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index 479e2d7ef9d..2cd01451e0d 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -194,4 +194,33 @@ RSpec.describe ApplicationSettingsHelper do
it { is_expected.to be false }
end
end
+
+ describe '.kroki_available_formats' do
+ let(:application_setting) { build(:application_setting) }
+
+ before do
+ helper.instance_variable_set(:@application_setting, application_setting)
+ stub_application_setting(kroki_formats: { 'blockdiag' => true, 'bpmn' => false, 'excalidraw' => false })
+ end
+
+ it 'returns available formats correctly' do
+ expect(helper.kroki_available_formats).to eq([
+ {
+ name: 'kroki_formats_blockdiag',
+ label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag and RackDiag)',
+ value: true
+ },
+ {
+ name: 'kroki_formats_bpmn',
+ label: 'BPMN',
+ value: false
+ },
+ {
+ name: 'kroki_formats_excalidraw',
+ label: 'Excalidraw',
+ value: false
+ }
+ ])
+ end
+ end
end
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index 00c4a1880de..b5d70af1336 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -73,12 +73,12 @@ RSpec.describe AuthHelper do
describe 'enabled_button_based_providers' do
before do
- allow(helper).to receive(:auth_providers) { [:twitter, :github, :google_oauth2] }
+ allow(helper).to receive(:auth_providers) { [:twitter, :github, :google_oauth2, :openid_connect] }
end
context 'all providers are enabled to sign in' do
it 'returns all the enabled providers from settings' do
- expect(helper.enabled_button_based_providers).to include('twitter', 'github', 'google_oauth2')
+ expect(helper.enabled_button_based_providers).to include('twitter', 'github', 'google_oauth2', 'openid_connect')
end
it 'puts google and github in the beginning' do
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 8a570bf9a90..2f5f4c4596b 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -7,19 +7,38 @@ RSpec.describe CommitsHelper do
context 'when current_user exists' do
before do
allow(helper).to receive(:current_user).and_return(double('User'))
- allow(helper).to receive(:can_collaborate_with_project?).and_return(true)
end
it 'renders a div for Vue' do
- result = helper.revert_commit_link('_commit_', '_path_', pajamas: true)
+ result = helper.revert_commit_link
expect(result).to include('js-revert-commit-trigger')
end
+ end
+
+ context 'when current_user does not exist' do
+ before do
+ allow(helper).to receive(:current_user).and_return(nil)
+ end
+
+ it 'does not render anything' do
+ result = helper.revert_commit_link
+
+ expect(result).to be_nil
+ end
+ end
+ end
- it 'does not render a div for Vue' do
- result = helper.revert_commit_link('_commit_', '_path_')
+ describe '#cherry_pick_commit_link' do
+ context 'when current_user exists' do
+ before do
+ allow(helper).to receive(:current_user).and_return(double('User'))
+ end
- expect(result).not_to include('js-revert-commit-trigger')
+ it 'renders a div for Vue' do
+ result = helper.cherry_pick_commit_link
+
+ expect(result).to include('js-cherry-pick-commit-trigger')
end
end
@@ -29,7 +48,7 @@ RSpec.describe CommitsHelper do
end
it 'does not render anything' do
- result = helper.revert_commit_link(double('Commit'), '_path_')
+ result = helper.cherry_pick_commit_link
expect(result).to be_nil
end
@@ -157,4 +176,77 @@ RSpec.describe CommitsHelper do
expect(helper.commit_path(project, commit)).to eq(project_commit_path(project, commit))
end
end
+
+ describe "#conditionally_paginate_diff_files" do
+ let(:diffs_collection) { instance_double(Gitlab::Diff::FileCollection::Commit, diff_files: diff_files) }
+ let(:diff_files) { Gitlab::Git::DiffCollection.new(files) }
+ let(:page) { nil }
+
+ let(:files) do
+ Array.new(85).map do
+ { too_large: false, diff: "" }
+ end
+ end
+
+ let(:params) do
+ {
+ page: page
+ }
+ end
+
+ subject { helper.conditionally_paginate_diff_files(diffs_collection, paginate: paginate) }
+
+ before do
+ allow(helper).to receive(:params).and_return(params)
+ end
+
+ context "pagination is enabled" do
+ let(:paginate) { true }
+
+ it "has been paginated" do
+ expect(subject).to be_an(Array)
+ end
+
+ it "can change the number of items per page" do
+ commits = helper.conditionally_paginate_diff_files(diffs_collection, paginate: paginate, per: 10)
+
+ expect(commits).to be_an(Array)
+ expect(commits.size).to eq(10)
+ end
+
+ context "page 1" do
+ let(:page) { 1 }
+
+ it "has 20 diffs" do
+ expect(subject.size).to eq(75)
+ end
+ end
+
+ context "page 2" do
+ let(:page) { 2 }
+
+ it "has the remaining 10 diffs" do
+ expect(subject.size).to eq(10)
+ end
+ end
+ end
+
+ context "pagination is disabled" do
+ let(:paginate) { false }
+
+ it "returns a standard DiffCollection" do
+ expect(subject).to be_a(Gitlab::Git::DiffCollection)
+ end
+ end
+
+ context "feature flag is disabled" do
+ let(:paginate) { true }
+
+ it "returns a standard DiffCollection" do
+ stub_feature_flags(paginate_commit_view: false)
+
+ expect(subject).to be_a(Gitlab::Git::DiffCollection)
+ end
+ end
+ end
end
diff --git a/spec/helpers/container_registry_helper_spec.rb b/spec/helpers/container_registry_helper_spec.rb
index 6e6e8137b3e..49e56113dd8 100644
--- a/spec/helpers/container_registry_helper_spec.rb
+++ b/spec/helpers/container_registry_helper_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe ContainerRegistryHelper do
using RSpec::Parameterized::TableSyntax
- describe '#limit_delete_tags_service?' do
- subject { helper.limit_delete_tags_service? }
+ describe '#container_registry_expiration_policies_throttling?' do
+ subject { helper.container_registry_expiration_policies_throttling? }
where(:feature_flag_enabled, :client_support, :expected_result) do
true | true | true
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index 3580959fde0..20fa8d62884 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -169,9 +169,9 @@ RSpec.describe DiffHelper do
it "returns strings with marked inline diffs" do
marked_old_line, marked_new_line = mark_inline_diffs(old_line, new_line)
- expect(marked_old_line).to eq(%q{abc <span class="idiff left right deletion">&#39;def&#39;</span>})
+ expect(marked_old_line).to eq(%q{abc <span class="idiff left deletion">&#39;</span>def<span class="idiff right deletion">&#39;</span>})
expect(marked_old_line).to be_html_safe
- expect(marked_new_line).to eq(%q{abc <span class="idiff left right addition">&quot;def&quot;</span>})
+ expect(marked_new_line).to eq(%q{abc <span class="idiff left addition">&quot;</span>def<span class="idiff right addition">&quot;</span>})
expect(marked_new_line).to be_html_safe
end
@@ -358,4 +358,48 @@ RSpec.describe DiffHelper do
expect(diff_file_path_text(diff_file, max: 10)).to eq("...open.rb")
end
end
+
+ describe "#collapsed_diff_url" do
+ let(:params) do
+ {
+ controller: "projects/commit",
+ action: "show",
+ namespace_id: "foo",
+ project_id: "bar",
+ id: commit.sha
+ }
+ end
+
+ subject { helper.collapsed_diff_url(diff_file) }
+
+ it "returns a valid URL" do
+ allow(helper).to receive(:safe_params).and_return(params)
+
+ expect(subject).to match(/foo\/bar\/-\/commit\/#{commit.sha}\/diff_for_path/)
+ end
+ end
+
+ describe "#render_fork_suggestion" do
+ subject { helper.render_fork_suggestion }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ end
+
+ context "user signed in" do
+ let(:current_user) { build(:user) }
+
+ it "renders the partial" do
+ expect(helper).to receive(:render).with(partial: "projects/fork_suggestion").exactly(:once)
+
+ 5.times { subject }
+ end
+ end
+
+ context "guest" do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
end
diff --git a/spec/helpers/enable_search_settings_helper_spec.rb b/spec/helpers/enable_search_settings_helper_spec.rb
new file mode 100644
index 00000000000..c55c549ea51
--- /dev/null
+++ b/spec/helpers/enable_search_settings_helper_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe EnableSearchSettingsHelper do
+ describe '#enable_search_settings' do
+ def before_content
+ helper.content_for(:before_content)
+ end
+
+ it 'sets content for before_content' do
+ expect(before_content).to be_nil
+
+ locals = { container_class: 'test-container-class' }
+
+ helper.enable_search_settings(locals: locals)
+
+ expect(before_content).to eql(helper.render("shared/search_settings", locals))
+ end
+ end
+end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index c629643e248..264bad92d56 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -200,7 +200,13 @@ RSpec.describe EventsHelper do
it 'returns a project snippet note url' do
event.target = create(:note_on_project_snippet, note: 'keep going')
- expect(subject).to eq("#{project_base_url}/-/snippets/#{event.note_target.id}#note_#{event.target.id}")
+ expect(subject).to eq("#{project_snippet_url(event.note_target.project, event.note_target)}#note_#{event.target.id}")
+ end
+
+ it 'returns a personal snippet note url' do
+ event.target = create(:note_on_personal_snippet, note: 'keep going')
+
+ expect(subject).to eq("#{snippet_url(event.note_target)}#note_#{event.target.id}")
end
it 'returns a project issue url' do
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index d75124b6da7..99efc7963e6 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -23,13 +23,13 @@ RSpec.describe Groups::GroupMembersHelper do
end
end
- describe '#linked_groups_data_json' do
+ describe '#group_group_links_data_json' do
include_context 'group_group_link'
it 'matches json schema' do
- json = helper.linked_groups_data_json(shared_group.shared_with_group_links)
+ json = helper.group_group_links_data_json(shared_group.shared_with_group_links)
- expect(json).to match_schema('group_group_links')
+ expect(json).to match_schema('group_link/group_group_links')
end
end
@@ -81,13 +81,13 @@ RSpec.describe Groups::GroupMembersHelper do
expect(helper.group_members_list_data_attributes(group, present_members([group_member]))).to include({
members: helper.members_data_json(group, present_members([group_member])),
member_path: '/groups/foo-bar/-/group_members/:id',
- group_id: group.id,
+ source_id: group.id,
can_manage_members: 'true'
})
end
end
- describe '#linked_groups_list_data_attributes' do
+ describe '#group_group_links_list_data_attributes' do
include_context 'group_group_link'
before do
@@ -95,10 +95,10 @@ RSpec.describe Groups::GroupMembersHelper do
end
it 'returns expected hash' do
- expect(helper.linked_groups_list_data_attributes(shared_group)).to include({
- members: helper.linked_groups_data_json(shared_group.shared_with_group_links),
+ expect(helper.group_group_links_list_data_attributes(shared_group)).to include({
+ members: helper.group_group_links_data_json(shared_group.shared_with_group_links),
member_path: '/groups/foo-bar/-/group_links/:id',
- group_id: shared_group.id
+ source_id: shared_group.id
})
end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 8eb1b7b3b3d..61aaa618c45 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -444,4 +444,82 @@ RSpec.describe GroupsHelper do
end
end
end
+
+ describe '#group_open_issues_count' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:count_service) { Groups::OpenIssuesCountService }
+
+ before do
+ allow(helper).to receive(:current_user) { current_user }
+ end
+
+ context 'when cached_sidebar_open_issues_count feature flag is enabled' do
+ before do
+ stub_feature_flags(cached_sidebar_open_issues_count: true)
+ end
+
+ it 'returns count value from cache' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(2500)
+ end
+
+ expect(helper.group_open_issues_count(group)).to eq('2.5k')
+ end
+ end
+
+ context 'when cached_sidebar_open_issues_count feature flag is disabled' do
+ before do
+ stub_feature_flags(cached_sidebar_open_issues_count: false)
+ end
+
+ it 'returns not cached issues count' do
+ allow(helper).to receive(:group_issues_count).and_return(2500)
+
+ expect(helper.group_open_issues_count(group)).to eq('2,500')
+ end
+ end
+ end
+
+ describe '#cached_open_group_issues_count' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:group) { create(:group, name: 'group') }
+ let_it_be(:count_service) { Groups::OpenIssuesCountService }
+
+ before do
+ allow(helper).to receive(:current_user) { current_user }
+ end
+
+ it 'returns all digits for count value under 1000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(999)
+ end
+
+ expect(helper.cached_open_group_issues_count(group)).to eq('999')
+ end
+
+ it 'returns truncated digits for count value over 1000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(2300)
+ end
+
+ expect(helper.cached_open_group_issues_count(group)).to eq('2.3k')
+ end
+
+ it 'returns truncated digits for count value over 10000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(12560)
+ end
+
+ expect(helper.cached_open_group_issues_count(group)).to eq('12.6k')
+ end
+
+ it 'returns truncated digits for count value over 100000' do
+ allow_next_instance_of(count_service) do |service|
+ allow(service).to receive(:count).and_return(112560)
+ end
+
+ expect(helper.cached_open_group_issues_count(group)).to eq('112.6k')
+ end
+ end
end
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index 914d0931476..576021b37b3 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -7,11 +7,49 @@ RSpec.describe InviteMembersHelper do
let_it_be(:developer) { create(:user, developer_projects: [project]) }
let(:owner) { project.owner }
+ before do
+ helper.extend(Gitlab::Experimentation::ControllerConcern)
+ end
+
context 'with project' do
before do
assign(:project, project)
end
+ describe "#can_invite_members_for_project?" do
+ context 'when the user can_import_members' do
+ before do
+ allow(helper).to receive(:can_import_members?).and_return(true)
+ end
+
+ it 'returns true' do
+ expect(helper.can_invite_members_for_project?(project)).to eq true
+ expect(helper).to have_received(:can_import_members?)
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it 'returns false' do
+ expect(helper.can_invite_members_for_project?(project)).to eq false
+ expect(helper).not_to have_received(:can_import_members?)
+ end
+ end
+ end
+
+ context 'when the user can not invite members' do
+ before do
+ expect(helper).to receive(:can_import_members?).and_return(false)
+ end
+
+ it 'returns false' do
+ expect(helper.can_invite_members_for_project?(project)).to eq false
+ end
+ end
+ end
+
describe "#directly_invite_members?" do
context 'when the user is an owner' do
before do
@@ -80,6 +118,51 @@ RSpec.describe InviteMembersHelper do
context 'with group' do
let_it_be(:group) { create(:group) }
+ describe "#can_invite_members_for_group?" do
+ include Devise::Test::ControllerHelpers
+
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ allow(helper).to receive(:current_user) { user }
+ end
+
+ context 'when the user can_import_members' do
+ before do
+ allow(helper).to receive(:can?).with(user, :admin_group_member, group).and_return(true)
+ end
+
+ it 'returns true' do
+ expect(helper.can_invite_members_for_group?(group)).to eq true
+ expect(helper).to have_received(:can?).with(user, :admin_group_member, group)
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(invite_members_group_modal: false)
+ end
+
+ it 'returns false' do
+ stub_feature_flags(invite_members_group_modal: false)
+
+ expect(helper.can_invite_members_for_group?(group)).to eq false
+ expect(helper).not_to have_received(:can?)
+ end
+ end
+ end
+
+ context 'when the user can not invite members' do
+ before do
+ expect(helper).to receive(:can?).with(user, :admin_group_member, group).and_return(false)
+ end
+
+ it 'returns false' do
+ expect(helper.can_invite_members_for_group?(group)).to eq false
+ end
+ end
+ end
+
describe "#invite_group_members?" do
context 'when the user is an owner' do
before do
@@ -123,7 +206,6 @@ RSpec.describe InviteMembersHelper do
before do
allow(helper).to receive(:experiment_tracking_category_and_group) { '_track_property_' }
- allow(helper).to receive(:tracking_label).with(owner)
allow(helper).to receive(:current_user) { owner }
end
@@ -132,8 +214,7 @@ RSpec.describe InviteMembersHelper do
helper.dropdown_invite_members_link(form_model)
- expect(helper).to have_received(:experiment_tracking_category_and_group)
- .with(:invite_members_new_dropdown, subject: owner)
+ expect(helper).to have_received(:experiment_tracking_category_and_group).with(:invite_members_new_dropdown)
end
context 'with experiment enabled' do
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
new file mode 100644
index 00000000000..42643b755f8
--- /dev/null
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
+ include_context 'project issuable templates context'
+
+ describe '#issuable_templates' do
+ let_it_be(:inherited_from) { nil }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:parent_group, reload: true) { create(:group) }
+ let_it_be(:project, reload: true) { create(:project, :custom_repo, files: issuable_template_files) }
+ let_it_be(:group_member) { create(:group_member, :developer, group: parent_group, user: user) }
+ let_it_be(:project_member) { create(:project_member, :developer, user: user, project: project) }
+
+ it 'returns empty hash when template type does not exist' do
+ expect(helper.issuable_templates(build(:project), 'non-existent-template-type')).to eq([])
+ end
+
+ context 'with cached issuable templates' do
+ before do
+ allow(Gitlab::Template::IssueTemplate).to receive(:template_names).and_return({})
+ allow(Gitlab::Template::MergeRequestTemplate).to receive(:template_names).and_return({})
+
+ helper.issuable_templates(project, 'issues')
+ helper.issuable_templates(project, 'merge_request')
+ end
+
+ it 'does not call TemplateFinder' do
+ expect(Gitlab::Template::IssueTemplate).not_to receive(:template_names)
+ expect(Gitlab::Template::MergeRequestTemplate).not_to receive(:template_names)
+ helper.issuable_templates(project, 'issues')
+ helper.issuable_templates(project, 'merge_request')
+ end
+ end
+
+ context 'when project has no parent group' do
+ it_behaves_like 'project issuable templates'
+ end
+
+ context 'when project has parent group' do
+ before do
+ project.update!(group: parent_group)
+ end
+
+ context 'when project parent group does not have a file template project' do
+ it_behaves_like 'project issuable templates'
+ end
+
+ context 'when project parent group has a file template project' do
+ let_it_be(:file_template_project) { create(:project, :custom_repo, group: parent_group, files: issuable_template_files) }
+ let_it_be(:group, reload: true) { create(:group, parent: parent_group) }
+ let_it_be(:project, reload: true) { create(:project, :custom_repo, group: group, files: issuable_template_files) }
+
+ before do
+ project.update!(group: group)
+ parent_group.update_columns(file_template_project_id: file_template_project.id)
+ end
+
+ it_behaves_like 'project issuable templates'
+ end
+ end
+ end
+
+ describe '#issuable_templates_names' do
+ let(:project) { double(Project, id: 21) }
+
+ let(:templates) do
+ [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
+ { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
+ ]
+ end
+
+ it 'returns project templates only' do
+ allow(helper).to receive(:ref_project).and_return(project)
+ allow(helper).to receive(:issuable_templates).and_return(templates)
+
+ expect(helper.issuable_templates_names(Issue.new)).to eq(%w[another_issue_template custom_issue_template])
+ end
+
+ context 'when there are not templates in the project' do
+ let(:templates) { {} }
+
+ it 'returns empty array' do
+ allow(helper).to receive(:ref_project).and_return(project)
+ allow(helper).to receive(:issuable_templates).and_return(templates)
+
+ expect(helper.issuable_templates_names(Issue.new)).to eq([])
+ end
+ end
+ end
+end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 57845904d32..d6b002b47eb 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -72,28 +72,38 @@ RSpec.describe IssuablesHelper do
let(:user) { create(:user) }
describe 'state text' do
- before do
- allow(helper).to receive(:issuables_count_for_state).and_return(42)
- end
-
- it 'returns "Open" when state is :opened' do
- expect(helper.issuables_state_counter_text(:issues, :opened, true))
- .to eq('<span>Open</span> <span class="badge badge-pill">42</span>')
- end
+ context 'when number of issuables can be generated' do
+ before do
+ allow(helper).to receive(:issuables_count_for_state).and_return(42)
+ end
- it 'returns "Closed" when state is :closed' do
- expect(helper.issuables_state_counter_text(:issues, :closed, true))
- .to eq('<span>Closed</span> <span class="badge badge-pill">42</span>')
+ it 'returns navigation with badges' do
+ expect(helper.issuables_state_counter_text(:issues, :opened, true))
+ .to eq('<span>Open</span> <span class="badge badge-pill">42</span>')
+ expect(helper.issuables_state_counter_text(:issues, :closed, true))
+ .to eq('<span>Closed</span> <span class="badge badge-pill">42</span>')
+ expect(helper.issuables_state_counter_text(:merge_requests, :merged, true))
+ .to eq('<span>Merged</span> <span class="badge badge-pill">42</span>')
+ expect(helper.issuables_state_counter_text(:merge_requests, :all, true))
+ .to eq('<span>All</span> <span class="badge badge-pill">42</span>')
+ end
end
- it 'returns "Merged" when state is :merged' do
- expect(helper.issuables_state_counter_text(:merge_requests, :merged, true))
- .to eq('<span>Merged</span> <span class="badge badge-pill">42</span>')
- end
+ context 'when count cannot be generated' do
+ before do
+ allow(helper).to receive(:issuables_count_for_state).and_return(-1)
+ end
- it 'returns "All" when state is :all' do
- expect(helper.issuables_state_counter_text(:merge_requests, :all, true))
- .to eq('<span>All</span> <span class="badge badge-pill">42</span>')
+ it 'returns avigation without badges' do
+ expect(helper.issuables_state_counter_text(:issues, :opened, true))
+ .to eq('<span>Open</span>')
+ expect(helper.issuables_state_counter_text(:issues, :closed, true))
+ .to eq('<span>Closed</span>')
+ expect(helper.issuables_state_counter_text(:merge_requests, :merged, true))
+ .to eq('<span>Merged</span>')
+ expect(helper.issuables_state_counter_text(:merge_requests, :all, true))
+ .to eq('<span>All</span>')
+ end
end
end
end
@@ -199,6 +209,7 @@ RSpec.describe IssuablesHelper do
markdownDocsPath: '/help/user/markdown',
lockVersion: issue.lock_version,
projectPath: @project.path,
+ projectId: @project.id,
projectNamespace: @project.namespace.path,
initialTitleHtml: issue.title,
initialTitleText: issue.title,
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 1ed61bd3144..07e55e9b016 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -254,4 +254,31 @@ RSpec.describe IssuesHelper do
expect(helper.use_startup_call?).to eq(true)
end
end
+
+ describe '#issue_header_actions_data' do
+ let(:current_user) { create(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(helper).to receive(:can?).and_return(true)
+ end
+
+ it 'returns expected result' do
+ expected = {
+ can_create_issue: "true",
+ can_reopen_issue: "true",
+ can_report_spam: "false",
+ can_update_issue: "true",
+ iid: issue.iid,
+ is_issue_author: "false",
+ issue_type: "issue",
+ new_issue_path: new_project_issue_path(project),
+ project_path: project.full_path,
+ report_abuse_path: new_abuse_report_path(user_id: issue.author.id, ref_url: issue_url(issue)),
+ submit_as_spam_path: mark_as_spam_project_issue_path(project, issue)
+ }
+
+ expect(helper.issue_header_actions_data(project, issue, current_user)).to include(expected)
+ end
+ end
end
diff --git a/spec/helpers/jira_connect_helper_spec.rb b/spec/helpers/jira_connect_helper_spec.rb
index a99072527c8..9695bed948b 100644
--- a/spec/helpers/jira_connect_helper_spec.rb
+++ b/spec/helpers/jira_connect_helper_spec.rb
@@ -4,12 +4,43 @@ require 'spec_helper'
RSpec.describe JiraConnectHelper do
describe '#jira_connect_app_data' do
- subject { helper.jira_connect_app_data }
+ let_it_be(:subscription) { create(:jira_connect_subscription) }
+ let(:user) { create(:user) }
- it 'includes Jira Connect app attributes' do
- is_expected.to include(
- :groups_path
- )
+ subject { helper.jira_connect_app_data([subscription]) }
+
+ context 'user is not logged in' do
+ before do
+ allow(view).to receive(:current_user).and_return(nil)
+ end
+
+ it 'includes Jira Connect app attributes' do
+ is_expected.to include(
+ :groups_path,
+ :subscriptions_path,
+ :users_path
+ )
+ end
+
+ it 'assigns users_path with value' do
+ expect(subject[:users_path]).to eq(jira_connect_users_path)
+ end
+
+ it 'passes group as "skip_groups" param' do
+ skip_groups_param = CGI.escape('skip_groups[]')
+
+ expect(subject[:groups_path]).to include("#{skip_groups_param}=#{subscription.namespace.id}")
+ end
+ end
+
+ context 'user is logged in' do
+ before do
+ allow(view).to receive(:current_user).and_return(user)
+ end
+
+ it 'assigns users_path to nil' do
+ expect(subject[:users_path]).to be_nil
+ end
end
end
end
diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb
new file mode 100644
index 00000000000..f789eb9d940
--- /dev/null
+++ b/spec/helpers/learn_gitlab_helper_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LearnGitlabHelper do
+ include AfterNextHelpers
+ include Devise::Test::ControllerHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, name: LearnGitlab::PROJECT_NAME, namespace: user.namespace) }
+ let_it_be(:namespace) { project.namespace }
+
+ before do
+ project.add_developer(user)
+
+ allow(helper).to receive(:user).and_return(user)
+ allow_next_instance_of(LearnGitlab) do |learn_gitlab|
+ allow(learn_gitlab).to receive(:project).and_return(project)
+ end
+
+ OnboardingProgress.onboard(namespace)
+ OnboardingProgress.register(namespace, :git_write)
+ end
+
+ describe '.onboarding_actions_data' do
+ subject(:onboarding_actions_data) { helper.onboarding_actions_data(project) }
+
+ it 'has all actions' do
+ expect(onboarding_actions_data.keys).to contain_exactly(
+ :git_write,
+ :pipeline_created,
+ :merge_request_created,
+ :user_added,
+ :trial_started,
+ :required_mr_approvals_enabled,
+ :code_owners_enabled,
+ :security_scan_enabled
+ )
+ end
+
+ it 'sets correct path and completion status' do
+ expect(onboarding_actions_data[:git_write]).to eq({
+ url: project_issue_url(project, LearnGitlabHelper::ACTION_ISSUE_IDS[:git_write]),
+ completed: true
+ })
+ expect(onboarding_actions_data[:pipeline_created]).to eq({
+ url: project_issue_url(project, LearnGitlabHelper::ACTION_ISSUE_IDS[:pipeline_created]),
+ completed: false
+ })
+ end
+ end
+
+ describe '.learn_gitlab_experiment_enabled?' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, namespace: user.namespace) }
+
+ let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
+
+ subject { helper.learn_gitlab_experiment_enabled?(project) }
+
+ where(:experiment_a, :experiment_b, :onboarding, :learn_gitlab_available, :result) do
+ true | false | true | true | true
+ false | true | true | true | true
+ false | false | true | true | false
+ true | true | true | false | false
+ true | true | false | true | false
+ end
+
+ with_them do
+ before do
+ stub_experiment_for_subject(learn_gitlab_a: experiment_a, learn_gitlab_b: experiment_b)
+ allow(OnboardingProgress).to receive(:onboarding?).with(project.namespace).and_return(onboarding)
+ allow_next(LearnGitlab, user).to receive(:available?).and_return(learn_gitlab_available)
+ end
+
+ context 'when signed in' do
+ before do
+ sign_in(user)
+ end
+
+ it { is_expected.to eq(result) }
+ end
+
+ context 'when not signed in' do
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
+end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 821faaab194..fce4d560b2f 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -89,15 +89,5 @@ RSpec.describe MergeRequestsHelper do
total: user.assigned_open_merge_requests_count + user.review_requested_open_merge_requests_count
)
end
-
- context 'when merge_request_reviewers is disabled' do
- before do
- stub_feature_flags(merge_request_reviewers: false)
- end
-
- it 'returns review_requested as 0' do
- expect(subject[:review_requested]).to eq(0)
- end
- end
end
end
diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb
index f9b3b535334..b8502cdf25e 100644
--- a/spec/helpers/notes_helper_spec.rb
+++ b/spec/helpers/notes_helper_spec.rb
@@ -316,4 +316,15 @@ RSpec.describe NotesHelper do
end
end
end
+
+ describe '#notes_data' do
+ let(:issue) { create(:issue, project: project) }
+
+ it 'sets last_fetched_at to 0 when start_at_zero is true' do
+ @project = project
+ @noteable = issue
+
+ expect(helper.notes_data(issue, true)[:lastFetchedAt]).to eq(0)
+ end
+ end
end
diff --git a/spec/helpers/notify_helper_spec.rb b/spec/helpers/notify_helper_spec.rb
index 9c9d745cb53..eb0f796038c 100644
--- a/spec/helpers/notify_helper_spec.rb
+++ b/spec/helpers/notify_helper_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe NotifyHelper do
include ActionView::Helpers::UrlHelper
+ using RSpec::Parameterized::TableSyntax
describe 'merge_request_reference_link' do
let(:project) { create(:project) }
@@ -27,6 +28,36 @@ RSpec.describe NotifyHelper do
end
end
+ describe '#invited_role_description' do
+ where(:role, :description) do
+ "Guest" | /As a guest/
+ "Reporter" | /As a reporter/
+ "Developer" | /As a developer/
+ "Maintainer" | /As a maintainer/
+ "Owner" | /As an owner/
+ "Minimal Access" | /As a user with minimal access/
+ end
+
+ with_them do
+ specify do
+ expect(helper.invited_role_description(role)).to match description
+ end
+ end
+ end
+
+ describe '#invited_to_description' do
+ where(:source, :description) do
+ "project" | /Projects can/
+ "group" | /Groups assemble/
+ end
+
+ with_them do
+ specify do
+ expect(helper.invited_to_description(source)).to match description
+ end
+ end
+ end
+
def reference_link(entity, url)
"<a href=\"#{url}\">#{entity.to_reference}</a>"
end
diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb
index 801d5de79b1..5b0ce00063f 100644
--- a/spec/helpers/operations_helper_spec.rb
+++ b/spec/helpers/operations_helper_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe OperationsHelper do
it 'returns the correct values' do
expect(subject).to eq(
- 'alerts_setup_url' => help_page_path('operations/incident_management/alert_integrations.md', anchor: 'generic-http-endpoint'),
+ 'alerts_setup_url' => help_page_path('operations/incident_management/integrations.md', anchor: 'configuration'),
'alerts_usage_url' => project_alert_management_index_path(project),
'prometheus_form_path' => project_service_path(project, prometheus_service),
'prometheus_reset_key_path' => reset_alerting_token_project_settings_operations_path(project),
diff --git a/spec/helpers/projects/alert_management_helper_spec.rb b/spec/helpers/projects/alert_management_helper_spec.rb
index fd35c1ecab8..0df194e460a 100644
--- a/spec/helpers/projects/alert_management_helper_spec.rb
+++ b/spec/helpers/projects/alert_management_helper_spec.rb
@@ -28,8 +28,8 @@ RSpec.describe Projects::AlertManagementHelper do
expect(helper.alert_management_data(current_user, project)).to match(
'project-path' => project_path,
'enable-alert-management-path' => setting_path,
- 'alerts-help-url' => 'http://test.host/help/operations/incident_management/index.md',
- 'populating-alerts-help-url' => 'http://test.host/help/operations/incident_management/index.md#enable-alert-management',
+ 'alerts-help-url' => 'http://test.host/help/operations/incident_management/alerts.md',
+ 'populating-alerts-help-url' => 'http://test.host/help/operations/incident_management/integrations.md#configuration',
'empty-alert-svg-path' => match_asset_path('/assets/illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => 'true',
'alert-management-enabled' => 'false',
@@ -113,7 +113,8 @@ RSpec.describe Projects::AlertManagementHelper do
'alert-id' => alert_id,
'project-path' => project_path,
'project-id' => project_id,
- 'project-issues-path' => issues_path
+ 'project-issues-path' => issues_path,
+ 'page' => 'OPERATIONS'
)
end
end
diff --git a/spec/helpers/projects/project_members_helper_spec.rb b/spec/helpers/projects/project_members_helper_spec.rb
index cc290367e34..5e0b4df7f7f 100644
--- a/spec/helpers/projects/project_members_helper_spec.rb
+++ b/spec/helpers/projects/project_members_helper_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::ProjectMembersHelper do
+ include MembersPresentation
+
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
@@ -142,4 +144,58 @@ RSpec.describe Projects::ProjectMembersHelper do
it { is_expected.to be(false) }
end
end
+
+ describe 'project members' do
+ let_it_be(:project_members) { create_list(:project_member, 1, project: project) }
+
+ describe '#project_members_data_json' do
+ it 'matches json schema' do
+ expect(helper.project_members_data_json(project, present_members(project_members))).to match_schema('members')
+ end
+ end
+
+ describe '#project_members_list_data_attributes' do
+ let(:allow_admin_project) { true }
+
+ before do
+ allow(helper).to receive(:project_project_member_path).with(project, ':id').and_return('/foo-bar/-/project_members/:id')
+ end
+
+ it 'returns expected hash' do
+ expect(helper.project_members_list_data_attributes(project, present_members(project_members))).to include({
+ members: helper.project_members_data_json(project, present_members(project_members)),
+ member_path: '/foo-bar/-/project_members/:id',
+ source_id: project.id,
+ can_manage_members: true
+ })
+ end
+ end
+ end
+
+ describe 'project group links' do
+ let_it_be(:project_group_links) { create_list(:project_group_link, 1, project: project) }
+ let(:allow_admin_project) { true }
+
+ describe '#project_group_links_data_json' do
+ it 'matches json schema' do
+ expect(helper.project_group_links_data_json(project_group_links)).to match_schema('group_link/project_group_links')
+ end
+ end
+
+ describe '#project_group_links_list_data_attributes' do
+ before do
+ allow(helper).to receive(:project_group_link_path).with(project, ':id').and_return('/foo-bar/-/group_links/:id')
+ allow(helper).to receive(:can?).with(current_user, :admin_project_member, project).and_return(true)
+ end
+
+ it 'returns expected hash' do
+ expect(helper.project_group_links_list_data_attributes(project, project_group_links)).to include({
+ members: helper.project_group_links_data_json(project_group_links),
+ member_path: '/foo-bar/-/group_links/:id',
+ source_id: project.id,
+ can_manage_members: true
+ })
+ end
+ end
+ end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index b920e2e5600..303e3c78153 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe ProjectsHelper do
include ProjectForksHelper
+ include AfterNextHelpers
let_it_be_with_reload(:project) { create(:project) }
let_it_be_with_refind(:project_with_repo) { create(:project, :repository) }
@@ -398,6 +399,45 @@ RSpec.describe ProjectsHelper do
helper.send(:get_project_nav_tabs, project, user)
end
+ context 'Security & Compliance tabs' do
+ before do
+ stub_feature_flags(secure_security_and_compliance_configuration_page_on_ce: feature_flag_enabled)
+ allow(helper).to receive(:can?).with(user, :read_security_configuration, project).and_return(can_read_security_configuration)
+ end
+
+ context 'when user cannot read security configuration' do
+ let(:can_read_security_configuration) { false }
+
+ context 'when feature flag is disabled' do
+ let(:feature_flag_enabled) { false }
+
+ it { is_expected.not_to include(:security_configuration) }
+ end
+
+ context 'when feature flag is enabled' do
+ let(:feature_flag_enabled) { true }
+
+ it { is_expected.not_to include(:security_configuration) }
+ end
+ end
+
+ context 'when user can read security configuration' do
+ let(:can_read_security_configuration) { true }
+
+ context 'when feature flag is disabled' do
+ let(:feature_flag_enabled) { false }
+
+ it { is_expected.not_to include(:security_configuration) }
+ end
+
+ context 'when feature flag is enabled' do
+ let(:feature_flag_enabled) { true }
+
+ it { is_expected.to include(:security_configuration) }
+ end
+ end
+ end
+
context 'when builds feature is enabled' do
before do
allow(project).to receive(:builds_enabled?).and_return(true)
@@ -459,6 +499,20 @@ RSpec.describe ProjectsHelper do
it { is_expected.not_to include(:confluence) }
it { is_expected.to include(:wiki) }
end
+
+ context 'learn gitlab experiment' do
+ context 'when it is enabled' do
+ before do
+ expect(helper).to receive(:learn_gitlab_experiment_enabled?).with(project).and_return(true)
+ end
+
+ it { is_expected.to include(:learn_gitlab) }
+ end
+
+ context 'when it is not enabled' do
+ it { is_expected.not_to include(:learn_gitlab) }
+ end
+ end
end
describe '#can_view_operations_tab?' do
@@ -657,31 +711,6 @@ RSpec.describe ProjectsHelper do
end
end
- describe 'link_to_filter_repo' do
- subject { helper.link_to_filter_repo }
-
- it 'generates a hardcoded link to git filter-repo' do
- result = helper.link_to_filter_repo
- doc = Nokogiri::HTML.fragment(result)
-
- expect(doc.children.size).to eq(1)
-
- link = doc.children.first
-
- aggregate_failures do
- expect(result).to be_html_safe
-
- expect(link.name).to eq('a')
- expect(link[:target]).to eq('_blank')
- expect(link[:rel]).to eq('noopener noreferrer')
- expect(link[:href]).to eq('https://github.com/newren/git-filter-repo')
- expect(link.inner_html).to eq('git filter-repo')
-
- expect(result).to be_html_safe
- end
- end
- end
-
describe '#explore_projects_tab?' do
subject { helper.explore_projects_tab? }
@@ -854,16 +883,36 @@ RSpec.describe ProjectsHelper do
end
describe '#can_import_members?' do
- let(:owner) { project.owner }
+ context 'when user is project owner' do
+ before do
+ allow(helper).to receive(:current_user) { project.owner }
+ end
- it 'returns false if user cannot admin_project_member' do
- allow(helper).to receive(:current_user) { user }
- expect(helper.can_import_members?).to eq false
+ it 'returns true for owner of project' do
+ expect(helper.can_import_members?).to eq true
+ end
end
- it 'returns true if user can admin_project_member' do
- allow(helper).to receive(:current_user) { owner }
- expect(helper.can_import_members?).to eq true
+ context 'when user is not a project owner' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:user_project_role, :can_import) do
+ :maintainer | true
+ :developer | false
+ :reporter | false
+ :guest | false
+ end
+
+ with_them do
+ before do
+ project.add_role(user, user_project_role)
+ allow(helper).to receive(:current_user) { user }
+ end
+
+ it 'resolves if the user can import members' do
+ expect(helper.can_import_members?).to eq can_import
+ end
+ end
end
end
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 2cb9d66ac63..a977f2c88c6 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -610,4 +610,35 @@ RSpec.describe SearchHelper do
end
end
end
+
+ describe '#search_sort_options' do
+ let(:user) { create(:user) }
+
+ mock_created_sort = [
+ {
+ title: _('Created date'),
+ sortable: true,
+ sortParam: {
+ asc: 'created_asc',
+ desc: 'created_desc'
+ }
+ },
+ {
+ title: _('Last updated'),
+ sortable: true,
+ sortParam: {
+ asc: 'updated_asc',
+ desc: 'updated_desc'
+ }
+ }
+ ]
+
+ before do
+ allow(self).to receive(:current_user).and_return(user)
+ end
+
+ it 'returns the correct data' do
+ expect(search_sort_options).to eq(mock_created_sort)
+ end
+ end
end
diff --git a/spec/helpers/sorting_helper_spec.rb b/spec/helpers/sorting_helper_spec.rb
index 2d581dfba37..f976fb098a8 100644
--- a/spec/helpers/sorting_helper_spec.rb
+++ b/spec/helpers/sorting_helper_spec.rb
@@ -50,24 +50,6 @@ RSpec.describe SortingHelper do
end
end
- describe '#search_sort_direction_button' do
- before do
- set_sorting_url 'test_label'
- end
-
- it 'keeps label filter param' do
- expect(search_sort_direction_button('created_asc')).to include('label_name=test_label')
- end
-
- it 'returns icon with sort-lowest when sort is asc' do
- expect(search_sort_direction_button('created_asc')).to include('sort-lowest')
- end
-
- it 'returns icon with sort-highest when sort is desc' do
- expect(search_sort_direction_button('created_desc')).to include('sort-highest')
- end
- end
-
def stub_controller_path(value)
allow(helper.controller).to receive(:controller_path).and_return(value)
end
diff --git a/spec/helpers/stat_anchors_helper_spec.rb b/spec/helpers/stat_anchors_helper_spec.rb
index c6556647bc8..0615baac3cb 100644
--- a/spec/helpers/stat_anchors_helper_spec.rb
+++ b/spec/helpers/stat_anchors_helper_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe StatAnchorsHelper do
let(:anchor) { anchor_klass.new(false, nil, nil, 'default') }
it 'returns the proper attributes' do
- expect(subject[:class]).to include('btn btn-default')
+ expect(subject[:class]).to include('gl-button btn btn-default')
end
end
@@ -29,7 +29,7 @@ RSpec.describe StatAnchorsHelper do
let(:anchor) { anchor_klass.new(false) }
it 'returns the proper attributes' do
- expect(subject[:class]).to include('btn btn-missing')
+ expect(subject[:class]).to include('gl-button btn btn-dashed')
end
end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index 6cb9894e306..bc25a2fcdfc 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -19,94 +19,6 @@ RSpec.describe TreeHelper do
)
end
- describe '.render_tree' do
- before do
- @id = sha
- @path = ""
- @project = project
- @lfs_blob_ids = []
- end
-
- it 'displays all entries without a warning' do
- tree = repository.tree(sha, 'files')
-
- html = render_tree(tree)
-
- expect(html).not_to have_selector('.tree-truncated-warning')
- end
-
- it 'truncates entries and adds a warning' do
- stub_const('TreeHelper::FILE_LIMIT', 1)
- tree = repository.tree(sha, 'files')
-
- html = render_tree(tree)
-
- expect(html).to have_selector('.tree-truncated-warning', count: 1)
- expect(html).to have_selector('.tree-item-file-name', count: 1)
- end
- end
-
- describe '.fast_project_blob_path' do
- it 'generates the same path as project_blob_path' do
- blob_path = repository.tree(sha, 'with space').entries.first.path
- fast_path = fast_project_blob_path(project, blob_path)
- std_path = project_blob_path(project, blob_path)
-
- expect(fast_path).to eq(std_path)
- end
-
- it 'generates the same path with encoded file names' do
- tree = repository.tree(sha, 'encoding')
- blob_path = tree.entries.find { |entry| entry.path == 'encoding/テスト.txt' }.path
- fast_path = fast_project_blob_path(project, blob_path)
- std_path = project_blob_path(project, blob_path)
-
- expect(fast_path).to eq(std_path)
- end
-
- it 'respects a configured relative URL' do
- allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return('/gitlab/root')
- blob_path = repository.tree(sha, '').entries.first.path
- fast_path = fast_project_blob_path(project, blob_path)
-
- expect(fast_path).to start_with('/gitlab/root')
- end
-
- it 'encodes files starting with #' do
- filename = '#test-file'
- create_file(filename)
-
- fast_path = fast_project_blob_path(project, filename)
-
- expect(fast_path).to end_with('%23test-file')
- end
- end
-
- describe '.fast_project_tree_path' do
- let(:tree_path) { repository.tree(sha, 'with space').path }
- let(:fast_path) { fast_project_tree_path(project, tree_path) }
- let(:std_path) { project_tree_path(project, tree_path) }
-
- it 'generates the same path as project_tree_path' do
- expect(fast_path).to eq(std_path)
- end
-
- it 'respects a configured relative URL' do
- allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return('/gitlab/root')
-
- expect(fast_path).to start_with('/gitlab/root')
- end
-
- it 'encodes files starting with #' do
- filename = '#test-file'
- create_file(filename)
-
- fast_path = fast_project_tree_path(project, filename)
-
- expect(fast_path).to end_with('%23test-file')
- end
- end
-
describe 'flatten_tree' do
let(:tree) { repository.tree(sha, 'files') }
let(:root_path) { 'files' }
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index 250aedda906..b6607182461 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -222,4 +222,24 @@ RSpec.describe UserCalloutsHelper do
it { is_expected.to be true }
end
end
+
+ describe '.show_unfinished_tag_cleanup_callout?' do
+ subject { helper.show_unfinished_tag_cleanup_callout? }
+
+ before do
+ allow(helper).to receive(:user_dismissed?).with(described_class::UNFINISHED_TAG_CLEANUP_CALLOUT) { dismissed }
+ end
+
+ context 'when user has not dismissed' do
+ let(:dismissed) { false }
+
+ it { is_expected.to be true }
+ end
+
+ context 'when user dismissed' do
+ let(:dismissed) { true }
+
+ it { is_expected.to be false }
+ end
+ end
end
diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb
index d5f9ef569c7..abb1673bb88 100644
--- a/spec/initializers/lograge_spec.rb
+++ b/spec/initializers/lograge_spec.rb
@@ -64,11 +64,11 @@ RSpec.describe 'lograge', type: :request do
)
expect(Lograge.formatter).to receive(:call)
- .with(a_hash_including(cpu_s: 0.11))
+ .with(a_hash_including(cpu_s: 0.111112))
.and_call_original
expect(Lograge.logger).to receive(:send)
- .with(anything, include('"cpu_s":0.11'))
+ .with(anything, include('"cpu_s":0.111112'))
.and_call_original
subject
@@ -89,6 +89,26 @@ RSpec.describe 'lograge', type: :request do
subject
end
+ context 'when logging memory allocations' do
+ include MemoryInstrumentationHelper
+
+ before do
+ skip_memory_instrumentation!
+ end
+
+ it 'logs memory usage metrics' do
+ expect(Lograge.formatter).to receive(:call)
+ .with(a_hash_including(:mem_objects))
+ .and_call_original
+
+ expect(Lograge.logger).to receive(:send)
+ .with(anything, include('"mem_objects":'))
+ .and_call_original
+
+ subject
+ end
+ end
+
it 'limits param size' do
expect(Lograge.formatter).to receive(:call)
.with(a_hash_including(params: limited_params))
diff --git a/spec/initializers/net_http_patch_spec.rb b/spec/initializers/net_http_patch_spec.rb
new file mode 100644
index 00000000000..e5205abbed2
--- /dev/null
+++ b/spec/initializers/net_http_patch_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+require 'fast_spec_helper'
+
+RSpec.describe 'Net::HTTP patch proxy user and password encoding' do
+ let(:net_http) { Net::HTTP.new('hostname.example') }
+
+ describe '#proxy_user' do
+ subject { net_http.proxy_user }
+
+ it { is_expected.to eq(nil) }
+
+ context 'with http_proxy env' do
+ let(:http_proxy) { 'http://proxy.example:8000' }
+
+ before do
+ allow(ENV).to receive(:[]).and_call_original
+ allow(ENV).to receive(:[]).with('http_proxy').and_return(http_proxy)
+ end
+
+ it { is_expected.to eq(nil) }
+
+ context 'and user:password authentication' do
+ let(:http_proxy) { 'http://Y%5CX:R%25S%5D%20%3FX@proxy.example:8000' }
+
+ context 'when on multiuser safe platform' do
+ # linux, freebsd, darwin are considered multi user safe platforms
+ # See https://github.com/ruby/net-http/blob/v0.1.1/lib/net/http.rb#L1174-L1178
+
+ before do
+ allow(net_http).to receive(:environment_variable_is_multiuser_safe?).and_return(true)
+ end
+
+ it { is_expected.to eq 'Y\\X' }
+ end
+
+ context 'when not on multiuser safe platform' do
+ before do
+ allow(net_http).to receive(:environment_variable_is_multiuser_safe?).and_return(false)
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+ end
+
+ describe '#proxy_pass' do
+ subject { net_http.proxy_pass }
+
+ it { is_expected.to eq(nil) }
+
+ context 'with http_proxy env' do
+ let(:http_proxy) { 'http://proxy.example:8000' }
+
+ before do
+ allow(ENV).to receive(:[]).and_call_original
+ allow(ENV).to receive(:[]).with('http_proxy').and_return(http_proxy)
+ end
+
+ it { is_expected.to eq(nil) }
+
+ context 'and user:password authentication' do
+ let(:http_proxy) { 'http://Y%5CX:R%25S%5D%20%3FX@proxy.example:8000' }
+
+ context 'when on multiuser safe platform' do
+ # linux, freebsd, darwin are considered multi user safe platforms
+ # See https://github.com/ruby/net-http/blob/v0.1.1/lib/net/http.rb#L1174-L1178
+
+ before do
+ allow(net_http).to receive(:environment_variable_is_multiuser_safe?).and_return(true)
+ end
+
+ it { is_expected.to eq 'R%S] ?X' }
+ end
+
+ context 'when not on multiuser safe platform' do
+ before do
+ allow(net_http).to receive(:environment_variable_is_multiuser_safe?).and_return(false)
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/initializers/validate_puma_spec.rb b/spec/initializers/validate_puma_spec.rb
new file mode 100644
index 00000000000..9ff0ef2c319
--- /dev/null
+++ b/spec/initializers/validate_puma_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'validate puma' do
+ include RakeHelpers
+
+ subject do
+ load Rails.root.join('config/initializers/validate_puma.rb')
+ end
+
+ before do
+ stub_const('Puma', double)
+ allow(Gitlab::Runtime).to receive(:puma?).and_return(true)
+ allow(Puma).to receive_message_chain(:cli_config, :options).and_return(workers: workers)
+ end
+
+ context 'for .com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ context 'when worker count is 0' do
+ let(:workers) { 0 }
+
+ specify { expect { subject }.to raise_error(String) }
+ end
+
+ context 'when worker count is > 0' do
+ let(:workers) { 2 }
+
+ specify { expect { subject }.not_to raise_error }
+ end
+ end
+
+ context 'for other environments' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(false)
+
+ allow(main_object).to receive(:warn)
+ end
+
+ context 'when worker count is 0' do
+ let(:workers) { 0 }
+
+ specify { expect { subject }.not_to raise_error }
+
+ it 'warns about running Puma in a Single mode' do
+ expect(main_object).to receive(:warn) do |warning|
+ expect(warning).to include('https://gitlab.com/groups/gitlab-org/-/epics/5303')
+ end
+
+ subject
+ end
+ end
+
+ context 'when worker count is > 0' do
+ let(:workers) { 2 }
+
+ specify { expect { subject }.not_to raise_error }
+
+ it 'does not issue a warning' do
+ expect(main_object).not_to receive(:warn)
+ end
+ end
+ end
+end
diff --git a/spec/javascripts/fly_out_nav_browser_spec.js b/spec/javascripts/fly_out_nav_browser_spec.js
index f92994594a9..12ea0e262bc 100644
--- a/spec/javascripts/fly_out_nav_browser_spec.js
+++ b/spec/javascripts/fly_out_nav_browser_spec.js
@@ -3,6 +3,7 @@
// see: https://gitlab.com/groups/gitlab-org/-/epics/895#what-if-theres-a-karma-spec-which-is-simply-unmovable-to-jest-ie-it-is-dependent-on-a-running-browser-environment
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
+import { SIDEBAR_COLLAPSED_CLASS } from '~/contextual_sidebar';
import {
calculateTop,
showSubLevelItems,
@@ -19,7 +20,6 @@ import {
setSidebar,
subItemsMouseLeave,
} from '~/fly_out_nav';
-import { SIDEBAR_COLLAPSED_CLASS } from '~/contextual_sidebar';
describe('Fly out sidebar navigation', () => {
let el;
diff --git a/spec/javascripts/matchers.js b/spec/javascripts/matchers.js
deleted file mode 100644
index ae005e152ed..00000000000
--- a/spec/javascripts/matchers.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import pixelmatch from 'pixelmatch';
-
-export default {
- toImageDiffEqual: () => {
- const getImageData = (img) => {
- const canvas = document.createElement('canvas');
- canvas.width = img.width;
- canvas.height = img.height;
- canvas.getContext('2d').drawImage(img, 0, 0);
- return canvas.getContext('2d').getImageData(0, 0, img.width, img.height).data;
- };
-
- return {
- compare(actual, expected, threshold = 0.1) {
- if (actual.height !== expected.height || actual.width !== expected.width) {
- return {
- pass: false,
- message: `Expected image dimensions (h x w) of ${expected.height}x${expected.width}.
- Received an image with ${actual.height}x${actual.width}`,
- };
- }
-
- const { width, height } = actual;
- const differentPixels = pixelmatch(
- getImageData(actual),
- getImageData(expected),
- null,
- width,
- height,
- { threshold },
- );
-
- return {
- pass: differentPixels < 20,
- message: `${differentPixels} pixels differ more than ${
- threshold * 100
- } percent between input and output.`,
- };
- },
- };
- },
-};
diff --git a/spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js b/spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js
index bbcdc0b879f..ec8d2778c1f 100644
--- a/spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js
+++ b/spec/javascripts/monitoring/components/dashboard_resize_browser_spec.js
@@ -5,14 +5,14 @@
* https://gitlab.com/groups/gitlab-org/-/epics/895#what-if-theres-a-karma-spec-which-is-simply-unmovable-to-jest-ie-it-is-dependent-on-a-running-browser-environment
*/
-import Vue from 'vue';
import { createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
+import axios from '~/lib/utils/axios_utils';
import Dashboard from '~/monitoring/components/dashboard.vue';
import { createStore } from '~/monitoring/stores';
-import axios from '~/lib/utils/axios_utils';
-import { mockApiEndpoint } from '../mock_data';
import { metricsDashboardPayload, dashboardProps } from '../fixture_data';
+import { mockApiEndpoint } from '../mock_data';
import { setupStoreWithData } from '../store_utils';
const localVue = createLocalVue();
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index 59136de0b0d..be14d2ee7e7 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -2,20 +2,18 @@
jasmine/no-global-setup, no-underscore-dangle, no-console
*/
+import { config as testUtilsConfig } from '@vue/test-utils';
+import jasmineDiff from 'jasmine-diff';
import $ from 'jquery';
import 'core-js/features/set-immediate';
import 'vendor/jasmine-jquery';
import '~/commons';
import Vue from 'vue';
-import jasmineDiff from 'jasmine-diff';
-import { config as testUtilsConfig } from '@vue/test-utils';
+import { getDefaultAdapter } from '~/lib/utils/axios_utils';
import Translate from '~/vue_shared/translate';
-import { getDefaultAdapter } from '~/lib/utils/axios_utils';
import { FIXTURES_PATH, TEST_HOST } from './test_constants';
-import customMatchers from './matchers';
-
// Tech debt issue TBD
testUtilsConfig.logModifiedComponents = false;
@@ -58,7 +56,6 @@ beforeAll(() => {
inline: window.__karma__.config.color,
}),
);
- jasmine.addMatchers(customMatchers);
});
// globalize common libraries
@@ -81,14 +78,6 @@ window.addEventListener('unhandledrejection', (event) => {
console.error(event.reason.stack || event.reason);
});
-// HACK: Chrome 59 disconnects if there are too many synchronous tests in a row
-// because it appears to lock up the thread that communicates to Karma's socket
-// This async beforeEach gets called on every spec and releases the JS thread long
-// enough for the socket to continue to communicate.
-// The downside is that it creates a minor performance penalty in the time it takes
-// to run our unit tests.
-beforeEach((done) => done());
-
let longRunningTestTimeoutHandle;
beforeEach((done) => {
diff --git a/spec/lib/api/entities/merge_request_basic_spec.rb b/spec/lib/api/entities/merge_request_basic_spec.rb
index fe4c27b70ae..8572b067984 100644
--- a/spec/lib/api/entities/merge_request_basic_spec.rb
+++ b/spec/lib/api/entities/merge_request_basic_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe ::API::Entities::MergeRequestBasic do
let_it_be(:project) { create(:project, :public) }
let_it_be(:merge_request) { create(:merge_request) }
let_it_be(:labels) { create_list(:label, 3) }
- let_it_be(:merge_requests) { create_list(:labeled_merge_request, 10, :unique_branches, :with_diffs, labels: labels) }
+ let_it_be(:merge_requests) { create_list(:labeled_merge_request, 10, :unique_branches, labels: labels) }
# This mimics the behavior of the `Grape::Entity` serializer
def present(obj)
@@ -42,29 +42,14 @@ RSpec.describe ::API::Entities::MergeRequestBasic do
end
context 'reviewers' do
- context "when merge_request_reviewers FF is enabled" do
- before do
- stub_feature_flags(merge_request_reviewers: true)
- merge_request.reviewers = [user]
- end
-
- it 'includes assigned reviewers' do
- result = Gitlab::Json.parse(present(merge_request).to_json)
-
- expect(result['reviewers'][0]['username']).to eq user.username
- end
+ before do
+ merge_request.reviewers = [user]
end
- context "when merge_request_reviewers FF is disabled" do
- before do
- stub_feature_flags(merge_request_reviewers: false)
- end
-
- it 'does not include reviewers' do
- result = Gitlab::Json.parse(present(merge_request).to_json)
+ it 'includes assigned reviewers' do
+ result = Gitlab::Json.parse(present(merge_request).to_json)
- expect(result.keys).not_to include('reviewers')
- end
+ expect(result['reviewers'][0]['username']).to eq user.username
end
end
end
diff --git a/spec/lib/api/entities/user_spec.rb b/spec/lib/api/entities/user_spec.rb
index 99ffe0eb925..e35deeb6263 100644
--- a/spec/lib/api/entities/user_spec.rb
+++ b/spec/lib/api/entities/user_spec.rb
@@ -23,4 +23,16 @@ RSpec.describe API::Entities::User do
expect(subject).not_to include(:created_at)
end
+
+ it 'exposes user as not a bot' do
+ expect(subject[:bot]).to be_falsey
+ end
+
+ context 'with bot user' do
+ let(:user) { create(:user, :security_bot) }
+
+ it 'exposes user as a bot' do
+ expect(subject[:bot]).to eq(true)
+ end
+ end
end
diff --git a/spec/lib/api/support/git_access_actor_spec.rb b/spec/lib/api/support/git_access_actor_spec.rb
index 143cc6e56ee..a09cabf4cd7 100644
--- a/spec/lib/api/support/git_access_actor_spec.rb
+++ b/spec/lib/api/support/git_access_actor_spec.rb
@@ -152,6 +152,10 @@ RSpec.describe API::Support::GitAccessActor do
end
describe '#update_last_used_at!' do
+ before do
+ stub_feature_flags(disable_ssh_key_used_tracking: false)
+ end
+
context 'when initialized with a User' do
let(:user) { build(:user) }
@@ -170,6 +174,14 @@ RSpec.describe API::Support::GitAccessActor do
subject.update_last_used_at!
end
+
+ it 'does not update `last_used_at` when the functionality is disabled' do
+ stub_feature_flags(disable_ssh_key_used_tracking: true)
+
+ expect(key).not_to receive(:update_last_used_at)
+
+ subject.update_last_used_at!
+ end
end
end
end
diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb
index 21ee40f22fe..5c8d4282118 100644
--- a/spec/lib/atlassian/jira_connect/client_spec.rb
+++ b/spec/lib/atlassian/jira_connect/client_spec.rb
@@ -18,15 +18,15 @@ RSpec.describe Atlassian::JiraConnect::Client do
end
end
- around do |example|
- freeze_time { example.run }
- end
-
describe '.generate_update_sequence_id' do
- it 'returns monotonic_time converted it to integer' do
- allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(1.0)
+ it 'returns unix time in microseconds as integer', :aggregate_failures do
+ travel_to(Time.utc(1970, 1, 1, 0, 0, 1)) do
+ expect(described_class.generate_update_sequence_id).to eq(1000)
+ end
- expect(described_class.generate_update_sequence_id).to eq(1)
+ travel_to(Time.utc(1970, 1, 1, 0, 0, 5)) do
+ expect(described_class.generate_update_sequence_id).to eq(5000)
+ end
end
end
@@ -238,22 +238,6 @@ RSpec.describe Atlassian::JiraConnect::Client do
expect(response['errorMessages']).to eq(%w(X Y Z))
end
end
-
- it 'does not call the API if the feature flag is not enabled' do
- stub_feature_flags(jira_sync_deployments: false)
-
- expect(subject).not_to receive(:post)
-
- subject.send(:store_deploy_info, project: project, deployments: deployments)
- end
-
- it 'does call the API if the feature flag enabled for the project' do
- stub_feature_flags(jira_sync_deployments: project)
-
- expect(subject).to receive(:post).with('/rest/deployments/0.1/bulk', { deployments: Array }).and_call_original
-
- subject.send(:store_deploy_info, project: project, deployments: deployments)
- end
end
describe '#store_ff_info' do
@@ -319,24 +303,6 @@ RSpec.describe Atlassian::JiraConnect::Client do
expect(response['errorMessages']).to eq(['a: X', 'a: Y', 'b: Z'])
end
end
-
- it 'does not call the API if the feature flag is not enabled' do
- stub_feature_flags(jira_sync_feature_flags: false)
-
- expect(subject).not_to receive(:post)
-
- subject.send(:store_ff_info, project: project, feature_flags: feature_flags)
- end
-
- it 'does call the API if the feature flag enabled for the project' do
- stub_feature_flags(jira_sync_feature_flags: project)
-
- expect(subject).to receive(:post).with('/rest/featureflags/0.1/bulk', {
- flags: Array, properties: Hash
- }).and_call_original
-
- subject.send(:store_ff_info, project: project, feature_flags: feature_flags)
- end
end
describe '#store_build_info' do
@@ -384,24 +350,6 @@ RSpec.describe Atlassian::JiraConnect::Client do
subject.send(:store_build_info, project: project, pipelines: pipelines.take(1))
end
- it 'does not call the API if the feature flag is not enabled' do
- stub_feature_flags(jira_sync_builds: false)
-
- expect(subject).not_to receive(:post)
-
- subject.send(:store_build_info, project: project, pipelines: pipelines)
- end
-
- it 'does call the API if the feature flag enabled for the project' do
- stub_feature_flags(jira_sync_builds: project)
-
- expect(subject).to receive(:post)
- .with('/rest/builds/0.1/bulk', { builds: Array })
- .and_call_original
-
- subject.send(:store_build_info, project: project, pipelines: pipelines)
- end
-
context 'there are errors' do
let(:failures) do
[{ errors: [{ message: 'X' }, { message: 'Y' }] }, { errors: [{ message: 'Z' }] }]
diff --git a/spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb
index 964801338cf..2d12cd1ed0a 100644
--- a/spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb
+++ b/spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::FeatureFlagEntity do
subject { described_class.represent(feature_flag) }
context 'when the feature flag does not belong to any Jira issue' do
- let_it_be(:feature_flag) { create(:operations_feature_flag) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project) }
describe '#issue_keys' do
it 'is empty' do
@@ -30,7 +30,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::FeatureFlagEntity do
context 'when the feature flag does belong to a Jira issue' do
let(:feature_flag) do
- create(:operations_feature_flag, description: 'THING-123')
+ create(:operations_feature_flag, project: project, description: 'THING-123')
end
describe '#issue_keys' do
@@ -66,6 +66,7 @@ RSpec.describe Atlassian::JiraConnect::Serializers::FeatureFlagEntity do
end
it 'has the correct summary' do
+ expect(entity.dig('summary', 'url')).to eq "http://localhost/#{project.full_path}/-/feature_flags/#{feature_flag.iid}/edit"
expect(entity.dig('summary', 'status')).to eq(
'enabled' => true,
'defaultValue' => '',
diff --git a/spec/lib/backup/files_spec.rb b/spec/lib/backup/files_spec.rb
index 450e396a389..92de191da2d 100644
--- a/spec/lib/backup/files_spec.rb
+++ b/spec/lib/backup/files_spec.rb
@@ -21,10 +21,6 @@ RSpec.describe Backup::Files do
allow(File).to receive(:realpath).with("/var/gitlab-pages").and_return("/var/gitlab-pages")
allow(File).to receive(:realpath).with("/var/gitlab-pages/..").and_return("/var")
- allow_any_instance_of(String).to receive(:color) do |string, _color|
- string
- end
-
allow_any_instance_of(described_class).to receive(:progress).and_return(progress)
end
@@ -150,7 +146,7 @@ RSpec.describe Backup::Files do
it 'excludes tmp dirs from rsync' do
expect(Gitlab::Popen).to receive(:popen)
- .with(%w(rsync -a --delete --exclude=lost+found --exclude=/@pages.tmp /var/gitlab-pages /var/gitlab-backup))
+ .with(%w(rsync -a --delete --exclude=lost+found --exclude=/gitlab-pages/@pages.tmp /var/gitlab-pages /var/gitlab-backup))
.and_return(['', 0])
subject.dump
@@ -158,7 +154,7 @@ RSpec.describe Backup::Files do
it 'retries if rsync fails due to vanishing files' do
expect(Gitlab::Popen).to receive(:popen)
- .with(%w(rsync -a --delete --exclude=lost+found --exclude=/@pages.tmp /var/gitlab-pages /var/gitlab-backup))
+ .with(%w(rsync -a --delete --exclude=lost+found --exclude=/gitlab-pages/@pages.tmp /var/gitlab-pages /var/gitlab-backup))
.and_return(['rsync failed', 24], ['', 0])
expect do
@@ -168,7 +164,7 @@ RSpec.describe Backup::Files do
it 'raises an error and outputs an error message if rsync failed' do
allow(Gitlab::Popen).to receive(:popen)
- .with(%w(rsync -a --delete --exclude=lost+found --exclude=/@pages.tmp /var/gitlab-pages /var/gitlab-backup))
+ .with(%w(rsync -a --delete --exclude=lost+found --exclude=/gitlab-pages/@pages.tmp /var/gitlab-pages /var/gitlab-backup))
.and_return(['rsync failed', 1])
expect do
@@ -186,8 +182,8 @@ RSpec.describe Backup::Files do
expect(subject.exclude_dirs(:tar)).to eq(['--exclude=lost+found', '--exclude=./@pages.tmp'])
end
- it 'prepends a leading slash to rsync excludes' do
- expect(subject.exclude_dirs(:rsync)).to eq(['--exclude=lost+found', '--exclude=/@pages.tmp'])
+ it 'prepends a leading slash and app_files_dir basename to rsync excludes' do
+ expect(subject.exclude_dirs(:rsync)).to eq(['--exclude=lost+found', '--exclude=/gitlab-pages/@pages.tmp'])
end
end
diff --git a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb
index 1f886059bf6..81aa8d35ebc 100644
--- a/spec/lib/banzai/filter/asset_proxy_filter_spec.rb
+++ b/spec/lib/banzai/filter/asset_proxy_filter_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do
stub_application_setting(asset_proxy_enabled: true)
stub_application_setting(asset_proxy_secret_key: 'shared-secret')
stub_application_setting(asset_proxy_url: 'https://assets.example.com')
- stub_application_setting(asset_proxy_whitelist: %w(gitlab.com *.mydomain.com))
+ stub_application_setting(asset_proxy_allowlist: %w(gitlab.com *.mydomain.com))
described_class.initialize_settings
@@ -39,16 +39,26 @@ RSpec.describe Banzai::Filter::AssetProxyFilter do
expect(Gitlab.config.asset_proxy.domain_regexp).to eq(/^(gitlab\.com|.*?\.mydomain\.com)$/i)
end
- context 'when whitelist is empty' do
+ context 'when allowlist is empty' do
it 'defaults to the install domain' do
stub_application_setting(asset_proxy_enabled: true)
- stub_application_setting(asset_proxy_whitelist: [])
+ stub_application_setting(asset_proxy_allowlist: [])
described_class.initialize_settings
expect(Gitlab.config.asset_proxy.allowlist).to eq [Gitlab.config.gitlab.host]
end
end
+
+ it 'supports deprecated whitelist settings' do
+ stub_application_setting(asset_proxy_enabled: true)
+ stub_application_setting(asset_proxy_whitelist: %w(foo.com bar.com))
+ stub_application_setting(asset_proxy_allowlist: [])
+
+ described_class.initialize_settings
+
+ expect(Gitlab.config.asset_proxy.allowlist).to eq %w(foo.com bar.com)
+ end
end
context 'when properly configured' do
diff --git a/spec/lib/banzai/filter/custom_emoji_filter_spec.rb b/spec/lib/banzai/filter/custom_emoji_filter_spec.rb
new file mode 100644
index 00000000000..ca8c9750e7f
--- /dev/null
+++ b/spec/lib/banzai/filter/custom_emoji_filter_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::CustomEmojiFilter do
+ include FilterSpecHelper
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:custom_emoji) { create(:custom_emoji, name: 'tanuki', group: group) }
+ let_it_be(:custom_emoji2) { create(:custom_emoji, name: 'happy_tanuki', group: group, file: 'https://foo.bar/happy.png') }
+
+ it 'replaces supported name custom emoji' do
+ doc = filter('<p>:tanuki:</p>', project: project)
+
+ expect(doc.css('gl-emoji').first.attributes['title'].value).to eq('tanuki')
+ expect(doc.css('gl-emoji img').size).to eq 1
+ end
+
+ it 'ignores non existent custom emoji' do
+ exp = act = '<p>:foo:</p>'
+ doc = filter(act)
+
+ expect(doc.to_html).to match Regexp.escape(exp)
+ end
+
+ it 'correctly uses the custom emoji URL' do
+ doc = filter('<p>:tanuki:</p>')
+
+ expect(doc.css('img').first.attributes['src'].value).to eq(custom_emoji.file)
+ end
+
+ it 'matches with adjacent text' do
+ doc = filter('tanuki (:tanuki:)')
+
+ expect(doc.css('img').size).to eq 1
+ end
+
+ it 'matches multiple same custom emoji' do
+ doc = filter(':tanuki: :tanuki:')
+
+ expect(doc.css('img').size).to eq 2
+ end
+
+ it 'matches multiple custom emoji' do
+ doc = filter(':tanuki: (:happy_tanuki:)')
+
+ expect(doc.css('img').size).to eq 2
+ end
+
+ it 'does not match enclosed colons' do
+ doc = filter('tanuki:tanuki:')
+
+ expect(doc.css('img').size).to be 0
+ end
+
+ it 'keeps whitespace intact' do
+ doc = filter('This deserves a :tanuki:, big time.')
+
+ expect(doc.to_html).to match(/^This deserves a <gl-emoji.+>, big time\.\z/)
+ end
+
+ it 'does not match emoji in a string' do
+ doc = filter("'2a00:tanuki:100::1'")
+
+ expect(doc.css('gl-emoji').size).to eq 0
+ end
+
+ it 'does not do N+1 query' do
+ create(:custom_emoji, name: 'party-parrot', group: group)
+
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ filter('<p>:tanuki:</p>')
+ end
+
+ expect do
+ filter('<p>:tanuki: :party-parrot:</p>')
+ end.not_to exceed_all_query_limit(control_count.count)
+ end
+end
diff --git a/spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb b/spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb
new file mode 100644
index 00000000000..2d7089853cf
--- /dev/null
+++ b/spec/lib/banzai/filter/feature_flag_reference_filter_spec.rb
@@ -0,0 +1,223 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::FeatureFlagReferenceFilter do
+ include FilterSpecHelper
+
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project) }
+ let_it_be(:reference) { feature_flag.to_reference }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Feature Flag #{reference}</#{elem}>"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with internal reference' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project, feature_flag)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Feature Flag (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
+ end
+
+ it 'ignores invalid feature flag IIDs' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("Feature Flag #{reference}")
+
+ expect(doc.css('a').first.attr('title')).to eq feature_flag.name
+ end
+
+ it 'escapes the title attribute' do
+ allow(feature_flag).to receive(:name).and_return(%{"></a>whatever<a title="})
+ doc = reference_filter("Feature Flag #{reference}")
+
+ expect(doc.text).to eq "Feature Flag #{reference}"
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Feature Flag #{reference}")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-feature_flag has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Feature Flag #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-feature-flag attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-feature-flag')
+ expect(link.attr('data-feature-flag')).to eq feature_flag.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Feature Flag #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.edit_project_feature_flag_url(project, feature_flag.iid, only_path: true)
+ end
+ end
+
+ context 'with cross-project / cross-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { "[feature_flag:#{project2.full_path}/#{feature_flag.iid}]" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'produces a valid text in a link' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql(reference)
+ end
+
+ it 'produces a valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{reference}.)")
+ end
+
+ it 'ignores invalid feature flag IIDs on the referenced project' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with cross-project / same-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { "[feature_flag:#{project2.full_path}/#{feature_flag.iid}]" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'produces a valid text in a link' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.css('a').first.text).to eql("[feature_flag:#{project2.path}/#{feature_flag.iid}]")
+ end
+
+ it 'produces a valid text' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.text).to eql("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+ end
+
+ it 'ignores invalid feature flag IIDs on the referenced project' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with cross-project shorthand reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { "[feature_flag:#{project2.path}/#{feature_flag.iid}]" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'produces a valid text in a link' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.css('a').first.text).to eql("[feature_flag:#{project2.path}/#{feature_flag.iid}]")
+ end
+
+ it 'produces a valid text' do
+ doc = reference_filter("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+
+ expect(doc.text).to eql("See ([feature_flag:#{project2.path}/#{feature_flag.iid}].)")
+ end
+
+ it 'ignores invalid feature flag IDs on the referenced project' do
+ exp = act = "Check [feature_flag:#{non_existing_record_id}]"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'with cross-project URL reference' do
+ let_it_be(:namespace) { create(:namespace, name: 'cross-reference') }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project2) }
+ let_it_be(:reference) { urls.edit_project_feature_flag_url(project2, feature_flag) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.edit_project_feature_flag_url(project2, feature_flag)
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(feature_flag.to_reference(project))}</a>\.\)})
+ end
+
+ it 'ignores invalid feature flag IIDs on the referenced project' do
+ act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
+ end
+ end
+
+ context 'with group context' do
+ let_it_be(:group) { create(:group) }
+
+ it 'links to a valid reference' do
+ reference = "[feature_flag:#{project.full_path}/#{feature_flag.iid}]"
+ result = reference_filter("See #{reference}", { project: nil, group: group } )
+
+ expect(result.css('a').first.attr('href')).to eq(urls.edit_project_feature_flag_url(project, feature_flag))
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See [feature_flag:#{feature_flag.iid}]"
+
+ expect(reference_filter(act, project: nil, group: group).to_html).to eq exp
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
index df78a3321ba..811c2aca342 100644
--- a/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/merge_request_reference_filter_spec.rb
@@ -216,7 +216,7 @@ RSpec.describe Banzai::Filter::MergeRequestReferenceFilter do
end
context 'URL reference for a commit' do
- let(:mr) { create(:merge_request, :with_diffs) }
+ let(:mr) { create(:merge_request) }
let(:reference) do
urls.project_merge_request_url(mr.project, mr) + "/diffs?commit_id=#{mr.diff_head_sha}"
end
diff --git a/spec/lib/banzai/filter/truncate_source_filter_spec.rb b/spec/lib/banzai/filter/truncate_source_filter_spec.rb
index b0c6d91daa8..d5eb8b738b1 100644
--- a/spec/lib/banzai/filter/truncate_source_filter_spec.rb
+++ b/spec/lib/banzai/filter/truncate_source_filter_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Banzai::Filter::TruncateSourceFilter do
it 'truncates UTF-8 text by bytes, on a character boundary' do
utf8_text = '日本語ã®æ–‡å­—ãŒå¤§ãã„'
- truncated = '日…'
+ truncated = 'æ—¥...'
expect(filter(utf8_text, limit: truncated.bytesize)).to eq(truncated)
expect(filter(utf8_text, limit: utf8_text.bytesize)).to eq(utf8_text)
diff --git a/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb b/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb
index 41a91c56f3b..ad4256c2045 100644
--- a/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb
@@ -3,11 +3,14 @@
require 'spec_helper'
RSpec.describe Banzai::Pipeline::BroadcastMessagePipeline do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
before do
stub_commonmark_sourcepos_disabled
end
- subject { described_class.to_html(exp, project: spy) }
+ subject { described_class.to_html(exp, project: project) }
context "allows `a` elements" do
let(:exp) { "<a>Link</a>" }
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index 9391ca386cf..bcee6f8f65d 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -131,4 +131,16 @@ RSpec.describe Banzai::Pipeline::FullPipeline do
expect(output).to include("test [[<em>TOC</em>]]")
end
end
+
+ describe 'backslash escapes' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ it 'does not convert an escaped reference' do
+ markdown = "\\#{issue.to_reference}"
+ output = described_class.to_html(markdown, project: project)
+
+ expect(output).to include("<span>#</span>#{issue.iid}")
+ end
+ end
end
diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
new file mode 100644
index 00000000000..241d6db4f11
--- /dev/null
+++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
+ using RSpec::Parameterized::TableSyntax
+
+ describe 'backslash escapes' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ def correct_html_included(markdown, expected)
+ result = described_class.call(markdown, {})
+
+ expect(result[:output].to_html).to include(expected)
+
+ result
+ end
+
+ context 'when feature flag honor_escaped_markdown is disabled' do
+ before do
+ stub_feature_flags(honor_escaped_markdown: false)
+ end
+
+ it 'does not escape the markdown' do
+ result = described_class.call(%q(\!), project: project)
+ output = result[:output].to_html
+
+ expect(output).to eq('<p data-sourcepos="1:1-1:2">!</p>')
+ expect(result[:escaped_literals]).to be_falsey
+ end
+ end
+
+ # Test strings taken from https://spec.commonmark.org/0.29/#backslash-escapes
+ describe 'CommonMark tests', :aggregate_failures do
+ it 'converts all ASCII punctuation to literals' do
+ markdown = %q(\!\"\#\$\%\&\'\*\+\,\-\.\/\:\;\<\=\>\?\@\[\]\^\_\`\{\|\}\~) + %q[\(\)\\\\]
+ punctuation = %w(! " # $ % &amp; ' * + , - . / : ; &lt; = &gt; ? @ [ \\ ] ^ _ ` { | } ~) + %w[( )]
+
+ result = described_class.call(markdown, project: project)
+ output = result[:output].to_html
+
+ punctuation.each { |char| expect(output).to include("<span>#{char}</span>") }
+ expect(result[:escaped_literals]).to be_truthy
+ end
+
+ it 'does not convert other characters to literals' do
+ markdown = %q(\→\A\a\ \3\φ\«)
+ expected = '\→\A\a\ \3\φ\«'
+
+ result = correct_html_included(markdown, expected)
+ expect(result[:escaped_literals]).to be_falsey
+ end
+
+ describe 'escaped characters are treated as regular characters and do not have their usual Markdown meanings' do
+ where(:markdown, :expected) do
+ %q(\*not emphasized*) | %q(<span>*</span>not emphasized*)
+ %q(\<br/> not a tag) | %q(<span>&lt;</span>br/&gt; not a tag)
+ %q!\[not a link](/foo)! | %q!<span>[</span>not a link](/foo)!
+ %q(\`not code`) | %q(<span>`</span>not code`)
+ %q(1\. not a list) | %q(1<span>.</span> not a list)
+ %q(\# not a heading) | %q(<span>#</span> not a heading)
+ %q(\[foo]: /url "not a reference") | %q(<span>[</span>foo]: /url "not a reference")
+ %q(\&ouml; not a character entity) | %q(<span>&amp;</span>ouml; not a character entity)
+ end
+
+ with_them do
+ it 'keeps them as literals' do
+ correct_html_included(markdown, expected)
+ end
+ end
+ end
+
+ it 'backslash is itself escaped, the following character is not' do
+ markdown = %q(\\\\*emphasis*)
+ expected = %q(<span>\</span><em>emphasis</em>)
+
+ correct_html_included(markdown, expected)
+ end
+
+ it 'backslash at the end of the line is a hard line break' do
+ markdown = <<~MARKDOWN
+ foo\\
+ bar
+ MARKDOWN
+ expected = "foo<br>\nbar"
+
+ correct_html_included(markdown, expected)
+ end
+
+ describe 'backslash escapes do not work in code blocks, code spans, autolinks, or raw HTML' do
+ where(:markdown, :expected) do
+ %q(`` \[\` ``) | %q(<code>\[\`</code>)
+ %q( \[\]) | %Q(<code>\\[\\]\n</code>)
+ %Q(~~~\n\\[\\]\n~~~) | %Q(<code>\\[\\]\n</code>)
+ %q(<http://example.com?find=\*>) | %q(<a href="http://example.com?find=%5C*">http://example.com?find=\*</a>)
+ %q[<a href="/bar\/)">] | %q[<a href="/bar%5C/)">]
+ end
+
+ with_them do
+ it { correct_html_included(markdown, expected) }
+ end
+ end
+
+ describe 'work in all other contexts, including URLs and link titles, link references, and info strings in fenced code blocks' do
+ where(:markdown, :expected) do
+ %q![foo](/bar\* "ti\*tle")! | %q(<a href="/bar*" title="ti*tle">foo</a>)
+ %Q![foo]\n\n[foo]: /bar\\* "ti\\*tle"! | %q(<a href="/bar*" title="ti*tle">foo</a>)
+ %Q(``` foo\\+bar\nfoo\n```) | %Q(<code lang="foo+bar">foo\n</code>)
+ end
+
+ with_them do
+ it { correct_html_included(markdown, expected) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
index f0498f41b61..c628d8d5b41 100644
--- a/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/pre_process_pipeline_spec.rb
@@ -30,6 +30,6 @@ RSpec.describe Banzai::Pipeline::PreProcessPipeline do
result = described_class.call(text, limit: 12)
- expect(result[:output]).to eq('foo foo f…')
+ expect(result[:output]).to eq('foo foo f...')
end
end
diff --git a/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb b/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb
new file mode 100644
index 00000000000..288eb9ae360
--- /dev/null
+++ b/spec/lib/banzai/reference_parser/feature_flag_parser_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::ReferenceParser::FeatureFlagParser do
+ include ReferenceParserHelpers
+
+ subject { described_class.new(Banzai::RenderContext.new(project, user)) }
+
+ let(:link) { empty_html_link }
+
+ describe '#nodes_visible_to_user' do
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+ let(:feature_flag) { create(:operations_feature_flag, project: project) }
+
+ context 'when the link has a data-issue attribute' do
+ before do
+ link['data-feature-flag'] = feature_flag.id.to_s
+ end
+
+ it_behaves_like "referenced feature visibility", "issues", "merge_requests" do
+ before do
+ project.add_developer(user) if enable_user?
+ end
+ end
+ end
+ end
+
+ describe '#referenced_by' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:feature_flag) { create(:operations_feature_flag, project: project) }
+
+ describe 'when the link has a data-feature-flag attribute' do
+ context 'using an existing feature flag ID' do
+ it 'returns an Array of feature flags' do
+ link['data-feature-flag'] = feature_flag.id.to_s
+
+ expect(subject.referenced_by([link])).to eq([feature_flag])
+ end
+ end
+
+ context 'using a non-existing feature flag ID' do
+ it 'returns an empty Array' do
+ link['data-feature-flag'] = ''
+
+ expect(subject.referenced_by([link])).to eq([])
+ end
+ end
+ end
+ end
+end
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 2abd3df20fd..80607485b6e 100644
--- a/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
+++ b/spec/lib/bulk_imports/common/extractors/graphql_extractor_spec.rb
@@ -5,8 +5,18 @@ require 'spec_helper'
RSpec.describe BulkImports::Common::Extractors::GraphqlExtractor do
let(:graphql_client) { instance_double(BulkImports::Clients::Graphql) }
let(:import_entity) { create(:bulk_import_entity) }
- let(:response) { double(original_hash: { foo: :bar }) }
- let(:query) { { query: double(to_s: 'test', variables: {}) } }
+ 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]
+ )
+ }
+ end
+
let(:context) do
instance_double(
BulkImports::Pipeline::Context,
@@ -14,58 +24,20 @@ RSpec.describe BulkImports::Common::Extractors::GraphqlExtractor do
)
end
- subject { described_class.new(query) }
-
- before do
- allow(subject).to receive(:graphql_client).and_return(graphql_client)
- allow(graphql_client).to receive(:parse)
- end
+ subject { described_class.new(options) }
describe '#extract' do
before do
- allow(subject).to receive(:query_variables).and_return({})
- allow(graphql_client).to receive(:execute).and_return(response)
- end
-
- it 'returns original hash' do
- expect(subject.extract(context)).to eq({ foo: :bar })
- end
- end
-
- describe 'query variables' do
- before do
+ allow(subject).to receive(:graphql_client).and_return(graphql_client)
+ allow(graphql_client).to receive(:parse)
allow(graphql_client).to receive(:execute).and_return(response)
end
- context 'when variables are present' do
- let(:variables) { { foo: :bar } }
- let(:query) { { query: double(to_s: 'test', variables: variables) } }
-
- it 'builds graphql query variables for import entity' do
- expect(graphql_client).to receive(:execute).with(anything, variables)
-
- subject.extract(context).first
- end
- end
-
- context 'when no variables are present' do
- let(:query) { { query: double(to_s: 'test', variables: nil) } }
-
- it 'returns empty hash' do
- expect(graphql_client).to receive(:execute).with(anything, nil)
-
- subject.extract(context).first
- end
- end
-
- context 'when variables are empty hash' do
- let(:query) { { query: double(to_s: 'test', variables: {}) } }
-
- it 'makes graphql request with empty hash' do
- expect(graphql_client).to receive(:execute).with(anything, {})
+ it 'returns ExtractedData' do
+ extracted_data = subject.extract(context)
- subject.extract(context).first
- end
+ expect(extracted_data).to be_instance_of(BulkImports::Pipeline::ExtractedData)
+ expect(extracted_data.data).to contain_exactly('bar')
end
end
end
diff --git a/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb b/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb
index 4de7d95172f..57ffdfa9aee 100644
--- a/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb
+++ b/spec/lib/bulk_imports/common/loaders/entity_loader_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe BulkImports::Common::Loaders::EntityLoader do
it "creates entities for the given data" do
group = create(:group, path: "imported-group")
parent_entity = create(:bulk_import_entity, group: group, bulk_import: create(:bulk_import))
- context = instance_double(BulkImports::Pipeline::Context, entity: parent_entity)
+ context = BulkImports::Pipeline::Context.new(parent_entity)
data = {
source_type: :group_entity,
diff --git a/spec/lib/bulk_imports/common/transformers/award_emoji_transformer_spec.rb b/spec/lib/bulk_imports/common/transformers/award_emoji_transformer_spec.rb
new file mode 100644
index 00000000000..5b560a30bf5
--- /dev/null
+++ b/spec/lib/bulk_imports/common/transformers/award_emoji_transformer_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Transformers::AwardEmojiTransformer do
+ describe '#transform' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:bulk_import) { create(:bulk_import) }
+ let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import, group: group) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ let(:hash) do
+ {
+ 'name' => 'thumbs up',
+ 'user' => {
+ 'public_email' => email
+ }
+ }
+ end
+
+ before do
+ group.add_developer(user)
+ end
+
+ shared_examples 'sets user_id and removes user key' do
+ it 'sets found user_id and removes user key' do
+ transformed_hash = subject.transform(context, hash)
+
+ expect(transformed_hash['user']).to be_nil
+ expect(transformed_hash['user_id']).to eq(user.id)
+ end
+ end
+
+ context 'when user can be found by email' do
+ let(:email) { user.email }
+
+ include_examples 'sets user_id and removes user key'
+ end
+
+ context 'when user cannot be found by email' do
+ let(:user) { bulk_import.user }
+ let(:email) { nil }
+
+ include_examples 'sets user_id and removes user key'
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/transformers/hash_key_digger_spec.rb b/spec/lib/bulk_imports/common/transformers/hash_key_digger_spec.rb
deleted file mode 100644
index 2b33701653e..00000000000
--- a/spec/lib/bulk_imports/common/transformers/hash_key_digger_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Common::Transformers::HashKeyDigger do
- describe '#transform' do
- it 'when the key_path is an array' do
- data = { foo: { bar: :value } }
- key_path = %i[foo bar]
- transformed = described_class.new(key_path: key_path).transform(nil, data)
-
- expect(transformed).to eq(:value)
- end
-
- it 'when the key_path is not an array' do
- data = { foo: { bar: :value } }
- key_path = :foo
- transformed = described_class.new(key_path: key_path).transform(nil, data)
-
- expect(transformed).to eq({ bar: :value })
- end
-
- it "when the data is not a hash" do
- expect { described_class.new(key_path: nil).transform(nil, nil) }
- .to raise_error(ArgumentError, "Given data must be a Hash")
- end
- end
-end
diff --git a/spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb b/spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb
deleted file mode 100644
index cdffa750694..00000000000
--- a/spec/lib/bulk_imports/common/transformers/underscorify_keys_transformer_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Common::Transformers::UnderscorifyKeysTransformer do
- describe '#transform' do
- it 'deep underscorifies hash keys' do
- data = {
- 'fullPath' => 'Foo',
- 'snakeKeys' => {
- 'snakeCaseKey' => 'Bar',
- 'moreKeys' => {
- 'anotherSnakeCaseKey' => 'Test'
- }
- }
- }
-
- transformed_data = described_class.new.transform(nil, data)
-
- expect(transformed_data).to have_key('full_path')
- expect(transformed_data).to have_key('snake_keys')
- expect(transformed_data['snake_keys']).to have_key('snake_case_key')
- expect(transformed_data['snake_keys']).to have_key('more_keys')
- expect(transformed_data.dig('snake_keys', 'more_keys')).to have_key('another_snake_case_key')
- end
- end
-end
diff --git a/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb b/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
new file mode 100644
index 00000000000..627247c04ab
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/extractors/subgroups_extractor_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Extractors::SubgroupsExtractor do
+ describe '#extract' do
+ it 'returns ExtractedData response' do
+ bulk_import = create(:bulk_import)
+ create(:bulk_import_configuration, bulk_import: bulk_import)
+ entity = create(:bulk_import_entity, bulk_import: bulk_import)
+ response = [{ 'test' => 'group' }]
+ context = BulkImports::Pipeline::Context.new(entity)
+
+ allow_next_instance_of(BulkImports::Clients::Http) do |client|
+ allow(client).to receive(:each_page).and_return(response)
+ end
+
+ extracted_data = subject.extract(context)
+
+ expect(extracted_data).to be_instance_of(BulkImports::Pipeline::ExtractedData)
+ expect(extracted_data.data).to eq(response)
+ end
+ 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
new file mode 100644
index 00000000000..ef46da7062b
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/graphql/get_group_query_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Graphql::GetGroupQuery do
+ describe '#variables' do
+ let(:entity) { double(source_full_path: 'test', bulk_import: nil) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ it 'returns query variables based on entity information' do
+ expected = { full_path: entity.source_full_path }
+
+ expect(described_class.variables(context)).to eq(expected)
+ end
+ end
+
+ describe '#data_path' do
+ it 'returns data path' do
+ expected = %w[data group]
+
+ 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 page_info]
+
+ expect(described_class.page_info_path).to eq(expected)
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
new file mode 100644
index 00000000000..247da200d68
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/graphql/get_labels_query_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Graphql::GetLabelsQuery do
+ describe '#variables' do
+ let(:entity) { double(source_full_path: 'test', next_page_for: 'next_page', bulk_import: nil) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ it 'returns query variables based on entity information' do
+ expected = { full_path: entity.source_full_path, cursor: entity.next_page_for }
+
+ expect(described_class.variables(context)).to eq(expected)
+ end
+ end
+
+ describe '#data_path' do
+ it 'returns data path' do
+ expected = %w[data group labels nodes]
+
+ expect(described_class.data_path).to eq(expected)
+ end
+ end
+
+ describe '#page_info_path' do
+ it 'returns pagination information path' do
+ expected = %w[data group labels page_info]
+
+ expect(described_class.page_info_path).to eq(expected)
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb b/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
new file mode 100644
index 00000000000..5d05f5a2d30
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/graphql/get_members_query_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Graphql::GetMembersQuery do
+ it 'has a valid query' do
+ entity = create(:bulk_import_entity)
+ context = BulkImports::Pipeline::Context.new(entity)
+
+ 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/loaders/group_loader_spec.rb b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
index b14dfc615a9..183292722d2 100644
--- a/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
+++ b/spec/lib/bulk_imports/groups/loaders/group_loader_spec.rb
@@ -7,21 +7,20 @@ RSpec.describe BulkImports::Groups::Loaders::GroupLoader do
let(:user) { create(:user) }
let(:data) { { foo: :bar } }
let(:service_double) { instance_double(::Groups::CreateService) }
- let(:entity) { create(:bulk_import_entity) }
- let(:context) do
- instance_double(
- BulkImports::Pipeline::Context,
- entity: entity,
- current_user: user
- )
- end
+ let(:bulk_import) { create(:bulk_import, user: user) }
+ let(:entity) { create(:bulk_import_entity, bulk_import: bulk_import) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
subject { described_class.new }
context 'when user can create group' do
shared_examples 'calls Group Create Service to create a new group' do
it 'calls Group Create Service to create a new group' do
- expect(::Groups::CreateService).to receive(:new).with(context.current_user, data).and_return(service_double)
+ expect(::Groups::CreateService)
+ .to receive(:new)
+ .with(context.current_user, data)
+ .and_return(service_double)
+
expect(service_double).to receive(:execute)
expect(entity).to receive(:update!)
diff --git a/spec/lib/bulk_imports/groups/loaders/labels_loader_spec.rb b/spec/lib/bulk_imports/groups/loaders/labels_loader_spec.rb
new file mode 100644
index 00000000000..ac2f9c8cb1d
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/loaders/labels_loader_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Loaders::LabelsLoader do
+ describe '#load' do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:entity) { create(:bulk_import_entity, group: group) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ let(:data) do
+ {
+ 'title' => 'label',
+ 'description' => 'description',
+ 'color' => '#FFFFFF'
+ }
+ end
+
+ it 'creates the label' do
+ expect { subject.load(context, data) }.to change(Label, :count).by(1)
+
+ label = group.labels.first
+
+ expect(label.title).to eq(data['title'])
+ expect(label.description).to eq(data['description'])
+ expect(label.color).to eq(data['color'])
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/loaders/members_loader_spec.rb b/spec/lib/bulk_imports/groups/loaders/members_loader_spec.rb
new file mode 100644
index 00000000000..d552578e7be
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/loaders/members_loader_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Loaders::MembersLoader do
+ describe '#load' do
+ let_it_be(:user_importer) { create(:user) }
+ let_it_be(:user_member) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user_importer) }
+ let_it_be(:entity) { create(:bulk_import_entity, bulk_import: bulk_import, group: group) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ let_it_be(:data) do
+ {
+ 'user_id' => user_member.id,
+ 'created_by_id' => user_importer.id,
+ 'access_level' => 30,
+ 'created_at' => '2020-01-01T00:00:00Z',
+ 'updated_at' => '2020-01-01T00:00:00Z',
+ 'expires_at' => nil
+ }
+ end
+
+ 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
+ expect { subject.load(context, data) }.to change(GroupMember, :count).by(1)
+
+ member = group.members.last
+
+ expect(member.user).to eq(user_member)
+ expect(member.created_by).to eq(user_importer)
+ 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
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
index 1a91f3d7a78..61950cdd9b0 100644
--- a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb
@@ -6,41 +6,34 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
describe '#run' do
let(:user) { create(:user) }
let(:parent) { create(:group) }
+ let(:bulk_import) { create(:bulk_import, user: user) }
let(:entity) do
create(
:bulk_import_entity,
+ bulk_import: bulk_import,
source_full_path: 'source/full/path',
destination_name: 'My Destination Group',
destination_namespace: parent.full_path
)
end
- let(:context) do
- BulkImports::Pipeline::Context.new(
- current_user: user,
- entity: entity
- )
- end
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
let(:group_data) do
{
- 'data' => {
- 'group' => {
- 'name' => 'source_name',
- 'fullPath' => 'source/full/path',
- 'visibility' => 'private',
- 'projectCreationLevel' => 'developer',
- 'subgroupCreationLevel' => 'maintainer',
- 'description' => 'Group Description',
- 'emailsDisabled' => true,
- 'lfsEnabled' => false,
- 'mentionsDisabled' => true
- }
- }
+ 'name' => 'source_name',
+ 'full_path' => 'source/full/path',
+ 'visibility' => 'private',
+ 'project_creation_level' => 'developer',
+ 'subgroup_creation_level' => 'maintainer',
+ 'description' => 'Group Description',
+ 'emails_disabled' => true,
+ 'lfs_enabled' => false,
+ 'mentions_disabled' => true
}
end
- subject { described_class.new }
+ subject { described_class.new(context) }
before do
allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
@@ -53,20 +46,20 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
it 'imports new group into destination group' do
group_path = 'my-destination-group'
- subject.run(context)
+ subject.run
imported_group = Group.find_by_path(group_path)
expect(imported_group).not_to be_nil
expect(imported_group.parent).to eq(parent)
expect(imported_group.path).to eq(group_path)
- expect(imported_group.description).to eq(group_data.dig('data', 'group', 'description'))
- expect(imported_group.visibility).to eq(group_data.dig('data', 'group', 'visibility'))
- expect(imported_group.project_creation_level).to eq(Gitlab::Access.project_creation_string_options[group_data.dig('data', 'group', 'projectCreationLevel')])
- expect(imported_group.subgroup_creation_level).to eq(Gitlab::Access.subgroup_creation_string_options[group_data.dig('data', 'group', 'subgroupCreationLevel')])
- expect(imported_group.lfs_enabled?).to eq(group_data.dig('data', 'group', 'lfsEnabled'))
- expect(imported_group.emails_disabled?).to eq(group_data.dig('data', 'group', 'emailsDisabled'))
- expect(imported_group.mentions_disabled?).to eq(group_data.dig('data', 'group', 'mentionsDisabled'))
+ expect(imported_group.description).to eq(group_data['description'])
+ expect(imported_group.visibility).to eq(group_data['visibility'])
+ expect(imported_group.project_creation_level).to eq(Gitlab::Access.project_creation_string_options[group_data['project_creation_level']])
+ expect(imported_group.subgroup_creation_level).to eq(Gitlab::Access.subgroup_creation_string_options[group_data['subgroup_creation_level']])
+ expect(imported_group.lfs_enabled?).to eq(group_data['lfs_enabled'])
+ expect(imported_group.emails_disabled?).to eq(group_data['emails_disabled'])
+ expect(imported_group.mentions_disabled?).to eq(group_data['mentions_disabled'])
end
end
@@ -87,8 +80,6 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do
it 'has transformers' do
expect(described_class.transformers)
.to contain_exactly(
- { klass: BulkImports::Common::Transformers::HashKeyDigger, options: { key_path: %w[data group] } },
- { klass: BulkImports::Common::Transformers::UnderscorifyKeysTransformer, options: nil },
{ klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil },
{ klass: BulkImports::Groups::Transformers::GroupAttributesTransformer, options: nil }
)
diff --git a/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
new file mode 100644
index 00000000000..63f28916d9a
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/labels_pipeline_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Pipelines::LabelsPipeline do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:cursor) { 'cursor' }
+ let(:entity) do
+ create(
+ :bulk_import_entity,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Group',
+ destination_namespace: group.full_path,
+ group: group
+ )
+ end
+
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ subject { described_class.new(context) }
+
+ def extractor_data(title:, has_next_page:, cursor: nil)
+ data = [
+ {
+ 'title' => title,
+ 'description' => 'desc',
+ 'color' => '#428BCA'
+ }
+ ]
+
+ page_info = {
+ 'end_cursor' => cursor,
+ 'has_next_page' => has_next_page
+ }
+
+ BulkImports::Pipeline::ExtractedData.new(data: data, page_info: page_info)
+ end
+
+ describe '#run' do
+ it 'imports a group labels' do
+ first_page = extractor_data(title: 'label1', has_next_page: true, cursor: cursor)
+ last_page = extractor_data(title: 'label2', has_next_page: false)
+
+ 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(Label, :count).by(2)
+
+ label = group.labels.order(:created_at).last
+
+ expect(label.title).to eq('label2')
+ expect(label.description).to eq('desc')
+ expect(label.color).to eq('#428BCA')
+ end
+ end
+
+ describe '#after_run' do
+ context 'when extracted data has next page' do
+ it 'updates tracker information and runs pipeline again' do
+ data = extractor_data(title: 'label', has_next_page: true, cursor: cursor)
+
+ expect(subject).to receive(:run)
+
+ subject.after_run(data)
+
+ tracker = entity.trackers.find_by(relation: :labels)
+
+ expect(tracker.has_next_page).to eq(true)
+ expect(tracker.next_page).to eq(cursor)
+ end
+ end
+
+ context 'when extracted data has no next page' do
+ it 'updates tracker information and does not run pipeline' do
+ data = extractor_data(title: 'label', has_next_page: false)
+
+ expect(subject).not_to receive(:run)
+
+ subject.after_run(data)
+
+ tracker = entity.trackers.find_by(relation: :labels)
+
+ expect(tracker.has_next_page).to eq(false)
+ expect(tracker.next_page).to be_nil
+ end
+ end
+ end
+
+ describe 'pipeline parts' do
+ it { expect(described_class).to include_module(BulkImports::Pipeline) }
+ it { expect(described_class).to include_module(BulkImports::Pipeline::Runner) }
+
+ it 'has extractors' do
+ expect(described_class.get_extractor)
+ .to eq(
+ klass: BulkImports::Common::Extractors::GraphqlExtractor,
+ options: {
+ query: BulkImports::Groups::Graphql::GetLabelsQuery
+ }
+ )
+ end
+
+ it 'has transformers' do
+ expect(described_class.transformers)
+ .to contain_exactly(
+ { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }
+ )
+ end
+
+ it 'has loaders' do
+ expect(described_class.get_loader).to eq(klass: BulkImports::Groups::Loaders::LabelsLoader, options: nil)
+ 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
new file mode 100644
index 00000000000..9f498f8154f
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/pipelines/members_pipeline_spec.rb
@@ -0,0 +1,87 @@
+# 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(:cursor) { 'cursor' }
+ 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(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ subject { described_class.new(context) }
+
+ describe '#run' do
+ it 'maps existing users to the imported group' do
+ first_page = member_data(email: member_user1.email, has_next_page: true, cursor: cursor)
+ last_page = member_data(email: member_user2.email, has_next_page: false)
+
+ 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 '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
+
+ it 'has loaders' do
+ expect(described_class.get_loader).to eq(klass: BulkImports::Groups::Loaders::MembersLoader, options: nil)
+ end
+ end
+
+ def member_data(email:, has_next_page:, cursor: nil)
+ 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 = {
+ 'end_cursor' => cursor,
+ 'has_next_page' => has_next_page
+ }
+
+ BulkImports::Pipeline::ExtractedData.new(data: data, page_info: page_info)
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
index e5a8ed7f47d..0404c52b895 100644
--- a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb
@@ -14,13 +14,7 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
)
end
- let(:context) do
- instance_double(
- BulkImports::Pipeline::Context,
- current_user: user,
- entity: parent_entity
- )
- end
+ let(:context) { BulkImports::Pipeline::Context.new(parent_entity) }
let(:subgroup_data) do
[
@@ -31,7 +25,7 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
]
end
- subject { described_class.new }
+ subject { described_class.new(context) }
before do
allow_next_instance_of(BulkImports::Groups::Extractors::SubgroupsExtractor) do |extractor|
@@ -42,7 +36,7 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do
end
it 'creates entities for the subgroups' do
- expect { subject.run(context) }.to change(BulkImports::Entity, :count).by(1)
+ expect { subject.run }.to change(BulkImports::Entity, :count).by(1)
subgroup_entity = BulkImports::Entity.last
diff --git a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
index 28a7859915d..5a7a51675d6 100644
--- a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
@@ -7,22 +7,18 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
let(:user) { create(:user) }
let(:parent) { create(:group) }
let(:group) { create(:group, name: 'My Source Group', parent: parent) }
+ let(:bulk_import) { create(:bulk_import, user: user) }
let(:entity) do
- instance_double(
- BulkImports::Entity,
+ create(
+ :bulk_import_entity,
+ bulk_import: bulk_import,
source_full_path: 'source/full/path',
destination_name: group.name,
destination_namespace: parent.full_path
)
end
- let(:context) do
- instance_double(
- BulkImports::Pipeline::Context,
- current_user: user,
- entity: entity
- )
- end
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
let(:data) do
{
@@ -85,16 +81,16 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
end
context 'when destination namespace is user namespace' do
- let(:entity) do
- instance_double(
- BulkImports::Entity,
+ it 'does not set parent id' do
+ entity = create(
+ :bulk_import_entity,
+ bulk_import: bulk_import,
source_full_path: 'source/full/path',
destination_name: group.name,
destination_namespace: user.namespace.full_path
)
- end
+ context = BulkImports::Pipeline::Context.new(entity)
- it 'does not set parent id' do
transformed_data = subject.transform(context, data)
expect(transformed_data).not_to have_key('parent_id')
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
new file mode 100644
index 00000000000..f66c67fc6a2
--- /dev/null
+++ b/spec/lib/bulk_imports/groups/transformers/member_attributes_transformer_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Groups::Transformers::MemberAttributesTransformer do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:secondary_email) { 'secondary@email.com' }
+ 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(:context) { BulkImports::Pipeline::Context.new(entity) }
+
+ it 'returns nil when receives no data' do
+ expect(subject.transform(context, nil)).to eq(nil)
+ end
+
+ it 'returns nil when no user is found' do
+ expect(subject.transform(context, member_data)).to eq(nil)
+ expect(subject.transform(context, member_data(email: 'inexistent@email.com'))).to eq(nil)
+ end
+
+ context 'when the user is not confirmed' do
+ before do
+ user.update!(confirmed_at: nil)
+ end
+
+ it 'returns nil even when the primary email match' do
+ data = member_data(email: user.email)
+
+ expect(subject.transform(context, data)).to eq(nil)
+ end
+
+ it 'returns nil even when a secondary email match' do
+ user.emails << Email.new(email: secondary_email)
+ data = member_data(email: secondary_email)
+
+ expect(subject.transform(context, data)).to eq(nil)
+ end
+ end
+
+ context 'when the user is confirmed' do
+ before do
+ user.update!(confirmed_at: Time.now.utc)
+ end
+
+ it 'finds the user by the primary email' 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
+ )
+ end
+
+ it 'finds the user by the secondary email' do
+ user.emails << Email.new(email: secondary_email, confirmed_at: Time.now.utc)
+ 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
+ )
+ end
+
+ context 'format access level' do
+ it 'ignores record if no access level is given' do
+ data = member_data(email: user.email, access_level: nil)
+
+ expect(subject.transform(context, data)).to be_nil
+ end
+
+ it 'ignores record if is not a valid access level' do
+ data = member_data(email: user.email, access_level: 999)
+
+ expect(subject.transform(context, data)).to be_nil
+ end
+ end
+ end
+
+ def member_data(email: '', access_level: 30)
+ {
+ 'created_at' => '2020-01-01T00:00:00Z',
+ 'updated_at' => '2020-01-01T00:00:00Z',
+ 'expires_at' => nil,
+ 'access_level' => {
+ 'integer_value' => access_level
+ },
+ 'user' => {
+ 'public_email' => email
+ }
+ }
+ end
+end
diff --git a/spec/lib/bulk_imports/importers/group_importer_spec.rb b/spec/lib/bulk_imports/importers/group_importer_spec.rb
index 87baf1b8026..b4fdb7b5e5b 100644
--- a/spec/lib/bulk_imports/importers/group_importer_spec.rb
+++ b/spec/lib/bulk_imports/importers/group_importer_spec.rb
@@ -4,28 +4,29 @@ require 'spec_helper'
RSpec.describe BulkImports::Importers::GroupImporter do
let(:user) { create(:user) }
+ let(:group) { create(:group) }
let(:bulk_import) { create(:bulk_import) }
- let(:bulk_import_entity) { create(:bulk_import_entity, :started, bulk_import: bulk_import) }
+ let(:bulk_import_entity) { create(:bulk_import_entity, :started, bulk_import: bulk_import, group: group) }
let(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
- let(:context) do
- BulkImports::Pipeline::Context.new(
- current_user: user,
- entity: bulk_import_entity,
- configuration: bulk_import_configuration
- )
- end
-
- subject { described_class.new(bulk_import_entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(bulk_import_entity) }
before do
allow(BulkImports::Pipeline::Context).to receive(:new).and_return(context)
end
+ subject { described_class.new(bulk_import_entity) }
+
describe '#execute' do
it 'starts the entity and run its pipelines' do
expect_to_run_pipeline BulkImports::Groups::Pipelines::GroupPipeline, context: context
- expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicsPipeline'.constantize, context: context) if Gitlab.ee?
expect_to_run_pipeline BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline, context: context
+ expect_to_run_pipeline BulkImports::Groups::Pipelines::MembersPipeline, context: context
+ expect_to_run_pipeline BulkImports::Groups::Pipelines::LabelsPipeline, context: context
+
+ if Gitlab.ee?
+ expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicsPipeline'.constantize, context: context)
+ expect_to_run_pipeline('EE::BulkImports::Groups::Pipelines::EpicAwardEmojiPipeline'.constantize, context: context)
+ end
subject.execute
@@ -33,7 +34,7 @@ RSpec.describe BulkImports::Importers::GroupImporter do
end
context 'when failed' do
- let(:bulk_import_entity) { create(:bulk_import_entity, :failed, bulk_import: bulk_import) }
+ let(:bulk_import_entity) { create(:bulk_import_entity, :failed, bulk_import: bulk_import, group: group) }
it 'does not transition entity to finished state' do
allow(bulk_import_entity).to receive(:start!)
@@ -46,8 +47,8 @@ RSpec.describe BulkImports::Importers::GroupImporter do
end
def expect_to_run_pipeline(klass, context:)
- expect_next_instance_of(klass) do |pipeline|
- expect(pipeline).to receive(:run).with(context)
+ expect_next_instance_of(klass, context) do |pipeline|
+ expect(pipeline).to receive(:run)
end
end
end
diff --git a/spec/lib/bulk_imports/pipeline/context_spec.rb b/spec/lib/bulk_imports/pipeline/context_spec.rb
index e9af6313ca4..c8c3fe3a861 100644
--- a/spec/lib/bulk_imports/pipeline/context_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/context_spec.rb
@@ -3,25 +3,29 @@
require 'spec_helper'
RSpec.describe BulkImports::Pipeline::Context do
- describe '#initialize' do
- it 'initializes with permitted attributes' do
- args = {
- current_user: create(:user),
- entity: create(:bulk_import_entity),
- configuration: create(:bulk_import_configuration)
- }
+ let(:group) { instance_double(Group) }
+ let(:user) { instance_double(User) }
+ let(:bulk_import) { instance_double(BulkImport, user: user, configuration: :config) }
- context = described_class.new(args)
+ let(:entity) do
+ instance_double(
+ BulkImports::Entity,
+ bulk_import: bulk_import,
+ group: group
+ )
+ end
+
+ subject { described_class.new(entity) }
- args.each do |k, v|
- expect(context.public_send(k)).to eq(v)
- end
- end
+ describe '#group' do
+ it { expect(subject.group).to eq(group) }
+ end
+
+ describe '#current_user' do
+ it { expect(subject.current_user).to eq(user) }
+ end
- context 'when invalid argument is passed' do
- it 'raises NoMethodError' do
- expect { described_class.new(test: 'test').test }.to raise_exception(NoMethodError)
- end
- end
+ describe '#current_user' do
+ it { expect(subject.configuration).to eq(bulk_import.configuration) }
end
end
diff --git a/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb b/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb
new file mode 100644
index 00000000000..25c5178227a
--- /dev/null
+++ b/spec/lib/bulk_imports/pipeline/extracted_data_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Pipeline::ExtractedData do
+ let(:data) { 'data' }
+ let(:has_next_page) { true }
+ let(:cursor) { 'cursor' }
+ let(:page_info) do
+ {
+ 'has_next_page' => has_next_page,
+ 'end_cursor' => cursor
+ }
+ end
+
+ subject { described_class.new(data: data, page_info: page_info) }
+
+ describe '#has_next_page?' do
+ context 'when next page is present' do
+ it 'returns true' do
+ expect(subject.has_next_page?).to eq(true)
+ end
+ end
+
+ context 'when next page is not present' do
+ let(:has_next_page) { false }
+
+ it 'returns false' do
+ expect(subject.has_next_page?).to eq(false)
+ end
+ end
+ end
+
+ describe '#next_page' do
+ it 'returns next page cursor information' do
+ expect(subject.next_page).to eq(cursor)
+ end
+ end
+
+ describe '#each' do
+ context 'when block is present' do
+ it 'yields each data item' do
+ expect { |b| subject.each(&b) }.to yield_control
+ end
+ end
+
+ context 'when block is not present' do
+ it 'returns enumerator' do
+ expect(subject.each).to be_instance_of(Enumerator)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/pipeline/runner_spec.rb b/spec/lib/bulk_imports/pipeline/runner_spec.rb
index 60833e83dcc..76e4e64a7d6 100644
--- a/spec/lib/bulk_imports/pipeline/runner_spec.rb
+++ b/spec/lib/bulk_imports/pipeline/runner_spec.rb
@@ -39,56 +39,94 @@ RSpec.describe BulkImports::Pipeline::Runner do
extractor BulkImports::Extractor
transformer BulkImports::Transformer
loader BulkImports::Loader
+
+ def after_run(_); end
end
stub_const('BulkImports::MyPipeline', pipeline)
end
context 'when entity is not marked as failed' do
- let(:context) do
- instance_double(
- BulkImports::Pipeline::Context,
- entity: instance_double(BulkImports::Entity, id: 1, source_type: 'group', failed?: false)
- )
- end
+ let(:entity) { create(:bulk_import_entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
it 'runs pipeline extractor, transformer, loader' do
- entries = [{ foo: :bar }]
+ extracted_data = BulkImports::Pipeline::ExtractedData.new(data: { foo: :bar })
expect_next_instance_of(BulkImports::Extractor) do |extractor|
- expect(extractor).to receive(:extract).with(context).and_return(entries)
+ expect(extractor)
+ .to receive(:extract)
+ .with(context)
+ .and_return(extracted_data)
end
expect_next_instance_of(BulkImports::Transformer) do |transformer|
- expect(transformer).to receive(:transform).with(context, entries.first).and_return(entries.first)
+ expect(transformer)
+ .to receive(:transform)
+ .with(context, extracted_data.data.first)
+ .and_return(extracted_data.data.first)
end
expect_next_instance_of(BulkImports::Loader) do |loader|
- expect(loader).to receive(:load).with(context, entries.first)
+ expect(loader)
+ .to receive(:load)
+ .with(context, extracted_data.data.first)
end
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger).to receive(:info)
.with(
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity',
message: 'Pipeline started',
+ pipeline_class: 'BulkImports::MyPipeline'
+ )
+ expect(logger).to receive(:info)
+ .with(
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity',
pipeline_class: 'BulkImports::MyPipeline',
- bulk_import_entity_id: 1,
- bulk_import_entity_type: 'group'
+ pipeline_step: :extractor,
+ step_class: 'BulkImports::Extractor'
)
expect(logger).to receive(:info)
- .with(bulk_import_entity_id: 1, bulk_import_entity_type: 'group', extractor: 'BulkImports::Extractor')
+ .with(
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity',
+ pipeline_class: 'BulkImports::MyPipeline',
+ pipeline_step: :transformer,
+ step_class: 'BulkImports::Transformer'
+ )
expect(logger).to receive(:info)
- .with(bulk_import_entity_id: 1, bulk_import_entity_type: 'group', transformer: 'BulkImports::Transformer')
+ .with(
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity',
+ pipeline_class: 'BulkImports::MyPipeline',
+ pipeline_step: :loader,
+ step_class: 'BulkImports::Loader'
+ )
+ expect(logger).to receive(:info)
+ .with(
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity',
+ pipeline_class: 'BulkImports::MyPipeline',
+ pipeline_step: :after_run
+ )
expect(logger).to receive(:info)
- .with(bulk_import_entity_id: 1, bulk_import_entity_type: 'group', loader: 'BulkImports::Loader')
+ .with(
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity',
+ message: 'Pipeline finished',
+ pipeline_class: 'BulkImports::MyPipeline'
+ )
end
- BulkImports::MyPipeline.new.run(context)
+ BulkImports::MyPipeline.new(context).run
end
context 'when exception is raised' do
let(:entity) { create(:bulk_import_entity, :created) }
- let(:context) { BulkImports::Pipeline::Context.new(entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
before do
allow_next_instance_of(BulkImports::Extractor) do |extractor|
@@ -97,12 +135,13 @@ RSpec.describe BulkImports::Pipeline::Runner do
end
it 'logs import failure' do
- BulkImports::MyPipeline.new.run(context)
+ BulkImports::MyPipeline.new(context).run
failure = entity.failures.first
expect(failure).to be_present
expect(failure.pipeline_class).to eq('BulkImports::MyPipeline')
+ expect(failure.pipeline_step).to eq('extractor')
expect(failure.exception_class).to eq('StandardError')
expect(failure.exception_message).to eq('Error!')
end
@@ -113,7 +152,7 @@ RSpec.describe BulkImports::Pipeline::Runner do
end
it 'marks entity as failed' do
- BulkImports::MyPipeline.new.run(context)
+ BulkImports::MyPipeline.new(context).run
expect(entity.failed?).to eq(true)
end
@@ -129,13 +168,13 @@ RSpec.describe BulkImports::Pipeline::Runner do
)
end
- BulkImports::MyPipeline.new.run(context)
+ BulkImports::MyPipeline.new(context).run
end
end
context 'when pipeline is not marked to abort on failure' do
it 'marks entity as failed' do
- BulkImports::MyPipeline.new.run(context)
+ BulkImports::MyPipeline.new(context).run
expect(entity.failed?).to eq(false)
end
@@ -144,25 +183,23 @@ RSpec.describe BulkImports::Pipeline::Runner do
end
context 'when entity is marked as failed' do
- let(:context) do
- instance_double(
- BulkImports::Pipeline::Context,
- entity: instance_double(BulkImports::Entity, id: 1, source_type: 'group', failed?: true)
- )
- end
+ let(:entity) { create(:bulk_import_entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(entity) }
it 'logs and returns without execution' do
+ allow(entity).to receive(:failed?).and_return(true)
+
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger).to receive(:info)
.with(
message: 'Skipping due to failed pipeline status',
pipeline_class: 'BulkImports::MyPipeline',
- bulk_import_entity_id: 1,
- bulk_import_entity_type: 'group'
+ bulk_import_entity_id: entity.id,
+ bulk_import_entity_type: 'group_entity'
)
end
- BulkImports::MyPipeline.new.run(context)
+ BulkImports::MyPipeline.new(context).run
end
end
end
diff --git a/spec/lib/feature/gitaly_spec.rb b/spec/lib/feature/gitaly_spec.rb
index a2181a63335..696427bb8b6 100644
--- a/spec/lib/feature/gitaly_spec.rb
+++ b/spec/lib/feature/gitaly_spec.rb
@@ -3,35 +3,78 @@
require 'spec_helper'
RSpec.describe Feature::Gitaly do
- let(:feature_flag) { "mep_mep" }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:project_2) { create(:project) }
+
+ before do
+ skip_feature_flags_yaml_validation
+ end
describe ".enabled?" do
- context 'when the gate is closed' do
- before do
- stub_feature_flags(gitaly_mep_mep: false)
+ context 'when the flag is set globally' do
+ let(:feature_flag) { 'global_flag' }
+
+ context 'when the gate is closed' do
+ before do
+ stub_feature_flags(gitaly_global_flag: false)
+ end
+
+ it 'returns false' do
+ expect(described_class.enabled?(feature_flag)).to be(false)
+ end
end
- it 'returns false' do
- expect(described_class.enabled?(feature_flag)).to be(false)
+ context 'when the flag defaults to on' do
+ it 'returns true' do
+ expect(described_class.enabled?(feature_flag)).to be(true)
+ end
end
end
- context 'when the flag defaults to on' do
- it 'returns true' do
- expect(described_class.enabled?(feature_flag)).to be(true)
+ context 'when the flag is enabled for a particular project' do
+ let(:feature_flag) { 'project_flag' }
+
+ before do
+ stub_feature_flags(gitaly_project_flag: project)
+ end
+
+ it 'returns true for that project' do
+ expect(described_class.enabled?(feature_flag, project)).to be(true)
+ end
+
+ it 'returns false for any other project' do
+ expect(described_class.enabled?(feature_flag, project_2)).to be(false)
+ end
+
+ it 'returns false when no project is passed' do
+ expect(described_class.enabled?(feature_flag)).to be(false)
end
end
end
describe ".server_feature_flags" do
before do
- stub_feature_flags(gitaly_mep_mep: true, foo: true)
+ stub_feature_flags(gitaly_global_flag: true, gitaly_project_flag: project, non_gitaly_flag: false)
end
subject { described_class.server_feature_flags }
- it { is_expected.to be_a(Hash) }
- it { is_expected.to eq("gitaly-feature-mep-mep" => "true") }
+ it 'returns a hash of flags starting with the prefix, with dashes instead of underscores' do
+ expect(subject).to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false')
+ end
+
+ context 'when a project is passed' do
+ it 'returns the value for the flag on the given project' do
+ expect(described_class.server_feature_flags(project))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'true')
+
+ expect(described_class.server_feature_flags(project_2))
+ .to eq('gitaly-feature-global-flag' => 'true',
+ 'gitaly-feature-project-flag' => 'false')
+ end
+ end
context 'when table does not exist' do
before do
diff --git a/spec/lib/gitlab/access/branch_protection_spec.rb b/spec/lib/gitlab/access/branch_protection_spec.rb
index 9b736a30c7e..44c30d1f596 100644
--- a/spec/lib/gitlab/access/branch_protection_spec.rb
+++ b/spec/lib/gitlab/access/branch_protection_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Access::BranchProtection do
- describe '#any?' do
- using RSpec::Parameterized::TableSyntax
+ using RSpec::Parameterized::TableSyntax
+ describe '#any?' do
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
@@ -19,8 +19,6 @@ RSpec.describe Gitlab::Access::BranchProtection do
end
describe '#developer_can_push?' do
- using RSpec::Parameterized::TableSyntax
-
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
@@ -36,8 +34,6 @@ RSpec.describe Gitlab::Access::BranchProtection do
end
describe '#developer_can_merge?' do
- using RSpec::Parameterized::TableSyntax
-
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
@@ -53,8 +49,6 @@ RSpec.describe Gitlab::Access::BranchProtection do
end
describe '#fully_protected?' do
- using RSpec::Parameterized::TableSyntax
-
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
diff --git a/spec/lib/gitlab/alert_management/payload/generic_spec.rb b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
index b7660462b0d..d022c629458 100644
--- a/spec/lib/gitlab/alert_management/payload/generic_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
@@ -19,7 +19,34 @@ RSpec.describe Gitlab::AlertManagement::Payload::Generic do
describe '#severity' do
subject { parsed_payload.severity }
- it_behaves_like 'parsable alert payload field with fallback', 'critical', 'severity'
+ context 'when set' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:raw_payload) { { 'severity' => payload_severity } }
+
+ where(:payload_severity, :expected_severity) do
+ 'critical' | :critical
+ 'high' | :high
+ 'medium' | :medium
+ 'low' | :low
+ 'info' | :info
+
+ 'CRITICAL' | :critical
+ 'cRiTiCaL' | :critical
+
+ 'unmapped' | nil
+ 1 | nil
+ nil | nil
+ end
+
+ with_them do
+ it { is_expected.to eq(expected_severity) }
+ end
+ end
+
+ context 'without key' do
+ it { is_expected.to be_nil }
+ end
end
describe '#monitoring_tool' do
diff --git a/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb b/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
index 457db58a28b..f574f5ba6a3 100644
--- a/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
@@ -156,8 +156,6 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
end
describe '#gitlab_fingerprint' do
- subject { parsed_payload.gitlab_fingerprint }
-
let(:raw_payload) do
{
'startsAt' => Time.current.to_s,
@@ -166,6 +164,8 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
}
end
+ subject { parsed_payload.gitlab_fingerprint }
+
it 'returns a fingerprint' do
plain_fingerprint = [
parsed_payload.send(:starts_at_raw),
@@ -237,4 +237,63 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
it { is_expected.to be_falsey }
end
end
+
+ describe '#severity' do
+ subject { parsed_payload.severity }
+
+ context 'when set' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:raw_payload) { { 'labels' => { 'severity' => payload_severity } } }
+
+ where(:payload_severity, :expected_severity) do
+ 'critical' | :critical
+ 'high' | :high
+ 'medium' | :medium
+ 'low' | :low
+ 'info' | :info
+
+ 's1' | :critical
+ 's2' | :high
+ 's3' | :medium
+ 's4' | :low
+ 's5' | :info
+ 'p1' | :critical
+ 'p2' | :high
+ 'p3' | :medium
+ 'p4' | :low
+ 'p5' | :info
+
+ 'CRITICAL' | :critical
+ 'cRiTiCaL' | :critical
+ 'S1' | :critical
+
+ 'unmapped' | nil
+ 1 | nil
+ nil | nil
+
+ 'debug' | :info
+ 'information' | :info
+ 'notice' | :info
+ 'warn' | :low
+ 'warning' | :low
+ 'minor' | :low
+ 'error' | :medium
+ 'major' | :high
+ 'emergency' | :critical
+ 'fatal' | :critical
+
+ 'alert' | :medium
+ 'page' | :high
+ end
+
+ with_them do
+ it { is_expected.to eq(expected_severity) }
+ end
+ end
+
+ context 'without key' do
+ it { is_expected.to be_nil }
+ end
+ end
end
diff --git a/spec/lib/gitlab/alert_management/payload_spec.rb b/spec/lib/gitlab/alert_management/payload_spec.rb
index 44b55e228c5..7c129a8a48e 100644
--- a/spec/lib/gitlab/alert_management/payload_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload_spec.rb
@@ -56,5 +56,20 @@ RSpec.describe Gitlab::AlertManagement::Payload do
it { is_expected.to be_a Gitlab::AlertManagement::Payload::Generic }
end
end
+
+ context 'with integration specified by caller' do
+ let(:integration) { instance_double(AlertManagement::HttpIntegration) }
+
+ subject { described_class.parse(project, payload, integration: integration) }
+
+ it 'passes an integration to a specific payload' do
+ expect(::Gitlab::AlertManagement::Payload::Generic)
+ .to receive(:new)
+ .with(project: project, payload: payload, integration: integration)
+ .and_call_original
+
+ subject
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/api_authentication/token_locator_spec.rb b/spec/lib/gitlab/api_authentication/token_locator_spec.rb
index 68ce48a70ea..e933fd8352e 100644
--- a/spec/lib/gitlab/api_authentication/token_locator_spec.rb
+++ b/spec/lib/gitlab/api_authentication/token_locator_spec.rb
@@ -51,5 +51,26 @@ RSpec.describe Gitlab::APIAuthentication::TokenLocator do
end
end
end
+
+ context 'with :http_token' do
+ let(:type) { :http_token }
+
+ context 'without credentials' do
+ let(:request) { double(headers: {}) }
+
+ it 'returns nil' do
+ expect(subject).to be(nil)
+ end
+ end
+
+ context 'with credentials' do
+ let(:password) { 'bar' }
+ let(:request) { double(headers: { "Authorization" => password }) }
+
+ it 'returns the credentials' do
+ expect(subject.password).to eq(password)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/api_authentication/token_resolver_spec.rb b/spec/lib/gitlab/api_authentication/token_resolver_spec.rb
index 0028fb080ac..97a7c8ba7cf 100644
--- a/spec/lib/gitlab/api_authentication/token_resolver_spec.rb
+++ b/spec/lib/gitlab/api_authentication/token_resolver_spec.rb
@@ -47,8 +47,8 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
subject { resolver.resolve(raw) }
- context 'with :personal_access_token' do
- let(:type) { :personal_access_token }
+ context 'with :personal_access_token_with_username' do
+ let(:type) { :personal_access_token_with_username }
let(:token) { personal_access_token }
context 'with valid credentials' do
@@ -62,10 +62,16 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
it_behaves_like 'an unauthorized request'
end
+
+ context 'with no username' do
+ let(:raw) { username_and_password(nil, token.token) }
+
+ it_behaves_like 'an unauthorized request'
+ end
end
- context 'with :job_token' do
- let(:type) { :job_token }
+ context 'with :job_token_with_username' do
+ let(:type) { :job_token_with_username }
let(:token) { ci_job }
context 'with valid credentials' do
@@ -93,8 +99,8 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
end
end
- context 'with :deploy_token' do
- let(:type) { :deploy_token }
+ context 'with :deploy_token_with_username' do
+ let(:type) { :deploy_token_with_username }
let(:token) { deploy_token }
context 'with a valid deploy token' do
@@ -109,6 +115,51 @@ RSpec.describe Gitlab::APIAuthentication::TokenResolver do
it_behaves_like 'an unauthorized request'
end
end
+
+ context 'with :personal_access_token' do
+ let(:type) { :personal_access_token }
+ let(:token) { personal_access_token }
+
+ context 'with valid credentials' do
+ let(:raw) { username_and_password(nil, token.token) }
+
+ it_behaves_like 'an authorized request'
+ end
+ end
+
+ context 'with :job_token' do
+ let(:type) { :job_token }
+ let(:token) { ci_job }
+
+ context 'with valid credentials' do
+ let(:raw) { username_and_password(nil, token.token) }
+
+ it_behaves_like 'an authorized request'
+ end
+
+ context 'when the job is not running' do
+ let(:raw) { username_and_password(nil, ci_job_done.token) }
+
+ it_behaves_like 'an unauthorized request'
+ end
+
+ context 'with an invalid job token' do
+ let(:raw) { username_and_password(nil, "not a valid CI job token") }
+
+ it_behaves_like 'an unauthorized request'
+ end
+ end
+
+ context 'with :deploy_token' do
+ let(:type) { :deploy_token }
+ let(:token) { deploy_token }
+
+ context 'with a valid deploy token' do
+ let(:raw) { username_and_password(nil, token.token) }
+
+ it_behaves_like 'an authorized request'
+ end
+ end
end
def username_and_password(username, password)
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index 36e4decdead..08510d4652b 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -510,6 +510,73 @@ module Gitlab
expect(render(input, context)).to include(output.strip)
end
+
+ it 'does not convert a blockdiag diagram to image' do
+ input = <<~ADOC
+ [blockdiag]
+ ....
+ blockdiag {
+ Kroki -> generates -> "Block diagrams";
+ Kroki -> is -> "very easy!";
+
+ Kroki [color = "greenyellow"];
+ "Block diagrams" [color = "pink"];
+ "very easy!" [color = "orange"];
+ }
+ ....
+ ADOC
+
+ output = <<~HTML
+ <div>
+ <div>
+ <pre>blockdiag {
+ Kroki -&gt; generates -&gt; "Block diagrams";
+ Kroki -&gt; is -&gt; "very easy!";
+
+ Kroki [color = "greenyellow"];
+ "Block diagrams" [color = "pink"];
+ "very easy!" [color = "orange"];
+ }</pre>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
+ end
+
+ context 'with Kroki and BlockDiag (additional format) enabled' do
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_enabled).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_url).and_return('https://kroki.io')
+ allow_any_instance_of(ApplicationSetting).to receive(:kroki_formats_blockdiag).and_return(true)
+ end
+
+ it 'converts a blockdiag diagram to image' do
+ input = <<~ADOC
+ [blockdiag]
+ ....
+ blockdiag {
+ Kroki -> generates -> "Block diagrams";
+ Kroki -> is -> "very easy!";
+
+ Kroki [color = "greenyellow"];
+ "Block diagrams" [color = "pink"];
+ "very easy!" [color = "orange"];
+ }
+ ....
+ ADOC
+
+ output = <<~HTML
+ <div>
+ <div>
+ <a class="no-attachment-icon" href="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w==" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Diagram" class="lazy" data-src="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w=="></a>
+ </div>
+ </div>
+ HTML
+
+ expect(render(input, context)).to include(output.strip)
+ end
end
end
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index 775f8f056b5..cddcaf09b74 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -7,7 +7,18 @@ RSpec.describe Gitlab::Auth::AuthFinders do
include HttpBasicAuthHelpers
# Create the feed_token and static_object_token for the user
- let_it_be(:user) { create(:user).tap(&:feed_token).tap(&:static_object_token) }
+ let_it_be(:user, freeze: true) { create(:user).tap(&:feed_token).tap(&:static_object_token) }
+ let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user) }
+
+ let_it_be(:project, freeze: true) { create(:project, :private) }
+ let_it_be(:pipeline, freeze: true) { create(:ci_pipeline, project: project) }
+ let_it_be(:job, freeze: true) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+ let_it_be(:failed_job, freeze: true) { create(:ci_build, :failed, pipeline: pipeline, user: user) }
+
+ let_it_be(:project2, freeze: true) { create(:project, :private) }
+ let_it_be(:pipeline2, freeze: true) { create(:ci_pipeline, project: project2) }
+ let_it_be(:job2, freeze: true) { create(:ci_build, :running, pipeline: pipeline2, user: user) }
+
let(:env) do
{
'rack.input' => ''
@@ -15,6 +26,12 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
let(:request) { ActionDispatch::Request.new(env) }
+ let(:params) { {} }
+
+ before_all do
+ project.add_developer(user)
+ project2.add_developer(user)
+ end
def set_param(key, value)
request.update_param(key, value)
@@ -28,75 +45,93 @@ RSpec.describe Gitlab::Auth::AuthFinders do
env.merge!(basic_auth_header(username, password))
end
- shared_examples 'find user from job token' do
+ def set_bearer_token(token)
+ env['HTTP_AUTHORIZATION'] = "Bearer #{token}"
+ end
+
+ shared_examples 'find user from job token' do |without_job_token_allowed|
context 'when route is allowed to be authenticated' do
let(:route_authentication_setting) { { job_token_allowed: true } }
- it "returns an Unauthorized exception for an invalid token" do
- set_token('invalid token')
+ context 'for an invalid token' do
+ let(:token) { 'invalid token' }
- expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ it "returns an Unauthorized exception" do
+ expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ expect(@current_authenticated_job).to be_nil
+ end
end
context 'with a running job' do
- before do
- job.update!(status: :running)
- end
-
- it 'return user if token is valid' do
- set_token(job.token)
+ let(:token) { job.token }
+ it 'return user' do
expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job
end
end
context 'with a job that is not running' do
- before do
- job.update!(status: :failed)
- end
+ let(:token) { failed_job.token }
it 'returns an Unauthorized exception' do
- set_token(job.token)
-
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ expect(@current_authenticated_job).to be_nil
+ end
+ end
+ end
+
+ context 'when route is not allowed to be authenticated' do
+ let(:route_authentication_setting) { { job_token_allowed: false } }
+
+ context 'with a running job' do
+ let(:token) { job.token }
+
+ if without_job_token_allowed == :error
+ it 'returns an Unauthorized exception' do
+ expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ expect(@current_authenticated_job).to be_nil
+ end
+ elsif without_job_token_allowed == :user
+ it 'returns the user' do
+ expect(subject).to eq(user)
+ expect(@current_authenticated_job).to eq job
+ end
+ else
+ it 'returns nil' do
+ is_expected.to be_nil
+ expect(@current_authenticated_job).to be_nil
+ end
end
end
end
end
describe '#find_user_from_bearer_token' do
- let_it_be_with_reload(:job) { create(:ci_build, user: user) }
-
subject { find_user_from_bearer_token }
context 'when the token is passed as an oauth token' do
- def set_token(token)
- env['HTTP_AUTHORIZATION'] = "Bearer #{token}"
+ before do
+ set_bearer_token(token)
end
- context 'with a job token' do
- it_behaves_like 'find user from job token'
- end
+ it_behaves_like 'find user from job token', :error
+ end
- context 'with oauth token' do
- let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) }
- let(:token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api').token }
+ context 'with oauth token' do
+ let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) }
+ let(:doorkeeper_access_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
- before do
- set_token(token)
- end
-
- it { is_expected.to eq user }
+ before do
+ set_bearer_token(doorkeeper_access_token.token)
end
+
+ it { is_expected.to eq user }
end
context 'with a personal access token' do
- let_it_be(:pat) { create(:personal_access_token, user: user) }
- let(:token) { pat.token }
-
before do
- env[described_class::PRIVATE_TOKEN_HEADER] = pat.token
+ env[described_class::PRIVATE_TOKEN_HEADER] = personal_access_token.token
end
it { is_expected.to eq user }
@@ -277,7 +312,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#deploy_token_from_request' do
- let_it_be(:deploy_token) { create(:deploy_token) }
+ let_it_be(:deploy_token, freeze: true) { create(:deploy_token) }
let_it_be(:route_authentication_setting) { { deploy_token_allowed: true } }
subject { deploy_token_from_request }
@@ -293,11 +328,13 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'with deploy token headers' do
- before do
- set_header(described_class::DEPLOY_TOKEN_HEADER, deploy_token.token)
- end
+ context 'with valid deploy token' do
+ before do
+ set_header(described_class::DEPLOY_TOKEN_HEADER, deploy_token.token)
+ end
- it { is_expected.to eq deploy_token }
+ it { is_expected.to eq deploy_token }
+ end
it_behaves_like 'an unauthenticated route'
@@ -311,17 +348,19 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'with oauth headers' do
- before do
- set_header('HTTP_AUTHORIZATION', "Bearer #{deploy_token.token}")
- end
+ context 'with valid token' do
+ before do
+ set_bearer_token(deploy_token.token)
+ end
- it { is_expected.to eq deploy_token }
+ it { is_expected.to eq deploy_token }
- it_behaves_like 'an unauthenticated route'
+ it_behaves_like 'an unauthenticated route'
+ end
context 'with invalid token' do
before do
- set_header('HTTP_AUTHORIZATION', "Bearer invalid_token")
+ set_bearer_token('invalid_token')
end
it { is_expected.to be_nil }
@@ -348,8 +387,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_access_token' do
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
-
before do
set_header('SCRIPT_NAME', 'url.atom')
end
@@ -374,24 +411,34 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'with OAuth headers' do
- it 'returns user' do
- set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}")
+ context 'with valid personal access token' do
+ before do
+ set_bearer_token(personal_access_token.token)
+ end
- expect(find_user_from_access_token).to eq user
+ it 'returns user' do
+ expect(find_user_from_access_token).to eq user
+ end
end
- it 'returns exception if invalid personal_access_token' do
- env['HTTP_AUTHORIZATION'] = 'Bearer invalid_20byte_token'
+ context 'with invalid personal_access_token' do
+ before do
+ set_bearer_token('invalid_20byte_token')
+ end
- expect { find_personal_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ it 'returns exception' do
+ expect { find_personal_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ end
end
context 'when using a non-prefixed access token' do
- let_it_be(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) }
+ let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, :no_prefix, user: user) }
- it 'returns user' do
- set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}")
+ before do
+ set_bearer_token(personal_access_token.token)
+ end
+ it 'returns user' do
expect(find_user_from_access_token).to eq user
end
end
@@ -399,8 +446,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_web_access_token' do
- let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) }
-
before do
set_header(described_class::PRIVATE_TOKEN_HEADER, personal_access_token.token)
end
@@ -451,9 +496,9 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'when the token has read_api scope' do
- before do
- personal_access_token.update!(scopes: ['read_api'])
+ let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user, scopes: ['read_api']) }
+ before do
set_header('SCRIPT_NAME', '/api/endpoint')
end
@@ -481,8 +526,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_personal_access_token' do
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
-
before do
set_header('SCRIPT_NAME', 'url.atom')
end
@@ -516,21 +559,23 @@ RSpec.describe Gitlab::Auth::AuthFinders do
describe '#find_oauth_access_token' do
let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) }
- let(:token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
+ let(:doorkeeper_access_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
context 'passed as header' do
- it 'returns token if valid oauth_access_token' do
- set_header('HTTP_AUTHORIZATION', "Bearer #{token.token}")
+ before do
+ set_bearer_token(doorkeeper_access_token.token)
+ end
- expect(find_oauth_access_token.token).to eq token.token
+ it 'returns token if valid oauth_access_token' do
+ expect(find_oauth_access_token.token).to eq doorkeeper_access_token.token
end
end
context 'passed as param' do
it 'returns user if valid oauth_access_token' do
- set_param(:access_token, token.token)
+ set_param(:access_token, doorkeeper_access_token.token)
- expect(find_oauth_access_token.token).to eq token.token
+ expect(find_oauth_access_token.token).to eq doorkeeper_access_token.token
end
end
@@ -538,10 +583,14 @@ RSpec.describe Gitlab::Auth::AuthFinders do
expect(find_oauth_access_token).to be_nil
end
- it 'returns exception if invalid oauth_access_token' do
- set_header('HTTP_AUTHORIZATION', "Bearer invalid_token")
+ context 'with invalid token' do
+ before do
+ set_bearer_token('invalid_token')
+ end
- expect { find_oauth_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ it 'returns exception if invalid oauth_access_token' do
+ expect { find_oauth_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ end
end
end
@@ -551,7 +600,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'access token is valid' do
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:route_authentication_setting) { { basic_auth_personal_access_token: true } }
it 'finds the token from basic auth' do
@@ -572,8 +620,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'route_setting is not set' do
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
-
it 'returns nil' do
auth_header_with(personal_access_token.token)
@@ -582,7 +628,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'route_setting is not correct' do
- let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:route_authentication_setting) { { basic_auth_personal_access_token: false } }
it 'returns nil' do
@@ -629,44 +674,18 @@ RSpec.describe Gitlab::Auth::AuthFinders do
context 'with CI username' do
let(:username) { ::Gitlab::Auth::CI_JOB_USER }
- let_it_be(:user) { create(:user) }
- let_it_be(:build) { create(:ci_build, user: user, status: :running) }
-
- it 'returns nil without password' do
- set_basic_auth_header(username, nil)
-
- is_expected.to be_nil
- end
-
- it 'returns user with valid token' do
- set_basic_auth_header(username, build.token)
-
- is_expected.to eq user
- expect(@current_authenticated_job).to eq build
- end
-
- it 'raises error with invalid token' do
- set_basic_auth_header(username, 'token')
-
- expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ before do
+ set_basic_auth_header(username, token)
end
- it 'returns exception if the job is not running' do
- set_basic_auth_header(username, build.token)
- build.success!
-
- expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
- end
+ it_behaves_like 'find user from job token', :user
end
end
describe '#validate_access_token!' do
subject { validate_access_token! }
- let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) }
-
context 'with a job token' do
- let_it_be(:job) { create(:ci_build, user: user, status: :running) }
let(:route_authentication_setting) { { job_token_allowed: true } }
before do
@@ -684,6 +703,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'token is not valid' do
+ let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) }
+
before do
allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token)
end
@@ -706,7 +727,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
context 'with impersonation token' do
- let_it_be(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
+ let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, :impersonation, user: user) }
context 'when impersonation is disabled' do
before do
@@ -722,96 +743,30 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_user_from_job_token' do
- let_it_be(:job) { create(:ci_build, user: user, status: :running) }
- let(:route_authentication_setting) { { job_token_allowed: true } }
-
subject { find_user_from_job_token }
- context 'when the job token is in the headers' do
- it 'returns the user if valid job token' do
- set_header(described_class::JOB_TOKEN_HEADER, job.token)
-
- is_expected.to eq(user)
- expect(@current_authenticated_job).to eq(job)
- end
-
- it 'returns nil without job token' do
- set_header(described_class::JOB_TOKEN_HEADER, '')
-
- is_expected.to be_nil
- end
-
- it 'returns exception if invalid job token' do
- set_header(described_class::JOB_TOKEN_HEADER, 'invalid token')
-
- expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ context 'when the token is in the headers' do
+ before do
+ set_header(described_class::JOB_TOKEN_HEADER, token)
end
- it 'returns exception if the job is not running' do
- set_header(described_class::JOB_TOKEN_HEADER, job.token)
- job.success!
+ it_behaves_like 'find user from job token'
+ end
- expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ context 'when the token is in the job_token param' do
+ before do
+ set_param(described_class::JOB_TOKEN_PARAM, token)
end
- context 'when route is not allowed to be authenticated' do
- let(:route_authentication_setting) { { job_token_allowed: false } }
-
- it 'sets current_user to nil' do
- set_header(described_class::JOB_TOKEN_HEADER, job.token)
-
- allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(true)
-
- is_expected.to be_nil
- end
- end
+ it_behaves_like 'find user from job token'
end
- context 'when the job token is in the params' do
- shared_examples 'job token params' do |token_key_name|
- before do
- set_param(token_key_name, token)
- end
-
- context 'with valid job token' do
- let(:token) { job.token }
-
- it 'returns the user' do
- is_expected.to eq(user)
- expect(@current_authenticated_job).to eq(job)
- end
- end
-
- context 'with empty job token' do
- let(:token) { '' }
-
- it 'returns nil' do
- is_expected.to be_nil
- end
- end
-
- context 'with invalid job token' do
- let(:token) { 'invalid token' }
-
- it 'returns exception' do
- expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
- end
- end
-
- context 'when route is not allowed to be authenticated' do
- let(:route_authentication_setting) { { job_token_allowed: false } }
- let(:token) { job.token }
-
- it 'sets current_user to nil' do
- allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(true)
-
- is_expected.to be_nil
- end
- end
+ context 'when the token is in the token param' do
+ before do
+ set_param(described_class::RUNNER_JOB_TOKEN_PARAM, token)
end
- it_behaves_like 'job token params', described_class::JOB_TOKEN_PARAM
- it_behaves_like 'job token params', described_class::RUNNER_JOB_TOKEN_PARAM
+ it_behaves_like 'find user from job token'
end
context 'when the job token is provided via basic auth' do
@@ -834,7 +789,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#cluster_agent_token_from_authorization_token' do
- let_it_be(:agent_token) { create(:cluster_agent_token) }
+ let_it_be(:agent_token, freeze: true) { create(:cluster_agent_token) }
context 'when route_setting is empty' do
it 'returns nil' do
@@ -884,7 +839,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#find_runner_from_token' do
- let_it_be(:runner) { create(:ci_runner) }
+ let_it_be(:runner, freeze: true) { create(:ci_runner) }
context 'with API requests' do
before do
diff --git a/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb b/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb
index 3d782272d7e..f23fdd3fbcb 100644
--- a/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb
+++ b/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb
@@ -19,6 +19,9 @@ RSpec.describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_cachin
before do
stub_rack_attack_setting(options)
+ Rack::Attack.reset!
+ Rack::Attack.clear_configuration
+ Gitlab::RackAttack.configure(Rack::Attack)
end
after do
diff --git a/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb b/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb
deleted file mode 100644
index 928aade4008..00000000000
--- a/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Auth::Otp::SessionEnforcer, :clean_gitlab_redis_shared_state do
- let_it_be(:key) { create(:key)}
-
- describe '#update_session' do
- it 'registers a session in Redis' do
- redis = double(:redis)
- expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
-
- expect(redis).to(
- receive(:setex)
- .with("#{described_class::OTP_SESSIONS_NAMESPACE}:#{key.id}",
- described_class::DEFAULT_EXPIRATION,
- true)
- .once)
-
- described_class.new(key).update_session
- end
- end
-
- describe '#access_restricted?' do
- subject { described_class.new(key).access_restricted? }
-
- context 'with existing session' do
- before do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set("#{described_class::OTP_SESSIONS_NAMESPACE}:#{key.id}", true )
- end
- end
-
- it { is_expected.to be_falsey }
- end
-
- context 'without an existing session' do
- it { is_expected.to be_truthy }
- end
- end
-end
diff --git a/spec/lib/gitlab/auth/u2f_webauthn_converter_spec.rb b/spec/lib/gitlab/auth/u2f_webauthn_converter_spec.rb
new file mode 100644
index 00000000000..deddc7f5294
--- /dev/null
+++ b/spec/lib/gitlab/auth/u2f_webauthn_converter_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::U2fWebauthnConverter do
+ let_it_be(:u2f_registration) do
+ device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
+ create(:u2f_registration, name: 'u2f_device',
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: Base64.strict_encode64(device.origin_public_key_raw))
+ end
+
+ it 'converts u2f registration' do
+ webauthn_credential = WebAuthn::U2fMigrator.new(
+ app_id: Gitlab.config.gitlab.url,
+ certificate: u2f_registration.certificate,
+ key_handle: u2f_registration.key_handle,
+ public_key: u2f_registration.public_key,
+ counter: u2f_registration.counter
+ ).credential
+
+ converted_webauthn = described_class.new(u2f_registration).convert
+
+ expect(converted_webauthn).to(
+ include(user_id: u2f_registration.user_id,
+ credential_xid: Base64.strict_encode64(webauthn_credential.id)))
+ 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
new file mode 100644
index 00000000000..708e5e21dbe
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillProjectUpdatedAtAfterRepositoryStorageMove, :migration, schema: 20210210093901 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/populate_issue_email_participants_spec.rb b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
new file mode 100644
index 00000000000..f724b007e01
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::PopulateIssueEmailParticipants, schema: 20201128210234 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/remove_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
new file mode 100644
index 00000000000..47e1d4620cd
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::RemoveDuplicateVulnerabilitiesFindings do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let!(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let!(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let!(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
+ let!(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'vulnerability-identifier',
+ external_id: 'vulnerability-identifier',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'vulnerability identifier')
+ end
+
+ let!(:first_finding) do
+ create_finding!(
+ uuid: "test1",
+ vulnerability_id: nil,
+ report_type: 0,
+ location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:first_duplicate) do
+ create_finding!(
+ uuid: "test2",
+ vulnerability_id: nil,
+ report_type: 0,
+ location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner2.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:second_duplicate) do
+ create_finding!(
+ uuid: "test3",
+ vulnerability_id: nil,
+ report_type: 0,
+ location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner3.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:unrelated_finding) do
+ create_finding!(
+ uuid: "unreleated_finding",
+ vulnerability_id: nil,
+ report_type: 1,
+ location_fingerprint: 'random_location_fingerprint',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: unrelated_scanner.id,
+ project_id: project.id
+ )
+ end
+
+ subject { described_class.new.perform(first_finding.id, unrelated_finding.id) }
+
+ before do
+ stub_const("#{described_class}::DELETE_BATCH_SIZE", 1)
+ end
+
+ it "removes entries which would result in duplicate UUIDv5" do
+ expect(vulnerability_findings.count).to eq(4)
+
+ expect { subject }.to change { vulnerability_findings.count }.from(4).to(2)
+
+ expect(vulnerability_findings.pluck(:id)).to eq([second_duplicate.id, unrelated_finding.id])
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ 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: 'test')
+ vulnerability_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: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.zone.now, confirmed_at: Time.zone.now)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+end
diff --git a/spec/lib/gitlab/background_migration_spec.rb b/spec/lib/gitlab/background_migration_spec.rb
index 052a01a8dd8..5b20572578c 100644
--- a/spec/lib/gitlab/background_migration_spec.rb
+++ b/spec/lib/gitlab/background_migration_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::BackgroundMigration do
expect(described_class).to receive(:perform)
.with('Foo', [10, 20])
- described_class.steal('Foo') { |(arg1, arg2)| arg1 == 10 && arg2 == 20 }
+ described_class.steal('Foo') { |job| job.args.second.first == 10 && job.args.second.second == 20 }
end
it 'does not steal jobs that do not match the predicate' do
diff --git a/spec/lib/gitlab/badge/coverage/metadata_spec.rb b/spec/lib/gitlab/badge/coverage/metadata_spec.rb
deleted file mode 100644
index 725ae03ad74..00000000000
--- a/spec/lib/gitlab/badge/coverage/metadata_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'lib/gitlab/badge/shared/metadata'
-
-RSpec.describe Gitlab::Badge::Coverage::Metadata do
- let(:badge) do
- double(project: create(:project), ref: 'feature', job: 'test')
- end
-
- let(:metadata) { described_class.new(badge) }
-
- it_behaves_like 'badge metadata'
-
- describe '#title' do
- it 'returns coverage report title' do
- expect(metadata.title).to eq 'coverage report'
- end
- end
-
- describe '#image_url' do
- it 'returns valid url' do
- expect(metadata.image_url).to include 'badges/feature/coverage.svg'
- end
- end
-
- describe '#link_url' do
- it 'returns valid link' do
- expect(metadata.link_url).to include 'commits/feature'
- end
- end
-end
diff --git a/spec/lib/gitlab/badge/coverage/report_spec.rb b/spec/lib/gitlab/badge/coverage/report_spec.rb
deleted file mode 100644
index 3b5ea3291e4..00000000000
--- a/spec/lib/gitlab/badge/coverage/report_spec.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Badge::Coverage::Report do
- let_it_be(:project) { create(:project) }
- let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
- let_it_be(:running_pipeline) { create(:ci_pipeline, :running, project: project) }
- let_it_be(:failure_pipeline) { create(:ci_pipeline, :failed, project: project) }
-
- let_it_be(:builds) do
- [
- create(:ci_build, :success, pipeline: success_pipeline, coverage: 40, created_at: 9.seconds.ago, name: 'coverage'),
- create(:ci_build, :success, pipeline: success_pipeline, coverage: 60, created_at: 8.seconds.ago)
- ]
- end
-
- let(:badge) do
- described_class.new(project, 'master', opts: { job: job_name })
- end
-
- let(:job_name) { nil }
-
- describe '#entity' do
- it 'describes a coverage' do
- expect(badge.entity).to eq 'coverage'
- end
- end
-
- describe '#metadata' do
- it 'returns correct metadata' do
- expect(badge.metadata.image_url).to include 'coverage.svg'
- end
- end
-
- describe '#template' do
- it 'returns correct template' do
- expect(badge.template.key_text).to eq 'coverage'
- end
- end
-
- describe '#status' do
- context 'with no job specified' do
- it 'returns the most recent successful pipeline coverage value' do
- expect(badge.status).to eq(50.00)
- end
-
- context 'and no successful pipelines' do
- before do
- allow(badge).to receive(:successful_pipeline).and_return(nil)
- end
-
- it 'returns nil' do
- expect(badge.status).to eq(nil)
- end
- end
- end
-
- context 'with a blank job name' do
- let(:job_name) { ' ' }
-
- it 'returns the latest successful pipeline coverage value' do
- expect(badge.status).to eq(50.00)
- end
- end
-
- context 'with an unmatching job name specified' do
- let(:job_name) { 'incorrect name' }
-
- it 'returns nil' do
- expect(badge.status).to be_nil
- end
- end
-
- context 'with a matching job name specified' do
- let(:job_name) { 'coverage' }
-
- it 'returns the pipeline coverage value' do
- expect(badge.status).to eq(40.00)
- end
-
- context 'with a more recent running pipeline' do
- let!(:another_build) { create(:ci_build, :success, pipeline: running_pipeline, coverage: 20, created_at: 7.seconds.ago, name: 'coverage') }
-
- it 'returns the running pipeline coverage value' do
- expect(badge.status).to eq(20.00)
- end
- end
-
- context 'with a more recent failed pipeline' do
- let!(:another_build) { create(:ci_build, :success, pipeline: failure_pipeline, coverage: 10, created_at: 6.seconds.ago, name: 'coverage') }
-
- it 'returns the failed pipeline coverage value' do
- expect(badge.status).to eq(10.00)
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/badge/coverage/template_spec.rb b/spec/lib/gitlab/badge/coverage/template_spec.rb
deleted file mode 100644
index ba5c1b2ce6e..00000000000
--- a/spec/lib/gitlab/badge/coverage/template_spec.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Badge::Coverage::Template do
- let(:badge) { double(entity: 'coverage', status: 90.00, customization: {}) }
- let(:template) { described_class.new(badge) }
-
- describe '#key_text' do
- it 'says coverage by default' do
- expect(template.key_text).to eq 'coverage'
- end
-
- context 'when custom key_text is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: "custom text" })
- end
-
- it 'returns custom value' do
- expect(template.key_text).to eq "custom text"
- end
-
- context 'when its size is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
- end
-
- it 'returns default value' do
- expect(template.key_text).to eq 'coverage'
- end
- end
- end
- end
-
- describe '#value_text' do
- context 'when coverage is known' do
- it 'returns coverage percentage' do
- expect(template.value_text).to eq '90.00%'
- end
- end
-
- context 'when coverage is known to many digits' do
- before do
- allow(badge).to receive(:status).and_return(92.349)
- end
-
- it 'returns rounded coverage percentage' do
- expect(template.value_text).to eq '92.35%'
- end
- end
-
- context 'when coverage is unknown' do
- before do
- allow(badge).to receive(:status).and_return(nil)
- end
-
- it 'returns string that says coverage is unknown' do
- expect(template.value_text).to eq 'unknown'
- end
- end
- end
-
- describe '#key_width' do
- it 'is fixed by default' do
- expect(template.key_width).to eq 62
- end
-
- context 'when custom key_width is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 101 })
- end
-
- it 'returns custom value' do
- expect(template.key_width).to eq 101
- end
-
- context 'when it is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 513 })
- end
-
- it 'returns default value' do
- expect(template.key_width).to eq 62
- end
- end
- end
- end
-
- describe '#value_width' do
- context 'when coverage is known' do
- it 'is narrower when coverage is known' do
- expect(template.value_width).to eq 54
- end
- end
-
- context 'when coverage is unknown' do
- before do
- allow(badge).to receive(:status).and_return(nil)
- end
-
- it 'is wider when coverage is unknown to fit text' do
- expect(template.value_width).to eq 58
- end
- 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 coverage is good' do
- before do
- allow(badge).to receive(:status).and_return(98)
- end
-
- it 'is green' do
- expect(template.value_color).to eq '#4c1'
- end
- end
-
- context 'when coverage is acceptable' do
- before do
- allow(badge).to receive(:status).and_return(90)
- end
-
- it 'is green-orange' do
- expect(template.value_color).to eq '#a3c51c'
- end
- end
-
- context 'when coverage is medium' do
- before do
- allow(badge).to receive(:status).and_return(75)
- end
-
- it 'is orange-yellow' do
- expect(template.value_color).to eq '#dfb317'
- end
- end
-
- context 'when coverage is low' do
- before do
- allow(badge).to receive(:status).and_return(50)
- end
-
- it 'is red' do
- expect(template.value_color).to eq '#e05d44'
- end
- end
-
- context 'when coverage is unknown' do
- before do
- allow(badge).to receive(:status).and_return(nil)
- end
-
- it 'is grey' do
- expect(template.value_color).to eq '#9f9f9f'
- end
- end
- end
-
- describe '#width' do
- context 'when coverage is known' do
- it 'returns the key width plus value width' do
- expect(template.width).to eq 116
- end
- end
-
- context 'when coverage is unknown' do
- before do
- allow(badge).to receive(:status).and_return(nil)
- end
-
- it 'returns key width plus wider value width' do
- expect(template.width).to eq 120
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/badge/pipeline/metadata_spec.rb b/spec/lib/gitlab/badge/pipeline/metadata_spec.rb
deleted file mode 100644
index c8ed0c8ea29..00000000000
--- a/spec/lib/gitlab/badge/pipeline/metadata_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require 'lib/gitlab/badge/shared/metadata'
-
-RSpec.describe Gitlab::Badge::Pipeline::Metadata do
- let(:badge) { double(project: create(:project), ref: 'feature') }
- let(:metadata) { described_class.new(badge) }
-
- it_behaves_like 'badge metadata'
-
- describe '#title' do
- it 'returns build status title' do
- expect(metadata.title).to eq 'pipeline status'
- end
- end
-
- describe '#image_url' do
- it 'returns valid url' do
- expect(metadata.image_url).to include 'badges/feature/pipeline.svg'
- end
- end
-
- describe '#link_url' do
- it 'returns valid link' do
- expect(metadata.link_url).to include 'commits/feature'
- end
- end
-end
diff --git a/spec/lib/gitlab/badge/pipeline/status_spec.rb b/spec/lib/gitlab/badge/pipeline/status_spec.rb
deleted file mode 100644
index b5dabca0477..00000000000
--- a/spec/lib/gitlab/badge/pipeline/status_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Badge::Pipeline::Status do
- let(:project) { create(:project, :repository) }
- let(:sha) { project.commit.sha }
- let(:branch) { 'master' }
- let(:badge) { described_class.new(project, branch) }
-
- describe '#entity' do
- it 'always says pipeline' do
- expect(badge.entity).to eq 'pipeline'
- end
- end
-
- describe '#template' do
- it 'returns badge template' do
- expect(badge.template.key_text).to eq 'pipeline'
- end
- end
-
- describe '#metadata' do
- it 'returns badge metadata' do
- expect(badge.metadata.image_url).to include 'badges/master/pipeline.svg'
- end
- end
-
- context 'pipeline exists', :sidekiq_might_not_need_inline do
- let!(:pipeline) { create_pipeline(project, sha, branch) }
-
- context 'pipeline success' do
- before do
- pipeline.success!
- end
-
- describe '#status' do
- it 'is successful' do
- expect(badge.status).to eq 'success'
- end
- end
- end
-
- context 'pipeline failed' do
- before do
- pipeline.drop!
- end
-
- describe '#status' do
- it 'failed' do
- expect(badge.status).to eq 'failed'
- end
- end
- end
-
- context 'when outdated pipeline for given ref exists' do
- before do
- pipeline.success!
-
- old_pipeline = create_pipeline(project, '11eeffdd', branch)
- old_pipeline.drop!
- end
-
- it 'does not take outdated pipeline into account' do
- expect(badge.status).to eq 'success'
- end
- end
-
- context 'when multiple pipelines exist for given sha' do
- before do
- pipeline.drop!
-
- new_pipeline = create_pipeline(project, sha, branch)
- new_pipeline.success!
- end
-
- it 'does not take outdated pipeline into account' do
- expect(badge.status).to eq 'success'
- end
- end
-
- context 'when ignored_skipped is set to true' do
- let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: true }) }
-
- before do
- pipeline.skip!
- end
-
- describe '#status' do
- it 'uses latest non-skipped status' do
- expect(new_badge.status).not_to eq 'skipped'
- end
- end
- end
-
- context 'when ignored_skipped is set to false' do
- let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: false }) }
-
- before do
- pipeline.skip!
- end
-
- describe '#status' do
- it 'uses latest status' do
- expect(new_badge.status).to eq 'skipped'
- end
- end
- end
- end
-
- context 'build does not exist' do
- describe '#status' do
- it 'is unknown' do
- expect(badge.status).to eq 'unknown'
- end
- end
- end
-
- def create_pipeline(project, sha, branch)
- pipeline = create(:ci_empty_pipeline,
- project: project,
- sha: sha,
- ref: branch)
-
- create(:ci_build, pipeline: pipeline, stage: 'notify')
- end
-end
diff --git a/spec/lib/gitlab/badge/pipeline/template_spec.rb b/spec/lib/gitlab/badge/pipeline/template_spec.rb
deleted file mode 100644
index c78e95852f3..00000000000
--- a/spec/lib/gitlab/badge/pipeline/template_spec.rb
+++ /dev/null
@@ -1,140 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Badge::Pipeline::Template do
- let(:badge) { double(entity: 'pipeline', status: 'success', customization: {}) }
- let(:template) { described_class.new(badge) }
-
- describe '#key_text' do
- it 'says pipeline by default' do
- expect(template.key_text).to eq 'pipeline'
- end
-
- context 'when custom key_text is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 'custom text' })
- end
-
- it 'returns custom value' do
- expect(template.key_text).to eq 'custom text'
- end
-
- context 'when its size is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
- end
-
- it 'returns default value' do
- expect(template.key_text).to eq 'pipeline'
- end
- end
- end
- end
-
- describe '#value_text' do
- it 'is status value' do
- expect(template.value_text).to eq 'passed'
- end
- end
-
- describe '#key_width' do
- it 'is fixed by default' do
- expect(template.key_width).to eq 62
- end
-
- context 'when custom key_width is defined' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 101 })
- end
-
- it 'returns custom value' do
- expect(template.key_width).to eq 101
- end
-
- context 'when it is larger than the max allowed value' do
- before do
- allow(badge).to receive(:customization).and_return({ key_width: 513 })
- end
-
- it 'returns default value' do
- expect(template.key_width).to eq 62
- end
- end
- end
- end
-
- describe 'widths and text anchors' do
- it 'has fixed width and text anchors' do
- expect(template.width).to eq 116
- expect(template.key_width).to eq 62
- expect(template.value_width).to eq 54
- expect(template.key_text_anchor).to eq 31
- expect(template.value_text_anchor).to eq 89
- end
- end
-
- describe '#key_color' do
- it 'is always the same' do
- expect(template.key_color).to eq '#555'
- end
- end
-
- describe '#value_color' do
- context 'when status is success' do
- it 'has expected color' do
- expect(template.value_color).to eq '#4c1'
- end
- end
-
- context 'when status is failed' do
- before do
- allow(badge).to receive(:status).and_return('failed')
- end
-
- it 'has expected color' do
- expect(template.value_color).to eq '#e05d44'
- end
- end
-
- context 'when status is running' do
- before do
- allow(badge).to receive(:status).and_return('running')
- end
-
- it 'has expected color' do
- expect(template.value_color).to eq '#dfb317'
- end
- end
-
- context 'when status is preparing' do
- before do
- allow(badge).to receive(:status).and_return('preparing')
- end
-
- it 'has expected color' do
- expect(template.value_color).to eq '#a7a7a7'
- end
- end
-
- context 'when status is unknown' do
- before do
- allow(badge).to receive(:status).and_return('unknown')
- end
-
- it 'has expected color' do
- expect(template.value_color).to eq '#9f9f9f'
- end
- end
-
- context 'when status does not match any known statuses' do
- before do
- allow(badge).to receive(:status).and_return('invalid')
- end
-
- it 'has expected color' do
- expect(template.value_color).to eq '#9f9f9f'
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/changelog/ast_spec.rb b/spec/lib/gitlab/changelog/ast_spec.rb
new file mode 100644
index 00000000000..fa15ac979fe
--- /dev/null
+++ b/spec/lib/gitlab/changelog/ast_spec.rb
@@ -0,0 +1,246 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::AST::Identifier do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+
+ describe '#evaluate' do
+ it 'evaluates a selector' do
+ data = { 'number' => 10 }
+
+ expect(described_class.new('number').evaluate(state, data)).to eq(10)
+ end
+
+ it 'returns nil if the key is not set' do
+ expect(described_class.new('number').evaluate(state, {})).to be_nil
+ end
+
+ it 'returns nil if the input is not a Hash' do
+ expect(described_class.new('number').evaluate(state, 45)).to be_nil
+ end
+
+ it 'returns the current data when using the special identifier "it"' do
+ expect(described_class.new('it').evaluate(state, 45)).to eq(45)
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::Integer do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+
+ describe '#evaluate' do
+ it 'evaluates a selector' do
+ expect(described_class.new(0).evaluate(state, [10])).to eq(10)
+ end
+
+ it 'returns nil if the index is not set' do
+ expect(described_class.new(1).evaluate(state, [10])).to be_nil
+ end
+
+ it 'returns nil if the input is not an Array' do
+ expect(described_class.new(0).evaluate(state, {})).to be_nil
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::Selector do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+ let(:data) { { 'numbers' => [10] } }
+
+ describe '#evaluate' do
+ it 'evaluates a selector' do
+ ident = Gitlab::Changelog::AST::Identifier.new('numbers')
+ int = Gitlab::Changelog::AST::Integer.new(0)
+
+ expect(described_class.new([ident, int]).evaluate(state, data)).to eq(10)
+ end
+
+ it 'evaluates a selector that returns nil' do
+ int = Gitlab::Changelog::AST::Integer.new(0)
+
+ expect(described_class.new([int]).evaluate(state, data)).to be_nil
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::Variable do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+ let(:data) { { 'numbers' => [10] } }
+
+ describe '#evaluate' do
+ it 'evaluates a variable' do
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{{numbers.0}}')
+ .nodes[0]
+
+ expect(node.evaluate(state, data)).to eq('10')
+ end
+
+ it 'evaluates an undefined variable' do
+ node =
+ Gitlab::Changelog::Parser.new.parse_and_transform('{{foobar}}').nodes[0]
+
+ expect(node.evaluate(state, data)).to eq('')
+ end
+
+ it 'evaluates the special variable "it"' do
+ node =
+ Gitlab::Changelog::Parser.new.parse_and_transform('{{it}}').nodes[0]
+
+ expect(node.evaluate(state, data)).to eq(data.to_s)
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::Expressions do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+
+ describe '#evaluate' do
+ it 'evaluates all expressions' do
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{{number}}foo')
+
+ expect(node.evaluate(state, { 'number' => 10 })).to eq('10foo')
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::Text do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+
+ describe '#evaluate' do
+ it 'returns the text' do
+ expect(described_class.new('foo').evaluate(state, {})).to eq('foo')
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::If do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+
+ describe '#evaluate' do
+ it 'evaluates a truthy if expression without an else clause' do
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{% if thing %}foo{% end %}')
+ .nodes[0]
+
+ expect(node.evaluate(state, { 'thing' => true })).to eq('foo')
+ end
+
+ it 'evaluates a falsy if expression without an else clause' do
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{% if thing %}foo{% end %}')
+ .nodes[0]
+
+ expect(node.evaluate(state, { 'thing' => false })).to eq('')
+ end
+
+ it 'evaluates a falsy if expression with an else clause' do
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{% if thing %}foo{% else %}bar{% end %}')
+ .nodes[0]
+
+ expect(node.evaluate(state, { 'thing' => false })).to eq('bar')
+ end
+ end
+
+ describe '#truthy?' do
+ it 'returns true for a non-empty String' do
+ expect(described_class.new.truthy?('foo')).to eq(true)
+ end
+
+ it 'returns true for a non-empty Array' do
+ expect(described_class.new.truthy?([10])).to eq(true)
+ end
+
+ it 'returns true for a Boolean true' do
+ expect(described_class.new.truthy?(true)).to eq(true)
+ end
+
+ it 'returns false for an empty String' do
+ expect(described_class.new.truthy?('')).to eq(false)
+ end
+
+ it 'returns true for an empty Array' do
+ expect(described_class.new.truthy?([])).to eq(false)
+ end
+
+ it 'returns false for a Boolean false' do
+ expect(described_class.new.truthy?(false)).to eq(false)
+ end
+ end
+end
+
+RSpec.describe Gitlab::Changelog::AST::Each do
+ let(:state) { Gitlab::Changelog::EvalState.new }
+
+ describe '#evaluate' do
+ it 'evaluates the expression' do
+ data = { 'animals' => [{ 'name' => 'Cat' }, { 'name' => 'Dog' }] }
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{% each animals %}{{name}}{% end %}')
+ .nodes[0]
+
+ expect(node.evaluate(state, data)).to eq('CatDog')
+ end
+
+ it 'returns an empty string when the input is not a collection' do
+ data = { 'animals' => 10 }
+ node = Gitlab::Changelog::Parser
+ .new
+ .parse_and_transform('{% each animals %}{{name}}{% end %}')
+ .nodes[0]
+
+ expect(node.evaluate(state, data)).to eq('')
+ end
+
+ it 'disallows too many nested loops' do
+ data = {
+ 'foo' => [
+ {
+ 'bar' => [
+ {
+ 'baz' => [
+ {
+ 'quix' => [
+ {
+ 'foo' => [{ 'name' => 'Alice' }]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+
+ template = <<~TPL
+ {% each foo %}
+ {% each bar %}
+ {% each baz %}
+ {% each quix %}
+ {% each foo %}
+ {{name}}
+ {% end %}
+ {% end %}
+ {% end %}
+ {% end %}
+ {% end %}
+ TPL
+
+ node =
+ Gitlab::Changelog::Parser.new.parse_and_transform(template).nodes[0]
+
+ expect { node.evaluate(state, data) }
+ .to raise_error(Gitlab::Changelog::Error)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/committer_spec.rb b/spec/lib/gitlab/changelog/committer_spec.rb
new file mode 100644
index 00000000000..1e04fe346cb
--- /dev/null
+++ b/spec/lib/gitlab/changelog/committer_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Committer do
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.creator }
+ let(:committer) { described_class.new(project, user) }
+ let(:config) { Gitlab::Changelog::Config.new(project) }
+
+ describe '#commit' do
+ context "when the release isn't in the changelog" do
+ it 'commits the changes' do
+ release = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ committer.commit(
+ release: release,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+
+ content = project.repository.blob_at('master', 'CHANGELOG.md').data
+
+ expect(content).to eq(<<~MARKDOWN)
+ ## 1.0.0 (2020-01-01)
+
+ No changes.
+ MARKDOWN
+ end
+ end
+
+ context 'when the release is already in the changelog' do
+ it "doesn't commit the changes" do
+ release = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ 2.times do
+ committer.commit(
+ release: release,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+ end
+
+ content = project.repository.blob_at('master', 'CHANGELOG.md').data
+
+ expect(content).to eq(<<~MARKDOWN)
+ ## 1.0.0 (2020-01-01)
+
+ No changes.
+ MARKDOWN
+ end
+ end
+
+ context 'when committing the changes fails' do
+ it 'retries the operation' do
+ release = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ service = instance_spy(Files::MultiService)
+ errored = false
+
+ allow(Files::MultiService)
+ .to receive(:new)
+ .and_return(service)
+
+ allow(service).to receive(:execute) do
+ if errored
+ { status: :success }
+ else
+ errored = true
+ { status: :error }
+ end
+ end
+
+ expect do
+ committer.commit(
+ release: release,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+ end.not_to raise_error
+ end
+ end
+
+ context "when the changelog changes before saving the changes" do
+ it 'raises a Error' do
+ release1 = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ release2 = Gitlab::Changelog::Release
+ .new(version: '2.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ # This creates the initial commit we'll later use to see if the
+ # changelog changed before saving our changes.
+ committer.commit(
+ release: release1,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Initial commit'
+ )
+
+ allow(Gitlab::Git::Commit)
+ .to receive(:last_for_path)
+ .with(
+ project.repository,
+ 'master',
+ 'CHANGELOG.md',
+ literal_pathspec: true
+ )
+ .and_return(double(:commit, sha: 'foo'))
+
+ expect do
+ committer.commit(
+ release: release2,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+ end.to raise_error(Gitlab::Changelog::Error)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/config_spec.rb b/spec/lib/gitlab/changelog/config_spec.rb
new file mode 100644
index 00000000000..51988acf3d1
--- /dev/null
+++ b/spec/lib/gitlab/changelog/config_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Config do
+ let(:project) { build_stubbed(:project) }
+
+ describe '.from_git' do
+ it 'retrieves the configuration from Git' do
+ allow(project.repository)
+ .to receive(:changelog_config)
+ .and_return("---\ndate_format: '%Y'")
+
+ expect(described_class)
+ .to receive(:from_hash)
+ .with(project, 'date_format' => '%Y')
+
+ described_class.from_git(project)
+ end
+
+ it 'returns the default configuration when no YAML file exists in Git' do
+ allow(project.repository)
+ .to receive(:changelog_config)
+ .and_return(nil)
+
+ expect(described_class)
+ .to receive(:new)
+ .with(project)
+
+ described_class.from_git(project)
+ end
+ end
+
+ describe '.from_hash' do
+ it 'sets the configuration according to a Hash' do
+ config = described_class.from_hash(
+ project,
+ 'date_format' => 'foo',
+ 'template' => 'bar',
+ 'categories' => { 'foo' => 'bar' }
+ )
+
+ expect(config.date_format).to eq('foo')
+ expect(config.template)
+ .to be_instance_of(Gitlab::Changelog::AST::Expressions)
+
+ expect(config.categories).to eq({ 'foo' => 'bar' })
+ end
+
+ it 'raises Error when the categories are not a Hash' do
+ expect { described_class.from_hash(project, 'categories' => 10) }
+ .to raise_error(Gitlab::Changelog::Error)
+ end
+ end
+
+ describe '#contributor?' do
+ it 'returns true if a user is a contributor' do
+ user = build_stubbed(:author)
+
+ allow(project.team).to receive(:contributor?).with(user).and_return(true)
+
+ expect(described_class.new(project).contributor?(user)).to eq(true)
+ end
+
+ it "returns true if a user isn't a contributor" do
+ user = build_stubbed(:author)
+
+ allow(project.team).to receive(:contributor?).with(user).and_return(false)
+
+ expect(described_class.new(project).contributor?(user)).to eq(false)
+ end
+ end
+
+ describe '#category' do
+ it 'returns the name of a category' do
+ config = described_class.new(project)
+
+ config.categories['foo'] = 'Foo'
+
+ expect(config.category('foo')).to eq('Foo')
+ end
+
+ it 'returns the raw category name when no alternative name is configured' do
+ config = described_class.new(project)
+
+ expect(config.category('bla')).to eq('bla')
+ end
+ end
+
+ describe '#format_date' do
+ it 'formats a date according to the configured date format' do
+ config = described_class.new(project)
+ time = Time.utc(2021, 1, 5)
+
+ expect(config.format_date(time)).to eq('2021-01-05')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/generator_spec.rb b/spec/lib/gitlab/changelog/generator_spec.rb
new file mode 100644
index 00000000000..bc4a7c5dd6b
--- /dev/null
+++ b/spec/lib/gitlab/changelog/generator_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Generator do
+ describe '#add' do
+ let(:project) { build_stubbed(:project) }
+ let(:author) { build_stubbed(:user) }
+ let(:commit) { build_stubbed(:commit) }
+ let(:config) { Gitlab::Changelog::Config.new(project) }
+
+ it 'generates the Markdown for the first release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '1.0.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new('')
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ ## 1.0.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+ MARKDOWN
+ end
+
+ it 'generates the Markdown for a newer release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '2.0.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+ end
+
+ it 'generates the Markdown for a patch release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '1.1.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.1.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+ end
+
+ it 'generates the Markdown for an old release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '0.5.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+
+ ## 0.5.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+ MARKDOWN
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/parser_spec.rb b/spec/lib/gitlab/changelog/parser_spec.rb
new file mode 100644
index 00000000000..1d353f5eb35
--- /dev/null
+++ b/spec/lib/gitlab/changelog/parser_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Parser do
+ let(:parser) { described_class.new }
+
+ describe '#root' do
+ it 'parses an empty template' do
+ expect(parser.root).to parse('')
+ end
+
+ it 'parses a variable with a single identifier step' do
+ expect(parser.root).to parse('{{foo}}')
+ end
+
+ it 'parses a variable with a single integer step' do
+ expect(parser.root).to parse('{{0}}')
+ end
+
+ it 'parses a variable with multiple selector steps' do
+ expect(parser.root).to parse('{{foo.bar}}')
+ end
+
+ it 'parses a variable with an integer selector step' do
+ expect(parser.root).to parse('{{foo.bar.0}}')
+ end
+
+ it 'parses the special "it" variable' do
+ expect(parser.root).to parse('{{it}}')
+ end
+
+ it 'parses a text node' do
+ expect(parser.root).to parse('foo')
+ end
+
+ it 'parses an if expression' do
+ expect(parser.root).to parse('{% if foo %}bar{% end %}')
+ end
+
+ it 'parses an if-else expression' do
+ expect(parser.root).to parse('{% if foo %}bar{% else %}baz{% end %}')
+ end
+
+ it 'parses an each expression' do
+ expect(parser.root).to parse('{% each foo %}foo{% end %}')
+ end
+
+ it 'parses an escaped newline' do
+ expect(parser.root).to parse("foo\\\nbar")
+ end
+
+ it 'parses a regular newline' do
+ expect(parser.root).to parse("foo\nbar")
+ end
+
+ it 'parses the default changelog template' do
+ expect(parser.root).to parse(Gitlab::Changelog::Config::DEFAULT_TEMPLATE)
+ end
+
+ it 'raises an error when parsing an integer selector that is too large' do
+ expect(parser.root).not_to parse('{{100000000000}}')
+ end
+ end
+
+ describe '#parse_and_transform' do
+ it 'parses and transforms a template' do
+ node = parser.parse_and_transform('foo')
+
+ expect(node).to be_instance_of(Gitlab::Changelog::AST::Expressions)
+ end
+
+ it 'raises parsing errors using a custom error class' do
+ expect { parser.parse_and_transform('{% each') }
+ .to raise_error(Gitlab::Changelog::Error)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/release_spec.rb b/spec/lib/gitlab/changelog/release_spec.rb
new file mode 100644
index 00000000000..f95244d6750
--- /dev/null
+++ b/spec/lib/gitlab/changelog/release_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Release do
+ describe '#to_markdown' do
+ let(:config) { Gitlab::Changelog::Config.new(build_stubbed(:project)) }
+ let(:commit) { build_stubbed(:commit) }
+ let(:author) { build_stubbed(:user) }
+ let(:mr) { build_stubbed(:merge_request) }
+ let(:release) do
+ described_class
+ .new(version: '1.0.0', date: Time.utc(2021, 1, 5), config: config)
+ end
+
+ context 'when there are no entries' do
+ it 'includes a notice about the lack of entries' do
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ No changes.
+
+ OUT
+ end
+ end
+
+ context 'when all data is present' do
+ it 'includes all data' do
+ allow(config).to receive(:contributor?).with(author).and_return(true)
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed',
+ author: author,
+ merge_request: mr
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### fixed (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)}) \
+ by #{author.to_reference(full: true)} \
+ ([merge request](#{mr.to_reference(full: true)}))
+
+ OUT
+ end
+ end
+
+ context 'when no merge request is present' do
+ it "doesn't include a merge request link" do
+ allow(config).to receive(:contributor?).with(author).and_return(true)
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed',
+ author: author
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### fixed (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)}) \
+ by #{author.to_reference(full: true)}
+
+ OUT
+ end
+ end
+
+ context 'when the author is not a contributor' do
+ it "doesn't include the author" do
+ allow(config).to receive(:contributor?).with(author).and_return(false)
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed',
+ author: author
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### fixed (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)})
+
+ OUT
+ end
+ end
+
+ context 'when a category has no entries' do
+ it "isn't included in the output" do
+ config.categories['kittens'] = 'Kittens'
+ config.categories['fixed'] = 'Bug fixes'
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed'
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### Bug fixes (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)})
+
+ OUT
+ end
+ end
+ end
+
+ describe '#header_start_position' do
+ it 'returns a regular expression for finding the start of a release section' do
+ config = Gitlab::Changelog::Config.new(build_stubbed(:project))
+ release = described_class
+ .new(version: '1.0.0', date: Time.utc(2021, 1, 5), config: config)
+
+ expect(release.header_start_pattern).to eq(/^##\s*1\.0\.0/)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/coverage/metadata_spec.rb b/spec/lib/gitlab/ci/badge/coverage/metadata_spec.rb
new file mode 100644
index 00000000000..6d272f060ab
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/coverage/metadata_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'lib/gitlab/ci/badge/shared/metadata'
+
+RSpec.describe Gitlab::Ci::Badge::Coverage::Metadata do
+ let(:badge) do
+ double(project: create(:project), ref: 'feature', job: 'test')
+ end
+
+ let(:metadata) { described_class.new(badge) }
+
+ it_behaves_like 'badge metadata'
+
+ describe '#title' do
+ it 'returns coverage report title' do
+ expect(metadata.title).to eq 'coverage report'
+ end
+ end
+
+ describe '#image_url' do
+ it 'returns valid url' do
+ expect(metadata.image_url).to include 'badges/feature/coverage.svg'
+ end
+ end
+
+ describe '#link_url' do
+ it 'returns valid link' do
+ expect(metadata.link_url).to include 'commits/feature'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/coverage/report_spec.rb b/spec/lib/gitlab/ci/badge/coverage/report_spec.rb
new file mode 100644
index 00000000000..13696d815aa
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/coverage/report_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Badge::Coverage::Report do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:success_pipeline) { create(:ci_pipeline, :success, project: project) }
+ let_it_be(:running_pipeline) { create(:ci_pipeline, :running, project: project) }
+ let_it_be(:failure_pipeline) { create(:ci_pipeline, :failed, project: project) }
+
+ let_it_be(:builds) do
+ [
+ create(:ci_build, :success, pipeline: success_pipeline, coverage: 40, created_at: 9.seconds.ago, name: 'coverage'),
+ create(:ci_build, :success, pipeline: success_pipeline, coverage: 60, created_at: 8.seconds.ago)
+ ]
+ end
+
+ let(:badge) do
+ described_class.new(project, 'master', opts: { job: job_name })
+ end
+
+ let(:job_name) { nil }
+
+ describe '#entity' do
+ it 'describes a coverage' do
+ expect(badge.entity).to eq 'coverage'
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns correct metadata' do
+ expect(badge.metadata.image_url).to include 'coverage.svg'
+ end
+ end
+
+ describe '#template' do
+ it 'returns correct template' do
+ expect(badge.template.key_text).to eq 'coverage'
+ end
+ end
+
+ describe '#status' do
+ context 'with no job specified' do
+ it 'returns the most recent successful pipeline coverage value' do
+ expect(badge.status).to eq(50.00)
+ end
+
+ context 'and no successful pipelines' do
+ before do
+ allow(badge).to receive(:successful_pipeline).and_return(nil)
+ end
+
+ it 'returns nil' do
+ expect(badge.status).to eq(nil)
+ end
+ end
+ end
+
+ context 'with a blank job name' do
+ let(:job_name) { ' ' }
+
+ it 'returns the latest successful pipeline coverage value' do
+ expect(badge.status).to eq(50.00)
+ end
+ end
+
+ context 'with an unmatching job name specified' do
+ let(:job_name) { 'incorrect name' }
+
+ it 'returns nil' do
+ expect(badge.status).to be_nil
+ end
+ end
+
+ context 'with a matching job name specified' do
+ let(:job_name) { 'coverage' }
+
+ it 'returns the pipeline coverage value' do
+ expect(badge.status).to eq(40.00)
+ end
+
+ context 'with a more recent running pipeline' do
+ let!(:another_build) { create(:ci_build, :success, pipeline: running_pipeline, coverage: 20, created_at: 7.seconds.ago, name: 'coverage') }
+
+ it 'returns the running pipeline coverage value' do
+ expect(badge.status).to eq(20.00)
+ end
+ end
+
+ context 'with a more recent failed pipeline' do
+ let!(:another_build) { create(:ci_build, :success, pipeline: failure_pipeline, coverage: 10, created_at: 6.seconds.ago, name: 'coverage') }
+
+ it 'returns the failed pipeline coverage value' do
+ expect(badge.status).to eq(10.00)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/coverage/template_spec.rb b/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
new file mode 100644
index 00000000000..f010d1bce50
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/coverage/template_spec.rb
@@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Badge::Coverage::Template do
+ let(:badge) { double(entity: 'coverage', status: 90.00, customization: {}) }
+ let(:template) { described_class.new(badge) }
+
+ describe '#key_text' do
+ it 'says coverage by default' do
+ expect(template.key_text).to eq 'coverage'
+ end
+
+ context 'when custom key_text is defined' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_text: "custom text" })
+ end
+
+ it 'returns custom value' do
+ expect(template.key_text).to eq "custom text"
+ end
+
+ context 'when its size is larger than the max allowed value' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
+ end
+
+ it 'returns default value' do
+ expect(template.key_text).to eq 'coverage'
+ end
+ end
+ end
+ end
+
+ describe '#value_text' do
+ context 'when coverage is known' do
+ it 'returns coverage percentage' do
+ expect(template.value_text).to eq '90.00%'
+ end
+ end
+
+ context 'when coverage is known to many digits' do
+ before do
+ allow(badge).to receive(:status).and_return(92.349)
+ end
+
+ it 'returns rounded coverage percentage' do
+ expect(template.value_text).to eq '92.35%'
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'returns string that says coverage is unknown' do
+ expect(template.value_text).to eq 'unknown'
+ end
+ end
+ end
+
+ describe '#key_width' do
+ it 'is fixed by default' do
+ expect(template.key_width).to eq 62
+ end
+
+ context 'when custom key_width is defined' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_width: 101 })
+ end
+
+ it 'returns custom value' do
+ expect(template.key_width).to eq 101
+ end
+
+ context 'when it is larger than the max allowed value' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_width: 513 })
+ end
+
+ it 'returns default value' do
+ expect(template.key_width).to eq 62
+ end
+ end
+ end
+ end
+
+ describe '#value_width' do
+ context 'when coverage is known' do
+ it 'is narrower when coverage is known' do
+ expect(template.value_width).to eq 54
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'is wider when coverage is unknown to fit text' do
+ expect(template.value_width).to eq 58
+ end
+ 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 coverage is good' do
+ before do
+ allow(badge).to receive(:status).and_return(98)
+ end
+
+ it 'is green' do
+ expect(template.value_color).to eq '#4c1'
+ end
+ end
+
+ context 'when coverage is acceptable' do
+ before do
+ allow(badge).to receive(:status).and_return(90)
+ end
+
+ it 'is green-orange' do
+ expect(template.value_color).to eq '#a3c51c'
+ end
+ end
+
+ context 'when coverage is medium' do
+ before do
+ allow(badge).to receive(:status).and_return(75)
+ end
+
+ it 'is orange-yellow' do
+ expect(template.value_color).to eq '#dfb317'
+ end
+ end
+
+ context 'when coverage is low' do
+ before do
+ allow(badge).to receive(:status).and_return(50)
+ end
+
+ it 'is red' do
+ expect(template.value_color).to eq '#e05d44'
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'is grey' do
+ expect(template.value_color).to eq '#9f9f9f'
+ end
+ end
+ end
+
+ describe '#width' do
+ context 'when coverage is known' do
+ it 'returns the key width plus value width' do
+ expect(template.width).to eq 116
+ end
+ end
+
+ context 'when coverage is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return(nil)
+ end
+
+ it 'returns key width plus wider value width' do
+ expect(template.width).to eq 120
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/pipeline/metadata_spec.rb b/spec/lib/gitlab/ci/badge/pipeline/metadata_spec.rb
new file mode 100644
index 00000000000..2f677237fad
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/pipeline/metadata_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'lib/gitlab/ci/badge/shared/metadata'
+
+RSpec.describe Gitlab::Ci::Badge::Pipeline::Metadata do
+ let(:badge) { double(project: create(:project), ref: 'feature') }
+ let(:metadata) { described_class.new(badge) }
+
+ it_behaves_like 'badge metadata'
+
+ describe '#title' do
+ it 'returns build status title' do
+ expect(metadata.title).to eq 'pipeline status'
+ end
+ end
+
+ describe '#image_url' do
+ it 'returns valid url' do
+ expect(metadata.image_url).to include 'badges/feature/pipeline.svg'
+ end
+ end
+
+ describe '#link_url' do
+ it 'returns valid link' do
+ expect(metadata.link_url).to include 'commits/feature'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/pipeline/status_spec.rb b/spec/lib/gitlab/ci/badge/pipeline/status_spec.rb
new file mode 100644
index 00000000000..45d0d781090
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/pipeline/status_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Badge::Pipeline::Status do
+ let(:project) { create(:project, :repository) }
+ let(:sha) { project.commit.sha }
+ let(:branch) { 'master' }
+ let(:badge) { described_class.new(project, branch) }
+
+ describe '#entity' do
+ it 'always says pipeline' do
+ expect(badge.entity).to eq 'pipeline'
+ end
+ end
+
+ describe '#template' do
+ it 'returns badge template' do
+ expect(badge.template.key_text).to eq 'pipeline'
+ end
+ end
+
+ describe '#metadata' do
+ it 'returns badge metadata' do
+ expect(badge.metadata.image_url).to include 'badges/master/pipeline.svg'
+ end
+ end
+
+ context 'pipeline exists', :sidekiq_might_not_need_inline do
+ let!(:pipeline) { create_pipeline(project, sha, branch) }
+
+ context 'pipeline success' do
+ before do
+ pipeline.success!
+ end
+
+ describe '#status' do
+ it 'is successful' do
+ expect(badge.status).to eq 'success'
+ end
+ end
+ end
+
+ context 'pipeline failed' do
+ before do
+ pipeline.drop!
+ end
+
+ describe '#status' do
+ it 'failed' do
+ expect(badge.status).to eq 'failed'
+ end
+ end
+ end
+
+ context 'when outdated pipeline for given ref exists' do
+ before do
+ pipeline.success!
+
+ old_pipeline = create_pipeline(project, '11eeffdd', branch)
+ old_pipeline.drop!
+ end
+
+ it 'does not take outdated pipeline into account' do
+ expect(badge.status).to eq 'success'
+ end
+ end
+
+ context 'when multiple pipelines exist for given sha' do
+ before do
+ pipeline.drop!
+
+ new_pipeline = create_pipeline(project, sha, branch)
+ new_pipeline.success!
+ end
+
+ it 'does not take outdated pipeline into account' do
+ expect(badge.status).to eq 'success'
+ end
+ end
+
+ context 'when ignored_skipped is set to true' do
+ let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: true }) }
+
+ before do
+ pipeline.skip!
+ end
+
+ describe '#status' do
+ it 'uses latest non-skipped status' do
+ expect(new_badge.status).not_to eq 'skipped'
+ end
+ end
+ end
+
+ context 'when ignored_skipped is set to false' do
+ let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: false }) }
+
+ before do
+ pipeline.skip!
+ end
+
+ describe '#status' do
+ it 'uses latest status' do
+ expect(new_badge.status).to eq 'skipped'
+ end
+ end
+ end
+ end
+
+ context 'build does not exist' do
+ describe '#status' do
+ it 'is unknown' do
+ expect(badge.status).to eq 'unknown'
+ end
+ end
+ end
+
+ def create_pipeline(project, sha, branch)
+ pipeline = create(:ci_empty_pipeline,
+ project: project,
+ sha: sha,
+ ref: branch)
+
+ create(:ci_build, pipeline: pipeline, stage: 'notify')
+ end
+end
diff --git a/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb b/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
new file mode 100644
index 00000000000..696bb62b4d6
--- /dev/null
+++ b/spec/lib/gitlab/ci/badge/pipeline/template_spec.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Badge::Pipeline::Template do
+ let(:badge) { double(entity: 'pipeline', status: 'success', customization: {}) }
+ let(:template) { described_class.new(badge) }
+
+ describe '#key_text' do
+ it 'says pipeline by default' do
+ expect(template.key_text).to eq 'pipeline'
+ end
+
+ context 'when custom key_text is defined' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_text: 'custom text' })
+ end
+
+ it 'returns custom value' do
+ expect(template.key_text).to eq 'custom text'
+ end
+
+ context 'when its size is larger than the max allowed value' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
+ end
+
+ it 'returns default value' do
+ expect(template.key_text).to eq 'pipeline'
+ end
+ end
+ end
+ end
+
+ describe '#value_text' do
+ it 'is status value' do
+ expect(template.value_text).to eq 'passed'
+ end
+ end
+
+ describe '#key_width' do
+ it 'is fixed by default' do
+ expect(template.key_width).to eq 62
+ end
+
+ context 'when custom key_width is defined' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_width: 101 })
+ end
+
+ it 'returns custom value' do
+ expect(template.key_width).to eq 101
+ end
+
+ context 'when it is larger than the max allowed value' do
+ before do
+ allow(badge).to receive(:customization).and_return({ key_width: 513 })
+ end
+
+ it 'returns default value' do
+ expect(template.key_width).to eq 62
+ end
+ end
+ end
+ end
+
+ describe 'widths and text anchors' do
+ it 'has fixed width and text anchors' do
+ expect(template.width).to eq 116
+ expect(template.key_width).to eq 62
+ expect(template.value_width).to eq 54
+ expect(template.key_text_anchor).to eq 31
+ expect(template.value_text_anchor).to eq 89
+ end
+ end
+
+ describe '#key_color' do
+ it 'is always the same' do
+ expect(template.key_color).to eq '#555'
+ end
+ end
+
+ describe '#value_color' do
+ context 'when status is success' do
+ it 'has expected color' do
+ expect(template.value_color).to eq '#4c1'
+ end
+ end
+
+ context 'when status is failed' do
+ before do
+ allow(badge).to receive(:status).and_return('failed')
+ end
+
+ it 'has expected color' do
+ expect(template.value_color).to eq '#e05d44'
+ end
+ end
+
+ context 'when status is running' do
+ before do
+ allow(badge).to receive(:status).and_return('running')
+ end
+
+ it 'has expected color' do
+ expect(template.value_color).to eq '#dfb317'
+ end
+ end
+
+ context 'when status is preparing' do
+ before do
+ allow(badge).to receive(:status).and_return('preparing')
+ end
+
+ it 'has expected color' do
+ expect(template.value_color).to eq '#a7a7a7'
+ end
+ end
+
+ context 'when status is unknown' do
+ before do
+ allow(badge).to receive(:status).and_return('unknown')
+ end
+
+ it 'has expected color' do
+ expect(template.value_color).to eq '#9f9f9f'
+ end
+ end
+
+ context 'when status does not match any known statuses' do
+ before do
+ allow(badge).to receive(:status).and_return('invalid')
+ end
+
+ it 'has expected color' do
+ expect(template.value_color).to eq '#9f9f9f'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/badge/shared/metadata.rb b/spec/lib/gitlab/ci/badge/shared/metadata.rb
index c99a65bb2f4..c99a65bb2f4 100644
--- a/spec/lib/gitlab/badge/shared/metadata.rb
+++ b/spec/lib/gitlab/ci/badge/shared/metadata.rb
diff --git a/spec/lib/gitlab/ci/build/credentials/registry/dependency_proxy_spec.rb b/spec/lib/gitlab/ci/build/credentials/registry/dependency_proxy_spec.rb
new file mode 100644
index 00000000000..f50c6e99e99
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/credentials/registry/dependency_proxy_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Build::Credentials::Registry::DependencyProxy do
+ let(:build) { create(:ci_build, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let(:gitlab_url) { 'gitlab.example.com:443' }
+
+ subject { described_class.new(build) }
+
+ before do
+ stub_config_setting(host: 'gitlab.example.com', port: 443)
+ end
+
+ it 'contains valid dependency proxy credentials' do
+ expect(subject).to be_kind_of(described_class)
+
+ expect(subject.username).to eq 'gitlab-ci-token'
+ expect(subject.password).to eq build.token
+ expect(subject.url).to eq gitlab_url
+ expect(subject.type).to eq 'registry'
+ end
+
+ describe '.valid?' do
+ subject { described_class.new(build).valid? }
+
+ context 'when dependency proxy is enabled' do
+ before do
+ stub_config(dependency_proxy: { enabled: true })
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when dependency proxy is disabled' do
+ before do
+ stub_config(dependency_proxy: { enabled: false })
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/credentials/registry/gitlab_registry_spec.rb b/spec/lib/gitlab/ci/build/credentials/registry/gitlab_registry_spec.rb
new file mode 100644
index 00000000000..43913e91085
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/credentials/registry/gitlab_registry_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Build::Credentials::Registry::GitlabRegistry do
+ let(:build) { create(:ci_build, name: 'spinach', stage: 'test', stage_idx: 0) }
+ let(:registry_url) { 'registry.example.com:5005' }
+
+ subject { described_class.new(build) }
+
+ before do
+ stub_container_registry_config(host_port: registry_url)
+ end
+
+ it 'contains valid DockerRegistry credentials' do
+ expect(subject).to be_kind_of(described_class)
+
+ expect(subject.username).to eq 'gitlab-ci-token'
+ expect(subject.password).to eq build.token
+ expect(subject.url).to eq registry_url
+ expect(subject.type).to eq 'registry'
+ end
+
+ describe '.valid?' do
+ subject { described_class.new(build).valid? }
+
+ context 'when registry is enabled' do
+ before do
+ stub_container_registry_config(enabled: true)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when registry is disabled' do
+ before do
+ stub_container_registry_config(enabled: false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/credentials/registry_spec.rb b/spec/lib/gitlab/ci/build/credentials/registry_spec.rb
deleted file mode 100644
index c0a76973f60..00000000000
--- a/spec/lib/gitlab/ci/build/credentials/registry_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Ci::Build::Credentials::Registry do
- let(:build) { create(:ci_build, name: 'spinach', stage: 'test', stage_idx: 0) }
- let(:registry_url) { 'registry.example.com:5005' }
-
- subject { described_class.new(build) }
-
- before do
- stub_container_registry_config(host_port: registry_url)
- end
-
- it 'contains valid DockerRegistry credentials' do
- expect(subject).to be_kind_of(described_class)
-
- expect(subject.username).to eq 'gitlab-ci-token'
- expect(subject.password).to eq build.token
- expect(subject.url).to eq registry_url
- expect(subject.type).to eq 'registry'
- end
-
- describe '.valid?' do
- subject { described_class.new(build).valid? }
-
- context 'when registry is enabled' do
- before do
- stub_container_registry_config(enabled: true)
- end
-
- it { is_expected.to be_truthy }
- end
-
- context 'when registry is disabled' do
- before do
- stub_container_registry_config(enabled: false)
- end
-
- it { is_expected.to be_falsey }
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/build/rules_spec.rb b/spec/lib/gitlab/ci/build/rules_spec.rb
index a1af5b75f87..0b50def05d4 100644
--- a/spec/lib/gitlab/ci/build/rules_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules_spec.rb
@@ -201,40 +201,13 @@ RSpec.describe Gitlab::Ci::Build::Rules do
end
describe '#build_attributes' do
- let(:seed_attributes) { {} }
-
subject(:build_attributes) do
- result.build_attributes(seed_attributes)
+ result.build_attributes
end
it 'compacts nil values' do
is_expected.to eq(options: {}, when: 'on_success')
end
-
- context 'when there are variables in rules' do
- let(:variables) { { VAR1: 'new var 1', VAR3: 'var 3' } }
-
- context 'when there are seed variables' do
- let(:seed_attributes) do
- { yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true }] }
- end
-
- it 'returns yaml_variables with override' do
- is_expected.to include(
- yaml_variables: [{ key: 'VAR1', value: 'new var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }]
- )
- end
- end
-
- context 'when there is not seed variables' do
- it 'does not return yaml_variables' do
- is_expected.not_to have_key(:yaml_variables)
- end
- end
- end
end
describe '#pass?' do
diff --git a/spec/lib/gitlab/ci/charts_spec.rb b/spec/lib/gitlab/ci/charts_spec.rb
index cfc2019a89b..46d7d4a58f0 100644
--- a/spec/lib/gitlab/ci/charts_spec.rb
+++ b/spec/lib/gitlab/ci/charts_spec.rb
@@ -9,6 +9,10 @@ RSpec.describe Gitlab::Ci::Charts do
subject { chart.to }
+ before do
+ create(:ci_empty_pipeline, project: project, duration: 120)
+ end
+
it 'goes until the end of the current month (including the whole last day of the month)' do
is_expected.to eq(Date.today.end_of_month.end_of_day)
end
@@ -20,6 +24,10 @@ RSpec.describe Gitlab::Ci::Charts do
it 'uses %B %Y as labels format' do
expect(chart.labels).to include(chart.from.strftime('%B %Y'))
end
+
+ it 'returns count of pipelines run each day in the current year' do
+ expect(chart.total.sum).to eq(1)
+ end
end
context 'monthchart' do
@@ -28,6 +36,10 @@ RSpec.describe Gitlab::Ci::Charts do
subject { chart.to }
+ before do
+ create(:ci_empty_pipeline, project: project, duration: 120)
+ end
+
it 'includes the whole current day' do
is_expected.to eq(Date.today.end_of_day)
end
@@ -39,6 +51,10 @@ RSpec.describe Gitlab::Ci::Charts do
it 'uses %d %B as labels format' do
expect(chart.labels).to include(chart.from.strftime('%d %B'))
end
+
+ it 'returns count of pipelines run each day in the current month' do
+ expect(chart.total.sum).to eq(1)
+ end
end
context 'weekchart' do
@@ -47,6 +63,10 @@ RSpec.describe Gitlab::Ci::Charts do
subject { chart.to }
+ before do
+ create(:ci_empty_pipeline, project: project, duration: 120)
+ end
+
it 'includes the whole current day' do
is_expected.to eq(Date.today.end_of_day)
end
@@ -58,6 +78,68 @@ RSpec.describe Gitlab::Ci::Charts do
it 'uses %d %B as labels format' do
expect(chart.labels).to include(chart.from.strftime('%d %B'))
end
+
+ it 'returns count of pipelines run each day in the current week' do
+ expect(chart.total.sum).to eq(1)
+ end
+ end
+
+ context 'weekchart_utc' do
+ today = Date.today
+ end_of_today = Time.use_zone(Time.find_zone('UTC')) { today.end_of_day }
+
+ let(:project) { create(:project) }
+ let(:chart) do
+ allow(Date).to receive(:today).and_return(today)
+ allow(today).to receive(:end_of_day).and_return(end_of_today)
+ Gitlab::Ci::Charts::WeekChart.new(project)
+ end
+
+ subject { chart.total }
+
+ before do
+ create(:ci_empty_pipeline, project: project, duration: 120)
+ end
+
+ it 'uses a utc time zone for range times' do
+ expect(chart.to.zone).to eq(end_of_today.zone)
+ expect(chart.from.zone).to eq(end_of_today.zone)
+ end
+
+ it 'returns count of pipelines run each day in the current week' do
+ expect(chart.total.sum).to eq(1)
+ end
+ end
+
+ context 'weekchart_non_utc' do
+ today = Date.today
+ end_of_today = Time.use_zone(Time.find_zone('Asia/Dubai')) { today.end_of_day }
+
+ let(:project) { create(:project) }
+ let(:chart) do
+ allow(Date).to receive(:today).and_return(today)
+ allow(today).to receive(:end_of_day).and_return(end_of_today)
+ Gitlab::Ci::Charts::WeekChart.new(project)
+ end
+
+ subject { chart.total }
+
+ before do
+ # The DB uses UTC always, so our use of a Time Zone in the application
+ # can cause the creation date of the pipeline to go unmatched depending
+ # on the offset. We can work around this by requesting the pipeline be
+ # created a with the `created_at` field set to a day ago in the same week.
+ create(:ci_empty_pipeline, project: project, duration: 120, created_at: today - 1.day)
+ end
+
+ it 'uses a non-utc time zone for range times' do
+ expect(chart.to.zone).to eq(end_of_today.zone)
+ expect(chart.from.zone).to eq(end_of_today.zone)
+ end
+
+ it 'returns count of pipelines run each day in the current week' do
+ expect(chart.total.sum).to eq(1)
+ end
end
context 'pipeline_times' do
diff --git a/spec/lib/gitlab/ci/config/entry/cache_spec.rb b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
index 80427eaa6ee..247f4b63910 100644
--- a/spec/lib/gitlab/ci/config/entry/cache_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Cache do
+ using RSpec::Parameterized::TableSyntax
+
subject(:entry) { described_class.new(config) }
describe 'validations' do
@@ -56,8 +58,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
end
context 'with `policy`' do
- using RSpec::Parameterized::TableSyntax
-
where(:policy, :result) do
'pull-push' | 'pull-push'
'push' | 'push'
@@ -77,8 +77,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
end
context 'with `when`' do
- using RSpec::Parameterized::TableSyntax
-
where(:when_config, :result) do
'on_success' | 'on_success'
'on_failure' | 'on_failure'
@@ -109,8 +107,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
end
context 'with `policy`' do
- using RSpec::Parameterized::TableSyntax
-
where(:policy, :valid) do
'pull-push' | true
'push' | true
@@ -126,8 +122,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
end
context 'with `when`' do
- using RSpec::Parameterized::TableSyntax
-
where(:when_config, :valid) do
'on_success' | true
'on_failure' | true
diff --git a/spec/lib/gitlab/ci/config/entry/commands_spec.rb b/spec/lib/gitlab/ci/config/entry/commands_spec.rb
index 439799fe973..1b8dfae692a 100644
--- a/spec/lib/gitlab/ci/config/entry/commands_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/commands_spec.rb
@@ -87,18 +87,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Commands do
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
- .to include 'commands config should be a string or an array containing strings and arrays of strings'
+ .to include 'commands config should be a string or a nested array of strings up to 10 levels deep'
end
end
end
context 'when entry value is multi-level nested array' do
- let(:config) { [['ls', ['echo 1']], 'pwd'] }
+ let(:config) do
+ ['ls 0', ['ls 1', ['ls 2', ['ls 3', ['ls 4', ['ls 5', ['ls 6', ['ls 7', ['ls 8', ['ls 9', ['ls 10']]]]]]]]]]]
+ end
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
- .to include 'commands config should be a string or an array containing strings and arrays of strings'
+ .to include 'commands config should be a string or a nested array of strings up to 10 levels deep'
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 7834a1a94f2..a3b5f32b9f9 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -763,16 +763,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
it 'returns allow_failure_criteria' do
expect(entry.value[:allow_failure_criteria]).to match(exit_codes: [42])
end
-
- context 'with ci_allow_failure_with_exit_codes disabled' do
- before do
- stub_feature_flags(ci_allow_failure_with_exit_codes: false)
- end
-
- it 'does not return allow_failure_criteria' do
- expect(entry.value.key?(:allow_failure_criteria)).to be_falsey
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index aadf94365c6..04e80450263 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -73,6 +73,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ context 'when resource_group key is not a string' do
+ let(:config) { { resource_group: 123 } }
+
+ it 'returns error about wrong value type' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include "job resource group should be a string"
+ end
+ end
+
context 'when it uses both "when:" and "rules:"' do
let(:config) do
{
@@ -340,6 +349,26 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ context 'with resource group' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:resource_group, :result) do
+ 'iOS' | 'iOS'
+ 'review/$CI_COMMIT_REF_NAME' | 'review/$CI_COMMIT_REF_NAME'
+ nil | nil
+ end
+
+ with_them do
+ let(:config) { { script: 'ls', resource_group: resource_group }.compact }
+
+ it do
+ entry.compose!(deps)
+
+ expect(entry.resource_group).to eq(result)
+ end
+ end
+ end
+
context 'with inheritance' do
context 'of variables' do
let(:config) do
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 4fdaaca8316..99f546ceb37 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -323,20 +323,6 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
expect { subject }.to raise_error(described_class::AmbigiousSpecificationError)
end
end
-
- context 'when feature flag is turned off' do
- let(:values) do
- { include: full_local_file_path }
- end
-
- before do
- stub_feature_flags(variables_in_include_section_ci: false)
- end
-
- it 'does not expand the variables' do
- expect(subject[0].location).to eq('$CI_PROJECT_PATH' + local_file)
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/yaml/tags/reference_spec.rb b/spec/lib/gitlab/ci/config/yaml/tags/reference_spec.rb
new file mode 100644
index 00000000000..c68dccd3455
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/yaml/tags/reference_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Config::Yaml::Tags::Reference do
+ let(:config) do
+ Gitlab::Ci::Config::Yaml.load!(yaml)
+ end
+
+ describe '.tag' do
+ it 'implements the tag method' do
+ expect(described_class.tag).to eq('!reference')
+ end
+ end
+
+ describe '#resolve' do
+ subject { Gitlab::Ci::Config::Yaml::Tags::Resolver.new(config).to_hash }
+
+ context 'with circular references' do
+ let(:yaml) do
+ <<~YML
+ a: !reference [b]
+ b: !reference [a]
+ YML
+ end
+
+ it 'raises CircularReferenceError' do
+ expect { subject }.to raise_error Gitlab::Ci::Config::Yaml::Tags::TagError, '!reference ["b"] is part of a circular chain'
+ end
+ end
+
+ context 'with nested circular references' do
+ let(:yaml) do
+ <<~YML
+ a: !reference [b, c]
+ b: { c: !reference [d, e, f] }
+ d: { e: { f: !reference [a] } }
+ YML
+ end
+
+ it 'raises CircularReferenceError' do
+ expect { subject }.to raise_error Gitlab::Ci::Config::Yaml::Tags::TagError, '!reference ["b", "c"] is part of a circular chain'
+ end
+ end
+
+ context 'with missing references' do
+ let(:yaml) { 'a: !reference [b]' }
+
+ it 'raises MissingReferenceError' do
+ expect { subject }.to raise_error Gitlab::Ci::Config::Yaml::Tags::TagError, '!reference ["b"] could not be found'
+ end
+ end
+
+ context 'with invalid references' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:yaml, :error_message) do
+ 'a: !reference' | '!reference [] is not valid'
+ 'a: !reference str' | '!reference "str" is not valid'
+ 'a: !reference 1' | '!reference "1" is not valid'
+ 'a: !reference [1]' | '!reference [1] is not valid'
+ 'a: !reference { b: c }' | '!reference {"b"=>"c"} is not valid'
+ end
+
+ with_them do
+ it 'raises an error' do
+ expect { subject }.to raise_error Gitlab::Ci::Config::Yaml::Tags::TagError, error_message
+ end
+ end
+ end
+
+ context 'with arrays' do
+ let(:yaml) do
+ <<~YML
+ a: { b: [1, 2] }
+ c: { d: { e: [3, 4] } }
+ f: { g: [ !reference [a, b], 5, !reference [c, d, e]] }
+ YML
+ end
+
+ it { is_expected.to match(a_hash_including({ f: { g: [[1, 2], 5, [3, 4]] } })) }
+ end
+
+ context 'with hashes' do
+ context 'when referencing an entire hash' do
+ let(:yaml) do
+ <<~YML
+ a: { b: { c: 'c', d: 'd' } }
+ e: { f: !reference [a, b] }
+ YML
+ end
+
+ it { is_expected.to match(a_hash_including({ e: { f: { c: 'c', d: 'd' } } })) }
+ end
+
+ context 'when referencing only a hash value' do
+ let(:yaml) do
+ <<~YML
+ a: { b: { c: 'c', d: 'd' } }
+ e: { f: { g: !reference [a, b, c], h: 'h' } }
+ i: !reference [e, f]
+ YML
+ end
+
+ it { is_expected.to match(a_hash_including({ i: { g: 'c', h: 'h' } })) }
+ end
+
+ context 'when referencing a value before its definition' do
+ let(:yaml) do
+ <<~YML
+ a: { b: !reference [c, d] }
+ g: { h: { i: 'i', j: 1 } }
+ c: { d: { e: !reference [g, h, j], f: 'f' } }
+ YML
+ end
+
+ it { is_expected.to match(a_hash_including({ a: { b: { e: 1, f: 'f' } } })) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/yaml/tags/resolver_spec.rb b/spec/lib/gitlab/ci/config/yaml/tags/resolver_spec.rb
new file mode 100644
index 00000000000..594242c33cc
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/yaml/tags/resolver_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Config::Yaml::Tags::Resolver do
+ let(:config) do
+ Gitlab::Ci::Config::Yaml.load!(yaml)
+ end
+
+ describe '#to_hash' do
+ subject { described_class.new(config).to_hash }
+
+ context 'when referencing deeply nested arrays' do
+ let(:yaml_templates) do
+ <<~YML
+ .job-1:
+ script:
+ - echo doing step 1 of job 1
+ - echo doing step 2 of job 1
+
+ .job-2:
+ script:
+ - echo doing step 1 of job 2
+ - !reference [.job-1, script]
+ - echo doing step 2 of job 2
+
+ .job-3:
+ script:
+ - echo doing step 1 of job 3
+ - !reference [.job-2, script]
+ - echo doing step 2 of job 3
+ YML
+ end
+
+ let(:job_yaml) do
+ <<~YML
+ test:
+ script:
+ - echo preparing to test
+ - !reference [.job-3, script]
+ - echo test finished
+ YML
+ end
+
+ shared_examples 'expands references' do
+ it 'expands the references' do
+ is_expected.to match({
+ '.job-1': {
+ script: [
+ 'echo doing step 1 of job 1',
+ 'echo doing step 2 of job 1'
+ ]
+ },
+ '.job-2': {
+ script: [
+ 'echo doing step 1 of job 2',
+ [
+ 'echo doing step 1 of job 1',
+ 'echo doing step 2 of job 1'
+ ],
+ 'echo doing step 2 of job 2'
+ ]
+ },
+ '.job-3': {
+ script: [
+ 'echo doing step 1 of job 3',
+ [
+ 'echo doing step 1 of job 2',
+ [
+ 'echo doing step 1 of job 1',
+ 'echo doing step 2 of job 1'
+ ],
+ 'echo doing step 2 of job 2'
+ ],
+ 'echo doing step 2 of job 3'
+ ]
+ },
+ test: {
+ script: [
+ 'echo preparing to test',
+ [
+ 'echo doing step 1 of job 3',
+ [
+ 'echo doing step 1 of job 2',
+ [
+ 'echo doing step 1 of job 1',
+ 'echo doing step 2 of job 1'
+ ],
+ 'echo doing step 2 of job 2'
+ ],
+ 'echo doing step 2 of job 3'
+ ],
+ 'echo test finished'
+ ]
+ }
+ })
+ end
+ end
+
+ context 'when templates are defined before the job' do
+ let(:yaml) do
+ <<~YML
+ #{yaml_templates}
+ #{job_yaml}
+ YML
+ end
+
+ it_behaves_like 'expands references'
+ end
+
+ context 'when templates are defined after the job' do
+ let(:yaml) do
+ <<~YML
+ #{job_yaml}
+ #{yaml_templates}
+ YML
+ end
+
+ it_behaves_like 'expands references'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index dc03d2f80fe..45ce4cac6c4 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -263,6 +263,26 @@ RSpec.describe Gitlab::Ci::Config do
end
end
end
+
+ context 'when yaml uses circular !reference' do
+ let(:yml) do
+ <<~YAML
+ job-1:
+ script:
+ - !reference [job-2, before_script]
+
+ job-2:
+ before_script: !reference [job-1, script]
+ YAML
+ end
+
+ it 'raises error' do
+ expect { config }.to raise_error(
+ described_class::ConfigError,
+ /\!reference \["job-2", "before_script"\] is part of a circular chain/
+ )
+ end
+ end
end
context "when using 'include' directive" do
diff --git a/spec/lib/gitlab/ci/cron_parser_spec.rb b/spec/lib/gitlab/ci/cron_parser_spec.rb
index dd27b4045c9..15293429354 100644
--- a/spec/lib/gitlab/ci/cron_parser_spec.rb
+++ b/spec/lib/gitlab/ci/cron_parser_spec.rb
@@ -63,6 +63,17 @@ RSpec.describe Gitlab::Ci::CronParser do
end
end
+ context 'when range and slash used' do
+ let(:cron) { '3-59/10 * * * *' }
+ let(:cron_timezone) { 'UTC' }
+
+ it_behaves_like returns_time_for_epoch
+
+ it 'returns specific time' do
+ expect(subject.min).to be_in([3, 13, 23, 33, 43, 53])
+ end
+ end
+
context 'when cron_timezone is TZInfo format' do
before do
allow(Time).to receive(:zone)
diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb
index 3130c0c0c41..342ca6b8b75 100644
--- a/spec/lib/gitlab/ci/jwt_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_spec.rb
@@ -44,6 +44,9 @@ RSpec.describe Gitlab::Ci::Jwt do
expect(payload[:pipeline_id]).to eq(pipeline.id.to_s)
expect(payload[:job_id]).to eq(build.id.to_s)
expect(payload[:ref]).to eq(pipeline.source_ref)
+ expect(payload[:ref_protected]).to eq(build.protected.to_s)
+ expect(payload[:environment]).to be_nil
+ expect(payload[:environment_protected]).to be_nil
end
end
@@ -90,6 +93,39 @@ RSpec.describe Gitlab::Ci::Jwt do
expect(payload[:ref_protected]).to eq('true')
end
end
+
+ describe 'environment' do
+ let(:environment) { build_stubbed(:environment, project: project, name: 'production') }
+ let(:build) do
+ build_stubbed(
+ :ci_build,
+ project: project,
+ user: user,
+ pipeline: pipeline,
+ environment: environment.name
+ )
+ end
+
+ before do
+ allow(build).to receive(:persisted_environment).and_return(environment)
+ end
+
+ it 'has correct values for environment attributes' do
+ expect(payload[:environment]).to eq('production')
+ expect(payload[:environment_protected]).to eq('false')
+ end
+
+ context ':ci_jwt_include_environment feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_jwt_include_environment: false)
+ end
+
+ it 'does not include environment attributes' do
+ expect(payload).not_to have_key(:environment)
+ expect(payload).not_to have_key(:environment_protected)
+ end
+ end
+ end
end
describe '.for_build' do
diff --git a/spec/lib/gitlab/ci/parsers/instrumentation_spec.rb b/spec/lib/gitlab/ci/parsers/instrumentation_spec.rb
new file mode 100644
index 00000000000..30bcce21be2
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/instrumentation_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Parsers::Instrumentation do
+ describe '#parse!' do
+ let(:parser_class) do
+ Class.new do
+ prepend Gitlab::Ci::Parsers::Instrumentation
+
+ def parse!(arg1, arg2)
+ "parse #{arg1} #{arg2}"
+ end
+ end
+ end
+
+ it 'sets metrics for duration of parsing' do
+ result = parser_class.new.parse!('hello', 'world')
+
+ expect(result).to eq('parse hello world')
+
+ metrics = Gitlab::Metrics.registry.get(:ci_report_parser_duration_seconds).get({ parser: parser_class.name })
+
+ expect(metrics.keys).to match_array(described_class::BUCKETS)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers_spec.rb b/spec/lib/gitlab/ci/parsers_spec.rb
index b932cd81272..c9891c06507 100644
--- a/spec/lib/gitlab/ci/parsers_spec.rb
+++ b/spec/lib/gitlab/ci/parsers_spec.rb
@@ -54,4 +54,12 @@ RSpec.describe Gitlab::Ci::Parsers do
end
end
end
+
+ describe '.instrument!' do
+ it 'prepends the Instrumentation module into each parser' do
+ expect(described_class.parsers.values).to all( receive(:prepend).with(Gitlab::Ci::Parsers::Instrumentation) )
+
+ described_class.instrument!
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
index 20406acb658..53dea1d0d19 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb
@@ -235,7 +235,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Build do
with_them do
before do
- project.update!(ci_keep_latest_artifact: keep_latest_artifact)
+ project.update!(keep_latest_artifact: keep_latest_artifact)
end
it 'builds a pipeline with appropriate locked value' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
index 3eaecb11ae0..1d17244e519 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines_spec.rb
@@ -58,20 +58,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines do
expect(build_statuses(child_pipeline)).to contain_exactly('canceled')
end
-
- context 'when FF ci_auto_cancel_all_pipelines is disabled' do
- before do
- stub_feature_flags(ci_auto_cancel_all_pipelines: false)
- end
-
- it 'does not cancel interruptible builds of child pipeline' do
- expect(build_statuses(child_pipeline)).to contain_exactly('running')
-
- perform
-
- expect(build_statuses(child_pipeline)).to contain_exactly('running')
- end
- end
end
context 'when the child pipeline has not an interruptible job' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
index 3616461d94f..cd868a57bbc 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::TemplateUsage do
%w(Template-1 Template-2).each do |expected_template|
expect(Gitlab::UsageDataCounters::CiTemplateUniqueCounter).to(
receive(:track_unique_project_event)
- .with(project_id: project.id, template: expected_template)
+ .with(project_id: project.id, template: expected_template, config_source: pipeline.config_source)
)
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build/resource_group_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build/resource_group_spec.rb
deleted file mode 100644
index 8fcc242ba5f..00000000000
--- a/spec/lib/gitlab/ci/pipeline/seed/build/resource_group_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Ci::Pipeline::Seed::Build::ResourceGroup do
- let_it_be(:project) { create(:project) }
- let(:job) { build(:ci_build, project: project) }
- let(:seed) { described_class.new(job, resource_group_key) }
-
- describe '#to_resource' do
- subject { seed.to_resource }
-
- context 'when resource group key is specified' do
- let(:resource_group_key) { 'iOS' }
-
- it 'returns a resource group object' do
- is_expected.to be_a(Ci::ResourceGroup)
- expect(subject.key).to eq('iOS')
- end
-
- context 'when environment has an invalid URL' do
- let(:resource_group_key) { ':::' }
-
- it 'returns nothing' do
- is_expected.to be_nil
- end
- end
-
- context 'when there is a resource group already' do
- let!(:resource_group) { create(:ci_resource_group, project: project, key: 'iOS') }
-
- it 'does not create a new resource group' do
- expect { subject }.not_to change { Ci::ResourceGroup.count }
- end
- end
- end
-
- context 'when resource group key is nil' do
- let(:resource_group_key) { nil }
-
- it 'returns nothing' do
- is_expected.to be_nil
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index cf020fc343c..0efc7484699 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -383,14 +383,25 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
context 'when job is a bridge' do
- let(:attributes) 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
diff --git a/spec/lib/gitlab/ci/pipeline/seed/processable/resource_group_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/processable/resource_group_spec.rb
new file mode 100644
index 00000000000..b7260599de2
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/seed/processable/resource_group_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Seed::Processable::ResourceGroup do
+ let_it_be(:project) { create(:project) }
+ let(:job) { build(:ci_build, project: project) }
+ let(:seed) { described_class.new(job, resource_group_key) }
+
+ describe '#to_resource' do
+ subject { seed.to_resource }
+
+ context 'when resource group key is specified' do
+ let(:resource_group_key) { 'iOS' }
+
+ it 'returns a resource group object' do
+ is_expected.to be_a(Ci::ResourceGroup)
+ expect(subject.key).to eq('iOS')
+ end
+
+ context 'when environment has an invalid URL' do
+ let(:resource_group_key) { ':::' }
+
+ it 'returns nothing' do
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when there is a resource group already' do
+ let!(:resource_group) { create(:ci_resource_group, project: project, key: 'iOS') }
+
+ it 'does not create a new resource group' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+ end
+ end
+ end
+
+ context 'when resource group key is nil' do
+ let(:resource_group_key) { nil }
+
+ it 'returns nothing' do
+ is_expected.to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/codequality_mr_diff_spec.rb b/spec/lib/gitlab/ci/reports/codequality_mr_diff_spec.rb
new file mode 100644
index 00000000000..8b177fa7fc1
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/codequality_mr_diff_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Reports::CodequalityMrDiff do
+ let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
+ let(:degradation_3) { build(:codequality_degradation_3) }
+
+ describe '#initialize!' do
+ subject(:report) { described_class.new(codequality_report) }
+
+ context 'when quality has degradations' do
+ context 'with several degradations on the same line' do
+ before do
+ codequality_report.add_degradation(degradation_1)
+ codequality_report.add_degradation(degradation_2)
+ end
+
+ it 'generates quality report for mr diff' do
+ expect(report.files).to match(
+ "file_a.rb" => [
+ { line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "major" },
+ { line: 10, description: "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", severity: "major" }
+ ]
+ )
+ end
+ end
+
+ context 'with several degradations on several files' do
+ before do
+ codequality_report.add_degradation(degradation_1)
+ codequality_report.add_degradation(degradation_2)
+ codequality_report.add_degradation(degradation_3)
+ end
+
+ it 'returns quality report for mr diff' do
+ expect(report.files).to match(
+ "file_a.rb" => [
+ { line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "major" },
+ { line: 10, description: "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", severity: "major" }
+ ],
+ "file_b.rb" => [
+ { line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "minor" }
+ ]
+ )
+ end
+ end
+ end
+
+ context 'when quality has no degradation' do
+ it 'returns an empty hash' do
+ expect(report.files).to match({})
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
index 7053d54381b..90188b56f5a 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_comparer_spec.rb
@@ -6,62 +6,8 @@ RSpec.describe Gitlab::Ci::Reports::CodequalityReportsComparer do
let(:comparer) { described_class.new(base_report, head_report) }
let(:base_report) { Gitlab::Ci::Reports::CodequalityReports.new }
let(:head_report) { Gitlab::Ci::Reports::CodequalityReports.new }
- let(:degradation_1) do
- {
- "categories": [
- "Complexity"
- ],
- "check_name": "argument_count",
- "content": {
- "body": ""
- },
- "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
- "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
- "location": {
- "path": "foo.rb",
- "lines": {
- "begin": 10,
- "end": 10
- }
- },
- "other_locations": [],
- "remediation_points": 900000,
- "severity": "major",
- "type": "issue",
- "engine_name": "structure"
- }.with_indifferent_access
- end
-
- let(:degradation_2) do
- {
- "type": "Issue",
- "check_name": "Rubocop/Metrics/ParameterLists",
- "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
- "categories": [
- "Complexity"
- ],
- "remediation_points": 550000,
- "location": {
- "path": "foo.rb",
- "positions": {
- "begin": {
- "column": 14,
- "line": 10
- },
- "end": {
- "column": 39,
- "line": 10
- }
- }
- },
- "content": {
- "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
- },
- "engine_name": "rubocop",
- "fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
- "severity": "minor"
- }.with_indifferent_access
- end
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
describe '#status' do
subject(:report_status) { comparer.status }
diff --git a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
index 44e67259369..ae9b2f2c62b 100644
--- a/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/codequality_reports_spec.rb
@@ -4,62 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::CodequalityReports do
let(:codequality_report) { described_class.new }
- let(:degradation_1) do
- {
- "categories": [
- "Complexity"
- ],
- "check_name": "argument_count",
- "content": {
- "body": ""
- },
- "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
- "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
- "location": {
- "path": "foo.rb",
- "lines": {
- "begin": 10,
- "end": 10
- }
- },
- "other_locations": [],
- "remediation_points": 900000,
- "severity": "major",
- "type": "issue",
- "engine_name": "structure"
- }.with_indifferent_access
- end
-
- let(:degradation_2) do
- {
- "type": "Issue",
- "check_name": "Rubocop/Metrics/ParameterLists",
- "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
- "categories": [
- "Complexity"
- ],
- "remediation_points": 550000,
- "location": {
- "path": "foo.rb",
- "positions": {
- "begin": {
- "column": 14,
- "line": 10
- },
- "end": {
- "column": 39,
- "line": 10
- }
- }
- },
- "content": {
- "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
- },
- "engine_name": "rubocop",
- "fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
- "severity": "minor"
- }.with_indifferent_access
- end
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
it { expect(codequality_report.degradations).to eq({}) }
diff --git a/spec/lib/gitlab/ci/status/bridge/factory_spec.rb b/spec/lib/gitlab/ci/status/bridge/factory_spec.rb
index d27bb98ba9a..6081f104e42 100644
--- a/spec/lib/gitlab/ci/status/bridge/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/bridge/factory_spec.rb
@@ -117,14 +117,31 @@ RSpec.describe Gitlab::Ci::Status::Bridge::Factory do
end
end
+ context 'when bridge is waiting for resource' do
+ let(:bridge) { create_bridge(:waiting_for_resource, :resource_group) }
+
+ it 'matches correct core status' do
+ expect(factory.core_status).to be_a Gitlab::Ci::Status::WaitingForResource
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'waiting'
+ expect(status.group).to eq 'waiting-for-resource'
+ expect(status.icon).to eq 'status_pending'
+ expect(status.favicon).to eq 'favicon_pending'
+ expect(status.illustration).to include(:image, :size, :title)
+ expect(status).not_to have_details
+ end
+ end
+
private
- def create_bridge(trait)
+ def create_bridge(*traits)
upstream_project = create(:project, :repository)
downstream_project = create(:project, :repository)
upstream_pipeline = create(:ci_pipeline, :running, project: upstream_project)
trigger = { trigger: { project: downstream_project.full_path, branch: 'feature' } }
- create(:ci_bridge, trait, options: trigger, pipeline: upstream_pipeline)
+ create(:ci_bridge, *traits, options: trigger, pipeline: upstream_pipeline)
end
end
diff --git a/spec/lib/gitlab/ci/status/bridge/waiting_for_resource_spec.rb b/spec/lib/gitlab/ci/status/bridge/waiting_for_resource_spec.rb
new file mode 100644
index 00000000000..3e19df28d83
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/bridge/waiting_for_resource_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Ci::Status::Bridge::WaitingForResource do
+ it { expect(described_class).to be < Gitlab::Ci::Status::Processable::WaitingForResource }
+end
diff --git a/spec/lib/gitlab/ci/status/build/waiting_for_resource_spec.rb b/spec/lib/gitlab/ci/status/build/waiting_for_resource_spec.rb
new file mode 100644
index 00000000000..44bd5a8611a
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/waiting_for_resource_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Ci::Status::Build::WaitingForResource do
+ it { expect(described_class).to be < Gitlab::Ci::Status::Processable::WaitingForResource }
+end
diff --git a/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb b/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb
new file mode 100644
index 00000000000..91a9724d043
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Status::Processable::WaitingForResource do
+ let(:user) { create(:user) }
+
+ subject do
+ processable = create(:ci_build, :waiting_for_resource, :resource_group)
+ described_class.new(Gitlab::Ci::Status::Core.new(processable, user))
+ end
+
+ describe '#illustration' do
+ it { expect(subject.illustration).to include(:image, :size, :title) }
+ end
+
+ describe '.matches?' do
+ subject {described_class.matches?(processable, user) }
+
+ context 'when processable is waiting for resource' do
+ let(:processable) { create(:ci_build, :waiting_for_resource) }
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+
+ context 'when processable is not waiting for resource' do
+ let(:processable) { create(:ci_build) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
index a2903391c6f..f09e03b4d55 100644
--- a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
+++ b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Ci::Trace::ChunkedIO, :clean_gitlab_redis_cache do
let(:chunked_io) { described_class.new(build) }
before do
- stub_feature_flags(ci_enable_live_trace: true)
+ stub_feature_flags(ci_enable_live_trace: true, gitlab_ci_trace_read_consistency: true)
end
describe "#initialize" do
diff --git a/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb b/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
index d85bf29f77f..954273fd41e 100644
--- a/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/sorted_spec.rb
@@ -5,8 +5,11 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
describe '#errors' do
context 'when FF :variable_inside_variable is disabled' do
+ let_it_be(:project_with_flag_disabled) { create(:project) }
+ let_it_be(:project_with_flag_enabled) { create(:project) }
+
before do
- stub_feature_flags(variable_inside_variable: false)
+ stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
end
context 'table tests' do
@@ -53,7 +56,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
end
with_them do
- subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project_with_flag_disabled) }
it 'does not report error' do
expect(subject.errors).to eq(nil)
@@ -67,8 +70,11 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
end
context 'when FF :variable_inside_variable is enabled' do
+ let_it_be(:project_with_flag_disabled) { create(:project) }
+ let_it_be(:project_with_flag_enabled) { create(:project) }
+
before do
- stub_feature_flags(variable_inside_variable: true)
+ stub_feature_flags(variable_inside_variable: [project_with_flag_enabled])
end
context 'table tests' do
@@ -100,7 +106,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
end
with_them do
- subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project_with_flag_enabled) }
it 'errors matches expected validation result' do
expect(subject.errors).to eq(validation_result)
@@ -164,7 +170,8 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
end
with_them do
- subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+ let_it_be(:project) { create(:project) }
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project) }
it 'does not expand variables' do
expect(subject.sort).to eq(variables)
@@ -239,7 +246,8 @@ RSpec.describe Gitlab::Ci::Variables::Collection::Sorted do
end
with_them do
- subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables) }
+ let_it_be(:project) { create(:project) }
+ subject { Gitlab::Ci::Variables::Collection::Sorted.new(variables, project) }
it 'sort returns correctly sorted variables' do
expect(subject.sort.map { |var| var[:key] }).to eq(result)
diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb
new file mode 100644
index 00000000000..b45abf8c0e1
--- /dev/null
+++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Ci::Variables::Helpers do
+ describe '.merge_variables' do
+ let(:current_variables) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
+
+ let(:new_variables) do
+ [{ key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
+ end
+
+ let(:result) do
+ [{ key: 'key1', value: 'value1', public: true },
+ { key: 'key2', value: 'value22', public: true },
+ { key: 'key3', value: 'value3', public: true }]
+ end
+
+ subject { described_class.merge_variables(current_variables, new_variables) }
+
+ it { is_expected.to eq(result) }
+
+ context 'when new variables is a hash' do
+ let(:new_variables) do
+ { 'key2' => 'value22', 'key3' => 'value3' }
+ end
+
+ it { is_expected.to eq(result) }
+ end
+
+ context 'when new variables is a hash with symbol keys' do
+ let(:new_variables) do
+ { key2: 'value22', key3: 'value3' }
+ end
+
+ it { is_expected.to eq(result) }
+ end
+
+ context 'when new variables is nil' do
+ let(:new_variables) {}
+ let(:result) do
+ [{ key: 'key1', value: 'value1', public: true },
+ { key: 'key2', value: 'value2', public: true }]
+ end
+
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ describe '.transform_to_yaml_variables' do
+ let(:variables) do
+ { 'key1' => 'value1', 'key2' => 'value2' }
+ end
+
+ let(:result) do
+ [{ key: 'key1', value: 'value1', public: true },
+ { key: 'key2', value: 'value2', public: true }]
+ end
+
+ subject { described_class.transform_to_yaml_variables(variables) }
+
+ it { is_expected.to eq(result) }
+
+ context 'when variables is nil' do
+ let(:variables) {}
+
+ it { is_expected.to eq([]) }
+ end
+ end
+
+ describe '.transform_from_yaml_variables' do
+ let(:variables) do
+ [{ key: 'key1', value: 'value1', public: true },
+ { key: 'key2', value: 'value2', public: true }]
+ end
+
+ let(:result) do
+ { 'key1' => 'value1', 'key2' => 'value2' }
+ end
+
+ subject { described_class.transform_from_yaml_variables(variables) }
+
+ it { is_expected.to eq(result) }
+
+ context 'when variables is nil' do
+ let(:variables) {}
+
+ it { is_expected.to eq({}) }
+ end
+
+ context 'when variables is a hash' do
+ let(:variables) do
+ { key1: 'value1', 'key2' => 'value2' }
+ end
+
+ it { is_expected.to eq(result) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/cleanup/orphan_job_artifact_files_spec.rb b/spec/lib/gitlab/cleanup/orphan_job_artifact_files_spec.rb
index 8a7425a4156..b5adb603dab 100644
--- a/spec/lib/gitlab/cleanup/orphan_job_artifact_files_spec.rb
+++ b/spec/lib/gitlab/cleanup/orphan_job_artifact_files_spec.rb
@@ -42,7 +42,8 @@ RSpec.describe Gitlab::Cleanup::OrphanJobArtifactFiles do
end
it 'stops when limit is reached' do
- cleanup = described_class.new(limit: 1)
+ stub_env('LIMIT', 1)
+ cleanup = described_class.new
mock_artifacts_found(cleanup, 'tmp/foo/bar/1', 'tmp/foo/bar/2')
diff --git a/spec/lib/gitlab/cluster/lifecycle_events_spec.rb b/spec/lib/gitlab/cluster/lifecycle_events_spec.rb
new file mode 100644
index 00000000000..4ed68d54680
--- /dev/null
+++ b/spec/lib/gitlab/cluster/lifecycle_events_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+RSpec.describe Gitlab::Cluster::LifecycleEvents do
+ # we create a new instance to ensure that we do not touch existing hooks
+ let(:replica) { Class.new(described_class) }
+
+ context 'hooks execution' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:method, :hook_names) do
+ :do_worker_start | %i[worker_start_hooks]
+ :do_before_fork | %i[before_fork_hooks]
+ :do_before_graceful_shutdown | %i[master_blackout_period master_graceful_shutdown]
+ :do_before_master_restart | %i[master_restart_hooks]
+ end
+
+ before do
+ # disable blackout period to speed-up tests
+ stub_config(shutdown: { blackout_seconds: 0 })
+ end
+
+ with_them do
+ subject { replica.public_send(method) }
+
+ it 'executes all hooks' do
+ hook_names.each do |hook_name|
+ hook = double
+ replica.instance_variable_set(:"@#{hook_name}", [hook])
+
+ # ensure that proper hooks are called
+ expect(hook).to receive(:call)
+ expect(replica).to receive(:call).with(hook_name, anything).and_call_original
+ end
+
+ subject
+ end
+ end
+ end
+
+ describe '#call' do
+ let(:name) { :my_hooks }
+
+ subject { replica.send(:call, name, hooks) }
+
+ context 'when many hooks raise exception' do
+ let(:hooks) do
+ [
+ -> { raise 'Exception A' },
+ -> { raise 'Exception B' }
+ ]
+ end
+
+ context 'USE_FATAL_LIFECYCLE_EVENTS is set to default' do
+ it 'only first hook is executed and is fatal' do
+ expect(hooks[0]).to receive(:call).and_call_original
+ expect(hooks[1]).not_to receive(:call)
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original
+ expect(replica).to receive(:warn).with('ERROR: The hook my_hooks failed with exception (RuntimeError) "Exception A".')
+
+ expect { subject }.to raise_error(described_class::FatalError, 'Exception A')
+ end
+ end
+
+ context 'when USE_FATAL_LIFECYCLE_EVENTS is disabled' do
+ before do
+ stub_const('Gitlab::Cluster::LifecycleEvents::USE_FATAL_LIFECYCLE_EVENTS', false)
+ end
+
+ it 'many hooks are executed and all exceptions are logged' do
+ expect(hooks[0]).to receive(:call).and_call_original
+ expect(hooks[1]).to receive(:call).and_call_original
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).twice.and_call_original
+ expect(replica).to receive(:warn).twice.and_call_original
+
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/composer/cache_spec.rb b/spec/lib/gitlab/composer/cache_spec.rb
new file mode 100644
index 00000000000..00318ac14f9
--- /dev/null
+++ b/spec/lib/gitlab/composer/cache_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Composer::Cache do
+ let_it_be(:package_name) { 'sample-project' }
+ let_it_be(:json) { { 'name' => package_name } }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :custom_repo, files: { 'composer.json' => json.to_json }, group: group) }
+ let(:branch) { project.repository.find_branch('master') }
+ let(:sha_regex) { /^[A-Fa-f0-9]{64}$/ }
+
+ shared_examples 'Composer create cache page' do
+ let(:expected_json) { ::Gitlab::Composer::VersionIndex.new(packages).to_json }
+
+ before do
+ stub_composer_cache_object_storage
+ end
+
+ it 'creates the cached page' do
+ expect { subject }.to change { Packages::Composer::CacheFile.count }.by(1)
+ cache_file = Packages::Composer::CacheFile.last
+ expect(cache_file.file_sha256).to eq package.reload.composer_metadatum.version_cache_sha
+ expect(cache_file.file.read).to eq expected_json
+ end
+ end
+
+ shared_examples 'Composer marks cache page for deletion' do
+ it 'marks the page for deletion' do
+ cache_file = Packages::Composer::CacheFile.last
+
+ freeze_time do
+ expect { subject }.to change { cache_file.reload.delete_at}.from(nil).to(1.day.from_now)
+ end
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new(project: project, name: package_name).execute }
+
+ context 'creating packages' do
+ context 'with a pre-existing package' do
+ let(:package) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let(:package2) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '2.0.0', json: json) }
+ let(:packages) { [package, package2] }
+
+ before do
+ package
+ described_class.new(project: project, name: package_name).execute
+ package.reload
+ package2
+ end
+
+ it 'updates the sha and creates the cache page' do
+ expect { subject }.to change { package2.reload.composer_metadatum.version_cache_sha }.from(nil).to(sha_regex)
+ .and change { package.reload.composer_metadatum.version_cache_sha }.to(sha_regex)
+ end
+
+ it_behaves_like 'Composer create cache page'
+ it_behaves_like 'Composer marks cache page for deletion'
+ end
+
+ context 'first package' do
+ let!(:package) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let(:packages) { [package] }
+
+ it 'updates the sha and creates the cache page' do
+ expect { subject }.to change { package.reload.composer_metadatum.version_cache_sha }.from(nil).to(sha_regex)
+ end
+
+ it_behaves_like 'Composer create cache page'
+ end
+ end
+
+ context 'updating packages' do
+ let(:package) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let(:package2) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '2.0.0', json: json) }
+ let(:packages) { [package, package2] }
+
+ before do
+ packages
+
+ described_class.new(project: project, name: package_name).execute
+
+ package.update!(version: '1.2.0')
+ package.reload
+ end
+
+ it_behaves_like 'Composer create cache page'
+ it_behaves_like 'Composer marks cache page for deletion'
+ end
+
+ context 'deleting packages' do
+ context 'when it is not the last package' do
+ let(:package) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let(:package2) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '2.0.0', json: json) }
+ let(:packages) { [package] }
+
+ before do
+ package
+ package2
+
+ described_class.new(project: project, name: package_name).execute
+
+ package2.destroy!
+ end
+
+ it_behaves_like 'Composer create cache page'
+ it_behaves_like 'Composer marks cache page for deletion'
+ end
+
+ context 'when it is the last package' do
+ let!(:package) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let!(:last_sha) do
+ described_class.new(project: project, name: package_name).execute
+ package.reload.composer_metadatum.version_cache_sha
+ end
+
+ before do
+ package.destroy!
+ end
+
+ subject { described_class.new(project: project, name: package_name, last_page_sha: last_sha).execute }
+
+ it_behaves_like 'Composer marks cache page for deletion'
+
+ it 'does not create a new page' do
+ expect { subject }.not_to change { Packages::Composer::CacheFile.count }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/composer/version_index_spec.rb b/spec/lib/gitlab/composer/version_index_spec.rb
index 4c4742d9f59..7b0ed703f42 100644
--- a/spec/lib/gitlab/composer/version_index_spec.rb
+++ b/spec/lib/gitlab/composer/version_index_spec.rb
@@ -15,7 +15,9 @@ RSpec.describe Gitlab::Composer::VersionIndex do
let(:packages) { [package1, package2] }
describe '#as_json' do
- subject(:index) { described_class.new(packages).as_json }
+ subject(:package_index) { index['packages'][package_name] }
+
+ let(:index) { described_class.new(packages).as_json }
def expected_json(package)
{
@@ -32,10 +34,16 @@ RSpec.describe Gitlab::Composer::VersionIndex do
end
it 'returns the packages json' do
- packages = index['packages'][package_name]
+ expect(package_index['1.0.0']).to eq(expected_json(package1))
+ expect(package_index['2.0.0']).to eq(expected_json(package2))
+ end
+
+ context 'with an unordered list of packages' do
+ let(:packages) { [package2, package1] }
- expect(packages['1.0.0']).to eq(expected_json(package1))
- expect(packages['2.0.0']).to eq(expected_json(package2))
+ it 'returns the packages sorted by version' do
+ expect(package_index.keys).to eq ['1.0.0', '2.0.0']
+ end
end
end
diff --git a/spec/lib/gitlab/conan_token_spec.rb b/spec/lib/gitlab/conan_token_spec.rb
index be1d3e757f5..00683cf6e47 100644
--- a/spec/lib/gitlab/conan_token_spec.rb
+++ b/spec/lib/gitlab/conan_token_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::ConanToken do
let(:jwt_secret) do
OpenSSL::HMAC.hexdigest(
- OpenSSL::Digest::SHA256.new,
+ OpenSSL::Digest.new('SHA256'),
base_secret,
described_class::HMAC_KEY
)
diff --git a/spec/lib/gitlab/config/entry/validators/nested_array_helpers_spec.rb b/spec/lib/gitlab/config/entry/validators/nested_array_helpers_spec.rb
new file mode 100644
index 00000000000..cd68307e71f
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/validators/nested_array_helpers_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Config::Entry::Validators::NestedArrayHelpers do
+ let(:config_struct) do
+ Struct.new(:value, keyword_init: true) do
+ include ActiveModel::Validations
+ extend Gitlab::Config::Entry::Validators::NestedArrayHelpers
+
+ validates_each :value do |record, attr, value|
+ unless validate_nested_array(value, 2) { |v| v.is_a?(Integer) }
+ record.errors.add(attr, "is invalid")
+ end
+ end
+ end
+ end
+
+ describe '#validate_nested_array' do
+ let(:config) { config_struct.new(value: value) }
+
+ subject(:errors) { config.errors }
+
+ before do
+ config.valid?
+ end
+
+ context 'with valid values' do
+ context 'with arrays of integers' do
+ let(:value) { [10, 11] }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'with nested arrays of integers' do
+ let(:value) { [10, [11, 12]] }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ context 'with invalid values' do
+ subject(:error_messages) { errors.messages }
+
+ context 'with single integers' do
+ let(:value) { 10 }
+
+ it { is_expected.to eq({ value: ['is invalid'] }) }
+ end
+
+ context 'when it is nested over the limit' do
+ let(:value) { [10, [11, [12]]] }
+
+ it { is_expected.to eq({ value: ['is invalid'] }) }
+ end
+
+ context 'when a value in the array is not valid' do
+ let(:value) { [10, 11.5] }
+
+ it { is_expected.to eq({ value: ['is invalid'] }) }
+ end
+
+ context 'when a value in the nested array is not valid' do
+ let(:value) { [10, [11, 12.5]] }
+
+ it { is_expected.to eq({ value: ['is invalid'] }) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/crypto_helper_spec.rb b/spec/lib/gitlab/crypto_helper_spec.rb
index c07089d8ef0..024564ea213 100644
--- a/spec/lib/gitlab/crypto_helper_spec.rb
+++ b/spec/lib/gitlab/crypto_helper_spec.rb
@@ -19,21 +19,85 @@ RSpec.describe Gitlab::CryptoHelper do
expect(encrypted).to match %r{\A[A-Za-z0-9+/=]+\z}
expect(encrypted).not_to include "\n"
end
+
+ it 'does not save hashed token with iv value in database' do
+ expect { described_class.aes256_gcm_encrypt('some-value') }.not_to change { TokenWithIv.count }
+ end
+
+ it 'encrypts using static iv' do
+ expect(Encryptor).to receive(:encrypt).with(described_class::AES256_GCM_OPTIONS.merge(value: 'some-value', iv: described_class::AES256_GCM_IV_STATIC)).and_return('hashed_value')
+
+ described_class.aes256_gcm_encrypt('some-value')
+ end
end
describe '.aes256_gcm_decrypt' do
- let(:encrypted) { described_class.aes256_gcm_encrypt('some-value') }
+ before do
+ stub_feature_flags(dynamic_nonce_creation: false)
+ end
+
+ context 'when token was encrypted using static nonce' do
+ let(:encrypted) { described_class.aes256_gcm_encrypt('some-value', nonce: described_class::AES256_GCM_IV_STATIC) }
+
+ it 'correctly decrypts encrypted string' do
+ decrypted = described_class.aes256_gcm_decrypt(encrypted)
+
+ expect(decrypted).to eq 'some-value'
+ end
+
+ it 'decrypts a value when it ends with a new line character' do
+ decrypted = described_class.aes256_gcm_decrypt(encrypted + "\n")
- it 'correctly decrypts encrypted string' do
- decrypted = described_class.aes256_gcm_decrypt(encrypted)
+ expect(decrypted).to eq 'some-value'
+ end
- expect(decrypted).to eq 'some-value'
+ it 'does not save hashed token with iv value in database' do
+ expect { described_class.aes256_gcm_decrypt(encrypted) }.not_to change { TokenWithIv.count }
+ end
+
+ context 'with feature flag switched on' do
+ before do
+ stub_feature_flags(dynamic_nonce_creation: true)
+ end
+
+ it 'correctly decrypts encrypted string' do
+ decrypted = described_class.aes256_gcm_decrypt(encrypted)
+
+ expect(decrypted).to eq 'some-value'
+ end
+ end
end
- it 'decrypts a value when it ends with a new line character' do
- decrypted = described_class.aes256_gcm_decrypt(encrypted + "\n")
+ context 'when token was encrypted using random nonce' do
+ let(:value) { 'random-value' }
+
+ # for compatibility with tokens encrypted using dynamic nonce
+ let!(:encrypted) do
+ iv = create_nonce
+ encrypted_token = described_class.create_encrypted_token(value, iv)
+ TokenWithIv.create!(hashed_token: Digest::SHA256.digest(encrypted_token), hashed_plaintext_token: Digest::SHA256.digest(encrypted_token), iv: iv)
+ encrypted_token
+ end
+
+ before do
+ stub_feature_flags(dynamic_nonce_creation: true)
+ end
- expect(decrypted).to eq 'some-value'
+ it 'correctly decrypts encrypted string' do
+ decrypted = described_class.aes256_gcm_decrypt(encrypted)
+
+ expect(decrypted).to eq value
+ end
+
+ it 'does not save hashed token with iv value in database' do
+ expect { described_class.aes256_gcm_decrypt(encrypted) }.not_to change { TokenWithIv.count }
+ end
end
end
+
+ def create_nonce
+ cipher = OpenSSL::Cipher.new('aes-256-gcm')
+ cipher.encrypt # Required before '#random_iv' can be called
+ cipher.random_iv # Ensures that the IV is the correct length respective to the algorithm used.
+ end
end
diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb
index 786db23ffc4..01aceec12c5 100644
--- a/spec/lib/gitlab/current_settings_spec.rb
+++ b/spec/lib/gitlab/current_settings_spec.rb
@@ -194,4 +194,32 @@ RSpec.describe Gitlab::CurrentSettings do
end
end
end
+
+ describe '#current_application_settings?', :use_clean_rails_memory_store_caching do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:current_application_settings?).and_call_original
+ end
+
+ it 'returns true when settings exist' do
+ create(:application_setting,
+ home_page_url: 'http://mydomain.com',
+ signup_enabled: false)
+
+ expect(described_class.current_application_settings?).to eq(true)
+ end
+
+ it 'returns false when settings do not exist' do
+ expect(described_class.current_application_settings?).to eq(false)
+ end
+
+ context 'with cache', :request_store do
+ include_context 'with settings in cache'
+
+ it 'returns an in-memory ApplicationSetting object' do
+ expect(ApplicationSetting).not_to receive(:current)
+
+ expect(described_class.current_application_settings?).to eq(true)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 21503dc1501..76578340f7b 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -218,7 +218,7 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
context 'when `to` is given' do
before do
- Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) }
+ Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project, finished_at: Time.zone.now) }
end
it 'finds records created between `from` and `to` range' do
@@ -230,12 +230,34 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
end
context 'when `from` and `to` are within a day' do
- it 'returns the number of deployments made on that day' do
- freeze_time do
- create(:deployment, :success, project: project)
- options[:from] = options[:to] = Time.now
+ context 'when query_deploymenys_via_finished_at_in_vsa feature flag is off' do
+ before do
+ stub_feature_flags(query_deploymenys_via_finished_at_in_vsa: false)
+ end
+
+ it 'returns the number of deployments made on that day' do
+ freeze_time do
+ create(:deployment, :success, project: project)
+ options[:from] = options[:to] = Time.zone.now
+
+ expect(subject).to eq('1')
+ end
+ end
+ end
+
+ context 'when query_deploymenys_via_finished_at_in_vsa feature flag is off' do
+ before do
+ stub_feature_flags(query_deploymenys_via_finished_at_in_vsa: true)
+ end
+
+ it 'returns the number of deployments made on that day' do
+ freeze_time do
+ create(:deployment, :success, project: project, finished_at: Time.zone.now)
+ options[:from] = Time.zone.now.at_beginning_of_day
+ options[:to] = Time.zone.now.at_end_of_day
- expect(subject).to eq('1')
+ expect(subject).to eq('1')
+ end
end
end
end
diff --git a/spec/lib/gitlab/danger/base_linter_spec.rb b/spec/lib/gitlab/danger/base_linter_spec.rb
deleted file mode 100644
index 0136a0278ae..00000000000
--- a/spec/lib/gitlab/danger/base_linter_spec.rb
+++ /dev/null
@@ -1,193 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-require_relative 'danger_spec_helper'
-
-require 'gitlab/danger/base_linter'
-
-RSpec.describe Gitlab::Danger::BaseLinter do
- let(:commit_class) do
- Struct.new(:message, :sha, :diff_parent)
- end
-
- let(:commit_message) { 'A commit message' }
- let(:commit) { commit_class.new(commit_message, anything, anything) }
-
- subject(:commit_linter) { described_class.new(commit) }
-
- describe '#failed?' do
- context 'with no failures' do
- it { expect(commit_linter).not_to be_failed }
- end
-
- context 'with failures' do
- before do
- commit_linter.add_problem(:subject_too_long, described_class.subject_description)
- end
-
- it { expect(commit_linter).to be_failed }
- end
- end
-
- describe '#add_problem' do
- it 'stores messages in #failures' do
- commit_linter.add_problem(:subject_too_long, '%s')
-
- expect(commit_linter.problems).to eq({ subject_too_long: described_class.problems_mapping[:subject_too_long] })
- end
- end
-
- shared_examples 'a valid commit' do
- it 'does not have any problem' do
- commit_linter.lint_subject
-
- expect(commit_linter.problems).to be_empty
- end
- end
-
- describe '#lint_subject' do
- context 'when subject valid' do
- it_behaves_like 'a valid commit'
- end
-
- context 'when subject is too short' do
- let(:commit_message) { 'A B' }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:subject_too_short, described_class.subject_description)
-
- commit_linter.lint_subject
- end
- end
-
- context 'when subject is too long' do
- let(:commit_message) { 'A B ' + 'C' * described_class::MAX_LINE_LENGTH }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:subject_too_long, described_class.subject_description)
-
- commit_linter.lint_subject
- end
- end
-
- context 'when ignoring length issues for subject having not-ready wording' do
- using RSpec::Parameterized::TableSyntax
-
- let(:final_message) { 'A B C' }
-
- context 'when used as prefix' do
- where(prefix: [
- 'WIP: ',
- 'WIP:',
- 'wIp:',
- '[WIP] ',
- '[WIP]',
- '[draft]',
- '[draft] ',
- '(draft)',
- '(draft) ',
- 'draft - ',
- 'draft: ',
- 'draft:',
- 'DRAFT:'
- ])
-
- with_them do
- it 'does not have any problems' do
- commit_message = prefix + final_message + 'D' * (described_class::MAX_LINE_LENGTH - final_message.size)
- commit = commit_class.new(commit_message, anything, anything)
-
- linter = described_class.new(commit).lint_subject
-
- expect(linter.problems).to be_empty
- end
- end
- end
-
- context 'when used as suffix' do
- where(suffix: %w[WIP draft])
-
- with_them do
- it 'does not have any problems' do
- commit_message = final_message + 'D' * (described_class::MAX_LINE_LENGTH - final_message.size) + suffix
- commit = commit_class.new(commit_message, anything, anything)
-
- linter = described_class.new(commit).lint_subject
-
- expect(linter.problems).to be_empty
- end
- end
- end
- end
-
- context 'when subject does not have enough words and is too long' do
- let(:commit_message) { 'A ' + 'B' * described_class::MAX_LINE_LENGTH }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:subject_too_short, described_class.subject_description)
- expect(commit_linter).to receive(:add_problem).with(:subject_too_long, described_class.subject_description)
-
- commit_linter.lint_subject
- end
- end
-
- context 'when subject starts with lowercase' do
- let(:commit_message) { 'a B C' }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:subject_starts_with_lowercase, described_class.subject_description)
-
- commit_linter.lint_subject
- end
- end
-
- [
- '[ci skip] A commit message',
- '[Ci skip] A commit message',
- '[API] A commit message',
- 'api: A commit message',
- 'API: A commit message',
- 'API: a commit message',
- 'API: a commit message'
- ].each do |message|
- context "when subject is '#{message}'" do
- let(:commit_message) { message }
-
- it 'does not add a problem' do
- expect(commit_linter).not_to receive(:add_problem)
-
- commit_linter.lint_subject
- end
- end
- end
-
- [
- '[ci skip]A commit message',
- '[Ci skip] A commit message',
- '[ci skip] a commit message',
- 'api: a commit message',
- '! A commit message'
- ].each do |message|
- context "when subject is '#{message}'" do
- let(:commit_message) { message }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:subject_starts_with_lowercase, described_class.subject_description)
-
- commit_linter.lint_subject
- end
- end
- end
-
- context 'when subject ends with a period' do
- let(:commit_message) { 'A B C.' }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:subject_ends_with_a_period, described_class.subject_description)
-
- commit_linter.lint_subject
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/changelog_spec.rb b/spec/lib/gitlab/danger/changelog_spec.rb
deleted file mode 100644
index 04c515f1205..00000000000
--- a/spec/lib/gitlab/danger/changelog_spec.rb
+++ /dev/null
@@ -1,229 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require_relative 'danger_spec_helper'
-
-require 'gitlab/danger/changelog'
-
-RSpec.describe Gitlab::Danger::Changelog do
- include DangerSpecHelper
-
- let(:added_files) { nil }
- let(:fake_git) { double('fake-git', added_files: added_files) }
-
- let(:mr_labels) { nil }
- let(:mr_json) { nil }
- let(:fake_gitlab) { double('fake-gitlab', mr_labels: mr_labels, mr_json: mr_json) }
-
- let(:changes_by_category) { nil }
- let(:sanitize_mr_title) { nil }
- let(:ee?) { false }
- let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, sanitize_mr_title: sanitize_mr_title, ee?: ee?) }
-
- let(:fake_danger) { new_fake_danger.include(described_class) }
-
- subject(:changelog) { fake_danger.new(git: fake_git, gitlab: fake_gitlab, helper: fake_helper) }
-
- describe '#required?' do
- subject { changelog.required? }
-
- context 'added files contain a migration' do
- [
- 'db/migrate/20200000000000_new_migration.rb',
- 'db/post_migrate/20200000000000_new_migration.rb'
- ].each do |file_path|
- let(:added_files) { [file_path] }
-
- it { is_expected.to be_truthy }
- end
- end
-
- context 'added files do not contain a migration' do
- [
- 'app/models/model.rb',
- 'app/assets/javascripts/file.js'
- ].each do |file_path|
- let(:added_files) { [file_path] }
-
- it { is_expected.to be_falsey }
- end
- end
- end
-
- describe '#optional?' do
- let(:category_with_changelog) { :backend }
- let(:label_with_changelog) { 'frontend' }
- let(:category_without_changelog) { Gitlab::Danger::Changelog::NO_CHANGELOG_CATEGORIES.first }
- let(:label_without_changelog) { Gitlab::Danger::Changelog::NO_CHANGELOG_LABELS.first }
-
- subject { changelog.optional? }
-
- context 'when MR contains only categories requiring no changelog' do
- let(:changes_by_category) { { category_without_changelog => nil } }
- let(:mr_labels) { [] }
-
- it 'is falsey' do
- is_expected.to be_falsy
- end
- end
-
- context 'when MR contains a label that require no changelog' do
- let(:changes_by_category) { { category_with_changelog => nil } }
- let(:mr_labels) { [label_with_changelog, label_without_changelog] }
-
- it 'is falsey' do
- is_expected.to be_falsy
- end
- end
-
- context 'when MR contains a category that require changelog and a category that require no changelog' do
- let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
- let(:mr_labels) { [] }
-
- it 'is truthy' do
- is_expected.to be_truthy
- end
- end
-
- context 'when MR contains a category that require changelog and a category that require no changelog with changelog label' do
- let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
- let(:mr_labels) { ['feature'] }
-
- it 'is truthy' do
- is_expected.to be_truthy
- end
- end
-
- context 'when MR contains a category that require changelog and a category that require no changelog with no changelog label' do
- let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
- let(:mr_labels) { ['tooling'] }
-
- it 'is truthy' do
- is_expected.to be_falsey
- end
- end
- end
-
- describe '#found' do
- subject { changelog.found }
-
- context 'added files contain a changelog' do
- [
- 'changelogs/unreleased/entry.yml',
- 'ee/changelogs/unreleased/entry.yml'
- ].each do |file_path|
- let(:added_files) { [file_path] }
-
- it { is_expected.to be_truthy }
- end
- end
-
- context 'added files do not contain a changelog' do
- [
- 'app/models/model.rb',
- 'app/assets/javascripts/file.js'
- ].each do |file_path|
- let(:added_files) { [file_path] }
- it { is_expected.to eq(nil) }
- end
- end
- end
-
- describe '#ee_changelog?' do
- subject { changelog.ee_changelog? }
-
- before do
- allow(changelog).to receive(:found).and_return(file_path)
- end
-
- context 'is ee changelog' do
- let(:file_path) { 'ee/changelogs/unreleased/entry.yml' }
-
- it { is_expected.to be_truthy }
- end
-
- context 'is not ee changelog' do
- let(:file_path) { 'changelogs/unreleased/entry.yml' }
-
- it { is_expected.to be_falsy }
- end
- end
-
- describe '#modified_text' do
- let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
-
- subject { changelog.modified_text }
-
- context "when title is not changed from sanitization", :aggregate_failures do
- let(:sanitize_mr_title) { 'Fake Title' }
-
- specify do
- expect(subject).to include('CHANGELOG.md was edited')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
- end
- end
-
- context "when title needs sanitization", :aggregate_failures do
- let(:sanitize_mr_title) { 'DRAFT: Fake Title' }
-
- specify do
- expect(subject).to include('CHANGELOG.md was edited')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
- end
- end
- end
-
- describe '#required_text' do
- let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
-
- subject { changelog.required_text }
-
- context "when title is not changed from sanitization", :aggregate_failures do
- let(:sanitize_mr_title) { 'Fake Title' }
-
- specify do
- expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).not_to include('--ee')
- end
- end
-
- context "when title needs sanitization", :aggregate_failures do
- let(:sanitize_mr_title) { 'DRAFT: Fake Title' }
-
- specify do
- expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).not_to include('--ee')
- end
- end
- end
-
- describe '#optional_text' do
- let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
-
- subject { changelog.optional_text }
-
- context "when title is not changed from sanitization", :aggregate_failures do
- let(:sanitize_mr_title) { 'Fake Title' }
-
- specify do
- expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
- end
- end
-
- context "when title needs sanitization", :aggregate_failures do
- let(:sanitize_mr_title) { 'DRAFT: Fake Title' }
-
- specify do
- expect(subject).to include('CHANGELOG missing')
- expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
- expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/commit_linter_spec.rb b/spec/lib/gitlab/danger/commit_linter_spec.rb
deleted file mode 100644
index d3d86037a53..00000000000
--- a/spec/lib/gitlab/danger/commit_linter_spec.rb
+++ /dev/null
@@ -1,242 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-require_relative 'danger_spec_helper'
-
-require 'gitlab/danger/commit_linter'
-
-RSpec.describe Gitlab::Danger::CommitLinter do
- using RSpec::Parameterized::TableSyntax
-
- let(:total_files_changed) { 2 }
- let(:total_lines_changed) { 10 }
- let(:stats) { { total: { files: total_files_changed, lines: total_lines_changed } } }
- let(:diff_parent) { Struct.new(:stats).new(stats) }
- let(:commit_class) do
- Struct.new(:message, :sha, :diff_parent)
- end
-
- let(:commit_message) { 'A commit message' }
- let(:commit_sha) { 'abcd1234' }
- let(:commit) { commit_class.new(commit_message, commit_sha, diff_parent) }
-
- subject(:commit_linter) { described_class.new(commit) }
-
- describe '#fixup?' do
- where(:commit_message, :is_fixup) do
- 'A commit message' | false
- 'fixup!' | true
- 'fixup! A commit message' | true
- 'squash!' | true
- 'squash! A commit message' | true
- end
-
- with_them do
- it 'is true when commit message starts with "fixup!" or "squash!"' do
- expect(commit_linter.fixup?).to be(is_fixup)
- end
- end
- end
-
- describe '#suggestion?' do
- where(:commit_message, :is_suggestion) do
- 'A commit message' | false
- 'Apply suggestion to' | true
- 'Apply suggestion to "A commit message"' | true
- end
-
- with_them do
- it 'is true when commit message starts with "Apply suggestion to"' do
- expect(commit_linter.suggestion?).to be(is_suggestion)
- end
- end
- end
-
- describe '#merge?' do
- where(:commit_message, :is_merge) do
- 'A commit message' | false
- 'Merge branch' | true
- 'Merge branch "A commit message"' | true
- end
-
- with_them do
- it 'is true when commit message starts with "Merge branch"' do
- expect(commit_linter.merge?).to be(is_merge)
- end
- end
- end
-
- describe '#revert?' do
- where(:commit_message, :is_revert) do
- 'A commit message' | false
- 'Revert' | false
- 'Revert "' | true
- 'Revert "A commit message"' | true
- end
-
- with_them do
- it 'is true when commit message starts with "Revert \""' do
- expect(commit_linter.revert?).to be(is_revert)
- end
- end
- end
-
- describe '#multi_line?' do
- where(:commit_message, :is_multi_line) do
- "A commit message" | false
- "A commit message\n" | false
- "A commit message\n\n" | false
- "A commit message\n\nSigned-off-by: User Name <user@name.me>" | false
- "A commit message\n\nWith details" | true
- end
-
- with_them do
- it 'is true when commit message contains details' do
- expect(commit_linter.multi_line?).to be(is_multi_line)
- end
- end
- end
-
- shared_examples 'a valid commit' do
- it 'does not have any problem' do
- commit_linter.lint
-
- expect(commit_linter.problems).to be_empty
- end
- end
-
- describe '#lint' do
- describe 'separator' do
- context 'when separator is missing' do
- let(:commit_message) { "A B C\n" }
-
- it_behaves_like 'a valid commit'
- end
-
- context 'when separator is a blank line' do
- let(:commit_message) { "A B C\n\nMore details." }
-
- it_behaves_like 'a valid commit'
- end
-
- context 'when separator is missing' do
- let(:commit_message) { "A B C\nMore details." }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:separator_missing)
-
- commit_linter.lint
- end
- end
- end
-
- describe 'details' do
- context 'when details are valid' do
- let(:commit_message) { "A B C\n\nMore details." }
-
- it_behaves_like 'a valid commit'
- end
-
- context 'when no details are given and many files are changed' do
- let(:total_files_changed) { described_class::MAX_CHANGED_FILES_IN_COMMIT + 1 }
-
- it_behaves_like 'a valid commit'
- end
-
- context 'when no details are given and many lines are changed' do
- let(:total_lines_changed) { described_class::MAX_CHANGED_LINES_IN_COMMIT + 1 }
-
- it_behaves_like 'a valid commit'
- end
-
- context 'when no details are given and many files and lines are changed' do
- let(:total_files_changed) { described_class::MAX_CHANGED_FILES_IN_COMMIT + 1 }
- let(:total_lines_changed) { described_class::MAX_CHANGED_LINES_IN_COMMIT + 1 }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:details_too_many_changes)
-
- commit_linter.lint
- end
- end
-
- context 'when details exceeds the max line length' do
- let(:commit_message) { "A B C\n\n" + 'D' * (described_class::MAX_LINE_LENGTH + 1) }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:details_line_too_long)
-
- commit_linter.lint
- end
- end
-
- context 'when details exceeds the max line length including URLs' do
- let(:commit_message) do
- "A B C\n\nsome message with https://example.com and https://gitlab.com" + 'D' * described_class::MAX_LINE_LENGTH
- end
-
- it_behaves_like 'a valid commit'
- end
- end
-
- describe 'message' do
- context 'when message includes a text emoji' do
- let(:commit_message) { "A commit message :+1:" }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:message_contains_text_emoji)
-
- commit_linter.lint
- end
- end
-
- context 'when message includes a unicode emoji' do
- let(:commit_message) { "A commit message 🚀" }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:message_contains_unicode_emoji)
-
- commit_linter.lint
- end
- end
-
- context 'when message includes a value that is surrounded by backticks' do
- let(:commit_message) { "A commit message `%20`" }
-
- it 'does not add a problem' do
- expect(commit_linter).not_to receive(:add_problem)
-
- commit_linter.lint
- end
- end
-
- context 'when message includes a short reference' do
- [
- 'A commit message to fix #1234',
- 'A commit message to fix !1234',
- 'A commit message to fix &1234',
- 'A commit message to fix %1234',
- 'A commit message to fix gitlab#1234',
- 'A commit message to fix gitlab!1234',
- 'A commit message to fix gitlab&1234',
- 'A commit message to fix gitlab%1234',
- 'A commit message to fix gitlab-org/gitlab#1234',
- 'A commit message to fix gitlab-org/gitlab!1234',
- 'A commit message to fix gitlab-org/gitlab&1234',
- 'A commit message to fix gitlab-org/gitlab%1234',
- 'A commit message to fix "gitlab-org/gitlab%1234"',
- 'A commit message to fix `gitlab-org/gitlab%1234'
- ].each do |message|
- let(:commit_message) { message }
-
- it 'adds a problem' do
- expect(commit_linter).to receive(:add_problem).with(:message_contains_short_reference)
-
- commit_linter.lint
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/emoji_checker_spec.rb b/spec/lib/gitlab/danger/emoji_checker_spec.rb
deleted file mode 100644
index 6092c751e1c..00000000000
--- a/spec/lib/gitlab/danger/emoji_checker_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-
-require 'gitlab/danger/emoji_checker'
-
-RSpec.describe Gitlab::Danger::EmojiChecker do
- using RSpec::Parameterized::TableSyntax
-
- describe '#includes_text_emoji?' do
- where(:text, :includes_emoji) do
- 'Hello World!' | false
- ':+1:' | true
- 'Hello World! :+1:' | true
- end
-
- with_them do
- it 'is true when text includes a text emoji' do
- expect(subject.includes_text_emoji?(text)).to be(includes_emoji)
- end
- end
- end
-
- describe '#includes_unicode_emoji?' do
- where(:text, :includes_emoji) do
- 'Hello World!' | false
- '🚀' | true
- 'Hello World! 🚀' | true
- end
-
- with_them do
- it 'is true when text includes a text emoji' do
- expect(subject.includes_unicode_emoji?(text)).to be(includes_emoji)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
deleted file mode 100644
index bd5c746dd54..00000000000
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ /dev/null
@@ -1,602 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-require_relative 'danger_spec_helper'
-
-require 'gitlab/danger/helper'
-
-RSpec.describe Gitlab::Danger::Helper do
- using RSpec::Parameterized::TableSyntax
- include DangerSpecHelper
-
- let(:fake_git) { double('fake-git') }
-
- let(:mr_author) { nil }
- let(:fake_gitlab) { double('fake-gitlab', mr_author: mr_author) }
-
- let(:fake_danger) { new_fake_danger.include(described_class) }
-
- subject(:helper) { fake_danger.new(git: fake_git, gitlab: fake_gitlab) }
-
- describe '#gitlab_helper' do
- context 'when gitlab helper is not available' do
- let(:fake_gitlab) { nil }
-
- it 'returns nil' do
- expect(helper.gitlab_helper).to be_nil
- end
- end
-
- context 'when gitlab helper is available' do
- it 'returns the gitlab helper' do
- expect(helper.gitlab_helper).to eq(fake_gitlab)
- end
- end
-
- context 'when danger gitlab plugin is not available' do
- it 'returns nil' do
- invalid_danger = Class.new do
- include Gitlab::Danger::Helper
- end.new
-
- expect(invalid_danger.gitlab_helper).to be_nil
- end
- end
- end
-
- describe '#release_automation?' do
- context 'when gitlab helper is not available' do
- it 'returns false' do
- expect(helper.release_automation?).to be_falsey
- end
- end
-
- context 'when gitlab helper is available' do
- context "but the MR author isn't the RELEASE_TOOLS_BOT" do
- let(:mr_author) { 'johnmarston' }
-
- it 'returns false' do
- expect(helper.release_automation?).to be_falsey
- end
- end
-
- context 'and the MR author is the RELEASE_TOOLS_BOT' do
- let(:mr_author) { described_class::RELEASE_TOOLS_BOT }
-
- it 'returns true' do
- expect(helper.release_automation?).to be_truthy
- end
- end
- end
- end
-
- describe '#all_changed_files' do
- subject { helper.all_changed_files }
-
- it 'interprets a list of changes from the danger git plugin' do
- expect(fake_git).to receive(:added_files) { %w[a b c.old] }
- expect(fake_git).to receive(:modified_files) { %w[d e] }
- expect(fake_git)
- .to receive(:renamed_files)
- .at_least(:once)
- .and_return([{ before: 'c.old', after: 'c.new' }])
-
- is_expected.to contain_exactly('a', 'b', 'c.new', 'd', 'e')
- end
- end
-
- describe '#changed_lines' do
- subject { helper.changed_lines('changed_file.rb') }
-
- before do
- allow(fake_git).to receive(:diff_for_file).with('changed_file.rb').and_return(diff)
- end
-
- context 'when file has diff' do
- let(:diff) { double(:diff, patch: "+ # New change here\n+ # New change there") }
-
- it 'returns file changes' do
- is_expected.to eq(['+ # New change here', '+ # New change there'])
- end
- end
-
- context 'when file has no diff (renamed without changes)' do
- let(:diff) { nil }
-
- it 'returns a blank array' do
- is_expected.to eq([])
- end
- end
- end
-
- describe "changed_files" do
- it 'returns list of changed files matching given regex' do
- expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb usage_data.rb])
-
- expect(helper.changed_files(/usage_data/)).to contain_exactly('usage_data.rb')
- end
- end
-
- describe '#all_ee_changes' do
- subject { helper.all_ee_changes }
-
- it 'returns all changed files starting with ee/' do
- expect(helper).to receive(:all_changed_files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k])
-
- is_expected.to match_array(%w[ee/wine.rb ee/lib/ido.rb])
- end
- end
-
- describe '#ee?' do
- subject { helper.ee? }
-
- it 'returns true if CI_PROJECT_NAME if set to gitlab' do
- stub_env('CI_PROJECT_NAME', 'gitlab')
- expect(Dir).not_to receive(:exist?)
-
- is_expected.to be_truthy
- end
-
- it 'delegates to CHANGELOG-EE.md existence if CI_PROJECT_NAME is set to something else' do
- stub_env('CI_PROJECT_NAME', 'something else')
- expect(Dir).to receive(:exist?).with(File.expand_path('../../../../ee', __dir__)) { true }
-
- is_expected.to be_truthy
- end
-
- it 'returns true if ee exists' do
- stub_env('CI_PROJECT_NAME', nil)
- expect(Dir).to receive(:exist?).with(File.expand_path('../../../../ee', __dir__)) { true }
-
- is_expected.to be_truthy
- end
-
- it "returns false if ee doesn't exist" do
- stub_env('CI_PROJECT_NAME', nil)
- expect(Dir).to receive(:exist?).with(File.expand_path('../../../../ee', __dir__)) { false }
-
- is_expected.to be_falsy
- end
- end
-
- describe '#project_name' do
- subject { helper.project_name }
-
- it 'returns gitlab if ee? returns true' do
- expect(helper).to receive(:ee?) { true }
-
- is_expected.to eq('gitlab')
- end
-
- it 'returns gitlab-ce if ee? returns false' do
- expect(helper).to receive(:ee?) { false }
-
- is_expected.to eq('gitlab-foss')
- end
- end
-
- describe '#markdown_list' do
- it 'creates a markdown list of items' do
- items = %w[a b]
-
- expect(helper.markdown_list(items)).to eq("* `a`\n* `b`")
- end
-
- it 'wraps items in <details> when there are more than 10 items' do
- items = ('a'..'k').to_a
-
- expect(helper.markdown_list(items)).to match(%r{<details>[^<]+</details>})
- end
- end
-
- describe '#changes_by_category' do
- it 'categorizes changed files' do
- expect(fake_git).to receive(:added_files) { %w[foo foo.md foo.rb foo.js db/migrate/foo lib/gitlab/database/foo.rb qa/foo ee/changelogs/foo.yml] }
- allow(fake_git).to receive(:modified_files) { [] }
- allow(fake_git).to receive(:renamed_files) { [] }
-
- expect(helper.changes_by_category).to eq(
- backend: %w[foo.rb],
- database: %w[db/migrate/foo lib/gitlab/database/foo.rb],
- frontend: %w[foo.js],
- none: %w[ee/changelogs/foo.yml foo.md],
- qa: %w[qa/foo],
- unknown: %w[foo]
- )
- end
- end
-
- describe '#categories_for_file' do
- before do
- allow(fake_git).to receive(:diff_for_file).with('usage_data.rb') { double(:diff, patch: "+ count(User.active)") }
- end
-
- where(:path, :expected_categories) do
- 'usage_data.rb' | [:database, :backend]
- 'doc/foo.md' | [:docs]
- 'CONTRIBUTING.md' | [:docs]
- 'LICENSE' | [:docs]
- 'MAINTENANCE.md' | [:docs]
- 'PHILOSOPHY.md' | [:docs]
- 'PROCESS.md' | [:docs]
- 'README.md' | [:docs]
-
- 'ee/doc/foo' | [:unknown]
- 'ee/README' | [:unknown]
-
- 'app/assets/foo' | [:frontend]
- 'app/views/foo' | [:frontend]
- 'public/foo' | [:frontend]
- 'scripts/frontend/foo' | [:frontend]
- 'spec/javascripts/foo' | [:frontend]
- 'spec/frontend/bar' | [:frontend]
- 'vendor/assets/foo' | [:frontend]
- 'babel.config.js' | [:frontend]
- 'jest.config.js' | [:frontend]
- 'package.json' | [:frontend]
- 'yarn.lock' | [:frontend]
- 'config/foo.js' | [:frontend]
- 'config/deep/foo.js' | [:frontend]
-
- 'ee/app/assets/foo' | [:frontend]
- 'ee/app/views/foo' | [:frontend]
- 'ee/spec/javascripts/foo' | [:frontend]
- 'ee/spec/frontend/bar' | [:frontend]
-
- '.gitlab/ci/frontend.gitlab-ci.yml' | %i[frontend engineering_productivity]
-
- 'app/models/foo' | [:backend]
- 'bin/foo' | [:backend]
- 'config/foo' | [:backend]
- 'lib/foo' | [:backend]
- 'rubocop/foo' | [:backend]
- '.rubocop.yml' | [:backend]
- '.rubocop_todo.yml' | [:backend]
- '.rubocop_manual_todo.yml' | [:backend]
- 'spec/foo' | [:backend]
- 'spec/foo/bar' | [:backend]
-
- 'ee/app/foo' | [:backend]
- 'ee/bin/foo' | [:backend]
- 'ee/spec/foo' | [:backend]
- 'ee/spec/foo/bar' | [:backend]
-
- 'spec/features/foo' | [:test]
- 'ee/spec/features/foo' | [:test]
- 'spec/support/shared_examples/features/foo' | [:test]
- 'ee/spec/support/shared_examples/features/foo' | [:test]
- 'spec/support/shared_contexts/features/foo' | [:test]
- 'ee/spec/support/shared_contexts/features/foo' | [:test]
- 'spec/support/helpers/features/foo' | [:test]
- 'ee/spec/support/helpers/features/foo' | [:test]
-
- 'generator_templates/foo' | [:backend]
- 'vendor/languages.yml' | [:backend]
- 'file_hooks/examples/' | [:backend]
-
- 'Gemfile' | [:backend]
- 'Gemfile.lock' | [:backend]
- 'Rakefile' | [:backend]
- 'FOO_VERSION' | [:backend]
-
- 'Dangerfile' | [:engineering_productivity]
- 'danger/commit_messages/Dangerfile' | [:engineering_productivity]
- 'ee/danger/commit_messages/Dangerfile' | [:engineering_productivity]
- 'danger/commit_messages/' | [:engineering_productivity]
- 'ee/danger/commit_messages/' | [:engineering_productivity]
- '.gitlab-ci.yml' | [:engineering_productivity]
- '.gitlab/ci/cng.gitlab-ci.yml' | [:engineering_productivity]
- '.gitlab/ci/ee-specific-checks.gitlab-ci.yml' | [:engineering_productivity]
- 'scripts/foo' | [:engineering_productivity]
- 'lib/gitlab/danger/foo' | [:engineering_productivity]
- 'ee/lib/gitlab/danger/foo' | [:engineering_productivity]
- 'lefthook.yml' | [:engineering_productivity]
- '.editorconfig' | [:engineering_productivity]
- 'tooling/bin/find_foss_tests' | [:engineering_productivity]
- '.codeclimate.yml' | [:engineering_productivity]
- '.gitlab/CODEOWNERS' | [:engineering_productivity]
-
- 'lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' | [:ci_template]
- 'lib/gitlab/ci/templates/dotNET-Core.yml' | [:ci_template]
-
- 'ee/FOO_VERSION' | [:unknown]
-
- 'db/schema.rb' | [:database]
- 'db/structure.sql' | [:database]
- 'db/migrate/foo' | [:database]
- 'db/post_migrate/foo' | [:database]
- 'ee/db/migrate/foo' | [:database]
- 'ee/db/post_migrate/foo' | [:database]
- 'ee/db/geo/migrate/foo' | [:database]
- 'ee/db/geo/post_migrate/foo' | [:database]
- 'app/models/project_authorization.rb' | [:database]
- 'app/services/users/refresh_authorized_projects_service.rb' | [:database]
- 'lib/gitlab/background_migration.rb' | [:database]
- 'lib/gitlab/background_migration/foo' | [:database]
- 'ee/lib/gitlab/background_migration/foo' | [:database]
- 'lib/gitlab/database.rb' | [:database]
- 'lib/gitlab/database/foo' | [:database]
- 'ee/lib/gitlab/database/foo' | [:database]
- 'lib/gitlab/github_import.rb' | [:database]
- 'lib/gitlab/github_import/foo' | [:database]
- 'lib/gitlab/sql/foo' | [:database]
- 'rubocop/cop/migration/foo' | [:database]
-
- 'db/fixtures/foo.rb' | [:backend]
- 'ee/db/fixtures/foo.rb' | [:backend]
- 'doc/api/graphql/reference/gitlab_schema.graphql' | [:backend]
- 'doc/api/graphql/reference/gitlab_schema.json' | [:backend]
-
- 'qa/foo' | [:qa]
- 'ee/qa/foo' | [:qa]
-
- 'changelogs/foo' | [:none]
- 'ee/changelogs/foo' | [:none]
- 'locale/gitlab.pot' | [:none]
-
- 'FOO' | [:unknown]
- 'foo' | [:unknown]
-
- 'foo/bar.rb' | [:backend]
- 'foo/bar.js' | [:frontend]
- 'foo/bar.txt' | [:none]
- 'foo/bar.md' | [:none]
- end
-
- with_them do
- subject { helper.categories_for_file(path) }
-
- it { is_expected.to eq(expected_categories) }
- end
-
- context 'having specific changes' do
- where(:expected_categories, :patch, :changed_files) do
- [:database, :backend] | '+ count(User.active)' | ['usage_data.rb', 'lib/gitlab/usage_data.rb', 'ee/lib/ee/gitlab/usage_data.rb']
- [:database, :backend] | '+ estimate_batch_distinct_count(User.active)' | ['usage_data.rb']
- [:backend] | '+ alt_usage_data(User.active)' | ['usage_data.rb']
- [:backend] | '+ count(User.active)' | ['user.rb']
- [:backend] | '+ count(User.active)' | ['usage_data/topology.rb']
- [:backend] | '+ foo_count(User.active)' | ['usage_data.rb']
- end
-
- with_them do
- it 'has the correct categories' do
- changed_files.each do |file|
- allow(fake_git).to receive(:diff_for_file).with(file) { double(:diff, patch: patch) }
-
- expect(helper.categories_for_file(file)).to eq(expected_categories)
- end
- end
- end
- end
- end
-
- describe '#label_for_category' do
- where(:category, :expected_label) do
- :backend | '~backend'
- :database | '~database'
- :docs | '~documentation'
- :foo | '~foo'
- :frontend | '~frontend'
- :none | ''
- :qa | '~QA'
- :engineering_productivity | '~"Engineering Productivity" for CI, Danger'
- :ci_template | '~"ci::templates"'
- end
-
- with_them do
- subject { helper.label_for_category(category) }
-
- it { is_expected.to eq(expected_label) }
- end
- end
-
- describe '#new_teammates' do
- it 'returns an array of Teammate' do
- usernames = %w[filipa iamphil]
-
- teammates = helper.new_teammates(usernames)
-
- expect(teammates.map(&:username)).to eq(usernames)
- end
- end
-
- describe '#security_mr?' do
- it 'returns false when `gitlab_helper` is unavailable' do
- expect(helper).to receive(:gitlab_helper).and_return(nil)
-
- expect(helper).not_to be_security_mr
- end
-
- it 'returns false when on a normal merge request' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('web_url' => 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1')
-
- expect(helper).not_to be_security_mr
- end
-
- it 'returns true when on a security merge request' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('web_url' => 'https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/1')
-
- expect(helper).to be_security_mr
- end
- end
-
- describe '#draft_mr?' do
- it 'returns false when `gitlab_helper` is unavailable' do
- expect(helper).to receive(:gitlab_helper).and_return(nil)
-
- expect(helper).not_to be_draft_mr
- end
-
- it 'returns true for a draft MR' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('title' => 'Draft: My MR title')
-
- expect(helper).to be_draft_mr
- end
-
- it 'returns false for non draft MR' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('title' => 'My MR title')
-
- expect(helper).not_to be_draft_mr
- end
- end
-
- describe '#cherry_pick_mr?' do
- it 'returns false when `gitlab_helper` is unavailable' do
- expect(helper).to receive(:gitlab_helper).and_return(nil)
-
- expect(helper).not_to be_cherry_pick_mr
- end
-
- context 'when MR title does not mention a cherry-pick' do
- it 'returns false' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('title' => 'Add feature xyz')
-
- expect(helper).not_to be_cherry_pick_mr
- end
- end
-
- context 'when MR title mentions a cherry-pick' do
- [
- 'Cherry Pick !1234',
- 'cherry-pick !1234',
- 'CherryPick !1234'
- ].each do |mr_title|
- it 'returns true' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('title' => mr_title)
-
- expect(helper).to be_cherry_pick_mr
- end
- end
- end
- end
-
- describe '#stable_branch?' do
- it 'returns false when `gitlab_helper` is unavailable' do
- expect(helper).to receive(:gitlab_helper).and_return(nil)
-
- expect(helper).not_to be_stable_branch
- end
-
- context 'when MR target branch is not a stable branch' do
- it 'returns false' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('target_branch' => 'my-feature-branch')
-
- expect(helper).not_to be_stable_branch
- end
- end
-
- context 'when MR target branch is a stable branch' do
- %w[
- 13-1-stable-ee
- 13-1-stable-ee-patch-1
- ].each do |target_branch|
- it 'returns true' do
- expect(fake_gitlab).to receive(:mr_json)
- .and_return('target_branch' => target_branch)
-
- expect(helper).to be_stable_branch
- end
- end
- end
- end
-
- describe '#mr_has_label?' do
- it 'returns false when `gitlab_helper` is unavailable' do
- expect(helper).to receive(:gitlab_helper).and_return(nil)
-
- expect(helper.mr_has_labels?('telemetry')).to be_falsey
- end
-
- context 'when mr has labels' do
- before do
- mr_labels = ['telemetry', 'telemetry::reviewed']
- expect(fake_gitlab).to receive(:mr_labels).and_return(mr_labels)
- end
-
- it 'returns true with a matched label' do
- expect(helper.mr_has_labels?('telemetry')).to be_truthy
- end
-
- it 'returns false with unmatched label' do
- expect(helper.mr_has_labels?('database')).to be_falsey
- end
-
- it 'returns true with an array of labels' do
- expect(helper.mr_has_labels?(['telemetry', 'telemetry::reviewed'])).to be_truthy
- end
-
- it 'returns true with multi arguments with matched labels' do
- expect(helper.mr_has_labels?('telemetry', 'telemetry::reviewed')).to be_truthy
- end
-
- it 'returns false with multi arguments with unmatched labels' do
- expect(helper.mr_has_labels?('telemetry', 'telemetry::non existing')).to be_falsey
- end
- end
- end
-
- describe '#labels_list' do
- let(:labels) { ['telemetry', 'telemetry::reviewed'] }
-
- it 'composes the labels string' do
- expect(helper.labels_list(labels)).to eq('~"telemetry", ~"telemetry::reviewed"')
- end
-
- context 'when passing a separator' do
- it 'composes the labels string with the given separator' do
- expect(helper.labels_list(labels, sep: ' ')).to eq('~"telemetry" ~"telemetry::reviewed"')
- end
- end
-
- it 'returns empty string for empty array' do
- expect(helper.labels_list([])).to eq('')
- end
- end
-
- describe '#prepare_labels_for_mr' do
- it 'composes the labels string' do
- mr_labels = ['telemetry', 'telemetry::reviewed']
-
- expect(helper.prepare_labels_for_mr(mr_labels)).to eq('/label ~"telemetry" ~"telemetry::reviewed"')
- end
-
- it 'returns empty string for empty array' do
- expect(helper.prepare_labels_for_mr([])).to eq('')
- end
- end
-
- describe '#has_ci_changes?' do
- context 'when .gitlab/ci is changed' do
- it 'returns true' do
- expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb .gitlab/ci/test.yml])
-
- expect(helper.has_ci_changes?).to be_truthy
- end
- end
-
- context 'when .gitlab-ci.yml is changed' do
- it 'returns true' do
- expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb .gitlab-ci.yml])
-
- expect(helper.has_ci_changes?).to be_truthy
- end
- end
-
- context 'when neither .gitlab/ci/ or .gitlab-ci.yml is changed' do
- it 'returns false' do
- expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb nested/.gitlab-ci.yml])
-
- expect(helper.has_ci_changes?).to be_falsey
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/merge_request_linter_spec.rb b/spec/lib/gitlab/danger/merge_request_linter_spec.rb
deleted file mode 100644
index 29facc9fdd6..00000000000
--- a/spec/lib/gitlab/danger/merge_request_linter_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-require_relative 'danger_spec_helper'
-
-require 'gitlab/danger/merge_request_linter'
-
-RSpec.describe Gitlab::Danger::MergeRequestLinter do
- using RSpec::Parameterized::TableSyntax
-
- let(:mr_class) do
- Struct.new(:message, :sha, :diff_parent)
- end
-
- let(:mr_title) { 'A B ' + 'C' }
- let(:merge_request) { mr_class.new(mr_title, anything, anything) }
-
- describe '#lint_subject' do
- subject(:mr_linter) { described_class.new(merge_request) }
-
- shared_examples 'a valid mr title' do
- it 'does not have any problem' do
- mr_linter.lint
-
- expect(mr_linter.problems).to be_empty
- end
- end
-
- context 'when subject valid' do
- it_behaves_like 'a valid mr title'
- end
-
- context 'when it is too long' do
- let(:mr_title) { 'A B ' + 'C' * described_class::MAX_LINE_LENGTH }
-
- it 'adds a problem' do
- expect(mr_linter).to receive(:add_problem).with(:subject_too_long, described_class.subject_description)
-
- mr_linter.lint
- end
- end
-
- describe 'using magic mr run options' do
- where(run_option: described_class.mr_run_options_regex.split('|') +
- described_class.mr_run_options_regex.split('|').map! { |x| "[#{x}]" })
-
- with_them do
- let(:mr_title) { run_option + ' A B ' + 'C' * (described_class::MAX_LINE_LENGTH - 5) }
-
- it_behaves_like 'a valid mr title'
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/roulette_spec.rb b/spec/lib/gitlab/danger/roulette_spec.rb
deleted file mode 100644
index 59ac3b12b6b..00000000000
--- a/spec/lib/gitlab/danger/roulette_spec.rb
+++ /dev/null
@@ -1,413 +0,0 @@
-# frozen_string_literal: true
-
-require 'webmock/rspec'
-require 'timecop'
-
-require 'gitlab/danger/roulette'
-require 'active_support/testing/time_helpers'
-
-RSpec.describe Gitlab::Danger::Roulette do
- include ActiveSupport::Testing::TimeHelpers
-
- around do |example|
- travel_to(Time.utc(2020, 06, 22, 10)) { example.run }
- end
-
- let(:backend_available) { true }
- let(:backend_tz_offset_hours) { 2.0 }
- let(:backend_maintainer) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'backend-maintainer',
- 'name' => 'Backend maintainer',
- 'role' => 'Backend engineer',
- 'projects' => { 'gitlab' => 'maintainer backend' },
- 'available' => backend_available,
- 'tz_offset_hours' => backend_tz_offset_hours
- )
- end
-
- let(:frontend_reviewer) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'frontend-reviewer',
- 'name' => 'Frontend reviewer',
- 'role' => 'Frontend engineer',
- 'projects' => { 'gitlab' => 'reviewer frontend' },
- 'available' => true,
- 'tz_offset_hours' => 2.0
- )
- end
-
- let(:frontend_maintainer) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'frontend-maintainer',
- 'name' => 'Frontend maintainer',
- 'role' => 'Frontend engineer',
- 'projects' => { 'gitlab' => "maintainer frontend" },
- 'available' => true,
- 'tz_offset_hours' => 2.0
- )
- end
-
- let(:software_engineer_in_test) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'software-engineer-in-test',
- 'name' => 'Software Engineer in Test',
- 'role' => 'Software Engineer in Test, Create:Source Code',
- 'projects' => { 'gitlab' => 'reviewer qa', 'gitlab-qa' => 'maintainer' },
- 'available' => true,
- 'tz_offset_hours' => 2.0
- )
- end
-
- let(:engineering_productivity_reviewer) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'eng-prod-reviewer',
- 'name' => 'EP engineer',
- 'role' => 'Engineering Productivity',
- 'projects' => { 'gitlab' => 'reviewer backend' },
- 'available' => true,
- 'tz_offset_hours' => 2.0
- )
- end
-
- let(:ci_template_reviewer) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'ci-template-maintainer',
- 'name' => 'CI Template engineer',
- 'role' => '~"ci::templates"',
- 'projects' => { 'gitlab' => 'reviewer ci_template' },
- 'available' => true,
- 'tz_offset_hours' => 2.0
- )
- end
-
- let(:teammates) do
- [
- backend_maintainer.to_h,
- frontend_maintainer.to_h,
- frontend_reviewer.to_h,
- software_engineer_in_test.to_h,
- engineering_productivity_reviewer.to_h,
- ci_template_reviewer.to_h
- ]
- end
-
- let(:teammate_json) do
- teammates.to_json
- end
-
- subject(:roulette) { Object.new.extend(described_class) }
-
- describe 'Spin#==' do
- it 'compares Spin attributes' do
- spin1 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, false, false)
- spin2 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, false, false)
- spin3 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, false, true)
- spin4 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, true, false)
- spin5 = described_class::Spin.new(:backend, frontend_reviewer, backend_maintainer, false, false)
- spin6 = described_class::Spin.new(:backend, backend_maintainer, frontend_maintainer, false, false)
- spin7 = described_class::Spin.new(:frontend, frontend_reviewer, frontend_maintainer, false, false)
-
- expect(spin1).to eq(spin2)
- expect(spin1).not_to eq(spin3)
- expect(spin1).not_to eq(spin4)
- expect(spin1).not_to eq(spin5)
- expect(spin1).not_to eq(spin6)
- expect(spin1).not_to eq(spin7)
- end
- end
-
- describe '#spin' do
- let!(:project) { 'gitlab' }
- let!(:mr_source_branch) { 'a-branch' }
- let!(:mr_labels) { ['backend', 'devops::create'] }
- let!(:author) { Gitlab::Danger::Teammate.new('username' => 'johndoe') }
- let(:timezone_experiment) { false }
- let(:spins) do
- # Stub the request at the latest time so that we can modify the raw data, e.g. available fields.
- WebMock
- .stub_request(:get, described_class::ROULETTE_DATA_URL)
- .to_return(body: teammate_json)
-
- subject.spin(project, categories, timezone_experiment: timezone_experiment)
- end
-
- before do
- allow(subject).to receive(:mr_author_username).and_return(author.username)
- allow(subject).to receive(:mr_labels).and_return(mr_labels)
- allow(subject).to receive(:mr_source_branch).and_return(mr_source_branch)
- end
-
- context 'when timezone_experiment == false' do
- context 'when change contains backend category' do
- let(:categories) { [:backend] }
-
- it 'assigns backend reviewer and maintainer' do
- expect(spins[0].reviewer).to eq(engineering_productivity_reviewer)
- expect(spins[0].maintainer).to eq(backend_maintainer)
- expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false)])
- end
-
- context 'when teammate is not available' do
- let(:backend_available) { false }
-
- it 'assigns backend reviewer and no maintainer' do
- expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, nil, false, false)])
- end
- end
- end
-
- context 'when change contains frontend category' do
- let(:categories) { [:frontend] }
-
- it 'assigns frontend reviewer and maintainer' do
- expect(spins).to eq([described_class::Spin.new(:frontend, frontend_reviewer, frontend_maintainer, false, false)])
- end
- end
-
- context 'when change contains many categories' do
- let(:categories) { [:frontend, :test, :qa, :engineering_productivity, :ci_template, :backend] }
-
- it 'has a deterministic sorting order' do
- expect(spins.map(&:category)).to eq categories.sort
- end
- end
-
- context 'when change contains QA category' do
- let(:categories) { [:qa] }
-
- it 'assigns QA reviewer' do
- expect(spins).to eq([described_class::Spin.new(:qa, software_engineer_in_test, nil, false, false)])
- end
- end
-
- context 'when change contains Engineering Productivity category' do
- let(:categories) { [:engineering_productivity] }
-
- it 'assigns Engineering Productivity reviewer and fallback to backend maintainer' do
- expect(spins).to eq([described_class::Spin.new(:engineering_productivity, engineering_productivity_reviewer, backend_maintainer, false, false)])
- end
- end
-
- context 'when change contains CI/CD Template category' do
- let(:categories) { [:ci_template] }
-
- it 'assigns CI/CD Template reviewer and fallback to backend maintainer' do
- expect(spins).to eq([described_class::Spin.new(:ci_template, ci_template_reviewer, backend_maintainer, false, false)])
- end
- end
-
- context 'when change contains test category' do
- let(:categories) { [:test] }
-
- it 'assigns corresponding SET' do
- expect(spins).to eq([described_class::Spin.new(:test, software_engineer_in_test, nil, :maintainer, false)])
- end
- end
- end
-
- context 'when timezone_experiment == true' do
- let(:timezone_experiment) { true }
-
- context 'when change contains backend category' do
- let(:categories) { [:backend] }
-
- it 'assigns backend reviewer and maintainer' do
- expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, true)])
- end
-
- context 'when teammate is not in a good timezone' do
- let(:backend_tz_offset_hours) { 5.0 }
-
- it 'assigns backend reviewer and no maintainer' do
- expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, nil, false, true)])
- end
- end
- end
-
- context 'when change includes a category with timezone disabled' do
- let(:categories) { [:backend] }
-
- before do
- stub_const("#{described_class}::INCLUDE_TIMEZONE_FOR_CATEGORY", backend: false)
- end
-
- it 'assigns backend reviewer and maintainer' do
- expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false)])
- end
-
- context 'when teammate is not in a good timezone' do
- let(:backend_tz_offset_hours) { 5.0 }
-
- it 'assigns backend reviewer and maintainer' do
- expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false)])
- end
- end
- end
- end
- end
-
- RSpec::Matchers.define :match_teammates do |expected|
- match do |actual|
- expected.each do |expected_person|
- actual_person_found = actual.find { |actual_person| actual_person.name == expected_person.username }
-
- actual_person_found &&
- actual_person_found.name == expected_person.name &&
- actual_person_found.role == expected_person.role &&
- actual_person_found.projects == expected_person.projects
- end
- end
- end
-
- describe '#team' do
- subject(:team) { roulette.team }
-
- context 'HTTP failure' do
- before do
- WebMock
- .stub_request(:get, described_class::ROULETTE_DATA_URL)
- .to_return(status: 404)
- end
-
- it 'raises a pretty error' do
- expect { team }.to raise_error(/Failed to read/)
- end
- end
-
- context 'JSON failure' do
- before do
- WebMock
- .stub_request(:get, described_class::ROULETTE_DATA_URL)
- .to_return(body: 'INVALID JSON')
- end
-
- it 'raises a pretty error' do
- expect { team }.to raise_error(/Failed to parse/)
- end
- end
-
- context 'success' do
- before do
- WebMock
- .stub_request(:get, described_class::ROULETTE_DATA_URL)
- .to_return(body: teammate_json)
- end
-
- it 'returns an array of teammates' do
- is_expected.to match_teammates([
- backend_maintainer,
- frontend_reviewer,
- frontend_maintainer,
- software_engineer_in_test,
- engineering_productivity_reviewer,
- ci_template_reviewer
- ])
- end
-
- it 'memoizes the result' do
- expect(team.object_id).to eq(roulette.team.object_id)
- end
- end
- end
-
- describe '#project_team' do
- subject { roulette.project_team('gitlab-qa') }
-
- before do
- WebMock
- .stub_request(:get, described_class::ROULETTE_DATA_URL)
- .to_return(body: teammate_json)
- end
-
- it 'filters team by project_name' do
- is_expected.to match_teammates([
- software_engineer_in_test
- ])
- end
- end
-
- describe '#spin_for_person' do
- let(:person_tz_offset_hours) { 0.0 }
- let(:person1) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'user1',
- 'available' => true,
- 'tz_offset_hours' => person_tz_offset_hours
- )
- end
-
- let(:person2) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'user2',
- 'available' => true,
- 'tz_offset_hours' => person_tz_offset_hours)
- end
-
- let(:author) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'johndoe',
- 'available' => true,
- 'tz_offset_hours' => 0.0)
- end
-
- let(:unavailable) do
- Gitlab::Danger::Teammate.new(
- 'username' => 'janedoe',
- 'available' => false,
- 'tz_offset_hours' => 0.0)
- end
-
- before do
- allow(subject).to receive(:mr_author_username).and_return(author.username)
- end
-
- (-4..4).each do |utc_offset|
- context "when local hour for person is #{10 + utc_offset} (offset: #{utc_offset})" do
- let(:person_tz_offset_hours) { utc_offset }
-
- [false, true].each do |timezone_experiment|
- context "with timezone_experiment == #{timezone_experiment}" do
- it 'returns a random person' do
- persons = [person1, person2]
-
- selected = subject.spin_for_person(persons, random: Random.new, timezone_experiment: timezone_experiment)
-
- expect(persons.map(&:username)).to include(selected.username)
- end
- end
- end
- end
- end
-
- ((-12..-5).to_a + (5..12).to_a).each do |utc_offset|
- context "when local hour for person is #{10 + utc_offset} (offset: #{utc_offset})" do
- let(:person_tz_offset_hours) { utc_offset }
-
- [false, true].each do |timezone_experiment|
- context "with timezone_experiment == #{timezone_experiment}" do
- it 'returns a random person or nil' do
- persons = [person1, person2]
-
- selected = subject.spin_for_person(persons, random: Random.new, timezone_experiment: timezone_experiment)
-
- if timezone_experiment
- expect(selected).to be_nil
- else
- expect(persons.map(&:username)).to include(selected.username)
- end
- end
- end
- end
- end
- end
-
- it 'excludes unavailable persons' do
- expect(subject.spin_for_person([unavailable], random: Random.new)).to be_nil
- end
-
- it 'excludes mr.author' do
- expect(subject.spin_for_person([author], random: Random.new)).to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/sidekiq_queues_spec.rb b/spec/lib/gitlab/danger/sidekiq_queues_spec.rb
deleted file mode 100644
index 7dd1a2e6924..00000000000
--- a/spec/lib/gitlab/danger/sidekiq_queues_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-require_relative 'danger_spec_helper'
-
-require 'gitlab/danger/sidekiq_queues'
-
-RSpec.describe Gitlab::Danger::SidekiqQueues do
- using RSpec::Parameterized::TableSyntax
- include DangerSpecHelper
-
- let(:fake_git) { double('fake-git') }
- let(:fake_danger) { new_fake_danger.include(described_class) }
-
- subject(:sidekiq_queues) { fake_danger.new(git: fake_git) }
-
- describe '#changed_queue_files' do
- where(:modified_files, :changed_queue_files) do
- %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml foo) | %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml)
- %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml) | %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml)
- %w(app/workers/all_queues.yml foo) | %w(app/workers/all_queues.yml)
- %w(ee/app/workers/all_queues.yml foo) | %w(ee/app/workers/all_queues.yml)
- %w(foo) | %w()
- %w() | %w()
- end
-
- with_them do
- it do
- allow(fake_git).to receive(:modified_files).and_return(modified_files)
-
- expect(sidekiq_queues.changed_queue_files).to match_array(changed_queue_files)
- end
- end
- end
-
- describe '#added_queue_names' do
- it 'returns queue names added by this change' do
- old_queues = { post_receive: nil }
-
- allow(sidekiq_queues).to receive(:old_queues).and_return(old_queues)
- allow(sidekiq_queues).to receive(:new_queues).and_return(old_queues.merge(merge: nil, process_commit: nil))
-
- expect(sidekiq_queues.added_queue_names).to contain_exactly(:merge, :process_commit)
- end
- end
-
- describe '#changed_queue_names' do
- it 'returns names for queues whose attributes were changed' do
- old_queues = {
- merge: { name: :merge, urgency: :low },
- post_receive: { name: :post_receive, urgency: :high },
- process_commit: { name: :process_commit, urgency: :high }
- }
-
- new_queues = old_queues.merge(mailers: { name: :mailers, urgency: :high },
- post_receive: { name: :post_receive, urgency: :low },
- process_commit: { name: :process_commit, urgency: :low })
-
- allow(sidekiq_queues).to receive(:old_queues).and_return(old_queues)
- allow(sidekiq_queues).to receive(:new_queues).and_return(new_queues)
-
- expect(sidekiq_queues.changed_queue_names).to contain_exactly(:post_receive, :process_commit)
- end
-
- it 'ignores removed queues' do
- old_queues = {
- merge: { name: :merge, urgency: :low },
- post_receive: { name: :post_receive, urgency: :high }
- }
-
- new_queues = {
- post_receive: { name: :post_receive, urgency: :low }
- }
-
- allow(sidekiq_queues).to receive(:old_queues).and_return(old_queues)
- allow(sidekiq_queues).to receive(:new_queues).and_return(new_queues)
-
- expect(sidekiq_queues.changed_queue_names).to contain_exactly(:post_receive)
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/teammate_spec.rb b/spec/lib/gitlab/danger/teammate_spec.rb
deleted file mode 100644
index 9c066ba4c1b..00000000000
--- a/spec/lib/gitlab/danger/teammate_spec.rb
+++ /dev/null
@@ -1,220 +0,0 @@
-# frozen_string_literal: true
-
-require 'timecop'
-require 'rspec-parameterized'
-
-require 'gitlab/danger/teammate'
-require 'active_support/testing/time_helpers'
-
-RSpec.describe Gitlab::Danger::Teammate do
- using RSpec::Parameterized::TableSyntax
-
- subject { described_class.new(options) }
-
- let(:tz_offset_hours) { 2.0 }
- let(:options) do
- {
- 'username' => 'luigi',
- 'projects' => projects,
- 'role' => role,
- 'markdown_name' => '[Luigi](https://gitlab.com/luigi) (`@luigi`)',
- 'tz_offset_hours' => tz_offset_hours
- }
- end
-
- let(:capabilities) { ['reviewer backend'] }
- let(:projects) { { project => capabilities } }
- let(:role) { 'Engineer, Manage' }
- let(:labels) { [] }
- let(:project) { double }
-
- describe '#==' do
- it 'compares Teammate username' do
- joe1 = described_class.new('username' => 'joe', 'projects' => projects)
- joe2 = described_class.new('username' => 'joe', 'projects' => [])
- jane1 = described_class.new('username' => 'jane', 'projects' => projects)
- jane2 = described_class.new('username' => 'jane', 'projects' => [])
-
- expect(joe1).to eq(joe2)
- expect(jane1).to eq(jane2)
- expect(jane1).not_to eq(nil)
- expect(described_class.new('username' => nil)).not_to eq(nil)
- end
- end
-
- describe '#to_h' do
- it 'returns the given options' do
- expect(subject.to_h).to eq(options)
- end
- end
-
- context 'when having multiple capabilities' do
- let(:capabilities) { ['reviewer backend', 'maintainer frontend', 'trainee_maintainer qa'] }
-
- it '#reviewer? supports multiple roles per project' do
- expect(subject.reviewer?(project, :backend, labels)).to be_truthy
- end
-
- it '#traintainer? supports multiple roles per project' do
- expect(subject.traintainer?(project, :qa, labels)).to be_truthy
- end
-
- it '#maintainer? supports multiple roles per project' do
- expect(subject.maintainer?(project, :frontend, labels)).to be_truthy
- end
-
- context 'when labels contain devops::create and the category is test' do
- let(:labels) { ['devops::create'] }
-
- context 'when role is Software Engineer in Test, Create' do
- let(:role) { 'Software Engineer in Test, Create' }
-
- it '#reviewer? returns true' do
- expect(subject.reviewer?(project, :test, labels)).to be_truthy
- end
-
- it '#maintainer? returns false' do
- expect(subject.maintainer?(project, :test, labels)).to be_falsey
- end
-
- context 'when hyperlink is mangled in the role' do
- let(:role) { '<a href="#">Software Engineer in Test</a>, Create' }
-
- it '#reviewer? returns true' do
- expect(subject.reviewer?(project, :test, labels)).to be_truthy
- end
- end
- end
-
- context 'when role is Software Engineer in Test' do
- let(:role) { 'Software Engineer in Test' }
-
- it '#reviewer? returns false' do
- expect(subject.reviewer?(project, :test, labels)).to be_falsey
- end
- end
-
- context 'when role is Software Engineer in Test, Manage' do
- let(:role) { 'Software Engineer in Test, Manage' }
-
- it '#reviewer? returns false' do
- expect(subject.reviewer?(project, :test, labels)).to be_falsey
- end
- end
-
- context 'when role is Backend Engineer, Engineering Productivity' do
- let(:role) { 'Backend Engineer, Engineering Productivity' }
-
- it '#reviewer? returns true' do
- expect(subject.reviewer?(project, :engineering_productivity, labels)).to be_truthy
- end
-
- it '#maintainer? returns false' do
- expect(subject.maintainer?(project, :engineering_productivity, labels)).to be_falsey
- end
-
- context 'when capabilities include maintainer backend' do
- let(:capabilities) { ['maintainer backend'] }
-
- it '#maintainer? returns true' do
- expect(subject.maintainer?(project, :engineering_productivity, labels)).to be_truthy
- end
- end
-
- context 'when capabilities include maintainer engineering productivity' do
- let(:capabilities) { ['maintainer engineering_productivity'] }
-
- it '#maintainer? returns true' do
- expect(subject.maintainer?(project, :engineering_productivity, labels)).to be_truthy
- end
- end
-
- context 'when capabilities include trainee_maintainer backend' do
- let(:capabilities) { ['trainee_maintainer backend'] }
-
- it '#traintainer? returns true' do
- expect(subject.traintainer?(project, :engineering_productivity, labels)).to be_truthy
- end
- end
- end
- end
- end
-
- context 'when having single capability' do
- let(:capabilities) { 'reviewer backend' }
-
- it '#reviewer? supports one role per project' do
- expect(subject.reviewer?(project, :backend, labels)).to be_truthy
- end
-
- it '#traintainer? supports one role per project' do
- expect(subject.traintainer?(project, :database, labels)).to be_falsey
- end
-
- it '#maintainer? supports one role per project' do
- expect(subject.maintainer?(project, :frontend, labels)).to be_falsey
- end
- end
-
- describe '#local_hour' do
- include ActiveSupport::Testing::TimeHelpers
-
- around do |example|
- travel_to(Time.utc(2020, 6, 23, 10)) { example.run }
- end
-
- context 'when author is given' do
- where(:tz_offset_hours, :expected_local_hour) do
- -12 | 22
- -10 | 0
- 2 | 12
- 4 | 14
- 12 | 22
- end
-
- with_them do
- it 'returns the correct local_hour' do
- expect(subject.local_hour).to eq(expected_local_hour)
- end
- end
- end
- end
-
- describe '#markdown_name' do
- it 'returns markdown name with timezone info' do
- expect(subject.markdown_name).to eq("#{options['markdown_name']} (UTC+2)")
- end
-
- context 'when offset is 1.5' do
- let(:tz_offset_hours) { 1.5 }
-
- it 'returns markdown name with timezone info, not truncated' do
- expect(subject.markdown_name).to eq("#{options['markdown_name']} (UTC+1.5)")
- end
- end
-
- context 'when author is given' do
- where(:tz_offset_hours, :author_offset, :diff_text) do
- -12 | -10 | "2 hours behind `@mario`"
- -10 | -12 | "2 hours ahead of `@mario`"
- -10 | 2 | "12 hours behind `@mario`"
- 2 | 4 | "2 hours behind `@mario`"
- 4 | 2 | "2 hours ahead of `@mario`"
- 2 | 3 | "1 hour behind `@mario`"
- 3 | 2 | "1 hour ahead of `@mario`"
- 2 | 2 | "same timezone as `@mario`"
- end
-
- with_them do
- it 'returns markdown name with timezone info' do
- author = described_class.new(options.merge('username' => 'mario', 'tz_offset_hours' => author_offset))
-
- floored_offset_hours = subject.__send__(:floored_offset_hours)
- utc_offset = floored_offset_hours >= 0 ? "+#{floored_offset_hours}" : floored_offset_hours
-
- expect(subject.markdown_name(author: author)).to eq("#{options['markdown_name']} (UTC#{utc_offset}, #{diff_text})")
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/title_linting_spec.rb b/spec/lib/gitlab/danger/title_linting_spec.rb
deleted file mode 100644
index b48d2c5e53d..00000000000
--- a/spec/lib/gitlab/danger/title_linting_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-require 'rspec-parameterized'
-
-require 'gitlab/danger/title_linting'
-
-RSpec.describe Gitlab::Danger::TitleLinting do
- using RSpec::Parameterized::TableSyntax
-
- describe '#sanitize_mr_title' do
- where(:mr_title, :expected_mr_title) do
- '`My MR title`' | "\\`My MR title\\`"
- 'WIP: My MR title' | 'My MR title'
- 'Draft: My MR title' | 'My MR title'
- '(Draft) My MR title' | 'My MR title'
- '[Draft] My MR title' | 'My MR title'
- '[DRAFT] My MR title' | 'My MR title'
- 'DRAFT: My MR title' | 'My MR title'
- 'DRAFT: `My MR title`' | "\\`My MR title\\`"
- end
-
- with_them do
- subject { described_class.sanitize_mr_title(mr_title) }
-
- it { is_expected.to eq(expected_mr_title) }
- end
- end
-
- describe '#remove_draft_flag' do
- where(:mr_title, :expected_mr_title) do
- 'WIP: My MR title' | 'My MR title'
- 'Draft: My MR title' | 'My MR title'
- '(Draft) My MR title' | 'My MR title'
- '[Draft] My MR title' | 'My MR title'
- '[DRAFT] My MR title' | 'My MR title'
- 'DRAFT: My MR title' | 'My MR title'
- end
-
- with_them do
- subject { described_class.remove_draft_flag(mr_title) }
-
- it { is_expected.to eq(expected_mr_title) }
- end
- end
-
- describe '#has_draft_flag?' do
- it 'returns true for a draft title' do
- expect(described_class.has_draft_flag?('Draft: My MR title')).to be true
- end
-
- it 'returns false for non draft title' do
- expect(described_class.has_draft_flag?('My MR title')).to be false
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/weightage/maintainers_spec.rb b/spec/lib/gitlab/danger/weightage/maintainers_spec.rb
deleted file mode 100644
index 066bb487fa2..00000000000
--- a/spec/lib/gitlab/danger/weightage/maintainers_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'gitlab/danger/weightage/maintainers'
-
-RSpec.describe Gitlab::Danger::Weightage::Maintainers do
- let(:multiplier) { Gitlab::Danger::Weightage::CAPACITY_MULTIPLIER }
- let(:regular_maintainer) { double('Teammate', reduced_capacity: false) }
- let(:reduced_capacity_maintainer) { double('Teammate', reduced_capacity: true) }
- let(:maintainers) do
- [
- regular_maintainer,
- reduced_capacity_maintainer
- ]
- end
-
- let(:maintainer_count) { Gitlab::Danger::Weightage::BASE_REVIEWER_WEIGHT * multiplier }
- let(:reduced_capacity_maintainer_count) { Gitlab::Danger::Weightage::BASE_REVIEWER_WEIGHT }
-
- subject(:weighted_maintainers) { described_class.new(maintainers).execute }
-
- describe '#execute' do
- it 'weights the maintainers overall' do
- expect(weighted_maintainers.count).to eq maintainer_count + reduced_capacity_maintainer_count
- end
-
- it 'has total count of regular maintainers' do
- expect(weighted_maintainers.count { |r| r.object_id == regular_maintainer.object_id }).to eq maintainer_count
- end
-
- it 'has count of reduced capacity maintainers' do
- expect(weighted_maintainers.count { |r| r.object_id == reduced_capacity_maintainer.object_id }).to eq reduced_capacity_maintainer_count
- end
- end
-end
diff --git a/spec/lib/gitlab/danger/weightage/reviewers_spec.rb b/spec/lib/gitlab/danger/weightage/reviewers_spec.rb
deleted file mode 100644
index cca81f4d9b5..00000000000
--- a/spec/lib/gitlab/danger/weightage/reviewers_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'gitlab/danger/weightage/reviewers'
-
-RSpec.describe Gitlab::Danger::Weightage::Reviewers do
- let(:multiplier) { Gitlab::Danger::Weightage::CAPACITY_MULTIPLIER }
- let(:regular_reviewer) { double('Teammate', hungry: false, reduced_capacity: false) }
- let(:hungry_reviewer) { double('Teammate', hungry: true, reduced_capacity: false) }
- let(:reduced_capacity_reviewer) { double('Teammate', hungry: false, reduced_capacity: true) }
- let(:reviewers) do
- [
- hungry_reviewer,
- regular_reviewer,
- reduced_capacity_reviewer
- ]
- end
-
- let(:regular_traintainer) { double('Teammate', hungry: false, reduced_capacity: false) }
- let(:hungry_traintainer) { double('Teammate', hungry: true, reduced_capacity: false) }
- let(:reduced_capacity_traintainer) { double('Teammate', hungry: false, reduced_capacity: true) }
- let(:traintainers) do
- [
- hungry_traintainer,
- regular_traintainer,
- reduced_capacity_traintainer
- ]
- end
-
- let(:hungry_reviewer_count) { Gitlab::Danger::Weightage::BASE_REVIEWER_WEIGHT * multiplier + described_class::DEFAULT_REVIEWER_WEIGHT }
- let(:hungry_traintainer_count) { described_class::TRAINTAINER_WEIGHT * multiplier + described_class::DEFAULT_REVIEWER_WEIGHT }
- let(:reviewer_count) { Gitlab::Danger::Weightage::BASE_REVIEWER_WEIGHT * multiplier }
- let(:traintainer_count) { Gitlab::Danger::Weightage::BASE_REVIEWER_WEIGHT * described_class::TRAINTAINER_WEIGHT * multiplier }
- let(:reduced_capacity_reviewer_count) { Gitlab::Danger::Weightage::BASE_REVIEWER_WEIGHT }
- let(:reduced_capacity_traintainer_count) { described_class::TRAINTAINER_WEIGHT }
-
- subject(:weighted_reviewers) { described_class.new(reviewers, traintainers).execute }
-
- describe '#execute', :aggregate_failures do
- it 'weights the reviewers overall' do
- reviewers_count = hungry_reviewer_count + reviewer_count + reduced_capacity_reviewer_count
- traintainers_count = hungry_traintainer_count + traintainer_count + reduced_capacity_traintainer_count
-
- expect(weighted_reviewers.count).to eq reviewers_count + traintainers_count
- end
-
- it 'has total count of hungry reviewers and traintainers' do
- expect(weighted_reviewers.count(&:hungry)).to eq hungry_reviewer_count + hungry_traintainer_count
- expect(weighted_reviewers.count { |r| r.object_id == hungry_reviewer.object_id }).to eq hungry_reviewer_count
- expect(weighted_reviewers.count { |r| r.object_id == hungry_traintainer.object_id }).to eq hungry_traintainer_count
- end
-
- it 'has total count of regular reviewers and traintainers' do
- expect(weighted_reviewers.count { |r| r.object_id == regular_reviewer.object_id }).to eq reviewer_count
- expect(weighted_reviewers.count { |r| r.object_id == regular_traintainer.object_id }).to eq traintainer_count
- end
-
- it 'has count of reduced capacity reviewers' do
- expect(weighted_reviewers.count(&:reduced_capacity)).to eq reduced_capacity_reviewer_count + reduced_capacity_traintainer_count
- expect(weighted_reviewers.count { |r| r.object_id == reduced_capacity_reviewer.object_id }).to eq reduced_capacity_reviewer_count
- expect(weighted_reviewers.count { |r| r.object_id == reduced_capacity_traintainer.object_id }).to eq reduced_capacity_traintainer_count
- end
- end
-end
diff --git a/spec/lib/gitlab/data_builder/build_spec.rb b/spec/lib/gitlab/data_builder/build_spec.rb
index 2f74e766a11..4242469b3db 100644
--- a/spec/lib/gitlab/data_builder/build_spec.rb
+++ b/spec/lib/gitlab/data_builder/build_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::DataBuilder::Build do
- let(:runner) { create(:ci_runner, :instance) }
+ let!(:tag_names) { %w(tag-1 tag-2) }
+ let(:runner) { create(:ci_runner, :instance, tag_list: tag_names.map { |n| ActsAsTaggableOn::Tag.create!(name: n)}) }
let(:user) { create(:user) }
let(:build) { create(:ci_build, :running, runner: runner, user: user) }
@@ -35,6 +36,7 @@ RSpec.describe Gitlab::DataBuilder::Build do
}
it { expect(data[:commit][:id]).to eq(build.pipeline.id) }
it { expect(data[:runner][:id]).to eq(build.runner.id) }
+ it { expect(data[:runner][:tags]).to match_array(tag_names) }
it { expect(data[:runner][:description]).to eq(build.runner.description) }
context 'commit author_url' do
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 297d87708d8..fd7cadeb89e 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -51,13 +51,15 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
context 'build with runner' do
let!(:build) { create(:ci_build, pipeline: pipeline, runner: ci_runner) }
- let(:ci_runner) { create(:ci_runner) }
+ let!(:tag_names) { %w(tag-1 tag-2) }
+ let(:ci_runner) { create(:ci_runner, tag_list: tag_names.map { |n| ActsAsTaggableOn::Tag.create!(name: n)}) }
it 'has runner attributes', :aggregate_failures do
expect(runner_data[:id]).to eq(ci_runner.id)
expect(runner_data[:description]).to eq(ci_runner.description)
expect(runner_data[:active]).to eq(ci_runner.active)
expect(runner_data[:is_shared]).to eq(ci_runner.instance_type?)
+ expect(runner_data[:tags]).to match_array(tag_names)
end
end
@@ -102,5 +104,16 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
expect(merge_request_attrs[:url]).to eq("http://localhost/#{merge_request.target_project.full_path}/-/merge_requests/#{merge_request.iid}")
end
end
+
+ context 'when pipeline has retried builds' do
+ before do
+ create(:ci_build, :retried, pipeline: pipeline)
+ end
+
+ it 'does not contain retried builds in payload' do
+ expect(data[:builds].count).to eq(1)
+ expect(build_data[:id]).to eq(build.id)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/database/migration_helpers/v2_spec.rb b/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
new file mode 100644
index 00000000000..f132ecbf13b
--- /dev/null
+++ b/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
@@ -0,0 +1,221 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
+ include Database::TriggerHelpers
+
+ let(:migration) do
+ ActiveRecord::Migration.new.extend(described_class)
+ end
+
+ before do
+ allow(migration).to receive(:puts)
+ end
+
+ shared_examples_for 'Setting up to rename a column' do
+ let(:model) { Class.new(ActiveRecord::Base) }
+
+ before do
+ model.table_name = :test_table
+ end
+
+ context 'when called inside a transaction block' do
+ before do
+ allow(migration).to receive(:transaction_open?).and_return(true)
+ end
+
+ it 'raises an error' do
+ expect do
+ migration.public_send(operation, :test_table, :original, :renamed)
+ end.to raise_error("#{operation} can not be run inside a transaction")
+ end
+ end
+
+ context 'when the existing column has a default value' do
+ before do
+ migration.change_column_default :test_table, existing_column, 'default value'
+ end
+
+ it 'raises an error' do
+ expect do
+ migration.public_send(operation, :test_table, :original, :renamed)
+ end.to raise_error("#{operation} does not currently support columns with default values")
+ end
+ end
+
+ context 'when passing a batch column' do
+ context 'when the batch column does not exist' do
+ it 'raises an error' do
+ expect do
+ migration.public_send(operation, :test_table, :original, :renamed, batch_column_name: :missing)
+ end.to raise_error('Column missing does not exist on test_table')
+ end
+ end
+
+ context 'when the batch column does exist' do
+ it 'passes it when creating the column' do
+ expect(migration).to receive(:create_column_from)
+ .with(:test_table, existing_column, added_column, type: nil, batch_column_name: :status)
+ .and_call_original
+
+ migration.public_send(operation, :test_table, :original, :renamed, batch_column_name: :status)
+ end
+ end
+ end
+
+ it 'creates the renamed column, syncing existing data' do
+ existing_record_1 = model.create!(status: 0, existing_column => 'existing')
+ existing_record_2 = model.create!(status: 0, existing_column => nil)
+
+ migration.send(operation, :test_table, :original, :renamed)
+ model.reset_column_information
+
+ expect(migration.column_exists?(:test_table, added_column)).to eq(true)
+
+ expect(existing_record_1.reload).to have_attributes(status: 0, original: 'existing', renamed: 'existing')
+ expect(existing_record_2.reload).to have_attributes(status: 0, original: nil, renamed: nil)
+ end
+
+ it 'installs triggers to sync new data' do
+ migration.public_send(operation, :test_table, :original, :renamed)
+ model.reset_column_information
+
+ new_record_1 = model.create!(status: 1, original: 'first')
+ new_record_2 = model.create!(status: 1, renamed: 'second')
+
+ expect(new_record_1.reload).to have_attributes(status: 1, original: 'first', renamed: 'first')
+ expect(new_record_2.reload).to have_attributes(status: 1, original: 'second', renamed: 'second')
+
+ new_record_1.update!(original: 'updated')
+ new_record_2.update!(renamed: nil)
+
+ expect(new_record_1.reload).to have_attributes(status: 1, original: 'updated', renamed: 'updated')
+ expect(new_record_2.reload).to have_attributes(status: 1, original: nil, renamed: nil)
+ end
+ end
+
+ describe '#rename_column_concurrently' do
+ before do
+ allow(migration).to receive(:transaction_open?).and_return(false)
+
+ migration.create_table :test_table do |t|
+ t.integer :status, null: false
+ t.text :original
+ t.text :other_column
+ end
+ end
+
+ it_behaves_like 'Setting up to rename a column' do
+ let(:operation) { :rename_column_concurrently }
+ let(:existing_column) { :original }
+ let(:added_column) { :renamed }
+ end
+
+ context 'when the column to rename does not exist' do
+ it 'raises an error' do
+ expect do
+ migration.rename_column_concurrently :test_table, :missing_column, :renamed
+ end.to raise_error('Column missing_column does not exist on test_table')
+ end
+ end
+ end
+
+ describe '#undo_cleanup_concurrent_column_rename' do
+ before do
+ allow(migration).to receive(:transaction_open?).and_return(false)
+
+ migration.create_table :test_table do |t|
+ t.integer :status, null: false
+ t.text :other_column
+ t.text :renamed
+ end
+ end
+
+ it_behaves_like 'Setting up to rename a column' do
+ let(:operation) { :undo_cleanup_concurrent_column_rename }
+ let(:existing_column) { :renamed }
+ let(:added_column) { :original }
+ end
+
+ context 'when the renamed column does not exist' do
+ it 'raises an error' do
+ expect do
+ migration.undo_cleanup_concurrent_column_rename :test_table, :original, :missing_column
+ end.to raise_error('Column missing_column does not exist on test_table')
+ end
+ end
+ end
+
+ shared_examples_for 'Cleaning up from renaming a column' do
+ let(:connection) { migration.connection }
+
+ before do
+ allow(migration).to receive(:transaction_open?).and_return(false)
+
+ migration.create_table :test_table do |t|
+ t.integer :status, null: false
+ t.text :original
+ t.text :other_column
+ end
+
+ migration.rename_column_concurrently :test_table, :original, :renamed
+ end
+
+ context 'when the helper is called repeatedly' do
+ before do
+ migration.public_send(operation, :test_table, :original, :renamed)
+ end
+
+ it 'does not make repeated attempts to cleanup' do
+ expect(migration).not_to receive(:remove_column)
+
+ expect do
+ migration.public_send(operation, :test_table, :original, :renamed)
+ end.not_to raise_error
+ end
+ end
+
+ context 'when the renamed column exists' do
+ let(:triggers) do
+ [
+ ['trigger_7cc71f92fd63', 'function_for_trigger_7cc71f92fd63', before: 'insert'],
+ ['trigger_f1a1f619636a', 'function_for_trigger_f1a1f619636a', before: 'update'],
+ ['trigger_769a49938884', 'function_for_trigger_769a49938884', before: 'update']
+ ]
+ end
+
+ it 'removes the sync triggers and renamed columns' do
+ triggers.each do |(trigger_name, function_name, event)|
+ expect_function_to_exist(function_name)
+ expect_valid_function_trigger(:test_table, trigger_name, function_name, event)
+ end
+
+ expect(migration.column_exists?(:test_table, added_column)).to eq(true)
+
+ migration.public_send(operation, :test_table, :original, :renamed)
+
+ expect(migration.column_exists?(:test_table, added_column)).to eq(false)
+
+ triggers.each do |(trigger_name, function_name, _)|
+ expect_trigger_not_to_exist(:test_table, trigger_name)
+ expect_function_not_to_exist(function_name)
+ end
+ end
+ end
+ end
+
+ describe '#undo_rename_column_concurrently' do
+ it_behaves_like 'Cleaning up from renaming a column' do
+ let(:operation) { :undo_rename_column_concurrently }
+ let(:added_column) { :renamed }
+ end
+ end
+
+ describe '#cleanup_concurrent_column_rename' do
+ it_behaves_like 'Cleaning up from renaming a column' do
+ let(:operation) { :cleanup_concurrent_column_rename }
+ let(:added_column) { :original }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 6b709cba5b3..6de7fc3a50e 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -1874,7 +1874,6 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
has_internal_id :iid,
scope: :project,
init: ->(s, _scope) { s&.project&.issues&.maximum(:iid) },
- backfill: true,
presence: false
end
end
@@ -1928,258 +1927,6 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(issue_b.iid).to eq(3)
end
- context 'when the new code creates a row post deploy but before the migration runs' do
- it 'does not change the row iid' do
- project = setup
- issue = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- expect(issue.reload.iid).to eq(1)
- end
-
- it 'backfills iids for rows already in the database' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_c.reload.iid).to eq(3)
- end
-
- it 'backfills iids across multiple projects' do
- project_a = setup
- project_b = setup
- issue_a = issues.create!(project_id: project_a.id)
- issue_b = issues.create!(project_id: project_b.id)
- issue_c = Issue.create!(project_id: project_a.id)
- issue_d = Issue.create!(project_id: project_b.id)
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(1)
- expect(issue_c.reload.iid).to eq(2)
- expect(issue_d.reload.iid).to eq(2)
- end
-
- it 'generates iids properly for models created after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- issue_d = Issue.create!(project_id: project.id)
- issue_e = Issue.create!(project_id: project.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_c.reload.iid).to eq(3)
- expect(issue_d.iid).to eq(4)
- expect(issue_e.iid).to eq(5)
- end
-
- it 'backfills iids and properly generates iids for new models across multiple projects' do
- project_a = setup
- project_b = setup
- issue_a = issues.create!(project_id: project_a.id)
- issue_b = issues.create!(project_id: project_b.id)
- issue_c = Issue.create!(project_id: project_a.id)
- issue_d = Issue.create!(project_id: project_b.id)
-
- model.backfill_iids('issues')
-
- issue_e = Issue.create!(project_id: project_a.id)
- issue_f = Issue.create!(project_id: project_b.id)
- issue_g = Issue.create!(project_id: project_a.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(1)
- expect(issue_c.reload.iid).to eq(2)
- expect(issue_d.reload.iid).to eq(2)
- expect(issue_e.iid).to eq(3)
- expect(issue_f.iid).to eq(3)
- expect(issue_g.iid).to eq(4)
- end
- end
-
- context 'when the new code creates a model and then old code creates a model post deploy but before the migration runs' do
- it 'backfills iids' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = Issue.create!(project_id: project.id)
- issue_c = issues.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_c.reload.iid).to eq(3)
- end
-
- it 'generates an iid for a new model after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_d = issues.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- issue_e = Issue.create!(project_id: project.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_c.reload.iid).to eq(3)
- expect(issue_d.reload.iid).to eq(4)
- expect(issue_e.iid).to eq(5)
- end
- end
-
- context 'when the new code and old code alternate creating models post deploy but before the migration runs' do
- it 'backfills iids' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = Issue.create!(project_id: project.id)
- issue_c = issues.create!(project_id: project.id)
- issue_d = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_c.reload.iid).to eq(3)
- expect(issue_d.reload.iid).to eq(4)
- end
-
- it 'generates an iid for a new model after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_d = issues.create!(project_id: project.id)
- issue_e = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- issue_f = Issue.create!(project_id: project.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_c.reload.iid).to eq(3)
- expect(issue_d.reload.iid).to eq(4)
- expect(issue_e.reload.iid).to eq(5)
- expect(issue_f.iid).to eq(6)
- end
- end
-
- context 'when the new code creates and deletes a model post deploy but before the migration runs' do
- it 'backfills iids for rows already in the database' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_c.delete
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- end
-
- it 'successfully creates a new model after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_c.delete
-
- model.backfill_iids('issues')
-
- issue_d = Issue.create!(project_id: project.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_d.iid).to eq(3)
- end
- end
-
- context 'when the new code creates and deletes a model and old code creates a model post deploy but before the migration runs' do
- it 'backfills iids' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_c.delete
- issue_d = issues.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_d.reload.iid).to eq(3)
- end
-
- it 'successfully creates a new model after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_c.delete
- issue_d = issues.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- issue_e = Issue.create!(project_id: project.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_d.reload.iid).to eq(3)
- expect(issue_e.iid).to eq(4)
- end
- end
-
- context 'when the new code creates and deletes a model and then creates another model post deploy but before the migration runs' do
- it 'successfully generates an iid for a new model after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_c.delete
- issue_d = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_d.reload.iid).to eq(3)
- end
-
- it 'successfully generates an iid for a new model after the migration' do
- project = setup
- issue_a = issues.create!(project_id: project.id)
- issue_b = issues.create!(project_id: project.id)
- issue_c = Issue.create!(project_id: project.id)
- issue_c.delete
- issue_d = Issue.create!(project_id: project.id)
-
- model.backfill_iids('issues')
-
- issue_e = Issue.create!(project_id: project.id)
-
- expect(issue_a.reload.iid).to eq(1)
- expect(issue_b.reload.iid).to eq(2)
- expect(issue_d.reload.iid).to eq(3)
- expect(issue_e.iid).to eq(4)
- end
- end
-
context 'when the first model is created for a project after the migration' do
it 'generates an iid' do
project_a = setup
diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
new file mode 100644
index 00000000000..3804dc52a77
--- /dev/null
+++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Migrations::Instrumentation do
+ describe '#observe' do
+ subject { described_class.new }
+
+ let(:migration) { 1234 }
+
+ it 'executes the given block' do
+ expect { |b| subject.observe(migration, &b) }.to yield_control
+ end
+
+ context 'behavior with observers' do
+ subject { described_class.new(observers).observe(migration) {} }
+
+ let(:observers) { [observer] }
+ let(:observer) { instance_double('Gitlab::Database::Migrations::Observers::MigrationObserver', before: nil, after: nil, record: nil) }
+
+ it 'calls #before, #after, #record on given observers' do
+ expect(observer).to receive(:before).ordered
+ expect(observer).to receive(:after).ordered
+ expect(observer).to receive(:record).ordered do |observation|
+ expect(observation.migration).to eq(migration)
+ end
+
+ subject
+ end
+
+ it 'ignores errors coming from observers #before' do
+ expect(observer).to receive(:before).and_raise('some error')
+
+ subject
+ end
+
+ it 'ignores errors coming from observers #after' do
+ expect(observer).to receive(:after).and_raise('some error')
+
+ subject
+ end
+
+ it 'ignores errors coming from observers #record' do
+ expect(observer).to receive(:record).and_raise('some error')
+
+ subject
+ end
+ end
+
+ context 'on successful execution' do
+ subject { described_class.new.observe(migration) {} }
+
+ it 'records walltime' 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.migration).to eq(migration)
+ end
+ end
+
+ context 'upon failure' do
+ subject { described_class.new.observe(migration) { 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(migration) { raise 'something went wrong' }
+ rescue
+ # ignore
+ end
+
+ let(:instance) { described_class.new }
+
+ it 'records walltime' do
+ expect(subject.walltime).not_to be_nil
+ end
+
+ it 'records failure' do
+ expect(subject.success).to be_falsey
+ end
+
+ it 'records the migration version' do
+ expect(subject.migration).to eq(migration)
+ end
+ end
+ end
+
+ context 'sequence of migrations with failures' do
+ subject { described_class.new }
+
+ let(:migration1) { double('migration1', call: nil) }
+ let(:migration2) { double('migration2', call: nil) }
+
+ it 'records observations for all migrations' do
+ subject.observe('migration1') {}
+ subject.observe('migration2') { raise 'something went wrong' } rescue nil
+
+ expect(subject.observations.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb b/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb
new file mode 100644
index 00000000000..73466471944
--- /dev/null
+++ b/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange do
+ subject { described_class.new }
+
+ let(:observation) { Gitlab::Database::Migrations::Observation.new }
+ let(:connection) { ActiveRecord::Base.connection }
+ let(:query) { 'select pg_database_size(current_database())' }
+
+ it 'records the size change' do
+ expect(connection).to receive(:execute).with(query).once.and_return([{ 'pg_database_size' => 1024 }])
+ expect(connection).to receive(:execute).with(query).once.and_return([{ 'pg_database_size' => 256 }])
+
+ subject.before
+ subject.after
+ subject.record(observation)
+
+ expect(observation.total_database_size_change).to eq(256 - 1024)
+ end
+
+ context 'out of order calls' do
+ before do
+ allow(connection).to receive(:execute).with(query).and_return([{ 'pg_database_size' => 1024 }])
+ end
+
+ it 'does not record anything if before size is unknown' do
+ subject.after
+
+ expect { subject.record(observation) }.not_to change { observation.total_database_size_change }
+ end
+
+ it 'does not record anything if after size is unknown' do
+ subject.before
+
+ expect { subject.record(observation) }.not_to change { observation.total_database_size_change }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
index b50e02c7043..b5d741fc5e9 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
@@ -513,6 +513,7 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
context 'finishing pending background migration jobs' do
let(:source_table_double) { double('table name') }
let(:raw_arguments) { [1, 50_000, source_table_double, partitioned_table, source_column] }
+ let(:background_job) { double('background job', args: ['background jobs', raw_arguments]) }
before do
allow(migration).to receive(:table_exists?).with(partitioned_table).and_return(true)
@@ -528,7 +529,7 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
expect(Gitlab::BackgroundMigration).to receive(:steal)
.with(described_class::MIGRATION_CLASS_NAME)
- .and_yield(raw_arguments)
+ .and_yield(background_job)
expect(source_table_double).to receive(:==).with(source_table.to_s)
diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb
index 220ae705e71..563399ff0d9 100644
--- a/spec/lib/gitlab/database/with_lock_retries_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb
@@ -54,6 +54,10 @@ RSpec.describe Gitlab::Database::WithLockRetries do
lock_fiber.resume # start the transaction and lock the table
end
+ after do
+ lock_fiber.resume if lock_fiber.alive?
+ end
+
context 'lock_fiber' do
it 'acquires lock successfully' do
check_exclusive_lock_query = """
diff --git a/spec/lib/gitlab/diff/char_diff_spec.rb b/spec/lib/gitlab/diff/char_diff_spec.rb
new file mode 100644
index 00000000000..e4e2a3ba050
--- /dev/null
+++ b/spec/lib/gitlab/diff/char_diff_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'diff_match_patch'
+
+RSpec.describe Gitlab::Diff::CharDiff do
+ let(:old_string) { "Helo \n Worlld" }
+ let(:new_string) { "Hello \n World" }
+
+ subject(:diff) { described_class.new(old_string, new_string) }
+
+ describe '#generate_diff' do
+ context 'when old string is nil' do
+ let(:old_string) { nil }
+
+ it 'does not raise an error' do
+ expect { subject.generate_diff }.not_to raise_error
+ end
+
+ it 'treats nil values as blank strings' do
+ changes = subject.generate_diff
+
+ expect(changes).to eq([
+ [:insert, "Hello \n World"]
+ ])
+ end
+ end
+
+ it 'generates an array of changes' do
+ changes = subject.generate_diff
+
+ expect(changes).to eq([
+ [:equal, "Hel"],
+ [:insert, "l"],
+ [:equal, "o \n Worl"],
+ [:delete, "l"],
+ [:equal, "d"]
+ ])
+ end
+ end
+
+ describe '#changed_ranges' do
+ subject { diff.changed_ranges }
+
+ context 'when old string is nil' do
+ let(:old_string) { nil }
+
+ it 'returns lists of changes' do
+ old_diffs, new_diffs = subject
+
+ expect(old_diffs).to eq([])
+ expect(new_diffs).to eq([0..12])
+ end
+ end
+
+ it 'returns ranges of changes' do
+ old_diffs, new_diffs = subject
+
+ expect(old_diffs).to eq([11..11])
+ expect(new_diffs).to eq([3..3])
+ end
+ end
+
+ describe '#to_html' do
+ it 'returns an HTML representation of the diff' do
+ subject.generate_diff
+
+ expect(subject.to_html).to eq(
+ '<span class="idiff">Hel</span>' \
+ '<span class="idiff addition">l</span>' \
+ "<span class=\"idiff\">o \n Worl</span>" \
+ '<span class="idiff deletion">l</span>' \
+ '<span class="idiff">d</span>'
+ )
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/file_collection_sorter_spec.rb b/spec/lib/gitlab/diff/file_collection_sorter_spec.rb
index 8822fc55c6e..9ba9271cefc 100644
--- a/spec/lib/gitlab/diff/file_collection_sorter_spec.rb
+++ b/spec/lib/gitlab/diff/file_collection_sorter_spec.rb
@@ -5,11 +5,14 @@ require 'spec_helper'
RSpec.describe Gitlab::Diff::FileCollectionSorter do
let(:diffs) do
[
+ double(new_path: 'README', old_path: 'README'),
double(new_path: '.dir/test', old_path: '.dir/test'),
double(new_path: '', old_path: '.file'),
double(new_path: '1-folder/A-file.ext', old_path: '1-folder/A-file.ext'),
+ double(new_path: '1-folder/README', old_path: '1-folder/README'),
double(new_path: nil, old_path: '1-folder/M-file.ext'),
double(new_path: '1-folder/Z-file.ext', old_path: '1-folder/Z-file.ext'),
+ double(new_path: '1-folder/README', old_path: '1-folder/README'),
double(new_path: '', old_path: '1-folder/nested/A-file.ext'),
double(new_path: '1-folder/nested/M-file.ext', old_path: '1-folder/nested/M-file.ext'),
double(new_path: nil, old_path: '1-folder/nested/Z-file.ext'),
@@ -19,7 +22,8 @@ RSpec.describe Gitlab::Diff::FileCollectionSorter do
double(new_path: nil, old_path: '2-folder/nested/A-file.ext'),
double(new_path: 'A-file.ext', old_path: 'A-file.ext'),
double(new_path: '', old_path: 'M-file.ext'),
- double(new_path: 'Z-file.ext', old_path: 'Z-file.ext')
+ double(new_path: 'Z-file.ext', old_path: 'Z-file.ext'),
+ double(new_path: 'README', old_path: 'README')
]
end
@@ -36,6 +40,8 @@ RSpec.describe Gitlab::Diff::FileCollectionSorter do
'1-folder/nested/Z-file.ext',
'1-folder/A-file.ext',
'1-folder/M-file.ext',
+ '1-folder/README',
+ '1-folder/README',
'1-folder/Z-file.ext',
'2-folder/nested/A-file.ext',
'2-folder/A-file.ext',
@@ -44,6 +50,8 @@ RSpec.describe Gitlab::Diff::FileCollectionSorter do
'.file',
'A-file.ext',
'M-file.ext',
+ 'README',
+ 'README',
'Z-file.ext'
])
end
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
index f6810d7a966..94717152488 100644
--- a/spec/lib/gitlab/diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -233,4 +233,22 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
cache.write_if_empty
end
end
+
+ describe '#key' do
+ subject { cache.key }
+
+ it 'returns the next version of the cache' do
+ is_expected.to start_with("highlighted-diff-files:#{cache.diffable.cache_key}:2")
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(improved_merge_diff_highlighting: false)
+ end
+
+ it 'returns the original version of the cache' do
+ is_expected.to start_with("highlighted-diff-files:#{cache.diffable.cache_key}:1")
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/diff/inline_diff_spec.rb b/spec/lib/gitlab/diff/inline_diff_spec.rb
index 35284e952f7..dce655d5690 100644
--- a/spec/lib/gitlab/diff/inline_diff_spec.rb
+++ b/spec/lib/gitlab/diff/inline_diff_spec.rb
@@ -37,6 +37,33 @@ RSpec.describe Gitlab::Diff::InlineDiff do
it 'can handle unchanged empty lines' do
expect { described_class.for_lines(['- bar', '+ baz', '']) }.not_to raise_error
end
+
+ context 'when lines have multiple changes' do
+ let(:diff) do
+ <<~EOF
+ - Hello, how are you?
+ + Hi, how are you doing?
+ EOF
+ end
+
+ let(:subject) { described_class.for_lines(diff.lines) }
+
+ it 'finds all inline diffs' do
+ expect(subject[0]).to eq([3..6])
+ expect(subject[1]).to eq([3..3, 17..22])
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(improved_merge_diff_highlighting: false)
+ end
+
+ it 'finds all inline diffs' do
+ expect(subject[0]).to eq([3..19])
+ expect(subject[1]).to eq([3..22])
+ end
+ end
+ end
end
describe "#inline_diffs" do
diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
index b1ffbedc7bf..eb11c051adc 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -40,6 +40,13 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
expect(new_issue.description).to eq(expected_description.strip)
end
+ it 'creates an issue_email_participant' do
+ receiver.execute
+ new_issue = Issue.last
+
+ expect(new_issue.issue_email_participants.first.email).to eq("jake@adventuretime.ooo")
+ end
+
it 'sends thank you email' do
expect { receiver.execute }.to have_enqueued_job.on_queue('mailers')
end
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
index c47f71c207d..1cebe37bea5 100644
--- a/spec/lib/gitlab/experimentation/controller_concern_spec.rb
+++ b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
@@ -10,6 +10,10 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
use_backwards_compatible_subject_index: true
},
test_experiment: {
+ tracking_category: 'Team',
+ rollout_strategy: rollout_strategy
+ },
+ my_experiment: {
tracking_category: 'Team'
}
}
@@ -20,6 +24,7 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
end
let(:enabled_percentage) { 10 }
+ let(:rollout_strategy) { nil }
controller(ApplicationController) do
include Gitlab::Experimentation::ControllerConcern
@@ -117,6 +122,7 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
end
context 'when subject is given' do
+ let(:rollout_strategy) { :user }
let(:user) { build(:user) }
it 'uses the subject' do
@@ -244,6 +250,7 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
it "provides the subject's hashed global_id as label" do
experiment_subject = double(:subject, to_global_id: 'abc')
+ allow(Gitlab::Experimentation).to receive(:valid_subject_for_rollout_strategy?).and_return(true)
controller.track_experiment_event(:test_experiment, 'start', 1, subject: experiment_subject)
@@ -420,6 +427,26 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
controller.record_experiment_user(:test_experiment, context)
end
+
+ context 'with a cookie based rollout strategy' do
+ it 'calls tracking_group with a nil subject' do
+ expect(controller).to receive(:tracking_group).with(:test_experiment, nil, subject: nil).and_return(:experimental)
+ allow(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user, context)
+
+ controller.record_experiment_user(:test_experiment, context)
+ end
+ end
+
+ context 'with a user based rollout strategy' do
+ let(:rollout_strategy) { :user }
+
+ it 'calls tracking_group with a user subject' do
+ expect(controller).to receive(:tracking_group).with(:test_experiment, nil, subject: user).and_return(:experimental)
+ allow(::Experiment).to receive(:add_user).with(:test_experiment, :experimental, user, context)
+
+ controller.record_experiment_user(:test_experiment, context)
+ end
+ end
end
context 'the user is part of the control group' do
diff --git a/spec/lib/gitlab/experimentation/experiment_spec.rb b/spec/lib/gitlab/experimentation/experiment_spec.rb
index 008e6699597..94dbf1d7e4b 100644
--- a/spec/lib/gitlab/experimentation/experiment_spec.rb
+++ b/spec/lib/gitlab/experimentation/experiment_spec.rb
@@ -9,7 +9,8 @@ RSpec.describe Gitlab::Experimentation::Experiment do
let(:params) do
{
tracking_category: 'Category1',
- use_backwards_compatible_subject_index: true
+ use_backwards_compatible_subject_index: true,
+ rollout_strategy: nil
}
end
diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb
index b503960b8c7..7eeae3f3f33 100644
--- a/spec/lib/gitlab/experimentation_spec.rb
+++ b/spec/lib/gitlab/experimentation_spec.rb
@@ -7,7 +7,6 @@ require 'spec_helper'
RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
it 'temporarily ensures we know what experiments exist for backwards compatibility' do
expected_experiment_keys = [
- :onboarding_issues,
:ci_notification_dot,
:upgrade_link_in_user_menu_a,
:invite_members_version_a,
@@ -15,8 +14,7 @@ RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
:invite_members_empty_group_version_a,
:contact_sales_btn_in_app,
:customize_homepage,
- :group_only_trials,
- :default_to_issues_board
+ :group_only_trials
]
backwards_compatible_experiment_keys = described_class.filter { |_, v| v[:use_backwards_compatible_subject_index] }.keys
@@ -27,6 +25,8 @@ RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
end
RSpec.describe Gitlab::Experimentation do
+ using RSpec::Parameterized::TableSyntax
+
before do
stub_const('Gitlab::Experimentation::EXPERIMENTS', {
backwards_compatible_test_experiment: {
@@ -35,6 +35,10 @@ RSpec.describe Gitlab::Experimentation do
},
test_experiment: {
tracking_category: 'Team'
+ },
+ tabular_experiment: {
+ tracking_category: 'Team',
+ rollout_strategy: rollout_strategy
}
})
@@ -46,6 +50,7 @@ RSpec.describe Gitlab::Experimentation do
end
let(:enabled_percentage) { 10 }
+ let(:rollout_strategy) { nil }
describe '.get_experiment' do
subject { described_class.get_experiment(:test_experiment) }
@@ -175,4 +180,59 @@ RSpec.describe Gitlab::Experimentation do
end
end
end
+
+ describe '.log_invalid_rollout' do
+ subject { described_class.log_invalid_rollout(:test_experiment, 1) }
+
+ before do
+ allow(described_class).to receive(:valid_subject_for_rollout_strategy?).and_return(valid)
+ end
+
+ context 'subject is not valid for experiment' do
+ let(:valid) { false }
+
+ it 'logs a warning message' do
+ expect_next_instance_of(Gitlab::ExperimentationLogger) do |logger|
+ expect(logger)
+ .to receive(:warn)
+ .with(
+ message: 'Subject must conform to the rollout strategy',
+ experiment_key: :test_experiment,
+ subject: 'Integer',
+ rollout_strategy: :cookie
+ )
+ end
+
+ subject
+ end
+ end
+
+ context 'subject is valid for experiment' do
+ let(:valid) { true }
+
+ it 'does not log a warning message' do
+ expect(Gitlab::ExperimentationLogger).not_to receive(:build)
+
+ subject
+ end
+ end
+ end
+
+ describe '.valid_subject_for_rollout_strategy?' do
+ subject { described_class.valid_subject_for_rollout_strategy?(:tabular_experiment, experiment_subject) }
+
+ where(:rollout_strategy, :experiment_subject, :result) do
+ :cookie | nil | true
+ nil | nil | true
+ :cookie | 'string' | true
+ nil | User.new | false
+ :user | User.new | true
+ :group | User.new | false
+ :group | Group.new | true
+ end
+
+ with_them do
+ it { is_expected.to be(result) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/file_finder_spec.rb b/spec/lib/gitlab/file_finder_spec.rb
index 8d6df62b3f6..0b5303f22b4 100644
--- a/spec/lib/gitlab/file_finder_spec.rb
+++ b/spec/lib/gitlab/file_finder_spec.rb
@@ -53,6 +53,14 @@ RSpec.describe Gitlab::FileFinder do
end
end
+ context 'with white space in the path' do
+ it 'filters by path correctly' do
+ results = subject.find('directory path:"with space/README.md"')
+
+ expect(results.count).to eq(1)
+ end
+ end
+
it 'does not cause N+1 query' do
expect(Gitlab::GitalyClient).to receive(:call).at_most(10).times.and_call_original
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 8961cdcae7d..49f1e6e994f 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -720,7 +720,8 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
committer_name: "Dmitriy Zaporozhets",
id: SeedRepo::Commit::ID,
message: "tree css fixes",
- parent_ids: ["874797c3a73b60d2187ed6e2fcabd289ff75171e"]
+ parent_ids: ["874797c3a73b60d2187ed6e2fcabd289ff75171e"],
+ trailers: {}
}
end
end
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 783f0a9ccf7..17bb83d0f2f 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -100,6 +100,13 @@ EOT
expect(diff.diff).to be_empty
expect(diff).to be_too_large
end
+
+ it 'logs the event' do
+ expect(Gitlab::Metrics).to receive(:add_event)
+ .with(:patch_hard_limit_bytes_hit)
+
+ diff
+ end
end
context 'using a collapsable diff that is too large' do
diff --git a/spec/lib/gitlab/git/push_spec.rb b/spec/lib/gitlab/git/push_spec.rb
index 0f52f10c0a6..8ba43b2967c 100644
--- a/spec/lib/gitlab/git/push_spec.rb
+++ b/spec/lib/gitlab/git/push_spec.rb
@@ -86,6 +86,16 @@ RSpec.describe Gitlab::Git::Push do
it { is_expected.to be_force_push }
end
+
+ context 'when called muiltiple times' do
+ it 'does not make make multiple calls to the force push check' do
+ expect(Gitlab::Checks::ForcePush).to receive(:force_push?).once
+
+ 2.times do
+ subject.force_push?
+ end
+ end
+ end
end
describe '#branch_added?' do
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index ef9b5a30c86..cc1b1ceadcf 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1894,8 +1894,11 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'removes the remote' do
repository_rugged.remotes.create(remote_name, url)
- repository.remove_remote(remote_name)
+ expect(repository.remove_remote(remote_name)).to be true
+ # Since we deleted the remote via Gitaly, Rugged doesn't know
+ # this changed underneath it. Let's refresh the Rugged repo.
+ repository_rugged = Rugged::Repository.new(repository_path)
expect(repository_rugged.remotes[remote_name]).to be_nil
end
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index a0cafe3d763..9a1ecfe6459 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -388,108 +388,6 @@ RSpec.describe Gitlab::GitAccess do
end
end
- describe '#check_otp_session!' do
- let_it_be(:user) { create(:user, :two_factor_via_otp)}
- let_it_be(:key) { create(:key, user: user) }
- let_it_be(:actor) { key }
-
- before do
- project.add_developer(user)
- stub_feature_flags(two_factor_for_cli: true)
- end
-
- context 'with an OTP session', :clean_gitlab_redis_shared_state do
- before do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set("#{Gitlab::Auth::Otp::SessionEnforcer::OTP_SESSIONS_NAMESPACE}:#{key.id}", true)
- end
- end
-
- it 'allows push and pull access' do
- aggregate_failures do
- expect { push_access_check }.not_to raise_error
- expect { pull_access_check }.not_to raise_error
- end
- end
- end
-
- context 'without OTP session' do
- it 'does not allow push or pull access' do
- user = 'jane.doe'
- host = 'fridge.ssh'
- port = 42
-
- stub_config(
- gitlab_shell: {
- ssh_user: user,
- ssh_host: host,
- ssh_port: port
- }
- )
-
- error_message = "OTP verification is required to access the repository.\n\n"\
- " Use: ssh #{user}@#{host} -p #{port} 2fa_verify"
-
- aggregate_failures do
- expect { push_access_check }.to raise_forbidden(error_message)
- expect { pull_access_check }.to raise_forbidden(error_message)
- end
- end
-
- context 'when protocol is HTTP' do
- let(:protocol) { 'http' }
-
- it 'allows push and pull access' do
- aggregate_failures do
- expect { push_access_check }.not_to raise_error
- expect { pull_access_check }.not_to raise_error
- end
- end
- end
-
- context 'when actor is not an SSH key' do
- let(:deploy_key) { create(:deploy_key, user: user) }
- let(:actor) { deploy_key }
-
- before do
- deploy_key.deploy_keys_projects.create(project: project, can_push: true)
- end
-
- it 'allows push and pull access' do
- aggregate_failures do
- expect { push_access_check }.not_to raise_error
- expect { pull_access_check }.not_to raise_error
- end
- end
- end
-
- context 'when 2FA is not enabled for the user' do
- let(:user) { create(:user)}
- let(:actor) { create(:key, user: user) }
-
- it 'allows push and pull access' do
- aggregate_failures do
- expect { push_access_check }.not_to raise_error
- expect { pull_access_check }.not_to raise_error
- end
- end
- end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(two_factor_for_cli: false)
- end
-
- it 'allows push and pull access' do
- aggregate_failures do
- expect { push_access_check }.not_to raise_error
- expect { pull_access_check }.not_to raise_error
- end
- end
- end
- end
- end
-
describe '#check_db_accessibility!' do
context 'when in a read-only GitLab instance' do
before do
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index ce01566b870..22707c9a36b 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -299,6 +299,11 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
let(:start_sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
let(:end_sha) { '54cec5282aa9f21856362fe321c800c236a61615' }
let(:commit_message) { 'Squash message' }
+
+ let(:time) do
+ Time.now.utc
+ end
+
let(:request) do
Gitaly::UserSquashRequest.new(
repository: repository.gitaly_repository,
@@ -307,7 +312,8 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
start_sha: start_sha,
end_sha: end_sha,
author: gitaly_user,
- commit_message: commit_message
+ commit_message: commit_message,
+ timestamp: Google::Protobuf::Timestamp.new(seconds: time.to_i)
)
end
@@ -315,7 +321,7 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
let(:response) { Gitaly::UserSquashResponse.new(squash_sha: squash_sha) }
subject do
- client.user_squash(user, squash_id, start_sha, end_sha, user, commit_message)
+ client.user_squash(user, squash_id, start_sha, end_sha, user, commit_message, time)
end
it 'sends a user_squash message and returns the squash sha' do
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index 7fcb11c4dfd..a8d42f4bccf 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -267,31 +267,63 @@ RSpec.describe Gitlab::GitalyClient do
end
describe '.request_kwargs' do
- context 'when catfile-cache feature is enabled' do
- before do
- stub_feature_flags('gitaly_catfile-cache': true)
+ it 'sets the gitaly-session-id in the metadata' do
+ results = described_class.request_kwargs('default', timeout: 1)
+ expect(results[:metadata]).to include('gitaly-session-id')
+ end
+
+ context 'when RequestStore is not enabled' do
+ it 'sets a different gitaly-session-id per request' do
+ gitaly_session_id = described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']
+
+ expect(described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']).not_to eq(gitaly_session_id)
end
+ end
- it 'sets the gitaly-session-id in the metadata' do
- results = described_class.request_kwargs('default', timeout: 1)
- expect(results[:metadata]).to include('gitaly-session-id')
+ context 'when RequestStore is enabled', :request_store do
+ it 'sets the same gitaly-session-id on every outgoing request metadata' do
+ gitaly_session_id = described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']
+
+ 3.times do
+ expect(described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']).to eq(gitaly_session_id)
+ end
end
+ end
- context 'when RequestStore is not enabled' do
- it 'sets a different gitaly-session-id per request' do
- gitaly_session_id = described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']
+ context 'gitlab_git_env' do
+ let(:policy) { 'gitaly-route-repository-accessor-policy' }
- expect(described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']).not_to eq(gitaly_session_id)
+ context 'when RequestStore is disabled' do
+ it 'does not force-route to primary' do
+ expect(described_class.request_kwargs('default', timeout: 1)[:metadata][policy]).to be_nil
end
end
- context 'when RequestStore is enabled', :request_store do
- it 'sets the same gitaly-session-id on every outgoing request metadata' do
- gitaly_session_id = described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']
+ context 'when RequestStore is enabled without git_env', :request_store do
+ it 'does not force-orute to primary' do
+ expect(described_class.request_kwargs('default', timeout: 1)[:metadata][policy]).to be_nil
+ end
+ end
- 3.times do
- expect(described_class.request_kwargs('default', timeout: 1)[:metadata]['gitaly-session-id']).to eq(gitaly_session_id)
- end
+ context 'when RequestStore is enabled with empty git_env', :request_store do
+ before do
+ Gitlab::SafeRequestStore[:gitlab_git_env] = {}
+ end
+
+ it 'disables force-routing to primary' do
+ expect(described_class.request_kwargs('default', timeout: 1)[:metadata][policy]).to be_nil
+ end
+ end
+
+ context 'when RequestStore is enabled with populated git_env', :request_store do
+ before do
+ Gitlab::SafeRequestStore[:gitlab_git_env] = {
+ "GIT_OBJECT_DIRECTORY_RELATIVE" => "foo/bar"
+ }
+ end
+
+ it 'enables force-routing to primary' do
+ expect(described_class.request_kwargs('default', timeout: 1)[:metadata][policy]).to eq('primary-only')
end
end
end
diff --git a/spec/lib/gitlab/graphql/pagination/connections_spec.rb b/spec/lib/gitlab/graphql/pagination/connections_spec.rb
new file mode 100644
index 00000000000..e89e5c17644
--- /dev/null
+++ b/spec/lib/gitlab/graphql/pagination/connections_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# Tests that our connections are correctly mapped.
+RSpec.describe ::Gitlab::Graphql::Pagination::Connections do
+ include GraphqlHelpers
+
+ before(:all) do
+ ActiveRecord::Schema.define do
+ create_table :testing_pagination_nodes, force: true do |t|
+ t.integer :value, null: false
+ end
+ end
+ end
+
+ after(:all) do
+ ActiveRecord::Schema.define do
+ drop_table :testing_pagination_nodes, force: true
+ end
+ end
+
+ let_it_be(:node_model) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'testing_pagination_nodes'
+ end
+ end
+
+ let(:query_string) { 'query { items(first: 2) { nodes { value } } }' }
+ let(:user) { nil }
+
+ let(:node) { Struct.new(:value) }
+ let(:node_type) do
+ Class.new(::GraphQL::Schema::Object) do
+ graphql_name 'Node'
+ field :value, GraphQL::INT_TYPE, null: false
+ end
+ end
+
+ let(:query_type) do
+ item_values = nodes
+
+ query_factory do |t|
+ t.field :items, node_type.connection_type, null: true
+
+ t.define_method :items do
+ item_values
+ end
+ end
+ end
+
+ shared_examples 'it maps to a specific connection class' do |connection_type|
+ let(:raw_values) { [1, 7, 42] }
+
+ it "maps to #{connection_type.name}" do
+ expect(connection_type).to receive(:new).and_call_original
+
+ results = execute_query(query_type).to_h
+
+ expect(graphql_dig_at(results, :data, :items, :nodes, :value)).to eq [1, 7]
+ end
+ end
+
+ describe 'OffsetPaginatedRelation' do
+ before do
+ # Expect to be ordered by an explicit ordering.
+ raw_values.each_with_index { |value, id| node_model.create!(id: id, value: value) }
+ end
+
+ let(:nodes) { ::Gitlab::Graphql::Pagination::OffsetPaginatedRelation.new(node_model.order(value: :asc)) }
+
+ include_examples 'it maps to a specific connection class', Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection
+ end
+
+ describe 'ActiveRecord::Relation' do
+ before do
+ # Expect to be ordered by ID descending
+ [3, 2, 1].zip(raw_values) { |id, value| node_model.create!(id: id, value: value) }
+ end
+
+ let(:nodes) { node_model.all }
+
+ include_examples 'it maps to a specific connection class', Gitlab::Graphql::Pagination::Keyset::Connection
+ end
+
+ describe 'ExternallyPaginatedArray' do
+ let(:nodes) { ::Gitlab::Graphql::ExternallyPaginatedArray.new(nil, nil, node.new(1), node.new(7)) }
+
+ include_examples 'it maps to a specific connection class', Gitlab::Graphql::Pagination::ExternallyPaginatedArrayConnection
+ end
+
+ describe 'Array' do
+ let(:nodes) { raw_values.map { |x| node.new(x) } }
+
+ include_examples 'it maps to a specific connection class', Gitlab::Graphql::Pagination::ArrayConnection
+ end
+end
diff --git a/spec/lib/gitlab/graphql/queries_spec.rb b/spec/lib/gitlab/graphql/queries_spec.rb
index 6e08a87523f..a140a283c1b 100644
--- a/spec/lib/gitlab/graphql/queries_spec.rb
+++ b/spec/lib/gitlab/graphql/queries_spec.rb
@@ -151,6 +151,10 @@ RSpec.describe Gitlab::Graphql::Queries do
let(:path) { 'post_by_slug.graphql' }
it_behaves_like 'a valid GraphQL query for the blog schema'
+
+ it 'has a complexity' do
+ expect(subject.complexity(schema)).to be < 10
+ end
end
context 'a query with an import' do
diff --git a/spec/lib/gitlab/health_checks/master_check_spec.rb b/spec/lib/gitlab/health_checks/master_check_spec.rb
index 1c1efe178e2..287ebcec207 100644
--- a/spec/lib/gitlab/health_checks/master_check_spec.rb
+++ b/spec/lib/gitlab/health_checks/master_check_spec.rb
@@ -4,47 +4,67 @@ require 'spec_helper'
require_relative './simple_check_shared'
RSpec.describe Gitlab::HealthChecks::MasterCheck do
- let(:result_class) { Gitlab::HealthChecks::Result }
-
before do
stub_const('SUCCESS_CODE', 100)
stub_const('FAILURE_CODE', 101)
- described_class.register_master
end
- after do
- described_class.finish_master
- end
+ context 'when Puma runs in Clustered mode' do
+ before do
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(true)
- describe '#readiness' do
- context 'when master is running' do
- it 'worker does return success' do
- _, child_status = run_worker
+ described_class.register_master
+ end
- expect(child_status.exitstatus).to eq(SUCCESS_CODE)
- end
+ after do
+ described_class.finish_master
end
- context 'when master finishes early' do
- before do
- described_class.send(:close_write)
+ describe '.available?' do
+ specify { expect(described_class.available?).to be true }
+ end
+
+ describe '.readiness' do
+ context 'when master is running' do
+ it 'worker does return success' do
+ _, child_status = run_worker
+
+ expect(child_status.exitstatus).to eq(SUCCESS_CODE)
+ end
end
- it 'worker does return failure' do
- _, child_status = run_worker
+ context 'when master finishes early' do
+ before do
+ described_class.send(:close_write)
+ end
- expect(child_status.exitstatus).to eq(FAILURE_CODE)
+ it 'worker does return failure' do
+ _, child_status = run_worker
+
+ expect(child_status.exitstatus).to eq(FAILURE_CODE)
+ end
end
- end
- def run_worker
- pid = fork do
- described_class.register_worker
+ def run_worker
+ pid = fork do
+ described_class.register_worker
- exit(described_class.readiness.success ? SUCCESS_CODE : FAILURE_CODE)
+ exit(described_class.readiness.success ? SUCCESS_CODE : FAILURE_CODE)
+ end
+
+ Process.wait2(pid)
end
+ end
+ end
+
+ # '.readiness' check is not invoked if '.available?' returns false
+ context 'when Puma runs in Single mode' do
+ before do
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(false)
+ end
- Process.wait2(pid)
+ describe '.available?' do
+ specify { expect(described_class.available?).to be false }
end
end
end
diff --git a/spec/lib/gitlab/health_checks/probes/collection_spec.rb b/spec/lib/gitlab/health_checks/probes/collection_spec.rb
index 03138e936aa..69828c143db 100644
--- a/spec/lib/gitlab/health_checks/probes/collection_spec.rb
+++ b/spec/lib/gitlab/health_checks/probes/collection_spec.rb
@@ -61,6 +61,35 @@ RSpec.describe Gitlab::HealthChecks::Probes::Collection do
expect(subject.json[:message]).to eq('Redis::CannotConnectError : Redis down')
end
end
+
+ context 'when some checks are not available' do
+ before do
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(false)
+ end
+
+ let(:checks) do
+ [
+ Gitlab::HealthChecks::MasterCheck
+ ]
+ end
+
+ it 'asks for check availability' do
+ expect(Gitlab::HealthChecks::MasterCheck).to receive(:available?)
+
+ subject
+ end
+
+ it 'does not call `readiness` on checks that are not available' do
+ expect(Gitlab::HealthChecks::MasterCheck).not_to receive(:readiness)
+
+ subject
+ end
+
+ it 'does not fail collection check' do
+ expect(subject.http_status).to eq(200)
+ expect(subject.json[:status]).to eq('ok')
+ end
+ end
end
context 'without checks' do
diff --git a/spec/lib/gitlab/hook_data/group_builder_spec.rb b/spec/lib/gitlab/hook_data/group_builder_spec.rb
new file mode 100644
index 00000000000..d7347ff99d4
--- /dev/null
+++ b/spec/lib/gitlab/hook_data/group_builder_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::HookData::GroupBuilder do
+ let_it_be(:group) { create(:group) }
+
+ describe '#build' do
+ let(:data) { described_class.new(group).build(event) }
+ let(:event_name) { data[:event_name] }
+ let(:attributes) do
+ [
+ :event_name, :created_at, :updated_at, :name, :path, :full_path, :group_id
+ ]
+ end
+
+ context 'data' do
+ shared_examples_for 'includes the required attributes' do
+ it 'includes the required attributes' do
+ expect(data).to include(*attributes)
+
+ expect(data[:name]).to eq(group.name)
+ expect(data[:path]).to eq(group.path)
+ expect(data[:full_path]).to eq(group.full_path)
+ expect(data[:group_id]).to eq(group.id)
+ expect(data[:created_at]).to eq(group.created_at.xmlschema)
+ expect(data[:updated_at]).to eq(group.updated_at.xmlschema)
+ end
+ end
+
+ shared_examples_for 'does not include old path attributes' do
+ it 'does not include old path attributes' do
+ expect(data).not_to include(:old_path, :old_full_path)
+ end
+ end
+
+ context 'on create' do
+ let(:event) { :create }
+
+ it { expect(event_name).to eq('group_create') }
+ it_behaves_like 'includes the required attributes'
+ it_behaves_like 'does not include old path attributes'
+ end
+
+ context 'on destroy' do
+ let(:event) { :destroy }
+
+ it { expect(event_name).to eq('group_destroy') }
+ it_behaves_like 'includes the required attributes'
+ it_behaves_like 'does not include old path attributes'
+ end
+
+ context 'on rename' do
+ let(:event) { :rename }
+
+ it { expect(event_name).to eq('group_rename') }
+ it_behaves_like 'includes the required attributes'
+
+ it 'includes old path details' do
+ allow(group).to receive(:path_before_last_save).and_return('old-path')
+
+ expect(data[:old_path]).to eq(group.path_before_last_save)
+ expect(data[:old_full_path]).to eq(group.path_before_last_save)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb b/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb
new file mode 100644
index 00000000000..89e5dffd7b4
--- /dev/null
+++ b/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::HookData::SubgroupBuilder do
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: parent_group) }
+
+ describe '#build' do
+ let(:data) { described_class.new(subgroup).build(event) }
+ let(:event_name) { data[:event_name] }
+ let(:attributes) do
+ [
+ :event_name, :created_at, :updated_at, :name, :path, :full_path, :group_id,
+ :parent_group_id, :parent_name, :parent_path, :parent_full_path
+ ]
+ end
+
+ context 'data' do
+ shared_examples_for 'includes the required attributes' do
+ it 'includes the required attributes' do
+ expect(data).to include(*attributes)
+
+ expect(data[:name]).to eq(subgroup.name)
+ expect(data[:path]).to eq(subgroup.path)
+ expect(data[:full_path]).to eq(subgroup.full_path)
+ expect(data[:group_id]).to eq(subgroup.id)
+ expect(data[:created_at]).to eq(subgroup.created_at.xmlschema)
+ expect(data[:updated_at]).to eq(subgroup.updated_at.xmlschema)
+ expect(data[:parent_name]).to eq(parent_group.name)
+ expect(data[:parent_path]).to eq(parent_group.path)
+ expect(data[:parent_full_path]).to eq(parent_group.full_path)
+ expect(data[:parent_group_id]).to eq(parent_group.id)
+ end
+ end
+
+ context 'on create' do
+ let(:event) { :create }
+
+ it { expect(event_name).to eq('subgroup_create') }
+ it_behaves_like 'includes the required attributes'
+ end
+
+ context 'on destroy' do
+ let(:event) { :destroy }
+
+ it { expect(event_name).to eq('subgroup_destroy') }
+ it_behaves_like 'includes the required attributes'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 825513bdfc5..d0282e14d5f 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -146,6 +146,7 @@ merge_requests:
- merge_user
- merge_request_diffs
- merge_request_diff
+- merge_head_diff
- merge_request_context_commits
- merge_request_context_commit_diff_files
- events
@@ -544,7 +545,7 @@ project:
- daily_build_group_report_results
- jira_imports
- compliance_framework_setting
-- compliance_management_frameworks
+- compliance_management_framework
- metrics_users_starred_dashboards
- alert_management_alerts
- repository_storage_moves
@@ -560,7 +561,10 @@ project:
- alert_management_http_integrations
- exported_protected_branches
- incident_management_oncall_schedules
+- incident_management_oncall_rotations
- debian_distributions
+- merge_request_metrics
+- security_orchestration_policy_configuration
award_emoji:
- awardable
- user
@@ -589,6 +593,7 @@ lfs_file_locks:
project_badges:
- project
metrics:
+- target_project
- merge_request
- latest_closed_by
- merged_by
diff --git a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
index efb271086a0..96c467e78d6 100644
--- a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
+++ b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
@@ -27,25 +27,55 @@ RSpec.describe Gitlab::ImportExport::DecompressedArchiveSizeValidator do
end
context 'when file exceeds allowed decompressed size' do
- it 'returns false' do
+ it 'logs error message returns false' do
+ expect(Gitlab::Import::Logger)
+ .to receive(:info)
+ .with(
+ import_upload_archive_path: filepath,
+ import_upload_archive_size: File.size(filepath),
+ message: 'Decompressed archive size limit reached'
+ )
expect(subject.valid?).to eq(false)
end
end
- context 'when something goes wrong during decompression' do
- before do
- allow(subject.archive_file).to receive(:eof?).and_raise(StandardError)
+ context 'when exception occurs during decompression' do
+ shared_examples 'logs raised exception and terminates validator process group' do
+ let(:std) { double(:std, close: nil, value: nil) }
+ let(:wait_thr) { double }
+
+ before do
+ allow(Process).to receive(:getpgid).and_return(2)
+ allow(Open3).to receive(:popen3).and_return([std, std, std, wait_thr])
+ allow(wait_thr).to receive(:[]).with(:pid).and_return(1)
+ allow(wait_thr).to receive(:value).and_raise(exception)
+ end
+
+ it 'logs raised exception and terminates validator process group' do
+ expect(Gitlab::Import::Logger)
+ .to receive(:info)
+ .with(
+ import_upload_archive_path: filepath,
+ import_upload_archive_size: File.size(filepath),
+ message: error_message
+ )
+ expect(Process).to receive(:kill).with(-1, 2)
+ expect(subject.valid?).to eq(false)
+ end
end
- it 'logs and tracks raised exception' do
- expect(Gitlab::ErrorTracking).to receive(:track_exception).with(instance_of(StandardError))
- expect(Gitlab::Import::Logger).to receive(:info).with(hash_including(message: 'Decompressed archive size validation failed.'))
+ context 'when timeout occurs' do
+ let(:error_message) { 'Timeout reached during archive decompression' }
+ let(:exception) { Timeout::Error }
- subject.valid?
+ include_examples 'logs raised exception and terminates validator process group'
end
- it 'returns false' do
- expect(subject.valid?).to eq(false)
+ context 'when exception occurs' do
+ let(:error_message) { 'Error!' }
+ let(:exception) { StandardError.new(error_message) }
+
+ include_examples 'logs raised exception and terminates validator process group'
end
end
end
diff --git a/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb b/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb
index b311a02833c..6680f4e7a03 100644
--- a/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb
@@ -11,12 +11,12 @@ RSpec.describe Gitlab::ImportExport::DesignRepoRestorer do
let!(:project) { create(:project) }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
- let(:bundler) { Gitlab::ImportExport::DesignRepoSaver.new(project: project_with_design_repo, shared: shared) }
+ let(:bundler) { Gitlab::ImportExport::DesignRepoSaver.new(exportable: project_with_design_repo, shared: shared) }
let(:bundle_path) { File.join(shared.export_path, Gitlab::ImportExport.design_repo_bundle_filename) }
let(:restorer) do
described_class.new(path_to_bundle: bundle_path,
shared: shared,
- project: project)
+ importable: project)
end
before do
diff --git a/spec/lib/gitlab/import_export/design_repo_saver_spec.rb b/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
index 2575d209db5..5501e3dee5a 100644
--- a/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::ImportExport::DesignRepoSaver do
let!(:project) { create(:project, :design_repo) }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
- let(:design_bundler) { described_class.new(project: project, shared: shared) }
+ let(:design_bundler) { described_class.new(exportable: project, shared: shared) }
before do
project.add_maintainer(user)
diff --git a/spec/lib/gitlab/import_export/fork_spec.rb b/spec/lib/gitlab/import_export/fork_spec.rb
index ef7394053b9..65c28a8b8a2 100644
--- a/spec/lib/gitlab/import_export/fork_spec.rb
+++ b/spec/lib/gitlab/import_export/fork_spec.rb
@@ -12,11 +12,11 @@ RSpec.describe 'forked project import' do
let(:shared) { project.import_export_shared }
let(:forked_from_project) { create(:project, :repository) }
let(:forked_project) { fork_project(project_with_repo, nil, repository: true) }
- let(:repo_saver) { Gitlab::ImportExport::RepoSaver.new(project: project_with_repo, shared: shared) }
+ let(:repo_saver) { Gitlab::ImportExport::RepoSaver.new(exportable: project_with_repo, shared: shared) }
let(:bundle_path) { File.join(shared.export_path, Gitlab::ImportExport.project_bundle_filename) }
let(:repo_restorer) do
- Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: bundle_path, shared: shared, project: project)
+ Gitlab::ImportExport::RepoRestorer.new(path_to_bundle: bundle_path, shared: shared, importable: project)
end
let!(:merge_request) do
diff --git a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
index 2794acb8980..d2153221e8f 100644
--- a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe Gitlab::ImportExport::Group::TreeRestorer do
group_tree_restorer = described_class.new(user: user, shared: @shared, group: @group)
expect(group_tree_restorer.restore).to be_truthy
+ expect(group_tree_restorer.groups_mapping).not_to be_empty
end
end
diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb
index 75db3167ebc..20f0f6af6f3 100644
--- a/spec/lib/gitlab/import_export/importer_spec.rb
+++ b/spec/lib/gitlab/import_export/importer_spec.rb
@@ -69,8 +69,8 @@ RSpec.describe Gitlab::ImportExport::Importer do
repo_path = File.join(shared.export_path, Gitlab::ImportExport.project_bundle_filename)
restorer = double(Gitlab::ImportExport::RepoRestorer)
- expect(Gitlab::ImportExport::RepoRestorer).to receive(:new).with(path_to_bundle: repo_path, shared: shared, project: project).and_return(restorer)
- expect(Gitlab::ImportExport::RepoRestorer).to receive(:new).with(path_to_bundle: wiki_repo_path, shared: shared, project: ProjectWiki.new(project)).and_return(restorer)
+ expect(Gitlab::ImportExport::RepoRestorer).to receive(:new).with(path_to_bundle: repo_path, shared: shared, importable: project).and_return(restorer)
+ expect(Gitlab::ImportExport::RepoRestorer).to receive(:new).with(path_to_bundle: wiki_repo_path, shared: shared, importable: ProjectWiki.new(project)).and_return(restorer)
expect(Gitlab::ImportExport::RepoRestorer).to receive(:new).and_call_original
expect(restorer).to receive(:restore).and_return(true).twice
diff --git a/spec/lib/gitlab/import_export/repo_restorer_spec.rb b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
index a6b917457c2..fe43a23e242 100644
--- a/spec/lib/gitlab/import_export/repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
@@ -27,10 +27,10 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do
end
describe 'bundle a project Git repo' do
- let(:bundler) { Gitlab::ImportExport::RepoSaver.new(project: project_with_repo, shared: shared) }
+ let(:bundler) { Gitlab::ImportExport::RepoSaver.new(exportable: project_with_repo, shared: shared) }
let(:bundle_path) { File.join(shared.export_path, Gitlab::ImportExport.project_bundle_filename) }
- subject { described_class.new(path_to_bundle: bundle_path, shared: shared, project: project) }
+ subject { described_class.new(path_to_bundle: bundle_path, shared: shared, importable: project) }
after do
Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path)
@@ -62,10 +62,10 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do
end
describe 'restore a wiki Git repo' do
- let(:bundler) { Gitlab::ImportExport::WikiRepoSaver.new(project: project_with_repo, shared: shared) }
+ let(:bundler) { Gitlab::ImportExport::WikiRepoSaver.new(exportable: project_with_repo, shared: shared) }
let(:bundle_path) { File.join(shared.export_path, Gitlab::ImportExport.wiki_repo_bundle_filename) }
- subject { described_class.new(path_to_bundle: bundle_path, shared: shared, project: ProjectWiki.new(project)) }
+ subject { described_class.new(path_to_bundle: bundle_path, shared: shared, importable: ProjectWiki.new(project)) }
after do
Gitlab::Shell.new.remove_repository(project.wiki.repository_storage, project.wiki.disk_path)
@@ -83,7 +83,7 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do
describe 'no wiki in the bundle' do
let!(:project_without_wiki) { create(:project) }
- let(:bundler) { Gitlab::ImportExport::WikiRepoSaver.new(project: project_without_wiki, shared: shared) }
+ let(:bundler) { Gitlab::ImportExport::WikiRepoSaver.new(exportable: project_without_wiki, shared: shared) }
it 'does not creates an empty wiki' do
expect(subject.restore).to be true
diff --git a/spec/lib/gitlab/import_export/repo_saver_spec.rb b/spec/lib/gitlab/import_export/repo_saver_spec.rb
index 73d51000c67..52001e778d6 100644
--- a/spec/lib/gitlab/import_export/repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_saver_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::ImportExport::RepoSaver do
let!(:project) { create(:project, :repository) }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
- let(:bundler) { described_class.new(project: project, shared: shared) }
+ let(:bundler) { described_class.new(exportable: project, shared: shared) }
before do
project.add_maintainer(user)
@@ -25,6 +25,14 @@ RSpec.describe Gitlab::ImportExport::RepoSaver do
expect(bundler.save).to be true
end
+ it 'creates the directory for the repository' do
+ allow(bundler).to receive(:bundle_full_path).and_return('/foo/bar/file.tar.gz')
+
+ expect(FileUtils).to receive(:mkdir_p).with('/foo/bar', anything)
+
+ bundler.save # rubocop:disable Rails/SaveBang
+ end
+
context 'when the repo is empty' do
let!(:project) { create(:project) }
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index a93ee051ccf..e301be47d68 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -220,6 +220,7 @@ MergeRequestDiff:
- commits_count
- files_count
- sorted
+- diff_type
MergeRequestDiffCommit:
- merge_request_diff_id
- relative_order
@@ -231,6 +232,7 @@ MergeRequestDiffCommit:
- committer_name
- committer_email
- message
+- trailers
MergeRequestDiffFile:
- merge_request_diff_id
- relative_order
@@ -255,6 +257,7 @@ MergeRequestContextCommit:
- committer_email
- message
- merge_request_id
+- trailers
MergeRequestContextCommitDiffFile:
- sha
- relative_order
@@ -580,6 +583,7 @@ ProjectFeature:
- requirements_access_level
- analytics_access_level
- operations_access_level
+- security_and_compliance_access_level
- created_at
- updated_at
ProtectedBranch::MergeAccessLevel:
diff --git a/spec/lib/gitlab/import_export/saver_spec.rb b/spec/lib/gitlab/import_export/saver_spec.rb
index 865c7e57b5a..877474dd862 100644
--- a/spec/lib/gitlab/import_export/saver_spec.rb
+++ b/spec/lib/gitlab/import_export/saver_spec.rb
@@ -6,7 +6,8 @@ require 'fileutils'
RSpec.describe Gitlab::ImportExport::Saver do
let!(:project) { create(:project, :public, name: 'project') }
let(:base_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
- let(:export_path) { "#{base_path}/project_tree_saver_spec/export" }
+ let(:archive_path) { "#{base_path}/archive" }
+ let(:export_path) { "#{archive_path}/export" }
let(:shared) { project.import_export_shared }
subject { described_class.new(exportable: project, shared: shared) }
@@ -35,10 +36,13 @@ RSpec.describe Gitlab::ImportExport::Saver do
.to match(%r[\/uploads\/-\/system\/import_export_upload\/export_file.*])
end
- it 'removes tmp files' do
+ it 'removes archive path and keeps base path untouched' do
+ allow(shared).to receive(:archive_path).and_return(archive_path)
+
subject.save
- expect(FileUtils).to have_received(:rm_rf).with(base_path)
- expect(Dir.exist?(base_path)).to eq(false)
+ 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
end
diff --git a/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb b/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
index 778d0859bf1..540f90e7804 100644
--- a/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/wiki_repo_saver_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::ImportExport::WikiRepoSaver do
let_it_be(:project) { create(:project, :wiki_repo) }
let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
let(:shared) { project.import_export_shared }
- let(:wiki_bundler) { described_class.new(project: project, shared: shared) }
+ let(:wiki_bundler) { described_class.new(exportable: project, shared: shared) }
let!(:project_wiki) { ProjectWiki.new(project, user) }
before do
diff --git a/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb b/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb
index 2ca7465e775..e4af3f77d5d 100644
--- a/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb
+++ b/spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb
@@ -53,6 +53,7 @@ RSpec.describe Gitlab::Instrumentation::RedisClusterValidator do
:del | [%w(foo bar)] | true # Arguments can be a nested array
:del | %w(foo foo) | false
:hset | %w(foo bar) | false # Not a multi-key command
+ :mget | [] | false # This is invalid, but not because it's a cross-slot command
end
with_them do
diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb
index c00b0fdf043..a5c9cde4c37 100644
--- a/spec/lib/gitlab/instrumentation_helper_spec.rb
+++ b/spec/lib/gitlab/instrumentation_helper_spec.rb
@@ -9,12 +9,17 @@ RSpec.describe Gitlab::InstrumentationHelper do
describe '.keys' do
it 'returns all available payload keys' do
expected_keys = [
+ :cpu_s,
:gitaly_calls,
:gitaly_duration_s,
:rugged_calls,
:rugged_duration_s,
:elasticsearch_calls,
:elasticsearch_duration_s,
+ :elasticsearch_timed_out_count,
+ :mem_objects,
+ :mem_bytes,
+ :mem_mallocs,
:redis_calls,
:redis_duration_s,
:redis_read_bytes,
@@ -37,7 +42,11 @@ RSpec.describe Gitlab::InstrumentationHelper do
:redis_shared_state_write_bytes,
:db_count,
:db_write_count,
- :db_cached_count
+ :db_cached_count,
+ :external_http_count,
+ :external_http_duration_s,
+ :rack_attack_redis_count,
+ :rack_attack_redis_duration_s
]
expect(described_class.keys).to eq(expected_keys)
@@ -49,10 +58,14 @@ RSpec.describe Gitlab::InstrumentationHelper do
subject { described_class.add_instrumentation_data(payload) }
- it 'adds only DB counts by default' do
+ before do
+ described_class.init_instrumentation_data
+ end
+
+ it 'includes DB counts' do
subject
- expect(payload).to eq(db_count: 0, db_cached_count: 0, db_write_count: 0)
+ expect(payload).to include(db_count: 0, db_cached_count: 0, db_write_count: 0)
end
context 'when Gitaly calls are made' do
@@ -110,6 +123,47 @@ RSpec.describe Gitlab::InstrumentationHelper do
expect(payload[:throttle_safelist]).to eq('foobar')
end
end
+
+ it 'logs cpu_s duration' do
+ subject
+
+ expect(payload).to include(:cpu_s)
+ end
+
+ context 'when logging memory allocations' do
+ include MemoryInstrumentationHelper
+
+ before do
+ skip_memory_instrumentation!
+ end
+
+ it 'logs memory usage metrics' do
+ subject
+
+ expect(payload).to include(
+ :mem_objects,
+ :mem_bytes,
+ :mem_mallocs
+ )
+ end
+
+ context 'when trace_memory_allocations is disabled' do
+ before do
+ stub_feature_flags(trace_memory_allocations: false)
+ Gitlab::Memory::Instrumentation.ensure_feature_flag!
+ end
+
+ it 'does not log memory usage metrics' do
+ subject
+
+ expect(payload).not_to include(
+ :mem_objects,
+ :mem_bytes,
+ :mem_mallocs
+ )
+ end
+ end
+ end
end
describe '.queue_duration_for_job' do
diff --git a/spec/lib/gitlab/kas_spec.rb b/spec/lib/gitlab/kas_spec.rb
index ce22f36e9fd..01ced407883 100644
--- a/spec/lib/gitlab/kas_spec.rb
+++ b/spec/lib/gitlab/kas_spec.rb
@@ -58,4 +58,48 @@ RSpec.describe Gitlab::Kas do
end
end
end
+
+ describe '.included_in_gitlab_com_rollout?' do
+ let_it_be(:project) { create(:project) }
+
+ context 'not GitLab.com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(false)
+ end
+
+ it 'returns true' do
+ expect(described_class.included_in_gitlab_com_rollout?(project)).to be_truthy
+ end
+ end
+
+ context 'GitLab.com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ context 'kubernetes_agent_on_gitlab_com feature flag disabled' do
+ before do
+ stub_feature_flags(kubernetes_agent_on_gitlab_com: false)
+ end
+
+ it 'returns false' do
+ expect(described_class.included_in_gitlab_com_rollout?(project)).to be_falsey
+ end
+ end
+
+ context 'kubernetes_agent_on_gitlab_com feature flag enabled' do
+ before do
+ stub_feature_flags(kubernetes_agent_on_gitlab_com: project)
+ end
+
+ it 'returns true' do
+ expect(described_class.included_in_gitlab_com_rollout?(project)).to be_truthy
+ end
+
+ it 'returns false for another project' do
+ expect(described_class.included_in_gitlab_com_rollout?(create(:project))).to be_falsey
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/memory/instrumentation_spec.rb b/spec/lib/gitlab/memory/instrumentation_spec.rb
new file mode 100644
index 00000000000..6b53550a3d0
--- /dev/null
+++ b/spec/lib/gitlab/memory/instrumentation_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Memory::Instrumentation do
+ include MemoryInstrumentationHelper
+
+ before do
+ skip_memory_instrumentation!
+ end
+
+ describe '.available?' do
+ it 'returns true' do
+ expect(described_class).to be_available
+ end
+ end
+
+ describe '.start_thread_memory_allocations' do
+ subject { described_class.start_thread_memory_allocations }
+
+ context 'when feature flag trace_memory_allocations is enabled' do
+ before do
+ stub_feature_flags(trace_memory_allocations: true)
+ end
+
+ it 'a hash is returned' do
+ is_expected.not_to be_empty
+ end
+ end
+
+ context 'when feature flag trace_memory_allocations is disabled' do
+ before do
+ stub_feature_flags(trace_memory_allocations: false)
+ end
+
+ it 'a nil is returned' do
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when feature is unavailable' do
+ before do
+ allow(described_class).to receive(:available?) { false }
+ end
+
+ it 'a nil is returned' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe '.with_memory_allocations' do
+ let(:ntimes) { 100 }
+
+ subject do
+ described_class.with_memory_allocations do
+ Array.new(1000).map { '0' * 100 }
+ end
+ end
+
+ before do
+ expect(described_class).to receive(:start_thread_memory_allocations).and_call_original
+ expect(described_class).to receive(:measure_thread_memory_allocations).and_call_original
+ end
+
+ context 'when feature flag trace_memory_allocations is enabled' do
+ before do
+ stub_feature_flags(trace_memory_allocations: true)
+ end
+
+ it 'a hash is returned' do
+ is_expected.to include(
+ mem_objects: be > 1000,
+ mem_mallocs: be > 1000,
+ mem_bytes: be > 100_000 # 100 items * 100 bytes each
+ )
+ end
+ end
+
+ context 'when feature flag trace_memory_allocations is disabled' do
+ before do
+ stub_feature_flags(trace_memory_allocations: false)
+ end
+
+ it 'a nil is returned' do
+ is_expected.to be_nil
+ end
+ end
+
+ context 'when feature is unavailable' do
+ before do
+ allow(described_class).to receive(:available?) { false }
+ end
+
+ it 'a nil is returned' do
+ is_expected.to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb b/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
new file mode 100644
index 00000000000..5bcaf8fbc47
--- /dev/null
+++ b/spec/lib/gitlab/metrics/subscribers/external_http_spec.rb
@@ -0,0 +1,172 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Subscribers::ExternalHttp, :request_store do
+ let(:transaction) { Gitlab::Metrics::Transaction.new }
+ let(:subscriber) { described_class.new }
+
+ let(:event_1) do
+ double(:event, payload: {
+ method: 'POST', code: "200", duration: 0.321,
+ scheme: 'https', host: 'gitlab.com', port: 80, path: '/api/v4/projects',
+ query: 'current=true'
+ })
+ end
+
+ let(:event_2) do
+ double(:event, payload: {
+ method: 'GET', code: "301", duration: 0.12,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
+ query: 'current=true'
+ })
+ end
+
+ let(:event_3) do
+ double(:event, payload: {
+ method: 'POST', duration: 5.3,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
+ query: 'current=true',
+ exception_object: Net::ReadTimeout.new
+ })
+ end
+
+ describe '.detail_store' do
+ context 'when external HTTP detail store is empty' do
+ before do
+ Gitlab::SafeRequestStore[:peek_enabled] = true
+ end
+
+ it 'returns an empty array' do
+ expect(described_class.detail_store).to eql([])
+ end
+ end
+
+ context 'when the performance bar is not enabled' do
+ it 'returns an empty array' do
+ expect(described_class.detail_store).to eql([])
+ end
+ end
+
+ context 'when external HTTP detail store has some values' do
+ before do
+ Gitlab::SafeRequestStore[:peek_enabled] = true
+ Gitlab::SafeRequestStore[:external_http_detail_store] = [{
+ method: 'POST', code: "200", duration: 0.321
+ }]
+ end
+
+ it 'returns the external http detailed store' do
+ expect(described_class.detail_store).to eql([{ method: 'POST', code: "200", duration: 0.321 }])
+ end
+ end
+ end
+
+ describe '.payload' do
+ context 'when SafeRequestStore does not have any item from external HTTP' do
+ it 'returns an empty array' do
+ expect(described_class.payload).to eql(external_http_count: 0, external_http_duration_s: 0.0)
+ end
+ end
+
+ context 'when external HTTP recorded some values' do
+ before do
+ Gitlab::SafeRequestStore[:external_http_count] = 7
+ Gitlab::SafeRequestStore[:external_http_duration_s] = 1.2
+ end
+
+ it 'returns the external http detailed store' do
+ expect(described_class.payload).to eql(external_http_count: 7, external_http_duration_s: 1.2)
+ end
+ end
+ end
+
+ describe '#request' do
+ before do
+ Gitlab::SafeRequestStore[:peek_enabled] = true
+ allow(subscriber).to receive(:current_transaction).and_return(transaction)
+ end
+
+ it 'tracks external HTTP request count' do
+ expect(transaction).to receive(:increment)
+ .with(:gitlab_external_http_total, 1, { code: "200", method: "POST" })
+ expect(transaction).to receive(:increment)
+ .with(:gitlab_external_http_total, 1, { code: "301", method: "GET" })
+
+ subscriber.request(event_1)
+ subscriber.request(event_2)
+ end
+
+ it 'tracks external HTTP duration' do
+ expect(transaction).to receive(:observe)
+ .with(:gitlab_external_http_duration_seconds, 0.321)
+ expect(transaction).to receive(:observe)
+ .with(:gitlab_external_http_duration_seconds, 0.12)
+ expect(transaction).to receive(:observe)
+ .with(:gitlab_external_http_duration_seconds, 5.3)
+
+ subscriber.request(event_1)
+ subscriber.request(event_2)
+ subscriber.request(event_3)
+ end
+
+ it 'tracks external HTTP exceptions' do
+ expect(transaction).to receive(:increment)
+ .with(:gitlab_external_http_total, 1, { code: 'undefined', method: "POST" })
+ expect(transaction).to receive(:increment)
+ .with(:gitlab_external_http_exception_total, 1)
+
+ subscriber.request(event_3)
+ end
+
+ it 'stores per-request counters' do
+ subscriber.request(event_1)
+ subscriber.request(event_2)
+ subscriber.request(event_3)
+
+ expect(Gitlab::SafeRequestStore[:external_http_count]).to eq(3)
+ expect(Gitlab::SafeRequestStore[:external_http_duration_s]).to eq(5.741) # 0.321 + 0.12 + 5.3
+ end
+
+ it 'stores a portion of events into the detail store' do
+ subscriber.request(event_1)
+ subscriber.request(event_2)
+ subscriber.request(event_3)
+
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store].length).to eq(3)
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store][0]).to include(
+ method: 'POST', code: "200", duration: 0.321,
+ scheme: 'https', host: 'gitlab.com', port: 80, path: '/api/v4/projects',
+ query: 'current=true', exception_object: nil,
+ backtrace: be_a(Array)
+ )
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store][1]).to include(
+ method: 'GET', code: "301", duration: 0.12,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
+ query: 'current=true', exception_object: nil,
+ backtrace: be_a(Array)
+ )
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store][2]).to include(
+ method: 'POST', duration: 5.3,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
+ query: 'current=true',
+ exception_object: be_a(Net::ReadTimeout),
+ backtrace: be_a(Array)
+ )
+ end
+
+ context 'when the performance bar is not enabled' do
+ before do
+ Gitlab::SafeRequestStore.delete(:peek_enabled)
+ end
+
+ it 'does not capture detail store' do
+ subscriber.request(event_1)
+ subscriber.request(event_2)
+ subscriber.request(event_3)
+
+ expect(Gitlab::SafeRequestStore[:external_http_detail_store]).to be(nil)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb b/spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb
new file mode 100644
index 00000000000..2d595632772
--- /dev/null
+++ b/spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb
@@ -0,0 +1,203 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Subscribers::RackAttack, :request_store do
+ let(:subscriber) { described_class.new }
+
+ describe '.payload' do
+ context 'when the request store is empty' do
+ it 'returns empty data' do
+ expect(described_class.payload).to eql(
+ rack_attack_redis_count: 0,
+ rack_attack_redis_duration_s: 0.0
+ )
+ end
+ end
+
+ context 'when the request store already has data' do
+ before do
+ Gitlab::SafeRequestStore[:rack_attack_instrumentation] = {
+ rack_attack_redis_count: 10,
+ rack_attack_redis_duration_s: 9.0
+ }
+ end
+
+ it 'returns the accumulated data' do
+ expect(described_class.payload).to eql(
+ rack_attack_redis_count: 10,
+ rack_attack_redis_duration_s: 9.0
+ )
+ end
+ end
+ end
+
+ describe '#redis' do
+ it 'accumulates per-request RackAttack cache usage' do
+ freeze_time do
+ subscriber.redis(
+ ActiveSupport::Notifications::Event.new(
+ 'redis.rack_attack', Time.current, Time.current + 1.second, '1', { operation: 'fetch' }
+ )
+ )
+ subscriber.redis(
+ ActiveSupport::Notifications::Event.new(
+ 'redis.rack_attack', Time.current, Time.current + 2.seconds, '1', { operation: 'write' }
+ )
+ )
+ subscriber.redis(
+ ActiveSupport::Notifications::Event.new(
+ 'redis.rack_attack', Time.current, Time.current + 3.seconds, '1', { operation: 'read' }
+ )
+ )
+ end
+
+ expect(Gitlab::SafeRequestStore[:rack_attack_instrumentation]).to eql(
+ rack_attack_redis_count: 3,
+ rack_attack_redis_duration_s: 6.0
+ )
+ end
+ end
+
+ shared_examples 'log into auth logger' do
+ context 'when matched throttle does not require user information' do
+ let(:event) do
+ ActiveSupport::Notifications::Event.new(
+ event_name, Time.current, Time.current + 2.seconds, '1', request: double(
+ :request,
+ ip: '1.2.3.4',
+ request_method: 'GET',
+ fullpath: '/api/v4/internal/authorized_keys',
+ env: {
+ 'rack.attack.match_type' => match_type,
+ 'rack.attack.matched' => 'throttle_unauthenticated'
+ }
+ )
+ )
+ end
+
+ it 'logs request information' do
+ expect(Gitlab::AuthLogger).to receive(:error).with(
+ include(
+ message: 'Rack_Attack',
+ env: match_type,
+ remote_ip: '1.2.3.4',
+ request_method: 'GET',
+ path: '/api/v4/internal/authorized_keys',
+ matched: 'throttle_unauthenticated'
+ )
+ )
+ subscriber.send(match_type, event)
+ end
+ end
+
+ context 'when matched throttle requires user information' do
+ context 'when user not found' do
+ let(:event) do
+ ActiveSupport::Notifications::Event.new(
+ event_name, Time.current, Time.current + 2.seconds, '1', request: double(
+ :request,
+ ip: '1.2.3.4',
+ request_method: 'GET',
+ fullpath: '/api/v4/internal/authorized_keys',
+ env: {
+ 'rack.attack.match_type' => match_type,
+ 'rack.attack.matched' => 'throttle_authenticated_api',
+ 'rack.attack.match_discriminator' => 'not_exist_user_id'
+ }
+ )
+ )
+ end
+
+ it 'logs request information and user id' do
+ expect(Gitlab::AuthLogger).to receive(:error).with(
+ include(
+ message: 'Rack_Attack',
+ env: match_type,
+ remote_ip: '1.2.3.4',
+ request_method: 'GET',
+ path: '/api/v4/internal/authorized_keys',
+ matched: 'throttle_authenticated_api',
+ user_id: 'not_exist_user_id'
+ )
+ )
+ subscriber.send(match_type, event)
+ end
+ end
+
+ context 'when user found' do
+ let(:user) { create(:user) }
+ let(:event) do
+ ActiveSupport::Notifications::Event.new(
+ event_name, Time.current, Time.current + 2.seconds, '1', request: double(
+ :request,
+ ip: '1.2.3.4',
+ request_method: 'GET',
+ fullpath: '/api/v4/internal/authorized_keys',
+ env: {
+ 'rack.attack.match_type' => match_type,
+ 'rack.attack.matched' => 'throttle_authenticated_api',
+ 'rack.attack.match_discriminator' => user.id
+ }
+ )
+ )
+ end
+
+ it 'logs request information and user meta' do
+ expect(Gitlab::AuthLogger).to receive(:error).with(
+ include(
+ message: 'Rack_Attack',
+ env: match_type,
+ remote_ip: '1.2.3.4',
+ request_method: 'GET',
+ path: '/api/v4/internal/authorized_keys',
+ matched: 'throttle_authenticated_api',
+ user_id: user.id,
+ 'meta.user' => user.username
+ )
+ )
+ subscriber.send(match_type, event)
+ end
+ end
+ end
+ end
+
+ describe '#throttle' do
+ let(:match_type) { :throttle }
+ let(:event_name) { 'throttle.rack_attack' }
+
+ it_behaves_like 'log into auth logger'
+ end
+
+ describe '#blocklist' do
+ let(:match_type) { :blocklist }
+ let(:event_name) { 'blocklist.rack_attack' }
+
+ it_behaves_like 'log into auth logger'
+ end
+
+ describe '#track' do
+ let(:match_type) { :track }
+ let(:event_name) { 'track.rack_attack' }
+
+ it_behaves_like 'log into auth logger'
+ end
+
+ describe '#safelist' do
+ let(:event) do
+ ActiveSupport::Notifications::Event.new(
+ 'safelist.rack_attack', Time.current, Time.current + 2.seconds, '1', request: double(
+ :request,
+ env: {
+ 'rack.attack.matched' => 'throttle_unauthenticated'
+ }
+ )
+ )
+ end
+
+ it 'adds the matched name to safe request store' do
+ subscriber.safelist(event)
+ expect(Gitlab::SafeRequestStore[:instrumentation_throttle_safelist]).to eql('throttle_unauthenticated')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/middleware/request_context_spec.rb b/spec/lib/gitlab/middleware/request_context_spec.rb
index 431f4453e37..6d5b581feaa 100644
--- a/spec/lib/gitlab/middleware/request_context_spec.rb
+++ b/spec/lib/gitlab/middleware/request_context_spec.rb
@@ -18,9 +18,11 @@ RSpec.describe Gitlab::Middleware::RequestContext do
end
describe '#call' do
- context 'setting the client ip' do
- subject { Gitlab::RequestContext.instance.client_ip }
+ let(:instance) { Gitlab::RequestContext.instance }
+
+ subject { described_class.new(app).call(env) }
+ context 'setting the client ip' do
context 'with X-Forwarded-For headers' do
let(:load_balancer_ip) { '1.2.3.4' }
let(:headers) do
@@ -33,13 +35,7 @@ RSpec.describe Gitlab::Middleware::RequestContext do
let(:env) { Rack::MockRequest.env_for("/").merge(headers) }
it 'returns the load balancer IP' do
- endpoint = proc do
- [200, {}, ["Hello"]]
- end
-
- described_class.new(endpoint).call(env)
-
- expect(subject).to eq(load_balancer_ip)
+ expect { subject }.to change { instance.client_ip }.from(nil).to(load_balancer_ip)
end
end
@@ -47,32 +43,19 @@ RSpec.describe Gitlab::Middleware::RequestContext do
let(:ip) { '192.168.1.11' }
before do
- allow_next_instance_of(Rack::Request) do |instance|
- allow(instance).to receive(:ip).and_return(ip)
+ allow_next_instance_of(Rack::Request) do |request|
+ allow(request).to receive(:ip).and_return(ip)
end
- described_class.new(app).call(env)
end
- it { is_expected.to eq(ip) }
- end
+ it 'sets the `client_ip`' do
+ expect { subject }.to change { instance.client_ip }.from(nil).to(ip)
+ end
- context 'before RequestContext middleware run' do
- it { is_expected.to be_nil }
+ it 'sets the `request_start_time`' do
+ expect { subject }.to change { instance.request_start_time }.from(nil).to(Float)
+ end
end
end
end
-
- context 'setting the thread cpu time' do
- it 'sets the `start_thread_cpu_time`' do
- expect { described_class.new(app).call(env) }
- .to change { Gitlab::RequestContext.instance.start_thread_cpu_time }.from(nil).to(Float)
- end
- end
-
- context 'setting the request start time' do
- it 'sets the `request_start_time`' do
- expect { described_class.new(app).call(env) }
- .to change { Gitlab::RequestContext.instance.request_start_time }.from(nil).to(Float)
- end
- end
end
diff --git a/spec/lib/gitlab/pages_transfer_spec.rb b/spec/lib/gitlab/pages_transfer_spec.rb
index 4f0ee76b244..552a2e0701c 100644
--- a/spec/lib/gitlab/pages_transfer_spec.rb
+++ b/spec/lib/gitlab/pages_transfer_spec.rb
@@ -8,13 +8,24 @@ RSpec.describe Gitlab::PagesTransfer do
context 'when receiving an allowed method' do
it 'schedules a PagesTransferWorker', :aggregate_failures do
- described_class::Async::METHODS.each do |meth|
+ described_class::METHODS.each do |meth|
expect(PagesTransferWorker)
.to receive(:perform_async).with(meth, %w[foo bar])
async.public_send(meth, 'foo', 'bar')
end
end
+
+ it 'does nothing if legacy storage is disabled' do
+ stub_feature_flags(pages_update_legacy_storage: false)
+
+ described_class::METHODS.each do |meth|
+ expect(PagesTransferWorker)
+ .not_to receive(:perform_async)
+
+ async.public_send(meth, 'foo', 'bar')
+ end
+ end
end
context 'when receiving a private method' do
@@ -59,6 +70,15 @@ RSpec.describe Gitlab::PagesTransfer do
expect(subject.public_send(meth, *args)).to be(false)
end
+
+ it 'does nothing if legacy storage is disabled' do
+ stub_feature_flags(pages_update_legacy_storage: false)
+
+ subject.public_send(meth, *args)
+
+ expect(File.exist?(config_path_before)).to be(true)
+ expect(File.exist?(config_path_after)).to be(false)
+ end
end
describe '#move_namespace' do
diff --git a/spec/lib/gitlab/patch/prependable_spec.rb b/spec/lib/gitlab/patch/prependable_spec.rb
index 8feab57a8f3..5b01bb99fc8 100644
--- a/spec/lib/gitlab/patch/prependable_spec.rb
+++ b/spec/lib/gitlab/patch/prependable_spec.rb
@@ -231,4 +231,22 @@ RSpec.describe Gitlab::Patch::Prependable do
.to raise_error(described_class::MultiplePrependedBlocks)
end
end
+
+ describe 'the extra hack for override verification' do
+ context 'when ENV["STATIC_VERIFICATION"] is not defined' do
+ it 'does not extend ClassMethods onto the defining module' do
+ expect(ee).not_to respond_to(:class_name)
+ end
+ end
+
+ context 'when ENV["STATIC_VERIFICATION"] is defined' do
+ before do
+ stub_env('STATIC_VERIFICATION', 'true')
+ end
+
+ it 'does extend ClassMethods onto the defining module' do
+ expect(ee).to respond_to(:class_name)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/performance_bar/stats_spec.rb b/spec/lib/gitlab/performance_bar/stats_spec.rb
index c34c6f7b31f..ad11eca56d1 100644
--- a/spec/lib/gitlab/performance_bar/stats_spec.rb
+++ b/spec/lib/gitlab/performance_bar/stats_spec.rb
@@ -22,10 +22,12 @@ RSpec.describe Gitlab::PerformanceBar::Stats do
expect(logger).to receive(:info)
.with({ duration_ms: 1.096, filename: 'lib/gitlab/pagination/offset_pagination.rb',
- filenum: 53, method: 'add_pagination_headers', request_id: 'foo', type: :sql })
+ method_path: 'lib/gitlab/pagination/offset_pagination.rb:add_pagination_headers',
+ count: 1, request_id: 'foo', type: :sql })
expect(logger).to receive(:info)
- .with({ duration_ms: 0.817, filename: 'lib/api/helpers.rb',
- filenum: 112, method: 'find_project', request_id: 'foo', type: :sql }).twice
+ .with({ duration_ms: 1.634, filename: 'lib/api/helpers.rb',
+ method_path: 'lib/api/helpers.rb:find_project',
+ count: 2, request_id: 'foo', type: :sql })
subject
end
diff --git a/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb b/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb
new file mode 100644
index 00000000000..2cb31b00f39
--- /dev/null
+++ b/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::RackAttack::InstrumentedCacheStore do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:store) { ::ActiveSupport::Cache::NullStore.new }
+
+ subject { described_class.new(upstream_store: store)}
+
+ where(:operation, :params, :test_proc) do
+ :fetch | [:key] | ->(s) { s.fetch(:key) }
+ :read | [:key] | ->(s) { s.read(:key) }
+ :read_multi | [:key_1, :key_2, :key_3] | ->(s) { s.read_multi(:key_1, :key_2, :key_3) }
+ :write_multi | [{ key_1: 1, key_2: 2, key_3: 3 }] | ->(s) { s.write_multi(key_1: 1, key_2: 2, key_3: 3) }
+ :fetch_multi | [:key_1, :key_2, :key_3] | ->(s) { s.fetch_multi(:key_1, :key_2, :key_3) {} }
+ :write | [:key, :value, { option_1: 1 }] | ->(s) { s.write(:key, :value, option_1: 1) }
+ :delete | [:key] | ->(s) { s.delete(:key) }
+ :exist? | [:key, { option_1: 1 }] | ->(s) { s.exist?(:key, option_1: 1) }
+ :delete_matched | [/^key$/, { option_1: 1 }] | ->(s) { s.delete_matched(/^key$/, option_1: 1 ) }
+ :increment | [:key, 1] | ->(s) { s.increment(:key, 1) }
+ :decrement | [:key, 1] | ->(s) { s.decrement(:key, 1) }
+ :cleanup | [] | ->(s) { s.cleanup }
+ :clear | [] | ->(s) { s.clear }
+ end
+
+ with_them do
+ it 'publishes a notification' do
+ event = nil
+
+ begin
+ subscriber = ActiveSupport::Notifications.subscribe("redis.rack_attack") do |*args|
+ event = ActiveSupport::Notifications::Event.new(*args)
+ end
+
+ test_proc.call(subject)
+ ensure
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
+ end
+
+ expect(event).not_to be_nil
+ expect(event.name).to eq("redis.rack_attack")
+ expect(event.duration).to be_a(Float).and(be > 0.0)
+ expect(event.payload[:operation]).to eql(operation)
+ end
+
+ it 'publishes a notification even if the cache store returns an error' do
+ allow(store).to receive(operation).and_raise('Something went wrong')
+
+ event = nil
+ exception = nil
+
+ begin
+ subscriber = ActiveSupport::Notifications.subscribe("redis.rack_attack") do |*args|
+ event = ActiveSupport::Notifications::Event.new(*args)
+ end
+
+ begin
+ test_proc.call(subject)
+ rescue => e
+ exception = e
+ end
+ ensure
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
+ end
+
+ expect(event).not_to be_nil
+ expect(event.name).to eq("redis.rack_attack")
+ expect(event.duration).to be_a(Float).and(be > 0.0)
+ expect(event.payload[:operation]).to eql(operation)
+
+ expect(exception).not_to be_nil
+ expect(exception.message).to eql('Something went wrong')
+ end
+
+ it 'delegates to the upstream store' do
+ allow(store).to receive(operation).and_call_original
+
+ if params.empty?
+ expect(store).to receive(operation).with(no_args)
+ else
+ expect(store).to receive(operation).with(*params)
+ end
+
+ test_proc.call(subject)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/rack_attack_spec.rb b/spec/lib/gitlab/rack_attack_spec.rb
index 5748e1e49e5..788d2eac61f 100644
--- a/spec/lib/gitlab/rack_attack_spec.rb
+++ b/spec/lib/gitlab/rack_attack_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
describe '.configure' do
let(:fake_rack_attack) { class_double("Rack::Attack") }
let(:fake_rack_attack_request) { class_double("Rack::Attack::Request") }
+ let(:fake_cache) { instance_double("Rack::Attack::Cache") }
let(:throttles) do
{
@@ -27,6 +28,8 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
allow(fake_rack_attack).to receive(:track)
allow(fake_rack_attack).to receive(:safelist)
allow(fake_rack_attack).to receive(:blocklist)
+ allow(fake_rack_attack).to receive(:cache).and_return(fake_cache)
+ allow(fake_cache).to receive(:store=)
end
it 'extends the request class' do
diff --git a/spec/lib/gitlab/repository_cache_adapter_spec.rb b/spec/lib/gitlab/repository_cache_adapter_spec.rb
index 4c57665b41f..625dcf11546 100644
--- a/spec/lib/gitlab/repository_cache_adapter_spec.rb
+++ b/spec/lib/gitlab/repository_cache_adapter_spec.rb
@@ -292,12 +292,11 @@ RSpec.describe Gitlab::RepositoryCacheAdapter do
describe '#expire_method_caches' do
it 'expires the caches of the given methods' do
- expect(cache).to receive(:expire).with(:rendered_readme)
expect(cache).to receive(:expire).with(:branch_names)
- expect(redis_set_cache).to receive(:expire).with(:rendered_readme, :branch_names)
- expect(redis_hash_cache).to receive(:delete).with(:rendered_readme, :branch_names)
+ expect(redis_set_cache).to receive(:expire).with(:branch_names)
+ expect(redis_hash_cache).to receive(:delete).with(:branch_names)
- repository.expire_method_caches(%i(rendered_readme branch_names))
+ repository.expire_method_caches(%i(branch_names))
end
it 'does not expire caches for non-existent methods' do
diff --git a/spec/lib/gitlab/request_forgery_protection_spec.rb b/spec/lib/gitlab/request_forgery_protection_spec.rb
index 20996dd44b8..a7b777cf4f2 100644
--- a/spec/lib/gitlab/request_forgery_protection_spec.rb
+++ b/spec/lib/gitlab/request_forgery_protection_spec.rb
@@ -52,6 +52,11 @@ RSpec.describe Gitlab::RequestForgeryProtection, :allow_forgery_protection do
end
describe '.verified?' do
+ it 'does not modify the env' do
+ env['REQUEST_METHOD'] = "GET"
+ expect { described_class.verified?(env) }.not_to change { env }
+ end
+
context 'when the request method is GET' do
before do
env['REQUEST_METHOD'] = 'GET'
diff --git a/spec/lib/gitlab/runtime_spec.rb b/spec/lib/gitlab/runtime_spec.rb
index 8ed7cc141cd..1ec14092c63 100644
--- a/spec/lib/gitlab/runtime_spec.rb
+++ b/spec/lib/gitlab/runtime_spec.rb
@@ -44,10 +44,11 @@ RSpec.describe Gitlab::Runtime do
context "puma" do
let(:puma_type) { double('::Puma') }
+ let(:max_workers) { 2 }
before do
stub_const('::Puma', puma_type)
- allow(puma_type).to receive_message_chain(:cli_config, :options).and_return(max_threads: 2)
+ allow(puma_type).to receive_message_chain(:cli_config, :options).and_return(max_threads: 2, workers: max_workers)
stub_env('ACTION_CABLE_IN_APP', 'false')
end
@@ -70,6 +71,20 @@ RSpec.describe Gitlab::Runtime do
it_behaves_like "valid runtime", :puma, 11
end
+
+ describe ".puma_in_clustered_mode?" do
+ context 'when Puma is set up with workers > 0' do
+ let(:max_workers) { 4 }
+
+ specify { expect(described_class.puma_in_clustered_mode?).to be true }
+ end
+
+ context 'when Puma is set up with workers = 0' do
+ let(:max_workers) { 0 }
+
+ specify { expect(described_class.puma_in_clustered_mode?).to be false }
+ end
+ end
end
context "unicorn" do
diff --git a/spec/lib/gitlab/search/query_spec.rb b/spec/lib/gitlab/search/query_spec.rb
index dd2f23a7e47..234b683ba1f 100644
--- a/spec/lib/gitlab/search/query_spec.rb
+++ b/spec/lib/gitlab/search/query_spec.rb
@@ -46,4 +46,22 @@ RSpec.describe Gitlab::Search::Query do
expect(subject.filters).to all(include(negated: true))
end
end
+
+ context 'with filter value in quotes' do
+ let(:query) { '"foo bar" name:"my test script.txt"' }
+
+ it 'does not break the filter value in quotes' do
+ expect(subject.term).to eq('"foo bar"')
+ expect(subject.filters[0]).to include(name: :name, negated: false, value: "MY TEST SCRIPT.TXT")
+ end
+ end
+
+ context 'with extra white spaces between the query words' do
+ let(:query) { ' foo = bar name:"my test.txt"' }
+
+ it 'removes the extra whitespace between tokens' do
+ expect(subject.term).to eq('foo = bar')
+ expect(subject.filters[0]).to include(name: :name, negated: false, value: "MY TEST.TXT")
+ end
+ end
end
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index c437b6bcceb..a1b18172a31 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::SearchResults do
include ProjectForksHelper
include SearchHelpers
+ using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, name: 'foo') }
@@ -41,8 +42,6 @@ RSpec.describe Gitlab::SearchResults do
end
describe '#formatted_count' do
- using RSpec::Parameterized::TableSyntax
-
where(:scope, :count_method, :expected) do
'projects' | :limited_projects_count | max_limited_count
'issues' | :limited_issues_count | max_limited_count
@@ -61,8 +60,6 @@ RSpec.describe Gitlab::SearchResults do
end
describe '#highlight_map' do
- using RSpec::Parameterized::TableSyntax
-
where(:scope, :expected) do
'projects' | {}
'issues' | {}
@@ -80,8 +77,6 @@ RSpec.describe Gitlab::SearchResults do
end
describe '#formatted_limited_count' do
- using RSpec::Parameterized::TableSyntax
-
where(:count, :expected) do
23 | '23'
99 | '99'
@@ -183,12 +178,18 @@ RSpec.describe Gitlab::SearchResults do
end
context 'ordering' do
- let(:query) { 'sorted' }
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
- include_examples 'search results sorted'
+ let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
+ let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
+ let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
+
+ include_examples 'search results sorted' do
+ let(:results_created) { described_class.new(user, 'sorted', Project.order(:id), sort: sort, filters: filters) }
+ let(:results_updated) { described_class.new(user, 'updated', Project.order(:id), sort: sort, filters: filters) }
+ end
end
end
@@ -219,12 +220,18 @@ RSpec.describe Gitlab::SearchResults do
end
context 'ordering' do
- let(:query) { 'sorted' }
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
- include_examples 'search results sorted'
+ let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
+ let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
+ let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
+
+ include_examples 'search results sorted' do
+ let(:results_created) { described_class.new(user, 'sorted', Project.order(:id), sort: sort, filters: filters) }
+ let(:results_updated) { described_class.new(user, 'updated', Project.order(:id), sort: sort, filters: filters) }
+ end
end
end
diff --git a/spec/lib/gitlab/sidekiq_logging/exception_handler_spec.rb b/spec/lib/gitlab/sidekiq_logging/exception_handler_spec.rb
deleted file mode 100644
index 94dcf6f9b9a..00000000000
--- a/spec/lib/gitlab/sidekiq_logging/exception_handler_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::SidekiqLogging::ExceptionHandler do
- describe '#call' do
- let(:job) do
- {
- "class" => "TestWorker",
- "args" => [1234, 'hello'],
- "retry" => false,
- "queue" => "cronjob:test_queue",
- "queue_namespace" => "cronjob",
- "jid" => "da883554ee4fe414012f5f42",
- "correlation_id" => 'cid'
- }
- end
-
- let(:exception_message) { 'An error was thrown' }
- let(:backtrace) { caller }
- let(:exception) { RuntimeError.new(exception_message) }
- let(:logger) { double }
-
- before do
- allow(Sidekiq).to receive(:logger).and_return(logger)
- allow(exception).to receive(:backtrace).and_return(backtrace)
- end
-
- subject { described_class.new.call(exception, { context: 'Test', job: job }) }
-
- it 'logs job data into root tree' do
- expected_data = job.merge(
- error_class: 'RuntimeError',
- error_message: exception_message,
- context: 'Test',
- error_backtrace: Rails.backtrace_cleaner.clean(backtrace)
- )
-
- expect(logger).to receive(:warn).with(expected_data)
-
- subject
- end
- end
-end
diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
index b99a5352717..3e8e117ec71 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -3,7 +3,13 @@
require 'spec_helper'
RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
- describe '#call' do
+ before do
+ # We disable a memory instrumentation feature
+ # as this requires a special patched Ruby
+ allow(Gitlab::Memory::Instrumentation).to receive(:available?) { false }
+ end
+
+ describe '#call', :request_store do
let(:timestamp) { Time.iso8601('2018-01-01T12:00:00.000Z') }
let(:created_at) { timestamp - 1.second }
let(:scheduling_latency_s) { 1.0 }
@@ -21,14 +27,13 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
"correlation_id" => 'cid',
"error_message" => "wrong number of arguments (2 for 3)",
"error_class" => "ArgumentError",
- "error_backtrace" => [],
- "db_count" => 1,
- "db_write_count" => 0,
- "db_cached_count" => 0
+ "error_backtrace" => []
}
end
let(:logger) { double }
+ let(:clock_realtime_start) { 0.222222299 }
+ let(:clock_realtime_end) { 1.333333799 }
let(:clock_thread_cputime_start) { 0.222222299 }
let(:clock_thread_cputime_end) { 1.333333799 }
let(:start_payload) do
@@ -38,7 +43,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'pid' => Process.pid,
'created_at' => created_at.to_f,
'enqueued_at' => created_at.to_f,
- 'scheduling_latency_s' => scheduling_latency_s
+ 'scheduling_latency_s' => scheduling_latency_s,
+ 'job_size_bytes' => be > 0
)
end
@@ -49,7 +55,10 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'duration_s' => 0.0,
'completed_at' => timestamp.to_f,
'cpu_s' => 1.111112,
- 'db_duration_s' => 0.0
+ 'db_duration_s' => 0.0,
+ 'db_cached_count' => 0,
+ 'db_count' => 0,
+ 'db_write_count' => 0
)
end
@@ -58,7 +67,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: fail: 0.0 sec',
'job_status' => 'fail',
'error_class' => 'ArgumentError',
- 'error_message' => 'some exception'
+ 'error_message' => 'Something went wrong',
+ 'error_backtrace' => be_a(Array).and(be_present)
)
end
@@ -67,7 +77,10 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
allow(subject).to receive(:current_time).and_return(timestamp.to_f)
- allow(Process).to receive(:clock_gettime).with(Process::CLOCK_THREAD_CPUTIME_ID).and_return(clock_thread_cputime_start, clock_thread_cputime_end)
+ allow(Process).to receive(:clock_gettime).with(Process::CLOCK_REALTIME, :float_second)
+ .and_return(clock_realtime_start, clock_realtime_end)
+ allow(Process).to receive(:clock_gettime).with(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
+ .and_return(clock_thread_cputime_start, clock_thread_cputime_end)
end
subject { described_class.new }
@@ -84,25 +97,97 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- subject.call(job, 'test_queue') { }
+ call_subject(job, 'test_queue') { }
+ end
+ end
+
+ it 'logs real job wrapped by active job worker' do
+ wrapped_job = job.merge(
+ "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
+ "wrapped" => "TestWorker"
+ )
+
+ Timecop.freeze(timestamp) do
+ expect(logger).to receive(:info).with(start_payload).ordered
+ expect(logger).to receive(:info).with(end_payload).ordered
+ expect(subject).to receive(:log_job_start).and_call_original
+ expect(subject).to receive(:log_job_done).and_call_original
+
+ call_subject(wrapped_job, 'test_queue') { }
end
end
it 'logs an exception in job' do
Timecop.freeze(timestamp) do
expect(logger).to receive(:info).with(start_payload)
- expect(logger).to receive(:warn).with(hash_including(exception_payload))
+ expect(logger).to receive(:warn).with(include(exception_payload))
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
expect do
- subject.call(job, 'test_queue') do
- raise ArgumentError, 'some exception'
+ call_subject(job, 'test_queue') do
+ raise ArgumentError, 'Something went wrong'
end
end.to raise_error(ArgumentError)
end
end
+ it 'logs the root cause of an Sidekiq::JobRetry::Skip exception in the job' do
+ Timecop.freeze(timestamp) do
+ expect(logger).to receive(:info).with(start_payload)
+ expect(logger).to receive(:warn).with(include(exception_payload))
+ expect(subject).to receive(:log_job_start).and_call_original
+ expect(subject).to receive(:log_job_done).and_call_original
+
+ expect do
+ call_subject(job, 'test_queue') do
+ raise ArgumentError, 'Something went wrong'
+ rescue
+ raise Sidekiq::JobRetry::Skip
+ end
+ end.to raise_error(Sidekiq::JobRetry::Skip)
+ end
+ end
+
+ it 'logs the root cause of an Sidekiq::JobRetry::Handled exception in the job' do
+ Timecop.freeze(timestamp) do
+ expect(logger).to receive(:info).with(start_payload)
+ expect(logger).to receive(:warn).with(include(exception_payload))
+ expect(subject).to receive(:log_job_start).and_call_original
+ expect(subject).to receive(:log_job_done).and_call_original
+
+ expect do
+ call_subject(job, 'test_queue') do
+ raise ArgumentError, 'Something went wrong'
+ rescue
+ raise Sidekiq::JobRetry::Handled
+ end
+ end.to raise_error(Sidekiq::JobRetry::Handled)
+ end
+ end
+
+ it 'keeps Sidekiq::JobRetry::Handled exception if the cause does not exist' do
+ Timecop.freeze(timestamp) do
+ expect(logger).to receive(:info).with(start_payload)
+ expect(logger).to receive(:warn).with(
+ include(
+ 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: fail: 0.0 sec',
+ 'job_status' => 'fail',
+ 'error_class' => 'Sidekiq::JobRetry::Skip',
+ 'error_message' => 'Sidekiq::JobRetry::Skip'
+ )
+ )
+ expect(subject).to receive(:log_job_start).and_call_original
+ expect(subject).to receive(:log_job_done).and_call_original
+
+ expect do
+ call_subject(job, 'test_queue') do
+ raise Sidekiq::JobRetry::Skip
+ end
+ end.to raise_error(Sidekiq::JobRetry::Skip)
+ end
+ end
+
it 'does not modify the job' do
Timecop.freeze(timestamp) do
job_copy = job.deep_dup
@@ -111,11 +196,29 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
allow(subject).to receive(:log_job_start).and_call_original
allow(subject).to receive(:log_job_done).and_call_original
- subject.call(job, 'test_queue') do
+ call_subject(job, 'test_queue') do
expect(job).to eq(job_copy)
end
end
end
+
+ it 'does not modify the wrapped job' do
+ Timecop.freeze(timestamp) do
+ wrapped_job = job.merge(
+ "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
+ "wrapped" => "TestWorker"
+ )
+ job_copy = wrapped_job.deep_dup
+
+ allow(logger).to receive(:info)
+ allow(subject).to receive(:log_job_start).and_call_original
+ allow(subject).to receive(:log_job_done).and_call_original
+
+ call_subject(wrapped_job, 'test_queue') do
+ expect(wrapped_job).to eq(job_copy)
+ end
+ end
+ end
end
context 'with SIDEKIQ_LOG_ARGUMENTS disabled' do
@@ -130,7 +233,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- subject.call(job, 'test_queue') { }
+ call_subject(job, 'test_queue') { }
end
end
@@ -143,7 +246,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- subject.call(job.except("created_at", "enqueued_at"), 'test_queue') { }
+ call_subject(job.except("created_at", "enqueued_at"), 'test_queue') { }
end
end
end
@@ -159,7 +262,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- subject.call(job, 'test_queue') { }
+ call_subject(job, 'test_queue') { }
end
end
end
@@ -177,7 +280,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
let(:expected_end_payload) do
- end_payload.merge(timing_data)
+ end_payload.merge(timing_data.stringify_keys)
end
it 'logs with Gitaly and Rugged timing data' do
@@ -185,7 +288,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(logger).to receive(:info).with(start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload).ordered
- subject.call(job, 'test_queue') do
+ call_subject(job, 'test_queue') do
job.merge!(timing_data)
end
end
@@ -207,7 +310,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
let(:expected_end_payload_with_db) do
expected_end_payload.merge(
'db_duration_s' => a_value >= 0.1,
- 'db_count' => 1,
+ 'db_count' => a_value >= 1,
'db_cached_count' => 0,
'db_write_count' => 0
)
@@ -217,7 +320,9 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(logger).to receive(:info).with(expected_start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload_with_db).ordered
- subject.call(job, 'test_queue') { ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') }
+ call_subject(job, 'test_queue') do
+ ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ end
end
it 'prevents database time from leaking to the next job' do
@@ -226,8 +331,13 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(logger).to receive(:info).with(expected_start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload).ordered
- subject.call(job, 'test_queue') { ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') }
- subject.call(job, 'test_queue') { }
+ call_subject(job.dup, 'test_queue') do
+ ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);')
+ end
+
+ Gitlab::SafeRequestStore.clear!
+
+ call_subject(job.dup, 'test_queue') { }
end
end
@@ -243,7 +353,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(logger).to receive(:info).with(expected_start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload).ordered
- subject.call(job, 'test_queue') do
+ call_subject(job, 'test_queue') do
job["#{ApplicationWorker::LOGGING_EXTRA_KEY}.key1"] = 15
job["#{ApplicationWorker::LOGGING_EXTRA_KEY}.key2"] = 16
job['key that will be ignored because it does not start with extra.'] = 17
@@ -251,13 +361,29 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
end
end
end
+
+ def call_subject(job, queue)
+ # This structured logger strongly depends on execution of `InstrumentationLogger`
+ subject.call(job, queue) do
+ ::Gitlab::SidekiqMiddleware::InstrumentationLogger.new.call('worker', job, queue) do
+ yield
+ end
+ end
+ end
end
describe '#add_time_keys!' do
- let(:time) { { duration: 0.1231234, cputime: 1.2342345 } }
+ let(:time) { { duration: 0.1231234 } }
let(:payload) { { 'class' => 'my-class', 'message' => 'my-message', 'job_status' => 'my-job-status' } }
let(:current_utc_time) { Time.now.utc }
- let(:payload_with_time_keys) { { 'class' => 'my-class', 'message' => 'my-message', 'job_status' => 'my-job-status', 'duration_s' => 0.123123, 'cpu_s' => 1.234235, 'completed_at' => current_utc_time.to_f } }
+
+ let(:payload_with_time_keys) do
+ { 'class' => 'my-class',
+ 'message' => 'my-message',
+ 'job_status' => 'my-job-status',
+ 'duration_s' => 0.123123,
+ 'completed_at' => current_utc_time.to_f }
+ end
subject { described_class.new }
diff --git a/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb
index f7010b2001a..e2b36125b4e 100644
--- a/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb
@@ -60,6 +60,27 @@ RSpec.describe Gitlab::SidekiqMiddleware::ClientMetrics do
end
end
+ context "when a worker is wrapped into ActiveJob" do
+ before do
+ stub_const('TestWrappedWorker', Class.new)
+ TestWrappedWorker.class_eval do
+ include Sidekiq::Worker
+ end
+ end
+
+ it_behaves_like "a metrics client middleware" do
+ let(:job) do
+ {
+ "class" => ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper,
+ "wrapped" => TestWrappedWorker
+ }
+ end
+
+ let(:worker) { TestWrappedWorker.new }
+ let(:labels) { default_labels.merge(urgency: "") }
+ end
+ end
+
context "when workers are attributed" do
def create_attributed_worker_class(urgency, external_dependencies, resource_boundary, category)
klass = Class.new do
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 44bfaf4cc3c..e58e41d3e4f 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -198,6 +198,28 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
it_behaves_like "a metrics middleware"
end
+ context "when a worker is wrapped into ActiveJob" do
+ before do
+ stub_const('TestWrappedWorker', Class.new)
+ TestWrappedWorker.class_eval do
+ include Sidekiq::Worker
+ end
+ end
+
+ let(:job) do
+ {
+ "class" => ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper,
+ "wrapped" => TestWrappedWorker
+ }
+ end
+
+ let(:worker) { TestWrappedWorker.new }
+ let(:worker_class) { TestWrappedWorker }
+ let(:labels) { default_labels.merge(urgency: "") }
+
+ it_behaves_like "a metrics middleware"
+ end
+
context "when workers are attributed" do
def create_attributed_worker_class(urgency, external_dependencies, resource_boundary, category)
Class.new do
diff --git a/spec/lib/gitlab/suggestions/commit_message_spec.rb b/spec/lib/gitlab/suggestions/commit_message_spec.rb
index 1411f64f8b7..965960f0c3e 100644
--- a/spec/lib/gitlab/suggestions/commit_message_spec.rb
+++ b/spec/lib/gitlab/suggestions/commit_message_spec.rb
@@ -72,6 +72,17 @@ RSpec.describe Gitlab::Suggestions::CommitMessage do
end
end
+ context 'when a custom commit message is specified' do
+ let(:message) { "i'm a project message. a user's custom message takes precedence over me :(" }
+ let(:custom_message) { "hello there! i'm a cool custom commit message." }
+
+ it 'shows the custom commit message' do
+ expect(Gitlab::Suggestions::CommitMessage
+ .new(user, suggestion_set, custom_message)
+ .message).to eq(custom_message)
+ end
+ end
+
context 'is specified and includes all placeholders' do
let(:message) do
'*** %{branch_name} %{files_count} %{file_paths} %{project_name} %{project_path} %{user_full_name} %{username} %{suggestions_count} ***'
diff --git a/spec/lib/gitlab/template/finders/global_template_finder_spec.rb b/spec/lib/gitlab/template/finders/global_template_finder_spec.rb
index e2751d194d3..38ec28c2b9a 100644
--- a/spec/lib/gitlab/template/finders/global_template_finder_spec.rb
+++ b/spec/lib/gitlab/template/finders/global_template_finder_spec.rb
@@ -15,9 +15,19 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
FileUtils.rm_rf(base_dir)
end
- subject(:finder) { described_class.new(base_dir, '', { 'General' => '', 'Bar' => 'Bar' }, excluded_patterns: excluded_patterns) }
+ subject(:finder) do
+ described_class.new(base_dir, '',
+ { 'General' => '', 'Bar' => 'Bar' },
+ include_categories_for_file,
+ excluded_patterns: excluded_patterns)
+ end
let(:excluded_patterns) { [] }
+ let(:include_categories_for_file) do
+ {
+ "SAST" => { "Security" => "Security" }
+ }
+ end
describe '.find' do
context 'with a non-prefixed General template' do
@@ -60,6 +70,7 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
context 'with a prefixed template' do
before do
create_template!('Bar/test-template')
+ create_template!('Security/SAST')
end
it 'finds the template with a prefix' do
@@ -76,6 +87,16 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
expect { finder.find('../foo') }.to raise_error(/Invalid path/)
end
+ context 'with include_categories_for_file being present' do
+ it 'finds the template with a prefix' do
+ expect(finder.find('SAST')).to be_present
+ end
+
+ it 'does not find any template which is missing in include_categories_for_file' do
+ expect(finder.find('DAST')).to be_nil
+ end
+ end
+
context 'while listed as an exclusion' do
let(:excluded_patterns) { [%r{^Bar/test-template$}] }
diff --git a/spec/lib/gitlab/terraform/state_migration_helper_spec.rb b/spec/lib/gitlab/terraform/state_migration_helper_spec.rb
new file mode 100644
index 00000000000..36c9c060e98
--- /dev/null
+++ b/spec/lib/gitlab/terraform/state_migration_helper_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Terraform::StateMigrationHelper do
+ before do
+ stub_terraform_state_object_storage
+ end
+
+ describe '.migrate_to_remote_storage' do
+ let!(:local_version) { create(:terraform_state_version, file_store: Terraform::StateUploader::Store::LOCAL) }
+
+ subject { described_class.migrate_to_remote_storage }
+
+ it 'migrates remote files to remote storage' do
+ subject
+
+ expect(local_version.reload.file_store).to eq(Terraform::StateUploader::Store::REMOTE)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
index acf7aeb303a..7a0a4f0cc46 100644
--- a/spec/lib/gitlab/tracking/standard_context_spec.rb
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -9,47 +9,48 @@ RSpec.describe Gitlab::Tracking::StandardContext do
let(:snowplow_context) { subject.to_context }
describe '#to_context' do
- context 'with no arguments' do
- it 'creates a Snowplow context with no data' do
- snowplow_context.to_json[:data].each do |_, v|
- expect(v).to be_nil
+ context 'environment' do
+ shared_examples 'contains environment' do |expected_environment|
+ it 'contains environment' do
+ expect(snowplow_context.to_json.dig(:data, :environment)).to eq(expected_environment)
end
end
- end
- context 'with extra data' do
- subject { described_class.new(foo: 'bar') }
-
- it 'creates a Snowplow context with the given data' do
- expect(snowplow_context.to_json.dig(:data, :foo)).to eq('bar')
+ context 'development or test' do
+ include_examples 'contains environment', 'development'
end
- end
- context 'with namespace' do
- subject { described_class.new(namespace: namespace) }
+ context 'staging' do
+ before do
+ allow(Gitlab).to receive(:staging?).and_return(true)
+ end
- it 'creates a Snowplow context using the given data' do
- expect(snowplow_context.to_json.dig(:data, :namespace_id)).to eq(namespace.id)
- expect(snowplow_context.to_json.dig(:data, :project_id)).to be_nil
+ include_examples 'contains environment', 'staging'
end
- end
- context 'with project' do
- subject { described_class.new(project: project) }
+ context 'production' do
+ before do
+ allow(Gitlab).to receive(:com_and_canary?).and_return(true)
+ end
- it 'creates a Snowplow context using the given data' do
- expect(snowplow_context.to_json.dig(:data, :namespace_id)).to eq(project.namespace.id)
- expect(snowplow_context.to_json.dig(:data, :project_id)).to eq(project.id)
+ include_examples 'contains environment', 'production'
end
end
- context 'with project and namespace' do
- subject { described_class.new(namespace: namespace, project: project) }
+ it 'contains source' do
+ expect(snowplow_context.to_json.dig(:data, :source)).to eq(described_class::GITLAB_RAILS_SOURCE)
+ end
+
+ context 'with extra data' do
+ subject { described_class.new(foo: 'bar') }
- it 'creates a Snowplow context using the given data' do
- expect(snowplow_context.to_json.dig(:data, :namespace_id)).to eq(namespace.id)
- expect(snowplow_context.to_json.dig(:data, :project_id)).to eq(project.id)
+ it 'creates a Snowplow context with the given data' do
+ expect(snowplow_context.to_json.dig(:data, :foo)).to eq('bar')
end
end
+
+ it 'does not contain any ids' do
+ expect(snowplow_context.to_json[:data].keys).not_to include(:user_id, :project_id, :namespace_id)
+ end
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index 8f1fd49f4c5..80740c8112e 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -42,36 +42,31 @@ RSpec.describe Gitlab::Tracking do
end
shared_examples 'delegates to destination' do |klass|
- context 'with standard context' do
- it "delegates to #{klass} destination" do
- expect_any_instance_of(klass).to receive(:event) do |_, category, action, args|
- expect(category).to eq('category')
- expect(action).to eq('action')
- expect(args[:label]).to eq('label')
- expect(args[:property]).to eq('property')
- expect(args[:value]).to eq(1.5)
- expect(args[:context].length).to eq(1)
- expect(args[:context].first.to_json[:schema]).to eq(Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL)
- expect(args[:context].first.to_json[:data]).to include(foo: 'bar')
- end
+ it "delegates to #{klass} destination" do
+ other_context = double(:context)
- described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5,
- standard_context: Gitlab::Tracking::StandardContext.new(foo: 'bar'))
- end
- end
+ project = double(:project)
+ user = double(:user)
+ namespace = double(:namespace)
- context 'without standard context' do
- it "delegates to #{klass} destination" do
- expect_any_instance_of(klass).to receive(:event) do |_, category, action, args|
- expect(category).to eq('category')
- expect(action).to eq('action')
- expect(args[:label]).to eq('label')
- expect(args[:property]).to eq('property')
- expect(args[:value]).to eq(1.5)
- end
+ expect(Gitlab::Tracking::StandardContext)
+ .to receive(:new)
+ .with(project: project, user: user, namespace: namespace)
+ .and_call_original
- described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5)
+ expect_any_instance_of(klass).to receive(:event) do |_, category, action, args|
+ expect(category).to eq('category')
+ expect(action).to eq('action')
+ expect(args[:label]).to eq('label')
+ expect(args[:property]).to eq('property')
+ expect(args[:value]).to eq(1.5)
+ expect(args[:context].length).to eq(2)
+ expect(args[:context].first).to eq(other_context)
+ expect(args[:context].last.to_json[:schema]).to eq(Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL)
end
+
+ described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5,
+ context: [other_context], project: project, user: user, namespace: namespace)
end
end
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index 686382dc262..fa01d4e48df 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -302,36 +302,36 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
it 'does not block urls from private networks' do
local_ips.each do |ip|
stub_domain_resolv(fake_domain, ip) do
- expect(described_class).not_to be_blocked_url("http://#{fake_domain}", url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url("http://#{fake_domain}", **url_blocker_attributes)
end
- expect(described_class).not_to be_blocked_url("http://#{ip}", url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url("http://#{ip}", **url_blocker_attributes)
end
end
it 'allows localhost endpoints' do
- expect(described_class).not_to be_blocked_url('http://0.0.0.0', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://localhost', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://127.0.0.1', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://0.0.0.0', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://localhost', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://127.0.0.1', **url_blocker_attributes)
end
it 'allows loopback endpoints' do
- expect(described_class).not_to be_blocked_url('http://127.0.0.2', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://127.0.0.2', **url_blocker_attributes)
end
it 'allows IPv4 link-local endpoints' do
- expect(described_class).not_to be_blocked_url('http://169.254.169.254', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://169.254.168.100', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://169.254.169.254', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://169.254.168.100', **url_blocker_attributes)
end
it 'allows IPv6 link-local endpoints' do
- expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.169.254]', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.169.254]', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a9fe]', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.168.100]', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.168.100]', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a864]', url_blocker_attributes)
- expect(described_class).not_to be_blocked_url('http://[fe80::c800:eff:fe74:8]', url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.169.254]', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.169.254]', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a9fe]', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.168.100]', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.168.100]', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a864]', **url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url('http://[fe80::c800:eff:fe74:8]', **url_blocker_attributes)
end
end
@@ -416,11 +416,11 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
attrs = url_blocker_attributes.merge(dns_rebind_protection: false)
stub_domain_resolv('example.com', '192.168.1.2') do
- expect(described_class).not_to be_blocked_url(url, attrs)
+ expect(described_class).not_to be_blocked_url(url, **attrs)
end
stub_domain_resolv('example.com', '192.168.1.3') do
- expect(described_class).to be_blocked_url(url, attrs)
+ expect(described_class).to be_blocked_url(url, **attrs)
end
end
end
@@ -442,18 +442,18 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
stub_domain_resolv(domain, '192.168.1.1') do
expect(described_class).not_to be_blocked_url("http://#{domain}",
- url_blocker_attributes)
+ **url_blocker_attributes)
end
stub_domain_resolv(subdomain1, '192.168.1.1') do
expect(described_class).not_to be_blocked_url("http://#{subdomain1}",
- url_blocker_attributes)
+ **url_blocker_attributes)
end
# subdomain2 is not part of the allowlist so it should be blocked
stub_domain_resolv(subdomain2, '192.168.1.1') do
expect(described_class).to be_blocked_url("http://#{subdomain2}",
- url_blocker_attributes)
+ **url_blocker_attributes)
end
end
@@ -463,12 +463,12 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
stub_domain_resolv(unicode_domain, '192.168.1.1') do
expect(described_class).not_to be_blocked_url("http://#{unicode_domain}",
- url_blocker_attributes)
+ **url_blocker_attributes)
end
stub_domain_resolv(idna_encoded_domain, '192.168.1.1') do
expect(described_class).not_to be_blocked_url("http://#{idna_encoded_domain}",
- url_blocker_attributes)
+ **url_blocker_attributes)
end
end
@@ -525,7 +525,7 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
it 'allows domain with port when resolved ip has port allowed' do
stub_domain_resolv("www.resolve-domain.com", '127.0.0.1') do
- expect(described_class).not_to be_blocked_url("http://www.resolve-domain.com:2000", url_blocker_attributes)
+ expect(described_class).not_to be_blocked_url("http://www.resolve-domain.com:2000", **url_blocker_attributes)
end
end
end
diff --git a/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb b/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb
index d9e44e9b85c..4c4248b143e 100644
--- a/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb
+++ b/spec/lib/gitlab/url_blockers/url_allowlist_spec.rb
@@ -37,19 +37,19 @@ RSpec.describe Gitlab::UrlBlockers::UrlAllowlist do
let(:allowlist) { ['example.io:3000'] }
it 'returns true if domain and ports present in allowlist' do
- parsed_allowlist = [['example.io', { port: 3000 }]]
+ parsed_allowlist = [['example.io', 3000]]
not_allowed = [
'example.io',
- ['example.io', { port: 3001 }]
+ ['example.io', 3001]
]
aggregate_failures do
- parsed_allowlist.each do |domain_and_port|
- expect(described_class).to be_domain_allowed(*domain_and_port)
+ parsed_allowlist.each do |domain, port|
+ expect(described_class).to be_domain_allowed(domain, port: port)
end
- not_allowed.each do |domain_and_port|
- expect(described_class).not_to be_domain_allowed(*domain_and_port)
+ not_allowed.each do |domain, port|
+ expect(described_class).not_to be_domain_allowed(domain, port: port)
end
end
end
@@ -139,23 +139,23 @@ RSpec.describe Gitlab::UrlBlockers::UrlAllowlist do
it 'returns true if ip and ports present in allowlist' do
parsed_allowlist = [
- ['127.0.0.9', { port: 3000 }],
- ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 443 }]
+ ['127.0.0.9', 3000],
+ ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', 443]
]
not_allowed = [
'127.0.0.9',
- ['127.0.0.9', { port: 3001 }],
+ ['127.0.0.9', 3001],
'[2001:db8:85a3:8d3:1319:8a2e:370:7348]',
- ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', { port: 3001 }]
+ ['[2001:db8:85a3:8d3:1319:8a2e:370:7348]', 3001]
]
aggregate_failures do
- parsed_allowlist.each do |ip_and_port|
- expect(described_class).to be_ip_allowed(*ip_and_port)
+ parsed_allowlist.each do |ip, port|
+ expect(described_class).to be_ip_allowed(ip, port: port)
end
- not_allowed.each do |ip_and_port|
- expect(described_class).not_to be_ip_allowed(*ip_and_port)
+ not_allowed.each do |ip, port|
+ expect(described_class).not_to be_ip_allowed(ip, port: port)
end
end
end
diff --git a/spec/lib/gitlab/usage/docs/renderer_spec.rb b/spec/lib/gitlab/usage/docs/renderer_spec.rb
new file mode 100644
index 00000000000..0677aa2d9d7
--- /dev/null
+++ b/spec/lib/gitlab/usage/docs/renderer_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Docs::Renderer do
+ describe 'contents' do
+ let(:dictionary_path) { Gitlab::Usage::Docs::Renderer::DICTIONARY_PATH }
+ let(:items) { Gitlab::Usage::MetricDefinition.definitions }
+
+ it 'generates dictionary for given items' do
+ generated_dictionary = described_class.new(items).contents
+ generated_dictionary_keys = RDoc::Markdown
+ .parse(generated_dictionary)
+ .table_of_contents
+ .select { |metric_doc| metric_doc.level == 2 && !metric_doc.text.start_with?('info:') }
+ .map(&:text)
+ .map { |text| text.sub('<code>', '').sub('</code>', '') }
+
+ expect(generated_dictionary_keys).to match_array(items.keys)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/docs/value_formatter_spec.rb b/spec/lib/gitlab/usage/docs/value_formatter_spec.rb
new file mode 100644
index 00000000000..7002c76a7cf
--- /dev/null
+++ b/spec/lib/gitlab/usage/docs/value_formatter_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Docs::ValueFormatter do
+ describe '.format' do
+ using RSpec::Parameterized::TableSyntax
+ where(:key, :value, :expected_value) do
+ :product_group | 'growth::product intelligence' | '`growth::product intelligence`'
+ :data_source | 'redis' | 'Redis'
+ :data_source | 'ruby' | 'Ruby'
+ :introduced_by_url | 'http://test.com' | '[Introduced by](http://test.com)'
+ :tier | %w(gold premium) | 'gold, premium'
+ :distribution | %w(ce ee) | 'ce, ee'
+ :key_path | 'key.path' | '**`key.path`**'
+ :milestone | '13.4' | '13.4'
+ :status | 'data_available' | 'data_available'
+ end
+
+ with_them do
+ subject { described_class.format(key, value) }
+
+ it { is_expected.to eq(expected_value) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb
index e101f837324..8b592838f5d 100644
--- a/spec/lib/gitlab/usage/metric_definition_spec.rb
+++ b/spec/lib/gitlab/usage/metric_definition_spec.rb
@@ -5,18 +5,14 @@ require 'spec_helper'
RSpec.describe Gitlab::Usage::MetricDefinition do
let(:attributes) do
{
- name: 'uuid',
description: 'GitLab instance unique identifier',
value_type: 'string',
product_category: 'collection',
- stage: 'growth',
+ product_stage: 'growth',
status: 'data_available',
default_generation: 'generation_1',
- full_path: {
- generation_1: 'uuid',
- generation_2: 'license.uuid'
- },
- group: 'group::product analytics',
+ key_path: 'uuid',
+ product_group: 'group::product analytics',
time_frame: 'none',
data_source: 'database',
distribution: %w(ee ce),
@@ -44,13 +40,12 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
using RSpec::Parameterized::TableSyntax
where(:attribute, :value) do
- :name | nil
:description | nil
:value_type | nil
:value_type | 'test'
:status | nil
- :default_generation | nil
- :group | nil
+ :key_path | nil
+ :product_group | nil
:time_frame | nil
:time_frame | '29d'
:data_source | 'other'
@@ -70,6 +65,20 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
described_class.new(path, attributes).validate!
end
+
+ context 'with skip_validation' do
+ it 'raise exception if skip_validation: false' do
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).at_least(:once).with(instance_of(Gitlab::Usage::Metric::InvalidMetricError))
+
+ described_class.new(path, attributes.merge( { skip_validation: false } )).validate!
+ end
+
+ it 'does not raise exception if has skip_validation: true' do
+ expect(Gitlab::ErrorTracking).not_to receive(:track_and_raise_for_dev_exception)
+
+ described_class.new(path, attributes.merge( { skip_validation: true } )).validate!
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/usage/metric_spec.rb b/spec/lib/gitlab/usage/metric_spec.rb
index 40671d980d6..d4a789419a4 100644
--- a/spec/lib/gitlab/usage/metric_spec.rb
+++ b/spec/lib/gitlab/usage/metric_spec.rb
@@ -4,15 +4,15 @@ require 'spec_helper'
RSpec.describe Gitlab::Usage::Metric do
describe '#definition' do
- it 'returns generation_1 metric definiton' do
- expect(described_class.new(default_generation_path: 'uuid').definition).to be_an(Gitlab::Usage::MetricDefinition)
+ it 'returns key_path metric definiton' do
+ expect(described_class.new(key_path: 'uuid').definition).to be_an(Gitlab::Usage::MetricDefinition)
end
end
describe '#unflatten_default_path' do
using RSpec::Parameterized::TableSyntax
- where(:default_generation_path, :value, :expected_hash) do
+ where(:key_path, :value, :expected_hash) do
'uuid' | nil | { uuid: nil }
'uuid' | '1111' | { uuid: '1111' }
'counts.issues' | nil | { counts: { issues: nil } }
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::Usage::Metric do
end
with_them do
- subject { described_class.new(default_generation_path: default_generation_path, value: value).unflatten_default_path }
+ subject { described_class.new(key_path: key_path, value: value).unflatten_key_path }
it { is_expected.to eq(expected_hash) }
end
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
new file mode 100644
index 00000000000..5469ded18f9
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb
@@ -0,0 +1,281 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redis_shared_state do
+ let(:entity1) { 'dfb9d2d2-f56c-4c77-8aeb-6cddc4a1f857' }
+ let(:entity2) { '1dd9afb2-a3ee-4de1-8ae3-a405579c8584' }
+ let(:entity3) { '34rfjuuy-ce56-sa35-ds34-dfer567dfrf2' }
+ let(:entity4) { '8b9a2671-2abf-4bec-a682-22f6a8f7bf31' }
+ let(:end_date) { Date.current }
+ let(:sources) { Gitlab::Usage::Metrics::Aggregates::Sources }
+
+ let_it_be(:recorded_at) { Time.current.to_i }
+
+ context 'aggregated_metrics_data' do
+ shared_examples 'aggregated_metrics_data' do
+ context 'no aggregated metric is defined' do
+ it 'returns empty hash' do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics).and_return([])
+ end
+
+ expect(aggregated_metrics_data).to eq({})
+ end
+ end
+
+ context 'there are aggregated metrics defined' do
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics).and_return(aggregated_metrics)
+ end
+ end
+
+ context 'with disabled database_sourced_aggregated_metrics feature flag' do
+ before do
+ stub_feature_flags(database_sourced_aggregated_metrics: false)
+ end
+
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_1', source: 'redis', events: %w[event3 event5], operator: "OR" },
+ { name: 'gmau_2', source: 'database', events: %w[event1 event2 event3], operator: "OR" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'skips database sourced metrics', :aggregate_failures do
+ results = {
+ 'gmau_1' => 5
+ }
+
+ params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at }
+
+ expect(sources::RedisHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event3 event5])).and_return(5)
+ expect(sources::PostgresHll).not_to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3]))
+ expect(aggregated_metrics_data).to eq(results)
+ end
+ end
+
+ context 'with AND operator' do
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_1', source: 'redis', events: %w[event3 event5], operator: "AND" },
+ { name: 'gmau_2', source: 'database', events: %w[event1 event2 event3], operator: "AND" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'returns the number of unique events recorded for every metric in aggregate', :aggregate_failures do
+ results = {
+ 'gmau_1' => 2,
+ 'gmau_2' => 1
+ }
+ params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at }
+
+ # gmau_1 data is as follow
+ # |A| => 4
+ expect(sources::RedisHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event3')).and_return(4)
+ # |B| => 6
+ expect(sources::RedisHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event5')).and_return(6)
+ # |A + B| => 8
+ expect(sources::RedisHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event3 event5])).and_return(8)
+ # Exclusion inclusion principle formula to calculate intersection of 2 sets
+ # |A & B| = (|A| + |B|) - |A + B| => (4 + 6) - 8 => 2
+
+ # gmau_2 data is as follow:
+ # |A| => 2
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event1')).and_return(2)
+ # |B| => 3
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event2')).and_return(3)
+ # |C| => 5
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event3')).and_return(5)
+
+ # |A + B| => 4 therefore |A & B| = (|A| + |B|) - |A + B| => 2 + 3 - 4 => 1
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2])).and_return(4)
+ # |A + C| => 6 therefore |A & C| = (|A| + |C|) - |A + C| => 2 + 5 - 6 => 1
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event3])).and_return(6)
+ # |B + C| => 7 therefore |B & C| = (|B| + |C|) - |B + C| => 3 + 5 - 7 => 1
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event2 event3])).and_return(7)
+ # |A + B + C| => 8
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(8)
+ # Exclusion inclusion principle formula to calculate intersection of 3 sets
+ # |A & B & C| = (|A & B| + |A & C| + |B & C|) - (|A| + |B| + |C|) + |A + B + C|
+ # (1 + 1 + 1) - (2 + 3 + 5) + 8 => 1
+
+ expect(aggregated_metrics_data).to eq(results)
+ end
+ end
+
+ context 'with OR operator' do
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_1', source: 'redis', events: %w[event3 event5], operator: "OR" },
+ { name: 'gmau_2', source: 'database', events: %w[event1 event2 event3], operator: "OR" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'returns the number of unique events occurred for any metric in aggregate', :aggregate_failures do
+ results = {
+ 'gmau_1' => 5,
+ 'gmau_2' => 3
+ }
+ params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at }
+
+ expect(sources::RedisHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event3 event5])).and_return(5)
+ expect(sources::PostgresHll).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(3)
+ expect(aggregated_metrics_data).to eq(results)
+ end
+ end
+
+ context 'hidden behind feature flag' do
+ let(:enabled_feature_flag) { 'test_ff_enabled' }
+ let(:disabled_feature_flag) { 'test_ff_disabled' }
+ let(:aggregated_metrics) do
+ [
+ # represents stable aggregated metrics that has been fully released
+ { name: 'gmau_without_ff', source: 'redis', events: %w[event3_slot event5_slot], operator: "OR" },
+ # represents new aggregated metric that is under performance testing on gitlab.com
+ { name: 'gmau_enabled', source: 'redis', events: %w[event4], operator: "OR", feature_flag: enabled_feature_flag },
+ # represents aggregated metric that is under development and shouldn't be yet collected even on gitlab.com
+ { name: 'gmau_disabled', source: 'redis', events: %w[event4], operator: "OR", feature_flag: disabled_feature_flag }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'does not calculate data for aggregates with ff turned off' do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+ stub_feature_flags(enabled_feature_flag => true, disabled_feature_flag => false)
+ allow(sources::RedisHll).to receive(:calculate_metrics_union).and_return(6)
+
+ expect(aggregated_metrics_data).to eq('gmau_without_ff' => 6, 'gmau_enabled' => 6)
+ end
+ end
+ end
+
+ context 'error handling' do
+ context 'development and test environment' do
+ it 'raises error when unknown aggregation operator is used' do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics)
+ .and_return([{ name: 'gmau_1', source: 'redis', events: %w[event1_slot], operator: "SUM" }])
+ end
+
+ expect { aggregated_metrics_data }.to raise_error Gitlab::Usage::Metrics::Aggregates::UnknownAggregationOperator
+ end
+
+ it 'raises error when unknown aggregation source is used' do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics)
+ .and_return([{ name: 'gmau_1', source: 'whoami', events: %w[event1_slot], operator: "AND" }])
+ end
+
+ expect { aggregated_metrics_data }.to raise_error Gitlab::Usage::Metrics::Aggregates::UnknownAggregationSource
+ end
+
+ it 're raises Gitlab::UsageDataCounters::HLLRedisCounter::EventError' do
+ error = Gitlab::UsageDataCounters::HLLRedisCounter::EventError
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:calculate_events_union).and_raise(error)
+
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics)
+ .and_return([{ name: 'gmau_1', source: 'redis', events: %w[event1_slot], operator: "OR" }])
+ end
+
+ expect { aggregated_metrics_data }.to raise_error error
+ end
+ end
+
+ context 'production' do
+ before do
+ stub_rails_env('production')
+ end
+
+ it 'rescues unknown aggregation operator error' do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics)
+ .and_return([{ name: 'gmau_1', source: 'redis', events: %w[event1_slot], operator: "SUM" }])
+ end
+
+ expect(aggregated_metrics_data).to eq('gmau_1' => -1)
+ end
+
+ it 'rescues unknown aggregation source error' do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics)
+ .and_return([{ name: 'gmau_1', source: 'whoami', events: %w[event1_slot], operator: "AND" }])
+ end
+
+ expect(aggregated_metrics_data).to eq('gmau_1' => -1)
+ end
+
+ it 'rescues Gitlab::UsageDataCounters::HLLRedisCounter::EventError' do
+ error = Gitlab::UsageDataCounters::HLLRedisCounter::EventError
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:calculate_events_union).and_raise(error)
+
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics)
+ .and_return([{ name: 'gmau_1', source: 'redis', events: %w[event1_slot], operator: "OR" }])
+ end
+
+ expect(aggregated_metrics_data).to eq('gmau_1' => -1)
+ end
+ end
+ end
+ end
+
+ it 'allows for YAML aliases in aggregated metrics configs' do
+ expect(YAML).to receive(:safe_load).with(kind_of(String), aliases: true)
+
+ described_class.new(recorded_at)
+ end
+
+ describe '.aggregated_metrics_weekly_data' do
+ subject(:aggregated_metrics_data) { described_class.new(recorded_at).weekly_data }
+
+ let(:start_date) { 7.days.ago.to_date }
+
+ it_behaves_like 'aggregated_metrics_data'
+ end
+
+ describe '.aggregated_metrics_monthly_data' do
+ subject(:aggregated_metrics_data) { described_class.new(recorded_at).monthly_data }
+
+ let(:start_date) { 4.weeks.ago.to_date }
+
+ it_behaves_like 'aggregated_metrics_data'
+
+ context 'metrics union calls' do
+ let(:aggregated_metrics) do
+ [
+ { name: 'gmau_3', source: 'redis', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "AND" }
+ ].map(&:with_indifferent_access)
+ end
+
+ it 'caches intermediate operations', :aggregate_failures do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:aggregated_metrics).and_return(aggregated_metrics)
+ end
+
+ params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at }
+
+ aggregated_metrics[0][:events].each do |event|
+ expect(sources::RedisHll).to receive(:calculate_metrics_union)
+ .with(params.merge(metric_names: event))
+ .once
+ .and_return(0)
+ end
+
+ 2.upto(4) do |subset_size|
+ aggregated_metrics[0][:events].combination(subset_size).each do |events|
+ expect(sources::RedisHll).to receive(:calculate_metrics_union)
+ .with(params.merge(metric_names: events))
+ .once
+ .and_return(0)
+ end
+ end
+
+ aggregated_metrics_data
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb
new file mode 100644
index 00000000000..7b8be8e8bc6
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb
@@ -0,0 +1,146 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_gitlab_redis_shared_state do
+ let_it_be(:start_date) { 7.days.ago }
+ let_it_be(:end_date) { Date.current }
+ let_it_be(:recorded_at) { Time.current }
+ let_it_be(:time_period) { { created_at: (start_date..end_date) } }
+ let(:metric_1) { 'metric_1' }
+ let(:metric_2) { 'metric_2' }
+ let(:metric_names) { [metric_1, metric_2] }
+
+ describe '.calculate_events_union' do
+ subject(:calculate_metrics_union) do
+ described_class.calculate_metrics_union(metric_names: metric_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at)
+ end
+
+ before do
+ [
+ {
+ metric_name: metric_1,
+ time_period: time_period,
+ recorded_at_timestamp: recorded_at,
+ data: ::Gitlab::Database::PostgresHll::Buckets.new(141 => 1, 56 => 1)
+ },
+ {
+ metric_name: metric_2,
+ time_period: time_period,
+ recorded_at_timestamp: recorded_at,
+ data: ::Gitlab::Database::PostgresHll::Buckets.new(10 => 1, 56 => 1)
+ }
+ ].each do |params|
+ described_class.save_aggregated_metrics(**params)
+ end
+ end
+
+ it 'returns the number of unique events in the union of all metrics' do
+ expect(calculate_metrics_union.round(2)).to eq(3.12)
+ end
+
+ context 'when there is no aggregated data saved' do
+ let(:metric_names) { [metric_1, 'i do not have any records'] }
+
+ it 'raises error when union data is missing' do
+ expect { calculate_metrics_union }.to raise_error Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable
+ end
+ end
+
+ context 'when there is only one metric defined as aggregated' do
+ let(:metric_names) { [metric_1] }
+
+ it 'returns the number of unique events for that metric' do
+ expect(calculate_metrics_union.round(2)).to eq(2.08)
+ end
+ end
+ end
+
+ describe '.save_aggregated_metrics' do
+ subject(:save_aggregated_metrics) do
+ described_class.save_aggregated_metrics(metric_name: metric_1,
+ time_period: time_period,
+ recorded_at_timestamp: recorded_at,
+ data: data)
+ end
+
+ context 'with compatible data argument' do
+ let(:data) { ::Gitlab::Database::PostgresHll::Buckets.new(141 => 1, 56 => 1) }
+
+ it 'persists serialized data in Redis' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).to receive(:set).with("#{metric_1}_weekly-#{recorded_at.to_i}", '{"141":1,"56":1}', ex: 120.hours)
+ end
+
+ save_aggregated_metrics
+ end
+
+ context 'with monthly key' do
+ let_it_be(:start_date) { 4.weeks.ago }
+ let_it_be(:time_period) { { created_at: (start_date..end_date) } }
+
+ it 'persists serialized data in Redis' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).to receive(:set).with("#{metric_1}_monthly-#{recorded_at.to_i}", '{"141":1,"56":1}', ex: 120.hours)
+ end
+
+ save_aggregated_metrics
+ end
+ end
+
+ context 'with all_time key' do
+ let_it_be(:time_period) { nil }
+
+ it 'persists serialized data in Redis' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).to receive(:set).with("#{metric_1}_all_time-#{recorded_at.to_i}", '{"141":1,"56":1}', ex: 120.hours)
+ end
+
+ save_aggregated_metrics
+ end
+ end
+
+ context 'error handling' do
+ before do
+ allow(Gitlab::Redis::SharedState).to receive(:with).and_raise(::Redis::CommandError)
+ end
+
+ it 'rescues and reraise ::Redis::CommandError for development and test environments' do
+ expect { save_aggregated_metrics }.to raise_error ::Redis::CommandError
+ end
+
+ context 'for environment different than development' do
+ before do
+ stub_rails_env('production')
+ end
+
+ it 'rescues ::Redis::CommandError' do
+ expect { save_aggregated_metrics }.not_to raise_error
+ end
+ end
+ end
+ end
+
+ context 'with incompatible data argument' do
+ let(:data) { 1 }
+
+ context 'for environment different than development' do
+ before do
+ stub_rails_env('production')
+ end
+
+ it 'does not persist data in Redis' do
+ Gitlab::Redis::SharedState.with do |redis|
+ expect(redis).not_to receive(:set)
+ end
+
+ save_aggregated_metrics
+ end
+ end
+
+ it 'raises error for development environment' do
+ expect { save_aggregated_metrics }.to raise_error /Unsupported data type/
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb
new file mode 100644
index 00000000000..af2de5ea343
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::RedisHll do
+ describe '.calculate_events_union' do
+ let(:event_names) { %w[event_a event_b] }
+ let(:start_date) { 7.days.ago }
+ let(:end_date) { Date.current }
+
+ subject(:calculate_metrics_union) do
+ described_class.calculate_metrics_union(metric_names: event_names, start_date: start_date, end_date: end_date, recorded_at: nil)
+ end
+
+ it 'calls Gitlab::UsageDataCounters::HLLRedisCounter.calculate_events_union' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:calculate_events_union)
+ .with(event_names: event_names, start_date: start_date, end_date: end_date)
+ .and_return(5)
+
+ calculate_metrics_union
+ end
+
+ it 'prevents from using fallback value as valid union result' do
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:calculate_events_union).and_return(-1)
+
+ expect { calculate_metrics_union }.to raise_error Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb b/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb
index c0deb2aa00c..58f974fbe12 100644
--- a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb
@@ -13,18 +13,32 @@ RSpec.describe 'aggregated metrics' do
end
end
+ RSpec::Matchers.define :has_known_source do
+ match do |aggregate|
+ Gitlab::Usage::Metrics::Aggregates::SOURCES.include?(aggregate[:source])
+ end
+
+ failure_message do |aggregate|
+ "Aggregate with name: `#{aggregate[:name]}` uses not allowed source `#{aggregate[:source]}`"
+ end
+ end
+
let_it_be(:known_events) do
Gitlab::UsageDataCounters::HLLRedisCounter.known_events
end
- Gitlab::UsageDataCounters::HLLRedisCounter.aggregated_metrics.tap do |aggregated_metrics|
+ Gitlab::Usage::Metrics::Aggregates::Aggregate.new(Time.current).send(:aggregated_metrics).tap do |aggregated_metrics|
it 'all events has unique name' do
event_names = aggregated_metrics&.map { |event| event[:name] }
expect(event_names).to eq(event_names&.uniq)
end
- aggregated_metrics&.each do |aggregate|
+ it 'all aggregated metrics has known source' do
+ expect(aggregated_metrics).to all has_known_source
+ end
+
+ aggregated_metrics&.select { |agg| agg[:source] == Gitlab::Usage::Metrics::Aggregates::REDIS_SOURCE }&.each do |aggregate|
context "for #{aggregate[:name]} aggregate of #{aggregate[:events].join(' ')}" do
let_it_be(:events_records) { known_events.select { |event| aggregate[:events].include?(event[:name]) } }
@@ -37,7 +51,7 @@ RSpec.describe 'aggregated metrics' do
end
it "uses allowed aggregation operators" do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter::ALLOWED_METRICS_AGGREGATIONS).to include aggregate[:operator]
+ expect(Gitlab::Usage::Metrics::Aggregates::ALLOWED_METRICS_AGGREGATIONS).to include aggregate[:operator]
end
it "uses events from the same Redis slot" do
diff --git a/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
index ba7bfe47bc9..b1d5d106082 100644
--- a/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb
@@ -3,28 +3,88 @@
require 'spec_helper'
RSpec.describe Gitlab::UsageDataCounters::CiTemplateUniqueCounter do
- let(:project_id) { 1 }
-
describe '.track_unique_project_event' do
- described_class::TEMPLATE_TO_EVENT.keys.each do |template|
- context "when given template #{template}" do
- it_behaves_like 'tracking unique hll events', :usage_data_track_ci_templates_unique_projects do
- subject(:request) { described_class.track_unique_project_event(project_id: project_id, template: template) }
+ using RSpec::Parameterized::TableSyntax
+
+ where(:template, :config_source, :expected_event) do
+ # Implicit Auto DevOps usage
+ 'Auto-DevOps.gitlab-ci.yml' | :auto_devops_source | 'p_ci_templates_implicit_auto_devops'
+ 'Jobs/Build.gitlab-ci.yml' | :auto_devops_source | 'p_ci_templates_implicit_auto_devops_build'
+ 'Jobs/Deploy.gitlab-ci.yml' | :auto_devops_source | 'p_ci_templates_implicit_auto_devops_deploy'
+ 'Security/SAST.gitlab-ci.yml' | :auto_devops_source | 'p_ci_templates_implicit_security_sast'
+ 'Security/Secret-Detection.gitlab-ci.yml' | :auto_devops_source | 'p_ci_templates_implicit_security_secret_detection'
+ # Explicit include:template usage
+ '5-Minute-Production-App.gitlab-ci.yml' | :repository_source | 'p_ci_templates_5_min_production_app'
+ 'Auto-DevOps.gitlab-ci.yml' | :repository_source | 'p_ci_templates_auto_devops'
+ 'AWS/CF-Provision-and-Deploy-EC2.gitlab-ci.yml' | :repository_source | 'p_ci_templates_aws_cf_deploy_ec2'
+ 'AWS/Deploy-ECS.gitlab-ci.yml' | :repository_source | 'p_ci_templates_aws_deploy_ecs'
+ 'Jobs/Build.gitlab-ci.yml' | :repository_source | 'p_ci_templates_auto_devops_build'
+ 'Jobs/Deploy.gitlab-ci.yml' | :repository_source | 'p_ci_templates_auto_devops_deploy'
+ 'Jobs/Deploy.latest.gitlab-ci.yml' | :repository_source | 'p_ci_templates_auto_devops_deploy_latest'
+ 'Security/SAST.gitlab-ci.yml' | :repository_source | 'p_ci_templates_security_sast'
+ 'Security/Secret-Detection.gitlab-ci.yml' | :repository_source | 'p_ci_templates_security_secret_detection'
+ 'Terraform/Base.latest.gitlab-ci.yml' | :repository_source | 'p_ci_templates_terraform_base_latest'
+ end
+
+ with_them do
+ it_behaves_like 'tracking unique hll events' do
+ subject(:request) { described_class.track_unique_project_event(project_id: project_id, template: template, config_source: config_source) }
+
+ let(:project_id) { 1 }
+ let(:target_id) { expected_event }
+ let(:expected_type) { instance_of(Integer) }
+ end
+ end
+
+ context 'known_events coverage tests' do
+ let(:project_id) { 1 }
+ let(:config_source) { :repository_source }
- let(:target_id) { "p_ci_templates_#{described_class::TEMPLATE_TO_EVENT[template]}" }
- let(:expected_type) { instance_of(Integer) }
+ # These tests help guard against missing "explicit" events in known_events/ci_templates.yml
+ context 'explicit include:template events' do
+ described_class::TEMPLATE_TO_EVENT.keys.each do |template|
+ it "does not raise error for #{template}" do
+ expect do
+ described_class.track_unique_project_event(project_id: project_id, template: template, config_source: config_source)
+ end.not_to raise_error
+ end
+ end
+ end
+
+ # This test is to help guard against missing "implicit" events in known_events/ci_templates.yml
+ it 'does not raise error for any template in an implicit Auto DevOps pipeline' do
+ project = create(:project, :auto_devops)
+ pipeline = double(project: project)
+ command = double
+ result = Gitlab::Ci::YamlProcessor.new(
+ Gitlab::Ci::Pipeline::Chain::Config::Content::AutoDevops.new(pipeline, command).content,
+ project: project,
+ user: double,
+ sha: double
+ ).execute
+
+ config_source = :auto_devops_source
+
+ result.included_templates.each do |template|
+ expect do
+ described_class.track_unique_project_event(project_id: project.id, template: template, config_source: config_source)
+ end.not_to raise_error
end
end
end
- it 'does not track templates outside of TEMPLATE_TO_EVENT' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to(
- receive(:track_event)
- )
+ context 'templates outside of TEMPLATE_TO_EVENT' do
+ let(:project_id) { 1 }
+ let(:config_source) { :repository_source }
+
Dir.glob(File.join('lib', 'gitlab', 'ci', 'templates', '**'), base: Rails.root) do |template|
next if described_class::TEMPLATE_TO_EVENT.key?(template)
- described_class.track_unique_project_event(project_id: 1, template: template)
+ it "does not track #{template}" do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to(receive(:track_event))
+
+ described_class.track_unique_project_event(project_id: project_id, template: template, config_source: config_source)
+ 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 b8eddc0ca7f..b4894ec049f 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
@@ -27,6 +27,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'deploy_token_packages',
'user_packages',
'compliance',
+ 'ecosystem',
'analytics',
'ide_edit',
'search',
@@ -39,12 +40,16 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'snippets',
'code_review',
'terraform',
- 'ci_templates'
+ 'ci_templates',
+ 'quickactions',
+ 'pipeline_authoring'
)
end
end
describe 'known_events' do
+ let(:feature) { 'test_hll_redis_counter_ff_check' }
+
let(:weekly_event) { 'g_analytics_contribution' }
let(:daily_event) { 'g_analytics_search' }
let(:analytics_slot_event) { 'g_analytics_contribution' }
@@ -64,7 +69,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
let(:known_events) do
[
- { name: weekly_event, redis_slot: "analytics", category: analytics_category, expiry: 84, aggregation: "weekly" },
+ { name: weekly_event, redis_slot: "analytics", category: analytics_category, expiry: 84, aggregation: "weekly", feature_flag: feature },
{ name: daily_event, redis_slot: "analytics", category: analytics_category, expiry: 84, aggregation: "daily" },
{ name: category_productivity_event, redis_slot: "analytics", category: productivity_category, aggregation: "weekly" },
{ name: compliance_slot_event, redis_slot: "compliance", category: compliance_category, aggregation: "weekly" },
@@ -75,6 +80,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
before do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
allow(described_class).to receive(:known_events).and_return(known_events)
end
@@ -85,6 +92,32 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
describe '.track_event' do
+ context 'with feature flag set' do
+ it 'tracks the event when feature enabled' do
+ stub_feature_flags(feature => true)
+
+ expect(Gitlab::Redis::HLL).to receive(:add)
+
+ described_class.track_event(weekly_event, values: 1)
+ end
+
+ it 'does not track the event with feature flag disabled' do
+ stub_feature_flags(feature => false)
+
+ expect(Gitlab::Redis::HLL).not_to receive(:add)
+
+ described_class.track_event(weekly_event, values: 1)
+ end
+ end
+
+ context 'with no feature flag set' do
+ it 'tracks the event' do
+ expect(Gitlab::Redis::HLL).to receive(:add)
+
+ described_class.track_event(daily_event, values: 1)
+ end
+ end
+
context 'when usage_ping is disabled' do
it 'does not track the event' do
stub_application_setting(usage_ping_enabled: false)
@@ -425,182 +458,59 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
end
- context 'aggregated_metrics_data' do
+ describe '.calculate_events_union' do
+ let(:time_range) { { start_date: 7.days.ago, end_date: DateTime.current } }
let(:known_events) do
[
{ name: 'event1_slot', redis_slot: "slot", category: 'category1', aggregation: "weekly" },
{ name: 'event2_slot', redis_slot: "slot", category: 'category2', aggregation: "weekly" },
{ name: 'event3_slot', redis_slot: "slot", category: 'category3', aggregation: "weekly" },
- { name: 'event5_slot', redis_slot: "slot", category: 'category4', aggregation: "weekly" },
+ { name: 'event5_slot', redis_slot: "slot", category: 'category4', aggregation: "daily" },
{ name: 'event4', category: 'category2', aggregation: "weekly" }
].map(&:with_indifferent_access)
end
before do
allow(described_class).to receive(:known_events).and_return(known_events)
- end
-
- shared_examples 'aggregated_metrics_data' do
- context 'no aggregated metrics is defined' do
- it 'returns empty hash' do
- allow(described_class).to receive(:aggregated_metrics).and_return([])
-
- expect(aggregated_metrics_data).to eq({})
- end
- end
-
- context 'there are aggregated metrics defined' do
- before do
- allow(described_class).to receive(:aggregated_metrics).and_return(aggregated_metrics)
- end
-
- context 'with AND operator' do
- let(:aggregated_metrics) do
- [
- { name: 'gmau_1', events: %w[event1_slot event2_slot], operator: "AND" },
- { name: 'gmau_2', events: %w[event1_slot event2_slot event3_slot], operator: "AND" },
- { name: 'gmau_3', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "AND" },
- { name: 'gmau_4', events: %w[event4], operator: "AND" }
- ].map(&:with_indifferent_access)
- end
-
- it 'returns the number of unique events for all known events' do
- results = {
- 'gmau_1' => 3,
- 'gmau_2' => 2,
- 'gmau_3' => 1,
- 'gmau_4' => 3
- }
-
- expect(aggregated_metrics_data).to eq(results)
- end
- end
-
- context 'with OR operator' do
- let(:aggregated_metrics) do
- [
- { name: 'gmau_1', events: %w[event3_slot event5_slot], operator: "OR" },
- { name: 'gmau_2', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "OR" },
- { name: 'gmau_3', events: %w[event4], operator: "OR" }
- ].map(&:with_indifferent_access)
- end
- it 'returns the number of unique events for all known events' do
- results = {
- 'gmau_1' => 2,
- 'gmau_2' => 3,
- 'gmau_3' => 3
- }
-
- expect(aggregated_metrics_data).to eq(results)
- end
- end
-
- context 'hidden behind feature flag' do
- let(:enabled_feature_flag) { 'test_ff_enabled' }
- let(:disabled_feature_flag) { 'test_ff_disabled' }
- let(:aggregated_metrics) do
- [
- # represents stable aggregated metrics that has been fully released
- { name: 'gmau_without_ff', events: %w[event3_slot event5_slot], operator: "OR" },
- # represents new aggregated metric that is under performance testing on gitlab.com
- { name: 'gmau_enabled', events: %w[event4], operator: "AND", feature_flag: enabled_feature_flag },
- # represents aggregated metric that is under development and shouldn't be yet collected even on gitlab.com
- { name: 'gmau_disabled', events: %w[event4], operator: "AND", feature_flag: disabled_feature_flag }
- ].map(&:with_indifferent_access)
- end
-
- it 'returns the number of unique events for all known events' do
- skip_feature_flags_yaml_validation
- stub_feature_flags(enabled_feature_flag => true, disabled_feature_flag => false)
+ described_class.track_event('event1_slot', values: entity1, time: 2.days.ago)
+ described_class.track_event('event1_slot', values: entity2, time: 2.days.ago)
+ described_class.track_event('event1_slot', values: entity3, time: 2.days.ago)
+ described_class.track_event('event2_slot', values: entity1, time: 2.days.ago)
+ described_class.track_event('event2_slot', values: entity2, time: 3.days.ago)
+ described_class.track_event('event2_slot', values: entity3, time: 3.days.ago)
+ described_class.track_event('event3_slot', values: entity1, time: 3.days.ago)
+ described_class.track_event('event3_slot', values: entity2, time: 3.days.ago)
+ described_class.track_event('event5_slot', values: entity2, time: 3.days.ago)
+
+ # events out of time scope
+ described_class.track_event('event2_slot', values: entity4, time: 8.days.ago)
- expect(aggregated_metrics_data).to eq('gmau_without_ff' => 2, 'gmau_enabled' => 3)
- end
- end
- end
+ # events in different slots
+ described_class.track_event('event4', values: entity1, time: 2.days.ago)
+ described_class.track_event('event4', values: entity2, time: 2.days.ago)
end
- describe '.aggregated_metrics_weekly_data' do
- subject(:aggregated_metrics_data) { described_class.aggregated_metrics_weekly_data }
-
- before do
- described_class.track_event('event1_slot', values: entity1, time: 2.days.ago)
- described_class.track_event('event1_slot', values: entity2, time: 2.days.ago)
- described_class.track_event('event1_slot', values: entity3, time: 2.days.ago)
- described_class.track_event('event2_slot', values: entity1, time: 2.days.ago)
- described_class.track_event('event2_slot', values: entity2, time: 3.days.ago)
- described_class.track_event('event2_slot', values: entity3, time: 3.days.ago)
- described_class.track_event('event3_slot', values: entity1, time: 3.days.ago)
- described_class.track_event('event3_slot', values: entity2, time: 3.days.ago)
- described_class.track_event('event5_slot', values: entity2, time: 3.days.ago)
-
- # events out of time scope
- described_class.track_event('event2_slot', values: entity3, time: 8.days.ago)
-
- # events in different slots
- described_class.track_event('event4', values: entity1, time: 2.days.ago)
- described_class.track_event('event4', values: entity2, time: 2.days.ago)
- described_class.track_event('event4', values: entity4, time: 2.days.ago)
- end
-
- it_behaves_like 'aggregated_metrics_data'
+ it 'calculates union of given events', :aggregate_failure do
+ expect(described_class.calculate_events_union(**time_range.merge(event_names: %w[event4]))).to eq 2
+ expect(described_class.calculate_events_union(**time_range.merge(event_names: %w[event1_slot event2_slot event3_slot]))).to eq 3
end
- describe '.aggregated_metrics_monthly_data' do
- subject(:aggregated_metrics_data) { described_class.aggregated_metrics_monthly_data }
-
- it_behaves_like 'aggregated_metrics_data' do
- before do
- described_class.track_event('event1_slot', values: entity1, time: 2.days.ago)
- described_class.track_event('event1_slot', values: entity2, time: 2.days.ago)
- described_class.track_event('event1_slot', values: entity3, time: 2.days.ago)
- described_class.track_event('event2_slot', values: entity1, time: 2.days.ago)
- described_class.track_event('event2_slot', values: entity2, time: 3.days.ago)
- described_class.track_event('event2_slot', values: entity3, time: 3.days.ago)
- described_class.track_event('event3_slot', values: entity1, time: 3.days.ago)
- described_class.track_event('event3_slot', values: entity2, time: 10.days.ago)
- described_class.track_event('event5_slot', values: entity2, time: 4.weeks.ago.advance(days: 1))
-
- # events out of time scope
- described_class.track_event('event5_slot', values: entity1, time: 4.weeks.ago.advance(days: -1))
-
- # events in different slots
- described_class.track_event('event4', values: entity1, time: 2.days.ago)
- described_class.track_event('event4', values: entity2, time: 2.days.ago)
- described_class.track_event('event4', values: entity4, time: 2.days.ago)
- end
- end
-
- context 'Redis calls' do
- let(:aggregated_metrics) do
- [
- { name: 'gmau_3', events: %w[event1_slot event2_slot event3_slot event5_slot], operator: "AND" }
- ].map(&:with_indifferent_access)
- end
-
- let(:known_events) do
- [
- { name: 'event1_slot', redis_slot: "slot", category: 'category1', aggregation: "weekly" },
- { name: 'event2_slot', redis_slot: "slot", category: 'category2', aggregation: "weekly" },
- { name: 'event3_slot', redis_slot: "slot", category: 'category3', aggregation: "weekly" },
- { name: 'event5_slot', redis_slot: "slot", category: 'category4', aggregation: "weekly" }
- ].map(&:with_indifferent_access)
- end
-
- it 'caches intermediate operations' do
- allow(described_class).to receive(:known_events).and_return(known_events)
- allow(described_class).to receive(:aggregated_metrics).and_return(aggregated_metrics)
+ it 'validates and raise exception if events has mismatched slot or aggregation', :aggregate_failure do
+ expect { described_class.calculate_events_union(**time_range.merge(event_names: %w[event1_slot event4])) }.to raise_error described_class::SlotMismatch
+ expect { described_class.calculate_events_union(**time_range.merge(event_names: %w[event5_slot event3_slot])) }.to raise_error described_class::AggregationMismatch
+ end
+ end
- 4.downto(1) do |subset_size|
- known_events.combination(subset_size).each do |events|
- keys = described_class.send(:weekly_redis_keys, events: events, start_date: 4.weeks.ago.to_date, end_date: Date.current)
- expect(Gitlab::Redis::HLL).to receive(:count).with(keys: keys).once.and_return(0)
- end
- end
+ describe '.weekly_time_range' do
+ it 'return hash with weekly time range boundaries' do
+ expect(described_class.weekly_time_range).to eq(start_date: 7.days.ago.to_date, end_date: Date.current)
+ end
+ end
- subject
- end
- end
+ describe '.monthly_time_range' do
+ it 'return hash with monthly time range boundaries' do
+ expect(described_class.monthly_time_range).to eq(start_date: 4.weeks.ago.to_date, end_date: Date.current)
end
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
index c7b208cfb31..a604de4a61f 100644
--- a/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb
@@ -73,6 +73,54 @@ RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :cl
end
end
+ describe '.track_approve_mr_action' do
+ subject { described_class.track_approve_mr_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_APPROVE_ACTION }
+ end
+ end
+
+ describe '.track_unapprove_mr_action' do
+ subject { described_class.track_unapprove_mr_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_UNAPPROVE_ACTION }
+ end
+ end
+
+ describe '.track_resolve_thread_action' do
+ subject { described_class.track_resolve_thread_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_RESOLVE_THREAD_ACTION }
+ end
+ end
+
+ describe '.track_unresolve_thread_action' do
+ subject { described_class.track_unresolve_thread_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_UNRESOLVE_THREAD_ACTION }
+ end
+ end
+
+ describe '.track_title_edit_action' do
+ subject { described_class.track_title_edit_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_EDIT_MR_TITLE_ACTION }
+ end
+ end
+
+ describe '.track_description_edit_action' do
+ subject { described_class.track_description_edit_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_EDIT_MR_DESC_ACTION }
+ end
+ end
+
describe '.track_create_comment_action' do
subject { described_class.track_create_comment_action(note: note) }
@@ -148,4 +196,92 @@ RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :cl
let(:action) { described_class::MR_PUBLISH_REVIEW_ACTION }
end
end
+
+ describe '.track_add_suggestion_action' do
+ subject { described_class.track_add_suggestion_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_ADD_SUGGESTION_ACTION }
+ end
+ end
+
+ describe '.track_apply_suggestion_action' do
+ subject { described_class.track_apply_suggestion_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_APPLY_SUGGESTION_ACTION }
+ end
+ end
+
+ describe '.track_users_assigned_to_mr' do
+ subject { described_class.track_users_assigned_to_mr(users: [user]) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_ASSIGNED_USERS_ACTION }
+ end
+ end
+
+ describe '.track_marked_as_draft_action' do
+ subject { described_class.track_marked_as_draft_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_MARKED_AS_DRAFT_ACTION }
+ end
+ end
+
+ describe '.track_unmarked_as_draft_action' do
+ subject { described_class.track_unmarked_as_draft_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_UNMARKED_AS_DRAFT_ACTION }
+ end
+ end
+
+ describe '.track_task_item_status_changed' do
+ subject { described_class.track_task_item_status_changed(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_TASK_ITEM_STATUS_CHANGED_ACTION }
+ end
+ end
+
+ describe '.track_users_review_requested' do
+ subject { described_class.track_users_review_requested(users: [user]) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_REVIEW_REQUESTED_USERS_ACTION }
+ end
+ end
+
+ describe '.track_approval_rule_added_action' do
+ subject { described_class.track_approval_rule_added_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_APPROVAL_RULE_ADDED_USERS_ACTION }
+ end
+ end
+
+ describe '.track_approval_rule_edited_action' do
+ subject { described_class.track_approval_rule_edited_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_APPROVAL_RULE_EDITED_USERS_ACTION }
+ end
+ end
+
+ describe '.track_approval_rule_deleted_action' do
+ subject { described_class.track_approval_rule_deleted_action(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_APPROVAL_RULE_DELETED_USERS_ACTION }
+ end
+ end
+
+ describe '.track_mr_create_from_issue' do
+ subject { described_class.track_mr_create_from_issue(user: user) }
+
+ it_behaves_like 'a tracked merge request unique event' do
+ let(:action) { described_class::MR_CREATE_FROM_ISSUE_ACTION }
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb
new file mode 100644
index 00000000000..d4c423f57fe
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb
@@ -0,0 +1,163 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter, :clean_gitlab_redis_shared_state do
+ let(:user) { build(:user, id: 1) }
+ let(:note) { build(:note, author: user) }
+ let(:args) { nil }
+
+ shared_examples_for 'a tracked quick action unique event' do
+ specify do
+ expect { 3.times { subject } }
+ .to change {
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
+ event_names: action,
+ start_date: 2.weeks.ago,
+ end_date: 2.weeks.from_now
+ )
+ }
+ .by(1)
+ end
+ end
+
+ subject { described_class.track_unique_action(quickaction_name, args: args, user: user) }
+
+ describe '.track_unique_action' do
+ let(:quickaction_name) { 'approve' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_approve' }
+ end
+ end
+
+ context 'tracking assigns' do
+ let(:quickaction_name) { 'assign' }
+
+ context 'single assignee' do
+ let(:args) { '@one' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_assign_single' }
+ end
+ end
+
+ context 'multiple assignees' do
+ let(:args) { '@one @two' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_assign_multiple' }
+ end
+ end
+
+ context 'assigning "me"' do
+ let(:args) { 'me' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_assign_self' }
+ end
+ end
+
+ context 'assigning a reviewer' do
+ let(:quickaction_name) { 'assign_reviewer' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_assign_reviewer' }
+ end
+ end
+
+ context 'assigning a reviewer with request review alias' do
+ let(:quickaction_name) { 'request_review' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_assign_reviewer' }
+ end
+ end
+ end
+
+ context 'tracking copy_metadata' do
+ let(:quickaction_name) { 'copy_metadata' }
+
+ context 'for issues' do
+ let(:args) { '#123' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_copy_metadata_issue' }
+ end
+ end
+
+ context 'for merge requests' do
+ let(:args) { '!123' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_copy_metadata_merge_request' }
+ end
+ end
+ end
+
+ context 'tracking spend' do
+ let(:quickaction_name) { 'spend' }
+
+ context 'adding time' do
+ let(:args) { '1d' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_spend_add' }
+ end
+ end
+
+ context 'removing time' do
+ let(:args) { '-1d' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_spend_subtract' }
+ end
+ end
+ end
+
+ context 'tracking unassign' do
+ let(:quickaction_name) { 'unassign' }
+
+ context 'unassigning everyone' do
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_unassign_all' }
+ end
+ end
+
+ context 'unassigning specific users' do
+ let(:args) { '@hello' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_unassign_specific' }
+ end
+ end
+ end
+
+ context 'tracking unlabel' do
+ context 'called as unlabel' do
+ let(:quickaction_name) { 'unlabel' }
+
+ context 'removing all labels' do
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_unlabel_all' }
+ end
+ end
+
+ context 'removing specific labels' do
+ let(:args) { '~wow' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_unlabel_specific' }
+ end
+ end
+ end
+
+ context 'called as remove_label' do
+ let(:quickaction_name) { 'remove_label' }
+
+ it_behaves_like 'a tracked quick action unique event' do
+ let(:action) { 'i_quickactions_unlabel_all' }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb
new file mode 100644
index 00000000000..7593d51fe76
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'a tracked vs code unique action' do |event|
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ def count_unique(date_from:, date_to:)
+ 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)' }
+
+ 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
+
+ expect(count_unique(date_from: time - 1.week, date_to: time + 1.week)).to eq(2)
+ end
+ end
+
+ it 'does not track when the user agent is not from vs code' do
+ aggregate_failures do
+ user_agent = { user_agent: 'normal_user_agent' }
+
+ expect(track_action(user: user1, **user_agent)).to be_falsey
+ expect(track_action(user: user1, **user_agent)).to be_falsey
+ expect(track_action(user: user2, **user_agent)).to be_falsey
+
+ expect(count_unique(date_from: time - 1.week, date_to: time + 1.week)).to eq(0)
+ end
+ end
+
+ it 'does not track if user agent is not present' do
+ expect(track_action(user: nil, user_agent: nil)).to be_nil
+ 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/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index fd02521622c..602f6640d72 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -228,11 +228,32 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
)
end
- it 'includes imports usage data' do
+ it 'includes import gmau usage data' do
for_defined_days_back do
user = create(:user)
+ group = create(:group)
+ group.add_owner(user)
+
+ create(:project, import_type: :github, creator_id: user.id)
+ create(:jira_import_state, :finished, project: create(:project, creator_id: user.id))
+ create(:issue_csv_import, user: user)
+ create(:group_import_state, group: group, user: user)
create(:bulk_import, user: user)
+ end
+
+ expect(described_class.usage_activity_by_stage_manage({})).to include(
+ unique_users_all_imports: 10
+ )
+
+ expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ unique_users_all_imports: 5
+ )
+ end
+
+ it 'includes imports usage data' do
+ for_defined_days_back do
+ user = create(:user)
%w(gitlab_project gitlab github bitbucket bitbucket_server gitea git manifest fogbugz phabricator).each do |type|
create(:project, import_type: type, creator_id: user.id)
@@ -242,72 +263,113 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
create(:jira_import_state, :finished, project: jira_project)
create(:issue_csv_import, user: user)
+
+ group = create(:group)
+ group.add_owner(user)
+ create(:group_import_state, group: group, user: user)
+
+ bulk_import = create(:bulk_import, user: user)
+ create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
+ create(:bulk_import_entity, :project_entity, bulk_import: bulk_import)
end
expect(described_class.usage_activity_by_stage_manage({})).to include(
{
bulk_imports: {
- gitlab: 2
+ gitlab_v1: 2,
+ gitlab: Gitlab::UsageData::DEPRECATED_VALUE
},
- projects_imported: {
- total: 2,
- gitlab_project: 2,
- gitlab: 2,
- github: 2,
+ project_imports: {
bitbucket: 2,
bitbucket_server: 2,
- gitea: 2,
git: 2,
+ gitea: 2,
+ github: 2,
+ gitlab: 2,
+ gitlab_migration: 2,
+ gitlab_project: 2,
manifest: 2
},
- issues_imported: {
+ issue_imports: {
jira: 2,
fogbugz: 2,
phabricator: 2,
csv: 2
- }
+ },
+ group_imports: {
+ group_import: 2,
+ gitlab_migration: 2
+ },
+ projects_imported: {
+ total: Gitlab::UsageData::DEPRECATED_VALUE,
+ gitlab_project: Gitlab::UsageData::DEPRECATED_VALUE,
+ gitlab: Gitlab::UsageData::DEPRECATED_VALUE,
+ github: Gitlab::UsageData::DEPRECATED_VALUE,
+ bitbucket: Gitlab::UsageData::DEPRECATED_VALUE,
+ bitbucket_server: Gitlab::UsageData::DEPRECATED_VALUE,
+ gitea: Gitlab::UsageData::DEPRECATED_VALUE,
+ git: Gitlab::UsageData::DEPRECATED_VALUE,
+ manifest: Gitlab::UsageData::DEPRECATED_VALUE
+ },
+ issues_imported: {
+ jira: Gitlab::UsageData::DEPRECATED_VALUE,
+ fogbugz: Gitlab::UsageData::DEPRECATED_VALUE,
+ phabricator: Gitlab::UsageData::DEPRECATED_VALUE,
+ csv: Gitlab::UsageData::DEPRECATED_VALUE
+ },
+ groups_imported: Gitlab::UsageData::DEPRECATED_VALUE
}
)
expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
{
bulk_imports: {
- gitlab: 1
+ gitlab_v1: 1,
+ gitlab: Gitlab::UsageData::DEPRECATED_VALUE
},
- projects_imported: {
- total: 1,
- gitlab_project: 1,
- gitlab: 1,
- github: 1,
+ project_imports: {
bitbucket: 1,
bitbucket_server: 1,
- gitea: 1,
git: 1,
+ gitea: 1,
+ github: 1,
+ gitlab: 1,
+ gitlab_migration: 1,
+ gitlab_project: 1,
manifest: 1
},
- issues_imported: {
+ issue_imports: {
jira: 1,
fogbugz: 1,
phabricator: 1,
csv: 1
- }
+ },
+ group_imports: {
+ group_import: 1,
+ gitlab_migration: 1
+ },
+ projects_imported: {
+ total: Gitlab::UsageData::DEPRECATED_VALUE,
+ gitlab_project: Gitlab::UsageData::DEPRECATED_VALUE,
+ gitlab: Gitlab::UsageData::DEPRECATED_VALUE,
+ github: Gitlab::UsageData::DEPRECATED_VALUE,
+ bitbucket: Gitlab::UsageData::DEPRECATED_VALUE,
+ bitbucket_server: Gitlab::UsageData::DEPRECATED_VALUE,
+ gitea: Gitlab::UsageData::DEPRECATED_VALUE,
+ git: Gitlab::UsageData::DEPRECATED_VALUE,
+ manifest: Gitlab::UsageData::DEPRECATED_VALUE
+ },
+ issues_imported: {
+ jira: Gitlab::UsageData::DEPRECATED_VALUE,
+ fogbugz: Gitlab::UsageData::DEPRECATED_VALUE,
+ phabricator: Gitlab::UsageData::DEPRECATED_VALUE,
+ csv: Gitlab::UsageData::DEPRECATED_VALUE
+ },
+ groups_imported: Gitlab::UsageData::DEPRECATED_VALUE
+
}
)
end
- it 'includes group imports usage data' do
- for_defined_days_back do
- user = create(:user)
- group = create(:group)
- group.add_owner(user)
- create(:group_import_state, group: group, user: user)
- end
-
- expect(described_class.usage_activity_by_stage_manage({}))
- .to include(groups_imported: 2)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period))
- .to include(groups_imported: 1)
- end
-
def omniauth_providers
[
OpenStruct.new(name: 'google_oauth2'),
@@ -1262,7 +1324,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.redis_hll_counters }
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
- let(:ineligible_total_categories) { %w[source_code ci_secrets_management incident_management_alerts snippets terraform] }
+ let(:ineligible_total_categories) do
+ %w[source_code ci_secrets_management incident_management_alerts snippets terraform pipeline_authoring]
+ end
it 'has all known_events' do
expect(subject).to have_key(:redis_hll_counters)
@@ -1286,8 +1350,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe '.aggregated_metrics_weekly' do
subject(:aggregated_metrics_payload) { described_class.aggregated_metrics_weekly }
- it 'uses ::Gitlab::UsageDataCounters::HLLRedisCounter#aggregated_metrics_data', :aggregate_failures do
- expect(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:aggregated_metrics_weekly_data).and_return(global_search_gmau: 123)
+ it 'uses ::Gitlab::Usage::Metrics::Aggregates::Aggregate#weekly_data', :aggregate_failures do
+ expect_next_instance_of(::Gitlab::Usage::Metrics::Aggregates::Aggregate) do |instance|
+ expect(instance).to receive(:weekly_data).and_return(global_search_gmau: 123)
+ end
expect(aggregated_metrics_payload).to eq(aggregated_metrics: { global_search_gmau: 123 })
end
end
@@ -1295,8 +1361,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe '.aggregated_metrics_monthly' do
subject(:aggregated_metrics_payload) { described_class.aggregated_metrics_monthly }
- it 'uses ::Gitlab::UsageDataCounters::HLLRedisCounter#aggregated_metrics_data', :aggregate_failures do
- expect(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:aggregated_metrics_monthly_data).and_return(global_search_gmau: 123)
+ it 'uses ::Gitlab::Usage::Metrics::Aggregates::Aggregate#monthly_data', :aggregate_failures do
+ expect_next_instance_of(::Gitlab::Usage::Metrics::Aggregates::Aggregate) do |instance|
+ expect(instance).to receive(:monthly_data).and_return(global_search_gmau: 123)
+ end
expect(aggregated_metrics_payload).to eq(aggregated_metrics: { global_search_gmau: 123 })
end
end
diff --git a/spec/lib/gitlab/utils/markdown_spec.rb b/spec/lib/gitlab/utils/markdown_spec.rb
index 93d91f7ed90..acc5bd47c8c 100644
--- a/spec/lib/gitlab/utils/markdown_spec.rb
+++ b/spec/lib/gitlab/utils/markdown_spec.rb
@@ -53,33 +53,23 @@ RSpec.describe Gitlab::Utils::Markdown do
end
context 'when string has a product suffix' do
- let(:string) { 'My Header (ULTIMATE)' }
-
- it 'ignores a product suffix' do
- is_expected.to eq 'my-header'
- end
-
- context 'with only modifier' do
- let(:string) { 'My Header (STARTER ONLY)' }
-
- it 'ignores a product suffix' do
- is_expected.to eq 'my-header'
- end
- end
-
- context 'with "*" around a product suffix' do
- let(:string) { 'My Header **(STARTER)**' }
-
- it 'ignores a product suffix' do
- is_expected.to eq 'my-header'
- end
- end
-
- context 'with "*" around a product suffix and only modifier' do
- let(:string) { 'My Header **(STARTER ONLY)**' }
-
- it 'ignores a product suffix' do
- is_expected.to eq 'my-header'
+ %w[CORE STARTER PREMIUM ULTIMATE FREE BRONZE SILVER GOLD].each do |tier|
+ ['', ' ONLY', ' SELF', ' SASS'].each do |modifier|
+ context "#{tier}#{modifier}" do
+ let(:string) { "My Header (#{tier}#{modifier})" }
+
+ it 'ignores a product suffix' do
+ is_expected.to eq 'my-header'
+ end
+
+ context 'with "*" around a product suffix' do
+ let(:string) { "My Header **(#{tier}#{modifier})**" }
+
+ it 'ignores a product suffix' do
+ is_expected.to eq 'my-header'
+ end
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/utils/override_spec.rb b/spec/lib/gitlab/utils/override_spec.rb
index 7ba7392df0f..a5e53c1dfc1 100644
--- a/spec/lib/gitlab/utils/override_spec.rb
+++ b/spec/lib/gitlab/utils/override_spec.rb
@@ -2,6 +2,9 @@
require 'fast_spec_helper'
+# Patching ActiveSupport::Concern
+require_relative '../../../../config/initializers/0_as_concern'
+
RSpec.describe Gitlab::Utils::Override do
let(:base) do
Struct.new(:good) do
@@ -164,6 +167,70 @@ RSpec.describe Gitlab::Utils::Override do
it_behaves_like 'checking as intended, nothing was overridden'
end
+
+ context 'when ActiveSupport::Concern and class_methods are used' do
+ # We need to give module names before using Override
+ let(:base) { stub_const('Base', Module.new) }
+ let(:extension) { stub_const('Extension', Module.new) }
+
+ def define_base(method_name:)
+ base.module_eval do
+ extend ActiveSupport::Concern
+
+ class_methods do
+ define_method(method_name) do
+ :f
+ end
+ end
+ end
+ end
+
+ def define_extension(method_name:)
+ extension.module_eval do
+ extend ActiveSupport::Concern
+
+ class_methods do
+ extend Gitlab::Utils::Override
+
+ override method_name
+ define_method(method_name) do
+ :g
+ end
+ end
+ end
+ end
+
+ context 'when it is defining a overriding method' do
+ before do
+ define_base(method_name: :f)
+ define_extension(method_name: :f)
+
+ base.prepend(extension)
+ end
+
+ it 'verifies' do
+ expect(base.f).to eq(:g)
+
+ described_class.verify!
+ end
+ end
+
+ context 'when it is not defining a overriding method' do
+ before do
+ define_base(method_name: :f)
+ define_extension(method_name: :g)
+
+ base.prepend(extension)
+ end
+
+ it 'raises NotImplementedError' do
+ expect(base.f).to eq(:f)
+
+ expect { described_class.verify! }
+ .to raise_error(NotImplementedError)
+ end
+ end
+ end
end
context 'when STATIC_VERIFICATION is not set' do
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index dfc381d0ef2..e964e695828 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -58,6 +58,16 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(described_class.estimate_batch_distinct_count(relation, 'column')).to eq(5)
end
+ it 'yield provided block with PostgresHll::Buckets' do
+ buckets = Gitlab::Database::PostgresHll::Buckets.new
+
+ allow_next_instance_of(Gitlab::Database::PostgresHll::BatchDistinctCounter) do |instance|
+ allow(instance).to receive(:execute).and_return(buckets)
+ end
+
+ expect { |block| described_class.estimate_batch_distinct_count(relation, 'column', &block) }.to yield_with_args(buckets)
+ end
+
context 'quasi integration test for different counting parameters' do
# HyperLogLog http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf algorithm
# used in estimate_batch_distinct_count produce probabilistic
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 1052d4cbacc..665eebdfd9e 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -116,8 +116,6 @@ RSpec.describe Gitlab::Utils do
end
describe '.ms_to_round_sec' do
- using RSpec::Parameterized::TableSyntax
-
where(:original, :expected) do
1999.8999 | 1.9999
12384 | 12.384
@@ -169,8 +167,6 @@ RSpec.describe Gitlab::Utils do
end
describe '.remove_line_breaks' do
- using RSpec::Parameterized::TableSyntax
-
where(:original, :expected) do
"foo\nbar\nbaz" | "foobarbaz"
"foo\r\nbar\r\nbaz" | "foobarbaz"
@@ -281,8 +277,6 @@ RSpec.describe Gitlab::Utils do
end
describe '.append_path' do
- using RSpec::Parameterized::TableSyntax
-
where(:host, :path, :result) do
'http://test/' | '/foo/bar' | 'http://test/foo/bar'
'http://test/' | '//foo/bar' | 'http://test/foo/bar'
@@ -393,8 +387,6 @@ RSpec.describe Gitlab::Utils do
end
describe ".safe_downcase!" do
- using RSpec::Parameterized::TableSyntax
-
where(:str, :result) do
"test".freeze | "test"
"Test".freeze | "test"
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 9662ad13631..c22df5dd063 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -15,9 +15,7 @@ RSpec.describe Gitlab::Workhorse do
end
before do
- allow(Feature::Gitaly).to receive(:server_feature_flags).and_return({
- 'gitaly-feature-foobar' => 'true'
- })
+ stub_feature_flags(gitaly_enforce_requests_limits: true)
end
describe ".send_git_archive" do
@@ -43,7 +41,7 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq('git-archive')
expect(params).to eq({
'GitalyServer' => {
- features: { 'gitaly-feature-foobar' => 'true' },
+ features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
address: Gitlab::GitalyClient.address(project.repository_storage),
token: Gitlab::GitalyClient.token(project.repository_storage)
},
@@ -73,7 +71,7 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq('git-archive')
expect(params).to eq({
'GitalyServer' => {
- features: { 'gitaly-feature-foobar' => 'true' },
+ features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
address: Gitlab::GitalyClient.address(project.repository_storage),
token: Gitlab::GitalyClient.token(project.repository_storage)
},
@@ -124,7 +122,7 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq("git-format-patch")
expect(params).to eq({
'GitalyServer' => {
- features: { 'gitaly-feature-foobar' => 'true' },
+ features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
address: Gitlab::GitalyClient.address(project.repository_storage),
token: Gitlab::GitalyClient.token(project.repository_storage)
},
@@ -187,7 +185,7 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq("git-diff")
expect(params).to eq({
'GitalyServer' => {
- features: { 'gitaly-feature-foobar' => 'true' },
+ features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
address: Gitlab::GitalyClient.address(project.repository_storage),
token: Gitlab::GitalyClient.token(project.repository_storage)
},
@@ -274,7 +272,7 @@ RSpec.describe Gitlab::Workhorse do
let(:gitaly_params) do
{
GitalyServer: {
- features: { 'gitaly-feature-foobar' => 'true' },
+ features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
address: Gitlab::GitalyClient.address('default'),
token: Gitlab::GitalyClient.token('default')
}
@@ -310,6 +308,35 @@ RSpec.describe Gitlab::Workhorse do
it { is_expected.to include(ShowAllRefs: true) }
end
+
+ context 'when a feature flag is set for a single project' do
+ before do
+ stub_feature_flags(gitaly_mep_mep: project)
+ end
+
+ it 'sets the flag to true for that project' do
+ response = described_class.git_http_ok(repository, Gitlab::GlRepository::PROJECT, user, action)
+
+ expect(response.dig(:GitalyServer, :features)).to eq('gitaly-feature-enforce-requests-limits' => 'true',
+ 'gitaly-feature-mep-mep' => 'true')
+ end
+
+ it 'sets the flag to false for other projects' do
+ other_project = create(:project, :public, :repository)
+ response = described_class.git_http_ok(other_project.repository, Gitlab::GlRepository::PROJECT, user, action)
+
+ expect(response.dig(:GitalyServer, :features)).to eq('gitaly-feature-enforce-requests-limits' => 'true',
+ 'gitaly-feature-mep-mep' => 'false')
+ end
+
+ it 'sets the flag to false when there is no project' do
+ snippet = create(:personal_snippet, :repository)
+ response = described_class.git_http_ok(snippet.repository, Gitlab::GlRepository::SNIPPET, user, action)
+
+ expect(response.dig(:GitalyServer, :features)).to eq('gitaly-feature-enforce-requests-limits' => 'true',
+ 'gitaly-feature-mep-mep' => 'false')
+ end
+ end
end
context "when git_receive_pack action is passed" do
@@ -423,7 +450,7 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq('git-blob')
expect(params).to eq({
'GitalyServer' => {
- features: { 'gitaly-feature-foobar' => 'true' },
+ features: { 'gitaly-feature-enforce-requests-limits' => 'true' },
address: Gitlab::GitalyClient.address(project.repository_storage),
token: Gitlab::GitalyClient.token(project.repository_storage)
},
@@ -485,7 +512,7 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq('git-snapshot')
expect(params).to eq(
'GitalyServer' => {
- 'features' => { 'gitaly-feature-foobar' => 'true' },
+ 'features' => { 'gitaly-feature-enforce-requests-limits' => 'true' },
'address' => Gitlab::GitalyClient.address(project.repository_storage),
'token' => Gitlab::GitalyClient.token(project.repository_storage)
},
diff --git a/spec/lib/gitlab_danger_spec.rb b/spec/lib/gitlab_danger_spec.rb
deleted file mode 100644
index ed668c52a0e..00000000000
--- a/spec/lib/gitlab_danger_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'fast_spec_helper'
-
-RSpec.describe GitlabDanger do
- let(:gitlab_danger_helper) { nil }
-
- subject { described_class.new(gitlab_danger_helper) }
-
- describe '.local_warning_message' do
- it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq("==> Only the following Danger rules can be run locally: #{described_class::LOCAL_RULES.join(', ')}")
- end
- end
-
- describe '.success_message' do
- it 'returns an informational success message' do
- expect(described_class.success_message).to eq('==> No Danger rule violations!')
- end
- end
-
- describe '#rule_names' do
- context 'when running locally' do
- it 'returns local only rules' do
- expect(subject.rule_names).to eq(described_class::LOCAL_RULES)
- end
- end
-
- context 'when running under CI' do
- let(:gitlab_danger_helper) { double('danger_gitlab_helper') }
-
- it 'returns all rules' do
- expect(subject.rule_names).to eq(described_class::LOCAL_RULES | described_class::CI_ONLY_RULES)
- end
- end
- end
-
- describe '#html_link' do
- context 'when running locally' do
- it 'returns the same string' do
- str = 'something'
-
- expect(subject.html_link(str)).to eq(str)
- end
- end
-
- context 'when running under CI' do
- let(:gitlab_danger_helper) { double('danger_gitlab_helper') }
-
- it 'returns a HTML link formatted version of the string' do
- str = 'something'
- html_formatted_str = %Q{<a href="#{str}">#{str}</a>}
-
- expect(gitlab_danger_helper).to receive(:html_link).with(str).and_return(html_formatted_str)
-
- expect(subject.html_link(str)).to eq(html_formatted_str)
- end
- end
- end
-
- describe '#ci?' do
- context 'when gitlab_danger_helper is not available' do
- it 'returns false' do
- expect(subject.ci?).to be_falsey
- end
- end
-
- context 'when gitlab_danger_helper is available' do
- let(:gitlab_danger_helper) { double('danger_gitlab_helper') }
-
- it 'returns true' do
- expect(subject.ci?).to be_truthy
- end
- end
- end
-end
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index e1b8323eb8e..5f945d5b9fc 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -95,6 +95,26 @@ RSpec.describe Gitlab do
end
end
+ describe '.com' do
+ subject { described_class.com { true } }
+
+ before do
+ allow(described_class).to receive(:com?).and_return(gl_com)
+ end
+
+ context 'when on GitLab.com' do
+ let(:gl_com) { true }
+
+ it { is_expected.to be true }
+ end
+
+ context 'when not on GitLab.com' do
+ let(:gl_com) { false }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe '.staging?' do
subject { described_class.staging? }
@@ -332,13 +352,13 @@ RSpec.describe Gitlab do
describe '.maintenance_mode?' do
it 'returns true when maintenance mode is enabled' do
- stub_application_setting(maintenance_mode: true)
+ stub_maintenance_mode_setting(true)
expect(described_class.maintenance_mode?).to eq(true)
end
it 'returns false when maintenance mode is disabled' do
- stub_application_setting(maintenance_mode: false)
+ stub_maintenance_mode_setting(false)
expect(described_class.maintenance_mode?).to eq(false)
end
diff --git a/spec/lib/object_storage/config_spec.rb b/spec/lib/object_storage/config_spec.rb
index 0ead2a1d269..1361d80fe75 100644
--- a/spec/lib/object_storage/config_spec.rb
+++ b/spec/lib/object_storage/config_spec.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
require 'rspec-parameterized'
-require 'fog/core'
RSpec.describe ObjectStorage::Config do
using RSpec::Parameterized::TableSyntax
@@ -34,7 +33,9 @@ RSpec.describe ObjectStorage::Config do
}
end
- subject { described_class.new(raw_config.as_json) }
+ subject do
+ described_class.new(raw_config.as_json)
+ end
describe '#load_provider' do
before do
@@ -45,6 +46,10 @@ RSpec.describe ObjectStorage::Config do
it 'registers AWS as a provider' do
expect(Fog.providers.keys).to include(:aws)
end
+
+ describe '#fog_connection' do
+ it { expect(subject.fog_connection).to be_a_kind_of(Fog::AWS::Storage::Real) }
+ end
end
context 'with Google' do
@@ -59,6 +64,10 @@ RSpec.describe ObjectStorage::Config do
it 'registers Google as a provider' do
expect(Fog.providers.keys).to include(:google)
end
+
+ describe '#fog_connection' do
+ it { expect(subject.fog_connection).to be_a_kind_of(Fog::Storage::GoogleXML::Real) }
+ end
end
context 'with Azure' do
@@ -73,6 +82,10 @@ RSpec.describe ObjectStorage::Config do
it 'registers AzureRM as a provider' do
expect(Fog.providers.keys).to include(:azurerm)
end
+
+ describe '#fog_connection' do
+ it { expect(subject.fog_connection).to be_a_kind_of(Fog::Storage::AzureRM::Real) }
+ end
end
end
@@ -170,6 +183,50 @@ RSpec.describe ObjectStorage::Config do
it { expect(subject.provider).to eq('AWS') }
it { expect(subject.aws?).to be true }
it { expect(subject.google?).to be false }
+
+ it 'returns the default S3 endpoint' do
+ subject.load_provider
+
+ expect(subject.s3_endpoint).to eq("https://test-bucket.s3.amazonaws.com")
+ end
+
+ describe 'with a custom endpoint' do
+ let(:endpoint) { 'https://my.example.com' }
+
+ before do
+ credentials[:endpoint] = endpoint
+ end
+
+ it 'returns the custom endpoint' do
+ subject.load_provider
+
+ expect(subject.s3_endpoint).to eq(endpoint)
+ end
+ end
+
+ context 'with custom S3 host and port' do
+ where(:host, :port, :scheme, :expected) do
+ 's3.example.com' | 8080 | nil | 'https://test-bucket.s3.example.com:8080'
+ 's3.example.com' | 443 | nil | 'https://test-bucket.s3.example.com'
+ 's3.example.com' | 443 | "https" | 'https://test-bucket.s3.example.com'
+ 's3.example.com' | nil | nil | 'https://test-bucket.s3.example.com'
+ 's3.example.com' | 80 | "http" | 'http://test-bucket.s3.example.com'
+ 's3.example.com' | "bogus" | nil | nil
+ end
+
+ with_them do
+ before do
+ credentials[:host] = host
+ credentials[:port] = port
+ credentials[:scheme] = scheme
+ subject.load_provider
+ end
+
+ it 'returns expected host' do
+ expect(subject.s3_endpoint).to eq(expected)
+ end
+ end
+ end
end
context 'with Google credentials' do
diff --git a/spec/lib/peek/views/external_http_spec.rb b/spec/lib/peek/views/external_http_spec.rb
new file mode 100644
index 00000000000..98c4f771f33
--- /dev/null
+++ b/spec/lib/peek/views/external_http_spec.rb
@@ -0,0 +1,215 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Peek::Views::ExternalHttp, :request_store do
+ subject { described_class.new }
+
+ let(:subscriber) { Gitlab::Metrics::Subscribers::ExternalHttp.new }
+
+ before do
+ allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?).and_return(true)
+ end
+
+ let(:event_1) do
+ {
+ method: 'POST', code: "200", duration: 0.03,
+ scheme: 'https', host: 'gitlab.com', port: 80, path: '/api/v4/projects',
+ query: 'current=true'
+ }
+ end
+
+ let(:event_2) do
+ {
+ method: 'POST', duration: 1.3,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2/issues',
+ query: 'current=true',
+ exception_object: Net::ReadTimeout.new
+ }
+ end
+
+ let(:event_3) do
+ {
+ method: 'GET', code: "301", duration: 0.005,
+ scheme: 'http', host: 'gitlab.com', port: 80, path: '/api/v4/projects/2',
+ query: 'current=true',
+ proxy_host: 'proxy.gitlab.com', proxy_port: 8080
+ }
+ end
+
+ it 'returns no results' do
+ expect(subject.results).to eq(
+ calls: 0, details: [], duration: "0ms", warnings: []
+ )
+ end
+
+ it 'returns aggregated results' do
+ subscriber.request(double(:event, payload: event_1))
+ subscriber.request(double(:event, payload: event_2))
+ subscriber.request(double(:event, payload: event_3))
+
+ results = subject.results
+ expect(results[:calls]).to eq(3)
+ expect(results[:duration]).to eq("1335.00ms")
+ expect(results[:details].count).to eq(3)
+
+ expected = [
+ {
+ duration: 30.0,
+ label: "POST https://gitlab.com:80/api/v4/projects?current=true",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ },
+ {
+ duration: 1300,
+ label: "POST http://gitlab.com:80/api/v4/projects/2/issues?current=true",
+ code: nil,
+ proxy: nil,
+ error: "Exception: Net::ReadTimeout",
+ warnings: ["1300.0 over 100"]
+ },
+ {
+ duration: 5.0,
+ label: "GET http://gitlab.com:80/api/v4/projects/2?current=true",
+ code: "Response status: 301",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ }
+ ]
+
+ expect(
+ results[:details].map { |data| data.slice(:duration, :label, :code, :proxy, :error, :warnings) }
+ ).to match_array(expected)
+ end
+
+ context 'when the host is in IPv4 format' do
+ before do
+ event_1[:host] = '1.2.3.4'
+ end
+
+ it 'displays IPv4 in the label' do
+ subscriber.request(double(:event, payload: event_1))
+
+ expect(subject.results[:details]).to contain_exactly(
+ a_hash_including(
+ duration: 30.0,
+ label: "POST https://1.2.3.4:80/api/v4/projects?current=true",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ )
+ )
+ end
+ end
+
+ context 'when the host is in IPv6 foramat' do
+ before do
+ event_1[:host] = '2606:4700:90:0:f22e:fbec:5bed:a9b9'
+ end
+
+ it 'displays IPv6 in the label' do
+ subscriber.request(double(:event, payload: event_1))
+
+ expect(subject.results[:details]).to contain_exactly(
+ a_hash_including(
+ duration: 30.0,
+ label: "POST https://[2606:4700:90:0:f22e:fbec:5bed:a9b9]:80/api/v4/projects?current=true",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ )
+ )
+ end
+ end
+
+ context 'when the query is a hash' do
+ before do
+ event_1[:query] = { current: true, 'item1' => 'string', 'item2' => [1, 2] }
+ end
+
+ it 'converts query hash into a query string' do
+ subscriber.request(double(:event, payload: event_1))
+
+ expect(subject.results[:details]).to contain_exactly(
+ a_hash_including(
+ duration: 30.0,
+ label: "POST https://gitlab.com:80/api/v4/projects?current=true&item1=string&item2%5B%5D=1&item2%5B%5D=2",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ )
+ )
+ end
+ end
+
+ context 'when the host is invalid' do
+ before do
+ event_1[:host] = '!@#%!@#%!@#%'
+ end
+
+ it 'displays unknown in the label' do
+ subscriber.request(double(:event, payload: event_1))
+
+ expect(subject.results[:details]).to contain_exactly(
+ a_hash_including(
+ duration: 30.0,
+ label: "POST unknown",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ )
+ )
+ end
+ end
+
+ context 'when URI creation raises an URI::Error' do
+ before do
+ # This raises an URI::Error exception
+ event_1[:port] = 'invalid'
+ end
+
+ it 'displays unknown in the label' do
+ subscriber.request(double(:event, payload: event_1))
+
+ expect(subject.results[:details]).to contain_exactly(
+ a_hash_including(
+ duration: 30.0,
+ label: "POST unknown",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ )
+ )
+ end
+ end
+
+ context 'when URI creation raises a StandardError exception' do
+ before do
+ # This raises a TypeError exception
+ event_1[:scheme] = 1234
+ end
+
+ it 'displays unknown in the label' do
+ subscriber.request(double(:event, payload: event_1))
+
+ expect(subject.results[:details]).to contain_exactly(
+ a_hash_including(
+ duration: 30.0,
+ label: "POST unknown",
+ code: "Response status: 200",
+ proxy: nil,
+ error: nil,
+ warnings: []
+ )
+ )
+ end
+ end
+end
diff --git a/spec/lib/release_highlights/validator/entry_spec.rb b/spec/lib/release_highlights/validator/entry_spec.rb
index 648356e63ba..da44938f165 100644
--- a/spec/lib/release_highlights/validator/entry_spec.rb
+++ b/spec/lib/release_highlights/validator/entry_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe ReleaseHighlights::Validator::Entry do
subject.valid?
- expect(subject.errors[:packages].first).to include("must be one of", "Core", "Starter", "Premium", "Ultimate")
+ expect(subject.errors[:packages].first).to include("must be one of", "Free", "Premium", "Ultimate")
end
end
end
diff --git a/spec/lib/release_highlights/validator_spec.rb b/spec/lib/release_highlights/validator_spec.rb
index e68d9145dcd..a423e8cc5f6 100644
--- a/spec/lib/release_highlights/validator_spec.rb
+++ b/spec/lib/release_highlights/validator_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe ReleaseHighlights::Validator do
---------------------------------------------------------
Validation failed for spec/fixtures/whats_new/invalid.yml
---------------------------------------------------------
- * Packages must be one of ["Core", "Starter", "Premium", "Ultimate"] (line 6)
+ * Packages must be one of ["Free", "Premium", "Ultimate"] (line 6)
MESSAGE
end
diff --git a/spec/lib/security/ci_configuration/sast_build_actions_spec.rb b/spec/lib/security/ci_configuration/sast_build_actions_spec.rb
new file mode 100644
index 00000000000..c8f9430eff9
--- /dev/null
+++ b/spec/lib/security/ci_configuration/sast_build_actions_spec.rb
@@ -0,0 +1,539 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::SastBuildActions do
+ let(:default_sast_values) do
+ { 'global' =>
+ [
+ { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => 'registry.gitlab.com/gitlab-org/security-products/analyzers' }
+ ],
+ 'pipeline' =>
+ [
+ { 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'test' },
+ { 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 4 },
+ { 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
+ { 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec, test, tests, tmp' }
+ ] }
+ end
+
+ let(:params) do
+ { 'global' =>
+ [
+ { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => 'new_registry' }
+ ],
+ 'pipeline' =>
+ [
+ { 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'security' },
+ { 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 1 },
+ { 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
+ { 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec,docs' }
+ ] }
+ end
+
+ let(:params_with_analyzer_info) do
+ params.merge( { 'analyzers' =>
+ [
+ {
+ 'name' => "bandit",
+ 'enabled' => false
+ },
+ {
+ 'name' => "brakeman",
+ 'enabled' => true,
+ 'variables' => [
+ { 'field' => "SAST_BRAKEMAN_LEVEL",
+ 'defaultValue' => "1",
+ 'value' => "2" }
+ ]
+ },
+ {
+ 'name' => "flawfinder",
+ 'enabled' => true,
+ 'variables' => [
+ { 'field' => "SAST_FLAWFINDER_LEVEL",
+ 'defaultValue' => "1",
+ 'value' => "1" }
+ ]
+ }
+ ] }
+ )
+ end
+
+ let(:params_with_all_analyzers_enabled) do
+ params.merge( { 'analyzers' =>
+ [
+ {
+ 'name' => "flawfinder",
+ 'enabled' => true
+ },
+ {
+ 'name' => "brakeman",
+ 'enabled' => true
+ }
+ ] }
+ )
+ end
+
+ context 'with existing .gitlab-ci.yml' do
+ let(:auto_devops_enabled) { false }
+
+ context 'sast has not been included' do
+ context 'template includes are array' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_template_array_without_sast }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_two_includes)
+ end
+ end
+
+ context 'template include is not an array' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_without_sast }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_two_includes)
+ end
+
+ it 'reports defaults have been overwritten' do
+ expect(result.first[:default_values_overwritten]).to eq(true)
+ end
+ end
+ end
+
+ context 'sast template include is not an array' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_all_params)
+ end
+ end
+
+ context 'with default values' do
+ let(:params) { default_sast_values }
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set)
+ end
+
+ it 'reports defaults have not been overwritten' do
+ expect(result.first[:default_values_overwritten]).to eq(false)
+ end
+
+ context 'analyzer section' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params_with_analyzer_info, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set_but_analyzers)
+ end
+
+ context 'analyzers are disabled' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params_with_analyzer_info, gitlab_ci_content).generate }
+
+ it 'writes SAST_EXCLUDED_ANALYZERS' do
+ stub_const('Security::CiConfiguration::SastBuildActions::SAST_DEFAULT_ANALYZERS', 'bandit, brakeman, flawfinder')
+
+ expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set_but_analyzers)
+ end
+ end
+
+ context 'all analyzers are enabled' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params_with_all_analyzers_enabled, gitlab_ci_content).generate }
+
+ it 'does not write SAST_DEFAULT_ANALYZERS or SAST_EXCLUDED_ANALYZERS' do
+ stub_const('Security::CiConfiguration::SastBuildActions::SAST_DEFAULT_ANALYZERS', 'brakeman, flawfinder')
+
+ expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set)
+ end
+ end
+ end
+ end
+
+ context 'with update stage and SEARCH_MAX_DEPTH and set SECURE_ANALYZERS_PREFIX to default' do
+ let(:params) do
+ { 'global' =>
+ [
+ { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => 'registry.gitlab.com/gitlab-org/security-products/analyzers' }
+ ],
+ 'pipeline' =>
+ [
+ { 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'brand_new_stage' },
+ { 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 5 },
+ { 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
+ { 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec,docs' }
+ ] }
+ end
+
+ let(:gitlab_ci_content) { existing_gitlab_ci }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_updated_stage)
+ end
+ end
+
+ context 'with no existing variables' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_with_no_variables }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_variable_section_added)
+ end
+ end
+
+ context 'with no existing sast config' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_with_no_sast_section }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_sast_section_added)
+ end
+ end
+
+ context 'with no existing sast variables' do
+ let(:gitlab_ci_content) { existing_gitlab_ci_with_no_sast_variables }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:action]).to eq('update')
+ expect(result.first[:content]).to eq(sast_yaml_sast_variables_section_added)
+ end
+ end
+
+ def existing_gitlab_ci_and_template_array_without_sast
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
+ "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "include" => [{ "template" => "existing.yml" }] }
+ end
+
+ def existing_gitlab_ci_and_single_template_with_sast_and_default_stage
+ { "stages" => %w(test),
+ "variables" => { "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
+ "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "test" },
+ "include" => { "template" => "Security/SAST.gitlab-ci.yml" } }
+ end
+
+ def existing_gitlab_ci_and_single_template_without_sast
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
+ "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "include" => { "template" => "existing.yml" } }
+ end
+
+ def existing_gitlab_ci_with_no_variables
+ { "stages" => %w(test security),
+ "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "include" => [{ "template" => "Security/SAST.gitlab-ci.yml" }] }
+ end
+
+ def existing_gitlab_ci_with_no_sast_section
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
+ "include" => [{ "template" => "Security/SAST.gitlab-ci.yml" }] }
+ end
+
+ def existing_gitlab_ci_with_no_sast_variables
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "localhost:5000/analyzers" },
+ "sast" => { "stage" => "security" },
+ "include" => [{ "template" => "Security/SAST.gitlab-ci.yml" }] }
+ end
+
+ def existing_gitlab_ci
+ { "stages" => %w(test security),
+ "variables" => { "RANDOM" => "make sure this persists", "SECURE_ANALYZERS_PREFIX" => "bad_prefix" },
+ "sast" => { "variables" => { "SAST_ANALYZER_IMAGE_TAG" => 2, "SEARCH_MAX_DEPTH" => 1 }, "stage" => "security" },
+ "include" => [{ "template" => "Security/SAST.gitlab-ci.yml" }] }
+ end
+ end
+
+ context 'with no .gitlab-ci.yml' do
+ let(:gitlab_ci_content) { nil }
+
+ context 'autodevops disabled' do
+ let(:auto_devops_enabled) { false }
+
+ context 'with one empty parameter' do
+ let(:params) do
+ { 'global' =>
+ [
+ { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => '' }
+ ] }
+ end
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set)
+ end
+ end
+
+ context 'with all parameters' do
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ it 'generates the correct YML' do
+ expect(result.first[:content]).to eq(sast_yaml_all_params)
+ end
+ end
+ end
+
+ context 'with autodevops enabled' do
+ let(:auto_devops_enabled) { true }
+
+ subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
+
+ before do
+ allow_next_instance_of(described_class) do |sast_build_actions|
+ allow(sast_build_actions).to receive(:auto_devops_stages).and_return(fast_auto_devops_stages)
+ end
+ end
+
+ it 'generates the correct YML' do
+ expect(result.first[:content]).to eq(auto_devops_with_custom_stage)
+ end
+ end
+ end
+
+ describe 'Security::CiConfiguration::SastBuildActions::SAST_DEFAULT_ANALYZERS' do
+ subject(:variable) {Security::CiConfiguration::SastBuildActions::SAST_DEFAULT_ANALYZERS}
+
+ it 'is sorted alphabetically' do
+ sorted_variable = Security::CiConfiguration::SastBuildActions::SAST_DEFAULT_ANALYZERS
+ .split(',')
+ .map(&:strip)
+ .sort
+ .join(', ')
+
+ expect(variable).to eq(sorted_variable)
+ end
+ end
+
+ # stubbing this method allows this spec file to use fast_spec_helper
+ def fast_auto_devops_stages
+ auto_devops_template = YAML.safe_load( File.read('lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml') )
+ auto_devops_template['stages']
+ end
+
+ def sast_yaml_with_no_variables_set_but_analyzers
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ sast:
+ variables:
+ SAST_EXCLUDED_ANALYZERS: bandit
+ SAST_BRAKEMAN_LEVEL: '2'
+ stage: test
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ CI_YML
+ end
+
+ def sast_yaml_with_no_variables_set
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ sast:
+ stage: test
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ CI_YML
+ end
+
+ def sast_yaml_all_params
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ - security
+ variables:
+ SECURE_ANALYZERS_PREFIX: new_registry
+ sast:
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 1
+ stage: security
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ CI_YML
+ end
+
+ def auto_devops_with_custom_stage
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - build
+ - test
+ - deploy
+ - review
+ - dast
+ - staging
+ - canary
+ - production
+ - incremental rollout 10%
+ - incremental rollout 25%
+ - incremental rollout 50%
+ - incremental rollout 100%
+ - performance
+ - cleanup
+ - security
+ variables:
+ SECURE_ANALYZERS_PREFIX: new_registry
+ sast:
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 1
+ stage: security
+ include:
+ - template: Auto-DevOps.gitlab-ci.yml
+ CI_YML
+ end
+
+ def sast_yaml_two_includes
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ - security
+ variables:
+ RANDOM: make sure this persists
+ SECURE_ANALYZERS_PREFIX: new_registry
+ sast:
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 1
+ stage: security
+ include:
+ - template: existing.yml
+ - template: Security/SAST.gitlab-ci.yml
+ CI_YML
+ end
+
+ def sast_yaml_variable_section_added
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ - security
+ sast:
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 1
+ stage: security
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ variables:
+ SECURE_ANALYZERS_PREFIX: new_registry
+ CI_YML
+ end
+
+ def sast_yaml_sast_section_added
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ - security
+ variables:
+ RANDOM: make sure this persists
+ SECURE_ANALYZERS_PREFIX: new_registry
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ sast:
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 1
+ stage: security
+ CI_YML
+ end
+
+ def sast_yaml_sast_variables_section_added
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ - security
+ variables:
+ RANDOM: make sure this persists
+ SECURE_ANALYZERS_PREFIX: new_registry
+ sast:
+ stage: security
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 1
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ CI_YML
+ end
+
+ def sast_yaml_updated_stage
+ <<-CI_YML.strip_heredoc
+ # You can override the included template(s) by including variable overrides
+ # See https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
+ # Note that environment variables can be set in several places
+ # See https://docs.gitlab.com/ee/ci/variables/#priority-of-environment-variables
+ stages:
+ - test
+ - security
+ - brand_new_stage
+ variables:
+ RANDOM: make sure this persists
+ sast:
+ variables:
+ SAST_EXCLUDED_PATHS: spec,docs
+ SEARCH_MAX_DEPTH: 5
+ stage: brand_new_stage
+ include:
+ - template: Security/SAST.gitlab-ci.yml
+ CI_YML
+ end
+end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 53ce200eed5..89cf1aaedd2 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -905,6 +905,28 @@ RSpec.describe Notify do
is_expected.to have_body_text project.full_name
is_expected.to have_body_text project_member.human_access.downcase
is_expected.to have_body_text project_member.invite_token
+ is_expected.to have_link('Join now', href: invite_url(project_member.invite_token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE))
+ end
+
+ it 'contains invite link for the avatar', :experiment do
+ stub_experiments('members/invite_email': :avatar)
+
+ is_expected.not_to have_content('You are invited!')
+ is_expected.not_to have_body_text 'What is a GitLab'
+ end
+
+ it 'contains invite link for the avatar', :experiment do
+ stub_experiments('members/invite_email': :permission_info)
+
+ is_expected.not_to have_content('You are invited!')
+ is_expected.to have_body_text 'What is a GitLab'
+ is_expected.to have_body_text 'What can I do with'
+ end
+
+ it 'has invite link for the control group' do
+ stub_experiments('members/invite_email': :control)
+
+ is_expected.to have_content('You are invited!')
end
end
diff --git a/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb b/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
new file mode 100644
index 00000000000..ff27bdcf12d
--- /dev/null
+++ b/spec/migrations/20201112130710_schedule_remove_duplicate_vulnerabilities_findings_spec.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201112130710_schedule_remove_duplicate_vulnerabilities_findings.rb')
+
+RSpec.describe ScheduleRemoveDuplicateVulnerabilitiesFindings, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let!(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let!(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let!(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
+ let!(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ project_id: project.id,
+ external_type: 'vulnerability-identifier',
+ external_id: 'vulnerability-identifier',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'vulnerability identifier')
+ end
+
+ let!(:first_finding) do
+ create_finding!(
+ uuid: "test1",
+ vulnerability_id: nil,
+ report_type: 0,
+ location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:first_duplicate) do
+ create_finding!(
+ uuid: "test2",
+ vulnerability_id: nil,
+ report_type: 0,
+ location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner2.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:second_duplicate) do
+ create_finding!(
+ uuid: "test3",
+ vulnerability_id: nil,
+ report_type: 0,
+ location_fingerprint: '2bda3014914481791847d8eca38d1a8d13b6ad76',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner3.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:unrelated_finding) do
+ create_finding!(
+ uuid: "unreleated_finding",
+ vulnerability_id: nil,
+ report_type: 1,
+ location_fingerprint: 'random_location_fingerprint',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: unrelated_scanner.id,
+ project_id: project.id
+ )
+ end
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migration' do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(4)
+ expect(described_class::MIGRATION).to be_scheduled_migration(first_finding.id, first_finding.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(first_duplicate.id, first_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(second_duplicate.id, second_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_migration(unrelated_finding.id, unrelated_finding.id)
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ 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: 'test')
+ vulnerability_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: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+end
diff --git a/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb b/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
new file mode 100644
index 00000000000..33b2e009c8d
--- /dev/null
+++ b/spec/migrations/20210119122354_alter_vsa_issue_first_mentioned_in_commit_value_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210119122354_alter_vsa_issue_first_mentioned_in_commit_value.rb')
+
+RSpec.describe AlterVsaIssueFirstMentionedInCommitValue, schema: 20210114033715 do
+ let(:group_stages) { table(:analytics_cycle_analytics_group_stages) }
+ let(:value_streams) { table(:analytics_cycle_analytics_group_value_streams) }
+ let(:namespaces) { table(:namespaces) }
+
+ let(:namespace) { namespaces.create!(id: 1, name: 'group', path: 'group') }
+ let(:value_stream) { value_streams.create!(name: 'test', group_id: namespace.id) }
+
+ let!(:stage_1) { group_stages.create!(group_value_stream_id: value_stream.id, group_id: namespace.id, name: 'stage 1', start_event_identifier: described_class::ISSUE_FIRST_MENTIONED_IN_COMMIT_EE, end_event_identifier: 1) }
+ let!(:stage_2) { group_stages.create!(group_value_stream_id: value_stream.id, group_id: namespace.id, name: 'stage 2', start_event_identifier: 2, end_event_identifier: described_class::ISSUE_FIRST_MENTIONED_IN_COMMIT_EE) }
+ let!(:stage_3) { group_stages.create!(group_value_stream_id: value_stream.id, group_id: namespace.id, name: 'stage 3', start_event_identifier: described_class::ISSUE_FIRST_MENTIONED_IN_COMMIT_FOSS, end_event_identifier: 3) }
+
+ describe '#up' do
+ it 'changes the EE specific identifier values to the FOSS version' do
+ migrate!
+
+ expect(stage_1.reload.start_event_identifier).to eq(described_class::ISSUE_FIRST_MENTIONED_IN_COMMIT_FOSS)
+ expect(stage_2.reload.end_event_identifier).to eq(described_class::ISSUE_FIRST_MENTIONED_IN_COMMIT_FOSS)
+ end
+
+ it 'does not change irrelevant records' do
+ expect { migrate! }.not_to change { stage_3.reload }
+ end
+ end
+end
diff --git a/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb b/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
new file mode 100644
index 00000000000..7e351617ea3
--- /dev/null
+++ b/spec/migrations/20210205174154_remove_bad_dependency_proxy_manifests_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210205174154_remove_bad_dependency_proxy_manifests.rb')
+
+RSpec.describe RemoveBadDependencyProxyManifests, schema: 20210128140157 do
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:dependency_proxy_manifests) { table(:dependency_proxy_manifests) }
+ let_it_be(:group) { namespaces.create!(type: 'Group', name: 'test', path: 'test') }
+
+ let_it_be(:dependency_proxy_manifest_with_content_type) do
+ dependency_proxy_manifests.create!(group_id: group.id, file: 'foo', file_name: 'foo', digest: 'asdf1234', content_type: 'content-type' )
+ end
+
+ let_it_be(:dependency_proxy_manifest_without_content_type) do
+ dependency_proxy_manifests.create!(group_id: group.id, file: 'bar', file_name: 'bar', digest: 'fdsa6789')
+ end
+
+ it 'removes the dependency_proxy_manifests with a content_type', :aggregate_failures do
+ expect(dependency_proxy_manifest_with_content_type).to be_present
+ expect(dependency_proxy_manifest_without_content_type).to be_present
+
+ expect { migrate! }.to change { dependency_proxy_manifests.count }.from(2).to(1)
+
+ expect(dependency_proxy_manifests.where.not(content_type: nil)).to be_empty
+ expect(dependency_proxy_manifest_without_content_type.reload).to be_present
+ end
+end
diff --git a/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb b/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
new file mode 100644
index 00000000000..52678111b48
--- /dev/null
+++ b/spec/migrations/20210210093901_backfill_updated_at_after_repository_storage_move_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210210093901_backfill_updated_at_after_repository_storage_move.rb')
+
+RSpec.describe BackfillUpdatedAtAfterRepositoryStorageMove, :sidekiq do
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:project_repository_storage_moves) { table(:project_repository_storage_moves) }
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+
+ describe '#up' do
+ it 'schedules background jobs for all distinct projects in batches' do
+ stub_const("#{described_class}::BATCH_SIZE", 3)
+
+ project_1 = projects.create!(id: 1, namespace_id: namespace.id)
+ project_2 = projects.create!(id: 2, namespace_id: namespace.id)
+ project_3 = projects.create!(id: 3, namespace_id: namespace.id)
+ project_4 = projects.create!(id: 4, namespace_id: namespace.id)
+ project_5 = projects.create!(id: 5, namespace_id: namespace.id)
+ project_6 = projects.create!(id: 6, namespace_id: namespace.id)
+ project_7 = projects.create!(id: 7, namespace_id: namespace.id)
+ projects.create!(id: 8, namespace_id: namespace.id)
+
+ project_repository_storage_moves.create!(id: 1, project_id: project_1.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 2, project_id: project_1.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 3, project_id: project_2.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 4, project_id: project_3.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 5, project_id: project_3.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 6, project_id: project_4.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 7, project_id: project_4.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 8, project_id: project_5.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 9, project_id: project_6.id, source_storage_name: 'default', destination_storage_name: 'default')
+ project_repository_storage_moves.create!(id: 10, project_id: project_7.id, source_storage_name: 'default', destination_storage_name: 'default')
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(3)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2.minutes, 1, 2, 3)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(4.minutes, 4, 5, 6)
+ expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(6.minutes, 7)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/add_has_external_issue_tracker_trigger_spec.rb b/spec/migrations/add_has_external_issue_tracker_trigger_spec.rb
new file mode 100644
index 00000000000..72983c7cfbf
--- /dev/null
+++ b/spec/migrations/add_has_external_issue_tracker_trigger_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe AddHasExternalIssueTrackerTrigger do
+ let(:migration) { described_class.new }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:services) { table(:services) }
+
+ before do
+ @namespace = namespaces.create!(name: 'foo', path: 'foo')
+ @project = projects.create!(namespace_id: @namespace.id)
+ end
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'INSERT trigger' do
+ it 'sets `has_external_issue_tracker` to true when active `issue_tracker` is inserted' do
+ expect do
+ services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+ end.to change { @project.reload.has_external_issue_tracker }.to(true)
+ end
+
+ it 'does not set `has_external_issue_tracker` to true when service is for a different project' do
+ different_project = projects.create!(namespace_id: @namespace.id)
+
+ expect do
+ services.create!(category: 'issue_tracker', active: true, project_id: different_project.id)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+
+ it 'does not set `has_external_issue_tracker` to true when inactive `issue_tracker` is inserted' do
+ expect do
+ services.create!(category: 'issue_tracker', active: false, project_id: @project.id)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+
+ it 'does not set `has_external_issue_tracker` to true when a non-`issue tracker` active service is inserted' do
+ expect do
+ services.create!(category: 'my_type', active: true, project_id: @project.id)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+ end
+
+ describe 'UPDATE trigger' do
+ it 'sets `has_external_issue_tracker` to true when `issue_tracker` is made active' do
+ service = services.create!(category: 'issue_tracker', active: false, project_id: @project.id)
+
+ expect do
+ service.update!(active: true)
+ end.to change { @project.reload.has_external_issue_tracker }.to(true)
+ end
+
+ it 'sets `has_external_issue_tracker` to false when `issue_tracker` is made inactive' do
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+
+ expect do
+ service.update!(active: false)
+ end.to change { @project.reload.has_external_issue_tracker }.to(false)
+ end
+
+ it 'sets `has_external_issue_tracker` to false when `issue_tracker` is made inactive, and an inactive `issue_tracker` exists' do
+ services.create!(category: 'issue_tracker', active: false, project_id: @project.id)
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+
+ expect do
+ service.update!(active: false)
+ end.to change { @project.reload.has_external_issue_tracker }.to(false)
+ end
+
+ it 'does not change `has_external_issue_tracker` when `issue_tracker` is made inactive, if an active `issue_tracker` exists' do
+ services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+
+ expect do
+ service.update!(active: false)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+
+ it 'does not change `has_external_issue_tracker` when service is for a different project' do
+ different_project = projects.create!(namespace_id: @namespace.id)
+ service = services.create!(category: 'issue_tracker', active: false, project_id: different_project.id)
+
+ expect do
+ service.update!(active: true)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+ end
+
+ describe 'DELETE trigger' do
+ it 'sets `has_external_issue_tracker` to false when `issue_tracker` is deleted' do
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+
+ expect do
+ service.delete
+ end.to change { @project.reload.has_external_issue_tracker }.to(false)
+ end
+
+ it 'sets `has_external_issue_tracker` to false when `issue_tracker` is deleted, if an inactive `issue_tracker` still exists' do
+ services.create!(category: 'issue_tracker', active: false, project_id: @project.id)
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+
+ expect do
+ service.delete
+ end.to change { @project.reload.has_external_issue_tracker }.to(false)
+ end
+
+ it 'does not change `has_external_issue_tracker` when `issue_tracker` is deleted, if an active `issue_tracker` still exists' do
+ services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+
+ expect do
+ service.delete
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+
+ it 'does not change `has_external_issue_tracker` when service is for a different project' do
+ different_project = projects.create!(namespace_id: @namespace.id)
+ service = services.create!(category: 'issue_tracker', active: true, project_id: different_project.id)
+
+ expect do
+ service.delete
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the INSERT trigger' do
+ expect do
+ services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+
+ it 'drops the UPDATE trigger' do
+ service = services.create!(category: 'issue_tracker', active: false, project_id: @project.id)
+ @project.update!(has_external_issue_tracker: false)
+
+ expect do
+ service.update!(active: true)
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+
+ it 'drops the DELETE trigger' do
+ service = services.create!(category: 'issue_tracker', active: true, project_id: @project.id)
+ @project.update!(has_external_issue_tracker: true)
+
+ expect do
+ service.delete
+ end.not_to change { @project.reload.has_external_issue_tracker }
+ end
+ end
+end
diff --git a/spec/migrations/add_new_post_eoa_plans_spec.rb b/spec/migrations/add_new_post_eoa_plans_spec.rb
new file mode 100644
index 00000000000..5ae227a6617
--- /dev/null
+++ b/spec/migrations/add_new_post_eoa_plans_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'post_migrate', '20210205104425_add_new_post_eoa_plans.rb')
+
+RSpec.describe AddNewPostEoaPlans do
+ let(:plans) { table(:plans) }
+
+ subject(:migration) { described_class.new }
+
+ describe '#up' do
+ it 'creates the two new records' do
+ expect { migration.up }.to change { plans.count }.by(2)
+
+ new_plans = plans.last(2)
+ expect(new_plans.map(&:name)).to contain_exactly('premium', 'ultimate')
+ end
+ end
+
+ describe '#down' do
+ it 'removes these two new records' do
+ plans.create!(name: 'premium', title: 'Premium (Formerly Silver)')
+ plans.create!(name: 'ultimate', title: 'Ultimate (Formerly Gold)')
+
+ expect { migration.down }.to change { plans.count }.by(-2)
+
+ expect(plans.find_by(name: 'premium')).to be_nil
+ expect(plans.find_by(name: 'ultimate')).to be_nil
+ end
+ end
+end
diff --git a/spec/migrations/cleanup_projects_with_bad_has_external_wiki_data_spec.rb b/spec/migrations/cleanup_projects_with_bad_has_external_wiki_data_spec.rb
new file mode 100644
index 00000000000..ee1f718849f
--- /dev/null
+++ b/spec/migrations/cleanup_projects_with_bad_has_external_wiki_data_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe CleanupProjectsWithBadHasExternalWikiData, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'foo', path: 'bar') }
+ let(:projects) { table(:projects) }
+ let(:services) { table(:services) }
+
+ def create_projects!(num)
+ Array.new(num) do
+ projects.create!(namespace_id: namespace.id)
+ end
+ end
+
+ def create_active_external_wiki_integrations!(*projects)
+ projects.each do |project|
+ services.create!(type: 'ExternalWikiService', project_id: project.id, active: true)
+ end
+ end
+
+ def create_disabled_external_wiki_integrations!(*projects)
+ projects.each do |project|
+ services.create!(type: 'ExternalWikiService', project_id: project.id, active: false)
+ end
+ end
+
+ def create_active_other_integrations!(*projects)
+ projects.each do |project|
+ services.create!(type: 'NotAnExternalWikiService', project_id: project.id, active: true)
+ end
+ end
+
+ it 'sets `projects.has_external_wiki` correctly' do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+
+ project_with_external_wiki_1,
+ project_with_external_wiki_2,
+ project_with_disabled_external_wiki_1,
+ project_with_disabled_external_wiki_2,
+ project_without_external_wiki_1,
+ project_without_external_wiki_2 = create_projects!(6)
+
+ create_active_external_wiki_integrations!(
+ project_with_external_wiki_1,
+ project_with_external_wiki_2
+ )
+
+ create_disabled_external_wiki_integrations!(
+ project_with_disabled_external_wiki_1,
+ project_with_disabled_external_wiki_2
+ )
+
+ create_active_other_integrations!(
+ project_without_external_wiki_1,
+ project_without_external_wiki_2
+ )
+
+ # PG triggers on the services table added in a previous migration
+ # will have set the `has_external_wiki` columns to correct data when
+ # the services records were created above.
+ #
+ # We set the `has_external_wiki` columns for projects to incorrect
+ # data manually below to emulate projects in a state before the PG
+ # triggers were added.
+ project_with_external_wiki_2.update!(has_external_wiki: false)
+ project_with_disabled_external_wiki_2.update!(has_external_wiki: true)
+ project_without_external_wiki_2.update!(has_external_wiki: true)
+
+ migrate!
+
+ expected_true = [
+ project_with_external_wiki_1,
+ project_with_external_wiki_2
+ ].each(&:reload).map(&:has_external_wiki)
+
+ expected_not_true = [
+ project_without_external_wiki_1,
+ project_without_external_wiki_2,
+ project_with_disabled_external_wiki_1,
+ project_with_disabled_external_wiki_2
+ ].each(&:reload).map(&:has_external_wiki)
+
+ expect(expected_true).to all(eq(true))
+ expect(expected_not_true).to all(be_falsey)
+ end
+end
diff --git a/spec/migrations/drop_alerts_service_data_spec.rb b/spec/migrations/drop_alerts_service_data_spec.rb
new file mode 100644
index 00000000000..b2128da938f
--- /dev/null
+++ b/spec/migrations/drop_alerts_service_data_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210205213933_drop_alerts_service_data.rb')
+
+RSpec.describe DropAlertsServiceData do
+ let_it_be(:alerts_service_data) { table(:alerts_service_data) }
+
+ it 'correctly migrates up and down' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(alerts_service_data.create!(service_id: 1)).to be_a alerts_service_data
+ }
+
+ migration.after -> {
+ expect { alerts_service_data.create!(service_id: 1) }
+ .to raise_error(ActiveRecord::StatementInvalid, /UndefinedTable/)
+ }
+ end
+ end
+end
diff --git a/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb b/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb
index ad83119f324..c705515ce98 100644
--- a/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb
+++ b/spec/migrations/encrypt_feature_flags_clients_tokens_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe EncryptFeatureFlagsClientsTokens do
let(:feature_flags_clients) { table(:operations_feature_flags_clients) }
let(:projects) { table(:projects) }
let(:plaintext) { "secret-token" }
- let(:ciphertext) { Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext) }
+ let(:ciphertext) { Gitlab::CryptoHelper.aes256_gcm_encrypt(plaintext, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC) }
describe '#up' do
it 'keeps plaintext token the same and populates token_encrypted if not present' do
diff --git a/spec/migrations/remove_alerts_service_records_again_spec.rb b/spec/migrations/remove_alerts_service_records_again_spec.rb
new file mode 100644
index 00000000000..963b54848f9
--- /dev/null
+++ b/spec/migrations/remove_alerts_service_records_again_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20210205214003_remove_alerts_service_records_again.rb')
+
+RSpec.describe RemoveAlertsServiceRecordsAgain do
+ let(:services) { table(:services) }
+
+ before do
+ 5.times { services.create!(type: 'AlertsService') }
+ services.create!(type: 'SomeOtherType')
+ end
+
+ it 'removes services records of type AlertsService and corresponding data', :aggregate_failures do
+ expect(services.count).to eq(6)
+
+ migrate!
+
+ expect(services.count).to eq(1)
+ expect(services.first.type).to eq('SomeOtherType')
+ expect(services.where(type: 'AlertsService')).to be_empty
+ end
+end
diff --git a/spec/migrations/schedule_migrate_security_scans_spec.rb b/spec/migrations/schedule_migrate_security_scans_spec.rb
index 61b14f239ae..eb86a910611 100644
--- a/spec/migrations/schedule_migrate_security_scans_spec.rb
+++ b/spec/migrations/schedule_migrate_security_scans_spec.rb
@@ -3,7 +3,6 @@
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200217225719_schedule_migrate_security_scans.rb')
-# rubocop: disable RSpec/FactoriesInMigrationSpecs
RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
let(:migration) { described_class.new }
let(:namespaces) { table(:namespaces) }
@@ -13,7 +12,7 @@ RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
let(:namespace) { namespaces.create!(name: "foo", path: "bar") }
let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:build) { builds.create! }
+ let(:job) { builds.create! }
before do
stub_const("#{described_class.name}::BATCH_SIZE", 1)
@@ -35,8 +34,8 @@ RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
end
context 'has security job artifacts' do
- let!(:job_artifact_1) { job_artifacts.create!(project_id: project.id, job_id: build.id, file_type: 5) }
- let!(:job_artifact_2) { job_artifacts.create!(project_id: project.id, job_id: build.id, file_type: 8) }
+ let!(:job_artifact_1) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 5) }
+ let!(:job_artifact_2) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 8) }
it 'schedules migration of security scans' do
Sidekiq::Testing.fake! do
@@ -52,8 +51,8 @@ RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
end
context 'has non-security job artifacts' do
- let!(:job_artifact_1) { job_artifacts.create!(project_id: project.id, job_id: build.id, file_type: 4) }
- let!(:job_artifact_2) { job_artifacts.create!(project_id: project.id, job_id: build.id, file_type: 9) }
+ let!(:job_artifact_1) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 4) }
+ let!(:job_artifact_2) { job_artifacts.create!(project_id: project.id, job_id: job.id, file_type: 9) }
it 'schedules migration of security scans' do
Sidekiq::Testing.fake! do
diff --git a/spec/migrations/schedule_populate_issue_email_participants_spec.rb b/spec/migrations/schedule_populate_issue_email_participants_spec.rb
new file mode 100644
index 00000000000..a3f18617b70
--- /dev/null
+++ b/spec/migrations/schedule_populate_issue_email_participants_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201128210234_schedule_populate_issue_email_participants.rb')
+
+RSpec.describe SchedulePopulateIssueEmailParticipants 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) }
+ let!(:issue3) { table(:issues).create!(id: 3, project_id: project.id, service_desk_reply_to: "b@gitlab.com") }
+ let!(:issue4) { table(:issues).create!(id: 4, project_id: project.id, service_desk_reply_to: "c@gitlab.com") }
+ let!(:issue5) { table(:issues).create!(id: 5, project_id: project.id, service_desk_reply_to: "d@gitlab.com") }
+ let(:issue_email_participants) { table(:issue_email_participants) }
+
+ it 'correctly schedules background migrations' do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(2.minutes, 1, 3)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(4.minutes, 4, 5)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb
index f0bae3f29c0..51435cc4342 100644
--- a/spec/models/active_session_spec.rb
+++ b/spec/models/active_session_spec.rb
@@ -358,7 +358,7 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
it 'calls .destroy_sessions' do
expect(ActiveSession).to(
receive(:destroy_sessions)
- .with(anything, user, [active_session.public_id, rack_session.public_id, rack_session.private_id]))
+ .with(anything, user, [encrypted_active_session_id, rack_session.public_id, rack_session.private_id]))
subject
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 4755d700d72..9a4dd2c799b 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -114,6 +114,21 @@ RSpec.describe ApplicationSetting do
it { is_expected.to allow_value(nil).for(:repository_storages_weighted_default) }
it { is_expected.not_to allow_value({ default: 100, shouldntexist: 50 }).for(:repository_storages_weighted) }
+ it { is_expected.to allow_value(400).for(:notes_create_limit) }
+ it { is_expected.not_to allow_value('two').for(:notes_create_limit) }
+ it { is_expected.not_to allow_value(nil).for(:notes_create_limit) }
+ it { is_expected.not_to allow_value(5.5).for(:notes_create_limit) }
+ it { is_expected.not_to allow_value(-2).for(:notes_create_limit) }
+
+ def many_usernames(num = 100)
+ Array.new(num) { |i| "username#{i}" }
+ end
+
+ it { is_expected.to allow_value(many_usernames(100)).for(:notes_create_limit_allowlist) }
+ it { is_expected.not_to allow_value(many_usernames(101)).for(:notes_create_limit_allowlist) }
+ it { is_expected.not_to allow_value(nil).for(:notes_create_limit_allowlist) }
+ it { is_expected.to allow_value([]).for(:notes_create_limit_allowlist) }
+
context 'help_page_documentation_base_url validations' do
it { is_expected.to allow_value(nil).for(:help_page_documentation_base_url) }
it { is_expected.to allow_value('https://docs.gitlab.com').for(:help_page_documentation_base_url) }
@@ -635,28 +650,28 @@ RSpec.describe ApplicationSetting do
end
end
- describe '#asset_proxy_whitelist' do
+ describe '#asset_proxy_allowlist' do
context 'when given an Array' do
it 'sets the domains and adds current running host' do
- setting.asset_proxy_whitelist = ['example.com', 'assets.example.com']
- expect(setting.asset_proxy_whitelist).to eq(['example.com', 'assets.example.com', 'localhost'])
+ setting.asset_proxy_allowlist = ['example.com', 'assets.example.com']
+ expect(setting.asset_proxy_allowlist).to eq(['example.com', 'assets.example.com', 'localhost'])
end
end
context 'when given a String' do
it 'sets multiple domains with spaces' do
- setting.asset_proxy_whitelist = 'example.com *.example.com'
- expect(setting.asset_proxy_whitelist).to eq(['example.com', '*.example.com', 'localhost'])
+ setting.asset_proxy_allowlist = 'example.com *.example.com'
+ expect(setting.asset_proxy_allowlist).to eq(['example.com', '*.example.com', 'localhost'])
end
it 'sets multiple domains with newlines and a space' do
- setting.asset_proxy_whitelist = "example.com\n *.example.com"
- expect(setting.asset_proxy_whitelist).to eq(['example.com', '*.example.com', 'localhost'])
+ setting.asset_proxy_allowlist = "example.com\n *.example.com"
+ expect(setting.asset_proxy_allowlist).to eq(['example.com', '*.example.com', 'localhost'])
end
it 'sets multiple domains with commas' do
- setting.asset_proxy_whitelist = "example.com, *.example.com"
- expect(setting.asset_proxy_whitelist).to eq(['example.com', '*.example.com', 'localhost'])
+ setting.asset_proxy_allowlist = "example.com, *.example.com"
+ expect(setting.asset_proxy_allowlist).to eq(['example.com', '*.example.com', 'localhost'])
end
end
end
@@ -949,6 +964,50 @@ RSpec.describe ApplicationSetting do
end
end
+ describe 'kroki_format_supported?' do
+ it 'returns true when Excalidraw is enabled' do
+ subject.kroki_formats_excalidraw = true
+ expect(subject.kroki_format_supported?('excalidraw')).to eq(true)
+ end
+
+ it 'returns true when BlockDiag is enabled' do
+ subject.kroki_formats_blockdiag = true
+ # format "blockdiag" aggregates multiple diagram types: actdiag, blockdiag, nwdiag...
+ expect(subject.kroki_format_supported?('actdiag')).to eq(true)
+ expect(subject.kroki_format_supported?('blockdiag')).to eq(true)
+ end
+
+ it 'returns false when BlockDiag is disabled' do
+ subject.kroki_formats_blockdiag = false
+ # format "blockdiag" aggregates multiple diagram types: actdiag, blockdiag, nwdiag...
+ expect(subject.kroki_format_supported?('actdiag')).to eq(false)
+ expect(subject.kroki_format_supported?('blockdiag')).to eq(false)
+ end
+
+ it 'returns false when the diagram type is optional and not enabled' do
+ expect(subject.kroki_format_supported?('bpmn')).to eq(false)
+ end
+
+ it 'returns true when the diagram type is enabled by default' do
+ expect(subject.kroki_format_supported?('vegalite')).to eq(true)
+ expect(subject.kroki_format_supported?('nomnoml')).to eq(true)
+ expect(subject.kroki_format_supported?('unknown-diagram-type')).to eq(false)
+ end
+
+ it 'returns false when the diagram type is unknown' do
+ expect(subject.kroki_format_supported?('unknown-diagram-type')).to eq(false)
+ end
+ end
+
+ describe 'kroki_formats' do
+ it 'returns the value for kroki_formats' do
+ subject.kroki_formats = { blockdiag: true, bpmn: false, excalidraw: true }
+ expect(subject.kroki_formats_blockdiag).to eq(true)
+ expect(subject.kroki_formats_bpmn).to eq(false)
+ expect(subject.kroki_formats_excalidraw).to eq(true)
+ end
+ end
+
it 'does not allow to set weight for non existing storage' do
setting.repository_storages_weighted = { invalid_storage: 100 }
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index 0732b671729..e5ab96ca514 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -81,6 +81,37 @@ RSpec.describe BulkImports::Entity, type: :model do
expect(entity.errors).to include(:parent)
end
end
+
+ context 'validate destination namespace of a group_entity' do
+ it 'is invalid if destination namespace is the source namespace' do
+ group_a = create(:group, path: 'group_a')
+
+ entity = build(
+ :bulk_import_entity,
+ :group_entity,
+ source_full_path: group_a.full_path,
+ destination_namespace: group_a.full_path
+ )
+
+ expect(entity).not_to be_valid
+ expect(entity.errors).to include(:destination_namespace)
+ end
+
+ it 'is invalid if destination namespace is a descendant of the source' do
+ group_a = create(:group, path: 'group_a')
+ group_b = create(:group, parent: group_a, path: 'group_b')
+
+ entity = build(
+ :bulk_import_entity,
+ :group_entity,
+ source_full_path: group_a.full_path,
+ destination_namespace: group_b.full_path
+ )
+
+ expect(entity).not_to be_valid
+ expect(entity.errors).to include(:destination_namespace)
+ end
+ end
end
describe "#update_tracker_for" do
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 4f09f6f1da4..b50e4204e0a 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -80,6 +80,14 @@ RSpec.describe Ci::Bridge do
end
end
+ it "schedules downstream pipeline creation when the status is waiting for resource" do
+ bridge.status = :waiting_for_resource
+
+ expect(bridge).to receive(:schedule_downstream_pipeline!)
+
+ bridge.enqueue_waiting_for_resource!
+ end
+
it 'raises error when the status is failed' do
bridge.status = :failed
diff --git a/spec/models/ci/build_dependencies_spec.rb b/spec/models/ci/build_dependencies_spec.rb
index c5f56dbe5bc..e343ec0e698 100644
--- a/spec/models/ci/build_dependencies_spec.rb
+++ b/spec/models/ci/build_dependencies_spec.rb
@@ -18,6 +18,10 @@ RSpec.describe Ci::BuildDependencies do
let!(:rubocop_test) { create(:ci_build, pipeline: pipeline, name: 'rubocop', stage_idx: 1, stage: 'test') }
let!(:staging) { create(:ci_build, pipeline: pipeline, name: 'staging', stage_idx: 2, stage: 'deploy') }
+ before do
+ stub_feature_flags(ci_validate_build_dependencies_override: false)
+ end
+
describe '#local' do
subject { described_class.new(job).local }
@@ -360,4 +364,28 @@ RSpec.describe Ci::BuildDependencies do
expect(subject).to contain_exactly(1, 2, 3, 4)
end
end
+
+ describe '#valid?' do
+ subject { described_class.new(job).valid? }
+
+ let(:job) { rspec_test }
+
+ it { is_expected.to eq(true) }
+
+ context 'when a local dependency is invalid' do
+ before do
+ build.update_column(:erased_at, Time.current)
+ end
+
+ it { is_expected.to eq(false) }
+
+ context 'when ci_validate_build_dependencies_override feature flag is enabled' do
+ before do
+ stub_feature_flags(ci_validate_build_dependencies_override: job.project)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index c2029b9240b..4ad7ce70a44 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1185,60 +1185,6 @@ RSpec.describe Ci::Build do
end
end
- describe 'state transition with resource group' do
- let(:resource_group) { create(:ci_resource_group, project: project) }
-
- context 'when build status is created' do
- let(:build) { create(:ci_build, :created, project: project, resource_group: resource_group) }
-
- it 'is waiting for resource when build is enqueued' do
- expect(Ci::ResourceGroups::AssignResourceFromResourceGroupWorker).to receive(:perform_async).with(resource_group.id)
-
- expect { build.enqueue! }.to change { build.status }.from('created').to('waiting_for_resource')
-
- expect(build.waiting_for_resource_at).not_to be_nil
- end
-
- context 'when build is waiting for resource' do
- before do
- build.update_column(:status, 'waiting_for_resource')
- end
-
- it 'is enqueued when build requests resource' do
- expect { build.enqueue_waiting_for_resource! }.to change { build.status }.from('waiting_for_resource').to('pending')
- end
-
- it 'releases a resource when build finished' do
- expect(build.resource_group).to receive(:release_resource_from).with(build).and_call_original
- expect(Ci::ResourceGroups::AssignResourceFromResourceGroupWorker).to receive(:perform_async).with(build.resource_group_id)
-
- build.enqueue_waiting_for_resource!
- build.success!
- end
-
- context 'when build has prerequisites' do
- before do
- allow(build).to receive(:any_unmet_prerequisites?) { true }
- end
-
- it 'is preparing when build is enqueued' do
- expect { build.enqueue_waiting_for_resource! }.to change { build.status }.from('waiting_for_resource').to('preparing')
- end
- end
-
- context 'when there are no available resources' do
- before do
- resource_group.assign_resource_to(create(:ci_build))
- end
-
- it 'stays as waiting for resource when build requests resource' do
- expect { build.enqueue_waiting_for_resource }.not_to change { build.status }
- end
- end
- end
- end
- end
-
describe '#on_stop' do
subject { build.on_stop }
@@ -1914,7 +1860,7 @@ RSpec.describe Ci::Build do
subject { build.artifacts_file_for_type(file_type) }
it 'queries artifacts for type' do
- expect(build).to receive_message_chain(:job_artifacts, :find_by).with(file_type: Ci::JobArtifact.file_types[file_type])
+ expect(build).to receive_message_chain(:job_artifacts, :find_by).with(file_type: [Ci::JobArtifact.file_types[file_type]])
subject
end
@@ -3605,7 +3551,7 @@ RSpec.describe Ci::Build do
context 'when validates for dependencies is enabled' do
before do
- stub_feature_flags(ci_disable_validates_dependencies: false)
+ stub_feature_flags(ci_validate_build_dependencies_override: false)
end
let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) }
@@ -3633,7 +3579,7 @@ RSpec.describe Ci::Build do
let(:options) { { dependencies: ['test'] } }
before do
- stub_feature_flags(ci_disable_validates_dependencies: true)
+ stub_feature_flags(ci_validate_build_dependencies_override: true)
end
it_behaves_like 'validation is not active'
@@ -4096,18 +4042,6 @@ RSpec.describe Ci::Build do
expect(coverage_report.files.keys).to match_array(['src/main/java/com/example/javademo/User.java'])
end
-
- context 'and smart_cobertura_parser feature flag is disabled' do
- before do
- stub_feature_flags(smart_cobertura_parser: false)
- end
-
- it 'parses blobs and add the results to the coverage report with unmodified paths' do
- expect { subject }.not_to raise_error
-
- expect(coverage_report.files.keys).to match_array(['com/example/javademo/User.java'])
- end
- end
end
context 'when there is a corrupted Cobertura coverage report' do
@@ -4922,14 +4856,6 @@ RSpec.describe Ci::Build do
it_behaves_like 'drops the build without changing allow_failure'
end
-
- context 'when ci_allow_failure_with_exit_codes is disabled' do
- before do
- stub_feature_flags(ci_allow_failure_with_exit_codes: false)
- end
-
- it_behaves_like 'drops the build without changing allow_failure'
- end
end
end
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 75ed5939724..3d728b9335e 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
it_behaves_like 'having unique enum values'
before do
- stub_feature_flags(ci_enable_live_trace: true)
+ stub_feature_flags(ci_enable_live_trace: true, gitlab_ci_trace_read_consistency: true)
stub_artifacts_object_storage
end
diff --git a/spec/models/ci/build_trace_chunks/fog_spec.rb b/spec/models/ci/build_trace_chunks/fog_spec.rb
index bc96e2584cf..d9e9533fb26 100644
--- a/spec/models/ci/build_trace_chunks/fog_spec.rb
+++ b/spec/models/ci/build_trace_chunks/fog_spec.rb
@@ -98,27 +98,6 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
expect(data_store.data(model)).to eq new_data
end
-
- context 'when ci_live_trace_use_fog_attributes flag is disabled' do
- before do
- stub_feature_flags(ci_live_trace_use_fog_attributes: false)
- end
-
- it 'does not pass along Fog attributes' do
- expect_next_instance_of(Fog::AWS::Storage::Files) do |files|
- expect(files).to receive(:create).with(
- key: anything,
- body: new_data
- ).and_call_original
- end
-
- expect(data_store.data(model)).to be_nil
-
- data_store.set_data(model, new_data)
-
- expect(data_store.data(model)).to eq new_data
- end
- end
end
end
end
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index f16396d62c9..f6e6a6a5e02 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
describe 'associations' do
it { is_expected.to belong_to(:last_pipeline) }
it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:group) }
end
describe 'validations' do
@@ -83,8 +84,9 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
end
describe 'scopes' do
- let_it_be(:project) { create(:project) }
- let(:recent_build_group_report_result) { create(:ci_daily_build_group_report_result, project: project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let(:recent_build_group_report_result) { create(:ci_daily_build_group_report_result, project: project, group: group) }
let(:old_build_group_report_result) do
create(:ci_daily_build_group_report_result, date: 1.week.ago, project: project)
end
@@ -97,6 +99,43 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
end
end
+ describe '.by_group' do
+ subject { described_class.by_group(group) }
+
+ it 'returns records by group' do
+ expect(subject).to contain_exactly(recent_build_group_report_result)
+ end
+ end
+
+ describe '.by_ref_path' do
+ subject(:coverages) { described_class.by_ref_path(recent_build_group_report_result.ref_path) }
+
+ it 'returns coverages by ref_path' do
+ expect(coverages).to contain_exactly(recent_build_group_report_result, old_build_group_report_result)
+ end
+ end
+
+ describe '.ordered_by_date_and_group_name' do
+ subject(:coverages) { described_class.ordered_by_date_and_group_name }
+
+ it 'returns coverages ordered by data and group name' do
+ expect(subject).to contain_exactly(recent_build_group_report_result, old_build_group_report_result)
+ end
+ end
+
+ describe '.by_dates' do
+ subject(:coverages) { described_class.by_dates(start_date, end_date) }
+
+ context 'when daily coverages exist during those dates' do
+ let(:start_date) { 1.day.ago.to_date.to_s }
+ let(:end_date) { Date.current.to_s }
+
+ it 'returns coverages' do
+ expect(coverages).to contain_exactly(recent_build_group_report_result)
+ end
+ end
+ end
+
describe '.with_coverage' do
subject { described_class.with_coverage }
diff --git a/spec/models/ci/pipeline_artifact_spec.rb b/spec/models/ci/pipeline_artifact_spec.rb
index 8cbace845a9..3fe09f05cab 100644
--- a/spec/models/ci/pipeline_artifact_spec.rb
+++ b/spec/models/ci/pipeline_artifact_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ci::PipelineArtifact, type: :model do
- let(:coverage_report) { create(:ci_pipeline_artifact) }
+ let(:coverage_report) { create(:ci_pipeline_artifact, :with_coverage_report) }
describe 'associations' do
it { is_expected.to belong_to(:pipeline) }
@@ -15,7 +15,7 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
it_behaves_like 'UpdateProjectStatistics' do
let_it_be(:pipeline, reload: true) { create(:ci_pipeline) }
- subject { build(:ci_pipeline_artifact, pipeline: pipeline) }
+ subject { build(:ci_pipeline_artifact, :with_code_coverage_with_multiple_files, pipeline: pipeline) }
end
describe 'validations' do
@@ -51,7 +51,7 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
end
describe 'file is being stored' do
- subject { create(:ci_pipeline_artifact) }
+ subject { create(:ci_pipeline_artifact, :with_coverage_report) }
context 'when existing object has local store' do
it_behaves_like 'mounted file in local store'
@@ -68,7 +68,7 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
end
context 'when file contains multi-byte characters' do
- let(:coverage_report_multibyte) { create(:ci_pipeline_artifact, :with_multibyte_characters) }
+ let(:coverage_report_multibyte) { create(:ci_pipeline_artifact, :with_coverage_multibyte_characters) }
it 'sets the size in bytesize' do
expect(coverage_report_multibyte.size).to eq(14)
@@ -76,48 +76,118 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
end
end
- describe '.has_code_coverage?' do
- subject { Ci::PipelineArtifact.has_code_coverage? }
+ describe '.report_exists?' do
+ subject(:pipeline_artifact) { Ci::PipelineArtifact.report_exists?(file_type) }
- context 'when pipeline artifact has a code coverage' do
- let!(:pipeline_artifact) { create(:ci_pipeline_artifact) }
+ context 'when file_type is code_coverage' do
+ let(:file_type) { :code_coverage }
+
+ context 'when pipeline artifact has a coverage report' do
+ let!(:pipeline_artifact) { create(:ci_pipeline_artifact, :with_coverage_report) }
+
+ it 'returns true' do
+ expect(pipeline_artifact).to be_truthy
+ end
+ end
- it 'returns true' do
- expect(subject).to be_truthy
+ context 'when pipeline artifact does not have a coverage report' do
+ it 'returns false' do
+ expect(pipeline_artifact).to be_falsey
+ end
end
end
- context 'when pipeline artifact does not have a code coverage' do
+ context 'when file_type is code_quality_mr_diff' do
+ let(:file_type) { :code_quality_mr_diff }
+
+ context 'when pipeline artifact has a codequality mr diff report' do
+ let!(:pipeline_artifact) { create(:ci_pipeline_artifact, :with_codequality_mr_diff_report) }
+
+ it 'returns true' do
+ expect(pipeline_artifact).to be_truthy
+ end
+ end
+
+ context 'when pipeline artifact does not have a codequality mr diff report' do
+ it 'returns false' do
+ expect(pipeline_artifact).to be_falsey
+ end
+ end
+ end
+
+ context 'when file_type is nil' do
+ let(:file_type) { nil }
+
it 'returns false' do
- expect(subject).to be_falsey
+ expect(pipeline_artifact).to be_falsey
end
end
end
- describe '.find_with_code_coverage' do
- subject { Ci::PipelineArtifact.find_with_code_coverage }
+ describe '.find_by_file_type' do
+ subject(:pipeline_artifact) { Ci::PipelineArtifact.find_by_file_type(file_type) }
- context 'when pipeline artifact has a coverage report' do
- let!(:coverage_report) { create(:ci_pipeline_artifact) }
+ context 'when file_type is code_coverage' do
+ let(:file_type) { :code_coverage }
+
+ context 'when pipeline artifact has a coverage report' do
+ let!(:coverage_report) { create(:ci_pipeline_artifact, :with_coverage_report) }
- it 'returns a pipeline artifact with a code coverage' do
- expect(subject.file_type).to eq('code_coverage')
+ it 'returns a pipeline artifact with a coverage report' do
+ expect(pipeline_artifact.file_type).to eq('code_coverage')
+ end
+ end
+
+ context 'when pipeline artifact does not have a coverage report' do
+ it 'returns nil' do
+ expect(pipeline_artifact).to be_nil
+ end
+ end
+ end
+
+ context 'when file_type is code_quality_mr_diff' do
+ let(:file_type) { :code_quality_mr_diff }
+
+ context 'when pipeline artifact has a quality report' do
+ let!(:coverage_report) { create(:ci_pipeline_artifact, :with_codequality_mr_diff_report) }
+
+ it 'returns a pipeline artifact with a quality report' do
+ expect(pipeline_artifact.file_type).to eq('code_quality_mr_diff')
+ end
+ end
+
+ context 'when pipeline artifact does not have a quality report' do
+ it 'returns nil' do
+ expect(pipeline_artifact).to be_nil
+ end
end
end
- context 'when pipeline artifact does not have a coverage report' do
+ context 'when file_type is nil' do
+ let(:file_type) { nil }
+
it 'returns nil' do
- expect(subject).to be_nil
+ expect(pipeline_artifact).to be_nil
end
end
end
describe '#present' do
- subject { coverage_report.present }
+ subject(:presenter) { report.present }
context 'when file_type is code_coverage' do
+ let(:report) { coverage_report }
+
it 'uses code coverage presenter' do
- expect(subject.present).to be_kind_of(Ci::PipelineArtifacts::CodeCoveragePresenter)
+ expect(presenter).to be_kind_of(Ci::PipelineArtifacts::CodeCoveragePresenter)
+ end
+ end
+
+ context 'when file_type is code_quality_mr_diff' do
+ let(:report) { create(:ci_pipeline_artifact, :with_codequality_mr_diff_report) }
+
+ it 'uses code codequality mr diff presenter' do
+ expect(presenter).to be_kind_of(Ci::PipelineArtifacts::CodeQualityMrDiffPresenter)
end
end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 140527e4414..94943fb3644 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1263,26 +1263,6 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
pipeline.send(event)
end
-
- context 'the feature is disabled' do
- it 'does not trigger a worker' do
- stub_feature_flags(jira_sync_builds: false)
-
- expect(worker).not_to receive(:perform_async)
-
- pipeline.send(event)
- end
- end
-
- context 'the feature is enabled for this project' do
- it 'does trigger a worker' do
- stub_feature_flags(jira_sync_builds: pipeline.project)
-
- expect(worker).to receive(:perform_async)
-
- pipeline.send(event)
- end
- end
end
end
end
@@ -2018,13 +1998,34 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
is_expected.to be_falsey
end
end
+
+ context 'bridge which is allowed to fail fails' do
+ before do
+ create :ci_bridge, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop'
+ end
+
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'bridge which is allowed to fail is successful' do
+ before do
+ create :ci_bridge, :allowed_to_fail, :success, pipeline: pipeline, name: 'rubocop'
+ end
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
end
describe '#number_of_warnings' do
it 'returns the number of warnings' do
create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop')
+ create(:ci_bridge, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop')
- expect(pipeline.number_of_warnings).to eq(1)
+ expect(pipeline.number_of_warnings).to eq(2)
end
it 'supports eager loading of the number of warnings' do
@@ -2322,7 +2323,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'on waiting for resource' do
before do
- allow(build).to receive(:requires_resource?) { true }
+ allow(build).to receive(:with_resource_group?) { true }
allow(Ci::ResourceGroups::AssignResourceFromResourceGroupWorker).to receive(:perform_async)
build.enqueue
@@ -3389,7 +3390,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#batch_lookup_report_artifact_for_file_type' do
context 'with code quality report artifact' do
- let(:pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) }
it "returns the code quality artifact" do
expect(pipeline.batch_lookup_report_artifact_for_file_type(:codequality)).to eq(pipeline.job_artifacts.sample)
@@ -3511,6 +3512,66 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '#has_codequality_mr_diff_report?' do
+ subject { pipeline.has_codequality_mr_diff_report? }
+
+ context 'when pipeline has a codequality mr diff report' do
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_mr_diff_report, :running, project: project) }
+
+ it { expect(subject).to be_truthy }
+ end
+
+ context 'when pipeline does not have a codequality mr diff report' do
+ let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
+ describe '#can_generate_codequality_reports?' do
+ subject { pipeline.can_generate_codequality_reports? }
+
+ context 'when pipeline has builds with codequality reports' do
+ before do
+ create(:ci_build, :codequality_reports, pipeline: pipeline, project: project)
+ end
+
+ context 'when pipeline status is running' do
+ let(:pipeline) { create(:ci_pipeline, :running, project: project) }
+
+ it { expect(subject).to be_falsey }
+ end
+
+ context 'when pipeline status is success' do
+ let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+
+ it 'can generate a codequality report' do
+ expect(subject).to be_truthy
+ end
+
+ context 'when feature is disabled' do
+ before do
+ stub_feature_flags(codequality_mr_diff: false)
+ end
+
+ it 'can not generate a codequality report' do
+ expect(subject).to be_falsey
+ end
+ end
+ end
+ end
+
+ context 'when pipeline does not have builds with codequality reports' do
+ before do
+ create(:ci_build, :artifacts, pipeline: pipeline, project: project)
+ end
+
+ let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
describe '#test_report_summary' do
subject { pipeline.test_report_summary }
diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb
index 35764e2bbbe..6290f4aef16 100644
--- a/spec/models/ci/processable_spec.rb
+++ b/spec/models/ci/processable_spec.rb
@@ -122,4 +122,58 @@ RSpec.describe Ci::Processable do
it { is_expected.to be_empty }
end
end
+
+ describe 'state transition with resource group' do
+ let(:resource_group) { create(:ci_resource_group, project: project) }
+
+ context 'when build status is created' do
+ let(:build) { create(:ci_build, :created, project: project, resource_group: resource_group) }
+
+ it 'is waiting for resource when build is enqueued' do
+ expect(Ci::ResourceGroups::AssignResourceFromResourceGroupWorker).to receive(:perform_async).with(resource_group.id)
+
+ expect { build.enqueue! }.to change { build.status }.from('created').to('waiting_for_resource')
+
+ expect(build.waiting_for_resource_at).not_to be_nil
+ end
+
+ context 'when build is waiting for resource' do
+ before do
+ build.update_column(:status, 'waiting_for_resource')
+ end
+
+ it 'is enqueued when build requests resource' do
+ expect { build.enqueue_waiting_for_resource! }.to change { build.status }.from('waiting_for_resource').to('pending')
+ end
+
+ it 'releases a resource when build finished' do
+ expect(build.resource_group).to receive(:release_resource_from).with(build).and_call_original
+ expect(Ci::ResourceGroups::AssignResourceFromResourceGroupWorker).to receive(:perform_async).with(build.resource_group_id)
+
+ build.enqueue_waiting_for_resource!
+ build.success!
+ end
+
+ context 'when build has prerequisites' do
+ before do
+ allow(build).to receive(:any_unmet_prerequisites?) { true }
+ end
+
+ it 'is preparing when build is enqueued' do
+ expect { build.enqueue_waiting_for_resource! }.to change { build.status }.from('waiting_for_resource').to('preparing')
+ end
+ end
+
+ context 'when there are no available resources' do
+ before do
+ resource_group.assign_resource_to(create(:ci_build))
+ end
+
+ it 'stays as waiting for resource when build requests resource' do
+ expect { build.enqueue_waiting_for_resource }.not_to change { build.status }
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/ci/resource_group_spec.rb b/spec/models/ci/resource_group_spec.rb
index 9f72d1a82e5..50a786419f2 100644
--- a/spec/models/ci/resource_group_spec.rb
+++ b/spec/models/ci/resource_group_spec.rb
@@ -32,12 +32,12 @@ RSpec.describe Ci::ResourceGroup do
let(:build) { create(:ci_build) }
let(:resource_group) { create(:ci_resource_group) }
- it 'retains resource for the build' do
- expect(resource_group.resources.first.build).to be_nil
+ it 'retains resource for the processable' do
+ expect(resource_group.resources.first.processable).to be_nil
is_expected.to eq(true)
- expect(resource_group.resources.first.build).to eq(build)
+ expect(resource_group.resources.first.processable).to eq(build)
end
context 'when there are no free resources' do
@@ -51,7 +51,7 @@ RSpec.describe Ci::ResourceGroup do
end
context 'when the build has already retained a resource' do
- let!(:another_resource) { create(:ci_resource, resource_group: resource_group, build: build) }
+ let!(:another_resource) { create(:ci_resource, resource_group: resource_group, processable: build) }
it 'fails to retain resource' do
expect { subject }.to raise_error(ActiveRecord::RecordNotUnique)
@@ -71,11 +71,11 @@ RSpec.describe Ci::ResourceGroup do
end
it 'releases resource from the build' do
- expect(resource_group.resources.first.build).to eq(build)
+ expect(resource_group.resources.first.processable).to eq(build)
is_expected.to eq(true)
- expect(resource_group.resources.first.build).to be_nil
+ expect(resource_group.resources.first.processable).to be_nil
end
end
diff --git a/spec/models/ci/resource_spec.rb b/spec/models/ci/resource_spec.rb
index 90f26ef2b31..5574f6f82b2 100644
--- a/spec/models/ci/resource_spec.rb
+++ b/spec/models/ci/resource_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Ci::Resource do
subject { described_class.retained_by(build) }
let(:build) { create(:ci_build) }
- let!(:resource) { create(:ci_resource, build: build) }
+ let!(:resource) { create(:ci_resource, processable: build) }
it 'returns retained resources' do
is_expected.to eq([resource])
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 3d873a1b9c1..0afc491dc73 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -288,6 +288,7 @@ RSpec.describe Ci::Stage, :models do
context 'when stage has warnings' do
before do
create(:ci_build, :failed, :allowed_to_fail, stage_id: stage.id)
+ create(:ci_bridge, :failed, :allowed_to_fail, stage_id: stage.id)
end
describe '#has_warnings?' do
@@ -310,7 +311,7 @@ RSpec.describe Ci::Stage, :models do
expect(synced_queries.count).to eq 1
expect(stage.number_of_warnings.inspect).to include 'BatchLoader'
- expect(stage.number_of_warnings).to eq 1
+ expect(stage.number_of_warnings).to eq 2
end
end
end
diff --git a/spec/models/clusters/agent_spec.rb b/spec/models/clusters/agent_spec.rb
index 49f41570717..a85a72eba0b 100644
--- a/spec/models/clusters/agent_spec.rb
+++ b/spec/models/clusters/agent_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Clusters::Agent do
subject { create(:cluster_agent) }
+ it { is_expected.to belong_to(:created_by_user).class_name('User').optional }
it { is_expected.to belong_to(:project).class_name('::Project') }
it { is_expected.to have_many(:agent_tokens).class_name('Clusters::AgentToken') }
diff --git a/spec/models/clusters/agent_token_spec.rb b/spec/models/clusters/agent_token_spec.rb
index 9110fdeda52..5cb84ee131a 100644
--- a/spec/models/clusters/agent_token_spec.rb
+++ b/spec/models/clusters/agent_token_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Clusters::AgentToken do
it { is_expected.to belong_to(:agent).class_name('Clusters::Agent') }
+ it { is_expected.to belong_to(:created_by_user).class_name('User').optional }
describe '#token' do
it 'is generated on save' do
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index fb0613187c5..07e64889b93 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -17,6 +17,8 @@ RSpec.describe Clusters::Platforms::Kubernetes do
it { is_expected.to delegate_method(:enabled?).to(:cluster) }
it { is_expected.to delegate_method(:provided_by_user?).to(:cluster) }
+ it { is_expected.to nullify_if_blank(:namespace) }
+
it_behaves_like 'having unique enum values'
describe 'before_validation' do
@@ -29,14 +31,6 @@ RSpec.describe Clusters::Platforms::Kubernetes do
expect(kubernetes.namespace).to eq('abc')
end
end
-
- context 'when namespace is blank' do
- let(:namespace) { '' }
-
- it 'nullifies the namespace' do
- expect(kubernetes.namespace).to be_nil
- end
- end
end
describe 'validation' do
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index acbabee9383..a5f02b61132 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -400,6 +400,19 @@ eos
allow(commit).to receive(:safe_message).and_return(message + "\n" + message)
expect(commit.full_title).to eq(message)
end
+
+ it 'truncates html representation if more than 1KiB' do
+ # Commit title is over 2KiB on a single line
+ huge_commit_title = ('panic ' * 350) + 'trailing text'
+
+ allow(commit).to receive(:safe_message).and_return(huge_commit_title)
+
+ commit.refresh_markdown_cache
+ full_title_html = commit.full_title_html
+
+ expect(full_title_html.bytesize).to be < 2.kilobytes
+ expect(full_title_html).not_to include('trailing text')
+ end
end
describe 'description' do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 532f68c2f18..01da379e001 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -510,6 +510,10 @@ RSpec.describe CommitStatus do
end
describe '#group_name' do
+ before do
+ stub_feature_flags(simplified_commit_status_group_name: false)
+ end
+
using RSpec::Parameterized::TableSyntax
let(:commit_status) do
@@ -557,6 +561,58 @@ RSpec.describe CommitStatus do
is_expected.to eq(group_name)
end
end
+
+ context 'with simplified_commit_status_group_name' do
+ before do
+ stub_feature_flags(simplified_commit_status_group_name: true)
+ end
+
+ where(:name, :group_name) do
+ 'rspec1' | 'rspec1'
+ 'rspec1 0 1' | 'rspec1'
+ 'rspec1 0/2' | 'rspec1'
+ 'rspec:windows' | 'rspec:windows'
+ 'rspec:windows 0' | 'rspec:windows 0'
+ 'rspec:windows 0 2/2' | 'rspec:windows 0'
+ 'rspec:windows 0 test' | 'rspec:windows 0 test'
+ 'rspec:windows 0 test 2/2' | 'rspec:windows 0 test'
+ 'rspec:windows 0 1 2/2' | 'rspec:windows'
+ 'rspec:windows 0 1 [aws] 2/2' | 'rspec:windows'
+ 'rspec:windows 0 1 name [aws] 2/2' | 'rspec:windows 0 1 name'
+ 'rspec:windows 0 1 name' | 'rspec:windows 0 1 name'
+ 'rspec:windows 0 1 name 1/2' | 'rspec:windows 0 1 name'
+ 'rspec:windows 0/1' | 'rspec:windows'
+ 'rspec:windows 0/1 name' | 'rspec:windows 0/1 name'
+ 'rspec:windows 0/1 name 1/2' | 'rspec:windows 0/1 name'
+ 'rspec:windows 0:1' | 'rspec:windows'
+ 'rspec:windows 0:1 name' | 'rspec:windows 0:1 name'
+ 'rspec:windows 10000 20000' | 'rspec:windows'
+ 'rspec:windows 0 : / 1' | 'rspec:windows'
+ 'rspec:windows 0 : / 1 name' | 'rspec:windows 0 : / 1 name'
+ '0 1 name ruby' | '0 1 name ruby'
+ '0 :/ 1 name ruby' | '0 :/ 1 name ruby'
+ 'rspec: [aws]' | 'rspec'
+ 'rspec: [aws] 0/1' | 'rspec'
+ 'rspec: [aws, max memory]' | 'rspec'
+ 'rspec:linux: [aws, max memory, data]' | 'rspec:linux'
+ 'rspec: [inception: [something, other thing], value]' | 'rspec'
+ 'rspec:windows 0/1: [name, other]' | 'rspec:windows'
+ 'rspec:windows: [name, other] 0/1' | 'rspec:windows'
+ 'rspec:windows: [name, 0/1] 0/1' | 'rspec:windows'
+ 'rspec:windows: [0/1, name]' | 'rspec:windows'
+ 'rspec:windows: [, ]' | 'rspec:windows'
+ 'rspec:windows: [name]' | 'rspec:windows'
+ 'rspec:windows: [name,other]' | 'rspec:windows'
+ end
+
+ with_them do
+ it "#{params[:name]} puts in #{params[:group_name]}" do
+ commit_status.name = name
+
+ is_expected.to eq(group_name)
+ end
+ end
+ end
end
describe '#detailed_status' do
@@ -725,22 +781,6 @@ RSpec.describe CommitStatus do
let(:commit_status) { create(:commit_status) }
it { is_expected.to eq(true) }
-
- context 'when build requires a resource' do
- before do
- allow(commit_status).to receive(:requires_resource?) { true }
- end
-
- it { is_expected.to eq(false) }
- end
-
- context 'when build has a prerequisite' do
- before do
- allow(commit_status).to receive(:any_unmet_prerequisites?) { true }
- end
-
- it { is_expected.to eq(false) }
- end
end
describe '#enqueue' do
@@ -748,7 +788,6 @@ RSpec.describe CommitStatus do
before do
allow(Time).to receive(:now).and_return(current_time)
- expect(commit_status.any_unmet_prerequisites?).to eq false
end
shared_examples 'commit status enqueued' do
diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb
index 5ee3c012dc9..35b0f107676 100644
--- a/spec/models/concerns/atomic_internal_id_spec.rb
+++ b/spec/models/concerns/atomic_internal_id_spec.rb
@@ -87,6 +87,158 @@ RSpec.describe AtomicInternalId do
end
end
+ describe '#clear_scope_iid!' do
+ context 'when no ensure_if condition is given' do
+ it 'clears automatically set IIDs' do
+ expect(milestone).to receive(:clear_project_iid!).and_call_original
+
+ expect_iid_to_be_set_and_rollback(milestone)
+
+ expect(milestone.iid).to be_nil
+ end
+
+ it 'does not clear manually set IIDS' do
+ milestone.iid = external_iid
+
+ expect(milestone).to receive(:clear_project_iid!).and_call_original
+
+ expect_iid_to_be_set_and_rollback(milestone)
+
+ expect(milestone.iid).to eq(external_iid)
+ end
+ end
+
+ context 'when an ensure_if condition is given' do
+ let(:test_class) do
+ Class.new(ApplicationRecord) do
+ include AtomicInternalId
+ include Importable
+
+ self.table_name = :milestones
+
+ belongs_to :project
+
+ has_internal_id :iid, scope: :project, track_if: -> { !importing }, ensure_if: -> { !importing }
+
+ def self.name
+ 'TestClass'
+ end
+ end
+ end
+
+ let(:instance) { test_class.new(milestone.attributes) }
+
+ context 'when the ensure_if condition evaluates to true' do
+ it 'clears automatically set IIDs' do
+ expect(instance).to receive(:clear_project_iid!).and_call_original
+
+ expect_iid_to_be_set_and_rollback(instance)
+
+ expect(instance.iid).to be_nil
+ end
+
+ it 'does not clear manually set IIDs' do
+ instance.iid = external_iid
+
+ expect(instance).to receive(:clear_project_iid!).and_call_original
+
+ expect_iid_to_be_set_and_rollback(instance)
+
+ expect(instance.iid).to eq(external_iid)
+ end
+ end
+
+ context 'when the ensure_if condition evaluates to false' do
+ before do
+ instance.importing = true
+ end
+
+ it 'does not clear IIDs' do
+ instance.iid = external_iid
+
+ expect(instance).not_to receive(:clear_project_iid!)
+
+ expect_iid_to_be_set_and_rollback(instance)
+
+ expect(instance.iid).to eq(external_iid)
+ end
+ end
+ end
+
+ def expect_iid_to_be_set_and_rollback(instance)
+ ActiveRecord::Base.transaction(requires_new: true) do
+ instance.save!
+
+ expect(instance.iid).not_to be_nil
+
+ raise ActiveRecord::Rollback
+ end
+ end
+ end
+
+ describe '#validate_scope_iid_exists!' do
+ let(:test_class) do
+ Class.new(ApplicationRecord) do
+ include AtomicInternalId
+ include Importable
+
+ self.table_name = :milestones
+
+ belongs_to :project
+
+ def self.name
+ 'TestClass'
+ end
+ end
+ end
+
+ let(:instance) { test_class.new(milestone.attributes) }
+
+ before do
+ test_class.has_internal_id :iid, scope: :project, presence: presence, ensure_if: -> { !importing }
+
+ instance.importing = true
+ end
+
+ context 'when the presence flag is set' do
+ let(:presence) { true }
+
+ it 'raises an error for blank iids on create' do
+ expect do
+ instance.save!
+ end.to raise_error(described_class::MissingValueError, 'iid was unexpectedly blank!')
+ end
+
+ it 'raises an error for blank iids on update' do
+ instance.iid = 100
+ instance.save!
+
+ instance.iid = nil
+
+ expect do
+ instance.save!
+ end.to raise_error(described_class::MissingValueError, 'iid was unexpectedly blank!')
+ end
+ end
+
+ context 'when the presence flag is not set' do
+ let(:presence) { false }
+
+ it 'does not raise an error for blank iids on create' do
+ expect { instance.save! }.not_to raise_error
+ end
+
+ it 'does not raise an error for blank iids on update' do
+ instance.iid = 100
+ instance.save!
+
+ instance.iid = nil
+
+ expect { instance.save! }.not_to raise_error
+ end
+ end
+ end
+
describe '.with_project_iid_supply' do
let(:iid) { 100 }
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index 82b0c00b396..e40b0cf11ff 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -44,7 +44,6 @@ RSpec.describe BulkInsertSafe do
insecure_mode: false
default_value_for :enum_value, 'case_1'
- default_value_for :secret_value, 'my-secret'
default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
default_value_for :jsonb_value, { "key" => "value" }
@@ -53,11 +52,11 @@ RSpec.describe BulkInsertSafe do
end
def self.valid_list(count)
- Array.new(count) { |n| new(name: "item-#{n}") }
+ Array.new(count) { |n| new(name: "item-#{n}", secret_value: 'my-secret') }
end
def self.invalid_list(count)
- Array.new(count) { new }
+ Array.new(count) { new(secret_value: 'my-secret') }
end
end
end
@@ -102,7 +101,7 @@ RSpec.describe BulkInsertSafe do
context 'primary keys' do
it 'raises error if primary keys are set prior to insertion' do
- item = bulk_insert_item_class.new(name: 'valid', id: 10)
+ item = bulk_insert_item_class.new(name: 'valid', id: 10, secret_value: 'my-secret')
expect { bulk_insert_item_class.bulk_insert!([item]) }
.to raise_error(bulk_insert_item_class::PrimaryKeySetError)
diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb
index 99acc563950..b550d22f686 100644
--- a/spec/models/concerns/featurable_spec.rb
+++ b/spec/models/concerns/featurable_spec.rb
@@ -134,22 +134,6 @@ RSpec.describe Featurable do
expect(project.feature_available?(:issues, user)).to eq(true)
end
end
-
- context 'when feature is disabled by a feature flag' do
- it 'returns false' do
- stub_feature_flags(issues: false)
-
- expect(project.feature_available?(:issues, user)).to eq(false)
- end
- end
-
- context 'when feature is enabled by a feature flag' do
- it 'returns true' do
- stub_feature_flags(issues: true)
-
- expect(project.feature_available?(:issues, user)).to eq(true)
- end
- end
end
describe '#*_enabled?' do
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index ff5b270cf33..3545c8e9686 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Issuable do
include ProjectForksHelper
+ using RSpec::Parameterized::TableSyntax
let(:issuable_class) { Issue }
let(:issue) { create(:issue, title: 'An issue', description: 'A description') }
@@ -45,13 +46,17 @@ RSpec.describe Issuable do
end
it { is_expected.to validate_presence_of(:project) }
- it { is_expected.to validate_presence_of(:iid) }
it { is_expected.to validate_presence_of(:author) }
it { is_expected.to validate_presence_of(:title) }
it { is_expected.to validate_length_of(:title).is_at_most(described_class::TITLE_LENGTH_MAX) }
it { is_expected.to validate_length_of(:description).is_at_most(described_class::DESCRIPTION_LENGTH_MAX).on(:create) }
- it_behaves_like 'validates description length with custom validation'
+ it_behaves_like 'validates description length with custom validation' do
+ before do
+ allow(InternalId).to receive(:generate_next).and_call_original
+ end
+ end
+
it_behaves_like 'truncates the description to its allowed maximum length on import'
end
end
@@ -820,8 +825,6 @@ RSpec.describe Issuable do
end
describe '#supports_time_tracking?' do
- using RSpec::Parameterized::TableSyntax
-
where(:issuable_type, :supports_time_tracking) do
:issue | true
:incident | true
@@ -838,8 +841,6 @@ RSpec.describe Issuable do
end
describe '#supports_severity?' do
- using RSpec::Parameterized::TableSyntax
-
where(:issuable_type, :supports_severity) do
:issue | false
:incident | true
@@ -856,8 +857,6 @@ RSpec.describe Issuable do
end
describe '#incident?' do
- using RSpec::Parameterized::TableSyntax
-
where(:issuable_type, :incident) do
:issue | false
:incident | true
@@ -874,8 +873,6 @@ RSpec.describe Issuable do
end
describe '#supports_issue_type?' do
- using RSpec::Parameterized::TableSyntax
-
where(:issuable_type, :supports_issue_type) do
:issue | true
:merge_request | false
@@ -894,8 +891,6 @@ RSpec.describe Issuable do
subject { issuable.severity }
context 'when issuable is not an incident' do
- using RSpec::Parameterized::TableSyntax
-
where(:issuable_type, :severity) do
:issue | 'unknown'
:merge_request | 'unknown'
diff --git a/spec/models/concerns/nullify_if_blank_spec.rb b/spec/models/concerns/nullify_if_blank_spec.rb
new file mode 100644
index 00000000000..2d1bdba39dd
--- /dev/null
+++ b/spec/models/concerns/nullify_if_blank_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe NullifyIfBlank do
+ let_it_be(:model) do
+ Class.new(ApplicationRecord) do
+ include NullifyIfBlank
+
+ nullify_if_blank :name
+
+ self.table_name = 'users'
+ end
+ end
+
+ context 'attribute exists' do
+ let(:instance) { model.new(name: name) }
+
+ subject { instance.name }
+
+ before do
+ instance.validate
+ end
+
+ context 'attribute is blank' do
+ let(:name) { '' }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'attribute is nil' do
+ let(:name) { nil }
+
+ it { is_expected.to be_nil}
+ end
+
+ context 'attribute is not blank' do
+ let(:name) { 'name' }
+
+ it { is_expected.to eq('name') }
+ end
+ end
+
+ context 'attribute does not exist' do
+ before do
+ model.table_name = 'issues'
+ end
+
+ it { expect { model.new.valid? }.to raise_error(ActiveModel::UnknownAttributeError) }
+ end
+end
diff --git a/spec/models/concerns/protected_ref_spec.rb b/spec/models/concerns/protected_ref_spec.rb
new file mode 100644
index 00000000000..0a020736269
--- /dev/null
+++ b/spec/models/concerns/protected_ref_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProtectedRef do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user, maintainer_projects: [project]) }
+
+ where(:klass, :factory, :action) do
+ ProtectedBranch | :protected_branch | :push
+ ProtectedTag | :protected_tag | :create
+ end
+
+ with_them do
+ describe '#protected_ref_accessible_to?' do
+ subject do
+ klass.protected_ref_accessible_to?('release', user, project: project, action: action)
+ end
+
+ it 'user cannot do action if rules do not exist' do
+ is_expected.to be_falsy
+ end
+
+ context 'the ref is protected' do
+ let!(:default_rule) { create(factory, :"developers_can_#{action}", project: project, name: 'release') }
+
+ context 'all rules permit action' do
+ let!(:maintainers_can) { create(factory, :"maintainers_can_#{action}", project: project, name: 'release*') }
+
+ it 'user can do action' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'one of the rules forbids action' do
+ let!(:no_one_can) { create(factory, :"no_one_can_#{action}", project: project, name: 'release*') }
+
+ it 'user cannot do action' do
+ is_expected.to be_falsy
+ end
+ end
+ end
+ end
+
+ describe '#developers_can?' do
+ subject do
+ klass.developers_can?(action, 'release')
+ end
+
+ it 'developers cannot do action if rules do not exist' do
+ is_expected.to be_falsy
+ end
+
+ context 'the ref is protected' do
+ let!(:default_rule) { create(factory, :"developers_can_#{action}", project: project, name: 'release') }
+
+ context 'all rules permit developers to do action' do
+ let!(:developers_can) { create(factory, :"developers_can_#{action}", project: project, name: 'release*') }
+
+ it 'developers can do action' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'one of the rules forbids developers to do action' do
+ let!(:maintainers_can) { create(factory, :"maintainers_can_#{action}", project: project, name: 'release*') }
+
+ it 'developers cannot do action' do
+ is_expected.to be_falsy
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/spammable_spec.rb b/spec/models/concerns/spammable_spec.rb
index d4fcb2e99eb..3c5f3b2d2ad 100644
--- a/spec/models/concerns/spammable_spec.rb
+++ b/spec/models/concerns/spammable_spec.rb
@@ -120,6 +120,61 @@ RSpec.describe Spammable do
end
end
+ describe '#render_recaptcha?' do
+ before do
+ allow(Gitlab::Recaptcha).to receive(:enabled?) { recaptcha_enabled }
+ end
+
+ context 'when recaptcha is not enabled' do
+ let(:recaptcha_enabled) { false }
+
+ it 'returns false' do
+ expect(issue.render_recaptcha?).to eq(false)
+ end
+ end
+
+ context 'when recaptcha is enabled' do
+ let(:recaptcha_enabled) { true }
+
+ context 'when there are two or more errors' do
+ before do
+ issue.errors.add(:base, 'a spam error')
+ issue.errors.add(:base, 'some other error')
+ end
+
+ it 'returns false' do
+ expect(issue.render_recaptcha?).to eq(false)
+ end
+ end
+
+ context 'when there are less than two errors' do
+ before do
+ issue.errors.add(:base, 'a spam error')
+ end
+
+ context 'when spammable does not need recaptcha' do
+ before do
+ issue.needs_recaptcha = false
+ end
+
+ it 'returns false' do
+ expect(issue.render_recaptcha?).to eq(false)
+ end
+ end
+
+ context 'when spammable needs recaptcha' do
+ before do
+ issue.needs_recaptcha!
+ end
+
+ it 'returns false' do
+ expect(issue.render_recaptcha?).to eq(true)
+ end
+ end
+ end
+ end
+ end
+
describe '#clear_spam_flags!' do
it 'clears spam and recaptcha flags' do
issue.spam = true
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index d8b77e1cd0d..2df76684d71 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe ApplicationSetting, 'TokenAuthenticatable' do
it 'persists new token as an encrypted string' do
expect(subject).to eq settings.reload.runners_registration_token
expect(settings.read_attribute('runners_registration_token_encrypted'))
- .to eq Gitlab::CryptoHelper.aes256_gcm_encrypt(subject)
+ .to eq Gitlab::CryptoHelper.aes256_gcm_encrypt(subject, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
expect(settings).to be_persisted
end
@@ -243,7 +243,7 @@ RSpec.describe Ci::Build, 'TokenAuthenticatable' do
it 'persists new token as an encrypted string' do
build.ensure_token!
- encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(build.token)
+ encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(build.token, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC)
expect(build.read_attribute('token_encrypted')).to eq encrypted
end
diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
index f6b8cf7def4..1e1cd97e410 100644
--- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
+++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
@@ -68,6 +68,10 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
context 'when using optional strategy' do
let(:options) { { encrypted: :optional } }
+ before do
+ stub_feature_flags(dynamic_nonce_creation: false)
+ end
+
it 'returns decrypted token when an encrypted token is present' do
allow(instance).to receive(:read_attribute)
.with('some_field_encrypted')
@@ -124,7 +128,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
it 'writes encrypted token and removes plaintext token and returns it' do
expect(instance).to receive(:[]=)
- .with('some_field_encrypted', encrypted)
+ .with('some_field_encrypted', any_args)
expect(instance).to receive(:[]=)
.with('some_field', nil)
@@ -137,7 +141,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do
it 'writes encrypted token and writes plaintext token' do
expect(instance).to receive(:[]=)
- .with('some_field_encrypted', encrypted)
+ .with('some_field_encrypted', any_args)
expect(instance).to receive(:[]=)
.with('some_field', 'my-value')
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 5bc61db6d21..68d12f51d4b 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -254,26 +254,6 @@ RSpec.describe Deployment do
deployment.send(event)
end
-
- context 'the feature is disabled' do
- it 'does not trigger a worker' do
- stub_feature_flags(jira_sync_deployments: false)
-
- expect(worker).not_to receive(:perform_async)
-
- deployment.send(event)
- end
- end
-
- context 'the feature is enabled for this project' do
- it 'does trigger a worker' do
- stub_feature_flags(jira_sync_deployments: deployment.project)
-
- expect(worker).to receive(:perform_async)
-
- deployment.send(event)
- end
- end
end
end
end
@@ -416,6 +396,26 @@ RSpec.describe Deployment do
end
end
+ describe '.finished_before' do
+ let!(:deployment1) { create(:deployment, finished_at: 1.day.ago) }
+ let!(:deployment2) { create(:deployment, finished_at: Time.current) }
+
+ it 'filters deployments by finished_at' do
+ expect(described_class.finished_before(1.hour.ago))
+ .to eq([deployment1])
+ end
+ end
+
+ describe '.finished_after' do
+ let!(:deployment1) { create(:deployment, finished_at: 1.day.ago) }
+ let!(:deployment2) { create(:deployment, finished_at: Time.current) }
+
+ it 'filters deployments by finished_at' do
+ expect(described_class.finished_after(1.hour.ago))
+ .to eq([deployment2])
+ end
+ end
+
describe 'with_deployable' do
subject { described_class.with_deployable }
@@ -428,22 +428,6 @@ RSpec.describe Deployment do
end
end
- describe 'finished_between' do
- subject { described_class.finished_between(start_time, end_time) }
-
- let_it_be(:start_time) { DateTime.new(2017) }
- let_it_be(:end_time) { DateTime.new(2019) }
- let_it_be(:deployment_2016) { create(:deployment, finished_at: DateTime.new(2016)) }
- let_it_be(:deployment_2017) { create(:deployment, finished_at: DateTime.new(2017)) }
- let_it_be(:deployment_2018) { create(:deployment, finished_at: DateTime.new(2018)) }
- let_it_be(:deployment_2019) { create(:deployment, finished_at: DateTime.new(2019)) }
- let_it_be(:deployment_2020) { create(:deployment, finished_at: DateTime.new(2020)) }
-
- it 'retrieves deployments that finished between the specified times' do
- is_expected.to contain_exactly(deployment_2017, deployment_2018)
- end
- end
-
describe 'visible' do
subject { described_class.visible }
diff --git a/spec/models/design_management/design_spec.rb b/spec/models/design_management/design_spec.rb
index d3ce2f2d48f..674d2fc420d 100644
--- a/spec/models/design_management/design_spec.rb
+++ b/spec/models/design_management/design_spec.rb
@@ -629,25 +629,4 @@ RSpec.describe DesignManagement::Design do
end
end
end
-
- describe '#immediately_before' do
- let_it_be(:design) { create(:design, issue: issue, relative_position: 100) }
- let_it_be(:next_design) { create(:design, issue: issue, relative_position: 200) }
-
- it 'is true when there is no element positioned between this item and the next' do
- expect(design.immediately_before?(next_design)).to be true
- end
-
- it 'is false when there is an element positioned between this item and the next' do
- create(:design, issue: issue, relative_position: 150)
-
- expect(design.immediately_before?(next_design)).to be false
- end
-
- it 'is false when the next design is to the left of this design' do
- further_left = create(:design, issue: issue, relative_position: 50)
-
- expect(design.immediately_before?(further_left)).to be false
- end
- end
end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 47492715c11..47148c4febc 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -744,13 +744,19 @@ RSpec.describe Event do
describe '#wiki_page and #wiki_page?' do
context 'for a wiki page event' do
- let(:wiki_page) do
- create(:wiki_page, project: project)
- end
+ let(:wiki_page) { create(:wiki_page, project: project) }
subject(:event) { create(:wiki_page_event, project: project, wiki_page: wiki_page) }
it { is_expected.to have_attributes(wiki_page?: be_truthy, wiki_page: wiki_page) }
+
+ context 'title is empty' do
+ before do
+ expect(event.target).to receive(:canonical_slug).and_return('')
+ end
+
+ it { is_expected.to have_attributes(wiki_page?: be_truthy, wiki_page: nil) }
+ end
end
context 'for any other event' do
@@ -907,6 +913,58 @@ RSpec.describe Event do
end
end
+ context 'with snippet note' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:note_on_project_snippet) { create(:note_on_project_snippet, author: user) }
+ let_it_be(:note_on_personal_snippet) { create(:note_on_personal_snippet, author: user) }
+ let_it_be(:other_note) { create(:note_on_issue, author: user)}
+ let_it_be(:personal_snippet_event) { create(:event, :commented, project: nil, target: note_on_personal_snippet, author: user) }
+ let_it_be(:project_snippet_event) { create(:event, :commented, project: note_on_project_snippet.project, target: note_on_project_snippet, author: user) }
+ let_it_be(:other_event) { create(:event, :commented, project: other_note.project, target: other_note, author: user) }
+
+ describe '#snippet_note?' do
+ it 'returns true for a project snippet event' do
+ expect(project_snippet_event.snippet_note?).to be true
+ end
+
+ it 'returns true for a personal snippet event' do
+ expect(personal_snippet_event.snippet_note?).to be true
+ end
+
+ it 'returns false for a other kinds of event' do
+ expect(other_event.snippet_note?).to be false
+ end
+ end
+
+ describe '#personal_snippet_note?' do
+ it 'returns false for a project snippet event' do
+ expect(project_snippet_event.personal_snippet_note?).to be false
+ end
+
+ it 'returns true for a personal snippet event' do
+ expect(personal_snippet_event.personal_snippet_note?).to be true
+ end
+
+ it 'returns false for a other kinds of event' do
+ expect(other_event.personal_snippet_note?).to be false
+ end
+ end
+
+ describe '#project_snippet_note?' do
+ it 'returns true for a project snippet event' do
+ expect(project_snippet_event.project_snippet_note?).to be true
+ end
+
+ it 'returns false for a personal snippet event' do
+ expect(personal_snippet_event.project_snippet_note?).to be false
+ end
+
+ it 'returns false for a other kinds of event' do
+ expect(other_event.project_snippet_note?).to be false
+ end
+ end
+ end
+
describe '#action_name' do
it 'handles all valid design events' do
created, updated, destroyed, archived = %i[created updated destroyed archived].map do |trait|
diff --git a/spec/models/experiment_spec.rb b/spec/models/experiment_spec.rb
index 171bfd116d3..22bbf2df8fd 100644
--- a/spec/models/experiment_spec.rb
+++ b/spec/models/experiment_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Experiment do
+ include AfterNextHelpers
+
subject { build(:experiment) }
describe 'associations' do
@@ -67,6 +69,33 @@ RSpec.describe Experiment do
end
end
+ describe '.add_group' do
+ let_it_be(:experiment_name) { :experiment_key }
+ let_it_be(:variant) { :control }
+ let_it_be(:group) { build(:group) }
+
+ subject(:add_group) { described_class.add_group(experiment_name, variant: variant, group: group) }
+
+ context 'when an experiment with the provided name does not exist' do
+ it 'creates a new experiment record' do
+ allow_next(described_class, name: :experiment_key)
+ .to receive(:record_group_and_variant!).with(group, variant)
+
+ expect { add_group }.to change(described_class, :count).by(1)
+ end
+ end
+
+ context 'when an experiment with the provided name already exists' do
+ before do
+ create(:experiment, name: experiment_name)
+ end
+
+ it 'does not create a new experiment record' do
+ expect { add_group }.not_to change(described_class, :count)
+ end
+ end
+ end
+
describe '.record_conversion_event' do
let_it_be(:user) { build(:user) }
@@ -136,6 +165,34 @@ RSpec.describe Experiment do
end
end
+ describe '#record_group_and_variant!' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:variant) { :control }
+ let_it_be(:experiment) { create(:experiment) }
+
+ subject(:record_group_and_variant!) { experiment.record_group_and_variant!(group, variant) }
+
+ context 'when no existing experiment_subject record exists for the given group' do
+ it 'creates an experiment_subject record' do
+ expect_next(ExperimentSubject).to receive(:update!).with(variant: variant).and_call_original
+
+ expect { record_group_and_variant! }.to change(ExperimentSubject, :count).by(1)
+ end
+ end
+
+ context 'when an existing experiment_subject exists for the given group' do
+ context 'but it belonged to a different variant' do
+ let!(:experiment_subject) do
+ create(:experiment_subject, experiment: experiment, group: group, user: nil, variant: :experimental)
+ end
+
+ it 'updates the variant value' do
+ expect { record_group_and_variant! }.to change { experiment_subject.reload.variant }.to('control')
+ end
+ end
+ end
+ end
+
describe '#record_user_and_group' do
let_it_be(:experiment) { create(:experiment) }
let_it_be(:user) { create(:user) }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 0acf2b96b74..e79b54b4674 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -32,6 +32,7 @@ RSpec.describe Group do
it { is_expected.to have_many(:dependency_proxy_blobs) }
it { is_expected.to have_many(:dependency_proxy_manifests) }
it { is_expected.to have_many(:debian_distributions).class_name('Packages::Debian::GroupDistribution').dependent(:destroy) }
+ it { is_expected.to have_many(:daily_build_group_report_results).class_name('Ci::DailyBuildGroupReportResult') }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -410,7 +411,7 @@ RSpec.describe Group do
it "is false if avatar is html page" do
group.update_attribute(:avatar, 'uploads/avatar.html')
- expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico"])
+ expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp"])
end
end
@@ -1492,6 +1493,28 @@ RSpec.describe Group do
end
end
+ describe '.preset_root_ancestor_for' do
+ let_it_be(:rootgroup, reload: true) { create(:group) }
+ let_it_be(:subgroup, reload: true) { create(:group, parent: rootgroup) }
+ let_it_be(:subgroup2, reload: true) { create(:group, parent: subgroup) }
+
+ it 'does noting for single group' do
+ expect(subgroup).not_to receive(:self_and_ancestors)
+
+ described_class.preset_root_ancestor_for([subgroup])
+ end
+
+ it 'sets the same root_ancestor for multiple groups' do
+ expect(subgroup).not_to receive(:self_and_ancestors)
+ expect(subgroup2).not_to receive(:self_and_ancestors)
+
+ described_class.preset_root_ancestor_for([rootgroup, subgroup, subgroup2])
+
+ expect(subgroup.root_ancestor).to eq(rootgroup)
+ expect(subgroup2.root_ancestor).to eq(rootgroup)
+ end
+ end
+
def subject_and_reload(*models)
subject
models.map(&:reload)
@@ -1756,19 +1779,6 @@ RSpec.describe Group do
describe 'with Debian Distributions' do
subject { create(:group) }
- let!(:distributions) { create_list(:debian_group_distribution, 2, :with_file, container: subject) }
-
- it 'removes distribution files on removal' do
- distribution_file_paths = distributions.map do |distribution|
- distribution.file.path
- end
-
- expect { subject.destroy }
- .to change {
- distribution_file_paths.select do |path|
- File.exist? path
- end.length
- }.from(distribution_file_paths.length).to(0)
- end
+ it_behaves_like 'model with Debian distributions'
end
end
diff --git a/spec/models/issue_link_spec.rb b/spec/models/issue_link_spec.rb
index ef41108ebea..433b51b8a70 100644
--- a/spec/models/issue_link_spec.rb
+++ b/spec/models/issue_link_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe IssueLink do
end
describe 'link_type' do
- it { is_expected.to define_enum_for(:link_type).with_values(relates_to: 0, blocks: 1, is_blocked_by: 2) }
+ it { is_expected.to define_enum_for(:link_type).with_values(relates_to: 0, blocks: 1) }
it 'provides the "related" as default link_type' do
expect(create(:issue_link).link_type).to eq 'relates_to'
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 81f045b4db1..969d897e551 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -1244,9 +1244,7 @@ RSpec.describe Issue do
end
describe '#allows_reviewers?' do
- it 'returns false as issues do not support reviewers feature' do
- stub_feature_flags(merge_request_reviewers: true)
-
+ it 'returns false as we do not support reviewers on issues yet' do
issue = build_stubbed(:issue)
expect(issue.allows_reviewers?).to be(false)
diff --git a/spec/models/license_template_spec.rb b/spec/models/license_template_spec.rb
index 515f728f515..fe06d1a357c 100644
--- a/spec/models/license_template_spec.rb
+++ b/spec/models/license_template_spec.rb
@@ -57,6 +57,6 @@ RSpec.describe LicenseTemplate do
end
def build_template(content)
- described_class.new(key: 'foo', name: 'foo', category: :Other, content: content)
+ described_class.new(key: 'foo', name: 'foo', project: nil, category: :Other, content: content)
end
end
diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb
index 760eaf1ac7f..13ff239a306 100644
--- a/spec/models/merge_request/metrics_spec.rb
+++ b/spec/models/merge_request/metrics_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe MergeRequest::Metrics do
describe 'associations' do
it { is_expected.to belong_to(:merge_request) }
+ it { is_expected.to belong_to(:target_project).class_name('Project') }
it { is_expected.to belong_to(:latest_closed_by).class_name('User') }
it { is_expected.to belong_to(:merged_by).class_name('User') }
end
@@ -36,5 +37,15 @@ RSpec.describe MergeRequest::Metrics do
is_expected.not_to include([metrics_2])
end
end
+
+ describe '.by_target_project' do
+ let(:target_project) { metrics_1.target_project }
+
+ subject { described_class.by_target_project(target_project) }
+
+ it 'finds metrics record with the associated target project' do
+ is_expected.to eq([metrics_1])
+ end
+ end
end
end
diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb
index 2edf44ecdc4..a24628b0f9d 100644
--- a/spec/models/merge_request_diff_commit_spec.rb
+++ b/spec/models/merge_request_diff_commit_spec.rb
@@ -48,7 +48,8 @@ RSpec.describe MergeRequestDiffCommit do
"committer_email": "dmitriy.zaporozhets@gmail.com",
"merge_request_diff_id": merge_request_diff_id,
"relative_order": 0,
- "sha": Gitlab::Database::ShaAttribute.serialize("5937ac0a7beb003549fc5fd26fc247adbce4a52e")
+ "sha": Gitlab::Database::ShaAttribute.serialize("5937ac0a7beb003549fc5fd26fc247adbce4a52e"),
+ "trailers": {}.to_json
},
{
"message": "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets \u003cdmitriy.zaporozhets@gmail.com\u003e\n",
@@ -60,7 +61,8 @@ RSpec.describe MergeRequestDiffCommit do
"committer_email": "dmitriy.zaporozhets@gmail.com",
"merge_request_diff_id": merge_request_diff_id,
"relative_order": 1,
- "sha": Gitlab::Database::ShaAttribute.serialize("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
+ "sha": Gitlab::Database::ShaAttribute.serialize("570e7b2abdd848b95f2f578043fc23bd6f6fd24d"),
+ "trailers": {}.to_json
}
]
end
@@ -92,7 +94,8 @@ RSpec.describe MergeRequestDiffCommit do
"committer_email": "alejorro70@gmail.com",
"merge_request_diff_id": merge_request_diff_id,
"relative_order": 0,
- "sha": Gitlab::Database::ShaAttribute.serialize("ba3343bc4fa403a8dfbfcab7fc1a8c29ee34bd69")
+ "sha": Gitlab::Database::ShaAttribute.serialize("ba3343bc4fa403a8dfbfcab7fc1a8c29ee34bd69"),
+ "trailers": {}.to_json
}]
end
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index a5493d1650b..5b11a7bf079 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -16,6 +16,8 @@ RSpec.describe MergeRequestDiff do
describe 'validations' do
subject { diff_with_commits }
+ it { is_expected.not_to validate_uniqueness_of(:diff_type).scoped_to(:merge_request_id) }
+
it 'checks sha format of base_commit_sha, head_commit_sha and start_commit_sha' do
subject.base_commit_sha = subject.head_commit_sha = subject.start_commit_sha = 'foobar'
@@ -23,6 +25,24 @@ RSpec.describe MergeRequestDiff do
expect(subject.errors.count).to eq 3
expect(subject.errors).to all(include('is not a valid SHA'))
end
+
+ it 'does not validate uniqueness by default' do
+ expect(build(:merge_request_diff, merge_request: subject.merge_request)).to be_valid
+ end
+
+ context 'when merge request diff is a merge_head type' do
+ it 'is valid' do
+ expect(build(:merge_request_diff, :merge_head, merge_request: subject.merge_request)).to be_valid
+ end
+
+ context 'when merge_head diff exists' do
+ let(:existing_merge_head_diff) { create(:merge_request_diff, :merge_head) }
+
+ it 'validates uniqueness' do
+ expect(build(:merge_request_diff, :merge_head, merge_request: existing_merge_head_diff.merge_request)).not_to be_valid
+ end
+ end
+ end
end
describe 'create new record' do
@@ -35,12 +55,32 @@ RSpec.describe MergeRequestDiff do
it { expect(subject.head_commit_sha).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') }
it { expect(subject.base_commit_sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') }
it { expect(subject.start_commit_sha).to eq('0b4bc9a49b562e85de7cc9e834518ea6828729b9') }
+
+ context 'when diff_type is merge_head' do
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ let_it_be(:merge_head) do
+ MergeRequests::MergeToRefService
+ .new(merge_request.project, merge_request.author)
+ .execute(merge_request)
+
+ merge_request.create_merge_head_diff
+ end
+
+ it { expect(merge_head).to be_valid }
+ it { expect(merge_head).to be_persisted }
+ it { expect(merge_head.commits.count).to eq(30) }
+ it { expect(merge_head.diffs.count).to eq(20) }
+ it { expect(merge_head.head_commit_sha).to eq(merge_request.merge_ref_head.diff_refs.head_sha) }
+ it { expect(merge_head.base_commit_sha).to eq(merge_request.merge_ref_head.diff_refs.base_sha) }
+ it { expect(merge_head.start_commit_sha).to eq(merge_request.target_branch_sha) }
+ end
end
describe '.by_commit_sha' do
subject(:by_commit_sha) { described_class.by_commit_sha(sha) }
- let!(:merge_request) { create(:merge_request, :with_diffs) }
+ let!(:merge_request) { create(:merge_request) }
context 'with sha contained in' do
let(:sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
@@ -63,6 +103,7 @@ RSpec.describe MergeRequestDiff do
let_it_be(:merge_request) { create(:merge_request) }
let_it_be(:outdated) { merge_request.merge_request_diff }
let_it_be(:latest) { merge_request.create_merge_request_diff }
+ let_it_be(:merge_head) { merge_request.create_merge_head_diff }
let_it_be(:closed_mr) { create(:merge_request, :closed_last_month) }
let(:closed) { closed_mr.merge_request_diff }
@@ -103,14 +144,14 @@ RSpec.describe MergeRequestDiff do
stub_external_diffs_setting(enabled: true)
end
- it { is_expected.to contain_exactly(outdated.id, latest.id, closed.id, merged.id, closed_recently.id, merged_recently.id) }
+ it { is_expected.to contain_exactly(outdated.id, latest.id, closed.id, merged.id, closed_recently.id, merged_recently.id, merge_head.id) }
it 'ignores diffs with 0 files' do
MergeRequestDiffFile.where(merge_request_diff_id: [closed_recently.id, merged_recently.id]).delete_all
closed_recently.update!(files_count: 0)
merged_recently.update!(files_count: 0)
- is_expected.to contain_exactly(outdated.id, latest.id, closed.id, merged.id)
+ is_expected.to contain_exactly(outdated.id, latest.id, closed.id, merged.id, merge_head.id)
end
end
@@ -317,7 +358,7 @@ RSpec.describe MergeRequestDiff do
end
describe '#latest?' do
- let!(:mr) { create(:merge_request, :with_diffs) }
+ let!(:mr) { create(:merge_request) }
let!(:first_diff) { mr.merge_request_diff }
let!(:last_diff) { mr.create_merge_request_diff }
@@ -326,7 +367,7 @@ RSpec.describe MergeRequestDiff do
end
shared_examples_for 'merge request diffs' do
- let(:merge_request) { create(:merge_request, :with_diffs) }
+ let(:merge_request) { create(:merge_request) }
let!(:diff) { merge_request.merge_request_diff.reload }
context 'when it was not cleaned by the system' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 1cf197322f5..ebe2cd2ac03 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -271,8 +271,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
stub_feature_flags(stricter_mr_branch_name: false)
end
- using RSpec::Parameterized::TableSyntax
-
where(:branch_name, :valid) do
'foo' | true
'foo:bar' | false
@@ -367,7 +365,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe '.by_commit_sha' do
subject(:by_commit_sha) { described_class.by_commit_sha(sha) }
- let!(:merge_request) { create(:merge_request, :with_diffs) }
+ let!(:merge_request) { create(:merge_request) }
context 'with sha contained in latest merge request diff' do
let(:sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
@@ -433,7 +431,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'when commit is a part of the merge request' do
- let!(:merge_request) { create(:merge_request, :with_diffs) }
+ let!(:merge_request) { create(:merge_request) }
let(:sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
it { is_expected.to eq([merge_request]) }
@@ -451,6 +449,17 @@ RSpec.describe MergeRequest, factory_default: :keep do
it { is_expected.to be_empty }
end
+
+ context 'when commit is part of the merge request and a squash commit at the same time' do
+ let!(:merge_request) { create(:merge_request) }
+ let(:sha) { merge_request.commits.first.id }
+
+ before do
+ merge_request.update!(squash_commit_sha: sha)
+ end
+
+ it { is_expected.to eq([merge_request]) }
+ end
end
describe '.by_cherry_pick_sha' do
@@ -480,6 +489,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
create(:merge_request, params).tap do |mr|
diffs.times { mr.merge_request_diffs.create }
+ mr.create_merge_head_diff
end
end
@@ -705,6 +715,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'when external issue tracker is enabled' do
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, source_project: project) }
+
before do
subject.project.has_external_issue_tracker = true
subject.project.save!
@@ -754,9 +768,8 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'when both internal and external issue trackers are enabled' do
before do
- subject.project.has_external_issue_tracker = true
- subject.project.save!
create(:jira_service, project: subject.project)
+ subject.project.reload
end
it 'does not cache issues from external trackers' do
@@ -779,6 +792,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'when only external issue tracker enabled' do
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, source_project: project) }
+
before do
subject.project.has_external_issue_tracker = true
subject.project.issues_enabled = false
@@ -808,7 +825,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:last_branch_commit) { subject.source_project.repository.commit(Gitlab::Git::BRANCH_REF_PREFIX + subject.source_branch) }
context 'with diffs' do
- subject { create(:merge_request, :with_diffs) }
+ subject { create(:merge_request) }
it 'returns the sha of the source branch last commit' do
expect(subject.source_branch_sha).to eq(last_branch_commit.sha)
@@ -875,7 +892,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
let(:options) { { paths: ['a/b', 'b/a', 'c/*'] } }
context 'when there are MR diffs' do
- let(:merge_request) { create(:merge_request, :with_diffs) }
+ let(:merge_request) { create(:merge_request) }
it 'delegates to the MR diffs' do
expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(options)
@@ -924,7 +941,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe '#note_positions_for_paths' do
let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request, :with_diffs) }
+ let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.project }
let!(:diff_note) do
create(:diff_note_on_merge_request, project: project, noteable: merge_request)
@@ -1263,7 +1280,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe '#issues_mentioned_but_not_closing' do
let(:closing_issue) { create :issue, project: subject.project }
let(:mentioned_issue) { create :issue, project: subject.project }
-
let(:commit) { double('commit', safe_message: "Fixes #{closing_issue.to_reference}") }
it 'detects issues mentioned in description but not closed' do
@@ -1279,13 +1295,12 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'when the project has an external issue tracker' do
- subject { create(:merge_request, source_project: create(:project, :repository)) }
-
before do
subject.project.add_developer(subject.author)
commit = double(:commit, safe_message: 'Fixes TEST-3')
create(:jira_service, project: subject.project)
+ subject.project.reload
allow(subject).to receive(:commits).and_return([commit])
allow(subject).to receive(:description).and_return('Is related to TEST-2 and TEST-3')
@@ -1645,7 +1660,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it_behaves_like 'an editable mentionable' do
- subject { create(:merge_request, :simple) }
+ subject { create(:merge_request, :simple, source_project: create(:project, :repository)) }
let(:backref_text) { "merge request #{subject.to_reference}" }
let(:set_mentionable_text) { ->(txt) { subject.description = txt } }
@@ -1971,6 +1986,30 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#has_codequality_mr_diff_report?' do
+ subject { merge_request.has_codequality_mr_diff_report? }
+
+ context 'when head pipeline has codequality mr diff report' do
+ let(:merge_request) { create(:merge_request, :with_codequality_mr_diff_reports) }
+
+ it { is_expected.to be_truthy }
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(codequality_mr_diff: false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when head pipeline does not have codeqquality mr diff report' do
+ let(:merge_request) { create(:merge_request) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
describe '#has_codequality_reports?' do
subject { merge_request.has_codequality_reports? }
@@ -1983,7 +2022,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'when feature flag is disabled' do
before do
- stub_feature_flags(codequality_mr_diff: false)
+ stub_feature_flags(codequality_backend_comparison: false)
end
it { is_expected.to be_falsey }
@@ -2015,6 +2054,50 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#has_sast_reports?' do
+ subject { merge_request.has_sast_reports? }
+
+ let(:project) { create(:project, :repository) }
+
+ before do
+ stub_licensed_features(sast: true)
+ end
+
+ context 'when head pipeline has sast reports' do
+ let(:merge_request) { create(:merge_request, :with_sast_reports, source_project: project) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when head pipeline does not have sast reports' do
+ let(:merge_request) { create(:merge_request, source_project: project) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#has_secret_detection_reports?' do
+ subject { merge_request.has_secret_detection_reports? }
+
+ let(:project) { create(:project, :repository) }
+
+ before do
+ stub_licensed_features(secret_detection: true)
+ end
+
+ context 'when head pipeline has secret detection reports' do
+ let(:merge_request) { create(:merge_request, :with_secret_detection_reports, source_project: project) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when head pipeline does not have secrets detection reports' do
+ let(:merge_request) { create(:merge_request, source_project: project) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
describe '#calculate_reactive_cache' do
let(:merge_request) { create(:merge_request) }
@@ -2144,6 +2227,54 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#find_codequality_mr_diff_reports' do
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, :with_codequality_mr_diff_reports, source_project: project) }
+ let(:pipeline) { merge_request.head_pipeline }
+
+ subject(:mr_diff_report) { merge_request.find_codequality_mr_diff_reports }
+
+ context 'when head pipeline has coverage reports' do
+ context 'when reactive cache worker is parsing results asynchronously' do
+ it 'returns status' do
+ expect(mr_diff_report[:status]).to eq(:parsing)
+ end
+ end
+
+ context 'when reactive cache worker is inline' do
+ before do
+ synchronous_reactive_cache(merge_request)
+ end
+
+ it 'returns status and data' do
+ expect(mr_diff_report[:status]).to eq(:parsed)
+ end
+
+ context 'when an error occurrs' do
+ before do
+ merge_request.update!(head_pipeline: nil)
+ end
+
+ it 'returns an error message' do
+ expect(mr_diff_report[:status]).to eq(:error)
+ end
+ end
+
+ context 'when cached results is not latest' do
+ before do
+ allow_next_instance_of(Ci::GenerateCodequalityMrDiffReportService) do |service|
+ allow(service).to receive(:latest?).and_return(false)
+ end
+ end
+
+ it 'raises and InvalidateReactiveCache error' do
+ expect { mr_diff_report }.to raise_error(ReactiveCaching::InvalidateReactiveCache)
+ end
+ end
+ end
+ end
+ end
+
describe '#compare_test_reports' do
subject { merge_request.compare_test_reports }
@@ -2765,8 +2896,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'with skip_ci_check option' do
- using RSpec::Parameterized::TableSyntax
-
before do
allow(subject).to receive_messages(check_mergeability: nil,
can_be_merged?: true,
@@ -2790,8 +2919,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'with skip_discussions_check option' do
- using RSpec::Parameterized::TableSyntax
-
before do
allow(subject).to receive_messages(mergeable_ci_state?: true,
check_mergeability: nil,
@@ -3345,6 +3472,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
context 'when resolve_outdated_diff_discussions is set' do
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, source_project: project) }
+
before do
discussion
@@ -3365,7 +3496,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe '#branch_merge_base_commit' do
let(:project) { create(:project, :repository) }
- subject { create(:merge_request, :with_diffs, source_project: project) }
+ subject { create(:merge_request, source_project: project) }
context 'source and target branch exist' do
it { expect(subject.branch_merge_base_commit.sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') }
@@ -3388,7 +3519,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context "with diffs" do
let(:project) { create(:project, :repository) }
- subject { create(:merge_request, :with_diffs, source_project: project) }
+ subject { create(:merge_request, source_project: project) }
let(:expected_diff_refs) do
Gitlab::Diff::DiffRefs.new(
@@ -3792,7 +3923,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe '#fetch_ref!' do
let(:project) { create(:project, :repository) }
- subject { create(:merge_request, :with_diffs, source_project: project) }
+ subject { create(:merge_request, source_project: project) }
it 'fetches the ref correctly' do
expect { subject.target_project.repository.delete_refs(subject.ref_path) }.not_to raise_error
@@ -4367,37 +4498,41 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
describe '#diffable_merge_ref?' do
+ let(:merge_request) { create(:merge_request) }
+
context 'merge request can be merged' do
- context 'merge_to_ref is not calculated' do
+ context 'merge_head diff is not created' do
it 'returns true' do
- expect(subject.diffable_merge_ref?).to eq(false)
+ expect(merge_request.diffable_merge_ref?).to eq(false)
end
end
- context 'merge_to_ref is calculated' do
+ context 'merge_head diff is created' do
before do
- MergeRequests::MergeToRefService.new(subject.project, subject.author).execute(subject)
+ create(:merge_request_diff, :merge_head, merge_request: merge_request)
end
it 'returns true' do
- expect(subject.diffable_merge_ref?).to eq(true)
+ expect(merge_request.diffable_merge_ref?).to eq(true)
end
context 'merge request is merged' do
- subject { build_stubbed(:merge_request, :merged, project: project) }
+ before do
+ merge_request.mark_as_merged!
+ end
it 'returns false' do
- expect(subject.diffable_merge_ref?).to eq(false)
+ expect(merge_request.diffable_merge_ref?).to eq(false)
end
end
context 'merge request cannot be merged' do
before do
- subject.mark_as_unchecked!
+ merge_request.mark_as_unchecked!
end
it 'returns false' do
- expect(subject.diffable_merge_ref?).to eq(true)
+ expect(merge_request.diffable_merge_ref?).to eq(true)
end
context 'display_merge_conflicts_in_diff is disabled' do
@@ -4406,7 +4541,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it 'returns false' do
- expect(subject.diffable_merge_ref?).to eq(false)
+ expect(merge_request.diffable_merge_ref?).to eq(false)
end
end
end
@@ -4476,17 +4611,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
describe '#allows_reviewers?' do
- it 'returns false without merge_request_reviewers feature' do
- stub_feature_flags(merge_request_reviewers: false)
-
- merge_request = build_stubbed(:merge_request)
-
- expect(merge_request.allows_reviewers?).to be(false)
- end
-
- it 'returns true with merge_request_reviewers feature' do
- stub_feature_flags(merge_request_reviewers: true)
-
+ it 'returns true' do
merge_request = build_stubbed(:merge_request)
expect(merge_request.allows_reviewers?).to be(true)
@@ -4506,4 +4631,34 @@ RSpec.describe MergeRequest, factory_default: :keep do
.from(nil).to(ref)
end
end
+
+ describe '#enabled_reports' do
+ let(:project) { create(:project, :repository) }
+
+ where(:report_type, :with_reports, :feature) do
+ :sast | :with_sast_reports | :sast
+ :secret_detection | :with_secret_detection_reports | :secret_detection
+ end
+
+ with_them do
+ subject { merge_request.enabled_reports[report_type] }
+
+ before do
+ stub_feature_flags(drop_license_management_artifact: false)
+ stub_licensed_features({ feature => true })
+ end
+
+ context "when head pipeline has reports" do
+ let(:merge_request) { create(:merge_request, with_reports, source_project: project) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context "when head pipeline does not have reports" do
+ let(:merge_request) { create(:merge_request, source_project: project) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index a3c0a43115e..647e279bf83 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -113,6 +113,7 @@ RSpec.describe Namespace do
describe 'inclusions' do
it { is_expected.to include_module(Gitlab::VisibilityLevel) }
+ it { is_expected.to include_module(Namespaces::Traversal::Recursive) }
end
describe '#visibility_level_field' do
@@ -770,80 +771,7 @@ RSpec.describe Namespace do
end
end
- describe '#self_and_hierarchy' do
- let!(:group) { create(:group, path: 'git_lab') }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
- let!(:another_group) { create(:group, path: 'gitllab') }
- let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
-
- it 'returns the correct tree' do
- expect(group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- expect(nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- expect(very_deep_nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- end
- end
-
- describe '#ancestors' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deep_nested_group) { create(:group, parent: nested_group) }
- let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
-
- it 'returns the correct ancestors' do
- expect(very_deep_nested_group.ancestors).to include(group, nested_group, deep_nested_group)
- expect(deep_nested_group.ancestors).to include(group, nested_group)
- expect(nested_group.ancestors).to include(group)
- expect(group.ancestors).to eq([])
- end
- end
-
- describe '#self_and_ancestors' do
- let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
- let(:deep_nested_group) { create(:group, parent: nested_group) }
- let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
-
- it 'returns the correct ancestors' do
- expect(very_deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- expect(deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group)
- expect(nested_group.self_and_ancestors).to contain_exactly(group, nested_group)
- expect(group.self_and_ancestors).to contain_exactly(group)
- end
- end
-
- describe '#descendants' do
- let!(:group) { create(:group, path: 'git_lab') }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
- let!(:another_group) { create(:group, path: 'gitllab') }
- let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
-
- it 'returns the correct descendants' do
- expect(very_deep_nested_group.descendants.to_a).to eq([])
- expect(deep_nested_group.descendants.to_a).to include(very_deep_nested_group)
- expect(nested_group.descendants.to_a).to include(deep_nested_group, very_deep_nested_group)
- expect(group.descendants.to_a).to include(nested_group, deep_nested_group, very_deep_nested_group)
- end
- end
-
- describe '#self_and_descendants' do
- let!(:group) { create(:group, path: 'git_lab') }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:deep_nested_group) { create(:group, parent: nested_group) }
- let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
- let!(:another_group) { create(:group, path: 'gitllab') }
- let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
-
- it 'returns the correct descendants' do
- expect(very_deep_nested_group.self_and_descendants).to contain_exactly(very_deep_nested_group)
- expect(deep_nested_group.self_and_descendants).to contain_exactly(deep_nested_group, very_deep_nested_group)
- expect(nested_group.self_and_descendants).to contain_exactly(nested_group, deep_nested_group, very_deep_nested_group)
- expect(group.self_and_descendants).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
- end
- end
+ it_behaves_like 'recursive namespace traversal'
describe '#users_with_descendants' do
let(:user_a) { create(:user) }
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 6e87ca6dcf7..364b80e8601 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -837,6 +837,16 @@ RSpec.describe Note do
end
end
+ describe '#for_project_snippet?' do
+ it 'returns true for a project snippet note' do
+ expect(build(:note_on_project_snippet).for_project_snippet?).to be true
+ end
+
+ it 'returns false for a personal snippet note' do
+ expect(build(:note_on_personal_snippet).for_project_snippet?).to be false
+ end
+ end
+
describe '#for_personal_snippet?' do
it 'returns false for a project snippet note' do
expect(build(:note_on_project_snippet).for_personal_snippet?).to be_falsy
@@ -890,35 +900,31 @@ RSpec.describe Note do
describe '#cache_markdown_field' do
let(:html) { '<p>some html</p>'}
+ before do
+ allow(Banzai::Renderer).to receive(:cacheless_render_field).and_call_original
+ end
+
context 'note for a project snippet' do
let(:snippet) { create(:project_snippet) }
- let(:note) { build(:note_on_project_snippet, project: snippet.project, noteable: snippet) }
+ let(:note) { create(:note_on_project_snippet, project: snippet.project, noteable: snippet) }
- before do
+ it 'skips project check' do
expect(Banzai::Renderer).to receive(:cacheless_render_field)
- .with(note, :note, { skip_project_check: false }).and_return(html)
-
- note.save
- end
+ .with(note, :note, { skip_project_check: false })
- it 'creates a note' do
- expect(note.note_html).to eq(html)
+ note.update!(note: html)
end
end
context 'note for a personal snippet' do
let(:snippet) { create(:personal_snippet) }
- let(:note) { build(:note_on_personal_snippet, noteable: snippet) }
+ let(:note) { create(:note_on_personal_snippet, noteable: snippet) }
- before do
+ it 'does not skip project check' do
expect(Banzai::Renderer).to receive(:cacheless_render_field)
- .with(note, :note, { skip_project_check: true }).and_return(html)
-
- note.save
- end
+ .with(note, :note, { skip_project_check: true })
- it 'creates a note' do
- expect(note.note_html).to eq(html)
+ note.update!(note: html)
end
end
end
diff --git a/spec/models/onboarding_progress_spec.rb b/spec/models/onboarding_progress_spec.rb
index bd951846bb8..0aa19345a25 100644
--- a/spec/models/onboarding_progress_spec.rb
+++ b/spec/models/onboarding_progress_spec.rb
@@ -29,6 +29,67 @@ RSpec.describe OnboardingProgress do
end
end
+ describe 'scopes' do
+ describe '.incomplete_actions' do
+ subject { described_class.incomplete_actions(actions) }
+
+ let!(:no_actions_completed) { create(:onboarding_progress) }
+ let!(:one_action_completed_one_action_incompleted) { create(:onboarding_progress, "#{action}_at" => Time.current) }
+
+ context 'when given one action' do
+ let(:actions) { action }
+
+ it { is_expected.to eq [no_actions_completed] }
+ end
+
+ context 'when given an array of actions' do
+ let(:actions) { [action, :git_write] }
+
+ it { is_expected.to eq [no_actions_completed] }
+ end
+ end
+
+ describe '.completed_actions' do
+ subject { described_class.completed_actions(actions) }
+
+ let!(:one_action_completed_one_action_incompleted) { create(:onboarding_progress, "#{action}_at" => Time.current) }
+ let!(:both_actions_completed) { create(:onboarding_progress, "#{action}_at" => Time.current, git_write_at: Time.current) }
+
+ context 'when given one action' do
+ let(:actions) { action }
+
+ it { is_expected.to eq [one_action_completed_one_action_incompleted, both_actions_completed] }
+ end
+
+ context 'when given an array of actions' do
+ let(:actions) { [action, :git_write] }
+
+ it { is_expected.to eq [both_actions_completed] }
+ end
+ end
+
+ describe '.completed_actions_with_latest_in_range' do
+ subject { described_class.completed_actions_with_latest_in_range(actions, 1.day.ago.beginning_of_day..1.day.ago.end_of_day) }
+
+ let!(:one_action_completed_in_range_one_action_incompleted) { create(:onboarding_progress, "#{action}_at" => 1.day.ago.middle_of_day) }
+ let!(:git_write_action_completed_in_range) { create(:onboarding_progress, git_write_at: 1.day.ago.middle_of_day) }
+ let!(:both_actions_completed_latest_action_out_of_range) { create(:onboarding_progress, "#{action}_at" => 1.day.ago.middle_of_day, git_write_at: Time.current) }
+ let!(:both_actions_completed_latest_action_in_range) { create(:onboarding_progress, "#{action}_at" => 1.day.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day) }
+
+ context 'when given one action' do
+ let(:actions) { :git_write }
+
+ it { is_expected.to eq [git_write_action_completed_in_range] }
+ end
+
+ context 'when given an array of actions' do
+ let(:actions) { [action, :git_write] }
+
+ it { is_expected.to eq [both_actions_completed_latest_action_in_range] }
+ end
+ end
+ end
+
describe '.onboard' do
subject(:onboard) { described_class.onboard(namespace) }
@@ -53,6 +114,22 @@ RSpec.describe OnboardingProgress do
end
end
+ describe '.onboarding?' do
+ subject(:onboarding?) { described_class.onboarding?(namespace) }
+
+ context 'when onboarded' do
+ before do
+ described_class.onboard(namespace)
+ end
+
+ it { is_expected.to eq true }
+ end
+
+ context 'when not onboarding' do
+ it { is_expected.to eq false }
+ end
+ end
+
describe '.register' do
subject(:register_action) { described_class.register(namespace, action) }
@@ -104,4 +181,10 @@ RSpec.describe OnboardingProgress do
end
end
end
+
+ describe '.column_name' do
+ subject { described_class.column_name(action) }
+
+ it { is_expected.to eq(:subscription_created_at) }
+ end
end
diff --git a/spec/models/operations/feature_flag_spec.rb b/spec/models/operations/feature_flag_spec.rb
index 93dd7d4f0bb..d5b3c7a8582 100644
--- a/spec/models/operations/feature_flag_spec.rb
+++ b/spec/models/operations/feature_flag_spec.rb
@@ -16,6 +16,35 @@ RSpec.describe Operations::FeatureFlag do
it { is_expected.to have_many(:scopes) }
end
+ describe '.reference_pattern' do
+ subject { described_class.reference_pattern }
+
+ it { is_expected.to match('[feature_flag:123]') }
+ it { is_expected.to match('[feature_flag:gitlab-org/gitlab/123]') }
+ end
+
+ describe '.link_reference_pattern' do
+ subject { described_class.link_reference_pattern }
+
+ it { is_expected.to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab/-/feature_flags/123/edit") }
+ it { is_expected.not_to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab/issues/123/edit") }
+ it { is_expected.not_to match("gitlab-org/gitlab/-/feature_flags/123/edit") }
+ end
+
+ describe '#to_reference' do
+ let(:namespace) { build(:namespace, path: 'sample-namespace') }
+ let(:project) { build(:project, name: 'sample-project', namespace: namespace) }
+ let(:feature_flag) { build(:operations_feature_flag, iid: 1, project: project) }
+
+ it 'returns feature flag id' do
+ expect(feature_flag.to_reference).to eq '[feature_flag:1]'
+ end
+
+ it 'returns complete path to the feature flag with full: true' do
+ expect(feature_flag.to_reference(full: true)).to eq '[feature_flag:sample-namespace/sample-project/1]'
+ end
+ end
+
describe 'validations' do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:name) }
diff --git a/spec/models/packages/composer/cache_file_spec.rb b/spec/models/packages/composer/cache_file_spec.rb
new file mode 100644
index 00000000000..a03b89ca2f5
--- /dev/null
+++ b/spec/models/packages/composer/cache_file_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Composer::CacheFile, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:group) }
+ it { is_expected.to belong_to(:namespace) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:namespace) }
+ end
+
+ describe 'scopes' do
+ let_it_be(:group1) { create(:group) }
+ let_it_be(:group2) { create(:group) }
+ let_it_be(:cache_file1) { create(:composer_cache_file, file_sha256: '123456', group: group1) }
+ let_it_be(:cache_file2) { create(:composer_cache_file, delete_at: 2.days.from_now, file_sha256: '456778', group: group2) }
+
+ describe '.with_namespace' do
+ subject { described_class.with_namespace(group1) }
+
+ it { is_expected.to eq [cache_file1] }
+ end
+
+ describe '.with_sha' do
+ subject { described_class.with_sha('123456') }
+
+ it { is_expected.to eq [cache_file1] }
+ end
+ end
+end
diff --git a/spec/models/packages/composer/metadatum_spec.rb b/spec/models/packages/composer/metadatum_spec.rb
index ae53532696b..1c888f1563c 100644
--- a/spec/models/packages/composer/metadatum_spec.rb
+++ b/spec/models/packages/composer/metadatum_spec.rb
@@ -11,4 +11,20 @@ RSpec.describe Packages::Composer::Metadatum, type: :model do
it { is_expected.to validate_presence_of(:target_sha) }
it { is_expected.to validate_presence_of(:composer_json) }
end
+
+ describe 'scopes' do
+ let_it_be(:package_name) { 'sample-project' }
+ let_it_be(:json) { { 'name' => package_name } }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :custom_repo, files: { 'composer.json' => json.to_json }, group: group) }
+ let_it_be(:package1) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) }
+ let_it_be(:package2) { create(:composer_package, :with_metadatum, project: project, name: 'other-name', version: '1.0.0', json: json) }
+ let_it_be(:package3) { create(:pypi_package, name: package_name, project: project) }
+
+ describe '.for_package' do
+ subject { described_class.for_package(package_name, project.id) }
+
+ it { is_expected.to eq [package1.composer_metadatum] }
+ end
+ end
end
diff --git a/spec/models/packages/debian/group_component_file_spec.rb b/spec/models/packages/debian/group_component_file_spec.rb
new file mode 100644
index 00000000000..bf33ca138c3
--- /dev/null
+++ b/spec/models/packages/debian/group_component_file_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GroupComponentFile do
+ it_behaves_like 'Debian Component File', :group, false
+end
diff --git a/spec/models/packages/debian/group_component_spec.rb b/spec/models/packages/debian/group_component_spec.rb
new file mode 100644
index 00000000000..f288ebbe5df
--- /dev/null
+++ b/spec/models/packages/debian/group_component_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::GroupComponent do
+ it_behaves_like 'Debian Distribution Component', :debian_group_component, :group, false
+end
diff --git a/spec/models/packages/debian/project_component_file_spec.rb b/spec/models/packages/debian/project_component_file_spec.rb
new file mode 100644
index 00000000000..5dfc47c14c0
--- /dev/null
+++ b/spec/models/packages/debian/project_component_file_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ProjectComponentFile do
+ it_behaves_like 'Debian Component File', :project, true
+end
diff --git a/spec/models/packages/debian/project_component_spec.rb b/spec/models/packages/debian/project_component_spec.rb
new file mode 100644
index 00000000000..4b041068b8d
--- /dev/null
+++ b/spec/models/packages/debian/project_component_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ProjectComponent do
+ it_behaves_like 'Debian Distribution Component', :debian_project_component, :project, true
+end
diff --git a/spec/models/packages/debian/publication_spec.rb b/spec/models/packages/debian/publication_spec.rb
new file mode 100644
index 00000000000..0ed056f499b
--- /dev/null
+++ b/spec/models/packages/debian/publication_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::Publication, type: :model do
+ let_it_be_with_reload(:publication) { create(:debian_publication) }
+
+ subject { publication }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:package).inverse_of(:debian_publication).class_name('Packages::Package') }
+ it { is_expected.to belong_to(:distribution).inverse_of(:publications).class_name('Packages::Debian::ProjectDistribution').with_foreign_key(:distribution_id) }
+ end
+
+ describe 'validations' do
+ describe '#package' do
+ it { is_expected.to validate_presence_of(:package) }
+ end
+
+ describe '#valid_debian_package_type' do
+ context 'with package type not being Debian' do
+ before do
+ publication.package.package_type = 'generic'
+ end
+
+ it 'will not allow package type not being Debian' do
+ expect(publication).not_to be_valid
+ expect(publication.errors.to_a).to eq(['Package type must be Debian'])
+ end
+ end
+
+ context 'with package not being a Debian package' do
+ before do
+ publication.package.version = nil
+ end
+
+ it 'will not allow package not being a distribution' do
+ expect(publication).not_to be_valid
+ expect(publication.errors.to_a).to eq(['Package must be a Debian package'])
+ end
+ end
+ end
+
+ describe '#distribution' do
+ it { is_expected.to validate_presence_of(:distribution) }
+ end
+ end
+end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 6645db33503..6c55d37b95f 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -4,6 +4,8 @@ require 'spec_helper'
RSpec.describe Packages::Package, type: :model do
include SortingHelper
+ it_behaves_like 'having unique enum values'
+
describe 'relationships' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:creator) }
@@ -14,7 +16,10 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to have_many(:pipelines).through(:build_infos) }
it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) }
it { is_expected.to have_one(:maven_metadatum).inverse_of(:package) }
+ it { is_expected.to have_one(:debian_publication).inverse_of(:package).class_name('Packages::Debian::Publication') }
+ it { is_expected.to have_one(:debian_distribution).through(:debian_publication).source(:distribution).inverse_of(:packages).class_name('Packages::Debian::ProjectDistribution') }
it { is_expected.to have_one(:nuget_metadatum).inverse_of(:package) }
+ it { is_expected.to have_one(:rubygems_metadatum).inverse_of(:package) }
end
describe '.with_composer_target' do
@@ -374,7 +379,28 @@ RSpec.describe Packages::Package, type: :model do
end
end
- Packages::Package.package_types.keys.without('conan').each do |pt|
+ describe "#unique_debian_package_name" do
+ let!(:package) { create(:debian_package) }
+
+ it "will allow a Debian package with same project, name and version, but different distribution" do
+ new_package = build(:debian_package, project: package.project, name: package.name, version: package.version)
+ expect(new_package).to be_valid
+ end
+
+ it "will not allow a Debian package with same project, name, version and distribution" do
+ new_package = build(:debian_package, project: package.project, name: package.name, version: package.version)
+ new_package.debian_publication.distribution = package.debian_publication.distribution
+ expect(new_package).not_to be_valid
+ expect(new_package.errors.to_a).to include('Debian package already exists in Distribution')
+ end
+
+ it "will allow a Debian package with same project, name, version, but no distribution" do
+ new_package = build(:debian_package, project: package.project, name: package.name, version: package.version, published_in: nil)
+ expect(new_package).to be_valid
+ end
+ end
+
+ Packages::Package.package_types.keys.without('conan', 'debian').each do |pt|
context "project id, name, version and package type uniqueness for package type #{pt}" do
let(:package) { create("#{pt}_package") }
@@ -581,6 +607,28 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to match_array([pypi_package]) }
end
+
+ describe '.displayable' do
+ let_it_be(:hidden_package) { create(:maven_package, :hidden) }
+ let_it_be(:processing_package) { create(:maven_package, :processing) }
+
+ subject { described_class.displayable }
+
+ it 'does not include hidden packages', :aggregate_failures do
+ is_expected.not_to include(hidden_package)
+ is_expected.not_to include(processing_package)
+ end
+ end
+
+ describe '.with_status' do
+ let_it_be(:hidden_package) { create(:maven_package, :hidden) }
+
+ subject { described_class.with_status(:hidden) }
+
+ it 'returns packages with specified status' do
+ is_expected.to match_array([hidden_package])
+ end
+ end
end
describe '.select_distinct_name' do
diff --git a/spec/models/packages/rubygems/metadatum_spec.rb b/spec/models/packages/rubygems/metadatum_spec.rb
new file mode 100644
index 00000000000..e99a07c7731
--- /dev/null
+++ b/spec/models/packages/rubygems/metadatum_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Rubygems::Metadatum, type: :model do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:package) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:package) }
+
+ describe '#rubygems_package_type' do
+ it 'will not allow a package with a different package_type' do
+ package = build('conan_package')
+ rubygems_metadatum = build('rubygems_metadatum', package: package)
+
+ expect(rubygems_metadatum).not_to be_valid
+ expect(rubygems_metadatum.errors.to_a).to include('Package type must be RubyGems')
+ end
+ end
+ end
+end
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index 30712af6b32..0a2b04f1a7c 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -56,6 +56,15 @@ RSpec.describe Pages::LookupPath do
include_examples 'uses disk storage'
+ it 'return nil when legacy storage is disabled and there is no deployment' do
+ stub_feature_flags(pages_serve_from_legacy_storage: false)
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+ .with(described_class::LegacyStorageDisabledError)
+ .and_call_original
+
+ expect(source).to eq(nil)
+ end
+
context 'when there is pages deployment' do
let(:deployment) { create(:pages_deployment, project: project) }
@@ -115,6 +124,35 @@ RSpec.describe Pages::LookupPath do
include_examples 'uses disk storage'
end
+
+ context 'when deployment were created during migration' do
+ before do
+ allow(deployment).to receive(:migrated?).and_return(true)
+ end
+
+ it 'uses deployment from object storage' do
+ freeze_time do
+ expect(source).to(
+ eq({
+ type: 'zip',
+ path: deployment.file.url(expire_at: 1.day.from_now),
+ global_id: "gid://gitlab/PagesDeployment/#{deployment.id}",
+ sha256: deployment.file_sha256,
+ file_size: deployment.size,
+ file_count: deployment.file_count
+ })
+ )
+ end
+ end
+
+ context 'when pages_serve_from_migrated_zip feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_serve_from_migrated_zip: false)
+ end
+
+ include_examples 'uses disk storage'
+ end
+ end
end
end
diff --git a/spec/models/pages/virtual_domain_spec.rb b/spec/models/pages/virtual_domain_spec.rb
index 38f5f4d2538..29c14cbeb3e 100644
--- a/spec/models/pages/virtual_domain_spec.rb
+++ b/spec/models/pages/virtual_domain_spec.rb
@@ -26,31 +26,34 @@ RSpec.describe Pages::VirtualDomain do
describe '#lookup_paths' do
let(:project_a) { instance_double(Project) }
- let(:project_z) { instance_double(Project) }
- let(:pages_lookup_path_a) { instance_double(Pages::LookupPath, prefix: 'aaa') }
- let(:pages_lookup_path_z) { instance_double(Pages::LookupPath, prefix: 'zzz') }
+ let(:project_b) { instance_double(Project) }
+ let(:project_c) { instance_double(Project) }
+ let(:pages_lookup_path_a) { instance_double(Pages::LookupPath, prefix: 'aaa', source: { type: 'zip', path: 'https://example.com' }) }
+ let(:pages_lookup_path_b) { instance_double(Pages::LookupPath, prefix: 'bbb', source: { type: 'zip', path: 'https://example.com' }) }
+ let(:pages_lookup_path_without_source) { instance_double(Pages::LookupPath, prefix: 'ccc', source: nil) }
context 'when there is pages domain provided' do
let(:domain) { instance_double(PagesDomain) }
- subject(:virtual_domain) { described_class.new([project_a, project_z], domain: domain) }
+ subject(:virtual_domain) { described_class.new([project_a, project_b, project_c], domain: domain) }
it 'returns collection of projects pages lookup paths sorted by prefix in reverse' do
expect(project_a).to receive(:pages_lookup_path).with(domain: domain, trim_prefix: nil).and_return(pages_lookup_path_a)
- expect(project_z).to receive(:pages_lookup_path).with(domain: domain, trim_prefix: nil).and_return(pages_lookup_path_z)
+ expect(project_b).to receive(:pages_lookup_path).with(domain: domain, trim_prefix: nil).and_return(pages_lookup_path_b)
+ expect(project_c).to receive(:pages_lookup_path).with(domain: domain, trim_prefix: nil).and_return(pages_lookup_path_without_source)
- expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_z, pages_lookup_path_a])
+ expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_b, pages_lookup_path_a])
end
end
context 'when there is trim_prefix provided' do
- subject(:virtual_domain) { described_class.new([project_a, project_z], trim_prefix: 'group/') }
+ subject(:virtual_domain) { described_class.new([project_a, project_b], trim_prefix: 'group/') }
it 'returns collection of projects pages lookup paths sorted by prefix in reverse' do
expect(project_a).to receive(:pages_lookup_path).with(trim_prefix: 'group/', domain: nil).and_return(pages_lookup_path_a)
- expect(project_z).to receive(:pages_lookup_path).with(trim_prefix: 'group/', domain: nil).and_return(pages_lookup_path_z)
+ expect(project_b).to receive(:pages_lookup_path).with(trim_prefix: 'group/', domain: nil).and_return(pages_lookup_path_b)
- expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_z, pages_lookup_path_a])
+ expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_b, pages_lookup_path_a])
end
end
end
diff --git a/spec/models/pages_deployment_spec.rb b/spec/models/pages_deployment_spec.rb
index e83cbc15004..029eb8e513a 100644
--- a/spec/models/pages_deployment_spec.rb
+++ b/spec/models/pages_deployment_spec.rb
@@ -26,6 +26,46 @@ RSpec.describe PagesDeployment do
end
end
+ describe '.migrated_from_legacy_storage' do
+ it 'only returns migrated deployments' do
+ project = create(:project)
+ migrated_deployment = create_migrated_deployment(project)
+ # create one other deployment
+ create(:pages_deployment, project: project)
+
+ expect(described_class.migrated_from_legacy_storage).to eq([migrated_deployment])
+ end
+ end
+
+ describe '#migrated?' do
+ it 'returns false for normal deployment' do
+ deployment = create(:pages_deployment)
+
+ expect(deployment.migrated?).to eq(false)
+ end
+
+ it 'returns true for migrated deployment' do
+ project = create(:project)
+ deployment = create_migrated_deployment(project)
+
+ expect(deployment.migrated?).to eq(true)
+ end
+ end
+
+ def create_migrated_deployment(project)
+ public_path = File.join(project.pages_path, "public")
+ FileUtils.mkdir_p(public_path)
+ File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
+ f.write("Hello!")
+ end
+
+ expect(::Pages::MigrateLegacyStorageToDeploymentService.new(project).execute[:status]).to eq(:success)
+
+ project.reload.pages_metadatum.pages_deployment
+ ensure
+ FileUtils.rm_rf(public_path)
+ end
+
describe 'default for file_store' do
let(:project) { create(:project) }
let(:deployment) do
diff --git a/spec/models/project_ci_cd_setting_spec.rb b/spec/models/project_ci_cd_setting_spec.rb
index 698465e854a..406485d8cc8 100644
--- a/spec/models/project_ci_cd_setting_spec.rb
+++ b/spec/models/project_ci_cd_setting_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe ProjectCiCdSetting do
+ using RSpec::Parameterized::TableSyntax
+
describe 'validations' do
it 'validates default_git_depth is between 0 and 1000 or nil' do
expect(subject).to validate_numericality_of(:default_git_depth)
@@ -36,4 +38,39 @@ RSpec.describe ProjectCiCdSetting do
expect(project.reload.ci_cd_settings.default_git_depth).to eq(0)
end
end
+
+ describe '#keep_latest_artifacts_available?' do
+ let(:attrs) { { keep_latest_artifact: project_enabled } }
+ let(:project_settings) { described_class.new(attrs) }
+
+ subject { project_settings.keep_latest_artifacts_available? }
+
+ context 'without application setting record' do
+ where(:project_enabled, :result_keep_latest_artifact) do
+ false | false
+ true | true
+ end
+
+ with_them do
+ it { expect(subject).to eq(result_keep_latest_artifact) }
+ end
+ end
+
+ context 'with application setting record' do
+ where(:instance_enabled, :project_enabled, :result_keep_latest_artifact) do
+ false | false | false
+ false | true | false
+ true | false | false
+ true | true | true
+ end
+
+ before do
+ Gitlab::CurrentSettings.current_application_settings.update!(keep_latest_artifact: instance_enabled)
+ end
+
+ with_them do
+ it { expect(subject).to eq(result_keep_latest_artifact) }
+ end
+ end
+ end
end
diff --git a/spec/models/project_services/alerts_service_spec.rb b/spec/models/project_services/alerts_service_spec.rb
deleted file mode 100644
index 75b91c29914..00000000000
--- a/spec/models/project_services/alerts_service_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# AlertsService is stripped down to only required methods
-# to avoid errors loading integration-related pages if
-# records are present.
-RSpec.describe AlertsService do
- let_it_be(:project) { create(:project) }
- subject(:service) { described_class.new(project: project) }
-
- it { is_expected.to be_valid }
-
- describe '#to_param' do
- subject { service.to_param }
-
- it { is_expected.to eq('alerts') }
- end
-
- describe '#supported_events' do
- subject { service.supported_events }
-
- it { is_expected.to be_empty }
- end
-
- describe '#save' do
- it 'prevents records from being created or updated' do
- expect(Gitlab::ProjectServiceLogger).to receive(:error).with(
- hash_including(message: 'Prevented attempt to save or update deprecated AlertsService')
- )
-
- expect(service.save).to be_falsey
-
- expect(service.errors.full_messages).to include(
- 'Alerts endpoint is deprecated and should not be created or modified. Use HTTP Integrations instead.'
- )
- end
- end
-end
diff --git a/spec/models/project_services/chat_notification_service_spec.rb b/spec/models/project_services/chat_notification_service_spec.rb
index 77a1377c138..476d99364b6 100644
--- a/spec/models/project_services/chat_notification_service_spec.rb
+++ b/spec/models/project_services/chat_notification_service_spec.rb
@@ -75,6 +75,39 @@ RSpec.describe ChatNotificationService do
end
end
+ context 'when the data object has a label' do
+ let(:label) { create(:label, project: project, name: 'Bug')}
+ let(:issue) { create(:labeled_issue, project: project, labels: [label]) }
+ let(:note) { create(:note, noteable: issue, project: project)}
+ let(:data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ it 'notifies the chat service' do
+ expect(chat_service).to receive(:notify).with(any_args)
+
+ chat_service.execute(data)
+ end
+
+ context 'and the chat_service has a label filter that does not matches the label' do
+ subject(:chat_service) { described_class.new(labels_to_be_notified: '~some random label') }
+
+ it 'does not notify the chat service' do
+ expect(chat_service).not_to receive(:notify)
+
+ chat_service.execute(data)
+ end
+ end
+
+ context 'and the chat_service has a label filter that matches the label' do
+ subject(:chat_service) { described_class.new(labels_to_be_notified: '~Backend, ~Bug') }
+
+ it 'notifies the chat service' do
+ expect(chat_service).to receive(:notify).with(any_args)
+
+ chat_service.execute(data)
+ end
+ end
+ end
+
context 'with "channel" property' do
before do
allow(chat_service).to receive(:channel).and_return(channel)
diff --git a/spec/models/project_services/confluence_service_spec.rb b/spec/models/project_services/confluence_service_spec.rb
index 5d153b17070..6c7ba2c9f32 100644
--- a/spec/models/project_services/confluence_service_spec.rb
+++ b/spec/models/project_services/confluence_service_spec.rb
@@ -43,13 +43,13 @@ RSpec.describe ConfluenceService do
end
end
- describe '#detailed_description' do
+ describe '#help' do
it 'can correctly return a link to the project wiki when active' do
project = create(:project)
subject.project = project
subject.active = true
- expect(subject.detailed_description).to include(Gitlab::Routing.url_helpers.project_wikis_url(project))
+ expect(subject.help).to include(Gitlab::Routing.url_helpers.project_wikis_url(project))
end
context 'when the project wiki is not enabled' do
@@ -60,7 +60,7 @@ RSpec.describe ConfluenceService do
[true, false].each do |active|
subject.active = active
- expect(subject.detailed_description).to be_nil
+ expect(subject.help).to be_nil
end
end
end
diff --git a/spec/models/project_services/datadog_service_spec.rb b/spec/models/project_services/datadog_service_spec.rb
index 1d9f49e4824..d15ea1f351b 100644
--- a/spec/models/project_services/datadog_service_spec.rb
+++ b/spec/models/project_services/datadog_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe DatadogService, :model do
let(:active) { true }
let(:dd_site) { 'datadoghq.com' }
let(:default_url) { 'https://webhooks-http-intake.logs.datadoghq.com/v1/input/' }
- let(:api_url) { nil }
+ let(:api_url) { '' }
let(:api_key) { SecureRandom.hex(32) }
let(:dd_env) { 'ci' }
let(:dd_service) { 'awesome-gitlab' }
@@ -22,13 +22,11 @@ RSpec.describe DatadogService, :model do
described_class.new(
active: active,
project: project,
- properties: {
- datadog_site: dd_site,
- api_url: api_url,
- api_key: api_key,
- datadog_env: dd_env,
- datadog_service: dd_service
- }
+ datadog_site: dd_site,
+ api_url: api_url,
+ api_key: api_key,
+ datadog_env: dd_env,
+ datadog_service: dd_service
)
end
@@ -58,7 +56,7 @@ RSpec.describe DatadogService, :model do
context 'when selecting site' do
let(:dd_site) { 'datadoghq.com' }
- let(:api_url) { nil }
+ let(:api_url) { '' }
it { is_expected.to validate_presence_of(:datadog_site) }
it { is_expected.not_to validate_presence_of(:api_url) }
@@ -66,7 +64,7 @@ RSpec.describe DatadogService, :model do
end
context 'with custom api_url' do
- let(:dd_site) { nil }
+ let(:dd_site) { '' }
let(:api_url) { 'https://webhooks-http-intake.logs.datad0g.com/v1/input/' }
it { is_expected.not_to validate_presence_of(:datadog_site) }
@@ -76,13 +74,21 @@ RSpec.describe DatadogService, :model do
end
context 'when missing site and api_url' do
- let(:dd_site) { nil }
- let(:api_url) { nil }
+ let(:dd_site) { '' }
+ let(:api_url) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to validate_presence_of(:datadog_site) }
it { is_expected.to validate_presence_of(:api_url) }
end
+
+ context 'when providing both site and api_url' do
+ let(:dd_site) { 'datadoghq.com' }
+ let(:api_url) { default_url }
+
+ 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
end
context 'when service is not active' do
@@ -113,8 +119,8 @@ RSpec.describe DatadogService, :model do
end
context 'without optional params' do
- let(:dd_service) { nil }
- let(:dd_env) { nil }
+ let(:dd_service) { '' }
+ let(:dd_env) { '' }
it { is_expected.to eq(default_url + api_key) }
end
@@ -126,7 +132,7 @@ RSpec.describe DatadogService, :model do
it { is_expected.to eq("https://app.#{dd_site}/account/settings#api") }
context 'with unset datadog_site' do
- let(:dd_site) { nil }
+ let(:dd_site) { '' }
it { is_expected.to eq("https://docs.datadoghq.com/account_management/api-app-keys/") }
end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index cd0873bddd2..78bd0e91208 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe JiraService do
include AssetsHelpers
let_it_be(:project) { create(:project, :repository) }
+
+ let(:current_user) { build_stubbed(:user) }
let(:url) { 'http://jira.example.com' }
let(:api_url) { 'http://api-jira.example.com' }
let(:username) { 'jira-username' }
@@ -456,6 +458,16 @@ RSpec.describe JiraService do
expect(WebMock).to have_requested(:get, issue_url)
end
+
+ context 'with options' do
+ let(:issue_url) { "#{url}/rest/api/2/issue/#{issue_key}?expand=renderedFields" }
+
+ it 'calls the Jira API with the options to get the issue' do
+ jira_service.find_issue(issue_key, rendered_fields: true)
+
+ expect(WebMock).to have_requested(:get, issue_url)
+ end
+ end
end
describe '#close_issue' do
@@ -498,25 +510,38 @@ RSpec.describe JiraService do
WebMock.stub_request(:post, @remote_link_url).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password))
end
+ let(:external_issue) { ExternalIssue.new('JIRA-123', project) }
+
+ def close_issue
+ @jira_service.close_issue(resource, external_issue, current_user)
+ end
+
it 'calls Jira API' do
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).to have_requested(:post, @comment_url).with(
body: /Issue solved with/
).once
end
+ it 'tracks usage' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+ .with('i_ecosystem_jira_service_close_issue', values: current_user.id)
+
+ close_issue
+ end
+
it 'does not fail if remote_link.all on issue returns nil' do
allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
- expect { @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project)) }
- .not_to raise_error
+ expect { close_issue }.not_to raise_error
end
# Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
# for more information
it 'creates Remote Link reference in Jira for comment' do
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
favicon_path = "http://localhost/assets/#{find_asset('favicon.png').digest_path}"
@@ -540,7 +565,7 @@ RSpec.describe JiraService do
context 'when "comment_on_event_enabled" is set to false' do
it 'creates Remote Link reference but does not create comment' do
allow(@jira_service).to receive_messages(comment_on_event_enabled: false)
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).not_to have_requested(:post, @comment_url)
expect(WebMock).to have_requested(:post, @remote_link_url)
@@ -562,7 +587,7 @@ RSpec.describe JiraService do
expect(remote_link).to receive(:save!)
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).not_to have_requested(:post, @comment_url)
end
@@ -571,7 +596,7 @@ RSpec.describe JiraService do
it 'does not send comment or remote links to issues already closed' do
allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true)
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).not_to have_requested(:post, @comment_url)
expect(WebMock).not_to have_requested(:post, @remote_link_url)
@@ -580,7 +605,7 @@ RSpec.describe JiraService do
it 'does not send comment or remote links to issues with unknown resolution' do
allow_any_instance_of(JIRA::Resource::Issue).to receive(:respond_to?).with(:resolution).and_return(false)
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).not_to have_requested(:post, @comment_url)
expect(WebMock).not_to have_requested(:post, @remote_link_url)
@@ -589,7 +614,7 @@ RSpec.describe JiraService do
it 'references the GitLab commit' do
stub_config_setting(base_url: custom_base_url)
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).to have_requested(:post, @comment_url).with(
body: %r{#{custom_base_url}/#{project.full_path}/-/commit/#{commit_id}}
@@ -604,7 +629,7 @@ RSpec.describe JiraService do
{ script_name: '/gitlab' }
end
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).to have_requested(:post, @comment_url).with(
body: %r{#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/#{commit_id}}
@@ -615,7 +640,7 @@ RSpec.describe JiraService do
allow(@jira_service).to receive(:log_error)
WebMock.stub_request(:post, @transitions_url).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password)).and_raise("Bad Request")
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(@jira_service).to have_received(:log_error).with(
"Issue transition failed",
@@ -628,7 +653,7 @@ RSpec.describe JiraService do
end
it 'calls the api with jira_issue_transition_id' do
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
expect(WebMock).to have_requested(:post, @transitions_url).with(
body: /999/
@@ -639,7 +664,7 @@ RSpec.describe JiraService do
it 'calls the api with transition ids separated by comma' do
allow(@jira_service).to receive_messages(jira_issue_transition_id: '1,2,3')
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
1.upto(3) do |transition_id|
expect(WebMock).to have_requested(:post, @transitions_url).with(
@@ -651,7 +676,7 @@ RSpec.describe JiraService do
it 'calls the api with transition ids separated by semicolon' do
allow(@jira_service).to receive_messages(jira_issue_transition_id: '1;2;3')
- @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project))
+ close_issue
1.upto(3) do |transition_id|
expect(WebMock).to have_requested(:post, @transitions_url).with(
@@ -702,6 +727,14 @@ RSpec.describe JiraService do
body: /mentioned this issue in/
).once
end
+
+ it 'tracks usage' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+ .with('i_ecosystem_jira_service_cross_reference', values: user.id)
+
+ subject
+ end
end
context 'when resource is a commit' do
diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb
index f2e2fa65e93..46194efcb3d 100644
--- a/spec/models/project_services/jira_tracker_data_spec.rb
+++ b/spec/models/project_services/jira_tracker_data_spec.rb
@@ -3,13 +3,28 @@
require 'spec_helper'
RSpec.describe JiraTrackerData do
- let(:service) { build(:jira_service) }
-
- describe 'Associations' do
+ describe 'associations' do
it { is_expected.to belong_to(:service) }
end
describe 'deployment_type' do
it { is_expected.to define_enum_for(:deployment_type).with_values([:unknown, :server, :cloud]).with_prefix(:deployment) }
end
+
+ describe 'proxy settings' do
+ it { is_expected.to validate_length_of(:proxy_address).is_at_most(2048) }
+ it { is_expected.to validate_length_of(:proxy_port).is_at_most(5) }
+ it { is_expected.to validate_length_of(:proxy_username).is_at_most(255) }
+ it { is_expected.to validate_length_of(:proxy_password).is_at_most(255) }
+ end
+
+ describe 'encrypted attributes' do
+ subject { described_class.encrypted_attributes.keys }
+
+ it {
+ is_expected.to contain_exactly(
+ :api_url, :password, :proxy_address, :proxy_password, :proxy_port, :proxy_username, :url, :username
+ )
+ }
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a2b51684d4d..fd7975bf65d 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_many(:services) }
it { is_expected.to have_many(:events) }
it { is_expected.to have_many(:merge_requests) }
+ it { is_expected.to have_many(:merge_request_metrics).class_name('MergeRequest::Metrics') }
it { is_expected.to have_many(:issues) }
it { is_expected.to have_many(:milestones) }
it { is_expected.to have_many(:iterations) }
@@ -558,6 +559,25 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#default_pipeline_lock' do
+ let(:project) { build_stubbed(:project) }
+
+ subject { project.default_pipeline_lock }
+
+ where(:keep_latest_artifact_enabled, :result_pipeline_locked) do
+ false | :unlocked
+ true | :artifacts_locked
+ end
+
+ before do
+ allow(project).to receive(:keep_latest_artifacts_available?).and_return(keep_latest_artifact_enabled)
+ end
+
+ with_them do
+ it { expect(subject).to eq(result_pipeline_locked) }
+ end
+ end
+
describe '#autoclose_referenced_issues' do
context 'when DB entry is nil' do
let(:project) { build(:project, autoclose_referenced_issues: nil) }
@@ -1002,103 +1022,125 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#external_issue_tracker' do
- let(:project) { create(:project) }
- let(:ext_project) { create(:redmine_project) }
+ describe '#has_wiki?' do
+ let(:no_wiki_project) { create(:project, :wiki_disabled, has_external_wiki: false) }
+ let(:wiki_enabled_project) { create(:project) }
+ let(:external_wiki_project) { create(:project, has_external_wiki: true) }
- context 'on existing projects with no value for has_external_issue_tracker' do
- before do
- project.update_column(:has_external_issue_tracker, nil)
- ext_project.update_column(:has_external_issue_tracker, nil)
+ it 'returns true if project is wiki enabled or has external wiki' do
+ expect(wiki_enabled_project).to have_wiki
+ expect(external_wiki_project).to have_wiki
+ expect(no_wiki_project).not_to have_wiki
+ end
+ end
+
+ describe '#default_owner' do
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:namespace) { create(:namespace, owner: owner) }
+
+ context 'the project does not have a group' do
+ let(:project) { build(:project, namespace: namespace) }
+
+ it 'is the namespace owner' do
+ expect(project.default_owner).to eq(owner)
end
+ end
- it 'updates the has_external_issue_tracker boolean' do
- expect do
- project.external_issue_tracker
- end.to change { project.reload.has_external_issue_tracker }.to(false)
+ context 'the project is in a group' do
+ let(:group) { build(:group) }
+ let(:project) { build(:project, group: group, namespace: namespace) }
- expect do
- ext_project.external_issue_tracker
- end.to change { ext_project.reload.has_external_issue_tracker }.to(true)
+ it 'is the group owner' do
+ allow(group).to receive(:default_owner).and_return(Object.new)
+
+ expect(project.default_owner).to eq(group.default_owner)
end
end
+ end
+
+ describe '#external_issue_tracker' do
+ it 'sets Project#has_external_issue_tracker when it is nil' do
+ project_with_no_tracker = create(:project, has_external_issue_tracker: nil)
+ project_with_tracker = create(:redmine_project, has_external_issue_tracker: nil)
+
+ expect do
+ project_with_no_tracker.external_issue_tracker
+ end.to change { project_with_no_tracker.reload.has_external_issue_tracker }.from(nil).to(false)
+
+ expect do
+ project_with_tracker.external_issue_tracker
+ end.to change { project_with_tracker.reload.has_external_issue_tracker }.from(nil).to(true)
+ end
it 'returns nil and does not query services when there is no external issue tracker' do
- expect(project).not_to receive(:services)
+ project = create(:project)
+ expect(project).not_to receive(:services)
expect(project.external_issue_tracker).to eq(nil)
end
it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do
- ext_project.reload # Factory returns a project with changed attributes
- expect(ext_project).to receive(:services).once.and_call_original
+ project = create(:redmine_project)
- 2.times { expect(ext_project.external_issue_tracker).to be_a_kind_of(RedmineService) }
+ expect(project).to receive(:services).once.and_call_original
+ 2.times { expect(project.external_issue_tracker).to be_a_kind_of(RedmineService) }
end
end
- describe '#cache_has_external_issue_tracker' do
- let_it_be(:project) { create(:project, has_external_issue_tracker: nil) }
-
- it 'stores true if there is any external_issue_tracker' do
- services = double(:service, external_issue_trackers: [RedmineService.new])
- expect(project).to receive(:services).and_return(services)
+ describe '#has_external_issue_tracker' do
+ let_it_be(:project) { create(:project) }
- expect do
- project.cache_has_external_issue_tracker
- end.to change { project.has_external_issue_tracker}.to(true)
+ def subject
+ project.reload.has_external_issue_tracker
end
- it 'stores false if there is no external_issue_tracker' do
- services = double(:service, external_issue_trackers: [])
- expect(project).to receive(:services).and_return(services)
+ it 'is false when external issue tracker service is not active' do
+ create(:service, project: project, category: 'issue_tracker', active: false)
- expect do
- project.cache_has_external_issue_tracker
- end.to change { project.has_external_issue_tracker}.to(false)
+ is_expected.to eq(false)
end
- it 'does not cache data when in a read-only GitLab instance' do
- allow(Gitlab::Database).to receive(:read_only?) { true }
+ it 'is false when other service is active' do
+ create(:service, project: project, category: 'not_issue_tracker', active: true)
- expect do
- project.cache_has_external_issue_tracker
- end.not_to change { project.has_external_issue_tracker }
+ is_expected.to eq(false)
end
- end
- describe '#has_wiki?' do
- let(:no_wiki_project) { create(:project, :wiki_disabled, has_external_wiki: false) }
- let(:wiki_enabled_project) { create(:project) }
- let(:external_wiki_project) { create(:project, has_external_wiki: true) }
-
- it 'returns true if project is wiki enabled or has external wiki' do
- expect(wiki_enabled_project).to have_wiki
- expect(external_wiki_project).to have_wiki
- expect(no_wiki_project).not_to have_wiki
- end
- end
+ context 'when there is an active external issue tracker service' do
+ let!(:service) do
+ create(:service, project: project, type: 'JiraService', category: 'issue_tracker', active: true)
+ end
- describe '#default_owner' do
- let_it_be(:owner) { create(:user) }
- let_it_be(:namespace) { create(:namespace, owner: owner) }
+ specify { is_expected.to eq(true) }
- context 'the project does not have a group' do
- let(:project) { build(:project, namespace: namespace) }
+ it 'becomes false when external issue tracker service is destroyed' do
+ expect do
+ Service.find(service.id).delete
+ end.to change { subject }.to(false)
+ end
- it 'is the namespace owner' do
- expect(project.default_owner).to eq(owner)
+ it 'becomes false when external issue tracker service becomes inactive' do
+ expect do
+ service.update_column(:active, false)
+ end.to change { subject }.to(false)
end
- end
- context 'the project is in a group' do
- let(:group) { build(:group) }
- let(:project) { build(:project, group: group, namespace: namespace) }
+ context 'when there are two active external issue tracker services' do
+ let_it_be(:second_service) do
+ create(:service, project: project, type: 'CustomIssueTracker', category: 'issue_tracker', active: true)
+ end
- it 'is the group owner' do
- allow(group).to receive(:default_owner).and_return(Object.new)
+ it 'does not become false when external issue tracker service is destroyed' do
+ expect do
+ Service.find(service.id).delete
+ end.not_to change { subject }
+ end
- expect(project.default_owner).to eq(group.default_owner)
+ it 'does not become false when external issue tracker service becomes inactive' do
+ expect do
+ service.update_column(:active, false)
+ end.not_to change { subject }
+ end
end
end
end
@@ -1234,7 +1276,7 @@ RSpec.describe Project, factory_default: :keep do
it 'is false if avatar is html page' do
project.update_attribute(:avatar, 'uploads/avatar.html')
- expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico'])
+ expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp'])
end
end
@@ -1529,10 +1571,7 @@ RSpec.describe Project, factory_default: :keep do
let(:project) { build(:project) }
it 'picks storage from ApplicationSetting' do
- expect_next_instance_of(ApplicationSetting) do |instance|
- expect(instance).to receive(:pick_repository_storage).and_return('picked')
- end
- expect(described_class).to receive(:pick_repository_storage).and_call_original
+ expect(Repository).to receive(:pick_storage_shard).and_return('picked')
expect(project.repository_storage).to eq('picked')
end
@@ -2227,8 +2266,6 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#ci_config_path=' do
- using RSpec::Parameterized::TableSyntax
-
let(:project) { build_stubbed(:project) }
where(:default_ci_config_path, :project_ci_config_path, :expected_ci_config_path) do
@@ -2980,6 +3017,7 @@ RSpec.describe Project, factory_default: :keep do
it_behaves_like 'can housekeep repository' do
let(:resource) { build_stubbed(:project) }
let(:resource_key) { 'projects' }
+ let(:expected_worker_class) { Projects::GitGarbageCollectWorker }
end
describe '#deployment_variables' do
@@ -3926,7 +3964,6 @@ RSpec.describe Project, factory_default: :keep do
describe '.filter_by_feature_visibility' do
include_context 'ProjectPolicyTable context'
include ProjectHelpers
- using RSpec::Parameterized::TableSyntax
let_it_be(:group) { create(:group) }
let!(:project) { create(:project, project_level, namespace: group ) }
@@ -4099,7 +4136,7 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#remove_pages' do
+ describe '#legacy_remove_pages' do
let(:project) { create(:project).tap { |project| project.mark_pages_as_deployed } }
let(:pages_metadatum) { project.pages_metadatum }
let(:namespace) { project.namespace }
@@ -4118,34 +4155,22 @@ RSpec.describe Project, factory_default: :keep do
expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return(true)
expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, namespace.full_path, anything)
- expect { project.remove_pages }.to change { pages_metadatum.reload.deployed }.from(true).to(false)
+ expect { project.legacy_remove_pages }.to change { pages_metadatum.reload.deployed }.from(true).to(false)
end
- it 'is run when the project is destroyed' do
- expect(project).to receive(:remove_pages).and_call_original
-
- expect { project.destroy }.not_to raise_error
- end
+ it 'does nothing if updates on legacy storage are disabled' do
+ stub_feature_flags(pages_update_legacy_storage: false)
- context 'when there is an old pages deployment' do
- let!(:old_deployment_from_another_project) { create(:pages_deployment) }
- let!(:old_deployment) { create(:pages_deployment, project: project) }
+ expect(Gitlab::PagesTransfer).not_to receive(:new)
+ expect(PagesWorker).not_to receive(:perform_in)
- it 'schedules a destruction of pages deployments' do
- expect(DestroyPagesDeploymentsWorker).to(
- receive(:perform_async).with(project.id)
- )
-
- project.remove_pages
- end
+ project.legacy_remove_pages
+ end
- it 'removes pages deployments', :sidekiq_inline do
- expect do
- project.remove_pages
- end.to change { PagesDeployment.count }.by(-1)
+ it 'is run when the project is destroyed' do
+ expect(project).to receive(:legacy_remove_pages).and_call_original
- expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil
- end
+ expect { project.destroy }.not_to raise_error
end
end
@@ -4176,8 +4201,6 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#git_transfer_in_progress?' do
- using RSpec::Parameterized::TableSyntax
-
let(:project) { build(:project) }
subject { project.git_transfer_in_progress? }
@@ -5068,10 +5091,8 @@ RSpec.describe Project, factory_default: :keep do
it 'executes services with the specified scope' do
data = 'any data'
- expect(SlackService).to receive(:allocate).and_wrap_original do |method|
- method.call.tap do |instance|
- expect(instance).to receive(:async_execute).with(data).once
- end
+ expect_next_found_instance_of(SlackService) do |instance|
+ expect(instance).to receive(:async_execute).with(data).once
end
service.project.execute_services(data, :push_hooks)
@@ -5801,8 +5822,6 @@ RSpec.describe Project, factory_default: :keep do
end
describe 'validation #changing_shared_runners_enabled_is_allowed' do
- using RSpec::Parameterized::TableSyntax
-
where(:shared_runners_setting, :project_shared_runners_enabled, :valid_record) do
'enabled' | true | true
'enabled' | false | true
@@ -6025,8 +6044,6 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#closest_setting' do
- using RSpec::Parameterized::TableSyntax
-
shared_examples_for 'fetching closest setting' do
let!(:namespace) { create(:namespace) }
let!(:project) { create(:project, namespace: namespace) }
@@ -6378,20 +6395,7 @@ RSpec.describe Project, factory_default: :keep do
describe 'with Debian Distributions' do
subject { create(:project) }
- let!(:distributions) { create_list(:debian_project_distribution, 2, :with_file, container: subject) }
-
- it 'removes distribution files on removal' do
- distribution_file_paths = distributions.map do |distribution|
- distribution.file.path
- end
-
- expect { subject.destroy }
- .to change {
- distribution_file_paths.select do |path|
- File.exist? path
- end.length
- }.from(distribution_file_paths.length).to(0)
- end
+ it_behaves_like 'model with Debian distributions'
end
describe '#environments_for_scope' do
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 8001d009901..c04fc70deca 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -47,5 +47,6 @@ RSpec.describe ProjectWiki do
let_it_be(:resource) { create(:project_wiki) }
let(:resource_key) { 'project_wikis' }
+ let(:expected_worker_class) { Wikis::GitGarbageCollectWorker }
end
end
diff --git a/spec/models/prometheus_metric_spec.rb b/spec/models/prometheus_metric_spec.rb
index 9588167bbcc..a20f4edcf4a 100644
--- a/spec/models/prometheus_metric_spec.rb
+++ b/spec/models/prometheus_metric_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe PrometheusMetric do
+ using RSpec::Parameterized::TableSyntax
+
subject { build(:prometheus_metric) }
it_behaves_like 'having unique enum values'
@@ -14,8 +16,6 @@ RSpec.describe PrometheusMetric do
it { is_expected.to validate_uniqueness_of(:identifier).scoped_to(:project_id).allow_nil }
describe 'common metrics' do
- using RSpec::Parameterized::TableSyntax
-
where(:common, :with_project, :result) do
false | true | true
false | false | false
@@ -34,8 +34,6 @@ RSpec.describe PrometheusMetric do
end
describe '#query_series' do
- using RSpec::Parameterized::TableSyntax
-
where(:legend, :type) do
'Some other legend' | NilClass
'Status Code' | Array
@@ -72,8 +70,6 @@ RSpec.describe PrometheusMetric do
end
describe '#priority' do
- using RSpec::Parameterized::TableSyntax
-
where(:group, :priority) do
:nginx_ingress_vts | 10
:nginx_ingress | 10
@@ -97,8 +93,6 @@ RSpec.describe PrometheusMetric do
end
describe '#required_metrics' do
- using RSpec::Parameterized::TableSyntax
-
where(:group, :required_metrics) do
:nginx_ingress_vts | %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg)
:nginx_ingress | %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum)
diff --git a/spec/models/protected_branch/push_access_level_spec.rb b/spec/models/protected_branch/push_access_level_spec.rb
index 051cb78a6b6..17a589f0485 100644
--- a/spec/models/protected_branch/push_access_level_spec.rb
+++ b/spec/models/protected_branch/push_access_level_spec.rb
@@ -54,16 +54,6 @@ RSpec.describe ProtectedBranch::PushAccessLevel do
specify do
expect(push_access_level.check_access(user)).to be_truthy
end
-
- context 'when the deploy_keys_on_protected_branches FF is false' do
- before do
- stub_feature_flags(deploy_keys_on_protected_branches: false)
- end
-
- it 'is false' do
- expect(push_access_level.check_access(user)).to be_falsey
- end
- end
end
context 'when the deploy key is not among the active keys of this project' do
diff --git a/spec/models/readme_blob_spec.rb b/spec/models/readme_blob_spec.rb
deleted file mode 100644
index 95622d55254..00000000000
--- a/spec/models/readme_blob_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ReadmeBlob do
- include FakeBlobHelpers
-
- describe 'policy' do
- let(:project) { build(:project, :repository) }
-
- subject { described_class.new(fake_blob(path: 'README.md'), project.repository) }
-
- it 'works with policy' do
- expect(Ability.allowed?(project.creator, :read_blob, subject)).to be_truthy
- end
- end
-end
diff --git a/spec/models/release_highlight_spec.rb b/spec/models/release_highlight_spec.rb
index 749b9b8e1ab..60087278671 100644
--- a/spec/models/release_highlight_spec.rb
+++ b/spec/models/release_highlight_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ReleaseHighlight do
+RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')).grep(/\d*\_(\d*\_\d*)\.yml$/) }
before do
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index b436c2e1088..209ac471210 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Release do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
- let_it_be(:release) { create(:release, project: project, author: user) }
+ let(:release) { create(:release, project: project, author: user) }
it { expect(release).to be_valid }
@@ -89,6 +89,61 @@ RSpec.describe Release do
end
end
+ describe '#update' do
+ subject { release.update(params) }
+
+ context 'when links do not exist' do
+ context 'when params are specified for creation' do
+ let(:params) do
+ { links_attributes: [{ name: 'test', url: 'https://www.google.com/' }] }
+ end
+
+ it 'creates a link successfuly' do
+ is_expected.to eq(true)
+
+ expect(release.links.count).to eq(1)
+ expect(release.links.first.name).to eq('test')
+ expect(release.links.first.url).to eq('https://www.google.com/')
+ end
+ end
+ end
+
+ context 'when a link exists' do
+ let!(:link1) { create(:release_link, release: release, name: 'test1', url: 'https://www.google1.com/') }
+ let!(:link2) { create(:release_link, release: release, name: 'test2', url: 'https://www.google2.com/') }
+
+ before do
+ release.reload
+ end
+
+ context 'when params are specified for update' do
+ let(:params) do
+ { links_attributes: [{ id: link1.id, name: 'new' }] }
+ end
+
+ it 'updates the link successfully' do
+ is_expected.to eq(true)
+
+ expect(release.links.count).to eq(2)
+ expect(release.links.first.name).to eq('new')
+ end
+ end
+
+ context 'when params are specified for deletion' do
+ let(:params) do
+ { links_attributes: [{ id: link1.id, _destroy: true }] }
+ end
+
+ it 'removes the link successfuly' do
+ is_expected.to eq(true)
+
+ expect(release.links.count).to eq(1)
+ expect(release.links.first.name).to eq(link2.name)
+ end
+ end
+ end
+ end
+
describe '#sources' do
subject { release.sources }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index dd54a701282..3a4de7ba279 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -483,12 +483,6 @@ RSpec.describe Repository do
it { is_expected.to be_an_instance_of(::Blob) }
end
- context 'readme blob on HEAD' do
- subject { repository.blob_at(repository.head_commit.sha, 'README.md') }
-
- it { is_expected.to be_an_instance_of(::ReadmeBlob) }
- end
-
context 'readme blob not on HEAD' do
subject { repository.blob_at(repository.find_branch('feature').target, 'README.md') }
@@ -1142,11 +1136,11 @@ RSpec.describe Repository do
expect(repository.license_key).to be_nil
end
- it 'returns nil when the content is not recognizable' do
+ it 'returns other when the content is not recognizable' do
repository.create_file(user, 'LICENSE', 'Gitlab B.V.',
message: 'Add LICENSE', branch_name: 'master')
- expect(repository.license_key).to be_nil
+ expect(repository.license_key).to eq('other')
end
it 'returns nil when the commit SHA does not exist' do
@@ -1186,11 +1180,12 @@ RSpec.describe Repository do
expect(repository.license).to be_nil
end
- it 'returns nil when the content is not recognizable' do
+ it 'returns other when the content is not recognizable' do
+ license = Licensee::License.new('other')
repository.create_file(user, 'LICENSE', 'Gitlab B.V.',
message: 'Add LICENSE', branch_name: 'master')
- expect(repository.license).to be_nil
+ expect(repository.license).to eq(license)
end
it 'returns the license' do
@@ -1938,7 +1933,6 @@ RSpec.describe Repository do
expect(repository).to receive(:expire_method_caches).with([
:size,
:commit_count,
- :rendered_readme,
:readme_path,
:contribution_guide,
:changelog,
@@ -1955,8 +1949,8 @@ RSpec.describe Repository do
:root_ref,
:merged_branch_names,
:has_visible_content?,
- :issue_template_names,
- :merge_request_template_names,
+ :issue_template_names_by_category,
+ :merge_request_template_names_by_category,
:user_defined_metrics_dashboard_paths,
:xcode_project?,
:has_ambiguous_refs?
@@ -2314,14 +2308,6 @@ RSpec.describe Repository do
expect(repository.readme).to be_nil
end
end
-
- context 'when a README exists' do
- let(:project) { create(:project, :repository) }
-
- it 'returns the README' do
- expect(repository.readme).to be_an_instance_of(ReadmeBlob)
- end
- end
end
end
@@ -2527,9 +2513,8 @@ RSpec.describe Repository do
describe '#refresh_method_caches' do
it 'refreshes the caches of the given types' do
expect(repository).to receive(:expire_method_caches)
- .with(%i(rendered_readme readme_path license_blob license_key license))
+ .with(%i(readme_path license_blob license_key license))
- expect(repository).to receive(:rendered_readme)
expect(repository).to receive(:readme_path)
expect(repository).to receive(:license_blob)
expect(repository).to receive(:license_key)
@@ -3049,4 +3034,51 @@ RSpec.describe Repository do
end
end
end
+
+ describe '.pick_storage_shard', :request_store do
+ before do
+ storages = {
+ 'default' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories'),
+ 'picked' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories')
+ }
+
+ allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ Gitlab::CurrentSettings.current_application_settings
+
+ update_storages({ 'picked' => 0, 'default' => 100 })
+ end
+
+ context 'when expire is false' do
+ it 'does not expire existing repository storage value' do
+ previous_storage = described_class.pick_storage_shard
+ expect(previous_storage).to eq('default')
+ expect(Gitlab::CurrentSettings).not_to receive(:expire_current_application_settings)
+
+ update_storages({ 'picked' => 100, 'default' => 0 })
+
+ new_storage = described_class.pick_storage_shard(expire: false)
+ expect(new_storage).to eq(previous_storage)
+ end
+ end
+
+ context 'when expire is true' do
+ it 'expires existing repository storage value' do
+ previous_storage = described_class.pick_storage_shard
+ expect(previous_storage).to eq('default')
+ expect(Gitlab::CurrentSettings).to receive(:expire_current_application_settings).and_call_original
+
+ update_storages({ 'picked' => 100, 'default' => 0 })
+
+ new_storage = described_class.pick_storage_shard(expire: true)
+ expect(new_storage).to eq('picked')
+ end
+ end
+
+ def update_storages(storage_hash)
+ settings = ApplicationSetting.last
+ settings.repository_storages_weighted = storage_hash
+ settings.save!
+ end
+ end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 04b3920cd6c..9ffefd4bbf7 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -39,35 +39,29 @@ RSpec.describe Service do
end
end
- context 'with an existing service template' do
- before do
+ context 'with existing services' do
+ before_all do
create(:service, :template)
+ create(:service, :instance)
+ create(:service, project: project)
+ create(:service, group: group, project: nil)
end
- it 'validates only one service template per type' do
+ it 'allows only one service template per type' do
expect(build(:service, :template)).to be_invalid
end
- end
- context 'with an existing instance service' do
- before do
- create(:service, :instance)
- end
-
- it 'validates only one service instance per type' do
+ it 'allows only one instance service per type' do
expect(build(:service, :instance)).to be_invalid
end
- end
- it 'validates uniqueness of type and project_id on create' do
- expect(create(:service, project: project, type: 'Service')).to be_valid
- expect(build(:service, project: project, type: 'Service').valid?(:create)).to eq(false)
- expect(build(:service, project: project, type: 'Service').valid?(:update)).to eq(true)
- end
+ it 'allows only one project service per type' do
+ expect(build(:service, project: project)).to be_invalid
+ end
- it 'validates uniqueness of type and group_id' do
- expect(create(:service, group_id: group.id, project_id: nil, type: 'Service')).to be_valid
- expect(build(:service, group_id: group.id, project_id: nil, type: 'Service')).to be_invalid
+ it 'allows only one group service per type' do
+ expect(build(:service, group: group, project: nil)).to be_invalid
+ end
end
end
@@ -753,38 +747,6 @@ RSpec.describe Service do
end
end
- describe "callbacks" do
- let!(:service) do
- RedmineService.new(
- project: project,
- active: true,
- properties: {
- project_url: 'http://redmine/projects/project_name_in_redmine',
- issues_url: "http://redmine/#{project.id}/project_name_in_redmine/:id",
- new_issue_url: 'http://redmine/projects/project_name_in_redmine/issues/new'
- }
- )
- end
-
- describe "on create" do
- it "updates the has_external_issue_tracker boolean" do
- expect do
- service.save!
- end.to change { service.project.has_external_issue_tracker }.from(false).to(true)
- end
- end
-
- describe "on update" do
- it "updates the has_external_issue_tracker boolean" do
- service.save!
-
- expect do
- service.update(active: false)
- end.to change { service.project.has_external_issue_tracker }.from(true).to(false)
- end
- end
- end
-
describe '#api_field_names' do
let(:fake_service) do
Class.new(Service) do
@@ -864,20 +826,6 @@ RSpec.describe Service do
end
end
- describe '#external_issue_tracker?' do
- where(:category, :active, :result) do
- :issue_tracker | true | true
- :issue_tracker | false | false
- :common | true | false
- end
-
- with_them do
- it 'returns the right result' do
- expect(build(:service, category: category, active: active).external_issue_tracker?).to eq(result)
- end
- end
- end
-
describe '#external_wiki?' do
where(:type, :active, :result) do
'ExternalWikiService' | true | true
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 68d183d5d55..623767d19e0 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -630,14 +630,10 @@ RSpec.describe Snippet do
subject { snippet.repository_storage }
before do
- expect_next_instance_of(ApplicationSetting) do |instance|
- expect(instance).to receive(:pick_repository_storage).and_return('picked')
- end
+ expect(Repository).to receive(:pick_storage_shard).and_return('picked')
end
it 'returns repository storage from ApplicationSetting' do
- expect(described_class).to receive(:pick_repository_storage).and_call_original
-
expect(subject).to eq 'picked'
end
diff --git a/spec/models/terraform/state_spec.rb b/spec/models/terraform/state_spec.rb
index ed311314086..1319e2adb03 100644
--- a/spec/models/terraform/state_spec.rb
+++ b/spec/models/terraform/state_spec.rb
@@ -8,8 +8,11 @@ RSpec.describe Terraform::State do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:locked_by_user).class_name('User') }
+ it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_presence_of(:project_id) }
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
+
describe 'scopes' do
describe '.ordered_by_name' do
let_it_be(:project) { create(:project) }
@@ -25,6 +28,15 @@ RSpec.describe Terraform::State do
it { expect(subject.map(&:name)).to eq(names.sort) }
end
+
+ describe '.with_name' do
+ let_it_be(:matching_name) { create(:terraform_state, name: 'matching-name') }
+ let_it_be(:other_name) { create(:terraform_state, name: 'other-name') }
+
+ subject { described_class.with_name(matching_name.name) }
+
+ it { is_expected.to contain_exactly(matching_name) }
+ end
end
describe '#destroy' do
diff --git a/spec/models/terraform/state_version_spec.rb b/spec/models/terraform/state_version_spec.rb
index 97ac77d5e7b..ac2e8d167b3 100644
--- a/spec/models/terraform/state_version_spec.rb
+++ b/spec/models/terraform/state_version_spec.rb
@@ -24,6 +24,24 @@ RSpec.describe Terraform::StateVersion do
it { expect(subject.map(&:version)).to eq(versions.sort.reverse) }
end
+
+ describe '.with_files_stored_locally' do
+ subject { described_class.with_files_stored_locally }
+
+ it 'includes states with local storage' do
+ create_list(:terraform_state_version, 5)
+
+ expect(subject).to have_attributes(count: 5)
+ end
+
+ it 'excludes states without local storage' do
+ stub_terraform_state_object_storage
+
+ create_list(:terraform_state_version, 5)
+
+ expect(subject).to have_attributes(count: 0)
+ end
+ end
end
context 'file storage' do
diff --git a/spec/models/token_with_iv_spec.rb b/spec/models/token_with_iv_spec.rb
new file mode 100644
index 00000000000..8dbccc19217
--- /dev/null
+++ b/spec/models/token_with_iv_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TokenWithIv do
+ describe 'validations' do
+ it { is_expected.to validate_presence_of :hashed_token }
+ it { is_expected.to validate_presence_of :iv }
+ it { is_expected.to validate_presence_of :hashed_plaintext_token }
+ end
+
+ describe '.find_by_hashed_token' do
+ it 'only includes matching record' do
+ matching_record = create(:token_with_iv, hashed_token: ::Digest::SHA256.digest('hashed-token'))
+ create(:token_with_iv)
+
+ expect(described_class.find_by_hashed_token('hashed-token')).to eq(matching_record)
+ end
+ end
+
+ describe '.find_by_plaintext_token' do
+ it 'only includes matching record' do
+ matching_record = create(:token_with_iv, hashed_plaintext_token: ::Digest::SHA256.digest('hashed-token'))
+ create(:token_with_iv)
+
+ expect(described_class.find_by_plaintext_token('hashed-token')).to eq(matching_record)
+ end
+ end
+end
diff --git a/spec/models/u2f_registration_spec.rb b/spec/models/u2f_registration_spec.rb
new file mode 100644
index 00000000000..1f2e4d1e447
--- /dev/null
+++ b/spec/models/u2f_registration_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe U2fRegistration do
+ let_it_be(:user) { create(:user) }
+ let(:u2f_registration) do
+ device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
+ create(:u2f_registration, name: 'u2f_device',
+ user: user,
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: Base64.strict_encode64(device.origin_public_key_raw))
+ end
+
+ describe 'callbacks' do
+ describe '#create_webauthn_registration' do
+ it 'creates webauthn registration' do
+ u2f_registration.save!
+
+ webauthn_registration = WebauthnRegistration.where(u2f_registration_id: u2f_registration.id)
+ expect(webauthn_registration).to exist
+ end
+
+ it 'logs error' do
+ allow(Gitlab::Auth::U2fWebauthnConverter).to receive(:new).and_raise('boom!')
+ expect(Gitlab::AppJsonLogger).to(
+ receive(:error).with(a_hash_including(event: 'u2f_migration',
+ error: 'RuntimeError',
+ message: 'U2F to WebAuthn conversion failed'))
+ )
+
+ u2f_registration.save!
+ end
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 0935d3576a4..860c015e166 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2477,7 +2477,7 @@ RSpec.describe User do
it 'is false if avatar is html page' do
user.update_attribute(:avatar, 'uploads/avatar.html')
- expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico'])
+ expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp'])
end
end
@@ -2831,6 +2831,79 @@ RSpec.describe User do
end
end
+ describe '#following?' do
+ it 'check if following another user' do
+ user = create :user
+ followee1 = create :user
+
+ expect(user.follow(followee1)).to be_truthy
+
+ expect(user.following?(followee1)).to be_truthy
+
+ expect(user.unfollow(followee1)).to be_truthy
+
+ expect(user.following?(followee1)).to be_falsey
+ end
+ end
+
+ describe '#follow' do
+ it 'follow another user' do
+ user = create :user
+ followee1 = create :user
+ followee2 = create :user
+
+ expect(user.followees).to be_empty
+
+ expect(user.follow(followee1)).to be_truthy
+ expect(user.follow(followee1)).to be_falsey
+
+ expect(user.followees).to contain_exactly(followee1)
+
+ expect(user.follow(followee2)).to be_truthy
+ expect(user.follow(followee2)).to be_falsey
+
+ expect(user.followees).to contain_exactly(followee1, followee2)
+ end
+
+ it 'follow itself is not possible' do
+ user = create :user
+
+ expect(user.followees).to be_empty
+
+ expect(user.follow(user)).to be_falsey
+
+ expect(user.followees).to be_empty
+ end
+ end
+
+ describe '#unfollow' do
+ it 'unfollow another user' do
+ user = create :user
+ followee1 = create :user
+ followee2 = create :user
+
+ expect(user.followees).to be_empty
+
+ expect(user.follow(followee1)).to be_truthy
+ expect(user.follow(followee1)).to be_falsey
+
+ expect(user.follow(followee2)).to be_truthy
+ expect(user.follow(followee2)).to be_falsey
+
+ expect(user.followees).to contain_exactly(followee1, followee2)
+
+ expect(user.unfollow(followee1)).to be_truthy
+ expect(user.unfollow(followee1)).to be_falsey
+
+ expect(user.followees).to contain_exactly(followee2)
+
+ expect(user.unfollow(followee2)).to be_truthy
+ expect(user.unfollow(followee2)).to be_falsey
+
+ expect(user.followees).to be_empty
+ end
+ end
+
describe '.find_by_private_commit_email' do
context 'with email' do
let_it_be(:user) { create(:user) }
diff --git a/spec/models/user_status_spec.rb b/spec/models/user_status_spec.rb
index 2c0664bd165..51dd91149cc 100644
--- a/spec/models/user_status_spec.rb
+++ b/spec/models/user_status_spec.rb
@@ -17,4 +17,34 @@ RSpec.describe UserStatus do
expect { status.user.destroy }.to change { described_class.count }.from(1).to(0)
end
+
+ describe '#clear_status_after=' do
+ it 'sets clear_status_at' do
+ status = build(:user_status)
+
+ freeze_time do
+ status.clear_status_after = '8_hours'
+
+ expect(status.clear_status_at).to be_like_time(8.hours.from_now)
+ end
+ end
+
+ it 'unsets clear_status_at' do
+ status = build(:user_status, clear_status_at: 8.hours.from_now)
+
+ status.clear_status_after = nil
+
+ expect(status.clear_status_at).to be_nil
+ end
+
+ context 'when unknown clear status is given' do
+ it 'unsets clear_status_at' do
+ status = build(:user_status, clear_status_at: 8.hours.from_now)
+
+ status.clear_status_after = 'unknown'
+
+ expect(status.clear_status_at).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 8bd4a463f87..6ba3ab6aace 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -468,6 +468,49 @@ RSpec.describe ProjectPolicy do
end
end
+ context "project bots" do
+ let(:project_bot) { create(:user, :project_bot) }
+ let(:user) { create(:user) }
+
+ context "project_bot_access" do
+ context "when regular user and part of the project" do
+ let(:current_user) { user }
+
+ before do
+ project.add_developer(user)
+ end
+
+ it { is_expected.not_to be_allowed(:project_bot_access)}
+ end
+
+ context "when project bot and not part of the project" do
+ let(:current_user) { project_bot }
+
+ it { is_expected.not_to be_allowed(:project_bot_access)}
+ end
+
+ context "when project bot and part of the project" do
+ let(:current_user) { project_bot }
+
+ before do
+ project.add_developer(project_bot)
+ end
+
+ it { is_expected.to be_allowed(:project_bot_access)}
+ end
+ end
+
+ context 'with resource access tokens' do
+ let(:current_user) { project_bot }
+
+ before do
+ project.add_maintainer(project_bot)
+ end
+
+ it { is_expected.not_to be_allowed(:admin_resource_access_tokens)}
+ end
+ end
+
describe 'read_prometheus_alerts' do
context 'with admin' do
let(:current_user) { admin }
@@ -822,6 +865,28 @@ RSpec.describe ProjectPolicy do
end
end
+ context 'security configuration feature' do
+ %w(guest reporter).each do |role|
+ context role do
+ let(:current_user) { send(role) }
+
+ it 'prevents reading security configuration' do
+ expect_disallowed(:read_security_configuration)
+ end
+ end
+ end
+
+ %w(developer maintainer owner).each do |role|
+ context role do
+ let(:current_user) { send(role) }
+
+ it 'allows reading security configuration' do
+ expect_allowed(:read_security_configuration)
+ end
+ end
+ end
+ end
+
describe 'design permissions' do
let(:current_user) { guest }
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index f78ad38f4e8..43b677483ce 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
describe '#artifacts' do
context "when option contains archive-type artifacts" do
- let(:build) { create(:ci_build, options: { artifacts: archive } ) }
+ let(:build) { create(:ci_build, options: { artifacts: archive }) }
it 'presents correct hash' do
expect(presenter.artifacts.first).to include(archive_expectation)
@@ -196,16 +196,6 @@ RSpec.describe Ci::BuildRunnerPresenter do
expect(subject[0]).to match(/^\+[0-9a-f]{40}:refs\/pipelines\/[0-9]+$/)
end
- context 'when the scalability_ci_fetch_sha feature flag is disabled' do
- before do
- stub_feature_flags(scalability_ci_fetch_sha: false)
- end
-
- it 'fetches the ref by name' do
- expect(subject[0]).to eq("+refs/pipelines/#{pipeline.id}:refs/pipelines/#{pipeline.id}")
- end
- end
-
context 'when ref is tag' do
let(:build) { create(:ci_build, :tag) }
@@ -259,7 +249,7 @@ RSpec.describe Ci::BuildRunnerPresenter do
it 'returns the correct refspecs' do
is_expected.to contain_exactly("+#{pipeline.sha}:refs/pipelines/#{pipeline.id}",
- "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
+ "+refs/heads/#{build.ref}:refs/remotes/origin/#{build.ref}")
end
end
end
diff --git a/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb b/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb
new file mode 100644
index 00000000000..06d5422eed3
--- /dev/null
+++ b/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineArtifacts::CodeQualityMrDiffPresenter do
+ let(:pipeline_artifact) { create(:ci_pipeline_artifact, :with_codequality_mr_diff_report) }
+
+ subject(:presenter) { described_class.new(pipeline_artifact) }
+
+ describe '#for_files' do
+ subject(:quality_data) { presenter.for_files(filenames) }
+
+ context 'when code quality has data' do
+ context 'when filenames is empty' do
+ let(:filenames) { %w() }
+
+ it 'returns hash without quality' do
+ expect(quality_data).to match(files: {})
+ end
+ end
+
+ context 'when filenames do not match code quality data' do
+ let(:filenames) { %w(demo.rb) }
+
+ it 'returns hash without quality' do
+ expect(quality_data).to match(files: {})
+ end
+ end
+
+ context 'when filenames matches code quality data' do
+ context 'when asking for one filename' do
+ let(:filenames) { %w(file_a.rb) }
+
+ it 'returns quality for the given filename' do
+ expect(quality_data).to match(
+ files: {
+ "file_a.rb" => [
+ { line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "major" },
+ { line: 10, description: "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", severity: "minor" }
+ ]
+ }
+ )
+ end
+ end
+
+ context 'when asking for multiple filenames' do
+ let(:filenames) { %w(file_a.rb file_b.rb) }
+
+ it 'returns quality for the given filenames' do
+ expect(quality_data).to match(
+ files: {
+ "file_a.rb" => [
+ { line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "major" },
+ { line: 10, description: "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", severity: "minor" }
+ ],
+ "file_b.rb" => [
+ { line: 10, description: "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count.", severity: "minor" }
+ ]
+ }
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/presenters/gitlab/whats_new/item_presenter_spec.rb b/spec/presenters/gitlab/whats_new/item_presenter_spec.rb
deleted file mode 100644
index 9b04741aa60..00000000000
--- a/spec/presenters/gitlab/whats_new/item_presenter_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::WhatsNew::ItemPresenter do
- let(:present) { Gitlab::WhatsNew::ItemPresenter.present(item) }
- let(:item) { { "packages" => %w(Core Starter Premium Ultimate) } }
- let(:gitlab_com) { true }
-
- before do
- allow(Gitlab).to receive(:com?).and_return(gitlab_com)
- end
-
- describe '.present' do
- context 'when on Gitlab.com' do
- it 'transforms package names to gitlab.com friendly package names' do
- expect(present).to eq({ "packages" => %w(Free Bronze Silver Gold) })
- end
- end
-
- context 'when not on Gitlab.com' do
- let(:gitlab_com) { false }
-
- it 'does not transform package names' do
- expect(present).to eq({ "packages" => %w(Core Starter Premium Ultimate) })
- end
- end
- end
-end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index a9050c233af..98bcbd8384b 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -350,7 +350,7 @@ RSpec.describe ProjectPresenter do
is_link: false,
label: a_string_including("New file"),
link: presenter.project_new_blob_path(project, 'master'),
- class_modifier: 'missing'
+ class_modifier: 'dashed'
)
end
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index 9fd30213133..8bd6049e6fa 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -36,6 +36,12 @@ RSpec.describe API::API do
expect(response).to have_gitlab_http_status(:ok)
end
+ it 'does authorize user for head request' do
+ head api('/groups', personal_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
it 'does not authorize user for revoked token' do
revoked = create(:personal_access_token, :revoked, user: user, scopes: [:read_api])
@@ -126,4 +132,34 @@ RSpec.describe API::API do
get(api('/users'))
end
end
+
+ describe 'supported content-types' do
+ context 'GET /user/:id.txt' do
+ let_it_be(:user) { create(:user) }
+
+ subject { get api("/users/#{user.id}.txt", user) }
+
+ it 'returns application/json' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/json')
+ expect(response.body).to include('{"id":')
+ end
+
+ context 'when api_always_use_application_json is disabled' do
+ before do
+ stub_feature_flags(api_always_use_application_json: false)
+ end
+
+ it 'returns text/plain' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('text/plain')
+ expect(response.body).to include('#<API::Entities::User:')
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/applications_spec.rb b/spec/requests/api/applications_spec.rb
index 63fbf6e32dd..ca09f5524ca 100644
--- a/spec/requests/api/applications_spec.rb
+++ b/spec/requests/api/applications_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe API::Applications, :api do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response).to be_a Hash
- expect(json_response['message']['redirect_uri'][0]).to eq('must be an absolute URI.')
+ expect(json_response['message']['redirect_uri'][0]).to eq('must be a valid URI.')
end
it 'does not allow creating an application with a forbidden URI format' do
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 767b5704851..a9afbd8bd72 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -312,7 +312,7 @@ RSpec.describe API::Ci::Pipelines do
let(:query) { {} }
let(:api_user) { user }
let_it_be(:job) do
- create(:ci_build, :success, pipeline: pipeline,
+ create(:ci_build, :success, name: 'build', pipeline: pipeline,
artifacts_expire_at: 1.day.since)
end
@@ -405,6 +405,38 @@ RSpec.describe API::Ci::Pipelines do
get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
end.not_to exceed_all_query_limit(control_count)
end
+
+ context 'pipeline has retried jobs' do
+ before_all do
+ job.update!(retried: true)
+ end
+
+ let_it_be(:successor) { create(:ci_build, :success, name: 'build', pipeline: pipeline) }
+
+ it 'does not return retried jobs by default' do
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ end
+
+ context 'when include_retried is false' do
+ let(:query) { { include_retried: false } }
+
+ it 'does not return retried jobs' do
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ end
+ end
+
+ context 'when include_retried is true' do
+ let(:query) { { include_retried: true } }
+
+ it 'returns retried jobs' do
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(2)
+ expect(json_response[0]['name']).to eq(json_response[1]['name'])
+ end
+ end
+ end
end
context 'no pipeline is found' do
diff --git a/spec/requests/api/debian_group_packages_spec.rb b/spec/requests/api/debian_group_packages_spec.rb
index 8a05d20fb33..9d63d675a02 100644
--- a/spec/requests/api/debian_group_packages_spec.rb
+++ b/spec/requests/api/debian_group_packages_spec.rb
@@ -6,32 +6,32 @@ RSpec.describe API::DebianGroupPackages do
include WorkhorseHelpers
include_context 'Debian repository shared context', :group do
- describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release.gpg' do
- let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/Release.gpg" }
+ describe 'GET groups/:id/packages/debian/dists/*distribution/Release.gpg' do
+ let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/Release.gpg" }
it_behaves_like 'Debian group repository GET endpoint', :not_found, nil
end
- describe 'GET groups/:id/-/packages/debian/dists/*distribution/Release' do
- let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/Release" }
+ describe 'GET groups/:id/packages/debian/dists/*distribution/Release' do
+ let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/Release" }
it_behaves_like 'Debian group repository GET endpoint', :success, 'TODO Release'
end
- describe 'GET groups/:id/-/packages/debian/dists/*distribution/InRelease' do
- let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/InRelease" }
+ describe 'GET groups/:id/packages/debian/dists/*distribution/InRelease' do
+ let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/InRelease" }
it_behaves_like 'Debian group repository GET endpoint', :not_found, nil
end
- describe 'GET groups/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
- let(:url) { "/groups/#{group.id}/-/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" }
+ describe 'GET groups/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
+ let(:url) { "/groups/#{group.id}/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" }
it_behaves_like 'Debian group repository GET endpoint', :success, 'TODO Packages'
end
- describe 'GET groups/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name' do
- let(:url) { "/groups/#{group.id}/-/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" }
+ describe 'GET groups/:id/packages/debian/pool/:component/:letter/:source_package/:file_name' do
+ let(:url) { "/groups/#{group.id}/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" }
it_behaves_like 'Debian group repository GET endpoint', :success, 'TODO File'
end
diff --git a/spec/requests/api/debian_project_packages_spec.rb b/spec/requests/api/debian_project_packages_spec.rb
index 663b69b1b76..4941f2a77f4 100644
--- a/spec/requests/api/debian_project_packages_spec.rb
+++ b/spec/requests/api/debian_project_packages_spec.rb
@@ -6,46 +6,46 @@ RSpec.describe API::DebianProjectPackages do
include WorkhorseHelpers
include_context 'Debian repository shared context', :project do
- describe 'GET projects/:id/-/packages/debian/dists/*distribution/Release.gpg' do
- let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/Release.gpg" }
+ describe 'GET projects/:id/packages/debian/dists/*distribution/Release.gpg' do
+ let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/Release.gpg" }
it_behaves_like 'Debian project repository GET endpoint', :not_found, nil
end
- describe 'GET projects/:id/-/packages/debian/dists/*distribution/Release' do
- let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/Release" }
+ describe 'GET projects/:id/packages/debian/dists/*distribution/Release' do
+ let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/Release" }
it_behaves_like 'Debian project repository GET endpoint', :success, 'TODO Release'
end
- describe 'GET projects/:id/-/packages/debian/dists/*distribution/InRelease' do
- let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/InRelease" }
+ describe 'GET projects/:id/packages/debian/dists/*distribution/InRelease' do
+ let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/InRelease" }
it_behaves_like 'Debian project repository GET endpoint', :not_found, nil
end
- describe 'GET projects/:id/-/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
- let(:url) { "/projects/#{project.id}/-/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" }
+ describe 'GET projects/:id/packages/debian/dists/*distribution/:component/binary-:architecture/Packages' do
+ let(:url) { "/projects/#{project.id}/packages/debian/dists/#{distribution}/#{component}/binary-#{architecture}/Packages" }
it_behaves_like 'Debian project repository GET endpoint', :success, 'TODO Packages'
end
- describe 'GET projects/:id/-/packages/debian/pool/:component/:letter/:source_package/:file_name' do
- let(:url) { "/projects/#{project.id}/-/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" }
+ describe 'GET projects/:id/packages/debian/pool/:component/:letter/:source_package/:file_name' do
+ let(:url) { "/projects/#{project.id}/packages/debian/pool/#{component}/#{letter}/#{source_package}/#{package_name}_#{package_version}_#{architecture}.deb" }
it_behaves_like 'Debian project repository GET endpoint', :success, 'TODO File'
end
- describe 'PUT projects/:id/-/packages/debian/incoming/:file_name' do
+ describe 'PUT projects/:id/packages/debian/:file_name' do
let(:method) { :put }
- let(:url) { "/projects/#{project.id}/-/packages/debian/incoming/#{file_name}" }
+ let(:url) { "/projects/#{project.id}/packages/debian/#{file_name}" }
it_behaves_like 'Debian project repository PUT endpoint', :created, nil
end
- describe 'PUT projects/:id/-/packages/debian/incoming/:file_name/authorize' do
+ describe 'PUT projects/:id/packages/debian/:file_name/authorize' do
let(:method) { :put }
- let(:url) { "/projects/#{project.id}/-/packages/debian/incoming/#{file_name}/authorize" }
+ let(:url) { "/projects/#{project.id}/packages/debian/#{file_name}/authorize" }
it_behaves_like 'Debian project repository PUT endpoint', :created, nil, is_authorize: true
end
diff --git a/spec/requests/api/deploy_tokens_spec.rb b/spec/requests/api/deploy_tokens_spec.rb
index 8ec4f888e2e..7a31ff725c8 100644
--- a/spec/requests/api/deploy_tokens_spec.rb
+++ b/spec/requests/api/deploy_tokens_spec.rb
@@ -10,24 +10,12 @@ RSpec.describe API::DeployTokens do
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
let!(:group_deploy_token) { create(:deploy_token, :group, groups: [group]) }
- shared_examples 'with feature flag disabled' do
- context 'disabled feature flag' do
- before do
- stub_feature_flags(deploy_tokens_api: false)
- end
-
- it { is_expected.to have_gitlab_http_status(:service_unavailable) }
- end
- end
-
describe 'GET /deploy_tokens' do
subject do
get api('/deploy_tokens', user)
response
end
- it_behaves_like 'with feature flag disabled'
-
context 'when unauthenticated' do
let(:user) { nil }
@@ -81,8 +69,6 @@ RSpec.describe API::DeployTokens do
project.add_maintainer(user)
end
- it_behaves_like 'with feature flag disabled'
-
it { is_expected.to have_gitlab_http_status(:ok) }
it 'returns all deploy tokens for the project' do
@@ -128,8 +114,6 @@ RSpec.describe API::DeployTokens do
group.add_maintainer(user)
end
- it_behaves_like 'with feature flag disabled'
-
it { is_expected.to have_gitlab_http_status(:ok) }
it 'returns all deploy tokens for the group' do
diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb
index 6a8d5f91abd..110d6e2f99e 100644
--- a/spec/requests/api/events_spec.rb
+++ b/spec/requests/api/events_spec.rb
@@ -55,6 +55,12 @@ RSpec.describe API::Events do
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
end
+
+ it 'returns "200" response on head request' do
+ head api('/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31', personal_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'when the requesting token does not have "read_user" or "api" scope' do
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index d162d288129..a47be1ead9c 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -4,6 +4,9 @@ require 'spec_helper'
RSpec.describe API::GenericPackages do
include HttpBasicAuthHelpers
+ using RSpec::Parameterized::TableSyntax
+
+ include_context 'workhorse headers'
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:project, reload: true) { create(:project) }
@@ -13,8 +16,6 @@ RSpec.describe API::GenericPackages do
let_it_be(:project_deploy_token_ro) { create(:project_deploy_token, deploy_token: deploy_token_ro, project: project) }
let_it_be(:deploy_token_wo) { create(:deploy_token, read_package_registry: false, write_package_registry: true) }
let_it_be(:project_deploy_token_wo) { create(:project_deploy_token, deploy_token: deploy_token_wo, project: project) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
let(:user) { personal_access_token.user }
let(:ci_build) { create(:ci_build, :running, user: user) }
@@ -76,8 +77,6 @@ RSpec.describe API::GenericPackages do
describe 'PUT /api/v4/projects/:id/packages/generic/:package_name/:package_version/:file_name/authorize' do
context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
where(:project_visibility, :user_role, :member?, :authenticate_with, :expected_status) do
'PUBLIC' | :developer | true | :personal_access_token | :success
'PUBLIC' | :guest | true | :personal_access_token | :forbidden
@@ -130,7 +129,7 @@ RSpec.describe API::GenericPackages do
end
it "responds with #{params[:expected_status]}" do
- authorize_upload_file(workhorse_header.merge(auth_header))
+ authorize_upload_file(workhorse_headers.merge(auth_header))
expect(response).to have_gitlab_http_status(expected_status)
end
@@ -145,7 +144,7 @@ RSpec.describe API::GenericPackages do
with_them do
it "responds with #{params[:expected_status]}" do
- authorize_upload_file(workhorse_header.merge(deploy_token_auth_header))
+ authorize_upload_file(workhorse_headers.merge(deploy_token_auth_header))
expect(response).to have_gitlab_http_status(expected_status)
end
@@ -163,7 +162,7 @@ RSpec.describe API::GenericPackages do
end
with_them do
- subject { authorize_upload_file(workhorse_header.merge(personal_access_token_header), param_name => param_value) }
+ subject { authorize_upload_file(workhorse_headers.merge(personal_access_token_header), param_name => param_value) }
it_behaves_like 'secure endpoint'
end
@@ -174,7 +173,7 @@ RSpec.describe API::GenericPackages do
stub_feature_flags(generic_packages: false)
project.add_developer(user)
- authorize_upload_file(workhorse_header.merge(personal_access_token_header))
+ authorize_upload_file(workhorse_headers.merge(personal_access_token_header))
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -194,8 +193,6 @@ RSpec.describe API::GenericPackages do
let(:params) { { file: file_upload } }
context 'authentication' do
- using RSpec::Parameterized::TableSyntax
-
where(:project_visibility, :user_role, :member?, :authenticate_with, :expected_status) do
'PUBLIC' | :guest | true | :personal_access_token | :forbidden
'PUBLIC' | :guest | true | :user_basic_auth | :forbidden
@@ -242,7 +239,7 @@ RSpec.describe API::GenericPackages do
end
it "responds with #{params[:expected_status]}" do
- headers = workhorse_header.merge(auth_header)
+ headers = workhorse_headers.merge(auth_header)
upload_file(params, headers)
@@ -257,7 +254,7 @@ RSpec.describe API::GenericPackages do
with_them do
it "responds with #{params[:expected_status]}" do
- headers = workhorse_header.merge(deploy_token_auth_header)
+ headers = workhorse_headers.merge(deploy_token_auth_header)
upload_file(params, headers)
@@ -273,7 +270,7 @@ RSpec.describe API::GenericPackages do
shared_examples 'creates a package and package file' do
it 'creates a package and package file' do
- headers = workhorse_header.merge(auth_header)
+ headers = workhorse_headers.merge(auth_header)
expect { upload_file(params, headers) }
.to change { project.packages.generic.count }.by(1)
@@ -284,6 +281,7 @@ RSpec.describe API::GenericPackages do
package = project.packages.generic.last
expect(package.name).to eq('mypackage')
+ expect(package.status).to eq('default')
expect(package.version).to eq('0.0.1')
if should_set_build_info
@@ -296,6 +294,39 @@ RSpec.describe API::GenericPackages do
expect(package_file.file_name).to eq('myfile.tar.gz')
end
end
+
+ context 'with a status' do
+ context 'valid status' do
+ let(:params) { super().merge(status: 'hidden') }
+
+ it 'assigns the status to the package' do
+ headers = workhorse_headers.merge(auth_header)
+
+ upload_file(params, headers)
+
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:created)
+
+ package = project.packages.find_by(name: 'mypackage')
+ expect(package).to be_hidden
+ end
+ end
+ end
+
+ context 'invalid status' do
+ let(:params) { super().merge(status: 'processing') }
+
+ it 'rejects the package' do
+ headers = workhorse_headers.merge(auth_header)
+
+ upload_file(params, headers)
+
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+ end
end
context 'when valid personal access token is used' do
@@ -327,26 +358,26 @@ RSpec.describe API::GenericPackages do
end
context 'event tracking' do
- subject { upload_file(params, workhorse_header.merge(personal_access_token_header)) }
+ subject { upload_file(params, workhorse_headers.merge(personal_access_token_header)) }
it_behaves_like 'a gitlab tracking event', described_class.name, 'push_package'
end
it 'rejects request without a file from workhorse' do
- headers = workhorse_header.merge(personal_access_token_header)
+ headers = workhorse_headers.merge(personal_access_token_header)
upload_file({}, headers)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'rejects request without an auth token' do
- upload_file(params, workhorse_header)
+ upload_file(params, workhorse_headers)
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'rejects request without workhorse rewritten fields' do
- headers = workhorse_header.merge(personal_access_token_header)
+ headers = workhorse_headers.merge(personal_access_token_header)
upload_file(params, headers, send_rewritten_field: false)
expect(response).to have_gitlab_http_status(:bad_request)
@@ -357,7 +388,7 @@ RSpec.describe API::GenericPackages do
allow(uploaded_file).to receive(:size).and_return(project.actual_limits.generic_packages_max_file_size + 1)
end
- headers = workhorse_header.merge(personal_access_token_header)
+ headers = workhorse_headers.merge(personal_access_token_header)
upload_file(params, headers)
expect(response).to have_gitlab_http_status(:bad_request)
@@ -373,8 +404,6 @@ RSpec.describe API::GenericPackages do
end
context 'application security' do
- using RSpec::Parameterized::TableSyntax
-
where(:param_name, :param_value) do
:package_name | 'my-package/../'
:package_name | 'my-package%2f%2e%2e%2f'
@@ -383,7 +412,7 @@ RSpec.describe API::GenericPackages do
end
with_them do
- subject { upload_file(params, workhorse_header.merge(personal_access_token_header), param_name => param_value) }
+ subject { upload_file(params, workhorse_headers.merge(personal_access_token_header), param_name => param_value) }
it_behaves_like 'secure endpoint'
end
@@ -404,8 +433,6 @@ RSpec.describe API::GenericPackages do
end
describe 'GET /api/v4/projects/:id/packages/generic/:package_name/:package_version/:file_name' do
- using RSpec::Parameterized::TableSyntax
-
let_it_be(:package) { create(:generic_package, project: project) }
let_it_be(:package_file) { create(:package_file, :generic, package: package) }
@@ -527,8 +554,6 @@ RSpec.describe API::GenericPackages do
end
context 'application security' do
- using RSpec::Parameterized::TableSyntax
-
where(:param_name, :param_value) do
:package_name | 'my-package/../'
:package_name | 'my-package%2f%2e%2e%2f'
diff --git a/spec/requests/api/graphql/ci/application_setting_spec.rb b/spec/requests/api/graphql/ci/application_setting_spec.rb
new file mode 100644
index 00000000000..156ee550f16
--- /dev/null
+++ b/spec/requests/api/graphql/ci/application_setting_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting Application Settings' do
+ include GraphqlHelpers
+
+ let(:fields) do
+ <<~QUERY
+ #{all_graphql_fields_for('CiApplicationSettings', max_depth: 1)}
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'ciApplicationSettings',
+ fields
+ )
+ end
+
+ let(:settings_data) { graphql_data['ciApplicationSettings'] }
+
+ context 'without admin permissions' do
+ let(:user) { create(:user) }
+
+ before do
+ post_graphql(query, current_user: user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ specify { expect(settings_data).to be nil }
+ end
+
+ context 'with admin permissions' do
+ let(:user) { create(:user, :admin) }
+
+ before do
+ post_graphql(query, current_user: user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'fetches the settings data' do
+ # assert against hash to ensure no additional fields are exposed
+ expect(settings_data).to match({ 'keepLatestArtifact' => Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact })
+ 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 db8a412e45c..99647d0fa3a 100644
--- a/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
+++ b/spec/requests/api/graphql/ci/ci_cd_setting_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe 'Getting Ci Cd Setting' do
it 'fetches the settings data' do
expect(settings_data['mergePipelinesEnabled']).to eql project.ci_cd_settings.merge_pipelines_enabled?
expect(settings_data['mergeTrainsEnabled']).to eql project.ci_cd_settings.merge_trains_enabled?
- expect(settings_data['keepLatestArtifact']).to eql project.ci_keep_latest_artifact?
+ expect(settings_data['keepLatestArtifact']).to eql project.keep_latest_artifacts_available?
end
end
end
diff --git a/spec/requests/api/graphql/issue/issue_spec.rb b/spec/requests/api/graphql/issue/issue_spec.rb
index 42c8e0cc9c0..09e89f65882 100644
--- a/spec/requests/api/graphql/issue/issue_spec.rb
+++ b/spec/requests/api/graphql/issue/issue_spec.rb
@@ -24,6 +24,20 @@ RSpec.describe 'Query.issue(id)' do
end
end
+ it_behaves_like 'a noteable graphql type we can query' do
+ let(:noteable) { issue }
+ let(:project) { issue.project }
+ let(:path_to_noteable) { [:issue] }
+
+ before do
+ project.add_guest(current_user)
+ end
+
+ def query(fields)
+ graphql_query_for('issue', issue_params, fields)
+ end
+ end
+
context 'when the user does not have access to the issue' do
it 'returns nil' do
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
diff --git a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb
index bf7eb3d980c..18cbb7d8b00 100644
--- a/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Updating an existing HTTP Integration' do
include GraphqlHelpers
- let_it_be(:user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:integration) { create(:alert_management_http_integration, project: project) }
@@ -32,18 +32,8 @@ RSpec.describe 'Updating an existing HTTP Integration' do
let(:mutation_response) { graphql_mutation_response(:http_integration_update) }
before do
- project.add_maintainer(user)
+ project.add_maintainer(current_user)
end
- it 'updates the integration' do
- post_graphql_mutation(mutation, current_user: user)
-
- integration_response = mutation_response['integration']
-
- expect(response).to have_gitlab_http_status(:success)
- expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
- expect(integration_response['name']).to eq('Modified Name')
- expect(integration_response['active']).to be_falsey
- expect(integration_response['url']).to include('modified-name')
- end
+ it_behaves_like 'updating an existing HTTP integration'
end
diff --git a/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb
index 328f4fb7b6e..fec9a8c6307 100644
--- a/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb
@@ -3,52 +3,10 @@
require 'spec_helper'
RSpec.describe 'Create a label or backlog board list' do
- include GraphqlHelpers
-
let_it_be(:group) { create(:group, :private) }
let_it_be(:board) { create(:board, group: group) }
- let_it_be(:user) { create(:user) }
- let_it_be(:dev_label) do
- create(:group_label, title: 'Development', color: '#FFAABB', group: group)
- end
-
- let(:current_user) { user }
- let(:mutation) { graphql_mutation(:board_list_create, input) }
- let(:mutation_response) { graphql_mutation_response(:board_list_create) }
-
- context 'the user is not allowed to read board lists' do
- let(:input) { { board_id: board.to_global_id.to_s, backlog: true } }
-
- it_behaves_like 'a mutation that returns a top-level access error'
- end
-
- context 'when user has permissions to admin board lists' do
- before do
- group.add_reporter(current_user)
- end
-
- describe 'backlog list' do
- let(:input) { { board_id: board.to_global_id.to_s, backlog: true } }
-
- it 'creates the list' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['list'])
- .to include('position' => nil, 'listType' => 'backlog')
- end
- end
-
- describe 'label list' do
- let(:input) { { board_id: board.to_global_id.to_s, label_id: dev_label.to_global_id.to_s } }
-
- it 'creates the list' do
- post_graphql_mutation(mutation, current_user: current_user)
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['list'])
- .to include('position' => 0, 'listType' => 'label', 'label' => include('title' => 'Development'))
- end
- end
+ it_behaves_like 'board lists create request' do
+ let(:mutation_name) { :board_list_create }
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 283badeaf33..0dcae28ac5d 100644
--- a/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/ci_cd_settings_update_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'CiCdSettingsUpdate' do
include GraphqlHelpers
- let_it_be(:project) { create(:project, ci_keep_latest_artifact: true) }
+ let_it_be(:project) { create(:project, keep_latest_artifact: true) }
let(:variables) { { full_path: project.full_path, keep_latest_artifact: false } }
let(:mutation) { graphql_mutation(:ci_cd_settings_update, variables) }
@@ -42,7 +42,7 @@ RSpec.describe 'CiCdSettingsUpdate' do
project.reload
expect(response).to have_gitlab_http_status(:success)
- expect(project.ci_keep_latest_artifact).to eq(false)
+ expect(project.keep_latest_artifact).to eq(false)
end
context 'when bad arguments are provided' do
diff --git a/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb
new file mode 100644
index 00000000000..2e4f35cbcde
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/reviewer_rereview_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Setting assignees of a merge request' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [user]) }
+ let(:project) { merge_request.project }
+ let(:user) { create(:user) }
+ let(:input) { { user_id: global_id_of(user) } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_reviewer_rereview, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_reviewer_rereview)
+ end
+
+ def mutation_errors
+ mutation_response['errors']
+ end
+
+ before do
+ project.add_developer(current_user)
+ project.add_developer(user)
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ describe 'reviewer does not exist' do
+ let(:input) { { user_id: global_id_of(create(:user)) } }
+
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_errors).not_to be_empty
+ end
+ end
+
+ describe 'reviewer exists' do
+ it 'does not return an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_errors).to be_empty
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
index 21da1332465..7dd897f6466 100644
--- a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
@@ -43,6 +43,8 @@ RSpec.describe 'Adding a DiffNote' do
it_behaves_like 'a Note mutation when there are active record validation errors', model: DiffNote
+ it_behaves_like 'a Note mutation when there are rate limit validation errors'
+
context do
let(:diff_refs) { build(:commit).diff_refs } # Allow fake diff refs so arguments are valid
diff --git a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
index 8bc68e6017c..0e5744fb64f 100644
--- a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
@@ -46,6 +46,8 @@ RSpec.describe 'Adding an image DiffNote' do
it_behaves_like 'a Note mutation when there are active record validation errors', model: DiffNote
+ it_behaves_like 'a Note mutation when there are rate limit validation errors'
+
context do
let(:diff_refs) { build(:commit).diff_refs } # Allow fake diff refs so arguments are valid
diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
index 6d761eb0a54..1eed1c8e2ae 100644
--- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
@@ -37,6 +37,8 @@ RSpec.describe 'Adding a Note' do
it_behaves_like 'a Note mutation when the given resource id is not for a Noteable'
+ it_behaves_like 'a Note mutation when there are rate limit validation errors'
+
it 'returns the note' do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
index 713b26a6a9b..1ce09881fde 100644
--- a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Updating an image DiffNote' do
include GraphqlHelpers
using RSpec::Parameterized::TableSyntax
- let_it_be(:noteable) { create(:merge_request, :with_diffs) }
+ let_it_be(:noteable) { create(:merge_request) }
let_it_be(:original_body) { 'Original body' }
let_it_be(:original_position) do
Gitlab::Diff::Position.new(
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
index 79bdcec7944..a4918cd560c 100644
--- a/spec/requests/api/graphql/mutations/releases/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -309,10 +309,7 @@ RSpec.describe 'Creation of a new release' do
let(:asset_link_2) { { name: 'My link', url: 'https://example.com/2' } }
let(:assets) { { links: [asset_link_1, asset_link_2] } }
- # Right now the raw Postgres error message is sent to the user as the validation message.
- # We should catch this validation error and return a nicer message:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/277087
- it_behaves_like 'errors-as-data with message', 'PG::UniqueViolation'
+ it_behaves_like 'errors-as-data with message', %r{Validation failed: Links have duplicate values \(My link\)}
end
context 'when two release assets share the same URL' do
@@ -320,8 +317,7 @@ RSpec.describe 'Creation of a new release' do
let(:asset_link_2) { { name: 'My second link', url: 'https://example.com' } }
let(:assets) { { links: [asset_link_1, asset_link_2] } }
- # Same note as above about the ugly error message
- it_behaves_like 'errors-as-data with message', 'PG::UniqueViolation'
+ it_behaves_like 'errors-as-data with message', %r{Validation failed: Links have duplicate values \(https://example.com\)}
end
context 'when the provided tag name is HEAD' do
diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
index fd0dc98a8d3..1c2260070ec 100644
--- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe 'Creating a Snippet' do
let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] }
let(:project_path) { nil }
let(:uploaded_files) { nil }
+ let(:spam_mutation_vars) { {} }
let(:mutation_vars) do
{
description: description,
@@ -25,7 +26,7 @@ RSpec.describe 'Creating a Snippet' do
project_path: project_path,
uploaded_files: uploaded_files,
blob_actions: actions
- }
+ }.merge(spam_mutation_vars)
end
let(:mutation) do
@@ -77,7 +78,20 @@ RSpec.describe 'Creating a Snippet' do
expect(mutation_response['snippet']).to be_nil
end
- it_behaves_like 'spam flag is present'
+ context 'when snippet_spam flag is disabled' do
+ before do
+ stub_feature_flags(snippet_spam: false)
+ end
+
+ it 'passes disable_spam_action_service param to service' do
+ expect(::Snippets::CreateService)
+ .to receive(:new)
+ .with(anything, anything, hash_including(disable_spam_action_service: true))
+ .and_call_original
+
+ subject
+ end
+ end
end
shared_examples 'creates snippet' do
@@ -98,15 +112,24 @@ RSpec.describe 'Creating a Snippet' do
end
context 'when action is invalid' do
- let(:file_1) { { filePath: 'example_file1' }}
+ let(:file_1) { { filePath: 'example_file1' } }
it_behaves_like 'a mutation that returns errors in the response', errors: ['Snippet actions have invalid data']
it_behaves_like 'does not create snippet'
end
it_behaves_like 'snippet edit usage data counters'
- it_behaves_like 'spam flag is present'
- it_behaves_like 'can raise spam flag' do
+
+ it_behaves_like 'a mutation which can mutate a spammable' do
+ let(:captcha_response) { 'abc123' }
+ let(:spam_log_id) { 1234 }
+ let(:spam_mutation_vars) do
+ {
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ }
+ end
+
let(:service) { Snippets::CreateService }
end
end
@@ -148,9 +171,6 @@ RSpec.describe 'Creating a Snippet' do
it_behaves_like 'a mutation that returns errors in the response', errors: ["Title can't be blank"]
it_behaves_like 'does not create snippet'
- it_behaves_like 'can raise spam flag' do
- let(:service) { Snippets::CreateService }
- end
end
context 'when there non ActiveRecord errors' do
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index 21d403c6f73..43dc8d8bc44 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe 'Updating a Snippet' do
let(:updated_file) { 'CHANGELOG' }
let(:deleted_file) { 'README' }
let(:snippet_gid) { GitlabSchema.id_from_object(snippet).to_s }
+ let(:spam_mutation_vars) { {} }
let(:mutation_vars) do
{
id: snippet_gid,
@@ -26,7 +27,7 @@ RSpec.describe 'Updating a Snippet' do
{ action: :update, filePath: updated_file, content: updated_content },
{ action: :delete, filePath: deleted_file }
]
- }
+ }.merge(spam_mutation_vars)
end
let(:mutation) do
@@ -81,11 +82,20 @@ RSpec.describe 'Updating a Snippet' do
end
end
- it_behaves_like 'can raise spam flag' do
- let(:service) { Snippets::UpdateService }
- end
+ context 'when snippet_spam flag is disabled' do
+ before do
+ stub_feature_flags(snippet_spam: false)
+ end
- it_behaves_like 'spam flag is present'
+ it 'passes disable_spam_action_service param to service' do
+ expect(::Snippets::UpdateService)
+ .to receive(:new)
+ .with(anything, anything, hash_including(disable_spam_action_service: true))
+ .and_call_original
+
+ subject
+ end
+ end
context 'when there are ActiveRecord validation errors' do
let(:updated_title) { '' }
@@ -112,11 +122,19 @@ RSpec.describe 'Updating a Snippet' do
expect(mutation_response['snippet']['visibilityLevel']).to eq('private')
end
end
+ end
- it_behaves_like 'spam flag is present'
- it_behaves_like 'can raise spam flag' do
- let(:service) { Snippets::UpdateService }
+ it_behaves_like 'a mutation which can mutate a spammable' do
+ let(:captcha_response) { 'abc123' }
+ let(:spam_log_id) { 1234 }
+ let(:spam_mutation_vars) do
+ {
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ }
end
+
+ let(:service) { Snippets::UpdateService }
end
def blob_at(filename)
diff --git a/spec/requests/api/graphql/packages/package_composer_details_spec.rb b/spec/requests/api/graphql/packages/package_composer_details_spec.rb
deleted file mode 100644
index 1a2cf4a972a..00000000000
--- a/spec/requests/api/graphql/packages/package_composer_details_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe 'package composer details' do
- using RSpec::Parameterized::TableSyntax
- include GraphqlHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:package) { create(:composer_package, project: project) }
- let_it_be(:composer_metadatum) do
- # we are forced to manually create the metadatum, without using the factory to force the sha to be a string
- # and avoid an error where gitaly can't find the repository
- create(:composer_metadatum, package: package, target_sha: 'foo_sha', composer_json: { name: 'name', type: 'type', license: 'license', version: 1 })
- end
-
- let(:query) do
- graphql_query_for(
- 'packageComposerDetails',
- { id: package_global_id },
- all_graphql_fields_for('PackageComposerDetails', max_depth: 2)
- )
- end
-
- let(:user) { project.owner }
- let(:package_global_id) { package.to_global_id.to_s }
- let(:package_composer_details_response) { graphql_data.dig('packageComposerDetails') }
-
- subject { post_graphql(query, current_user: user) }
-
- it_behaves_like 'a working graphql query' do
- before do
- subject
- end
-
- it 'matches the JSON schema' do
- expect(package_composer_details_response).to match_schema('graphql/packages/package_composer_details')
- end
- end
-end
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
new file mode 100644
index 00000000000..bb3ceb81f16
--- /dev/null
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'package details' do
+ using RSpec::Parameterized::TableSyntax
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:package) { create(:composer_package, project: project) }
+ let_it_be(:composer_json) { { name: 'name', type: 'type', license: 'license', version: 1 } }
+ let_it_be(:composer_metadatum) do
+ # we are forced to manually create the metadatum, without using the factory to force the sha to be a string
+ # and avoid an error where gitaly can't find the repository
+ create(:composer_metadatum, package: package, target_sha: 'foo_sha', composer_json: composer_json)
+ end
+
+ let(:depth) { 3 }
+ let(:excluded) { %w[metadata apiFuzzingCiConfiguration] }
+
+ let(:query) do
+ graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
+ #{all_graphql_fields_for('Package', max_depth: depth, excluded: excluded)}
+ metadata {
+ #{query_graphql_fragment('ComposerMetadata')}
+ }
+ FIELDS
+ end
+
+ let(:user) { project.owner }
+ let(:package_global_id) { global_id_of(package) }
+ let(:package_details) { graphql_data_at(:package) }
+
+ subject { post_graphql(query, current_user: user) }
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ subject
+ end
+
+ it 'matches the JSON schema' do
+ expect(package_details).to match_schema('graphql/packages/package_details')
+ end
+
+ it 'includes the fields of the correct package' do
+ expect(package_details).to include(
+ 'id' => package_global_id,
+ 'metadata' => {
+ 'targetSha' => 'foo_sha',
+ 'composerJson' => composer_json.transform_keys(&:to_s).transform_values(&:to_s)
+ }
+ )
+ end
+ end
+
+ context 'there are other versions of this package' do
+ let(:depth) { 3 }
+ let(:excluded) { %w[metadata project tags pipelines] } # to limit the query complexity
+
+ let_it_be(:siblings) { create_list(:composer_package, 2, project: project, name: package.name) }
+
+ it 'includes the sibling versions' do
+ subject
+
+ expect(graphql_data_at(:package, :versions, :nodes)).to match_array(
+ siblings.map { |p| a_hash_including('id' => global_id_of(p)) }
+ )
+ end
+
+ context 'going deeper' do
+ let(:depth) { 6 }
+
+ it 'does not create a cycle of versions' do
+ subject
+
+ expect(graphql_data_at(:package, :versions, :nodes, :version)).to be_present
+ expect(graphql_data_at(:package, :versions, :nodes, :versions)).not_to be_present
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/container_repositories_spec.rb b/spec/requests/api/graphql/project/container_repositories_spec.rb
index 6b1c8689515..2087d8c2cc3 100644
--- a/spec/requests/api/graphql/project/container_repositories_spec.rb
+++ b/spec/requests/api/graphql/project/container_repositories_spec.rb
@@ -156,4 +156,51 @@ RSpec.describe 'getting container repositories in a project' do
expect(container_repositories_count_response).to eq(container_repositories.size)
end
+
+ describe 'sorting and pagination' do
+ let_it_be(:data_path) { [:project, :container_repositories] }
+ let_it_be(:sort_project) { create(:project, :public) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:container_repository1) { create(:container_repository, name: 'b', project: sort_project) }
+ let_it_be(:container_repository2) { create(:container_repository, name: 'a', project: sort_project) }
+ let_it_be(:container_repository3) { create(:container_repository, name: 'd', project: sort_project) }
+ let_it_be(:container_repository4) { create(:container_repository, name: 'c', project: sort_project) }
+ let_it_be(:container_repository5) { create(:container_repository, name: 'e', project: sort_project) }
+
+ before do
+ stub_container_registry_tags(repository: container_repository1.path, tags: %w(tag1 tag1 tag3), with_manifest: false)
+ stub_container_registry_tags(repository: container_repository2.path, tags: %w(tag4 tag5 tag6), with_manifest: false)
+ stub_container_registry_tags(repository: container_repository3.path, tags: %w(tag7 tag8), with_manifest: false)
+ stub_container_registry_tags(repository: container_repository4.path, tags: %w(tag9), with_manifest: false)
+ stub_container_registry_tags(repository: container_repository5.path, tags: %w(tag10 tag11), with_manifest: false)
+ end
+
+ def pagination_query(params)
+ graphql_query_for(:project, { full_path: sort_project.full_path },
+ query_nodes(:container_repositories, :name, include_pagination_info: true, args: params)
+ )
+ end
+
+ def pagination_results_data(data)
+ data.map { |container_repository| container_repository.dig('name') }
+ end
+
+ context 'when sorting by name' do
+ context 'when ascending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { :NAME_ASC }
+ let(:first_param) { 2 }
+ let(:expected_results) { [container_repository2.name, container_repository1.name, container_repository4.name, container_repository3.name, container_repository5.name] }
+ end
+ end
+
+ context 'when descending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { :NAME_DESC }
+ let(:first_param) { 2 }
+ let(:expected_results) { [container_repository5.name, container_repository3.name, container_repository4.name, container_repository1.name, container_repository2.name] }
+ end
+ end
+ end
+ end
end
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 a671ddc7ab1..7148750b6cb 100644
--- a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
+++ b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
@@ -22,6 +22,23 @@ RSpec.describe 'Getting designs related to an issue' do
end
end
+ it_behaves_like 'a noteable graphql type we can query' do
+ let(:noteable) { design }
+ let(:note_factory) { :diff_note_on_design }
+ let(:discussion_factory) { :diff_note_on_design }
+ let(:path_to_noteable) { [:issue, :design_collection, :designs, :nodes, 0] }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ def query(fields)
+ graphql_query_for(:issue, { id: global_id_of(issue) }, <<~FIELDS)
+ designCollection { designs { nodes { #{fields} } } }
+ FIELDS
+ end
+ end
+
it 'is not too deep for anonymous users' do
note_fields = <<~FIELDS
id
@@ -37,7 +54,7 @@ RSpec.describe 'Getting designs related to an issue' do
expect(note_data['id']).to eq(note.to_global_id.to_s)
end
- def query(note_fields = all_graphql_fields_for(Note))
+ def query(note_fields = all_graphql_fields_for(Note, max_depth: 1))
design_node = <<~NODE
designs {
nodes {
diff --git a/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb b/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb
index ac0b18a37d6..70c5bda35e1 100644
--- a/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb
@@ -8,9 +8,11 @@ RSpec.describe 'Query.project.mergeRequests.pipelines' do
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:author) { create(:user) }
let_it_be(:merge_requests) do
- %i[with_diffs with_image_diffs conflict].map do |trait|
- create(:merge_request, trait, author: author, source_project: project)
- end
+ [
+ create(:merge_request, author: author, source_project: project),
+ create(:merge_request, :with_image_diffs, author: author, source_project: project),
+ create(:merge_request, :conflict, author: author, source_project: project)
+ ]
end
describe '.count' do
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index e1b867ad097..a4e8d0bc35e 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -66,14 +66,6 @@ RSpec.describe 'getting merge request information nested in a project' do
expect(graphql_data_at(:project, :merge_request, :reviewers, :nodes)).to match_array(expected)
expect(graphql_data_at(:project, :merge_request, :participants, :nodes)).to include(*expected)
end
-
- it 'suppresses reviewers if reviewers are not allowed' do
- stub_feature_flags(merge_request_reviewers: false)
-
- post_graphql(query, current_user: current_user)
-
- expect(graphql_data_at(:project, :merge_request, :reviewers)).to be_nil
- end
end
it 'includes diff stats' do
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index c85cb8b2ffe..d684be91dc9 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -196,17 +196,18 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
context 'when requesting `commit_count`' do
- let(:requested_fields) { [:commit_count] }
+ let(:merge_request_with_commits) { create(:merge_request, source_project: project) }
+ let(:search_params) { { iids: [merge_request_a.iid.to_s, merge_request_with_commits.iid.to_s] } }
+ let(:requested_fields) { [:iid, :commit_count] }
it 'exposes `commit_count`' do
- merge_request_a.metrics.update!(commits_count: 5)
-
execute_query
- expect(results).to include(a_hash_including('commitCount' => 5))
+ expect(results).to match_array([
+ { "iid" => merge_request_a.iid.to_s, "commitCount" => 0 },
+ { "iid" => merge_request_with_commits.iid.to_s, "commitCount" => 29 }
+ ])
end
-
- include_examples 'N+1 query check'
end
context 'when requesting `merged_at`' do
@@ -264,18 +265,6 @@ RSpec.describe 'getting merge request listings nested in a project' do
})
end
- context 'the feature flag is disabled' do
- before do
- stub_feature_flags(merge_request_reviewers: false)
- end
-
- it 'does not return reviewers' do
- execute_query
-
- expect(results).to all(match a_hash_including('reviewers' => be_nil))
- end
- end
-
include_examples 'N+1 query check'
end
end
@@ -396,4 +385,87 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
end
end
+
+ context 'when only the count is requested' do
+ context 'when merged at filter is present' do
+ let_it_be(:merge_request) do
+ create(:merge_request, :unique_branches, source_project: project).tap do |mr|
+ mr.metrics.update!(merged_at: Time.new(2020, 1, 3))
+ end
+ end
+
+ let(:query) do
+ # Note: __typename meta field is always requested by the FE
+ graphql_query_for(:project, { full_path: project.full_path },
+ <<~QUERY
+ mergeRequests(mergedAfter: "2020-01-01", mergedBefore: "2020-01-05", first: 0, sourceBranches: null, labels: null) {
+ count
+ __typename
+ }
+ QUERY
+ )
+ end
+
+ shared_examples 'count examples' do
+ it 'returns the correct count' do
+ post_graphql(query, current_user: current_user)
+
+ count = graphql_data.dig('project', 'mergeRequests', 'count')
+ expect(count).to eq(1)
+ end
+ end
+
+ context 'when "optimized_merge_request_count_with_merged_at_filter" feature flag is enabled' do
+ before do
+ stub_feature_flags(optimized_merge_request_count_with_merged_at_filter: true)
+ end
+
+ it 'does not query the merge requests table for the count' do
+ query_recorder = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
+
+ queries = query_recorder.data.each_value.first[:occurrences]
+ expect(queries).not_to include(match(/SELECT COUNT\(\*\) FROM "merge_requests"/))
+ expect(queries).to include(match(/SELECT COUNT\(\*\) FROM "merge_request_metrics"/))
+ end
+
+ context 'when total_time_to_merge and count is queried' do
+ let(:query) do
+ graphql_query_for(:project, { full_path: project.full_path },
+ <<~QUERY
+ mergeRequests(mergedAfter: "2020-01-01", mergedBefore: "2020-01-05", first: 0) {
+ totalTimeToMerge
+ count
+ }
+ QUERY
+ )
+ end
+
+ it 'does not query the merge requests table for the total_time_to_merge' do
+ query_recorder = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
+
+ queries = query_recorder.data.each_value.first[:occurrences]
+ expect(queries).to include(match(/SELECT.+SUM.+FROM "merge_request_metrics" WHERE/))
+ end
+ end
+
+ it_behaves_like 'count examples'
+
+ context 'when "optimized_merge_request_count_with_merged_at_filter" feature flag is disabled' do
+ before do
+ stub_feature_flags(optimized_merge_request_count_with_merged_at_filter: false)
+ end
+
+ it 'queries the merge requests table for the count' do
+ query_recorder = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
+
+ queries = query_recorder.data.each_value.first[:occurrences]
+ expect(queries).to include(match(/SELECT COUNT\(\*\) FROM "merge_requests"/))
+ expect(queries).not_to include(match(/SELECT COUNT\(\*\) FROM "merge_request_metrics"/))
+ end
+
+ it_behaves_like 'count examples'
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/packages_spec.rb b/spec/requests/api/graphql/project/packages_spec.rb
index 5df98ed1e6b..b20c96d54c8 100644
--- a/spec/requests/api/graphql/project/packages_spec.rb
+++ b/spec/requests/api/graphql/project/packages_spec.rb
@@ -5,16 +5,27 @@ require 'spec_helper'
RSpec.describe 'getting a package list for a project' do
include GraphqlHelpers
- let_it_be(:project) { create(:project) }
+ let_it_be(:project) { create(:project, :repository) }
let_it_be(:current_user) { create(:user) }
+
let_it_be(:package) { create(:package, project: project) }
- let(:packages_data) { graphql_data['project']['packages']['edges'] }
+ let_it_be(:maven_package) { create(:maven_package, project: project) }
+ let_it_be(:debian_package) { create(:debian_package, project: project) }
+ let_it_be(:composer_package) { create(:composer_package, project: project) }
+ let_it_be(:composer_metadatum) do
+ create(:composer_metadatum, package: composer_package,
+ target_sha: 'afdeh',
+ composer_json: { name: 'x', type: 'y', license: 'z', version: 1 })
+ end
+
+ let(:package_names) { graphql_data_at(:project, :packages, :edges, :node, :name) }
let(:fields) do
<<~QUERY
edges {
node {
- #{all_graphql_fields_for('packages'.classify)}
+ #{all_graphql_fields_for('packages'.classify, excluded: ['project'])}
+ metadata { #{query_graphql_fragment('ComposerMetadata')} }
}
}
QUERY
@@ -37,7 +48,17 @@ RSpec.describe 'getting a package list for a project' do
it_behaves_like 'a working graphql query'
it 'returns packages successfully' do
- expect(packages_data[0]['node']['name']).to eq package.name
+ expect(package_names).to contain_exactly(
+ package.name,
+ maven_package.name,
+ debian_package.name,
+ composer_package.name
+ )
+ end
+
+ it 'deals with metadata' do
+ target_shas = graphql_data_at(:project, :packages, :edges, :node, :metadata, :target_sha)
+ expect(target_shas).to contain_exactly(composer_metadatum.target_sha)
end
end
@@ -53,7 +74,7 @@ RSpec.describe 'getting a package list for a project' do
end
end
- context 'when the user is not autenthicated' do
+ context 'when the user is not authenticated' do
before do
post_graphql(query)
end
diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb
index ccc2825da25..72197f00df4 100644
--- a/spec/requests/api/graphql/project/release_spec.rb
+++ b/spec/requests/api/graphql/project/release_spec.rb
@@ -283,7 +283,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
- let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
+ let_it_be(:release, reload: true) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
let_it_be(:release_link_1) { create(:release_link, release: release) }
let_it_be(:release_link_2) { create(:release_link, release: release, filepath: link_filepath) }
@@ -324,7 +324,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
- let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
+ let_it_be(:release, reload: true) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
let_it_be(:release_link_1) { create(:release_link, release: release) }
let_it_be(:release_link_2) { create(:release_link, release: release, filepath: link_filepath) }
@@ -435,13 +435,13 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be_with_reload(:release) { create(:release, project: project) }
let(:release_fields) do
- query_graphql_field(%{
+ %{
milestones {
nodes {
title
}
}
- })
+ }
end
let(:actual_milestone_title_order) do
diff --git a/spec/requests/api/graphql/project/terraform/state_spec.rb b/spec/requests/api/graphql/project/terraform/state_spec.rb
new file mode 100644
index 00000000000..9f1d9ab204a
--- /dev/null
+++ b/spec/requests/api/graphql/project/terraform/state_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'query a single terraform state' do
+ include GraphqlHelpers
+ include ::API::Helpers::RelatedResourcesHelpers
+
+ let_it_be(:terraform_state) { create(:terraform_state, :with_version, :locked) }
+
+ let(:latest_version) { terraform_state.latest_version }
+ let(:project) { terraform_state.project }
+ let(:current_user) { project.creator }
+ let(:data) { graphql_data.dig('project', 'terraformState') }
+
+ let(:query) do
+ graphql_query_for(
+ :project,
+ { fullPath: project.full_path },
+ query_graphql_field(
+ :terraformState,
+ { name: terraform_state.name },
+ %{
+ id
+ name
+ lockedAt
+ createdAt
+ updatedAt
+
+ latestVersion {
+ id
+ serial
+ createdAt
+ updatedAt
+
+ createdByUser {
+ id
+ }
+
+ job {
+ name
+ }
+ }
+
+ lockedByUser {
+ id
+ }
+ }
+ )
+ )
+ end
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns terraform state data' do
+ expect(data).to match(a_hash_including({
+ 'id' => global_id_of(terraform_state),
+ 'name' => terraform_state.name,
+ 'lockedAt' => terraform_state.locked_at.iso8601,
+ 'createdAt' => terraform_state.created_at.iso8601,
+ 'updatedAt' => terraform_state.updated_at.iso8601,
+ 'lockedByUser' => { 'id' => global_id_of(terraform_state.locked_by_user) },
+ 'latestVersion' => {
+ 'id' => eq(global_id_of(latest_version)),
+ 'serial' => eq(latest_version.version),
+ 'createdAt' => eq(latest_version.created_at.iso8601),
+ 'updatedAt' => eq(latest_version.updated_at.iso8601),
+ 'createdByUser' => { 'id' => eq(global_id_of(latest_version.created_by_user)) },
+ 'job' => { 'name' => eq(latest_version.build.name) }
+ }
+ }))
+ end
+
+ context 'unauthorized users' do
+ let(:current_user) { nil }
+
+ it { expect(data).to be_nil }
+ end
+end
diff --git a/spec/requests/api/group_import_spec.rb b/spec/requests/api/group_import_spec.rb
index d8e945baf6a..bb7436502ed 100644
--- a/spec/requests/api/group_import_spec.rb
+++ b/spec/requests/api/group_import_spec.rb
@@ -5,13 +5,13 @@ require 'spec_helper'
RSpec.describe API::GroupImport do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:path) { '/groups/import' }
let(:file) { File.join('spec', 'fixtures', 'group_export.tar.gz') }
let(:export_path) { "#{Dir.tmpdir}/group_export_spec" }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
before do
allow_next_instance_of(Gitlab::ImportExport) do |import_export|
diff --git a/spec/requests/api/group_labels_spec.rb b/spec/requests/api/group_labels_spec.rb
index 72621e2ce5e..c677e68b285 100644
--- a/spec/requests/api/group_labels_spec.rb
+++ b/spec/requests/api/group_labels_spec.rb
@@ -3,13 +3,19 @@
require 'spec_helper'
RSpec.describe API::GroupLabels do
+ let_it_be(:valid_group_label_title_1) { 'Label foo & bar:subgroup::v.1' }
+ let_it_be(:valid_group_label_title_1_esc) { ERB::Util.url_encode(valid_group_label_title_1) }
+ let_it_be(:valid_group_label_title_2) { 'Bar & foo:subgroup::v.2' }
+ let_it_be(:valid_subgroup_label_title_1) { 'Support label foobar:sub::v.1' }
+ let_it_be(:valid_new_label_title) { 'New & foo:feature::v.3' }
+
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
let!(:group_member) { create(:group_member, group: group, user: user) }
- let!(:group_label1) { create(:group_label, title: 'feature-label', group: group) }
- let!(:group_label2) { create(:group_label, title: 'bug', group: group) }
- let!(:subgroup_label) { create(:group_label, title: 'support-label', group: subgroup) }
+ let!(:group_label1) { create(:group_label, title: valid_group_label_title_1, group: group) }
+ let!(:group_label2) { create(:group_label, title: valid_group_label_title_2, group: group) }
+ let!(:subgroup_label) { create(:group_label, title: valid_subgroup_label_title_1, group: subgroup) }
describe 'GET :id/labels' do
context 'get current group labels' do
@@ -104,7 +110,7 @@ RSpec.describe API::GroupLabels do
describe 'GET :id/labels/:label_id' do
it 'returns a single label for the group' do
- get api("/groups/#{group.id}/labels/#{group_label1.name}", user)
+ get api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}", user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq(group_label1.name)
@@ -117,13 +123,13 @@ RSpec.describe API::GroupLabels do
it 'returns created label when all params are given' do
post api("/groups/#{group.id}/labels", user),
params: {
- name: 'Foo',
+ name: valid_new_label_title,
color: '#FFAABB',
description: 'test'
}
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq('Foo')
+ expect(json_response['name']).to eq(valid_new_label_title)
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to eq('test')
end
@@ -131,12 +137,12 @@ RSpec.describe API::GroupLabels do
it 'returns created label when only required params are given' do
post api("/groups/#{group.id}/labels", user),
params: {
- name: 'Foo & Bar',
+ name: valid_new_label_title,
color: '#FFAABB'
}
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq('Foo & Bar')
+ expect(json_response['name']).to eq(valid_new_label_title)
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to be_nil
end
@@ -204,7 +210,7 @@ RSpec.describe API::GroupLabels do
describe 'DELETE /groups/:id/labels/:label_id' do
it 'returns 204 for existing label' do
- delete api("/groups/#{group.id}/labels/#{group_label1.name}", user)
+ delete api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}", user)
expect(response).to have_gitlab_http_status(:no_content)
end
@@ -228,7 +234,7 @@ RSpec.describe API::GroupLabels do
end
it_behaves_like '412 response' do
- let(:request) { api("/groups/#{group.id}/labels/#{group_label1.name}", user) }
+ let(:request) { api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}", user) }
end
end
@@ -237,13 +243,13 @@ RSpec.describe API::GroupLabels do
put api("/groups/#{group.id}/labels", user),
params: {
name: group_label1.name,
- new_name: 'New Label',
+ new_name: valid_new_label_title,
color: '#FFFFFF',
description: 'test'
}
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('New Label')
+ expect(json_response['name']).to eq(valid_new_label_title)
expect(json_response['color']).to eq('#FFFFFF')
expect(json_response['description']).to eq('test')
end
@@ -255,11 +261,11 @@ RSpec.describe API::GroupLabels do
put api("/groups/#{subgroup.id}/labels", user),
params: {
name: subgroup_label.name,
- new_name: 'New Label'
+ new_name: valid_new_label_title
}
expect(response).to have_gitlab_http_status(:ok)
- expect(subgroup.labels[0].name).to eq('New Label')
+ expect(subgroup.labels[0].name).to eq(valid_new_label_title)
expect(group_label1.name).to eq(group_label1.title)
end
@@ -267,7 +273,7 @@ RSpec.describe API::GroupLabels do
put api("/groups/#{group.id}/labels", user),
params: {
name: 'not_exists',
- new_name: 'label3'
+ new_name: valid_new_label_title
}
expect(response).to have_gitlab_http_status(:not_found)
@@ -291,15 +297,15 @@ RSpec.describe API::GroupLabels do
describe 'PUT /groups/:id/labels/:label_id' do
it 'returns 200 if name and colors and description are changed' do
- put api("/groups/#{group.id}/labels/#{group_label1.name}", user),
+ put api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}", user),
params: {
- new_name: 'New Label',
+ new_name: valid_new_label_title,
color: '#FFFFFF',
description: 'test'
}
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('New Label')
+ expect(json_response['name']).to eq(valid_new_label_title)
expect(json_response['color']).to eq('#FFFFFF')
expect(json_response['description']).to eq('test')
end
@@ -310,25 +316,25 @@ RSpec.describe API::GroupLabels do
put api("/groups/#{subgroup.id}/labels/#{subgroup_label.name}", user),
params: {
- new_name: 'New Label'
+ new_name: valid_new_label_title
}
expect(response).to have_gitlab_http_status(:ok)
- expect(subgroup.labels[0].name).to eq('New Label')
+ expect(subgroup.labels[0].name).to eq(valid_new_label_title)
expect(group_label1.name).to eq(group_label1.title)
end
it 'returns 404 if label does not exist' do
put api("/groups/#{group.id}/labels/not_exists", user),
params: {
- new_name: 'label3'
+ new_name: valid_new_label_title
}
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns 400 if no new parameters given' do
- put api("/groups/#{group.id}/labels/#{group_label1.name}", user)
+ put api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}", user)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('new_name, color, description are missing, '\
@@ -339,7 +345,7 @@ RSpec.describe API::GroupLabels do
describe 'POST /groups/:id/labels/:label_id/subscribe' do
context 'when label_id is a label title' do
it 'subscribes to the label' do
- post api("/groups/#{group.id}/labels/#{group_label1.title}/subscribe", user)
+ post api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}/subscribe", user)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['name']).to eq(group_label1.title)
@@ -385,7 +391,7 @@ RSpec.describe API::GroupLabels do
context 'when label_id is a label title' do
it 'unsubscribes from the label' do
- post api("/groups/#{group.id}/labels/#{group_label1.title}/unsubscribe", user)
+ post api("/groups/#{group.id}/labels/#{valid_group_label_title_1_esc}/unsubscribe", user)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['name']).to eq(group_label1.title)
diff --git a/spec/requests/api/group_packages_spec.rb b/spec/requests/api/group_packages_spec.rb
index 26895e473de..792aa2c1f20 100644
--- a/spec/requests/api/group_packages_spec.rb
+++ b/spec/requests/api/group_packages_spec.rb
@@ -144,6 +144,7 @@ RSpec.describe API::GroupPackages do
end
it_behaves_like 'with versionless packages'
+ it_behaves_like 'with status param'
it_behaves_like 'does not cause n^2 queries'
end
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index c7756a4fae5..1c359b6e50f 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe API::Groups do
it_behaves_like 'invalid file upload request'
end
- context 'when file format is not supported' do
+ context 'when file is too large' do
let(:file_path) { 'spec/fixtures/big-image.png' }
let(:message) { 'is too big' }
@@ -661,6 +661,7 @@ RSpec.describe API::Groups do
describe 'PUT /groups/:id' do
let(:new_group_name) { 'New Group'}
+ let(:file_path) { 'spec/fixtures/dk.png' }
it_behaves_like 'group avatar upload' do
def make_upload_request
@@ -678,7 +679,8 @@ RSpec.describe API::Groups do
request_access_enabled: true,
project_creation_level: "noone",
subgroup_creation_level: "maintainer",
- default_branch_protection: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS
+ default_branch_protection: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS,
+ avatar: fixture_file_upload(file_path)
}
expect(response).to have_gitlab_http_status(:ok)
@@ -701,6 +703,7 @@ RSpec.describe API::Groups do
expect(json_response['shared_projects']).to be_an Array
expect(json_response['shared_projects'].length).to eq(0)
expect(json_response['default_branch_protection']).to eq(::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
+ expect(json_response['avatar_url']).to end_with('dk.png')
end
context 'updating the `default_branch_protection` attribute' do
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index e04f63befd0..86999c4adaa 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -50,41 +50,6 @@ RSpec.describe API::Internal::Base do
end
end
- shared_examples 'actor key validations' do
- context 'key id is not provided' do
- let(:key_id) { nil }
-
- it 'returns an error message' do
- subject
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find a user without a key')
- end
- end
-
- context 'key does not exist' do
- let(:key_id) { non_existing_record_id }
-
- it 'returns an error message' do
- subject
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find the given key')
- end
- end
-
- context 'key without user' do
- let(:key_id) { create(:key, user: nil).id }
-
- it 'returns an error message' do
- subject
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Could not find a user for the given key')
- end
- end
- end
-
describe 'GET /internal/two_factor_recovery_codes' do
let(:key_id) { key.id }
@@ -578,25 +543,51 @@ RSpec.describe API::Internal::Base do
end
context "git pull" do
- before do
- stub_feature_flags(gitaly_mep_mep: true)
+ context "with a feature flag enabled globally" do
+ before do
+ stub_feature_flags(gitaly_mep_mep: true)
+ end
+
+ it "has the correct payload" do
+ pull(key, project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response["status"]).to be_truthy
+ expect(json_response["gl_repository"]).to eq("project-#{project.id}")
+ expect(json_response["gl_project_path"]).to eq(project.full_path)
+ expect(json_response["gitaly"]).not_to be_nil
+ expect(json_response["gitaly"]["repository"]).not_to be_nil
+ expect(json_response["gitaly"]["repository"]["storage_name"]).to eq(project.repository.gitaly_repository.storage_name)
+ expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
+ expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
+ expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
+ expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-mep-mep' => 'true')
+ expect(user.reload.last_activity_on).to eql(Date.today)
+ end
end
- it "has the correct payload" do
- pull(key, project)
+ context "with a feature flag enabled for a project" do
+ before do
+ stub_feature_flags(gitaly_mep_mep: project)
+ end
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response["status"]).to be_truthy
- expect(json_response["gl_repository"]).to eq("project-#{project.id}")
- expect(json_response["gl_project_path"]).to eq(project.full_path)
- expect(json_response["gitaly"]).not_to be_nil
- expect(json_response["gitaly"]["repository"]).not_to be_nil
- expect(json_response["gitaly"]["repository"]["storage_name"]).to eq(project.repository.gitaly_repository.storage_name)
- expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
- expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
- expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
- expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-mep-mep' => 'true')
- expect(user.reload.last_activity_on).to eql(Date.today)
+ it "has the flag 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"]["features"]).to eq('gitaly-feature-mep-mep' => 'true')
+ end
+
+ it "has the flag 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"]["features"]).to eq('gitaly-feature-mep-mep' => 'false')
+ end
end
end
@@ -1094,6 +1085,104 @@ RSpec.describe API::Internal::Base do
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
+
+ context 'admin mode' do
+ shared_examples 'pushes succeed for ssh and http' do
+ it 'accepts the SSH push' do
+ push(key, project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'accepts the HTTP push' do
+ push(key, project, 'http')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ shared_examples 'pushes fail for ssh and http' do
+ it 'rejects the SSH push' do
+ push(key, project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'rejects the HTTP push' do
+ push(key, project, 'http')
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'feature flag :user_mode_in_session is enabled' do
+ context 'with an admin user' do
+ let(:user) { create(:admin) }
+
+ context 'is member of the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'pushes succeed for ssh and http'
+ end
+
+ context 'is not member of the project' do
+ it_behaves_like 'pushes succeed for ssh and http'
+ end
+ end
+
+ context 'with a regular user' do
+ context 'is member of the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'pushes succeed for ssh and http'
+ end
+
+ context 'is not member of the project' do
+ it_behaves_like 'pushes fail for ssh and http'
+ end
+ end
+ end
+
+ context 'feature flag :user_mode_in_session is disabled' do
+ before do
+ stub_feature_flags(user_mode_in_session: false)
+ end
+
+ context 'with an admin user' do
+ let(:user) { create(:admin) }
+
+ context 'is member of the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'pushes succeed for ssh and http'
+ end
+
+ context 'is not member of the project' do
+ it_behaves_like 'pushes succeed for ssh and http'
+ end
+ end
+
+ context 'with a regular user' do
+ context 'is member of the project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'pushes succeed for ssh and http'
+ end
+
+ context 'is not member of the project' do
+ it_behaves_like 'pushes fail for ssh and http'
+ end
+ end
+ end
+ end
end
describe 'POST /internal/post_receive', :clean_gitlab_redis_shared_state do
@@ -1308,10 +1397,6 @@ RSpec.describe API::Internal::Base do
let(:key_id) { key.id }
let(:otp) { '123456'}
- before do
- stub_feature_flags(two_factor_for_cli: true)
- end
-
subject do
post api('/internal/two_factor_otp_check'),
params: {
@@ -1321,76 +1406,10 @@ RSpec.describe API::Internal::Base do
}
end
- it_behaves_like 'actor key validations'
-
- context 'when the key is a deploy key' do
- let(:key_id) { create(:deploy_key).id }
-
- it 'returns an error message' do
- subject
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq('Deploy keys cannot be used for Two Factor')
- end
- end
-
- context 'when the two factor is enabled' do
- before do
- allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
- end
-
- context 'when the OTP is valid' do
- it 'registers a new OTP session and returns success' do
- allow_any_instance_of(Users::ValidateOtpService).to receive(:execute).with(otp).and_return(status: :success)
-
- expect_next_instance_of(::Gitlab::Auth::Otp::SessionEnforcer) do |session_enforcer|
- expect(session_enforcer).to receive(:update_session).once
- end
-
- subject
-
- expect(json_response['success']).to be_truthy
- end
- end
-
- context 'when the OTP is invalid' do
- it 'is not success' do
- allow_any_instance_of(Users::ValidateOtpService).to receive(:execute).with(otp).and_return(status: :error)
-
- subject
-
- expect(json_response['success']).to be_falsey
- end
- end
- end
-
- context 'when the two factor is disabled' do
- before do
- allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(false)
- end
+ it 'is not available' do
+ subject
- it 'returns an error message' do
- subject
-
- expect(json_response['success']).to be_falsey
- expect(json_response['message']).to eq 'Two-factor authentication is not enabled for this user'
- end
- end
-
- context 'two_factor_for_cli feature is disabled' do
- before do
- stub_feature_flags(two_factor_for_cli: false)
- end
-
- context 'when two-factor is enabled for the user' do
- it 'returns user two factor config' do
- allow_any_instance_of(User).to receive(:two_factor_enabled?).and_return(true)
-
- subject
-
- expect(json_response['success']).to be_falsey
- end
- end
+ expect(json_response['success']).to be_falsey
end
end
diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb
index afff3647b91..2e13016a0a6 100644
--- a/spec/requests/api/internal/kubernetes_spec.rb
+++ b/spec/requests/api/internal/kubernetes_spec.rb
@@ -62,25 +62,25 @@ RSpec.describe API::Internal::Kubernetes do
let!(:agent_token) { create(:cluster_agent_token) }
it 'returns no_content for valid gitops_sync_count' do
- send_request(params: { gitops_sync_count: 10 }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+ send_request(params: { gitops_sync_count: 10 })
expect(response).to have_gitlab_http_status(:no_content)
end
it 'returns no_content 0 gitops_sync_count' do
- send_request(params: { gitops_sync_count: 0 }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+ send_request(params: { gitops_sync_count: 0 })
expect(response).to have_gitlab_http_status(:no_content)
end
it 'returns 400 for non number' do
- send_request(params: { gitops_sync_count: 'string' }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+ send_request(params: { gitops_sync_count: 'string' })
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 400 for negative number' do
- send_request(params: { gitops_sync_count: '-1' }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+ send_request(params: { gitops_sync_count: '-1' })
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -125,6 +125,36 @@ RSpec.describe API::Internal::Kubernetes do
)
)
end
+
+ context 'on GitLab.com' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(true)
+ end
+
+ context 'kubernetes_agent_on_gitlab_com feature flag disabled' do
+ before do
+ stub_feature_flags(kubernetes_agent_on_gitlab_com: false)
+ end
+
+ it 'returns 403' do
+ send_request(headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'kubernetes_agent_on_gitlab_com feature flag enabled' do
+ before do
+ stub_feature_flags(kubernetes_agent_on_gitlab_com: agent_token.agent.project)
+ end
+
+ it 'returns success' do
+ send_request(headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+ end
end
end
@@ -174,6 +204,36 @@ RSpec.describe API::Internal::Kubernetes do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'on GitLab.com' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(true)
+ end
+
+ context 'kubernetes_agent_on_gitlab_com feature flag disabled' do
+ before do
+ stub_feature_flags(kubernetes_agent_on_gitlab_com: false)
+ end
+
+ it 'returns 403' do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'kubernetes_agent_on_gitlab_com feature flag enabled' do
+ before do
+ stub_feature_flags(kubernetes_agent_on_gitlab_com: agent_token.agent.project)
+ end
+
+ it 'returns success' do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+ end
end
context 'project is private' do
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 6f854a28cec..1c43ef25f14 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe API::Jobs do
end
let!(:job) do
- create(:ci_build, :success, pipeline: pipeline,
+ create(:ci_build, :success, :tags, pipeline: pipeline,
artifacts_expire_at: 1.day.since)
end
@@ -50,6 +50,7 @@ RSpec.describe API::Jobs do
expect(json_response).not_to be_empty
expect(json_response.first['commit']['id']).to eq project.commit.id
expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at)
+ expect(json_response.first['tag_list'].sort).to eq job.tag_list.sort
end
context 'without artifacts and trace' do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 6db6de4b533..e3fffd3e3fd 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -10,14 +10,19 @@ RSpec.describe API::Labels do
else
label_id = spec_params[:name] || spec_params[:label_id]
- put api("/projects/#{project.id}/labels/#{label_id}", user),
+ put api("/projects/#{project.id}/labels/#{ERB::Util.url_encode(label_id)}", user),
params: request_params.merge(spec_params.except(:name, :id))
end
end
+ let_it_be(:valid_label_title_1) { 'Label foo & bar:subgroup::v.1' }
+ let_it_be(:valid_label_title_1_esc) { ERB::Util.url_encode(valid_label_title_1) }
+ let_it_be(:valid_label_title_2) { 'Label bar & foo:subgroup::v.2' }
+ let_it_be(:valid_group_label_title_1) { 'Group label foobar:sub::v.1' }
+
let(:user) { create(:user) }
let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
- let!(:label1) { create(:label, description: 'the best label', title: 'label1', project: project) }
+ let!(:label1) { create(:label, description: 'the best label v.1', title: valid_label_title_1, project: project) }
let!(:priority_label) { create(:label, title: 'bug', project: project, priority: 3) }
route_types = [:deprecated, :rest]
@@ -25,10 +30,10 @@ RSpec.describe API::Labels do
shared_examples 'label update API' do
route_types.each do |route_type|
it "returns 200 if name is changed (#{route_type} route)" do
- put_labels_api(route_type, user, spec_params, new_name: 'New Label')
+ put_labels_api(route_type, user, spec_params, new_name: valid_label_title_2)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('New Label')
+ expect(json_response['name']).to eq(valid_label_title_2)
expect(json_response['color']).to eq(label1.color)
end
@@ -77,10 +82,10 @@ RSpec.describe API::Labels do
end
it "returns 200 if name and colors and description are changed (#{route_type} route)" do
- put_labels_api(route_type, user, spec_params, new_name: 'New Label', color: '#FFFFFF', description: 'test')
+ put_labels_api(route_type, user, spec_params, new_name: valid_label_title_2, color: '#FFFFFF', description: 'test')
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['name']).to eq('New Label')
+ expect(json_response['name']).to eq(valid_label_title_2)
expect(json_response['color']).to eq('#FFFFFF')
expect(json_response['description']).to eq('test')
end
@@ -141,7 +146,7 @@ RSpec.describe API::Labels do
priority: nil
}.merge(spec_params.except(:name, :id))
- put api("/projects/#{project.id}/labels/#{label_id}", user),
+ put api("/projects/#{project.id}/labels/#{ERB::Util.url_encode(label_id)}", user),
params: request_params
expect(response).to have_gitlab_http_status(:ok)
@@ -167,7 +172,7 @@ RSpec.describe API::Labels do
it 'returns 204 for existing label (rest route)' do
label_id = spec_params[:name] || spec_params[:label_id]
- delete api("/projects/#{project.id}/labels/#{label_id}", user), params: spec_params.except(:name, :label_id)
+ delete api("/projects/#{project.id}/labels/#{ERB::Util.url_encode(label_id)}", user), params: spec_params.except(:name, :label_id)
expect(response).to have_gitlab_http_status(:no_content)
end
@@ -179,7 +184,7 @@ RSpec.describe API::Labels do
describe 'GET /projects/:id/labels' do
let_it_be(:group) { create(:group) }
- let_it_be(:group_label) { create(:group_label, title: 'feature label', group: group) }
+ let_it_be(:group_label) { create(:group_label, title: valid_group_label_title_1, group: group) }
before do
project.update!(group: group)
@@ -219,7 +224,7 @@ RSpec.describe API::Labels do
'closed_issues_count' => 1,
'open_merge_requests_count' => 0,
'name' => label1.name,
- 'description' => 'the best label',
+ 'description' => label1.description,
'color' => a_string_matching(/^#\h{6}$/),
'text_color' => a_string_matching(/^#\h{6}$/),
'priority' => nil,
@@ -293,14 +298,14 @@ RSpec.describe API::Labels do
it 'returns created label when all params' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'Foo',
+ name: valid_label_title_2,
color: '#FFAABB',
description: 'test',
priority: 2
}
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq('Foo')
+ expect(json_response['name']).to eq(valid_label_title_2)
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to eq('test')
expect(json_response['priority']).to eq(2)
@@ -309,12 +314,12 @@ RSpec.describe API::Labels do
it 'returns created label when only required params' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'Foo & Bar',
+ name: valid_label_title_2,
color: '#FFAABB'
}
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq('Foo & Bar')
+ expect(json_response['name']).to eq(valid_label_title_2)
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to be_nil
expect(json_response['priority']).to be_nil
@@ -323,13 +328,13 @@ RSpec.describe API::Labels do
it 'creates a prioritized label' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'Foo & Bar',
+ name: valid_label_title_2,
color: '#FFAABB',
priority: 3
}
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq('Foo & Bar')
+ expect(json_response['name']).to eq(valid_label_title_2)
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to be_nil
expect(json_response['priority']).to eq(3)
@@ -348,7 +353,7 @@ RSpec.describe API::Labels do
it 'returns 400 for invalid color' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'Foo',
+ name: valid_label_title_2,
color: '#FFAA'
}
expect(response).to have_gitlab_http_status(:bad_request)
@@ -358,7 +363,7 @@ RSpec.describe API::Labels do
it 'returns 400 for too long color code' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'Foo',
+ name: valid_label_title_2,
color: '#FFAAFFFF'
}
expect(response).to have_gitlab_http_status(:bad_request)
@@ -393,7 +398,7 @@ RSpec.describe API::Labels do
it 'returns 400 for invalid priority' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'Foo',
+ name: valid_label_title_2,
color: '#FFAAFFFF',
priority: 'foo'
}
@@ -404,7 +409,7 @@ RSpec.describe API::Labels do
it 'returns 409 if label already exists in project' do
post api("/projects/#{project.id}/labels", user),
params: {
- name: 'label1',
+ name: valid_label_title_1,
color: '#FFAABB'
}
expect(response).to have_gitlab_http_status(:conflict)
@@ -414,7 +419,7 @@ RSpec.describe API::Labels do
describe 'DELETE /projects/:id/labels' do
it_behaves_like 'label delete API' do
- let(:spec_params) { { name: 'label1' } }
+ let(:spec_params) { { name: valid_label_title_1 } }
end
it_behaves_like 'label delete API' do
@@ -422,7 +427,7 @@ RSpec.describe API::Labels do
end
it 'returns 404 for non existing label' do
- delete api("/projects/#{project.id}/labels", user), params: { name: 'label2' }
+ delete api("/projects/#{project.id}/labels", user), params: { name: 'unknown' }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 Label Not Found')
@@ -446,14 +451,14 @@ RSpec.describe API::Labels do
it_behaves_like '412 response' do
let(:request) { api("/projects/#{project.id}/labels", user) }
- let(:params) { { name: 'label1' } }
+ let(:params) { { name: valid_label_title_1 } }
end
end
describe 'PUT /projects/:id/labels' do
context 'when using name' do
it_behaves_like 'label update API' do
- let(:spec_params) { { name: 'label1' } }
+ let(:spec_params) { { name: valid_label_title_1 } }
let(:expected_response_label_id) { label1.id }
end
end
@@ -468,7 +473,7 @@ RSpec.describe API::Labels do
it 'returns 404 if label does not exist' do
put api("/projects/#{project.id}/labels", user),
params: {
- name: 'label2',
+ name: valid_label_title_2,
new_name: 'label3'
}
@@ -571,7 +576,7 @@ RSpec.describe API::Labels do
describe "POST /projects/:id/labels/:label_id/subscribe" do
context "when label_id is a label title" do
it "subscribes to the label" do
- post api("/projects/#{project.id}/labels/#{label1.title}/subscribe", user)
+ post api("/projects/#{project.id}/labels/#{valid_label_title_1_esc}/subscribe", user)
expect(response).to have_gitlab_http_status(:created)
expect(json_response["name"]).to eq(label1.title)
@@ -617,7 +622,7 @@ RSpec.describe API::Labels do
context "when label_id is a label title" do
it "unsubscribes from the label" do
- post api("/projects/#{project.id}/labels/#{label1.title}/unsubscribe", user)
+ post api("/projects/#{project.id}/labels/#{valid_label_title_1_esc}/unsubscribe", user)
expect(response).to have_gitlab_http_status(:created)
expect(json_response["name"]).to eq(label1.title)
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index e5d11fb1218..7f0e4f18e3b 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -4,6 +4,8 @@ require 'spec_helper'
RSpec.describe API::MavenPackages do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let_it_be_with_refind(:package_settings) { create(:namespace_package_setting, :group) }
let_it_be(:group) { package_settings.namespace }
let_it_be(:user) { create(:user) }
@@ -20,8 +22,7 @@ RSpec.describe API::MavenPackages do
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
let(:package_name) { 'com/example/my-app' }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ let(:headers) { workhorse_headers }
let(:headers_with_token) { headers.merge('Private-Token' => personal_access_token.token) }
let(:group_deploy_token_headers) { { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => deploy_token_for_group.token } }
@@ -32,6 +33,7 @@ RSpec.describe API::MavenPackages do
end
let(:version) { '1.0-SNAPSHOT' }
+ let(:param_path) { "#{package_name}/#{version}"}
before do
project.add_developer(user)
@@ -547,8 +549,8 @@ RSpec.describe API::MavenPackages do
end
describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name' do
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let(:send_rewritten_field) { true }
let(:file_upload) { fixture_file_upload('spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.jar') }
@@ -601,7 +603,7 @@ RSpec.describe API::MavenPackages do
end
context 'without workhorse header' do
- let(:workhorse_header) { {} }
+ let(:workhorse_headers) { {} }
subject { upload_file_with_token(params: params) }
@@ -695,6 +697,14 @@ RSpec.describe API::MavenPackages do
expect(json_response['message']).to include('Duplicate package is not allowed')
end
+ context 'when uploading to the versionless package which contains metadata about all versions' do
+ let(:version) { nil }
+ let(:param_path) { package_name }
+ let!(:package) { create(:maven_package, project: project, version: version, name: project.full_path) }
+
+ it_behaves_like 'storing the package file'
+ end
+
context 'when uploading different non-duplicate files to the same package' do
let!(:package) { create(:maven_package, project: project, name: project.full_path) }
@@ -744,7 +754,7 @@ RSpec.describe API::MavenPackages do
end
def upload_file(params: {}, request_headers: headers, file_extension: 'jar')
- url = "/projects/#{project.id}/packages/maven/#{package_name}/#{version}/my-app-1.0-20180724.124855-1.#{file_extension}"
+ url = "/projects/#{project.id}/packages/maven/#{param_path}/my-app-1.0-20180724.124855-1.#{file_extension}"
workhorse_finalize(
api(url),
method: :put,
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index a04867658e8..ad8e21bf4c1 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1322,7 +1322,16 @@ RSpec.describe API::MergeRequests do
end
context 'Work in Progress' do
- let!(:merge_request_wip) { create(:merge_request, author: user, assignees: [user], source_project: project, target_project: project, title: "WIP: Test", created_at: base_time + 1.second) }
+ let!(:merge_request_wip) do
+ create(:merge_request,
+ author: user,
+ assignees: [user],
+ source_project: project,
+ target_project: project,
+ title: "WIP: Test",
+ created_at: base_time + 1.second
+ )
+ end
it "returns merge request" do
get api("/projects/#{project.id}/merge_requests/#{merge_request_wip.iid}", user)
@@ -1566,9 +1575,9 @@ RSpec.describe API::MergeRequests do
end
end
- context 'when access_raw_diffs is passed as an option' do
+ context 'when access_raw_diffs is true' do
it_behaves_like 'accesses diffs via raw_diffs' do
- let(:params) { { access_raw_diffs: true } }
+ let(:params) { { access_raw_diffs: "true" } }
end
end
end
@@ -1766,6 +1775,36 @@ RSpec.describe API::MergeRequests do
end
end
+ context 'accepts reviewer_ids' do
+ let(:params) do
+ {
+ title: 'Test merge request',
+ source_branch: 'feature_conflict',
+ target_branch: 'master',
+ author_id: user.id,
+ reviewer_ids: [user2.id]
+ }
+ end
+
+ it 'creates a new merge request with a reviewer' do
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['title']).to eq('Test merge request')
+ expect(json_response['reviewers'].first['name']).to eq(user2.name)
+ end
+
+ it 'creates a new merge request with no reviewer' do
+ params[:reviewer_ids] = []
+
+ post api("/projects/#{project.id}/merge_requests", user), params: params
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['title']).to eq('Test merge request')
+ expect(json_response['reviewers']).to be_empty
+ end
+ end
+
context 'between branches projects' do
context 'different labels' do
let(:params) do
@@ -2111,6 +2150,34 @@ RSpec.describe API::MergeRequests do
it_behaves_like 'issuable update endpoint' do
let(:entity) { merge_request }
end
+
+ context 'accepts reviewer_ids' do
+ let(:params) do
+ {
+ title: 'Updated merge request',
+ reviewer_ids: [user2.id]
+ }
+ end
+
+ it 'adds a reviewer to the existing merge request' do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['title']).to eq('Updated merge request')
+ expect(json_response['reviewers'].first['name']).to eq(user2.name)
+ end
+
+ it 'removes a reviewer from the existing merge request' do
+ merge_request.reviewers = [user2]
+ params[:reviewer_ids] = []
+
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['title']).to eq('Updated merge request')
+ expect(json_response['reviewers']).to be_empty
+ end
+ end
end
describe "POST /projects/:id/merge_requests/:merge_request_iid/context_commits" do
diff --git a/spec/requests/api/npm_instance_packages_spec.rb b/spec/requests/api/npm_instance_packages_spec.rb
index 8299717b5c7..70c76067a6e 100644
--- a/spec/requests/api/npm_instance_packages_spec.rb
+++ b/spec/requests/api/npm_instance_packages_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe API::NpmInstancePackages do
include_context 'npm api setup'
describe 'GET /api/v4/packages/npm/*package_name' do
- it_behaves_like 'handling get metadata requests' do
+ it_behaves_like 'handling get metadata requests', scope: :instance do
let(:url) { api("/packages/npm/#{package_name}") }
end
end
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index 1421f20ac28..7ea238c0607 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -6,25 +6,25 @@ RSpec.describe API::NpmProjectPackages do
include_context 'npm api setup'
describe 'GET /api/v4/projects/:id/packages/npm/*package_name' do
- it_behaves_like 'handling get metadata requests' do
+ it_behaves_like 'handling get metadata requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/#{package_name}") }
end
end
describe 'GET /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags' do
- it_behaves_like 'handling get dist tags requests' do
+ it_behaves_like 'handling get dist tags requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags") }
end
end
describe 'PUT /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do
- it_behaves_like 'handling create dist tag requests' do
+ it_behaves_like 'handling create dist tag requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
end
end
describe 'DELETE /api/v4/projects/:id/packages/npm/-/package/*package_name/dist-tags/:tag' do
- it_behaves_like 'handling delete dist tag requests' do
+ it_behaves_like 'handling delete dist tag requests', scope: :project do
let(:url) { api("/projects/#{project.id}/packages/npm/-/package/#{package_name}/dist-tags/#{tag_name}") }
end
end
@@ -32,10 +32,14 @@ RSpec.describe API::NpmProjectPackages do
describe 'GET /api/v4/projects/:id/packages/npm/*package_name/-/*file_name' do
let_it_be(:package_file) { package.package_files.first }
- let(:params) { {} }
- let(:url) { api("/projects/#{project.id}/packages/npm/#{package_file.package.name}/-/#{package_file.file_name}") }
+ let(:headers) { {} }
+ let(:url) { api("/projects/#{project.id}/packages/npm/#{package.name}/-/#{package_file.file_name}") }
- subject { get(url, params: params) }
+ subject { get(url, headers: headers) }
+
+ before do
+ project.add_developer(user)
+ end
shared_examples 'a package file that requires auth' do
it 'denies download with no token' do
@@ -45,7 +49,7 @@ RSpec.describe API::NpmProjectPackages do
end
context 'with access token' do
- let(:params) { { access_token: token.token } }
+ let(:headers) { build_token_auth_header(token.token) }
it 'returns the file' do
subject
@@ -56,7 +60,7 @@ RSpec.describe API::NpmProjectPackages do
end
context 'with job token' do
- let(:params) { { job_token: job.token } }
+ let(:headers) { build_token_auth_header(job.token) }
it 'returns the file' do
subject
@@ -86,7 +90,7 @@ RSpec.describe API::NpmProjectPackages do
it_behaves_like 'a package file that requires auth'
context 'with guest' do
- let(:params) { { access_token: token.token } }
+ let(:headers) { build_token_auth_header(token.token) }
it 'denies download when not enough permissions' do
project.add_guest(user)
@@ -108,7 +112,11 @@ RSpec.describe API::NpmProjectPackages do
end
describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do
- RSpec.shared_examples 'handling invalid record with 400 error' do
+ before do
+ project.add_developer(user)
+ end
+
+ shared_examples 'handling invalid record with 400 error' do
it 'handles an ActiveRecord::RecordInvalid exception with 400 error' do
expect { upload_package_with_token(package_name, params) }
.not_to change { project.packages.count }
@@ -261,7 +269,9 @@ RSpec.describe API::NpmProjectPackages do
end
def upload_package(package_name, params = {})
- put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params: params
+ token = params.delete(:access_token) || params.delete(:job_token)
+ headers = build_token_auth_header(token)
+ put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params: params, headers: headers
end
def upload_package_with_token(package_name, params = {})
diff --git a/spec/requests/api/nuget_project_packages_spec.rb b/spec/requests/api/nuget_project_packages_spec.rb
index 813ebc35ede..0277aa73220 100644
--- a/spec/requests/api/nuget_project_packages_spec.rb
+++ b/spec/requests/api/nuget_project_packages_spec.rb
@@ -144,8 +144,8 @@ RSpec.describe API::NugetProjectPackages do
end
describe 'PUT /api/v4/projects/:id/packages/nuget/authorize' do
- let_it_be(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let_it_be(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let(:url) { "/projects/#{target.id}/packages/nuget/authorize" }
let(:headers) { {} }
@@ -176,7 +176,7 @@ RSpec.describe API::NugetProjectPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
@@ -194,8 +194,8 @@ RSpec.describe API::NugetProjectPackages do
end
describe 'PUT /api/v4/projects/:id/packages/nuget' do
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let_it_be(:file_name) { 'package.nupkg' }
let(:url) { "/projects/#{target.id}/packages/nuget" }
let(:headers) { {} }
@@ -239,7 +239,7 @@ RSpec.describe API::NugetProjectPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
@@ -256,7 +256,7 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'rejects nuget access with invalid target id'
context 'file size above maximum limit' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_headers) }
before do
allow_next_instance_of(UploadedFile) do |uploaded_file|
diff --git a/spec/requests/api/oauth_tokens_spec.rb b/spec/requests/api/oauth_tokens_spec.rb
index 23d5df873d4..52c7408545f 100644
--- a/spec/requests/api/oauth_tokens_spec.rb
+++ b/spec/requests/api/oauth_tokens_spec.rb
@@ -26,17 +26,14 @@ RSpec.describe 'OAuth tokens' do
end
context 'when user does not have 2FA enabled' do
- # NOTE: using ROPS grant flow without client credentials will be deprecated
- # and removed in the next version of Doorkeeper.
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/219137
context 'when no client credentials provided' do
- it 'creates an access token' do
+ it 'does not create an access token' do
user = create(:user)
request_oauth_token(user)
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['access_token']).not_to be_nil
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(json_response['access_token']).to be_nil
end
end
@@ -54,15 +51,11 @@ RSpec.describe 'OAuth tokens' do
context 'with invalid credentials' do
it 'does not create an access token' do
- # NOTE: remove this after update to Doorkeeper 5.5 or newer, see
- # https://gitlab.com/gitlab-org/gitlab/-/issues/219137
- pending 'Enable this example after upgrading Doorkeeper to 5.5 or newer'
-
user = create(:user)
request_oauth_token(user, basic_auth_header(client.uid, 'invalid secret'))
- expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response).to have_gitlab_http_status(:unauthorized)
expect(json_response['error']).to eq('invalid_client')
end
end
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
new file mode 100644
index 00000000000..181fcafd577
--- /dev/null
+++ b/spec/requests/api/project_attributes.yml
@@ -0,0 +1,149 @@
+---
+itself: # project
+ unexposed_attributes:
+ - bfg_object_map
+ - delete_error
+ - detected_repository_languages
+ - disable_overriding_approvers_per_merge_request
+ - external_authorization_classification_label
+ - external_webhook_token
+ - has_external_issue_tracker
+ - has_external_wiki
+ - import_source
+ - import_type
+ - import_url
+ - issues_template
+ - jobs_cache_index
+ - last_repository_check_at
+ - last_repository_check_failed
+ - last_repository_updated_at
+ - marked_for_deletion_at
+ - marked_for_deletion_by_user_id
+ - max_artifacts_size
+ - max_pages_size
+ - merge_requests_author_approval
+ - merge_requests_disable_committers_approval
+ - merge_requests_rebase_enabled
+ - merge_requests_template
+ - mirror_last_successful_update_at
+ - mirror_last_update_at
+ - mirror_overwrites_diverged_branches
+ - mirror_trigger_builds
+ - mirror_user_id
+ - only_mirror_protected_branches
+ - pages_https_only
+ - pending_delete
+ - pool_repository_id
+ - pull_mirror_available_overridden
+ - pull_mirror_branch_prefix
+ - remote_mirror_available_overridden
+ - repository_read_only
+ - repository_size_limit
+ - require_password_to_approve
+ - reset_approvals_on_push
+ - runners_token_encrypted
+ - storage_version
+ - updated_at
+ remapped_attributes:
+ avatar: avatar_url
+ build_allow_git_fetch: build_git_strategy
+ merge_requests_ff_only_enabled: merge_method
+ namespace_id: namespace
+ public_builds: public_jobs
+ visibility_level: visibility
+ computed_attributes:
+ - _links
+ - can_create_merge_request_in
+ - compliance_frameworks
+ - container_expiration_policy
+ - default_branch
+ - empty_repo
+ - forks_count
+ - http_url_to_repo
+ - name_with_namespace
+ - open_issues_count
+ - owner
+ - path_with_namespace
+ - permissions
+ - readme_url
+ - shared_with_groups
+ - ssh_url_to_repo
+ - web_url
+
+build_auto_devops: # auto_devops
+ unexposed_attributes:
+ - id
+ - project_id
+ - created_at
+ - updated_at
+ remapped_attributes:
+ enabled: auto_devops_enabled
+ deploy_strategy: auto_devops_deploy_strategy
+
+ci_cd_settings:
+ unexposed_attributes:
+ - id
+ - project_id
+ - group_runners_enabled
+ - keep_latest_artifact
+ - merge_pipelines_enabled
+ - merge_trains_enabled
+ - auto_rollback_enabled
+ remapped_attributes:
+ default_git_depth: ci_default_git_depth
+ forward_deployment_enabled: ci_forward_deployment_enabled
+
+build_import_state: # import_state
+ unexposed_attributes:
+ - id
+ - project_id
+ - retry_count
+ - last_update_started_at
+ - last_update_scheduled_at
+ - next_execution_timestamp
+ - jid
+ - last_update_at
+ - last_successful_update_at
+ - correlation_id_value
+ remapped_attributes:
+ status: import_status
+ last_error: import_error
+
+project_feature:
+ unexposed_attributes:
+ - id
+ - created_at
+ - metrics_dashboard_access_level
+ - project_id
+ - requirements_access_level
+ - security_and_compliance_access_level
+ - updated_at
+ computed_attributes:
+ - issues_enabled
+ - jobs_enabled
+ - merge_requests_enabled
+ - requirements_enabled
+ - security_and_compliance_enabled
+ - snippets_enabled
+ - wiki_enabled
+
+project_setting:
+ unexposed_attributes:
+ - allow_editing_commit_messages
+ - created_at
+ - has_confluence
+ - has_vulnerabilities
+ - prevent_merge_without_jira_issue
+ - project_id
+ - push_rule_id
+ - show_default_award_emojis
+ - squash_option
+ - updated_at
+
+build_service_desk_setting: # service_desk_setting
+ unexposed_attributes:
+ - project_id
+ - issue_template_key
+ - outgoing_name
+ remapped_attributes:
+ project_key: service_desk_address
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 8e99d37c84f..a049d7d7515 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -5,13 +5,12 @@ require 'spec_helper'
RSpec.describe API::ProjectImport do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let(:user) { create(:user) }
let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
let(:namespace) { create(:group) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
-
before do
namespace.add_owner(user)
end
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index eb86df36dbb..1f3887cab8a 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -120,6 +120,7 @@ RSpec.describe API::ProjectPackages do
end
it_behaves_like 'with versionless packages'
+ it_behaves_like 'with status param'
it_behaves_like 'does not cause n^2 queries'
end
end
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
index fc1035fc17d..a424bc62014 100644
--- a/spec/requests/api/project_templates_spec.rb
+++ b/spec/requests/api/project_templates_spec.rb
@@ -131,7 +131,7 @@ RSpec.describe API::ProjectTemplates do
end
end
- describe 'GET /projects/:id/templates/:type/:key' do
+ describe 'GET /projects/:id/templates/:type/:name' do
it 'returns a specific dockerfile' do
get api("/projects/#{public_project.id}/templates/dockerfiles/Binary")
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 8a4a7880ab4..ad36777184a 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1140,7 +1140,7 @@ RSpec.describe API::Projects do
let!(:public_project) { create(:project, :public, name: 'public_project', creator_id: user4.id, namespace: user4.namespace) }
it 'returns error when user not found' do
- get api('/users/0/projects/')
+ get api("/users/#{non_existing_record_id}/projects/")
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
@@ -1540,6 +1540,35 @@ RSpec.describe API::Projects do
end
context 'when authenticated as an admin' do
+ let(:project_attributes_file) { 'spec/requests/api/project_attributes.yml' }
+ let(:project_attributes) { YAML.load_file(project_attributes_file) }
+
+ let(:expected_keys) do
+ keys = project_attributes.map do |relation, relation_config|
+ begin
+ actual_keys = project.send(relation).attributes.keys
+ rescue NoMethodError
+ actual_keys = ["#{relation} is nil"]
+ end
+ unexposed_attributes = relation_config['unexposed_attributes'] || []
+ remapped_attributes = relation_config['remapped_attributes'] || {}
+ computed_attributes = relation_config['computed_attributes'] || []
+ actual_keys - unexposed_attributes - remapped_attributes.keys + remapped_attributes.values + computed_attributes
+ end.flatten
+
+ unless Gitlab.ee?
+ keys -= %w[
+ approvals_before_merge
+ compliance_frameworks
+ mirror
+ requirements_enabled
+ security_and_compliance_enabled
+ ]
+ end
+
+ keys
+ end
+
it 'returns a project by id' do
project
project_member
@@ -1588,6 +1617,27 @@ RSpec.describe API::Projects do
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
expect(json_response['operations_access_level']).to be_present
end
+
+ it 'exposes all necessary attributes' do
+ create(:project_group_link, project: project)
+
+ get api("/projects/#{project.id}", admin)
+
+ diff = Set.new(json_response.keys) ^ Set.new(expected_keys)
+
+ expect(diff).to be_empty, failure_message(diff)
+ end
+
+ def failure_message(diff)
+ <<~MSG
+ It looks like project's set of exposed attributes is different from the expected set.
+
+ The following attributes are missing or newly added:
+ #{diff.to_a.to_sentence}
+
+ Please update #{project_attributes_file} file"
+ MSG
+ end
end
context 'when authenticated as a regular user' do
@@ -2155,7 +2205,7 @@ RSpec.describe API::Projects do
end
it 'fails if forked_from project which does not exist' do
- post api("/projects/#{project_fork_target.id}/fork/0", admin)
+ post api("/projects/#{project_fork_target.id}/fork/#{non_existing_record_id}", admin)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -2399,7 +2449,7 @@ RSpec.describe API::Projects do
end
it 'returns a 404 error when project does not exist' do
- delete api("/projects/123/share/#{non_existing_record_id}", user)
+ delete api("/projects/#{non_existing_record_id}/share/#{non_existing_record_id}", user)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -2956,7 +3006,7 @@ RSpec.describe API::Projects do
end
it 'returns the proper security headers' do
- get api('/projects/1/starrers', current_user)
+ get api("/projects/#{public_project.id}/starrers", current_user)
expect(response).to include_security_headers
end
@@ -3029,7 +3079,7 @@ RSpec.describe API::Projects do
end
it 'returns not_found(404) for not existing project' do
- get api("/projects/0/languages", user)
+ get api("/projects/#{non_existing_record_id}/languages", user)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3080,7 +3130,7 @@ RSpec.describe API::Projects do
end
it 'does not remove a non existing project' do
- delete api('/projects/1328', user)
+ delete api("/projects/#{non_existing_record_id}", user)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3099,7 +3149,7 @@ RSpec.describe API::Projects do
end
it 'does not remove a non existing project' do
- delete api('/projects/1328', admin)
+ delete api("/projects/#{non_existing_record_id}", admin)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -3329,8 +3379,8 @@ RSpec.describe API::Projects do
expect(json_response['message']['path']).to eq(['has already been taken'])
end
- it 'accepts a name for the target project' do
- post api("/projects/#{project.id}/fork", user2), params: { name: 'My Random Project' }
+ it 'accepts custom parameters for the target project' do
+ post api("/projects/#{project.id}/fork", user2), params: { name: 'My Random Project', description: 'A description', visibility: 'private' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response['name']).to eq('My Random Project')
@@ -3338,6 +3388,8 @@ RSpec.describe API::Projects do
expect(json_response['owner']['id']).to eq(user2.id)
expect(json_response['namespace']['id']).to eq(user2.namespace.id)
expect(json_response['forked_from_project']['id']).to eq(project.id)
+ expect(json_response['description']).to eq('A description')
+ expect(json_response['visibility']).to eq('private')
expect(json_response['import_status']).to eq('scheduled')
expect(json_response).to include("import_error")
end
@@ -3369,6 +3421,13 @@ RSpec.describe API::Projects do
expect(json_response['message']['path']).to eq(['has already been taken'])
expect(json_response['message']['name']).to eq(['has already been taken'])
end
+
+ it 'fails to fork with an unknown visibility level' do
+ post api("/projects/#{project.id}/fork", user2), params: { visibility: 'something' }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('visibility does not have a valid value')
+ end
end
context 'when unauthenticated' do
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index 72a470dca4b..ae5b132f409 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -5,6 +5,7 @@ RSpec.describe API::PypiPackages do
include WorkhorseHelpers
include PackagesManagerApiSpecHelpers
include HttpBasicAuthHelpers
+ using RSpec::Parameterized::TableSyntax
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :public) }
@@ -20,8 +21,6 @@ RSpec.describe API::PypiPackages do
subject { get api(url) }
context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPI package versions' | :success
'PUBLIC' | :guest | true | true | 'PyPI package versions' | :success
@@ -75,16 +74,14 @@ RSpec.describe API::PypiPackages do
end
describe 'POST /api/v4/projects/:id/packages/pypi/authorize' do
- let_it_be(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let_it_be(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let(:url) { "/projects/#{project.id}/packages/pypi/authorize" }
let(:headers) { {} }
subject { post api(url), headers: headers }
context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process PyPI api request' | :success
'PUBLIC' | :guest | true | true | 'process PyPI api request' | :forbidden
@@ -109,7 +106,7 @@ RSpec.describe API::PypiPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
@@ -127,8 +124,8 @@ RSpec.describe API::PypiPackages do
end
describe 'POST /api/v4/projects/:id/packages/pypi' do
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let_it_be(:file_name) { 'package.whl' }
let(:url) { "/projects/#{project.id}/packages/pypi" }
let(:headers) { {} }
@@ -149,8 +146,6 @@ RSpec.describe API::PypiPackages do
end
context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPI package creation' | :created
'PUBLIC' | :guest | true | true | 'process PyPI api request' | :forbidden
@@ -175,7 +170,7 @@ RSpec.describe API::PypiPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
@@ -189,7 +184,7 @@ RSpec.describe API::PypiPackages do
let(:requires_python) { 'x' * 256 }
let(:token) { personal_access_token.token }
let(:user_headers) { basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -201,7 +196,7 @@ RSpec.describe API::PypiPackages do
context 'with an invalid package' do
let(:token) { personal_access_token.token }
let(:user_headers) { basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
params[:name] = '.$/@!^*'
@@ -218,7 +213,7 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'rejects PyPI access with unknown project id'
context 'file size above maximum limit' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_headers) }
before do
allow_next_instance_of(UploadedFile) do |uploaded_file|
@@ -239,8 +234,6 @@ RSpec.describe API::PypiPackages do
subject { get api(url) }
context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'PyPI package download' | :success
'PUBLIC' | :guest | true | true | 'PyPI package download' | :success
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 45bce8c8a5c..ace73e49c7c 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -610,4 +610,85 @@ RSpec.describe API::Repositories do
end
end
end
+
+ describe 'POST /projects/:id/repository/changelog' do
+ it 'generates the changelog for a version' do
+ spy = instance_spy(Repositories::ChangelogService)
+
+ allow(Repositories::ChangelogService)
+ .to receive(:new)
+ .with(
+ project,
+ user,
+ version: '1.0.0',
+ from: 'foo',
+ to: 'bar',
+ date: DateTime.new(2020, 1, 1),
+ branch: 'kittens',
+ trailer: 'Foo',
+ file: 'FOO.md',
+ message: 'Commit message'
+ )
+ .and_return(spy)
+
+ allow(spy).to receive(:execute)
+
+ post(
+ api("/projects/#{project.id}/repository/changelog", user),
+ params: {
+ version: '1.0.0',
+ from: 'foo',
+ to: 'bar',
+ date: '2020-01-01',
+ branch: 'kittens',
+ trailer: 'Foo',
+ file: 'FOO.md',
+ message: 'Commit message'
+ }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'produces an error when generating the changelog fails' do
+ spy = instance_spy(Repositories::ChangelogService)
+
+ allow(Repositories::ChangelogService)
+ .to receive(:new)
+ .with(
+ project,
+ user,
+ version: '1.0.0',
+ from: 'foo',
+ to: 'bar',
+ date: DateTime.new(2020, 1, 1),
+ branch: 'kittens',
+ trailer: 'Foo',
+ file: 'FOO.md',
+ message: 'Commit message'
+ )
+ .and_return(spy)
+
+ allow(spy)
+ .to receive(:execute)
+ .and_raise(Gitlab::Changelog::Error.new('oops'))
+
+ post(
+ api("/projects/#{project.id}/repository/changelog", user),
+ params: {
+ version: '1.0.0',
+ from: 'foo',
+ to: 'bar',
+ date: '2020-01-01',
+ branch: 'kittens',
+ trailer: 'Foo',
+ file: 'FOO.md',
+ message: 'Commit message'
+ }
+ )
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq('Failed to generate the changelog: oops')
+ end
+ end
end
diff --git a/spec/requests/api/resource_access_tokens_spec.rb b/spec/requests/api/resource_access_tokens_spec.rb
new file mode 100644
index 00000000000..9fd7eb2177d
--- /dev/null
+++ b/spec/requests/api/resource_access_tokens_spec.rb
@@ -0,0 +1,293 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe API::ResourceAccessTokens do
+ context "when the resource is a project" do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:other_project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ describe "GET projects/:id/access_tokens" do
+ subject(:get_tokens) { get api("/projects/#{project_id}/access_tokens", user) }
+
+ context "when the user has maintainer permissions" do
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+ let_it_be(:access_tokens) { create_list(:personal_access_token, 3, user: project_bot) }
+ let_it_be(:project_id) { project.id }
+
+ before do
+ project.add_maintainer(user)
+ project.add_maintainer(project_bot)
+ end
+
+ it "gets a list of access tokens for the specified project" do
+ get_tokens
+
+ token_ids = json_response.map { |token| token['id'] }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(token_ids).to match_array(access_tokens.pluck(:id))
+ end
+
+ context "when using a project access token to GET other project access tokens" do
+ let_it_be(:token) { access_tokens.first }
+
+ it "gets a list of access tokens for the specified project" do
+ get api("/projects/#{project_id}/access_tokens", personal_access_token: token)
+
+ token_ids = json_response.map { |token| token['id'] }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(token_ids).to match_array(access_tokens.pluck(:id))
+ end
+ end
+
+ context "when tokens belong to a different project" do
+ let_it_be(:bot) { create(:user, :project_bot) }
+ let_it_be(:token) { create(:personal_access_token, user: bot) }
+
+ before do
+ other_project.add_maintainer(bot)
+ other_project.add_maintainer(user)
+ end
+
+ it "does not return tokens from a different project" do
+ get_tokens
+
+ token_ids = json_response.map { |token| token['id'] }
+
+ expect(token_ids).not_to include(token.id)
+ end
+ end
+
+ context "when the project has no access tokens" do
+ let(:project_id) { other_project.id }
+
+ before do
+ other_project.add_maintainer(user)
+ end
+
+ it 'returns an empty array' do
+ get_tokens
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+ end
+
+ context "when trying to get the tokens of a different project" do
+ let_it_be(:project_id) { other_project.id }
+
+ it "returns 404" do
+ get_tokens
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context "when the project does not exist" do
+ let(:project_id) { non_existing_record_id }
+
+ it "returns 404" do
+ get_tokens
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context "when the user does not have valid permissions" do
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+ let_it_be(:access_tokens) { create_list(:personal_access_token, 3, user: project_bot) }
+ let_it_be(:project_id) { project.id }
+
+ before do
+ project.add_developer(user)
+ project.add_maintainer(project_bot)
+ end
+
+ it "returns 401" do
+ get_tokens
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ describe "DELETE projects/:id/access_tokens/:token_id", :sidekiq_inline do
+ subject(:delete_token) { delete api("/projects/#{project_id}/access_tokens/#{token_id}", user) }
+
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+ let_it_be(:token) { create(:personal_access_token, user: project_bot) }
+ let_it_be(:project_id) { project.id }
+ let_it_be(:token_id) { token.id }
+
+ before do
+ project.add_maintainer(project_bot)
+ end
+
+ context "when the user has maintainer permissions" do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it "deletes the project access token from the project" do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(User.exists?(project_bot.id)).to be_falsy
+ end
+
+ context "when attempting to delete a non-existent project access token" do
+ let_it_be(:token_id) { non_existing_record_id }
+
+ it "does not delete the token, and returns 404" do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to include("Could not find project access token with token_id: #{token_id}")
+ end
+ end
+
+ context "when attempting to delete a token that does not belong to the specified project" do
+ let_it_be(:project_id) { other_project.id }
+
+ before do
+ other_project.add_maintainer(user)
+ end
+
+ it "does not delete the token, and returns 404" do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to include("Could not find project access token with token_id: #{token_id}")
+ end
+ end
+ end
+
+ context "when the user does not have valid permissions" do
+ before do
+ project.add_developer(user)
+ end
+
+ it "does not delete the token, and returns 400", :aggregate_failures do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(User.exists?(project_bot.id)).to be_truthy
+ expect(response.body).to include("#{user.name} cannot delete #{token.user.name}")
+ end
+ end
+ end
+
+ describe "POST projects/:id/access_tokens" do
+ let_it_be(:params) { { name: "test", scopes: ["api"], expires_at: Date.today + 1.month } }
+
+ subject(:create_token) { post api("/projects/#{project_id}/access_tokens", user), params: params }
+
+ context "when the user has maintainer permissions" do
+ let_it_be(:project_id) { project.id }
+ let_it_be(:expires_at) { 1.month.from_now }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ context "with valid params" do
+ context "with full params" do
+ it "creates a project access token with the params", :aggregate_failures do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response["name"]).to eq("test")
+ expect(json_response["scopes"]).to eq(["api"])
+ expect(json_response["expires_at"]).to eq(expires_at.to_date.iso8601)
+ end
+ end
+
+ context "when 'expires_at' is not set" do
+ let_it_be(:params) { { name: "test", scopes: ["api"] } }
+
+ it "creates a project access token with the params", :aggregate_failures do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response["name"]).to eq("test")
+ expect(json_response["scopes"]).to eq(["api"])
+ expect(json_response["expires_at"]).to eq(nil)
+ end
+ end
+ end
+
+ context "with invalid params" do
+ context "when missing the 'name' param" do
+ let_it_be(:params) { { scopes: ["api"], expires_at: 5.days.from_now } }
+
+ it "does not create a project access token without 'name'" do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include("name is missing")
+ end
+ end
+
+ context "when missing the 'scopes' param" do
+ let_it_be(:params) { { name: "test", expires_at: 5.days.from_now } }
+
+ it "does not create a project access token without 'scopes'" do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include("scopes is missing")
+ end
+ end
+ end
+
+ context "when trying to create a token in a different project" do
+ let_it_be(:project_id) { other_project.id }
+
+ it "does not create the token, and returns the project not found error" do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to include("Project Not Found")
+ end
+ end
+ end
+
+ context "when the user does not have valid permissions" do
+ let_it_be(:project_id) { project.id }
+
+ context "when the user is a developer" do
+ before do
+ project.add_developer(user)
+ end
+
+ it "does not create the token, and returns the permission error" do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include("User does not have permission to create project access token")
+ end
+ end
+
+ context "when a project access token tries to create another project access token" do
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+ let_it_be(:user) { project_bot }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it "does not allow a project access token to create another project access token" do
+ create_token
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include("User does not have permission to create project access token")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/rubygem_packages_spec.rb b/spec/requests/api/rubygem_packages_spec.rb
new file mode 100644
index 00000000000..5dd68bf9b10
--- /dev/null
+++ b/spec/requests/api/rubygem_packages_spec.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::RubygemPackages do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:personal_access_token) { create(:personal_access_token) }
+ let_it_be(:user) { personal_access_token.user }
+ let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
+ let_it_be(:headers) { {} }
+
+ shared_examples 'when feature flag is disabled' do
+ let(:headers) do
+ { 'HTTP_AUTHORIZATION' => personal_access_token.token }
+ end
+
+ before do
+ stub_feature_flags(rubygem_packages: false)
+ end
+
+ it_behaves_like 'returning response status', :not_found
+ end
+
+ shared_examples 'when package feature is disabled' do
+ before do
+ stub_config(packages: { enabled: false })
+ end
+
+ it_behaves_like 'returning response status', :not_found
+ end
+
+ shared_examples 'without authentication' do
+ it_behaves_like 'returning response status', :unauthorized
+ end
+
+ shared_examples 'with authentication' do
+ let(:headers) do
+ { 'HTTP_AUTHORIZATION' => token }
+ end
+
+ let(:tokens) do
+ {
+ personal_access_token: personal_access_token.token,
+ deploy_token: deploy_token.token,
+ job_token: job.token
+ }
+ end
+
+ where(:user_role, :token_type, :valid_token, :status) do
+ :guest | :personal_access_token | true | :not_found
+ :guest | :personal_access_token | false | :unauthorized
+ :guest | :deploy_token | true | :not_found
+ :guest | :deploy_token | false | :unauthorized
+ :guest | :job_token | true | :not_found
+ :guest | :job_token | false | :unauthorized
+ :reporter | :personal_access_token | true | :not_found
+ :reporter | :personal_access_token | false | :unauthorized
+ :reporter | :deploy_token | true | :not_found
+ :reporter | :deploy_token | false | :unauthorized
+ :reporter | :job_token | true | :not_found
+ :reporter | :job_token | false | :unauthorized
+ :developer | :personal_access_token | true | :not_found
+ :developer | :personal_access_token | false | :unauthorized
+ :developer | :deploy_token | true | :not_found
+ :developer | :deploy_token | false | :unauthorized
+ :developer | :job_token | true | :not_found
+ :developer | :job_token | false | :unauthorized
+ end
+
+ with_them do
+ before do
+ project.send("add_#{user_role}", user) unless user_role == :anonymous
+ end
+
+ let(:token) { valid_token ? tokens[token_type] : 'invalid-token123' }
+
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+
+ shared_examples 'an unimplemented route' do
+ it_behaves_like 'without authentication'
+ it_behaves_like 'with authentication'
+ it_behaves_like 'when feature flag is disabled'
+ it_behaves_like 'when package feature is disabled'
+ end
+
+ describe 'GET /api/v4/projects/:project_id/packages/rubygems/:filename' do
+ let(:url) { api("/projects/#{project.id}/packages/rubygems/specs.4.8.gz") }
+
+ subject { get(url, headers: headers) }
+
+ it_behaves_like 'an unimplemented route'
+ end
+
+ describe 'GET /api/v4/projects/:project_id/packages/rubygems/quick/Marshal.4.8/:file_name' do
+ let(:url) { api("/projects/#{project.id}/packages/rubygems/quick/Marshal.4.8/my_gem-1.0.0.gemspec.rz") }
+
+ subject { get(url, headers: headers) }
+
+ it_behaves_like 'an unimplemented route'
+ end
+
+ describe 'GET /api/v4/projects/:project_id/packages/rubygems/gems/:file_name' do
+ let(:url) { api("/projects/#{project.id}/packages/rubygems/gems/my_gem-1.0.0.gem") }
+
+ subject { get(url, headers: headers) }
+
+ it_behaves_like 'an unimplemented route'
+ end
+
+ describe 'POST /api/v4/projects/:project_id/packages/rubygems/api/v1/gems/authorize' do
+ let(:url) { api("/projects/#{project.id}/packages/rubygems/api/v1/gems/authorize") }
+
+ subject { post(url, headers: headers) }
+
+ it_behaves_like 'an unimplemented route'
+ end
+
+ describe 'POST /api/v4/projects/:project_id/packages/rubygems/api/v1/gems' do
+ let(:url) { api("/projects/#{project.id}/packages/rubygems/api/v1/gems") }
+
+ subject { post(url, headers: headers) }
+
+ it_behaves_like 'an unimplemented route'
+ end
+
+ describe 'GET /api/v4/projects/:project_id/packages/rubygems/api/v1/dependencies' do
+ let(:url) { api("/projects/#{project.id}/packages/rubygems/api/v1/dependencies") }
+
+ subject { get(url, headers: headers) }
+
+ it_behaves_like 'an unimplemented route'
+ end
+end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 8fb0f8fc51a..3b84c812010 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -199,6 +199,14 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['allow_local_requests_from_hooks_and_services']).to eq(true)
end
+ it 'supports legacy asset_proxy_whitelist' do
+ put api("/application/settings", admin),
+ params: { asset_proxy_whitelist: ['example.com', '*.example.com'] }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['asset_proxy_allowlist']).to eq(['example.com', '*.example.com', 'localhost'])
+ end
+
it 'disables ability to switch to legacy storage' do
put api("/application/settings", admin),
params: { hashed_storage_enabled: false }
@@ -362,24 +370,24 @@ RSpec.describe API::Settings, 'Settings' do
asset_proxy_enabled: true,
asset_proxy_url: 'http://assets.example.com',
asset_proxy_secret_key: 'shared secret',
- asset_proxy_whitelist: ['example.com', '*.example.com']
+ asset_proxy_allowlist: ['example.com', '*.example.com']
}
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['asset_proxy_enabled']).to be(true)
expect(json_response['asset_proxy_url']).to eq('http://assets.example.com')
expect(json_response['asset_proxy_secret_key']).to be_nil
- expect(json_response['asset_proxy_whitelist']).to eq(['example.com', '*.example.com', 'localhost'])
+ expect(json_response['asset_proxy_allowlist']).to eq(['example.com', '*.example.com', 'localhost'])
end
- it 'allows a string for asset_proxy_whitelist' do
+ it 'allows a string for asset_proxy_allowlist' do
put api('/application/settings', admin),
params: {
- asset_proxy_whitelist: 'example.com, *.example.com'
+ asset_proxy_allowlist: 'example.com, *.example.com'
}
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['asset_proxy_whitelist']).to eq(['example.com', '*.example.com', 'localhost'])
+ expect(json_response['asset_proxy_allowlist']).to eq(['example.com', '*.example.com', 'localhost'])
end
end
diff --git a/spec/requests/api/suggestions_spec.rb b/spec/requests/api/suggestions_spec.rb
index 78a2688ac5e..7f53d379af5 100644
--- a/spec/requests/api/suggestions_spec.rb
+++ b/spec/requests/api/suggestions_spec.rb
@@ -65,6 +65,19 @@ RSpec.describe API::Suggestions do
end
end
+ context 'when a custom commit message is included' do
+ it 'renders an ok response and returns json content' do
+ project.add_maintainer(user)
+
+ message = "cool custom commit message!"
+
+ put api(url, user), params: { commit_message: message }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(project.repository.commit.message).to eq(message)
+ end
+ end
+
context 'when not able to apply patch' do
let(:url) { "/suggestions/#{unappliable_suggestion.id}/apply" }
@@ -113,9 +126,11 @@ RSpec.describe API::Suggestions do
let(:url) { "/suggestions/batch_apply" }
context 'when successfully applies multiple patches as a batch' do
- it 'renders an ok response and returns json content' do
+ before do
project.add_maintainer(user)
+ end
+ it 'renders an ok response and returns json content' do
put api(url, user), params: { ids: [suggestion.id, suggestion2.id] }
expect(response).to have_gitlab_http_status(:ok)
@@ -123,6 +138,16 @@ RSpec.describe API::Suggestions do
'appliable', 'applied',
'from_content', 'to_content'))
end
+
+ it 'provides a custom commit message' do
+ message = "cool custom commit message!"
+
+ put api(url, user), params: { ids: [suggestion.id, suggestion2.id],
+ commit_message: message }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(project.repository.commit.message).to eq(message)
+ end
end
context 'when not able to apply one or more of the patches' do
diff --git a/spec/requests/api/templates_spec.rb b/spec/requests/api/templates_spec.rb
index e1c5bfd82c4..adb37c62dc3 100644
--- a/spec/requests/api/templates_spec.rb
+++ b/spec/requests/api/templates_spec.rb
@@ -65,7 +65,9 @@ RSpec.describe API::Templates do
expect(json_response['nickname']).to be_nil
expect(json_response['popular']).to be true
expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/')
- expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT')
+ # This was dropped:
+ # https://github.com/github/choosealicense.com/commit/325806b42aa3d5b78e84120327ec877bc936dbdd#diff-66df8f1997786f7052d29010f2cbb4c66391d60d24ca624c356acc0ab986f139
+ expect(json_response['source_url']).to be_nil
expect(json_response['description']).to include('A short and simple permissive license with conditions')
expect(json_response['conditions']).to eq(%w[include-copyright])
expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use])
@@ -81,7 +83,7 @@ RSpec.describe API::Templates do
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(12)
+ expect(json_response.size).to eq(13)
expect(json_response.map { |l| l['key'] }).to include('agpl-3.0')
end
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index bfdb5458fd1..2cb3c8e9ab5 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe API::Terraform::State do
context 'with maintainer permissions' do
let(:current_user) { maintainer }
- it_behaves_like 'tracking unique hll events', :usage_data_p_terraform_state_api_unique_users do
+ it_behaves_like 'tracking unique hll events' do
let(:target_id) { 'p_terraform_state_api_unique_users' }
let(:expected_type) { instance_of(Integer) }
end
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index c51358bf659..55d17fabc9a 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -54,6 +54,15 @@ RSpec.describe API::Triggers do
expect(pipeline.builds.size).to eq(5)
end
+ it 'stores payload as a variable' do
+ post api("/projects/#{project.id}/trigger/pipeline"), params: options.merge(ref: 'master')
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(pipeline.variables.find { |v| v.key == 'TRIGGER_PAYLOAD' }.value).to eq(
+ "{\"ref\":\"master\",\"id\":\"#{project.id}\",\"variables\":{}}"
+ )
+ end
+
it 'returns bad request with no pipeline created if there\'s no commit for that ref' do
post api("/projects/#{project.id}/trigger/pipeline"), params: options.merge(ref: 'other-branch')
@@ -84,7 +93,7 @@ RSpec.describe API::Triggers do
post api("/projects/#{project.id}/trigger/pipeline"), params: options.merge(variables: variables, ref: 'master')
expect(response).to have_gitlab_http_status(:created)
- expect(pipeline.variables.map { |v| { v.key => v.value } }.last).to eq(variables)
+ expect(pipeline.variables.find { |v| v.key == 'TRIGGER_KEY' }.value).to eq('TRIGGER_VALUE')
end
end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 94fba451860..d70a8bd692d 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -652,6 +652,34 @@ RSpec.describe API::Users do
expect(response).to match_response_schema('public_api/v4/user/basic')
expect(json_response.keys).not_to include 'created_at'
end
+
+ it "returns the `followers` field for public users" do
+ get api("/users/#{user.id}")
+
+ expect(response).to match_response_schema('public_api/v4/user/basic')
+ expect(json_response.keys).to include 'followers'
+ end
+
+ it "does not return the `followers` field for private users" do
+ get api("/users/#{private_user.id}")
+
+ expect(response).to match_response_schema('public_api/v4/user/basic')
+ expect(json_response.keys).not_to include 'followers'
+ end
+
+ it "returns the `following` field for public users" do
+ get api("/users/#{user.id}")
+
+ expect(response).to match_response_schema('public_api/v4/user/basic')
+ expect(json_response.keys).to include 'following'
+ end
+
+ it "does not return the `following` field for private users" do
+ get api("/users/#{private_user.id}")
+
+ expect(response).to match_response_schema('public_api/v4/user/basic')
+ expect(json_response.keys).not_to include 'following'
+ end
end
it "returns a 404 error if user id not found" do
@@ -688,6 +716,128 @@ RSpec.describe API::Users do
end
end
+ describe 'POST /users/:id/follow' do
+ let(:followee) { create(:user) }
+
+ context 'on an unfollowed user' do
+ it 'follows the user' do
+ post api("/users/#{followee.id}/follow", user)
+
+ expect(user.followees).to contain_exactly(followee)
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+
+ context 'on a followed user' do
+ before do
+ user.follow(followee)
+ end
+
+ it 'does not change following' do
+ post api("/users/#{followee.id}/follow", user)
+
+ expect(user.followees).to contain_exactly(followee)
+ expect(response).to have_gitlab_http_status(:not_modified)
+ end
+ end
+ end
+
+ describe 'POST /users/:id/unfollow' do
+ let(:followee) { create(:user) }
+
+ context 'on a followed user' do
+ before do
+ user.follow(followee)
+ end
+
+ it 'unfollow the user' do
+ post api("/users/#{followee.id}/unfollow", user)
+
+ expect(user.followees).to be_empty
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+
+ context 'on an unfollowed user' do
+ it 'does not change following' do
+ post api("/users/#{followee.id}/unfollow", user)
+
+ expect(user.followees).to be_empty
+ expect(response).to have_gitlab_http_status(:not_modified)
+ end
+ end
+ end
+
+ describe 'GET /users/:id/followers' do
+ let(:follower) { create(:user) }
+
+ context 'user has followers' do
+ it 'lists followers' do
+ follower.follow(user)
+
+ get api("/users/#{user.id}/followers", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ end
+
+ it 'do not lists followers if profile is private' do
+ follower.follow(private_user)
+
+ get api("/users/#{private_user.id}/followers", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
+ end
+
+ context 'user does not have any follower' do
+ it 'does list nothing' do
+ get api("/users/#{user.id}/followers", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_empty
+ end
+ end
+ end
+
+ describe 'GET /users/:id/following' do
+ let(:followee) { create(:user) }
+
+ context 'user has followers' do
+ it 'lists following user' do
+ user.follow(followee)
+
+ get api("/users/#{user.id}/following", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ end
+
+ it 'do not lists following user if profile is private' do
+ user.follow(private_user)
+
+ get api("/users/#{private_user.id}/following", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
+ end
+
+ context 'user does not have any follower' do
+ it 'does list nothing' do
+ get api("/users/#{user.id}/following", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_empty
+ end
+ end
+ end
+
describe "POST /users" do
it "creates user" do
expect do
@@ -2565,7 +2715,7 @@ RSpec.describe API::Users do
it 'does not approve a deactivated user' do
expect { approve }.not_to change { deactivated_user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@@ -2585,7 +2735,7 @@ RSpec.describe API::Users do
it 'returns 201' do
expect { approve }.not_to change { user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@@ -2595,7 +2745,7 @@ RSpec.describe API::Users do
it 'returns 403' do
expect { approve }.not_to change { blocked_user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@@ -2605,7 +2755,7 @@ RSpec.describe API::Users do
it 'returns 403' do
expect { approve }.not_to change { ldap_blocked_user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@@ -2866,6 +3016,47 @@ RSpec.describe API::Users do
expect(response).to have_gitlab_http_status(:success)
expect(user.reload.status).to be_nil
end
+
+ context 'when clear_status_after is given' do
+ it 'sets the clear_status_at column' do
+ freeze_time do
+ expected_clear_status_at = 3.hours.from_now
+
+ put api('/user/status', user), params: { emoji: 'smirk', message: 'hello world', clear_status_after: '3_hours' }
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(user.status.reload.clear_status_at).to be_within(1.minute).of(expected_clear_status_at)
+ expect(Time.parse(json_response["clear_status_at"])).to be_within(1.minute).of(expected_clear_status_at)
+ end
+ end
+
+ it 'unsets the clear_status_at column' do
+ user.create_status!(clear_status_at: 5.hours.ago)
+
+ put api('/user/status', user), params: { emoji: 'smirk', message: 'hello world', clear_status_after: nil }
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(user.status.reload.clear_status_at).to be_nil
+ end
+
+ it 'raises error when unknown status value is given' do
+ put api('/user/status', user), params: { emoji: 'smirk', message: 'hello world', clear_status_after: 'wrong' }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ context 'when the clear_status_with_quick_options feature flag is disabled' do
+ before do
+ stub_feature_flags(clear_status_with_quick_options: false)
+ end
+
+ it 'does not persist clear_status_at' do
+ put api('/user/status', user), params: { emoji: 'smirk', message: 'hello world', clear_status_after: '3_hours' }
+
+ expect(user.status.reload.clear_status_at).to be_nil
+ end
+ end
+ end
end
describe 'POST /users/:user_id/personal_access_tokens' do
diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb
index a0a0f66c8d1..7abbaf4f9ec 100644
--- a/spec/requests/api/version_spec.rb
+++ b/spec/requests/api/version_spec.rb
@@ -33,6 +33,12 @@ RSpec.describe API::Version do
expect_version
end
+
+ it 'returns "200" response on head requests' do
+ head api('/version', personal_access_token: personal_access_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'with read_user scope' do
@@ -43,6 +49,12 @@ RSpec.describe API::Version do
expect_version
end
+
+ it 'returns "200" response on head requests' do
+ head api('/version', personal_access_token: personal_access_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'with neither api nor read_user scope' do
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 1ee3e36be8b..a1e28c18769 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -382,6 +382,14 @@ RSpec.describe 'Git HTTP requests' do
end
end
end
+
+ context 'but the service parameter is missing' do
+ it 'rejects clones with 403 Forbidden' do
+ get("/#{path}/info/refs", headers: auth_env(*env.values_at(:user, :password), nil))
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
end
context 'and not a member of the team' do
@@ -409,6 +417,14 @@ RSpec.describe 'Git HTTP requests' do
it_behaves_like 'pushes are allowed'
end
+
+ context 'but the service parameter is missing' do
+ it 'rejects clones with 401 Unauthorized' do
+ get("/#{path}/info/refs")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
end
end
diff --git a/spec/requests/groups/email_campaigns_controller_spec.rb b/spec/requests/groups/email_campaigns_controller_spec.rb
new file mode 100644
index 00000000000..930e645f6c0
--- /dev/null
+++ b/spec/requests/groups/email_campaigns_controller_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::EmailCampaignsController do
+ include InProductMarketingHelper
+ using RSpec::Parameterized::TableSyntax
+
+ describe 'GET #index', :snowplow do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:user) { create(:user) }
+ let(:track) { 'create' }
+ let(:series) { '0' }
+ let(:schema) { described_class::EMAIL_CAMPAIGNS_SCHEMA_URL }
+ let(:data) do
+ {
+ namespace_id: group.id,
+ track: track.to_sym,
+ series: series.to_i,
+ subject_line: subject_line(track.to_sym, series.to_i)
+ }
+ end
+
+ before do
+ sign_in(user)
+ group.add_developer(user)
+ allow(Gitlab::Tracking).to receive(:self_describing_event)
+ end
+
+ subject do
+ get group_email_campaigns_url(group, track: track, series: series)
+ response
+ end
+
+ shared_examples 'track and redirect' do
+ it do
+ is_expected.to track_self_describing_event(schema, data)
+ is_expected.to have_gitlab_http_status(:redirect)
+ end
+ end
+
+ shared_examples 'no track and 404' do
+ it do
+ is_expected.not_to track_self_describing_event
+ is_expected.to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ describe 'track parameter' do
+ context 'when valid' do
+ where(track: Namespaces::InProductMarketingEmailsService::TRACKS.keys)
+
+ with_them do
+ it_behaves_like 'track and redirect'
+ end
+ end
+
+ context 'when invalid' do
+ where(track: [nil, 'xxxx'])
+
+ with_them do
+ it_behaves_like 'no track and 404'
+ end
+ end
+ end
+
+ describe 'series parameter' do
+ context 'when valid' do
+ where(series: (0..Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.length - 1).to_a)
+
+ with_them do
+ it_behaves_like 'track and redirect'
+ end
+ end
+
+ context 'when invalid' do
+ where(series: [-1, nil, Namespaces::InProductMarketingEmailsService::INTERVAL_DAYS.length])
+
+ with_them do
+ it_behaves_like 'no track and 404'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/health_controller_spec.rb b/spec/requests/health_controller_spec.rb
index 592a57bc637..f70faf5bb9c 100644
--- a/spec/requests/health_controller_spec.rb
+++ b/spec/requests/health_controller_spec.rb
@@ -77,91 +77,129 @@ RSpec.describe HealthController do
shared_context 'endpoint responding with readiness data' do
context 'when requesting instance-checks' do
- it 'responds with readiness checks data' do
- expect(Gitlab::HealthChecks::MasterCheck).to receive(:check) { true }
-
- subject
-
- expect(json_response).to include({ 'status' => 'ok' })
- expect(json_response['master_check']).to contain_exactly({ 'status' => 'ok' })
- end
+ context 'when Puma runs in Clustered mode' do
+ before do
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(true)
+ end
- it 'responds with readiness checks data when a failure happens' do
- expect(Gitlab::HealthChecks::MasterCheck).to receive(:check) { false }
+ it 'responds with readiness checks data' do
+ expect(Gitlab::HealthChecks::MasterCheck).to receive(:check) { true }
- subject
+ subject
- expect(json_response).to include({ 'status' => 'failed' })
- expect(json_response['master_check']).to contain_exactly(
- { 'status' => 'failed', 'message' => 'unexpected Master check result: false' })
+ expect(json_response).to include({ 'status' => 'ok' })
+ expect(json_response['master_check']).to contain_exactly({ 'status' => 'ok' })
+ end
- expect(response).to have_gitlab_http_status(:service_unavailable)
- expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
- end
- end
+ it 'responds with readiness checks data when a failure happens' do
+ expect(Gitlab::HealthChecks::MasterCheck).to receive(:check) { false }
- context 'when requesting all checks' do
- before do
- params.merge!(all: true)
- end
+ subject
- it 'responds with readiness checks data' do
- subject
+ expect(json_response).to include({ 'status' => 'failed' })
+ expect(json_response['master_check']).to contain_exactly(
+ { 'status' => 'failed', 'message' => 'unexpected Master check result: false' })
- expect(json_response['db_check']).to contain_exactly({ 'status' => 'ok' })
- expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
- expect(json_response['queues_check']).to contain_exactly({ 'status' => 'ok' })
- expect(json_response['shared_state_check']).to contain_exactly({ 'status' => 'ok' })
- expect(json_response['gitaly_check']).to contain_exactly(
- { 'status' => 'ok', 'labels' => { 'shard' => 'default' } })
+ expect(response).to have_gitlab_http_status(:service_unavailable)
+ expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
+ end
end
- it 'responds with readiness checks data when a failure happens' do
- allow(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_return(
- Gitlab::HealthChecks::Result.new('redis_check', false, "check error"))
+ context 'when Puma runs in Single mode' do
+ before do
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(false)
+ end
- subject
+ it 'does not invoke MasterCheck, succeedes' do
+ expect(Gitlab::HealthChecks::MasterCheck).not_to receive(:check) { true }
- expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
- expect(json_response['redis_check']).to contain_exactly(
- { 'status' => 'failed', 'message' => 'check error' })
+ subject
- expect(response).to have_gitlab_http_status(:service_unavailable)
- expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
+ expect(json_response).to eq('status' => 'ok')
+ end
end
+ end
- context 'when DB is not accessible and connection raises an exception' do
+ context 'when requesting all checks' do
+ shared_context 'endpoint responding with readiness data for all checks' do
before do
- expect(Gitlab::HealthChecks::DbCheck)
- .to receive(:readiness)
- .and_raise(PG::ConnectionBad, 'could not connect to server')
+ params.merge!(all: true)
end
- it 'responds with 500 including the exception info' do
+ it 'responds with readiness checks data' do
subject
- expect(response).to have_gitlab_http_status(:internal_server_error)
+ expect(json_response['db_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['queues_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['shared_state_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['gitaly_check']).to contain_exactly(
+ { 'status' => 'ok', 'labels' => { 'shard' => 'default' } })
+ end
+
+ it 'responds with readiness checks data when a failure happens' do
+ allow(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_return(
+ Gitlab::HealthChecks::Result.new('redis_check', false, "check error"))
+
+ subject
+
+ expect(json_response['cache_check']).to contain_exactly({ 'status' => 'ok' })
+ expect(json_response['redis_check']).to contain_exactly(
+ { 'status' => 'failed', 'message' => 'check error' })
+
+ expect(response).to have_gitlab_http_status(:service_unavailable)
expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
- expect(json_response).to eq(
- { 'status' => 'failed', 'message' => 'PG::ConnectionBad : could not connect to server' })
+ end
+
+ context 'when DB is not accessible and connection raises an exception' do
+ before do
+ expect(Gitlab::HealthChecks::DbCheck)
+ .to receive(:readiness)
+ .and_raise(PG::ConnectionBad, 'could not connect to server')
+ end
+
+ it 'responds with 500 including the exception info' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:internal_server_error)
+ expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
+ expect(json_response).to eq(
+ { 'status' => 'failed', 'message' => 'PG::ConnectionBad : could not connect to server' })
+ end
+ end
+
+ context 'when any exception happens during the probing' do
+ before do
+ expect(Gitlab::HealthChecks::Redis::RedisCheck)
+ .to receive(:readiness)
+ .and_raise(::Redis::CannotConnectError, 'Redis down')
+ end
+
+ it 'responds with 500 including the exception info' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:internal_server_error)
+ expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
+ expect(json_response).to eq(
+ { 'status' => 'failed', 'message' => 'Redis::CannotConnectError : Redis down' })
+ end
end
end
- context 'when any exception happens during the probing' do
+ context 'when Puma runs in Clustered mode' do
before do
- expect(Gitlab::HealthChecks::Redis::RedisCheck)
- .to receive(:readiness)
- .and_raise(::Redis::CannotConnectError, 'Redis down')
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(true)
end
- it 'responds with 500 including the exception info' do
- subject
+ it_behaves_like 'endpoint responding with readiness data for all checks'
+ end
- expect(response).to have_gitlab_http_status(:internal_server_error)
- expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
- expect(json_response).to eq(
- { 'status' => 'failed', 'message' => 'Redis::CannotConnectError : Redis down' })
+ context 'when Puma runs in Single mode' do
+ before do
+ allow(Gitlab::Runtime).to receive(:puma_in_clustered_mode?).and_return(false)
end
+
+ it_behaves_like 'endpoint responding with readiness data for all checks'
end
end
end
diff --git a/spec/requests/import/gitlab_groups_controller_spec.rb b/spec/requests/import/gitlab_groups_controller_spec.rb
index 51f1363cf1c..c65caf2ebf0 100644
--- a/spec/requests/import/gitlab_groups_controller_spec.rb
+++ b/spec/requests/import/gitlab_groups_controller_spec.rb
@@ -5,12 +5,10 @@ require 'spec_helper'
RSpec.describe Import::GitlabGroupsController do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let_it_be(:user) { create(:user) }
let(:import_path) { "#{Dir.tmpdir}/gitlab_groups_controller_spec" }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) do
- { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token }
- end
before do
allow_next_instance_of(Gitlab::ImportExport) do |import_export|
diff --git a/spec/requests/import/gitlab_projects_controller_spec.rb b/spec/requests/import/gitlab_projects_controller_spec.rb
index d7d4de21a33..58843a7fec4 100644
--- a/spec/requests/import/gitlab_projects_controller_spec.rb
+++ b/spec/requests/import/gitlab_projects_controller_spec.rb
@@ -5,8 +5,7 @@ require 'spec_helper'
RSpec.describe Import::GitlabProjectsController do
include WorkhorseHelpers
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
let_it_be(:namespace) { create(:namespace) }
let_it_be(:user) { namespace.owner }
diff --git a/spec/requests/oauth/tokens_controller_spec.rb b/spec/requests/oauth/tokens_controller_spec.rb
new file mode 100644
index 00000000000..c3cdae2cd21
--- /dev/null
+++ b/spec/requests/oauth/tokens_controller_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Oauth::TokensController do
+ it 'allows cross-origin POST requests' do
+ post '/oauth/token', headers: { 'Origin' => 'http://notgitlab.com' }
+
+ expect(response.headers['Access-Control-Allow-Origin']).to eq '*'
+ expect(response.headers['Access-Control-Allow-Methods']).to eq 'POST'
+ expect(response.headers['Access-Control-Allow-Headers']).to be_nil
+ expect(response.headers['Access-Control-Allow-Credentials']).to be_nil
+ end
+end
diff --git a/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb b/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb
new file mode 100644
index 00000000000..5d2f3e98bb4
--- /dev/null
+++ b/spec/requests/projects/ci/promeheus_metrics/histograms_controller_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Projects::Ci::PrometheusMetrics::HistogramsController' do
+ let_it_be(:project) { create(:project, :public) }
+
+ describe 'POST /*namespace_id/:project_id/-/ci/prometheus_metrics/histograms' do
+ context 'with known histograms' do
+ it 'returns 201 Created' do
+ post histograms_route(histograms: [
+ { name: :pipeline_graph_link_calculation_duration_seconds, value: 1 },
+ { name: :pipeline_graph_links_total, value: 10 }
+ ])
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+ end
+
+ context 'with unknown histograms' do
+ it 'returns 404 Not Found' do
+ post histograms_route(histograms: [{ name: :chunky_bacon, value: 5 }])
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with the feature flag disabled' do
+ before do
+ stub_feature_flags(ci_accept_frontend_prometheus_metrics: false)
+ end
+
+ it 'returns 202 Accepted' do
+ post histograms_route(histograms: [
+ { name: :pipeline_graph_link_calculation_duration_seconds, value: 1 }
+ ])
+
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+ end
+ end
+
+ def histograms_route(params = {})
+ namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: project.namespace, project_id: project, **params)
+ end
+end
diff --git a/spec/requests/projects/noteable_notes_spec.rb b/spec/requests/projects/noteable_notes_spec.rb
index 2bf1ffb2edc..5ae2aadaa84 100644
--- a/spec/requests/projects/noteable_notes_spec.rb
+++ b/spec/requests/projects/noteable_notes_spec.rb
@@ -18,9 +18,7 @@ RSpec.describe 'Project noteable notes' do
login_as(user)
end
- it 'does not set a Gitlab::EtagCaching ETag if there is a note' do
- create(:note_on_merge_request, noteable: merge_request, project: merge_request.project)
-
+ it 'does not set a Gitlab::EtagCaching ETag' do
get notes_path
expect(response).to have_gitlab_http_status(:ok)
@@ -29,12 +27,5 @@ RSpec.describe 'Project noteable notes' do
# interfere with notes pagination
expect(response_etag).not_to eq(stored_etag)
end
-
- it 'sets a Gitlab::EtagCaching ETag if there is no note' do
- get notes_path
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response_etag).to eq(stored_etag)
- end
end
end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 34f34c0b850..1bb260b5ea1 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Rack Attack global throttles' do
+RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_caching do
include RackAttackSpecHelpers
let(:settings) { Gitlab::CurrentSettings.current_application_settings }
@@ -149,14 +149,14 @@ RSpec.describe 'Rack Attack global throttles' do
expect(response).to have_gitlab_http_status(:ok)
end
- arguments = {
+ arguments = a_hash_including({
message: 'Rack_Attack',
env: :throttle,
remote_ip: '127.0.0.1',
request_method: 'GET',
path: '/users/sign_in',
matched: 'throttle_unauthenticated'
- }
+ })
expect(Gitlab::AuthLogger).to receive(:error).with(arguments)
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index b224ef87229..f3ddcbef1c2 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -268,6 +268,14 @@ RSpec.describe UsersController do
end
it_behaves_like 'renders all public keys'
+
+ context 'when public visibility is restricted' do
+ before do
+ stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
+ end
+
+ it_behaves_like 'renders all public keys'
+ end
end
end
end
diff --git a/spec/requests/whats_new_controller_spec.rb b/spec/requests/whats_new_controller_spec.rb
index 8005d38dbb0..ba7b5d4c000 100644
--- a/spec/requests/whats_new_controller_spec.rb
+++ b/spec/requests/whats_new_controller_spec.rb
@@ -2,64 +2,48 @@
require 'spec_helper'
-RSpec.describe WhatsNewController do
+RSpec.describe WhatsNewController, :clean_gitlab_redis_cache do
+ after do
+ ReleaseHighlight.instance_variable_set(:@file_paths, nil)
+ end
+
describe 'whats_new_path' do
let(:item) { double(:item) }
let(:highlights) { double(:highlight, items: [item], map: [item].map, next_page: 2) }
- context 'with whats_new_drawer feature enabled' do
- before do
- stub_feature_flags(whats_new_drawer: true)
- end
-
- context 'with no page param' do
- it 'responds with paginated data and headers' do
- allow(ReleaseHighlight).to receive(:paginated).with(page: 1).and_return(highlights)
- allow(Gitlab::WhatsNew::ItemPresenter).to receive(:present).with(item).and_return(item)
+ context 'with no page param' do
+ it 'responds with paginated data and headers' do
+ allow(ReleaseHighlight).to receive(:paginated).with(page: 1).and_return(highlights)
- get whats_new_path, xhr: true
+ get whats_new_path, xhr: true
- expect(response.body).to eq(highlights.items.to_json)
- expect(response.headers['X-Next-Page']).to eq(2)
- end
+ expect(response.body).to eq(highlights.items.to_json)
+ expect(response.headers['X-Next-Page']).to eq(2)
end
+ end
- context 'with page param' do
- it 'passes the page parameter' do
- expect(ReleaseHighlight).to receive(:paginated).with(page: 2).and_call_original
-
- get whats_new_path(page: 2), xhr: true
- end
-
- it 'returns a 404 if page param is negative' do
- get whats_new_path(page: -1), xhr: true
+ context 'with page param' do
+ it 'passes the page parameter' do
+ expect(ReleaseHighlight).to receive(:paginated).with(page: 2).and_call_original
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ get whats_new_path(page: 2), xhr: true
end
- context 'with version param' do
- it 'returns items without pagination headers' do
- allow(ReleaseHighlight).to receive(:for_version).with(version: '42').and_return(highlights)
- allow(Gitlab::WhatsNew::ItemPresenter).to receive(:present).with(item).and_return(item)
-
- get whats_new_path(version: 42), xhr: true
+ it 'returns a 404 if page param is negative' do
+ get whats_new_path(page: -1), xhr: true
- expect(response.body).to eq(highlights.items.to_json)
- expect(response.headers['X-Next-Page']).to be_nil
- end
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
- context 'with whats_new_drawer feature disabled' do
- before do
- stub_feature_flags(whats_new_drawer: false)
- end
+ context 'with version param' do
+ it 'returns items without pagination headers' do
+ allow(ReleaseHighlight).to receive(:for_version).with(version: '42').and_return(highlights)
- it 'returns a 404' do
- get whats_new_path, xhr: true
+ get whats_new_path(version: 42), xhr: true
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response.body).to eq(highlights.items.to_json)
+ expect(response.headers['X-Next-Page']).to be_nil
end
end
end
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index 9374df0c4a2..8c36d7d4668 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -141,13 +141,6 @@ RSpec.describe Admin::DevOpsReportController, "routing" do
end
end
-# admin_cohorts GET /admin/cohorts(.:format) admin/cohorst#index
-RSpec.describe Admin::CohortsController, "routing" do
- it "to #index" do
- expect(get("/admin/cohorts")).to route_to('admin/cohorts#index')
- end
-end
-
RSpec.describe Admin::GroupsController, "routing" do
let(:name) { 'complex.group-namegit' }
diff --git a/spec/routing/projects/security/configuration_controller_routing_spec.rb b/spec/routing/projects/security/configuration_controller_routing_spec.rb
new file mode 100644
index 00000000000..c2b10a49dea
--- /dev/null
+++ b/spec/routing/projects/security/configuration_controller_routing_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Security::ConfigurationController, 'routing' do
+ let(:base_params) { { namespace_id: 'gitlab', project_id: 'gitlabhq' } }
+
+ before do
+ allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq', any_args).and_return(true)
+ end
+
+ it 'routes to #show' do
+ expect(get('/gitlab/gitlabhq/-/security/configuration')).to route_to('projects/security/configuration#show', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ end
+end
diff --git a/spec/rubocop/code_reuse_helpers_spec.rb b/spec/rubocop/code_reuse_helpers_spec.rb
index 574a4a85a34..4c3dd8f8167 100644
--- a/spec/rubocop/code_reuse_helpers_spec.rb
+++ b/spec/rubocop/code_reuse_helpers_spec.rb
@@ -6,7 +6,7 @@ require 'parser/current'
require_relative '../../rubocop/code_reuse_helpers'
RSpec.describe RuboCop::CodeReuseHelpers do
- def parse_source(source, path = 'foo.rb')
+ def build_and_parse_source(source, path = 'foo.rb')
buffer = Parser::Source::Buffer.new(path)
buffer.source = source
@@ -24,13 +24,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#send_to_constant?' do
it 'returns true when sending to a constant' do
- node = parse_source('Foo.bar')
+ node = build_and_parse_source('Foo.bar')
expect(cop.send_to_constant?(node)).to eq(true)
end
it 'returns false when sending to something other than a constant' do
- node = parse_source('10')
+ node = build_and_parse_source('10')
expect(cop.send_to_constant?(node)).to eq(false)
end
@@ -38,13 +38,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#send_receiver_name_ends_with?' do
it 'returns true when the receiver ends with a suffix' do
- node = parse_source('FooFinder.new')
+ node = build_and_parse_source('FooFinder.new')
expect(cop.send_receiver_name_ends_with?(node, 'Finder')).to eq(true)
end
it 'returns false when the receiver is the same as a suffix' do
- node = parse_source('Finder.new')
+ node = build_and_parse_source('Finder.new')
expect(cop.send_receiver_name_ends_with?(node, 'Finder')).to eq(false)
end
@@ -52,7 +52,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#file_path_for_node' do
it 'returns the file path of a node' do
- node = parse_source('10')
+ node = build_and_parse_source('10')
path = cop.file_path_for_node(node)
expect(path).to eq('foo.rb')
@@ -61,7 +61,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#name_of_constant' do
it 'returns the name of a constant' do
- node = parse_source('Foo')
+ node = build_and_parse_source('Foo')
expect(cop.name_of_constant(node)).to eq(:Foo)
end
@@ -69,13 +69,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_finder?' do
it 'returns true for a node in the finders directory' do
- node = parse_source('10', rails_root_join('app', 'finders', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'finders', 'foo.rb'))
expect(cop.in_finder?(node)).to eq(true)
end
it 'returns false for a node outside the finders directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_finder?(node)).to eq(false)
end
@@ -83,13 +83,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_model?' do
it 'returns true for a node in the models directory' do
- node = parse_source('10', rails_root_join('app', 'models', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'models', 'foo.rb'))
expect(cop.in_model?(node)).to eq(true)
end
it 'returns false for a node outside the models directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_model?(node)).to eq(false)
end
@@ -97,13 +97,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_service_class?' do
it 'returns true for a node in the services directory' do
- node = parse_source('10', rails_root_join('app', 'services', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'services', 'foo.rb'))
expect(cop.in_service_class?(node)).to eq(true)
end
it 'returns false for a node outside the services directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_service_class?(node)).to eq(false)
end
@@ -111,13 +111,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_presenter?' do
it 'returns true for a node in the presenters directory' do
- node = parse_source('10', rails_root_join('app', 'presenters', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'presenters', 'foo.rb'))
expect(cop.in_presenter?(node)).to eq(true)
end
it 'returns false for a node outside the presenters directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_presenter?(node)).to eq(false)
end
@@ -125,13 +125,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_serializer?' do
it 'returns true for a node in the serializers directory' do
- node = parse_source('10', rails_root_join('app', 'serializers', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'serializers', 'foo.rb'))
expect(cop.in_serializer?(node)).to eq(true)
end
it 'returns false for a node outside the serializers directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_serializer?(node)).to eq(false)
end
@@ -139,13 +139,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_worker?' do
it 'returns true for a node in the workers directory' do
- node = parse_source('10', rails_root_join('app', 'workers', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'workers', 'foo.rb'))
expect(cop.in_worker?(node)).to eq(true)
end
it 'returns false for a node outside the workers directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_worker?(node)).to eq(false)
end
@@ -153,13 +153,13 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_api?' do
it 'returns true for a node in the API directory' do
- node = parse_source('10', rails_root_join('lib', 'api', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('lib', 'api', 'foo.rb'))
expect(cop.in_api?(node)).to eq(true)
end
it 'returns false for a node outside the API directory' do
- node = parse_source('10', rails_root_join('lib', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('lib', 'foo', 'foo.rb'))
expect(cop.in_api?(node)).to eq(false)
end
@@ -167,21 +167,21 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#in_directory?' do
it 'returns true for a directory in the CE app/ directory' do
- node = parse_source('10', rails_root_join('app', 'models', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'models', 'foo.rb'))
expect(cop.in_directory?(node, 'models')).to eq(true)
end
it 'returns true for a directory in the EE app/ directory' do
node =
- parse_source('10', rails_root_join('ee', 'app', 'models', 'foo.rb'))
+ build_and_parse_source('10', rails_root_join('ee', 'app', 'models', 'foo.rb'))
expect(cop.in_directory?(node, 'models')).to eq(true)
end
it 'returns false for a directory in the lib/ directory' do
node =
- parse_source('10', rails_root_join('lib', 'models', 'foo.rb'))
+ build_and_parse_source('10', rails_root_join('lib', 'models', 'foo.rb'))
expect(cop.in_directory?(node, 'models')).to eq(false)
end
@@ -189,7 +189,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#name_of_receiver' do
it 'returns the name of a send receiver' do
- node = parse_source('Foo.bar')
+ node = build_and_parse_source('Foo.bar')
expect(cop.name_of_receiver(node)).to eq('Foo')
end
@@ -197,7 +197,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#each_class_method' do
it 'yields every class method to the supplied block' do
- node = parse_source(<<~RUBY)
+ node = build_and_parse_source(<<~RUBY)
class Foo
class << self
def first
@@ -220,7 +220,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#each_send_node' do
it 'yields every send node to the supplied block' do
- node = parse_source("foo\nbar")
+ node = build_and_parse_source("foo\nbar")
nodes = cop.each_send_node(node).to_a
expect(nodes.length).to eq(2)
@@ -231,7 +231,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
describe '#disallow_send_to' do
it 'disallows sending a message to a constant' do
- def_node = parse_source(<<~RUBY)
+ def_node = build_and_parse_source(<<~RUBY)
def foo
FooFinder.new
end
diff --git a/spec/rubocop/cop/active_record_association_reload_spec.rb b/spec/rubocop/cop/active_record_association_reload_spec.rb
index 8dbe6daeeca..f28c4e60f3c 100644
--- a/spec/rubocop/cop/active_record_association_reload_spec.rb
+++ b/spec/rubocop/cop/active_record_association_reload_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../rubocop/cop/active_record_association_reload'
RSpec.describe RuboCop::Cop::ActiveRecordAssociationReload do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when using ActiveRecord::Base' do
diff --git a/spec/rubocop/cop/api/base_spec.rb b/spec/rubocop/cop/api/base_spec.rb
index de05ab93874..ec646b9991b 100644
--- a/spec/rubocop/cop/api/base_spec.rb
+++ b/spec/rubocop/cop/api/base_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/api/base'
RSpec.describe RuboCop::Cop::API::Base do
- include CopHelper
-
subject(:cop) { described_class.new }
let(:corrected) do
@@ -17,7 +14,7 @@ RSpec.describe RuboCop::Cop::API::Base do
CORRECTED
end
- ['Grape::API', '::Grape::API', 'Grape::API::Instance', '::Grape::API::Instance'].each do |offense|
+ %w[Grape::API ::Grape::API Grape::API::Instance ::Grape::API::Instance].each do |offense|
it "adds an offense when inheriting from #{offense}" do
expect_offense(<<~CODE)
class SomeAPI < #{offense}
diff --git a/spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb b/spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb
index c7bb8255398..b50866b54b3 100644
--- a/spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb
+++ b/spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb
@@ -5,36 +5,38 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/api/grape_array_missing_coerce'
RSpec.describe RuboCop::Cop::API::GrapeArrayMissingCoerce do
- include CopHelper
+ let(:msg) do
+ "This Grape parameter defines an Array but is missing a coerce_with definition. " \
+ "For more details, see " \
+ "https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions"
+ end
subject(:cop) { described_class.new }
it 'adds an offense with a required parameter' do
- inspect_source(<<~CODE)
+ expect_offense(<<~TYPE)
class SomeAPI < Grape::API::Instance
params do
requires :values, type: Array[String]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
end
end
- CODE
-
- expect(cop.offenses.size).to eq(1)
+ TYPE
end
it 'adds an offense with an optional parameter' do
- inspect_source(<<~CODE)
+ expect_offense(<<~TYPE)
class SomeAPI < Grape::API::Instance
params do
optional :values, type: Array[String]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
end
end
- CODE
-
- expect(cop.offenses.size).to eq(1)
+ TYPE
end
it 'does not add an offense' do
- inspect_source(<<~CODE)
+ expect_no_offenses(<<~CODE)
class SomeAPI < Grape::API::Instance
params do
requires :values, type: Array[String], coerce_with: ->(val) { val.split(',').map(&:strip) }
@@ -44,19 +46,15 @@ RSpec.describe RuboCop::Cop::API::GrapeArrayMissingCoerce do
end
end
CODE
-
- expect(cop.offenses.size).to be_zero
end
it 'does not add an offense for unrelated classes' do
- inspect_source(<<~CODE)
+ expect_no_offenses(<<~CODE)
class SomeClass
params do
requires :values, type: Array[String]
end
end
CODE
-
- expect(cop.offenses.size).to be_zero
end
end
diff --git a/spec/rubocop/cop/avoid_becomes_spec.rb b/spec/rubocop/cop/avoid_becomes_spec.rb
index 07cf374faf5..401c694f373 100644
--- a/spec/rubocop/cop/avoid_becomes_spec.rb
+++ b/spec/rubocop/cop/avoid_becomes_spec.rb
@@ -2,33 +2,31 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/avoid_becomes'
RSpec.describe RuboCop::Cop::AvoidBecomes do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of becomes with a constant parameter' do
- inspect_source('foo.becomes(Project)')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ foo.becomes(Project)
+ ^^^^^^^^^^^^^^^^^^^^ Avoid the use of becomes(SomeConstant), [...]
+ CODE
end
it 'flags the use of becomes with a namespaced constant parameter' do
- inspect_source('foo.becomes(Namespace::Group)')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ foo.becomes(Namespace::Group)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid the use of becomes(SomeConstant), [...]
+ CODE
end
it 'flags the use of becomes with a dynamic parameter' do
- inspect_source(<<~RUBY)
- model = Namespace
- project = Project.first
- project.becomes(model)
- RUBY
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ model = Namespace
+ project = Project.first
+ project.becomes(model)
+ ^^^^^^^^^^^^^^^^^^^^^^ Avoid the use of becomes(SomeConstant), [...]
+ CODE
end
end
diff --git a/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb b/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
index 3c3aa5b7b5c..ac59d36db3f 100644
--- a/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
+++ b/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../rubocop/cop/avoid_break_from_strong_memoize'
RSpec.describe RuboCop::Cop::AvoidBreakFromStrongMemoize do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags violation for break inside strong_memoize' do
@@ -56,7 +54,7 @@ RSpec.describe RuboCop::Cop::AvoidBreakFromStrongMemoize do
call do
strong_memoize(:result) do
break if something
-
+ ^^^^^ Do not use break inside strong_memoize, use next instead.
do_an_heavy_calculation
end
end
@@ -65,7 +63,7 @@ RSpec.describe RuboCop::Cop::AvoidBreakFromStrongMemoize do
expect(instance).to receive(:add_offense).once
end
- inspect_source(source)
+ expect_offense(source)
end
it "doesn't check when block is empty" do
diff --git a/spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb b/spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb
index 1e1fe851840..460a0b13458 100644
--- a/spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb
+++ b/spec/rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers_spec.rb
@@ -2,18 +2,15 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers'
RSpec.describe RuboCop::Cop::AvoidKeywordArgumentsInSidekiqWorkers do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags violation for keyword arguments usage in perform method signature' do
expect_offense(<<~RUBY)
def perform(id:)
- ^^^^^^^^^^^^^^^^ Do not use keyword arguments in Sidekiq workers. For details, check https://github.com/mperham/sidekiq/issues/2372
+ ^^^^^^^^^^^^^^^^ Do not use keyword arguments in Sidekiq workers. For details, [...]
end
RUBY
end
@@ -21,7 +18,7 @@ RSpec.describe RuboCop::Cop::AvoidKeywordArgumentsInSidekiqWorkers do
it 'flags violation for optional keyword arguments usage in perform method signature' do
expect_offense(<<~RUBY)
def perform(id: nil)
- ^^^^^^^^^^^^^^^^^^^^ Do not use keyword arguments in Sidekiq workers. For details, check https://github.com/mperham/sidekiq/issues/2372
+ ^^^^^^^^^^^^^^^^^^^^ Do not use keyword arguments in Sidekiq workers. For details, [...]
end
RUBY
end
diff --git a/spec/rubocop/cop/ban_catch_throw_spec.rb b/spec/rubocop/cop/ban_catch_throw_spec.rb
index 4f669bad4af..b3c4ad8688c 100644
--- a/spec/rubocop/cop/ban_catch_throw_spec.rb
+++ b/spec/rubocop/cop/ban_catch_throw_spec.rb
@@ -1,30 +1,28 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/ban_catch_throw'
RSpec.describe RuboCop::Cop::BanCatchThrow do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'registers an offense when `catch` or `throw` are used' do
- inspect_source("catch(:foo) {\n throw(:foo)\n}")
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(2)
- expect(cop.offenses.map(&:line)).to eq([1, 2])
- expect(cop.highlights).to eq(['catch(:foo)', 'throw(:foo)'])
- end
+ expect_offense(<<~CODE)
+ catch(:foo) {
+ ^^^^^^^^^^^ Do not use catch or throw unless a gem's API demands it.
+ throw(:foo)
+ ^^^^^^^^^^^ Do not use catch or throw unless a gem's API demands it.
+ }
+ CODE
end
it 'does not register an offense for a method called catch or throw' do
- inspect_source("foo.catch(:foo) {\n foo.throw(:foo)\n}")
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses(<<~CODE)
+ foo.catch(:foo) {
+ foo.throw(:foo)
+ }
+ CODE
end
end
diff --git a/spec/rubocop/cop/code_reuse/finder_spec.rb b/spec/rubocop/cop/code_reuse/finder_spec.rb
index 6f04d5e0d60..484a1549a89 100644
--- a/spec/rubocop/cop/code_reuse/finder_spec.rb
+++ b/spec/rubocop/cop/code_reuse/finder_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/finder'
RSpec.describe RuboCop::Cop::CodeReuse::Finder do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of a Finder inside another Finder' do
@@ -23,8 +20,6 @@ RSpec.describe RuboCop::Cop::CodeReuse::Finder do
end
end
SOURCE
-
- expect(cop.offenses.size).to eq(1)
end
it 'flags the use of a Finder inside a model class method' do
diff --git a/spec/rubocop/cop/code_reuse/presenter_spec.rb b/spec/rubocop/cop/code_reuse/presenter_spec.rb
index 8efd4da8aa1..4639854588e 100644
--- a/spec/rubocop/cop/code_reuse/presenter_spec.rb
+++ b/spec/rubocop/cop/code_reuse/presenter_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/presenter'
RSpec.describe RuboCop::Cop::CodeReuse::Presenter do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of a Presenter in a Service class' do
diff --git a/spec/rubocop/cop/code_reuse/serializer_spec.rb b/spec/rubocop/cop/code_reuse/serializer_spec.rb
index 74999df5859..84db2e62b41 100644
--- a/spec/rubocop/cop/code_reuse/serializer_spec.rb
+++ b/spec/rubocop/cop/code_reuse/serializer_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/serializer'
RSpec.describe RuboCop::Cop::CodeReuse::Serializer do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of a Serializer in a Service class' do
diff --git a/spec/rubocop/cop/code_reuse/service_class_spec.rb b/spec/rubocop/cop/code_reuse/service_class_spec.rb
index 4870daf72dc..b6d94dd749f 100644
--- a/spec/rubocop/cop/code_reuse/service_class_spec.rb
+++ b/spec/rubocop/cop/code_reuse/service_class_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/service_class'
RSpec.describe RuboCop::Cop::CodeReuse::ServiceClass do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of a Service class in a Finder' do
diff --git a/spec/rubocop/cop/code_reuse/worker_spec.rb b/spec/rubocop/cop/code_reuse/worker_spec.rb
index 9e015f286d8..42c9303a93b 100644
--- a/spec/rubocop/cop/code_reuse/worker_spec.rb
+++ b/spec/rubocop/cop/code_reuse/worker_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/code_reuse/worker'
RSpec.describe RuboCop::Cop::CodeReuse::Worker do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of a worker in a controller' do
diff --git a/spec/rubocop/cop/default_scope_spec.rb b/spec/rubocop/cop/default_scope_spec.rb
index fee1895603c..506843e030e 100644
--- a/spec/rubocop/cop/default_scope_spec.rb
+++ b/spec/rubocop/cop/default_scope_spec.rb
@@ -2,47 +2,44 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/default_scope'
RSpec.describe RuboCop::Cop::DefaultScope do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'does not flag the use of default_scope with a send receiver' do
- inspect_source('foo.default_scope')
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses('foo.default_scope')
end
it 'flags the use of default_scope with a constant receiver' do
- inspect_source('User.default_scope')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~SOURCE)
+ User.default_scope
+ ^^^^^^^^^^^^^^^^^^ Do not use `default_scope`, [...]
+ SOURCE
end
it 'flags the use of default_scope with a nil receiver' do
- inspect_source('class Foo ; default_scope ; end')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~SOURCE)
+ class Foo ; default_scope ; end
+ ^^^^^^^^^^^^^ Do not use `default_scope`, [...]
+ SOURCE
end
it 'flags the use of default_scope when passing arguments' do
- inspect_source('class Foo ; default_scope(:foo) ; end')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~SOURCE)
+ class Foo ; default_scope(:foo) ; end
+ ^^^^^^^^^^^^^^^^^^^ Do not use `default_scope`, [...]
+ SOURCE
end
it 'flags the use of default_scope when passing a block' do
- inspect_source('class Foo ; default_scope { :foo } ; end')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~SOURCE)
+ class Foo ; default_scope { :foo } ; end
+ ^^^^^^^^^^^^^ Do not use `default_scope`, [...]
+ SOURCE
end
it 'ignores the use of default_scope with a local variable receiver' do
- inspect_source('users = User.all ; users.default_scope')
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses('users = User.all ; users.default_scope')
end
end
diff --git a/spec/rubocop/cop/destroy_all_spec.rb b/spec/rubocop/cop/destroy_all_spec.rb
index df664724a91..f6850a00238 100644
--- a/spec/rubocop/cop/destroy_all_spec.rb
+++ b/spec/rubocop/cop/destroy_all_spec.rb
@@ -2,44 +2,41 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/destroy_all'
RSpec.describe RuboCop::Cop::DestroyAll do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of destroy_all with a send receiver' do
- inspect_source('foo.destroy_all # rubocop: disable Cop/DestroyAll')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ foo.destroy_all # rubocop: disable Cop/DestroyAll
+ ^^^^^^^^^^^^^^^ Use `delete_all` instead of `destroy_all`. [...]
+ CODE
end
it 'flags the use of destroy_all with a constant receiver' do
- inspect_source('User.destroy_all # rubocop: disable Cop/DestroyAll')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ User.destroy_all # rubocop: disable Cop/DestroyAll
+ ^^^^^^^^^^^^^^^^ Use `delete_all` instead of `destroy_all`. [...]
+ CODE
end
it 'flags the use of destroy_all when passing arguments' do
- inspect_source('User.destroy_all([])')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ User.destroy_all([])
+ ^^^^^^^^^^^^^^^^^^^^ Use `delete_all` instead of `destroy_all`. [...]
+ CODE
end
it 'flags the use of destroy_all with a local variable receiver' do
- inspect_source(<<~RUBY)
- users = User.all
- users.destroy_all # rubocop: disable Cop/DestroyAll
- RUBY
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ users = User.all
+ users.destroy_all # rubocop: disable Cop/DestroyAll
+ ^^^^^^^^^^^^^^^^^ Use `delete_all` instead of `destroy_all`. [...]
+ CODE
end
it 'does not flag the use of delete_all' do
- inspect_source('foo.delete_all')
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses('foo.delete_all')
end
end
diff --git a/spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb b/spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb
index 2db03898e01..f96e25c59e7 100644
--- a/spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb
+++ b/spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb
@@ -2,19 +2,16 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/avoid_uploaded_file_from_params'
RSpec.describe RuboCop::Cop::Gitlab::AvoidUploadedFileFromParams do
- include CopHelper
-
subject(:cop) { described_class.new }
- context 'UploadedFile.from_params' do
+ context 'when using UploadedFile.from_params' do
it 'flags its call' do
expect_offense(<<~SOURCE)
- UploadedFile.from_params(params)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `UploadedFile` set by `multipart.rb` instead of calling `UploadedFile.from_params` directly. See https://docs.gitlab.com/ee/development/uploads.html#how-to-add-a-new-upload-route
+ UploadedFile.from_params(params)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `UploadedFile` set by `multipart.rb` instead of calling [...]
SOURCE
end
end
diff --git a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
index ad7e685e505..c280ab8fa8b 100644
--- a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
+++ b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
@@ -2,25 +2,22 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/bulk_insert'
RSpec.describe RuboCop::Cop::Gitlab::BulkInsert do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of Gitlab::Database.bulk_insert' do
expect_offense(<<~SOURCE)
- Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{RuboCop::Cop::Gitlab::BulkInsert::MSG}
+ Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, [...]
SOURCE
end
it 'flags the use of ::Gitlab::Database.bulk_insert' do
expect_offense(<<~SOURCE)
- ::Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{RuboCop::Cop::Gitlab::BulkInsert::MSG}
+ ::Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, [...]
SOURCE
end
end
diff --git a/spec/rubocop/cop/gitlab/change_timezone_spec.rb b/spec/rubocop/cop/gitlab/change_timezone_spec.rb
index 6abbc06bb1a..9cb822ec4f2 100644
--- a/spec/rubocop/cop/gitlab/change_timezone_spec.rb
+++ b/spec/rubocop/cop/gitlab/change_timezone_spec.rb
@@ -2,19 +2,16 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/change_timzone'
RSpec.describe RuboCop::Cop::Gitlab::ChangeTimezone do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'Time.zone=' do
it 'registers an offense with no 2nd argument' do
expect_offense(<<~PATTERN)
Time.zone = 'Awkland'
- ^^^^^^^^^^^^^^^^^^^^^ Do not change timezone in the runtime (application or rspec), it could result in silently modifying other behavior.
+ ^^^^^^^^^^^^^^^^^^^^^ Do not change timezone in the runtime (application or rspec), it could result [...]
PATTERN
end
end
diff --git a/spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb b/spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb
index bed06ab2b17..19e5fe946be 100644
--- a/spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb
+++ b/spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb
@@ -2,78 +2,75 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/const_get_inherit_false'
RSpec.describe RuboCop::Cop::Gitlab::ConstGetInheritFalse do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'Object.const_get' do
- it 'registers an offense with no 2nd argument' do
+ it 'registers an offense with no 2nd argument and corrects' do
expect_offense(<<~PATTERN)
Object.const_get(:CONSTANT)
^^^^^^^^^ Use inherit=false when using const_get.
PATTERN
- end
- it 'autocorrects' do
- expect(autocorrect_source('Object.const_get(:CONSTANT)')).to eq('Object.const_get(:CONSTANT, false)')
+ expect_correction(<<~PATTERN)
+ Object.const_get(:CONSTANT, false)
+ PATTERN
end
context 'inherit=false' do
it 'does not register an offense' do
expect_no_offenses(<<~PATTERN)
- Object.const_get(:CONSTANT, false)
+ Object.const_get(:CONSTANT, false)
PATTERN
end
end
context 'inherit=true' do
- it 'registers an offense' do
+ it 'registers an offense and corrects' do
expect_offense(<<~PATTERN)
- Object.const_get(:CONSTANT, true)
- ^^^^^^^^^ Use inherit=false when using const_get.
+ Object.const_get(:CONSTANT, true)
+ ^^^^^^^^^ Use inherit=false when using const_get.
PATTERN
- end
- it 'autocorrects' do
- expect(autocorrect_source('Object.const_get(:CONSTANT, true)')).to eq('Object.const_get(:CONSTANT, false)')
+ expect_correction(<<~PATTERN)
+ Object.const_get(:CONSTANT, false)
+ PATTERN
end
end
end
context 'const_get for a nested class' do
- it 'registers an offense on reload usage' do
+ it 'registers an offense on reload usage and corrects' do
expect_offense(<<~PATTERN)
Nested::Blog.const_get(:CONSTANT)
^^^^^^^^^ Use inherit=false when using const_get.
PATTERN
- end
- it 'autocorrects' do
- expect(autocorrect_source('Nested::Blag.const_get(:CONSTANT)')).to eq('Nested::Blag.const_get(:CONSTANT, false)')
+ expect_correction(<<~PATTERN)
+ Nested::Blog.const_get(:CONSTANT, false)
+ PATTERN
end
context 'inherit=false' do
it 'does not register an offense' do
expect_no_offenses(<<~PATTERN)
- Nested::Blog.const_get(:CONSTANT, false)
+ Nested::Blog.const_get(:CONSTANT, false)
PATTERN
end
end
context 'inherit=true' do
- it 'registers an offense if inherit is true' do
+ it 'registers an offense if inherit is true and corrects' do
expect_offense(<<~PATTERN)
- Nested::Blog.const_get(:CONSTANT, true)
- ^^^^^^^^^ Use inherit=false when using const_get.
+ Nested::Blog.const_get(:CONSTANT, true)
+ ^^^^^^^^^ Use inherit=false when using const_get.
PATTERN
- end
- it 'autocorrects' do
- expect(autocorrect_source('Nested::Blag.const_get(:CONSTANT, true)')).to eq('Nested::Blag.const_get(:CONSTANT, false)')
+ expect_correction(<<~PATTERN)
+ Nested::Blog.const_get(:CONSTANT, false)
+ PATTERN
end
end
end
diff --git a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb b/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
index 5804b03b641..a207155f432 100644
--- a/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
+++ b/spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb
@@ -6,8 +6,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/gitlab/duplicate_spec_location'
RSpec.describe RuboCop::Cop::Gitlab::DuplicateSpecLocation do
- include CopHelper
-
subject(:cop) { described_class.new }
let(:rails_root) { '../../../../' }
diff --git a/spec/rubocop/cop/gitlab/except_spec.rb b/spec/rubocop/cop/gitlab/except_spec.rb
index 173e5943da5..7a122e3cf53 100644
--- a/spec/rubocop/cop/gitlab/except_spec.rb
+++ b/spec/rubocop/cop/gitlab/except_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/except'
RSpec.describe RuboCop::Cop::Gitlab::Except do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of Gitlab::SQL::Except.new' do
diff --git a/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb b/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
index db3bcf1dfdb..03d7fc5e8b1 100644
--- a/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
+++ b/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
@@ -1,46 +1,31 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/finder_with_find_by'
RSpec.describe RuboCop::Cop::Gitlab::FinderWithFindBy do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when calling execute.find' do
- let(:source) do
- <<~SRC
- DummyFinder.new(some_args)
- .execute
- .find_by!(1)
- SRC
- end
-
- let(:corrected_source) do
- <<~SRC
- DummyFinder.new(some_args)
- .find_by!(1)
- SRC
- end
-
- it 'registers an offence' do
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- end
-
- it 'can autocorrect the source' do
- expect(autocorrect_source(source)).to eq(corrected_source)
+ it 'registers an offense and corrects' do
+ expect_offense(<<~CODE)
+ DummyFinder.new(some_args)
+ .execute
+ .find_by!(1)
+ ^^^^^^^^ Don't chain finders `#execute` method with [...]
+ CODE
+
+ expect_correction(<<~CODE)
+ DummyFinder.new(some_args)
+ .find_by!(1)
+ CODE
end
context 'when called within the `FinderMethods` module' do
- let(:source) do
- <<~SRC
+ it 'does not register an offense' do
+ expect_no_offenses(<<~SRC)
module FinderMethods
def find_by!(*args)
execute.find_by!(args)
@@ -48,12 +33,6 @@ RSpec.describe RuboCop::Cop::Gitlab::FinderWithFindBy do
end
SRC
end
-
- it 'does not register an offence' do
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
- end
end
end
end
diff --git a/spec/rubocop/cop/gitlab/httparty_spec.rb b/spec/rubocop/cop/gitlab/httparty_spec.rb
index b112ac84bff..fcd18b0eb9b 100644
--- a/spec/rubocop/cop/gitlab/httparty_spec.rb
+++ b/spec/rubocop/cop/gitlab/httparty_spec.rb
@@ -2,46 +2,30 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/httparty'
RSpec.describe RuboCop::Cop::Gitlab::HTTParty do # rubocop:disable RSpec/FilePath
- include CopHelper
-
subject(:cop) { described_class.new }
- shared_examples('registering include offense') do |options|
- let(:offending_lines) { options[:offending_lines] }
-
+ shared_examples('registering include offense') do
it 'registers an offense when the class includes HTTParty' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(offending_lines.size)
- expect(cop.offenses.map(&:line)).to eq(offending_lines)
- end
+ expect_offense(source)
end
end
- shared_examples('registering call offense') do |options|
- let(:offending_lines) { options[:offending_lines] }
-
+ shared_examples('registering call offense') do
it 'registers an offense when the class calls HTTParty' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(offending_lines.size)
- expect(cop.offenses.map(&:line)).to eq(offending_lines)
- end
+ expect_offense(source)
end
end
context 'when source is a regular module' do
- it_behaves_like 'registering include offense', offending_lines: [2] do
+ it_behaves_like 'registering include offense' do
let(:source) do
<<~RUBY
module M
include HTTParty
+ ^^^^^^^^^^^^^^^^ Avoid including `HTTParty` directly. [...]
end
RUBY
end
@@ -49,11 +33,12 @@ RSpec.describe RuboCop::Cop::Gitlab::HTTParty do # rubocop:disable RSpec/FilePat
end
context 'when source is a regular class' do
- it_behaves_like 'registering include offense', offending_lines: [2] do
+ it_behaves_like 'registering include offense' do
let(:source) do
<<~RUBY
class Foo
include HTTParty
+ ^^^^^^^^^^^^^^^^ Avoid including `HTTParty` directly. [...]
end
RUBY
end
@@ -61,12 +46,13 @@ RSpec.describe RuboCop::Cop::Gitlab::HTTParty do # rubocop:disable RSpec/FilePat
end
context 'when HTTParty is called' do
- it_behaves_like 'registering call offense', offending_lines: [3] do
+ it_behaves_like 'registering call offense' do
let(:source) do
<<~RUBY
class Foo
def bar
HTTParty.get('http://example.com')
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid calling `HTTParty` directly. [...]
end
end
RUBY
diff --git a/spec/rubocop/cop/gitlab/intersect_spec.rb b/spec/rubocop/cop/gitlab/intersect_spec.rb
index e724f47029c..6f0367591cd 100644
--- a/spec/rubocop/cop/gitlab/intersect_spec.rb
+++ b/spec/rubocop/cop/gitlab/intersect_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/intersect'
RSpec.describe RuboCop::Cop::Gitlab::Intersect do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of Gitlab::SQL::Intersect.new' do
diff --git a/spec/rubocop/cop/gitlab/json_spec.rb b/spec/rubocop/cop/gitlab/json_spec.rb
index fc25f69a244..29c3b96cc1a 100644
--- a/spec/rubocop/cop/gitlab/json_spec.rb
+++ b/spec/rubocop/cop/gitlab/json_spec.rb
@@ -2,38 +2,21 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/json'
RSpec.describe RuboCop::Cop::Gitlab::Json do
- include CopHelper
-
subject(:cop) { described_class.new }
- shared_examples('registering call offense') do |options|
- let(:offending_lines) { options[:offending_lines] }
-
- it 'registers an offense when the class calls JSON' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(offending_lines.size)
- expect(cop.offenses.map(&:line)).to eq(offending_lines)
- end
- end
- end
-
context 'when JSON is called' do
- it_behaves_like 'registering call offense', offending_lines: [3] do
- let(:source) do
- <<~RUBY
- class Foo
- def bar
- JSON.parse('{ "foo": "bar" }')
- end
+ it 'registers an offense' do
+ expect_offense(<<~RUBY)
+ class Foo
+ def bar
+ JSON.parse('{ "foo": "bar" }')
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid calling `JSON` directly. [...]
end
- RUBY
- end
+ end
+ RUBY
end
end
end
diff --git a/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb b/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
index 1d09c720bf7..08634d5753a 100644
--- a/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
+++ b/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
@@ -2,42 +2,33 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/module_with_instance_variables'
RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
- include CopHelper
+ let(:msg) { "Do not use instance variables in a module. [...]" }
subject(:cop) { described_class.new }
- shared_examples('registering offense') do |options|
- let(:offending_lines) { options[:offending_lines] }
-
+ shared_examples('registering offense') do
it 'registers an offense when instance variable is used in a module' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(offending_lines.size)
- expect(cop.offenses.map(&:line)).to eq(offending_lines)
- end
+ expect_offense(source)
end
end
shared_examples('not registering offense') do
it 'does not register offenses' do
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses(source)
end
end
context 'when source is a regular module' do
- it_behaves_like 'registering offense', offending_lines: [3] do
+ it_behaves_like 'registering offense' do
let(:source) do
<<~RUBY
module M
def f
@f = true
+ ^^^^^^^^^ #{msg}
end
end
RUBY
@@ -46,13 +37,14 @@ RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
end
context 'when source is a nested module' do
- it_behaves_like 'registering offense', offending_lines: [4] do
+ it_behaves_like 'registering offense' do
let(:source) do
<<~RUBY
module N
module M
def f
@f = true
+ ^^^^^^^^^ #{msg}
end
end
end
@@ -62,13 +54,14 @@ RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
end
context 'when source is a nested module with multiple offenses' do
- it_behaves_like 'registering offense', offending_lines: [4, 12] do
+ it_behaves_like 'registering offense' do
let(:source) do
<<~RUBY
module N
module M
def f
@f = true
+ ^^^^^^^^^ #{msg}
end
def g
@@ -77,6 +70,7 @@ RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
def h
@h = true
+ ^^^^^^^^^ #{msg}
end
end
end
@@ -129,12 +123,13 @@ RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
end
context 'when source is using simple or ivar assignment with other ivar' do
- it_behaves_like 'registering offense', offending_lines: [3] do
+ it_behaves_like 'registering offense' do
let(:source) do
<<~RUBY
module M
def f
@f ||= g(@g)
+ ^^ #{msg}
end
end
RUBY
@@ -143,13 +138,15 @@ RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
end
context 'when source is using or ivar assignment with something else' do
- it_behaves_like 'registering offense', offending_lines: [3, 4] do
+ it_behaves_like 'registering offense' do
let(:source) do
<<~RUBY
module M
def f
@f ||= true
+ ^^ #{msg}
@f.to_s
+ ^^ #{msg}
end
end
RUBY
diff --git a/spec/rubocop/cop/gitlab/namespaced_class_spec.rb b/spec/rubocop/cop/gitlab/namespaced_class_spec.rb
new file mode 100644
index 00000000000..d1f61aa5afb
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/namespaced_class_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/namespaced_class'
+
+RSpec.describe RuboCop::Cop::Gitlab::NamespacedClass do
+ subject(:cop) { described_class.new }
+
+ it 'flags a class definition without namespace' do
+ expect_offense(<<~SOURCE)
+ class MyClass
+ ^^^^^^^^^^^^^ #{described_class::MSG}
+ end
+ SOURCE
+ end
+
+ it 'flags a class definition with inheritance without namespace' do
+ expect_offense(<<~SOURCE)
+ class MyClass < ApplicationRecord
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
+ def some_method
+ true
+ end
+ end
+ SOURCE
+ end
+
+ it 'does not flag the class definition with namespace in separate lines' do
+ expect_no_offenses(<<~SOURCE)
+ module MyModule
+ class MyClass < ApplicationRecord
+ end
+
+ class MyOtherClass
+ def other_method
+ 1 + 1
+ end
+ end
+ end
+ SOURCE
+ end
+
+ it 'does not flag the class definition with nested namespace in separate lines' do
+ expect_no_offenses(<<~SOURCE)
+ module TopLevelModule
+ module NestedModule
+ class MyClass
+ end
+ end
+ end
+ SOURCE
+ end
+
+ it 'does not flag the class definition nested inside namespaced class' do
+ expect_no_offenses(<<~SOURCE)
+ module TopLevelModule
+ class TopLevelClass
+ class MyClass
+ end
+ end
+ end
+ SOURCE
+ end
+
+ it 'does not flag a compact namespaced class definition' do
+ expect_no_offenses(<<~SOURCE)
+ class MyModule::MyClass < ApplicationRecord
+ end
+ SOURCE
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb b/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb
index e6fb9ab9d57..6dbbcdd8324 100644
--- a/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb
+++ b/spec/rubocop/cop/gitlab/policy_rule_boolean_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/policy_rule_boolean'
RSpec.describe RuboCop::Cop::Gitlab::PolicyRuleBoolean do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'registers offense for &&' do
diff --git a/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb b/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
index 322c7c82968..071ddcf8b7d 100644
--- a/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
+++ b/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
@@ -2,55 +2,38 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/predicate_memoization'
RSpec.describe RuboCop::Cop::Gitlab::PredicateMemoization do
- include CopHelper
-
subject(:cop) { described_class.new }
- shared_examples('registering offense') do |options|
- let(:offending_lines) { options[:offending_lines] }
-
- it 'registers an offense when a predicate method is memoizing via ivar' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(offending_lines.size)
- expect(cop.offenses.map(&:line)).to eq(offending_lines)
- end
- end
- end
-
shared_examples('not registering offense') do
it 'does not register offenses' do
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses(source)
end
end
- context 'when source is a predicate method memoizing via ivar' do
- it_behaves_like 'registering offense', offending_lines: [3] do
+ context 'when source is a predicate method using ivar with assignment' do
+ it_behaves_like 'not registering offense' do
let(:source) do
<<~RUBY
class C
def really?
- @really ||= true
+ @really = true
end
end
RUBY
end
end
+ end
- it_behaves_like 'registering offense', offending_lines: [4] do
+ context 'when source is a predicate method using local with ||=' do
+ it_behaves_like 'not registering offense' do
let(:source) do
<<~RUBY
class C
def really?
- value = true
- @really ||= value
+ really ||= true
end
end
RUBY
@@ -58,13 +41,13 @@ RSpec.describe RuboCop::Cop::Gitlab::PredicateMemoization do
end
end
- context 'when source is a predicate method using ivar with assignment' do
+ context 'when source is a regular method memoizing via ivar' do
it_behaves_like 'not registering offense' do
let(:source) do
<<~RUBY
class C
- def really?
- @really = true
+ def really
+ @really ||= true
end
end
RUBY
@@ -72,30 +55,37 @@ RSpec.describe RuboCop::Cop::Gitlab::PredicateMemoization do
end
end
- context 'when source is a predicate method using local with ||=' do
- it_behaves_like 'not registering offense' do
- let(:source) do
- <<~RUBY
+ context 'when source is a predicate method memoizing via ivar' do
+ let(:msg) { "Avoid using `@value ||= query` [...]" }
+
+ context 'when assigning to boolean' do
+ it 'registers an offense' do
+ node = "@really ||= true"
+
+ expect_offense(<<~CODE, node: node, msg: msg)
class C
def really?
- really ||= true
+ %{node}
+ ^{node} %{msg}
end
end
- RUBY
+ CODE
end
end
- end
- context 'when source is a regular method memoizing via ivar' do
- it_behaves_like 'not registering offense' do
- let(:source) do
- <<~RUBY
+ context 'when assigning to another variable that is a boolean' do
+ it 'registers an offense' do
+ node = "@really ||= value"
+
+ expect_offense(<<~CODE, node: node, msg: msg)
class C
- def really
- @really ||= true
+ def really?
+ value = true
+ %{node}
+ ^{node} %{msg}
end
end
- RUBY
+ CODE
end
end
end
diff --git a/spec/rubocop/cop/gitlab/rails_logger_spec.rb b/spec/rubocop/cop/gitlab/rails_logger_spec.rb
index 768da243b02..7258b047191 100644
--- a/spec/rubocop/cop/gitlab/rails_logger_spec.rb
+++ b/spec/rubocop/cop/gitlab/rails_logger_spec.rb
@@ -2,37 +2,31 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/rails_logger'
RSpec.describe RuboCop::Cop::Gitlab::RailsLogger do
- include CopHelper
-
subject(:cop) { described_class.new }
described_class::LOG_METHODS.each do |method|
it "flags the use of Rails.logger.#{method} with a constant receiver" do
- inspect_source("Rails.logger.#{method}('some error')")
+ node = "Rails.logger.#{method}('some error')"
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE, node: node, msg: "Use a structured JSON logger instead of `Rails.logger`. [...]")
+ %{node}
+ ^{node} %{msg}
+ CODE
end
end
it 'does not flag the use of Rails.logger with a constant that is not Rails' do
- inspect_source("AppLogger.error('some error')")
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses("AppLogger.error('some error')")
end
it 'does not flag the use of logger with a send receiver' do
- inspect_source("file_logger.info('important info')")
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses("file_logger.info('important info')")
end
it 'does not flag the use of Rails.logger.level' do
- inspect_source("Rails.logger.level")
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses("Rails.logger.level")
end
end
diff --git a/spec/rubocop/cop/gitlab/union_spec.rb b/spec/rubocop/cop/gitlab/union_spec.rb
index 20364b1b901..04a3db8e7dd 100644
--- a/spec/rubocop/cop/gitlab/union_spec.rb
+++ b/spec/rubocop/cop/gitlab/union_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/union'
RSpec.describe RuboCop::Cop::Gitlab::Union do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of Gitlab::SQL::Union.new' do
diff --git a/spec/rubocop/cop/graphql/authorize_types_spec.rb b/spec/rubocop/cop/graphql/authorize_types_spec.rb
index a1b7a3f3a9b..9242b865b20 100644
--- a/spec/rubocop/cop/graphql/authorize_types_spec.rb
+++ b/spec/rubocop/cop/graphql/authorize_types_spec.rb
@@ -6,21 +6,18 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/authorize_types'
RSpec.describe RuboCop::Cop::Graphql::AuthorizeTypes do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'adds an offense when there is no authorize call' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
module Types
class AType < BaseObject
+ ^^^^^^^^^^^^^^^^^^^^^^^^ Add an `authorize :ability` call to the type: https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#type-authorization
field :a_thing
field :another_thing
end
end
TYPE
-
- expect(cop.offenses.size).to eq 1
end
it 'does not add an offense for classes that have an authorize call' do
diff --git a/spec/rubocop/cop/graphql/descriptions_spec.rb b/spec/rubocop/cop/graphql/descriptions_spec.rb
index b44205b0920..9ad40fad83d 100644
--- a/spec/rubocop/cop/graphql/descriptions_spec.rb
+++ b/spec/rubocop/cop/graphql/descriptions_spec.rb
@@ -5,38 +5,34 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/descriptions'
RSpec.describe RuboCop::Cop::Graphql::Descriptions do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'fields' do
it 'adds an offense when there is no description' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
module Types
class FakeType < BaseObject
field :a_thing,
+ ^^^^^^^^^^^^^^^ Please add a `description` property.
GraphQL::STRING_TYPE,
null: false
end
end
TYPE
-
- expect(cop.offenses.size).to eq 1
end
it 'adds an offense when description does not end in a period' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
module Types
class FakeType < BaseObject
field :a_thing,
+ ^^^^^^^^^^^^^^^ `description` strings must end with a `.`.
GraphQL::STRING_TYPE,
null: false,
description: 'A descriptive description'
end
end
TYPE
-
- expect(cop.offenses.size).to eq 1
end
it 'does not add an offense when description is correct' do
@@ -55,32 +51,30 @@ RSpec.describe RuboCop::Cop::Graphql::Descriptions do
context 'arguments' do
it 'adds an offense when there is no description' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
module Types
class FakeType < BaseObject
argument :a_thing,
+ ^^^^^^^^^^^^^^^^^^ Please add a `description` property.
GraphQL::STRING_TYPE,
null: false
end
end
TYPE
-
- expect(cop.offenses.size).to eq 1
end
it 'adds an offense when description does not end in a period' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
module Types
class FakeType < BaseObject
argument :a_thing,
+ ^^^^^^^^^^^^^^^^^^ `description` strings must end with a `.`.
GraphQL::STRING_TYPE,
null: false,
description: 'Behold! A description'
end
end
TYPE
-
- expect(cop.offenses.size).to eq 1
end
it 'does not add an offense when description is correct' do
diff --git a/spec/rubocop/cop/graphql/gid_expected_type_spec.rb b/spec/rubocop/cop/graphql/gid_expected_type_spec.rb
index 8fd7ae03748..d9a129244d6 100644
--- a/spec/rubocop/cop/graphql/gid_expected_type_spec.rb
+++ b/spec/rubocop/cop/graphql/gid_expected_type_spec.rb
@@ -6,16 +6,13 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/gid_expected_type'
RSpec.describe RuboCop::Cop::Graphql::GIDExpectedType do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'adds an offense when there is no expected_type parameter' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
GitlabSchema.object_from_id(received_id)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add an expected_type parameter to #object_from_id calls if possible.
TYPE
-
- expect(cop.offenses.size).to eq 1
end
it 'does not add an offense for calls that have an expected_type parameter' do
diff --git a/spec/rubocop/cop/graphql/id_type_spec.rb b/spec/rubocop/cop/graphql/id_type_spec.rb
index 6135c9fef43..93c01cd7f06 100644
--- a/spec/rubocop/cop/graphql/id_type_spec.rb
+++ b/spec/rubocop/cop/graphql/id_type_spec.rb
@@ -6,16 +6,13 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/id_type'
RSpec.describe RuboCop::Cop::Graphql::IDType do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'adds an offense when GraphQL::ID_TYPE is used as a param to #argument' do
- inspect_source(<<~TYPE)
+ expect_offense(<<~TYPE)
argument :some_arg, GraphQL::ID_TYPE, some: other, params: do_not_matter
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use GraphQL::ID_TYPE, use a specific GlobalIDType instead
TYPE
-
- expect(cop.offenses.size).to eq 1
end
context 'whitelisted arguments' do
diff --git a/spec/rubocop/cop/graphql/json_type_spec.rb b/spec/rubocop/cop/graphql/json_type_spec.rb
index 6d9f86e44d2..91838c1708e 100644
--- a/spec/rubocop/cop/graphql/json_type_spec.rb
+++ b/spec/rubocop/cop/graphql/json_type_spec.rb
@@ -5,29 +5,29 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/json_type'
RSpec.describe RuboCop::Cop::Graphql::JSONType do
- include CopHelper
+ let(:msg) do
+ 'Avoid using GraphQL::Types::JSON. See: https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#json'
+ end
subject(:cop) { described_class.new }
context 'fields' do
it 'adds an offense when GraphQL::Types::JSON is used' do
- inspect_source(<<~RUBY.strip)
+ expect_offense(<<~RUBY)
class MyType
field :some_field, GraphQL::Types::JSON
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
end
RUBY
-
- expect(cop.offenses.size).to eq(1)
end
it 'adds an offense when GraphQL::Types::JSON is used with other keywords' do
- inspect_source(<<~RUBY.strip)
+ expect_offense(<<~RUBY)
class MyType
field :some_field, GraphQL::Types::JSON, null: true, description: 'My description'
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
end
RUBY
-
- expect(cop.offenses.size).to eq(1)
end
it 'does not add an offense for other types' do
@@ -41,23 +41,21 @@ RSpec.describe RuboCop::Cop::Graphql::JSONType do
context 'arguments' do
it 'adds an offense when GraphQL::Types::JSON is used' do
- inspect_source(<<~RUBY.strip)
+ expect_offense(<<~RUBY)
class MyType
argument :some_arg, GraphQL::Types::JSON
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
end
RUBY
-
- expect(cop.offenses.size).to eq(1)
end
it 'adds an offense when GraphQL::Types::JSON is used with other keywords' do
- inspect_source(<<~RUBY.strip)
+ expect_offense(<<~RUBY)
class MyType
argument :some_arg, GraphQL::Types::JSON, null: true, description: 'My description'
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
end
RUBY
-
- expect(cop.offenses.size).to eq(1)
end
it 'does not add an offense for other types' do
diff --git a/spec/rubocop/cop/graphql/resolver_type_spec.rb b/spec/rubocop/cop/graphql/resolver_type_spec.rb
index 25213e30528..11c0ad284a9 100644
--- a/spec/rubocop/cop/graphql/resolver_type_spec.rb
+++ b/spec/rubocop/cop/graphql/resolver_type_spec.rb
@@ -6,24 +6,19 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/graphql/resolver_type'
RSpec.describe RuboCop::Cop::Graphql::ResolverType do
- include CopHelper
-
subject(:cop) { described_class.new }
- it 'adds an offense when there is no type annotaion' do
- lacks_type = <<-SRC
+ it 'adds an offense when there is no type annotation' do
+ expect_offense(<<~SRC)
module Resolvers
class FooResolver < BaseResolver
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Missing type annotation: Please add `type` DSL method call. e.g: type UserType.connection_type, null: true
def resolve(**args)
[:thing]
end
end
end
SRC
-
- inspect_source(lacks_type)
-
- expect(cop.offenses.size).to eq 1
end
it 'does not add an offense for resolvers that have a type call' do
@@ -41,9 +36,10 @@ RSpec.describe RuboCop::Cop::Graphql::ResolverType do
end
it 'ignores type calls on other objects' do
- lacks_type = <<-SRC
+ expect_offense(<<~SRC)
module Resolvers
class FooResolver < BaseResolver
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Missing type annotation: Please add `type` DSL method call. e.g: type UserType.connection_type, null: true
class FalsePositive < BaseObject
type RedHerringType, null: true
end
@@ -54,10 +50,6 @@ RSpec.describe RuboCop::Cop::Graphql::ResolverType do
end
end
SRC
-
- inspect_source(lacks_type)
-
- expect(cop.offenses.size).to eq 1
end
it 'does not add an offense unless the class is named using the Resolver convention' do
diff --git a/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb b/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
index ac6c481a7c3..b3ec426dc07 100644
--- a/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
+++ b/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
@@ -2,29 +2,28 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/group_public_or_visible_to_user'
RSpec.describe RuboCop::Cop::GroupPublicOrVisibleToUser do
- include CopHelper
+ let(:msg) do
+ "`Group.public_or_visible_to_user` should be used with extreme care. " \
+ "Please ensure that you are not using it on its own and that the amount of rows being filtered is reasonable."
+ end
subject(:cop) { described_class.new }
it 'flags the use of Group.public_or_visible_to_user with a constant receiver' do
- inspect_source('Group.public_or_visible_to_user')
-
- expect(cop.offenses.size).to eq(1)
+ expect_offense(<<~CODE)
+ Group.public_or_visible_to_user
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{msg}
+ CODE
end
- it 'does not flat the use of public_or_visible_to_user with a constant that is not Group' do
- inspect_source('Project.public_or_visible_to_user')
-
- expect(cop.offenses.size).to eq(0)
+ it 'does not flag the use of public_or_visible_to_user with a constant that is not Group' do
+ expect_no_offenses('Project.public_or_visible_to_user')
end
it 'does not flag the use of Group.public_or_visible_to_user with a send receiver' do
- inspect_source('foo.public_or_visible_to_user')
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses('foo.public_or_visible_to_user')
end
end
diff --git a/spec/rubocop/cop/include_sidekiq_worker_spec.rb b/spec/rubocop/cop/include_sidekiq_worker_spec.rb
index f12652a1a58..bdd622d4894 100644
--- a/spec/rubocop/cop/include_sidekiq_worker_spec.rb
+++ b/spec/rubocop/cop/include_sidekiq_worker_spec.rb
@@ -3,33 +3,21 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../rubocop/cop/include_sidekiq_worker'
RSpec.describe RuboCop::Cop::IncludeSidekiqWorker do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when `Sidekiq::Worker` is included' do
- let(:source) { 'include Sidekiq::Worker' }
- let(:correct_source) { 'include ApplicationWorker' }
-
- it 'registers an offense' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq(['Sidekiq::Worker'])
- end
- end
-
- it 'autocorrects to the right version' do
- autocorrected = autocorrect_source(source)
-
- expect(autocorrected).to eq(correct_source)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(<<~CODE)
+ include Sidekiq::Worker
+ ^^^^^^^^^^^^^^^ Include `ApplicationWorker`, not `Sidekiq::Worker`.
+ CODE
+
+ expect_correction(<<~CODE)
+ include ApplicationWorker
+ CODE
end
end
end
diff --git a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
index 47247006e42..2d293fd0a05 100644
--- a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
+++ b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/inject_enterprise_edition_module'
RSpec.describe RuboCop::Cop::InjectEnterpriseEditionModule do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the use of `prepend_if_ee EE` in the middle of a file' do
@@ -185,18 +182,19 @@ RSpec.describe RuboCop::Cop::InjectEnterpriseEditionModule do
end
it 'autocorrects offenses by just disabling the Cop' do
- source = <<~SOURCE
- class Foo
- prepend_if_ee 'EE::Foo'
- include_if_ee 'Bar'
- end
+ expect_offense(<<~SOURCE)
+ class Foo
+ prepend_if_ee 'EE::Foo'
+ ^^^^^^^^^^^^^^^^^^^^^^^ Injecting EE modules must be done on the last line of this file, outside of any class or module definitions
+ include_if_ee 'Bar'
+ end
SOURCE
- expect(autocorrect_source(source)).to eq(<<~SOURCE)
- class Foo
- prepend_if_ee 'EE::Foo' # rubocop: disable Cop/InjectEnterpriseEditionModule
- include_if_ee 'Bar'
- end
+ expect_correction(<<~SOURCE)
+ class Foo
+ prepend_if_ee 'EE::Foo' # rubocop: disable Cop/InjectEnterpriseEditionModule
+ include_if_ee 'Bar'
+ end
SOURCE
end
diff --git a/spec/rubocop/cop/lint/last_keyword_argument_spec.rb b/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
index 826c681a880..aac59f0db4c 100644
--- a/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
+++ b/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/lint/last_keyword_argument'
RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument do
- include CopHelper
-
subject(:cop) { described_class.new }
before do
diff --git a/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb b/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb
index 97b9d0d1ee2..149fb0a48eb 100644
--- a/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb
+++ b/spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb
@@ -28,6 +28,15 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
^^^^ #{described_class::MSG}
end
+ create_table_with_constraints :test_text_limits_create do |t|
+ t.integer :test_id, null: false
+ t.text :title
+ t.text :description
+ ^^^^ #{described_class::MSG}
+
+ t.text_limit :title, 100
+ end
+
add_column :test_text_limits, :email, :text
^^^^^^^^^^ #{described_class::MSG}
@@ -57,6 +66,15 @@ RSpec.describe RuboCop::Cop::Migration::AddLimitToTextColumns do
t.text :name
end
+ create_table_with_constraints :test_text_limits_create do |t|
+ t.integer :test_id, null: false
+ t.text :title
+ t.text :description
+
+ t.text_limit :title, 100
+ t.text_limit :description, 255
+ end
+
add_column :test_text_limits, :email, :text
add_column_with_default :test_text_limits, :role, :text, default: 'default'
change_column_type_concurrently :test_text_limits, :test_id, :text
diff --git a/spec/rubocop/cop/performance/ar_count_each_spec.rb b/spec/rubocop/cop/performance/ar_count_each_spec.rb
index 6242c7a4c5e..402e3e93147 100644
--- a/spec/rubocop/cop/performance/ar_count_each_spec.rb
+++ b/spec/rubocop/cop/performance/ar_count_each_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/performance/ar_count_each.rb'
RSpec.describe RuboCop::Cop::Performance::ARCountEach do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when it is not haml file' do
@@ -32,8 +30,6 @@ RSpec.describe RuboCop::Cop::Performance::ARCountEach do
^^^^^^^^^^^^ If @users is AR relation, avoid `@users.count ...; @users.each... `, this will trigger two queries. Use `@users.load.size ...; @users.each... ` instead. If @users is an array, try to use @users.size.
@users.each { |user| display(user) }
SOURCE
-
- expect(cop.offenses.map(&:cop_name)).to contain_exactly('Performance/ARCountEach')
end
end
diff --git a/spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb b/spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb
index 3321d400ae1..8497ff0e909 100644
--- a/spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb
+++ b/spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/performance/ar_exists_and_present_blank.rb'
RSpec.describe RuboCop::Cop::Performance::ARExistsAndPresentBlank do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when it is not haml file' do
@@ -32,8 +30,6 @@ RSpec.describe RuboCop::Cop::Performance::ARExistsAndPresentBlank do
show @users if @users.present?
^^^^^^^^^^^^^^^ Avoid `@users.present?`, because it will generate database query 'Select TABLE.*' which is expensive. Suggest to use `@users.any?` to replace `@users.present?`
SOURCE
-
- expect(cop.offenses.map(&:cop_name)).to contain_exactly('Performance/ARExistsAndPresentBlank')
end
end
@@ -44,8 +40,6 @@ RSpec.describe RuboCop::Cop::Performance::ARExistsAndPresentBlank do
show @users if @users.blank?
^^^^^^^^^^^^^ Avoid `@users.blank?`, because it will generate database query 'Select TABLE.*' which is expensive. Suggest to use `@users.empty?` to replace `@users.blank?`
SOURCE
-
- expect(cop.offenses.map(&:cop_name)).to contain_exactly('Performance/ARExistsAndPresentBlank')
end
end
@@ -58,8 +52,6 @@ RSpec.describe RuboCop::Cop::Performance::ARExistsAndPresentBlank do
show @users if @users.present?
^^^^^^^^^^^^^^^ Avoid `@users.present?`, because it will generate database query 'Select TABLE.*' which is expensive. Suggest to use `@users.any?` to replace `@users.present?`
SOURCE
-
- expect(cop.offenses.map(&:cop_name)).to contain_exactly('Performance/ARExistsAndPresentBlank', 'Performance/ARExistsAndPresentBlank')
end
end
diff --git a/spec/rubocop/cop/performance/readlines_each_spec.rb b/spec/rubocop/cop/performance/readlines_each_spec.rb
index c19426606f6..5a30107722a 100644
--- a/spec/rubocop/cop/performance/readlines_each_spec.rb
+++ b/spec/rubocop/cop/performance/readlines_each_spec.rb
@@ -5,19 +5,21 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/performance/readlines_each'
RSpec.describe RuboCop::Cop::Performance::ReadlinesEach do
- include CopHelper
-
subject(:cop) { described_class.new }
let(:message) { 'Avoid `IO.readlines.each`, since it reads contents into memory in full. Use `IO.each_line` or `IO.each` instead.' }
shared_examples_for(:class_read) do |klass|
context "and it is called as a class method on #{klass}" do
- # We can't use `expect_offense` here because indentation changes based on `klass`
it 'flags it as an offense' do
- inspect_source "#{klass}.readlines(file_path).each { |line| puts line }"
+ leading_readline = "#{klass}.readlines(file_path)."
+ padding = " " * leading_readline.length
+ node = "#{leading_readline}each { |line| puts line }"
- expect(cop.offenses.map(&:cop_name)).to contain_exactly('Performance/ReadlinesEach')
+ expect_offense(<<~CODE, node: node)
+ %{node}
+ #{padding}^^^^ Avoid `IO.readlines.each`, since it reads contents into memory in full. [...]
+ CODE
end
end
@@ -62,9 +64,14 @@ RSpec.describe RuboCop::Cop::Performance::ReadlinesEach do
end
it 'autocorrects `readlines.each` to `each_line`' do
- expect(autocorrect_source('obj.readlines.each { |line| line }')).to(
- eq('obj.each_line { |line| line }')
- )
+ expect_offense(<<~CODE)
+ obj.readlines.each { |line| line }
+ ^^^^ Avoid `IO.readlines.each`, since it reads contents into memory in full. [...]
+ CODE
+
+ expect_correction(<<~CODE)
+ obj.each_line { |line| line }
+ CODE
end
end
diff --git a/spec/rubocop/cop/project_path_helper_spec.rb b/spec/rubocop/cop/project_path_helper_spec.rb
index 78a590b89f6..16782802a27 100644
--- a/spec/rubocop/cop/project_path_helper_spec.rb
+++ b/spec/rubocop/cop/project_path_helper_spec.rb
@@ -3,41 +3,30 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../rubocop/cop/project_path_helper'
RSpec.describe RuboCop::Cop::ProjectPathHelper do
- include CopHelper
-
subject(:cop) { described_class.new }
context "when using namespace_project with the project's namespace" do
let(:source) { 'edit_namespace_project_issue_path(@issue.project.namespace, @issue.project, @issue)' }
let(:correct_source) { 'edit_project_issue_path(@issue.project, @issue)' }
- it 'registers an offense' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq(['edit_namespace_project_issue_path'])
- end
- end
-
- it 'autocorrects to the right version' do
- autocorrected = autocorrect_source(source)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(<<~CODE)
+ #{source}
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use short project path helpers without explicitly passing the namespace[...]
+ CODE
- expect(autocorrected).to eq(correct_source)
+ expect_correction(<<~CODE)
+ #{correct_source}
+ CODE
end
end
context 'when using namespace_project with a different namespace' do
it 'registers no offense' do
- inspect_source('edit_namespace_project_issue_path(namespace, project)')
-
- expect(cop.offenses.size).to eq(0)
+ expect_no_offenses('edit_namespace_project_issue_path(namespace, project)')
end
end
end
diff --git a/spec/rubocop/cop/put_project_routes_under_scope_spec.rb b/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
index b0627af0e8b..eb783d22129 100644
--- a/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
+++ b/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../rubocop/cop/put_project_routes_under_scope'
RSpec.describe RuboCop::Cop::PutProjectRoutesUnderScope do
- include CopHelper
-
subject(:cop) { described_class.new }
%w[resource resources get post put patch delete].each do |route_method|
diff --git a/spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb b/spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb
index 4876fcd5050..9332ab4186e 100644
--- a/spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb
+++ b/spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb
@@ -1,15 +1,11 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/qa/ambiguous_page_object_name'
RSpec.describe RuboCop::Cop::QA::AmbiguousPageObjectName do
- include CopHelper
-
let(:source_file) { 'qa/page.rb' }
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/qa/element_with_pattern_spec.rb b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
index 6289b1a7c97..28c351ccf1e 100644
--- a/spec/rubocop/cop/qa/element_with_pattern_spec.rb
+++ b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
@@ -1,15 +1,11 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/qa/element_with_pattern'
RSpec.describe RuboCop::Cop::QA::ElementWithPattern do
- include CopHelper
-
let(:source_file) { 'qa/page.rb' }
subject(:cop) { described_class.new }
diff --git a/spec/rubocop/cop/rspec/any_instance_of_spec.rb b/spec/rubocop/cop/rspec/any_instance_of_spec.rb
index 42bb7d196a1..e7675ded25e 100644
--- a/spec/rubocop/cop/rspec/any_instance_of_spec.rb
+++ b/spec/rubocop/cop/rspec/any_instance_of_spec.rb
@@ -5,59 +5,51 @@ require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/rspec/any_instance_of'
RSpec.describe RuboCop::Cop::RSpec::AnyInstanceOf do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when calling allow_any_instance_of' do
let(:source) do
<<~SRC
- allow_any_instance_of(User).to receive(:invalidate_issue_cache_counts)
+ allow_any_instance_of(User).to receive(:invalidate_issue_cache_counts)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use `allow_any_instance_of` [...]
SRC
end
let(:corrected_source) do
<<~SRC
- allow_next_instance_of(User) do |instance|
- allow(instance).to receive(:invalidate_issue_cache_counts)
- end
+ allow_next_instance_of(User) do |instance|
+ allow(instance).to receive(:invalidate_issue_cache_counts)
+ end
SRC
end
- it 'registers an offence' do
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- end
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(source)
- it 'can autocorrect the source' do
- expect(autocorrect_source(source)).to eq(corrected_source)
+ expect_correction(corrected_source)
end
end
context 'when calling expect_any_instance_of' do
let(:source) do
<<~SRC
- expect_any_instance_of(User).to receive(:invalidate_issue_cache_counts).with(args).and_return(double)
+ expect_any_instance_of(User).to receive(:invalidate_issue_cache_counts).with(args).and_return(double)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use `expect_any_instance_of` [...]
SRC
end
let(:corrected_source) do
<<~SRC
- expect_next_instance_of(User) do |instance|
- expect(instance).to receive(:invalidate_issue_cache_counts).with(args).and_return(double)
- end
+ expect_next_instance_of(User) do |instance|
+ expect(instance).to receive(:invalidate_issue_cache_counts).with(args).and_return(double)
+ end
SRC
end
- it 'registers an offence' do
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- end
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(source)
- it 'can autocorrect the source' do
- expect(autocorrect_source(source)).to eq(corrected_source)
+ expect_correction(corrected_source)
end
end
end
diff --git a/spec/rubocop/cop/rspec/be_success_matcher_spec.rb b/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
index d49507c89b1..050f0396fac 100644
--- a/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
+++ b/spec/rubocop/cop/rspec/be_success_matcher_spec.rb
@@ -5,34 +5,27 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/be_success_matcher'
RSpec.describe RuboCop::Cop::RSpec::BeSuccessMatcher do
- include CopHelper
-
let(:source_file) { 'spec/foo_spec.rb' }
subject(:cop) { described_class.new }
shared_examples 'cop' do |good:, bad:|
context "using #{bad} call" do
- it 'registers an offense' do
- inspect_source(bad, source_file)
-
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq([bad])
- end
-
- it "autocorrects it to `#{good}`" do
- autocorrected = autocorrect_source(bad, source_file)
-
- expect(autocorrected).to eql(good)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(<<~CODE, node: bad)
+ %{node}
+ ^{node} Do not use deprecated `success?` method, use `successful?` instead.
+ CODE
+
+ expect_correction(<<~CODE)
+ #{good}
+ CODE
end
end
context "using #{good} call" do
it 'does not register an offense' do
- inspect_source(good)
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses(good)
end
end
end
diff --git a/spec/rubocop/cop/rspec/env_assignment_spec.rb b/spec/rubocop/cop/rspec/env_assignment_spec.rb
index 07afd30fc90..cc132d1532a 100644
--- a/spec/rubocop/cop/rspec/env_assignment_spec.rb
+++ b/spec/rubocop/cop/rspec/env_assignment_spec.rb
@@ -3,13 +3,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../../rubocop/cop/rspec/env_assignment'
RSpec.describe RuboCop::Cop::RSpec::EnvAssignment do
- include CopHelper
-
offense_call_single_quotes_key = %(ENV['FOO'] = 'bar').freeze
offense_call_double_quotes_key = %(ENV["FOO"] = 'bar').freeze
@@ -17,31 +13,24 @@ RSpec.describe RuboCop::Cop::RSpec::EnvAssignment do
subject(:cop) { described_class.new }
- shared_examples 'an offensive ENV#[]= call' do |content|
- it "registers an offense for `#{content}`" do
- inspect_source(content, source_file)
-
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq([content])
- end
- end
-
- shared_examples 'an autocorrected ENV#[]= call' do |content, autocorrected_content|
- it "registers an offense for `#{content}` and autocorrects it to `#{autocorrected_content}`" do
- autocorrected = autocorrect_source(content, source_file)
+ shared_examples 'an offensive and correction ENV#[]= call' do |content, autocorrected_content|
+ it "registers an offense for `#{content}` and corrects", :aggregate_failures do
+ expect_offense(<<~CODE)
+ #{content}
+ ^^^^^^^^^^^^^^^^^^ Don't assign to ENV, use `stub_env` instead.
+ CODE
- expect(autocorrected).to eql(autocorrected_content)
+ expect_correction(<<~CODE)
+ #{autocorrected_content}
+ CODE
end
end
context 'with a key using single quotes' do
- it_behaves_like 'an offensive ENV#[]= call', offense_call_single_quotes_key
- it_behaves_like 'an autocorrected ENV#[]= call', offense_call_single_quotes_key, %(stub_env('FOO', 'bar'))
+ it_behaves_like 'an offensive and correction ENV#[]= call', offense_call_single_quotes_key, %(stub_env('FOO', 'bar'))
end
context 'with a key using double quotes' do
- it_behaves_like 'an offensive ENV#[]= call', offense_call_double_quotes_key
- it_behaves_like 'an autocorrected ENV#[]= call', offense_call_double_quotes_key, %(stub_env("FOO", 'bar'))
+ it_behaves_like 'an offensive and correction ENV#[]= call', offense_call_double_quotes_key, %(stub_env("FOO", 'bar'))
end
end
diff --git a/spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb b/spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb
index f7adc1373df..d1ce8d01e0b 100644
--- a/spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb
+++ b/spec/rubocop/cop/rspec/expect_gitlab_tracking_spec.rb
@@ -2,13 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../../rubocop/cop/rspec/expect_gitlab_tracking'
RSpec.describe RuboCop::Cop::RSpec::ExpectGitlabTracking do
- include CopHelper
-
let(:source_file) { 'spec/foo_spec.rb' }
subject(:cop) { described_class.new }
@@ -36,29 +32,18 @@ RSpec.describe RuboCop::Cop::RSpec::ExpectGitlabTracking do
good_samples.each do |good|
context "good: #{good}" do
it 'does not register an offense' do
- inspect_source(good)
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses(good)
end
end
end
bad_samples.each do |bad|
context "bad: #{bad}" do
- it 'registers an offense', :aggregate_failures do
- inspect_source(bad, source_file)
-
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq([bad])
-
- msg = cop.offenses.first.message
-
- expect(msg).to match(
- /Do not expect directly on `Gitlab::Tracking#event`/
- )
- expect(msg).to match(/add the `snowplow` annotation/)
- expect(msg).to match(/use `expect_snowplow_event` instead/)
+ it 'registers an offense' do
+ expect_offense(<<~CODE, node: bad)
+ %{node}
+ ^{node} Do not expect directly on `Gitlab::Tracking#event`[...]
+ CODE
end
end
end
diff --git a/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb b/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
index fe9cea47a43..8beec53375e 100644
--- a/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
+++ b/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
@@ -3,17 +3,13 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../../rubocop/cop/rspec/factories_in_migration_specs'
RSpec.describe RuboCop::Cop::RSpec::FactoriesInMigrationSpecs do
- include CopHelper
-
subject(:cop) { described_class.new }
shared_examples 'an offensive factory call' do |namespace|
- %i[build build_list create create_list].each do |forbidden_method|
+ %i[build build_list create create_list attributes_for].each do |forbidden_method|
namespaced_forbidden_method = "#{namespace}#{forbidden_method}(:user)"
it "registers an offense for #{namespaced_forbidden_method}" do
diff --git a/spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb b/spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb
index 33fdaaee3c7..0e6af71ea3e 100644
--- a/spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb
+++ b/spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb
@@ -7,8 +7,6 @@ require 'rubocop'
require_relative '../../../../../rubocop/cop/rspec/factory_bot/inline_association'
RSpec.describe RuboCop::Cop::RSpec::FactoryBot::InlineAssociation do
- include CopHelper
-
subject(:cop) { described_class.new }
shared_examples 'offense' do |code_snippet, autocorrected|
@@ -17,27 +15,31 @@ RSpec.describe RuboCop::Cop::RSpec::FactoryBot::InlineAssociation do
let(:offense_marker) { '^' * code_snippet.size }
let(:offense_msg) { msg(type) }
let(:offense) { "#{offense_marker} #{offense_msg}" }
- let(:pristine_source) { source.sub(offense, '') }
let(:source) do
<<~RUBY
- FactoryBot.define do
- factory :project do
- attribute { #{code_snippet} }
- #{offense}
- end
+ FactoryBot.define do
+ factory :project do
+ attribute { #{code_snippet} }
+ #{offense}
end
+ end
RUBY
end
- it 'registers an offense' do
- expect_offense(source)
+ let(:corrected_source) do
+ <<~RUBY
+ FactoryBot.define do
+ factory :project do
+ attribute { #{autocorrected} }
+ end
+ end
+ RUBY
end
- it 'autocorrects the source' do
- corrected = autocorrect_source(pristine_source)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(source)
- expect(corrected).not_to include(code_snippet)
- expect(corrected).to include(autocorrected)
+ expect_correction(corrected_source)
end
end
diff --git a/spec/rubocop/cop/rspec/have_gitlab_http_status_spec.rb b/spec/rubocop/cop/rspec/have_gitlab_http_status_spec.rb
index f6040350dc0..c2d97c8992a 100644
--- a/spec/rubocop/cop/rspec/have_gitlab_http_status_spec.rb
+++ b/spec/rubocop/cop/rspec/have_gitlab_http_status_spec.rb
@@ -4,50 +4,42 @@ require 'fast_spec_helper'
require 'rspec-parameterized'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../../rubocop/cop/rspec/have_gitlab_http_status'
RSpec.describe RuboCop::Cop::RSpec::HaveGitlabHttpStatus do
- include CopHelper
-
using RSpec::Parameterized::TableSyntax
let(:source_file) { 'spec/foo_spec.rb' }
subject(:cop) { described_class.new }
- shared_examples 'offense' do |code|
- it 'registers an offense' do
- inspect_source(code, source_file)
+ shared_examples 'offense' do |bad, good|
+ it 'registers an offense', :aggregate_failures do
+ expect_offense(<<~CODE, node: bad)
+ %{node}
+ ^{node} [...]
+ CODE
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq([code])
+ expect_correction(<<~CODE)
+ #{good}
+ CODE
end
end
shared_examples 'no offense' do |code|
it 'does not register an offense' do
- inspect_source(code)
-
- expect(cop.offenses).to be_empty
- end
- end
-
- shared_examples 'autocorrect' do |bad, good|
- it 'autocorrects' do
- autocorrected = autocorrect_source(bad, source_file)
-
- expect(autocorrected).to eql(good)
+ expect_no_offenses(code)
end
end
- shared_examples 'no autocorrect' do |code|
+ shared_examples 'offense with no autocorrect' do |code|
it 'does not autocorrect' do
- autocorrected = autocorrect_source(code, source_file)
+ expect_offense(<<~CODE, node: code)
+ %{node}
+ ^{node} [...]
+ CODE
- expect(autocorrected).to eql(code)
+ expect_no_corrections
end
end
@@ -64,10 +56,8 @@ RSpec.describe RuboCop::Cop::RSpec::HaveGitlabHttpStatus do
end
with_them do
- include_examples 'offense', params[:bad]
+ include_examples 'offense', params[:bad], params[:good]
include_examples 'no offense', params[:good]
- include_examples 'autocorrect', params[:bad], params[:good]
- include_examples 'no autocorrect', params[:good]
end
end
@@ -77,10 +67,8 @@ RSpec.describe RuboCop::Cop::RSpec::HaveGitlabHttpStatus do
end
with_them do
- include_examples 'offense', params[:bad]
- include_examples 'offense', params[:good]
- include_examples 'autocorrect', params[:bad], params[:good]
- include_examples 'no autocorrect', params[:good]
+ include_examples 'offense', params[:bad], params[:good]
+ include_examples 'offense with no autocorrect', params[:good]
end
end
@@ -114,7 +102,6 @@ RSpec.describe RuboCop::Cop::RSpec::HaveGitlabHttpStatus do
with_them do
include_examples 'no offense', params[:code]
- include_examples 'no autocorrect', params[:code]
end
end
end
diff --git a/spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb b/spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb
index 6e9e436602c..eac6ceb3ddf 100644
--- a/spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb
+++ b/spec/rubocop/cop/rspec/htt_party_basic_auth_spec.rb
@@ -5,12 +5,10 @@ require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/rspec/httparty_basic_auth'
RSpec.describe RuboCop::Cop::RSpec::HTTPartyBasicAuth do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when passing `basic_auth: { user: ... }`' do
- it 'registers an offence' do
+ it 'registers an offense and corrects', :aggregate_failures do
expect_offense(<<~SOURCE, 'spec/foo.rb')
HTTParty.put(
url,
@@ -19,17 +17,19 @@ RSpec.describe RuboCop::Cop::RSpec::HTTPartyBasicAuth do
body: body
)
SOURCE
- end
- it 'can autocorrect the source' do
- bad = 'HTTParty.put(url, basic_auth: { user: user, password: token })'
- good = 'HTTParty.put(url, basic_auth: { username: user, password: token })'
- expect(autocorrect_source(bad)).to eq(good)
+ expect_correction(<<~SOURCE)
+ HTTParty.put(
+ url,
+ basic_auth: { username: user, password: token },
+ body: body
+ )
+ SOURCE
end
end
context 'when passing `basic_auth: { username: ... }`' do
- it 'does not register an offence' do
+ it 'does not register an offense' do
expect_no_offenses(<<~SOURCE, 'spec/frontend/fixtures/foo.rb')
HTTParty.put(
url,
diff --git a/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb b/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb
index d9e3ca5741c..ffabbae90dc 100644
--- a/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb
+++ b/spec/rubocop/cop/rspec/modify_sidekiq_middleware_spec.rb
@@ -5,33 +5,20 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/modify_sidekiq_middleware'
RSpec.describe RuboCop::Cop::RSpec::ModifySidekiqMiddleware do
- include CopHelper
-
subject(:cop) { described_class.new }
- let(:source) do
- <<~SRC
- Sidekiq::Testing.server_middleware do |chain|
- chain.add(MyCustomMiddleware)
- end
- SRC
- end
-
- let(:corrected) do
- <<~SRC
- with_sidekiq_server_middleware do |chain|
- chain.add(MyCustomMiddleware)
- end
- SRC
- end
-
- it 'registers an offence' do
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- end
-
- it 'can autocorrect the source' do
- expect(autocorrect_source(source)).to eq(corrected)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(<<~CODE)
+ Sidekiq::Testing.server_middleware do |chain|
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't modify global sidekiq middleware, [...]
+ chain.add(MyCustomMiddleware)
+ end
+ CODE
+
+ expect_correction(<<~CODE)
+ with_sidekiq_server_middleware do |chain|
+ chain.add(MyCustomMiddleware)
+ end
+ CODE
end
end
diff --git a/spec/rubocop/cop/rspec/timecop_freeze_spec.rb b/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
index b1cf82492e4..939623f8299 100644
--- a/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
+++ b/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
@@ -3,50 +3,29 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../../rubocop/cop/rspec/timecop_freeze'
RSpec.describe RuboCop::Cop::RSpec::TimecopFreeze do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when calling Timecop.freeze' do
- let(:source) do
- <<~SRC
- Timecop.freeze(Time.current) { example.run }
- SRC
- end
-
- let(:corrected_source) do
- <<~SRC
- freeze_time(Time.current) { example.run }
- SRC
- end
-
- it 'registers an offence' do
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- end
-
- it 'can autocorrect the source' do
- expect(autocorrect_source(source)).to eq(corrected_source)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(<<~CODE)
+ Timecop.freeze(Time.current) { example.run }
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use `Timecop.freeze`, use `freeze_time` instead. [...]
+ CODE
+
+ expect_correction(<<~CODE)
+ freeze_time(Time.current) { example.run }
+ CODE
end
end
context 'when calling a different method on Timecop' do
- let(:source) do
- <<~SRC
- Timecop.travel(Time.current)
- SRC
- end
-
- it 'does not register an offence' do
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense' do
+ expect_no_offenses(<<~CODE)
+ Timecop.travel(Time.current)
+ CODE
end
end
end
diff --git a/spec/rubocop/cop/rspec/timecop_travel_spec.rb b/spec/rubocop/cop/rspec/timecop_travel_spec.rb
index 2ee8bfe9ad7..476e45e69a6 100644
--- a/spec/rubocop/cop/rspec/timecop_travel_spec.rb
+++ b/spec/rubocop/cop/rspec/timecop_travel_spec.rb
@@ -3,50 +3,29 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
-
require_relative '../../../../rubocop/cop/rspec/timecop_travel'
RSpec.describe RuboCop::Cop::RSpec::TimecopTravel do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when calling Timecop.travel' do
- let(:source) do
- <<~SRC
- Timecop.travel(1.day.ago) { create(:issue) }
- SRC
- end
-
- let(:corrected_source) do
- <<~SRC
- travel_to(1.day.ago) { create(:issue) }
- SRC
- end
-
- it 'registers an offence' do
- inspect_source(source)
-
- expect(cop.offenses.size).to eq(1)
- end
-
- it 'can autocorrect the source' do
- expect(autocorrect_source(source)).to eq(corrected_source)
+ it 'registers an offense and corrects', :aggregate_failures do
+ expect_offense(<<~CODE)
+ Timecop.travel(1.day.ago) { create(:issue) }
+ ^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use `Timecop.travel`, use `travel_to` instead. [...]
+ CODE
+
+ expect_correction(<<~CODE)
+ travel_to(1.day.ago) { create(:issue) }
+ CODE
end
end
context 'when calling a different method on Timecop' do
- let(:source) do
- <<~SRC
- Timecop.freeze { create(:issue) }
- SRC
- end
-
- it 'does not register an offence' do
- inspect_source(source)
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense' do
+ expect_no_offenses(<<~CODE)
+ Timecop.freeze { create(:issue) }
+ CODE
end
end
end
diff --git a/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb b/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
index 4936936836d..23531cd0201 100644
--- a/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
+++ b/spec/rubocop/cop/rspec/top_level_describe_path_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/rspec/top_level_describe_path'
RSpec.describe RuboCop::Cop::RSpec::TopLevelDescribePath do
- include CopHelper
-
subject(:cop) { described_class.new }
context 'when the file ends in _spec.rb' do
diff --git a/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb b/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb
index a6a44b3fa68..cacf0a1b67d 100644
--- a/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb
+++ b/spec/rubocop/cop/ruby_interpolation_in_translation_spec.rb
@@ -1,68 +1,51 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/ruby_interpolation_in_translation'
# Disabling interpolation check as we deliberately want to have #{} in strings.
# rubocop:disable Lint/InterpolationCheck
RSpec.describe RuboCop::Cop::RubyInterpolationInTranslation do
- subject(:cop) { described_class.new }
+ let(:msg) { "Don't use ruby interpolation \#{} inside translated strings, instead use %{}" }
- it 'does not add an offence for a regular messages' do
- inspect_source('_("Hello world")')
+ subject(:cop) { described_class.new }
- expect(cop.offenses).to be_empty
+ it 'does not add an offense for a regular messages' do
+ expect_no_offenses('_("Hello world")')
end
- it 'adds the correct offence when using interpolation in a string' do
- inspect_source('_("Hello #{world}")')
-
- offense = cop.offenses.first
-
- expect(offense.location.source).to eq('#{world}')
- expect(offense.message).to eq('Don\'t use ruby interpolation #{} inside translated strings, instead use %{}')
+ it 'adds the correct offense when using interpolation in a string' do
+ expect_offense(<<~CODE)
+ _("Hello \#{world}")
+ ^^^^^ #{msg}
+ ^^^^^^^^ #{msg}
+ CODE
end
it 'detects when using a ruby interpolation in the first argument of a pluralized string' do
- inspect_source('n_("Hello #{world}", "Hello world")')
-
- expect(cop.offenses).not_to be_empty
+ expect_offense(<<~CODE)
+ n_("Hello \#{world}", "Hello world")
+ ^^^^^ #{msg}
+ ^^^^^^^^ #{msg}
+ CODE
end
it 'detects when using a ruby interpolation in the second argument of a pluralized string' do
- inspect_source('n_("Hello world", "Hello #{world}")')
-
- expect(cop.offenses).not_to be_empty
+ expect_offense(<<~CODE)
+ n_("Hello world", "Hello \#{world}")
+ ^^^^^ #{msg}
+ ^^^^^^^^ #{msg}
+ CODE
end
it 'detects when using interpolation in a namespaced translation' do
- inspect_source('s_("Hello|#{world}")')
-
- expect(cop.offenses).not_to be_empty
- end
-
- it 'does not add an offence for messages defined over multiple lines' do
- source = <<~SRC
- _("Hello "\
- "world ")
- SRC
-
- inspect_source(source)
- expect(cop.offenses).to be_empty
- end
-
- it 'adds an offence for violations in a message defined over multiple lines' do
- source = <<~SRC
- _("Hello "\
- "\#{world} ")
- SRC
-
- inspect_source(source)
- expect(cop.offenses).not_to be_empty
+ expect_offense(<<~CODE)
+ s_("Hello|\#{world}")
+ ^^^^^ #{msg}
+ ^^^^^^^^ #{msg}
+ CODE
end
end
# rubocop:enable Lint/InterpolationCheck
diff --git a/spec/rubocop/cop/safe_params_spec.rb b/spec/rubocop/cop/safe_params_spec.rb
index c8f6768c4bb..62f8e542d86 100644
--- a/spec/rubocop/cop/safe_params_spec.rb
+++ b/spec/rubocop/cop/safe_params_spec.rb
@@ -2,12 +2,9 @@
require 'fast_spec_helper'
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/safe_params'
RSpec.describe RuboCop::Cop::SafeParams do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'flags the params as an argument of url_for' do
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 6e526f7ad8f..a19ddf9dbe6 100644
--- a/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
+++ b/spec/rubocop/cop/scalability/bulk_perform_with_context_spec.rb
@@ -5,54 +5,44 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/bulk_perform_with_context'
RSpec.describe RuboCop::Cop::Scalability::BulkPerformWithContext do
- include CopHelper
-
subject(:cop) { described_class.new }
it "adds an offense when calling bulk_perform_async" do
- inspect_source(<<~CODE)
+ expect_offense(<<~CODE)
Worker.bulk_perform_async(args)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `Worker.bulk_perform_async_with_contexts` [...]
CODE
-
- expect(cop.offenses.size).to eq(1)
end
it "adds an offense when calling bulk_perform_in" do
- inspect_source(<<~CODE)
+ expect_offense(<<~CODE)
diffs.each_batch(of: BATCH_SIZE) do |relation, index|
ids = relation.pluck_primary_key.map { |id| [id] }
DeleteDiffFilesWorker.bulk_perform_in(index * 5.minutes, ids)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `Worker.bulk_perform_async_with_contexts` [...]
end
CODE
-
- expect(cop.offenses.size).to eq(1)
end
it "does not add an offense for migrations" do
allow(cop).to receive(:in_migration?).and_return(true)
- inspect_source(<<~CODE)
+ expect_no_offenses(<<~CODE)
Worker.bulk_perform_in(args)
CODE
-
- expect(cop.offenses.size).to eq(0)
end
it "does not add an offence for specs" do
allow(cop).to receive(:in_spec?).and_return(true)
- inspect_source(<<~CODE)
+ expect_no_offenses(<<~CODE)
Worker.bulk_perform_in(args)
CODE
-
- expect(cop.offenses.size).to eq(0)
end
it "does not add an offense for scheduling BackgroundMigrations" do
- inspect_source(<<~CODE)
+ expect_no_offenses(<<~CODE)
BackgroundMigrationWorker.bulk_perform_in(args)
CODE
-
- expect(cop.offenses.size).to eq(0)
end
end
diff --git a/spec/rubocop/cop/scalability/cron_worker_context_spec.rb b/spec/rubocop/cop/scalability/cron_worker_context_spec.rb
index 4699e06e9cf..11b2b82d2f5 100644
--- a/spec/rubocop/cop/scalability/cron_worker_context_spec.rb
+++ b/spec/rubocop/cop/scalability/cron_worker_context_spec.rb
@@ -5,18 +5,15 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/cron_worker_context'
RSpec.describe RuboCop::Cop::Scalability::CronWorkerContext do
- include CopHelper
-
subject(:cop) { described_class.new }
it 'adds an offense when including CronjobQueue' do
- inspect_source(<<~CODE)
+ expect_offense(<<~CODE)
class SomeWorker
include CronjobQueue
+ ^^^^^^^^^^^^ Manually define an ApplicationContext for cronjob-workers.[...]
end
CODE
-
- expect(cop.offenses.size).to eq(1)
end
it 'does not add offenses for other workers' do
diff --git a/spec/rubocop/cop/scalability/file_uploads_spec.rb b/spec/rubocop/cop/scalability/file_uploads_spec.rb
index 78ff7fea55c..bda5c056b03 100644
--- a/spec/rubocop/cop/scalability/file_uploads_spec.rb
+++ b/spec/rubocop/cop/scalability/file_uploads_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/file_uploads'
RSpec.describe RuboCop::Cop::Scalability::FileUploads do
- include CopHelper
-
subject(:cop) { described_class.new }
let(:message) { 'Do not upload files without workhorse acceleration. Please refer to https://docs.gitlab.com/ee/development/uploads.html' }
diff --git a/spec/rubocop/cop/scalability/idempotent_worker_spec.rb b/spec/rubocop/cop/scalability/idempotent_worker_spec.rb
index 666122a9de4..729f2613697 100644
--- a/spec/rubocop/cop/scalability/idempotent_worker_spec.rb
+++ b/spec/rubocop/cop/scalability/idempotent_worker_spec.rb
@@ -5,8 +5,6 @@ require 'rubocop'
require_relative '../../../../rubocop/cop/scalability/idempotent_worker'
RSpec.describe RuboCop::Cop::Scalability::IdempotentWorker do
- include CopHelper
-
subject(:cop) { described_class.new }
before do
@@ -16,21 +14,18 @@ RSpec.describe RuboCop::Cop::Scalability::IdempotentWorker do
end
it 'adds an offense when not defining idempotent method' do
- inspect_source(<<~CODE)
+ expect_offense(<<~CODE)
class SomeWorker
+ ^^^^^^^^^^^^^^^^ Avoid adding not idempotent workers.[...]
end
CODE
-
- expect(cop.offenses.size).to eq(1)
end
it 'adds an offense when not defining idempotent method' do
- inspect_source(<<~CODE)
+ expect_no_offenses(<<~CODE)
class SomeWorker
idempotent!
end
CODE
-
- expect(cop.offenses.size).to be_zero
end
end
diff --git a/spec/rubocop/cop/static_translation_definition_spec.rb b/spec/rubocop/cop/static_translation_definition_spec.rb
index 8a38a318999..8656b07a6e4 100644
--- a/spec/rubocop/cop/static_translation_definition_spec.rb
+++ b/spec/rubocop/cop/static_translation_definition_spec.rb
@@ -8,78 +8,76 @@ require 'rspec-parameterized'
require_relative '../../../rubocop/cop/static_translation_definition'
RSpec.describe RuboCop::Cop::StaticTranslationDefinition do
- include CopHelper
-
using RSpec::Parameterized::TableSyntax
+ let(:msg) do
+ "The text you're translating will be already in the translated form when it's assigned to the constant. " \
+ "When a users changes the locale, these texts won't be translated again. " \
+ "Consider moving the translation logic to a method."
+ end
+
subject(:cop) { described_class.new }
- shared_examples 'offense' do |code, highlight, line|
+ shared_examples 'offense' do |code|
it 'registers an offense' do
- inspect_source(code)
-
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([line])
- expect(cop.highlights).to eq([highlight])
+ expect_offense(code)
end
end
shared_examples 'no offense' do |code|
it 'does not register an offense' do
- inspect_source(code)
-
- expect(cop.offenses).to be_empty
+ expect_no_offenses(code)
end
end
describe 'offenses' do
- where(:code, :highlight, :line) do
+ where(:code) do
[
- ['A = _("a")', '_("a")', 1],
- ['B = s_("b")', 's_("b")', 1],
- ['C = n_("c")', 'n_("c")', 1],
- [
- <<~CODE,
- class MyClass
- def self.translations
- @cache ||= { hello: _("hello") }
- end
+ <<~CODE,
+ A = _("a")
+ ^^^^^^ #{msg}
+ CODE
+ <<~CODE,
+ B = s_("b")
+ ^^^^^^^ #{msg}
+ CODE
+ <<~CODE,
+ C = n_("c")
+ ^^^^^^^ #{msg}
+ CODE
+ <<~CODE,
+ class MyClass
+ def self.translations
+ @cache ||= { hello: _("hello") }
+ ^^^^^^^^^^ #{msg}
end
- CODE
- '_("hello")',
- 3
- ],
- [
- <<~CODE,
- module MyModule
- A = {
- b: {
- c: _("a")
- }
+ end
+ CODE
+ <<~CODE,
+ module MyModule
+ A = {
+ b: {
+ c: _("a")
+ ^^^^^^ #{msg}
}
- end
- CODE
- '_("a")',
- 4
- ],
- [
- <<~CODE,
- class MyClass
- B = [
- [
- s_("a")
- ]
+ }
+ end
+ CODE
+ <<~CODE
+ class MyClass
+ B = [
+ [
+ s_("a")
+ ^^^^^^^ #{msg}
]
- end
- CODE
- 's_("a")',
- 4
- ]
+ ]
+ end
+ CODE
]
end
with_them do
- include_examples 'offense', params[:code], params[:highlight], params[:line]
+ include_examples 'offense', params[:code]
end
end
diff --git a/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb
index 1c90df798a5..b6711effe9e 100644
--- a/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb
+++ b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb
@@ -1,17 +1,13 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/usage_data/distinct_count_by_large_foreign_key'
RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey do
- include CopHelper
-
let(:allowed_foreign_keys) { [:author_id, :user_id, :'merge_requests.target_project_id'] }
-
+ let(:msg) { 'Avoid doing `distinct_count` on foreign keys for large tables having above 100 million rows.' }
let(:config) do
RuboCop::Config.new('UsageData/DistinctCountByLargeForeignKey' => {
'AllowedForeignKeys' => allowed_foreign_keys
@@ -21,36 +17,32 @@ RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey do
subject(:cop) { described_class.new(config) }
context 'when counting by disallowed key' do
- it 'registers an offence' do
- inspect_source('distinct_count(Issue, :creator_id)')
-
- expect(cop.offenses.size).to eq(1)
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ distinct_count(Issue, :creator_id)
+ ^^^^^^^^^^^^^^ #{msg}
+ CODE
end
- it 'does not register an offence when batch is false' do
- inspect_source('distinct_count(Issue, :creator_id, batch: false)')
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense when batch is false' do
+ expect_no_offenses('distinct_count(Issue, :creator_id, batch: false)')
end
- it 'register an offence when batch is true' do
- inspect_source('distinct_count(Issue, :creator_id, batch: true)')
-
- expect(cop.offenses.size).to eq(1)
+ it 'registers an offense when batch is true' do
+ expect_offense(<<~CODE)
+ distinct_count(Issue, :creator_id, batch: true)
+ ^^^^^^^^^^^^^^ #{msg}
+ CODE
end
end
context 'when calling by allowed key' do
- it 'does not register an offence with symbol' do
- inspect_source('distinct_count(Issue, :author_id)')
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense with symbol' do
+ expect_no_offenses('distinct_count(Issue, :author_id)')
end
- it 'does not register an offence with string' do
- inspect_source("distinct_count(Issue, 'merge_requests.target_project_id')")
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense with string' do
+ expect_no_offenses("distinct_count(Issue, 'merge_requests.target_project_id')")
end
end
end
diff --git a/spec/rubocop/cop/usage_data/large_table_spec.rb b/spec/rubocop/cop/usage_data/large_table_spec.rb
index 638e8c67dc8..26bd4e61625 100644
--- a/spec/rubocop/cop/usage_data/large_table_spec.rb
+++ b/spec/rubocop/cop/usage_data/large_table_spec.rb
@@ -1,18 +1,15 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-
require 'rubocop'
-require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/usage_data/large_table'
RSpec.describe RuboCop::Cop::UsageData::LargeTable do
- include CopHelper
-
let(:large_tables) { %i[Rails Time] }
let(:count_methods) { %i[count distinct_count] }
let(:allowed_methods) { %i[minimum maximum] }
+ let(:msg) { 'Use one of the count, distinct_count methods for counting on' }
let(:config) do
RuboCop::Config.new('UsageData/LargeTable' => {
@@ -31,59 +28,54 @@ RSpec.describe RuboCop::Cop::UsageData::LargeTable do
context 'with large tables' do
context 'when calling Issue.count' do
- it 'register an offence' do
- inspect_source('Issue.count')
-
- expect(cop.offenses.size).to eq(1)
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ Issue.count
+ ^^^^^^^^^^^ #{msg} Issue
+ CODE
end
end
context 'when calling Issue.active.count' do
- it 'register an offence' do
- inspect_source('Issue.active.count')
-
- expect(cop.offenses.size).to eq(1)
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ Issue.active.count
+ ^^^^^^^^^^^^ #{msg} Issue
+ CODE
end
end
context 'when calling count(Issue)' do
- it 'does not register an offence' do
- inspect_source('count(Issue)')
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense' do
+ expect_no_offenses('count(Issue)')
end
end
context 'when calling count(Ci::Build.active)' do
- it 'does not register an offence' do
- inspect_source('count(Ci::Build.active)')
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense' do
+ expect_no_offenses('count(Ci::Build.active)')
end
end
context 'when calling Ci::Build.active.count' do
- it 'register an offence' do
- inspect_source('Ci::Build.active.count')
-
- expect(cop.offenses.size).to eq(1)
+ it 'registers an offense' do
+ expect_offense(<<~CODE)
+ Ci::Build.active.count
+ ^^^^^^^^^^^^^^^^ #{msg} Ci::Build
+ CODE
end
end
context 'when using allowed methods' do
- it 'does not register an offence' do
- inspect_source('Issue.minimum')
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense' do
+ expect_no_offenses('Issue.minimum')
end
end
end
context 'with non related class' do
- it 'does not register an offence' do
- inspect_source('Rails.count')
-
- expect(cop.offenses).to be_empty
+ it 'does not register an offense' do
+ expect_no_offenses('Rails.count')
end
end
end
diff --git a/spec/rubocop/qa_helpers_spec.rb b/spec/rubocop/qa_helpers_spec.rb
index 051817903a8..cf6d2f1a845 100644
--- a/spec/rubocop/qa_helpers_spec.rb
+++ b/spec/rubocop/qa_helpers_spec.rb
@@ -6,7 +6,7 @@ require 'parser/current'
require_relative '../../rubocop/qa_helpers'
RSpec.describe RuboCop::QAHelpers do
- def parse_source(source, path = 'foo.rb')
+ def build_and_parse_source(source, path = 'foo.rb')
buffer = Parser::Source::Buffer.new(path)
buffer.source = source
@@ -24,13 +24,13 @@ RSpec.describe RuboCop::QAHelpers do
describe '#in_qa_file?' do
it 'returns true for a node in the qa/ directory' do
- node = parse_source('10', rails_root_join('qa', 'qa', 'page', 'dashboard', 'groups.rb'))
+ node = build_and_parse_source('10', rails_root_join('qa', 'qa', 'page', 'dashboard', 'groups.rb'))
expect(cop.in_qa_file?(node)).to eq(true)
end
it 'returns false for a node outside the qa/ directory' do
- node = parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
expect(cop.in_qa_file?(node)).to eq(false)
end
diff --git a/spec/serializers/admin/user_entity_spec.rb b/spec/serializers/admin/user_entity_spec.rb
index 7db49af09c3..42efe0eec54 100644
--- a/spec/serializers/admin/user_entity_spec.rb
+++ b/spec/serializers/admin/user_entity_spec.rb
@@ -22,6 +22,7 @@ RSpec.describe Admin::UserEntity do
:username,
:last_activity_on,
:avatar_url,
+ :note,
:badges,
:projects_count,
:actions
diff --git a/spec/serializers/admin/user_serializer_spec.rb b/spec/serializers/admin/user_serializer_spec.rb
index 719a90384c6..53a9457409c 100644
--- a/spec/serializers/admin/user_serializer_spec.rb
+++ b/spec/serializers/admin/user_serializer_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe Admin::UserSerializer do
:username,
:last_activity_on,
:avatar_url,
+ :note,
:badges,
:projects_count,
:actions
diff --git a/spec/serializers/ci/codequality_mr_diff_entity_spec.rb b/spec/serializers/ci/codequality_mr_diff_entity_spec.rb
new file mode 100644
index 00000000000..82708908d95
--- /dev/null
+++ b/spec/serializers/ci/codequality_mr_diff_entity_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CodequalityMrDiffEntity do
+ let(:entity) { described_class.new(mr_diff_report) }
+ let(:mr_diff_report) { Gitlab::Ci::Reports::CodequalityMrDiff.new(codequality_report) }
+ let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
+
+ describe '#as_json' do
+ subject(:report) { entity.as_json }
+
+ context 'when quality report has degradations' do
+ before do
+ codequality_report.add_degradation(degradation_1)
+ codequality_report.add_degradation(degradation_2)
+ end
+
+ it 'contains correct codequality mr diff report', :aggregate_failures do
+ expect(report[:files].keys).to eq(["file_a.rb"])
+ expect(report[:files]["file_a.rb"].first).to include(:line, :description, :severity)
+ end
+ end
+ end
+end
diff --git a/spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb b/spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb
new file mode 100644
index 00000000000..906ca36041f
--- /dev/null
+++ b/spec/serializers/ci/codequality_mr_diff_report_serializer_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CodequalityMrDiffReportSerializer do
+ let(:serializer) { described_class.new.represent(mr_diff_report) }
+ let(:mr_diff_report) { Gitlab::Ci::Reports::CodequalityMrDiff.new(codequality_report) }
+ let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
+
+ describe '#to_json' do
+ subject { serializer.as_json }
+
+ context 'when quality report has degradations' do
+ before do
+ codequality_report.add_degradation(degradation_1)
+ codequality_report.add_degradation(degradation_2)
+ end
+
+ it 'matches the schema' do
+ expect(subject).to match_schema('entities/codequality_mr_diff_report')
+ end
+ end
+
+ context 'when quality report has no degradations' do
+ it 'matches the schema' do
+ expect(subject).to match_schema('entities/codequality_mr_diff_report')
+ end
+ end
+ end
+end
diff --git a/spec/serializers/ci/dag_pipeline_entity_spec.rb b/spec/serializers/ci/dag_pipeline_entity_spec.rb
index e1703b09f97..fdc2f5e1a04 100644
--- a/spec/serializers/ci/dag_pipeline_entity_spec.rb
+++ b/spec/serializers/ci/dag_pipeline_entity_spec.rb
@@ -73,11 +73,11 @@ RSpec.describe Ci::DagPipelineEntity do
end
end
- it 'performs the smallest number of queries' do
+ it 'performs the smallest number of queries', :request_store do
log = ActiveRecord::QueryRecorder.new { subject }
- # stages, project, builds, build_needs
- expect(log.count).to eq 4
+ # stages, project, builds, build_needs, feature_flag
+ expect(log.count).to eq 5
end
it 'contains all the data' do
diff --git a/spec/serializers/ci/pipeline_entity_spec.rb b/spec/serializers/ci/pipeline_entity_spec.rb
new file mode 100644
index 00000000000..6ce3cef5f44
--- /dev/null
+++ b/spec/serializers/ci/pipeline_entity_spec.rb
@@ -0,0 +1,261 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineEntity do
+ include Gitlab::Routing
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let(:request) { double('request', current_user: user) }
+ let(:entity) { described_class.represent(pipeline, request: request) }
+
+ describe '#as_json' do
+ subject { entity.as_json }
+
+ context 'when pipeline is empty' do
+ let(:pipeline) { create(:ci_empty_pipeline) }
+
+ it 'contains required fields' do
+ expect(subject).to include :id, :user, :path, :coverage, :source
+ expect(subject).to include :ref, :commit
+ expect(subject).to include :updated_at, :created_at
+ end
+
+ it 'excludes coverage data when disabled' do
+ entity = described_class
+ .represent(pipeline, request: request, disable_coverage: true)
+
+ expect(entity.as_json).not_to include(:coverage)
+ end
+
+ it 'contains details' do
+ expect(subject).to include :details
+ expect(subject[:details])
+ .to include :duration, :finished_at, :name
+ expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip
+ end
+
+ it 'contains flags' do
+ expect(subject).to include :flags
+ expect(subject[:flags])
+ .to include :stuck, :auto_devops, :yaml_errors,
+ :retryable, :cancelable, :merge_request
+ end
+ end
+
+ context 'when default branch not protected' do
+ before do
+ stub_not_protect_default_branch
+ end
+
+ context 'when pipeline is retryable' do
+ let_it_be(:pipeline) do
+ create(:ci_pipeline, status: :success, project: project)
+ end
+
+ before do
+ create(:ci_build, :failed, pipeline: pipeline)
+ end
+
+ it 'does not serialize stage builds' do
+ subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage|
+ expect(stage).not_to include(:groups, :latest_statuses, :retries)
+ end
+ end
+
+ context 'user has ability to retry pipeline' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'contains retry path' do
+ expect(subject[:retry_path]).to be_present
+ end
+ end
+
+ context 'user does not have ability to retry pipeline' do
+ it 'does not contain retry path' do
+ expect(subject).not_to have_key(:retry_path)
+ end
+ end
+ end
+
+ context 'when pipeline is cancelable' do
+ let_it_be(:pipeline) do
+ create(:ci_pipeline, status: :running, project: project)
+ end
+
+ before do
+ create(:ci_build, :pending, pipeline: pipeline)
+ end
+
+ it 'does not serialize stage builds' do
+ subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage|
+ expect(stage).not_to include(:groups, :latest_statuses, :retries)
+ end
+ end
+
+ context 'user has ability to cancel pipeline' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'contains cancel path' do
+ expect(subject[:cancel_path]).to be_present
+ end
+ end
+
+ context 'user does not have ability to cancel pipeline' do
+ it 'does not contain cancel path' do
+ expect(subject).not_to have_key(:cancel_path)
+ end
+ end
+ end
+ end
+
+ context 'delete path' do
+ context 'user has ability to delete pipeline' do
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ it 'contains delete path' do
+ expect(subject[:delete_path]).to be_present
+ end
+ end
+
+ context 'user does not have ability to delete pipeline' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ it 'does not contain delete path' do
+ expect(subject).not_to have_key(:delete_path)
+ end
+ end
+ end
+
+ context 'when pipeline ref is empty' do
+ let(:pipeline) { create(:ci_empty_pipeline) }
+
+ before do
+ allow(pipeline).to receive(:ref).and_return(nil)
+ end
+
+ it 'does not generate branch path' do
+ expect(subject[:ref][:path]).to be_nil
+ end
+ end
+
+ context 'when pipeline has a failure reason set' do
+ let(:pipeline) { create(:ci_empty_pipeline) }
+
+ before do
+ pipeline.drop!(:config_error)
+ end
+
+ it 'has a correct failure reason' do
+ expect(subject[:failure_reason])
+ .to eq 'CI/CD YAML configuration error!'
+ end
+ end
+
+ context 'when request has a project' do
+ before do
+ allow(request).to receive(:project).and_return(project)
+ end
+
+ context 'when pipeline is detached merge request pipeline' do
+ let_it_be(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
+ let(:project) { merge_request.target_project }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
+
+ it 'makes detached flag true' do
+ expect(subject[:flags][:detached_merge_request_pipeline]).to be_truthy
+ end
+
+ it 'does not expose source sha and target sha' do
+ expect(subject[:source_sha]).to be_nil
+ expect(subject[:target_sha]).to be_nil
+ end
+
+ context 'when user is a developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'has merge request information' do
+ expect(subject[:merge_request][:iid]).to eq(merge_request.iid)
+
+ expect(project_merge_request_path(project, merge_request))
+ .to include(subject[:merge_request][:path])
+
+ expect(subject[:merge_request][:title]).to eq(merge_request.title)
+
+ expect(subject[:merge_request][:source_branch])
+ .to eq(merge_request.source_branch)
+
+ expect(project_commits_path(project, merge_request.source_branch))
+ .to include(subject[:merge_request][:source_branch_path])
+
+ expect(subject[:merge_request][:target_branch])
+ .to eq(merge_request.target_branch)
+
+ expect(project_commits_path(project, merge_request.target_branch))
+ .to include(subject[:merge_request][:target_branch_path])
+ end
+ end
+
+ context 'when user is an external user' do
+ it 'has no merge request information' do
+ expect(subject[:merge_request]).to be_nil
+ end
+ end
+ end
+
+ context 'when pipeline is merge request pipeline' do
+ let_it_be(:merge_request) { create(:merge_request, :with_merge_request_pipeline, merge_sha: 'abc') }
+ let(:project) { merge_request.target_project }
+ let(:pipeline) { merge_request.pipelines_for_merge_request.first }
+
+ it 'makes detached flag false' do
+ expect(subject[:flags][:detached_merge_request_pipeline]).to be_falsy
+ end
+
+ it 'makes atached flag true' do
+ expect(subject[:flags][:merge_request_pipeline]).to be_truthy
+ end
+
+ it 'exposes source sha and target sha' do
+ expect(subject[:source_sha]).to be_present
+ expect(subject[:target_sha]).to be_present
+ end
+
+ it 'exposes merge request event type' do
+ expect(subject[:merge_request_event_type]).to be_present
+ end
+ end
+ end
+
+ context 'when pipeline has failed builds' do
+ let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
+ let_it_be(:build) { create(:ci_build, :success, pipeline: pipeline) }
+ let_it_be(:failed_1) { create(:ci_build, :failed, pipeline: pipeline) }
+ let_it_be(:failed_2) { create(:ci_build, :failed, pipeline: pipeline) }
+
+ context 'when the user can retry the pipeline' do
+ it 'exposes these failed builds' do
+ allow(entity).to receive(:can_retry?).and_return(true)
+
+ expect(subject[:failed_builds].map { |b| b[:id] }).to contain_exactly(failed_1.id, failed_2.id)
+ end
+ end
+
+ context 'when the user cannot retry the pipeline' do
+ it 'is nil' do
+ allow(entity).to receive(:can_retry?).and_return(false)
+
+ expect(subject[:failed_builds]).to be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/serializers/codequality_degradation_entity_spec.rb b/spec/serializers/codequality_degradation_entity_spec.rb
index fc969195e35..315f00baa72 100644
--- a/spec/serializers/codequality_degradation_entity_spec.rb
+++ b/spec/serializers/codequality_degradation_entity_spec.rb
@@ -10,77 +10,24 @@ RSpec.describe CodequalityDegradationEntity do
context 'when codequality contains an error' do
context 'when line is included in location' do
- let(:codequality_degradation) do
- {
- "categories": [
- "Complexity"
- ],
- "check_name": "argument_count",
- "content": {
- "body": ""
- },
- "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
- "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
- "location": {
- "path": "foo.rb",
- "lines": {
- "begin": 10,
- "end": 10
- }
- },
- "other_locations": [],
- "remediation_points": 900000,
- "severity": "major",
- "type": "issue",
- "engine_name": "structure"
- }.with_indifferent_access
- end
+ let(:codequality_degradation) { build(:codequality_degradation_2) }
it 'contains correct codequality degradation details', :aggregate_failures do
expect(subject[:description]).to eq("Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.")
expect(subject[:severity]).to eq("major")
- expect(subject[:file_path]).to eq("foo.rb")
+ expect(subject[:file_path]).to eq("file_a.rb")
expect(subject[:line]).to eq(10)
end
end
context 'when line is included in positions' do
- let(:codequality_degradation) do
- {
- "type": "Issue",
- "check_name": "Rubocop/Metrics/ParameterLists",
- "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
- "categories": [
- "Complexity"
- ],
- "remediation_points": 550000,
- "location": {
- "path": "foo.rb",
- "positions": {
- "begin": {
- "column": 24,
- "line": 14
- },
- "end": {
- "column": 49,
- "line": 14
- }
- }
- },
- "content": {
- "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
- },
- "engine_name": "rubocop",
- "fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
- "severity": "minor"
- }.with_indifferent_access
- end
+ let(:codequality_degradation) { build(:codequality_degradation_3) }
it 'contains correct codequality degradation details', :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("foo.rb")
- expect(subject[:line]).to eq(14)
+ expect(subject[:file_path]).to eq("file_b.rb")
+ expect(subject[:line]).to eq(10)
end
end
end
diff --git a/spec/serializers/codequality_reports_comparer_entity_spec.rb b/spec/serializers/codequality_reports_comparer_entity_spec.rb
index 7a79c30cc3f..3c74c20ca19 100644
--- a/spec/serializers/codequality_reports_comparer_entity_spec.rb
+++ b/spec/serializers/codequality_reports_comparer_entity_spec.rb
@@ -7,62 +7,8 @@ RSpec.describe CodequalityReportsComparerEntity do
let(:comparer) { Gitlab::Ci::Reports::CodequalityReportsComparer.new(base_report, head_report) }
let(:base_report) { Gitlab::Ci::Reports::CodequalityReports.new }
let(:head_report) { Gitlab::Ci::Reports::CodequalityReports.new }
- let(:degradation_1) do
- {
- "categories": [
- "Complexity"
- ],
- "check_name": "argument_count",
- "content": {
- "body": ""
- },
- "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
- "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
- "location": {
- "path": "foo.rb",
- "lines": {
- "begin": 10,
- "end": 10
- }
- },
- "other_locations": [],
- "remediation_points": 900000,
- "severity": "major",
- "type": "issue",
- "engine_name": "structure"
- }.with_indifferent_access
- end
-
- let(:degradation_2) do
- {
- "type": "Issue",
- "check_name": "Rubocop/Metrics/ParameterLists",
- "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
- "categories": [
- "Complexity"
- ],
- "remediation_points": 550000,
- "location": {
- "path": "foo.rb",
- "positions": {
- "begin": {
- "column": 14,
- "line": 10
- },
- "end": {
- "column": 39,
- "line": 10
- }
- }
- },
- "content": {
- "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
- },
- "engine_name": "rubocop",
- "fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
- "severity": "minor"
- }.with_indifferent_access
- end
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
describe '#as_json' do
subject { entity.as_json }
diff --git a/spec/serializers/codequality_reports_comparer_serializer_spec.rb b/spec/serializers/codequality_reports_comparer_serializer_spec.rb
index 3c47bfb6adc..50c8a69737c 100644
--- a/spec/serializers/codequality_reports_comparer_serializer_spec.rb
+++ b/spec/serializers/codequality_reports_comparer_serializer_spec.rb
@@ -8,62 +8,8 @@ RSpec.describe CodequalityReportsComparerSerializer do
let(:comparer) { Gitlab::Ci::Reports::CodequalityReportsComparer.new(base_report, head_report) }
let(:base_report) { Gitlab::Ci::Reports::CodequalityReports.new }
let(:head_report) { Gitlab::Ci::Reports::CodequalityReports.new }
- let(:degradation_1) do
- {
- "categories": [
- "Complexity"
- ],
- "check_name": "argument_count",
- "content": {
- "body": ""
- },
- "description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
- "fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
- "location": {
- "path": "foo.rb",
- "lines": {
- "begin": 10,
- "end": 10
- }
- },
- "other_locations": [],
- "remediation_points": 900000,
- "severity": "major",
- "type": "issue",
- "engine_name": "structure"
- }.with_indifferent_access
- end
-
- let(:degradation_2) do
- {
- "type": "Issue",
- "check_name": "Rubocop/Metrics/ParameterLists",
- "description": "Avoid parameter lists longer than 5 parameters. [12/5]",
- "categories": [
- "Complexity"
- ],
- "remediation_points": 550000,
- "location": {
- "path": "foo.rb",
- "positions": {
- "begin": {
- "column": 14,
- "line": 10
- },
- "end": {
- "column": 39,
- "line": 10
- }
- }
- },
- "content": {
- "body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
- },
- "engine_name": "rubocop",
- "fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
- "severity": "minor"
- }.with_indifferent_access
- end
+ let(:degradation_1) { build(:codequality_degradation_1) }
+ let(:degradation_2) { build(:codequality_degradation_2) }
describe '#to_json' do
subject { serializer.as_json }
diff --git a/spec/serializers/diff_file_metadata_entity_spec.rb b/spec/serializers/diff_file_metadata_entity_spec.rb
new file mode 100644
index 00000000000..3ce1ea49677
--- /dev/null
+++ b/spec/serializers/diff_file_metadata_entity_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DiffFileMetadataEntity do
+ let(:merge_request) { create(:merge_request_with_diffs) }
+ let(:raw_diff_file) { merge_request.merge_request_diff.diffs.raw_diff_files.first }
+ let(:entity) { described_class.new(raw_diff_file) }
+
+ context 'as json' do
+ subject { entity.as_json }
+
+ it 'exposes the expected fields' do
+ expect(subject.keys).to contain_exactly(
+ :added_lines,
+ :removed_lines,
+ :new_path,
+ :old_path,
+ :new_file,
+ :deleted_file,
+ :submodule,
+ :file_identifier_hash,
+ :file_hash
+ )
+ end
+ end
+end
diff --git a/spec/serializers/diffs_entity_spec.rb b/spec/serializers/diffs_entity_spec.rb
index 7569493573b..a7446f14745 100644
--- a/spec/serializers/diffs_entity_spec.rb
+++ b/spec/serializers/diffs_entity_spec.rb
@@ -3,10 +3,11 @@
require 'spec_helper'
RSpec.describe DiffsEntity do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
+
let(:request) { EntityRequest.new(project: project, current_user: user) }
- let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
let(:merge_request_diffs) { merge_request.merge_request_diffs }
let(:options) do
{ request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs }
@@ -30,6 +31,14 @@ RSpec.describe DiffsEntity do
)
end
+ context 'broken merge request' do
+ let(:merge_request) { create(:merge_request, :invalid, target_project: project, source_project: project) }
+
+ it 'renders without errors' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
context "when a commit_id is passed" do
let(:commits) { merge_request.commits }
let(:entity) do
diff --git a/spec/serializers/group_group_link_entity_spec.rb b/spec/serializers/group_group_link_entity_spec.rb
deleted file mode 100644
index 9affe4af381..00000000000
--- a/spec/serializers/group_group_link_entity_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GroupGroupLinkEntity do
- include_context 'group_group_link'
-
- let_it_be(:current_user) { create(:user) }
- let(:entity) { described_class.new(group_group_link) }
-
- before do
- allow(entity).to receive(:current_user).and_return(current_user)
- end
-
- it 'matches json schema' do
- expect(entity.to_json).to match_schema('entities/group_group_link')
- end
-
- context 'a user with :admin_group_member permissions' do
- before do
- allow(entity).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true)
- end
-
- it 'sets `can_update` and `can_remove` to `true`' do
- json = entity.as_json
-
- expect(json[:can_update]).to be true
- expect(json[:can_remove]).to be true
- end
- end
-end
diff --git a/spec/serializers/group_group_link_serializer_spec.rb b/spec/serializers/group_group_link_serializer_spec.rb
deleted file mode 100644
index 0d977ea0a9a..00000000000
--- a/spec/serializers/group_group_link_serializer_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GroupGroupLinkSerializer do
- include_context 'group_group_link'
-
- subject(:json) { described_class.new.represent(shared_group.shared_with_group_links).to_json }
-
- it 'matches json schema' do
- expect(json).to match_schema('group_group_links')
- end
-end
diff --git a/spec/serializers/group_link/group_group_link_entity_spec.rb b/spec/serializers/group_link/group_group_link_entity_spec.rb
new file mode 100644
index 00000000000..15bcbbcb1d6
--- /dev/null
+++ b/spec/serializers/group_link/group_group_link_entity_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupLink::GroupGroupLinkEntity do
+ include_context 'group_group_link'
+
+ let_it_be(:current_user) { create(:user) }
+ let(:entity) { described_class.new(group_group_link) }
+
+ before do
+ allow(entity).to receive(:current_user).and_return(current_user)
+ end
+
+ it 'matches json schema' do
+ expect(entity.to_json).to match_schema('group_link/group_group_link')
+ end
+
+ context 'when current user has `:admin_group_member` permissions' do
+ before do
+ allow(entity).to receive(:can?).with(current_user, :admin_group_member, shared_group).and_return(true)
+ end
+
+ it 'exposes `can_update` and `can_remove` as `true`' do
+ json = entity.as_json
+
+ expect(json[:can_update]).to be true
+ expect(json[:can_remove]).to be true
+ end
+ end
+end
diff --git a/spec/serializers/group_link/group_group_link_serializer_spec.rb b/spec/serializers/group_link/group_group_link_serializer_spec.rb
new file mode 100644
index 00000000000..a4ca32dae7b
--- /dev/null
+++ b/spec/serializers/group_link/group_group_link_serializer_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupLink::GroupGroupLinkSerializer do
+ include_context 'group_group_link'
+
+ subject(:json) { described_class.new.represent(shared_group.shared_with_group_links).to_json }
+
+ it 'matches json schema' do
+ expect(json).to match_schema('group_link/group_group_links')
+ end
+end
diff --git a/spec/serializers/group_link/group_link_entity_spec.rb b/spec/serializers/group_link/group_link_entity_spec.rb
new file mode 100644
index 00000000000..941445feaa2
--- /dev/null
+++ b/spec/serializers/group_link/group_link_entity_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupLink::GroupLinkEntity do
+ include_context 'group_group_link'
+
+ let(:entity) { described_class.new(group_group_link) }
+ let(:entity_hash) { entity.as_json }
+
+ it 'matches json schema' do
+ expect(entity.to_json).to match_schema('group_link/group_link')
+ end
+
+ it 'correctly exposes `valid_roles`' do
+ expect(entity_hash[:valid_roles]).to include(Gitlab::Access.options_with_owner)
+ end
+
+ it 'correctly exposes `shared_with_group.avatar_url`' do
+ avatar_url = 'https://gitlab.com/uploads/-/system/group/avatar/24/foobar.png?width=40'
+ allow(shared_with_group).to receive(:avatar_url).with(only_path: false, size: Member::AVATAR_SIZE).and_return(avatar_url)
+
+ expect(entity_hash[:shared_with_group][:avatar_url]).to match(avatar_url)
+ end
+end
diff --git a/spec/serializers/group_link/project_group_link_entity_spec.rb b/spec/serializers/group_link/project_group_link_entity_spec.rb
new file mode 100644
index 00000000000..0bb3d06933b
--- /dev/null
+++ b/spec/serializers/group_link/project_group_link_entity_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupLink::ProjectGroupLinkEntity do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project_group_link) { create(:project_group_link) }
+ let(:entity) { described_class.new(project_group_link) }
+
+ before do
+ allow(entity).to receive(:current_user).and_return(current_user)
+ end
+
+ it 'matches json schema' do
+ expect(entity.to_json).to match_schema('group_link/project_group_link')
+ end
+
+ context 'when current user has `admin_project_member` permissions' do
+ before do
+ allow(entity).to receive(:can?).with(current_user, :admin_project_member, project_group_link.project).and_return(true)
+ end
+
+ it 'exposes `can_update` and `can_remove` as `true`' do
+ json = entity.as_json
+
+ expect(json[:can_update]).to be true
+ expect(json[:can_remove]).to be true
+ end
+ end
+end
diff --git a/spec/serializers/group_link/project_group_link_serializer_spec.rb b/spec/serializers/group_link/project_group_link_serializer_spec.rb
new file mode 100644
index 00000000000..ecd5d4d70e4
--- /dev/null
+++ b/spec/serializers/group_link/project_group_link_serializer_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupLink::ProjectGroupLinkSerializer do
+ let_it_be(:project_group_links) { create_list(:project_group_link, 1) }
+
+ subject(:json) { described_class.new.represent(project_group_links).to_json }
+
+ it 'matches json schema' do
+ expect(json).to match_schema('group_link/project_group_links')
+ end
+end
diff --git a/spec/serializers/member_entity_spec.rb b/spec/serializers/member_entity_spec.rb
index f34434188c1..883cb511abc 100644
--- a/spec/serializers/member_entity_spec.rb
+++ b/spec/serializers/member_entity_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe MemberEntity do
let_it_be(:current_user) { create(:user) }
- let(:entity) { described_class.new(member, { current_user: current_user, group: group }) }
+ let(:entity) { described_class.new(member, { current_user: current_user, group: group, source: source }) }
let(:entity_hash) { entity.as_json }
shared_examples 'member.json' do
@@ -40,8 +40,27 @@ RSpec.describe MemberEntity do
end
end
+ shared_examples 'is_direct_member' do
+ context 'when `source` is the same as `member.source`' do
+ let(:source) { direct_member_source }
+
+ it 'exposes `is_direct_member` as `true`' do
+ expect(entity_hash[:is_direct_member]).to be(true)
+ end
+ end
+
+ context 'when `source` is not the same as `member.source`' do
+ let(:source) { inherited_member_source }
+
+ it 'exposes `is_direct_member` as `false`' do
+ expect(entity_hash[:is_direct_member]).to be(false)
+ end
+ end
+ end
+
context 'group member' do
let(:group) { create(:group) }
+ let(:source) { group }
let(:member) { GroupMemberPresenter.new(create(:group_member, group: group), current_user: current_user) }
it_behaves_like 'member.json'
@@ -52,11 +71,19 @@ RSpec.describe MemberEntity do
it_behaves_like 'member.json'
it_behaves_like 'invite'
end
+
+ context 'is_direct_member' do
+ let(:direct_member_source) { group }
+ let(:inherited_member_source) { create(:group) }
+
+ it_behaves_like 'is_direct_member'
+ end
end
context 'project member' do
let(:project) { create(:project) }
let(:group) { project.group }
+ let(:source) { project }
let(:member) { ProjectMemberPresenter.new(create(:project_member, project: project), current_user: current_user) }
it_behaves_like 'member.json'
@@ -67,5 +94,12 @@ RSpec.describe MemberEntity do
it_behaves_like 'member.json'
it_behaves_like 'invite'
end
+
+ context 'is_direct_member' do
+ let(:direct_member_source) { project }
+ let(:inherited_member_source) { group }
+
+ it_behaves_like 'is_direct_member'
+ end
end
end
diff --git a/spec/serializers/member_serializer_spec.rb b/spec/serializers/member_serializer_spec.rb
index d3ec45fe9c4..af209c0191f 100644
--- a/spec/serializers/member_serializer_spec.rb
+++ b/spec/serializers/member_serializer_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe MemberSerializer do
let_it_be(:current_user) { create(:user) }
- subject { described_class.new.represent(members, { current_user: current_user, group: group }) }
+ subject { described_class.new.represent(members, { current_user: current_user, group: group, source: source }) }
shared_examples 'members.json' do
it 'matches json schema' do
@@ -17,6 +17,7 @@ RSpec.describe MemberSerializer do
context 'group member' do
let(:group) { create(:group) }
+ let(:source) { group }
let(:members) { present_members(create_list(:group_member, 1, group: group)) }
it_behaves_like 'members.json'
@@ -24,6 +25,7 @@ RSpec.describe MemberSerializer do
context 'project member' do
let(:project) { create(:project) }
+ let(:source) { project }
let(:group) { project.group }
let(:members) { present_members(create_list(:project_member, 1, project: project)) }
diff --git a/spec/serializers/merge_request_basic_entity_spec.rb b/spec/serializers/merge_request_basic_entity_spec.rb
index 4a8bcd72d9c..7aa1f47fda5 100644
--- a/spec/serializers/merge_request_basic_entity_spec.rb
+++ b/spec/serializers/merge_request_basic_entity_spec.rb
@@ -20,23 +20,11 @@ RSpec.describe MergeRequestBasicEntity do
let(:params) { { reviewers: [reviewer] } }
let(:reviewer) { build(:user) }
- context 'when merge_request_reviewers feature is disabled' do
- it 'does not contain assignees attributes' do
- stub_feature_flags(merge_request_reviewers: false)
-
- expect(subject[:reviewers]).to be_nil
- end
- end
-
- context 'when merge_request_reviewers feature is enabled' do
- it 'contains reviewers attributes' do
- stub_feature_flags(merge_request_reviewers: true)
-
- expect(subject[:reviewers].count).to be 1
- expect(subject[:reviewers].first.keys).to include(
- :id, :name, :username, :state, :avatar_url, :web_url
- )
- end
+ it 'contains reviewers attributes' do
+ expect(subject[:reviewers].count).to be 1
+ expect(subject[:reviewers].first.keys).to include(
+ :id, :name, :username, :state, :avatar_url, :web_url
+ )
end
end
end
diff --git a/spec/serializers/merge_request_sidebar_extras_entity_spec.rb b/spec/serializers/merge_request_sidebar_extras_entity_spec.rb
index 74e9956c8a0..58f860097c2 100644
--- a/spec/serializers/merge_request_sidebar_extras_entity_spec.rb
+++ b/spec/serializers/merge_request_sidebar_extras_entity_spec.rb
@@ -35,23 +35,11 @@ RSpec.describe MergeRequestSidebarExtrasEntity do
end
describe '#reviewers' do
- context 'when merge_request_reviewers feature is disabled' do
- it 'does not contain reviewers attributes' do
- stub_feature_flags(merge_request_reviewers: false)
-
- expect(entity[:reviewers]).to be_nil
- end
- end
-
- context 'when merge_request_reviewers feature is enabled' do
- it 'contains reviewers attributes' do
- stub_feature_flags(merge_request_reviewers: true)
-
- expect(entity[:reviewers].count).to be 1
- expect(entity[:reviewers].first.keys).to include(
- :id, :name, :username, :state, :avatar_url, :web_url, :can_merge
- )
- end
+ it 'contains reviewers attributes' do
+ expect(entity[:reviewers].count).to be 1
+ expect(entity[:reviewers].first.keys).to include(
+ :id, :name, :username, :state, :avatar_url, :web_url, :can_merge
+ )
end
end
end
diff --git a/spec/serializers/merge_request_user_entity_spec.rb b/spec/serializers/merge_request_user_entity_spec.rb
index a2ad8e72845..dcd4ef6acfb 100644
--- a/spec/serializers/merge_request_user_entity_spec.rb
+++ b/spec/serializers/merge_request_user_entity_spec.rb
@@ -17,5 +17,23 @@ RSpec.describe MergeRequestUserEntity do
it 'exposes needed attributes' do
expect(subject).to include(:id, :name, :username, :state, :avatar_url, :web_url, :can_merge)
end
+
+ context 'when `status` is not preloaded' do
+ it 'does not expose the availability attribute' do
+ expect(subject).not_to include(:availability)
+ end
+ end
+
+ context 'when `status` is preloaded' do
+ before do
+ user.create_status!(availability: :busy)
+
+ user.status # make sure `status` is loaded
+ end
+
+ it 'exposes the availibility attribute' do
+ expect(subject[:availability]).to eq('busy')
+ end
+ end
end
end
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 42d843af596..926b33e8e1f 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe MergeRequestWidgetEntity do
end
describe 'codequality report artifacts', :request_store do
- let(:merge_base_pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
+ let(:merge_base_pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) }
before do
project.add_developer(user)
@@ -90,7 +90,7 @@ RSpec.describe MergeRequestWidgetEntity do
end
context 'with report artifacts' do
- let(:pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) }
let(:generic_job_id) { pipeline.builds.first.id }
let(:merge_base_job_id) { merge_base_pipeline.builds.first.id }
@@ -100,7 +100,7 @@ RSpec.describe MergeRequestWidgetEntity do
end
context 'on pipelines for merged results' do
- let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_codequality_report, project: project) }
+ let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_codequality_reports, project: project) }
it 'returns URLs from the head_pipeline and merge_base_pipeline' do
expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
diff --git a/spec/serializers/paginated_diff_entity_spec.rb b/spec/serializers/paginated_diff_entity_spec.rb
index 7090ce1f08d..a8ac89a8481 100644
--- a/spec/serializers/paginated_diff_entity_spec.rb
+++ b/spec/serializers/paginated_diff_entity_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe PaginatedDiffEntity do
let(:user) { create(:user) }
let(:request) { double('request', current_user: user) }
- let(:merge_request) { create(:merge_request, :with_diffs) }
+ let(:merge_request) { create(:merge_request) }
let(:diff_batch) { merge_request.merge_request_diff.diffs_in_batch(2, 3, diff_options: nil) }
let(:options) do
{
diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb
index 74e91cc9cdd..2f54f45866b 100644
--- a/spec/serializers/pipeline_details_entity_spec.rb
+++ b/spec/serializers/pipeline_details_entity_spec.rb
@@ -10,8 +10,8 @@ RSpec.describe PipelineDetailsEntity do
described_class.represent(pipeline, request: request)
end
- it 'inherrits from PipelineEntity' do
- expect(described_class).to be < PipelineEntity
+ it 'inherits from PipelineEntity' do
+ expect(described_class).to be < Ci::PipelineEntity
end
before do
diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb
deleted file mode 100644
index d7cd13edec8..00000000000
--- a/spec/serializers/pipeline_entity_spec.rb
+++ /dev/null
@@ -1,264 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe PipelineEntity do
- include Gitlab::Routing
-
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
- let(:request) { double('request') }
-
- before do
- stub_not_protect_default_branch
-
- allow(request).to receive(:current_user).and_return(user)
- allow(request).to receive(:project).and_return(project)
- end
-
- let(:entity) do
- described_class.represent(pipeline, request: request)
- end
-
- describe '#as_json' do
- subject { entity.as_json }
-
- context 'when pipeline is empty' do
- let(:pipeline) { create(:ci_empty_pipeline) }
-
- it 'contains required fields' do
- expect(subject).to include :id, :user, :path, :coverage, :source
- expect(subject).to include :ref, :commit
- expect(subject).to include :updated_at, :created_at
- end
-
- it 'excludes coverage data when disabled' do
- entity = described_class
- .represent(pipeline, request: request, disable_coverage: true)
-
- expect(entity.as_json).not_to include(:coverage)
- end
-
- it 'contains details' do
- expect(subject).to include :details
- expect(subject[:details])
- .to include :duration, :finished_at, :name
- expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip
- end
-
- it 'contains flags' do
- expect(subject).to include :flags
- expect(subject[:flags])
- .to include :stuck, :auto_devops, :yaml_errors,
- :retryable, :cancelable, :merge_request
- end
- end
-
- context 'when pipeline is retryable' do
- let(:project) { create(:project) }
-
- let(:pipeline) do
- create(:ci_pipeline, status: :success, project: project)
- end
-
- before do
- create(:ci_build, :failed, pipeline: pipeline)
- end
-
- it 'does not serialize stage builds' do
- subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage|
- expect(stage).not_to include(:groups, :latest_statuses, :retries)
- end
- end
-
- context 'user has ability to retry pipeline' do
- before do
- project.add_developer(user)
- end
-
- it 'contains retry path' do
- expect(subject[:retry_path]).to be_present
- end
- end
-
- context 'user does not have ability to retry pipeline' do
- it 'does not contain retry path' do
- expect(subject).not_to have_key(:retry_path)
- end
- end
- end
-
- context 'when pipeline is cancelable' do
- let(:project) { create(:project) }
-
- let(:pipeline) do
- create(:ci_pipeline, status: :running, project: project)
- end
-
- before do
- create(:ci_build, :pending, pipeline: pipeline)
- end
-
- it 'does not serialize stage builds' do
- subject.with_indifferent_access.dig(:details, :stages, 0).tap do |stage|
- expect(stage).not_to include(:groups, :latest_statuses, :retries)
- end
- end
-
- context 'user has ability to cancel pipeline' do
- before do
- project.add_developer(user)
- end
-
- it 'contains cancel path' do
- expect(subject[:cancel_path]).to be_present
- end
- end
-
- context 'user does not have ability to cancel pipeline' do
- it 'does not contain cancel path' do
- expect(subject).not_to have_key(:cancel_path)
- end
- end
- end
-
- context 'delete path' do
- context 'user has ability to delete pipeline' do
- let(:project) { create(:project, namespace: user.namespace) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
-
- it 'contains delete path' do
- expect(subject[:delete_path]).to be_present
- end
- end
-
- context 'user does not have ability to delete pipeline' do
- let(:project) { create(:project) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
-
- it 'does not contain delete path' do
- expect(subject).not_to have_key(:delete_path)
- end
- end
- end
-
- context 'when pipeline ref is empty' do
- let(:pipeline) { create(:ci_empty_pipeline) }
-
- before do
- allow(pipeline).to receive(:ref).and_return(nil)
- end
-
- it 'does not generate branch path' do
- expect(subject[:ref][:path]).to be_nil
- end
- end
-
- context 'when pipeline has a failure reason set' do
- let(:pipeline) { create(:ci_empty_pipeline) }
-
- before do
- pipeline.drop!(:config_error)
- end
-
- it 'has a correct failure reason' do
- expect(subject[:failure_reason])
- .to eq 'CI/CD YAML configuration error!'
- end
- end
-
- context 'when pipeline is detached merge request pipeline' do
- let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) }
- let(:project) { merge_request.target_project }
- let(:pipeline) { merge_request.pipelines_for_merge_request.first }
-
- it 'makes detached flag true' do
- expect(subject[:flags][:detached_merge_request_pipeline]).to be_truthy
- end
-
- it 'does not expose source sha and target sha' do
- expect(subject[:source_sha]).to be_nil
- expect(subject[:target_sha]).to be_nil
- end
-
- context 'when user is a developer' do
- before do
- project.add_developer(user)
- end
-
- it 'has merge request information' do
- expect(subject[:merge_request][:iid]).to eq(merge_request.iid)
-
- expect(project_merge_request_path(project, merge_request))
- .to include(subject[:merge_request][:path])
-
- expect(subject[:merge_request][:title]).to eq(merge_request.title)
-
- expect(subject[:merge_request][:source_branch])
- .to eq(merge_request.source_branch)
-
- expect(project_commits_path(project, merge_request.source_branch))
- .to include(subject[:merge_request][:source_branch_path])
-
- expect(subject[:merge_request][:target_branch])
- .to eq(merge_request.target_branch)
-
- expect(project_commits_path(project, merge_request.target_branch))
- .to include(subject[:merge_request][:target_branch_path])
- end
- end
-
- context 'when user is an external user' do
- it 'has no merge request information' do
- expect(subject[:merge_request]).to be_nil
- end
- end
- end
-
- context 'when pipeline is merge request pipeline' do
- let(:merge_request) { create(:merge_request, :with_merge_request_pipeline, merge_sha: 'abc') }
- let(:project) { merge_request.target_project }
- let(:pipeline) { merge_request.pipelines_for_merge_request.first }
-
- it 'makes detached flag false' do
- expect(subject[:flags][:detached_merge_request_pipeline]).to be_falsy
- end
-
- it 'makes atached flag true' do
- expect(subject[:flags][:merge_request_pipeline]).to be_truthy
- end
-
- it 'exposes source sha and target sha' do
- expect(subject[:source_sha]).to be_present
- expect(subject[:target_sha]).to be_present
- end
-
- it 'exposes merge request event type' do
- expect(subject[:merge_request_event_type]).to be_present
- end
- end
-
- context 'when pipeline has failed builds' do
- let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
- let_it_be(:build) { create(:ci_build, :success, pipeline: pipeline) }
- let_it_be(:failed_1) { create(:ci_build, :failed, pipeline: pipeline) }
- let_it_be(:failed_2) { create(:ci_build, :failed, pipeline: pipeline) }
-
- context 'when the user can retry the pipeline' do
- it 'exposes these failed builds' do
- allow(entity).to receive(:can_retry?).and_return(true)
-
- expect(subject[:failed_builds].map { |b| b[:id] }).to contain_exactly(failed_1.id, failed_2.id)
- end
- end
-
- context 'when the user cannot retry the pipeline' do
- it 'is nil' do
- allow(entity).to receive(:can_retry?).and_return(false)
-
- expect(subject[:failed_builds]).to be_nil
- end
- end
- end
- end
-end
diff --git a/spec/serializers/user_serializer_spec.rb b/spec/serializers/user_serializer_spec.rb
index d54f33b6a23..f2ef1508098 100644
--- a/spec/serializers/user_serializer_spec.rb
+++ b/spec/serializers/user_serializer_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe UserSerializer do
context 'serializer with merge request context' do
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.project }
- let(:serializer) { described_class.new(merge_request_iid: merge_request.iid) }
+ let(:serializer) { described_class.new(current_user: user1, merge_request_iid: merge_request.iid) }
before do
allow(project).to(
diff --git a/spec/services/alert_management/process_prometheus_alert_service_spec.rb b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
index 8f81c1967d5..288a33b71cd 100644
--- a/spec/services/alert_management/process_prometheus_alert_service_spec.rb
+++ b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
@@ -68,36 +68,29 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
it_behaves_like 'creates an alert management alert'
+ it_behaves_like 'Alert Notification Service sends notification email'
end
context 'existing alert is ignored' do
let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: fingerprint) }
it_behaves_like 'adds an alert management alert event'
+ it_behaves_like 'Alert Notification Service sends no notifications'
end
- context 'two existing alerts, one resolved one open' do
- let!(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
+ context 'existing alert is acknowledged' do
+ let!(:alert) { create(:alert_management_alert, :acknowledged, project: project, fingerprint: fingerprint) }
it_behaves_like 'adds an alert management alert event'
+ it_behaves_like 'Alert Notification Service sends no notifications'
end
- context 'when status change did not succeed' do
- before do
- allow(AlertManagement::Alert).to receive(:for_fingerprint).and_return([alert])
- allow(alert).to receive(:trigger).and_return(false)
- end
-
- it 'writes a warning to the log' do
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Unable to update AlertManagement::Alert status to triggered',
- project_id: project.id,
- alert_id: alert.id
- )
+ context 'two existing alerts, one resolved one open' do
+ let!(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
+ let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
- execute
- end
+ it_behaves_like 'adds an alert management alert event'
+ it_behaves_like 'Alert Notification Service sends notification email'
end
context 'when auto-creation of issues is disabled' do
@@ -109,11 +102,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when emails are disabled' do
let(:send_email) { false }
- it 'does not send notification' do
- expect(NotificationService).not_to receive(:new)
-
- expect(subject).to be_success
- end
+ it_behaves_like 'Alert Notification Service sends no notifications'
end
end
@@ -136,11 +125,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when emails are disabled' do
let(:send_email) { false }
- it 'does not send notification' do
- expect(NotificationService).not_to receive(:new)
-
- expect(subject).to be_success
- end
+ it_behaves_like 'Alert Notification Service sends no notifications'
end
end
@@ -158,7 +143,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
it 'writes a warning to the log' do
expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Unable to create AlertManagement::Alert',
+ message: 'Unable to create AlertManagement::Alert from Prometheus',
project_id: project.id,
alert_errors: { hosts: ['hosts array is over 255 chars'] }
)
@@ -235,11 +220,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when emails are disabled' do
let(:send_email) { false }
- it 'does not send notification' do
- expect(NotificationService).not_to receive(:new)
-
- expect(subject).to be_success
- end
+ it_behaves_like 'Alert Notification Service sends no notifications'
end
end
diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb
index 46483fede97..1352a595ba4 100644
--- a/spec/services/application_settings/update_service_spec.rb
+++ b/spec/services/application_settings/update_service_spec.rb
@@ -122,7 +122,7 @@ RSpec.describe ApplicationSettings::UpdateService do
it_behaves_like 'invalidates markdown cache', { asset_proxy_enabled: true }
it_behaves_like 'invalidates markdown cache', { asset_proxy_url: 'http://test.com' }
it_behaves_like 'invalidates markdown cache', { asset_proxy_secret_key: 'another secret' }
- it_behaves_like 'invalidates markdown cache', { asset_proxy_whitelist: ['domain.com'] }
+ it_behaves_like 'invalidates markdown cache', { asset_proxy_allowlist: ['domain.com'] }
context 'when also setting the local_markdown_version' do
let(:params) { { asset_proxy_enabled: true, local_markdown_version: 12 } }
diff --git a/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb b/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
index a4637b6ba1c..0c944cad40c 100644
--- a/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
+++ b/spec/services/authorized_project_update/recalculate_for_user_range_service_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe AuthorizedProjectUpdate::RecalculateForUserRangeService do
it 'calls Users::RefreshAuthorizedProjectsService' do
users.each do |user|
expect(Users::RefreshAuthorizedProjectsService).to(
- receive(:new).with(user).and_call_original)
+ receive(:new).with(user, source: described_class.name).and_call_original)
end
range = users.map(&:id).minmax
diff --git a/spec/services/boards/lists/create_service_spec.rb b/spec/services/boards/lists/create_service_spec.rb
index d639fdbb46a..cac26b3c88d 100644
--- a/spec/services/boards/lists/create_service_spec.rb
+++ b/spec/services/boards/lists/create_service_spec.rb
@@ -3,99 +3,23 @@
require 'spec_helper'
RSpec.describe Boards::Lists::CreateService do
- describe '#execute' do
- shared_examples 'creating board lists' do
- let_it_be(:user) { create(:user) }
+ context 'when board parent is a project' do
+ let_it_be(:parent) { create(:project) }
+ let_it_be(:board) { create(:board, project: parent) }
+ let_it_be(:label) { create(:label, project: parent, name: 'in-progress') }
- before_all do
- parent.add_developer(user)
- end
-
- subject(:service) { described_class.new(parent, user, label_id: label.id) }
-
- context 'when board lists is empty' do
- it 'creates a new list at beginning of the list' do
- response = service.execute(board)
-
- expect(response.success?).to eq(true)
- expect(response.payload[:list].position).to eq 0
- end
- end
-
- context 'when board lists has the done list' do
- it 'creates a new list at beginning of the list' do
- response = service.execute(board)
-
- expect(response.success?).to eq(true)
- expect(response.payload[:list].position).to eq 0
- end
- end
-
- context 'when board lists has labels lists' do
- it 'creates a new list at end of the lists' do
- create(:list, board: board, position: 0)
- create(:list, board: board, position: 1)
-
- response = service.execute(board)
-
- expect(response.success?).to eq(true)
- expect(response.payload[:list].position).to eq 2
- end
- end
-
- context 'when board lists has label and done lists' do
- it 'creates a new list at end of the label lists' do
- list1 = create(:list, board: board, position: 0)
-
- list2 = service.execute(board).payload[:list]
-
- expect(list1.reload.position).to eq 0
- expect(list2.reload.position).to eq 1
- end
- end
-
- context 'when provided label does not belong to the parent' do
- it 'returns an error' do
- label = create(:label, name: 'in-development')
- service = described_class.new(parent, user, label_id: label.id)
-
- response = service.execute(board)
-
- expect(response.success?).to eq(false)
- expect(response.errors).to include('Label not found')
- end
- end
-
- context 'when backlog param is sent' do
- it 'creates one and only one backlog list' do
- service = described_class.new(parent, user, 'backlog' => true)
- list = service.execute(board).payload[:list]
-
- expect(list.list_type).to eq('backlog')
- expect(list.position).to be_nil
- expect(list).to be_valid
-
- another_backlog = service.execute(board).payload[:list]
-
- expect(another_backlog).to eq list
- end
- end
- end
-
- context 'when board parent is a project' do
- let_it_be(:parent) { create(:project) }
- let_it_be(:board) { create(:board, project: parent) }
- let_it_be(:label) { create(:label, project: parent, name: 'in-progress') }
+ it_behaves_like 'board lists create service'
+ end
- it_behaves_like 'creating board lists'
- end
+ context 'when board parent is a group' do
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:board) { create(:board, group: parent) }
+ let_it_be(:label) { create(:group_label, group: parent, name: 'in-progress') }
- context 'when board parent is a group' do
- let_it_be(:parent) { create(:group) }
- let_it_be(:board) { create(:board, group: parent) }
- let_it_be(:label) { create(:group_label, group: parent, name: 'in-progress') }
+ it_behaves_like 'board lists create service'
+ end
- it_behaves_like 'creating board lists'
- end
+ def create_list(params)
+ create(:list, params.merge(board: board))
end
end
diff --git a/spec/services/bulk_create_integration_service_spec.rb b/spec/services/bulk_create_integration_service_spec.rb
index 674382ee14f..3ac993972c6 100644
--- a/spec/services/bulk_create_integration_service_spec.rb
+++ b/spec/services/bulk_create_integration_service_spec.rb
@@ -43,46 +43,6 @@ RSpec.describe BulkCreateIntegrationService do
end
end
- shared_examples 'updates project callbacks' do
- it 'updates projects#has_external_issue_tracker for issue tracker services' do
- described_class.new(integration, batch, association).execute
-
- expect(project.reload.has_external_issue_tracker).to eq(true)
- expect(excluded_project.reload.has_external_issue_tracker).to eq(false)
- end
-
- context 'with an external wiki integration' do
- before do
- integration.update!(category: 'common', type: 'ExternalWikiService')
- end
-
- it 'updates projects#has_external_wiki for external wiki services' do
- described_class.new(integration, batch, association).execute
-
- expect(project.reload.has_external_wiki).to eq(true)
- expect(excluded_project.reload.has_external_wiki).to eq(false)
- end
- end
- end
-
- shared_examples 'does not update project callbacks' do
- it 'does not update projects#has_external_issue_tracker for issue tracker services' do
- described_class.new(integration, batch, association).execute
-
- expect(project.reload.has_external_issue_tracker).to eq(false)
- end
-
- context 'with an inactive external wiki integration' do
- let(:integration) { create(:external_wiki_service, :instance, active: false) }
-
- it 'does not update projects#has_external_wiki for external wiki services' do
- described_class.new(integration, batch, association).execute
-
- expect(project.reload.has_external_wiki).to eq(false)
- end
- end
- end
-
context 'passing an instance-level integration' do
let(:integration) { instance_integration }
let(:inherit_from_id) { integration.id }
@@ -95,15 +55,6 @@ RSpec.describe BulkCreateIntegrationService do
it_behaves_like 'creates integration from batch ids'
it_behaves_like 'updates inherit_from_id'
- it_behaves_like 'updates project callbacks'
-
- context 'when integration is not active' do
- before do
- integration.update!(active: false)
- end
-
- it_behaves_like 'does not update project callbacks'
- end
end
context 'with a group association' do
@@ -130,7 +81,6 @@ RSpec.describe BulkCreateIntegrationService do
it_behaves_like 'creates integration from batch ids'
it_behaves_like 'updates inherit_from_id'
- it_behaves_like 'updates project callbacks'
end
context 'with a group association' do
@@ -157,7 +107,6 @@ RSpec.describe BulkCreateIntegrationService do
let(:inherit_from_id) { integration.id }
it_behaves_like 'creates integration from batch ids'
- it_behaves_like 'updates project callbacks'
end
end
end
diff --git a/spec/services/captcha/captcha_verification_service_spec.rb b/spec/services/captcha/captcha_verification_service_spec.rb
new file mode 100644
index 00000000000..245e06703f5
--- /dev/null
+++ b/spec/services/captcha/captcha_verification_service_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Captcha::CaptchaVerificationService do
+ describe '#execute' do
+ let(:captcha_response) { nil }
+ let(:request) { double(:request) }
+ let(:service) { described_class.new }
+
+ subject { service.execute(captcha_response: captcha_response, request: request) }
+
+ context 'when there is no captcha_response' do
+ it 'returns false' do
+ expect(subject).to eq(false)
+ end
+ end
+
+ context 'when there is a captcha_response' do
+ let(:captcha_response) { 'abc123' }
+
+ before do
+ expect(Gitlab::Recaptcha).to receive(:load_configurations!)
+ end
+
+ it 'returns false' do
+ expect(service).to receive(:verify_recaptcha).with(response: captcha_response) { true }
+
+ expect(subject).to eq(true)
+ end
+
+ it 'has a request method which returns the request' do
+ subject
+
+ expect(service.send(:request)).to eq(request)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_job_artifacts_service_spec.rb b/spec/services/ci/create_job_artifacts_service_spec.rb
index 29e51a23dea..1efd1d390a2 100644
--- a/spec/services/ci/create_job_artifacts_service_spec.rb
+++ b/spec/services/ci/create_job_artifacts_service_spec.rb
@@ -27,6 +27,14 @@ RSpec.describe Ci::CreateJobArtifactsService do
UploadedFile.new(upload.path, **params)
end
+ def unique_metrics_report_uploaders
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
+ event_names: described_class::METRICS_REPORT_UPLOAD_EVENT_NAME,
+ start_date: 2.weeks.ago,
+ end_date: 2.weeks.from_now
+ )
+ end
+
describe '#execute' do
subject { service.execute(artifacts_file, params, metadata_file: metadata_file) }
@@ -42,6 +50,12 @@ RSpec.describe Ci::CreateJobArtifactsService do
expect(new_artifact.file_sha256).to eq(artifacts_sha256)
end
+ it 'does not track the job user_id' do
+ subject
+
+ expect(unique_metrics_report_uploaders).to eq(0)
+ end
+
context 'when metadata file is also uploaded' do
let(:metadata_file) do
file_to_upload('spec/fixtures/ci_build_artifacts_metadata.gz', sha256: artifacts_sha256)
@@ -174,6 +188,20 @@ RSpec.describe Ci::CreateJobArtifactsService do
end
end
+ context 'when artifact_type is metrics' do
+ before do
+ allow(job).to receive(:user_id).and_return(123)
+ end
+
+ let(:params) { { 'artifact_type' => 'metrics', 'artifact_format' => 'gzip' }.with_indifferent_access }
+
+ it 'tracks the job user_id' do
+ subject
+
+ expect(unique_metrics_report_uploaders).to eq(1)
+ end
+ end
+
context 'when artifact type is cluster_applications' do
let(:artifacts_file) do
file_to_upload('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz', sha256: artifacts_sha256)
diff --git a/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
new file mode 100644
index 00000000000..9cf66dfceb0
--- /dev/null
+++ b/spec/services/ci/create_pipeline_service/cross_project_pipeline_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CreatePipelineService, '#execute' do
+ let_it_be(:group) { create(:group, name: 'my-organization') }
+ let(:upstream_project) { create(:project, :repository, name: 'upstream', group: group) }
+ let(:downstram_project) { create(:project, :repository, name: 'downstream', group: group) }
+ let(:user) { create(:user) }
+
+ let(:service) do
+ described_class.new(upstream_project, user, ref: 'master')
+ end
+
+ before do
+ upstream_project.add_developer(user)
+ downstram_project.add_developer(user)
+ create_gitlab_ci_yml(upstream_project, upstream_config)
+ create_gitlab_ci_yml(downstram_project, downstream_config)
+ end
+
+ context 'with resource group', :aggregate_failures do
+ let(:upstream_config) do
+ <<~YAML
+ instrumentation_test:
+ stage: test
+ resource_group: iOS
+ trigger:
+ project: my-organization/downstream
+ strategy: depend
+ YAML
+ end
+
+ let(:downstream_config) do
+ <<~YAML
+ test:
+ script: echo "Testing..."
+ YAML
+ end
+
+ it 'creates bridge job with resource group' do
+ pipeline = create_pipeline!
+
+ test = pipeline.statuses.find_by(name: 'instrumentation_test')
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.triggered_pipelines).not_to be_exist
+ expect(upstream_project.resource_groups.count).to eq(1)
+ expect(test).to be_a Ci::Bridge
+ expect(test).to be_waiting_for_resource
+ expect(test.resource_group.key).to eq('iOS')
+ end
+
+ context 'when sidekiq processes the job', :sidekiq_inline do
+ it 'transitions to pending status and triggers a downstream pipeline' do
+ pipeline = create_pipeline!
+
+ test = pipeline.statuses.find_by(name: 'instrumentation_test')
+ expect(test).to be_pending
+ expect(pipeline.triggered_pipelines.count).to eq(1)
+ end
+
+ context 'when the resource is occupied by the other bridge' do
+ before do
+ resource_group = create(:ci_resource_group, project: upstream_project, key: 'iOS')
+ resource_group.assign_resource_to(create(:ci_build, project: upstream_project))
+ end
+
+ it 'stays waiting for resource' do
+ pipeline = create_pipeline!
+
+ test = pipeline.statuses.find_by(name: 'instrumentation_test')
+ expect(test).to be_waiting_for_resource
+ expect(pipeline.triggered_pipelines.count).to eq(0)
+ end
+ end
+ end
+ end
+
+ def create_pipeline!
+ service.execute(:push)
+ end
+
+ def create_gitlab_ci_yml(project, content)
+ project.repository.create_file(user, '.gitlab-ci.yml', content, branch_name: 'master', message: 'test')
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb b/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb
new file mode 100644
index 00000000000..4cf52223e38
--- /dev/null
+++ b/spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Ci::CreatePipelineService do
+ describe '!reference tags' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
+
+ let(:ref) { 'refs/heads/master' }
+ let(:source) { :push }
+ let(:service) { described_class.new(project, user, { ref: ref }) }
+ let(:pipeline) { service.execute(source) }
+
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ context 'with valid config' do
+ let(:config) do
+ <<~YAML
+ .job-1:
+ script:
+ - echo doing step 1 of job 1
+
+ .job-2:
+ before_script:
+ - ls
+ script: !reference [.job-1, script]
+
+ job:
+ before_script: !reference [.job-2, before_script]
+ script:
+ - echo doing my first step
+ - !reference [.job-2, script]
+ - echo doing my last step
+ YAML
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds.first.options).to match(a_hash_including({
+ 'before_script' => ['ls'],
+ 'script' => [
+ 'echo doing my first step',
+ 'echo doing step 1 of job 1',
+ 'echo doing my last step'
+ ]
+ }))
+ end
+ end
+
+ context 'with invalid config' do
+ let(:config) do
+ <<~YAML
+ job-1:
+ script:
+ - echo doing step 1 of job 1
+ - !reference [job-3, script]
+
+ job-2:
+ script:
+ - echo doing step 1 of job 2
+ - !reference [job-3, script]
+
+ job-3:
+ script:
+ - echo doing step 1 of job 3
+ - !reference [job-1, script]
+ YAML
+ end
+
+ it 'creates a pipeline without builds' do
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds).to be_empty
+ expect(pipeline.yaml_errors).to eq("!reference [\"job-3\", \"script\"] is part of a circular chain")
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
index 8df9b0c3e60..a3818937113 100644
--- a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
@@ -76,6 +76,56 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
}
end
end
+
+ context 'with resource group' do
+ let(:config) do
+ <<~YAML
+ instrumentation_test:
+ stage: test
+ resource_group: iOS
+ trigger:
+ include: path/to/child.yml
+ strategy: depend
+ YAML
+ end
+
+ it 'creates bridge job with resource group', :aggregate_failures do
+ pipeline = create_pipeline!
+
+ test = pipeline.statuses.find_by(name: 'instrumentation_test')
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.triggered_pipelines).not_to be_exist
+ expect(project.resource_groups.count).to eq(1)
+ expect(test).to be_a Ci::Bridge
+ expect(test).to be_waiting_for_resource
+ expect(test.resource_group.key).to eq('iOS')
+ end
+
+ context 'when sidekiq processes the job', :sidekiq_inline do
+ it 'transitions to pending status and triggers a downstream pipeline' do
+ pipeline = create_pipeline!
+
+ test = pipeline.statuses.find_by(name: 'instrumentation_test')
+ expect(test).to be_pending
+ expect(pipeline.triggered_pipelines.count).to eq(1)
+ end
+
+ context 'when the resource is occupied by the other bridge' do
+ before do
+ resource_group = create(:ci_resource_group, project: project, key: 'iOS')
+ resource_group.assign_resource_to(create(:ci_build, project: project))
+ end
+
+ it 'stays waiting for resource' do
+ pipeline = create_pipeline!
+
+ test = pipeline.statuses.find_by(name: 'instrumentation_test')
+ expect(test).to be_waiting_for_resource
+ expect(pipeline.triggered_pipelines.count).to eq(0)
+ end
+ end
+ end
+ end
end
describe 'child pipeline triggers' do
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index ac6c4c188e4..04ecac6a85a 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -145,20 +145,6 @@ RSpec.describe Ci::CreatePipelineService do
expect(find_job('job-2').options.dig(:allow_failure_criteria)).to be_nil
expect(find_job('job-3').options.dig(:allow_failure_criteria, :exit_codes)).to eq([42])
end
-
- context 'with ci_allow_failure_with_exit_codes disabled' do
- before do
- stub_feature_flags(ci_allow_failure_with_exit_codes: false)
- end
-
- it 'does not persist allow_failure_criteria' do
- expect(pipeline).to be_persisted
-
- expect(find_job('job-1').options.key?(:allow_failure_criteria)).to be_falsey
- expect(find_job('job-2').options.key?(:allow_failure_criteria)).to be_falsey
- expect(find_job('job-3').options.key?(:allow_failure_criteria)).to be_falsey
- end
- end
end
context 'if:' do
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index e1f1bdc41a1..1005985b3e4 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -102,7 +102,6 @@ RSpec.describe Ci::CreatePipelineService do
describe 'recording a conversion event' do
it 'schedules a record conversion event worker' do
expect(Experiments::RecordConversionEventWorker).to receive(:perform_async).with(:ci_syntax_templates, user.id)
- expect(Experiments::RecordConversionEventWorker).to receive(:perform_async).with(:pipelines_empty_state, user.id)
pipeline
end
@@ -538,7 +537,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
- expect(pipeline.builds.map(&:name)).to match_array(%w[build code_quality eslint-sast secret_detection_default_branch test])
+ expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection_default_branch test])
end
end
@@ -952,9 +951,9 @@ RSpec.describe Ci::CreatePipelineService do
expect(result).to be_persisted
expect(deploy_job.resource_group.key).to eq(resource_group_key)
expect(project.resource_groups.count).to eq(1)
- expect(resource_group.builds.count).to eq(1)
+ expect(resource_group.processables.count).to eq(1)
expect(resource_group.resources.count).to eq(1)
- expect(resource_group.resources.first.build).to eq(nil)
+ expect(resource_group.resources.first.processable).to eq(nil)
end
context 'when resource group key includes predefined variables' do
diff --git a/spec/services/ci/daily_build_group_report_result_service_spec.rb b/spec/services/ci/daily_build_group_report_result_service_spec.rb
index e54f10cc4f4..e58a5de26a1 100644
--- a/spec/services/ci/daily_build_group_report_result_service_spec.rb
+++ b/spec/services/ci/daily_build_group_report_result_service_spec.rb
@@ -3,10 +3,12 @@
require 'spec_helper'
RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
- let!(:pipeline) { create(:ci_pipeline, created_at: '2020-02-06 00:01:10') }
- let!(:rspec_job) { create(:ci_build, pipeline: pipeline, name: '3/3 rspec', coverage: 80) }
- let!(:karma_job) { create(:ci_build, pipeline: pipeline, name: '2/2 karma', coverage: 90) }
- let!(:extra_job) { create(:ci_build, pipeline: pipeline, name: 'extra', coverage: nil) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: create(:project, group: group), created_at: '2020-02-06 00:01:10') }
+ let_it_be(:rspec_job) { create(:ci_build, pipeline: pipeline, name: 'rspec 3/3', coverage: 80) }
+ let_it_be(:karma_job) { create(:ci_build, pipeline: pipeline, name: 'karma 2/2', coverage: 90) }
+ let_it_be(:extra_job) { create(:ci_build, pipeline: pipeline, name: 'extra', coverage: nil) }
+
let(:coverages) { Ci::DailyBuildGroupReportResult.all }
it 'creates daily code coverage record for each job in the pipeline that has coverage value' do
@@ -19,7 +21,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
ref_path: pipeline.source_ref_path,
group_name: rspec_job.group_name,
data: { 'coverage' => rspec_job.coverage },
- date: pipeline.created_at.to_date
+ date: pipeline.created_at.to_date,
+ group_id: group.id
)
end
@@ -30,7 +33,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
ref_path: pipeline.source_ref_path,
group_name: karma_job.group_name,
data: { 'coverage' => karma_job.coverage },
- date: pipeline.created_at.to_date
+ date: pipeline.created_at.to_date,
+ group_id: group.id
)
end
@@ -38,8 +42,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
end
context 'when there are multiple builds with the same group name that report coverage' do
- let!(:test_job_1) { create(:ci_build, pipeline: pipeline, name: '1/2 test', coverage: 70) }
- let!(:test_job_2) { create(:ci_build, pipeline: pipeline, name: '2/2 test', coverage: 80) }
+ let!(:test_job_1) { create(:ci_build, pipeline: pipeline, name: 'test 1/2', coverage: 70) }
+ let!(:test_job_2) { create(:ci_build, pipeline: pipeline, name: 'test 2/2', coverage: 80) }
it 'creates daily code coverage record with the average as the value' do
described_class.new.execute(pipeline)
@@ -67,8 +71,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
)
end
- let!(:new_rspec_job) { create(:ci_build, pipeline: new_pipeline, name: '4/4 rspec', coverage: 84) }
- let!(:new_karma_job) { create(:ci_build, pipeline: new_pipeline, name: '3/3 karma', coverage: 92) }
+ let!(:new_rspec_job) { create(:ci_build, pipeline: new_pipeline, name: 'rspec 4/4', coverage: 84) }
+ let!(:new_karma_job) { create(:ci_build, pipeline: new_pipeline, name: 'karma 3/3', coverage: 92) }
before do
# Create the existing daily code coverage records
@@ -107,8 +111,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultService, '#execute' do
)
end
- let!(:new_rspec_job) { create(:ci_build, pipeline: new_pipeline, name: '4/4 rspec', coverage: 84) }
- let!(:new_karma_job) { create(:ci_build, pipeline: new_pipeline, name: '3/3 karma', coverage: 92) }
+ let!(:new_rspec_job) { create(:ci_build, pipeline: new_pipeline, name: 'rspec 4/4', coverage: 84) }
+ let!(:new_karma_job) { create(:ci_build, pipeline: new_pipeline, name: 'karma 3/3', coverage: 92) }
before do
# Create the existing daily code coverage records
diff --git a/spec/services/ci/generate_codequality_mr_diff_report_service_spec.rb b/spec/services/ci/generate_codequality_mr_diff_report_service_spec.rb
new file mode 100644
index 00000000000..5d747a09f2a
--- /dev/null
+++ b/spec/services/ci/generate_codequality_mr_diff_report_service_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::GenerateCodequalityMrDiffReportService do
+ let(:service) { described_class.new(project) }
+ let(:project) { create(:project, :repository) }
+
+ describe '#execute' do
+ subject { service.execute(base_pipeline, head_pipeline) }
+
+ context 'when head pipeline has codequality mr diff report' do
+ let!(:merge_request) { create(:merge_request, :with_codequality_mr_diff_reports, source_project: project) }
+ let!(:service) { described_class.new(project, nil, id: merge_request.id) }
+ let!(:head_pipeline) { merge_request.head_pipeline }
+ let!(:base_pipeline) { nil }
+
+ it 'returns status and data', :aggregate_failures do
+ expect_any_instance_of(Ci::PipelineArtifact) do |instance|
+ expect(instance).to receive(:present)
+ expect(instance).to receive(:for_files).with(merge_request.new_paths).and_call_original
+ end
+
+ expect(subject[:status]).to eq(:parsed)
+ expect(subject[:data]).to eq(files: {})
+ end
+ end
+
+ context 'when head pipeline does not have a codequality mr diff report' do
+ let!(:merge_request) { create(:merge_request, source_project: project) }
+ let!(:service) { described_class.new(project, nil, id: merge_request.id) }
+ let!(:head_pipeline) { merge_request.head_pipeline }
+ let!(:base_pipeline) { nil }
+
+ it 'returns status and error message' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:status_reason]).to include('An error occurred while fetching codequality mr diff reports.')
+ end
+ end
+
+ context 'when head pipeline has codequality mr diff report and no merge request associated' do
+ let!(:head_pipeline) { create(:ci_pipeline, :with_codequality_mr_diff_report, project: project) }
+ let!(:base_pipeline) { nil }
+
+ it 'returns status and error message' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:status_reason]).to include('An error occurred while fetching codequality mr diff reports.')
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb
new file mode 100644
index 00000000000..0c48f15d726
--- /dev/null
+++ b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService do
+ describe '#execute' do
+ subject(:pipeline_artifact) { described_class.new.execute(pipeline) }
+
+ context 'when pipeline has codequality reports' do
+ let(:project) { create(:project, :repository) }
+
+ describe 'pipeline completed status' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :result) do
+ :success | 1
+ :failed | 1
+ :canceled | 1
+ :skipped | 1
+ end
+
+ with_them do
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, status: status, project: project) }
+
+ it 'creates a pipeline artifact' do
+ expect { pipeline_artifact }.to change(Ci::PipelineArtifact, :count).by(result)
+ end
+
+ it 'persists the default file name' do
+ expect(pipeline_artifact.file.filename).to eq('code_quality_mr_diff.json')
+ end
+
+ it 'sets expire_at to 1 week' do
+ freeze_time do
+ expect(pipeline_artifact.expire_at).to eq(1.week.from_now)
+ end
+ end
+ end
+ end
+
+ context 'when pipeline artifact has already been created' do
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) }
+
+ it 'does not persist the same artifact twice' do
+ 2.times { described_class.new.execute(pipeline) }
+
+ expect(Ci::PipelineArtifact.count).to eq(1)
+ end
+ end
+ end
+
+ context 'when pipeline is not completed and codequality report does not exist' do
+ let(:pipeline) { create(:ci_pipeline, :running) }
+
+ it 'does not persist data' do
+ pipeline_artifact
+
+ expect(Ci::PipelineArtifact.count).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_trigger_service_spec.rb b/spec/services/ci/pipeline_trigger_service_spec.rb
index 0cc66e67b91..89d3da89011 100644
--- a/spec/services/ci/pipeline_trigger_service_spec.rb
+++ b/spec/services/ci/pipeline_trigger_service_spec.rb
@@ -45,6 +45,27 @@ RSpec.describe Ci::PipelineTriggerService do
expect(result[:status]).to eq(:success)
end
+ it 'stores the payload as a variable' do
+ expect { result }.to change { Ci::PipelineVariable.count }.by(1)
+
+ var = result[:pipeline].variables.first
+
+ expect(var.key).to eq('TRIGGER_PAYLOAD')
+ expect(var.value).to eq('{"ref":"master","variables":null}')
+ expect(var.variable_type).to eq('file')
+ end
+
+ context 'when FF ci_trigger_payload_into_pipeline is disabled' do
+ before do
+ stub_feature_flags(ci_trigger_payload_into_pipeline: false)
+ end
+
+ it 'does not store the payload as a variable' do
+ expect { result }.not_to change { Ci::PipelineVariable.count }
+ expect(result[:pipeline].variables).to be_empty
+ end
+ end
+
context 'when commit message has [ci skip]' do
before do
allow_next(Ci::Pipeline).to receive(:git_commit_message) { '[ci skip]' }
@@ -60,8 +81,8 @@ RSpec.describe Ci::PipelineTriggerService do
let(:params) { { token: trigger.token, ref: 'master', variables: variables } }
let(:variables) { { 'AAA' => 'AAA123' } }
- it 'has a variable' do
- expect { result }.to change { Ci::PipelineVariable.count }.by(1)
+ it 'has variables' do
+ expect { result }.to change { Ci::PipelineVariable.count }.by(2)
.and change { Ci::TriggerRequest.count }.by(1)
expect(result[:pipeline].variables.map { |v| { v.key => v.value } }.first).to eq(variables)
expect(result[:pipeline].trigger_requests.last.variables).to be_nil
@@ -155,8 +176,8 @@ RSpec.describe Ci::PipelineTriggerService do
let(:params) { { token: job.token, ref: 'master', variables: variables } }
let(:variables) { { 'AAA' => 'AAA123' } }
- it 'has a variable' do
- expect { result }.to change { Ci::PipelineVariable.count }.by(1)
+ it 'has variables' do
+ expect { result }.to change { Ci::PipelineVariable.count }.by(2)
.and change { Ci::Sources::Pipeline.count }.by(1)
expect(result[:pipeline].variables.map { |v| { v.key => v.value } }.first).to eq(variables)
expect(job.sourced_pipelines.last.pipeline_id).to eq(result[:pipeline].id)
diff --git a/spec/services/ci/process_build_service_spec.rb b/spec/services/ci/process_build_service_spec.rb
index 6d2af81a6e8..42a92504839 100644
--- a/spec/services/ci/process_build_service_spec.rb
+++ b/spec/services/ci/process_build_service_spec.rb
@@ -146,9 +146,11 @@ RSpec.describe Ci::ProcessBuildService, '#execute' do
end
end
- context 'when FF skip_dag_manual_and_delayed_jobs is disabled' do
+ context 'when FF skip_dag_manual_and_delayed_jobs is disabled on the project' do
+ let_it_be(:other_project) { create(:project) }
+
before do
- stub_feature_flags(skip_dag_manual_and_delayed_jobs: false)
+ stub_feature_flags(skip_dag_manual_and_delayed_jobs: other_project)
end
where(:build_when, :current_status, :after_status) do
diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb
index a7889f0644d..d316c9a262b 100644
--- a/spec/services/ci/process_pipeline_service_spec.rb
+++ b/spec/services/ci/process_pipeline_service_spec.rb
@@ -50,6 +50,35 @@ RSpec.describe Ci::ProcessPipelineService do
expect(all_builds.retried).to contain_exactly(build_retried)
end
+ context 'counter ci_legacy_update_jobs_as_retried_total' do
+ let(:counter) { double(increment: true) }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:counter).and_call_original
+ allow(Gitlab::Metrics).to receive(:counter)
+ .with(:ci_legacy_update_jobs_as_retried_total, anything)
+ .and_return(counter)
+ end
+
+ it 'increments the counter' do
+ expect(counter).to receive(:increment)
+
+ subject.execute
+ end
+
+ context 'when the previous build has already retried column true' do
+ before do
+ build_retried.update_columns(retried: true)
+ end
+
+ it 'does not increment the counter' do
+ expect(counter).not_to receive(:increment)
+
+ subject.execute
+ end
+ end
+ end
+
def create_build(name, **opts)
create(:ci_build, :created, pipeline: pipeline, name: name, **opts)
end
diff --git a/spec/services/ci/prometheus_metrics/observe_histograms_service_spec.rb b/spec/services/ci/prometheus_metrics/observe_histograms_service_spec.rb
new file mode 100644
index 00000000000..2eef852b0f4
--- /dev/null
+++ b/spec/services/ci/prometheus_metrics/observe_histograms_service_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PrometheusMetrics::ObserveHistogramsService do
+ let_it_be(:project) { create(:project) }
+ let(:params) { {} }
+
+ subject(:execute) { described_class.new(project, params).execute }
+
+ before do
+ Gitlab::Metrics.reset_registry!
+ end
+
+ context 'with empty data' do
+ it 'does not raise errors' do
+ is_expected.to be_success
+ end
+ end
+
+ context 'observes metrics successfully' do
+ let(:params) do
+ {
+ histograms: [
+ { name: 'pipeline_graph_link_calculation_duration_seconds', value: '1' },
+ { name: 'pipeline_graph_links_per_job_ratio', value: '0.9' }
+ ]
+ }
+ end
+
+ it 'increments the metrics' do
+ execute
+
+ expect(histogram_data).to match(a_hash_including({ 0.8 => 0.0, 1 => 1.0, 2 => 1.0 }))
+
+ expect(histogram_data(:pipeline_graph_links_per_job_ratio))
+ .to match(a_hash_including({ 0.8 => 0.0, 0.9 => 1.0, 1 => 1.0 }))
+ end
+
+ it 'returns an empty body and status code' do
+ is_expected.to be_success
+ expect(subject.http_status).to eq(:created)
+ expect(subject.payload).to eq({})
+ end
+ end
+
+ context 'with unknown histograms' do
+ let(:params) do
+ { histograms: [{ name: 'chunky_bacon', value: '4' }] }
+ end
+
+ it 'raises ActiveRecord::RecordNotFound error' do
+ expect { subject }.to raise_error ActiveRecord::RecordNotFound
+ end
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(ci_accept_frontend_prometheus_metrics: false)
+ end
+
+ let(:params) do
+ {
+ histograms: [
+ { name: 'pipeline_graph_link_calculation_duration_seconds', value: '4' }
+ ]
+ }
+ end
+
+ it 'does not register the metrics' do
+ execute
+
+ expect(histogram_data).to be_nil
+ end
+
+ it 'returns an empty body and status code' do
+ is_expected.to be_success
+ expect(subject.http_status).to eq(:accepted)
+ expect(subject.payload).to eq({})
+ end
+ end
+
+ def histogram_data(name = :pipeline_graph_link_calculation_duration_seconds)
+ Gitlab::Metrics.registry.get(name)&.get({})
+ end
+end
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 0cdc8d2c870..88770c8095b 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -455,7 +455,7 @@ module Ci
end
before do
- stub_feature_flags(ci_disable_validates_dependencies: false)
+ stub_feature_flags(ci_validate_build_dependencies_override: false)
end
let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) }
@@ -470,15 +470,31 @@ module Ci
context 'when validates for dependencies is enabled' do
before do
- stub_feature_flags(ci_disable_validates_dependencies: false)
+ stub_feature_flags(ci_validate_build_dependencies_override: false)
end
it_behaves_like 'validation is active'
+
+ context 'when the main feature flag is enabled for a specific project' do
+ before do
+ stub_feature_flags(ci_validate_build_dependencies: pipeline.project)
+ end
+
+ it_behaves_like 'validation is active'
+ end
+
+ context 'when the main feature flag is enabled for a different project' do
+ before do
+ stub_feature_flags(ci_validate_build_dependencies: create(:project))
+ end
+
+ it_behaves_like 'validation is not active'
+ end
end
context 'when validates for dependencies is disabled' do
before do
- stub_feature_flags(ci_disable_validates_dependencies: true)
+ stub_feature_flags(ci_validate_build_dependencies_override: true)
end
it_behaves_like 'validation is not active'
diff --git a/spec/services/container_expiration_policies/cleanup_service_spec.rb b/spec/services/container_expiration_policies/cleanup_service_spec.rb
index 34f69d24141..746e3464427 100644
--- a/spec/services/container_expiration_policies/cleanup_service_spec.rb
+++ b/spec/services/container_expiration_policies/cleanup_service_spec.rb
@@ -61,7 +61,8 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
original_size: 1000,
before_truncate_size: 800,
after_truncate_size: 200,
- before_delete_size: 100
+ before_delete_size: 100,
+ deleted_size: 100
}
end
@@ -77,7 +78,8 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
cleanup_tags_service_original_size: 1000,
cleanup_tags_service_before_truncate_size: 800,
cleanup_tags_service_after_truncate_size: 200,
- cleanup_tags_service_before_delete_size: 100
+ cleanup_tags_service_before_delete_size: 100,
+ cleanup_tags_service_deleted_size: 100
)
expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
expect(repository.reload.cleanup_unfinished?).to be_truthy
@@ -97,5 +99,21 @@ RSpec.describe ContainerExpirationPolicies::CleanupService do
expect(response.success?).to eq(false)
end
end
+
+ context 'with a network error' do
+ before do
+ expect(Projects::ContainerRepository::CleanupTagsService)
+ .to receive(:new).and_raise(Faraday::TimeoutError)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Faraday::TimeoutError)
+
+ expect(ContainerRepository.waiting_for_cleanup.count).to eq(1)
+ expect(repository.reload.cleanup_unfinished?).to be_truthy
+ expect(repository.expiration_policy_started_at).not_to eq(nil)
+ expect(repository.expiration_policy_completed_at).to eq(nil)
+ end
+ end
end
end
diff --git a/spec/services/deployments/create_service_spec.rb b/spec/services/deployments/create_service_spec.rb
index 2d157c9d114..0bb5949ddb1 100644
--- a/spec/services/deployments/create_service_spec.rb
+++ b/spec/services/deployments/create_service_spec.rb
@@ -41,6 +41,27 @@ RSpec.describe Deployments::CreateService do
expect(service.execute).to be_persisted
end
+
+ context 'when the last deployment has the same parameters' do
+ let(:params) do
+ {
+ sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
+ ref: 'master',
+ tag: false,
+ status: 'success'
+ }
+ end
+
+ it 'does not create a new deployment' do
+ described_class.new(environment, user, params).execute
+
+ expect(Deployments::UpdateEnvironmentWorker).not_to receive(:perform_async)
+ expect(Deployments::LinkMergeRequestWorker).not_to receive(:perform_async)
+ expect(Deployments::ExecuteHooksWorker).not_to receive(:perform_async)
+
+ described_class.new(environment.reload, user, params).execute
+ end
+ end
end
describe '#deployment_attributes' do
diff --git a/spec/services/design_management/move_designs_service_spec.rb b/spec/services/design_management/move_designs_service_spec.rb
index a43f0a2f805..c8abce77325 100644
--- a/spec/services/design_management/move_designs_service_spec.rb
+++ b/spec/services/design_management/move_designs_service_spec.rb
@@ -76,18 +76,6 @@ RSpec.describe DesignManagement::MoveDesignsService do
end
end
- context 'the designs are not adjacent' do
- let(:current_design) { designs.first }
- let(:previous_design) { designs.second }
- let(:next_design) { designs.third }
-
- it 'raises not_adjacent' do
- create(:design, issue: issue, relative_position: next_design.relative_position - 1)
-
- expect(subject).to be_error.and(have_attributes(message: :not_adjacent))
- end
- end
-
context 'moving a design with neighbours' do
let(:current_design) { designs.first }
let(:previous_design) { designs.second }
diff --git a/spec/services/discussions/resolve_service_spec.rb b/spec/services/discussions/resolve_service_spec.rb
index 42c4ef52741..2e30455eb0a 100644
--- a/spec/services/discussions/resolve_service_spec.rb
+++ b/spec/services/discussions/resolve_service_spec.rb
@@ -24,6 +24,13 @@ RSpec.describe Discussions::ResolveService do
expect(discussion).to be_resolved
end
+ it 'tracks thread resolve usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_resolve_thread_action).with(user: user)
+
+ service.execute
+ end
+
it 'executes the notification service' do
expect_next_instance_of(MergeRequests::ResolvedDiscussionNotificationService) do |instance|
expect(instance).to receive(:execute).with(discussion.noteable)
@@ -101,6 +108,13 @@ RSpec.describe Discussions::ResolveService do
service.execute
end
+ it 'does not track thread resolve usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_resolve_thread_action).with(user: user)
+
+ service.execute
+ end
+
it 'does not schedule an auto-merge' do
expect(AutoMergeProcessWorker).not_to receive(:perform_async)
diff --git a/spec/services/discussions/unresolve_service_spec.rb b/spec/services/discussions/unresolve_service_spec.rb
new file mode 100644
index 00000000000..6298a00a474
--- /dev/null
+++ b/spec/services/discussions/unresolve_service_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Discussions::UnresolveService do
+ describe "#execute" do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user, developer_projects: [project]) }
+ let_it_be(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds, source_project: project) }
+ let(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion }
+
+ let(:service) { described_class.new(discussion, user) }
+
+ before do
+ project.add_developer(user)
+ discussion.resolve!(user)
+ end
+
+ it "unresolves the discussion" do
+ service.execute
+
+ expect(discussion).not_to be_resolved
+ end
+
+ it "counts the unresolve event" do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_unresolve_thread_action).with(user: user)
+
+ service.execute
+ end
+ end
+end
diff --git a/spec/services/feature_flags/create_service_spec.rb b/spec/services/feature_flags/create_service_spec.rb
index e115d8098c9..128fab114fe 100644
--- a/spec/services/feature_flags/create_service_spec.rb
+++ b/spec/services/feature_flags/create_service_spec.rb
@@ -66,18 +66,6 @@ RSpec.describe FeatureFlags::CreateService do
subject
end
- context 'the feature flag is disabled' do
- before do
- stub_feature_flags(jira_sync_feature_flags: false)
- end
-
- it 'does not sync the feature flag to Jira' do
- expect(::JiraConnect::SyncFeatureFlagsWorker).not_to receive(:perform_async)
-
- subject
- end
- end
-
it 'creates audit event' do
expected_message = 'Created feature flag <strong>feature_flag</strong> '\
'with description <strong>"description"</strong>. '\
diff --git a/spec/services/feature_flags/update_service_spec.rb b/spec/services/feature_flags/update_service_spec.rb
index 8c4055ddd9e..9639cf3081d 100644
--- a/spec/services/feature_flags/update_service_spec.rb
+++ b/spec/services/feature_flags/update_service_spec.rb
@@ -26,18 +26,6 @@ RSpec.describe FeatureFlags::UpdateService do
expect(subject[:status]).to eq(:success)
end
- context 'the feature flag is disabled' do
- before do
- stub_feature_flags(jira_sync_feature_flags: false)
- end
-
- it 'does not sync the feature flag to Jira' do
- expect(::JiraConnect::SyncFeatureFlagsWorker).not_to receive(:perform_async)
-
- subject
- end
- end
-
it 'syncs the feature flag to Jira' do
expect(::JiraConnect::SyncFeatureFlagsWorker).to receive(:perform_async).with(Integer, Integer)
diff --git a/spec/services/git/branch_hooks_service_spec.rb b/spec/services/git/branch_hooks_service_spec.rb
index a5290f0be68..52df21897b9 100644
--- a/spec/services/git/branch_hooks_service_spec.rb
+++ b/spec/services/git/branch_hooks_service_spec.rb
@@ -11,7 +11,8 @@ RSpec.describe Git::BranchHooksService do
let(:branch) { project.default_branch }
let(:ref) { "refs/heads/#{branch}" }
- let(:commit) { project.commit(sample_commit.id) }
+ let(:commit_id) { sample_commit.id }
+ let(:commit) { project.commit(commit_id) }
let(:oldrev) { commit.parent_id }
let(:newrev) { commit.id }
@@ -93,12 +94,12 @@ RSpec.describe Git::BranchHooksService do
describe 'Push Event' do
let(:event) { Event.pushed_action.first }
- before do
- service.execute
- end
+ subject(:execute_service) { service.execute }
context "with an existing branch" do
it 'generates a push event with one commit' do
+ execute_service
+
expect(event).to be_an_instance_of(PushEvent)
expect(event.project).to eq(project)
expect(event).to be_pushed_action
@@ -109,12 +110,87 @@ RSpec.describe Git::BranchHooksService do
expect(event.push_event_payload.ref).to eq('master')
expect(event.push_event_payload.commit_count).to eq(1)
end
+
+ context 'with changing CI config' do
+ before do
+ allow_next_instance_of(Gitlab::Git::Diff) do |diff|
+ allow(diff).to receive(:new_path).and_return('.gitlab-ci.yml')
+ end
+
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+ end
+
+ let!(:commit_author) { create(:user, email: sample_commit.author_email) }
+
+ let(:tracking_params) do
+ ['o_pipeline_authoring_unique_users_committing_ciconfigfile', values: commit_author.id]
+ end
+
+ it 'tracks the event' do
+ execute_service
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to have_received(:track_event).with(*tracking_params)
+ end
+
+ context 'when the FF usage_data_unique_users_committing_ciconfigfile is disabled' do
+ before do
+ stub_feature_flags(usage_data_unique_users_committing_ciconfigfile: false)
+ end
+
+ it 'does not track the event' do
+ execute_service
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .not_to have_received(:track_event).with(*tracking_params)
+ end
+ end
+
+ context 'when usage ping is disabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: false)
+ end
+
+ it 'does not track the event' do
+ execute_service
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .not_to have_received(:track_event).with(*tracking_params)
+ end
+ end
+
+ context 'when the branch is not the main branch' do
+ let(:branch) { 'feature' }
+
+ it 'does not track the event' do
+ execute_service
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .not_to have_received(:track_event).with(*tracking_params)
+ end
+ end
+
+ context 'when the CI config is a different path' do
+ before do
+ project.ci_config_path = 'config/ci.yml'
+ end
+
+ it 'does not track the event' do
+ execute_service
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .not_to have_received(:track_event).with(*tracking_params)
+ end
+ end
+ end
end
context "with a new branch" do
let(:oldrev) { Gitlab::Git::BLANK_SHA }
it 'generates a push event with more than one commit' do
+ execute_service
+
expect(event).to be_an_instance_of(PushEvent)
expect(event.project).to eq(project)
expect(event).to be_pushed_action
@@ -131,6 +207,8 @@ RSpec.describe Git::BranchHooksService do
let(:newrev) { Gitlab::Git::BLANK_SHA }
it 'generates a push event with no commits' do
+ execute_service
+
expect(event).to be_an_instance_of(PushEvent)
expect(event.project).to eq(project)
expect(event).to be_pushed_action
@@ -150,7 +228,6 @@ RSpec.describe Git::BranchHooksService do
)
end
- let(:commit) { project.repository.commit(commit_id) }
let(:blank_sha) { Gitlab::Git::BLANK_SHA }
def clears_cache(extended: [])
@@ -431,11 +508,7 @@ RSpec.describe Git::BranchHooksService do
end
describe 'Metrics dashboard sync' do
- context 'with feature flag enabled' do
- before do
- Feature.enable(:metrics_dashboards_sync)
- end
-
+ shared_examples 'trigger dashboard sync' do
it 'imports metrics to database' do
expect(Metrics::Dashboard::SyncDashboardsWorker).to receive(:perform_async)
@@ -443,12 +516,95 @@ RSpec.describe Git::BranchHooksService do
end
end
- context 'with feature flag disabled' do
- it 'imports metrics to database' do
- expect(Metrics::Dashboard::SyncDashboardsWorker).to receive(:perform_async)
+ shared_examples 'no dashboard sync' do
+ it 'does not sync metrics to database' do
+ expect(Metrics::Dashboard::SyncDashboardsWorker).not_to receive(:perform_async)
service.execute
end
end
+
+ def change_repository(**changes)
+ actions = changes.flat_map do |(action, paths)|
+ Array(paths).flat_map do |file_path|
+ { action: action, file_path: file_path, content: SecureRandom.hex }
+ end
+ end
+
+ project.repository.multi_action(
+ user, message: 'message', branch_name: branch, actions: actions
+ )
+ end
+
+ let(:charts) { '.gitlab/dashboards/charts.yml' }
+ let(:readme) { 'README.md' }
+ let(:commit_id) { change_repository(**commit_changes) }
+
+ context 'with default branch' do
+ context 'when adding files' do
+ let(:new_file) { 'somenewfile.md' }
+
+ context 'also related' do
+ let(:commit_changes) { { create: [charts, new_file] } }
+
+ include_examples 'trigger dashboard sync'
+ end
+
+ context 'only unrelated' do
+ let(:commit_changes) { { create: new_file } }
+
+ include_examples 'no dashboard sync'
+ end
+ end
+
+ context 'when deleting files' do
+ before do
+ change_repository(create: charts)
+ end
+
+ context 'also related' do
+ let(:commit_changes) { { delete: [charts, readme] } }
+
+ include_examples 'trigger dashboard sync'
+ end
+
+ context 'only unrelated' do
+ let(:commit_changes) { { delete: readme } }
+
+ include_examples 'no dashboard sync'
+ end
+ end
+
+ context 'when updating files' do
+ before do
+ change_repository(create: charts)
+ end
+
+ context 'also related' do
+ let(:commit_changes) { { update: [charts, readme] } }
+
+ include_examples 'trigger dashboard sync'
+ end
+
+ context 'only unrelated' do
+ let(:commit_changes) { { update: readme } }
+
+ include_examples 'no dashboard sync'
+ end
+ end
+
+ context 'without changes' do
+ let(:commit_changes) { {} }
+
+ include_examples 'no dashboard sync'
+ end
+ end
+
+ context 'with other branch' do
+ let(:branch) { 'fix' }
+ let(:commit_changes) { { create: charts } }
+
+ include_examples 'no dashboard sync'
+ end
end
end
diff --git a/spec/services/git/wiki_push_service_spec.rb b/spec/services/git/wiki_push_service_spec.rb
index cd38f2e97fb..df9a48d7b1c 100644
--- a/spec/services/git/wiki_push_service_spec.rb
+++ b/spec/services/git/wiki_push_service_spec.rb
@@ -257,6 +257,46 @@ RSpec.describe Git::WikiPushService, services: true do
end
end
+ describe '#perform_housekeeping', :clean_gitlab_redis_shared_state do
+ let(:housekeeping) { Repositories::HousekeepingService.new(wiki) }
+
+ subject { create_service(current_sha).execute }
+
+ before do
+ allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping)
+ end
+
+ it 'does not perform housekeeping when not needed' do
+ expect(housekeeping).not_to receive(:execute)
+
+ subject
+ end
+
+ context 'when housekeeping is needed' do
+ before do
+ allow(housekeeping).to receive(:needed?).and_return(true)
+ end
+
+ it 'performs housekeeping' do
+ expect(housekeeping).to receive(:execute)
+
+ subject
+ end
+
+ it 'does not raise an exception' do
+ allow(housekeeping).to receive(:try_obtain_lease).and_return(false)
+
+ expect { subject }.not_to raise_error
+ end
+ end
+
+ it 'increments the push counter' do
+ expect(housekeeping).to receive(:increment!)
+
+ subject
+ end
+ end
+
# In order to construct the correct GitPostReceive object that represents the
# changes we are applying, we need to describe the changes between old-ref and
# new-ref. Old ref (the base sha) we have to capture before we perform any
diff --git a/spec/services/groups/import_export/export_service_spec.rb b/spec/services/groups/import_export/export_service_spec.rb
index 690bcb94556..d6ce40f413b 100644
--- a/spec/services/groups/import_export/export_service_spec.rb
+++ b/spec/services/groups/import_export/export_service_spec.rb
@@ -71,6 +71,16 @@ RSpec.describe Groups::ImportExport::ExportService do
service.execute
end
+ it 'compresses and removes tmp files' do
+ expect(group.import_export_upload).to be_nil
+ expect(Gitlab::ImportExport::Saver).to receive(:new).and_call_original
+
+ service.execute
+
+ expect(Dir.exist?(shared.archive_path)).to eq false
+ expect(File.exist?(group.import_export_upload.export_file.path)).to eq true
+ end
+
it 'notifies the user' do
expect_next_instance_of(NotificationService) do |instance|
expect(instance).to receive(:group_was_exported)
@@ -134,7 +144,7 @@ RSpec.describe Groups::ImportExport::ExportService do
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
expect(group.import_export_upload).to be_nil
- expect(Dir.exist?(shared.base_path)).to eq(false)
+ expect(Dir.exist?(shared.archive_path)).to eq(false)
end
it 'notifies the user about failed group export' do
@@ -159,7 +169,7 @@ RSpec.describe Groups::ImportExport::ExportService do
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
expect(group.import_export_upload).to be_nil
- expect(Dir.exist?(shared.base_path)).to eq(false)
+ expect(Dir.exist?(shared.archive_path)).to eq(false)
end
it 'notifies logger' do
diff --git a/spec/services/groups/open_issues_count_service_spec.rb b/spec/services/groups/open_issues_count_service_spec.rb
new file mode 100644
index 00000000000..8bbb1c90c6b
--- /dev/null
+++ b/spec/services/groups/open_issues_count_service_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::OpenIssuesCountService, :use_clean_rails_memory_store_caching do
+ let_it_be(:group) { create(:group, :public)}
+ let_it_be(:project) { create(:project, :public, namespace: group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:issue) { create(:issue, :opened, project: project) }
+ let_it_be(:confidential) { create(:issue, :opened, confidential: true, project: project) }
+ let_it_be(:closed) { create(:issue, :closed, project: project) }
+
+ subject { described_class.new(group, user) }
+
+ describe '#relation_for_count' do
+ before do
+ allow(IssuesFinder).to receive(:new).and_call_original
+ end
+
+ it 'uses the IssuesFinder to scope issues' do
+ expect(IssuesFinder)
+ .to receive(:new)
+ .with(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true, public_only: true)
+
+ subject.count
+ end
+ end
+
+ describe '#count' do
+ context 'when user is nil' do
+ it 'does not include confidential issues in the issue count' do
+ expect(described_class.new(group).count).to eq(1)
+ end
+ end
+
+ context 'when user is provided' do
+ context 'when user can read confidential issues' do
+ before do
+ group.add_reporter(user)
+ end
+
+ it 'returns the right count with confidential issues' do
+ expect(subject.count).to eq(2)
+ end
+ end
+
+ context 'when user cannot read confidential issues' do
+ before do
+ group.add_guest(user)
+ end
+
+ it 'does not include confidential issues' do
+ expect(subject.count).to eq(1)
+ end
+ end
+
+ context 'with different cache values' do
+ let(:public_count_key) { subject.cache_key(described_class::PUBLIC_COUNT_KEY) }
+ let(:under_threshold) { described_class::CACHED_COUNT_THRESHOLD - 1 }
+ let(:over_threshold) { described_class::CACHED_COUNT_THRESHOLD + 1 }
+
+ context 'when cache is empty' do
+ before do
+ Rails.cache.delete(public_count_key)
+ end
+
+ it 'refreshes cache if value over threshold' do
+ allow(subject).to receive(:uncached_count).and_return(over_threshold)
+
+ expect(subject.count).to eq(over_threshold)
+ expect(Rails.cache.read(public_count_key)).to eq(over_threshold)
+ end
+
+ it 'does not refresh cache if value under threshold' do
+ allow(subject).to receive(:uncached_count).and_return(under_threshold)
+
+ expect(subject.count).to eq(under_threshold)
+ expect(Rails.cache.read(public_count_key)).to be_nil
+ end
+ end
+
+ context 'when cached count is under the threshold value' do
+ before do
+ Rails.cache.write(public_count_key, under_threshold)
+ end
+
+ it 'does not refresh cache' do
+ expect(Rails.cache).not_to receive(:write)
+ expect(subject.count).to eq(under_threshold)
+ end
+ end
+
+ context 'when cached count is over the threshold value' do
+ before do
+ Rails.cache.write(public_count_key, over_threshold)
+ end
+
+ it 'does not refresh cache' do
+ expect(Rails.cache).not_to receive(:write)
+ expect(subject.count).to eq(over_threshold)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/integrations/test/project_service_spec.rb b/spec/services/integrations/test/project_service_spec.rb
index dd603765d59..052b25b0f10 100644
--- a/spec/services/integrations/test/project_service_spec.rb
+++ b/spec/services/integrations/test/project_service_spec.rb
@@ -3,11 +3,12 @@
require 'spec_helper'
RSpec.describe Integrations::Test::ProjectService do
- let(:user) { double('user') }
+ include AfterNextHelpers
describe '#execute' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:integration) { create(:slack_service, project: project) }
+ let(:user) { project.owner }
let(:event) { nil }
let(:sample_data) { { data: 'sample' } }
let(:success_result) { { success: true, result: {} } }
@@ -70,16 +71,17 @@ RSpec.describe Integrations::Test::ProjectService do
end
it 'executes integration' do
- allow(project).to receive(:notes).and_return([Note.new])
+ create(:note, project: project)
+
allow(Gitlab::DataBuilder::Note).to receive(:build).and_return(sample_data)
+ allow_next(NotesFinder).to receive(:execute).and_return(Note.all)
expect(integration).to receive(:test).with(sample_data).and_return(success_result)
expect(subject).to eq(success_result)
end
end
- context 'issue' do
- let(:event) { 'issue' }
+ shared_examples_for 'a test of an integration that operates on issues' do
let(:issue) { build(:issue) }
it 'returns error message if not enough data' do
@@ -90,32 +92,28 @@ RSpec.describe Integrations::Test::ProjectService do
it 'executes integration' do
allow(project).to receive(:issues).and_return([issue])
allow(issue).to receive(:to_hook_data).and_return(sample_data)
+ allow_next(IssuesFinder).to receive(:execute).and_return([issue])
expect(integration).to receive(:test).with(sample_data).and_return(success_result)
expect(subject).to eq(success_result)
end
end
- context 'confidential_issue' do
- let(:event) { 'confidential_issue' }
- let(:issue) { build(:issue) }
+ context 'issue' do
+ let(:event) { 'issue' }
- it 'returns error message if not enough data' do
- expect(integration).not_to receive(:test)
- expect(subject).to include({ status: :error, message: 'Ensure the project has issues.' })
- end
+ it_behaves_like 'a test of an integration that operates on issues'
+ end
- it 'executes integration' do
- allow(project).to receive(:issues).and_return([issue])
- allow(issue).to receive(:to_hook_data).and_return(sample_data)
+ context 'confidential_issue' do
+ let(:event) { 'confidential_issue' }
- expect(integration).to receive(:test).with(sample_data).and_return(success_result)
- expect(subject).to eq(success_result)
- end
+ it_behaves_like 'a test of an integration that operates on issues'
end
context 'merge_request' do
let(:event) { 'merge_request' }
+ let(:merge_request) { build(:merge_request) }
it 'returns error message if not enough data' do
expect(integration).not_to receive(:test)
@@ -123,16 +121,17 @@ RSpec.describe Integrations::Test::ProjectService do
end
it 'executes integration' do
- create(:merge_request, source_project: project)
- allow_any_instance_of(MergeRequest).to receive(:to_hook_data).and_return(sample_data)
+ allow(merge_request).to receive(:to_hook_data).and_return(sample_data)
+ allow_next(MergeRequestsFinder).to receive(:execute).and_return([merge_request])
expect(integration).to receive(:test).with(sample_data).and_return(success_result)
- expect(subject).to eq(success_result)
+ expect(subject).to include(success_result)
end
end
context 'deployment' do
- let(:project) { create(:project, :test_repo) }
+ let_it_be(:project) { create(:project, :test_repo) }
+ let(:deployment) { build(:deployment) }
let(:event) { 'deployment' }
it 'returns error message if not enough data' do
@@ -141,8 +140,8 @@ RSpec.describe Integrations::Test::ProjectService do
end
it 'executes integration' do
- create(:deployment, project: project)
allow(Gitlab::DataBuilder::Deployment).to receive(:build).and_return(sample_data)
+ allow_next(DeploymentsFinder).to receive(:execute).and_return([deployment])
expect(integration).to receive(:test).with(sample_data).and_return(success_result)
expect(subject).to eq(success_result)
@@ -151,6 +150,7 @@ RSpec.describe Integrations::Test::ProjectService do
context 'pipeline' do
let(:event) { 'pipeline' }
+ let(:pipeline) { build(:ci_pipeline) }
it 'returns error message if not enough data' do
expect(integration).not_to receive(:test)
@@ -158,8 +158,8 @@ RSpec.describe Integrations::Test::ProjectService do
end
it 'executes integration' do
- create(:ci_empty_pipeline, project: project)
allow(Gitlab::DataBuilder::Pipeline).to receive(:build).and_return(sample_data)
+ allow_next(Ci::PipelinesFinder).to receive(:execute).and_return([pipeline])
expect(integration).to receive(:test).with(sample_data).and_return(success_result)
expect(subject).to eq(success_result)
@@ -167,7 +167,7 @@ RSpec.describe Integrations::Test::ProjectService do
end
context 'wiki_page' do
- let(:project) { create(:project, :wiki_repo) }
+ let_it_be(:project) { create(:project, :wiki_repo) }
let(:event) { 'wiki_page' }
it 'returns error message if wiki disabled' do
diff --git a/spec/services/issue_rebalancing_service_spec.rb b/spec/services/issue_rebalancing_service_spec.rb
index 94f594c8083..7b3d4213b24 100644
--- a/spec/services/issue_rebalancing_service_spec.rb
+++ b/spec/services/issue_rebalancing_service_spec.rb
@@ -32,70 +32,88 @@ RSpec.describe IssueRebalancingService do
project.reload.issues.reorder(relative_position: :asc).to_a
end
- it 'rebalances a set of issues with clumps at the end and start' do
- all_issues = start_clump + unclumped + end_clump.reverse
- service = described_class.new(project.issues.first)
+ shared_examples 'IssueRebalancingService shared examples' do
+ it 'rebalances a set of issues with clumps at the end and start' do
+ all_issues = start_clump + unclumped + end_clump.reverse
+ service = described_class.new(project.issues.first)
- expect { service.execute }.not_to change { issues_in_position_order.map(&:id) }
+ expect { service.execute }.not_to change { issues_in_position_order.map(&:id) }
- all_issues.each(&:reset)
+ all_issues.each(&:reset)
- gaps = all_issues.take(all_issues.count - 1).zip(all_issues.drop(1)).map do |a, b|
- b.relative_position - a.relative_position
+ gaps = all_issues.take(all_issues.count - 1).zip(all_issues.drop(1)).map do |a, b|
+ b.relative_position - a.relative_position
+ end
+
+ expect(gaps).to all(be > RelativePositioning::MIN_GAP)
+ expect(all_issues.first.relative_position).to be > (RelativePositioning::MIN_POSITION * 0.9999)
+ expect(all_issues.last.relative_position).to be < (RelativePositioning::MAX_POSITION * 0.9999)
end
- expect(gaps).to all(be > RelativePositioning::MIN_GAP)
- expect(all_issues.first.relative_position).to be > (RelativePositioning::MIN_POSITION * 0.9999)
- expect(all_issues.last.relative_position).to be < (RelativePositioning::MAX_POSITION * 0.9999)
- end
+ it 'is idempotent' do
+ service = described_class.new(project.issues.first)
- it 'is idempotent' do
- service = described_class.new(project.issues.first)
+ expect do
+ service.execute
+ service.execute
+ end.not_to change { issues_in_position_order.map(&:id) }
+ end
- expect do
- service.execute
- service.execute
- end.not_to change { issues_in_position_order.map(&:id) }
- end
+ it 'does nothing if the feature flag is disabled' do
+ stub_feature_flags(rebalance_issues: false)
+ issue = project.issues.first
+ issue.project
+ issue.project.group
+ old_pos = issue.relative_position
- it 'does nothing if the feature flag is disabled' do
- stub_feature_flags(rebalance_issues: false)
- issue = project.issues.first
- issue.project
- issue.project.group
- old_pos = issue.relative_position
+ service = described_class.new(issue)
- service = described_class.new(issue)
+ expect { service.execute }.not_to exceed_query_limit(0)
+ expect(old_pos).to eq(issue.reload.relative_position)
+ end
- expect { service.execute }.not_to exceed_query_limit(0)
- expect(old_pos).to eq(issue.reload.relative_position)
- end
+ it 'acts if the flag is enabled for the project' do
+ issue = create(:issue, project: project, author: user, relative_position: max_pos)
+ stub_feature_flags(rebalance_issues: issue.project)
- it 'acts if the flag is enabled for the project' do
- issue = create(:issue, project: project, author: user, relative_position: max_pos)
- stub_feature_flags(rebalance_issues: issue.project)
+ service = described_class.new(issue)
- service = described_class.new(issue)
+ expect { service.execute }.to change { issue.reload.relative_position }
+ end
- expect { service.execute }.to change { issue.reload.relative_position }
- end
+ it 'acts if the flag is enabled for the group' do
+ issue = create(:issue, project: project, author: user, relative_position: max_pos)
+ project.update!(group: create(:group))
+ stub_feature_flags(rebalance_issues: issue.project.group)
- it 'acts if the flag is enabled for the group' do
- issue = create(:issue, project: project, author: user, relative_position: max_pos)
- project.update!(group: create(:group))
- stub_feature_flags(rebalance_issues: issue.project.group)
+ service = described_class.new(issue)
- service = described_class.new(issue)
+ expect { service.execute }.to change { issue.reload.relative_position }
+ end
+
+ it 'aborts if there are too many issues' do
+ issue = project.issues.first
+ base = double(count: 10_001)
- expect { service.execute }.to change { issue.reload.relative_position }
+ allow(Issue).to receive(:relative_positioning_query_base).with(issue).and_return(base)
+
+ expect { described_class.new(issue).execute }.to raise_error(described_class::TooManyIssues)
+ end
end
- it 'aborts if there are too many issues' do
- issue = project.issues.first
- base = double(count: 10_001)
+ context 'when issue_rebalancing_optimization feature flag is on' do
+ before do
+ stub_feature_flags(issue_rebalancing_optimization: true)
+ end
+
+ it_behaves_like 'IssueRebalancingService shared examples'
+ end
- allow(Issue).to receive(:relative_positioning_query_base).with(issue).and_return(base)
+ context 'when issue_rebalancing_optimization feature flag is on' do
+ before do
+ stub_feature_flags(issue_rebalancing_optimization: false)
+ end
- expect { described_class.new(issue).execute }.to raise_error(described_class::TooManyIssues)
+ it_behaves_like 'IssueRebalancingService shared examples'
end
end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index dc545f57d23..3cf45143594 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -84,6 +84,7 @@ RSpec.describe Issues::CloseService do
let!(:external_issue_tracker) { create(:jira_service, project: project) }
it 'closes the issue on the external issue tracker' do
+ project.reload
expect(project.external_issue_tracker).to receive(:close_issue)
described_class.new(project, user).close_issue(external_issue)
@@ -94,6 +95,7 @@ RSpec.describe Issues::CloseService do
let!(:external_issue_tracker) { create(:jira_service, project: project, active: false) }
it 'does not close the issue on the external issue tracker' do
+ project.reload
expect(project.external_issue_tracker).not_to receive(:close_issue)
described_class.new(project, user).close_issue(external_issue)
@@ -104,6 +106,7 @@ RSpec.describe Issues::CloseService do
let!(:external_issue_tracker) { create(:bugzilla_service, project: project) }
it 'does not close the issue on the external issue tracker' do
+ project.reload
expect(project.external_issue_tracker).not_to receive(:close_issue)
described_class.new(project, user).close_issue(external_issue)
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index cc6a49fc4cf..e42e9722297 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -452,162 +452,50 @@ RSpec.describe Issues::CreateService do
end
context 'checking spam' do
- include_context 'includes Spam constants'
+ let(:request) { double(:request) }
+ let(:api) { true }
+ let(:captcha_response) { 'abc123' }
+ let(:spam_log_id) { 1 }
- let(:title) { 'Legit issue' }
- let(:description) { 'please fix' }
- let(:opts) do
+ let(:params) do
{
- title: title,
- description: description,
- request: double(:request, env: {})
+ title: 'Spam issue',
+ request: request,
+ api: api,
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
}
end
- subject { described_class.new(project, user, opts) }
-
- before do
- stub_feature_flags(allow_possible_spam: false)
+ subject do
+ described_class.new(project, user, params)
end
- context 'when reCAPTCHA was verified' do
- let(:log_user) { user }
- let(:spam_logs) { create_list(:spam_log, 2, user: log_user, title: title) }
- let(:target_spam_log) { spam_logs.last }
-
- before do
- opts[:recaptcha_verified] = true
- opts[:spam_log_id] = target_spam_log.id
-
- expect(Spam::SpamVerdictService).not_to receive(:new)
- end
-
- it 'does not mark an issue as spam' do
- expect(issue).not_to be_spam
- end
-
- it 'creates a valid issue' do
- expect(issue).to be_valid
- end
-
- it 'does not assign a spam_log to the issue' do
- expect(issue.spam_log).to be_nil
- end
-
- it 'marks related spam_log as recaptcha_verified' do
- expect { issue }.to change { target_spam_log.reload.recaptcha_verified }.from(false).to(true)
- end
-
- context 'when spam log does not belong to a user' do
- let(:log_user) { create(:user) }
-
- it 'does not mark spam_log as recaptcha_verified' do
- expect { issue }.not_to change { target_spam_log.reload.recaptcha_verified }
- end
+ before do
+ allow_next_instance_of(UserAgentDetailService) do |instance|
+ allow(instance).to receive(:create)
end
end
- context 'when reCAPTCHA was not verified' do
- before do
- expect_next_instance_of(Spam::SpamActionService) do |spam_service|
- expect(spam_service).to receive_messages(check_for_spam?: true)
- end
- end
-
- context 'when SpamVerdictService requires reCAPTCHA' do
- before do
- expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
- expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW)
- end
- end
-
- it 'does not mark the issue as spam' do
- expect(issue).not_to be_spam
- end
-
- it 'marks the issue as needing reCAPTCHA' do
- expect(issue.needs_recaptcha?).to be_truthy
- end
-
- it 'invalidates the issue' do
- expect(issue).to be_invalid
- end
-
- it 'creates a new spam_log' do
- expect { issue }
- .to have_spam_log(title: title, description: description, user_id: user.id, noteable_type: 'Issue')
- end
- end
-
- context 'when SpamVerdictService disallows creation' do
- before do
- expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
- expect(verdict_service).to receive(:execute).and_return(DISALLOW)
- end
- end
-
- context 'when allow_possible_spam feature flag is false' do
- it 'marks the issue as spam' do
- expect(issue).to be_spam
- end
-
- it 'does not mark the issue as needing reCAPTCHA' do
- expect(issue.needs_recaptcha?).to be_falsey
- end
-
- it 'invalidates the issue' do
- expect(issue).to be_invalid
- end
-
- it 'creates a new spam_log' do
- expect { issue }
- .to have_spam_log(title: title, description: description, user_id: user.id, noteable_type: 'Issue')
- end
- end
-
- context 'when allow_possible_spam feature flag is true' do
- before do
- stub_feature_flags(allow_possible_spam: true)
- end
-
- it 'does not mark the issue as spam' do
- expect(issue).not_to be_spam
- end
-
- it 'does not mark the issue as needing reCAPTCHA' do
- expect(issue.needs_recaptcha?).to be_falsey
- end
-
- it 'creates a valid issue' do
- expect(issue).to be_valid
- end
-
- it 'creates a new spam_log' do
- expect { issue }
- .to have_spam_log(title: title, description: description, user_id: user.id, noteable_type: 'Issue')
- end
- end
+ it 'executes SpamActionService' do
+ spam_params = Spam::SpamParams.new(
+ api: api,
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ )
+ expect_next_instance_of(
+ Spam::SpamActionService,
+ {
+ spammable: an_instance_of(Issue),
+ request: request,
+ user: user,
+ action: :create
+ }
+ ) do |instance|
+ expect(instance).to receive(:execute).with(spam_params: spam_params)
end
- context 'when the SpamVerdictService allows creation' do
- before do
- expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service|
- expect(verdict_service).to receive(:execute).and_return(ALLOW)
- end
- end
-
- it 'does not mark an issue as spam' do
- expect(issue).not_to be_spam
- end
-
- it 'creates a valid issue' do
- expect(issue).to be_valid
- end
-
- it 'does not assign a spam_log to an issue' do
- expect(issue.spam_log).to be_nil
- end
- end
+ subject.execute
end
end
end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 06a6a52bc41..fd42a84e405 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -711,7 +711,7 @@ RSpec.describe Issues::UpdateService, :mailer do
}
service = described_class.new(project, user, params)
- expect(service).not_to receive(:spam_check)
+ expect(Spam::SpamActionService).not_to receive(:new)
service.execute(issue)
end
diff --git a/spec/services/members/update_service_spec.rb b/spec/services/members/update_service_spec.rb
index 2d4457f3f62..a1b1397d444 100644
--- a/spec/services/members/update_service_spec.rb
+++ b/spec/services/members/update_service_spec.rb
@@ -13,9 +13,11 @@ RSpec.describe Members::UpdateService do
{ access_level: Gitlab::Access::MAINTAINER }
end
+ subject { described_class.new(current_user, params).execute(member, permission: permission) }
+
shared_examples 'a service raising Gitlab::Access::AccessDeniedError' do
it 'raises Gitlab::Access::AccessDeniedError' do
- expect { described_class.new(current_user, params).execute(member, permission: permission) }
+ expect { subject }
.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
@@ -24,18 +26,24 @@ RSpec.describe Members::UpdateService do
it 'updates the member' do
expect(TodosDestroyer::EntityLeaveWorker).not_to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, source.class.name)
- updated_member = described_class.new(current_user, params).execute(member, permission: permission)
+ updated_member = subject.fetch(:member)
expect(updated_member).to be_valid
expect(updated_member.access_level).to eq(Gitlab::Access::MAINTAINER)
end
+ it 'returns success status' do
+ result = subject.fetch(:status)
+
+ expect(result).to eq(:success)
+ end
+
context 'when member is downgraded to guest' do
shared_examples 'schedules to delete confidential todos' do
it do
expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, source.class.name).once
- updated_member = described_class.new(current_user, params).execute(member, permission: permission)
+ updated_member = subject.fetch(:member)
expect(updated_member).to be_valid
expect(updated_member.access_level).to eq(Gitlab::Access::GUEST)
@@ -62,6 +70,16 @@ RSpec.describe Members::UpdateService do
expect { described_class.new(current_user, params) }.to raise_error(ArgumentError, 'invalid value for Integer(): "invalid"')
end
end
+
+ context 'when member is not valid' do
+ let(:params) { { expires_at: 2.days.ago } }
+
+ it 'returns error status' do
+ result = subject
+
+ expect(result[:status]).to eq(:error)
+ end
+ end
end
before do
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index 9ae310d8cee..f21feb70bc5 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe MergeRequests::AfterCreateService do
- include AfterNextHelpers
-
let_it_be(:merge_request) { create(:merge_request) }
subject(:after_create_service) do
@@ -66,15 +64,8 @@ RSpec.describe MergeRequests::AfterCreateService do
execute_service
end
- it 'registers an onboarding progress action' do
- OnboardingProgress.onboard(merge_request.target_project.namespace)
-
- expect_next(OnboardingProgressService, merge_request.target_project.namespace)
- .to receive(:execute).with(action: :merge_request_created).and_call_original
-
- execute_service
-
- expect(OnboardingProgress.completed?(merge_request.target_project.namespace, :merge_request_created)).to be(true)
+ it_behaves_like 'records an onboarding progress action', :merge_request_created do
+ let(:namespace) { merge_request.target_project.namespace }
end
end
end
diff --git a/spec/services/merge_requests/approval_service_spec.rb b/spec/services/merge_requests/approval_service_spec.rb
index 124501f17d5..df9a98c5540 100644
--- a/spec/services/merge_requests/approval_service_spec.rb
+++ b/spec/services/merge_requests/approval_service_spec.rb
@@ -31,6 +31,13 @@ RSpec.describe MergeRequests::ApprovalService do
expect(todo.reload).to be_pending
end
+
+ it 'does not track merge request approve action' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_approve_mr_action).with(user: user)
+
+ service.execute(merge_request)
+ end
end
context 'with valid approval' do
@@ -59,6 +66,13 @@ RSpec.describe MergeRequests::ApprovalService do
service.execute(merge_request)
end
end
+
+ it 'tracks merge request approve action' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_approve_mr_action).with(user: user)
+
+ service.execute(merge_request)
+ end
end
context 'user cannot update the merge request' do
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index f83b8d98ce8..22b3456708f 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -252,6 +252,7 @@ RSpec.describe MergeRequests::BuildService do
issue.update!(iid: 123)
else
create(:"#{issue_tracker}_service", project: project)
+ project.reload
end
end
@@ -351,6 +352,7 @@ RSpec.describe MergeRequests::BuildService do
issue.update!(iid: 123)
else
create(:"#{issue_tracker}_service", project: project)
+ project.reload
end
end
diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb
index be8c41bc4a1..6528edfc8b7 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -52,6 +52,14 @@ RSpec.describe MergeRequests::CreateFromIssueService do
service.execute
end
+ it 'tracks the mr creation when the mr is valid' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_mr_create_from_issue)
+ .with(user: user)
+
+ service.execute
+ end
+
it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created', :sidekiq_might_not_need_inline do
expect_next_instance_of(MergeRequest) do |instance|
expect(instance).to receive(:valid?).at_least(:once).and_return(false)
@@ -62,6 +70,17 @@ RSpec.describe MergeRequests::CreateFromIssueService do
service.execute
end
+ it 'does not track the mr creation when the Mr is invalid' do
+ expect_next_instance_of(MergeRequest) do |instance|
+ expect(instance).to receive(:valid?).at_least(:once).and_return(false)
+ end
+
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_mr_create_from_issue)
+
+ service.execute
+ end
+
it 'creates a merge request', :sidekiq_might_not_need_inline do
expect { service.execute }.to change(target_project.merge_requests, :count).by(1)
end
diff --git a/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb b/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb
index cdaacaf5fca..d2070a466b1 100644
--- a/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb
+++ b/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe MergeRequests::DeleteNonLatestDiffsService, :clean_gitlab_redis_s
stub_const("#{described_class.name}::BATCH_SIZE", 2)
3.times { merge_request.create_merge_request_diff }
+ merge_request.create_merge_head_diff
+ merge_request.reset
end
it 'schedules non-latest merge request diffs removal' do
diff --git a/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb b/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb
new file mode 100644
index 00000000000..1075f6f9034
--- /dev/null
+++ b/spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::MarkReviewerReviewedService do
+ let(:current_user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [current_user]) }
+ let(:reviewer) { merge_request.merge_request_reviewers.find_by(user_id: current_user.id) }
+ let(:project) { merge_request.project }
+ let(:service) { described_class.new(project, current_user) }
+ let(:result) { service.execute(merge_request) }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ describe '#execute' do
+ describe 'invalid permissions' do
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ describe 'reviewer does not exist' do
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ describe 'reviewer exists' do
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates reviewers state' do
+ expect(result[:status]).to eq :success
+ expect(reviewer.state).to eq 'reviewed'
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index dd37d87e3f5..611f12c8146 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -161,7 +161,7 @@ RSpec.describe MergeRequests::MergeService do
commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}")
allow(merge_request).to receive(:commits).and_return([commit])
- expect_any_instance_of(JiraService).to receive(:close_issue).with(merge_request, jira_issue).once
+ expect_any_instance_of(JiraService).to receive(:close_issue).with(merge_request, jira_issue, user).once
service.execute(merge_request)
end
@@ -310,12 +310,12 @@ RSpec.describe MergeRequests::MergeService do
it 'logs and saves error if there is an exception' do
error_message = 'error message'
- allow(service).to receive(:repository).and_raise('error message')
+ allow(service).to receive(:repository).and_raise(error_message)
allow(service).to receive(:execute_hooks)
service.execute(merge_request)
- expect(merge_request.merge_error).to include('Something went wrong during merge')
+ expect(merge_request.merge_error).to eq(described_class::GENERIC_ERROR_MESSAGE)
expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
end
@@ -343,9 +343,7 @@ RSpec.describe MergeRequests::MergeService do
expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
end
- it 'logs and saves error if there is a merge conflict' do
- error_message = 'Conflicts detected during merge'
-
+ it 'logs and saves error if commit is not created' do
allow_any_instance_of(Repository).to receive(:merge).and_return(false)
allow(service).to receive(:execute_hooks)
@@ -353,8 +351,8 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
- expect(merge_request.merge_error).to include(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(merge_request.merge_error).to include(described_class::GENERIC_ERROR_MESSAGE)
+ expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(described_class::GENERIC_ERROR_MESSAGE))
end
context 'when squashing is required' do
diff --git a/spec/services/merge_requests/mergeability_check_service_spec.rb b/spec/services/merge_requests/mergeability_check_service_spec.rb
index 17bfa9d7368..e0baf5af8b4 100644
--- a/spec/services/merge_requests/mergeability_check_service_spec.rb
+++ b/spec/services/merge_requests/mergeability_check_service_spec.rb
@@ -33,6 +33,14 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
expect(merge_request.merge_status).to eq('can_be_merged')
end
+ it 'reloads merge head diff' do
+ expect_next_instance_of(MergeRequests::ReloadMergeHeadDiffService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ subject
+ end
+
it 'update diff discussion positions' do
expect_next_instance_of(Discussions::CaptureDiffNotePositionsService) do |service|
expect(service).to receive(:execute)
@@ -142,7 +150,11 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
end
it 'resets one merge request upon execution' do
- expect_any_instance_of(MergeRequest).to receive(:reset).once
+ expect_next_instance_of(MergeRequests::ReloadMergeHeadDiffService) do |svc|
+ expect(svc).to receive(:execute).and_return(status: :success)
+ end
+
+ expect_any_instance_of(MergeRequest).to receive(:reset).once.and_call_original
execute_within_threads(amount: 2)
end
@@ -266,6 +278,14 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
it_behaves_like 'unmergeable merge request'
+ it 'reloads merge head diff' do
+ expect_next_instance_of(MergeRequests::ReloadMergeHeadDiffService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ subject
+ end
+
it 'returns ServiceResponse.error' do
result = subject
@@ -329,6 +349,12 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
subject
end
+
+ it 'does not reload merge head diff' do
+ expect(MergeRequests::ReloadMergeHeadDiffService).not_to receive(:new)
+
+ subject
+ end
end
end
diff --git a/spec/services/merge_requests/post_merge_service_spec.rb b/spec/services/merge_requests/post_merge_service_spec.rb
index 6523b5a158c..71329905558 100644
--- a/spec/services/merge_requests/post_merge_service_spec.rb
+++ b/spec/services/merge_requests/post_merge_service_spec.rb
@@ -3,9 +3,11 @@
require 'spec_helper'
RSpec.describe MergeRequests::PostMergeService do
- let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request, assignees: [user]) }
- let(:project) { merge_request.project }
+ include ProjectForksHelper
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request, reload: true) { create(:merge_request, assignees: [user]) }
+ let_it_be(:project) { merge_request.project }
subject { described_class.new(project, user).execute(merge_request) }
@@ -128,5 +130,139 @@ RSpec.describe MergeRequests::PostMergeService do
expect(deploy_job.reload.canceled?).to be false
end
end
+
+ context 'for a merge request chain' do
+ before do
+ ::MergeRequests::UpdateService
+ .new(project, user, force_remove_source_branch: '1')
+ .execute(merge_request)
+ end
+
+ context 'when there is another MR' do
+ let!(:another_merge_request) do
+ create(:merge_request,
+ source_project: source_project,
+ source_branch: 'my-awesome-feature',
+ target_project: merge_request.source_project,
+ target_branch: merge_request.source_branch
+ )
+ end
+
+ shared_examples 'does not retarget merge request' do
+ it 'another merge request is unchanged' do
+ expect { subject }.not_to change { another_merge_request.reload.target_branch }
+ .from(merge_request.source_branch)
+ end
+ end
+
+ shared_examples 'retargets merge request' do
+ it 'another merge request is retargeted' do
+ expect(SystemNoteService)
+ .to receive(:change_branch).once
+ .with(another_merge_request, another_merge_request.project, user,
+ 'target', 'delete',
+ merge_request.source_branch, merge_request.target_branch)
+
+ expect { subject }.to change { another_merge_request.reload.target_branch }
+ .from(merge_request.source_branch)
+ .to(merge_request.target_branch)
+ end
+
+ context 'when FF retarget_merge_requests is disabled' do
+ before do
+ stub_feature_flags(retarget_merge_requests: false)
+ end
+
+ include_examples 'does not retarget merge request'
+ end
+
+ context 'when source branch is to be kept' do
+ before do
+ ::MergeRequests::UpdateService
+ .new(project, user, force_remove_source_branch: false)
+ .execute(merge_request)
+ end
+
+ include_examples 'does not retarget merge request'
+ end
+ end
+
+ context 'in the same project' do
+ let(:source_project) { project }
+
+ it_behaves_like 'retargets merge request'
+
+ context 'and is closed' do
+ before do
+ another_merge_request.close
+ end
+
+ it_behaves_like 'does not retarget merge request'
+ end
+
+ context 'and is merged' do
+ before do
+ another_merge_request.mark_as_merged
+ end
+
+ it_behaves_like 'does not retarget merge request'
+ end
+ end
+
+ context 'in forked project' do
+ let!(:source_project) { fork_project(project) }
+
+ context 'when user has access to source project' do
+ before do
+ source_project.add_developer(user)
+ end
+
+ it_behaves_like 'retargets merge request'
+ end
+
+ context 'when user does not have access to source project' do
+ it_behaves_like 'does not retarget merge request'
+ end
+ end
+
+ context 'and current and another MR is from a fork' do
+ let(:project) { create(:project) }
+ let(:source_project) { fork_project(project) }
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: source_project,
+ target_project: project
+ )
+ end
+
+ before do
+ source_project.add_developer(user)
+ end
+
+ it_behaves_like 'does not retarget merge request'
+ end
+ end
+
+ context 'when many merge requests are to be retargeted' do
+ let!(:many_merge_requests) do
+ create_list(:merge_request, 10, :unique_branches,
+ source_project: merge_request.source_project,
+ target_project: merge_request.source_project,
+ target_branch: merge_request.source_branch
+ )
+ end
+
+ it 'retargets only 4 of them' do
+ subject
+
+ expect(many_merge_requests.each(&:reload).pluck(:target_branch).tally)
+ .to eq(
+ merge_request.source_branch => 6,
+ merge_request.target_branch => 4
+ )
+ end
+ end
+ end
end
end
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index 85bcf4562b1..c2769d4fa88 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
let(:existing_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{source_branch}" }
let(:deleted_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 #{Gitlab::Git::BLANK_SHA} refs/heads/#{source_branch}" }
let(:default_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{project.default_branch}" }
+ let(:error_mr_required) { "A merge_request.create push option is required to create a merge request for branch #{source_branch}" }
shared_examples_for 'a service that can create a merge request' do
subject(:last_mr) { MergeRequest.last }
@@ -176,11 +177,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -197,11 +196,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -263,11 +260,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -308,11 +303,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -329,11 +322,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -374,11 +365,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -395,11 +384,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -440,11 +427,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -461,11 +446,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -506,11 +489,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
@@ -527,11 +508,9 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
it_behaves_like 'a service that does not create a merge request'
it 'adds an error to the service' do
- error = "A merge_request.create push option is required to create a merge request for branch #{source_branch}"
-
service.execute
- expect(service.errors).to include(error)
+ expect(service.errors).to include(error_mr_required)
end
context 'when coupled with the `create` push option' do
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 3ccf02fcdfb..747ecbf4fa4 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -633,31 +633,37 @@ RSpec.describe MergeRequests::RefreshService do
end
context 'merge request metrics' do
- let(:issue) { create :issue, project: @project }
- let(:commit_author) { create :user }
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:issue) { create(:issue, project: project) }
let(:commit) { project.commit }
before do
- project.add_developer(commit_author)
project.add_developer(user)
allow(commit).to receive_messages(
safe_message: "Closes #{issue.to_reference}",
references: [issue],
- author_name: commit_author.name,
- author_email: commit_author.email,
+ author_name: user.name,
+ author_email: user.email,
committed_date: Time.current
)
-
- allow_any_instance_of(MergeRequest).to receive(:commits).and_return(CommitCollection.new(@project, [commit], 'feature'))
end
context 'when the merge request is sourced from the same project' do
it 'creates a `MergeRequestsClosingIssues` record for each issue closed by a commit' do
- merge_request = create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: @project)
- refresh_service = service.new(@project, @user)
+ allow_any_instance_of(MergeRequest).to receive(:commits).and_return(
+ CommitCollection.new(project, [commit], 'close-by-commit')
+ )
+
+ merge_request = create(:merge_request,
+ target_branch: 'master',
+ source_branch: 'close-by-commit',
+ source_project: project)
+
+ refresh_service = service.new(project, user)
allow(refresh_service).to receive(:execute_hooks)
- refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature')
+ refresh_service.execute(@oldrev, @newrev, 'refs/heads/close-by-commit')
issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id)
expect(issue_ids).to eq([issue.id])
@@ -666,16 +672,21 @@ RSpec.describe MergeRequests::RefreshService do
context 'when the merge request is sourced from a different project' do
it 'creates a `MergeRequestsClosingIssues` record for each issue closed by a commit' do
- forked_project = fork_project(@project, @user, repository: true)
+ forked_project = fork_project(project, user, repository: true)
+
+ allow_any_instance_of(MergeRequest).to receive(:commits).and_return(
+ CommitCollection.new(forked_project, [commit], 'close-by-commit')
+ )
merge_request = create(:merge_request,
target_branch: 'master',
- source_branch: 'feature',
- target_project: @project,
+ target_project: project,
+ source_branch: 'close-by-commit',
source_project: forked_project)
- refresh_service = service.new(@project, @user)
+
+ refresh_service = service.new(forked_project, user)
allow(refresh_service).to receive(:execute_hooks)
- refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature')
+ refresh_service.execute(@oldrev, @newrev, 'refs/heads/close-by-commit')
issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id)
expect(issue_ids).to eq([issue.id])
diff --git a/spec/services/merge_requests/reload_merge_head_diff_service_spec.rb b/spec/services/merge_requests/reload_merge_head_diff_service_spec.rb
new file mode 100644
index 00000000000..3152a4e3861
--- /dev/null
+++ b/spec/services/merge_requests/reload_merge_head_diff_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ReloadMergeHeadDiffService do
+ let(:merge_request) { create(:merge_request) }
+
+ subject { described_class.new(merge_request).execute }
+
+ describe '#execute' do
+ before do
+ MergeRequests::MergeToRefService
+ .new(merge_request.project, merge_request.author)
+ .execute(merge_request)
+ end
+
+ it 'creates a merge head diff' do
+ expect(subject[:status]).to eq(:success)
+ expect(merge_request.reload.merge_head_diff).to be_present
+ end
+
+ context 'when merge ref head is not present' do
+ before do
+ allow(merge_request).to receive(:merge_ref_head).and_return(nil)
+ end
+
+ it 'returns error' do
+ expect(subject[:status]).to eq(:error)
+ end
+ end
+
+ context 'when failed to create merge head diff' do
+ before do
+ allow(merge_request).to receive(:create_merge_head_diff!).and_raise('fail')
+ end
+
+ it 'returns error' do
+ expect(subject[:status]).to eq(:error)
+ end
+ end
+
+ context 'when there is existing merge head diff' do
+ let!(:existing_merge_head_diff) { create(:merge_request_diff, :merge_head, merge_request: merge_request) }
+
+ it 'recreates merge head diff' do
+ expect(subject[:status]).to eq(:success)
+ expect(merge_request.reload.merge_head_diff).not_to eq(existing_merge_head_diff)
+ end
+ end
+
+ context 'when default_merge_ref_for_diffs feature flag is disabled' do
+ before do
+ stub_feature_flags(default_merge_ref_for_diffs: false)
+ end
+
+ it 'returns error' do
+ expect(subject[:status]).to eq(:error)
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/remove_approval_service_spec.rb b/spec/services/merge_requests/remove_approval_service_spec.rb
index 40da928e832..4ef2da290e1 100644
--- a/spec/services/merge_requests/remove_approval_service_spec.rb
+++ b/spec/services/merge_requests/remove_approval_service_spec.rb
@@ -32,6 +32,13 @@ RSpec.describe MergeRequests::RemoveApprovalService do
execute!
end
+
+ it 'tracks merge request unapprove action' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_unapprove_mr_action).with(user: user)
+
+ execute!
+ end
end
context 'with a user who has not approved' do
@@ -41,6 +48,13 @@ RSpec.describe MergeRequests::RemoveApprovalService do
execute!
end
+
+ it 'does not track merge request unapprove action' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_unapprove_mr_action).with(user: user)
+
+ execute!
+ end
end
end
end
diff --git a/spec/services/merge_requests/request_review_service_spec.rb b/spec/services/merge_requests/request_review_service_spec.rb
new file mode 100644
index 00000000000..5cb4120852a
--- /dev/null
+++ b/spec/services/merge_requests/request_review_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::RequestReviewService do
+ let(:current_user) { create(:user) }
+ let(:user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [user]) }
+ let(:reviewer) { merge_request.find_reviewer(user) }
+ let(:project) { merge_request.project }
+ let(:service) { described_class.new(project, current_user) }
+ let(:result) { service.execute(merge_request, user) }
+ let(:todo_service) { spy('todo service') }
+ let(:notification_service) { spy('notification service') }
+
+ before do
+ allow(NotificationService).to receive(:new) { notification_service }
+ allow(service).to receive(:todo_service).and_return(todo_service)
+ allow(service).to receive(:notification_service).and_return(notification_service)
+
+ reviewer.update!(state: MergeRequestReviewer.states[:reviewed])
+
+ project.add_developer(current_user)
+ project.add_developer(user)
+ end
+
+ describe '#execute' do
+ describe 'invalid permissions' do
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ describe 'reviewer does not exist' do
+ let(:result) { service.execute(merge_request, create(:user)) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ describe 'reviewer exists' do
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates reviewers state' do
+ service.execute(merge_request, user)
+ reviewer.reload
+
+ expect(reviewer.state).to eq 'unreviewed'
+ end
+
+ it 'sends email to reviewer' do
+ expect(notification_service).to receive_message_chain(:async, :review_requested_of_merge_request).with(merge_request, current_user, user)
+
+ service.execute(merge_request, user)
+ end
+
+ it 'creates a new todo for the reviewer' do
+ expect(todo_service).to receive(:create_request_review_todo).with(merge_request, current_user, user)
+
+ service.execute(merge_request, user)
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 9eb82dcd0ad..edb95840604 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -87,6 +87,38 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(@merge_request.discussion_locked).to be_truthy
end
+ context 'usage counters' do
+ let(:merge_request2) { create(:merge_request) }
+ let(:draft_merge_request) { create(:merge_request, :draft_merge_request)}
+
+ it 'update as expected' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_title_edit_action).once.with(user: user)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_description_edit_action).once.with(user: user)
+
+ MergeRequests::UpdateService.new(project, user, opts).execute(merge_request2)
+ end
+
+ it 'tracks Draft/WIP marking' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_marked_as_draft_action).once.with(user: user)
+
+ opts[:title] = "WIP: #{opts[:title]}"
+
+ MergeRequests::UpdateService.new(project, user, opts).execute(merge_request2)
+ end
+
+ it 'tracks Draft/WIP un-marking' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_unmarked_as_draft_action).once.with(user: user)
+
+ opts[:title] = "Non-draft/wip title string"
+
+ MergeRequests::UpdateService.new(project, user, opts).execute(draft_merge_request)
+ end
+ end
+
context 'updating milestone' do
RSpec.shared_examples 'updates milestone' do
it 'sets milestone' do
@@ -142,29 +174,19 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
context 'with reviewers' do
let(:opts) { { reviewer_ids: [user2.id] } }
- context 'when merge_request_reviewers feature is disabled' do
- before(:context) do
- stub_feature_flags(merge_request_reviewers: false)
- end
-
- it 'does not create a system note about merge_request review request' do
- note = find_note('review requested from')
+ it 'creates system note about merge_request review request' do
+ note = find_note('requested review from')
- expect(note).to be_nil
- end
+ expect(note).not_to be_nil
+ expect(note.note).to include "requested review from #{user2.to_reference}"
end
- context 'when merge_request_reviewers feature is enabled' do
- before(:context) do
- stub_feature_flags(merge_request_reviewers: true)
- end
-
- it 'creates system note about merge_request review request' do
- note = find_note('requested review from')
+ it 'updates the tracking' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_users_review_requested)
+ .with(users: [user])
- expect(note).not_to be_nil
- expect(note.note).to include "requested review from #{user2.to_reference}"
- end
+ update_merge_request(reviewer_ids: [user.id])
end
end
@@ -794,6 +816,14 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(merge_request.assignee_ids).to eq([user.id])
end
+ it 'updates the tracking when user ids are valid' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_users_assigned_to_mr)
+ .with(users: [user])
+
+ update_merge_request(assignee_ids: [user.id])
+ end
+
it 'does not update assignee_id when user cannot read issue' do
non_member = create(:user)
original_assignees = merge_request.assignees
@@ -883,6 +913,33 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
end
+ context 'updating `target_branch`' do
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ source_branch: 'mr-b',
+ target_branch: 'mr-a')
+ end
+
+ it 'updates to master' do
+ expect(SystemNoteService).to receive(:change_branch).with(
+ merge_request, project, user, 'target', 'update', 'mr-a', 'master'
+ )
+
+ expect { update_merge_request(target_branch: 'master') }
+ .to change { merge_request.reload.target_branch }.from('mr-a').to('master')
+ end
+
+ it 'updates to master because of branch deletion' do
+ expect(SystemNoteService).to receive(:change_branch).with(
+ merge_request, project, user, 'target', 'delete', 'mr-a', 'master'
+ )
+
+ expect { update_merge_request(target_branch: 'master', target_branch_was_deleted: true) }
+ .to change { merge_request.reload.target_branch }.from('mr-a').to('master')
+ end
+ end
+
it_behaves_like 'issuable record that supports quick actions' do
let(:existing_merge_request) { create(:merge_request, source_project: project) }
let(:issuable) { described_class.new(project, user, params).execute(existing_merge_request) }
diff --git a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
new file mode 100644
index 00000000000..7346a5b95ae
--- /dev/null
+++ b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
@@ -0,0 +1,159 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
+ subject(:execute_service) { described_class.new(track, interval).execute }
+
+ let(:track) { :create }
+ let(:interval) { 1 }
+
+ let(:previous_action_completed_at) { 2.days.ago.middle_of_day }
+ let(:current_action_completed_at) { nil }
+ let(:experiment_enabled) { true }
+ let(:user_can_perform_current_track_action) { true }
+ let(:actions_completed) { { created_at: previous_action_completed_at, git_write_at: current_action_completed_at } }
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user, email_opted_in: true) }
+
+ before do
+ create(:onboarding_progress, namespace: group, **actions_completed)
+ group.add_developer(user)
+ stub_experiment_for_subject(in_product_marketing_emails: experiment_enabled)
+ allow(Ability).to receive(:allowed?).with(user, anything, anything).and_return(user_can_perform_current_track_action)
+ allow(Notify).to receive(:in_product_marketing_email).and_return(double(deliver_later: nil))
+ end
+
+ RSpec::Matchers.define :send_in_product_marketing_email do |*args|
+ match do
+ expect(Notify).to have_received(:in_product_marketing_email).with(*args).once
+ end
+
+ match_when_negated do
+ expect(Notify).not_to have_received(:in_product_marketing_email)
+ end
+ end
+
+ context 'for each track and series with the right conditions' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:track, :interval, :actions_completed) do
+ :create | 1 | { created_at: 2.days.ago.middle_of_day }
+ :create | 5 | { created_at: 6.days.ago.middle_of_day }
+ :create | 10 | { created_at: 11.days.ago.middle_of_day }
+ :verify | 1 | { created_at: 2.days.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day }
+ :verify | 5 | { created_at: 6.days.ago.middle_of_day, git_write_at: 6.days.ago.middle_of_day }
+ :verify | 10 | { created_at: 11.days.ago.middle_of_day, git_write_at: 11.days.ago.middle_of_day }
+ :trial | 1 | { created_at: 2.days.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day, pipeline_created_at: 2.days.ago.middle_of_day }
+ :trial | 5 | { created_at: 6.days.ago.middle_of_day, git_write_at: 6.days.ago.middle_of_day, pipeline_created_at: 6.days.ago.middle_of_day }
+ :trial | 10 | { created_at: 11.days.ago.middle_of_day, git_write_at: 11.days.ago.middle_of_day, pipeline_created_at: 11.days.ago.middle_of_day }
+ :team | 1 | { created_at: 2.days.ago.middle_of_day, git_write_at: 2.days.ago.middle_of_day, pipeline_created_at: 2.days.ago.middle_of_day, trial_started_at: 2.days.ago.middle_of_day }
+ :team | 5 | { created_at: 6.days.ago.middle_of_day, git_write_at: 6.days.ago.middle_of_day, pipeline_created_at: 6.days.ago.middle_of_day, trial_started_at: 6.days.ago.middle_of_day }
+ :team | 10 | { created_at: 11.days.ago.middle_of_day, git_write_at: 11.days.ago.middle_of_day, pipeline_created_at: 11.days.ago.middle_of_day, trial_started_at: 11.days.ago.middle_of_day }
+ end
+
+ with_them do
+ it { is_expected.to send_in_product_marketing_email(user.id, group.id, track, described_class::INTERVAL_DAYS.index(interval)) }
+ end
+ end
+
+ context 'when initialized with a different track' do
+ let(:track) { :verify }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+
+ context 'when the previous track actions have been completed' do
+ let(:current_action_completed_at) { 2.days.ago.middle_of_day }
+
+ it { is_expected.to send_in_product_marketing_email(user.id, group.id, :verify, 0) }
+ end
+ end
+
+ context 'when initialized with a different interval' do
+ let(:interval) { 5 }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+
+ context 'when the previous track action was completed within the intervals range' do
+ let(:previous_action_completed_at) { 6.days.ago.middle_of_day }
+
+ it { is_expected.to send_in_product_marketing_email(user.id, group.id, :create, 1) }
+ end
+ end
+
+ describe 'experimentation' do
+ context 'when the experiment is enabled' do
+ it 'adds the group as an experiment subject in the experimental group' do
+ expect(Experiment).to receive(:add_group)
+ .with(:in_product_marketing_emails, variant: :experimental, group: group)
+
+ execute_service
+ end
+ end
+
+ context 'when the experiment is disabled' do
+ let(:experiment_enabled) { false }
+
+ it 'adds the group as an experiment subject in the control group' do
+ expect(Experiment).to receive(:add_group)
+ .with(:in_product_marketing_emails, variant: :control, group: group)
+
+ execute_service
+ end
+
+ it { is_expected.not_to send_in_product_marketing_email }
+ end
+ end
+
+ context 'when the previous track action is not yet completed' do
+ let(:previous_action_completed_at) { nil }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+ end
+
+ context 'when the previous track action is completed outside the intervals range' do
+ let(:previous_action_completed_at) { 3.days.ago }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+ end
+
+ context 'when the current track action is completed' do
+ let(:current_action_completed_at) { Time.current }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+ end
+
+ context "when the user cannot perform the current track's action" do
+ let(:user_can_perform_current_track_action) { false }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+ end
+
+ context 'when the user has not opted into marketing emails' do
+ let(:user) { create(:user, email_opted_in: false) }
+
+ it { is_expected.not_to send_in_product_marketing_email }
+ end
+
+ context 'when the user has already received a marketing email as part of another group' do
+ before do
+ other_group = create(:group)
+ other_group.add_developer(user)
+ create(:onboarding_progress, namespace: other_group, created_at: previous_action_completed_at, git_write_at: current_action_completed_at)
+ end
+
+ # For any group Notify is called exactly once
+ it { is_expected.to send_in_product_marketing_email(user.id, anything, :create, 0) }
+ end
+
+ context 'when invoked with a non existing track' do
+ let(:track) { :foo }
+
+ before do
+ stub_const("#{described_class}::TRACKS", { foo: :git_write })
+ end
+
+ it { expect { subject }.to raise_error(NotImplementedError, 'No ability defined for track foo') }
+ end
+end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 20f06619e02..f59749f0b63 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -459,6 +459,26 @@ RSpec.describe Notes::CreateService do
.and change { existing_note.updated_at }
end
+ context 'failure in when_saved' do
+ let(:service) { described_class.new(project, user, reply_opts) }
+
+ it 'converts existing note to DiscussionNote' do
+ expect do
+ existing_note
+
+ allow(service).to receive(:when_saved).and_raise(ActiveRecord::StatementInvalid)
+
+ travel_to(Time.current + 1.minute) do
+ service.execute
+ rescue ActiveRecord::StatementInvalid
+ end
+
+ existing_note.reload
+ end.to change { existing_note.type }.from(nil).to('DiscussionNote')
+ .and change { existing_note.updated_at }
+ end
+ end
+
it 'returns a DiscussionNote with its parent discussion refreshed correctly' do
discussion_notes = subject.discussion.notes
diff --git a/spec/services/notification_recipients/build_service_spec.rb b/spec/services/notification_recipients/build_service_spec.rb
index cc08f9fceff..ff54d6ccd2f 100644
--- a/spec/services/notification_recipients/build_service_spec.rb
+++ b/spec/services/notification_recipients/build_service_spec.rb
@@ -110,4 +110,28 @@ RSpec.describe NotificationRecipients::BuildService do
end
end
end
+
+ describe '#build_requested_review_recipients' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ before do
+ merge_request.reviewers.push(assignee)
+ end
+
+ shared_examples 'no N+1 queries' do
+ it 'avoids N+1 queries', :request_store do
+ create_user
+
+ service.build_requested_review_recipients(note)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ service.build_requested_review_recipients(note)
+ end
+
+ create_user
+
+ expect { service.build_requested_review_recipients(note) }.not_to exceed_query_limit(control_count)
+ end
+ end
+ end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 85234077b1f..b67c37ba02d 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -2177,6 +2177,46 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.merge_when_pipeline_succeeds(merge_request, @u_disabled) }
end
end
+
+ describe '#review_requested_of_merge_request' do
+ let(:merge_request) { create(:merge_request, author: author, source_project: project, reviewers: [reviewer]) }
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:reviewer) { create(:user) }
+
+ it 'sends email to reviewer', :aggregate_failures do
+ notification.review_requested_of_merge_request(merge_request, current_user, reviewer)
+
+ merge_request.reviewers.each { |reviewer| should_email(reviewer) }
+ should_not_email(merge_request.author)
+ should_not_email(@u_watcher)
+ should_not_email(@u_participant_mentioned)
+ should_not_email(@subscriber)
+ should_not_email(@watcher_and_subscriber)
+ should_not_email(@u_guest_watcher)
+ should_not_email(@u_guest_custom)
+ should_not_email(@u_custom_global)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
+ should_not_email(@u_lazy_participant)
+ end
+
+ it 'adds "review requested" reason for new reviewer' do
+ notification.review_requested_of_merge_request(merge_request, current_user, [reviewer])
+
+ merge_request.reviewers.each do |reviewer|
+ email = find_email_for(reviewer)
+
+ expect(email).to have_header('X-GitLab-NotificationReason', NotificationReason::REVIEW_REQUESTED)
+ end
+ end
+
+ it_behaves_like 'project emails are disabled' do
+ let(:notification_target) { merge_request }
+ let(:notification_trigger) { notification.review_requested_of_merge_request(merge_request, current_user, reviewer) }
+ end
+ end
end
describe 'Projects', :deliver_mails_inline do
diff --git a/spec/services/packages/composer/create_package_service_spec.rb b/spec/services/packages/composer/create_package_service_spec.rb
index d10356cfda7..4f1a46e7e45 100644
--- a/spec/services/packages/composer/create_package_service_spec.rb
+++ b/spec/services/packages/composer/create_package_service_spec.rb
@@ -43,6 +43,7 @@ RSpec.describe Packages::Composer::CreatePackageService do
end
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
end
context 'with a tag' do
@@ -66,6 +67,7 @@ RSpec.describe Packages::Composer::CreatePackageService do
end
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
end
end
diff --git a/spec/services/packages/conan/create_package_service_spec.rb b/spec/services/packages/conan/create_package_service_spec.rb
index ca783475503..6f644f5ef95 100644
--- a/spec/services/packages/conan/create_package_service_spec.rb
+++ b/spec/services/packages/conan/create_package_service_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe Packages::Conan::CreatePackageService do
it_behaves_like 'assigns the package creator'
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
end
context 'invalid params' do
diff --git a/spec/services/packages/debian/create_distribution_service_spec.rb b/spec/services/packages/debian/create_distribution_service_spec.rb
new file mode 100644
index 00000000000..87cf1070075
--- /dev/null
+++ b/spec/services/packages/debian/create_distribution_service_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::CreateDistributionService do
+ RSpec.shared_examples 'Create Debian Distribution' do |expected_message, expected_components, expected_architectures|
+ it 'returns ServiceResponse', :aggregate_failures do
+ if expected_message.nil?
+ expect { response }
+ .to change { container.debian_distributions.klass.all.count }
+ .from(0).to(1)
+ .and change { container.debian_distributions.count }
+ .from(0).to(1)
+ .and change { container.debian_distributions.first&.components&.count }
+ .from(nil).to(expected_components.count)
+ .and change { container.debian_distributions.first&.architectures&.count }
+ .from(nil).to(expected_architectures.count)
+ .and not_change { Packages::Debian::ProjectComponentFile.count }
+ .and not_change { Packages::Debian::GroupComponentFile.count }
+ else
+ expect { response }
+ .to not_change { container.debian_distributions.klass.all.count }
+ .and not_change { container.debian_distributions.count }
+ .and not_change { Packages::Debian::ProjectComponent.count }
+ .and not_change { Packages::Debian::GroupComponent.count }
+ .and not_change { Packages::Debian::ProjectArchitecture.count }
+ .and not_change { Packages::Debian::GroupArchitecture.count }
+ .and not_change { Packages::Debian::ProjectComponentFile.count }
+ .and not_change { Packages::Debian::GroupComponentFile.count }
+ end
+
+ expect(response).to be_a(ServiceResponse)
+ expect(response.success?).to eq(expected_message.nil?)
+ expect(response.error?).to eq(!expected_message.nil?)
+ expect(response.message).to eq(expected_message)
+
+ distribution = response.payload[:distribution]
+ expect(distribution.persisted?).to eq(expected_message.nil?)
+ expect(distribution.container).to eq(container)
+ expect(distribution.creator).to eq(user)
+ params.each_pair do |name, value|
+ expect(distribution.send(name)).to eq(value)
+ end
+
+ expect(distribution.components.map(&:name)).to contain_exactly(*expected_components)
+ expect(distribution.architectures.map(&:name)).to contain_exactly(*expected_architectures)
+ end
+ end
+
+ shared_examples 'Debian Create Distribution Service' do
+ context 'with only the codename param' do
+ let(:params) { { codename: 'my-codename' } }
+
+ it_behaves_like 'Create Debian Distribution', nil, %w[main], %w[all amd64]
+ end
+
+ context 'with codename, components and architectures' do
+ let(:params) do
+ {
+ codename: 'my-codename',
+ components: %w[contrib non-free],
+ architectures: %w[arm64]
+ }
+ end
+
+ it_behaves_like 'Create Debian Distribution', nil, %w[contrib non-free], %w[all arm64]
+ end
+
+ context 'with invalid suite' do
+ let(:params) do
+ {
+ codename: 'my-codename',
+ suite: 'erroné'
+ }
+ end
+
+ it_behaves_like 'Create Debian Distribution', 'Suite is invalid', %w[], %w[]
+ end
+
+ context 'with invalid component name' do
+ let(:params) do
+ {
+ codename: 'my-codename',
+ components: %w[before erroné after],
+ architectures: %w[arm64]
+ }
+ end
+
+ it_behaves_like 'Create Debian Distribution', 'Component Name is invalid', %w[before erroné], %w[]
+ end
+
+ context 'with invalid architecture name' do
+ let(:params) do
+ {
+ codename: 'my-codename',
+ components: %w[contrib non-free],
+ architectures: %w[before erroné after']
+ }
+ end
+
+ it_behaves_like 'Create Debian Distribution', 'Architecture Name is invalid', %w[contrib non-free], %w[before erroné]
+ end
+ end
+
+ let_it_be(:user) { create(:user) }
+
+ subject { described_class.new(container, user, params) }
+
+ let(:response) { subject.execute }
+
+ context 'within a projet' do
+ let_it_be(:container) { create(:project) }
+
+ it_behaves_like 'Debian Create Distribution Service'
+ end
+
+ context 'within a group' do
+ let_it_be(:container) { create(:group) }
+
+ it_behaves_like 'Debian Create Distribution Service'
+ end
+end
diff --git a/spec/services/packages/debian/destroy_distribution_service_spec.rb b/spec/services/packages/debian/destroy_distribution_service_spec.rb
new file mode 100644
index 00000000000..e4c43884bb4
--- /dev/null
+++ b/spec/services/packages/debian/destroy_distribution_service_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::DestroyDistributionService do
+ RSpec.shared_examples 'Destroy Debian Distribution' do |expected_message|
+ it 'returns ServiceResponse', :aggregate_failures do
+ if expected_message.nil?
+ expect { response }
+ .to change { container.debian_distributions.klass.all.count }
+ .from(1).to(0)
+ .and change { container.debian_distributions.count }
+ .from(1).to(0)
+ .and change { component1.class.all.count }
+ .from(2).to(0)
+ .and change { architecture1.class.all.count }
+ .from(3).to(0)
+ .and change { component_file1.class.all.count }
+ .from(4).to(0)
+ else
+ expect { response }
+ .to not_change { container.debian_distributions.klass.all.count }
+ .and not_change { container.debian_distributions.count }
+ .and not_change { component1.class.all.count }
+ .and not_change { architecture1.class.all.count }
+ .and not_change { component_file1.class.all.count }
+ end
+
+ expect(response).to be_a(ServiceResponse)
+ expect(response.success?).to eq(expected_message.nil?)
+ expect(response.error?).to eq(!expected_message.nil?)
+ expect(response.message).to eq(expected_message)
+
+ if expected_message.nil?
+ expect(response.payload).to eq({})
+ else
+ expect(response.payload).to eq(distribution: distribution)
+ end
+ end
+ end
+
+ RSpec.shared_examples 'Debian Destroy Distribution Service' do |container_type, can_freeze|
+ context "with a Debian #{container_type} distribution" do
+ let_it_be(:container, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
+ let_it_be(:distribution, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container) }
+ let_it_be(:component1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution, name: 'component1') }
+ let_it_be(:component2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution, name: 'component2') }
+ let_it_be(:architecture0, freeze: true) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
+ let_it_be(:architecture1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture1') }
+ let_it_be(:architecture2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture2') }
+ let_it_be(:component_file1, freeze: can_freeze) { create("debian_#{container_type}_component_file", :source, component: component1) }
+ let_it_be(:component_file2, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1, architecture: architecture1) }
+ let_it_be(:component_file3, freeze: can_freeze) { create("debian_#{container_type}_component_file", :source, component: component2) }
+ let_it_be(:component_file4, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component2, architecture: architecture2) }
+
+ subject { described_class.new(distribution) }
+
+ let(:response) { subject.execute }
+
+ context 'with a distribution' do
+ it_behaves_like 'Destroy Debian Distribution'
+ end
+
+ context 'when destroy fails' do
+ let(:distribution) { create("debian_#{container_type}_distribution", container: container) }
+
+ before do
+ expect(distribution).to receive(:destroy).and_return(false)
+ end
+
+ it_behaves_like 'Destroy Debian Distribution', "Unable to destroy Debian #{container_type} distribution"
+ end
+ end
+ end
+
+ it_behaves_like 'Debian Destroy Distribution Service', :project, true
+ it_behaves_like 'Debian Destroy Distribution Service', :group, false
+end
diff --git a/spec/services/packages/debian/update_distribution_service_spec.rb b/spec/services/packages/debian/update_distribution_service_spec.rb
new file mode 100644
index 00000000000..852fc713e34
--- /dev/null
+++ b/spec/services/packages/debian/update_distribution_service_spec.rb
@@ -0,0 +1,159 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::UpdateDistributionService do
+ RSpec.shared_examples 'Update Debian Distribution' do |expected_message, expected_components, expected_architectures, component_file_delta = 0|
+ it 'returns ServiceResponse', :aggregate_failures do
+ expect(distribution).to receive(:update).with(simple_params).and_call_original if expected_message.nil?
+
+ if component_file_delta.zero?
+ expect { response }
+ .to not_change { container.debian_distributions.klass.all.count }
+ .and not_change { container.debian_distributions.count }
+ .and not_change { component1.class.all.count }
+ .and not_change { architecture1.class.all.count }
+ .and not_change { component_file1.class.all.count }
+ else
+ expect { response }
+ .to not_change { container.debian_distributions.klass.all.count }
+ .and not_change { container.debian_distributions.count }
+ .and not_change { component1.class.all.count }
+ .and not_change { architecture1.class.all.count }
+ .and change { component_file1.class.all.count }
+ .from(4).to(4 + component_file_delta)
+ end
+
+ expect(response).to be_a(ServiceResponse)
+ expect(response.success?).to eq(expected_message.nil?)
+ expect(response.error?).to eq(!expected_message.nil?)
+ expect(response.message).to eq(expected_message)
+
+ expect(response.payload).to eq(distribution: distribution)
+
+ distribution.reload
+ distribution.components.reload
+ distribution.architectures.reload
+
+ if expected_message.nil?
+ simple_params.each_pair do |name, value|
+ expect(distribution.send(name)).to eq(value)
+ end
+ else
+ original_params.each_pair do |name, value|
+ expect(distribution.send(name)).to eq(value)
+ end
+ end
+
+ expect(distribution.components.map(&:name)).to contain_exactly(*expected_components)
+ expect(distribution.architectures.map(&:name)).to contain_exactly(*expected_architectures)
+ end
+ end
+
+ RSpec.shared_examples 'Debian Update Distribution Service' do |container_type, can_freeze|
+ context "with a Debian #{container_type} distribution" do
+ let_it_be(:container, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
+ let_it_be(:distribution, reload: true) { create("debian_#{container_type}_distribution", container: container) }
+ let_it_be(:component1) { create("debian_#{container_type}_component", distribution: distribution, name: 'component1') }
+ let_it_be(:component2) { create("debian_#{container_type}_component", distribution: distribution, name: 'component2') }
+ let_it_be(:architecture0) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
+ let_it_be(:architecture1) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture1') }
+ let_it_be(:architecture2) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture2') }
+ let_it_be(:component_file1) { create("debian_#{container_type}_component_file", :source, component: component1) }
+ let_it_be(:component_file2) { create("debian_#{container_type}_component_file", component: component1, architecture: architecture1) }
+ let_it_be(:component_file3) { create("debian_#{container_type}_component_file", :source, component: component2) }
+ let_it_be(:component_file4) { create("debian_#{container_type}_component_file", component: component2, architecture: architecture2) }
+
+ let(:original_params) do
+ {
+ suite: nil,
+ origin: nil,
+ label: nil,
+ version: nil,
+ description: nil,
+ valid_time_duration_seconds: nil,
+ automatic: true,
+ automatic_upgrades: false
+ }
+ end
+
+ let(:params) { {} }
+ let(:simple_params) { params.except(:components, :architectures) }
+
+ subject { described_class.new(distribution, params) }
+
+ let(:response) { subject.execute }
+
+ context 'with valid simple params' do
+ let(:params) do
+ {
+ suite: 'my-suite',
+ origin: 'my-origin',
+ label: 'my-label',
+ version: '42.0',
+ description: 'my-description',
+ valid_time_duration_seconds: 7.days,
+ automatic: false,
+ automatic_upgrades: true
+ }
+ end
+
+ it_behaves_like 'Update Debian Distribution', nil, %w[component1 component2], %w[all architecture1 architecture2]
+ end
+
+ context 'with invalid simple params' do
+ let(:params) do
+ {
+ suite: 'suite erronée',
+ origin: 'origin erronée',
+ label: 'label erronée',
+ version: 'version erronée',
+ description: 'description erronée',
+ valid_time_duration_seconds: 1.hour
+ }
+ end
+
+ it_behaves_like 'Update Debian Distribution', 'Suite is invalid, Origin is invalid, Label is invalid, Version is invalid, and Valid time duration seconds must be greater than or equal to 86400', %w[component1 component2], %w[all architecture1 architecture2]
+ end
+
+ context 'with valid components and architectures' do
+ let(:params) do
+ {
+ suite: 'my-suite',
+ components: %w[component2 component3],
+ architectures: %w[architecture2 architecture3]
+ }
+ end
+
+ it_behaves_like 'Update Debian Distribution', nil, %w[component2 component3], %w[all architecture2 architecture3], -2
+ end
+
+ context 'with invalid components' do
+ let(:params) do
+ {
+ suite: 'my-suite',
+ components: %w[component2 erroné],
+ architectures: %w[architecture2 architecture3]
+ }
+ end
+
+ it_behaves_like 'Update Debian Distribution', 'Component Name is invalid', %w[component1 component2], %w[all architecture1 architecture2]
+ end
+
+ context 'with invalid architectures' do
+ let(:params) do
+ {
+ suite: 'my-suite',
+ components: %w[component2 component3],
+ architectures: %w[architecture2 erroné]
+ }
+ end
+
+ it_behaves_like 'Update Debian Distribution', 'Architecture Name is invalid', %w[component1 component2], %w[all architecture1 architecture2]
+ end
+ end
+ end
+
+ it_behaves_like 'Debian Update Distribution Service', :project, true
+ it_behaves_like 'Debian Update Distribution Service', :group, false
+end
diff --git a/spec/services/packages/generic/create_package_file_service_spec.rb b/spec/services/packages/generic/create_package_file_service_spec.rb
index 816e728c342..10c54369f26 100644
--- a/spec/services/packages/generic/create_package_file_service_spec.rb
+++ b/spec/services/packages/generic/create_package_file_service_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
let(:temp_file) { Tempfile.new("test") }
let(:file) { UploadedFile.new(temp_file.path, sha256: sha256) }
let(:package) { create(:generic_package, project: project) }
+ let(:package_service) { double }
+
let(:params) do
{
package_name: 'mypackage',
@@ -23,31 +25,34 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
}
end
+ let(:package_params) do
+ {
+ name: params[:package_name],
+ version: params[:package_version],
+ build: params[:build],
+ status: nil
+ }
+ end
+
subject { described_class.new(project, user, params).execute }
before do
FileUtils.touch(temp_file)
+ expect(::Packages::Generic::FindOrCreatePackageService).to receive(:new).with(project, user, package_params).and_return(package_service)
+ expect(package_service).to receive(:execute).and_return(package)
end
after do
FileUtils.rm_f(temp_file)
end
- it 'creates package file' do
- package_service = double
- package_params = {
- name: params[:package_name],
- version: params[:package_version],
- build: params[:build]
- }
- expect(::Packages::Generic::FindOrCreatePackageService).to receive(:new).with(project, user, package_params).and_return(package_service)
- expect(package_service).to receive(:execute).and_return(package)
-
+ it 'creates package file', :aggregate_failures do
expect { subject }.to change { package.package_files.count }.by(1)
.and change { Packages::PackageFileBuildInfo.count }.by(1)
package_file = package.package_files.last
aggregate_failures do
+ expect(package_file.package.status).to eq('default')
expect(package_file.package).to eq(package)
expect(package_file.file_name).to eq('myfile.tar.gz.1')
expect(package_file.size).to eq(file.size)
@@ -55,6 +60,21 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
end
end
+ context 'with a status' do
+ let(:params) { super().merge(status: 'hidden') }
+ let(:package_params) { super().merge(status: 'hidden') }
+
+ it 'updates an existing packages status' do
+ expect { subject }.to change { package.package_files.count }.by(1)
+ .and change { Packages::PackageFileBuildInfo.count }.by(1)
+
+ package_file = package.package_files.last
+ aggregate_failures do
+ expect(package_file.package.status).to eq('hidden')
+ end
+ end
+ end
+
it_behaves_like 'assigns build to package file'
end
end
diff --git a/spec/services/packages/maven/find_or_create_package_service_spec.rb b/spec/services/packages/maven/find_or_create_package_service_spec.rb
index 82dffeefcde..2543ab0c669 100644
--- a/spec/services/packages/maven/find_or_create_package_service_spec.rb
+++ b/spec/services/packages/maven/find_or_create_package_service_spec.rb
@@ -36,10 +36,11 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
expect(pkg.version).to eq(version)
end
- context 'with a build' do
+ context 'with optional attributes' do
subject { service.execute.payload[:package] }
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
end
end
@@ -111,6 +112,13 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService do
expect(subject.errors).to include('Duplicate package is not allowed')
end
+ context 'when uploading to the versionless package which contains metadata about all versions' do
+ let(:version) { nil }
+ let(:param_path) { path }
+
+ it_behaves_like 'reuse existing package'
+ end
+
context 'when uploading different non-duplicate files to the same package' do
before do
package_file = existing_package.package_files.find_by(file_name: 'my-app-1.0-20180724.124855-1.jar')
diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb
index 6db3777cde8..10fce6c1651 100644
--- a/spec/services/packages/npm/create_package_service_spec.rb
+++ b/spec/services/packages/npm/create_package_service_spec.rb
@@ -53,6 +53,7 @@ RSpec.describe Packages::Npm::CreatePackageService do
let(:params) { super().merge(build: job) }
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
it 'creates a package file build info' do
expect { subject }.to change { Packages::PackageFileBuildInfo.count }.by(1)
diff --git a/spec/services/packages/nuget/create_package_service_spec.rb b/spec/services/packages/nuget/create_package_service_spec.rb
index 5289ad40d61..e338ac36fc3 100644
--- a/spec/services/packages/nuget/create_package_service_spec.rb
+++ b/spec/services/packages/nuget/create_package_service_spec.rb
@@ -32,5 +32,6 @@ RSpec.describe Packages::Nuget::CreatePackageService do
it_behaves_like 'assigns the package creator'
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
end
end
diff --git a/spec/services/packages/pypi/create_package_service_spec.rb b/spec/services/packages/pypi/create_package_service_spec.rb
index 28a727c4a09..a932cf73eb7 100644
--- a/spec/services/packages/pypi/create_package_service_spec.rb
+++ b/spec/services/packages/pypi/create_package_service_spec.rb
@@ -52,6 +52,7 @@ RSpec.describe Packages::Pypi::CreatePackageService do
end
it_behaves_like 'assigns build to package'
+ it_behaves_like 'assigns status to package'
context 'with an existing package' do
before do
diff --git a/spec/services/pages/delete_services_spec.rb b/spec/services/pages/delete_services_spec.rb
index 440549020a2..f1edf93b0c1 100644
--- a/spec/services/pages/delete_services_spec.rb
+++ b/spec/services/pages/delete_services_spec.rb
@@ -3,35 +3,74 @@
require 'spec_helper'
RSpec.describe Pages::DeleteService do
- shared_examples 'remove pages' do
- let_it_be(:project) { create(:project, path: "my.project")}
- let_it_be(:admin) { create(:admin) }
- let_it_be(:domain) { create(:pages_domain, project: project) }
- let_it_be(:service) { described_class.new(project, admin)}
+ let_it_be(:admin) { create(:admin) }
- it 'deletes published pages' do
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
- expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
+ let(:project) { create(:project, path: "my.project")}
+ let!(:domain) { create(:pages_domain, project: project) }
+ let(:service) { described_class.new(project, admin)}
- Sidekiq::Testing.inline! { service.execute }
+ before do
+ project.mark_pages_as_deployed
+ end
+
+ it 'deletes published pages', :sidekiq_inline do
+ expect(project.pages_deployed?).to be(true)
+
+ expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
+ expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
+
+ service.execute
+
+ expect(project.pages_deployed?).to be(false)
+ end
+
+ it "doesn't remove anything from the legacy storage if updates on it are disabled", :sidekiq_inline do
+ stub_feature_flags(pages_update_legacy_storage: false)
+
+ expect(project.pages_deployed?).to be(true)
+
+ expect(PagesWorker).not_to receive(:perform_in)
+
+ service.execute
- expect(project.reload.pages_metadatum.deployed?).to be(false)
- end
+ expect(project.pages_deployed?).to be(false)
+ end
+
+ it 'deletes all domains', :sidekiq_inline do
+ expect(project.pages_domains.count).to eq(1)
+
+ service.execute
+
+ expect(project.reload.pages_domains.count).to eq(0)
+ end
- it 'deletes all domains' do
- expect(project.pages_domains.count).to be 1
+ it 'schedules a destruction of pages deployments' do
+ expect(DestroyPagesDeploymentsWorker).to(
+ receive(:perform_async).with(project.id)
+ )
- Sidekiq::Testing.inline! { service.execute }
+ service.execute
+ end
+
+ it 'removes pages deployments', :sidekiq_inline do
+ create(:pages_deployment, project: project)
- expect(project.reload.pages_domains.count).to be 0
- end
+ expect do
+ service.execute
+ end.to change { PagesDeployment.count }.by(-1)
end
- context 'with feature flag enabled' do
- before do
- expect(PagesRemoveWorker).to receive(:perform_async).and_call_original
- end
+ it 'marks pages as not deployed, deletes domains and schedules worker to remove pages from disk' do
+ expect(project.pages_deployed?).to eq(true)
+ expect(project.pages_domains.count).to eq(1)
+
+ service.execute
+
+ expect(project.pages_deployed?).to eq(false)
+ expect(project.pages_domains.count).to eq(0)
+
+ expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
- it_behaves_like 'remove pages'
+ Sidekiq::Worker.drain_all
end
end
diff --git a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb
new file mode 100644
index 00000000000..4ec57044912
--- /dev/null
+++ b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Pages::MigrateFromLegacyStorageService do
+ let(:service) { described_class.new(Rails.logger, migration_threads: 3, batch_size: 10, ignore_invalid_entries: false) }
+
+ it 'does not try to migrate pages if pages are not deployed' do
+ expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+
+ expect(service.execute).to eq(migrated: 0, errored: 0)
+ end
+
+ it 'uses multiple threads' do
+ projects = create_list(:project, 20)
+ projects.each do |project|
+ project.mark_pages_as_deployed
+
+ FileUtils.mkdir_p File.join(project.pages_path, "public")
+ File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
+ f.write("Hello!")
+ end
+ end
+
+ service = described_class.new(Rails.logger, migration_threads: 3, batch_size: 2, ignore_invalid_entries: false)
+
+ threads = Concurrent::Set.new
+
+ expect(service).to receive(:migrate_project).exactly(20).times.and_wrap_original do |m, *args|
+ threads.add(Thread.current)
+
+ # sleep to be 100% certain that once thread can't consume all the queue
+ # it works without it, but I want to avoid making this test flaky
+ sleep(0.01)
+
+ m.call(*args)
+ end
+
+ expect(service.execute).to eq(migrated: 20, errored: 0)
+ expect(threads.length).to eq(3)
+ end
+
+ context 'when pages are marked as deployed' do
+ let(:project) { create(:project) }
+
+ before do
+ project.mark_pages_as_deployed
+ end
+
+ context 'when pages directory does not exist' do
+ it 'tries to migrate the project, but does not crash' do
+ expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect(service.execute).to eq(migrated: 0, errored: 1)
+ end
+ end
+
+ context 'when pages directory exists on disk' do
+ before do
+ FileUtils.mkdir_p File.join(project.pages_path, "public")
+ File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
+ f.write("Hello!")
+ end
+ end
+
+ it 'migrates pages projects without deployments' do
+ expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project, ignore_invalid_entries: false) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect do
+ expect(service.execute).to eq(migrated: 1, errored: 0)
+ end.to change { project.pages_metadatum.reload.pages_deployment }.from(nil)
+ end
+
+ context 'when deployed already exists for the project' do
+ before do
+ deployment = create(:pages_deployment, project: project)
+ project.set_first_pages_deployment!(deployment)
+ end
+
+ it 'does not try to migrate project' do
+ expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+
+ expect(service.execute).to eq(migrated: 0, errored: 0)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb b/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
index 29023621413..d95303c3e85 100644
--- a/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
+++ b/spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb
@@ -6,6 +6,14 @@ RSpec.describe Pages::MigrateLegacyStorageToDeploymentService do
let(:project) { create(:project, :repository) }
let(:service) { described_class.new(project) }
+ it 'calls ::Pages::ZipDirectoryService' do
+ expect_next_instance_of(::Pages::ZipDirectoryService, project.pages_path, ignore_invalid_entries: true) do |zip_service|
+ expect(zip_service).to receive(:execute).and_call_original
+ end
+
+ expect(described_class.new(project, ignore_invalid_entries: true).execute[:status]).to eq(:error)
+ end
+
it 'marks pages as not deployed if public directory is absent' do
project.mark_pages_as_deployed
diff --git a/spec/services/pages/zip_directory_service_spec.rb b/spec/services/pages/zip_directory_service_spec.rb
index dcab6b2dada..9de68dd62bb 100644
--- a/spec/services/pages/zip_directory_service_spec.rb
+++ b/spec/services/pages/zip_directory_service_spec.rb
@@ -10,8 +10,14 @@ RSpec.describe Pages::ZipDirectoryService do
end
end
+ let(:ignore_invalid_entries) { false }
+
+ let(:service) do
+ described_class.new(@work_dir, ignore_invalid_entries: ignore_invalid_entries)
+ end
+
let(:result) do
- described_class.new(@work_dir).execute
+ service.execute
end
let(:status) { result[:status] }
@@ -20,6 +26,8 @@ RSpec.describe Pages::ZipDirectoryService do
let(:entries_count) { result[:entries_count] }
it 'returns error if project pages dir does not exist' do
+ expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
+
expect(
described_class.new("/tmp/not/existing/dir").execute
).to eq(status: :error, message: "Can not find valid public dir in /tmp/not/existing/dir")
@@ -132,32 +140,69 @@ RSpec.describe Pages::ZipDirectoryService do
end
end
- it 'ignores the symlink pointing outside of public directory' do
- create_file("target.html", "hello")
- create_link("public/link.html", "../target.html")
+ shared_examples "raises or ignores file" do |raised_exception, file|
+ it 'raises error' do
+ expect do
+ result
+ end.to raise_error(raised_exception)
+ end
- with_zip_file do |zip_file|
- expect { zip_file.get_entry("public/link.html") }.to raise_error(Errno::ENOENT)
+ context 'when errors are ignored' do
+ let(:ignore_invalid_entries) { true }
+
+ it 'does not create entry' do
+ with_zip_file do |zip_file|
+ expect { zip_file.get_entry(file) }.to raise_error(Errno::ENOENT)
+ end
+ end
end
end
- it 'ignores the symlink if target is absent' do
- create_link("public/link.html", "./target.html")
+ context 'when symlink points outside of public directory' do
+ before do
+ create_file("target.html", "hello")
+ create_link("public/link.html", "../target.html")
+ end
- with_zip_file do |zip_file|
- expect { zip_file.get_entry("public/link.html") }.to raise_error(Errno::ENOENT)
+ include_examples "raises or ignores file", described_class::InvalidEntryError, "public/link.html"
+ end
+
+ context 'when target of the symlink is absent' do
+ before do
+ create_link("public/link.html", "./target.html")
end
+
+ include_examples "raises or ignores file", Errno::ENOENT, "public/link.html"
end
- it 'ignores symlink if is absolute and points to outside of directory' do
- target = File.join(@work_dir, "target")
- FileUtils.touch(target)
+ context 'when targets itself' do
+ before do
+ create_link("public/link.html", "./link.html")
+ end
- create_link("public/link.html", target)
+ include_examples "raises or ignores file", Errno::ELOOP, "public/link.html"
+ end
- with_zip_file do |zip_file|
- expect { zip_file.get_entry("public/link.html") }.to raise_error(Errno::ENOENT)
+ context 'when symlink is absolute and points to outside of directory' do
+ before do
+ target = File.join(@work_dir, "target")
+ FileUtils.touch(target)
+
+ create_link("public/link.html", target)
end
+
+ include_examples "raises or ignores file", described_class::InvalidEntryError, "public/link.html"
+ end
+
+ context 'when entry has unknown ftype' do
+ before do
+ file = create_file("public/index.html", "hello")
+
+ allow(File).to receive(:lstat).and_call_original
+ expect(File).to receive(:lstat).with(file) { double("lstat", ftype: "unknown") }
+ end
+
+ include_examples "raises or ignores file", described_class::InvalidEntryError, "public/index.html"
end
it "includes raw symlink if it's target is a valid directory" do
@@ -204,9 +249,13 @@ RSpec.describe Pages::ZipDirectoryService do
end
def create_file(name, content)
- File.open(File.join(@work_dir, name), "w") do |f|
+ file_path = File.join(@work_dir, name)
+
+ File.open(file_path, "w") do |f|
f.write(content)
end
+
+ file_path
end
def create_dir(dir)
diff --git a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
index 4d489d7fe4b..79654c9b190 100644
--- a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
+++ b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
@@ -135,7 +135,7 @@ RSpec.describe PagesDomains::ObtainLetsEncryptCertificateService do
cert.add_extension ef.create_extension("authorityKeyIdentifier",
"keyid:always,issuer:always")
- cert.sign key, OpenSSL::Digest::SHA1.new
+ cert.sign key, OpenSSL::Digest.new('SHA1')
cert.to_pem
end
diff --git a/spec/services/post_receive_service_spec.rb b/spec/services/post_receive_service_spec.rb
index 6e2cd7edf04..033194972c7 100644
--- a/spec/services/post_receive_service_spec.rb
+++ b/spec/services/post_receive_service_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe PostReceiveService do
include Gitlab::Routing
- include AfterNextHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
@@ -47,11 +46,7 @@ RSpec.describe PostReceiveService do
expect(subject).to be_empty
end
- it 'does not record an onboarding progress action' do
- expect_next(OnboardingProgressService).not_to receive(:execute)
-
- subject
- end
+ it_behaves_like 'does not record an onboarding progress action'
end
context 'when repository is nil' do
@@ -88,11 +83,8 @@ RSpec.describe PostReceiveService do
expect(response.reference_counter_decreased).to be(true)
end
- it 'records an onboarding progress action' do
- expect_next(OnboardingProgressService, project.namespace)
- .to receive(:execute).with(action: :git_write)
-
- subject
+ it_behaves_like 'records an onboarding progress action', :git_write do
+ let(:namespace) { project.namespace }
end
end
diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb
index 4b7b7b0b200..4e366fce0d9 100644
--- a/spec/services/projects/alerting/notify_service_spec.rb
+++ b/spec/services/projects/alerting/notify_service_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Projects::Alerting::NotifyService do
subject { service.execute(token, nil) }
- shared_examples 'notifcations are handled correctly' do
+ shared_examples 'notifications are handled correctly' do
context 'with valid token' do
let(:token) { integration.token }
let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled, auto_close_incident?: auto_close_enabled) }
@@ -85,6 +85,15 @@ RSpec.describe Projects::Alerting::NotifyService do
it_behaves_like 'creates an alert management alert'
it_behaves_like 'assigns the alert properties'
+ it 'passes the integration to alert processing' do
+ expect(Gitlab::AlertManagement::Payload)
+ .to receive(:parse)
+ .with(project, payload.to_h, integration: integration)
+ .and_call_original
+
+ subject
+ end
+
it 'creates a system note corresponding to alert creation' do
expect { subject }.to change(Note, :count).by(1)
expect(Note.last.note).to include(payload_raw.fetch(:monitoring_tool))
@@ -259,7 +268,7 @@ RSpec.describe Projects::Alerting::NotifyService do
subject { service.execute(token, integration) }
- it_behaves_like 'notifcations are handled correctly' do
+ it_behaves_like 'notifications are handled correctly' do
let(:source) { integration.name }
end
diff --git a/spec/services/projects/branches_by_mode_service_spec.rb b/spec/services/projects/branches_by_mode_service_spec.rb
new file mode 100644
index 00000000000..9199c3e0b3a
--- /dev/null
+++ b/spec/services/projects/branches_by_mode_service_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::BranchesByModeService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:finder) { described_class.new(project, params) }
+ let(:params) { { mode: 'all' } }
+
+ subject { finder.execute }
+
+ describe '#execute' do
+ context 'page is passed' do
+ let(:params) { { page: 4, mode: 'all', offset: 3 } }
+
+ it 'uses offset pagination' do
+ expect(finder).to receive(:fetch_branches_via_offset_pagination).and_call_original
+
+ branches, prev_page, next_page = subject
+
+ expect(branches.size).to eq(10)
+ expect(next_page).to be_nil
+ expect(prev_page).to eq("/#{project.full_path}/-/branches/all?offset=2&page=3")
+ end
+
+ context 'but the page does not contain any branches' do
+ let(:params) { { page: 10, mode: 'all' } }
+
+ it 'uses offset pagination' do
+ expect(finder).to receive(:fetch_branches_via_offset_pagination).and_call_original
+
+ branches, prev_page, next_page = subject
+
+ expect(branches).to eq([])
+ expect(next_page).to be_nil
+ expect(prev_page).to be_nil
+ end
+ end
+ end
+
+ context 'search is passed' do
+ let(:params) { { search: 'feature' } }
+
+ it 'uses offset pagination' do
+ expect(finder).to receive(:fetch_branches_via_offset_pagination).and_call_original
+
+ branches, prev_page, next_page = subject
+
+ expect(branches.map(&:name)).to match_array(%w(feature feature_conflict))
+ expect(next_page).to be_nil
+ expect(prev_page).to be_nil
+ end
+ end
+
+ context 'branch_list_keyset_pagination is disabled' do
+ it 'uses offset pagination' do
+ stub_feature_flags(branch_list_keyset_pagination: false)
+
+ expect(finder).to receive(:fetch_branches_via_offset_pagination).and_call_original
+
+ branches, prev_page, next_page = subject
+
+ expect(branches.size).to eq(20)
+ expect(next_page).to eq("/#{project.full_path}/-/branches/all?offset=1&page_token=conflict-resolvable")
+ expect(prev_page).to be_nil
+ end
+ end
+
+ context 'uses gitaly pagination' do
+ before do
+ expect(finder).to receive(:fetch_branches_via_gitaly_pagination).and_call_original
+ end
+
+ it 'returns branches for the first page' do
+ branches, prev_page, next_page = subject
+
+ expect(branches.size).to eq(20)
+ expect(next_page).to eq("/#{project.full_path}/-/branches/all?offset=1&page_token=conflict-resolvable")
+ expect(prev_page).to be_nil
+ end
+
+ context 'when second page is requested' do
+ let(:params) { { page_token: 'conflict-resolvable', mode: 'all', sort: 'name_asc', offset: 1 } }
+
+ it 'returns branches for the first page' do
+ branches, prev_page, next_page = subject
+
+ expect(branches.size).to eq(20)
+ expect(next_page).to eq("/#{project.full_path}/-/branches/all?offset=2&page_token=improve%2Fawesome&sort=name_asc")
+ expect(prev_page).to eq("/#{project.full_path}/-/branches/all?offset=0&page=1&sort=name_asc")
+ end
+ end
+
+ context 'when last page is requested' do
+ let(:params) { { page_token: 'signed-commits', mode: 'all', sort: 'name_asc', offset: 4 } }
+
+ it 'returns branches after the specified branch' do
+ branches, prev_page, next_page = subject
+
+ expect(branches.size).to eq(14)
+ expect(next_page).to be_nil
+ expect(prev_page).to eq("/#{project.full_path}/-/branches/all?offset=3&page=4&sort=name_asc")
+ end
+ end
+ end
+
+ context 'filter by mode' do
+ let(:stale) { double(state: 'stale') }
+ let(:active) { double(state: 'active') }
+
+ before do
+ allow_next_instance_of(BranchesFinder) do |instance|
+ allow(instance).to receive(:execute).and_return([stale, active])
+ end
+ end
+
+ context 'stale' do
+ let(:params) { { mode: 'stale' } }
+
+ it 'returns stale branches' do
+ is_expected.to eq([[stale], nil, nil])
+ end
+ end
+
+ context 'active' do
+ let(:params) { { mode: 'active' } }
+
+ it 'returns active branches' do
+ is_expected.to eq([[active], nil, nil])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/cleanup_service_spec.rb b/spec/services/projects/cleanup_service_spec.rb
index 6fd29813d98..f2c052d9397 100644
--- a/spec/services/projects/cleanup_service_spec.rb
+++ b/spec/services/projects/cleanup_service_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe Projects::CleanupService do
end
it 'runs garbage collection on the repository' do
- expect_next_instance_of(GitGarbageCollectWorker) do |worker|
+ expect_next_instance_of(Projects::GitGarbageCollectWorker) do |worker|
expect(worker).to receive(:perform).with(project.id, :prune, "project_cleanup:gc:#{project.id}")
end
diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
index 17c2f0f6c17..eed22416868 100644
--- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb
@@ -284,7 +284,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
deleted: nil
)
- expect(result).to eq(service_response.compact)
+ expect(result).to eq(service_response)
end
end
@@ -369,6 +369,6 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do
before_truncate_size: before_truncate_size,
after_truncate_size: after_truncate_size,
before_delete_size: before_delete_size
- }.compact
+ }.compact.merge(deleted_size: deleted&.size)
end
end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 6c0e6654622..f7da6f75141 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -40,6 +40,48 @@ RSpec.describe Projects::CreateService, '#execute' do
end
end
+ describe 'setting name and path' do
+ subject(:project) { create_project(user, opts) }
+
+ context 'when both are set' do
+ let(:opts) { { name: 'one', path: 'two' } }
+
+ it 'keeps them as specified' do
+ expect(project.name).to eq('one')
+ expect(project.path).to eq('two')
+ end
+ end
+
+ context 'when path is set' do
+ let(:opts) { { path: 'one.two_three-four' } }
+
+ it 'sets name == path' do
+ expect(project.path).to eq('one.two_three-four')
+ expect(project.name).to eq(project.path)
+ end
+ end
+
+ context 'when name is a valid path' do
+ let(:opts) { { name: 'one.two_three-four' } }
+
+ it 'sets path == name' do
+ expect(project.name).to eq('one.two_three-four')
+ expect(project.path).to eq(project.name)
+ end
+ end
+
+ context 'when name is not a valid path' do
+ let(:opts) { { name: 'one.two_three-four and five' } }
+
+ # TODO: Retained for backwards compatibility. Remove in API v5.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52725
+ it 'parameterizes the name' do
+ expect(project.name).to eq('one.two_three-four and five')
+ expect(project.path).to eq('one-two_three-four-and-five')
+ end
+ end
+ end
+
context 'user namespace' do
it do
project = create_project(user, opts)
@@ -419,7 +461,7 @@ RSpec.describe Projects::CreateService, '#execute' do
context 'when another repository already exists on disk' do
let(:opts) do
{
- name: 'Existing',
+ name: 'existing',
namespace_id: user.namespace.id
}
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index a11f16573f5..df02f8ea15d 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -323,6 +323,50 @@ RSpec.describe Projects::ForkService do
end
end
end
+
+ describe 'fork with optional attributes' do
+ let(:public_project) { create(:project, :public) }
+
+ it 'sets optional attributes to specified values' do
+ forked_project = fork_project(
+ public_project,
+ nil,
+ namespace: public_project.namespace,
+ path: 'forked',
+ name: 'My Fork',
+ description: 'Description',
+ visibility: 'internal',
+ using_service: true
+ )
+
+ expect(forked_project.path).to eq('forked')
+ expect(forked_project.name).to eq('My Fork')
+ expect(forked_project.description).to eq('Description')
+ expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it 'sets visibility level to private if an unknown visibility is requested' do
+ forked_project = fork_project(public_project, nil, using_service: true, visibility: 'unknown')
+
+ expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'sets visibility level to project visibility level if requested visibility is greater' do
+ private_project = create(:project, :private)
+
+ forked_project = fork_project(private_project, nil, using_service: true, visibility: 'public')
+
+ expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'sets visibility level to target namespace visibility level if requested visibility is greater' do
+ private_group = create(:group, :private)
+
+ forked_project = fork_project(public_project, nil, namespace: private_group, using_service: true, visibility: 'public')
+
+ expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
end
context 'when a project is already forked' do
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
index 8ae47ec266c..e196220eabe 100644
--- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Projects::Prometheus::Alerts::NotifyService do
include PrometheusHelpers
+ using RSpec::Parameterized::TableSyntax
let_it_be(:project, reload: true) { create(:project) }
@@ -61,8 +62,6 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
context 'with project specific cluster' do
- using RSpec::Parameterized::TableSyntax
-
where(:cluster_enabled, :status, :configured_token, :token_input, :result) do
true | :installed | token | token | :success
true | :installed | nil | nil | :success
@@ -104,8 +103,6 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
context 'with manual prometheus installation' do
- using RSpec::Parameterized::TableSyntax
-
where(:alerting_setting, :configured_token, :token_input, :result) do
true | token | token | :success
true | token | 'x' | :failure
@@ -139,8 +136,6 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
context 'with HTTP integration' do
- using RSpec::Parameterized::TableSyntax
-
where(:active, :token, :result) do
:active | :valid | :success
:active | :invalid | :failure
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index a6730c5de52..6bf2876f640 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Projects::UpdatePagesService do
subject { described_class.new(project, build) }
before do
- project.remove_pages
+ project.legacy_remove_pages
end
context '::TMP_EXTRACT_PATH' do
@@ -55,6 +55,15 @@ RSpec.describe Projects::UpdatePagesService do
end
end
+ it "doesn't deploy to legacy storage if it's disabled" do
+ stub_feature_flags(pages_update_legacy_storage: false)
+
+ expect(execute).to eq(:success)
+ expect(project.pages_deployed?).to be_truthy
+
+ expect(File.exist?(File.join(project.pages_path, 'public', 'index.html'))).to eq(false)
+ end
+
it 'creates pages_deployment and saves it in the metadata' do
expect do
expect(execute).to eq(:success)
diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb
index ef8f166cc3f..828667fdfc2 100644
--- a/spec/services/projects/update_repository_storage_service_spec.rb
+++ b/spec/services/projects/update_repository_storage_service_spec.rb
@@ -59,13 +59,18 @@ RSpec.describe Projects::UpdateRepositoryStorageService do
end
context 'when the filesystems are the same' do
- let(:destination) { project.repository_storage }
+ before do
+ expect(Gitlab::GitalyClient).to receive(:filesystem_id).twice.and_return(SecureRandom.uuid)
+ end
- it 'bails out and does nothing' do
+ it 'updates the database without trying to move the repostory', :aggregate_failures do
result = subject.execute
+ project.reload
- expect(result).to be_error
- expect(result.message).to match(/SameFilesystemError/)
+ expect(result).to be_success
+ expect(project).not_to be_repository_read_only
+ expect(project.repository_storage).to eq('test_second_storage')
+ expect(project.project_repository.shard_name).to eq('test_second_storage')
end
end
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 21e294418a1..1a102b125f6 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -879,139 +879,123 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- context 'when the merge_request_reviewers flag is enabled' do
- describe 'assign_reviewer command' do
- let(:content) { "/assign_reviewer @#{developer.username}" }
- let(:issuable) { merge_request }
+ describe 'assign_reviewer command' do
+ let(:content) { "/assign_reviewer @#{developer.username}" }
+ let(:issuable) { merge_request }
- context 'with one user' do
- it_behaves_like 'assign_reviewer command'
- end
+ context 'with one user' do
+ it_behaves_like 'assign_reviewer command'
+ end
- context 'with an issue instead of a merge request' do
- let(:issuable) { issue }
+ context 'with an issue instead of a merge request' do
+ let(:issuable) { issue }
- it_behaves_like 'empty command'
- end
+ it_behaves_like 'empty command'
+ end
- # CE does not have multiple reviewers
- context 'assign command with multiple assignees' do
- before do
- project.add_developer(developer2)
- end
+ # CE does not have multiple reviewers
+ context 'assign command with multiple assignees' do
+ before do
+ project.add_developer(developer2)
+ end
- # There's no guarantee that the reference extractor will preserve
- # the order of the mentioned users since this is dependent on the
- # order in which rows are returned. We just ensure that at least
- # one of the mentioned users is assigned.
- context 'assigns to one of the two users' do
- let(:content) { "/assign_reviewer @#{developer.username} @#{developer2.username}" }
+ # There's no guarantee that the reference extractor will preserve
+ # the order of the mentioned users since this is dependent on the
+ # order in which rows are returned. We just ensure that at least
+ # one of the mentioned users is assigned.
+ context 'assigns to one of the two users' do
+ let(:content) { "/assign_reviewer @#{developer.username} @#{developer2.username}" }
- it 'assigns to a single reviewer' do
- _, updates, message = service.execute(content, issuable)
+ it 'assigns to a single reviewer' do
+ _, updates, message = service.execute(content, issuable)
- expect(updates[:reviewer_ids].count).to eq(1)
- reviewer = updates[:reviewer_ids].first
- expect([developer.id, developer2.id]).to include(reviewer)
+ expect(updates[:reviewer_ids].count).to eq(1)
+ reviewer = updates[:reviewer_ids].first
+ expect([developer.id, developer2.id]).to include(reviewer)
- user = reviewer == developer.id ? developer : developer2
+ user = reviewer == developer.id ? developer : developer2
- expect(message).to match("Assigned #{user.to_reference} as reviewer.")
- end
+ expect(message).to match("Assigned #{user.to_reference} as reviewer.")
end
end
+ end
- context 'with "me" alias' do
- let(:content) { '/assign_reviewer me' }
+ context 'with "me" alias' do
+ let(:content) { '/assign_reviewer me' }
- it_behaves_like 'assign_reviewer command'
- end
+ it_behaves_like 'assign_reviewer command'
+ end
- context 'with an alias and whitespace' do
- let(:content) { '/assign_reviewer me ' }
+ context 'with an alias and whitespace' do
+ let(:content) { '/assign_reviewer me ' }
- it_behaves_like 'assign_reviewer command'
- end
+ it_behaves_like 'assign_reviewer command'
+ end
- context 'with an incorrect user' do
- let(:content) { '/assign_reviewer @abcd1234' }
+ context 'with an incorrect user' do
+ let(:content) { '/assign_reviewer @abcd1234' }
- it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
- end
+ it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
+ end
- context 'with the "reviewer" alias' do
- let(:content) { "/reviewer @#{developer.username}" }
+ context 'with the "reviewer" alias' do
+ let(:content) { "/reviewer @#{developer.username}" }
- it_behaves_like 'assign_reviewer command'
- end
+ it_behaves_like 'assign_reviewer command'
+ end
- context 'with no user' do
- let(:content) { '/assign_reviewer' }
+ context 'with the "request_review" alias' do
+ let(:content) { "/request_review @#{developer.username}" }
- it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
- end
+ it_behaves_like 'assign_reviewer command'
+ end
- context 'includes only the user reference with extra text' do
- let(:content) { "/assign_reviewer @#{developer.username} do it!" }
+ context 'with no user' do
+ let(:content) { '/assign_reviewer' }
- it_behaves_like 'assign_reviewer command'
- end
+ it_behaves_like 'empty command', "Failed to assign a reviewer because no user was found."
end
- describe 'unassign_reviewer command' do
- # CE does not have multiple reviewers, so basically anything
- # after /unassign_reviewer (including whitespace) will remove
- # all the current reviewers.
- let(:issuable) { create(:merge_request, reviewers: [developer]) }
- let(:content) { "/unassign_reviewer @#{developer.username}" }
+ context 'includes only the user reference with extra text' do
+ let(:content) { "/assign_reviewer @#{developer.username} do it!" }
- context 'with one user' do
- it_behaves_like 'unassign_reviewer command'
- end
-
- context 'with an issue instead of a merge request' do
- let(:issuable) { issue }
-
- it_behaves_like 'empty command'
- end
+ it_behaves_like 'assign_reviewer command'
+ end
+ end
- context 'with anything after the command' do
- let(:content) { '/unassign_reviewer supercalifragilisticexpialidocious' }
+ describe 'unassign_reviewer command' do
+ # CE does not have multiple reviewers, so basically anything
+ # after /unassign_reviewer (including whitespace) will remove
+ # all the current reviewers.
+ let(:issuable) { create(:merge_request, reviewers: [developer]) }
+ let(:content) { "/unassign_reviewer @#{developer.username}" }
- it_behaves_like 'unassign_reviewer command'
- end
+ context 'with one user' do
+ it_behaves_like 'unassign_reviewer command'
+ end
- context 'with the "remove_reviewer" alias' do
- let(:content) { "/remove_reviewer @#{developer.username}" }
+ context 'with an issue instead of a merge request' do
+ let(:issuable) { issue }
- it_behaves_like 'unassign_reviewer command'
- end
+ it_behaves_like 'empty command'
+ end
- context 'with no user' do
- let(:content) { '/unassign_reviewer' }
+ context 'with anything after the command' do
+ let(:content) { '/unassign_reviewer supercalifragilisticexpialidocious' }
- it_behaves_like 'unassign_reviewer command'
- end
+ it_behaves_like 'unassign_reviewer command'
end
- end
- context 'when the merge_request_reviewers flag is disabled' do
- before do
- stub_feature_flags(merge_request_reviewers: false)
- end
+ context 'with the "remove_reviewer" alias' do
+ let(:content) { "/remove_reviewer @#{developer.username}" }
- describe 'assign_reviewer command' do
- it_behaves_like 'empty command' do
- let(:content) { "/assign_reviewer @#{developer.username}" }
- let(:issuable) { merge_request }
- end
+ it_behaves_like 'unassign_reviewer command'
end
- describe 'unassign_reviewer command' do
- it_behaves_like 'empty command' do
- let(:content) { "/unassign_reviewer @#{developer.username}" }
- let(:issuable) { merge_request }
- end
+ context 'with no user' do
+ let(:content) { '/unassign_reviewer' }
+
+ it_behaves_like 'unassign_reviewer command'
end
end
@@ -1787,6 +1771,24 @@ RSpec.describe QuickActions::InterpretService do
expect(text).to eq(" - list\n\ntest")
end
+ it 'tracks MAU for commands' do
+ content = "/shrug test\n/assign me\n/milestone %4"
+
+ expect(Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter)
+ .to receive(:track_unique_action)
+ .with('shrug', args: 'test', user: developer)
+
+ expect(Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter)
+ .to receive(:track_unique_action)
+ .with('assign', args: 'me', user: developer)
+
+ expect(Gitlab::UsageDataCounters::QuickActionActivityUniqueCounter)
+ .to receive(:track_unique_action)
+ .with('milestone', args: '%4', user: developer)
+
+ service.execute(content, issue)
+ end
+
context '/create_merge_request command' do
let(:branch_name) { '1-feature' }
let(:content) { "/create_merge_request #{branch_name}" }
diff --git a/spec/services/repositories/changelog_service_spec.rb b/spec/services/repositories/changelog_service_spec.rb
new file mode 100644
index 00000000000..a545b0f070a
--- /dev/null
+++ b/spec/services/repositories/changelog_service_spec.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::ChangelogService do
+ describe '#execute' do
+ it 'generates and commits a changelog section' do
+ project = create(:project, :empty_repo)
+ creator = project.creator
+ author1 = create(:user)
+ author2 = create(:user)
+
+ project.add_maintainer(author1)
+ project.add_maintainer(author2)
+
+ mr1 = create(:merge_request, :merged, target_project: project)
+ mr2 = create(:merge_request, :merged, target_project: project)
+
+ # The range of commits ignores the first commit, but includes the last
+ # commit. To ensure both the commits below are included, we must create an
+ # extra commit.
+ #
+ # In the real world, the start commit of the range will be the last commit
+ # of the previous release, so ignoring that is expected and desired.
+ sha1 = create_commit(
+ project,
+ creator,
+ commit_message: 'Initial commit',
+ actions: [{ action: 'create', content: 'test', file_path: 'README.md' }]
+ )
+
+ sha2 = create_commit(
+ project,
+ author1,
+ commit_message: "Title 1\n\nChangelog: feature",
+ actions: [{ action: 'create', content: 'foo', file_path: 'a.txt' }]
+ )
+
+ sha3 = create_commit(
+ project,
+ author2,
+ commit_message: "Title 2\n\nChangelog: feature",
+ actions: [{ action: 'create', content: 'bar', file_path: 'b.txt' }]
+ )
+
+ commit1 = project.commit(sha2)
+ commit2 = project.commit(sha3)
+
+ allow(MergeRequestDiffCommit)
+ .to receive(:oldest_merge_request_id_per_commit)
+ .with(project.id, [commit2.id, commit1.id])
+ .and_return([
+ { sha: sha2, merge_request_id: mr1.id },
+ { sha: sha3, merge_request_id: mr2.id }
+ ])
+
+ recorder = ActiveRecord::QueryRecorder.new do
+ described_class
+ .new(project, creator, version: '1.0.0', from: sha1, to: sha3)
+ .execute
+ end
+
+ changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
+
+ expect(recorder.count).to eq(10)
+ expect(changelog).to include('Title 1', 'Title 2')
+ end
+ end
+
+ describe '#start_of_commit_range' do
+ let(:project) { build_stubbed(:project) }
+ let(:user) { build_stubbed(:user) }
+
+ context 'when the "from" argument is specified' do
+ it 'returns the value of the argument' do
+ service = described_class
+ .new(project, user, version: '1.0.0', from: 'foo', to: 'bar')
+
+ expect(service.start_of_commit_range).to eq('foo')
+ end
+ end
+
+ context 'when the "from" argument is unspecified' do
+ it 'returns the tag commit of the previous version' do
+ service = described_class
+ .new(project, user, version: '1.0.0', to: 'bar')
+
+ finder_spy = instance_spy(Repositories::PreviousTagFinder)
+ tag = double(:tag, target_commit: double(:commit, id: '123'))
+
+ allow(Repositories::PreviousTagFinder)
+ .to receive(:new)
+ .with(project)
+ .and_return(finder_spy)
+
+ allow(finder_spy)
+ .to receive(:execute)
+ .with('1.0.0')
+ .and_return(tag)
+
+ expect(service.start_of_commit_range).to eq('123')
+ end
+
+ it 'raises an error when no tag is found' do
+ service = described_class
+ .new(project, user, version: '1.0.0', to: 'bar')
+
+ finder_spy = instance_spy(Repositories::PreviousTagFinder)
+
+ allow(Repositories::PreviousTagFinder)
+ .to receive(:new)
+ .with(project)
+ .and_return(finder_spy)
+
+ allow(finder_spy)
+ .to receive(:execute)
+ .with('1.0.0')
+ .and_return(nil)
+
+ expect { service.start_of_commit_range }
+ .to raise_error(Gitlab::Changelog::Error)
+ end
+ end
+ end
+
+ def create_commit(project, user, params)
+ params = { start_branch: 'master', branch_name: 'master' }.merge(params)
+ Files::MultiService.new(project, user, params).execute.fetch(:result)
+ end
+end
diff --git a/spec/services/resource_access_tokens/create_service_spec.rb b/spec/services/resource_access_tokens/create_service_spec.rb
index 5cfa1ae93e6..517ed086713 100644
--- a/spec/services/resource_access_tokens/create_service_spec.rb
+++ b/spec/services/resource_access_tokens/create_service_spec.rb
@@ -195,6 +195,14 @@ RSpec.describe ResourceAccessTokens::CreateService do
end
end
end
+
+ it 'logs the event' do
+ allow(Gitlab::AppLogger).to receive(:info)
+
+ response = subject
+
+ expect(Gitlab::AppLogger).to have_received(:info).with(/PROJECT ACCESS TOKEN CREATION: created_by: #{user.username}, project_id: #{resource.id}, token_user: #{response.payload[:access_token].user.name}, token_id: \d+/)
+ end
end
context 'when resource is a project' do
@@ -208,7 +216,7 @@ RSpec.describe ResourceAccessTokens::CreateService do
response = subject
expect(response.error?).to be true
- expect(response.errors).to include("User does not have permission to create #{resource_type} Access Token")
+ expect(response.errors).to include("User does not have permission to create #{resource_type} access token")
end
end
diff --git a/spec/services/resource_access_tokens/revoke_service_spec.rb b/spec/services/resource_access_tokens/revoke_service_spec.rb
index af29ee2a721..99adb4bb7a0 100644
--- a/spec/services/resource_access_tokens/revoke_service_spec.rb
+++ b/spec/services/resource_access_tokens/revoke_service_spec.rb
@@ -40,6 +40,14 @@ RSpec.describe ResourceAccessTokens::RevokeService do
expect(User.exists?(resource_bot.id)).to be_falsy
end
+
+ it 'logs the event' do
+ allow(Gitlab::AppLogger).to receive(:info)
+
+ subject
+
+ expect(Gitlab::AppLogger).to have_received(:info).with("PROJECT ACCESS TOKEN REVOCATION: revoked_by: #{user.username}, project_id: #{resource.id}, token_user: #{resource_bot.name}, token_id: #{access_token.id}")
+ end
end
shared_examples 'rollback revoke steps' do
diff --git a/spec/services/resource_events/change_milestone_service_spec.rb b/spec/services/resource_events/change_milestone_service_spec.rb
index a2131c5c1b0..ed234376381 100644
--- a/spec/services/resource_events/change_milestone_service_spec.rb
+++ b/spec/services/resource_events/change_milestone_service_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe ResourceEvents::ChangeMilestoneService do
let_it_be(:timebox) { create(:milestone) }
let(:created_at_time) { Time.utc(2019, 12, 30) }
- let(:add_timebox_args) { { created_at: created_at_time, old_milestone: nil } }
- let(:remove_timebox_args) { { created_at: created_at_time, old_milestone: timebox } }
+ let(:add_timebox_args) { { old_milestone: nil } }
+ let(:remove_timebox_args) { { old_milestone: timebox } }
[:issue, :merge_request].each do |issuable|
it_behaves_like 'timebox(milestone or iteration) resource events creator', ResourceMilestoneEvent do
diff --git a/spec/services/search/global_service_spec.rb b/spec/services/search/global_service_spec.rb
index 7b914a4d3d6..e8716ef4d90 100644
--- a/spec/services/search/global_service_spec.rb
+++ b/spec/services/search/global_service_spec.rb
@@ -56,14 +56,20 @@ RSpec.describe Search::GlobalService do
context 'issues' do
let(:scope) { 'issues' }
- context 'sort by created_at' do
- let!(:project) { create(:project, :public) }
+ context 'sorting' do
+ let_it_be(:project) { create(:project, :public) }
+
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
+ let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
+ let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
+ let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
+
include_examples 'search results sorted' do
- let(:results) { described_class.new(nil, search: 'sorted', sort: sort).execute }
+ let(:results_created) { described_class.new(nil, search: 'sorted', sort: sort).execute }
+ let(:results_updated) { described_class.new(nil, search: 'updated', sort: sort).execute }
end
end
end
@@ -71,14 +77,20 @@ RSpec.describe Search::GlobalService do
context 'merge_request' do
let(:scope) { 'merge_requests' }
- context 'sort by created_at' do
+ context 'sorting' do
let!(:project) { create(:project, :public) }
+
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
+ let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
+ let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
+ let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
+
include_examples 'search results sorted' do
- let(:results) { described_class.new(nil, search: 'sorted', sort: sort).execute }
+ let(:results_created) { described_class.new(nil, search: 'sorted', sort: sort).execute }
+ let(:results_updated) { described_class.new(nil, search: 'updated', sort: sort).execute }
end
end
end
diff --git a/spec/services/search/group_service_spec.rb b/spec/services/search/group_service_spec.rb
index 2bfe714f393..7beeec98b23 100644
--- a/spec/services/search/group_service_spec.rb
+++ b/spec/services/search/group_service_spec.rb
@@ -44,15 +44,21 @@ RSpec.describe Search::GroupService do
context 'issues' do
let(:scope) { 'issues' }
- context 'sort by created_at' do
- let!(:group) { create(:group) }
- let!(:project) { create(:project, :public, group: group) }
+ context 'sorting' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+
let!(:old_result) { create(:issue, project: project, title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:issue, project: project, title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:issue, project: project, title: 'sorted very old', created_at: 1.year.ago) }
+ let!(:old_updated) { create(:issue, project: project, title: 'updated old', updated_at: 1.month.ago) }
+ let!(:new_updated) { create(:issue, project: project, title: 'updated recent', updated_at: 1.day.ago) }
+ let!(:very_old_updated) { create(:issue, project: project, title: 'updated very old', updated_at: 1.year.ago) }
+
include_examples 'search results sorted' do
- let(:results) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
+ let(:results_created) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
+ let(:results_updated) { described_class.new(nil, group, search: 'updated', sort: sort).execute }
end
end
end
@@ -60,15 +66,21 @@ RSpec.describe Search::GroupService do
context 'merge requests' do
let(:scope) { 'merge_requests' }
- context 'sort by created_at' do
+ context 'sorting' do
let!(:group) { create(:group) }
let!(:project) { create(:project, :public, group: group) }
+
let!(:old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'old-1', title: 'sorted old', created_at: 1.month.ago) }
let!(:new_result) { create(:merge_request, :opened, source_project: project, source_branch: 'new-1', title: 'sorted recent', created_at: 1.day.ago) }
let!(:very_old_result) { create(:merge_request, :opened, source_project: project, source_branch: 'very-old-1', title: 'sorted very old', created_at: 1.year.ago) }
+ let!(:old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-old-1', title: 'updated old', updated_at: 1.month.ago) }
+ let!(:new_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-new-1', title: 'updated recent', updated_at: 1.day.ago) }
+ let!(:very_old_updated) { create(:merge_request, :opened, source_project: project, source_branch: 'updated-very-old-1', title: 'updated very old', updated_at: 1.year.ago) }
+
include_examples 'search results sorted' do
- let(:results) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
+ let(:results_created) { described_class.new(nil, group, search: 'sorted', sort: sort).execute }
+ let(:results_updated) { described_class.new(nil, group, search: 'updated', sort: sort).execute }
end
end
end
diff --git a/spec/services/security/ci_configuration/sast_create_service_spec.rb b/spec/services/security/ci_configuration/sast_create_service_spec.rb
new file mode 100644
index 00000000000..ff7ab614e08
--- /dev/null
+++ b/spec/services/security/ci_configuration/sast_create_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::SastCreateService, :snowplow do
+ describe '#execute' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let(:params) { {} }
+
+ subject(:result) { described_class.new(project, user, params).execute }
+
+ context 'user does not belong to project' do
+ it 'returns an error status' do
+ expect(result[:status]).to eq(:error)
+ expect(result[:success_path]).to be_nil
+ end
+
+ it 'does not track a snowplow event' do
+ subject
+
+ expect_no_snowplow_event
+ end
+ end
+
+ context 'user belongs to project' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'does track the snowplow event' do
+ subject
+
+ expect_snowplow_event(
+ category: 'Security::CiConfiguration::SastCreateService',
+ action: 'create',
+ label: 'false'
+ )
+ end
+
+ it 'raises exception if the user does not have permission to create a new branch' do
+ allow(project).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, "You are not allowed to create protected branches on this project.")
+
+ expect { subject }.to raise_error(Gitlab::Git::PreReceiveError)
+ end
+
+ context 'with no parameters' do
+ it 'returns the path to create a new merge request' do
+ expect(result[:status]).to eq(:success)
+ expect(result[:success_path]).to match(/#{Gitlab::Routing.url_helpers.project_new_merge_request_url(project, {})}(.*)description(.*)source_branch/)
+ end
+ end
+
+ context 'with parameters' do
+ let(:params) do
+ { 'stage' => 'security',
+ 'SEARCH_MAX_DEPTH' => 1,
+ 'SECURE_ANALYZERS_PREFIX' => 'new_registry',
+ 'SAST_EXCLUDED_PATHS' => 'spec,docs' }
+ end
+
+ it 'returns the path to create a new merge request' do
+ expect(result[:status]).to eq(:success)
+ expect(result[:success_path]).to match(/#{Gitlab::Routing.url_helpers.project_new_merge_request_url(project, {})}(.*)description(.*)source_branch/)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/security/ci_configuration/sast_parser_service_spec.rb b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
new file mode 100644
index 00000000000..21490f993c7
--- /dev/null
+++ b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::CiConfiguration::SastParserService do
+ describe '#configuration' do
+ include_context 'read ci configuration for sast enabled project'
+
+ let(:configuration) { described_class.new(project).configuration }
+ let(:secure_analyzers_prefix) { configuration['global'][0] }
+ let(:sast_excluded_paths) { configuration['global'][1] }
+ let(:sast_analyzer_image_tag) { configuration['global'][2] }
+ let(:sast_pipeline_stage) { configuration['pipeline'][0] }
+ let(:sast_search_max_depth) { configuration['pipeline'][1] }
+ let(:brakeman) { configuration['analyzers'][0] }
+ let(:bandit) { configuration['analyzers'][1] }
+ let(:sast_brakeman_level) { brakeman['variables'][0] }
+
+ it 'parses the configuration for SAST' do
+ expect(secure_analyzers_prefix['default_value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(sast_excluded_paths['default_value']).to eql('spec, test, tests, tmp')
+ expect(sast_analyzer_image_tag['default_value']).to eql('2')
+ expect(sast_pipeline_stage['default_value']).to eql('test')
+ expect(sast_search_max_depth['default_value']).to eql('4')
+ expect(brakeman['enabled']).to be(true)
+ expect(sast_brakeman_level['default_value']).to eql('1')
+ end
+
+ context 'while populating current values of the entities' do
+ context 'when .gitlab-ci.yml is present' do
+ it 'populates the current values from the file' do
+ allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_content)
+ expect(secure_analyzers_prefix['value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers2')
+ expect(sast_excluded_paths['value']).to eql('spec, executables')
+ expect(sast_analyzer_image_tag['value']).to eql('2')
+ expect(sast_pipeline_stage['value']).to eql('our_custom_security_stage')
+ expect(sast_search_max_depth['value']).to eql('8')
+ expect(brakeman['enabled']).to be(false)
+ expect(bandit['enabled']).to be(true)
+ expect(sast_brakeman_level['value']).to eql('2')
+ end
+
+ context 'SAST_DEFAULT_ANALYZERS is set' do
+ it 'enables analyzers correctly' do
+ allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_default_analyzers_content)
+
+ expect(brakeman['enabled']).to be(false)
+ expect(bandit['enabled']).to be(true)
+ end
+ end
+
+ context 'SAST_EXCLUDED_ANALYZERS is set' do
+ it 'enables analyzers correctly' do
+ allow(project.repository).to receive(:blob_data_at).and_return(gitlab_ci_yml_excluded_analyzers_content)
+
+ expect(brakeman['enabled']).to be(false)
+ expect(bandit['enabled']).to be(true)
+ end
+ end
+ end
+
+ context 'when .gitlab-ci.yml is absent' do
+ it 'populates the current values with the default values' do
+ allow(project.repository).to receive(:blob_data_at).and_return(nil)
+ expect(secure_analyzers_prefix['value']).to eql('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(sast_excluded_paths['value']).to eql('spec, test, tests, tmp')
+ expect(sast_analyzer_image_tag['value']).to eql('2')
+ expect(sast_pipeline_stage['value']).to eql('test')
+ expect(sast_search_max_depth['value']).to eql('4')
+ expect(brakeman['enabled']).to be(true)
+ expect(sast_brakeman_level['value']).to eql('1')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb
index 96807fd629f..32a09e1afc8 100644
--- a/spec/services/snippets/create_service_spec.rb
+++ b/spec/services/snippets/create_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Snippets::CreateService do
describe '#execute' do
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
+ let(:action) { :create }
let(:opts) { base_opts.merge(extra_opts) }
let(:base_opts) do
{
@@ -309,7 +310,7 @@ RSpec.describe Snippets::CreateService do
it_behaves_like 'a service that creates a snippet'
it_behaves_like 'public visibility level restrictions apply'
- it_behaves_like 'snippets spam check is performed'
+ it_behaves_like 'checking spam'
it_behaves_like 'snippet create data is tracked'
it_behaves_like 'an error service response when save fails'
it_behaves_like 'creates repository and files'
@@ -337,7 +338,7 @@ RSpec.describe Snippets::CreateService do
it_behaves_like 'a service that creates a snippet'
it_behaves_like 'public visibility level restrictions apply'
- it_behaves_like 'snippets spam check is performed'
+ it_behaves_like 'checking spam'
it_behaves_like 'snippet create data is tracked'
it_behaves_like 'an error service response when save fails'
it_behaves_like 'creates repository and files'
diff --git a/spec/services/snippets/update_repository_storage_service_spec.rb b/spec/services/snippets/update_repository_storage_service_spec.rb
index b2bcd620d76..6ba09a9dca9 100644
--- a/spec/services/snippets/update_repository_storage_service_spec.rb
+++ b/spec/services/snippets/update_repository_storage_service_spec.rb
@@ -54,13 +54,18 @@ RSpec.describe Snippets::UpdateRepositoryStorageService do
end
context 'when the filesystems are the same' do
- let(:destination) { snippet.repository_storage }
+ before do
+ expect(Gitlab::GitalyClient).to receive(:filesystem_id).twice.and_return(SecureRandom.uuid)
+ end
- it 'bails out and does nothing' do
+ it 'updates the database without trying to move the repostory', :aggregate_failures do
result = subject.execute
+ snippet.reload
- expect(result).to be_error
- expect(result.message).to match(/SameFilesystemError/)
+ expect(result).to be_success
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq(destination)
+ expect(snippet.snippet_repository.shard_name).to eq(destination)
end
end
diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb
index a2341dc71b2..e737c00ae67 100644
--- a/spec/services/snippets/update_service_spec.rb
+++ b/spec/services/snippets/update_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Snippets::UpdateService do
describe '#execute', :aggregate_failures do
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create :user, admin: true }
+ let(:action) { :update }
let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
let(:base_opts) do
{
@@ -738,11 +739,7 @@ RSpec.describe Snippets::UpdateService do
it_behaves_like 'only file_name is present'
it_behaves_like 'only content is present'
it_behaves_like 'invalid params error response'
- it_behaves_like 'snippets spam check is performed' do
- before do
- subject
- end
- end
+ it_behaves_like 'checking spam'
context 'when snippet does not have a repository' do
let!(:snippet) { create(:project_snippet, author: user, project: project) }
@@ -766,11 +763,7 @@ RSpec.describe Snippets::UpdateService do
it_behaves_like 'only file_name is present'
it_behaves_like 'only content is present'
it_behaves_like 'invalid params error response'
- it_behaves_like 'snippets spam check is performed' do
- before do
- subject
- end
- end
+ it_behaves_like 'checking spam'
context 'when snippet does not have a repository' do
let!(:snippet) { create(:personal_snippet, author: user, project: project) }
diff --git a/spec/services/spam/spam_action_service_spec.rb b/spec/services/spam/spam_action_service_spec.rb
index 8edd9406bce..371923f1518 100644
--- a/spec/services/spam/spam_action_service_spec.rb
+++ b/spec/services/spam/spam_action_service_spec.rb
@@ -24,41 +24,16 @@ RSpec.describe Spam::SpamActionService do
issue.spam = false
end
- describe '#initialize' do
- subject { described_class.new(spammable: issue, request: request, user: user) }
-
- context 'when the request is nil' do
- let(:request) { nil }
-
- it 'assembles the options with information from the spammable' do
- aggregate_failures do
- expect(subject.options[:ip_address]).to eq(issue.ip_address)
- expect(subject.options[:user_agent]).to eq(issue.user_agent)
- expect(subject.options.key?(:referrer)).to be_falsey
- end
- end
- end
-
- context 'when the request is present' do
- let(:request) { double(:request, env: env) }
-
- it 'assembles the options with information from the spammable' do
- aggregate_failures do
- expect(subject.options[:ip_address]).to eq(fake_ip)
- expect(subject.options[:user_agent]).to eq(fake_user_agent)
- expect(subject.options[:referrer]).to eq(fake_referrer)
- end
- end
- end
- end
-
shared_examples 'only checks for spam if a request is provided' do
context 'when request is missing' do
- subject { described_class.new(spammable: issue, request: nil, user: user) }
+ let(:request) { nil }
it "doesn't check as spam" do
- subject
+ expect(fake_verdict_service).not_to receive(:execute)
+
+ response = subject
+ expect(response.message).to match(/request was not present/)
expect(issue).not_to be_spam
end
end
@@ -66,34 +41,88 @@ RSpec.describe Spam::SpamActionService do
context 'when request exists' do
it 'creates a spam log' do
expect { subject }
- .to log_spam(title: issue.title, description: issue.description, noteable_type: 'Issue')
+ .to log_spam(title: issue.title, description: issue.description, noteable_type: 'Issue')
end
end
end
+ shared_examples 'creates a spam log' do
+ it do
+ expect { subject }.to change { SpamLog.count }.by(1)
+
+ new_spam_log = SpamLog.last
+ expect(new_spam_log.user_id).to eq(user.id)
+ expect(new_spam_log.title).to eq(issue.title)
+ expect(new_spam_log.description).to eq(issue.description)
+ expect(new_spam_log.source_ip).to eq(fake_ip)
+ expect(new_spam_log.user_agent).to eq(fake_user_agent)
+ expect(new_spam_log.noteable_type).to eq('Issue')
+ expect(new_spam_log.via_api).to eq(false)
+ end
+ end
+
describe '#execute' do
let(:request) { double(:request, env: env) }
+ let(:fake_captcha_verification_service) { double(:captcha_verification_service) }
let(:fake_verdict_service) { double(:spam_verdict_service) }
let(:allowlisted) { false }
+ let(:api) { nil }
+ let(:captcha_response) { 'abc123' }
+ let(:spam_log_id) { existing_spam_log.id }
+ let(:spam_params) do
+ Spam::SpamActionService.filter_spam_params!(
+ api: api,
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ )
+ end
+
+ let(:verdict_service_opts) do
+ {
+ ip_address: fake_ip,
+ user_agent: fake_user_agent,
+ referrer: fake_referrer
+ }
+ end
+
+ let(:verdict_service_args) do
+ {
+ target: issue,
+ user: user,
+ request: request,
+ options: verdict_service_opts,
+ context: {
+ action: :create,
+ target_type: 'Issue'
+ }
+ }
+ end
let_it_be(:existing_spam_log) { create(:spam_log, user: user, recaptcha_verified: false) }
subject do
- described_service = described_class.new(spammable: issue, request: request, user: user)
+ described_service = described_class.new(spammable: issue, request: request, user: user, action: :create)
allow(described_service).to receive(:allowlisted?).and_return(allowlisted)
- described_service.execute(api: nil, recaptcha_verified: recaptcha_verified, spam_log_id: existing_spam_log.id)
+ described_service.execute(spam_params: spam_params)
end
before do
- allow(Spam::SpamVerdictService).to receive(:new).and_return(fake_verdict_service)
+ allow(Captcha::CaptchaVerificationService).to receive(:new) { fake_captcha_verification_service }
+ allow(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args).and_return(fake_verdict_service)
end
- context 'when reCAPTCHA was already verified' do
- let(:recaptcha_verified) { true }
+ context 'when captcha response verification returns true' do
+ before do
+ expect(fake_captcha_verification_service)
+ .to receive(:execute).with(captcha_response: captcha_response, request: request) { true }
+ end
it "doesn't check with the SpamVerdictService" do
aggregate_failures do
- expect(SpamLog).to receive(:verify_recaptcha!)
+ expect(SpamLog).to receive(:verify_recaptcha!).with(
+ user_id: user.id,
+ id: spam_log_id
+ )
expect(fake_verdict_service).not_to receive(:execute)
end
@@ -105,8 +134,11 @@ RSpec.describe Spam::SpamActionService do
end
end
- context 'when reCAPTCHA was not verified' do
- let(:recaptcha_verified) { false }
+ context 'when captcha response verification returns false' do
+ before do
+ expect(fake_captcha_verification_service)
+ .to receive(:execute).with(captcha_response: captcha_response, request: request) { false }
+ end
context 'when spammable attributes have not changed' do
before do
@@ -120,6 +152,10 @@ RSpec.describe Spam::SpamActionService do
end
context 'when spammable attributes have changed' do
+ let(:expected_service_check_response_message) do
+ /check Issue spammable model for any errors or captcha requirement/
+ end
+
before do
issue.description = 'SPAM!'
end
@@ -130,7 +166,9 @@ RSpec.describe Spam::SpamActionService do
it 'does not perform spam check' do
expect(Spam::SpamVerdictService).not_to receive(:new)
- subject
+ response = subject
+
+ expect(response.message).to match(/user was allowlisted/)
end
end
@@ -147,8 +185,9 @@ RSpec.describe Spam::SpamActionService do
it_behaves_like 'only checks for spam if a request is provided'
it 'marks as spam' do
- subject
+ response = subject
+ expect(response.message).to match(expected_service_check_response_message)
expect(issue).to be_spam
end
end
@@ -157,8 +196,9 @@ RSpec.describe Spam::SpamActionService do
it_behaves_like 'only checks for spam if a request is provided'
it 'does not mark as spam' do
- subject
+ response = subject
+ expect(response.message).to match(expected_service_check_response_message)
expect(issue).not_to be_spam
end
end
@@ -176,15 +216,19 @@ RSpec.describe Spam::SpamActionService do
it_behaves_like 'only checks for spam if a request is provided'
+ it_behaves_like 'creates a spam log'
+
it 'does not mark as spam' do
- subject
+ response = subject
+ expect(response.message).to match(expected_service_check_response_message)
expect(issue).not_to be_spam
end
it 'marks as needing reCAPTCHA' do
- subject
+ response = subject
+ expect(response.message).to match(expected_service_check_response_message)
expect(issue.needs_recaptcha?).to be_truthy
end
end
@@ -192,9 +236,12 @@ RSpec.describe Spam::SpamActionService do
context 'when allow_possible_spam feature flag is true' do
it_behaves_like 'only checks for spam if a request is provided'
+ it_behaves_like 'creates a spam log'
+
it 'does not mark as needing reCAPTCHA' do
- subject
+ response = subject
+ expect(response.message).to match(expected_service_check_response_message)
expect(issue.needs_recaptcha).to be_falsey
end
end
@@ -209,6 +256,51 @@ RSpec.describe Spam::SpamActionService do
expect { subject }
.not_to change { SpamLog.count }
end
+
+ it 'clears spam flags' do
+ expect(issue).to receive(:clear_spam_flags!)
+
+ subject
+ end
+ end
+
+ context 'spam verdict service options' do
+ before do
+ allow(fake_verdict_service).to receive(:execute) { ALLOW }
+ end
+
+ context 'when the request is nil' do
+ let(:request) { nil }
+ let(:issue_ip_address) { '1.2.3.4' }
+ let(:issue_user_agent) { 'lynx' }
+ let(:verdict_service_opts) do
+ {
+ ip_address: issue_ip_address,
+ user_agent: issue_user_agent
+ }
+ end
+
+ before do
+ allow(issue).to receive(:ip_address) { issue_ip_address }
+ allow(issue).to receive(:user_agent) { issue_user_agent }
+ end
+
+ it 'assembles the options with information from the spammable' do
+ # TODO: This code untestable, because we do not perform a verification if there is not a
+ # request. See corresponding comment in code
+ # expect(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args)
+
+ subject
+ end
+ end
+
+ context 'when the request is present' do
+ it 'assembles the options with information from the request' do
+ expect(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args)
+
+ subject
+ end
+ end
end
end
end
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index 3e7594bd30f..77d0e892725 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -32,8 +32,8 @@ RSpec.describe Suggestions::ApplyService do
create(:suggestion, :content_from_repo, suggestion_args)
end
- def apply(suggestions)
- result = apply_service.new(user, *suggestions).execute
+ def apply(suggestions, custom_message = nil)
+ result = apply_service.new(user, *suggestions, message: custom_message).execute
suggestions.map { |suggestion| suggestion.reload }
@@ -74,6 +74,14 @@ RSpec.describe Suggestions::ApplyService do
expect(commit.author_name).to eq(user.name)
end
+ it 'tracks apply suggestion event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_apply_suggestion_action)
+ .with(user: user)
+
+ apply(suggestions)
+ end
+
context 'when a custom suggestion commit message' do
before do
project.update!(suggestion_commit_message: message)
@@ -103,6 +111,16 @@ RSpec.describe Suggestions::ApplyService do
end
end
end
+
+ context 'with a user suggested commit message' do
+ let(:message) { "i'm a custom commit message!" }
+
+ it "uses the user's commit message" do
+ apply(suggestions, message)
+
+ expect(project.repository.commit.message).to(eq(message))
+ end
+ end
end
subject(:apply_service) { described_class }
@@ -570,56 +588,84 @@ RSpec.describe Suggestions::ApplyService do
project.add_maintainer(user)
end
+ shared_examples_for 'service not tracking apply suggestion event' do
+ it 'does not track apply suggestion event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_apply_suggestion_action)
+
+ result
+ end
+ end
+
context 'diff file was not found' do
- it 'returns error message' do
- expect(suggestion.note).to receive(:latest_diff_file) { nil }
+ let(:result) { apply_service.new(user, suggestion).execute }
- result = apply_service.new(user, suggestion).execute
+ before do
+ expect(suggestion.note).to receive(:latest_diff_file) { nil }
+ end
+ it 'returns error message' do
expect(result).to eq(message: 'A file was not found.',
status: :error)
end
+
+ it_behaves_like 'service not tracking apply suggestion event'
end
context 'when not all suggestions belong to the same branch' do
- it 'renders error message' do
- merge_request2 = create(:merge_request,
- :conflict,
- source_project: project,
- target_project: project)
-
- position2 = Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: 15,
- diff_refs: merge_request2
- .diff_refs)
+ let(:merge_request2) do
+ create(
+ :merge_request,
+ :conflict,
+ source_project: project,
+ target_project: project
+ )
+ end
- diff_note2 = create(:diff_note_on_merge_request,
- noteable: merge_request2,
- position: position2,
- project: project)
+ let(:position2) do
+ Gitlab::Diff::Position.new(
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 15,
+ diff_refs: merge_request2.diff_refs
+ )
+ end
- other_branch_suggestion = create(:suggestion, note: diff_note2)
+ let(:diff_note2) do
+ create(
+ :diff_note_on_merge_request,
+ noteable: merge_request2,
+ position: position2,
+ project: project
+ )
+ end
- result = apply_service.new(user, suggestion, other_branch_suggestion).execute
+ let(:other_branch_suggestion) { create(:suggestion, note: diff_note2) }
+ let(:result) { apply_service.new(user, suggestion, other_branch_suggestion).execute }
+ it 'renders error message' do
expect(result).to eq(message: 'Suggestions must all be on the same branch.',
status: :error)
end
+
+ it_behaves_like 'service not tracking apply suggestion event'
end
context 'suggestion is not appliable' do
let(:inapplicable_reason) { "Can't apply this suggestion." }
+ let(:result) { apply_service.new(user, suggestion).execute }
- it 'returns error message' do
+ before do
expect(suggestion).to receive(:appliable?).and_return(false)
expect(suggestion).to receive(:inapplicable_reason).and_return(inapplicable_reason)
+ end
- result = apply_service.new(user, suggestion).execute
-
+ it 'returns error message' do
expect(result).to eq(message: inapplicable_reason, status: :error)
end
+
+ it_behaves_like 'service not tracking apply suggestion event'
end
context 'lines of suggestions overlap' do
@@ -632,12 +678,14 @@ RSpec.describe Suggestions::ApplyService do
create_suggestion(to_content: "I Overlap!")
end
- it 'returns error message' do
- result = apply_service.new(user, suggestion, overlapping_suggestion).execute
+ let(:result) { apply_service.new(user, suggestion, overlapping_suggestion).execute }
+ it 'returns error message' do
expect(result).to eq(message: 'Suggestions are not applicable as their lines cannot overlap.',
status: :error)
end
+
+ it_behaves_like 'service not tracking apply suggestion event'
end
end
end
diff --git a/spec/services/suggestions/create_service_spec.rb b/spec/services/suggestions/create_service_spec.rb
index 80823364fe8..5148d6756fc 100644
--- a/spec/services/suggestions/create_service_spec.rb
+++ b/spec/services/suggestions/create_service_spec.rb
@@ -53,6 +53,15 @@ RSpec.describe Suggestions::CreateService do
subject { described_class.new(note) }
+ shared_examples_for 'service not tracking add suggestion event' do
+ it 'does not track add suggestion event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_add_suggestion_action)
+
+ subject.execute
+ end
+ end
+
describe '#execute' do
context 'should not try to parse suggestions' do
context 'when not a diff note for merge requests' do
@@ -66,6 +75,8 @@ RSpec.describe Suggestions::CreateService do
subject.execute
end
+
+ it_behaves_like 'service not tracking add suggestion event'
end
context 'when diff note is not for text' do
@@ -76,17 +87,21 @@ RSpec.describe Suggestions::CreateService do
note: markdown)
end
- it 'does not try to parse suggestions' do
+ before do
allow(note).to receive(:on_text?) { false }
+ end
+ it 'does not try to parse suggestions' do
expect(Gitlab::Diff::SuggestionsParser).not_to receive(:parse)
subject.execute
end
+
+ it_behaves_like 'service not tracking add suggestion event'
end
end
- context 'should not create suggestions' do
+ context 'when diff file is not found' do
let(:note) do
create(:diff_note_on_merge_request, project: project_with_repo,
noteable: merge_request,
@@ -94,13 +109,17 @@ RSpec.describe Suggestions::CreateService do
note: markdown)
end
- it 'creates no suggestion when diff file is not found' do
+ before do
expect_next_instance_of(DiffNote) do |diff_note|
expect(diff_note).to receive(:latest_diff_file).once { nil }
end
+ end
+ it 'creates no suggestion' do
expect { subject.execute }.not_to change(Suggestion, :count)
end
+
+ it_behaves_like 'service not tracking add suggestion event'
end
context 'should create suggestions' do
@@ -137,6 +156,14 @@ RSpec.describe Suggestions::CreateService do
end
end
+ it 'tracks add suggestion event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_add_suggestion_action)
+ .with(user: note.author)
+
+ subject.execute
+ end
+
context 'outdated position note' do
let!(:outdated_diff) { merge_request.merge_request_diff }
let!(:latest_diff) { merge_request.create_merge_request_diff }
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 2020c67f465..1ec5237370f 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -45,15 +45,13 @@ RSpec.describe SystemHooksService do
it do
expect(event_data(group, :create)).to include(
- :event_name, :name, :created_at, :updated_at, :path, :group_id,
- :owner_name, :owner_email
+ :event_name, :name, :created_at, :updated_at, :path, :group_id
)
end
it do
expect(event_data(group, :destroy)).to include(
- :event_name, :name, :created_at, :updated_at, :path, :group_id,
- :owner_name, :owner_email
+ :event_name, :name, :created_at, :updated_at, :path, :group_id
)
end
@@ -156,9 +154,6 @@ RSpec.describe SystemHooksService do
it { expect(event_name(project_member, :update)).to eq "user_update_for_team" }
it { expect(event_name(key, :create)).to eq 'key_create' }
it { expect(event_name(key, :destroy)).to eq 'key_destroy' }
- it { expect(event_name(group, :create)).to eq 'group_create' }
- it { expect(event_name(group, :destroy)).to eq 'group_destroy' }
- it { expect(event_name(group, :rename)).to eq 'group_rename' }
end
def event_data(*args)
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 9c35f9e3817..df4880dfa13 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -213,15 +213,16 @@ RSpec.describe SystemNoteService do
describe '.change_branch' do
it 'calls MergeRequestsService' do
- old_branch = double
- new_branch = double
- branch_type = double
+ old_branch = double('old_branch')
+ new_branch = double('new_branch')
+ branch_type = double('branch_type')
+ event_type = double('event_type')
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
- expect(service).to receive(:change_branch).with(branch_type, old_branch, new_branch)
+ expect(service).to receive(:change_branch).with(branch_type, event_type, old_branch, new_branch)
end
- described_class.change_branch(noteable, project, author, branch_type, old_branch, new_branch)
+ described_class.change_branch(noteable, project, author, branch_type, event_type, old_branch, new_branch)
end
end
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index 96afca2f2cb..ae18bc23c17 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -729,12 +729,14 @@ RSpec.describe ::SystemNotes::IssuablesService do
it 'is false with issue tracker supporting referencing' do
create(:jira_service, project: project)
+ project.reload
expect(service.cross_reference_disallowed?(noteable)).to be_falsey
end
it 'is true with issue tracker not supporting referencing' do
create(:bugzilla_service, project: project)
+ project.reload
expect(service.cross_reference_disallowed?(noteable)).to be_truthy
end
diff --git a/spec/services/system_notes/merge_requests_service_spec.rb b/spec/services/system_notes/merge_requests_service_spec.rb
index 50d16231e8f..2131f3d3bdf 100644
--- a/spec/services/system_notes/merge_requests_service_spec.rb
+++ b/spec/services/system_notes/merge_requests_service_spec.rb
@@ -167,18 +167,38 @@ RSpec.describe ::SystemNotes::MergeRequestsService do
end
describe '.change_branch' do
- subject { service.change_branch('target', old_branch, new_branch) }
-
let(:old_branch) { 'old_branch'}
let(:new_branch) { 'new_branch'}
it_behaves_like 'a system note' do
let(:action) { 'branch' }
+
+ subject { service.change_branch('target', 'update', old_branch, new_branch) }
end
context 'when target branch name changed' do
- it 'sets the note text' do
- expect(subject.note).to eq "changed target branch from `#{old_branch}` to `#{new_branch}`"
+ context 'on update' do
+ subject { service.change_branch('target', 'update', old_branch, new_branch) }
+
+ it 'sets the note text' do
+ expect(subject.note).to eq "changed target branch from `#{old_branch}` to `#{new_branch}`"
+ end
+ end
+
+ context 'on delete' do
+ subject { service.change_branch('target', 'delete', old_branch, new_branch) }
+
+ it 'sets the note text' do
+ expect(subject.note).to eq "changed automatically target branch to `#{new_branch}` because `#{old_branch}` was deleted"
+ end
+ end
+
+ context 'for invalid event_type' do
+ subject { service.change_branch('target', 'invalid', old_branch, new_branch) }
+
+ it 'raises exception' do
+ expect { subject }.to raise_error /invalid value for event_type/
+ end
end
end
end
diff --git a/spec/services/test_hooks/project_service_spec.rb b/spec/services/test_hooks/project_service_spec.rb
index 7470bdff527..a87e612e378 100644
--- a/spec/services/test_hooks/project_service_spec.rb
+++ b/spec/services/test_hooks/project_service_spec.rb
@@ -3,11 +3,13 @@
require 'spec_helper'
RSpec.describe TestHooks::ProjectService do
+ include AfterNextHelpers
+
let(:current_user) { create(:user) }
describe '#execute' do
- let(:project) { create(:project, :repository) }
- let(:hook) { create(:project_hook, project: project) }
+ let_it_be(:project) { create(:project, :repository) }
+ let(:hook) { create(:project_hook, project: project) }
let(:trigger) { 'not_implemented_events' }
let(:service) { described_class.new(hook, current_user, trigger) }
let(:sample_data) { { data: 'sample' } }
@@ -61,17 +63,17 @@ RSpec.describe TestHooks::ProjectService do
end
it 'executes hook' do
- allow(project).to receive(:notes).and_return([Note.new])
+ create(:note, project: project)
+
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(service.execute).to include(success_result)
end
end
- context 'issues_events' do
- let(:trigger) { 'issues_events' }
- let(:trigger_key) { :issue_hooks }
+ shared_examples_for 'a test webhook that operates on issues' do
let(:issue) { build(:issue) }
it 'returns error message if not enough data' do
@@ -80,36 +82,32 @@ RSpec.describe TestHooks::ProjectService do
end
it 'executes hook' do
- allow(project).to receive(:issues).and_return([issue])
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(service.execute).to include(success_result)
end
end
+ context 'issues_events' do
+ let(:trigger) { 'issues_events' }
+ let(:trigger_key) { :issue_hooks }
+
+ it_behaves_like 'a test webhook that operates on issues'
+ end
+
context 'confidential_issues_events' do
let(:trigger) { 'confidential_issues_events' }
let(:trigger_key) { :confidential_issue_hooks }
- let(:issue) { build(:issue) }
- it 'returns error message if not enough data' do
- expect(hook).not_to receive(:execute)
- expect(service.execute).to include({ status: :error, message: 'Ensure the project has issues.' })
- end
-
- it 'executes hook' do
- allow(project).to receive(:issues).and_return([issue])
- allow(issue).to receive(:to_hook_data).and_return(sample_data)
-
- expect(hook).to receive(:execute).with(sample_data, trigger_key).and_return(success_result)
- expect(service.execute).to include(success_result)
- end
+ it_behaves_like 'a test webhook that operates on issues'
end
context 'merge_requests_events' do
let(:trigger) { 'merge_requests_events' }
let(:trigger_key) { :merge_request_hooks }
+ let(:merge_request) { build(:merge_request) }
it 'returns error message if not enough data' do
expect(hook).not_to receive(:execute)
@@ -117,8 +115,8 @@ RSpec.describe TestHooks::ProjectService do
end
it 'executes hook' do
- create(:merge_request, source_project: project)
- allow_any_instance_of(MergeRequest).to receive(:to_hook_data).and_return(sample_data)
+ 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(service.execute).to include(success_result)
@@ -128,6 +126,7 @@ RSpec.describe TestHooks::ProjectService do
context 'job_events' do
let(:trigger) { 'job_events' }
let(:trigger_key) { :job_hooks }
+ let(:ci_job) { build(:ci_build) }
it 'returns error message if not enough data' do
expect(hook).not_to receive(:execute)
@@ -135,8 +134,8 @@ RSpec.describe TestHooks::ProjectService do
end
it 'executes hook' do
- create(:ci_build, project: project)
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(service.execute).to include(success_result)
@@ -146,6 +145,7 @@ RSpec.describe TestHooks::ProjectService do
context 'pipeline_events' do
let(:trigger) { 'pipeline_events' }
let(:trigger_key) { :pipeline_hooks }
+ let(:pipeline) { build(:ci_empty_pipeline) }
it 'returns error message if not enough data' do
expect(hook).not_to receive(:execute)
@@ -153,8 +153,8 @@ RSpec.describe TestHooks::ProjectService do
end
it 'executes hook' do
- create(:ci_empty_pipeline, project: project)
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(service.execute).to include(success_result)
@@ -162,7 +162,7 @@ RSpec.describe TestHooks::ProjectService do
end
context 'wiki_page_events' do
- let(:project) { create(:project, :wiki_repo) }
+ let_it_be(:project) { create(:project, :wiki_repo) }
let(:trigger) { 'wiki_page_events' }
let(:trigger_key) { :wiki_page_hooks }
@@ -190,6 +190,7 @@ RSpec.describe TestHooks::ProjectService do
context 'releases_events' do
let(:trigger) { 'releases_events' }
let(:trigger_key) { :release_hooks }
+ let(:release) { build(:release) }
it 'returns error message if not enough data' do
expect(hook).not_to receive(:execute)
@@ -197,8 +198,8 @@ RSpec.describe TestHooks::ProjectService do
end
it 'executes hook' do
- allow(project).to receive(:releases).and_return([Release.new])
- allow_any_instance_of(Release).to receive(:to_hook_data).and_return(sample_data)
+ 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(service.execute).to include(success_result)
diff --git a/spec/services/test_hooks/system_service_spec.rb b/spec/services/test_hooks/system_service_spec.rb
index 34dd2173b09..e500a1057ab 100644
--- a/spec/services/test_hooks/system_service_spec.rb
+++ b/spec/services/test_hooks/system_service_spec.rb
@@ -3,12 +3,12 @@
require 'spec_helper'
RSpec.describe TestHooks::SystemService do
- let(:current_user) { create(:user) }
+ include AfterNextHelpers
describe '#execute' do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:hook) { create(:system_hook) }
- let(:service) { described_class.new(hook, current_user, trigger) }
+ let(:service) { described_class.new(hook, project.owner, trigger) }
let(:success_result) { { status: :success, http_status: 200, message: 'ok' } }
before do
@@ -63,6 +63,9 @@ RSpec.describe TestHooks::SystemService do
context 'merge_requests_events' do
let(:trigger) { 'merge_requests_events' }
+ let(:trigger_key) { :merge_request_hooks }
+ let(:merge_request) { build(:merge_request) }
+ let(:sample_data) { { data: 'sample' } }
it 'returns error message if the user does not have any repository with a merge request' do
expect(hook).not_to receive(:execute)
@@ -70,12 +73,8 @@ RSpec.describe TestHooks::SystemService do
end
it 'executes hook' do
- trigger_key = :merge_request_hooks
- sample_data = { data: 'sample' }
- create(:project_member, user: current_user, project: project)
- create(:merge_request, source_project: project)
- allow_any_instance_of(MergeRequest).to receive(:to_hook_data).and_return(sample_data)
-
+ 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(service.execute).to include(success_result)
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 83d233a8112..743dc080b06 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -1193,6 +1193,17 @@ RSpec.describe TodoService do
end
end
+ describe '#create_request_review_todo' do
+ let(:target) { create(:merge_request, author: author, source_project: project) }
+ let(:reviewer) { create(:user) }
+
+ it 'creates a todo for reviewer' do
+ service.create_request_review_todo(target, author, reviewer)
+
+ should_create_todo(user: reviewer, target: target, action: Todo::REVIEW_REQUESTED)
+ end
+ end
+
def should_create_todo(attributes = {})
attributes.reverse_merge!(
project: project,
diff --git a/spec/services/users/approve_service_spec.rb b/spec/services/users/approve_service_spec.rb
index 55b2c83f4a8..9999e674c7d 100644
--- a/spec/services/users/approve_service_spec.rb
+++ b/spec/services/users/approve_service_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Users::ApproveService do
it 'returns error result' do
expect(subject[:status]).to eq(:error)
expect(subject[:message])
- .to match(/The user you are trying to approve is not pending an approval/)
+ .to match(/The user you are trying to approve is not pending approval/)
end
end
@@ -61,6 +61,14 @@ RSpec.describe Users::ApproveService do
expect(user.reload).to be_active
end
+ it 'logs approval in application logs' do
+ allow(Gitlab::AppLogger).to receive(:info)
+
+ subject
+
+ expect(Gitlab::AppLogger).to have_received(:info).with(message: "User instance access request approved", user: "#{user.username}", email: "#{user.email}", approved_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}")
+ end
+
it 'emails the user on approval' do
expect(DeviseMailer).to receive(:user_admin_approval).with(user).and_call_original
expect { subject }.to have_enqueued_mail(DeviseMailer, :user_admin_approval)
@@ -82,6 +90,20 @@ RSpec.describe Users::ApproveService do
.not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
end
end
+
+ context 'audit events' do
+ context 'when not licensed' do
+ before do
+ stub_licensed_features(
+ admin_audit_log: false
+ )
+ end
+
+ it 'does not log any audit event' do
+ expect { subject }.not_to change(AuditEvent, :count)
+ end
+ end
+ end
end
context 'pending invitations' do
diff --git a/spec/services/users/batch_status_cleaner_service_spec.rb b/spec/services/users/batch_status_cleaner_service_spec.rb
new file mode 100644
index 00000000000..46a004542d8
--- /dev/null
+++ b/spec/services/users/batch_status_cleaner_service_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::BatchStatusCleanerService do
+ let_it_be(:user_status_1) { create(:user_status, emoji: 'coffee', message: 'msg1', clear_status_at: 1.year.ago) }
+ let_it_be(:user_status_2) { create(:user_status, emoji: 'coffee', message: 'msg1', clear_status_at: 1.year.from_now) }
+ let_it_be(:user_status_3) { create(:user_status, emoji: 'coffee', message: 'msg1', clear_status_at: 2.years.ago) }
+ let_it_be(:user_status_4) { create(:user_status, emoji: 'coffee', message: 'msg1') }
+
+ subject(:result) { described_class.execute }
+
+ it 'cleans up scheduled user statuses' do
+ expect(result[:deleted_rows]).to eq(2)
+
+ deleted_statuses = UserStatus.where(user_id: [user_status_1.user_id, user_status_3.user_id])
+ expect(deleted_statuses).to be_empty
+ end
+
+ it 'does not affect rows with future clear_status_at' do
+ expect { result }.not_to change { user_status_2.reload }
+ end
+
+ it 'does not affect rows without clear_status_at' do
+ expect { result }.not_to change { user_status_4.reload }
+ end
+
+ describe 'batch_size' do
+ it 'clears status in batches' do
+ result = described_class.execute(batch_size: 1)
+
+ expect(result[:deleted_rows]).to eq(1)
+
+ result = described_class.execute(batch_size: 1)
+
+ expect(result[:deleted_rows]).to eq(1)
+
+ result = described_class.execute(batch_size: 1)
+
+ expect(result[:deleted_rows]).to eq(0)
+ end
+ end
+end
diff --git a/spec/services/users/build_service_spec.rb b/spec/services/users/build_service_spec.rb
index 446741221b3..b2a7d349ce6 100644
--- a/spec/services/users/build_service_spec.rb
+++ b/spec/services/users/build_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Users::BuildService do
+ using RSpec::Parameterized::TableSyntax
+
describe '#execute' do
let(:params) { build_stubbed(:user).slice(:first_name, :last_name, :username, :email, :password) }
@@ -72,8 +74,6 @@ RSpec.describe Users::BuildService do
end
context 'with "user_default_external" application setting' do
- using RSpec::Parameterized::TableSyntax
-
where(:user_default_external, :external, :email, :user_default_internal_regex, :result) do
true | nil | 'fl@example.com' | nil | true
true | true | 'fl@example.com' | nil | true
@@ -192,8 +192,6 @@ RSpec.describe Users::BuildService do
end
context 'with "user_default_external" application setting' do
- using RSpec::Parameterized::TableSyntax
-
where(:user_default_external, :external, :email, :user_default_internal_regex, :result) do
true | nil | 'fl@example.com' | nil | true
true | true | 'fl@example.com' | nil | true
diff --git a/spec/services/users/refresh_authorized_projects_service_spec.rb b/spec/services/users/refresh_authorized_projects_service_spec.rb
index 9404668e3c5..cc01b22f9d2 100644
--- a/spec/services/users/refresh_authorized_projects_service_spec.rb
+++ b/spec/services/users/refresh_authorized_projects_service_spec.rb
@@ -143,6 +143,21 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
expect(authorizations[0].project_id).to eq(project.id)
expect(authorizations[0].access_level).to eq(Gitlab::Access::MAINTAINER)
end
+
+ it 'logs the details of the refresh' do
+ source = :foo
+ service = described_class.new(user, source: source)
+ user.project_authorizations.delete_all
+
+ expect(Gitlab::AppJsonLogger).to(
+ receive(:info)
+ .with(event: 'authorized_projects_refresh',
+ 'authorized_projects_refresh.source': source,
+ 'authorized_projects_refresh.rows_deleted': 0,
+ 'authorized_projects_refresh.rows_added': 1))
+
+ service.update_authorizations([], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
+ end
end
describe '#fresh_access_levels_per_project' do
diff --git a/spec/services/users/reject_service_spec.rb b/spec/services/users/reject_service_spec.rb
index 07863d1a290..b9aaff5cde5 100644
--- a/spec/services/users/reject_service_spec.rb
+++ b/spec/services/users/reject_service_spec.rb
@@ -48,6 +48,26 @@ RSpec.describe Users::RejectService do
subject
end
+
+ it 'logs rejection in application logs' do
+ allow(Gitlab::AppLogger).to receive(:info)
+
+ subject
+
+ expect(Gitlab::AppLogger).to have_received(:info).with(message: "User instance access request rejected", user: "#{user.username}", email: "#{user.email}", rejected_by: "#{current_user.username}", ip_address: "#{current_user.current_sign_in_ip}")
+ end
+ end
+ end
+
+ context 'audit events' do
+ context 'when not licensed' do
+ before do
+ stub_licensed_features(admin_audit_log: false)
+ end
+
+ it 'does not log any audit event' do
+ expect { subject }.not_to change(AuditEvent, :count)
+ end
end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9fac6c8e192..64c1479a412 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -13,6 +13,7 @@ end
Warning[:deprecated] = true unless ENV.key?('SILENCE_DEPRECATIONS')
require './spec/deprecation_toolkit_env'
+DeprecationToolkitEnv.configure!
require './spec/simplecov_env'
SimpleCovEnv.start!
@@ -33,6 +34,7 @@ require 'rspec-parameterized'
require 'shoulda/matchers'
require 'test_prof/recipes/rspec/let_it_be'
require 'test_prof/factory_default'
+require 'parslet/rig/rspec'
rspec_profiling_is_configured =
ENV['RSPEC_PROFILING_POSTGRES_URL'].present? ||
@@ -174,6 +176,7 @@ RSpec.configure do |config|
if ENV['CI'] || ENV['RETRIES']
# This includes the first try, i.e. tests will be run 4 times before failing.
config.default_retry_count = ENV.fetch('RETRIES', 3).to_i + 1
+ config.exceptions_to_hard_fail = [DeprecationToolkitEnv::DeprecationBehaviors::SelectiveRaise::RaiseDisallowedDeprecation]
end
if ENV['FLAKY_RSPEC_GENERATE_REPORT']
@@ -216,16 +219,9 @@ RSpec.configure do |config|
# (ie. ApplicationSetting#auto_devops_enabled)
stub_feature_flags(force_autodevops_on_by_default: false)
- # The following can be removed once Vue Issuable Sidebar
- # is feature-complete and can be made default in place
- # of older sidebar.
- # See https://gitlab.com/groups/gitlab-org/-/epics/1863
- stub_feature_flags(vue_issuable_sidebar: false)
- stub_feature_flags(vue_issuable_epic_sidebar: false)
-
# Merge request widget GraphQL requests are disabled in the tests
# for now whilst we migrate as much as we can over the GraphQL
- stub_feature_flags(merge_request_widget_graphql: false)
+ # stub_feature_flags(merge_request_widget_graphql: false)
# Using FortiAuthenticator as OTP provider is disabled by default in
# tests, until we introduce it in user settings
@@ -289,6 +285,8 @@ RSpec.configure do |config|
current_user_mode.send(:user)&.admin?
end
end
+
+ allow(Gitlab::CurrentSettings).to receive(:current_application_settings?).and_return(false)
end
config.around(:example, :quarantine) do |example|
diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb
index c9d372993b5..5761e05d541 100644
--- a/spec/support/factory_bot.rb
+++ b/spec/support/factory_bot.rb
@@ -3,3 +3,16 @@
FactoryBot::SyntaxRunner.class_eval do
include RSpec::Mocks::ExampleMethods
end
+
+# Patching FactoryBot to allow stubbing non AR models
+# See https://github.com/thoughtbot/factory_bot/pull/1466
+module Gitlab
+ module FactoryBotStubPatch
+ def has_settable_id?(result_instance)
+ result_instance.class.respond_to?(:primary_key) &&
+ result_instance.class.primary_key
+ end
+ end
+end
+
+FactoryBot::Strategy::Stub.prepend(Gitlab::FactoryBotStubPatch)
diff --git a/spec/support/gitlab_experiment.rb b/spec/support/gitlab_experiment.rb
index 1f283e4f06c..45ae9958c52 100644
--- a/spec/support/gitlab_experiment.rb
+++ b/spec/support/gitlab_experiment.rb
@@ -1,4 +1,16 @@
# frozen_string_literal: true
+# Require the provided spec helper and matchers.
+require 'gitlab/experiment/rspec'
+
+# This is a temporary fix until we have a larger discussion around the
+# challenges raised in https://gitlab.com/gitlab-org/gitlab/-/issues/300104
+class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/NamespacedClass
+ def initialize(...)
+ super(...)
+ Feature.persist_used!(feature_flag_name)
+ end
+end
+
# Disable all caching for experiments in tests.
Gitlab::Experiment::Configuration.cache = nil
diff --git a/spec/support/graphql/field_selection.rb b/spec/support/graphql/field_selection.rb
index e2a3334acac..00323c46d69 100644
--- a/spec/support/graphql/field_selection.rb
+++ b/spec/support/graphql/field_selection.rb
@@ -47,7 +47,7 @@ module Graphql
NO_SKIP = ->(_name, _field) { false }
def self.select_fields(type, skip = NO_SKIP, parent_types = Set.new, max_depth = 3)
- return new if max_depth <= 0
+ return new if max_depth <= 0 || !type.kind.fields?
new(type.fields.flat_map do |name, field|
next [] if skip[name, field]
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 6d3ac699a7c..a90cbbf3bd3 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -3,6 +3,32 @@
module CycleAnalyticsHelpers
include GitHelpers
+ def wait_for_stages_to_load
+ expect(page).to have_selector '.js-stage-table'
+ wait_for_requests
+ end
+
+ def select_group(target_group)
+ visit group_analytics_cycle_analytics_path(target_group)
+
+ wait_for_stages_to_load
+ end
+
+ def toggle_dropdown(field)
+ page.within("[data-testid='#{field}']") do
+ find('.dropdown-toggle').click
+
+ wait_for_requests
+
+ expect(find('.dropdown-menu')).to have_selector('.dropdown-item')
+ end
+ end
+
+ def select_dropdown_option_by_value(name, value, elem = '.dropdown-item')
+ toggle_dropdown name
+ page.find("[data-testid='#{name}'] .dropdown-menu").find("#{elem}[value='#{value}']").click
+ end
+
def create_commit_referencing_issue(issue, branch_name: generate(:branch))
project.repository.add_branch(user, branch_name, 'master')
create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name)
diff --git a/spec/support/helpers/features/members_table_helpers.rb b/spec/support/helpers/features/members_table_helpers.rb
index 5394e370900..4a0e218ed3e 100644
--- a/spec/support/helpers/features/members_table_helpers.rb
+++ b/spec/support/helpers/features/members_table_helpers.rb
@@ -30,6 +30,32 @@ module Spec
def invite_users_form
page.find('[data-testid="invite-users-form"]')
end
+
+ def find_row(name)
+ page.within(members_table) do
+ page.find('tbody > tr', text: name)
+ end
+ end
+
+ def find_member_row(user)
+ find_row(user.name)
+ end
+
+ def find_invited_member_row(email)
+ find_row(email)
+ end
+
+ def find_group_row(group)
+ find_row(group.full_name)
+ end
+
+ def fill_in_filtered_search(label, with:)
+ page.within '[data-testid="members-filtered-search-bar"]' do
+ find_field(label).click
+ find('input').native.send_keys(with)
+ click_button 'Search'
+ end
+ end
end
end
end
diff --git a/spec/support/helpers/features/notes_helpers.rb b/spec/support/helpers/features/notes_helpers.rb
index 8c27f81930d..f8252254531 100644
--- a/spec/support/helpers/features/notes_helpers.rb
+++ b/spec/support/helpers/features/notes_helpers.rb
@@ -21,6 +21,8 @@ module Spec
find(".js-comment-submit-button").click
end
end
+
+ wait_for_requests
end
def edit_note(note_text_to_edit, new_note_text)
@@ -29,6 +31,8 @@ module Spec
fill_in('note[note]', with: new_note_text)
find('.js-comment-button').click
end
+
+ wait_for_requests
end
def preview_note(text)
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 35c298a4d48..46d0c13dc18 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -125,11 +125,15 @@ module GraphqlHelpers
end
def graphql_query_for(name, attributes = {}, fields = nil)
- <<~QUERY
- {
- #{query_graphql_field(name, attributes, fields)}
- }
- QUERY
+ type = GitlabSchema.types['Query'].fields[GraphqlHelpers.fieldnamerize(name)]&.type
+ wrap_query(query_graphql_field(name, attributes, fields, type))
+ end
+
+ def wrap_query(query)
+ q = query.to_s
+ return q if q.starts_with?('{')
+
+ "{ #{q} }"
end
def graphql_mutation(name, input, fields = nil, &block)
@@ -219,12 +223,13 @@ module GraphqlHelpers
"#{namerized}#{field_params}"
end
- def query_graphql_field(name, attributes = {}, fields = nil)
+ def query_graphql_field(name, attributes = {}, fields = nil, type = nil)
+ type ||= name.to_s.classify
attributes, fields = [nil, attributes] if fields.nil? && !attributes.is_a?(Hash)
field = field_with_params(name, attributes)
- field + wrap_fields(fields || all_graphql_fields_for(name.to_s.classify)).to_s
+ field + wrap_fields(fields || all_graphql_fields_for(type)).to_s
end
def page_info_selection
@@ -237,6 +242,10 @@ module GraphqlHelpers
query_graphql_path([[name, args], node_selection], fields)
end
+ def query_graphql_fragment(name)
+ "... on #{name} { #{all_graphql_fields_for(name)} }"
+ end
+
# e.g:
# query_graphql_path(%i[foo bar baz], all_graphql_fields_for('Baz'))
# => foo { bar { baz { x y z } } }
@@ -277,8 +286,8 @@ module GraphqlHelpers
allow_high_graphql_recursion
allow_high_graphql_transaction_threshold
- type = GitlabSchema.types[class_name.to_s]
- return "" unless type
+ type = class_name.respond_to?(:kind) ? class_name : GitlabSchema.types[class_name.to_s]
+ raise "#{class_name} is not a known type in the GitlabSchema" unless type
# We can't guess arguments, so skip fields that require them
skip = ->(name, field) { excluded.include?(name) || required_arguments?(field) }
@@ -287,7 +296,7 @@ module GraphqlHelpers
end
def with_signature(variables, query)
- %Q[query(#{variables.map(&:sig).join(', ')}) #{query}]
+ %Q[query(#{variables.map(&:sig).join(', ')}) #{wrap_query(query)}]
end
def var(type)
@@ -305,6 +314,10 @@ module GraphqlHelpers
def post_graphql(query, current_user: nil, variables: nil, headers: {})
params = { query: query, variables: serialize_variables(variables) }
post api('/', current_user, version: 'graphql'), params: params, headers: headers
+
+ if graphql_errors # Errors are acceptable, but not this one:
+ expect(graphql_errors).not_to include(a_hash_including('message' => 'Internal server error'))
+ end
end
def post_graphql_mutation(mutation, current_user: nil)
@@ -374,10 +387,8 @@ module GraphqlHelpers
end
# Raises an error if no data is found
- def graphql_data(body = json_response)
- # Note that `json_response` is defined as `let(:json_response)` and
- # therefore, in a spec with multiple queries, will only contain data
- # from the _first_ query, not subsequent ones
+ # NB: We use fresh_response_data to support tests that make multiple requests.
+ def graphql_data(body = fresh_response_data)
body['data'] || (raise NoData, graphql_errors(body))
end
@@ -510,8 +521,12 @@ module GraphqlHelpers
end
end
- def global_id_of(model)
- model.to_global_id.to_s
+ def global_id_of(model, id: nil, model_name: nil)
+ if id || model_name
+ ::Gitlab::GlobalId.build(model, id: id, model_name: model_name).to_s
+ else
+ model.to_global_id.to_s
+ end
end
def missing_required_argument(path, argument)
diff --git a/spec/support/helpers/next_found_instance_of.rb b/spec/support/helpers/next_found_instance_of.rb
index ff34fcdd1d3..feb63f90211 100644
--- a/spec/support/helpers/next_found_instance_of.rb
+++ b/spec/support/helpers/next_found_instance_of.rb
@@ -6,7 +6,7 @@ module NextFoundInstanceOf
def expect_next_found_instance_of(klass)
check_if_active_record!(klass)
- stub_allocate(expect(klass)) do |expectation|
+ stub_allocate(expect(klass), klass) do |expectation|
yield(expectation)
end
end
@@ -14,7 +14,7 @@ module NextFoundInstanceOf
def allow_next_found_instance_of(klass)
check_if_active_record!(klass)
- stub_allocate(allow(klass)) do |allowance|
+ stub_allocate(allow(klass), klass) do |allowance|
yield(allowance)
end
end
@@ -25,9 +25,17 @@ module NextFoundInstanceOf
raise ArgumentError.new(ERROR_MESSAGE) unless klass < ActiveRecord::Base
end
- def stub_allocate(target)
+ def stub_allocate(target, klass)
target.to receive(:allocate).and_wrap_original do |method|
- method.call.tap { |allocation| yield(allocation) }
+ method.call.tap do |allocation|
+ # ActiveRecord::Core.allocate returns a frozen object:
+ # https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activerecord/lib/active_record/core.rb#L620
+ # It's unexpected behavior and probably a bug in Rails
+ # Let's work it around by setting the attributes to default to unfreeze the object for now
+ allocation.instance_variable_set(:@attributes, klass._default_attributes)
+
+ yield(allocation)
+ end
end
end
end
diff --git a/spec/support/helpers/search_settings_helpers.rb b/spec/support/helpers/search_settings_helpers.rb
new file mode 100644
index 00000000000..838f897bff5
--- /dev/null
+++ b/spec/support/helpers/search_settings_helpers.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module SearchHelpers
+ self::INPUT_PLACEHOLDER = 'Search settings'
+end
diff --git a/spec/support/helpers/seed_helper.rb b/spec/support/helpers/seed_helper.rb
index 90d7f60fdeb..f65993efa05 100644
--- a/spec/support/helpers/seed_helper.rb
+++ b/spec/support/helpers/seed_helper.rb
@@ -4,7 +4,7 @@ require_relative 'test_env'
# This file is specific to specs in spec/lib/gitlab/git/
-SEED_STORAGE_PATH = TestEnv.repos_path
+SEED_STORAGE_PATH = Gitlab::GitalyClient::StorageSettings.allow_disk_access { TestEnv.repos_path }
TEST_REPO_PATH = 'gitlab-git-test.git'
TEST_NORMAL_REPO_PATH = 'not-bare-repo.git'
TEST_MUTABLE_REPO_PATH = 'mutable-repo.git'
diff --git a/spec/support/helpers/smime_helper.rb b/spec/support/helpers/smime_helper.rb
index 261aef9518e..fa16c433c6b 100644
--- a/spec/support/helpers/smime_helper.rb
+++ b/spec/support/helpers/smime_helper.rb
@@ -52,7 +52,7 @@ module SmimeHelper
cert.add_extension(extension_factory.create_extension('extendedKeyUsage', 'clientAuth,emailProtection', false))
end
- cert.sign(signed_by&.fetch(:key, nil) || key, OpenSSL::Digest::SHA256.new)
+ cert.sign(signed_by&.fetch(:key, nil) || key, OpenSSL::Digest.new('SHA256'))
{ key: key, cert: cert }
end
diff --git a/spec/support/helpers/sorting_helper.rb b/spec/support/helpers/sorting_helper.rb
index 3801d25fb63..f19f8c12928 100644
--- a/spec/support/helpers/sorting_helper.rb
+++ b/spec/support/helpers/sorting_helper.rb
@@ -17,4 +17,35 @@ module SortingHelper
click_link value
end
end
+
+ def nils_last(value)
+ NilsLast.new(value)
+ end
+
+ class NilsLast
+ include Comparable
+
+ attr_reader :value
+ delegate :==, :eql?, :hash, to: :value
+
+ def initialize(value)
+ @value = value
+ @reverse = false
+ end
+
+ def <=>(other)
+ return unless other.is_a?(self.class)
+ return 0 if value.nil? && other.value.nil?
+ return 1 if value.nil?
+ return -1 if other.value.nil?
+
+ int = value <=> other.value
+ @reverse ? -int : int
+ end
+
+ def -@
+ @reverse = true
+ self
+ end
+ end
end
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index 3b733a2e57a..9851a3de9e9 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -121,6 +121,12 @@ module StubConfiguration
allow(::Gitlab.config.packages).to receive_messages(to_settings(messages))
end
+ def stub_maintenance_mode_setting(value)
+ allow(Gitlab::CurrentSettings).to receive(:current_application_settings?).and_return(true)
+
+ stub_application_setting(maintenance_mode: value)
+ end
+
private
# Modifies stubbed messages to also stub possible predicate versions
diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index dc54a21d0fa..0d0ac171baa 100644
--- a/spec/support/helpers/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -85,6 +85,13 @@ module StubObjectStorage
**params)
end
+ def stub_composer_cache_object_storage(**params)
+ stub_object_storage_uploader(config: Gitlab.config.packages.object_store,
+ uploader: ::Packages::Composer::CacheUploader,
+ remote_directory: 'packages',
+ **params)
+ end
+
def stub_uploads_object_storage(uploader = described_class, **params)
stub_object_storage_uploader(config: Gitlab.config.uploads.object_store,
uploader: uploader,
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index cb25f5f9429..2d71662b0eb 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -149,7 +149,9 @@ module TestEnv
end
end
- FileUtils.mkdir_p(repos_path)
+ FileUtils.mkdir_p(
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access { TestEnv.repos_path }
+ )
FileUtils.mkdir_p(SECOND_STORAGE_PATH)
FileUtils.mkdir_p(backup_path)
FileUtils.mkdir_p(pages_path)
diff --git a/spec/support/helpers/wait_for_requests.rb b/spec/support/helpers/wait_for_requests.rb
index 43060e571a9..8fd9bb47053 100644
--- a/spec/support/helpers/wait_for_requests.rb
+++ b/spec/support/helpers/wait_for_requests.rb
@@ -52,6 +52,6 @@ module WaitForRequests
end
def finished_all_ajax_requests?
- Capybara.page.evaluate_script('window.pendingRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
+ Capybara.page.evaluate_script('window.pendingRequests || window.pendingApolloRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
end
end
diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb
index 6e75fa58700..47cffad8c41 100644
--- a/spec/support/matchers/markdown_matchers.rb
+++ b/spec/support/matchers/markdown_matchers.rb
@@ -246,6 +246,33 @@ module MarkdownMatchers
end
end
end
+
+ # MermaidFilter
+ matcher :parse_mermaid do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_selector('code.js-render-mermaid')
+ end
+ end
+
+ # PLantumlFilter
+ matcher :parse_plantuml do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_link(href: 'http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd9vm80EtS5lW00')
+ end
+ end
+
+ # KrokiFilter
+ matcher :parse_kroki do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_link(href: 'http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==')
+ end
+ end
end
# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for
diff --git a/spec/support/matchers/nullify_if_blank_matcher.rb b/spec/support/matchers/nullify_if_blank_matcher.rb
new file mode 100644
index 00000000000..8f6737499cc
--- /dev/null
+++ b/spec/support/matchers/nullify_if_blank_matcher.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :nullify_if_blank do |attribute|
+ match do |record|
+ expect(record.class.attributes_to_nullify).to include(attribute)
+ end
+
+ failure_message do |record|
+ "expected nullify_if_blank configuration on #{record.class} to include #{attribute}"
+ end
+end
diff --git a/spec/support/matchers/pushed_frontend_feature_flags_matcher.rb b/spec/support/matchers/pushed_frontend_feature_flags_matcher.rb
new file mode 100644
index 00000000000..b49d4da8cda
--- /dev/null
+++ b/spec/support/matchers/pushed_frontend_feature_flags_matcher.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :have_pushed_frontend_feature_flags do |expected|
+ def to_js(key, value)
+ "\"#{key}\":#{value}"
+ end
+
+ match do |actual|
+ expected.all? do |feature_flag_name, enabled|
+ page.html.include?(to_js(feature_flag_name, enabled))
+ end
+ end
+
+ failure_message do |actual|
+ missing = expected.select do |feature_flag_name, enabled|
+ !page.html.include?(to_js(feature_flag_name, enabled))
+ end
+
+ formatted_missing_flags = missing.map { |feature_flag_name, enabled| to_js(feature_flag_name, enabled) }.join("\n")
+
+ "The following feature flag(s) cannot be found in the frontend HTML source: #{formatted_missing_flags}"
+ end
+end
diff --git a/spec/support/matchers/track_self_describing_event_matcher.rb b/spec/support/matchers/track_self_describing_event_matcher.rb
new file mode 100644
index 00000000000..c3723d2418f
--- /dev/null
+++ b/spec/support/matchers/track_self_describing_event_matcher.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+RSpec::Matchers.define :track_self_describing_event do |schema, data|
+ match do
+ expect(Gitlab::Tracking).to have_received(:self_describing_event)
+ .with(schema, data: data)
+ end
+
+ match_when_negated do
+ expect(Gitlab::Tracking).not_to have_received(:self_describing_event)
+ end
+end
diff --git a/spec/support/memory_instrumentation_helper.rb b/spec/support/memory_instrumentation_helper.rb
new file mode 100644
index 00000000000..84ec02fa5aa
--- /dev/null
+++ b/spec/support/memory_instrumentation_helper.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# Memory instrumentation can only be done if running on a valid Ruby
+#
+# This concept is currently tried to be upstreamed here:
+# - https://github.com/ruby/ruby/pull/3978
+module MemoryInstrumentationHelper
+ def skip_memory_instrumentation!
+ return if ::Gitlab::Memory::Instrumentation.available?
+
+ # if we are running in CI, a test cannot be skipped
+ return if ENV['CI']
+
+ skip 'Missing a memory instrumentation patch. ' \
+ 'More information can be found here: https://gitlab.com/gitlab-org/gitlab/-/issues/296530.'
+ end
+end
diff --git a/spec/support/migrations_helpers/vulnerabilities_findings_helper.rb b/spec/support/migrations_helpers/vulnerabilities_findings_helper.rb
new file mode 100644
index 00000000000..922f49ba84a
--- /dev/null
+++ b/spec/support/migrations_helpers/vulnerabilities_findings_helper.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+module MigrationHelpers
+ module VulnerabilitiesFindingsHelper
+ def attributes_for_vulnerabilities_finding
+ uuid = SecureRandom.uuid
+
+ {
+ project_fingerprint: SecureRandom.hex(20),
+ location_fingerprint: Digest::SHA1.hexdigest(SecureRandom.hex(10)),
+ uuid: uuid,
+ name: "Vulnerability Finding #{uuid}",
+ metadata_version: '1.3',
+ raw_metadata: raw_metadata
+ }
+ end
+
+ def raw_metadata
+ {
+ "description" => "The cipher does not provide data integrity update 1",
+ "message" => "The cipher does not provide data integrity",
+ "cve" => "818bf5dacb291e15d9e6dc3c5ac32178:CIPHER",
+ "solution" => "GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result.",
+ "location" => {
+ "file" => "maven/src/main/java/com/gitlab/security_products/tests/App.java",
+ "start_line" => 29,
+ "end_line" => 29,
+ "class" => "com.gitlab.security_products.tests.App",
+ "method" => "insecureCypher"
+ },
+ "links" => [
+ {
+ "name" => "Cipher does not check for integrity first?",
+ "url" => "https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first"
+ }
+ ],
+ "assets" => [
+ {
+ "type" => "postman",
+ "name" => "Test Postman Collection",
+ "url" => "http://localhost/test.collection"
+ }
+ ],
+ "evidence" => {
+ "summary" => "Credit card detected",
+ "request" => {
+ "method" => "GET",
+ "url" => "http://goat:8080/WebGoat/logout",
+ "body" => nil,
+ "headers" => [
+ {
+ "name" => "Accept",
+ "value" => "*/*"
+ }
+ ]
+ },
+ "response" => {
+ "reason_phrase" => "OK",
+ "status_code" => 200,
+ "body" => nil,
+ "headers" => [
+ {
+ "name" => "Content-Length",
+ "value" => "0"
+ }
+ ]
+ },
+ "source" => {
+ "id" => "assert:Response Body Analysis",
+ "name" => "Response Body Analysis",
+ "url" => "htpp://hostname/documentation"
+ },
+ "supporting_messages" => [
+ {
+ "name" => "Origional",
+ "request" => {
+ "method" => "GET",
+ "url" => "http://goat:8080/WebGoat/logout",
+ "body" => "",
+ "headers" => [
+ {
+ "name" => "Accept",
+ "value" => "*/*"
+ }
+ ]
+ }
+ },
+ {
+ "name" => "Recorded",
+ "request" => {
+ "method" => "GET",
+ "url" => "http://goat:8080/WebGoat/logout",
+ "body" => "",
+ "headers" => [
+ {
+ "name" => "Accept",
+ "value" => "*/*"
+ }
+ ]
+ },
+ "response" => {
+ "reason_phrase" => "OK",
+ "status_code" => 200,
+ "body" => "",
+ "headers" => [
+ {
+ "name" => "Content-Length",
+ "value" => "0"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 57d8320b76a..3fd4f2698e9 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -18,7 +18,8 @@ RSpec.shared_context 'project navbar structure' do
{
nav_item: _('Security & Compliance'),
nav_sub_items: [
- _('Audit Events')
+ _('Configuration'),
+ (_('Audit Events') if Gitlab.ee?)
]
}
end
@@ -71,7 +72,7 @@ RSpec.shared_context 'project navbar structure' do
_('Schedules')
]
},
- (security_and_compliance_nav_item if Gitlab.ee?),
+ security_and_compliance_nav_item,
{
nav_item: _('Operations'),
nav_sub_items: [
@@ -190,7 +191,7 @@ RSpec.shared_context 'group navbar structure' do
nav_item: _('Merge Requests'),
nav_sub_items: []
},
- (security_and_compliance_nav_item if Gitlab.ee?),
+ security_and_compliance_nav_item,
(push_rules_nav_item if Gitlab.ee?),
{
nav_item: _('Kubernetes'),
diff --git a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
index 580ebf00dcb..f3bbb325475 100644
--- a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
@@ -22,7 +22,7 @@ RSpec.shared_context 'conan api setup' do
let(:jwt_secret) do
OpenSSL::HMAC.hexdigest(
- OpenSSL::Digest::SHA256.new,
+ OpenSSL::Digest.new('SHA256'),
base_secret,
Gitlab::ConanToken::HMAC_KEY
)
@@ -67,9 +67,9 @@ RSpec.shared_context 'conan file upload endpoints' do
include WorkhorseHelpers
include HttpBasicAuthHelpers
+ include_context 'workhorse headers'
+
let(:jwt) { build_jwt(personal_access_token) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
- let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_header) }
+ let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_headers) }
let(:recipe_path) { "foo/bar/#{project.full_path.tr('/', '+')}/baz"}
end
diff --git a/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
index 7c23ec33cf8..60a29d78084 100644
--- a/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/npm_packages_shared_context.rb
@@ -4,10 +4,10 @@ RSpec.shared_context 'npm api setup' do
include PackagesManagerApiSpecHelpers
include HttpBasicAuthHelpers
- let_it_be(:user) { create(:user) }
+ let_it_be(:user, reload: true) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :public, namespace: group) }
- let_it_be(:package, reload: true) { create(:npm_package, project: project) }
+ let_it_be(:package, reload: true) { create(:npm_package, project: project, name: "@#{group.path}/scoped_package") }
let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
@@ -15,8 +15,15 @@ RSpec.shared_context 'npm api setup' do
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let(:package_name) { package.name }
+end
- before do
- project.add_developer(user)
+RSpec.shared_context 'set package name from package name type' do
+ let(:package_name) do
+ case package_name_type
+ when :scoped_naming_convention
+ "@#{group.path}/scoped-package"
+ when :non_existing
+ 'non-existing-package'
+ end
end
end
diff --git a/spec/support/shared_contexts/requests/api/workhorse_shared_context.rb b/spec/support/shared_contexts/requests/api/workhorse_shared_context.rb
new file mode 100644
index 00000000000..36be64339a2
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/workhorse_shared_context.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'workhorse headers' do
+ let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
+ let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+end
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 320f7564cf9..3322c6ef01a 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -62,7 +62,6 @@ Service.available_services_names.each do |service|
stub_licensed_features(licensed_feature => true)
project.clear_memoization(:disabled_services)
- project.clear_memoization(:licensed_feature_available)
end
end
end
diff --git a/spec/support/shared_examples/alert_notification_service_shared_examples.rb b/spec/support/shared_examples/alert_notification_service_shared_examples.rb
index 1568e4357a1..7bd6df8c608 100644
--- a/spec/support/shared_examples/alert_notification_service_shared_examples.rb
+++ b/spec/support/shared_examples/alert_notification_service_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'Alert Notification Service sends notification email' do
let(:notification_service) { spy }
- it 'sends a notification for firing alerts only' do
+ it 'sends a notification' do
expect(NotificationService)
.to receive(:new)
.and_return(notification_service)
@@ -15,15 +15,15 @@ RSpec.shared_examples 'Alert Notification Service sends notification email' do
end
end
-RSpec.shared_examples 'Alert Notification Service sends no notifications' do |http_status:|
- let(:notification_service) { spy }
- let(:create_events_service) { spy }
-
+RSpec.shared_examples 'Alert Notification Service sends no notifications' do |http_status: nil|
it 'does not notify' do
- expect(notification_service).not_to receive(:async)
- expect(create_events_service).not_to receive(:execute)
+ expect(NotificationService).not_to receive(:new)
- expect(subject).to be_error
- expect(subject.http_status).to eq(http_status)
+ if http_status.present?
+ expect(subject).to be_error
+ expect(subject.http_status).to eq(http_status)
+ else
+ expect(subject).to be_success
+ end
end
end
diff --git a/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb b/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb
index f89d52f81ad..7f49d20c83e 100644
--- a/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb
+++ b/spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.rb
@@ -3,6 +3,8 @@
RSpec.shared_examples 'multiple issue boards' do
context 'authorized user' do
before do
+ stub_feature_flags(board_new_list: false)
+
parent.add_maintainer(user)
login_as(user)
diff --git a/spec/support/shared_examples/controllers/unique_hll_events_examples.rb b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
index c5d65743810..842ad89bafd 100644
--- a/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
+++ b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
@@ -5,20 +5,14 @@
# - expected_type
# - target_id
-RSpec.shared_examples 'tracking unique hll events' do |feature_flag|
+RSpec.shared_examples 'tracking unique hll events' do
it 'tracks unique event' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(target_id, values: expected_type)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to(
+ receive(:track_event)
+ .with(target_id, values: expected_type)
+ .and_call_original # we call original to trigger additional validations; otherwise the method is stubbed
+ )
request
end
-
- context 'when feature flag is disabled' do
- it 'does not track unique event' do
- stub_feature_flags(feature_flag => false)
-
- expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
-
- request
- end
- end
end
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index dcbf494186a..0a040557ffe 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -218,7 +218,7 @@ RSpec.shared_examples 'wiki controller actions' do
end
context 'page view tracking' do
- it_behaves_like 'tracking unique hll events', :track_unique_wiki_page_views do
+ it_behaves_like 'tracking unique hll events' do
let(:target_id) { 'wiki_action' }
let(:expected_type) { instance_of(String) }
end
diff --git a/spec/support/shared_examples/features/comment_and_close_button_shared_examples.rb b/spec/support/shared_examples/features/comment_and_close_button_shared_examples.rb
new file mode 100644
index 00000000000..4ee2840ed9f
--- /dev/null
+++ b/spec/support/shared_examples/features/comment_and_close_button_shared_examples.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'page with comment and close button' do |button_text|
+ context 'when remove_comment_close_reopen feature flag is enabled' do
+ before do
+ stub_feature_flags(remove_comment_close_reopen: true)
+ setup
+ end
+
+ it "does not show #{button_text} button" do
+ within '.note-form-actions' do
+ expect(page).not_to have_button(button_text)
+ end
+ end
+ end
+
+ context 'when remove_comment_close_reopen feature flag is disabled' do
+ before do
+ stub_feature_flags(remove_comment_close_reopen: false)
+ setup
+ end
+
+ it "shows #{button_text} button" do
+ within '.note-form-actions' do
+ expect(page).to have_button(button_text)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/discussion_comments_shared_example.rb b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
index 560cfbfb117..6bebd59ed70 100644
--- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb
+++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
@@ -150,12 +150,13 @@ RSpec.shared_examples 'thread comments' do |resource_name|
wait_for_requests
end
- it 'clicking "Start thread" will post a thread' do
+ it 'clicking "Start thread" will post a thread and show a reply component' do
expect(page).to have_content(comment)
new_comment = all(comments_selector).last
expect(new_comment).to have_selector('.discussion')
+ expect(new_comment).to have_css('.discussion-with-resolve-btn')
end
if resource_name =~ /(issue|merge request)/
diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
index 2fff4137934..ccd063faac4 100644
--- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
@@ -48,7 +48,7 @@ RSpec.shared_examples 'an editable merge request' do
end
page.within '.reviewer' do
- expect(page).to have_content user.name
+ expect(page).to have_content user.username
end
page.within '.milestone' do
diff --git a/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb b/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb
index 48cde90bd9b..ad6ca3e1900 100644
--- a/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb
+++ b/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb
@@ -40,7 +40,7 @@ RSpec.shared_examples 'multiple reviewers merge request' do |action, save_button
# Closing dropdown to persist
click_link 'Edit'
- expect(page).to have_content user2.name
+ expect(page).to have_content user2.username
end
end
end
diff --git a/spec/support/shared_examples/features/navbar_shared_examples.rb b/spec/support/shared_examples/features/navbar_shared_examples.rb
index c768e95c45a..9b89a3b5e54 100644
--- a/spec/support/shared_examples/features/navbar_shared_examples.rb
+++ b/spec/support/shared_examples/features/navbar_shared_examples.rb
@@ -8,12 +8,13 @@ RSpec.shared_examples 'verified navigation bar' do
end
it 'renders correctly' do
- current_structure = page.all('.sidebar-top-level-items > li', class: ['!hidden']).map do |item|
+ # we are using * here in the selectors to prevent a regression where we added a non 'li' inside an 'ul'
+ current_structure = page.all('.sidebar-top-level-items > *', class: ['!hidden']).map do |item|
next if item.find_all('a').empty?
nav_item = item.find_all('a').first.text.gsub(/\s+\d+$/, '') # remove counts at the end
- nav_sub_items = item.all('.sidebar-sub-level-items > li', class: ['!fly-out-top-item']).map do |list_item|
+ nav_sub_items = item.all('.sidebar-sub-level-items > *', class: ['!fly-out-top-item']).map do |list_item|
list_item.all('a').first.text
end
diff --git a/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb b/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
index a46382bc292..56154c7cd03 100644
--- a/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
+++ b/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
@@ -56,6 +56,8 @@ RSpec.shared_examples "protected branches > access control > CE" do
expect(first("li")).to have_content("Roles")
find(:link, access_type_name).click
end
+
+ find(".js-allowed-to-push").click
end
wait_for_requests
diff --git a/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb b/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb
index a2d2143271c..28fe198c9c3 100644
--- a/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb
+++ b/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-RSpec.shared_examples 'when the deploy_keys_on_protected_branches FF is turned on' do
+RSpec.shared_examples 'Deploy keys with protected branches' do
before do
- stub_feature_flags(deploy_keys_on_protected_branches: true)
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/support/shared_examples/features/search_settings_shared_examples.rb b/spec/support/shared_examples/features/search_settings_shared_examples.rb
new file mode 100644
index 00000000000..6a507c4be56
--- /dev/null
+++ b/spec/support/shared_examples/features/search_settings_shared_examples.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'cannot search settings' do
+ it 'does note have search settings field' do
+ expect(page).not_to have_field(placeholder: SearchHelpers::INPUT_PLACEHOLDER)
+ end
+end
+
+RSpec.shared_examples 'can search settings' do |search_term, non_match_section|
+ it 'has search settings field' do
+ expect(page).to have_field(placeholder: SearchHelpers::INPUT_PLACEHOLDER)
+ end
+
+ it 'hides unmatching sections on search' do
+ expect(page).to have_content(non_match_section)
+
+ fill_in SearchHelpers::INPUT_PLACEHOLDER, with: search_term
+
+ expect(page).to have_content(search_term)
+ expect(page).not_to have_content(non_match_section)
+ end
+end
+
+RSpec.shared_examples 'can search settings with feature flag check' do |search_term, non_match_section|
+ let(:flag) { true }
+
+ before do
+ stub_feature_flags(search_settings_in_page: flag)
+
+ visit(visit_path)
+ end
+
+ context 'with feature flag on' do
+ it_behaves_like 'can search settings', search_term, non_match_section
+ end
+
+ context 'with feature flag off' do
+ let(:flag) { false }
+
+ it_behaves_like 'cannot search settings'
+ end
+end
diff --git a/spec/support/shared_examples/finders/packages_shared_examples.rb b/spec/support/shared_examples/finders/packages_shared_examples.rb
index 52976565b21..2d4e8d0df1f 100644
--- a/spec/support/shared_examples/finders/packages_shared_examples.rb
+++ b/spec/support/shared_examples/finders/packages_shared_examples.rb
@@ -17,3 +17,23 @@ RSpec.shared_examples 'concerning versionless param' do
it { is_expected.not_to include(versionless_package) }
end
end
+
+RSpec.shared_examples 'concerning package statuses' do
+ let_it_be(:hidden_package) { create(:maven_package, :hidden, project: project) }
+
+ context 'hidden packages' do
+ it { is_expected.not_to include(hidden_package) }
+ end
+
+ context 'with status param' do
+ let(:params) { { status: :hidden } }
+
+ it { is_expected.to match_array([hidden_package]) }
+ end
+
+ context 'with invalid status param' do
+ let(:params) { { status: 'invalid_status' } }
+
+ it { expect { subject }.to raise_exception(described_class::InvalidStatusError) }
+ end
+end
diff --git a/spec/support/shared_examples/graphql/label_fields.rb b/spec/support/shared_examples/graphql/label_fields.rb
index caf5dae409a..4159e4e03ab 100644
--- a/spec/support/shared_examples/graphql/label_fields.rb
+++ b/spec/support/shared_examples/graphql/label_fields.rb
@@ -18,7 +18,7 @@ RSpec.shared_examples 'a GraphQL type with labels' do
subject { described_class.fields['labels'] }
it { is_expected.to have_graphql_type(Types::LabelType.connection_type) }
- it { is_expected.to have_graphql_arguments(:search_term) }
+ it { is_expected.to have_graphql_arguments(labels_resolver_arguments) }
end
end
@@ -105,7 +105,7 @@ RSpec.shared_examples 'querying a GraphQL type with labels' do
run_query(query_for(label_a))
end
- it 'batches queries for labels by title' do
+ it 'batches queries for labels by title', :request_store do
multi_selection = query_for(label_b, label_c)
single_selection = query_for(label_d)
diff --git a/spec/support/shared_examples/graphql/mutations/boards_list_create_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/boards_list_create_shared_examples.rb
new file mode 100644
index 00000000000..b096a5e17c0
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/boards_list_create_shared_examples.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'board lists create mutation' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+ let(:list_create_params) { {} }
+
+ subject { mutation.resolve(board_id: board.to_global_id.to_s, **list_create_params) }
+
+ describe '#ready?' do
+ it 'raises an error if required arguments are missing' do
+ expect { mutation.ready?(board_id: 'some id') }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/)
+ end
+
+ it 'raises an error if too many required arguments are specified' do
+ expect { mutation.ready?(board_id: 'some id', backlog: true, label_id: 'some label') }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/)
+ end
+ end
+
+ describe '#resolve' do
+ context 'with proper permissions' do
+ before_all do
+ group.add_reporter(user)
+ end
+
+ describe 'backlog list' do
+ let(:list_create_params) { { backlog: true } }
+
+ it 'creates one and only one backlog' do
+ expect { subject }.to change { board.lists.backlog.count }.by(1)
+ expect(board.lists.backlog.first.list_type).to eq 'backlog'
+
+ backlog_id = board.lists.backlog.first.id
+
+ expect { subject }.not_to change { board.lists.backlog.count }
+ expect(board.lists.backlog.last.id).to eq backlog_id
+ end
+ end
+
+ describe 'label list' do
+ let_it_be(:dev_label) do
+ create(:group_label, title: 'Development', color: '#FFAABB', group: group)
+ end
+
+ let(:list_create_params) { { label_id: dev_label.to_global_id.to_s } }
+
+ it 'creates a new label board list' do
+ expect { subject }.to change { board.lists.count }.by(1)
+
+ new_list = subject[:list]
+
+ expect(new_list.title).to eq dev_label.title
+ expect(new_list.position).to eq 0
+ end
+
+ context 'when label not found' do
+ let(:list_create_params) { { label_id: "gid://gitlab/Label/#{non_existing_record_id}" } }
+
+ it 'returns an error' do
+ expect(subject[:errors]).to include 'Label not found'
+ end
+ end
+ end
+ end
+
+ context 'without proper permissions' do
+ before_all do
+ group.add_guest(user)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ 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
new file mode 100644
index 00000000000..d294f034d2e
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'a mutation which can mutate a spammable' do
+ describe "#additional_spam_params" do
+ it 'passes additional spam params to the service' do
+ args = [
+ anything,
+ anything,
+ hash_including(
+ api: true,
+ request: instance_of(ActionDispatch::Request),
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ )
+ ]
+ expect(service).to receive(:new).with(*args).and_call_original
+
+ subject
+ end
+ end
+
+ describe "#with_spam_action_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 #with_spam_action_fields was invoked and that the fields are present in the
+ # response. The specific behavior of #with_spam_action_fields is covered in the
+ # CanMutateSpammable unit tests.
+ expect(mutation_response.keys)
+ .to include('spam', 'spamLogId', 'needsCaptchaResponse', 'captchaSiteKey')
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb
index 0338eb43f8d..4468af1a603 100644
--- a/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/http_integrations_shared_examples.rb
@@ -17,3 +17,78 @@ RSpec.shared_examples 'creating a new HTTP integration' do
expect(integration_response['apiUrl']).to eq(nil)
end
end
+
+RSpec.shared_examples 'updating an existing HTTP integration' do
+ it 'updates the integration' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ integration_response = mutation_response['integration']
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(integration_response['id']).to eq(GitlabSchema.id_from_object(integration).to_s)
+ expect(integration_response['name']).to eq('Modified Name')
+ expect(integration_response['active']).to be_falsey
+ expect(integration_response['url']).to include('modified-name')
+ end
+end
+
+RSpec.shared_examples 'validating the payload_example' do
+ context 'with invalid payloadExample attribute' do
+ let(:payload_example) { 'not a JSON' }
+
+ it 'responds with errors' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect_graphql_errors_to_include(/was provided invalid value for payloadExample \(Invalid JSON string/)
+ end
+ end
+
+ it 'validates the payload_example size' do
+ allow(::Gitlab::Utils::DeepSize)
+ .to receive(:new)
+ .with(Gitlab::Json.parse(payload_example))
+ .and_return(double(valid?: false))
+
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect_graphql_errors_to_include(/payloadExample JSON is too big/)
+ end
+end
+
+RSpec.shared_examples 'validating the payload_attribute_mappings' do
+ context 'with invalid payloadAttributeMapping attribute does not contain fieldName' do
+ let(:payload_attribute_mappings) do
+ [{ path: %w[alert name], type: 'STRING' }]
+ end
+
+ it 'responds with errors' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect_graphql_errors_to_include(/was provided invalid value for payloadAttributeMappings\.0\.fieldName \(Expected value to not be null/)
+ end
+ end
+
+ context 'with invalid payloadAttributeMapping attribute does not contain path' do
+ let(:payload_attribute_mappings) do
+ [{ fieldName: 'TITLE', type: 'STRING' }]
+ end
+
+ it 'responds with errors' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect_graphql_errors_to_include(/was provided invalid value for payloadAttributeMappings\.0\.path \(Expected value to not be null/)
+ end
+ end
+
+ context 'with invalid payloadAttributeMapping attribute does not contain type' do
+ let(:payload_attribute_mappings) do
+ [{ fieldName: 'TITLE', path: %w[alert name] }]
+ end
+
+ it 'responds with errors' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect_graphql_errors_to_include(/was provided invalid value for payloadAttributeMappings\.0\.type \(Expected value to not be null/)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/mutations/spammable_mutation_fields_examples.rb b/spec/support/shared_examples/graphql/mutations/spammable_mutation_fields_examples.rb
deleted file mode 100644
index 8678b23ad31..00000000000
--- a/spec/support/shared_examples/graphql/mutations/spammable_mutation_fields_examples.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.shared_examples 'spam flag is present' do
- specify :aggregate_failures do
- subject
-
- expect(mutation_response).to have_key('spam')
- expect(mutation_response['spam']).to be_falsey
- end
-end
-
-RSpec.shared_examples 'can raise spam flag' do
- it 'spam parameters are passed to the service' do
- args = [anything, anything, hash_including(api: true, request: instance_of(ActionDispatch::Request))]
- expect(service).to receive(:new).with(*args).and_call_original
-
- subject
- end
-
- context 'when the snippet is detected as spam' do
- it 'raises spam flag' do
- allow_next_instance_of(service) do |instance|
- allow(instance).to receive(:spam_check) do |snippet, user, _|
- snippet.spam!
- end
- end
-
- subject
-
- expect(mutation_response['spam']).to be true
- expect(mutation_response['errors']).to include("Your snippet has been recognized as spam and has been discarded.")
- end
- end
-
- context 'when :snippet_spam flag is disabled' do
- before do
- stub_feature_flags(snippet_spam: false)
- end
-
- it 'request parameter is not passed to the service' do
- expect(service).to receive(:new)
- .with(anything, anything, hash_not_including(request: instance_of(ActionDispatch::Request)))
- .and_call_original
-
- subject
- end
- end
-end
diff --git a/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb b/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
index 24c8a247c93..fb598b978f6 100644
--- a/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
@@ -64,3 +64,22 @@ RSpec.shared_examples 'a Note mutation when the given resource id is not for a N
let(:match_errors) { include(/does not represent an instance of Note/) }
end
end
+
+RSpec.shared_examples 'a Note mutation when there are rate limit validation errors' do
+ before do
+ stub_application_setting(notes_create_limit: 3)
+ 3.times { post_graphql_mutation(mutation, current_user: current_user) }
+ end
+
+ it_behaves_like 'a Note mutation that does not create a Note'
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: ['This endpoint has been requested too many times. Try again later.']
+
+ context 'when the user is in the allowlist' do
+ before do
+ stub_application_setting(notes_create_limit_allowlist: ["#{current_user.username}"])
+ end
+
+ it_behaves_like 'a Note mutation that creates a Note'
+ end
+end
diff --git a/spec/support/shared_examples/helpers/issuable_description_templates_shared_examples.rb b/spec/support/shared_examples/helpers/issuable_description_templates_shared_examples.rb
new file mode 100644
index 00000000000..9e8c96d576a
--- /dev/null
+++ b/spec/support/shared_examples/helpers/issuable_description_templates_shared_examples.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'project issuable templates context' do
+ let_it_be(:issuable_template_files) do
+ {
+ '.gitlab/issue_templates/issue-bar.md' => 'Issue Template Bar',
+ '.gitlab/issue_templates/issue-foo.md' => 'Issue Template Foo',
+ '.gitlab/issue_templates/issue-bad.txt' => 'Issue Template Bad',
+ '.gitlab/issue_templates/issue-baz.xyz' => 'Issue Template Baz',
+
+ '.gitlab/merge_request_templates/merge_request-bar.md' => 'Merge Request Template Bar',
+ '.gitlab/merge_request_templates/merge_request-foo.md' => 'Merge Request Template Foo',
+ '.gitlab/merge_request_templates/merge_request-bad.txt' => 'Merge Request Template Bad',
+ '.gitlab/merge_request_templates/merge_request-baz.xyz' => 'Merge Request Template Baz'
+ }
+ end
+end
+
+RSpec.shared_examples 'project issuable templates' do
+ context 'issuable templates' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it 'returns only md files as issue templates' do
+ expect(helper.issuable_templates(project, 'issue')).to eq(templates('issue', project))
+ end
+
+ it 'returns only md files as merge_request templates' do
+ expect(helper.issuable_templates(project, 'merge_request')).to eq(templates('merge_request', project))
+ end
+ end
+
+ def expected_templates(issuable_type)
+ expectation = {}
+
+ expectation["Project Templates"] = templates(issuable_type, project)
+ expectation["Group #{inherited_from.namespace.full_name}"] = templates(issuable_type, inherited_from) if inherited_from.present?
+
+ expectation
+ end
+
+ def templates(issuable_type, inherited_from)
+ [
+ { id: "#{issuable_type}-bar", key: "#{issuable_type}-bar", name: "#{issuable_type}-bar", project_id: inherited_from&.id },
+ { id: "#{issuable_type}-foo", key: "#{issuable_type}-foo", name: "#{issuable_type}-foo", project_id: inherited_from&.id }
+ ]
+ end
+end
diff --git a/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb b/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb
new file mode 100644
index 00000000000..dfa1388e0bb
--- /dev/null
+++ b/spec/support/shared_examples/lib/api/internal_base_shared_examples.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'actor key validations' do
+ context 'key id is not provided' do
+ let(:key_id) { nil }
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find a user without a key')
+ end
+ end
+
+ context 'key does not exist' do
+ let(:key_id) { non_existing_record_id }
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find the given key')
+ end
+ end
+
+ context 'key without user' do
+ let(:key_id) { create(:key, user: nil).id }
+
+ it 'returns an error message' do
+ subject
+
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find a user for the given key')
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb
index 07d01d5c50e..eafb49cef71 100644
--- a/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/search_results_sorted_shared_examples.rb
@@ -1,19 +1,35 @@
# frozen_string_literal: true
RSpec.shared_examples 'search results sorted' do
- context 'sort: newest' do
+ context 'sort: created_desc' do
let(:sort) { 'created_desc' }
it 'sorts results by created_at' do
- expect(results.objects(scope).map(&:id)).to eq([new_result.id, old_result.id, very_old_result.id])
+ expect(results_created.objects(scope).map(&:id)).to eq([new_result.id, old_result.id, very_old_result.id])
end
end
- context 'sort: oldest' do
+ context 'sort: created_asc' do
let(:sort) { 'created_asc' }
it 'sorts results by created_at' do
- expect(results.objects(scope).map(&:id)).to eq([very_old_result.id, old_result.id, new_result.id])
+ expect(results_created.objects(scope).map(&:id)).to eq([very_old_result.id, old_result.id, new_result.id])
+ end
+ end
+
+ context 'sort: updated_desc' do
+ let(:sort) { 'updated_desc' }
+
+ it 'sorts results by updated_desc' do
+ expect(results_updated.objects(scope).map(&:id)).to eq([new_updated.id, old_updated.id, very_old_updated.id])
+ end
+ end
+
+ context 'sort: updated_asc' do
+ let(:sort) { 'updated_asc' }
+
+ it 'sorts results by updated_asc' do
+ expect(results_updated.objects(scope).map(&:id)).to eq([very_old_updated.id, old_updated.id, new_updated.id])
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb
index 286305f2506..edd9b6cdf37 100644
--- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issue_activity_shared_examples.rb
@@ -24,12 +24,4 @@ RSpec.shared_examples 'a tracked issue edit event' do |event|
it 'does not track edit actions if author is not present' do
expect(track_action(author: nil)).to be_nil
end
-
- context 'when feature flag track_issue_activity_actions is disabled' do
- it 'does not track edit actions' do
- stub_feature_flags(track_issue_activity_actions: false)
-
- expect(track_action(author: user1)).to be_nil
- end
- end
end
diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
index fe99b1cacd9..42f82987989 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
@@ -9,19 +9,30 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
end
describe 'Validation' do
- before do
- allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
-
- instance.valid?
- end
-
context 'when presence validation is required' do
before do
skip unless validate_presence
end
- it 'validates presence' do
- expect(instance.errors[internal_id_attribute]).to include("can't be blank")
+ context 'when creating an object' do
+ before do
+ allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+ end
+
+ it 'raises an error if the internal id is blank' do
+ expect { instance.save! }.to raise_error(AtomicInternalId::MissingValueError)
+ end
+ end
+
+ context 'when updating an object' do
+ it 'raises an error if the internal id is blank' do
+ instance.save!
+
+ write_internal_id(nil)
+ allow(instance).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+
+ expect { instance.save! }.to raise_error(AtomicInternalId::MissingValueError)
+ end
end
end
@@ -30,8 +41,27 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
skip if validate_presence
end
- it 'does not validate presence' do
- expect(instance.errors[internal_id_attribute]).to be_empty
+ context 'when creating an object' do
+ before do
+ allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+ end
+
+ it 'does not raise an error if the internal id is blank' do
+ expect(read_internal_id).to be_nil
+
+ expect { instance.save! }.not_to raise_error
+ end
+ end
+
+ context 'when updating an object' do
+ it 'does not raise an error if the internal id is blank' do
+ instance.save!
+
+ write_internal_id(nil)
+ allow(instance).to receive(:"ensure_#{scope}_#{internal_id_attribute}!")
+
+ expect { instance.save! }.not_to raise_error
+ end
end
end
end
@@ -76,6 +106,51 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
end
end
+ describe 'unsetting the instance internal id on rollback' do
+ context 'when the internal id has been changed' do
+ context 'when the internal id is automatically set' do
+ it 'clears it on the instance' do
+ expect_iid_to_be_set_and_rollback
+
+ expect(read_internal_id).to be_nil
+ end
+ end
+
+ context 'when the internal id is manually set' do
+ it 'does not clear it on the instance' do
+ write_internal_id(100)
+
+ expect_iid_to_be_set_and_rollback
+
+ expect(read_internal_id).not_to be_nil
+ end
+ end
+ end
+
+ context 'when the internal id has not been changed' do
+ it 'preserves the value on the instance' do
+ instance.save!
+ original_id = read_internal_id
+
+ expect(original_id).not_to be_nil
+
+ expect_iid_to_be_set_and_rollback
+
+ expect(read_internal_id).to eq(original_id)
+ end
+ end
+
+ def expect_iid_to_be_set_and_rollback
+ ActiveRecord::Base.transaction(requires_new: true) do
+ instance.save!
+
+ expect(read_internal_id).not_to be_nil
+
+ raise ActiveRecord::Rollback
+ end
+ end
+ end
+
describe 'supply of internal ids' do
let(:scope_value) { scope_attrs.each_value.first }
let(:method_name) { :"with_#{scope}_#{internal_id_attribute}_supply" }
diff --git a/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb
deleted file mode 100644
index 2f0b95427d2..00000000000
--- a/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'can housekeep repository' do
- context 'with a clean redis state', :clean_gitlab_redis_shared_state do
- describe '#pushes_since_gc' do
- context 'without any pushes' do
- it 'returns 0' do
- expect(resource.pushes_since_gc).to eq(0)
- end
- end
-
- context 'with a number of pushes' do
- it 'returns the number of pushes' do
- 3.times { resource.increment_pushes_since_gc }
-
- expect(resource.pushes_since_gc).to eq(3)
- end
- end
- end
-
- describe '#increment_pushes_since_gc' do
- it 'increments the number of pushes since the last GC' do
- 3.times { resource.increment_pushes_since_gc }
-
- expect(resource.pushes_since_gc).to eq(3)
- end
- end
-
- describe '#reset_pushes_since_gc' do
- it 'resets the number of pushes since the last GC' do
- 3.times { resource.increment_pushes_since_gc }
-
- resource.reset_pushes_since_gc
-
- expect(resource.pushes_since_gc).to eq(0)
- end
- end
-
- describe '#pushes_since_gc_redis_shared_state_key' do
- it 'returns the proper redis key format' do
- expect(resource.send(:pushes_since_gc_redis_shared_state_key)).to eq("#{resource_key}/#{resource.id}/pushes_since_gc")
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb b/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb
index 85a2c6f1449..8deeecea30d 100644
--- a/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb
@@ -2,11 +2,12 @@
RSpec.shared_examples 'can move repository storage' do
let(:container) { raise NotImplementedError }
+ let(:repository) { container.repository }
describe '#set_repository_read_only!' do
it 'makes the repository read-only' do
expect { container.set_repository_read_only! }
- .to change(container, :repository_read_only?)
+ .to change { container.repository_read_only? }
.from(false)
.to(true)
end
@@ -28,7 +29,7 @@ RSpec.shared_examples 'can move repository storage' do
allow(container).to receive(:git_transfer_in_progress?) { true }
expect { container.set_repository_read_only!(skip_git_transfer_check: true) }
- .to change(container, :repository_read_only?)
+ .to change { container.repository_read_only? }
.from(false)
.to(true)
end
@@ -38,16 +39,16 @@ RSpec.shared_examples 'can move repository storage' do
describe '#set_repository_writable!' do
it 'sets repository_read_only to false' do
expect { container.set_repository_writable! }
- .to change(container, :repository_read_only)
+ .to change { container.repository_read_only? }
.from(true).to(false)
end
end
describe '#reference_counter' do
it 'returns a Gitlab::ReferenceCounter object' do
- expect(Gitlab::ReferenceCounter).to receive(:new).with(container.repository.gl_repository).and_call_original
+ expect(Gitlab::ReferenceCounter).to receive(:new).with(repository.gl_repository).and_call_original
- result = container.reference_counter(type: container.repository.repo_type)
+ result = container.reference_counter(type: repository.repo_type)
expect(result).to be_a Gitlab::ReferenceCounter
end
diff --git a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
index 826ee453919..1be4d9b80a4 100644
--- a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
@@ -152,36 +152,4 @@ RSpec.shared_examples 'model with repository' do
it { is_expected.to respond_to(:disk_path) }
it { is_expected.to respond_to(:gitlab_shell) }
end
-
- describe '.pick_repository_storage' do
- subject { described_class.pick_repository_storage }
-
- before do
- storages = {
- 'default' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories'),
- 'picked' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories')
- }
- allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
- end
-
- it 'picks storage from ApplicationSetting' do
- expect(Gitlab::CurrentSettings).to receive(:pick_repository_storage).and_return('picked')
-
- expect(subject).to eq('picked')
- end
-
- it 'picks from the available storages based on weight', :request_store do
- stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
- Gitlab::CurrentSettings.expire_current_application_settings
- Gitlab::CurrentSettings.current_application_settings
-
- settings = ApplicationSetting.last
- settings.repository_storages_weighted = { 'picked' => 100, 'default' => 0 }
- settings.save!
-
- expect(Gitlab::CurrentSettings.repository_storages_weighted).to eq({ 'default' => 100 })
- expect(subject).to eq('picked')
- expect(Gitlab::CurrentSettings.repository_storages_weighted).to eq({ 'default' => 0, 'picked' => 100 })
- end
- end
end
diff --git a/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
index 2f0b95427d2..4006b8226ce 100644
--- a/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb
@@ -41,5 +41,11 @@ RSpec.shared_examples 'can housekeep repository' do
expect(resource.send(:pushes_since_gc_redis_shared_state_key)).to eq("#{resource_key}/#{resource.id}/pushes_since_gc")
end
end
+
+ describe '#git_garbage_collect_worker_klass' do
+ it 'defines a git gargabe collect worker' do
+ expect(resource.git_garbage_collect_worker_klass).to eq(expected_worker_class)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
index 4c617f3ba46..819cf6018fe 100644
--- a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb
@@ -33,7 +33,7 @@ RSpec.shared_examples 'handles repository moves' do
subject { build(repository_storage_factory_key, container: container) }
it "does not allow the container to be read-only on create" do
- container.update!(repository_read_only: true)
+ container.set_repository_read_only!
expect(subject).not_to be_valid
expect(subject.errors[error_key].first).to match(/is read only/)
@@ -45,8 +45,8 @@ RSpec.shared_examples 'handles repository moves' do
context 'destination_storage_name' do
subject { build(repository_storage_factory_key) }
- it 'picks storage from ApplicationSetting' do
- expect(Gitlab::CurrentSettings).to receive(:pick_repository_storage).and_return('picked').at_least(:once)
+ it 'can pick new storage' do
+ expect(Repository).to receive(:pick_storage_shard).and_return('picked').at_least(:once)
expect(subject.destination_storage_name).to eq('picked')
end
@@ -99,6 +99,11 @@ RSpec.shared_examples 'handles repository moves' do
expect(container).not_to be_repository_read_only
end
+
+ it 'updates the updated_at column of the container', :aggregate_failures do
+ expect { storage_move.finish_replication! }.to change { container.updated_at }
+ expect(storage_move.container.updated_at).to be >= storage_move.updated_at
+ end
end
context 'and transits to failed' do
diff --git a/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
index 38983f752f4..b73ff516670 100644
--- a/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb
@@ -11,6 +11,7 @@ RSpec.shared_examples 'Debian Distribution Architecture' do |factory, container,
describe 'relationships' do
it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:architectures) }
+ it { is_expected.to have_many(:files).class_name("Packages::Debian::#{container.capitalize}ComponentFile").inverse_of(:architecture) }
end
describe 'validations' do
diff --git a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
new file mode 100644
index 00000000000..02ced49ee94
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
@@ -0,0 +1,245 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
+ let_it_be(:container1, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
+ let_it_be(:container2, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang
+ let_it_be(:distribution1, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container1) }
+ let_it_be(:distribution2, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container2) }
+ let_it_be(:architecture1_1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution1) }
+ let_it_be(:architecture1_2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution1) }
+ let_it_be(:architecture2_1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution2) }
+ let_it_be(:architecture2_2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution2) }
+ let_it_be(:component1_1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution1) }
+ let_it_be(:component1_2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution1) }
+ let_it_be(:component2_1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution2) }
+ let_it_be(:component2_2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution2) }
+
+ let_it_be_with_refind(:component_file_with_architecture) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1) }
+ let_it_be(:component_file_other_architecture, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_2) }
+ let_it_be(:component_file_other_component, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_2, architecture: architecture1_1) }
+ let_it_be(:component_file_other_compression_type, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, compression_type: :xz) }
+ let_it_be(:component_file_other_file_md5, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_md5: 'other_md5') }
+ let_it_be(:component_file_other_file_sha256, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_sha256: 'other_sha256') }
+ let_it_be(:component_file_other_container, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component2_1, architecture: architecture2_1) }
+ let_it_be_with_refind(:component_file_with_file_type_source) { create("debian_#{container_type}_component_file", :source, component: component1_1) }
+ let_it_be(:component_file_with_file_type_di_packages, freeze: can_freeze) { create("debian_#{container_type}_component_file", :di_packages, component: component1_1, architecture: architecture1_1) }
+
+ subject { component_file_with_architecture }
+
+ describe 'relationships' do
+ context 'with stubbed uploader' do
+ before do
+ allow_next_instance_of(Packages::Debian::ComponentFileUploader) do |uploader|
+ allow(uploader).to receive(:dynamic_segment).and_return('stubbed')
+ end
+ end
+
+ it { is_expected.to belong_to(:component).class_name("Packages::Debian::#{container_type.capitalize}Component").inverse_of(:files) }
+ end
+
+ context 'with packages file_type' do
+ it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files) }
+ end
+
+ context 'with :source file_type' do
+ subject { component_file_with_file_type_source }
+
+ it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files).optional }
+ end
+ end
+
+ describe 'validations' do
+ describe "#component" do
+ before do
+ allow_next_instance_of(Packages::Debian::ComponentFileUploader) do |uploader|
+ allow(uploader).to receive(:dynamic_segment).and_return('stubbed')
+ end
+ end
+
+ it { is_expected.to validate_presence_of(:component) }
+ end
+
+ describe "#architecture" do
+ context 'with packages file_type' do
+ it { is_expected.to validate_presence_of(:architecture) }
+ end
+
+ context 'with :source file_type' do
+ subject { component_file_with_file_type_source }
+
+ it { is_expected.to validate_absence_of(:architecture) }
+ end
+ end
+
+ describe '#file_type' do
+ it { is_expected.to validate_presence_of(:file_type) }
+
+ it { is_expected.to allow_value(:packages).for(:file_type) }
+ end
+
+ describe '#compression_type' do
+ it { is_expected.not_to validate_presence_of(:compression_type) }
+
+ it { is_expected.to allow_value(nil).for(:compression_type) }
+ it { is_expected.to allow_value(:gz).for(:compression_type) }
+ end
+
+ describe '#file' do
+ subject { component_file_with_architecture.file }
+
+ context 'the uploader api' do
+ it { is_expected.to respond_to(:store_dir) }
+ it { is_expected.to respond_to(:cache_dir) }
+ it { is_expected.to respond_to(:work_dir) }
+ end
+ end
+
+ describe '#file_store' do
+ it { is_expected.to validate_presence_of(:file_store) }
+ end
+
+ describe '#file_md5' do
+ it { is_expected.to validate_presence_of(:file_md5) }
+ end
+
+ describe '#file_sha256' do
+ it { is_expected.to validate_presence_of(:file_sha256) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.with_container' do
+ subject { described_class.with_container(container2) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_container)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_codename_or_suite' do
+ subject { described_class.with_codename_or_suite(distribution2.codename) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_container)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_component_name' do
+ subject { described_class.with_component_name(component1_2.name) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_component)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_file_type' do
+ subject { described_class.with_file_type(:source) }
+
+ it do
+ # let_it_be_with_refind triggers a query
+ component_file_with_file_type_source
+
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_with_file_type_source)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_architecture_name' do
+ subject { described_class.with_architecture_name(architecture1_2.name) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_architecture)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_compression_type' do
+ subject { described_class.with_compression_type(:xz) }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_compression_type)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+
+ describe '.with_file_sha256' do
+ subject { described_class.with_file_sha256('other_sha256') }
+
+ it do
+ queries = ActiveRecord::QueryRecorder.new do
+ expect(subject.to_a).to contain_exactly(component_file_other_file_sha256)
+ end
+
+ expect(queries.count).to eq(1)
+ end
+ end
+ end
+
+ describe 'callbacks' do
+ let(:component_file) { build("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, size: nil) }
+
+ subject { component_file.save! }
+
+ it 'updates metadata columns' do
+ expect(component_file)
+ .to receive(:update_file_store)
+ .and_call_original
+
+ expect(component_file)
+ .to receive(:update_column)
+ .with(:file_store, ::Packages::PackageFileUploader::Store::LOCAL)
+ .and_call_original
+
+ expect { subject }.to change { component_file.size }.from(nil).to(74)
+ end
+ end
+
+ describe '#relative_path' do
+ context 'with a Packages file_type' do
+ subject { component_file_with_architecture.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/binary-#{architecture1_1.name}/Packages") }
+ end
+
+ context 'with a Source file_type' do
+ subject { component_file_with_file_type_source.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/source/Source") }
+ end
+
+ context 'with a DI Packages file_type' do
+ subject { component_file_with_file_type_di_packages.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/debian-installer/binary-#{architecture1_1.name}/Packages") }
+ end
+
+ context 'with an xz compression_type' do
+ subject { component_file_other_compression_type.relative_path }
+
+ it { is_expected.to eq("#{component1_1.name}/binary-#{architecture1_1.name}/Packages.xz") }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb
new file mode 100644
index 00000000000..bf6fc23116c
--- /dev/null
+++ b/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'Debian Distribution Component' do |factory, container, can_freeze|
+ let_it_be_with_refind(:component) { create(factory) } # rubocop:disable Rails/SaveBang
+ let_it_be(:component_same_distribution, freeze: can_freeze) { create(factory, distribution: component.distribution) }
+ let_it_be(:component_same_name, freeze: can_freeze) { create(factory, name: component.name) }
+
+ subject { component }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:components) }
+ it { is_expected.to have_many(:files).class_name("Packages::Debian::#{container.capitalize}ComponentFile").inverse_of(:component) }
+ end
+
+ describe 'validations' do
+ describe "#distribution" do
+ it { is_expected.to validate_presence_of(:distribution) }
+ end
+
+ describe '#name' do
+ it { is_expected.to validate_presence_of(:name) }
+
+ it { is_expected.to allow_value('main').for(:name) }
+ it { is_expected.to allow_value('non-free').for(:name) }
+ it { is_expected.to allow_value('a' * 255).for(:name) }
+ it { is_expected.not_to allow_value('a' * 256).for(:name) }
+ it { is_expected.not_to allow_value('non/free').for(:name) }
+ it { is_expected.not_to allow_value('hé').for(:name) }
+ end
+ end
+
+ describe 'scopes' do
+ describe '.with_distribution' do
+ subject { described_class.with_distribution(component.distribution) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([component, component_same_distribution])
+ end
+ end
+
+ describe '.with_name' do
+ subject { described_class.with_name(component.name) }
+
+ it 'does not return other distributions' do
+ expect(subject.to_a).to eq([component, component_same_name])
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
index af87d30099f..b4ec146df14 100644
--- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -17,7 +17,13 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
it { is_expected.to belong_to(container) }
it { is_expected.to belong_to(:creator).class_name('User') }
+ it { is_expected.to have_many(:components).class_name("Packages::Debian::#{container.capitalize}Component").inverse_of(:distribution) }
it { is_expected.to have_many(:architectures).class_name("Packages::Debian::#{container.capitalize}Architecture").inverse_of(:distribution) }
+
+ if container != :group
+ it { is_expected.to have_many(:publications).class_name('Packages::Debian::Publication').inverse_of(:distribution).with_foreign_key(:distribution_id) }
+ it { is_expected.to have_many(:packages).class_name('Packages::Package').through(:publications) }
+ end
end
describe 'validations' do
diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb
index 62da9e15259..89d30688b5c 100644
--- a/spec/support/shared_examples/models/wiki_shared_examples.rb
+++ b/spec/support/shared_examples/models/wiki_shared_examples.rb
@@ -154,6 +154,15 @@ RSpec.shared_examples 'wiki model' do
it 'returns true' do
expect(subject.empty?).to be(true)
end
+
+ context 'when the repository does not exist' do
+ let(:wiki_container) { wiki_container_without_repo }
+
+ it 'returns true and does not create the repo' do
+ expect(subject.empty?).to be(true)
+ expect(wiki.repository_exists?).to be false
+ end
+ end
end
context 'when the wiki has pages' do
diff --git a/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb b/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb
new file mode 100644
index 00000000000..e86f1e77447
--- /dev/null
+++ b/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'model with Debian distributions' do
+ let(:container_type) { subject.class.name.downcase }
+ let!(:distributions) { create_list("debian_#{container_type}_distribution", 2, :with_file, container: subject) }
+ let!(:components) { create_list("debian_#{container_type}_component", 5, distribution: distributions[0]) }
+ let!(:component_files) { create_list("debian_#{container_type}_component_file", 3, component: components[0]) }
+
+ it 'removes distribution files on removal' do
+ distribution_file_paths = distributions.map do |distribution|
+ [distribution.file.path] +
+ distribution.component_files.map do |component_file|
+ component_file.file.path
+ end
+ end.flatten
+
+ expect { subject.destroy! }
+ .to change {
+ distribution_file_paths.select do |path|
+ File.exist? path
+ end.length
+ }.from(distribution_file_paths.length).to(0)
+ end
+end
diff --git a/spec/support/shared_examples/namespaces/recursive_traversal_examples.rb b/spec/support/shared_examples/namespaces/recursive_traversal_examples.rb
new file mode 100644
index 00000000000..2c94be61bc1
--- /dev/null
+++ b/spec/support/shared_examples/namespaces/recursive_traversal_examples.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'recursive namespace traversal' do
+ describe '#self_and_hierarchy' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+ let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
+
+ it 'returns the correct tree' do
+ expect(group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ expect(nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ expect(very_deep_nested_group.self_and_hierarchy).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ end
+ end
+
+ describe '#ancestors' do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:deep_nested_group) { create(:group, parent: nested_group) }
+ let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+
+ it 'returns the correct ancestors' do
+ expect(very_deep_nested_group.ancestors).to include(group, nested_group, deep_nested_group)
+ expect(deep_nested_group.ancestors).to include(group, nested_group)
+ expect(nested_group.ancestors).to include(group)
+ expect(group.ancestors).to eq([])
+ end
+ end
+
+ describe '#self_and_ancestors' do
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+ let(:deep_nested_group) { create(:group, parent: nested_group) }
+ let(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+
+ it 'returns the correct ancestors' do
+ expect(very_deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ expect(deep_nested_group.self_and_ancestors).to contain_exactly(group, nested_group, deep_nested_group)
+ expect(nested_group.self_and_ancestors).to contain_exactly(group, nested_group)
+ expect(group.self_and_ancestors).to contain_exactly(group)
+ end
+ end
+
+ describe '#descendants' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+ let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
+
+ it 'returns the correct descendants' do
+ expect(very_deep_nested_group.descendants.to_a).to eq([])
+ expect(deep_nested_group.descendants.to_a).to include(very_deep_nested_group)
+ expect(nested_group.descendants.to_a).to include(deep_nested_group, very_deep_nested_group)
+ expect(group.descendants.to_a).to include(nested_group, deep_nested_group, very_deep_nested_group)
+ end
+ end
+
+ describe '#self_and_descendants' do
+ let!(:group) { create(:group, path: 'git_lab') }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:deep_nested_group) { create(:group, parent: nested_group) }
+ let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
+ let!(:another_group) { create(:group, path: 'gitllab') }
+ let!(:another_group_nested) { create(:group, path: 'foo', parent: another_group) }
+
+ it 'returns the correct descendants' do
+ expect(very_deep_nested_group.self_and_descendants).to contain_exactly(very_deep_nested_group)
+ expect(deep_nested_group.self_and_descendants).to contain_exactly(deep_nested_group, very_deep_nested_group)
+ expect(nested_group.self_and_descendants).to contain_exactly(nested_group, deep_nested_group, very_deep_nested_group)
+ expect(group.self_and_descendants).to contain_exactly(group, nested_group, deep_nested_group, very_deep_nested_group)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
index e2582f20ece..4fde68efd60 100644
--- a/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issuable/close_quick_action_shared_examples.rb
@@ -44,7 +44,6 @@ RSpec.shared_examples 'close quick action' do |issuable_type|
it 'creates the note and interprets the close quick action accordingly' do
add_note("this is done, close\n\n/close")
- wait_for_requests
expect(page).not_to have_content '/close'
expect(page).to have_content 'this is done, close'
diff --git a/spec/support/shared_examples/quick_actions/issue/clone_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/clone_quick_action_shared_examples.rb
index a99304f7214..ab04692616a 100644
--- a/spec/support/shared_examples/quick_actions/issue/clone_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issue/clone_quick_action_shared_examples.rb
@@ -54,8 +54,6 @@ RSpec.shared_examples 'clone quick action' do
# Note that this is missing one `-`
add_note("/clone -with_notes #{target_project.full_path}")
- wait_for_requests
-
expect(page).to have_content 'Failed to clone this issue: wrong parameters.'
expect(issue.reload).to be_open
end
@@ -68,8 +66,6 @@ RSpec.shared_examples 'clone quick action' do
it 'does not clone the issue' do
add_note("/clone #{project_unauthorized.full_path}")
- wait_for_requests
-
expect(page).to have_content "Cloned this issue to #{project_unauthorized.full_path}."
expect(issue.reload).to be_open
@@ -83,8 +79,6 @@ RSpec.shared_examples 'clone quick action' do
it 'does not clone the issue' do
add_note("/clone not/valid")
- wait_for_requests
-
expect(page).to have_content "Failed to clone this issue because target project doesn't exist."
expect(issue.reload).to be_open
end
@@ -154,7 +148,6 @@ RSpec.shared_examples 'clone quick action' do
expect(issue.reload).not_to be_closed
edit_note("/cloe #{target_project.full_path}", "test note.\n/clone #{target_project.full_path}")
- wait_for_all_requests
expect(page).to have_content 'test note.'
expect(issue.reload).to be_open
@@ -172,7 +165,6 @@ RSpec.shared_examples 'clone quick action' do
expect(page).not_to have_content 'Commands applied'
edit_note("/cloe #{target_project.full_path}", "/clone #{target_project.full_path}")
- wait_for_all_requests
expect(page).not_to have_content "/clone #{target_project.full_path}"
expect(issue.reload).to be_open
diff --git a/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb
index 910805dbdea..9dc39c6cf73 100644
--- a/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issue/create_merge_request_quick_action_shared_examples.rb
@@ -22,8 +22,6 @@ RSpec.shared_examples 'create_merge_request quick action' do
branch_name = 'invalid branch name'
add_note("/create_merge_request #{branch_name}")
- wait_for_requests
-
expect_mr_quickaction(false, branch_name)
end
@@ -31,16 +29,12 @@ RSpec.shared_examples 'create_merge_request quick action' do
branch_name = 'feature'
add_note("/create_merge_request #{branch_name}")
- wait_for_requests
-
expect_mr_quickaction(false, branch_name)
end
it 'creates a new merge request using issue iid and title as branch name when the branch name is empty' do
add_note("/create_merge_request")
- wait_for_requests
-
expect_mr_quickaction(true)
created_mr = project.merge_requests.last
diff --git a/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
index 32c46753006..5892fc32e94 100644
--- a/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
@@ -27,8 +27,6 @@ RSpec.shared_examples 'move quick action' do
it 'does not move the issue' do
add_note("/move #{project_unauthorized.full_path}")
- wait_for_requests
-
expect(page).to have_content "Moved this issue to #{project_unauthorized.full_path}."
expect(issue.reload).to be_open
end
@@ -38,8 +36,6 @@ RSpec.shared_examples 'move quick action' do
it 'does not move the issue' do
add_note("/move not/valid")
- wait_for_requests
-
expect(page).to have_content "Failed to move this issue because target project doesn't exist."
expect(issue.reload).to be_open
end
@@ -110,7 +106,6 @@ RSpec.shared_examples 'move quick action' do
expect(issue.reload).not_to be_closed
edit_note("/mvoe #{target_project.full_path}", "test note.\n/move #{target_project.full_path}")
- wait_for_all_requests
expect(page).to have_content 'test note.'
expect(issue.reload).to be_closed
@@ -129,7 +124,6 @@ RSpec.shared_examples 'move quick action' do
expect(issue.reload).not_to be_closed
edit_note("/mvoe #{target_project.full_path}", "/move #{target_project.full_path}")
- wait_for_all_requests
expect(page).not_to have_content "/move #{target_project.full_path}"
expect(issue.reload).to be_closed
diff --git a/spec/support/shared_examples/quick_actions/issue/zoom_quick_actions_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/zoom_quick_actions_shared_examples.rb
index 1ea249d5f9d..34937949174 100644
--- a/spec/support/shared_examples/quick_actions/issue/zoom_quick_actions_shared_examples.rb
+++ b/spec/support/shared_examples/quick_actions/issue/zoom_quick_actions_shared_examples.rb
@@ -10,8 +10,6 @@ RSpec.shared_examples 'zoom quick actions' do
it 'skips addition silently' do
add_note("/zoom #{zoom_link}")
- wait_for_requests
-
expect(page).not_to have_content('Zoom meeting added')
expect(page).not_to have_content('Failed to add a Zoom meeting')
expect(ZoomMeeting.canonical_meeting_url(issue.reload)).not_to eq(zoom_link)
@@ -22,8 +20,6 @@ RSpec.shared_examples 'zoom quick actions' do
it 'adds a Zoom link' do
add_note("/zoom #{zoom_link}")
- wait_for_requests
-
expect(page).to have_content('Zoom meeting added')
expect(ZoomMeeting.canonical_meeting_url(issue.reload)).to eq(zoom_link)
end
@@ -35,8 +31,6 @@ RSpec.shared_examples 'zoom quick actions' do
it 'cannot add invalid zoom link' do
add_note("/zoom #{invalid_zoom_link}")
- wait_for_requests
-
expect(page).to have_content('Failed to add a Zoom meeting')
expect(page).not_to have_content(zoom_link)
end
@@ -64,8 +58,6 @@ RSpec.shared_examples 'zoom quick actions' do
it 'skips removal silently' do
add_note('/remove_zoom')
- wait_for_requests
-
expect(page).not_to have_content('Zoom meeting removed')
expect(page).not_to have_content('Failed to remove a Zoom meeting')
expect(ZoomMeeting.canonical_meeting_url(issue.reload)).to be_nil
@@ -78,8 +70,6 @@ RSpec.shared_examples 'zoom quick actions' do
it 'removes last Zoom link' do
add_note('/remove_zoom')
- wait_for_requests
-
expect(page).to have_content('Zoom meeting removed')
expect(ZoomMeeting.canonical_meeting_url(issue.reload)).to be_nil
end
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index 83ba72c12aa..acaa0d8c2bc 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.shared_context 'Debian repository shared context' do |object_type|
+ include_context 'workhorse headers'
+
before do
stub_feature_flags(debian_packages: true)
end
@@ -37,16 +39,15 @@ RSpec.shared_context 'Debian repository shared context' do |object_type|
let(:params) { workhorse_params }
let(:auth_headers) { {} }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) do
+ let(:wh_headers) do
if method == :put
- { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token }
+ workhorse_headers
else
{}
end
end
- let(:headers) { auth_headers.merge(workhorse_headers) }
+ let(:headers) { auth_headers.merge(wh_headers) }
let(:send_rewritten_field) { true }
@@ -201,7 +202,7 @@ RSpec.shared_examples 'rejects Debian access with unknown project id' do
let(:project) { double(id: non_existing_record_id) }
context 'as anonymous' do
- it_behaves_like 'Debian project repository GET request', :anonymous, true, :not_found, nil
+ it_behaves_like 'Debian project repository GET request', :anonymous, true, :unauthorized, nil
end
context 'as authenticated user' do
@@ -228,13 +229,13 @@ RSpec.shared_examples 'Debian project repository GET endpoint' do |success_statu
'PUBLIC' | :anonymous | false | true | success_status | success_body
'PRIVATE' | :developer | true | true | success_status | success_body
'PRIVATE' | :guest | true | true | :forbidden | nil
- 'PRIVATE' | :developer | true | false | :not_found | nil
- 'PRIVATE' | :guest | true | false | :not_found | nil
+ 'PRIVATE' | :developer | true | false | :unauthorized | nil
+ 'PRIVATE' | :guest | true | false | :unauthorized | nil
'PRIVATE' | :developer | false | true | :not_found | nil
'PRIVATE' | :guest | false | true | :not_found | nil
- 'PRIVATE' | :developer | false | false | :not_found | nil
- 'PRIVATE' | :guest | false | false | :not_found | nil
- 'PRIVATE' | :anonymous | false | true | :not_found | nil
+ 'PRIVATE' | :developer | false | false | :unauthorized | nil
+ 'PRIVATE' | :guest | false | false | :unauthorized | nil
+ 'PRIVATE' | :anonymous | false | true | :unauthorized | nil
end
with_them do
@@ -263,13 +264,13 @@ RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_statu
'PUBLIC' | :anonymous | false | true | :unauthorized | nil
'PRIVATE' | :developer | true | true | success_status | nil
'PRIVATE' | :guest | true | true | :forbidden | nil
- 'PRIVATE' | :developer | true | false | :not_found | nil
- 'PRIVATE' | :guest | true | false | :not_found | nil
+ 'PRIVATE' | :developer | true | false | :unauthorized | nil
+ 'PRIVATE' | :guest | true | false | :unauthorized | nil
'PRIVATE' | :developer | false | true | :not_found | nil
'PRIVATE' | :guest | false | true | :not_found | nil
- 'PRIVATE' | :developer | false | false | :not_found | nil
- 'PRIVATE' | :guest | false | false | :not_found | nil
- 'PRIVATE' | :anonymous | false | true | :not_found | nil
+ 'PRIVATE' | :developer | false | false | :unauthorized | nil
+ 'PRIVATE' | :guest | false | false | :unauthorized | nil
+ 'PRIVATE' | :anonymous | false | true | :unauthorized | nil
end
with_them do
@@ -321,7 +322,7 @@ RSpec.shared_examples 'rejects Debian access with unknown group id' do
let(:group) { double(id: non_existing_record_id) }
context 'as anonymous' do
- it_behaves_like 'Debian group repository GET request', :anonymous, true, :not_found, nil
+ it_behaves_like 'Debian group repository GET request', :anonymous, true, :unauthorized, nil
end
context 'as authenticated user' do
@@ -348,13 +349,13 @@ RSpec.shared_examples 'Debian group repository GET endpoint' do |success_status,
'PUBLIC' | :anonymous | false | true | success_status | success_body
'PRIVATE' | :developer | true | true | success_status | success_body
'PRIVATE' | :guest | true | true | :forbidden | nil
- 'PRIVATE' | :developer | true | false | :not_found | nil
- 'PRIVATE' | :guest | true | false | :not_found | nil
+ 'PRIVATE' | :developer | true | false | :unauthorized | nil
+ 'PRIVATE' | :guest | true | false | :unauthorized | nil
'PRIVATE' | :developer | false | true | :not_found | nil
'PRIVATE' | :guest | false | true | :not_found | nil
- 'PRIVATE' | :developer | false | false | :not_found | nil
- 'PRIVATE' | :guest | false | false | :not_found | nil
- 'PRIVATE' | :anonymous | false | true | :not_found | nil
+ 'PRIVATE' | :developer | false | false | :unauthorized | nil
+ 'PRIVATE' | :guest | false | false | :unauthorized | nil
+ 'PRIVATE' | :anonymous | false | true | :unauthorized | nil
end
with_them do
diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/create_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/create_list_shared_examples.rb
new file mode 100644
index 00000000000..fe2cdbe3182
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/graphql/mutations/create_list_shared_examples.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'board lists create request' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:dev_label) do
+ create(:group_label, title: 'Development', color: '#FFAABB', group: group)
+ end
+
+ let(:mutation) { graphql_mutation(mutation_name, input) }
+ let(:mutation_response) { graphql_mutation_response(mutation_name) }
+
+ context 'the user is not allowed to read board lists' do
+ let(:input) { { board_id: board.to_global_id.to_s, backlog: true } }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to admin board lists' do
+ before do
+ group.add_reporter(current_user)
+ end
+
+ describe 'backlog list' do
+ let(:input) { { board_id: board.to_global_id.to_s, backlog: true } }
+
+ it 'creates the list' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['list'])
+ .to include('position' => nil, 'listType' => 'backlog')
+ end
+ end
+
+ describe 'label list' do
+ let(:input) { { board_id: board.to_global_id.to_s, label_id: dev_label.to_global_id.to_s } }
+
+ it 'creates the list' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['list'])
+ .to include('position' => 0, 'listType' => 'label', 'label' => include('title' => 'Development'))
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb
new file mode 100644
index 00000000000..9cf5bc04f65
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+# Requires `query(fields)`, `path_to_noteable`, `project`, and `noteable` bindings
+RSpec.shared_examples 'a noteable graphql type we can query' do
+ let(:note_factory) { :note }
+ let(:discussion_factory) { :discussion_note }
+
+ describe '.discussions' do
+ let(:fields) do
+ "discussions { nodes { #{all_graphql_fields_for('Discussion')} } }"
+ end
+
+ def expected
+ noteable.discussions.map do |discussion|
+ include(
+ 'id' => global_id_of(discussion),
+ 'replyId' => global_id_of(discussion, id: discussion.reply_id),
+ 'createdAt' => discussion.created_at.iso8601,
+ 'notes' => include(
+ 'nodes' => have_attributes(size: discussion.notes.size)
+ )
+ )
+ end
+ end
+
+ it 'can fetch discussions' do
+ create(discussion_factory, project: project, noteable: noteable)
+
+ post_graphql(query(fields), current_user: current_user)
+
+ expect(graphql_data_at(*path_to_noteable, :discussions, :nodes))
+ .to match_array(expected)
+ end
+ end
+
+ describe '.notes' do
+ let(:fields) do
+ "notes { nodes { #{all_graphql_fields_for('Note', max_depth: 2)} } }"
+ end
+
+ def expected
+ noteable.notes.map do |note|
+ include(
+ 'id' => global_id_of(note),
+ 'project' => include('id' => global_id_of(project)),
+ 'author' => include('id' => global_id_of(note.author)),
+ 'createdAt' => note.created_at.iso8601,
+ 'body' => eq(note.note)
+ )
+ end
+ end
+
+ it 'can fetch notes' do
+ create(note_factory, project: project, noteable: noteable)
+
+ post_graphql(query(fields), current_user: current_user)
+
+ expect(graphql_data_at(*path_to_noteable, :notes, :nodes))
+ .to match_array(expected)
+ 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 7066f803f9d..40799688144 100644
--- a/spec/support/shared_examples/requests/api/notes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
@@ -127,6 +127,12 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
end
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/notes" do
+ let(:params) { { body: 'hi!' } }
+
+ subject do
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params
+ end
+
it "creates a new note" do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: { body: 'hi!' }
@@ -274,6 +280,29 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'when request exceeds the rate limit' do
+ before do
+ stub_application_setting(notes_create_limit: 1)
+ allow(::Gitlab::ApplicationRateLimiter).to receive(:increment).and_return(2)
+ end
+
+ it 'prevents user from creating more notes' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:too_many_requests)
+ expect(json_response['message']['error']).to eq('This endpoint has been requested too many times. Try again later.')
+ end
+
+ it 'allows user in allow-list to create notes' do
+ stub_application_setting(notes_create_limit_allowlist: ["#{user.username}"])
+ subject
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['body']).to eq('hi!')
+ expect(json_response['author']['username']).to eq(user.username)
+ end
+ end
end
describe "PUT /#{parent_type}/:id/#{noteable_type}/:noteable_id/notes/:note_id" do
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
index d3ad7aa0595..be051dcbb7b 100644
--- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
@@ -1,270 +1,430 @@
# frozen_string_literal: true
-RSpec.shared_examples 'handling get metadata requests' do
+RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
+ using RSpec::Parameterized::TableSyntax
+
let_it_be(:package_dependency_link1) { create(:packages_dependency_link, package: package, dependency_type: :dependencies) }
let_it_be(:package_dependency_link2) { create(:packages_dependency_link, package: package, dependency_type: :devDependencies) }
let_it_be(:package_dependency_link3) { create(:packages_dependency_link, package: package, dependency_type: :bundleDependencies) }
let_it_be(:package_dependency_link4) { create(:packages_dependency_link, package: package, dependency_type: :peerDependencies) }
- let(:params) { {} }
let(:headers) { {} }
- subject { get(url, params: params, headers: headers) }
+ subject { get(url, headers: headers) }
- shared_examples 'returning the npm package info' do
- it 'returns the package info' do
+ shared_examples 'accept metadata request' do |status:|
+ it 'accepts the metadata request' do
subject
- expect_a_valid_package_response
+ expect(response).to have_gitlab_http_status(status)
+ expect(response.media_type).to eq('application/json')
+ expect(response).to match_response_schema('public_api/v4/packages/npm_package')
+ expect(json_response['name']).to eq(package.name)
+ expect(json_response['versions'][package.version]).to match_schema('public_api/v4/packages/npm_package_version')
+ ::Packages::Npm::PackagePresenter::NPM_VALID_DEPENDENCY_TYPES.each do |dependency_type|
+ expect(json_response.dig('versions', package.version, dependency_type.to_s)).to be_any
+ end
+ expect(json_response['dist-tags']).to match_schema('public_api/v4/packages/npm_package_tags')
end
end
- shared_examples 'a package that requires auth' do
- it 'denies request without oauth token' do
+ shared_examples 'reject metadata request' do |status:|
+ it 'rejects the metadata request' do
subject
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(status)
end
+ end
- context 'with oauth token' do
- let(:params) { { access_token: token.token } }
-
- it 'returns the package info with oauth token' do
- subject
+ shared_examples 'redirect metadata request' do |status:|
+ it 'redirects metadata request' do
+ subject
- expect_a_valid_package_response
- end
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response.headers['Location']).to eq("https://registry.npmjs.org/#{package_name}")
end
+ end
- context 'with job token' do
- let(:params) { { job_token: job.token } }
-
- it 'returns the package info with running job token' do
- subject
+ where(:auth, :package_name_type, :request_forward, :visibility, :user_role, :expected_result, :expected_status) do
+ nil | :scoped_naming_convention | true | 'PUBLIC' | nil | :accept | :ok
+ nil | :scoped_naming_convention | false | 'PUBLIC' | nil | :accept | :ok
+ nil | :non_existing | true | 'PUBLIC' | nil | :redirect | :redirected
+ nil | :non_existing | false | 'PUBLIC' | nil | :reject | :not_found
+ nil | :scoped_naming_convention | true | 'PRIVATE' | nil | :reject | :not_found
+ nil | :scoped_naming_convention | false | 'PRIVATE' | nil | :reject | :not_found
+ nil | :non_existing | true | 'PRIVATE' | nil | :redirect | :redirected
+ nil | :non_existing | false | 'PRIVATE' | nil | :reject | :not_found
+ nil | :scoped_naming_convention | true | 'INTERNAL' | nil | :reject | :not_found
+ nil | :scoped_naming_convention | false | 'INTERNAL' | nil | :reject | :not_found
+ nil | :non_existing | true | 'INTERNAL' | nil | :redirect | :redirected
+ nil | :non_existing | false | 'INTERNAL' | nil | :reject | :not_found
+
+ :oauth | :scoped_naming_convention | true | 'PUBLIC' | :guest | :accept | :ok
+ :oauth | :scoped_naming_convention | true | 'PUBLIC' | :reporter | :accept | :ok
+ :oauth | :scoped_naming_convention | false | 'PUBLIC' | :guest | :accept | :ok
+ :oauth | :scoped_naming_convention | false | 'PUBLIC' | :reporter | :accept | :ok
+ :oauth | :non_existing | true | 'PUBLIC' | :guest | :redirect | :redirected
+ :oauth | :non_existing | true | 'PUBLIC' | :reporter | :redirect | :redirected
+ :oauth | :non_existing | false | 'PUBLIC' | :guest | :reject | :not_found
+ :oauth | :non_existing | false | 'PUBLIC' | :reporter | :reject | :not_found
+ :oauth | :scoped_naming_convention | true | 'PRIVATE' | :guest | :reject | :forbidden
+ :oauth | :scoped_naming_convention | true | 'PRIVATE' | :reporter | :accept | :ok
+ :oauth | :scoped_naming_convention | false | 'PRIVATE' | :guest | :reject | :forbidden
+ :oauth | :scoped_naming_convention | false | 'PRIVATE' | :reporter | :accept | :ok
+ :oauth | :non_existing | true | 'PRIVATE' | :guest | :redirect | :redirected
+ :oauth | :non_existing | true | 'PRIVATE' | :reporter | :redirect | :redirected
+ :oauth | :non_existing | false | 'PRIVATE' | :guest | :reject | :forbidden
+ :oauth | :non_existing | false | 'PRIVATE' | :reporter | :reject | :not_found
+ :oauth | :scoped_naming_convention | true | 'INTERNAL' | :guest | :accept | :ok
+ :oauth | :scoped_naming_convention | true | 'INTERNAL' | :reporter | :accept | :ok
+ :oauth | :scoped_naming_convention | false | 'INTERNAL' | :guest | :accept | :ok
+ :oauth | :scoped_naming_convention | false | 'INTERNAL' | :reporter | :accept | :ok
+ :oauth | :non_existing | true | 'INTERNAL' | :guest | :redirect | :redirected
+ :oauth | :non_existing | true | 'INTERNAL' | :reporter | :redirect | :redirected
+ :oauth | :non_existing | false | 'INTERNAL' | :guest | :reject | :not_found
+ :oauth | :non_existing | false | 'INTERNAL' | :reporter | :reject | :not_found
+
+ :personal_access_token | :scoped_naming_convention | true | 'PUBLIC' | :guest | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | true | 'PUBLIC' | :reporter | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | false | 'PUBLIC' | :guest | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | false | 'PUBLIC' | :reporter | :accept | :ok
+ :personal_access_token | :non_existing | true | 'PUBLIC' | :guest | :redirect | :redirected
+ :personal_access_token | :non_existing | true | 'PUBLIC' | :reporter | :redirect | :redirected
+ :personal_access_token | :non_existing | false | 'PUBLIC' | :guest | :reject | :not_found
+ :personal_access_token | :non_existing | false | 'PUBLIC' | :reporter | :reject | :not_found
+ :personal_access_token | :scoped_naming_convention | true | 'PRIVATE' | :guest | :reject | :forbidden
+ :personal_access_token | :scoped_naming_convention | true | 'PRIVATE' | :reporter | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | false | 'PRIVATE' | :guest | :reject | :forbidden
+ :personal_access_token | :scoped_naming_convention | false | 'PRIVATE' | :reporter | :accept | :ok
+ :personal_access_token | :non_existing | true | 'PRIVATE' | :guest | :redirect | :redirected
+ :personal_access_token | :non_existing | true | 'PRIVATE' | :reporter | :redirect | :redirected
+ :personal_access_token | :non_existing | false | 'PRIVATE' | :guest | :reject | :forbidden
+ :personal_access_token | :non_existing | false | 'PRIVATE' | :reporter | :reject | :not_found
+ :personal_access_token | :scoped_naming_convention | true | 'INTERNAL' | :guest | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | true | 'INTERNAL' | :reporter | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | false | 'INTERNAL' | :guest | :accept | :ok
+ :personal_access_token | :scoped_naming_convention | false | 'INTERNAL' | :reporter | :accept | :ok
+ :personal_access_token | :non_existing | true | 'INTERNAL' | :guest | :redirect | :redirected
+ :personal_access_token | :non_existing | true | 'INTERNAL' | :reporter | :redirect | :redirected
+ :personal_access_token | :non_existing | false | 'INTERNAL' | :guest | :reject | :not_found
+ :personal_access_token | :non_existing | false | 'INTERNAL' | :reporter | :reject | :not_found
+
+ :job_token | :scoped_naming_convention | true | 'PUBLIC' | :developer | :accept | :ok
+ :job_token | :scoped_naming_convention | false | 'PUBLIC' | :developer | :accept | :ok
+ :job_token | :non_existing | true | 'PUBLIC' | :developer | :redirect | :redirected
+ :job_token | :non_existing | false | 'PUBLIC' | :developer | :reject | :not_found
+ :job_token | :scoped_naming_convention | true | 'PRIVATE' | :developer | :accept | :ok
+ :job_token | :scoped_naming_convention | false | 'PRIVATE' | :developer | :accept | :ok
+ :job_token | :non_existing | true | 'PRIVATE' | :developer | :redirect | :redirected
+ :job_token | :non_existing | false | 'PRIVATE' | :developer | :reject | :not_found
+ :job_token | :scoped_naming_convention | true | 'INTERNAL' | :developer | :accept | :ok
+ :job_token | :scoped_naming_convention | false | 'INTERNAL' | :developer | :accept | :ok
+ :job_token | :non_existing | true | 'INTERNAL' | :developer | :redirect | :redirected
+ :job_token | :non_existing | false | 'INTERNAL' | :developer | :reject | :not_found
+
+ :deploy_token | :scoped_naming_convention | true | 'PUBLIC' | nil | :accept | :ok
+ :deploy_token | :scoped_naming_convention | false | 'PUBLIC' | nil | :accept | :ok
+ :deploy_token | :non_existing | true | 'PUBLIC' | nil | :redirect | :redirected
+ :deploy_token | :non_existing | false | 'PUBLIC' | nil | :reject | :not_found
+ :deploy_token | :scoped_naming_convention | true | 'PRIVATE' | nil | :accept | :ok
+ :deploy_token | :scoped_naming_convention | false | 'PRIVATE' | nil | :accept | :ok
+ :deploy_token | :non_existing | true | 'PRIVATE' | nil | :redirect | :redirected
+ :deploy_token | :non_existing | false | 'PRIVATE' | nil | :reject | :not_found
+ :deploy_token | :scoped_naming_convention | true | 'INTERNAL' | nil | :accept | :ok
+ :deploy_token | :scoped_naming_convention | false | 'INTERNAL' | nil | :accept | :ok
+ :deploy_token | :non_existing | true | 'INTERNAL' | nil | :redirect | :redirected
+ :deploy_token | :non_existing | false | 'INTERNAL' | nil | :reject | :not_found
+ end
- expect_a_valid_package_response
+ with_them do
+ include_context 'set package name from package name type'
+
+ let(:headers) do
+ case auth
+ when :oauth
+ build_token_auth_header(token.token)
+ when :personal_access_token
+ build_token_auth_header(personal_access_token.token)
+ when :job_token
+ build_token_auth_header(job.token)
+ when :deploy_token
+ build_token_auth_header(deploy_token.token)
+ else
+ {}
end
+ end
- it 'denies request without running job token' do
- job.update!(status: :success)
+ before do
+ project.send("add_#{user_role}", user) if user_role
+ project.update!(visibility: Gitlab::VisibilityLevel.const_get(visibility, false))
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
+ stub_application_setting(npm_package_requests_forwarding: request_forward)
+ end
- subject
+ example_name = "#{params[:expected_result]} metadata request"
+ status = params[:expected_status]
- expect(response).to have_gitlab_http_status(:unauthorized)
+ if scope == :instance && params[:package_name_type] != :scoped_naming_convention
+ if params[:request_forward]
+ example_name = 'redirect metadata request'
+ status = :redirected
+ else
+ example_name = 'reject metadata request'
+ status = :not_found
end
end
- context 'with deploy token' do
- let(:headers) { build_token_auth_header(deploy_token.token) }
+ it_behaves_like example_name, status: status
+ end
- it 'returns the package info with deploy token' do
- subject
+ context 'with a developer' do
+ let(:headers) { build_token_auth_header(personal_access_token.token) }
- expect_a_valid_package_response
- end
+ before do
+ project.add_developer(user)
end
- end
-
- context 'a public project' do
- it_behaves_like 'returning the npm package info'
context 'project path with a dot' do
before do
project.update!(path: 'foo.bar')
end
- it_behaves_like 'returning the npm package info'
+ it_behaves_like 'accept metadata request', status: :ok
end
- context 'with request forward disabled' do
+ context 'with a job token' do
+ let(:headers) { build_token_auth_header(job.token) }
+
before do
- stub_application_setting(npm_package_requests_forwarding: false)
+ job.update!(status: :success)
end
- it_behaves_like 'returning the npm package info'
+ it_behaves_like 'reject metadata request', status: :unauthorized
+ end
+ end
+end
+
+RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
+ using RSpec::Parameterized::TableSyntax
+ include_context 'set package name from package name type'
- context 'with unknown package' do
- let(:package_name) { 'unknown' }
+ let_it_be(:package_tag1) { create(:packages_tag, package: package) }
+ let_it_be(:package_tag2) { create(:packages_tag, package: package) }
- it 'returns the proper response' do
- subject
+ let(:headers) { {} }
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
+ subject { get(url, headers: headers) }
+
+ shared_examples 'reject package tags request' do |status:|
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
end
- context 'with request forward enabled' do
- before do
- stub_application_setting(npm_package_requests_forwarding: true)
- end
+ it_behaves_like 'returning response status', status
+ end
- it_behaves_like 'returning the npm package info'
+ shared_examples 'handling different package names, visibilities and user roles' do
+ where(:package_name_type, :visibility, :user_role, :expected_result, :expected_status) do
+ :scoped_naming_convention | 'PUBLIC' | :anonymous | :accept | :ok
+ :scoped_naming_convention | 'PUBLIC' | :guest | :accept | :ok
+ :scoped_naming_convention | 'PUBLIC' | :reporter | :accept | :ok
+ :non_existing | 'PUBLIC' | :anonymous | :reject | :not_found
+ :non_existing | 'PUBLIC' | :guest | :reject | :not_found
+ :non_existing | 'PUBLIC' | :reporter | :reject | :not_found
+
+ :scoped_naming_convention | 'PRIVATE' | :anonymous | :reject | :not_found
+ :scoped_naming_convention | 'PRIVATE' | :guest | :reject | :forbidden
+ :scoped_naming_convention | 'PRIVATE' | :reporter | :accept | :ok
+ :non_existing | 'PRIVATE' | :anonymous | :reject | :not_found
+ :non_existing | 'PRIVATE' | :guest | :reject | :forbidden
+ :non_existing | 'PRIVATE' | :reporter | :reject | :not_found
+
+ :scoped_naming_convention | 'INTERNAL' | :anonymous | :reject | :not_found
+ :scoped_naming_convention | 'INTERNAL' | :guest | :accept | :ok
+ :scoped_naming_convention | 'INTERNAL' | :reporter | :accept | :ok
+ :non_existing | 'INTERNAL' | :anonymous | :reject | :not_found
+ :non_existing | 'INTERNAL' | :guest | :reject | :not_found
+ :non_existing | 'INTERNAL' | :reporter | :reject | :not_found
+ end
+
+ with_them do
+ let(:anonymous) { user_role == :anonymous }
- context 'with unknown package' do
- let(:package_name) { 'unknown' }
+ subject { get(url, headers: anonymous ? {} : headers) }
- it 'returns a redirect' do
- subject
+ before do
+ project.send("add_#{user_role}", user) unless anonymous
+ project.update!(visibility: Gitlab::VisibilityLevel.const_get(visibility, false))
+ end
- expect(response).to have_gitlab_http_status(:found)
- expect(response.headers['Location']).to eq('https://registry.npmjs.org/unknown')
- end
+ example_name = "#{params[:expected_result]} package tags request"
+ status = params[:expected_status]
- it_behaves_like 'a gitlab tracking event', described_class.name, 'npm_request_forward'
+ if scope == :instance && params[:package_name_type] != :scoped_naming_convention
+ example_name = 'reject package tags request'
+ status = :not_found
end
+
+ it_behaves_like example_name, status: status
end
end
- context 'internal project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
+ context 'with oauth token' do
+ let(:headers) { build_token_auth_header(token.token) }
- it_behaves_like 'a package that requires auth'
+ it_behaves_like 'handling different package names, visibilities and user roles'
end
- context 'private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
+ context 'with personal access token' do
+ let(:headers) { build_token_auth_header(personal_access_token.token) }
- it_behaves_like 'a package that requires auth'
+ it_behaves_like 'handling different package names, visibilities and user roles'
+ end
+end
- context 'with guest' do
- let(:params) { { access_token: token.token } }
+RSpec.shared_examples 'handling create dist tag requests' do |scope: :project|
+ using RSpec::Parameterized::TableSyntax
+ include_context 'set package name from package name type'
- it 'denies request when not enough permissions' do
- project.add_guest(user)
+ let_it_be(:tag_name) { 'test' }
- subject
+ let(:params) { {} }
+ let(:version) { package.version }
+ let(:env) { { 'api.request.body': version } }
+ let(:headers) { {} }
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ shared_examples 'reject create package tag request' do |status:|
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
end
+
+ it_behaves_like 'returning response status', status
end
- def expect_a_valid_package_response
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/json')
- expect(response).to match_response_schema('public_api/v4/packages/npm_package')
- expect(json_response['name']).to eq(package.name)
- expect(json_response['versions'][package.version]).to match_schema('public_api/v4/packages/npm_package_version')
- ::Packages::Npm::PackagePresenter::NPM_VALID_DEPENDENCY_TYPES.each do |dependency_type|
- expect(json_response.dig('versions', package.version, dependency_type.to_s)).to be_any
+ shared_examples 'handling different package names, visibilities and user roles' do
+ where(:package_name_type, :visibility, :user_role, :expected_result, :expected_status) do
+ :scoped_naming_convention | 'PUBLIC' | :anonymous | :reject | :forbidden
+ :scoped_naming_convention | 'PUBLIC' | :guest | :reject | :forbidden
+ :scoped_naming_convention | 'PUBLIC' | :developer | :accept | :ok
+ :non_existing | 'PUBLIC' | :anonymous | :reject | :forbidden
+ :non_existing | 'PUBLIC' | :guest | :reject | :forbidden
+ :non_existing | 'PUBLIC' | :developer | :reject | :not_found
+
+ :scoped_naming_convention | 'PRIVATE' | :anonymous | :reject | :not_found
+ :scoped_naming_convention | 'PRIVATE' | :guest | :reject | :forbidden
+ :scoped_naming_convention | 'PRIVATE' | :developer | :accept | :ok
+ :non_existing | 'PRIVATE' | :anonymous | :reject | :not_found
+ :non_existing | 'PRIVATE' | :guest | :reject | :forbidden
+ :non_existing | 'PRIVATE' | :developer | :reject | :not_found
+
+ :scoped_naming_convention | 'INTERNAL' | :anonymous | :reject | :forbidden
+ :scoped_naming_convention | 'INTERNAL' | :guest | :reject | :forbidden
+ :scoped_naming_convention | 'INTERNAL' | :developer | :accept | :ok
+ :non_existing | 'INTERNAL' | :anonymous | :reject | :forbidden
+ :non_existing | 'INTERNAL' | :guest | :reject | :forbidden
+ :non_existing | 'INTERNAL' | :developer | :reject | :not_found
end
- expect(json_response['dist-tags']).to match_schema('public_api/v4/packages/npm_package_tags')
- end
-end
-RSpec.shared_examples 'handling get dist tags requests' do
- let_it_be(:package_tag1) { create(:packages_tag, package: package) }
- let_it_be(:package_tag2) { create(:packages_tag, package: package) }
+ with_them do
+ let(:anonymous) { user_role == :anonymous }
- let(:params) { {} }
+ subject { put(url, env: env, headers: headers) }
- subject { get(url, params: params) }
+ before do
+ project.send("add_#{user_role}", user) unless anonymous
+ project.update!(visibility: Gitlab::VisibilityLevel.const_get(visibility, false))
+ end
- context 'with public project' do
- context 'with authenticated user' do
- let(:params) { { private_token: personal_access_token.token } }
+ example_name = "#{params[:expected_result]} create package tag request"
+ status = params[:expected_status]
- it_behaves_like 'returns package tags', :maintainer
- it_behaves_like 'returns package tags', :developer
- it_behaves_like 'returns package tags', :reporter
- it_behaves_like 'returns package tags', :guest
- end
+ if scope == :instance && params[:package_name_type] != :scoped_naming_convention
+ example_name = 'reject create package tag request'
+ status = :not_found
+ end
- context 'with unauthenticated user' do
- it_behaves_like 'returns package tags', :no_type
+ it_behaves_like example_name, status: status
end
end
- context 'with private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
+ context 'with oauth token' do
+ let(:headers) { build_token_auth_header(token.token) }
- context 'with authenticated user' do
- let(:params) { { private_token: personal_access_token.token } }
+ it_behaves_like 'handling different package names, visibilities and user roles'
+ end
- it_behaves_like 'returns package tags', :maintainer
- it_behaves_like 'returns package tags', :developer
- it_behaves_like 'returns package tags', :reporter
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
+ context 'with personal access token' do
+ let(:headers) { build_token_auth_header(personal_access_token.token) }
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :not_found
- end
+ it_behaves_like 'handling different package names, visibilities and user roles'
end
end
-RSpec.shared_examples 'handling create dist tag requests' do
- let_it_be(:tag_name) { 'test' }
+RSpec.shared_examples 'handling delete dist tag requests' do |scope: :project|
+ using RSpec::Parameterized::TableSyntax
+ include_context 'set package name from package name type'
- let(:params) { {} }
- let(:env) { {} }
- let(:version) { package.version }
-
- subject { put(url, env: env, params: params) }
+ let_it_be(:package_tag) { create(:packages_tag, package: package) }
- context 'with public project' do
- context 'with authenticated user' do
- let(:params) { { private_token: personal_access_token.token } }
- let(:env) { { 'api.request.body': version } }
+ let(:tag_name) { package_tag.name }
+ let(:headers) { {} }
- it_behaves_like 'create package tag', :maintainer
- it_behaves_like 'create package tag', :developer
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
+ shared_examples 'reject delete package tag request' do |status:|
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
end
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
- end
+ it_behaves_like 'returning response status', status
end
-end
-RSpec.shared_examples 'handling delete dist tag requests' do
- let_it_be(:package_tag) { create(:packages_tag, package: package) }
+ shared_examples 'handling different package names, visibilities and user roles' do
+ where(:package_name_type, :visibility, :user_role, :expected_result, :expected_status) do
+ :scoped_naming_convention | 'PUBLIC' | :anonymous | :reject | :forbidden
+ :scoped_naming_convention | 'PUBLIC' | :guest | :reject | :forbidden
+ :scoped_naming_convention | 'PUBLIC' | :maintainer | :accept | :ok
+ :non_existing | 'PUBLIC' | :anonymous | :reject | :forbidden
+ :non_existing | 'PUBLIC' | :guest | :reject | :forbidden
+ :non_existing | 'PUBLIC' | :maintainer | :reject | :not_found
+
+ :scoped_naming_convention | 'PRIVATE' | :anonymous | :reject | :not_found
+ :scoped_naming_convention | 'PRIVATE' | :guest | :reject | :forbidden
+ :scoped_naming_convention | 'PRIVATE' | :maintainer | :accept | :ok
+ :non_existing | 'INTERNAL' | :anonymous | :reject | :forbidden
+ :non_existing | 'INTERNAL' | :guest | :reject | :forbidden
+ :non_existing | 'INTERNAL' | :maintainer | :reject | :not_found
+ end
- let(:params) { {} }
- let(:tag_name) { package_tag.name }
+ with_them do
+ let(:anonymous) { user_role == :anonymous }
+
+ subject { delete(url, headers: headers) }
- subject { delete(url, params: params) }
+ before do
+ project.send("add_#{user_role}", user) unless anonymous
+ project.update!(visibility: Gitlab::VisibilityLevel.const_get(visibility, false))
+ end
- context 'with public project' do
- context 'with authenticated user' do
- let(:params) { { private_token: personal_access_token.token } }
+ example_name = "#{params[:expected_result]} delete package tag request"
+ status = params[:expected_status]
- it_behaves_like 'delete package tag', :maintainer
- it_behaves_like 'rejects package tags access', :developer, :forbidden
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
+ if scope == :instance && params[:package_name_type] != :scoped_naming_convention
+ example_name = 'reject delete package tag request'
+ status = :not_found
+ end
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
+ it_behaves_like example_name, status: status
end
end
- context 'with private project' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
+ context 'with oauth token' do
+ let(:headers) { build_token_auth_header(token.token) }
- context 'with authenticated user' do
- let(:params) { { private_token: personal_access_token.token } }
+ it_behaves_like 'handling different package names, visibilities and user roles'
+ end
- it_behaves_like 'delete package tag', :maintainer
- it_behaves_like 'rejects package tags access', :developer, :forbidden
- it_behaves_like 'rejects package tags access', :reporter, :forbidden
- it_behaves_like 'rejects package tags access', :guest, :forbidden
- end
+ context 'with personal access token' do
+ let(:headers) { build_token_auth_header(personal_access_token.token) }
- context 'with unauthenticated user' do
- it_behaves_like 'rejects package tags access', :no_type, :unauthorized
- end
+ it_behaves_like 'handling different package names, visibilities and user roles'
end
end
diff --git a/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb
new file mode 100644
index 00000000000..e6b3dc74b74
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb
@@ -0,0 +1,190 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'rejects package tags access' do |status:|
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
+ end
+
+ it_behaves_like 'returning response status', status
+end
+
+RSpec.shared_examples 'accept package tags request' do |status:|
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ stub_application_setting(npm_package_requests_forwarding: false)
+ end
+
+ context 'with valid package name' do
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
+ end
+
+ it_behaves_like 'returning response status', status
+
+ it 'returns a valid json response' do
+ subject
+
+ expect(response.media_type).to eq('application/json')
+ expect(json_response).to be_a(Hash)
+ end
+
+ it 'returns two package tags' do
+ subject
+
+ expect(json_response).to match_schema('public_api/v4/packages/npm_package_tags')
+ expect(json_response.length).to eq(3) # two tags + latest (auto added)
+ expect(json_response[package_tag1.name]).to eq(package.version)
+ expect(json_response[package_tag2.name]).to eq(package.version)
+ expect(json_response['latest']).to eq(package.version)
+ end
+ end
+
+ context 'with invalid package name' do
+ where(:package_name, :status) do
+ '%20' | :bad_request
+ nil | :not_found
+ end
+
+ with_them do
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+end
+
+RSpec.shared_examples 'accept create package tag request' do |user_type|
+ using RSpec::Parameterized::TableSyntax
+
+ context 'with valid package name' do
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
+ end
+
+ it_behaves_like 'returning response status', :no_content
+
+ it 'creates the package tag' do
+ expect { subject }.to change { Packages::Tag.count }.by(1)
+
+ last_tag = Packages::Tag.last
+ expect(last_tag.name).to eq(tag_name)
+ expect(last_tag.package).to eq(package)
+ end
+
+ it 'returns a valid response' do
+ subject
+
+ expect(response.body).to be_empty
+ end
+
+ context 'with already existing tag' do
+ let_it_be(:package2) { create(:npm_package, project: project, name: package.name, version: '5.5.55') }
+ let_it_be(:tag) { create(:packages_tag, package: package2, name: tag_name) }
+
+ it_behaves_like 'returning response status', :no_content
+
+ it 'reuses existing tag' do
+ expect(package.tags).to be_empty
+ expect(package2.tags).to eq([tag])
+ expect { subject }.to not_change { Packages::Tag.count }
+ expect(package.reload.tags).to eq([tag])
+ expect(package2.reload.tags).to be_empty
+ end
+
+ it 'returns a valid response' do
+ subject
+
+ expect(response.body).to be_empty
+ end
+ end
+ end
+
+ context 'with invalid package name' do
+ where(:package_name, :status) do
+ 'unknown' | :not_found
+ '' | :not_found
+ '%20' | :bad_request
+ end
+
+ with_them do
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+
+ context 'with invalid tag name' do
+ where(:tag_name, :status) do
+ '' | :not_found
+ '%20' | :bad_request
+ end
+
+ with_them do
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+
+ context 'with invalid version' do
+ where(:version, :status) do
+ ' ' | :bad_request
+ '' | :bad_request
+ nil | :bad_request
+ end
+
+ with_them do
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+end
+
+RSpec.shared_examples 'accept delete package tag request' do |user_type|
+ using RSpec::Parameterized::TableSyntax
+
+ context 'with valid package name' do
+ before do
+ package.update!(name: package_name) unless package_name == 'non-existing-package'
+ end
+
+ it_behaves_like 'returning response status', :no_content
+
+ it 'returns a valid response' do
+ subject
+
+ expect(response.body).to be_empty
+ end
+
+ it 'destroy the package tag' do
+ expect(package.tags).to eq([package_tag])
+ expect { subject }.to change { Packages::Tag.count }.by(-1)
+ expect(package.reload.tags).to be_empty
+ end
+
+ context 'with tag from other package' do
+ let(:package2) { create(:npm_package, project: project) }
+ let(:package_tag) { create(:packages_tag, package: package2) }
+
+ it_behaves_like 'returning response status', :not_found
+ end
+ end
+
+ context 'with invalid package name' do
+ where(:package_name, :status) do
+ 'unknown' | :not_found
+ '' | :not_found
+ '%20' | :bad_request
+ end
+
+ with_them do
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+
+ context 'with invalid tag name' do
+ where(:tag_name, :status) do
+ 'unknown' | :not_found
+ '' | :not_found
+ '%20' | :bad_request
+ end
+
+ with_them do
+ it_behaves_like 'returning response status', params[:status]
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
index 8b60857cdaf..617fdecbb5b 100644
--- a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
@@ -123,7 +123,7 @@ RSpec.shared_examples 'process nuget workhorse authorization' do |user_type, sta
context 'with a request that bypassed gitlab-workhorse' do
let(:headers) do
basic_auth_header(user.username, personal_access_token.token)
- .merge(workhorse_header)
+ .merge(workhorse_headers)
.tap { |h| h.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER) }
end
diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
index 3833604e304..15976eed021 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -24,7 +24,7 @@ end
RSpec.shared_examples 'deploy token for package uploads' do
context 'with deploy token headers' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -35,7 +35,7 @@ RSpec.shared_examples 'deploy token for package uploads' do
end
context 'invalid token' do
- let(:headers) { basic_auth_header(deploy_token.username, 'bar').merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, 'bar').merge(workhorse_headers) }
it_behaves_like 'returning response status', :unauthorized
end
@@ -102,7 +102,7 @@ end
RSpec.shared_examples 'job token for package uploads' do
context 'with job token headers' do
- let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token).merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -114,13 +114,13 @@ RSpec.shared_examples 'job token for package uploads' do
end
context 'invalid token' do
- let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar').merge(workhorse_header) }
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar').merge(workhorse_headers) }
it_behaves_like 'returning response status', :unauthorized
end
context 'invalid user' do
- let(:headers) { basic_auth_header('foo', job.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header('foo', job.token).merge(workhorse_headers) }
it_behaves_like 'returning response status', :unauthorized
end
diff --git a/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb
deleted file mode 100644
index 2c203dc096e..00000000000
--- a/spec/support/shared_examples/requests/api/packages_tags_shared_examples.rb
+++ /dev/null
@@ -1,185 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'rejects package tags access' do |user_type, status|
- context "for user type #{user_type}" do
- before do
- project.send("add_#{user_type}", user) unless user_type == :no_type
- end
-
- it_behaves_like 'returning response status', status
- end
-end
-
-RSpec.shared_examples 'returns package tags' do |user_type|
- using RSpec::Parameterized::TableSyntax
-
- before do
- stub_application_setting(npm_package_requests_forwarding: false)
- project.send("add_#{user_type}", user) unless user_type == :no_type
- end
-
- it_behaves_like 'returning response status', :success
-
- it 'returns a valid json response' do
- subject
-
- expect(response.media_type).to eq('application/json')
- expect(json_response).to be_a(Hash)
- end
-
- it 'returns two package tags' do
- subject
-
- expect(json_response).to match_schema('public_api/v4/packages/npm_package_tags')
- expect(json_response.length).to eq(3) # two tags + latest (auto added)
- expect(json_response[package_tag1.name]).to eq(package.version)
- expect(json_response[package_tag2.name]).to eq(package.version)
- expect(json_response['latest']).to eq(package.version)
- end
-
- context 'with invalid package name' do
- where(:package_name, :status) do
- '%20' | :bad_request
- nil | :not_found
- end
-
- with_them do
- it_behaves_like 'returning response status', params[:status]
- end
- end
-end
-
-RSpec.shared_examples 'create package tag' do |user_type|
- using RSpec::Parameterized::TableSyntax
-
- before do
- project.send("add_#{user_type}", user) unless user_type == :no_type
- end
-
- it_behaves_like 'returning response status', :no_content
-
- it 'creates the package tag' do
- expect { subject }.to change { Packages::Tag.count }.by(1)
-
- last_tag = Packages::Tag.last
- expect(last_tag.name).to eq(tag_name)
- expect(last_tag.package).to eq(package)
- end
-
- it 'returns a valid response' do
- subject
-
- expect(response.body).to be_empty
- end
-
- context 'with already existing tag' do
- let_it_be(:package2) { create(:npm_package, project: project, name: package.name, version: '5.5.55') }
- let_it_be(:tag) { create(:packages_tag, package: package2, name: tag_name) }
-
- it_behaves_like 'returning response status', :no_content
-
- it 'reuses existing tag' do
- expect(package.tags).to be_empty
- expect(package2.tags).to eq([tag])
- expect { subject }.to not_change { Packages::Tag.count }
- expect(package.reload.tags).to eq([tag])
- expect(package2.reload.tags).to be_empty
- end
-
- it 'returns a valid response' do
- subject
-
- expect(response.body).to be_empty
- end
- end
-
- context 'with invalid package name' do
- where(:package_name, :status) do
- 'unknown' | :not_found
- '' | :not_found
- '%20' | :bad_request
- end
-
- with_them do
- it_behaves_like 'returning response status', params[:status]
- end
- end
-
- context 'with invalid tag name' do
- where(:tag_name, :status) do
- '' | :not_found
- '%20' | :bad_request
- end
-
- with_them do
- it_behaves_like 'returning response status', params[:status]
- end
- end
-
- context 'with invalid version' do
- where(:version, :status) do
- ' ' | :bad_request
- '' | :bad_request
- nil | :bad_request
- end
-
- with_them do
- it_behaves_like 'returning response status', params[:status]
- end
- end
-end
-
-RSpec.shared_examples 'delete package tag' do |user_type|
- using RSpec::Parameterized::TableSyntax
-
- before do
- project.send("add_#{user_type}", user) unless user_type == :no_type
- end
-
- context "for #{user_type} user" do
- it_behaves_like 'returning response status', :no_content
-
- it 'returns a valid response' do
- subject
-
- expect(response.body).to be_empty
- end
-
- it 'destroy the package tag' do
- expect(package.tags).to eq([package_tag])
- expect { subject }.to change { Packages::Tag.count }.by(-1)
- expect(package.reload.tags).to be_empty
- end
-
- context 'with tag from other package' do
- let(:package2) { create(:npm_package, project: project) }
- let(:package_tag) { create(:packages_tag, package: package2) }
-
- it_behaves_like 'returning response status', :not_found
- end
-
- context 'with invalid package name' do
- where(:package_name, :status) do
- 'unknown' | :not_found
- '' | :not_found
- '%20' | :bad_request
- end
-
- with_them do
- it_behaves_like 'returning response status', params[:status]
- end
- end
-
- context 'with invalid tag name' do
- where(:tag_name, :status) do
- 'unknown' | :not_found
- '' | :not_found
- '%20' | :bad_request
- end
-
- with_them do
- it_behaves_like 'returning response status', params[:status]
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/requests/api/read_user_shared_examples.rb b/spec/support/shared_examples/requests/api/read_user_shared_examples.rb
index 59cd0ab67b4..b9fd997bd2c 100644
--- a/spec/support/shared_examples/requests/api/read_user_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/read_user_shared_examples.rb
@@ -7,21 +7,33 @@ RSpec.shared_examples 'allows the "read_user" scope' do |api_version|
context 'when the requesting token has the "api" scope' do
let(:token) { create(:personal_access_token, scopes: ['api'], user: user) }
- it 'returns a "200" response' do
+ it 'returns a "200" response on get request' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it 'returns a "200" response on head request' do
+ head api_call.call(path, user, personal_access_token: token, version: version)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'when the requesting token has the "read_user" scope' do
let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
- it 'returns a "200" response' do
+ it 'returns a "200" response on get request' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it 'returns a "200" response on head request' do
+ head api_call.call(path, user, personal_access_token: token, version: version)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'when the requesting token does not have any required scope' do
@@ -45,21 +57,33 @@ RSpec.shared_examples 'allows the "read_user" scope' do |api_version|
context 'when the requesting token has the "api" scope' do
let!(:token) { Doorkeeper::AccessToken.create! application_id: application.id, resource_owner_id: user.id, scopes: "api" }
- it 'returns a "200" response' do
+ it 'returns a "200" response on get request' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it 'returns a "200" response on head request' do
+ head api_call.call(path, user, oauth_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'when the requesting token has the "read_user" scope' do
let!(:token) { Doorkeeper::AccessToken.create! application_id: application.id, resource_owner_id: user.id, scopes: "read_user" }
- it 'returns a "200" response' do
+ it 'returns a "200" response on get request' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it 'returns a "200" response on head request' do
+ head api_call.call(path, user, oauth_access_token: token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
end
context 'when the requesting token does not have any required scope' do
diff --git a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
index b2970fd265d..3ca2b9fa6de 100644
--- a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
@@ -85,14 +85,37 @@ RSpec.shared_examples 'repository_storage_moves API' do |container_type|
end
describe "GET /#{container_type}/:id/repository_storage_moves" do
- it_behaves_like 'get container repository storage move list' do
- let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves" }
+ let(:container_id) { container.id }
+ let(:url) { "/#{container_type}/#{container_id}/repository_storage_moves" }
+
+ it_behaves_like 'get container repository storage move list'
+
+ context 'non-existent container' do
+ let(:container_id) { non_existing_record_id }
+
+ it 'returns not found' do
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
describe "GET /#{container_type}/:id/repository_storage_moves/:repository_storage_move_id" do
- it_behaves_like 'get single container repository storage move' do
- let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves/#{repository_storage_move_id}" }
+ let(:container_id) { container.id }
+ let(:url) { "/#{container_type}/#{container_id}/repository_storage_moves/#{repository_storage_move_id}" }
+
+ it_behaves_like 'get single container repository storage move'
+
+ context 'non-existent container' do
+ let(:container_id) { non_existing_record_id }
+ let(:repository_storage_move_id) { storage_move.id }
+
+ it 'returns not found' do
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
end
end
@@ -109,7 +132,8 @@ RSpec.shared_examples 'repository_storage_moves API' do |container_type|
end
describe "POST /#{container_type}/:id/repository_storage_moves" do
- let(:url) { "/#{container_type}/#{container.id}/repository_storage_moves" }
+ let(:container_id) { container.id }
+ let(:url) { "/#{container_type}/#{container_id}/repository_storage_moves" }
let(:destination_storage_name) { 'test_second_storage' }
def create_container_repository_storage_move
@@ -154,6 +178,16 @@ RSpec.shared_examples 'repository_storage_moves API' do |container_type|
expect(json_response['destination_storage_name']).to be_present
end
end
+
+ context 'when container does not exist' do
+ let(:container_id) { non_existing_record_id }
+
+ it 'returns not found' do
+ create_container_repository_storage_move
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
end
describe "POST /#{container_type.singularize}_repository_storage_moves" do
diff --git a/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb b/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb
index 460e8d57a2b..b5139bd8c99 100644
--- a/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb
@@ -13,6 +13,9 @@ RSpec.shared_examples 'resolvable discussions API' do |parent_type, noteable_typ
end
it "unresolves discussion if resolved is false" do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_unresolve_thread_action).with(user: user)
+
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
"discussions/#{note.discussion_id}", user), params: { resolved: false }
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 3b039049ca9..926da827e75 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -112,7 +112,7 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
expect(response).not_to have_gitlab_http_status(:too_many_requests)
end
- arguments = {
+ arguments = a_hash_including({
message: 'Rack_Attack',
env: :throttle,
remote_ip: '127.0.0.1',
@@ -121,7 +121,7 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
user_id: user.id,
'meta.user' => user.username,
matched: throttle_types[throttle_setting_prefix]
- }
+ })
expect(Gitlab::AuthLogger).to receive(:error).with(arguments).once
@@ -278,7 +278,7 @@ RSpec.shared_examples 'rate-limited web authenticated requests' do
expect(response).not_to have_gitlab_http_status(:too_many_requests)
end
- arguments = {
+ arguments = a_hash_including({
message: 'Rack_Attack',
env: :throttle,
remote_ip: '127.0.0.1',
@@ -287,7 +287,7 @@ RSpec.shared_examples 'rate-limited web authenticated requests' do
user_id: user.id,
'meta.user' => user.username,
matched: throttle_types[throttle_setting_prefix]
- }
+ })
expect(Gitlab::AuthLogger).to receive(:error).with(arguments).once
expect { request_authenticated_web_url }.not_to exceed_query_limit(control_count)
diff --git a/spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb
index 8f7c08ed625..0e2bddc19ab 100644
--- a/spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb
@@ -1,32 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'boards list service' do
- context 'when parent does not have a board' do
- it 'creates a new parent board' do
- expect { service.execute }.to change(parent.boards, :count).by(1)
- end
-
- it 'delegates the parent board creation to Boards::CreateService' do
- expect_any_instance_of(Boards::CreateService).to receive(:execute).once
-
- service.execute
- end
-
- context 'when create_default_board is false' do
- it 'does not create a new parent board' do
- expect { service.execute(create_default_board: false) }.not_to change(parent.boards, :count)
- end
- end
- end
-
- context 'when parent has a board' do
- before do
- create(:board, resource_parent: parent)
- end
-
- it 'does not create a new board' do
- expect { service.execute }.not_to change(parent.boards, :count)
- end
+ it 'does not create a new board' do
+ expect { service.execute }.not_to change(parent.boards, :count)
end
it 'returns parent boards' do
diff --git a/spec/support/shared_examples/services/boards/lists_create_service_shared_examples.rb b/spec/support/shared_examples/services/boards/lists_create_service_shared_examples.rb
new file mode 100644
index 00000000000..3be002c2126
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/lists_create_service_shared_examples.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'board lists create service' do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+
+ before_all do
+ parent.add_developer(user)
+ end
+
+ subject(:service) { described_class.new(parent, user, label_id: label.id) }
+
+ context 'when board lists is empty' do
+ it 'creates a new list at beginning of the list' do
+ response = service.execute(board)
+
+ expect(response.success?).to eq(true)
+ expect(response.payload[:list].position).to eq 0
+ end
+ end
+
+ context 'when board lists has the done list' do
+ it 'creates a new list at beginning of the list' do
+ response = service.execute(board)
+
+ expect(response.success?).to eq(true)
+ expect(response.payload[:list].position).to eq 0
+ end
+ end
+
+ context 'when board lists has labels lists' do
+ it 'creates a new list at end of the lists' do
+ create_list(position: 0)
+ create_list(position: 1)
+
+ response = service.execute(board)
+
+ expect(response.success?).to eq(true)
+ expect(response.payload[:list].position).to eq 2
+ end
+ end
+
+ context 'when board lists has label and done lists' do
+ it 'creates a new list at end of the label lists' do
+ list1 = create_list(position: 0)
+
+ list2 = service.execute(board).payload[:list]
+
+ expect(list1.reload.position).to eq 0
+ expect(list2.reload.position).to eq 1
+ end
+ end
+
+ context 'when provided label does not belong to the parent' do
+ it 'returns an error' do
+ label = create(:label, name: 'in-development')
+ service = described_class.new(parent, user, label_id: label.id)
+
+ response = service.execute(board)
+
+ expect(response.success?).to eq(false)
+ expect(response.errors).to include('Label not found')
+ end
+ end
+
+ context 'when backlog param is sent' do
+ it 'creates one and only one backlog list' do
+ service = described_class.new(parent, user, 'backlog' => true)
+ list = service.execute(board).payload[:list]
+
+ expect(list.list_type).to eq('backlog')
+ expect(list.position).to be_nil
+ expect(list).to be_valid
+
+ another_backlog = service.execute(board).payload[:list]
+
+ expect(another_backlog).to eq list
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/issuable_shared_examples.rb b/spec/support/shared_examples/services/issuable_shared_examples.rb
index 47c7a1e7356..5b3e0f9e0b9 100644
--- a/spec/support/shared_examples/services/issuable_shared_examples.rb
+++ b/spec/support/shared_examples/services/issuable_shared_examples.rb
@@ -18,6 +18,27 @@ RSpec.shared_examples 'updating a single task' do
update_issuable(description: "- [ ] Task 1\n- [ ] Task 2")
end
+ context 'usage counters' do
+ it 'update as expected' do
+ if try(:merge_request)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_task_item_status_changed).once.with(user: user)
+ else
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .not_to receive(:track_task_item_status_changed)
+ end
+
+ update_issuable(
+ update_task: {
+ index: 1,
+ checked: true,
+ line_source: '- [ ] Task 1',
+ line_number: 1
+ }
+ )
+ end
+ end
+
context 'when a task is marked as completed' do
before do
update_issuable(update_task: { index: 1, checked: true, line_source: '- [ ] Task 1', line_number: 1 })
diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb
index fa307d2a9a6..4e34c191306 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -40,6 +40,19 @@ RSpec.shared_examples 'assigns the package creator' do
end
end
+RSpec.shared_examples 'assigns status to package' do
+ context 'with status param' do
+ let_it_be(:status) { 'hidden' }
+ let(:params) { super().merge(status: status) }
+
+ it 'assigns the status to the package' do
+ package = subject
+
+ expect(package.status).to eq(status)
+ end
+ end
+end
+
RSpec.shared_examples 'returns packages' do |container_type, user_type|
context "for #{user_type}" do
before do
@@ -190,6 +203,7 @@ RSpec.shared_examples 'filters on each package_type' do |is_project: false|
let_it_be(:package7) { create(:generic_package, project: project) }
let_it_be(:package8) { create(:golang_package, project: project) }
let_it_be(:package9) { create(:debian_package, project: project) }
+ let_it_be(:package9) { create(:rubygems_package, project: project) }
Packages::Package.package_types.keys.each do |package_type|
context "for package type #{package_type}" do
@@ -262,3 +276,41 @@ RSpec.shared_examples 'with versionless packages' do
end
end
end
+
+RSpec.shared_examples 'with status param' do
+ context 'hidden packages' do
+ let!(:hidden_package) { create(:maven_package, :hidden, project: project) }
+
+ shared_examples 'not including the hidden package' do
+ it 'does not return the package' do
+ subject
+
+ expect(json_response.map { |package| package['id'] }).not_to include(hidden_package.id)
+ end
+ end
+
+ context 'no status param' do
+ it_behaves_like 'not including the hidden package'
+ end
+
+ context 'with hidden status param' do
+ let(:params) { super().merge(status: 'hidden') }
+
+ it 'returns the package' do
+ subject
+
+ expect(json_response.map { |package| package['id'] }).to include(hidden_package.id)
+ end
+ end
+ end
+
+ context 'bad status param' do
+ let(:params) { super().merge(status: 'invalid') }
+
+ it 'returns the package' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb
index f201c7b1780..1fb1b9f79b2 100644
--- a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb
@@ -71,7 +71,7 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type|
it 'does not enqueue a GC run' do
expect { subject.execute }
- .not_to change(GitGarbageCollectWorker.jobs, :count)
+ .not_to change(Projects::GitGarbageCollectWorker.jobs, :count)
end
end
@@ -84,24 +84,29 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type|
stub_application_setting(housekeeping_enabled: false)
expect { subject.execute }
- .not_to change(GitGarbageCollectWorker.jobs, :count)
+ .not_to change(Projects::GitGarbageCollectWorker.jobs, :count)
end
it 'enqueues a GC run' do
expect { subject.execute }
- .to change(GitGarbageCollectWorker.jobs, :count).by(1)
+ .to change(Projects::GitGarbageCollectWorker.jobs, :count).by(1)
end
end
end
context 'when the filesystems are the same' do
- let(:destination) { project.repository_storage }
+ before do
+ expect(Gitlab::GitalyClient).to receive(:filesystem_id).twice.and_return(SecureRandom.uuid)
+ end
- it 'bails out and does nothing' do
+ it 'updates the database without trying to move the repostory', :aggregate_failures do
result = subject.execute
+ project.reload
- expect(result).to be_error
- expect(result.message).to match(/SameFilesystemError/)
+ expect(result).to be_success
+ expect(project).not_to be_repository_read_only
+ expect(project.repository_storage).to eq('test_second_storage')
+ expect(project.project_repository.shard_name).to eq('test_second_storage')
end
end
diff --git a/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb b/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb
index a174ae94b75..4c00faee56b 100644
--- a/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb
+++ b/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb
@@ -3,16 +3,16 @@
RSpec.shared_examples 'housekeeps repository' do
subject { described_class.new(resource) }
- context 'with a clean redis state', :clean_gitlab_redis_shared_state do
+ context 'with a clean redis state', :clean_gitlab_redis_shared_state, :aggregate_failures do
describe '#execute' do
it 'enqueues a sidekiq job' do
expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
expect(subject).to receive(:lease_key).and_return(:the_lease_key)
expect(subject).to receive(:task).and_return(:incremental_repack)
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(resource.id, :incremental_repack, :the_lease_key, :the_uuid).and_call_original
+ expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :incremental_repack, :the_lease_key, :the_uuid).and_call_original
Sidekiq::Testing.fake! do
- expect { subject.execute }.to change(GitGarbageCollectWorker.jobs, :size).by(1)
+ expect { subject.execute }.to change(resource.git_garbage_collect_worker_klass.jobs, :size).by(1)
end
end
@@ -38,7 +38,7 @@ RSpec.shared_examples 'housekeeps repository' do
end
it 'does not enqueue a job' do
- expect(GitGarbageCollectWorker).not_to receive(:perform_async)
+ expect(resource.git_garbage_collect_worker_klass).not_to receive(:perform_async)
expect { subject.execute }.to raise_error(Repositories::HousekeepingService::LeaseTaken)
end
@@ -63,16 +63,16 @@ RSpec.shared_examples 'housekeeps repository' do
allow(subject).to receive(:lease_key).and_return(:the_lease_key)
# At push 200
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(resource.id, :gc, :the_lease_key, :the_uuid)
+ expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :gc, :the_lease_key, :the_uuid)
.once
# At push 50, 100, 150
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(resource.id, :full_repack, :the_lease_key, :the_uuid)
+ expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :full_repack, :the_lease_key, :the_uuid)
.exactly(3).times
# At push 10, 20, ... (except those above)
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(resource.id, :incremental_repack, :the_lease_key, :the_uuid)
+ expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :incremental_repack, :the_lease_key, :the_uuid)
.exactly(16).times
# At push 6, 12, 18, ... (except those above)
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(resource.id, :pack_refs, :the_lease_key, :the_uuid)
+ expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :pack_refs, :the_lease_key, :the_uuid)
.exactly(27).times
201.times do
@@ -90,7 +90,7 @@ RSpec.shared_examples 'housekeeps repository' do
allow(housekeeping).to receive(:try_obtain_lease).and_return(:gc_uuid)
allow(housekeeping).to receive(:lease_key).and_return(:gc_lease_key)
- expect(GitGarbageCollectWorker).to receive(:perform_async).with(resource.id, :gc, :gc_lease_key, :gc_uuid).twice
+ expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :gc, :gc_lease_key, :gc_uuid).twice
2.times do
housekeeping.execute
diff --git a/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb b/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb
index d70ed707822..fac9f1d6253 100644
--- a/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb
@@ -3,8 +3,12 @@
RSpec.shared_examples 'timebox(milestone or iteration) resource events creator' do |timebox_event_class|
let_it_be(:user) { create(:user) }
+ before do
+ resource.system_note_timestamp = created_at_time
+ end
+
context 'when milestone/iteration is added' do
- let(:service) { described_class.new(resource, user, add_timebox_args) }
+ let(:service) { described_class.new(resource, user, **add_timebox_args) }
before do
set_timebox(timebox_event_class, timebox)
@@ -18,7 +22,7 @@ RSpec.shared_examples 'timebox(milestone or iteration) resource events creator'
end
context 'when milestone/iteration is removed' do
- let(:service) { described_class.new(resource, user, remove_timebox_args) }
+ let(:service) { described_class.new(resource, user, **remove_timebox_args) }
before do
set_timebox(timebox_event_class, nil)
diff --git a/spec/support/shared_examples/services/snippets_shared_examples.rb b/spec/support/shared_examples/services/snippets_shared_examples.rb
index 4a08c0d4365..10add3a7299 100644
--- a/spec/support/shared_examples/services/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/services/snippets_shared_examples.rb
@@ -1,42 +1,56 @@
# frozen_string_literal: true
-RSpec.shared_examples 'snippets spam check is performed' do
- shared_examples 'marked as spam' do
- it 'marks a snippet as spam' do
- expect(snippet).to be_spam
- end
+RSpec.shared_examples 'checking spam' do
+ let(:request) { double(:request) }
+ let(:api) { true }
+ let(:captcha_response) { 'abc123' }
+ let(:spam_log_id) { 1 }
+ let(:disable_spam_action_service) { false }
- it 'invalidates the snippet' do
- expect(snippet).to be_invalid
- end
+ let(:extra_opts) do
+ {
+ request: request,
+ api: api,
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id,
+ disable_spam_action_service: disable_spam_action_service
+ }
+ end
- it 'creates a new spam_log' do
- expect { snippet }
- .to have_spam_log(title: snippet.title, noteable_type: snippet.class.name)
+ before do
+ allow_next_instance_of(UserAgentDetailService) do |instance|
+ allow(instance).to receive(:create)
end
+ end
- it 'assigns a spam_log to an issue' do
- expect(snippet.spam_log).to eq(SpamLog.last)
+ it 'executes SpamActionService' do
+ spam_params = Spam::SpamParams.new(
+ api: api,
+ captcha_response: captcha_response,
+ spam_log_id: spam_log_id
+ )
+ expect_next_instance_of(
+ Spam::SpamActionService,
+ {
+ spammable: kind_of(Snippet),
+ request: request,
+ user: an_instance_of(User),
+ action: action
+ }
+ ) do |instance|
+ expect(instance).to receive(:execute).with(spam_params: spam_params)
end
- end
- let(:extra_opts) do
- { visibility_level: Gitlab::VisibilityLevel::PUBLIC, request: double(:request, env: {}) }
+ subject
end
- before do
- expect_next_instance_of(Spam::AkismetService) do |akismet_service|
- expect(akismet_service).to receive_messages(spam?: true)
- end
- end
+ context 'when spam action service is disabled' do
+ let(:disable_spam_action_service) { true }
- [true, false, nil].each do |allow_possible_spam|
- context "when allow_possible_spam flag is #{allow_possible_spam.inspect}" do
- before do
- stub_feature_flags(allow_possible_spam: allow_possible_spam) unless allow_possible_spam.nil?
- end
+ it 'request parameter is not passed to the service' do
+ expect(Spam::SpamActionService).not_to receive(:new)
- it_behaves_like 'marked as spam'
+ subject
end
end
end
diff --git a/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb b/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb
new file mode 100644
index 00000000000..f2314793cb4
--- /dev/null
+++ b/spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb
@@ -0,0 +1,320 @@
+# frozen_string_literal: true
+
+require 'fileutils'
+
+RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
+ include GitHelpers
+
+ let!(:lease_uuid) { SecureRandom.uuid }
+ let!(:lease_key) { "resource_housekeeping:#{resource.id}" }
+ let(:params) { [resource.id, task, lease_key, lease_uuid] }
+ let(:shell) { Gitlab::Shell.new }
+ let(:repository) { resource.repository }
+ let(:statistics_service_klass) { nil }
+
+ subject { described_class.new }
+
+ before do
+ allow(subject).to receive(:find_resource).and_return(resource)
+ end
+
+ shared_examples 'it calls Gitaly' do
+ specify do
+ repository_service = instance_double(Gitlab::GitalyClient::RepositoryService)
+
+ expect(subject).to receive(:get_gitaly_client).with(task, repository.raw_repository).and_return(repository_service)
+ expect(repository_service).to receive(gitaly_task)
+
+ subject.perform(*params)
+ end
+ end
+
+ shared_examples 'it updates the resource statistics' do
+ it 'updates the resource statistics' do
+ expect_next_instance_of(statistics_service_klass, anything, nil, statistics: statistics_keys) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ subject.perform(*params)
+ end
+
+ it 'does nothing if the database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+
+ expect(statistics_service_klass).not_to receive(:new)
+
+ subject.perform(*params)
+ end
+ end
+
+ describe '#perform', :aggregate_failures do
+ let(:gitaly_task) { :garbage_collect }
+ let(:task) { :gc }
+
+ context 'with active lease_uuid' do
+ before do
+ allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ end
+
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the resource statistics' if update_statistics
+
+ it "flushes ref caches when the task if 'gc'" do
+ expect(subject).to receive(:renew_lease).with(lease_key, lease_uuid).and_call_original
+ expect(repository).to receive(:expire_branches_cache).and_call_original
+ expect(repository).to receive(:branch_names).and_call_original
+ expect(repository).to receive(:has_visible_content?).and_call_original
+ expect(repository.raw_repository).to receive(:has_visible_content?).and_call_original
+
+ subject.perform(*params)
+ end
+
+ it 'handles gRPC errors' do
+ allow_next_instance_of(Gitlab::GitalyClient::RepositoryService, repository.raw_repository) do |instance|
+ allow(instance).to receive(:garbage_collect).and_raise(GRPC::NotFound)
+ end
+
+ expect { subject.perform(*params) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
+ end
+ end
+
+ context 'with different lease than the active one' do
+ before do
+ allow(subject).to receive(:get_lease_uuid).and_return(SecureRandom.uuid)
+ end
+
+ it 'returns silently' do
+ expect(repository).not_to receive(:expire_branches_cache).and_call_original
+ expect(repository).not_to receive(:branch_names).and_call_original
+ expect(repository).not_to receive(:has_visible_content?).and_call_original
+
+ subject.perform(*params)
+ end
+ end
+
+ context 'with no active lease' do
+ let(:params) { [resource.id] }
+
+ before do
+ allow(subject).to receive(:get_lease_uuid).and_return(false)
+ end
+
+ context 'when is able to get the lease' do
+ before do
+ allow(subject).to receive(:try_obtain_lease).and_return(SecureRandom.uuid)
+ end
+
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the resource statistics' if update_statistics
+
+ it "flushes ref caches when the task if 'gc'" do
+ expect(subject).to receive(:get_lease_uuid).with("git_gc:#{task}:#{expected_default_lease}").and_return(false)
+ expect(repository).to receive(:expire_branches_cache).and_call_original
+ expect(repository).to receive(:branch_names).and_call_original
+ expect(repository).to receive(:has_visible_content?).and_call_original
+ expect(repository.raw_repository).to receive(:has_visible_content?).and_call_original
+
+ subject.perform(*params)
+ end
+ end
+
+ context 'when no lease can be obtained' do
+ it 'returns silently' do
+ expect(subject).to receive(:try_obtain_lease).and_return(false)
+
+ expect(subject).not_to receive(:command)
+ expect(repository).not_to receive(:expire_branches_cache).and_call_original
+ expect(repository).not_to receive(:branch_names).and_call_original
+ expect(repository).not_to receive(:has_visible_content?).and_call_original
+
+ subject.perform(*params)
+ end
+ end
+ end
+
+ context 'repack_full' do
+ let(:task) { :full_repack }
+ let(:gitaly_task) { :repack_full }
+
+ before do
+ expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ end
+
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the resource statistics' if update_statistics
+ end
+
+ context 'pack_refs' do
+ let(:task) { :pack_refs }
+ let(:gitaly_task) { :pack_refs }
+
+ before do
+ expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ end
+
+ it 'calls Gitaly' do
+ repository_service = instance_double(Gitlab::GitalyClient::RefService)
+
+ expect(subject).to receive(:get_gitaly_client).with(task, repository.raw_repository).and_return(repository_service)
+ expect(repository_service).to receive(gitaly_task)
+
+ subject.perform(*params)
+ end
+
+ it 'does not update the resource statistics' do
+ expect(statistics_service_klass).not_to receive(:new)
+
+ subject.perform(*params)
+ end
+ end
+
+ context 'repack_incremental' do
+ let(:task) { :incremental_repack }
+ let(:gitaly_task) { :repack_incremental }
+
+ before do
+ expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ end
+
+ it_behaves_like 'it calls Gitaly'
+ it_behaves_like 'it updates the resource statistics' if update_statistics
+ end
+
+ shared_examples 'gc tasks' do
+ before do
+ allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ allow(subject).to receive(:bitmaps_enabled?).and_return(bitmaps_enabled)
+ end
+
+ it 'incremental repack adds a new packfile' do
+ create_objects(resource)
+ before_packs = packs(resource)
+
+ expect(before_packs.count).to be >= 1
+
+ subject.perform(resource.id, 'incremental_repack', lease_key, lease_uuid)
+ after_packs = packs(resource)
+
+ # Exactly one new pack should have been created
+ expect(after_packs.count).to eq(before_packs.count + 1)
+
+ # Previously existing packs are still around
+ expect(before_packs & after_packs).to eq(before_packs)
+ end
+
+ it 'full repack consolidates into 1 packfile' do
+ create_objects(resource)
+ subject.perform(resource.id, 'incremental_repack', lease_key, lease_uuid)
+ before_packs = packs(resource)
+
+ expect(before_packs.count).to be >= 2
+
+ subject.perform(resource.id, 'full_repack', lease_key, lease_uuid)
+ after_packs = packs(resource)
+
+ expect(after_packs.count).to eq(1)
+
+ # Previously existing packs should be gone now
+ expect(after_packs - before_packs).to eq(after_packs)
+
+ expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled)
+ end
+
+ it 'gc consolidates into 1 packfile and updates packed-refs' do
+ create_objects(resource)
+ before_packs = packs(resource)
+ before_packed_refs = packed_refs(resource)
+
+ expect(before_packs.count).to be >= 1
+
+ # It's quite difficult to use `expect_next_instance_of` in this place
+ # because the RepositoryService is instantiated several times to do
+ # some repository calls like `exists?`, `create_repository`, ... .
+ # Therefore, since we're instantiating the object several times,
+ # RSpec has troubles figuring out which instance is the next and which
+ # one we want to mock.
+ # Besides, at this point, we actually want to perform the call to Gitaly,
+ # otherwise we would just use `instance_double` like in other parts of the
+ # spec file.
+ expect_any_instance_of(Gitlab::GitalyClient::RepositoryService) # rubocop:disable RSpec/AnyInstanceOf
+ .to receive(:garbage_collect)
+ .with(bitmaps_enabled, prune: false)
+ .and_call_original
+
+ subject.perform(resource.id, 'gc', lease_key, lease_uuid)
+ after_packed_refs = packed_refs(resource)
+ after_packs = packs(resource)
+
+ expect(after_packs.count).to eq(1)
+
+ # Previously existing packs should be gone now
+ expect(after_packs - before_packs).to eq(after_packs)
+
+ # The packed-refs file should have been updated during 'git gc'
+ expect(before_packed_refs).not_to eq(after_packed_refs)
+
+ expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled)
+ end
+
+ it 'cleans up repository after finishing' do
+ expect(resource).to receive(:cleanup).and_call_original
+
+ subject.perform(resource.id, 'gc', lease_key, lease_uuid)
+ end
+
+ it 'prune calls garbage_collect with the option prune: true' do
+ repository_service = instance_double(Gitlab::GitalyClient::RepositoryService)
+
+ expect(subject).to receive(:get_gitaly_client).with(:prune, repository.raw_repository).and_return(repository_service)
+ expect(repository_service).to receive(:garbage_collect).with(bitmaps_enabled, prune: true)
+
+ subject.perform(resource.id, 'prune', lease_key, lease_uuid)
+ end
+
+ # Create a new commit on a random new branch
+ def create_objects(resource)
+ rugged = rugged_repo(resource.repository)
+ old_commit = rugged.branches.first.target
+ new_commit_sha = Rugged::Commit.create(
+ rugged,
+ message: "hello world #{SecureRandom.hex(6)}",
+ author: { email: 'foo@bar', name: 'baz' },
+ committer: { email: 'foo@bar', name: 'baz' },
+ tree: old_commit.tree,
+ parents: [old_commit]
+ )
+ rugged.references.create("refs/heads/#{SecureRandom.hex(6)}", new_commit_sha)
+ end
+
+ def packs(resource)
+ Dir["#{path_to_repo}/objects/pack/*.pack"]
+ end
+
+ def packed_refs(resource)
+ path = File.join(path_to_repo, 'packed-refs')
+ FileUtils.touch(path)
+ File.read(path)
+ end
+
+ def path_to_repo
+ @path_to_repo ||= File.join(TestEnv.repos_path, resource.repository.relative_path)
+ end
+
+ def bitmap_path(pack)
+ pack.sub(/\.pack\z/, '.bitmap')
+ end
+ end
+
+ context 'with bitmaps enabled' do
+ let(:bitmaps_enabled) { true }
+
+ include_examples 'gc tasks'
+ end
+
+ context 'with bitmaps disabled' do
+ let(:bitmaps_enabled) { false }
+
+ include_examples 'gc tasks'
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/cleanup_rake_spec.rb b/spec/tasks/gitlab/cleanup_rake_spec.rb
index dc460611169..08d8651dcef 100644
--- a/spec/tasks/gitlab/cleanup_rake_spec.rb
+++ b/spec/tasks/gitlab/cleanup_rake_spec.rb
@@ -109,8 +109,7 @@ RSpec.describe 'gitlab:cleanup rake tasks' do
it 'passes dry_run correctly' do
expect(Gitlab::Cleanup::OrphanJobArtifactFiles)
.to receive(:new)
- .with(limit: anything,
- dry_run: false,
+ .with(dry_run: false,
niceness: anything,
logger: anything)
.and_call_original
@@ -145,7 +144,6 @@ RSpec.describe 'gitlab:cleanup rake tasks' do
expect(Gitlab::Cleanup::OrphanLfsFileReferences)
.to receive(:new)
.with(project,
- limit: anything,
dry_run: false,
logger: anything)
.and_call_original
@@ -153,24 +151,6 @@ RSpec.describe 'gitlab:cleanup rake tasks' do
rake_task
end
end
-
- context 'with LIMIT set to 100' do
- before do
- stub_env('LIMIT', '100')
- end
-
- it 'passes limit as integer' do
- expect(Gitlab::Cleanup::OrphanLfsFileReferences)
- .to receive(:new)
- .with(project,
- limit: 100,
- dry_run: true,
- logger: anything)
- .and_call_original
-
- rake_task
- end
- end
end
describe 'gitlab:cleanup:orphan_lfs_files' do
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index edfdb44022b..d1f4a12d8fc 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -297,6 +297,57 @@ RSpec.describe 'gitlab:db namespace rake task' do
end
end
+ describe '#migrate_with_instrumentation' do
+ subject { run_rake_task('gitlab:db:migration_testing', "[#{filename}]") }
+
+ let(:ctx) { double('ctx', migrations: all_migrations, schema_migration: double, get_all_versions: existing_versions) }
+ let(:instrumentation) { instance_double(Gitlab::Database::Migrations::Instrumentation, observations: observations) }
+ let(:existing_versions) { [1] }
+ let(:all_migrations) { [double('migration1', version: 1), pending_migration] }
+ let(:pending_migration) { double('migration2', version: 2) }
+ let(:filename) { 'results-file.json'}
+ let(:buffer) { StringIO.new }
+ let(:observations) { %w[some data] }
+
+ before do
+ allow(ActiveRecord::Base.connection).to receive(:migration_context).and_return(ctx)
+ allow(Gitlab::Database::Migrations::Instrumentation).to receive(:new).and_return(instrumentation)
+ allow(ActiveRecord::Migrator).to receive_message_chain('new.run').with(any_args).with(no_args)
+
+ allow(instrumentation).to receive(:observe).and_yield
+
+ allow(File).to receive(:open).with(filename, 'wb+').and_yield(buffer)
+ end
+
+ it 'fails when given no filename argument' do
+ expect { run_rake_task('gitlab:db:migration_testing') }.to raise_error(/specify result_file/)
+ end
+
+ it 'fails when the given file already exists' do
+ expect(File).to receive(:exist?).with(filename).and_return(true)
+
+ expect { subject }.to raise_error(/File exists/)
+ end
+
+ it 'instruments the pending migration' do
+ expect(instrumentation).to receive(:observe).with(2).and_yield
+
+ subject
+ end
+
+ it 'executes the pending migration' do
+ expect(ActiveRecord::Migrator).to receive_message_chain('new.run').with(:up, ctx.migrations, ctx.schema_migration, pending_migration.version).with(no_args)
+
+ subject
+ end
+
+ it 'writes observations out to JSON file' do
+ subject
+
+ expect(buffer.string).to eq(observations.to_json)
+ 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/git_rake_spec.rb b/spec/tasks/gitlab/git_rake_spec.rb
index 4d89b126c9e..50ec2632d83 100644
--- a/spec/tasks/gitlab/git_rake_spec.rb
+++ b/spec/tasks/gitlab/git_rake_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe 'gitlab:git rake tasks' do
before do
Rake.application.rake_require 'tasks/gitlab/git'
- allow_any_instance_of(String).to receive(:color) { |string, _color| string }
-
stub_warn_user_is_not_gitlab
end
diff --git a/spec/tasks/gitlab/pages_rake_spec.rb b/spec/tasks/gitlab/pages_rake_spec.rb
index 76808f52890..08194f4d1c9 100644
--- a/spec/tasks/gitlab/pages_rake_spec.rb
+++ b/spec/tasks/gitlab/pages_rake_spec.rb
@@ -2,66 +2,80 @@
require 'rake_helper'
-RSpec.describe 'gitlab:pages:migrate_legacy_storagerake task' do
+RSpec.describe 'gitlab:pages' do
before(:context) do
Rake.application.rake_require 'tasks/gitlab/pages'
end
- subject { run_rake_task('gitlab:pages:migrate_legacy_storage') }
+ describe 'migrate_legacy_storage task' do
+ subject { run_rake_task('gitlab:pages:migrate_legacy_storage') }
- let(:project) { create(:project) }
+ it 'calls migration service' do
+ expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
+ migration_threads: 3,
+ batch_size: 10,
+ ignore_invalid_entries: false) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
- it 'does not try to migrate pages if pages are not deployed' do
- expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+ subject
+ end
- subject
- end
+ it 'uses PAGES_MIGRATION_THREADS environment variable' do
+ stub_env('PAGES_MIGRATION_THREADS', '5')
- context 'when pages are marked as deployed' do
- before do
- project.mark_pages_as_deployed
+ expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
+ migration_threads: 5,
+ batch_size: 10,
+ ignore_invalid_entries: false) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ subject
end
- context 'when pages directory does not exist' do
- it 'tries to migrate the project, but does not crash' do
- expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project) do |service|
- expect(service).to receive(:execute).and_call_original
- end
+ it 'uses PAGES_MIGRATION_BATCH_SIZE environment variable' do
+ stub_env('PAGES_MIGRATION_BATCH_SIZE', '100')
- subject
+ expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
+ migration_threads: 3,
+ batch_size: 100,
+ ignore_invalid_entries: false) do |service|
+ expect(service).to receive(:execute).and_call_original
end
+
+ subject
end
- context 'when pages directory exists on disk' do
- before do
- FileUtils.mkdir_p File.join(project.pages_path, "public")
- File.open(File.join(project.pages_path, "public/index.html"), "w") do |f|
- f.write("Hello!")
- end
+ it 'uses PAGES_MIGRATION_IGNORE_INVALID_ENTRIES environment variable' do
+ stub_env('PAGES_MIGRATION_IGNORE_INVALID_ENTRIES', 'true')
+
+ expect_next_instance_of(::Pages::MigrateFromLegacyStorageService, anything,
+ migration_threads: 3,
+ batch_size: 10,
+ ignore_invalid_entries: true) do |service|
+ expect(service).to receive(:execute).and_call_original
end
- it 'migrates pages projects without deployments' do
- expect_next_instance_of(::Pages::MigrateLegacyStorageToDeploymentService, project) do |service|
- expect(service).to receive(:execute).and_call_original
- end
+ subject
+ end
+ end
+
+ describe 'clean_migrated_zip_storage task' do
+ it 'removes only migrated deployments' do
+ regular_deployment = create(:pages_deployment)
+ migrated_deployment = create(:pages_deployment, :migrated)
- expect do
- subject
- end.to change { project.pages_metadatum.reload.pages_deployment }.from(nil)
- end
+ regular_deployment.project.update_pages_deployment!(regular_deployment)
+ migrated_deployment.project.update_pages_deployment!(migrated_deployment)
- context 'when deployed already exists for the project' do
- before do
- deployment = create(:pages_deployment, project: project)
- project.set_first_pages_deployment!(deployment)
- end
+ expect(PagesDeployment.all).to contain_exactly(regular_deployment, migrated_deployment)
- it 'does not try to migrate project' do
- expect(::Pages::MigrateLegacyStorageToDeploymentService).not_to receive(:new)
+ run_rake_task('gitlab:pages:clean_migrated_zip_storage')
- subject
- end
- end
+ expect(PagesDeployment.all).to contain_exactly(regular_deployment)
+ expect(PagesDeployment.find_by_id(regular_deployment.id)).not_to be_nil
+ expect(PagesDeployment.find_by_id(migrated_deployment.id)).to be_nil
end
end
end
diff --git a/spec/tasks/gitlab/password_rake_spec.rb b/spec/tasks/gitlab/password_rake_spec.rb
new file mode 100644
index 00000000000..d5320f3b4af
--- /dev/null
+++ b/spec/tasks/gitlab/password_rake_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:password rake tasks' do
+ let_it_be(:user_1) { create(:user, username: 'foobar', password: 'initial_password') }
+
+ def stub_username(username)
+ allow(Gitlab::TaskHelpers).to receive(:prompt).with('Enter username: ').and_return(username)
+ end
+
+ def stub_password(password, confirmation = nil)
+ confirmation ||= password
+ allow(Gitlab::TaskHelpers).to receive(:prompt_for_password).and_return(password)
+ allow(Gitlab::TaskHelpers).to receive(:prompt_for_password).with('Confirm password: ').and_return(confirmation)
+ end
+
+ before do
+ Rake.application.rake_require 'tasks/gitlab/password'
+
+ stub_username('foobar')
+ stub_password('secretpassword')
+ end
+
+ describe ':reset' do
+ context 'when all inputs are correct' do
+ it 'updates the password properly' do
+ run_rake_task('gitlab:password:reset', user_1.username)
+ expect(user_1.reload.valid_password?('secretpassword')).to eq(true)
+ end
+ end
+
+ context 'when username is not provided' do
+ it 'asks for username' do
+ expect(Gitlab::TaskHelpers).to receive(:prompt).with('Enter username: ')
+
+ run_rake_task('gitlab:password:reset')
+ end
+
+ context 'when username is empty' do
+ it 'aborts with an error' do
+ stub_username('')
+ expect { run_rake_task('gitlab:password:reset') }.to raise_error(/Username can not be empty./)
+ end
+ end
+ end
+
+ context 'when username is passed as argument' do
+ it 'does not ask for username' do
+ expect(Gitlab::TaskHelpers).not_to receive(:prompt)
+
+ run_rake_task('gitlab:password:reset', 'foobar')
+ end
+ end
+
+ context 'when passwords do not match' do
+ before do
+ stub_password('randompassword', 'differentpassword')
+ end
+
+ it 'aborts with an error' do
+ expect { run_rake_task('gitlab:password:reset') }.to raise_error(%r{Unable to change password of the user with username foobar.\nPassword confirmation doesn't match Password})
+ end
+ end
+
+ context 'when user cannot be found' do
+ before do
+ stub_username('nonexistentuser')
+ end
+
+ it 'aborts with an error' do
+ expect { run_rake_task('gitlab:password:reset') }.to raise_error(/Unable to find user with username nonexistentuser./)
+ end
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/terraform/migrate_rake_spec.rb b/spec/tasks/gitlab/terraform/migrate_rake_spec.rb
new file mode 100644
index 00000000000..4188521df8e
--- /dev/null
+++ b/spec/tasks/gitlab/terraform/migrate_rake_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:terraform_states' do
+ let_it_be(:version) { create(:terraform_state_version) }
+
+ let(:logger) { instance_double(Logger) }
+ let(:helper) { double }
+
+ before(:all) do
+ Rake.application.rake_require 'tasks/gitlab/terraform/migrate'
+ end
+
+ before do
+ allow(Logger).to receive(:new).with(STDOUT).and_return(logger)
+ end
+
+ describe 'gitlab:terraform_states:migrate' do
+ subject { run_rake_task('gitlab:terraform_states:migrate') }
+
+ it 'invokes the migration helper to move files to object storage' do
+ expect(Gitlab::Terraform::StateMigrationHelper).to receive(:migrate_to_remote_storage).and_yield(version)
+ expect(logger).to receive(:info).with('Starting transfer of Terraform states to object storage')
+ expect(logger).to receive(:info).with(/Transferred Terraform state version ID #{version.id}/)
+
+ subject
+ end
+
+ context 'an error is raised while migrating' do
+ let(:error_message) { 'Something went wrong' }
+
+ before do
+ allow(Gitlab::Terraform::StateMigrationHelper).to receive(:migrate_to_remote_storage).and_raise(StandardError, error_message)
+ end
+
+ it 'logs the error' do
+ expect(logger).to receive(:info).with('Starting transfer of Terraform states to object storage')
+ expect(logger).to receive(:error).with("Failed to migrate: #{error_message}")
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/base_linter_spec.rb b/spec/tooling/danger/base_linter_spec.rb
new file mode 100644
index 00000000000..54d8f3dc1f7
--- /dev/null
+++ b/spec/tooling/danger/base_linter_spec.rb
@@ -0,0 +1,192 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/base_linter'
+
+RSpec.describe Tooling::Danger::BaseLinter do
+ let(:commit_class) do
+ Struct.new(:message, :sha, :diff_parent)
+ end
+
+ let(:commit_message) { 'A commit message' }
+ let(:commit) { commit_class.new(commit_message, anything, anything) }
+
+ subject(:commit_linter) { described_class.new(commit) }
+
+ describe '#failed?' do
+ context 'with no failures' do
+ it { expect(commit_linter).not_to be_failed }
+ end
+
+ context 'with failures' do
+ before do
+ commit_linter.add_problem(:subject_too_long, described_class.subject_description)
+ end
+
+ it { expect(commit_linter).to be_failed }
+ end
+ end
+
+ describe '#add_problem' do
+ it 'stores messages in #failures' do
+ commit_linter.add_problem(:subject_too_long, '%s')
+
+ expect(commit_linter.problems).to eq({ subject_too_long: described_class.problems_mapping[:subject_too_long] })
+ end
+ end
+
+ shared_examples 'a valid commit' do
+ it 'does not have any problem' do
+ commit_linter.lint_subject
+
+ expect(commit_linter.problems).to be_empty
+ end
+ end
+
+ describe '#lint_subject' do
+ context 'when subject valid' do
+ it_behaves_like 'a valid commit'
+ end
+
+ context 'when subject is too short' do
+ let(:commit_message) { 'A B' }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:subject_too_short, described_class.subject_description)
+
+ commit_linter.lint_subject
+ end
+ end
+
+ context 'when subject is too long' do
+ let(:commit_message) { 'A B ' + 'C' * described_class::MAX_LINE_LENGTH }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:subject_too_long, described_class.subject_description)
+
+ commit_linter.lint_subject
+ end
+ end
+
+ context 'when ignoring length issues for subject having not-ready wording' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:final_message) { 'A B C' }
+
+ context 'when used as prefix' do
+ where(prefix: [
+ 'WIP: ',
+ 'WIP:',
+ 'wIp:',
+ '[WIP] ',
+ '[WIP]',
+ '[draft]',
+ '[draft] ',
+ '(draft)',
+ '(draft) ',
+ 'draft - ',
+ 'draft: ',
+ 'draft:',
+ 'DRAFT:'
+ ])
+
+ with_them do
+ it 'does not have any problems' do
+ commit_message = prefix + final_message + 'D' * (described_class::MAX_LINE_LENGTH - final_message.size)
+ commit = commit_class.new(commit_message, anything, anything)
+
+ linter = described_class.new(commit).lint_subject
+
+ expect(linter.problems).to be_empty
+ end
+ end
+ end
+
+ context 'when used as suffix' do
+ where(suffix: %w[WIP draft])
+
+ with_them do
+ it 'does not have any problems' do
+ commit_message = final_message + 'D' * (described_class::MAX_LINE_LENGTH - final_message.size) + suffix
+ commit = commit_class.new(commit_message, anything, anything)
+
+ linter = described_class.new(commit).lint_subject
+
+ expect(linter.problems).to be_empty
+ end
+ end
+ end
+ end
+
+ context 'when subject does not have enough words and is too long' do
+ let(:commit_message) { 'A ' + 'B' * described_class::MAX_LINE_LENGTH }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:subject_too_short, described_class.subject_description)
+ expect(commit_linter).to receive(:add_problem).with(:subject_too_long, described_class.subject_description)
+
+ commit_linter.lint_subject
+ end
+ end
+
+ context 'when subject starts with lowercase' do
+ let(:commit_message) { 'a B C' }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:subject_starts_with_lowercase, described_class.subject_description)
+
+ commit_linter.lint_subject
+ end
+ end
+
+ [
+ '[ci skip] A commit message',
+ '[Ci skip] A commit message',
+ '[API] A commit message',
+ 'api: A commit message',
+ 'API: A commit message',
+ 'API: a commit message',
+ 'API: a commit message'
+ ].each do |message|
+ context "when subject is '#{message}'" do
+ let(:commit_message) { message }
+
+ it 'does not add a problem' do
+ expect(commit_linter).not_to receive(:add_problem)
+
+ commit_linter.lint_subject
+ end
+ end
+ end
+
+ [
+ '[ci skip]A commit message',
+ '[Ci skip] A commit message',
+ '[ci skip] a commit message',
+ 'api: a commit message',
+ '! A commit message'
+ ].each do |message|
+ context "when subject is '#{message}'" do
+ let(:commit_message) { message }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:subject_starts_with_lowercase, described_class.subject_description)
+
+ commit_linter.lint_subject
+ end
+ end
+ end
+
+ context 'when subject ends with a period' do
+ let(:commit_message) { 'A B C.' }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:subject_ends_with_a_period, described_class.subject_description)
+
+ commit_linter.lint_subject
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/changelog_spec.rb b/spec/tooling/danger/changelog_spec.rb
new file mode 100644
index 00000000000..c0eca67ce92
--- /dev/null
+++ b/spec/tooling/danger/changelog_spec.rb
@@ -0,0 +1,228 @@
+# frozen_string_literal: true
+
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/changelog'
+
+RSpec.describe Tooling::Danger::Changelog do
+ include DangerSpecHelper
+
+ let(:added_files) { nil }
+ let(:fake_git) { double('fake-git', added_files: added_files) }
+
+ let(:mr_labels) { nil }
+ let(:mr_json) { nil }
+ let(:fake_gitlab) { double('fake-gitlab', mr_labels: mr_labels, mr_json: mr_json) }
+
+ let(:changes_by_category) { nil }
+ let(:sanitize_mr_title) { nil }
+ let(:ee?) { false }
+ let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, sanitize_mr_title: sanitize_mr_title, ee?: ee?) }
+
+ let(:fake_danger) { new_fake_danger.include(described_class) }
+
+ subject(:changelog) { fake_danger.new(git: fake_git, gitlab: fake_gitlab, helper: fake_helper) }
+
+ describe '#required?' do
+ subject { changelog.required? }
+
+ context 'added files contain a migration' do
+ [
+ 'db/migrate/20200000000000_new_migration.rb',
+ 'db/post_migrate/20200000000000_new_migration.rb'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'added files do not contain a migration' do
+ [
+ 'app/models/model.rb',
+ 'app/assets/javascripts/file.js'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+ end
+
+ describe '#optional?' do
+ let(:category_with_changelog) { :backend }
+ let(:label_with_changelog) { 'frontend' }
+ let(:category_without_changelog) { Tooling::Danger::Changelog::NO_CHANGELOG_CATEGORIES.first }
+ let(:label_without_changelog) { Tooling::Danger::Changelog::NO_CHANGELOG_LABELS.first }
+
+ subject { changelog.optional? }
+
+ context 'when MR contains only categories requiring no changelog' do
+ let(:changes_by_category) { { category_without_changelog => nil } }
+ let(:mr_labels) { [] }
+
+ it 'is falsey' do
+ is_expected.to be_falsy
+ end
+ end
+
+ context 'when MR contains a label that require no changelog' do
+ let(:changes_by_category) { { category_with_changelog => nil } }
+ let(:mr_labels) { [label_with_changelog, label_without_changelog] }
+
+ it 'is falsey' do
+ is_expected.to be_falsy
+ end
+ end
+
+ context 'when MR contains a category that require changelog and a category that require no changelog' do
+ let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
+ let(:mr_labels) { [] }
+
+ it 'is truthy' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when MR contains a category that require changelog and a category that require no changelog with changelog label' do
+ let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
+ let(:mr_labels) { ['feature'] }
+
+ it 'is truthy' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when MR contains a category that require changelog and a category that require no changelog with no changelog label' do
+ let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
+ let(:mr_labels) { ['tooling'] }
+
+ it 'is truthy' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+
+ describe '#found' do
+ subject { changelog.found }
+
+ context 'added files contain a changelog' do
+ [
+ 'changelogs/unreleased/entry.yml',
+ 'ee/changelogs/unreleased/entry.yml'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'added files do not contain a changelog' do
+ [
+ 'app/models/model.rb',
+ 'app/assets/javascripts/file.js'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+ it { is_expected.to eq(nil) }
+ end
+ end
+ end
+
+ describe '#ee_changelog?' do
+ subject { changelog.ee_changelog? }
+
+ before do
+ allow(changelog).to receive(:found).and_return(file_path)
+ end
+
+ context 'is ee changelog' do
+ let(:file_path) { 'ee/changelogs/unreleased/entry.yml' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'is not ee changelog' do
+ let(:file_path) { 'changelogs/unreleased/entry.yml' }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '#modified_text' do
+ let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
+
+ subject { changelog.modified_text }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ let(:sanitize_mr_title) { 'Fake Title' }
+
+ specify do
+ expect(subject).to include('CHANGELOG.md was edited')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ end
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:sanitize_mr_title) { 'DRAFT: Fake Title' }
+
+ specify do
+ expect(subject).to include('CHANGELOG.md was edited')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ end
+ end
+ end
+
+ describe '#required_text' do
+ let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
+
+ subject { changelog.required_text }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ let(:sanitize_mr_title) { 'Fake Title' }
+
+ specify do
+ expect(subject).to include('CHANGELOG missing')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).not_to include('--ee')
+ end
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:sanitize_mr_title) { 'DRAFT: Fake Title' }
+
+ specify do
+ expect(subject).to include('CHANGELOG missing')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).not_to include('--ee')
+ end
+ end
+ end
+
+ describe '#optional_text' do
+ let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
+
+ subject { changelog.optional_text }
+
+ context "when title is not changed from sanitization", :aggregate_failures do
+ let(:sanitize_mr_title) { 'Fake Title' }
+
+ specify do
+ expect(subject).to include('CHANGELOG missing')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ end
+ end
+
+ context "when title needs sanitization", :aggregate_failures do
+ let(:sanitize_mr_title) { 'DRAFT: Fake Title' }
+
+ specify do
+ expect(subject).to include('CHANGELOG missing')
+ expect(subject).to include('bin/changelog -m 1234 "Fake Title"')
+ expect(subject).to include('bin/changelog --ee -m 1234 "Fake Title"')
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/commit_linter_spec.rb b/spec/tooling/danger/commit_linter_spec.rb
new file mode 100644
index 00000000000..694e524af21
--- /dev/null
+++ b/spec/tooling/danger/commit_linter_spec.rb
@@ -0,0 +1,241 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/commit_linter'
+
+RSpec.describe Tooling::Danger::CommitLinter do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:total_files_changed) { 2 }
+ let(:total_lines_changed) { 10 }
+ let(:stats) { { total: { files: total_files_changed, lines: total_lines_changed } } }
+ let(:diff_parent) { Struct.new(:stats).new(stats) }
+ let(:commit_class) do
+ Struct.new(:message, :sha, :diff_parent)
+ end
+
+ let(:commit_message) { 'A commit message' }
+ let(:commit_sha) { 'abcd1234' }
+ let(:commit) { commit_class.new(commit_message, commit_sha, diff_parent) }
+
+ subject(:commit_linter) { described_class.new(commit) }
+
+ describe '#fixup?' do
+ where(:commit_message, :is_fixup) do
+ 'A commit message' | false
+ 'fixup!' | true
+ 'fixup! A commit message' | true
+ 'squash!' | true
+ 'squash! A commit message' | true
+ end
+
+ with_them do
+ it 'is true when commit message starts with "fixup!" or "squash!"' do
+ expect(commit_linter.fixup?).to be(is_fixup)
+ end
+ end
+ end
+
+ describe '#suggestion?' do
+ where(:commit_message, :is_suggestion) do
+ 'A commit message' | false
+ 'Apply suggestion to' | true
+ 'Apply suggestion to "A commit message"' | true
+ end
+
+ with_them do
+ it 'is true when commit message starts with "Apply suggestion to"' do
+ expect(commit_linter.suggestion?).to be(is_suggestion)
+ end
+ end
+ end
+
+ describe '#merge?' do
+ where(:commit_message, :is_merge) do
+ 'A commit message' | false
+ 'Merge branch' | true
+ 'Merge branch "A commit message"' | true
+ end
+
+ with_them do
+ it 'is true when commit message starts with "Merge branch"' do
+ expect(commit_linter.merge?).to be(is_merge)
+ end
+ end
+ end
+
+ describe '#revert?' do
+ where(:commit_message, :is_revert) do
+ 'A commit message' | false
+ 'Revert' | false
+ 'Revert "' | true
+ 'Revert "A commit message"' | true
+ end
+
+ with_them do
+ it 'is true when commit message starts with "Revert \""' do
+ expect(commit_linter.revert?).to be(is_revert)
+ end
+ end
+ end
+
+ describe '#multi_line?' do
+ where(:commit_message, :is_multi_line) do
+ "A commit message" | false
+ "A commit message\n" | false
+ "A commit message\n\n" | false
+ "A commit message\n\nSigned-off-by: User Name <user@name.me>" | false
+ "A commit message\n\nWith details" | true
+ end
+
+ with_them do
+ it 'is true when commit message contains details' do
+ expect(commit_linter.multi_line?).to be(is_multi_line)
+ end
+ end
+ end
+
+ shared_examples 'a valid commit' do
+ it 'does not have any problem' do
+ commit_linter.lint
+
+ expect(commit_linter.problems).to be_empty
+ end
+ end
+
+ describe '#lint' do
+ describe 'separator' do
+ context 'when separator is missing' do
+ let(:commit_message) { "A B C\n" }
+
+ it_behaves_like 'a valid commit'
+ end
+
+ context 'when separator is a blank line' do
+ let(:commit_message) { "A B C\n\nMore details." }
+
+ it_behaves_like 'a valid commit'
+ end
+
+ context 'when separator is missing' do
+ let(:commit_message) { "A B C\nMore details." }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:separator_missing)
+
+ commit_linter.lint
+ end
+ end
+ end
+
+ describe 'details' do
+ context 'when details are valid' do
+ let(:commit_message) { "A B C\n\nMore details." }
+
+ it_behaves_like 'a valid commit'
+ end
+
+ context 'when no details are given and many files are changed' do
+ let(:total_files_changed) { described_class::MAX_CHANGED_FILES_IN_COMMIT + 1 }
+
+ it_behaves_like 'a valid commit'
+ end
+
+ context 'when no details are given and many lines are changed' do
+ let(:total_lines_changed) { described_class::MAX_CHANGED_LINES_IN_COMMIT + 1 }
+
+ it_behaves_like 'a valid commit'
+ end
+
+ context 'when no details are given and many files and lines are changed' do
+ let(:total_files_changed) { described_class::MAX_CHANGED_FILES_IN_COMMIT + 1 }
+ let(:total_lines_changed) { described_class::MAX_CHANGED_LINES_IN_COMMIT + 1 }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:details_too_many_changes)
+
+ commit_linter.lint
+ end
+ end
+
+ context 'when details exceeds the max line length' do
+ let(:commit_message) { "A B C\n\n" + 'D' * (described_class::MAX_LINE_LENGTH + 1) }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:details_line_too_long)
+
+ commit_linter.lint
+ end
+ end
+
+ context 'when details exceeds the max line length including URLs' do
+ let(:commit_message) do
+ "A B C\n\nsome message with https://example.com and https://gitlab.com" + 'D' * described_class::MAX_LINE_LENGTH
+ end
+
+ it_behaves_like 'a valid commit'
+ end
+ end
+
+ describe 'message' do
+ context 'when message includes a text emoji' do
+ let(:commit_message) { "A commit message :+1:" }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:message_contains_text_emoji)
+
+ commit_linter.lint
+ end
+ end
+
+ context 'when message includes a unicode emoji' do
+ let(:commit_message) { "A commit message 🚀" }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:message_contains_unicode_emoji)
+
+ commit_linter.lint
+ end
+ end
+
+ context 'when message includes a value that is surrounded by backticks' do
+ let(:commit_message) { "A commit message `%20`" }
+
+ it 'does not add a problem' do
+ expect(commit_linter).not_to receive(:add_problem)
+
+ commit_linter.lint
+ end
+ end
+
+ context 'when message includes a short reference' do
+ [
+ 'A commit message to fix #1234',
+ 'A commit message to fix !1234',
+ 'A commit message to fix &1234',
+ 'A commit message to fix %1234',
+ 'A commit message to fix gitlab#1234',
+ 'A commit message to fix gitlab!1234',
+ 'A commit message to fix gitlab&1234',
+ 'A commit message to fix gitlab%1234',
+ 'A commit message to fix gitlab-org/gitlab#1234',
+ 'A commit message to fix gitlab-org/gitlab!1234',
+ 'A commit message to fix gitlab-org/gitlab&1234',
+ 'A commit message to fix gitlab-org/gitlab%1234',
+ 'A commit message to fix "gitlab-org/gitlab%1234"',
+ 'A commit message to fix `gitlab-org/gitlab%1234'
+ ].each do |message|
+ let(:commit_message) { message }
+
+ it 'adds a problem' do
+ expect(commit_linter).to receive(:add_problem).with(:message_contains_short_reference)
+
+ commit_linter.lint
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/danger/danger_spec_helper.rb b/spec/tooling/danger/danger_spec_helper.rb
index b1e84b3c13d..b1e84b3c13d 100644
--- a/spec/lib/gitlab/danger/danger_spec_helper.rb
+++ b/spec/tooling/danger/danger_spec_helper.rb
diff --git a/spec/tooling/danger/emoji_checker_spec.rb b/spec/tooling/danger/emoji_checker_spec.rb
new file mode 100644
index 00000000000..bbd957b3d00
--- /dev/null
+++ b/spec/tooling/danger/emoji_checker_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+
+require_relative '../../../tooling/danger/emoji_checker'
+
+RSpec.describe Tooling::Danger::EmojiChecker do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '#includes_text_emoji?' do
+ where(:text, :includes_emoji) do
+ 'Hello World!' | false
+ ':+1:' | true
+ 'Hello World! :+1:' | true
+ end
+
+ with_them do
+ it 'is true when text includes a text emoji' do
+ expect(subject.includes_text_emoji?(text)).to be(includes_emoji)
+ end
+ end
+ end
+
+ describe '#includes_unicode_emoji?' do
+ where(:text, :includes_emoji) do
+ 'Hello World!' | false
+ '🚀' | true
+ 'Hello World! 🚀' | true
+ end
+
+ with_them do
+ it 'is true when text includes a text emoji' do
+ expect(subject.includes_unicode_emoji?(text)).to be(includes_emoji)
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/feature_flag_spec.rb b/spec/tooling/danger/feature_flag_spec.rb
new file mode 100644
index 00000000000..db63116cc37
--- /dev/null
+++ b/spec/tooling/danger/feature_flag_spec.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/feature_flag'
+
+RSpec.describe Tooling::Danger::FeatureFlag do
+ include DangerSpecHelper
+
+ let(:added_files) { nil }
+ let(:modified_files) { nil }
+ let(:deleted_files) { nil }
+ let(:fake_git) { double('fake-git', added_files: added_files, modified_files: modified_files, deleted_files: deleted_files) }
+
+ let(:mr_labels) { nil }
+ let(:mr_json) { nil }
+ let(:fake_gitlab) { double('fake-gitlab', mr_labels: mr_labels, mr_json: mr_json) }
+
+ let(:changes_by_category) { nil }
+ let(:sanitize_mr_title) { nil }
+ let(:ee?) { false }
+ let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, sanitize_mr_title: sanitize_mr_title, ee?: ee?) }
+
+ let(:fake_danger) { new_fake_danger.include(described_class) }
+
+ subject(:feature_flag) { fake_danger.new(git: fake_git, gitlab: fake_gitlab, helper: fake_helper) }
+
+ describe '#feature_flag_files' do
+ let(:feature_flag_files) do
+ [
+ 'config/feature_flags/development/entry.yml',
+ 'ee/config/feature_flags/ops/entry.yml'
+ ]
+ end
+
+ let(:other_files) do
+ [
+ 'app/models/model.rb',
+ 'app/assets/javascripts/file.js'
+ ]
+ end
+
+ shared_examples 'an array of Found objects' do |change_type|
+ it 'returns an array of Found objects' do
+ expect(feature_flag.feature_flag_files(change_type: change_type)).to contain_exactly(an_instance_of(described_class::Found), an_instance_of(described_class::Found))
+ expect(feature_flag.feature_flag_files(change_type: change_type).map(&:path)).to eq(feature_flag_files)
+ end
+ end
+
+ shared_examples 'an empty array' do |change_type|
+ it 'returns an array of Found objects' do
+ expect(feature_flag.feature_flag_files(change_type: change_type)).to be_empty
+ end
+ end
+
+ describe 'retrieves added feature flag files' do
+ context 'with added added feature flag files' do
+ let(:added_files) { feature_flag_files }
+
+ include_examples 'an array of Found objects', :added
+ end
+
+ context 'without added added feature flag files' do
+ let(:added_files) { other_files }
+
+ include_examples 'an empty array', :added
+ end
+ end
+
+ describe 'retrieves modified feature flag files' do
+ context 'with modified modified feature flag files' do
+ let(:modified_files) { feature_flag_files }
+
+ include_examples 'an array of Found objects', :modified
+ end
+
+ context 'without modified modified feature flag files' do
+ let(:modified_files) { other_files }
+
+ include_examples 'an empty array', :modified
+ end
+ end
+
+ describe 'retrieves deleted feature flag files' do
+ context 'with deleted deleted feature flag files' do
+ let(:deleted_files) { feature_flag_files }
+
+ include_examples 'an array of Found objects', :deleted
+ end
+
+ context 'without deleted deleted feature flag files' do
+ let(:deleted_files) { other_files }
+
+ include_examples 'an empty array', :deleted
+ end
+ end
+ end
+
+ describe described_class::Found do
+ let(:feature_flag_path) { 'config/feature_flags/development/entry.yml' }
+ let(:group) { 'group::source code' }
+ let(:raw_yaml) do
+ YAML.dump('group' => group)
+ end
+
+ subject(:found) { described_class.new(feature_flag_path) }
+
+ before do
+ allow(File).to receive(:read).and_call_original
+ expect(File).to receive(:read).with(feature_flag_path).and_return(raw_yaml)
+ end
+
+ describe '#raw' do
+ it 'returns the raw YAML' do
+ expect(found.raw).to eq(raw_yaml)
+ end
+ end
+
+ describe '#group' do
+ it 'returns the group found in the YAML' do
+ expect(found.group).to eq(group)
+ end
+ end
+
+ describe '#group_match_mr_label?' do
+ subject(:result) { found.group_match_mr_label?(mr_group_label) }
+
+ context 'when MR labels match FF group' do
+ let(:mr_group_label) { 'group::source code' }
+
+ specify { expect(result).to eq(true) }
+ end
+
+ context 'when MR labels does not match FF group' do
+ let(:mr_group_label) { 'group::access' }
+
+ specify { expect(result).to eq(false) }
+ end
+
+ context 'when group is nil' do
+ let(:group) { nil }
+
+ context 'and MR has no group label' do
+ let(:mr_group_label) { nil }
+
+ specify { expect(result).to eq(true) }
+ end
+
+ context 'and MR has a group label' do
+ let(:mr_group_label) { 'group::source code' }
+
+ specify { expect(result).to eq(false) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/helper_spec.rb b/spec/tooling/danger/helper_spec.rb
new file mode 100644
index 00000000000..c338d138352
--- /dev/null
+++ b/spec/tooling/danger/helper_spec.rb
@@ -0,0 +1,682 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/helper'
+
+RSpec.describe Tooling::Danger::Helper do
+ using RSpec::Parameterized::TableSyntax
+ include DangerSpecHelper
+
+ let(:fake_git) { double('fake-git') }
+
+ let(:mr_author) { nil }
+ let(:fake_gitlab) { double('fake-gitlab', mr_author: mr_author) }
+
+ let(:fake_danger) { new_fake_danger.include(described_class) }
+
+ subject(:helper) { fake_danger.new(git: fake_git, gitlab: fake_gitlab) }
+
+ describe '#gitlab_helper' do
+ context 'when gitlab helper is not available' do
+ let(:fake_gitlab) { nil }
+
+ it 'returns nil' do
+ expect(helper.gitlab_helper).to be_nil
+ end
+ end
+
+ context 'when gitlab helper is available' do
+ it 'returns the gitlab helper' do
+ expect(helper.gitlab_helper).to eq(fake_gitlab)
+ end
+ end
+
+ context 'when danger gitlab plugin is not available' do
+ it 'returns nil' do
+ invalid_danger = Class.new do
+ include Tooling::Danger::Helper
+ end.new
+
+ expect(invalid_danger.gitlab_helper).to be_nil
+ end
+ end
+ end
+
+ describe '#release_automation?' do
+ context 'when gitlab helper is not available' do
+ it 'returns false' do
+ expect(helper.release_automation?).to be_falsey
+ end
+ end
+
+ context 'when gitlab helper is available' do
+ context "but the MR author isn't the RELEASE_TOOLS_BOT" do
+ let(:mr_author) { 'johnmarston' }
+
+ it 'returns false' do
+ expect(helper.release_automation?).to be_falsey
+ end
+ end
+
+ context 'and the MR author is the RELEASE_TOOLS_BOT' do
+ let(:mr_author) { described_class::RELEASE_TOOLS_BOT }
+
+ it 'returns true' do
+ expect(helper.release_automation?).to be_truthy
+ end
+ end
+ end
+ end
+
+ describe '#all_changed_files' do
+ subject { helper.all_changed_files }
+
+ it 'interprets a list of changes from the danger git plugin' do
+ expect(fake_git).to receive(:added_files) { %w[a b c.old] }
+ expect(fake_git).to receive(:modified_files) { %w[d e] }
+ expect(fake_git)
+ .to receive(:renamed_files)
+ .at_least(:once)
+ .and_return([{ before: 'c.old', after: 'c.new' }])
+
+ is_expected.to contain_exactly('a', 'b', 'c.new', 'd', 'e')
+ end
+ end
+
+ describe '#changed_lines' do
+ subject { helper.changed_lines('changed_file.rb') }
+
+ before do
+ allow(fake_git).to receive(:diff_for_file).with('changed_file.rb').and_return(diff)
+ end
+
+ context 'when file has diff' do
+ let(:diff) { double(:diff, patch: "+ # New change here\n+ # New change there") }
+
+ it 'returns file changes' do
+ is_expected.to eq(['+ # New change here', '+ # New change there'])
+ end
+ end
+
+ context 'when file has no diff (renamed without changes)' do
+ let(:diff) { nil }
+
+ it 'returns a blank array' do
+ is_expected.to eq([])
+ end
+ end
+ end
+
+ describe "changed_files" do
+ it 'returns list of changed files matching given regex' do
+ expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb usage_data.rb])
+
+ expect(helper.changed_files(/usage_data/)).to contain_exactly('usage_data.rb')
+ end
+ end
+
+ describe '#all_ee_changes' do
+ subject { helper.all_ee_changes }
+
+ it 'returns all changed files starting with ee/' do
+ expect(helper).to receive(:all_changed_files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k])
+
+ is_expected.to match_array(%w[ee/wine.rb ee/lib/ido.rb])
+ end
+ end
+
+ describe '#ee?' do
+ subject { helper.ee? }
+
+ it 'returns true if CI_PROJECT_NAME if set to gitlab' do
+ stub_env('CI_PROJECT_NAME', 'gitlab')
+ expect(Dir).not_to receive(:exist?)
+
+ is_expected.to be_truthy
+ end
+
+ it 'delegates to CHANGELOG-EE.md existence if CI_PROJECT_NAME is set to something else' do
+ stub_env('CI_PROJECT_NAME', 'something else')
+ expect(Dir).to receive(:exist?).with(File.expand_path('../../../../ee', __dir__)) { true }
+
+ is_expected.to be_truthy
+ end
+
+ it 'returns true if ee exists' do
+ stub_env('CI_PROJECT_NAME', nil)
+ expect(Dir).to receive(:exist?).with(File.expand_path('../../../../ee', __dir__)) { true }
+
+ is_expected.to be_truthy
+ end
+
+ it "returns false if ee doesn't exist" do
+ stub_env('CI_PROJECT_NAME', nil)
+ expect(Dir).to receive(:exist?).with(File.expand_path('../../../../ee', __dir__)) { false }
+
+ is_expected.to be_falsy
+ end
+ end
+
+ describe '#project_name' do
+ subject { helper.project_name }
+
+ it 'returns gitlab if ee? returns true' do
+ expect(helper).to receive(:ee?) { true }
+
+ is_expected.to eq('gitlab')
+ end
+
+ it 'returns gitlab-ce if ee? returns false' do
+ expect(helper).to receive(:ee?) { false }
+
+ is_expected.to eq('gitlab-foss')
+ end
+ end
+
+ describe '#markdown_list' do
+ it 'creates a markdown list of items' do
+ items = %w[a b]
+
+ expect(helper.markdown_list(items)).to eq("* `a`\n* `b`")
+ end
+
+ it 'wraps items in <details> when there are more than 10 items' do
+ items = ('a'..'k').to_a
+
+ expect(helper.markdown_list(items)).to match(%r{<details>[^<]+</details>})
+ end
+ end
+
+ describe '#changes_by_category' do
+ it 'categorizes changed files' do
+ expect(fake_git).to receive(:added_files) { %w[foo foo.md foo.rb foo.js db/migrate/foo lib/gitlab/database/foo.rb qa/foo ee/changelogs/foo.yml] }
+ allow(fake_git).to receive(:modified_files) { [] }
+ allow(fake_git).to receive(:renamed_files) { [] }
+
+ expect(helper.changes_by_category).to eq(
+ backend: %w[foo.rb],
+ database: %w[db/migrate/foo lib/gitlab/database/foo.rb],
+ frontend: %w[foo.js],
+ none: %w[ee/changelogs/foo.yml foo.md],
+ qa: %w[qa/foo],
+ unknown: %w[foo]
+ )
+ end
+ end
+
+ describe '#categories_for_file' do
+ before do
+ allow(fake_git).to receive(:diff_for_file).with('usage_data.rb') { double(:diff, patch: "+ count(User.active)") }
+ end
+
+ where(:path, :expected_categories) do
+ 'usage_data.rb' | [:database, :backend]
+ 'doc/foo.md' | [:docs]
+ 'CONTRIBUTING.md' | [:docs]
+ 'LICENSE' | [:docs]
+ 'MAINTENANCE.md' | [:docs]
+ 'PHILOSOPHY.md' | [:docs]
+ 'PROCESS.md' | [:docs]
+ 'README.md' | [:docs]
+
+ 'ee/doc/foo' | [:unknown]
+ 'ee/README' | [:unknown]
+
+ 'app/assets/foo' | [:frontend]
+ 'app/views/foo' | [:frontend]
+ 'public/foo' | [:frontend]
+ 'scripts/frontend/foo' | [:frontend]
+ 'spec/javascripts/foo' | [:frontend]
+ 'spec/frontend/bar' | [:frontend]
+ 'vendor/assets/foo' | [:frontend]
+ 'babel.config.js' | [:frontend]
+ 'jest.config.js' | [:frontend]
+ 'package.json' | [:frontend]
+ 'yarn.lock' | [:frontend]
+ 'config/foo.js' | [:frontend]
+ 'config/deep/foo.js' | [:frontend]
+
+ 'ee/app/assets/foo' | [:frontend]
+ 'ee/app/views/foo' | [:frontend]
+ 'ee/spec/javascripts/foo' | [:frontend]
+ 'ee/spec/frontend/bar' | [:frontend]
+
+ '.gitlab/ci/frontend.gitlab-ci.yml' | %i[frontend engineering_productivity]
+
+ 'app/models/foo' | [:backend]
+ 'bin/foo' | [:backend]
+ 'config/foo' | [:backend]
+ 'lib/foo' | [:backend]
+ 'rubocop/foo' | [:backend]
+ '.rubocop.yml' | [:backend]
+ '.rubocop_todo.yml' | [:backend]
+ '.rubocop_manual_todo.yml' | [:backend]
+ 'spec/foo' | [:backend]
+ 'spec/foo/bar' | [:backend]
+
+ 'ee/app/foo' | [:backend]
+ 'ee/bin/foo' | [:backend]
+ 'ee/spec/foo' | [:backend]
+ 'ee/spec/foo/bar' | [:backend]
+
+ 'spec/features/foo' | [:test]
+ 'ee/spec/features/foo' | [:test]
+ 'spec/support/shared_examples/features/foo' | [:test]
+ 'ee/spec/support/shared_examples/features/foo' | [:test]
+ 'spec/support/shared_contexts/features/foo' | [:test]
+ 'ee/spec/support/shared_contexts/features/foo' | [:test]
+ 'spec/support/helpers/features/foo' | [:test]
+ 'ee/spec/support/helpers/features/foo' | [:test]
+
+ 'generator_templates/foo' | [:backend]
+ 'vendor/languages.yml' | [:backend]
+ 'file_hooks/examples/' | [:backend]
+
+ 'Gemfile' | [:backend]
+ 'Gemfile.lock' | [:backend]
+ 'Rakefile' | [:backend]
+ 'FOO_VERSION' | [:backend]
+
+ 'Dangerfile' | [:engineering_productivity]
+ 'danger/commit_messages/Dangerfile' | [:engineering_productivity]
+ 'ee/danger/commit_messages/Dangerfile' | [:engineering_productivity]
+ 'danger/commit_messages/' | [:engineering_productivity]
+ 'ee/danger/commit_messages/' | [:engineering_productivity]
+ '.gitlab-ci.yml' | [:engineering_productivity]
+ '.gitlab/ci/cng.gitlab-ci.yml' | [:engineering_productivity]
+ '.gitlab/ci/ee-specific-checks.gitlab-ci.yml' | [:engineering_productivity]
+ 'scripts/foo' | [:engineering_productivity]
+ 'tooling/danger/foo' | [:engineering_productivity]
+ 'ee/tooling/danger/foo' | [:engineering_productivity]
+ 'lefthook.yml' | [:engineering_productivity]
+ '.editorconfig' | [:engineering_productivity]
+ 'tooling/bin/find_foss_tests' | [:engineering_productivity]
+ '.codeclimate.yml' | [:engineering_productivity]
+ '.gitlab/CODEOWNERS' | [:engineering_productivity]
+
+ 'lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' | [:ci_template]
+ 'lib/gitlab/ci/templates/dotNET-Core.yml' | [:ci_template]
+
+ 'ee/FOO_VERSION' | [:unknown]
+
+ 'db/schema.rb' | [:database]
+ 'db/structure.sql' | [:database]
+ 'db/migrate/foo' | [:database]
+ 'db/post_migrate/foo' | [:database]
+ 'ee/db/migrate/foo' | [:database]
+ 'ee/db/post_migrate/foo' | [:database]
+ 'ee/db/geo/migrate/foo' | [:database]
+ 'ee/db/geo/post_migrate/foo' | [:database]
+ 'app/models/project_authorization.rb' | [:database]
+ 'app/services/users/refresh_authorized_projects_service.rb' | [:database]
+ 'lib/gitlab/background_migration.rb' | [:database]
+ 'lib/gitlab/background_migration/foo' | [:database]
+ 'ee/lib/gitlab/background_migration/foo' | [:database]
+ 'lib/gitlab/database.rb' | [:database]
+ 'lib/gitlab/database/foo' | [:database]
+ 'ee/lib/gitlab/database/foo' | [:database]
+ 'lib/gitlab/github_import.rb' | [:database]
+ 'lib/gitlab/github_import/foo' | [:database]
+ 'lib/gitlab/sql/foo' | [:database]
+ 'rubocop/cop/migration/foo' | [:database]
+
+ 'db/fixtures/foo.rb' | [:backend]
+ 'ee/db/fixtures/foo.rb' | [:backend]
+ 'doc/api/graphql/reference/gitlab_schema.graphql' | [:backend]
+ 'doc/api/graphql/reference/gitlab_schema.json' | [:backend]
+
+ 'qa/foo' | [:qa]
+ 'ee/qa/foo' | [:qa]
+
+ 'changelogs/foo' | [:none]
+ 'ee/changelogs/foo' | [:none]
+ 'locale/gitlab.pot' | [:none]
+
+ 'FOO' | [:unknown]
+ 'foo' | [:unknown]
+
+ 'foo/bar.rb' | [:backend]
+ 'foo/bar.js' | [:frontend]
+ 'foo/bar.txt' | [:none]
+ 'foo/bar.md' | [:none]
+ end
+
+ with_them do
+ subject { helper.categories_for_file(path) }
+
+ it { is_expected.to eq(expected_categories) }
+ end
+
+ context 'having specific changes' do
+ where(:expected_categories, :patch, :changed_files) do
+ [:database, :backend] | '+ count(User.active)' | ['usage_data.rb', 'lib/gitlab/usage_data.rb', 'ee/lib/ee/gitlab/usage_data.rb']
+ [:database, :backend] | '+ estimate_batch_distinct_count(User.active)' | ['usage_data.rb']
+ [:backend] | '+ alt_usage_data(User.active)' | ['usage_data.rb']
+ [:backend] | '+ count(User.active)' | ['user.rb']
+ [:backend] | '+ count(User.active)' | ['usage_data/topology.rb']
+ [:backend] | '+ foo_count(User.active)' | ['usage_data.rb']
+ end
+
+ with_them do
+ it 'has the correct categories' do
+ changed_files.each do |file|
+ allow(fake_git).to receive(:diff_for_file).with(file) { double(:diff, patch: patch) }
+
+ expect(helper.categories_for_file(file)).to eq(expected_categories)
+ end
+ end
+ end
+ end
+ end
+
+ describe '#label_for_category' do
+ where(:category, :expected_label) do
+ :backend | '~backend'
+ :database | '~database'
+ :docs | '~documentation'
+ :foo | '~foo'
+ :frontend | '~frontend'
+ :none | ''
+ :qa | '~QA'
+ :engineering_productivity | '~"Engineering Productivity" for CI, Danger'
+ :ci_template | '~"ci::templates"'
+ end
+
+ with_them do
+ subject { helper.label_for_category(category) }
+
+ it { is_expected.to eq(expected_label) }
+ end
+ end
+
+ describe '#new_teammates' do
+ it 'returns an array of Teammate' do
+ usernames = %w[filipa iamphil]
+
+ teammates = helper.new_teammates(usernames)
+
+ expect(teammates.map(&:username)).to eq(usernames)
+ end
+ end
+
+ describe '#mr_title' do
+ it 'returns "" when `gitlab_helper` is unavailable' do
+ expect(helper).to receive(:gitlab_helper).and_return(nil)
+
+ expect(helper.mr_title).to eq('')
+ end
+
+ it 'returns the MR title when `gitlab_helper` is available' do
+ mr_title = 'My MR title'
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => mr_title)
+
+ expect(helper.mr_title).to eq(mr_title)
+ end
+ end
+
+ describe '#mr_web_url' do
+ it 'returns "" when `gitlab_helper` is unavailable' do
+ expect(helper).to receive(:gitlab_helper).and_return(nil)
+
+ expect(helper.mr_web_url).to eq('')
+ end
+
+ it 'returns the MR web_url when `gitlab_helper` is available' do
+ mr_web_url = 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1'
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('web_url' => mr_web_url)
+
+ expect(helper.mr_web_url).to eq(mr_web_url)
+ end
+ end
+
+ describe '#mr_target_branch' do
+ it 'returns "" when `gitlab_helper` is unavailable' do
+ expect(helper).to receive(:gitlab_helper).and_return(nil)
+
+ expect(helper.mr_target_branch).to eq('')
+ end
+
+ it 'returns the MR web_url when `gitlab_helper` is available' do
+ mr_target_branch = 'main'
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('target_branch' => mr_target_branch)
+
+ expect(helper.mr_target_branch).to eq(mr_target_branch)
+ end
+ end
+
+ describe '#security_mr?' do
+ it 'returns false when on a normal merge request' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('web_url' => 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1')
+
+ expect(helper).not_to be_security_mr
+ end
+
+ it 'returns true when on a security merge request' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('web_url' => 'https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/1')
+
+ expect(helper).to be_security_mr
+ end
+ end
+
+ describe '#draft_mr?' do
+ it 'returns true for a draft MR' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'Draft: My MR title')
+
+ expect(helper).to be_draft_mr
+ end
+
+ it 'returns false for non draft MR' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'My MR title')
+
+ expect(helper).not_to be_draft_mr
+ end
+ end
+
+ describe '#cherry_pick_mr?' do
+ context 'when MR title does not mention a cherry-pick' do
+ it 'returns false' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'Add feature xyz')
+
+ expect(helper).not_to be_cherry_pick_mr
+ end
+ end
+
+ context 'when MR title mentions a cherry-pick' do
+ [
+ 'Cherry Pick !1234',
+ 'cherry-pick !1234',
+ 'CherryPick !1234'
+ ].each do |mr_title|
+ it 'returns true' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => mr_title)
+
+ expect(helper).to be_cherry_pick_mr
+ end
+ end
+ end
+ end
+
+ describe '#run_all_rspec_mr?' do
+ context 'when MR title does not mention RUN ALL RSPEC' do
+ it 'returns false' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'Add feature xyz')
+
+ expect(helper).not_to be_run_all_rspec_mr
+ end
+ end
+
+ context 'when MR title mentions RUN ALL RSPEC' do
+ it 'returns true' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'Add feature xyz RUN ALL RSPEC')
+
+ expect(helper).to be_run_all_rspec_mr
+ end
+ end
+ end
+
+ describe '#run_as_if_foss_mr?' do
+ context 'when MR title does not mention RUN AS-IF-FOSS' do
+ it 'returns false' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'Add feature xyz')
+
+ expect(helper).not_to be_run_as_if_foss_mr
+ end
+ end
+
+ context 'when MR title mentions RUN AS-IF-FOSS' do
+ it 'returns true' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('title' => 'Add feature xyz RUN AS-IF-FOSS')
+
+ expect(helper).to be_run_as_if_foss_mr
+ end
+ end
+ end
+
+ describe '#stable_branch?' do
+ it 'returns false when `gitlab_helper` is unavailable' do
+ expect(helper).to receive(:gitlab_helper).and_return(nil)
+
+ expect(helper).not_to be_stable_branch
+ end
+
+ context 'when MR target branch is not a stable branch' do
+ it 'returns false' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('target_branch' => 'my-feature-branch')
+
+ expect(helper).not_to be_stable_branch
+ end
+ end
+
+ context 'when MR target branch is a stable branch' do
+ %w[
+ 13-1-stable-ee
+ 13-1-stable-ee-patch-1
+ ].each do |target_branch|
+ it 'returns true' do
+ expect(fake_gitlab).to receive(:mr_json)
+ .and_return('target_branch' => target_branch)
+
+ expect(helper).to be_stable_branch
+ end
+ end
+ end
+ end
+
+ describe '#mr_has_label?' do
+ it 'returns false when `gitlab_helper` is unavailable' do
+ expect(helper).to receive(:gitlab_helper).and_return(nil)
+
+ expect(helper.mr_has_labels?('telemetry')).to be_falsey
+ end
+
+ context 'when mr has labels' do
+ before do
+ mr_labels = ['telemetry', 'telemetry::reviewed']
+ expect(fake_gitlab).to receive(:mr_labels).and_return(mr_labels)
+ end
+
+ it 'returns true with a matched label' do
+ expect(helper.mr_has_labels?('telemetry')).to be_truthy
+ end
+
+ it 'returns false with unmatched label' do
+ expect(helper.mr_has_labels?('database')).to be_falsey
+ end
+
+ it 'returns true with an array of labels' do
+ expect(helper.mr_has_labels?(['telemetry', 'telemetry::reviewed'])).to be_truthy
+ end
+
+ it 'returns true with multi arguments with matched labels' do
+ expect(helper.mr_has_labels?('telemetry', 'telemetry::reviewed')).to be_truthy
+ end
+
+ it 'returns false with multi arguments with unmatched labels' do
+ expect(helper.mr_has_labels?('telemetry', 'telemetry::non existing')).to be_falsey
+ end
+ end
+ end
+
+ describe '#labels_list' do
+ let(:labels) { ['telemetry', 'telemetry::reviewed'] }
+
+ it 'composes the labels string' do
+ expect(helper.labels_list(labels)).to eq('~"telemetry", ~"telemetry::reviewed"')
+ end
+
+ context 'when passing a separator' do
+ it 'composes the labels string with the given separator' do
+ expect(helper.labels_list(labels, sep: ' ')).to eq('~"telemetry" ~"telemetry::reviewed"')
+ end
+ end
+
+ it 'returns empty string for empty array' do
+ expect(helper.labels_list([])).to eq('')
+ end
+ end
+
+ describe '#prepare_labels_for_mr' do
+ it 'composes the labels string' do
+ mr_labels = ['telemetry', 'telemetry::reviewed']
+
+ expect(helper.prepare_labels_for_mr(mr_labels)).to eq('/label ~"telemetry" ~"telemetry::reviewed"')
+ end
+
+ it 'returns empty string for empty array' do
+ expect(helper.prepare_labels_for_mr([])).to eq('')
+ end
+ end
+
+ describe '#has_ci_changes?' do
+ context 'when .gitlab/ci is changed' do
+ it 'returns true' do
+ expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb .gitlab/ci/test.yml])
+
+ expect(helper.has_ci_changes?).to be_truthy
+ end
+ end
+
+ context 'when .gitlab-ci.yml is changed' do
+ it 'returns true' do
+ expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb .gitlab-ci.yml])
+
+ expect(helper.has_ci_changes?).to be_truthy
+ end
+ end
+
+ context 'when neither .gitlab/ci/ or .gitlab-ci.yml is changed' do
+ it 'returns false' do
+ expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb nested/.gitlab-ci.yml])
+
+ expect(helper.has_ci_changes?).to be_falsey
+ end
+ end
+ end
+
+ describe '#group_label' do
+ it 'returns nil when no group label is present' do
+ expect(helper.group_label(%w[foo bar])).to be_nil
+ end
+
+ it 'returns the group label when a group label is present' do
+ expect(helper.group_label(['foo', 'group::source code', 'bar'])).to eq('group::source code')
+ end
+ end
+end
diff --git a/spec/tooling/danger/merge_request_linter_spec.rb b/spec/tooling/danger/merge_request_linter_spec.rb
new file mode 100644
index 00000000000..3273b6b3d07
--- /dev/null
+++ b/spec/tooling/danger/merge_request_linter_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/merge_request_linter'
+
+RSpec.describe Tooling::Danger::MergeRequestLinter do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:mr_class) do
+ Struct.new(:message, :sha, :diff_parent)
+ end
+
+ let(:mr_title) { 'A B ' + 'C' }
+ let(:merge_request) { mr_class.new(mr_title, anything, anything) }
+
+ describe '#lint_subject' do
+ subject(:mr_linter) { described_class.new(merge_request) }
+
+ shared_examples 'a valid mr title' do
+ it 'does not have any problem' do
+ mr_linter.lint
+
+ expect(mr_linter.problems).to be_empty
+ end
+ end
+
+ context 'when subject valid' do
+ it_behaves_like 'a valid mr title'
+ end
+
+ context 'when it is too long' do
+ let(:mr_title) { 'A B ' + 'C' * described_class::MAX_LINE_LENGTH }
+
+ it 'adds a problem' do
+ expect(mr_linter).to receive(:add_problem).with(:subject_too_long, described_class.subject_description)
+
+ mr_linter.lint
+ end
+ end
+
+ describe 'using magic mr run options' do
+ where(run_option: described_class.mr_run_options_regex.split('|') +
+ described_class.mr_run_options_regex.split('|').map! { |x| "[#{x}]" })
+
+ with_them do
+ let(:mr_title) { run_option + ' A B ' + 'C' * (described_class::MAX_LINE_LENGTH - 5) }
+
+ it_behaves_like 'a valid mr title'
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/roulette_spec.rb b/spec/tooling/danger/roulette_spec.rb
new file mode 100644
index 00000000000..1e500a1ed08
--- /dev/null
+++ b/spec/tooling/danger/roulette_spec.rb
@@ -0,0 +1,429 @@
+# frozen_string_literal: true
+
+require 'webmock/rspec'
+require 'timecop'
+
+require_relative '../../../tooling/danger/roulette'
+require 'active_support/testing/time_helpers'
+
+RSpec.describe Tooling::Danger::Roulette do
+ include ActiveSupport::Testing::TimeHelpers
+
+ around do |example|
+ travel_to(Time.utc(2020, 06, 22, 10)) { example.run }
+ end
+
+ let(:backend_available) { true }
+ let(:backend_tz_offset_hours) { 2.0 }
+ let(:backend_maintainer) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'backend-maintainer',
+ 'name' => 'Backend maintainer',
+ 'role' => 'Backend engineer',
+ 'projects' => { 'gitlab' => 'maintainer backend' },
+ 'available' => backend_available,
+ 'tz_offset_hours' => backend_tz_offset_hours
+ )
+ end
+
+ let(:frontend_reviewer) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'frontend-reviewer',
+ 'name' => 'Frontend reviewer',
+ 'role' => 'Frontend engineer',
+ 'projects' => { 'gitlab' => 'reviewer frontend' },
+ 'available' => true,
+ 'tz_offset_hours' => 2.0
+ )
+ end
+
+ let(:frontend_maintainer) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'frontend-maintainer',
+ 'name' => 'Frontend maintainer',
+ 'role' => 'Frontend engineer',
+ 'projects' => { 'gitlab' => "maintainer frontend" },
+ 'available' => true,
+ 'tz_offset_hours' => 2.0
+ )
+ end
+
+ let(:software_engineer_in_test) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'software-engineer-in-test',
+ 'name' => 'Software Engineer in Test',
+ 'role' => 'Software Engineer in Test, Create:Source Code',
+ 'projects' => { 'gitlab' => 'maintainer qa', 'gitlab-qa' => 'maintainer' },
+ 'available' => true,
+ 'tz_offset_hours' => 2.0
+ )
+ end
+
+ let(:engineering_productivity_reviewer) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'eng-prod-reviewer',
+ 'name' => 'EP engineer',
+ 'role' => 'Engineering Productivity',
+ 'projects' => { 'gitlab' => 'reviewer backend' },
+ 'available' => true,
+ 'tz_offset_hours' => 2.0
+ )
+ end
+
+ let(:ci_template_reviewer) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'ci-template-maintainer',
+ 'name' => 'CI Template engineer',
+ 'role' => '~"ci::templates"',
+ 'projects' => { 'gitlab' => 'reviewer ci_template' },
+ 'available' => true,
+ 'tz_offset_hours' => 2.0
+ )
+ end
+
+ let(:teammates) do
+ [
+ backend_maintainer.to_h,
+ frontend_maintainer.to_h,
+ frontend_reviewer.to_h,
+ software_engineer_in_test.to_h,
+ engineering_productivity_reviewer.to_h,
+ ci_template_reviewer.to_h
+ ]
+ end
+
+ let(:teammate_json) do
+ teammates.to_json
+ end
+
+ subject(:roulette) { Object.new.extend(described_class) }
+
+ describe 'Spin#==' do
+ it 'compares Spin attributes' do
+ spin1 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, false, false)
+ spin2 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, false, false)
+ spin3 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, false, true)
+ spin4 = described_class::Spin.new(:backend, frontend_reviewer, frontend_maintainer, true, false)
+ spin5 = described_class::Spin.new(:backend, frontend_reviewer, backend_maintainer, false, false)
+ spin6 = described_class::Spin.new(:backend, backend_maintainer, frontend_maintainer, false, false)
+ spin7 = described_class::Spin.new(:frontend, frontend_reviewer, frontend_maintainer, false, false)
+
+ expect(spin1).to eq(spin2)
+ expect(spin1).not_to eq(spin3)
+ expect(spin1).not_to eq(spin4)
+ expect(spin1).not_to eq(spin5)
+ expect(spin1).not_to eq(spin6)
+ expect(spin1).not_to eq(spin7)
+ end
+ end
+
+ describe '#spin' do
+ let!(:project) { 'gitlab' }
+ let!(:mr_source_branch) { 'a-branch' }
+ let!(:mr_labels) { ['backend', 'devops::create'] }
+ let!(:author) { Tooling::Danger::Teammate.new('username' => 'johndoe') }
+ let(:timezone_experiment) { false }
+ let(:spins) do
+ # Stub the request at the latest time so that we can modify the raw data, e.g. available fields.
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: teammate_json)
+
+ subject.spin(project, categories, timezone_experiment: timezone_experiment)
+ end
+
+ before do
+ allow(subject).to receive(:mr_author_username).and_return(author.username)
+ allow(subject).to receive(:mr_labels).and_return(mr_labels)
+ allow(subject).to receive(:mr_source_branch).and_return(mr_source_branch)
+ end
+
+ context 'when timezone_experiment == false' do
+ context 'when change contains backend category' do
+ let(:categories) { [:backend] }
+
+ it 'assigns backend reviewer and maintainer' do
+ expect(spins[0].reviewer).to eq(engineering_productivity_reviewer)
+ expect(spins[0].maintainer).to eq(backend_maintainer)
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false)])
+ end
+
+ context 'when teammate is not available' do
+ let(:backend_available) { false }
+
+ it 'assigns backend reviewer and no maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, nil, false, false)])
+ end
+ end
+ end
+
+ context 'when change contains frontend category' do
+ let(:categories) { [:frontend] }
+
+ it 'assigns frontend reviewer and maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:frontend, frontend_reviewer, frontend_maintainer, false, false)])
+ end
+ end
+
+ context 'when change contains many categories' do
+ let(:categories) { [:frontend, :test, :qa, :engineering_productivity, :ci_template, :backend] }
+
+ it 'has a deterministic sorting order' do
+ expect(spins.map(&:category)).to eq categories.sort
+ end
+ end
+
+ context 'when change contains QA category' do
+ let(:categories) { [:qa] }
+
+ it 'assigns QA maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:qa, nil, software_engineer_in_test, false, false)])
+ end
+ end
+
+ context 'when change contains QA category and another category' do
+ let(:categories) { [:backend, :qa] }
+
+ it 'assigns QA maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false), described_class::Spin.new(:qa, nil, software_engineer_in_test, :maintainer, false)])
+ end
+
+ context 'and author is an SET' do
+ let!(:author) { Tooling::Danger::Teammate.new('username' => software_engineer_in_test.username) }
+
+ it 'assigns QA reviewer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false), described_class::Spin.new(:qa, nil, nil, false, false)])
+ end
+ end
+ end
+
+ context 'when change contains Engineering Productivity category' do
+ let(:categories) { [:engineering_productivity] }
+
+ it 'assigns Engineering Productivity reviewer and fallback to backend maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:engineering_productivity, engineering_productivity_reviewer, backend_maintainer, false, false)])
+ end
+ end
+
+ context 'when change contains CI/CD Template category' do
+ let(:categories) { [:ci_template] }
+
+ it 'assigns CI/CD Template reviewer and fallback to backend maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:ci_template, ci_template_reviewer, backend_maintainer, false, false)])
+ end
+ end
+
+ context 'when change contains test category' do
+ let(:categories) { [:test] }
+
+ it 'assigns corresponding SET' do
+ expect(spins).to eq([described_class::Spin.new(:test, software_engineer_in_test, nil, :maintainer, false)])
+ end
+ end
+ end
+
+ context 'when timezone_experiment == true' do
+ let(:timezone_experiment) { true }
+
+ context 'when change contains backend category' do
+ let(:categories) { [:backend] }
+
+ it 'assigns backend reviewer and maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, true)])
+ end
+
+ context 'when teammate is not in a good timezone' do
+ let(:backend_tz_offset_hours) { 5.0 }
+
+ it 'assigns backend reviewer and no maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, nil, false, true)])
+ end
+ end
+ end
+
+ context 'when change includes a category with timezone disabled' do
+ let(:categories) { [:backend] }
+
+ before do
+ stub_const("#{described_class}::INCLUDE_TIMEZONE_FOR_CATEGORY", backend: false)
+ end
+
+ it 'assigns backend reviewer and maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false)])
+ end
+
+ context 'when teammate is not in a good timezone' do
+ let(:backend_tz_offset_hours) { 5.0 }
+
+ it 'assigns backend reviewer and maintainer' do
+ expect(spins).to eq([described_class::Spin.new(:backend, engineering_productivity_reviewer, backend_maintainer, false, false)])
+ end
+ end
+ end
+ end
+ end
+
+ RSpec::Matchers.define :match_teammates do |expected|
+ match do |actual|
+ expected.each do |expected_person|
+ actual_person_found = actual.find { |actual_person| actual_person.name == expected_person.username }
+
+ actual_person_found &&
+ actual_person_found.name == expected_person.name &&
+ actual_person_found.role == expected_person.role &&
+ actual_person_found.projects == expected_person.projects
+ end
+ end
+ end
+
+ describe '#team' do
+ subject(:team) { roulette.team }
+
+ context 'HTTP failure' do
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(status: 404)
+ end
+
+ it 'raises a pretty error' do
+ expect { team }.to raise_error(/Failed to read/)
+ end
+ end
+
+ context 'JSON failure' do
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: 'INVALID JSON')
+ end
+
+ it 'raises a pretty error' do
+ expect { team }.to raise_error(/Failed to parse/)
+ end
+ end
+
+ context 'success' do
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: teammate_json)
+ end
+
+ it 'returns an array of teammates' do
+ is_expected.to match_teammates([
+ backend_maintainer,
+ frontend_reviewer,
+ frontend_maintainer,
+ software_engineer_in_test,
+ engineering_productivity_reviewer,
+ ci_template_reviewer
+ ])
+ end
+
+ it 'memoizes the result' do
+ expect(team.object_id).to eq(roulette.team.object_id)
+ end
+ end
+ end
+
+ describe '#project_team' do
+ subject { roulette.project_team('gitlab-qa') }
+
+ before do
+ WebMock
+ .stub_request(:get, described_class::ROULETTE_DATA_URL)
+ .to_return(body: teammate_json)
+ end
+
+ it 'filters team by project_name' do
+ is_expected.to match_teammates([
+ software_engineer_in_test
+ ])
+ end
+ end
+
+ describe '#spin_for_person' do
+ let(:person_tz_offset_hours) { 0.0 }
+ let(:person1) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'user1',
+ 'available' => true,
+ 'tz_offset_hours' => person_tz_offset_hours
+ )
+ end
+
+ let(:person2) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'user2',
+ 'available' => true,
+ 'tz_offset_hours' => person_tz_offset_hours)
+ end
+
+ let(:author) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'johndoe',
+ 'available' => true,
+ 'tz_offset_hours' => 0.0)
+ end
+
+ let(:unavailable) do
+ Tooling::Danger::Teammate.new(
+ 'username' => 'janedoe',
+ 'available' => false,
+ 'tz_offset_hours' => 0.0)
+ end
+
+ before do
+ allow(subject).to receive(:mr_author_username).and_return(author.username)
+ end
+
+ (-4..4).each do |utc_offset|
+ context "when local hour for person is #{10 + utc_offset} (offset: #{utc_offset})" do
+ let(:person_tz_offset_hours) { utc_offset }
+
+ [false, true].each do |timezone_experiment|
+ context "with timezone_experiment == #{timezone_experiment}" do
+ it 'returns a random person' do
+ persons = [person1, person2]
+
+ selected = subject.spin_for_person(persons, random: Random.new, timezone_experiment: timezone_experiment)
+
+ expect(persons.map(&:username)).to include(selected.username)
+ end
+ end
+ end
+ end
+ end
+
+ ((-12..-5).to_a + (5..12).to_a).each do |utc_offset|
+ context "when local hour for person is #{10 + utc_offset} (offset: #{utc_offset})" do
+ let(:person_tz_offset_hours) { utc_offset }
+
+ [false, true].each do |timezone_experiment|
+ context "with timezone_experiment == #{timezone_experiment}" do
+ it 'returns a random person or nil' do
+ persons = [person1, person2]
+
+ selected = subject.spin_for_person(persons, random: Random.new, timezone_experiment: timezone_experiment)
+
+ if timezone_experiment
+ expect(selected).to be_nil
+ else
+ expect(persons.map(&:username)).to include(selected.username)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ it 'excludes unavailable persons' do
+ expect(subject.spin_for_person([unavailable], random: Random.new)).to be_nil
+ end
+
+ it 'excludes mr.author' do
+ expect(subject.spin_for_person([author], random: Random.new)).to be_nil
+ end
+ end
+end
diff --git a/spec/tooling/danger/sidekiq_queues_spec.rb b/spec/tooling/danger/sidekiq_queues_spec.rb
new file mode 100644
index 00000000000..c5fc8592621
--- /dev/null
+++ b/spec/tooling/danger/sidekiq_queues_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
+
+require_relative '../../../tooling/danger/sidekiq_queues'
+
+RSpec.describe Tooling::Danger::SidekiqQueues do
+ using RSpec::Parameterized::TableSyntax
+ include DangerSpecHelper
+
+ let(:fake_git) { double('fake-git') }
+ let(:fake_danger) { new_fake_danger.include(described_class) }
+
+ subject(:sidekiq_queues) { fake_danger.new(git: fake_git) }
+
+ describe '#changed_queue_files' do
+ where(:modified_files, :changed_queue_files) do
+ %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml foo) | %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml)
+ %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml) | %w(app/workers/all_queues.yml ee/app/workers/all_queues.yml)
+ %w(app/workers/all_queues.yml foo) | %w(app/workers/all_queues.yml)
+ %w(ee/app/workers/all_queues.yml foo) | %w(ee/app/workers/all_queues.yml)
+ %w(foo) | %w()
+ %w() | %w()
+ end
+
+ with_them do
+ it do
+ allow(fake_git).to receive(:modified_files).and_return(modified_files)
+
+ expect(sidekiq_queues.changed_queue_files).to match_array(changed_queue_files)
+ end
+ end
+ end
+
+ describe '#added_queue_names' do
+ it 'returns queue names added by this change' do
+ old_queues = { post_receive: nil }
+
+ allow(sidekiq_queues).to receive(:old_queues).and_return(old_queues)
+ allow(sidekiq_queues).to receive(:new_queues).and_return(old_queues.merge(merge: nil, process_commit: nil))
+
+ expect(sidekiq_queues.added_queue_names).to contain_exactly(:merge, :process_commit)
+ end
+ end
+
+ describe '#changed_queue_names' do
+ it 'returns names for queues whose attributes were changed' do
+ old_queues = {
+ merge: { name: :merge, urgency: :low },
+ post_receive: { name: :post_receive, urgency: :high },
+ process_commit: { name: :process_commit, urgency: :high }
+ }
+
+ new_queues = old_queues.merge(mailers: { name: :mailers, urgency: :high },
+ post_receive: { name: :post_receive, urgency: :low },
+ process_commit: { name: :process_commit, urgency: :low })
+
+ allow(sidekiq_queues).to receive(:old_queues).and_return(old_queues)
+ allow(sidekiq_queues).to receive(:new_queues).and_return(new_queues)
+
+ expect(sidekiq_queues.changed_queue_names).to contain_exactly(:post_receive, :process_commit)
+ end
+
+ it 'ignores removed queues' do
+ old_queues = {
+ merge: { name: :merge, urgency: :low },
+ post_receive: { name: :post_receive, urgency: :high }
+ }
+
+ new_queues = {
+ post_receive: { name: :post_receive, urgency: :low }
+ }
+
+ allow(sidekiq_queues).to receive(:old_queues).and_return(old_queues)
+ allow(sidekiq_queues).to receive(:new_queues).and_return(new_queues)
+
+ expect(sidekiq_queues.changed_queue_names).to contain_exactly(:post_receive)
+ end
+ end
+end
diff --git a/spec/tooling/danger/teammate_spec.rb b/spec/tooling/danger/teammate_spec.rb
new file mode 100644
index 00000000000..f3afdc6e912
--- /dev/null
+++ b/spec/tooling/danger/teammate_spec.rb
@@ -0,0 +1,225 @@
+# frozen_string_literal: true
+
+require_relative '../../../tooling/danger/teammate'
+require 'active_support/testing/time_helpers'
+require 'rspec-parameterized'
+
+RSpec.describe Tooling::Danger::Teammate do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new(options) }
+
+ let(:tz_offset_hours) { 2.0 }
+ let(:options) do
+ {
+ 'username' => 'luigi',
+ 'projects' => projects,
+ 'role' => role,
+ 'markdown_name' => '[Luigi](https://gitlab.com/luigi) (`@luigi`)',
+ 'tz_offset_hours' => tz_offset_hours
+ }
+ end
+
+ let(:capabilities) { ['reviewer backend'] }
+ let(:projects) { { project => capabilities } }
+ let(:role) { 'Engineer, Manage' }
+ let(:labels) { [] }
+ let(:project) { double }
+
+ describe '#==' do
+ it 'compares Teammate username' do
+ joe1 = described_class.new('username' => 'joe', 'projects' => projects)
+ joe2 = described_class.new('username' => 'joe', 'projects' => [])
+ jane1 = described_class.new('username' => 'jane', 'projects' => projects)
+ jane2 = described_class.new('username' => 'jane', 'projects' => [])
+
+ expect(joe1).to eq(joe2)
+ expect(jane1).to eq(jane2)
+ expect(jane1).not_to eq(nil)
+ expect(described_class.new('username' => nil)).not_to eq(nil)
+ end
+ end
+
+ describe '#to_h' do
+ it 'returns the given options' do
+ expect(subject.to_h).to eq(options)
+ end
+ end
+
+ context 'when having multiple capabilities' do
+ let(:capabilities) { ['reviewer backend', 'maintainer frontend', 'trainee_maintainer qa'] }
+
+ it '#any_capability? returns true if the person has any capability for the category in the given project' do
+ expect(subject.any_capability?(project, :backend)).to be_truthy
+ expect(subject.any_capability?(project, :frontend)).to be_truthy
+ expect(subject.any_capability?(project, :qa)).to be_truthy
+ expect(subject.any_capability?(project, :engineering_productivity)).to be_falsey
+ end
+
+ it '#reviewer? supports multiple roles per project' do
+ expect(subject.reviewer?(project, :backend, labels)).to be_truthy
+ end
+
+ it '#traintainer? supports multiple roles per project' do
+ expect(subject.traintainer?(project, :qa, labels)).to be_truthy
+ end
+
+ it '#maintainer? supports multiple roles per project' do
+ expect(subject.maintainer?(project, :frontend, labels)).to be_truthy
+ end
+
+ context 'when labels contain devops::create and the category is test' do
+ let(:labels) { ['devops::create'] }
+
+ context 'when role is Software Engineer in Test, Create' do
+ let(:role) { 'Software Engineer in Test, Create' }
+
+ it '#reviewer? returns true' do
+ expect(subject.reviewer?(project, :test, labels)).to be_truthy
+ end
+
+ it '#maintainer? returns false' do
+ expect(subject.maintainer?(project, :test, labels)).to be_falsey
+ end
+
+ context 'when hyperlink is mangled in the role' do
+ let(:role) { '<a href="#">Software Engineer in Test</a>, Create' }
+
+ it '#reviewer? returns true' do
+ expect(subject.reviewer?(project, :test, labels)).to be_truthy
+ end
+ end
+ end
+
+ context 'when role is Software Engineer in Test' do
+ let(:role) { 'Software Engineer in Test' }
+
+ it '#reviewer? returns false' do
+ expect(subject.reviewer?(project, :test, labels)).to be_falsey
+ end
+ end
+
+ context 'when role is Software Engineer in Test, Manage' do
+ let(:role) { 'Software Engineer in Test, Manage' }
+
+ it '#reviewer? returns false' do
+ expect(subject.reviewer?(project, :test, labels)).to be_falsey
+ end
+ end
+
+ context 'when role is Backend Engineer, Engineering Productivity' do
+ let(:role) { 'Backend Engineer, Engineering Productivity' }
+
+ it '#reviewer? returns true' do
+ expect(subject.reviewer?(project, :engineering_productivity, labels)).to be_truthy
+ end
+
+ it '#maintainer? returns false' do
+ expect(subject.maintainer?(project, :engineering_productivity, labels)).to be_falsey
+ end
+
+ context 'when capabilities include maintainer backend' do
+ let(:capabilities) { ['maintainer backend'] }
+
+ it '#maintainer? returns true' do
+ expect(subject.maintainer?(project, :engineering_productivity, labels)).to be_truthy
+ end
+ end
+
+ context 'when capabilities include maintainer engineering productivity' do
+ let(:capabilities) { ['maintainer engineering_productivity'] }
+
+ it '#maintainer? returns true' do
+ expect(subject.maintainer?(project, :engineering_productivity, labels)).to be_truthy
+ end
+ end
+
+ context 'when capabilities include trainee_maintainer backend' do
+ let(:capabilities) { ['trainee_maintainer backend'] }
+
+ it '#traintainer? returns true' do
+ expect(subject.traintainer?(project, :engineering_productivity, labels)).to be_truthy
+ end
+ end
+ end
+ end
+ end
+
+ context 'when having single capability' do
+ let(:capabilities) { 'reviewer backend' }
+
+ it '#reviewer? supports one role per project' do
+ expect(subject.reviewer?(project, :backend, labels)).to be_truthy
+ end
+
+ it '#traintainer? supports one role per project' do
+ expect(subject.traintainer?(project, :database, labels)).to be_falsey
+ end
+
+ it '#maintainer? supports one role per project' do
+ expect(subject.maintainer?(project, :frontend, labels)).to be_falsey
+ end
+ end
+
+ describe '#local_hour' do
+ include ActiveSupport::Testing::TimeHelpers
+
+ around do |example|
+ travel_to(Time.utc(2020, 6, 23, 10)) { example.run }
+ end
+
+ context 'when author is given' do
+ where(:tz_offset_hours, :expected_local_hour) do
+ -12 | 22
+ -10 | 0
+ 2 | 12
+ 4 | 14
+ 12 | 22
+ end
+
+ with_them do
+ it 'returns the correct local_hour' do
+ expect(subject.local_hour).to eq(expected_local_hour)
+ end
+ end
+ end
+ end
+
+ describe '#markdown_name' do
+ it 'returns markdown name with timezone info' do
+ expect(subject.markdown_name).to eq("#{options['markdown_name']} (UTC+2)")
+ end
+
+ context 'when offset is 1.5' do
+ let(:tz_offset_hours) { 1.5 }
+
+ it 'returns markdown name with timezone info, not truncated' do
+ expect(subject.markdown_name).to eq("#{options['markdown_name']} (UTC+1.5)")
+ end
+ end
+
+ context 'when author is given' do
+ where(:tz_offset_hours, :author_offset, :diff_text) do
+ -12 | -10 | "2 hours behind `@mario`"
+ -10 | -12 | "2 hours ahead of `@mario`"
+ -10 | 2 | "12 hours behind `@mario`"
+ 2 | 4 | "2 hours behind `@mario`"
+ 4 | 2 | "2 hours ahead of `@mario`"
+ 2 | 3 | "1 hour behind `@mario`"
+ 3 | 2 | "1 hour ahead of `@mario`"
+ 2 | 2 | "same timezone as `@mario`"
+ end
+
+ with_them do
+ it 'returns markdown name with timezone info' do
+ author = described_class.new(options.merge('username' => 'mario', 'tz_offset_hours' => author_offset))
+
+ floored_offset_hours = subject.__send__(:floored_offset_hours)
+ utc_offset = floored_offset_hours >= 0 ? "+#{floored_offset_hours}" : floored_offset_hours
+
+ expect(subject.markdown_name(author: author)).to eq("#{options['markdown_name']} (UTC#{utc_offset}, #{diff_text})")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/tooling/danger/title_linting_spec.rb b/spec/tooling/danger/title_linting_spec.rb
new file mode 100644
index 00000000000..7bc1684cd87
--- /dev/null
+++ b/spec/tooling/danger/title_linting_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+
+require_relative '../../../tooling/danger/title_linting'
+
+RSpec.describe Tooling::Danger::TitleLinting do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '#sanitize_mr_title' do
+ where(:mr_title, :expected_mr_title) do
+ '`My MR title`' | "\\`My MR title\\`"
+ 'WIP: My MR title' | 'My MR title'
+ 'Draft: My MR title' | 'My MR title'
+ '(Draft) My MR title' | 'My MR title'
+ '[Draft] My MR title' | 'My MR title'
+ '[DRAFT] My MR title' | 'My MR title'
+ 'DRAFT: My MR title' | 'My MR title'
+ 'DRAFT: `My MR title`' | "\\`My MR title\\`"
+ end
+
+ with_them do
+ subject { described_class.sanitize_mr_title(mr_title) }
+
+ it { is_expected.to eq(expected_mr_title) }
+ end
+ end
+
+ describe '#remove_draft_flag' do
+ where(:mr_title, :expected_mr_title) do
+ 'WIP: My MR title' | 'My MR title'
+ 'Draft: My MR title' | 'My MR title'
+ '(Draft) My MR title' | 'My MR title'
+ '[Draft] My MR title' | 'My MR title'
+ '[DRAFT] My MR title' | 'My MR title'
+ 'DRAFT: My MR title' | 'My MR title'
+ end
+
+ with_them do
+ subject { described_class.remove_draft_flag(mr_title) }
+
+ it { is_expected.to eq(expected_mr_title) }
+ end
+ end
+
+ describe '#has_draft_flag?' do
+ it 'returns true for a draft title' do
+ expect(described_class.has_draft_flag?('Draft: My MR title')).to be true
+ end
+
+ it 'returns false for non draft title' do
+ expect(described_class.has_draft_flag?('My MR title')).to be false
+ end
+ end
+
+ describe '#has_cherry_pick_flag?' do
+ [
+ 'Cherry Pick !1234',
+ 'cherry-pick !1234',
+ 'CherryPick !1234'
+ ].each do |mr_title|
+ it 'returns true for cherry-pick title' do
+ expect(described_class.has_cherry_pick_flag?(mr_title)).to be true
+ end
+ end
+
+ it 'returns false for non cherry-pick title' do
+ expect(described_class.has_cherry_pick_flag?('My MR title')).to be false
+ end
+ end
+
+ describe '#has_run_all_rspec_flag?' do
+ it 'returns true for a title that includes RUN ALL RSPEC' do
+ expect(described_class.has_run_all_rspec_flag?('My MR title RUN ALL RSPEC')).to be true
+ end
+
+ it 'returns true for a title that does not include RUN ALL RSPEC' do
+ expect(described_class.has_run_all_rspec_flag?('My MR title')).to be false
+ end
+ end
+
+ describe '#has_run_as_if_foss_flag?' do
+ it 'returns true for a title that includes RUN AS-IF-FOSS' do
+ expect(described_class.has_run_as_if_foss_flag?('My MR title RUN AS-IF-FOSS')).to be true
+ end
+
+ it 'returns true for a title that does not include RUN AS-IF-FOSS' do
+ expect(described_class.has_run_as_if_foss_flag?('My MR title')).to be false
+ end
+ end
+end
diff --git a/spec/tooling/danger/weightage/maintainers_spec.rb b/spec/tooling/danger/weightage/maintainers_spec.rb
new file mode 100644
index 00000000000..b99ffe706a4
--- /dev/null
+++ b/spec/tooling/danger/weightage/maintainers_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require_relative '../../../../tooling/danger/weightage/maintainers'
+
+RSpec.describe Tooling::Danger::Weightage::Maintainers do
+ let(:multiplier) { Tooling::Danger::Weightage::CAPACITY_MULTIPLIER }
+ let(:regular_maintainer) { double('Teammate', reduced_capacity: false) }
+ let(:reduced_capacity_maintainer) { double('Teammate', reduced_capacity: true) }
+ let(:maintainers) do
+ [
+ regular_maintainer,
+ reduced_capacity_maintainer
+ ]
+ end
+
+ let(:maintainer_count) { Tooling::Danger::Weightage::BASE_REVIEWER_WEIGHT * multiplier }
+ let(:reduced_capacity_maintainer_count) { Tooling::Danger::Weightage::BASE_REVIEWER_WEIGHT }
+
+ subject(:weighted_maintainers) { described_class.new(maintainers).execute }
+
+ describe '#execute' do
+ it 'weights the maintainers overall' do
+ expect(weighted_maintainers.count).to eq maintainer_count + reduced_capacity_maintainer_count
+ end
+
+ it 'has total count of regular maintainers' do
+ expect(weighted_maintainers.count { |r| r.object_id == regular_maintainer.object_id }).to eq maintainer_count
+ end
+
+ it 'has count of reduced capacity maintainers' do
+ expect(weighted_maintainers.count { |r| r.object_id == reduced_capacity_maintainer.object_id }).to eq reduced_capacity_maintainer_count
+ end
+ end
+end
diff --git a/spec/tooling/danger/weightage/reviewers_spec.rb b/spec/tooling/danger/weightage/reviewers_spec.rb
new file mode 100644
index 00000000000..5693ce7a10c
--- /dev/null
+++ b/spec/tooling/danger/weightage/reviewers_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require_relative '../../../../tooling/danger/weightage/reviewers'
+
+RSpec.describe Tooling::Danger::Weightage::Reviewers do
+ let(:multiplier) { Tooling::Danger::Weightage::CAPACITY_MULTIPLIER }
+ let(:regular_reviewer) { double('Teammate', hungry: false, reduced_capacity: false) }
+ let(:hungry_reviewer) { double('Teammate', hungry: true, reduced_capacity: false) }
+ let(:reduced_capacity_reviewer) { double('Teammate', hungry: false, reduced_capacity: true) }
+ let(:reviewers) do
+ [
+ hungry_reviewer,
+ regular_reviewer,
+ reduced_capacity_reviewer
+ ]
+ end
+
+ let(:regular_traintainer) { double('Teammate', hungry: false, reduced_capacity: false) }
+ let(:hungry_traintainer) { double('Teammate', hungry: true, reduced_capacity: false) }
+ let(:reduced_capacity_traintainer) { double('Teammate', hungry: false, reduced_capacity: true) }
+ let(:traintainers) do
+ [
+ hungry_traintainer,
+ regular_traintainer,
+ reduced_capacity_traintainer
+ ]
+ end
+
+ let(:hungry_reviewer_count) { Tooling::Danger::Weightage::BASE_REVIEWER_WEIGHT * multiplier + described_class::DEFAULT_REVIEWER_WEIGHT }
+ let(:hungry_traintainer_count) { described_class::TRAINTAINER_WEIGHT * multiplier + described_class::DEFAULT_REVIEWER_WEIGHT }
+ let(:reviewer_count) { Tooling::Danger::Weightage::BASE_REVIEWER_WEIGHT * multiplier }
+ let(:traintainer_count) { Tooling::Danger::Weightage::BASE_REVIEWER_WEIGHT * described_class::TRAINTAINER_WEIGHT * multiplier }
+ let(:reduced_capacity_reviewer_count) { Tooling::Danger::Weightage::BASE_REVIEWER_WEIGHT }
+ let(:reduced_capacity_traintainer_count) { described_class::TRAINTAINER_WEIGHT }
+
+ subject(:weighted_reviewers) { described_class.new(reviewers, traintainers).execute }
+
+ describe '#execute', :aggregate_failures do
+ it 'weights the reviewers overall' do
+ reviewers_count = hungry_reviewer_count + reviewer_count + reduced_capacity_reviewer_count
+ traintainers_count = hungry_traintainer_count + traintainer_count + reduced_capacity_traintainer_count
+
+ expect(weighted_reviewers.count).to eq reviewers_count + traintainers_count
+ end
+
+ it 'has total count of hungry reviewers and traintainers' do
+ expect(weighted_reviewers.count(&:hungry)).to eq hungry_reviewer_count + hungry_traintainer_count
+ expect(weighted_reviewers.count { |r| r.object_id == hungry_reviewer.object_id }).to eq hungry_reviewer_count
+ expect(weighted_reviewers.count { |r| r.object_id == hungry_traintainer.object_id }).to eq hungry_traintainer_count
+ end
+
+ it 'has total count of regular reviewers and traintainers' do
+ expect(weighted_reviewers.count { |r| r.object_id == regular_reviewer.object_id }).to eq reviewer_count
+ expect(weighted_reviewers.count { |r| r.object_id == regular_traintainer.object_id }).to eq traintainer_count
+ end
+
+ it 'has count of reduced capacity reviewers' do
+ expect(weighted_reviewers.count(&:reduced_capacity)).to eq reduced_capacity_reviewer_count + reduced_capacity_traintainer_count
+ expect(weighted_reviewers.count { |r| r.object_id == reduced_capacity_reviewer.object_id }).to eq reduced_capacity_reviewer_count
+ expect(weighted_reviewers.count { |r| r.object_id == reduced_capacity_traintainer.object_id }).to eq reduced_capacity_traintainer_count
+ end
+ end
+end
diff --git a/spec/tooling/gitlab_danger_spec.rb b/spec/tooling/gitlab_danger_spec.rb
new file mode 100644
index 00000000000..20ac40d1d2a
--- /dev/null
+++ b/spec/tooling/gitlab_danger_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require_relative '../../tooling/gitlab_danger'
+
+RSpec.describe GitlabDanger do
+ let(:gitlab_danger_helper) { nil }
+
+ subject { described_class.new(gitlab_danger_helper) }
+
+ describe '.local_warning_message' do
+ it 'returns an informational message with rules that can run' do
+ expect(described_class.local_warning_message).to eq("==> Only the following Danger rules can be run locally: #{described_class::LOCAL_RULES.join(', ')}")
+ end
+ end
+
+ describe '.success_message' do
+ it 'returns an informational success message' do
+ expect(described_class.success_message).to eq('==> No Danger rule violations!')
+ end
+ end
+
+ describe '#rule_names' do
+ context 'when running locally' do
+ it 'returns local only rules' do
+ expect(subject.rule_names).to eq(described_class::LOCAL_RULES)
+ end
+ end
+
+ context 'when running under CI' do
+ let(:gitlab_danger_helper) { double('danger_gitlab_helper') }
+
+ it 'returns all rules' do
+ expect(subject.rule_names).to eq(described_class::LOCAL_RULES | described_class::CI_ONLY_RULES)
+ end
+ end
+ end
+
+ describe '#html_link' do
+ context 'when running locally' do
+ it 'returns the same string' do
+ str = 'something'
+
+ expect(subject.html_link(str)).to eq(str)
+ end
+ end
+
+ context 'when running under CI' do
+ let(:gitlab_danger_helper) { double('danger_gitlab_helper') }
+
+ it 'returns a HTML link formatted version of the string' do
+ str = 'something'
+ html_formatted_str = %Q{<a href="#{str}">#{str}</a>}
+
+ expect(gitlab_danger_helper).to receive(:html_link).with(str).and_return(html_formatted_str)
+
+ expect(subject.html_link(str)).to eq(html_formatted_str)
+ end
+ end
+ end
+
+ describe '#ci?' do
+ context 'when gitlab_danger_helper is not available' do
+ it 'returns false' do
+ expect(subject.ci?).to be_falsey
+ end
+ end
+
+ context 'when gitlab_danger_helper is available' do
+ let(:gitlab_danger_helper) { double('danger_gitlab_helper') }
+
+ it 'returns true' do
+ expect(subject.ci?).to be_truthy
+ end
+ end
+ end
+end
diff --git a/spec/tooling/lib/tooling/kubernetes_client_spec.rb b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
index 2511295206c..4a84ec09b5c 100644
--- a/spec/tooling/lib/tooling/kubernetes_client_spec.rb
+++ b/spec/tooling/lib/tooling/kubernetes_client_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Tooling::KubernetesClient do
specify do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with(["kubectl delete #{described_class::RESOURCE_LIST} " +
- %(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=#{wait} #{release_names_in_command})])
+ %(--namespace "#{namespace}" --now --ignore-not-found --wait=#{wait} #{release_names_in_command})])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
expect(Gitlab::Popen).to receive(:popen_with_detail)
@@ -44,7 +44,7 @@ RSpec.describe Tooling::KubernetesClient do
it 'raises an error if the Kubernetes command fails' do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with(["kubectl delete #{described_class::RESOURCE_LIST} " +
- %(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=true -l release="#{release_name}")])
+ %(--namespace "#{namespace}" --now --ignore-not-found --wait=true -l release="#{release_name}")])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
expect { subject.cleanup_by_release(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
@@ -81,7 +81,7 @@ RSpec.describe Tooling::KubernetesClient do
specify do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with(["kubectl delete #{resource_type} ".squeeze(' ') +
- %(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=#{wait} #{release_names_in_command})])
+ %(--namespace "#{namespace}" --now --ignore-not-found --wait=#{wait} #{release_names_in_command})])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
# We're not verifying the output here, just silencing it
@@ -92,7 +92,7 @@ RSpec.describe Tooling::KubernetesClient do
it 'raises an error if the Kubernetes command fails' do
expect(Gitlab::Popen).to receive(:popen_with_detail)
.with(["kubectl delete #{resource_type} " +
- %(--namespace "#{namespace}" --now --ignore-not-found --include-uninitialized --wait=true #{pod_for_release})])
+ %(--namespace "#{namespace}" --now --ignore-not-found --wait=true #{pod_for_release})])
.and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
expect { subject.cleanup_by_created_at(resource_type: resource_type, created_before: two_days_ago) }.to raise_error(described_class::CommandFailedError)
diff --git a/spec/uploaders/packages/composer/cache_uploader_spec.rb b/spec/uploaders/packages/composer/cache_uploader_spec.rb
new file mode 100644
index 00000000000..a4ba4cc2a1e
--- /dev/null
+++ b/spec/uploaders/packages/composer/cache_uploader_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Composer::CacheUploader do
+ let(:cache_file) { create(:composer_cache_file) } # rubocop:disable Rails/SaveBang
+ let(:uploader) { described_class.new(cache_file, :file) }
+ let(:path) { Gitlab.config.packages.storage_path }
+
+ subject { uploader }
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[^\h{2}/\h{2}/\h{64}/packages/composer_cache/\d+$],
+ cache_dir: %r[/packages/tmp/cache],
+ work_dir: %r[/packages/tmp/work]
+
+ context 'object store is remote' do
+ before do
+ stub_composer_cache_object_storage
+ end
+
+ include_context 'with storage', described_class::Store::REMOTE
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[^\h{2}/\h{2}/\h{64}/packages/composer_cache/\d+$]
+ end
+
+ describe 'remote file' do
+ let(:cache_file) { create(:composer_cache_file, :object_storage) }
+
+ context 'with object storage enabled' do
+ before do
+ stub_composer_cache_object_storage
+ end
+
+ it 'can store file remotely' do
+ allow(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async)
+
+ cache_file
+
+ expect(cache_file.file_store).to eq(described_class::Store::REMOTE)
+ expect(cache_file.file.path).not_to be_blank
+ end
+ end
+ end
+end
diff --git a/spec/uploaders/packages/debian/component_file_uploader_spec.rb b/spec/uploaders/packages/debian/component_file_uploader_spec.rb
new file mode 100644
index 00000000000..de60ec94acf
--- /dev/null
+++ b/spec/uploaders/packages/debian/component_file_uploader_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Debian::ComponentFileUploader do
+ [:project, :group].each do |container_type|
+ context "Packages::Debian::#{container_type.capitalize}ComponentFile" do
+ let(:factory) { "debian_#{container_type}_component_file" }
+ let(:component_file) { create(factory) } # rubocop:disable Rails/SaveBang
+ let(:uploader) { described_class.new(component_file, :file) }
+ let(:path) { Gitlab.config.packages.storage_path }
+
+ subject { uploader }
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[^\h{2}/\h{2}/\h{64}/debian_#{container_type}_component_file/\d+$],
+ cache_dir: %r[/packages/tmp/cache$],
+ work_dir: %r[/packages/tmp/work$]
+
+ context 'object store is remote' do
+ before do
+ stub_package_file_object_storage
+ end
+
+ include_context 'with storage', described_class::Store::REMOTE
+
+ it_behaves_like "builds correct paths",
+ store_dir: %r[^\h{2}/\h{2}/\h{64}/debian_#{container_type}_component_file/\d+$],
+ cache_dir: %r[/packages/tmp/cache$],
+ work_dir: %r[/packages/tmp/work$]
+ end
+
+ describe 'remote file' do
+ let(:component_file) { create(factory, :object_storage) }
+
+ context 'with object storage enabled' do
+ before do
+ stub_package_file_object_storage
+ end
+
+ it 'can store file remotely' do
+ allow(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async)
+
+ component_file
+
+ expect(component_file.file_store).to eq(described_class::Store::REMOTE)
+ expect(component_file.file.path).not_to be_blank
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/validators/nested_attributes_duplicates_validator_spec.rb b/spec/validators/nested_attributes_duplicates_validator_spec.rb
new file mode 100644
index 00000000000..f59e422e5d4
--- /dev/null
+++ b/spec/validators/nested_attributes_duplicates_validator_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe NestedAttributesDuplicatesValidator do
+ let(:validator) { described_class.new(attributes: [attribute], **options) }
+
+ describe '#validate_each' do
+ let(:project) { build(:project) }
+ let(:record) { project }
+ let(:attribute) { :variables }
+ let(:value) { project.variables }
+
+ subject { validator.validate_each(record, attribute, value) }
+
+ context 'with no scope' do
+ let(:options) { {} }
+ let(:variables) { build_list(:ci_variable, 2, project: project) }
+
+ before do
+ project.variables << variables
+ end
+
+ it 'does not have any errors' do
+ subject
+
+ expect(project.errors.empty?).to be true
+ end
+
+ context 'with duplicates' do
+ before do
+ project.variables.build(key: variables.first.key, value: 'dummy_value')
+ end
+
+ it 'has a duplicate key error' do
+ subject
+
+ expect(project.errors).to have_key(:variables)
+ end
+ end
+ end
+
+ context 'with a scope attribute' do
+ let(:options) { { scope: :environment_scope } }
+ let(:first_variable) { build(:ci_variable, key: 'test_key', environment_scope: '*', project: project) }
+ let(:second_variable) { build(:ci_variable, key: 'test_key', environment_scope: 'prod', project: project) }
+
+ before do
+ project.variables << first_variable
+ project.variables << second_variable
+ end
+
+ it 'does not have any errors' do
+ subject
+
+ expect(project.errors.empty?).to be true
+ end
+
+ context 'with duplicates' do
+ before do
+ project.variables.build(key: second_variable.key, value: 'dummy_value', environment_scope: second_variable.environment_scope)
+ end
+
+ it 'has a duplicate key error' do
+ subject
+
+ expect(project.errors).to have_key(:variables)
+ end
+ end
+ end
+
+ context 'with a child attribute' do
+ let(:release) { build(:release) }
+ let(:first_link) { build(:release_link, name: 'test1', url: 'https://www.google1.com', release: release) }
+ let(:second_link) { build(:release_link, name: 'test2', url: 'https://www.google2.com', release: release) }
+ let(:record) { release }
+ let(:attribute) { :links }
+ let(:value) { release.links }
+ let(:options) { { scope: :release, child_attributes: %i[name url] } }
+
+ before do
+ release.links << first_link
+ release.links << second_link
+ end
+
+ it 'does not have any errors' do
+ subject
+
+ expect(release.errors.empty?).to be true
+ end
+
+ context 'when name is duplicated' do
+ let(:second_link) { build(:release_link, name: 'test1', release: release) }
+
+ it 'has a duplicate error' do
+ subject
+
+ expect(release.errors).to have_key(attribute)
+ end
+ end
+
+ context 'when url is duplicated' do
+ let(:second_link) { build(:release_link, url: 'https://www.google1.com', release: release) }
+
+ it 'has a duplicate error' do
+ subject
+
+ expect(release.errors).to have_key(attribute)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/validators/variable_duplicates_validator_spec.rb b/spec/validators/variable_duplicates_validator_spec.rb
deleted file mode 100644
index acc47ff225f..00000000000
--- a/spec/validators/variable_duplicates_validator_spec.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe VariableDuplicatesValidator do
- let(:validator) { described_class.new(attributes: [:variables], **options) }
-
- describe '#validate_each' do
- let(:project) { build(:project) }
-
- subject { validator.validate_each(project, :variables, project.variables) }
-
- context 'with no scope' do
- let(:options) { {} }
- let(:variables) { build_list(:ci_variable, 2, project: project) }
-
- before do
- project.variables << variables
- end
-
- it 'does not have any errors' do
- subject
-
- expect(project.errors.empty?).to be true
- end
-
- context 'with duplicates' do
- before do
- project.variables.build(key: variables.first.key, value: 'dummy_value')
- end
-
- it 'has a duplicate key error' do
- subject
-
- expect(project.errors).to have_key(:variables)
- end
- end
- end
-
- context 'with a scope attribute' do
- let(:options) { { scope: :environment_scope } }
- let(:first_variable) { build(:ci_variable, key: 'test_key', environment_scope: '*', project: project) }
- let(:second_variable) { build(:ci_variable, key: 'test_key', environment_scope: 'prod', project: project) }
-
- before do
- project.variables << first_variable
- project.variables << second_variable
- end
-
- it 'does not have any errors' do
- subject
-
- expect(project.errors.empty?).to be true
- end
-
- context 'with duplicates' do
- before do
- project.variables.build(key: second_variable.key, value: 'dummy_value', environment_scope: second_variable.environment_scope)
- end
-
- it 'has a duplicate key error' do
- subject
-
- expect(project.errors).to have_key(:variables)
- end
- end
- end
- end
-end
diff --git a/spec/views/groups/show.html.haml_spec.rb b/spec/views/groups/show.html.haml_spec.rb
new file mode 100644
index 00000000000..a53aab43c18
--- /dev/null
+++ b/spec/views/groups/show.html.haml_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'groups/show.html.haml' do
+ let_it_be(:user) { build(:user) }
+ let_it_be(:group) { create(:group) }
+
+ before do
+ assign(:group, group)
+ end
+
+ context 'when rendering with the layout' do
+ subject(:render_page) { render template: 'groups/show.html.haml', layout: 'layouts/group' }
+
+ describe 'invite team members' do
+ before do
+ allow(view).to receive(:session).and_return({})
+ allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:experiment_enabled?).and_return(false)
+ allow(view).to receive(:group_path).and_return('')
+ allow(view).to receive(:group_shared_path).and_return('')
+ allow(view).to receive(:group_archived_path).and_return('')
+ end
+
+ context 'when invite team members is not available in sidebar' do
+ before do
+ allow(view).to receive(:can_invite_members_for_group?).and_return(false)
+ end
+
+ it 'does not display the js-invite-members-trigger' do
+ render_page
+
+ expect(rendered).not_to have_selector('.js-invite-members-trigger')
+ end
+ end
+
+ context 'when invite team members is available' do
+ before do
+ allow(view).to receive(:can_invite_members_for_group?).and_return(true)
+ end
+
+ it 'includes the div for js-invite-members-trigger' do
+ render_page
+
+ expect(rendered).to have_selector('.js-invite-members-trigger')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb
index 15fdfaaaa65..6752bdc8337 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -92,7 +92,8 @@ RSpec.describe 'layouts/_head' do
before do
stub_config(extra: {
matomo_url: matomo_host,
- matomo_site_id: 12345
+ matomo_site_id: 12345,
+ matomo_disable_cookies: false
})
end
@@ -101,6 +102,19 @@ RSpec.describe 'layouts/_head' do
expect(rendered).to match(/<script.*>.*var u="\/\/#{matomo_host}\/".*<\/script>/m)
expect(rendered).to match(%r(<noscript>.*<img src="//#{matomo_host}/matomo.php.*</noscript>))
+ expect(rendered).not_to include('_paq.push(["disableCookies"])')
+ end
+
+ context 'when matomo_disable_cookies is true' do
+ before do
+ stub_config(extra: { matomo_url: matomo_host, matomo_site_id: 12345, matomo_disable_cookies: true })
+ end
+
+ it 'disables cookies' do
+ render
+
+ expect(rendered).to include('_paq.push(["disableCookies"])')
+ end
end
end
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index 01892e72c97..80342cbdb41 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'layouts/header/_new_dropdown' do
before do
allow(Gitlab::Experimentation).to receive(:active?).and_return(true)
allow(view).to receive(:experiment_tracking_category_and_group)
- allow(view).to receive(:tracking_label).with(user)
+ allow(view).to receive(:tracking_label)
end
context 'with ability to invite members' do
@@ -20,8 +20,8 @@ RSpec.describe 'layouts/header/_new_dropdown' do
subject
expect(view).to have_received(:experiment_tracking_category_and_group)
- .with(:invite_members_new_dropdown, subject: user)
- expect(view).to have_received(:tracking_label).with(user)
+ .with(:invite_members_new_dropdown)
+ expect(view).to have_received(:tracking_label)
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 c5b56b15431..e34d8b91b38 100644
--- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
@@ -48,7 +48,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
describe 'Packages' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
let_it_be(:package_menu_name) { 'Packages & Registries' }
let_it_be(:package_entry_name) { 'Package Registry' }
diff --git a/spec/views/layouts/nav/sidebar/_project_security_link.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project_security_link.html.haml_spec.rb
new file mode 100644
index 00000000000..d3fb35bff6d
--- /dev/null
+++ b/spec/views/layouts/nav/sidebar/_project_security_link.html.haml_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'layouts/nav/sidebar/_project_security_link' do
+ let_it_be_with_reload(:project) { create(:project) }
+ context 'on security configuration' do
+ before do
+ assign(:project, project)
+ allow(controller).to receive(:controller_name).and_return('configuration')
+ allow(controller).to receive(:controller_path).and_return('projects/security/configuration')
+ allow(controller).to receive(:action_name).and_return('show')
+ allow(view).to receive(:any_project_nav_tab?).and_return(true)
+ allow(view).to receive(:project_nav_tab?).and_return(true)
+ end
+
+ it 'activates Security & Compliance tab' do
+ render
+
+ expect(rendered).to have_css('li.active', text: 'Security & Compliance')
+ end
+
+ it 'activates Configuration sub tab' do
+ render
+
+ expect(rendered).to have_css('.sidebar-sub-level-items > li.active', text: 'Configuration')
+ end
+ end
+end
diff --git a/spec/views/layouts/profile.html.haml_spec.rb b/spec/views/layouts/profile.html.haml_spec.rb
new file mode 100644
index 00000000000..93f8a075209
--- /dev/null
+++ b/spec/views/layouts/profile.html.haml_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'layouts/profile' do
+ let(:user) { create(:user) }
+
+ before do
+ allow(view).to receive(:session).and_return({})
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
+ allow(view).to receive(:experiment_enabled?).and_return(false)
+ allow(view).to receive(:enable_search_settings).and_call_original
+ end
+
+ it 'calls enable_search_settings helper with a custom container class' do
+ render
+ expect(view).to have_received(:enable_search_settings)
+ .with({ locals: { container_class: 'gl-my-5' } })
+ end
+
+ context 'when search_settings_in_page feature flag is on' do
+ it 'displays the search settings entry point' do
+ render
+ expect(rendered).to include('js-search-settings-app')
+ end
+ end
+
+ context 'when search_settings_in_page feature flag is off' do
+ before do
+ stub_feature_flags(search_settings_in_page: false)
+ end
+
+ it 'does not display the search settings entry point' do
+ render
+ expect(rendered).not_to include('js-search-settings-app')
+ end
+ end
+end
diff --git a/spec/views/projects/_home_panel.html.haml_spec.rb b/spec/views/projects/_home_panel.html.haml_spec.rb
index 548dba7874a..cc0eb9919da 100644
--- a/spec/views/projects/_home_panel.html.haml_spec.rb
+++ b/spec/views/projects/_home_panel.html.haml_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'projects/_home_panel' do
let(:project) { create(:project) }
before do
+ stub_feature_flags(vue_notification_dropdown: false)
assign(:project, project)
allow(view).to receive(:current_user).and_return(user)
diff --git a/spec/views/projects/empty.html.haml_spec.rb b/spec/views/projects/empty.html.haml_spec.rb
index de83722160e..6762dcd22d5 100644
--- a/spec/views/projects/empty.html.haml_spec.rb
+++ b/spec/views/projects/empty.html.haml_spec.rb
@@ -79,4 +79,41 @@ RSpec.describe 'projects/empty' do
it_behaves_like 'no invite member info'
end
end
+
+ context 'when rendering with the layout' do
+ subject(:render_page) { render template: 'projects/empty.html.haml', layout: 'layouts/project' }
+
+ describe 'invite team members' do
+ before do
+ allow(view).to receive(:session).and_return({})
+ allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:experiment_enabled?).and_return(false)
+ end
+
+ context 'when invite team members is not available in sidebar' do
+ before do
+ allow(view).to receive(:can_invite_members_for_project?).and_return(false)
+ end
+
+ it 'does not display the js-invite-members-trigger' do
+ render_page
+
+ expect(rendered).not_to have_selector('.js-invite-members-trigger')
+ end
+ end
+
+ context 'when invite team members is available' do
+ before do
+ allow(view).to receive(:can_invite_members_for_project?).and_return(true)
+ end
+
+ it 'includes the div for js-invite-members-trigger' do
+ render_page
+
+ expect(rendered).to have_selector('.js-invite-members-trigger')
+ end
+ end
+ end
+ end
end
diff --git a/spec/views/projects/show.html.haml_spec.rb b/spec/views/projects/show.html.haml_spec.rb
new file mode 100644
index 00000000000..995e31e83af
--- /dev/null
+++ b/spec/views/projects/show.html.haml_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'projects/show.html.haml' do
+ let_it_be(:user) { build(:user) }
+ let_it_be(:project) { ProjectPresenter.new(create(:project, :repository), current_user: user) }
+
+ before do
+ assign(:project, project)
+ end
+
+ context 'when rendering with the layout' do
+ subject(:render_page) { render template: 'projects/show.html.haml', layout: 'layouts/project' }
+
+ describe 'invite team members' do
+ before do
+ allow(view).to receive(:event_filter_link)
+ allow(view).to receive(:session).and_return({})
+ allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:experiment_enabled?).and_return(false)
+ allow(view).to receive(:add_page_startup_graphql_call)
+ end
+
+ context 'when invite team members is not available in sidebar' do
+ before do
+ allow(view).to receive(:can_invite_members_for_project?).and_return(false)
+ end
+
+ it 'does not display the js-invite-members-trigger' do
+ render_page
+
+ expect(rendered).not_to have_selector('.js-invite-members-trigger')
+ end
+ end
+
+ context 'when invite team members is available' do
+ before do
+ allow(view).to receive(:can_invite_members_for_project?).and_return(true)
+ end
+
+ it 'includes the div for js-invite-members-trigger' do
+ render_page
+
+ expect(rendered).to have_selector('.js-invite-members-trigger')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/views/projects/tree/_tree_row.html.haml_spec.rb b/spec/views/projects/tree/_tree_row.html.haml_spec.rb
deleted file mode 100644
index 43a37934afd..00000000000
--- a/spec/views/projects/tree/_tree_row.html.haml_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'projects/tree/_tree_row' do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
-
- # rubocop: disable Rails/FindBy
- # This is not ActiveRecord where..first
- let(:blob_item) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID, 'files/ruby').first }
- # rubocop: enable Rails/FindBy
-
- before do
- assign(:project, project)
- assign(:repository, repository)
- assign(:id, File.join('master', ''))
- assign(:lfs_blob_ids, [])
- end
-
- it 'renders blob item' do
- render_partial(blob_item)
-
- expect(rendered).to have_content(blob_item.name)
- expect(rendered).not_to have_selector('.label-lfs', text: 'LFS')
- end
-
- describe 'LFS blob' do
- before do
- assign(:lfs_blob_ids, [blob_item].map(&:id))
-
- render_partial(blob_item)
- end
-
- it 'renders LFS badge' do
- expect(rendered).to have_selector('.label-lfs', text: 'LFS')
- end
- end
-
- def render_partial(items)
- render partial: 'projects/tree/tree_row', collection: [items].flatten
- end
-end
diff --git a/spec/views/registrations/welcome/show.html.haml_spec.rb b/spec/views/registrations/welcome/show.html.haml_spec.rb
index bede52bed4b..f731594e9ee 100644
--- a/spec/views/registrations/welcome/show.html.haml_spec.rb
+++ b/spec/views/registrations/welcome/show.html.haml_spec.rb
@@ -13,7 +13,6 @@ RSpec.describe 'registrations/welcome/show' do
allow(view).to receive(:in_trial_flow?).and_return(false)
allow(view).to receive(:in_invitation_flow?).and_return(false)
allow(view).to receive(:in_oauth_flow?).and_return(false)
- allow(view).to receive(:experiment_enabled?).with(:onboarding_issues).and_return(false)
allow(Gitlab).to receive(:com?).and_return(false)
render
diff --git a/spec/views/search/_filter.html.haml_spec.rb b/spec/views/search/_filter.html.haml_spec.rb
deleted file mode 100644
index 868408f7beb..00000000000
--- a/spec/views/search/_filter.html.haml_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'search/_filter' do
- context 'when the search page is opened' do
- it 'displays the correct elements' do
- render
-
- expect(rendered).to have_selector('label[for="dashboard_search_group"]')
- expect(rendered).to have_selector('input#js-search-group-dropdown')
-
- expect(rendered).to have_selector('label[for="dashboard_search_project"]')
- expect(rendered).to have_selector('input#js-search-project-dropdown')
- end
- end
-end
diff --git a/spec/views/search/_form.html.haml_spec.rb b/spec/views/search/_form.html.haml_spec.rb
deleted file mode 100644
index 073a39e4ed6..00000000000
--- a/spec/views/search/_form.html.haml_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'search/_form' do
- context 'when the search page is opened' do
- it 'displays the correct elements' do
- render
-
- expect(rendered).to have_selector('.search-field-holder.form-group')
- expect(rendered).to have_selector('label[for="dashboard_search"]')
- end
- end
-end
diff --git a/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb b/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb
new file mode 100644
index 00000000000..400319a42b7
--- /dev/null
+++ b/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'shared/ssh_keys/_key_delete.html.haml' do
+ context 'when the text parameter is used' do
+ it 'has text' do
+ render 'shared/ssh_keys/key_delete.html.haml', text: 'Button', html_class: '', button_data: ''
+
+ expect(rendered).to have_button('Button')
+ end
+ end
+
+ context 'when the text parameter is not used' do
+ it 'does not have text' do
+ render 'shared/ssh_keys/key_delete.html.haml', html_class: '', button_data: ''
+
+ expect(rendered).to have_button('Delete')
+ end
+ end
+end
diff --git a/spec/workers/build_coverage_worker_spec.rb b/spec/workers/build_coverage_worker_spec.rb
deleted file mode 100644
index 4beb6e5972f..00000000000
--- a/spec/workers/build_coverage_worker_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BuildCoverageWorker do
- describe '#perform' do
- context 'when build exists' do
- let!(:build) { create(:ci_build) }
-
- it 'updates code coverage' do
- expect_any_instance_of(Ci::Build)
- .to receive(:update_coverage)
-
- described_class.new.perform(build.id)
- end
- end
-
- context 'when build does not exist' do
- it 'does not raise exception' do
- expect { described_class.new.perform(123) }
- .not_to raise_error
- end
- end
- end
-end
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
index 02e15b7bc22..6d040f83dc7 100644
--- a/spec/workers/build_finished_worker_spec.rb
+++ b/spec/workers/build_finished_worker_spec.rb
@@ -11,20 +11,16 @@ RSpec.describe BuildFinishedWorker do
context 'when build exists' do
let!(:build) { create(:ci_build) }
- it 'calculates coverage and calls hooks', :aggregate_failures do
- trace_worker = double('trace worker')
- coverage_worker = double('coverage worker')
-
- allow(BuildTraceSectionsWorker).to receive(:new).and_return(trace_worker)
- allow(BuildCoverageWorker).to receive(:new).and_return(coverage_worker)
+ before do
+ expect(Ci::Build).to receive(:find_by).with(id: build.id).and_return(build)
+ end
- # Unfortunately, `ordered` does not seem to work when called within `allow_next_instance_of`
- # so we're doing this the long and dirty way
- expect(trace_worker).to receive(:perform).ordered
- expect(coverage_worker).to receive(:perform).ordered
+ it 'calculates coverage and calls hooks', :aggregate_failures do
+ expect(build).to receive(:parse_trace_sections!).ordered
+ expect(build).to receive(:update_coverage).ordered
- expect_next_instance_of(Ci::BuildReportResultWorker) do |instance|
- expect(instance).to receive(:perform)
+ expect_next_instance_of(Ci::BuildReportResultService) do |build_report_result_service|
+ expect(build_report_result_service).to receive(:execute).with(build)
end
expect(BuildHooksWorker).to receive(:perform_async)
diff --git a/spec/workers/build_trace_sections_worker_spec.rb b/spec/workers/build_trace_sections_worker_spec.rb
deleted file mode 100644
index 1c84b0083fb..00000000000
--- a/spec/workers/build_trace_sections_worker_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BuildTraceSectionsWorker do
- describe '#perform' do
- context 'when build exists' do
- let!(:build) { create(:ci_build) }
-
- it 'updates trace sections' do
- expect_any_instance_of(Ci::Build)
- .to receive(:parse_trace_sections!)
-
- described_class.new.perform(build.id)
- end
- end
-
- context 'when build does not exist' do
- it 'does not raise exception' do
- expect { described_class.new.perform(123) }
- .not_to raise_error
- end
- end
- end
-end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index d3a4144d606..8cf14ed6f8b 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -72,6 +72,21 @@ RSpec.describe BulkImportWorker do
expect(bulk_import.entities.map(&:status_name)).to contain_exactly(:created, :started)
end
end
+
+ context 'when exception occurs' do
+ it 'tracks the exception & marks import as failed' do
+ bulk_import = create(:bulk_import, :created)
+ create(:bulk_import_entity, :created, bulk_import: bulk_import)
+
+ allow(BulkImports::EntityWorker).to receive(:perform_async).and_raise(StandardError)
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(kind_of(StandardError), bulk_import_id: bulk_import.id)
+
+ subject.perform(bulk_import.id)
+
+ expect(bulk_import.reload.failed?).to eq(true)
+ end
+ end
end
end
end
diff --git a/spec/workers/bulk_imports/entity_worker_spec.rb b/spec/workers/bulk_imports/entity_worker_spec.rb
index 31515b31947..cd9a6f605b9 100644
--- a/spec/workers/bulk_imports/entity_worker_spec.rb
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -24,6 +24,20 @@ RSpec.describe BulkImports::EntityWorker do
expect(entity.reload.jid).to eq(jid)
end
+
+ context 'when exception occurs' do
+ it 'tracks the exception & marks entity as failed' do
+ allow(BulkImports::Importers::GroupImporter).to receive(:new) { raise StandardError }
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(kind_of(StandardError), bulk_import_id: bulk_import.id, entity_id: entity.id)
+
+ subject.perform(entity.id)
+
+ expect(entity.reload.failed?).to eq(true)
+ end
+ end
end
context 'when started entity does not exist' do
diff --git a/spec/workers/ci/build_report_result_worker_spec.rb b/spec/workers/ci/build_report_result_worker_spec.rb
deleted file mode 100644
index aedfa70c8b8..00000000000
--- a/spec/workers/ci/build_report_result_worker_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::BuildReportResultWorker do
- subject { described_class.new.perform(build_id) }
-
- context 'when build exists' do
- let(:build) { create(:ci_build) }
- let(:build_id) { build.id }
-
- it 'calls build report result service' do
- expect_next_instance_of(Ci::BuildReportResultService) do |build_report_result_service|
- expect(build_report_result_service).to receive(:execute)
- end
-
- subject
- end
- end
-
- context 'when build does not exist' do
- let(:build_id) { -1 }
-
- it 'does not call build report result service' do
- expect(Ci::BuildReportResultService).not_to receive(:execute)
-
- subject
- end
- end
-end
diff --git a/spec/workers/ci/pipeline_artifacts/create_quality_report_worker_spec.rb b/spec/workers/ci/pipeline_artifacts/create_quality_report_worker_spec.rb
new file mode 100644
index 00000000000..be351032b58
--- /dev/null
+++ b/spec/workers/ci/pipeline_artifacts/create_quality_report_worker_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::PipelineArtifacts::CreateQualityReportWorker do
+ describe '#perform' do
+ subject { described_class.new.perform(pipeline_id) }
+
+ context 'when pipeline exists' do
+ let(:pipeline) { create(:ci_pipeline, :with_codequality_reports) }
+ let(:pipeline_id) { pipeline.id }
+
+ it 'calls pipeline codequality report service' do
+ expect_next_instance_of(::Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService) do |quality_report_service|
+ expect(quality_report_service).to receive(:execute)
+ end
+
+ subject
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { pipeline_id }
+
+ it 'creates a pipeline artifact' do
+ expect { subject }.to change { pipeline.pipeline_artifacts.count }.by(1)
+ end
+ end
+ end
+
+ context 'when pipeline does not exist' do
+ let(:pipeline_id) { non_existing_record_id }
+
+ it 'does not call pipeline codequality report service' do
+ expect(Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService).not_to receive(:execute)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb b/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
index 9e9aa962b63..2bdd8345374 100644
--- a/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
+++ b/spec/workers/ci/pipeline_artifacts/expire_artifacts_worker_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Ci::PipelineArtifacts::ExpireArtifactsWorker do
describe '#perform' do
let_it_be(:pipeline_artifact) do
- create(:ci_pipeline_artifact, expire_at: 1.week.ago)
+ create(:ci_pipeline_artifact, :with_coverage_report, expire_at: 1.week.ago)
end
it 'executes a service' do
diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
index e6592f7f204..eb4faaed769 100644
--- a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
+++ b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb
@@ -82,6 +82,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
it 'skips the repository' do
expect(ContainerExpirationPolicies::CleanupService).not_to receive(:new)
expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:project_id, repository.project.id)
expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, :skipped)
expect { subject }.to change { ContainerRepository.waiting_for_cleanup.count }.from(1).to(0)
@@ -198,7 +199,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end
end
- def cleanup_service_response(status: :finished, repository:, cleanup_tags_service_original_size: 100, cleanup_tags_service_before_truncate_size: 80, cleanup_tags_service_after_truncate_size: 80, cleanup_tags_service_before_delete_size: 50)
+ def cleanup_service_response(status: :finished, repository:, cleanup_tags_service_original_size: 100, cleanup_tags_service_before_truncate_size: 80, cleanup_tags_service_after_truncate_size: 80, cleanup_tags_service_before_delete_size: 50, cleanup_tags_service_deleted_size: 50)
ServiceResponse.success(
message: "cleanup #{status}",
payload: {
@@ -213,13 +214,16 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do
end
def expect_log_extra_metadata(service_response:, cleanup_status: :finished, truncated: false)
- expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, cleanup_status)
expect(worker).to receive(:log_extra_metadata_on_done).with(:container_repository_id, repository.id)
- %i[cleanup_tags_service_original_size cleanup_tags_service_before_truncate_size cleanup_tags_service_after_truncate_size cleanup_tags_service_before_delete_size].each do |field|
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:project_id, repository.project.id)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_status, cleanup_status)
+
+ %i[cleanup_tags_service_original_size cleanup_tags_service_before_truncate_size cleanup_tags_service_after_truncate_size cleanup_tags_service_before_delete_size cleanup_tags_service_deleted_size].each do |field|
value = service_response.payload[field]
expect(worker).to receive(:log_extra_metadata_on_done).with(field, value) unless value.nil?
end
expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_tags_service_truncated, truncated)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:running_jobs_count, 0)
end
end
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index 13089549086..3df64c35166 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -5,350 +5,22 @@ require 'fileutils'
require 'spec_helper'
RSpec.describe GitGarbageCollectWorker do
- include GitHelpers
-
let_it_be(:project) { create(:project, :repository) }
- let(:shell) { Gitlab::Shell.new }
- let!(:lease_uuid) { SecureRandom.uuid }
- let!(:lease_key) { "project_housekeeping:#{project.id}" }
- let(:params) { [project.id, task, lease_key, lease_uuid] }
-
- subject { described_class.new }
-
- shared_examples 'it calls Gitaly' do
- specify do
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(gitaly_task)
- .and_return(nil)
-
- subject.perform(*params)
- end
- end
- shared_examples 'it updates the project statistics' do
- it 'updates the project statistics' do
- expect_next_instance_of(Projects::UpdateStatisticsService, project, nil, statistics: [:repository_size, :lfs_objects_size]) do |service|
- expect(service).to receive(:execute).and_call_original
- end
-
- subject.perform(*params)
- end
+ let(:lease_uuid) { SecureRandom.uuid }
+ let(:lease_key) { "project_housekeeping:#{project.id}" }
+ let(:task) { :full_repack }
+ let(:params) { [project.id, task, lease_key, lease_uuid] }
- it 'does nothing if the database is read-only' do
- allow(Gitlab::Database).to receive(:read_only?) { true }
-
- expect_any_instance_of(Projects::UpdateStatisticsService).not_to receive(:execute)
-
- subject.perform(*params)
- end
- end
+ subject { described_class.new }
describe "#perform" do
- let(:gitaly_task) { :garbage_collect }
- let(:task) { :gc }
-
- context 'with active lease_uuid' do
- before do
- allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
- end
-
- it_behaves_like 'it calls Gitaly'
- it_behaves_like 'it updates the project statistics'
-
- it "flushes ref caches when the task if 'gc'" do
- expect(subject).to receive(:renew_lease).with(lease_key, lease_uuid).and_call_original
- expect_any_instance_of(Repository).to receive(:expire_branches_cache).and_call_original
- expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
- expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
- expect_any_instance_of(Gitlab::Git::Repository).to receive(:has_visible_content?).and_call_original
-
- subject.perform(*params)
- end
-
- it 'handles gRPC errors' do
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect).and_raise(GRPC::NotFound)
-
- expect { subject.perform(*params) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
- end
- end
-
- context 'with different lease than the active one' do
- before do
- allow(subject).to receive(:get_lease_uuid).and_return(SecureRandom.uuid)
- end
-
- it 'returns silently' do
- expect_any_instance_of(Repository).not_to receive(:expire_branches_cache).and_call_original
- expect_any_instance_of(Repository).not_to receive(:branch_names).and_call_original
- expect_any_instance_of(Repository).not_to receive(:has_visible_content?).and_call_original
-
- subject.perform(*params)
- end
- end
-
- context 'with no active lease' do
- let(:params) { [project.id] }
-
- before do
- allow(subject).to receive(:get_lease_uuid).and_return(false)
- end
-
- context 'when is able to get the lease' do
- before do
- allow(subject).to receive(:try_obtain_lease).and_return(SecureRandom.uuid)
- end
-
- it_behaves_like 'it calls Gitaly'
- it_behaves_like 'it updates the project statistics'
-
- it "flushes ref caches when the task if 'gc'" do
- expect(subject).to receive(:get_lease_uuid).with("git_gc:#{task}:#{project.id}").and_return(false)
- expect_any_instance_of(Repository).to receive(:expire_branches_cache).and_call_original
- expect_any_instance_of(Repository).to receive(:branch_names).and_call_original
- expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original
- expect_any_instance_of(Gitlab::Git::Repository).to receive(:has_visible_content?).and_call_original
-
- subject.perform(*params)
- end
-
- context 'when the repository has joined a pool' do
- let!(:pool) { create(:pool_repository, :ready) }
- let(:project) { pool.source_project }
-
- it 'ensures the repositories are linked' do
- expect_any_instance_of(PoolRepository).to receive(:link_repository).once
-
- subject.perform(*params)
- end
- end
-
- context 'LFS object garbage collection' do
- before do
- stub_lfs_setting(enabled: true)
- end
-
- let_it_be(:lfs_reference) { create(:lfs_objects_project, project: project) }
- let(:lfs_object) { lfs_reference.lfs_object }
-
- it 'cleans up unreferenced LFS objects' do
- expect_next_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences) do |svc|
- expect(svc.project).to eq(project)
- expect(svc.dry_run).to be_falsy
- expect(svc).to receive(:run!).and_call_original
- end
-
- subject.perform(*params)
-
- expect(project.lfs_objects.reload).not_to include(lfs_object)
- end
-
- it 'catches and logs exceptions' do
- expect_any_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences)
- .to receive(:run!)
- .and_raise(/Failed/)
-
- expect(Gitlab::GitLogger).to receive(:warn)
- expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
-
- subject.perform(*params)
- end
-
- it 'does nothing if the database is read-only' do
- allow(Gitlab::Database).to receive(:read_only?) { true }
- expect_any_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences).not_to receive(:run!)
-
- subject.perform(*params)
-
- expect(project.lfs_objects.reload).to include(lfs_object)
- end
- end
- end
-
- context 'when no lease can be obtained' do
- before do
- expect(subject).to receive(:try_obtain_lease).and_return(false)
- end
-
- it 'returns silently' do
- expect(subject).not_to receive(:command)
- expect_any_instance_of(Repository).not_to receive(:expire_branches_cache).and_call_original
- expect_any_instance_of(Repository).not_to receive(:branch_names).and_call_original
- expect_any_instance_of(Repository).not_to receive(:has_visible_content?).and_call_original
-
- subject.perform(*params)
- end
- end
- end
-
- context "repack_full" do
- let(:task) { :full_repack }
- let(:gitaly_task) { :repack_full }
-
- before do
- expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
+ it 'calls the Projects::GitGarbageGitGarbageCollectWorker with the same params' do
+ expect_next_instance_of(Projects::GitGarbageCollectWorker) do |instance|
+ expect(instance).to receive(:perform).with(*params)
end
- it_behaves_like 'it calls Gitaly'
- it_behaves_like 'it updates the project statistics'
- end
-
- context "pack_refs" do
- let(:task) { :pack_refs }
- let(:gitaly_task) { :pack_refs }
-
- before do
- expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
- end
-
- it "calls Gitaly" do
- expect_any_instance_of(Gitlab::GitalyClient::RefService).to receive(task)
- .and_return(nil)
-
- subject.perform(*params)
- end
-
- it 'does not update the project statistics' do
- expect(Projects::UpdateStatisticsService).not_to receive(:new)
-
- subject.perform(*params)
- end
- end
-
- context "repack_incremental" do
- let(:task) { :incremental_repack }
- let(:gitaly_task) { :repack_incremental }
-
- before do
- expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
- end
-
- it_behaves_like 'it calls Gitaly'
- it_behaves_like 'it updates the project statistics'
- end
-
- shared_examples 'gc tasks' do
- before do
- allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
- allow(subject).to receive(:bitmaps_enabled?).and_return(bitmaps_enabled)
- end
-
- it 'incremental repack adds a new packfile' do
- create_objects(project)
- before_packs = packs(project)
-
- expect(before_packs.count).to be >= 1
-
- subject.perform(project.id, 'incremental_repack', lease_key, lease_uuid)
- after_packs = packs(project)
-
- # Exactly one new pack should have been created
- expect(after_packs.count).to eq(before_packs.count + 1)
-
- # Previously existing packs are still around
- expect(before_packs & after_packs).to eq(before_packs)
- end
-
- it 'full repack consolidates into 1 packfile' do
- create_objects(project)
- subject.perform(project.id, 'incremental_repack', lease_key, lease_uuid)
- before_packs = packs(project)
-
- expect(before_packs.count).to be >= 2
-
- subject.perform(project.id, 'full_repack', lease_key, lease_uuid)
- after_packs = packs(project)
-
- expect(after_packs.count).to eq(1)
-
- # Previously existing packs should be gone now
- expect(after_packs - before_packs).to eq(after_packs)
-
- expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled)
- end
-
- it 'gc consolidates into 1 packfile and updates packed-refs' do
- create_objects(project)
- before_packs = packs(project)
- before_packed_refs = packed_refs(project)
-
- expect(before_packs.count).to be >= 1
-
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
- .to receive(:garbage_collect)
- .with(bitmaps_enabled, prune: false)
- .and_call_original
-
- subject.perform(project.id, 'gc', lease_key, lease_uuid)
- after_packed_refs = packed_refs(project)
- after_packs = packs(project)
-
- expect(after_packs.count).to eq(1)
-
- # Previously existing packs should be gone now
- expect(after_packs - before_packs).to eq(after_packs)
-
- # The packed-refs file should have been updated during 'git gc'
- expect(before_packed_refs).not_to eq(after_packed_refs)
-
- expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled)
- end
-
- it 'cleans up repository after finishing' do
- expect_any_instance_of(Project).to receive(:cleanup).and_call_original
-
- subject.perform(project.id, 'gc', lease_key, lease_uuid)
- end
-
- it 'prune calls garbage_collect with the option prune: true' do
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
- .to receive(:garbage_collect)
- .with(bitmaps_enabled, prune: true)
- .and_return(nil)
-
- subject.perform(project.id, 'prune', lease_key, lease_uuid)
- end
- end
-
- context 'with bitmaps enabled' do
- let(:bitmaps_enabled) { true }
-
- include_examples 'gc tasks'
- end
-
- context 'with bitmaps disabled' do
- let(:bitmaps_enabled) { false }
-
- include_examples 'gc tasks'
- end
- end
-
- # Create a new commit on a random new branch
- def create_objects(project)
- rugged = rugged_repo(project.repository)
- old_commit = rugged.branches.first.target
- new_commit_sha = Rugged::Commit.create(
- rugged,
- message: "hello world #{SecureRandom.hex(6)}",
- author: { email: 'foo@bar', name: 'baz' },
- committer: { email: 'foo@bar', name: 'baz' },
- tree: old_commit.tree,
- parents: [old_commit]
- )
- rugged.references.create("refs/heads/#{SecureRandom.hex(6)}", new_commit_sha)
- end
-
- def packs(project)
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- Dir["#{project.repository.path_to_repo}/objects/pack/*.pack"]
+ subject.perform(*params)
end
end
-
- def packed_refs(project)
- path = "#{project.repository.path_to_repo}/packed-refs"
- FileUtils.touch(path)
- File.read(path)
- end
-
- def bitmap_path(pack)
- pack.sub(/\.pack\z/, '.bitmap')
- end
end
diff --git a/spec/workers/jira_connect/sync_builds_worker_spec.rb b/spec/workers/jira_connect/sync_builds_worker_spec.rb
index 7c58803d778..8fb8692fdf7 100644
--- a/spec/workers/jira_connect/sync_builds_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_builds_worker_spec.rb
@@ -32,29 +32,5 @@ RSpec.describe ::JiraConnect::SyncBuildsWorker do
subject
end
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(jira_sync_builds: false)
- end
-
- it 'does not call the sync service' do
- expect_next(::JiraConnect::SyncService).not_to receive(:execute)
-
- subject
- end
- end
-
- context 'when the feature flag is enabled for this project' do
- before do
- stub_feature_flags(jira_sync_builds: pipeline.project)
- end
-
- it 'calls the sync service' do
- expect_next(::JiraConnect::SyncService).to receive(:execute)
-
- subject
- end
- end
end
end
diff --git a/spec/workers/jira_connect/sync_deployments_worker_spec.rb b/spec/workers/jira_connect/sync_deployments_worker_spec.rb
index 9485f4cd3a7..16fa2643d04 100644
--- a/spec/workers/jira_connect/sync_deployments_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_deployments_worker_spec.rb
@@ -32,29 +32,5 @@ RSpec.describe ::JiraConnect::SyncDeploymentsWorker do
subject
end
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(jira_sync_deployments: false)
- end
-
- it 'does not call the sync service' do
- expect_next(::JiraConnect::SyncService).not_to receive(:execute)
-
- subject
- end
- end
-
- context 'when the feature flag is enabled for this project' do
- before do
- stub_feature_flags(jira_sync_deployments: deployment.project)
- end
-
- it 'calls the sync service' do
- expect_next(::JiraConnect::SyncService).to receive(:execute)
-
- subject
- end
- end
end
end
diff --git a/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb b/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
index 035f4ebdd3c..038eed7b9f1 100644
--- a/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
@@ -32,29 +32,5 @@ RSpec.describe ::JiraConnect::SyncFeatureFlagsWorker do
subject
end
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(jira_sync_feature_flags: false)
- end
-
- it 'does not call the sync service' do
- expect_next(::JiraConnect::SyncService).not_to receive(:execute)
-
- subject
- end
- end
-
- context 'when the feature flag is enabled for this project' do
- before do
- stub_feature_flags(jira_sync_feature_flags: feature_flag.project)
- end
-
- it 'calls the sync service' do
- expect_next(::JiraConnect::SyncService).to receive(:execute)
-
- subject
- end
- end
end
end
diff --git a/spec/workers/merge_request_cleanup_refs_worker_spec.rb b/spec/workers/merge_request_cleanup_refs_worker_spec.rb
index 88d7322536b..7401c6dd4d7 100644
--- a/spec/workers/merge_request_cleanup_refs_worker_spec.rb
+++ b/spec/workers/merge_request_cleanup_refs_worker_spec.rb
@@ -17,6 +17,18 @@ RSpec.describe MergeRequestCleanupRefsWorker do
subject
end
end
+
+ context 'when merge_request_refs_cleanup flag is disabled' do
+ before do
+ stub_feature_flags(merge_request_refs_cleanup: false)
+ end
+
+ it 'does not clean up the merge request' do
+ expect(MergeRequests::CleanupRefsService).not_to receive(:new)
+
+ perform_multiple(1)
+ end
+ end
end
context 'when merge request does not exist' do
diff --git a/spec/workers/namespaceless_project_destroy_worker_spec.rb b/spec/workers/namespaceless_project_destroy_worker_spec.rb
index 618cd9cabe9..cd66af82364 100644
--- a/spec/workers/namespaceless_project_destroy_worker_spec.rb
+++ b/spec/workers/namespaceless_project_destroy_worker_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe NamespacelessProjectDestroyWorker do
subject.perform(project.id)
end
- it 'does not do anything in Project#remove_pages method' do
+ it 'does not do anything in Project#legacy_remove_pages method' do
expect(Gitlab::PagesTransfer).not_to receive(:new)
subject.perform(project.id)
diff --git a/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb b/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb
new file mode 100644
index 00000000000..722ecfc1dec
--- /dev/null
+++ b/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::InProductMarketingEmailsWorker, '#perform' do
+ context 'when the experiment is inactive' do
+ before do
+ stub_experiment(in_product_marketing_emails: false)
+ end
+
+ it 'does not execute the in product marketing emails service' do
+ expect(Namespaces::InProductMarketingEmailsService).not_to receive(:send_for_all_tracks_and_intervals)
+
+ subject.perform
+ end
+ end
+
+ context 'when the experiment is active' do
+ before do
+ stub_experiment(in_product_marketing_emails: true)
+ end
+
+ it 'calls the send_for_all_tracks_and_intervals method on the in product marketing emails service' do
+ expect(Namespaces::InProductMarketingEmailsService).to receive(:send_for_all_tracks_and_intervals)
+
+ subject.perform
+ end
+ end
+end
diff --git a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
index f1789fa8fbd..6d69ccb50bd 100644
--- a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
+++ b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
@@ -3,30 +3,15 @@
require 'spec_helper'
RSpec.describe Namespaces::OnboardingPipelineCreatedWorker, '#perform' do
- include AfterNextHelpers
-
let_it_be(:ci_pipeline) { create(:ci_pipeline) }
- before do
- OnboardingProgress.onboard(ci_pipeline.project.namespace)
- end
-
- it 'registers an onboarding progress action' do
- expect_next(OnboardingProgressService, ci_pipeline.project.namespace)
- .to receive(:execute).with(action: :pipeline_created).and_call_original
+ it_behaves_like 'records an onboarding progress action', :pipeline_created do
+ let(:namespace) { ci_pipeline.project.namespace }
- subject.perform(ci_pipeline.project.namespace_id)
-
- expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(true)
+ subject { described_class.new.perform(ci_pipeline.project.namespace_id) }
end
- context "when a namespace doesn't exist" do
- it 'does not register an onboarding progress action' do
- expect_next(OnboardingProgressService, ci_pipeline.project.namespace).not_to receive(:execute)
-
- subject.perform(nil)
-
- expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(false)
- end
+ it_behaves_like 'does not record an onboarding progress action' do
+ subject { described_class.new.perform(nil) }
end
end
diff --git a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
index a773e160fab..14428c0ecb8 100644
--- a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
+++ b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
@@ -3,20 +3,9 @@
require 'spec_helper'
RSpec.describe Namespaces::OnboardingUserAddedWorker, '#perform' do
- include AfterNextHelpers
+ let_it_be(:namespace) { create(:group) }
- let_it_be(:group) { create(:group) }
+ subject { described_class.new.perform(namespace.id) }
- before do
- OnboardingProgress.onboard(group)
- end
-
- it 'registers an onboarding progress action' do
- expect_next(OnboardingProgressService, group)
- .to receive(:execute).with(action: :user_added).and_call_original
-
- subject.perform(group.id)
-
- expect(OnboardingProgress.completed?(group, :user_added)).to be(true)
- end
+ it_behaves_like 'records an onboarding progress action', :user_added
end
diff --git a/spec/workers/new_note_worker_spec.rb b/spec/workers/new_note_worker_spec.rb
index 86b6d041e5c..7ba3fe94254 100644
--- a/spec/workers/new_note_worker_spec.rb
+++ b/spec/workers/new_note_worker_spec.rb
@@ -65,4 +65,24 @@ RSpec.describe NewNoteWorker do
subject.perform(note.id)
end
end
+
+ context 'when Note author has been blocked' do
+ let_it_be(:note) { create(:note, author: create(:user, :blocked)) }
+
+ it "does not call NotificationService" do
+ expect(NotificationService).not_to receive(:new)
+
+ described_class.new.perform(note.id)
+ end
+ end
+
+ context 'when Note author has been deleted' do
+ let_it_be(:note) { create(:note, author: User.ghost) }
+
+ it "does not call NotificationService" do
+ expect(NotificationService).not_to receive(:new)
+
+ described_class.new.perform(note.id)
+ end
+ end
end
diff --git a/spec/workers/packages/composer/cache_cleanup_worker_spec.rb b/spec/workers/packages/composer/cache_cleanup_worker_spec.rb
new file mode 100644
index 00000000000..e69fe55acc2
--- /dev/null
+++ b/spec/workers/packages/composer/cache_cleanup_worker_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Composer::CacheCleanupWorker, type: :worker do
+ describe '#perform' do
+ let_it_be(:group) { create(:group) }
+
+ let!(:cache_file1) { create(:composer_cache_file, delete_at: nil, group: group, file_sha256: '124') }
+ let!(:cache_file2) { create(:composer_cache_file, delete_at: 2.days.from_now, group: group, file_sha256: '3456') }
+ let!(:cache_file3) { create(:composer_cache_file, delete_at: 1.day.ago, group: group, file_sha256: '5346') }
+ let!(:cache_file4) { create(:composer_cache_file, delete_at: nil, group: group, file_sha256: '56889') }
+
+ subject { described_class.new.perform }
+
+ before do
+ # emulate group deletion
+ cache_file4.update_columns(namespace_id: nil)
+ end
+
+ it 'deletes expired packages' do
+ expect { subject }.to change { Packages::Composer::CacheFile.count }.by(-2)
+ expect { cache_file1.reload }.not_to raise_error ActiveRecord::RecordNotFound
+ expect { cache_file2.reload }.not_to raise_error ActiveRecord::RecordNotFound
+ expect { cache_file3.reload }.to raise_error ActiveRecord::RecordNotFound
+ expect { cache_file4.reload }.to raise_error ActiveRecord::RecordNotFound
+ end
+ end
+end
diff --git a/spec/workers/pages_remove_worker_spec.rb b/spec/workers/pages_remove_worker_spec.rb
index 638e87043f2..864aa763fa9 100644
--- a/spec/workers/pages_remove_worker_spec.rb
+++ b/spec/workers/pages_remove_worker_spec.rb
@@ -3,24 +3,23 @@
require 'spec_helper'
RSpec.describe PagesRemoveWorker do
- let_it_be(:project) { create(:project, path: "my.project")}
- let_it_be(:domain) { create(:pages_domain, project: project) }
+ let(:project) { create(:project, path: "my.project")}
+ let!(:domain) { create(:pages_domain, project: project) }
+
subject { described_class.new.perform(project.id) }
+ before do
+ project.mark_pages_as_deployed
+ end
+
it 'deletes published pages' do
+ expect(project.pages_deployed?).to be(true)
+
expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
subject
- expect(project.reload.pages_metadatum.deployed?).to be(false)
- end
-
- it 'deletes all domains' do
- expect(project.pages_domains.count).to be 1
-
- subject
-
- expect(project.reload.pages_domains.count).to be 0
+ expect(project.reload.pages_deployed?).to be(false)
end
end
diff --git a/spec/workers/pages_transfer_worker_spec.rb b/spec/workers/pages_transfer_worker_spec.rb
index 248a3713bf6..7d17461bc5a 100644
--- a/spec/workers/pages_transfer_worker_spec.rb
+++ b/spec/workers/pages_transfer_worker_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe PagesTransferWorker do
describe '#perform' do
- Gitlab::PagesTransfer::Async::METHODS.each do |meth|
+ Gitlab::PagesTransfer::METHODS.each do |meth|
context "when method is #{meth}" do
let(:args) { [1, 2, 3] }
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 5b8d8878a99..aaae0988602 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -85,6 +85,14 @@ RSpec.describe PostReceive do
perform
end
+
+ it 'tracks an event for the new_project_readme experiment', :experiment do
+ expect_next_instance_of(NewProjectReadmeExperiment, :new_project_readme, nil, actor: empty_project.owner) do |e|
+ expect(e).to receive(:track_initial_writes).with(empty_project)
+ end
+
+ perform
+ end
end
shared_examples 'not updating remote mirrors' do
diff --git a/spec/workers/projects/git_garbage_collect_worker_spec.rb b/spec/workers/projects/git_garbage_collect_worker_spec.rb
new file mode 100644
index 00000000000..8c44643ae51
--- /dev/null
+++ b/spec/workers/projects/git_garbage_collect_worker_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::GitGarbageCollectWorker do
+ let_it_be(:project) { create(:project, :repository) }
+
+ 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
+
+ context 'when is able to get the lease' do
+ let(:params) { [project.id] }
+
+ subject { described_class.new }
+
+ before do
+ allow(subject).to receive(:get_lease_uuid).and_return(false)
+ allow(subject).to receive(:find_resource).and_return(project)
+ allow(subject).to receive(:try_obtain_lease).and_return(SecureRandom.uuid)
+ end
+
+ context 'when the repository has joined a pool' do
+ let!(:pool) { create(:pool_repository, :ready) }
+ let(:project) { pool.source_project }
+
+ it 'ensures the repositories are linked' do
+ expect(project.pool_repository).to receive(:link_repository).once
+
+ subject.perform(*params)
+ end
+ end
+
+ context 'LFS object garbage collection' do
+ let_it_be(:lfs_reference) { create(:lfs_objects_project, project: project) }
+ let(:lfs_object) { lfs_reference.lfs_object }
+
+ before do
+ stub_lfs_setting(enabled: true)
+ end
+
+ it 'cleans up unreferenced LFS objects' do
+ expect_next_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences) do |svc|
+ expect(svc.project).to eq(project)
+ expect(svc.dry_run).to be_falsy
+ expect(svc).to receive(:run!).and_call_original
+ end
+
+ subject.perform(*params)
+
+ expect(project.lfs_objects.reload).not_to include(lfs_object)
+ end
+
+ it 'catches and logs exceptions' do
+ allow_next_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences) do |svc|
+ allow(svg).to receive(:run!).and_raise(/Failed/)
+ end
+
+ expect(Gitlab::GitLogger).to receive(:warn)
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ subject.perform(*params)
+ end
+
+ it 'does nothing if the database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+ expect(Gitlab::Cleanup::OrphanLfsFileReferences).not_to receive(:new)
+
+ subject.perform(*params)
+
+ expect(project.lfs_objects.reload).to include(lfs_object)
+ end
+ end
+ end
+end
diff --git a/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb b/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb
index 0dd50efba1c..869818b257e 100644
--- a/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb
+++ b/spec/workers/schedule_merge_request_cleanup_refs_worker_spec.rb
@@ -20,6 +20,18 @@ RSpec.describe ScheduleMergeRequestCleanupRefsWorker do
worker.perform
end
+ context 'when merge_request_refs_cleanup flag is disabled' do
+ before do
+ stub_feature_flags(merge_request_refs_cleanup: false)
+ end
+
+ it 'does not schedule any merge request clean ups' do
+ expect(MergeRequestCleanupRefsWorker).not_to receive(:bulk_perform_in)
+
+ worker.perform
+ end
+ end
+
include_examples 'an idempotent worker' do
it 'schedules MergeRequestCleanupRefsWorker to be performed by batch' do
expect(MergeRequestCleanupRefsWorker)
diff --git a/spec/workers/user_status_cleanup/batch_worker_spec.rb b/spec/workers/user_status_cleanup/batch_worker_spec.rb
new file mode 100644
index 00000000000..2fd84d0e085
--- /dev/null
+++ b/spec/workers/user_status_cleanup/batch_worker_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe UserStatusCleanup::BatchWorker do
+ include_examples 'an idempotent worker' do
+ subject do
+ perform_multiple([], worker: described_class.new)
+ end
+ end
+
+ describe '#perform' do
+ subject(:run_worker) { described_class.new.perform }
+
+ context 'when no records are scheduled for cleanup' do
+ let(:user_status) { create(:user_status) }
+
+ it 'does nothing' do
+ expect { run_worker }.not_to change { user_status.reload }
+ end
+ end
+
+ it 'cleans up the records' do
+ user_status_1 = create(:user_status, clear_status_at: 1.year.ago)
+ user_status_2 = create(:user_status, clear_status_at: 2.years.ago)
+
+ run_worker
+
+ deleted_statuses = UserStatus.where(user_id: [user_status_1.user_id, user_status_2.user_id])
+ expect(deleted_statuses).to be_empty
+ end
+ end
+end
diff --git a/spec/workers/wikis/git_garbage_collect_worker_spec.rb b/spec/workers/wikis/git_garbage_collect_worker_spec.rb
new file mode 100644
index 00000000000..77c2e49a83a
--- /dev/null
+++ b/spec/workers/wikis/git_garbage_collect_worker_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Wikis::GitGarbageCollectWorker do
+ it_behaves_like 'can collect git garbage' do
+ let_it_be(:resource) { create(:project_wiki) }
+ let_it_be(:page) { create(:wiki_page, wiki: resource) }
+
+ let(:statistics_service_klass) { Projects::UpdateStatisticsService }
+ let(:statistics_keys) { [:wiki_size] }
+ let(:expected_default_lease) { "project_wikis:#{resource.id}" }
+ end
+end
diff --git a/tooling/danger/base_linter.rb b/tooling/danger/base_linter.rb
new file mode 100644
index 00000000000..c58f2d84dc8
--- /dev/null
+++ b/tooling/danger/base_linter.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require_relative 'title_linting'
+
+module Tooling
+ module Danger
+ class BaseLinter
+ MIN_SUBJECT_WORDS_COUNT = 3
+ MAX_LINE_LENGTH = 72
+
+ attr_reader :commit, :problems
+
+ def self.problems_mapping
+ {
+ subject_too_short: "The %s must contain at least #{MIN_SUBJECT_WORDS_COUNT} words",
+ subject_too_long: "The %s may not be longer than #{MAX_LINE_LENGTH} characters",
+ subject_starts_with_lowercase: "The %s must start with a capital letter",
+ subject_ends_with_a_period: "The %s must not end with a period"
+ }
+ end
+
+ def self.subject_description
+ 'commit subject'
+ end
+
+ def initialize(commit)
+ @commit = commit
+ @problems = {}
+ end
+
+ def failed?
+ problems.any?
+ end
+
+ def add_problem(problem_key, *args)
+ @problems[problem_key] = sprintf(self.class.problems_mapping[problem_key], *args)
+ end
+
+ def lint_subject
+ if subject_too_short?
+ add_problem(:subject_too_short, self.class.subject_description)
+ end
+
+ if subject_too_long?
+ add_problem(:subject_too_long, self.class.subject_description)
+ end
+
+ if subject_starts_with_lowercase?
+ add_problem(:subject_starts_with_lowercase, self.class.subject_description)
+ end
+
+ if subject_ends_with_a_period?
+ add_problem(:subject_ends_with_a_period, self.class.subject_description)
+ end
+
+ self
+ end
+
+ private
+
+ def subject
+ TitleLinting.remove_draft_flag(message_parts[0])
+ end
+
+ def subject_too_short?
+ subject.split(' ').length < MIN_SUBJECT_WORDS_COUNT
+ end
+
+ def subject_too_long?
+ line_too_long?(subject)
+ end
+
+ def line_too_long?(line)
+ line.length > MAX_LINE_LENGTH
+ end
+
+ def subject_starts_with_lowercase?
+ return false if ('A'..'Z').cover?(subject[0])
+
+ first_char = subject.sub(/\A(\[.+\]|\w+:)\s/, '')[0]
+ first_char_downcased = first_char.downcase
+ return true unless ('a'..'z').cover?(first_char_downcased)
+
+ first_char.downcase == first_char
+ end
+
+ def subject_ends_with_a_period?
+ subject.end_with?('.')
+ end
+
+ def message_parts
+ @message_parts ||= commit.message.split("\n", 3)
+ end
+ end
+ end
+end
diff --git a/tooling/danger/changelog.rb b/tooling/danger/changelog.rb
new file mode 100644
index 00000000000..f7f505f51a6
--- /dev/null
+++ b/tooling/danger/changelog.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require_relative 'title_linting'
+
+module Tooling
+ module Danger
+ module Changelog
+ NO_CHANGELOG_LABELS = [
+ 'tooling',
+ 'tooling::pipelines',
+ 'tooling::workflow',
+ 'ci-build',
+ 'meta'
+ ].freeze
+ NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
+ CREATE_CHANGELOG_COMMAND = 'bin/changelog -m %<mr_iid>s "%<mr_title>s"'
+ CREATE_EE_CHANGELOG_COMMAND = 'bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"'
+ CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n"
+ CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n"
+
+ OPTIONAL_CHANGELOG_MESSAGE = <<~MSG
+ If you want to create a changelog entry for GitLab FOSS, run the following:
+
+ #{CREATE_CHANGELOG_COMMAND}
+
+ If you want to create a changelog entry for GitLab EE, run the following instead:
+
+ #{CREATE_EE_CHANGELOG_COMMAND}
+
+ If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
+ MSG
+
+ REQUIRED_CHANGELOG_MESSAGE = <<~MSG
+ To create a changelog entry, run the following:
+
+ #{CREATE_CHANGELOG_COMMAND}
+
+ This merge request requires a changelog entry because it [introduces a database migration](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
+ MSG
+
+ def required?
+ git.added_files.any? { |path| path =~ %r{\Adb/(migrate|post_migrate)/} }
+ end
+ alias_method :db_changes?, :required?
+
+ def optional?
+ categories_need_changelog? && without_no_changelog_label?
+ end
+
+ def found
+ @found ||= git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
+ end
+
+ def ee_changelog?
+ found.start_with?('ee/')
+ end
+
+ def modified_text
+ CHANGELOG_MODIFIED_URL_TEXT +
+ format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
+ end
+
+ def required_text
+ CHANGELOG_MISSING_URL_TEXT +
+ format(REQUIRED_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
+ end
+
+ def optional_text
+ CHANGELOG_MISSING_URL_TEXT +
+ format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
+ end
+
+ private
+
+ def mr_iid
+ gitlab.mr_json["iid"]
+ end
+
+ def sanitized_mr_title
+ TitleLinting.sanitize_mr_title(gitlab.mr_json["title"])
+ end
+
+ def categories_need_changelog?
+ (helper.changes_by_category.keys - NO_CHANGELOG_CATEGORIES).any?
+ end
+
+ def without_no_changelog_label?
+ (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
+ end
+ end
+ end
+end
diff --git a/tooling/danger/commit_linter.rb b/tooling/danger/commit_linter.rb
new file mode 100644
index 00000000000..905031ec881
--- /dev/null
+++ b/tooling/danger/commit_linter.rb
@@ -0,0 +1,150 @@
+# frozen_string_literal: true
+
+require_relative 'base_linter'
+require_relative 'emoji_checker'
+
+module Tooling
+ module Danger
+ class CommitLinter < BaseLinter
+ MAX_CHANGED_FILES_IN_COMMIT = 3
+ MAX_CHANGED_LINES_IN_COMMIT = 30
+ SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(?<!`)(#|!|&|%)\d+(?<!`)}.freeze
+
+ def self.problems_mapping
+ super.merge(
+ {
+ separator_missing: "The commit subject and body must be separated by a blank line",
+ details_too_many_changes: "Commits that change #{MAX_CHANGED_LINES_IN_COMMIT} or more lines across " \
+ "at least #{MAX_CHANGED_FILES_IN_COMMIT} files must describe these changes in the commit body",
+ details_line_too_long: "The commit body should not contain more than #{MAX_LINE_LENGTH} characters per line",
+ message_contains_text_emoji: "Avoid the use of Markdown Emoji such as `:+1:`. These add limited value " \
+ "to the commit message, and are displayed as plain text outside of GitLab",
+ message_contains_unicode_emoji: "Avoid the use of Unicode Emoji. These add no value to the commit " \
+ "message, and may not be displayed properly everywhere",
+ message_contains_short_reference: "Use full URLs instead of short references (`gitlab-org/gitlab#123` or " \
+ "`!123`), as short references are displayed as plain text outside of GitLab"
+ }
+ )
+ end
+
+ def initialize(commit)
+ super
+
+ @linted = false
+ end
+
+ def fixup?
+ commit.message.start_with?('fixup!', 'squash!')
+ end
+
+ def suggestion?
+ commit.message.start_with?('Apply suggestion to')
+ end
+
+ def merge?
+ commit.message.start_with?('Merge branch')
+ end
+
+ def revert?
+ commit.message.start_with?('Revert "')
+ end
+
+ def multi_line?
+ !details.nil? && !details.empty?
+ end
+
+ def lint
+ return self if @linted
+
+ @linted = true
+ lint_subject
+ lint_separator
+ lint_details
+ lint_message
+
+ self
+ end
+
+ private
+
+ def lint_separator
+ return self unless separator && !separator.empty?
+
+ add_problem(:separator_missing)
+
+ self
+ end
+
+ def lint_details
+ if !multi_line? && many_changes?
+ add_problem(:details_too_many_changes)
+ end
+
+ details&.each_line do |line|
+ line_without_urls = line.strip.gsub(%r{https?://\S+}, '')
+
+ # If the line includes a URL, we'll allow it to exceed MAX_LINE_LENGTH characters, but
+ # only if the line _without_ the URL does not exceed this limit.
+ next unless line_too_long?(line_without_urls)
+
+ add_problem(:details_line_too_long)
+ break
+ end
+
+ self
+ end
+
+ def lint_message
+ if message_contains_text_emoji?
+ add_problem(:message_contains_text_emoji)
+ end
+
+ if message_contains_unicode_emoji?
+ add_problem(:message_contains_unicode_emoji)
+ end
+
+ if message_contains_short_reference?
+ add_problem(:message_contains_short_reference)
+ end
+
+ self
+ end
+
+ def files_changed
+ commit.diff_parent.stats[:total][:files]
+ end
+
+ def lines_changed
+ commit.diff_parent.stats[:total][:lines]
+ end
+
+ def many_changes?
+ files_changed > MAX_CHANGED_FILES_IN_COMMIT && lines_changed > MAX_CHANGED_LINES_IN_COMMIT
+ end
+
+ def separator
+ message_parts[1]
+ end
+
+ def details
+ message_parts[2]&.gsub(/^Signed-off-by.*$/, '')
+ end
+
+ def message_contains_text_emoji?
+ emoji_checker.includes_text_emoji?(commit.message)
+ end
+
+ def message_contains_unicode_emoji?
+ emoji_checker.includes_unicode_emoji?(commit.message)
+ end
+
+ def message_contains_short_reference?
+ commit.message.match?(SHORT_REFERENCE_REGEX)
+ end
+
+ def emoji_checker
+ @emoji_checker ||= Tooling::Danger::EmojiChecker.new
+ end
+ end
+ end
+end
diff --git a/tooling/danger/emoji_checker.rb b/tooling/danger/emoji_checker.rb
new file mode 100644
index 00000000000..9d8ff93037c
--- /dev/null
+++ b/tooling/danger/emoji_checker.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'json'
+
+module Tooling
+ module Danger
+ class EmojiChecker
+ DIGESTS = File.expand_path('../../fixtures/emojis/digests.json', __dir__)
+ ALIASES = File.expand_path('../../fixtures/emojis/aliases.json', __dir__)
+
+ # A regex that indicates a piece of text _might_ include an Emoji. The regex
+ # alone is not enough, as we'd match `:foo:bar:baz`. Instead, we use this
+ # regex to save us from having to check for all possible emoji names when we
+ # know one definitely is not included.
+ LIKELY_EMOJI = /:[\+a-z0-9_\-]+:/.freeze
+
+ UNICODE_EMOJI_REGEX = %r{(
+ [\u{1F300}-\u{1F5FF}] |
+ [\u{1F1E6}-\u{1F1FF}] |
+ [\u{2700}-\u{27BF}] |
+ [\u{1F900}-\u{1F9FF}] |
+ [\u{1F600}-\u{1F64F}] |
+ [\u{1F680}-\u{1F6FF}] |
+ [\u{2600}-\u{26FF}]
+ )}x.freeze
+
+ def initialize
+ names = JSON.parse(File.read(DIGESTS)).keys +
+ JSON.parse(File.read(ALIASES)).keys
+
+ @emoji = names.map { |name| ":#{name}:" }
+ end
+
+ def includes_text_emoji?(text)
+ return false unless text.match?(LIKELY_EMOJI)
+
+ @emoji.any? { |emoji| text.include?(emoji) }
+ end
+
+ def includes_unicode_emoji?(text)
+ text.match?(UNICODE_EMOJI_REGEX)
+ end
+ end
+ end
+end
diff --git a/tooling/danger/feature_flag.rb b/tooling/danger/feature_flag.rb
new file mode 100644
index 00000000000..2e65831ef9f
--- /dev/null
+++ b/tooling/danger/feature_flag.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'yaml'
+
+module Tooling
+ module Danger
+ module FeatureFlag
+ # `change_type` can be:
+ # - :added
+ # - :modified
+ # - :deleted
+ def feature_flag_files(change_type:)
+ files = git.public_send("#{change_type}_files") # rubocop:disable GitlabSecurity/PublicSend
+ files.select { |path| path =~ %r{\A(ee/)?config/feature_flags/} }.map { |path| Found.new(path) }
+ end
+
+ class Found
+ attr_reader :path
+
+ def initialize(path)
+ @path = path
+ end
+
+ def raw
+ @raw ||= File.read(path)
+ end
+
+ def group
+ @group ||= yaml['group']
+ end
+
+ def group_match_mr_label?(mr_group_label)
+ mr_group_label == group
+ end
+
+ private
+
+ def yaml
+ @yaml ||= YAML.safe_load(raw)
+ end
+ end
+ end
+ end
+end
diff --git a/tooling/danger/helper.rb b/tooling/danger/helper.rb
new file mode 100644
index 00000000000..60026ee9c70
--- /dev/null
+++ b/tooling/danger/helper.rb
@@ -0,0 +1,294 @@
+# frozen_string_literal: true
+
+require_relative 'teammate'
+require_relative 'title_linting'
+
+module Tooling
+ module Danger
+ module Helper
+ RELEASE_TOOLS_BOT = 'gitlab-release-tools-bot'
+
+ # Returns a list of all files that have been added, modified or renamed.
+ # `git.modified_files` might contain paths that already have been renamed,
+ # so we need to remove them from the list.
+ #
+ # Considering these changes:
+ #
+ # - A new_file.rb
+ # - D deleted_file.rb
+ # - M modified_file.rb
+ # - R renamed_file_before.rb -> renamed_file_after.rb
+ #
+ # it will return
+ # ```
+ # [ 'new_file.rb', 'modified_file.rb', 'renamed_file_after.rb' ]
+ # ```
+ #
+ # @return [Array<String>]
+ def all_changed_files
+ Set.new
+ .merge(git.added_files.to_a)
+ .merge(git.modified_files.to_a)
+ .merge(git.renamed_files.map { |x| x[:after] })
+ .subtract(git.renamed_files.map { |x| x[:before] })
+ .to_a
+ .sort
+ end
+
+ # Returns a string containing changed lines as git diff
+ #
+ # Considering changing a line in lib/gitlab/usage_data.rb it will return:
+ #
+ # [ "--- a/lib/gitlab/usage_data.rb",
+ # "+++ b/lib/gitlab/usage_data.rb",
+ # "+ # Test change",
+ # "- # Old change" ]
+ def changed_lines(changed_file)
+ diff = git.diff_for_file(changed_file)
+ return [] unless diff
+
+ diff.patch.split("\n").select { |line| %r{^[+-]}.match?(line) }
+ end
+
+ def all_ee_changes
+ all_changed_files.grep(%r{\Aee/})
+ end
+
+ def ee?
+ # Support former project name for `dev` and support local Danger run
+ %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('../../../ee', __dir__))
+ end
+
+ def gitlab_helper
+ # Unfortunately the following does not work:
+ # - respond_to?(:gitlab)
+ # - respond_to?(:gitlab, true)
+ gitlab
+ rescue NameError
+ nil
+ end
+
+ def release_automation?
+ gitlab_helper&.mr_author == RELEASE_TOOLS_BOT
+ end
+
+ def project_name
+ ee? ? 'gitlab' : 'gitlab-foss'
+ end
+
+ def markdown_list(items)
+ list = items.map { |item| "* `#{item}`" }.join("\n")
+
+ if items.size > 10
+ "\n<details>\n\n#{list}\n\n</details>\n"
+ else
+ list
+ end
+ end
+
+ # @return [Hash<String,Array<String>>]
+ def changes_by_category
+ all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash|
+ categories_for_file(file).each { |category| hash[category] << file }
+ end
+ end
+
+ # Determines the categories a file is in, e.g., `[:frontend]`, `[:backend]`, or `%i[frontend engineering_productivity]`
+ # using filename regex and specific change regex if given.
+ #
+ # @return Array<Symbol>
+ def categories_for_file(file)
+ _, categories = CATEGORIES.find do |key, _|
+ filename_regex, changes_regex = Array(key)
+
+ found = filename_regex.match?(file)
+ found &&= changed_lines(file).any? { |changed_line| changes_regex.match?(changed_line) } if changes_regex
+
+ found
+ end
+
+ Array(categories || :unknown)
+ end
+
+ # Returns the GFM for a category label, making its best guess if it's not
+ # a category we know about.
+ #
+ # @return[String]
+ def label_for_category(category)
+ CATEGORY_LABELS.fetch(category, "~#{category}")
+ end
+
+ CATEGORY_LABELS = {
+ docs: "~documentation", # Docs are reviewed along DevOps stages, so don't need roulette for now.
+ none: "",
+ qa: "~QA",
+ test: "~test ~Quality for `spec/features/*`",
+ engineering_productivity: '~"Engineering Productivity" for CI, Danger',
+ ci_template: '~"ci::templates"'
+ }.freeze
+ # First-match win, so be sure to put more specific regex at the top...
+ CATEGORIES = {
+ [%r{usage_data\.rb}, %r{^(\+|-).*\s+(count|distinct_count|estimate_batch_distinct_count)\(.*\)(.*)$}] => [:database, :backend],
+
+ %r{\Adoc/.*(\.(md|png|gif|jpg))\z} => :docs,
+ %r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
+
+ %r{\A(ee/)?app/(assets|views)/} => :frontend,
+ %r{\A(ee/)?public/} => :frontend,
+ %r{\A(ee/)?spec/(javascripts|frontend)/} => :frontend,
+ %r{\A(ee/)?vendor/assets/} => :frontend,
+ %r{\A(ee/)?scripts/frontend/} => :frontend,
+ %r{(\A|/)(
+ \.babelrc |
+ \.eslintignore |
+ \.eslintrc(\.yml)? |
+ \.nvmrc |
+ \.prettierignore |
+ \.prettierrc |
+ \.scss-lint.yml |
+ \.stylelintrc |
+ \.haml-lint.yml |
+ \.haml-lint_todo.yml |
+ babel\.config\.js |
+ jest\.config\.js |
+ package\.json |
+ yarn\.lock |
+ config/.+\.js
+ )\z}x => :frontend,
+
+ %r{(\A|/)(
+ \.gitlab/ci/frontend\.gitlab-ci\.yml
+ )\z}x => %i[frontend engineering_productivity],
+
+ %r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
+ %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
+ %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
+ %r{\A(ee/)?app/finders/} => :database,
+ %r{\Arubocop/cop/migration(/|\.rb)} => :database,
+
+ %r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
+ %r{\A\.codeclimate\.yml\z} => :engineering_productivity,
+ %r{\Alefthook.yml\z} => :engineering_productivity,
+ %r{\A\.editorconfig\z} => :engineering_productivity,
+ %r{Dangerfile\z} => :engineering_productivity,
+ %r{\A(ee/)?(danger/|tooling/danger/)} => :engineering_productivity,
+ %r{\A(ee/)?scripts/} => :engineering_productivity,
+ %r{\Atooling/} => :engineering_productivity,
+ %r{(CODEOWNERS)} => :engineering_productivity,
+ %r{(tests.yml)} => :engineering_productivity,
+
+ %r{\Alib/gitlab/ci/templates} => :ci_template,
+
+ %r{\A(ee/)?spec/features/} => :test,
+ %r{\A(ee/)?spec/support/shared_examples/features/} => :test,
+ %r{\A(ee/)?spec/support/shared_contexts/features/} => :test,
+ %r{\A(ee/)?spec/support/helpers/features/} => :test,
+
+ %r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
+ %r{\A(ee/)?(bin|config|generator_templates|lib|rubocop)/} => :backend,
+ %r{\A(ee/)?spec/} => :backend,
+ %r{\A(ee/)?vendor/} => :backend,
+ %r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
+ %r{\A[A-Z_]+_VERSION\z} => :backend,
+ %r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
+ %r{\Afile_hooks/} => :backend,
+
+ %r{\A(ee/)?qa/} => :qa,
+
+ # Files that don't fit into any category are marked with :none
+ %r{\A(ee/)?changelogs/} => :none,
+ %r{\Alocale/gitlab\.pot\z} => :none,
+
+ # GraphQL auto generated doc files and schema
+ %r{\Adoc/api/graphql/reference/} => :backend,
+
+ # Fallbacks in case the above patterns miss anything
+ %r{\.rb\z} => :backend,
+ %r{(
+ \.(md|txt)\z |
+ \.markdownlint\.json
+ )}x => :none, # To reinstate roulette for documentation, set to `:docs`.
+ %r{\.js\z} => :frontend
+ }.freeze
+
+ def new_teammates(usernames)
+ usernames.map { |u| Tooling::Danger::Teammate.new('username' => u) }
+ end
+
+ def mr_title
+ return '' unless gitlab_helper
+
+ gitlab_helper.mr_json['title']
+ end
+
+ def mr_web_url
+ return '' unless gitlab_helper
+
+ gitlab_helper.mr_json['web_url']
+ end
+
+ def mr_target_branch
+ return '' unless gitlab_helper
+
+ gitlab_helper.mr_json['target_branch']
+ end
+
+ def draft_mr?
+ TitleLinting.has_draft_flag?(mr_title)
+ end
+
+ def security_mr?
+ mr_web_url.include?('/gitlab-org/security/')
+ end
+
+ def cherry_pick_mr?
+ TitleLinting.has_cherry_pick_flag?(mr_title)
+ end
+
+ def run_all_rspec_mr?
+ TitleLinting.has_run_all_rspec_flag?(mr_title)
+ end
+
+ def run_as_if_foss_mr?
+ TitleLinting.has_run_as_if_foss_flag?(mr_title)
+ end
+
+ def stable_branch?
+ /\A\d+-\d+-stable-ee/i.match?(mr_target_branch)
+ end
+
+ def mr_has_labels?(*labels)
+ return false unless gitlab_helper
+
+ labels = labels.flatten.uniq
+ (labels & gitlab_helper.mr_labels) == labels
+ end
+
+ def labels_list(labels, sep: ', ')
+ labels.map { |label| %Q{~"#{label}"} }.join(sep)
+ end
+
+ def prepare_labels_for_mr(labels)
+ return '' unless labels.any?
+
+ "/label #{labels_list(labels, sep: ' ')}"
+ end
+
+ def changed_files(regex)
+ all_changed_files.grep(regex)
+ end
+
+ def has_database_scoped_labels?(labels)
+ labels.any? { |label| label.start_with?('database::') }
+ end
+
+ def has_ci_changes?
+ changed_files(%r{\A(\.gitlab-ci\.yml|\.gitlab/ci/)}).any?
+ end
+
+ def group_label(labels)
+ labels.find { |label| label.start_with?('group::') }
+ end
+ end
+ end
+end
diff --git a/tooling/danger/merge_request_linter.rb b/tooling/danger/merge_request_linter.rb
new file mode 100644
index 00000000000..ddeb9cc2981
--- /dev/null
+++ b/tooling/danger/merge_request_linter.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require_relative 'base_linter'
+
+module Tooling
+ module Danger
+ class MergeRequestLinter < BaseLinter
+ alias_method :lint, :lint_subject
+
+ def self.subject_description
+ 'merge request title'
+ end
+
+ def self.mr_run_options_regex
+ [
+ 'RUN AS-IF-FOSS',
+ 'UPDATE CACHE',
+ 'RUN ALL RSPEC',
+ 'SKIP RSPEC FAIL-FAST'
+ ].join('|')
+ end
+
+ private
+
+ def subject
+ super.gsub(/\[?(#{self.class.mr_run_options_regex})\]?/, '').strip
+ end
+ end
+ end
+end
diff --git a/tooling/danger/request_helper.rb b/tooling/danger/request_helper.rb
new file mode 100644
index 00000000000..d6b99f562f9
--- /dev/null
+++ b/tooling/danger/request_helper.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'net/http'
+require 'json'
+
+module Tooling
+ module Danger
+ module RequestHelper
+ HTTPError = Class.new(RuntimeError)
+
+ # @param [String] url
+ def self.http_get_json(url)
+ rsp = Net::HTTP.get_response(URI.parse(url))
+
+ unless rsp.is_a?(Net::HTTPOK)
+ raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}"
+ end
+
+ JSON.parse(rsp.body)
+ end
+ end
+ end
+end
diff --git a/tooling/danger/roulette.rb b/tooling/danger/roulette.rb
new file mode 100644
index 00000000000..c928fb2b655
--- /dev/null
+++ b/tooling/danger/roulette.rb
@@ -0,0 +1,169 @@
+# frozen_string_literal: true
+
+require_relative 'teammate'
+require_relative 'request_helper'
+require_relative 'weightage/reviewers'
+require_relative 'weightage/maintainers'
+
+module Tooling
+ module Danger
+ module Roulette
+ ROULETTE_DATA_URL = 'https://gitlab-org.gitlab.io/gitlab-roulette/roulette.json'
+ HOURS_WHEN_PERSON_CAN_BE_PICKED = (6..14).freeze
+
+ INCLUDE_TIMEZONE_FOR_CATEGORY = {
+ database: false
+ }.freeze
+
+ Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role, :timezone_experiment)
+
+ def team_mr_author
+ team.find { |person| person.username == mr_author_username }
+ end
+
+ # Assigns GitLab team members to be reviewer and maintainer
+ # for each change category that a Merge Request contains.
+ #
+ # @return [Array<Spin>]
+ def spin(project, categories, timezone_experiment: false)
+ spins = categories.sort.map do |category|
+ including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)
+
+ spin_for_category(project, category, timezone_experiment: including_timezone)
+ end
+
+ backend_spin = spins.find { |spin| spin.category == :backend }
+
+ spins.each do |spin|
+ including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(spin.category, timezone_experiment)
+ case spin.category
+ when :qa
+ # MR includes QA changes, but also other changes, and author isn't an SET
+ if categories.size > 1 && !team_mr_author&.any_capability?(project, spin.category)
+ spin.optional_role = :maintainer
+ end
+ when :test
+ spin.optional_role = :maintainer
+
+ if spin.reviewer.nil?
+ # Fetch an already picked backend reviewer, or pick one otherwise
+ spin.reviewer = backend_spin&.reviewer || spin_for_category(project, :backend, timezone_experiment: including_timezone).reviewer
+ end
+ when :engineering_productivity
+ if spin.maintainer.nil?
+ # Fetch an already picked backend maintainer, or pick one otherwise
+ spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
+ end
+ when :ci_template
+ if spin.maintainer.nil?
+ # Fetch an already picked backend maintainer, or pick one otherwise
+ spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
+ end
+ end
+ end
+
+ spins
+ end
+
+ # Looks up the current list of GitLab team members and parses it into a
+ # useful form
+ #
+ # @return [Array<Teammate>]
+ def team
+ @team ||=
+ begin
+ data = Tooling::Danger::RequestHelper.http_get_json(ROULETTE_DATA_URL)
+ data.map { |hash| ::Tooling::Danger::Teammate.new(hash) }
+ rescue JSON::ParserError
+ raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
+ end
+ end
+
+ # Like +team+, but only returns teammates in the current project, based on
+ # project_name.
+ #
+ # @return [Array<Teammate>]
+ def project_team(project_name)
+ team.select { |member| member.in_project?(project_name) }
+ rescue => err
+ warn("Reviewer roulette failed to load team data: #{err.message}")
+ []
+ end
+
+ # Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
+ # selection will change on next spin
+ # @param [Array<Teammate>] people
+ def spin_for_person(people, random:, timezone_experiment: false)
+ shuffled_people = people.shuffle(random: random)
+
+ if timezone_experiment
+ shuffled_people.find(&method(:valid_person_with_timezone?))
+ else
+ shuffled_people.find(&method(:valid_person?))
+ end
+ end
+
+ private
+
+ # @param [Teammate] person
+ # @return [Boolean]
+ def valid_person?(person)
+ !mr_author?(person) && person.available
+ end
+
+ # @param [Teammate] person
+ # @return [Boolean]
+ def valid_person_with_timezone?(person)
+ valid_person?(person) && HOURS_WHEN_PERSON_CAN_BE_PICKED.cover?(person.local_hour)
+ end
+
+ # @param [Teammate] person
+ # @return [Boolean]
+ def mr_author?(person)
+ person.username == mr_author_username
+ end
+
+ def mr_author_username
+ helper.gitlab_helper&.mr_author || `whoami`
+ end
+
+ def mr_source_branch
+ return `git rev-parse --abbrev-ref HEAD` unless helper.gitlab_helper&.mr_json
+
+ helper.gitlab_helper.mr_json['source_branch']
+ end
+
+ def mr_labels
+ helper.gitlab_helper&.mr_labels || []
+ end
+
+ def new_random(seed)
+ Random.new(Digest::MD5.hexdigest(seed).to_i(16))
+ end
+
+ def spin_role_for_category(team, role, project, category)
+ team.select do |member|
+ member.public_send("#{role}?", project, category, mr_labels) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+
+ def spin_for_category(project, category, timezone_experiment: false)
+ team = project_team(project)
+ reviewers, traintainers, maintainers =
+ %i[reviewer traintainer maintainer].map do |role|
+ spin_role_for_category(team, role, project, category)
+ end
+
+ random = new_random(mr_source_branch)
+
+ weighted_reviewers = Weightage::Reviewers.new(reviewers, traintainers).execute
+ weighted_maintainers = Weightage::Maintainers.new(maintainers).execute
+
+ reviewer = spin_for_person(weighted_reviewers, random: random, timezone_experiment: timezone_experiment)
+ maintainer = spin_for_person(weighted_maintainers, random: random, timezone_experiment: timezone_experiment)
+
+ Spin.new(category, reviewer, maintainer, false, timezone_experiment)
+ end
+ end
+ end
+end
diff --git a/tooling/danger/sidekiq_queues.rb b/tooling/danger/sidekiq_queues.rb
new file mode 100644
index 00000000000..ae32b128682
--- /dev/null
+++ b/tooling/danger/sidekiq_queues.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Danger
+ module SidekiqQueues
+ def changed_queue_files
+ @changed_queue_files ||= git.modified_files.grep(%r{\A(ee/)?app/workers/all_queues\.yml})
+ end
+
+ def added_queue_names
+ @added_queue_names ||= new_queues.keys - old_queues.keys
+ end
+
+ def changed_queue_names
+ @changed_queue_names ||=
+ (new_queues.values_at(*old_queues.keys) - old_queues.values)
+ .compact.map { |queue| queue[:name] }
+ end
+
+ private
+
+ def old_queues
+ @old_queues ||= queues_for(gitlab.base_commit)
+ end
+
+ def new_queues
+ @new_queues ||= queues_for(gitlab.head_commit)
+ end
+
+ def queues_for(branch)
+ changed_queue_files
+ .flat_map { |file| YAML.safe_load(`git show #{branch}:#{file}`, permitted_classes: [Symbol]) }
+ .to_h { |queue| [queue[:name], queue] }
+ end
+ end
+ end
+end
diff --git a/tooling/danger/teammate.rb b/tooling/danger/teammate.rb
new file mode 100644
index 00000000000..bcd33bebdc9
--- /dev/null
+++ b/tooling/danger/teammate.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Danger
+ class Teammate
+ attr_reader :options, :username, :name, :role, :projects, :available, :hungry, :reduced_capacity, :tz_offset_hours
+
+ # The options data are produced by https://gitlab.com/gitlab-org/gitlab-roulette/-/blob/master/lib/team_member.rb
+ def initialize(options = {})
+ @options = options
+ @username = options['username']
+ @name = options['name']
+ @markdown_name = options['markdown_name']
+ @role = options['role']
+ @projects = options['projects']
+ @available = options['available']
+ @hungry = options['hungry']
+ @reduced_capacity = options['reduced_capacity']
+ @tz_offset_hours = options['tz_offset_hours']
+ end
+
+ def to_h
+ options
+ end
+
+ def ==(other)
+ return false unless other.respond_to?(:username)
+
+ other.username == username
+ end
+
+ def in_project?(name)
+ projects&.has_key?(name)
+ end
+
+ def any_capability?(project, category)
+ capabilities(project).any? { |capability| capability.end_with?(category.to_s) }
+ end
+
+ def reviewer?(project, category, labels)
+ has_capability?(project, category, :reviewer, labels)
+ end
+
+ def traintainer?(project, category, labels)
+ has_capability?(project, category, :trainee_maintainer, labels)
+ end
+
+ def maintainer?(project, category, labels)
+ has_capability?(project, category, :maintainer, labels)
+ end
+
+ def markdown_name(author: nil)
+ "#{@markdown_name} (#{utc_offset_text(author)})"
+ end
+
+ def local_hour
+ (Time.now.utc + tz_offset_hours * 3600).hour
+ end
+
+ protected
+
+ def floored_offset_hours
+ floored_offset = tz_offset_hours.floor(0)
+
+ floored_offset == tz_offset_hours ? floored_offset : tz_offset_hours
+ end
+
+ private
+
+ def utc_offset_text(author = nil)
+ offset_text =
+ if floored_offset_hours >= 0
+ "UTC+#{floored_offset_hours}"
+ else
+ "UTC#{floored_offset_hours}"
+ end
+
+ return offset_text unless author
+
+ "#{offset_text}, #{offset_diff_compared_to_author(author)}"
+ end
+
+ def offset_diff_compared_to_author(author)
+ diff = floored_offset_hours - author.floored_offset_hours
+ return "same timezone as `@#{author.username}`" if diff == 0
+
+ ahead_or_behind = diff < 0 ? 'behind' : 'ahead of'
+ pluralized_hours = pluralize(diff.abs, 'hour', 'hours')
+
+ "#{pluralized_hours} #{ahead_or_behind} `@#{author.username}`"
+ end
+
+ def has_capability?(project, category, kind, labels)
+ case category
+ when :test
+ area = role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
+
+ area && labels.any?("devops::#{area.downcase}") if kind == :reviewer
+ when :engineering_productivity
+ return false unless role[/Engineering Productivity/]
+ return true if kind == :reviewer
+ return true if capabilities(project).include?("#{kind} engineering_productivity")
+
+ capabilities(project).include?("#{kind} backend")
+ else
+ capabilities(project).include?("#{kind} #{category}")
+ end
+ end
+
+ def capabilities(project)
+ Array(projects.fetch(project, []))
+ end
+
+ def pluralize(count, singular, plural)
+ word = count == 1 || count.to_s =~ /^1(\.0+)?$/ ? singular : plural
+
+ "#{count || 0} #{word}"
+ end
+ end
+ end
+end
diff --git a/tooling/danger/title_linting.rb b/tooling/danger/title_linting.rb
new file mode 100644
index 00000000000..dcd83df7d93
--- /dev/null
+++ b/tooling/danger/title_linting.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Danger
+ module TitleLinting
+ DRAFT_REGEX = /\A*#{Regexp.union(/(?i)(\[WIP\]\s*|WIP:\s*|WIP$)/, /(?i)(\[draft\]|\(draft\)|draft:|draft\s\-\s|draft$)/)}+\s*/i.freeze
+ CHERRY_PICK_REGEX = /cherry[\s-]*pick/i.freeze
+ RUN_ALL_RSPEC_REGEX = /RUN ALL RSPEC/i.freeze
+ RUN_AS_IF_FOSS_REGEX = /RUN AS-IF-FOSS/i.freeze
+
+ module_function
+
+ def sanitize_mr_title(title)
+ remove_draft_flag(title).gsub(/`/, '\\\`')
+ end
+
+ def remove_draft_flag(title)
+ title.gsub(DRAFT_REGEX, '')
+ end
+
+ def has_draft_flag?(title)
+ DRAFT_REGEX.match?(title)
+ end
+
+ def has_cherry_pick_flag?(title)
+ CHERRY_PICK_REGEX.match?(title)
+ end
+
+ def has_run_all_rspec_flag?(title)
+ RUN_ALL_RSPEC_REGEX.match?(title)
+ end
+
+ def has_run_as_if_foss_flag?(title)
+ RUN_AS_IF_FOSS_REGEX.match?(title)
+ end
+ end
+ end
+end
diff --git a/tooling/danger/weightage.rb b/tooling/danger/weightage.rb
new file mode 100644
index 00000000000..cf8d17410dc
--- /dev/null
+++ b/tooling/danger/weightage.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Danger
+ module Weightage
+ CAPACITY_MULTIPLIER = 2 # change this number to change what it means to be a reduced capacity reviewer 1/this number
+ BASE_REVIEWER_WEIGHT = 1
+ end
+ end
+end
diff --git a/tooling/danger/weightage/maintainers.rb b/tooling/danger/weightage/maintainers.rb
new file mode 100644
index 00000000000..068b24e7913
--- /dev/null
+++ b/tooling/danger/weightage/maintainers.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require_relative '../weightage'
+
+module Tooling
+ module Danger
+ module Weightage
+ class Maintainers
+ def initialize(maintainers)
+ @maintainers = maintainers
+ end
+
+ def execute
+ maintainers.each_with_object([]) do |maintainer, weighted_maintainers|
+ add_weighted_reviewer(weighted_maintainers, maintainer, BASE_REVIEWER_WEIGHT)
+ end
+ end
+
+ private
+
+ attr_reader :maintainers
+
+ def add_weighted_reviewer(reviewers, reviewer, weight)
+ if reviewer.reduced_capacity
+ reviewers.fill(reviewer, reviewers.size, weight)
+ else
+ reviewers.fill(reviewer, reviewers.size, weight * CAPACITY_MULTIPLIER)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/tooling/danger/weightage/reviewers.rb b/tooling/danger/weightage/reviewers.rb
new file mode 100644
index 00000000000..e74fce37187
--- /dev/null
+++ b/tooling/danger/weightage/reviewers.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require_relative '../weightage'
+
+module Tooling
+ module Danger
+ module Weightage
+ # Weights after (current multiplier of 2)
+ #
+ # +------------------------------+--------------------------------+
+ # | reviewer type | weight(times in reviewer pool) |
+ # +------------------------------+--------------------------------+
+ # | reduced capacity reviewer | 1 |
+ # | reviewer | 2 |
+ # | hungry reviewer | 4 |
+ # | reduced capacity traintainer | 3 |
+ # | traintainer | 6 |
+ # | hungry traintainer | 8 |
+ # +------------------------------+--------------------------------+
+ #
+ class Reviewers
+ DEFAULT_REVIEWER_WEIGHT = CAPACITY_MULTIPLIER * BASE_REVIEWER_WEIGHT
+ TRAINTAINER_WEIGHT = 3
+
+ def initialize(reviewers, traintainers)
+ @reviewers = reviewers
+ @traintainers = traintainers
+ end
+
+ def execute
+ # TODO: take CODEOWNERS into account?
+ # https://gitlab.com/gitlab-org/gitlab/issues/26723
+
+ weighted_reviewers + weighted_traintainers
+ end
+
+ private
+
+ attr_reader :reviewers, :traintainers
+
+ def weighted_reviewers
+ reviewers.each_with_object([]) do |reviewer, total_reviewers|
+ add_weighted_reviewer(total_reviewers, reviewer, BASE_REVIEWER_WEIGHT)
+ end
+ end
+
+ def weighted_traintainers
+ traintainers.each_with_object([]) do |reviewer, total_traintainers|
+ add_weighted_reviewer(total_traintainers, reviewer, TRAINTAINER_WEIGHT)
+ end
+ end
+
+ def add_weighted_reviewer(reviewers, reviewer, weight)
+ if reviewer.reduced_capacity
+ reviewers.fill(reviewer, reviewers.size, weight)
+ elsif reviewer.hungry
+ reviewers.fill(reviewer, reviewers.size, weight * CAPACITY_MULTIPLIER + DEFAULT_REVIEWER_WEIGHT)
+ else
+ reviewers.fill(reviewer, reviewers.size, weight * CAPACITY_MULTIPLIER)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/tooling/gitlab_danger.rb b/tooling/gitlab_danger.rb
new file mode 100644
index 00000000000..d20d3499641
--- /dev/null
+++ b/tooling/gitlab_danger.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+# rubocop:todo Gitlab/NamespacedClass
+class GitlabDanger
+ LOCAL_RULES ||= %w[
+ changes_size
+ commit_messages
+ database
+ documentation
+ duplicate_yarn_dependencies
+ eslint
+ karma
+ pajamas
+ pipeline
+ prettier
+ product_intelligence
+ utility_css
+ ].freeze
+
+ CI_ONLY_RULES ||= %w[
+ ce_ee_vue_templates
+ changelog
+ ci_templates
+ metadata
+ feature_flag
+ roulette
+ sidekiq_queues
+ specialization_labels
+ specs
+ ].freeze
+
+ MESSAGE_PREFIX = '==>'.freeze
+
+ attr_reader :gitlab_danger_helper
+
+ def initialize(gitlab_danger_helper)
+ @gitlab_danger_helper = gitlab_danger_helper
+ end
+
+ def self.local_warning_message
+ "#{MESSAGE_PREFIX} Only the following Danger rules can be run locally: #{LOCAL_RULES.join(', ')}"
+ end
+
+ def self.success_message
+ "#{MESSAGE_PREFIX} No Danger rule violations!"
+ end
+
+ def rule_names
+ ci? ? LOCAL_RULES | CI_ONLY_RULES : LOCAL_RULES
+ end
+
+ def html_link(str)
+ self.ci? ? gitlab_danger_helper.html_link(str) : str
+ end
+
+ def ci?
+ !gitlab_danger_helper.nil?
+ end
+end
diff --git a/tooling/lib/tooling/kubernetes_client.rb b/tooling/lib/tooling/kubernetes_client.rb
index f7abc5ac4cf..35605fd493c 100644
--- a/tooling/lib/tooling/kubernetes_client.rb
+++ b/tooling/lib/tooling/kubernetes_client.rb
@@ -43,7 +43,6 @@ module Tooling
%(--namespace "#{namespace}"),
'--now',
'--ignore-not-found',
- '--include-uninitialized',
%(--wait=#{wait}),
selector
]
@@ -58,7 +57,6 @@ module Tooling
%(--namespace "#{namespace}"),
'--now',
'--ignore-not-found',
- '--include-uninitialized',
%(--wait=#{wait}),
resource_names.join(' ')
]
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 259148fa18f..259148fa18f 100644..100755
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
diff --git a/vendor/gitignore/Java.gitignore b/vendor/gitignore/Java.gitignore
index a1c2a238a96..a1c2a238a96 100644..100755
--- a/vendor/gitignore/Java.gitignore
+++ b/vendor/gitignore/Java.gitignore
diff --git a/vendor/sample_data_templates/sample.tar.gz b/vendor/sample_data_templates/sample.tar.gz
index 1ab09f8dc41..70e4baee522 100644
--- a/vendor/sample_data_templates/sample.tar.gz
+++ b/vendor/sample_data_templates/sample.tar.gz
Binary files differ
diff --git a/workhorse/CHANGELOG b/workhorse/CHANGELOG
index 42c13465ba9..3142f2601b7 100644
--- a/workhorse/CHANGELOG
+++ b/workhorse/CHANGELOG
@@ -1,5 +1,43 @@
# Changelog for gitlab-workhorse
+## v8.63.0
+
+### Added
+- Accept more paths as Git HTTP
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/684
+
+### Other
+- Migrate error tracking from raven to labkit
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/671
+
+## v8.62.0
+
+### Added
+- Add RubyGems registry upload route
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/680
+
+### Fixed
+- Cleanup Connection headers
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/678
+
+## v8.61.0
+
+### Fixed
+- Revert "Support Git HTTP on toplevel repositories"
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/681
+
+## v8.60.0
+
+### Added
+- Support Git HTTP on toplevel repositories
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/670
+- Update GoCloud to v0.21.1+
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/675
+
+### Changed
+- Allow blank S3 regions to be used
+ https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/677
+
## v8.59.0
### Fixed
diff --git a/workhorse/VERSION b/workhorse/VERSION
index 8c20f999400..661bb99fdf9 100644
--- a/workhorse/VERSION
+++ b/workhorse/VERSION
@@ -1 +1 @@
-8.59.0
+8.63.0
diff --git a/workhorse/gitaly_test.go b/workhorse/gitaly_test.go
index 95d6907ac6a..d0e694bf8e7 100644
--- a/workhorse/gitaly_test.go
+++ b/workhorse/gitaly_test.go
@@ -9,6 +9,7 @@ import (
"math/rand"
"net"
"net/http"
+ "net/url"
"os"
"os/exec"
"path"
@@ -169,6 +170,62 @@ func TestGetInfoRefsProxiedToGitalyInterruptedStream(t *testing.T) {
waitDone(t, done)
}
+func TestGetInfoRefsRouting(t *testing.T) {
+ gitalyServer, socketPath := startGitalyServer(t, codes.OK)
+ defer gitalyServer.GracefulStop()
+
+ apiResponse := gitOkBody(t)
+ apiResponse.GitalyServer.Address = "unix:" + socketPath
+ ts := testAuthServer(t, nil, url.Values{"service": {"git-receive-pack"}}, 200, apiResponse)
+ defer ts.Close()
+
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ testCases := []struct {
+ method string
+ path string
+ status int
+ }{
+ // valid requests
+ {"GET", "/toplevel.git/info/refs?service=git-receive-pack", 200},
+ {"GET", "/toplevel.wiki.git/info/refs?service=git-receive-pack", 200},
+ {"GET", "/toplevel/child/project.git/info/refs?service=git-receive-pack", 200},
+ {"GET", "/toplevel/child/project.wiki.git/info/refs?service=git-receive-pack", 200},
+ {"GET", "/toplevel/child/project/snippets/123.git/info/refs?service=git-receive-pack", 200},
+ {"GET", "/snippets/123.git/info/refs?service=git-receive-pack", 200},
+ // failing due to missing service parameter
+ {"GET", "/foo/bar.git/info/refs", 403},
+ // failing due to invalid service parameter
+ {"GET", "/foo/bar.git/info/refs?service=git-zzz-pack", 403},
+ // failing due to invalid repository path
+ {"GET", "/.git/info/refs?service=git-receive-pack", 204},
+ // failing due to invalid request method
+ {"POST", "/toplevel.git/info/refs?service=git-receive-pack", 204},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.path, func(t *testing.T) {
+ req, err := http.NewRequest(tc.method, ws.URL+tc.path, nil)
+ require.NoError(t, err)
+
+ resp, err := http.DefaultClient.Do(req)
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ body := string(testhelper.ReadAll(t, resp.Body))
+
+ if tc.status == 200 {
+ require.Equal(t, 200, resp.StatusCode)
+ require.Contains(t, body, "\x00", "expect response generated by test gitaly server")
+ } else {
+ require.Equal(t, tc.status, resp.StatusCode)
+ require.Empty(t, body, "normal request has empty response body")
+ }
+ })
+ }
+}
+
func waitDone(t *testing.T, done chan struct{}) {
t.Helper()
select {
@@ -259,6 +316,65 @@ func TestPostReceivePackProxiedToGitalyInterrupted(t *testing.T) {
waitDone(t, done)
}
+func TestPostReceivePackRouting(t *testing.T) {
+ gitalyServer, socketPath := startGitalyServer(t, codes.OK)
+ defer gitalyServer.GracefulStop()
+
+ apiResponse := gitOkBody(t)
+ apiResponse.GitalyServer.Address = "unix:" + socketPath
+ ts := testAuthServer(t, nil, nil, 200, apiResponse)
+ defer ts.Close()
+
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ testCases := []struct {
+ method string
+ path string
+ contentType string
+ match bool
+ }{
+ {"POST", "/toplevel.git/git-receive-pack", "application/x-git-receive-pack-request", true},
+ {"POST", "/toplevel.wiki.git/git-receive-pack", "application/x-git-receive-pack-request", true},
+ {"POST", "/toplevel/child/project.git/git-receive-pack", "application/x-git-receive-pack-request", true},
+ {"POST", "/toplevel/child/project.wiki.git/git-receive-pack", "application/x-git-receive-pack-request", true},
+ {"POST", "/toplevel/child/project/snippets/123.git/git-receive-pack", "application/x-git-receive-pack-request", true},
+ {"POST", "/snippets/123.git/git-receive-pack", "application/x-git-receive-pack-request", true},
+ {"POST", "/foo/bar/git-receive-pack", "application/x-git-receive-pack-request", false},
+ {"POST", "/foo/bar.git/git-zzz-pack", "application/x-git-receive-pack-request", false},
+ {"POST", "/.git/git-receive-pack", "application/x-git-receive-pack-request", false},
+ {"POST", "/toplevel.git/git-receive-pack", "application/x-git-upload-pack-request", false},
+ {"GET", "/toplevel.git/git-receive-pack", "application/x-git-receive-pack-request", false},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.path, func(t *testing.T) {
+ req, err := http.NewRequest(
+ tc.method,
+ ws.URL+tc.path,
+ bytes.NewReader(testhelper.GitalyReceivePackResponseMock),
+ )
+ require.NoError(t, err)
+
+ req.Header.Set("Content-Type", tc.contentType)
+
+ resp, err := http.DefaultClient.Do(req)
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ body := string(testhelper.ReadAll(t, resp.Body))
+
+ if tc.match {
+ require.Equal(t, 200, resp.StatusCode)
+ require.Contains(t, body, "\x00", "expect response generated by test gitaly server")
+ } else {
+ require.Equal(t, 204, resp.StatusCode)
+ require.Empty(t, body, "normal request has empty response body")
+ }
+ })
+ }
+}
+
// ReaderFunc is an adapter to turn a conforming function into an io.Reader.
type ReaderFunc func(b []byte) (int, error)
@@ -376,6 +492,65 @@ func TestPostUploadPackProxiedToGitalyInterrupted(t *testing.T) {
waitDone(t, done)
}
+func TestPostUploadPackRouting(t *testing.T) {
+ gitalyServer, socketPath := startGitalyServer(t, codes.OK)
+ defer gitalyServer.GracefulStop()
+
+ apiResponse := gitOkBody(t)
+ apiResponse.GitalyServer.Address = "unix:" + socketPath
+ ts := testAuthServer(t, nil, nil, 200, apiResponse)
+ defer ts.Close()
+
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ testCases := []struct {
+ method string
+ path string
+ contentType string
+ match bool
+ }{
+ {"POST", "/toplevel.git/git-upload-pack", "application/x-git-upload-pack-request", true},
+ {"POST", "/toplevel.wiki.git/git-upload-pack", "application/x-git-upload-pack-request", true},
+ {"POST", "/toplevel/child/project.git/git-upload-pack", "application/x-git-upload-pack-request", true},
+ {"POST", "/toplevel/child/project.wiki.git/git-upload-pack", "application/x-git-upload-pack-request", true},
+ {"POST", "/toplevel/child/project/snippets/123.git/git-upload-pack", "application/x-git-upload-pack-request", true},
+ {"POST", "/snippets/123.git/git-upload-pack", "application/x-git-upload-pack-request", true},
+ {"POST", "/foo/bar/git-upload-pack", "application/x-git-upload-pack-request", false},
+ {"POST", "/foo/bar.git/git-zzz-pack", "application/x-git-upload-pack-request", false},
+ {"POST", "/.git/git-upload-pack", "application/x-git-upload-pack-request", false},
+ {"POST", "/toplevel.git/git-upload-pack", "application/x-git-receive-pack-request", false},
+ {"GET", "/toplevel.git/git-upload-pack", "application/x-git-upload-pack-request", false},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.path, func(t *testing.T) {
+ req, err := http.NewRequest(
+ tc.method,
+ ws.URL+tc.path,
+ bytes.NewReader(testhelper.GitalyReceivePackResponseMock),
+ )
+ require.NoError(t, err)
+
+ req.Header.Set("Content-Type", tc.contentType)
+
+ resp, err := http.DefaultClient.Do(req)
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ body := string(testhelper.ReadAll(t, resp.Body))
+
+ if tc.match {
+ require.Equal(t, 200, resp.StatusCode)
+ require.Contains(t, body, "\x00", "expect response generated by test gitaly server")
+ } else {
+ require.Equal(t, 204, resp.StatusCode)
+ require.Empty(t, body, "normal request has empty response body")
+ }
+ })
+ }
+}
+
func TestGetDiffProxiedToGitalySuccessfully(t *testing.T) {
gitalyServer, socketPath := startGitalyServer(t, codes.OK)
defer gitalyServer.GracefulStop()
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 5fed8de4796..20344f0081d 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -3,19 +3,17 @@ module gitlab.com/gitlab-org/gitlab-workhorse
go 1.13
require (
- github.com/Azure/azure-storage-blob-go v0.10.0
+ github.com/Azure/azure-storage-blob-go v0.11.1-0.20201209121048-6df5d9af221d
github.com/BurntSushi/toml v0.3.1
github.com/FZambia/sentinel v1.0.0
github.com/alecthomas/chroma v0.7.3
- github.com/aws/aws-sdk-go v1.31.13
- github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect
+ github.com/aws/aws-sdk-go v1.36.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/disintegration/imaging v1.6.2
- github.com/getsentry/raven-go v0.2.0
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721
github.com/golang/protobuf v1.4.3
github.com/gomodule/redigo v2.0.0+incompatible
- github.com/gorilla/websocket v1.4.0
+ github.com/gorilla/websocket v1.4.1
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/johannesboyne/gofakes3 v0.0.0-20200510090907-02d71f533bec
@@ -30,11 +28,15 @@ require (
github.com/stretchr/testify v1.6.1
gitlab.com/gitlab-org/gitaly v1.74.0
gitlab.com/gitlab-org/labkit v1.0.0
- gocloud.dev v0.20.0
+ gocloud.dev v0.21.1-0.20201223184910-5094f54ed8bb
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
- golang.org/x/net v0.0.0-20200625001655-4c5254603344
- golang.org/x/tools v0.0.0-20200608174601-1b747fd94509
- google.golang.org/grpc v1.29.1
+ golang.org/x/net v0.0.0-20201224014010-6772e930b67b
+ golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 // indirect
+ golang.org/x/text v0.3.5 // indirect
+ golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516
+ google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89 // indirect
+ google.golang.org/grpc v1.34.1
+ google.golang.org/grpc/examples v0.0.0-20201226181154-53788aa5dcb4 // indirect
honnef.co/go/tools v0.0.1-2020.1.5
)
diff --git a/workhorse/go.sum b/workhorse/go.sum
index 0b92dda088c..ddb08a1e846 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -6,18 +6,19 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR
cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.55.0/go.mod h1:ZHmoY+/lIMNkN2+fBmuTiqZ4inFhvQad8ft7MT8IV5Y=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.58.0 h1:vtAfVc723K3xKq1BQydk/FyCldnaNFhGhpJxaJzgRMQ=
-cloud.google.com/go v0.58.0/go.mod h1:W+9FnSUw6nhVwXlFcp1eL+krq5+HQUJeUogSeJZZiWg=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go v0.66.0/go.mod h1:dgqGAjKCDxyhGTtC9dAREQGUJpkceNm1yt590Qno0Ko=
+cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww=
+cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -28,60 +29,64 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/firestore v1.2.0/go.mod h1:iISCjWnTpnoJT1R287xRdjvQHJrxQOpeah4phb5D3h0=
+cloud.google.com/go/firestore v1.4.0/go.mod h1:NjjGEnxCS3CAKYp+vmALu20QzcqasGodQp48WxJGAYc=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/pubsub v1.9.0/go.mod h1:G3o6/kJvEMIEAN5urdkaP4be49WQsjNiykBIto9LFtY=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.9.0 h1:oXnZyBjHB6hC8TnSle0AWW6pGJ29EuSo5ww+SFmdNBg=
-cloud.google.com/go/storage v1.9.0/go.mod h1:m+/etGaqZbylxaNT876QGXqEHp4PR2Rq5GMqICWb9bU=
-contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
-contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw=
-contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
-contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+cloud.google.com/go/storage v1.12.0 h1:4y3gHptW1EHVtcPAVE0eBBlFuGqEejTTG3KdIE0lUX4=
+cloud.google.com/go/storage v1.12.0/go.mod h1:fFLk2dp2oAhDz8QFKwqrjdJvxSp/W2g7nillojlL5Ho=
+contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
+contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc=
+contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
-github.com/Azure/azure-amqp-common-go/v3 v3.0.0/go.mod h1:SY08giD/XbhTz07tJdpw1SoxQXHPN30+DI3Z04SYqyg=
-github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
-github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY=
-github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
+github.com/Azure/azure-amqp-common-go/v3 v3.0.1/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0=
+github.com/Azure/azure-amqp-common-go/v3 v3.1.0/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0=
+github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
+github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
github.com/Azure/azure-sdk-for-go v37.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
-github.com/Azure/azure-service-bus-go v0.10.1/go.mod h1:E/FOceuKAFUfpbIJDKWz/May6guE+eGibfGT6q+n1to=
-github.com/Azure/azure-storage-blob-go v0.9.0/go.mod h1:8UBPbiOhrMQ4pLPi3gA1tXnpjrS76UYE/fo5A40vf4g=
-github.com/Azure/azure-storage-blob-go v0.10.0 h1:evCwGreYo3XLeBV4vSxLbLiYb6e0SzsJiXQVRGsRXxs=
-github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE=
-github.com/Azure/go-amqp v0.12.6/go.mod h1:qApuH6OFTSKZFmCOxccvAv5rLizBQf4v8pRmG138DPo=
-github.com/Azure/go-amqp v0.12.7/go.mod h1:qApuH6OFTSKZFmCOxccvAv5rLizBQf4v8pRmG138DPo=
-github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
-github.com/Azure/go-autorest/autorest v0.9.3 h1:OZEIaBbMdUE/Js+BQKlpO81XlISgipr6yDJ+PSwsgi4=
-github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
-github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
-github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
-github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
-github.com/Azure/go-autorest/autorest/adal v0.8.3 h1:O1AGG9Xig71FxdX9HO5pGNyZ7TbSyHaVg+5eJO/jSGw=
-github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
-github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk=
-github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
-github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U=
-github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
-github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
-github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=
-github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
-github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
-github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
-github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
-github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
-github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
-github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
-github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
-github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
-github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
-github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
+github.com/Azure/azure-sdk-for-go v49.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-service-bus-go v0.10.7/go.mod h1:o5z/3lDG1iT/T/G7vgIwIqVDTx9Qa2wndf5OdzSzpF8=
+github.com/Azure/azure-storage-blob-go v0.11.1-0.20201209121048-6df5d9af221d h1:YEjZNZ0HS7ITX+BJ7wUXtTk6GXM3g8xftaqQ94XU/cs=
+github.com/Azure/azure-storage-blob-go v0.11.1-0.20201209121048-6df5d9af221d/go.mod h1:A0u4VjtpgZJ7Y7um/+ix2DHBuEKFC6sEIlj0xc13a4Q=
+github.com/Azure/go-amqp v0.13.0/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs=
+github.com/Azure/go-amqp v0.13.1/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs=
+github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
+github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
+github.com/Azure/go-autorest/autorest v0.11.7/go.mod h1:V6p3pKZx1KKkJubbxnDWrzNhEIfOy/pTGasLqzHIPHs=
+github.com/Azure/go-autorest/autorest v0.11.9/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
+github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE=
+github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
+github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
+github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
+github.com/Azure/go-autorest/autorest/adal v0.9.4/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
+github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/adal v0.9.6 h1:d3pSDwvBWBLqdA91u+keH1zs1cCEzrQdHKY6iqbQNkE=
+github.com/Azure/go-autorest/autorest/adal v0.9.6/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/azure/auth v0.5.3 h1:lZifaPRAk1bqg5vGqreL6F8uLC5V0fDpY8nFvc3boFc=
+github.com/Azure/go-autorest/autorest/azure/auth v0.5.3/go.mod h1:4bJZhUhcq8LB20TruwHbAQsmUs2Xh+QR7utuJpLXX3A=
+github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY=
+github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
+github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
+github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
+github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
+github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
+github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
+github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
+github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
+github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -89,7 +94,7 @@ github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EF
github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
github.com/FZambia/sentinel v1.0.0 h1:KJ0ryjKTZk5WMp0dXvSdNqp3lFaW1fNFuEYfrkLOYIc=
github.com/FZambia/sentinel v1.0.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
-github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
+github.com/GoogleCloudPlatform/cloudsql-proxy v1.19.1/go.mod h1:+yYmuKqcBVkgRePGpUhTA9OEg0XsnFE96eZ6nJ2yCQM=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
@@ -123,10 +128,10 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.17.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
-github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
-github.com/aws/aws-sdk-go v1.31.13 h1:UeWMTRTL0XAKLR7vxDL4/u7KOtz/LtfJr+lXtxN4YEQ=
-github.com/aws/aws-sdk-go v1.31.13/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.36.1 h1:rDgSL20giXXu48Ycx6Qa4vWaNTVTltUl6vA73ObCSVk=
+github.com/aws/aws-sdk-go v1.36.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -137,11 +142,9 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
-github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
-github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -153,6 +156,7 @@ github.com/client9/reopen v1.0.0 h1:8tpLVR74DLpLObrn2KvsyxJY++2iORGR17WLUdSzUws=
github.com/client9/reopen v1.0.0/go.mod h1:caXVCEr+lUtoN1FlsRiOWdfQtdRHIYfcb0ai8qKWtkQ=
github.com/cloudflare/tableflip v1.2.1-0.20200514155827-4baec9811f2b/go.mod h1:vhhSlJqV8uUnxGkRSgyvGthfGlkAwJ4UuSV51fSrCQY=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
@@ -171,6 +175,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
@@ -178,6 +183,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
+github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
+github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
@@ -193,17 +200,22 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/raven-go v0.1.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
@@ -213,7 +225,9 @@ github.com/getsentry/sentry-go v0.7.0 h1:MR2yfR4vFfv/2+iBuSnkdQwVg7N9cJzihZ6KJu7
github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJd8awjdPnUwg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@@ -228,6 +242,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
@@ -261,6 +279,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -288,28 +308,40 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
-github.com/google/go-replayers/grpcreplay v0.1.0 h1:eNb1y9rZFmY4ax45uEEECSa8fsxGRU+8Bil52ASAwic=
-github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
-github.com/google/go-replayers/httpreplay v0.1.0 h1:AX7FUb4BjrrzNvblr/OlgwrmFiep6soj5K2QSDW7BGk=
-github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
+github.com/google/go-replayers/grpcreplay v1.0.0 h1:B5kVOzJ1hBgnevTgIWhSTatQ3608yu/2NnU0Ta1d0kY=
+github.com/google/go-replayers/grpcreplay v1.0.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
+github.com/google/go-replayers/httpreplay v0.1.2 h1:HCfx+dQzwN9XbGTHF8qJ+67WN8glL9FTWV5rraCJ/jU=
+github.com/google/go-replayers/httpreplay v0.1.2/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE=
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=
+github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c h1:lIC98ZUNah83ky7d9EXktLFe4H7Nwus59dTOLXr8xAI=
-github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c h1:Jx2lEv4nMccTJE+IIZOVIvk+DjNKlRsW0sm1uBr896U=
+github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.4.0 h1:kXcsA/rIGzJImVqPdhfnr6q0xsS9gU0515q1EPpJ9fE=
github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
@@ -325,6 +357,8 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
+github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
@@ -357,6 +391,7 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
@@ -366,8 +401,10 @@ github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
-github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
+github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/johannesboyne/gofakes3 v0.0.0-20200510090907-02d71f533bec h1:jEZFmuFe51KdrceqM4NL3dJiuog0zojzcN/VculG26o=
github.com/johannesboyne/gofakes3 v0.0.0-20200510090907-02d71f533bec/go.mod h1:fNiSoOiEI5KlkWXn26OwKnNe58ilTIkpBlgOrt7Olu8=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
@@ -377,6 +414,7 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
@@ -399,6 +437,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -411,8 +451,9 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
-github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libgit2/git2go/v30 v30.0.5/go.mod h1:YReiQ7xhMoyAL4ISYFLZt+OGqn6xtLqvTC1xJ9oAH7Y=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
@@ -424,8 +465,6 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
-github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@@ -457,6 +496,8 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -475,6 +516,8 @@ github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid/v2 v2.0.2 h1:r4fFzBm+bv0wNKNh5eXTwU7i85y5x+uwkxCUTNVQqLc=
@@ -642,6 +685,8 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDf
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
gitlab.com/gitlab-org/gitaly v1.87.1-0.20201001041716-3f5e218def93 h1:5qkRBchgs4IvlbRdJTMISuktLF1ZtLMowyhzQteEeKI=
gitlab.com/gitlab-org/gitaly v1.87.1-0.20201001041716-3f5e218def93/go.mod h1:NEpGSBkjMt7yV5SB1MFySVQqTKFEUdfTDxS76Rt7GC8=
@@ -660,6 +705,9 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
+go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
@@ -669,8 +717,8 @@ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
-gocloud.dev v0.20.0 h1:mbEKMfnyPV7W1Rj35R1xXfjszs9dXkwSOq2KoFr25g8=
-gocloud.dev v0.20.0/go.mod h1:+Y/RpSXrJthIOM8uFNzWp6MRu9pFPNFEEZrQMxpkfIc=
+gocloud.dev v0.21.1-0.20201223184910-5094f54ed8bb h1:3EJw/ZRo3jKHY2WP8HiAxCpGlfsrKpaIeCl6VfMprKw=
+gocloud.dev v0.21.1-0.20201223184910-5094f54ed8bb/go.mod h1:iI47kpBb27cms1+KJCbcO2NbZBOg4V6SJWFeO/Kpp1c=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -681,9 +729,12 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
+golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -719,6 +770,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
+golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -737,11 +790,12 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -755,16 +809,28 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20201203001011-0b49973bad19 h1:ZD+2Sd/BnevwJp8PSli8WgGAGzb9IZtxBsv1iZMYeEA=
+golang.org/x/oauth2 v0.0.0-20201203001011-0b49973bad19/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -773,6 +839,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -798,6 +866,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -811,7 +880,6 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -820,21 +888,37 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk=
+golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
+golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -858,6 +942,7 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20190829051458-42f498d34c4d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -879,26 +964,36 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200317043434-63da46f3035e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200606014950-c42cb6316fb6/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200608174601-1b747fd94509 h1:MI14dOfl3OG6Zd32w3ugsrvcUO810fDZdWakTq39dH4=
-golang.org/x/tools v0.0.0-20200608174601-1b747fd94509/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201202200335-bef1c476418a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516 h1:E8xavSjXY8LFvcMSu/8Fjztt+SerwKnuAUOdS+aCXUM=
+golang.org/x/tools v0.0.0-20201203202102-a1a1cbeaa516/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
@@ -908,16 +1003,25 @@ google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.26.0 h1:VJZ8h6E8ip82FRpQl848c5vAadxlTXrUh8RzQzSRm08=
-google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo=
+google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
+google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
+google.golang.org/api v0.36.0 h1:l2Nfbl2GPXdWorv+dT2XfinX2jOOw4zv1VhLstx+6rE=
+google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -940,17 +1044,27 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200325114520-5b2d0af7952b/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200603110839-e855014d5736/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482 h1:i+Aiej6cta/Frzp13/swvwz5O00kYcSe0A/C5Wd7zX8=
-google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200921151605-7abf4a1a14d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201203001206-6486ece9c497 h1:jDYzwXmX9tLnuG4sL85HPmE1ruErXOopALp2i/0AHnI=
+google.golang.org/genproto v0.0.0-20201203001206-6486ece9c497/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89 h1:R2owLnwrU3BdTJ5R9cnHDNsnEmBQ7n5lZjKShnbISe4=
+google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@@ -968,6 +1082,16 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
+google.golang.org/grpc v1.34.1 h1:ugq+9++ZQPFzM2pKUMCIK8gj9M0pFyuUWO9Q8kwEDQw=
+google.golang.org/grpc v1.34.1/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
+google.golang.org/grpc/examples v0.0.0-20201226181154-53788aa5dcb4 h1:tfxAh8kBsG9GdCdaDiSCA1qqpd8lMOqgEebUyqTtnH8=
+google.golang.org/grpc/examples v0.0.0-20201226181154-53788aa5dcb4/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -978,6 +1102,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/DataDog/dd-trace-go.v1 v1.7.0 h1:7wbMayb6JXcbAS95RN7MI42W3o1BCxCcdIzZfVWBAiE=
gopkg.in/DataDog/dd-trace-go.v1 v1.7.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
@@ -985,6 +1111,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
@@ -1018,6 +1146,7 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/workhorse/internal/api/api.go b/workhorse/internal/api/api.go
index 988bb73f256..a420288a95a 100644
--- a/workhorse/internal/api/api.go
+++ b/workhorse/internal/api/api.go
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"net/http"
+ "net/textproto"
"net/url"
"strconv"
"strings"
@@ -188,6 +189,8 @@ func (api *API) newRequest(r *http.Request, suffix string) (*http.Request, error
authReq = authReq.WithContext(r.Context())
+ removeConnectionHeaders(authReq.Header)
+
// Clean some headers when issuing a new request without body
authReq.Header.Del("Content-Type")
authReq.Header.Del("Content-Encoding")
@@ -203,7 +206,9 @@ func (api *API) newRequest(r *http.Request, suffix string) (*http.Request, error
authReq.Header.Del("Proxy-Authenticate")
authReq.Header.Del("Proxy-Authorization")
authReq.Header.Del("Te")
- authReq.Header.Del("Trailers")
+ // "Trailer", not "Trailers" as per rfc2616; See errata https://www.rfc-editor.org/errata_search.php?eid=4522
+ // See https://httpwg.org/http-core/draft-ietf-httpbis-semantics-latest.html#field.connection
+ authReq.Header.Del("Trailer")
authReq.Header.Del("Upgrade")
// Also forward the Host header, which is excluded from the Header map by the http library.
@@ -290,6 +295,18 @@ func (api *API) doRequestWithoutRedirects(authReq *http.Request) (*http.Response
return signingTripper.RoundTrip(authReq)
}
+// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
+// See https://tools.ietf.org/html/rfc7230#section-6.1
+func removeConnectionHeaders(h http.Header) {
+ for _, f := range h["Connection"] {
+ for _, sf := range strings.Split(f, ",") {
+ if sf = textproto.TrimString(sf); sf != "" {
+ h.Del(sf)
+ }
+ }
+ }
+}
+
func copyAuthHeader(httpResponse *http.Response, w http.ResponseWriter) {
// Negotiate authentication (Kerberos) may need to return a WWW-Authenticate
// header to the client even in case of success as per RFC4559.
diff --git a/workhorse/internal/errortracker/sentry.go b/workhorse/internal/errortracker/sentry.go
new file mode 100644
index 00000000000..72a32c8d349
--- /dev/null
+++ b/workhorse/internal/errortracker/sentry.go
@@ -0,0 +1,60 @@
+package errortracker
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "runtime/debug"
+
+ "gitlab.com/gitlab-org/labkit/errortracking"
+
+ "gitlab.com/gitlab-org/labkit/log"
+)
+
+// NewHandler allows us to handle panics in upstreams gracefully, by logging them
+// using structured logging and reporting them into Sentry as `error`s with a
+// proper correlation ID attached.
+func NewHandler(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ defer func() {
+ if p := recover(); p != nil {
+ fields := log.ContextFields(r.Context())
+ log.WithFields(fields).Error(p)
+ debug.PrintStack()
+ // A panic isn't always an `error`, so we may have to convert it into one.
+ e, ok := p.(error)
+ if !ok {
+ e = fmt.Errorf("%v", p)
+ }
+ TrackFailedRequest(r, e, fields)
+ }
+ }()
+
+ next.ServeHTTP(w, r)
+ })
+}
+
+func TrackFailedRequest(r *http.Request, err error, fields log.Fields) {
+ captureOpts := []errortracking.CaptureOption{
+ errortracking.WithContext(r.Context()),
+ errortracking.WithRequest(r),
+ }
+ for k, v := range fields {
+ captureOpts = append(captureOpts, errortracking.WithField(k, fmt.Sprintf("%v", v)))
+ }
+
+ errortracking.Capture(err, captureOpts...)
+}
+
+func Initialize(version string) error {
+ // Use a custom environment variable (not SENTRY_DSN) to prevent
+ // clashes with gitlab-rails.
+ sentryDSN := os.Getenv("GITLAB_WORKHORSE_SENTRY_DSN")
+ sentryEnvironment := os.Getenv("GITLAB_WORKHORSE_SENTRY_ENVIRONMENT")
+
+ return errortracking.Initialize(
+ errortracking.WithSentryDSN(sentryDSN),
+ errortracking.WithSentryEnvironment(sentryEnvironment),
+ errortracking.WithVersion(version),
+ )
+}
diff --git a/workhorse/internal/filestore/save_file_opts.go b/workhorse/internal/filestore/save_file_opts.go
index 1eb708c3f55..d0b2c6ec809 100644
--- a/workhorse/internal/filestore/save_file_opts.go
+++ b/workhorse/internal/filestore/save_file_opts.go
@@ -146,7 +146,7 @@ func (c *ObjectStorageConfig) IsGoCloud() bool {
func (c *ObjectStorageConfig) IsValid() bool {
if c.IsAWS() {
- return c.S3Config.Bucket != "" && c.S3Config.Region != "" && c.s3CredentialsValid()
+ return c.S3Config.Bucket != "" && c.s3CredentialsValid()
} else if c.IsGoCloud() {
// We could parse and validate the URL, but GoCloud providers
// such as AzureRM don't have a fallback to normal HTTP, so we
diff --git a/workhorse/internal/filestore/save_file_opts_test.go b/workhorse/internal/filestore/save_file_opts_test.go
index 2d6cd683b51..facfb1cdc85 100644
--- a/workhorse/internal/filestore/save_file_opts_test.go
+++ b/workhorse/internal/filestore/save_file_opts_test.go
@@ -187,6 +187,9 @@ func TestUseWorkhorseClientEnabled(t *testing.T) {
iamConfig := missingCfg
iamConfig.S3Config.UseIamProfile = true
+ missingRegion := cfg
+ missingRegion.S3Config.Region = ""
+
tests := []struct {
name string
UseWorkhorseClient bool
@@ -245,6 +248,13 @@ func TestUseWorkhorseClientEnabled(t *testing.T) {
},
expected: false,
},
+ {
+ name: "missing S3 region",
+ UseWorkhorseClient: true,
+ remoteTempObjectID: "test-object",
+ objectStorageConfig: missingRegion,
+ expected: true,
+ },
}
for _, test := range tests {
diff --git a/workhorse/internal/helper/helpers.go b/workhorse/internal/helper/helpers.go
index f9b46181579..2e23f50b913 100644
--- a/workhorse/internal/helper/helpers.go
+++ b/workhorse/internal/helper/helpers.go
@@ -14,50 +14,31 @@ import (
"syscall"
"github.com/sebest/xff"
- "gitlab.com/gitlab-org/labkit/log"
- "gitlab.com/gitlab-org/labkit/mask"
+
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/log"
)
const NginxResponseBufferHeader = "X-Accel-Buffering"
-func logErrorWithFields(r *http.Request, err error, fields log.Fields) {
- if err != nil {
- CaptureRavenError(r, err, fields)
- }
-
- printError(r, err, fields)
-}
-
-func CaptureAndFail(w http.ResponseWriter, r *http.Request, err error, msg string, code int) {
+func CaptureAndFail(w http.ResponseWriter, r *http.Request, err error, msg string, code int, loggerCallbacks ...log.ConfigureLogger) {
http.Error(w, msg, code)
- logErrorWithFields(r, err, nil)
-}
+ logger := log.WithRequest(r).WithError(err)
+
+ for _, cb := range loggerCallbacks {
+ logger = cb(logger)
+ }
-func Fail500(w http.ResponseWriter, r *http.Request, err error) {
- CaptureAndFail(w, r, err, "Internal server error", http.StatusInternalServerError)
+ logger.Error(msg)
}
-func Fail500WithFields(w http.ResponseWriter, r *http.Request, err error, fields log.Fields) {
- http.Error(w, "Internal server error", http.StatusInternalServerError)
- logErrorWithFields(r, err, fields)
+func Fail500(w http.ResponseWriter, r *http.Request, err error, loggerCallbacks ...log.ConfigureLogger) {
+ CaptureAndFail(w, r, err, "Internal server error", http.StatusInternalServerError, loggerCallbacks...)
}
func RequestEntityTooLarge(w http.ResponseWriter, r *http.Request, err error) {
CaptureAndFail(w, r, err, "Request Entity Too Large", http.StatusRequestEntityTooLarge)
}
-func printError(r *http.Request, err error, fields log.Fields) {
- if r != nil {
- entry := log.WithContextFields(r.Context(), log.Fields{
- "method": r.Method,
- "uri": mask.URL(r.RequestURI),
- })
- entry.WithFields(fields).WithError(err).Error()
- } else {
- log.WithFields(fields).WithError(err).Error("unknown error")
- }
-}
-
func SetNoCacheHeaders(header http.Header) {
header.Set("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")
header.Set("Pragma", "no-cache")
@@ -97,7 +78,7 @@ func OpenFile(path string) (file *os.File, fi os.FileInfo, err error) {
func URLMustParse(s string) *url.URL {
u, err := url.Parse(s)
if err != nil {
- log.WithError(err).WithField("url", s).Fatal("urlMustParse")
+ log.WithError(err).WithFields(log.Fields{"url": s}).Error("urlMustParse")
}
return u
}
diff --git a/workhorse/internal/helper/raven.go b/workhorse/internal/helper/raven.go
deleted file mode 100644
index 898e8ec85f8..00000000000
--- a/workhorse/internal/helper/raven.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package helper
-
-import (
- "net/http"
- "reflect"
-
- raven "github.com/getsentry/raven-go"
-
- //lint:ignore SA1019 this was recently deprecated. Update workhorse to use labkit errortracking package.
- correlation "gitlab.com/gitlab-org/labkit/correlation/raven"
-
- "gitlab.com/gitlab-org/labkit/log"
-)
-
-var ravenHeaderBlacklist = []string{
- "Authorization",
- "Private-Token",
-}
-
-func CaptureRavenError(r *http.Request, err error, fields log.Fields) {
- client := raven.DefaultClient
- extra := raven.Extra{}
-
- for k, v := range fields {
- extra[k] = v
- }
-
- interfaces := []raven.Interface{}
- if r != nil {
- CleanHeadersForRaven(r)
- interfaces = append(interfaces, raven.NewHttp(r))
-
- //lint:ignore SA1019 this was recently deprecated. Update workhorse to use labkit errortracking package.
- extra = correlation.SetExtra(r.Context(), extra)
- }
-
- exception := &raven.Exception{
- Stacktrace: raven.NewStacktrace(2, 3, nil),
- Value: err.Error(),
- Type: reflect.TypeOf(err).String(),
- }
- interfaces = append(interfaces, exception)
-
- packet := raven.NewPacketWithExtra(err.Error(), extra, interfaces...)
- client.Capture(packet, nil)
-}
-
-func CleanHeadersForRaven(r *http.Request) {
- if r == nil {
- return
- }
-
- for _, key := range ravenHeaderBlacklist {
- if r.Header.Get(key) != "" {
- r.Header.Set(key, "[redacted]")
- }
- }
-}
diff --git a/workhorse/internal/imageresizer/image_resizer.go b/workhorse/internal/imageresizer/image_resizer.go
index 69e9496aec2..7d423b80067 100644
--- a/workhorse/internal/imageresizer/image_resizer.go
+++ b/workhorse/internal/imageresizer/image_resizer.go
@@ -428,16 +428,18 @@ func logFields(startTime time.Time, params *resizeParams, outcome *resizeOutcome
func handleOutcome(w http.ResponseWriter, req *http.Request, startTime time.Time, params *resizeParams, outcome *resizeOutcome) {
fields := logFields(startTime, params, outcome)
- log := log.WithRequest(req).WithFields(fields)
+ logger := log.WithRequest(req).WithFields(fields)
switch outcome.status {
case statusRequestFailure:
if outcome.bytesWritten <= 0 {
- helper.Fail500WithFields(w, req, outcome.err, fields)
+ helper.Fail500(w, req, outcome.err, func(b *log.Builder) *log.Builder {
+ return b.WithFields(fields)
+ })
} else {
- log.WithError(outcome.err).Error(outcome.status)
+ logger.WithError(outcome.err).Error(outcome.status)
}
default:
- log.Info(outcome.status)
+ logger.Info(outcome.status)
}
}
diff --git a/workhorse/internal/log/logging.go b/workhorse/internal/log/logging.go
index c65ec07743a..9c19cde1395 100644
--- a/workhorse/internal/log/logging.go
+++ b/workhorse/internal/log/logging.go
@@ -8,11 +8,13 @@ import (
"gitlab.com/gitlab-org/labkit/mask"
"golang.org/x/net/context"
- "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/errortracker"
)
type Fields = log.Fields
+type ConfigureLogger func(*Builder) *Builder
+
type Builder struct {
entry *logrus.Entry
fields log.Fields
@@ -83,6 +85,6 @@ func (b *Builder) Error(args ...interface{}) {
b.entry.Error(args...)
if b.req != nil && b.err != nil {
- helper.CaptureRavenError(b.req, b.err, b.fields)
+ errortracker.TrackFailedRequest(b.req, b.err, b.fields)
}
}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index 5bbd245719b..edcbfa88a67 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -55,7 +55,7 @@ type uploadPreparers struct {
const (
apiPattern = `^/api/`
ciAPIPattern = `^/ci/api/`
- gitProjectPattern = `^/([^/]+/){1,}[^/]+\.git/`
+ gitProjectPattern = `^/.+\.git/`
projectPattern = `^/([^/]+/){1,}[^/]+/`
snippetUploadPattern = `^/uploads/personal_snippet`
userUploadPattern = `^/uploads/user`
@@ -262,7 +262,10 @@ func (u *upstream) configureRoutes() {
u.route("POST", apiPattern+`v4/projects/[0-9]+/packages/pypi`, upload.Accelerate(api, signingProxy, preparers.packages)),
// Debian Artifact Repository
- u.route("PUT", apiPattern+`v4/projects/[0-9]+/-/packages/debian/incoming/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+ u.route("PUT", apiPattern+`v4/projects/[0-9]+/packages/debian/`, upload.BodyUploader(api, signingProxy, preparers.packages)),
+
+ // Gem Artifact Repository
+ u.route("POST", apiPattern+`v4/projects/[0-9]+/packages/rubygems/`, upload.BodyUploader(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.
diff --git a/workhorse/internal/upstream/upstream.go b/workhorse/internal/upstream/upstream.go
index c81a21c0ecd..fd655a07679 100644
--- a/workhorse/internal/upstream/upstream.go
+++ b/workhorse/internal/upstream/upstream.go
@@ -16,6 +16,7 @@ import (
"gitlab.com/gitlab-org/labkit/correlation"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/config"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/errortracker"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/rejectmethods"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/upload"
@@ -63,7 +64,7 @@ func NewUpstream(cfg config.Config, accessLogger *logrus.Logger) http.Handler {
correlationOpts = append(correlationOpts, correlation.WithPropagation())
}
- handler := correlation.InjectCorrelationID(&up, correlationOpts...)
+ handler := correlation.InjectCorrelationID(errortracker.NewHandler(&up), correlationOpts...)
// TODO: move to LabKit https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/339
handler = rejectmethods.NewMiddleware(handler)
return handler
diff --git a/workhorse/main.go b/workhorse/main.go
index 47ab63a875a..c43ec45240f 100644
--- a/workhorse/main.go
+++ b/workhorse/main.go
@@ -16,6 +16,7 @@ import (
"gitlab.com/gitlab-org/labkit/tracing"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/config"
+ "gitlab.com/gitlab-org/gitlab-workhorse/internal/errortracker"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/queueing"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/redis"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/secret"
@@ -156,6 +157,8 @@ func run(boot bootConfig, cfg config.Config) error {
}
defer closer.Close()
+ errortracker.Initialize(cfg.Version)
+
tracing.Initialize(tracing.WithServiceName("gitlab-workhorse"))
log.WithField("version", Version).WithField("build_time", BuildTime).Print("Starting")
@@ -223,7 +226,7 @@ func run(boot bootConfig, cfg config.Config) error {
}
defer accessCloser.Close()
- up := wrapRaven(upstream.NewUpstream(cfg, accessLogger))
+ up := upstream.NewUpstream(cfg, accessLogger)
go func() { finalErrors <- http.Serve(listener, up) }()
diff --git a/workhorse/main_test.go b/workhorse/main_test.go
index d15af1d3e4c..b725f36a68a 100644
--- a/workhorse/main_test.go
+++ b/workhorse/main_test.go
@@ -694,6 +694,12 @@ func testAuthServer(t *testing.T, url *regexp.Regexp, params url.Values, code in
return testhelper.TestServerWithHandler(url, func(w http.ResponseWriter, r *http.Request) {
require.NotEmpty(t, r.Header.Get("X-Request-Id"))
+ // return a 204 No Content response if we don't receive the JWT header
+ if r.Header.Get(secret.RequestHeader) == "" {
+ w.WriteHeader(204)
+ return
+ }
+
w.Header().Set("Content-Type", api.ResponseContentType)
logEntry := log.WithFields(log.Fields{
diff --git a/workhorse/raven.go b/workhorse/raven.go
deleted file mode 100644
index f641203f142..00000000000
--- a/workhorse/raven.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package main
-
-import (
- "net/http"
- "os"
-
- raven "github.com/getsentry/raven-go"
-
- "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
-)
-
-func wrapRaven(h http.Handler) http.Handler {
- // Use a custom environment variable (not SENTRY_DSN) to prevent
- // clashes with gitlab-rails.
- sentryDSN := os.Getenv("GITLAB_WORKHORSE_SENTRY_DSN")
- sentryEnvironment := os.Getenv("GITLAB_WORKHORSE_SENTRY_ENVIRONMENT")
- raven.SetDSN(sentryDSN) // sentryDSN may be empty
-
- if sentryEnvironment != "" {
- raven.SetEnvironment(sentryEnvironment)
- }
-
- if sentryDSN == "" {
- return h
- }
-
- raven.DefaultClient.SetRelease(Version)
-
- return http.HandlerFunc(raven.RecoveryHandler(
- func(w http.ResponseWriter, r *http.Request) {
- defer func() {
- if p := recover(); p != nil {
- helper.CleanHeadersForRaven(r)
- panic(p)
- }
- }()
-
- h.ServeHTTP(w, r)
- }))
-}
diff --git a/workhorse/upload_test.go b/workhorse/upload_test.go
index 1e5d9bd00e9..6d118119dff 100644
--- a/workhorse/upload_test.go
+++ b/workhorse/upload_test.go
@@ -292,9 +292,77 @@ func TestLfsUpload(t *testing.T) {
require.Equal(t, rspBody, string(rspData))
}
-func packageUploadTestServer(t *testing.T, resource string, reqBody string, rspBody string) *httptest.Server {
+func TestLfsUploadRouting(t *testing.T) {
+ reqBody := "test data"
+ rspBody := "test success"
+ oid := "916f0027a575074ce72a331777c3478d6513f786a591bd892da1a577bf2335f9"
+
+ ts := testhelper.TestServerWithHandler(regexp.MustCompile(`.`), func(w http.ResponseWriter, r *http.Request) {
+ if r.Header.Get(secret.RequestHeader) == "" {
+ w.WriteHeader(204)
+ } else {
+ fmt.Fprint(w, rspBody)
+ }
+ })
+ defer ts.Close()
+
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ testCases := []struct {
+ method string
+ path string
+ contentType string
+ match bool
+ }{
+ {"PUT", "/toplevel.git/gitlab-lfs/objects", "application/octet-stream", true},
+ {"PUT", "/toplevel.wiki.git/gitlab-lfs/objects", "application/octet-stream", true},
+ {"PUT", "/toplevel/child/project.git/gitlab-lfs/objects", "application/octet-stream", true},
+ {"PUT", "/toplevel/child/project.wiki.git/gitlab-lfs/objects", "application/octet-stream", true},
+ {"PUT", "/toplevel/child/project/snippets/123.git/gitlab-lfs/objects", "application/octet-stream", true},
+ {"PUT", "/snippets/123.git/gitlab-lfs/objects", "application/octet-stream", true},
+ {"PUT", "/foo/bar/gitlab-lfs/objects", "application/octet-stream", false},
+ {"PUT", "/foo/bar.git/gitlab-lfs/objects/zzz", "application/octet-stream", false},
+ {"PUT", "/.git/gitlab-lfs/objects", "application/octet-stream", false},
+ {"PUT", "/toplevel.git/gitlab-lfs/objects", "application/zzz", false},
+ {"POST", "/toplevel.git/gitlab-lfs/objects", "application/octet-stream", false},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.path, func(t *testing.T) {
+ resource := fmt.Sprintf(tc.path+"/%s/%d", oid, len(reqBody))
+
+ req, err := http.NewRequest(
+ tc.method,
+ ws.URL+resource,
+ strings.NewReader(reqBody),
+ )
+ require.NoError(t, err)
+
+ req.Header.Set("Content-Type", tc.contentType)
+ req.ContentLength = int64(len(reqBody))
+
+ resp, err := http.DefaultClient.Do(req)
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ rspData, err := ioutil.ReadAll(resp.Body)
+ require.NoError(t, err)
+
+ if tc.match {
+ require.Equal(t, 200, resp.StatusCode)
+ require.Equal(t, rspBody, string(rspData), "expect response generated by test upstream server")
+ } else {
+ require.Equal(t, 204, resp.StatusCode)
+ require.Empty(t, rspData, "normal request has empty response body")
+ }
+ })
+ }
+}
+
+func packageUploadTestServer(t *testing.T, method string, resource string, reqBody string, rspBody string) *httptest.Server {
return testhelper.TestServerWithHandler(regexp.MustCompile(`.`), func(w http.ResponseWriter, r *http.Request) {
- require.Equal(t, r.Method, "PUT")
+ require.Equal(t, r.Method, method)
apiResponse := fmt.Sprintf(
`{"TempPath":%q, "Size": %d}`, scratchDir, len(reqBody),
)
@@ -330,17 +398,17 @@ func packageUploadTestServer(t *testing.T, resource string, reqBody string, rspB
})
}
-func testPackageFileUpload(t *testing.T, resource string) {
+func testPackageFileUpload(t *testing.T, method string, resource string) {
reqBody := "test data"
rspBody := "test success"
- ts := packageUploadTestServer(t, resource, reqBody, rspBody)
+ ts := packageUploadTestServer(t, method, resource, reqBody, rspBody)
defer ts.Close()
ws := startWorkhorseServer(ts.URL)
defer ws.Close()
- req, err := http.NewRequest("PUT", ws.URL+resource, strings.NewReader(reqBody))
+ req, err := http.NewRequest(method, ws.URL+resource, strings.NewReader(reqBody))
require.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
@@ -355,15 +423,19 @@ func testPackageFileUpload(t *testing.T, resource string) {
}
func TestPackageFilesUpload(t *testing.T) {
- routes := []string{
- "/api/v4/packages/conan/v1/files",
- "/api/v4/projects/2412/packages/conan/v1/files",
- "/api/v4/projects/2412/packages/maven/v1/files",
- "/api/v4/projects/2412/packages/generic/mypackage/0.0.1/myfile.tar.gz",
- "/api/v4/projects/2412/-/packages/debian/incoming/libsample0_1.2.3~alpha2-1_amd64.deb",
+ routes := []struct {
+ method string
+ resource string
+ }{
+ {"PUT", "/api/v4/packages/conan/v1/files"},
+ {"PUT", "/api/v4/projects/2412/packages/conan/v1/files"},
+ {"PUT", "/api/v4/projects/2412/packages/maven/v1/files"},
+ {"PUT", "/api/v4/projects/2412/packages/generic/mypackage/0.0.1/myfile.tar.gz"},
+ {"PUT", "/api/v4/projects/2412/packages/debian/libsample0_1.2.3~alpha2-1_amd64.deb"},
+ {"POST", "/api/v4/projects/2412/packages/rubygems/api/v1/gems/sample.gem"},
}
for _, r := range routes {
- testPackageFileUpload(t, r)
+ testPackageFileUpload(t, r.method, r.resource)
}
}
diff --git a/yarn.lock b/yarn.lock
index e21ccf83cc9..3d8f9242f54 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -840,25 +840,41 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
-"@gitlab/at.js@1.5.5":
- version "1.5.5"
- resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.5.tgz#5f6bfe6baaef360daa9b038fa78798d7a6a916b4"
- integrity sha512-282Dn3SPVsUHVDhMsXgfnv+Rzog0uxecjttxGRQvxh25es1+xvkGQFsvJfkSKJ3X1kHVkSjKf+Tt5Rra+Jhp9g==
+"@eslint/eslintrc@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318"
+ integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.1.1"
+ espree "^7.3.0"
+ globals "^12.1.0"
+ ignore "^4.0.6"
+ import-fresh "^3.2.1"
+ js-yaml "^3.13.1"
+ lodash "^4.17.20"
+ minimatch "^3.0.4"
+ strip-json-comments "^3.1.1"
-"@gitlab/eslint-plugin@6.0.0":
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-6.0.0.tgz#deb18f63808af1cb1cc117a92558f07edb1e2256"
- integrity sha512-3TihEG0EzbGtc6wxZLANZN1ge2tnAv0qU8w6smUACmPhqFj0/DrCq9V6QKPqAHk/Yn3hrfGk5nznAzzuMEgwDQ==
+"@gitlab/at.js@1.5.7":
+ version "1.5.7"
+ resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.7.tgz#1ee6f838cc4410a1d797770934df91d90df8179e"
+ integrity sha512-c6ySRK/Ma7lxwpIVbSAF3P+xiTLrNTGTLRx4/pHK111AdFxwgUwrYF6aVZFXvmG65jHOJHoa0eQQ21RW6rm0Rg==
+
+"@gitlab/eslint-plugin@8.0.0":
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-8.0.0.tgz#e8d30fd98e2102f417617d0c60ef1810520a8ac6"
+ integrity sha512-hTTdcyxN3Ead2FaNwaiPg9sv2YbCDrlyAgKAPV7dit2uPqR0nkIlng9JPNMIixTXBrJ/Y+VvjIRrKKNYBubocw==
dependencies:
babel-eslint "^10.0.3"
- eslint-config-airbnb-base "^14.0.0"
+ eslint-config-airbnb-base "^14.2.1"
eslint-config-prettier "^6.10.0"
eslint-plugin-babel "^5.3.0"
eslint-plugin-filenames "^1.3.2"
- eslint-plugin-import "^2.20.1"
+ eslint-plugin-import "^2.22.1"
eslint-plugin-jest "^23.8.2"
eslint-plugin-promise "^4.2.1"
- eslint-plugin-vue "^7.4.1"
+ eslint-plugin-vue "^7.5.0"
vue-eslint-parser "^7.0.0"
"@gitlab/favicon-overlay@2.0.0":
@@ -866,27 +882,27 @@
resolved "https://registry.yarnpkg.com/@gitlab/favicon-overlay/-/favicon-overlay-2.0.0.tgz#2f32d0b6a4d5b8ac44e2927083d9ab478a78c984"
integrity sha512-GNcORxXJ98LVGzOT9dDYKfbheqH6lNgPDD72lyXRnQIH7CjgGyos8i17aSBPq1f4s3zF3PyedFiAR4YEZbva2Q==
-"@gitlab/svgs@1.178.0":
- version "1.178.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.178.0.tgz#069edb8abb4c7137d48f527592476655f066538b"
- integrity sha512-m1xe5SPgpi9lSFCHHTkkGeScxkqhi7aD8qApL5F4MqCGeKF9IhELIVoMD1R6vkfjzFJh0BwFREPkuwjnAOMKfA==
+"@gitlab/svgs@1.182.0":
+ version "1.182.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.182.0.tgz#600cb577c598ff63325c3f6f049e3254abdbb580"
+ integrity sha512-hV6Hkd92bNyzGm2awdwtyXVjT71QZkfAMVV9qHg9fhu5swA4qLrxzXpYBBfeY3/e2KJIByVfROP8tSFws0R6Kw==
"@gitlab/tributejs@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@25.11.3":
- version "25.11.3"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.11.3.tgz#54719d1276f417e66904f9f951671633f1647006"
- integrity sha512-ur8UfgJ7giQZtp7pbVAwRYSWoxOzsFTpx/OpDge5EnmrH3S6YT0BOPxYs9T2HcMYN2Cejft1rhFJY+aPGxqxJA==
+"@gitlab/ui@27.4.6":
+ version "27.4.6"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-27.4.6.tgz#2364c2ba981024cdce32b4657c5f0eb2ae781a4d"
+ integrity sha512-0fUNgu0tjk/BBq9NmuZg7THcEsUvfhz/mhUwnLWB5hjrfa7Nnu+TRBgeVfs08vDyK7h6uualgITTH+eTGo6tyw==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.13.1"
copy-to-clipboard "^3.0.8"
dompurify "^2.2.6"
- echarts "^4.2.1"
+ echarts "^4.9.0"
highlight.js "^9.13.1"
js-beautify "^1.8.8"
lodash "^4.17.20"
@@ -1120,6 +1136,13 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+"@npmcli/move-file@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464"
+ integrity sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==
+ dependencies:
+ mkdirp "^1.0.4"
+
"@nuxt/opencollective@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
@@ -1309,10 +1332,15 @@
jest-diff "^25.2.1"
pretty-format "^25.2.1"
-"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.5":
- version "7.0.6"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
- integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
+"@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/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/minimatch@*":
version "3.0.3"
@@ -1437,150 +1465,149 @@
lodash "^4.17.15"
pretty "^2.0.0"
-"@webassemblyjs/ast@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
- integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==
- dependencies:
- "@webassemblyjs/helper-module-context" "1.8.5"
- "@webassemblyjs/helper-wasm-bytecode" "1.8.5"
- "@webassemblyjs/wast-parser" "1.8.5"
-
-"@webassemblyjs/floating-point-hex-parser@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721"
- integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==
-
-"@webassemblyjs/helper-api-error@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7"
- integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==
-
-"@webassemblyjs/helper-buffer@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204"
- integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==
-
-"@webassemblyjs/helper-code-frame@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e"
- integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==
- dependencies:
- "@webassemblyjs/wast-printer" "1.8.5"
-
-"@webassemblyjs/helper-fsm@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452"
- integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==
-
-"@webassemblyjs/helper-module-context@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245"
- integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- mamacro "^0.0.3"
-
-"@webassemblyjs/helper-wasm-bytecode@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61"
- integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==
-
-"@webassemblyjs/helper-wasm-section@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf"
- integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/helper-buffer" "1.8.5"
- "@webassemblyjs/helper-wasm-bytecode" "1.8.5"
- "@webassemblyjs/wasm-gen" "1.8.5"
-
-"@webassemblyjs/ieee754@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e"
- integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==
+"@webassemblyjs/ast@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
+ integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==
+ dependencies:
+ "@webassemblyjs/helper-module-context" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/wast-parser" "1.9.0"
+
+"@webassemblyjs/floating-point-hex-parser@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4"
+ integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==
+
+"@webassemblyjs/helper-api-error@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2"
+ integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==
+
+"@webassemblyjs/helper-buffer@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00"
+ integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==
+
+"@webassemblyjs/helper-code-frame@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27"
+ integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==
+ dependencies:
+ "@webassemblyjs/wast-printer" "1.9.0"
+
+"@webassemblyjs/helper-fsm@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8"
+ integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==
+
+"@webassemblyjs/helper-module-context@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07"
+ integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+
+"@webassemblyjs/helper-wasm-bytecode@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790"
+ integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==
+
+"@webassemblyjs/helper-wasm-section@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346"
+ integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-buffer" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/wasm-gen" "1.9.0"
+
+"@webassemblyjs/ieee754@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4"
+ integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==
dependencies:
"@xtuc/ieee754" "^1.2.0"
-"@webassemblyjs/leb128@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10"
- integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==
+"@webassemblyjs/leb128@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95"
+ integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==
dependencies:
"@xtuc/long" "4.2.2"
-"@webassemblyjs/utf8@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc"
- integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==
-
-"@webassemblyjs/wasm-edit@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a"
- integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/helper-buffer" "1.8.5"
- "@webassemblyjs/helper-wasm-bytecode" "1.8.5"
- "@webassemblyjs/helper-wasm-section" "1.8.5"
- "@webassemblyjs/wasm-gen" "1.8.5"
- "@webassemblyjs/wasm-opt" "1.8.5"
- "@webassemblyjs/wasm-parser" "1.8.5"
- "@webassemblyjs/wast-printer" "1.8.5"
-
-"@webassemblyjs/wasm-gen@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc"
- integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/helper-wasm-bytecode" "1.8.5"
- "@webassemblyjs/ieee754" "1.8.5"
- "@webassemblyjs/leb128" "1.8.5"
- "@webassemblyjs/utf8" "1.8.5"
-
-"@webassemblyjs/wasm-opt@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264"
- integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/helper-buffer" "1.8.5"
- "@webassemblyjs/wasm-gen" "1.8.5"
- "@webassemblyjs/wasm-parser" "1.8.5"
-
-"@webassemblyjs/wasm-parser@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d"
- integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/helper-api-error" "1.8.5"
- "@webassemblyjs/helper-wasm-bytecode" "1.8.5"
- "@webassemblyjs/ieee754" "1.8.5"
- "@webassemblyjs/leb128" "1.8.5"
- "@webassemblyjs/utf8" "1.8.5"
-
-"@webassemblyjs/wast-parser@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c"
- integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==
- dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/floating-point-hex-parser" "1.8.5"
- "@webassemblyjs/helper-api-error" "1.8.5"
- "@webassemblyjs/helper-code-frame" "1.8.5"
- "@webassemblyjs/helper-fsm" "1.8.5"
+"@webassemblyjs/utf8@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab"
+ integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==
+
+"@webassemblyjs/wasm-edit@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf"
+ integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-buffer" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/helper-wasm-section" "1.9.0"
+ "@webassemblyjs/wasm-gen" "1.9.0"
+ "@webassemblyjs/wasm-opt" "1.9.0"
+ "@webassemblyjs/wasm-parser" "1.9.0"
+ "@webassemblyjs/wast-printer" "1.9.0"
+
+"@webassemblyjs/wasm-gen@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c"
+ integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/ieee754" "1.9.0"
+ "@webassemblyjs/leb128" "1.9.0"
+ "@webassemblyjs/utf8" "1.9.0"
+
+"@webassemblyjs/wasm-opt@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61"
+ integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-buffer" "1.9.0"
+ "@webassemblyjs/wasm-gen" "1.9.0"
+ "@webassemblyjs/wasm-parser" "1.9.0"
+
+"@webassemblyjs/wasm-parser@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e"
+ integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-api-error" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/ieee754" "1.9.0"
+ "@webassemblyjs/leb128" "1.9.0"
+ "@webassemblyjs/utf8" "1.9.0"
+
+"@webassemblyjs/wast-parser@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914"
+ integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/floating-point-hex-parser" "1.9.0"
+ "@webassemblyjs/helper-api-error" "1.9.0"
+ "@webassemblyjs/helper-code-frame" "1.9.0"
+ "@webassemblyjs/helper-fsm" "1.9.0"
"@xtuc/long" "4.2.2"
-"@webassemblyjs/wast-printer@1.8.5":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc"
- integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==
+"@webassemblyjs/wast-printer@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899"
+ integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==
dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/wast-parser" "1.8.5"
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/wast-parser" "1.9.0"
"@xtuc/long" "4.2.2"
"@wry/context@^0.4.0":
@@ -1639,27 +1666,22 @@ acorn-globals@^6.0.0:
acorn "^7.1.1"
acorn-walk "^7.1.1"
-acorn-jsx@^5.2.0:
+acorn-jsx@^5.2.0, acorn-jsx@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
-acorn-walk@^6.1.1:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
- integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
-
acorn-walk@^7.1.1:
version "7.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn@^6.0.7, acorn@^6.2.1, acorn@^6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e"
- integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==
+acorn@^6.3.0, acorn@^6.4.1:
+ version "6.4.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
+ integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
-acorn@^7.1.1:
+acorn@^7.1.1, acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
@@ -1694,7 +1716,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
-ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4:
+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"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -1704,6 +1726,16 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
+ajv@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.4.tgz#827e5f5ae32f5e5c1637db61f253a112229b5e2f"
+ integrity sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
@@ -1721,6 +1753,11 @@ ansi-colors@^3.0.0:
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"
+ integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
+
ansi-escapes@^4.2.1:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d"
@@ -1949,13 +1986,16 @@ array-flatten@^2.1.0:
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.1.tgz#426bb9da84090c1838d812c8150af20a8331e296"
integrity sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=
-array-includes@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d"
- integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=
+array-includes@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8"
+ integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==
dependencies:
- define-properties "^1.1.2"
- es-abstract "^1.7.0"
+ call-bind "^1.0.0"
+ define-properties "^1.1.3"
+ es-abstract "^1.18.0-next.1"
+ get-intrinsic "^1.0.1"
+ is-string "^1.0.5"
array-union@^1.0.1, array-union@^1.0.2:
version "1.0.2"
@@ -1974,13 +2014,14 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
-array.prototype.flat@^1.2.1:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b"
- integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==
+array.prototype.flat@^1.2.3:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123"
+ integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
+ es-abstract "^1.18.0-next.1"
arraybuffer.slice@~0.0.7:
version "0.0.7"
@@ -2030,6 +2071,11 @@ astral-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+astral-regex@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
+ integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
+
async-foreach@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
@@ -2140,15 +2186,15 @@ babel-jest@^26.5.2:
graceful-fs "^4.2.4"
slash "^3.0.0"
-babel-loader@^8.0.6:
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb"
- integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==
+babel-loader@^8.2.2:
+ version "8.2.2"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81"
+ integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==
dependencies:
- find-cache-dir "^2.0.0"
- loader-utils "^1.0.2"
- mkdirp "^0.5.1"
- pify "^4.0.1"
+ find-cache-dir "^3.3.1"
+ loader-utils "^1.4.0"
+ make-dir "^3.1.0"
+ schema-utils "^2.6.5"
babel-plugin-dynamic-import-node@^2.3.3:
version "2.3.3"
@@ -2323,10 +2369,10 @@ bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.1, bluebird@^3.5.5, bluebird@~3.
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
- version "4.11.8"
- resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
- integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9:
+ version "4.11.9"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
+ integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
body-parser@1.19.0, body-parser@^1.16.1:
version "1.19.0"
@@ -2386,7 +2432,7 @@ boxen@^4.2.0:
type-fest "^0.8.1"
widest-line "^3.1.0"
-brace-expansion@^1.1.7, brace-expansion@^1.1.8:
+brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
@@ -2417,7 +2463,7 @@ braces@^3.0.1, braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
-brorand@^1.0.1:
+brorand@^1.0.1, brorand@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
@@ -2486,14 +2532,15 @@ browserify-zlib@^0.2.0:
pako "~1.0.5"
browserslist@^4.12.0, browserslist@^4.6.3, browserslist@^4.8.3:
- version "4.12.0"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d"
- integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==
+ version "4.16.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766"
+ integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==
dependencies:
- caniuse-lite "^1.0.30001043"
- electron-to-chromium "^1.3.413"
- node-releases "^1.1.53"
- pkg-up "^2.0.0"
+ caniuse-lite "^1.0.30001173"
+ colorette "^1.2.1"
+ electron-to-chromium "^1.3.634"
+ escalade "^3.1.1"
+ node-releases "^1.1.69"
bs-logger@0.x:
version "0.2.6"
@@ -2574,28 +2621,27 @@ cacache@^12.0.2, cacache@^12.0.3:
unique-filename "^1.1.1"
y18n "^4.0.0"
-cacache@^13.0.1:
- version "13.0.1"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c"
- integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==
+cacache@^15.0.5:
+ version "15.0.5"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0"
+ integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==
dependencies:
- chownr "^1.1.2"
- figgy-pudding "^3.5.1"
+ "@npmcli/move-file" "^1.0.1"
+ chownr "^2.0.0"
fs-minipass "^2.0.0"
glob "^7.1.4"
- graceful-fs "^4.2.2"
infer-owner "^1.0.4"
- lru-cache "^5.1.1"
- minipass "^3.0.0"
+ lru-cache "^6.0.0"
+ minipass "^3.1.1"
minipass-collect "^1.0.2"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.2"
- mkdirp "^0.5.1"
- move-concurrently "^1.0.1"
- p-map "^3.0.0"
+ mkdirp "^1.0.3"
+ p-map "^4.0.0"
promise-inflight "^1.0.1"
- rimraf "^2.7.1"
- ssri "^7.0.0"
+ rimraf "^3.0.2"
+ ssri "^8.0.0"
+ tar "^6.0.2"
unique-filename "^1.1.1"
cache-base@^1.0.1:
@@ -2638,6 +2684,14 @@ cacheable-request@^6.0.0:
normalize-url "^4.1.0"
responselike "^1.0.2"
+call-bind@^1.0.0, call-bind@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
+
call-me-maybe@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
@@ -2717,10 +2771,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.30000980, caniuse-lite@^1.0.30001043:
- version "1.0.30001081"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001081.tgz#40615a3c416a047c5a4d45673e5257bf128eb3b5"
- integrity sha512-iZdh3lu09jsUtLE6Bp8NAbJskco4Y3UDtkR3GTCJGsbMowBU5IWDFF79sV2ws7lSqTzWyKazxam2thasHymENQ==
+caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30001173:
+ version "1.0.30001178"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001178.tgz#3ad813b2b2c7d585b0be0a2440e1e233c6eabdbc"
+ integrity sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==
capture-exit@^2.0.0:
version "2.0.0"
@@ -2746,15 +2800,6 @@ ccount@^1.0.0:
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff"
integrity sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==
-chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
chalk@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -2766,6 +2811,15 @@ chalk@^1.1.1:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
chalk@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
@@ -2807,11 +2861,6 @@ character-reference-invalid@^1.0.0:
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed"
integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==
-chardet@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
- integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
-
charenc@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
@@ -2822,7 +2871,7 @@ check-types@^7.3.0:
resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d"
integrity sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=
-chokidar@^2.1.8, chokidar@^3.0.0, chokidar@^3.2.2, chokidar@^3.4.0:
+chokidar@^2.1.8, chokidar@^3.0.0, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==
@@ -2837,11 +2886,16 @@ chokidar@^2.1.8, chokidar@^3.0.0, chokidar@^3.2.2, chokidar@^3.4.0:
optionalDependencies:
fsevents "~2.1.2"
-chownr@^1.1.1, chownr@^1.1.2:
+chownr@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142"
integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==
+chownr@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
+ integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
+
chrome-trace-event@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
@@ -2889,18 +2943,6 @@ cli-boxes@^2.2.0:
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
-cli-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
- integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
- dependencies:
- restore-cursor "^3.1.0"
-
-cli-width@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
- integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
-
clipboard@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b"
@@ -2919,15 +2961,6 @@ clipboard@^2.0.0:
select "^1.1.2"
tiny-emitter "^2.0.0"
-cliui@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
- integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
- dependencies:
- string-width "^2.1.1"
- strip-ansi "^4.0.0"
- wrap-ansi "^2.0.0"
-
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
@@ -3050,6 +3083,11 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+colorette@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
+ integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
+
colors@^1.1.0:
version "1.3.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
@@ -3106,17 +3144,16 @@ compressible@~2.0.16:
dependencies:
mime-db ">= 1.40.0 < 2"
-compression-webpack-plugin@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-3.0.1.tgz#be7a343e6dfbccbd64a77c5fbe29627d140fc321"
- integrity sha512-FOwoBVzDiwSdJDnZTKXDpAjJU90k8SbChgxnoiYwTo15xjIDJkSC8wFKuc13DymXjgasPEqzS5+2RUgSKXdKKA==
+compression-webpack-plugin@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-5.0.2.tgz#df84e682cfa1fb2a230e71cf83d50c323d5369c2"
+ integrity sha512-F2G4cQfsMZ6CiPlG22Q5EDUCqnfyZqTjyJP5cMgNYUbBg/dUzV3hto8yTFFIogDCTWooVbePHQE0qL6FrJUSsA==
dependencies:
- cacache "^13.0.1"
- find-cache-dir "^3.0.0"
- neo-async "^2.5.0"
- schema-utils "^2.6.1"
- serialize-javascript "^2.1.2"
- webpack-sources "^1.0.1"
+ cacache "^15.0.5"
+ find-cache-dir "^3.3.1"
+ schema-utils "^2.7.0"
+ serialize-javascript "^4.0.0"
+ webpack-sources "^1.4.3"
compression@^1.7.4:
version "1.7.4"
@@ -3175,10 +3212,10 @@ configstore@^5.0.1:
write-file-atomic "^3.0.0"
xdg-basedir "^4.0.0"
-confusing-browser-globals@^1.0.7:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd"
- integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==
+confusing-browser-globals@^1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59"
+ integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==
connect-history-api-fallback@^1.6.0:
version "1.6.0"
@@ -3287,10 +3324,10 @@ copy-to-clipboard@^3.0.8:
dependencies:
toggle-selection "^1.0.6"
-copy-webpack-plugin@^5.0.5:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88"
- integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==
+copy-webpack-plugin@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz#8a889e1dcafa6c91c6cd4be1ad158f1d3823bae2"
+ integrity sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==
dependencies:
cacache "^12.0.3"
find-cache-dir "^2.1.0"
@@ -3302,7 +3339,7 @@ copy-webpack-plugin@^5.0.5:
normalize-path "^3.0.0"
p-limit "^2.2.1"
schema-utils "^1.0.0"
- serialize-javascript "^2.1.2"
+ serialize-javascript "^4.0.0"
webpack-log "^2.0.0"
core-js-compat@^3.6.2:
@@ -3318,10 +3355,10 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.1.3, core-js@^3.6.4:
- version "3.6.4"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647"
- integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==
+core-js@^3.1.3, core-js@^3.8.3:
+ version "3.8.3"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0"
+ integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==
core-js@~2.3.0:
version "2.3.0"
@@ -3385,7 +3422,15 @@ cropper@^2.3.0:
dependencies:
jquery ">= 1.9.1"
-cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+cross-spawn@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+ integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI=
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -3396,15 +3441,7 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
- integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI=
- dependencies:
- lru-cache "^4.0.1"
- which "^1.2.9"
-
-cross-spawn@^7.0.0:
+cross-spawn@^7.0.0, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -3440,13 +3477,6 @@ crypto-random-string@^2.0.0:
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-crypto-random-string@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-3.0.1.tgz#29d7dc759d577a768afb3b7b2765dd9bd7ffe36a"
- integrity sha512-dUL0cJ4PBLanJGJQBHQUkvZ3C4q13MXzl54oRqAIiJGiNkOZ4JDwkg/SBo7daGghzlJv16yW1p/4lIQukmbedA==
- dependencies:
- type-fest "^0.5.2"
-
css-b64-images@~0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/css-b64-images/-/css-b64-images-0.2.5.tgz#42005d83204b2b4a5d93b6b1a5644133b5927a02"
@@ -3857,7 +3887,7 @@ debug@3.1.0, debug@~3.1.0:
dependencies:
ms "2.0.0"
-debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
+debug@^3.1.0, debug@^3.1.1, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -3921,7 +3951,7 @@ deep-extend@~0.5.1:
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f"
integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==
-deep-is@~0.1.3:
+deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
@@ -3951,7 +3981,7 @@ defer-to-connect@^1.0.1:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-define-properties@^1.1.2, define-properties@^1.1.3:
+define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
@@ -4205,9 +4235,9 @@ domutils@^1.5.1:
domelementtype "1"
dot-prop@^4.1.1:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
- integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4"
+ integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==
dependencies:
is-obj "^1.0.0"
@@ -4251,12 +4281,12 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
-echarts@^4.2.1:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/echarts/-/echarts-4.6.0.tgz#b5a47a1046cec93ceeef954f9ee54751340558ec"
- integrity sha512-xKkcr6v9UVOSF+PMuj7Ngt3bnzLwN1sSXWCvpvX+jYb3mePYsZnABq7wGkPac/m0nV653uGHXoHK8DCKCprdNg==
+echarts@^4.9.0:
+ version "4.9.0"
+ resolved "https://registry.yarnpkg.com/echarts/-/echarts-4.9.0.tgz#a9b9baa03f03a2a731e6340c55befb57a9e1347d"
+ integrity sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==
dependencies:
- zrender "4.2.0"
+ zrender "4.3.2"
editions@^1.3.3:
version "1.3.4"
@@ -4283,23 +4313,23 @@ ejs@^2.6.1:
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
-electron-to-chromium@^1.3.413:
- version "1.3.466"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.466.tgz#89f716db3afc4bb482ea2aaaa16c4808f89f762a"
- integrity sha512-eieqkoM2hCkZZRhETKyCouMziDV3l4XEKHRLuzcHG+HV+P7PeODU/z9HAmBgMQkzvHg2DoyQhfIDmmeguLZT/Q==
+electron-to-chromium@^1.3.634:
+ version "1.3.642"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz#8b884f50296c2ae2a9997f024d0e3e57facc2b94"
+ integrity sha512-cev+jOrz/Zm1i+Yh334Hed6lQVOkkemk2wRozfMF4MtTR7pxf3r3L5Rbd7uX1zMcEqVJ7alJBnJL7+JffkC6FQ==
elliptic@^6.0.0:
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
- integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+ integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
dependencies:
- bn.js "^4.4.0"
- brorand "^1.0.1"
+ bn.js "^4.11.9"
+ brorand "^1.1.0"
hash.js "^1.0.0"
- hmac-drbg "^1.0.0"
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
- minimalistic-crypto-utils "^1.0.0"
+ hmac-drbg "^1.0.1"
+ inherits "^2.0.4"
+ minimalistic-assert "^1.0.1"
+ minimalistic-crypto-utils "^1.0.1"
emittery@^0.7.1:
version "0.7.1"
@@ -4321,11 +4351,6 @@ emoji-unicode-version@^0.2.1:
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
integrity sha1-Dr82ZrVBQJeXHTSZTimfznXNuvw=
-emojis-list@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
- integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
-
emojis-list@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
@@ -4383,15 +4408,6 @@ engine.io@~3.2.0:
engine.io-parser "~2.1.0"
ws "~3.3.1"
-enhanced-resolve@4.1.0, enhanced-resolve@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
- integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==
- dependencies:
- graceful-fs "^4.1.2"
- memory-fs "^0.4.0"
- tapable "^1.0.0"
-
enhanced-resolve@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
@@ -4401,6 +4417,22 @@ enhanced-resolve@^0.9.1:
memory-fs "^0.2.0"
tapable "^0.1.8"
+enhanced-resolve@^4.1.1, 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==
+ dependencies:
+ graceful-fs "^4.1.2"
+ memory-fs "^0.5.0"
+ tapable "^1.0.0"
+
+enquirer@^2.3.5:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+ integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+ dependencies:
+ ansi-colors "^4.1.1"
+
ent@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
@@ -4437,22 +4469,25 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-es-abstract@^1.12.0, es-abstract@^1.17.0-next.1, es-abstract@^1.7.0:
- version "1.17.4"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184"
- integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==
+es-abstract@^1.18.0-next.1:
+ version "1.18.0-next.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2"
+ integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==
dependencies:
+ call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
has "^1.0.3"
has-symbols "^1.0.1"
- is-callable "^1.1.5"
- is-regex "^1.0.5"
- object-inspect "^1.7.0"
+ is-callable "^1.2.2"
+ is-negative-zero "^2.0.1"
+ is-regex "^1.1.1"
+ object-inspect "^1.9.0"
object-keys "^1.1.1"
- object.assign "^4.1.0"
- string.prototype.trimleft "^2.1.1"
- string.prototype.trimright "^2.1.1"
+ object.assign "^4.1.2"
+ string.prototype.trimend "^1.0.3"
+ string.prototype.trimstart "^1.0.3"
es-to-primitive@^1.2.1:
version "1.2.1"
@@ -4480,6 +4515,11 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
escape-goat@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
@@ -4500,11 +4540,6 @@ escape-string-regexp@^2.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
-escaper@^2.5.3:
- version "2.5.3"
- resolved "https://registry.yarnpkg.com/escaper/-/escaper-2.5.3.tgz#8b8fe90ba364054151ab7eff18b4ce43b1e13ab5"
- integrity sha512-QGb9sFxBVpbzMggrKTX0ry1oiI4CSDAl9vIL702hzl1jGW8VZs7qfqTRX7WDOjoNDoEVGcEtu1ZOQgReSfT2kQ==
-
escodegen@^1.14.1:
version "1.14.3"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
@@ -4517,14 +4552,14 @@ escodegen@^1.14.1:
optionalDependencies:
source-map "~0.6.1"
-eslint-config-airbnb-base@^14.0.0:
- version "14.0.0"
- resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz#8a7bcb9643d13c55df4dd7444f138bf4efa61e17"
- integrity sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==
+eslint-config-airbnb-base@^14.2.1:
+ version "14.2.1"
+ resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e"
+ integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==
dependencies:
- confusing-browser-globals "^1.0.7"
- object.assign "^4.1.0"
- object.entries "^1.1.0"
+ confusing-browser-globals "^1.0.10"
+ object.assign "^4.1.2"
+ object.entries "^1.1.2"
eslint-config-prettier@^6.10.0:
version "6.10.0"
@@ -4533,27 +4568,26 @@ eslint-config-prettier@^6.10.0:
dependencies:
get-stdin "^6.0.0"
-eslint-import-resolver-jest@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-jest/-/eslint-import-resolver-jest-2.1.2.tgz#8720fbe8b8498e95cb2bc6ef52b46b713aedaa59"
- integrity sha512-gKEHNW02XGzbj6nr6xPwI5bsUgAXFsJZZQwqRJQV8Xw2XJe6pxd1cvo9bCVCwx3xolvmQ4eWcw8Xlf8UICX41A==
+eslint-import-resolver-jest@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-jest/-/eslint-import-resolver-jest-3.0.0.tgz#fd61da30fe58f4c1074af1f069b4267c70a91fd6"
+ integrity sha512-dCrepGDfaI5cK1QeUhUSbrkDalFkFGXyvjsfWyDxg1uPWiwsGpGmK6GFVPS4mn/IAYLipquB9AHonGQP/iaOAQ==
dependencies:
- find-root "^1.0.0"
- micromatch "^3.1.6"
- resolve "^1.5.0"
+ find-root "^1.1.0"
+ resolve "^1.12.0"
-eslint-import-resolver-node@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
- integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==
+eslint-import-resolver-node@^0.3.4:
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
+ integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==
dependencies:
debug "^2.6.9"
- resolve "^1.5.0"
+ resolve "^1.13.1"
-eslint-import-resolver-webpack@^0.12.1:
- version "0.12.1"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.12.1.tgz#771ae561e887ca4e53ee87605fbb36c5e290b0f5"
- integrity sha512-O/sUAXk6GWrICiN8JUkkjdt9uZpqZHP+FVnTxtEILL6EZMaPSrnP4lGPSFwcKsv7O211maqq4Nz60+dh236hVg==
+eslint-import-resolver-webpack@0.13.0:
+ version "0.13.0"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.0.tgz#5cb19cf4b6996c8a2514aeb10f909e2c70488dc3"
+ integrity sha512-hZWGcmjaJZK/WSCYGI/y4+FMGQZT+cwW/1E/P4rDwFj2PbanlQHISViw4ccDJ+2wxAqjgwBfxwy3seABbVKDEw==
dependencies:
array-find "^1.0.0"
debug "^2.6.9"
@@ -4566,10 +4600,10 @@ eslint-import-resolver-webpack@^0.12.1:
resolve "^1.13.1"
semver "^5.7.1"
-eslint-module-utils@^2.4.1:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz#7878f7504824e1b857dd2505b59a8e5eda26a708"
- integrity sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==
+eslint-module-utils@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6"
+ integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==
dependencies:
debug "^2.6.9"
pkg-dir "^2.0.0"
@@ -4591,28 +4625,29 @@ eslint-plugin-filenames@^1.3.2:
lodash.snakecase "4.1.1"
lodash.upperfirst "4.3.1"
-eslint-plugin-import@^2.20.1:
- version "2.20.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3"
- integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==
+eslint-plugin-import@^2.22.1:
+ version "2.22.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
+ integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==
dependencies:
- array-includes "^3.0.3"
- array.prototype.flat "^1.2.1"
+ array-includes "^3.1.1"
+ array.prototype.flat "^1.2.3"
contains-path "^0.1.0"
debug "^2.6.9"
doctrine "1.5.0"
- eslint-import-resolver-node "^0.3.2"
- eslint-module-utils "^2.4.1"
+ eslint-import-resolver-node "^0.3.4"
+ eslint-module-utils "^2.6.0"
has "^1.0.3"
minimatch "^3.0.4"
- object.values "^1.1.0"
+ object.values "^1.1.1"
read-pkg-up "^2.0.0"
- resolve "^1.12.0"
+ resolve "^1.17.0"
+ tsconfig-paths "^3.9.0"
-eslint-plugin-jasmine@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-4.1.0.tgz#4f6d41b1a8622348c97559cbcd29badffa74dbfa"
- integrity sha512-Vfuk2Sm1ULR7MqGjVIOOEdQWyoFBfSwvwUeo9MrajVGJB3C24c9Mmj1Cgf8Qwmf3aS2bezPt1sckpKXWpd74Dw==
+eslint-plugin-jasmine@4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-4.1.2.tgz#50cc20d603b02b37727f8d174d4b83b9b8ef25a5"
+ integrity sha512-Jr52EBi6Ql5WVDvRCKBID9kRD6/CaObvCWmgHpqobczX2Mzt8/QMu9vpgx6q/O5jyQ9CIGrKaEbPuEfHRf8guw==
eslint-plugin-jest@^23.8.2:
version "23.8.2"
@@ -4621,25 +4656,25 @@ eslint-plugin-jest@^23.8.2:
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
-eslint-plugin-no-jquery@^2.3.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.3.1.tgz#1c364cb863a38cc1570c8020155b6004cca62178"
- integrity sha512-/fiQUBSOMUETnfBuiK5ewvtRbek1IRTy5ov/6RZ6nlybvZ337vyGaNPWM1KgaIoIeN7dairNrPfq0h7A0tpT3A==
+eslint-plugin-no-jquery@2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.5.0.tgz#6c12e3aae172bfd3363b7ac8c3f3e944704867f4"
+ integrity sha512-RrQ380mUJJKdjgpQ/tZAJ3B3W1n3LbVmULooS2Pv5pUDcc5uVHVSJMTdUlsbvQyfo6hWP2LJ4FbOoDzENWcF7A==
eslint-plugin-promise@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a"
integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==
-eslint-plugin-vue@^7.4.1:
- version "7.4.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.4.1.tgz#2526ef0c010c218824a89423dbe6ddbe76f04fd6"
- integrity sha512-W/xPNHYIkGJphLUM2UIYYGKbRw3BcDoMIPY9lu1TTa2YLiZoxurddfnmOP+UOVywxb5vi438ejzwvKdZqydtIw==
+eslint-plugin-vue@^7.5.0:
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.5.0.tgz#cc6d983eb22781fa2440a7573cf39af439bb5725"
+ integrity sha512-QnMMTcyV8PLxBz7QQNAwISSEs6LYk2LJvGlxalXvpCtfKnqo7qcY0aZTIxPe8QOnHd7WCwiMZLOJzg6A03T0Gw==
dependencies:
eslint-utils "^2.1.0"
natural-compare "^1.4.0"
semver "^7.3.2"
- vue-eslint-parser "^7.3.0"
+ vue-eslint-parser "^7.4.1"
eslint-rule-composer@^0.3.0:
version "0.3.0"
@@ -4654,21 +4689,14 @@ eslint-scope@^4.0.3:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-scope@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
- integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==
+eslint-scope@^5.0.0, eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
dependencies:
- esrecurse "^4.1.0"
+ esrecurse "^4.3.0"
estraverse "^4.1.1"
-eslint-utils@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
- integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
- dependencies:
- eslint-visitor-keys "^1.1.0"
-
eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
@@ -4676,55 +4704,60 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0:
dependencies:
eslint-visitor-keys "^1.1.0"
-eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
- integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
+eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+ integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
-eslint@^6.8.0:
- version "6.8.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
- integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
+eslint-visitor-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
+ integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+
+eslint@7.19.0:
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.19.0.tgz#6719621b196b5fad72e43387981314e5d0dc3f41"
+ integrity sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg==
dependencies:
"@babel/code-frame" "^7.0.0"
+ "@eslint/eslintrc" "^0.3.0"
ajv "^6.10.0"
- chalk "^2.1.0"
- cross-spawn "^6.0.5"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
- eslint-scope "^5.0.0"
- eslint-utils "^1.4.3"
- eslint-visitor-keys "^1.1.0"
- espree "^6.1.2"
- esquery "^1.0.1"
+ enquirer "^2.3.5"
+ eslint-scope "^5.1.1"
+ eslint-utils "^2.1.0"
+ eslint-visitor-keys "^2.0.0"
+ espree "^7.3.1"
+ esquery "^1.2.0"
esutils "^2.0.2"
- file-entry-cache "^5.0.1"
+ file-entry-cache "^6.0.0"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
- inquirer "^7.0.0"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
- levn "^0.3.0"
- lodash "^4.17.14"
+ levn "^0.4.1"
+ lodash "^4.17.20"
minimatch "^3.0.4"
- mkdirp "^0.5.1"
natural-compare "^1.4.0"
- optionator "^0.8.3"
+ optionator "^0.9.1"
progress "^2.0.0"
- regexpp "^2.0.1"
- semver "^6.1.2"
- strip-ansi "^5.2.0"
- strip-json-comments "^3.0.1"
- table "^5.2.3"
+ regexpp "^3.1.0"
+ semver "^7.2.1"
+ strip-ansi "^6.0.0"
+ strip-json-comments "^3.1.0"
+ table "^6.0.4"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-espree@^6.1.2, espree@^6.2.1:
+espree@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
@@ -4733,30 +4766,44 @@ espree@^6.1.2, espree@^6.2.1:
acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.1.0"
+espree@^7.3.0, espree@^7.3.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
+ integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
+ dependencies:
+ acorn "^7.4.0"
+ acorn-jsx "^5.3.1"
+ eslint-visitor-keys "^1.3.0"
+
esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esquery@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
- integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==
+esquery@^1.0.1, esquery@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57"
+ integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
dependencies:
- estraverse "^4.0.0"
+ estraverse "^5.1.0"
-esrecurse@^4.1.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
- integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==
+esrecurse@^4.1.0, esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
dependencies:
- estraverse "^4.1.0"
+ estraverse "^5.2.0"
-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.1.1, estraverse@^4.2.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+estraverse@^5.1.0, estraverse@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
+ integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
+
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -4943,15 +4990,6 @@ extend@^3.0.0, extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-external-editor@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
- integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
- dependencies:
- chardet "^0.7.0"
- iconv-lite "^0.4.24"
- tmp "^0.0.33"
-
extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@@ -5010,7 +5048,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-fast-levenshtein@~2.0.6:
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
@@ -5027,17 +5065,10 @@ fault@^1.0.2:
dependencies:
format "^0.2.2"
-faye-websocket@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
- integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=
- dependencies:
- websocket-driver ">=0.5.1"
-
-faye-websocket@~0.11.1:
- version "0.11.1"
- resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38"
- integrity sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=
+faye-websocket@^0.11.3:
+ version "0.11.3"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
+ integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
dependencies:
websocket-driver ">=0.5.1"
@@ -5053,13 +5084,6 @@ figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
-figures@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
- integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
- dependencies:
- escape-string-regexp "^1.0.5"
-
file-entry-cache@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
@@ -5067,6 +5091,13 @@ file-entry-cache@^5.0.1:
dependencies:
flat-cache "^2.0.1"
+file-entry-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a"
+ integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==
+ dependencies:
+ flat-cache "^3.0.4"
+
file-loader@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-5.1.0.tgz#cb56c070efc0e40666424309bd0d9e45ac6f2bb8"
@@ -5131,7 +5162,7 @@ finalhandler@~1.1.2:
statuses "~1.5.0"
unpipe "~1.0.0"
-find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
+find-cache-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
@@ -5140,16 +5171,16 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
make-dir "^2.0.0"
pkg-dir "^3.0.0"
-find-cache-dir@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.0.0.tgz#cd4b7dd97b7185b7e17dbfe2d6e4115ee3eeb8fc"
- integrity sha512-t7ulV1fmbxh5G9l/492O1p5+EBbr3uwpt6odhFTMc+nWyhmbloe+ja9BZ8pIBtqFWhOmCWVjx+pTW4zDkFoclw==
+find-cache-dir@^3.0.0, find-cache-dir@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880"
+ integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==
dependencies:
commondir "^1.0.1"
- make-dir "^3.0.0"
+ make-dir "^3.0.2"
pkg-dir "^4.1.0"
-find-root@^1.0.0, find-root@^1.1.0:
+find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
@@ -5184,7 +5215,7 @@ 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:
+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==
@@ -5203,11 +5234,24 @@ flat-cache@^2.0.1:
rimraf "2.6.3"
write "1.0.3"
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ dependencies:
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
+
flatted@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916"
integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==
+flatted@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
+ integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
+
flush-write-stream@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
@@ -5221,11 +5265,6 @@ follow-redirects@^1.0.0, follow-redirects@^1.10.0:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
-font-awesome@4.7.0:
- version "4.7.0"
- resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
- integrity sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=
-
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -5362,16 +5401,20 @@ gensync@^1.0.0-beta.1:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==
-get-caller-file@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
- integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
-
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+get-intrinsic@^1.0.1, get-intrinsic@^1.0.2:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
+ integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.1"
+
get-package-type@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
@@ -5423,27 +5466,25 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
-gettext-extractor-vue@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/gettext-extractor-vue/-/gettext-extractor-vue-4.0.2.tgz#16e1cdbdaf37e5bdf3cb0aff63685bdc5e74e906"
- integrity sha512-tnTAU1TdQFREv4Q4hfBDuB329eugeFsYmV7lE9U1jkZEyxcf4oPgimLHNZVNaEUg4+JJwhB8B9HIeqbcbSW32g==
+gettext-extractor-vue@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/gettext-extractor-vue/-/gettext-extractor-vue-5.0.0.tgz#dc463868d49e14097c4545c8ed4851d8d3edd6dd"
+ integrity sha512-OSuEJlOexxkjYQL2SGf385oWIiy4weWMfUp/ZlOWzMSz0a+HB/Hlv0S4KFTz4A4GuOp3gu15qwXl61GQJ/u+1w==
dependencies:
- bluebird "^3.5.1"
- glob "^7.1.2"
- vue-template-compiler "^2.5.20"
+ glob "^7.1.6"
-gettext-extractor@^3.4.3:
- version "3.4.3"
- resolved "https://registry.yarnpkg.com/gettext-extractor/-/gettext-extractor-3.4.3.tgz#882679cefc71888eb6e69297e6b2dc14c0384fef"
- integrity sha512-YSNdTCHmzm58Rc21thtXj7jRIOlqINftM3XbtvNK28C88i35EnEB89iOeV9Vetv7wcb/wiPAtcq/6iSnt2pMyw==
+gettext-extractor@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/gettext-extractor/-/gettext-extractor-3.5.3.tgz#6ed46931c154a7485a80fa8b91b835ff7b8d0411"
+ integrity sha512-9EgJ+hmbtAbATdMIvCj4WnrkeDWH6fv1z+IJJ1XCxdcUMGx6JQdVVFTdzJkSyIHh4td53ngoB5EQbavbKJU9Og==
dependencies:
"@types/glob" "5 - 7"
"@types/parse5" "^5"
css-selector-parser "^1.3"
glob "5 - 7"
- parse5 "^5"
- pofile "^1"
- typescript "2 - 3"
+ parse5 "5 - 6"
+ pofile "1.0.x"
+ typescript "2 - 4"
glob-parent@^3.1.0:
version "3.1.0"
@@ -5489,13 +5530,6 @@ global-dirs@^2.0.1:
dependencies:
ini "^1.3.5"
-global-modules@2.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"
- integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
- dependencies:
- global-prefix "^3.0.0"
-
global-modules@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
@@ -5505,6 +5539,13 @@ global-modules@^1.0.0:
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"
+ integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
+ 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"
@@ -5627,7 +5668,7 @@ 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.6, graceful-fs@^4.1.9, graceful-fs@^4.2.2, graceful-fs@^4.2.4:
+graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
@@ -5816,7 +5857,7 @@ highlight.js@^9.13.1, highlight.js@~9.13.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
-hmac-drbg@^1.0.0:
+hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
@@ -5859,10 +5900,10 @@ html-encoding-sniffer@^2.0.1:
dependencies:
whatwg-encoding "^1.0.5"
-html-entities@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
- integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=
+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-escaper@^2.0.0:
version "2.0.0"
@@ -5930,6 +5971,11 @@ http-errors@~1.6.2:
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
+http-parser-js@>=0.5.1:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
+ integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
+
http-proxy-agent@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
@@ -5949,9 +5995,9 @@ http-proxy-middleware@0.19.1:
micromatch "^3.1.10"
http-proxy@^1.13.0, http-proxy@^1.17.0:
- version "1.18.0"
- resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
- integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
+ 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==
dependencies:
eventemitter3 "^4.0.0"
follow-redirects "^1.0.0"
@@ -5984,7 +6030,7 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
-iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24:
+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"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -6051,10 +6097,10 @@ import-fresh@^2.0.0:
caller-path "^2.0.0"
resolve-from "^3.0.0"
-import-fresh@^3.0.0:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66"
- integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==
+import-fresh@^3.0.0, import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
@@ -6069,7 +6115,7 @@ 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, import-local@^2.0.0:
+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==
@@ -6085,14 +6131,6 @@ import-local@^3.0.2:
pkg-dir "^4.2.0"
resolve-cwd "^3.0.0"
-imports-loader@^0.8.0:
- version "0.8.0"
- resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.8.0.tgz#030ea51b8ca05977c40a3abfd9b4088fe0be9a69"
- integrity sha512-kXWL7Scp8KQ4552ZcdVTeaQCZSLW+e6nJfp3cwUMB673T7Hr98Xjx5JK+ql7ADlJUvj1JS5O01RLbKoutN5QDQ==
- dependencies:
- loader-utils "^1.0.2"
- source-map "^0.6.1"
-
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -6148,39 +6186,25 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
-ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
- integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-inquirer@^7.0.0:
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703"
- integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==
- dependencies:
- ansi-escapes "^4.2.1"
- chalk "^2.4.2"
- cli-cursor "^3.1.0"
- cli-width "^2.0.0"
- external-editor "^3.0.3"
- figures "^3.0.0"
- lodash "^4.17.15"
- mute-stream "0.0.8"
- run-async "^2.2.0"
- rxjs "^6.5.3"
- string-width "^4.1.0"
- strip-ansi "^5.1.0"
- through "^2.3.6"
+ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
+ version "1.3.8"
+ 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"
@@ -6190,10 +6214,10 @@ internal-ip@^4.3.0:
default-gateway "^4.2.0"
ipaddr.js "^1.9.0"
-interpret@1.2.0, interpret@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
- integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
+interpret@^1.2.0, interpret@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
+ integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
@@ -6202,11 +6226,6 @@ invariant@^2.2.2, invariant@^2.2.4:
dependencies:
loose-envify "^1.0.0"
-invert-kv@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
- integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
-
ip-regex@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
@@ -6286,10 +6305,10 @@ is-buffer@^2.0.0:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
-is-callable@^1.1.4, is-callable@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
- integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
+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"
+ integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
is-ci@^2.0.0:
version "2.0.0"
@@ -6421,6 +6440,11 @@ is-installed-globally@^0.3.1:
global-dirs "^2.0.1"
is-path-inside "^3.0.1"
+is-negative-zero@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
+ integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
+
is-npm@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
@@ -6489,22 +6513,13 @@ is-potential-custom-element-name@^1.0.0:
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
-is-promise@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
- integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
-
-is-regex@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
- integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==
+is-regex@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251"
+ integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==
dependencies:
- has "^1.0.3"
-
-is-regexp@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
- integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
+ call-bind "^1.0.2"
+ has-symbols "^1.0.1"
is-regexp@^2.0.0:
version "2.1.0"
@@ -6521,6 +6536,11 @@ is-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
+is-string@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
+ integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
+
is-symbol@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
@@ -7320,6 +7340,11 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -7335,10 +7360,10 @@ 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.2:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
- integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
+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@2.x, json5@^2.1.2:
version "2.1.3"
@@ -7500,6 +7525,11 @@ keyv@^3.0.0:
dependencies:
json-buffer "3.0.0"
+khroma@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/khroma/-/khroma-1.2.0.tgz#46dcc9d7533923c228b51724db108f11fec108d8"
+ integrity sha512-DlKk5y243dujy8fOH02aRnnewLfiHJV0s8aXaVrCohgBf3s7fEAn6gc6LLQ21agODlFZS8ufrn+juu70uCA9Tw==
+
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -7525,9 +7555,9 @@ kind-of@^5.0.0:
integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
kind-of@^6.0.0, kind-of@^6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
- integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
klaw@~2.0.0:
version "2.0.0"
@@ -7553,13 +7583,6 @@ latest-version@^5.0.0:
dependencies:
package-json "^6.3.0"
-lcid@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
- integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
- dependencies:
- invert-kv "^2.0.0"
-
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -7572,7 +7595,15 @@ levenary@^1.1.1:
dependencies:
leven "^3.1.0"
-levn@^0.3.0, levn@~0.3.0:
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+levn@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
@@ -7647,15 +7678,6 @@ loader-runner@^2.4.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
-loader-utils@1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
- integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
- dependencies:
- big.js "^5.2.2"
- emojis-list "^2.0.0"
- json5 "^1.0.1"
-
loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
@@ -7867,10 +7889,10 @@ log4js@^4.0.0:
rfdc "^1.1.4"
streamroller "^1.0.6"
-loglevel@^1.6.6:
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.7.tgz#b3e034233188c68b889f5b862415306f565e2c56"
- integrity sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==
+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.1:
version "2.0.2"
@@ -7930,6 +7952,13 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
lz-string@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
@@ -7943,10 +7972,10 @@ make-dir@^2.0.0, make-dir@^2.1.0:
pify "^4.0.1"
semver "^5.6.0"
-make-dir@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801"
- integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==
+make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
+ integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
dependencies:
semver "^6.0.0"
@@ -7962,18 +7991,6 @@ makeerror@1.0.x:
dependencies:
tmpl "1.0.x"
-mamacro@^0.0.3:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4"
- integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==
-
-map-age-cleaner@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
- integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
- dependencies:
- p-defer "^1.0.0"
-
map-cache@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@@ -8109,21 +8126,12 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-mem@^4.0.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
- integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
- dependencies:
- map-age-cleaner "^0.1.1"
- mimic-fn "^2.0.0"
- p-is-promise "^2.0.0"
-
memory-fs@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
integrity sha1-8rslNovBIeORwlIN6Slpyu4KApA=
-memory-fs@^0.4.0, memory-fs@^0.4.1:
+memory-fs@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=
@@ -8131,6 +8139,14 @@ memory-fs@^0.4.0, memory-fs@^0.4.1:
errno "^0.1.3"
readable-stream "^2.0.1"
+memory-fs@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
+ integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
+ dependencies:
+ errno "^0.1.3"
+ readable-stream "^2.0.1"
+
meow@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
@@ -8184,29 +8200,29 @@ merge2@^1.2.3:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5"
integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==
-mermaid@^8.5.2:
- version "8.5.2"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.5.2.tgz#0f1914cda53d4ea5377380e5ce07a38bef2ea7e8"
- integrity sha512-I+s+8/RzlazF3dGOhDUfU/ERkUV4zfIlTWb3703jNx+2lfACs+4AdY9ULQaw6BPWzW3gB+XlXFOOX/m/vqujIA==
+mermaid@^8.9.0:
+ version "8.9.0"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.9.0.tgz#e569517863ab903aa5389cd746b68ca958a8ca7c"
+ integrity sha512-J582tyE1vkdNu4BGgfwXnFo4Mu6jpuc4uK96mIenavaak9kr4T5gaMmYCo/7edwq/vTBkx/soZ5LcJo5WXZ1BQ==
dependencies:
"@braintree/sanitize-url" "^3.1.0"
- crypto-random-string "^3.0.1"
d3 "^5.7.0"
dagre "^0.8.4"
dagre-d3 "^0.6.4"
entity-decode "^2.0.2"
graphlib "^2.1.7"
he "^1.2.0"
+ khroma "^1.1.0"
minify "^4.1.1"
moment-mini "^2.22.1"
- scope-css "^1.2.1"
+ stylis "^3.5.2"
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.6:
+micromatch@^3.0.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==
@@ -8263,7 +8279,7 @@ mime@^2.3.1, mime@^2.4.4:
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
-mimic-fn@^2.0.0, mimic-fn@^2.1.0:
+mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
@@ -8293,12 +8309,12 @@ minify@^4.1.1:
try-catch "^2.0.0"
try-to-catch "^1.0.2"
-minimalistic-assert@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
- integrity sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
-minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+minimalistic-crypto-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
@@ -8318,11 +8334,6 @@ minimist-options@^3.0.1:
arrify "^1.0.1"
is-plain-obj "^1.1.0"
-minimist@0.0.8, minimist@~0.0.1:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
- integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-
minimist@1.1.x:
version "1.1.3"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
@@ -8333,6 +8344,11 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+minimist@~0.0.1:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+ integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
+
minipass-collect@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
@@ -8361,6 +8377,14 @@ minipass@^3.0.0, minipass@^3.1.1:
dependencies:
yallist "^4.0.0"
+minizlib@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
+ integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
+ dependencies:
+ minipass "^3.0.0"
+ yallist "^4.0.0"
+
miragejs@^0.1.40:
version "0.1.40"
resolved "https://registry.yarnpkg.com/miragejs/-/miragejs-0.1.40.tgz#5bcba7634312c012748ae7f294e1516b74b37182"
@@ -8417,17 +8441,17 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
-mkdirp@1.x, mkdirp@^1.0.4, mkdirp@~1.0.3:
+mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
- version "0.5.1"
- resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
- integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
+"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
+ integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
- minimist "0.0.8"
+ minimist "^1.2.5"
mock-apollo-client@^0.5.0:
version "0.5.0"
@@ -8498,11 +8522,6 @@ multicast-dns@^6.0.1:
dns-packet "^1.0.1"
thunky "^0.1.0"
-mute-stream@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
- integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
-
nan@^2.13.2:
version "2.14.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
@@ -8558,14 +8577,14 @@ node-ensure@^0.0.0:
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
node-fetch@^2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
- integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
+ integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
-node-forge@0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
- integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
+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-gyp@^3.8.0:
version "3.8.0"
@@ -8636,10 +8655,10 @@ node-notifier@^8.0.0:
uuid "^8.3.0"
which "^2.0.2"
-node-releases@^1.1.53:
- version "1.1.58"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.58.tgz#8ee20eef30fa60e52755fcc0942def5a734fe935"
- integrity sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg==
+node-releases@^1.1.69:
+ version "1.1.70"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08"
+ integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==
node-sass@^4.14.1:
version "4.14.1"
@@ -8802,12 +8821,12 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
-object-inspect@^1.7.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
- integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
+object-inspect@^1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
+ integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
-object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
+object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@@ -8819,24 +8838,24 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
-object.assign@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
- integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
+object.assign@^4.1.0, object.assign@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
+ integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
dependencies:
- define-properties "^1.1.2"
- function-bind "^1.1.1"
- has-symbols "^1.0.0"
- object-keys "^1.0.11"
+ call-bind "^1.0.0"
+ define-properties "^1.1.3"
+ has-symbols "^1.0.1"
+ object-keys "^1.1.1"
-object.entries@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b"
- integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==
+object.entries@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6"
+ integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- function-bind "^1.1.1"
+ es-abstract "^1.18.0-next.1"
has "^1.0.3"
object.pick@^1.3.0:
@@ -8846,14 +8865,14 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-object.values@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9"
- integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==
+object.values@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731"
+ integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- es-abstract "^1.12.0"
- function-bind "^1.1.1"
+ es-abstract "^1.18.0-next.1"
has "^1.0.3"
obuf@^1.0.0, obuf@^1.1.2:
@@ -8914,7 +8933,7 @@ optimist@^0.6.1:
minimist "~0.0.1"
wordwrap "~0.0.2"
-optionator@^0.8.1, optionator@^0.8.3:
+optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@@ -8926,6 +8945,18 @@ optionator@^0.8.1, optionator@^0.8.3:
type-check "~0.3.2"
word-wrap "~1.2.3"
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.3"
+
orderedmap@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.0.0.tgz#d90fc2ba1ed085190907d601dec6e6a53f8d41ba"
@@ -8948,15 +8979,6 @@ os-homedir@^1.0.0:
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-os-locale@^3.0.0, os-locale@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
- integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
- dependencies:
- execa "^1.0.0"
- lcid "^2.0.0"
- mem "^4.0.0"
-
os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
@@ -8975,11 +8997,6 @@ p-cancelable@^1.0.0:
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
-p-defer@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
- integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
-
p-each-series@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48"
@@ -8990,11 +9007,6 @@ p-finally@^1.0.0:
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
-p-is-promise@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
- integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
-
p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
@@ -9035,10 +9047,10 @@ p-map@^2.0.0:
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
-p-map@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d"
- integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==
+p-map@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
dependencies:
aggregate-error "^3.0.0"
@@ -9157,7 +9169,7 @@ parse-passwd@^1.0.0:
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
-parse5@5.1.1, parse5@^5:
+"parse5@5 - 6", parse5@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
@@ -9334,13 +9346,6 @@ pirates@^4.0.1:
dependencies:
node-modules-regexp "^1.0.0"
-pixelmatch@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854"
- integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=
- dependencies:
- pngjs "^3.0.0"
-
pkg-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
@@ -9362,19 +9367,7 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
-pkg-up@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
- integrity sha1-yBmscoBZpGHKscOImivjxJoATX8=
- dependencies:
- find-up "^2.1.0"
-
-pngjs@^3.0.0:
- version "3.3.3"
- resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b"
- integrity sha512-1n3Z4p3IOxArEs1VRXnZ/RXdfEniAUS9jb68g58FIXMNkPJeZd+Qh4Uq7/e0LVxAQGos1eIUrqrt4FpjdnEd+Q==
-
-pofile@^1:
+pofile@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
integrity sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg==
@@ -9389,14 +9382,14 @@ 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.25:
- version "1.0.25"
- resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
- integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==
+portfinder@^1.0.26:
+ version "1.0.28"
+ resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
+ integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==
dependencies:
async "^2.6.2"
debug "^3.1.1"
- mkdirp "^0.5.1"
+ mkdirp "^0.5.5"
posix-character-classes@^0.1.0:
version "0.1.1"
@@ -9548,6 +9541,11 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2
source-map "^0.6.1"
supports-color "^6.1.0"
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -9882,20 +9880,20 @@ querystring@0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
-querystringify@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef"
- integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==
+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==
quick-lru@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
-randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80"
- integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==
+randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
dependencies:
safe-buffer "^5.1.0"
@@ -9929,13 +9927,13 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
-raw-loader@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.0.tgz#d639c40fb9d72b5c7f8abc1fb2ddb25b29d3d540"
- integrity sha512-iINUOYvl1cGEmfoaLjnZXt4bKfT2LJnZZib5N/LLyAphC+Dd11vNP9CNVb38j+SAJpFI1uo8j9frmih53ASy7Q==
+raw-loader@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6"
+ integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==
dependencies:
- loader-utils "^1.2.3"
- schema-utils "^2.5.0"
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
rc@^1.2.8, rc@~1.2.7:
version "1.2.8"
@@ -10120,10 +10118,10 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
-regexpp@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
- integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
+regexpp@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
+ integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
regexpu-core@^4.7.0:
version "4.7.0"
@@ -10301,10 +10299,10 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
-require-main-filename@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
- integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
require-main-filename@^2.0.0:
version "2.0.0"
@@ -10375,7 +10373,7 @@ 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.3.2, resolve@^1.5.0:
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2:
version "1.17.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
@@ -10389,14 +10387,6 @@ responselike@^1.0.2:
dependencies:
lowercase-keys "^1.0.0"
-restore-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
- integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
- dependencies:
- onetime "^5.1.0"
- signal-exit "^3.0.2"
-
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
@@ -10412,21 +10402,14 @@ rfdc@^1.1.4:
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-rimraf@2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.3, rimraf@^2.7.1:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
- integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
- dependencies:
- glob "^7.1.3"
-
-rimraf@2.6.3:
+rimraf@2, rimraf@2.6.3, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
dependencies:
glob "^7.1.3"
-rimraf@^3.0.0:
+rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
@@ -10456,13 +10439,6 @@ rsvp@^4.8.4:
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.4.tgz#b50e6b34583f3dd89329a2f23a8a2be072845911"
integrity sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==
-run-async@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
- integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA=
- dependencies:
- is-promise "^2.1.0"
-
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
@@ -10475,14 +10451,7 @@ rw@1:
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
-rxjs@^6.5.3:
- version "6.5.4"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
- integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
- dependencies:
- tslib "^1.9.0"
-
-safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@5.1.2, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
@@ -10553,7 +10522,7 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.7.0:
+schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0:
version "2.7.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
@@ -10562,14 +10531,14 @@ schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.7
ajv "^6.12.4"
ajv-keywords "^3.5.2"
-scope-css@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/scope-css/-/scope-css-1.2.1.tgz#c35768bc900cad030a3e0d663a818c0f6a57f40e"
- integrity sha512-UjLRmyEYaDNiOS673xlVkZFlVCtckJR/dKgr434VMm7Lb+AOOqXKdAcY7PpGlJYErjXXJzKN7HWo4uRPiZZG0Q==
+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==
dependencies:
- escaper "^2.5.3"
- slugify "^1.3.1"
- strip-css-comments "^3.0.0"
+ "@types/json-schema" "^7.0.6"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
scss-tokenizer@^0.2.3:
version "0.2.3"
@@ -10594,12 +10563,12 @@ select@^1.1.2:
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
-selfsigned@^1.10.7:
- version "1.10.7"
- resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b"
- integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==
+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==
dependencies:
- node-forge "0.9.0"
+ node-forge "^0.10.0"
semver-diff@^3.1.1:
version "3.1.1"
@@ -10618,12 +10587,14 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
-semver@7.x, semver@^7.3.2:
- version "7.3.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
- integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
+semver@7.x, semver@^7.2.1, semver@^7.3.2:
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
+ integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
+ dependencies:
+ lru-cache "^6.0.0"
-semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
+semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -10657,6 +10628,13 @@ serialize-javascript@^2.1.0, serialize-javascript@^2.1.2:
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
+serialize-javascript@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
+ integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
+ dependencies:
+ randombytes "^2.1.0"
+
serve-index@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
@@ -10793,10 +10771,14 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"
-slugify@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.1.tgz#f572127e8535329fbc6c1edb74ab856b61ad7de2"
- integrity sha512-6BwyhjF5tG5P8s+0DPNyJmBSBePG6iMyhjvIW5zGdA3tFik9PtK+yNkZgTeiroCRGZYgkHftFA62tGVK1EI9Kw==
+slice-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
+ integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
+ dependencies:
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
smooshpack@^0.0.62:
version "0.0.62"
@@ -10883,25 +10865,26 @@ socket.io@2.1.1:
socket.io-client "2.1.1"
socket.io-parser "~3.2.0"
-sockjs-client@1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5"
- integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==
+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.5"
+ debug "^3.2.6"
eventsource "^1.0.7"
- faye-websocket "~0.11.1"
- inherits "^2.0.3"
- json3 "^3.3.2"
- url-parse "^1.4.3"
+ faye-websocket "^0.11.3"
+ inherits "^2.0.4"
+ json3 "^3.3.3"
+ url-parse "^1.4.7"
-sockjs@0.3.19:
- version "0.3.19"
- resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d"
- integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==
+sockjs@^0.3.21:
+ version "0.3.21"
+ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417"
+ integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==
dependencies:
- faye-websocket "^0.10.0"
- uuid "^3.0.1"
+ faye-websocket "^0.11.3"
+ uuid "^3.4.0"
+ websocket-driver "^0.7.4"
sortablejs@^1.10.2, sortablejs@^1.9.0:
version "1.10.2"
@@ -11002,10 +10985,10 @@ spdy-transport@^3.0.0:
readable-stream "^3.0.6"
wbuf "^1.7.3"
-spdy@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2"
- integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==
+spdy@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
+ integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
dependencies:
debug "^4.1.0"
handle-thing "^2.0.0"
@@ -11057,12 +11040,11 @@ ssri@^6.0.1:
dependencies:
figgy-pudding "^3.5.1"
-ssri@^7.0.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d"
- integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==
+ssri@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808"
+ integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==
dependencies:
- figgy-pudding "^3.5.1"
minipass "^3.1.1"
stack-utils@^2.0.2:
@@ -11107,11 +11089,6 @@ stealthy-require@^1.1.1:
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
-stickyfilljs@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/stickyfilljs/-/stickyfilljs-2.1.0.tgz#46dabb599d8275d185bdb97db597f86a2e3afa7b"
- integrity sha512-LkG0BXArL5HbW2O09IAXfnBQfpScgGqJuUDUrI3Ire5YKjRz/EhakIZEJogHwgXeQ4qnTicM9sK9uYfWN11qKg==
-
stream-browserify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
@@ -11168,7 +11145,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-string-width@^1.0.1:
+string-width@^1.0.1, "string-width@^1.0.2 || 2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
@@ -11177,14 +11154,6 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
string-width@^3.0.0, string-width@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
@@ -11203,21 +11172,21 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
-string.prototype.trimleft@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74"
- integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==
+string.prototype.trimend@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b"
+ integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- function-bind "^1.1.1"
-string.prototype.trimright@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9"
- integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==
+string.prototype.trimstart@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa"
+ integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- function-bind "^1.1.1"
string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@~1.1.1:
version "1.1.1"
@@ -11286,13 +11255,6 @@ strip-bom@^4.0.0:
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
-strip-css-comments@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-css-comments/-/strip-css-comments-3.0.0.tgz#7a5625eff8a2b226cf8947a11254da96e13dae89"
- integrity sha1-elYl7/iisibPiUehElTaluE9rok=
- dependencies:
- is-regexp "^1.0.0"
-
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -11315,10 +11277,10 @@ strip-indent@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
-strip-json-comments@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
- integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
+strip-json-comments@^3.1.0, 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==
strip-json-comments@~2.0.1:
version "2.0.1"
@@ -11408,6 +11370,11 @@ stylelint@^10.1.0:
svg-tags "^1.0.0"
table "^5.2.3"
+stylis@^3.5.2:
+ version "3.5.4"
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
+ integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
+
sugarss@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d"
@@ -11415,13 +11382,6 @@ sugarss@^2.0.0:
dependencies:
postcss "^7.0.2"
-supports-color@6.1.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@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -11434,6 +11394,13 @@ 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"
@@ -11479,6 +11446,16 @@ table@^5.2.3:
slice-ansi "^2.1.0"
string-width "^3.0.0"
+table@^6.0.4:
+ version "6.0.7"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34"
+ integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==
+ dependencies:
+ ajv "^7.0.2"
+ lodash "^4.17.20"
+ slice-ansi "^4.0.0"
+ string-width "^4.2.0"
+
taffydb@2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268"
@@ -11503,6 +11480,18 @@ tar@^2.0.0:
fstream "^1.0.12"
inherits "2"
+tar@^6.0.2:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
+ integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
+ dependencies:
+ chownr "^2.0.0"
+ fs-minipass "^2.0.0"
+ minipass "^3.0.0"
+ minizlib "^2.1.1"
+ mkdirp "^1.0.3"
+ yallist "^4.0.0"
+
term-size@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753"
@@ -11592,11 +11581,6 @@ through2@^2.0.0:
readable-stream "~2.3.6"
xtend "~4.0.1"
-through@^2.3.6:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
-
thunky@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
@@ -11675,7 +11659,7 @@ tiptap@^1.8.0:
tiptap-commands "^1.4.0"
tiptap-utils "^1.1.1"
-tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
+tmp@0.0.33, tmp@0.0.x:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
@@ -11851,6 +11835,16 @@ ts-jest@26.x:
semver "7.x"
yargs-parser "20.x"
+tsconfig-paths@^3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
+ integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.1"
+ minimist "^1.2.0"
+ strip-bom "^3.0.0"
+
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.13.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
@@ -11880,6 +11874,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -11892,11 +11893,6 @@ type-detect@4.0.8:
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-type-fest@^0.5.2:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2"
- integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==
-
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
@@ -11927,10 +11923,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-"typescript@2 - 3":
- version "3.9.7"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
- integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
+"typescript@2 - 4":
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72"
+ integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"
@@ -12163,12 +12159,12 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"
-url-parse@^1.4.3:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8"
- integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==
+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.0.0"
+ querystringify "^2.1.1"
requires-port "^1.0.0"
url-search-params-polyfill@^5.0.0:
@@ -12239,7 +12235,7 @@ uuid@8.1.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
-uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3:
+uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
@@ -12249,10 +12245,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.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
- integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
+v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1:
+ 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-to-istanbul@^5.0.1:
version "5.0.1"
@@ -12403,10 +12399,10 @@ vue-apollo@^3.0.3:
serialize-javascript "^2.1.0"
throttle-debounce "^2.1.0"
-vue-eslint-parser@^7.0.0, vue-eslint-parser@^7.3.0:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.3.0.tgz#894085839d99d81296fa081d19643733f23d7559"
- integrity sha512-n5PJKZbyspD0+8LnaZgpEvNCrjQx1DyDHw8JdWwoxhhC+yRip4TAvSDpXGf9SWX6b0umeB5aR61gwUo6NVvFxw==
+vue-eslint-parser@^7.0.0, vue-eslint-parser@^7.4.1:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.4.1.tgz#e4adcf7876a7379758d9056a72235af18a587f92"
+ integrity sha512-AFvhdxpFvliYq1xt/biNBslTHE/zbEvSnr1qfHA/KxRIpErmEDrQZlQnvEexednRHmLfDNOMuDYwZL5xkLzIXQ==
dependencies:
debug "^4.1.1"
eslint-scope "^5.0.0"
@@ -12466,7 +12462,7 @@ vue-style-loader@^4.1.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
-vue-template-compiler@^2.5.20, vue-template-compiler@^2.6.12:
+vue-template-compiler@^2.6.12:
version "2.6.12"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz#947ed7196744c8a5285ebe1233fe960437fcc57e"
integrity sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==
@@ -12527,23 +12523,23 @@ walker@^1.0.7, walker@~1.0.5:
dependencies:
makeerror "1.0.x"
-watchpack-chokidar2@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0"
- integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==
+watchpack-chokidar2@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957"
+ integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==
dependencies:
chokidar "^2.1.8"
-watchpack@^1.6.0:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa"
- integrity sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==
+watchpack@^1.7.4:
+ version "1.7.5"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453"
+ integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==
dependencies:
graceful-fs "^4.1.2"
neo-async "^2.5.0"
optionalDependencies:
- chokidar "^3.4.0"
- watchpack-chokidar2 "^2.0.0"
+ chokidar "^3.4.1"
+ watchpack-chokidar2 "^2.0.1"
wbuf@^1.1.0, wbuf@^1.7.3:
version "1.7.3"
@@ -12567,13 +12563,13 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
-webpack-bundle-analyzer@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz#39b3a8f829ca044682bc6f9e011c95deb554aefd"
- integrity sha512-orUfvVYEfBMDXgEKAKVvab5iQ2wXneIEorGNsyuOyVYpjYrI7CUOhhXNDd3huMwQ3vNNWWlGP+hzflMFYNzi2g==
+webpack-bundle-analyzer@^3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c"
+ integrity sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==
dependencies:
- acorn "^6.0.7"
- acorn-walk "^6.1.1"
+ acorn "^7.1.1"
+ acorn-walk "^7.1.1"
bfj "^6.1.1"
chalk "^2.4.1"
commander "^2.18.0"
@@ -12581,27 +12577,27 @@ webpack-bundle-analyzer@^3.6.0:
express "^4.16.3"
filesize "^3.6.1"
gzip-size "^5.0.0"
- lodash "^4.17.15"
+ lodash "^4.17.19"
mkdirp "^0.5.1"
opener "^1.5.1"
ws "^6.0.0"
-webpack-cli@^3.3.11:
- version "3.3.11"
- resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631"
- integrity sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==
- dependencies:
- chalk "2.4.2"
- cross-spawn "6.0.5"
- enhanced-resolve "4.1.0"
- findup-sync "3.0.0"
- global-modules "2.0.0"
- import-local "2.0.0"
- interpret "1.2.0"
- loader-utils "1.2.3"
- supports-color "6.1.0"
- v8-compile-cache "2.0.3"
- yargs "13.2.4"
+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-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2:
version "3.7.2"
@@ -12614,10 +12610,10 @@ webpack-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2:
range-parser "^1.2.1"
webpack-log "^2.0.0"
-webpack-dev-server@^3.10.3:
- version "3.10.3"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0"
- integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ==
+webpack-dev-server@^3.11.2:
+ version "3.11.2"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708"
+ integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==
dependencies:
ansi-html "0.0.7"
bonjour "^3.5.0"
@@ -12627,31 +12623,31 @@ webpack-dev-server@^3.10.3:
debug "^4.1.1"
del "^4.1.1"
express "^4.17.1"
- html-entities "^1.2.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.6"
+ loglevel "^1.6.8"
opn "^5.5.0"
p-retry "^3.0.1"
- portfinder "^1.0.25"
+ portfinder "^1.0.26"
schema-utils "^1.0.0"
- selfsigned "^1.10.7"
+ selfsigned "^1.10.8"
semver "^6.3.0"
serve-index "^1.9.1"
- sockjs "0.3.19"
- sockjs-client "1.4.0"
- spdy "^4.0.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 "12.0.5"
+ yargs "^13.3.2"
webpack-log@^2.0.0:
version "2.0.0"
@@ -12661,7 +12657,7 @@ webpack-log@^2.0.0:
ansi-colors "^3.0.0"
uuid "^3.3.2"
-webpack-sources@^1.0.1, webpack-sources@^1.4.0, webpack-sources@^1.4.1:
+webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
@@ -12674,40 +12670,42 @@ webpack-stats-plugin@^0.3.1:
resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.3.1.tgz#1103c39a305a4e6ba15d5078db84bc0b35447417"
integrity sha512-pxqzFE055NlNTlNyfDG3xlB2QwT1EWdm/CF5dCJI/e+rRHVxrWhWg1rf1lfsWhI1/EePv8gi/A36YxO/+u0FgQ==
-webpack@^4.42.0:
- version "4.42.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.0.tgz#b901635dd6179391d90740a63c93f76f39883eb8"
- integrity sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==
+webpack@^4.46.0:
+ version "4.46.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
+ integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
dependencies:
- "@webassemblyjs/ast" "1.8.5"
- "@webassemblyjs/helper-module-context" "1.8.5"
- "@webassemblyjs/wasm-edit" "1.8.5"
- "@webassemblyjs/wasm-parser" "1.8.5"
- acorn "^6.2.1"
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-module-context" "1.9.0"
+ "@webassemblyjs/wasm-edit" "1.9.0"
+ "@webassemblyjs/wasm-parser" "1.9.0"
+ acorn "^6.4.1"
ajv "^6.10.2"
ajv-keywords "^3.4.1"
chrome-trace-event "^1.0.2"
- enhanced-resolve "^4.1.0"
+ enhanced-resolve "^4.5.0"
eslint-scope "^4.0.3"
json-parse-better-errors "^1.0.2"
loader-runner "^2.4.0"
loader-utils "^1.2.3"
memory-fs "^0.4.1"
micromatch "^3.1.10"
- mkdirp "^0.5.1"
+ mkdirp "^0.5.3"
neo-async "^2.6.1"
node-libs-browser "^2.2.1"
schema-utils "^1.0.0"
tapable "^1.1.3"
terser-webpack-plugin "^1.4.3"
- watchpack "^1.6.0"
+ watchpack "^1.7.4"
webpack-sources "^1.4.1"
-websocket-driver@>=0.5.1:
- version "0.6.5"
- resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36"
- integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=
+websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
+ integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
dependencies:
+ http-parser-js ">=0.5.1"
+ safe-buffer ">=5.1.0"
websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1:
@@ -12769,7 +12767,7 @@ widest-line@^3.1.0:
dependencies:
string-width "^4.0.0"
-word-wrap@~1.2.3:
+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"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
@@ -12794,14 +12792,6 @@ worker-loader@^2.0.0:
loader-utils "^1.0.0"
schema-utils "^0.4.0"
-wrap-ansi@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
- integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
- dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
-
wrap-ansi@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
@@ -12934,7 +12924,7 @@ xterm@3.14.5:
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.14.5.tgz#c9d14e48be6873aa46fb429f22f2165557fd2dea"
integrity sha512-DVmQ8jlEtL+WbBKUZuMxHMBgK/yeIZwkXB81bH+MGaKKnJGYwA+770hzhXPfwEIokK9On9YIFPRleVp/5G7z9g==
-"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
+y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
@@ -12988,15 +12978,7 @@ yargs-parser@^10.0.0:
dependencies:
camelcase "^4.1.0"
-yargs-parser@^11.1.1:
- version "11.1.1"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
- integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
- dependencies:
- camelcase "^5.0.0"
- decamelize "^1.2.0"
-
-yargs-parser@^13.1.0, yargs-parser@^13.1.2:
+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==
@@ -13012,41 +12994,6 @@ yargs-parser@^18.1.2:
camelcase "^5.0.0"
decamelize "^1.2.0"
-yargs@12.0.5:
- version "12.0.5"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
- integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
- dependencies:
- cliui "^4.0.0"
- decamelize "^1.2.0"
- find-up "^3.0.0"
- get-caller-file "^1.0.1"
- os-locale "^3.0.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1 || ^4.0.0"
- yargs-parser "^11.1.1"
-
-yargs@13.2.4:
- version "13.2.4"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
- integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==
- dependencies:
- cliui "^5.0.0"
- find-up "^3.0.0"
- get-caller-file "^2.0.1"
- os-locale "^3.1.0"
- 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.0"
-
yargs@^13.3.2:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
@@ -13114,7 +13061,7 @@ zen-observable@^0.8.0:
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.11.tgz#d3415885eeeb42ee5abb9821c95bb518fcd6d199"
integrity sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==
-zrender@4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/zrender/-/zrender-4.2.0.tgz#d001302e155f28de1f9fc7fcd5c254bad28471cf"
- integrity sha512-YJ9hxt5uFincYYU3KK31+Ce+B6PJmYYK0Q9fQ6jOUAoC/VHbe4kCKAPkxKeT7jGTxrK5wYu18R0TLGqj2zbEOA==
+zrender@4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/zrender/-/zrender-4.3.2.tgz#ec7432f9415c82c73584b6b7b8c47e1b016209c6"
+ integrity sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g==